Tweaked AI threshold score, added "HPAware" skill flag, changed lots of AI scores

This commit is contained in:
Maruno17
2023-03-30 21:11:27 +01:00
parent 0bb0fb4a26
commit ad29a79e1c
16 changed files with 828 additions and 748 deletions

View File

@@ -194,6 +194,7 @@ class Battle::Battler
if @effects[PBEffects::HyperBeam] > 0 # Intentionally before Truant if @effects[PBEffects::HyperBeam] > 0 # Intentionally before Truant
PBDebug.log("[Move failed] #{pbThis} is recharging after using #{move.name}") PBDebug.log("[Move failed] #{pbThis} is recharging after using #{move.name}")
@battle.pbDisplay(_INTL("{1} must recharge!", pbThis)) @battle.pbDisplay(_INTL("{1} must recharge!", pbThis))
@effects[PBEffects::Truant] = !@effects[PBEffects::Truant] if hasActiveAbility?(:TRUANT)
return false return false
end end
if choice[1] == -2 # Battle Palace if choice[1] == -2 # Battle Palace

View File

@@ -1,12 +1,12 @@
class Battle::AI class Battle::AI
MOVE_FAIL_SCORE = 25 MOVE_FAIL_SCORE = 20
MOVE_USELESS_SCORE = 60 # Move predicted to do nothing or just be detrimental MOVE_USELESS_SCORE = 60 # Move predicted to do nothing or just be detrimental
MOVE_BASE_SCORE = 100 MOVE_BASE_SCORE = 100
# Returns a value between 0.0 and 1.0. All move scores are lowered by this # 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. # value multiplied by the highest-scoring move's score.
def move_score_threshold def move_score_threshold
return 0.6 + 0.3 * (([@trainer.skill, 100].min / 100.0) ** 0.5) # 0.6 to 0.9 return 0.6 + 0.35 * (([@trainer.skill, 100].min / 100.0) ** 0.5) # 0.635 to 0.95
end end
#============================================================================= #=============================================================================

View File

@@ -125,12 +125,17 @@ class Battle::AI
"PowerHigherWithUserPositiveStatStages" "PowerHigherWithUserPositiveStatStages"
] ]
if !target.has_move_with_function?(*moves_that_prefer_high_speed) if !target.has_move_with_function?(*moves_that_prefer_high_speed)
# TODO: Not worth it if the target is too much slower than its foe(s)
# and can't be made fast enough.
each_foe_battler(target.side) do |b, i| each_foe_battler(target.side) do |b, i|
return true if b.faster_than?(target) return true if b.faster_than?(target)
end end
return false return false
end end
when :ACCURACY when :ACCURACY
# TODO: Yes if any of target's moves have lower accuracy, or target is
# affected by accuracy-lowering effects, or if target's foe(s) have
# increased evasion.
when :EVASION when :EVASION
end end
return true return true
@@ -151,22 +156,14 @@ class Battle::AI
# the foe anyway). # the foe anyway).
# Prefer if move is a status move and it's the user's first/second turn # Prefer if move is a status move and it's the user's first/second turn
if @user.turnCount < 2 && @move.statusMove? if @user.turnCount < 2 && @move.statusMove?
score += total_increment * desire_mult * 4 score += total_increment * desire_mult * 5
end end
# Prefer if user is at high HP, don't prefer if user is at low HP # Prefer if user is at high HP, don't prefer if user is at low HP
if target.index != @user.index if target.index != @user.index
if @user.hp >= @user.totalhp * 0.7 score += total_increment * desire_mult * ((100 * @user.hp / @user.totalhp) - 50) / 8 # +6 to -6 per stage
score += total_increment * desire_mult * 3
else
score += total_increment * desire_mult * ((100 * @user.hp / @user.totalhp) - 50) / 6 # +3 to -8 per stage
end
end end
# Prefer if target is at high HP, don't prefer if target is at low HP # Prefer if target is at high HP, don't prefer if target is at low HP
if target.hp >= target.totalhp * 0.7 score += total_increment * desire_mult * ((100 * target.hp / target.totalhp) - 50) / 8 # +6 to -6 per stage
score += total_increment * desire_mult * 4
else
score += total_increment * desire_mult * ((100 * target.hp / target.totalhp) - 50) / 4 # +5 to -12 per stage
end
# TODO: Look at abilities that trigger upon stat raise. There are none. # TODO: Look at abilities that trigger upon stat raise. There are none.
return score return score
end end
@@ -193,16 +190,16 @@ class Battle::AI
# Modify score depending on current stat stage # Modify score depending on current stat stage
# More strongly prefer if the target has no special moves # More strongly prefer if the target has no special moves
if old_stage >= 2 && increment == 1 if old_stage >= 2 && increment == 1
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult)
else else
has_special_moves = target.check_for_move { |m| m.specialMove?(m.type) } has_special_moves = target.check_for_move { |m| m.specialMove?(m.type) }
inc = (has_special_moves) ? 10 : 20 inc = (has_special_moves) ? 8 : 12
score += inc * inc_mult score += inc * inc_mult
end end
when :DEFENSE when :DEFENSE
# Modify score depending on current stat stage # Modify score depending on current stat stage
if old_stage >= 2 && increment == 1 if old_stage >= 2 && increment == 1
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult)
else else
score += 10 * inc_mult score += 10 * inc_mult
end end
@@ -210,29 +207,35 @@ class Battle::AI
# Modify score depending on current stat stage # Modify score depending on current stat stage
# More strongly prefer if the target has no physical moves # More strongly prefer if the target has no physical moves
if old_stage >= 2 && increment == 1 if old_stage >= 2 && increment == 1
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult)
else else
has_physical_moves = target.check_for_move { |m| m.physicalMove?(m.type) && has_physical_moves = target.check_for_move { |m| m.physicalMove?(m.type) &&
m.function != "UseUserDefenseInsteadOfUserAttack" && m.function != "UseUserDefenseInsteadOfUserAttack" &&
m.function != "UseTargetAttackInsteadOfUserAttack" } m.function != "UseTargetAttackInsteadOfUserAttack" }
inc = (has_physical_moves) ? 10 : 20 inc = (has_physical_moves) ? 8 : 12
score += inc * inc_mult score += inc * inc_mult
end end
when :SPECIAL_DEFENSE when :SPECIAL_DEFENSE
# Modify score depending on current stat stage # Modify score depending on current stat stage
if old_stage >= 2 && increment == 1 if old_stage >= 2 && increment == 1
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult)
else else
score += 10 * inc_mult score += 10 * inc_mult
end end
when :SPEED when :SPEED
# Prefer if target is slower than a foe # Prefer if target is slower than a foe
# TODO: Don't prefer if the target is too much slower than any foe that it target_speed = target.rough_stat(:SPEED)
# can't catch up.
each_foe_battler(target.side) do |b, i| each_foe_battler(target.side) do |b, i|
next if target.faster_than?(b) b_speed = b.rough_stat(:SPEED)
score += 15 * inc_mult next if b_speed > target_speed * 2.5 # Much too slow to reasonably catch up
break if b_speed > target_speed
if b_speed < target_speed * (increment + 2) / 2
score += 15 * inc_mult # Target will become faster than b
else
score += 8 * inc_mult
end
break
end
end end
# TODO: Prefer if the target is able to cause flinching (moves that # TODO: Prefer if the target is able to cause flinching (moves that
# flinch, or has King's Rock/Stench). # flinch, or has King's Rock/Stench).
@@ -242,21 +245,21 @@ class Battle::AI
"PowerHigherWithUserPositiveStatStages" "PowerHigherWithUserPositiveStatStages"
] ]
if target.has_move_with_function?(*moves_that_prefer_high_speed) if target.has_move_with_function?(*moves_that_prefer_high_speed)
score += 8 * inc_mult score += 5 * inc_mult
end end
# Don't prefer if any foe has Gyro Ball # Don't prefer if any foe has Gyro Ball
each_foe_battler(target.side) do |b, i| each_foe_battler(target.side) do |b, i|
next if !b.has_move_with_function?("PowerHigherWithTargetFasterThanUser") next if !b.has_move_with_function?("PowerHigherWithTargetFasterThanUser")
score -= 8 * inc_mult score -= 5 * inc_mult
end end
# Don't prefer if target has Speed Boost (will be gaining Speed anyway) # Don't prefer if target has Speed Boost (will be gaining Speed anyway)
if target.has_active_ability?(:SPEEDBOOST) if target.has_active_ability?(:SPEEDBOOST)
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
end end
when :ACCURACY when :ACCURACY
# Modify score depending on current stat stage # Modify score depending on current stat stage
if old_stage >= 2 && increment == 1 if old_stage >= 2 && increment == 1
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult)
else else
min_accuracy = 100 min_accuracy = 100
target.battler.moves.each do |m| target.battler.moves.each do |m|
@@ -272,11 +275,11 @@ class Battle::AI
# Prefer if a foe of the target will take damage at the end of the round # Prefer if a foe of the target will take damage at the end of the round
each_foe_battler(target.side) do |b, i| each_foe_battler(target.side) do |b, i|
eor_damage = b.rough_end_of_round_damage eor_damage = b.rough_end_of_round_damage
score += 4 * inc_mult if eor_damage > 0 score += 5 * inc_mult if eor_damage > 0
end end
# Modify score depending on current stat stage # Modify score depending on current stat stage
if old_stage >= 2 && increment == 1 if old_stage >= 2 && increment == 1
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult)
else else
score += 10 * inc_mult score += 10 * inc_mult
end end
@@ -419,6 +422,8 @@ class Battle::AI
"PowerHigherWithUserPositiveStatStages" "PowerHigherWithUserPositiveStatStages"
] ]
if !target.has_move_with_function?(*moves_that_prefer_high_speed) if !target.has_move_with_function?(*moves_that_prefer_high_speed)
# TODO: Not worth it if the target is too much faster than its foe(s)
# and can't be brought slow enough.
each_foe_battler(target.side) do |b, i| each_foe_battler(target.side) do |b, i|
return true if !b.faster_than?(target) return true if !b.faster_than?(target)
end end
@@ -445,22 +450,14 @@ class Battle::AI
# TODO: Don't prefer if target is semi-invulnerable and user is faster. # TODO: Don't prefer if target is semi-invulnerable and user is faster.
# Prefer if move is a status move and it's the user's first/second turn # Prefer if move is a status move and it's the user's first/second turn
if @user.turnCount < 2 && @move.statusMove? if @user.turnCount < 2 && @move.statusMove?
score += total_decrement * desire_mult * 4 score += total_decrement * desire_mult * 5
end end
# Prefer if user is at high HP, don't prefer if user is at low HP # Prefer if user is at high HP, don't prefer if user is at low HP
if target.index != @user.index if target.index != @user.index
if @user.hp >= @user.totalhp * 0.7 score += total_decrement * desire_mult * ((100 * @user.hp / @user.totalhp) - 50) / 8 # +6 to -6 per stage
score += total_decrement * desire_mult * 3
else
score += total_decrement * desire_mult * ((100 * @user.hp / @user.totalhp) - 50) / 6 # +3 to -8 per stage
end
end end
# Prefer if target is at high HP, don't prefer if target is at low HP # Prefer if target is at high HP, don't prefer if target is at low HP
if target.hp >= target.totalhp * 0.7 score += total_decrement * desire_mult * ((100 * target.hp / target.totalhp) - 50) / 8 # +6 to -6 per stage
score += total_decrement * desire_mult * 3
else
score += total_decrement * desire_mult * ((100 * target.hp / target.totalhp) - 50) / 6 # +3 to -8 per stage
end
# TODO: Look at abilities that trigger upon stat lowering. # TODO: Look at abilities that trigger upon stat lowering.
return score return score
end end
@@ -488,70 +485,76 @@ class Battle::AI
# Modify score depending on current stat stage # Modify score depending on current stat stage
# More strongly prefer if the target has no special moves # More strongly prefer if the target has no special moves
if old_stage <= -2 && decrement == 1 if old_stage <= -2 && decrement == 1
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult)
else else
has_special_moves = target.check_for_move { |m| m.specialMove?(m.type) } has_special_moves = target.check_for_move { |m| m.specialMove?(m.type) }
dec = (has_special_moves) ? 5 : 10 dec = (has_special_moves) ? 8 : 12
score += dec * dec_mult score += dec * dec_mult
end end
when :DEFENSE when :DEFENSE
# Modify score depending on current stat stage # Modify score depending on current stat stage
if old_stage <= -2 && decrement == 1 if old_stage <= -2 && decrement == 1
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult)
else else
score += 5 * dec_mult score += 10 * dec_mult
end end
when :SPECIAL_ATTACK when :SPECIAL_ATTACK
# Modify score depending on current stat stage # Modify score depending on current stat stage
# More strongly prefer if the target has no physical moves # More strongly prefer if the target has no physical moves
if old_stage <= -2 && decrement == 1 if old_stage <= -2 && decrement == 1
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult)
else else
has_physical_moves = target.check_for_move { |m| m.physicalMove?(m.type) && has_physical_moves = target.check_for_move { |m| m.physicalMove?(m.type) &&
m.function != "UseUserDefenseInsteadOfUserAttack" && m.function != "UseUserDefenseInsteadOfUserAttack" &&
m.function != "UseTargetAttackInsteadOfUserAttack" } m.function != "UseTargetAttackInsteadOfUserAttack" }
dec = (has_physical_moves) ? 5 : 10 dec = (has_physical_moves) ? 8 : 12
score += dec * dec_mult score += dec * dec_mult
end end
when :SPECIAL_DEFENSE when :SPECIAL_DEFENSE
# Modify score depending on current stat stage # Modify score depending on current stat stage
if old_stage <= -2 && decrement == 1 if old_stage <= -2 && decrement == 1
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult)
else else
score += 5 * dec_mult score += 10 * dec_mult
end end
when :SPEED when :SPEED
# Prefer if target is faster than an ally # Prefer if target is faster than an ally
# TODO: Don't prefer if the target is too much faster than any ally and target_speed = target.rough_stat(:SPEED)
# can't be brought slow enough.
each_foe_battler(target.side) do |b, i| each_foe_battler(target.side) do |b, i|
next if b.faster_than?(target) b_speed = b.rough_stat(:SPEED)
score += 15 * dec_mult next if target_speed > b_speed * 2.5 # Much too fast to reasonably be overtaken
break if target_speed > b_speed
if target_speed < b_speed * 2 / (decrement + 2)
score += 15 * inc_mult # Target will become slower than b
else
score += 8 * inc_mult
end
break
end
end end
# Prefer if any ally has Electro Ball # Prefer if any ally has Electro Ball
each_foe_battler(target.side) do |b, i| each_foe_battler(target.side) do |b, i|
next if !b.has_move_with_function?("PowerHigherWithUserFasterThanTarget") next if !b.has_move_with_function?("PowerHigherWithUserFasterThanTarget")
score += 8 * dec_mult score += 5 * dec_mult
end end
# Don't prefer if target has Speed Boost (will be gaining Speed anyway) # Don't prefer if target has Speed Boost (will be gaining Speed anyway)
if target.has_active_ability?(:SPEEDBOOST) if target.has_active_ability?(:SPEEDBOOST)
score -= 20 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult)
end end
when :ACCURACY when :ACCURACY
# Modify score depending on current stat stage # Modify score depending on current stat stage
if old_stage <= -2 && decrement == 1 if old_stage <= -2 && decrement == 1
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult)
else else
score += 5 * dec_mult score += 10 * dec_mult
end end
# TODO: Prefer if target is poisoned/toxiced/Leech Seeded/cursed. # TODO: Prefer if target is poisoned/toxiced/Leech Seeded/cursed.
when :EVASION when :EVASION
# Modify score depending on current stat stage # Modify score depending on current stat stage
if old_stage <= -2 && decrement == 1 if old_stage <= -2 && decrement == 1
score -= 15 * ((target.opposes?(@user)) ? 1 : desire_mult) score -= 10 * ((target.opposes?(@user)) ? 1 : desire_mult)
else else
score += 5 * dec_mult score += 10 * dec_mult
end end
end end
# Prefer if target has Stored Power # Prefer if target has Stored Power
@@ -588,40 +591,40 @@ class Battle::AI
when :Sun when :Sun
# Check for Fire/Water moves # Check for Fire/Water moves
if b.has_damaging_move_of_type?(:FIRE) if b.has_damaging_move_of_type?(:FIRE)
ret += (b.opposes?(move_user)) ? -8 : 8 ret += (b.opposes?(move_user)) ? -10 : 10
end end
if b.has_damaging_move_of_type?(:WATER) if b.has_damaging_move_of_type?(:WATER)
ret += (b.opposes?(move_user)) ? 8 : -8 ret += (b.opposes?(move_user)) ? 10 : -10
end end
# TODO: Check for freezing moves. # TODO: Check for freezing moves.
when :Rain when :Rain
# Check for Fire/Water moves # Check for Fire/Water moves
if b.has_damaging_move_of_type?(:WATER) if b.has_damaging_move_of_type?(:WATER)
ret += (b.opposes?(move_user)) ? -8 : 8 ret += (b.opposes?(move_user)) ? -10 : 10
end end
if b.has_damaging_move_of_type?(:FIRE) if b.has_damaging_move_of_type?(:FIRE)
ret += (b.opposes?(move_user)) ? 8 : -8 ret += (b.opposes?(move_user)) ? 10 : -10
end end
when :Sandstorm when :Sandstorm
# Check for battlers affected by sandstorm's effects # Check for battlers affected by sandstorm's effects
if b.battler.takesSandstormDamage? # End of round damage if b.battler.takesSandstormDamage? # End of round damage
ret += (b.opposes?(move_user)) ? 8 : -8 ret += (b.opposes?(move_user)) ? 10 : -10
end end
if b.has_type?(:ROCK) # +SpDef for Rock types if b.has_type?(:ROCK) # +SpDef for Rock types
ret += (b.opposes?(move_user)) ? -8 : 8 ret += (b.opposes?(move_user)) ? -10 : 10
end end
when :Hail when :Hail
# Check for battlers affected by hail's effects # Check for battlers affected by hail's effects
if b.battler.takesHailDamage? # End of round damage if b.battler.takesHailDamage? # End of round damage
ret += (b.opposes?(move_user)) ? 8 : -8 ret += (b.opposes?(move_user)) ? 10 : -10
end end
when :ShadowSky when :ShadowSky
# Check for battlers affected by Shadow Sky's effects # Check for battlers affected by Shadow Sky's effects
if b.has_damaging_move_of_type?(:SHADOW) if b.has_damaging_move_of_type?(:SHADOW)
ret += (b.opposes?(move_user)) ? 8 : -8 ret += (b.opposes?(move_user)) ? 10 : -10
end end
if b.battler.takesShadowSkyDamage? # End of round damage if b.battler.takesShadowSkyDamage? # End of round damage
ret += (b.opposes?(move_user)) ? 8 : -8 ret += (b.opposes?(move_user)) ? 10 : -10
end end
end end
# Check each battler's abilities/other moves affected by the new weather # Check each battler's abilities/other moves affected by the new weather
@@ -698,32 +701,32 @@ class Battle::AI
# Immunity to sleep # Immunity to sleep
# TODO: Check all battlers for sleep-inducing moves and other effects? # TODO: Check all battlers for sleep-inducing moves and other effects?
if b.status == :NONE if b.status == :NONE
ret += (b.opposes?(move_user)) ? -5 : 5 ret += (b.opposes?(move_user)) ? -8 : 8
end end
if b.effects[PBEffects::Yawn] > 0 if b.effects[PBEffects::Yawn] > 0
ret += (b.opposes?(move_user)) ? -10 : 10 ret += (b.opposes?(move_user)) ? -10 : 10
end end
# Check for Electric moves # Check for Electric moves
if b.has_damaging_move_of_type?(:ELECTRIC) if b.has_damaging_move_of_type?(:ELECTRIC)
ret += (b.opposes?(move_user)) ? -15 : 15 ret += (b.opposes?(move_user)) ? -10 : 10
end end
when :Grassy when :Grassy
# End of round healing # End of round healing
ret += (b.opposes?(move_user)) ? -10 : 10 ret += (b.opposes?(move_user)) ? -8 : 8
# Check for Grass moves # Check for Grass moves
if b.has_damaging_move_of_type?(:GRASS) if b.has_damaging_move_of_type?(:GRASS)
ret += (b.opposes?(move_user)) ? -15 : 15 ret += (b.opposes?(move_user)) ? -10 : 10
end end
when :Misty when :Misty
# Immunity to status problems/confusion # Immunity to status problems/confusion
# TODO: Check all battlers for status/confusion-inducing moves and other # TODO: Check all battlers for status/confusion-inducing moves and other
# effects? # effects?
if b.status == :NONE || b.effects[PBEffects::Confusion] == 0 if b.status == :NONE || b.effects[PBEffects::Confusion] == 0
ret += (b.opposes?(move_user)) ? -5 : 5 ret += (b.opposes?(move_user)) ? -8 : 8
end end
# Check for Dragon moves # Check for Dragon moves
if b.has_damaging_move_of_type?(:DRAGON) if b.has_damaging_move_of_type?(:DRAGON)
ret += (b.opposes?(move_user)) ? 15 : -15 ret += (b.opposes?(move_user)) ? 10 : -10
end end
when :Psychic when :Psychic
# Check for priority moves # Check for priority moves
@@ -732,7 +735,7 @@ class Battle::AI
end end
# Check for Psychic moves # Check for Psychic moves
if b.has_damaging_move_of_type?(:PSYCHIC) if b.has_damaging_move_of_type?(:PSYCHIC)
ret += (b.opposes?(move_user)) ? -15 : 15 ret += (b.opposes?(move_user)) ? -10 : 10
end end
end end
end end
@@ -745,7 +748,7 @@ class Battle::AI
}[terrain] }[terrain]
each_battler do |b, i| each_battler do |b, i|
if seed && b.has_active_item?(seed) if seed && b.has_active_item?(seed)
ret += (b.opposes?(move_user)) ? -15 : 15 ret += (b.opposes?(move_user)) ? -8 : 8
end end
end end
# Check for abilities/moves affected by the terrain # Check for abilities/moves affected by the terrain
@@ -773,20 +776,20 @@ class Battle::AI
ret += (b.opposes?(move_user)) ? -5 : 5 ret += (b.opposes?(move_user)) ? -5 : 5
end end
if abils && b.has_active_ability?(abils) if abils && b.has_active_ability?(abils)
ret += (b.opposes?(move_user)) ? -15 : 15 ret += (b.opposes?(move_user)) ? -8 : 8
end end
# Moves # Moves
if b.has_move_with_function?("EffectDependsOnEnvironment", if b.has_move_with_function?("EffectDependsOnEnvironment",
"SetUserTypesBasedOnEnvironment", "SetUserTypesBasedOnEnvironment",
"TypeAndPowerDependOnTerrain", "TypeAndPowerDependOnTerrain",
"UseMoveDependingOnEnvironment") "UseMoveDependingOnEnvironment")
ret += (b.opposes?(move_user)) ? -10 : 10 ret += (b.opposes?(move_user)) ? -5 : 5
end end
if good_moves && b.has_move_with_function?(*good_moves) if good_moves && b.has_move_with_function?(*good_moves)
ret += (b.opposes?(move_user)) ? -10 : 10 ret += (b.opposes?(move_user)) ? -5 : 5
end end
if bad_moves && b.has_move_with_function?(*bad_moves) if bad_moves && b.has_move_with_function?(*bad_moves)
ret += (b.opposes?(move_user)) ? 10 : -10 ret += (b.opposes?(move_user)) ? 5 : -5
end end
end end
end end

View File

