Added old AI references/rewrite attempt as references

This commit is contained in:
Maruno17
2022-08-09 19:35:45 +01:00
parent a20f378b33
commit eeeb9b3494
55 changed files with 57870 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
# 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

@@ -0,0 +1,182 @@
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

@@ -0,0 +1,182 @@
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

@@ -0,0 +1,286 @@
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

@@ -0,0 +1,838 @@
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

@@ -0,0 +1,797 @@
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

@@ -0,0 +1,228 @@
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

@@ -0,0 +1,375 @@
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

@@ -0,0 +1,498 @@
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

@@ -0,0 +1,409 @@
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

@@ -0,0 +1,661 @@
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

@@ -0,0 +1,108 @@
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

@@ -0,0 +1,154 @@
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

@@ -0,0 +1,495 @@
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

@@ -0,0 +1,832 @@
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

@@ -0,0 +1,121 @@
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

@@ -0,0 +1,308 @@
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