Misc tidying and commenting of AI code

This commit is contained in:
Maruno17
2022-08-28 17:59:02 +01:00
parent fbbddc8c2b
commit 9ed2f3e920
10 changed files with 238 additions and 209 deletions

View File

@@ -13,12 +13,8 @@ class Battle::AI
# be fiddly since damages should be calculated for each target but
# they're all related.
battler.eachMoveWithIndex do |_m, i|
next if !@battle.pbCanChooseMove?(battler.index, i, false)
if @user.wild?
pbRegisterMoveWild(i, choices)
else
pbRegisterMoveTrainer(i, choices)
end
next if !@battle.pbCanChooseMove?(battler.index, i, false) # Unchoosable moves aren't considered
pbAddMoveWithScoreToChoices(i, choices)
end
# Log the available choices
if $INTERNAL
@@ -37,30 +33,37 @@ class Battle::AI
# Get scores for the given move against each possible target
#=============================================================================
# Wild Pokémon choose their moves randomly.
def pbRegisterMoveWild(idxMove, choices)
battler = @user.battler
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
end
# Trainer Pokémon calculate how much they want to use each of their moves.
def pbRegisterMoveTrainer(idxMove, choices)
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 = pbGetMoveScore(move)
choices.push([idxMove, score, -1]) if score > 0
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?
totalScore = 0
@battle.allBattlers.each do |b|
next if !@battle.pbMoveCanTarget?(battler.index, b.index, target_data)
@@ -69,9 +72,17 @@ class Battle::AI
end
choices.push([idxMove, totalScore, -1]) if totalScore > 0
else
# Includes: Foe, NearAlly, NearFoe, NearOther, Other, RandomNearFoe, UserOrNearAlly
# If move affects one battler and you have to choose which one
@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 = pbGetMoveScore(move, b)
choices.push([idxMove, score, b.index]) if score > 0
@@ -84,6 +95,7 @@ class Battle::AI
#=============================================================================
def set_up_move_check(move, target)
@move.set_up(move, @user)
# TODO: Set @target to nil if there isn't one?
@target = (target) ? @battlers[target.index] : @user
@target&.refresh_battler
# Determine whether user or target is faster, and store that result so it
@@ -94,10 +106,10 @@ class Battle::AI
#=============================================================================
# Returns whether the move will definitely fail (assuming no battle conditions
# change between now and using the move)
# TODO: Add skill checks in here for particular calculations?
#=============================================================================
def pbPredictMoveFailure
return false if !@trainer.has_skill_flag?("PredictMoveFailure")
# TODO: Something involving pbCanChooseMove? (see Assault Vest).
# TODO: Something involving user.usingMultiTurnAttack? (perhaps earlier than
# this?).
# User is asleep and will not wake up
@@ -348,6 +360,8 @@ class Battle::AI
#=============================================================================
# Calculate how much damage a move is likely to do to a given target (as a
# percentage of the target's current HP)
# TODO: How much is this going to be used? Should the predicted percentage of
# damage be used as the initial score for damaging moves?
#=============================================================================
def pbGetDamagingMoveBaseScore
# Don't prefer moves that are ineffective because of abilities or effects
@@ -391,7 +405,8 @@ class Battle::AI
end
#=============================================================================
#
# TODO: Remove this method. If we're keeping any score changes inherent to a
# move's effect, they will go in MoveEffectScore handlers instead.
#=============================================================================
def pbGetStatusMoveBaseScore
# TODO: Call @target.immune_to_move? here too, not just for damaging moves

View File

