More AI function codes, tweaked AI score threshold, renumbered all PBEffects constants

This commit is contained in:
Maruno17
2023-03-19 17:22:53 +00:00
parent e9a44377ce
commit e2648032c1
11 changed files with 402 additions and 233 deletions

View File

@@ -59,7 +59,7 @@ end
#===============================================================================
# After inflicting damage, user switches out. Ignores trapping moves.
# (U-turn, Volt Switch)
# (Flip Turn, U-turn, Volt Switch)
#===============================================================================
class Battle::Move::SwitchOutUserDamagingMove < Battle::Move
def pbEndOfMoveUsageEffect(user, targets, numHits, switchedBattlers)

View File

@@ -6,7 +6,7 @@ class Battle::AI
# Returns a value between 0.0 and 1.0. All move scores are lowered by this
# value multiplied by the highest-scoring move's score.
def move_score_threshold
return 0.6 + 0.35 * (([@trainer.skill, 100].min / 100.0) ** 0.5) # 0.6 to 0.95
return 0.6 + 0.3 * (([@trainer.skill, 100].min / 100.0) ** 0.5) # 0.6 to 0.9
end
#=============================================================================
@@ -147,8 +147,8 @@ class Battle::AI
move.pbOnStartUse(@user.battler, []) # Determine which move is used instead
move = Battle::Move.from_pokemon_move(@battle, Pokemon::Move.new(move.npMove))
end
@move.set_up(move)
@battle.moldBreaker = @user.has_mold_breaker?
@move.set_up(move)
end
def set_up_move_check_target(target)
@@ -158,6 +158,7 @@ class Battle::AI
if @target.battler.lastRegularMoveUsed &&
GameData::Move.get(@target.battler.lastRegularMoveUsed).has_flag?("CanMirrorMove")
mov = Battle::Move.from_pokemon_move(@battle, Pokemon::Move.new(@target.battler.lastRegularMoveUsed))
@battle.moldBreaker = @user.has_mold_breaker?
@move.set_up(mov)
end
end
@@ -291,7 +292,7 @@ class Battle::AI
# TODO: The above also applies if the move is Heal Pulse or a few other moves
# like that, which CAN target a foe but you'd never do so. Maybe use a
# move flag to determine such moves? The implication is that such moves
# wouldn't apply the "175 - score" bit, which would make their
# wouldn't apply the "185 - score" bit, which would make their
# MoveHandlers do the opposite calculations to other moves with the same
# targets, but is this desirable?
#=============================================================================
@@ -322,7 +323,7 @@ class Battle::AI
end
# TODO: Is this reversal of the score okay?
old_score = score
score = 175 - score
score = 185 - score
PBDebug.log_score_change(score - old_score, "score inverted (move targets ally but can target foe)")
end
return score

View File

@@ -299,6 +299,59 @@ class Battle::AI::AIBattler
return false
end
# NOTE: This specifically means "is not currently trapped but can become
# trapped by an effect". Similar to def pbCanSwitchOut? but this returns
# false if any certain switching OR certain trapping applies.
def can_become_trapped?
return false if fainted?
# Ability/item effects that allow switching no matter what
if ability_active? && Battle::AbilityEffects.triggerCertainSwitching(ability, @battler, @ai.battle)
return false
end
if item_active? && Battle::ItemEffects.triggerCertainSwitching(item, @battler, @ai.battle)
return false
end
# Other certain switching effects
return false if Settings::MORE_TYPE_EFFECTS && has_type?(:GHOST)
# Other certain trapping effects
return false if @battler.trappedInBattle?
# Trapping abilities/items
ai.each_foe_battler(side) do |b, i|
if b.ability_active? &&
Battle::AbilityEffects.triggerTrappingByTarget(b.ability, @battler, b.battler, @ai.battle)
return false
end
if b.item_active? &&
Battle::ItemEffects.triggerTrappingByTarget(b.item, @battler, b.battler, @ai.battle)
return false
end
end
return true
end
#=============================================================================
def wants_status_problem?(new_status)
return true if new_status == :NONE
if ability_active?
case ability_id
when :GUTS
return true if stat_raise_worthwhile?(self, :ATTACK, true)
when :MARVELSCALE
return true if stat_raise_worthwhile?(self, :DEFENSE, true)
when :QUICKFEET
return true if stat_raise_worthwhile?(self, :SPEED, true)
when :FLAREBOOST
return true if new_status == :BURN && stat_raise_worthwhile?(self, :SPECIAL_ATTACK, true)
end
end
return true if new_status == :SLEEP && check_for_move { |m| m.usableWhenAsleep? }
if has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed")
return true if [:POISON, :BURN, :PARALYSIS].include?(new_status)
end
return false
end
#=============================================================================
# TODO: Add more items.

