Split AI move handlers into general ones and ones per target, rearranged some main move-scoring code

This commit is contained in:
Maruno17
2022-10-30 15:25:46 +00:00
parent e12fd08eb1
commit 3408b038cf
16 changed files with 1133 additions and 1040 deletions

View File

@@ -64,10 +64,13 @@ end
# #
#=============================================================================== #===============================================================================
module Battle::AI::Handlers module Battle::AI::Handlers
MoveEffectScore = HandlerHash.new MoveFailureCheck = HandlerHash.new
MoveBasePower = HandlerHash.new MoveFailureAgainstTargetCheck = HandlerHash.new
MoveFailureCheck = HandlerHash.new MoveEffectScore = HandlerHash.new
GeneralMoveScore = HandlerHash.new MoveEffectAgainstTargetScore = HandlerHash.new
MoveBasePower = HandlerHash.new
GeneralMoveScore = HandlerHash.new
GeneralMoveAgainstTargetScore = HandlerHash.new
# Move type - uses main battle code via rough_type # Move type - uses main battle code via rough_type
# Move accuracy - uses main battle code via rough_accuracy # Move accuracy - uses main battle code via rough_accuracy
# Move target # Move target
@@ -79,11 +82,20 @@ module Battle::AI::Handlers
return MoveFailureCheck.trigger(function_code, *args) || false return MoveFailureCheck.trigger(function_code, *args) || false
end end
def self.move_will_fail_against_target?(function_code, *args)
return MoveFailureAgainstTargetCheck.trigger(function_code, *args) || false
end
def self.apply_move_effect_score(function_code, score, *args) def self.apply_move_effect_score(function_code, score, *args)
ret = MoveEffectScore.trigger(function_code, score, *args) ret = MoveEffectScore.trigger(function_code, score, *args)
return (ret.nil?) ? score : ret return (ret.nil?) ? score : ret
end end
def self.apply_move_effect_against_target_score(function_code, score, *args)
ret = MoveEffectAgainstTargetScore.trigger(function_code, score, *args)
return (ret.nil?) ? score : ret
end
def self.get_base_power(function_code, power, *args) def self.get_base_power(function_code, power, *args)
ret = MoveBasePower.trigger(function_code, power, *args) ret = MoveBasePower.trigger(function_code, power, *args)
return (ret.nil?) ? power : ret return (ret.nil?) ? power : ret
@@ -96,4 +108,12 @@ module Battle::AI::Handlers
end end
return score return score
end end
def self.apply_general_move_against_target_score_modifiers(score, *args)
GeneralMoveAgainstTargetScore.each do |id, score_proc|
new_score = score_proc.call(score, *args)
score = new_score if new_score
end
return score
end
end end

View File

@@ -61,7 +61,7 @@ class Battle::AI
scoreSum = 0 scoreSum = 0
scoreCount = 0 scoreCount = 0
battler.allOpposing.each do |b| battler.allOpposing.each do |b|
scoreSum += pbGetMoveScore(battler.moves[idxEncoredMove], b) scoreSum += pbGetMoveScore(battler.moves[idxEncoredMove], [b])
scoreCount += 1 scoreCount += 1
end end
if scoreCount > 0 && scoreSum / scoreCount <= 20 if scoreCount > 0 && scoreSum / scoreCount <= 20

View File

@@ -1,112 +1,97 @@
class Battle::AI class Battle::AI
MOVE_FAIL_SCORE = 25
MOVE_USELESS_SCORE = 60 # Move predicted to do nothing or just be detrimental
MOVE_BASE_SCORE = 100
#============================================================================= #=============================================================================
# Get scores for the user's moves (done before any action is assessed). # Get scores for the user's moves (done before any action is assessed).
#============================================================================= #=============================================================================
def pbGetMoveScores def pbGetMoveScores
battler = @user.battler
# Get scores and targets for each move
choices = [] choices = []
# TODO: Split this into two, the first part being the calculation of all @user.battler.eachMoveWithIndex do |move, idxMove|
# predicted damages and the second part being the score calculations # Unchoosable moves aren't considered
# (which are based on the predicted damages). Multi-target moves could if !@battle.pbCanChooseMove?(@user.index, idxMove, false)
# be fiddly since damages should be calculated for each target but if move.pp == 0 && move.total_pp > 0
# they're all related. PBDebug.log("[AI] #{@user.battler.pbThis} (#{@user.index}) cannot use move #{move.name} as it has no PP left")
battler.eachMoveWithIndex do |m, i|
if !@battle.pbCanChooseMove?(battler.index, i, false) # Unchoosable moves aren't considered
if m.pp == 0 && m.total_pp > 0
PBDebug.log("[AI] #{battler.pbThis} (#{battler.index}) cannot use move #{m.name} as it has no PP left")
else else
PBDebug.log("[AI] #{battler.pbThis} (#{battler.index}) cannot choose to use #{m.name}") PBDebug.log("[AI] #{@user.battler.pbThis} (#{@user.index}) cannot choose to use #{move.name}")
end end
next next
end end
pbAddMoveWithScoreToChoices(i, choices) # Set up move in class variables
set_up_move_check(move)
# Predict whether the move will fail (generally)
if @trainer.has_skill_flag?("PredictMoveFailure") && pbPredictMoveFailure
add_move_to_choices(choices, idxMove, MOVE_FAIL_SCORE)
next
end
target_data = move.pbTarget(@user.battler)
# TODO: Alter target_data if user has Protean and move is Curse.
case target_data.num_targets
when 0 # No targets, affects the user or a side or the whole field
# Includes: BothSides, FoeSide, None, User, UserSide
score = MOVE_BASE_SCORE
PBDebug.logonerr { score = pbGetMoveScore(move) }
add_move_to_choices(choices, idxMove, score)
when 1 # One target to be chosen by the trainer
# Includes: Foe, NearAlly, NearFoe, NearOther, Other, RandomNearFoe, UserOrNearAlly
# TODO: Figure out first which targets are valid. Includes the call to
# pbMoveCanTarget?, but also includes move-redirecting effects like
# Lightning Rod. Skip any battlers that can't be targeted.
@battle.allBattlers.each do |b|
next if !@battle.pbMoveCanTarget?(@user.battler.index, b.index, target_data)
# TODO: This should consider targeting an ally if possible. Scores will
# need to distinguish between harmful and beneficial to target.
# def pbGetMoveScore uses "175 - score" if the target is an ally;
# is this okay?
# Noticeably affects a few moves like Heal Pulse, as well as moves
# that the target can be immune to by an ability (you may want to
# attack the ally anyway so it gains the effect of that ability).
next if target_data.targets_foe && !@user.battler.opposes?(b)
score = MOVE_BASE_SCORE
PBDebug.logonerr { score = pbGetMoveScore(move, [b]) }
add_move_to_choices(choices, idxMove, score, b.index)
end
else # Multiple targets at once
# Includes: AllAllies, AllBattlers, AllFoes, AllNearFoes, AllNearOthers, UserAndAllies
targets = []
@battle.allBattlers.each do |b|
next if !@battle.pbMoveCanTarget?(@user.battler.index, b.index, target_data)
targets.push(b)
end
score = MOVE_BASE_SCORE
PBDebug.logonerr { score = pbGetMoveScore(move, targets) }
add_move_to_choices(choices, idxMove, score)
end
end end
@battle.moldBreaker = false @battle.moldBreaker = false
return choices return choices
end end
#============================================================================= def add_move_to_choices(choices, idxMove, score, idxTarget = -1)
# Get scores for the given move against each possible target. choices.push([idxMove, score, idxTarget])
#============================================================================= # If the user is a wild Pokémon, doubly prefer one of its moves (the choice
# Wild Pokémon choose their moves randomly. # is random but consistent and does not correlate to any other property of
# Trainer Pokémon calculate how much they want to use each of their moves. # the user)
def pbAddMoveWithScoreToChoices(idxMove, choices) if @user.wild? && @user.pokemon.personalID % @user.battler.moves.length == idxMove
battler = @user.battler choices.push([idxMove, score, idxTarget])
# TODO: Better incorporate this with the below code in future. This is here
# for now because of the num_targets > 1 code below, which would
# produce a score of 100 * the number of targets for a multi-target
# move, making it ridiculously over-preferred.
if @user.wild?
score = 100
choices.push([idxMove, score, -1]) # Move index, score, target
# Doubly prefer one of the user's moves (the choice is random but consistent
# and does not correlate to any other property of the user)
choices.push([idxMove, score, -1]) if battler.pokemon.personalID % battler.moves.length == idxMove
return
end
move = battler.moves[idxMove]
target_data = move.pbTarget(battler)
# TODO: Alter target_data if user has Protean and move is Curse.
if [:UserAndAllies, :AllAllies, :AllBattlers].include?(target_data.id) ||
target_data.num_targets == 0
# Also includes: BothSides, FoeSide, None, User, UserSide
# If move has no targets, affects the user, a side or the whole field, or
# specially affects multiple Pokémon and the AI calculates an overall
# score at once instead of per target
score = 100
PBDebug.logonerr { score = pbGetMoveScore(move) }
choices.push([idxMove, score, -1])
elsif target_data.num_targets > 1
# Includes: AllFoes, AllNearFoes, AllNearOthers
# Would also include UserAndAllies, AllAllies, AllBattlers, but they're above
# If move affects multiple battlers and you don't choose a particular one
# TODO: Should the scores from each target be averaged instead of summed?
total_score = 0
num_targets = 0
@battle.allBattlers.each do |b|
next if !@battle.pbMoveCanTarget?(battler.index, b.index, target_data)
score = 100
PBDebug.logonerr { score = pbGetMoveScore(move, b) }
total_score += ((battler.opposes?(b)) ? score : -score)
num_targets += 1
end
final_score = (num_targets == 1) ? total_score : 1.5 * total_score / num_targets
choices.push([idxMove, final_score, -1])
else
# Includes: Foe, NearAlly, NearFoe, NearOther, Other, RandomNearFoe, UserOrNearAlly
# If move affects one battler and you have to choose which one
# TODO: Figure out first which targets are valid. Includes the call to
# pbMoveCanTarget?, but also includes move-redirecting effects like
# Lightning Rod. Skip any battlers that can't be targeted.
@battle.allBattlers.each do |b|
next if !@battle.pbMoveCanTarget?(battler.index, b.index, target_data)
# TODO: This should consider targeting an ally if possible. Scores will
# need to distinguish between harmful and beneficial to target -
# maybe make the score "150 - score" if target is an ally (but
# only if the score is > 10 which is the "will fail" value)?
# Noticeably affects a few moves like Heal Pulse, as well as moves
# that the target can be immune to by an ability (you may want to
# attack the ally anyway so it gains the effect of that ability).
next if target_data.targets_foe && !battler.opposes?(b)
score = 100
PBDebug.logonerr { score = pbGetMoveScore(move, b) }
choices.push([idxMove, score, b.index])
end
end end
end end
#============================================================================= #=============================================================================
# Set some extra class variables for the move/target combo being assessed. # Set some extra class variables for the move/target combo being assessed.
#============================================================================= #=============================================================================
def set_up_move_check(move, target) def set_up_move_check(move)
@move.set_up(move, @user) @move.set_up(move, @user)
# TODO: Set @target to nil if there isn't one?
@target = (target) ? @battlers[target.index] : @user
@target&.refresh_battler
@battle.moldBreaker = @user.has_mold_breaker? @battle.moldBreaker = @user.has_mold_breaker?
end end
def set_up_move_check_target(target)
# TODO: Set @target to nil if there isn't one?
@target = (target) ? @battlers[target.index] : nil # @user
@target&.refresh_battler
end
#============================================================================= #=============================================================================
# Returns whether the move will definitely fail (assuming no battle conditions # Returns whether the move will definitely fail (assuming no battle conditions
# change between now and using the move). # change between now and using the move).
@@ -121,7 +106,13 @@ class Battle::AI
# User will be truanting # User will be truanting
return true if @user.has_active_ability?(:TRUANT) && @user.effects[PBEffects::Truant] return true if @user.has_active_ability?(:TRUANT) && @user.effects[PBEffects::Truant]
# Move effect-specific checks # Move effect-specific checks
return true if Battle::AI::Handlers.move_will_fail?(@move.function, @move, @user, @target, self, @battle) return true if Battle::AI::Handlers.move_will_fail?(@move.function, @move, @user, self, @battle)
return false
end
def pbPredictMoveFailureAgainstTarget
# Move effect-specific checks
return true if Battle::AI::Handlers.move_will_fail_against_target?(@move.function, @move, @user, @target, self, @battle)
# Immunity to priority moves because of Psychic Terrain # Immunity to priority moves because of Psychic Terrain
return true if @battle.field.terrain == :Psychic && @target.battler.affectedByTerrain? && return true if @battle.field.terrain == :Psychic && @target.battler.affectedByTerrain? &&
@target.opposes?(@user) && @move.rough_priority(@user) > 0 @target.opposes?(@user) && @move.rough_priority(@user) > 0
@@ -152,31 +143,63 @@ class Battle::AI
#============================================================================= #=============================================================================
# Get a score for the given move being used against the given target. # Get a score for the given move being used against the given target.
#============================================================================= #=============================================================================
def pbGetMoveScore(move, target = nil) def pbGetMoveScore(move, targets = nil)
set_up_move_check(move, target)
# Predict whether the move will fail
if @trainer.has_skill_flag?("PredictMoveFailure")
return 25 if pbPredictMoveFailure
end
# Get the base score for the move # Get the base score for the move
score = 100 score = MOVE_BASE_SCORE
# if @move.damagingMove? # Scores for each target in turn
# # Is also the predicted damage amount as a percentage of target's current HP if targets
# score = pbGetDamagingMoveBaseScore # Reset the base score for the move (each target will add its own score)
# else # Status moves score = 0
# # Depends on the move's effect # TODO: Distinguish between affected foes and affected allies?
# score = pbGetStatusMoveBaseScore affected_targets = 0
# end # Get a score for the move against each target in turn
targets.each do |target|
# Modify the score according to the move's effect set_up_move_check_target(target)
score = Battle::AI::Handlers.apply_move_effect_score(@move.function, # Predict whether the move will fail against the target
score, @move, @user, @target, self, @battle) if @trainer.has_skill_flag?("PredictMoveFailure")
# Modify the score according to various other effects next if pbPredictMoveFailureAgainstTarget
score = Battle::AI::Handlers.apply_general_move_score_modifiers( end
score, @move, @user, @target, self, @battle) affected_targets += 1
# Score the move
t_score = MOVE_BASE_SCORE
if @trainer.has_skill_flag?("ScoreMoves")
# Modify the score according to the move's effect against the target
t_score = Battle::AI::Handlers.apply_move_effect_against_target_score(@move.function,
MOVE_BASE_SCORE, @move, @user, @target, self, @battle)
# Modify the score according to various other effects against the target
score = Battle::AI::Handlers.apply_general_move_against_target_score_modifiers(
score, @move, @user, @target, self, @battle)
end
score += (@target.opposes?(@user)) ? t_score : 175 - t_score
end
# Check if any targets were affected
if affected_targets == 0
if @trainer.has_skill_flag?("PredictMoveFailure")
return MOVE_FAIL_SCORE if !@move.move.worksWithNoTargets?
score = MOVE_USELESS_SCORE
else
score = MOVE_BASE_SCORE
end
else
# TODO: Can this accounting for multiple targets be improved somehow?
score /= affected_targets # Average the score against multiple targets
# Bonus for affecting multiple targets
if @trainer.has_skill_flag?("PreferMultiTargetMoves")
score += (affected_targets - 1) * 10
end
end
end
# If we're here, the move either has no targets or at least one target will
# be affected (or the move is usable even if no targets are affected, e.g.
# Self-Destruct)
if @trainer.has_skill_flag?("ScoreMoves")
# Modify the score according to the move's effect
score = Battle::AI::Handlers.apply_move_effect_score(@move.function,
score, @move, @user, self, @battle)
# Modify the score according to various other effects
score = Battle::AI::Handlers.apply_general_move_score_modifiers(
score, @move, @user, self, @battle)
end
score = score.to_i score = score.to_i
score = 0 if score < 0 score = 0 if score < 0
return score return score
@@ -188,26 +211,23 @@ class Battle::AI
#============================================================================= #=============================================================================
def pbChooseMove(choices) def pbChooseMove(choices)
user_battler = @user.battler user_battler = @user.battler
# If no moves can be chosen, auto-choose a move or Struggle # If no moves can be chosen, auto-choose a move or Struggle
if choices.length == 0 if choices.length == 0
@battle.pbAutoChooseMove(user_battler.index) @battle.pbAutoChooseMove(user_battler.index)
PBDebug.log("[AI] #{user_battler.pbThis} (#{user_battler.index}) will auto-use a move or Struggle") PBDebug.log("[AI] #{user_battler.pbThis} (#{user_battler.index}) will auto-use a move or Struggle")
return return
end end
# Figure out useful information about the choices # Figure out useful information about the choices
max_score = 0 max_score = 0
choices.each { |c| max_score = c[1] if max_score < c[1] } choices.each { |c| max_score = c[1] if max_score < c[1] }
# Decide whether all choices are bad, and if so, try switching instead # Decide whether all choices are bad, and if so, try switching instead
if @trainer.high_skill? && @user.can_switch_lax? if @trainer.high_skill? && @user.can_switch_lax?
badMoves = false badMoves = false
if (max_score <= 25 && user_battler.turnCount > 2) || if (max_score <= MOVE_FAIL_SCORE && user_battler.turnCount > 2) ||
(max_score <= 60 && user_battler.turnCount > 4) (max_score <= MOVE_USELESS_SCORE && user_battler.turnCount > 4)
badMoves = true if pbAIRandom(100) < 80 badMoves = true if pbAIRandom(100) < 80
end end
if !badMoves && max_score <= 60 && user_battler.turnCount >= 1 if !badMoves && max_score <= MOVE_USELESS_SCORE && user_battler.turnCount >= 1
badMoves = choices.none? { |c| user_battler.moves[c[0]].damagingMove? } badMoves = choices.none? { |c| user_battler.moves[c[0]].damagingMove? }
badMoves = false if badMoves && pbAIRandom(100) < 10 badMoves = false if badMoves && pbAIRandom(100) < 10
end end
@@ -216,12 +236,10 @@ class Battle::AI
return return
end end
end end
# Calculate a minimum score threshold and reduce all move scores by it # Calculate a minimum score threshold and reduce all move scores by it
threshold = (max_score * 0.85).floor threshold = (max_score * 0.85).floor
choices.each { |c| c[3] = [c[1] - threshold, 0].max } choices.each { |c| c[3] = [c[1] - threshold, 0].max }
total_score = choices.sum { |c| c[3] } total_score = choices.sum { |c| c[3] }
# Log the available choices # Log the available choices
if $INTERNAL if $INTERNAL
PBDebug.log("[AI] Move choices for #{user_battler.pbThis(true)} (#{user_battler.index}):") PBDebug.log("[AI] Move choices for #{user_battler.pbThis(true)} (#{user_battler.index}):")
@@ -233,7 +251,6 @@ class Battle::AI
PBDebug.log(log_msg) PBDebug.log(log_msg)
end end
end end
# Pick a move randomly from choices weighted by their scores # Pick a move randomly from choices weighted by their scores
randNum = pbAIRandom(total_score) randNum = pbAIRandom(total_score)
choices.each do |c| choices.each do |c|
@@ -243,7 +260,6 @@ class Battle::AI
@battle.pbRegisterTarget(user_battler.index, c[2]) if c[2] >= 0 @battle.pbRegisterTarget(user_battler.index, c[2]) if c[2] >= 0
break break
end end
# Log the result # Log the result
if @battle.choices[user_battler.index][2] if @battle.choices[user_battler.index][2]
PBDebug.log(" => will use #{@battle.choices[user_battler.index][2].name}") PBDebug.log(" => will use #{@battle.choices[user_battler.index][2].name}")

View File