@@ -29,7 +29,7 @@ Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:shiny_target,
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if target.wild? && target.battler.shiny? if target.wild? && target.battler.shiny?
old_score = score old_score = score
score -= 15 score -= 20
PBDebug.log_score_change(score - old_score, "avoid attacking a shiny wild Pokémon") PBDebug.log_score_change(score - old_score, "avoid attacking a shiny wild Pokémon")
end end
next score next score
@@ -46,7 +46,7 @@ Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:shiny_target,
# => Include EOR damage in this? # => Include EOR damage in this?
# => Prefer move if it will KO the target (moreso if user is slower than target) # => Prefer move if it will KO the target (moreso if user is slower than target)
#=============================================================================== #===============================================================================
Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:add_predicted_damage, Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:predicted_damage,
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if move.damagingMove? if move.damagingMove?
dmg = move.rough_damage dmg = move.rough_damage
@@ -128,7 +128,7 @@ Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:thawing_move_against_fr
if ai.trainer.medium_skill? && target.status == :FROZEN if ai.trainer.medium_skill? && target.status == :FROZEN
if move.rough_type == :FIRE || (Settings::MECHANICS_GENERATION >= 6 && move.move.thawsUser?) if move.rough_type == :FIRE || (Settings::MECHANICS_GENERATION >= 6 && move.move.thawsUser?)
old_score = score old_score = score
score -= 15 score -= 20
PBDebug.log_score_change(score - old_score, "thaws the target") PBDebug.log_score_change(score - old_score, "thaws the target")
end end
end end
@@ -205,7 +205,7 @@ Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:damaging_a_biding_targe
hits_possible += 1 if user.faster_than?(target) hits_possible += 1 if user.faster_than?(target)
if dmg * hits_possible + eor_dmg < target.hp * 1.05 if dmg * hits_possible + eor_dmg < target.hp * 1.05
old_score = score old_score = score
score -= 15 score -= 20
PBDebug.log_score_change(score - old_score, "don't want to damage the Biding target") PBDebug.log_score_change(score - old_score, "don't want to damage the Biding target")
end end
end end
@@ -227,7 +227,7 @@ Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:knocking_out_a_destiny_
dmg = move.rough_damage dmg = move.rough_damage
if dmg > target.hp * 1.05 # Predicted to KO the target if dmg > target.hp * 1.05 # Predicted to KO the target
old_score = score old_score = score
score -= 15 score -= 20
score -= 10 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0 score -= 10 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
PBDebug.log_score_change(score - old_score, "don't want to KO the Destiny Bonding target") PBDebug.log_score_change(score - old_score, "don't want to KO the Destiny Bonding target")
end end
@@ -264,7 +264,7 @@ Battle::AI::Handlers::GeneralMoveAgainstTargetScore.add(:target_can_Magic_Coat_o
score = Battle::AI::MOVE_USELESS_SCORE score = Battle::AI::MOVE_USELESS_SCORE
PBDebug.log_score_change(score - old_score, "useless because target will Magic Bounce it") PBDebug.log_score_change(score - old_score, "useless because target will Magic Bounce it")
elsif target.has_move_with_function?("BounceBackProblemCausingStatusMoves") elsif target.has_move_with_function?("BounceBackProblemCausingStatusMoves")
score -= 8 score -= 7
PBDebug.log_score_change(score - old_score, "target knows Magic Coat and could bounce it") PBDebug.log_score_change(score - old_score, "target knows Magic Coat and could bounce it")
end end
end end
@@ -286,7 +286,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:any_foe_can_Magic_Coat_or_Bounce_mov
PBDebug.log_score_change(score - old_score, "useless because a foe will Magic Bounce it") PBDebug.log_score_change(score - old_score, "useless because a foe will Magic Bounce it")
break break
elsif b.has_move_with_function?("BounceBackProblemCausingStatusMoves") elsif b.has_move_with_function?("BounceBackProblemCausingStatusMoves")
score -= 8 score -= 7
PBDebug.log_score_change(score - old_score, "a foe knows Magic Coat and could bounce it") PBDebug.log_score_change(score - old_score, "a foe knows Magic Coat and could bounce it")
break break
end end
@@ -307,7 +307,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:any_battler_can_Snatch_move,
next if b.effects[PBEffects::SkyDrop] >= 0 next if b.effects[PBEffects::SkyDrop] >= 0
next if !b.has_move_with_function?("StealAndUseBeneficialStatusMove") next if !b.has_move_with_function?("StealAndUseBeneficialStatusMove")
old_score = score old_score = score
score -= 8 score -= 7
PBDebug.log_score_change(score - old_score, "another battler could Snatch it") PBDebug.log_score_change(score - old_score, "another battler could Snatch it")
break break
end end
@@ -335,10 +335,10 @@ Battle::AI::Handlers::GeneralMoveScore.add(:thawing_move_when_frozen,
if ai.trainer.medium_skill? && user.status == :FROZEN if ai.trainer.medium_skill? && user.status == :FROZEN
old_score = score old_score = score
if move.move.thawsUser? if move.move.thawsUser?
score += 30 score += 20
PBDebug.log_score_change(score - old_score, "move will thaw the user") PBDebug.log_score_change(score - old_score, "move will thaw the user")
elsif user.check_for_move { |m| m.thawsUser? } elsif user.check_for_move { |m| m.thawsUser? }
score -= 30 # Don't prefer this move if user knows another move that thaws score -= 20 # Don't prefer this move if user knows another move that thaws
PBDebug.log_score_change(score - old_score, "user knows another move will thaw it") PBDebug.log_score_change(score - old_score, "user knows another move will thaw it")
end end
end end
@@ -354,7 +354,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:dance_move_against_dancer,
if move.move.danceMove? if move.move.danceMove?
old_score = score old_score = score
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
score -= 12 if b.has_active_ability?(:DANCER) score -= 10 if b.has_active_ability?(:DANCER)
end end
PBDebug.log_score_change(score - old_score, "don't want to use a dance move because a foe has Dancer") PBDebug.log_score_change(score - old_score, "don't want to use a dance move because a foe has Dancer")
end end
@@ -381,10 +381,12 @@ Battle::AI::Handlers::GeneralMoveScore.add(:good_move_for_choice_item,
# Don't prefer moves which are 0x against at least one type # Don't prefer moves which are 0x against at least one type
move_type = move.rough_type move_type = move.rough_type
GameData::Type.each do |type_data| GameData::Type.each do |type_data|
score -= 5 if type_data.immunities.include?(move_type) score -= 8 if type_data.immunities.include?(move_type)
end end
# Don't prefer moves with lower accuracy # Don't prefer moves with lower accuracy
score = score * move.accuracy / 100 if move.accuracy > 0 if move.accuracy > 0
score -= (0.4 * (100 - move.accuracy)).to_i # -0 (100%) to -39 (1%)
end
# Don't prefer moves with low PP # Don't prefer moves with low PP
score -= 10 if move.move.pp <= 5 score -= 10 if move.move.pp <= 5
PBDebug.log_score_change(score - old_score, "move is less suitable to be Choiced into") PBDebug.log_score_change(score - old_score, "move is less suitable to be Choiced into")
@@ -400,7 +402,7 @@ Battle::AI::Handlers::GeneralMoveScore.add(:good_move_for_choice_item,
# more (desperate). # more (desperate).
# TODO: Review score modifier. # TODO: Review score modifier.
#=============================================================================== #===============================================================================
Battle::AI::Handlers::GeneralMoveScore.add(:either_side_down_to_last_pokemon, Battle::AI::Handlers::GeneralMoveScore.add(:damaging_move_and_either_side_no_reserves,
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
if ai.trainer.medium_skill? && move.damagingMove? if ai.trainer.medium_skill? && move.damagingMove?
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)

View File

@@ -13,6 +13,7 @@
# PredictMoveFailure # PredictMoveFailure
# ScoreMoves # ScoreMoves
# PreferMultiTargetMoves # PreferMultiTargetMoves
# HPAware (considers HP values of user/target for "worth it?" score changes)
# ConsiderSwitching (can choose to switch out Pokémon) # ConsiderSwitching (can choose to switch out Pokémon)
# ReserveLastPokemon (don't switch it in if possible) # ReserveLastPokemon (don't switch it in if possible)
# UsePokemonInOrder (uses earliest-listed Pokémon possible) # UsePokemonInOrder (uses earliest-listed Pokémon possible)
@@ -58,7 +59,10 @@ class Battle::AI::AITrainer
@skill_flags.push("ScoreMoves") @skill_flags.push("ScoreMoves")
@skill_flags.push("PreferMultiTargetMoves") @skill_flags.push("PreferMultiTargetMoves")
end end
@skill_flags.push("ConsiderSwitching") if medium_skill? if medium_skill?
@skill_flags.push("ConsiderSwitching")
@skill_flags.push("HPAware")
end
if !medium_skill? if !medium_skill?
@skill_flags.push("UsePokemonInOrder") @skill_flags.push("UsePokemonInOrder")
elsif best_skill? elsif best_skill?

View File

@@ -55,13 +55,6 @@ class Battle::AI::AIBattler
def idxOpposingSide; return @battler.idxOpposingSide; end def idxOpposingSide; return @battler.idxOpposingSide; end
def pbOpposingSide; return @battler.pbOpposingSide; end def pbOpposingSide; return @battler.pbOpposingSide; end
def faster_than?(other)
return false if other.nil?
this_speed = rough_stat(:SPEED)
other_speed = other.rough_stat(:SPEED)
return (this_speed > other_speed) ^ (@ai.battle.field.effects[PBEffects::TrickRoom] > 0)
end
#============================================================================= #=============================================================================
# Returns how much damage this battler will take at the end of this round. # Returns how much damage this battler will take at the end of this round.
@@ -167,8 +160,6 @@ class Battle::AI::AIBattler
#============================================================================= #=============================================================================
def speed; return @battler.speed; end
def base_stat(stat) def base_stat(stat)
ret = 0 ret = 0
case stat case stat
@@ -190,6 +181,13 @@ class Battle::AI::AIBattler
return (value.to_f * stageMul[stage] / stageDiv[stage]).floor return (value.to_f * stageMul[stage] / stageDiv[stage]).floor
end end
def faster_than?(other)
return false if other.nil?
this_speed = rough_stat(:SPEED)
other_speed = other.rough_stat(:SPEED)
return (this_speed > other_speed) ^ (@ai.battle.field.effects[PBEffects::TrickRoom] > 0)
end
#============================================================================= #=============================================================================
def types; return @battler.types; end def types; return @battler.types; end
@@ -423,6 +421,7 @@ class Battle::AI::AIBattler
# Return values are typically between -10 and +10. 0 is indifferent, positive # Return values are typically between -10 and +10. 0 is indifferent, positive
# values mean this battler benefits, negative values mean this battler suffers. # values mean this battler benefits, negative values mean this battler suffers.
def wants_item?(item) def wants_item?(item)
item = :NONE if !item
item = item.id if !item.is_a?(Symbol) && item.respond_to?("id") item = item.id if !item.is_a?(Symbol) && item.respond_to?("id")
return 0 if has_active_ability?(:KLUTZ) return 0 if has_active_ability?(:KLUTZ)
# TODO: Unnerve, other item-negating effects. # TODO: Unnerve, other item-negating effects.
@@ -511,7 +510,7 @@ class Battle::AI::AIBattler
end end
# Prefer if this battler knows Fling and it will do a lot of damage/have an # Prefer if this battler knows Fling and it will do a lot of damage/have an
# additional (negative) effect when flung # additional (negative) effect when flung
if has_move_with_function?("ThrowUserItemAtTarget") if item != :NONE && has_move_with_function?("ThrowUserItemAtTarget")
GameData::Item.get(item).flags.each do |flag| GameData::Item.get(item).flags.each do |flag|
next if !flag[/^Fling_(\d+)$/i] next if !flag[/^Fling_(\d+)$/i]
amt = $~[1].to_i amt = $~[1].to_i
@@ -533,12 +532,12 @@ class Battle::AI::AIBattler
#============================================================================= #=============================================================================
# Items can be consumed by Stuff Cheeks, Teatime, Bug Bite/Pluck and Fling. # Items can be consumed by Stuff Cheeks, Teatime, Bug Bite/Pluck and Fling.
def get_score_change_for_consuming_item(item) def get_score_change_for_consuming_item(item, try_preserving_item = false)
ret = 0 ret = 0
case item case item
when :ORANBERRY, :BERRYJUICE, :ENIGMABERRY, :SITRUSBERRY when :ORANBERRY, :BERRYJUICE, :ENIGMABERRY, :SITRUSBERRY
# Healing # Healing
ret += (hp > totalhp * 3 / 4) ? -8 : 8 ret += (hp > totalhp * 0.75) ? -6 : 6
ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN)
when :AGUAVBERRY, :FIGYBERRY, :IAPAPABERRY, :MAGOBERRY, :WIKIBERRY when :AGUAVBERRY, :FIGYBERRY, :IAPAPABERRY, :MAGOBERRY, :WIKIBERRY
# Healing with confusion # Healing with confusion
@@ -548,7 +547,7 @@ class Battle::AI::AIBattler
elsif Settings::MECHANICS_GENERATION >= 8 elsif Settings::MECHANICS_GENERATION >= 8
fraction_to_heal = 3 fraction_to_heal = 3
end end
ret += (hp > totalhp * (1 - (1 / fraction_to_heal))) ? -8 : 8 ret += (hp > totalhp * (1 - (1.0 / fraction_to_heal))) ? -6 : 6
ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN)
# TODO: Check whether the item will cause confusion? # TODO: Check whether the item will cause confusion?
when :ASPEARBERRY, :CHERIBERRY, :CHESTOBERRY, :PECHABERRY, :RAWSTBERRY when :ASPEARBERRY, :CHERIBERRY, :CHESTOBERRY, :PECHABERRY, :RAWSTBERRY
@@ -560,21 +559,25 @@ class Battle::AI::AIBattler
:PECHABERRY => :POISON, :PECHABERRY => :POISON,
:RAWSTBERRY => :BURN :RAWSTBERRY => :BURN
}[item] }[item]
ret += (cured_status && status == cured_status) ? 8 : -8 ret += (cured_status && status == cured_status) ? 6 : -6
when :PERSIMBERRY when :PERSIMBERRY
# Confusion cure # Confusion cure
ret += (effects[PBEffects::Confusion] > 1) ? 8 : -8 ret += (effects[PBEffects::Confusion] > 1) ? 6 : -6
when :LUMBERRY when :LUMBERRY
# Any status/confusion cure # Any status/confusion cure
ret += (status != :NONE || effects[PBEffects::Confusion] > 1) ? 8 : -8 ret += (status != :NONE || effects[PBEffects::Confusion] > 1) ? 6 : -6
when :MENTALHERB when :MENTALHERB
# Cure mental effects # Cure mental effects
ret += 8 if effects[PBEffects::Attract] >= 0 || if effects[PBEffects::Attract] >= 0 ||
effects[PBEffects::Taunt] > 1 || effects[PBEffects::Taunt] > 1 ||
effects[PBEffects::Encore] > 1 || effects[PBEffects::Encore] > 1 ||
effects[PBEffects::Torment] || effects[PBEffects::Torment] ||
effects[PBEffects::Disable] > 1 || effects[PBEffects::Disable] > 1 ||
effects[PBEffects::HealBlock] > 1 effects[PBEffects::HealBlock] > 1
ret += 6
else
ret -= 6
end
when :APICOTBERRY, :GANLONBERRY, :LIECHIBERRY, :PETAYABERRY, :SALACBERRY, when :APICOTBERRY, :GANLONBERRY, :LIECHIBERRY, :PETAYABERRY, :SALACBERRY,
:KEEBERRY, :MARANGABERRY :KEEBERRY, :MARANGABERRY
# Stat raise # Stat raise
@@ -587,7 +590,7 @@ class Battle::AI::AIBattler
:KEEBERRY => :DEFENSE, :KEEBERRY => :DEFENSE,
:MARANGABERRY => :SPECIAL_DEFENSE :MARANGABERRY => :SPECIAL_DEFENSE
}[item] }[item]
ret += 8 if stat && @ai.stat_raise_worthwhile?(self, stat) ret += (stat && @ai.stat_raise_worthwhile?(self, stat)) ? 8 : -8
ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN)
when :STARFBERRY when :STARFBERRY
# Random stat raise # Random stat raise
@@ -595,24 +598,19 @@ class Battle::AI::AIBattler
ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN)
when :WHITEHERB when :WHITEHERB
# Resets lowered stats # Resets lowered stats
reduced_stats = false ret += (@battler.hasLoweredStatStages?) ? 8 : -8
GameData::Stat.each_battle do |s|
next if stages[s.id] >= 0
reduced_stats = true
break
end
ret += 8 if reduced_stats
when :MICLEBERRY when :MICLEBERRY
# Raises accuracy of next move # Raises accuracy of next move
ret += 8 ret += (@ai.stat_raise_worthwhile?(self, :ACCURACY, true)) ? 6 : -6
when :LANSATBERRY when :LANSATBERRY
# Focus energy # Focus energy
ret += 8 if effects[PBEffects::FocusEnergy] < 2 ret += (effects[PBEffects::FocusEnergy] < 2) ? 6 : -6
when :LEPPABERRY when :LEPPABERRY
# Restore PP # Restore PP
ret += 8 ret += 6
ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN) ret = ret * 3 / 2 if GameData::Item.get(item).is_berry? && has_active_ability?(:RIPEN)
end end
ret = 0 if ret < 0 && !try_preserving_item
return ret return ret
end end

View File