@@ -5,7 +5,7 @@ class Battle::AI
#=============================================================================
def apply_effect_chance_to_score(score)
if @move.damagingMove?
# TODO: Doesn't return the correct value for "014" (Chatter).
# TODO: Doesn't return the correct value for "ConfuseTarget" (Chatter).
effect_chance = @move.addlEffect
if effect_chance > 0
effect_chance *= 2 if @user.hasActiveAbility?(:SERENEGRACE) ||
@@ -22,10 +22,10 @@ class Battle::AI
#=============================================================================
# TODO: These function codes need to have an attr_reader :statUp and for them
# to be set when the move is initialised.
# 035 Shell Smash
# 037 Acupressure
# 137 Magnetic Flux
# 15C Gear Up
# LowerUserDefSpDef1RaiseUserAtkSpAtkSpd2 Shell Smash
# RaiseTargetRandomStat2 Acupressure
# RaisePlusMinusUserAndAlliesDefSpDef1 Magnetic Flux
# RaisePlusMinusUserAndAlliesAtkSpAtk1 Gear Up
def calc_user_stat_raise_mini_score
mini_score = 1.0
# Determine whether the move boosts Attack, Special Attack or Speed (Bulk Up
@@ -36,7 +36,7 @@ class Battle::AI
next if idx.odd?
next if ![:ATTACK, :SPATK, :SPEED].include?(stat)
sweeping_stat = true
next if @move.function == "024" # Bulk Up (+Atk +Def)
next if @move.function == "RaiseUserAtkDef1" # Bulk Up (+Atk +Def)
offensive_stat = true
break
end
@@ -79,12 +79,12 @@ class Battle::AI
end
# Prefer if target has a status problem
if @target.status != PBStatuses::NONE
if @target.status != :NONE
mini_score *= (sweeping_stat) ? 1.2 : 1.1
case @target.status
when PBStatuses::SLEEP, PBStatuses::FROZEN
when :SLEEP, :FROZEN
mini_score *= 1.3
when PBStatuses::BURN
when :BURN
# TODO: Prefer if the move boosts Sp Def.
mini_score *= 1.1 if !offensive_stat
end
@@ -101,7 +101,7 @@ class Battle::AI
if @target.effects[PBEffects::Encore] > 0 &&
GameData::Move.get(@target.effects[PBEffects::EncoreMove]).category == 2 # Status move
# TODO: Why should this check greatly prefer raising both the user's defences?
if sweeping_stat || @move.function == "02A" # +Def +SpDef
if sweeping_stat || @move.function == "RaiseUserDefSpDef1" # +Def +SpDef
mini_score *= 1.5
else
mini_score *= 1.3
@@ -144,7 +144,7 @@ class Battle::AI
when :ATTACK
has_physical_move = false
@user.eachMove do |m|
next if !m.physicalMove?(m.type) || m.function == "121" # Foul Play
next if !m.physicalMove?(m.type) || m.function == "UseTargetAttackInsteadOfUserAttack" # Foul Play
has_physical_move = true
break
end
@@ -165,17 +165,17 @@ class Battle::AI
# it won't be hurt by weather
if @user.hp == @user.totalhp &&
(@user.hasActiveItem?(:FOCUSSASH) || @user.hasActiveAbility?(:STURDY))
if !(@battle.pbWeather == PBWeather::Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == PBWeather::Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == PBWeather::ShadowSky && @user.takesShadowSkyDamage?)
if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
mini_score *= 1.4
end
end
# Prefer if user has the Sweeper role
# TODO: Is 1.1x for 025 Coil (+Atk, +Def, +acc).
# TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
# Don't prefer if user is burned or paralysed
mini_score *= 0.5 if @user.status == PBStatuses::BURN || @user.status == PBStatuses::PARALYSIS
mini_score *= 0.5 if @user.status == :BURN || @user.status == :PARALYSIS
# Don't prefer if user's Speed stat is lowered
sum_stages = @user.stages[:SPEED]
mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0
@@ -191,23 +191,23 @@ class Battle::AI
mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST)
# TODO: Don't prefer if target has previously used a move that benefits
# from user's Attack being boosted.
mini_score *= 0.3 if check_for_move(@target) { |move| move.function == "121" } # Foul Play
mini_score *= 0.3 if check_for_move(@target) { |move| move.function == "UseTargetAttackInsteadOfUserAttack" } # Foul Play
# TODO: Don't prefer if the target has previously used a priority move.
when :DEFENSE
# Prefer if user has a healing item
# TODO: Is 1.1x for 025 Coil (+Atk, +Def, +acc).
# TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
(@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
# Prefer if user knows any healing moves
# TODO: Is 1.2x for 025 Coil (+Atk, +Def, +acc).
# TODO: Is 1.2x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? }
# Prefer if user knows Pain Split or Leech Seed
# TODO: Leech Seed is 1.2x for 025 Coil (+Atk, +Def, +acc).
mini_score *= 1.2 if @user.pbHasMoveFunction?("05A") # Pain Split
mini_score *= 1.3 if @user.pbHasMoveFunction?("0DC") # Leech Seed
# TODO: Leech Seed is 1.2x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split
mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed
# Prefer if user has certain roles
# TODO: Is 1.1x for 025 Coil (+Atk, +Def, +acc).
# TODO: Is 1.1x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# Don't prefer if user is badly poisoned
mini_score *= 0.2 if @user.effects[PBEffects::Toxic] > 0
@@ -227,9 +227,9 @@ class Battle::AI
# it won't be hurt by weather
if @user.hp == @user.totalhp &&
(@user.hasActiveItem?(:FOCUSSASH) || @user.hasActiveAbility?(:STURDY))
if !(@battle.pbWeather == PBWeather::Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == PBWeather::Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == PBWeather::ShadowSky && @user.takesShadowSkyDamage?)
if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
mini_score *= 1.4
end
end
@@ -243,7 +243,7 @@ class Battle::AI
mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
end
# Prefer if user has lowered Speed
# TODO: Is a flat 1.3x for 026 Dragon Dance (+Atk, +Spd).
# TODO: Is a flat 1.3x for RaiseUserAtkSpd1 Dragon Dance (+Atk, +Spd).
sum_stages = @user.stages[:SPEED]
mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
# Prefer if user has Moxie
@@ -251,7 +251,7 @@ class Battle::AI
# Prefer if user has the Sweeper role
mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
# Don't prefer if user is burned or paralysed
mini_score *= 0.2 if @user.status == PBStatuses::PARALYSIS
mini_score *= 0.2 if @user.status == :PARALYSIS
# Don't prefer if user has Speed Boost
mini_score *= 0.6 if @user.hasActiveAbility?(:SPEEDBOOST)
@@ -275,9 +275,9 @@ class Battle::AI
# it won't be hurt by weather
if @user.hp == @user.totalhp &&
(@user.hasActiveItem?(:FOCUSSASH) || @user.hasActiveAbility?(:STURDY))
if !(@battle.pbWeather == PBWeather::Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == PBWeather::Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == PBWeather::ShadowSky && @user.takesShadowSkyDamage?)
if !(@battle.pbWeather == :Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == :Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == :ShadowSky && @user.takesShadowSkyDamage?)
mini_score *= 1.4
end
end
@@ -305,8 +305,8 @@ class Battle::AI
# Prefer if user knows any healing moves
mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? }
# Prefer if user knows Pain Split or Leech Seed
mini_score *= 1.2 if @user.pbHasMoveFunction?("05A") # Pain Split
mini_score *= 1.3 if @user.pbHasMoveFunction?("0DC") # Leech Seed
mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split
mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed
# Prefer if user has certain roles
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# Don't prefer if user's Defense stat is raised
@@ -330,8 +330,8 @@ class Battle::AI
mini_score *= 1.1 if @target.hasActiveItem?([:BRIGHTPOWDER, :LAXINCENSE])
# Prefer if target has an ability that lowers foes' accuracy
# TODO: Tangled Feet while user is confused?
if (@battle.pbWeather == PBWeather::Sandstorm && @target.hasActiveAbility?(:SANDVEIL)) ||
(@battle.pbWeather == PBWeather::Hail && @target.hasActiveAbility?(:SNOWCLOAK))
if (@battle.pbWeather == :Sandstorm && @target.hasActiveAbility?(:SANDVEIL)) ||
(@battle.pbWeather == :Hail && @target.hasActiveAbility?(:SNOWCLOAK))
mini_score *= 1.1
end
@@ -343,15 +343,15 @@ class Battle::AI
mini_score *= 1.3 if @user.hasActiveItem?([:BRIGHTPOWDER, :LAXINCENSE])
# Prefer if user has an ability that lowers foes' accuracy
# TODO: Tangled Feet while user is confused?
if (@battle.pbWeather == PBWeather::Sandstorm && @user.hasActiveAbility?(:SANDVEIL)) ||
(@battle.pbWeather == PBWeather::Hail && @user.hasActiveAbility?(:SNOWCLOAK))
if (@battle.pbWeather == :Sandstorm && @user.hasActiveAbility?(:SANDVEIL)) ||
(@battle.pbWeather == :Hail && @user.hasActiveAbility?(:SNOWCLOAK))
mini_score *= 1.3
end
# Prefer if user knows any healing moves
mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? }
# Prefer if user knows Pain Split or Leech Seed
mini_score *= 1.2 if @user.pbHasMoveFunction?("05A") # Pain Split
mini_score *= 1.3 if @user.pbHasMoveFunction?("0DC") # Leech Seed
mini_score *= 1.2 if @user.pbHasMoveFunction?("UserTargetAverageHP") # Pain Split
mini_score *= 1.3 if @user.pbHasMoveFunction?("StartLeechSeedTarget") # Leech Seed
# Prefer if user has certain roles
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# TODO: Don't prefer if user's evasion stat is raised
@@ -367,15 +367,17 @@ class Battle::AI
# TODO: Don't prefer if target has Unaware? Reborn resets mini_score to 1.
# This check needs more consideration. Note that @target is user for
# status moves, so that part is wrong.
# TODO: Is 0x for 025, 026, 026 (all moves that raise multiple stats)
# TODO: Is 0x for RaiseUserAtkDefAcc1, RaiseUserAtkSpd1 (all moves that raise multiple stats)
mini_score *= 0.5 if @move.statusMove? && @target.hasActiveAbility?(:UNAWARE)
# TODO: Don't prefer if any foe has previously used a stat stage-clearing
# move (050, 051 Clear Smog/Haze).
mini_score *= 0.3 if check_for_move(@target) { |move| ["050", "051"].include?(move.function) } # Clear Smog, Haze
# move (Clear Smog/Haze).
mini_score *= 0.3 if check_for_move(@target) { |move|
["ResetTargetStatStages", "ResetAllBattlersStatStages"].include?(move.function)
} # Clear Smog, Haze
# TODO: Prefer if user is faster than the target.
# TODO: Is 1.3x for 025 Coil (+Atk, +Def, +acc).
# TODO: Is 1.3x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
mini_score *= 1.5 if @user_faster
# TODO: Don't prefer if target is a higher level than the user
if @target.level > @user.level + 5