@@ -5,7 +5,7 @@ class Battle::AI
def get_score_for_user_stat_raise(score) def get_score_for_user_stat_raise(score)
# Discard status move/don't prefer damaging move if user has Contrary # Discard status move/don't prefer damaging move if user has Contrary
if !@battle.moldBreaker && @user.has_active_ability?(:CONTRARY) if !@battle.moldBreaker && @user.has_active_ability?(:CONTRARY)
return (@move.statusMove?) ? score - 40 : score - 20 return (@move.statusMove?) ? MOVE_USELESS_SCORE : score - 20
end end
# Don't make score changes if foes have Unaware and user can't make use of # Don't make score changes if foes have Unaware and user can't make use of
# extra stat stages # extra stat stages
@@ -37,7 +37,7 @@ class Battle::AI
if stat_changes.length == 0 if stat_changes.length == 0
# TODO: Have a parameter that decides whether to reduce the score here # TODO: Have a parameter that decides whether to reduce the score here
# (for moves where this is just part of the effect). # (for moves where this is just part of the effect).
return (@move.statusMove?) ? score - 40 : score return (@move.statusMove?) ? MOVE_USELESS_SCORE : score
end end
# Make score changes based on the general concept of raising stats at all # Make score changes based on the general concept of raising stats at all

View File

@@ -12,19 +12,14 @@
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DoesNothingCongratulations", Battle::AI::Handlers::MoveEffectScore.add("DoesNothingCongratulations",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score - 60 next Battle::AI::MOVE_USELESS_SCORE
} }
) )
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DoesNothingFailsIfNoAlly",
proc { |move, user, target, ai, battle|
next true if user.battler.allAllies.length == 0
}
)
Battle::AI::Handlers::MoveEffectScore.copy("DoesNothingCongratulations", Battle::AI::Handlers::MoveEffectScore.copy("DoesNothingCongratulations",
"DoesNothingFailsIfNoAlly") "DoesNothingFailsIfNoAlly")
@@ -49,12 +44,12 @@ Battle::AI::Handlers::MoveEffectScore.copy("DoesNothingCongratulations",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FailsIfNotUserFirstTurn", Battle::AI::Handlers::MoveFailureCheck.add("FailsIfNotUserFirstTurn",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.turnCount > 0 next true if user.turnCount > 0
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("FailsIfNotUserFirstTurn", Battle::AI::Handlers::MoveEffectScore.add("FailsIfNotUserFirstTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score + 25 # Use it or lose it next score + 25 # Use it or lose it
} }
) )
@@ -63,7 +58,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FailsIfNotUserFirstTurn",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserHasUnusedMove", Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserHasUnusedMove",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
has_another_move = false has_another_move = false
has_unused_move = false has_unused_move = false
user.battler.eachMove do |m| user.battler.eachMove do |m|
@@ -81,7 +76,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserHasUnusedMove",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserNotConsumedBerry", Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserNotConsumedBerry",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !user.battler.belched? next true if !user.battler.belched?
} }
) )
@@ -89,7 +84,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserNotConsumedBerry",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FailsIfTargetHasNoItem", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("FailsIfTargetHasNoItem",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !target.item || !target.item_active? next true if !target.item || !target.item_active?
} }
@@ -98,7 +93,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FailsIfTargetHasNoItem",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FailsUnlessTargetSharesTypeWithUser", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("FailsUnlessTargetSharesTypeWithUser",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
user_types = user.pbTypes(true) user_types = user.pbTypes(true)
target_types = target.pbTypes(true) target_types = target.pbTypes(true)
@@ -107,9 +102,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("FailsUnlessTargetSharesTypeWithUser"
) )
#=============================================================================== #===============================================================================
# # TODO: Split some of this into a MoveEffectScore?
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("FailsIfUserDamagedThisTurn", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfUserDamagedThisTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Check whether user is faster than its foe(s) and could use this move # Check whether user is faster than its foe(s) and could use this move
user_faster_count = 0 user_faster_count = 0
@@ -122,7 +117,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FailsIfUserDamagedThisTurn",
foe_faster_count += 1 foe_faster_count += 1
end end
end end
next score - 40 if user_faster_count == 0 next Battle::AI::MOVE_USELESS_SCORE if user_faster_count == 0
score += 10 if foe_faster_count == 0 score += 10 if foe_faster_count == 0
# Effects that make the target unlikely to act before the user # Effects that make the target unlikely to act before the user
if ai.trainer.high_skill? if ai.trainer.high_skill?
@@ -148,10 +143,10 @@ Battle::AI::Handlers::MoveEffectScore.add("FailsIfUserDamagedThisTurn",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("FailsIfTargetActed", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfTargetActed",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Check whether user is faster than its foe(s) and could use this move # Check whether user is faster than its foe(s) and could use this move
next score - 40 if target.faster_than?(user) next Battle::AI::MOVE_USELESS_SCORE if target.faster_than?(user)
score += 10 score += 10
# TODO: Predict the target switching/using an item. # TODO: Predict the target switching/using an item.
# TODO: Predict the target using a damaging move or Me First. # TODO: Predict the target using a damaging move or Me First.
@@ -165,7 +160,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FailsIfTargetActed",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("CrashDamageIfFailsUnusableInGravity", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CrashDamageIfFailsUnusableInGravity",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - (100 - move.rough_accuracy) if user.battler.takesIndirectDamage? next score - (100 - move.rough_accuracy) if user.battler.takesIndirectDamage?
} }
@@ -175,15 +170,15 @@ Battle::AI::Handlers::MoveEffectScore.add("CrashDamageIfFailsUnusableInGravity",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartSunWeather", Battle::AI::Handlers::MoveFailureCheck.add("StartSunWeather",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if [:HarshSun, :HeavyRain, :StrongWinds, next true if [:HarshSun, :HeavyRain, :StrongWinds,
move.move.weatherType].include?(battle.field.weather) move.move.weatherType].include?(battle.field.weather)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather", Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) || next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE) battle.pbCheckGlobalAbility(:CLOUDNINE)
score += 10 if battle.field.weather != :None # Prefer replacing another weather score += 10 if battle.field.weather != :None # Prefer replacing another weather
score += 15 if user.has_active_item?(:HEATROCK) score += 15 if user.has_active_item?(:HEATROCK)
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
@@ -227,9 +222,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather",
Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather", Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather",
"StartRainWeather") "StartRainWeather")
Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather", Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) || next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE) battle.pbCheckGlobalAbility(:CLOUDNINE)
score += 10 if battle.field.weather != :None # Prefer replacing another weather score += 10 if battle.field.weather != :None # Prefer replacing another weather
score += 15 if user.has_active_item?(:DAMPROCK) score += 15 if user.has_active_item?(:DAMPROCK)
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
@@ -269,9 +264,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather",
Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather", Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather",
"StartSandstormWeather") "StartSandstormWeather")
Battle::AI::Handlers::MoveEffectScore.add("StartSandstormWeather", Battle::AI::Handlers::MoveEffectScore.add("StartSandstormWeather",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) || next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE) battle.pbCheckGlobalAbility(:CLOUDNINE)
score += 10 if battle.field.weather != :None # Prefer replacing another weather score += 10 if battle.field.weather != :None # Prefer replacing another weather
score += 15 if user.has_active_item?(:SMOOTHROCK) score += 15 if user.has_active_item?(:SMOOTHROCK)
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
@@ -310,9 +305,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSandstormWeather",
Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather", Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather",
"StartHailWeather") "StartHailWeather")
Battle::AI::Handlers::MoveEffectScore.add("StartHailWeather", Battle::AI::Handlers::MoveEffectScore.add("StartHailWeather",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) || next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE) battle.pbCheckGlobalAbility(:CLOUDNINE)
score += 10 if battle.field.weather != :None # Prefer replacing another weather score += 10 if battle.field.weather != :None # Prefer replacing another weather
score += 15 if user.has_active_item?(:ICYROCK) score += 15 if user.has_active_item?(:ICYROCK)
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
@@ -349,12 +344,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartHailWeather",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartElectricTerrain", Battle::AI::Handlers::MoveFailureCheck.add("StartElectricTerrain",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if battle.field.terrain == :Electric next true if battle.field.terrain == :Electric
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartElectricTerrain", Battle::AI::Handlers::MoveEffectScore.add("StartElectricTerrain",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
if battle.field.terrain != :None if battle.field.terrain != :None
score -= ai.get_score_for_terrain(battle.field.terrain, user) score -= ai.get_score_for_terrain(battle.field.terrain, user)
@@ -368,12 +363,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartElectricTerrain",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartGrassyTerrain", Battle::AI::Handlers::MoveFailureCheck.add("StartGrassyTerrain",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if battle.field.terrain == :Grassy next true if battle.field.terrain == :Grassy
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartGrassyTerrain", Battle::AI::Handlers::MoveEffectScore.add("StartGrassyTerrain",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
if battle.field.terrain != :None if battle.field.terrain != :None
score -= ai.get_score_for_terrain(battle.field.terrain, user) score -= ai.get_score_for_terrain(battle.field.terrain, user)
@@ -387,12 +382,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGrassyTerrain",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartMistyTerrain", Battle::AI::Handlers::MoveFailureCheck.add("StartMistyTerrain",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if battle.field.terrain == :Misty next true if battle.field.terrain == :Misty
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartMistyTerrain", Battle::AI::Handlers::MoveEffectScore.add("StartMistyTerrain",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
if battle.field.terrain != :None if battle.field.terrain != :None
score -= ai.get_score_for_terrain(battle.field.terrain, user) score -= ai.get_score_for_terrain(battle.field.terrain, user)
@@ -406,12 +401,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartMistyTerrain",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartPsychicTerrain", Battle::AI::Handlers::MoveFailureCheck.add("StartPsychicTerrain",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if battle.field.terrain == :Psychic next true if battle.field.terrain == :Psychic
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartPsychicTerrain", Battle::AI::Handlers::MoveEffectScore.add("StartPsychicTerrain",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
if battle.field.terrain != :None if battle.field.terrain != :None
score -= ai.get_score_for_terrain(battle.field.terrain, user) score -= ai.get_score_for_terrain(battle.field.terrain, user)
@@ -425,12 +420,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPsychicTerrain",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("RemoveTerrain", Battle::AI::Handlers::MoveFailureCheck.add("RemoveTerrain",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if battle.field.terrain == :None next true if battle.field.terrain == :None
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("RemoveTerrain", Battle::AI::Handlers::MoveEffectScore.add("RemoveTerrain",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score - ai.get_score_for_terrain(battle.field.terrain, user) next score - ai.get_score_for_terrain(battle.field.terrain, user)
} }
) )
@@ -439,12 +434,12 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveTerrain",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("AddSpikesToFoeSide", Battle::AI::Handlers::MoveFailureCheck.add("AddSpikesToFoeSide",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.pbOpposingSide.effects[PBEffects::Spikes] >= 3 next true if user.pbOpposingSide.effects[PBEffects::Spikes] >= 3
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide", Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex } inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex }
foe_reserves = [] foe_reserves = []
battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty| battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty|
@@ -464,7 +459,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide",
end end
foe_reserves.push(pkmn) # pkmn will be affected by Spikes foe_reserves.push(pkmn) # pkmn will be affected by Spikes
end end
next score - 40 if foe_reserves.empty? next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty?
multiplier = [8, 5, 3][user.pbOpposingSide.effects[PBEffects::Spikes]] multiplier = [8, 5, 3][user.pbOpposingSide.effects[PBEffects::Spikes]]
score += multiplier * foe_reserves.length score += multiplier * foe_reserves.length
next score next score
@@ -475,12 +470,12 @@ Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("AddToxicSpikesToFoeSide", Battle::AI::Handlers::MoveFailureCheck.add("AddToxicSpikesToFoeSide",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.pbOpposingSide.effects[PBEffects::ToxicSpikes] >= 2 next true if user.pbOpposingSide.effects[PBEffects::ToxicSpikes] >= 2
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide", Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex } inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex }
foe_reserves = [] foe_reserves = []
battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty| battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty|
@@ -502,7 +497,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide",
end end
foe_reserves.push(pkmn) # pkmn will be affected by Toxic Spikes foe_reserves.push(pkmn) # pkmn will be affected by Toxic Spikes
end end
next score - 40 if foe_reserves.empty? next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty?
multiplier = [6, 4][user.pbOpposingSide.effects[PBEffects::ToxicSpikes]] multiplier = [6, 4][user.pbOpposingSide.effects[PBEffects::ToxicSpikes]]
score += multiplier * foe_reserves.length score += multiplier * foe_reserves.length
next score next score
@@ -513,12 +508,12 @@ Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("AddStealthRocksToFoeSide", Battle::AI::Handlers::MoveFailureCheck.add("AddStealthRocksToFoeSide",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.pbOpposingSide.effects[PBEffects::StealthRock] next true if user.pbOpposingSide.effects[PBEffects::StealthRock]
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide", Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex } inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex }
foe_reserves = [] foe_reserves = []
battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty| battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty|
@@ -531,7 +526,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide",
end end
foe_reserves.push(pkmn) # pkmn will be affected by Stealth Rock foe_reserves.push(pkmn) # pkmn will be affected by Stealth Rock
end end
next score - 40 if foe_reserves.empty? next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty?
next score + 8 * foe_reserves.length next score + 8 * foe_reserves.length
} }
) )
@@ -540,12 +535,12 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("AddStickyWebToFoeSide", Battle::AI::Handlers::MoveFailureCheck.add("AddStickyWebToFoeSide",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.pbOpposingSide.effects[PBEffects::StickyWeb] next true if user.pbOpposingSide.effects[PBEffects::StickyWeb]
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide", Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex } inBattleIndices = battle.allSameSideBattlers(user.idxOpposingSide).map { |b| b.pokemonIndex }
foe_reserves = [] foe_reserves = []
battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty| battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty|
@@ -563,7 +558,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide",
end end
foe_reserves.push(pkmn) # pkmn will be affected by Sticky Web foe_reserves.push(pkmn) # pkmn will be affected by Sticky Web
end end
next score - 40 if foe_reserves.empty? next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty?
next score + 7 * foe_reserves.length next score + 7 * foe_reserves.length
} }
) )
@@ -572,7 +567,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SwapSideEffects", Battle::AI::Handlers::MoveFailureCheck.add("SwapSideEffects",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
has_effect = false has_effect = false
2.times do |side| 2.times do |side|
effects = battle.sides[side].effects effects = battle.sides[side].effects
@@ -593,7 +588,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SwapSideEffects",
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("SwapSideEffects", Battle::AI::Handlers::MoveEffectScore.add("SwapSideEffects",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
good_effects = [:AuroraVeil, :LightScreen, :Mist, :Rainbow, :Reflect, good_effects = [:AuroraVeil, :LightScreen, :Mist, :Rainbow, :Reflect,
:Safeguard, :SeaOfFire, :Swamp, :Tailwind].map! { |e| PBEffects.const_get(e) } :Safeguard, :SeaOfFire, :Swamp, :Tailwind].map! { |e| PBEffects.const_get(e) }
@@ -617,7 +612,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwapSideEffects",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UserMakeSubstitute", Battle::AI::Handlers::MoveFailureCheck.add("UserMakeSubstitute",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.effects[PBEffects::Substitute] > 0 next true if user.effects[PBEffects::Substitute] > 0
next true if user.hp <= [user.totalhp / 4, 1].max next true if user.hp <= [user.totalhp / 4, 1].max
} }
@@ -627,7 +622,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserMakeSubstitute",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("RemoveUserBindingAndEntryHazards", Battle::AI::Handlers::MoveEffectScore.add("RemoveUserBindingAndEntryHazards",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score += 10 if user.effects[PBEffects::Trapping] > 0 score += 10 if user.effects[PBEffects::Trapping] > 0
score += 15 if user.effects[PBEffects::LeechSeed] >= 0 score += 15 if user.effects[PBEffects::LeechSeed] >= 0
if battle.pbAbleNonActiveCount(user.idxOwnSide) > 0 if battle.pbAbleNonActiveCount(user.idxOwnSide) > 0
@@ -643,13 +638,13 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveUserBindingAndEntryHazards",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("AttackTwoTurnsLater", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AttackTwoTurnsLater",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if battle.positions[target.index].effects[PBEffects::FutureSightCounter] > 0 next true if battle.positions[target.index].effects[PBEffects::FutureSightCounter] > 0
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("AttackTwoTurnsLater", Battle::AI::Handlers::MoveEffectScore.add("AttackTwoTurnsLater",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
# Future Sight tends to be wasteful if down to last Pokémon # Future Sight tends to be wasteful if down to last Pokémon
next score - 20 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0 next score - 20 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
} }
@@ -659,7 +654,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AttackTwoTurnsLater",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UserSwapsPositionsWithAlly", Battle::AI::Handlers::MoveFailureCheck.add("UserSwapsPositionsWithAlly",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
num_targets = 0 num_targets = 0
idxUserOwner = battle.pbGetOwnerIndexFromBattlerIndex(user.index) idxUserOwner = battle.pbGetOwnerIndexFromBattlerIndex(user.index)
user.battler.allAllies.each do |b| user.battler.allAllies.each do |b|
@@ -671,7 +666,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserSwapsPositionsWithAlly",
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("UserSwapsPositionsWithAlly", Battle::AI::Handlers::MoveEffectScore.add("UserSwapsPositionsWithAlly",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score - 30 # Usually no point in using this next score - 30 # Usually no point in using this
} }
) )
@@ -680,7 +675,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserSwapsPositionsWithAlly",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("BurnAttackerBeforeUserActs", Battle::AI::Handlers::MoveEffectScore.add("BurnAttackerBeforeUserActs",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
ai.battlers.each do |b| ai.battlers.each do |b|
next if !b || !b.opposes?(user) next if !b || !b.opposes?(user)
next if !b.battler.affectedByContactEffect? next if !b.battler.affectedByContactEffect?

View File