@@ -117,11 +117,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfUserDamagedThisTu
end end
end end
next Battle::AI::MOVE_USELESS_SCORE if user_faster_count == 0 next Battle::AI::MOVE_USELESS_SCORE if user_faster_count == 0
score += 10 if foe_faster_count == 0 score += 15 if foe_faster_count == 0
# Effects that make the target unlikely to act before the user # Effects that make the target unlikely to act before the user
if ai.trainer.high_skill? if ai.trainer.high_skill?
if !target.can_attack? if !target.can_attack?
score += 20 score += 15
elsif target.effects[PBEffects::Confusion] > 1 || elsif target.effects[PBEffects::Confusion] > 1 ||
target.effects[PBEffects::Attract] == user.index target.effects[PBEffects::Attract] == user.index
score += 10 score += 10
@@ -130,8 +130,10 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfUserDamagedThisTu
end end
end end
# Don't risk using this move if target is weak # Don't risk using this move if target is weak
score -= 10 if target.hp <= target.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if target.hp <= target.totalhp / 4 score -= 10 if target.hp <= target.totalhp / 2
score -= 10 if target.hp <= target.totalhp / 4
end
next score next score
} }
) )
@@ -143,12 +145,13 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfTargetActed",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Check whether user is faster than its foe(s) and could use this move # Check whether user is faster than its foe(s) and could use this move
next Battle::AI::MOVE_USELESS_SCORE if target.faster_than?(user) next Battle::AI::MOVE_USELESS_SCORE if target.faster_than?(user)
score += 10
# TODO: Predict the target switching/using an item. # TODO: Predict the target switching/using an item.
# TODO: Predict the target using a damaging move or Me First. # TODO: Predict the target using a damaging move or Me First.
# Don't risk using this move if target is weak # Don't risk using this move if target is weak
score -= 10 if target.hp <= target.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if target.hp <= target.totalhp / 4 score -= 10 if target.hp <= target.totalhp / 2
score -= 10 if target.hp <= target.totalhp / 4
end
next score next score
} }
) )
@@ -158,7 +161,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FailsIfTargetActed",
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CrashDamageIfFailsUnusableInGravity", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CrashDamageIfFailsUnusableInGravity",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score -= (100 - move.rough_accuracy) if user.battler.takesIndirectDamage? if user.battler.takesIndirectDamage?
score -= (0.4 * (100 - move.rough_accuracy)).to_i # -0 (100%) to -40 (1%)
end
next score next score
} }
) )
@@ -175,7 +180,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSunWeather",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE) battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP # Not worth it at lower HP
if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp < user.totalhp / 2
end
if ai.trainer.high_skill? && battle.field.weather != :None if ai.trainer.high_skill? && battle.field.weather != :None
score -= ai.get_score_for_weather(battle.field.weather, user) score -= ai.get_score_for_weather(battle.field.weather, user)
end end
@@ -193,7 +201,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRainWeather",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE) battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP # Not worth it at lower HP
if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp < user.totalhp / 2
end
if ai.trainer.high_skill? && battle.field.weather != :None if ai.trainer.high_skill? && battle.field.weather != :None
score -= ai.get_score_for_weather(battle.field.weather, user) score -= ai.get_score_for_weather(battle.field.weather, user)
end end
@@ -211,7 +222,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartSandstormWeather",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE) battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP # Not worth it at lower HP
if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp < user.totalhp / 2
end
if ai.trainer.high_skill? && battle.field.weather != :None if ai.trainer.high_skill? && battle.field.weather != :None
score -= ai.get_score_for_weather(battle.field.weather, user) score -= ai.get_score_for_weather(battle.field.weather, user)
end end
@@ -229,7 +243,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartHailWeather",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE) battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP # Not worth it at lower HP
if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp < user.totalhp / 2
end
if ai.trainer.high_skill? && battle.field.weather != :None if ai.trainer.high_skill? && battle.field.weather != :None
score -= ai.get_score_for_weather(battle.field.weather, user) score -= ai.get_score_for_weather(battle.field.weather, user)
end end
@@ -248,7 +265,10 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartElectricTerrain",
) )
Battle::AI::Handlers::MoveEffectScore.add("StartElectricTerrain", Battle::AI::Handlers::MoveEffectScore.add("StartElectricTerrain",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP # Not worth it at lower HP
if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp < user.totalhp / 2
end
if ai.trainer.high_skill? && battle.field.terrain != :None if ai.trainer.high_skill? && battle.field.terrain != :None
score -= ai.get_score_for_terrain(battle.field.terrain, user) score -= ai.get_score_for_terrain(battle.field.terrain, user)
end end
@@ -267,7 +287,10 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartGrassyTerrain",
) )
Battle::AI::Handlers::MoveEffectScore.add("StartGrassyTerrain", Battle::AI::Handlers::MoveEffectScore.add("StartGrassyTerrain",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP # Not worth it at lower HP
if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp < user.totalhp / 2
end
if ai.trainer.high_skill? && battle.field.terrain != :None if ai.trainer.high_skill? && battle.field.terrain != :None
score -= ai.get_score_for_terrain(battle.field.terrain, user) score -= ai.get_score_for_terrain(battle.field.terrain, user)
end end
@@ -286,7 +309,10 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartMistyTerrain",
) )
Battle::AI::Handlers::MoveEffectScore.add("StartMistyTerrain", Battle::AI::Handlers::MoveEffectScore.add("StartMistyTerrain",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP # Not worth it at lower HP
if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp < user.totalhp / 2
end
if ai.trainer.high_skill? && battle.field.terrain != :None if ai.trainer.high_skill? && battle.field.terrain != :None
score -= ai.get_score_for_terrain(battle.field.terrain, user) score -= ai.get_score_for_terrain(battle.field.terrain, user)
end end
@@ -305,7 +331,10 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartPsychicTerrain",
) )
Battle::AI::Handlers::MoveEffectScore.add("StartPsychicTerrain", Battle::AI::Handlers::MoveEffectScore.add("StartPsychicTerrain",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP # Not worth it at lower HP
if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp < user.totalhp / 2
end
if ai.trainer.high_skill? && battle.field.terrain != :None if ai.trainer.high_skill? && battle.field.terrain != :None
score -= ai.get_score_for_terrain(battle.field.terrain, user) score -= ai.get_score_for_terrain(battle.field.terrain, user)
end end
@@ -358,8 +387,8 @@ Battle::AI::Handlers::MoveEffectScore.add("AddSpikesToFoeSide",
foe_reserves.push(pkmn) # pkmn will be affected by Spikes foe_reserves.push(pkmn) # pkmn will be affected by Spikes
end end
next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty? next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty?
multiplier = [8, 5, 3][user.pbOpposingSide.effects[PBEffects::Spikes]] multiplier = [10, 7, 5][user.pbOpposingSide.effects[PBEffects::Spikes]]
score += multiplier * foe_reserves.length score += [multiplier * foe_reserves.length, 30].min
next score next score
} }
) )
@@ -402,8 +431,8 @@ Battle::AI::Handlers::MoveEffectScore.add("AddToxicSpikesToFoeSide",
foe_reserves.push(pkmn) # pkmn will be affected by Toxic Spikes foe_reserves.push(pkmn) # pkmn will be affected by Toxic Spikes
end end
next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty? next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty?
multiplier = [6, 4][user.pbOpposingSide.effects[PBEffects::ToxicSpikes]] multiplier = [8, 5][user.pbOpposingSide.effects[PBEffects::ToxicSpikes]]
score += multiplier * foe_reserves.length score += [multiplier * foe_reserves.length, 30].min
next score next score
} }
) )
@@ -431,7 +460,8 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStealthRocksToFoeSide",
foe_reserves.push(pkmn) # pkmn will be affected by Stealth Rock foe_reserves.push(pkmn) # pkmn will be affected by Stealth Rock
end end
next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty? next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty?
next score + 8 * foe_reserves.length score += [10 * foe_reserves.length, 30].min
next score
} }
) )
@@ -463,7 +493,8 @@ Battle::AI::Handlers::MoveEffectScore.add("AddStickyWebToFoeSide",
foe_reserves.push(pkmn) # pkmn will be affected by Sticky Web foe_reserves.push(pkmn) # pkmn will be affected by Sticky Web
end end
next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty? next Battle::AI::MOVE_USELESS_SCORE if foe_reserves.empty?
next score + 7 * foe_reserves.length score += [8 * foe_reserves.length, 30].min
next score
} }
) )
@@ -524,10 +555,12 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserMakeSubstitute",
Battle::AI::Handlers::MoveEffectScore.add("UserMakeSubstitute", Battle::AI::Handlers::MoveEffectScore.add("UserMakeSubstitute",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Prefer more the higher the user's HP # Prefer more the higher the user's HP
score += (8 * user.hp.to_f / user.totalhp).round if ai.trainer.has_skill_flag?("HPAware")
score += (10 * user.hp.to_f / user.totalhp).round
end
# Prefer if foes don't know any moves that can bypass a substitute # Prefer if foes don't know any moves that can bypass a substitute
ai.each_battler do |b, i| ai.each_foe_battler(user.side) do |b, i|
score += 4 if !b.check_for_move { |m| m.ignoresSubstitute?(b.battler) } score += 5 if !b.check_for_move { |m| m.ignoresSubstitute?(b.battler) }
end end
# TODO: Predict incoming damage, and prefer if it's greater than # TODO: Predict incoming damage, and prefer if it's greater than
# user.totalhp / 4? # user.totalhp / 4?
@@ -625,8 +658,8 @@ Battle::AI::Handlers::MoveEffectScore.add("AllBattlersLoseHalfHPUserSkipsNextTur
ally_hp_lost += b.hp / 2 ally_hp_lost += b.hp / 2
end end
end end
score += 15 * foe_hp_lost / ally_hp_lost score += 20 * foe_hp_lost / ally_hp_lost
score -= 15 * ally_hp_lost / foe_hp_lost score -= 20 * ally_hp_lost / foe_hp_lost
# Recharging # Recharging
score = Battle::AI::Handlers.apply_move_effect_score("AttackAndSkipNextTurn", score = Battle::AI::Handlers.apply_move_effect_score("AttackAndSkipNextTurn",
score, move, user, ai, battle) score, move, user, ai, battle)
@@ -654,7 +687,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartShadowSkyWeather",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) || next Battle::AI::MOVE_USELESS_SCORE if battle.pbCheckGlobalAbility(:AIRLOCK) ||
battle.pbCheckGlobalAbility(:CLOUDNINE) battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 10 if user.hp < user.totalhp / 2 # Not worth it at lower HP # Not worth it at lower HP
if ai.trainer.has_skill_flag?("HPAware")
score -= 15 if user.hp < user.totalhp / 2
end
if ai.trainer.high_skill? && battle.field.weather != :None if ai.trainer.high_skill? && battle.field.weather != :None
score -= ai.get_score_for_weather(battle.field.weather, user) score -= ai.get_score_for_weather(battle.field.weather, user)
end end

View File

@@ -60,7 +60,9 @@ Battle::AI::Handlers::MoveEffectScore.add("MaxUserAttackLoseHalfOfTotalHP",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
score = ai.get_score_for_target_stat_raise(score, user, move.move.statUp) score = ai.get_score_for_target_stat_raise(score, user, move.move.statUp)
# Don't prefer the lower the user's HP is # Don't prefer the lower the user's HP is
score -= 80 * (1 - (user.hp.to_f / user.totalhp)) # 0 to -40 if ai.trainer.has_skill_flag?("HPAware")
score -= 60 * (1 - (user.hp.to_f / user.totalhp)) # -0 to -30
end
next score next score
} }
) )
@@ -202,7 +204,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed2LowerUserWeight",
# User will become susceptible to Sky Drop # User will become susceptible to Sky Drop
if b.has_move_with_function?("TwoTurnAttackInvulnerableInSkyTargetCannotAct") && if b.has_move_with_function?("TwoTurnAttackInvulnerableInSkyTargetCannotAct") &&
Settings::MECHANICS_GENERATION >= 6 Settings::MECHANICS_GENERATION >= 6
score -= 7 if current_weight >= 2000 && current_weight < 3000 score -= 10 if current_weight >= 2000 && current_weight < 3000
end end
end end
end end
@@ -464,8 +466,8 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1LoseThirdOfTotalHP
score = ai.get_score_for_target_stat_raise(score, user, move.move.statUp) score = ai.get_score_for_target_stat_raise(score, user, move.move.statUp)
next score if score == Battle::AI::MOVE_USELESS_SCORE next score if score == Battle::AI::MOVE_USELESS_SCORE
# Score for losing HP # Score for losing HP
if user.hp <= user.totalhp * 0.75 if ai.trainer.has_skill_flag?("HPAware") && user.hp <= user.totalhp * 0.75
score -= 30 * (user.totalhp - user.hp) / user.totalhp score -= 45 * (user.totalhp - user.hp) / user.totalhp # -0 to -30
end end
next score next score
} }
@@ -499,7 +501,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseUserMainStats1TrapUserInBattle",
if user.effects[PBEffects::PerishSong] > 0 || if user.effects[PBEffects::PerishSong] > 0 ||
user.effects[PBEffects::Attract] >= 0 || user.effects[PBEffects::Attract] >= 0 ||
eor_damage > 0 eor_damage > 0
score -= 12 score -= 15
end end
end end
next score next score
@@ -513,12 +515,14 @@ Battle::AI::Handlers::MoveEffectScore.add("StartRaiseUserAtk1WhenDamaged",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Ignore the stat-raising effect if user is at a low HP and likely won't # Ignore the stat-raising effect if user is at a low HP and likely won't
# benefit from it # benefit from it
next score if user.hp < user.totalhp / 3 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 # TODO: Check whether any foe has damaging moves that will trigger the stat
# raise? # raise?
# Prefer if user benefits from a raised Attack stat # Prefer if user benefits from a raised Attack stat
score += 8 if ai.stat_raise_worthwhile?(user, :ATTACK) score += 10 if ai.stat_raise_worthwhile?(user, :ATTACK)
score += 4 if user.has_move_with_function?("PowerHigherWithUserPositiveStatStages") score += 7 if user.has_move_with_function?("PowerHigherWithUserPositiveStatStages")
next score next score
} }
) )
@@ -694,22 +698,24 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RaiseTargetRandomStat2",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if !battle.moldBreaker && target.has_active_ability?(:CONTRARY) next Battle::AI::MOVE_USELESS_SCORE if !battle.moldBreaker && target.has_active_ability?(:CONTRARY)
next Battle::AI::MOVE_USELESS_SCORE if target.rough_end_of_round_damage >= target.hp next Battle::AI::MOVE_USELESS_SCORE if target.rough_end_of_round_damage >= target.hp
score -= 5 if target.index != user.index # Less likely to use on ally score -= 7 if target.index != user.index # Less likely to use on ally
score += 5 if target.has_active_ability?(:SIMPLE) score += 10 if target.has_active_ability?(:SIMPLE)
# Prefer if target is at high HP, don't prefer if target is at low HP # Prefer if target is at high HP, don't prefer if target is at low HP
if target.hp >= target.totalhp * 0.7 if ai.trainer.has_skill_flag?("HPAware")
score += 8 if target.hp >= target.totalhp * 0.7
else score += 10
score += ((100 * target.hp / target.totalhp) - 50) / 4 # +5 to -12 else
score += (50 * ((target.hp.to_f / target.totalhp) - 0.6)).to_i # +5 to -30
end
end end
# Prefer if target has Stored Power # Prefer if target has Stored Power
if target.has_move_with_function?("PowerHigherWithUserPositiveStatStages") if target.has_move_with_function?("PowerHigherWithUserPositiveStatStages")
score += 8 score += 10
end end
# Don't prefer if any foe has Punishment # Don't prefer if any foe has Punishment
ai.each_foe_battler(target.side) do |b, i| ai.each_foe_battler(target.side) do |b, i|
next if !b.has_move_with_function?("PowerHigherWithTargetPositiveStatStages") next if !b.has_move_with_function?("PowerHigherWithTargetPositiveStatStages")
score -= 5 score -= 8
end end
next score next score
} }
@@ -909,7 +915,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetSpeed1MakeTar
if !target.effects[PBEffects::TarShot] if !target.effects[PBEffects::TarShot]
eff = target.effectiveness_of_type_against_battler(:FIRE) eff = target.effectiveness_of_type_against_battler(:FIRE)
if !Effectiveness.ineffective?(eff) if !Effectiveness.ineffective?(eff)
score += 8 * eff if user.has_damaging_move_of_type?(:FIRE) score += 10 * eff if user.has_damaging_move_of_type?(:FIRE)
end end
end end
next score next score
@@ -992,22 +998,23 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("LowerTargetEvasion1Remo
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetEvasion1RemoveSideEffects", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("LowerTargetEvasion1RemoveSideEffects",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if !target.opposes?(user)
# Score for stat drop # Score for stat drop
score = ai.get_score_for_target_stat_drop(score, target, move.move.statDown) score = ai.get_score_for_target_stat_drop(score, target, move.move.statDown)
# Score for removing side effects/terrain # Score for removing side effects/terrain
score += 8 if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 1 || score += 10 if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 1 ||
target.pbOwnSide.effects[PBEffects::Reflect] > 1 || target.pbOwnSide.effects[PBEffects::Reflect] > 1 ||
target.pbOwnSide.effects[PBEffects::LightScreen] > 1 || target.pbOwnSide.effects[PBEffects::LightScreen] > 1 ||
target.pbOwnSide.effects[PBEffects::Mist] > 1 || target.pbOwnSide.effects[PBEffects::Mist] > 1 ||
target.pbOwnSide.effects[PBEffects::Safeguard] > 1 target.pbOwnSide.effects[PBEffects::Safeguard] > 1
if target.can_switch_lax? if target.can_switch_lax?
score -= 10 if target.pbOwnSide.effects[PBEffects::Spikes] > 0 || score -= 15 if target.pbOwnSide.effects[PBEffects::Spikes] > 0 ||
target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0 || target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0 ||
target.pbOwnSide.effects[PBEffects::StealthRock] || target.pbOwnSide.effects[PBEffects::StealthRock] ||
target.pbOwnSide.effects[PBEffects::StickyWeb] target.pbOwnSide.effects[PBEffects::StickyWeb]
end end
if user.opposes?(target) && user.can_switch_lax? && Settings::MECHANICS_GENERATION >= 6 if user.can_switch_lax? && Settings::MECHANICS_GENERATION >= 6
score += 10 if target.pbOpposingSide.effects[PBEffects::Spikes] > 0 || score += 15 if target.pbOpposingSide.effects[PBEffects::Spikes] > 0 ||
target.pbOpposingSide.effects[PBEffects::ToxicSpikes] > 0 || target.pbOpposingSide.effects[PBEffects::ToxicSpikes] > 0 ||
target.pbOpposingSide.effects[PBEffects::StealthRock] || target.pbOpposingSide.effects[PBEffects::StealthRock] ||
target.pbOpposingSide.effects[PBEffects::StickyWeb] target.pbOpposingSide.effects[PBEffects::StickyWeb]
@@ -1296,14 +1303,14 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserCopyTargetStatStages
score = ai.get_score_for_target_stat_drop(score, user, drops, false, true) if drops.length > 0 score = ai.get_score_for_target_stat_drop(score, user, drops, false, true) if drops.length > 0
if Settings::NEW_CRITICAL_HIT_RATE_MECHANICS if Settings::NEW_CRITICAL_HIT_RATE_MECHANICS
if user.effects[PBEffects::FocusEnergy] > 0 && target.effects[PBEffects::FocusEnergy] == 0 if user.effects[PBEffects::FocusEnergy] > 0 && target.effects[PBEffects::FocusEnergy] == 0
score -= 4 score -= 5
elsif user.effects[PBEffects::FocusEnergy] == 0 && target.effects[PBEffects::FocusEnergy] > 0 elsif user.effects[PBEffects::FocusEnergy] == 0 && target.effects[PBEffects::FocusEnergy] > 0
score += 4 score += 5
end end
if user.effects[PBEffects::LaserFocus] > 0 && target.effects[PBEffects::LaserFocus] == 0 if user.effects[PBEffects::LaserFocus] > 0 && target.effects[PBEffects::LaserFocus] == 0
score -= 3 score -= 5
elsif user.effects[PBEffects::LaserFocus] == 0 && target.effects[PBEffects::LaserFocus] > 0 elsif user.effects[PBEffects::LaserFocus] == 0 && target.effects[PBEffects::LaserFocus] > 0
score += 3 score += 5
end end
end end
next score next score
@@ -1428,7 +1435,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToStatStageLower
["LowerPoisonedTargetAtkSpAtkSpd1", ["LowerPoisonedTargetAtkSpAtkSpd1",
"PoisonTargetLowerTargetSpeed1", "PoisonTargetLowerTargetSpeed1",
"HealUserByTargetAttackLowerTargetAttack1"].include?(m.function) } "HealUserByTargetAttackLowerTargetAttack1"].include?(m.function) }
score += 10 score += 15
has_move = true has_move = true
end end
end end
@@ -1498,49 +1505,33 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseAtk
change_matters = false change_matters = false
# Score based on changes to Attack # Score based on changes to Attack
if target_atk > user_atk if target_atk > user_atk
# User's Attack will be raised # User's Attack will be raised, target's Attack will be lowered
if ai.stat_raise_worthwhile?(user, :ATTACK, true) if ai.stat_raise_worthwhile?(user, :ATTACK, true) ||
score += (20 * ((target_atk.to_f / user_atk) - 1)).to_i ai.stat_drop_worthwhile?(target, :ATTACK, true)
change_matters = true score += (40 * ((target_atk.to_f / user_atk) - 1)).to_i
end
# Target's Attack will be lowered
if ai.stat_drop_worthwhile?(target, :ATTACK, true)
score += (20 * ((target_atk.to_f / user_atk) - 1)).to_i
change_matters = true change_matters = true
end end
elsif target_atk < user_atk elsif target_atk < user_atk
# User's Attack will be lowered # User's Attack will be lowered, target's Attack will be raised
if ai.stat_drop_worthwhile?(user, :ATTACK, true) if ai.stat_drop_worthwhile?(user, :ATTACK, true) ||
score -= (20 * ((user_atk.to_f / target_atk) - 1)).to_i ai.stat_raise_worthwhile?(target, :ATTACK, true)
change_matters = true score -= (40 * ((user_atk.to_f / target_atk) - 1)).to_i
end
# Target's Attack will be raised
if ai.stat_raise_worthwhile?(target, :ATTACK, true)
score -= (20 * ((user_atk.to_f / target_atk) - 1)).to_i
change_matters = true change_matters = true
end end
end end
# Score based on changes to Special Attack # Score based on changes to Special Attack
if target_spatk > user_spatk if target_spatk > user_spatk
# User's Special Attack will be raised # User's Special Attack will be raised, target's Special Attack will be lowered
if ai.stat_raise_worthwhile?(user, :SPECIAL_ATTACK, true) if ai.stat_raise_worthwhile?(user, :SPECIAL_ATTACK, true) ||
score += (20 * ((target_spatk.to_f / user_spatk) - 1)).to_i ai.stat_drop_worthwhile?(target, :SPECIAL_ATTACK, true)
change_matters = true score += (40 * ((target_spatk.to_f / user_spatk) - 1)).to_i
end
# Target's Special Attack will be lowered
if ai.stat_drop_worthwhile?(target, :SPECIAL_ATTACK, true)
score += (20 * ((target_spatk.to_f / user_spatk) - 1)).to_i
change_matters = true change_matters = true
end end
elsif target_spatk < user_spatk elsif target_spatk < user_spatk
# User's Special Attack will be lowered # User's Special Attack will be lowered, target's Special Attack will be raised
if ai.stat_drop_worthwhile?(user, :SPECIAL_ATTACK, true) if ai.stat_drop_worthwhile?(user, :SPECIAL_ATTACK, true) ||
score -= (20 * ((user_spatk.to_f / target_spatk) - 1)).to_i ai.stat_raise_worthwhile?(target, :SPECIAL_ATTACK, true)
change_matters = true score -= (40 * ((user_spatk.to_f / target_spatk) - 1)).to_i
end
# Target's Special Attack will be raised
if ai.stat_raise_worthwhile?(target, :SPECIAL_ATTACK, true)
score -= (20 * ((user_spatk.to_f / target_spatk) - 1)).to_i
change_matters = true change_matters = true
end end
end end
@@ -1562,49 +1553,33 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseDef
change_matters = false change_matters = false
# Score based on changes to Defense # Score based on changes to Defense
if target_def > user_def if target_def > user_def
# User's Defense will be raised # User's Defense will be raised, target's Defense will be lowered
if ai.stat_raise_worthwhile?(user, :DEFENSE, true) if ai.stat_raise_worthwhile?(user, :DEFENSE, true) ||
score += (20 * ((target_def.to_f / user_def) - 1)).to_i ai.stat_drop_worthwhile?(target, :DEFENSE, true)
change_matters = true score += (40 * ((target_def.to_f / user_def) - 1)).to_i
end
# Target's Defense will be lowered
if ai.stat_drop_worthwhile?(target, :DEFENSE, true)
score += (20 * ((target_def.to_f / user_def) - 1)).to_i
change_matters = true change_matters = true
end end
elsif target_def < user_def elsif target_def < user_def
# User's Defense will be lowered # User's Defense will be lowered, target's Defense will be raised
if ai.stat_drop_worthwhile?(user, :DEFENSE, true) if ai.stat_drop_worthwhile?(user, :DEFENSE, true) ||
score -= (20 * ((user_def.to_f / target_def) - 1)).to_i ai.stat_raise_worthwhile?(target, :DEFENSE, true)
change_matters = true score -= (40 * ((user_def.to_f / target_def) - 1)).to_i
end
# Target's Defense will be raised
if ai.stat_raise_worthwhile?(target, :DEFENSE, true)
score -= (20 * ((user_def.to_f / target_def) - 1)).to_i
change_matters = true change_matters = true
end end
end end
# Score based on changes to Special Defense # Score based on changes to Special Defense
if target_spdef > user_spdef if target_spdef > user_spdef
# User's Special Defense will be raised # User's Special Defense will be raised, target's Special Defense will be lowered
if ai.stat_raise_worthwhile?(user, :SPECIAL_DEFENSE, true) if ai.stat_raise_worthwhile?(user, :SPECIAL_DEFENSE, true) ||
score += (20 * ((target_spdef.to_f / user_spdef) - 1)).to_i ai.stat_drop_worthwhile?(target, :SPECIAL_DEFENSE, true)
change_matters = true score += (40 * ((target_spdef.to_f / user_spdef) - 1)).to_i
end
# Target's Special Defense will be lowered
if ai.stat_drop_worthwhile?(target, :SPECIAL_DEFENSE, true)
score += (20 * ((target_spdef.to_f / user_spdef) - 1)).to_i
change_matters = true change_matters = true
end end
elsif target_spdef < user_spdef elsif target_spdef < user_spdef
# User's Special Defense will be lowered # User's Special Defense will be lowered, target's Special Defense will be raised
if ai.stat_drop_worthwhile?(user, :SPECIAL_DEFENSE, true) if ai.stat_drop_worthwhile?(user, :SPECIAL_DEFENSE, true) ||
score -= (20 * ((user_spdef.to_f / target_spdef) - 1)).to_i ai.stat_raise_worthwhile?(target, :SPECIAL_DEFENSE, true)
change_matters = true score -= (40 * ((user_spdef.to_f / target_spdef) - 1)).to_i
end
# Target's Special Defense will be raised
if ai.stat_raise_worthwhile?(target, :SPECIAL_DEFENSE, true)
score -= (20 * ((user_spdef.to_f / target_spdef) - 1)).to_i
change_matters = true change_matters = true
end end
end end
@@ -1636,7 +1611,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideDoubleSpeed",
Battle::AI::Handlers::MoveEffectScore.add("StartUserSideDoubleSpeed", Battle::AI::Handlers::MoveEffectScore.add("StartUserSideDoubleSpeed",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Don't want to make allies faster if Trick Room will make them act later # Don't want to make allies faster if Trick Room will make them act later
next Battle::AI::MOVE_USELESS_SCORE if battle.field.effects[PBEffects::TrickRoom] > 1 if ai.trainer.medium_skill?
next Battle::AI::MOVE_USELESS_SCORE if battle.field.effects[PBEffects::TrickRoom] > 1
end
# Get the speeds of all battlers # Get the speeds of all battlers
ally_speeds = [] ally_speeds = []
foe_speeds = [] foe_speeds = []
@@ -1654,7 +1631,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideDoubleSpeed",
end end
next Battle::AI::MOVE_USELESS_SCORE if outspeeds == 0 next Battle::AI::MOVE_USELESS_SCORE if outspeeds == 0
# This move will achieve something # This move will achieve something
next score + 10 * outspeeds + 5 next score + 8 + (10 * outspeeds)
} }
) )
@@ -1663,38 +1640,38 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideDoubleSpeed",
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("StartSwapAllBattlersBaseDefensiveStats", Battle::AI::Handlers::MoveEffectScore.add("StartSwapAllBattlersBaseDefensiveStats",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
any_change_matters = false change_matters = false
ai.each_battler do |b, i| ai.each_battler do |b, i|
b_def = b.base_stat(:DEFENSE) b_def = b.base_stat(:DEFENSE)
b_spdef = b.base_stat(:SPECIAL_DEFENSE) b_spdef = b.base_stat(:SPECIAL_DEFENSE)
next if b_def == b_spdef next if b_def == b_spdef
score_change = 0 score_change = 0
if b_def > b_spdef if b_def > b_spdef
# Battler's Defense will be lowered # Battler's Defense will be lowered, battler's Special Defense will be raised
if ai.stat_drop_worthwhile?(b, :DEFENSE, true) if ai.stat_drop_worthwhile?(b, :DEFENSE, true)
score_change -= (20 * ((b_def.to_f / b_spdef) - 1)).to_i score_change -= (20 * ((b_def.to_f / b_spdef) - 1)).to_i
any_change_matters = true change_matters = true
end end
# Battler's Special Defense will be raised # Battler's Special Defense will be raised
if ai.stat_raise_worthwhile?(b, :SPECIAL_DEFENSE, true) if ai.stat_raise_worthwhile?(b, :SPECIAL_DEFENSE, true)
score_change += (20 * ((b_def.to_f / b_spdef) - 1)).to_i score_change += (20 * ((b_def.to_f / b_spdef) - 1)).to_i
any_change_matters = true change_matters = true
end end
else else
# Battler's Special Defense will be lowered # Battler's Special Defense will be lowered
if ai.stat_drop_worthwhile?(b, :SPECIAL_DEFENSE, true) if ai.stat_drop_worthwhile?(b, :SPECIAL_DEFENSE, true)
score_change -= (20 * ((b_spdef.to_f / b_def) - 1)).to_i score_change -= (20 * ((b_spdef.to_f / b_def) - 1)).to_i
any_change_matters = true change_matters = true
end end
# Battler's Defense will be raised # Battler's Defense will be raised
if ai.stat_raise_worthwhile?(b, :DEFENSE, true) if ai.stat_raise_worthwhile?(b, :DEFENSE, true)
score_change += (20 * ((b_spdef.to_f / b_def) - 1)).to_i score_change += (20 * ((b_spdef.to_f / b_def) - 1)).to_i
any_change_matters = true change_matters = true
end end
end end
score += (b.opposes?(user)) ? -score_change : score_change score += (b.opposes?(user)) ? -score_change : score_change
end end
next Battle::AI::MOVE_USELESS_SCORE if !any_change_matters next Battle::AI::MOVE_USELESS_SCORE if !change_matters
next Battle::AI::MOVE_USELESS_SCORE if score <= Battle::AI::MOVE_BASE_SCORE next Battle::AI::MOVE_USELESS_SCORE if score <= Battle::AI::MOVE_BASE_SCORE
next score next score
} }

View File

