AI rewrites of ability-changing function codes, OHKO codes and binding codes

This commit is contained in:
Maruno17
2022-12-10 21:59:44 +00:00
parent 539a47671d
commit 7ace4c5289
6 changed files with 471 additions and 34 deletions

View File

@@ -292,6 +292,16 @@ class Battle::AI
score += 15 * inc_mult
break
end
# TODO: Prefer if the user is able to cause flinching (moves that flinch,
# or has King's Rock/Stench).
# Prefer if the user has Electro Ball or Power Trip/Stored Power
moves_that_prefer_high_speed = [
"PowerHigherWithUserFasterThanTarget",
"PowerHigherWithUserPositiveStatStages"
]
if @user.check_for_move { |m| moves_that_prefer_high_speed.include?(m.function) }
score += 8 * inc_mult
end
# Don't prefer if any foe has Gyro Ball
each_foe_battler(@user.side) do |b, i|
next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetFasterThanUser" }
@@ -956,4 +966,295 @@ class Battle::AI
end
return ret
end
#=============================================================================
# Returns a value indicating how beneficial the given ability will be to the
# given battler if it has it.
# Return values are typically between -10 and +10. 0 is indifferent, positive
# values mean the battler benefits, negative values mean the battler suffers.
#=============================================================================
# These values are taken from the Complete-Fire-Red-Upgrade decomp here:
# https://github.com/Skeli789/Complete-Fire-Red-Upgrade/blob/f7f35becbd111c7e936b126f6328fc52d9af68c8/src/ability_battle_effects.c#L41
BASE_ABILITY_RATINGS = {
:ADAPTABILITY => 8,
:AERILATE => 8,
:AFTERMATH => 5,
:AIRLOCK => 5,
:ANALYTIC => 5,
:ANGERPOINT => 4,
:ANTICIPATION => 2,
:ARENATRAP => 9,
:AROMAVEIL => 3,
# :ASONECHILLINGNEIGH => 0,
# :ASONEGRIMNEIGH => 0,
:AURABREAK => 3,
:BADDREAMS => 4,
# :BALLFETCH => 0,
# :BATTERY => 0,
:BATTLEARMOR => 2,
:BATTLEBOND => 6,
:BEASTBOOST => 7,
:BERSERK => 5,
:BIGPECKS => 1,
:BLAZE => 5,
:BULLETPROOF => 7,
:CHEEKPOUCH => 4,
# :CHILLINGNEIGH => 0,
:CHLOROPHYLL => 6,
:CLEARBODY => 4,
:CLOUDNINE => 5,
:COLORCHANGE => 2,
:COMATOSE => 6,
:COMPETITIVE => 5,
:COMPOUNDEYES => 7,
:CONTRARY => 8,
:CORROSION => 5,
:COTTONDOWN => 3,
# :CURIOUSMEDICINE => 0,
:CURSEDBODY => 4,
:CUTECHARM => 2,
:DAMP => 2,
:DANCER => 5,
:DARKAURA => 6,
:DAUNTLESSSHIELD => 3,
:DAZZLING => 5,
:DEFEATIST => -1,
:DEFIANT => 5,
:DELTASTREAM => 10,
:DESOLATELAND => 10,
:DISGUISE => 8,
:DOWNLOAD => 7,
:DRAGONSMAW => 8,
:DRIZZLE => 9,
:DROUGHT => 9,
:DRYSKIN => 6,
:EARLYBIRD => 4,
:EFFECTSPORE => 4,
:ELECTRICSURGE => 8,
:EMERGENCYEXIT => 3,
:FAIRYAURA => 6,
:FILTER => 6,
:FLAMEBODY => 4,
:FLAREBOOST => 5,
:FLASHFIRE => 6,
:FLOWERGIFT => 4,
# :FLOWERVEIL => 0,
:FLUFFY => 5,
:FORECAST => 6,
:FOREWARN => 2,
# :FRIENDGUARD => 0,
:FRISK => 3,
:FULLMETALBODY => 4,
:FURCOAT => 7,
:GALEWINGS => 6,
:GALVANIZE => 8,
:GLUTTONY => 3,
:GOOEY => 5,
:GORILLATACTICS => 4,
:GRASSPELT => 2,
:GRASSYSURGE => 8,
# :GRIMNEIGH => 0,
:GULPMISSLE => 3,
:GUTS => 6,
:HARVEST => 5,
# :HEALER => 0,
:HEATPROOF => 5,
:HEAVYMETAL => -1,
# :HONEYGATHER => 0,
:HUGEPOWER => 10,
:HUNGERSWITCH => 2,
:HUSTLE => 7,
:HYDRATION => 4,
:HYPERCUTTER => 3,
:ICEBODY => 3,
:ICEFACE => 4,
:ICESCALES => 7,
# :ILLUMINATE => 0,
:ILLUSION => 8,
:IMMUNITY => 4,
:IMPOSTER => 9,
:INFILTRATOR => 6,
:INNARDSOUT => 5,
:INNERFOCUS => 2,
:INSOMNIA => 4,
:INTIMIDATE => 7,
:INTREPIDSWORD => 3,
:IRONBARBS => 6,
:IRONFIST => 6,
:JUSTIFIED => 4,
:KEENEYE => 1,
:KLUTZ => -1,
:LEAFGUARD => 2,
:LEVITATE => 7,
:LIBERO => 8,
:LIGHTMETAL => 2,
:LIGHTNINGROD => 7,
:LIMBER => 3,
:LIQUIDOOZE => 3,
:LIQUIDVOICE => 5,
:LONGREACH => 3,
:MAGICBOUNCE => 9,
:MAGICGUARD => 9,
:MAGICIAN => 3,
:MAGMAARMOR => 1,
:MAGNETPULL => 9,
:MARVELSCALE => 5,
:MEGALAUNCHER => 7,
:MERCILESS => 4,
:MIMICRY => 2,
# :MINUS => 0,
:MIRRORARMOR => 6,
:MISTYSURGE => 8,
:MOLDBREAKER => 7,
:MOODY => 10,
:MOTORDRIVE => 6,
:MOXIE => 7,
:MULTISCALE => 8,
:MULTITYPE => 8,
:MUMMY => 5,
:NATURALCURE => 7,
:NEUROFORCE => 6,
:NEUTRALIZINGGAS => 5,
:NOGUARD => 8,
:NORMALIZE => -1,
:OBLIVIOUS => 2,
:OVERCOAT => 5,
:OVERGROW => 5,
:OWNTEMPO => 3,
:PARENTALBOND => 10,
:PASTELVEIL => 4,
:PERISHBODY => -1,
:PICKPOCKET => 3,
:PICKUP => 1,
:PIXILATE => 8,
# :PLUS => 0,
:POISONHEAL => 8,
:POISONPOINT => 4,
:POISONTOUCH => 4,
:POWERCONSTRUCT => 10,
# :POWEROFALCHEMY => 0,
:POWERSPOT => 2,
:PRANKSTER => 8,
:PRESSURE => 5,
:PRIMORDIALSEA => 10,
:PRISMARMOR => 6,
:PROPELLORTAIL => 2,
:PROTEAN => 8,
:PSYCHICSURGE => 8,
:PUNKROCK => 2,
:PUREPOWER => 10,
:QUEENLYMAJESTY => 6,
# :QUICKDRAW => 0,
:QUICKFEET => 5,
:RAINDISH => 3,
:RATTLED => 3,
# :RECEIVER => 0,
:RECKLESS => 6,
:REFRIGERATE => 8,
:REGENERATOR => 8,
:RIPEN => 4,
:RIVALRY => 1,
:RKSSYSTEM => 8,
:ROCKHEAD => 5,
:ROUGHSKIN => 6,
# :RUNAWAY => 0,
:SANDFORCE => 4,
:SANDRUSH => 6,
:SANDSPIT => 5,
:SANDSTREAM => 9,
:SANDVEIL => 3,
:SAPSIPPER => 7,
:SCHOOLING => 6,
:SCRAPPY => 6,
:SCREENCLEANER => 3,
:SERENEGRACE => 8,
:SHADOWSHIELD => 8,
:SHADOWTAG => 10,
:SHEDSKIN => 7,
:SHEERFORCE => 8,
:SHELLARMOR => 2,
:SHIELDDUST => 5,
:SHIELDSDOWN => 6,
:SIMPLE => 8,
:SKILLLINK => 7,
:SLOWSTART => -2,
:SLUSHRUSH => 5,
:SNIPER => 3,
:SNOWCLOAK => 3,
:SNOWWARNING => 8,
:SOLARPOWER => 3,
:SOLIDROCK => 6,
:SOULHEART => 7,
:SOUNDPROOF => 4,
:SPEEDBOOST => 9,
:STAKEOUT => 6,
:STALL => -1,
:STALWART => 2,
:STAMINA => 6,
:STANCECHANGE => 10,
:STATIC => 4,
:STEADFAST => 2,
:STEAMENGINE => 3,
:STEELWORKER => 6,
:STEELYSPIRIT => 2,
:STENCH => 1,
:STICKYHOLD => 3,
:STORMDRAIN => 7,
:STRONGJAW => 6,
:STURDY => 6,
:SUCTIONCUPS => 2,
:SUPERLUCK => 3,
:SURGESURFER => 4,
:SWARM => 5,
:SWEETVEIL => 4,
:SWIFTSWIM => 6,
# :SYMBIOSIS => 0,
:SYNCHRONIZE => 4,
:TANGLEDFEET => 2,
:TANGLINGHAIR => 5,
:TECHNICIAN => 8,
# :TELEPATHY => 0,
:TERAVOLT => 7,
:THICKFAT => 7,
:TINTEDLENS => 7,
:TORRENT => 5,
:TOUGHCLAWS => 7,
:TOXICBOOST => 6,
:TRACE => 6,
:TRANSISTOR => 8,
:TRIAGE => 7,
:TRUANT => -2,
:TURBOBLAZE => 7,
:UNAWARE => 6,
:UNBURDEN => 7,
:UNNERVE => 3,
# :UNSEENFIST => 0,
:VICTORYSTAR => 6,
:VITALSPIRIT => 4,
:VOLTABSORB => 7,
:WANDERINGSPIRIT => 2,
:WATERABSORB => 7,
:WATERBUBBLE => 8,
:WATERCOMPACTION => 4,
:WATERVEIL => 4,
:WEAKARMOR => 2,
:WHITESMOKE => 4,
:WIMPOUT => 3,
:WONDERGUARD => 10,
:WONDERSKIN => 4,
:ZENMODE => -1
}
# TODO: This method assumes the ability isn't being negated. Should it return
# 0 if it is? The calculations that call this method separately check
# for it being negated, because they need to do something special in
# that case, so I think it's okay for this method to ignore negation.
def battler_wants_ability?(battler, ability = :NONE)
ability = ability.id if !ability.is_a?(Symbol) && ability.respond_to?("id")
# TODO: Ideally replace the above list of ratings with context-sensitive
# calculations. Should they all go in this method, or should there be
# more handlers for each ability?
ret = BASE_ABILITY_RATINGS[ability] || 0
return ret
end
end

