mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-09 14:14:59 +00:00
More work on the AI, refactored stat stage multipliers
This commit is contained in:
@@ -562,8 +562,9 @@ Battle::AI::Handlers::MoveEffectScore.add("UserMakeSubstitute",
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
score += 5 if !b.check_for_move { |m| m.ignoresSubstitute?(b.battler) }
|
||||
end
|
||||
# TODO: Predict incoming damage, and prefer if it's greater than
|
||||
# user.totalhp / 4?
|
||||
# Prefer if the user lost more than a Substitute's worth of HP from the last
|
||||
# attack against it
|
||||
score += 7 if user.battler.lastHPLost >= user.totalhp / 4
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
@@ -518,8 +518,6 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRaiseUserAtk1WhenDamaged",
|
||||
if ai.trainer.has_skill_flag?("HPAware")
|
||||
next score if user.hp <= user.totalhp / 3
|
||||
end
|
||||
# TODO: Check whether any foe has damaging moves that will trigger the stat
|
||||
# raise?
|
||||
# Prefer if user benefits from a raised Attack stat
|
||||
score += 10 if ai.stat_raise_worthwhile?(user, :ATTACK)
|
||||
score += 7 if user.has_move_with_function?("PowerHigherWithUserPositiveStatStages")
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#===============================================================================
|
||||
# TODO: Should there be all the "next score" for status moves? Remember that
|
||||
# other function codes can call this code as part of their scoring.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SleepTarget",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -9,15 +8,16 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SleepTarget",
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SleepTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep anyway
|
||||
useless_score = (move.statusMove?) ? Battle::AI::MOVE_USELESS_SCORE : score
|
||||
next useless_score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep anyway
|
||||
# No score modifier if the sleep will be removed immediately
|
||||
next score if target.has_active_item?([:CHESTOBERRY, :LUMBERRY])
|
||||
next score if target.faster_than?(user) &&
|
||||
target.has_active_ability?(:HYDRATION) &&
|
||||
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
|
||||
next useless_score if target.has_active_item?([:CHESTOBERRY, :LUMBERRY])
|
||||
next useless_score if target.faster_than?(user) &&
|
||||
target.has_active_ability?(:HYDRATION) &&
|
||||
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
|
||||
if target.battler.pbCanSleep?(user.battler, false, move.move)
|
||||
add_effect = move.get_score_change_for_additional_effect(user, target)
|
||||
next score if add_effect == -999 # Additional effect will be negated
|
||||
next useless_score if add_effect == -999 # Additional effect will be negated
|
||||
score += add_effect
|
||||
# Inherent preference
|
||||
score += 15
|
||||
@@ -88,8 +88,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("SleepTarget",
|
||||
"SleepTargetNextTurn")
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Should there be all the "next score" for status moves? Remember that
|
||||
# other function codes can call this code as part of their scoring.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PoisonTarget",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -98,16 +97,16 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PoisonTarget",
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
|
||||
next Battle::AI::MOVE_USELESS_SCORE if move.statusMove? && target.has_active_ability?(:POISONHEAL)
|
||||
useless_score = (move.statusMove?) ? Battle::AI::MOVE_USELESS_SCORE : score
|
||||
next useless_score if target.has_active_ability?(:POISONHEAL)
|
||||
# No score modifier if the poisoning will be removed immediately
|
||||
next score if target.has_active_item?([:PECHABERRY, :LUMBERRY])
|
||||
next score if target.faster_than?(user) &&
|
||||
target.has_active_ability?(:HYDRATION) &&
|
||||
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
|
||||
next useless_score if target.has_active_item?([:PECHABERRY, :LUMBERRY])
|
||||
next useless_score if target.faster_than?(user) &&
|
||||
target.has_active_ability?(:HYDRATION) &&
|
||||
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
|
||||
if target.battler.pbCanPoison?(user.battler, false, move.move)
|
||||
add_effect = move.get_score_change_for_additional_effect(user, target)
|
||||
next score if add_effect == -999 # Additional effect will be negated
|
||||
next useless_score if add_effect == -999 # Additional effect will be negated
|
||||
score += add_effect
|
||||
# Inherent preference
|
||||
score += 15
|
||||
@@ -159,10 +158,10 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PoisonTargetLowerTarget
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTargetLowerTargetSpeed1",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("LowerTargetSpeed1",
|
||||
score, move, user, target, ai, battle)
|
||||
poison_score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget",
|
||||
0, move, user, target, ai, battle)
|
||||
score += poison_score if poison_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
score = ai.get_score_for_target_stat_drop(score, target, move.move.statDown, false)
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -176,8 +175,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("PoisonTarget",
|
||||
"BadPoisonTarget")
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Should there be all the "next score" for status moves? Remember that
|
||||
# other function codes can call this code as part of their scoring.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ParalyzeTarget",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -186,15 +184,15 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ParalyzeTarget",
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
|
||||
useless_score = (move.statusMove?) ? Battle::AI::MOVE_USELESS_SCORE : score
|
||||
# No score modifier if the paralysis will be removed immediately
|
||||
next score if target.has_active_item?([:CHERIBERRY, :LUMBERRY])
|
||||
next score if target.faster_than?(user) &&
|
||||
target.has_active_ability?(:HYDRATION) &&
|
||||
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
|
||||
next useless_score if target.has_active_item?([:CHERIBERRY, :LUMBERRY])
|
||||
next useless_score if target.faster_than?(user) &&
|
||||
target.has_active_ability?(:HYDRATION) &&
|
||||
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
|
||||
if target.battler.pbCanParalyze?(user.battler, false, move.move)
|
||||
add_effect = move.get_score_change_for_additional_effect(user, target)
|
||||
next score if add_effect == -999 # Additional effect will be negated
|
||||
next useless_score if add_effect == -999 # Additional effect will be negated
|
||||
score += add_effect
|
||||
# Inherent preference (because of the chance of full paralysis)
|
||||
score += 10
|
||||
@@ -262,17 +260,22 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("ParalyzeTarget",
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeFlinchTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
paralyze_score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
|
||||
0, move, user, target, ai, battle)
|
||||
flinch_score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
|
||||
0, move, user, target, ai, battle)
|
||||
if paralyze_score == Battle::AI::MOVE_USELESS_SCORE &&
|
||||
flinch_score == Battle::AI::MOVE_USELESS_SCORE
|
||||
next Battle::AI::MOVE_USELESS_SCORE
|
||||
end
|
||||
score += paralyze_score if paralyze_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
score += flinch_score if flinch_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Should there be all the "next score" for status moves? Remember that
|
||||
# other function codes can call this code as part of their scoring.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("BurnTarget",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -281,15 +284,15 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("BurnTarget",
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
|
||||
useless_score = (move.statusMove?) ? Battle::AI::MOVE_USELESS_SCORE : score
|
||||
# No score modifier if the burn will be removed immediately
|
||||
next score if target.has_active_item?([:RAWSTBERRY, :LUMBERRY])
|
||||
next score if target.faster_than?(user) &&
|
||||
target.has_active_ability?(:HYDRATION) &&
|
||||
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
|
||||
next useless_score if target.has_active_item?([:RAWSTBERRY, :LUMBERRY])
|
||||
next useless_score if target.faster_than?(user) &&
|
||||
target.has_active_ability?(:HYDRATION) &&
|
||||
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
|
||||
if target.battler.pbCanBurn?(user.battler, false, move.move)
|
||||
add_effect = move.get_score_change_for_additional_effect(user, target)
|
||||
next score if add_effect == -999 # Additional effect will be negated
|
||||
next useless_score if add_effect == -999 # Additional effect will be negated
|
||||
score += add_effect
|
||||
# Inherent preference
|
||||
score += 15
|
||||
@@ -339,17 +342,22 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnTarget",
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnFlinchTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
burn_score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
|
||||
0, move, user, target, ai, battle)
|
||||
flinch_score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
|
||||
0, move, user, target, ai, battle)
|
||||
if burn_score == Battle::AI::MOVE_USELESS_SCORE &&
|
||||
flinch_score == Battle::AI::MOVE_USELESS_SCORE
|
||||
next Battle::AI::MOVE_USELESS_SCORE
|
||||
end
|
||||
score += burn_score if burn_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
score += flinch_score if flinch_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Should there be all the "next score" for status moves? Remember that
|
||||
# other function codes can call this code as part of their scoring.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("FreezeTarget",
|
||||
proc { |move, user, target, ai, battle|
|
||||
@@ -358,15 +366,15 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("FreezeTarget",
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FreezeTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
|
||||
useless_score = (move.statusMove?) ? Battle::AI::MOVE_USELESS_SCORE : score
|
||||
# No score modifier if the freeze will be removed immediately
|
||||
next score if target.has_active_item?([:ASPEARBERRY, :LUMBERRY])
|
||||
next score if target.faster_than?(user) &&
|
||||
target.has_active_ability?(:HYDRATION) &&
|
||||
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
|
||||
next useless_score if target.has_active_item?([:ASPEARBERRY, :LUMBERRY])
|
||||
next useless_score if target.faster_than?(user) &&
|
||||
target.has_active_ability?(:HYDRATION) &&
|
||||
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
|
||||
if target.battler.pbCanFreeze?(user.battler, false, move.move)
|
||||
add_effect = move.get_score_change_for_additional_effect(user, target)
|
||||
next score if add_effect == -999 # Additional effect will be negated
|
||||
next useless_score if add_effect == -999 # Additional effect will be negated
|
||||
score += add_effect
|
||||
# Inherent preference
|
||||
score += 15
|
||||
@@ -413,10 +421,16 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("FreezeTarget",
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FreezeFlinchTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("FreezeTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
freeze_score = Battle::AI::Handlers.apply_move_effect_against_target_score("FreezeTarget",
|
||||
0, move, user, target, ai, battle)
|
||||
flinch_score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
|
||||
0, move, user, target, ai, battle)
|
||||
if freeze_score == Battle::AI::MOVE_USELESS_SCORE &&
|
||||
flinch_score == Battle::AI::MOVE_USELESS_SCORE
|
||||
next Battle::AI::MOVE_USELESS_SCORE
|
||||
end
|
||||
score += freeze_score if freeze_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
score += flinch_score if flinch_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -426,19 +440,17 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FreezeFlinchTarget",
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeBurnOrFreezeTarget",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
next score if target.effects[PBEffects::Yawn] > 0 # Target is going to fall asleep
|
||||
# No score modifier if the status problem will be removed immediately
|
||||
next score if target.has_active_item?(:LUMBERRY)
|
||||
next score if target.faster_than?(user) &&
|
||||
target.has_active_ability?(:HYDRATION) &&
|
||||
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
|
||||
# Scores for the possible effects
|
||||
score += (Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
|
||||
Battle::AI::MOVE_BASE_SCORE, move, user, target, ai, battle) - Battle::AI::MOVE_BASE_SCORE) / 3
|
||||
score += (Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
|
||||
Battle::AI::MOVE_BASE_SCORE, move, user, target, ai, battle) - Battle::AI::MOVE_BASE_SCORE) / 3
|
||||
score += (Battle::AI::Handlers.apply_move_effect_against_target_score("FreezeTarget",
|
||||
Battle::AI::MOVE_BASE_SCORE, move, user, target, ai, battle) - Battle::AI::MOVE_BASE_SCORE) / 3
|
||||
["ParalyzeTarget", "BurnTarget", "FreezeTarget"].each do |function_code|
|
||||
effect_score = Battle::AI::Handlers.apply_move_effect_against_target_score(function_code,
|
||||
0, move, user, target, ai, battle)
|
||||
score += effect_score / 3 if effect_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -461,22 +473,17 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("GiveUserStatusToTarget",
|
||||
# Curing the user's status problem
|
||||
score += 15 if !user.wants_status_problem?(user.status)
|
||||
# Giving the target a status problem
|
||||
case user.status
|
||||
when :SLEEP
|
||||
next Battle::AI::Handlers.apply_move_effect_against_target_score("SleepTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
when :PARALYSIS
|
||||
next Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
when :POISON
|
||||
next Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
when :BURN
|
||||
next Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
when :FROZEN
|
||||
next Battle::AI::Handlers.apply_move_effect_against_target_score("FreezeTarget",
|
||||
function_code = {
|
||||
:SLEEP => "SleepTarget",
|
||||
:PARALYSIS => "ParalyzeTarget",
|
||||
:POISON => "PoisonTarget",
|
||||
:BURN => "BurnTarget",
|
||||
:FROZEN => "FreezeTarget"
|
||||
}[user.status]
|
||||
if function_code
|
||||
new_score = Battle::AI::Handlers.apply_move_effect_against_target_score(function_code,
|
||||
score, move, user, target, ai, battle)
|
||||
next new_score if new_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
end
|
||||
next score
|
||||
}
|
||||
@@ -633,7 +640,6 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ConfuseTarget",
|
||||
score += 20 * target.hp / target.totalhp
|
||||
end
|
||||
# Prefer if the target is paralysed or infatuated, to compound the turn skipping
|
||||
# TODO: Also prefer if the target is trapped in battle or can't switch out?
|
||||
score += 8 if target.status == :PARALYSIS || target.effects[PBEffects::Attract] >= 0
|
||||
# Don't prefer if target benefits from being confused
|
||||
score -= 15 if target.has_active_ability?(:TANGLEDFEET)
|
||||
@@ -665,7 +671,6 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AttractTarget",
|
||||
# Inherent preference
|
||||
score += 15
|
||||
# Prefer if the target is paralysed or confused, to compound the turn skipping
|
||||
# TODO: Also prefer if the target is trapped in battle or can't switch out?
|
||||
score += 8 if target.status == :PARALYSIS || target.effects[PBEffects::Confusion] > 1
|
||||
# Don't prefer if the target can infatuate the user because of this move
|
||||
score -= 15 if target.has_active_item?(:DESTINYKNOT) &&
|
||||
|
||||
@@ -464,9 +464,6 @@ Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit",
|
||||
end
|
||||
# Prefer if user knows a damaging move which won't definitely critical hit
|
||||
if user.check_for_move { |m| m.damagingMove? && m.function != "AlwaysCriticalHit"}
|
||||
# TODO: Change the score depending on how much of an effect a critical hit
|
||||
# will have? Critical hits ignore the user's offensive stat drops
|
||||
# and the target's defensive stat raises, and multiply the damage.
|
||||
score += 15
|
||||
end
|
||||
next score
|
||||
@@ -521,9 +518,6 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPreventCriticalHitsAgainstUserSi
|
||||
crit_stage = 99 if b.check_for_move { |m| m.pbCritialOverride(b.battler, user.battler) > 0 }
|
||||
crit_stage = [crit_stage, Battle::Move::CRITICAL_HIT_RATIOS.length - 1].min
|
||||
end
|
||||
# TODO: Change the score depending on how much of an effect a critical hit
|
||||
# will have? Critical hits ignore the user's offensive stat drops
|
||||
# and the target's defensive stat raises, and multiply the damage.
|
||||
score += 8 * crit_stage if crit_stage > 0
|
||||
score += 10 if b.effects[PBEffects::LaserFocus] > 0
|
||||
end
|
||||
@@ -655,10 +649,7 @@ 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 ai.trainer.has_skill_flag?("HPAware")
|
||||
if ai.trainer.has_skill_flag?("HPAware") && battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
|
||||
if user.hp <= user.totalhp / 2
|
||||
score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15
|
||||
end
|
||||
@@ -686,10 +677,7 @@ 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 ai.trainer.has_skill_flag?("HPAware")
|
||||
if ai.trainer.has_skill_flag?("HPAware") && battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
|
||||
if user.hp <= user.totalhp / 2
|
||||
score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15
|
||||
end
|
||||
@@ -720,10 +708,7 @@ 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 ai.trainer.has_skill_flag?("HPAware")
|
||||
if ai.trainer.has_skill_flag?("HPAware") && battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
|
||||
if user.hp <= user.totalhp / 2
|
||||
score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15
|
||||
end
|
||||
@@ -767,8 +752,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUser",
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if !b.can_attack?
|
||||
next if !b.check_for_move { |m| m.canProtectAgainst? }
|
||||
# TODO: Include b's Unseen Fist somehow? We don't know which move b will
|
||||
# be using, so we don't know if Unseen Fist will apply.
|
||||
next if b.has_active_ability?(:UNSEENFIST) && b.check_for_move { |m| m.contactMove? }
|
||||
useless = false
|
||||
# General preference
|
||||
score += 7
|
||||
@@ -812,8 +796,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker",
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if !b.can_attack?
|
||||
next if !b.check_for_move { |m| m.canProtectAgainst? }
|
||||
# TODO: Include b's Unseen Fist somehow? We don't know which move b will
|
||||
# be using, so we don't know if Unseen Fist will apply.
|
||||
next if b.has_active_ability?(:UNSEENFIST) && b.check_for_move { |m| m.contactMove? }
|
||||
useless = false
|
||||
# General preference
|
||||
score += 7
|
||||
@@ -821,7 +804,9 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker",
|
||||
if b.check_for_move { |m| m.contactMove? }
|
||||
poison_score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget",
|
||||
0, move, user, b, ai, battle)
|
||||
score += poison_score / 2 # Halved because we don't know what move b will use
|
||||
if poison_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
score += poison_score / 2 # Halved because we don't know what move b will use
|
||||
end
|
||||
end
|
||||
# Prefer if the foe is in the middle of using a two turn attack
|
||||
score += 15 if b.effects[PBEffects::TwoTurnAttack] &&
|
||||
@@ -852,7 +837,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker",
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Special scoring for Aegislash.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShield",
|
||||
proc { |score, move, user, ai, battle|
|
||||
@@ -863,8 +848,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShie
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if !b.can_attack?
|
||||
next if !b.check_for_move { |m| m.damagingMove? && m.canProtectAgainst? }
|
||||
# TODO: Include b's Unseen Fist somehow? We don't know which move b will
|
||||
# be using, so we don't know if Unseen Fist will apply.
|
||||
next if b.has_active_ability?(:UNSEENFIST) && b.check_for_move { |m| m.contactMove? }
|
||||
useless = false
|
||||
# General preference
|
||||
score += 7
|
||||
@@ -898,6 +882,9 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShie
|
||||
# Don't prefer if the user used a protection move last turn, making this one
|
||||
# less likely to work
|
||||
score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10)
|
||||
# Aegislash
|
||||
score += 10 if user.battler.isSpecies?(:AEGISLASH) && user.form == 1 &&
|
||||
user.ability == :STANCECHANGE
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -914,8 +901,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct"
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if !b.can_attack?
|
||||
next if !b.check_for_move { |m| m.damagingMove? && m.canProtectAgainst? }
|
||||
# TODO: Include b's Unseen Fist somehow? We don't know which move b will
|
||||
# be using, so we don't know if Unseen Fist will apply.
|
||||
next if b.has_active_ability?(:UNSEENFIST) && b.check_for_move { |m| m.contactMove? }
|
||||
useless = false
|
||||
# General preference
|
||||
score += 7
|
||||
@@ -964,8 +950,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShi
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if !b.can_attack?
|
||||
next if !b.check_for_move { |m| m.canProtectAgainst? }
|
||||
# TODO: Include b's Unseen Fist somehow? We don't know which move b will
|
||||
# be using, so we don't know if Unseen Fist will apply.
|
||||
next if b.has_active_ability?(:UNSEENFIST) && b.check_for_move { |m| m.contactMove? }
|
||||
useless = false
|
||||
# General preference
|
||||
score += 7
|
||||
@@ -1016,8 +1001,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUse
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if !b.can_attack?
|
||||
next if !b.check_for_move { |m| m.damagingMove? && m.canProtectAgainst? }
|
||||
# TODO: Include b's Unseen Fist somehow? We don't know which move b will
|
||||
# be using, so we don't know if Unseen Fist will apply.
|
||||
next if b.has_active_ability?(:UNSEENFIST) && b.check_for_move { |m| m.contactMove? }
|
||||
useless = false
|
||||
# General preference
|
||||
score += 7
|
||||
@@ -1252,8 +1236,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilThirdOfDamageDealt
|
||||
score -= 25 * [dmg, user.hp].min / user.hp
|
||||
end
|
||||
# Score for paralysing
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
paralyze_score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
|
||||
0, move, user, target, ai, battle)
|
||||
score += paralyze_score if paralyze_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -1274,8 +1259,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilThirdOfDamageDealt
|
||||
score -= 25 * [dmg, user.hp].min / user.hp
|
||||
end
|
||||
# Score for burning
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
burn_score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
|
||||
0, move, user, target, ai, battle)
|
||||
score += burn_score if burn_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -1359,7 +1345,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("EnsureNextMoveAlwaysHits
|
||||
acc = m.pbBaseAccuracy(user.battler, target.battler) if ai.trainer.medium_skill?
|
||||
score += 5 if acc < 90 && acc != 0
|
||||
score += 8 if acc <= 50 && acc != 0
|
||||
# TODO: Prefer more if m is a OHKO move.
|
||||
score += 8 if m.is_a?(Battle::Move::OHKO)
|
||||
end
|
||||
# TODO: Prefer if target has increased evasion.
|
||||
# Not worth it if the user or the target is at low HP
|
||||
@@ -1535,10 +1521,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetMovesBecomeElectri
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: This could check all other battlers, not just foes. It could check the
|
||||
# effectivenesses of their Normal and Electric moves on all their foes,
|
||||
# not just on the user. I think this is overkill, particularly as the
|
||||
# effect only lasts for one round.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveEffectScore.add("NormalMovesBecomeElectric",
|
||||
proc { |score, move, user, ai, battle|
|
||||
|
||||
@@ -31,8 +31,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimesPoisonTarget"
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("HitTwoTimes",
|
||||
score, move, user, target, ai, battle)
|
||||
# Score for poisoning
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
poison_score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget",
|
||||
0, move, user, target, ai, battle)
|
||||
score += poison_score if poison_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -279,6 +280,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackParalyzeTar
|
||||
# Score for being a two turn attack
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||
score, move, user, target, ai, battle)
|
||||
next score if score == Battle::AI::MOVE_USELESS_SCORE
|
||||
# Score for paralysing
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
@@ -294,6 +296,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackBurnTarget"
|
||||
# Score for being a two turn attack
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||
score, move, user, target, ai, battle)
|
||||
next score if score == Battle::AI::MOVE_USELESS_SCORE
|
||||
# Score for burning
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
@@ -309,6 +312,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackFlinchTarge
|
||||
# Score for being a two turn attack
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||
score, move, user, target, ai, battle)
|
||||
next score if score == Battle::AI::MOVE_USELESS_SCORE
|
||||
# Score for flinching
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
@@ -323,11 +327,12 @@ Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserAtkDef1",
|
||||
"TwoTurnAttackRaiseUserSpAtkSpDefSpd2")
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackRaiseUserSpAtkSpDefSpd2",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
# Score for raising user's stats
|
||||
score = ai.get_score_for_target_stat_raise(score, user, move.move.statUp)
|
||||
# Score for being a two turn attack
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||
score, move, user, target, ai, battle)
|
||||
next score if score == Battle::AI::MOVE_USELESS_SCORE
|
||||
# Score for raising user's stats
|
||||
score = ai.get_score_for_target_stat_raise(score, user, move.move.statUp)
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -340,6 +345,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackChargeRaise
|
||||
# Score for being a two turn attack
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||
score, move, user, target, ai, battle)
|
||||
next score if score == Battle::AI::MOVE_USELESS_SCORE
|
||||
# Score for raising the user's stat
|
||||
score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserDefense1",
|
||||
score, move, user, ai, battle)
|
||||
@@ -355,6 +361,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackChargeRaise
|
||||
# Score for being a two turn attack
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||
score, move, user, target, ai, battle)
|
||||
next score if score == Battle::AI::MOVE_USELESS_SCORE
|
||||
# Score for raising the user's stat
|
||||
score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserSpAtk1",
|
||||
score, move, user, ai, battle)
|
||||
@@ -370,6 +377,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl
|
||||
# Score for being a two turn attack
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||
score, move, user, target, ai, battle)
|
||||
next score if score == Battle::AI::MOVE_USELESS_SCORE
|
||||
# Score for being semi-invulnerable underground
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
if b.check_for_move { |m| m.hitsDiggingTargets? }
|
||||
@@ -390,6 +398,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl
|
||||
# Score for being a two turn attack
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||
score, move, user, target, ai, battle)
|
||||
next score if score == Battle::AI::MOVE_USELESS_SCORE
|
||||
# Score for being semi-invulnerable underwater
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
if b.check_for_move { |m| m.hitsDivingTargets? }
|
||||
@@ -410,6 +419,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl
|
||||
# Score for being a two turn attack
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||
score, move, user, target, ai, battle)
|
||||
next score if score == Battle::AI::MOVE_USELESS_SCORE
|
||||
# Score for being semi-invulnerable in the sky
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
if b.check_for_move { |m| m.hitsFlyingTargets? }
|
||||
@@ -430,6 +440,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl
|
||||
# Score for being a two turn attack and semi-invulnerable in the sky
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttackInvulnerableInSky",
|
||||
score, move, user, target, ai, battle)
|
||||
next score if score == Battle::AI::MOVE_USELESS_SCORE
|
||||
# Score for paralyzing the target
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
|
||||
score, move, user, target, ai, battle)
|
||||
@@ -460,6 +471,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl
|
||||
# Score for being a two turn attack
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||
score, move, user, target, ai, battle)
|
||||
next score if score == Battle::AI::MOVE_USELESS_SCORE
|
||||
# Score for being invulnerable
|
||||
score += 8
|
||||
# Score for removing protections
|
||||
|
||||
@@ -97,11 +97,7 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHPLoseFlyingTypeTh
|
||||
score = Battle::AI::Handlers.apply_move_effect_score("HealUserHalfOfTotalHP",
|
||||
score, move, user, ai, battle)
|
||||
# User loses the Flying type this round
|
||||
if user.has_type?(:FLYING)
|
||||
# TODO: Decide whether losing the Flying type is good or bad. Look at
|
||||
# type effectiveness changes against the user, and for foes' Ground
|
||||
# moves (foe foes slower than the user). Anything else?
|
||||
end
|
||||
# NOTE: Not worth considering and scoring for.
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -118,7 +114,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CureTargetStatusHealUser
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
# Consider how much HP will be restored
|
||||
score = Battle::AI::Handlers.apply_move_effect_score("HealUserHalfOfTotalHP",
|
||||
score, move, user, ai, battle)
|
||||
score, move, user, ai, battle)
|
||||
# Will cure target's status
|
||||
score += (target.wants_status_problem?(target.status)) ? 10 : -8
|
||||
next score
|
||||
|
||||
@@ -217,8 +217,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserConsumeBerryRaiseDefense2",
|
||||
Battle::AI::Handlers::MoveEffectScore.add("UserConsumeBerryRaiseDefense2",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# Score for raising the user's stat
|
||||
score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserDefense2",
|
||||
score, move, user, ai, battle)
|
||||
stat_raise_score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserDefense2",
|
||||
0, move, user, ai, battle)
|
||||
score += stat_raise_score if stat_raise_score != Battle::AI::MOVE_USELESS_SCORE
|
||||
# Score for the consumed berry's effect
|
||||
score += user.get_score_change_for_consuming_item(user.item_id, true)
|
||||
# Score for other results of consuming the berry
|
||||
|
||||
Reference in New Issue
Block a user