@@ -1,5 +1,6 @@
#=============================================================================== #===============================================================================
# # 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", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SleepTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
@@ -33,18 +34,18 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SleepTarget",
# asleep, but the target won't (usually) be able to make use of # asleep, but the target won't (usually) be able to make use of
# them, so they're not worth considering. # them, so they're not worth considering.
score -= 10 if target.has_active_ability?(:EARLYBIRD) score -= 10 if target.has_active_ability?(:EARLYBIRD)
score -= 5 if target.has_active_ability?(:MARVELSCALE) score -= 8 if target.has_active_ability?(:MARVELSCALE)
# Don't prefer if target has a move it can use while asleep # Don't prefer if target has a move it can use while asleep
score -= 8 if target.check_for_move { |m| m.usableWhenAsleep? } score -= 8 if target.check_for_move { |m| m.usableWhenAsleep? }
# Don't prefer if the target can heal itself (or be healed by an ally) # Don't prefer if the target can heal itself (or be healed by an ally)
if target.has_active_ability?(:SHEDSKIN) if target.has_active_ability?(:SHEDSKIN)
score -= 5 score -= 8
elsif target.has_active_ability?(:HYDRATION) && elsif target.has_active_ability?(:HYDRATION) &&
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather) [:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
score -= 10 score -= 15
end end
ai.each_same_side_battler(target.side) do |b, i| ai.each_same_side_battler(target.side) do |b, i|
score -= 5 if i != target.index && b.has_active_ability?(:HEALER) score -= 8 if i != target.index && b.has_active_ability?(:HEALER)
end end
end end
next score next score
@@ -87,7 +88,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("SleepTarget",
"SleepTargetNextTurn") "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", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PoisonTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
@@ -108,9 +110,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTarget",
next score if add_effect == -999 # Additional effect will be negated next score if add_effect == -999 # Additional effect will be negated
score += add_effect score += add_effect
# Inherent preference # Inherent preference
score += 10 score += 15
# Prefer if the target is at high HP # Prefer if the target is at high HP
score += 10 * target.hp / target.totalhp if ai.trainer.has_skill_flag?("HPAware")
score += 15 * target.hp / target.totalhp
end
# Prefer if the user or an ally has a move/ability that is better if the target is poisoned # Prefer if the user or an ally has a move/ability that is better if the target is poisoned
ai.each_same_side_battler(user.side) do |b, i| ai.each_same_side_battler(user.side) do |b, i|
score += 5 if b.has_move_with_function?("DoublePowerIfTargetPoisoned", score += 5 if b.has_move_with_function?("DoublePowerIfTargetPoisoned",
@@ -120,24 +124,24 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PoisonTarget",
# Don't prefer if target benefits from having the poison status problem # Don't prefer if target benefits from having the poison status problem
score -= 8 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET, :TOXICBOOST]) score -= 8 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET, :TOXICBOOST])
score -= 25 if target.has_active_ability?(:POISONHEAL) score -= 25 if target.has_active_ability?(:POISONHEAL)
score -= 15 if target.has_active_ability?(:SYNCHRONIZE) && score -= 20 if target.has_active_ability?(:SYNCHRONIZE) &&
user.battler.pbCanPoisonSynchronize?(target.battler) user.battler.pbCanPoisonSynchronize?(target.battler)
score -= 5 if target.has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed", score -= 5 if target.has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed",
"CureUserBurnPoisonParalysis") "CureUserBurnPoisonParalysis")
score -= 10 if target.check_for_move { |m| score -= 15 if target.check_for_move { |m|
m.function == "GiveUserStatusToTarget" && user.battler.pbCanPoison?(target.battler, false, m) m.function == "GiveUserStatusToTarget" && user.battler.pbCanPoison?(target.battler, false, m)
} }
# Don't prefer if the target won't take damage from the poison # Don't prefer if the target won't take damage from the poison
score -= 15 if !target.battler.takesIndirectDamage? score -= 20 if !target.battler.takesIndirectDamage?
# Don't prefer if the target can heal itself (or be healed by an ally) # Don't prefer if the target can heal itself (or be healed by an ally)
if target.has_active_ability?(:SHEDSKIN) if target.has_active_ability?(:SHEDSKIN)
score -= 5 score -= 8
elsif target.has_active_ability?(:HYDRATION) && elsif target.has_active_ability?(:HYDRATION) &&
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather) [:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
score -= 10 score -= 15
end end
ai.each_same_side_battler(target.side) do |b, i| ai.each_same_side_battler(target.side) do |b, i|
score -= 5 if i != target.index && b.has_active_ability?(:HEALER) score -= 8 if i != target.index && b.has_active_ability?(:HEALER)
end end
end end
next score next score
@@ -172,7 +176,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("PoisonTarget",
"BadPoisonTarget") "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", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("ParalyzeTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
@@ -198,11 +203,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeTarget",
if target.faster_than?(user) if target.faster_than?(user)
user_speed = user.rough_stat(:SPEED) user_speed = user.rough_stat(:SPEED)
target_speed = target.rough_stat(:SPEED) target_speed = target.rough_stat(:SPEED)
score += 10 if target_speed < user_speed * ((Settings::MECHANICS_GENERATION >= 7) ? 2 : 4) score += 15 if target_speed < user_speed * ((Settings::MECHANICS_GENERATION >= 7) ? 2 : 4)
end end
# Prefer if the target is confused or infatuated, to compound the turn skipping # Prefer if the target is confused or infatuated, to compound the turn skipping
score += 5 if target.effects[PBEffects::Confusion] > 1 score += 7 if target.effects[PBEffects::Confusion] > 1
score += 5 if target.effects[PBEffects::Attract] >= 0 score += 7 if target.effects[PBEffects::Attract] >= 0
# Prefer if the user or an ally has a move/ability that is better if the target is paralysed # Prefer if the user or an ally has a move/ability that is better if the target is paralysed
ai.each_same_side_battler(user.side) do |b, i| ai.each_same_side_battler(user.side) do |b, i|
score += 5 if b.has_move_with_function?("DoublePowerIfTargetParalyzedCureTarget", score += 5 if b.has_move_with_function?("DoublePowerIfTargetParalyzedCureTarget",
@@ -210,22 +215,22 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeTarget",
end end
# Don't prefer if target benefits from having the paralysis status problem # Don't prefer if target benefits from having the paralysis status problem
score -= 8 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET]) score -= 8 if target.has_active_ability?([:GUTS, :MARVELSCALE, :QUICKFEET])
score -= 15 if target.has_active_ability?(:SYNCHRONIZE) && score -= 20 if target.has_active_ability?(:SYNCHRONIZE) &&
user.battler.pbCanParalyzeSynchronize?(target.battler) user.battler.pbCanParalyzeSynchronize?(target.battler)
score -= 5 if target.has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed", score -= 5 if target.has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed",
"CureUserBurnPoisonParalysis") "CureUserBurnPoisonParalysis")
score -= 10 if target.check_for_move { |m| score -= 15 if target.check_for_move { |m|
m.function == "GiveUserStatusToTarget" && user.battler.pbCanParalyze?(target.battler, false, m) m.function == "GiveUserStatusToTarget" && user.battler.pbCanParalyze?(target.battler, false, m)
} }
# Don't prefer if the target can heal itself (or be healed by an ally) # Don't prefer if the target can heal itself (or be healed by an ally)
if target.has_active_ability?(:SHEDSKIN) if target.has_active_ability?(:SHEDSKIN)
score -= 5 score -= 8
elsif target.has_active_ability?(:HYDRATION) && elsif target.has_active_ability?(:HYDRATION) &&
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather) [:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
score -= 10 score -= 15
end end
ai.each_same_side_battler(target.side) do |b, i| ai.each_same_side_battler(target.side) do |b, i|
score -= 5 if i != target.index && b.has_active_ability?(:HEALER) score -= 8 if i != target.index && b.has_active_ability?(:HEALER)
end end
end end
next score next score
@@ -266,7 +271,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ParalyzeFlinchTarget",
) )
#=============================================================================== #===============================================================================
# # 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", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("BurnTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
@@ -286,10 +292,10 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnTarget",
next score if add_effect == -999 # Additional effect will be negated next score if add_effect == -999 # Additional effect will be negated
score += add_effect score += add_effect
# Inherent preference # Inherent preference
score += 10 score += 15
# Prefer if the target knows any physical moves that will be weaked by a burn # Prefer if the target knows any physical moves that will be weaked by a burn
if !target.has_active_ability?(:GUTS) && target.check_for_move { |m| m.physicalMove? } if !target.has_active_ability?(:GUTS) && target.check_for_move { |m| m.physicalMove? }
score += 5 score += 8
score += 8 if !target.check_for_move { |m| m.specialMove? } score += 8 if !target.check_for_move { |m| m.specialMove? }
end end
# Prefer if the user or an ally has a move/ability that is better if the target is burned # Prefer if the user or an ally has a move/ability that is better if the target is burned
@@ -299,24 +305,24 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnTarget",
# Don't prefer if target benefits from having the burn status problem # Don't prefer if target benefits from having the burn status problem
score -= 8 if target.has_active_ability?([:FLAREBOOST, :GUTS, :MARVELSCALE, :QUICKFEET]) score -= 8 if target.has_active_ability?([:FLAREBOOST, :GUTS, :MARVELSCALE, :QUICKFEET])
score -= 5 if target.has_active_ability?(:HEATPROOF) score -= 5 if target.has_active_ability?(:HEATPROOF)
score -= 15 if target.has_active_ability?(:SYNCHRONIZE) && score -= 20 if target.has_active_ability?(:SYNCHRONIZE) &&
user.battler.pbCanBurnSynchronize?(target.battler) user.battler.pbCanBurnSynchronize?(target.battler)
score -= 5 if target.has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed", score -= 5 if target.has_move_with_function?("DoublePowerIfUserPoisonedBurnedParalyzed",
"CureUserBurnPoisonParalysis") "CureUserBurnPoisonParalysis")
score -= 10 if target.check_for_move { |m| score -= 15 if target.check_for_move { |m|
m.function == "GiveUserStatusToTarget" && user.battler.pbCanBurn?(target.battler, false, m) m.function == "GiveUserStatusToTarget" && user.battler.pbCanBurn?(target.battler, false, m)
} }
# Don't prefer if the target won't take damage from the burn # Don't prefer if the target won't take damage from the burn
score -= 15 if !target.battler.takesIndirectDamage? score -= 20 if !target.battler.takesIndirectDamage?
# Don't prefer if the target can heal itself (or be healed by an ally) # Don't prefer if the target can heal itself (or be healed by an ally)
if target.has_active_ability?(:SHEDSKIN) if target.has_active_ability?(:SHEDSKIN)
score -= 5 score -= 8
elsif target.has_active_ability?(:HYDRATION) && elsif target.has_active_ability?(:HYDRATION) &&
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather) [:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
score -= 10 score -= 15
end end
ai.each_same_side_battler(target.side) do |b, i| ai.each_same_side_battler(target.side) do |b, i|
score -= 5 if i != target.index && b.has_active_ability?(:HEALER) score -= 8 if i != target.index && b.has_active_ability?(:HEALER)
end end
end end
next score next score
@@ -342,7 +348,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BurnFlinchTarget",
) )
#=============================================================================== #===============================================================================
# # 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", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("FreezeTarget",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
@@ -371,18 +378,18 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FreezeTarget",
# NOTE: The target's Guts/Quick Feet will benefit from the target being # NOTE: The target's Guts/Quick Feet will benefit from the target being
# frozen, but the target won't be able to make use of them, so # frozen, but the target won't be able to make use of them, so
# they're not worth considering. # they're not worth considering.
score -= 5 if target.has_active_ability?(:MARVELSCALE) score -= 8 if target.has_active_ability?(:MARVELSCALE)
# Don't prefer if the target knows a move that can thaw it # Don't prefer if the target knows a move that can thaw it
score -= 15 if target.check_for_move { |m| m.thawsUser? } score -= 15 if target.check_for_move { |m| m.thawsUser? }
# Don't prefer if the target can heal itself (or be healed by an ally) # Don't prefer if the target can heal itself (or be healed by an ally)
if target.has_active_ability?(:SHEDSKIN) if target.has_active_ability?(:SHEDSKIN)
score -= 5 score -= 8
elsif target.has_active_ability?(:HYDRATION) && elsif target.has_active_ability?(:HYDRATION) &&
[:Rain, :HeavyRain].include?(target.battler.effectiveWeather) [:Rain, :HeavyRain].include?(target.battler.effectiveWeather)
score -= 10 score -= 15
end end
ai.each_same_side_battler(target.side) do |b, i| ai.each_same_side_battler(target.side) do |b, i|
score -= 5 if i != target.index && b.has_active_ability?(:HEALER) score -= 8 if i != target.index && b.has_active_ability?(:HEALER)
end end
end end
next score next score
@@ -451,7 +458,9 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("GiveUserStatusToTarget"
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("GiveUserStatusToTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("GiveUserStatusToTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score += 10 # For getting rid of the user's status problem # Curing the user's status problem
score += 15 if !user.wants_status_problem?(user.status)
# Giving the target a status problem
case user.status case user.status
when :SLEEP when :SLEEP
next Battle::AI::Handlers.apply_move_effect_against_target_score("SleepTarget", next Battle::AI::Handlers.apply_move_effect_against_target_score("SleepTarget",
@@ -483,7 +492,8 @@ Battle::AI::Handlers::MoveFailureCheck.add("CureUserBurnPoisonParalysis",
) )
Battle::AI::Handlers::MoveEffectScore.add("CureUserBurnPoisonParalysis", Battle::AI::Handlers::MoveEffectScore.add("CureUserBurnPoisonParalysis",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
next score + 15 next Battle::AI::MOVE_USELESS_SCORE if user.wants_status_problem?(user.status)
next score + 20
} }
) )
@@ -499,7 +509,7 @@ Battle::AI::Handlers::MoveEffectScore.add("CureUserPartyStatus",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
score = Battle::AI::MOVE_BASE_SCORE # Ignore the scores for each targeted battler calculated earlier score = Battle::AI::MOVE_BASE_SCORE # Ignore the scores for each targeted battler calculated earlier
battle.pbParty(user.index).each do |pkmn| battle.pbParty(user.index).each do |pkmn|
score += 10 if pkmn && pkmn.status != :NONE score += 12 if pkmn && pkmn.status != :NONE
end end
next score next score
} }
@@ -514,8 +524,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CureTargetBurn",
next score if add_effect == -999 # Additional effect will be negated next score if add_effect == -999 # Additional effect will be negated
if target.status == :BURN if target.status == :BURN
score -= add_effect score -= add_effect
score -= 10 if target.wants_status_problem?(:BURN)
score += 15 if target.wants_status_problem?(:BURN) score += 15
else
score -= 10
end
end end
next score next score
} }
@@ -543,7 +556,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToInflictedStatu
# Tends to be wasteful if the foe just has one Pokémon left # Tends to be wasteful if the foe just has one Pokémon left
next score - 20 if battle.pbAbleNonActiveCount(user.idxOpposingSide) == 0 next score - 20 if battle.pbAbleNonActiveCount(user.idxOpposingSide) == 0
# Prefer for each user side battler # Prefer for each user side battler
ai.each_same_side_battler(user.side) { |b, i| score += 10 } ai.each_same_side_battler(user.side) { |b, i| score += 15 }
next score next score
} }
) )
@@ -559,10 +572,10 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("FlinchTarget",
next score if add_effect == -999 # Additional effect will be negated next score if add_effect == -999 # Additional effect will be negated
score += add_effect score += add_effect
# Inherent preference # Inherent preference
score += 10 score += 15
# Prefer if the target is paralysed, confused or infatuated, to compound the # Prefer if the target is paralysed, confused or infatuated, to compound the
# turn skipping # turn skipping
score += 5 if target.status == :PARALYSIS || score += 8 if target.status == :PARALYSIS ||
target.effects[PBEffects::Confusion] > 1 || target.effects[PBEffects::Confusion] > 1 ||
target.effects[PBEffects::Attract] >= 0 target.effects[PBEffects::Attract] >= 0
next score next score
@@ -614,14 +627,16 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ConfuseTarget",
next score if add_effect == -999 # Additional effect will be negated next score if add_effect == -999 # Additional effect will be negated
score += add_effect score += add_effect
# Inherent preference # Inherent preference
score += 5 score += 10
# Prefer if the target is at high HP # Prefer if the target is at high HP
score += 10 * target.hp / target.totalhp if ai.trainer.has_skill_flag?("HPAware")
score += 20 * target.hp / target.totalhp
end
# Prefer if the target is paralysed or infatuated, to compound the turn skipping # 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? # TODO: Also prefer if the target is trapped in battle or can't switch out?
score += 5 if target.status == :PARALYSIS || target.effects[PBEffects::Attract] >= 0 score += 8 if target.status == :PARALYSIS || target.effects[PBEffects::Attract] >= 0
# Don't prefer if target benefits from being confused # Don't prefer if target benefits from being confused
score -= 10 if target.has_active_ability?(:TANGLEDFEET) score -= 15 if target.has_active_ability?(:TANGLEDFEET)
end end
next score next score
} }
@@ -648,15 +663,15 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AttractTarget",
next score if add_effect == -999 # Additional effect will be negated next score if add_effect == -999 # Additional effect will be negated
score += add_effect score += add_effect
# Inherent preference # Inherent preference
score += 10 score += 15
# Prefer if the target is paralysed or confused, to compound the turn skipping # 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? # TODO: Also prefer if the target is trapped in battle or can't switch out?
score += 5 if target.status == :PARALYSIS || target.effects[PBEffects::Confusion] > 1 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 # Don't prefer if the target can infatuate the user because of this move
score -= 10 if target.has_active_item?(:DESTINYKNOT) && score -= 15 if target.has_active_item?(:DESTINYKNOT) &&
user.battler.pbCanAttract?(target.battler, false) user.battler.pbCanAttract?(target.battler, false)
# Don't prefer if the user has another way to infatuate the target # Don't prefer if the user has another way to infatuate the target
score -= 8 if move.statusMove? && user.has_active_ability?(:CUTECHARM) score -= 15 if move.statusMove? && user.has_active_ability?(:CUTECHARM)
end end
next score next score
} }
@@ -695,11 +710,11 @@ Battle::AI::Handlers::MoveEffectScore.add("SetUserTypesBasedOnEnvironment",
new_type = :NORMAL if !GameData::Type.exists?(new_type) new_type = :NORMAL if !GameData::Type.exists?(new_type)
end end
# Check if any user's moves will get STAB because of the type change # Check if any user's moves will get STAB because of the type change
score += 8 if user.has_damaging_move_of_type?(new_type) score += 14 if user.has_damaging_move_of_type?(new_type)
# Check if any user's moves will lose STAB because of the type change # Check if any user's moves will lose STAB because of the type change
user.pbTypes(true).each do |type| user.pbTypes(true).each do |type|
next if type == new_type next if type == new_type
score -= 8 if user.has_damaging_move_of_type?(type) score -= 14 if user.has_damaging_move_of_type?(type)
end end
# NOTE: Other things could be considered, like the foes' moves' # NOTE: Other things could be considered, like the foes' moves'
# effectivenesses against the current and new user's type(s), and # effectivenesses against the current and new user's type(s), and
@@ -734,11 +749,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserTypesToResistLast
if Effectiveness.ineffective?(effectiveness) if Effectiveness.ineffective?(effectiveness)
next Battle::AI::MOVE_USELESS_SCORE next Battle::AI::MOVE_USELESS_SCORE
elsif Effectiveness.super_effective?(effectiveness) elsif Effectiveness.super_effective?(effectiveness)
score += 12 score += 15
elsif Effectiveness.normal?(effectiveness) elsif Effectiveness.normal?(effectiveness)
score += 8 score += 10
else # Not very effective else # Not very effective
score += 4 score += 5
end end
next score next score
} }
@@ -786,7 +801,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserTypesToUserMoveTy
# Check if any user's moves will get STAB because of the type change # Check if any user's moves will get STAB because of the type change
possible_types.each do |type| possible_types.each do |type|
next if !user.has_damaging_move_of_type?(type) next if !user.has_damaging_move_of_type?(type)
score += 10 score += 14
break break
end end
# NOTE: Other things could be considered, like the foes' moves' # NOTE: Other things could be considered, like the foes' moves'
@@ -817,7 +832,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetTypesToPsychic"
next if !m.damagingMove? next if !m.damagingMove?
effectiveness = Effectiveness.calculate(m.pbCalcType(b.battler), :PSYCHIC) effectiveness = Effectiveness.calculate(m.pbCalcType(b.battler), :PSYCHIC)
if Effectiveness.super_effective?(effectiveness) if Effectiveness.super_effective?(effectiveness)
score += 8 score += 10
elsif Effectiveness.ineffective?(effectiveness) elsif Effectiveness.ineffective?(effectiveness)
score -= 10 score -= 10
end end
@@ -842,7 +857,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetTypesToWater",
next if !m.damagingMove? next if !m.damagingMove?
effectiveness = Effectiveness.calculate(m.pbCalcType(b.battler), :WATER) effectiveness = Effectiveness.calculate(m.pbCalcType(b.battler), :WATER)
if Effectiveness.super_effective?(effectiveness) if Effectiveness.super_effective?(effectiveness)
score += 8 score += 10
elsif Effectiveness.ineffective?(effectiveness) elsif Effectiveness.ineffective?(effectiveness)
score -= 10 score -= 10
end end
@@ -866,7 +881,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AddGhostTypeToTarget",
next if !m.damagingMove? next if !m.damagingMove?
effectiveness = Effectiveness.calculate(m.pbCalcType(b.battler), :GHOST) effectiveness = Effectiveness.calculate(m.pbCalcType(b.battler), :GHOST)
if Effectiveness.super_effective?(effectiveness) if Effectiveness.super_effective?(effectiveness)
score += 8 score += 10
elsif Effectiveness.not_very_effective?(effectiveness) elsif Effectiveness.not_very_effective?(effectiveness)
score -= 5 score -= 5
elsif Effectiveness.ineffective?(effectiveness) elsif Effectiveness.ineffective?(effectiveness)
@@ -892,7 +907,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AddGrassTypeToTarget",
next if !m.damagingMove? next if !m.damagingMove?
effectiveness = Effectiveness.calculate(m.pbCalcType(b.battler), :GRASS) effectiveness = Effectiveness.calculate(m.pbCalcType(b.battler), :GRASS)
if Effectiveness.super_effective?(effectiveness) if Effectiveness.super_effective?(effectiveness)
score += 8 score += 10
elsif Effectiveness.not_very_effective?(effectiveness) elsif Effectiveness.not_very_effective?(effectiveness)
score -= 5 score -= 5
elsif Effectiveness.ineffective?(effectiveness) elsif Effectiveness.ineffective?(effectiveness)
@@ -929,9 +944,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToSimple
new_ability_rating = target.wants_ability?(:SIMPLE) new_ability_rating = target.wants_ability?(:SIMPLE)
side_mult = (target.opposes?(user)) ? 1 : -1 side_mult = (target.opposes?(user)) ? 1 : -1
if old_ability_rating > new_ability_rating if old_ability_rating > new_ability_rating
score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max score += 5 * side_mult * [old_ability_rating - new_ability_rating, 3].max
elsif old_ability_rating < new_ability_rating elsif old_ability_rating < new_ability_rating
score -= 4 * side_mult * [new_ability_rating - old_ability_rating, 3].max score -= 5 * side_mult * [new_ability_rating - old_ability_rating, 3].max
end end
next score next score
} }
@@ -953,9 +968,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToInsomn
new_ability_rating = target.wants_ability?(:INSOMNIA) new_ability_rating = target.wants_ability?(:INSOMNIA)
side_mult = (target.opposes?(user)) ? 1 : -1 side_mult = (target.opposes?(user)) ? 1 : -1
if old_ability_rating > new_ability_rating if old_ability_rating > new_ability_rating
score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max score += 5 * side_mult * [old_ability_rating - new_ability_rating, 3].max
elsif old_ability_rating < new_ability_rating elsif old_ability_rating < new_ability_rating
score -= 4 * side_mult * [new_ability_rating - old_ability_rating, 3].max score -= 5 * side_mult * [new_ability_rating - old_ability_rating, 3].max
end end
next score next score
} }
@@ -976,9 +991,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetUserAbilityToTargetAb
old_ability_rating = user.wants_ability?(user.ability_id) old_ability_rating = user.wants_ability?(user.ability_id)
new_ability_rating = user.wants_ability?(target.ability_id) new_ability_rating = user.wants_ability?(target.ability_id)
if old_ability_rating > new_ability_rating if old_ability_rating > new_ability_rating
score += 4 * [old_ability_rating - new_ability_rating, 3].max score += 5 * [old_ability_rating - new_ability_rating, 3].max
elsif old_ability_rating < new_ability_rating elsif old_ability_rating < new_ability_rating
score -= 4 * [new_ability_rating - old_ability_rating, 3].max score -= 5 * [new_ability_rating - old_ability_rating, 3].max
end end
next score next score
} }
@@ -1002,9 +1017,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SetTargetAbilityToUserAb
new_ability_rating = target.wants_ability?(user.ability_id) new_ability_rating = target.wants_ability?(user.ability_id)
side_mult = (target.opposes?(user)) ? 1 : -1 side_mult = (target.opposes?(user)) ? 1 : -1
if old_ability_rating > new_ability_rating if old_ability_rating > new_ability_rating
score += 4 * side_mult * [old_ability_rating - new_ability_rating, 3].max score += 5 * side_mult * [old_ability_rating - new_ability_rating, 3].max
elsif old_ability_rating < new_ability_rating elsif old_ability_rating < new_ability_rating
score -= 4 * side_mult * [new_ability_rating - old_ability_rating, 3].max score -= 5 * side_mult * [new_ability_rating - old_ability_rating, 3].max
end end
next score next score
} }
@@ -1033,9 +1048,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapAbilities"
target_diff = 0 if !target.ability_active? target_diff = 0 if !target.ability_active?
side_mult = (target.opposes?(user)) ? 1 : -1 side_mult = (target.opposes?(user)) ? 1 : -1
if user_diff > target_diff if user_diff > target_diff
score += 4 * side_mult * [user_diff - target_diff, 3].max score += 5 * side_mult * [user_diff - target_diff, 3].max
elsif target_diff < user_diff elsif target_diff < user_diff
score -= 4 * side_mult * [target_diff - user_diff, 3].max score -= 5 * side_mult * [target_diff - user_diff, 3].max
end end
next score next score
} }
@@ -1054,9 +1069,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbility",
target_ability_rating = target.wants_ability?(target.ability_id) target_ability_rating = target.wants_ability?(target.ability_id)
side_mult = (target.opposes?(user)) ? 1 : -1 side_mult = (target.opposes?(user)) ? 1 : -1
if target_ability_rating > 0 if target_ability_rating > 0
score += 4 * side_mult * [target_ability_rating, 3].max score += 5 * side_mult * [target_ability_rating, 3].max
elsif target_ability_rating < 0 elsif target_ability_rating < 0
score -= 4 * side_mult * [target_ability_rating.abs, 3].max score -= 5 * side_mult * [target_ability_rating.abs, 3].max
end end
next score next score
} }
@@ -1073,9 +1088,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("NegateTargetAbilityIfTar
target_ability_rating = target.wants_ability?(target.ability_id) target_ability_rating = target.wants_ability?(target.ability_id)
side_mult = (target.opposes?(user)) ? 1 : -1 side_mult = (target.opposes?(user)) ? 1 : -1
if target_ability_rating > 0 if target_ability_rating > 0
score += 4 * side_mult * [target_ability_rating, 3].max score += 5 * side_mult * [target_ability_rating, 3].max
elsif target_ability_rating < 0 elsif target_ability_rating < 0
score -= 4 * side_mult * [target_ability_rating.abs, 3].max score -= 5 * side_mult * [target_ability_rating.abs, 3].max
end end
next score next score
} }
@@ -1112,7 +1127,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserAirborne",
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
next if !b.has_damaging_move_of_type?(:GROUND) next if !b.has_damaging_move_of_type?(:GROUND)
next if Effectiveness.resistant?(user.effectiveness_of_type_against_battler(:GROUND, b)) next if Effectiveness.resistant?(user.effectiveness_of_type_against_battler(:GROUND, b))
score += 5 score += 10
end end
# Don't prefer if terrain exists (which the user will no longer be affected by) # Don't prefer if terrain exists (which the user will no longer be affected by)
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
@@ -1131,7 +1146,7 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartTargetAirborneAndA
next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false) next move.move.pbFailsAgainstTarget?(user.battler, target.battler, false)
} }
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartUserAirborne", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartTargetAirborneAndAlwaysHitByMoves",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Move is useless if the target is already airborne # Move is useless if the target is already airborne
if target.has_type?(:FLYING) || if target.has_type?(:FLYING) ||
@@ -1146,12 +1161,12 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartUserAirborne",
b.battler.eachMove do |m| b.battler.eachMove do |m|
acc = m.accuracy acc = m.accuracy
acc = m.pbBaseAccuracy(b.battler, target.battler) if ai.trainer.medium_skill? acc = m.pbBaseAccuracy(b.battler, target.battler) if ai.trainer.medium_skill?
score += 4 if acc < 90 && acc != 0 score += 5 if acc < 90 && acc != 0
score += 4 if acc <= 50 && acc != 0 score += 5 if acc <= 50 && acc != 0
end end
next if !b.has_damaging_move_of_type?(:GROUND) next if !b.has_damaging_move_of_type?(:GROUND)
next if Effectiveness.resistant?(target.effectiveness_of_type_against_battler(:GROUND, b)) next if Effectiveness.resistant?(target.effectiveness_of_type_against_battler(:GROUND, b))
score -= 5 score -= 7
end end
# Prefer if terrain exists (which the target will no longer be affected by) # Prefer if terrain exists (which the target will no longer be affected by)
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
@@ -1181,7 +1196,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitsTargetInSkyGroundsTa
score += 10 score += 10
# Prefer if any allies have damaging Ground-type moves # Prefer if any allies have damaging Ground-type moves
ai.each_foe_battler(target.side) do |b, i| ai.each_foe_battler(target.side) do |b, i|
score += 5 if b.has_damaging_move_of_type?(:GROUND) score += 8 if b.has_damaging_move_of_type?(:GROUND)
end end
# Don't prefer if terrain exists (which the target will become affected by) # Don't prefer if terrain exists (which the target will become affected by)
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
@@ -1207,25 +1222,26 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
# affected by terrain # affected by terrain
if b.battler.airborne? if b.battler.airborne?
score_change = 10 score_change = 10
score_change -= 8 if battle.field.terrain != :None if ai.trainer.medium_skill?
score_change -= 8 if battle.field.terrain != :None
end
score += (user.opposes?(b)) ? score_change : -score_change score += (user.opposes?(b)) ? score_change : -score_change
# Prefer if allies have any damaging Ground moves they'll be able to use # Prefer if allies have any damaging Ground moves they'll be able to use
# on a grounded foe, and vice versa # on a grounded foe, and vice versa
ai.each_foe_battler(b.side) do |b2, j| ai.each_foe_battler(b.side) do |b2, j|
if b2.has_damaging_move_of_type?(:GROUND) next if !b2.has_damaging_move_of_type?(:GROUND)
score += (user.opposes?(b2)) ? -5 : 5 score += (user.opposes?(b2)) ? -8 : 8
end
end end
end end
# Prefer ending Sky Drop being used on allies, don't prefer ending Sky # Prefer ending Sky Drop being used on allies, don't prefer ending Sky
# Drop being used on foes # Drop being used on foes
if b.effects[PBEffects::SkyDrop] >= 0 if b.effects[PBEffects::SkyDrop] >= 0
score += (user.opposes?(b)) ? -5 : 5 score += (user.opposes?(b)) ? -8 : 8
end end
# Gravity raises accuracy of all moves; prefer if the user/ally has low # Gravity raises accuracy of all moves; prefer if the user/ally has low
# accuracy moves, don't prefer if foes have any # accuracy moves, don't prefer if foes have any
if b.check_for_move { |m| m.accuracy < 85 } if b.check_for_move { |m| m.accuracy < 85 }
score += (user.opposes?(b)) ? -5 : 5 score += (user.opposes?(b)) ? -8 : 8
end end
# Prefer stopping foes' sky-based attacks, don't prefer stopping allies' # Prefer stopping foes' sky-based attacks, don't prefer stopping allies'
# sky-based attacks # sky-based attacks
@@ -1233,7 +1249,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartGravity",
b.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky", b.battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSky",
"TwoTurnAttackInvulnerableInSkyParalyzeTarget", "TwoTurnAttackInvulnerableInSkyParalyzeTarget",
"TwoTurnAttackInvulnerableInSkyTargetCannotAct") "TwoTurnAttackInvulnerableInSkyTargetCannotAct")
score += (user.opposes?(b)) ? 8 : -8 score += (user.opposes?(b)) ? 10 : -10
end end
end end
next score next score