View File

@@ -916,7 +916,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserLosesFireType",
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToSimple",
proc { |move, user, target, ai, battle|
@@ -924,9 +924,23 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToSimpl
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
}
)
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToSimple",
proc { |score, move, user, target, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active?
old_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
new_ability_rating = ai.battler_wants_ability?(target, :SIMPLE)
side_mult = (target.opposes?(user)) ? 1 : -1
if old_ability_rating > new_ability_rating
score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max
elsif old_ability_rating < new_ability_rating
score -= 4 * side_mult * [new_ability_rating - old_ability_rating, 3].max
end
next score
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToInsomnia",
proc { |move, user, target, ai, battle|
@@ -934,9 +948,23 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToInsom
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
}
)
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToInsomnia",
proc { |score, move, user, target, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active?
old_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
new_ability_rating = ai.battler_wants_ability?(target, :INSOMNIA)
side_mult = (target.opposes?(user)) ? 1 : -1
if old_ability_rating > new_ability_rating
score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max
elsif old_ability_rating < new_ability_rating
score -= 4 * side_mult * [new_ability_rating - old_ability_rating, 3].max
end
next score
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserAbilityToTargetAbility",
proc { |move, user, target, ai, battle|
@@ -946,16 +974,20 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetUserAbilityToTargetA
)
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)
score -= 50 if [:TRUANT, :SLOWSTART].include?(target.ability_id)
next Battle::AI::MOVE_USELESS_SCORE if !user.ability_active?
old_ability_rating = ai.battler_wants_ability?(user, user.ability_id)
new_ability_rating = ai.battler_wants_ability?(user, target.ability_id)
if old_ability_rating > new_ability_rating
score += 4 * [old_ability_rating - new_ability_rating, 3].max
elsif old_ability_rating < new_ability_rating
score -= 4 * [new_ability_rating - old_ability_rating, 3].max
end
next score
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToUserAbility",
proc { |move, user, target, ai, battle|
@@ -967,52 +999,87 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SetTargetAbilityToUserA
)
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)
score += 90 if [:TRUANT, :SLOWSTART].include?(user.ability_id)
next Battle::AI::MOVE_USELESS_SCORE if !target.ability_active?
old_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
new_ability_rating = ai.battler_wants_ability?(target, user.ability_id)
side_mult = (target.opposes?(user)) ? 1 : -1
if old_ability_rating > new_ability_rating
score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max
elsif old_ability_rating < new_ability_rating
score -= 4 * side_mult * [new_ability_rating - old_ability_rating, 3].max
end
next score
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("UserTargetSwapAbilities",
proc { |move, user, target, ai, battle|
next true if !user.ability || user.battler.unstoppableAbility? ||
user.ability_id == :WONDERGUARD
user.battler.ungainableAbility? || user.ability_id == :WONDERGUARD
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
}
)
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)
score -= 90 if [:TRUANT, :SLOWSTART].include?(target.ability_id)
next Battle::AI::MOVE_USELESS_SCORE if !user.ability_active? && !target.ability_active?
old_user_ability_rating = ai.battler_wants_ability?(user, user.ability_id)
new_user_ability_rating = ai.battler_wants_ability?(user, target.ability_id)
user_diff = new_user_ability_rating - old_user_ability_rating
user_diff = 0 if !user.ability_active?
old_target_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
new_target_ability_rating = ai.battler_wants_ability?(target, user.ability_id)
target_diff = new_target_ability_rating - old_target_ability_rating
target_diff = 0 if !target.ability_active?
side_mult = (target.opposes?(user)) ? 1 : -1
if user_diff > target_diff
score += 4 * side_mult * [user_diff - target_diff, 3].max
elsif target_diff < user_diff
score -= 4 * side_mult * [target_diff - user_diff, 3].max
end
next score
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("NegateTargetAbility",
proc { |move, user, target, ai, battle|
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
}
)
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbility",
proc { |score, move, user, target, ai, battle|
target_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
side_mult = (target.opposes?(user)) ? 1 : -1
if target_ability_rating > 0
score += 4 * side_mult * [target_ability_rating, 3].max
elsif target_ability_rating < 0
score -= 4 * side_mult * [target_ability_rating.abs, 3].max
end
next score
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbilityIfTargetActed",
proc { |score, move, user, target, ai, battle|
next score if target.effects[PBEffects::Substitute] > 0 || target.effects[PBEffects::GastroAcid]
next score if target.battler.unstoppableAbility?
next score if user.faster_than?(target)
next score + 10
target_ability_rating = ai.battler_wants_ability?(target, target.ability_id)
side_mult = (target.opposes?(user)) ? 1 : -1
if target_ability_rating > 0
score += 4 * side_mult * [target_ability_rating, 3].max
elsif target_ability_rating < 0
score -= 4 * side_mult * [target_ability_rating.abs, 3].max
end
next score
}
)
@@ -1134,7 +1201,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartGravity",
)
Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
proc { |score, move, user, ai, battle|
# TODO: Gravity increases accuracy of all moves. Should this be considered?
# TODO: Gravity increases accuracy of all moves. Prefer if user/ally has low
# accuracy moves, don't prefer if foes have them. Should "low
# accuracy" mean anything below 85%?
ai.each_battler do |b, i|
# Prefer grounding airborne foes, don't prefer grounding airborne allies
# Prefer making allies affected by terrain, don't prefer making foes

View File

@@ -58,7 +58,7 @@ Battle::AI::Handlers::MoveBasePower.add("LowerTargetHPToUserHP",
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("OHKO",
proc { |move, user, target, ai, battle|
@@ -71,27 +71,44 @@ Battle::AI::Handlers::MoveBasePower.add("OHKO",
next target.hp
}
)
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("OHKO",
proc { |score, move, user, target, ai, battle|
# Don't prefer if the target has less HP and user has a non-OHKO damaging move
if user.check_for_move { |m| !m.is_a?(Battle::Move::OHKO) && m.damagingMove? }
score -= 10 if target.hp <= target.totalhp / 2
score -= 10 if target.hp <= target.totalhp / 4
end
# TODO: Maybe predict dealt damage of all user's other moves, and score this
# move useless if another one can KO the target. Might also need to
# take into account whether those moves will fail. Might need to do
# this specially after all move scores are determined.
next score
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
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)
next true if target.has_type?(:ICE)
next Battle::AI::Handlers.move_will_fail_against_target?("OHKO", move, user, target, ai, battle)
}
)
Battle::AI::Handlers::MoveBasePower.copy("OHKO",
"OHKOIce")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("OHKO",
"OHKOIce")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("OHKO",
"OHKOHitsUndergroundTarget")
Battle::AI::Handlers::MoveBasePower.copy("OHKO",
"OHKOHitsUndergroundTarget")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("OHKO",
"OHKOHitsUndergroundTarget")
#===============================================================================
#
@@ -397,6 +414,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetNotAc
Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit",
proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if user.effects[PBEffects::LaserFocus] > 0
# TODO: Useless if user will already always critical hit ("AlwaysCriticalHit"
# or Lucky Chant/crit stage is +3/etc.).
next score + 10
}
)
@@ -517,6 +536,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenPhysicalDamageAgainstUserS
# Doesn't stack with Aurora Veil
next Battle::AI::MOVE_USELESS_SCORE if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
# Don't prefer the lower the user's HP is
# TODO: Should this HP check exist? The effect can still be set up for
# allies. Maybe just don't prefer if there are no replacement mons
# left.
if user.hp < user.totalhp / 2
score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30
end
@@ -543,6 +565,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenSpecialDamageAgainstUserSi
# Doesn't stack with Aurora Veil
next Battle::AI::MOVE_USELESS_SCORE if user.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
# Don't prefer the lower the user's HP is
# TODO: Should this HP check exist? The effect can still be set up for
# allies. Maybe just don't prefer if there are no replacement mons
# left.
if user.hp < user.totalhp / 2
score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30
end
@@ -571,6 +596,9 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHai
next Battle::AI::MOVE_USELESS_SCORE if user.pbOwnSide.effects[PBEffects::Reflect] > 0 &&
user.pbOwnSide.effects[PBEffects::LightScreen] > 0
# Don't prefer the lower the user's HP is
# TODO: Should this HP check exist? The effect can still be set up for
# allies. Maybe just don't prefer if there are no replacement mons
# left.
if user.hp < user.totalhp / 2
score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30
end
@@ -893,14 +921,18 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("EnsureNextMoveAlwaysHits
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
# TODO: This isn't the correct use of check_for_move, since it should just
# loop through them instead.
user.check_for_move do |m|
next if target.effects[PBEffects::Minimize] && m.tramplesMinimize? && Settings::MECHANICS_GENERATION >= 6
# TODO: There are other effects that make a move certain to hit. Account
# for those as well, or is that too micro-managey?
# for those as well. Score this move useless if no moves would
# benefit from locking on.
acc = m.accuracy
acc = m.pbBaseAccuracy(user.battler, target.battler) if ai.trainer.medium_skill?
score += 4 if acc < 90 && acc != 0
score += 4 if acc <= 50 && acc != 0
# TODO: Prefer more if m is a OHKO move.
end
# Not worth it if the user or the target is at low HP
score -= 10 if user.hp < user.totalhp / 2

View File

@@ -260,7 +260,7 @@ Battle::AI::Handlers::MoveBasePower.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
# In 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_against_target_score("TwoTurnAttack",

View File

@@ -159,27 +159,59 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SwitchOutTargetDamagingM
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTarget",
proc { |score, move, user, target, ai, battle|
next score + 40 if target.effects[PBEffects::Trapping] == 0
next score if target.effects[PBEffects::Trapping] > 0
next score if target.effects[PBEffects::Substitute] > 0
# Prefer if the user has a Binding Band or Grip Claw (because why have it if
# you don't want to use it?)
score += 5 if user.has_active_item?([:BINDINGBAND, :GRIPCLAW])
# Target will take damage at the end of each round from the binding
score += 8 if target.battler.takesIndirectDamage?
# Check whether the target will be trapped in battle by the binding
untrappable = Settings::MORE_TYPE_EFFECTS && target.has_type?(:GHOST)
if !untrappable && target.ability_active?
untrappable = Battle::AbilityEffects.triggerCertainSwitching(target.ability, target.battler, battle)
end
if !untrappable && target.item_active?
untrappable = Battle::ItemEffects.triggerCertainSwitching(target.ability, target.battler, battle)
end
if !untrappable && !target.battler.trappedInBattle?
score += 8 # Prefer if the target will become trapped by this move
eor_damage = target.rough_end_of_round_damage
if eor_damage > 0
# Prefer if the target will take damage at the end of each round on top
# of binding damage
score += 8
elsif eor_damage < 0
# Don't prefer if the target will heal itself at the end of each round
score -= 8
end
# Prefer if the target has been Perish Songed
score += 10 if target.effects[PBEffects::PerishSong] > 0
end
# Don't prefer if the target can remove the binding (and the binding has an
# effect)
if (!untrappable && !target.battler.trappedInBattle?) || target.battler.takesIndirectDamage?
if target.check_for_move { |m| m.function == "RemoveUserBindingAndEntryHazards" }
score -= 8
end
end
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveBasePower.add("BindTargetDoublePowerIfTargetUnderwater",
proc { |power, move, user, target, ai, battle|
next move.move.pbModifyDamage(power, user.battler, target.battler)
}
)
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTargetDoublePowerIfTargetUnderwater",
proc { |score, move, user, target, ai, battle|
next score + 40 if target.effects[PBEffects::Trapping] == 0
}
)
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("BindTarget",
"BindTargetDoublePowerIfTargetUnderwater")
#===============================================================================
# TODO: Review score modifiers.

View File

@@ -1,3 +1,6 @@
# TODO: Check all lingering effects to see if the AI needs to adjust itself
# because of them.
#===============================================================================
# TODO: Review score modifier.
#===============================================================================