mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
Split AI move handlers into general ones and ones per target, rearranged some main move-scoring code
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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?
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user