View File

@@ -75,9 +75,11 @@ Battle::AI::Handlers::MoveBasePower.add("OHKO",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("OHKO", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("OHKO",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Don't prefer if the target has less HP and user has a non-OHKO damaging move # 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? } if ai.trainer.has_skill_flag?("HPAware")
score -= 8 if target.hp <= target.totalhp / 2 if user.check_for_move { |m| m.damagingMove? && !m.is_a?(Battle::Move::OHKO) }
score -= 8 if target.hp <= target.totalhp / 4 score -= 12 if target.hp <= target.totalhp / 2
score -= 8 if target.hp <= target.totalhp / 4
end
end end
next score next score
} }
@@ -115,7 +117,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DamageTargetAlly",
target.battler.allAllies.each do |b| target.battler.allAllies.each do |b|
next if !b.near?(target.battler) || !b.battler.takesIndirectDamage? next if !b.near?(target.battler) || !b.battler.takesIndirectDamage?
score += 10 score += 10
score += 15 if b.hp <= b.totalhp / 16 if ai.trainer.has_skill_flag?("HPAware")
score += 10 if b.hp <= b.totalhp / 16
end
end end
next score next score
} }
@@ -218,7 +222,7 @@ Battle::AI::Handlers::MoveEffectScore.add("PowerHigherWithConsecutiveUse",
# Prefer continuing to use this move # Prefer continuing to use this move
score += 10 if user.effects[PBEffects::FuryCutter] > 0 score += 10 if user.effects[PBEffects::FuryCutter] > 0
# Prefer if holding the Metronome # Prefer if holding the Metronome
score += 5 if user.has_active_item?(:METRONOME) score += 7 if user.has_active_item?(:METRONOME)
next score next score
} }
) )
@@ -236,7 +240,7 @@ Battle::AI::Handlers::MoveEffectScore.add("PowerHigherWithConsecutiveUse",
# Prefer continuing to use this move # Prefer continuing to use this move
score += 10 if user.pbOwnSide.effects[PBEffects::EchoedVoiceCounter] > 0 score += 10 if user.pbOwnSide.effects[PBEffects::EchoedVoiceCounter] > 0
# Prefer if holding the Metronome # Prefer if holding the Metronome
score += 5 if user.has_active_item?(:METRONOME) score += 7 if user.has_active_item?(:METRONOME)
next score next score
} }
) )
@@ -274,8 +278,11 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetHPLessThanHalf",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetAsleepCureTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetAsleepCureTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if target.status == :SLEEP && target.statusCount > 1 # Will cure status if target.status == :SLEEP && target.statusCount > 1 # Will cure status
score -= 10 if target.wants_status_problem?(:SLEEP)
score += 15 if target.wants_status_problem?(:SLEEP) score += 15
else
score -= 10
end
end end
next score next score
} }
@@ -298,8 +305,11 @@ Battle::AI::Handlers::MoveBasePower.copy("DoublePowerIfTargetPoisoned",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetParalyzedCureTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetParalyzedCureTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if target.status == :PARALYSIS # Will cure status if target.status == :PARALYSIS # Will cure status
score -= 10 if target.wants_status_problem?(:PARALYSIS)
score += 15 if target.wants_status_problem?(:PARALYSIS) score += 15
else
score -= 10
end
end end
next score next score
} }
@@ -374,7 +384,7 @@ Battle::AI::Handlers::MoveEffectScore.add("DoublePowerIfUserLostHPThisTurn",
# Prefer if user is slower than its foe(s) and the foe(s) can attack # Prefer if user is slower than its foe(s) and the foe(s) can attack
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
next if user.faster_than?(b) || !b.can_attack? next if user.faster_than?(b) || !b.can_attack?
score += 4 score += 8
end end
next score next score
} }
@@ -389,7 +399,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetLostH
ai.each_foe_battler(target.side) do |b, i| ai.each_foe_battler(target.side) do |b, i|
next if i == user.index next if i == user.index
next if user.faster_than?(b) || !b.can_attack? next if user.faster_than?(b) || !b.can_attack?
score += 4 score += 8
end end
next score next score
} }
@@ -405,7 +415,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetLostH
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetActed", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetActed",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score += 15 if target.faster_than?(user) score += 10 if target.faster_than?(user)
next score next score
} }
) )
@@ -415,7 +425,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetActed
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetNotActed", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DoublePowerIfTargetNotActed",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score += 15 if user.faster_than?(target) score += 10 if user.faster_than?(target)
next score next score
} }
) )
@@ -457,7 +467,7 @@ Battle::AI::Handlers::MoveEffectScore.add("EnsureNextCriticalHit",
# TODO: Change the score depending on how much of an effect a critical hit # 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 # will have? Critical hits ignore the user's offensive stat drops
# and the target's defensive stat raises, and multiply the damage. # and the target's defensive stat raises, and multiply the damage.
score += 10 score += 15
end end
next score next score
} }
@@ -514,7 +524,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPreventCriticalHitsAgainstUserSi
# TODO: Change the score depending on how much of an effect a critical hit # 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 # will have? Critical hits ignore the user's offensive stat drops
# and the target's defensive stat raises, and multiply the damage. # and the target's defensive stat raises, and multiply the damage.
score += 5 * crit_stage if crit_stage > 0 score += 8 * crit_stage if crit_stage > 0
score += 10 if b.effects[PBEffects::LaserFocus] > 0 score += 10 if b.effects[PBEffects::LaserFocus] > 0
end end
next score next score
@@ -540,15 +550,17 @@ Battle::AI::Handlers::MoveEffectScore.add("UserEnduresFaintingThisTurn",
useless = true useless = true
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
next if !b.can_attack? next if !b.can_attack?
score += 5
useless = false useless = false
score += 4
end end
next Battle::AI::MOVE_USELESS_SCORE if useless next Battle::AI::MOVE_USELESS_SCORE if useless
# Don't prefer if user has high HP, prefer if user has lower HP # Don't prefer if user has high HP, prefer if user has lower HP
if user.hp >= user.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
score -= 8 if user.hp >= user.totalhp / 2
elsif user.hp >= user.totalhp / 8 score -= 15
score += 4 elsif user.hp <= user.totalhp / 4
score += 8
end
end end
# Don't prefer if the user used a protection move last turn, making this one # Don't prefer if the user used a protection move last turn, making this one
# less likely to work # less likely to work
@@ -570,20 +582,25 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenElectricMoves",
Battle::AI::Handlers::MoveEffectScore.add("StartWeakenElectricMoves", Battle::AI::Handlers::MoveEffectScore.add("StartWeakenElectricMoves",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Don't prefer the lower the user's HP is # Don't prefer the lower the user's HP is
if user.hp < user.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30 if user.hp <= user.totalhp / 2
score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15
end
end end
# Prefer if foes have Electric moves # Prefer if foes have Electric moves
any_foe_electric_moves = false
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
next if !b.has_damaging_move_of_type?(:ELECTRIC) next if !b.has_damaging_move_of_type?(:ELECTRIC)
score += 10 score += 15
score += 5 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :ELECTRIC } score += 7 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :ELECTRIC }
any_foe_electric_moves = true
end end
next Battle::AI::MOVE_USELESS_SCORE if !any_foe_electric_moves
# Don't prefer if any allies have Electric moves # Don't prefer if any allies have Electric moves
ai.each_same_side_battler(user.side) do |b, i| ai.each_same_side_battler(user.side) do |b, i|
next if !b.has_damaging_move_of_type?(:ELECTRIC) next if !b.has_damaging_move_of_type?(:ELECTRIC)
score -= 8 score -= 10
score -= 4 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :ELECTRIC } score -= 5 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :ELECTRIC }
end end
next score next score
} }
@@ -601,20 +618,25 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartWeakenFireMoves",
Battle::AI::Handlers::MoveEffectScore.add("StartWeakenFireMoves", Battle::AI::Handlers::MoveEffectScore.add("StartWeakenFireMoves",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Don't prefer the lower the user's HP is # Don't prefer the lower the user's HP is
if user.hp < user.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30 if user.hp <= user.totalhp / 2
score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15
end
end end
# Prefer if foes have Fire moves # Prefer if foes have Fire moves
any_foe_fire_moves = false
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
next if !b.has_damaging_move_of_type?(:FIRE) next if !b.has_damaging_move_of_type?(:FIRE)
score += 10 score += 15
score += 5 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :FIRE } score += 7 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :FIRE }
any_foe_fire_moves = true
end end
next Battle::AI::MOVE_USELESS_SCORE if !any_foe_fire_moves
# Don't prefer if any allies have Fire moves # Don't prefer if any allies have Fire moves
ai.each_same_side_battler(user.side) do |b, i| ai.each_same_side_battler(user.side) do |b, i|
next if !b.has_damaging_move_of_type?(:FIRE) next if !b.has_damaging_move_of_type?(:FIRE)
score -= 8 score -= 10
score -= 4 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :FIRE } score -= 5 if !b.check_for_move { |m| m.damagingMove? && m.pbCalcType(b.battler) != :FIRE }
end end
next score next score
} }
@@ -636,14 +658,16 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenPhysicalDamageAgainstUserS
# TODO: Should this HP check exist? The effect can still be set up for # 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 # allies. Maybe just don't prefer if there are no replacement mons
# left. # left.
if user.hp < user.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30 if user.hp <= user.totalhp / 2
score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15
end
end end
# Prefer if foes have physical moves (moreso if they don't have special moves) # Prefer if foes have physical moves (moreso if they don't have special moves)
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
next if !b.check_for_move { |m| m.physicalMove?(m.type) } next if !b.check_for_move { |m| m.physicalMove?(m.type) }
score += 8 score += 10
score += 5 if !b.check_for_move { |m| m.specialMove?(m.type) } score += 8 if !b.check_for_move { |m| m.specialMove?(m.type) }
end end
next score next score
} }
@@ -665,14 +689,16 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenSpecialDamageAgainstUserSi
# TODO: Should this HP check exist? The effect can still be set up for # 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 # allies. Maybe just don't prefer if there are no replacement mons
# left. # left.
if user.hp < user.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30 if user.hp <= user.totalhp / 2
score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15
end
end end
# Prefer if foes have special moves (moreso if they don't have physical moves) # Prefer if foes have special moves (moreso if they don't have physical moves)
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
next if !b.check_for_move { |m| m.specialMove?(m.type) } next if !b.check_for_move { |m| m.specialMove?(m.type) }
score += 8 score += 10
score += 5 if !b.check_for_move { |m| m.physicalMove?(m.type) } score += 8 if !b.check_for_move { |m| m.physicalMove?(m.type) }
end end
next score next score
} }
@@ -697,8 +723,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartWeakenDamageAgainstUserSideIfHai
# TODO: Should this HP check exist? The effect can still be set up for # 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 # allies. Maybe just don't prefer if there are no replacement mons
# left. # left.
if user.hp < user.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
score -= 40 * (0.75 - (user.hp.to_f / user.totalhp)) # -10 to -30 if user.hp <= user.totalhp / 2
score -= (20 * (0.75 - (user.hp.to_f / user.totalhp))).to_i # -5 to -15
end
end end
next score + 15 next score + 15
} }
@@ -743,16 +771,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUser",
# be using, so we don't know if Unseen Fist will apply. # be using, so we don't know if Unseen Fist will apply.
useless = false useless = false
# General preference # General preference
score += 4 score += 7
# Prefer if the foe is in the middle of using a two turn attack # Prefer if the foe is in the middle of using a two turn attack
score += 8 if b.effects[PBEffects::TwoTurnAttack] && score += 15 if b.effects[PBEffects::TwoTurnAttack] &&
GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] }
# Prefer if foe takes EOR damage, don't prefer if they have EOR healing # Prefer if foe takes EOR damage, don't prefer if they have EOR healing
b_eor_damage = b.rough_end_of_round_damage b_eor_damage = b.rough_end_of_round_damage
if b_eor_damage > 0 if b_eor_damage > 0
score += 5 score += 8
elsif b_eor_damage < 0 elsif b_eor_damage < 0
score -= 5 score -= 8
end end
end end
next Battle::AI::MOVE_USELESS_SCORE if useless next Battle::AI::MOVE_USELESS_SCORE if useless
@@ -761,13 +789,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUser",
if user_eor_damage >= user.hp if user_eor_damage >= user.hp
next Battle::AI::MOVE_USELESS_SCORE next Battle::AI::MOVE_USELESS_SCORE
elsif user_eor_damage > 0 elsif user_eor_damage > 0
score -= 5 score -= 8
elsif user_eor_damage < 0 elsif user_eor_damage < 0
score += 5 score += 8
end end
# Don't prefer if the user used a protection move last turn, making this one # Don't prefer if the user used a protection move last turn, making this one
# less likely to work # less likely to work
score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10)
next score next score
} }
) )
@@ -788,7 +816,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker",
# be using, so we don't know if Unseen Fist will apply. # be using, so we don't know if Unseen Fist will apply.
useless = false useless = false
# General preference # General preference
score += 4 score += 7
# Prefer if the foe is likely to be poisoned by this move # Prefer if the foe is likely to be poisoned by this move
if b.check_for_move { |m| m.contactMove? } if b.check_for_move { |m| m.contactMove? }
poison_score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget", poison_score = Battle::AI::Handlers.apply_move_effect_against_target_score("PoisonTarget",
@@ -796,14 +824,14 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker",
score += poison_score / 2 # Halved because we don't know what move b will use 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 # Prefer if the foe is in the middle of using a two turn attack
score += 8 if b.effects[PBEffects::TwoTurnAttack] && score += 15 if b.effects[PBEffects::TwoTurnAttack] &&
GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] }
# Prefer if foe takes EOR damage, don't prefer if they have EOR healing # Prefer if foe takes EOR damage, don't prefer if they have EOR healing
b_eor_damage = b.rough_end_of_round_damage b_eor_damage = b.rough_end_of_round_damage
if b_eor_damage > 0 if b_eor_damage > 0
score += 5 score += 8
elsif b_eor_damage < 0 elsif b_eor_damage < 0
score -= 5 score -= 8
end end
end end
next Battle::AI::MOVE_USELESS_SCORE if useless next Battle::AI::MOVE_USELESS_SCORE if useless
@@ -812,13 +840,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserBanefulBunker",
if user_eor_damage >= user.hp if user_eor_damage >= user.hp
next Battle::AI::MOVE_USELESS_SCORE next Battle::AI::MOVE_USELESS_SCORE
elsif user_eor_damage > 0 elsif user_eor_damage > 0
score -= 5 score -= 8
elsif user_eor_damage < 0 elsif user_eor_damage < 0
score += 5 score += 8
end end
# Don't prefer if the user used a protection move last turn, making this one # Don't prefer if the user used a protection move last turn, making this one
# less likely to work # less likely to work
score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10)
next score next score
} }
) )
@@ -839,7 +867,7 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShie
# be using, so we don't know if Unseen Fist will apply. # be using, so we don't know if Unseen Fist will apply.
useless = false useless = false
# General preference # General preference
score += 4 score += 7
# Prefer if the foe's Attack can be lowered by this move # Prefer if the foe's Attack can be lowered by this move
if b.battler.affectedByContactEffect? && b.check_for_move { |m| m.contactMove? } if b.battler.affectedByContactEffect? && b.check_for_move { |m| m.contactMove? }
drop_score = ai.get_score_for_target_stat_drop( drop_score = ai.get_score_for_target_stat_drop(
@@ -847,14 +875,14 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShie
score += drop_score / 2 # Halved because we don't know what move b will use score += drop_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 # Prefer if the foe is in the middle of using a two turn attack
score += 8 if b.effects[PBEffects::TwoTurnAttack] && score += 15 if b.effects[PBEffects::TwoTurnAttack] &&
GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] }
# Prefer if foe takes EOR damage, don't prefer if they have EOR healing # Prefer if foe takes EOR damage, don't prefer if they have EOR healing
b_eor_damage = b.rough_end_of_round_damage b_eor_damage = b.rough_end_of_round_damage
if b_eor_damage > 0 if b_eor_damage > 0
score += 5 score += 8
elsif b_eor_damage < 0 elsif b_eor_damage < 0
score -= 5 score -= 8
end end
end end
next Battle::AI::MOVE_USELESS_SCORE if useless next Battle::AI::MOVE_USELESS_SCORE if useless
@@ -863,13 +891,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesKingsShie
if user_eor_damage >= user.hp if user_eor_damage >= user.hp
next Battle::AI::MOVE_USELESS_SCORE next Battle::AI::MOVE_USELESS_SCORE
elsif user_eor_damage > 0 elsif user_eor_damage > 0
score -= 5 score -= 8
elsif user_eor_damage < 0 elsif user_eor_damage < 0
score += 5 score += 8
end end
# Don't prefer if the user used a protection move last turn, making this one # Don't prefer if the user used a protection move last turn, making this one
# less likely to work # less likely to work
score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10)
next score next score
} }
) )
@@ -890,21 +918,21 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct"
# be using, so we don't know if Unseen Fist will apply. # be using, so we don't know if Unseen Fist will apply.
useless = false useless = false
# General preference # General preference
score += 4 score += 7
# Prefer if the foe's Attack can be lowered by this move # Prefer if the foe's Attack can be lowered by this move
if b.battler.affectedByContactEffect? && b.check_for_move { |m| m.contactMove? } if b.battler.affectedByContactEffect? && b.check_for_move { |m| m.contactMove? }
drop_score = ai.get_score_for_target_stat_drop(0, b, [:DEFENSE, 2], false) drop_score = ai.get_score_for_target_stat_drop(0, b, [:DEFENSE, 2], false)
score += drop_score / 2 # Halved because we don't know what move b will use score += drop_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 # Prefer if the foe is in the middle of using a two turn attack
score += 8 if b.effects[PBEffects::TwoTurnAttack] && score += 15 if b.effects[PBEffects::TwoTurnAttack] &&
GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] }
# Prefer if foe takes EOR damage, don't prefer if they have EOR healing # Prefer if foe takes EOR damage, don't prefer if they have EOR healing
b_eor_damage = b.rough_end_of_round_damage b_eor_damage = b.rough_end_of_round_damage
if b_eor_damage > 0 if b_eor_damage > 0
score += 5 score += 8
elsif b_eor_damage < 0 elsif b_eor_damage < 0
score -= 5 score -= 8
end end
end end
next Battle::AI::MOVE_USELESS_SCORE if useless next Battle::AI::MOVE_USELESS_SCORE if useless
@@ -913,13 +941,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromDamagingMovesObstruct"
if user_eor_damage >= user.hp if user_eor_damage >= user.hp
next Battle::AI::MOVE_USELESS_SCORE next Battle::AI::MOVE_USELESS_SCORE
elsif user_eor_damage > 0 elsif user_eor_damage > 0
score -= 5 score -= 8
elsif user_eor_damage < 0 elsif user_eor_damage < 0
score += 5 score += 8
end end
# Don't prefer if the user used a protection move last turn, making this one # Don't prefer if the user used a protection move last turn, making this one
# less likely to work # less likely to work
score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10)
next score next score
} }
) )
@@ -940,20 +968,20 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShi
# be using, so we don't know if Unseen Fist will apply. # be using, so we don't know if Unseen Fist will apply.
useless = false useless = false
# General preference # General preference
score += 4 score += 7
# Prefer if this move will deal damage # Prefer if this move will deal damage
if b.battler.affectedByContactEffect? && b.check_for_move { |m| m.contactMove? } if b.battler.affectedByContactEffect? && b.check_for_move { |m| m.contactMove? }
score += 5 score += 5
end end
# Prefer if the foe is in the middle of using a two turn attack # Prefer if the foe is in the middle of using a two turn attack
score += 8 if b.effects[PBEffects::TwoTurnAttack] && score += 15 if b.effects[PBEffects::TwoTurnAttack] &&
GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] }
# Prefer if foe takes EOR damage, don't prefer if they have EOR healing # Prefer if foe takes EOR damage, don't prefer if they have EOR healing
b_eor_damage = b.rough_end_of_round_damage b_eor_damage = b.rough_end_of_round_damage
if b_eor_damage > 0 if b_eor_damage > 0
score += 5 score += 8
elsif b_eor_damage < 0 elsif b_eor_damage < 0
score -= 5 score -= 8
end end
end end
next Battle::AI::MOVE_USELESS_SCORE if useless next Battle::AI::MOVE_USELESS_SCORE if useless
@@ -962,13 +990,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserFromTargetingMovesSpikyShi
if user_eor_damage >= user.hp if user_eor_damage >= user.hp
next Battle::AI::MOVE_USELESS_SCORE next Battle::AI::MOVE_USELESS_SCORE
elsif user_eor_damage > 0 elsif user_eor_damage > 0
score -= 5 score -= 8
elsif user_eor_damage < 0 elsif user_eor_damage < 0
score += 5 score += 8
end end
# Don't prefer if the user used a protection move last turn, making this one # Don't prefer if the user used a protection move last turn, making this one
# less likely to work # less likely to work
score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10)
next score next score
} }
) )
@@ -992,16 +1020,16 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUse
# be using, so we don't know if Unseen Fist will apply. # be using, so we don't know if Unseen Fist will apply.
useless = false useless = false
# General preference # General preference
score += 4 score += 7
# Prefer if the foe is in the middle of using a two turn attack # Prefer if the foe is in the middle of using a two turn attack
score += 8 if b.effects[PBEffects::TwoTurnAttack] && score += 15 if b.effects[PBEffects::TwoTurnAttack] &&
GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] } GameData::Move.get(b.effects[PBEffects::TwoTurnAttack]).flags.any? { |f| f[/^CanProtect$/i] }
# Prefer if foe takes EOR damage, don't prefer if they have EOR healing # Prefer if foe takes EOR damage, don't prefer if they have EOR healing
b_eor_damage = b.rough_end_of_round_damage b_eor_damage = b.rough_end_of_round_damage
if b_eor_damage > 0 if b_eor_damage > 0
score += 5 score += 8
elsif b_eor_damage < 0 elsif b_eor_damage < 0
score -= 5 score -= 8
end end
end end
next Battle::AI::MOVE_USELESS_SCORE if useless next Battle::AI::MOVE_USELESS_SCORE if useless
@@ -1010,12 +1038,12 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromDamagingMovesIfUse
if user_eor_damage >= user.hp if user_eor_damage >= user.hp
next Battle::AI::MOVE_USELESS_SCORE next Battle::AI::MOVE_USELESS_SCORE
elsif user_eor_damage > 0 elsif user_eor_damage > 0
score -= 5 score -= 8
elsif user_eor_damage < 0 elsif user_eor_damage < 0
score += 5 score += 8
end end
# Use it or lose it # Use it or lose it
score += 10 score += 25
next score next score
} }
) )
@@ -1038,13 +1066,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromStatusMoves",
!m.pbTarget(b.battler).targets_all } !m.pbTarget(b.battler).targets_all }
useless = false useless = false
# General preference # General preference
score += 4 score += 5
# Prefer if foe takes EOR damage, don't prefer if they have EOR healing # Prefer if foe takes EOR damage, don't prefer if they have EOR healing
b_eor_damage = b.rough_end_of_round_damage b_eor_damage = b.rough_end_of_round_damage
if b_eor_damage > 0 if b_eor_damage > 0
score += 5 score += 8
elsif b_eor_damage < 0 elsif b_eor_damage < 0
score -= 5 score -= 8
end end
end end
next Battle::AI::MOVE_USELESS_SCORE if useless next Battle::AI::MOVE_USELESS_SCORE if useless
@@ -1053,9 +1081,9 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromStatusMoves",
if user_eor_damage >= user.hp if user_eor_damage >= user.hp
next Battle::AI::MOVE_USELESS_SCORE next Battle::AI::MOVE_USELESS_SCORE
elsif user_eor_damage > 0 elsif user_eor_damage > 0
score -= 5 score -= 8
elsif user_eor_damage < 0 elsif user_eor_damage < 0
score += 5 score += 8
end end
next score next score
} }
@@ -1082,13 +1110,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromPriorityMoves",
next if !b.check_for_move { |m| m.pbPriority(b.battler) > 0 && m.canProtectAgainst? } next if !b.check_for_move { |m| m.pbPriority(b.battler) > 0 && m.canProtectAgainst? }
useless = false useless = false
# General preference # General preference
score += 4 score += 7
# Prefer if foe takes EOR damage, don't prefer if they have EOR healing # Prefer if foe takes EOR damage, don't prefer if they have EOR healing
b_eor_damage = b.rough_end_of_round_damage b_eor_damage = b.rough_end_of_round_damage
if b_eor_damage > 0 if b_eor_damage > 0
score += 5 score += 8
elsif b_eor_damage < 0 elsif b_eor_damage < 0
score -= 5 score -= 8
end end
end end
next Battle::AI::MOVE_USELESS_SCORE if useless next Battle::AI::MOVE_USELESS_SCORE if useless
@@ -1097,13 +1125,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromPriorityMoves",
if user_eor_damage >= user.hp if user_eor_damage >= user.hp
next Battle::AI::MOVE_USELESS_SCORE next Battle::AI::MOVE_USELESS_SCORE
elsif user_eor_damage > 0 elsif user_eor_damage > 0
score -= 5 score -= 8
elsif user_eor_damage < 0 elsif user_eor_damage < 0
score += 5 score += 8
end end
# Don't prefer if the user used a protection move last turn, making this one # Don't prefer if the user used a protection move last turn, making this one
# less likely to work # less likely to work
score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10)
next score next score
} }
) )
@@ -1128,13 +1156,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromMultiTargetDamagin
m.pbTarget(b.battler).num_targets > 1 } m.pbTarget(b.battler).num_targets > 1 }
useless = false useless = false
# General preference # General preference
score += 4 score += 7
# Prefer if foe takes EOR damage, don't prefer if they have EOR healing # Prefer if foe takes EOR damage, don't prefer if they have EOR healing
b_eor_damage = b.rough_end_of_round_damage b_eor_damage = b.rough_end_of_round_damage
if b_eor_damage > 0 if b_eor_damage > 0
score += (b.opposes?(user)) ? 5 : -5 score += (b.opposes?(user)) ? 8 : -8
elsif b_eor_damage < 0 elsif b_eor_damage < 0
score -= (b.opposes?(user)) ? 5 : -5 score -= (b.opposes?(user)) ? 8 : -8
end end
end end
next Battle::AI::MOVE_USELESS_SCORE if useless next Battle::AI::MOVE_USELESS_SCORE if useless
@@ -1143,13 +1171,13 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromMultiTargetDamagin
if user_eor_damage >= user.hp if user_eor_damage >= user.hp
next Battle::AI::MOVE_USELESS_SCORE next Battle::AI::MOVE_USELESS_SCORE
elsif user_eor_damage > 0 elsif user_eor_damage > 0
score -= 5 score -= 8
elsif user_eor_damage < 0 elsif user_eor_damage < 0
score += 5 score += 8
end end
# Don't prefer if the user used a protection move last turn, making this one # Don't prefer if the user used a protection move last turn, making this one
# less likely to work # less likely to work
score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 12 : 8) score -= (user.effects[PBEffects::ProtectRate] - 1) * ((Settings::MECHANICS_GENERATION >= 6) ? 15 : 10)
next score next score
} }
) )
@@ -1163,7 +1191,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RemoveProtections",
m.is_a?(Battle::Move::ProtectUserSideFromStatusMoves) || m.is_a?(Battle::Move::ProtectUserSideFromStatusMoves) ||
m.is_a?(Battle::Move::ProtectUserSideFromDamagingMovesIfUserFirstTurn)) && m.is_a?(Battle::Move::ProtectUserSideFromDamagingMovesIfUserFirstTurn)) &&
!m.is_a?(Battle::Move::UserEnduresFaintingThisTurn) } !m.is_a?(Battle::Move::UserEnduresFaintingThisTurn) }
score += 5 score += 7
end end
next score next score
} }
@@ -1203,7 +1231,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilQuarterOfDamageDea
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes
end end
score -= 10 * [dmg, user.hp].min / user.hp score -= 25 * [dmg, user.hp].min / user.hp
next score next score
} }
) )
@@ -1221,7 +1249,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilThirdOfDamageDealt
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes
end end
score -= 10 * [dmg, user.hp].min / user.hp score -= 25 * [dmg, user.hp].min / user.hp
end end
# Score for paralysing # Score for paralysing
score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
@@ -1243,7 +1271,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilThirdOfDamageDealt
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes
end end
score -= 10 * [dmg, user.hp].min / user.hp score -= 25 * [dmg, user.hp].min / user.hp
end end
# Score for burning # Score for burning
score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("BurnTarget",
@@ -1264,7 +1292,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RecoilHalfOfDamageDealt"
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes next Battle::AI::MOVE_USELESS_SCORE if reserves <= foes
end end
score -= 10 * [dmg, user.hp].min / user.hp score -= 25 * [dmg, user.hp].min / user.hp
next score next score
} }
) )
@@ -1329,13 +1357,16 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("EnsureNextMoveAlwaysHits
# benefit from locking on. # benefit from locking on.
acc = m.accuracy acc = m.accuracy
acc = m.pbBaseAccuracy(user.battler, target.battler) if ai.trainer.medium_skill? acc = m.pbBaseAccuracy(user.battler, target.battler) if ai.trainer.medium_skill?
score += 4 if acc < 90 && acc != 0 score += 5 if acc < 90 && acc != 0
score += 4 if acc <= 50 && acc != 0 score += 8 if acc <= 50 && acc != 0
# TODO: Prefer more if m is a OHKO move. # TODO: Prefer more if m is a OHKO move.
end end
# TODO: Prefer if target has increased evasion.
# Not worth it if the user or the target is at low HP # Not worth it if the user or the target is at low HP
score -= 10 if user.hp < user.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
score -= 8 if target.hp < target.totalhp / 2 score -= 10 if user.hp < user.totalhp / 2
score -= 8 if target.hp < target.totalhp / 2
end
next score next score
} }
) )

