- 107
- Posts
- 4
- Years
- Seen Apr 27, 2023
How do I increase the AI of a Wild Pokemon? It would be nice to have smarter savages.
def pbChooseMoves(idxBattler)
user = @battle.battlers[idxBattler]
wildBattler = (@battle.wildBattle? && @battle.opposes?(idxBattler) && @battle.pbPlayer.badge_count<2 && user.level<25)
skill = 0
owner=(@battle.pbGetOwnerFromBattlerIndex(user.index)) rescue nil
if owner
skill = owner.skill_level || 0
else
catch_rate = user.pokemon.species_data.catch_rate
skill = 255-catch_rate
end
# Get scores and targets for each move
# NOTE: A move is only added to the choices array if it has a non-zero
# score.
choices = []
user.eachMoveWithIndex do |_m,i|
next if [email protected]?(idxBattler,i,false)
if wildBattler
pbRegisterMoveWild(user,i,choices)
else
pbRegisterMoveTrainer(user,i,choices,skill)
end
end
# Figure out useful information about the choices
totalScore = 0
maxScore = 0
choices.each do |c|
totalScore += c[1]
maxScore = c[1] if maxScore<c[1]
end
# Log the available choices
if $INTERNAL
logMsg = "[AI] Move choices for #{user.pbThis(true)} (#{user.index}): "
choices.each_with_index do |c,i|
logMsg += "#{user.moves[c[0]].name}=#{c[1]}"
logMsg += " (target #{c[2]})" if c[2]>=0
logMsg += ", " if i<choices.length-1
end
PBDebug.log(logMsg)
end
# Find any preferred moves and just choose from them
if !wildBattler && skill>=PBTrainerAI.highSkill && maxScore>100
stDev = pbStdDev(choices)
if stDev>=40 && pbAIRandom(100)<90
preferredMoves = []
choices.each do |c|
next if c[1]<200 && c[1]<maxScore*0.8
preferredMoves.push(c)
preferredMoves.push(c) if c[1]==maxScore # Doubly prefer the best move
end
if preferredMoves.length>0
m = preferredMoves[pbAIRandom(preferredMoves.length)]
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) prefers #{user.moves[m[0]].name}")
@battle.pbRegisterMove(idxBattler,m[0],false)
@battle.pbRegisterTarget(idxBattler,m[2]) if m[2]>=0
return
end
end
end
# Decide whether all choices are bad, and if so, try switching instead
if !wildBattler && skill>=PBTrainerAI.highSkill
badMoves = false
if (maxScore<=20 && user.turnCount>2) ||
(maxScore<=40 && user.turnCount>5)
badMoves = true if pbAIRandom(100)<80
end
if !badMoves && totalScore<100 && user.turnCount>1
badMoves = true
choices.each do |c|
next if !user.moves[c[0]].damagingMove?
badMoves = false
break
end
badMoves = false if badMoves && pbAIRandom(100)<10
end
if badMoves && pbEnemyShouldWithdrawEx?(idxBattler,true)
if $INTERNAL
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will switch due to terrible moves")
end
return
end
end
# If there are no calculated choices, pick one at random
if choices.length==0
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) doesn't want to use any moves; picking one at random")
user.eachMoveWithIndex do |_m,i|
next if [email protected]?(idxBattler,i,false)
choices.push([i,100,-1]) # Move index, score, target
end
if choices.length==0 # No moves are physically possible to use; use Struggle
@battle.pbAutoChooseMove(user.index)
end
end
# Randomly choose a move from the choices and register it
randNum = pbAIRandom(totalScore)
choices.each do |c|
randNum -= c[1]
next if randNum>=0
@battle.pbRegisterMove(idxBattler,c[0],false)
@battle.pbRegisterTarget(idxBattler,c[2]) if c[2]>=0
break
end
# Log the result
if @battle.choices[idxBattler][2]
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will use #{@battle.choices[idxBattler][2].name}")
end
end
What a coincidence, I actually did this in v17 and v18 a couple of weeks ago.
the v18 version is very similar to the code the v19 version would have, so I just changed the respective calls to match.
didn't test it, but the other versions I mentioned were and this is just variable name changes
You do want to change how I calculate skill though, as it bases it off inverse catch rate, which can range from 0 to 255, while trainer AI levels only check between 1 and 100 (anything higher acts like champion AI).
You might also want to change how a "wild battler" (wild mon that will use the ai) is defined, as the way I have here is less than 2 badges and the mon is less than level 25
Spoiler:Code:def pbChooseMoves(idxBattler) user = @battle.battlers[idxBattler] wildBattler = (@battle.wildBattle? && @battle.opposes?(idxBattler) && @battle.pbPlayer.badge_count<2 && user.level<25) skill = 0 owner=(@battle.pbGetOwnerFromBattlerIndex(user.index)) rescue nil if owner skill = owner.skill_level || 0 else catch_rate = user.pokemon.species_data.catch_rate skill = 255-catch_rate end # Get scores and targets for each move # NOTE: A move is only added to the choices array if it has a non-zero # score. choices = [] user.eachMoveWithIndex do |_m,i| next if [email protected]?(idxBattler,i,false) if wildBattler pbRegisterMoveWild(user,i,choices) else pbRegisterMoveTrainer(user,i,choices,skill) end end # Figure out useful information about the choices totalScore = 0 maxScore = 0 choices.each do |c| totalScore += c[1] maxScore = c[1] if maxScore<c[1] end # Log the available choices if $INTERNAL logMsg = "[AI] Move choices for #{user.pbThis(true)} (#{user.index}): " choices.each_with_index do |c,i| logMsg += "#{user.moves[c[0]].name}=#{c[1]}" logMsg += " (target #{c[2]})" if c[2]>=0 logMsg += ", " if i<choices.length-1 end PBDebug.log(logMsg) end # Find any preferred moves and just choose from them if !wildBattler && skill>=PBTrainerAI.highSkill && maxScore>100 stDev = pbStdDev(choices) if stDev>=40 && pbAIRandom(100)<90 preferredMoves = [] choices.each do |c| next if c[1]<200 && c[1]<maxScore*0.8 preferredMoves.push(c) preferredMoves.push(c) if c[1]==maxScore # Doubly prefer the best move end if preferredMoves.length>0 m = preferredMoves[pbAIRandom(preferredMoves.length)] PBDebug.log("[AI] #{user.pbThis} (#{user.index}) prefers #{user.moves[m[0]].name}") @battle.pbRegisterMove(idxBattler,m[0],false) @battle.pbRegisterTarget(idxBattler,m[2]) if m[2]>=0 return end end end # Decide whether all choices are bad, and if so, try switching instead if !wildBattler && skill>=PBTrainerAI.highSkill badMoves = false if (maxScore<=20 && user.turnCount>2) || (maxScore<=40 && user.turnCount>5) badMoves = true if pbAIRandom(100)<80 end if !badMoves && totalScore<100 && user.turnCount>1 badMoves = true choices.each do |c| next if !user.moves[c[0]].damagingMove? badMoves = false break end badMoves = false if badMoves && pbAIRandom(100)<10 end if badMoves && pbEnemyShouldWithdrawEx?(idxBattler,true) if $INTERNAL PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will switch due to terrible moves") end return end end # If there are no calculated choices, pick one at random if choices.length==0 PBDebug.log("[AI] #{user.pbThis} (#{user.index}) doesn't want to use any moves; picking one at random") user.eachMoveWithIndex do |_m,i| next if [email protected]?(idxBattler,i,false) choices.push([i,100,-1]) # Move index, score, target end if choices.length==0 # No moves are physically possible to use; use Struggle @battle.pbAutoChooseMove(user.index) end end # Randomly choose a move from the choices and register it randNum = pbAIRandom(totalScore) choices.each do |c| randNum -= c[1] next if randNum>=0 @battle.pbRegisterMove(idxBattler,c[0],false) @battle.pbRegisterTarget(idxBattler,c[2]) if c[2]>=0 break end # Log the result if @battle.choices[idxBattler][2] PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will use #{@battle.choices[idxBattler][2].name}") end end
What a coincidence, I actually did this in v17 and v18 a couple of weeks ago.
the v18 version is very similar to the code the v19 version would have, so I just changed the respective calls to match.
didn't test it, but the other versions I mentioned were and this is just variable name changes
You do want to change how I calculate skill though, as it bases it off inverse catch rate, which can range from 0 to 255, while trainer AI levels only check between 1 and 100 (anything higher acts like champion AI).
You might also want to change how a "wild battler" (wild mon that will use the ai) is defined, as the way I have here is less than 2 badges and the mon is less than level 25
Spoiler:Code:def pbChooseMoves(idxBattler) user = @battle.battlers[idxBattler] wildBattler = (@battle.wildBattle? && @battle.opposes?(idxBattler) && @battle.pbPlayer.badge_count<2 && user.level<25) skill = 0 owner=(@battle.pbGetOwnerFromBattlerIndex(user.index)) rescue nil if owner skill = owner.skill_level || 0 else catch_rate = user.pokemon.species_data.catch_rate skill = 255-catch_rate end # Get scores and targets for each move # NOTE: A move is only added to the choices array if it has a non-zero # score. choices = [] user.eachMoveWithIndex do |_m,i| next if [email protected]?(idxBattler,i,false) if wildBattler pbRegisterMoveWild(user,i,choices) else pbRegisterMoveTrainer(user,i,choices,skill) end end # Figure out useful information about the choices totalScore = 0 maxScore = 0 choices.each do |c| totalScore += c[1] maxScore = c[1] if maxScore<c[1] end # Log the available choices if $INTERNAL logMsg = "[AI] Move choices for #{user.pbThis(true)} (#{user.index}): " choices.each_with_index do |c,i| logMsg += "#{user.moves[c[0]].name}=#{c[1]}" logMsg += " (target #{c[2]})" if c[2]>=0 logMsg += ", " if i<choices.length-1 end PBDebug.log(logMsg) end # Find any preferred moves and just choose from them if !wildBattler && skill>=PBTrainerAI.highSkill && maxScore>100 stDev = pbStdDev(choices) if stDev>=40 && pbAIRandom(100)<90 preferredMoves = [] choices.each do |c| next if c[1]<200 && c[1]<maxScore*0.8 preferredMoves.push(c) preferredMoves.push(c) if c[1]==maxScore # Doubly prefer the best move end if preferredMoves.length>0 m = preferredMoves[pbAIRandom(preferredMoves.length)] PBDebug.log("[AI] #{user.pbThis} (#{user.index}) prefers #{user.moves[m[0]].name}") @battle.pbRegisterMove(idxBattler,m[0],false) @battle.pbRegisterTarget(idxBattler,m[2]) if m[2]>=0 return end end end # Decide whether all choices are bad, and if so, try switching instead if !wildBattler && skill>=PBTrainerAI.highSkill badMoves = false if (maxScore<=20 && user.turnCount>2) || (maxScore<=40 && user.turnCount>5) badMoves = true if pbAIRandom(100)<80 end if !badMoves && totalScore<100 && user.turnCount>1 badMoves = true choices.each do |c| next if !user.moves[c[0]].damagingMove? badMoves = false break end badMoves = false if badMoves && pbAIRandom(100)<10 end if badMoves && pbEnemyShouldWithdrawEx?(idxBattler,true) if $INTERNAL PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will switch due to terrible moves") end return end end # If there are no calculated choices, pick one at random if choices.length==0 PBDebug.log("[AI] #{user.pbThis} (#{user.index}) doesn't want to use any moves; picking one at random") user.eachMoveWithIndex do |_m,i| next if [email protected]?(idxBattler,i,false) choices.push([i,100,-1]) # Move index, score, target end if choices.length==0 # No moves are physically possible to use; use Struggle @battle.pbAutoChooseMove(user.index) end end # Randomly choose a move from the choices and register it randNum = pbAIRandom(totalScore) choices.each do |c| randNum -= c[1] next if randNum>=0 @battle.pbRegisterMove(idxBattler,c[0],false) @battle.pbRegisterTarget(idxBattler,c[2]) if c[2]>=0 break end # Log the result if @battle.choices[idxBattler][2] PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will use #{@battle.choices[idxBattler][2].name}") end end
What a coincidence, I actually did this in v17 and v18 a couple of weeks ago.
the v18 version is very similar to the code the v19 version would have, so I just changed the respective calls to match.
didn't test it, but the other versions I mentioned were and this is just variable name changes
You do want to change how I calculate skill though, as it bases it off inverse catch rate, which can range from 0 to 255, while trainer AI levels only check between 1 and 100 (anything higher acts like champion AI).
You might also want to change how a "wild battler" (wild mon that will use the ai) is defined, as the way I have here is less than 2 badges and the mon is less than level 25
Spoiler:Code:def pbChooseMoves(idxBattler) user = @battle.battlers[idxBattler] wildBattler = (@battle.wildBattle? && @battle.opposes?(idxBattler) && @battle.pbPlayer.badge_count<2 && user.level<25) skill = 0 owner=(@battle.pbGetOwnerFromBattlerIndex(user.index)) rescue nil if owner skill = owner.skill_level || 0 else catch_rate = user.pokemon.species_data.catch_rate skill = 255-catch_rate end # Get scores and targets for each move # NOTE: A move is only added to the choices array if it has a non-zero # score. choices = [] user.eachMoveWithIndex do |_m,i| next if [email protected]?(idxBattler,i,false) if wildBattler pbRegisterMoveWild(user,i,choices) else pbRegisterMoveTrainer(user,i,choices,skill) end end # Figure out useful information about the choices totalScore = 0 maxScore = 0 choices.each do |c| totalScore += c[1] maxScore = c[1] if maxScore<c[1] end # Log the available choices if $INTERNAL logMsg = "[AI] Move choices for #{user.pbThis(true)} (#{user.index}): " choices.each_with_index do |c,i| logMsg += "#{user.moves[c[0]].name}=#{c[1]}" logMsg += " (target #{c[2]})" if c[2]>=0 logMsg += ", " if i<choices.length-1 end PBDebug.log(logMsg) end # Find any preferred moves and just choose from them if !wildBattler && skill>=PBTrainerAI.highSkill && maxScore>100 stDev = pbStdDev(choices) if stDev>=40 && pbAIRandom(100)<90 preferredMoves = [] choices.each do |c| next if c[1]<200 && c[1]<maxScore*0.8 preferredMoves.push(c) preferredMoves.push(c) if c[1]==maxScore # Doubly prefer the best move end if preferredMoves.length>0 m = preferredMoves[pbAIRandom(preferredMoves.length)] PBDebug.log("[AI] #{user.pbThis} (#{user.index}) prefers #{user.moves[m[0]].name}") @battle.pbRegisterMove(idxBattler,m[0],false) @battle.pbRegisterTarget(idxBattler,m[2]) if m[2]>=0 return end end end # Decide whether all choices are bad, and if so, try switching instead if !wildBattler && skill>=PBTrainerAI.highSkill badMoves = false if (maxScore<=20 && user.turnCount>2) || (maxScore<=40 && user.turnCount>5) badMoves = true if pbAIRandom(100)<80 end if !badMoves && totalScore<100 && user.turnCount>1 badMoves = true choices.each do |c| next if !user.moves[c[0]].damagingMove? badMoves = false break end badMoves = false if badMoves && pbAIRandom(100)<10 end if badMoves && pbEnemyShouldWithdrawEx?(idxBattler,true) if $INTERNAL PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will switch due to terrible moves") end return end end # If there are no calculated choices, pick one at random if choices.length==0 PBDebug.log("[AI] #{user.pbThis} (#{user.index}) doesn't want to use any moves; picking one at random") user.eachMoveWithIndex do |_m,i| next if [email protected]?(idxBattler,i,false) choices.push([i,100,-1]) # Move index, score, target end if choices.length==0 # No moves are physically possible to use; use Struggle @battle.pbAutoChooseMove(user.index) end end # Randomly choose a move from the choices and register it randNum = pbAIRandom(totalScore) choices.each do |c| randNum -= c[1] next if randNum>=0 @battle.pbRegisterMove(idxBattler,c[0],false) @battle.pbRegisterTarget(idxBattler,c[2]) if c[2]>=0 break end # Log the result if @battle.choices[idxBattler][2] PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will use #{@battle.choices[idxBattler][2].name}") end end
def pbChooseMoves(idxBattler)
user = @battle.battlers[idxBattler]
wildBattler = (@battle.wildBattle? && @battle.opposes?(idxBattler) && @battle.pbPlayer.numbadges<2 && user.level<25)
skill = 0
owner=(@battle.pbGetOwnerFromBattlerIndex(user.index)) rescue nil
if owner
skill = owner.skill || 0
else
rareness = pbGetSpeciesData(user.species,user.form,SpeciesRareness)
skill = 255-rareness
end
# Get scores and targets for each move
# NOTE: A move is only added to the choices array if it has a non-zero
# score.
choices = []
user.eachMoveWithIndex do |_m,i|
next if [email protected]?(idxBattler,i,false)
if wildBattler
pbRegisterMoveWild(user,i,choices)
else
pbRegisterMoveTrainer(user,i,choices,skill)
end
end
# Figure out useful information about the choices
totalScore = 0
maxScore = 0
choices.each do |c|
totalScore += c[1]
maxScore = c[1] if maxScore<c[1]
end
# Log the available choices
if $INTERNAL
logMsg = "[AI] Move choices for #{user.pbThis(true)} (#{user.index}): "
choices.each_with_index do |c,i|
logMsg += "#{user.moves[c[0]].name}=#{c[1]}"
logMsg += " (target #{c[2]})" if c[2]>=0
logMsg += ", " if i<choices.length-1
end
PBDebug.log(logMsg)
end
# Find any preferred moves and just choose from them
if !wildBattler && skill>=PBTrainerAI.highSkill && maxScore>100
stDev = pbStdDev(choices)
if stDev>=40 && pbAIRandom(100)<90
preferredMoves = []
choices.each do |c|
next if c[1]<200 && c[1]<maxScore*0.8
preferredMoves.push(c)
preferredMoves.push(c) if c[1]==maxScore # Doubly prefer the best move
end
if preferredMoves.length>0
m = preferredMoves[pbAIRandom(preferredMoves.length)]
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) prefers #{user.moves[m[0]].name}")
@battle.pbRegisterMove(idxBattler,m[0],false)
@battle.pbRegisterTarget(idxBattler,m[2]) if m[2]>=0
return
end
end
end
# Decide whether all choices are bad, and if so, try switching instead
if !wildBattler && skill>=PBTrainerAI.highSkill
badMoves = false
if (maxScore<=20 && user.turnCount>2) ||
(maxScore<=40 && user.turnCount>5)
badMoves = true if pbAIRandom(100)<80
end
if !badMoves && totalScore<100 && user.turnCount>1
badMoves = true
choices.each do |c|
next if !user.moves[c[0]].damagingMove?
badMoves = false
break
end
badMoves = false if badMoves && pbAIRandom(100)<10
end
if badMoves && pbEnemyShouldWithdrawEx?(idxBattler,true)
if $INTERNAL
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will switch due to terrible moves")
end
return
end
end
# If there are no calculated choices, pick one at random
if choices.length==0
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) doesn't want to use any moves; picking one at random")
user.eachMoveWithIndex do |_m,i|
next if [email protected]?(idxBattler,i,false)
choices.push([i,100,-1]) # Move index, score, target
end
if choices.length==0 # No moves are physically possible to use; use Struggle
@battle.pbAutoChooseMove(user.index)
end
end
# Randomly choose a move from the choices and register it
randNum = pbAIRandom(totalScore)
choices.each do |c|
randNum -= c[1]
next if randNum>=0
@battle.pbRegisterMove(idxBattler,c[0],false)
@battle.pbRegisterTarget(idxBattler,c[2]) if c[2]>=0
break
end
# Log the result
if @battle.choices[idxBattler][2]
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will use #{@battle.choices[user.index][2].name}")
end
end
Oh man you were on v18 the whole time!
well, at least you have it working, sorry for assuming.
edit: sent to early
Spoiler:Code:def pbChooseMoves(idxBattler) user = @battle.battlers[idxBattler] wildBattler = (@battle.wildBattle? && @battle.opposes?(idxBattler) && @battle.pbPlayer.numbadges<2 && user.level<25) skill = 0 owner=(@battle.pbGetOwnerFromBattlerIndex(user.index)) rescue nil if owner skill = owner.skill || 0 else rareness = pbGetSpeciesData(user.species,user.form,SpeciesRareness) skill = 255-rareness end # Get scores and targets for each move # NOTE: A move is only added to the choices array if it has a non-zero # score. choices = [] user.eachMoveWithIndex do |_m,i| next if [email protected]?(idxBattler,i,false) if wildBattler pbRegisterMoveWild(user,i,choices) else pbRegisterMoveTrainer(user,i,choices,skill) end end # Figure out useful information about the choices totalScore = 0 maxScore = 0 choices.each do |c| totalScore += c[1] maxScore = c[1] if maxScore<c[1] end # Log the available choices if $INTERNAL logMsg = "[AI] Move choices for #{user.pbThis(true)} (#{user.index}): " choices.each_with_index do |c,i| logMsg += "#{user.moves[c[0]].name}=#{c[1]}" logMsg += " (target #{c[2]})" if c[2]>=0 logMsg += ", " if i<choices.length-1 end PBDebug.log(logMsg) end # Find any preferred moves and just choose from them if !wildBattler && skill>=PBTrainerAI.highSkill && maxScore>100 stDev = pbStdDev(choices) if stDev>=40 && pbAIRandom(100)<90 preferredMoves = [] choices.each do |c| next if c[1]<200 && c[1]<maxScore*0.8 preferredMoves.push(c) preferredMoves.push(c) if c[1]==maxScore # Doubly prefer the best move end if preferredMoves.length>0 m = preferredMoves[pbAIRandom(preferredMoves.length)] PBDebug.log("[AI] #{user.pbThis} (#{user.index}) prefers #{user.moves[m[0]].name}") @battle.pbRegisterMove(idxBattler,m[0],false) @battle.pbRegisterTarget(idxBattler,m[2]) if m[2]>=0 return end end end # Decide whether all choices are bad, and if so, try switching instead if !wildBattler && skill>=PBTrainerAI.highSkill badMoves = false if (maxScore<=20 && user.turnCount>2) || (maxScore<=40 && user.turnCount>5) badMoves = true if pbAIRandom(100)<80 end if !badMoves && totalScore<100 && user.turnCount>1 badMoves = true choices.each do |c| next if !user.moves[c[0]].damagingMove? badMoves = false break end badMoves = false if badMoves && pbAIRandom(100)<10 end if badMoves && pbEnemyShouldWithdrawEx?(idxBattler,true) if $INTERNAL PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will switch due to terrible moves") end return end end # If there are no calculated choices, pick one at random if choices.length==0 PBDebug.log("[AI] #{user.pbThis} (#{user.index}) doesn't want to use any moves; picking one at random") user.eachMoveWithIndex do |_m,i| next if [email protected]?(idxBattler,i,false) choices.push([i,100,-1]) # Move index, score, target end if choices.length==0 # No moves are physically possible to use; use Struggle @battle.pbAutoChooseMove(user.index) end end # Randomly choose a move from the choices and register it randNum = pbAIRandom(totalScore) choices.each do |c| randNum -= c[1] next if randNum>=0 @battle.pbRegisterMove(idxBattler,c[0],false) @battle.pbRegisterTarget(idxBattler,c[2]) if c[2]>=0 break end # Log the result if @battle.choices[idxBattler][2] PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will use #{@battle.choices[user.index][2].name}") end end
What a coincidence, I actually did this in v17 and v18 a couple of weeks ago.
the v18 version is very similar to the code the v19 version would have, so I just changed the respective calls to match.
didn't test it, but the other versions I mentioned were and this is just variable name changes
You do want to change how I calculate skill though, as it bases it off inverse catch rate, which can range from 0 to 255, while trainer AI levels only check between 1 and 100 (anything higher acts like champion AI).
You might also want to change how a "wild battler" (wild mon that will use the ai) is defined, as the way I have here is less than 2 badges and the mon is less than level 25
Spoiler:Code:def pbChooseMoves(idxBattler) user = @battle.battlers[idxBattler] wildBattler = (@battle.wildBattle? && @battle.opposes?(idxBattler) && @battle.pbPlayer.badge_count<2 && user.level<25) skill = 0 owner=(@battle.pbGetOwnerFromBattlerIndex(user.index)) rescue nil if owner skill = owner.skill_level || 0 else catch_rate = user.pokemon.species_data.catch_rate skill = 255-catch_rate end # Get scores and targets for each move # NOTE: A move is only added to the choices array if it has a non-zero # score. choices = [] user.eachMoveWithIndex do |_m,i| next if [email protected]?(idxBattler,i,false) if wildBattler pbRegisterMoveWild(user,i,choices) else pbRegisterMoveTrainer(user,i,choices,skill) end end # Figure out useful information about the choices totalScore = 0 maxScore = 0 choices.each do |c| totalScore += c[1] maxScore = c[1] if maxScore<c[1] end # Log the available choices if $INTERNAL logMsg = "[AI] Move choices for #{user.pbThis(true)} (#{user.index}): " choices.each_with_index do |c,i| logMsg += "#{user.moves[c[0]].name}=#{c[1]}" logMsg += " (target #{c[2]})" if c[2]>=0 logMsg += ", " if i<choices.length-1 end PBDebug.log(logMsg) end # Find any preferred moves and just choose from them if !wildBattler && skill>=PBTrainerAI.highSkill && maxScore>100 stDev = pbStdDev(choices) if stDev>=40 && pbAIRandom(100)<90 preferredMoves = [] choices.each do |c| next if c[1]<200 && c[1]<maxScore*0.8 preferredMoves.push(c) preferredMoves.push(c) if c[1]==maxScore # Doubly prefer the best move end if preferredMoves.length>0 m = preferredMoves[pbAIRandom(preferredMoves.length)] PBDebug.log("[AI] #{user.pbThis} (#{user.index}) prefers #{user.moves[m[0]].name}") @battle.pbRegisterMove(idxBattler,m[0],false) @battle.pbRegisterTarget(idxBattler,m[2]) if m[2]>=0 return end end end # Decide whether all choices are bad, and if so, try switching instead if !wildBattler && skill>=PBTrainerAI.highSkill badMoves = false if (maxScore<=20 && user.turnCount>2) || (maxScore<=40 && user.turnCount>5) badMoves = true if pbAIRandom(100)<80 end if !badMoves && totalScore<100 && user.turnCount>1 badMoves = true choices.each do |c| next if !user.moves[c[0]].damagingMove? badMoves = false break end badMoves = false if badMoves && pbAIRandom(100)<10 end if badMoves && pbEnemyShouldWithdrawEx?(idxBattler,true) if $INTERNAL PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will switch due to terrible moves") end return end end # If there are no calculated choices, pick one at random if choices.length==0 PBDebug.log("[AI] #{user.pbThis} (#{user.index}) doesn't want to use any moves; picking one at random") user.eachMoveWithIndex do |_m,i| next if [email protected]?(idxBattler,i,false) choices.push([i,100,-1]) # Move index, score, target end if choices.length==0 # No moves are physically possible to use; use Struggle @battle.pbAutoChooseMove(user.index) end end # Randomly choose a move from the choices and register it randNum = pbAIRandom(totalScore) choices.each do |c| randNum -= c[1] next if randNum>=0 @battle.pbRegisterMove(idxBattler,c[0],false) @battle.pbRegisterTarget(idxBattler,c[2]) if c[2]>=0 break end # Log the result if @battle.choices[idxBattler][2] PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will use #{@battle.choices[idxBattler][2].name}") end end
Can you also post the method of increasing the AI of wild Pokemon for version 17.2?
def pbChooseMoves(index)
attacker=@battlers[index]
scores=[0,0,0,0]
targets=nil
myChoices=[]
totalscore=0
target=-1
skill=0
wildbattle=!@opponent && pbIsOpposing?(index) &&
pbPlayer.numbadges<2 && attacker.level<25
if wildbattle # If wild battle
for i in 0...4
if pbCanChooseMove?(index,i,false)
scores[i]=100
myChoices.push(i)
totalscore+=100
end
end
else
owner=pbGetOwner(attacker.index)
if owner
skill=pbGetOwner(attacker.index).skill || 0
else
dexdata=pbOpenDexData
pbDexDataOffset(dexdata,attacker.pokemon.fSpecies,16)
rareness=dexdata.fgetb # Get rareness from dexdata file
dexdata.close
skill=255-rareness # seems good enough.
end
opponent=attacker.pbOppositeOpposing
if @doublebattle && !opponent.fainted? && !opponent.pbPartner.fainted?
# Choose a target and move. Also care about partner.
otheropp=opponent.pbPartner
scoresAndTargets=[]
targets=[-1,-1,-1,-1]
for i in 0...4
if pbCanChooseMove?(index,i,false)
score1=pbGetMoveScore(attacker.moves[i],attacker,opponent,skill)
score2=pbGetMoveScore(attacker.moves[i],attacker,otheropp,skill)
if (attacker.moves[i].target&0x20)!=0 # Target's user's side
if attacker.pbPartner.fainted? # No partner
score1*=5/3
score2*=5/3
else
# If this move can also target the partner, get the partner's
# score too
s=pbGetMoveScore(attacker.moves[i],attacker,attacker.pbPartner,skill)
if s>=140 # Highly effective
score1*=1/3
score2*=1/3
elsif s>=100 # Very effective
score1*=2/3
score2*=2/3
elsif s>=40 # Less effective
score1*=4/3
score2*=4/3
else # Hardly effective
score1*=5/3
score2*=5/3
end
end
end
myChoices.push(i)
scoresAndTargets.push([i*2,i,score1,opponent.index])
scoresAndTargets.push([i*2+1,i,score2,otheropp.index])
end
end
scoresAndTargets.sort!{|a,b|
if a[2]==b[2] # if scores are equal
a[0]<=>b[0] # sort by index (for stable comparison)
else
b[2]<=>a[2]
end
}
for i in 0...scoresAndTargets.length
idx=scoresAndTargets[i][1]
thisScore=scoresAndTargets[i][2]
if thisScore>0
if scores[idx]==0 || ((scores[idx]==thisScore && pbAIRandom(10)<5) ||
(scores[idx]!=thisScore && pbAIRandom(10)<3))
scores[idx]=thisScore
targets[idx]=scoresAndTargets[i][3]
end
end
end
for i in 0...4
scores[i]=0 if scores[i]<0
totalscore+=scores[i]
end
else
# Choose a move. There is only 1 opposing Pokémon.
if @doublebattle && opponent.fainted?
opponent=opponent.pbPartner
end
for i in 0...4
if pbCanChooseMove?(index,i,false)
scores[i]=pbGetMoveScore(attacker.moves[i],attacker,opponent,skill)
myChoices.push(i)
end
scores[i]=0 if scores[i]<0
totalscore+=scores[i]
end
end
end
maxscore=0
for i in 0...4
maxscore=scores[i] if scores[i] && scores[i]>maxscore
end
# Minmax choices depending on AI
if !wildbattle && skill>=PBTrainerAI.mediumSkill
threshold=(skill>=PBTrainerAI.bestSkill) ? 1.5 : (skill>=PBTrainerAI.highSkill) ? 2 : 3
newscore=(skill>=PBTrainerAI.bestSkill) ? 5 : (skill>=PBTrainerAI.highSkill) ? 10 : 15
for i in 0...scores.length
if scores[i]>newscore && scores[i]*threshold<maxscore
totalscore-=(scores[i]-newscore)
scores[i]=newscore
end
end
maxscore=0
for i in 0...4
maxscore=scores[i] if scores[i] && scores[i]>maxscore
end
end
if $INTERNAL
x="[AI] #{attacker.pbThis}'s moves: "
j=0
for i in 0...4
if attacker.moves[i].id!=0
x+=", " if j>0
x+=PBMoves.getName(attacker.moves[i].id)+"="+scores[i].to_s
j+=1
end
end
PBDebug.log(x)
end
if !wildbattle && maxscore>100
stdev=pbStdDev(scores)
if stdev>=40 && pbAIRandom(10)!=0
# If standard deviation is 40 or more,
# there is a highly preferred move. Choose it.
preferredMoves=[]
for i in 0...4
if attacker.moves[i].id!=0 && (scores[i]>=maxscore*0.8 || scores[i]>=200)
preferredMoves.push(i)
preferredMoves.push(i) if scores[i]==maxscore # Doubly prefer the best move
end
end
if preferredMoves.length>0
i=preferredMoves[pbAIRandom(preferredMoves.length)]
PBDebug.log("[AI] Prefer #{PBMoves.getName(attacker.moves[i].id)}")
pbRegisterMove(index,i,false)
target=targets[i] if targets
if @doublebattle && target>=0
pbRegisterTarget(index,target)
end
return
end
end
end
if !wildbattle && attacker.turncount
badmoves=false
if ((maxscore<=20 && attacker.turncount>2) ||
(maxscore<=30 && attacker.turncount>5)) && pbAIRandom(10)<8
badmoves=true
end
if totalscore<100 && attacker.turncount>1
badmoves=true
movecount=0
for i in 0...4
if attacker.moves[i].id!=0
if scores[i]>0 && attacker.moves[i].basedamage>0
badmoves=false
end
movecount+=1
end
end
badmoves=badmoves && pbAIRandom(10)!=0
end
if badmoves
# Attacker has terrible moves, try switching instead
if pbEnemyShouldWithdrawEx?(index,true)
if $INTERNAL
PBDebug.log("[AI] Switching due to terrible moves")
PBDebug.log([index,@choices[index][0],@choices[index][1],
pbCanChooseNonActive?(index),
@battlers[index].pbNonActivePokemonCount()].inspect)
end
return
end
end
end
if maxscore<=0
# If all scores are 0 or less, choose a move at random
if myChoices.length>0
pbRegisterMove(index,myChoices[pbAIRandom(myChoices.length)],false)
else
pbAutoChooseMove(index)
end
else
randnum=pbAIRandom(totalscore)
cumtotal=0
for i in 0...4
if scores[i]>0
cumtotal+=scores[i]
if randnum<cumtotal
pbRegisterMove(index,i,false)
target=targets[i] if targets
break
end
end
end
end
PBDebug.log("[AI] Will use #{@choices[index][2].name}") if @choices[index][2]
if @doublebattle && target>=0
pbRegisterTarget(index,target)
end
end
Certainly!
Edit: wrong one!
Spoiler:Code:def pbChooseMoves(index) attacker=@battlers[index] scores=[0,0,0,0] targets=nil myChoices=[] totalscore=0 target=-1 skill=0 wildbattle=!@opponent && pbIsOpposing?(index) && pbPlayer.numbadges<2 && attacker.level<25 if wildbattle # If wild battle for i in 0...4 if pbCanChooseMove?(index,i,false) scores[i]=100 myChoices.push(i) totalscore+=100 end end else owner=pbGetOwner(attacker.index) if owner skill=pbGetOwner(attacker.index).skill || 0 else dexdata=pbOpenDexData pbDexDataOffset(dexdata,attacker.pokemon.fSpecies,16) rareness=dexdata.fgetb # Get rareness from dexdata file dexdata.close skill=255-rareness # seems good enough. end opponent=attacker.pbOppositeOpposing if @doublebattle && !opponent.fainted? && !opponent.pbPartner.fainted? # Choose a target and move. Also care about partner. otheropp=opponent.pbPartner scoresAndTargets=[] targets=[-1,-1,-1,-1] for i in 0...4 if pbCanChooseMove?(index,i,false) score1=pbGetMoveScore(attacker.moves[i],attacker,opponent,skill) score2=pbGetMoveScore(attacker.moves[i],attacker,otheropp,skill) if (attacker.moves[i].target&0x20)!=0 # Target's user's side if attacker.pbPartner.fainted? # No partner score1*=5/3 score2*=5/3 else # If this move can also target the partner, get the partner's # score too s=pbGetMoveScore(attacker.moves[i],attacker,attacker.pbPartner,skill) if s>=140 # Highly effective score1*=1/3 score2*=1/3 elsif s>=100 # Very effective score1*=2/3 score2*=2/3 elsif s>=40 # Less effective score1*=4/3 score2*=4/3 else # Hardly effective score1*=5/3 score2*=5/3 end end end myChoices.push(i) scoresAndTargets.push([i*2,i,score1,opponent.index]) scoresAndTargets.push([i*2+1,i,score2,otheropp.index]) end end scoresAndTargets.sort!{|a,b| if a[2]==b[2] # if scores are equal a[0]<=>b[0] # sort by index (for stable comparison) else b[2]<=>a[2] end } for i in 0...scoresAndTargets.length idx=scoresAndTargets[i][1] thisScore=scoresAndTargets[i][2] if thisScore>0 if scores[idx]==0 || ((scores[idx]==thisScore && pbAIRandom(10)<5) || (scores[idx]!=thisScore && pbAIRandom(10)<3)) scores[idx]=thisScore targets[idx]=scoresAndTargets[i][3] end end end for i in 0...4 scores[i]=0 if scores[i]<0 totalscore+=scores[i] end else # Choose a move. There is only 1 opposing Pokémon. if @doublebattle && opponent.fainted? opponent=opponent.pbPartner end for i in 0...4 if pbCanChooseMove?(index,i,false) scores[i]=pbGetMoveScore(attacker.moves[i],attacker,opponent,skill) myChoices.push(i) end scores[i]=0 if scores[i]<0 totalscore+=scores[i] end end end maxscore=0 for i in 0...4 maxscore=scores[i] if scores[i] && scores[i]>maxscore end # Minmax choices depending on AI if !wildbattle && skill>=PBTrainerAI.mediumSkill threshold=(skill>=PBTrainerAI.bestSkill) ? 1.5 : (skill>=PBTrainerAI.highSkill) ? 2 : 3 newscore=(skill>=PBTrainerAI.bestSkill) ? 5 : (skill>=PBTrainerAI.highSkill) ? 10 : 15 for i in 0...scores.length if scores[i]>newscore && scores[i]*threshold<maxscore totalscore-=(scores[i]-newscore) scores[i]=newscore end end maxscore=0 for i in 0...4 maxscore=scores[i] if scores[i] && scores[i]>maxscore end end if $INTERNAL x="[AI] #{attacker.pbThis}'s moves: " j=0 for i in 0...4 if attacker.moves[i].id!=0 x+=", " if j>0 x+=PBMoves.getName(attacker.moves[i].id)+"="+scores[i].to_s j+=1 end end PBDebug.log(x) end if !wildbattle && maxscore>100 stdev=pbStdDev(scores) if stdev>=40 && pbAIRandom(10)!=0 # If standard deviation is 40 or more, # there is a highly preferred move. Choose it. preferredMoves=[] for i in 0...4 if attacker.moves[i].id!=0 && (scores[i]>=maxscore*0.8 || scores[i]>=200) preferredMoves.push(i) preferredMoves.push(i) if scores[i]==maxscore # Doubly prefer the best move end end if preferredMoves.length>0 i=preferredMoves[pbAIRandom(preferredMoves.length)] PBDebug.log("[AI] Prefer #{PBMoves.getName(attacker.moves[i].id)}") pbRegisterMove(index,i,false) target=targets[i] if targets if @doublebattle && target>=0 pbRegisterTarget(index,target) end return end end end if !wildbattle && attacker.turncount badmoves=false if ((maxscore<=20 && attacker.turncount>2) || (maxscore<=30 && attacker.turncount>5)) && pbAIRandom(10)<8 badmoves=true end if totalscore<100 && attacker.turncount>1 badmoves=true movecount=0 for i in 0...4 if attacker.moves[i].id!=0 if scores[i]>0 && attacker.moves[i].basedamage>0 badmoves=false end movecount+=1 end end badmoves=badmoves && pbAIRandom(10)!=0 end if badmoves # Attacker has terrible moves, try switching instead if pbEnemyShouldWithdrawEx?(index,true) if $INTERNAL PBDebug.log("[AI] Switching due to terrible moves") PBDebug.log([index,@choices[index][0],@choices[index][1], pbCanChooseNonActive?(index), @battlers[index].pbNonActivePokemonCount()].inspect) end return end end end if maxscore<=0 # If all scores are 0 or less, choose a move at random if myChoices.length>0 pbRegisterMove(index,myChoices[pbAIRandom(myChoices.length)],false) else pbAutoChooseMove(index) end else randnum=pbAIRandom(totalscore) cumtotal=0 for i in 0...4 if scores[i]>0 cumtotal+=scores[i] if randnum<cumtotal pbRegisterMove(index,i,false) target=targets[i] if targets break end end end end PBDebug.log("[AI] Will use #{@choices[index][2].name}") if @choices[index][2] if @doublebattle && target>=0 pbRegisterTarget(index,target) end end