@@ -1,12 +1,12 @@
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SleepTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SleepTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.battler.pbCanSleep?(user.battler, false, move.move) next true if move.statusMove? && !target.battler.pbCanSleep?(user.battler, false, move.move)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("SleepTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SleepTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep anyway next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep anyway
# No score modifier if the sleep will be removed immediately # No score modifier if the sleep will be removed immediately
@@ -58,44 +58,48 @@ Battle::AI::Handlers::MoveEffectScore.add("SleepTarget",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SleepTargetIfUserDarkrai", Battle::AI::Handlers::MoveFailureCheck.add("SleepTargetIfUserDarkrai",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !user.battler.isSpecies?(:DARKRAI) && user.effects[PBEffects::TransformSpecies] != :DARKRAI next true if !user.battler.isSpecies?(:DARKRAI) && user.effects[PBEffects::TransformSpecies] != :DARKRAI
}
)
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SleepTargetIfUserDarkrai",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.battler.pbCanSleep?(user.battler, false, move.move) next true if move.statusMove? && !target.battler.pbCanSleep?(user.battler, false, move.move)
} }
) )
Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("SleepTarget",
"SleepTargetIfUserDarkrai") "SleepTargetIfUserDarkrai")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("SleepTarget",
"SleepTargetChangeUserMeloettaForm") "SleepTargetChangeUserMeloettaForm")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SleepTargetNextTurn", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SleepTargetNextTurn",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Yawn] > 0 next true if target.effects[PBEffects::Yawn] > 0
next true if !target.battler.pbCanSleep?(user.battler, false, move.move) next true if !target.battler.pbCanSleep?(user.battler, false, move.move)
} }
) )
Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("SleepTarget",
"SleepTargetNextTurn") "SleepTargetNextTurn")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("PoisonTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PoisonTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.battler.pbCanPoison?(user.battler, false, move.move) next true if move.statusMove? && !target.battler.pbCanPoison?(user.battler, false, move.move)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("PoisonTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
next score - 40 if move.statusMove? && target.has_active_ability?(:POISONHEAL) next Battle::AI::MOVE_USELESS_SCORE if move.statusMove? && target.has_active_ability?(:POISONHEAL)
# No score modifier if the poisoning will be removed immediately # No score modifier if the poisoning will be removed immediately
next score if target.has_active_item?([:PECHABERRY, :LUMBERRY]) next score if target.has_active_item?([:PECHABERRY, :LUMBERRY])
next score if target.faster_than?(user) && next score if target.faster_than?(user) &&
@@ -148,17 +152,17 @@ Battle::AI::Handlers::MoveEffectScore.add("PoisonTarget",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("PoisonTargetLowerTargetSpeed1", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PoisonTargetLowerTargetSpeed1",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !target.battler.pbCanPoison?(user.battler, false, move.move) && next true if !target.battler.pbCanPoison?(user.battler, false, move.move) &&
!target.battler.pbCanLowerStatStage?(:SPEED, user.battler, move.move) !target.battler.pbCanLowerStatStage?(:SPEED, user.battler, move.move)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("PoisonTargetLowerTargetSpeed1", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTargetLowerTargetSpeed1",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score = Battle::AI::Handlers.apply_move_effect_score("PoisonTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
score = Battle::AI::Handlers.apply_move_effect_score("LowerTargetSpeed1", score = Battle::AI::Handlers.apply_move_effect_against_target_score("LowerTargetSpeed1",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
next score next score
} }
@@ -167,20 +171,20 @@ Battle::AI::Handlers::MoveEffectScore.add("PoisonTargetLowerTargetSpeed1",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("PoisonTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("PoisonTarget",
"BadPoisonTarget") "BadPoisonTarget")
Battle::AI::Handlers::MoveEffectScore.copy("PoisonTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("PoisonTarget",
"BadPoisonTarget") "BadPoisonTarget")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ParalyzeTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ParalyzeTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.battler.pbCanParalyze?(user.battler, false, move.move) next true if move.statusMove? && !target.battler.pbCanParalyze?(user.battler, false, move.move)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("ParalyzeTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
# No score modifier if the paralysis will be removed immediately # No score modifier if the paralysis will be removed immediately
@@ -239,30 +243,30 @@ Battle::AI::Handlers::MoveEffectScore.add("ParalyzeTarget",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ParalyzeTargetIfNotTypeImmune", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ParalyzeTargetIfNotTypeImmune",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
eff = target.effectiveness_of_type_against_battler(move.rough_type, user) eff = target.effectiveness_of_type_against_battler(move.rough_type, user)
next true if Effectiveness.ineffective?(eff) next true if Effectiveness.ineffective?(eff)
next true if move.statusMove? && !target.battler.pbCanParalyze?(user.battler, false, move.move) next true if move.statusMove? && !target.battler.pbCanParalyze?(user.battler, false, move.move)
} }
) )
Battle::AI::Handlers::MoveEffectScore.copy("ParalyzeTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("ParalyzeTarget",
"ParalyzeTargetIfNotTypeImmune") "ParalyzeTargetIfNotTypeImmune")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.copy("ParalyzeTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("ParalyzeTarget",
"ParalyzeTargetAlwaysHitsInRainHitsTargetInSky") "ParalyzeTargetAlwaysHitsInRainHitsTargetInSky")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ParalyzeFlinchTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeFlinchTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score = Battle::AI::Handlers.apply_move_effect_score("ParalyzeTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
score = Battle::AI::Handlers.apply_move_effect_score("FlinchTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
next score next score
} }
@@ -271,12 +275,12 @@ Battle::AI::Handlers::MoveEffectScore.add("ParalyzeFlinchTarget",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("BurnTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("BurnTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.battler.pbCanBurn?(user.battler, false, move.move) next true if move.statusMove? && !target.battler.pbCanBurn?(user.battler, false, move.move)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("BurnTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
# No score modifier if the burn will be removed immediately # No score modifier if the burn will be removed immediately
@@ -337,11 +341,11 @@ Battle::AI::Handlers::MoveEffectScore.add("BurnTarget",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("BurnFlinchTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnFlinchTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score = Battle::AI::Handlers.apply_move_effect_score("BurnTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
score = Battle::AI::Handlers.apply_move_effect_score("FlinchTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
next score next score
} }
@@ -350,12 +354,12 @@ Battle::AI::Handlers::MoveEffectScore.add("BurnFlinchTarget",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FreezeTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("FreezeTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.battler.pbCanFreeze?(user.battler, false, move.move) next true if move.statusMove? && !target.battler.pbCanFreeze?(user.battler, false, move.move)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("FreezeTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FreezeTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
# No score modifier if the freeze will be removed immediately # No score modifier if the freeze will be removed immediately
@@ -401,23 +405,23 @@ Battle::AI::Handlers::MoveEffectScore.add("FreezeTarget",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.copy("FreezeTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FreezeTarget",
"FreezeTargetSuperEffectiveAgainstWater") "FreezeTargetSuperEffectiveAgainstWater")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.copy("FreezeTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FreezeTarget",
"FreezeTargetAlwaysHitsInHail") "FreezeTargetAlwaysHitsInHail")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("FreezeFlinchTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FreezeFlinchTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score = Battle::AI::Handlers.apply_move_effect_score("FreezeTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("FreezeTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
score = Battle::AI::Handlers.apply_move_effect_score("FlinchTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
next score next score
} }
@@ -426,7 +430,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FreezeFlinchTarget",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ParalyzeBurnOrFreezeTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeBurnOrFreezeTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
# No score modifier if the status problem will be removed immediately # No score modifier if the status problem will be removed immediately
@@ -435,12 +439,12 @@ Battle::AI::Handlers::MoveEffectScore.add("ParalyzeBurnOrFreezeTarget",
target.has_active_ability?(:HYDRATION) && target.has_active_ability?(:HYDRATION) &&
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather) [:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
# Scores for the possible effects # Scores for the possible effects
score += (Battle::AI::Handlers.apply_move_effect_score("ParalyzeTarget", score += (Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
100, move, user, target, ai, battle) - 100) / 3 Battle::AI::MOVE_BASE_SCORE, move, user, target, ai, battle) - Battle::AI::MOVE_BASE_SCORE) / 3
score += (Battle::AI::Handlers.apply_move_effect_score("BurnTarget", score += (Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
100, move, user, target, ai, battle) - 100) / 3 Battle::AI::MOVE_BASE_SCORE, move, user, target, ai, battle) - Battle::AI::MOVE_BASE_SCORE) / 3
score += (Battle::AI::Handlers.apply_move_effect_score("FreezeTarget", score += (Battle::AI::Handlers.apply_move_effect_against_target_score("FreezeTarget",
100, move, user, target, ai, battle) - 100) / 3 Battle::AI::MOVE_BASE_SCORE, move, user, target, ai, battle) - Battle::AI::MOVE_BASE_SCORE) / 3
next score next score
} }
) )
@@ -449,29 +453,33 @@ Battle::AI::Handlers::MoveEffectScore.add("ParalyzeBurnOrFreezeTarget",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("GiveUserStatusToTarget", Battle::AI::Handlers::MoveFailureCheck.add("GiveUserStatusToTarget",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.status == :NONE next true if user.status == :NONE
}
)
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("GiveUserStatusToTarget",
proc { |move, user, target, ai, battle|
next true if !target.battler.pbCanInflictStatus?(user.status, user.battler, false, move.move) next true if !target.battler.pbCanInflictStatus?(user.status, user.battler, false, move.move)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("GiveUserStatusToTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("GiveUserStatusToTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score += 10 # For getting rid of the user's status problem score += 10 # For getting rid of the user's status problem
case user.status case user.status
when :SLEEP when :SLEEP
next Battle::AI::Handlers.apply_move_effect_score("SleepTarget", next Battle::AI::Handlers.apply_move_effect_against_target_score("SleepTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
when :PARALYSIS when :PARALYSIS
next Battle::AI::Handlers.apply_move_effect_score("ParalyzeTarget", next Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
when :POISON when :POISON
next Battle::AI::Handlers.apply_move_effect_score("PoisonTarget", next Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
when :BURN when :BURN
next Battle::AI::Handlers.apply_move_effect_score("BurnTarget", next Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
when :FROZEN when :FROZEN
next Battle::AI::Handlers.apply_move_effect_score("FreezeTarget", next Battle::AI::Handlers.apply_move_effect_against_target_score("FreezeTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
end end
next score next score
@@ -482,12 +490,12 @@ Battle::AI::Handlers::MoveEffectScore.add("GiveUserStatusToTarget",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("CureUserBurnPoisonParalysis", Battle::AI::Handlers::MoveFailureCheck.add("CureUserBurnPoisonParalysis",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if ![:BURN, :POISON, :PARALYSIS].include?(user.status) next true if ![:BURN, :POISON, :PARALYSIS].include?(user.status)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("CureUserBurnPoisonParalysis", Battle::AI::Handlers::MoveEffectScore.add("CureUserBurnPoisonParalysis",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score + 15 next score + 15
} }
) )
@@ -496,16 +504,13 @@ Battle::AI::Handlers::MoveEffectScore.add("CureUserBurnPoisonParalysis",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("CureUserPartyStatus", Battle::AI::Handlers::MoveFailureCheck.add("CureUserPartyStatus",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
has_effect = battle.allSameSideBattlers(user.battler).any? { |b| b.status != :NONE } next battle.pbParty(user.index).none? { |pkmn| pkmn&.able? && pkmn.status != :NONE }
if !has_effect
has_effect = battle.pbParty(user.index).any? { |pkmn| pkmn&.able? && pkmn.status != :NONE }
end
next !has_effect
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("CureUserPartyStatus", Battle::AI::Handlers::MoveEffectScore.add("CureUserPartyStatus",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score = Battle::AI::MOVE_BASE_SCORE # Ignore the scores for each targeted battler calculated earlier
battle.pbParty(user.index).each do |pkmn| battle.pbParty(user.index).each do |pkmn|
score += 10 if pkmn && pkmn.status != :NONE score += 10 if pkmn && pkmn.status != :NONE
end end
@@ -515,8 +520,11 @@ Battle::AI::Handlers::MoveEffectScore.add("CureUserPartyStatus",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
# TODO: target should probably be treated as an enemy when deciding the score,
# since the score will be inverted elsewhere due to the target being an
# ally.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("CureTargetBurn", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CureTargetBurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if target.status == :BURN if target.status == :BURN
if target.opposes?(user) if target.opposes?(user)
@@ -533,12 +541,12 @@ Battle::AI::Handlers::MoveEffectScore.add("CureTargetBurn",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideImmunityToInflictedStatus", Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideImmunityToInflictedStatus",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.pbOwnSide.effects[PBEffects::Safeguard] > 0 next true if user.pbOwnSide.effects[PBEffects::Safeguard] > 0
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToInflictedStatus", Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToInflictedStatus",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if user.status != :NONE if user.status != :NONE
score -= 20 score -= 20
else else
@@ -551,7 +559,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToInflictedStatu
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("FlinchTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FlinchTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if target.faster_than?(user) || target.effects[PBEffects::Substitute] > 0 next score if target.faster_than?(user) || target.effects[PBEffects::Substitute] > 0
next score if target.has_active_ability?(:INNERFOCUS) && !battle.moldBreaker next score if target.has_active_ability?(:INNERFOCUS) && !battle.moldBreaker
@@ -576,23 +584,23 @@ Battle::AI::Handlers::MoveEffectScore.add("FlinchTarget",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FlinchTargetFailsIfUserNotAsleep", Battle::AI::Handlers::MoveFailureCheck.add("FlinchTargetFailsIfUserNotAsleep",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !user.battler.asleep? next true if !user.battler.asleep?
} }
) )
Battle::AI::Handlers::MoveEffectScore.copy("FlinchTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FlinchTarget",
"FlinchTargetFailsIfUserNotAsleep") "FlinchTargetFailsIfUserNotAsleep")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FlinchTargetFailsIfNotUserFirstTurn", Battle::AI::Handlers::MoveFailureCheck.add("FlinchTargetFailsIfNotUserFirstTurn",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.turnCount > 0 next true if user.turnCount > 0
} }
) )
Battle::AI::Handlers::MoveEffectScore.copy("FlinchTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FlinchTarget",
"FlinchTargetFailsIfNotUserFirstTurn") "FlinchTargetFailsIfNotUserFirstTurn")
#=============================================================================== #===============================================================================
# #
@@ -602,18 +610,18 @@ Battle::AI::Handlers::MoveBasePower.add("FlinchTargetDoublePowerIfTargetInSky",
next move.move.pbBaseDamage(power, user.battler, target.battler) next move.move.pbBaseDamage(power, user.battler, target.battler)
} }
) )
Battle::AI::Handlers::MoveEffectScore.copy("FlinchTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FlinchTarget",
"FlinchTargetDoublePowerIfTargetInSky") "FlinchTargetDoublePowerIfTargetInSky")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ConfuseTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ConfuseTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.battler.pbCanConfuse?(user.battler, false, move.move) next true if move.statusMove? && !target.battler.pbCanConfuse?(user.battler, false, move.move)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("ConfuseTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ConfuseTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# No score modifier if the status problem will be removed immediately # No score modifier if the status problem will be removed immediately
next score if target.has_active_item?(:PERSIMBERRY) next score if target.has_active_item?(:PERSIMBERRY)
@@ -641,18 +649,18 @@ Battle::AI::Handlers::MoveEffectScore.add("ConfuseTarget",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.copy("ConfuseTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("ConfuseTarget",
"ConfuseTargetAlwaysHitsInRainHitsTargetInSky") "ConfuseTargetAlwaysHitsInRainHitsTargetInSky")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("AttractTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AttractTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.battler.pbCanAttract?(user.battler, false) next true if move.statusMove? && !target.battler.pbCanAttract?(user.battler, false)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("AttractTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AttractTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if target.battler.pbCanAttract?(user.battler, false) if target.battler.pbCanAttract?(user.battler, false)
case move.additional_effect_usability(user, target) case move.additional_effect_usability(user, target)
@@ -680,7 +688,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AttractTarget",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesBasedOnEnvironment", Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesBasedOnEnvironment",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !user.battler.canChangeType? next true if !user.battler.canChangeType?
new_type = nil new_type = nil
terr_types = Battle::Move::SetUserTypesBasedOnEnvironment::TERRAIN_TYPES terr_types = Battle::Move::SetUserTypesBasedOnEnvironment::TERRAIN_TYPES
@@ -699,7 +707,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesBasedOnEnvironment",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToResistLastAttack", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserTypesToResistLastAttack",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !user.battler.canChangeType? next true if !user.battler.canChangeType?
next true if !target.battler.lastMoveUsed || !target.battler.lastMoveUsedType || next true if !target.battler.lastMoveUsed || !target.battler.lastMoveUsedType ||
@@ -718,7 +726,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToResistLastAttack",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToTargetTypes", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserTypesToTargetTypes",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !user.battler.canChangeType? next true if !user.battler.canChangeType?
next true if target.battler.pbTypes(true).empty? next true if target.battler.pbTypes(true).empty?
@@ -731,7 +739,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToTargetTypes",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToUserMoveType", Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToUserMoveType",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !user.battler.canChangeType? next true if !user.battler.canChangeType?
has_possible_type = false has_possible_type = false
user.battler.eachMoveWithIndex do |m, i| user.battler.eachMoveWithIndex do |m, i|
@@ -748,7 +756,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToUserMoveType",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetTypesToPsychic", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetTypesToPsychic",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false) next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
} }
@@ -757,26 +765,26 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetTypesToPsychic",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("SetTargetTypesToPsychic", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("SetTargetTypesToPsychic",
"SetTargetTypesToWater") "SetTargetTypesToWater")
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("SetTargetTypesToWater", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("SetTargetTypesToWater",
"AddGhostTypeToTarget") "AddGhostTypeToTarget")
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("AddGhostTypeToTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("AddGhostTypeToTarget",
"AddGrassTypeToTarget") "AddGrassTypeToTarget")
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UserLosesFireType", Battle::AI::Handlers::MoveFailureCheck.add("UserLosesFireType",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !user.has_type?(:FIRE) next true if !user.has_type?(:FIRE)
} }
) )
@@ -784,7 +792,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserLosesFireType",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToSimple", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToSimple",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !GameData::Ability.exists?(:SIMPLE) next true if !GameData::Ability.exists?(:SIMPLE)
next true if target.battler.unstoppableAbility? || next true if target.battler.unstoppableAbility? ||
@@ -795,7 +803,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToSimple",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToInsomnia", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToInsomnia",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !GameData::Ability.exists?(:INSOMNIA) next true if !GameData::Ability.exists?(:INSOMNIA)
next true if target.battler.unstoppableAbility? || next true if target.battler.unstoppableAbility? ||
@@ -806,7 +814,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToInsomnia",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetUserAbilityToTargetAbility", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserAbilityToTargetAbility",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if user.battler.unstoppableAbility? next true if user.battler.unstoppableAbility?
next true if !target.ability || user.ability_id == target.ability_id next true if !target.ability || user.ability_id == target.ability_id
@@ -814,7 +822,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserAbilityToTargetAbility",
[:POWEROFALCHEMY, :RECEIVER, :TRACE, :WONDERGUARD].include?(target.ability_id) [:POWEROFALCHEMY, :RECEIVER, :TRACE, :WONDERGUARD].include?(target.ability_id)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("SetUserAbilityToTargetAbility", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserAbilityToTargetAbility",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score -= 40 # don't prefer this move score -= 40 # don't prefer this move
if ai.trainer.medium_skill? && user.opposes?(target) if ai.trainer.medium_skill? && user.opposes?(target)
@@ -827,7 +835,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SetUserAbilityToTargetAbility",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToUserAbility", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToUserAbility",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !user.ability || user.ability_id == target.ability_id next true if !user.ability || user.ability_id == target.ability_id
next true if user.battler.ungainableAbility? || next true if user.battler.ungainableAbility? ||
@@ -835,7 +843,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToUserAbility",
next true if target.battler.unstoppableAbility? || target.ability_id == :TRUANT next true if target.battler.unstoppableAbility? || target.ability_id == :TRUANT
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("SetTargetAbilityToUserAbility", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToUserAbility",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score -= 40 # don't prefer this move score -= 40 # don't prefer this move
if ai.trainer.medium_skill? && user.opposes?(target) if ai.trainer.medium_skill? && user.opposes?(target)
@@ -848,7 +856,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SetTargetAbilityToUserAbility",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UserTargetSwapAbilities", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("UserTargetSwapAbilities",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !user.ability || !target.ability next true if !user.ability || !target.ability
next true if Settings::MECHANICS_GENERATION <= 5 && user.ability_id == target.ability_id next true if Settings::MECHANICS_GENERATION <= 5 && user.ability_id == target.ability_id
@@ -858,7 +866,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserTargetSwapAbilities",
target.ability_id == :WONDERGUARD target.ability_id == :WONDERGUARD
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapAbilities", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapAbilities",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score -= 40 # don't prefer this move score -= 40 # don't prefer this move
if ai.trainer.high_skill? && user.opposes?(target) if ai.trainer.high_skill? && user.opposes?(target)
@@ -871,7 +879,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapAbilities",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("NegateTargetAbility", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("NegateTargetAbility",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false) next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
} }
@@ -880,7 +888,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("NegateTargetAbility",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("NegateTargetAbilityIfTargetActed", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbilityIfTargetActed",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score += 15 if target.faster_than?(user) score += 15 if target.faster_than?(user)
next score next score
@@ -896,7 +904,7 @@ Battle::AI::Handlers::MoveEffectScore.add("NegateTargetAbilityIfTargetActed",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartUserAirborne", Battle::AI::Handlers::MoveFailureCheck.add("StartUserAirborne",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.effects[PBEffects::Ingrain] || next true if user.effects[PBEffects::Ingrain] ||
user.effects[PBEffects::SmackDown] || user.effects[PBEffects::SmackDown] ||
user.effects[PBEffects::MagnetRise] > 0 user.effects[PBEffects::MagnetRise] > 0
@@ -906,7 +914,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartUserAirborne",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartTargetAirborneAndAlwaysHitByMoves", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartTargetAirborneAndAlwaysHitByMoves",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false) next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
} }
@@ -920,7 +928,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartTargetAirborneAndAlwaysHitByMov
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("HitsTargetInSkyGroundsTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitsTargetInSkyGroundsTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
score += 20 if target.effects[PBEffects::MagnetRise] > 0 || score += 20 if target.effects[PBEffects::MagnetRise] > 0 ||
@@ -940,12 +948,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HitsTargetInSkyGroundsTarget",
# TODO: This code shouldn't make use of target. # TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartGravity", Battle::AI::Handlers::MoveFailureCheck.add("StartGravity",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if battle.field.effects[PBEffects::Gravity] > 0 next true if battle.field.effects[PBEffects::Gravity] > 0
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartGravity", Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
score -= 15 if user.effects[PBEffects::SkyDrop] >= 0 || score -= 15 if user.effects[PBEffects::SkyDrop] >= 0 ||
user.effects[PBEffects::MagnetRise] > 0 || user.effects[PBEffects::MagnetRise] > 0 ||
@@ -953,15 +961,15 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
user.has_type?(:FLYING) || user.has_type?(:FLYING) ||
user.has_active_ability?(:LEVITATE) || user.has_active_ability?(:LEVITATE) ||
user.has_active_item?(:AIRBALLOON) user.has_active_item?(:AIRBALLOON)
score += 15 if target.effects[PBEffects::SkyDrop] >= 0 || # score += 15 if target.effects[PBEffects::SkyDrop] >= 0 ||
target.effects[PBEffects::MagnetRise] > 0 || # target.effects[PBEffects::MagnetRise] > 0 ||
target.effects[PBEffects::Telekinesis] > 0 || # target.effects[PBEffects::Telekinesis] > 0 ||
target.has_type?(:FLYING) || # target.has_type?(:FLYING) ||
target.has_active_ability?(:LEVITATE) || # target.has_active_ability?(:LEVITATE) ||
target.has_active_item?(:AIRBALLOON) # target.has_active_item?(:AIRBALLOON)
score += 5 if target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky", # score += 5 if target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky",
"TwoTurnAttackInvulnerableInSkyParalyzeTarget", # "TwoTurnAttackInvulnerableInSkyParalyzeTarget",
"TwoTurnAttackInvulnerableInSkyTargetCannotAct") # "TwoTurnAttackInvulnerableInSkyTargetCannotAct")
end end
next score next score
} }
@@ -970,15 +978,15 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TransformUserIntoTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TransformUserIntoTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Transform] next true if user.effects[PBEffects::Transform]
next true if target.effects[PBEffects::Transform] || next true if target.effects[PBEffects::Transform] ||
target.effects[PBEffects::Illusion] target.effects[PBEffects::Illusion]
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("TransformUserIntoTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TransformUserIntoTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 20 next score - 10
} }
) )