View File

@@ -8,7 +8,8 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoTimes",
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimes", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoTimes",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Prefer if the target has a Substitute and the first hit can break it # Prefer if the target has a Substitute and this move can break it before
# the last hit
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
dmg = move.rough_damage dmg = move.rough_damage
num_hits = move.move.pbNumHits(user.battler, [target.battler]) num_hits = move.move.pbNumHits(user.battler, [target.battler])
@@ -72,7 +73,8 @@ Battle::AI::Handlers::MoveBasePower.add("HitThreeTimesPowersUpWithEachHit",
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitThreeTimesPowersUpWithEachHit", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitThreeTimesPowersUpWithEachHit",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Prefer if the target has a Substitute and the first or second hit can break it # Prefer if the target has a Substitute and this move can break it before
# the last hit
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
dmg = move.rough_damage dmg = move.rough_damage
score += 10 if target.effects[PBEffects::Substitute] < dmg / 2 score += 10 if target.effects[PBEffects::Substitute] < dmg / 2
@@ -101,7 +103,8 @@ Battle::AI::Handlers::MoveBasePower.add("HitTwoToFiveTimes",
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoToFiveTimes", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitTwoToFiveTimes",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Prefer if the target has a Substitute and the first hit(s) can break it # Prefer if the target has a Substitute and this move can break it before
# the last/third hit
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
dmg = move.rough_damage dmg = move.rough_damage
num_hits = (user.has_active_ability?(:SKILLLINK)) ? 5 : 3 # 3 is about average num_hits = (user.has_active_ability?(:SKILLLINK)) ? 5 : 3 # 3 is about average
@@ -169,7 +172,8 @@ Battle::AI::Handlers::MoveBasePower.add("HitOncePerUserTeamMember",
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitOncePerUserTeamMember", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitOncePerUserTeamMember",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Prefer if the target has a Substitute and the first hit(s) can break it # Prefer if the target has a Substitute and this move can break it before
# the last hit
if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler) if target.effects[PBEffects::Substitute] > 0 && !move.move.ignoresSubstitute?(user.battler)
dmg = move.rough_damage dmg = move.rough_damage
num_hits = 0 num_hits = 0
@@ -188,10 +192,10 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HitOncePerUserTeamMember
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectScore.add("AttackAndSkipNextTurn", Battle::AI::Handlers::MoveEffectScore.add("AttackAndSkipNextTurn",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Don't prefer because it uses up two turns
score -= 10 if !user.has_active_ability?(:TRUANT)
# Don't prefer if user is at a high HP (treat this move as a last resort) # Don't prefer if user is at a high HP (treat this move as a last resort)
score -= 10 if user.hp >= user.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp >= user.totalhp / 2
end
next score next score
} }
) )
@@ -210,7 +214,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttack",
# Don't prefer because it uses up two turns # Don't prefer because it uses up two turns
score -= 10 score -= 10
# Don't prefer if user is at a low HP (time is better spent on quicker moves) # Don't prefer if user is at a low HP (time is better spent on quicker moves)
score -= 8 if user.hp < user.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp < user.totalhp / 2
end
# Don't prefer if target has a protecting move # Don't prefer if target has a protecting move
if ai.trainer.high_skill? && !(user.has_active_ability?(:UNSEENFIST) && move.move.contactMove?) if ai.trainer.high_skill? && !(user.has_active_ability?(:UNSEENFIST) && move.move.contactMove?)
has_protect_move = false has_protect_move = false
@@ -241,7 +247,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttack",
end end
end end
end end
score -= 15 if has_protect_move score -= 20 if has_protect_move
end end
next score next score
} }
@@ -367,9 +373,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl
# Score for being semi-invulnerable underground # Score for being semi-invulnerable underground
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
if b.check_for_move { |m| m.hitsDiggingTargets? } if b.check_for_move { |m| m.hitsDiggingTargets? }
score -= 8 score -= 10
else else
score += 5 score += 8
end end
end end
next score next score
@@ -387,9 +393,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl
# Score for being semi-invulnerable underwater # Score for being semi-invulnerable underwater
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
if b.check_for_move { |m| m.hitsDivingTargets? } if b.check_for_move { |m| m.hitsDivingTargets? }
score -= 8 score -= 10
else else
score += 5 score += 8
end end
end end
next score next score
@@ -407,9 +413,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl
# Score for being semi-invulnerable in the sky # Score for being semi-invulnerable in the sky
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
if b.check_for_move { |m| m.hitsFlyingTargets? } if b.check_for_move { |m| m.hitsFlyingTargets? }
score -= 8 score -= 10
else else
score += 5 score += 8
end end
end end
next score next score
@@ -455,7 +461,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerabl
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack", score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
# Score for being invulnerable # Score for being invulnerable
score += 5 score += 8
# Score for removing protections # Score for removing protections
score = Battle::AI::Handlers.apply_move_effect_against_target_score("RemoveProtections", score = Battle::AI::Handlers.apply_move_effect_against_target_score("RemoveProtections",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
@@ -506,9 +512,11 @@ Battle::AI::Handlers::MoveEffectScore.add("MultiTurnAttackBideThenReturnDoubleDa
end end
next Battle::AI::MOVE_USELESS_SCORE if !has_damaging_move next Battle::AI::MOVE_USELESS_SCORE if !has_damaging_move
# Don't prefer if the user isn't at high HP # Don't prefer if the user isn't at high HP
next Battle::AI::MOVE_USELESS_SCORE if user.hp <= user.totalhp / 4 if ai.trainer.has_skill_flag?("HPAware")
score -= 15 if user.hp <= user.totalhp / 2 next Battle::AI::MOVE_USELESS_SCORE if user.hp <= user.totalhp / 4
score -= 8 if user.hp <= user.totalhp * 3 / 4 score -= 15 if user.hp <= user.totalhp / 2
score -= 8 if user.hp <= user.totalhp * 3 / 4
end
next score next score
} }
) )

View File