View File

@@ -11,6 +11,8 @@ class Battle::AI::AIMove
def set_up(move)
@move = move
@move.calcType = rough_type
@ai.battle.moldBreaker ||= ["IgnoreTargetAbility",
"CategoryDependsOnHigherDamageIgnoreTargetAbility"].include?(function)
end
#=============================================================================

View File

@@ -455,13 +455,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAtkSpAtk1",
Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserMainStats1LoseThirdOfTotalHP",
proc { |move, user, ai, battle|
next true if user.hp <= [user.totalhp / 3, 1].max
will_fail = true
(move.move.statUp.length / 2).times do |i|
next if !user.battler.pbCanRaiseStatStage?(move.move.statUp[i * 2], user.battler, move.move)
will_fail = false
break
end
next will_fail
next Battle::AI::Handlers.move_will_fail?("RaiseUserAtkDef1", move, user, ai, battle)
}
)
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1LoseThirdOfTotalHP",
@@ -478,27 +472,35 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1LoseThirdOfTotalHP
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserMainStats1TrapUserInBattle",
proc { |move, user, ai, battle|
next true if user.effects[PBEffects::NoRetreat]
will_fail = true
(move.move.statUp.length / 2).times do |i|
next if !user.battler.pbCanRaiseStatStage?(move.move.statUp[i * 2], user.battler, move.move)
will_fail = false
break
end
next will_fail
next Battle::AI::Handlers.move_will_fail?("RaiseUserAtkDef1", move, user, ai, battle)
}
)
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1TrapUserInBattle",
proc { |score, move, user, ai, battle|
# Score for stat increase
score = ai.get_score_for_target_stat_raise(score, user, move.move.statUp)
# Score for trapping user in battle
if ai.trainer.medium_skill? && !user.battler.trappedInBattle?
score -= 10 if user.hp <= user.totalhp / 2
# Score for user becoming trapped in battle
if user.can_become_trapped? && battle.pbCanChooseNonActive?(user.index)
# Not worth trapping if user will faint this round anyway
eor_damage = user.rough_end_of_round_damage
if eor_damage >= user.hp
next (move.damagingMove?) ? score : Battle::AI::MOVE_USELESS_SCORE
end
# Score for user becoming trapped in battle
# TODO: These checks are related to desire to switch, and there can be a lot
# more things to consider, e.g. effectiveness of the target's moves
# against its foes. Also applies to other code that calls
# can_become_trapped?
if user.effects[PBEffects::PerishSong] > 0 ||
user.effects[PBEffects::Attract] >= 0 ||
eor_damage > 0
score -= 12
end
end
next score
}

View File