View File

@@ -46,7 +46,7 @@ Battle::AI::Handlers::MoveBasePower.add("FixedDamageUserLevelRandom",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetHPToUserHP", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetHPToUserHP",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if user.hp >= target.hp next true if user.hp >= target.hp
} }
@@ -60,7 +60,7 @@ Battle::AI::Handlers::MoveBasePower.add("LowerTargetHPToUserHP",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("OHKO", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("OHKO",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.level > user.level next true if target.level > user.level
next true if !battle.moldBreaker && target.has_active_ability?(:STURDY) next true if !battle.moldBreaker && target.has_active_ability?(:STURDY)
@@ -75,7 +75,7 @@ Battle::AI::Handlers::MoveBasePower.add("OHKO",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("OHKOIce", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("OHKOIce",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.level > user.level next true if target.level > user.level
next true if !battle.moldBreaker && target.has_active_ability?(:STURDY) next true if !battle.moldBreaker && target.has_active_ability?(:STURDY)
@@ -88,15 +88,15 @@ Battle::AI::Handlers::MoveBasePower.copy("OHKO",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("OHKO", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("OHKO",
"OHKOHitsUndergroundTarget") "OHKOHitsUndergroundTarget")
Battle::AI::Handlers::MoveBasePower.copy("OHKO", Battle::AI::Handlers::MoveBasePower.copy("OHKO",
"OHKOHitsUndergroundTarget") "OHKOHitsUndergroundTarget")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DamageTargetAlly", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DamageTargetAlly",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
target.battler.allAllies.each do |b| target.battler.allAllies.each do |b|
next if !b.near?(target.battler) || !b.battler.takesIndirectDamage? next if !b.near?(target.battler) || !b.battler.takesIndirectDamage?
@@ -239,7 +239,7 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetHPLessThanHalf",
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetHPLessThanHalf", Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetHPLessThanHalf",
"DoublePowerIfTargetAsleepCureTarget") "DoublePowerIfTargetAsleepCureTarget")
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetAsleepCureTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetAsleepCureTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 20 if target.status == :SLEEP && # Will cure status next score - 20 if target.status == :SLEEP && # Will cure status
target.statusCount > 1 target.statusCount > 1
@@ -260,7 +260,7 @@ Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetPoisoned",
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetPoisoned", Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetPoisoned",
"DoublePowerIfTargetParalyzedCureTarget") "DoublePowerIfTargetParalyzedCureTarget")
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetParalyzedCureTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetParalyzedCureTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 20 if target.status == :PARALYSIS # Will cure status next score - 20 if target.status == :PARALYSIS # Will cure status
} }
@@ -330,15 +330,16 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetInSky",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfUserLostHPThisTurn", Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfUserLostHPThisTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score + 15 if target.faster_than?(user) # TODO: Remove target from this; consider the speeds of all foes instead.
# next score + 15 if target.faster_than?(user)
} }
) )
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetLostHPThisTurn", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetLostHPThisTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score + 15 if battle.pbOpposingBattlerCount(user.battler) > 1 next score + 15 if battle.pbOpposingBattlerCount(user.battler) > 1
} }
@@ -352,7 +353,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetLostHPThisTurn",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetActed", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetActed",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score + 15 if target.faster_than?(user) next score + 15 if target.faster_than?(user)
} }
@@ -361,7 +362,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetActed",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetNotActed", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetNotActed",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score + 15 if user.faster_than?(target) next score + 15 if user.faster_than?(target)
} }
@@ -376,7 +377,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetNotActed",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit", Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if user.effects[PBEffects::LaserFocus] > 0 if user.effects[PBEffects::LaserFocus] > 0
score -= 90 score -= 90
else else
@@ -390,7 +391,7 @@ Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartPreventCriticalHitsAgainstUserSide", Battle::AI::Handlers::MoveFailureCheck.add("StartPreventCriticalHitsAgainstUserSide",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.pbOwnSide.effects[PBEffects::LuckyChant] > 0 next true if user.pbOwnSide.effects[PBEffects::LuckyChant] > 0
} }
) )
@@ -398,7 +399,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartPreventCriticalHitsAgainstUserS
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("CannotMakeTargetFaint", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CannotMakeTargetFaint",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.hp == 1 next true if target.hp == 1
} }
@@ -409,11 +410,11 @@ Battle::AI::Handlers::MoveFailureCheck.add("CannotMakeTargetFaint",
# TODO: This code shouldn't make use of target. # TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn", Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score -= 10 if user.hp > user.totalhp / 2 score -= 10 if user.hp > user.totalhp / 2
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
score -= 20 if user.effects[PBEffects::ProtectRate] > 1 score -= 20 if user.effects[PBEffects::ProtectRate] > 1
score -= 20 if target.effects[PBEffects::HyperBeam] > 0 # score -= 20 if target.effects[PBEffects::HyperBeam] > 0
else else
score -= user.effects[PBEffects::ProtectRate] * 10 score -= user.effects[PBEffects::ProtectRate] * 10
end end
@@ -425,7 +426,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenElectricMoves", Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenElectricMoves",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
if Settings::MECHANICS_GENERATION >= 6 if Settings::MECHANICS_GENERATION >= 6
next true if battle.field.effects[PBEffects::MudSportField] > 0 next true if battle.field.effects[PBEffects::MudSportField] > 0
else else
@@ -438,7 +439,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenElectricMoves",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenFireMoves", Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenFireMoves",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
if Settings::MECHANICS_GENERATION >= 6 if Settings::MECHANICS_GENERATION >= 6
next true if battle.field.effects[PBEffects::WaterSportField] > 0 next true if battle.field.effects[PBEffects::WaterSportField] > 0
else else
@@ -451,7 +452,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenFireMoves",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenPhysicalDamageAgainstUserSide", Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenPhysicalDamageAgainstUserSide",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.pbOwnSide.effects[PBEffects::Reflect] > 0 next true if user.pbOwnSide.effects[PBEffects::Reflect] > 0
} }
) )
@@ -460,7 +461,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenPhysicalDamageAgainstUser
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenSpecialDamageAgainstUserSide", Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenSpecialDamageAgainstUserSide",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.pbOwnSide.effects[PBEffects::LightScreen] > 0 next true if user.pbOwnSide.effects[PBEffects::LightScreen] > 0
} }
) )
@@ -469,13 +470,13 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenSpecialDamageAgainstUserS
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenDamageAgainstUserSideIfHail", Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenDamageAgainstUserSideIfHail",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0 next true if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
next true if user.battler.effectiveWeather != :Hail next true if user.battler.effectiveWeather != :Hail
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHail", Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHail",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score + 40 next score + 40
} }
) )
@@ -484,7 +485,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHai
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("RemoveScreens", Battle::AI::Handlers::MoveEffectScore.add("RemoveScreens",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score += 10 if user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0 score += 10 if user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0
score += 10 if user.pbOpposingSide.effects[PBEffects::Reflect] > 0 score += 10 if user.pbOpposingSide.effects[PBEffects::Reflect] > 0
score += 10 if user.pbOpposingSide.effects[PBEffects::LightScreen] > 0 score += 10 if user.pbOpposingSide.effects[PBEffects::LightScreen] > 0
@@ -497,16 +498,16 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveScreens",
# TODO: This code shouldn't make use of target. # TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ProtectUser", Battle::AI::Handlers::MoveEffectScore.add("ProtectUser",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 || if user.effects[PBEffects::ProtectRate] > 1 # ||
target.effects[PBEffects::HyperBeam] > 0 # target.effects[PBEffects::HyperBeam] > 0
score -= 50 score -= 50
else else
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40 score -= user.effects[PBEffects::ProtectRate] * 40
end end
score += 50 if user.turnCount == 0 score += 50 if user.turnCount == 0
score += 30 if target.effects[PBEffects::TwoTurnAttack] # score += 30 if target.effects[PBEffects::TwoTurnAttack]
end end
next score next score
} }
@@ -517,14 +518,14 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUser",
# TODO: This code shouldn't make use of target. # TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker", Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score - 40 if user.effects[PBEffects::ProtectRate] > 1 || next Battle::AI::MOVE_USELESS_SCORE if user.effects[PBEffects::ProtectRate] > 1 # ||
target.effects[PBEffects::HyperBeam] > 0 # target.effects[PBEffects::HyperBeam] > 0
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40 score -= user.effects[PBEffects::ProtectRate] * 40
end end
score += 10 if user.turnCount == 0 score += 10 if user.turnCount == 0
score += 15 if target.effects[PBEffects::TwoTurnAttack] # score += 15 if target.effects[PBEffects::TwoTurnAttack]
score += 15 # Because of possible poisoning score += 15 # Because of possible poisoning
next score next score
} }
@@ -535,16 +536,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker",
# TODO: This code shouldn't make use of target. # TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShield", Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShield",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 || if user.effects[PBEffects::ProtectRate] > 1 # ||
target.effects[PBEffects::HyperBeam] > 0 # target.effects[PBEffects::HyperBeam] > 0
score -= 50 score -= 50
else else
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40 score -= user.effects[PBEffects::ProtectRate] * 40
end end
score += 50 if user.turnCount == 0 score += 50 if user.turnCount == 0
score += 30 if target.effects[PBEffects::TwoTurnAttack] # score += 30 if target.effects[PBEffects::TwoTurnAttack]
end end
next score next score
} }
@@ -555,16 +556,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShie
# TODO: This code shouldn't make use of target. # TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct", Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 || if user.effects[PBEffects::ProtectRate] > 1 # ||
target.effects[PBEffects::HyperBeam] > 0 # target.effects[PBEffects::HyperBeam] > 0
score -= 50 score -= 50
else else
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40 score -= user.effects[PBEffects::ProtectRate] * 40
end end
score += 50 if user.turnCount == 0 score += 50 if user.turnCount == 0
score += 30 if target.effects[PBEffects::TwoTurnAttack] # score += 30 if target.effects[PBEffects::TwoTurnAttack]
end end
next score next score
} }
@@ -575,16 +576,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct"
# TODO: This code shouldn't make use of target. # TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShield", Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShield",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 || if user.effects[PBEffects::ProtectRate] > 1 # ||
target.effects[PBEffects::HyperBeam] > 0 # target.effects[PBEffects::HyperBeam] > 0
score -= 90 score -= 90
else else
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40 score -= user.effects[PBEffects::ProtectRate] * 40
end end
score += 50 if user.turnCount == 0 score += 50 if user.turnCount == 0
score += 30 if target.effects[PBEffects::TwoTurnAttack] # score += 30 if target.effects[PBEffects::TwoTurnAttack]
end end
next score next score
} }
@@ -594,13 +595,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShi
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromDamagingMovesIfUserFirstTurn", Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromDamagingMovesIfUserFirstTurn",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.turnCount > 0 next true if user.turnCount > 0
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUserFirstTurn", Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUserFirstTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score + 30 next score + 25 # Use it or lose it
} }
) )
@@ -608,7 +609,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUse
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromStatusMoves", Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromStatusMoves",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.pbOwnSide.effects[PBEffects::CraftyShield] next true if user.pbOwnSide.effects[PBEffects::CraftyShield]
} }
) )
@@ -639,11 +640,11 @@ Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromStatusMoves",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1", Battle::AI::Handlers::MoveFailureCheck.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !user.battler.isSpecies?(:HOOPA) || user.battler.form != 1 next true if !user.battler.isSpecies?(:HOOPA) || user.battler.form != 1
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score + 20 if target.stages[:DEFENSE] > 0 next score + 20 if target.stages[:DEFENSE] > 0
} }
@@ -652,14 +653,14 @@ Battle::AI::Handlers::MoveEffectScore.add("HoopaRemoveProtectionsBypassSubstitut
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("RecoilQuarterOfDamageDealt", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilQuarterOfDamageDealt",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if !user.battler.takesIndirectDamage? || user.has_active_ability?(:ROCKHEAD) next score if !user.battler.takesIndirectDamage? || user.has_active_ability?(:ROCKHEAD)
dmg = move.rough_damage / 4 dmg = move.rough_damage / 4
if dmg >= user.hp if dmg >= user.hp
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
next score - 40 if reserves <= foes next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes
end end
score -= 10 * [dmg, user.hp].min / user.hp score -= 10 * [dmg, user.hp].min / user.hp
next score next score
@@ -669,7 +670,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilQuarterOfDamageDealt",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtParalyzeTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilThirdOfDamageDealtParalyzeTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for being a recoil move # Score for being a recoil move
if user.battler.takesIndirectDamage? && !user.has_active_ability?(:ROCKHEAD) if user.battler.takesIndirectDamage? && !user.has_active_ability?(:ROCKHEAD)
@@ -677,12 +678,12 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtParalyzeTarge
if dmg >= user.hp if dmg >= user.hp
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
next score - 40 if reserves <= foes next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes
end end
score -= 10 * [dmg, user.hp].min / user.hp score -= 10 * [dmg, user.hp].min / user.hp
end end
# Score for paralysing # Score for paralysing
score = Battle::AI::Handlers.apply_move_effect_score("ParalyzeTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
next score next score
} }
@@ -691,7 +692,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtParalyzeTarge
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtBurnTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilThirdOfDamageDealtBurnTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for being a recoil move # Score for being a recoil move
if user.battler.takesIndirectDamage? && !user.has_active_ability?(:ROCKHEAD) if user.battler.takesIndirectDamage? && !user.has_active_ability?(:ROCKHEAD)
@@ -699,12 +700,12 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtBurnTarget",
if dmg >= user.hp if dmg >= user.hp
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
next score - 40 if reserves <= foes next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes
end end
score -= 10 * [dmg, user.hp].min / user.hp score -= 10 * [dmg, user.hp].min / user.hp
end end
# Score for burning # Score for burning
score = Battle::AI::Handlers.apply_move_effect_score("BurnTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
next score next score
} }
@@ -713,14 +714,14 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtBurnTarget",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("RecoilHalfOfDamageDealt", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilHalfOfDamageDealt",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if !user.battler.takesIndirectDamage? || user.has_active_ability?(:ROCKHEAD) next score if !user.battler.takesIndirectDamage? || user.has_active_ability?(:ROCKHEAD)
dmg = move.rough_damage / 2 dmg = move.rough_damage / 2
if dmg >= user.hp if dmg >= user.hp
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
next score - 40 if reserves <= foes next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes
end end
score -= 10 * [dmg, user.hp].min / user.hp score -= 10 * [dmg, user.hp].min / user.hp
next score next score
@@ -745,7 +746,7 @@ Battle::AI::Handlers::MoveBasePower.add("EffectivenessIncludesFlyingType",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("CategoryDependsOnHigherDamagePoisonTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CategoryDependsOnHigherDamagePoisonTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score + 5 if target.battler.pbCanPoison?(user.battler, false) next score + 5 if target.battler.pbCanPoison?(user.battler, false)
} }
@@ -775,14 +776,14 @@ Battle::AI::Handlers::MoveEffectScore.add("CategoryDependsOnHigherDamagePoisonTa
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("EnsureNextMoveAlwaysHits", Battle::AI::Handlers::MoveFailureCheck.add("EnsureNextMoveAlwaysHits",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.effects[PBEffects::LockOn] > 0 next true if user.effects[PBEffects::LockOn] > 0
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("EnsureNextMoveAlwaysHits", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("EnsureNextMoveAlwaysHits",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 40 if user.has_active_ability?(:NOGUARD) || target.has_active_ability?(:NOGUARD) next Battle::AI::MOVE_USELESS_SCORE if user.has_active_ability?(:NOGUARD) || target.has_active_ability?(:NOGUARD)
next score - 40 if target.effects[PBEffects::Telekinesis] > 0 next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::Telekinesis] > 0
# Prefer if the user knows moves with low accuracy # Prefer if the user knows moves with low accuracy
user.check_for_move do |m| user.check_for_move do |m|
next if target.effects[PBEffects::Minimize] && m.tramplesMinimize? && Settings::MECHANICS_GENERATION >= 6 next if target.effects[PBEffects::Minimize] && m.tramplesMinimize? && Settings::MECHANICS_GENERATION >= 6
@@ -803,9 +804,9 @@ Battle::AI::Handlers::MoveEffectScore.add("EnsureNextMoveAlwaysHits",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndGhostImmunity", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartNegateTargetEvasionStatStageAndGhostImmunity",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 40 if target.effects[PBEffects::Foresight] || user.has_active_ability?(:SCRAPPY) next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::Foresight] || user.has_active_ability?(:SCRAPPY)
# Check if the user knows any moves that would benefit from negating the # Check if the user knows any moves that would benefit from negating the
# target's Ghost type immunity # target's Ghost type immunity
if target.has_type?(:GHOST) if target.has_type?(:GHOST)
@@ -823,9 +824,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndG
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("StartNegateTargetEvasionStatStageAndDarkImmunity", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartNegateTargetEvasionStatStageAndDarkImmunity",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 40 if target.effects[PBEffects::MiracleEye] next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::MiracleEye]
# Check if the user knows any moves that would benefit from negating the # Check if the user knows any moves that would benefit from negating the
# target's Dark type immunity # target's Dark type immunity
if target.has_type?(:DARK) if target.has_type?(:DARK)
@@ -863,7 +864,7 @@ Battle::AI::Handlers::MoveBasePower.add("TypeDependsOnUserIVs",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TypeAndPowerDependOnUserBerry", Battle::AI::Handlers::MoveFailureCheck.add("TypeAndPowerDependOnUserBerry",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
item = user.item item = user.item
next true if !item || !item.is_berry? || !user.item_active? next true if !item || !item.is_berry? || !user.item_active?
next true if item.flags.none? { |f| f[/^NaturalGift_/i] } next true if item.flags.none? { |f| f[/^NaturalGift_/i] }
@@ -895,7 +896,7 @@ Battle::AI::Handlers::MoveBasePower.add("TypeAndPowerDependOnUserBerry",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TypeDependsOnUserMorpekoFormRaiseUserSpeed1", Battle::AI::Handlers::MoveFailureCheck.add("TypeDependsOnUserMorpekoFormRaiseUserSpeed1",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !user.battler.isSpecies?(:MORPEKO) && user.effects[PBEffects::TransformSpecies] != :MORPEKO next true if !user.battler.isSpecies?(:MORPEKO) && user.effects[PBEffects::TransformSpecies] != :MORPEKO
} }
) )
@@ -920,15 +921,15 @@ Battle::AI::Handlers::MoveBasePower.copy("TypeAndPowerDependOnWeather",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("TargetMovesBecomeElectric", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetMovesBecomeElectric",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next 0 if user.faster_than?(target) next Battle::AI::MOVE_USELESS_SCORE if user.faster_than?(target)
} }
) )
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
# TODO: This code can be called with or without a target. Make sure it doesn't # TODO: This code can be called with a single target and with no targets. Make
# assume that there is a target. # sure it doesn't assume that there is a target.
#=============================================================================== #===============================================================================
# NormalMovesBecomeElectric # NormalMovesBecomeElectric

View File

@@ -6,7 +6,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes",
next power * move.move.pbNumHits(user.battler, [target.battler]) next power * move.move.pbNumHits(user.battler, [target.battler])
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimes", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimes",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Prefer if the target has a Substitute and the first hit can break it # Prefer if the target has a Substitute and the first hit can break it
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
@@ -24,13 +24,13 @@ Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimes",
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes", Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes",
"HitTwoTimesPoisonTarget") "HitTwoTimesPoisonTarget")
Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesPoisonTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimesPoisonTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for hitting multiple times # Score for hitting multiple times
score = Battle::AI::Handlers.apply_move_effect_score("HitTwoTimes", score = Battle::AI::Handlers.apply_move_effect_against_target_score("HitTwoTimes",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
# Score for poisoning # Score for poisoning
score = Battle::AI::Handlers.apply_move_effect_score("PoisonTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
next score next score
} }
@@ -41,13 +41,13 @@ Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesPoisonTarget",
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes", Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes",
"HitTwoTimesFlinchTarget") "HitTwoTimesFlinchTarget")
Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesFlinchTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimesFlinchTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for hitting multiple times # Score for hitting multiple times
score = Battle::AI::Handlers.apply_move_effect_score("HitTwoTimes", score = Battle::AI::Handlers.apply_move_effect_against_target_score("HitTwoTimes",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
# Score for flinching # Score for flinching
score = Battle::AI::Handlers.apply_move_effect_score("FlinchTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
next score next score
} }
@@ -70,7 +70,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesPowersUpWithEachHit",
next power * 6 # Hits do x1, x2, x3 ret in turn, for x6 in total next power * 6 # Hits do x1, x2, x3 ret in turn, for x6 in total
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesPowersUpWithEachHit", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitThreeTimesPowersUpWithEachHit",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Prefer if the target has a Substitute and the first or second hit can break it # Prefer if the target has a Substitute and the first or second hit can break it
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
@@ -87,8 +87,8 @@ Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesPowersUpWithEachHit",
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes", Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes",
"HitThreeTimesAlwaysCriticalHit") "HitThreeTimesAlwaysCriticalHit")
Battle::AI::Handlers::MoveEffectScore.copy("HitTwoTimes", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("HitTwoTimes",
"HitThreeTimesAlwaysCriticalHit") "HitThreeTimesAlwaysCriticalHit")
#=============================================================================== #===============================================================================
# #
@@ -99,7 +99,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes",
next power * 31 / 10 # Average damage dealt next power * 31 / 10 # Average damage dealt
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimes", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoToFiveTimes",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Prefer if the target has a Substitute and the first hit(s) can break it # Prefer if the target has a Substitute and the first hit(s) can break it
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
@@ -124,18 +124,18 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja"
next power * 31 / 10 # Average damage dealt next power * 31 / 10 # Average damage dealt
} }
) )
Battle::AI::Handlers::MoveEffectScore.copy("HitTwoToFiveTimes", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("HitTwoToFiveTimes",
"HitTwoToFiveTimesOrThreeForAshGreninja") "HitTwoToFiveTimesOrThreeForAshGreninja")
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("HitTwoToFiveTimes", Battle::AI::Handlers::MoveBasePower.copy("HitTwoToFiveTimes",
"HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1") "HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1")
Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for being a multi-hit attack # Score for being a multi-hit attack
score = Battle::AI::Handlers.apply_move_effect_score("HitTwoToFiveTimes", score = Battle::AI::Handlers.apply_move_effect_against_target_score("HitTwoToFiveTimes",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
# User's stat changes # User's stat changes
aspeed = user.rough_stat(:SPEED) aspeed = user.rough_stat(:SPEED)
@@ -152,7 +152,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUs
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HitOncePerUserTeamMember", Battle::AI::Handlers::MoveFailureCheck.add("HitOncePerUserTeamMember",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
will_fail = true will_fail = true
battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, i| battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, i|
next if !pkmn.able? || pkmn.status != :NONE next if !pkmn.able? || pkmn.status != :NONE
@@ -171,7 +171,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitOncePerUserTeamMember",
next ret next ret
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HitOncePerUserTeamMember", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitOncePerUserTeamMember",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Prefer if the target has a Substitute and the first hit(s) can break it # Prefer if the target has a Substitute and the first hit(s) can break it
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
@@ -191,7 +191,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HitOncePerUserTeamMember",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("AttackAndSkipNextTurn", Battle::AI::Handlers::MoveEffectScore.add("AttackAndSkipNextTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
# Don't prefer because it uses up two turns # Don't prefer because it uses up two turns
score -= 10 if !user.has_active_ability?(:TRUANT) score -= 10 if !user.has_active_ability?(:TRUANT)
# Don't prefer if user is at a high HP (treat this move as a last resort) # Don't prefer if user is at a high HP (treat this move as a last resort)
@@ -204,12 +204,12 @@ Battle::AI::Handlers::MoveEffectScore.add("AttackAndSkipNextTurn",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttack", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttack",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Power Herb makes this a 1 turn move, the same as a move with no effect # Power Herb makes this a 1 turn move, the same as a move with no effect
next score if user.has_active_item?(:POWERHERB) next score if user.has_active_item?(:POWERHERB)
# Treat as a failure if user has Truant (the charging turn has no effect) # Treat as a failure if user has Truant (the charging turn has no effect)
next score - 60 if user.has_active_ability?(:TRUANT) next Battle::AI::MOVE_USELESS_SCORE if user.has_active_ability?(:TRUANT)
# Don't prefer because it uses up two turns # Don't prefer because it uses up two turns
score -= 15 score -= 15
# Don't prefer if user is at a low HP (time is better spent on quicker moves) # Don't prefer if user is at a low HP (time is better spent on quicker moves)
@@ -258,12 +258,12 @@ Battle::AI::Handlers::MoveBasePower.add("TwoTurnAttackOneTurnInSun",
next move.move.pbBaseDamageMultiplier(power, user.battler, target.battler) next move.move.pbBaseDamageMultiplier(power, user.battler, target.battler)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackOneTurnInSun", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackOneTurnInSun",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Sunny weather this a 1 turn move, the same as a move with no effect # Sunny weather this a 1 turn move, the same as a move with no effect
next score if [:Sun, :HarshSun].include?(user.battler.effectiveWeather) next score if [:Sun, :HarshSun].include?(user.battler.effectiveWeather)
# Score for being a two turn attack # Score for being a two turn attack
next Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", next Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
} }
) )
@@ -271,13 +271,13 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackOneTurnInSun",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackParalyzeTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackParalyzeTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for being a two turn attack # Score for being a two turn attack
score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
# Score for paralysing # Score for paralysing
score = Battle::AI::Handlers.apply_move_effect_score("ParalyzeTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
next score next score
} }
@@ -286,13 +286,13 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackParalyzeTarget",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackBurnTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackBurnTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for being a two turn attack # Score for being a two turn attack
score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
# Score for burning # Score for burning
score = Battle::AI::Handlers.apply_move_effect_score("BurnTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
next score next score
} }
@@ -301,13 +301,13 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackBurnTarget",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackFlinchTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackFlinchTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for being a two turn attack # Score for being a two turn attack
score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
# Score for flinching # Score for flinching
score = Battle::AI::Handlers.apply_move_effect_score("FlinchTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
next score next score
} }
@@ -318,12 +318,12 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackFlinchTarget",
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1", Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1",
"TwoTurnAttackRaiseUserSpAtkSpDefSpd2") "TwoTurnAttackRaiseUserSpAtkSpDefSpd2")
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for raising user's stats # Score for raising user's stats
score = ai.get_score_for_user_stat_raise(score) score = ai.get_score_for_user_stat_raise(score)
# Score for being a two turn attack # Score for being a two turn attack
score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
next score next score
} }
@@ -332,14 +332,14 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2"
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserDefense1", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackChargeRaiseUserDefense1",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for being a two turn attack # Score for being a two turn attack
score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
# Score for raising the user's stat # Score for raising the user's stat
score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserDefense1", score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserDefense1",
score, move, user, target, ai, battle) score, move, user, ai, battle)
next score next score
} }
) )
@@ -347,14 +347,14 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserDefense1"
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserSpAtk1", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackChargeRaiseUserSpAtk1",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for being a two turn attack # Score for being a two turn attack
score = Battle::AI::Handlers.apply_move_effect_score("TwoTurnAttack", score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
# Score for raising the user's stat # Score for raising the user's stat
score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserSpAtk1", score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserSpAtk1",
score, move, user, target, ai, battle) score, move, user, ai, battle)
next score next score
} }
) )
@@ -382,7 +382,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserSpAtk1",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TwoTurnAttackInvulnerableInSkyTargetCannotAct", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TwoTurnAttackInvulnerableInSkyTargetCannotAct",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !target.opposes?(user) next true if !target.opposes?(user)
next true if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) next true if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
@@ -417,6 +417,7 @@ Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackPowersUpEachTurn",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
# TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDamage", Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDamage",
proc { |power, move, user, target, ai, battle| proc { |power, move, user, target, ai, battle|
@@ -424,7 +425,7 @@ Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDama
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("MultiTurnAttackBideThenReturnDoubleDamage", Battle::AI::Handlers::MoveEffectScore.add("MultiTurnAttackBideThenReturnDoubleDamage",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if user.hp <= user.totalhp / 4 if user.hp <= user.totalhp / 4
score -= 90 score -= 90
elsif user.hp <= user.totalhp / 2 elsif user.hp <= user.totalhp / 2

View File

@@ -2,14 +2,14 @@
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HealUserFullyAndFallAsleep", Battle::AI::Handlers::MoveFailureCheck.add("HealUserFullyAndFallAsleep",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !user.battler.canHeal? next true if !user.battler.canHeal?
next true if user.battler.asleep? next true if user.battler.asleep?
next true if !user.battler.pbCanSleep?(user.battler, false, move.move, true) next true if !user.battler.pbCanSleep?(user.battler, false, move.move, true)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HealUserFullyAndFallAsleep", Battle::AI::Handlers::MoveEffectScore.add("HealUserFullyAndFallAsleep",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 if user.hp >= user.totalhp * 0.5
score -= 10 score -= 10
@@ -34,12 +34,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserFullyAndFallAsleep",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HealUserHalfOfTotalHP", Battle::AI::Handlers::MoveFailureCheck.add("HealUserHalfOfTotalHP",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !user.battler.canHeal? next true if !user.battler.canHeal?
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHP", Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHP",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 if user.hp >= user.totalhp * 0.5
score -= 10 score -= 10
@@ -56,7 +56,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHP",
Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP", Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP",
"HealUserDependingOnWeather") "HealUserDependingOnWeather")
Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnWeather", Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnWeather",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 if user.hp >= user.totalhp * 0.5
score -= 10 score -= 10
@@ -80,7 +80,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnWeather",
Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP", Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP",
"HealUserDependingOnSandstorm") "HealUserDependingOnSandstorm")
Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnSandstorm", Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnSandstorm",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 if user.hp >= user.totalhp * 0.5
score -= 10 score -= 10
@@ -98,7 +98,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnSandstorm",
Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP", Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP",
"HealUserHalfOfTotalHPLoseFlyingTypeThisTurn") "HealUserHalfOfTotalHPLoseFlyingTypeThisTurn")
Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHPLoseFlyingTypeThisTurn", Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHPLoseFlyingTypeThisTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 if user.hp >= user.totalhp * 0.5
score -= 10 score -= 10
@@ -117,13 +117,13 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHPLoseFlyingTypeTh
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("CureTargetStatusHealUserHalfOfTotalHP", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CureTargetStatusHealUserHalfOfTotalHP",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !user.battler.canHeal? next true if !user.battler.canHeal?
next true if target.status == :NONE next true if target.status == :NONE
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("CureTargetStatusHealUserHalfOfTotalHP", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CureTargetStatusHealUserHalfOfTotalHP",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# TODO: Add high level checks for whether the target wants to lose their # TODO: Add high level checks for whether the target wants to lose their
# status problem, and change the score accordingly. # status problem, and change the score accordingly.
@@ -145,7 +145,7 @@ Battle::AI::Handlers::MoveEffectScore.add("CureTargetStatusHealUserHalfOfTotalHP
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HealUserByTargetAttackLowerTargetAttack1", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserByTargetAttackLowerTargetAttack1",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
if !battle.moldBreaker && target.has_active_ability?(:CONTRARY) if !battle.moldBreaker && target.has_active_ability?(:CONTRARY)
next true if target.statStageAtMax?(:ATTACK) next true if target.statStageAtMax?(:ATTACK)
@@ -154,7 +154,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("HealUserByTargetAttackLowerTargetAtt
end end
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HealUserByTargetAttackLowerTargetAttack1", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByTargetAttackLowerTargetAttack1",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Check whether lowering the target's Attack will have any impact # Check whether lowering the target's Attack will have any impact
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
@@ -188,7 +188,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserByTargetAttackLowerTargetAtta
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("HealUserByHalfOfDamageDone", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByHalfOfDamageDone",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
heal_amt = move.rough_damage / 2 heal_amt = move.rough_damage / 2
@@ -211,18 +211,18 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserByHalfOfDamageDone",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HealUserByHalfOfDamageDoneIfTargetAsleep", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserByHalfOfDamageDoneIfTargetAsleep",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !target.battler.asleep? next true if !target.battler.asleep?
} }
) )
Battle::AI::Handlers::MoveEffectScore.copy("HealUserByHalfOfDamageDone", Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("HealUserByHalfOfDamageDone",
"HealUserByHalfOfDamageDoneIfTargetAsleep") "HealUserByHalfOfDamageDoneIfTargetAsleep")
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("HealUserByThreeQuartersOfDamageDone", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByThreeQuartersOfDamageDone",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
heal_amt = move.rough_damage * 0.75 heal_amt = move.rough_damage * 0.75
@@ -245,64 +245,56 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserByThreeQuartersOfDamageDone",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HealUserAndAlliesQuarterOfTotalHP", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserAndAlliesQuarterOfTotalHP",
proc { |move, user, target, ai, battle|
valid_targets = battle.allSameSideBattlers(user.battler) { |b| b.canHeal? }
next true if valid_targets.empty?
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealUserAndAlliesQuarterOfTotalHP",
proc { |score, move, user, target, ai, battle|
battle.allSameSideBattlers(user.index).each do |b|
next if !b.canHeal?
# Consider how much HP will be restored
if b.hp >= b.totalhp * 0.75
score -= 5
else
score += 15 * (b.totalhp - b.hp) / b.totalhp
end
end
next score
}
)
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HealUserAndAlliesQuarterOfTotalHPCureStatus",
proc { |move, user, target, ai, battle|
valid_targets = battle.allSameSideBattlers(user.battler) { |b| b.canHeal? || b.status != :NONE }
next true if valid_targets.empty?
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealUserAndAlliesQuarterOfTotalHPCureStatus",
proc { |score, move, user, target, ai, battle|
battle.allSameSideBattlers(user.index).each do |b|
next if !b.canHeal? && b.status == :NONE
# Consider how much HP will be restored
if b.hp >= b.totalhp * 0.75
score -= 5
else
score += 15 * (b.totalhp - b.hp) / b.totalhp
end
# Check whether an existing status problem will be removed
score += 10 if user.status != :NONE
end
next score
}
)
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HealTargetHalfOfTotalHP",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !target.battler.canHeal? next true if !target.battler.canHeal?
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HealTargetHalfOfTotalHP", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserAndAlliesQuarterOfTotalHP",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 40 if user.opposes?(target) # Consider how much HP will be restored
if target.hp >= target.totalhp * 0.75
score -= 5
else
score += 15 * (target.totalhp - target.hp) / target.totalhp
end
next score
}
)
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserAndAlliesQuarterOfTotalHPCureStatus",
proc { |move, user, target, ai, battle|
next true if !target.battler.canHeal? && target.status == :NONE
}
)
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserAndAlliesQuarterOfTotalHPCureStatus",
proc { |score, move, user, target, ai, battle|
# Consider how much HP will be restored
if target.hp >= target.totalhp * 0.75
score -= 5
else
score += 15 * (target.totalhp - target.hp) / target.totalhp
end
# Check whether an existing status problem will be removed
score += 10 if target.status != :NONE
next score
}
)
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealTargetHalfOfTotalHP",
proc { |move, user, target, ai, battle|
next true if !target.battler.canHeal?
}
)
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealTargetHalfOfTotalHP",
proc { |score, move, user, target, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if target.opposes?(user)
# Consider how much HP will be restored # Consider how much HP will be restored
heal_amt = target.totalhp / 2 heal_amt = target.totalhp / 2
heal_amt = target.totalhp * 0.75 if move.move.pulseMove? && heal_amt = target.totalhp * 0.75 if move.move.pulseMove? &&
@@ -320,11 +312,11 @@ Battle::AI::Handlers::MoveEffectScore.add("HealTargetHalfOfTotalHP",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("HealTargetHalfOfTotalHP", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("HealTargetHalfOfTotalHP",
"HealTargetDependingOnGrassyTerrain") "HealTargetDependingOnGrassyTerrain")
Battle::AI::Handlers::MoveEffectScore.add("HealTargetDependingOnGrassyTerrain", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealTargetDependingOnGrassyTerrain",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 40 if user.opposes?(target) next Battle::AI::MOVE_USELESS_SCORE if user.opposes?(target)
# Consider how much HP will be restored # Consider how much HP will be restored
heal_amt = target.totalhp / 2 heal_amt = target.totalhp / 2
heal_amt = (target.totalhp * 2 / 3.0).round if battle.field.terrain == :Grassy heal_amt = (target.totalhp * 2 / 3.0).round if battle.field.terrain == :Grassy
@@ -342,12 +334,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HealTargetDependingOnGrassyTerrain",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HealUserPositionNextTurn", Battle::AI::Handlers::MoveFailureCheck.add("HealUserPositionNextTurn",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if battle.positions[user.index].effects[PBEffects::Wish] > 0 next true if battle.positions[user.index].effects[PBEffects::Wish] > 0
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HealUserPositionNextTurn", Battle::AI::Handlers::MoveEffectScore.add("HealUserPositionNextTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 if user.hp >= user.totalhp * 0.5
score -= 10 score -= 10
@@ -362,12 +354,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserPositionNextTurn",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurn", Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurn",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.effects[PBEffects::AquaRing] next true if user.effects[PBEffects::AquaRing]
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurn", Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score += 10 score += 10
score += 10 if user.has_active_item?(:BIGROOT) score += 10 if user.has_active_item?(:BIGROOT)
next score next score
@@ -378,12 +370,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurn",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurnTrapUserInBattle", Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurnTrapUserInBattle",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.effects[PBEffects::Ingrain] next true if user.effects[PBEffects::Ingrain]
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurnTrapUserInBattle", Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurnTrapUserInBattle",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score += 5 score += 5
score += 10 if user.turnCount < 2 score += 10 if user.turnCount < 2
score += 10 if user.has_active_item?(:BIGROOT) score += 10 if user.has_active_item?(:BIGROOT)
@@ -394,14 +386,14 @@ Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurnTrapUserInBattle
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartDamageTargetEachTurnIfTargetAsleep", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartDamageTargetEachTurnIfTargetAsleep",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !target.battler.asleep? || target.effects[PBEffects::Nightmare] next true if !target.battler.asleep? || target.effects[PBEffects::Nightmare]
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartDamageTargetEachTurnIfTargetAsleep", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartDamageTargetEachTurnIfTargetAsleep",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 40 if target.statusCount <= 1 next Battle::AI::MOVE_USELESS_SCORE if target.statusCount <= 1
next score + 10 * target.statusCount next score + 10 * target.statusCount
} }
) )
@@ -409,13 +401,13 @@ Battle::AI::Handlers::MoveEffectScore.add("StartDamageTargetEachTurnIfTargetAsle
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartLeechSeedTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartLeechSeedTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::LeechSeed] >= 0 next true if target.effects[PBEffects::LeechSeed] >= 0
next true if target.has_type?(:GRASS) next true if target.has_type?(:GRASS)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartLeechSeedTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartLeechSeedTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score += 10 if user.turnCount < 2 score += 10 if user.turnCount < 2
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
@@ -440,7 +432,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartLeechSeedTarget",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHP", Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHP",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score -= 15 # User will lose 50% HP, don't prefer this move score -= 15 # User will lose 50% HP, don't prefer this move
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
score += 10 if user.hp >= user.totalhp * 0.75 # User at 75% HP or more score += 10 if user.hp >= user.totalhp * 0.75 # User at 75% HP or more
@@ -463,7 +455,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHP",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UserLosesHalfOfTotalHPExplosive", Battle::AI::Handlers::MoveFailureCheck.add("UserLosesHalfOfTotalHPExplosive",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !battle.moldBreaker && battle.pbCheckGlobalAbility(:DAMP) next true if !battle.moldBreaker && battle.pbCheckGlobalAbility(:DAMP)
} }
) )
@@ -476,7 +468,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("UserLosesHalfOfTotalHP",
Battle::AI::Handlers::MoveFailureCheck.copy("UserLosesHalfOfTotalHPExplosive", Battle::AI::Handlers::MoveFailureCheck.copy("UserLosesHalfOfTotalHPExplosive",
"UserFaintsExplosive") "UserFaintsExplosive")
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsExplosive", Battle::AI::Handlers::MoveEffectScore.add("UserFaintsExplosive",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score -= 25 # User will faint, don't prefer this move score -= 25 # User will faint, don't prefer this move
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
score -= 10 if user.hp >= user.totalhp * 0.5 # User at 50% HP or more score -= 10 if user.hp >= user.totalhp * 0.5 # User at 50% HP or more
@@ -522,10 +514,10 @@ Battle::AI::Handlers::MoveEffectScore.copy("UserFaintsExplosive",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsLowerTargetAtkSpAtk2", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserFaintsLowerTargetAtkSpAtk2",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 40 if !target.battler.pbCanLowerStatStage?(:ATTACK, user.battler) && next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanLowerStatStage?(:ATTACK, user.battler) &&
!target.battler.pbCanLowerStatStage?(:SPECIAL_ATTACK, user.battler) !target.battler.pbCanLowerStatStage?(:SPECIAL_ATTACK, user.battler)
score -= 25 # User will faint, don't prefer this move score -= 25 # User will faint, don't prefer this move
# Check the impact of lowering the target's stats # Check the impact of lowering the target's stats
if target.stages[:ATTACK] < 0 && target.stages[:SPECIAL_ATTACK] < 0 if target.stages[:ATTACK] < 0 && target.stages[:SPECIAL_ATTACK] < 0
@@ -552,12 +544,12 @@ Battle::AI::Handlers::MoveEffectScore.add("UserFaintsLowerTargetAtkSpAtk2",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UserFaintsHealAndCureReplacement", Battle::AI::Handlers::MoveFailureCheck.add("UserFaintsHealAndCureReplacement",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !battle.pbCanChooseNonActive?(user.index) next true if !battle.pbCanChooseNonActive?(user.index)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsHealAndCureReplacement", Battle::AI::Handlers::MoveEffectScore.add("UserFaintsHealAndCureReplacement",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score -= 25 # User will faint, don't prefer this move score -= 25 # User will faint, don't prefer this move
# Check whether the replacement user needs healing, and don't make the below # Check whether the replacement user needs healing, and don't make the below
# calculations if not # calculations if not
@@ -568,7 +560,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserFaintsHealAndCureReplacement",
need_healing = true need_healing = true
break break
end end
next score - 15 if !need_healing next Battle::AI::MOVE_USELESS_SCORE if !need_healing
end end
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
score -= 10 if user.hp >= user.totalhp * 0.5 # User at 50% HP or more score -= 10 if user.hp >= user.totalhp * 0.5 # User at 50% HP or more
@@ -594,23 +586,18 @@ Battle::AI::Handlers::MoveEffectScore.copy("UserFaintsHealAndCureReplacement",
"UserFaintsHealAndCureReplacementRestorePP") "UserFaintsHealAndCureReplacementRestorePP")
#=============================================================================== #===============================================================================
# # TODO: This code should be for a single battler (each is checked in turn).
# Should have a MoveEffectAgainstTargetScore instead.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartPerishCountsForAllBattlers", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartPerishCountsForAllBattlers",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
will_fail = true next true if target.effects[PBEffects::PerishSong] > 0
battle.allBattlers.each do |b| next true if Battle::AbilityEffects.triggerMoveImmunity(target.ability, user.battler, target.battler,
next if b.effects[PBEffects::PerishSong] > 0 move.move, move.rough_type, battle, false)
next if Battle::AbilityEffects.triggerMoveImmunity(b.ability, user.battler, b,
move.move, move.rough_type, battle, false)
will_fail = false
break
end
next will_fail
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers", Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score -= 15 score -= 15
# Check which battlers will be affected by this move # Check which battlers will be affected by this move
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
@@ -628,7 +615,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers",
allies_affected += 1 allies_affected += 1
end end
end end
next score - 25 if foes_affected == 0 next Battle::AI::MOVE_USELESS_SCORE if foes_affected == 0
score += 15 if allies_affected == 0 # No downside for user; cancel out inherent negative score score += 15 if allies_affected == 0 # No downside for user; cancel out inherent negative score
score += 15 * (foes_affected - allies_affected) score += 15 * (foes_affected - allies_affected)
score += 5 * foes_with_high_hp score += 5 * foes_with_high_hp
@@ -650,12 +637,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("AttackerFaintsIfUserFaints", Battle::AI::Handlers::MoveFailureCheck.add("AttackerFaintsIfUserFaints",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next Settings::MECHANICS_GENERATION >= 7 && user.effects[PBEffects::DestinyBondPrevious] next Settings::MECHANICS_GENERATION >= 7 && user.effects[PBEffects::DestinyBondPrevious]
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("AttackerFaintsIfUserFaints", Battle::AI::Handlers::MoveEffectScore.add("AttackerFaintsIfUserFaints",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score -= 25 score -= 25
# Check whether user is faster than its foe(s) and could use this move # Check whether user is faster than its foe(s) and could use this move
user_faster_count = 0 user_faster_count = 0
@@ -679,7 +666,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AttackerFaintsIfUserFaints",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("SetAttackerMovePPTo0IfUserFaints", Battle::AI::Handlers::MoveEffectScore.add("SetAttackerMovePPTo0IfUserFaints",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score -= 25 score -= 25
# Check whether user is faster than its foe(s) and could use this move # Check whether user is faster than its foe(s) and could use this move
user_faster_count = 0 user_faster_count = 0

View File

@@ -1,7 +1,7 @@
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("UserTakesTargetItem", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTakesTargetItem",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if user.wild? || user.item next score if user.wild? || user.item
next score if !target.item || target.battler.unlosableItem?(target.item) next score if !target.item || target.battler.unlosableItem?(target.item)
@@ -22,13 +22,13 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTakesTargetItem",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TargetTakesUserItem", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetTakesUserItem",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !user.item || user.battler.unlosableItem?(user.item) next true if !user.item || user.battler.unlosableItem?(user.item)
next true if target.item || target.battler.unlosableItem?(user.item) next true if target.item || target.battler.unlosableItem?(user.item)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("TargetTakesUserItem", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetTakesUserItem",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
user_item_preference = ai.battler_wants_item?(user, user.item_id) user_item_preference = ai.battler_wants_item?(user, user.item_id)
user_no_item_preference = ai.battler_wants_item?(user, :NONE) user_no_item_preference = ai.battler_wants_item?(user, :NONE)
@@ -43,7 +43,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetTakesUserItem",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UserTargetSwapItems", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("UserTargetSwapItems",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if user.wild? next true if user.wild?
next true if !user.item && !target.item next true if !user.item && !target.item
@@ -52,7 +52,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserTargetSwapItems",
next true if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker next true if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapItems", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapItems",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
user_new_item_preference = ai.battler_wants_item?(user, target.item_id) user_new_item_preference = ai.battler_wants_item?(user, target.item_id)
user_old_item_preference = ai.battler_wants_item?(user, user.item_id) user_old_item_preference = ai.battler_wants_item?(user, user.item_id)
@@ -71,12 +71,12 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapItems",
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("RestoreUserConsumedItem", Battle::AI::Handlers::MoveFailureCheck.add("RestoreUserConsumedItem",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !user.battler.recycleItem || user.item next true if !user.battler.recycleItem || user.item
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem", Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
user_new_item_preference = ai.battler_wants_item?(user, user.battler.recycleItem) user_new_item_preference = ai.battler_wants_item?(user, user.battler.recycleItem)
user_old_item_preference = ai.battler_wants_item?(user, user.item_id) user_old_item_preference = ai.battler_wants_item?(user, user.item_id)
score += (user_new_item_preference - user_old_item_preference) * 8 score += (user_new_item_preference - user_old_item_preference) * 8
@@ -92,7 +92,7 @@ Battle::AI::Handlers::MoveBasePower.add("RemoveTargetItem",
next move.move.pbBaseDamage(power, user.battler, target.battler) next move.move.pbBaseDamage(power, user.battler, target.battler)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("RemoveTargetItem", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RemoveTargetItem",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if user.wild? next score if user.wild?
next score if !target.item || target.battler.unlosableItem?(target.item) next score if !target.item || target.battler.unlosableItem?(target.item)
@@ -109,7 +109,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveTargetItem",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DestroyTargetBerryOrGem", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DestroyTargetBerryOrGem",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if !target.item || (!target.item.is_berry? && next score if !target.item || (!target.item.is_berry? &&
!(Settings::MECHANICS_GENERATION >= 6 && target.item.is_gem?)) !(Settings::MECHANICS_GENERATION >= 6 && target.item.is_gem?))
@@ -127,7 +127,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DestroyTargetBerryOrGem",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("CorrodeTargetItem", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CorrodeTargetItem",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !target.item || target.unlosableItem?(target.item) || next true if !target.item || target.unlosableItem?(target.item) ||
target.effects[PBEffects::Substitute] > 0 target.effects[PBEffects::Substitute] > 0
@@ -135,7 +135,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("CorrodeTargetItem",
next true if battle.corrosiveGas[target.index % 2][target.party_index] next true if battle.corrosiveGas[target.index % 2][target.party_index]
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("CorrodeTargetItem", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CorrodeTargetItem",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if target.item_active? if target.item_active?
score += 30 score += 30
@@ -149,25 +149,20 @@ Battle::AI::Handlers::MoveEffectScore.add("CorrodeTargetItem",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartTargetCannotUseItem", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartTargetCannotUseItem",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Embargo] > 0 next true if target.effects[PBEffects::Embargo] > 0
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("StartTargetCannotUseItem",
proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::Embargo] > 0
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
# TODO: This code shouldn't make use of target. # TODO: This code shouldn't make use of target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems", Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score - 40 if battle.field.effects[PBEffects::MagicRoom] > 0 next Battle::AI::MOVE_USELESS_SCORE if battle.field.effects[PBEffects::MagicRoom] > 0
next score + 30 if !user.item && target.item next score + 30 if !user.item # && target.item
} }
) )
@@ -175,13 +170,13 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UserConsumeBerryRaiseDefense2", Battle::AI::Handlers::MoveFailureCheck.add("UserConsumeBerryRaiseDefense2",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
item = user.item item = user.item
next true if !item || !item.is_berry? || !user.item_active? next true if !item || !item.is_berry? || !user.item_active?
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("UserConsumeBerryRaiseDefense2", Battle::AI::Handlers::MoveEffectScore.add("UserConsumeBerryRaiseDefense2",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if ai.trainer.high_skill? if ai.trainer.high_skill?
useful_berries = [ useful_berries = [
:ORANBERRY, :SITRUSBERRY, :AGUAVBERRY, :APICOTBERRY, :CHERIBERRY, :ORANBERRY, :SITRUSBERRY, :AGUAVBERRY, :APICOTBERRY, :CHERIBERRY,
@@ -206,14 +201,14 @@ Battle::AI::Handlers::MoveEffectScore.add("UserConsumeBerryRaiseDefense2",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
# TODO: This code shouldn't make use of target. # TODO: This code should be for a single battler (each is checked in turn).
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("AllBattlersConsumeBerry", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AllBattlersConsumeBerry",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !target.item || !target.item.is_berry? || target.battler.semiInvulnerable? next true if !target.item || !target.item.is_berry? || target.battler.semiInvulnerable?
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("AllBattlersConsumeBerry", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AllBattlersConsumeBerry",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
useful_berries = [ useful_berries = [
:ORANBERRY, :SITRUSBERRY, :AGUAVBERRY, :APICOTBERRY, :CHERIBERRY, :ORANBERRY, :SITRUSBERRY, :AGUAVBERRY, :APICOTBERRY, :CHERIBERRY,
@@ -252,7 +247,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AllBattlersConsumeBerry",
#=============================================================================== #===============================================================================
# #
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("UserConsumeTargetBerry", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserConsumeTargetBerry",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if !target.item || !target.item.is_berry? next score if !target.item || !target.item.is_berry?
next score if user.battler.unlosableItem?(target.item) next score if user.battler.unlosableItem?(target.item)
@@ -270,7 +265,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserConsumeTargetBerry",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ThrowUserItemAtTarget", Battle::AI::Handlers::MoveFailureCheck.add("ThrowUserItemAtTarget",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
item = user.item item = user.item
next true if !item || !user.item_active? || user.battler.unlosableItem?(item) next true if !item || !user.item_active? || user.battler.unlosableItem?(item)
next true if item.is_berry? && !user.battler.canConsumeBerry? next true if item.is_berry? && !user.battler.canConsumeBerry?

View File

@@ -2,6 +2,15 @@
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("RedirectAllMovesToUser", Battle::AI::Handlers::MoveEffectScore.add("RedirectAllMovesToUser",
proc { |score, move, user, ai, battle|
next 0 if user.battler.allAllies.length == 0
}
)
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RedirectAllMovesToTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next 0 if user.battler.allAllies.length == 0 next 0 if user.battler.allAllies.length == 0
} }
@@ -10,16 +19,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RedirectAllMovesToUser",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("RedirectAllMovesToTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CannotBeRedirected",
proc { |score, move, user, target, ai, battle|
next 0 if user.battler.allAllies.length == 0
}
)
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("CannotBeRedirected",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
redirection = false redirection = false
user.battler.allOpposing.each do |b| user.battler.allOpposing.each do |b|
@@ -50,12 +50,12 @@ Battle::AI::Handlers::MoveBasePower.add("RandomlyDamageOrHealTarget",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HealAllyOrDamageFoe", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealAllyOrDamageFoe",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !target.opposes?(user) && target.battler.canHeal? next true if !target.opposes?(user) && target.battler.canHeal?
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HealAllyOrDamageFoe", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealAllyOrDamageFoe",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if !target.opposes?(user) if !target.opposes?(user)
score += 50 score += 50
@@ -69,32 +69,39 @@ Battle::AI::Handlers::MoveEffectScore.add("HealAllyOrDamageFoe",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("CurseTargetOrLowerUserSpd1RaiseUserAtkDef1", Battle::AI::Handlers::MoveFailureCheck.add("CurseTargetOrLowerUserSpd1RaiseUserAtkDef1",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
if user.has_type?(:GHOST) if !user.has_type?(:GHOST)
next true if target.effects[PBEffects::Curse]
else
next true if !user.battler.pbCanLowerStatStage?(:SPEED, user.battler, move.move) && next true if !user.battler.pbCanLowerStatStage?(:SPEED, user.battler, move.move) &&
!user.battler.pbCanRaiseStatStage?(:ATTACK, user.battler, move.move) && !user.battler.pbCanRaiseStatStage?(:ATTACK, user.battler, move.move) &&
!user.battler.pbCanRaiseStatStage?(:DEFENSE, user.battler, move.move) !user.battler.pbCanRaiseStatStage?(:DEFENSE, user.battler, move.move)
end end
} }
) )
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CurseTargetOrLowerUserSpd1RaiseUserAtkDef1",
proc { |move, user, target, ai, battle|
next true if user.has_type?(:GHOST) && target.effects[PBEffects::Curse]
}
)
Battle::AI::Handlers::MoveEffectScore.add("CurseTargetOrLowerUserSpd1RaiseUserAtkDef1", Battle::AI::Handlers::MoveEffectScore.add("CurseTargetOrLowerUserSpd1RaiseUserAtkDef1",
proc { |score, move, user, ai, battle|
next score if user.has_type?(:GHOST)
avg = user.stages[:SPEED] * 10
avg -= user.stages[:ATTACK] * 10
avg -= user.stages[:DEFENSE] * 10
score += avg / 3
next score
}
)
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CurseTargetOrLowerUserSpd1RaiseUserAtkDef1",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if user.has_type?(:GHOST) next score if !user.has_type?(:GHOST)
if user.hp <= user.totalhp / 2 if user.hp <= user.totalhp / 2
if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
score -= 90 score -= 90
else else
score -= 50 score -= 50
score -= 30 if battle.switchStyle score -= 30 if battle.switchStyle
end
end end
else
avg = user.stages[:SPEED] * 10
avg -= user.stages[:ATTACK] * 10
avg -= user.stages[:DEFENSE] * 10
score += avg / 3
end end
next score next score
} }
@@ -114,7 +121,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitsAllFoesAndPowersUpInPsychicTerrain"
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HitsAllFoesAndPowersUpInPsychicTerrain", Battle::AI::Handlers::MoveEffectScore.add("HitsAllFoesAndPowersUpInPsychicTerrain",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score + 20 if battle.field.terrain == :Psychic && user.battler.affectedByTerrain? && next score + 20 if battle.field.terrain == :Psychic && user.battler.affectedByTerrain? &&
battle.allOtherSideBattlers(user.index).length > 1 battle.allOtherSideBattlers(user.index).length > 1
} }
@@ -123,12 +130,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HitsAllFoesAndPowersUpInPsychicTerrai
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TargetNextFireMoveDamagesTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetNextFireMoveDamagesTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Powder] next true if target.effects[PBEffects::Powder]
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("TargetNextFireMoveDamagesTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetNextFireMoveDamagesTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
aspeed = user.rough_stat(:SPEED) aspeed = user.rough_stat(:SPEED)
ospeed = target.rough_stat(:SPEED) ospeed = target.rough_stat(:SPEED)
@@ -154,14 +161,13 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetNextFireMoveDamagesTarget",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("PowerUpAllyMove", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PowerUpAllyMove",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.fainted? || target.effects[PBEffects::HelpingHand] next true if target.fainted? || target.effects[PBEffects::HelpingHand]
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("PowerUpAllyMove", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PowerUpAllyMove",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 60 if user.battler.allAllies.empty?
next score + 30 next score + 30
} }
) )
@@ -176,15 +182,15 @@ Battle::AI::Handlers::MoveBasePower.add("CounterPhysicalDamage",
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("CounterPhysicalDamage", Battle::AI::Handlers::MoveEffectScore.add("CounterPhysicalDamage",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score - 40 if target.effects[PBEffects::HyperBeam] > 0 # next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::HyperBeam] > 0
attack = user.rough_stat(:ATTACK) attack = user.rough_stat(:ATTACK)
spatk = user.rough_stat(:SPECIAL_ATTACK) spatk = user.rough_stat(:SPECIAL_ATTACK)
if attack * 1.5 < spatk if attack * 1.5 < spatk
score -= 60 score -= 60
elsif ai.trainer.medium_skill? && target.battler.lastMoveUsed # elsif ai.trainer.medium_skill? && target.battler.lastMoveUsed
moveData = GameData::Move.get(target.battler.lastMoveUsed) # moveData = GameData::Move.get(target.battler.lastMoveUsed)
score += 60 if moveData.physical? # score += 60 if moveData.physical?
end end
next score next score
} }
@@ -200,15 +206,15 @@ Battle::AI::Handlers::MoveBasePower.add("CounterSpecialDamage",
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("CounterSpecialDamage", Battle::AI::Handlers::MoveEffectScore.add("CounterSpecialDamage",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score - 40 if target.effects[PBEffects::HyperBeam] > 0 # next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::HyperBeam] > 0
attack = user.rough_stat(:ATTACK) attack = user.rough_stat(:ATTACK)
spatk = user.rough_stat(:SPECIAL_ATTACK) spatk = user.rough_stat(:SPECIAL_ATTACK)
if attack > spatk * 1.5 if attack > spatk * 1.5
score -= 60 score -= 60
elsif ai.trainer.medium_skill? && target.battler.lastMoveUsed # elsif ai.trainer.medium_skill? && target.battler.lastMoveUsed
moveData = GameData::Move.get(target.battler.lastMoveUsed) # moveData = GameData::Move.get(target.battler.lastMoveUsed)
score += 60 if moveData.special? # score += 60 if moveData.special?
end end
next score next score
} }
@@ -224,8 +230,8 @@ Battle::AI::Handlers::MoveBasePower.add("CounterDamagePlusHalf",
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("CounterDamagePlusHalf", Battle::AI::Handlers::MoveEffectScore.add("CounterDamagePlusHalf",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score - 40 if target.effects[PBEffects::HyperBeam] > 0 # next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::HyperBeam] > 0
} }
) )
@@ -233,12 +239,12 @@ Battle::AI::Handlers::MoveEffectScore.add("CounterDamagePlusHalf",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UserAddStockpileRaiseDefSpDef1", Battle::AI::Handlers::MoveFailureCheck.add("UserAddStockpileRaiseDefSpDef1",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.effects[PBEffects::Stockpile] >= 3 next true if user.effects[PBEffects::Stockpile] >= 3
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("UserAddStockpileRaiseDefSpDef1", Battle::AI::Handlers::MoveEffectScore.add("UserAddStockpileRaiseDefSpDef1",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
avg = 0 avg = 0
avg -= user.stages[:DEFENSE] * 10 avg -= user.stages[:DEFENSE] * 10
avg -= user.stages[:SPECIAL_DEFENSE] * 10 avg -= user.stages[:SPECIAL_DEFENSE] * 10
@@ -255,7 +261,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserAddStockpileRaiseDefSpDef1",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("PowerDependsOnUserStockpile", Battle::AI::Handlers::MoveFailureCheck.add("PowerDependsOnUserStockpile",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.effects[PBEffects::Stockpile] == 0 next true if user.effects[PBEffects::Stockpile] == 0
} }
) )
@@ -269,7 +275,7 @@ Battle::AI::Handlers::MoveBasePower.add("PowerDependsOnUserStockpile",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HealUserDependingOnUserStockpile", Battle::AI::Handlers::MoveFailureCheck.add("HealUserDependingOnUserStockpile",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.effects[PBEffects::Stockpile] == 0 next true if user.effects[PBEffects::Stockpile] == 0
next true if !user.battler.canHeal? && next true if !user.battler.canHeal? &&
user.effects[PBEffects::StockpileDef] == 0 && user.effects[PBEffects::StockpileDef] == 0 &&
@@ -277,7 +283,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("HealUserDependingOnUserStockpile",
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnUserStockpile", Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnUserStockpile",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
mult = [0, 25, 50, 100][user.effects[PBEffects::Stockpile]] mult = [0, 25, 50, 100][user.effects[PBEffects::Stockpile]]
score += mult score += mult
score -= user.hp * mult * 2 / user.totalhp score -= user.hp * mult * 2 / user.totalhp
@@ -304,7 +310,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnUserStockpile",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UseLastMoveUsed", Battle::AI::Handlers::MoveFailureCheck.add("UseLastMoveUsed",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !battle.lastMoveUsed next true if !battle.lastMoveUsed
next true if move.move.moveBlacklist.include?(GameData::Move.get(battle.lastMoveUsed).function_code) next true if move.move.moveBlacklist.include?(GameData::Move.get(battle.lastMoveUsed).function_code)
} }
@@ -313,15 +319,15 @@ Battle::AI::Handlers::MoveFailureCheck.add("UseLastMoveUsed",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UseLastMoveUsedByTarget", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("UseLastMoveUsedByTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !target.battler.lastRegularMoveUsed next true if !target.battler.lastRegularMoveUsed
next true if GameData::Move.get(target.battler.lastRegularMoveUsed).flags.none? { |f| f[/^CanMirrorMove$/i] } next true if GameData::Move.get(target.battler.lastRegularMoveUsed).flags.none? { |f| f[/^CanMirrorMove$/i] }
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("UseLastMoveUsedByTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UseLastMoveUsedByTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 40 next Battle::AI::MOVE_USELESS_SCORE
} }
) )
@@ -345,7 +351,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UseLastMoveUsedByTarget",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UseRandomMoveFromUserParty", Battle::AI::Handlers::MoveFailureCheck.add("UseRandomMoveFromUserParty",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
will_fail = true will_fail = true
battle.pbParty(user.index).each_with_index do |pkmn, i| battle.pbParty(user.index).each_with_index do |pkmn, i|
next if !pkmn || i == user.party_index next if !pkmn || i == user.party_index
@@ -366,7 +372,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UseRandomMoveFromUserParty",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UseRandomUserMoveIfAsleep", Battle::AI::Handlers::MoveFailureCheck.add("UseRandomUserMoveIfAsleep",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !user.battler.asleep? next true if !user.battler.asleep?
will_fail = true will_fail = true
user.battler.eachMoveWithIndex do |m, i| user.battler.eachMoveWithIndex do |m, i|
@@ -378,11 +384,6 @@ Battle::AI::Handlers::MoveFailureCheck.add("UseRandomUserMoveIfAsleep",
next will_fail next will_fail
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("UseRandomUserMoveIfAsleep",
proc { |score, move, user, target, ai, battle|
next score + 50 if user.battler.asleep? # Because it can only be used while asleep
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
@@ -399,7 +400,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UseRandomUserMoveIfAsleep",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ReplaceMoveThisBattleWithTargetLastMoveUsed", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ReplaceMoveThisBattleWithTargetLastMoveUsed",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Transform] || user.battler.pbHasMove?(move.id) next true if user.effects[PBEffects::Transform] || user.battler.pbHasMove?(move.id)
last_move_data = GameData::Move.try_get(target.battler.lastRegularMoveUsed) last_move_data = GameData::Move.try_get(target.battler.lastRegularMoveUsed)
@@ -413,7 +414,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("ReplaceMoveThisBattleWithTargetLastM
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ReplaceMoveWithTargetLastMoveUsed", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ReplaceMoveWithTargetLastMoveUsed",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Transform] || !user.battler.pbHasMove?(move.id) next true if user.effects[PBEffects::Transform] || !user.battler.pbHasMove?(move.id)
last_move_data = GameData::Move.try_get(target.battler.lastRegularMoveUsed) last_move_data = GameData::Move.try_get(target.battler.lastRegularMoveUsed)

View File

@@ -2,7 +2,7 @@
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FleeFromBattle", Battle::AI::Handlers::MoveFailureCheck.add("FleeFromBattle",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !battle.pbCanRun?(user.index) next true if !battle.pbCanRun?(user.index)
} }
) )
@@ -11,7 +11,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FleeFromBattle",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserStatusMove", Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserStatusMove",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
if user.wild? if user.wild?
next true if !battle.pbCanRun?(user.index) next true if !battle.pbCanRun?(user.index)
else else
@@ -20,7 +20,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserStatusMove",
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserStatusMove", Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserStatusMove",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next score + 10 if user.wild? next score + 10 if user.wild?
if battle.pbTeamAbleNonActiveCount(user.index) > 1 # Don't switch in ace if battle.pbTeamAbleNonActiveCount(user.index) > 1 # Don't switch in ace
score -= 60 score -= 60
@@ -50,7 +50,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserStatusMove",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserDamagingMove", Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserDamagingMove",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
next 0 if !battle.pbCanChooseNonActive?(user.index) || next 0 if !battle.pbCanChooseNonActive?(user.index) ||
battle.pbTeamAbleNonActiveCount(user.index) > 1 # Don't switch in ace battle.pbTeamAbleNonActiveCount(user.index) > 1 # Don't switch in ace
} }
@@ -58,8 +58,9 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserDamagingMove",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
# TODO: Might need both MoveEffectScore and MoveEffectAgainstTargetScore.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetAtkSpAtk1SwitchOutUser", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetAtkSpAtk1SwitchOutUser",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
will_fail = true will_fail = true
(move.move.statDown.length / 2).times do |i| (move.move.statDown.length / 2).times do |i|
@@ -70,7 +71,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetAtkSpAtk1SwitchOutUser",
next will_fail next will_fail
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAtkSpAtk1SwitchOutUser", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAtkSpAtk1SwitchOutUser",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
avg = target.stages[:ATTACK] * 10 avg = target.stages[:ATTACK] * 10
avg += target.stages[:SPECIAL_ATTACK] * 10 avg += target.stages[:SPECIAL_ATTACK] * 10
@@ -83,12 +84,12 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAtkSpAtk1SwitchOutUser",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserPassOnEffects", Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserPassOnEffects",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if !battle.pbCanChooseNonActive?(user.index) next true if !battle.pbCanChooseNonActive?(user.index)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserPassOnEffects", Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserPassOnEffects",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if battle.pbCanChooseNonActive?(user.index) if battle.pbCanChooseNonActive?(user.index)
score -= 40 if user.effects[PBEffects::Confusion] > 0 score -= 40 if user.effects[PBEffects::Confusion] > 0
total = 0 total = 0
@@ -116,7 +117,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserPassOnEffects",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutTargetStatusMove", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SwitchOutTargetStatusMove",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if (!battle.moldBreaker && target.has_active_ability?(:SUCTIONCUPS)) || next true if (!battle.moldBreaker && target.has_active_ability?(:SUCTIONCUPS)) ||
target.effects[PBEffects::Ingrain] target.effects[PBEffects::Ingrain]
@@ -133,7 +134,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutTargetStatusMove",
end end
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetStatusMove", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SwitchOutTargetStatusMove",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score += 20 if target.pbOwnSide.effects[PBEffects::Spikes] > 0 score += 20 if target.pbOwnSide.effects[PBEffects::Spikes] > 0
score += 20 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0 score += 20 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0
@@ -145,7 +146,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetStatusMove",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetDamagingMove", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SwitchOutTargetDamagingMove",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if (battle.moldBreaker || !target.has_active_ability?(:SUCTIONCUPS)) && if (battle.moldBreaker || !target.has_active_ability?(:SUCTIONCUPS)) &&
!target.effects[PBEffects::Ingrain] !target.effects[PBEffects::Ingrain]
@@ -160,7 +161,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetDamagingMove",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("BindTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score + 40 if target.effects[PBEffects::Trapping] == 0 next score + 40 if target.effects[PBEffects::Trapping] == 0
} }
@@ -174,7 +175,7 @@ Battle::AI::Handlers::MoveBasePower.add("BindTargetDoublePowerIfTargetUnderwater
next move.move.pbModifyDamage(power, user.battler, target.battler) next move.move.pbModifyDamage(power, user.battler, target.battler)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("BindTargetDoublePowerIfTargetUnderwater", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTargetDoublePowerIfTargetUnderwater",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score + 40 if target.effects[PBEffects::Trapping] == 0 next score + 40 if target.effects[PBEffects::Trapping] == 0
} }
@@ -183,7 +184,7 @@ Battle::AI::Handlers::MoveEffectScore.add("BindTargetDoublePowerIfTargetUnderwat
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TrapTargetInBattle",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
if move.statusMove? if move.statusMove?
next true if target.effects[PBEffects::MeanLook] >= 0 next true if target.effects[PBEffects::MeanLook] >= 0
@@ -195,7 +196,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
if move.statusMove? if move.statusMove?
next true if target.effects[PBEffects::Octolock] >= 0 next true if target.effects[PBEffects::Octolock] >= 0
@@ -203,7 +204,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle",
end end
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score += 30 if !target.battler.trappedInBattle? score += 30 if !target.battler.trappedInBattle?
score -= 50 if !target.battler.pbCanLowerStatStage?(:DEFENSE, user.battler, move.move) && score -= 50 if !target.battler.pbCanLowerStatStage?(:DEFENSE, user.battler, move.move) &&
@@ -215,7 +216,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TrapTargetInBattleLowerTargetDefSpDef
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("TrapUserAndTargetInBattle", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapUserAndTargetInBattle",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::JawLock] < 0 if target.effects[PBEffects::JawLock] < 0
score += 40 if !user.battler.trappedInBattle? && !target.battler.trappedInBattle? score += 40 if !user.battler.trappedInBattle? && !target.battler.trappedInBattle?
@@ -228,7 +229,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TrapUserAndTargetInBattle",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TrapAllBattlersInBattleForOneTurn", Battle::AI::Handlers::MoveFailureCheck.add("TrapAllBattlersInBattleForOneTurn",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if battle.field.effects[PBEffects::FairyLock] > 0 next true if battle.field.effects[PBEffects::FairyLock] > 0
} }
) )
@@ -240,16 +241,17 @@ Battle::AI::Handlers::MoveFailureCheck.add("TrapAllBattlersInBattleForOneTurn",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
# TODO: Consider all foes rather than just target. Can't use "target".
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("UsedAfterUserTakesPhysicalDamage", Battle::AI::Handlers::MoveEffectScore.add("UsedAfterUserTakesPhysicalDamage",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
hasPhysicalAttack = false hasPhysicalAttack = false
target.battler.eachMove do |m| # target.battler.eachMove do |m|
next if !m.physicalMove?(m.type) # next if !m.physicalMove?(m.type)
hasPhysicalAttack = true # hasPhysicalAttack = true
break # break
end # end
score -= 50 if !hasPhysicalAttack score -= 50 if !hasPhysicalAttack
end end
next score next score
@@ -260,7 +262,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UsedAfterUserTakesPhysicalDamage",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("UsedAfterAllyRoundWithDoublePower", Battle::AI::Handlers::MoveEffectScore.add("UsedAfterAllyRoundWithDoublePower",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
user.battler.allAllies.each do |b| user.battler.allAllies.each do |b|
next if !b.pbHasMove?(move.id) next if !b.pbHasMove?(move.id)
@@ -284,7 +286,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UsedAfterAllyRoundWithDoublePower",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TargetUsesItsLastUsedMoveAgain", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetUsesItsLastUsedMoveAgain",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if !target.battler.lastRegularMoveUsed || next true if !target.battler.lastRegularMoveUsed ||
!target.battler.pbHasMove?(target.battler.lastRegularMoveUsed) !target.battler.pbHasMove?(target.battler.lastRegularMoveUsed)
@@ -297,11 +299,11 @@ Battle::AI::Handlers::MoveFailureCheck.add("TargetUsesItsLastUsedMoveAgain",
next true if target.battler.moves[idxMove].pp == 0 && target.battler.moves[idxMove].total_pp > 0 next true if target.battler.moves[idxMove].pp == 0 && target.battler.moves[idxMove].total_pp > 0
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("TargetUsesItsLastUsedMoveAgain", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetUsesItsLastUsedMoveAgain",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Without lots of code here to determine good/bad moves and relative # Without lots of code here to determine good/bad moves and relative
# speeds, using this move is likely to just be a waste of a turn # speeds, using this move is likely to just be a waste of a turn
next score - 40 next Battle::AI::MOVE_USELESS_SCORE
} }
) )
@@ -314,7 +316,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetUsesItsLastUsedMoveAgain",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("HigherPriorityInGrassyTerrain", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HigherPriorityInGrassyTerrain",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill? && battle.field.terrain == :Grassy if ai.trainer.medium_skill? && battle.field.terrain == :Grassy
score += 15 if target.faster_than?(user) score += 15 if target.faster_than?(user)
@@ -326,7 +328,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HigherPriorityInGrassyTerrain",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("LowerPPOfTargetLastMoveBy3", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerPPOfTargetLastMoveBy3",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
last_move = target.battler.pbGetMoveWithID(target.battler.lastRegularMoveUsed) last_move = target.battler.pbGetMoveWithID(target.battler.lastRegularMoveUsed)
if last_move && last_move.total_pp > 0 && last_move.pp <= 3 if last_move && last_move.total_pp > 0 && last_move.pp <= 3
@@ -339,22 +341,22 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerPPOfTargetLastMoveBy3",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("LowerPPOfTargetLastMoveBy4", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerPPOfTargetLastMoveBy4",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
last_move = target.battler.pbGetMoveWithID(target.battler.lastRegularMoveUsed) last_move = target.battler.pbGetMoveWithID(target.battler.lastRegularMoveUsed)
next true if !last_move || last_move.pp == 0 || last_move.total_pp <= 0 next true if !last_move || last_move.pp == 0 || last_move.total_pp <= 0
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("LowerPPOfTargetLastMoveBy4", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerPPOfTargetLastMoveBy4",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score - 40 next Battle::AI::MOVE_USELESS_SCORE
} }
) )
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetLastMoveUsed", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetLastMoveUsed",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Disable] > 0 || !target.battler.lastRegularMoveUsed next true if target.effects[PBEffects::Disable] > 0 || !target.battler.lastRegularMoveUsed
next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false) next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false)
@@ -372,13 +374,13 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetLastMoveUsed",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetUsingSameMoveConsecutively", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetUsingSameMoveConsecutively",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Torment] next true if target.effects[PBEffects::Torment]
next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false) next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false)
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingSameMoveConsecutively", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingSameMoveConsecutively",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next 0 if target.effects[PBEffects::Torment] next 0 if target.effects[PBEffects::Torment]
} }
@@ -387,7 +389,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingSameMoveConsecutive
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetUsingDifferentMove", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetUsingDifferentMove",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Encore] > 0 next true if target.effects[PBEffects::Encore] > 0
next true if !target.battler.lastRegularMoveUsed || next true if !target.battler.lastRegularMoveUsed ||
@@ -404,7 +406,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetUsingDifferentMove",
next will_fail next will_fail
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingDifferentMove", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingDifferentMove",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if user.faster_than?(target) if user.faster_than?(target)
moveData = GameData::Move.get(target.battler.lastRegularMoveUsed) moveData = GameData::Move.get(target.battler.lastRegularMoveUsed)
@@ -424,7 +426,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingDifferentMove",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetStatusMoves", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetStatusMoves",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Taunt] > 0 next true if target.effects[PBEffects::Taunt] > 0
next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false) next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false)
@@ -436,7 +438,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetStatusMoves",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetHealingMoves", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetHealingMoves",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::HealBlock] > 0 next true if target.effects[PBEffects::HealBlock] > 0
next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false) next true if move.move.pbMoveFailedAromaVeil?(user.battler, target.battler, false)
@@ -446,7 +448,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetHealingMoves",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DisableTargetSoundMoves", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetSoundMoves",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::ThroatChop] == 0 && ai.trainer.high_skill? if target.effects[PBEffects::ThroatChop] == 0 && ai.trainer.high_skill?
hasSoundMove = false hasSoundMove = false
@@ -465,7 +467,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DisableTargetSoundMoves",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetMovesKnownByUser", Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetMovesKnownByUser",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
next true if user.effects[PBEffects::Imprison] next true if user.effects[PBEffects::Imprison]
} }
) )
@@ -473,17 +475,19 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetMovesKnownByUser",
#=============================================================================== #===============================================================================
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("AllBattlersLoseHalfHPUserSkipsNextTurn", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AllBattlersLoseHalfHPUserSkipsNextTurn",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next true if battle.allBattlers.none? { |b| b.hp > 1 } next true if target.hp <= 1
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTurn", Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTurn",
proc { |score, move, user, ai, battle|
next score + 10 # Shadow moves are more preferable
}
)
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AllBattlersLoseHalfHPUserSkipsNextTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score += 20 # Shadow moves are more preferable next score + 20 if target.hp >= target.totalhp / 2
score += 20 if target.hp >= target.totalhp / 2
score -= 20 if user.hp < user.hp / 2
next score
} }
) )
@@ -491,7 +495,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTur
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfHP", Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfHP",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score += 20 # Shadow moves are more preferable score += 20 # Shadow moves are more preferable
score -= 40 score -= 40
next score next score
@@ -504,10 +508,10 @@ Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfHP",
Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather", Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather",
"StartShadowSkyWeather") "StartShadowSkyWeather")
Battle::AI::Handlers::MoveEffectScore.add("StartShadowSkyWeather", Battle::AI::Handlers::MoveEffectScore.add("StartShadowSkyWeather",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score += 20 # Shadow moves are more preferable score += 20 # Shadow moves are more preferable
next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) || next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE) battle.pbCheckGlobalAbility(:CLOUDNINE)
score += 10 if battle.field.weather != :None # Prefer replacing another weather score += 10 if battle.field.weather != :None # Prefer replacing another weather
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP
next score next score
@@ -518,7 +522,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartShadowSkyWeather",
# TODO: Review score modifiers. # TODO: Review score modifiers.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("RemoveAllScreens", Battle::AI::Handlers::MoveFailureCheck.add("RemoveAllScreens",
proc { |move, user, target, ai, battle| proc { |move, user, ai, battle|
will_fail = true will_fail = true
battle.sides.each do |side| battle.sides.each do |side|
will_fail = false if side.effects[PBEffects::AuroraVeil] > 0 || will_fail = false if side.effects[PBEffects::AuroraVeil] > 0 ||
@@ -530,7 +534,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("RemoveAllScreens",
} }
) )
Battle::AI::Handlers::MoveEffectScore.add("RemoveAllScreens", Battle::AI::Handlers::MoveEffectScore.add("RemoveAllScreens",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
score += 20 # Shadow moves are more preferable score += 20 # Shadow moves are more preferable
if user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0 || if user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0 ||
user.pbOpposingSide.effects[PBEffects::Reflect] > 0 || user.pbOpposingSide.effects[PBEffects::Reflect] > 0 ||

View File

@@ -1,7 +1,7 @@
#=============================================================================== #===============================================================================
# TODO: Review score modifier. # TODO: Review score modifier.
#=============================================================================== #===============================================================================
# TODO: High priority checks: # TODO:
# => Prefer move if it will KO the target (moreso if user is slower than target) # => Prefer move if it will KO the target (moreso if user is slower than target)
# => Don't prefer damaging move if it won't KO, user has Stance Change and # => Don't prefer damaging move if it won't KO, user has Stance Change and
# is in shield form, and user is slower than the target # is in shield form, and user is slower than the target
@@ -11,50 +11,98 @@
# => Check memory for past damage dealt by a target's priority move, and don't # => Check memory for past damage dealt by a target's priority move, and don't
# prefer the move if user is slower than the target and can't move faster # prefer the move if user is slower than the target and can't move faster
# than it because of priority # than it because of priority
# => Discard move if user is slower than the target and target is semi-
# invulnerable (and move won't hit it)
# => Check memory for whether target has previously used Quick Guard, and # => Check memory for whether target has previously used Quick Guard, and
# don't prefer move if so # don't prefer move if so
#=============================================================================== #===============================================================================
# TODO: Review score modifier.
#=============================================================================== #===============================================================================
# TODO: Low priority checks: #===============================================================================
# => Don't prefer move if user is faster than the target #===============================================================================
# => Prefer move if user is faster than the target and target is semi- #===============================================================================
# invulnerable
#=============================================================================== #===============================================================================
# Don't prefer a dancing move if the target has the Dancer ability. # Don't prefer hitting a wild shiny Pokémon.
# TODO: Review score modifier. # TODO: Review score modifier.
# TODO: Check all battlers, not just the target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:dance_move_against_dancer, Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:shiny_target,
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score /= 2 if move.move.danceMove? && target&.has_active_ability?(:DANCER) next score - 40 if target.wild? && target.battler.shiny?
} }
) )
#=============================================================================== #===============================================================================
# Adjust score based on how much damage it can deal.
# Prefer the move even more if it's predicted to do enough damage to KO the
# target.
# TODO: Review score modifier. # TODO: Review score modifier.
# => If target has previously used a move that will hurt the user by 30% of
# its current HP or more, moreso don't prefer a status move.
# => Include EOR damage in this?
#=============================================================================== #===============================================================================
# TODO: Check memory for whether target has previously used Ion Deluge, and Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:add_predicted_damage,
# don't prefer move if it's Normal-type and target is immune because proc { |score, move, user, target, ai, battle|
# of its ability (Lightning Rod, etc.). if move.damagingMove?
dmg = move.rough_damage
score += [15.0 * dmg / target.hp, 20].min
score += 10 if dmg > target.hp * 1.1 # Predicted to KO the target
next score.to_i
end
}
)
#=============================================================================== #===============================================================================
# Account for accuracy of move.
# TODO: Review score modifier. # TODO: Review score modifier.
#=============================================================================== #===============================================================================
# TODO: Don't prefer sound move if user hasn't been Throat Chopped but Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:move_accuracy,
# target has previously used Throat Chop. proc { |score, move, user, target, ai, battle|
next score * move.rough_accuracy / 100.0
}
)
#=============================================================================== #===============================================================================
# Don't prefer attacking the target if they'd be semi-invulnerable.
# TODO: Review score modifier. # TODO: Review score modifier.
#=============================================================================== #===============================================================================
# TODO: Don't prefer damaging moves if the target is Biding, unless the move Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:target_semi_invulnerable,
# will deal enough damage to KO the target before it retaliates (assuming proc { |score, move, user, target, ai, battle|
# the move is used repeatedly until the target retaliates). Don't worry # TODO: Also consider the move's priority compared to that of the move the
# about the target's Bide if the user will be immune to it. # target is using.
if move.rough_accuracy > 0 && user.faster_than?(target) &&
(target.battler.semiInvulnerable? || target.effects[PBEffects::SkyDrop] >= 0)
miss = true
miss = false if user.has_active_ability?(:NOGUARD) || target.has_active_ability?(:NOGUARD)
if ai.trainer.high_skill? && miss
# Knows what can get past semi-invulnerability
if target.effects[PBEffects::SkyDrop] >= 0 ||
target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky",
"TwoTurnAttackInvulnerableInSkyParalyzeTarget",
"TwoTurnAttackInvulnerableInSkyTargetCannotAct")
miss = false if move.move.hitsFlyingTargets?
elsif target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableUnderground")
miss = false if move.move.hitsDiggingTargets?
elsif target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableUnderwater")
miss = false if move.move.hitsDivingTargets?
end
end
next Battle::AI::MOVE_USELESS_SCORE if miss
end
}
)
#===============================================================================
# If target is frozen, don't prefer moves that could thaw them.
# TODO: Review score modifier.
#===============================================================================
Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:thawing_move_against_frozen_target,
proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill? && target.status == :FROZEN
if move.rough_type == :FIRE || (Settings::MECHANICS_GENERATION >= 6 && move.move.thawsUser?)
next score - 30
end
end
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifier. # TODO: Review score modifier.
@@ -64,37 +112,26 @@ Battle::AI::Handlers::GeneralMoveScore.add(:dance_move_against_dancer,
# lowered offences (Atk/Def or SpAtk/SpDef, whichever is relevant). # lowered offences (Atk/Def or SpAtk/SpDef, whichever is relevant).
#=============================================================================== #===============================================================================
# Don't prefer damaging moves that will knock out the target if they are using # Prefer flinching external effects (note that move effects which cause
# Destiny Bond. # flinching are dealt with in the function code part of score calculation).
# TODO: Review score modifier. # TODO: Review score modifier.
# => Also don't prefer damaging moves if user is slower than the target, move
# is likely to be lethal, and target has previously used Destiny Bond
#=============================================================================== #===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:avoid_knocking_out_destiny_bonder, Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:flinching_effects,
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill? && move.damagingMove? && if ai.trainer.medium_skill?
target && target.effects[PBEffects::DestinyBond] if (battle.moldBreaker || !target.has_active_ability?([:INNERFOCUS, :SHIELDDUST])) &&
dmg = move.rough_damage target.effects[PBEffects::Substitute] == 0
if dmg > target.hp * 1.05 # Predicted to KO the target if move.move.flinchingMove? ||
score -= 25 (move.damagingMove? &&
score -= 20 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0 (user.has_active_item?([:KINGSROCK, :RAZORFANG]) ||
user.has_active_ability?(:STENCH)))
next score + 20
end
end end
next score
end end
} }
) )
#===============================================================================
# TODO: Review score modifier.
#===============================================================================
# TODO: Don't prefer a move that is stopped by Wide Guard if target has
# previously used Wide Guard.
#===============================================================================
# TODO: Review score modifier.
#===============================================================================
# TODO: Don't prefer Fire-type moves if target has previously used Powder.
#=============================================================================== #===============================================================================
# TODO: Review score modifier. # TODO: Review score modifier.
#=============================================================================== #===============================================================================
@@ -110,53 +147,90 @@ Battle::AI::Handlers::GeneralMoveScore.add(:avoid_knocking_out_destiny_bonder,
# an effect that's good for the user (Poison Touch/Pickpocket). # an effect that's good for the user (Poison Touch/Pickpocket).
#=============================================================================== #===============================================================================
# Prefer damaging moves if the foe is down to their last Pokémon (opportunistic). # Don't prefer a dancing move if the target has the Dancer ability.
# Prefer damaging moves if the AI is down to its last Pokémon but the foe has
# more (desperate).
# TODO: Review score modifier. # TODO: Review score modifier.
# TODO: Check all battlers, not just the target.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:prefer_damaging_moves_if_last_pokemon, Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:dance_move_against_dancer,
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill? && move.damagingMove? next score /= 2 if move.move.danceMove? && target.has_active_ability?(:DANCER)
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
# Don't mess with scores just because a move is damaging; need to play well
next score if ai.trainer.high_skill? && foes > reserves # AI is outnumbered
# Prefer damaging moves depending on remaining Pokémon
if foes == 0 # Foe is down to their last Pokémon
score *= 1.1 # => Go for the kill
elsif reserves == 0 # AI is down to its last Pokémon, foe has reserves
score *= 1.05 # => Go out with a bang
end
end
next score
} }
) )
#=============================================================================== #===============================================================================
# Don't prefer attacking the target if they'd be semi-invulnerable.
# TODO: Review score modifier. # TODO: Review score modifier.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:target_semi_invulnerable, # TODO: Don't prefer damaging moves if the target is Biding, unless the move
# will deal enough damage to KO the target before it retaliates (assuming
# the move is used repeatedly until the target retaliates). Don't worry
# about the target's Bide if the user will be immune to it.
#===============================================================================
# Don't prefer damaging moves that will knock out the target if they are using
# Destiny Bond.
# TODO: Review score modifier.
# => Also don't prefer damaging moves if user is slower than the target, move
# is likely to be lethal, and target has previously used Destiny Bond
#===============================================================================
Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:avoid_knocking_out_destiny_bonder,
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if move.rough_accuracy > 0 && target && user.faster_than?(target) && if ai.trainer.medium_skill? && move.damagingMove? && target.effects[PBEffects::DestinyBond]
(target.battler.semiInvulnerable? || target.effects[PBEffects::SkyDrop] >= 0) dmg = move.rough_damage
miss = true if dmg > target.hp * 1.05 # Predicted to KO the target
miss = false if user.has_active_ability?(:NOGUARD) || target.has_active_ability?(:NOGUARD) score -= 25
if ai.trainer.high_skill? && miss score -= 20 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
# Knows what can get past semi-invulnerability end
if target.effects[PBEffects::SkyDrop] >= 0 || next score
target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky", end
"TwoTurnAttackInvulnerableInSkyParalyzeTarget", }
"TwoTurnAttackInvulnerableInSkyTargetCannotAct") )
miss = false if move.move.hitsFlyingTargets?
elsif target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableUnderground") #===============================================================================
miss = false if move.move.hitsDiggingTargets? # TODO: Review score modifier.
elsif target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableUnderwater") #===============================================================================
miss = false if move.move.hitsDivingTargets? # TODO: Don't prefer Fire-type moves if target has previously used Powder.
#===============================================================================
# TODO: Review score modifier.
#===============================================================================
# TODO: Check memory for whether target has previously used Ion Deluge, and
# don't prefer move if it's Normal-type and target is immune because
# of its ability (Lightning Rod, etc.).
#===============================================================================
# TODO: Review score modifier.
#===============================================================================
# TODO: Don't prefer a move that can be Magic Coated if the target (or any foe
# if the move doesn't have a target) has Magic Bounce.
#===============================================================================
#===============================================================================
#===============================================================================
#===============================================================================
#===============================================================================
#===============================================================================
# TODO: Review score modifier.
#===============================================================================
# TODO: Prefer Shadow moves.
#===============================================================================
# If user is frozen, prefer a move that can thaw the user.
# TODO: Review score modifier.
#===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:thawing_move_when_frozen,
proc { |score, move, user, ai, battle|
if ai.trainer.medium_skill? && user.status == :FROZEN
if move.move.thawsUser?
score += 30
else
user.battler.eachMove do |m|
next unless m.thawsUser?
score -= 30 # Don't prefer this move if user knows another move that thaws
break
end end
end end
next score - 40 if miss next score
end end
} }
) )
@@ -166,7 +240,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:target_semi_invulnerable,
# TODO: Review score modifier. # TODO: Review score modifier.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:good_move_for_choice_item, Battle::AI::Handlers::GeneralMoveScore.add(:good_move_for_choice_item,
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
if user.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) || if user.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) ||
user.has_active_ability?(:GORILLATACTICS) user.has_active_ability?(:GORILLATACTICS)
@@ -196,108 +270,37 @@ Battle::AI::Handlers::GeneralMoveScore.add(:good_move_for_choice_item,
) )
#=============================================================================== #===============================================================================
# If user is frozen, prefer a move that can thaw the user. # Prefer damaging moves if the foe is down to their last Pokémon (opportunistic).
# Prefer damaging moves if the AI is down to its last Pokémon but the foe has
# more (desperate).
# TODO: Review score modifier. # TODO: Review score modifier.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:thawing_move_when_frozen, Battle::AI::Handlers::GeneralMoveScore.add(:prefer_damaging_moves_if_last_pokemon,
proc { |score, move, user, target, ai, battle| proc { |score, move, user, ai, battle|
if ai.trainer.medium_skill? && user.status == :FROZEN if ai.trainer.medium_skill? && move.damagingMove?
if move.move.thawsUser? reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
score += 30 foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
else # Don't mess with scores just because a move is damaging; need to play well
user.battler.eachMove do |m| next score if ai.trainer.high_skill? && foes > reserves # AI is outnumbered
next unless m.thawsUser? # Prefer damaging moves depending on remaining Pokémon
score -= 30 # Don't prefer this move if user knows another move that thaws if foes == 0 # Foe is down to their last Pokémon
break score *= 1.1 # => Go for the kill
end elsif reserves == 0 # AI is down to its last Pokémon, foe has reserves
end score *= 1.05 # => Go out with a bang
next score
end
}
)
#===============================================================================
# If target is frozen, don't prefer moves that could thaw them.
# TODO: Review score modifier.
#===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:thawing_move_against_frozen_target,
proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill? && target&.status == :FROZEN
if move.rough_type == :FIRE || (Settings::MECHANICS_GENERATION >= 6 && move.move.thawsUser?)
next score - 30
end end
end end
} next score
)
#===============================================================================
# Don't prefer hitting a wild shiny Pokémon.
# TODO: Review score modifier.
#===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:shiny_target,
proc { |score, move, user, target, ai, battle|
next score - 40 if target && target.wild? && target.battler.shiny?
} }
) )
#=============================================================================== #===============================================================================
# TODO: Review score modifier. # TODO: Review score modifier.
#=============================================================================== #===============================================================================
# TODO: Discard a move that can be Magic Coated if either opponent has Magic # TODO: Don't prefer a move that is stopped by Wide Guard if any foe has
# Bounce. # previously used Wide Guard.
#===============================================================================
# Account for accuracy of move.
# TODO: Review score modifier.
#===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:move_accuracy,
proc { |score, move, user, target, ai, battle|
next score * move.rough_accuracy / 100.0
}
)
#===============================================================================
# Prefer flinching external effects (note that move effects which cause
# flinching are dealt with in the function code part of score calculation).
# TODO: Review score modifier.
#===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:flinching_effects,
proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill? && target
if (battle.moldBreaker || !target.has_active_ability?([:INNERFOCUS, :SHIELDDUST])) &&
target.effects[PBEffects::Substitute] == 0
if move.move.flinchingMove? ||
(move.damagingMove? &&
(user.has_active_item?([:KINGSROCK, :RAZORFANG]) ||
user.has_active_ability?(:STENCH)))
next score + 20
end
end
end
}
)
#===============================================================================
# Adjust score based on how much damage it can deal.
# Prefer the move even more if it's predicted to do enough damage to KO the
# target.
# TODO: Review score modifier.
# => If target has previously used a move that will hurt the user by 30% of
# its current HP or more, moreso don't prefer a status move.
#===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:add_predicted_damage,
proc { |score, move, user, target, ai, battle|
if move.damagingMove? && target
dmg = move.rough_damage
score += [15.0 * dmg / target.hp, 20].min
score += 10 if dmg > target.hp * 1.1 # Predicted to KO the target
next score.to_i
end
}
)
#=============================================================================== #===============================================================================
# TODO: Review score modifier. # TODO: Review score modifier.
#=============================================================================== #===============================================================================
# TODO: Prefer a damaging move if it's predicted to KO the target. Maybe include # TODO: Don't prefer sound move if user hasn't been Throat Chopped but a foe has
# EOR damage in the prediction? # previously used Throat Chop.