@@ -12,20 +12,20 @@ Battle::AI::Handlers::MoveFailureCheck.add("HealUserFullyAndFallAsleep",
Battle::AI::Handlers::MoveEffectScore.add("HealUserFullyAndFallAsleep", Battle::AI::Handlers::MoveEffectScore.add("HealUserFullyAndFallAsleep",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp >= user.totalhp * 0.5
else score -= 10
score += 20 * (user.totalhp - user.hp) / user.totalhp else
score += 30 * (user.totalhp - user.hp) / user.totalhp # +15 to +30
end
end end
# Check whether an existing status problem will be removed # Check whether an existing status problem will be removed
score += 10 if user.status != :NONE if user.status != :NONE
# Check if user will be able to act while asleep score += (user.wants_status_problem?(user.status)) ? -10 : 8
end
# Check if user is happy to be asleep, e.g. can use moves while asleep
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
if user.check_for_move { |m| m.usableWhenAsleep? } score += (user.wants_status_problem?(:SLEEP)) ? 10 : -8
score += 10
else
score -= 10
end
end end
next score next score
} }
@@ -42,10 +42,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("HealUserHalfOfTotalHP",
Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHP", Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHP",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 if ai.trainer.has_skill_flag?("HPAware")
score -= 10 next score - 10 if user.hp >= user.totalhp * 0.5
else score += 30 * (user.totalhp - user.hp) / user.totalhp # +15 to +30
score += 20 * (user.totalhp - user.hp) / user.totalhp
end end
next score next score
} }
@@ -59,17 +58,14 @@ Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP",
Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnWeather", Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnWeather",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 score = Battle::AI::Handlers.apply_move_effect_score("HealUserHalfOfTotalHP",
score -= 10 score, move, user, ai, battle)
case user.battler.effectiveWeather
when :Sun, :HarshSun
score += 5
when :None, :StrongWinds
else else
case user.battler.effectiveWeather score -= 10
when :Sun, :HarshSun
score += 5
when :None, :StrongWinds
else
score -= 10
end
score += 20 * (user.totalhp - user.hp) / user.totalhp
end end
next score next score
} }
@@ -83,12 +79,9 @@ Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP",
Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnSandstorm", Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnSandstorm",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 score = Battle::AI::Handlers.apply_move_effect_score("HealUserHalfOfTotalHP",
score -= 10 score, move, user, ai, battle)
else score += 5 if user.battler.effectiveWeather == :Sandstorm
score += 5 if user.battler.effectiveWeather == :Sandstorm
score += 20 * (user.totalhp - user.hp) / user.totalhp
end
next score next score
} }
) )
@@ -101,15 +94,13 @@ Battle::AI::Handlers::MoveFailureCheck.copy("HealUserHalfOfTotalHP",
Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHPLoseFlyingTypeThisTurn", Battle::AI::Handlers::MoveEffectScore.add("HealUserHalfOfTotalHPLoseFlyingTypeThisTurn",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 score = Battle::AI::Handlers.apply_move_effect_score("HealUserHalfOfTotalHP",
score -= 10 score, move, user, ai, battle)
else # User loses the Flying type this round
score += 20 * (user.totalhp - user.hp) / user.totalhp
end
if user.has_type?(:FLYING) if user.has_type?(:FLYING)
# TODO: Decide whether losing the Flying type is good or bad. Look at # TODO: Decide whether losing the Flying type is good or bad. Look at
# type effectiveness changes against the user, and for foes' Ground # type effectiveness changes against the user, and for foes' Ground
# moves. Anything else? # moves (foe foes slower than the user). Anything else?
end end
next score next score
} }
@@ -125,15 +116,11 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("CureTargetStatusHealUse
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CureTargetStatusHealUserHalfOfTotalHP", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CureTargetStatusHealUserHalfOfTotalHP",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Will cure status
score -= 10
score += 15 if target.wants_status_problem?(target.status)
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 score = Battle::AI::Handlers.apply_move_effect_score("HealUserHalfOfTotalHP",
score -= 10 score, move, user, ai, battle)
else # Will cure target's status
score += 20 * (user.totalhp - user.hp) / user.totalhp score += (target.wants_status_problem?(target.status)) ? 10 : -8
end
next score next score
} }
) )
@@ -155,23 +142,23 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByTargetAttackLo
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
score = ai.get_score_for_target_stat_drop(score, target, move.move.statDown) score = ai.get_score_for_target_stat_drop(score, target, move.move.statDown)
end end
# Consider how much HP will be restored # Healing the user
heal_amt = target.rough_stat(:ATTACK) if target.has_active_ability?(:LIQUIDOOZE)
if heal_amt > user.totalhp * 0.3 # Only modify the score if it'll heal a decent amount score -= 20
# Things that affect healing caused by draining elsif user.battler.canHeal?
if target.has_active_ability?(:LIQUIDOOZE) score += 5 if user.has_active_item?(:BIGROOT)
score -= 20 if ai.trainer.has_skill_flag?("HPAware")
elsif user.battler.canHeal? # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 heal_amt = target.rough_stat(:ATTACK)
score -= 10 heal_amt *= 1.3 if user.has_active_item?(:BIGROOT)
else heal_amt = [heal_amt, user.totalhp - user.hp].min
heal_amt *= 1.3 if user.has_active_item?(:BIGROOT) if heal_amt > user.totalhp * 0.3 # Only modify the score if it'll heal a decent amount
heal_fraction = [user.totalhp - user.hp, heal_amt].min.to_f / user.totalhp if user.hp < user.totalhp * 0.5
score += 40 * heal_fraction * (user.totalhp - user.hp) / user.totalhp score += 20 * (user.totalhp - user.hp) / user.totalhp # +10 to +20
end
score += 20 * heal_amt / user.totalhp # +6 to +20
end end
end end
else
score -= 10 if target.has_active_ability?(:LIQUIDOOZE)
end end
next score next score
} }
@@ -182,19 +169,23 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByTargetAttackLo
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByHalfOfDamageDone", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByHalfOfDamageDone",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Consider how much HP will be restored rough_dmg = move.rough_damage
heal_amt = move.rough_damage / 2 if target.has_active_ability?(:LIQUIDOOZE)
if heal_amt > user.totalhp * 0.3 # Only modify the score if it'll heal a decent amount score -= 20 if rough_dmg < target.hp
# Things that affect healing caused by draining elsif user.battler.canHeal?
if target.has_active_ability?(:LIQUIDOOZE) score += 5 if user.has_active_item?(:BIGROOT)
score -= 20 if ai.trainer.has_skill_flag?("HPAware")
elsif user.battler.canHeal? # Consider how much HP will be restored
heal_amt = rough_dmg / 2
heal_amt *= 1.3 if user.has_active_item?(:BIGROOT) heal_amt *= 1.3 if user.has_active_item?(:BIGROOT)
heal_fraction = [user.totalhp - user.hp, heal_amt].min.to_f / user.totalhp heal_amt = [heal_amt, user.totalhp - user.hp].min
score += 40 * heal_fraction * (user.totalhp - user.hp) / user.totalhp if heal_amt > user.totalhp * 0.3 # Only modify the score if it'll heal a decent amount
if user.hp < user.totalhp * 0.5
score += 20 * (user.totalhp - user.hp) / user.totalhp # +10 to +20
end
score += 20 * heal_amt / user.totalhp # +6 to +20
end
end end
else
score -= 10 if target.has_active_ability?(:LIQUIDOOZE)
end end
next score next score
} }
@@ -216,19 +207,23 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("HealUserByHalfOfDamageD
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByThreeQuartersOfDamageDone", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserByThreeQuartersOfDamageDone",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Consider how much HP will be restored rough_dmg = move.rough_damage
heal_amt = move.rough_damage * 0.75 if target.has_active_ability?(:LIQUIDOOZE)
if heal_amt > user.totalhp * 0.3 # Only modify the score if it'll heal a decent amount score -= 20 if rough_dmg < target.hp
# Things that affect healing caused by draining elsif user.battler.canHeal?
if target.has_active_ability?(:LIQUIDOOZE) score += 5 if user.has_active_item?(:BIGROOT)
score -= 20 if ai.trainer.has_skill_flag?("HPAware")
elsif user.battler.canHeal? # Consider how much HP will be restored
heal_amt = rough_dmg * 0.75
heal_amt *= 1.3 if user.has_active_item?(:BIGROOT) heal_amt *= 1.3 if user.has_active_item?(:BIGROOT)
heal_fraction = [user.totalhp - user.hp, heal_amt].min.to_f / user.totalhp heal_amt = [heal_amt, user.totalhp - user.hp].min
score += 40 * heal_fraction * (user.totalhp - user.hp) / user.totalhp if heal_amt > user.totalhp * 0.3 # Only modify the score if it'll heal a decent amount
if user.hp < user.totalhp * 0.5
score += 20 * (user.totalhp - user.hp) / user.totalhp # +10 to +20
end
score += 20 * heal_amt / user.totalhp # +6 to +20
end
end end
else
score -= 10 if target.has_active_ability?(:LIQUIDOOZE)
end end
next score next score
} }
@@ -244,11 +239,14 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserAndAlliesQuarte
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserAndAlliesQuarterOfTotalHP", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserAndAlliesQuarterOfTotalHP",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next score if !target.battler.canHeal?
# Consider how much HP will be restored # Consider how much HP will be restored
if target.hp >= target.totalhp * 0.75 if ai.trainer.has_skill_flag?("HPAware")
score -= 5 if target.hp >= target.totalhp * 0.75
else score -= 5
score += 15 * (target.totalhp - target.hp) / target.totalhp else
score += 15 * (target.totalhp - target.hp) / target.totalhp # +3 to +15
end
end end
next score next score
} }
@@ -265,13 +263,12 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealUserAndAlliesQuarte
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserAndAlliesQuarterOfTotalHPCureStatus", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealUserAndAlliesQuarterOfTotalHPCureStatus",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if target.hp >= target.totalhp * 0.75 score = Battle::AI::Handlers.apply_move_effect_score("HealUserAndAlliesQuarterOfTotalHP",
score -= 5 score, move, user, ai, battle)
else
score += 15 * (target.totalhp - target.hp) / target.totalhp
end
# Check whether an existing status problem will be removed # Check whether an existing status problem will be removed
score += 10 if target.status != :NONE if target.status != :NONE
score += (target.wants_status_problem?(target.status)) ? -10 : 10
end
next score next score
} }
) )
@@ -288,14 +285,17 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealTargetHalfOfTotalHP"
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if target.opposes?(user) next Battle::AI::MOVE_USELESS_SCORE if target.opposes?(user)
# Consider how much HP will be restored # Consider how much HP will be restored
heal_amt = target.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
heal_amt = target.totalhp * 0.75 if move.move.pulseMove? && if target.hp >= target.totalhp * 0.5
user.has_active_ability?(:MEGALAUNCHER) score -= 10
if target.hp >= target.totalhp * 0.5 else
score -= 10 heal_amt = target.totalhp * 0.5
else heal_amt = target.totalhp * 0.75 if move.move.pulseMove? &&
heal_fraction = [target.totalhp - target.hp, heal_amt].min.to_f / target.totalhp user.has_active_ability?(:MEGALAUNCHER)
score += 40 * heal_fraction * (target.totalhp - target.hp) / target.totalhp heal_amt = [heal_amt, target.totalhp - target.hp].min
score += 20 * (target.totalhp - target.hp) / target.totalhp # +10 to +20
score += 20 * heal_amt / target.totalhp # +10 or +15
end
end end
next score next score
} }
@@ -310,13 +310,16 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealTargetDependingOnGra
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if user.opposes?(target) next Battle::AI::MOVE_USELESS_SCORE if user.opposes?(target)
# Consider how much HP will be restored # Consider how much HP will be restored
heal_amt = target.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
heal_amt = (target.totalhp * 2 / 3.0).round if battle.field.terrain == :Grassy if target.hp >= target.totalhp * 0.5
if target.hp >= target.totalhp * 0.5 score -= 10
score -= 10 else
else heal_amt = target.totalhp * 0.5
heal_fraction = [target.totalhp - target.hp, heal_amt].min.to_f / target.totalhp heal_amt = (target.totalhp * 2 / 3.0).round if battle.field.terrain == :Grassy
score += 40 * heal_fraction * (target.totalhp - target.hp) / target.totalhp heal_amt = [heal_amt, target.totalhp - target.hp].min
score += 20 * (target.totalhp - target.hp) / target.totalhp # +10 to +20
score += 20 * heal_amt / target.totalhp # +10 or +13
end
end end
next score next score
} }
@@ -333,10 +336,12 @@ Battle::AI::Handlers::MoveFailureCheck.add("HealUserPositionNextTurn",
Battle::AI::Handlers::MoveEffectScore.add("HealUserPositionNextTurn", Battle::AI::Handlers::MoveEffectScore.add("HealUserPositionNextTurn",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp >= user.totalhp * 0.5
else score -= 10
score += 15 * (user.totalhp - user.hp) / user.totalhp else
score += 20 * (user.totalhp - user.hp) / user.totalhp # +10 to +20
end
end end
next score next score
} }
@@ -352,8 +357,8 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurn",
) )
Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurn", Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurn",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
score += 10 score += 15
score += 10 if user.has_active_item?(:BIGROOT) score += 5 if user.has_active_item?(:BIGROOT)
next score next score
} }
) )
@@ -368,9 +373,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartHealUserEachTurnTrapUserInBattl
) )
Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurnTrapUserInBattle", Battle::AI::Handlers::MoveEffectScore.add("StartHealUserEachTurnTrapUserInBattle",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
score += 5 score += 8
score += 10 if user.turnCount < 2 score += 15 if user.turnCount < 2
score += 10 if user.has_active_item?(:BIGROOT) score += 5 if user.has_active_item?(:BIGROOT)
next score next score
} }
) )
@@ -386,7 +391,7 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartDamageTargetEachTu
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartDamageTargetEachTurnIfTargetAsleep", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartDamageTargetEachTurnIfTargetAsleep",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if target.statusCount <= 1 next Battle::AI::MOVE_USELESS_SCORE if target.statusCount <= 1
next score + 10 * target.statusCount next score + 8 * target.statusCount
} }
) )
@@ -402,20 +407,21 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartLeechSeedTarget",
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartLeechSeedTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartLeechSeedTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score += 15
# Prefer early on # Prefer early on
score += 10 if user.turnCount < 2 score += 10 if user.turnCount < 2
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
# Prefer if the user has no damaging moves # Prefer if the user has no damaging moves
score += 20 if !user.check_for_move { |m| m.damagingMove? } score += 10 if !user.check_for_move { |m| m.damagingMove? }
# Prefer if the target can't switch out to remove its seeding # Prefer if the target can't switch out to remove its seeding
score += 10 if !battle.pbCanChooseNonActive?(target.index) score += 8 if !battle.pbCanChooseNonActive?(target.index)
# Don't prefer if the leeched HP will hurt the user # Don't prefer if the leeched HP will hurt the user
score -= 20 if target.has_active_ability?([:LIQUIDOOZE]) score -= 20 if target.has_active_ability?([:LIQUIDOOZE])
end end
if ai.trainer.high_skill? if ai.trainer.high_skill?
# Prefer if user can stall while damage is dealt # Prefer if user can stall while damage is dealt
if user.check_for_move { |m| m.is_a?(Battle::Move::ProtectMove) } if user.check_for_move { |m| m.is_a?(Battle::Move::ProtectMove) }
score += 15 score += 10
end end
# Don't prefer if target can remove the seed # Don't prefer if target can remove the seed
if target.has_move_with_function?("RemoveUserBindingAndEntryHazards") if target.has_move_with_function?("RemoveUserBindingAndEntryHazards")
@@ -432,9 +438,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartLeechSeedTarget",
Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHP", Battle::AI::Handlers::MoveEffectScore.add("UserLosesHalfOfTotalHP",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
score -= 15 # User will lose 50% HP, don't prefer this move score -= 15 # User will lose 50% HP, don't prefer this move
if ai.trainer.medium_skill? if ai.trainer.has_skill_flag?("HPAware")
score += 10 if user.hp >= user.totalhp * 0.75 # User at 75% HP or more score += 15 if user.hp >= user.totalhp * 0.75 # User has HP to spare
score += 10 if user.hp <= user.totalhp * 0.25 # User at 25% HP or less score += 15 if user.hp <= user.totalhp * 0.25 # User is near fainting anyway; suicide
end end
if ai.trainer.high_skill? if ai.trainer.high_skill?
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
@@ -467,10 +473,10 @@ Battle::AI::Handlers::MoveFailureCheck.copy("UserLosesHalfOfTotalHPExplosive",
"UserFaintsExplosive") "UserFaintsExplosive")
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsExplosive", Battle::AI::Handlers::MoveEffectScore.add("UserFaintsExplosive",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
score -= 25 # User will faint, don't prefer this move score -= 20 # User will faint, don't prefer this move
if ai.trainer.medium_skill? if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp >= user.totalhp * 0.5 # User at 50% HP or more score -= 10 if user.hp >= user.totalhp * 0.5
score += 10 if user.hp <= user.totalhp * 0.25 # User at 25% HP or less score += 20 if user.hp <= user.totalhp * 0.25 # User is near fainting anyway; suicide
end end
if ai.trainer.high_skill? if ai.trainer.high_skill?
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
@@ -515,14 +521,14 @@ Battle::AI::Handlers::MoveEffectScore.copy("UserFaintsExplosive",
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserFaintsLowerTargetAtkSpAtk2", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserFaintsLowerTargetAtkSpAtk2",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score -= 25 # User will faint, don't prefer this move score -= 20 # User will faint, don't prefer this move
# Check the impact of lowering the target's stats # Check the impact of lowering the target's stats
score = ai.get_score_for_target_stat_drop(score, target, move.move.statDown) score = ai.get_score_for_target_stat_drop(score, target, move.move.statDown)
next score if score == Battle::AI::MOVE_USELESS_SCORE next score if score == Battle::AI::MOVE_USELESS_SCORE
# Score for the user fainting # Score for the user fainting
if ai.trainer.medium_skill? if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp >= user.totalhp * 0.5 # User at 50% HP or more score -= 10 if user.hp >= user.totalhp * 0.5
score += 10 if user.hp <= user.totalhp * 0.25 # User at 25% HP or less score += 20 if user.hp <= user.totalhp * 0.25 # User is near fainting anyway; suicide
end end
if ai.trainer.high_skill? if ai.trainer.high_skill?
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
@@ -545,7 +551,7 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserFaintsHealAndCureReplacement",
) )
Battle::AI::Handlers::MoveEffectScore.add("UserFaintsHealAndCureReplacement", Battle::AI::Handlers::MoveEffectScore.add("UserFaintsHealAndCureReplacement",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
score -= 25 # User will faint, don't prefer this move score -= 20 # User will faint, don't prefer this move
# Check whether the replacement user needs healing, and don't make the below # Check whether the replacement user needs healing, and don't make the below
# calculations if not # calculations if not
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
@@ -556,10 +562,11 @@ Battle::AI::Handlers::MoveEffectScore.add("UserFaintsHealAndCureReplacement",
break break
end end
next Battle::AI::MOVE_USELESS_SCORE if !need_healing next Battle::AI::MOVE_USELESS_SCORE if !need_healing
score += 10
end end
if ai.trainer.medium_skill? if ai.trainer.has_skill_flag?("HPAware")
score -= 10 if user.hp >= user.totalhp * 0.5 # User at 50% HP or more score -= 10 if user.hp >= user.totalhp * 0.5
score += 10 if user.hp <= user.totalhp * 0.25 # User at 25% HP or less score += 20 if user.hp <= user.totalhp * 0.25 # User is near fainting anyway; suicide
end end
if ai.trainer.high_skill? if ai.trainer.high_skill?
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
@@ -611,16 +618,17 @@ Battle::AI::Handlers::MoveEffectScore.add("StartPerishCountsForAllBattlers",
end end
next Battle::AI::MOVE_USELESS_SCORE if foes_affected == 0 next Battle::AI::MOVE_USELESS_SCORE if foes_affected == 0
score += 15 if allies_affected == 0 # No downside for user; cancel out inherent negative score score += 15 if allies_affected == 0 # No downside for user; cancel out inherent negative score
score += 15 * (foes_affected - allies_affected) score -= 15 * allies_affected
score += 5 * foes_with_high_hp score += 20 * foes_affected
score += 10 * foes_with_high_hp if ai.trainer.has_skill_flag?("HPAware")
end end
if ai.trainer.high_skill? if ai.trainer.high_skill?
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide) reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide) foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
if foes == 0 # Foe is down to their last Pokémon, can't lose Perish count if foes == 0 # Foe is down to their last Pokémon, can't lose Perish count
score += 30 # => Want to auto-win in 3 turns score += 25 # => Want to auto-win in 3 turns
elsif reserves == 0 # AI is down to its last Pokémon, can't lose Perish count elsif reserves == 0 # AI is down to its last Pokémon, can't lose Perish count
score -= 20 # => Don't want to auto-lose in 3 turns score -= 15 # => Don't want to auto-lose in 3 turns
end end
end end
next score next score
@@ -644,9 +652,9 @@ Battle::AI::Handlers::MoveEffectScore.add("AttackerFaintsIfUserFaints",
user_faster_count += 1 if user.faster_than?(b) user_faster_count += 1 if user.faster_than?(b)
end end
next score if user_faster_count == 0 # Move will almost certainly have no effect next score if user_faster_count == 0 # Move will almost certainly have no effect
score += 5 * user_faster_count score += 7 * user_faster_count
# Prefer this move at lower user HP # Prefer this move at lower user HP
if ai.trainer.medium_skill? if ai.trainer.has_skill_flag?("HPAware")
score += 20 if user.hp <= user.totalhp * 0.4 score += 20 if user.hp <= user.totalhp * 0.4
score += 10 if user.hp <= user.totalhp * 0.25 score += 10 if user.hp <= user.totalhp * 0.25
score += 15 if user.hp <= user.totalhp * 0.1 score += 15 if user.hp <= user.totalhp * 0.1
@@ -667,12 +675,12 @@ Battle::AI::Handlers::MoveEffectScore.add("SetAttackerMovePPTo0IfUserFaints",
user_faster_count += 1 if user.faster_than?(b) user_faster_count += 1 if user.faster_than?(b)
end end
next score if user_faster_count == 0 # Move will almost certainly have no effect next score if user_faster_count == 0 # Move will almost certainly have no effect
score += 5 * user_faster_count score += 7 * user_faster_count
# Prefer this move at lower user HP (not as preferred as Destiny Bond, though) # Prefer this move at lower user HP (not as preferred as Destiny Bond, though)
if ai.trainer.medium_skill? if ai.trainer.has_skill_flag?("HPAware")
score += 15 if user.hp <= user.totalhp * 0.4 score += 20 if user.hp <= user.totalhp * 0.4
score += 10 if user.hp <= user.totalhp * 0.25 score += 10 if user.hp <= user.totalhp * 0.25
score += 10 if user.hp <= user.totalhp * 0.1 score += 15 if user.hp <= user.totalhp * 0.1
end end
next score next score
} }

View File

@@ -13,8 +13,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTakesTargetItem",
user_no_item_preference = user.wants_item?(:NONE) user_no_item_preference = user.wants_item?(:NONE)
target_item_preference = target.wants_item?(target.item_id) target_item_preference = target.wants_item?(target.item_id)
target_no_item_preference = target.wants_item?(:NONE) target_no_item_preference = target.wants_item?(:NONE)
score += (user_item_preference - user_no_item_preference) * 3 score += user_item_preference - user_no_item_preference
score += (target_item_preference - target_no_item_preference) * 3 score += target_item_preference - target_no_item_preference
next score next score
} }
) )
@@ -35,8 +35,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetTakesUserItem",
user_no_item_preference = user.wants_item?(:NONE) user_no_item_preference = user.wants_item?(:NONE)
target_item_preference = target.wants_item?(user.item_id) target_item_preference = target.wants_item?(user.item_id)
target_no_item_preference = target.wants_item?(:NONE) target_no_item_preference = target.wants_item?(:NONE)
score -= (user_item_preference - user_no_item_preference) * 3 score += user_no_item_preference - user_item_preference
score -= (target_item_preference - target_no_item_preference) * 3 score += target_no_item_preference - target_item_preference
next score next score
} }
) )
@@ -60,11 +60,11 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapItems",
user_old_item_preference = user.wants_item?(user.item_id) user_old_item_preference = user.wants_item?(user.item_id)
target_new_item_preference = target.wants_item?(user.item_id) target_new_item_preference = target.wants_item?(user.item_id)
target_old_item_preference = target.wants_item?(target.item_id) target_old_item_preference = target.wants_item?(target.item_id)
score += (user_new_item_preference - user_old_item_preference) * 3 score += user_new_item_preference - user_old_item_preference
score -= (target_new_item_preference - target_old_item_preference) * 3 score += target_old_item_preference - target_new_item_preference
# Don't prefer if user used this move in the last round # Don't prefer if user used this move in the last round
score -= 15 if user.battler.lastMoveUsed && score -= 15 if user.battler.lastMoveUsed &&
GameData::Move.get(user.battler.lastMoveUsed).function_code == "UserTargetSwapItems" GameData::Move.get(user.battler.lastMoveUsed).function_code == move.function
next score next score
} }
) )
@@ -80,8 +80,8 @@ Battle::AI::Handlers::MoveFailureCheck.add("RestoreUserConsumedItem",
Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem", Battle::AI::Handlers::MoveEffectScore.add("RestoreUserConsumedItem",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
user_new_item_preference = user.wants_item?(user.battler.recycleItem) user_new_item_preference = user.wants_item?(user.battler.recycleItem)
user_old_item_preference = user.wants_item?(user.item_id) user_old_item_preference = user.wants_item?(:NONE)
score += (user_new_item_preference - user_old_item_preference) * 4 score += (user_new_item_preference - user_old_item_preference) * 2
next score next score
} }
) )
@@ -103,7 +103,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RemoveTargetItem",
# User can knock off the target's item; score it # User can knock off the target's item; score it
target_item_preference = target.wants_item?(target.item_id) target_item_preference = target.wants_item?(target.item_id)
target_no_item_preference = target.wants_item?(:NONE) target_no_item_preference = target.wants_item?(:NONE)
score += (target_item_preference - target_no_item_preference) * 4 score += (target_item_preference - target_no_item_preference) * 2
next score next score
} }
) )
@@ -121,7 +121,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DestroyTargetBerryOrGem"
# User can incinerate the target's item; score it # User can incinerate the target's item; score it
target_item_preference = target.wants_item?(target.item_id) target_item_preference = target.wants_item?(target.item_id)
target_no_item_preference = target.wants_item?(:NONE) target_no_item_preference = target.wants_item?(:NONE)
score += (target_item_preference - target_no_item_preference) * 4 score += (target_item_preference - target_no_item_preference) * 2
next score next score
} }
) )
@@ -142,7 +142,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CorrodeTargetItem",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
target_item_preference = target.wants_item?(target.item_id) target_item_preference = target.wants_item?(target.item_id)
target_no_item_preference = target.wants_item?(:NONE) target_no_item_preference = target.wants_item?(:NONE)
score += (target_item_preference - target_no_item_preference) * 4 score += (target_item_preference - target_no_item_preference) * 2
next score next score
} }
) )
@@ -158,8 +158,9 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("StartTargetCannotUseIte
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartTargetCannotUseItem", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("StartTargetCannotUseItem",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if !target.item || !target.item_active? next Battle::AI::MOVE_USELESS_SCORE if !target.item || !target.item_active?
# TODO: Useless if target's item cannot be negated or it has no effect.
item_score = target.wants_item?(target.item_id) item_score = target.wants_item?(target.item_id)
score += item_score * 3 score += item_score * 2
next score next score
} }
) )
@@ -176,6 +177,7 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems",
next if !b.item next if !b.item
# Skip b if its item is disabled # Skip b if its item is disabled
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
# TODO: Skip b if its item cannot be negated or it has no effect.
if battle.field.effects[PBEffects::MagicRoom] > 0 if battle.field.effects[PBEffects::MagicRoom] > 0
# NOTE: Same as b.item_active? but ignoring the Magic Room part. # NOTE: Same as b.item_active? but ignoring the Magic Room part.
next if b.effects[PBEffects::Embargo] > 0 next if b.effects[PBEffects::Embargo] > 0
@@ -194,10 +196,10 @@ Battle::AI::Handlers::MoveEffectScore.add("StartNegateHeldItems",
next Battle::AI::MOVE_USELESS_SCORE if !any_held_items next Battle::AI::MOVE_USELESS_SCORE if !any_held_items
if battle.field.effects[PBEffects::MagicRoom] > 0 if battle.field.effects[PBEffects::MagicRoom] > 0
next Battle::AI::MOVE_USELESS_SCORE if total_want >= 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 score -= [total_want, -5].max * 4 # Will enable items, prefer if allies affected more
else else
next Battle::AI::MOVE_USELESS_SCORE if total_want <= 0 next Battle::AI::MOVE_USELESS_SCORE if total_want <= 0
score += [total_want, 5].min * 5 # Will disable items, prefer if foes affected more score += [total_want, 5].min * 4 # Will disable items, prefer if foes affected more
end end
next score next score
} }
@@ -218,19 +220,19 @@ Battle::AI::Handlers::MoveEffectScore.add("UserConsumeBerryRaiseDefense2",
score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserDefense2", score = Battle::AI::Handlers.apply_move_effect_score("RaiseUserDefense2",
score, move, user, ai, battle) score, move, user, ai, battle)
# Score for the consumed berry's effect # Score for the consumed berry's effect
score += ai.get_score_change_for_consuming_item(user, user.item_id) score += user.get_score_change_for_consuming_item(user.item_id, true)
# Score for other results of consuming the berry # Score for other results of consuming the berry
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
# Prefer if user will heal itself with Cheek Pouch # Prefer if user will heal itself with Cheek Pouch
score += 5 if user.battler.canHeal? && user.hp < user.totalhp / 2 && score += 8 if user.battler.canHeal? && user.hp < user.totalhp / 2 &&
user.has_active_ability?(:CHEEKPOUCH) user.has_active_ability?(:CHEEKPOUCH)
# Prefer if target can recover the consumed berry # Prefer if target can recover the consumed berry
score += 8 if user.has_active_ability?(:HARVEST) || score += 8 if user.has_active_ability?(:HARVEST) ||
user.has_move_with_function?("RestoreUserConsumedItem") user.has_move_with_function?("RestoreUserConsumedItem")
# Prefer if user couldn't normally consume the berry # Prefer if user couldn't normally consume the berry
score += 4 if !user.battler.canConsumeBerry? score += 5 if !user.battler.canConsumeBerry?
# Prefer if user will become able to use Belch # Prefer if user will become able to use Belch
score += 4 if !user.battler.belched? && user.has_move_with_function?("FailsIfUserNotConsumedBerry") score += 5 if !user.battler.belched? && user.has_move_with_function?("FailsIfUserNotConsumedBerry")
# Prefer if user will benefit from not having an item # Prefer if user will benefit from not having an item
score += 5 if user.has_active_ability?(:UNBURDEN) score += 5 if user.has_active_ability?(:UNBURDEN)
end end
@@ -249,21 +251,21 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("AllBattlersConsumeBerry
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AllBattlersConsumeBerry", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("AllBattlersConsumeBerry",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for the consumed berry's effect # Score for the consumed berry's effect
score_change = ai.get_score_change_for_consuming_item(target, target.item_id) score_change = target.get_score_change_for_consuming_item(target.item_id, !target.opposes?(user))
# Score for other results of consuming the berry # Score for other results of consuming the berry
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
# Prefer if target will heal itself with Cheek Pouch # Prefer if target will heal itself with Cheek Pouch
score_change += 5 if target.battler.canHeal? && target.hp < target.totalhp / 2 && score_change += 8 if target.battler.canHeal? && target.hp < target.totalhp / 2 &&
target.has_active_ability?(:CHEEKPOUCH) target.has_active_ability?(:CHEEKPOUCH)
# Prefer if target can recover the consumed berry # Prefer if target can recover the consumed berry
score_change += 8 if target.has_active_ability?(:HARVEST) || score_change += 8 if target.has_active_ability?(:HARVEST) ||
target.has_move_with_function?("RestoreUserConsumedItem") target.has_move_with_function?("RestoreUserConsumedItem")
# Prefer if target couldn't normally consume the berry # Prefer if target couldn't normally consume the berry
score_change += 4 if !target.battler.canConsumeBerry? score_change += 5 if !target.battler.canConsumeBerry?
# Prefer if target will become able to use Belch # Prefer if target will become able to use Belch
score += 4 if !target.battler.belched? && target.has_move_with_function?("FailsIfUserNotConsumedBerry") score_change += 5 if !target.battler.belched? && target.has_move_with_function?("FailsIfUserNotConsumedBerry")
# Prefer if target will benefit from not having an item # Prefer if target will benefit from not having an item
score += 5 if target.has_active_ability?(:UNBURDEN) score_change += 5 if target.has_active_ability?(:UNBURDEN)
end end
score += (target.opposes?(user)) ? -score_change : score_change score += (target.opposes?(user)) ? -score_change : score_change
next score next score
@@ -280,21 +282,21 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserConsumeTargetBerry",
next score if target.effects[PBEffects::Substitute] > 0 next score if target.effects[PBEffects::Substitute] > 0
next score if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker next score if target.has_active_ability?(:STICKYHOLD) && !battle.moldBreaker
# Score the user gaining the item's effect # Score the user gaining the item's effect
score += ai.get_score_change_for_consuming_item(user, target.item_id) score += user.get_score_change_for_consuming_item(target.item_id)
# Score for other results of consuming the berry # Score for other results of consuming the berry
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
# Prefer if user will heal itself with Cheek Pouch # Prefer if user will heal itself with Cheek Pouch
score += 5 if user.battler.canHeal? && user.hp < user.totalhp / 2 && score += 8 if user.battler.canHeal? && user.hp < user.totalhp / 2 &&
user.has_active_ability?(:CHEEKPOUCH) user.has_active_ability?(:CHEEKPOUCH)
# Prefer if user will become able to use Belch # Prefer if user will become able to use Belch
score += 4 if !user.battler.belched? && user.has_move_with_function?("FailsIfUserNotConsumedBerry") score += 5 if !user.battler.belched? && user.has_move_with_function?("FailsIfUserNotConsumedBerry")
# Don't prefer if target will benefit from not having an item # Don't prefer if target will benefit from not having an item
score -= 5 if target.has_active_ability?(:UNBURDEN) score -= 5 if target.has_active_ability?(:UNBURDEN)
end end
# Score the target no longer having the item # Score the target no longer having the item
target_item_preference = target.wants_item?(target.item_id) target_item_preference = target.wants_item?(target.item_id)
target_no_item_preference = target.wants_item?(:NONE) target_no_item_preference = target.wants_item?(:NONE)
score += (target_item_preference - target_no_item_preference) * 4 score += (target_item_preference - target_no_item_preference) * 2
next score next score
} }
) )
@@ -332,12 +334,12 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ThrowUserItemAtTarget",
score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget", score = Battle::AI::Handlers.apply_move_effect_against_target_score("FlinchTarget",
score, move, user, target, ai, battle) score, move, user, target, ai, battle)
else else
score -= ai.get_score_change_for_consuming_item(target, user.item_id) score -= target.get_score_change_for_consuming_item(user.item_id)
end end
# Score for other results of consuming the berry # Score for other results of consuming the berry
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
# Don't prefer if target will become able to use Belch # Don't prefer if target will become able to use Belch
score -= 4 if user.item.is_berry? && !target.battler.belched? && score -= 5 if user.item.is_berry? && !target.battler.belched? &&
target.has_move_with_function?("FailsIfUserNotConsumedBerry") target.has_move_with_function?("FailsIfUserNotConsumedBerry")
# Prefer if user will benefit from not having an item # Prefer if user will benefit from not having an item
score += 5 if user.has_active_ability?(:UNBURDEN) score += 5 if user.has_active_ability?(:UNBURDEN)
@@ -346,7 +348,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ThrowUserItemAtTarget",
# keep its held item # keep its held item
user_item_preference = user.wants_item?(user.item_id) user_item_preference = user.wants_item?(user.item_id)
user_no_item_preference = user.wants_item?(:NONE) user_no_item_preference = user.wants_item?(:NONE)
score += (user_item_preference - user_no_item_preference) * 4 score += (user_item_preference - user_no_item_preference) * 2
next score next score
} }
) )

View File