@@ -506,23 +506,16 @@ 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::MoveEffectAgainstTargetScore.add("CureTargetBurn",
proc { |score, move, user, target, ai, battle|
add_effect = move.get_score_change_for_additional_effect(user, target)
next score if add_effect == -999 # Additional effect will be negated
if target.status == :BURN
if target.opposes?(user)
score -= add_effect
score -= 10
else
score += add_effect
score += 10
end
score += 15 if target.wants_status_problem?(:BURN)
end
next score
}
@@ -1089,7 +1082,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbilityIfTar
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
# IgnoreTargetAbility

View File

@@ -267,13 +267,16 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetHPLessThanHalf",
"DoublePowerIfUserPoisonedBurnedParalyzed")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetHPLessThanHalf",
"DoublePowerIfTargetAsleepCureTarget")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetAsleepCureTarget",
proc { |score, move, user, target, ai, battle|
score -= 20 if target.status == :SLEEP && target.statusCount > 1 # Will cure status
if target.status == :SLEEP && target.statusCount > 1 # Will cure status
score -= 10
score += 15 if target.wants_status_problem?(:SLEEP)
end
next score
}
)
@@ -288,13 +291,16 @@ Battle::AI::Handlers::MoveBasePower.add("DoublePowerIfTargetPoisoned",
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetPoisoned",
"DoublePowerIfTargetParalyzedCureTarget")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetParalyzedCureTarget",
proc { |score, move, user, target, ai, battle|
score -= 20 if target.status == :PARALYSIS # Will cure status
if target.status == :PARALYSIS # Will cure status
score -= 10
score += 15 if target.wants_status_problem?(:PARALYSIS)
end
next score
}
)
@@ -1284,7 +1290,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("PoisonTarget",
"CategoryDependsOnHigherDamagePoisonTarget")
#===============================================================================
# TODO: Review score modifiers. Category part is already accounted for.
#
#===============================================================================
# CategoryDependsOnHigherDamageIgnoreTargetAbility

View File

@@ -116,7 +116,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHPLoseFlyingTypeTh
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CureTargetStatusHealUserHalfOfTotalHP",
proc { |move, user, target, ai, battle|
@@ -125,13 +125,9 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CureTargetStatusHealUse
)
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.
if target.opposes?(user)
# Will cure status
score -= 10
else
score += 15
end
score += 15 if target.wants_status_problem?(target.status)
# Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5
score -= 10
@@ -422,7 +418,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartLeechSeedTarget",
score += 15
end
# Don't prefer if target can remove the seed
if target.check_for_move { |m| m.is_a?(Battle::Move::RemoveUserBindingAndEntryHazards) }
if target.has_move_with_function?("RemoveUserBindingAndEntryHazards")
score -= 15
end
end

View File

@@ -165,13 +165,40 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartTargetCannotUseItem
)
#===============================================================================
# TODO: Review score modifiers.
# TODO: This code shouldn't make use of target.
#
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems",
proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if battle.field.effects[PBEffects::MagicRoom] > 0
score += 30 if !user.item # && target.item
next if battle.field.effects[PBEffects::MagicRoom] == 1 # About to expire anyway
any_held_items = false
total_want = 0 # Positive means foes want their items more than allies do
ai.each_battler do |b, i|
next if !b.item
# Skip b if its item is disabled
if ai.trainer.medium_skill?
if battle.field.effects[PBEffects::MagicRoom] > 0
# NOTE: Same as b.item_active? but ignoring the Magic Room part.
next if b.effects[PBEffects::Embargo] > 0
next if battle.corrosiveGas[b.index % 2][b.party_index]
next if b.has_active_ability?(:KLUTZ)
else
next if !b.item_active?
end
end
# Rate b's held item and add it to total_want
any_held_items = true
want = b.wants_item?(b.item_id)
total_want += (b.opposes?(user)) ? want : -want
end
# Alter score
next Battle::AI::MOVE_USELESS_SCORE if !any_held_items
if battle.field.effects[PBEffects::MagicRoom] > 0
next Battle::AI::MOVE_USELESS_SCORE if total_want >= 0
score -= [total_want, -5].max * 5 # Will enable items, prefer if allies affected more
else
next Battle::AI::MOVE_USELESS_SCORE if total_want <= 0
score += [total_want, 5].min * 5 # Will disable items, prefer if foes affected more
end
next score
}
)

View File

