Fixed Rollout being affected by Parental Bond, fixed multi-turn moves being stopped by Torment, fixed BGM not stopping when returning to the title screen, removed AI references

This commit is contained in:
Maruno17
2023-05-15 19:41:34 +01:00
parent 6ca7da0a06
commit e7e153bf11
65 changed files with 13 additions and 61094 deletions

View File

@@ -1,69 +0,0 @@
# AI skill levels:
# 0: Wild Pokémon
# 1-31: Basic trainer (young/inexperienced)
# 32-47: Some skill
# 48-99: High skill
# 100+: Best trainers (Gym Leaders, Elite Four, Champion)
# NOTE: A trainer's skill value can range from 0-255, but by default only four
# distinct skill levels exist. The skill value is typically the same as
# the trainer's base money value.
module PBTrainerAI
# Minimum skill level to be in each AI category.
def self.minimumSkill; return 1; end
def self.mediumSkill; return 32; end
def self.highSkill; return 48; end
def self.bestSkill; return 100; end
end
class PokeBattle_AI
def initialize(battle)
@battle = battle
end
def pbAIRandom(x); return rand(x); end
def pbStdDev(choices)
sum = 0
n = 0
choices.each do |c|
sum += c[1]
n += 1
end
return 0 if n<2
mean = sum.to_f/n.to_f
varianceTimesN = 0
choices.each do |c|
next if c[1]<=0
deviation = c[1].to_f-mean
varianceTimesN += deviation*deviation
end
# Using population standard deviation
# [(n-1) makes it a sample std dev, would be 0 with only 1 sample]
return Math.sqrt(varianceTimesN/n)
end
#=============================================================================
# Decide whether the opponent should Mega Evolve their Pokémon
#=============================================================================
def pbEnemyShouldMegaEvolve?(idxBattler)
battler = @battle.battlers[idxBattler]
if @battle.pbCanMegaEvolve?(idxBattler) # Simple "always should if possible"
PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will Mega Evolve")
return true
end
return false
end
#=============================================================================
# Choose an action
#=============================================================================
def pbDefaultChooseEnemyCommand(idxBattler)
return if pbEnemyShouldUseItem?(idxBattler)
return if pbEnemyShouldWithdraw?(idxBattler)
return if @battle.pbAutoFightMenu(idxBattler)
@battle.pbRegisterMegaEvolution(idxBattler) if pbEnemyShouldMegaEvolve?(idxBattler)
pbChooseMoves(idxBattler)
end
end

View File

@@ -1,182 +0,0 @@
class PokeBattle_AI
#=============================================================================
# Decide whether the opponent should use an item on the Pokémon
#=============================================================================
def pbEnemyShouldUseItem?(idxBattler)
user = @battle.battlers[idxBattler]
item, idxTarget = pbEnemyItemToUse(idxBattler)
return false if item==0
# Determine target of item (always the Pokémon choosing the action)
useType = pbGetItemData(item,ITEM_BATTLE_USE)
if useType && (useType==1 || useType==6) # Use on Pokémon
idxTarget = @battle.battlers[idxTarget].pokemonIndex # Party Pokémon
end
# Register use of item
@battle.pbRegisterItem(idxBattler,item,idxTarget)
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will use item #{PBItems.getName(item)}")
return true
end
# NOTE: The AI will only consider using an item on the Pokémon it's currently
# choosing an action for.
def pbEnemyItemToUse(idxBattler)
return 0 if !@internalBattle
items = @battle.pbGetOwnerItems(idxBattler)
return 0 if !items || items.length==0
# Determine target of item (always the Pokémon choosing the action)
idxTarget = idxBattler # Battler using the item
battler = @battle.battlers[idxTarget]
pkmn = battler.pokemon
# Item categories
hpItems = {
:POTION => 20,
:SUPERPOTION => 50,
:HYPERPOTION => 200,
:MAXPOTION => 999,
:BERRYJUICE => 20,
:SWEETHEART => 20,
:FRESHWATER => 50,
:SODAPOP => 60,
:LEMONADE => 80,
:MOOMOOMILK => 100,
:ORANBERRY => 10,
:SITRUSBERRY => battler.totalhp/4,
:ENERGYPOWDER => 50,
:ENERGYROOT => 200
}
hpItems[:RAGECANDYBAR] = 20 if !NEWEST_BATTLE_MECHANICS
fullRestoreItems = [
:FULLRESTORE
]
oneStatusItems = [ # Preferred over items that heal all status problems
:AWAKENING,:CHESTOBERRY,:BLUEFLUTE,
:ANTIDOTE,:PECHABERRY,
:BURNHEAL,:RAWSTBERRY,
:PARALYZEHEAL,:PARLYZHEAL,:CHERIBERRY,
:ICEHEAL,:ASPEARBERRY
]
allStatusItems = [
:FULLHEAL,:LAVACOOKIE,:OLDGATEAU,:CASTELIACONE,:LUMIOSEGALETTE,
:SHALOURSABLE,:BIGMALASADA,:LUMBERRY,:HEALPOWDER
]
allStatusItems.push(:RAGECANDYBAR) if NEWEST_BATTLE_MECHANICS
xItems = {
:XATTACK => [PBStats::ATTACK,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XATTACK2 => [PBStats::ATTACK,2],
:XATTACK3 => [PBStats::ATTACK,3],
:XATTACK6 => [PBStats::ATTACK,6],
:XDEFENSE => [PBStats::DEFENSE,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XDEFENSE2 => [PBStats::DEFENSE,2],
:XDEFENSE3 => [PBStats::DEFENSE,3],
:XDEFENSE6 => [PBStats::DEFENSE,6],
:XDEFEND => [PBStats::DEFENSE,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XDEFEND2 => [PBStats::DEFENSE,2],
:XDEFEND3 => [PBStats::DEFENSE,3],
:XDEFEND6 => [PBStats::DEFENSE,6],
:XSPATK => [PBStats::SPATK,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XSPATK2 => [PBStats::SPATK,2],
:XSPATK3 => [PBStats::SPATK,3],
:XSPATK6 => [PBStats::SPATK,6],
:XSPECIAL => [PBStats::SPATK,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XSPECIAL2 => [PBStats::SPATK,2],
:XSPECIAL3 => [PBStats::SPATK,3],
:XSPECIAL6 => [PBStats::SPATK,6],
:XSPDEF => [PBStats::SPDEF,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XSPDEF2 => [PBStats::SPDEF,2],
:XSPDEF3 => [PBStats::SPDEF,3],
:XSPDEF6 => [PBStats::SPDEF,6],
:XSPEED => [PBStats::SPEED,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XSPEED2 => [PBStats::SPEED,2],
:XSPEED3 => [PBStats::SPEED,3],
:XSPEED6 => [PBStats::SPEED,6],
:XACCURACY => [PBStats::ACCURACY,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XACCURACY2 => [PBStats::ACCURACY,2],
:XACCURACY3 => [PBStats::ACCURACY,3],
:XACCURACY6 => [PBStats::ACCURACY,6]
}
losthp = battler.totalhp-battler.hp
preferFullRestore = (battler.hp<=battler.totalhp*2/3 &&
(battler.status!=PBStatuses::NONE || battler.effects[PBEffects::Confusion]>0))
# Find all usable items
usableHPItems = []
usableStatusItems = []
usableXItems = []
items.each do |i|
next if !i || i==0
next if !@battle.pbCanUseItemOnPokemon?(i,pkmn,battler,@battle.scene,false)
next if !ItemHandlers.triggerCanUseInBattle(i,pkmn,battler,nil,
false,self,@battle.scene,false)
checkedItem = false
# Log HP healing items
if losthp>0
hpItems.each do |item, power|
next if !isConst?(i,PBItems,item)
checkedItem = true
usableHPItems.push([i,5,power])
end
next if checkedItem
end
# Log Full Restores (HP healer and status curer)
if losthp>0 || battler.status!=PBStatuses::NONE
fullRestoreItems.each do |item|
next if !isConst?(i,PBItems,item)
checkedItem = true
usableHPItems.push([i,(preferFullRestore) ? 3 : 7,999])
usableStatusItems.push([i,(preferFullRestore) ? 3 : 9])
end
next if checkedItem
end
# Log single status-curing items
if battler.status!=PBStatuses::NONE
oneStatusItems.each do |item|
next if !isConst?(i,PBItems,item)
checkedItem = true
usableStatusItems.push([i,5])
end
next if checkedItem
# Log Full Heal-type items
allStatusItems.each do |item|
next if !isConst?(i,PBItems,item)
checkedItem = true
usableStatusItems.push([i,7])
end
next if checkedItem
end
# Log stat-raising items
xItems.each do |item, data|
next if !isConst?(i,PBItems,item)
checkedItem = true
usableXItems.push([i,battler.stages[data[0]],data[1]])
end
next if checkedItem
end
# Prioritise using a HP restoration item
if usableHPItems.length>0 && (battler.hp<=battler.totalhp/4 ||
(battler.hp<=battler.totalhp/2 && pbAIRandom(100)<30))
usableHPItems.sort! { |a,b| (a[1]==b[1]) ? a[2]<=>b[2] : a[1]<=>b[1] }
prevItem = nil
usableHPItems.each do |i|
return i[0],idxTarget if i[2]>=losthp
prevItem = i
end
return prevItem[0],idxTarget
end
# Next prioritise using a status-curing item
if usableStatusItems.length>0 && pbAIRandom(100)<40
usableStatusItems.sort! { |a,b| a[1]<=>b[1] }
return usableStatusItems[0][0],idxTarget
end
# Next try using an X item
if usableXItems.length>0 && pbAIRandom(100)<30
usableXItems.sort! { |a,b| (a[1]==b[1]) ? a[2]<=>b[2] : a[1]<=>b[1] }
prevItem = nil
usableXItems.each do |i|
break if prevItem && i[1]>prevItem[1]
return i[0],idxTarget if i[1]+i[2]>=6
prevItem = i
end
return prevItem[0],idxTarget
end
return 0
end
end

View File

@@ -1,182 +0,0 @@
class PokeBattle_AI
#=============================================================================
# Decide whether the opponent should switch Pokémon
#=============================================================================
def pbEnemyShouldWithdraw?(idxBattler)
return pbEnemyShouldWithdrawEx?(idxBattler,false)
end
def pbEnemyShouldWithdrawEx?(idxBattler,forceSwitch)
return false if @battle.wildBattle?
shouldSwitch = forceSwitch
batonPass = -1
moveType = -1
skill = @battle.pbGetOwnerFromBattlerIndex(idxBattler).skill || 0
battler = @battle.battlers[idxBattler]
# If Pokémon is within 6 levels of the foe, and foe's last move was
# super-effective and powerful
if !shouldSwitch && battler.turnCount>0 && skill>=PBTrainerAI.highSkill
target = battler.pbDirectOpposing(true)
if !target.fainted? && target.lastMoveUsed>0 &&
(target.level-battler.level).abs<=6
moveData = pbGetMoveData(target.lastMoveUsed)
moveType = moveData[MOVE_TYPE]
typeMod = pbCalcTypeMod(moveType,target,battler)
if PBTypes.superEffective?(typeMod) && moveData[MOVE_BASE_DAMAGE]>50
switchChance = (moveData[MOVE_BASE_DAMAGE]>70) ? 30 : 20
shouldSwitch = (pbAIRandom(100)<switchChance)
end
end
end
# Pokémon can't do anything (must have been in battle for at least 5 rounds)
if !@battle.pbCanChooseAnyMove?(idxBattler) &&
battler.turnCount && battler.turnCount>=5
shouldSwitch = true
end
# Pokémon is Perish Songed and has Baton Pass
if skill>=PBTrainerAI.highSkill && battler.effects[PBEffects::PerishSong]==1
battler.eachMoveWithIndex do |m,i|
next if m.function!="0ED" # Baton Pass
next if !@battle.pbCanChooseMove?(idxBattler,i,false)
batonPass = i
break
end
end
# Pokémon will faint because of bad poisoning at the end of this round, but
# would survive at least one more round if it were regular poisoning instead
if battler.status==PBStatuses::POISON && battler.statusCount>0 &&
skill>=PBTrainerAI.highSkill
toxicHP = battler.totalhp/16
nextToxicHP = toxicHP*(battler.effects[PBEffects::Toxic]+1)
if battler.hp<=nextToxicHP && battler.hp>toxicHP*2
shouldSwitch = true if pbAIRandom(100)<80
end
end
# Pokémon is Encored into an unfavourable move
if battler.effects[PBEffects::Encore]>0 && skill>=PBTrainerAI.mediumSkill
idxEncoredMove = battler.pbEncoredMoveIndex
if idxEncoredMove>=0
scoreSum = 0
scoreCount = 0
battler.eachOpposing do |b|
scoreSum += pbGetMoveScore(battler.moves[idxEncoredMove],battler,b,skill)
scoreCount += 1
end
if scoreCount>0 && scoreSum/scoreCount<=20
shouldSwitch = true if pbAIRandom(100)<80
end
end
end
# If there is a single foe and it is resting after Hyper Beam or is
# Truanting (i.e. free turn)
if @battle.pbSideSize(battler.index+1)==1 &&
!battler.pbDirectOpposing.fainted? && skill>=PBTrainerAI.highSkill
opp = battler.pbDirectOpposing
if opp.effects[PBEffects::HyperBeam]>0 ||
(opp.hasActiveAbility?(:TRUANT) && opp.effects[PBEffects::Truant])
shouldSwitch = false if pbAIRandom(100)<80
end
end
# Sudden Death rule - I'm not sure what this means
if @battle.rules["suddendeath"] && battler.turnCount>0
if battler.hp<=battler.totalhp/4 && pbAIRandom(100)<30
shouldSwitch = true
elsif battler.hp<=battler.totalhp/2 && pbAIRandom(100)<80
shouldSwitch = true
end
end
# Pokémon is about to faint because of Perish Song
if battler.effects[PBEffects::PerishSong]==1
shouldSwitch = true
end
if shouldSwitch
list = []
@battle.pbParty(idxBattler).each_with_index do |pkmn,i|
next if !@battle.pbCanSwitch?(idxBattler,i)
# If perish count is 1, it may be worth it to switch
# even with Spikes, since Perish Song's effect will end
if battler.effects[PBEffects::PerishSong]!=1
# Will contain effects that recommend against switching
spikes = battler.pbOwnSide.effects[PBEffects::Spikes]
# Don't switch to this if too little HP
if spikes>0
spikesDmg = [8,6,4][spikes-1]
if pkmn.hp<=pkmn.totalhp/spikesDmg
next if !pkmn.hasType?(:FLYING) && !pkmn.hasActiveAbility?(:LEVITATE)
end
end
end
# moveType is the type of the target's last used move
if moveType>=0 && PBTypes.ineffective?(pbCalcTypeMod(moveType,battler,battler))
weight = 65
typeMod = pbCalcTypeModPokemon(pkmn,battler.pbDirectOpposing(true))
if PBTypes.superEffective?(typeMod.to_f/PBTypeEffectivenesss::NORMAL_EFFECTIVE)
# Greater weight if new Pokemon's type is effective against target
weight = 85
end
list.unshift(i) if pbAIRandom(100)<weight # Put this Pokemon first
elsif moveType>=0 && PBTypes.resistant?(pbCalcTypeMod(moveType,battler,battler))
weight = 40
typeMod = pbCalcTypeModPokemon(pkmn,battler.pbDirectOpposing(true))
if PBTypes.superEffective?(typeMod.to_f/PBTypeEffectivenesss::NORMAL_EFFECTIVE)
# Greater weight if new Pokemon's type is effective against target
weight = 60
end
list.unshift(i) if pbAIRandom(100)<weight # Put this Pokemon first
else
list.push(i) # put this Pokemon last
end
end
if list.length>0
if batonPass>=0 && @battle.pbRegisterMove(idxBattler,batonPass,false)
PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will use Baton Pass to avoid Perish Song")
return true
end
if @battle.pbRegisterSwitch(idxBattler,list[0])
PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will switch with " +
"#{@battle.pbParty(idxBattler)[list[0]].name}")
return
end
end
end
return false
end
#=============================================================================
# Choose a replacement Pokémon
#=============================================================================
def pbDefaultChooseNewEnemy(idxBattler,party)
enemies = []
party.each_with_index do |_p,i|
enemies.push(i) if @battle.pbCanSwitchLax?(idxBattler,i)
end
return -1 if enemies.length==0
return pbChooseBestNewEnemy(idxBattler,party,enemies)
end
def pbChooseBestNewEnemy(idxBattler,party,enemies)
return -1 if !enemies || enemies.length==0
best = -1
bestSum = 0
movesData = pbLoadMovesData
enemies.each do |i|
pkmn = party[i]
sum = 0
pkmn.moves.each do |m|
next if m.id==0
moveData = movesData[m.id]
next if moveData[MOVE_BASE_DAMAGE]==0
@battle.battlers[idxBattler].eachOpposing do |b|
bTypes = b.pbTypes(true)
sum += PBTypes.getCombinedEffectiveness(moveData[MOVE_TYPE],
bTypes[0],bTypes[1],bTypes[2])
end
end
if best==-1 || sum>bestSum
best = i
bestSum = sum
end
end
return best
end
end

View File

@@ -1,286 +0,0 @@
class PokeBattle_AI
#=============================================================================
# Main move-choosing method (moves with higher scores are more likely to be
# chosen)
#=============================================================================
def pbChooseMoves(idxBattler)
user = @battle.battlers[idxBattler]
wildBattler = (@battle.wildBattle? && @battle.opposes?(idxBattler))
skill = 0
if !wildBattler
skill = @battle.pbGetOwnerFromBattlerIndex(user.index).skill || 0
end
# Get scores and targets for each move
# NOTE: A move is only added to the choices array if it has a non-zero
# score.
choices = []
user.eachMoveWithIndex do |_m,i|
next if !@battle.pbCanChooseMove?(idxBattler,i,false)
if wildBattler
pbRegisterMoveWild(user,i,choices)
else
pbRegisterMoveTrainer(user,i,choices,skill)
end
end
# Figure out useful information about the choices
totalScore = 0
maxScore = 0
choices.each do |c|
totalScore += c[1]
maxScore = c[1] if maxScore<c[1]
end
# Log the available choices
if $INTERNAL
logMsg = "[AI] Move choices for #{user.pbThis(true)} (#{user.index}): "
choices.each_with_index do |c,i|
logMsg += "#{user.moves[c[0]].name}=#{c[1]}"
logMsg += " (target #{c[2]})" if c[2]>=0
logMsg += ", " if i<choices.length-1
end
PBDebug.log(logMsg)
end
# Find any preferred moves and just choose from them
if !wildBattler && skill>=PBTrainerAI.highSkill && maxScore>100
stDev = pbStdDev(choices)
if stDev>=40 && pbAIRandom(100)<90
preferredMoves = []
choices.each do |c|
next if c[1]<200 && c[1]<maxScore*0.8
preferredMoves.push(c)
preferredMoves.push(c) if c[1]==maxScore # Doubly prefer the best move
end
if preferredMoves.length>0
m = preferredMoves[pbAIRandom(preferredMoves.length)]
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) prefers #{user.moves[m[0]].name}")
@battle.pbRegisterMove(idxBattler,m[0],false)
@battle.pbRegisterTarget(idxBattler,m[2]) if m[2]>=0
return
end
end
end
# Decide whether all choices are bad, and if so, try switching instead
if !wildBattler && skill>=PBTrainerAI.highSkill
badMoves = false
if (maxScore<=20 && user.turnCount>2) ||
(maxScore<=40 && user.turnCount>5)
badMoves = true if pbAIRandom(100)<80
end
if !badMoves && totalScore<100 && user.turnCount>1
badMoves = true
choices.each do |c|
next if !user.moves[c[0]].damagingMove?
badMoves = false
break
end
badMoves = false if badMoves && pbAIRandom(100)<10
end
if badMoves && pbEnemyShouldWithdrawEx?(idxBattler,true)
if $INTERNAL
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will switch due to terrible moves")
end
return
end
end
# Randomly choose a move to use
if choices.length==0
# If there are no calculated choices, use Struggle (or an Encored move)
@battle.pbAutoChooseMove(idxBattler)
else
# Randomly choose a move from the choices and register it
randNum = pbAIRandom(totalScore)
choices.each do |c|
randNum -= c[1]
next if randNum>=0
@battle.pbRegisterMove(idxBattler,c[0],false)
@battle.pbRegisterTarget(idxBattler,c[2]) if c[2]>=0
break
end
end
# Log the result
if @battle.choices[idxBattler][2]
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will use #{@battle.choices[user.index][2].name}")
end
end
#=============================================================================
# Get scores for the given move against each possible target
#=============================================================================
# Wild Pokémon choose their moves randomly.
def pbRegisterMoveWild(_user,idxMove,choices)
choices.push([idxMove,100,-1]) # Move index, score, target
end
# Trainer Pokémon calculate how much they want to use each of their moves.
def pbRegisterMoveTrainer(user,idxMove,choices,skill)
move = user.moves[idxMove]
targetType = move.pbTarget(user)
if PBTargets.multipleTargets?(targetType)
# If move affects multiple battlers and you don't choose a particular one
totalScore = 0
@battle.eachBattler do |b|
next if !@battle.pbMoveCanTarget?(user.index,b.index,targetType)
score = pbGetMoveScore(move,user,b,skill)
totalScore += ((user.opposes?(b)) ? score : -score)
end
choices.push([idxMove,totalScore,-1]) if totalScore>0
elsif PBTargets.noTargets?(targetType)
# If move has no targets, affects the user, a side or the whole field
score = pbGetMoveScore(move,user,user,skill)
choices.push([idxMove,score,-1]) if score>0
else
# If move affects one battler and you have to choose which one
scoresAndTargets = []
@battle.eachBattler do |b|
next if !@battle.pbMoveCanTarget?(user.index,b.index,targetType)
next if PBTargets.canChooseFoeTarget?(targetType) && !user.opposes?(b)
score = pbGetMoveScore(move,user,b,skill)
scoresAndTargets.push([score,b.index]) if score>0
end
if scoresAndTargets.length>0
# Get the one best target for the move
scoresAndTargets.sort! { |a,b| b[0]<=>a[0] }
choices.push([idxMove,scoresAndTargets[0][0],scoresAndTargets[0][1]])
end
end
end
#=============================================================================
# Get a score for the given move being used against the given target
#=============================================================================
def pbGetMoveScore(move,user,target,skill=100)
skill = PBTrainerAI.minimumSkill if skill<PBTrainerAI.minimumSkill
score = 100
score = pbGetMoveScoreFunctionCode(score,move,user,target,skill)
# A score of 0 here means it absolutely should not be used
return 0 if score<=0
if skill>=PBTrainerAI.mediumSkill
# Prefer damaging moves if AI has no more Pokémon or AI is less clever
if @battle.pbAbleNonActiveCount(user.idxOwnSide)==0
if !(skill>=PBTrainerAI.highSkill && @battle.pbAbleNonActiveCount(target.idxOwnSide)>0)
if move.statusMove?
score /= 1.5
elsif target.hp<=target.totalhp/2
score *= 1.5
end
end
end
# Don't prefer attacking the target if they'd be semi-invulnerable
if skill>=PBTrainerAI.highSkill && move.accuracy>0 &&
(target.semiInvulnerable? || target.effects[PBEffects::SkyDrop]>=0)
miss = true
miss = false if user.hasActiveAbility?(:NOGUARD) || target.hasActiveAbility?(:NOGUARD)
if miss && pbRoughStat(user,PBStats::SPEED,skill)>pbRoughStat(target,PBStats::SPEED,skill)
# Knows what can get past semi-invulnerability
if target.effects[PBEffects::SkyDrop]>=0
miss = false if move.hitsFlyingTargets?
else
if target.inTwoTurnAttack?("0C9","0CC","0CE") # Fly, Bounce, Sky Drop
miss = false if move.hitsFlyingTargets?
elsif target.inTwoTurnAttack?("0CA") # Dig
miss = false if move.hitsDiggingTargets?
elsif target.inTwoTurnAttack?("0CB") # Dive
miss = false if move.hitsDivingTargets?
end
end
end
score -= 80 if miss
end
# Pick a good move for the Choice items
if user.hasActiveItem?([:CHOICEBAND,:CHOICESPECS,:CHOICESCARF])
if move.baseDamage>=60; score += 60
elsif move.damagingMove?; score += 30
elsif move.function=="0F2"; score += 70 # Trick
else; score -= 60
end
end
# If user is asleep, prefer moves that are usable while asleep
if user.status==PBStatuses::SLEEP && !move.usableWhenAsleep?
user.eachMove do |m|
next unless m.usableWhenAsleep?
score -= 60
break
end
end
# If user is frozen, prefer a move that can thaw the user
if user.status==PBStatuses::FROZEN
if move.thawsUser?
score += 40
else
user.eachMove do |m|
next unless m.thawsUser?
score -= 60
break
end
end
end
# If target is frozen, don't prefer moves that could thaw them
if target.status==PBStatuses::FROZEN
user.eachMove do |m|
next if m.thawsUser?
score -= 60
break
end
end
end
# Adjust score based on how much damage it can deal
if move.damagingMove?
score = pbGetMoveScoreDamage(score,move,user,target,skill)
else # Status moves
# Don't prefer attacks which don't deal damage
score -= 10
# Account for accuracy of move
accuracy = pbRoughAccuracy(move,user,target,skill)
score *= accuracy/100.0
score = 0 if score<=10 && skill>=PBTrainerAI.highSkill
end
score = score.to_i
score = 0 if score<0
return score
end
#=============================================================================
# Add to a move's score based on how much damage it will deal (as a percentage
# of the target's current HP)
#=============================================================================
def pbGetMoveScoreDamage(score,move,user,target,skill)
# Don't prefer moves that are ineffective because of abilities or effects
return 0 if score<=0 || pbCheckMoveImmunity(score,move,user,target,skill)
# Calculate how much damage the move will do (roughly)
baseDmg = pbMoveBaseDamage(move,user,target,skill)
realDamage = pbRoughDamage(move,user,target,skill,baseDmg)
# Account for accuracy of move
accuracy = pbRoughAccuracy(move,user,target,skill)
realDamage *= accuracy/100.0
# Two-turn attacks waste 2 turns to deal one lot of damage
if move.chargingTurnMove? || move.function=="0C2" # Hyper Beam
realDamage *= 2/3 # Not halved because semi-invulnerable during use or hits first turn
end
# Prefer flinching external effects (note that move effects which cause
# flinching are dealt with in the function code part of score calculation)
if skill>=PBTrainerAI.mediumSkill
if !target.hasActiveAbility?(:INNERFOCUS) &&
!target.hasActiveAbility?(:SHIELDDUST) &&
target.effects[PBEffects::Substitute]==0
canFlinch = false
if move.canKingsRock? && user.hasActiveItem?([:KINGSROCK,:RAZORFANG])
canFlinch = true
end
if user.hasActiveAbility?(:STENCH) && !move.flinchingMove?
canFlinch = true
end
realDamage *= 1.3 if canFlinch
end
end
# Convert damage to percentage of target's remaining HP
damagePercentage = realDamage*100.0/target.hp
# Don't prefer weak attacks
# damagePercentage /= 2 if damagePercentage<20
# Prefer damaging attack if level difference is significantly high
damagePercentage *= 1.2 if user.level-10>target.level
# Adjust score
damagePercentage = 120 if damagePercentage>120 # Treat all lethal moves the same
damagePercentage += 40 if damagePercentage>100 # Prefer moves likely to be lethal
score += damagePercentage.to_i
return score
end
end

View File

@@ -1,838 +0,0 @@
class PokeBattle_AI
#=============================================================================
# Get a score for the given move based on its effect
#=============================================================================
def pbGetMoveScoreFunctionCode(score,move,user,target,skill=100)
case move.function
#---------------------------------------------------------------------------
when "000" # No extra effect
#---------------------------------------------------------------------------
when "001"
score -= 95
score = 0 if skill>=PBTrainerAI.highSkill
#---------------------------------------------------------------------------
when "002" # Struggle
#---------------------------------------------------------------------------
when "003"
if target.pbCanSleep?(user,false)
score += 30
if skill>=PBTrainerAI.mediumSkill
score -= 30 if target.effects[PBEffects::Yawn]>0
end
if skill>=PBTrainerAI.highSkill
score -= 30 if target.hasActiveAbility?(:MARVELSCALE)
end
if skill>=PBTrainerAI.bestSkill
if target.pbHasMoveFunction?("011","0B4") # Snore, Sleep Talk
score -= 50
end
end
else
if skill>=PBTrainerAI.mediumSkill
score -= 90 if move.statusMove?
end
end
#---------------------------------------------------------------------------
when "004"
if target.effects[PBEffects::Yawn]>0 || !target.pbCanSleep?(user,false)
score -= 90 if skill>=PBTrainerAI.mediumSkill
else
score += 30
if skill>=PBTrainerAI.highSkill
score -= 30 if target.hasActiveAbility?(:MARVELSCALE)
end
if skill>=PBTrainerAI.bestSkill
if target.pbHasMoveFunction?("011","0B4") # Snore, Sleep Talk
score -= 50
end
end
end
#---------------------------------------------------------------------------
when "005", "006", "0BE"
if target.pbCanPoison?(user,false)
score += 30
if skill>=PBTrainerAI.mediumSkill
score += 30 if target.hp<=target.totalhp/4
score += 50 if target.hp<=target.totalhp/8
score -= 40 if target.effects[PBEffects::Yawn]>0
end
if skill>=PBTrainerAI.highSkill
score += 10 if pbRoughStat(target,PBStats::DEFENSE,skill)>100
score += 10 if pbRoughStat(target,PBStats::SPDEF,skill)>100
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:TOXICBOOST])
end
else
if skill>=PBTrainerAI.mediumSkill
score -= 90 if move.statusMove?
end
end
#---------------------------------------------------------------------------
when "007", "008", "009", "0C5"
if target.pbCanParalyze?(user,false) &&
!(skill>=PBTrainerAI.mediumSkill &&
isConst?(move.id,PBMoves,:THUNDERWAVE) &&
PBTypes.ineffective?(pbCalcTypeMod(move.type,user,target)))
score += 30
if skill>=PBTrainerAI.mediumSkill
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
if aspeed<ospeed
score += 30
elsif aspeed>ospeed
score -= 40
end
end
if skill>=PBTrainerAI.highSkill
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET])
end
else
if skill>=PBTrainerAI.mediumSkill
score -= 90 if move.statusMove?
end
end
#---------------------------------------------------------------------------
when "00A", "00B", "0C6"
if target.pbCanBurn?(user,false)
score += 30
if skill>=PBTrainerAI.highSkill
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET,:FLAREBOOST])
end
else
if skill>=PBTrainerAI.mediumSkill
score -= 90 if move.statusMove?
end
end
#---------------------------------------------------------------------------
when "00C", "00D", "00E"
if target.pbCanFreeze?(user,false)
score += 30
if skill>=PBTrainerAI.highSkill
score -= 20 if target.hasActiveAbility?(:MARVELSCALE)
end
else
if skill>=PBTrainerAI.mediumSkill
score -= 90 if move.statusMove?
end
end
#---------------------------------------------------------------------------
when "00F"
score += 30
if skill>=PBTrainerAI.highSkill
score += 30 if !target.hasActiveAbility?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute]==0
end
#---------------------------------------------------------------------------
when "010"
if skill>=PBTrainerAI.highSkill
score += 30 if !target.hasActiveAbility?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute]==0
end
score += 30 if target.effects[PBEffects::Minimize]
#---------------------------------------------------------------------------
when "011"
if user.asleep?
score += 100 # Because it can only be used while asleep
if skill>=PBTrainerAI.highSkill
score += 30 if !target.hasActiveAbility?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute]==0
end
else
score -= 90 # Because it will fail here
score = 0 if skill>=PBTrainerAI.bestSkill
end
#---------------------------------------------------------------------------
when "012"
if user.turnCount==0
if skill>=PBTrainerAI.highSkill
score += 30 if !target.hasActiveAbility?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute]==0
end
else
score -= 90 # Because it will fail here
score = 0 if skill>=PBTrainerAI.bestSkill
end
#---------------------------------------------------------------------------
when "013", "014", "015"
if target.pbCanConfuse?(user,false)
score += 30
else
if skill>=PBTrainerAI.mediumSkill
score -= 90 if move.statusMove?
end
end
#---------------------------------------------------------------------------
when "016"
canattract = true
agender = user.gender
ogender = target.gender
if agender==2 || ogender==2 || agender==ogender
score -= 90; canattract = false
elsif target.effects[PBEffects::Attract]>=0
score -= 80; canattract = false
elsif skill>=PBTrainerAI.bestSkill && target.hasActiveAbility?(:OBLIVIOUS)
score -= 80; canattract = false
end
if skill>=PBTrainerAI.highSkill
if canattract && target.hasActiveItem?(:DESTINYKNOT) &&
user.pbCanAttract?(target,false)
score -= 30
end
end
#---------------------------------------------------------------------------
when "017"
score += 30 if target.status==PBStatuses::NONE
#---------------------------------------------------------------------------
when "018"
case user.status
when PBStatuses::POISON
score += 40
if skill>=PBTrainerAI.mediumSkill
if user.hp<user.totalhp/8
score += 60
elsif skill>=PBTrainerAI.highSkill &&
user.hp<(user.effects[PBEffects::Toxic]+1)*user.totalhp/16
score += 60
end
end
when PBStatuses::BURN, PBStatuses::PARALYSIS
score += 40
else
score -= 90
end
#---------------------------------------------------------------------------
when "019"
statuses = 0
@battle.pbParty(user.index).each do |pkmn|
statuses += 1 if pkmn && pkmn.status!=PBStatuses::NONE
end
if statuses==0
score -= 80
else
score += 20*statuses
end
#---------------------------------------------------------------------------
when "01A"
if user.pbOwnSide.effects[PBEffects::Safeguard]>0
score -= 80
elsif user.status!=0
score -= 40
else
score += 30
end
#---------------------------------------------------------------------------
when "01B"
if user.status==PBStatuses::NONE
score -= 90
else
score += 40
end
#---------------------------------------------------------------------------
when "01C"
if move.statusMove?
if user.statStageAtMax?(PBStats::ATTACK)
score -= 90
else
score -= user.stages[PBStats::ATTACK]*20
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
user.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
else
score += 20 if user.stages[PBStats::ATTACK]<0
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
user.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
score += 20 if hasPhysicalAttack
end
end
#---------------------------------------------------------------------------
when "01D", "01E", "0C8"
if move.statusMove?
if user.statStageAtMax?(PBStats::DEFENSE)
score -= 90
else
score -= user.stages[PBStats::DEFENSE]*20
end
else
score += 20 if user.stages[PBStats::DEFENSE]<0
end
#---------------------------------------------------------------------------
when "01F"
if move.statusMove?
if user.statStageAtMax?(PBStats::SPEED)
score -= 90
else
score -= user.stages[PBStats::SPEED]*10
if skill>=PBTrainerAI.highSkill
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
score += 30 if aspeed<ospeed && aspeed*2>ospeed
end
end
else
score += 20 if user.stages[PBStats::SPEED]<0
end
#---------------------------------------------------------------------------
when "020"
if move.statusMove?
if user.statStageAtMax?(PBStats::SPATK)
score -= 90
else
score -= user.stages[PBStats::SPATK]*20
if skill>=PBTrainerAI.mediumSkill
hasSpecicalAttack = false
user.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
else
score += 20 if user.stages[PBStats::SPATK]<0
if skill>=PBTrainerAI.mediumSkill
hasSpecicalAttack = false
user.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
score += 20 if hasSpecicalAttack
end
end
#---------------------------------------------------------------------------
when "021"
foundMove = false
user.eachMove do |m|
next if !isConst?(m.type,PBTypes,:ELECTRIC) || !m.damagingMove?
foundMove = true
break
end
score += 20 if foundMove
if move.statusMove?
if user.statStageAtMax?(PBStats::SPDEF)
score -= 90
else
score -= user.stages[PBStats::SPDEF]*20
end
else
score += 20 if user.stages[PBStats::SPDEF]<0
end
#---------------------------------------------------------------------------
when "022"
if move.statusMove?
if user.statStageAtMax?(PBStats::EVASION)
score -= 90
else
score -= user.stages[PBStats::EVASION]*10
end
else
score += 20 if user.stages[PBStats::EVASION]<0
end
#---------------------------------------------------------------------------
when "023"
if move.statusMove?
if user.effects[PBEffects::FocusEnergy]>=2
score -= 80
else
score += 30
end
else
score += 30 if user.effects[PBEffects::FocusEnergy]<2
end
#---------------------------------------------------------------------------
when "024"
if user.statStageAtMax?(PBStats::ATTACK) &&
user.statStageAtMax?(PBStats::DEFENSE)
score -= 90
else
score -= user.stages[PBStats::ATTACK]*10
score -= user.stages[PBStats::DEFENSE]*10
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
user.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
#---------------------------------------------------------------------------
when "025"
if user.statStageAtMax?(PBStats::ATTACK) &&
user.statStageAtMax?(PBStats::DEFENSE) &&
user.statStageAtMax?(PBStats::ACCURACY)
score -= 90
else
score -= user.stages[PBStats::ATTACK]*10
score -= user.stages[PBStats::DEFENSE]*10
score -= user.stages[PBStats::ACCURACY]*10
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
user.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
#---------------------------------------------------------------------------
when "026"
score += 40 if user.turnCount==0 # Dragon Dance tends to be popular
if user.statStageAtMax?(PBStats::ATTACK) &&
user.statStageAtMax?(PBStats::SPEED)
score -= 90
else
score -= user.stages[PBStats::ATTACK]*10
score -= user.stages[PBStats::SPEED]*10
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
user.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
if skill>=PBTrainerAI.highSkill
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
score += 20 if aspeed<ospeed && aspeed*2>ospeed
end
end
#---------------------------------------------------------------------------
when "027", "028"
if user.statStageAtMax?(PBStats::ATTACK) &&
user.statStageAtMax?(PBStats::SPATK)
score -= 90
else
score -= user.stages[PBStats::ATTACK]*10
score -= user.stages[PBStats::SPATK]*10
if skill>=PBTrainerAI.mediumSkill
hasDamagingAttack = false
user.eachMove do |m|
next if !m.damagingMove?
hasDamagingAttack = true
break
end
if hasDamagingAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
if move.function=="028" # Growth
score += 20 if @battle.pbWeather==PBWeather::Sun ||
@battle.pbWeather==PBWeather::HarshSun
end
end
#---------------------------------------------------------------------------
when "029"
if user.statStageAtMax?(PBStats::ATTACK) &&
user.statStageAtMax?(PBStats::ACCURACY)
score -= 90
else
score -= user.stages[PBStats::ATTACK]*10
score -= user.stages[PBStats::ACCURACY]*10
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
user.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
#---------------------------------------------------------------------------
when "02A"
if user.statStageAtMax?(PBStats::DEFENSE) &&
user.statStageAtMax?(PBStats::SPDEF)
score -= 90
else
score -= user.stages[PBStats::DEFENSE]*10
score -= user.stages[PBStats::SPDEF]*10
end
#---------------------------------------------------------------------------
when "02B"
if user.statStageAtMax?(PBStats::SPEED) &&
user.statStageAtMax?(PBStats::SPATK) &&
user.statStageAtMax?(PBStats::SPDEF)
score -= 90
else
score -= user.stages[PBStats::SPATK]*10
score -= user.stages[PBStats::SPDEF]*10
score -= user.stages[PBStats::SPEED]*10
if skill>=PBTrainerAI.mediumSkill
hasSpecicalAttack = false
user.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
if skill>=PBTrainerAI.highSkill
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
if aspeed<ospeed && aspeed*2>ospeed
score += 20
end
end
end
#---------------------------------------------------------------------------
when "02C"
if user.statStageAtMax?(PBStats::SPATK) &&
user.statStageAtMax?(PBStats::SPDEF)
score -= 90
else
score += 40 if user.turnCount==0 # Calm Mind tends to be popular
score -= user.stages[PBStats::SPATK]*10
score -= user.stages[PBStats::SPDEF]*10
if skill>=PBTrainerAI.mediumSkill
hasSpecicalAttack = false
user.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
#---------------------------------------------------------------------------
when "02D"
PBStats.eachMainBattleStat { |s| score += 10 if user.stages[s]<0 }
if skill>=PBTrainerAI.mediumSkill
hasDamagingAttack = false
user.eachMove do |m|
next if !m.damagingMove?
hasDamagingAttack = true
break
end
score += 20 if hasDamagingAttack
end
#---------------------------------------------------------------------------
when "02E"
if move.statusMove?
if user.statStageAtMax?(PBStats::ATTACK)
score -= 90
else
score += 40 if user.turnCount==0
score -= user.stages[PBStats::ATTACK]*20
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
user.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
else
score += 10 if user.turnCount==0
score += 20 if user.stages[PBStats::ATTACK]<0
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
user.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
score += 20 if hasPhysicalAttack
end
end
#---------------------------------------------------------------------------
when "02F"
if move.statusMove?
if user.statStageAtMax?(PBStats::DEFENSE)
score -= 90
else
score += 40 if user.turnCount==0
score -= user.stages[PBStats::DEFENSE]*20
end
else
score += 10 if user.turnCount==0
score += 20 if user.stages[PBStats::DEFENSE]<0
end
#---------------------------------------------------------------------------
when "030", "031"
if move.statusMove?
if user.statStageAtMax?(PBStats::SPEED)
score -= 90
else
score += 20 if user.turnCount==0
score -= user.stages[PBStats::SPEED]*10
if skill>=PBTrainerAI.highSkill
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
score += 30 if aspeed<ospeed && aspeed*2>ospeed
end
end
else
score += 10 if user.turnCount==0
score += 20 if user.stages[PBStats::SPEED]<0
end
#---------------------------------------------------------------------------
when "032"
if move.statusMove?
if user.statStageAtMax?(PBStats::SPATK)
score -= 90
else
score += 40 if user.turnCount==0
score -= user.stages[PBStats::SPATK]*20
if skill>=PBTrainerAI.mediumSkill
hasSpecicalAttack = false
user.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
else
score += 10 if user.turnCount==0
score += 20 if user.stages[PBStats::SPATK]<0
if skill>=PBTrainerAI.mediumSkill
hasSpecicalAttack = false
user.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
score += 20 if hasSpecicalAttack
end
end
#---------------------------------------------------------------------------
when "033"
if move.statusMove?
if user.statStageAtMax?(PBStats::SPDEF)
score -= 90
else
score += 40 if user.turnCount==0
score -= user.stages[PBStats::SPDEF]*20
end
else
score += 10 if user.turnCount==0
score += 20 if user.stages[PBStats::SPDEF]<0
end
#---------------------------------------------------------------------------
when "034"
if move.statusMove?
if user.statStageAtMax?(PBStats::EVASION)
score -= 90
else
score += 40 if user.turnCount==0
score -= user.stages[PBStats::EVASION]*10
end
else
score += 10 if user.turnCount==0
score += 20 if user.stages[PBStats::EVASION]<0
end
#---------------------------------------------------------------------------
when "035"
score -= user.stages[PBStats::ATTACK]*20
score -= user.stages[PBStats::SPEED]*20
score -= user.stages[PBStats::SPATK]*20
score += user.stages[PBStats::DEFENSE]*10
score += user.stages[PBStats::SPDEF]*10
if skill>=PBTrainerAI.mediumSkill
hasDamagingAttack = false
user.eachMove do |m|
next if !m.damagingMove?
hasDamagingAttack = true
break
end
score += 20 if hasDamagingAttack
end
#---------------------------------------------------------------------------
when "036"
if user.statStageAtMax?(PBStats::ATTACK) &&
user.statStageAtMax?(PBStats::SPEED)
score -= 90
else
score -= user.stages[PBStats::ATTACK]*10
score -= user.stages[PBStats::SPEED]*10
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
user.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
if skill>=PBTrainerAI.highSkill
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
score += 30 if aspeed<ospeed && aspeed*2>ospeed
end
end
#---------------------------------------------------------------------------
when "037"
avgStat = 0; canChangeStat = false
PBStats.eachBattleStat do |s|
next if target.statStageAtMax?(s)
avgStat -= target.stages[s]
canChangeStat = true
end
if canChangeStat
avgStat = avgStat/2 if avgStat<0 # More chance of getting even better
score += avgStat*10
else
score -= 90
end
#---------------------------------------------------------------------------
when "038"
if move.statusMove?
if user.statStageAtMax?(PBStats::DEFENSE)
score -= 90
else
score += 40 if user.turnCount==0
score -= user.stages[PBStats::DEFENSE]*30
end
else
score += 10 if user.turnCount==0
score += 30 if user.stages[PBStats::DEFENSE]<0
end
#---------------------------------------------------------------------------
when "039"
if move.statusMove?
if user.statStageAtMax?(PBStats::SPATK)
score -= 90
else
score += 40 if user.turnCount==0
score -= user.stages[PBStats::SPATK]*30
if skill>=PBTrainerAI.mediumSkill
hasSpecicalAttack = false
user.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
else
score += 10 if user.turnCount==0
score += 30 if user.stages[PBStats::SPATK]<0
if skill>=PBTrainerAI.mediumSkill
hasSpecicalAttack = false
user.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
score += 30 if hasSpecicalAttack
end
end
#---------------------------------------------------------------------------
when "03A"
if user.statStageAtMax?(PBStats::ATTACK) ||
user.hp<=user.totalhp/2
score -= 100
else
score += (6-user.stages[PBStats::ATTACK])*10
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
user.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 40
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
#---------------------------------------------------------------------------
when "03B"
avg = user.stages[PBStats::ATTACK]*10
avg += user.stages[PBStats::DEFENSE]*10
score += avg/2
#---------------------------------------------------------------------------
when "03C"
avg = user.stages[PBStats::DEFENSE]*10
avg += user.stages[PBStats::SPDEF]*10
score += avg/2
#---------------------------------------------------------------------------
when "03D"
avg = user.stages[PBStats::DEFENSE]*10
avg += user.stages[PBStats::SPEED]*10
avg += user.stages[PBStats::SPDEF]*10
score += (avg/3).floor
#---------------------------------------------------------------------------
when "03E"
score += user.stages[PBStats::SPEED]*10
#---------------------------------------------------------------------------
when "03F"
score += user.stages[PBStats::SPATK]*10
#---------------------------------------------------------------------------
end
return score
end
end

View File

@@ -1,797 +0,0 @@
class PokeBattle_AI
alias __b__pbGetMoveScoreFunctionCode pbGetMoveScoreFunctionCode
#=============================================================================
# Get a score for the given move based on its effect
#=============================================================================
def pbGetMoveScoreFunctionCode(score,move,user,target,skill=100)
score = __b__pbGetMoveScoreFunctionCode(score,move,user,target,skill)
case move.function
#---------------------------------------------------------------------------
when "040"
if !target.pbCanConfuse?(user,false)
score -= 90
else
score += 30 if target.stages[PBStats::SPATK]<0
end
#---------------------------------------------------------------------------
when "041"
if !target.pbCanConfuse?(user,false)
score -= 90
else
score += 30 if target.stages[PBStats::ATTACK]<0
end
#---------------------------------------------------------------------------
when "042"
if move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::ATTACK,user)
score -= 90
else
score += target.stages[PBStats::ATTACK]*20
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
else
score += 20 if target.stages[PBStats::ATTACK]>0
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
score += 20 if hasPhysicalAttack
end
end
#---------------------------------------------------------------------------
when "043"
if move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::DEFENSE,user)
score -= 90
else
score += target.stages[PBStats::DEFENSE]*20
end
else
score += 20 if target.stages[PBStats::DEFENSE]>0
end
#---------------------------------------------------------------------------
when "044"
if move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::SPEED,user)
score -= 90
else
score += target.stages[PBStats::SPEED]*10
if skill>=PBTrainerAI.highSkill
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
score += 30 if aspeed<ospeed && aspeed*2>ospeed
end
end
else
score += 20 if user.stages[PBStats::SPEED]>0
end
#---------------------------------------------------------------------------
when "045"
if move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::SPATK,user)
score -= 90
else
score += user.stages[PBStats::SPATK]*20
if skill>=PBTrainerAI.mediumSkill
hasSpecicalAttack = false
target.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
else
score += 20 if user.stages[PBStats::SPATK]>0
if skill>=PBTrainerAI.mediumSkill
hasSpecicalAttack = false
target.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
score += 20 if hasSpecicalAttack
end
end
#---------------------------------------------------------------------------
when "046"
if move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::SPDEF,user)
score -= 90
else
score += target.stages[PBStats::SPDEF]*20
end
else
score += 20 if target.stages[PBStats::SPDEF]>0
end
#---------------------------------------------------------------------------
when "047"
if move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::ACCURACY,user)
score -= 90
else
score += target.stages[PBStats::ACCURACY]*10
end
else
score += 20 if target.stages[PBStats::ACCURACY]>0
end
#---------------------------------------------------------------------------
when "048"
if move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::EVASION,user)
score -= 90
else
score += target.stages[PBStats::EVASION]*10
end
else
score += 20 if target.stages[PBStats::EVASION]>0
end
#---------------------------------------------------------------------------
when "049"
if move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::EVASION,user)
score -= 90
else
score += target.stages[PBStats::EVASION]*10
end
else
score += 20 if target.stages[PBStats::EVASION]>0
end
score += 30 if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0 ||
target.pbOwnSide.effects[PBEffects::Reflect]>0 ||
target.pbOwnSide.effects[PBEffects::LightScreen]>0 ||
target.pbOwnSide.effects[PBEffects::Mist]>0 ||
target.pbOwnSide.effects[PBEffects::Safeguard]>0
score -= 30 if target.pbOwnSide.effects[PBEffects::Spikes]>0 ||
target.pbOwnSide.effects[PBEffects::ToxicSpikes]>0 ||
target.pbOwnSide.effects[PBEffects::StealthRock]
#---------------------------------------------------------------------------
when "04A"
avg = target.stages[PBStats::ATTACK]*10
avg += target.stages[PBStats::DEFENSE]*10
score += avg/2
#---------------------------------------------------------------------------
when "04B"
if move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::ATTACK,user)
score -= 90
else
score += 40 if user.turnCount==0
score += target.stages[PBStats::ATTACK]*20
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
else
score += 10 if user.turnCount==0
score += 20 if target.stages[PBStats::ATTACK]>0
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
score += 20 if hasPhysicalAttack
end
end
#---------------------------------------------------------------------------
when "04C"
if move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::DEFENSE,user)
score -= 90
else
score += 40 if user.turnCount==0
score += target.stages[PBStats::DEFENSE]*20
end
else
score += 10 if user.turnCount==0
score += 20 if target.stages[PBStats::DEFENSE]>0
end
#---------------------------------------------------------------------------
when "04D"
if move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::SPEED,user)
score -= 90
else
score += 20 if user.turnCount==0
score += target.stages[PBStats::SPEED]*20
if skill>=PBTrainerAI.highSkill
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
score += 30 if aspeed<ospeed && aspeed*2>ospeed
end
end
else
score += 10 if user.turnCount==0
score += 30 if target.stages[PBStats::SPEED]>0
end
#---------------------------------------------------------------------------
when "04E"
if user.gender==2 || target.gender==2 || user.gender==target.gender ||
target.hasActiveAbility?(:OBLIVIOUS)
score -= 90
elsif move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::SPATK,user)
score -= 90
else
score += 40 if user.turnCount==0
score += target.stages[PBStats::SPATK]*20
if skill>=PBTrainerAI.mediumSkill
hasSpecicalAttack = false
target.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
else
score += 10 if user.turnCount==0
score += 20 if target.stages[PBStats::SPATK]>0
if skill>=PBTrainerAI.mediumSkill
hasSpecicalAttack = false
target.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
score += 30 if hasSpecicalAttack
end
end
#---------------------------------------------------------------------------
when "04F"
if move.statusMove?
if !target.pbCanLowerStatStage?(PBStats::SPDEF,user)
score -= 90
else
score += 40 if user.turnCount==0
score += target.stages[PBStats::SPDEF]*20
end
else
score += 10 if user.turnCount==0
score += 20 if target.stages[PBStats::SPDEF]>0
end
#---------------------------------------------------------------------------
when "050"
if target.effects[PBEffects::Substitute]>0
score -= 90
else
avg = 0; anyChange = false
PBStats.eachBattleStat do |s|
next if target.stages[s]==0
avg += target.stages[s]
anyChange = true
end
if anyChange
score += avg*10
else
score -= 90
end
end
#---------------------------------------------------------------------------
when "051"
if skill>=PBTrainerAI.mediumSkill
stages = 0
@battle.eachBattler do |b|
totalStages = 0
PBStats.eachBattleStat { |s| totalStages += b.stages[s] }
if b.opposes?(user)
stages += totalStages
else
stages -= totalStages
end
end
score += stages*10
end
#---------------------------------------------------------------------------
when "052"
if skill>=PBTrainerAI.mediumSkill
aatk = user.stages[PBStats::ATTACK]
aspa = user.stages[PBStats::SPATK]
oatk = target.stages[PBStats::ATTACK]
ospa = target.stages[PBStats::SPATK]
if aatk>=oatk && aspa>=ospa
score -= 80
else
score += (oatk-aatk)*10
score += (ospa-aspa)*10
end
else
score -= 50
end
#---------------------------------------------------------------------------
when "053"
if skill>=PBTrainerAI.mediumSkill
adef = user.stages[PBStats::DEFENSE]
aspd = user.stages[PBStats::SPDEF]
odef = target.stages[PBStats::DEFENSE]
ospd = target.stages[PBStats::SPDEF]
if adef>=odef && aspd>=ospd
score -= 80
else
score += (odef-adef)*10
score += (ospd-aspd)*10
end
else
score -= 50
end
#---------------------------------------------------------------------------
when "054"
if skill>=PBTrainerAI.mediumSkill
userStages = 0; targetStages = 0
PBStats.eachBattleStat do |s|
userStages += user.stages[s]
targetStages += target.stages[s]
end
score += (targetStages-userStages)*10
else
score -= 50
end
#---------------------------------------------------------------------------
when "055"
if skill>=PBTrainerAI.mediumSkill
equal = true
PBStats.eachBattleStat do |s|
stagediff = target.stages[s]-user.stages[s]
score += stagediff*10
equal = false if stagediff!=0
end
score -= 80 if equal
else
score -= 50
end
#---------------------------------------------------------------------------
when "056"
score -= 80 if user.pbOwnSide.effects[PBEffects::Mist]>0
#---------------------------------------------------------------------------
when "057"
if skill>=PBTrainerAI.mediumSkill
aatk = pbRoughStat(user,PBStats::ATTACK,skill)
adef = pbRoughStat(user,PBStats::DEFENSE,skill)
if aatk==adef ||
user.effects[PBEffects::PowerTrick] # No flip-flopping
score -= 90
elsif adef>aatk # Prefer a higher Attack
score += 30
else
score -= 30
end
else
score -= 30
end
#---------------------------------------------------------------------------
when "058"
if skill>=PBTrainerAI.mediumSkill
aatk = pbRoughStat(user,PBStats::ATTACK,skill)
aspatk = pbRoughStat(user,PBStats::SPATK,skill)
oatk = pbRoughStat(target,PBStats::ATTACK,skill)
ospatk = pbRoughStat(target,PBStats::SPATK,skill)
if aatk<oatk && aspatk<ospatk
score += 50
elsif aatk+aspatk<oatk+ospatk
score += 30
else
score -= 50
end
else
score -= 30
end
#---------------------------------------------------------------------------
when "059"
if skill>=PBTrainerAI.mediumSkill
adef = pbRoughStat(user,PBStats::DEFENSE,skill)
aspdef = pbRoughStat(user,PBStats::SPDEF,skill)
odef = pbRoughStat(target,PBStats::DEFENSE,skill)
ospdef = pbRoughStat(target,PBStats::SPDEF,skill)
if adef<odef && aspdef<ospdef
score += 50
elsif adef+aspdef<odef+ospdef
score += 30
else
score -= 50
end
else
score -= 30
end
#---------------------------------------------------------------------------
when "05A"
if target.effects[PBEffects::Substitute]>0
score -= 90
elsif user.hp>=(user.hp+target.hp)/2
score -= 90
else
score += 40
end
#---------------------------------------------------------------------------
when "05B"
score -= 90 if user.pbOwnSide.effects[PBEffects::Tailwind]>0
#---------------------------------------------------------------------------
when "05C"
moveBlacklist = [
"002", # Struggle
"014", # Chatter
"05C", # Mimic
"05D", # Sketch
"0B6" # Metronome
]
lastMoveData = pbGetMoveData(target.lastRegularMoveUsed)
if user.effects[PBEffects::Transform] ||
target.lastRegularMoveUsed<=0 ||
moveBlacklist.include?(lastMoveData[MOVE_FUNCTION_CODE]) ||
isConst?(lastMoveData[MOVE_TYPE],PBTypes,:SHADOW)
score -= 90
end
user.eachMove do |m|
next if m.id!=target.lastRegularMoveUsed
score -= 90
break
end
#---------------------------------------------------------------------------
when "05D"
moveBlacklist = [
"002", # Struggle
"014", # Chatter
"05D" # Sketch
]
lastMoveData = pbGetMoveData(target.lastRegularMoveUsed)
if user.effects[PBEffects::Transform] ||
target.lastRegularMoveUsed<=0 ||
moveBlacklist.include?(lastMoveData[MOVE_FUNCTION_CODE]) ||
isConst?(lastMoveData[MOVE_TYPE],PBTypes,:SHADOW)
score -= 90
end
user.eachMove do |m|
next if m.id!=target.lastRegularMoveUsed
score -= 90 # User already knows the move that will be Sketched
break
end
#---------------------------------------------------------------------------
when "05E"
if isConst?(user.ability,PBAbilities,:MULTITYPE) ||
isConst?(user.ability,PBAbilities,:RKSSYSTEM)
score -= 90
else
types = []
user.eachMove do |m|
next if m.id==@id
next if PBTypes.isPseudoType?(m.type)
next if user.pbHasType?(m.type)
types.push(m.type) if !types.include?(m.type)
end
score -= 90 if types.length==0
end
#---------------------------------------------------------------------------
when "05F"
if isConst?(user.ability,PBAbilities,:MULTITYPE) ||
isConst?(user.ability,PBAbilities,:RKSSYSTEM)
score -= 90
elsif target.lastMoveUsed<=0 ||
PBTypes.isPseudoType?(pbGetMoveData(target.lastMoveUsed,MOVE_TYPE))
score -= 90
else
aType = -1
target.eachMove do |m|
next if m.id!=target.lastMoveUsed
aType = m.pbCalcType(user)
break
end
if aType<0
score -= 90
else
types = []
for i in 0..PBTypes.maxValue
next if user.pbHasType?(i)
types.push(i) if PBTypes.resistant?(aType,i)
end
score -= 90 if types.length==0
end
end
#---------------------------------------------------------------------------
when "060"
if isConst?(user.ability,PBAbilities,:MULTITYPE) ||
isConst?(user.ability,PBAbilities,:RKSSYSTEM)
score -= 90
elsif skill>=PBTrainerAI.mediumSkill
envtypes = [
:NORMAL, # None
:GRASS, # Grass
:GRASS, # Tall grass
:WATER, # Moving water
:WATER, # Still water
:WATER, # Underwater
:ROCK, # Rock
:ROCK, # Cave
:GROUND # Sand
]
type = envtypes[@environment]
score -= 90 if user.pbHasType?(type)
end
#---------------------------------------------------------------------------
when "061"
if target.effects[PBEffects::Substitute]>0 ||
isConst?(target.ability,PBAbilities,:MULTITYPE) ||
isConst?(target.ability,PBAbilities,:RKSSYSTEM)
score -= 90
elsif target.pbHasType?(:WATER)
score -= 90
end
#---------------------------------------------------------------------------
when "062"
if isConst?(user.ability,PBAbilities,:MULTITYPE) ||
isConst?(user.ability,PBAbilities,:RKSSYSTEM)
score -= 90
elsif user.pbHasType?(target.type1) &&
user.pbHasType?(target.type2) &&
target.pbHasType?(user.type1) &&
target.pbHasType?(user.type2)
score -= 90
end
#---------------------------------------------------------------------------
when "063"
if target.effects[PBEffects::Substitute]>0
score -= 90
elsif skill>=PBTrainerAI.mediumSkill
if isConst?(target.ability,PBAbilities,:MULTITYPE) ||
isConst?(target.ability,PBAbilities,:RKSSYSTEM) ||
isConst?(target.ability,PBAbilities,:SIMPLE) ||
isConst?(target.ability,PBAbilities,:TRUANT)
score -= 90
end
end
#---------------------------------------------------------------------------
when "064"
if target.effects[PBEffects::Substitute]>0
score -= 90
elsif skill>=PBTrainerAI.mediumSkill
if isConst?(target.ability,PBAbilities,:INSOMNIA) ||
isConst?(target.ability,PBAbilities,:MULTITYPE) ||
isConst?(target.ability,PBAbilities,:RKSSYSTEM) ||
isConst?(target.ability,PBAbilities,:TRUANT)
score -= 90
end
end
#---------------------------------------------------------------------------
when "065"
score -= 40 # don't prefer this move
if skill>=PBTrainerAI.mediumSkill
if target.ability==0 || user.ability==target.ability ||
isConst?(user.ability,PBAbilities,:MULTITYPE) ||
isConst?(user.ability,PBAbilities,:RKSSYSTEM) ||
isConst?(target.ability,PBAbilities,:FLOWERGIFT) ||
isConst?(target.ability,PBAbilities,:FORECAST) ||
isConst?(target.ability,PBAbilities,:ILLUSION) ||
isConst?(target.ability,PBAbilities,:IMPOSTER) ||
isConst?(target.ability,PBAbilities,:MULTITYPE) ||
isConst?(target.ability,PBAbilities,:RKSSYSTEM) ||
isConst?(target.ability,PBAbilities,:TRACE) ||
isConst?(target.ability,PBAbilities,:WONDERGUARD) ||
isConst?(target.ability,PBAbilities,:ZENMODE)
score -= 90
end
end
if skill>=PBTrainerAI.highSkill
if isConst?(target.ability,PBAbilities,:TRUANT) &&
user.opposes?(target)
score -= 90
elsif isConst?(target.ability,PBAbilities,:SLOWSTART) &&
user.opposes?(target)
score -= 90
end
end
#---------------------------------------------------------------------------
when "066"
score -= 40 # don't prefer this move
if target.effects[PBEffects::Substitute]>0
score -= 90
elsif skill>=PBTrainerAI.mediumSkill
if user.ability==0 || user.ability==target.ability ||
isConst?(target.ability,PBAbilities,:MULTITYPE) ||
isConst?(target.ability,PBAbilities,:RKSSYSTEM) ||
isConst?(target.ability,PBAbilities,:TRUANT) ||
isConst?(user.ability,PBAbilities,:FLOWERGIFT) ||
isConst?(user.ability,PBAbilities,:FORECAST) ||
isConst?(user.ability,PBAbilities,:ILLUSION) ||
isConst?(user.ability,PBAbilities,:IMPOSTER) ||
isConst?(user.ability,PBAbilities,:MULTITYPE) ||
isConst?(user.ability,PBAbilities,:RKSSYSTEM) ||
isConst?(user.ability,PBAbilities,:TRACE) ||
isConst?(user.ability,PBAbilities,:ZENMODE)
score -= 90
end
if skill>=PBTrainerAI.highSkill
if isConst?(user.ability,PBAbilities,:TRUANT) &&
user.opposes?(target)
score += 90
elsif isConst?(user.ability,PBAbilities,:SLOWSTART) &&
user.opposes?(target)
score += 90
end
end
end
#---------------------------------------------------------------------------
when "067"
score -= 40 # don't prefer this move
if skill>=PBTrainerAI.mediumSkill
if (user.ability==0 && target.ability==0) ||
user.ability==target.ability ||
isConst?(user.ability,PBAbilities,:ILLUSION) ||
isConst?(user.ability,PBAbilities,:MULTITYPE) ||
isConst?(user.ability,PBAbilities,:RKSSYSTEM) ||
isConst?(user.ability,PBAbilities,:WONDERGUARD) ||
isConst?(target.ability,PBAbilities,:ILLUSION) ||
isConst?(target.ability,PBAbilities,:MULTITYPE) ||
isConst?(target.ability,PBAbilities,:RKSSYSTEM) ||
isConst?(target.ability,PBAbilities,:WONDERGUARD)
score -= 90
end
end
if skill>=PBTrainerAI.highSkill
if isConst?(target.ability,PBAbilities,:TRUANT) &&
user.opposes?(target)
score -= 90
elsif isConst?(target.ability,PBAbilities,:SLOWSTART) &&
user.opposes?(target)
score -= 90
end
end
#---------------------------------------------------------------------------
when "068"
if target.effects[PBEffects::Substitute]>0 ||
target.effects[PBEffects::GastroAcid]
score -= 90
elsif skill>=PBTrainerAI.highSkill
score -= 90 if isConst?(target.ability,PBAbilities,:MULTITYPE)
score -= 90 if isConst?(target.ability,PBAbilities,:RKSSYSTEM)
score -= 90 if isConst?(target.ability,PBAbilities,:SLOWSTART)
score -= 90 if isConst?(target.ability,PBAbilities,:TRUANT)
end
#---------------------------------------------------------------------------
when "069"
score -= 70
#---------------------------------------------------------------------------
when "06A"
if target.hp<=20
score += 80
elsif target.level>=25
score -= 60 # Not useful against high-level Pokemon
end
#---------------------------------------------------------------------------
when "06B"
score += 80 if target.hp<=40
#---------------------------------------------------------------------------
when "06C"
score -= 50
score += target.hp*100/target.totalhp
#---------------------------------------------------------------------------
when "06D"
score += 80 if target.hp<=user.level
#---------------------------------------------------------------------------
when "06E"
if user.hp>=target.hp
score -= 90
elsif user.hp<target.hp/2
score += 50
end
#---------------------------------------------------------------------------
when "06F"
score += 30 if target.hp<=user.level
#---------------------------------------------------------------------------
when "070"
score -= 90 if target.hasActiveAbility?(:STURDY)
score -= 90 if target.level>user.level
#---------------------------------------------------------------------------
when "071"
if target.effects[PBEffects::HyperBeam]>0
score -= 90
else
attack = pbRoughStat(user,PBStats::ATTACK,skill)
spatk = pbRoughStat(user,PBStats::SPATK,skill)
if attack*1.5<spatk
score -= 60
elsif skill>=PBTrainerAI.mediumSkill && target.lastMoveUsed>0
moveData = pbGetMoveData(target.lastMoveUsed)
if moveData[MOVE_BASE_DAMAGE]>0 &&
(MOVE_CATEGORY_PER_MOVE && moveData[MOVE_CATEGORY]==0) ||
(!MOVE_CATEGORY_PER_MOVE && PBTypes.isPhysicalType?(moveData[MOVE_TYPE]))
score -= 60
end
end
end
#---------------------------------------------------------------------------
when "072"
if target.effects[PBEffects::HyperBeam]>0
score -= 90
else
attack = pbRoughStat(user,PBStats::ATTACK,skill)
spatk = pbRoughStat(user,PBStats::SPATK,skill)
if attack>spatk*1.5
score -= 60
elsif skill>=PBTrainerAI.mediumSkill && target.lastMoveUsed>0
moveData = pbGetMoveData(target.lastMoveUsed)
if moveData[MOVE_BASE_DAMAGE]>0 &&
(MOVE_CATEGORY_PER_MOVE && moveData[MOVE_CATEGORY]==1) ||
(!MOVE_CATEGORY_PER_MOVE && !PBTypes.isSpecialType?(moveData[MOVE_TYPE]))
score -= 60
end
end
end
#---------------------------------------------------------------------------
when "073"
score -= 90 if target.effects[PBEffects::HyperBeam]>0
#---------------------------------------------------------------------------
when "074"
target.eachAlly do |b|
next if !b.near?(target)
score += 10
end
#---------------------------------------------------------------------------
when "075"
#---------------------------------------------------------------------------
when "076"
#---------------------------------------------------------------------------
when "077"
#---------------------------------------------------------------------------
when "078"
if skill>=PBTrainerAI.highSkill
score += 30 if !target.hasActiveAbility?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute]==0
end
#---------------------------------------------------------------------------
when "079"
#---------------------------------------------------------------------------
when "07A"
#---------------------------------------------------------------------------
when "07B"
#---------------------------------------------------------------------------
when "07C"
score -= 20 if target.status==PBStatuses::PARALYSIS # Will cure status
#---------------------------------------------------------------------------
when "07D"
score -= 20 if target.status==PBStatuses::SLEEP && # Will cure status
target.statusCount>1
#---------------------------------------------------------------------------
when "07E"
#---------------------------------------------------------------------------
when "07F"
#---------------------------------------------------------------------------
end
return score
end
end

View File

@@ -1,228 +0,0 @@
class PokeBattle_AI
alias __c__pbGetMoveScoreFunctionCode pbGetMoveScoreFunctionCode
#=============================================================================
# Get a score for the given move based on its effect
#=============================================================================
def pbGetMoveScoreFunctionCode(score,move,user,target,skill=100)
score = __c__pbGetMoveScoreFunctionCode(score,move,user,target,skill)
case move.function
#---------------------------------------------------------------------------
when "080"
#---------------------------------------------------------------------------
when "081"
attspeed = pbRoughStat(user,PBStats::SPEED,skill)
oppspeed = pbRoughStat(target,PBStats::SPEED,skill)
score += 30 if oppspeed>attspeed
#---------------------------------------------------------------------------
when "082"
score += 20 if @battle.pbOpposingBattlerCount(user)>1
#---------------------------------------------------------------------------
when "083"
if skill>=PBTrainerAI.mediumSkill
user.eachAlly do |b|
next if !b.pbHasMove?(move.id)
score += 20
end
end
#---------------------------------------------------------------------------
when "084"
attspeed = pbRoughStat(user,PBStats::SPEED,skill)
oppspeed = pbRoughStat(target,PBStats::SPEED,skill)
score += 30 if oppspeed>attspeed
#---------------------------------------------------------------------------
when "085"
#---------------------------------------------------------------------------
when "086"
#---------------------------------------------------------------------------
when "087"
#---------------------------------------------------------------------------
when "088"
#---------------------------------------------------------------------------
when "089"
#---------------------------------------------------------------------------
when "08A"
#---------------------------------------------------------------------------
when "08B"
#---------------------------------------------------------------------------
when "08C"
#---------------------------------------------------------------------------
when "08D"
#---------------------------------------------------------------------------
when "08E"
#---------------------------------------------------------------------------
when "08F"
#---------------------------------------------------------------------------
when "090"
#---------------------------------------------------------------------------
when "091"
#---------------------------------------------------------------------------
when "092"
#---------------------------------------------------------------------------
when "093"
score += 25 if user.effects[PBEffects::Rage]
#---------------------------------------------------------------------------
when "094"
#---------------------------------------------------------------------------
when "095"
#---------------------------------------------------------------------------
when "096"
score -= 90 if !pbIsBerry?(user.item) || !user.itemActive?
#---------------------------------------------------------------------------
when "097"
#---------------------------------------------------------------------------
when "098"
#---------------------------------------------------------------------------
when "099"
#---------------------------------------------------------------------------
when "09A"
#---------------------------------------------------------------------------
when "09B"
#---------------------------------------------------------------------------
when "09C"
hasAlly = false
user.eachAlly do |b|
hasAlly = true
score += 30
break
end
score -= 90 if !hasAlly
#---------------------------------------------------------------------------
when "09D"
score -= 90 if user.effects[PBEffects::MudSport]
#---------------------------------------------------------------------------
when "09E"
score -= 90 if user.effects[PBEffects::WaterSport]
#---------------------------------------------------------------------------
when "09F"
#---------------------------------------------------------------------------
when "0A0"
#---------------------------------------------------------------------------
when "0A1"
score -= 90 if user.pbOwnSide.effects[PBEffects::LuckyChant]>0
#---------------------------------------------------------------------------
when "0A2"
score -= 90 if user.pbOwnSide.effects[PBEffects::Reflect]>0
#---------------------------------------------------------------------------
when "0A3"
score -= 90 if user.pbOwnSide.effects[PBEffects::LightScreen]>0
#---------------------------------------------------------------------------
when "0A4"
#---------------------------------------------------------------------------
when "0A5"
#---------------------------------------------------------------------------
when "0A6"
score -= 90 if target.effects[PBEffects::Substitute]>0
score -= 90 if user.effects[PBEffects::LockOn]>0
#---------------------------------------------------------------------------
when "0A7"
if target.effects[PBEffects::Foresight]
score -= 90
elsif target.pbHasType?(:GHOST)
score += 70
elsif target.stages[PBStats::EVASION]<=0
score -= 60
end
#---------------------------------------------------------------------------
when "0A8"
if target.effects[PBEffects::MiracleEye]
score -= 90
elsif target.pbHasType?(:DARK)
score += 70
elsif target.stages[PBStats::EVASION]<=0
score -= 60
end
#---------------------------------------------------------------------------
when "0A9"
#---------------------------------------------------------------------------
when "0AA"
if user.effects[PBEffects::ProtectRate]>1 ||
target.effects[PBEffects::HyperBeam]>0
score -= 90
else
if skill>=PBTrainerAI.mediumSkill
score -= user.effects[PBEffects::ProtectRate]*40
end
score += 50 if user.turnCount==0
score += 30 if target.effects[PBEffects::TwoTurnAttack]>0
end
#---------------------------------------------------------------------------
when "0AB"
#---------------------------------------------------------------------------
when "0AC"
#---------------------------------------------------------------------------
when "0AD"
#---------------------------------------------------------------------------
when "0AE"
score -= 40
if skill>=PBTrainerAI.highSkill
score -= 100 if target.lastRegularMoveUsed<=0 ||
!pbGetMoveData(target.lastRegularMoveUsed,MOVE_FLAGS)[/e/] # Not copyable by Mirror Move
end
#---------------------------------------------------------------------------
when "0AF"
#---------------------------------------------------------------------------
when "0B0"
#---------------------------------------------------------------------------
when "0B1"
#---------------------------------------------------------------------------
when "0B2"
#---------------------------------------------------------------------------
when "0B3"
#---------------------------------------------------------------------------
when "0B4"
if user.asleep?
score += 100 # Because it can only be used while asleep
else
score -= 90
end
#---------------------------------------------------------------------------
when "0B5"
#---------------------------------------------------------------------------
when "0B6"
#---------------------------------------------------------------------------
when "0B7"
score -= 90 if target.effects[PBEffects::Torment]
#---------------------------------------------------------------------------
when "0B8"
score -= 90 if user.effects[PBEffects::Imprison]
#---------------------------------------------------------------------------
when "0B9"
score -= 90 if target.effects[PBEffects::Disable]>0
#---------------------------------------------------------------------------
when "0BA"
score -= 90 if target.effects[PBEffects::Taunt]>0
#---------------------------------------------------------------------------
when "0BB"
score -= 90 if target.effects[PBEffects::HealBlock]>0
#---------------------------------------------------------------------------
when "0BC"
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
if target.effects[PBEffects::Encore]>0
score -= 90
elsif aspeed>ospeed
if target.lastMoveUsed<=0
score -= 90
else
moveData = pbGetMoveData(target.lastRegularMoveUsed)
if moveData[MOVE_CATEGORY]==2 && # Status move
(moveData[MOVE_TARGET]==PBTargets::User ||
moveData[MOVE_TARGET]==PBTargets::BothSides)
score += 60
elsif moveData[MOVE_CATEGORY]!=2 && # Damaging move
moveData[MOVE_TARGET]==PBTargets::NearOther &&
PBTypes.ineffective?(pbCalcTypeMod(moveData[MOVE_TYPE],target,user))
score += 60
end
end
end
#---------------------------------------------------------------------------
when "0BD"
#---------------------------------------------------------------------------
when "0BF"
#---------------------------------------------------------------------------
end
return score
end
end

View File

@@ -1,375 +0,0 @@
class PokeBattle_AI
alias __d__pbGetMoveScoreFunctionCode pbGetMoveScoreFunctionCode
#=============================================================================
# Get a score for the given move based on its effect
#=============================================================================
def pbGetMoveScoreFunctionCode(score,move,user,target,skill=100)
score = __d__pbGetMoveScoreFunctionCode(score,move,user,target,skill)
case move.function
#---------------------------------------------------------------------------
when "0C0"
#---------------------------------------------------------------------------
when "0C1"
#---------------------------------------------------------------------------
when "0C2"
#---------------------------------------------------------------------------
when "0C3"
#---------------------------------------------------------------------------
when "0C4"
#---------------------------------------------------------------------------
when "0C7"
score += 20 if user.effects[PBEffects::FocusEnergy]>0
if skill>=PBTrainerAI.highSkill
score += 20 if !target.hasActiveAbility?(:INNERFOCUS) &&
target.effects[PBEffects::Substitute]==0
end
#---------------------------------------------------------------------------
when "0C9"
#---------------------------------------------------------------------------
when "0CA"
#---------------------------------------------------------------------------
when "0CB"
#---------------------------------------------------------------------------
when "0CC"
#---------------------------------------------------------------------------
when "0CD"
#---------------------------------------------------------------------------
when "0CE"
#---------------------------------------------------------------------------
when "0CF"
score += 40 if target.effects[PBEffects::Trapping]==0
#---------------------------------------------------------------------------
when "0D0"
score += 40 if target.effects[PBEffects::Trapping]==0
#---------------------------------------------------------------------------
when "0D1"
#---------------------------------------------------------------------------
when "0D2"
#---------------------------------------------------------------------------
when "0D3"
#---------------------------------------------------------------------------
when "0D4"
if user.hp<=user.totalhp/4
score -= 90
elsif user.hp<=user.totalhp/2
score -= 50
end
#---------------------------------------------------------------------------
when "0D5", "0D6"
if user.hp==user.totalhp || (skill>=PBTrainerAI.mediumSkill && !user.canHeal?)
score -= 90
else
score += 50
score -= user.hp*100/user.totalhp
end
#---------------------------------------------------------------------------
when "0D7"
score -= 90 if @battle.positions[user.index].effects[PBEffects::Wish]>0
#---------------------------------------------------------------------------
when "0D8"
if user.hp==user.totalhp || (skill>=PBTrainerAI.mediumSkill && !user.canHeal?)
score -= 90
else
case @battle.pbWeather
when PBWeather::Sun, PBWeather::HarshSun
score += 30
when PBWeather::None
else
score -= 30
end
score += 50
score -= user.hp*100/user.totalhp
end
#---------------------------------------------------------------------------
when "0D9"
if user.hp==user.totalhp || !user.pbCanSleep?(user,false,nil,true)
score -= 90
else
score += 70
score -= user.hp*140/user.totalhp
score += 30 if user.status!=0
end
#---------------------------------------------------------------------------
when "0DA"
score -= 90 if user.effects[PBEffects::AquaRing]
#---------------------------------------------------------------------------
when "0DB"
score -= 90 if user.effects[PBEffects::Ingrain]
#---------------------------------------------------------------------------
when "0DC"
if target.effects[PBEffects::LeechSeed]>=0
score -= 90
elsif skill>=PBTrainerAI.mediumSkill && target.pbHasType?(:GRASS)
score -= 90
else
score += 60 if user.turnCount==0
end
#---------------------------------------------------------------------------
when "0DD"
if skill>=PBTrainerAI.highSkill && target.hasActiveAbility?(:LIQUIDOOZE)
score -= 70
else
score += 20 if user.hp<=user.totalhp/2
end
#---------------------------------------------------------------------------
when "0DE"
if !target.asleep?
score -= 100
elsif skill>=PBTrainerAI.highSkill && target.hasActiveAbility?(:LIQUIDOOZE)
score -= 70
else
score += 20 if user.hp<=user.totalhp/2
end
#---------------------------------------------------------------------------
when "0DF"
if user.opposes?(target)
score -= 100
else
score += 20 if target.hp<target.totalhp/2 &&
target.effects[PBEffects::Substitute]==0
end
#---------------------------------------------------------------------------
when "0E0"
reserves = @battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = @battle.pbAbleNonActiveCount(user.idxOpposingSide)
if @battle.pbCheckGlobalAbility(:DAMP)
score -= 100
elsif skill>=PBTrainerAI.mediumSkill && reserves==0 && foes>0
score -= 100 # don't want to lose
elsif skill>=PBTrainerAI.highSkill && reserves==0 && foes==0
score += 80 # want to draw
else
score -= user.hp*100/user.totalhp
end
#---------------------------------------------------------------------------
when "0E1"
#---------------------------------------------------------------------------
when "0E2"
if !target.pbCanLowerStatStage?(PBStats::ATTACK,user) &&
!target.pbCanLowerStatStage?(PBStats::SPATK,user)
score -= 100
elsif @battle.pbAbleNonActiveCount(user.idxOwnSide)==0
score -= 100
else
score += target.stages[PBStats::ATTACK]*10
score += target.stages[PBStats::SPATK]*10
score -= user.hp*100/user.totalhp
end
#---------------------------------------------------------------------------
when "0E3", "0E4"
score -= 70
#---------------------------------------------------------------------------
when "0E5"
if @battle.pbAbleNonActiveCount(user.idxOwnSide)==0
score -= 90
else
score -= 90 if target.effects[PBEffects::PerishSong]>0
end
#---------------------------------------------------------------------------
when "0E6"
score += 50
score -= user.hp*100/user.totalhp
score += 30 if user.hp<=user.totalhp/10
#---------------------------------------------------------------------------
when "0E7"
score += 50
score -= user.hp*100/user.totalhp
score += 30 if user.hp<=user.totalhp/10
#---------------------------------------------------------------------------
when "0E8"
score -= 25 if user.hp>user.totalhp/2
if skill>=PBTrainerAI.mediumSkill
score -= 90 if user.effects[PBEffects::ProtectRate]>1
score -= 90 if target.effects[PBEffects::HyperBeam]>0
else
score -= user.effects[PBEffects::ProtectRate]*40
end
#---------------------------------------------------------------------------
when "0E9"
if target.hp==1
score -= 90
elsif target.hp<=target.totalhp/8
score -= 60
elsif target.hp<=target.totalhp/4
score -= 30
end
#---------------------------------------------------------------------------
when "0EA"
score -= 100 if @battle.trainerBattle?
#---------------------------------------------------------------------------
when "0EB"
if target.effects[PBEffects::Ingrain] ||
(skill>=PBTrainerAI.highSkill && target.hasActiveAbility?(:SUCTIONCUPS))
score -= 90
else
ch = 0
@battle.pbParty(target.index).each_with_index do |pkmn,i|
ch += 1 if @battle.pbCanSwitchLax?(target.index,i)
end
score -= 90 if ch==0
end
if score>20
score += 50 if target.pbOwnSide.effects[PBEffects::Spikes]>0
score += 50 if target.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
score += 50 if target.pbOwnSide.effects[PBEffects::StealthRock]
end
#---------------------------------------------------------------------------
when "0EC"
if !target.effects[PBEffects::Ingrain] &&
!(skill>=PBTrainerAI.highSkill && target.hasActiveAbility?(:SUCTIONCUPS))
score += 40 if target.pbOwnSide.effects[PBEffects::Spikes]>0
score += 40 if target.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
score += 40 if target.pbOwnSide.effects[PBEffects::StealthRock]
end
#---------------------------------------------------------------------------
when "0ED"
if !@battle.pbCanChooseNonActive?(user.index)
score -= 80
else
score -= 40 if user.effects[PBEffects::Confusion]>0
total = 0
PBStats.eachBattleStat { |s| total += user.stages[s] }
if total<=0 || user.turnCount==0
score -= 60
else
score += total*10
# special case: user has no damaging moves
hasDamagingMove = false
user.eachMove do |m|
next if !m.damagingMove?
hasDamagingMove = true
break
end
score += 75 if !hasDamagingMove
end
end
#---------------------------------------------------------------------------
when "0EE"
#---------------------------------------------------------------------------
when "0EF"
score -= 90 if target.effects[PBEffects::MeanLook]>=0
#---------------------------------------------------------------------------
when "0F0"
if skill>=PBTrainerAI.highSkill
score += 20 if target.item!=0
end
#---------------------------------------------------------------------------
when "0F1"
if skill>=PBTrainerAI.highSkill
if user.item==0 && target.item!=0
score += 40
else
score -= 90
end
else
score -= 80
end
#---------------------------------------------------------------------------
when "0F2"
if user.item==0 && target.item==0
score -= 90
elsif skill>=PBTrainerAI.highSkill && target.hasActiveAbility?(:STICKYHOLD)
score -= 90
elsif user.hasActiveItem?([:FLAMEORB,:TOXICORB,:STICKYBARB,:IRONBALL,
:CHOICEBAND,:CHOICESCARF,:CHOICESPECS])
score += 50
elsif user.item==0 && target.item!=0
score -= 30 if pbGetMoveData(user.lastMoveUsed,MOVE_FUNCTION_CODE)=="0F2" # Trick/Switcheroo
end
#---------------------------------------------------------------------------
when "0F3"
if user.item==0 || target.item!=0
score -= 90
else
if user.hasActiveItem?([:FLAMEORB,:TOXICORB,:STICKYBARB,:IRONBALL,
:CHOICEBAND,:CHOICESCARF,:CHOICESPECS])
score += 50
else
score -= 80
end
end
#---------------------------------------------------------------------------
when "0F4", "0F5"
if target.effects[PBEffects::Substitute]==0
if skill>=PBTrainerAI.highSkill && pbIsBerry?(target.item)
score += 30
end
end
#---------------------------------------------------------------------------
when "0F6"
if user.recycleItem==0 || user.item!=0
score -= 80
elsif user.recycleItem!=0
score += 30
end
#---------------------------------------------------------------------------
when "0F7"
if user.item==0 || !user.itemActive? ||
user.unlosableItem?(user.item) || pbIsPokeBall?(user.item)
score -= 90
end
#---------------------------------------------------------------------------
when "0F8"
score -= 90 if target.effects[PBEffects::Embargo]>0
#---------------------------------------------------------------------------
when "0F9"
if @battle.field.effects[PBEffects::MagicRoom]>0
score -= 90
else
score += 30 if user.item==0 && target.item!=0
end
#---------------------------------------------------------------------------
when "0FA"
score -= 25
#---------------------------------------------------------------------------
when "0FB"
score -= 30
#---------------------------------------------------------------------------
when "0FC"
score -= 40
#---------------------------------------------------------------------------
when "0FD"
score -= 30
if target.pbCanParalyze?(user,false)
score += 30
if skill>=PBTrainerAI.mediumSkill
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
if aspeed<ospeed
score += 30
elsif aspeed>ospeed
score -= 40
end
end
if skill>=PBTrainerAI.highSkill
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET])
end
end
#---------------------------------------------------------------------------
when "0FE"
score -= 30
if target.pbCanBurn?(user,false)
score += 30
if skill>=PBTrainerAI.highSkill
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET,:FLAREBOOST])
end
end
#---------------------------------------------------------------------------
when "0FF"
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 90
elsif @battle.pbWeather==PBWeather::Sun
score -= 90
else
user.eachMove do |m|
next if !m.damagingMove? || !isConst?(m.type,PBTypes,:FIRE)
score += 20
end
end
#---------------------------------------------------------------------------
end
return score
end
end

View File

@@ -1,498 +0,0 @@
class PokeBattle_AI
alias __e__pbGetMoveScoreFunctionCode pbGetMoveScoreFunctionCode
#=============================================================================
# Get a score for the given move based on its effect
#=============================================================================
def pbGetMoveScoreFunctionCode(score,move,user,target,skill=100)
score = __e__pbGetMoveScoreFunctionCode(score,move,user,target,skill)
case move.function
#---------------------------------------------------------------------------
when "100"
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 90
elsif @battle.pbWeather==PBWeather::Rain
score -= 90
else
user.eachMove do |m|
next if !m.damagingMove? || !isConst?(m.type,PBTypes,:WATER)
score += 20
end
end
#---------------------------------------------------------------------------
when "101"
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 90
elsif @battle.pbWeather==PBWeather::Sandstorm
score -= 90
end
#---------------------------------------------------------------------------
when "102"
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 90
elsif @battle.pbWeather==PBWeather::Hail
score -= 90
end
#---------------------------------------------------------------------------
when "103"
if user.pbOpposingSide.effects[PBEffects::Spikes]>=3
score -= 90
else
canChoose = false
user.eachOpposing do |b|
next if !@battle.pbCanChooseNonActive?(b.index)
canChoose = true
break
end
if !canChoose
# Opponent can't switch in any Pokemon
score -= 90
else
score += 10*@battle.pbAbleNonActiveCount(user.idxOpposingSide)
score += [40,26,13][user.pbOpposingSide.effects[PBEffects::Spikes]]
end
end
#---------------------------------------------------------------------------
when "104"
if user.pbOpposingSide.effects[PBEffects::ToxicSpikes]>=2
score -= 90
else
canChoose = false
user.eachOpposing do |b|
next if !@battle.pbCanChooseNonActive?(b.index)
canChoose = true
break
end
if !canChoose
# Opponent can't switch in any Pokemon
score -= 90
else
score += 8*@battle.pbAbleNonActiveCount(user.idxOpposingSide)
score += [26,13][user.pbOpposingSide.effects[PBEffects::ToxicSpikes]]
end
end
#---------------------------------------------------------------------------
when "105"
if user.pbOpposingSide.effects[PBEffects::StealthRock]
score -= 90
else
canChoose = false
user.eachOpposing do |b|
next if !@battle.pbCanChooseNonActive?(b.index)
canChoose = true
break
end
if !canChoose
# Opponent can't switch in any Pokemon
score -= 90
else
score += 10*@battle.pbAbleNonActiveCount(user.idxOpposingSide)
end
end
#---------------------------------------------------------------------------
when "106"
#---------------------------------------------------------------------------
when "107"
#---------------------------------------------------------------------------
when "108"
#---------------------------------------------------------------------------
when "109"
#---------------------------------------------------------------------------
when "10A"
score += 20 if user.pbOpposingSide.effects[PBEffects::AuroraVeil]>0
score += 20 if user.pbOpposingSide.effects[PBEffects::Reflect]>0
score += 20 if user.pbOpposingSide.effects[PBEffects::LightScreen]>0
#---------------------------------------------------------------------------
when "10B"
score += 10*(user.stages[PBStats::ACCURACY]-target.stages[PBStats::EVASION])
#---------------------------------------------------------------------------
when "10C"
if user.effects[PBEffects::Substitute]>0
score -= 90
elsif user.hp<=user.totalhp/4
score -= 90
end
#---------------------------------------------------------------------------
when "10D"
if user.pbHasType?(:GHOST)
if target.effects[PBEffects::Curse]
score -= 90
elsif user.hp<=user.totalhp/2
if @battle.pbAbleNonActiveCount(user.idxOwnSide)==0
score -= 90
else
score -= 50
score -= 30 if @battle.switchStyle
end
end
else
avg = user.stages[PBStats::SPEED]*10
avg -= user.stages[PBStats::ATTACK]*10
avg -= user.stages[PBStats::DEFENSE]*10
score += avg/3
end
#---------------------------------------------------------------------------
when "10E"
score -= 40
#---------------------------------------------------------------------------
when "10F"
if target.effects[PBEffects::Nightmare] ||
target.effects[PBEffects::Substitute]>0
score -= 90
elsif !target.asleep?
score -= 90
else
score -= 90 if target.statusCount<=1
score += 50 if target.statusCount>3
end
#---------------------------------------------------------------------------
when "110"
score += 30 if user.effects[PBEffects::Trapping]>0
score += 30 if user.effects[PBEffects::LeechSeed]>=0
if @battle.pbAbleNonActiveCount(user.idxOwnSide)>0
score += 80 if user.pbOwnSide.effects[PBEffects::Spikes]>0
score += 80 if user.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
score += 80 if user.pbOwnSide.effects[PBEffects::StealthRock]
end
#---------------------------------------------------------------------------
when "111"
if @battle.positions[target.index].effects[PBEffects::FutureSightCounter]>0
score -= 100
elsif @battle.pbAbleNonActiveCount(user.idxOwnSide)==0
# Future Sight tends to be wasteful if down to last Pokemon
score -= 70
end
#---------------------------------------------------------------------------
when "112"
avg = 0
avg -= user.stages[PBStats::DEFENSE]*10
avg -= user.stages[PBStats::SPDEF]*10
score += avg/2
if user.effects[PBEffects::Stockpile]>=3
score -= 80
else
# More preferable if user also has Spit Up/Swallow
score += 20 if user.pbHasMoveFunction?("113","114") # Spit Up, Swallow
end
#---------------------------------------------------------------------------
when "113"
score -= 100 if user.effects[PBEffects::Stockpile]==0
#---------------------------------------------------------------------------
when "114"
if user.effects[PBEffects::Stockpile]==0
score -= 90
elsif user.hp==user.totalhp
score -= 90
else
mult = [0,25,50,100][user.effects[PBEffects::Stockpile]]
score += mult
score -= user.hp*mult*2/user.totalhp
end
#---------------------------------------------------------------------------
when "115"
score += 50 if target.effects[PBEffects::HyperBeam]>0
score -= 35 if target.hp<=target.totalhp/2 # If target is weak, no
score -= 70 if target.hp<=target.totalhp/4 # need to risk this move
#---------------------------------------------------------------------------
when "116"
#---------------------------------------------------------------------------
when "117"
hasAlly = false
user.eachAlly do |b|
hasAlly = true
break
end
score -= 90 if !hasAlly
#---------------------------------------------------------------------------
when "118"
if @battle.field.effects[PBEffects::Gravity]>0
score -= 90
elsif skill>=PBTrainerAI.mediumSkill
score -= 30
score -= 20 if user.effects[PBEffects::SkyDrop]>=0
score -= 20 if user.effects[PBEffects::MagnetRise]>0
score -= 20 if user.effects[PBEffects::Telekinesis]>0
score -= 20 if user.pbHasType?(:FLYING)
score -= 20 if user.hasActiveAbility?(:LEVITATE)
score -= 20 if user.hasActiveItem?(:AIRBALLOON)
score += 20 if target.effects[PBEffects::SkyDrop]>=0
score += 20 if target.effects[PBEffects::MagnetRise]>0
score += 20 if target.effects[PBEffects::Telekinesis]>0
score += 20 if target.inTwoTurnAttack?("0C9","0CC","0CE") # Fly, Bounce, Sky Drop
score += 20 if target.pbHasType?(:FLYING)
score += 20 if target.hasActiveAbility?(:LEVITATE)
score += 20 if target.hasActiveItem?(:AIRBALLOON)
end
#---------------------------------------------------------------------------
when "119"
if user.effects[PBEffects::MagnetRise]>0 ||
user.effects[PBEffects::Ingrain] ||
user.effects[PBEffects::SmackDown]
score -= 90
end
#---------------------------------------------------------------------------
when "11A"
if target.effects[PBEffects::Telekinesis]>0 ||
target.effects[PBEffects::Ingrain] ||
target.effects[PBEffects::SmackDown]
score -= 90
end
#---------------------------------------------------------------------------
when "11B"
#---------------------------------------------------------------------------
when "11C"
if skill>=PBTrainerAI.mediumSkill
score += 20 if target.effects[PBEffects::MagnetRise]>0
score += 20 if target.effects[PBEffects::Telekinesis]>0
score += 20 if target.inTwoTurnAttack?("0C9","0CC") # Fly, Bounce
score += 20 if target.pbHasType?(:FLYING)
score += 20 if target.hasActiveAbility?(:LEVITATE)
score += 20 if target.hasActiveItem?(:AIRBALLOON)
end
#---------------------------------------------------------------------------
when "11D"
#---------------------------------------------------------------------------
when "11E"
#---------------------------------------------------------------------------
when "11F"
#---------------------------------------------------------------------------
when "120"
#---------------------------------------------------------------------------
when "121"
#---------------------------------------------------------------------------
when "122"
#---------------------------------------------------------------------------
when "123"
if !target.pbHasType?(user.type1) &&
!target.pbHasType?(user.type2)
score -= 90
end
#---------------------------------------------------------------------------
when "124"
#---------------------------------------------------------------------------
when "125"
#---------------------------------------------------------------------------
when "126"
score += 20 # Shadow moves are more preferable
#---------------------------------------------------------------------------
when "127"
score += 20 # Shadow moves are more preferable
if target.pbCanParalyze?(user,false)
score += 30
if skill>=PBTrainerAI.mediumSkill
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
if aspeed<ospeed
score += 30
elsif aspeed>ospeed
score -= 40
end
end
if skill>=PBTrainerAI.highSkill
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET])
end
end
#---------------------------------------------------------------------------
when "128"
score += 20 # Shadow moves are more preferable
if target.pbCanBurn?(user,false)
score += 30
if skill>=PBTrainerAI.highSkill
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET,:FLAREBOOST])
end
end
#---------------------------------------------------------------------------
when "129"
score += 20 # Shadow moves are more preferable
if target.pbCanFreeze?(user,false)
score += 30
if skill>=PBTrainerAI.highSkill
score -= 20 if target.hasActiveAbility?(:MARVELSCALE)
end
end
#---------------------------------------------------------------------------
when "12A"
score += 20 # Shadow moves are more preferable
if target.pbCanConfuse?(user,false)
score += 30
else
if skill>=PBTrainerAI.mediumSkill
score -= 90
end
end
#---------------------------------------------------------------------------
when "12B"
score += 20 # Shadow moves are more preferable
if !target.pbCanLowerStatStage?(PBStats::DEFENSE,user)
score -= 90
else
score += 40 if user.turnCount==0
score += target.stages[PBStats::DEFENSE]*20
end
#---------------------------------------------------------------------------
when "12C"
score += 20 # Shadow moves are more preferable
if !target.pbCanLowerStatStage?(PBStats::EVASION,user)
score -= 90
else
score += target.stages[PBStats::EVASION]*15
end
#---------------------------------------------------------------------------
when "12D"
score += 20 # Shadow moves are more preferable
#---------------------------------------------------------------------------
when "12E"
score += 20 # Shadow moves are more preferable
score += 20 if target.hp>=target.totalhp/2
score -= 20 if user.hp<user.hp/2
#---------------------------------------------------------------------------
when "12F"
score += 20 # Shadow moves are more preferable
score -= 110 if target.effects[PBEffects::MeanLook]>=0
#---------------------------------------------------------------------------
when "130"
score += 20 # Shadow moves are more preferable
score -= 40
#---------------------------------------------------------------------------
when "131"
score += 20 # Shadow moves are more preferable
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 90
elsif @battle.pbWeather==PBWeather::ShadowSky
score -= 90
end
#---------------------------------------------------------------------------
when "132"
score += 20 # Shadow moves are more preferable
if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0 ||
target.pbOwnSide.effects[PBEffects::Reflect]>0 ||
target.pbOwnSide.effects[PBEffects::LightScreen]>0 ||
target.pbOwnSide.effects[PBEffects::Safeguard]>0
score += 30
score -= 90 if user.pbOwnSide.effects[PBEffects::AuroraVeil]>0 ||
user.pbOwnSide.effects[PBEffects::Reflect]>0 ||
user.pbOwnSide.effects[PBEffects::LightScreen]>0 ||
user.pbOwnSide.effects[PBEffects::Safeguard]>0
else
score -= 110
end
#---------------------------------------------------------------------------
when "133", "134"
score -= 95
score = 0 if skill>=PBTrainerAI.highSkill
#---------------------------------------------------------------------------
when "135"
if target.pbCanFreeze?(user,false)
score += 30
if skill>=PBTrainerAI.highSkill
score -= 20 if target.hasActiveAbility?(:MARVELSCALE)
end
end
#---------------------------------------------------------------------------
when "136"
score += 20 if user.stages[PBStats::DEFENSE]<0
#---------------------------------------------------------------------------
when "137"
hasEffect = user.statStageAtMax?(PBStats::DEFENSE) &&
user.statStageAtMax?(PBStats::SPDEF)
user.eachAlly do |b|
next if b.statStageAtMax?(PBStats::DEFENSE) && b.statStageAtMax?(PBStats::SPDEF)
hasEffect = true
score -= b.stages[PBStats::DEFENSE]*10
score -= b.stages[PBStats::SPDEF]*10
end
if hasEffect
score -= user.stages[PBStats::DEFENSE]*10
score -= user.stages[PBStats::SPDEF]*10
else
score -= 90
end
#---------------------------------------------------------------------------
when "138"
if target.statStageAtMax?(PBStats::SPDEF)
score -= 90
else
score -= target.stages[PBStats::SPDEF]*10
end
#---------------------------------------------------------------------------
when "139"
if !target.pbCanLowerStatStage?(PBStats::ATTACK,user)
score -= 90
else
score += target.stages[PBStats::ATTACK]*20
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
#---------------------------------------------------------------------------
when "13A"
avg = target.stages[PBStats::ATTACK]*10
avg += target.stages[PBStats::SPATK]*10
score += avg/2
#---------------------------------------------------------------------------
when "13B"
if !user.isSpecies?(:HOOPA) || user.form!=1
score -= 100
else
score += 20 if target.stages[PBStats::DEFENSE]>0
end
#---------------------------------------------------------------------------
when "13C"
score += 20 if target.stages[PBStats::SPATK]>0
#---------------------------------------------------------------------------
when "13D"
if !target.pbCanLowerStatStage?(PBStats::SPATK,user)
score -= 90
else
score += 40 if user.turnCount==0
score += target.stages[PBStats::SPATK]*20
end
#---------------------------------------------------------------------------
when "13E"
count = 0
@battle.eachBattler do |b|
if b.pbHasType?(:GRASS) && !b.airborne? &&
(!b.statStageAtMax?(PBStats::ATTACK) || !b.statStageAtMax?(PBStats::SPATK))
count += 1
if user.opposes?(b)
score -= 20
else
score -= user.stages[PBStats::ATTACK]*10
score -= user.stages[PBStats::SPATK]*10
end
end
end
score -= 95 if count==0
#---------------------------------------------------------------------------
when "13F"
count = 0
@battle.eachBattler do |b|
if b.pbHasType?(:GRASS) && !b.statStageAtMax?(PBStats::DEFENSE)
count += 1
if user.opposes?(b)
score -= 20
else
score -= user.stages[PBStats::DEFENSE]*10
end
end
end
score -= 95 if count==0
#---------------------------------------------------------------------------
end
return score
end
end

View File

@@ -1,409 +0,0 @@
class PokeBattle_AI
alias __f__pbGetMoveScoreFunctionCode pbGetMoveScoreFunctionCode
#=============================================================================
# Get a score for the given move based on its effect
#=============================================================================
def pbGetMoveScoreFunctionCode(score,move,user,target,skill=100)
score = __f__pbGetMoveScoreFunctionCode(score,move,user,target,skill)
case move.function
#---------------------------------------------------------------------------
when "140"
count=0
@battle.eachBattler do |b|
if b.poisoned? &&
(!b.statStageAtMin?(PBStats::ATTACK) ||
!b.statStageAtMin?(PBStats::SPATK) ||
!b.statStageAtMin?(PBStats::SPEED))
count += 1
if user.opposes?(b)
score += user.stages[PBStats::ATTACK]*10
score += user.stages[PBStats::SPATK]*10
score += user.stages[PBStats::SPEED]*10
else
score -= 20
end
end
end
score -= 95 if count==0
#---------------------------------------------------------------------------
when "141"
if target.effects[PBEffects::Substitute]>0
score -= 90
else
numpos = 0; numneg = 0
PBStats.eachBattleStat do |s|
numpos += target.stages[s] if target.stages[s]>0
numneg += target.stages[s] if target.stages[s]<0
end
if numpos!=0 || numneg!=0
score += (numpos-numneg)*10
else
score -= 95
end
end
#---------------------------------------------------------------------------
when "142"
score -= 90 if target.pbHasType?(:GHOST)
#---------------------------------------------------------------------------
when "143"
score -= 90 if target.pbHasType?(:GRASS)
#---------------------------------------------------------------------------
when "144"
#---------------------------------------------------------------------------
when "145"
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
score -= 90 if aspeed>ospeed
#---------------------------------------------------------------------------
when "146"
#---------------------------------------------------------------------------
when "147"
#---------------------------------------------------------------------------
when "148"
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
if aspeed>ospeed
score -= 90
else
score += 30 if target.pbHasMoveType?(:FIRE)
end
#---------------------------------------------------------------------------
when "149"
if user.turnCount==0
score += 30
else
score -= 90 # Because it will fail here
score = 0 if skill>=PBTrainerAI.bestSkill
end
#---------------------------------------------------------------------------
when "14A"
#---------------------------------------------------------------------------
when "14B", "14C"
if user.effects[PBEffects::ProtectRate]>1 ||
target.effects[PBEffects::HyperBeam]>0
score -= 90
else
if skill>=PBTrainerAI.mediumSkill
score -= user.effects[PBEffects::ProtectRate]*40
end
score += 50 if user.turnCount==0
score += 30 if target.effects[PBEffects::TwoTurnAttack]>0
end
#---------------------------------------------------------------------------
when "14D"
#---------------------------------------------------------------------------
when "14E"
if user.statStageAtMax?(PBStats::SPATK) &&
user.statStageAtMax?(PBStats::SPDEF) &&
user.statStageAtMax?(PBStats::SPEED)
score -= 90
else
score -= user.stages[PBStats::SPATK]*10 # Only *10 isntead of *20
score -= user.stages[PBStats::SPDEF]*10 # because two-turn attack
score -= user.stages[PBStats::SPEED]*10
if skill>=PBTrainerAI.mediumSkill
hasSpecialAttack = false
user.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecialAttack = true
break
end
if hasSpecialAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
if skill>=PBTrainerAI.highSkill
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
score += 30 if aspeed<ospeed && aspeed*2>ospeed
end
end
#---------------------------------------------------------------------------
when "14F"
if skill>=PBTrainerAI.highSkill && target.hasActiveAbility?(:LIQUIDOOZE)
score -= 80
else
score += 40 if user.hp<=user.totalhp/2
end
#---------------------------------------------------------------------------
when "150"
score += 20 if !user.statStageAtMax?(PBStats::ATTACK) && target.hp<=target.totalhp/4
#---------------------------------------------------------------------------
when "151"
avg = target.stages[PBStats::ATTACK]*10
avg += target.stages[PBStats::SPATK]*10
score += avg/2
#---------------------------------------------------------------------------
when "152"
#---------------------------------------------------------------------------
when "153"
score -= 95 if target.pbOwnSide.effects[PBEffects::StickyWeb]
#---------------------------------------------------------------------------
when "154"
#---------------------------------------------------------------------------
when "155"
#---------------------------------------------------------------------------
when "156"
#---------------------------------------------------------------------------
when "157"
score -= 90
#---------------------------------------------------------------------------
when "158"
score -= 90 if !user.belched?
#---------------------------------------------------------------------------
when "159"
if !target.pbCanPoison?(user,false) && !target.pbCanLowerStatStage?(PBStats::SPEED,user)
score -= 90
else
if target.pbCanPoison?(user,false)
score += 30
if skill>=PBTrainerAI.mediumSkill
score += 30 if target.hp<=target.totalhp/4
score += 50 if target.hp<=target.totalhp/8
score -= 40 if target.effects[PBEffects::Yawn]>0
end
if skill>=PBTrainerAI.highSkill
score += 10 if pbRoughStat(target,PBStats::DEFENSE,skill)>100
score += 10 if pbRoughStat(target,PBStats::SPDEF,skill)>100
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:TOXICBOOST])
end
end
if target.pbCanLowerStatStage?(PBStats::SPEED,user)
score += target.stages[PBStats::SPEED]*10
if skill>=PBTrainerAI.highSkill
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
score += 30 if aspeed<ospeed && aspeed*2>ospeed
end
end
end
#---------------------------------------------------------------------------
when "15A"
if target.opposes?(user)
score -= 40 if target.status==PBStatuses::BURN
else
score += 40 if target.status==PBStatuses::BURN
end
#---------------------------------------------------------------------------
when "15B"
if target.status==PBStatuses::NONE
score -= 90
elsif user.hp==user.totalhp && target.opposes?(user)
score -= 90
else
score += (user.totalhp-user.hp)*50/user.totalhp
score -= 30 if target.opposes?(user)
end
#---------------------------------------------------------------------------
when "15C"
hasEffect = user.statStageAtMax?(PBStats::ATTACK) &&
user.statStageAtMax?(PBStats::SPATK)
user.eachAlly do |b|
next if b.statStageAtMax?(PBStats::ATTACK) && b.statStageAtMax?(PBStats::SPATK)
hasEffect = true
score -= b.stages[PBStats::ATTACK]*10
score -= b.stages[PBStats::SPATK]*10
end
if hasEffect
score -= user.stages[PBStats::ATTACK]*10
score -= user.stages[PBStats::SPATK]*10
else
score -= 90
end
#---------------------------------------------------------------------------
when "15D"
numStages = 0
PBStats.eachBattleStat do |s|
next if target.stages[s]<=0
numStages += target.stages[s]
end
score += numStages*20
#---------------------------------------------------------------------------
when "15E"
if user.effects[PBEffects::LaserFocus]>0
score -= 90
else
score += 40
end
#---------------------------------------------------------------------------
when "15F"
score += user.stages[PBStats::DEFENSE]*10
#---------------------------------------------------------------------------
when "160"
if target.statStageAtMin?(PBStats::ATTACK)
score -= 90
else
if target.pbCanLowerStatStage?(PBStats::ATTACK,user)
score += target.stages[PBStats::ATTACK]*20
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill>=PBTrainerAI.highSkill
score -= 90
end
end
end
score += (user.totalhp-user.hp)*50/user.totalhp
end
#---------------------------------------------------------------------------
when "161"
if skill>=PBTrainerAI.mediumSkill
if user.speed>target.speed
score += 50
else
score -= 70
end
end
#---------------------------------------------------------------------------
when "162"
score -= 90 if !user.pbHasType?(:FIRE)
#---------------------------------------------------------------------------
when "163"
#---------------------------------------------------------------------------
when "164"
#---------------------------------------------------------------------------
when "165"
if skill>=PBTrainerAI.mediumSkill
userSpeed = pbRoughStat(user,PBStats::SPEED,skill)
targetSpeed = pbRoughStat(target,PBStats::SPEED,skill)
if userSpeed<targetSpeed
score += 30
end
else
score += 30
end
#---------------------------------------------------------------------------
when "166"
#---------------------------------------------------------------------------
when "167"
if user.pbOwnSide.effects[PBEffects::AuroraVeil]>0 || @battle.pbWeather!=PBWeather::Hail
score -= 90
else
score += 40
end
#---------------------------------------------------------------------------
when "168"
if user.effects[PBEffects::ProtectRate]>1 ||
target.effects[PBEffects::HyperBeam]>0
score -= 90
else
if skill>=PBTrainerAI.mediumSkill
score -= user.effects[PBEffects::ProtectRate]*40
end
score += 50 if user.turnCount==0
score += 30 if target.effects[PBEffects::TwoTurnAttack]>0
score += 20 # Because of possible poisoning
end
#---------------------------------------------------------------------------
when "169"
#---------------------------------------------------------------------------
when "16A"
hasAlly = false
target.eachAlly do |b|
hasAlly = true
break
end
score -= 90 if !hasAlly
#---------------------------------------------------------------------------
when "16B"
if skill>=PBTrainerAI.mediumSkill
if target.lastRegularMoveUsed<0 ||
!target.pbHasMove?(target.lastRegularMoveUsed) ||
target.usingMultiTurnAttack?
score -= 90
else
# Without lots of code here to determine good/bad moves and relative
# speeds, using this move is likely to just be a waste of a turn
score -= 50
end
end
#---------------------------------------------------------------------------
when "16C"
if target.effects[PBEffects::ThroatChop]==0 && skill>=PBTrainerAI.highSkill
hasSoundMove = false
user.eachMove do |m|
next if !m.soundMove?
hasSoundMove = true
break
end
score += 40 if hasSoundMove
end
#---------------------------------------------------------------------------
when "16D"
if user.hp==user.totalhp || (skill>=PBTrainerAI.mediumSkill && !user.canHeal?)
score -= 90
else
score += 50
score -= user.hp*100/user.totalhp
score += 30 if @battle.pbWeather==PBWeather::Sandstorm
end
#---------------------------------------------------------------------------
when "16E"
if user.hp==user.totalhp || (skill>=PBTrainerAI.mediumSkill && !user.canHeal?)
score -= 90
else
score += 50
score -= user.hp*100/user.totalhp
if skill>=PBTrainerAI.mediumSkill
score += 30 if @battle.field.terrain==PBBattleTerrains::Grassy
end
end
#---------------------------------------------------------------------------
when "16F"
if !target.opposes?(user)
if target.hp==target.totalhp || (skill>=PBTrainerAI.mediumSkill && !target.canHeal?)
score -= 90
else
score += 50
score -= target.hp*100/target.totalhp
end
end
#---------------------------------------------------------------------------
when "170"
reserves = @battle.pbAbleNonActiveCount(user.idxOwnSide)
foes = @battle.pbAbleNonActiveCount(user.idxOpposingSide)
if @battle.pbCheckGlobalAbility(:DAMP)
score -= 100
elsif skill>=PBTrainerAI.mediumSkill && reserves==0 && foes>0
score -= 100 # don't want to lose
elsif skill>=PBTrainerAI.highSkill && reserves==0 && foes==0
score += 80 # want to draw
else
score -= (user.total.hp-user.hp)*75/user.totalhp
end
#---------------------------------------------------------------------------
when "171"
if skill>=PBTrainerAI.mediumSkill
hasPhysicalAttack = false
target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
score -= 80 if !hasPhysicalAttack
end
#---------------------------------------------------------------------------
when "172"
score += 20 # Because of possible burning
#---------------------------------------------------------------------------
when "173"
#---------------------------------------------------------------------------
when "174"
score -= 90 if user.turnCount>0 || user.lastRoundMoved>=0
#---------------------------------------------------------------------------
when "175"
score += 30 if target.effects[PBEffects::Minimize]
#---------------------------------------------------------------------------
end
return score
end
end

View File

@@ -1,661 +0,0 @@
class PokeBattle_AI
#=============================================================================
#
#=============================================================================
def pbTargetsMultiple?(move,user)
numTargets = 0
case move.pbTarget(user)
when PBTargets::AllNearFoes
@battle.eachOtherSideBattler(user) { |b| numTargets += 1 if b.near?(user) }
return numTargets>1
when PBTargets::AllNearOthers
@battle.eachBattler { |b| numTargets += 1 if b.near?(user) }
return numTargets>1
when PBTargets::UserAndAllies
@battle.eachSameSideBattler(user) { |_b| numTargets += 1 }
return numTargets>1
when PBTargets::AllFoes
@battle.eachOtherSideBattler(user) { |_b| numTargets += 1 }
return numTargets>1
when PBTargets::AllBattlers
@battle.eachBattler { |_b| numTargets += 1 }
return numTargets>1
end
return false
end
#=============================================================================
# Move's type effectiveness
#=============================================================================
def pbCalcTypeModSingle(moveType,defType,user,target)
ret = PBTypes.getEffectiveness(moveType,defType)
# Ring Target
if target.hasActiveItem?(:RINGTARGET)
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if PBTypes.ineffective?(moveType,defType)
end
# Foresight
if user.hasActiveAbility?(:SCRAPPY) || target.effects[PBEffects::Foresight]
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :GHOST &&
PBTypes.ineffective?(moveType,defType)
end
# Miracle Eye
if target.effects[PBEffects::MiracleEye]
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :DARK &&
PBTypes.ineffective?(moveType,defType)
end
# Delta Stream's weather
if @battle.pbWeather==PBWeather::StrongWinds
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :FLYING &&
PBTypes.superEffective?(moveType,defType)
end
# Grounded Flying-type Pokémon become susceptible to Ground moves
if !target.airborne?
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :FLYING && moveType == :GROUND
end
return ret
end
def pbCalcTypeMod(moveType,user,target)
return PBTypeEffectiveness::NORMAL_EFFECTIVE if moveType<0
return PBTypeEffectiveness::NORMAL_EFFECTIVE if moveType == :GROUND &&
target.pbHasType?(:FLYING) && target.hasActiveItem?(:IRONBALL)
# Determine types
tTypes = target.pbTypes(true)
# Get effectivenesses
typeMods = [PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE] * 3 # 3 types max
tTypes.each_with_index do |type,i|
typeMods[i] = pbCalcTypeModSingle(moveType,type,user,target)
end
# Multiply all effectivenesses together
ret = 1
typeMods.each { |m| ret *= m }
return ret
end
# For switching. Determines the effectiveness of a potential switch-in against
# an opposing battler.
def pbCalcTypeModPokemon(battlerThis,_battlerOther)
mod1 = PBTypes.getCombinedEffectiveness(battlerThis.type1,target.type1,target.type2)
mod2 = PBTypeEffectiveness::NORMAL_EFFECTIVE
if battlerThis.type1!=battlerThis.type2
mod2 = PBTypes.getCombinedEffectiveness(battlerThis.type2,target.type1,target.type2)
end
return mod1*mod2 # Normal effectiveness is 64 here
end
#=============================================================================
# Immunity to a move because of the target's ability, item or other effects
#=============================================================================
def pbCheckMoveImmunity(score,move,user,target,skill)
type = pbRoughType(move,user,skill)
typeMod = pbCalcTypeMod(type,user,target)
# Type effectiveness
return true if PBTypeEffectiveness.ineffective?(typeMod) || score<=0
# Immunity due to ability/item/other effects
if skill>=PBTrainerAI.mediumSkill
case move.type
when :GROUND
return true if target.airborne? && !move.hitsFlyingTargets?
when :FIRE
return true if target.hasActiveAbility?(:FLASHFIRE)
when :WATER
return true if target.hasActiveAbility?([:DRYSKIN,:STORMDRAIN,:WATERABSORB])
when :GRASS
return true if target.hasActiveAbility?(:SAPSIPPER)
when :ELECTRIC
return true if target.hasActiveAbility?([:LIGHTNINGROD,:MOTORDRIVE,:VOLTABSORB])
end
return true if PBTypeEffectiveness.notVeryEffective?(typeMod) &&
target.hasActiveAbility?(:WONDERGUARD)
return true if move.damagingMove? && user.index!=target.index && !target.opposes?(user) &&
target.hasActiveAbility?(:TELEPATHY)
return true if move.canMagicCoat? && target.hasActiveAbility?(:MAGICBOUNCE) &&
target.opposes?(user)
return true if move.soundMove? && target.hasActiveAbility?(:SOUNDPROOF)
return true if move.bombMove? && target.hasActiveAbility?(:BULLETPROOF)
if move.powderMove?
return true if target.pbHasType?(:GRASS)
return true if target.hasActiveAbility?(:OVERCOAT)
return true if target.hasActiveItem?(:SAFETYGOGGLES)
end
return true if target.effects[PBEffects::Substitute]>0 && move.statusMove? &&
!move.ignoresSubstitute?(user) && user.index!=target.index
return true if NEWEST_BATTLE_MECHANICS && user.hasActiveAbility?(:PRANKSTER) &&
target.pbHasType?(:DARK) && target.opposes?(user)
return true if move.priority>0 && @battle.field.terrain==PBBattleTerrains::Psychic &&
target.affectedByTerrain? && target.opposes?(user)
end
return false
end
#=============================================================================
# Get approximate properties for a battler
#=============================================================================
def pbRoughType(move,user,skill)
ret = move.type
if skill>=PBTrainerAI.highSkill
ret = move.pbCalcType(user)
end
return ret
end
def pbRoughStat(battler,stat,skill)
return battler.pbSpeed if skill>=PBTrainerAI.highSkill && stat==PBStats::SPEED
stageMul = [2,2,2,2,2,2, 2, 3,4,5,6,7,8]
stageDiv = [8,7,6,5,4,3, 2, 2,2,2,2,2,2]
stage = battler.stages[stat]+6
value = 0
case stat
when PBStats::ATTACK then value = battler.attack
when PBStats::DEFENSE then value = battler.defense
when PBStats::SPATK then value = battler.spatk
when PBStats::SPDEF then value = battler.spdef
when PBStats::SPEED then value = battler.speed
end
return (value.to_f*stageMul[stage]/stageDiv[stage]).floor
end
#=============================================================================
# Get a better move's base damage value
#=============================================================================
def pbMoveBaseDamage(move,user,target,skill)
baseDmg = move.baseDamage
baseDmg = 60 if baseDmg==1
return baseDmg if skill<PBTrainerAI.mediumSkill
# Covers all function codes which have their own def pbBaseDamage
case move.function
when "010" # Stomp
baseDmg *= 2 if skill>=PBTrainerAI.mediumSkill && target.effects[PBEffects::Minimize]
# Sonic Boom, Dragon Rage, Super Fang, Night Shade, Endeavor
when "06A", "06B", "06C", "06D", "06E"
baseDmg = move.pbFixedDamage(user,target)
when "06F" # Psywave
baseDmg = user.level
when "070" # OHKO
baseDmg = 200
when "071", "072", "073" # Counter, Mirror Coat, Metal Burst
baseDmg = 60
when "075", "076", "0D0", "12D" # Surf, Earthquake, Whirlpool, Shadow Storm
baseDmg = move.pbModifyDamage(baseDmg,user,target)
# Gust, Twister, Venoshock, Smelling Salts, Wake-Up Slap, Facade, Hex, Brine,
# Retaliate, Weather Ball, Return, Frustration, Eruption, Crush Grip,
# Stored Power, Punishment, Hidden Power, Fury Cutter, Echoed Voice,
# Trump Card, Flail, Electro Ball, Low Kick, Fling, Spit Up
when "077", "078", "07B", "07C", "07D", "07E", "07F", "080", "085", "087",
"089", "08A", "08B", "08C", "08E", "08F", "090", "091", "092", "097",
"098", "099", "09A", "0F7", "113"
baseDmg = move.pbBaseDamage(baseDmg,user,target)
when "086" # Acrobatics
baseDmg *= 2 if !user.item || user.hasActiveItem?(:FLYINGGEM)
when "08D" # Gyro Ball
targetSpeed = pbRoughStat(target,PBStats::SPEED,skill)
userSpeed = pbRoughStat(user,PBStats::SPEED,skill)
baseDmg = [[(25*targetSpeed/userSpeed).floor,150].min,1].max
when "094" # Present
baseDmg = 50
when "095" # Magnitude
baseDmg = 71
baseDmg *= 2 if target.inTwoTurnAttack?("0CA") # Dig
when "096" # Natural Gift
baseDmg = move.pbNaturalGiftBaseDamage(user.item_id)
when "09B" # Heavy Slam
baseDmg = move.pbBaseDamage(baseDmg,user,target)
baseDmg *= 2 if NEWEST_BATTLE_MECHANICS && skill>=PBTrainerAI.mediumSkill &&
target.effects[PBEffects::Minimize]
when "0A0", "0BD", "0BE" # Frost Breath, Double Kick, Twineedle
baseDmg *= 2
when "0BF" # Triple Kick
baseDmg *= 6 # Hits do x1, x2, x3 baseDmg in turn, for x6 in total
when "0C0" # Fury Attack
if user.hasActiveAbility?(:SKILLLINK)
baseDmg *= 5
else
baseDmg = (baseDmg*19/6).floor # Average damage dealt
end
when "0C1" # Beat Up
mult = 0
@battle.eachInTeamFromBattlerIndex(user.index) do |pkmn,_i|
mult += 1 if pkmn && pkmn.able? && pkmn.status==PBStatuses::NONE
end
baseDmg *= mult
when "0C4" # Solar Beam
baseDmg = move.pbBaseDamageMultiplier(baseDmg,user,target)
when "0D3" # Rollout
baseDmg *= 2 if user.effects[PBEffects::DefenseCurl]
when "0D4" # Bide
baseDmg = 40
when "0E1" # Final Gambit
baseDmg = user.hp
when "144" # Flying Press
if GameData::Type.exists?(:FLYING)
if skill>=PBTrainerAI.highSkill
targetTypes = target.pbTypes(true)
mult = PBTypes.getCombinedEffectiveness(:FLYING,
targetTypes[0],targetTypes[1],targetTypes[2])
baseDmg = (baseDmg.to_f*mult/PBTypeEffectiveness::NORMAL_EFFECTIVE).round
else
mult = PBTypes.getCombinedEffectiveness(:FLYING,
target.type1,target.type2,target.effects[PBEffects::Type3])
baseDmg = (baseDmg.to_f*mult/PBTypeEffectiveness::NORMAL_EFFECTIVE).round
end
end
baseDmg *= 2 if skill>=PBTrainerAI.mediumSkill && target.effects[PBEffects::Minimize]
when "166" # Stomping Tantrum
baseDmg *= 2 if user.lastRoundMoveFailed
when "175" # Double Iron Bash
baseDmg *= 2
baseDmg *= 2 if skill>=PBTrainerAI.mediumSkill && target.effects[PBEffects::Minimize]
end
return baseDmg
end
#=============================================================================
# Damage calculation
#=============================================================================
def pbRoughDamage(move,user,target,skill,baseDmg)
# Fixed damage moves
return baseDmg if move.is_a?(PokeBattle_FixedDamageMove)
# Get the move's type
type = pbRoughType(move,user,skill)
##### Calculate user's attack stat #####
atk = pbRoughStat(user,PBStats::ATTACK,skill)
if move.function=="121" # Foul Play
atk = pbRoughStat(target,PBStats::ATTACK,skill)
elsif move.specialMove?(type)
if move.function=="121" # Foul Play
atk = pbRoughStat(target,PBStats::SPATK,skill)
else
atk = pbRoughStat(user,PBStats::SPATK,skill)
end
end
##### Calculate target's defense stat #####
defense = pbRoughStat(target,PBStats::DEFENSE,skill)
if move.specialMove?(type) && move.function!="122" # Psyshock
defense = pbRoughStat(target,PBStats::SPDEF,skill)
end
##### Calculate all multiplier effects #####
multipliers = [1.0, 1.0, 1.0, 1.0]
# Ability effects that alter damage
moldBreaker = false
if skill>=PBTrainerAI.highSkill && target.hasMoldBreaker?
moldBreaker = true
end
if skill>=PBTrainerAI.mediumSkill && user.abilityActive?
# NOTE: These abilities aren't suitable for checking at the start of the
# round.
abilityBlacklist = [:ANALYTIC,:SNIPER,:TINTEDLENS,:AERILATE,:PIXILATE,:REFRIGERATE]
canCheck = true
abilityBlacklist.each do |m|
next if move.id != m
canCheck = false
break
end
if canCheck
BattleHandlers.triggerDamageCalcUserAbility(user.ability,
user,target,move,multipliers,baseDmg,type)
end
end
if skill>=PBTrainerAI.mediumSkill && !moldBreaker
user.eachAlly do |b|
next if !b.abilityActive?
BattleHandlers.triggerDamageCalcUserAllyAbility(b.ability,
user,target,move,multipliers,baseDmg,type)
end
end
if skill>=PBTrainerAI.bestSkill && !moldBreaker && target.abilityActive?
# NOTE: These abilities aren't suitable for checking at the start of the
# round.
abilityBlacklist = [:FILTER,:SOLIDROCK]
canCheck = true
abilityBlacklist.each do |m|
next if move.id != m
canCheck = false
break
end
if canCheck
BattleHandlers.triggerDamageCalcTargetAbility(target.ability,
user,target,move,multipliers,baseDmg,type)
end
end
if skill>=PBTrainerAI.bestSkill && !moldBreaker
target.eachAlly do |b|
next if !b.abilityActive?
BattleHandlers.triggerDamageCalcTargetAllyAbility(b.ability,
user,target,move,multipliers,baseDmg,type)
end
end
# Item effects that alter damage
# NOTE: Type-boosting gems aren't suitable for checking at the start of the
# round.
if skill>=PBTrainerAI.mediumSkill && user.itemActive?
# NOTE: These items aren't suitable for checking at the start of the
# round.
itemBlacklist = [:EXPERTBELT,:LIFEORB]
if !itemBlacklist.include?(user.item_id)
BattleHandlers.triggerDamageCalcUserItem(user.item,
user,target,move,multipliers,baseDmg,type)
end
end
if skill>=PBTrainerAI.bestSkill && target.itemActive?
# NOTE: Type-weakening berries aren't suitable for checking at the start
# of the round.
if !target.item.is_berry?
BattleHandlers.triggerDamageCalcTargetItem(target.item,
user,target,move,multipliers,baseDmg,type)
end
end
# Global abilities
if skill>=PBTrainerAI.mediumSkill
if (@battle.pbCheckGlobalAbility(:DARKAURA) && type == :DARK) ||
(@battle.pbCheckGlobalAbility(:FAIRYAURA) && type == :FAIRY)
if @battle.pbCheckGlobalAbility(:AURABREAK)
multipliers[BASE_DMG_MULT] *= 2/3
else
multipliers[BASE_DMG_MULT] *= 4/3
end
end
end
# Parental Bond
if skill>=PBTrainerAI.mediumSkill && user.hasActiveAbility?(:PARENTALBOND)
multipliers[BASE_DMG_MULT] *= 1.25
end
# Me First
# TODO
# Helping Hand - n/a
# Charge
if skill>=PBTrainerAI.mediumSkill
if user.effects[PBEffects::Charge]>0 && type == :ELECTRIC
multipliers[BASE_DMG_MULT] *= 2
end
end
# Mud Sport and Water Sport
if skill>=PBTrainerAI.mediumSkill
if type == :ELECTRIC
@battle.eachBattler do |b|
next if !b.effects[PBEffects::MudSport]
multipliers[BASE_DMG_MULT] /= 3
break
end
if @battle.field.effects[PBEffects::MudSportField]>0
multipliers[BASE_DMG_MULT] /= 3
end
end
if type == :FIRE
@battle.eachBattler do |b|
next if !b.effects[PBEffects::WaterSport]
multipliers[BASE_DMG_MULT] /= 3
break
end
if @battle.field.effects[PBEffects::WaterSportField]>0
multipliers[BASE_DMG_MULT] /= 3
end
end
end
# Terrain moves
if user.affectedByTerrain? && skill>=PBTrainerAI.mediumSkill
case @battle.field.terrain
when PBBattleTerrains::Electric
multipliers[BASE_DMG_MULT] *= 1.5 if type == :ELECTRIC
when PBBattleTerrains::Grassy
multipliers[BASE_DMG_MULT] *= 1.5 if type == :GRASS
when PBBattleTerrains::Psychic
multipliers[BASE_DMG_MULT] *= 1.5 if type == :PSYCHIC
end
end
if target.affectedByTerrain? && skill>=PBTrainerAI.mediumSkill
if @battle.field.terrain==PBBattleTerrains::Misty && type == :DRAGON
multipliers[BASE_DMG_MULT] /= 2
end
end
# Badge multipliers
if skill>=PBTrainerAI.highSkill
if @battle.internalBattle
# Don't need to check the Atk/Sp Atk-boosting badges because the AI
# won't control the player's Pokémon.
if target.pbOwnedByPlayer?
if move.physicalMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_DEFENSE
multipliers[DEF_MULT] *= 1.1
elsif move.specialMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPDEF
multipliers[DEF_MULT] *= 1.1
end
end
end
end
# Multi-targeting attacks
if skill>=PBTrainerAI.highSkill
if pbTargetsMultiple?(move,user)
multipliers[FINAL_DMG_MULT] *= 0.75
end
end
# Weather
if skill>=PBTrainerAI.mediumSkill
case @battle.pbWeather
when PBWeather::Sun, PBWeather::HarshSun
if type == :FIRE
multipliers[FINAL_DMG_MULT] *= 1.5
elsif type == :WATER
multipliers[FINAL_DMG_MULT] /= 2
end
when PBWeather::Rain, PBWeather::HeavyRain
if type == :FIRE
multipliers[FINAL_DMG_MULT] /= 2
elsif type == :WATER
multipliers[FINAL_DMG_MULT] *= 1.5
end
when PBWeather::Sandstorm
if target.pbHasType?(:ROCK) && move.specialMove?(type) && move.function!="122" # Psyshock
multipliers[DEF_MULT] *= 1.5
end
end
end
# Critical hits - n/a
# Random variance - n/a
# STAB
if skill>=PBTrainerAI.mediumSkill
if type && user.pbHasType?(type)
if user.hasActiveAbility?(:ADAPTABILITY)
multipliers[FINAL_DMG_MULT] *= 2
else
multipliers[FINAL_DMG_MULT] *= 1.5
end
end
end
# Type effectiveness
if skill>=PBTrainerAI.mediumSkill
typemod = pbCalcTypeMod(type,user,target)
multipliers[FINAL_DMG_MULT] *= typemod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE
end
# Burn
if skill>=PBTrainerAI.highSkill
if user.status==PBStatuses::BURN && move.physicalMove?(type) &&
!user.hasActiveAbility?(:GUTS) &&
!(NEWEST_BATTLE_MECHANICS && move.function=="07E") # Facade
multipliers[FINAL_DMG_MULT] /= 2
end
end
# Aurora Veil, Reflect, Light Screen
if skill>=PBTrainerAI.highSkill
if !move.ignoresReflect? && !user.hasActiveAbility?(:INFILTRATOR)
if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] *= 2/3.0
else
multipliers[FINAL_DMG_MULT] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && move.physicalMove?(type)
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] *= 2/3.0
else
multipliers[FINAL_DMG_MULT] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && move.specialMove?(type)
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] *= 2/3.0
else
multipliers[FINAL_DMG_MULT] /= 2
end
end
end
end
# Minimize
if skill>=PBTrainerAI.highSkill
if target.effects[PBEffects::Minimize] && move.tramplesMinimize?(2)
multipliers[FINAL_DMG_MULT] *= 2
end
end
# Move-specific base damage modifiers
# TODO
# Move-specific final damage modifiers
# TODO
##### Main damage calculation #####
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT]).round, 1].max
atk = [(atk * multipliers[ATK_MULT]).round, 1].max
defense = [(defense * multipliers[DEF_MULT]).round, 1].max
damage = (((2.0 * user.level / 5 + 2).floor * baseDmg * atk / defense).floor / 50).floor + 2
damage = [(damage * multipliers[FINAL_DMG_MULT]).round, 1].max
# "AI-specific calculations below"
# Increased critical hit rates
if skill>=PBTrainerAI.mediumSkill
c = 0
# Ability effects that alter critical hit rate
if c>=0 && user.abilityActive?
c = BattleHandlers.triggerCriticalCalcUserAbility(user.ability,user,target,c)
end
if skill>=PBTrainerAI.bestSkill
if c>=0 && !moldBreaker && target.abilityActive?
c = BattleHandlers.triggerCriticalCalcTargetAbility(target.ability,user,target,c)
end
end
# Item effects that alter critical hit rate
if c>=0 && user.itemActive?
c = BattleHandlers.triggerCriticalCalcUserItem(user.item,user,target,c)
end
if skill>=PBTrainerAI.bestSkill
if c>=0 && target.itemActive?
c = BattleHandlers.triggerCriticalCalcTargetItem(target.item,user,target,c)
end
end
# Other efffects
c = -1 if target.pbOwnSide.effects[PBEffects::LuckyChant]>0
if c>=0
c += 1 if move.highCriticalRate?
c += user.effects[PBEffects::FocusEnergy]
c += 1 if user.inHyperMode? && move.type == :SHADOW
end
if c>=0
c = 4 if c>4
damage += damage*0.1*c
end
end
return damage.floor
end
#=============================================================================
# Accuracy calculation
#=============================================================================
def pbRoughAccuracy(move,user,target,skill)
# "Always hit" effects and "always hit" accuracy
if skill>=PBTrainerAI.mediumSkill
return 125 if target.effects[PBEffects::Minimize] && move.tramplesMinimize?(1)
return 125 if target.effects[PBEffects::Telekinesis]>0
end
baseAcc = move.accuracy
if skill>=PBTrainerAI.highSkill
baseAcc = move.pbBaseAccuracy(user,target)
end
return 125 if baseAcc==0 && skill>=PBTrainerAI.mediumSkill
# Get the move's type
type = pbRoughType(move,user,skill)
# Calculate all modifier effects
modifiers = []
modifiers[BASE_ACC] = baseAcc
modifiers[ACC_STAGE] = user.stages[PBStats::ACCURACY]
modifiers[EVA_STAGE] = target.stages[PBStats::EVASION]
modifiers[ACC_MULT] = 1.0
modifiers[EVA_MULT] = 1.0
pbCalcAccuracyModifiers(user,target,modifiers,move,type,skill)
# Check if move can't miss
return 125 if modifiers[BASE_ACC]==0
# Calculation
accStage = [[modifiers[ACC_STAGE],-6].max,6].min + 6
evaStage = [[modifiers[EVA_STAGE],-6].max,6].min + 6
stageMul = [3,3,3,3,3,3, 3, 4,5,6,7,8,9]
stageDiv = [9,8,7,6,5,4, 3, 3,3,3,3,3,3]
accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage]
evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage]
accuracy = (accuracy * modifiers[ACC_MULT]).round
evasion = (evasion * modifiers[EVA_MULT]).round
evasion = 1 if evasion<1
return modifiers[BASE_ACC] * accuracy / evasion
end
def pbCalcAccuracyModifiers(user,target,modifiers,move,type,skill)
moldBreaker = false
if skill>=PBTrainerAI.highSkill && target.hasMoldBreaker?
moldBreaker = true
end
# Ability effects that alter accuracy calculation
if skill>=PBTrainerAI.mediumSkill
if user.abilityActive?
BattleHandlers.triggerAccuracyCalcUserAbility(user.ability,
modifiers,user,target,move,type)
end
user.eachAlly do |b|
next if !b.abilityActive?
BattleHandlers.triggerAccuracyCalcUserAllyAbility(b.ability,
modifiers,user,target,move,type)
end
end
if skill>=PBTrainerAI.bestSkill
if target.abilityActive? && !moldBreaker
BattleHandlers.triggerAccuracyCalcTargetAbility(target.ability,
modifiers,user,target,move,type)
end
end
# Item effects that alter accuracy calculation
if skill>=PBTrainerAI.mediumSkill
if user.itemActive?
BattleHandlers.triggerAccuracyCalcUserItem(user.item,
modifiers,user,target,move,type)
end
end
if skill>=PBTrainerAI.bestSkill
if target.itemActive?
BattleHandlers.triggerAccuracyCalcTargetItem(target.item,
modifiers,user,target,move,type)
end
end
# Other effects, inc. ones that set ACC_MULT or EVA_STAGE to specific values
if skill>=PBTrainerAI.mediumSkill
if @battle.field.effects[PBEffects::Gravity]>0
modifiers[ACC_MULT] *= 5/3.0
end
if user.effects[PBEffects::MicleBerry]
modifiers[ACC_MULT] *= 1.2
end
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::Foresight] && modifiers[EVA_STAGE]>0
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[EVA_STAGE]>0
end
# "AI-specific calculations below"
if skill>=PBTrainerAI.mediumSkill
modifiers[EVA_STAGE] = 0 if move.function=="0A9" # Chip Away
modifiers[BASE_ACC] = 0 if ["0A5","139","13A","13B","13C", # "Always hit"
"147"].include?(move.function)
modifiers[BASE_ACC] = 0 if user.effects[PBEffects::LockOn]>0 &&
user.effects[PBEffects::LockOnPos]==target.index
end
if skill>=PBTrainerAI.highSkill
if move.function=="006" # Toxic
modifiers[BASE_ACC] = 0 if NEWEST_BATTLE_MECHANICS && move.statusMove? &&
user.pbHasType?(:POISON)
end
if move.function=="070" # OHKO moves
modifiers[BASE_ACC] = move.accuracy+user.level-target.level
modifiers[ACC_MULT] = 0 if target.level>user.level
if skill>=PBTrainerAI.bestSkill
modifiers[ACC_MULT] = 0 if target.hasActiveAbility?(:STURDY)
end
end
end
end
end

View File

@@ -1,108 +0,0 @@
class PBStuff
#Standardized lists of moves with similar purposes/characteristics
#(mostly just "stuff that gets called together")
UNFREEZEMOVE = [PBMoves::FLAMEWHEEL,PBMoves::SACREDFIRE,PBMoves::FLAREBLITZ,
PBMoves::FUSIONFLARE,PBMoves::SCALD,PBMoves::STEAMERUPTION,PBMoves::BURNUP]
SWITCHOUTMOVE = [PBMoves::ROAR,PBMoves::WHIRLWIND,PBMoves::CIRCLETHROW,
PBMoves::DRAGONTAIL,PBMoves::YAWN,PBMoves::PERISHSONG]
SETUPMOVE = [PBMoves::SWORDSDANCE,PBMoves::DRAGONDANCE,PBMoves::CALMMIND,
PBMoves::WORKUP,PBMoves::NASTYPLOT,PBMoves::TAILGLOW,PBMoves::BELLYDRUM,
PBMoves::BULKUP,PBMoves::COIL,PBMoves::CURSE,PBMoves::GROWTH,
PBMoves::HONECLAWS,PBMoves::QUIVERDANCE,PBMoves::SHELLSMASH]
PROTECTMOVE = [PBMoves::PROTECT,PBMoves::DETECT,PBMoves::KINGSSHIELD,
PBMoves::SPIKYSHIELD,PBMoves::BANEFULBUNKER]
PROTECTIGNORINGMOVE = [PBMoves::FEINT,PBMoves::HYPERSPACEHOLE,
PBMoves::HYPERSPACEFURY,PBMoves::SHADOWFORCE,PBMoves::PHANTOMFORCE]
SCREENBREAKERMOVE = [PBMoves::DEFOG,PBMoves::BRICKBREAK,PBMoves::PSYCHICFANGS]
CONTRARYBAITMOVE = [PBMoves::SUPERPOWER,PBMoves::OVERHEAT,PBMoves::DRACOMETEOR,
PBMoves::LEAFSTORM,PBMoves::FLEURCANNON,PBMoves::PSYCHOBOOST]
TWOTURNAIRMOVE = [PBMoves::BOUNCE,PBMoves::FLY,PBMoves::SKYDROP]
PIVOTMOVE = [PBMoves::UTURN,PBMoves::VOLTSWITCH,PBMoves::PARTINGSHOT]
DANCEMOVE = [PBMoves::QUIVERDANCE,PBMoves::DRAGONDANCE,PBMoves::FIERYDANCE,
PBMoves::FEATHERDANCE,PBMoves::PETALDANCE,PBMoves::SWORDSDANCE,
PBMoves::TEETERDANCE,PBMoves::LUNARDANCE,PBMoves::REVELATIONDANCE]
BULLETMOVE = [PBMoves::ACIDSPRAY,PBMoves::AURASPHERE,PBMoves::BARRAGE,
PBMoves::BULLETSEED,PBMoves::EGGBOMB,PBMoves::ELECTROBALL,PBMoves::ENERGYBALL,
PBMoves::FOCUSBLAST,PBMoves::GYROBALL,PBMoves::ICEBALL,PBMoves::MAGNETBOMB,
PBMoves::MISTBALL,PBMoves::MUDBOMB,PBMoves::OCTAZOOKA,PBMoves::ROCKWRECKER,
PBMoves::SEARINGSHOT,PBMoves::SEEDBOMB,PBMoves::SHADOWBALL,PBMoves::SLUDGEBOMB,
PBMoves::WEATHERBALL,PBMoves::ZAPCANNON,PBMoves::BEAKBLAST]
BURNMOVE = [PBMoves::WILLOWISP,PBMoves::SACREDFIRE,PBMoves::INFERNO]
PARAMOVE = [PBMoves::THUNDERWAVE,PBMoves::STUNSPORE,PBMoves::GLARE,
PBMoves::NUZZLE,PBMoves::ZAPCANNON]
SLEEPMOVE = [PBMoves::SPORE,PBMoves::SLEEPPOWDER,PBMoves::HYPNOSIS,PBMoves::DARKVOID,
PBMoves::GRASSWHISTLE,PBMoves::LOVELYKISS,PBMoves::SING]
POISONMOVE = [PBMoves::TOXIC,PBMoves::POISONPOWDER,PBMoves::POISONGAS,PBMoves::TOXICTHREAD]
CONFUMOVE = [PBMoves::CONFUSERAY,PBMoves::SUPERSONIC,PBMoves::FLATTER,PBMoves::SWAGGER,
PBMoves::SWEETKISS,PBMoves::TEETERDANCE,PBMoves::CHATTER,PBMoves::DYNAMICPUNCH]
HEALFUNCTIONS = [0xD5,0xD6,0xD7,0xD8,0xD9,0xDD,0xDE,0xDF,0xE3,0xE4,0x114,0x139,0x158,0x162,0x169,0x16C,0x172]
#massive arrays of stuff that no one wants to see
NATURALGIFTDAMAGE={
100 => [:WATMELBERRY,:DURINBERRY,:BELUEBERRY,:LIECHIBERRY,:GANLONBERRY,:SALACBERRY,
:PETAYABERRY,:APICOTBERRY,:LANSATBERRY,:STARFBERRY,:ENIGMABERRY,:MICLEBERRY,
:CUSTAPBERRY,:JABOCABERRY,:ROWAPBERRY],
90 => [:BLUKBERRY,:NANABBERRY,:WEPEARBERRY,:PINAPBERRY,:POMEGBERRY,:KELPSYBERRY,
:QUALOTBERRY,:HONDEWBERRY,:GREPABERRY,:TAMATOBERRY,:CORNNBERRY,:MAGOSTBERRY,
:RABUTABERRY,:NOMELBERRY,:SPELONBERRY,:PAMTREBERRY],
80 => [:CHERIBERRY,:CHESTOBERRY,:PECHABERRY,:RAWSTBERRY,:ASPEARBERRY,:LEPPABERRY,
:ORANBERRY,:PERSIMBERRY,:LUMBERRY,:SITRUSBERRY,:FIGYBERRY,:WIKIBERRY,
:MAGOBERRY,:AGUAVBERRY,:IAPAPABERRY,:RAZZBERRY,:OCCABERRY,:PASSHOBERRY,
:WACANBERRY,:RINDOBERRY,:YACHEBERRY,:CHOPLEBERRY,:KEBIABERRY,:SHUCABERRY,
:COBABERRY,:PAYAPABERRY,:TANGABERRY,:CHARTIBERRY,:KASIBBERRY,:HABANBERRY,
:COLBURBERRY,:BABIRIBERRY,:CHILANBERRY]}
FLINGDAMAGE={
300 => [:MEMEONADE],
130 => [:IRONBALL],
100 => [:ARMORFOSSIL,:CLAWFOSSIL,:COVERFOSSIL,:DOMEFOSSIL,:HARDSTONE,:HELIXFOSSIL,
:OLDAMBER,:PLUMEFOSSIL,:RAREBONE,:ROOTFOSSIL,:SKULLFOSSIL],
90 => [:DEEPSEATOOTH,:DRACOPLATE,:DREADPLATE,:EARTHPLATE,:FISTPLATE,:FLAMEPLATE,
:GRIPCLAW,:ICICLEPLATE,:INSECTPLATE,:IRONPLATE,:MEADOWPLATE,:MINDPLATE,
:SKYPLATE,:SPLASHPLATE,:SPOOKYPLATE,:STONEPLATE,:THICKCLUB,:TOXICPLATE,
:ZAPPLATE],
80 => [:DAWNSTONE,:DUSKSTONE,:ELECTIRIZER,:MAGMARIZER,:ODDKEYSTONE,:OVALSTONE,
:PROTECTOR,:QUICKCLAW,:RAZORCLAW,:SHINYSTONE,:STICKYBARB,:ASSAULTVEST],
70 => [:BURNDRIVE,:CHILLDRIVE,:DOUSEDRIVE,:DRAGONFANG,:POISONBARB,:POWERANKLET,
:POWERBAND,:POWERBELT,:POWERBRACER,:POWERLENS,:POWERWEIGHT,:SHOCKDRIVE],
60 => [:ADAMANTORB,:DAMPROCK,:HEATROCK,:LUSTROUSORB,:MACHOBRACE,:ROCKYHELMET,
:STICK,:AMPLIFIELDROCK,:ADRENALINEORB],
50 => [:DUBIOUSDISC,:SHARPBEAK],
40 => [:EVIOLITE,:ICYROCK,:LUCKYPUNCH,:PROTECTIVEPADS],
30 => [:ABILITYURGE,:ABSORBBULB,:AMULETCOIN,:ANTIDOTE,:AWAKENING,:BALMMUSHROOM,
:BERRYJUICE,:BIGMUSHROOM,:BIGNUGGET,:BIGPEARL,:BINDINGBAND,:BLACKBELT,
:BLACKFLUTE,:BLACKGLASSES,:BLACKSLUDGE,:BLUEFLUTE,:BLUESHARD,:BURNHEAL,
:CALCIUM,:CARBOS,:CASTELIACONE,:CELLBATTERY,:CHARCOAL,:CLEANSETAG,
:COMETSHARD,:DAMPMULCH,:DEEPSEASCALE,:DIREHIT,:DIREHIT2,:DIREHIT3,
:DRAGONSCALE,:EJECTBUTTON,:ELIXIR,:ENERGYPOWDER,:ENERGYROOT,:ESCAPEROPE,
:ETHER,:EVERSTONE,:EXPSHARE,:FIRESTONE,:FLAMEORB,:FLOATSTONE,:FLUFFYTAIL,
:FRESHWATER,:FULLHEAL,:FULLRESTORE,:GOOEYMULCH,:GREENSHARD,:GROWTHMULCH,
:GUARDSPEC,:HEALPOWDER,:HEARTSCALE,:HONEY,:HPUP,:HYPERPOTION,:ICEHEAL,
:IRON,:ITEMDROP,:ITEMURGE,:KINGSROCK,:LAVACOOKIE,:LEAFSTONE,:LEMONADE,
:LIFEORB,:LIGHTBALL,:LIGHTCLAY,:LUCKYEGG,:MAGNET,:MAXELIXIR,:MAXETHER,
:MAXPOTION,:MAXREPEL,:MAXREVIVE,:METALCOAT,:METRONOME,:MIRACLESEED,
:MOOMOOMILK,:MOONSTONE,:MYSTICWATER,:NEVERMELTICE,:NUGGET,:OLDGATEAU,
:PARLYZHEAL,:PEARL,:PEARLSTRING,:POKEDOLL,:POKETOY,:POTION,:PPMAX,:PPUP,
:PRISMSCALE,:PROTEIN,:RAGECANDYBAR,:RARECANDY,:RAZORFANG,:REDFLUTE,
:REDSHARD,:RELICBAND,:RELICCOPPER,:RELICCROWN,:RELICGOLD,:RELICSILVER,
:RELICSTATUE,:RELICVASE,:REPEL,:RESETURGE,:REVIVALHERB,:REVIVE,:SACREDASH,
:SCOPELENS,:SHELLBELL,:SHOALSALT,:SHOALSHELL,:SMOKEBALL,:SODAPOP,:SOULDEW,
:SPELLTAG,:STABLEMULCH,:STARDUST,:STARPIECE,:SUNSTONE,:SUPERPOTION,
:SUPERREPEL,:SWEETHEART,:THUNDERSTONE,:TINYMUSHROOM,:TOXICORB,
:TWISTEDSPOON,:UPGRADE,:WATERSTONE,:WHITEFLUTE,:XACCURACY,:XACCURACY2,
:XACCURACY3,:XACCURACY6,:XATTACK,:XATTACK2,:XATTACK3,:XATTACK6,:XDEFEND,
:XDEFEND2,:XDEFEND3,:XDEFEND6,:XSPDEF,:XSPDEF2,:XSPDEF3,:XSPDEF6,:XSPECIAL,
:XSPECIAL2,:XSPECIAL3,:XSPECIAL6,:XSPEED,:XSPEED2,:XSPEED3,:XSPEED6,
:YELLOWFLUTE,:YELLOWSHARD,:ZINC,:BIGMALASADA,:ICESTONE],
20 => [:CLEVERWING,:GENIUSWING,:HEALTHWING,:MUSCLEWING,:PRETTYWING,
:RESISTWING,:SWIFTWING],
10 => [:AIRBALLOON,:BIGROOT,:BLUESCARF,:BRIGHTPOWDER,:CHOICEBAND,:CHOICESCARF,
:CHOICESPECS,:DESTINYKNOT,:EXPERTBELT,:FOCUSBAND,:FOCUSSASH,:FULLINCENSE,
:GREENSCARF,:LAGGINGTAIL,:LAXINCENSE,:LEFTOVERS,:LUCKINCENSE,:MENTALHERB,
:METALPOWDER,:MUSCLEBAND,:ODDINCENSE,:PINKSCARF,:POWERHERB,:PUREINCENSE,
:QUICKPOWDER,:REAPERCLOTH,:REDCARD,:REDSCARF,:RINGTARGET,:ROCKINCENSE,
:ROSEINCENSE,:SEAINCENSE,:SHEDSHELL,:SILKSCARF,:SILVERPOWDER,:SMOOTHROCK,
:SOFTSAND,:SOOTHEBELL,:WAVEINCENSE,:WHITEHERB,:WIDELENS,:WISEGLASSES,
:YELLOWSCARF,:ZOOMLENS,:BLUEMIC,:VANILLAIC,:STRAWBIC,:CHOCOLATEIC]}
end

View File

@@ -1,154 +0,0 @@
class PokeBattle_Battle
# Legacy method that should stop being used.
def pbGetOwner(battlerIndex)
if opposes?(battlerIndex)
if @opponent.is_a?(Array)
return (battlerIndex==1) ? @opponent[0] : @opponent[1]
else
return @opponent
end
else
if @player.is_a?(Array)
return (battlerIndex==0) ? @player[0] : @player[1]
else
return @player
end
end
end
# Reborn method (the difference is that each element in "choices" is an array
# in Essentials but just a number in Reborn)
def pbStdDev(choices)
sum = 0
n = 0
choices.each do |c|
sum += c
n += 1
end
return 0 if n<2
mean = sum.to_f/n.to_f
varianceTimesN = 0
for i in 0...choices.length
next if choices[i]<=0
deviation = choices[i].to_f-mean
varianceTimesN += deviation*deviation
end
# Using population standard deviation
# [(n-1) makes it a sample std dev, would be 0 with only 1 sample]
return Math.sqrt(varianceTimesN/n)
end
##############################################################################
# Choose an action.
##############################################################################
def pbDefaultChooseEnemyCommand(idxBattler)
if !@battle.pbCanShowFightMenu?(idxBattler)
return if pbEnemyShouldUseItem?(idxBattler)
# return if pbEnemyShouldWithdraw?(idxBattler) # Old Switching Method
return if pbShouldSwitch?(idxBattler)
return if @battle.pbAutoFightMenu(idxBattler)
@battle.pbAutoChooseMove(idxBattler)
return
end
pbBuildMoveScores(idxBattler) # Grab the array of scores/targets before doing anything else
return if pbShouldSwitch?(idxBattler)
# return if pbEnemyShouldWithdraw?(idxBattler) # Old Switching Method
return if pbEnemyShouldUseItem?(idxBattler)
return if @battle.pbAutoFightMenu(idxBattler)
@battle.pbRegisterUltraBurst(idxBattler) if pbEnemyShouldUltraBurst?(idxBattler)
@battle.pbRegisterMegaEvolution(idxBattler) if pbEnemyShouldMegaEvolve?(idxBattler)
if pbEnemyShouldZMove?(idxBattler)
return pbChooseEnemyZMove(idxBattler)
end
pbChooseMoves(idxBattler)
end
def pbChooseEnemyZMove(index) #Put specific cases for trainers using status Z-Moves
chosenmove=false
chosenindex=-1
attacker = @battlers[index]
opponent=attacker.pbOppositeOpposing
otheropp=opponent.pbPartner
skill=pbGetOwner(attacker.index).skill || 0
for i in 0..3
move=@battlers[index].moves[i]
if @battlers[index].pbCompatibleZMoveFromMove?(move)
if move.id == (PBMoves::CONVERSION) || move.id == (PBMoves::SPLASH)
pbRegisterZMove(index)
pbRegisterMove(index,i,false)
pbRegisterTarget(index,opponent.index)
return
end
if !chosenmove
chosenindex = i
chosenmove=move
else
if move.basedamage>chosenmove.basedamage
chosenindex=i
chosenmove=move
end
end
end
end
#oppeff1 = chosenmove.pbTypeModifier(chosenmove.type,attacker,opponent)
oppeff1 = pbTypeModNoMessages(chosenmove.type,attacker,opponent,chosenmove,skill)
#oppeff2 = chosenmove.pbTypeModifier(chosenmove.type,attacker,otheropp)
oppeff2 = pbTypeModNoMessages(chosenmove.type,attacker,otheropp,chosenmove,skill)
oppeff1 = 0 if opponent.hp<(opponent.totalhp/2.0).round
oppeff1 = 0 if (opponent.effects[PBEffects::Substitute]>0 || opponent.effects[PBEffects::Disguise]) && attacker.item!=(PBItems::KOMMONIUMZ2)
oppeff2 = 0 if otheropp.hp<(otheropp.totalhp/2.0).round
oppeff2 = 0 if (otheropp.effects[PBEffects::Substitute]>0 || otheropp.effects[PBEffects::Disguise]) && attacker.item!=(PBItems::KOMMONIUMZ2)
oppmult=0
for i in 1..7 #iterates through all the stats
oppmult+=opponent.stages[i] if opponent.stages[i]>0
end
othermult=0
for i in 1..7
othermult+=otheropp.stages[i] if otheropp.stages[i]>0
end
if (oppeff1<4) && ((oppeff2<4) || otheropp.hp==0)
pbChooseMoves(index)
elsif oppeff1>oppeff2
pbRegisterZMove(index)
pbRegisterMove(index,chosenindex,false)
pbRegisterTarget(index,opponent.index)
elsif oppeff1<oppeff2
pbRegisterZMove(index)
pbRegisterMove(index,chosenindex,false)
pbRegisterTarget(index,otheropp.index)
elsif oppeff1==oppeff2
if oppmult > othermult
pbRegisterZMove(index)
pbRegisterMove(index,chosenindex,false)
pbRegisterTarget(index,opponent.index)
elsif oppmult < othermult
pbRegisterZMove(index)
pbRegisterMove(index,chosenindex,false)
pbRegisterTarget(index,otheropp.index)
else
if otheropp.hp > opponent.hp
pbRegisterZMove(index)
pbRegisterMove(index,chosenindex,false)
pbRegisterTarget(index,otheropp.index)
else
pbRegisterZMove(index)
pbRegisterMove(index,chosenindex,false)
pbRegisterTarget(index,opponent.index)
end
end
end
end
#=============================================================================
# Decide whether the opponent should Ultra Burst their Pokémon.
#=============================================================================
def pbEnemyShouldUltraBurst?(idxBattler)
battler = @battlers[idxBattler]
if pbCanUltraBurst?(idxBattler) # Simple "always should if possible"
PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will Ultra Burst")
return true
end
return false
end
end

View File

@@ -1,495 +0,0 @@
class PokeBattle_Battle
################################################################################
# Decide whether the opponent should use an item on the Pokémon.
################################################################################
def pbEnemyShouldUseItem?(index)
item=pbEnemyItemToUse(index)
if item>0 && @battlers[index].effects[PBEffects::Embargo]==0
pbRegisterItem(index,item,nil)
return true
end
return false
end
def pbEnemyItemAlreadyUsed?(index,item,items)
if @choices[1][0]==3 && @choices[1][1]==item
qty=0
for i in items
qty+=1 if i==item
end
return true if qty<=1
end
return false
end
def pbEnemyItemToUse(index)
return 0 if !@opponent
return 0 if !@internalbattle
items=pbGetOwnerItems(index)
return 0 if !items
skill=pbGetOwner(index).skill || 0
battler=@battlers[index]
party = pbParty(index)
opponent1 = battler.pbOppositeOpposing
opponent2 = opponent1.pbPartner
currentroles = pbGetMonRole(battler,opponent1,skill)
return 0 if battler.isFainted?
highscore = 0
movecount = -1
maxplaypri = -1
partynumber = 0
aimem = getAIMemory(skill,opponent1.pokemonIndex)
for i in party
next if i.nil?
next if i.hp == 0
partynumber+=1
end
itemnumber = 0
for i in items
next if pbEnemyItemAlreadyUsed?(index,i,items)
itemnumber+=1
end
#highest score
for i in battler.moves
scorearray = 0
scorearray = @scores[i] if @scores[i]
if scorearray>100 && i.priority>maxplaypri
maxplaypri = i.priority
end
end
highscore = @scores.max
highdamage = -1
maxopppri = -1
pridam = -1
bestid = -1
#expected damage
#if battler.pbSpeed<pbRoughStat(opponent1,PBStats::SPEED,skill)
if aimem.length > 0
for i in aimem
tempdam = pbRoughDamage(i,opponent1,battler,skill,i.basedamage)
if tempdam>highdamage
highdamage = tempdam
bestid = i.id
end
if i.priority > maxopppri
maxopppri = i.priority
pridam = tempdam
end
end
end
highratio = -1
#expected damage percentage
if battler.hp!=0
highratio = highdamage*(1.0/battler.hp)
end
scorearray = []
arraycount = -1
PBDebug.log(sprintf("Beginning AI Item use check.")) if $INTERNAL
PBDebug.log(sprintf(" ")) if $INTERNAL
for i in items
arraycount+=1
scorearray.push(0)
itemscore=100
ishpitem = false
isstatusitem = false
next if pbEnemyItemAlreadyUsed?(index,i,items)
if (i== PBItems::POTION) ||
(i== PBItems::ULTRAPOTION) ||
(i== PBItems::SUPERPOTION) ||
(i== PBItems::HYPERPOTION) ||
(i== PBItems::MAXPOTION) ||
(i== PBItems::FULLRESTORE) ||
(i== PBItems::FRESHWATER) ||
(i== PBItems::SODAPOP) ||
(i== PBItems::LEMONADE) ||
(i== PBItems::MOOMOOMILK) ||
(i== PBItems::MEMEONADE) ||
(i== PBItems::STRAWBIC) ||
(i== PBItems::CHOCOLATEIC) ||
(i== PBItems::BLUEMIC)
ishpitem=true
end
if (i== PBItems::FULLRESTORE) ||
(i== PBItems::FULLHEAL) ||
(i== PBItems::RAGECANDYBAR) ||
(i== PBItems::LAVACOOKIE) ||
(i== PBItems::OLDGATEAU) ||
(i== PBItems::CASTELIACONE) ||
(i== PBItems::LUMIOSEGALETTE) ||
(i== PBItems::BIGMALASADA)
isstatusitem=true
end
if ishpitem
PBDebug.log(sprintf("This is a HP-healing item.")) if $INTERNAL
restoreamount=0
if (i== PBItems::POTION)
restoreamount=20
elsif (i== PBItems::ULTRAPOTION)
restoreamount=200
elsif (i== PBItems::SUPERPOTION)
restoreamount=60
elsif (i== PBItems::HYPERPOTION)
restoreamount=120
elsif (i== PBItems::MAXPOTION) || (i== PBItems::FULLRESTORE)
restoreamount=battler.totalhp
elsif (i== PBItems::FRESHWATER)
restoreamount=30
elsif (i== PBItems::SODAPOP)
restoreamount=50
elsif (i== PBItems::LEMONADE)
restoreamount=70
elsif (i== PBItems::MOOMOOMILK)
restoreamount=110
elsif (i== PBItems::MEMEONADE)
restoreamount=103
elsif (i== PBItems::STRAWBIC)
restoreamount=90
elsif (i== PBItems::CHOCOLATEIC)
restoreamount=70
elsif (i== PBItems::BLUEMIC)
restoreamount=200
end
resratio=restoreamount*(1.0/battler.totalhp)
itemscore*= (2 - (2*(battler.hp*(1.0/battler.totalhp))))
if highdamage>=battler.hp
if highdamage > [battler.hp+restoreamount,battler.totalhp].min
itemscore*=0
else
itemscore*=1.2
end
healmove = false
for j in battler.moves
if j.isHealingMove?
healmove=true
end
end
if healmove
if battler.pbSpeed < opponent1.pbSpeed
if highdamage>=battler.hp
itemscore*=1.1
else
itemscore*=0.6
if resratio<0.55
itemscore*=0.2
end
end
end
end
else
itemscore*=0.4
end
if highdamage > restoreamount
itemscore*=0
else
if restoreamount-highdamage < 15
itemscore*=0.5
end
end
if battler.pbSpeed > opponent1.pbSpeed
itemscore*=0.8
if highscore >=110
if maxopppri > maxplaypri
itemscore*=1.3
if pridam>battler.hp
if pridam>(battler.hp/2.0)
itemscore*=0
else
itemscore*=2
end
end
elsif !(!opponent1.abilitynulled && opponent1.ability == PBAbilities::STURDY)
itemscore*=0
end
end
if currentroles.include?(PBMonRoles::SWEEPER)
itemscore*=1.1
end
else
if highdamage*2 > [battler.hp+restoreamount,battler.totalhp].min
itemscore*=0
else
itemscore*=1.5
if highscore >=110
itemscore*=1.5
end
end
end
if battler.hp == battler.totalhp
itemscore*=0
elsif battler.hp >= (battler.totalhp*0.8)
itemscore*=0.2
elsif battler.hp >= (battler.totalhp*0.6)
itemscore*=0.3
elsif battler.hp >= (battler.totalhp*0.5)
itemscore*=0.5
end
minipot = (partynumber-1)
minimini = -1
for j in items
next if pbEnemyItemAlreadyUsed?(index,j,items)
next if !((j== PBItems::POTION) || (j== PBItems::ULTRAPOTION) ||
(j== PBItems::SUPERPOTION) || (j== PBItems::HYPERPOTION) ||
(j== PBItems::MAXPOTION) || (j== PBItems::FULLRESTORE) ||
(j== PBItems::FRESHWATER) || (j== PBItems::SODAPOP) ||
(j== PBItems::LEMONADE) || (j== PBItems::MOOMOOMILK) ||
(j== PBItems::MEMEONADE) || (j== PBItems::STRAWBIC) ||
(j== PBItems::CHOCOLATEIC) || (j== PBItems::BLUEMIC))
minimini+=1
end
if minipot>minimini
itemscore*=(0.9**(minipot-minimini))
minipot=minimini
elsif minimini>minipot
itemscore*=(1.1**(minimini-minipot))
minimini=minipot
end
if currentroles.include?(PBMonRoles::LEAD) || currentroles.include?(PBMonRoles::SCREENER)
itemscore*=0.6
end
if currentroles.include?(PBMonRoles::TANK)
itemscore*=1.1
end
if currentroles.include?(PBMonRoles::SECOND)
itemscore*=1.1
end
if battler.hasWorkingItem(:LEFTOVERS) || (battler.hasWorkingItem(:BLACKSLUDGE) && battler.pbHasType?(:POISON))
itemscore*=0.9
end
if battler.status!=0 && !(i== PBItems::FULLRESTORE)
itemscore*=0.7
if battler.effects[PBEffects::Toxic]>0 && partynumber>1
itemscore*=0.2
end
end
if PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)>4
itemscore*=0.7
elsif PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)<4
itemscore*=1.1
if PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)==0
itemscore*=1.2
end
end
if PBTypes.getCombinedEffectiveness(opponent1.type2,battler.type1,battler.type2)>4
itemscore*=0.6
elsif PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)<4
itemscore*=1.1
if PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)==0
itemscore*=1.2
end
end
if (!battler.abilitynulled && battler.ability == PBAbilities::REGENERATOR) && partynumber>1
itemscore*=0.7
end
end
if isstatusitem
PBDebug.log(sprintf("This is a status-curing item.")) if $INTERNAL
if !(i== PBItems::FULLRESTORE)
if battler.status==0
itemscore*=0
else
if highdamage>battler.hp
if (bestid==106 && battler.status==PBStatuses::SLEEP) || (bestid==298 && battler.status==PBStatuses::PARALYSIS) || bestid==179
if highdamage*0.5>battler.hp
itemscore*=0
else
itemscore*=1.4
end
else
itemscore*=0
end
end
end
if battler.status==PBStatuses::SLEEP
if battler.pbHasMove?((PBMoves::SLEEPTALK)) ||
battler.pbHasMove?((PBMoves::SNORE)) ||
battler.pbHasMove?((PBMoves::REST)) ||
(!battler.abilitynulled && battler.ability == PBAbilities::COMATOSE)
itemscore*=0.6
end
if checkAImoves([PBMoves::DREAMEATER,PBMoves::NIGHTMARE],aimem) || (!opponent1.abilitynulled && opponent1.ability == PBAbilities::BADDREAMS)
itemscore*=1.3
end
if highdamage*(1.0/battler.hp)>0.2
itemscore*=1.3
else
itemscore*=0.7
end
end
if battler.status==PBStatuses::PARALYSIS
if (!battler.abilitynulled && battler.ability == PBAbilities::QUICKFEET) || (!battler.abilitynulled && battler.ability == PBAbilities::GUTS)
itemscore*=0.5
end
if battler.pbSpeed>opponent1.pbSpeed && (battler.pbSpeed*0.5)<opponent1.pbSpeed
itemscore*=1.3
end
itemscore*=1.1
end
if battler.status==PBStatuses::BURN
itemscore*=1.1
if battler.attack>battler.spatk
itemscore*=1.2
else
itemscore*=0.8
end
if !battler.abilitynulled
itemscore*=0.6 if battler.ability == PBAbilities::GUTS
itemscore*=0.7 if battler.ability == PBAbilities::MAGICGUARD
itemscore*=0.8 if battler.ability == PBAbilities::FLAREBOOST
end
end
if battler.status==PBStatuses::POISON
itemscore*=1.1
if !battler.abilitynulled
itemscore*=0.5 if battler.ability == PBAbilities::GUTS
itemscore*=0.5 if battler.ability == PBAbilities::MAGICGUARD
itemscore*=0.5 if battler.ability == PBAbilities::TOXICBOOST
itemscore*=0.4 if battler.ability == PBAbilities::POISONHEAL
end
if battler.effects[PBEffects::Toxic]>0
itemscore*=1.1
if battler.effects[PBEffects::Toxic]>3
itemscore*=1.3
end
end
end
if battler.status==PBStatuses::FROZEN
itemscore*=1.3
thawmove=false
for j in battler.moves
if j.canThawUser?
thawmove=true
end
end
if thawmove
itemscore*=0.5
end
if highdamage*(1.0/battler.hp)>0.15
itemscore*=1.1
else
itemscore*=0.9
end
end
end
if battler.pbHasMove?((PBMoves::REFRESH)) ||
battler.pbHasMove?((PBMoves::REST)) ||
battler.pbHasMove?((PBMoves::PURIFY))
itemscore*=0.5
end
if (!battler.abilitynulled && battler.ability == PBAbilities::NATURALCURE) && partynumber>1
itemscore*=0.2
end
if (!battler.abilitynulled && battler.ability == PBAbilities::SHEDSKIN)
itemscore*=0.3
end
end
if partynumber==1 || currentroles.include?(PBMonRoles::ACE)
itemscore*=1.2
else
itemscore*=0.8
if battler.itemUsed2
itemscore*=0.6
end
end
if battler.effects[PBEffects::Confusion]>0
itemscore*=0.9
end
if battler.effects[PBEffects::Attract]>=0
itemscore*=0.6
end
if battler.effects[PBEffects::Substitute]>0
itemscore*=1.1
end
if battler.effects[PBEffects::LeechSeed]>=0
itemscore*=0.5
end
if battler.effects[PBEffects::Curse]
itemscore*=0.5
end
if battler.effects[PBEffects::PerishSong]>0
itemscore*=0.2
end
minipot=0
for s in [PBStats::ATTACK,PBStats::DEFENSE,PBStats::SPEED,
PBStats::SPATK,PBStats::SPDEF,PBStats::ACCURACY,PBStats::EVASION]
minipot+=battler.stages[s]
end
if currentroles.include?(PBMonRoles::PHYSICALWALL) || currentroles.include?(PBMonRoles::SPECIALWALL)
for s in [PBStats::DEFENSE,PBStats::SPDEF]
minipot+=battler.stages[s]
end
end
if currentroles.include?(PBMonRoles::SWEEPER)
for s in [PBStats::SPEED]
minipot+=battler.stages[s]
end
if battler.attack>battler.spatk
for s in [PBStats::ATTACK]
minipot+=battler.stages[s]
end
else
for s in [PBStats::SPATK]
minipot+=battler.stages[s]
end
end
end
minipot*=5
minipot+=100
minipot*=0.01
itemscore*=minipot
if opponent1.effects[PBEffects::TwoTurnAttack]>0 || opponent1.effects[PBEffects::HyperBeam]>0
itemscore*=1.2
end
if highscore>70
itemscore*=1.1
else
itemscore*=0.9
end
fielddisrupt = getFieldDisruptScore(battler,opponent1,skill)
if fielddisrupt <= 0
fielddisrupt=0.6
end
itemscore*= (1.0/fielddisrupt)
if @trickroom > 0
itemscore*=0.9
end
if battler.pbOwnSide.effects[PBEffects::Tailwind]>0
itemscore*=0.6
end
if battler.pbOwnSide.effects[PBEffects::Reflect]>0
itemscore*=0.9
end
if battler.pbOwnSide.effects[PBEffects::LightScreen]>0
itemscore*=0.9
end
if battler.pbOwnSide.effects[PBEffects::AuroraVeil]>0
itemscore*=0.8
end
if @doublebattle
itemscore*=0.8
end
itemscore-=100
PBDebug.log(sprintf("Score for %s: %d",PBItems.getName(i),itemscore)) if $INTERNAL
scorearray[arraycount] = itemscore
end
bestitem=-1
bestscore=-10000
counter=-1
for k in scorearray
counter+=1
if k>bestscore
bestscore = k
bestitem = items[counter]
end
end
PBDebug.log(sprintf("Highest item score: %d",bestscore)) if $INTERNAL
PBDebug.log(sprintf("Highest move score: %d",highscore)) if $INTERNAL
if highscore<bestscore
PBDebug.log(sprintf("Using %s",PBItems.getName(bestitem))) if $INTERNAL
return bestitem
else
PBDebug.log(sprintf("Not using an item.")) if $INTERNAL
PBDebug.log(sprintf(" ")) if $INTERNAL
return 0
end
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -1,832 +0,0 @@
class PokeBattle_Battle
attr_accessor :scores
attr_accessor :targets
attr_accessor :myChoices
################################################################################
# Choose a move to use.
# Called before any decisions are made.
################################################################################
def pbBuildMoveScores(index) #Generates an array of movescores for decisions
# Ally targetting stuff marked with ###
attacker=@battlers[index]
@scores=[0,0,0,0]
@targets=nil
@myChoices=[]
totalscore=0
target=-1
skill=0
wildbattle=!@opponent && pbIsOpposing?(index)
if wildbattle # If wild battle
preference = attacker.personalID % 16
preference = preference % 4
for i in 0...4
if pbCanChooseMove?(index,i,false)
@scores[i]=100
if preference == i # for personality
@scores[i]+=100
end
@myChoices.push(i)
end
end
else
skill=pbGetOwner(attacker.index).skill || 0
opponent=attacker.pbOppositeOpposing
fastermon = (attacker.pbSpeed>pbRoughStat(opponent,PBStats::SPEED,skill)) ^ (@trickroom!=0)
if fastermon && opponent
PBDebug.log(sprintf("AI Pokemon #{attacker.name} is faster than #{opponent.name}.")) if $INTERNAL
elsif opponent
PBDebug.log(sprintf("Player Pokemon #{opponent.name} is faster than #{attacker.name}.")) if $INTERNAL
end
#if @doublebattle && !opponent.isFainted? && !opponent.pbPartner.isFainted?
if @doublebattle && ((!opponent.isFainted? && !opponent.pbPartner.isFainted?) || !attacker.pbPartner.isFainted?)
# Choose a target and move. Also care about partner.
otheropp=opponent.pbPartner
fastermon = (attacker.pbSpeed>pbRoughStat(opponent,PBStats::SPEED,skill)) ^ (@trickroom!=0)
if fastermon && otheropp
PBDebug.log(sprintf("AI Pokemon #{attacker.name} is faster than #{otheropp.name}.")) if $INTERNAL
elsif otheropp
PBDebug.log(sprintf("Player Pokemon #{otheropp.name} is faster than #{attacker.name}.")) if $INTERNAL
end
notopp=attacker.pbPartner ###
scoresAndTargets=[]
@targets=[-1,-1,-1,-1]
maxscore1=0
maxscore2=0
totalscore1=0
totalscore2=0
baseDamageArray=[]
baseDamageArray2=[]
baseDamageArray3=[] ###
for j in 0...4
next if attacker.moves[j].id < 1
# check attacker.moves[j].basedamage and if this is 0 instead check the status method
dmgValue = pbRoughDamage(attacker.moves[j],attacker,opponent,skill,attacker.moves[j].basedamage)
if attacker.moves[j].basedamage!=0
if opponent.hp==0
dmgPercent = 0
else
dmgPercent = (dmgValue*100)/(opponent.hp)
dmgPercent = 110 if dmgPercent > 110
end
else
dmgPercent = pbStatusDamage(attacker.moves[j])
end
baseDamageArray.push(dmgPercent)
#Second opponent
dmgValue2 = pbRoughDamage(attacker.moves[j],attacker,otheropp,skill,attacker.moves[j].basedamage)
if attacker.moves[j].basedamage!=0
if otheropp.hp==0
dmgPercent2=0
else
dmgPercent2 = (dmgValue2*100)/(otheropp.hp)
dmgPercent2 = 110 if dmgPercent2 > 110
end
else
dmgPercent2 = pbStatusDamage(attacker.moves[j])
end
baseDamageArray2.push(dmgPercent2)
#Partner ###
dmgValue3 = pbRoughDamage(attacker.moves[j],attacker,notopp,skill,attacker.moves[j].basedamage)
if attacker.moves[j].basedamage!=0
if notopp.hp==0
dmgPercent3=0
else
dmgPercent3 = (dmgValue3*100)/(notopp.hp)
dmgPercent3 = 110 if dmgPercent3 > 110
end
else
dmgPercent3 = pbStatusDamage(attacker.moves[j])
end
baseDamageArray3.push(dmgPercent3)
end
for i in 0...4
if pbCanChooseMove?(index,i,false)
score1=pbGetMoveScore(attacker.moves[i],attacker,opponent,skill,baseDamageArray[i],baseDamageArray,i)
score2=pbGetMoveScore(attacker.moves[i],attacker,otheropp,skill,baseDamageArray2[i],baseDamageArray2,i)
totalscore = score1+score2
if (attacker.moves[i].target&0x08)!=0 # Targets all users
score1=totalscore # Consider both scores as it will hit BOTH targets
score2=totalscore
if attacker.pbPartner.isFainted? || (!attacker.pbPartner.abilitynulled && attacker.pbPartner.ability == PBAbilities::TELEPATHY) # No partner
score1*=1.66
score2*=1.66
else
# If this move can also target the partner, get the partner's
# score too
v=pbRoughDamage(attacker.moves[i],attacker,attacker.pbPartner,skill,attacker.moves[i].basedamage)
p=(v*100)/(attacker.pbPartner.hp)
s=pbGetMoveScore(attacker.moves[i],attacker,attacker.pbPartner,skill,p)
s=110 if s>110
if !attacker.pbPartner.abilitynulled &&
(attacker.moves[i].type == PBTypes::FIRE && attacker.pbPartner.ability == PBAbilities::FLASHFIRE) ||
(attacker.moves[i].type == PBTypes::WATER && [PBAbilities::WATERABSORB, PBAbilities::STORMDRAIN, PBAbilities::DRYSKIN].include?(attacker.pbPartner.ability)) ||
(attacker.moves[i].type == PBTypes::GRASS && attacker.pbPartner.ability == PBAbilities::SAPSIPPER) ||
(attacker.moves[i].type == PBTypes::ELECTRIC && [PBAbilities::VOLTABSORB, PBAbilities::LIGHTNINGROD, PBAbilities::MOTORDRIVE].include?(attacker.pbPartner.ability))
score1*=2.00
score2*=2.00
else
if (attacker.pbPartner.hp.to_f)/attacker.pbPartner.totalhp>0.10 || ((attacker.pbPartner.pbSpeed<attacker.pbSpeed) ^ (@trickroom!=0))
s = 100-s
s=0 if s<0
s/=100.0
s * 0.5 # multiplier to control how much to arbitrarily care about hitting partner; lower cares more
if (attacker.pbPartner.pbSpeed<attacker.pbSpeed) ^ (@trickroom!=0)
s * 0.5 # care more if we're faster and would knock it out before it attacks
end
score1*=s
score2*=s
end
end
end
score1=score1.to_i
score2=score2.to_i
PBDebug.log(sprintf("%s: Final Score after Multi-Target Adjustment: %d",PBMoves.getName(attacker.moves[i].id),score1))
PBDebug.log(sprintf(""))
end
if attacker.moves[i].target==PBTargets::AllOpposing # Consider both scores as it will hit BOTH targets
totalscore = score1+score2
score1=totalscore
score2=totalscore
PBDebug.log(sprintf("%s: Final Score after Multi-Target Adjustment: %d",PBMoves.getName(attacker.moves[i].id),score1))
PBDebug.log(sprintf(""))
end
@myChoices.push(i)
scoresAndTargets.push([i*2,i,score1,opponent.index])
scoresAndTargets.push([i*2+1,i,score2,otheropp.index])
else
scoresAndTargets.push([i*2,i,-1,opponent.index])
scoresAndTargets.push([i*2+1,i,-1,otheropp.index])
end
end
for i in 0...4 ### This whole bit
if pbCanChooseMove?(index,i,false)
movecode = attacker.moves[i].function
if movecode == 0xDF || movecode == 0x63 || movecode == 0x67 || #Heal Pulse, Simple Beam, Skill Swap,
movecode == 0xA0 || movecode == 0xC1 || movecode == 0x142 || #Frost Breath, Beat Up, Topsy-Turvy,
movecode == 0x162 || movecode == 0x164 || movecode == 0x167 || #Floral Healing, Instruct, Pollen Puff,
movecode == 0x169 || movecode == 0x170 || movecode == 0x55 || #Purify, Spotlight, Psych Up,
movecode == 0x40 || movecode == 0x41 || movecode == 0x66 #Swagger, Flatter, Entrainment
partnerscore=pbGetMoveScore(attacker.moves[i],attacker,notopp,skill,baseDamageArray3[i],baseDamageArray3,i)
PBDebug.log(sprintf("%s: Score for using on partner: %d",PBMoves.getName(attacker.moves[i].id),partnerscore))
PBDebug.log(sprintf(""))
scoresAndTargets.push([i*10,i,partnerscore,notopp.index])
end
end
end
scoresAndTargets.sort!{|a,b|
if a[2]==b[2] # if scores are equal
a[0]<=>b[0] # sort by index (for stable comparison)
else
b[2]<=>a[2]
end
}
for i in 0...scoresAndTargets.length
idx=scoresAndTargets[i][1]
thisScore=scoresAndTargets[i][2]
if thisScore>0 || thisScore==-1
if scores[idx]==0 || ((scores[idx]==thisScore && pbAIRandom(10)<5) ||
(scores[idx] < thisScore))
# (scores[idx]!=thisScore && pbAIRandom(10)<3))
@scores[idx]=thisScore
@targets[idx]=scoresAndTargets[i][3]
end
end
end
else
# Choose a move. There is only 1 opposing Pokémon.
if @doublebattle && opponent.isFainted?
opponent=opponent.pbPartner
end
baseDamageArray=[]
baseDamageArrayAdj=[]
for j in 0...4
next if attacker.moves[j].id < 1
# check attacker.moves[j].basedamage and if this is 0 instead check the status method
dmgValue = pbRoughDamage(attacker.moves[j],attacker,opponent,skill,attacker.moves[j].basedamage)
if attacker.moves[j].basedamage!=0
dmgPercent = (dmgValue*100)/(opponent.hp)
dmgPercent = 110 if dmgPercent > 110
if attacker.moves[j].function == 0x115 || attacker.moves[j].function == 0xC3 ||
attacker.moves[j].function == 0xC4 || attacker.moves[j].function == 0xC5 ||
attacker.moves[j].function == 0xC6 || attacker.moves[j].function == 0xC7 ||
attacker.moves[j].function == 0xC8
dmgPercentAdj = (dmgPercent * 0.5)
else
dmgPercentAdj = dmgPercent
end
else
dmgPercent = pbStatusDamage(attacker.moves[j])
dmgPercentAdj = dmgPercent
end
baseDamageArray.push(dmgPercent)
baseDamageArrayAdj.push(dmgPercentAdj)
end
for i in 0...4
if pbCanChooseMove?(index,i,false)
@scores[i]=pbGetMoveScore(attacker.moves[i],attacker,opponent,skill,baseDamageArray[i],baseDamageArrayAdj,i)
@myChoices.push(i)
else
@scores[i] = -1
end
end
end
end
end
################################################################################
# Primary method for deciding which move to use.
################################################################################
def pbChooseMoves(index)
maxscore=0
totalscore=0
attacker=@battlers[index]
skill=pbGetOwner(attacker.index).skill rescue 0
wildbattle=!@opponent && pbIsOpposing?(index)
for i in 0...4
#next if scores[i] == -1
@scores[i]=0 if @scores[i]<0
maxscore=@scores[i] if @scores[i]>maxscore
totalscore+=@scores[i]
end
# Minmax choices depending on AI
if !wildbattle && skill>=PBTrainerAI.mediumSkill
threshold=(skill>=PBTrainerAI.bestSkill) ? 1.5 : (skill>=PBTrainerAI.highSkill) ? 2 : 3
newscore=(skill>=PBTrainerAI.bestSkill) ? 5 : (skill>=PBTrainerAI.highSkill) ? 10 : 15
for i in 0...@scores.length
if @scores[i]>newscore && @scores[i]*threshold<maxscore
totalscore-=(@scores[i]-newscore)
@scores[i]=newscore
end
end
end
if $INTERNAL
x="[#{attacker.pbThis}: "
j=0
for i in 0...4
if attacker.moves[i].id!=0
x+=", " if j>0
x+=PBMoves.getName(attacker.moves[i].id)+"="+@scores[i].to_s
j+=1
end
end
x+="]"
PBDebug.log(x)
end
if !wildbattle #&& maxscore>100
stdev=pbStdDev(@scores)
preferredMoves=[]
for i in 0...4
if attacker.moves[i].id!=0 && (@scores[i] >= (maxscore*0.95)) && pbCanChooseMove?(index,i,false)
preferredMoves.push(i)
preferredMoves.push(i) if @scores[i]==maxscore # Doubly prefer the best move
end
end
if preferredMoves.length>0
i=preferredMoves[pbAIRandom(preferredMoves.length)]
PBDebug.log("[Prefer "+PBMoves.getName(attacker.moves[i].id)+"]") if $INTERNAL
pbRegisterMove(index,i,false)
target=@targets[i] if @targets
if @doublebattle && target && target>=0
pbRegisterTarget(index,target)
end
return
end
end
PBDebug.log("If this battle is not wild, something has gone wrong in scoring moves (no preference chosen).") if $INTERNAL
if !wildbattle && attacker.turncount
badmoves=false
if ((maxscore<=20 && attacker.turncount>2) ||
(maxscore<=30 && attacker.turncount>5)) && pbAIRandom(10)<8
badmoves=true
end
if totalscore<100 && attacker.turncount>1
badmoves=true
movecount=0
for i in 0...4
if attacker.moves[i].id!=0
if @scores[i]>0 && attacker.moves[i].basedamage>0
badmoves=false
end
movecount+=1
end
end
badmoves=badmoves && pbAIRandom(10)!=0
end
end
if maxscore<=0
# If all scores are 0 or less, choose a move at random
if @myChoices.length>0
pbRegisterMove(index,@myChoices[pbAIRandom(@myChoices.length)],false)
else
pbAutoChooseMove(index)
end
else
randnum=pbAIRandom(totalscore)
cumtotal=0
for i in 0...4
if @scores[i]>0
cumtotal+=@scores[i]
if randnum<cumtotal
pbRegisterMove(index,i,false)
target=@targets[i] if @targets
break
end
end
end
end
if @doublebattle && target && target>=0
pbRegisterTarget(index,target)
end
end
##############################################################################
# Get a score for each move being considered (trainer-owned Pokémon only).
# Moves with higher scores are more likely to be chosen.
##############################################################################
def pbGetMoveScore(move,attacker,opponent,skill=100,roughdamage=10,initialscores=[],scoreindex=-1)
if roughdamage<1
roughdamage=1
end
PBDebug.log(sprintf("%s: initial score: %d",PBMoves.getName(move.id),roughdamage)) if $INTERNAL
skill=PBTrainerAI.minimumSkill if skill<PBTrainerAI.minimumSkill
#score=(pbRoughDamage(move,attacker,opponent,skill,move.basedamage)*100/opponent.hp) #roughdamage
score=roughdamage
#Temporarly mega-ing pokemon if it can #perry
if pbCanMegaEvolve?(attacker.index)
attacker.pokemon.makeMega
attacker.pbUpdate(true)
attacker.form=attacker.startform
megaEvolved=true
end
#Little bit of prep before getting into the case statement
oppitemworks = opponent.itemWorks?
attitemworks = attacker.itemWorks?
aimem = getAIMemory(skill,opponent.pokemonIndex)
bettertype = move.pbType(move.type,attacker,opponent)
opponent=attacker.pbOppositeOpposing if !opponent
opponent=opponent.pbPartner if opponent && opponent.isFainted?
roles = pbGetMonRole(attacker,opponent,skill)
if move.priority>0 || (move.basedamage==0 && !attacker.abilitynulled && attacker.ability == PBAbilities::PRANKSTER)
if move.basedamage>0
PBDebug.log(sprintf("Priority Check Begin")) if $INTERNAL
fastermon = (attacker.pbSpeed>pbRoughStat(opponent,PBStats::SPEED,skill)) ^ (@trickroom!=0)
if fastermon
PBDebug.log(sprintf("AI Pokemon is faster.")) if $INTERNAL
else
PBDebug.log(sprintf("Player Pokemon is faster.")) if $INTERNAL
end
if score>100
if @doublebattle
score*=1.3
else
if fastermon
score*=1.3
else
score*=2
end
end
else
if (!attacker.abilitynulled && attacker.ability == PBAbilities::STANCECHANGE)
if !fastermon
score*=0.7
end
end
end
movedamage = -1
opppri = false
pridam = -1
if (attacker.pbSpeed<pbRoughStat(opponent,PBStats::SPEED,skill)) ^ (@trickroom!=0)
if aimem.length > 0
for i in aimem
tempdam = pbRoughDamage(i,opponent,attacker,skill,i.basedamage)
if i.priority>0
opppri=true
if tempdam>pridam
pridam = tempdam
end
end
if tempdam>movedamage
movedamage = tempdam
end
end
end
end
PBDebug.log(sprintf("Expected damage taken: %d",movedamage)) if $INTERNAL
if !fastermon
if movedamage>attacker.hp
if @doublebattle
score+=75
else
score+=150
end
end
end
if opppri
score*=1.1
if pridam>attacker.hp
if fastermon
score*=3
else
score*=0.5
end
end
end
if !fastermon && opponent.effects[PBEffects::TwoTurnAttack]>0
score*=0
end
if $fefieldeffect==37
score*=0
end
if !opponent.abilitynulled && (opponent.ability == PBAbilities::DAZZLING || opponent.ability == PBAbilities::QUEENLYMAJESTY)
score*=0
end
end
score*=0.2 if checkAImoves([PBMoves::QUICKGUARD],aimem)
PBDebug.log(sprintf("Priority Check End")) if $INTERNAL
elsif move.priority<0
if fastermon
score*=0.9
if move.basedamage>0
if opponent.effects[PBEffects::TwoTurnAttack]>0
score*=2
end
end
end
end
##### Alter score depending on the move's function code ########################
score = pbGetMoveScoreFunctions(move,attacker,opponent,skill,roughdamage,initialscores,scoreindex,
score, oppitemworks, attitemworks, aimem, bettertype, roles, tempdam)
###### END FUNCTION CODES
if (!opponent.abilitynulled && opponent.ability == PBAbilities::DANCER)
if (PBStuff::DANCEMOVE).include?(move.id)
score*=0.5
score*=0.1 if $fefieldeffect==6
end
end
ioncheck = false
destinycheck = false
widecheck = false
powdercheck = false
shieldcheck = false
if skill>=PBTrainerAI.highSkill
for j in aimem
ioncheck = true if j.id==(PBMoves::IONDELUGE)
destinycheck = true if j.id==(PBMoves::DESTINYBOND)
widecheck = true if j.id==(PBMoves::WIDEGUARD)
powdercheck = true if j.id==(PBMoves::POWDER)
shieldcheck = true if j.id==(PBMoves::SPIKYSHIELD) ||
j.id==(PBMoves::KINGSSHIELD) || j.id==(PBMoves::BANEFULBUNKER)
end
if @doublebattle && @aiMoveMemory[2][opponent.pbPartner.pokemonIndex].length>0
for j in @aiMoveMemory[2][opponent.pbPartner.pokemonIndex]
widecheck = true if j.id==(PBMoves::WIDEGUARD)
powdercheck = true if j.id==(PBMoves::POWDER)
end
end
end
if ioncheck == true
if move.type == 0
if (!opponent.pbPartner.abilitynulled && opponent.pbPartner.ability == PBAbilities::LIGHTNINGROD) ||
(!opponent.abilitynulled && opponent.ability == PBAbilities::LIGHTNINGROD) ||
(!opponent.abilitynulled && opponent.ability == PBAbilities::VOLTABSORB) ||
(!opponent.abilitynulled && opponent.ability == PBAbilities::MOTORDRIVE)
score *= 0.3
end
end
end
if (move.target==PBTargets::SingleNonUser || move.target==PBTargets::RandomOpposing ||
move.target==PBTargets::AllOpposing || move.target==PBTargets::SingleOpposing ||
move.target==PBTargets::OppositeOpposing)
if move.type==13 || (ioncheck == true && move.type == 0)
if (!opponent.pbPartner.abilitynulled && opponent.pbPartner.ability == PBAbilities::LIGHTNINGROD)
score*=0
elsif (!attacker.pbPartner.abilitynulled && attacker.pbPartner.ability == PBAbilities::LIGHTNINGROD)
score*=0.3
end
elsif move.type==11
if (!opponent.pbPartner.abilitynulled && opponent.pbPartner.ability == PBAbilities::LIGHTNINGROD)
score*=0
elsif (!attacker.pbPartner.abilitynulled && attacker.pbPartner.ability == PBAbilities::LIGHTNINGROD)
score*=0.3
end
end
end
if move.isSoundBased?
if ((!opponent.abilitynulled && opponent.ability == PBAbilities::SOUNDPROOF) && !opponent.moldbroken) || attacker.effects[PBEffects::ThroatChop]!=0
score*=0
else
score *= 0.6 if checkAImoves([PBMoves::THROATCHOP],aimem)
end
end
if move.flags&0x80!=0 # Boosted crit moves
if !((!opponent.abilitynulled && opponent.ability == PBAbilities::SHELLARMOR) ||
(!opponent.abilitynulled && opponent.ability == PBAbilities::BATTLEARMOR) ||
attacker.effects[PBEffects::LaserFocus]>0)
boostercount = 0
if move.pbIsPhysical?(move.type)
boostercount += opponent.stages[PBStats::DEFENSE] if opponent.stages[PBStats::DEFENSE]>0
boostercount -= attacker.stages[PBStats::ATTACK] if attacker.stages[PBStats::ATTACK]<0
elsif move.pbIsSpecial?(move.type)
boostercount += opponent.stages[PBStats::SPDEF] if opponent.stages[PBStats::SPDEF]>0
boostercount -= attacker.stages[PBStats::SPATK] if attacker.stages[PBStats::SPATK]<0
end
score*=(1.05**boostercount)
end
end
if move.basedamage>0
if skill>=PBTrainerAI.highSkill
if opponent.effects[PBEffects::DestinyBond]
score*=0.2
else
if ((opponent.pbSpeed>attacker.pbSpeed) ^ (@trickroom!=0)) && destinycheck
score*=0.7
end
end
end
end
if widecheck && ((move.target == PBTargets::AllOpposing) || (move.target == PBTargets::AllNonUsers))
score*=0.2
end
if powdercheck && move.type==10
score*=0.2
end
if move.isContactMove? && !(attacker.item == PBItems::PROTECTIVEPADS) && !(!attacker.abilitynulled && attacker.ability == PBAbilities::LONGREACH)
if (oppitemworks && opponent.item == PBItems::ROCKYHELMET) || shieldcheck
score*=0.85
end
if !opponent.abilitynulled
if opponent.ability == PBAbilities::ROUGHSKIN || opponent.ability == PBAbilities::IRONBARBS
score*=0.85
elsif opponent.ability == PBAbilities::EFFECTSPORE
score*=0.75
elsif opponent.ability == PBAbilities::FLAMEBODY && attacker.pbCanBurn?(false)
score*=0.75
elsif opponent.ability == PBAbilities::STATIC && attacker.pbCanParalyze?(false)
score*=0.75
elsif opponent.ability == PBAbilities::POISONPOINT && attacker.pbCanPoison?(false)
score*=0.75
elsif opponent.ability == PBAbilities::CUTECHARM && attacker.effects[PBEffects::Attract]<0
if initialscores.length>0
if initialscores[scoreindex] < 102
score*=0.8
end
end
elsif opponent.ability == PBAbilities::GOOEY || opponent.ability == PBAbilities::TANGLINGHAIR
if attacker.pbCanReduceStatStage?(PBStats::SPEED)
score*=0.9
if ((pbRoughStat(opponent,PBStats::SPEED,skill)<attacker.pbSpeed) ^ (@trickroom!=0))
score*=0.8
end
end
elsif opponent.ability == PBAbilities::MUMMY
if !attacker.abilitynulled && !attacker.unstoppableAbility? &&
attacker.ability != opponent.ability && attacker.ability != PBAbilities::SHIELDDUST
mummyscore = getAbilityDisruptScore(move,opponent,attacker,skill)
if mummyscore < 2
mummyscore = 2 - mummyscore
else
mummyscore = 0
end
score*=mummyscore
end
end
end
if (!attacker.abilitynulled && attacker.ability == PBAbilities::POISONTOUCH) && opponent.pbCanPoison?(false)
score*=1.1
end
if (!attacker.abilitynulled && attacker.ability == PBAbilities::PICKPOCKET) && opponent.item!=0 && !pbIsUnlosableItem(opponent,opponent.item)
score*=1.1
end
if opponent.effects[PBEffects::KingsShield]== true ||
opponent.effects[PBEffects::BanefulBunker]== true ||
opponent.effects[PBEffects::SpikyShield]== true
score *=0.1
end
end
if move.basedamage>0 && (opponent.effects[PBEffects::SpikyShield] ||
opponent.effects[PBEffects::BanefulBunker] || opponent.effects[PBEffects::KingsShield])
score*=0.1
end
if move.basedamage==0
if hasgreatmoves(initialscores,scoreindex,skill)
maxdam=checkAIdamage(aimem,attacker,opponent,skill)
if maxdam>0 && maxdam<(attacker.hp*0.3)
score*=0.6
else
score*=0.2 ### highly controversial, revert to 0.1 if shit sucks
end
end
end
ispowder = (move.id==214 || move.id==218 || move.id==220 || move.id==445 || move.id==600 || move.id==18 || move.id==219)
if ispowder && (opponent.type==(PBTypes::GRASS) ||
(!opponent.abilitynulled && opponent.ability == PBAbilities::OVERCOAT) ||
(oppitemworks && opponent.item == PBItems::SAFETYGOGGLES))
score*=0
end
# A score of 0 here means it should absolutely not be used
if score<=0
PBDebug.log(sprintf("%s: final score: 0",PBMoves.getName(move.id))) if $INTERNAL
PBDebug.log(sprintf(" ")) if $INTERNAL
attacker.pbUpdate(true) if defined?(megaEvolved) && megaEvolved==true #perry
return score
end
##### Other score modifications ################################################
# Prefer damaging moves if AI has no more Pokémon
if attacker.pbNonActivePokemonCount==0
if skill>=PBTrainerAI.mediumSkill &&
!(skill>=PBTrainerAI.highSkill && opponent.pbNonActivePokemonCount>0)
if move.basedamage==0
PBDebug.log("[Not preferring status move]") if $INTERNAL
score*=0.9
elsif opponent.hp<=opponent.totalhp/2.0
PBDebug.log("[Preferring damaging move]") if $INTERNAL
score*=1.1
end
end
end
# Don't prefer attacking the opponent if they'd be semi-invulnerable
if opponent.effects[PBEffects::TwoTurnAttack]>0 &&
skill>=PBTrainerAI.highSkill
invulmove=$pkmn_move[opponent.effects[PBEffects::TwoTurnAttack]][0] #the function code of the current move
if move.accuracy>0 && # Checks accuracy, i.e. targets opponent
([0xC9,0xCA,0xCB,0xCC,0xCD,0xCE].include?(invulmove) ||
opponent.effects[PBEffects::SkyDrop]) &&
((attacker.pbSpeed>opponent.pbSpeed) ^ (@trickroom!=0))
if skill>=PBTrainerAI.bestSkill # Can get past semi-invulnerability
miss=false
case invulmove
when 0xC9, 0xCC # Fly, Bounce
miss=true unless move.function==0x08 || # Thunder
move.function==0x15 || # Hurricane
move.function==0x77 || # Gust
move.function==0x78 || # Twister
move.function==0x11B || # Sky Uppercut
move.function==0x11C || # Smack Down
(move.id == PBMoves::WHIRLWIND)
when 0xCA # Dig
miss=true unless move.function==0x76 || # Earthquake
move.function==0x95 # Magnitude
when 0xCB # Dive
miss=true unless move.function==0x75 || # Surf
move.function==0xD0 || # Whirlpool
move.function==0x12D # Shadow Storm
when 0xCD # Shadow Force
miss=true
when 0xCE # Sky Drop
miss=true unless move.function==0x08 || # Thunder
move.function==0x15 || # Hurricane
move.function==0x77 || # Gust
move.function==0x78 || # Twister
move.function==0x11B || # Sky Uppercut
move.function==0x11C # Smack Down
end
if opponent.effects[PBEffects::SkyDrop]
miss=true unless move.function==0x08 || # Thunder
move.function==0x15 || # Hurricane
move.function==0x77 || # Gust
move.function==0x78 || # Twister
move.function==0x11B || # Sky Uppercut
move.function==0x11C # Smack Down
end
score*=0 if miss
else
score*=0
end
end
end
# Pick a good move for the Choice items
if attitemworks && (attacker.item == PBItems::CHOICEBAND ||
attacker.item == PBItems::CHOICESPECS || attacker.item == PBItems::CHOICESCARF)
if move.basedamage==0 && move.function!=0xF2 # Trick
score*=0.1
end
if ((move.type == PBTypes::NORMAL) && $fefieldeffect!=29) ||
(move.type == PBTypes::GHOST) || (move.type == PBTypes::FIGHTING) ||
(move.type == PBTypes::DRAGON) || (move.type == PBTypes::PSYCHIC) ||
(move.type == PBTypes::GROUND) || (move.type == PBTypes::ELECTRIC) ||
(move.type == PBTypes::POISON)
score*=0.95
end
if (move.type == PBTypes::FIRE) || (move.type == PBTypes::WATER) ||
(move.type == PBTypes::GRASS) || (move.type == PBTypes::ELECTRIC)
score*=0.95
end
if move.accuracy > 0
miniacc = (move.accuracy/100.0)
score *= miniacc
end
if move.pp < 6
score *= 0.9
end
end
#If user is frozen, prefer a move that can thaw the user
if attacker.status==PBStatuses::FROZEN
if skill>=PBTrainerAI.mediumSkill
if move.canThawUser?
score+=30
else
hasFreezeMove=false
for m in attacker.moves
if m.canThawUser?
hasFreezeMove=true; break
end
end
score*=0 if hasFreezeMove
end
end
end
# If target is frozen, don't prefer moves that could thaw them
if opponent.status==PBStatuses::FROZEN
if (move.type == PBTypes::FIRE)
score *= 0.1
end
end
# Adjust score based on how much damage it can deal
if move.basedamage>0
typemod=pbTypeModNoMessages(bettertype,attacker,opponent,move,skill)
if typemod==0 || score<=0
score=0
elsif skill>=PBTrainerAI.mediumSkill && !(!attacker.abilitynulled &&
(attacker.ability == PBAbilities::MOLDBREAKER ||
attacker.ability == PBAbilities::TURBOBLAZE ||
attacker.ability == PBAbilities::TERAVOLT))
if !opponent.abilitynulled
if (typemod<=4 && opponent.ability == PBAbilities::WONDERGUARD) ||
(move.type == PBTypes::GROUND && (opponent.ability == PBAbilities::LEVITATE || (oppitemworks && opponent.item == PBItems::AIRBALLOON) || opponent.effects[PBEffects::MagnetRise]>0)) ||
(move.type == PBTypes::FIRE && opponent.ability == PBAbilities::FLASHFIRE) ||
(move.type == PBTypes::WATER && (opponent.ability == PBAbilities::WATERABSORB || opponent.ability == PBAbilities::STORMDRAIN || opponent.ability == PBAbilities::DRYSKIN)) ||
(move.type == PBTypes::GRASS && opponent.ability == PBAbilities::SAPSIPPER) ||
(move.type == PBTypes::ELECTRIC)&& (opponent.ability == PBAbilities::VOLTABSORB || opponent.ability == PBAbilities::LIGHTNINGROD || opponent.ability == PBAbilities::MOTORDRIVE)
score=0
end
end
else
if move.type == PBTypes::GROUND && (opponent.ability == PBAbilities::LEVITATE || (oppitemworks && opponent.item == PBItems::AIRBALLOON) || opponent.effects[PBEffects::MagnetRise]>0)
score=0
end
end
if score != 0
# Calculate how much damage the move will do (roughly)
realBaseDamage=move.basedamage
realBaseDamage=60 if move.basedamage==1
if skill>=PBTrainerAI.mediumSkill
realBaseDamage=pbBetterBaseDamage(move,attacker,opponent,skill,realBaseDamage)
end
end
else # non-damaging moves
if !opponent.abilitynulled
if (move.type == PBTypes::GROUND && (opponent.ability == PBAbilities::LEVITATE || (oppitemworks && opponent.item == PBItems::AIRBALLOON) || opponent.effects[PBEffects::MagnetRise]>0)) ||
(move.type == PBTypes::FIRE && opponent.ability == PBAbilities::FLASHFIRE) ||
(move.type == PBTypes::WATER && (opponent.ability == PBAbilities::WATERABSORB || opponent.ability == PBAbilities::STORMDRAIN || opponent.ability == PBAbilities::DRYSKIN)) ||
(move.type == PBTypes::GRASS && opponent.ability == PBAbilities::SAPSIPPER) ||
(move.type == PBTypes::ELECTRIC)&& (opponent.ability == PBAbilities::VOLTABSORB || opponent.ability == PBAbilities::LIGHTNINGROD || opponent.ability == PBAbilities::MOTORDRIVE)
score=0
end
end
end
accuracy=pbRoughAccuracy(move,attacker,opponent,skill)
score*=accuracy/100.0
#score=0 if score<=10 && skill>=PBTrainerAI.highSkill
if (move.basedamage==0 && !(move.id == PBMoves::NATUREPOWER)) &&
(move.target==PBTargets::SingleNonUser || move.target==PBTargets::RandomOpposing ||
move.target==PBTargets::AllOpposing || move.target==PBTargets::OpposingSide ||
move.target==PBTargets::SingleOpposing || move.target==PBTargets::OppositeOpposing) &&
((!opponent.abilitynulled && opponent.ability == PBAbilities::MAGICBOUNCE) ||
(!opponent.pbPartner.abilitynulled && opponent.pbPartner.ability == PBAbilities::MAGICBOUNCE))
score=0
end
if skill>=PBTrainerAI.mediumSkill
if (!attacker.abilitynulled && attacker.ability == PBAbilities::PRANKSTER)
if opponent.pbHasType?(:DARK)
if move.basedamage==0 && move.priority>-1
score=0
end
end
end
end
# Avoid shiny wild pokemon if you're an AI partner
if pbIsWild?
if attacker.index == 2
if opponent.pokemon.isShiny?
score *= 0.15
end
end
end
score=score.to_i
score=0 if score<0
PBDebug.log(sprintf("%s: final score: %d",PBMoves.getName(move.id),score)) if $INTERNAL
PBDebug.log(sprintf(" ")) if $INTERNAL
attacker.pbUpdate(true) if defined?(megaEvolved) && megaEvolved==true #perry
return score
end
##############################################################################
# Decide whether the opponent should use a Z-Move.
##############################################################################
def pbEnemyShouldZMove?(index)
return pbCanZMove?(index) #Conditions based on effectiveness and type handled later
end
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,121 +0,0 @@
class PokeBattle_Battle
attr_accessor :aiMoveMemory
alias __ai__initialize initialize
def initialize(battle)
__ai__initialize(battle)
@aiMoveMemory = [[],
[],
[[], [], [], [], [], [], [], [], [], [], [], []] # One array for each party index
]
end
################################################################################
# AI Memory utility functions
################################################################################
def getAIMemory(skill,index=0)
if skill>=PBTrainerAI.bestSkill
return @aiMoveMemory[2][index]
elsif skill>=PBTrainerAI.highSkill
return @aiMoveMemory[1]
elsif skill>=PBTrainerAI.mediumSkill
return @aiMoveMemory[0]
else
return []
end
end
def checkAImoves(moveID,memory)
#basic "does the other mon have x"
return false if memory.length == 0
for i in moveID
for j in memory
j = pbChangeMove(j,nil)#doesn't matter that i'm passing nil, won't get used
return true if i == j.id #i should already be an ID here
end
end
return false
end
def checkAIhealing(memory)
#less basic "can the other mon heal"
return false if memory.length == 0
for j in memory
return true if j.isHealingMove?
end
return false
end
def checkAIpriority(memory)
#"does the other mon have priority"
return false if memory.length == 0
for j in memory
return true if j.priority>0
end
return false
end
def checkAIaccuracy(memory)
#"does the other mon have moves that don't miss"
return false if memory.length == 0
for j in memory
j = pbChangeMove(j,nil)
return true if j.accuracy==0
end
return false
end
def checkAIdamage(memory,attacker,opponent,skill)
#returns how much damage the AI expects to take
return -1 if memory.length == 0
maxdam=0
for j in memory
tempdam = pbRoughDamage(j,opponent,attacker,skill,j.basedamage)
maxdam=tempdam if tempdam>maxdam
end
return maxdam
end
def checkAIbest(memory,modifier,type=[],usepower=true,attacker=nil,opponent=nil,skill=nil)
return false if memory.length == 0
#had to split this because switching ai uses power
bestmove = 0
if usepower
biggestpower = 0
for j in memory
if j.basedamage>biggestpower
biggestpower=j.basedamage
bestmove=j
end
end
else #maxdam
maxdam=0
for j in memory
tempdam = pbRoughDamage(j,opponent,attacker,skill,j.basedamage)
if tempdam>maxdam
maxdam=tempdam
bestmove=j
end
end
end
return false if bestmove==0
#i don't want to make multiple functions for rare cases
#we're doing it in one and you're gonna like it
case modifier
when 1 #type mod. checks types from a list.
return true if type.include?(bestmove.type)
when 2 #physical mod.
return true if bestmove.pbIsPhysical?(bestmove.type)
when 3 #special mod.
return true if bestmove.pbIsSpecial?(bestmove.type)
when 4 #contact mod.
return true if bestmove.isContactMove?
when 5 #sound mod.
return true if bestmove.isSoundBased?
when 6 #why.
return true if (PBStuff::BULLETMOVE).include?(bestmove.id)
end
return false #you're still here? it's over! go home.
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -1,308 +0,0 @@
class PokeBattle_Battle
def pbGetMonRole(mon,opponent,skill,position=0,party=nil)
#PBDebug.log(sprintf("Beginning role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
monRoles=[]
monability = mon.ability.to_i
curemove=false
healingmove=false
wishmove=false
phasemove=false
priorityko=false
pivotmove=false
spinmove=false
batonmove=false
tauntmove=false
restmove=false
weathermove=false
fieldmove=false
if mon.class == PokeBattle_Battler
if mon.ev[3]>251 && (mon.nature==PBNatures::MODEST ||
mon.nature==PBNatures::JOLLY || mon.nature==PBNatures::TIMID ||
mon.nature==PBNatures::ADAMANT) || (mon.item==(PBItems::CHOICEBAND) ||
mon.item==(PBItems::CHOICESPECS) || mon.item==(PBItems::CHOICESCARF))
monRoles.push(PBMonRoles::SWEEPER)
end
for i in mon.moves
next if i.nil?
next if i.id == 0
if i.priority>0
dam=pbRoughDamage(i,mon,opponent,skill,i.basedamage)
if opponent.hp>0
percentage=(dam*100.0)/opponent.hp
priorityko=true if percentage>100
end
end
if i.isHealingMove?
healingmove=true
elsif (i.id == (PBMoves::HEALBELL) || i.id == (PBMoves::AROMATHERAPY))
curemove=true
elsif (i.id == (PBMoves::WISH))
wishmove=true
elsif (i.id == (PBMoves::YAWN) || i.id == (PBMoves::PERISHSONG) ||
i.id == (PBMoves::DRAGONTAIL) || i.id == (PBMoves::CIRCLETHROW) ||
i.id == (PBMoves::WHIRLWIND) || i.id == (PBMoves::ROAR))
phasemove=true
elsif (i.id == (PBMoves::UTURN) || i.id == (PBMoves::VOLTSWITCH))
pivotmove=true
elsif (i.id == (PBMoves::RAPIDSPIN))
spinmove=true
elsif (i.id == (PBMoves::BATONPASS))
batonmove=true
elsif (i.id == (PBMoves::TAUNT))
tauntmove=true
elsif (i.id == (PBMoves::REST))
restmove=true
elsif (i.id == (PBMoves::SUNNYDAY) || i.id == (PBMoves::RAINDANCE) ||
i.id == (PBMoves::HAIL) || i.id == (PBMoves::SANDSTORM))
weathermove=true
elsif (i.id == (PBMoves::GRASSYTERRAIN) || i.id == (PBMoves::ELECTRICTERRAIN) ||
i.id == (PBMoves::MISTYTERRAIN) || i.id == (PBMoves::PSYCHICTERRAIN) ||
i.id == (PBMoves::MIST) || i.id == (PBMoves::IONDELUGE) ||
i.id == (PBMoves::TOPSYTURVY))
fieldmove=true
end
end
if healingmove && (mon.ev[2]>251 && (mon.nature==PBNatures::BOLD ||
mon.nature==PBNatures::RELAXED || mon.nature==PBNatures::IMPISH ||
mon.nature==PBNatures::LAX))
monRoles.push(PBMonRoles::PHYSICALWALL)
end
if healingmove && (mon.ev[5]>251 && (mon.nature==PBNatures::CALM ||
mon.nature==PBNatures::GENTLE || mon.nature==PBNatures::SASSY ||
mon.nature==PBNatures::CAREFUL))
monRoles.push(PBMonRoles::SPECIALWALL)
end
if mon.pokemonIndex==0
monRoles.push(PBMonRoles::LEAD)
end
if curemove || (wishmove && mon.ev[0]>251)
monRoles.push(PBMonRoles::CLERIC)
end
if phasemove == true
monRoles.push(PBMonRoles::PHAZER)
end
if mon.item==(PBItems::LIGHTCLAY)
monRoles.push(PBMonRoles::SCREENER)
end
if priorityko || (mon.speed>opponent.speed)
monRoles.push(PBMonRoles::REVENGEKILLER)
end
if (pivotmove && healingmove) || (monability == PBAbilities::REGENERATOR)
monRoles.push(PBMonRoles::PIVOT)
end
if spinmove
monRoles.push(PBMonRoles::SPINNER)
end
if (mon.ev[0]>251 && !healingmove) || mon.item==(PBItems::ASSAULTVEST)
monRoles.push(PBMonRoles::TANK)
end
if batonmove
monRoles.push(PBMonRoles::BATONPASSER)
end
if tauntmove || mon.item==(PBItems::CHOICEBAND) ||
mon.item==(PBItems::CHOICESPECS)
monRoles.push(PBMonRoles::STALLBREAKER)
end
if restmove || (monability == PBAbilities::COMATOSE) ||
mon.item==(PBItems::TOXICORB) || mon.item==(PBItems::FLAMEORB) ||
(monability == PBAbilities::GUTS) ||
(monability == PBAbilities::QUICKFEET)||
(monability == PBAbilities::FLAREBOOST) ||
(monability == PBAbilities::TOXICBOOST) ||
(monability == PBAbilities::NATURALCURE) ||
(monability == PBAbilities::MAGICGUARD) ||
(monability == PBAbilities::MAGICBOUNCE) ||
((monability == PBAbilities::HYDRATION) && pbWeather==PBWeather::RAINDANCE)
monRoles.push(PBMonRoles::STATUSABSORBER)
end
if (monability == PBAbilities::SHADOWTAG) ||
(monability == PBAbilities::ARENATRAP) ||
(monability == PBAbilities::MAGNETPULL)
monRoles.push(PBMonRoles::TRAPPER)
end
if weathermove || (monability == PBAbilities::DROUGHT) ||
(monability == PBAbilities::SANDSTREAM) ||
(monability == PBAbilities::DRIZZLE) ||
(monability == PBAbilities::SNOWWARNING) ||
(monability == PBAbilities::PRIMORDIALSEA) ||
(monability == PBAbilities::DESOLATELAND) ||
(monability == PBAbilities::DELTASTREAM)
monRoles.push(PBMonRoles::WEATHERSETTER)
end
if fieldmove || (monability == PBAbilities::GRASSYSURGE) ||
(monability == PBAbilities::ELECTRICSURGE) ||
(monability == PBAbilities::MISTYSURGE) ||
(monability == PBAbilities::PSYCHICSURGE) ||
mon.item==(PBItems::AMPLIFIELDROCK)
monRoles.push(PBMonRoles::FIELDSETTER)
end
#if $game_switches[525] && mon.pokemonIndex==(pbParty(mon.index).length-1)
if mon.pokemonIndex==(pbParty(mon.index).length-1)
monRoles.push(PBMonRoles::ACE)
end
secondhighest=true
if pbParty(mon.index).length>2
for i in 0..(pbParty(mon.index).length-2)
next if pbParty(mon.index)[i].nil?
if mon.level<pbParty(mon.index)[i].level
secondhighest=false
end
end
end
#if $game_switches[525]&& secondhighest
if secondhighest
monRoles.push(PBMonRoles::SECOND)
end
#PBDebug.log(sprintf("Ending role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
#PBDebug.log(sprintf("")) if $INTERNAL
return monRoles
elsif mon.class == PokeBattle_Pokemon
movelist = []
for i in mon.moves
next if i.nil?
next if i.id == 0
movedummy = PokeBattle_Move.pbFromPBMove(self,i,mon)
movelist.push(movedummy)
end
if mon.ev[3]>251 && (mon.nature==PBNatures::MODEST ||
mon.nature==PBNatures::JOLLY || mon.nature==PBNatures::TIMID ||
mon.nature==PBNatures::ADAMANT) || (mon.item==(PBItems::CHOICEBAND) ||
mon.item==(PBItems::CHOICESPECS) || mon.item==(PBItems::CHOICESCARF))
monRoles.push(PBMonRoles::SWEEPER)
end
for i in movelist
next if i.nil?
if i.isHealingMove?
healingmove=true
elsif (i.id == (PBMoves::HEALBELL) || i.id == (PBMoves::AROMATHERAPY))
curemove=true
elsif (i.id == (PBMoves::WISH))
wishmove=true
elsif (i.id == (PBMoves::YAWN) || i.id == (PBMoves::PERISHSONG) ||
i.id == (PBMoves::DRAGONTAIL) || i.id == (PBMoves::CIRCLETHROW) ||
i.id == (PBMoves::WHIRLWIND) || i.id == (PBMoves::ROAR))
phasemove=true
elsif (i.id == (PBMoves::UTURN) || i.id == (PBMoves::VOLTSWITCH))
pivotmove=true
elsif (i.id == (PBMoves::RAPIDSPIN))
spinmove=true
elsif (i.id == (PBMoves::BATONPASS))
batonmove=true
elsif(i.id == (PBMoves::TAUNT))
tauntmove=true
elsif (i.id == (PBMoves::REST))
restmove=true
elsif (i.id == (PBMoves::SUNNYDAY) || i.id == (PBMoves::RAINDANCE) ||
i.id == (PBMoves::HAIL) || i.id == (PBMoves::SANDSTORM))
weathermove=true
elsif (i.id == (PBMoves::GRASSYTERRAIN) || i.id == (PBMoves::ELECTRICTERRAIN) ||
i.id == (PBMoves::MISTYTERRAIN) || i.id == (PBMoves::PSYCHICTERRAIN) ||
i.id == (PBMoves::MIST) || i.id == (PBMoves::IONDELUGE) ||
i.id == (PBMoves::TOPSYTURVY))
fieldmove=true
end
end
if healingmove && (mon.ev[2]>251 && (mon.nature==PBNatures::BOLD ||
mon.nature==PBNatures::RELAXED || mon.nature==PBNatures::IMPISH ||
mon.nature==PBNatures::LAX))
monRoles.push(PBMonRoles::PHYSICALWALL)
end
if healingmove && (mon.ev[5]>251 && (mon.nature==PBNatures::CALM ||
mon.nature==PBNatures::GENTLE || mon.nature==PBNatures::SASSY ||
mon.nature==PBNatures::CAREFUL))
monRoles.push(PBMonRoles::SPECIALWALL)
end
if position==0
monRoles.push(PBMonRoles::LEAD)
end
if (phasemove)
monRoles.push(PBMonRoles::PHAZER)
end
if mon.item==(PBItems::LIGHTCLAY)
monRoles.push(PBMonRoles::SCREENER)
end
# pbRoughDamage does not take Pokemon objects, this will cause issues
priorityko=false
for i in movelist
next if i.priority<1
next if i.basedamage<10
priorityko=true
end
if priorityko || (mon.speed>opponent.speed)
monRoles.push(PBMonRoles::REVENGEKILLER)
end
if (pivotmove && healingmove) || (monability == PBAbilities::REGENERATOR)
monRoles.push(PBMonRoles::PIVOT)
end
if spinmove
monRoles.push(PBMonRoles::SPINNER)
end
if (mon.ev[0]>251 && !healingmove) || mon.item==(PBItems::ASSAULTVEST)
monRoles.push(PBMonRoles::TANK)
end
if batonmove
monRoles.push(PBMonRoles::BATONPASSER)
end
if tauntmove || mon.item==(PBItems::CHOICEBAND) ||
mon.item==(PBItems::CHOICESPECS)
monRoles.push(PBMonRoles::STALLBREAKER)
end
if restmove || (monability == PBAbilities::COMATOSE) ||
mon.item==(PBItems::TOXICORB) || mon.item==(PBItems::FLAMEORB) ||
(monability == PBAbilities::GUTS) ||
(monability == PBAbilities::QUICKFEET) ||
(monability == PBAbilities::FLAREBOOST) ||
(monability == PBAbilities::TOXICBOOST) ||
(monability == PBAbilities::NATURALCURE) ||
(monability == PBAbilities::MAGICGUARD) ||
(monability == PBAbilities::MAGICBOUNCE) ||
((monability == PBAbilities::HYDRATION) && pbWeather==PBWeather::RAINDANCE)
monRoles.push(PBMonRoles::STATUSABSORBER)
end
if (monability == PBAbilities::SHADOWTAG) ||
(monability == PBAbilities::ARENATRAP) ||
(monability == PBAbilities::MAGNETPULL)
monRoles.push(PBMonRoles::TRAPPER)
end
if weathermove || (monability == PBAbilities::DROUGHT) ||
(monability == PBAbilities::SANDSTREAM) ||
(monability == PBAbilities::DRIZZLE) ||
(monability == PBAbilities::SNOWWARNING) ||
(monability == PBAbilities::PRIMORDIALSEA) ||
(monability == PBAbilities::DESOLATELAND) ||
(monability == PBAbilities::DELTASTREAM)
monRoles.push(PBMonRoles::WEATHERSETTER)
end
if fieldmove || (monability == PBAbilities::GRASSYSURGE) ||
(monability == PBAbilities::ELECTRICSURGE) ||
(monability == PBAbilities::MISTYSURGE) ||
(monability == PBAbilities::PSYCHICSURGE) ||
mon.item==(PBItems::AMPLIFIELDROCK)
monRoles.push(PBMonRoles::FIELDSETTER)
end
if position==(party.length-1)
#if $game_switches[525] && position==(party.length-1)
monRoles.push(PBMonRoles::ACE)
end
secondhighest=true
if party.length>2
for i in 0..(party.length-2)
next if party[i].nil?
if mon.level<party[i].level
secondhighest=false
end
end
end
#if $game_switches[525]&& secondhighest
if secondhighest
monRoles.push(PBMonRoles::SECOND)
end
#PBDebug.log(sprintf("Ending role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
#PBDebug.log(sprintf("")) if $INTERNAL
return monRoles
end
#PBDebug.log(sprintf("Ending role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
#PBDebug.log(sprintf("")) if $INTERNAL
return monRoles
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -1,209 +0,0 @@
class PokeBattle_Battle
attr_reader :battleAI
alias mkai_initialize initialize
def initialize(*args)
mkai_initialize(*args)
@battleAI = MKAI.new(self, self.wildBattle?)
@battleAI.sides[0].set_party(@party1)
@battleAI.sides[0].set_trainers(@player)
@battleAI.sides[1].set_party(@party2)
@battleAI.sides[1].set_trainers(@opponent)
end
def pbRecallAndReplace(idxBattler, idxParty, batonPass = false)
if !@battlers[idxBattler].fainted?
@scene.pbRecall(idxBattler)
@battleAI.sides[idxBattler % 2].recall(idxBattler)
end
@battlers[idxBattler].pbAbilitiesOnSwitchOut # Inc. primordial weather check
@scene.pbShowPartyLineup(idxBattler & 1) if pbSideSize(idxBattler) == 1
pbMessagesOnReplace(idxBattler, idxParty)
pbReplace(idxBattler, idxParty, batonPass)
end
# Bug fix (used b instead of battler)
def pbMessageOnRecall(battler)
if battler.pbOwnedByPlayer?
if battler.hp<=battler.totalhp/4
pbDisplayBrief(_INTL("Good job, {1}! Come back!",battler.name))
elsif battler.hp<=battler.totalhp/2
pbDisplayBrief(_INTL("OK, {1}! Come back!",battler.name))
elsif battler.turnCount>=5
pbDisplayBrief(_INTL("{1}, thats enough! Come back!",battler.name))
elsif battler.turnCount>=2
pbDisplayBrief(_INTL("{1}, come back!",battler.name))
else
pbDisplayBrief(_INTL("{1}, switch out! Come back!",battler.name))
end
else
owner = pbGetOwnerName(battler.index)
pbDisplayBrief(_INTL("{1} withdrew {2}!",owner,battler.name))
end
end
alias mkai_pbEndOfRoundPhase pbEndOfRoundPhase
def pbEndOfRoundPhase
mkai_pbEndOfRoundPhase
@battleAI.end_of_round
end
alias mkai_pbShowAbilitySplash pbShowAbilitySplash
def pbShowAbilitySplash(battler, delay = false, logTrigger = true)
mkai_pbShowAbilitySplash(battler, delay, logTrigger)
@battleAI.reveal_ability(battler)
end
end
class PokeBattle_Move
attr_reader :statUp
attr_reader :statDown
alias mkai_pbReduceDamage pbReduceDamage
def pbReduceDamage(user, target)
mkai_pbReduceDamage(user, target)
@battle.battleAI.register_damage(self, user, target, target.damageState.hpLost)
end
def pbCouldBeCritical?(user, target)
return false if target.pbOwnSide.effects[PBEffects::LuckyChant] > 0
# Set up the critical hit ratios
ratios = (NEWEST_BATTLE_MECHANICS) ? [24,8,2,1] : [16,8,4,3,2]
c = 0
# Ability effects that alter critical hit rate
if c >= 0 && user.abilityActive?
c = BattleHandlers.triggerCriticalCalcUserAbility(user.ability, user, target, c)
end
if c >= 0 && target.abilityActive? && !@battle.moldBreaker
c = BattleHandlers.triggerCriticalCalcTargetAbility(target.ability, user, target, c)
end
# Item effects that alter critical hit rate
if c >= 0 && user.itemActive?
c = BattleHandlers.triggerCriticalCalcUserItem(user.item, user, target, c)
end
if c >= 0 && target.itemActive?
c = BattleHandlers.triggerCriticalCalcTargetItem(target.item, user, target, c)
end
return false if c < 0
# Move-specific "always/never a critical hit" effects
return false if pbCritialOverride(user,target) == -1
return true
end
end
class MKAI
def pbAIRandom(x)
return rand(x)
end
def pbDefaultChooseEnemyCommand(idxBattler)
sideIndex = idxBattler % 2
index = MKAI.battler_to_proj_index(idxBattler)
side = @sides[sideIndex]
projection = side.battlers[index]
# Choose move
data = projection.choose_move
if data.nil?
# Struggle
@battle.pbAutoChooseMove(idxBattler)
elsif data[0] == :ITEM
# [:ITEM, item_id, target&]
item = data[1]
# Determine target of item (always the Pokémon choosing the action)
useType = pbGetItemData(item, ITEM_BATTLE_USE)
if data[2]
target_index = data[2]
else
target_index = idxBattler
if useType && (useType == 1 || useType == 6) # Use on Pokémon
target_index = @battle.battlers[target_index].pokemonIndex # Party Pokémon
end
end
# Register our item
@battle.pbRegisterItem(idxBattler, item, target_index)
elsif data[0] == :SWITCH
# [:SWITCH, pokemon_index]
@battle.pbRegisterSwitch(idxBattler, data[1])
else
# [move_index, move_target]
move_index, move_target = data
# Mega evolve if we determine that we should
@battle.pbRegisterMegaEvolution(idxBattler) if projection.should_mega_evolve?(idxBattler)
# Register our move
@battle.pbRegisterMove(idxBattler, move_index, false)
# Register the move's target
@battle.pbRegisterTarget(idxBattler, move_target)
end
end
#=============================================================================
# Choose a replacement Pokémon
#=============================================================================
def pbDefaultChooseNewEnemy(idxBattler, party)
proj = self.battler_to_projection(@battle.battlers[idxBattler])
scores = proj.get_optimal_switch_choice
scores.each do |_, _, proj|
pkmn = proj.pokemon
index = @battle.pbParty(idxBattler).index(pkmn)
if @battle.pbCanSwitchLax?(idxBattler, index)
return index
end
end
return -1
end
end
class PokeBattle_Battler
alias mkai_pbInitialize pbInitialize
def pbInitialize(pkmn, idxParty, batonPass = false)
mkai_pbInitialize(pkmn, idxParty, batonPass)
ai = @battle.battleAI
sideIndex = @index % 2
ai.sides[sideIndex].send_out(@index, self)
end
alias mkai_pbFaint pbFaint
def pbFaint(*args)
mkai_pbFaint(*args)
@battle.battleAI.faint_battler(self)
end
end
class PokeBattle_PoisonMove
attr_reader :toxic
end
class Array
def sum
n = 0
self.each { |e| n += e }
n
end
end
# Overwrite Frisk to show the enemy held item
BattleHandlers::AbilityOnSwitchIn.add(:FRISK,
proc { |ability,battler,battle|
foes = []
battle.eachOtherSideBattler(battler.index) do |b|
foes.push(b) if b.item > 0
end
if foes.length > 0
battle.pbShowAbilitySplash(battler)
if NEWEST_BATTLE_MECHANICS
foes.each do |b|
battle.pbDisplay(_INTL("{1} frisked {2} and found its {3}!",
battler.pbThis, b.pbThis(true), PBItems.getName(b.item)))
battle.battleAI.reveal_item(b)
end
else
foe = foes[battle.pbRandom(foes.length)]
battle.pbDisplay(_INTL("{1} frisked the foe and found one {2}!",
battler.pbThis, PBItems.getName(foe.item)))
battle.battleAI.reveal_item(foe)
end
battle.pbHideAbilitySplash(battler)
end
}
)

View File

@@ -1,133 +0,0 @@
class MKAI
attr_reader :battle
attr_reader :sides
def initialize(battle, wild_battle)
@battle = battle
@sides = [Side.new(self, 0), Side.new(self, 1, wild_battle)]
MKAI.log("AI initialized")
end
def self.battler_to_proj_index(battlerIndex)
if battlerIndex % 2 == 0 # Player side: 0, 2, 4 -> 0, 1, 2
return battlerIndex / 2
else # Opponent side: 1, 3, 5 -> 0, 1, 2
return (battlerIndex - 1) / 2
end
end
def self.weighted_rand(weights)
num = rand(weights.sum)
for i in 0...weights.size
if num < weights[i]
return i
else
num -= weights[i]
end
end
return nil
end
def self.get_weights(factor, weights)
avg = weights.sum / weights.size.to_f
newweights = weights.map do |e|
diff = e - avg
next [0, ((e - diff * factor) * 100).round].max
end
return newweights
end
def self.weighted_factored_rand(factor, weights)
avg = weights.sum / weights.size.to_f
newweights = weights.map do |e|
diff = e - avg
next [0, ((e - diff * factor) * 100).round].max
end
return weighted_rand(newweights)
end
def self.log(msg)
echoln msg
end
def battler_to_projection(battler)
@sides.each do |side|
side.battlers.each do |projection|
if projection && projection.pokemon == battler.pokemon
return projection
end
end
side.party.each do |projection|
if projection && projection.pokemon == battler.pokemon
return projection
end
end
end
return nil
end
def pokemon_to_projection(pokemon)
@sides.each do |side|
side.battlers.each do |projection|
if projection && projection.pokemon == pokemon
return projection
end
end
side.party.each do |projection|
if projection && projection.pokemon == pokemon
return projection
end
end
end
return nil
end
def register_damage(move, user, target, damage)
user = battler_to_projection(user)
target = battler_to_projection(target)
user.register_damage_dealt(move, target, damage)
target.register_damage_taken(move, user, damage)
end
def faint_battler(battler)
# Remove the battler from the AI's list of the active battlers
@sides.each do |side|
side.battlers.each_with_index do |proj, index|
if proj && proj.battler == battler
# Decouple the projection from the battler
side.recall(battler.index)
side.battlers[index] = nil
break
end
end
end
end
def end_of_round
@sides.each { |side| side.end_of_round }
end
def reveal_ability(battler)
@sides.each do |side|
side.battlers.each do |proj|
if proj && proj.battler == battler && !proj.revealed_ability
proj.revealed_ability = true
MKAI.log("#{proj.pokemon.name}'s ability was revealed.")
break
end
end
end
end
def reveal_item(battler)
@sides.each do |side|
side.battlers.each do |proj|
if proj.battler == battler && !proj.revealed_item
proj.revealed_item = true
MKAI.log("#{proj.pokemon.name}'s item was revealed.")
break
end
end
end
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -1,68 +0,0 @@
class MKAI
class Side
attr_reader :ai
attr_reader :index
attr_reader :battlers
attr_reader :party
attr_reader :trainers
attr_reader :flags
def initialize(ai, index, wild_pokemon = false)
@ai = ai
@index = index
@battle = @ai.battle
@wild_pokemon = wild_pokemon
@battlers = []
@party = []
@flags = {}
end
def effects
return @battle.sides[@index].effects
end
def set_party(party)
@party = party.map { |pokemon| BattlerProjection.new(self, pokemon, @wild_pokemon) }
end
def set_trainers(trainers)
@trainers = trainers
end
def opposing_side
return @ai.sides[1 - @index]
end
def recall(battlerIndex)
index = MKAI.battler_to_proj_index(battlerIndex)
proj = @battlers[index]
if proj.nil?
raise "Battler to be recalled was not found in the active battlers list."
end
if !proj.active?
raise "Battler to be recalled was not active."
end
@battlers[index] = nil
proj.battler = nil
end
def send_out(battlerIndex, battler)
proj = @party.find { |proj| proj && proj.pokemon == battler.pokemon }
if proj.nil?
raise "Battler to be sent-out was not found in the party list."
end
if proj.active?
raise "Battler to be sent-out was already sent out before."
end
index = MKAI.battler_to_proj_index(battlerIndex)
@battlers[index] = proj
proj.ai_index = index
proj.battler = battler
end
def end_of_round
@battlers.each { |proj| proj.end_of_round if proj }
@flags = {}
end
end
end

View File

@@ -1,92 +0,0 @@
class PokeBattle_AI
#=============================================================================
#
#=============================================================================
# AI skill levels:
# 0: Wild Pokémon
# 1-31: Basic trainer (young/inexperienced)
# 32-47: Some skill
# 48-99: High skill
# 100+: Best trainers (Gym Leaders, Elite Four, Champion)
# NOTE: A trainer's skill value can range from 0-255, but by default only four
# distinct skill levels exist. The skill value is typically the same as
# the trainer's base money value.
module AILevel
# Minimum skill level to be in each AI skill bracket.
def self.minimum; return 1; end
def self.medium; return 32; end
def self.high; return 48; end
def self.best; return 100; end
end
#=============================================================================
#
#=============================================================================
def initialize(battle)
@battle = battle
@skill = 0
@user = nil
@wildBattler = @battle.wildBattle? # Whether AI is choosing for a wild Pokémon
@roles = [Array.new(@battle.pbParty(0).length) { |i| determine_roles(0, i) },
Array.new(@battle.pbParty(1).length) { |i| determine_roles(1, i) }]
end
def pbAIRandom(x); return rand(x); end
def pbStdDev(choices)
sum = 0
n = 0
choices.each do |c|
sum += c[1]
n += 1
end
return 0 if n<2
mean = sum.to_f/n.to_f
varianceTimesN = 0
choices.each do |c|
next if c[1]<=0
deviation = c[1].to_f-mean
varianceTimesN += deviation*deviation
end
# Using population standard deviation
# [(n-1) makes it a sample std dev, would be 0 with only 1 sample]
return Math.sqrt(varianceTimesN/n)
end
# Decide whether the opponent should Mega Evolve their Pokémon
def pbEnemyShouldMegaEvolve?
if @battle.pbCanMegaEvolve?(@user.index) # Simple "always should if possible"
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) will Mega Evolve")
return true
end
return false
end
# Choose an action
def pbDefaultChooseEnemyCommand(idxBattler)
set_up(idxBattler)
choices = pbGetMoveScores
return if pbEnemyShouldUseItem?
return if pbEnemyShouldWithdraw?
return if @battle.pbAutoFightMenu(idxBattler)
@battle.pbRegisterMegaEvolution(idxBattler) if pbEnemyShouldMegaEvolve?
pbChooseMove(choices)
end
# Set some class variables for the Pokémon whose action is being chosen
def set_up(idxBattler)
# TODO: Where relevant, pretend the user is Mega Evolved if it isn't but can
# be.
@user = @battle.battlers[idxBattler]
@wildBattler = (@battle.wildBattle? && @user.opposes?)
@skill = 0
if !@wildBattler
@skill = @battle.pbGetOwnerFromBattlerIndex(@user.index).skill || 0
@skill = AILevel.minimum if @skill < AILevel.minimum
end
end
def skill_check(threshold)
return @skill >= threshold
end
end

View File

@@ -1,170 +0,0 @@
class PokeBattle_AI
#=============================================================================
# Decide whether the opponent should use an item on the Pokémon
#=============================================================================
def pbEnemyShouldUseItem?
item, idxTarget = pbEnemyItemToUse
return false if !item
# Determine target of item (always the Pokémon choosing the action)
useType = GameData::Item.get(item).battle_use
if useType==1 || useType==6 # Use on Pokémon
idxTarget = @battle.battlers[idxTarget].pokemonIndex # Party Pokémon
end
# Register use of item
@battle.pbRegisterItem(@user.index,item,idxTarget)
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) will use item #{GameData::Item.get(item).name}")
return true
end
# NOTE: The AI will only consider using an item on the Pokémon it's currently
# choosing an action for.
def pbEnemyItemToUse
return nil if !@battle.internalBattle
items = @battle.pbGetOwnerItems(@user.index)
return nil if !items || items.length==0
# Determine target of item (always the Pokémon choosing the action)
idxTarget = @user.index # Battler using the item
battler = @battle.battlers[idxTarget]
pkmn = battler.pokemon
# Item categories
hpItems = {
:POTION => 20,
:SUPERPOTION => 50,
:HYPERPOTION => 200,
:MAXPOTION => 999,
:BERRYJUICE => 20,
:SWEETHEART => 20,
:FRESHWATER => 50,
:SODAPOP => 60,
:LEMONADE => 80,
:MOOMOOMILK => 100,
:ORANBERRY => 10,
:SITRUSBERRY => battler.totalhp/4,
:ENERGYPOWDER => 50,
:ENERGYROOT => 200
}
hpItems[:RAGECANDYBAR] = 20 if !NEWEST_BATTLE_MECHANICS
fullRestoreItems = [
:FULLRESTORE
]
oneStatusItems = [ # Preferred over items that heal all status problems
:AWAKENING, :CHESTOBERRY, :BLUEFLUTE,
:ANTIDOTE, :PECHABERRY,
:BURNHEAL, :RAWSTBERRY,
:PARALYZEHEAL, :PARLYZHEAL, :CHERIBERRY,
:ICEHEAL, :ASPEARBERRY
]
allStatusItems = [
:FULLHEAL, :LAVACOOKIE, :OLDGATEAU, :CASTELIACONE, :LUMIOSEGALETTE,
:SHALOURSABLE, :BIGMALASADA, :LUMBERRY, :HEALPOWDER
]
allStatusItems.push(:RAGECANDYBAR) if NEWEST_BATTLE_MECHANICS
xItems = {
:XATTACK => [PBStats::ATTACK, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XATTACK2 => [PBStats::ATTACK, 2],
:XATTACK3 => [PBStats::ATTACK, 3],
:XATTACK6 => [PBStats::ATTACK, 6],
:XDEFENSE => [PBStats::DEFENSE, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XDEFENSE2 => [PBStats::DEFENSE, 2],
:XDEFENSE3 => [PBStats::DEFENSE, 3],
:XDEFENSE6 => [PBStats::DEFENSE, 6],
:XDEFEND => [PBStats::DEFENSE, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XDEFEND2 => [PBStats::DEFENSE, 2],
:XDEFEND3 => [PBStats::DEFENSE, 3],
:XDEFEND6 => [PBStats::DEFENSE, 6],
:XSPATK => [PBStats::SPATK, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XSPATK2 => [PBStats::SPATK, 2],
:XSPATK3 => [PBStats::SPATK, 3],
:XSPATK6 => [PBStats::SPATK, 6],
:XSPECIAL => [PBStats::SPATK, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XSPECIAL2 => [PBStats::SPATK, 2],
:XSPECIAL3 => [PBStats::SPATK, 3],
:XSPECIAL6 => [PBStats::SPATK, 6],
:XSPDEF => [PBStats::SPDEF, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XSPDEF2 => [PBStats::SPDEF, 2],
:XSPDEF3 => [PBStats::SPDEF, 3],
:XSPDEF6 => [PBStats::SPDEF, 6],
:XSPEED => [PBStats::SPEED, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XSPEED2 => [PBStats::SPEED, 2],
:XSPEED3 => [PBStats::SPEED, 3],
:XSPEED6 => [PBStats::SPEED, 6],
:XACCURACY => [PBStats::ACCURACY, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
:XACCURACY2 => [PBStats::ACCURACY, 2],
:XACCURACY3 => [PBStats::ACCURACY, 3],
:XACCURACY6 => [PBStats::ACCURACY, 6]
}
losthp = battler.totalhp - battler.hp
preferFullRestore = (battler.hp <= battler.totalhp * 2 / 3 &&
(battler.status != PBStatuses::NONE || battler.effects[PBEffects::Confusion] > 0))
# Find all usable items
usableHPItems = []
usableStatusItems = []
usableXItems = []
items.each do |i|
next if !i
next if !@battle.pbCanUseItemOnPokemon?(i,pkmn,battler,@battle.scene,false)
next if !ItemHandlers.triggerCanUseInBattle(i,pkmn,battler,nil,
false,self,@battle.scene,false)
# Log HP healing items
if losthp > 0
power = hpItems[i]
if power
usableHPItems.push([i, 5, power])
next
end
end
# Log Full Restores (HP healer and status curer)
if losthp > 0 || battler.status != PBStatuses::NONE
if fullRestoreItems.include?(i)
usableHPItems.push([i, (preferFullRestore) ? 3 : 7, 999])
usableStatusItems.push([i, (preferFullRestore) ? 3 : 9])
next
end
end
# Log single status-curing items
if oneStatusItems.include?(i)
usableStatusItems.push([i, 5])
next
end
# Log Full Heal-type items
if allStatusItems.include?(i)
usableStatusItems.push([i, 7])
next
end
# Log stat-raising items
if xItems[i]
data = xItems[i]
usableXItems.push([i, battler.stages[data[0]], data[1]])
next
end
end
# Prioritise using a HP restoration item
if usableHPItems.length>0 && (battler.hp<=battler.totalhp/4 ||
(battler.hp<=battler.totalhp/2 && pbAIRandom(100)<30))
usableHPItems.sort! { |a,b| (a[1]==b[1]) ? a[2]<=>b[2] : a[1]<=>b[1] }
prevItem = nil
usableHPItems.each do |i|
return i[0], idxTarget if i[2]>=losthp
prevItem = i
end
return prevItem[0], idxTarget
end
# Next prioritise using a status-curing item
if usableStatusItems.length>0 && pbAIRandom(100)<40
usableStatusItems.sort! { |a,b| a[1]<=>b[1] }
return usableStatusItems[0][0], idxTarget
end
# Next try using an X item
if usableXItems.length>0 && pbAIRandom(100)<30
usableXItems.sort! { |a,b| (a[1]==b[1]) ? a[2]<=>b[2] : a[1]<=>b[1] }
prevItem = nil
usableXItems.each do |i|
break if prevItem && i[1]>prevItem[1]
return i[0], idxTarget if i[1]+i[2]>=6
prevItem = i
end
return prevItem[0], idxTarget
end
return nil
end
end

View File

@@ -1,178 +0,0 @@
class PokeBattle_AI
#=============================================================================
# Decide whether the opponent should switch Pokémon
#=============================================================================
def pbEnemyShouldWithdraw?
return pbEnemyShouldWithdrawEx?(false)
end
def pbEnemyShouldWithdrawEx?(forceSwitch)
return false if @wildBattler
shouldSwitch = forceSwitch
batonPass = -1
moveType = nil
# If Pokémon is within 6 levels of the foe, and foe's last move was
# super-effective and powerful
if !shouldSwitch && @user.turnCount > 0 && skill_check(AILevel.high)
target = @user.pbDirectOpposing(true)
if !target.fainted? && target.lastMoveUsed &&
(target.level - @user.level).abs <= 6
moveData = GameData::Move.get(target.lastMoveUsed)
moveType = moveData.type
typeMod = pbCalcTypeMod(moveType, target, @user)
if PBTypeEffectiveness.superEffective?(typeMod) && moveData.base_damage > 50
switchChance = (moveData.base_damage > 70) ? 30 : 20
shouldSwitch = (pbAIRandom(100) < switchChance)
end
end
end
# Pokémon can't do anything (must have been in battle for at least 5 rounds)
if !@battle.pbCanChooseAnyMove?(@user.index) &&
@user.turnCount && @user.turnCount>=5
shouldSwitch = true
end
# Pokémon is Perish Songed and has Baton Pass
if skill_check(AILevel.high) && @user.effects[PBEffects::PerishSong]==1
@user.eachMoveWithIndex do |m,i|
next if m.function!="0ED" # Baton Pass
next if !@battle.pbCanChooseMove?(@user.index,i,false)
batonPass = i
break
end
end
# Pokémon will faint because of bad poisoning at the end of this round, but
# would survive at least one more round if it were regular poisoning instead
if @user.status==PBStatuses::POISON && @user.statusCount>0 &&
skill_check(AILevel.high)
toxicHP = @user.totalhp/16
nextToxicHP = toxicHP*(@user.effects[PBEffects::Toxic]+1)
if @user.hp<=nextToxicHP && @user.hp>toxicHP*2
shouldSwitch = true if pbAIRandom(100)<80
end
end
# Pokémon is Encored into an unfavourable move
if @user.effects[PBEffects::Encore]>0 && skill_check(AILevel.medium)
idxEncoredMove = @user.pbEncoredMoveIndex
if idxEncoredMove>=0
scoreSum = 0
scoreCount = 0
@user.eachOpposing do |b|
scoreSum += pbGetMoveScore(@user.moves[idxEncoredMove],b)
scoreCount += 1
end
if scoreCount>0 && scoreSum/scoreCount<=20
shouldSwitch = true if pbAIRandom(100)<80
end
end
end
# If there is a single foe and it is resting after Hyper Beam or is
# Truanting (i.e. free turn)
if @battle.pbSideSize(@user.index+1)==1 &&
!@user.pbDirectOpposing.fainted? && skill_check(AILevel.high)
opp = @user.pbDirectOpposing
if opp.effects[PBEffects::HyperBeam]>0 ||
(opp.hasActiveAbility?(:TRUANT) && opp.effects[PBEffects::Truant])
shouldSwitch = false if pbAIRandom(100)<80
end
end
# Sudden Death rule - I'm not sure what this means
if @battle.rules["suddendeath"] && @user.turnCount>0
if @user.hp<=@user.totalhp/4 && pbAIRandom(100)<30
shouldSwitch = true
elsif @user.hp<=@user.totalhp/2 && pbAIRandom(100)<80
shouldSwitch = true
end
end
# Pokémon is about to faint because of Perish Song
if @user.effects[PBEffects::PerishSong]==1
shouldSwitch = true
end
if shouldSwitch
list = []
@battle.pbParty(@user.index).each_with_index do |pkmn,i|
next if !@battle.pbCanSwitch?(@user.index,i)
# If perish count is 1, it may be worth it to switch
# even with Spikes, since Perish Song's effect will end
if @user.effects[PBEffects::PerishSong]!=1
# Will contain effects that recommend against switching
spikes = @user.pbOwnSide.effects[PBEffects::Spikes]
# Don't switch to this if too little HP
if spikes>0
spikesDmg = [8,6,4][spikes-1]
if pkmn.hp<=pkmn.totalhp/spikesDmg
next if !pkmn.hasType?(:FLYING) && !pkmn.hasActiveAbility?(:LEVITATE)
end
end
end
# moveType is the type of the target's last used move
if moveType && PBTypeEffectiveness.ineffective?(pbCalcTypeMod(moveType,@user,@user))
weight = 65
typeMod = pbCalcTypeModPokemon(pkmn,@user.pbDirectOpposing(true))
if PBTypeEffectiveness.superEffective?(typeMod)
# Greater weight if new Pokemon's type is effective against target
weight = 85
end
list.unshift(i) if pbAIRandom(100)<weight # Put this Pokemon first
elsif moveType && PBTypeEffectiveness.resistant?(pbCalcTypeMod(moveType,@user,@user))
weight = 40
typeMod = pbCalcTypeModPokemon(pkmn,@user.pbDirectOpposing(true))
if PBTypeEffectiveness.superEffective?(typeMod)
# Greater weight if new Pokemon's type is effective against target
weight = 60
end
list.unshift(i) if pbAIRandom(100)<weight # Put this Pokemon first
else
list.push(i) # put this Pokemon last
end
end
if list.length>0
if batonPass>=0 && @battle.pbRegisterMove(@user.index,batonPass,false)
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) will use Baton Pass to avoid Perish Song")
return true
end
if @battle.pbRegisterSwitch(@user.index,list[0])
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) will switch with " +
"#{@battle.pbParty(@user.index)[list[0]].name}")
return
end
end
end
return false
end
#=============================================================================
# Choose a replacement Pokémon (called directly from @battle, not part of
# action choosing)
#=============================================================================
def pbDefaultChooseNewEnemy(idxBattler,party)
set_up(idxBattler)
enemies = []
party.each_with_index do |_p,i|
enemies.push(i) if @battle.pbCanSwitchLax?(idxBattler,i)
end
return -1 if enemies.length==0
return pbChooseBestNewEnemy(idxBattler,party,enemies)
end
def pbChooseBestNewEnemy(idxBattler,party,enemies)
return -1 if !enemies || enemies.length==0
best = -1
bestSum = 0
enemies.each do |i|
pkmn = party[i]
sum = 0
pkmn.moves.each do |m|
next if m.base_damage == 0
@battle.battlers[idxBattler].eachOpposing do |b|
bTypes = b.pbTypes(true)
sum += PBTypes.getCombinedEffectiveness(m.type, bTypes[0], bTypes[1], bTypes[2])
end
end
if best==-1 || sum>bestSum
best = i
bestSum = sum
end
end
return best
end
end

View File

@@ -1,497 +0,0 @@
<<<class PokeBattle_AI
#=============================================================================
# Main move-choosing method (moves with higher scores are more likely to be
# chosen)
#=============================================================================
def pbChooseMove(choices)
# Figure out useful information about the choices
totalScore = 0
maxScore = 0
choices.each do |c|
totalScore += c[1]
maxScore = c[1] if maxScore < c[1]
end
# Find any preferred moves and just choose from them
if skill_check(AILevel.high) && maxScore > 100
stDev = pbStdDev(choices)
if stDev >= 40 && pbAIRandom(100) < 90
preferredMoves = []
choices.each do |c|
next if c[1] < 200 && c[1] < maxScore * 0.8
preferredMoves.push(c)
preferredMoves.push(c) if c[1] == maxScore # Doubly prefer the best move
end
if preferredMoves.length > 0
m = preferredMoves[pbAIRandom(preferredMoves.length)]
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) prefers #{@user.moves[m[0]].name}")
@battle.pbRegisterMove(@user.index, m[0], false)
@battle.pbRegisterTarget(@user.index, m[2]) if m[2] >= 0
return
end
end
end
# Decide whether all choices are bad, and if so, try switching instead
if !@wildBattler && skill_check(AILevel.high)
badMoves = false
if (maxScore <= 20 && @user.turnCount > 2) ||
(maxScore <= 40 && @user.turnCount > 5)
badMoves = true if pbAIRandom(100) < 80
end
if !badMoves && totalScore < 100 && @user.turnCount > 1
badMoves = true
choices.each do |c|
next if !@user.moves[c[0]].damagingMove?
badMoves = false
break
end
badMoves = false if badMoves && pbAIRandom(100) < 10
end
if badMoves && pbEnemyShouldWithdrawEx?(true)
if $INTERNAL
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) will switch due to terrible moves")
end
return
end
end
# If there are no calculated choices, pick one at random
if choices.length == 0
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) doesn't want to use any moves; picking one at random")
@user.eachMoveWithIndex do |_m, i|
next if !@battle.pbCanChooseMove?(@user.index, i, false)
choices.push([i, 100, -1]) # Move index, score, target
end
if choices.length == 0 # No moves are physically possible to use; use Struggle
@battle.pbAutoChooseMove(@user.index)
end
end
# Randomly choose a move from the choices and register it
randNum = pbAIRandom(totalScore)
choices.each do |c|
randNum -= c[1]
next if randNum >= 0
@battle.pbRegisterMove(@user.index, c[0], false)
@battle.pbRegisterTarget(@user.index, c[2]) if c[2] >= 0
break
end
# Log the result
if @battle.choices[@user.index][2]
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) will use #{@battle.choices[@user.index][2].name}")
end
end
#=============================================================================
# Get scores for the user's moves (done before any action is assessed)
# NOTE: A move is only added to the choices array if it has a non-zero score.
#=============================================================================
def pbGetMoveScores
# Get scores and targets for each move
choices = []
# TODO: Split this into two, the first part being the calculation of all
# predicted damages and the second part being the score calculations
# (which are based on the predicted damages). Note that this requires
# saving each of the scoresAndTargets entries in here rather than in
# def pbRegisterMoveTrainer, and only at the very end are they
# whittled down to one per move which are chosen from. Multi-target
# moves could be fiddly since damages should be calculated for each
# target but they're all related.
@user.eachMoveWithIndex do |_m, i|
next if !@battle.pbCanChooseMove?(@user.index, i, false)
if @wildBattler
pbRegisterMoveWild(i, choices)
else
pbRegisterMoveTrainer(i, choices)
end
end
# Log the available choices
if $INTERNAL
logMsg = "[AI] Move choices for #{@user.pbThis(true)} (#{@user.index}): "
choices.each_with_index do |c, i|
logMsg += "#{@user.moves[c[0]].name}=#{c[1]}"
logMsg += " (target #{c[2]})" if c[2] >= 0
logMsg += ", " if i < choices.length-1
end
PBDebug.log(logMsg)
end
return choices
end
#=============================================================================
# Get scores for the given move against each possible target
#=============================================================================
# Wild Pokémon choose their moves randomly.
def pbRegisterMoveWild(idxMove, choices)
score = 100
# Doubly prefer one of the user's moves (the choice is random but consistent
# and does not correlate to any other property of the user)
score *= 2 if @user.pokemon.personalID % @user.moves.length == idxMove
choices.push([idxMove, score, -1]) # Move index, score, target
end
# Trainer Pokémon calculate how much they want to use each of their moves.
def pbRegisterMoveTrainer(idxMove, choices)
move = @user.moves[idxMove]
targetType = move.pbTarget(@user)
# TODO: Alter targetType if user has Protean and move is Curse.
if PBTargets.multipleTargets?(targetType)
# Move affects multiple battlers and you don't choose a particular one
totalScore = 0
@battle.eachBattler do |b|
next if !@battle.pbMoveCanTarget?(@user.index, b.index, targetType)
score = pbGetMoveScore(move, b)
totalScore += ((@user.opposes?(b)) ? score : -score)
end
choices.push([idxMove, totalScore, -1]) if totalScore > 0
elsif PBTargets.noTargets?(targetType)
# Move has no targets, affects the user, a side or the whole field
score = pbGetMoveScore(move)
choices.push([idxMove, score, -1]) if score > 0
else
# Move affects one battler and you have to choose which one
scoresAndTargets = []
@battle.eachBattler do |b|
next if !@battle.pbMoveCanTarget?(@user.index, b.index, targetType)
next if PBTargets.canChooseFoeTarget?(targetType) && !@user.opposes?(b)
score = pbGetMoveScore(move, b)
scoresAndTargets.push([score, b.index]) if score > 0
end
if scoresAndTargets.length > 0
# Get the one best target for the move
scoresAndTargets.sort! { |a, b| b[0] <=> a[0] }
choices.push([idxMove, scoresAndTargets[0][0], scoresAndTargets[0][1]])
end
end
end
#=============================================================================
# Set some class variables for the move being assessed
#=============================================================================
def set_up_move_check(move, target)
@move = move
@target = target
# TODO: Calculate pbRoughType once here.
# Determine whether user or target is faster, and store that result so it
# doesn't need recalculating
if @target
user_speed = pbRoughStat(@user, PBStats::SPEED)
target_speed = pbRoughStat(@target, PBStats::SPEED)
@user_faster = (user_speed > target_speed) ^ (@battle.field.effects[PBEffects::TrickRoom] > 0)
else
@user_faster = false # Won't be used if there is no target
end
end
#=============================================================================
# Get a score for the given move being used against the given target
#=============================================================================
def pbGetMoveScore(move, target = nil)
set_up_move_check(move, target)
# Get the base score for the move
if @move.damagingMove?
# Is also the predicted damage amount as a percentage of target's current HP
score = pbGetDamagingMoveBaseScore
else # Status moves
# Depends on the move's effect
score = pbGetStatusMoveBaseScore
end
# Modify the score according to the move's effect
score = pbGetMoveScoreFunctions(score)
# A score of 0 here means it absolutely should not be used
return 0 if score <= 0
# TODO: High priority checks:
# => Prefer move if it will KO the target (moreso if user is slower than target)
# => Don't prefer damaging move if it won't KO, user has Stance Change and
# is in shield form, and user is slower than the target
# => Check memory for past damage dealt by a target's non-high priority move,
# and prefer move if user is slower than the target and another hit from
# the same amount will KO the user
# => Check memory for past damage dealt by a target's priority move, and don't
# prefer the move if user is slower than the target and can't move faster
# than it because of priority
# => Discard move if user is slower than the target and target is semi-
# invulnerable (and move won't hit it)
# => Check memory for whether target has previously used Quick Guard, and
# don't prefer move if so
# TODO: Low priority checks:
# => Don't prefer move if user is faster than the target
# => Prefer move if user is faster than the target and target is semi-
# invulnerable
# Don't prefer a dancing move if the target has the Dancer ability
# TODO: Check all battlers, not just the target.
if skill_check(AILevel.high) && @move.danceMove? && @target.hasActiveAbility?(:DANCER)
score /= 2
end
# TODO: Check memory for whether target has previously used Ion Deluge, and
# don't prefer move if it's Normal-type and target is immune because
# of its ability (Lightning Rod, etc.).
# TODO: Discard move if it can be redirected by a non-target's ability
# (Lightning Rod/Storm Drain). Include checking for a previous use of
# Ion Deluge and this move being Normal-type.
# => If non-target is a user's ally, don't prefer move (rather than discarding
# it)
# TODO: Discard move if it's sound-based and user has been Throat Chopped.
# Don't prefer move if user hasn't been Throat Chopped but target has
# previously used Throat Chop. The first part of this would probably
# go elsewhere (damage calc?).
# TODO: Prefer move if it has a high critical hit rate, critical hits are
# possible but not certain, and target has raised defences/user has
# lowered offences (Atk/Def or SpAtk/SpDef, whichever is relevant).
# 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
# is likely to be lethal, and target has previously used Destiny Bond
# TODO: Don't prefer a move that is stopped by Wide Guard if target has
# previously used Wide Guard.
# TODO: Don't prefer Fire-type moves if target has previously used Powder.
# TODO: Don't prefer contact move if making contact with the target could
# trigger an effect that's bad for the user (Static, etc.).
# => Also check if target has previously used Spiky Shield.King's Shield/
# Baneful Bunker, and don't prefer move if so
# TODO: Prefer a contact move if making contact with the target could trigger
# an effect that's good for the user (Poison Touch/Pickpocket).
# TODO: Don't prefer a status move if user has a damaging move that will KO
# 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.
if skill_check(AILevel.medium)
# Prefer damaging moves if AI has no more Pokémon or AI is less clever
if @battle.pbAbleNonActiveCount(@user.idxOwnSide) == 0
if !(skill_check(AILevel.high) && @battle.pbAbleNonActiveCount(@target.idxOwnSide) > 0)
if @move.statusMove?
score *= 0.9
elsif @target.hp <= @target.totalhp / 2
score *= 1.1
end
end
end
# Don't prefer attacking the target if they'd be semi-invulnerable
if skill_check(AILevel.high) && @move.accuracy > 0 && @user_faster &&
(@target.semiInvulnerable? || @target.effects[PBEffects::SkyDrop] >= 0)
miss = true
miss = false if @user.hasActiveAbility?(:NOGUARD)
miss = false if skill_check(AILevel.best) && @target.hasActiveAbility?(:NOGUARD)
if skill_check(AILevel.best) && miss
# Knows what can get past semi-invulnerability
if @target.effects[PBEffects::SkyDrop] >= 0
@target.effects[PBEffects::SkyDrop] != @user.index
miss = false if @move.hitsFlyingTargets?
else
if @target.inTwoTurnAttack?("0C9", "0CC", "0CE") # Fly, Bounce, Sky Drop
miss = false if @move.hitsFlyingTargets?
elsif @target.inTwoTurnAttack?("0CA") # Dig
miss = false if @move.hitsDiggingTargets?
elsif @target.inTwoTurnAttack?("0CB") # Dive
miss = false if @move.hitsDivingTargets?
end
end
end
score = 0 if miss
end
# Pick a good move for the Choice items
if @user.hasActiveItem?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF])
# Really don't prefer status moves (except Trick)
score *= 0.1 if @move.statusMove? && @move.function != "0F2" # Trick
# Don't prefer moves of certain types
move_type = pbRoughType(@move)
# Most unpreferred types are 0x effective against another type, except
# Fire/Water/Grass
# TODO: Actually check through the types for 0x instead of hardcoding
# them.
# TODO: Reborn separately doesn't prefer Fire/Water/Grass/Electric, also
# with a 0.95x score, meaning Electric can be 0.95x twice. Why are
# these four types not preferred? Maybe because they're all not
# very effective against Dragon.
unpreferred_types = [:NORMAL, :FIGHTING, :POISON, :GROUND, :GHOST,
:FIRE, :WATER, :GRASS, :ELECTRIC, :PSYCHIC, :DRAGON]
score *= 0.95 if unpreferred_types.include?(move_type)
# Don't prefer moves with lower accuracy
score *= @move.accuracy / 100.0 if @move.accuracy > 0
# Don't prefer moves with low PP
score *= 0.9 if @move.pp < 6
end
# If user is asleep, don't prefer moves that can't be used while asleep
if skill_check(AILevel.medium) && @user.asleep? &&
@user.statusCount > 1 && !@move.usableWhenAsleep?
score *= 0.2
end
# If user is frozen, prefer a move that can thaw the user
if skill_check(AILevel.medium) && @user.status == PBStatuses::FROZEN
if @move.thawsUser?
score += 30
else
@user.eachMove do |m|
next unless m.thawsUser?
score *= 0 # Discard this move if user knows another move that thaws
break
end
end
end
# If target is frozen, don't prefer moves that could thaw them
if @target.status == PBStatuses::FROZEN
if pbRoughType(@move) == :FIRE || (NEWEST_BATTLE_MECHANICS && @move.thawsUser?)
score *= 0.1
end
end
end
# Don't prefer hitting a wild shiny Pokémon
if @battle.wildBattle? && @target.opposes? && @target.shiny?
score *= 0.15
end
# TODO: Discard a move that can be Magic Coated if either opponent has Magic
# Bounce.
# Account for accuracy of move
accuracy = pbRoughAccuracy(@move, @target)
score *= accuracy / 100.0
# Prefer flinching external effects (note that move effects which cause
# flinching are dealt with in the function code part of score calculation)
if skill_check(AILevel.medium)
if !@target.hasActiveAbility?([:INNERFOCUS, :SHIELDDUST]) &&
@target.effects[PBEffects::Substitute] == 0
can_flinch = false
if @move.canKingsRock? && @user.hasActiveItem?([:KINGSROCK, :RAZORFANG])
can_flinch = true
elsif @user.hasActiveAbility?(:STENCH) && !@move.flinchingMove?
can_flinch = true
end
calc_damage *= 1.3 if can_flinch
end
end
score = score.to_i
score = 0 if score < 0
return score
end
#=============================================================================
# Calculate how much damage a move is likely to do to a given target (as a
# percentage of the target's current HP)
#=============================================================================
def pbGetDamagingMoveBaseScore
# Don't prefer moves that are ineffective because of abilities or effects
return 0 if pbCheckMoveImmunity(@move, @target)
# Calculate how much damage the move will do (roughly)
base_damage = pbMoveBaseDamage(@move, @target)
calc_damage = pbRoughDamage(@move, @target, base_damage)
# TODO: Maybe move this check elsewhere? Note that Reborn's base score does
# not include this halving, but the predicted damage does.
# Two-turn attacks waste 2 turns to deal one lot of damage
calc_damage /= 2 if @move.chargingTurnMove?
# TODO: Maybe move this check elsewhere?
# Increased critical hit rate
if skill_check(AILevel.medium)
crit_stage = pbRoughCriticalHitStage(@move, @target)
if crit_stage >= 0
crit_fraction = (crit_stage > 50) ? 1 : PokeBattle_Move::CRITICAL_HIT_RATIOS[crit_stage]
crit_mult = (NEWEST_BATTLE_MECHANICS) ? 0.5 : 1
calc_damage *= (1 + crit_mult / crit_fraction)
end
end
# Convert damage to percentage of target's remaining HP
damage_percentage = calc_damage * 100.0 / @target.hp
# Don't prefer weak attacks
# damage_percentage /= 2 if damage_percentage < 20
# Prefer damaging attack if level difference is significantly high
# damage_percentage *= 1.2 if @user.level - 10 > @target.level
# Adjust score
damage_percentage = 110 if damage_percentage > 110 # Treat all lethal moves the same
damage_percentage += 40 if damage_percentage > 100 # Prefer moves likely to be lethal
score = damage_percentage.to_i
return score
end
def pbGetStatusMoveBaseScore
# TODO: Call pbCheckMoveImmunity here too, not just for damaging moves
# (only if this status move will be affected).
# TODO: Make sure all status moves are accounted for.
# TODO: Duplicates:
# 003 cause sleep - Dark Void (15), Grass Whistle (15), Hypnosis (15), Sing (15),
# Lovely Kiss (20), Sleep Powder (20), Spore (60)
# 005 poisons - Poison Powder (15), Poison Gas (20)
# 007 paralyses - Stun Spore (25), Glare (30), Thunder Wave (30)
# 013 confuses - Teeter Dance (5), Supersonic (10), Sweet Kiss (20), Confuse Ray (25)
# 01C user's Atk +1 - Howl (10), Sharpen (10), Medicate (15)
# 030 user's Spd +2 - Agility (15), Rock Polish (25)
# 042 target Atk -1 - Growl (10), Baby-Doll Eyes (15)
# 047 target acc -1 - Sand Attack (5), Flash (10), Kinesis (10), Smokescreen (10)
# 04B target Atk -2 - Charm (10), Feather Dance (15)
# 04D target Spd -2 - String Shot (10), Cotton Spore (15), Scary Face (15)
# 04F target SpDef -2 - Metal Sound (10), Fake Tears (15)
case @move.function
when "013", "047", "049", "052", "053", "057", "058", "059", "05E", "061",
"062", "066", "067", "09C", "09D", "09E", "0A6", "0A7", "0A8", "0AB",
"0AC", "0B1", "0B2", "0B8", "0BB", "0E6", "0E8", "0F6", "0F9", "10F",
"114", "118", "119", "120", "124", "138", "13E", "13F", "143", "152",
"15E", "161", "16A", "16B"
return 5
when "013", "01C", "01D", "01E", "023", "027", "028", "029", "037", "042",
"043", "047", "04B", "04D", "04F", "051", "055", "060", "0B7", "0F8",
"139", "13A", "13C", "148"
return 10
when "003", "005", "018", "01C", "021", "022", "030", "042", "04A", "04B",
"04C", "04D", "04E", "04F", "05C", "05D", "065", "0B0", "0B5", "0DB",
"0DF", "0E3", "0E4", "0FF", "100", "101", "102", "137", "13D", "140",
"142", "151", "15C", "16E"
return 15
when "003", "004", "005", "013", "040", "041", "054", "056", "05F", "063",
"064", "068", "069", "0AE", "0AF", "0B6", "0D9", "0DA", "0E5", "0EB",
"0EF", "145", "146", "159"
return 20
when "006", "007", "00A", "013", "016", "01B", "02A", "02F", "030", "031",
"033", "034", "038", "03A", "05A", "0AA", "0B9", "0BA", "0D5", "0D6",
"0D7", "0D8", "0DC", "0E7", "0F2", "10C", "112", "117", "141", "160",
"16D"
return 25
when "007", "024", "025", "02C", "0B3", "0B4", "0BC", "0ED", "103", "104",
"105", "10D", "11F", "14C", "154", "155", "156", "15B", "173"
return 30
when "019", "02E", "032", "039", "05B", "0A2", "0A3", "149", "14B", "168"
return 35
when "026", "02B", "035", "036", "14E"
return 40
when "003", "153", "167"
return 60
end
# "001", "01A", "048", "0A1", "0E2", "0EA", "0F3", "10E", "11A", "11D",
# "11E", "14A"
return 0
end
end

View File

@@ -1,431 +0,0 @@
class PokeBattle_AI
#=============================================================================
# Apply additional effect chance to a move's score
# TODO: Apply all the additional effect chance modifiers.
#=============================================================================
def apply_effect_chance_to_score(score)
if @move.damagingMove?
# TODO: Doesn't return the correct value for "014" (Chatter).
effect_chance = @move.addlEffect
if effect_chance > 0
effect_chance *= 2 if @user.hasActiveAbility?(:SERENEGRACE) ||
@user.pbOwnSide.effects[PBEffects::Rainbow] > 0
effect_multiplier = [effect_chance.to_f, 100].min / 100
score = ((score - 1) * effect_multiplier) + 1
end
end
return score
end
#=============================================================================
#
#=============================================================================
# TODO: These function codes need to have an attr_reader :statUp and for them
# to be set when the move is initialised.
# 035 Shell Smash
# 037 Acupressure
# 137 Magnetic Flux
# 15C Gear Up
def calc_user_stat_raise_mini_score
mini_score = 1.0
# Determine whether the move boosts Attack, Special Attack or Speed (Bulk Up
# is sometimes not considered a sweeping move)
sweeping_stat = false
offensive_stat = false
@move.stat_up.each_with_index do |stat, idx|
next if idx.odd?
next if ![:ATTACK, :SPATK, :SPEED].include?(stat)
sweeping_stat = true
next if @move.function == "024" # Bulk Up (+Atk +Def)
offensive_stat = true
break
end
# Prefer if user has most of its HP
if @user.hp >= @user.totalhp * 3 / 4
mini_score *= (sweeping_stat) ? 1.2 : 1.1
end
# Prefer if user hasn't been in battle for long
if @user.turnCount < 2
mini_score *= (sweeping_stat) ? 1.2 : 1.1
end
# Prefer if user has the ability Simple
mini_score *= 2 if @user.hasActiveAbility?(:SIMPLE)
# TODO: Prefer if user's moves won't do much damage.
# Prefer if user has something that will limit damage taken
mini_score *= 1.3 if @user.effects[PBEffects::Substitute] > 0 ||
(@user.form == 0 && @user.ability_id == :DISGUISE)
# Don't prefer if user doesn't have much HP left
mini_score *= 0.3 if @user.hp < @user.totalhp / 3
# Don't prefer if user is badly poisoned
mini_score *= 0.2 if @user.effects[PBEffects::Toxic] > 0 && !offensive_stat
# Don't prefer if user is confused
if @user.effects[PBEffects::Confusion] > 0
# TODO: Especially don't prefer if the move raises Atk. Even more so if
# the move raises the stat by 2+. Not quite so much if the move also
# raises Def.
mini_score *= 0.5
end
# Don't prefer if user is infatuated or Leech Seeded
if @user.effects[PBEffects::Attract] >= 0 || @user.effects[PBEffects::LeechSeed] >= 0
mini_score *= (offensive_stat) ? 0.6 : 0.3
end
# Don't prefer if user has an ability or item that will force it to switch
# out
if @user.hp < @user.totalhp * 3 / 4
mini_score *= 0.3 if @user.hasActiveAbility?([:EMERGENCYEXIT, :WIMPOUT])
mini_score *= 0.3 if @user.hasActiveItem?(:EJECTBUTTON)
end
# Prefer if target has a status problem
if @target.status != PBStatuses::NONE
mini_score *= (sweeping_stat) ? 1.2 : 1.1
case @target.status
when PBStatuses::SLEEP, PBStatuses::FROZEN
mini_score *= 1.3
when PBStatuses::BURN
# TODO: Prefer if the move boosts Sp Def.
mini_score *= 1.1 if !offensive_stat
end
end
# Prefer if target is yawning
if @target.effects[PBEffects::Yawn] > 0
mini_score *= (sweeping_stat) ? 1.7 : 1.3
end
# Prefer if target is recovering after Hyper Beam
if @target.effects[PBEffects::HyperBeam] > 0
mini_score *= (sweeping_stat) ? 1.3 : 1.2
end
# Prefer if target is Encored into a status move
if @target.effects[PBEffects::Encore] > 0 &&
GameData::Move.get(@target.effects[PBEffects::EncoreMove]).category == 2 # Status move
# TODO: Why should this check greatly prefer raising both the user's defences?
if sweeping_stat || @move.function == "02A" # +Def +SpDef
mini_score *= 1.5
else
mini_score *= 1.3
end
end
# TODO: Don't prefer if target has previously used a move that would force
# the user to switch (or Yawn/Perish Song which encourage it). Prefer
# instead if the move raises evasion. Note this comes after the
# dissociation of Bulk Up from sweeping_stat.
if skill_check(AILevel.medium)
# TODO: Prefer if the maximum damage the target has dealt wouldn't hurt
# the user much.
end
# Don't prefer if foe's side is able to use a boosted Retaliate
# TODO: I think this is what Reborn means. Reborn doesn't check for the
# existence of the move Retaliate, just whether it can be boosted.
if @user.pbOpposingSide.effects[PBEffects::LastRoundFainted] == @battle.turnCount - 1
mini_score *= 0.3
end
# Don't prefer if it's not a single battle
if !@battle.singleBattle?
mini_score *= (offensive_stat) ? 0.25 : 0.5
end
return mini_score
end
#=============================================================================
#
#=============================================================================
# TODO: This method doesn't take the increment into account but should.
def calc_user_stat_raise_one(stat, increment)
mini_score = 1.0
# Ignore if user won't benefit from the stat being raised
# TODO: Exception if user knows Baton Pass? Exception if user knows Power Trip?
case stat
when PBStats::ATTACK
has_physical_move = false
@user.eachMove do |m|
next if !m.physicalMove?(m.type) || m.function == "121" # Foul Play
has_physical_move = true
break
end
return mini_score if !has_physical_move
when PBStats::SPATK
has_special_move = false
@user.eachMove do |m|
next if !m.specialMove?(m.type)
has_special_move = true
break
end
return mini_score if !has_special_move
end
case stat
when PBStats::ATTACK
# Prefer if user can definitely survive a hit no matter how powerful, and
# it won't be hurt by weather
if @user.hp == @user.totalhp &&
(@user.hasActiveItem?(:FOCUSSASH) || @user.hasActiveAbility?(:STURDY))
if !(@battle.pbWeather == PBWeather::Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == PBWeather::Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == PBWeather::ShadowSky && @user.takesShadowSkyDamage?)
mini_score *= 1.4
end
end
# Prefer if user has the Sweeper role
# TODO: Is 1.1x for 025 Coil (+Atk, +Def, +acc).
mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
# Don't prefer if user is burned or paralysed
mini_score *= 0.5 if @user.status == PBStatuses::BURN || @user.status == PBStatuses::PARALYSIS
# Don't prefer if user's Speed stat is lowered
sum_stages = @user.stages[PBStats::SPEED]
mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0
# TODO: Prefer if target has previously used a HP-restoring move.
# TODO: Don't prefer if some of foes' stats are raised
sum_stages = 0
[PBStats::ATTACK, PBStats::SPATK, PBStats::SPEED].each do |s|
sum_stages += @target.stages[s]
end
mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0
# TODO: Don't prefer if target has Speed Boost (+Spd at end of each round).
mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST)
# TODO: Don't prefer if target has previously used a move that benefits
# from user's Attack being boosted.
mini_score *= 0.3 if check_for_move(@target) { |move| move.function == "121" } # Foul Play
# TODO: Don't prefer if the target has previously used a priority move.
when PBStats::DEFENSE
# Prefer if user has a healing item
# TODO: Is 1.1x for 025 Coil (+Atk, +Def, +acc).
mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
(@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
# Prefer if user knows any healing moves
# TODO: Is 1.2x for 025 Coil (+Atk, +Def, +acc).
mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? }
# Prefer if user knows Pain Split or Leech Seed
# TODO: Leech Seed is 1.2x for 025 Coil (+Atk, +Def, +acc).
mini_score *= 1.2 if @user.pbHasMoveFunction?("05A") # Pain Split
mini_score *= 1.3 if @user.pbHasMoveFunction?("0DC") # Leech Seed
# Prefer if user has certain roles
# TODO: Is 1.1x for 025 Coil (+Atk, +Def, +acc).
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# Don't prefer if user is badly poisoned
mini_score *= 0.2 if @user.effects[PBEffects::Toxic] > 0
# Don't prefer if user's Defense stat is raised
sum_stages = @user.stages[PBStats::DEFENSE]
mini_score *= 1 - sum_stages * 0.15 if sum_stages > 0
# TODO: Prefer if foes have higher Attack than Special Attack, and user
# doesn't have a wall role, user is faster and user has at least 75%
# HP. Don't prefer instead if user is slower (ignore HP).
# TODO: Don't prefer if previous damage done by foes wouldn't hurt the
# user much.
when PBStats::SPEED
# Prefer if user can definitely survive a hit no matter how powerful, and
# it won't be hurt by weather
if @user.hp == @user.totalhp &&
(@user.hasActiveItem?(:FOCUSSASH) || @user.hasActiveAbility?(:STURDY))
if !(@battle.pbWeather == PBWeather::Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == PBWeather::Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == PBWeather::ShadowSky && @user.takesShadowSkyDamage?)
mini_score *= 1.4
end
end
# Prefer if user's Attack/SpAtk stat (whichever is higher) is lowered
# TODO: Why?
if @user.attack > @user.spatk
sum_stages = @user.stages[PBStats::ATTACK]
mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
else
sum_stages = @user.stages[PBStats::SPATK]
mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
end
# Prefer if user has lowered Speed
# TODO: Is a flat 1.3x for 026 Dragon Dance (+Atk, +Spd).
sum_stages = @user.stages[PBStats::SPEED]
mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
# Prefer if user has Moxie
mini_score *= 1.3 if @user.hasActiveAbility?(:MOXIE)
# Prefer if user has the Sweeper role
mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
# Don't prefer if user is burned or paralysed
mini_score *= 0.2 if @user.status == PBStatuses::PARALYSIS
# Don't prefer if user has Speed Boost
mini_score *= 0.6 if @user.hasActiveAbility?(:SPEEDBOOST)
# TODO: Don't prefer if target has raised defenses.
sum_stages = 0
[PBStats::DEFENSE, PBStats::SPDEF].each { |s| sum_stages += @target.stages[s] }
mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0
# TODO: Don't prefer if the target has previously used a priority move.
# TODO: Don't prefer if Trick Room applies or any foe has previously used
# Trick Room.
mini_score *= 0.2 if @battle.field.effects[PBEffects::TrickRoom] > 0
# TODO: Don't prefer if user is already faster than the target. Exception
# for moves that benefit from a raised user's Speed?
# TODO: Don't prefer if user is already faster than the target and there's
# only 1 unfainted foe (this check is done by Agility/Autotomize
# (both +2 Spd) only in Reborn.)
when PBStats::SPATK
# Prefer if user can definitely survive a hit no matter how powerful, and
# it won't be hurt by weather
if @user.hp == @user.totalhp &&
(@user.hasActiveItem?(:FOCUSSASH) || @user.hasActiveAbility?(:STURDY))
if !(@battle.pbWeather == PBWeather::Sandstorm && @user.takesSandstormDamage?) &&
!(@battle.pbWeather == PBWeather::Hail && @user.takesHailDamage?) &&
!(@battle.pbWeather == PBWeather::ShadowSky && @user.takesShadowSkyDamage?)
mini_score *= 1.4
end
end
# Prefer if user has the Sweeper role
mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
# Don't prefer if user's Speed stat is lowered
sum_stages = @user.stages[PBStats::SPEED]
mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0
# TODO: Prefer if target has previously used a HP-restoring move.
# TODO: Don't prefer if some of foes' stats are raised
sum_stages = 0
[PBStats::ATTACK, PBStats::SPATK, PBStats::SPEED].each do |s|
sum_stages += @target.stages[s]
end
mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0
# TODO: Don't prefer if target has Speed Boost (+Spd at end of each round)
mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST)
# TODO: Don't prefer if the target has previously used a priority move.
when PBStats::SPDEF
# Prefer if user has a healing item
mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
(@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
# Prefer if user knows any healing moves
mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? }
# Prefer if user knows Pain Split or Leech Seed
mini_score *= 1.2 if @user.pbHasMoveFunction?("05A") # Pain Split
mini_score *= 1.3 if @user.pbHasMoveFunction?("0DC") # Leech Seed
# Prefer if user has certain roles
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# Don't prefer if user's Defense stat is raised
sum_stages = @user.stages[PBStats::SPDEF]
mini_score *= 1 - sum_stages * 0.15 if sum_stages > 0
# TODO: Prefer if foes have higher Special Attack than Attack.
# TODO: Don't prefer if previous damage done by foes wouldn't hurt the
# user much.
when PBStats::ACCURACY
# Prefer if user knows any weaker moves
mini_score *= 1.1 if check_for_move(@user) { |move| move.damagingMove? && move.basedamage < 95 }
# Prefer if target has a raised evasion
sum_stages = @target.stages[PBStats::EVASION]
mini_score *= 1 + sum_stages * 0.05 if sum_stages > 0
# Prefer if target has an item that lowers foes' accuracy
mini_score *= 1.1 if @target.hasActiveItem?([:BRIGHTPOWDER, :LAXINCENSE])
# Prefer if target has an ability that lowers foes' accuracy
# TODO: Tangled Feet while user is confused?
if (@battle.pbWeather == PBWeather::Sandstorm && @target.hasActiveAbility?(:SANDVEIL)) ||
(@battle.pbWeather == PBWeather::Hail && @target.hasActiveAbility?(:SNOWCLOAK))
mini_score *= 1.1
end
when PBStats::EVASION
# Prefer if user has a healing item
mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
(@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
# Prefer if user has an item that lowers foes' accuracy
mini_score *= 1.3 if @user.hasActiveItem?([:BRIGHTPOWDER, :LAXINCENSE])
# Prefer if user has an ability that lowers foes' accuracy
# TODO: Tangled Feet while user is confused?
if (@battle.pbWeather == PBWeather::Sandstorm && @user.hasActiveAbility?(:SANDVEIL)) ||
(@battle.pbWeather == PBWeather::Hail && @user.hasActiveAbility?(:SNOWCLOAK))
mini_score *= 1.3
end
# Prefer if user knows any healing moves
mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? }
# Prefer if user knows Pain Split or Leech Seed
mini_score *= 1.2 if @user.pbHasMoveFunction?("05A") # Pain Split
mini_score *= 1.3 if @user.pbHasMoveFunction?("0DC") # Leech Seed
# Prefer if user has certain roles
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
# TODO: Don't prefer if user's evasion stat is raised
# TODO: Don't prefer if target has No Guard.
mini_score *= 0.2 if @target.hasActiveAbility?(:NOGUARD)
# TODO: Don't prefer if target has previously used any moves that never miss.
end
# Don't prefer if user has Contrary
mini_score *= 0.5 if @user.hasActiveAbility?(:CONTRARY)
# TODO: Don't prefer if target has Unaware? Reborn resets mini_score to 1.
# This check needs more consideration. Note that @target is user for
# status moves, so that part is wrong.
# TODO: Is 0x for 025, 026, 026 (all moves that raise multiple stats)
mini_score *= 0.5 if @move.statusMove? && @target.hasActiveAbility?(:UNAWARE)
# TODO: Don't prefer if any foe has previously used a stat stage-clearing
# move (050, 051 Clear Smog/Haze).
mini_score *= 0.3 if check_for_move(@target) { |move| ["050", "051"].include?(move.function) } # Clear Smog, Haze
# TODO: Prefer if user is faster than the target.
# TODO: Is 1.3x for 025 Coil (+Atk, +Def, +acc).
mini_score *= 1.5 if @user_faster
# TODO: Don't prefer if target is a higher level than the user
if @target.level > @user.level + 5
mini_score *= 0.6
if @target.level > @user.level + 10
mini_score *= 0.2
end
end
return mini_score
end
#=============================================================================
#
#=============================================================================
def get_score_for_user_stat_raise(score)
# Discard status move if user has Contrary
return 0 if @move.statusMove? && @user.hasActiveAbility?(:CONTRARY)
# Discard move if it can't raise any stats
can_change_any_stat = false
@move.stat_up.each_with_index do |stat, idx|
next if idx.odd?
next if @user.statStageAtMax?(stat)
can_change_any_stat = true
break
end
if !can_change_any_stat
return (@move.statusMove?) ? 0 : score
end
# Get the main mini-score
main_mini_score = calc_user_stat_raise_mini_score
# For each stat to be raised in turn, calculate a mini-score describing how
# beneficial that stat being raised will be
mini_score = 0
num_stats = 0
@move.stat_up.each_with_index do |stat, idx|
next if idx.odd?
next if @user.statStageAtMax?(stat)
# TODO: Use the effective increment (e.g. 1 if the stat is raised by 2 but
# the stat is already at +5).
mini_score += calc_user_stat_raise_one(stat, @move.stat_up[idx + 1])
num_stats += 1
end
# Apply the average mini-score to the actual score
score = apply_effect_chance_to_score(main_mini_score * mini_score / num_stats)
return score
end
end

View File

@@ -1,746 +0,0 @@
class PokeBattle_AI
alias __b__pbGetMoveScoreFunctions pbGetMoveScoreFunctions
#=============================================================================
# Get a score for the given move based on its effect
#=============================================================================
def pbGetMoveScoreFunctions(score)
score = __b__pbGetMoveScoreFunctions(score)
case @move.function
#---------------------------------------------------------------------------
when "040"
if !@target.pbCanConfuse?(@user,false)
score -= 90
else
score += 30 if @target.stages[PBStats::SPATK]<0
end
#---------------------------------------------------------------------------
when "041"
if !@target.pbCanConfuse?(@user,false)
score -= 90
else
score += 30 if @target.stages[PBStats::ATTACK]<0
end
#---------------------------------------------------------------------------
when "042"
if @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::ATTACK,@user)
score -= 90
else
score += @target.stages[PBStats::ATTACK]*20
if skill_check(AILevel.medium)
hasPhysicalAttack = false
@target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill_check(AILevel.high)
score -= 90
end
end
end
else
score += 20 if @target.stages[PBStats::ATTACK]>0
if skill_check(AILevel.medium)
hasPhysicalAttack = false
@target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
score += 20 if hasPhysicalAttack
end
end
#---------------------------------------------------------------------------
when "043"
if @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::DEFENSE,@user)
score -= 90
else
score += @target.stages[PBStats::DEFENSE]*20
end
else
score += 20 if @target.stages[PBStats::DEFENSE]>0
end
#---------------------------------------------------------------------------
when "044"
if @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::SPEED,@user)
score -= 90
else
score += @target.stages[PBStats::SPEED]*10
if skill_check(AILevel.high)
aspeed = pbRoughStat(@user,PBStats::SPEED)
ospeed = pbRoughStat(@target,PBStats::SPEED)
score += 30 if aspeed<ospeed && aspeed*2>ospeed
end
end
else
score += 20 if @user.stages[PBStats::SPEED]>0
end
#---------------------------------------------------------------------------
when "045"
if @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::SPATK,@user)
score -= 90
else
score += @user.stages[PBStats::SPATK]*20
if skill_check(AILevel.medium)
hasSpecicalAttack = false
@target.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif skill_check(AILevel.high)
score -= 90
end
end
end
else
score += 20 if @user.stages[PBStats::SPATK]>0
if skill_check(AILevel.medium)
hasSpecicalAttack = false
@target.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
score += 20 if hasSpecicalAttack
end
end
#---------------------------------------------------------------------------
when "046"
if @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::SPDEF,@user)
score -= 90
else
score += @target.stages[PBStats::SPDEF]*20
end
else
score += 20 if @target.stages[PBStats::SPDEF]>0
end
#---------------------------------------------------------------------------
when "047"
if @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::ACCURACY,@user)
score -= 90
else
score += @target.stages[PBStats::ACCURACY]*10
end
else
score += 20 if @target.stages[PBStats::ACCURACY]>0
end
#---------------------------------------------------------------------------
when "048"
if @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::EVASION,@user)
score -= 90
else
score += @target.stages[PBStats::EVASION]*10
end
else
score += 20 if @target.stages[PBStats::EVASION]>0
end
#---------------------------------------------------------------------------
when "049"
if @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::EVASION,@user)
score -= 90
else
score += @target.stages[PBStats::EVASION]*10
end
else
score += 20 if @target.stages[PBStats::EVASION]>0
end
score += 30 if @target.pbOwnSide.effects[PBEffects::AuroraVeil]>0 ||
@target.pbOwnSide.effects[PBEffects::Reflect]>0 ||
@target.pbOwnSide.effects[PBEffects::LightScreen]>0 ||
@target.pbOwnSide.effects[PBEffects::Mist]>0 ||
@target.pbOwnSide.effects[PBEffects::Safeguard]>0
score -= 30 if @target.pbOwnSide.effects[PBEffects::Spikes]>0 ||
@target.pbOwnSide.effects[PBEffects::ToxicSpikes]>0 ||
@target.pbOwnSide.effects[PBEffects::StealthRock]
#---------------------------------------------------------------------------
when "04A"
avg = @target.stages[PBStats::ATTACK]*10
avg += @target.stages[PBStats::DEFENSE]*10
score += avg/2
#---------------------------------------------------------------------------
when "04B"
if @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::ATTACK,@user)
score -= 90
else
score += 40 if @user.turnCount==0
score += @target.stages[PBStats::ATTACK]*20
if skill_check(AILevel.medium)
hasPhysicalAttack = false
@target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill_check(AILevel.high)
score -= 90
end
end
end
else
score += 10 if @user.turnCount==0
score += 20 if @target.stages[PBStats::ATTACK]>0
if skill_check(AILevel.medium)
hasPhysicalAttack = false
@target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
score += 20 if hasPhysicalAttack
end
end
#---------------------------------------------------------------------------
when "04C"
if @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::DEFENSE,@user)
score -= 90
else
score += 40 if @user.turnCount==0
score += @target.stages[PBStats::DEFENSE]*20
end
else
score += 10 if @user.turnCount==0
score += 20 if @target.stages[PBStats::DEFENSE]>0
end
#---------------------------------------------------------------------------
when "04D"
if @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::SPEED,@user)
score -= 90
else
score += 20 if @user.turnCount==0
score += @target.stages[PBStats::SPEED]*20
if skill_check(AILevel.high)
aspeed = pbRoughStat(@user,PBStats::SPEED)
ospeed = pbRoughStat(@target,PBStats::SPEED)
score += 30 if aspeed<ospeed && aspeed*2>ospeed
end
end
else
score += 10 if @user.turnCount==0
score += 30 if @target.stages[PBStats::SPEED]>0
end
#---------------------------------------------------------------------------
when "04E"
if @user.gender==2 || @target.gender==2 || @user.gender==@target.gender ||
@target.hasActiveAbility?(:OBLIVIOUS)
score -= 90
elsif @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::SPATK,@user)
score -= 90
else
score += 40 if @user.turnCount==0
score += @target.stages[PBStats::SPATK]*20
if skill_check(AILevel.medium)
hasSpecicalAttack = false
@target.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
if hasSpecicalAttack
score += 20
elsif skill_check(AILevel.high)
score -= 90
end
end
end
else
score += 10 if @user.turnCount==0
score += 20 if @target.stages[PBStats::SPATK]>0
if skill_check(AILevel.medium)
hasSpecicalAttack = false
@target.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecicalAttack = true
break
end
score += 30 if hasSpecicalAttack
end
end
#---------------------------------------------------------------------------
when "04F"
if @move.statusMove?
if !@target.pbCanLowerStatStage?(PBStats::SPDEF,@user)
score -= 90
else
score += 40 if @user.turnCount==0
score += @target.stages[PBStats::SPDEF]*20
end
else
score += 10 if @user.turnCount==0
score += 20 if @target.stages[PBStats::SPDEF]>0
end
#---------------------------------------------------------------------------
when "050"
if @target.effects[PBEffects::Substitute]>0
score -= 90
else
avg = 0; anyChange = false
PBStats.eachBattleStat do |s|
next if @target.stages[s]==0
avg += @target.stages[s]
anyChange = true
end
if anyChange
score += avg*10
else
score -= 90
end
end
#---------------------------------------------------------------------------
when "051"
if skill_check(AILevel.medium)
stages = 0
@battle.eachBattler do |b|
totalStages = 0
PBStats.eachBattleStat { |s| totalStages += b.stages[s] }
if b.opposes?(@user)
stages += totalStages
else
stages -= totalStages
end
end
score += stages*10
end
#---------------------------------------------------------------------------
when "052"
if skill_check(AILevel.medium)
aatk = @user.stages[PBStats::ATTACK]
aspa = @user.stages[PBStats::SPATK]
oatk = @target.stages[PBStats::ATTACK]
ospa = @target.stages[PBStats::SPATK]
if aatk>=oatk && aspa>=ospa
score -= 80
else
score += (oatk-aatk)*10
score += (ospa-aspa)*10
end
else
score -= 50
end
#---------------------------------------------------------------------------
when "053"
if skill_check(AILevel.medium)
adef = @user.stages[PBStats::DEFENSE]
aspd = @user.stages[PBStats::SPDEF]
odef = @target.stages[PBStats::DEFENSE]
ospd = @target.stages[PBStats::SPDEF]
if adef>=odef && aspd>=ospd
score -= 80
else
score += (odef-adef)*10
score += (ospd-aspd)*10
end
else
score -= 50
end
#---------------------------------------------------------------------------
when "054"
if skill_check(AILevel.medium)
userStages = 0; targetStages = 0
PBStats.eachBattleStat do |s|
userStages += @user.stages[s]
targetStages += @target.stages[s]
end
score += (targetStages-userStages)*10
else
score -= 50
end
#---------------------------------------------------------------------------
when "055"
if skill_check(AILevel.medium)
equal = true
PBStats.eachBattleStat do |s|
stagediff = @target.stages[s]-@user.stages[s]
score += stagediff*10
equal = false if stagediff!=0
end
score -= 80 if equal
else
score -= 50
end
#---------------------------------------------------------------------------
when "056"
score -= 80 if @user.pbOwnSide.effects[PBEffects::Mist]>0
#---------------------------------------------------------------------------
when "057"
if skill_check(AILevel.medium)
aatk = pbRoughStat(@user,PBStats::ATTACK)
adef = pbRoughStat(@user,PBStats::DEFENSE)
if aatk==adef ||
@user.effects[PBEffects::PowerTrick] # No flip-flopping
score -= 90
elsif adef>aatk # Prefer a higher Attack
score += 30
else
score -= 30
end
else
score -= 30
end
#---------------------------------------------------------------------------
when "058"
if skill_check(AILevel.medium)
aatk = pbRoughStat(@user,PBStats::ATTACK)
aspatk = pbRoughStat(@user,PBStats::SPATK)
oatk = pbRoughStat(@target,PBStats::ATTACK)
ospatk = pbRoughStat(@target,PBStats::SPATK)
if aatk<oatk && aspatk<ospatk
score += 50
elsif aatk+aspatk<oatk+ospatk
score += 30
else
score -= 50
end
else
score -= 30
end
#---------------------------------------------------------------------------
when "059"
if skill_check(AILevel.medium)
adef = pbRoughStat(@user,PBStats::DEFENSE)
aspdef = pbRoughStat(@user,PBStats::SPDEF)
odef = pbRoughStat(@target,PBStats::DEFENSE)
ospdef = pbRoughStat(@target,PBStats::SPDEF)
if adef<odef && aspdef<ospdef
score += 50
elsif adef+aspdef<odef+ospdef
score += 30
else
score -= 50
end
else
score -= 30
end
#---------------------------------------------------------------------------
when "05A"
if @target.effects[PBEffects::Substitute]>0
score -= 90
elsif @user.hp>=(@user.hp+@target.hp)/2
score -= 90
else
score += 40
end
#---------------------------------------------------------------------------
when "05B"
score -= 90 if @user.pbOwnSide.effects[PBEffects::Tailwind]>0
#---------------------------------------------------------------------------
when "05C"
moveBlacklist = [
"002", # Struggle
"014", # Chatter
"05C", # Mimic
"05D", # Sketch
"0B6" # Metronome
]
if @user.effects[PBEffects::Transform] || !@target.lastRegularMoveUsed
score -= 90
else
lastMoveData = GameData::Move.get(@target.lastRegularMoveUsed)
if moveBlacklist.include?(lastMoveData.function_code) ||
lastMoveData.type == :SHADOW
score -= 90
end
@user.eachMove do |m|
next if m != @target.lastRegularMoveUsed
score -= 90
break
end
end
#---------------------------------------------------------------------------
when "05D"
moveBlacklist = [
"002", # Struggle
"014", # Chatter
"05D" # Sketch
]
if @user.effects[PBEffects::Transform] || !@target.lastRegularMoveUsed
score -= 90
else
lastMoveData = GameData::Move.get(@target.lastRegularMoveUsed)
if moveBlacklist.include?(lastMoveData.function_code) ||
lastMoveData.type == :SHADOW
score -= 90
end
@user.eachMove do |m|
next if m != @target.lastRegularMoveUsed
score -= 90 # User already knows the move that will be Sketched
break
end
end
#---------------------------------------------------------------------------
when "05E"
if [:MULTITYPE, :RKSSYSTEM].include?(@user.ability_id)
score -= 90
else
types = []
@user.eachMove do |m|
next if m.id==@id
next if PBTypes.isPseudoType?(m.type)
next if @user.pbHasType?(m.type)
types.push(m.type) if !types.include?(m.type)
end
score -= 90 if types.length==0
end
#---------------------------------------------------------------------------
when "05F"
if [:MULTITYPE, :RKSSYSTEM].include?(@user.ability_id)
score -= 90
elsif !@target.lastMoveUsed ||
PBTypes.isPseudoType?(GameData::Move.get(@target.lastMoveUsed).type)
score -= 90
else
aType = nil
@target.eachMove do |m|
next if m.id!=@target.lastMoveUsed
aType = m.pbCalcType(@user)
break
end
if aType
types = []
GameData::Type.each do |t|
types.push(t.id) if !@user.pbHasType?(t.id) && PBTypes.resistant?(aType, t.id)
end
score -= 90 if types.length==0
else
score -= 90
end
end
#---------------------------------------------------------------------------
when "060"
if [:MULTITYPE, :RKSSYSTEM].include?(@user.ability_id)
score -= 90
elsif skill_check(AILevel.medium)
envtypes = [
:NORMAL, # None
:GRASS, # Grass
:GRASS, # Tall grass
:WATER, # Moving water
:WATER, # Still water
:WATER, # Underwater
:ROCK, # Rock
:ROCK, # Cave
:GROUND # Sand
]
type = envtypes[@battle.environment]
score -= 90 if @user.pbHasType?(type)
end
#---------------------------------------------------------------------------
when "061"
if @target.effects[PBEffects::Substitute]>0 ||
[:MULTITYPE, :RKSSYSTEM].include?(@target.ability_id)
score -= 90
elsif @target.pbHasType?(:WATER)
score -= 90
end
#---------------------------------------------------------------------------
when "062"
if [:MULTITYPE, :RKSSYSTEM].include?(@user.ability_id)
score -= 90
elsif @user.pbHasType?(@target.type1) &&
@user.pbHasType?(@target.type2) &&
@target.pbHasType?(@user.type1) &&
@target.pbHasType?(@user.type2)
score -= 90
end
#---------------------------------------------------------------------------
when "063"
if @target.effects[PBEffects::Substitute]>0
score -= 90
elsif skill_check(AILevel.medium)
if [:MULTITYPE, :RKSSYSTEM, :SIMPLE, :TRUANT].include?(@target.ability_id)
score -= 90
end
end
#---------------------------------------------------------------------------
when "064"
if @target.effects[PBEffects::Substitute]>0
score -= 90
elsif skill_check(AILevel.medium)
if [:INSOMNIA, :MULTITYPE, :RKSSYSTEM, :TRUANT].include?(@target.ability_id)
score -= 90
end
end
#---------------------------------------------------------------------------
when "065"
score -= 40 # don't prefer this move
if skill_check(AILevel.medium)
if !@target.ability || @user.ability_id == @target.ability_id ||
[:MULTITYPE, :RKSSYSTEM].include?(@user.ability_id) ||
[:FLOWERGIFT, :FORECAST, :ILLUSION, :IMPOSTER, :MULTITYPE, :RKSSYSTEM,
:TRACE, :WONDERGUARD, :ZENMODE].include?(@target.ability_id)
score -= 90
end
end
if skill_check(AILevel.high) && @user.opposes?(@target)
score -= 90 if [:SLOWSTART, :TRUANT].include?(@target.ability_id)
end
#---------------------------------------------------------------------------
when "066"
score -= 40 # don't prefer this move
if @target.effects[PBEffects::Substitute]>0
score -= 90
elsif skill_check(AILevel.medium)
if !@user.ability || @user.ability_id == @target.ability_id ||
[:MULTITYPE, :RKSSYSTEM, :TRUANT].include?(@target.ability_id) ||
[:FLOWERGIFT, :FORECAST, :ILLUSION, :IMPOSTER, :MULTITYPE, :RKSSYSTEM,
:TRACE, :ZENMODE].include?(@user.ability_id)
score -= 90
end
if skill_check(AILevel.high) && @user.opposes?(@target)
score += 90 if [:SLOWSTART, :TRUANT].include?(@user.ability_id)
end
end
#---------------------------------------------------------------------------
when "067"
score -= 40 # don't prefer this move
if skill_check(AILevel.medium)
if (!@user.ability && !@target.ability) ||
@user.ability_id == @target.ability_id ||
[:ILLUSION, :MULTITYPE, :RKSSYSTEM, :WONDERGUARD].include?(@user.ability_id) ||
[:ILLUSION, :MULTITYPE, :RKSSYSTEM, :WONDERGUARD].include?(@target.ability_id)
score -= 90
end
end
if skill_check(AILevel.high) && @user.opposes?(@target)
score -= 90 if [:SLOWSTART, :TRUANT].include?(@target.ability_id)
end
#---------------------------------------------------------------------------
when "068"
if @target.effects[PBEffects::Substitute]>0 ||
@target.effects[PBEffects::GastroAcid]
score -= 90
elsif skill_check(AILevel.high)
score -= 90 if [:MULTITYPE, :RKSSYSTEM, :SLOWSTART, :TRUANT].include?(@target.ability_id)
end
#---------------------------------------------------------------------------
when "069"
score -= 70
#---------------------------------------------------------------------------
when "06A"
if @target.hp<=20
score += 80
elsif @target.level>=25
score -= 60 # Not useful against high-level Pokemon
end
#---------------------------------------------------------------------------
when "06B"
score += 80 if @target.hp<=40
#---------------------------------------------------------------------------
when "06C"
score -= 50
score += @target.hp*100/@target.totalhp
#---------------------------------------------------------------------------
when "06D"
score += 80 if @target.hp<=@user.level
#---------------------------------------------------------------------------
when "06E"
if @user.hp>=@target.hp
score -= 90
elsif @user.hp<@target.hp/2
score += 50
end
#---------------------------------------------------------------------------
when "06F"
score += 30 if @target.hp<=@user.level
#---------------------------------------------------------------------------
when "070"
score -= 90 if @target.hasActiveAbility?(:STURDY)
score -= 90 if @target.level>@user.level
#---------------------------------------------------------------------------
when "071"
if @target.effects[PBEffects::HyperBeam]>0
score -= 90
else
attack = pbRoughStat(@user,PBStats::ATTACK)
spatk = pbRoughStat(@user,PBStats::SPATK)
if attack*1.5<spatk
score -= 60
elsif skill_check(AILevel.medium) && @target.lastMoveUsed
moveData = GameData::Move.get(@target.lastMoveUsed)
if moveData.base_damage > 0 &&
(MOVE_CATEGORY_PER_MOVE && moveData.category == 0) ||
(!MOVE_CATEGORY_PER_MOVE && PBTypes.isPhysicalType?(moveData.type))
score -= 60
end
end
end
#---------------------------------------------------------------------------
when "072"
if @target.effects[PBEffects::HyperBeam]>0
score -= 90
else
attack = pbRoughStat(@user,PBStats::ATTACK)
spatk = pbRoughStat(@user,PBStats::SPATK)
if attack>spatk*1.5
score -= 60
elsif skill_check(AILevel.medium) && @target.lastMoveUsed
moveData = GameData::Move.get(@target.lastMoveUsed)
if moveData.base_damage > 0 &&
(MOVE_CATEGORY_PER_MOVE && moveData.category == 1) ||
(!MOVE_CATEGORY_PER_MOVE && !PBTypes.isSpecialType?(moveData.type))
score -= 60
end
end
end
#---------------------------------------------------------------------------
when "073"
score -= 90 if @target.effects[PBEffects::HyperBeam]>0
#---------------------------------------------------------------------------
when "074"
@target.eachAlly do |b|
next if !b.near?(@target)
score += 10
end
#---------------------------------------------------------------------------
when "075"
#---------------------------------------------------------------------------
when "076"
#---------------------------------------------------------------------------
when "077"
#---------------------------------------------------------------------------
when "078"
if skill_check(AILevel.high)
score += 30 if !@target.hasActiveAbility?(:INNERFOCUS) &&
@target.effects[PBEffects::Substitute]==0
end
#---------------------------------------------------------------------------
when "079"
#---------------------------------------------------------------------------
when "07A"
#---------------------------------------------------------------------------
when "07B"
#---------------------------------------------------------------------------
when "07C"
score -= 20 if @target.status==PBStatuses::PARALYSIS # Will cure status
#---------------------------------------------------------------------------
when "07D"
score -= 20 if @target.status==PBStatuses::SLEEP && # Will cure status
@target.statusCount>1
#---------------------------------------------------------------------------
when "07E"
#---------------------------------------------------------------------------
when "07F"
#---------------------------------------------------------------------------
end
return score
end
end

View File

@@ -1,227 +0,0 @@
class PokeBattle_AI
alias __c__pbGetMoveScoreFunctions pbGetMoveScoreFunctions
#=============================================================================
# Get a score for the given move based on its effect
#=============================================================================
def pbGetMoveScoreFunctions(score)
score = __c__pbGetMoveScoreFunctions(score)
case @move.function
#---------------------------------------------------------------------------
when "080"
#---------------------------------------------------------------------------
when "081"
attspeed = pbRoughStat(@user,PBStats::SPEED)
oppspeed = pbRoughStat(@target,PBStats::SPEED)
score += 30 if oppspeed>attspeed
#---------------------------------------------------------------------------
when "082"
score += 20 if @battle.pbOpposingBattlerCount(@user)>1
#---------------------------------------------------------------------------
when "083"
if skill_check(AILevel.medium)
@user.eachAlly do |b|
next if !b.pbHasMove?(@move.id)
score += 20
end
end
#---------------------------------------------------------------------------
when "084"
attspeed = pbRoughStat(@user,PBStats::SPEED)
oppspeed = pbRoughStat(@target,PBStats::SPEED)
score += 30 if oppspeed>attspeed
#---------------------------------------------------------------------------
when "085"
#---------------------------------------------------------------------------
when "086"
#---------------------------------------------------------------------------
when "087"
#---------------------------------------------------------------------------
when "088"
#---------------------------------------------------------------------------
when "089"
#---------------------------------------------------------------------------
when "08A"
#---------------------------------------------------------------------------
when "08B"
#---------------------------------------------------------------------------
when "08C"
#---------------------------------------------------------------------------
when "08D"
#---------------------------------------------------------------------------
when "08E"
#---------------------------------------------------------------------------
when "08F"
#---------------------------------------------------------------------------
when "090"
#---------------------------------------------------------------------------
when "091"
#---------------------------------------------------------------------------
when "092"
#---------------------------------------------------------------------------
when "093"
score += 25 if @user.effects[PBEffects::Rage]
#---------------------------------------------------------------------------
when "094"
#---------------------------------------------------------------------------
when "095"
#---------------------------------------------------------------------------
when "096"
score -= 90 if !@user.item || !@user.item.is_berry? || !@user.itemActive?
#---------------------------------------------------------------------------
when "097"
#---------------------------------------------------------------------------
when "098"
#---------------------------------------------------------------------------
when "099"
#---------------------------------------------------------------------------
when "09A"
#---------------------------------------------------------------------------
when "09B"
#---------------------------------------------------------------------------
when "09C"
hasAlly = false
@user.eachAlly do |b|
hasAlly = true
score += 30
break
end
score -= 90 if !hasAlly
#---------------------------------------------------------------------------
when "09D"
score -= 90 if @user.effects[PBEffects::MudSport]
#---------------------------------------------------------------------------
when "09E"
score -= 90 if @user.effects[PBEffects::WaterSport]
#---------------------------------------------------------------------------
when "09F"
#---------------------------------------------------------------------------
when "0A0"
#---------------------------------------------------------------------------
when "0A1"
score -= 90 if @user.pbOwnSide.effects[PBEffects::LuckyChant]>0
#---------------------------------------------------------------------------
when "0A2"
score -= 90 if @user.pbOwnSide.effects[PBEffects::Reflect]>0
#---------------------------------------------------------------------------
when "0A3"
score -= 90 if @user.pbOwnSide.effects[PBEffects::LightScreen]>0
#---------------------------------------------------------------------------
when "0A4"
#---------------------------------------------------------------------------
when "0A5"
#---------------------------------------------------------------------------
when "0A6"
score -= 90 if @target.effects[PBEffects::Substitute]>0
score -= 90 if @user.effects[PBEffects::LockOn]>0
#---------------------------------------------------------------------------
when "0A7"
if @target.effects[PBEffects::Foresight]
score -= 90
elsif @target.pbHasType?(:GHOST)
score += 70
elsif @target.stages[PBStats::EVASION]<=0
score -= 60
end
#---------------------------------------------------------------------------
when "0A8"
if @target.effects[PBEffects::MiracleEye]
score -= 90
elsif @target.pbHasType?(:DARK)
score += 70
elsif @target.stages[PBStats::EVASION]<=0
score -= 60
end
#---------------------------------------------------------------------------
when "0A9"
#---------------------------------------------------------------------------
when "0AA"
if @user.effects[PBEffects::ProtectRate]>1 ||
@target.effects[PBEffects::HyperBeam]>0
score -= 90
else
if skill_check(AILevel.medium)
score -= @user.effects[PBEffects::ProtectRate]*40
end
score += 50 if @user.turnCount==0
score += 30 if @target.effects[PBEffects::TwoTurnAttack]
end
#---------------------------------------------------------------------------
when "0AB"
#---------------------------------------------------------------------------
when "0AC"
#---------------------------------------------------------------------------
when "0AD"
#---------------------------------------------------------------------------
when "0AE"
score -= 40
if skill_check(AILevel.high)
score -= 100 if !@target.lastRegularMoveUsed ||
!GameData::Move.get(@target.lastRegularMoveUsed).flags[/e/] # Not copyable by Mirror Move
end
#---------------------------------------------------------------------------
when "0AF"
#---------------------------------------------------------------------------
when "0B0"
#---------------------------------------------------------------------------
when "0B1"
#---------------------------------------------------------------------------
when "0B2"
#---------------------------------------------------------------------------
when "0B3"
#---------------------------------------------------------------------------
when "0B4"
if @user.asleep?
score += 100 # Because it can only be used while asleep
else
score -= 90
end
#---------------------------------------------------------------------------
when "0B5"
#---------------------------------------------------------------------------
when "0B6"
#---------------------------------------------------------------------------
when "0B7"
score -= 90 if @target.effects[PBEffects::Torment]
#---------------------------------------------------------------------------
when "0B8"
score -= 90 if @user.effects[PBEffects::Imprison]
#---------------------------------------------------------------------------
when "0B9"
score -= 90 if @target.effects[PBEffects::Disable]>0
#---------------------------------------------------------------------------
when "0BA"
score -= 90 if @target.effects[PBEffects::Taunt]>0
#---------------------------------------------------------------------------
when "0BB"
score -= 90 if @target.effects[PBEffects::HealBlock]>0
#---------------------------------------------------------------------------
when "0BC"
aspeed = pbRoughStat(@user,PBStats::SPEED)
ospeed = pbRoughStat(@target,PBStats::SPEED)
if @target.effects[PBEffects::Encore]>0
score -= 90
elsif aspeed>ospeed
if !@target.lastRegularMoveUsed
score -= 90
else
moveData = GameData::Move.get(@target.lastRegularMoveUsed)
if moveData.category == 2 && # Status move
[PBTargets::User, PBTargets::BothSides].include?(moveData.target)
score += 60
elsif moveData.category != 2 && # Damaging move
moveData.target == PBTargets::NearOther &&
PBTypeEffectiveness.ineffective?(pbCalcTypeMod(moveData.type, @target, @user))
score += 60
end
end
end
#---------------------------------------------------------------------------
when "0BD"
#---------------------------------------------------------------------------
when "0BF"
#---------------------------------------------------------------------------
end
return score
end
end

View File

@@ -1,375 +0,0 @@
class PokeBattle_AI
alias __d__pbGetMoveScoreFunctions pbGetMoveScoreFunctions
#=============================================================================
# Get a score for the given move based on its effect
#=============================================================================
def pbGetMoveScoreFunctions(score)
score = __d__pbGetMoveScoreFunctions(score)
case @move.function
#---------------------------------------------------------------------------
when "0C0"
#---------------------------------------------------------------------------
when "0C1"
#---------------------------------------------------------------------------
when "0C2"
#---------------------------------------------------------------------------
when "0C3"
#---------------------------------------------------------------------------
when "0C4"
#---------------------------------------------------------------------------
when "0C7"
score += 20 if @user.effects[PBEffects::FocusEnergy]>0
if skill_check(AILevel.high)
score += 20 if !@target.hasActiveAbility?(:INNERFOCUS) &&
@target.effects[PBEffects::Substitute]==0
end
#---------------------------------------------------------------------------
when "0C9"
#---------------------------------------------------------------------------
when "0CA"
#---------------------------------------------------------------------------
when "0CB"
#---------------------------------------------------------------------------
when "0CC"
#---------------------------------------------------------------------------
when "0CD"
#---------------------------------------------------------------------------
when "0CE"
#---------------------------------------------------------------------------
when "0CF"
score += 40 if @target.effects[PBEffects::Trapping]==0
#---------------------------------------------------------------------------
when "0D0"
score += 40 if @target.effects[PBEffects::Trapping]==0
#---------------------------------------------------------------------------
when "0D1"
#---------------------------------------------------------------------------
when "0D2"
#---------------------------------------------------------------------------
when "0D3"
#---------------------------------------------------------------------------
when "0D4"
if @user.hp<=@user.totalhp/4
score -= 90
elsif @user.hp<=@user.totalhp/2
score -= 50
end
#---------------------------------------------------------------------------
when "0D5", "0D6"
if @user.hp==@user.totalhp || (skill_check(AILevel.medium) && !@user.canHeal?)
score -= 90
else
score += 50
score -= @user.hp*100/@user.totalhp
end
#---------------------------------------------------------------------------
when "0D7"
score -= 90 if @battle.positions[@user.index].effects[PBEffects::Wish]>0
#---------------------------------------------------------------------------
when "0D8"
if @user.hp==@user.totalhp || (skill_check(AILevel.medium) && !@user.canHeal?)
score -= 90
else
case @battle.pbWeather
when PBWeather::Sun, PBWeather::HarshSun
score += 30
when PBWeather::None
else
score -= 30
end
score += 50
score -= @user.hp*100/@user.totalhp
end
#---------------------------------------------------------------------------
when "0D9"
if @user.hp==@user.totalhp || !@user.pbCanSleep?(@user,false,nil,true)
score -= 90
else
score += 70
score -= @user.hp*140/@user.totalhp
score += 30 if @user.status!=0
end
#---------------------------------------------------------------------------
when "0DA"
score -= 90 if @user.effects[PBEffects::AquaRing]
#---------------------------------------------------------------------------
when "0DB"
score -= 90 if @user.effects[PBEffects::Ingrain]
#---------------------------------------------------------------------------
when "0DC"
if @target.effects[PBEffects::LeechSeed]>=0
score -= 90
elsif skill_check(AILevel.medium) && @target.pbHasType?(:GRASS)
score -= 90
else
score += 60 if @user.turnCount==0
end
#---------------------------------------------------------------------------
when "0DD"
if skill_check(AILevel.high) && @target.hasActiveAbility?(:LIQUIDOOZE)
score -= 70
else
score += 20 if @user.hp<=@user.totalhp/2
end
#---------------------------------------------------------------------------
when "0DE"
if !@target.asleep?
score -= 100
elsif skill_check(AILevel.high) && @target.hasActiveAbility?(:LIQUIDOOZE)
score -= 70
else
score += 20 if @user.hp<=@user.totalhp/2
end
#---------------------------------------------------------------------------
when "0DF"
if @user.opposes?(@target)
score -= 100
else
score += 20 if @target.hp<@target.totalhp/2 &&
@target.effects[PBEffects::Substitute]==0
end
#---------------------------------------------------------------------------
when "0E0"
reserves = @battle.pbAbleNonActiveCount(@user.idxOwnSide)
foes = @battle.pbAbleNonActiveCount(@user.idxOpposingSide)
if @battle.pbCheckGlobalAbility(:DAMP)
score -= 100
elsif skill_check(AILevel.medium) && reserves==0 && foes>0
score -= 100 # don't want to lose
elsif skill_check(AILevel.high) && reserves==0 && foes==0
score += 80 # want to draw
else
score -= @user.hp*100/@user.totalhp
end
#---------------------------------------------------------------------------
when "0E1"
#---------------------------------------------------------------------------
when "0E2"
if !@target.pbCanLowerStatStage?(PBStats::ATTACK,@user) &&
!@target.pbCanLowerStatStage?(PBStats::SPATK,@user)
score -= 100
elsif @battle.pbAbleNonActiveCount(@user.idxOwnSide)==0
score -= 100
else
score += @target.stages[PBStats::ATTACK]*10
score += @target.stages[PBStats::SPATK]*10
score -= @user.hp*100/@user.totalhp
end
#---------------------------------------------------------------------------
when "0E3", "0E4"
score -= 70
#---------------------------------------------------------------------------
when "0E5"
if @battle.pbAbleNonActiveCount(@user.idxOwnSide)==0
score -= 90
else
score -= 90 if @target.effects[PBEffects::PerishSong]>0
end
#---------------------------------------------------------------------------
when "0E6"
score += 50
score -= @user.hp*100/@user.totalhp
score += 30 if @user.hp<=@user.totalhp/10
#---------------------------------------------------------------------------
when "0E7"
score += 50
score -= @user.hp*100/@user.totalhp
score += 30 if @user.hp<=@user.totalhp/10
#---------------------------------------------------------------------------
when "0E8"
score -= 25 if @user.hp>@user.totalhp/2
if skill_check(AILevel.medium)
score -= 90 if @user.effects[PBEffects::ProtectRate]>1
score -= 90 if @target.effects[PBEffects::HyperBeam]>0
else
score -= @user.effects[PBEffects::ProtectRate]*40
end
#---------------------------------------------------------------------------
when "0E9"
if @target.hp==1
score -= 90
elsif @target.hp<=@target.totalhp/8
score -= 60
elsif @target.hp<=@target.totalhp/4
score -= 30
end
#---------------------------------------------------------------------------
when "0EA"
score -= 100 if @battle.trainerBattle?
#---------------------------------------------------------------------------
when "0EB"
if @target.effects[PBEffects::Ingrain] ||
(skill_check(AILevel.high) && @target.hasActiveAbility?(:SUCTIONCUPS))
score -= 90
else
ch = 0
@battle.pbParty(@target.index).each_with_index do |pkmn,i|
ch += 1 if @battle.pbCanSwitchLax?(@target.index,i)
end
score -= 90 if ch==0
end
if score>20
score += 50 if @target.pbOwnSide.effects[PBEffects::Spikes]>0
score += 50 if @target.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
score += 50 if @target.pbOwnSide.effects[PBEffects::StealthRock]
end
#---------------------------------------------------------------------------
when "0EC"
if !@target.effects[PBEffects::Ingrain] &&
!(skill_check(AILevel.high) && @target.hasActiveAbility?(:SUCTIONCUPS))
score += 40 if @target.pbOwnSide.effects[PBEffects::Spikes]>0
score += 40 if @target.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
score += 40 if @target.pbOwnSide.effects[PBEffects::StealthRock]
end
#---------------------------------------------------------------------------
when "0ED"
if !@battle.pbCanChooseNonActive?(@user.index)
score -= 80
else
score -= 40 if @user.effects[PBEffects::Confusion]>0
total = 0
PBStats.eachBattleStat { |s| total += @user.stages[s] }
if total<=0 || @user.turnCount==0
score -= 60
else
score += total*10
# special case: user has no damaging moves
hasDamagingMove = false
@user.eachMove do |m|
next if !m.damagingMove?
hasDamagingMove = true
break
end
score += 75 if !hasDamagingMove
end
end
#---------------------------------------------------------------------------
when "0EE"
#---------------------------------------------------------------------------
when "0EF"
score -= 90 if @target.effects[PBEffects::MeanLook]>=0
#---------------------------------------------------------------------------
when "0F0"
if skill_check(AILevel.high)
score += 20 if @target.item
end
#---------------------------------------------------------------------------
when "0F1"
if skill_check(AILevel.high)
if !@user.item && @target.item
score += 40
else
score -= 90
end
else
score -= 80
end
#---------------------------------------------------------------------------
when "0F2"
if !@user.item && !@target.item
score -= 90
elsif skill_check(AILevel.high) && @target.hasActiveAbility?(:STICKYHOLD)
score -= 90
elsif @user.hasActiveItem?([:FLAMEORB,:TOXICORB,:STICKYBARB,:IRONBALL,
:CHOICEBAND,:CHOICESCARF,:CHOICESPECS])
score += 50
elsif !@user.item && @target.item
score -= 30 if user.lastMoveUsed &&
GameData::Move.get(@user.lastMoveUsed).function_code == "0F2" # Trick/Switcheroo
end
#---------------------------------------------------------------------------
when "0F3"
if !@user.item || @target.item
score -= 90
else
if @user.hasActiveItem?([:FLAMEORB,:TOXICORB,:STICKYBARB,:IRONBALL,
:CHOICEBAND,:CHOICESCARF,:CHOICESPECS])
score += 50
else
score -= 80
end
end
#---------------------------------------------------------------------------
when "0F4", "0F5"
if @target.effects[PBEffects::Substitute]==0
if skill_check(AILevel.high) && @target.item && @target.item.is_berry?
score += 30
end
end
#---------------------------------------------------------------------------
when "0F6"
if !@user.recycleItem || @user.item
score -= 80
elsif @user.recycleItem
score += 30
end
#---------------------------------------------------------------------------
when "0F7"
if !@user.item || !@user.itemActive? ||
@user.unlosableItem?(@user.item) || @user.item.is_poke_ball?
score -= 90
end
#---------------------------------------------------------------------------
when "0F8"
score -= 90 if @target.effects[PBEffects::Embargo]>0
#---------------------------------------------------------------------------
when "0F9"
if @battle.field.effects[PBEffects::MagicRoom]>0
score -= 90
else
score += 30 if !@user.item && @target.item
end
#---------------------------------------------------------------------------
when "0FA"
score -= 25
#---------------------------------------------------------------------------
when "0FB"
score -= 30
#---------------------------------------------------------------------------
when "0FC"
score -= 40
#---------------------------------------------------------------------------
when "0FD"
score -= 30
if @target.pbCanParalyze?(@user,false)
score += 30
if skill_check(AILevel.medium)
aspeed = pbRoughStat(@user,PBStats::SPEED)
ospeed = pbRoughStat(@target,PBStats::SPEED)
if aspeed<ospeed
score += 30
elsif aspeed>ospeed
score -= 40
end
end
if skill_check(AILevel.high)
score -= 40 if @target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET])
end
end
#---------------------------------------------------------------------------
when "0FE"
score -= 30
if @target.pbCanBurn?(@user,false)
score += 30
if skill_check(AILevel.high)
score -= 40 if @target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET,:FLAREBOOST])
end
end
#---------------------------------------------------------------------------
when "0FF"
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 90
elsif @battle.pbWeather==PBWeather::Sun
score -= 90
else
@user.eachMove do |m|
score += 20 if m.damagingMove? && m.type == :FIRE
end
end
#---------------------------------------------------------------------------
end
return score
end
end

View File

@@ -1,497 +0,0 @@
class PokeBattle_AI
alias __e__pbGetMoveScoreFunctions pbGetMoveScoreFunctions
#=============================================================================
# Get a score for the given move based on its effect
#=============================================================================
def pbGetMoveScoreFunctions(score)
score = __e__pbGetMoveScoreFunctions(score)
case @move.function
#---------------------------------------------------------------------------
when "100"
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 90
elsif @battle.pbWeather==PBWeather::Rain
score -= 90
else
@user.eachMove do |m|
score += 20 if m.damagingMove? && m.type == :WATER
end
end
#---------------------------------------------------------------------------
when "101"
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 90
elsif @battle.pbWeather==PBWeather::Sandstorm
score -= 90
end
#---------------------------------------------------------------------------
when "102"
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 90
elsif @battle.pbWeather==PBWeather::Hail
score -= 90
end
#---------------------------------------------------------------------------
when "103"
if @user.pbOpposingSide.effects[PBEffects::Spikes]>=3
score -= 90
else
canChoose = false
@user.eachOpposing do |b|
next if !@battle.pbCanChooseNonActive?(b.index)
canChoose = true
break
end
if !canChoose
# Opponent can't switch in any Pokemon
score -= 90
else
score += 10*@battle.pbAbleNonActiveCount(@user.idxOpposingSide)
score += [40,26,13][@user.pbOpposingSide.effects[PBEffects::Spikes]]
end
end
#---------------------------------------------------------------------------
when "104"
if @user.pbOpposingSide.effects[PBEffects::ToxicSpikes]>=2
score -= 90
else
canChoose = false
@user.eachOpposing do |b|
next if !@battle.pbCanChooseNonActive?(b.index)
canChoose = true
break
end
if !canChoose
# Opponent can't switch in any Pokemon
score -= 90
else
score += 8*@battle.pbAbleNonActiveCount(@user.idxOpposingSide)
score += [26,13][@user.pbOpposingSide.effects[PBEffects::ToxicSpikes]]
end
end
#---------------------------------------------------------------------------
when "105"
if @user.pbOpposingSide.effects[PBEffects::StealthRock]
score -= 90
else
canChoose = false
@user.eachOpposing do |b|
next if !@battle.pbCanChooseNonActive?(b.index)
canChoose = true
break
end
if !canChoose
# Opponent can't switch in any Pokemon
score -= 90
else
score += 10*@battle.pbAbleNonActiveCount(@user.idxOpposingSide)
end
end
#---------------------------------------------------------------------------
when "106"
#---------------------------------------------------------------------------
when "107"
#---------------------------------------------------------------------------
when "108"
#---------------------------------------------------------------------------
when "109"
#---------------------------------------------------------------------------
when "10A"
score += 20 if @user.pbOpposingSide.effects[PBEffects::AuroraVeil]>0
score += 20 if @user.pbOpposingSide.effects[PBEffects::Reflect]>0
score += 20 if @user.pbOpposingSide.effects[PBEffects::LightScreen]>0
#---------------------------------------------------------------------------
when "10B"
score += 10*(@user.stages[PBStats::ACCURACY]-@target.stages[PBStats::EVASION])
#---------------------------------------------------------------------------
when "10C"
if @user.effects[PBEffects::Substitute]>0
score -= 90
elsif @user.hp<=@user.totalhp/4
score -= 90
end
#---------------------------------------------------------------------------
when "10D"
if @user.pbHasType?(:GHOST)
if @target.effects[PBEffects::Curse]
score -= 90
elsif @user.hp<=@user.totalhp/2
if @battle.pbAbleNonActiveCount(@user.idxOwnSide)==0
score -= 90
else
score -= 50
score -= 30 if @battle.switchStyle
end
end
else
avg = @user.stages[PBStats::SPEED]*10
avg -= @user.stages[PBStats::ATTACK]*10
avg -= @user.stages[PBStats::DEFENSE]*10
score += avg/3
end
#---------------------------------------------------------------------------
when "10E"
score -= 40
#---------------------------------------------------------------------------
when "10F"
if @target.effects[PBEffects::Nightmare] ||
@target.effects[PBEffects::Substitute]>0
score -= 90
elsif !@target.asleep?
score -= 90
else
score -= 90 if @target.statusCount<=1
score += 50 if @target.statusCount>3
end
#---------------------------------------------------------------------------
when "110"
score += 30 if @user.effects[PBEffects::Trapping]>0
score += 30 if @user.effects[PBEffects::LeechSeed]>=0
if @battle.pbAbleNonActiveCount(@user.idxOwnSide)>0
score += 80 if @user.pbOwnSide.effects[PBEffects::Spikes]>0
score += 80 if @user.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
score += 80 if @user.pbOwnSide.effects[PBEffects::StealthRock]
end
#---------------------------------------------------------------------------
when "111"
if @battle.positions[@target.index].effects[PBEffects::FutureSightCounter]>0
score -= 100
elsif @battle.pbAbleNonActiveCount(@user.idxOwnSide)==0
# Future Sight tends to be wasteful if down to last Pokemon
score -= 70
end
#---------------------------------------------------------------------------
when "112"
avg = 0
avg -= @user.stages[PBStats::DEFENSE]*10
avg -= @user.stages[PBStats::SPDEF]*10
score += avg/2
if @user.effects[PBEffects::Stockpile]>=3
score -= 80
else
# More preferable if user also has Spit Up/Swallow
score += 20 if @user.pbHasMoveFunction?("113","114") # Spit Up, Swallow
end
#---------------------------------------------------------------------------
when "113"
score -= 100 if @user.effects[PBEffects::Stockpile]==0
#---------------------------------------------------------------------------
when "114"
if @user.effects[PBEffects::Stockpile]==0
score -= 90
elsif @user.hp==@user.totalhp
score -= 90
else
mult = [0,25,50,100][@user.effects[PBEffects::Stockpile]]
score += mult
score -= @user.hp*mult*2/@user.totalhp
end
#---------------------------------------------------------------------------
when "115"
score += 50 if @target.effects[PBEffects::HyperBeam]>0
score -= 35 if @target.hp<=@target.totalhp/2 # If target is weak, no
score -= 70 if @target.hp<=@target.totalhp/4 # need to risk this move
#---------------------------------------------------------------------------
when "116"
#---------------------------------------------------------------------------
when "117"
hasAlly = false
@user.eachAlly do |b|
hasAlly = true
break
end
score -= 90 if !hasAlly
#---------------------------------------------------------------------------
when "118"
if @battle.field.effects[PBEffects::Gravity]>0
score -= 90
elsif skill_check(AILevel.medium)
score -= 30
score -= 20 if @user.effects[PBEffects::SkyDrop]>=0
score -= 20 if @user.effects[PBEffects::MagnetRise]>0
score -= 20 if @user.effects[PBEffects::Telekinesis]>0
score -= 20 if @user.pbHasType?(:FLYING)
score -= 20 if @user.hasActiveAbility?(:LEVITATE)
score -= 20 if @user.hasActiveItem?(:AIRBALLOON)
score += 20 if @target.effects[PBEffects::SkyDrop]>=0
score += 20 if @target.effects[PBEffects::MagnetRise]>0
score += 20 if @target.effects[PBEffects::Telekinesis]>0
score += 20 if @target.inTwoTurnAttack?("0C9","0CC","0CE") # Fly, Bounce, Sky Drop
score += 20 if @target.pbHasType?(:FLYING)
score += 20 if @target.hasActiveAbility?(:LEVITATE)
score += 20 if @target.hasActiveItem?(:AIRBALLOON)
end
#---------------------------------------------------------------------------
when "119"
if @user.effects[PBEffects::MagnetRise]>0 ||
@user.effects[PBEffects::Ingrain] ||
@user.effects[PBEffects::SmackDown]
score -= 90
end
#---------------------------------------------------------------------------
when "11A"
if @target.effects[PBEffects::Telekinesis]>0 ||
@target.effects[PBEffects::Ingrain] ||
@target.effects[PBEffects::SmackDown]
score -= 90
end
#---------------------------------------------------------------------------
when "11B"
#---------------------------------------------------------------------------
when "11C"
if skill_check(AILevel.medium)
score += 20 if @target.effects[PBEffects::MagnetRise]>0
score += 20 if @target.effects[PBEffects::Telekinesis]>0
score += 20 if @target.inTwoTurnAttack?("0C9","0CC") # Fly, Bounce
score += 20 if @target.pbHasType?(:FLYING)
score += 20 if @target.hasActiveAbility?(:LEVITATE)
score += 20 if @target.hasActiveItem?(:AIRBALLOON)
end
#---------------------------------------------------------------------------
when "11D"
#---------------------------------------------------------------------------
when "11E"
#---------------------------------------------------------------------------
when "11F"
#---------------------------------------------------------------------------
when "120"
#---------------------------------------------------------------------------
when "121"
#---------------------------------------------------------------------------
when "122"
#---------------------------------------------------------------------------
when "123"
if !@target.pbHasType?(@user.type1) &&
!@target.pbHasType?(@user.type2)
score -= 90
end
#---------------------------------------------------------------------------
when "124"
#---------------------------------------------------------------------------
when "125"
#---------------------------------------------------------------------------
when "126"
score += 20 # Shadow moves are more preferable
#---------------------------------------------------------------------------
when "127"
score += 20 # Shadow moves are more preferable
if @target.pbCanParalyze?(@user,false)
score += 30
if skill_check(AILevel.medium)
aspeed = pbRoughStat(@user,PBStats::SPEED)
ospeed = pbRoughStat(@target,PBStats::SPEED)
if aspeed<ospeed
score += 30
elsif aspeed>ospeed
score -= 40
end
end
if skill_check(AILevel.high)
score -= 40 if @target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET])
end
end
#---------------------------------------------------------------------------
when "128"
score += 20 # Shadow moves are more preferable
if @target.pbCanBurn?(@user,false)
score += 30
if skill_check(AILevel.high)
score -= 40 if @target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET,:FLAREBOOST])
end
end
#---------------------------------------------------------------------------
when "129"
score += 20 # Shadow moves are more preferable
if @target.pbCanFreeze?(@user,false)
score += 30
if skill_check(AILevel.high)
score -= 20 if @target.hasActiveAbility?(:MARVELSCALE)
end
end
#---------------------------------------------------------------------------
when "12A"
score += 20 # Shadow moves are more preferable
if @target.pbCanConfuse?(@user,false)
score += 30
else
if skill_check(AILevel.medium)
score -= 90
end
end
#---------------------------------------------------------------------------
when "12B"
score += 20 # Shadow moves are more preferable
if !@target.pbCanLowerStatStage?(PBStats::DEFENSE,@user)
score -= 90
else
score += 40 if @user.turnCount==0
score += @target.stages[PBStats::DEFENSE]*20
end
#---------------------------------------------------------------------------
when "12C"
score += 20 # Shadow moves are more preferable
if !@target.pbCanLowerStatStage?(PBStats::EVASION,@user)
score -= 90
else
score += @target.stages[PBStats::EVASION]*15
end
#---------------------------------------------------------------------------
when "12D"
score += 20 # Shadow moves are more preferable
#---------------------------------------------------------------------------
when "12E"
score += 20 # Shadow moves are more preferable
score += 20 if @target.hp>=@target.totalhp/2
score -= 20 if @user.hp<@user.hp/2
#---------------------------------------------------------------------------
when "12F"
score += 20 # Shadow moves are more preferable
score -= 110 if @target.effects[PBEffects::MeanLook]>=0
#---------------------------------------------------------------------------
when "130"
score += 20 # Shadow moves are more preferable
score -= 40
#---------------------------------------------------------------------------
when "131"
score += 20 # Shadow moves are more preferable
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
score -= 90
elsif @battle.pbWeather==PBWeather::ShadowSky
score -= 90
end
#---------------------------------------------------------------------------
when "132"
score += 20 # Shadow moves are more preferable
if @target.pbOwnSide.effects[PBEffects::AuroraVeil]>0 ||
@target.pbOwnSide.effects[PBEffects::Reflect]>0 ||
@target.pbOwnSide.effects[PBEffects::LightScreen]>0 ||
@target.pbOwnSide.effects[PBEffects::Safeguard]>0
score += 30
score -= 90 if @user.pbOwnSide.effects[PBEffects::AuroraVeil]>0 ||
@user.pbOwnSide.effects[PBEffects::Reflect]>0 ||
@user.pbOwnSide.effects[PBEffects::LightScreen]>0 ||
@user.pbOwnSide.effects[PBEffects::Safeguard]>0
else
score -= 110
end
#---------------------------------------------------------------------------
when "133", "134"
score -= 95
score = 0 if skill_check(AILevel.high)
#---------------------------------------------------------------------------
when "135"
if @target.pbCanFreeze?(@user,false)
score += 30
if skill_check(AILevel.high)
score -= 20 if @target.hasActiveAbility?(:MARVELSCALE)
end
end
#---------------------------------------------------------------------------
when "136"
score += 20 if @user.stages[PBStats::DEFENSE]<0
#---------------------------------------------------------------------------
when "137"
hasEffect = @user.statStageAtMax?(PBStats::DEFENSE) &&
@user.statStageAtMax?(PBStats::SPDEF)
@user.eachAlly do |b|
next if b.statStageAtMax?(PBStats::DEFENSE) && b.statStageAtMax?(PBStats::SPDEF)
hasEffect = true
score -= b.stages[PBStats::DEFENSE]*10
score -= b.stages[PBStats::SPDEF]*10
end
if hasEffect
score -= @user.stages[PBStats::DEFENSE]*10
score -= @user.stages[PBStats::SPDEF]*10
else
score -= 90
end
#---------------------------------------------------------------------------
when "138"
if @target.statStageAtMax?(PBStats::SPDEF)
score -= 90
else
score -= @target.stages[PBStats::SPDEF]*10
end
#---------------------------------------------------------------------------
when "139"
if !@target.pbCanLowerStatStage?(PBStats::ATTACK,@user)
score -= 90
else
score += @target.stages[PBStats::ATTACK]*20
if skill_check(AILevel.medium)
hasPhysicalAttack = false
@target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill_check(AILevel.high)
score -= 90
end
end
end
#---------------------------------------------------------------------------
when "13A"
avg = @target.stages[PBStats::ATTACK]*10
avg += @target.stages[PBStats::SPATK]*10
score += avg/2
#---------------------------------------------------------------------------
when "13B"
if !@user.isSpecies?(:HOOPA) || @user.form!=1
score -= 100
else
score += 20 if @target.stages[PBStats::DEFENSE]>0
end
#---------------------------------------------------------------------------
when "13C"
score += 20 if @target.stages[PBStats::SPATK]>0
#---------------------------------------------------------------------------
when "13D"
if !@target.pbCanLowerStatStage?(PBStats::SPATK,@user)
score -= 90
else
score += 40 if @user.turnCount==0
score += @target.stages[PBStats::SPATK]*20
end
#---------------------------------------------------------------------------
when "13E"
count = 0
@battle.eachBattler do |b|
if b.pbHasType?(:GRASS) && !b.airborne? &&
(!b.statStageAtMax?(PBStats::ATTACK) || !b.statStageAtMax?(PBStats::SPATK))
count += 1
if @user.opposes?(b)
score -= 20
else
score -= @user.stages[PBStats::ATTACK]*10
score -= @user.stages[PBStats::SPATK]*10
end
end
end
score -= 95 if count==0
#---------------------------------------------------------------------------
when "13F"
count = 0
@battle.eachBattler do |b|
if b.pbHasType?(:GRASS) && !b.statStageAtMax?(PBStats::DEFENSE)
count += 1
if @user.opposes?(b)
score -= 20
else
score -= @user.stages[PBStats::DEFENSE]*10
end
end
end
score -= 95 if count==0
#---------------------------------------------------------------------------
end
return score
end
end

View File

@@ -1,409 +0,0 @@
class PokeBattle_AI
alias __f__pbGetMoveScoreFunctions pbGetMoveScoreFunctions
#=============================================================================
# Get a score for the given move based on its effect
#=============================================================================
def pbGetMoveScoreFunctions(score)
score = __f__pbGetMoveScoreFunctions(score)
case @move.function
#---------------------------------------------------------------------------
when "140"
count=0
@battle.eachBattler do |b|
if b.poisoned? &&
(!b.statStageAtMin?(PBStats::ATTACK) ||
!b.statStageAtMin?(PBStats::SPATK) ||
!b.statStageAtMin?(PBStats::SPEED))
count += 1
if @user.opposes?(b)
score += @user.stages[PBStats::ATTACK]*10
score += @user.stages[PBStats::SPATK]*10
score += @user.stages[PBStats::SPEED]*10
else
score -= 20
end
end
end
score -= 95 if count==0
#---------------------------------------------------------------------------
when "141"
if @target.effects[PBEffects::Substitute]>0
score -= 90
else
numpos = 0; numneg = 0
PBStats.eachBattleStat do |s|
numpos += @target.stages[s] if @target.stages[s]>0
numneg += @target.stages[s] if @target.stages[s]<0
end
if numpos!=0 || numneg!=0
score += (numpos-numneg)*10
else
score -= 95
end
end
#---------------------------------------------------------------------------
when "142"
score -= 90 if @target.pbHasType?(:GHOST)
#---------------------------------------------------------------------------
when "143"
score -= 90 if @target.pbHasType?(:GRASS)
#---------------------------------------------------------------------------
when "144"
#---------------------------------------------------------------------------
when "145"
aspeed = pbRoughStat(@user,PBStats::SPEED)
ospeed = pbRoughStat(@target,PBStats::SPEED)
score -= 90 if aspeed>ospeed
#---------------------------------------------------------------------------
when "146"
#---------------------------------------------------------------------------
when "147"
#---------------------------------------------------------------------------
when "148"
aspeed = pbRoughStat(@user,PBStats::SPEED)
ospeed = pbRoughStat(@target,PBStats::SPEED)
if aspeed>ospeed
score -= 90
else
score += 30 if @target.pbHasMoveType?(:FIRE)
end
#---------------------------------------------------------------------------
when "149"
if @user.turnCount==0
score += 30
else
score -= 90 # Because it will fail here
score = 0 if skill_check(AILevel.best)
end
#---------------------------------------------------------------------------
when "14A"
#---------------------------------------------------------------------------
when "14B", "14C"
if @user.effects[PBEffects::ProtectRate]>1 ||
@target.effects[PBEffects::HyperBeam]>0
score -= 90
else
if skill_check(AILevel.medium)
score -= @user.effects[PBEffects::ProtectRate]*40
end
score += 50 if @user.turnCount==0
score += 30 if @target.effects[PBEffects::TwoTurnAttack]
end
#---------------------------------------------------------------------------
when "14D"
#---------------------------------------------------------------------------
when "14E"
if @user.statStageAtMax?(PBStats::SPATK) &&
@user.statStageAtMax?(PBStats::SPDEF) &&
@user.statStageAtMax?(PBStats::SPEED)
score -= 90
else
score -= @user.stages[PBStats::SPATK]*10 # Only *10 isntead of *20
score -= @user.stages[PBStats::SPDEF]*10 # because two-turn attack
score -= @user.stages[PBStats::SPEED]*10
if skill_check(AILevel.medium)
hasSpecialAttack = false
@user.eachMove do |m|
next if !m.specialMove?(m.type)
hasSpecialAttack = true
break
end
if hasSpecialAttack
score += 20
elsif skill_check(AILevel.high)
score -= 90
end
end
if skill_check(AILevel.high)
aspeed = pbRoughStat(@user,PBStats::SPEED)
ospeed = pbRoughStat(@target,PBStats::SPEED)
score += 30 if aspeed<ospeed && aspeed*2>ospeed
end
end
#---------------------------------------------------------------------------
when "14F"
if skill_check(AILevel.high) && @target.hasActiveAbility?(:LIQUIDOOZE)
score -= 80
else
score += 40 if @user.hp<=@user.totalhp/2
end
#---------------------------------------------------------------------------
when "150"
score += 20 if !@user.statStageAtMax?(PBStats::ATTACK) && @target.hp<=@target.totalhp/4
#---------------------------------------------------------------------------
when "151"
avg = @target.stages[PBStats::ATTACK]*10
avg += @target.stages[PBStats::SPATK]*10
score += avg/2
#---------------------------------------------------------------------------
when "152"
#---------------------------------------------------------------------------
when "153"
score -= 95 if @target.pbOwnSide.effects[PBEffects::StickyWeb]
#---------------------------------------------------------------------------
when "154"
#---------------------------------------------------------------------------
when "155"
#---------------------------------------------------------------------------
when "156"
#---------------------------------------------------------------------------
when "157"
score -= 90
#---------------------------------------------------------------------------
when "158"
score -= 90 if !@user.belched?
#---------------------------------------------------------------------------
when "159"
if !@target.pbCanPoison?(@user,false) && !@target.pbCanLowerStatStage?(PBStats::SPEED,@user)
score -= 90
else
if @target.pbCanPoison?(@user,false)
score += 30
if skill_check(AILevel.medium)
score += 30 if @target.hp<=@target.totalhp/4
score += 50 if @target.hp<=@target.totalhp/8
score -= 40 if @target.effects[PBEffects::Yawn]>0
end
if skill_check(AILevel.high)
score += 10 if pbRoughStat(@target,PBStats::DEFENSE)>100
score += 10 if pbRoughStat(@target,PBStats::SPDEF)>100
score -= 40 if @target.hasActiveAbility?([:GUTS,:MARVELSCALE,:TOXICBOOST])
end
end
if @target.pbCanLowerStatStage?(PBStats::SPEED,@user)
score += @target.stages[PBStats::SPEED]*10
if skill_check(AILevel.high)
aspeed = pbRoughStat(@user,PBStats::SPEED)
ospeed = pbRoughStat(@target,PBStats::SPEED)
score += 30 if aspeed<ospeed && aspeed*2>ospeed
end
end
end
#---------------------------------------------------------------------------
when "15A"
if @target.opposes?(@user)
score -= 40 if @target.status==PBStatuses::BURN
else
score += 40 if @target.status==PBStatuses::BURN
end
#---------------------------------------------------------------------------
when "15B"
if @target.status==PBStatuses::NONE
score -= 90
elsif @user.hp==@user.totalhp && @target.opposes?(@user)
score -= 90
else
score += (@user.totalhp-@user.hp)*50/@user.totalhp
score -= 30 if @target.opposes?(@user)
end
#---------------------------------------------------------------------------
when "15C"
hasEffect = @user.statStageAtMax?(PBStats::ATTACK) &&
@user.statStageAtMax?(PBStats::SPATK)
@user.eachAlly do |b|
next if b.statStageAtMax?(PBStats::ATTACK) && b.statStageAtMax?(PBStats::SPATK)
hasEffect = true
score -= b.stages[PBStats::ATTACK]*10
score -= b.stages[PBStats::SPATK]*10
end
if hasEffect
score -= @user.stages[PBStats::ATTACK]*10
score -= @user.stages[PBStats::SPATK]*10
else
score -= 90
end
#---------------------------------------------------------------------------
when "15D"
numStages = 0
PBStats.eachBattleStat do |s|
next if @target.stages[s]<=0
numStages += @target.stages[s]
end
score += numStages*20
#---------------------------------------------------------------------------
when "15E"
if @user.effects[PBEffects::LaserFocus]>0
score -= 90
else
score += 40
end
#---------------------------------------------------------------------------
when "15F"
score += @user.stages[PBStats::DEFENSE]*10
#---------------------------------------------------------------------------
when "160"
if @target.statStageAtMin?(PBStats::ATTACK)
score -= 90
else
if @target.pbCanLowerStatStage?(PBStats::ATTACK,@user)
score += @target.stages[PBStats::ATTACK]*20
if skill_check(AILevel.medium)
hasPhysicalAttack = false
@target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
if hasPhysicalAttack
score += 20
elsif skill_check(AILevel.high)
score -= 90
end
end
end
score += (@user.totalhp-@user.hp)*50/@user.totalhp
end
#---------------------------------------------------------------------------
when "161"
if skill_check(AILevel.medium)
if @user.speed>@target.speed
score += 50
else
score -= 70
end
end
#---------------------------------------------------------------------------
when "162"
score -= 90 if !@user.pbHasType?(:FIRE)
#---------------------------------------------------------------------------
when "163"
#---------------------------------------------------------------------------
when "164"
#---------------------------------------------------------------------------
when "165"
if skill_check(AILevel.medium)
userSpeed = pbRoughStat(@user,PBStats::SPEED)
targetSpeed = pbRoughStat(@target,PBStats::SPEED)
if userSpeed<targetSpeed
score += 30
end
else
score += 30
end
#---------------------------------------------------------------------------
when "166"
#---------------------------------------------------------------------------
when "167"
if @user.pbOwnSide.effects[PBEffects::AuroraVeil]>0 || @battle.pbWeather!=PBWeather::Hail
score -= 90
else
score += 40
end
#---------------------------------------------------------------------------
when "168"
if @user.effects[PBEffects::ProtectRate]>1 ||
@target.effects[PBEffects::HyperBeam]>0
score -= 90
else
if skill_check(AILevel.medium)
score -= @user.effects[PBEffects::ProtectRate]*40
end
score += 50 if @user.turnCount==0
score += 30 if @target.effects[PBEffects::TwoTurnAttack]
score += 20 # Because of possible poisoning
end
#---------------------------------------------------------------------------
when "169"
#---------------------------------------------------------------------------
when "16A"
hasAlly = false
@target.eachAlly do |b|
hasAlly = true
break
end
score -= 90 if !hasAlly
#---------------------------------------------------------------------------
when "16B"
if skill_check(AILevel.medium)
if !@target.lastRegularMoveUsed ||
!@target.pbHasMove?(@target.lastRegularMoveUsed) ||
@target.usingMultiTurnAttack?
score -= 90
else
# Without lots of code here to determine good/bad moves and relative
# speeds, using this move is likely to just be a waste of a turn
score -= 50
end
end
#---------------------------------------------------------------------------
when "16C"
if @target.effects[PBEffects::ThroatChop]==0 && skill_check(AILevel.high)
hasSoundMove = false
@user.eachMove do |m|
next if !m.soundMove?
hasSoundMove = true
break
end
score += 40 if hasSoundMove
end
#---------------------------------------------------------------------------
when "16D"
if @user.hp==@user.totalhp || (skill_check(AILevel.medium) && !@user.canHeal?)
score -= 90
else
score += 50
score -= @user.hp*100/@user.totalhp
score += 30 if @battle.pbWeather==PBWeather::Sandstorm
end
#---------------------------------------------------------------------------
when "16E"
if @user.hp==@user.totalhp || (skill_check(AILevel.medium) && !@user.canHeal?)
score -= 90
else
score += 50
score -= @user.hp*100/@user.totalhp
if skill_check(AILevel.medium)
score += 30 if @battle.field.terrain==PBBattleTerrains::Grassy
end
end
#---------------------------------------------------------------------------
when "16F"
if !@target.opposes?(@user)
if @target.hp==@target.totalhp || (skill_check(AILevel.medium) && !@target.canHeal?)
score -= 90
else
score += 50
score -= @target.hp*100/@target.totalhp
end
end
#---------------------------------------------------------------------------
when "170"
reserves = @battle.pbAbleNonActiveCount(@user.idxOwnSide)
foes = @battle.pbAbleNonActiveCount(@user.idxOpposingSide)
if @battle.pbCheckGlobalAbility(:DAMP)
score -= 100
elsif skill_check(AILevel.medium) && reserves==0 && foes>0
score -= 100 # don't want to lose
elsif skill_check(AILevel.high) && reserves==0 && foes==0
score += 80 # want to draw
else
score -= (@user.total.hp-@user.hp)*75/@user.totalhp
end
#---------------------------------------------------------------------------
when "171"
if skill_check(AILevel.medium)
hasPhysicalAttack = false
@target.eachMove do |m|
next if !m.physicalMove?(m.type)
hasPhysicalAttack = true
break
end
score -= 80 if !hasPhysicalAttack
end
#---------------------------------------------------------------------------
when "172"
score += 20 # Because of possible burning
#---------------------------------------------------------------------------
when "173"
#---------------------------------------------------------------------------
when "174"
score -= 90 if @user.turnCount>0 || @user.lastRoundMoved>=0
#---------------------------------------------------------------------------
when "175"
score += 30 if @target.effects[PBEffects::Minimize]
#---------------------------------------------------------------------------
end
return score
end
end

View File

@@ -1,725 +0,0 @@
class PokeBattle_AI
#=============================================================================
#
#=============================================================================
def pbTargetsMultiple?(move)
numTargets = 0
case move.pbTarget(@user)
when PBTargets::AllNearFoes
@battle.eachOtherSideBattler(@user) { |b| numTargets += 1 if b.near?(@user) }
return numTargets > 1
when PBTargets::AllNearOthers
@battle.eachBattler { |b| numTargets += 1 if b.near?(@user) }
return numTargets > 1
when PBTargets::UserAndAllies
@battle.eachSameSideBattler(@user) { |_b| numTargets += 1 }
return numTargets > 1
when PBTargets::AllFoes
@battle.eachOtherSideBattler(@user) { |_b| numTargets += 1 }
return numTargets > 1
when PBTargets::AllBattlers
@battle.eachBattler { |_b| numTargets += 1 }
return numTargets > 1
end
return false
end
#=============================================================================
# Move's type effectiveness
#=============================================================================
def pbCalcTypeModSingle(moveType,defType,user,target)
ret = PBTypes.getEffectiveness(moveType,defType)
# Ring Target
if target.hasActiveItem?(:RINGTARGET)
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if PBTypes.ineffective?(moveType,defType)
end
# Foresight
if user.hasActiveAbility?(:SCRAPPY) || target.effects[PBEffects::Foresight]
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :GHOST &&
PBTypes.ineffective?(moveType,defType)
end
# Miracle Eye
if target.effects[PBEffects::MiracleEye]
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :DARK &&
PBTypes.ineffective?(moveType,defType)
end
# Delta Stream's weather
if @battle.pbWeather==PBWeather::StrongWinds
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :FLYING &&
PBTypes.superEffective?(moveType,defType)
end
# Grounded Flying-type Pokémon become susceptible to Ground moves
if !target.airborne?
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :FLYING && moveType == :GROUND
end
return ret
end
def pbCalcTypeMod(moveType,user,target)
return PBTypeEffectiveness::NORMAL_EFFECTIVE if !moveType
return PBTypeEffectiveness::NORMAL_EFFECTIVE if moveType == :GROUND &&
target.pbHasType?(:FLYING) && target.hasActiveItem?(:IRONBALL)
# Determine types
tTypes = target.pbTypes(true)
# Get effectivenesses
typeMods = [PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE] * 3 # 3 types max
tTypes.each_with_index do |type,i|
typeMods[i] = pbCalcTypeModSingle(moveType,type,user,target)
end
# Multiply all effectivenesses together
ret = 1
typeMods.each { |m| ret *= m }
return ret
end
# For switching. Determines the effectiveness of a potential switch-in against
# an opposing battler.
def pbCalcTypeModPokemon(battlerThis, _battlerOther)
mod1 = PBTypes.getCombinedEffectiveness(battlerThis.type1, target.type1, target.type2)
return mod1 if battlerThis.type1 == battlerThis.type2
mod2 = PBTypes.getCombinedEffectiveness(battlerThis.type2, target.type1, target.type2)
return mod1 * mod2.to_f / PBTypeEffectivenesss::NORMAL_EFFECTIVE
end
#=============================================================================
# Immunity to a move because of the target's ability, item or other effects
#=============================================================================
def pbCheckMoveImmunity(move, target)
# TODO: Add consideration of user's Mold Breaker.
move_type = pbRoughType(move)
typeMod = pbCalcTypeMod(move_type, @user, target)
# Type effectiveness
return true if PBTypeEffectiveness.ineffective?(typeMod)
# Immunity due to ability/item/other effects
if skill_check(AILevel.medium)
case move_type
when :GROUND
# TODO: Split target.airborne? into separate parts to allow different
# skill levels to apply to each part.
return true if target.airborne? && !move.hitsFlyingTargets?
when :FIRE
return true if target.hasActiveAbility?(:FLASHFIRE)
when :WATER
return true if target.hasActiveAbility?([:DRYSKIN, :STORMDRAIN, :WATERABSORB])
when :GRASS
return true if target.hasActiveAbility?(:SAPSIPPER)
when :ELECTRIC
return true if target.hasActiveAbility?([:LIGHTNINGROD, :MOTORDRIVE, :VOLTABSORB])
end
return true if PBTypeEffectiveness.notVeryEffective?(typeMod) &&
target.hasActiveAbility?(:WONDERGUARD)
return true if move.damagingMove? && @user.index != target.index && !target.opposes?(@user) &&
target.hasActiveAbility?(:TELEPATHY)
return true if move.canMagicCoat? && target.hasActiveAbility?(:MAGICBOUNCE) &&
target.opposes?(@user)
return true if move.soundMove? && target.hasActiveAbility?(:SOUNDPROOF)
return true if move.bombMove? && target.hasActiveAbility?(:BULLETPROOF)
if move.powderMove?
return true if target.pbHasType?(:GRASS)
return true if skill_check(AILevel.best) && target.hasActiveAbility?(:OVERCOAT)
return true if skill_check(AILevel.high) && target.hasActiveItem?(:SAFETYGOGGLES)
end
return true if target.effects[PBEffects::Substitute] > 0 && move.statusMove? &&
!move.ignoresSubstitute?(@user) && @user.index != target.index
return true if NEWEST_BATTLE_MECHANICS && @user.hasActiveAbility?(:PRANKSTER) &&
target.pbHasType?(:DARK) && target.opposes?(@user)
return true if move.priority>0 && @battle.field.terrain == PBBattleTerrains::Psychic &&
target.affectedByTerrain? && target.opposes?(@user)
# TODO: Dazzling/Queenly Majesty go here.
end
return false
end
#=============================================================================
# Get approximate properties for a battler
#=============================================================================
def pbRoughType(move)
ret = move.type
if skill_check(AILevel.high)
ret = move.pbCalcType(@user)
end
return ret
end
def pbRoughStat(battler,stat)
return battler.pbSpeed if skill_check(AILevel.high) && stat==PBStats::SPEED
stageMul = [2,2,2,2,2,2, 2, 3,4,5,6,7,8]
stageDiv = [8,7,6,5,4,3, 2, 2,2,2,2,2,2]
stage = battler.stages[stat]+6
value = 0
case stat
when PBStats::ATTACK then value = battler.attack
when PBStats::DEFENSE then value = battler.defense
when PBStats::SPATK then value = battler.spatk
when PBStats::SPDEF then value = battler.spdef
when PBStats::SPEED then value = battler.speed
end
return (value.to_f * stageMul[stage] / stageDiv[stage]).floor
end
#=============================================================================
# Get a better move's base damage value
#=============================================================================
def pbMoveBaseDamage(move, target)
baseDmg = move.baseDamage
baseDmg = 60 if baseDmg == 1
return baseDmg if !skill_check(AILevel.medium)
# Covers all function codes which have their own def pbBaseDamage
case move.function
when "010" # Stomp
baseDmg *= 2 if target.effects[PBEffects::Minimize]
# Sonic Boom, Dragon Rage, Super Fang, Night Shade, Endeavor
when "06A", "06B", "06C", "06D", "06E"
baseDmg = move.pbFixedDamage(@user, target)
when "06F" # Psywave
baseDmg = @user.level
when "070" # OHKO
baseDmg = target.totalhp
when "071", "072", "073" # Counter, Mirror Coat, Metal Burst
# TODO: Check memory to find the move that did the most damage, and use
# that value (if this move counters it, applying this move's
# doubling effect if appropriate).
baseDmg = 60
when "075", "076", "0D0", "12D" # Surf, Earthquake, Whirlpool, Shadow Storm
baseDmg = move.pbModifyDamage(baseDmg, @user, target)
# Bulldoze, Gust, Twister, Venoshock, Smelling Salts, Wake-Up Slap, Facade,
# Hex, Brine, Retaliate, Weather Ball, Return, Frustration, Eruption,
# Crush Grip, Stored Power, Punishment, Flail, Electro Ball, Low Kick,
# Knock Off, Spit Up, Stomping Tantrum
when "044", "077", "078", "07B", "07C", "07D", "07E", "07F", "080", "085",
"087", "089", "08A", "08B", "08C", "08E", "08F", "098", "099", "09A",
"0F0", "113", "166"
baseDmg = move.pbBaseDamage(baseDmg, @user, target)
when "086" # Acrobatics
baseDmg *= 2 if !@user.item || @user.hasActiveItem?(:FLYINGGEM)
when "08D" # Gyro Ball
target_speed = pbRoughStat(target, PBStats::SPEED)
user_speed = pbRoughStat(@user, PBStats::SPEED)
baseDmg = [[(25 * target_speed / user_speed).floor, 150].min, 1].max
when "091" # Fury Cutter
baseDmg = move.pbBaseDamage(baseDmg, @user, target)
baseDmg *= 2 if baseDmg < 160 && @user.effects[PBEffects::FuryCutter] > 0
when "092" # Echoed Voice
factor = @user.pbOwnSide.effects[PBEffects::EchoedVoiceCounter]
baseDmg *= [(factor + 1), 5].min
when "094" # Present
baseDmg = 50
when "095" # Magnitude
baseDmg = 71
baseDmg *= 2 if target.inTwoTurnAttack?("0CA") # Dig
baseDmg /= 2 if @battle.field.terrain == PBBattleTerrains::Grassy
when "096" # Natural Gift
baseDmg = 0 if !@user.item || !@user.item.is_berry? || !@user.itemActive?
baseDmg = move.pbNaturalGiftBaseDamage(@user.item_id) if baseDmg > 0
when "097" # Trump Card
dmgs = [200, 80, 60, 50, 40]
pp_left = [[move.pp - 1, dmgs.length - 1].min, 0].max
return dmgs[pp_left]
when "09B" # Heavy Slam
baseDmg = move.pbBaseDamage(baseDmg, @user, target)
baseDmg *= 2 if NEWEST_BATTLE_MECHANICS && target.effects[PBEffects::Minimize]
when "0BD", "0BE" # Double Kick, Twineedle
baseDmg *= 2
when "0BF" # Triple Kick
baseDmg *= 6 # Hits do x1, x2, x3 baseDmg in turn, for x6 in total
when "0C0" # Fury Attack
if @user.hasActiveAbility?(:SKILLLINK)
baseDmg *= 5
else
baseDmg = (baseDmg * 19 / 6).floor # Average damage dealt
end
when "0C1" # Beat Up
mult = 0
@battle.eachInTeamFromBattlerIndex(@user.index) do |pkmn, _i|
mult += 1 if pkmn && pkmn.able? && pkmn.status == PBStatuses::NONE
end
baseDmg *= mult
when "0C4" # Solar Beam
baseDmg = move.pbBaseDamageMultiplier(baseDmg, @user, target)
when "0D3" # Rollout
baseDmg *= 2 if @user.effects[PBEffects::DefenseCurl]
when "0D4" # Bide
# TODO: Maybe make this equal to the highest damage a foe has dealt?
baseDmg = 40
when "0E1" # Final Gambit
baseDmg = @user.hp
when "0F7" # Fling
if !@user.item || !@user.itemActive? || @user.unlosableItem?(@user.item) ||
(@user.item.is_berry? && @battle.pbCheckOpposingAbility(:UNNERVE, @user.index))
baseDmg = 0
else
# TODO: Currently assumes a power of 10 if item is unflingable.
baseDmg = move.pbBaseDamage(baseDmg, @user, target)
end
when "144" # Flying Press
if GameData::Type.exists?(:FLYING)
if skill_check(AILevel.high)
targetTypes = target.pbTypes(true)
mult = PBTypes.getCombinedEffectiveness(:FLYING,
targetTypes[0], targetTypes[1], targetTypes[2])
baseDmg = (baseDmg.to_f * mult / PBTypeEffectiveness::NORMAL_EFFECTIVE).round
else
mult = PBTypes.getCombinedEffectiveness(:FLYING,
target.type1, target.type2, target.effects[PBEffects::Type3])
baseDmg = (baseDmg.to_f * mult / PBTypeEffectiveness::NORMAL_EFFECTIVE).round
end
end
baseDmg *= 2 if target.effects[PBEffects::Minimize]
when "175" # Double Iron Bash
baseDmg *= 2
baseDmg *= 2 if target.effects[PBEffects::Minimize]
end
return baseDmg
end
#=============================================================================
# Damage calculation
#=============================================================================
def pbRoughDamage(move,target,baseDmg)
# Fixed damage moves
return baseDmg if move.is_a?(PokeBattle_FixedDamageMove)
# Get the move's type
type = pbRoughType(move)
##### Calculate user's attack stat #####
atk = pbRoughStat(@user,PBStats::ATTACK)
if move.function=="121" # Foul Play
atk = pbRoughStat(target,PBStats::ATTACK)
elsif move.specialMove?(type)
if move.function=="121" # Foul Play
atk = pbRoughStat(target,PBStats::SPATK)
else
atk = pbRoughStat(@user,PBStats::SPATK)
end
end
##### Calculate target's defense stat #####
defense = pbRoughStat(target,PBStats::DEFENSE)
if move.specialMove?(type) && move.function!="122" # Psyshock
defense = pbRoughStat(target,PBStats::SPDEF)
end
##### Calculate all multiplier effects #####
multipliers = [1.0, 1.0, 1.0, 1.0]
# Ability effects that alter damage
mold_breaker = false
if skill_check(AILevel.high) && @user.hasMoldBreaker?
mold_breaker = true
end
if skill_check(AILevel.medium) && @user.abilityActive?
# NOTE: These abilities aren't suitable for checking at the start of the
# round.
if ![:ANALYTIC, :SNIPER, :TINTEDLENS, :AERILATE, :PIXILATE,
:REFRIGERATE].include?(@user.ability_id)
BattleHandlers.triggerDamageCalcUserAbility(@user.ability,
@user,target,move,multipliers,baseDmg,type)
end
end
if skill_check(AILevel.medium) && !mold_breaker
@user.eachAlly do |b|
next if !b.abilityActive?
BattleHandlers.triggerDamageCalcUserAllyAbility(b.ability,
@user,target,move,multipliers,baseDmg,type)
end
end
if skill_check(AILevel.best) && !mold_breaker && target.abilityActive?
# NOTE: These abilities aren't suitable for checking at the start of the
# round.
if ![:FILTER, :SOLIDROCK].include?(target.ability_id)
BattleHandlers.triggerDamageCalcTargetAbility(target.ability,
@user,target,move,multipliers,baseDmg,type)
end
end
if skill_check(AILevel.best) && !mold_breaker
target.eachAlly do |b|
next if !b.abilityActive?
BattleHandlers.triggerDamageCalcTargetAllyAbility(b.ability,
@user,target,move,multipliers,baseDmg,type)
end
end
# Item effects that alter damage
# NOTE: Type-boosting gems aren't suitable for checking at the start of the
# round.
if skill_check(AILevel.medium) && @user.itemActive?
# NOTE: These items aren't suitable for checking at the start of the
# round.
if ![:EXPERTBELT, :LIFEORB].include?(@user.item_id)
BattleHandlers.triggerDamageCalcUserItem(@user.item,
@user,target,move,multipliers,baseDmg,type)
end
# TODO: Prefer (1.5x?) if item will be consumed and user has Unburden.
end
if skill_check(AILevel.best) && target.itemActive?
# NOTE: Type-weakening berries aren't suitable for checking at the start
# of the round.
if !target.item.is_berry?
BattleHandlers.triggerDamageCalcTargetItem(target.item,
@user,target,move,multipliers,baseDmg,type)
end
end
# Global abilities
if skill_check(AILevel.medium)
if (@battle.pbCheckGlobalAbility(:DARKAURA) && type == :DARK) ||
(@battle.pbCheckGlobalAbility(:FAIRYAURA) && type == :FAIRY)
if @battle.pbCheckGlobalAbility(:AURABREAK)
multipliers[BASE_DMG_MULT] *= 2.0 / 3
else
multipliers[BASE_DMG_MULT] *= 4.0 / 3
end
end
end
# Parental Bond
if skill_check(AILevel.medium) && @user.hasActiveAbility?(:PARENTALBOND)
multipliers[BASE_DMG_MULT] *= 1.25
end
# Me First
# TODO
# Helping Hand - n/a
# Charge
if skill_check(AILevel.medium)
if @user.effects[PBEffects::Charge]>0 && type == :ELECTRIC
multipliers[BASE_DMG_MULT] *= 2
end
end
# Mud Sport and Water Sport
if skill_check(AILevel.medium)
if type == :ELECTRIC
@battle.eachBattler do |b|
next if !b.effects[PBEffects::MudSport]
multipliers[BASE_DMG_MULT] /= 3
break
end
if @battle.field.effects[PBEffects::MudSportField]>0
multipliers[BASE_DMG_MULT] /= 3
end
end
if type == :FIRE
@battle.eachBattler do |b|
next if !b.effects[PBEffects::WaterSport]
multipliers[BASE_DMG_MULT] /= 3
break
end
if @battle.field.effects[PBEffects::WaterSportField]>0
multipliers[BASE_DMG_MULT] /= 3
end
end
end
# Terrain moves
if @user.affectedByTerrain? && skill_check(AILevel.medium)
case @battle.field.terrain
when PBBattleTerrains::Electric
multipliers[BASE_DMG_MULT] *= 1.5 if type == :ELECTRIC
when PBBattleTerrains::Grassy
multipliers[BASE_DMG_MULT] *= 1.5 if type == :GRASS
when PBBattleTerrains::Psychic
multipliers[BASE_DMG_MULT] *= 1.5 if type == :PSYCHIC
end
end
if target.affectedByTerrain? && skill_check(AILevel.medium)
if @battle.field.terrain==PBBattleTerrains::Misty && type == :DRAGON
multipliers[BASE_DMG_MULT] /= 2
end
end
# Badge multipliers
if skill_check(AILevel.high)
if @battle.internalBattle
# Don't need to check the Atk/Sp Atk-boosting badges because the AI
# won't control the player's Pokémon.
if target.pbOwnedByPlayer?
if move.physicalMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_DEFENSE
multipliers[DEF_MULT] *= 1.1
elsif move.specialMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPDEF
multipliers[DEF_MULT] *= 1.1
end
end
end
end
# Multi-targeting attacks
if skill_check(AILevel.high)
if pbTargetsMultiple?(move)
multipliers[FINAL_DMG_MULT] *= 0.75
end
end
# Weather
if skill_check(AILevel.medium)
case @battle.pbWeather
when PBWeather::Sun, PBWeather::HarshSun
if type == :FIRE
multipliers[FINAL_DMG_MULT] *= 1.5
elsif type == :WATER
multipliers[FINAL_DMG_MULT] /= 2
end
when PBWeather::Rain, PBWeather::HeavyRain
if type == :FIRE
multipliers[FINAL_DMG_MULT] /= 2
elsif type == :WATER
multipliers[FINAL_DMG_MULT] *= 1.5
end
when PBWeather::Sandstorm
if target.pbHasType?(:ROCK) && move.specialMove?(type) && move.function!="122" # Psyshock
multipliers[DEF_MULT] *= 1.5
end
end
end
# Critical hits - n/a
# Random variance - n/a
# STAB
if skill_check(AILevel.medium)
if type && @user.pbHasType?(type)
if @user.hasActiveAbility?(:ADAPTABILITY)
multipliers[FINAL_DMG_MULT] *= 2
else
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round
end
end
end
# Type effectiveness
if skill_check(AILevel.medium)
typemod = pbCalcTypeMod(type,@user,target)
multipliers[FINAL_DMG_MULT] *= typemod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE
end
# Burn
if skill_check(AILevel.high)
if @user.status==PBStatuses::BURN && move.physicalMove?(type) &&
!@user.hasActiveAbility?(:GUTS) &&
!(NEWEST_BATTLE_MECHANICS && move.function=="07E") # Facade
multipliers[FINAL_DMG_MULT] /= 2
end
end
# Aurora Veil, Reflect, Light Screen
if skill_check(AILevel.high)
if !move.ignoresReflect? && !@user.hasActiveAbility?(:INFILTRATOR)
if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] *= 2.0 / 3
else
multipliers[FINAL_DMG_MULT] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && move.physicalMove?(type)
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] *= 2.0 / 3
else
multipliers[FINAL_DMG_MULT] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && move.specialMove?(type)
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] *= 2.0 / 3
else
multipliers[FINAL_DMG_MULT] /= 2
end
end
end
end
# Minimize
if skill_check(AILevel.high)
if target.effects[PBEffects::Minimize] && move.tramplesMinimize?(2)
multipliers[FINAL_DMG_MULT] *= 2
end
end
# Move-specific base damage modifiers
# TODO
# Move-specific final damage modifiers
# TODO
##### Main damage calculation #####
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT]).round, 1].max
atk = [(atk * multipliers[ATK_MULT]).round, 1].max
defense = [(defense * multipliers[DEF_MULT]).round, 1].max
damage = (((2.0 * @user.level / 5 + 2).floor * baseDmg * atk / defense).floor / 50).floor + 2
damage = [(damage * multipliers[FINAL_DMG_MULT]).round, 1].max
return damage.floor
end
#=============================================================================
# Critical hit rate calculation
#=============================================================================
def pbRoughCriticalHitStage(move, target)
return -1 if target.pbOwnSide.effects[PBEffects::LuckyChant] > 0
mold_breaker = (skill_check(AILevel.medium) && @user.hasMoldBreaker?)
crit_stage = 0
# Ability effects that alter critical hit rate
if skill_check(AILevel.medium) && @user.abilityActive?
crit_stage = BattleHandlers.triggerCriticalCalcUserAbility(@user.ability, @user, target, crit_stage)
return -1 if crit_stage < 0
end
if skill_check(AILevel.best) && !mold_breaker && target.abilityActive?
crit_stage = BattleHandlers.triggerCriticalCalcTargetAbility(target.ability, @user, target, crit_stage)
return -1 if crit_stage < 0
end
# Item effects that alter critical hit rate
if skill_check(AILevel.medium) && @user.itemActive?
crit_stage = BattleHandlers.triggerCriticalCalcUserItem(@user.item, @user, target, crit_stage)
return -1 if crit_stage < 0
end
if skill_check(AILevel.high) && target.itemActive?
crit_stage = BattleHandlers.triggerCriticalCalcTargetItem(target.item, @user, target, crit_stage)
return -1 if crit_stage < 0
end
# Other effects
case move.pbCritialOverride(@user, target)
when 1 then return 99
when -1 then return -1
end
return 99 if crit_stage > 50 # Merciless
return 99 if @user.effects[PBEffects::LaserFocus] > 0
crit_stage += 1 if move.highCriticalRate?
crit_stage += @user.effects[PBEffects::FocusEnergy]
crit_stage += 1 if @user.inHyperMode? && move.type == :SHADOW
crit_stage = [crit_stage, PokeBattle_Move::CRITICAL_HIT_RATIOS.length - 1].min
return crit_stage
end
#=============================================================================
# Accuracy calculation
#=============================================================================
def pbRoughAccuracy(move, target)
# "Always hit" effects and "always hit" accuracy
if skill_check(AILevel.medium)
return 100 if target.effects[PBEffects::Minimize] && move.tramplesMinimize?(1)
return 100 if target.effects[PBEffects::Telekinesis] > 0
end
# Get base accuracy
baseAcc = move.accuracy
if skill_check(AILevel.medium)
baseAcc = move.pbBaseAccuracy(@user, target)
end
return 100 if baseAcc == 0 && skill_check(AILevel.medium)
# Get the move's type
type = pbRoughType(move)
# Calculate all modifier effects
modifiers = []
modifiers[BASE_ACC] = baseAcc
modifiers[ACC_STAGE] = @user.stages[PBStats::ACCURACY]
modifiers[EVA_STAGE] = target.stages[PBStats::EVASION]
modifiers[ACC_MULT] = 1.0
modifiers[EVA_MULT] = 1.0
pbCalcAccuracyModifiers(target, modifiers, move, type)
# Check if move certainly misses/can't miss
return 0 if modifiers[BASE_ACC] < 0
return 100 if modifiers[BASE_ACC] == 0
# Calculation
accStage = [[modifiers[ACC_STAGE], -6].max, 6].min + 6
evaStage = [[modifiers[EVA_STAGE], -6].max, 6].min + 6
stageMul = [3,3,3,3,3,3, 3, 4,5,6,7,8,9]
stageDiv = [9,8,7,6,5,4, 3, 3,3,3,3,3,3]
accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage]
evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage]
accuracy = (accuracy * modifiers[ACC_MULT]).round
evasion = (evasion * modifiers[EVA_MULT]).round
evasion = 1 if evasion < 1
return modifiers[BASE_ACC] * accuracy / evasion
end
def pbCalcAccuracyModifiers(target,modifiers,move,type)
mold_breaker = false
if skill_check(AILevel.medium) && @user.hasMoldBreaker?
mold_breaker = true
end
# Ability effects that alter accuracy calculation
if skill_check(AILevel.medium)
if @user.abilityActive?
BattleHandlers.triggerAccuracyCalcUserAbility(@user.ability,
modifiers, @user, target, move, type)
end
end
if skill_check(AILevel.high)
@user.eachAlly do |b|
next if !b.abilityActive?
BattleHandlers.triggerAccuracyCalcUserAllyAbility(b.ability,
modifiers, @user, target, move, type)
end
end
if skill_check(AILevel.best)
if target.abilityActive? && !mold_breaker
BattleHandlers.triggerAccuracyCalcTargetAbility(target.ability,
modifiers, @user, target, move, type)
end
end
# Item effects that alter accuracy calculation
if skill_check(AILevel.medium)
if @user.itemActive?
# TODO: Zoom Lens needs to be checked differently (compare speeds of
# user and target).
BattleHandlers.triggerAccuracyCalcUserItem(@user.item,
modifiers, @user, target, move, type)
end
end
if skill_check(AILevel.high)
if target.itemActive?
BattleHandlers.triggerAccuracyCalcTargetItem(target.item,
modifiers, @user, target, move, type)
end
end
# Other effects, inc. ones that set ACC_MULT or EVA_STAGE to specific values
if @battle.field.effects[PBEffects::Gravity] > 0
modifiers[ACC_MULT] *= 5 / 3.0
end
if skill_check(AILevel.medium)
if @user.effects[PBEffects::MicleBerry]
modifiers[ACC_MULT] *= 1.2
end
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::Foresight] && modifiers[EVA_STAGE] > 0
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[EVA_STAGE] > 0
end
# "AI-specific calculations below"
modifiers[EVA_STAGE] = 0 if move.function == "0A9" # Chip Away
modifiers[BASE_ACC] = 0 if ["0A5", "139", "13A", "13B", "13C", # "Always hit"
"147"].include?(move.function)
if skill_check(AILevel.medium)
modifiers[BASE_ACC] = 0 if @user.effects[PBEffects::LockOn] > 0 &&
@user.effects[PBEffects::LockOnPos] == target.index
end
if skill_check(AILevel.medium)
if move.function == "006" # Toxic
modifiers[BASE_ACC] = 0 if NEWEST_BATTLE_MECHANICS && move.statusMove? &&
@user.pbHasType?(:POISON)
elsif move.function == "070" # OHKO moves
modifiers[BASE_ACC] = move.accuracy + @user.level - target.level
modifiers[BASE_ACC] = -1 if modifiers[BASE_ACC] <= 0 # Certain miss
modifiers[ACC_MULT] = 0 if target.level > @user.level
if skill_check(AILevel.best)
modifiers[ACC_MULT] = 0 if target.hasActiveAbility?(:STURDY) && !mold_breaker
end
end
end
end
#=============================================================================
# Check if battler has a move that meets the criteria in the block provided
#=============================================================================
def check_for_move(battler)
ret = false
battler.eachMove do |move|
next unless yield move
ret = true
break
end
return ret
end
end

View File

@@ -1,165 +0,0 @@
class PokeBattle_AI
#=============================================================================
#
#=============================================================================
# TODO: Reborn has the REVENGEKILLER role which compares mon's speed with
# opponent (only when deciding whether to switch mon in) - this
# comparison should be calculated when needed instead of being a role.
module BattleRole
PHAZER = 0
CLERIC = 1
STALLBREAKER = 2
STATUSABSORBER = 3
BATONPASSER = 4
SPINNER = 5
FIELDSETTER = 6
WEATHERSETTER = 7
SWEEPER = 8
PIVOT = 9
PHYSICALWALL = 10
SPECIALWALL = 11
TANK = 12
TRAPPER = 13
SCREENER = 14
ACE = 15
LEAD = 16
SECOND = 17
end
#=============================================================================
# Determine the roles filled by a Pokémon on a given side at a given party
# index.
#=============================================================================
def determine_roles(side, index)
pkmn = @battle.pbParty(side)[index]
ret = []
return ret if !pkmn || pkmn.egg?
# Check for moves indicative of particular roles
hasHealMove = false
hasPivotMove = false
pkmn.moves.each do |m|
next if !m
move = PokeBattle_Move.pbFromPBMove(@battle, m)
hasHealMove = true if !hasHealMove && move.healingMove?
case move.function
when "004", "0E5", "0EB", "0EC" # Yawn, Perish Song, Roar, Circle Throw
ret.push(BattleRole::PHAZER)
when "019" # Aromatherapy/Heal Bell
ret.push(BattleRole::CLERIC)
when "0BA" # Taunt
ret.push(BattleRole::STALLBREAKER)
when "0D7" # Wish
ret.push(BattleRole::CLERIC) if pkmn.ev[PBStats::HP] == PokeBattle_Pokemon::EV_STAT_LIMIT
when "0D9" # Rest
ret.push(BattleRole::STATUSABSORBER)
when "0ED" # Baton Pass
ret.push(BattleRole::BATONPASSER)
when "0EE" # U-turn
hasPivotMove = true
when "110" # Rapid Spin
ret.push(BattleRole::SPINNER)
when "154", "155", "156", "173" # Terrain moves
ret.push(BattleRole::FIELDSETTER)
else
ret.push(BattleRole::WEATHERSETTER) if move.is_a?(PokeBattle_WeatherMove)
end
end
# Check EVs, nature and moves for combinations indicative of particular roles
if pkmn.ev[PBStats::SPEED] == PokeBattle_Pokemon::EV_STAT_LIMIT
if [PBNatures::MODEST, PBNatures::ADAMANT, # SpAtk+ Atk-, Atk+ SpAtk-
PBNatures::TIMID, PBNatures::JOLLY].include?(pkmn.nature) # Spd+ Atk-, Spd+ SpAtk-
ret.push(BattleRole::SWEEPER)
end
end
if hasHealMove
ret.push(BattleRole::PIVOT) if hasPivotMove
if PBNatures.getStatRaised(pkmn.nature) == PBStats::DEFENSE &&
PBNatures.getStatLowered(pkmn.nature) != PBStats::DEFENSE
ret.push(BattleRole::PHYSICALWALL) if pkmn.ev[PBStats::DEFENSE] == PokeBattle_Pokemon::EV_STAT_LIMIT
elsif PBNatures.getStatRaised(pkmn.nature) == PBStats::SPDEF &&
PBNatures.getStatLowered(pkmn.nature) != PBStats::SPDEF
ret.push(BattleRole::SPECIALWALL) if pkmn.ev[PBStats::SPDEF] == PokeBattle_Pokemon::EV_STAT_LIMIT
end
else
ret.push(BattleRole::TANK) if pkmn.ev[PBStats::HP] == PokeBattle_Pokemon::EV_STAT_LIMIT
end
# Check for abilities indicative of particular roles
case pkmn.ability_id
when :REGENERATOR
ret.push(BattleRole::PIVOT)
when :GUTS, :QUICKFEET, :FLAREBOOST, :TOXICBOOST, :NATURALCURE, :MAGICGUARD,
:MAGICBOUNCE, :HYDRATION
ret.push(BattleRole::STATUSABSORBER)
when :SHADOWTAG, :ARENATRAP, :MAGNETPULL
ret.push(BattleRole::TRAPPER)
when :DROUGHT, :DRIZZLE, :SANDSTREAM, :SNOWWARNING, :PRIMORDIALSEA,
:DESOLATELAND, :DELTASTREAM
ret.push(BattleRole::WEATHERSETTER)
when :GRASSYSURGE, :ELECTRICSURGE, :MISTYSURGE, :PSYCHICSURGE
ret.push(BattleRole::FIELDSETTER)
end
# Check for items indicative of particular roles
case pkmn.item_id
when :LIGHTCLAY
ret.push(BattleRole::SCREENER)
when :ASSAULTVEST
ret.push(BattleRole::TANK)
when :CHOICEBAND, :CHOICESPECS
ret.push(BattleRole::STALLBREAKER)
ret.push(BattleRole::SWEEPER) if pkmn.ev[PBStats::SPEED] == PokeBattle_Pokemon::EV_STAT_LIMIT
when :CHOICESCARF
ret.push(BattleRole::SWEEPER) if pkmn.ev[PBStats::SPEED] == PokeBattle_Pokemon::EV_STAT_LIMIT
when :TOXICORB, :FLAMEORB
ret.push(BattleRole::STATUSABSORBER)
when :TERRAINEXTENDER
ret.push(BattleRole::FIELDSETTER)
end
# Check for position in team, level relative to other levels in team
partyStarts = @battle.pbPartyStarts(side)
if partyStarts.include?(index + 1) || index == @battle.pbParty(side).length - 1
ret.push(BattleRole::ACE)
else
ret.push(BattleRole::LEAD) if partyStarts.include?(index)
idxTrainer = @battle.pbGetOwnerIndexFromPartyIndex(side, index)
maxLevel = @battle.pbMaxLevelInTeam(side, idxTrainer)
if pkmn.level >= maxLevel
ret.push(BattleRole::SECOND)
else
secondHighest = true
seenHigherLevel = false
@battle.eachInTeam(side, @battle.pbGetOwnerIndexFromPartyIndex(side, index)).each do |p|
next if p.level < pkmn.level
if seenHigherLevel
secondHighest = false
break
end
seenHigherLevel = true
end
# NOTE: There can be multiple "second"s if all their levels are equal
# and the highest in the team (and none are the ace).
ret.push(BattleRole::SECOND) if secondHighest
end
end
return ret
end
def check_role(side, idxBattler, *roles)
role_array = @roles[side][idxBattler]
roles.each do |r|
return true if role_array.include?(r)
end
return false
end
def check_battler_role(battler, *roles)
side = idxParty.idxOwnSide
idxParty = idxParty.pokemonIndex
return check_role(side, idxParty, *roles)
end
end

View File

@@ -1,86 +0,0 @@
class PokeBattle_StatUpMove < PokeBattle_Move
attr_reader :statUp
end
class PokeBattle_MultiStatUpMove < PokeBattle_Move
attr_reader :statUp
end
#===============================================================================
# Battle Palace AI.
#===============================================================================
class PokeBattle_AI
alias _battlePalace_pbEnemyShouldWithdraw? pbEnemyShouldWithdraw?
def pbEnemyShouldWithdraw?
return _battlePalace_pbEnemyShouldWithdraw? if !@battlePalace
shouldswitch = false
if @user.effects[PBEffects::PerishSong]==1
shouldswitch = true
elsif !@battle.pbCanChooseAnyMove?(@user.index) &&
@user.turnCount && @user.turnCount>5
shouldswitch = true
else
hppercent = @user.hp*100/@user.totalhp
percents = []
maxindex = -1
maxpercent = 0
factor = 0
@battle.pbParty(@user.index).each_with_index do |pkmn,i|
if @battle.pbCanSwitch?(@user.index,i)
percents[i] = 100*pkmn.hp/pkmn.totalhp
if percents[i]>maxpercent
maxindex = i
maxpercent = percents[i]
end
else
percents[i] = 0
end
end
if hppercent<50
factor = (maxpercent<hppercent) ? 20 : 40
end
if hppercent<25
factor = (maxpercent<hppercent) ? 30 : 50
end
case @user.status
when PBStatuses::SLEEP, PBStatuses::FROZEN
factor += 20
when PBStatuses::POISON, PBStatuses::BURN
factor += 10
when PBStatuses::PARALYSIS
factor += 15
end
if @justswitched[@user.index]
factor -= 60
factor = 0 if factor<0
end
shouldswitch = (pbAIRandom(100)<factor)
if shouldswitch && maxindex>=0
@battle.pbRegisterSwitch(@user.index,maxindex)
return true
end
end
@justswitched[@user.index] = shouldswitch
if shouldswitch
@battle.pbParty(@user.index).each_with_index do |_pkmn,i|
next if !@battle.pbCanSwitch?(@user.index,i)
@battle.pbRegisterSwitch(@user.index,i)
return true
end
end
return false
end
end
#===============================================================================
# Battle Arena AI.
#===============================================================================
class PokeBattle_AI
alias _battleArena_pbEnemyShouldWithdraw? pbEnemyShouldWithdraw?
def pbEnemyShouldWithdraw?
return _battleArena_pbEnemyShouldWithdraw? if !@battleArena
return false
end
end

View File

@@ -1,110 +0,0 @@
=begin
class PBStuff
#Standardized lists of moves with similar purposes/characteristics
#(mostly just "stuff that gets called together")
UNFREEZEMOVE = [PBMoves::FLAMEWHEEL,PBMoves::SACREDFIRE,PBMoves::FLAREBLITZ,
PBMoves::FUSIONFLARE,PBMoves::SCALD,PBMoves::STEAMERUPTION,PBMoves::BURNUP]
SWITCHOUTMOVE = [PBMoves::ROAR,PBMoves::WHIRLWIND,PBMoves::CIRCLETHROW,
PBMoves::DRAGONTAIL,PBMoves::YAWN,PBMoves::PERISHSONG]
SETUPMOVE = [PBMoves::SWORDSDANCE,PBMoves::DRAGONDANCE,PBMoves::CALMMIND,
PBMoves::WORKUP,PBMoves::NASTYPLOT,PBMoves::TAILGLOW,PBMoves::BELLYDRUM,
PBMoves::BULKUP,PBMoves::COIL,PBMoves::CURSE,PBMoves::GROWTH,
PBMoves::HONECLAWS,PBMoves::QUIVERDANCE,PBMoves::SHELLSMASH]
PROTECTMOVE = [PBMoves::PROTECT,PBMoves::DETECT,PBMoves::KINGSSHIELD,
PBMoves::SPIKYSHIELD,PBMoves::BANEFULBUNKER]
PROTECTIGNORINGMOVE = [PBMoves::FEINT,PBMoves::HYPERSPACEHOLE,
PBMoves::HYPERSPACEFURY,PBMoves::SHADOWFORCE,PBMoves::PHANTOMFORCE]
SCREENBREAKERMOVE = [PBMoves::DEFOG,PBMoves::BRICKBREAK,PBMoves::PSYCHICFANGS]
CONTRARYBAITMOVE = [PBMoves::SUPERPOWER,PBMoves::OVERHEAT,PBMoves::DRACOMETEOR,
PBMoves::LEAFSTORM,PBMoves::FLEURCANNON,PBMoves::PSYCHOBOOST]
TWOTURNAIRMOVE = [PBMoves::BOUNCE,PBMoves::FLY,PBMoves::SKYDROP]
PIVOTMOVE = [PBMoves::UTURN,PBMoves::VOLTSWITCH,PBMoves::PARTINGSHOT]
DANCEMOVE = [PBMoves::QUIVERDANCE,PBMoves::DRAGONDANCE,PBMoves::FIERYDANCE,
PBMoves::FEATHERDANCE,PBMoves::PETALDANCE,PBMoves::SWORDSDANCE,
PBMoves::TEETERDANCE,PBMoves::LUNARDANCE,PBMoves::REVELATIONDANCE]
BULLETMOVE = [PBMoves::ACIDSPRAY,PBMoves::AURASPHERE,PBMoves::BARRAGE,
PBMoves::BULLETSEED,PBMoves::EGGBOMB,PBMoves::ELECTROBALL,PBMoves::ENERGYBALL,
PBMoves::FOCUSBLAST,PBMoves::GYROBALL,PBMoves::ICEBALL,PBMoves::MAGNETBOMB,
PBMoves::MISTBALL,PBMoves::MUDBOMB,PBMoves::OCTAZOOKA,PBMoves::ROCKWRECKER,
PBMoves::SEARINGSHOT,PBMoves::SEEDBOMB,PBMoves::SHADOWBALL,PBMoves::SLUDGEBOMB,
PBMoves::WEATHERBALL,PBMoves::ZAPCANNON,PBMoves::BEAKBLAST]
BURNMOVE = [PBMoves::WILLOWISP,PBMoves::SACREDFIRE,PBMoves::INFERNO]
PARAMOVE = [PBMoves::THUNDERWAVE,PBMoves::STUNSPORE,PBMoves::GLARE,
PBMoves::NUZZLE,PBMoves::ZAPCANNON]
SLEEPMOVE = [PBMoves::SPORE,PBMoves::SLEEPPOWDER,PBMoves::HYPNOSIS,PBMoves::DARKVOID,
PBMoves::GRASSWHISTLE,PBMoves::LOVELYKISS,PBMoves::SING]
POISONMOVE = [PBMoves::TOXIC,PBMoves::POISONPOWDER,PBMoves::POISONGAS,PBMoves::TOXICTHREAD]
CONFUMOVE = [PBMoves::CONFUSERAY,PBMoves::SUPERSONIC,PBMoves::FLATTER,PBMoves::SWAGGER,
PBMoves::SWEETKISS,PBMoves::TEETERDANCE,PBMoves::CHATTER,PBMoves::DYNAMICPUNCH]
HEALFUNCTIONS = [0xD5,0xD6,0xD7,0xD8,0xD9,0xDD,0xDE,0xDF,0xE3,0xE4,0x114,0x139,0x158,0x162,0x169,0x16C,0x172]
#massive arrays of stuff that no one wants to see
NATURALGIFTDAMAGE={
100 => [:WATMELBERRY,:DURINBERRY,:BELUEBERRY,:LIECHIBERRY,:GANLONBERRY,:SALACBERRY,
:PETAYABERRY,:APICOTBERRY,:LANSATBERRY,:STARFBERRY,:ENIGMABERRY,:MICLEBERRY,
:CUSTAPBERRY,:JABOCABERRY,:ROWAPBERRY],
90 => [:BLUKBERRY,:NANABBERRY,:WEPEARBERRY,:PINAPBERRY,:POMEGBERRY,:KELPSYBERRY,
:QUALOTBERRY,:HONDEWBERRY,:GREPABERRY,:TAMATOBERRY,:CORNNBERRY,:MAGOSTBERRY,
:RABUTABERRY,:NOMELBERRY,:SPELONBERRY,:PAMTREBERRY],
80 => [:CHERIBERRY,:CHESTOBERRY,:PECHABERRY,:RAWSTBERRY,:ASPEARBERRY,:LEPPABERRY,
:ORANBERRY,:PERSIMBERRY,:LUMBERRY,:SITRUSBERRY,:FIGYBERRY,:WIKIBERRY,
:MAGOBERRY,:AGUAVBERRY,:IAPAPABERRY,:RAZZBERRY,:OCCABERRY,:PASSHOBERRY,
:WACANBERRY,:RINDOBERRY,:YACHEBERRY,:CHOPLEBERRY,:KEBIABERRY,:SHUCABERRY,
:COBABERRY,:PAYAPABERRY,:TANGABERRY,:CHARTIBERRY,:KASIBBERRY,:HABANBERRY,
:COLBURBERRY,:BABIRIBERRY,:CHILANBERRY]}
FLINGDAMAGE={
300 => [:MEMEONADE],
130 => [:IRONBALL],
100 => [:ARMORFOSSIL,:CLAWFOSSIL,:COVERFOSSIL,:DOMEFOSSIL,:HARDSTONE,:HELIXFOSSIL,
:OLDAMBER,:PLUMEFOSSIL,:RAREBONE,:ROOTFOSSIL,:SKULLFOSSIL],
90 => [:DEEPSEATOOTH,:DRACOPLATE,:DREADPLATE,:EARTHPLATE,:FISTPLATE,:FLAMEPLATE,
:GRIPCLAW,:ICICLEPLATE,:INSECTPLATE,:IRONPLATE,:MEADOWPLATE,:MINDPLATE,
:SKYPLATE,:SPLASHPLATE,:SPOOKYPLATE,:STONEPLATE,:THICKCLUB,:TOXICPLATE,
:ZAPPLATE],
80 => [:DAWNSTONE,:DUSKSTONE,:ELECTIRIZER,:MAGMARIZER,:ODDKEYSTONE,:OVALSTONE,
:PROTECTOR,:QUICKCLAW,:RAZORCLAW,:SHINYSTONE,:STICKYBARB,:ASSAULTVEST],
70 => [:BURNDRIVE,:CHILLDRIVE,:DOUSEDRIVE,:DRAGONFANG,:POISONBARB,:POWERANKLET,
:POWERBAND,:POWERBELT,:POWERBRACER,:POWERLENS,:POWERWEIGHT,:SHOCKDRIVE],
60 => [:ADAMANTORB,:DAMPROCK,:HEATROCK,:LUSTROUSORB,:MACHOBRACE,:ROCKYHELMET,
:STICK,:AMPLIFIELDROCK,:ADRENALINEORB],
50 => [:DUBIOUSDISC,:SHARPBEAK],
40 => [:EVIOLITE,:ICYROCK,:LUCKYPUNCH,:PROTECTIVEPADS],
30 => [:ABILITYURGE,:ABSORBBULB,:AMULETCOIN,:ANTIDOTE,:AWAKENING,:BALMMUSHROOM,
:BERRYJUICE,:BIGMUSHROOM,:BIGNUGGET,:BIGPEARL,:BINDINGBAND,:BLACKBELT,
:BLACKFLUTE,:BLACKGLASSES,:BLACKSLUDGE,:BLUEFLUTE,:BLUESHARD,:BURNHEAL,
:CALCIUM,:CARBOS,:CASTELIACONE,:CELLBATTERY,:CHARCOAL,:CLEANSETAG,
:COMETSHARD,:DAMPMULCH,:DEEPSEASCALE,:DIREHIT,:DIREHIT2,:DIREHIT3,
:DRAGONSCALE,:EJECTBUTTON,:ELIXIR,:ENERGYPOWDER,:ENERGYROOT,:ESCAPEROPE,
:ETHER,:EVERSTONE,:EXPSHARE,:FIRESTONE,:FLAMEORB,:FLOATSTONE,:FLUFFYTAIL,
:FRESHWATER,:FULLHEAL,:FULLRESTORE,:GOOEYMULCH,:GREENSHARD,:GROWTHMULCH,
:GUARDSPEC,:HEALPOWDER,:HEARTSCALE,:HONEY,:HPUP,:HYPERPOTION,:ICEHEAL,
:IRON,:ITEMDROP,:ITEMURGE,:KINGSROCK,:LAVACOOKIE,:LEAFSTONE,:LEMONADE,
:LIFEORB,:LIGHTBALL,:LIGHTCLAY,:LUCKYEGG,:MAGNET,:MAXELIXIR,:MAXETHER,
:MAXPOTION,:MAXREPEL,:MAXREVIVE,:METALCOAT,:METRONOME,:MIRACLESEED,
:MOOMOOMILK,:MOONSTONE,:MYSTICWATER,:NEVERMELTICE,:NUGGET,:OLDGATEAU,
:PARLYZHEAL,:PEARL,:PEARLSTRING,:POKEDOLL,:POKETOY,:POTION,:PPMAX,:PPUP,
:PRISMSCALE,:PROTEIN,:RAGECANDYBAR,:RARECANDY,:RAZORFANG,:REDFLUTE,
:REDSHARD,:RELICBAND,:RELICCOPPER,:RELICCROWN,:RELICGOLD,:RELICSILVER,
:RELICSTATUE,:RELICVASE,:REPEL,:RESETURGE,:REVIVALHERB,:REVIVE,:SACREDASH,
:SCOPELENS,:SHELLBELL,:SHOALSALT,:SHOALSHELL,:SMOKEBALL,:SODAPOP,:SOULDEW,
:SPELLTAG,:STABLEMULCH,:STARDUST,:STARPIECE,:SUNSTONE,:SUPERPOTION,
:SUPERREPEL,:SWEETHEART,:THUNDERSTONE,:TINYMUSHROOM,:TOXICORB,
:TWISTEDSPOON,:UPGRADE,:WATERSTONE,:WHITEFLUTE,:XACCURACY,:XACCURACY2,
:XACCURACY3,:XACCURACY6,:XATTACK,:XATTACK2,:XATTACK3,:XATTACK6,:XDEFEND,
:XDEFEND2,:XDEFEND3,:XDEFEND6,:XSPDEF,:XSPDEF2,:XSPDEF3,:XSPDEF6,:XSPECIAL,
:XSPECIAL2,:XSPECIAL3,:XSPECIAL6,:XSPEED,:XSPEED2,:XSPEED3,:XSPEED6,
:YELLOWFLUTE,:YELLOWSHARD,:ZINC,:BIGMALASADA,:ICESTONE],
20 => [:CLEVERWING,:GENIUSWING,:HEALTHWING,:MUSCLEWING,:PRETTYWING,
:RESISTWING,:SWIFTWING],
10 => [:AIRBALLOON,:BIGROOT,:BLUESCARF,:BRIGHTPOWDER,:CHOICEBAND,:CHOICESCARF,
:CHOICESPECS,:DESTINYKNOT,:EXPERTBELT,:FOCUSBAND,:FOCUSSASH,:FULLINCENSE,
:GREENSCARF,:LAGGINGTAIL,:LAXINCENSE,:LEFTOVERS,:LUCKINCENSE,:MENTALHERB,
:METALPOWDER,:MUSCLEBAND,:ODDINCENSE,:PINKSCARF,:POWERHERB,:PUREINCENSE,
:QUICKPOWDER,:REAPERCLOTH,:REDCARD,:REDSCARF,:RINGTARGET,:ROCKINCENSE,
:ROSEINCENSE,:SEAINCENSE,:SHEDSHELL,:SILKSCARF,:SILVERPOWDER,:SMOOTHROCK,
:SOFTSAND,:SOOTHEBELL,:WAVEINCENSE,:WHITEHERB,:WIDELENS,:WISEGLASSES,
:YELLOWSCARF,:ZOOMLENS,:BLUEMIC,:VANILLAIC,:STRAWBIC,:CHOCOLATEIC]}
end
=end

View File

@@ -1,165 +0,0 @@
class PokeBattle_Battle
# Legacy method that should stop being used.
def pbGetOwner(battlerIndex)
if opposes?(battlerIndex)
if @opponent.is_a?(Array)
return (battlerIndex==1) ? @opponent[0] : @opponent[1]
else
return @opponent
end
else
if @player.is_a?(Array)
return (battlerIndex==0) ? @player[0] : @player[1]
else
return @player
end
end
end
# Reborn method (the difference is that each element in "choices" is an array
# in Essentials but just a number in Reborn)
def pbStdDev(choices)
sum = 0
n = 0
choices.each do |c|
sum += c
n += 1
end
return 0 if n<2
mean = sum.to_f/n.to_f
varianceTimesN = 0
for i in 0...choices.length
next if choices[i]<=0
deviation = choices[i].to_f-mean
varianceTimesN += deviation*deviation
end
# Using population standard deviation
# [(n-1) makes it a sample std dev, would be 0 with only 1 sample]
return Math.sqrt(varianceTimesN/n)
end
##############################################################################
# Choose an action.
##############################################################################
def pbDefaultChooseEnemyCommand(idxBattler)
if !@battle.pbCanShowFightMenu?(idxBattler)
return if pbEnemyShouldUseItem?(idxBattler)
# return if pbEnemyShouldWithdraw?(idxBattler) # Old Switching Method
return if pbShouldSwitch?(idxBattler)
return if @battle.pbAutoFightMenu(idxBattler)
@battle.pbAutoChooseMove(idxBattler)
return
end
pbBuildMoveScores(idxBattler) # Grab the array of scores/targets before doing anything else
return if pbShouldSwitch?(idxBattler)
# return if pbEnemyShouldWithdraw?(idxBattler) # Old Switching Method
return if pbEnemyShouldUseItem?(idxBattler)
return if @battle.pbAutoFightMenu(idxBattler)
@battle.pbRegisterUltraBurst(idxBattler) if pbEnemyShouldUltraBurst?(idxBattler)
@battle.pbRegisterMegaEvolution(idxBattler) if pbEnemyShouldMegaEvolve?(idxBattler)
if pbEnemyShouldZMove?(idxBattler)
return pbChooseEnemyZMove(idxBattler)
end
pbChooseMoves(idxBattler)
end
##############################################################################
#
##############################################################################
def pbChooseEnemyZMove(index) #Put specific cases for trainers using status Z-Moves
chosenmove=false
chosenindex=-1
attacker = @battlers[index]
opponent=attacker.pbOppositeOpposing
otheropp=opponent.pbPartner
skill=pbGetOwner(attacker.index).skill || 0
for i in 0..3
move=@battlers[index].moves[i]
if @battlers[index].pbCompatibleZMoveFromMove?(move)
if move.id == (PBMoves::CONVERSION) || move.id == (PBMoves::SPLASH)
pbRegisterZMove(index)
pbRegisterMove(index,i,false)
pbRegisterTarget(index,opponent.index)
return
end
if !chosenmove
chosenindex = i
chosenmove=move
else
if move.basedamage>chosenmove.basedamage
chosenindex=i
chosenmove=move
end
end
end
end
#oppeff1 = chosenmove.pbTypeModifier(chosenmove.type,attacker,opponent)
oppeff1 = pbTypeModNoMessages(chosenmove.type,attacker,opponent,chosenmove,skill)
#oppeff2 = chosenmove.pbTypeModifier(chosenmove.type,attacker,otheropp)
oppeff2 = pbTypeModNoMessages(chosenmove.type,attacker,otheropp,chosenmove,skill)
oppeff1 = 0 if opponent.hp<(opponent.totalhp/2.0).round
oppeff1 = 0 if (opponent.effects[PBEffects::Substitute]>0 || opponent.effects[PBEffects::Disguise]) && attacker.item!=(PBItems::KOMMONIUMZ2)
oppeff2 = 0 if otheropp.hp<(otheropp.totalhp/2.0).round
oppeff2 = 0 if (otheropp.effects[PBEffects::Substitute]>0 || otheropp.effects[PBEffects::Disguise]) && attacker.item!=(PBItems::KOMMONIUMZ2)
oppmult=0
for i in 1..7 #iterates through all the stats
oppmult+=opponent.stages[i] if opponent.stages[i]>0
end
othermult=0
for i in 1..7
othermult+=otheropp.stages[i] if otheropp.stages[i]>0
end
if (oppeff1<4) && ((oppeff2<4) || otheropp.hp==0)
pbChooseMoves(index)
elsif oppeff1>oppeff2
pbRegisterZMove(index)
pbRegisterMove(index,chosenindex,false)
pbRegisterTarget(index,opponent.index)
elsif oppeff1<oppeff2
pbRegisterZMove(index)
pbRegisterMove(index,chosenindex,false)
pbRegisterTarget(index,otheropp.index)
elsif oppeff1==oppeff2
if oppmult > othermult
pbRegisterZMove(index)
pbRegisterMove(index,chosenindex,false)
pbRegisterTarget(index,opponent.index)
elsif oppmult < othermult
pbRegisterZMove(index)
pbRegisterMove(index,chosenindex,false)
pbRegisterTarget(index,otheropp.index)
else
if otheropp.hp > opponent.hp
pbRegisterZMove(index)
pbRegisterMove(index,chosenindex,false)
pbRegisterTarget(index,otheropp.index)
else
pbRegisterZMove(index)
pbRegisterMove(index,chosenindex,false)
pbRegisterTarget(index,opponent.index)
end
end
end
end
##############################################################################
# Decide whether the opponent should use a Z-Move.
##############################################################################
def pbEnemyShouldZMove?(index)
return pbCanZMove?(index) #Conditions based on effectiveness and type handled later
end
#=============================================================================
# Decide whether the opponent should Ultra Burst their Pokémon.
#=============================================================================
def pbEnemyShouldUltraBurst?(idxBattler)
battler = @battlers[idxBattler]
if pbCanUltraBurst?(idxBattler) # Simple "always should if possible"
PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will Ultra Burst")
return true
end
return false
end
end

View File

@@ -1,495 +0,0 @@
class PokeBattle_Battle
################################################################################
# Decide whether the opponent should use an item on the Pokémon.
################################################################################
def pbEnemyShouldUseItem?(index)
item=pbEnemyItemToUse(index)
if item>0 && @battlers[index].effects[PBEffects::Embargo]==0
pbRegisterItem(index,item,nil)
return true
end
return false
end
def pbEnemyItemAlreadyUsed?(index,item,items)
if @choices[1][0]==3 && @choices[1][1]==item
qty=0
for i in items
qty+=1 if i==item
end
return true if qty<=1
end
return false
end
def pbEnemyItemToUse(index)
return 0 if !@opponent
return 0 if !@internalbattle
items=pbGetOwnerItems(index)
return 0 if !items
skill=pbGetOwner(index).skill || 0
battler=@battlers[index]
party = pbParty(index)
opponent1 = battler.pbOppositeOpposing
opponent2 = opponent1.pbPartner
currentroles = pbGetMonRole(battler,opponent1,skill)
return 0 if battler.isFainted?
highscore = 0
movecount = -1
maxplaypri = -1
partynumber = 0
aimem = getAIMemory(skill,opponent1.pokemonIndex)
for i in party
next if i.nil?
next if i.hp == 0
partynumber+=1
end
itemnumber = 0
for i in items
next if pbEnemyItemAlreadyUsed?(index,i,items)
itemnumber+=1
end
#highest score
for i in battler.moves
scorearray = 0
scorearray = @scores[i] if @scores[i]
if scorearray>100 && i.priority>maxplaypri
maxplaypri = i.priority
end
end
highscore = @scores.max
highdamage = -1
maxopppri = -1
pridam = -1
bestid = -1
#expected damage
#if battler.pbSpeed<pbRoughStat(opponent1,PBStats::SPEED,skill)
if aimem.length > 0
for i in aimem
tempdam = pbRoughDamage(i,opponent1,battler,skill,i.basedamage)
if tempdam>highdamage
highdamage = tempdam
bestid = i.id
end
if i.priority > maxopppri
maxopppri = i.priority
pridam = tempdam
end
end
end
highratio = -1
#expected damage percentage
if battler.hp!=0
highratio = highdamage*(1.0/battler.hp)
end
scorearray = []
arraycount = -1
PBDebug.log(sprintf("Beginning AI Item use check.")) if $INTERNAL
PBDebug.log(sprintf(" ")) if $INTERNAL
for i in items
arraycount+=1
scorearray.push(0)
itemscore=100
ishpitem = false
isstatusitem = false
next if pbEnemyItemAlreadyUsed?(index,i,items)
if (i== PBItems::POTION) ||
(i== PBItems::ULTRAPOTION) ||
(i== PBItems::SUPERPOTION) ||
(i== PBItems::HYPERPOTION) ||
(i== PBItems::MAXPOTION) ||
(i== PBItems::FULLRESTORE) ||
(i== PBItems::FRESHWATER) ||
(i== PBItems::SODAPOP) ||
(i== PBItems::LEMONADE) ||
(i== PBItems::MOOMOOMILK) ||
(i== PBItems::MEMEONADE) ||
(i== PBItems::STRAWBIC) ||
(i== PBItems::CHOCOLATEIC) ||
(i== PBItems::BLUEMIC)
ishpitem=true
end
if (i== PBItems::FULLRESTORE) ||
(i== PBItems::FULLHEAL) ||
(i== PBItems::RAGECANDYBAR) ||
(i== PBItems::LAVACOOKIE) ||
(i== PBItems::OLDGATEAU) ||
(i== PBItems::CASTELIACONE) ||
(i== PBItems::LUMIOSEGALETTE) ||
(i== PBItems::BIGMALASADA)
isstatusitem=true
end
if ishpitem
PBDebug.log(sprintf("This is a HP-healing item.")) if $INTERNAL
restoreamount=0
if (i== PBItems::POTION)
restoreamount=20
elsif (i== PBItems::ULTRAPOTION)
restoreamount=200
elsif (i== PBItems::SUPERPOTION)
restoreamount=60
elsif (i== PBItems::HYPERPOTION)
restoreamount=120
elsif (i== PBItems::MAXPOTION) || (i== PBItems::FULLRESTORE)
restoreamount=battler.totalhp
elsif (i== PBItems::FRESHWATER)
restoreamount=30
elsif (i== PBItems::SODAPOP)
restoreamount=50
elsif (i== PBItems::LEMONADE)
restoreamount=70
elsif (i== PBItems::MOOMOOMILK)
restoreamount=110
elsif (i== PBItems::MEMEONADE)
restoreamount=103
elsif (i== PBItems::STRAWBIC)
restoreamount=90
elsif (i== PBItems::CHOCOLATEIC)
restoreamount=70
elsif (i== PBItems::BLUEMIC)
restoreamount=200
end
resratio=restoreamount*(1.0/battler.totalhp)
itemscore*= (2 - (2*(battler.hp*(1.0/battler.totalhp))))
if highdamage>=battler.hp
if highdamage > [battler.hp+restoreamount,battler.totalhp].min
itemscore*=0
else
itemscore*=1.2
end
healmove = false
for j in battler.moves
if j.isHealingMove?
healmove=true
end
end
if healmove
if battler.pbSpeed < opponent1.pbSpeed
if highdamage>=battler.hp
itemscore*=1.1
else
itemscore*=0.6
if resratio<0.55
itemscore*=0.2
end
end
end
end
else
itemscore*=0.4
end
if highdamage > restoreamount
itemscore*=0
else
if restoreamount-highdamage < 15
itemscore*=0.5
end
end
if battler.pbSpeed > opponent1.pbSpeed
itemscore*=0.8
if highscore >=110
if maxopppri > maxplaypri
itemscore*=1.3
if pridam>battler.hp
if pridam>(battler.hp/2.0)
itemscore*=0
else
itemscore*=2
end
end
elsif !(!opponent1.abilitynulled && opponent1.ability == PBAbilities::STURDY)
itemscore*=0
end
end
if currentroles.include?(PBMonRoles::SWEEPER)
itemscore*=1.1
end
else
if highdamage*2 > [battler.hp+restoreamount,battler.totalhp].min
itemscore*=0
else
itemscore*=1.5
if highscore >=110
itemscore*=1.5
end
end
end
if battler.hp == battler.totalhp
itemscore*=0
elsif battler.hp >= (battler.totalhp*0.8)
itemscore*=0.2
elsif battler.hp >= (battler.totalhp*0.6)
itemscore*=0.3
elsif battler.hp >= (battler.totalhp*0.5)
itemscore*=0.5
end
minipot = (partynumber-1)
minimini = -1
for j in items
next if pbEnemyItemAlreadyUsed?(index,j,items)
next if !((j== PBItems::POTION) || (j== PBItems::ULTRAPOTION) ||
(j== PBItems::SUPERPOTION) || (j== PBItems::HYPERPOTION) ||
(j== PBItems::MAXPOTION) || (j== PBItems::FULLRESTORE) ||
(j== PBItems::FRESHWATER) || (j== PBItems::SODAPOP) ||
(j== PBItems::LEMONADE) || (j== PBItems::MOOMOOMILK) ||
(j== PBItems::MEMEONADE) || (j== PBItems::STRAWBIC) ||
(j== PBItems::CHOCOLATEIC) || (j== PBItems::BLUEMIC))
minimini+=1
end
if minipot>minimini
itemscore*=(0.9**(minipot-minimini))
minipot=minimini
elsif minimini>minipot
itemscore*=(1.1**(minimini-minipot))
minimini=minipot
end
if currentroles.include?(PBMonRoles::LEAD) || currentroles.include?(PBMonRoles::SCREENER)
itemscore*=0.6
end
if currentroles.include?(PBMonRoles::TANK)
itemscore*=1.1
end
if currentroles.include?(PBMonRoles::SECOND)
itemscore*=1.1
end
if battler.hasWorkingItem(:LEFTOVERS) || (battler.hasWorkingItem(:BLACKSLUDGE) && battler.pbHasType?(:POISON))
itemscore*=0.9
end
if battler.status!=0 && !(i== PBItems::FULLRESTORE)
itemscore*=0.7
if battler.effects[PBEffects::Toxic]>0 && partynumber>1
itemscore*=0.2
end
end
if PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)>4
itemscore*=0.7
elsif PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)<4
itemscore*=1.1
if PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)==0
itemscore*=1.2
end
end
if PBTypes.getCombinedEffectiveness(opponent1.type2,battler.type1,battler.type2)>4
itemscore*=0.6
elsif PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)<4
itemscore*=1.1
if PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)==0
itemscore*=1.2
end
end
if (!battler.abilitynulled && battler.ability == PBAbilities::REGENERATOR) && partynumber>1
itemscore*=0.7
end
end
if isstatusitem
PBDebug.log(sprintf("This is a status-curing item.")) if $INTERNAL
if !(i== PBItems::FULLRESTORE)
if battler.status==0
itemscore*=0
else
if highdamage>battler.hp
if (bestid==106 && battler.status==PBStatuses::SLEEP) || (bestid==298 && battler.status==PBStatuses::PARALYSIS) || bestid==179
if highdamage*0.5>battler.hp
itemscore*=0
else
itemscore*=1.4
end
else
itemscore*=0
end
end
end
if battler.status==PBStatuses::SLEEP
if battler.pbHasMove?((PBMoves::SLEEPTALK)) ||
battler.pbHasMove?((PBMoves::SNORE)) ||
battler.pbHasMove?((PBMoves::REST)) ||
(!battler.abilitynulled && battler.ability == PBAbilities::COMATOSE)
itemscore*=0.6
end
if checkAImoves([PBMoves::DREAMEATER,PBMoves::NIGHTMARE],aimem) || (!opponent1.abilitynulled && opponent1.ability == PBAbilities::BADDREAMS)
itemscore*=1.3
end
if highdamage*(1.0/battler.hp)>0.2
itemscore*=1.3
else
itemscore*=0.7
end
end
if battler.status==PBStatuses::PARALYSIS
if (!battler.abilitynulled && battler.ability == PBAbilities::QUICKFEET) || (!battler.abilitynulled && battler.ability == PBAbilities::GUTS)
itemscore*=0.5
end
if battler.pbSpeed>opponent1.pbSpeed && (battler.pbSpeed*0.5)<opponent1.pbSpeed
itemscore*=1.3
end
itemscore*=1.1
end
if battler.status==PBStatuses::BURN
itemscore*=1.1
if battler.attack>battler.spatk
itemscore*=1.2
else
itemscore*=0.8
end
if !battler.abilitynulled
itemscore*=0.6 if battler.ability == PBAbilities::GUTS
itemscore*=0.7 if battler.ability == PBAbilities::MAGICGUARD
itemscore*=0.8 if battler.ability == PBAbilities::FLAREBOOST
end
end
if battler.status==PBStatuses::POISON
itemscore*=1.1
if !battler.abilitynulled
itemscore*=0.5 if battler.ability == PBAbilities::GUTS
itemscore*=0.5 if battler.ability == PBAbilities::MAGICGUARD
itemscore*=0.5 if battler.ability == PBAbilities::TOXICBOOST
itemscore*=0.4 if battler.ability == PBAbilities::POISONHEAL
end
if battler.effects[PBEffects::Toxic]>0
itemscore*=1.1
if battler.effects[PBEffects::Toxic]>3
itemscore*=1.3
end
end
end
if battler.status==PBStatuses::FROZEN
itemscore*=1.3
thawmove=false
for j in battler.moves
if j.canThawUser?
thawmove=true
end
end
if thawmove
itemscore*=0.5
end
if highdamage*(1.0/battler.hp)>0.15
itemscore*=1.1
else
itemscore*=0.9
end
end
end
if battler.pbHasMove?((PBMoves::REFRESH)) ||
battler.pbHasMove?((PBMoves::REST)) ||
battler.pbHasMove?((PBMoves::PURIFY))
itemscore*=0.5
end
if (!battler.abilitynulled && battler.ability == PBAbilities::NATURALCURE) && partynumber>1
itemscore*=0.2
end
if (!battler.abilitynulled && battler.ability == PBAbilities::SHEDSKIN)
itemscore*=0.3
end
end
if partynumber==1 || currentroles.include?(PBMonRoles::ACE)
itemscore*=1.2
else
itemscore*=0.8
if battler.itemUsed2
itemscore*=0.6
end
end
if battler.effects[PBEffects::Confusion]>0
itemscore*=0.9
end
if battler.effects[PBEffects::Attract]>=0
itemscore*=0.6
end
if battler.effects[PBEffects::Substitute]>0
itemscore*=1.1
end
if battler.effects[PBEffects::LeechSeed]>=0
itemscore*=0.5
end
if battler.effects[PBEffects::Curse]
itemscore*=0.5
end
if battler.effects[PBEffects::PerishSong]>0
itemscore*=0.2
end
minipot=0
for s in [PBStats::ATTACK,PBStats::DEFENSE,PBStats::SPEED,
PBStats::SPATK,PBStats::SPDEF,PBStats::ACCURACY,PBStats::EVASION]
minipot+=battler.stages[s]
end
if currentroles.include?(PBMonRoles::PHYSICALWALL) || currentroles.include?(PBMonRoles::SPECIALWALL)
for s in [PBStats::DEFENSE,PBStats::SPDEF]
minipot+=battler.stages[s]
end
end
if currentroles.include?(PBMonRoles::SWEEPER)
for s in [PBStats::SPEED]
minipot+=battler.stages[s]
end
if battler.attack>battler.spatk
for s in [PBStats::ATTACK]
minipot+=battler.stages[s]
end
else
for s in [PBStats::SPATK]
minipot+=battler.stages[s]
end
end
end
minipot*=5
minipot+=100
minipot*=0.01
itemscore*=minipot
if opponent1.effects[PBEffects::TwoTurnAttack]>0 || opponent1.effects[PBEffects::HyperBeam]>0
itemscore*=1.2
end
if highscore>70
itemscore*=1.1
else
itemscore*=0.9
end
fielddisrupt = getFieldDisruptScore(battler,opponent1,skill)
if fielddisrupt <= 0
fielddisrupt=0.6
end
itemscore*= (1.0/fielddisrupt)
if @trickroom > 0
itemscore*=0.9
end
if battler.pbOwnSide.effects[PBEffects::Tailwind]>0
itemscore*=0.6
end
if battler.pbOwnSide.effects[PBEffects::Reflect]>0
itemscore*=0.9
end
if battler.pbOwnSide.effects[PBEffects::LightScreen]>0
itemscore*=0.9
end
if battler.pbOwnSide.effects[PBEffects::AuroraVeil]>0
itemscore*=0.8
end
if @doublebattle
itemscore*=0.8
end
itemscore-=100
PBDebug.log(sprintf("Score for %s: %d",PBItems.getName(i),itemscore)) if $INTERNAL
scorearray[arraycount] = itemscore
end
bestitem=-1
bestscore=-10000
counter=-1
for k in scorearray
counter+=1
if k>bestscore
bestscore = k
bestitem = items[counter]
end
end
PBDebug.log(sprintf("Highest item score: %d",bestscore)) if $INTERNAL
PBDebug.log(sprintf("Highest move score: %d",highscore)) if $INTERNAL
if highscore<bestscore
PBDebug.log(sprintf("Using %s",PBItems.getName(bestitem))) if $INTERNAL
return bestitem
else
PBDebug.log(sprintf("Not using an item.")) if $INTERNAL
PBDebug.log(sprintf(" ")) if $INTERNAL
return 0
end
end
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,121 +0,0 @@
class PokeBattle_Battle
attr_accessor :aiMoveMemory
alias __ai__initialize initialize
def initialize(scene,p1,p2,player,opponent)
__ai__initialize(scene,p1,p2,player,opponent)
@aiMoveMemory = [[],
[],
[[], [], [], [], [], [], [], [], [], [], [], []] # One array for each party index
]
end
################################################################################
# AI Memory utility functions
################################################################################
def getAIMemory(skill,index=0)
if skill>=PBTrainerAI.bestSkill
return @aiMoveMemory[2][index]
elsif skill>=PBTrainerAI.highSkill
return @aiMoveMemory[1]
elsif skill>=PBTrainerAI.mediumSkill
return @aiMoveMemory[0]
else
return []
end
end
def checkAImoves(moveID,memory)
#basic "does the other mon have x"
return false if memory.length == 0
for i in moveID
for j in memory
j = pbChangeMove(j,nil)#doesn't matter that i'm passing nil, won't get used
return true if i == j.id #i should already be an ID here
end
end
return false
end
def checkAIhealing(memory)
#less basic "can the other mon heal"
return false if memory.length == 0
for j in memory
return true if j.isHealingMove?
end
return false
end
def checkAIpriority(memory)
#"does the other mon have priority"
return false if memory.length == 0
for j in memory
return true if j.priority>0
end
return false
end
def checkAIaccuracy(memory)
#"does the other mon have moves that don't miss"
return false if memory.length == 0
for j in memory
j = pbChangeMove(j,nil)
return true if j.accuracy==0
end
return false
end
def checkAIdamage(memory,attacker,opponent,skill)
#returns how much damage the AI expects to take
return -1 if memory.length == 0
maxdam=0
for j in memory
tempdam = pbRoughDamage(j,opponent,attacker,skill,j.basedamage)
maxdam=tempdam if tempdam>maxdam
end
return maxdam
end
def checkAIbest(memory,modifier,type=[],usepower=true,attacker=nil,opponent=nil,skill=nil)
return false if memory.length == 0
#had to split this because switching ai uses power
bestmove = 0
if usepower
biggestpower = 0
for j in memory
if j.basedamage>biggestpower
biggestpower=j.basedamage
bestmove=j
end
end
else #maxdam
maxdam=0
for j in memory
tempdam = pbRoughDamage(j,opponent,attacker,skill,j.basedamage)
if tempdam>maxdam
maxdam=tempdam
bestmove=j
end
end
end
return false if bestmove==0
#i don't want to make multiple functions for rare cases
#we're doing it in one and you're gonna like it
case modifier
when 1 #type mod. checks types from a list.
return true if type.include?(bestmove.type)
when 2 #physical mod.
return true if bestmove.pbIsPhysical?(bestmove.type)
when 3 #special mod.
return true if bestmove.pbIsSpecial?(bestmove.type)
when 4 #contact mod.
return true if bestmove.isContactMove?
when 5 #sound mod.
return true if bestmove.isSoundBased?
when 6 #why.
return true if (PBStuff::BULLETMOVE).include?(bestmove.id)
end
return false #you're still here? it's over! go home.
end
end

View File

@@ -1,974 +0,0 @@
class PokeBattle_Battle
=begin
# Added to Essentials
def pbStatusDamage(move)
if (move.id == PBMoves::AFTERYOU || move.id == PBMoves::BESTOW || # 11D, 0F3
move.id == PBMoves::CRAFTYSHIELD || move.id == PBMoves::LUCKYCHANT || # 14A, 0A1
move.id == PBMoves::MEMENTO || move.id == PBMoves::QUASH || # 0E2, 11E
move.id == PBMoves::SAFEGUARD || move.id == PBMoves::SPITE || # 01A, 10E
move.id == PBMoves::SPLASH || move.id == PBMoves::SWEETSCENT || # 001, 048
move.id == PBMoves::TELEKINESIS || move.id == PBMoves::TELEPORT) # 11A, 0EA
# "001", "01A", "048", "0A1", "0E2", "0EA", "0F3", "10E", "11A", "11D", "11E", "14A"
return 0
elsif (move.id == PBMoves::ALLYSWITCH || move.id == PBMoves::AROMATICMIST ||
move.id == PBMoves::CONVERSION || move.id == PBMoves::ENDURE ||
move.id == PBMoves::ENTRAINMENT || move.id == PBMoves::FLOWERSHIELD ||
move.id == PBMoves::FORESIGHT || move.id == PBMoves::FORESTSCURSE ||
move.id == PBMoves::GRAVITY || move.id == PBMoves::DEFOG ||
move.id == PBMoves::GUARDSWAP || move.id == PBMoves::HEALBLOCK ||
move.id == PBMoves::IMPRISON || move.id == PBMoves::INSTRUCT ||
move.id == PBMoves::FAIRYLOCK || move.id == PBMoves::LASERFOCUS ||
move.id == PBMoves::HELPINGHAND || move.id == PBMoves::MAGICROOM ||
move.id == PBMoves::MAGNETRISE || move.id == PBMoves::SOAK ||
move.id == PBMoves::LOCKON || move.id == PBMoves::MINDREADER ||
move.id == PBMoves::MIRACLEEYE || move.id == PBMoves::MUDSPORT ||
move.id == PBMoves::NIGHTMARE || move.id == PBMoves::ODORSLEUTH ||
move.id == PBMoves::POWERSPLIT || move.id == PBMoves::POWERSWAP ||
move.id == PBMoves::GRUDGE || move.id == PBMoves::GUARDSPLIT ||
move.id == PBMoves::POWERTRICK || move.id == PBMoves::QUICKGUARD ||
move.id == PBMoves::RECYCLE || move.id == PBMoves::REFLECTTYPE ||
move.id == PBMoves::ROTOTILLER || move.id == PBMoves::SANDATTACK ||
move.id == PBMoves::SKILLSWAP || move.id == PBMoves::SNATCH ||
move.id == PBMoves::MAGICCOAT || move.id == PBMoves::SPEEDSWAP ||
move.id == PBMoves::SPOTLIGHT || move.id == PBMoves::SWALLOW ||
move.id == PBMoves::TEETERDANCE || move.id == PBMoves::WATERSPORT ||
move.id == PBMoves::WIDEGUARD || move.id == PBMoves::WONDERROOM)
# "013", "047", "049", "052", "053", "057", "058", "059", "05E", "061",
# "062", "066", "067", "09C", "09D", "09E", "0A6", "0A6", "0A7", "0A7",
# "0A8", "0AB", "0AC", "0B1", "0B2", "0B8", "0BB", "0E6", "0E8", "0F6",
# "0F9", "10F", "114", "118", "119", "120", "124", "138", "13E", "13F",
# "143", "152", "15E", "161", "16A", "16B"
return 5
elsif (move.id == PBMoves::ACUPRESSURE || move.id == PBMoves::CAMOUFLAGE ||
move.id == PBMoves::CHARM || move.id == PBMoves::CONFIDE ||
move.id == PBMoves::DEFENSECURL || move.id == PBMoves::GROWTH ||
move.id == PBMoves::EMBARGO || move.id == PBMoves::FLASH ||
move.id == PBMoves::FOCUSENERGY || move.id == PBMoves::GROWL ||
move.id == PBMoves::HARDEN || move.id == PBMoves::HAZE ||
move.id == PBMoves::HONECLAWS || move.id == PBMoves::HOWL ||
move.id == PBMoves::KINESIS || move.id == PBMoves::LEER ||
move.id == PBMoves::METALSOUND || move.id == PBMoves::NOBLEROAR ||
move.id == PBMoves::PLAYNICE || move.id == PBMoves::POWDER ||
move.id == PBMoves::PSYCHUP || move.id == PBMoves::SHARPEN ||
move.id == PBMoves::SMOKESCREEN || move.id == PBMoves::STRINGSHOT ||
move.id == PBMoves::SUPERSONIC || move.id == PBMoves::TAILWHIP ||
move.id == PBMoves::TEARFULLOOK || move.id == PBMoves::TORMENT ||
move.id == PBMoves::WITHDRAW || move.id == PBMoves::WORKUP)
# "013", "01C", "01C", "01D", "01D", "01E", "023", "027", "028", "029",
# "037", "042", "043", "043", "047", "047", "047", "04B", "04D", "04F",
# "051", "055", "060", "0B7", "0F8", "139", "13A", "13A", "13C", "148"
return 10
elsif (move.id == PBMoves::ASSIST || move.id == PBMoves::BABYDOLLEYES ||
move.id == PBMoves::CAPTIVATE || move.id == PBMoves::COTTONSPORE ||
move.id == PBMoves::DARKVOID || move.id == PBMoves::AGILITY ||
move.id == PBMoves::DOUBLETEAM || move.id == PBMoves::EERIEIMPULSE ||
move.id == PBMoves::FAKETEARS || move.id == PBMoves::FEATHERDANCE ||
move.id == PBMoves::FLORALHEALING || move.id == PBMoves::GRASSWHISTLE ||
move.id == PBMoves::HEALPULSE || move.id == PBMoves::HEALINGWISH ||
move.id == PBMoves::HYPNOSIS || move.id == PBMoves::INGRAIN ||
move.id == PBMoves::LUNARDANCE || move.id == PBMoves::MEFIRST ||
move.id == PBMoves::MEDITATE || move.id == PBMoves::MIMIC ||
move.id == PBMoves::PARTINGSHOT || move.id == PBMoves::POISONPOWDER ||
move.id == PBMoves::REFRESH || move.id == PBMoves::ROLEPLAY ||
move.id == PBMoves::SCARYFACE || move.id == PBMoves::SCREECH ||
move.id == PBMoves::SING || move.id == PBMoves::SKETCH ||
move.id == PBMoves::TICKLE || move.id == PBMoves::CHARGE ||
move.id == PBMoves::TRICKORTREAT || move.id == PBMoves::VENOMDRENCH ||
move.id == PBMoves::GEARUP || move.id == PBMoves::MAGNETICFLUX ||
move.id == PBMoves::SANDSTORM || move.id == PBMoves::HAIL ||
move.id == PBMoves::SUNNYDAY || move.id == PBMoves::RAINDANCE)
# "003", "003", "003", "003", "005", "018", "01C", "021", "022", "030",
# "042", "04A", "04B", "04C", "04D", "04D", "04E", "04F", "05C", "05D",
# "065", "0B0", "0B5", "0DB", "0DF", "0E3", "0E4", "0FF", "100", "101",
# "102", "137", "13D", "140", "142", "151", "15C", "16E"
return 15
elsif (move.id == PBMoves::AQUARING || move.id == PBMoves::BLOCK ||
move.id == PBMoves::CONVERSION2 || move.id == PBMoves::ELECTRIFY ||
move.id == PBMoves::FLATTER || move.id == PBMoves::GASTROACID ||
move.id == PBMoves::HEARTSWAP || move.id == PBMoves::IONDELUGE ||
move.id == PBMoves::MEANLOOK || move.id == PBMoves::LOVELYKISS ||
move.id == PBMoves::METRONOME || move.id == PBMoves::COPYCAT ||
move.id == PBMoves::MIRRORMOVE || move.id == PBMoves::MIST ||
move.id == PBMoves::PERISHSONG || move.id == PBMoves::REST ||
move.id == PBMoves::ROAR || move.id == PBMoves::SIMPLEBEAM ||
move.id == PBMoves::SLEEPPOWDER || move.id == PBMoves::SPIDERWEB ||
move.id == PBMoves::SWAGGER || move.id == PBMoves::SWEETKISS ||
move.id == PBMoves::POISONGAS || move.id == PBMoves::TOXICTHREAD ||
move.id == PBMoves::TRANSFORM || move.id == PBMoves::WHIRLWIND ||
move.id == PBMoves::WORRYSEED || move.id == PBMoves::YAWN)
# "003", "003", "004", "005", "013", "040", "041", "054", "056", "05F",
# "063", "064", "068", "069", "0AE", "0AF", "0B6", "0D9", "0DA", "0E5",
# "0EB", "0EB", "0EF", "0EF", "0EF", "145", "146", "159"
return 20
elsif (move.id == PBMoves::AMNESIA || move.id == PBMoves::ATTRACT ||
move.id == PBMoves::BARRIER || move.id == PBMoves::BELLYDRUM ||
move.id == PBMoves::CONFUSERAY || move.id == PBMoves::DESTINYBOND ||
move.id == PBMoves::DETECT || move.id == PBMoves::DISABLE ||
move.id == PBMoves::ACIDARMOR || move.id == PBMoves::COSMICPOWER ||
move.id == PBMoves::COTTONGUARD || move.id == PBMoves::DEFENDORDER ||
move.id == PBMoves::FOLLOWME || move.id == PBMoves::AUTOTOMIZE ||
move.id == PBMoves::HEALORDER || move.id == PBMoves::IRONDEFENSE ||
move.id == PBMoves::LEECHSEED || move.id == PBMoves::MILKDRINK ||
move.id == PBMoves::MINIMIZE || move.id == PBMoves::MOONLIGHT ||
move.id == PBMoves::MORNINGSUN || move.id == PBMoves::PAINSPLIT ||
move.id == PBMoves::PROTECT || move.id == PBMoves::PSYCHOSHIFT ||
move.id == PBMoves::RAGEPOWDER || move.id == PBMoves::ROOST ||
move.id == PBMoves::RECOVER || move.id == PBMoves::ROCKPOLISH ||
move.id == PBMoves::SHOREUP || move.id == PBMoves::SLACKOFF ||
move.id == PBMoves::SOFTBOILED || move.id == PBMoves::STRENGTHSAP ||
move.id == PBMoves::STOCKPILE || move.id == PBMoves::STUNSPORE ||
move.id == PBMoves::SUBSTITUTE ||
move.id == PBMoves::SWITCHEROO || move.id == PBMoves::SYNTHESIS ||
move.id == PBMoves::TAUNT || move.id == PBMoves::TOPSYTURVY ||
move.id == PBMoves::TOXIC || move.id == PBMoves::TRICK ||
move.id == PBMoves::WILLOWISP || move.id == PBMoves::WISH)
# "006", "007", "00A", "013", "016", "01B", "02A", "02A", "02F", "02F",
# "02F", "030", "031", "033", "034", "038", "03A", "05A", "0AA", "0AA",
# "0B9", "0BA", "0D5", "0D5", "0D5", "0D5", "0D5", "0D6", "0D7", "0D8",
# "0D8", "0D8", "0DC", "0E7", "0F2", "0F2", "10C", "112", "117", "117",
# "141", "160", "16D"
return 25
elsif (move.id == PBMoves::BATONPASS || move.id == PBMoves::BULKUP ||
move.id == PBMoves::CALMMIND || move.id == PBMoves::COIL ||
move.id == PBMoves::CURSE || move.id == PBMoves::ELECTRICTERRAIN ||
move.id == PBMoves::ENCORE || move.id == PBMoves::GLARE ||
move.id == PBMoves::GRASSYTERRAIN || move.id == PBMoves::MISTYTERRAIN ||
move.id == PBMoves::NATUREPOWER || move.id == PBMoves::PSYCHICTERRAIN ||
move.id == PBMoves::PURIFY || move.id == PBMoves::SLEEPTALK ||
move.id == PBMoves::SPIKES || move.id == PBMoves::STEALTHROCK ||
move.id == PBMoves::SPIKYSHIELD || move.id == PBMoves::THUNDERWAVE ||
move.id == PBMoves::TOXICSPIKES || move.id == PBMoves::TRICKROOM)
# "007", "007", "024", "025", "02C", "0B3", "0B4", "0BC", "0ED", "103",
# "104", "105", "10D", "11F", "14C", "154", "155", "156", "15B", "173"
return 30
elsif (move.id == PBMoves::AROMATHERAPY || move.id == PBMoves::BANEFULBUNKER ||
move.id == PBMoves::HEALBELL || move.id == PBMoves::KINGSSHIELD ||
move.id == PBMoves::LIGHTSCREEN || move.id == PBMoves::MATBLOCK ||
move.id == PBMoves::NASTYPLOT || move.id == PBMoves::REFLECT ||
move.id == PBMoves::SWORDSDANCE || move.id == PBMoves::TAILGLOW ||
move.id == PBMoves::TAILWIND)
# "019", "019", "02E", "032", "039", "05B", "0A2", "0A3", "149", "14B", "168"
return 35
elsif (move.id == PBMoves::DRAGONDANCE || move.id == PBMoves::GEOMANCY ||
move.id == PBMoves::QUIVERDANCE || move.id == PBMoves::SHELLSMASH ||
move.id == PBMoves::SHIFTGEAR)
# "026", "02B", "035", "036", "14E"
return 40
elsif (move.id == PBMoves::AURORAVEIL || move.id == PBMoves::STICKYWEB ||
move.id == PBMoves::SPORE)
# "003", "153", "167"
return 60
end
end
=end
def pbAegislashStats(aegi)
if aegi.form==1
return aegi
else
bladecheck = aegi.clone
bladecheck.form = 1
return bladecheck
end
end
def pbMegaStats(mon)
if mon.isMega?
return mon
else
megacheck = mon.clone
megacheck.stages = mon.stages.clone
megacheck.form = mon.getMegaForm
return megacheck
end
end
def pbChangeMove(move,attacker)
move = PokeBattle_Move.pbFromPBMove(self,PBMove.new(move.id),attacker)
case move.id
when PBMoves::WEATHERBALL
weather=pbWeather
move.type=(PBTypes::NORMAL)
move.type=PBTypes::FIRE if (weather==PBWeather::SUNNYDAY && !attacker.hasWorkingItem(:UTILITYUMBRELLA))
move.type=PBTypes::WATER if (weather==PBWeather::RAINDANCE && !attacker.hasWorkingItem(:UTILITYUMBRELLA))
move.type=PBTypes::ROCK if weather==PBWeather::SANDSTORM
move.type=PBTypes::ICE if weather==PBWeather::HAIL
if pbWeather !=0
move.basedamage*=2 if move.basedamage == 50
end
when PBMoves::HIDDENPOWER
if attacker
move.type = move.pbType(type,attacker,nil)
end
when PBMoves::NATUREPOWER
move=0
if $fefieldeffect > 0
naturemoves = FieldEffects::NATUREMOVES
move= naturemoves[$fefieldeffect] # Combination of environment and Terrain
else
move=PBMoves::TRIATTACK
end
move = PokeBattle_Move.pbFromPBMove(self,PBMove.new(move),attacker)
end
return move
end
def getAbilityDisruptScore(move,attacker,opponent,skill)
abilityscore=100.0
return abilityscore if !opponent.abilitynulled == false #if the ability doesn't work, then nothing here matters
if opponent.ability == PBAbilities::SPEEDBOOST
PBDebug.log(sprintf("Speedboost Disrupt")) if $INTERNAL
abilityscore*=1.1
if opponent.stages[PBStats::SPEED]<2
abilityscore*=1.3
end
elsif opponent.ability == PBAbilities::SANDVEIL
PBDebug.log(sprintf("Sand veil Disrupt")) if $INTERNAL
if @weather==PBWeather::SANDSTORM
abilityscore*=1.3
end
elsif opponent.ability == PBAbilities::VOLTABSORB ||
opponent.ability == PBAbilities::LIGHTNINGROD ||
opponent.ability == PBAbilities::MOTORDRIVE
PBDebug.log(sprintf("Volt Absorb Disrupt")) if $INTERNAL
elecvar = false
totalelec=true
elecmove=nil
for i in attacker.moves
if !(i.type == PBTypes::ELECTRIC)
totalelec=false
end
if (i.type == PBTypes::ELECTRIC)
elecvar=true
elecmove=i
end
end
if elecvar
if totalelec
abilityscore*=3
end
if pbTypeModNoMessages(elecmove.type,attacker,opponent,elecmove,skill)>4
abilityscore*=2
end
end
elsif opponent.ability == PBAbilities::WATERABSORB ||
opponent.ability == PBAbilities::STORMDRAIN ||
opponent.ability == PBAbilities::DRYSKIN
PBDebug.log(sprintf("Water Absorb Disrupt")) if $INTERNAL
watervar = false
totalwater=true
watermove=nil
firevar=false
for i in attacker.moves
if !(i.type == PBTypes::WATER)
totalwater=false
end
if (i.type == PBTypes::WATER)
watervar=true
watermove=i
end
if (i.type == PBTypes::FIRE)
firevar=true
end
end
if watervar
if totalwater
abilityscore*=3
end
if pbTypeModNoMessages(watermove.type,attacker,opponent,watermove,skill)>4
abilityscore*=2
end
end
if opponent.ability == PBAbilities::DRYSKIN
if firevar
abilityscore*=0.5
end
end
elsif opponent.ability == PBAbilities::FLASHFIRE
PBDebug.log(sprintf("Flash Fire Disrupt")) if $INTERNAL
firevar = false
totalfire=true
firemove=nil
for i in attacker.moves
if !(i.type == PBTypes::FIRE)
totalfire=false
end
if (i.type == PBTypes::FIRE)
firevar=true
firemove=i
end
end
if firevar
if totalfire
abilityscore*=3
end
if pbTypeModNoMessages(firemove.type,attacker,opponent,firemove,skill)>4
abilityscore*=2
end
end
elsif opponent.ability == PBAbilities::LEVITATE
PBDebug.log(sprintf("Levitate Disrupt")) if $INTERNAL
groundvar = false
totalground=true
groundmove=nil
for i in attacker.moves
if !(i.type == PBTypes::GROUND)
totalground=false
end
if (i.type == PBTypes::GROUND)
groundvar=true
groundmove=i
end
end
if groundvar
if totalground
abilityscore*=3
end
if pbTypeModNoMessages(groundmove.type,attacker,opponent,groundmove,skill)>4
abilityscore*=2
end
end
elsif opponent.ability == PBAbilities::SHADOWTAG
PBDebug.log(sprintf("Shadow Tag Disrupt")) if $INTERNAL
if !attacker.hasType?(PBTypes::GHOST)
abilityscore*=1.5
end
elsif opponent.ability == PBAbilities::ARENATRAP
PBDebug.log(sprintf("Arena Trap Disrupt")) if $INTERNAL
if attacker.isAirborne?
abilityscore*=1.5
end
elsif opponent.ability == PBAbilities::WONDERGUARD
PBDebug.log(sprintf("Wonder Guard Disrupt")) if $INTERNAL
wondervar=false
for i in attacker.moves
if pbTypeModNoMessages(i.type,attacker,opponent,i,skill)>4
wondervar=true
end
end
if !wondervar
abilityscore*=5
end
elsif opponent.ability == PBAbilities::SERENEGRACE
PBDebug.log(sprintf("Serene Grace Disrupt")) if $INTERNAL
abilityscore*=1.3
elsif opponent.ability == PBAbilities::PUREPOWER || opponent.ability == PBAbilities::HUGEPOWER
PBDebug.log(sprintf("Pure Power Disrupt")) if $INTERNAL
abilityscore*=2
elsif opponent.ability == PBAbilities::SOUNDPROOF
PBDebug.log(sprintf("Soundproof Disrupt")) if $INTERNAL
soundvar=false
for i in attacker.moves
if i.isSoundBased?
soundvar=true
end
end
if !soundvar
abilityscore*=3
end
elsif opponent.ability == PBAbilities::THICKFAT
PBDebug.log(sprintf("Thick Fat Disrupt")) if $INTERNAL
totalguard=true
for i in attacker.moves
if !(i.type == PBTypes::FIRE) && !(i.type == PBTypes::ICE)
totalguard=false
end
end
if totalguard
abilityscore*=1.5
end
elsif opponent.ability == PBAbilities::TRUANT
PBDebug.log(sprintf("Truant Disrupt")) if $INTERNAL
abilityscore*=0.1
elsif opponent.ability == PBAbilities::GUTS ||
opponent.ability == PBAbilities::QUICKFEET ||
opponent.ability == PBAbilities::MARVELSCALE
PBDebug.log(sprintf("Guts Disrupt")) if $INTERNAL
if opponent.status!=0
abilityscore*=1.5
end
elsif opponent.ability == PBAbilities::LIQUIDOOZE
PBDebug.log(sprintf("Liquid Ooze Disrupt")) if $INTERNAL
if opponent.effects[PBEffects::LeechSeed]>=0 || attacker.pbHasMove?((PBMoves::LEECHSEED))
abilityscore*=2
end
elsif opponent.ability == PBAbilities::AIRLOCK || opponent.ability == PBAbilities::CLOUDNINE
PBDebug.log(sprintf("Airlock Disrupt")) if $INTERNAL
abilityscore*=1.1
elsif opponent.ability == PBAbilities::HYDRATION
PBDebug.log(sprintf("Hydration Disrupt")) if $INTERNAL
if @weather==PBWeather::RAINDANCE
abilityscore*=1.3
end
elsif opponent.ability == PBAbilities::ADAPTABILITY
PBDebug.log(sprintf("Adaptability Disrupt")) if $INTERNAL
abilityscore*=1.3
elsif opponent.ability == PBAbilities::SKILLLINK
PBDebug.log(sprintf("Skill Link Disrupt")) if $INTERNAL
abilityscore*=1.5
elsif opponent.ability == PBAbilities::POISONHEAL
PBDebug.log(sprintf("Poison Heal Disrupt")) if $INTERNAL
if opponent.status==PBStatuses::POISON
abilityscore*=2
end
elsif opponent.ability == PBAbilities::NORMALIZE
PBDebug.log(sprintf("Normalize Disrupt")) if $INTERNAL
abilityscore*=0.6
elsif opponent.ability == PBAbilities::MAGICGUARD
PBDebug.log(sprintf("Magic Guard Disrupt")) if $INTERNAL
abilityscore*=1.4
elsif opponent.ability == PBAbilities::STALL
PBDebug.log(sprintf("Stall Disrupt")) if $INTERNAL
abilityscore*=0.5
elsif opponent.ability == PBAbilities::TECHNICIAN
PBDebug.log(sprintf("Technician Disrupt")) if $INTERNAL
abilityscore*=1.3
elsif opponent.ability == PBAbilities::MOLDBREAKER
PBDebug.log(sprintf("Mold Breaker Disrupt")) if $INTERNAL
abilityscore*=1.1
elsif opponent.ability == PBAbilities::UNAWARE
PBDebug.log(sprintf("Unaware Disrupt")) if $INTERNAL
abilityscore*=1.7
elsif opponent.ability == PBAbilities::SLOWSTART
PBDebug.log(sprintf("Slow Start Disrupt")) if $INTERNAL
abilityscore*=0.3
elsif opponent.ability == PBAbilities::MULTITYPE || opponent.ability == PBAbilities::STANCECHANGE ||
opponent.ability == PBAbilities::SCHOOLING || opponent.ability == PBAbilities::SHIELDSDOWN ||
opponent.ability == PBAbilities::DISGUISE || opponent.ability == PBAbilities::RKSSYSTEM ||
opponent.ability == PBAbilities::POWERCONSTRUCT
PBDebug.log(sprintf("Multitype Disrupt")) if $INTERNAL
abilityscore*=0
elsif opponent.ability == PBAbilities::SHEERFORCE
PBDebug.log(sprintf("Sheer Force Disrupt")) if $INTERNAL
abilityscore*=1.2
elsif opponent.ability == PBAbilities::CONTRARY
PBDebug.log(sprintf("Contrary Disrupt")) if $INTERNAL
abilityscore*=1.4
if opponent.stages[PBStats::ATTACK]>0 || opponent.stages[PBStats::SPATK]>0 ||
opponent.stages[PBStats::DEFENSE]>0 || opponent.stages[PBStats::SPDEF]>0 ||
opponent.stages[PBStats::SPEED]>0
abilityscore*=2
end
elsif opponent.ability == PBAbilities::DEFEATIST
PBDebug.log(sprintf("Defeatist Disrupt")) if $INTERNAL
abilityscore*=0.5
elsif opponent.ability == PBAbilities::MULTISCALE
PBDebug.log(sprintf("Multiscale Disrupt")) if $INTERNAL
if opponent.hp==opponent.totalhp
abilityscore*=1.5
end
elsif opponent.ability == PBAbilities::HARVEST
PBDebug.log(sprintf("Harvest Disrupt")) if $INTERNAL
abilityscore*=1.2
elsif opponent.ability == PBAbilities::MOODY
PBDebug.log(sprintf("Moody Disrupt")) if $INTERNAL
abilityscore*=1.8
elsif opponent.ability == PBAbilities::SAPSIPPER
PBDebug.log(sprintf("Sap Sipper Disrupt")) if $INTERNAL
grassvar = false
totalgrass=true
grassmove=nil
for i in attacker.moves
if !(i.type == PBTypes::GRASS)
totalgrass=false
end
if (i.type == PBTypes::GRASS)
grassvar=true
grassmove=i
end
end
if grassvar
if totalgrass
abilityscore*=3
end
if pbTypeModNoMessages(grassmove.type,attacker,opponent,grassmove,skill)>4
abilityscore*=2
end
end
elsif opponent.ability == PBAbilities::PRANKSTER
PBDebug.log(sprintf("Prankster Disrupt")) if $INTERNAL
if attacker.speed>opponent.speed
abilityscore*=1.5
end
elsif opponent.ability == PBAbilities::SNOWCLOAK
PBDebug.log(sprintf("Snow Cloak Disrupt")) if $INTERNAL
if @weather==PBWeather::HAIL
abilityscore*=1.1
end
elsif opponent.ability == PBAbilities::FURCOAT
PBDebug.log(sprintf("Fur Coat Disrupt")) if $INTERNAL
if attacker.attack>attacker.spatk
abilityscore*=1.5
end
elsif opponent.ability == PBAbilities::PARENTALBOND
PBDebug.log(sprintf("Parental Bond Disrupt")) if $INTERNAL
abilityscore*=3
elsif opponent.ability == PBAbilities::PROTEAN
PBDebug.log(sprintf("Protean Disrupt")) if $INTERNAL
abilityscore*=3
elsif opponent.ability == PBAbilities::TOUGHCLAWS
PBDebug.log(sprintf("Tough Claws Disrupt")) if $INTERNAL
abilityscore*=1.2
elsif opponent.ability == PBAbilities::BEASTBOOST
PBDebug.log(sprintf("Beast Boost Disrupt")) if $INTERNAL
abilityscore*=1.1
elsif opponent.ability == PBAbilities::COMATOSE
PBDebug.log(sprintf("Comatose Disrupt")) if $INTERNAL
abilityscore*=1.3
elsif opponent.ability == PBAbilities::FLUFFY
PBDebug.log(sprintf("Fluffy Disrupt")) if $INTERNAL
abilityscore*=1.5
firevar = false
for i in attacker.moves
if (i.type == PBTypes::FIRE)
firevar=true
end
end
if firevar
abilityscore*=0.5
end
elsif opponent.ability == PBAbilities::MERCILESS
PBDebug.log(sprintf("Merciless Disrupt")) if $INTERNAL
abilityscore*=1.3
elsif opponent.ability == PBAbilities::WATERBUBBLE
PBDebug.log(sprintf("Water Bubble Disrupt")) if $INTERNAL
abilityscore*=1.5
firevar = false
for i in attacker.moves
if (i.type == PBTypes::FIRE)
firevar=true
end
end
if firevar
abilityscore*=1.3
end
elsif attacker.pbPartner==opponent
if abilityscore!=0
if abilityscore>200
abilityscore=200
end
tempscore = abilityscore
abilityscore = 200 - tempscore
end
end
abilityscore*=0.01
return abilityscore
end
def getFieldDisruptScore(attacker,opponent,skill)
fieldscore=100.0
aroles = pbGetMonRole(attacker,opponent,skill)
oroles = pbGetMonRole(opponent,attacker,skill)
aimem = getAIMemory(skill,opponent.pokemonIndex)
if $fefieldeffect==1 # Electric Terrain
PBDebug.log(sprintf("Electric Terrain Disrupt")) if $INTERNAL
if opponent.pbHasType?(:ELECTRIC) || opponent.pbPartner.pbHasType?(:ELECTRIC)
fieldscore*=1.5
end
if attacker.pbHasType?(:ELECTRIC)
fieldscore*=0.5
end
partyelec=false
for k in pbParty(attacker.index)
next if k.nil?
if k.hasType?(:ELECTRIC)
partyelec=true
end
end
if partyelec
fieldscore*=0.5
end
if (!opponent.abilitynulled && opponent.ability == PBAbilities::SURGESURFER)
fieldscore*=1.3
end
if (!attacker.abilitynulled && attacker.ability == PBAbilities::SURGESURFER)
fieldscore*=0.7
end
end
if $fefieldeffect==2 # Grassy Terrain
PBDebug.log(sprintf("Grassy Terrain Disrupt")) if $INTERNAL
if opponent.pbHasType?(:GRASS) || opponent.pbPartner.pbHasType?(:GRASS)
fieldscore*=1.5
end
if attacker.pbHasType?(:GRASS)
fieldscore*=0.5
end
if opponent.pbHasType?(:FIRE) || opponent.pbPartner.pbHasType?(:FIRE)
fieldscore*=1.8
end
if attacker.pbHasType?(:FIRE)
fieldscore*=0.2
end
partygrass=false
for k in pbParty(attacker.index)
next if k.nil?
if k.hasType?(:GRASS)
partygrass=true
end
end
if partygrass
fieldscore*=0.5
end
partyfire=false
for k in pbParty(attacker.index)
next if k.nil?
if k.hasType?(:FIRE)
partyfire=true
end
end
if partyfire
fieldscore*=0.2
end
if aroles.include?(PBMonRoles::SPECIALWALL) || aroles.include?(PBMonRoles::PHYSICALWALL)
fieldscore*=0.8
end
if oroles.include?(PBMonRoles::SPECIALWALL) || oroles.include?(PBMonRoles::PHYSICALWALL)
fieldscore*=1.2
end
end
if $fefieldeffect==3 # Misty Terrain
PBDebug.log(sprintf("Misty Terrain Disrupt")) if $INTERNAL
if attacker.spatk>attacker.attack
if opponent.pbHasType?(:FAIRY) || opponent.pbPartner.pbHasType?(:FAIRY)
fieldscore*=1.3
end
end
if opponent.spatk>opponent.attack
if attacker.pbHasType?(:FAIRY)
fieldscore*=0.7
end
end
if opponent.pbHasType?(:DRAGON) || opponent.pbPartner.pbHasType?(:DRAGON)
fieldscore*=0.5
end
if attacker.pbHasType?(:DRAGON)
fieldscore*=1.5
end
partyfairy=false
for k in pbParty(attacker.index)
next if k.nil?
if k.hasType?(:FAIRY)
partyfairy=true
end
end
if partyfairy
fieldscore*=0.7
end
partydragon=false
for k in pbParty(attacker.index)
next if k.nil?
if k.hasType?(:DRAGON)
partydragon=true
end
end
if partydragon
fieldscore*=1.5
end
if !(attacker.pbHasType?(:POISON) || attacker.pbHasType?(:STEEL))
if $fecounter==1
fieldscore*=1.8
end
end
end
if $fefieldeffect==37 # Psychic Terrain
PBDebug.log(sprintf("Psychic Terrain Disrupt")) if $INTERNAL
if opponent.pbHasType?(:PSYCHIC) || opponent.pbPartner.pbHasType?(:PSYCHIC)
fieldscore*=1.7
end
if attacker.pbHasType?(:PSYCHIC)
fieldscore*=0.3
end
partypsy=false
for k in pbParty(attacker.index)
next if k.nil?
if k.hasType?(:PSYCHIC)
partypsy=true
end
end
if partypsy
fieldscore*=0.3
end
if (!opponent.abilitynulled && opponent.ability == PBAbilities::TELEPATHY)
fieldscore*=1.3
end
if (!attacker.abilitynulled && attacker.ability == PBAbilities::TELEPATHY)
fieldscore*=0.7
end
end
fieldscore*=0.01
return fieldscore
end
# Used by all moves that raise the user's stat(s)
def setupminiscore(attacker,opponent,skill,move,sweep,code,double,initialscores,scoreindex)
aimem = getAIMemory(skill,opponent.pokemonIndex)
miniscore=100
#hi we are going in the comments for this one because it is in dire need of explanation
#up until this point, most of the key differences between different set up moves has
#been whether they are good for setting up to sweep or not.
#this is not the case past here.
#there are some really obnoxious differences between moves, and the way i'm dealing
#with it is through binary strings.
#this string is passed as a single number and is then processed by the function as such:
# 00001 = attack 00010 = defense 00100 = sp.attack 01000 = sp.defense 10000 = speed
#cosmic power would be 01010 in binary or 10 in normal, bulk up would be 00011 or 3, etc
#evasion has a code of 0
#this way new moves can be added and still use this function without any loss in
#the overall scoring precision of the AI
if initialscores.length>0
miniscore*=1.3 if hasbadmoves(initialscores,scoreindex,20)
end
if skill>=PBTrainerAI.mediumSkill
if aimem.length > 0
maxdam = checkAIdamage(aimem,attacker,opponent,skill)
if maxdam<(attacker.hp/4.0) && sweep
miniscore*=1.2
elsif maxdam<(attacker.hp/3.0) && !sweep
miniscore*=1.1
elsif maxdam<(attacker.hp/4.0) && code == 10
miniscore*=1.5
else
if move.basedamage==0
miniscore*=0.8
if maxdam>attacker.hp
miniscore*=0.1
end
end
end
else
if move.basedamage==0
effcheck = PBTypes.getCombinedEffectiveness(opponent.type1,attacker.type1,attacker.type2)
if effcheck > 4
miniscore*=0.5
end
effcheck2 = PBTypes.getCombinedEffectiveness(opponent.type2,attacker.type1,attacker.type2)
if effcheck2 > 4
miniscore*=0.5
end
end
end
end
if attacker.effects[PBEffects::Confusion]>0
if code & 0b1 == 0b1 #if move boosts attack
miniscore*=0.2
miniscore*=0.5 if double #using swords dance or shell smash while confused is Extra Bad
miniscore*=1.5 if code & 0b11 == 0b11 #adds a correction for moves that boost attack and defense
else
miniscore*=0.5
end
end
if !sweep
miniscore*=1.1 if opponent.status==PBStatuses::BURN && code & 0b1000 == 0b1000 #sp.def boosting
end
if checkAImoves(PBStuff::SWITCHOUTMOVE,aimem)
miniscore*=0.5 if sweep
miniscore*=0.2 if !sweep
miniscore*=1.5 if code == 0 #correction for evasion moves
end
=begin
if attacker.effects[PBEffects::Substitute]>0 || attacker.effects[PBEffects::Disguise]
miniscore*=1.3
end
if (attacker.hp.to_f)/attacker.totalhp<0.33
miniscore*=0.3
end
if (attacker.hp.to_f)/attacker.totalhp<0.75 &&
(!attacker.abilitynulled && (attacker.ability == PBAbilities::EMERGENCYEXIT || attacker.ability == PBAbilities::WIMPOUT) ||
(attacker.itemWorks? && attacker.item == PBItems::EJECTBUTTON))
miniscore*=0.3
end
if attacker.pbOpposingSide.effects[PBEffects::Retaliate]
miniscore*=0.3
end
if opponent.status==PBStatuses::SLEEP || opponent.status==PBStatuses::FROZEN
miniscore*=1.3
end
if (!attacker.abilitynulled && attacker.ability == PBAbilities::SIMPLE)
miniscore*=2
end
if (attacker.hp.to_f)/attacker.totalhp>0.75
miniscore*=1.2 if sweep
miniscore*=1.1 if !sweep
end
if opponent.effects[PBEffects::HyperBeam]>0
miniscore*=1.3 if sweep
miniscore*=1.2 if !sweep
end
if opponent.effects[PBEffects::Yawn]>0
miniscore*=1.7 if sweep
miniscore*=1.3 if !sweep
end
if attacker.turncount<2
miniscore*=1.2 if sweep
miniscore*=1.1 if !sweep
end
if opponent.status!=0
miniscore*=1.2 if sweep
miniscore*=1.1 if !sweep
end
if opponent.effects[PBEffects::Encore]>0
if opponent.moves[(opponent.effects[PBEffects::EncoreIndex])].basedamage==0
if sweep || code == 10 #cosmic power
miniscore*=1.5
else
miniscore*=1.3
end
end
end
sweep = false if code == 3 #from here on out, bulk up is not a sweep move
if attacker.effects[PBEffects::LeechSeed]>=0 || attacker.effects[PBEffects::Attract]>=0
miniscore*=0.6 if sweep
miniscore*=0.3 if !sweep
end
miniscore*=0.2 if attacker.effects[PBEffects::Toxic]>0 && !sweep
if @doublebattle
miniscore*=0.5
miniscore*=0.5 if !sweep #drop is doubled
end
=end
return miniscore
end
# General processing for stat-dropping moves
def unsetupminiscore(attacker,opponent,skill,move,roles,type,physical,greatmoves=false)
#attack stat = type 1 defense stat = type 2 speed = 3 evasion = no
miniscore = 100
aimem = getAIMemory(skill,opponent.pokemonIndex)
if type == 3 #speed stuff
if (pbRoughStat(opponent,PBStats::SPEED,skill)*0.66)<attacker.pbSpeed
if greatmoves
miniscore*=1.5 if greatmoves
else
miniscore*=1.1
end
end
else #non-speed stuff
count=-1
party=pbParty(attacker.index)
sweepvar=false
for i in 0...party.length
count+=1
next if (count==attacker.pokemonIndex || party[i].nil?)
temproles = pbGetMonRole(party[i],opponent,skill,count,party)
if temproles.include?(PBMonRoles::SWEEPER)
sweepvar=true
end
end
if sweepvar
miniscore*=1.1
end
end
if type == 2 #defense stuff
miniscore*=1.5 if checkAIhealing(aimem)
miniscore*=1.5 if move.function == 0x4C
else
if roles.include?(PBMonRoles::PHYSICALWALL) || roles.include?(PBMonRoles::SPECIALWALL)
miniscore*=1.3 if type == 1
miniscore*=1.1 if type == 3
end
end
livecount1=0
for i in pbParty(attacker.index)
next if i.nil?
livecount1+=1 if i.hp!=0
end
livecount2=0
for i in pbParty(opponent.index)
next if i.nil?
livecount2+=1 if i.hp!=0
end
if livecount2==1 || (!attacker.abilitynulled && attacker.ability == PBAbilities::SHADOWTAG) || opponent.effects[PBEffects::MeanLook]>0
miniscore*=1.4
end
#status section
if type == 2 || !physical
miniscore*=1.2 if opponent.status==PBStatuses::POISON || opponent.status==PBStatuses::BURN
elsif type == 1
miniscore*=1.2 if opponent.status==PBStatuses::POISON
miniscore*=0.5 if opponent.status==PBStatuses::BURN
end
#move checks
if type == 1 && physical
miniscore*=0.5 if attacker.pbHasMove?(PBMoves::FOULPLAY)
elsif type == 3
miniscore*=0.5 if attacker.pbHasMove?(PBMoves::GYROBALL)
miniscore*=1.5 if attacker.pbHasMove?(PBMoves::ELECTROBALL)
miniscore*=1.3 if checkAImoves([PBMoves::ELECTROBALL],aimem)
miniscore*=0.5 if checkAImoves([PBMoves::GYROBALL],aimem)
miniscore*=0.1 if @trickroom!=0 || checkAImoves([PBMoves::TRICKROOM],aimem)
end
#final things
if type == 3
miniscore*=0.1 if opponent.itemWorks? && (opponent.item == PBItems::LAGGINGTAIL || opponent.item == PBItems::IRONBALL)
miniscore*=0.2 if !opponent.abilitynulled && [PBAbilities::COMPETITIVE, PBAbilities::DEFIANT, PBAbilities::CONTRARY].include?(opponent.ability)
else
miniscore*=0.1 if !opponent.abilitynulled && [PBAbilities::UNAWARE, PBAbilities::COMPETITIVE, PBAbilities::DEFIANT, PBAbilities::CONTRARY].include?(opponent.ability)
end
if move.basedamage>0
miniscore-=100
if move.addlEffect.to_f != 100
miniscore*=(move.addlEffect.to_f/100)
if !attacker.abilitynulled && attacker.ability == PBAbilities::SERENEGRACE
miniscore*=2
end
end
miniscore+=100
else
if livecount1==1
miniscore*=0.5
end
if attacker.status!=0
miniscore*=0.7
end
end
miniscore /= 100
return miniscore
end
def hasgreatmoves(initialscores,scoreindex,skill)
#slight variance in precision based on trainer skill
threshold = 100
threshold = 105 if skill>=PBTrainerAI.highSkill
threshold = 110 if skill>=PBTrainerAI.bestSkill
for i in 0...initialscores.length
next if i==scoreindex
if initialscores[i]>=threshold
return true
end
end
return false
end
def hasbadmoves(initialscores,scoreindex,threshold)
for i in 0...initialscores.length
next if i==scoreindex
if initialscores[i]>threshold
return false
end
end
return false
end
def statchangecounter(mon,initial,final,limiter=0)
count = 0
case limiter
when 0 #all stats
for i in initial..final
count += mon.stages[i]
end
when 1 #increases only
for i in initial..final
count += mon.stages[i] if mon.stages[i]>0
end
when -1 #decreases only
for i in initial..final
count += mon.stages[i] if mon.stages[i]<0
end
end
return count
end
end

View File

@@ -1,327 +0,0 @@
=begin
class PokeBattle_Battle
def pbGetMonRole(mon,opponent,skill,position=0,party=nil)
#PBDebug.log(sprintf("Beginning role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
monRoles=[]
monability = mon.ability.to_i
curemove=false
healingmove=false
wishmove=false
phasemove=false
priorityko=false
pivotmove=false
spinmove=false
batonmove=false
tauntmove=false
restmove=false
weathermove=false
fieldmove=false
if mon.class == PokeBattle_Battler
if mon.ev[3]>251 && (mon.nature==PBNatures::MODEST ||
mon.nature==PBNatures::JOLLY || mon.nature==PBNatures::TIMID ||
mon.nature==PBNatures::ADAMANT) || (mon.item==(PBItems::CHOICEBAND) ||
mon.item==(PBItems::CHOICESPECS) || mon.item==(PBItems::CHOICESCARF))
monRoles.push(PBMonRoles::SWEEPER)
end
for i in mon.moves
next if i.nil?
next if i.id == 0
# Unused as only counts for REVENGEKILLER, which is only used if mon is
# a Pokémon and not a battler (used in switching calculation)
if i.priority>0
dam=pbRoughDamage(i,mon,opponent,skill,i.basedamage)
if opponent.hp>0
percentage=(dam*100.0)/opponent.hp
priorityko=true if percentage>100
end
end
if i.isHealingMove?
healingmove=true
elsif (i.id == (PBMoves::HEALBELL) || i.id == (PBMoves::AROMATHERAPY))
curemove=true
elsif (i.id == (PBMoves::WISH))
wishmove=true
elsif (i.id == (PBMoves::YAWN) || i.id == (PBMoves::PERISHSONG) ||
i.id == (PBMoves::DRAGONTAIL) || i.id == (PBMoves::CIRCLETHROW) ||
i.id == (PBMoves::WHIRLWIND) || i.id == (PBMoves::ROAR))
phasemove=true
elsif (i.id == (PBMoves::UTURN) || i.id == (PBMoves::VOLTSWITCH))
pivotmove=true
elsif (i.id == (PBMoves::RAPIDSPIN))
spinmove=true
elsif (i.id == (PBMoves::BATONPASS))
batonmove=true
elsif (i.id == (PBMoves::TAUNT))
tauntmove=true
elsif (i.id == (PBMoves::REST))
restmove=true
elsif (i.id == (PBMoves::SUNNYDAY) || i.id == (PBMoves::RAINDANCE) ||
i.id == (PBMoves::HAIL) || i.id == (PBMoves::SANDSTORM))
weathermove=true
elsif (i.id == (PBMoves::GRASSYTERRAIN) || i.id == (PBMoves::ELECTRICTERRAIN) ||
i.id == (PBMoves::MISTYTERRAIN) || i.id == (PBMoves::PSYCHICTERRAIN) ||
i.id == (PBMoves::MIST) || i.id == (PBMoves::IONDELUGE) ||
i.id == (PBMoves::TOPSYTURVY))
fieldmove=true
end
end
if healingmove && (mon.ev[2]>251 && (mon.nature==PBNatures::BOLD ||
mon.nature==PBNatures::RELAXED || mon.nature==PBNatures::IMPISH ||
mon.nature==PBNatures::LAX))
monRoles.push(PBMonRoles::PHYSICALWALL)
end
if healingmove && (mon.ev[5]>251 && (mon.nature==PBNatures::CALM ||
mon.nature==PBNatures::GENTLE || mon.nature==PBNatures::SASSY ||
mon.nature==PBNatures::CAREFUL))
monRoles.push(PBMonRoles::SPECIALWALL)
end
if mon.pokemonIndex==0
monRoles.push(PBMonRoles::LEAD)
end
if curemove || (wishmove && mon.ev[0]>251)
monRoles.push(PBMonRoles::CLERIC)
end
if phasemove == true
monRoles.push(PBMonRoles::PHAZER)
end
if mon.item==(PBItems::LIGHTCLAY)
monRoles.push(PBMonRoles::SCREENER)
end
# Unused
if priorityko || (mon.speed>opponent.speed)
monRoles.push(PBMonRoles::REVENGEKILLER)
end
if (pivotmove && healingmove) || (monability == PBAbilities::REGENERATOR)
monRoles.push(PBMonRoles::PIVOT)
end
if spinmove
monRoles.push(PBMonRoles::SPINNER)
end
if (mon.ev[0]>251 && !healingmove) || mon.item==(PBItems::ASSAULTVEST)
monRoles.push(PBMonRoles::TANK)
end
if batonmove
monRoles.push(PBMonRoles::BATONPASSER)
end
if tauntmove || mon.item==(PBItems::CHOICEBAND) ||
mon.item==(PBItems::CHOICESPECS)
monRoles.push(PBMonRoles::STALLBREAKER)
end
if restmove || (monability == PBAbilities::COMATOSE) ||
mon.item==(PBItems::TOXICORB) || mon.item==(PBItems::FLAMEORB) ||
(monability == PBAbilities::GUTS) ||
(monability == PBAbilities::QUICKFEET)||
(monability == PBAbilities::FLAREBOOST) ||
(monability == PBAbilities::TOXICBOOST) ||
(monability == PBAbilities::NATURALCURE) ||
(monability == PBAbilities::MAGICGUARD) ||
(monability == PBAbilities::MAGICBOUNCE) ||
((monability == PBAbilities::HYDRATION) && pbWeather==PBWeather::RAINDANCE)
monRoles.push(PBMonRoles::STATUSABSORBER)
end
if (monability == PBAbilities::SHADOWTAG) ||
(monability == PBAbilities::ARENATRAP) ||
(monability == PBAbilities::MAGNETPULL)
monRoles.push(PBMonRoles::TRAPPER)
end
if weathermove || (monability == PBAbilities::DROUGHT) ||
(monability == PBAbilities::SANDSTREAM) ||
(monability == PBAbilities::DRIZZLE) ||
(monability == PBAbilities::SNOWWARNING) ||
(monability == PBAbilities::PRIMORDIALSEA) ||
(monability == PBAbilities::DESOLATELAND) ||
(monability == PBAbilities::DELTASTREAM)
monRoles.push(PBMonRoles::WEATHERSETTER)
end
if fieldmove || (monability == PBAbilities::GRASSYSURGE) ||
(monability == PBAbilities::ELECTRICSURGE) ||
(monability == PBAbilities::MISTYSURGE) ||
(monability == PBAbilities::PSYCHICSURGE) ||
mon.item==(PBItems::AMPLIFIELDROCK)
monRoles.push(PBMonRoles::FIELDSETTER)
end
#if $game_switches[525] && mon.pokemonIndex==(pbParty(mon.index).length-1)
if mon.pokemonIndex==(pbParty(mon.index).length-1)
monRoles.push(PBMonRoles::ACE)
end
secondhighest=true
if pbParty(mon.index).length>2
for i in 0..(pbParty(mon.index).length-2)
next if pbParty(mon.index)[i].nil?
if mon.level<pbParty(mon.index)[i].level
secondhighest=false
end
end
end
#if $game_switches[525]&& secondhighest
if secondhighest
monRoles.push(PBMonRoles::SECOND)
end
#PBDebug.log(sprintf("Ending role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
#PBDebug.log(sprintf("")) if $INTERNAL
return monRoles
elsif mon.class == PokeBattle_Pokemon
movelist = []
for i in mon.moves
next if i.nil?
next if i.id == 0
movedummy = PokeBattle_Move.pbFromPBMove(self,i,mon)
movelist.push(movedummy)
end
if mon.ev[3]>251 && (mon.nature==PBNatures::MODEST ||
mon.nature==PBNatures::JOLLY || mon.nature==PBNatures::TIMID ||
mon.nature==PBNatures::ADAMANT) || (mon.item==(PBItems::CHOICEBAND) ||
mon.item==(PBItems::CHOICESPECS) || mon.item==(PBItems::CHOICESCARF))
monRoles.push(PBMonRoles::SWEEPER)
end
for i in movelist
next if i.nil?
if i.isHealingMove?
healingmove=true
elsif (i.id == (PBMoves::HEALBELL) || i.id == (PBMoves::AROMATHERAPY))
curemove=true
elsif (i.id == (PBMoves::WISH))
wishmove=true
elsif (i.id == (PBMoves::YAWN) || i.id == (PBMoves::PERISHSONG) ||
i.id == (PBMoves::DRAGONTAIL) || i.id == (PBMoves::CIRCLETHROW) ||
i.id == (PBMoves::WHIRLWIND) || i.id == (PBMoves::ROAR))
phasemove=true
elsif (i.id == (PBMoves::UTURN) || i.id == (PBMoves::VOLTSWITCH))
pivotmove=true
elsif (i.id == (PBMoves::RAPIDSPIN))
spinmove=true
elsif (i.id == (PBMoves::BATONPASS))
batonmove=true
elsif(i.id == (PBMoves::TAUNT))
tauntmove=true
elsif (i.id == (PBMoves::REST))
restmove=true
elsif (i.id == (PBMoves::SUNNYDAY) || i.id == (PBMoves::RAINDANCE) ||
i.id == (PBMoves::HAIL) || i.id == (PBMoves::SANDSTORM))
weathermove=true
elsif (i.id == (PBMoves::GRASSYTERRAIN) || i.id == (PBMoves::ELECTRICTERRAIN) ||
i.id == (PBMoves::MISTYTERRAIN) || i.id == (PBMoves::PSYCHICTERRAIN) ||
i.id == (PBMoves::MIST) || i.id == (PBMoves::IONDELUGE) ||
i.id == (PBMoves::TOPSYTURVY))
fieldmove=true
end
end
if healingmove && (mon.ev[2]>251 && (mon.nature==PBNatures::BOLD ||
mon.nature==PBNatures::RELAXED || mon.nature==PBNatures::IMPISH ||
mon.nature==PBNatures::LAX))
monRoles.push(PBMonRoles::PHYSICALWALL)
end
if healingmove && (mon.ev[5]>251 && (mon.nature==PBNatures::CALM ||
mon.nature==PBNatures::GENTLE || mon.nature==PBNatures::SASSY ||
mon.nature==PBNatures::CAREFUL))
monRoles.push(PBMonRoles::SPECIALWALL)
end
if position==0
monRoles.push(PBMonRoles::LEAD)
end
if curemove || (wishmove && mon.ev[0]>251)
monRoles.push(PBMonRoles::CLERIC)
end
if (phasemove)
monRoles.push(PBMonRoles::PHAZER)
end
if mon.item==(PBItems::LIGHTCLAY)
monRoles.push(PBMonRoles::SCREENER)
end
# pbRoughDamage does not take Pokemon objects, this will cause issues
priorityko=false
for i in movelist
next if i.priority<1
next if i.basedamage<10
priorityko=true
end
if priorityko || (mon.speed>opponent.speed)
monRoles.push(PBMonRoles::REVENGEKILLER)
end
if (pivotmove && healingmove) || (monability == PBAbilities::REGENERATOR)
monRoles.push(PBMonRoles::PIVOT)
end
if spinmove
monRoles.push(PBMonRoles::SPINNER)
end
if (mon.ev[0]>251 && !healingmove) || mon.item==(PBItems::ASSAULTVEST)
monRoles.push(PBMonRoles::TANK)
end
if batonmove
monRoles.push(PBMonRoles::BATONPASSER)
end
if tauntmove || mon.item==(PBItems::CHOICEBAND) ||
mon.item==(PBItems::CHOICESPECS)
monRoles.push(PBMonRoles::STALLBREAKER)
end
if restmove || (monability == PBAbilities::COMATOSE) ||
mon.item==(PBItems::TOXICORB) || mon.item==(PBItems::FLAMEORB) ||
(monability == PBAbilities::GUTS) ||
(monability == PBAbilities::QUICKFEET) ||
(monability == PBAbilities::FLAREBOOST) ||
(monability == PBAbilities::TOXICBOOST) ||
(monability == PBAbilities::NATURALCURE) ||
(monability == PBAbilities::MAGICGUARD) ||
(monability == PBAbilities::MAGICBOUNCE) ||
# TODO: Reference to the weather here.
((monability == PBAbilities::HYDRATION) && pbWeather==PBWeather::RAINDANCE)
monRoles.push(PBMonRoles::STATUSABSORBER)
end
if (monability == PBAbilities::SHADOWTAG) ||
(monability == PBAbilities::ARENATRAP) ||
(monability == PBAbilities::MAGNETPULL)
monRoles.push(PBMonRoles::TRAPPER)
end
if weathermove || (monability == PBAbilities::DROUGHT) ||
(monability == PBAbilities::SANDSTREAM) ||
(monability == PBAbilities::DRIZZLE) ||
(monability == PBAbilities::SNOWWARNING) ||
(monability == PBAbilities::PRIMORDIALSEA) ||
(monability == PBAbilities::DESOLATELAND) ||
(monability == PBAbilities::DELTASTREAM)
monRoles.push(PBMonRoles::WEATHERSETTER)
end
if fieldmove || (monability == PBAbilities::GRASSYSURGE) ||
(monability == PBAbilities::ELECTRICSURGE) ||
(monability == PBAbilities::MISTYSURGE) ||
(monability == PBAbilities::PSYCHICSURGE) ||
mon.item==(PBItems::AMPLIFIELDROCK)
monRoles.push(PBMonRoles::FIELDSETTER)
end
if position==(party.length-1)
#if $game_switches[525] && position==(party.length-1)
monRoles.push(PBMonRoles::ACE)
end
secondhighest=true
if party.length>2
for i in 0...(party.length-1)
next if party[i].nil?
if mon.level<party[i].level
secondhighest=false
end
end
end
#if $game_switches[525]&& secondhighest
if secondhighest
monRoles.push(PBMonRoles::SECOND)
end
#PBDebug.log(sprintf("Ending role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
#PBDebug.log(sprintf("")) if $INTERNAL
return monRoles
end
#PBDebug.log(sprintf("Ending role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
#PBDebug.log(sprintf("")) if $INTERNAL
return monRoles
end
end
=end

View File

@@ -233,6 +233,7 @@ class Scene_Map
if $game_temp.title_screen_calling
pbMapInterpreter.command_end if pbMapInterpreterRunning?
$game_temp.title_screen_calling = false
pbBGMFade(1.0)
Graphics.transition
Graphics.freeze
end

View File

@@ -47,7 +47,7 @@ class Window_UnformattedTextPokemon < SpriteWindow_Base
return ret
end
def resizeToFitInternal(text, maxwidth) # maxwidth is maximum acceptable window width
def resizeToFitInternal(text, maxwidth) # maxwidth is maximum acceptable window width
dims = [0, 0]
cwidth = maxwidth < 0 ? Graphics.width : maxwidth
getLineBrokenChunks(self.contents, text,
@@ -173,7 +173,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
moveCursor
end
def lineHeight(value)
def lineHeight=(value)
@lineHeight = value
self.text = self.text
end
@@ -296,7 +296,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
width = 1
height = 1
numlines = 0
visiblelines = (self.height - self.borderY) / 32
visiblelines = (self.height - self.borderY) / @lineHeight
if value.length == 0
@fmtchars = []
@bitmapwidth = width
@@ -307,7 +307,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
@fmtchars = []
fmt = getFormattedText(self.contents, 0, 0,
self.width - self.borderX - SpriteWindow_Base::TEXT_PADDING, -1,
shadowc3tag(@baseColor, @shadowColor) + value, 32, true)
shadowc3tag(@baseColor, @shadowColor) + value, @lineHeight, true)
@oldfont = self.contents.font.clone
fmt.each do |ch|
chx = ch[1] + ch[3]
@@ -334,7 +334,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
else
@fmtchars = getFormattedText(self.contents, 0, 0,
self.width - self.borderX - SpriteWindow_Base::TEXT_PADDING, -1,
shadowc3tag(@baseColor, @shadowColor) + value, 32, true)
shadowc3tag(@baseColor, @shadowColor) + value, @lineHeight, true)
@oldfont = self.contents.font.clone
@fmtchars.each do |ch|
chx = ch[1] + ch[3]

View File

@@ -61,7 +61,7 @@ class Battle::Battler
end
end
# Taunt
if @effects[PBEffects::Taunt] > 0 && move.statusMove?
if @effects[PBEffects::Taunt] > 0 && move.statusMove? && !specialUsage
if showMessages
msg = _INTL("{1} can't use {2} after the taunt!", pbThis, move.name)
(commandPhase) ? @battle.pbDisplayPaused(msg) : @battle.pbDisplay(msg)
@@ -69,7 +69,7 @@ class Battle::Battler
return false
end
# Torment
if @effects[PBEffects::Torment] && !@effects[PBEffects::Instructed] &&
if @effects[PBEffects::Torment] && !@effects[PBEffects::Instructed] && !specialUsage &&
@lastMoveUsed && move.id == @lastMoveUsed && move.id != @battle.struggle.id
if showMessages
msg = _INTL("{1} can't use the same move twice in a row due to the torment!", pbThis)

View File

@@ -536,6 +536,8 @@ end
# Power is also doubled if user has curled up. (Ice Ball, Rollout)
#===============================================================================
class Battle::Move::MultiTurnAttackPowersUpEachTurn < Battle::Move
def pbNumHits(user, targets); return 1; end
def pbBaseDamage(baseDmg, user, target)
shift = (5 - user.effects[PBEffects::Rollout]) # 0-4, where 0 is most powerful
shift = 0 if user.effects[PBEffects::Rollout] == 0 # For first turn

View File

@@ -756,6 +756,9 @@ end
#===============================================================================
# The target can no longer use the same move twice in a row. (Torment)
# NOTE: Torment is only supposed to start applying at the end of the round in
# which it is used, unlike Taunt which starts applying immediately. I've
# decided to make Torment apply immediately.
#===============================================================================
class Battle::Move::DisableTargetUsingSameMoveConsecutively < Battle::Move
def ignoresSubstitute?(user); return true; end