@@ -6,7 +6,7 @@ Battle::AI::Handlers::MoveEffectScore.add("RedirectAllMovesToUser",
# Useless if there is no ally to redirect attacks from # Useless if there is no ally to redirect attacks from
next Battle::AI::MOVE_USELESS_SCORE if user.battler.allAllies.length == 0 next Battle::AI::MOVE_USELESS_SCORE if user.battler.allAllies.length == 0
# Prefer if ally is at low HP and user is at high HP # Prefer if ally is at low HP and user is at high HP
if user.hp > user.totalhp * 2 / 3 if ai.trainer.has_skill_flag?("HPAware") && user.hp > user.totalhp * 2 / 3
ai.each_ally(user.index) do |b, i| ai.each_ally(user.index) do |b, i|
score += 10 if b.hp <= b.totalhp / 3 score += 10 if b.hp <= b.totalhp / 3
end end
@@ -27,7 +27,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RedirectAllMovesToTarget
next Battle::AI::MOVE_USELESS_SCORE if user.battler.allAllies.length == 0 next Battle::AI::MOVE_USELESS_SCORE if user.battler.allAllies.length == 0
end end
# Generaly don't prefer this move, as it's a waste of the user's turn # Generaly don't prefer this move, as it's a waste of the user's turn
next score - 15 next score - 20
} }
) )
@@ -47,7 +47,7 @@ Battle::AI::Handlers::MoveBasePower.add("RandomlyDamageOrHealTarget",
Battle::AI::Handlers::MoveEffectScore.add("RandomlyDamageOrHealTarget", Battle::AI::Handlers::MoveEffectScore.add("RandomlyDamageOrHealTarget",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
# Generaly don't prefer this move, as it may heal the target instead # Generaly don't prefer this move, as it may heal the target instead
next score - 8 next score - 10
} }
) )
@@ -56,17 +56,18 @@ Battle::AI::Handlers::MoveEffectScore.add("RandomlyDamageOrHealTarget",
#=============================================================================== #===============================================================================
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealAllyOrDamageFoe", Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("HealAllyOrDamageFoe",
proc { |move, user, target, ai, battle| proc { |move, user, target, ai, battle|
next !target.opposes?(user) && target.battler.canHeal? next !target.opposes?(user) && !target.battler.canHeal?
} }
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealAllyOrDamageFoe", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HealAllyOrDamageFoe",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if !target.opposes?(user) next score if target.opposes?(user)
# Consider how much HP will be restored # Consider how much HP will be restored
if ai.trainer.has_skill_flag?("HPAware")
if target.hp >= target.totalhp * 0.5 if target.hp >= target.totalhp * 0.5
score -= 10 score -= 10
else else
score += 20 * (target.totalhp - target.hp) / target.totalhp score += 20 * (target.totalhp - target.hp) / target.totalhp # +10 to +20
end end
end end
next score next score
@@ -116,19 +117,21 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("CurseTargetOrLowerUserSp
next score if !user.has_type?(:GHOST) && next score if !user.has_type?(:GHOST) &&
!(move.rough_type == :GHOST && user.has_active_ability?([:LIBERO, :PROTEAN])) !(move.rough_type == :GHOST && user.has_active_ability?([:LIBERO, :PROTEAN]))
# Don't prefer if user will faint because of using this move # Don't prefer if user will faint because of using this move
next Battle::AI::MOVE_USELESS_SCORE if user.hp <= user.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware")
next Battle::AI::MOVE_USELESS_SCORE if user.hp <= user.totalhp / 2
end
# Prefer early on # Prefer early on
score += 10 if user.turnCount < 2 score += 10 if user.turnCount < 2
if ai.trainer.medium_skill? if ai.trainer.medium_skill?
# Prefer if the user has no damaging moves # Prefer if the user has no damaging moves
score += 20 if !user.check_for_move { |m| m.damagingMove? } score += 15 if !user.check_for_move { |m| m.damagingMove? }
# Prefer if the target can't switch out to remove its curse # Prefer if the target can't switch out to remove its curse
score += 10 if !battle.pbCanChooseNonActive?(target.index) score += 10 if !battle.pbCanChooseNonActive?(target.index)
end end
if ai.trainer.high_skill? if ai.trainer.high_skill?
# Prefer if user can stall while damage is dealt # Prefer if user can stall while damage is dealt
if user.check_for_move { |m| m.is_a?(Battle::Move::ProtectMove) } if user.check_for_move { |m| m.is_a?(Battle::Move::ProtectMove) }
score += 8 score += 5
end end
end end
next score next score
@@ -192,13 +195,10 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetNextFireMoveDamag
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetNextFireMoveDamagesTarget", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetNextFireMoveDamagesTarget",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Effect wears off at the end of the round
next Battle::AI::MOVE_USELESS_SCORE if target.faster_than?(user)
# Prefer if target knows any Fire moves (moreso if that's the only type they know) # Prefer if target knows any Fire moves (moreso if that's the only type they know)
if target.check_for_move { |m| m.pbCalcType(b.battler) == :FIRE } next Battle::AI::MOVE_USELESS_SCORE if !target.check_for_move { |m| m.pbCalcType(target.battler) == :FIRE }
score += 10 score += 10
score += 10 if !target.check_for_move { |m| m.pbCalcType(b.battler) != :FIRE } score += 10 if !target.check_for_move { |m| m.pbCalcType(target.battler) != :FIRE }
end
next score next score
} }
) )
@@ -240,7 +240,7 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("PowerUpAllyMove",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PowerUpAllyMove", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PowerUpAllyMove",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if !target.check_for_move { |m| m.damagingMove? } next Battle::AI::MOVE_USELESS_SCORE if !target.check_for_move { |m| m.damagingMove? }
next score + 4 next score + 5
} }
) )
@@ -265,10 +265,10 @@ Battle::AI::Handlers::MoveEffectScore.add("CounterPhysicalDamage",
score += 5 if b.rough_stat(:ATTACK) > b.rough_stat(:SPECIAL_ATTACK) score += 5 if b.rough_stat(:ATTACK) > b.rough_stat(:SPECIAL_ATTACK)
# Prefer if the last move the foe used was physical # Prefer if the last move the foe used was physical
if ai.trainer.medium_skill? && b.battler.lastMoveUsed if ai.trainer.medium_skill? && b.battler.lastMoveUsed
score += 5 if GameData::Move.get(b.battler.lastMoveUsed).physical? score += 8 if GameData::Move.get(b.battler.lastMoveUsed).physical?
end end
# Prefer if the foe is taunted into using a damaging move # Prefer if the foe is taunted into using a damaging move
score += 4 if b.effects[PBEffects::Taunt] > 0 score += 5 if b.effects[PBEffects::Taunt] > 0
end end
# Useless if no foes have a physical move to counter # Useless if no foes have a physical move to counter
next Battle::AI::MOVE_USELESS_SCORE if !has_physical_move next Battle::AI::MOVE_USELESS_SCORE if !has_physical_move
@@ -297,10 +297,10 @@ Battle::AI::Handlers::MoveEffectScore.add("CounterSpecialDamage",
score += 5 if b.rough_stat(:SPECIAL_ATTACK) > b.rough_stat(:ATTACK) score += 5 if b.rough_stat(:SPECIAL_ATTACK) > b.rough_stat(:ATTACK)
# Prefer if the last move the foe used was special # Prefer if the last move the foe used was special
if ai.trainer.medium_skill? && b.battler.lastMoveUsed if ai.trainer.medium_skill? && b.battler.lastMoveUsed
score += 5 if GameData::Move.get(b.battler.lastMoveUsed).special? score += 8 if GameData::Move.get(b.battler.lastMoveUsed).special?
end end
# Prefer if the foe is taunted into using a damaging move # Prefer if the foe is taunted into using a damaging move
score += 4 if b.effects[PBEffects::Taunt] > 0 score += 5 if b.effects[PBEffects::Taunt] > 0
end end
# Useless if no foes have a special move to counter # Useless if no foes have a special move to counter
next Battle::AI::MOVE_USELESS_SCORE if !has_special_move next Battle::AI::MOVE_USELESS_SCORE if !has_special_move
@@ -327,10 +327,10 @@ Battle::AI::Handlers::MoveEffectScore.add("CounterDamagePlusHalf",
has_damaging_move = true has_damaging_move = true
# Prefer if the last move the foe used was damaging # Prefer if the last move the foe used was damaging
if ai.trainer.medium_skill? && b.battler.lastMoveUsed if ai.trainer.medium_skill? && b.battler.lastMoveUsed
score += 5 if GameData::Move.get(b.battler.lastMoveUsed).damaging? score += 8 if GameData::Move.get(b.battler.lastMoveUsed).damaging?
end end
# Prefer if the foe is taunted into using a damaging move # Prefer if the foe is taunted into using a damaging move
score += 6 if b.effects[PBEffects::Taunt] > 0 score += 5 if b.effects[PBEffects::Taunt] > 0
end end
# Useless if no foes have a damaging move to counter # Useless if no foes have a damaging move to counter
next Battle::AI::MOVE_USELESS_SCORE if !has_damaging_move next Battle::AI::MOVE_USELESS_SCORE if !has_damaging_move
@@ -352,7 +352,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UserAddStockpileRaiseDefSpDef1",
# More preferable if user also has Spit Up/Swallow # More preferable if user also has Spit Up/Swallow
if user.battler.pbHasMoveFunction?("PowerDependsOnUserStockpile", if user.battler.pbHasMoveFunction?("PowerDependsOnUserStockpile",
"HealUserDependingOnUserStockpile") "HealUserDependingOnUserStockpile")
score += [10, 8, 5, 3][user.effects[PBEffects::Stockpile]] score += [10, 10, 8, 5][user.effects[PBEffects::Stockpile]]
end end
next score next score
} }
@@ -397,13 +397,12 @@ Battle::AI::Handlers::MoveEffectScore.add("HealUserDependingOnUserStockpile",
proc { |score, move, user, ai, battle| proc { |score, move, user, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if !user.battler.canHeal? next Battle::AI::MOVE_USELESS_SCORE if !user.battler.canHeal?
# Consider how much HP will be restored # Consider how much HP will be restored
if user.hp >= user.totalhp * 0.5 if ai.trainer.has_skill_flag?("HPAware")
score -= 10 next score - 10 if user.hp >= user.totalhp * 0.5
else score += 20 * (user.totalhp - user.hp) / user.totalhp # +10 to +20
# Slightly prefer to hold out for another Stockpile to make this move stronger
score -= 5 if user.effects[PBEffects::Stockpile] < 2
score += 20 * (user.totalhp - user.hp) / user.totalhp
end end
# Slightly prefer to hold out for another Stockpile to make this move stronger
score -= 5 if user.effects[PBEffects::Stockpile] < 2
next score next score
} }
) )
@@ -550,13 +549,13 @@ Battle::AI::Handlers::MoveEffectScore.add("BounceBackProblemCausingStatusMoves",
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
next if !b.can_attack? next if !b.can_attack?
next if !b.check_for_move { |m| m.statusMove? && m.canMagicCoat? } next if !b.check_for_move { |m| m.statusMove? && m.canMagicCoat? }
score += 4 score += 5
useless = false useless = false
end end
next Battle::AI::MOVE_USELESS_SCORE if useless next Battle::AI::MOVE_USELESS_SCORE if useless
# Don't prefer the lower the user's HP is (better to try something else) # Don't prefer the lower the user's HP is (better to try something else)
if user.hp < user.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware") && user.hp < user.totalhp / 2
score -= 20 * (0.75 - (user.hp.to_f / user.totalhp)) # -5 to -15 score -= (20 * (1.0 - (user.hp.to_f / user.totalhp))).to_i # -10 to -20
end end
next score next score
} }
@@ -571,13 +570,13 @@ Battle::AI::Handlers::MoveEffectScore.add("StealAndUseBeneficialStatusMove",
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
next if !b.can_attack? next if !b.can_attack?
next if !b.check_for_move { |m| m.statusMove? && m.canSnatch? } next if !b.check_for_move { |m| m.statusMove? && m.canSnatch? }
score += 4 score += 5
useless = false useless = false
end end
next Battle::AI::MOVE_USELESS_SCORE if useless next Battle::AI::MOVE_USELESS_SCORE if useless
# Don't prefer the lower the user's HP is (better to try something else) # Don't prefer the lower the user's HP is (better to try something else)
if user.hp < user.totalhp / 2 if ai.trainer.has_skill_flag?("HPAware") && user.hp < user.totalhp / 2
score -= 20 * (0.75 - (user.hp.to_f / user.totalhp)) # -5 to -15 score -= (20 * (1.0 - (user.hp.to_f / user.totalhp))).to_i # -10 to -20
end end
next score next score
} }
@@ -606,7 +605,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("ReplaceMoveThisBattleWit
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Generally don't prefer, as this wastes the user's turn just to gain a move # Generally don't prefer, as this wastes the user's turn just to gain a move
# of unknown utility # of unknown utility
score -= 8 score -= 10
# Slightly prefer if this move will definitely succeed, just for the sake of # Slightly prefer if this move will definitely succeed, just for the sake of
# getting rid of this move # getting rid of this move
score += 5 if user.faster_than?(target) score += 5 if user.faster_than?(target)

View File

@@ -139,9 +139,9 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("SwitchOutTargetStatusMo
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SwitchOutTargetStatusMove", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SwitchOutTargetStatusMove",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
score += 20 if target.pbOwnSide.effects[PBEffects::Spikes] > 0 score += 15 if target.pbOwnSide.effects[PBEffects::Spikes] > 0
score += 20 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0 score += 15 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0
score += 20 if target.pbOwnSide.effects[PBEffects::StealthRock] score += 15 if target.pbOwnSide.effects[PBEffects::StealthRock]
next score next score
} }
) )
@@ -153,9 +153,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("SwitchOutTargetDamagingM
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
if (battle.moldBreaker || !target.has_active_ability?(:SUCTIONCUPS)) && if (battle.moldBreaker || !target.has_active_ability?(:SUCTIONCUPS)) &&
!target.effects[PBEffects::Ingrain] !target.effects[PBEffects::Ingrain]
score += 20 if target.pbOwnSide.effects[PBEffects::Spikes] > 0 score += 15 if target.pbOwnSide.effects[PBEffects::Spikes] > 0
score += 20 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0 score += 15 if target.pbOwnSide.effects[PBEffects::ToxicSpikes] > 0
score += 20 if target.pbOwnSide.effects[PBEffects::StealthRock] score += 15 if target.pbOwnSide.effects[PBEffects::StealthRock]
end end
next score next score
} }
@@ -172,7 +172,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTarget",
# you don't want to use it?) # you don't want to use it?)
score += 5 if user.has_active_item?([:BINDINGBAND, :GRIPCLAW]) score += 5 if user.has_active_item?([:BINDINGBAND, :GRIPCLAW])
# Target will take damage at the end of each round from the binding # Target will take damage at the end of each round from the binding
score += 8 if target.battler.takesIndirectDamage? score += 10 if target.battler.takesIndirectDamage?
# Check whether the target will be trapped in battle by the binding # Check whether the target will be trapped in battle by the binding
if target.can_become_trapped? if target.can_become_trapped?
score += 8 # Prefer if the target will become trapped by this move score += 8 # Prefer if the target will become trapped by this move
@@ -180,20 +180,20 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("BindTarget",
if eor_damage > 0 if eor_damage > 0
# Prefer if the target will take damage at the end of each round on top # Prefer if the target will take damage at the end of each round on top
# of binding damage # of binding damage
score += 8 score += 10
elsif eor_damage < 0 elsif eor_damage < 0
# Don't prefer if the target will heal itself at the end of each round # Don't prefer if the target will heal itself at the end of each round
score -= 8 score -= 10
end end
# Prefer if the target has been Perish Songed # Prefer if the target has been Perish Songed
score += 10 if target.effects[PBEffects::PerishSong] > 0 score += 15 if target.effects[PBEffects::PerishSong] > 0
end end
# Don't prefer if the target can remove the binding (and the binding has an # Don't prefer if the target can remove the binding (and the binding has an
# effect) # effect)
if target.can_become_trapped? || target.battler.takesIndirectDamage? if target.can_become_trapped? || target.battler.takesIndirectDamage?
if ai.trainer.medium_skill? && if ai.trainer.medium_skill? &&
target.has_move_with_function?("RemoveUserBindingAndEntryHazards") target.has_move_with_function?("RemoveUserBindingAndEntryHazards")
score -= 8 score -= 10
end end
end end
next score next score
@@ -232,13 +232,6 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattle",
if eor_damage >= target.hp if eor_damage >= target.hp
next (move.damagingMove?) ? score : Battle::AI::MOVE_USELESS_SCORE next (move.damagingMove?) ? score : Battle::AI::MOVE_USELESS_SCORE
end 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 # Not worth trapping if target can remove the binding
if ai.trainer.medium_skill? && if ai.trainer.medium_skill? &&
target.has_move_with_function?("RemoveUserBindingAndEntryHazards") target.has_move_with_function?("RemoveUserBindingAndEntryHazards")
@@ -256,7 +249,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattle",
if target.effects[PBEffects::PerishSong] > 0 || if target.effects[PBEffects::PerishSong] > 0 ||
target.effects[PBEffects::Attract] >= 0 || target.effects[PBEffects::Attract] >= 0 ||
eor_damage > 0 eor_damage > 0
score += 12 score += 15
end end
next score next score
} }
@@ -284,7 +277,7 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TrapTargetInBattleLower
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattleLowerTargetDefSpDef1EachTurn",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Score for stat drop # Score for stat drop
score = ai.get_score_for_target_stat_drop(score, target, [:DEFENSE, 1, :SPECIAL_DEFENSE], false) score = ai.get_score_for_target_stat_drop(score, target, [:DEFENSE, 1, :SPECIAL_DEFENSE, 1], false)
# Score for target becoming trapped in battle # Score for target becoming trapped in battle
if target.can_become_trapped? && battle.pbCanChooseNonActive?(target.index) if target.can_become_trapped? && battle.pbCanChooseNonActive?(target.index)
# Not worth trapping if target will faint this round anyway # Not worth trapping if target will faint this round anyway
@@ -304,7 +297,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapTargetInBattleLowerT
if target.effects[PBEffects::PerishSong] > 0 || if target.effects[PBEffects::PerishSong] > 0 ||
target.effects[PBEffects::Attract] >= 0 || target.effects[PBEffects::Attract] >= 0 ||
eor_damage > 0 eor_damage > 0
score += 12 score += 15
end end
end end
next score next score
@@ -338,7 +331,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TrapUserAndTargetInBattl
if target.effects[PBEffects::PerishSong] > 0 || if target.effects[PBEffects::PerishSong] > 0 ||
target.effects[PBEffects::Attract] >= 0 || target.effects[PBEffects::Attract] >= 0 ||
eor_damage > 0 eor_damage > 0
score += 12 score += 15
end end
end end
next score next score
@@ -403,7 +396,7 @@ Battle::AI::Handlers::MoveEffectScore.add("UsedAfterAllyRoundWithDoublePower",
end end
next score if !ally_has_move next score if !ally_has_move
# Prefer for the sake of doubling in power # Prefer for the sake of doubling in power
score += 5 score += 10
next score next score
} }
) )
@@ -502,7 +495,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetUsesItsLastUsedMov
# ally (since we're here in this code), this move's score will be # ally (since we're here in this code), this move's score will be
# inverted later. A higher score here means this move will be less # inverted later. A higher score here means this move will be less
# preferred, which is the result we want. # preferred, which is the result we want.
score += 20 score += 10
next score next score
} }
) )
@@ -601,19 +594,19 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetLastMoveUs
next !target.check_for_move { |m| m.id == target.battler.lastRegularMoveUsed } next !target.check_for_move { |m| m.id == target.battler.lastRegularMoveUsed }
} }
) )
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingSameMoveConsecutively", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetLastMoveUsed",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if target.has_active_item?(:MENTALHERB) next Battle::AI::MOVE_USELESS_SCORE if target.has_active_item?(:MENTALHERB)
# Inherent preference
score += 5
# Prefer if the target is locked into using a single move, or will be # Prefer if the target is locked into using a single move, or will be
if target.effects[PBEffects::ChoiceBand] || if target.effects[PBEffects::ChoiceBand] ||
target.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) || target.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) ||
target.has_active_ability?(:GORILLATACTICS) target.has_active_ability?(:GORILLATACTICS)
score += 8 score += 10
end end
# PRefer disabling a damaging move # Prefer disabling a damaging move
score += 5 if GameData::Move.try_get(target.battler.lastRegularMoveUsed)&.damaging? score += 8 if GameData::Move.try_get(target.battler.lastRegularMoveUsed)&.damaging?
# Inherent preference
score += 8
next score next score
} }
) )
@@ -631,14 +624,14 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("DisableTargetUsingSameM
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingSameMoveConsecutively", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingSameMoveConsecutively",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
next Battle::AI::MOVE_USELESS_SCORE if target.has_active_item?(:MENTALHERB) next Battle::AI::MOVE_USELESS_SCORE if target.has_active_item?(:MENTALHERB)
# Inherent preference
score += 10
# Prefer if the target is locked into using a single move, or will be # Prefer if the target is locked into using a single move, or will be
if target.effects[PBEffects::ChoiceBand] || if target.effects[PBEffects::ChoiceBand] ||
target.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) || target.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) ||
target.has_active_ability?(:GORILLATACTICS) target.has_active_ability?(:GORILLATACTICS)
score += 8 score += 10
end end
# Inherent preference
score += 8
next score next score
} }
) )
@@ -672,24 +665,24 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetUsingDiffer
else else
score += 8 score += 8
end end
elsif move_data.damaging? && move_data.target == :NearOther elsif move_data.damaging? && [:NearOther, :Other].include?(move_data.target)
# Prefer encoring damaging moves depending on their type effectiveness # Prefer encoring damaging moves depending on their type effectiveness
# against the user # against the user
eff = user.effectiveness_of_type_against_battler(move_data.type, target) eff = user.effectiveness_of_type_against_battler(move_data.type, target)
if Effectiveness.ineffective?(eff) if Effectiveness.ineffective?(eff)
score += 15 score += 20
elsif Effectiveness.not_very_effective?(eff) elsif Effectiveness.not_very_effective?(eff)
score += 10 score += 15
elsif Effectiveness.super_effective?(eff) elsif Effectiveness.super_effective?(eff)
score -= 5 score -= 8
else else
score += 5 score += 8
end end
end end
else else
# We don't know which move is going to be encored; just prefer limiting # We don't know which move is going to be encored; just prefer limiting
# the target's options # the target's options
score += 8 score += 10
end end
next score next score
} }
@@ -717,13 +710,17 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetStatusMoves
end end
end end
# Move is likely useless if the target will lock themselves into a move, # Move is likely useless if the target will lock themselves into a move,
# because they'll likely lock themselves into a damaging move anyway # because they'll likely lock themselves into a damaging move
if !target.effects[PBEffects::ChoiceBand] if !target.effects[PBEffects::ChoiceBand]
if target.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) || if target.has_active_item?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF]) ||
target.has_active_ability?(:GORILLATACTICS) target.has_active_ability?(:GORILLATACTICS)
next Battle::AI::MOVE_USELESS_SCORE next Battle::AI::MOVE_USELESS_SCORE
end end
end end
# Prefer based on how many status moves the target knows
target.battler.eachMove do |m|
score += 5 if m.statusMove? && (m.pp > 0 || m.total_pp == 0)
end
# Prefer if the target has a protection move # Prefer if the target has a protection move
protection_moves = [ protection_moves = [
"ProtectUser", # Detect, Protect "ProtectUser", # Detect, Protect
@@ -738,10 +735,8 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetStatusMoves
"ProtectUserBanefulBunker" # Baneful Bunker "ProtectUserBanefulBunker" # Baneful Bunker
] ]
if target.check_for_move { |m| m.statusMove? && protection_moves.include?(m.function) } if target.check_for_move { |m| m.statusMove? && protection_moves.include?(m.function) }
score += 6 score += 10
end end
# Inherent preference
score += 8
next score next score
} }
) )
@@ -766,7 +761,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetHealingMove
end end
end end
# Inherent preference # Inherent preference
score += 8 score += 10
next score next score
} }
) )
@@ -799,16 +794,16 @@ Battle::AI::Handlers::MoveFailureCheck.add("DisableTargetMovesKnownByUser",
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetMovesKnownByUser", Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("DisableTargetMovesKnownByUser",
proc { |score, move, user, target, ai, battle| proc { |score, move, user, target, ai, battle|
# Useless if the foes have no moves that the user also knows # Useless if the foes have no moves that the user also knows
shared_move = false affected_foe_count = 0
user_moves = user.battler.moves.map { |m| m.id } user_moves = user.battler.moves.map { |m| m.id }
ai.each_foe_battler(user.side) do |b, i| ai.each_foe_battler(user.side) do |b, i|
next if !b.check_for_move { |m| user_moves.include?(m.id) } next if !b.check_for_move { |m| user_moves.include?(m.id) }
shared_move = true affected_foe_count += 1
break break
end end
next Battle::AI::MOVE_USELESS_SCORE if !shared_move next Battle::AI::MOVE_USELESS_SCORE if affected_foe_count == 0
# Inherent preference # Inherent preference
score += 6 score += 8 * affected_foe_count
next score next score
} }
) )

View File

@@ -74,7 +74,7 @@ end
#=============================================================================== #===============================================================================
MenuHandlers.add(:debug_menu, :print_move_target_functions, { MenuHandlers.add(:debug_menu, :print_move_target_functions, {
"name" => _INTL("Print Out Move Targets"), "name" => _INTL("Print Out Move Targets"),
"parent" => :other_menu, "parent" => :main,
"description" => _INTL("Print all blah blah blah."), "description" => _INTL("Print all blah blah blah."),
"effect" => proc { "effect" => proc {
marListMoveTargetFunctionCodes marListMoveTargetFunctionCodes