@@ -9,7 +9,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("FleeFromBattle",
Battle::AI::Handlers::MoveEffectScore.add("FleeFromBattle",
proc { |score, move, user, ai, battle|
# Generally don't prefer (don't want to end the battle too easily)
next score - 15
next score - 20
}
)
@@ -24,21 +24,19 @@ Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserStatusMove",
)
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserStatusMove",
proc { |score, move, user, ai, battle|
next score + 10 if user.wild?
# Wild Pokémon run from battle
next score - 20 if user.wild?
# Trainer-owned Pokémon switch out
if ai.trainer.has_skill_flag?("ReserveLastPokemon") && battle.pbTeamAbleNonActiveCount(user.index) == 1
score -= 60 # Don't switch in ace
else
score += 40 if user.effects[PBEffects::Confusion] > 0
total = 0
GameData::Stat.each_battle { |s| total += user.stages[s.id] }
if total <= 0 || user.turnCount == 0
score += 60
else
score -= total * 10
# special case: user has no damaging moves
score += 75 if !user.check_for_move { |m| m.damagingMove? }
end
next Battle::AI::MOVE_USELESS_SCORE # Don't switch in ace
end
# Prefer if the user switching out will lose a negative effect
score += 10 if user.effects[PBEffects::Confusion] > 1
# Prefer if the user doesn't have any damaging moves
# TODO: Check effectiveness of moves.
score += 15 if !user.check_for_move { |m| m.damagingMove? }
# Don't prefer the more stat raises the user has
GameData::Stat.each_battle { |s| score -= user.stages[s.id] * 5 }
next score
}
)
@@ -48,8 +46,14 @@ Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserStatusMove",
#===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserDamagingMove",
proc { |score, move, user, ai, battle|
next 0 if !battle.pbCanChooseNonActive?(user.index)
next 0 if ai.trainer.has_skill_flag?("ReserveLastPokemon") && battle.pbTeamAbleNonActiveCount(user.index) == 1 # Don't switch in ace
next score if !battle.pbCanChooseNonActive?(user.index)
# Don't want to switch in ace
score -= 20 if ai.trainer.has_skill_flag?("ReserveLastPokemon") &&
battle.pbTeamAbleNonActiveCount(user.index) == 1
# Prefer if the user switching out will lose a negative effect
score += 10 if user.effects[PBEffects::Confusion] > 1
# Don't prefer the more stat raises the user has
GameData::Stat.each_battle { |s| score -= user.stages[s.id] * 5 }
next score
}
)
@@ -72,6 +76,18 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetAtkSpAtk1Swi
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetAtkSpAtk1SwitchOutUser",
proc { |score, move, user, target, ai, battle|
score = ai.get_score_for_target_stat_drop(score, target, move.move.statDown, false)
if battle.pbCanChooseNonActive?(user.index)
# Don't want to switch in ace
score -= 20 if ai.trainer.has_skill_flag?("ReserveLastPokemon") &&
battle.pbTeamAbleNonActiveCount(user.index) == 1
# Prefer if the user switching out will lose a negative effect
score += 10 if user.effects[PBEffects::Confusion] > 1
# Prefer if the user doesn't have any damaging moves
# TODO: Check effectiveness of moves.
score += 15 if !user.check_for_move { |m| m.damagingMove? }
# Don't prefer the more stat raises the user has
GameData::Stat.each_battle { |s| score -= user.stages[s.id] * 5 }
end
next score
}
)
@@ -86,20 +102,16 @@ Battle::AI::Handlers::MoveFailureCheck.add("SwitchOutUserPassOnEffects",
)
Battle::AI::Handlers::MoveEffectScore.add("SwitchOutUserPassOnEffects",
proc { |score, move, user, ai, battle|
if battle.pbCanChooseNonActive?(user.index)
score -= 40 if user.effects[PBEffects::Confusion] > 0
total = 0
GameData::Stat.each_battle { |s| total += user.stages[s.id] }
if total <= 0 || user.turnCount == 0
score -= 60
else
score += total * 10
# special case: user has no damaging moves
score += 75 if !user.check_for_move { |m| m.damagingMove? }
end
else
score -= 100
end
# Don't want to switch in ace
score -= 20 if ai.trainer.has_skill_flag?("ReserveLastPokemon") &&
battle.pbTeamAbleNonActiveCount(user.index) == 1
# Don't prefer if the user will pass on a negative effect
score -= 10 if user.effects[PBEffects::Confusion] > 1
# Prefer if the user doesn't have any damaging moves
# TODO: Check effectiveness of moves.
score += 15 if !user.check_for_move { |m| m.damagingMove? }
# Prefer if the user will pass on good stat stages
GameData::Stat.each_battle { |s| score += user.stages[s.id] * 5 }
next score
}
)
@@ -162,14 +174,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTarget",
# 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?
if target.can_become_trapped?
score += 8 # Prefer if the target will become trapped by this move
eor_damage = target.rough_end_of_round_damage
if eor_damage > 0
@@ -185,8 +190,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTarget",
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.has_move_with_function?("RemoveUserBindingAndEntryHazards")
if target.can_become_trapped? || target.battler.takesIndirectDamage?
if ai.trainer.medium_skill? &&
target.has_move_with_function?("RemoveUserBindingAndEntryHazards")
score -= 8
end
end
@@ -206,8 +212,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("BindTarget",
"BindTargetDoublePowerIfTargetUnderwater")
#===============================================================================
# TODO: Review score modifiers.
# TODO: Include get_score_change_for_additional_effect usage.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TrapTargetInBattle",
proc { |move, user, target, ai, battle|
@@ -217,15 +222,56 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TrapTargetInBattle",
next false
}
)
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattle",
proc { |score, move, user, target, ai, battle|
if !target.can_become_trapped? || !battle.pbCanChooseNonActive?(target.index)
next (move.damagingMove?) ? score : Battle::AI::MOVE_USELESS_SCORE
end
# Not worth trapping if target will faint this round anyway
eor_damage = target.rough_end_of_round_damage
if eor_damage >= target.hp
next (move.damagingMove?) ? score : Battle::AI::MOVE_USELESS_SCORE
end
# Score for EOR damage (intentionally before Rapid Spin check)
hp_fraction = (Settings::MECHANICS_GENERATION >= 6) ? 8 : 16
if user.has_active_item?(:BINDINGBAND)
hp_fraction = (Settings::MECHANICS_GENERATION >= 6) ? 6 : 8
end
rounds_to_deplete_hp = (hp_fraction.to_f * target.hp / target.totalhp).ceil
score += 30 / rounds_to_deplete_hp
# Not worth trapping if target can remove the binding
if ai.trainer.medium_skill? &&
target.has_move_with_function?("RemoveUserBindingAndEntryHazards")
next (move.damagingMove?) ? score : Battle::AI::MOVE_USELESS_SCORE
end
# Score for being an additional effect
add_effect = move.get_score_change_for_additional_effect(user, target)
next score if add_effect == -999 # Additional effect will be negated
score += add_effect
# Score for target becoming trapped in battle
# TODO: These checks are related to desire to switch, and there can be a lot
# more things to consider, e.g. effectiveness of the target's moves
# against its foes. Also applies to other code that calls
# can_become_trapped?
if target.effects[PBEffects::PerishSong] > 0 ||
target.effects[PBEffects::Attract] >= 0 ||
eor_damage > 0
score += 12
end
next score
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.copy("TrapTargetInBattle",
"TrapTargetInBattleMainEffect")
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("TrapTargetInBattle",
"TrapTargetInBattleMainEffect")
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn",
proc { |move, user, target, ai, battle|
@@ -237,20 +283,63 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TrapTargetInBattleLower
)
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) &&
!target.battler.pbCanLowerStatStage?(:SPECIAL_DEFENSE, user.battler, move.move)
# Score for stat drop
score = ai.get_score_for_target_stat_drop(score, target, [:DEFENSE, 1, :SPECIAL_DEFENSE], false)
# Score for target becoming trapped in battle
if target.can_become_trapped? && battle.pbCanChooseNonActive?(target.index)
# Not worth trapping if target will faint this round anyway
eor_damage = target.rough_end_of_round_damage
if eor_damage >= target.hp
next (move.damagingMove?) ? score : Battle::AI::MOVE_USELESS_SCORE
end
# Not worth trapping if target can remove the binding
if target.has_move_with_function?("RemoveUserBindingAndEntryHazards")
next (move.damagingMove?) ? score : Battle::AI::MOVE_USELESS_SCORE
end
# Score for target becoming trapped in battle
# TODO: These checks are related to desire to switch, and there can be a lot
# more things to consider, e.g. effectiveness of the target's moves
# against its foes. Also applies to other code that calls
# can_become_trapped?
if target.effects[PBEffects::PerishSong] > 0 ||
target.effects[PBEffects::Attract] >= 0 ||
eor_damage > 0
score += 12
end
end
next score
}
)
#===============================================================================
# TODO: Review score modifiers.
#
#===============================================================================
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?
# NOTE: Don't worry about scoring for the user also becoming trapped in
# battle, because it knows this move and accepts what it's getting
# itself into.
if target.can_become_trapped? && battle.pbCanChooseNonActive?(target.index)
# Not worth trapping if target will faint this round anyway
eor_damage = target.rough_end_of_round_damage
if eor_damage >= target.hp
next (move.damagingMove?) ? score : Battle::AI::MOVE_USELESS_SCORE
end
# Not worth trapping if target can remove the binding
if ai.trainer.medium_skill? &&
target.has_move_with_function?("RemoveUserBindingAndEntryHazards")
next (move.damagingMove?) ? score : Battle::AI::MOVE_USELESS_SCORE
end
# Score for target becoming trapped in battle
# TODO: These checks are related to desire to switch, and there can be a lot
# more things to consider, e.g. effectiveness of the target's moves
# against its foes. Also applies to other code that calls
# can_become_trapped?
if target.effects[PBEffects::PerishSong] > 0 ||
target.effects[PBEffects::Attract] >= 0 ||
eor_damage > 0
score += 12
end
end
next score
}