View File

@@ -386,7 +386,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed1",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed1",
"RaiseUserSpeed2")
@@ -409,7 +409,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed2",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed2",
"RaiseUserSpeed2LowerUserWeight")
@@ -417,7 +417,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed2",
"RaiseUserSpeed2LowerUserWeight")
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed2",
"RaiseUserSpeed3")
@@ -610,9 +610,6 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpAtk1",
score -= 90
end
end
if move.function == "RaiseUserAtkSpAtk1Or2InSun" # Growth
score += 20 if [:Sun, :HarshSun].include?(user.battler.effectiveWeather)
end
next score
}
)
@@ -622,8 +619,27 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpAtk1",
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtkSpAtk1Or2InSun")
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtkSpAtk1Or2InSun")
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpAtk1Or2InSun",
proc { |score, move, user, target, ai, battle|
score -= user.stages[:ATTACK] * 10
score -= user.stages[:SPECIAL_ATTACK] * 10
if ai.trainer.medium_skill?
hasDamagingAttack = false
user.battler.eachMove do |m|
next if !m.damagingMove?
hasDamagingAttack = true
break
end
if hasDamagingAttack
score += 20
elsif ai.trainer.high_skill?
score -= 90
end
end
score += 20 if [:Sun, :HarshSun].include?(user.battler.effectiveWeather)
next score
}
)
#===============================================================================
#
@@ -665,7 +681,7 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerUserDefSpDef1RaiseUserAtkSpAtkSp
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtkSpd1")
@@ -697,7 +713,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAtkSpd1",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserAtk1Spd2")
@@ -794,7 +810,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpAtkSpDef1",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkSpAtk1",
"RaiseUserSpAtkSpDefSpd1")
@@ -1025,7 +1041,7 @@ Battle::AI::Handlers::MoveEffectScore.add("LowerUserDefSpDefSpd1",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("RaiseTargetAttack1",
proc { |move, user, target, ai, battle|
@@ -2151,6 +2167,6 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideDoubleSpeed",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
# StartSwapAllBattlersBaseDefensiveStats

View File

@@ -3,20 +3,22 @@
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("SleepTarget",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.pbCanSleep?(user.battler, false, move.move)
next true if move.statusMove? && !target.battler.pbCanSleep?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("SleepTarget",
proc { |score, move, user, target, ai, battle|
score += 30
if ai.trainer.medium_skill?
score -= 30 if target.effects[PBEffects::Yawn] > 0
end
score -= 30 if target.has_active_ability?(:MARVELSCALE)
if ai.trainer.best_skill?
if target.battler.pbHasMoveFunction?("FlinchTargetFailsIfUserNotAsleep",
"UseRandomUserMoveIfAsleep") # Snore, Sleep Talk
score -= 50
if target.battler.pbCanSleep?(user.battler, false, move.move)
score += 30
if ai.trainer.medium_skill?
score -= 30 if target.effects[PBEffects::Yawn] > 0
end
score -= 30 if target.has_active_ability?(:MARVELSCALE)
if ai.trainer.best_skill?
if target.battler.pbHasMoveFunction?("FlinchTargetFailsIfUserNotAsleep",
"UseRandomUserMoveIfAsleep") # Snore, Sleep Talk
score -= 50
end
end
end
next score
@@ -29,7 +31,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SleepTarget",
Battle::AI::Handlers::MoveFailureCheck.add("SleepTargetIfUserDarkrai",
proc { |move, user, target, ai, battle|
next true if !user.battler.isSpecies?(:DARKRAI) && user.effects[PBEffects::TransformSpecies] != :DARKRAI
next true if move.statusMove? && !target.pbCanSleep?(user.battler, false, move.move)
next true if move.statusMove? && !target.battler.pbCanSleep?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget",
@@ -47,17 +49,19 @@ Battle::AI::Handlers::MoveEffectScore.copy("SleepTarget",
Battle::AI::Handlers::MoveFailureCheck.add("SleepTargetNextTurn",
proc { |move, user, target, ai, battle|
next true if target.effects[PBEffects::Yawn] > 0
next true if !target.pbCanSleep?(user.battler, false, move.move)
next true if !target.battler.pbCanSleep?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("SleepTargetNextTurn",
proc { |score, move, user, target, ai, battle|
score += 30
score -= 30 if target.has_active_ability?(:MARVELSCALE)
if ai.trainer.best_skill?
if target.battler.pbHasMoveFunction?("FlinchTargetFailsIfUserNotAsleep",
"UseRandomUserMoveIfAsleep") # Snore, Sleep Talk
score -= 50
if target.battler.pbCanSleep?(user.battler, false, move.move)
score += 30
score -= 30 if target.has_active_ability?(:MARVELSCALE)
if ai.trainer.best_skill?
if target.battler.pbHasMoveFunction?("FlinchTargetFailsIfUserNotAsleep",
"UseRandomUserMoveIfAsleep") # Snore, Sleep Talk
score -= 50
end
end
end
next score
@@ -69,22 +73,24 @@ Battle::AI::Handlers::MoveEffectScore.add("SleepTargetNextTurn",
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("PoisonTarget",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.pbCanPoison?(user.battler, false, move.move)
next true if move.statusMove? && !target.battler.pbCanPoison?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("PoisonTarget",
proc { |score, move, user, target, ai, battle|
score += 30
if ai.trainer.medium_skill?
score += 30 if target.hp <= target.totalhp / 4
score += 50 if target.hp <= target.totalhp / 8
score -= 40 if target.effects[PBEffects::Yawn] > 0
if target.battler.pbCanPoison?(user.battler, false, move.move)
score += 30
if ai.trainer.medium_skill?
score += 30 if target.hp <= target.totalhp / 4
score += 50 if target.hp <= target.totalhp / 8
score -= 40 if target.effects[PBEffects::Yawn] > 0
end
if ai.trainer.high_skill?
score += 10 if target.rough_stat(:DEFENSE) > 100
score += 10 if target.rough_stat(:SPECIAL_DEFENSE) > 100
end
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :TOXICBOOST])
end
if ai.trainer.high_skill?
score += 10 if target.rough_stat(:DEFENSE) > 100
score += 10 if target.rough_stat(:SPECIAL_DEFENSE) > 100
end
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :TOXICBOOST])
next score
}
)
@@ -94,7 +100,7 @@ Battle::AI::Handlers::MoveEffectScore.add("PoisonTarget",
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("PoisonTargetLowerTargetSpeed1",
proc { |move, user, target, ai, battle|
next true if !target.pbCanPoison?(user.battler, false, move.move) &&
next true if !target.battler.pbCanPoison?(user.battler, false, move.move) &&
!target.battler.pbCanLowerStatStage?(:SPEED, user.battler, move.move)
}
)
@@ -132,17 +138,19 @@ Battle::AI::Handlers::MoveFailureCheck.copy("PoisonTarget",
"BadPoisonTarget")
Battle::AI::Handlers::MoveEffectScore.add("BadPoisonTarget",
proc { |score, move, user, target, ai, battle|
score += 30
if ai.trainer.medium_skill?
score += 30 if target.hp <= target.totalhp / 4
score += 50 if target.hp <= target.totalhp / 8
score -= 40 if target.effects[PBEffects::Yawn] > 0
if target.battler.pbCanPoison?(user.battler, false)
score += 30
if ai.trainer.medium_skill?
score += 30 if target.hp <= target.totalhp / 4
score += 50 if target.hp <= target.totalhp / 8
score -= 40 if target.effects[PBEffects::Yawn] > 0
end
if ai.trainer.high_skill?
score += 10 if target.rough_stat(:DEFENSE) > 100
score += 10 if target.rough_stat(:SPECIAL_DEFENSE) > 100
end
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :TOXICBOOST])
end
if ai.trainer.high_skill?
score += 10 if target.rough_stat(:DEFENSE) > 100
score += 10 if target.rough_stat(:SPECIAL_DEFENSE) > 100
end
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :TOXICBOOST])
next score
}
)
@@ -152,22 +160,24 @@ Battle::AI::Handlers::MoveEffectScore.add("BadPoisonTarget",
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("ParalyzeTarget",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.pbCanParalyze?(user.battler, false, move.move)
next true if move.statusMove? && !target.battler.pbCanParalyze?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("ParalyzeTarget",
proc { |score, move, user, target, ai, battle|
score += 30
if ai.trainer.medium_skill?
aspeed = user.rough_stat(:SPEED)
ospeed = target.rough_stat(:SPEED)
if aspeed < ospeed
score += 30
elsif aspeed > ospeed
score -= 40
if target.battler.pbCanParalyze?(user.battler, false, move.move)
score += 30
if ai.trainer.medium_skill?
aspeed = user.rough_stat(:SPEED)
ospeed = target.rough_stat(:SPEED)
if aspeed < ospeed
score += 30
elsif aspeed > ospeed
score -= 40
end
end
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET])
end
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET])
next score
}
)
@@ -179,7 +189,7 @@ Battle::AI::Handlers::MoveFailureCheck.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.pbCanParalyze?(user.battler, false, move.move)
next true if move.statusMove? && !target.battler.pbCanParalyze?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.copy("ParalyzeTarget",
@@ -197,13 +207,15 @@ Battle::AI::Handlers::MoveEffectScore.copy("ParalyzeTarget",
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("BurnTarget",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.pbCanBurn?(user.battler, false, move.move)
next true if move.statusMove? && !target.battler.pbCanBurn?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("BurnTarget",
proc { |score, move, user, target, ai, battle|
score += 30
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET, :FLAREBOOST])
if target.battler.pbCanBurn?(user.battler, false, move.move)
score += 30
score -= 40 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET, :FLAREBOOST])
end
next score
}
)
@@ -225,23 +237,12 @@ Battle::AI::Handlers::MoveEffectScore.copy("BurnTarget",
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("FreezeTarget",
proc { |move, user, target, ai, battle|
next true if move.statusMove? && !target.pbCanFreeze?(user.battler, false, move.move)
next true if move.statusMove? && !target.battler.pbCanFreeze?(user.battler, false, move.move)
}
)
Battle::AI::Handlers::MoveEffectScore.add("FreezeTarget",
proc { |score, move, user, target, ai, battle|
score += 30
score -= 20 if target.has_active_ability?(:MARVELSCALE)
next score
}
)
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("FreezeTargetSuperEffectiveAgainstWater",
proc { |score, move, user, target, ai, battle|
if target.battler.pbCanFreeze?(user.battler, false)
if target.battler.pbCanFreeze?(user.battler, false, move.move)
score += 30
score -= 20 if target.has_active_ability?(:MARVELSCALE)
end
@@ -252,22 +253,19 @@ Battle::AI::Handlers::MoveEffectScore.add("FreezeTargetSuperEffectiveAgainstWate
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("FreezeTargetAlwaysHitsInHail",
proc { |score, move, user, target, ai, battle|
if target.battler.pbCanFreeze?(user.battler, false)
score += 30
score -= 20 if target.has_active_ability?(:MARVELSCALE)
else
score -= 90 if move.statusMove?
end
next score
}
)
Battle::AI::Handlers::MoveEffectScore.copy("FreezeTarget",
"FreezeTargetSuperEffectiveAgainstWater")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.copy("FreezeTargetAlwaysHitsInHail",
Battle::AI::Handlers::MoveEffectScore.copy("FreezeTarget",
"FreezeTargetAlwaysHitsInHail")
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.copy("FreezeTarget",
"FreezeFlinchTarget")
#===============================================================================
@@ -350,10 +348,12 @@ Battle::AI::Handlers::MoveEffectScore.add("CureUserPartyStatus",
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("CureTargetBurn",
proc { |score, move, user, target, ai, battle|
if target.opposes?(user)
score -= 40 if target.status == :BURN
elsif target.status == :BURN
score += 40
if target.status == :BURN
if target.opposes?(user)
score -= 40
else
score += 40
end
end
next score
}
@@ -430,9 +430,8 @@ Battle::AI::Handlers::MoveBasePower.add("FlinchTargetDoublePowerIfTargetInSky",
)
Battle::AI::Handlers::MoveEffectScore.add("FlinchTargetDoublePowerIfTargetInSky",
proc { |score, move, user, target, ai, battle|
score += 30 if !target.has_active_ability?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute] == 0
next score
next score + 30 if !target.has_active_ability?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute] == 0
}
)
@@ -446,7 +445,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("ConfuseTarget",
)
Battle::AI::Handlers::MoveEffectScore.add("ConfuseTarget",
proc { |score, move, user, target, ai, battle|
next score + 30
next score + 30 if target.battler.pbCanConfuse?(user.battler, false, move.move)
}
)
@@ -466,10 +465,12 @@ Battle::AI::Handlers::MoveFailureCheck.add("AttractTarget",
)
Battle::AI::Handlers::MoveEffectScore.add("AttractTarget",
proc { |score, move, user, target, ai, battle|
score += 30
if target.has_active_item?(:DESTINYKNOT) &&
user.battler.pbCanAttract?(target.battler, false)
score -= 30
if target.battler.pbCanAttract?(user.battler, false)
score += 30
if target.has_active_item?(:DESTINYKNOT) &&
user.battler.pbCanAttract?(target.battler, false)
score -= 30
end
end
next score
}
@@ -775,20 +776,20 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartTargetAirborneAndAlwaysHitByMov
Battle::AI::Handlers::MoveEffectScore.add("HitsTargetInSkyGroundsTarget",
proc { |score, move, user, target, ai, battle|
if ai.trainer.medium_skill?
score += 20 if target.effects[PBEffects::MagnetRise] > 0
score += 20 if target.effects[PBEffects::Telekinesis] > 0
score += 20 if target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky",
score += 20 if target.effects[PBEffects::MagnetRise] > 0 ||
target.effects[PBEffects::Telekinesis] > 0 ||
target.has_type?(:FLYING) ||
target.has_active_ability?(:LEVITATE) ||
target.has_active_item?(:AIRBALLOON) ||
target.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky",
"TwoTurnAttackInvulnerableInSkyParalyzeTarget")
score += 20 if target.has_type?(:FLYING)
score += 20 if target.has_active_ability?(:LEVITATE)
score += 20 if target.has_active_item?(:AIRBALLOON)
end
next score
}
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartGravity",
proc { |move, user, target, ai, battle|

View File

@@ -419,15 +419,6 @@ Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit",
}
)
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit",
proc { |score, move, user, target, ai, battle|
next 0 if user.pbOwnSide.effects[PBEffects::LuckyChant] > 0
}
)
#===============================================================================
#
#===============================================================================
@@ -458,7 +449,7 @@ Battle::AI::Handlers::MoveEffectScore.add("CannotMakeTargetFaint",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn",
proc { |score, move, user, target, ai, battle|
@@ -555,7 +546,7 @@ 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|
@@ -574,7 +565,7 @@ 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|
@@ -594,7 +585,7 @@ 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|
@@ -613,7 +604,7 @@ 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|
@@ -632,7 +623,7 @@ 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|
@@ -674,12 +665,12 @@ Battle::AI::Handlers::MoveFailureCheck.add("ProtectUserSideFromStatusMoves",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
# ProtectUserSideFromPriorityMoves
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
# ProtectUserSideFromMultiTargetDamagingMoves
@@ -949,6 +940,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetMovesBecomeElectric",
)
#===============================================================================
#
# TODO: This code can be called with or without a target. Make sure it doesn't
# assume that there is a target.
#===============================================================================
# NormalMovesBecomeElectric

View File

@@ -214,7 +214,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TwoTurnAttackFlinchTarget",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2",
proc { |move, user, target, ai, battle|

View File

@@ -353,7 +353,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHPExplosive",
if ai.trainer.medium_skill? && reserves == 0 && foes > 0
score -= 60 # don't want to lose
elsif ai.trainer.high_skill? && reserves == 0 && foes == 0
score += 80 # want to draw
score += 40 # want to draw
else
score -= (user.totalhp - user.hp) * 75 / user.totalhp
end
@@ -373,7 +373,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserFaintsExplosive",
if ai.trainer.medium_skill? && reserves == 0 && foes > 0
score -= 60 # don't want to lose
elsif ai.trainer.high_skill? && reserves == 0 && foes == 0
score += 80 # want to draw
score += 40 # want to draw
else
score -= user.hp * 100 / user.totalhp
end
@@ -457,7 +457,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("UserFaintsHealAndCureReplacement",
"UserFaintsHealAndCureReplacementRestorePP")
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("StartPerishCountsForAllBattlers",
proc { |move, user, target, ai, battle|

View File

@@ -99,8 +99,8 @@ Battle::AI::Handlers::MoveEffectScore.add("RemoveTargetItem",
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("DestroyTargetBerryOrGem",
proc { |score, move, user, target, ai, battle|
if target.effects[PBEffects::Substitute] == 0
if ai.trainer.high_skill? && target.item && target.item.is_berry?
if ai.trainer.high_skill?
if target.item && target.item.is_berry? && target.effects[PBEffects::Substitute] == 0
score += 30
end
end
@@ -108,6 +108,9 @@ Battle::AI::Handlers::MoveEffectScore.add("DestroyTargetBerryOrGem",
}
)
#===============================================================================
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("CorrodeTargetItem",
proc { |move, user, target, ai, battle|
next true if !target.item || target.unlosableItem?(target.item) ||
@@ -118,10 +121,10 @@ Battle::AI::Handlers::MoveFailureCheck.add("CorrodeTargetItem",
)
Battle::AI::Handlers::MoveEffectScore.add("CorrodeTargetItem",
proc { |score, move, user, target, ai, battle|
if !target.item_active?
score -= 60
if target.item_active?
score += 30
else
score += 50
score -= 50
end
next score
}
@@ -142,7 +145,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartTargetCannotUseItem",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems",
proc { |score, move, user, target, ai, battle|
@@ -185,7 +188,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserConsumeBerryRaiseDefense2",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("AllBattlersConsumeBerry",
proc { |move, user, target, ai, battle|

View File

@@ -166,7 +166,7 @@ Battle::AI::Handlers::MoveEffectScore.add("PowerUpAllyMove",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("CounterPhysicalDamage",
proc { |power, move, user, target, ai, battle|
@@ -192,7 +192,7 @@ Battle::AI::Handlers::MoveEffectScore.add("CounterPhysicalDamage",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("CounterSpecialDamage",
proc { |power, move, user, target, ai, battle|
@@ -218,7 +218,7 @@ Battle::AI::Handlers::MoveEffectScore.add("CounterSpecialDamage",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("CounterDamagePlusHalf",
proc { |power, move, user, target, ai, battle|
@@ -246,7 +246,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserAddStockpileRaiseDefSpDef1",
avg -= user.stages[:SPECIAL_DEFENSE] * 10
score += avg / 2
if user.battler.pbHasMoveFunction?("PowerDependsOnUserStockpile",
"HealUserDependingOnUserStockpile") # Spit Up, Swallow
"HealUserDependingOnUserStockpile") # Spit Up, Swallow
score += 20 # More preferable if user also has Spit Up/Swallow
end
next score
@@ -338,7 +338,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UseLastMoveUsedByTarget",
# UseMoveDependingOnEnvironment
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
# UseRandomMove
@@ -386,12 +386,12 @@ Battle::AI::Handlers::MoveEffectScore.add("UseRandomUserMoveIfAsleep",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
# BounceBackProblemCausingStatusMoves
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
# StealAndUseBeneficialStatusMove

View File

@@ -305,7 +305,7 @@ Battle::AI::Handlers::MoveEffectScore.add("TargetUsesItsLastUsedMoveAgain",
)
#===============================================================================
#
# TODO: This code shouldn't make use of target.
#===============================================================================
# StartSlowerBattlersActFirst