PokeBot/ai/strategies.lua

2013 lines
48 KiB
Lua
Raw Normal View History

2015-04-06 01:18:46 -07:00
local Strategies = {}
2014-07-12 18:47:39 -07:00
2015-04-06 01:18:46 -07:00
local Combat = require "ai.combat"
local Control = require "ai.control"
2014-07-12 18:47:39 -07:00
2015-04-06 01:18:46 -07:00
local Battle = require "action.battle"
local Textbox = require "action.textbox"
local Walk = require "action.walk"
2014-07-12 18:47:39 -07:00
2015-04-24 21:00:33 -07:00
local Data = require "data.data"
2015-04-06 01:18:46 -07:00
local Bridge = require "util.bridge"
local Input = require "util.input"
local Memory = require "util.memory"
local Menu = require "util.menu"
local Player = require "util.player"
2015-04-13 00:47:34 -07:00
local Shop = require "action.shop"
2015-04-06 01:18:46 -07:00
local Utils = require "util.utils"
2014-07-12 18:47:39 -07:00
2015-04-06 01:18:46 -07:00
local Inventory = require "storage.inventory"
local Pokemon = require "storage.pokemon"
2014-07-12 18:47:39 -07:00
local splitNumber, splitTime = 0, 0
2015-04-06 00:50:00 -07:00
local resetting
local status = {tries = 0, canProgress = nil, initialized = false}
local stats = {}
2015-04-06 01:18:46 -07:00
Strategies.status = status
Strategies.stats = stats
Strategies.updates = {}
2015-04-06 01:18:46 -07:00
Strategies.deepRun = false
2014-07-12 18:47:39 -07:00
local strategyFunctions
-- RISK/RESET
2014-07-12 18:47:39 -07:00
2015-04-06 01:18:46 -07:00
function Strategies.getTimeRequirement(name)
return Strategies.timeRequirements[name]()
end
2015-04-17 13:40:56 -07:00
function Strategies.hardReset(reason, message, extra, wait)
2014-07-12 18:47:39 -07:00
resetting = true
2015-04-17 13:40:56 -07:00
if Data.run.seed then
if extra then
2015-04-17 13:40:56 -07:00
extra = extra.." | "..Data.run.seed
else
2015-04-17 13:40:56 -07:00
extra = Data.run.seed
end
2014-07-12 18:47:39 -07:00
end
2015-04-17 13:40:56 -07:00
local map, px, py = Memory.value("game", "map"), Player.position()
2015-04-27 23:22:24 -07:00
Data.reset(reason, Control.areaName, map, px, py, stats)
2015-04-17 13:40:56 -07:00
Bridge.chat(message, false, extra)
2015-04-28 10:24:43 -07:00
if Strategies.deepRun then
p("", true)
p("", true)
p("", true)
end
2015-04-04 18:38:47 -07:00
if wait and INTERNAL and not STREAMING_MODE then
2015-04-06 00:50:00 -07:00
strategyFunctions.wait()
else
client.reboot_core()
2015-04-04 18:38:47 -07:00
end
2014-07-12 18:47:39 -07:00
return true
end
2015-04-17 13:40:56 -07:00
function Strategies.reset(reason, explanation, extra, wait)
2015-04-06 01:18:46 -07:00
local time = Utils.elapsedTime()
2015-04-10 02:17:35 -07:00
local resetMessage = "reset"
if time then
resetMessage = resetMessage.." after "..time
2014-07-12 18:47:39 -07:00
end
2015-04-10 02:17:35 -07:00
resetMessage = resetMessage.." at "..Control.areaName
2014-07-12 18:47:39 -07:00
local separator
2015-04-06 01:18:46 -07:00
if Strategies.deepRun and not Control.yolo then
2014-07-12 18:47:39 -07:00
separator = " BibleThump"
else
separator = ":"
end
2015-04-17 13:40:56 -07:00
resetMessage = resetMessage..separator.." "..explanation
2015-05-03 16:57:28 -07:00
2015-05-04 19:36:11 -07:00
if not Data.yellow and (Strategies.updates.misty or Strategies.updates.surge) and Strategies.deepRun then
Strategies.tweetProgress(Utils.capitalize(resetMessage))
end
2015-05-03 16:57:28 -07:00
2015-04-17 13:40:56 -07:00
return Strategies.hardReset(reason, resetMessage, extra, wait)
2014-07-12 18:47:39 -07:00
end
2015-04-06 01:18:46 -07:00
function Strategies.death(extra)
2015-04-17 13:40:56 -07:00
local reason, explanation
if Control.missed then
2015-04-17 13:40:56 -07:00
explanation = "Missed"
reason = "miss"
elseif Control.criticaled then
2015-04-17 13:40:56 -07:00
explanation = "Critical'd"
reason = "critical"
elseif Combat.sandAttacked() then
explanation = "Sand-Attack'd"
reason = "accuracy"
2015-05-04 19:36:11 -07:00
elseif Combat.isConfused() then
explanation = "Confusion'd"
reason = "confusion"
elseif Control.yolo then
2015-04-17 13:40:56 -07:00
explanation = "Yolo strats"
reason = "yolo"
2014-07-12 18:47:39 -07:00
else
2015-04-17 13:40:56 -07:00
explanation = "Died"
reason = "death"
2014-07-12 18:47:39 -07:00
end
2015-04-17 13:40:56 -07:00
return Strategies.reset(reason, explanation, extra)
2014-07-12 18:47:39 -07:00
end
2015-04-06 01:18:46 -07:00
function Strategies.overMinute(min)
if type(min) == "string" then
min = Strategies.getTimeRequirement(min)
end
return Utils.igt() > (min * 60)
2014-07-12 18:47:39 -07:00
end
function Strategies.resetTime(timeLimit, explanation, custom)
2015-04-06 01:18:46 -07:00
if Strategies.overMinute(timeLimit) then
if not custom then
explanation = "Took too long to "..explanation.."."
end
if RESET_FOR_TIME then
2015-04-17 13:40:56 -07:00
return Strategies.reset("time", explanation)
2014-07-12 18:47:39 -07:00
end
end
end
2015-04-24 21:34:49 -07:00
function Strategies.setYolo(name, forced)
2015-05-04 02:17:40 -07:00
if not forced and not RESET_FOR_TIME then
return false
end
2015-04-28 00:19:04 -07:00
local shouldYolo
if BEAST_MODE then
shouldYolo = true
else
local minimumTime = Strategies.getTimeRequirement(name)
shouldYolo = Strategies.overMinute(minimumTime)
end
2015-04-06 01:18:46 -07:00
if Control.yolo ~= shouldYolo then
Control.yolo = shouldYolo
Control.setYolo(shouldYolo)
2014-07-12 18:47:39 -07:00
local prefix
2015-04-06 01:18:46 -07:00
if Control.yolo then
2014-07-12 18:47:39 -07:00
prefix = "en"
else
prefix = "dis"
end
2015-04-06 01:18:46 -07:00
print("YOLO "..prefix.."abled at "..Control.areaName)
2014-07-12 18:47:39 -07:00
end
2015-04-06 01:18:46 -07:00
return Control.yolo
2014-07-12 18:47:39 -07:00
end
2015-04-06 00:50:00 -07:00
-- HELPERS
function Strategies.tweetProgress(message, progress)
if progress then
Strategies.updates[progress] = true
2015-05-04 02:17:40 -07:00
message = message.." Pokemon "..Utils.capitalize(Data.gameName).." http://www.twitch.tv/thepokebot"
end
Bridge.tweet(message)
2015-05-03 16:57:28 -07:00
return true
end
function Strategies.initialize(once)
if not once then
once = "initialized"
2015-04-18 19:51:32 -07:00
end
if not status[once] then
status[once] = true
return true
end
end
2014-07-12 18:47:39 -07:00
function Strategies.chat(once, message)
if Strategies.initialize(once) then
Bridge.chat(message)
end
end
2015-05-07 01:25:27 -07:00
function Strategies.canHealFor(damage, allowAlreadyHealed, disableFullRestore)
2015-05-04 19:36:11 -07:00
if type(damage) == "string" then
damage = Combat.healthFor(damage)
end
2015-04-26 16:31:07 -07:00
local curr_hp, max_hp = Combat.hp(), Combat.maxHP()
2015-05-07 01:25:27 -07:00
if allowAlreadyHealed and curr_hp > damage then
return true
end
2015-04-04 18:37:48 -07:00
if max_hp - curr_hp > 3 then
2015-05-07 01:25:27 -07:00
local healChecks = {"super_potion", "potion"}
if not disableFullRestore then
table.insert(healChecks, 1, "full_restore")
end
2015-04-04 18:37:48 -07:00
for idx,potion in ipairs(healChecks) do
2015-04-06 01:18:46 -07:00
if Inventory.contains(potion) and Utils.canPotionWith(potion, damage, curr_hp, max_hp) then
2015-04-04 18:37:48 -07:00
return potion
end
end
end
end
2015-04-06 01:18:46 -07:00
function Strategies.hasHealthFor(opponent, extra)
if not extra then
2014-07-12 18:47:39 -07:00
extra = 0
end
2015-04-26 16:31:07 -07:00
local afterHealth = math.min(Combat.hp() + extra, Combat.maxHP())
2015-04-10 00:34:50 -07:00
return afterHealth > Combat.healthFor(opponent)
2014-07-12 18:47:39 -07:00
end
2015-04-06 01:18:46 -07:00
function Strategies.damaged(factor)
if not factor then
2014-07-12 18:47:39 -07:00
factor = 1
end
2015-04-26 16:31:07 -07:00
return Combat.hp() * factor < Combat.maxHP()
2014-07-12 18:47:39 -07:00
end
function Strategies.trainerBattle()
local battleStatus = Memory.value("game", "battle")
if battleStatus > 0 then
if battleStatus == 2 then
Strategies.initialize("foughtTrainer")
return true
end
Battle.handleWild(battleStatus)
2015-04-23 10:25:20 -07:00
else
Textbox.handle()
end
end
2015-04-13 00:47:34 -07:00
local function interact(direction, extended)
2015-04-11 14:03:44 -07:00
if Battle.handleWild() then
if Battle.isActive() then
return true
end
if Textbox.isActive() then
if status.interacted then
return true
end
Input.cancel()
else
2015-04-13 00:47:34 -07:00
if Player.interact(direction, extended) then
2015-04-11 14:03:44 -07:00
status.interacted = true
end
end
end
end
2015-04-06 01:18:46 -07:00
function Strategies.buffTo(buff, defLevel)
if Strategies.trainerBattle() then
2014-07-12 18:47:39 -07:00
local forced
if not Battle.opponentDamaged() then
2015-05-01 11:12:48 -07:00
if defLevel and Memory.double("battle", "opponent_defense") > defLevel then
forced = buff
end
2014-07-12 18:47:39 -07:00
end
2015-04-06 01:18:46 -07:00
Battle.automate(forced, true)
elseif status.foughtTrainer then
2014-07-12 18:47:39 -07:00
return true
end
end
2015-04-06 01:18:46 -07:00
function Strategies.dodgeUp(npc, sx, sy, dodge, offset)
if not Battle.handleWild() then
2014-07-12 18:47:39 -07:00
return false
end
2015-04-06 01:18:46 -07:00
local px, py = Player.position()
if py < sy - 1 then
2014-07-12 18:47:39 -07:00
return true
end
local wx, wy = px, py
if py < sy then
2014-07-12 18:47:39 -07:00
wy = py - 1
elseif px == sx or px == dodge then
2015-04-06 01:18:46 -07:00
if px - Memory.raw(npc) == offset then
if px == sx then
2014-07-12 18:47:39 -07:00
wx = dodge
else
wx = sx
end
else
wy = py - 1
end
end
2015-04-06 01:18:46 -07:00
Walk.step(wx, wy)
2014-07-12 18:47:39 -07:00
end
local function dodgeSideways(options)
2014-07-12 18:47:39 -07:00
local left = 1
if options.left then
2014-07-12 18:47:39 -07:00
left = -1
end
2015-04-06 01:18:46 -07:00
local px, py = Player.position()
if px * left > (options.sx + (options.dist or 1)) * left then
2014-07-12 18:47:39 -07:00
return true
end
local wx, wy = px, py
if px * left > options.sx * left then
2014-07-12 18:47:39 -07:00
wx = px + 1 * left
elseif py == options.sy or py == options.dodge then
if px + left == options.npcX and py - Memory.raw(options.npc) == options.offset then
if py == options.sy then
2014-07-12 18:47:39 -07:00
wy = options.dodge
else
wy = options.sy
end
else
wx = px + 1 * left
end
end
2015-04-06 01:18:46 -07:00
Walk.step(wx, wy)
2014-07-12 18:47:39 -07:00
end
2015-04-06 01:18:46 -07:00
function Strategies.completedMenuFor(data)
2015-05-03 00:14:47 -07:00
if status.cancel then
return true
end
2015-04-06 01:18:46 -07:00
local count = Inventory.count(data.item)
2015-05-07 01:25:27 -07:00
if count == 0 or (not data.all and status.startCount and count < status.startCount) then
2014-07-12 18:47:39 -07:00
return true
end
return false
end
2015-04-06 01:18:46 -07:00
function Strategies.closeMenuFor(data)
if (not status.menuOpened and not data.close) or data.chain then
2015-05-03 00:14:47 -07:00
if Menu.onPokemonSelect() or Menu.hasTextbox() then
Input.press("B")
return false
end
2014-07-12 18:47:39 -07:00
return true
end
return Menu.close()
2014-07-12 18:47:39 -07:00
end
2015-04-06 01:18:46 -07:00
function Strategies.useItem(data)
if not status.startCount then
status.startCount = Inventory.count(data.item)
2014-07-12 18:47:39 -07:00
end
2015-04-06 01:18:46 -07:00
if Strategies.completedMenuFor(data) then
2015-05-03 00:14:47 -07:00
return Strategies.closeMenuFor(data)
end
if Menu.pause() then
status.menuOpened = true
Inventory.use(data.item, data.poke)
2014-07-12 18:47:39 -07:00
end
end
function Strategies.tossItem(...)
if not status.startCount then
status.startCount = Inventory.count()
elseif Inventory.count() < status.startCount then
return true
end
local tossItem = Inventory.contains(...)
2015-04-16 12:23:02 -07:00
if not tossItem then
p("Nothing available to toss", ...)
return true
end
if tossItem ~= status.toss then
status.toss = tossItem
p("Tossing "..tossItem.." to make space", Inventory.count())
end
if not Inventory.useItemOption(tossItem, nil, 1) then
if Menu.pause() then
Input.press("A")
end
end
end
2014-07-12 18:47:39 -07:00
local function completedSkillFor(data)
if data.map then
2015-04-06 01:18:46 -07:00
if data.map ~= Memory.value("game", "map") then
2014-07-12 18:47:39 -07:00
return true
end
elseif data.x or data.y then
2015-04-06 01:18:46 -07:00
local px, py = Player.position()
if data.x == px or data.y == py then
2014-07-12 18:47:39 -07:00
return true
end
elseif data.done then
2015-04-06 01:18:46 -07:00
if Memory.raw(data.done) > (data.val or 0) then
2014-07-12 18:47:39 -07:00
return true
end
elseif status.tries > 0 and not Menu.isOpened() then
2014-07-12 18:47:39 -07:00
return true
end
return false
end
2015-04-06 01:18:46 -07:00
function Strategies.isPrepared(...)
if not status.preparing then
return false
2014-07-12 18:47:39 -07:00
end
for i,name in ipairs(arg) do
2015-04-06 01:18:46 -07:00
local currentCount = Inventory.count(name)
if currentCount > 0 then
local previousCount = status.preparing[name]
if previousCount == nil or currentCount == previousCount then
2014-07-12 18:47:39 -07:00
return false
end
end
end
return true
end
2015-04-06 01:18:46 -07:00
function Strategies.prepare(...)
if not status.preparing then
status.preparing = {}
2014-07-12 18:47:39 -07:00
end
local item
for idx,name in ipairs(arg) do
2015-04-06 01:18:46 -07:00
local currentCount = Inventory.count(name)
local needsItem = currentCount > 0
local previousCount = status.preparing[name]
if previousCount == nil then
status.preparing[name] = currentCount
elseif needsItem then
needsItem = currentCount == previousCount
end
if needsItem then
item = name
break
2014-07-12 18:47:39 -07:00
end
end
if not item then
return true
end
2015-04-06 01:18:46 -07:00
if Battle.isActive() then
Inventory.use(item, nil, true)
2014-07-12 18:47:39 -07:00
else
2015-04-06 01:18:46 -07:00
Input.cancel()
2014-07-12 18:47:39 -07:00
end
end
function Strategies.getsSilphCarbosSpecially()
return Data.yellow and stats.nidoran.speedDV >= 11
end
function Strategies.needsCarbosAtLeast(count)
local speedDV = stats.nidoran.speedDV
local carbosRequired = 0
if Data.yellow then
if speedDV <= 8 then
carbosRequired = 3
elseif speedDV <= 10 then
carbosRequired = 2
else
carbosRequired = 1
end
else
if speedDV <= 6 then
carbosRequired = 3
elseif speedDV <= 7 then
carbosRequired = 2
elseif speedDV <= 9 then
carbosRequired = 1
end
end
return count <= carbosRequired
end
local function nidokingStats()
local att = Pokemon.index(0, "attack")
local def = Pokemon.index(0, "defense")
local spd = Pokemon.index(0, "speed")
local scl = Pokemon.index(0, "special")
local statDesc = att.." "..def.." "..spd.." "..scl
2015-04-16 12:34:13 -07:00
local attDV, defDV, spdDV, sclDV = Pokemon.getDVs("nidoking")
stats.nidoran = {
attack = att,
defense = def,
speed = spd,
special = scl,
level4 = stats.nidoran.level4,
rating = stats.nidoran.rating,
2015-04-16 12:34:13 -07:00
attackDV = attDV,
defenseDV = defDV,
2015-04-16 12:34:13 -07:00
speedDV = spdDV,
specialDV = sclDV,
}
Combat.factorPP(false)
2015-05-03 21:08:28 -07:00
Combat.setDisableThrash(false)
2015-04-16 12:34:13 -07:00
p(attDV, defDV, spdDV, sclDV)
print(statDesc)
Bridge.stats(statDesc)
end
2015-04-12 11:26:52 -07:00
function Strategies.completeCans()
local px, py = Player.position()
if px == 4 and py == 6 then
2015-04-29 16:01:33 -07:00
local trashcanTries = status.tries + 1
local timeLimit = Strategies.getTimeRequirement("trash") + 1
if Combat.inRedBar() then
timeLimit = timeLimit + 0.5
end
2015-04-12 11:26:52 -07:00
local prefix
local suffix = "!"
2015-04-29 16:01:33 -07:00
if trashcanTries <= 1 then
2015-04-12 11:26:52 -07:00
prefix = "PERFECT"
2015-04-29 16:01:33 -07:00
elseif trashcanTries <= (Data.yellow and 2 or 3) then
2015-04-12 11:26:52 -07:00
prefix = "Amazing"
2015-04-29 16:01:33 -07:00
elseif trashcanTries <= (Data.yellow and 4 or 6) then
2015-04-12 11:26:52 -07:00
prefix = "Great"
2015-04-29 16:01:33 -07:00
elseif trashcanTries <= (Data.yellow and 6 or 9) then
2015-04-12 11:26:52 -07:00
prefix = "Good"
2015-04-29 16:01:33 -07:00
elseif trashcanTries <= (Data.yellow and 10 or 22) then
2015-04-12 11:26:52 -07:00
prefix = "Ugh"
2015-04-17 14:26:35 -07:00
suffix = "."
2015-04-12 11:26:52 -07:00
else -- TODO trashcans WR
prefix = "Reset me now"
suffix = " BibleThump"
end
2015-04-29 16:01:33 -07:00
Bridge.chat(" "..prefix..", "..trashcanTries.." try Trashcans"..suffix)
Bridge.trashResults(trashcanTries)
2015-04-30 12:58:46 -07:00
if Strategies.resetTime(timeLimit, "complete Trashcans") then
2015-04-29 16:01:33 -07:00
return true
end
Strategies.setYolo("trash")
2015-04-12 11:26:52 -07:00
return true
end
local completePath = {
Down = {{2,11}, {8,7}},
Right = {{2,12}, {3,12}, {1,6}, {2,6}, {3,6}},
Left = {{9,8}, {8,8}, {7,8}, {6,8}, {5,8}, {9,10}, {8,10}, {7,10}, {6,10}, {5,10}, {}, {}, {}, {}, {}, {}},
}
local walkIn = "Up"
for dir,tileset in pairs(completePath) do
for i,tile in ipairs(tileset) do
if px == tile[1] and py == tile[2] then
walkIn = dir
break
end
end
end
Input.press(walkIn, 0)
end
2015-04-06 00:50:00 -07:00
-- GENERALIZED STRATEGIES
2014-07-12 18:47:39 -07:00
2015-04-06 01:18:46 -07:00
Strategies.functions = {
2014-07-12 18:47:39 -07:00
2015-05-03 00:14:47 -07:00
tweetMisty = function()
Strategies.setYolo("misty")
2015-05-04 19:36:11 -07:00
if not Strategies.updates.brock and not Control.yolo and (not Combat.inRedBar() or Inventory.contains("potion")) then
2015-05-03 00:14:47 -07:00
local timeLimit = Strategies.getTimeRequirement("misty")
if not Strategies.overMinute(timeLimit) then
local pbn = ""
if not Data.yellow and not Strategies.overMinute(timeLimit - 1) then
pbn = " (PB pace)"
end
local elt = Utils.elapsedTime()
Strategies.tweetProgress("Got a run going, just beat Misty "..elt.." in"..pbn, "misty")
end
end
return true
end,
tweetVictoryRoad = function()
local elt = Utils.elapsedTime()
local pbn = ""
if not Strategies.overMinute("victory_road") then
pbn = " (PB pace)"
end
local elt = Utils.elapsedTime()
2015-05-03 16:57:28 -07:00
Strategies.tweetProgress("Entering Victory Road at "..elt..pbn.." on our way to the Elite Four in", "victory")
return true
end,
2015-04-15 01:46:09 -07:00
bicycle = function()
if Memory.value("player", "bicycle") == 1 then
if Menu.close() then
return true
end
else
return Strategies.useItem({item="bicycle"})
end
end,
2014-07-12 18:47:39 -07:00
startFrames = function()
2015-04-06 01:18:46 -07:00
Strategies.frames = 0
2014-07-12 18:47:39 -07:00
return true
end,
reportFrames = function()
2015-04-06 01:18:46 -07:00
print("FR "..Strategies.frames)
local repels = Memory.value("player", "repel")
if repels > 0 then
2014-07-12 18:47:39 -07:00
print("S "..repels)
end
2015-04-06 01:18:46 -07:00
Strategies.frames = nil
2014-07-12 18:47:39 -07:00
return true
end,
split = function(data)
2015-04-17 13:40:56 -07:00
Data.increment("reset_split")
2015-04-06 01:18:46 -07:00
Bridge.split(data and data.finished)
if Strategies.replay or not INTERNAL then
splitNumber = splitNumber + 1
local timeDiff
2015-04-06 01:18:46 -07:00
splitTime, timeDiff = Utils.timeSince(splitTime)
if timeDiff then
2015-04-06 01:18:46 -07:00
print(splitNumber..". "..Control.areaName..": "..Utils.elapsedTime().." ("..timeDiff..")")
end
end
2014-07-12 18:47:39 -07:00
return true
end,
interact = function(data)
2015-05-03 16:57:28 -07:00
return interact(data.dir, data.long)
2015-04-11 14:03:44 -07:00
end,
talk = function(data)
2015-04-13 00:47:34 -07:00
return interact(data.dir, data.long)
2015-04-11 14:03:44 -07:00
end,
take = function(data)
2015-05-03 16:57:28 -07:00
return interact(data.dir, data.long)
2014-07-12 18:47:39 -07:00
end,
confirm = function(data)
2015-04-06 01:18:46 -07:00
if Battle.handleWild() then
if Textbox.isActive() then
2015-04-11 14:03:44 -07:00
status.talked = true
2015-04-06 01:18:46 -07:00
Input.cancel(data.type or "A")
2014-07-12 18:47:39 -07:00
else
2015-04-11 14:03:44 -07:00
if status.talked then
2014-07-12 18:47:39 -07:00
return true
end
2015-04-11 14:03:44 -07:00
Player.interact(data.dir, false)
2014-07-12 18:47:39 -07:00
end
end
end,
item = function(data)
2015-04-06 01:18:46 -07:00
if Battle.handleWild() then
2015-05-03 00:14:47 -07:00
if status.cancel or data.full and not Inventory.isFull() then
return Strategies.closeMenuFor(data)
2014-07-12 18:47:39 -07:00
end
2015-04-15 01:47:18 -07:00
if not status.checked and data.item ~= "carbos" and not Inventory.contains(data.item) then
print("No "..data.item.." available!")
end
2015-04-15 01:47:18 -07:00
status.checked = true
2015-04-06 01:18:46 -07:00
return Strategies.useItem(data)
2014-07-12 18:47:39 -07:00
end
end,
potion = function(data)
2015-05-03 00:14:47 -07:00
if not status.cancel then
local curr_hp = Combat.hp()
if curr_hp == 0 then
return false
end
local toHP
if Control.yolo and data.yolo ~= nil then
toHP = data.yolo
2014-07-12 18:47:39 -07:00
else
2015-05-03 00:14:47 -07:00
toHP = data.hp
end
if type(toHP) == "string" then
toHP = Combat.healthFor(toHP)
end
toHP = math.min(toHP, Combat.maxHP())
local toHeal = toHP - curr_hp
if toHeal > 0 then
local toPotion
if data.forced then
toPotion = Inventory.contains(data.forced)
2014-07-12 18:47:39 -07:00
else
2015-05-03 00:14:47 -07:00
local p_first, p_second, p_third
if toHeal > 50 then
if data.full then
p_first = "full_restore"
else
p_first = "super_potion"
end
p_second, p_third = "super_potion", "potion"
2014-07-12 18:47:39 -07:00
else
2015-05-03 00:14:47 -07:00
if toHeal > 20 then
p_first, p_second = "super_potion", "potion"
else
p_first, p_second = "potion", "super_potion"
end
if data.full then
p_third = "full_restore"
end
2014-07-12 18:47:39 -07:00
end
2015-05-03 00:14:47 -07:00
toPotion = Inventory.contains(p_first, p_second, p_third)
2014-07-12 18:47:39 -07:00
end
2015-05-03 00:14:47 -07:00
if toPotion then
if Menu.pause() then
Inventory.use(toPotion)
status.menuOpened = true
end
return false
2014-07-12 18:47:39 -07:00
end
2015-05-03 00:14:47 -07:00
--TODO report wanted potion
2014-07-12 18:47:39 -07:00
end
end
2015-04-06 01:18:46 -07:00
if Strategies.closeMenuFor(data) then
2014-07-12 18:47:39 -07:00
return true
end
end,
teach = function(data)
2015-05-07 01:27:26 -07:00
if Strategies.initialize("teaching") then
if not status.cancel then
status.cancel = data.full and not Inventory.isFull()
end
2014-07-12 18:47:39 -07:00
end
2015-05-03 00:14:47 -07:00
2014-07-12 18:47:39 -07:00
local itemName
if data.item then
2014-07-12 18:47:39 -07:00
itemName = data.item
else
itemName = data.move
end
2015-05-03 00:14:47 -07:00
if not status.cancel then
if Pokemon.hasMove(data.move) then
if data.chain and Memory.value("menu", "main") == 128 then
2014-07-12 18:47:39 -07:00
return true
end
2015-05-03 00:14:47 -07:00
status.cancel = true
2014-07-12 18:47:39 -07:00
else
2015-05-04 19:36:11 -07:00
local teachTo = data.poke
2015-05-03 00:14:47 -07:00
if Strategies.initialize("triedTeaching") then
if not Inventory.contains(itemName) then
2015-05-04 19:36:11 -07:00
local errorMessage = "Unable to teach move "..itemName
if teachTo and type(teachTo) == "string" then
errorMessage = errorMessage.." to "..teachTo
end
return Strategies.reset("error", errorMessage, nil, true)
2015-05-03 00:14:47 -07:00
end
end
local replacement
if data.replace then
2015-05-04 19:36:11 -07:00
replacement = Pokemon.moveIndex(data.replace, teachTo) - 1
2015-05-03 00:14:47 -07:00
else
replacement = 0
end
2015-05-04 19:36:11 -07:00
if Inventory.teach(itemName, teachTo, replacement) then
2015-05-03 00:14:47 -07:00
status.menuOpened = true
else
Menu.pause()
end
2014-07-12 18:47:39 -07:00
end
end
2015-05-03 00:14:47 -07:00
if status.cancel then
return Strategies.closeMenuFor(data)
end
2014-07-12 18:47:39 -07:00
end,
skill = function(data)
if completedSkillFor(data) then
2015-04-24 21:00:33 -07:00
if Data.yellow then
if not Menu.hasTextbox() then
return true
end
else
if not Menu.isOpened() then
return true
end
2014-07-12 18:47:39 -07:00
end
2015-04-06 01:18:46 -07:00
Input.press("B")
elseif not data.dir or Player.face(data.dir) then
if Pokemon.use(data.move) then
2015-04-06 00:50:00 -07:00
status.tries = status.tries + 1
2015-04-24 21:00:33 -07:00
elseif Data.yellow and Menu.hasTextbox() then
2015-05-03 00:14:47 -07:00
Textbox.handle()
2014-07-12 18:47:39 -07:00
else
2015-04-06 01:18:46 -07:00
Menu.pause()
2014-07-12 18:47:39 -07:00
end
end
end,
fly = function(data)
2015-04-06 01:18:46 -07:00
if Memory.value("game", "map") == data.map then
2014-07-12 18:47:39 -07:00
return true
end
local cities = {
pallet = {62, "Up"},
viridian = {63, "Up"},
lavender = {66, "Down"},
celadon = {68, "Down"},
fuchsia = {69, "Down"},
cinnabar = {70, "Down"},
2015-04-13 00:47:34 -07:00
saffron = {72, "Down"},
2014-07-12 18:47:39 -07:00
}
2015-04-06 01:18:46 -07:00
local main = Memory.value("menu", "main")
2015-04-24 21:00:33 -07:00
if main == (Data.yellow and 144 or 228) then
2015-04-13 00:47:34 -07:00
local currentCity = Memory.value("game", "fly")
2014-07-12 18:47:39 -07:00
local destination = cities[data.dest]
local press
2015-04-13 00:47:34 -07:00
if destination[1] - currentCity == 0 then
2014-07-12 18:47:39 -07:00
press = "A"
else
press = destination[2]
end
2015-04-06 01:18:46 -07:00
Input.press(press)
elseif not Pokemon.use("fly") then
Menu.pause()
2014-07-12 18:47:39 -07:00
end
end,
swap = function(data)
if not status.firstIndex then
local itemIndex = data.item
if type(data.item) == "string" then
itemIndex = Inventory.indexOf(data.item)
status.checkItem = data.item
end
local destIndex = data.dest
if type(data.dest) == "string" then
destIndex = Inventory.indexOf(data.dest)
status.checkItem = data.dest
end
if destIndex < itemIndex then
status.firstIndex = destIndex
status.lastIndex = itemIndex
else
status.firstIndex = destIndex
status.lastIndex = itemIndex
end
status.startedAt = Inventory.indexOf(status.checkItem)
end
local swapComplete
if status.firstIndex == status.lastIndex then
swapComplete = true
elseif status.firstIndex < 0 or status.lastIndex < 0 then
swapComplete = true
2015-04-18 19:51:32 -07:00
if Strategies.initialize("swapUnavailable") then
p("Not available to swap", data.item, data.dest, itemIndex, destIndex)
end
elseif status.startedAt ~= Inventory.indexOf(status.checkItem) then
swapComplete = true
end
if swapComplete then
2015-05-03 00:14:47 -07:00
return Strategies.closeMenuFor(data)
end
local main = Memory.value("menu", "main")
if main == 128 then
if Menu.getCol() ~= 5 then
Menu.select(2, true)
else
local selection = Memory.value("menu", "selection_mode")
if selection == 0 then
if Menu.select(status.firstIndex, "accelerate", true, nil, true) then
Input.press("Select")
end
else
2015-05-03 00:14:47 -07:00
if Menu.select(status.lastIndex, "accelerate", true, nil, true) then
Input.press("Select")
end
end
end
2015-05-03 00:14:47 -07:00
else
Menu.pause()
end
2014-07-12 18:47:39 -07:00
end,
2015-05-03 00:14:47 -07:00
acquire = function(data)
Bridge.caught(data.poke)
return true
end,
swapMove = function(data)
return Battle.swapMove(data.move, data.to)
end,
2015-04-06 00:50:00 -07:00
wait = function()
print("Please save state")
Input.press("Start", 999999999)
2015-04-06 00:50:00 -07:00
end,
2014-07-12 18:47:39 -07:00
waitToTalk = function()
2015-04-06 01:18:46 -07:00
if Battle.isActive() then
status.canProgress = false
2015-04-06 01:18:46 -07:00
Battle.automate()
elseif Textbox.isActive() then
status.canProgress = true
2015-04-06 01:18:46 -07:00
Input.cancel()
elseif status.canProgress then
2014-07-12 18:47:39 -07:00
return true
end
end,
waitToPause = function()
if Menu.pause() then
return true
end
end,
waitToFight = function(data)
if Battle.isActive() then
status.canProgress = true
Battle.automate()
elseif status.canProgress then
return true
elseif Textbox.handle() then
if data.dir then
Player.interact(data.dir, false)
else
Input.cancel()
end
end
end,
2014-07-12 18:47:39 -07:00
allowDeath = function(data)
2015-04-06 01:18:46 -07:00
Control.canDie(data.on)
2014-07-12 18:47:39 -07:00
return true
end,
2015-04-07 04:58:18 -07:00
leer = function(data)
local bm = Combat.bestMove()
if not bm or bm.minTurns < 3 then
if Strategies.trainerBattle() then
Battle.automate(data.forced)
elseif status.foughtTrainer then
2015-04-07 04:58:18 -07:00
return true
end
return false
end
local opp = Battle.opponent()
local defLimit = 9001
for i,poke in ipairs(data) do
if opp == poke[1] then
local minimumAttack = poke[3]
if not minimumAttack or stats.nidoran.attack > minimumAttack then
2015-04-07 04:58:18 -07:00
defLimit = poke[2]
end
break
end
end
return Strategies.buffTo("leer", defLimit)
end,
2015-04-13 00:47:34 -07:00
fightX = function(data)
return Strategies.prepare("x_"..data.x)
end,
2015-04-06 00:50:00 -07:00
-- ROUTE
2014-07-12 18:47:39 -07:00
2015-04-07 04:58:18 -07:00
swapNidoran = function()
local main = Memory.value("menu", "main")
local nidoranIndex = Pokemon.indexOf("nidoran")
if nidoranIndex == 0 then
if Menu.close() then
return true
end
elseif Menu.pause() then
2015-04-24 21:00:33 -07:00
if Data.yellow then
2015-04-07 04:58:18 -07:00
if Inventory.contains("potion") and Pokemon.info("nidoran", "hp") < 15 then
Inventory.use("potion", "nidoran")
return false
end
else
if Combat.isPoisoned("squirtle")then
2015-04-07 04:58:18 -07:00
Inventory.use("antidote", "squirtle")
return false
end
if Inventory.contains("potion") and Pokemon.info("squirtle", "hp") < 15 then
Inventory.use("potion", "squirtle")
return false
end
end
local column = Menu.getCol()
if main == 128 then
if column == 11 then
Menu.select(1, true)
elseif column == 12 then
Menu.select(1, true)
else
Input.press("B")
end
elseif main == Menu.pokemon then
local selectIndex
2015-04-07 04:58:18 -07:00
if Memory.value("menu", "selection_mode") == 1 then
selectIndex = nidoranIndex
2015-04-07 04:58:18 -07:00
else
selectIndex = 0
2015-04-07 04:58:18 -07:00
end
Pokemon.select(selectIndex)
2015-04-07 04:58:18 -07:00
else
Input.press("B")
end
end
end,
2014-07-12 18:47:39 -07:00
dodgePalletBoy = function()
2015-04-06 01:18:46 -07:00
return Strategies.dodgeUp(0x0223, 14, 14, 15, 7)
2014-07-12 18:47:39 -07:00
end,
checkNidoranStats = function()
local nidx = Pokemon.indexOf("nidoran")
if Pokemon.index(nidx, "level") < 8 then
return false
end
2015-05-04 19:36:11 -07:00
if not Data.yellow and status.tries < 300 then
status.tries = status.tries + 1
return false
end
local att = Pokemon.index(nidx, "attack")
local def = Pokemon.index(nidx, "defense")
local spd = Pokemon.index(nidx, "speed")
local scl = Pokemon.index(nidx, "special")
2015-04-30 12:58:46 -07:00
local attDV, defDV, spdDV, sclDV = Pokemon.getDVs("nidoran")
2015-05-03 00:14:47 -07:00
local level4 = not Data.yellow and stats.nidoran.level4
stats.nidoran = {
attack = att,
defense = def,
speed = spd,
special = scl,
2015-05-03 00:14:47 -07:00
level4 = level4,
rating = 0,
2015-04-30 12:58:46 -07:00
attackDV = attDV,
defenseDV = defDV,
speedDV = spdDV,
specialDV = sclDV,
}
Bridge.stats(att.." "..def.." "..spd.." "..scl)
Bridge.chat("is checking Nidoran's stats at level 8... "..att.." attack, "..def.." defense, "..spd.." speed, "..scl.." special.")
local resetsForStats = att < 15 or spd < 14 or scl < 12
2015-05-04 02:17:40 -07:00
local restrictiveStats = not Data.yellow and RESET_FOR_TIME
if not resetsForStats and restrictiveStats then
resetsForStats = att == 15 and spd == 14
end
if resetsForStats then
local nidoranStatus
if att < 15 and spd < 14 and scl < 12 then
nidoranStatus = Utils.random {
"let's just forget this ever happened.",
"I hate everything BibleThump",
"perfect stats Kappa",
"there's always the next one...",
"worst possible stats.",
}
else
2015-05-04 02:17:40 -07:00
if restrictiveStats and att == 15 and spd == 14 then
nidoranStatus = Utils.append(nidoranStatus, "unrunnable attack/speed combination", ", ")
else
if att < 15 then
nidoranStatus = Utils.append(nidoranStatus, "unrunnable attack", ", ")
end
if spd < 14 then
nidoranStatus = Utils.append(nidoranStatus, "unrunnable speed", ", ")
end
end
if scl < 12 then
nidoranStatus = Utils.append(nidoranStatus, "unrunnable special", ", ")
end
end
if not nidoranStatus then
nidoranStatus = "unrunnabled"
end
return Strategies.reset("stats", "Bad Nidoran - "..nidoranStatus)
end
status.tries = 9001
local statDiff = (16 - att) + (15 - spd) + (13 - scl)
if def < 12 then
statDiff = statDiff + 1
end
2015-05-04 02:17:40 -07:00
if not Data.yellow and not stats.nidoran.level4 then
statDiff = statDiff + 1
end
stats.nidoran.rating = statDiff
local superlative
local exclaim = "!"
if statDiff == 0 then
superlative = " perfect"
exclaim = "! Kreygasm"
elseif att == 16 and spd == 15 then
if statDiff == 1 then
superlative = " great"
else
superlative = " good"
end
2015-05-04 19:36:11 -07:00
elseif statDiff <= ((restrictiveStats or Data.yellow) and 3 or 4) then
superlative = "n okay"
exclaim = "."
else
superlative = " min stat"
exclaim = "."
end
local message
if Data.yellow then
2015-05-03 21:08:28 -07:00
message = "caught"
else
message = "beat Brock with"
end
2015-05-03 00:14:47 -07:00
message = message.." a"..superlative.." Nidoran"..exclaim
2015-05-04 19:36:11 -07:00
if Data.yellow then
message = message.." On "..(Strategies.vaporeon and "Vaporeon" or "Flareon").." strats."
else
2015-05-03 00:14:47 -07:00
message = message.." Caught at level "..(stats.nidoran.level4 and "4" or "3").."."
end
2015-04-28 09:35:33 -07:00
if BEAST_MODE then
p("", true)
p("", true)
end
Bridge.chat(message)
return true
end,
2015-04-07 04:58:18 -07:00
evolveNidorino = function()
if Pokemon.inParty("nidorino") then
Bridge.caught("nidorino")
return true
end
if Battle.isActive() then
status.tries = 0
status.canProgress = true
if not Battle.opponentAlive() then
2015-04-07 04:58:18 -07:00
Input.press("A")
else
Battle.automate()
end
elseif status.tries > 3600 then
print("Broke from Nidorino on tries")
return true
else
if status.canProgress then
status.tries = status.tries + 1
end
Input.press("A")
end
end,
catchFlierBackup = function()
if Strategies.initialize() then
2015-04-29 14:15:10 -07:00
Bridge.moonGuesses(true)
2015-04-07 04:58:18 -07:00
Control.canDie(true)
end
if not Control.canCatch() then
return true
end
local caught = Pokemon.inParty("pidgey", "spearow")
if Battle.isActive() then
if Memory.double("battle", "our_hp") == 0 then
local sacrifice = Pokemon.getSacrifice("squirtle", "pikachu")
if not sacrifice then
2015-04-07 04:58:18 -07:00
Control.canDie(false)
elseif Menu.onPokemonSelect() then
Pokemon.select(sacrifice)
2015-04-07 04:58:18 -07:00
else
Input.press("A")
end
else
Battle.handle()
end
else
local birdPath
local px, py = Player.position()
if caught then
if px > 33 then
return true
end
local startY = 9
if px > 28 then
startY = py
end
birdPath = {{32,startY}, {32,11}, {34,11}}
elseif px == 37 then
if py == 10 then
py = 11
else
py = 10
end
Walk.step(px, py)
else
birdPath = {{32,10}, {32,11}, {34,11}, {34,10}, {37,10}}
end
if birdPath then
Walk.custom(birdPath)
end
end
end,
evolveNidoking = function(data)
if Battle.handleWild() then
local usedMoonStone = not Inventory.contains("moon_stone")
2015-04-07 04:58:18 -07:00
if Strategies.initialize() then
if data.early then
if not Control.getMoonExp then
return true
end
if data.poke then
if stats.nidoran.attack > 15 or not Pokemon.inParty(data.poke) then
return true
end
end
if data.exp and Pokemon.getExp() > data.exp then
return true
end
2015-04-07 04:58:18 -07:00
end
end
if usedMoonStone then
if Strategies.initialize("evolved") then
2015-04-07 04:58:18 -07:00
Bridge.caught("nidoking")
end
if Strategies.closeMenuFor(data) then
2015-04-07 04:58:18 -07:00
return true
end
elseif not Inventory.use("moon_stone") then
Menu.pause()
status.menuOpened = true
2015-04-07 04:58:18 -07:00
end
end
end,
2015-04-30 12:55:38 -07:00
fightGrimer = function()
if Strategies.trainerBattle() then
if Combat.isDisabled("horn_attack") and Strategies.initialize("disabled") then
local message = Utils.random {
"Last for 0 turns pretty please?",
2015-05-01 11:12:48 -07:00
"Guess it's time to tackle everything.",
2015-04-30 12:55:38 -07:00
"How could this... happen to me?",
}
2015-05-01 11:12:48 -07:00
Bridge.chat("WutFace Grimer just disabled Horn Attack. "..message)
2015-04-30 12:55:38 -07:00
end
Battle.automate()
elseif status.foughtTrainer then
return true
end
end,
2015-04-06 00:50:00 -07:00
helix = function()
2015-04-06 01:18:46 -07:00
if Battle.handleWild() then
if Inventory.contains("helix_fossil") then
return true
end
2015-04-11 14:03:44 -07:00
Player.interact("Up", false)
2014-07-12 18:47:39 -07:00
end
end,
2015-04-07 04:58:18 -07:00
reportMtMoon = function()
if Battle.pp("horn_attack") == 0 then
print("ERR: Ran out of Horn Attacks")
end
2015-04-17 13:40:56 -07:00
local moonEncounters = Data.run.encounters_moon
if moonEncounters then
2015-05-03 16:57:28 -07:00
local cutterStatus
2015-04-07 04:58:18 -07:00
local conjunction = "but"
2015-04-17 13:40:56 -07:00
local goodEncounters = moonEncounters < 10
2015-05-03 16:57:28 -07:00
local caughtCutter = Pokemon.inParty("paras", "sandshrew")
2015-04-07 04:58:18 -07:00
local catchDescription
2015-04-29 14:15:10 -07:00
if caughtCutter then
2015-05-03 16:57:28 -07:00
catchDescription = caughtCutter
2015-04-07 04:58:18 -07:00
if goodEncounters then
conjunction = "and"
end
2015-05-03 16:57:28 -07:00
cutterStatus = "we caught a "..Utils.capitalize(caughtCutter).."!"
2015-04-07 04:58:18 -07:00
else
2015-05-03 16:57:28 -07:00
local catchPokemon = Data.yellow and "sandshrew" or "paras"
2015-04-07 04:58:18 -07:00
catchDescription = "no_"..catchPokemon
if not goodEncounters then
conjunction = "and"
end
2015-05-03 16:57:28 -07:00
cutterStatus = "we didn't catch a "
if Data.yellow then
cutterStatus = cutterStatus.."cutter"
else
cutterStatus = cutterStatus..Utils.capitalize(catchPokemon).." :("
end
2015-04-07 04:58:18 -07:00
end
Bridge.caught(catchDescription)
2015-05-03 16:57:28 -07:00
Bridge.chat(moonEncounters.." Moon encounters, "..conjunction.." "..cutterStatus)
2015-04-29 14:15:10 -07:00
Bridge.moonResults(moonEncounters, caughtCutter)
2015-04-07 04:58:18 -07:00
end
Strategies.resetTime("mt_moon", "complete Mt. Moon")
2015-04-07 04:58:18 -07:00
return true
end,
dodgeCerulean = function(data)
local left = data.left
return dodgeSideways {
2015-04-06 00:50:00 -07:00
npc = 0x0242,
npcX = 15,
sx = (left and 16 or 14), sy = 18,
dodge = (left and 17 or 19),
2015-04-06 00:50:00 -07:00
offset = 10,
dist = (left and -7 or 4),
left = left
2015-04-06 00:50:00 -07:00
}
2014-07-12 18:47:39 -07:00
end,
rareCandyEarly = function(data)
if Strategies.initialize() then
2015-04-15 01:47:18 -07:00
if Pokemon.info("nidoking", "level") ~= 20 then
2015-05-03 00:13:38 -07:00
status.cancel = true
else
if Data.yellow then
p("RCE", Pokemon.getExp())
end
status.cancel = Pokemon.getExp() > 5550
end
end
2015-05-07 01:27:26 -07:00
data.poke = "nidoking"
data.item = "rare_candy"
data.all = true
return strategyFunctions.item(data)
end,
2015-05-03 00:13:38 -07:00
teachThrash = function(data)
if Strategies.initialize() then
2015-05-07 01:27:26 -07:00
if Pokemon.info("nidoking", "level") ~= 21 or not Inventory.contains("rare_candy") then
2015-05-03 00:13:38 -07:00
status.cancel = true
else
status.updateStats = true
end
end
2015-05-03 00:13:38 -07:00
2015-05-07 01:27:26 -07:00
data.move = "thrash"
data.poke = "nidoking"
data.item = "rare_candy"
data.replace = Data.yellow and "tackle" or "leer"
data.all = true
if strategyFunctions.teach(data) then
if status.updateStats then
nidokingStats()
end
return true
end
end,
learnThrash = function()
if Strategies.initialize() then
if Pokemon.info("nidoking", "level") ~= 22 then
return true
end
end
if Strategies.trainerBattle() then
if Pokemon.moveIndex("thrash", "nidoking") then
nidokingStats()
return true
end
local settingsRow = Memory.value("menu", "settings_row")
if settingsRow == 8 then
local column = Memory.value("menu", "column")
if column == 15 then
Input.press("A")
return false
end
if column == 5 then
2015-04-24 21:00:33 -07:00
local replacementMove = Data.yellow and "tackle" or "leer"
local replaceIndex = Pokemon.moveIndex(replacementMove, "nidoking")
if replaceIndex then
Menu.select(replaceIndex - 1, true)
else
Input.cancel()
end
return false
end
end
Battle.automate()
elseif status.foughtTrainer then
return true
end
end,
swapThrash = function()
if not Battle.isActive() then
if Textbox.handle() and status.canProgress then
return true
end
else
status.canProgress = true
return Battle.swapMove("thrash", 0)
end
end,
2015-04-18 19:58:47 -07:00
lassEther = function()
if Strategies.initialize() then
2015-04-24 21:00:33 -07:00
if Data.yellow then
if not Strategies.vaporeon or not Strategies.getsSilphCarbosSpecially() then
2015-04-18 19:58:47 -07:00
return true
end
2015-05-06 21:50:03 -07:00
if Inventory.containsAll("pokeball", "potion") then
2015-04-18 19:58:47 -07:00
return true
end
else
2015-05-06 21:50:03 -07:00
if Inventory.containsAll("antidote", "elixer") then
2015-04-18 19:58:47 -07:00
return true
end
end
end
2015-05-07 01:27:26 -07:00
return interact("Up")
end,
talkToBill = function()
if Textbox.isActive() then
return true
end
return interact("Up")
2015-04-18 19:58:47 -07:00
end,
jingleSkip = function()
if status.canProgress then
local px, py = Player.position()
if px < 4 then
return true
end
Input.press("Left", 0)
else
2015-05-03 00:14:47 -07:00
Input.press("A", 2)
status.canProgress = true
end
end,
2015-04-29 16:01:33 -07:00
guessTrashcans = function(data)
Bridge.trashGuesses(data.enabled)
return true
end,
2015-04-18 19:56:32 -07:00
epicCutscene = function()
Bridge.chatRandom(
2015-04-18 19:56:32 -07:00
" CUTSCENE HYPE!",
" Please, sit back and enjoy the cutscene.",
"is enjoying the scenery Kappa b",
2015-04-26 16:36:05 -07:00
" Wait, is it too late to get Mew from under the truck??",
2015-04-18 19:56:32 -07:00
" Cutscenes DansGame",
2015-04-26 16:36:05 -07:00
" Your regularly scheduled run will continue in just a moment. Thank you for your patience.",
2015-04-18 19:56:32 -07:00
" Guys I think the game softlocked Kappa",
" Perfect, I needed a quick bathroom break.",
2015-04-26 16:36:05 -07:00
" *yawn*",
" :z",
" I think that ship broke the ocean.",
" Ah, lovely weather in Vermilion City this time of year, isn't it?",
" As a devout practicing member of the Church of Going Fast, I find the depiction of this unskippable cutscene offensive, frankly.",
" Anyone else feel cheated we didn't actually get to ride to some far off land in that boat?"
)
2015-04-18 19:56:32 -07:00
return true
end,
announceFourTurn = function()
2015-04-28 10:02:21 -07:00
Bridge.chat("needs to 4-turn Thrash, or hit through Confusion (each a 1 in 2 chance) to beat this dangerous trainer...")
return true
end,
announceOddish = function()
if Strategies.trainerBattle() then
if Pokemon.isOpponent("oddish") then
local __, turnsToKill = Combat.bestMove()
if turnsToKill and turnsToKill > 1 and Strategies.initialize() then
Bridge.chat("needs a good damage range to 1-shot this Oddish, which can paralyze.")
end
end
Battle.automate()
elseif status.foughtTrainer then
return true
end
end,
2015-04-13 00:47:34 -07:00
shopTM07 = function()
return Shop.transaction {
direction = "Up",
buy = {{name="horn_drill", index=3}}
}
end,
shopRepels = function()
2015-04-24 21:00:33 -07:00
local repelCount = Data.yellow and 10 or 9
2015-04-13 00:47:34 -07:00
return Shop.transaction {
direction = "Up",
buy = {{name="super_repel", index=3, amount=repelCount}}
}
end,
shopPokeDoll = function()
return Shop.transaction {
direction = "Down",
buy = {{name="pokedoll", index=0}}
}
end,
shopVending = function()
return Shop.vend {
direction = "Up",
buy = {{name="fresh_water", index=0}, {name="soda_pop", index=1}}
}
end,
giveWater = function()
if not Inventory.contains("fresh_water", "soda_pop") then
return true
end
if Textbox.isActive() then
Input.cancel("A")
else
local cx, cy = Memory.raw(0x0223) - 3, Memory.raw(0x0222) - 3
local px, py = Player.position()
if Utils.dist(cx, cy, px, py) == 1 then
Player.interact(Walk.dir(px, py, cx, cy))
else
Walk.step(cx, cy)
end
end
end,
shopExtraWater = function()
return Shop.vend {
direction = "Up",
buy = {{name="fresh_water", index=0}}
}
end,
digFight = function()
if Strategies.initialize() then
if Combat.inRedBar() then
2015-04-17 14:26:35 -07:00
Bridge.chat("is using Rock Slide to one-hit these Ghastlies in red-bar (each is 1 in 10 to miss).")
2015-04-13 00:47:34 -07:00
end
end
if Strategies.trainerBattle() then
2015-04-13 00:47:34 -07:00
local currentlyDead = Memory.double("battle", "our_hp") == 0
if currentlyDead then
local backupPokemon = Pokemon.getSacrifice("paras", "squirtle", "sandshrew", "charmander")
2015-04-13 00:47:34 -07:00
if not backupPokemon then
return Strategies.death()
end
Strategies.chat("died", " Rock Slide missed BibleThump Trying to finish them off with Dig...")
2015-04-13 00:47:34 -07:00
if Menu.onPokemonSelect() then
Pokemon.select(backupPokemon)
2015-04-13 00:47:34 -07:00
else
Input.press("A")
end
else
Battle.automate()
end
elseif status.foughtTrainer then
2015-04-13 00:47:34 -07:00
return true
end
end,
pokeDoll = function()
if Battle.isActive() then
status.canProgress = true
-- {s="swap",item="potion",dest="x_special",chain=true}, --TODO yellow
Inventory.use("pokedoll", nil, true)
elseif status.canProgress then
return true
else
Input.cancel()
end
end,
silphElevator = function()
if Menu.isOpened() then
2015-04-13 00:47:34 -07:00
status.canProgress = true
Menu.select(9, false, true)
else
if status.canProgress then
return true
end
Player.interact("Up")
end
end,
silphCarbos = function()
if Strategies.initialize() then
local skipCarbos = not Strategies.needsCarbosAtLeast(2)
if not skipCarbos then
Bridge.chat(" This Nidoking has bad speed, so we need the extra Carbos here.")
elseif Strategies.getsSilphCarbosSpecially() then
skipCarbos = false
end
if skipCarbos then
return true
end
end
return strategyFunctions.interact({dir="Left"})
end,
2015-04-13 00:47:34 -07:00
playPokeFlute = function()
if Battle.isActive() then
return true
end
if Menu.hasTextbox() then
Input.cancel()
2015-04-06 01:18:46 -07:00
elseif Menu.pause() then
Inventory.use("pokeflute")
2014-07-12 18:47:39 -07:00
end
end,
2015-04-06 00:50:00 -07:00
push = function(data)
local pos
if data.dir == "Up" or data.dir == "Down" then
pos = data.y
else
pos = data.x
2014-07-12 18:47:39 -07:00
end
2015-04-06 01:18:46 -07:00
local newP = Memory.raw(pos)
if not status.startPosition then
status.startPosition = newP
elseif status.startPosition ~= newP then
2014-07-12 18:47:39 -07:00
return true
end
2015-04-06 01:18:46 -07:00
Input.press(data.dir, 0)
2014-07-12 18:47:39 -07:00
end,
2015-04-13 00:47:34 -07:00
drivebyRareCandy = function()
if Textbox.isActive() then
status.canProgress = true
Input.cancel()
elseif status.canProgress then
return true
else
local px, py = Player.position()
if py < 13 then
status.tries = 0
return
end
if py == 13 and status.tries % 2 == 0 then
Input.press("A", 2)
else
Input.press("Up")
status.tries = 0
end
status.tries = status.tries + 1
end
end,
safariCarbos = function()
if Strategies.initialize() then
Strategies.setYolo("safari_carbos")
status.carbos = Inventory.count("carbos")
2015-04-30 13:14:47 -07:00
if not Strategies.needsCarbosAtLeast(3) then
2015-04-30 13:14:47 -07:00
return true
end
Bridge.chat(" This Nidoking has bad speed, so we'll need to go out of our way for the extra Carbos here.")
2015-04-13 00:47:34 -07:00
end
if Inventory.count("carbos") ~= status.carbos then
if Walk.step(20, 20) then
return true
end
else
local px, py = Player.position()
if px < 21 then
Walk.step(21, py)
elseif px == 21 and py == 13 then
Player.interact("Left")
else
Walk.step(21, 13)
end
end
end,
2015-04-16 12:23:02 -07:00
tossInSafari = function()
if Inventory.count() <= (Inventory.contains("full_restore") and 18 or 17) then
2015-04-18 19:58:47 -07:00
if Strategies.closeMenuFor({close=true}) then
return true
end
2015-04-18 21:07:00 -07:00
return false
2015-04-18 19:58:47 -07:00
end
if Inventory.contains("carbos") then
return strategyFunctions.item({item="carbos",poke="nidoking",close=true})
2015-04-16 12:23:02 -07:00
end
return Strategies.tossItem("antidote", "tm34", "pokeball")
end,
2015-04-13 00:47:34 -07:00
centerSkipFullRestore = function()
if Strategies.initialize() then
if Control.yolo or Inventory.contains("full_restore") then
return true
end
2015-04-17 14:26:35 -07:00
Bridge.chat("needs to grab the backup Full Restore here.")
2015-04-13 00:47:34 -07:00
end
local px, py = Player.position()
if px < 21 then
px = 21
elseif py < 9 then
py = 9
else
2015-04-14 14:48:39 -07:00
return strategyFunctions.interact({dir="Down"})
2015-04-13 00:47:34 -07:00
end
Walk.step(px, py)
end,
dodgeGirl = function()
local gx, gy = Memory.raw(0x0223) - 5, Memory.raw(0x0222)
local px, py = Player.position()
if py > gy then
if px > 3 then
px = 3
else
return true
end
elseif gy - py ~= 1 or px ~= gx then
py = py + 1
elseif px == 3 then
px = 2
else
px = 3
end
Walk.step(px, py)
end,
cinnabarCarbos = function()
2015-04-30 13:14:47 -07:00
local minDV = Data.yellow and 11 or 10
local skipsCarbos = not Strategies.needsCarbosAtLeast(Data.yellow and 2 or 1)
2015-04-30 13:14:47 -07:00
if Strategies.initialize() then
status.startCount = Inventory.count("carbos")
if not skipsCarbos then
Bridge.chat(" This Nidoking has mediocre speed, so we'll need to pick up the extra Carbos here.")
end
end
2015-04-13 00:47:34 -07:00
local px, py = Player.position()
if px == 21 then
return true
end
2015-04-30 13:14:47 -07:00
if skipsCarbos then
px, py = 21, 20
2015-04-13 00:47:34 -07:00
else
if py == 20 then
py = 21
elseif px == 17 and Inventory.count("carbos") == status.startCount then
2015-04-13 00:47:34 -07:00
Player.interact("Right")
return false
else
px = 21
end
end
Walk.step(px, py)
end,
checkEther = function()
if Data.yellow then
Strategies.maxEtherSkip = Strategies.requiresE4Center()
else -- TODO don't skip center if not in redbar?
Strategies.maxEtherSkip = not Strategies.requiresE4Center()
end
if not Strategies.maxEtherSkip then
2015-04-17 14:26:35 -07:00
Bridge.chat("is grabbing the Max Ether to skip the Elite 4 Center.")
end
return true
end,
ether = function(data)
local main = Memory.value("menu", "main")
data.item = status.item
if status.item and Strategies.completedMenuFor(data) then
if Strategies.closeMenuFor(data) then
return true
end
else
if not status.item then
if data.max and Strategies.maxEtherSkip then
return true
end
status.item = Inventory.contains("ether", "max_ether", "elixer")
if not status.item then
if Strategies.closeMenuFor(data) then
return true
end
print("No Ether - "..Control.areaName)
return false
end
end
if status.item == "elixer" then
2015-05-07 01:23:50 -07:00
data.item = "elixer"
data.poke = "nidoking"
return Strategies.useItem(data)
end
if Memory.value("menu", "main") == 144 and Menu.getCol() == 5 then
if Menu.hasTextbox() then
Input.cancel()
else
Menu.select(Pokemon.battleMove("horn_drill"), true)
end
elseif Menu.pause() then
Inventory.use(status.item, "nidoking")
status.menuOpened = true
end
end
end,
tossInVictoryRoad = function()
if Strategies.initialize() then
if Strategies.maxEtherSkip then
return true
end
2015-05-04 19:17:54 -07:00
if Inventory.ppRestoreCount() >= 2 then
return true
end
end
2015-04-16 12:23:02 -07:00
return Strategies.tossItem("antidote", "tm34", "pokeball")
end,
grabMaxEther = function()
if Strategies.initialize() then
2015-05-04 19:17:54 -07:00
if Strategies.maxEtherSkip and Inventory.ppRestoreCount() >= 2 then
return true
end
if Inventory.isFull() then
return true
end
end
if Inventory.contains("max_ether") then
return true
end
local px, py = Player.position()
if px > 7 then
2015-04-17 13:40:56 -07:00
return Strategies.reset("error", "Accidentally walked on the island :(", px, true)
end
if Memory.value("player", "moving") == 0 then
Player.interact("Right")
end
end,
2015-05-07 01:23:50 -07:00
potionBeforeLorelei = function(data)
if Strategies.initialize() then
if Strategies.requiresE4Center() then
return true
end
2015-05-07 01:23:50 -07:00
if not Strategies.canHealFor("LoreleiDewgong", true) then
return true
end
Bridge.chat("is healing before Lorelei to skip the Elite 4 Center...")
end
2015-05-07 01:23:50 -07:00
data.hp = Combat.healthFor("LoreleiDewgong")
return strategyFunctions.potion(data)
end,
centerSkip = function()
if Strategies.initialize() then
Strategies.setYolo("e4center")
if not Strategies.requiresE4Center() then
local message
if Data.yellow then
2015-05-07 01:22:42 -07:00
message = "has enough HP to skip the Center. "..Utils.random {
"Let's do this!",
"Let's go!",
2015-05-07 01:22:42 -07:00
"What could go wrong now?",
"No crits!",
}
else
message = "is skipping the Center and attempting to red-bar "
if Strategies.hasHealthFor("LoreleiDewgong") then
message = message.."off Lorelei..."
else
message = message.."the Elite 4!"
end
end
Bridge.chat(message)
return true
end
2015-05-07 01:22:42 -07:00
Bridge.chat("is taking the Center to heal for Lorelei.")
end
return strategyFunctions.confirm({dir="Up"})
end,
prepareForLance = function()
local enableFull
if Strategies.hasHealthFor("LanceGyarados", 100) then
enableFull = Inventory.count("super_potion") < 2
elseif Strategies.hasHealthFor("LanceGyarados", 50) then
enableFull = not Inventory.contains("super_potion")
else
enableFull = true
end
local min_recovery = Combat.healthFor("LanceGyarados")
if not Control.yolo then
min_recovery = min_recovery + 2
end
return strategyFunctions.potion({hp=min_recovery, full=enableFull, chain=true})
end,
champion = function()
if status.finishTime then
if not status.frames then
status.frames = 0
2015-05-04 02:17:40 -07:00
local victoryMessage = "Beat Pokemon "..Utils.capitalize(Data.gameName).." in "..status.finishTime
if not Strategies.overMinute("champion") then
victoryMessage = victoryMessage..", a new PB!"
end
Strategies.tweetProgress(victoryMessage)
2015-04-17 13:40:56 -07:00
if Data.run.seed then
2015-04-24 21:00:33 -07:00
Data.setFrames()
2015-04-17 13:40:56 -07:00
print("v"..VERSION..": "..Data.run.frames.." frames, with seed "..Data.run.seed)
2015-04-24 21:00:33 -07:00
if (Data.yellow or not INTERNAL or RESET_FOR_TIME) and not Strategies.replay then
2015-04-16 12:34:13 -07:00
print("Please save this seed number to share, if you would like proof of your run!")
print("A screenshot has been saved to the Gameboy\\Screenshots folder in BizHawk.")
gui.cleartext()
gui.text(0, 0, "PokeBot v"..VERSION)
2015-04-17 13:40:56 -07:00
gui.text(0, 7, "Seed: "..Data.run.seed)
gui.text(0, 14, "Name: "..Textbox.getNamePlaintext())
gui.text(0, 21, "Reset for time: "..tostring(RESET_FOR_TIME))
gui.text(0, 28, "Time: "..Utils.elapsedTime())
2015-04-25 02:38:26 -07:00
gui.text(0, 35, "Frames: "..Utils.frames())
client.setscreenshotosd(true)
client.screenshot()
client.setscreenshotosd(false)
gui.cleartext()
end
end
elseif status.frames == 500 then
Bridge.chat("beat the game in "..status.finishTime.."!")
2015-04-27 23:26:44 -07:00
elseif status.frames > 1800 then
2015-04-28 10:24:43 -07:00
return Strategies.hardReset("won", "Back to the grind - you can follow on Twitter for updates on our next good run! https://twitter.com/thepokebot")
end
status.frames = status.frames + 1
elseif Memory.value("menu", "shop_current") == 252 then
strategyFunctions.split({finished=true})
status.finishTime = Utils.elapsedTime()
else
Input.cancel()
2015-04-13 00:47:34 -07:00
end
end,
2015-04-06 00:50:00 -07:00
}
2014-07-12 18:47:39 -07:00
2015-04-06 01:18:46 -07:00
strategyFunctions = Strategies.functions
2014-07-12 18:47:39 -07:00
2015-04-06 01:18:46 -07:00
function Strategies.execute(data)
local strategyFunction = strategyFunctions[data.s]
if not strategyFunction then
2015-04-24 21:00:33 -07:00
p("INVALID STRATEGY", data.s, Data.gameName)
return true
end
if strategyFunction(data) then
2015-04-06 00:50:00 -07:00
status = {tries=0}
2015-04-06 02:19:25 -07:00
Strategies.status = status
Strategies.completeGameStrategy()
-- if Data.yellow and INTERNAL and not STREAMING_MODE then
-- print(data.s)
-- end
if resetting then
2014-07-12 18:47:39 -07:00
return nil
end
return true
end
return false
end
2015-04-06 01:18:46 -07:00
function Strategies.init(midGame)
splitTime = Utils.timeSince(0)
if midGame then
2015-04-15 01:38:51 -07:00
Control.preferredPotion = "super"
2015-04-06 01:18:46 -07:00
Combat.factorPP(true)
2014-07-12 18:47:39 -07:00
end
2015-05-01 11:12:48 -07:00
local nido = Pokemon.inParty("nidoran", "nidorino", "nidoking")
if nido then
local attDV, defDV, spdDV, sclDV = Pokemon.getDVs(nido)
p(attDV, defDV, spdDV, sclDV)
stats.nidoran = {
rating = 1,
attackDV = attDV,
defenseDV = defDV,
speedDV = spdDV,
specialDV = sclDV,
level4 = true,
}
if nido == "nidoking" then
stats.nidoran.attack = 55
stats.nidoran.defense = 45
stats.nidoran.speed = 50
stats.nidoran.special = 45
else
stats.nidoran.attack = 16
stats.nidoran.defense = 12
stats.nidoran.speed = 15
stats.nidoran.special = 13
end
p(stats.nidoran.attack, "x", stats.nidoran.speed, stats.nidoran.special)
end
2015-04-06 01:18:46 -07:00
Strategies.initGame(midGame)
2014-07-12 18:47:39 -07:00
end
2015-04-06 01:18:46 -07:00
function Strategies.softReset()
2015-04-06 02:19:25 -07:00
status = {tries=0}
Strategies.status = status
stats = {}
Strategies.stats = stats
Strategies.updates = {}
splitNumber, splitTime = 0, 0
2014-07-12 18:47:39 -07:00
resetting = nil
Strategies.deepRun = false
2015-04-06 01:18:46 -07:00
Strategies.resetGame()
2014-07-12 18:47:39 -07:00
end
2015-04-06 01:18:46 -07:00
return Strategies