mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
More AI checks and fixes
This commit is contained in:
@@ -71,15 +71,22 @@ end
|
|||||||
# (Belly Drum)
|
# (Belly Drum)
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
class Battle::Move::MaxUserAttackLoseHalfOfTotalHP < Battle::Move
|
class Battle::Move::MaxUserAttackLoseHalfOfTotalHP < Battle::Move
|
||||||
|
attr_reader :statUp
|
||||||
|
|
||||||
def canSnatch?; return true; end
|
def canSnatch?; return true; end
|
||||||
|
|
||||||
|
def initialize(battle, move)
|
||||||
|
super
|
||||||
|
@statUp = [:ATTACK, 12]
|
||||||
|
end
|
||||||
|
|
||||||
def pbMoveFailed?(user, targets)
|
def pbMoveFailed?(user, targets)
|
||||||
hpLoss = [user.totalhp / 2, 1].max
|
hpLoss = [user.totalhp / 2, 1].max
|
||||||
if user.hp <= hpLoss
|
if user.hp <= hpLoss
|
||||||
@battle.pbDisplay(_INTL("But it failed!"))
|
@battle.pbDisplay(_INTL("But it failed!"))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return true if !user.pbCanRaiseStatStage?(:ATTACK, user, self, true)
|
return true if !user.pbCanRaiseStatStage?(@statUp[0], user, self, true)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -87,16 +94,18 @@ class Battle::Move::MaxUserAttackLoseHalfOfTotalHP < Battle::Move
|
|||||||
hpLoss = [user.totalhp / 2, 1].max
|
hpLoss = [user.totalhp / 2, 1].max
|
||||||
user.pbReduceHP(hpLoss, false, false)
|
user.pbReduceHP(hpLoss, false, false)
|
||||||
if user.hasActiveAbility?(:CONTRARY)
|
if user.hasActiveAbility?(:CONTRARY)
|
||||||
user.stages[:ATTACK] = -6
|
user.stages[@statUp[0]] = -6
|
||||||
user.statsLoweredThisRound = true
|
user.statsLoweredThisRound = true
|
||||||
user.statsDropped = true
|
user.statsDropped = true
|
||||||
@battle.pbCommonAnimation("StatDown", user)
|
@battle.pbCommonAnimation("StatDown", user)
|
||||||
@battle.pbDisplay(_INTL("{1} cut its own HP and minimized its Attack!", user.pbThis))
|
@battle.pbDisplay(_INTL("{1} cut its own HP and minimized its {2}!",
|
||||||
|
user.pbThis, GameData::Stat.get(@statUp[0]).name))
|
||||||
else
|
else
|
||||||
user.stages[:ATTACK] = 6
|
user.stages[@statUp[0]] = 6
|
||||||
user.statsRaisedThisRound = true
|
user.statsRaisedThisRound = true
|
||||||
@battle.pbCommonAnimation("StatUp", user)
|
@battle.pbCommonAnimation("StatUp", user)
|
||||||
@battle.pbDisplay(_INTL("{1} cut its own HP and maximized its Attack!", user.pbThis))
|
@battle.pbDisplay(_INTL("{1} cut its own HP and maximized its {2}!",
|
||||||
|
user.pbThis, GameData::Stat.get(@statUp[0]).name))
|
||||||
end
|
end
|
||||||
user.pbItemHPHealCheck
|
user.pbItemHPHealCheck
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -99,9 +99,6 @@ class Battle::AI
|
|||||||
@target = (target) ? @battlers[target.index] : @user
|
@target = (target) ? @battlers[target.index] : @user
|
||||||
@target&.refresh_battler
|
@target&.refresh_battler
|
||||||
@battle.moldBreaker = @user.has_mold_breaker?
|
@battle.moldBreaker = @user.has_mold_breaker?
|
||||||
# Determine whether user or target is faster, and store that result so it
|
|
||||||
# doesn't need recalculating
|
|
||||||
@user_faster = @user.faster_than?(@target)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
@@ -110,7 +107,6 @@ class Battle::AI
|
|||||||
# TODO: Add skill checks in here for particular calculations?
|
# TODO: Add skill checks in here for particular calculations?
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
def pbPredictMoveFailure
|
def pbPredictMoveFailure
|
||||||
return false if !@trainer.has_skill_flag?("PredictMoveFailure")
|
|
||||||
# TODO: Something involving user.usingMultiTurnAttack? (perhaps earlier than
|
# TODO: Something involving user.usingMultiTurnAttack? (perhaps earlier than
|
||||||
# this?).
|
# this?).
|
||||||
# User is asleep and will not wake up
|
# User is asleep and will not wake up
|
||||||
@@ -152,20 +148,22 @@ class Battle::AI
|
|||||||
#=============================================================================
|
#=============================================================================
|
||||||
def pbGetMoveScore(move, target = nil)
|
def pbGetMoveScore(move, target = nil)
|
||||||
set_up_move_check(move, target)
|
set_up_move_check(move, target)
|
||||||
user_battler = @user.battler
|
|
||||||
target_battler = @target.battler
|
|
||||||
|
|
||||||
# Predict whether the move will fail
|
# Predict whether the move will fail
|
||||||
return 25 if pbPredictMoveFailure
|
if @trainer.has_skill_flag?("PredictMoveFailure")
|
||||||
|
return 25 if pbPredictMoveFailure
|
||||||
|
end
|
||||||
|
|
||||||
# Get the base score for the move
|
# Get the base score for the move
|
||||||
if @move.damagingMove?
|
score = 100
|
||||||
# Is also the predicted damage amount as a percentage of target's current HP
|
# if @move.damagingMove?
|
||||||
score = pbGetDamagingMoveBaseScore
|
# # Is also the predicted damage amount as a percentage of target's current HP
|
||||||
else # Status moves
|
# score = pbGetDamagingMoveBaseScore
|
||||||
# Depends on the move's effect
|
# else # Status moves
|
||||||
score = pbGetStatusMoveBaseScore
|
# # Depends on the move's effect
|
||||||
end
|
# score = pbGetStatusMoveBaseScore
|
||||||
|
# end
|
||||||
|
|
||||||
# Modify the score according to the move's effect
|
# Modify the score according to the move's effect
|
||||||
score = Battle::AI::Handlers.apply_move_effect_score(@move.function,
|
score = Battle::AI::Handlers.apply_move_effect_score(@move.function,
|
||||||
score, @move, @user, @target, self, @battle)
|
score, @move, @user, @target, self, @battle)
|
||||||
@@ -200,10 +198,10 @@ class Battle::AI
|
|||||||
if @trainer.high_skill? && @user.can_switch_lax?
|
if @trainer.high_skill? && @user.can_switch_lax?
|
||||||
badMoves = false
|
badMoves = false
|
||||||
if (max_score <= 25 && user_battler.turnCount > 2) ||
|
if (max_score <= 25 && user_battler.turnCount > 2) ||
|
||||||
(max_score <= 50 && user_battler.turnCount > 5)
|
(max_score <= 60 && user_battler.turnCount > 4)
|
||||||
badMoves = true if pbAIRandom(100) < 80
|
badMoves = true if pbAIRandom(100) < 80
|
||||||
end
|
end
|
||||||
if !badMoves && max_score < 50 && user_battler.turnCount >= 1
|
if !badMoves && max_score <= 60 && user_battler.turnCount >= 1
|
||||||
badMoves = choices.none? { |c| user_battler.moves[c[0]].damagingMove? }
|
badMoves = choices.none? { |c| user_battler.moves[c[0]].damagingMove? }
|
||||||
badMoves = false if badMoves && pbAIRandom(100) < 10
|
badMoves = false if badMoves && pbAIRandom(100) < 10
|
||||||
end
|
end
|
||||||
@@ -222,11 +220,7 @@ class Battle::AI
|
|||||||
if $INTERNAL
|
if $INTERNAL
|
||||||
PBDebug.log("[AI] Move choices for #{user_battler.pbThis(true)} (#{user_battler.index}):")
|
PBDebug.log("[AI] Move choices for #{user_battler.pbThis(true)} (#{user_battler.index}):")
|
||||||
choices.each_with_index do |c, i|
|
choices.each_with_index do |c, i|
|
||||||
chance = "0"
|
chance = sprintf("%5.1f", (c[3] > 0) ? 100.0 * c[3] / total_score : 0)
|
||||||
chance = sprintf("%.1f", 100.0 * c[3] / total_score) if c[3] > 0
|
|
||||||
while chance.length < 5
|
|
||||||
chance = " " + chance
|
|
||||||
end
|
|
||||||
log_msg = " * #{chance}% chance: #{user_battler.moves[c[0]].name}"
|
log_msg = " * #{chance}% chance: #{user_battler.moves[c[0]].name}"
|
||||||
log_msg += " (against target #{c[2]})" if c[2] >= 0
|
log_msg += " (against target #{c[2]})" if c[2] >= 0
|
||||||
log_msg += " = score #{c[1]}"
|
log_msg += " = score #{c[1]}"
|
||||||
@@ -31,7 +31,7 @@ class Battle::AI
|
|||||||
mod2 = Effectiveness::NORMAL_EFFECTIVE
|
mod2 = Effectiveness::NORMAL_EFFECTIVE
|
||||||
if pkmn.types.length > 1
|
if pkmn.types.length > 1
|
||||||
mod2 = Effectiveness.calculate(pkmn.types[1], target_battler.types[0], target_battler.types[1])
|
mod2 = Effectiveness.calculate(pkmn.types[1], target_battler.types[0], target_battler.types[1])
|
||||||
mod2 = mod2.to_f / Effectivenesss::NORMAL_EFFECTIVE
|
mod2 = mod2.to_f / Effectiveness::NORMAL_EFFECTIVE
|
||||||
end
|
end
|
||||||
return mod1 * mod2
|
return mod1 * mod2
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -120,14 +120,14 @@ class Battle::AI
|
|||||||
|
|
||||||
# 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 * 5
|
score += total_increment * 4
|
||||||
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 @user.hp >= @user.totalhp * 0.7
|
if @user.hp >= @user.totalhp * 0.7
|
||||||
score += 10 * total_increment
|
score += 4 * total_increment
|
||||||
else
|
else
|
||||||
score += total_increment * ((100 * @user.hp / @user.totalhp) - 50) / 2 # +10 to -25 per stage
|
score += total_increment * ((100 * @user.hp / @user.totalhp) - 50) / 4 # +5 to -12 per stage
|
||||||
end
|
end
|
||||||
|
|
||||||
# Don't prefer if user is about to faint due to EOR damage
|
# Don't prefer if user is about to faint due to EOR damage
|
||||||
@@ -234,69 +234,81 @@ class Battle::AI
|
|||||||
# Make score changes based on the raising of a specific stat.
|
# Make score changes based on the raising of a specific stat.
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
def get_user_stat_raise_score_one(score, stat, increment)
|
def get_user_stat_raise_score_one(score, stat, increment)
|
||||||
|
# Figure out how much the stat will actually change by
|
||||||
|
stage_mul = [2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8]
|
||||||
|
stage_div = [8, 7, 6, 5, 4, 3, 2, 2, 2, 2, 2, 2, 2]
|
||||||
|
if [:ACCURACY, :EVASION].include?(stat)
|
||||||
|
stage_mul = [3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9]
|
||||||
|
stage_div = [9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 3]
|
||||||
|
end
|
||||||
|
old_stage = @user.stages[stat]
|
||||||
|
new_stage = old_stage + increment
|
||||||
|
inc_mult = (stage_mul[new_stage].to_f * stage_div[old_stage]) / (stage_div[new_stage] * stage_mul[old_stage])
|
||||||
|
inc_mult -= 1
|
||||||
|
# Stat-based score changes
|
||||||
case stat
|
case stat
|
||||||
when :ATTACK
|
when :ATTACK
|
||||||
# Modify score depending on current stat stage
|
# Modify score depending on current stat stage
|
||||||
# More strongly prefer if the user has no special moves
|
# More strongly prefer if the user has no special moves
|
||||||
if @user.stages[stat] >= 3
|
if old_stage >= 3
|
||||||
score -= 20
|
score -= 20
|
||||||
else
|
else
|
||||||
has_special_moves = @user.check_for_move { |m| m.specialMove?(m.type) }
|
has_special_moves = @user.check_for_move { |m| m.specialMove?(m.type) }
|
||||||
inc = (has_special_moves) ? 5 : 10
|
inc = (has_special_moves) ? 5 : 10
|
||||||
score += inc * (3 - @user.stages[stat]) * increment # 5 to 45
|
score += inc * (3 - old_stage) * inc_mult
|
||||||
score += 5 * increment if @user.hp == @user.totalhp
|
score += 5 * inc_mult if @user.hp == @user.totalhp
|
||||||
end
|
end
|
||||||
|
|
||||||
when :DEFENSE
|
when :DEFENSE
|
||||||
# Modify score depending on current stat stage
|
# Modify score depending on current stat stage
|
||||||
if @user.stages[stat] >= 3
|
if old_stage >= 3
|
||||||
score -= 20
|
score -= 20
|
||||||
else
|
else
|
||||||
score += 5 * (3 - @user.stages[stat]) * increment # 5 to 45
|
score += 5 * (3 - old_stage) * inc_mult
|
||||||
score += 5 * increment if @user.hp == @user.totalhp
|
score += 5 * inc_mult if @user.hp == @user.totalhp
|
||||||
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 user has no physical moves
|
# More strongly prefer if the user has no physical moves
|
||||||
if @user.stages[stat] >= 3
|
if old_stage >= 3
|
||||||
score -= 20
|
score -= 20
|
||||||
else
|
else
|
||||||
has_physical_moves = @user.check_for_move { |m| m.physicalMove?(m.type) &&
|
has_physical_moves = @user.check_for_move { |m| m.physicalMove?(m.type) &&
|
||||||
m.function != "UseUserBaseDefenseInsteadOfUserBaseAttack" &&
|
m.function != "UseUserBaseDefenseInsteadOfUserBaseAttack" &&
|
||||||
m.function != "UseTargetAttackInsteadOfUserAttack" }
|
m.function != "UseTargetAttackInsteadOfUserAttack" }
|
||||||
inc = (has_physical_moves) ? 5 : 10
|
inc = (has_physical_moves) ? 5 : 10
|
||||||
score += inc * (3 - @user.stages[stat]) * increment # 5 to 45
|
score += inc * (3 - old_stage) * inc_mult
|
||||||
score += 5 * increment if @user.hp == @user.totalhp
|
score += 5 * inc_mult if @user.hp == @user.totalhp
|
||||||
end
|
end
|
||||||
|
|
||||||
when :SPECIAL_DEFENSE
|
when :SPECIAL_DEFENSE
|
||||||
# Modify score depending on current stat stage
|
# Modify score depending on current stat stage
|
||||||
if @user.stages[stat] >= 3
|
if old_stage >= 3
|
||||||
score -= 20
|
score -= 20
|
||||||
else
|
else
|
||||||
score += 5 * (3 - @user.stages[stat]) * increment # 5 to 45
|
score += 5 * (3 - old_stage) * inc_mult
|
||||||
score += 5 * increment if @user.hp == @user.totalhp
|
score += 5 * inc_mult if @user.hp == @user.totalhp
|
||||||
end
|
end
|
||||||
|
|
||||||
when :SPEED
|
when :SPEED
|
||||||
# Prefer if user is slower than a foe
|
# Prefer if user is slower than a foe
|
||||||
each_foe_battler(@user.side) do |b, i|
|
each_foe_battler(@user.side) do |b, i|
|
||||||
next if @user.faster_than?(b)
|
next if @user.faster_than?(b)
|
||||||
score += 15 * increment
|
score += 15 * inc_mult
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
# Don't prefer if any foe has Gyro Ball
|
# Don't prefer if any foe has Gyro Ball
|
||||||
each_foe_battler(@user.side) do |b, i|
|
each_foe_battler(@user.side) do |b, i|
|
||||||
next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetFasterThanUser" }
|
next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetFasterThanUser" }
|
||||||
score -= 10 * increment
|
score -= 8 * inc_mult
|
||||||
end
|
end
|
||||||
# Don't prefer if user has Speed Boost (will be gaining Speed anyway)
|
# Don't prefer if user has Speed Boost (will be gaining Speed anyway)
|
||||||
score -= 20 if @user.has_active_ability?(:SPEEDBOOST)
|
score -= 20 if @user.has_active_ability?(:SPEEDBOOST)
|
||||||
|
|
||||||
when :ACCURACY
|
when :ACCURACY
|
||||||
# Modify score depending on current stat stage
|
# Modify score depending on current stat stage
|
||||||
if @user.stages[stat] >= 3
|
if old_stage >= 3
|
||||||
score -= 20
|
score -= 20
|
||||||
else
|
else
|
||||||
min_accuracy = 100
|
min_accuracy = 100
|
||||||
@@ -304,12 +316,10 @@ class Battle::AI
|
|||||||
next if m.accuracy == 0 || m.is_a?(Battle::Move::OHKO)
|
next if m.accuracy == 0 || m.is_a?(Battle::Move::OHKO)
|
||||||
min_accuracy = m.accuracy if m.accuracy < min_accuracy
|
min_accuracy = m.accuracy if m.accuracy < min_accuracy
|
||||||
end
|
end
|
||||||
stageMul = [3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9]
|
min_accuracy *= stage_mul[old_stage] / stage_div[old_stage]
|
||||||
stageDiv = [9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 3]
|
|
||||||
min_accuracy *= stageMul[@user.stages[stat]] / stageDiv[@user.stages[stat]]
|
|
||||||
if min_accuracy < 90
|
if min_accuracy < 90
|
||||||
score += 5 * (3 - @user.stages[stat]) * increment # 5 to 45
|
score += 5 * (3 - old_stage) * inc_mult
|
||||||
score += 5 * increment if @user.hp == @user.totalhp
|
score += 5 * inc_mult if @user.hp == @user.totalhp
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -323,26 +333,26 @@ class Battle::AI
|
|||||||
score += 60 * eor_damage / b.totalhp if eor_damage > 0
|
score += 60 * eor_damage / b.totalhp if eor_damage > 0
|
||||||
end
|
end
|
||||||
# Modify score depending on current stat stage
|
# Modify score depending on current stat stage
|
||||||
if @user.stages[stat] >= 3
|
if old_stage >= 3
|
||||||
score -= 20
|
score -= 20
|
||||||
else
|
else
|
||||||
score += 5 * (3 - @user.stages[stat]) * increment # 5 to 45
|
score += 5 * (3 - old_stage) * inc_mult
|
||||||
score += 5 * increment if @user.hp == @user.totalhp
|
score += 5 * inc_mult if @user.hp == @user.totalhp
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check impact on moves of gaining stat stages
|
# Check impact on moves of gaining stat stages
|
||||||
pos_change = [@user.stages[stat] + increment, increment].min
|
pos_change = [old_stage + increment, increment].min
|
||||||
if pos_change > 0
|
if pos_change > 0
|
||||||
# Prefer if user has Stored Power
|
# Prefer if user has Stored Power
|
||||||
if @user.check_for_move { |m| m.function == "PowerHigherWithUserPositiveStatStages" }
|
if @user.check_for_move { |m| m.function == "PowerHigherWithUserPositiveStatStages" }
|
||||||
score += 10 * pos_change
|
score += 5 * pos_change
|
||||||
end
|
end
|
||||||
# Don't prefer if any foe has Punishment
|
# Don't prefer if any foe has Punishment
|
||||||
each_foe_battler(@user.side) do |b, i|
|
each_foe_battler(@user.side) do |b, i|
|
||||||
next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetPositiveStatStages" }
|
next if !b.check_for_move { |m| m.function == "PowerHigherWithTargetPositiveStatStages" }
|
||||||
score -= 10 * pos_change
|
score -= 5 * pos_change
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -543,7 +553,7 @@ class Battle::AI
|
|||||||
|
|
||||||
# TODO: Prefer if user is faster than the target.
|
# TODO: Prefer if user is faster than the target.
|
||||||
# TODO: Is 1.3x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
|
# TODO: Is 1.3x for RaiseUserAtkDefAcc1 Coil (+Atk, +Def, +acc).
|
||||||
mini_score *= 1.5 if @user_faster
|
mini_score *= 1.5 if @user.faster_than?(@target)
|
||||||
# TODO: Don't prefer if target is a higher level than the user
|
# TODO: Don't prefer if target is a higher level than the user
|
||||||
if @target.level > @user.level + 5
|
if @target.level > @user.level + 5
|
||||||
mini_score *= 0.6
|
mini_score *= 0.6
|
||||||
|
|||||||
@@ -22,10 +22,15 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack1",
|
|||||||
"RaiseUserAttack2")
|
"RaiseUserAttack2")
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack2",
|
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserAttack2IfTargetFaints",
|
||||||
"RaiseUserAttack2IfTargetFaints")
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
if move.rough_damage >= target.hp * 0.9
|
||||||
|
next ai.get_score_for_user_stat_raise(score)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
#
|
#
|
||||||
@@ -36,13 +41,13 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack2",
|
|||||||
"RaiseUserAttack3")
|
"RaiseUserAttack3")
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack2IfTargetFaints",
|
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserAttack2IfTargetFaints",
|
||||||
"RaiseUserAttack3IfTargetFaints")
|
"RaiseUserAttack3IfTargetFaints")
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveFailureCheck.add("MaxUserAttackLoseHalfOfTotalHP",
|
Battle::AI::Handlers::MoveFailureCheck.add("MaxUserAttackLoseHalfOfTotalHP",
|
||||||
proc { |move, user, target, ai, battle|
|
proc { |move, user, target, ai, battle|
|
||||||
@@ -52,20 +57,9 @@ Battle::AI::Handlers::MoveFailureCheck.add("MaxUserAttackLoseHalfOfTotalHP",
|
|||||||
)
|
)
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("MaxUserAttackLoseHalfOfTotalHP",
|
Battle::AI::Handlers::MoveEffectScore.add("MaxUserAttackLoseHalfOfTotalHP",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
score += (6 - user.stages[:ATTACK]) * 10
|
score = ai.get_score_for_user_stat_raise(score)
|
||||||
if ai.trainer.medium_skill?
|
# Don't prefer the lower the user's HP is
|
||||||
hasPhysicalAttack = false
|
score -= 80 * (1 - (@user.hp.to_f / @user.totalhp)) # 0 to -40
|
||||||
user.battler.eachMove do |m|
|
|
||||||
next if !m.physicalMove?(m.type)
|
|
||||||
hasPhysicalAttack = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if hasPhysicalAttack
|
|
||||||
score += 40
|
|
||||||
elsif ai.trainer.high_skill?
|
|
||||||
score -= 90
|
|
||||||
end
|
|
||||||
end
|
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -190,12 +184,37 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed1",
|
|||||||
"RaiseUserSpeed2")
|
"RaiseUserSpeed2")
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed2",
|
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserSpeed2",
|
||||||
"RaiseUserSpeed2LowerUserWeight")
|
"RaiseUserSpeed2LowerUserWeight")
|
||||||
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserSpeed2",
|
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserSpeed2LowerUserWeight",
|
||||||
"RaiseUserSpeed2LowerUserWeight")
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
score = ai.get_score_for_user_stat_raise(score)
|
||||||
|
if ai.trainer.medium_skill?
|
||||||
|
# TODO: Take into account weight-modifying items/abilities? This "> 1"
|
||||||
|
# line can probably ignore them, but these moves' powers will change
|
||||||
|
# because of those modifiers, and the score changes may need to be
|
||||||
|
# different accordingly.
|
||||||
|
if user.battler.pokemon.weight - user.effects[PBEffects::WeightChange] > 1
|
||||||
|
if user.check_for_move { |m| m.function == "PowerHigherWithUserHeavierThanTarget" }
|
||||||
|
score -= 10
|
||||||
|
end
|
||||||
|
ai.each_foe_battler(user.side) do |b|
|
||||||
|
if b.check_for_move { |m| m.function == "PowerHigherWithUserHeavierThanTarget" }
|
||||||
|
score -= 10
|
||||||
|
end
|
||||||
|
if b.check_for_move { |m| m.function == "PowerHigherWithTargetWeight" }
|
||||||
|
score += 10
|
||||||
|
end
|
||||||
|
# TODO: Check foes for Sky Drop and whether the user is too heavy for it
|
||||||
|
# but the weight reduction will make it susceptible.
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
#
|
#
|
||||||
@@ -246,12 +265,24 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserEvasion1",
|
|||||||
"RaiseUserEvasion2")
|
"RaiseUserEvasion2")
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserEvasion2",
|
Battle::AI::Handlers::MoveFailureCheck.copy("RaiseUserEvasion2",
|
||||||
"RaiseUserEvasion2MinimizeUser")
|
"RaiseUserEvasion2MinimizeUser")
|
||||||
Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserEvasion2",
|
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserEvasion2MinimizeUser",
|
||||||
"RaiseUserEvasion2MinimizeUser")
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
score = ai.get_score_for_user_stat_raise(score)
|
||||||
|
if ai.trainer.medium_skill? && !user.effects[PBEffects::Minimize]
|
||||||
|
ai.each_foe_battler(user.side) do |b|
|
||||||
|
# Moves that do double damage and (in Gen 6+) have perfect accuracy
|
||||||
|
if b.check_for_move { |m| m.tramplesMinimize? }
|
||||||
|
score -= (Settings::MECHANICS_GENERATION >= 6) ? 15 : 10
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
#
|
#
|
||||||
@@ -262,7 +293,7 @@ Battle::AI::Handlers::MoveEffectScore.copy("RaiseUserEvasion2",
|
|||||||
"RaiseUserEvasion3")
|
"RaiseUserEvasion3")
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserCriticalHitRate2",
|
Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserCriticalHitRate2",
|
||||||
proc { |move, user, target, ai, battle|
|
proc { |move, user, target, ai, battle|
|
||||||
@@ -271,9 +302,22 @@ Battle::AI::Handlers::MoveFailureCheck.add("RaiseUserCriticalHitRate2",
|
|||||||
)
|
)
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserCriticalHitRate2",
|
Battle::AI::Handlers::MoveEffectScore.add("RaiseUserCriticalHitRate2",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if move.statusMove? || user.effects[PBEffects::FocusEnergy] < 2
|
next score - 40 if !user.check_for_move { |m| m.damagingMove? }
|
||||||
next score + 30
|
score += 15
|
||||||
|
if ai.trainer.medium_skill?
|
||||||
|
# Other effects that raise the critical hit rate
|
||||||
|
if user.item_active?
|
||||||
|
if [:RAZORCLAW, :SCOPELENS].include?(user.item_id) ||
|
||||||
|
(user.item_id == :LUCKYPUNCH && user.battler.isSpecies?(:CHANSEY)) ||
|
||||||
|
([:LEEK, :STICK].include?(user.item_id) &&
|
||||||
|
(user.battler.isSpecies?(:FARFETCHD) || user.battler.isSpecies?(:SIRFETCHD)))
|
||||||
|
score += 10
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# Critical hits do more damage
|
||||||
|
score += 10 if user.has_active_ability?(:SNIPER)
|
||||||
end
|
end
|
||||||
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1438,44 +1482,31 @@ Battle::AI::Handlers::MoveEffectScore.add("RaiseGrassBattlersDef1",
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapAtkSpAtkStages",
|
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapAtkSpAtkStages",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if ai.trainer.medium_skill?
|
user_attack = user.stages[:ATTACK]
|
||||||
aatk = user.stages[:ATTACK]
|
user_spatk = user.stages[:SPECIAL_ATTACK]
|
||||||
aspa = user.stages[:SPECIAL_ATTACK]
|
target_attack = target.stages[:ATTACK]
|
||||||
oatk = target.stages[:ATTACK]
|
target_spatk = target.stages[:SPECIAL_ATTACK]
|
||||||
ospa = target.stages[:SPECIAL_ATTACK]
|
next score - 40 if user_attack >= target_attack && user_spatk >= target_spatk
|
||||||
if aatk >= oatk && aspa >= ospa
|
next score - 20 if user_attack + user_spatk <= target_attack + target_spatk
|
||||||
score -= 80
|
score += (target_attack - user_attack) * 10
|
||||||
else
|
score += (target_spatk - user_spatk) * 10
|
||||||
score += (oatk - aatk) * 10
|
|
||||||
score += (ospa - aspa) * 10
|
|
||||||
end
|
|
||||||
else
|
|
||||||
score -= 50
|
|
||||||
end
|
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
# TODO: Review score modifiers.
|
||||||
# TODO: Review score modifiers.
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapDefSpDefStages",
|
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapDefSpDefStages",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if ai.trainer.medium_skill?
|
user_def = user.stages[:DEFENSE]
|
||||||
adef = user.stages[:DEFENSE]
|
user_spdef = user.stages[:SPECIAL_DEFENSE]
|
||||||
aspd = user.stages[:SPECIAL_DEFENSE]
|
target_def = target.stages[:DEFENSE]
|
||||||
odef = target.stages[:DEFENSE]
|
target_spdef = target.stages[:SPECIAL_DEFENSE]
|
||||||
ospd = target.stages[:SPECIAL_DEFENSE]
|
next score - 40 if user_def >= target_def && user_spdef >= target_spdef
|
||||||
if adef >= odef && aspd >= ospd
|
next score - 20 if user_def + user_spdef <= target_def + target_spdef
|
||||||
score -= 80
|
score += (target_def - user_def) * 10
|
||||||
else
|
score += (target_spdef - user_spdef) * 10
|
||||||
score += (odef - adef) * 10
|
|
||||||
score += (ospd - aspd) * 10
|
|
||||||
end
|
|
||||||
else
|
|
||||||
score -= 50
|
|
||||||
end
|
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -1485,17 +1516,16 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapDefSpDefStages",
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapStatStages",
|
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapStatStages",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if ai.trainer.medium_skill?
|
user_stages = 0
|
||||||
userStages = 0
|
target_stages = 0
|
||||||
targetStages = 0
|
target_stage_better = false
|
||||||
GameData::Stat.each_battle do |s|
|
GameData::Stat.each_battle do |s|
|
||||||
userStages += user.stages[s.id]
|
user_stages += user.stages[s.id]
|
||||||
targetStages += target.stages[s.id]
|
target_stages += target.stages[s.id]
|
||||||
end
|
target_stage_better = true if target.stages[s.id] > user.stages[s.id]
|
||||||
score += (targetStages - userStages) * 10
|
|
||||||
else
|
|
||||||
score -= 50
|
|
||||||
end
|
end
|
||||||
|
next score - 40 if !target_stage_better
|
||||||
|
score += (target_stages - user_stages) * 10
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -1505,17 +1535,13 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapStatStages",
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserCopyTargetStatStages",
|
Battle::AI::Handlers::MoveEffectScore.add("UserCopyTargetStatStages",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if ai.trainer.medium_skill?
|
equal = true
|
||||||
equal = true
|
GameData::Stat.each_battle do |s|
|
||||||
GameData::Stat.each_battle do |s|
|
stagediff = target.stages[s.id] - user.stages[s.id]
|
||||||
stagediff = target.stages[s.id] - user.stages[s.id]
|
score += stagediff * 10
|
||||||
score += stagediff * 10
|
equal = false if stagediff != 0
|
||||||
equal = false if stagediff != 0
|
|
||||||
end
|
|
||||||
score -= 80 if equal
|
|
||||||
else
|
|
||||||
score -= 50
|
|
||||||
end
|
end
|
||||||
|
next 60 if equal # No stat changes
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -1584,19 +1610,17 @@ Battle::AI::Handlers::MoveFailureCheck.add("ResetAllBattlersStatStages",
|
|||||||
)
|
)
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("ResetAllBattlersStatStages",
|
Battle::AI::Handlers::MoveEffectScore.add("ResetAllBattlersStatStages",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if ai.trainer.medium_skill?
|
stages = 0
|
||||||
stages = 0
|
battle.allBattlers.each do |b|
|
||||||
battle.allBattlers.each do |b|
|
totalStages = 0
|
||||||
totalStages = 0
|
GameData::Stat.each_battle { |s| totalStages += b.stages[s.id] }
|
||||||
GameData::Stat.each_battle { |s| totalStages += b.stages[s.id] }
|
if b.opposes?(user.battler)
|
||||||
if b.opposes?(user.battler)
|
stages += totalStages
|
||||||
stages += totalStages
|
else
|
||||||
else
|
stages -= totalStages
|
||||||
stages -= totalStages
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
next score + stages * 10
|
|
||||||
end
|
end
|
||||||
|
next score + stages * 10
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1614,19 +1638,13 @@ Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideImmunityToStatStageLowe
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserSwapBaseAtkDef",
|
Battle::AI::Handlers::MoveEffectScore.add("UserSwapBaseAtkDef",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if ai.trainer.medium_skill?
|
aatk = user.rough_stat(:ATTACK)
|
||||||
aatk = user.rough_stat(:ATTACK)
|
adef = user.rough_stat(:DEFENSE)
|
||||||
adef = user.rough_stat(:DEFENSE)
|
next score - 40 if aatk == adef || user.effects[PBEffects::PowerTrick] # No flip-flopping
|
||||||
if aatk == adef ||
|
if adef > aatk # Prefer a higher Attack
|
||||||
user.effects[PBEffects::PowerTrick] # No flip-flopping
|
score += 20
|
||||||
score -= 90
|
|
||||||
elsif adef > aatk # Prefer a higher Attack
|
|
||||||
score += 30
|
|
||||||
else
|
|
||||||
score -= 30
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
score -= 30
|
score -= 20
|
||||||
end
|
end
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
@@ -1637,12 +1655,10 @@ Battle::AI::Handlers::MoveEffectScore.add("UserSwapBaseAtkDef",
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapBaseSpeed",
|
Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapBaseSpeed",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if ai.trainer.medium_skill?
|
if user.speed > target.speed
|
||||||
if user.speed > target.speed
|
score += 25
|
||||||
score += 50
|
else
|
||||||
else
|
score -= 25
|
||||||
score -= 70
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
@@ -1653,20 +1669,15 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetSwapBaseSpeed",
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageBaseAtkSpAtk",
|
Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageBaseAtkSpAtk",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if ai.trainer.medium_skill?
|
user_atk = user.battler.attack
|
||||||
aatk = user.rough_stat(:ATTACK)
|
user_spatk = user.battler.spatk
|
||||||
aspatk = user.rough_stat(:SPECIAL_ATTACK)
|
target_atk = target.battler.attack
|
||||||
oatk = target.rough_stat(:ATTACK)
|
target_spatk = target.battler.spatk
|
||||||
ospatk = target.rough_stat(:SPECIAL_ATTACK)
|
next score - 40 if user_atk > target_atk && user_spatk > target_spatk
|
||||||
if aatk < oatk && aspatk < ospatk
|
if user_atk + user_spatk < target_atk + target_spatk
|
||||||
score += 50
|
score += 20
|
||||||
elsif aatk + aspatk < oatk + ospatk
|
|
||||||
score += 30
|
|
||||||
else
|
|
||||||
score -= 50
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
score -= 30
|
score -= 20
|
||||||
end
|
end
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
@@ -1677,20 +1688,15 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageBaseAtkSpAtk",
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageBaseDefSpDef",
|
Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageBaseDefSpDef",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if ai.trainer.medium_skill?
|
user_def = user.rough_stat(:DEFENSE)
|
||||||
adef = user.rough_stat(:DEFENSE)
|
user_spdef = user.rough_stat(:SPECIAL_DEFENSE)
|
||||||
aspdef = user.rough_stat(:SPECIAL_DEFENSE)
|
target_def = target.rough_stat(:DEFENSE)
|
||||||
odef = target.rough_stat(:DEFENSE)
|
target_spdef = target.rough_stat(:SPECIAL_DEFENSE)
|
||||||
ospdef = target.rough_stat(:SPECIAL_DEFENSE)
|
next score - 40 if user_def > target_def && user_spdef > target_spdef
|
||||||
if adef < odef && aspdef < ospdef
|
if user_def + user_spdef < target_def + target_spdef
|
||||||
score += 50
|
score += 20
|
||||||
elsif adef + aspdef < odef + ospdef
|
|
||||||
score += 30
|
|
||||||
else
|
|
||||||
score -= 50
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
score -= 30
|
score -= 20
|
||||||
end
|
end
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
@@ -1701,12 +1707,10 @@ Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageBaseDefSpDef",
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageHP",
|
Battle::AI::Handlers::MoveEffectScore.add("UserTargetAverageHP",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if target.effects[PBEffects::Substitute] > 0
|
if user.hp >= (user.hp + target.hp) / 2
|
||||||
score -= 90
|
score -= 25
|
||||||
elsif user.hp >= (user.hp + target.hp) / 2
|
|
||||||
score -= 90
|
|
||||||
else
|
else
|
||||||
score += 40
|
score += 25
|
||||||
end
|
end
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,11 +56,25 @@ Battle::AI::Handlers::GeneralMoveScore.add(:dance_move_against_dancer,
|
|||||||
# lowered offences (Atk/Def or SpAtk/SpDef, whichever is relevant).
|
# lowered offences (Atk/Def or SpAtk/SpDef, whichever is relevant).
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
|
# Don't prefer damaging moves that will knock out the target if they are using
|
||||||
|
# Destiny Bond.
|
||||||
# TODO: Review score modifier.
|
# TODO: Review score modifier.
|
||||||
#===============================================================================
|
|
||||||
# TODO: Don't prefer damaging moves if target is Destiny Bonding.
|
|
||||||
# => Also don't prefer damaging moves if user is slower than the target, move
|
# => Also don't prefer damaging moves if user is slower than the target, move
|
||||||
# is likely to be lethal, and target has previously used Destiny Bond
|
# is likely to be lethal, and target has previously used Destiny Bond
|
||||||
|
#===============================================================================
|
||||||
|
Battle::AI::Handlers::GeneralMoveScore.add(:avoid_knocking_out_destiny_bonder,
|
||||||
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
if ai.trainer.medium_skill? && move.damagingMove? &&
|
||||||
|
target && target.effects[PBEffects::DestinyBond]
|
||||||
|
dmg = move.rough_damage
|
||||||
|
if dmg > target.hp * 1.05 # Predicted to KO the target
|
||||||
|
score -= 25
|
||||||
|
score -= 20 if battle.pbAbleNonActiveCount(user.idxOwnSide) == 0
|
||||||
|
end
|
||||||
|
next score
|
||||||
|
end
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifier.
|
# TODO: Review score modifier.
|
||||||
@@ -88,24 +102,26 @@ Battle::AI::Handlers::GeneralMoveScore.add(:dance_move_against_dancer,
|
|||||||
# an effect that's good for the user (Poison Touch/Pickpocket).
|
# an effect that's good for the user (Poison Touch/Pickpocket).
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
|
# Prefer damaging moves if the foe is down to their last Pokémon (opportunistic).
|
||||||
|
# Prefer damaging moves if the AI is down to its last Pokémon but the foe has
|
||||||
|
# more (desperate).
|
||||||
# TODO: Review score modifier.
|
# TODO: Review score modifier.
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Don't prefer a status move if user has a damaging move that will KO
|
Battle::AI::Handlers::GeneralMoveScore.add(:prefer_damaging_moves_if_last_pokemon,
|
||||||
# the target.
|
|
||||||
# => If target has previously used a move that will hurt the user by 30% of
|
|
||||||
# its current HP or more, moreso don't prefer a status move.
|
|
||||||
|
|
||||||
#===============================================================================
|
|
||||||
# Prefer damaging moves if AI has no more Pokémon or AI is less clever.
|
|
||||||
# TODO: Review score modifier.
|
|
||||||
#===============================================================================
|
|
||||||
Battle::AI::Handlers::GeneralMoveScore.add(:damaging_moves_if_last_pokemon,
|
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if ai.trainer.medium_skill? && battle.pbAbleNonActiveCount(user.idxOwnSide) == 0 &&
|
if ai.trainer.medium_skill? && move.damagingMove?
|
||||||
!(ai.trainer.high_skill? && target && battle.pbAbleNonActiveCount(target.idxOwnSide) > 0)
|
reserves = battle.pbAbleNonActiveCount(user.idxOwnSide)
|
||||||
next score * 0.9 if move.statusMove?
|
foes = battle.pbAbleNonActiveCount(user.idxOpposingSide)
|
||||||
next score * 1.1 if target && target.battler.hp <= target.battler.totalhp / 2
|
# Don't mess with scores just because a move is damaging; need to play well
|
||||||
|
next score if ai.trainer.high_skill? && foes > reserves # AI is outnumbered
|
||||||
|
# Prefer damaging moves depending on remaining Pokémon
|
||||||
|
if foes == 0 # Foe is down to their last Pokémon
|
||||||
|
score *= 1.1 # => Go for the kill
|
||||||
|
elsif reserves == 0 # AI is down to its last Pokémon, foe has reserves
|
||||||
|
score *= 1.05 # => Go out with a bang
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -256,7 +272,11 @@ Battle::AI::Handlers::GeneralMoveScore.add(:flinching_effects,
|
|||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# Adjust score based on how much damage it can deal.
|
# Adjust score based on how much damage it can deal.
|
||||||
|
# Prefer the move even more if it's predicted to do enough damage to KO the
|
||||||
|
# target.
|
||||||
# TODO: Review score modifier.
|
# TODO: Review score modifier.
|
||||||
|
# => If target has previously used a move that will hurt the user by 30% of
|
||||||
|
# its current HP or more, moreso don't prefer a status move.
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::GeneralMoveScore.add(:add_predicted_damage,
|
Battle::AI::Handlers::GeneralMoveScore.add(:add_predicted_damage,
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
|||||||
@@ -48,14 +48,14 @@ def debug_test_auto_battle(logging = false)
|
|||||||
player_trainers, ally_items, player_party, player_party_starts = debug_set_up_trainer
|
player_trainers, ally_items, player_party, player_party_starts = debug_set_up_trainer
|
||||||
# Log the combatants
|
# Log the combatants
|
||||||
echo_participant = lambda do |trainer, party, index|
|
echo_participant = lambda do |trainer, party, index|
|
||||||
trainer_txt = "Trainer #{index}: #{trainer.full_name}"
|
trainer_txt = "[Trainer #{index}] #{trainer.full_name} [skill: #{trainer.skill_level}]"
|
||||||
($INTERNAL) ? PBDebug.log_header(trainer_txt) : echoln(trainer_txt)
|
($INTERNAL) ? PBDebug.log_header(trainer_txt) : echoln(trainer_txt)
|
||||||
party.each do |pkmn|
|
party.each do |pkmn|
|
||||||
pkmn_txt = " #{pkmn.name}, Lv.#{pkmn.level}\r\n"
|
pkmn_txt = "* #{pkmn.name}, Lv.#{pkmn.level}"
|
||||||
pkmn_txt += " Ability: #{pkmn.ability&.name || "---"}\r\n"
|
pkmn_txt += " [Ability: #{pkmn.ability&.name || "---"}]"
|
||||||
pkmn_txt += " Held item: #{pkmn.item&.name || "---"}"
|
pkmn_txt += " [Item: #{pkmn.item&.name || "---"}]"
|
||||||
($INTERNAL) ? PBDebug.log(pkmn_txt) : echoln(pkmn_txt)
|
($INTERNAL) ? PBDebug.log(pkmn_txt) : echoln(pkmn_txt)
|
||||||
moves_msg = " Moves: "
|
moves_msg = " Moves: "
|
||||||
pkmn.moves.each_with_index do |move, i|
|
pkmn.moves.each_with_index do |move, i|
|
||||||
moves_msg += ", " if i > 0
|
moves_msg += ", " if i > 0
|
||||||
moves_msg += move.name
|
moves_msg += move.name
|
||||||
@@ -64,6 +64,8 @@ def debug_test_auto_battle(logging = false)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
echo_participant.call(player_trainers[0], player_party, 1)
|
echo_participant.call(player_trainers[0], player_party, 1)
|
||||||
|
PBDebug.log("")
|
||||||
|
echoln "" if !$INTERNAL
|
||||||
echo_participant.call(foe_trainers[0], foe_party, 2)
|
echo_participant.call(foe_trainers[0], foe_party, 2)
|
||||||
echoln "" if !$INTERNAL
|
echoln "" if !$INTERNAL
|
||||||
# Create the battle scene (the visual side of it)
|
# Create the battle scene (the visual side of it)
|
||||||
|
|||||||
Reference in New Issue
Block a user