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
MoveEffectScore = HandlerHash.new
MoveBasePower = HandlerHash.new
MoveFailureCheck = HandlerHash.new
GeneralMoveScore = HandlerHash.new
MoveFailureCheck = HandlerHash.new
MoveFailureAgainstTargetCheck = HandlerHash.new
MoveEffectScore = HandlerHash.new
MoveEffectAgainstTargetScore = HandlerHash.new
MoveBasePower = HandlerHash.new
GeneralMoveScore = HandlerHash.new
GeneralMoveAgainstTargetScore = HandlerHash.new
# Move type - uses main battle code via rough_type
# Move accuracy - uses main battle code via rough_accuracy
# Move target
@@ -79,11 +82,20 @@ module Battle::AI::Handlers
return MoveFailureCheck.trigger(function_code, *args) || false
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)
ret = MoveEffectScore.trigger(function_code, score, *args)
return (ret.nil?) ? score : ret
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)
ret = MoveBasePower.trigger(function_code, power, *args)
return (ret.nil?) ? power : ret
@@ -96,4 +108,12 @@ module Battle::AI::Handlers
end
return score
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

View File

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

View File

@@ -1,112 +1,97 @@
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).
#=============================================================================
def pbGetMoveScores
battler = @user.battler
# Get scores and targets for each move
choices = []
# TODO: Split this into two, the first part being the calculation of all
# predicted damages and the second part being the score calculations
# (which are based on the predicted damages). Multi-target moves could
# be fiddly since damages should be calculated for each target but
# they're all related.
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")
@user.battler.eachMoveWithIndex do |move, idxMove|
# Unchoosable moves aren't considered
if !@battle.pbCanChooseMove?(@user.index, idxMove, false)
if move.pp == 0 && move.total_pp > 0
PBDebug.log("[AI] #{@user.battler.pbThis} (#{@user.index}) cannot use move #{move.name} as it has no PP left")
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
next
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
@battle.moldBreaker = false
return choices
end
#=============================================================================
# Get scores for the given move against each possible target.
#=============================================================================
# Wild Pokémon choose their moves randomly.
# Trainer Pokémon calculate how much they want to use each of their moves.
def pbAddMoveWithScoreToChoices(idxMove, choices)
battler = @user.battler
# 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
def add_move_to_choices(choices, idxMove, score, idxTarget = -1)
choices.push([idxMove, score, idxTarget])
# If the user is a wild Pokémon, doubly prefer one of its moves (the choice
# is random but consistent and does not correlate to any other property of
# the user)
if @user.wild? && @user.pokemon.personalID % @user.battler.moves.length == idxMove
choices.push([idxMove, score, idxTarget])
end
end
#=============================================================================
# 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)
# 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?
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
# change between now and using the move).
@@ -121,7 +106,13 @@ class Battle::AI
# User will be truanting
return true if @user.has_active_ability?(:TRUANT) && @user.effects[PBEffects::Truant]
# 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
return true if @battle.field.terrain == :Psychic && @target.battler.affectedByTerrain? &&
@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.
#=============================================================================
def pbGetMoveScore(move, target = nil)
set_up_move_check(move, target)
# Predict whether the move will fail
if @trainer.has_skill_flag?("PredictMoveFailure")
return 25 if pbPredictMoveFailure
end
def pbGetMoveScore(move, targets = nil)
# Get the base score for the move
score = 100
# if @move.damagingMove?
# # Is also the predicted damage amount as a percentage of target's current HP
# score = pbGetDamagingMoveBaseScore
# else # Status moves
# # Depends on the move's effect
# score = pbGetStatusMoveBaseScore
# end
# Modify the score according to the move's effect
score = Battle::AI::Handlers.apply_move_effect_score(@move.function,
score, @move, @user, @target, self, @battle)
# Modify the score according to various other effects
score = Battle::AI::Handlers.apply_general_move_score_modifiers(
score, @move, @user, @target, self, @battle)
score = MOVE_BASE_SCORE
# Scores for each target in turn
if targets
# Reset the base score for the move (each target will add its own score)
score = 0
# TODO: Distinguish between affected foes and affected allies?
affected_targets = 0
# Get a score for the move against each target in turn
targets.each do |target|
set_up_move_check_target(target)
# Predict whether the move will fail against the target
if @trainer.has_skill_flag?("PredictMoveFailure")
next if pbPredictMoveFailureAgainstTarget
end
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 = 0 if score < 0
return score
@@ -188,26 +211,23 @@ class Battle::AI
#=============================================================================
def pbChooseMove(choices)
user_battler = @user.battler
# If no moves can be chosen, auto-choose a move or Struggle
if choices.length == 0
@battle.pbAutoChooseMove(user_battler.index)
PBDebug.log("[AI] #{user_battler.pbThis} (#{user_battler.index}) will auto-use a move or Struggle")
return
end
# Figure out useful information about the choices
max_score = 0
choices.each { |c| max_score = c[1] if max_score < c[1] }
# Decide whether all choices are bad, and if so, try switching instead
if @trainer.high_skill? && @user.can_switch_lax?
badMoves = false
if (max_score <= 25 && user_battler.turnCount > 2) ||
(max_score <= 60 && user_battler.turnCount > 4)
if (max_score <= MOVE_FAIL_SCORE && user_battler.turnCount > 2) ||
(max_score <= MOVE_USELESS_SCORE && user_battler.turnCount > 4)
badMoves = true if pbAIRandom(100) < 80
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 = false if badMoves && pbAIRandom(100) < 10
end
@@ -216,12 +236,10 @@ class Battle::AI
return
end
end
# Calculate a minimum score threshold and reduce all move scores by it
threshold = (max_score * 0.85).floor
choices.each { |c| c[3] = [c[1] - threshold, 0].max }
total_score = choices.sum { |c| c[3] }
# Log the available choices
if $INTERNAL
PBDebug.log("[AI] Move choices for #{user_battler.pbThis(true)} (#{user_battler.index}):")
@@ -233,7 +251,6 @@ class Battle::AI
PBDebug.log(log_msg)
end
end
# Pick a move randomly from choices weighted by their scores
randNum = pbAIRandom(total_score)
choices.each do |c|
@@ -243,7 +260,6 @@ class Battle::AI
@battle.pbRegisterTarget(user_battler.index, c[2]) if c[2] >= 0
break
end
# Log the result
if @battle.choices[user_battler.index][2]
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)
# Discard status move/don't prefer damaging move if user has 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
# Don't make score changes if foes have Unaware and user can't make use of
# extra stat stages
@@ -37,7 +37,7 @@ class Battle::AI
if stat_changes.length == 0
# TODO: Have a parameter that decides whether to reduce the score here
# (for moves where this is just part of the effect).
return (@move.statusMove?) ? score - 40 : score
return (@move.statusMove?) ? MOVE_USELESS_SCORE : score
end
# 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",
proc { |score, move, user, target, ai, battle|
next score - 60
proc { |score, move, user, ai, battle|
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",
"DoesNothingFailsIfNoAlly")
@@ -49,12 +44,12 @@ Battle::AI::Handlers::MoveEffectScore.copy("DoesNothingCongratulations",
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FailsIfNotUserFirstTurn",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if user.turnCount > 0
}
)
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
}
)
@@ -63,7 +58,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FailsIfNotUserFirstTurn",
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserHasUnusedMove",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
has_another_move = false
has_unused_move = false
user.battler.eachMove do |m|
@@ -81,7 +76,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserHasUnusedMove",
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FailsIfUserNotConsumedBerry",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
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|
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|
user_types = user.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|
# Check whether user is faster than its foe(s) and could use this move
user_faster_count = 0
@@ -122,7 +117,7 @@ Battle::AI::Handlers::MoveEffectScore.add("FailsIfUserDamagedThisTurn",
foe_faster_count += 1
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
# Effects that make the target unlikely to act before the user
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|
# 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
# TODO: Predict the target switching/using an item.
# 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|
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if [:HarshSun, :HeavyRain, :StrongWinds,
move.move.weatherType].include?(battle.field.weather)
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather",
proc { |score, move, user, target, ai, battle|
next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
score += 10 if battle.field.weather != :None # Prefer replacing another weather
score += 15 if user.has_active_item?(:HEATROCK)
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",
"StartRainWeather")
Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather",
proc { |score, move, user, target, ai, battle|
next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
score += 10 if battle.field.weather != :None # Prefer replacing another weather
score += 15 if user.has_active_item?(:DAMPROCK)
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",
"StartSandstormWeather")
Battle::AI::Handlers::MoveEffectScore.add("StartSandstormWeather",
proc { |score, move, user, target, ai, battle|
next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
score += 10 if battle.field.weather != :None # Prefer replacing another weather
score += 15 if user.has_active_item?(:SMOOTHROCK)
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",
"StartHailWeather")
Battle::AI::Handlers::MoveEffectScore.add("StartHailWeather",
proc { |score, move, user, target, ai, battle|
next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
score += 10 if battle.field.weather != :None # Prefer replacing another weather
score += 15 if user.has_active_item?(:ICYROCK)
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if battle.field.terrain == :Electric
}
)
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
if battle.field.terrain != :None
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if battle.field.terrain == :Grassy
}
)
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
if battle.field.terrain != :None
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if battle.field.terrain == :Misty
}
)
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
if battle.field.terrain != :None
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if battle.field.terrain == :Psychic
}
)
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
if battle.field.terrain != :None
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if battle.field.terrain == :None
}
)
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)
}
)
@@ -439,12 +434,12 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveTerrain",
#
#===============================================================================
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
}
)
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 }
foe_reserves = []
battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty|
@@ -464,7 +459,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide",
end
foe_reserves.push(pkmn) # pkmn will be affected by Spikes
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]]
score += multiplier * foe_reserves.length
next score
@@ -475,12 +470,12 @@ Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide",
#
#===============================================================================
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
}
)
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 }
foe_reserves = []
battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty|
@@ -502,7 +497,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide",
end
foe_reserves.push(pkmn) # pkmn will be affected by Toxic Spikes
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]]
score += multiplier * foe_reserves.length
next score
@@ -513,12 +508,12 @@ Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide",
#
#===============================================================================
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]
}
)
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 }
foe_reserves = []
battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty|
@@ -531,7 +526,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide",
end
foe_reserves.push(pkmn) # pkmn will be affected by Stealth Rock
end
next score - 40 if foe_reserves.empty?
next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty?
next score + 8 * foe_reserves.length
}
)
@@ -540,12 +535,12 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide",
#
#===============================================================================
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]
}
)
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 }
foe_reserves = []
battle.pbParty(user.idxOpposingSide).each_with_index do |pkmn, idxParty|
@@ -563,7 +558,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide",
end
foe_reserves.push(pkmn) # pkmn will be affected by Sticky Web
end
next score - 40 if foe_reserves.empty?
next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty?
next score + 7 * foe_reserves.length
}
)
@@ -572,7 +567,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide",
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SwapSideEffects",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
has_effect = false
2.times do |side|
effects = battle.sides[side].effects
@@ -593,7 +588,7 @@ Battle::AI::Handlers::MoveFailureCheck.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?
good_effects = [:AuroraVeil, :LightScreen, :Mist, :Rainbow, :Reflect,
:Safeguard, :SeaOfFire, :Swamp, :Tailwind].map! { |e| PBEffects.const_get(e) }
@@ -617,7 +612,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwapSideEffects",
# TODO: Review score modifiers.
#===============================================================================
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.hp <= [user.totalhp / 4, 1].max
}
@@ -627,7 +622,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserMakeSubstitute",
#
#===============================================================================
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 += 15 if user.effects[PBEffects::LeechSeed] >= 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|
next true if battle.positions[target.index].effects[PBEffects::FutureSightCounter] > 0
}
)
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
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
num_targets = 0
idxUserOwner = battle.pbGetOwnerIndexFromBattlerIndex(user.index)
user.battler.allAllies.each do |b|
@@ -671,7 +666,7 @@ Battle::AI::Handlers::MoveFailureCheck.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
}
)
@@ -680,7 +675,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserSwapsPositionsWithAlly",
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("BurnAttackerBeforeUserActs",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
ai.battlers.each do |b|
next if !b || !b.opposes?(user)
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|
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|
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
@@ -58,44 +58,48 @@ Battle::AI::Handlers::MoveEffectScore.add("SleepTarget",
#
#===============================================================================
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
}
)
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)
}
)
Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget",
"SleepTargetIfUserDarkrai")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("SleepTarget",
"SleepTargetIfUserDarkrai")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget",
"SleepTargetChangeUserMeloettaForm")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("SleepTarget",
"SleepTargetChangeUserMeloettaForm")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SleepTargetNextTurn",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SleepTargetNextTurn",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Yawn] > 0
next true if !target.battler.pbCanSleep?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget",
"SleepTargetNextTurn")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("SleepTarget",
"SleepTargetNextTurn")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("PoisonTarget",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PoisonTarget",
proc { |move, user, target, ai, battle|
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|
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
next score if target.has_active_item?([:PECHABERRY, :LUMBERRY])
next score if target.faster_than?(user) &&
@@ -148,17 +152,17 @@ Battle::AI::Handlers::MoveEffectScore.add("PoisonTarget",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("PoisonTargetLowerTargetSpeed1",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PoisonTargetLowerTargetSpeed1",
proc { |move, user, target, ai, battle|
next true if !target.battler.pbCanPoison?(user.battler, false, 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|
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 = 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)
next score
}
@@ -167,20 +171,20 @@ Battle::AI::Handlers::MoveEffectScore.add("PoisonTargetLowerTargetSpeed1",
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("PoisonTarget",
"BadPoisonTarget")
Battle::AI::Handlers::MoveEffectScore.copy("PoisonTarget",
"BadPoisonTarget")
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("PoisonTarget",
"BadPoisonTarget")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("PoisonTarget",
"BadPoisonTarget")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ParalyzeTarget",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ParalyzeTarget",
proc { |move, user, target, ai, battle|
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|
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
# 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|
eff = target.effectiveness_of_type_against_battler(move.rough_type, user)
next true if Effectiveness.ineffective?(eff)
next true if move.statusMove? && !target.battler.pbCanParalyze?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.copy("ParalyzeTarget",
"ParalyzeTargetIfNotTypeImmune")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("ParalyzeTarget",
"ParalyzeTargetIfNotTypeImmune")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.copy("ParalyzeTarget",
"ParalyzeTargetAlwaysHitsInRainHitsTargetInSky")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("ParalyzeTarget",
"ParalyzeTargetAlwaysHitsInRainHitsTargetInSky")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ParalyzeFlinchTarget",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeFlinchTarget",
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 = 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)
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|
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|
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
# 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|
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 = 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)
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|
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|
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
# 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",
"FreezeTargetSuperEffectiveAgainstWater")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FreezeTarget",
"FreezeTargetSuperEffectiveAgainstWater")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.copy("FreezeTarget",
"FreezeTargetAlwaysHitsInHail")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FreezeTarget",
"FreezeTargetAlwaysHitsInHail")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("FreezeFlinchTarget",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FreezeFlinchTarget",
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 = 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)
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|
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
@@ -435,12 +439,12 @@ Battle::AI::Handlers::MoveEffectScore.add("ParalyzeBurnOrFreezeTarget",
target.has_active_ability?(:HYDRATION) &&
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
# Scores for the possible effects
score += (Battle::AI::Handlers.apply_move_effect_score("ParalyzeTarget",
100, move, user, target, ai, battle) - 100) / 3
score += (Battle::AI::Handlers.apply_move_effect_score("BurnTarget",
100, move, user, target, ai, battle) - 100) / 3
score += (Battle::AI::Handlers.apply_move_effect_score("FreezeTarget",
100, move, user, target, ai, battle) - 100) / 3
score += (Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
Battle::AI::MOVE_BASE_SCORE, move, user, target, ai, battle) - Battle::AI::MOVE_BASE_SCORE) / 3
score += (Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
Battle::AI::MOVE_BASE_SCORE, move, user, target, ai, battle) - Battle::AI::MOVE_BASE_SCORE) / 3
score += (Battle::AI::Handlers.apply_move_effect_against_target_score("FreezeTarget",
Battle::AI::MOVE_BASE_SCORE, move, user, target, ai, battle) - Battle::AI::MOVE_BASE_SCORE) / 3
next score
}
)
@@ -449,29 +453,33 @@ Battle::AI::Handlers::MoveEffectScore.add("ParalyzeBurnOrFreezeTarget",
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("GiveUserStatusToTarget",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
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)
}
)
Battle::AI::Handlers::MoveEffectScore.add("GiveUserStatusToTarget",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("GiveUserStatusToTarget",
proc { |score, move, user, target, ai, battle|
score += 10 # For getting rid of the user's status problem
case user.status
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)
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)
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)
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)
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)
end
next score
@@ -482,12 +490,12 @@ Battle::AI::Handlers::MoveEffectScore.add("GiveUserStatusToTarget",
#
#===============================================================================
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)
}
)
Battle::AI::Handlers::MoveEffectScore.add("CureUserBurnPoisonParalysis",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
next score + 15
}
)
@@ -496,16 +504,13 @@ Battle::AI::Handlers::MoveEffectScore.add("CureUserBurnPoisonParalysis",
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("CureUserPartyStatus",
proc { |move, user, target, ai, battle|
has_effect = battle.allSameSideBattlers(user.battler).any? { |b| b.status != :NONE }
if !has_effect
has_effect = battle.pbParty(user.index).any? { |pkmn| pkmn&.able? && pkmn.status != :NONE }
end
next !has_effect
proc { |move, user, ai, battle|
next battle.pbParty(user.index).none? { |pkmn| pkmn&.able? && pkmn.status != :NONE }
}
)
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|
score += 10 if pkmn && pkmn.status != :NONE
end
@@ -515,8 +520,11 @@ Battle::AI::Handlers::MoveEffectScore.add("CureUserPartyStatus",
#===============================================================================
# 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|
if target.status == :BURN
if target.opposes?(user)
@@ -533,12 +541,12 @@ Battle::AI::Handlers::MoveEffectScore.add("CureTargetBurn",
# TODO: Review score modifiers.
#===============================================================================
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
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToInflictedStatus",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
if user.status != :NONE
score -= 20
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|
next score if target.faster_than?(user) || target.effects[PBEffects::Substitute] > 0
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if !user.battler.asleep?
}
)
Battle::AI::Handlers::MoveEffectScore.copy("FlinchTarget",
"FlinchTargetFailsIfUserNotAsleep")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FlinchTarget",
"FlinchTargetFailsIfUserNotAsleep")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FlinchTargetFailsIfNotUserFirstTurn",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if user.turnCount > 0
}
)
Battle::AI::Handlers::MoveEffectScore.copy("FlinchTarget",
"FlinchTargetFailsIfNotUserFirstTurn")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FlinchTarget",
"FlinchTargetFailsIfNotUserFirstTurn")
#===============================================================================
#
@@ -602,18 +610,18 @@ Battle::AI::Handlers::MoveBasePower.add("FlinchTargetDoublePowerIfTargetInSky",
next move.move.pbBaseDamage(power, user.battler, target.battler)
}
)
Battle::AI::Handlers::MoveEffectScore.copy("FlinchTarget",
"FlinchTargetDoublePowerIfTargetInSky")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FlinchTarget",
"FlinchTargetDoublePowerIfTargetInSky")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ConfuseTarget",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ConfuseTarget",
proc { |move, user, target, ai, battle|
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|
# No score modifier if the status problem will be removed immediately
next score if target.has_active_item?(:PERSIMBERRY)
@@ -641,18 +649,18 @@ Battle::AI::Handlers::MoveEffectScore.add("ConfuseTarget",
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.copy("ConfuseTarget",
"ConfuseTargetAlwaysHitsInRainHitsTargetInSky")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("ConfuseTarget",
"ConfuseTargetAlwaysHitsInRainHitsTargetInSky")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("AttractTarget",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AttractTarget",
proc { |move, user, target, ai, battle|
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|
if target.battler.pbCanAttract?(user.battler, false)
case move.additional_effect_usability(user, target)
@@ -680,7 +688,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AttractTarget",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesBasedOnEnvironment",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if !user.battler.canChangeType?
new_type = nil
terr_types = Battle::Move::SetUserTypesBasedOnEnvironment::TERRAIN_TYPES
@@ -699,7 +707,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesBasedOnEnvironment",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToResistLastAttack",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserTypesToResistLastAttack",
proc { |move, user, target, ai, battle|
next true if !user.battler.canChangeType?
next true if !target.battler.lastMoveUsed || !target.battler.lastMoveUsedType ||
@@ -718,7 +726,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToResistLastAttack",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToTargetTypes",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserTypesToTargetTypes",
proc { |move, user, target, ai, battle|
next true if !user.battler.canChangeType?
next true if target.battler.pbTypes(true).empty?
@@ -731,7 +739,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToTargetTypes",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToUserMoveType",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if !user.battler.canChangeType?
has_possible_type = false
user.battler.eachMoveWithIndex do |m, i|
@@ -748,7 +756,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetUserTypesToUserMoveType",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetTypesToPsychic",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetTypesToPsychic",
proc { |move, user, target, ai, battle|
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
}
@@ -757,26 +765,26 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetTypesToPsychic",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("SetTargetTypesToPsychic",
"SetTargetTypesToWater")
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("SetTargetTypesToPsychic",
"SetTargetTypesToWater")
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("SetTargetTypesToWater",
"AddGhostTypeToTarget")
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("SetTargetTypesToWater",
"AddGhostTypeToTarget")
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("AddGhostTypeToTarget",
"AddGrassTypeToTarget")
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("AddGhostTypeToTarget",
"AddGrassTypeToTarget")
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UserLosesFireType",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if !user.has_type?(:FIRE)
}
)
@@ -784,7 +792,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserLosesFireType",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToSimple",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToSimple",
proc { |move, user, target, ai, battle|
next true if !GameData::Ability.exists?(:SIMPLE)
next true if target.battler.unstoppableAbility? ||
@@ -795,7 +803,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToSimple",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToInsomnia",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToInsomnia",
proc { |move, user, target, ai, battle|
next true if !GameData::Ability.exists?(:INSOMNIA)
next true if target.battler.unstoppableAbility? ||
@@ -806,7 +814,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToInsomnia",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetUserAbilityToTargetAbility",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserAbilityToTargetAbility",
proc { |move, user, target, ai, battle|
next true if user.battler.unstoppableAbility?
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)
}
)
Battle::AI::Handlers::MoveEffectScore.add("SetUserAbilityToTargetAbility",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserAbilityToTargetAbility",
proc { |score, move, user, target, ai, battle|
score -= 40 # don't prefer this move
if ai.trainer.medium_skill? && user.opposes?(target)
@@ -827,7 +835,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SetUserAbilityToTargetAbility",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SetTargetAbilityToUserAbility",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToUserAbility",
proc { |move, user, target, ai, battle|
next true if !user.ability || user.ability_id == target.ability_id
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
}
)
Battle::AI::Handlers::MoveEffectScore.add("SetTargetAbilityToUserAbility",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToUserAbility",
proc { |score, move, user, target, ai, battle|
score -= 40 # don't prefer this move
if ai.trainer.medium_skill? && user.opposes?(target)
@@ -848,7 +856,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SetTargetAbilityToUserAbility",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UserTargetSwapAbilities",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("UserTargetSwapAbilities",
proc { |move, user, target, ai, battle|
next true if !user.ability || !target.ability
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
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapAbilities",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapAbilities",
proc { |score, move, user, target, ai, battle|
score -= 40 # don't prefer this move
if ai.trainer.high_skill? && user.opposes?(target)
@@ -871,7 +879,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapAbilities",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("NegateTargetAbility",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("NegateTargetAbility",
proc { |move, user, target, ai, battle|
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
}
@@ -880,7 +888,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("NegateTargetAbility",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("NegateTargetAbilityIfTargetActed",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbilityIfTargetActed",
proc { |score, move, user, target, ai, battle|
score += 15 if target.faster_than?(user)
next score
@@ -896,7 +904,7 @@ Battle::AI::Handlers::MoveEffectScore.add("NegateTargetAbilityIfTargetActed",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartUserAirborne",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if user.effects[PBEffects::Ingrain] ||
user.effects[PBEffects::SmackDown] ||
user.effects[PBEffects::MagnetRise] > 0
@@ -906,7 +914,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartUserAirborne",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartTargetAirborneAndAlwaysHitByMoves",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartTargetAirborneAndAlwaysHitByMoves",
proc { |move, user, target, ai, battle|
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
}
@@ -920,7 +928,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartTargetAirborneAndAlwaysHitByMov
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("HitsTargetInSkyGroundsTarget",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitsTargetInSkyGroundsTarget",
proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill?
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.
#===============================================================================
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
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
if ai.trainer.medium_skill?
score -= 15 if user.effects[PBEffects::SkyDrop] >= 0 ||
user.effects[PBEffects::MagnetRise] > 0 ||
@@ -953,15 +961,15 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
user.has_type?(:FLYING) ||
user.has_active_ability?(:LEVITATE) ||
user.has_active_item?(:AIRBALLOON)
score += 15 if target.effects[PBEffects::SkyDrop] >= 0 ||
target.effects[PBEffects::MagnetRise] > 0 ||
target.effects[PBEffects::Telekinesis] > 0 ||
target.has_type?(:FLYING) ||
target.has_active_ability?(:LEVITATE) ||
target.has_active_item?(:AIRBALLOON)
score += 5 if target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky",
"TwoTurnAttackInvulnerableInSkyParalyzeTarget",
"TwoTurnAttackInvulnerableInSkyTargetCannotAct")
# score += 15 if target.effects[PBEffects::SkyDrop] >= 0 ||
# target.effects[PBEffects::MagnetRise] > 0 ||
# target.effects[PBEffects::Telekinesis] > 0 ||
# target.has_type?(:FLYING) ||
# target.has_active_ability?(:LEVITATE) ||
# target.has_active_item?(:AIRBALLOON)
# score += 5 if target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky",
# "TwoTurnAttackInvulnerableInSkyParalyzeTarget",
# "TwoTurnAttackInvulnerableInSkyTargetCannotAct")
end
next score
}
@@ -970,15 +978,15 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TransformUserIntoTarget",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TransformUserIntoTarget",
proc { |move, user, target, ai, battle|
next true if user.effects[PBEffects::Transform]
next true if target.effects[PBEffects::Transform] ||
target.effects[PBEffects::Illusion]
}
)
Battle::AI::Handlers::MoveEffectScore.add("TransformUserIntoTarget",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TransformUserIntoTarget",
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|
next true if user.hp >= target.hp
}
@@ -60,7 +60,7 @@ Battle::AI::Handlers::MoveBasePower.add("LowerTargetHPToUserHP",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("OHKO",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("OHKO",
proc { |move, user, target, ai, battle|
next true if target.level > user.level
next true if !battle.moldBreaker && target.has_active_ability?(:STURDY)
@@ -75,7 +75,7 @@ Battle::AI::Handlers::MoveBasePower.add("OHKO",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("OHKOIce",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("OHKOIce",
proc { |move, user, target, ai, battle|
next true if target.level > user.level
next true if !battle.moldBreaker && target.has_active_ability?(:STURDY)
@@ -88,15 +88,15 @@ Battle::AI::Handlers::MoveBasePower.copy("OHKO",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("OHKO",
"OHKOHitsUndergroundTarget")
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("OHKO",
"OHKOHitsUndergroundTarget")
Battle::AI::Handlers::MoveBasePower.copy("OHKO",
"OHKOHitsUndergroundTarget")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DamageTargetAlly",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DamageTargetAlly",
proc { |score, move, user, target, ai, battle|
target.battler.allAllies.each do |b|
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",
"DoublePowerIfTargetAsleepCureTarget")
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetAsleepCureTarget",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetAsleepCureTarget",
proc { |score, move, user, target, ai, battle|
next score - 20 if target.status == :SLEEP && # Will cure status
target.statusCount > 1
@@ -260,7 +260,7 @@ Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetPoisoned",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetPoisoned",
"DoublePowerIfTargetParalyzedCureTarget")
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetParalyzedCureTarget",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetParalyzedCureTarget",
proc { |score, move, user, target, ai, battle|
next score - 20 if target.status == :PARALYSIS # Will cure status
}
@@ -330,15 +330,16 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetInSky",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfUserLostHPThisTurn",
proc { |score, move, user, target, ai, battle|
next score + 15 if target.faster_than?(user)
proc { |score, move, user, ai, battle|
# TODO: Remove target from this; consider the speeds of all foes instead.
# next score + 15 if target.faster_than?(user)
}
)
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetLostHPThisTurn",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetLostHPThisTurn",
proc { |score, move, user, target, ai, battle|
next score + 15 if battle.pbOpposingBattlerCount(user.battler) > 1
}
@@ -352,7 +353,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetLostHPThisTurn",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetActed",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetActed",
proc { |score, move, user, target, ai, battle|
next score + 15 if target.faster_than?(user)
}
@@ -361,7 +362,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetActed",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetNotActed",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetNotActed",
proc { |score, move, user, target, ai, battle|
next score + 15 if user.faster_than?(target)
}
@@ -376,7 +377,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfTargetNotActed",
# TODO: Review score modifiers.
#===============================================================================
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
score -= 90
else
@@ -390,7 +391,7 @@ Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit",
# TODO: Review score modifiers.
#===============================================================================
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
}
)
@@ -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|
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.
#===============================================================================
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
if ai.trainer.medium_skill?
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
score -= user.effects[PBEffects::ProtectRate] * 10
end
@@ -425,7 +426,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenElectricMoves",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
if Settings::MECHANICS_GENERATION >= 6
next true if battle.field.effects[PBEffects::MudSportField] > 0
else
@@ -438,7 +439,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenElectricMoves",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenFireMoves",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
if Settings::MECHANICS_GENERATION >= 6
next true if battle.field.effects[PBEffects::WaterSportField] > 0
else
@@ -451,7 +452,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenFireMoves",
# TODO: Review score modifiers.
#===============================================================================
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
}
)
@@ -460,7 +461,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenPhysicalDamageAgainstUser
# TODO: Review score modifiers.
#===============================================================================
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
}
)
@@ -469,13 +470,13 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenSpecialDamageAgainstUserS
# TODO: Review score modifiers.
#===============================================================================
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.battler.effectiveWeather != :Hail
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHail",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
next score + 40
}
)
@@ -484,7 +485,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHai
# TODO: Review score modifiers.
#===============================================================================
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::Reflect] > 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.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ProtectUser",
proc { |score, move, user, target, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 ||
target.effects[PBEffects::HyperBeam] > 0
proc { |score, move, user, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 # ||
# target.effects[PBEffects::HyperBeam] > 0
score -= 50
else
if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40
end
score += 50 if user.turnCount == 0
score += 30 if target.effects[PBEffects::TwoTurnAttack]
# score += 30 if target.effects[PBEffects::TwoTurnAttack]
end
next score
}
@@ -517,14 +518,14 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUser",
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker",
proc { |score, move, user, target, ai, battle|
next score - 40 if user.effects[PBEffects::ProtectRate] > 1 ||
target.effects[PBEffects::HyperBeam] > 0
proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if user.effects[PBEffects::ProtectRate] > 1 # ||
# target.effects[PBEffects::HyperBeam] > 0
if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40
end
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
next score
}
@@ -535,16 +536,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker",
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShield",
proc { |score, move, user, target, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 ||
target.effects[PBEffects::HyperBeam] > 0
proc { |score, move, user, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 # ||
# target.effects[PBEffects::HyperBeam] > 0
score -= 50
else
if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40
end
score += 50 if user.turnCount == 0
score += 30 if target.effects[PBEffects::TwoTurnAttack]
# score += 30 if target.effects[PBEffects::TwoTurnAttack]
end
next score
}
@@ -555,16 +556,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShie
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct",
proc { |score, move, user, target, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 ||
target.effects[PBEffects::HyperBeam] > 0
proc { |score, move, user, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 # ||
# target.effects[PBEffects::HyperBeam] > 0
score -= 50
else
if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40
end
score += 50 if user.turnCount == 0
score += 30 if target.effects[PBEffects::TwoTurnAttack]
# score += 30 if target.effects[PBEffects::TwoTurnAttack]
end
next score
}
@@ -575,16 +576,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct"
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShield",
proc { |score, move, user, target, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 ||
target.effects[PBEffects::HyperBeam] > 0
proc { |score, move, user, ai, battle|
if user.effects[PBEffects::ProtectRate] > 1 # ||
# target.effects[PBEffects::HyperBeam] > 0
score -= 90
else
if ai.trainer.medium_skill?
score -= user.effects[PBEffects::ProtectRate] * 40
end
score += 50 if user.turnCount == 0
score += 30 if target.effects[PBEffects::TwoTurnAttack]
# score += 30 if target.effects[PBEffects::TwoTurnAttack]
end
next score
}
@@ -594,13 +595,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShi
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromDamagingMovesIfUserFirstTurn",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if user.turnCount > 0
}
)
Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUserFirstTurn",
proc { |score, move, user, target, ai, battle|
next score + 30
proc { |score, move, user, ai, battle|
next score + 25 # Use it or lose it
}
)
@@ -608,7 +609,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUse
# TODO: Review score modifiers.
#===============================================================================
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]
}
)
@@ -639,11 +640,11 @@ Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromStatusMoves",
# TODO: Review score modifiers.
#===============================================================================
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
}
)
Battle::AI::Handlers::MoveEffectScore.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1",
proc { |score, move, user, target, ai, battle|
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|
next score if !user.battler.takesIndirectDamage? || user.has_active_ability?(:ROCKHEAD)
dmg = move.rough_damage / 4
if dmg >= user.hp
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
next score - 40 if reserves <= foes
next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes
end
score -= 10 * [dmg, user.hp].min / user.hp
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|
# Score for being a recoil move
if user.battler.takesIndirectDamage? && !user.has_active_ability?(:ROCKHEAD)
@@ -677,12 +678,12 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtParalyzeTarge
if dmg >= user.hp
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
next score - 40 if reserves <= foes
next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes
end
score -= 10 * [dmg, user.hp].min / user.hp
end
# 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)
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|
# Score for being a recoil move
if user.battler.takesIndirectDamage? && !user.has_active_ability?(:ROCKHEAD)
@@ -699,12 +700,12 @@ Battle::AI::Handlers::MoveEffectScore.add("RecoilThirdOfDamageDealtBurnTarget",
if dmg >= user.hp
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
next score - 40 if reserves <= foes
next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes
end
score -= 10 * [dmg, user.hp].min / user.hp
end
# 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)
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|
next score if !user.battler.takesIndirectDamage? || user.has_active_ability?(:ROCKHEAD)
dmg = move.rough_damage / 2
if dmg >= user.hp
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
next score - 40 if reserves <= foes
next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes
end
score -= 10 * [dmg, user.hp].min / user.hp
next score
@@ -745,7 +746,7 @@ Battle::AI::Handlers::MoveBasePower.add("EffectivenessIncludesFlyingType",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("CategoryDependsOnHigherDamagePoisonTarget",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CategoryDependsOnHigherDamagePoisonTarget",
proc { |score, move, user, target, ai, battle|
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
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|
next score - 40 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 user.has_active_ability?(:NOGUARD) || target.has_active_ability?(:NOGUARD)
next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::Telekinesis] > 0
# Prefer if the user knows moves with low accuracy
user.check_for_move do |m|
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|
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
# target's Ghost type immunity
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|
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
# target's Dark type immunity
if target.has_type?(:DARK)
@@ -863,7 +864,7 @@ Battle::AI::Handlers::MoveBasePower.add("TypeDependsOnUserIVs",
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TypeAndPowerDependOnUserBerry",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
item = user.item
next true if !item || !item.is_berry? || !user.item_active?
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
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.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("TargetMovesBecomeElectric",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetMovesBecomeElectric",
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: This code can be called with or without a target. Make sure it doesn't
# assume that there is a target.
# TODO: This code can be called with a single target and with no targets. Make
# sure it doesn't assume that there is a target.
#===============================================================================
# NormalMovesBecomeElectric

View File

@@ -6,7 +6,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes",
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|
# 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)
@@ -24,13 +24,13 @@ Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimes",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes",
"HitTwoTimesPoisonTarget")
Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesPoisonTarget",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimesPoisonTarget",
proc { |score, move, user, target, ai, battle|
# 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 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)
next score
}
@@ -41,13 +41,13 @@ Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesPoisonTarget",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes",
"HitTwoTimesFlinchTarget")
Battle::AI::Handlers::MoveEffectScore.add("HitTwoTimesFlinchTarget",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimesFlinchTarget",
proc { |score, move, user, target, ai, battle|
# 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 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)
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
}
)
Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesPowersUpWithEachHit",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitThreeTimesPowersUpWithEachHit",
proc { |score, move, user, target, ai, battle|
# 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)
@@ -87,8 +87,8 @@ Battle::AI::Handlers::MoveEffectScore.add("HitThreeTimesPowersUpWithEachHit",
#===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("HitTwoTimes",
"HitThreeTimesAlwaysCriticalHit")
Battle::AI::Handlers::MoveEffectScore.copy("HitTwoTimes",
"HitThreeTimesAlwaysCriticalHit")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("HitTwoTimes",
"HitThreeTimesAlwaysCriticalHit")
#===============================================================================
#
@@ -99,7 +99,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes",
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|
# 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)
@@ -124,18 +124,18 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimesOrThreeForAshGreninja"
next power * 31 / 10 # Average damage dealt
}
)
Battle::AI::Handlers::MoveEffectScore.copy("HitTwoToFiveTimes",
"HitTwoToFiveTimesOrThreeForAshGreninja")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("HitTwoToFiveTimes",
"HitTwoToFiveTimesOrThreeForAshGreninja")
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("HitTwoToFiveTimes",
"HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1")
Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1",
proc { |score, move, user, target, ai, battle|
# 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)
# User's stat changes
aspeed = user.rough_stat(:SPEED)
@@ -152,7 +152,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HitTwoToFiveTimesRaiseUserSpd1LowerUs
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HitOncePerUserTeamMember",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
will_fail = true
battle.eachInTeamFromBattlerIndex(user.index) do |pkmn, i|
next if !pkmn.able? || pkmn.status != :NONE
@@ -171,7 +171,7 @@ Battle::AI::Handlers::MoveBasePower.add("HitOncePerUserTeamMember",
next ret
}
)
Battle::AI::Handlers::MoveEffectScore.add("HitOncePerUserTeamMember",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitOncePerUserTeamMember",
proc { |score, move, user, target, ai, battle|
# 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)
@@ -191,7 +191,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HitOncePerUserTeamMember",
#
#===============================================================================
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
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)
@@ -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|
# Power Herb makes this a 1 turn move, the same as a move with no effect
next score if user.has_active_item?(:POWERHERB)
# 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
score -= 15
# 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)
}
)
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackOneTurnInSun",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackOneTurnInSun",
proc { |score, move, user, target, ai, battle|
# Sunny weather this a 1 turn move, the same as a move with no effect
next score if [:Sun, :HarshSun].include?(user.battler.effectiveWeather)
# 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)
}
)
@@ -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|
# 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 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)
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|
# 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 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)
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|
# 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 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)
next score
}
@@ -318,12 +318,12 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackFlinchTarget",
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1",
"TwoTurnAttackRaiseUserSpAtkSpDefSpd2")
Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2",
proc { |score, move, user, target, ai, battle|
# Score for raising user's stats
score = ai.get_score_for_user_stat_raise(score)
# 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)
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|
# 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 for raising the user's stat
score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserDefense1",
score, move, user, target, ai, battle)
score, move, user, ai, battle)
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|
# 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 for raising the user's stat
score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserSpAtk1",
score, move, user, target, ai, battle)
score, move, user, ai, battle)
next score
}
)
@@ -382,7 +382,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackChargeRaiseUserSpAtk1",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TwoTurnAttackInvulnerableInSkyTargetCannotAct",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TwoTurnAttackInvulnerableInSkyTargetCannotAct",
proc { |move, user, target, ai, battle|
next true if !target.opposes?(user)
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: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDamage",
proc { |power, move, user, target, ai, battle|
@@ -424,7 +425,7 @@ Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDama
}
)
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
score -= 90
elsif user.hp <= user.totalhp / 2

View File

@@ -2,14 +2,14 @@
#
#===============================================================================
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.asleep?
next true if !user.battler.pbCanSleep?(user.battler, false, move.move, true)
}
)
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
if user.hp >= user.totalhp * 0.5
score -= 10
@@ -34,12 +34,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserFullyAndFallAsleep",
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("HealUserHalfOfTotalHP",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if !user.battler.canHeal?
}
)
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
if user.hp >= user.totalhp * 0.5
score -= 10
@@ -56,7 +56,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHP",
Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP",
"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
if user.hp >= user.totalhp * 0.5
score -= 10
@@ -80,7 +80,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnWeather",
Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP",
"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
if user.hp >= user.totalhp * 0.5
score -= 10
@@ -98,7 +98,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnSandstorm",
Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP",
"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
if user.hp >= user.totalhp * 0.5
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|
next true if !user.battler.canHeal?
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|
# TODO: Add high level checks for whether the target wants to lose their
# 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|
if !battle.moldBreaker && target.has_active_ability?(:CONTRARY)
next true if target.statStageAtMax?(:ATTACK)
@@ -154,7 +154,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("HealUserByTargetAttackLowerTargetAtt
end
}
)
Battle::AI::Handlers::MoveEffectScore.add("HealUserByTargetAttackLowerTargetAttack1",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByTargetAttackLowerTargetAttack1",
proc { |score, move, user, target, ai, battle|
# Check whether lowering the target's Attack will have any impact
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|
# Consider how much HP will be restored
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|
next true if !target.battler.asleep?
}
)
Battle::AI::Handlers::MoveEffectScore.copy("HealUserByHalfOfDamageDone",
"HealUserByHalfOfDamageDoneIfTargetAsleep")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("HealUserByHalfOfDamageDone",
"HealUserByHalfOfDamageDoneIfTargetAsleep")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("HealUserByThreeQuartersOfDamageDone",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByThreeQuartersOfDamageDone",
proc { |score, move, user, target, ai, battle|
# Consider how much HP will be restored
heal_amt = move.rough_damage * 0.75
@@ -245,64 +245,56 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserByThreeQuartersOfDamageDone",
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.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",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserAndAlliesQuarterOfTotalHP",
proc { |move, user, target, ai, battle|
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|
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
heal_amt = target.totalhp / 2
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",
"HealTargetDependingOnGrassyTerrain")
Battle::AI::Handlers::MoveEffectScore.add("HealTargetDependingOnGrassyTerrain",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("HealTargetHalfOfTotalHP",
"HealTargetDependingOnGrassyTerrain")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealTargetDependingOnGrassyTerrain",
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
heal_amt = target.totalhp / 2
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if battle.positions[user.index].effects[PBEffects::Wish] > 0
}
)
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
if user.hp >= user.totalhp * 0.5
score -= 10
@@ -362,12 +354,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserPositionNextTurn",
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurn",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if user.effects[PBEffects::AquaRing]
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurn",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
score += 10
score += 10 if user.has_active_item?(:BIGROOT)
next score
@@ -378,12 +370,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurn",
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurnTrapUserInBattle",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if user.effects[PBEffects::Ingrain]
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurnTrapUserInBattle",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
score += 5
score += 10 if user.turnCount < 2
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|
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|
next score - 40 if target.statusCount <= 1
next Battle::AI::MOVE_USELESS_SCORE if target.statusCount <= 1
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|
next true if target.effects[PBEffects::LeechSeed] >= 0
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|
score += 10 if user.turnCount < 2
if ai.trainer.medium_skill?
@@ -440,7 +432,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartLeechSeedTarget",
#
#===============================================================================
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
if ai.trainer.medium_skill?
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if !battle.moldBreaker && battle.pbCheckGlobalAbility(:DAMP)
}
)
@@ -476,7 +468,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("UserLosesHalfOfTotalHP",
Battle::AI::Handlers::MoveFailureCheck.copy("UserLosesHalfOfTotalHPExplosive",
"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
if ai.trainer.medium_skill?
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|
next score - 40 if !target.battler.pbCanLowerStatStage?(:ATTACK, user.battler) &&
!target.battler.pbCanLowerStatStage?(:SPECIAL_ATTACK, user.battler)
next Battle::AI::MOVE_USELESS_SCORE if !target.battler.pbCanLowerStatStage?(:ATTACK, user.battler) &&
!target.battler.pbCanLowerStatStage?(:SPECIAL_ATTACK, user.battler)
score -= 25 # User will faint, don't prefer this move
# Check the impact of lowering the target's stats
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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if !battle.pbCanChooseNonActive?(user.index)
}
)
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
# Check whether the replacement user needs healing, and don't make the below
# calculations if not
@@ -568,7 +560,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserFaintsHealAndCureReplacement",
need_healing = true
break
end
next score - 15 if !need_healing
next Battle::AI::MOVE_USELESS_SCORE if !need_healing
end
if ai.trainer.medium_skill?
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")
#===============================================================================
#
# 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|
will_fail = true
battle.allBattlers.each do |b|
next if b.effects[PBEffects::PerishSong] > 0
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
next true if target.effects[PBEffects::PerishSong] > 0
next true if Battle::AbilityEffects.triggerMoveImmunity(target.ability, user.battler, target.battler,
move.move, move.rough_type, battle, false)
}
)
Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
score -= 15
# Check which battlers will be affected by this move
if ai.trainer.medium_skill?
@@ -628,7 +615,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers",
allies_affected += 1
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 * (foes_affected - allies_affected)
score += 5 * foes_with_high_hp
@@ -650,12 +637,12 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers",
#
#===============================================================================
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]
}
)
Battle::AI::Handlers::MoveEffectScore.add("AttackerFaintsIfUserFaints",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
score -= 25
# Check whether user is faster than its foe(s) and could use this move
user_faster_count = 0
@@ -679,7 +666,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AttackerFaintsIfUserFaints",
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("SetAttackerMovePPTo0IfUserFaints",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
score -= 25
# Check whether user is faster than its foe(s) and could use this move
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|
next score if user.wild? || user.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|
next true if !user.item || user.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|
user_item_preference = ai.battler_wants_item?(user, user.item_id)
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|
next true if user.wild?
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
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapItems",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapItems",
proc { |score, move, user, target, ai, battle|
user_new_item_preference = ai.battler_wants_item?(user, target.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",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if !user.battler.recycleItem || user.item
}
)
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_old_item_preference = ai.battler_wants_item?(user, user.item_id)
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)
}
)
Battle::AI::Handlers::MoveEffectScore.add("RemoveTargetItem",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RemoveTargetItem",
proc { |score, move, user, target, ai, battle|
next score if user.wild?
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|
next score if !target.item || (!target.item.is_berry? &&
!(Settings::MECHANICS_GENERATION >= 6 && target.item.is_gem?))
@@ -127,7 +127,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DestroyTargetBerryOrGem",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("CorrodeTargetItem",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CorrodeTargetItem",
proc { |move, user, target, ai, battle|
next true if !target.item || target.unlosableItem?(target.item) ||
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]
}
)
Battle::AI::Handlers::MoveEffectScore.add("CorrodeTargetItem",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CorrodeTargetItem",
proc { |score, move, user, target, ai, battle|
if target.item_active?
score += 30
@@ -149,25 +149,20 @@ Battle::AI::Handlers::MoveEffectScore.add("CorrodeTargetItem",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartTargetCannotUseItem",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartTargetCannotUseItem",
proc { |move, user, target, ai, battle|
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: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems",
proc { |score, move, user, target, ai, battle|
next score - 40 if battle.field.effects[PBEffects::MagicRoom] > 0
next score + 30 if !user.item && target.item
proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if battle.field.effects[PBEffects::MagicRoom] > 0
next score + 30 if !user.item # && target.item
}
)
@@ -175,13 +170,13 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("UserConsumeBerryRaiseDefense2",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
item = user.item
next true if !item || !item.is_berry? || !user.item_active?
}
)
Battle::AI::Handlers::MoveEffectScore.add("UserConsumeBerryRaiseDefense2",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
if ai.trainer.high_skill?
useful_berries = [
:ORANBERRY, :SITRUSBERRY, :AGUAVBERRY, :APICOTBERRY, :CHERIBERRY,
@@ -206,14 +201,14 @@ Battle::AI::Handlers::MoveEffectScore.add("UserConsumeBerryRaiseDefense2",
#===============================================================================
# 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|
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|
useful_berries = [
: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|
next score if !target.item || !target.item.is_berry?
next score if user.battler.unlosableItem?(target.item)
@@ -270,7 +265,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserConsumeTargetBerry",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ThrowUserItemAtTarget",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
item = user.item
next true if !item || !user.item_active? || user.battler.unlosableItem?(item)
next true if item.is_berry? && !user.battler.canConsumeBerry?

View File

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

View File

@@ -2,7 +2,7 @@
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FleeFromBattle",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if !battle.pbCanRun?(user.index)
}
)
@@ -11,7 +11,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FleeFromBattle",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserStatusMove",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
if user.wild?
next true if !battle.pbCanRun?(user.index)
else
@@ -20,7 +20,7 @@ Battle::AI::Handlers::MoveFailureCheck.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?
if battle.pbTeamAbleNonActiveCount(user.index) > 1 # Don't switch in ace
score -= 60
@@ -50,7 +50,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserStatusMove",
# TODO: Review score modifiers.
#===============================================================================
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) ||
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: Might need both MoveEffectScore and MoveEffectAgainstTargetScore.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetAtkSpAtk1SwitchOutUser",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetAtkSpAtk1SwitchOutUser",
proc { |move, user, target, ai, battle|
will_fail = true
(move.move.statDown.length / 2).times do |i|
@@ -70,7 +71,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("LowerTargetAtkSpAtk1SwitchOutUser",
next will_fail
}
)
Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAtkSpAtk1SwitchOutUser",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAtkSpAtk1SwitchOutUser",
proc { |score, move, user, target, ai, battle|
avg = target.stages[:ATTACK] * 10
avg += target.stages[:SPECIAL_ATTACK] * 10
@@ -83,12 +84,12 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerTargetAtkSpAtk1SwitchOutUser",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserPassOnEffects",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if !battle.pbCanChooseNonActive?(user.index)
}
)
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserPassOnEffects",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
if battle.pbCanChooseNonActive?(user.index)
score -= 40 if user.effects[PBEffects::Confusion] > 0
total = 0
@@ -116,7 +117,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserPassOnEffects",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutTargetStatusMove",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SwitchOutTargetStatusMove",
proc { |move, user, target, ai, battle|
next true if (!battle.moldBreaker && target.has_active_ability?(:SUCTIONCUPS)) ||
target.effects[PBEffects::Ingrain]
@@ -133,7 +134,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutTargetStatusMove",
end
}
)
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetStatusMove",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SwitchOutTargetStatusMove",
proc { |score, move, user, target, ai, battle|
score += 20 if target.pbOwnSide.effects[PBEffects::Spikes] > 0
score += 20 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0
@@ -145,7 +146,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetStatusMove",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetDamagingMove",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SwitchOutTargetDamagingMove",
proc { |score, move, user, target, ai, battle|
if (battle.moldBreaker || !target.has_active_ability?(:SUCTIONCUPS)) &&
!target.effects[PBEffects::Ingrain]
@@ -160,7 +161,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutTargetDamagingMove",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("BindTarget",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTarget",
proc { |score, move, user, target, ai, battle|
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)
}
)
Battle::AI::Handlers::MoveEffectScore.add("BindTargetDoublePowerIfTargetUnderwater",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTargetDoublePowerIfTargetUnderwater",
proc { |score, move, user, target, ai, battle|
next score + 40 if target.effects[PBEffects::Trapping] == 0
}
@@ -183,7 +184,7 @@ Battle::AI::Handlers::MoveEffectScore.add("BindTargetDoublePowerIfTargetUnderwat
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TrapTargetInBattle",
proc { |move, user, target, ai, battle|
if move.statusMove?
next true if target.effects[PBEffects::MeanLook] >= 0
@@ -195,7 +196,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn",
proc { |move, user, target, ai, battle|
if move.statusMove?
next true if target.effects[PBEffects::Octolock] >= 0
@@ -203,7 +204,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("TrapTargetInBattle",
end
}
)
Battle::AI::Handlers::MoveEffectScore.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn",
proc { |score, move, user, target, ai, battle|
score += 30 if !target.battler.trappedInBattle?
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.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("TrapUserAndTargetInBattle",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapUserAndTargetInBattle",
proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::JawLock] < 0
score += 40 if !user.battler.trappedInBattle? && !target.battler.trappedInBattle?
@@ -228,7 +229,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TrapUserAndTargetInBattle",
# TODO: Review score modifiers.
#===============================================================================
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
}
)
@@ -240,16 +241,17 @@ Battle::AI::Handlers::MoveFailureCheck.add("TrapAllBattlersInBattleForOneTurn",
#===============================================================================
# TODO: Review score modifiers.
# TODO: Consider all foes rather than just target. Can't use "target".
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("UsedAfterUserTakesPhysicalDamage",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
if ai.trainer.medium_skill?
hasPhysicalAttack = false
target.battler.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
# target.battler.eachMove do |m|
# next if !m.physicalMove?(m.type)
# hasPhysicalAttack = true
# break
# end
score -= 50 if !hasPhysicalAttack
end
next score
@@ -260,7 +262,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UsedAfterUserTakesPhysicalDamage",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("UsedAfterAllyRoundWithDoublePower",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
if ai.trainer.medium_skill?
user.battler.allAllies.each do |b|
next if !b.pbHasMove?(move.id)
@@ -284,7 +286,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UsedAfterAllyRoundWithDoublePower",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TargetUsesItsLastUsedMoveAgain",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetUsesItsLastUsedMoveAgain",
proc { |move, user, target, ai, battle|
next true if !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
}
)
Battle::AI::Handlers::MoveEffectScore.add("TargetUsesItsLastUsedMoveAgain",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetUsesItsLastUsedMoveAgain",
proc { |score, move, user, target, ai, battle|
# 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
next score - 40
next Battle::AI::MOVE_USELESS_SCORE
}
)
@@ -314,7 +316,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetUsesItsLastUsedMoveAgain",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("HigherPriorityInGrassyTerrain",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HigherPriorityInGrassyTerrain",
proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill? && battle.field.terrain == :Grassy
score += 15 if target.faster_than?(user)
@@ -326,7 +328,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HigherPriorityInGrassyTerrain",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("LowerPPOfTargetLastMoveBy3",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerPPOfTargetLastMoveBy3",
proc { |score, move, user, target, ai, battle|
last_move = target.battler.pbGetMoveWithID(target.battler.lastRegularMoveUsed)
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.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("LowerPPOfTargetLastMoveBy4",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerPPOfTargetLastMoveBy4",
proc { |move, user, target, ai, battle|
last_move = target.battler.pbGetMoveWithID(target.battler.lastRegularMoveUsed)
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|
next score - 40
next Battle::AI::MOVE_USELESS_SCORE
}
)
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetLastMoveUsed",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetLastMoveUsed",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Disable] > 0 || !target.battler.lastRegularMoveUsed
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.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetUsingSameMoveConsecutively",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetUsingSameMoveConsecutively",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Torment]
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|
next 0 if target.effects[PBEffects::Torment]
}
@@ -387,7 +389,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingSameMoveConsecutive
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetUsingDifferentMove",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetUsingDifferentMove",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Encore] > 0
next true if !target.battler.lastRegularMoveUsed ||
@@ -404,7 +406,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetUsingDifferentMove",
next will_fail
}
)
Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingDifferentMove",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingDifferentMove",
proc { |score, move, user, target, ai, battle|
if user.faster_than?(target)
moveData = GameData::Move.get(target.battler.lastRegularMoveUsed)
@@ -424,7 +426,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DisableTargetUsingDifferentMove",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetStatusMoves",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetStatusMoves",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Taunt] > 0
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.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetHealingMoves",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetHealingMoves",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::HealBlock] > 0
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.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DisableTargetSoundMoves",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetSoundMoves",
proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::ThroatChop] == 0 && ai.trainer.high_skill?
hasSoundMove = false
@@ -465,7 +467,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DisableTargetSoundMoves",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetMovesKnownByUser",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
next true if user.effects[PBEffects::Imprison]
}
)
@@ -473,17 +475,19 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetMovesKnownByUser",
#===============================================================================
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("AllBattlersLoseHalfHPUserSkipsNextTurn",
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AllBattlersLoseHalfHPUserSkipsNextTurn",
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",
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|
score += 20 # Shadow moves are more preferable
score += 20 if target.hp >= target.totalhp / 2
score -= 20 if user.hp < user.hp / 2
next score
next score + 20 if target.hp >= target.totalhp / 2
}
)
@@ -491,7 +495,7 @@ Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTur
# TODO: Review score modifiers.
#===============================================================================
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 -= 40
next score
@@ -504,10 +508,10 @@ Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfHP",
Battle::AI::Handlers::MoveFailureCheck.copy("StartSunWeather",
"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
next score - 40 if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE)
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
next score
@@ -518,7 +522,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartShadowSkyWeather",
# TODO: Review score modifiers.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("RemoveAllScreens",
proc { |move, user, target, ai, battle|
proc { |move, user, ai, battle|
will_fail = true
battle.sides.each do |side|
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",
proc { |score, move, user, target, ai, battle|
proc { |score, move, user, ai, battle|
score += 20 # Shadow moves are more preferable
if user.pbOpposingSide.effects[PBEffects::AuroraVeil] > 0 ||
user.pbOpposingSide.effects[PBEffects::Reflect] > 0 ||

View File

@@ -1,7 +1,7 @@
#===============================================================================
# TODO: Review score modifier.
#===============================================================================
# TODO: High priority checks:
# TODO:
# => 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
# 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
# prefer the move if user is slower than the target and can't move faster
# 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
# 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: 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|
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.
# => 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
# don't prefer move if it's Normal-type and target is immune because
# of its ability (Lightning Rod, etc.).
Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:add_predicted_damage,
proc { |score, move, user, target, ai, battle|
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: Don't prefer sound move if user hasn't been Throat Chopped but
# target has previously used Throat Chop.
Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:move_accuracy,
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: 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.
Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:target_semi_invulnerable,
proc { |score, move, user, target, ai, battle|
# TODO: Also consider the move's priority compared to that of the move the
# 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.
@@ -64,37 +112,26 @@ Battle::AI::Handlers::GeneralMoveScore.add(:dance_move_against_dancer,
# 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
# Destiny Bond.
# 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.
# => 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|
if ai.trainer.medium_skill? && move.damagingMove? &&
target && target.effects[PBEffects::DestinyBond]
dmg = move.rough_damage
if dmg > target.hp * 1.05 # Predicted to KO the target
score -= 25
score -= 20 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
if ai.trainer.medium_skill?
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
next score
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.
#===============================================================================
@@ -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).
#===============================================================================
# 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).
# Don't prefer a dancing move if the target has the Dancer ability.
# 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|
if ai.trainer.medium_skill? && move.damagingMove?
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
next score /= 2 if move.move.danceMove? && target.has_active_ability?(:DANCER)
}
)
#===============================================================================
# Don't prefer attacking the target if they'd be semi-invulnerable.
# 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|
if move.rough_accuracy > 0 && target && 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?
if ai.trainer.medium_skill? && move.damagingMove? && target.effects[PBEffects::DestinyBond]
dmg = move.rough_damage
if dmg > target.hp * 1.05 # Predicted to KO the target
score -= 25
score -= 20 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
end
next score
end
}
)
#===============================================================================
# TODO: Review score modifier.
#===============================================================================
# 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
next score - 40 if miss
next score
end
}
)
@@ -166,7 +240,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:target_semi_invulnerable,
# TODO: Review score modifier.
#===============================================================================
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 user.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) ||
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.
#===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:thawing_move_when_frozen,
proc { |score, move, user, target, 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
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
Battle::AI::Handlers::GeneralMoveScore.add(:prefer_damaging_moves_if_last_pokemon,
proc { |score, move, user, ai, battle|
if ai.trainer.medium_skill? && move.damagingMove?
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
}
)
#===============================================================================
# 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?
next score
}
)
#===============================================================================
# TODO: Review score modifier.
#===============================================================================
# TODO: Discard a move that can be Magic Coated if either opponent has Magic
# Bounce.
#===============================================================================
# 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: Don't prefer a move that is stopped by Wide Guard if any foe has
# previously used Wide Guard.
#===============================================================================
# TODO: Review score modifier.
#===============================================================================
# TODO: Prefer a damaging move if it's predicted to KO the target. Maybe include
# EOR damage in the prediction?
# TODO: Don't prefer sound move if user hasn't been Throat Chopped but a foe has
# previously used Throat Chop.

View File

@@ -11,26 +11,31 @@
#
# Skill flags:
# PredictMoveFailure
# ScoreMoves
# PreferMultiTargetMoves
#===============================================================================
class Battle::AI::AITrainer
attr_reader :side, :trainer_index
attr_reader :skill
def initialize(ai, side, index, trainer)
@ai = ai
@side = side
@ai = ai
@side = side
@trainer_index = index
@trainer = trainer
@skill = 0
@skill_flags = []
@trainer = trainer
@skill = 0
@skill_flags = []
set_up_skill
end
def set_up_skill
@skill = @trainer.skill_level if @trainer
# 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
def has_skill_flag?(flag)

View File

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