View File

@@ -11,26 +11,31 @@
# #
# Skill flags: # Skill flags:
# PredictMoveFailure # PredictMoveFailure
# ScoreMoves
# PreferMultiTargetMoves
#=============================================================================== #===============================================================================
class Battle::AI::AITrainer class Battle::AI::AITrainer
attr_reader :side, :trainer_index attr_reader :side, :trainer_index
attr_reader :skill attr_reader :skill
def initialize(ai, side, index, trainer) def initialize(ai, side, index, trainer)
@ai = ai @ai = ai
@side = side @side = side
@trainer_index = index @trainer_index = index
@trainer = trainer @trainer = trainer
@skill = 0
@skill = 0 @skill_flags = []
@skill_flags = []
set_up_skill set_up_skill
end end
def set_up_skill def set_up_skill
@skill = @trainer.skill_level if @trainer @skill = @trainer.skill_level if @trainer
# TODO: Add skill flags depending on @skill. # TODO: Add skill flags depending on @skill.
@skill_flags.push("PredictMoveFailure") if @skill > 0 if @skill > 0
@skill_flags.push("PredictMoveFailure")
@skill_flags.push("ScoreMoves")
@skill_flags.push("PreferMultiTargetMoves")
end
end end
def has_skill_flag?(flag) def has_skill_flag?(flag)

View File

@@ -22,6 +22,7 @@ class Battle::AI::AIBattler
end end
end end
def pokemon; return @battler.pokemon; end
def level; return @battler.level; end def level; return @battler.level; end
def hp; return @battler.hp; end def hp; return @battler.hp; end
def fainted?; return @battler.fainted?; end def fainted?; return @battler.fainted?; end