View File

@@ -28,92 +28,92 @@ module PBEffects
Encore = 23
EncoreMove = 24
Endure = 25
ExtraType = 111
FirstPledge = 26
FlashFire = 27
Flinch = 28
FocusEnergy = 29
FocusPunch = 30
FollowMe = 31
Foresight = 32
FuryCutter = 33
GastroAcid = 34
GemConsumed = 35
Grudge = 36
HealBlock = 37
HelpingHand = 38
HyperBeam = 39
Illusion = 40
Imprison = 41
Ingrain = 42
Instruct = 43
Instructed = 44
JawLock = 45
KingsShield = 46
LaserFocus = 47
LeechSeed = 48
LockOn = 49
LockOnPos = 50
MagicBounce = 51
MagicCoat = 52
MagnetRise = 53
MeanLook = 54
MeFirst = 55
Metronome = 56
MicleBerry = 57
Minimize = 58
MiracleEye = 59
MirrorCoat = 60
MirrorCoatTarget = 61
MoveNext = 62
MudSport = 63
Nightmare = 64
NoRetreat = 65
Obstruct = 66
Octolock = 67
Outrage = 68
ParentalBond = 69
PerishSong = 70
PerishSongUser = 71
PickupItem = 72
PickupUse = 73
Pinch = 74 # Battle Palace only
Powder = 75
PowerTrick = 76
Prankster = 77
PriorityAbility = 78
PriorityItem = 79
Protect = 80
ProtectRate = 81
Quash = 82
Rage = 83
RagePowder = 84 # Used along with FollowMe
Rollout = 85
Roost = 86
ShellTrap = 87
SkyDrop = 88
SlowStart = 89
SmackDown = 90
Snatch = 91
SpikyShield = 92
Spotlight = 93
Stockpile = 94
StockpileDef = 95
StockpileSpDef = 96
Substitute = 97
TarShot = 98
Taunt = 99
Telekinesis = 100
ThroatChop = 101
Torment = 102
Toxic = 103
Transform = 104
TransformSpecies = 105
Trapping = 106 # Trapping move
TrappingMove = 107
TrappingUser = 108
Truant = 109
TwoTurnAttack = 110
ExtraType = 26
FirstPledge = 27
FlashFire = 28
Flinch = 29
FocusEnergy = 30
FocusPunch = 31
FollowMe = 32
Foresight = 33
FuryCutter = 34
GastroAcid = 35
GemConsumed = 36
Grudge = 37
HealBlock = 38
HelpingHand = 39
HyperBeam = 40
Illusion = 41
Imprison = 42
Ingrain = 43
Instruct = 44
Instructed = 45
JawLock = 46
KingsShield = 47
LaserFocus = 48
LeechSeed = 49
LockOn = 50
LockOnPos = 51
MagicBounce = 52
MagicCoat = 53
MagnetRise = 54
MeanLook = 55
MeFirst = 56
Metronome = 57
MicleBerry = 58
Minimize = 59
MiracleEye = 60
MirrorCoat = 61
MirrorCoatTarget = 62
MoveNext = 63
MudSport = 64
Nightmare = 65
NoRetreat = 66
Obstruct = 67
Octolock = 68
Outrage = 69
ParentalBond = 70
PerishSong = 71
PerishSongUser = 72
PickupItem = 73
PickupUse = 74
Pinch = 75 # Battle Palace only
Powder = 76
PowerTrick = 77
Prankster = 78
PriorityAbility = 79
PriorityItem = 80
Protect = 81
ProtectRate = 82
Quash = 83
Rage = 84
RagePowder = 85 # Used along with FollowMe
Rollout = 86
Roost = 87
ShellTrap = 88
SkyDrop = 89
SlowStart = 90
SmackDown = 91
Snatch = 92
SpikyShield = 93
Spotlight = 94
Stockpile = 95
StockpileDef = 96
StockpileSpDef = 97
Substitute = 98
TarShot = 99
Taunt = 100
Telekinesis = 101
ThroatChop = 102
Torment = 103
Toxic = 104
Transform = 105
TransformSpecies = 106
Trapping = 107 # Trapping move that deals EOR damage
TrappingMove = 108
TrappingUser = 109
Truant = 110
TwoTurnAttack = 111
Unburden = 112
Uproar = 113
WaterSport = 114
@@ -123,56 +123,56 @@ module PBEffects
#=============================================================================
# These effects apply to a battler position
#=============================================================================
FutureSightCounter = 0
FutureSightMove = 1
FutureSightUserIndex = 2
FutureSightUserPartyIndex = 3
HealingWish = 4
LunarDance = 5
Wish = 6
WishAmount = 7
WishMaker = 8
FutureSightCounter = 700
FutureSightMove = 701
FutureSightUserIndex = 702
FutureSightUserPartyIndex = 703
HealingWish = 704
LunarDance = 705
Wish = 706
WishAmount = 707
WishMaker = 708
#=============================================================================
# These effects apply to a side
#=============================================================================
AuroraVeil = 0
CraftyShield = 1
EchoedVoiceCounter = 2
EchoedVoiceUsed = 3
LastRoundFainted = 4
LightScreen = 5
LuckyChant = 6
MatBlock = 7
Mist = 8
QuickGuard = 9
Rainbow = 10
Reflect = 11
Round = 12
Safeguard = 13
SeaOfFire = 14
Spikes = 15
StealthRock = 16
StickyWeb = 17
Swamp = 18
Tailwind = 19
ToxicSpikes = 20
WideGuard = 21
AuroraVeil = 800
CraftyShield = 801
EchoedVoiceCounter = 802
EchoedVoiceUsed = 803
LastRoundFainted = 804
LightScreen = 805
LuckyChant = 806
MatBlock = 807
Mist = 808
QuickGuard = 809
Rainbow = 810
Reflect = 811
Round = 812
Safeguard = 813
SeaOfFire = 814
Spikes = 815
StealthRock = 816
StickyWeb = 817
Swamp = 818
Tailwind = 819
ToxicSpikes = 820
WideGuard = 821
#=============================================================================
# These effects apply to the battle (i.e. both sides)
#=============================================================================
AmuletCoin = 0
FairyLock = 1
FusionBolt = 2
FusionFlare = 3
Gravity = 4
HappyHour = 5
IonDeluge = 6
MagicRoom = 7
MudSportField = 8
PayDay = 9
TrickRoom = 10
WaterSportField = 11
WonderRoom = 12
AmuletCoin = 900
FairyLock = 901
FusionBolt = 902
FusionFlare = 903
Gravity = 904
HappyHour = 905
IonDeluge = 906
MagicRoom = 907
MudSportField = 908
PayDay = 909
TrickRoom = 910
WaterSportField = 911
WonderRoom = 912
end