Refactor capitalize module names

This commit is contained in:
Kyle Coburn 2015-04-06 01:18:46 -07:00
parent f7a1faf1ca
commit c665d3f573
25 changed files with 1516 additions and 1527 deletions

View File

@ -28,13 +28,13 @@ MD5: 3d45c1ee9abd5738df46d2bdda8b57dc
SHA-1: ea9bcae617fdf159b045185467ae58b2e4a48b9a
```
Open the ROM file with BizHawk (Drag the .gb file onto EmuHawk), and Pokémon Red should start up.
Open the ROM file with BizHawk (Drag the .gb file onto EmuHawk), and Pokémon Red should start up.
The colors may look weird. To fix this, go to GB>Palette Editor, and then find the POKEMON RED.pal file which should be under Gameboy>Palettes in the directory where BizHawk was unextracted.
##Running the bot##
If you want to test the full run, change [this line](https://github.com/kylecoburn/PokeBot/blob/52232581f227b829ea283d795ddaf60a52ce24fe/main.lua#L4) to be false.
Then, under the 'Tools' menu, select 'Lua Console'.
Then, under the 'Tools' menu, select 'Lua Console'.
Click the open folder button, and navigate to the PokéBot folder you downloaded. Select 'main.lua' and press open. The bot should start running!
Seeds

View File

@ -1,33 +1,33 @@
local battle = {}
local Battle = {}
local textbox = require "action.textbox"
local Textbox = require "action.textbox"
local combat = require "ai.combat"
local control = require "ai.control"
local Combat = require "ai.combat"
local Control = require "ai.control"
local memory = require "util.memory"
local menu = require "util.menu"
local input = require "util.input"
local utils = require "util.utils"
local Memory = require "util.memory"
local Menu = require "util.menu"
local Input = require "util.input"
local Utils = require "util.utils"
local inventory = require "storage.inventory"
local pokemon = require "storage.pokemon"
local Inventory = require "storage.inventory"
local Pokemon = require "storage.pokemon"
local function potionsForHit(potion, curr_hp, max_hp)
if not potion then
return
end
local ours, killAmount = combat.inKillRange()
local ours, killAmount = Combat.inKillRange()
if ours then
return utils.canPotionWith(potion, killAmount, curr_hp, max_hp)
return Utils.canPotionWith(potion, killAmount, curr_hp, max_hp)
end
end
local function recover()
if control.canRecover() then
local currentHP = pokemon.index(0, "hp")
if Control.canRecover() then
local currentHP = Pokemon.index(0, "hp")
if currentHP > 0 then
local maxHP = pokemon.index(0, "max_hp")
local maxHP = Pokemon.index(0, "max_hp")
if currentHP < maxHP then
local first, second
if potionIn == "full" then
@ -48,216 +48,216 @@ local function recover()
second = "super_potion"
end
end
local potion = inventory.contains(first, second)
local potion = Inventory.contains(first, second)
if potionsForHit(potion, currentHP, maxHP) then
inventory.use(potion, nil, true)
Inventory.use(potion, nil, true)
return true
end
end
end
end
if memory.value("battle", "paralyzed") == 64 then
local heals = inventory.contains("paralyze_heal", "full_restore")
if Memory.value("battle", "paralyzed") == 64 then
local heals = Inventory.contains("paralyze_heal", "full_restore")
if heals then
inventory.use(heals, nil, true)
Inventory.use(heals, nil, true)
return true
end
end
end
local function openBattleMenu()
if memory.value("battle", "text") == 1 then
input.cancel()
if Memory.value("battle", "text") == 1 then
Input.cancel()
return false
end
local battleMenu = memory.value("battle", "menu")
local col = menu.getCol()
local battleMenu = Memory.value("battle", "menu")
local col = Menu.getCol()
if battleMenu == 106 or (battleMenu == 94 and col == 5) then
return true
elseif battleMenu == 94 then
local rowSelected = memory.value("menu", "row")
local rowSelected = Memory.value("menu", "row")
if col == 9 then
if rowSelected == 1 then
input.press("Up")
Input.press("Up")
else
input.press("A")
Input.press("A")
end
else
input.press("Left")
Input.press("Left")
end
else
input.press("B")
Input.press("B")
end
end
local function attack(attackIndex)
if memory.double("battle", "opponent_hp") < 1 then
input.cancel()
if Memory.double("battle", "opponent_hp") < 1 then
Input.cancel()
elseif openBattleMenu() then
menu.select(attackIndex, true, false, false, false, 3)
Menu.select(attackIndex, true, false, false, false, 3)
end
end
-- Table functions
function battle.swapMove(sidx, fidx)
function Battle.swapMove(sidx, fidx)
if openBattleMenu() then
local selection = memory.value("menu", "selection_mode")
local selection = Memory.value("menu", "selection_mode")
local swapSelect
if selection == sidx then
swapSelect = fidx
else
swapSelect = sidx
end
if menu.select(swapSelect, false, false, nil, true, 3) then
input.press("Select")
if Menu.select(swapSelect, false, false, nil, true, 3) then
Input.press("Select")
end
end
end
function battle.isActive()
return memory.value("game", "battle") > 0
function Battle.isActive()
return Memory.value("game", "battle") > 0
end
function battle.isTrainer()
local battleType = memory.value("game", "battle")
function Battle.isTrainer()
local battleType = Memory.value("game", "battle")
if battleType == 2 then
return true
end
if battleType == 1 then
battle.run()
Battle.run()
else
textbox.handle()
Textbox.handle()
end
end
function battle.opponent()
return pokemon.getName(memory.value("battle", "opponent_id"))
function Battle.opponent()
return Pokemon.getName(Memory.value("battle", "opponent_id"))
end
function battle.run()
if memory.double("battle", "opponent_hp") < 1 then
input.cancel()
elseif memory.value("battle", "menu") ~= 94 then
if memory.value("menu", "text_length") == 127 then
input.press("B")
function Battle.run()
if Memory.double("battle", "opponent_hp") < 1 then
Input.cancel()
elseif Memory.value("battle", "menu") ~= 94 then
if Memory.value("menu", "text_length") == 127 then
Input.press("B")
else
input.cancel()
Input.cancel()
end
elseif textbox.handle() then
local selected = memory.value("menu", "selection")
elseif Textbox.handle() then
local selected = Memory.value("menu", "selection")
if selected == 239 then
input.press("A", 2)
Input.press("A", 2)
else
input.escape()
Input.escape()
end
end
end
function battle.handleWild()
if memory.value("game", "battle") ~= 1 then
function Battle.handleWild()
if Memory.value("game", "battle") ~= 1 then
return true
end
battle.run()
Battle.run()
end
function battle.fight(move, isNumber, skipBuffs)
function Battle.fight(move, isNumber, skipBuffs)
if move then
if not isNumber then
move = pokemon.battleMove(move)
move = Pokemon.battleMove(move)
end
attack(move)
else
move = combat.bestMove()
move = Combat.bestMove()
if move then
attack(move.midx)
elseif memory.value("menu", "text_length") == 127 then
input.press("B")
elseif Memory.value("menu", "text_length") == 127 then
Input.press("B")
else
input.cancel()
Input.cancel()
end
end
end
function battle.swap(target)
local battleMenu = memory.value("battle", "menu")
if utils.onPokemonSelect(battleMenu) then
if menu.getCol() == 0 then
menu.select(pokemon.indexOf(target), true)
function Battle.swap(target)
local battleMenu = Memory.value("battle", "menu")
if Utils.onPokemonSelect(battleMenu) then
if Menu.getCol() == 0 then
Menu.select(Pokemon.indexOf(target), true)
else
input.press("A")
Input.press("A")
end
elseif battleMenu == 94 then
local selected = memory.value("menu", "selection")
local selected = Memory.value("menu", "selection")
if selected == 199 then
input.press("A", 2)
elseif menu.getCol() == 9 then
input.press("Right", 0)
Input.press("A", 2)
elseif Menu.getCol() == 9 then
Input.press("Right", 0)
else
input.press("Up", 0)
Input.press("Up", 0)
end
else
input.cancel()
Input.cancel()
end
end
function movePP(name)
local midx = pokemon.battleMove(name)
local midx = Pokemon.battleMove(name)
if not midx then
return 0
end
return memory.raw(0x102C + midx)
return Memory.raw(0x102C + midx)
end
battle.pp = movePP
Battle.pp = movePP
function battle.automate(moveName, skipBuffs)
function Battle.automate(moveName, skipBuffs)
if not recover() then
local state = memory.value("game", "battle")
local state = Memory.value("game", "battle")
if state == 0 then
input.cancel()
Input.cancel()
else
if moveName and movePP(moveName) == 0 then
moveName = nil
end
if state == 1 then
if control.shouldFight() then
battle.fight(moveName, false, skipBuffs)
if Control.shouldFight() then
Battle.fight(moveName, false, skipBuffs)
else
battle.run()
Battle.run()
end
elseif state == 2 then
battle.fight(moveName, false, skipBuffs)
Battle.fight(moveName, false, skipBuffs)
end
end
end
end
function battle.sacrifice(...)
local sacrifice = pokemon.getSacrifice(...)
function Battle.sacrifice(...)
local sacrifice = Pokemon.getSacrifice(...)
if sacrifice then
battle.swap(sacrifice)
Battle.swap(sacrifice)
return true
end
return false
end
function battle.redeployNidoking()
if pokemon.isDeployed("nidoking") then
function Battle.redeployNidoking()
if Pokemon.isDeployed("nidoking") then
return false
end
local battleMenu = memory.value("battle", "menu")
if utils.onPokemonSelect(battleMenu) then
menu.select(0, true)
elseif battleMenu == 95 and menu.getCol() == 1 then
input.press("A")
local battleMenu = Memory.value("battle", "menu")
if Utils.onPokemonSelect(battleMenu) then
Menu.select(0, true)
elseif battleMenu == 95 and Menu.getCol() == 1 then
Input.press("A")
else
local __, turns = combat.bestMove()
local __, turns = Combat.bestMove()
if turns == 1 then
forced = "sand_attack"
end
battle.automate(forced)
Battle.automate(forced)
end
return true
end
return battle
return Battle

View File

@ -1,26 +1,26 @@
local shop = {}
local Shop = {}
local textbox = require "action.textbox"
local Textbox = require "action.textbox"
local input = require "util.input"
local memory = require "util.memory"
local menu = require "util.menu"
local player = require "util.player"
local Input = require "util.input"
local Memory = require "util.memory"
local Menu = require "util.menu"
local Player = require "util.player"
local inventory = require "storage.inventory"
local Inventory = require "storage.inventory"
function shop.transaction(options)
function Shop.transaction(options)
local item, itemMenu, menuIdx, quantityMenu
if options.sell then
menuIdx = 1
itemMenu = 29
quantityMenu = 158
for i,sit in ipairs(options.sell) do
local idx = inventory.indexOf(sit.name)
local idx = Inventory.indexOf(sit.name)
if idx ~= -1 then
item = sit
item.index = idx
item.amount = inventory.count(sit.name)
item.amount = Inventory.count(sit.name)
break
end
end
@ -30,7 +30,7 @@ function shop.transaction(options)
itemMenu = 123
quantityMenu = 161
for i,bit in ipairs(options.buy) do
local needed = (bit.amount or 1) - inventory.count(bit.name)
local needed = (bit.amount or 1) - Inventory.count(bit.name)
if needed > 0 then
item = bit
item.amount = needed
@ -39,44 +39,44 @@ function shop.transaction(options)
end
end
if not item then
if not textbox.isActive() then
if not Textbox.isActive() then
return true
end
input.press("B")
elseif player.isFacing(options.direction or "Left") then
if textbox.isActive() then
if menu.isCurrently(32, "shop") then
menu.select(menuIdx, true, false, "shop")
elseif menu.getCol() == 15 then
input.press("A")
elseif menu.isCurrently(itemMenu, "transaction") then
if menu.select(item.index, "accelerate", true, "transaction", true) then
if menu.isCurrently(quantityMenu, "shop") then
local currAmount = memory.value("shop", "transaction_amount")
if menu.balance(currAmount, item.amount, false, 99, true) then
input.press("A")
Input.press("B")
elseif Player.isFacing(options.direction or "Left") then
if Textbox.isActive() then
if Menu.isCurrently(32, "shop") then
Menu.select(menuIdx, true, false, "shop")
elseif Menu.getCol() == 15 then
Input.press("A")
elseif Menu.isCurrently(itemMenu, "transaction") then
if Menu.select(item.index, "accelerate", true, "transaction", true) then
if Menu.isCurrently(quantityMenu, "shop") then
local currAmount = Memory.value("shop", "transaction_amount")
if Menu.balance(currAmount, item.amount, false, 99, true) then
Input.press("A")
end
else
input.press("A")
Input.press("A")
end
end
else
input.press("B")
Input.press("B")
end
else
input.press("A", 2)
Input.press("A", 2)
end
else
player.interact(options.direction or "Left")
Player.interact(options.direction or "Left")
end
return false
end
function shop.vend(options)
function Shop.vend(options)
local item
menuIdx = 0
for i,bit in ipairs(options.buy) do
local needed = (bit.amount or 1) - inventory.count(bit.name)
local needed = (bit.amount or 1) - Inventory.count(bit.name)
if needed > 0 then
item = bit
item.buy = needed
@ -84,22 +84,22 @@ function shop.vend(options)
end
end
if not item then
if not textbox.isActive() then
if not Textbox.isActive() then
return true
end
input.press("B")
elseif player.face(options.direction) then
if textbox.isActive() then
if memory.value("battle", "text") > 1 and memory.value("battle", "menu") ~= 95 then
menu.select(item.index, true)
Input.press("B")
elseif Player.face(options.direction) then
if Textbox.isActive() then
if Memory.value("battle", "text") > 1 and Memory.value("battle", "menu") ~= 95 then
Menu.select(item.index, true)
else
input.press("A")
Input.press("A")
end
else
input.press("A", 2)
Input.press("A", 2)
end
end
return false
end
return shop
return Shop

View File

@ -1,9 +1,8 @@
local textbox = {}
local Textbox = {}
local input = require "util.input"
local memory = require "util.memory"
local menu = require "util.menu"
local utils = require "util.utils"
local Input = require "util.input"
local Memory = require "util.memory"
local Menu = require "util.menu"
local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ *():;[]ab-?!mf/.,"
-- local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ *():;[]ポモ-?!♂♀/.,"
@ -19,11 +18,11 @@ local function getIndexForLetter(letter)
return alphabet:find(letter, 1, true)
end
function textbox.name(letter, randomize)
local inputting = memory.value("menu", "text_input") == 240
function Textbox.name(letter, randomize)
local inputting = Memory.value("menu", "text_input") == 240
if inputting then
if memory.value("menu", "text_length") > 0 then
input.press("Start")
if Memory.value("menu", "text_length") > 0 then
Input.press("Start")
return true
end
local lidx
@ -33,29 +32,29 @@ function textbox.name(letter, randomize)
lidx = nidoIdx
end
local crow = memory.value("menu", "input_row")
local crow = Memory.value("menu", "input_row")
local drow = math.ceil(lidx / 9)
if menu.balance(crow, drow, true, 6, true) then
local ccol = math.floor(memory.value("menu", "column") / 2)
if Menu.balance(crow, drow, true, 6, true) then
local ccol = math.floor(Memory.value("menu", "column") / 2)
local dcol = math.fmod(lidx - 1, 9)
if menu.sidle(ccol, dcol, 9, true) then
input.press("A")
if Menu.sidle(ccol, dcol, 9, true) then
Input.press("A")
end
end
else
-- TODO cancel when menu isn't up
-- if memory.value("menu", "current") == 7 then
if memory.raw(0x10B7) == 3 then
input.press("A", 2)
-- if Memory.value("menu", "current") == 7 then
if Memory.raw(0x10B7) == 3 then
Input.press("A", 2)
elseif randomize then
input.press("A", math.random(1, 5))
Input.press("A", math.random(1, 5))
else
input.cancel()
Input.cancel()
end
end
end
function textbox.getName()
function Textbox.getName()
if nidoName == "a" then
return ""
end
@ -71,22 +70,22 @@ function textbox.getName()
return nidoName
end
function textbox.setName(index)
function Textbox.setName(index)
if index >= 0 and index < #alphabet then
nidoIdx = index + 1
nidoName = getLetterAt(index)
end
end
function textbox.isActive()
return memory.value("game", "textbox") == 1
function Textbox.isActive()
return Memory.value("game", "textbox") == 1
end
function textbox.handle()
if not textbox.isActive() then
function Textbox.handle()
if not Textbox.isActive() then
return true
end
input.cancel()
Input.cancel()
end
return textbox
return Textbox

View File

@ -1,14 +1,13 @@
local walk = {}
local Walk = {}
local control = require "ai.control"
local Control = require "ai.control"
local paths = require("data."..GAME_NAME..".paths")
local input = require "util.input"
local memory = require "util.memory"
local player = require "util.player"
local utils = require "util.utils"
local Input = require "util.input"
local Memory = require "util.memory"
local Player = require "util.player"
local pokemon = require "storage.pokemon"
local Pokemon = require "storage.pokemon"
local path, stepIdx, currentMap
local pathIdx = 0
@ -26,7 +25,7 @@ end
local function completeStep(region)
stepIdx = stepIdx + 1
return walk.traverse(region)
return Walk.traverse(region)
end
-- Helper functions
@ -44,31 +43,31 @@ function dir(px, py, dx, dy)
end
return direction
end
walk.dir = dir
Walk.dir = dir
function step(dx, dy)
local px, py = player.position()
local px, py = Player.position()
if px == dx and py == dy then
return true
end
input.press(dir(px, py, dx, dy), 0)
Input.press(dir(px, py, dx, dy), 0)
end
walk.step = step
Walk.step = step
-- Table functions
function walk.reset()
function Walk.reset()
path = nil
pathIdx = 0
customIdx = 1
customDir = 1
currentMap = nil
walk.strategy = nil
Walk.strategy = nil
end
function walk.init()
local region = memory.value("game", "map")
local px, py = player.position()
function Walk.init()
local region = Memory.value("game", "map")
local px, py = Player.position()
if region == 0 and px == 0 and py == 0 then
return false
end
@ -85,10 +84,10 @@ function walk.init()
end
end
function walk.traverse(region)
function Walk.traverse(region)
local newIndex
if not path or currentMap ~= region then
walk.strategy = nil
Walk.strategy = nil
setPath(pathIdx + 1, region)
newIndex = pathIdx
customIdx = 1
@ -98,36 +97,36 @@ function walk.traverse(region)
end
local tile = path[stepIdx]
if tile.c then
control.set(tile)
Control.set(tile)
return completeStep(region)
end
if tile.s then
if walk.strategy then
walk.strategy = nil
if Walk.strategy then
Walk.strategy = nil
return completeStep(region)
end
walk.strategy = tile
Walk.strategy = tile
elseif step(tile[1], tile[2]) then
pokemon.updateParty()
Pokemon.updateParty()
return completeStep(region)
end
return newIndex
end
function walk.canMove()
return memory.value("player", "moving") == 0 and memory.value("player", "fighting") == 0
function Walk.canMove()
return Memory.value("player", "moving") == 0 and Memory.value("player", "fighting") == 0
end
-- Custom path
function walk.invertCustom(silent)
function Walk.invertCustom(silent)
if not silent then
customIdx = customIdx + customDir
end
customDir = customDir * -1
end
function walk.custom(cpath, increment)
function Walk.custom(cpath, increment)
if not cpath then
customIdx = 1
customDir = 1
@ -147,8 +146,8 @@ function walk.custom(cpath, increment)
end
local t1, t2 = tile[1], tile[2]
if t2 == nil then
if player.face(t1) then
input.press("A", 2)
if Player.face(t1) then
Input.press("A", 2)
end
return t1
end
@ -157,4 +156,4 @@ function walk.custom(cpath, increment)
end
end
return walk
return Walk

View File

@ -1,10 +1,9 @@
local combat = {}
local Combat = {}
local movelist = require "data.movelist"
local opponents = require "data.opponents"
local Movelist = require "data.movelist"
local Opponents = require "data.opponents"
local memory = require "util.memory"
local utils = require "util.utils"
local Memory = require "util.memory"
local damageMultiplier = { -- http://bulbapedia.bulbagarden.net/wiki/Type_chart#Generation_I
normal = {normal=1.0, fighting=1.0, flying=1.0, poison=1.0, ground=1.0, rock=0.5, bug=1.0, ghost=0.0, fire=1.0, water=1.0, grass=1.0, electric=1.0, psychic=1.0, ice=1.0, dragon=1.0, },
@ -47,9 +46,9 @@ local enablePP = false
local floor = math.floor
local function isDisabled(mid)
return mid == memory.value("battle", "disabled")
return mid == Memory.value("battle", "disabled")
end
combat.isDisabled = isDisabled
Combat.isDisabled = isDisabled
local function calcDamage(move, attacker, defender, rng)
if move.fixed then
@ -60,14 +59,14 @@ local function calcDamage(move, attacker, defender, rng)
end
if move.power > 9000 then
local oid = defender.id
if oid ~= 14 and oid ~= 147 and oid ~= 171 and (oidd ~= 151 or memory.value("game", "map") == 120) then -- ???
if memory.value("battle", "x_accuracy") == 1 and defender.speed < attacker.speed then
if oid ~= 14 and oid ~= 147 and oid ~= 171 and (oidd ~= 151 or Memory.value("game", "map") == 120) then -- ???
if Memory.value("battle", "x_accuracy") == 1 and defender.speed < attacker.speed then
return 9001, 9001
end
end
return 0, 0
end
if move.name == "Thrash" and combat.disableThrash then
if move.name == "Thrash" and Combat.disableThrash then
return 0, 0
end
@ -96,34 +95,34 @@ local function calcDamage(move, attacker, defender, rng)
end
local function getOpponentType(ty)
local t1 = types[memory.value("battle", "opponent_type1")]
local t1 = types[Memory.value("battle", "opponent_type1")]
if ty ~= 0 then
t1 = types[memory.value("battle", "opponent_type2")]
t1 = types[Memory.value("battle", "opponent_type2")]
if not t1 then
return memory.value("battle", "opponent_type2")
return Memory.value("battle", "opponent_type2")
end
end
if t1 then
return t1
end
return memory.value("battle", "opponent_type1")
return Memory.value("battle", "opponent_type1")
end
combat.getOpponentType = getOpponentType
Combat.getOpponentType = getOpponentType
function getOurType(ty)
local t1 = types[memory.value("battle", "our_type1")]
local t1 = types[Memory.value("battle", "our_type1")]
if ty ~= 0 then
t1 = types[memory.value("battle", "our_type2")]
t1 = types[Memory.value("battle", "our_type2")]
if not t1 then
return memory.value("battle", "opponent_type2")
return Memory.value("battle", "opponent_type2")
end
end
if t1 then
return t1
end
return memory.value("battle", "opponent_type1")
return Memory.value("battle", "opponent_type1")
end
combat.getOurType = getOurType
Combat.getOurType = getOurType
local function getMoves(who)--Get the moveset of us [0] or them [1]
local moves = {}
@ -134,18 +133,18 @@ local function getMoves(who)--Get the moveset of us [0] or them [1]
base = 0x101C
end
for idx=0, 3 do
local val = memory.raw(base + idx)
local val = Memory.raw(base + idx)
if val > 0 then
local moveTable = movelist.get(val)
local moveTable = Movelist.get(val)
if who == 0 then
moveTable.pp = memory.raw(0x102D + idx)
moveTable.pp = Memory.raw(0x102D + idx)
end
moves[idx + 1] = moveTable
end
end
return moves
end
combat.getMoves = getMoves
Combat.getMoves = getMoves
local function modPlayerStats(user, enemy, move)
local effect = move.effects
@ -183,9 +182,9 @@ local function calcBestHit(attacker, defender, ours, rng)
if not ret or minTurns < bestMinTurns or maxTurns < bestTurns then
replaces = true
elseif maxTurns == bestTurns and move.name == "Thrash" then
replaces = defender.hp == memory.double("battle", "opponent_max_hp")
replaces = defender.hp == Memory.double("battle", "opponent_max_hp")
elseif maxTurns == bestTurns and ret.name == "Thrash" then
replaces = defender.hp ~= memory.double("battle", "opponent_max_hp")
replaces = defender.hp ~= Memory.double("battle", "opponent_max_hp")
elseif move.fast and not ret.fast then
replaces = maxTurns <= bestTurns
elseif ret.fast then
@ -245,13 +244,13 @@ end
local function activePokemon(preset)
local ours = {
id = memory.value("battle", "our_id"),
level = memory.value("battle", "our_level"),
hp = memory.double("battle", "our_hp"),
att = memory.double("battle", "our_attack"),
def = memory.double("battle", "our_defense"),
spec = memory.double("battle", "our_special"),
speed = memory.double("battle", "our_speed"),
id = Memory.value("battle", "our_id"),
level = Memory.value("battle", "our_level"),
hp = Memory.double("battle", "our_hp"),
att = Memory.double("battle", "our_attack"),
def = Memory.double("battle", "our_defense"),
spec = Memory.double("battle", "our_special"),
speed = Memory.double("battle", "our_speed"),
type1 = getOurType(0),
type2 = getOurType(1),
moves = getMoves(0),
@ -259,7 +258,7 @@ local function activePokemon(preset)
local enemy
if preset then
enemy = opponents[preset]
enemy = Opponents[preset]
local toBoost = enemy.boost
if toBoost then
local currSpec = ours.spec
@ -270,13 +269,13 @@ local function activePokemon(preset)
end
else
enemy = {
id = memory.value("battle", "opponent_id"),
level = memory.value("battle", "opponent_level"),
hp = memory.double("battle", "opponent_hp"),
att = memory.double("battle", "opponent_attack"),
def = memory.double("battle", "opponent_defense"),
spec = memory.double("battle", "opponent_special"),
speed = memory.double("battle", "opponent_speed"),
id = Memory.value("battle", "opponent_id"),
level = Memory.value("battle", "opponent_level"),
hp = Memory.double("battle", "opponent_hp"),
att = Memory.double("battle", "opponent_attack"),
def = Memory.double("battle", "opponent_defense"),
spec = Memory.double("battle", "opponent_special"),
speed = Memory.double("battle", "opponent_speed"),
type1 = getOpponentType(0),
type2 = getOpponentType(1),
moves = getMoves(1),
@ -284,35 +283,35 @@ local function activePokemon(preset)
end
return ours, enemy
end
combat.activePokemon = activePokemon
Combat.activePokemon = activePokemon
local function isSleeping()
return memory.raw(0x116F) > 1
return Memory.raw(0x116F) > 1
end
combat.isSleeping = isSleeping
Combat.isSleeping = isSleeping
local function isConfused()
return memory.raw(0x106B) > 0
return Memory.raw(0x106B) > 0
end
combat.isConfused = isConfused
Combat.isConfused = isConfused
-- Combat AI
function combat.factorPP(enabled)
function Combat.factorPP(enabled)
enablePP = enabled
end
function combat.reset()
function Combat.reset()
enablePP = false
end
function combat.healthFor(opponent)
function Combat.healthFor(opponent)
local ours, enemy = activePokemon(opponent)
local enemyAttack, turnsToDie = calcBestHit(enemy, ours, false)
return enemyAttack.damage
end
function combat.inKillRange(draw)
function Combat.inKillRange(draw)
local ours, enemy = activePokemon()
local enemyAttack, __ = calcBestHit(enemy, ours, false)
local __, turnsToKill = calcBestHit(ours, enemy, true)
@ -331,7 +330,7 @@ function combat.inKillRange(draw)
if ours.hp < hpReq then
local outspeed = enemyAttack.outspeed
if outspeed and outspeed ~= true then
outspeed = memory.value("battle", "turns") > 0
outspeed = Memory.value("battle", "turns") > 0
end
if outspeed or isConfused or turnsToKill > 1 or ours.speed <= enemy.speed or isSleeping() then
return ours, hpReq
@ -353,7 +352,7 @@ local function getBattlePokemon()
return ours, enemy
end
function combat.nonKill()
function Combat.nonKill()
local ours, enemy = getBattlePokemon()
if not enemy then
return
@ -373,14 +372,14 @@ function combat.nonKill()
return ret
end
function combat.bestMove()
function Combat.bestMove()
local ours, enemy = getBattlePokemon()
if enemy then
return getBestMove(ours, enemy)
end
end
function combat.enemyAttack()
function Combat.enemyAttack()
local ours, enemy = activePokemon()
if enemy.hp == 0 then
return
@ -388,4 +387,4 @@ function combat.enemyAttack()
return calcBestHit(enemy, ours, false)
end
return combat
return Combat

View File

@ -1,17 +1,15 @@
local control = {}
local Control = {}
local combat = require "ai.combat"
local strategies
local Combat = require "ai.combat"
local Strategies
local bridge = require "util.bridge"
local memory = require "util.memory"
local menu = require "util.menu"
local paint = require "util.paint"
local player = require "util.player"
local utils = require "util.utils"
local Bridge = require "util.bridge"
local Memory = require "util.memory"
local Paint = require "util.paint"
local Utils = require "util.utils"
local inventory = require "storage.inventory"
local pokemon = require "storage.pokemon"
local Inventory = require "storage.inventory"
local Pokemon = require "storage.pokemon"
local potionInBattle = true
local fightEncounter, caveFights = 0, 0
@ -22,20 +20,20 @@ local shouldCatch, attackIdx
local extraEncounter, maxEncounters
local battleYolo
control.areaName = "Unknown"
control.moonEncounters = nil
control.yolo = false
Control.areaName = "Unknown"
Control.moonEncounters = nil
Control.yolo = false
local controlFunctions = {
a = function(data)
control.areaName = data.a
Control.areaName = data.a
return true
end,
potion = function(data)
if data.b ~= nil then
control.battlePotion(data.b)
Control.battlePotion(data.b)
end
battleYolo = data.yolo
end,
@ -48,11 +46,11 @@ local controlFunctions = {
end,
pp = function(data)
combat.factorPP(data.on)
Combat.factorPP(data.on)
end,
setThrash = function(data)
combat.disableThrash = data.disable
Combat.disableThrash = data.disable
end,
disableCatch = function()
@ -113,11 +111,11 @@ local controlFunctions = {
-- COMBAT
function control.battlePotion(enable)
function Control.battlePotion(enable)
potionInBattle = enable
end
function control.canDie(enabled)
function Control.canDie(enabled)
if enabled == nil then
return canDie
end
@ -125,25 +123,25 @@ function control.canDie(enabled)
end
local function isNewFight()
if fightEncounter < encounters and memory.double("battle", "opponent_hp") == memory.double("battle", "opponent_max_hp") then
if fightEncounter < encounters and Memory.double("battle", "opponent_hp") == Memory.double("battle", "opponent_max_hp") then
fightEncounter = encounters
return true
end
end
function control.shouldFight()
function Control.shouldFight()
if not shouldFight then
return false
end
local expTotal = pokemon.getExp()
local expTotal = Pokemon.getExp()
if expTotal < minExp then
local oid = memory.value("battle", "opponent_id")
local olvl = memory.value("battle", "opponent_level")
local oid = Memory.value("battle", "opponent_id")
local olvl = Memory.value("battle", "opponent_level")
for i,p in ipairs(shouldFight) do
if oid == pokemon.getID(p.name) and (not p.lvl or utils.match(olvl, p.lvl)) then
if oid == Pokemon.getID(p.name) and (not p.lvl or Utils.match(olvl, p.lvl)) then
if oneHits then
local move = combat.bestMove()
if move and move.maxDamage * 0.925 < memory.double("battle", "opponent_hp") then
local move = Combat.bestMove()
if move and move.maxDamage * 0.925 < Memory.double("battle", "opponent_hp") then
return false
end
end
@ -153,24 +151,24 @@ function control.shouldFight()
end
end
function control.canCatch(partySize)
function Control.canCatch(partySize)
if not partySize then
partySize = memory.value("player", "party_size")
partySize = Memory.value("player", "party_size")
end
local pokeballs = inventory.count("pokeball")
local pokeballs = Inventory.count("pokeball")
local minimumCount = 4 - partySize
if pokeballs < minimumCount then
strategies.reset("Not enough PokeBalls", pokeballs)
Strategies.reset("Not enough PokeBalls", pokeballs)
return false
end
return true
end
function control.shouldCatch(partySize)
function Control.shouldCatch(partySize)
if maxEncounters and encounters > maxEncounters then
local extraCount = extraEncounter and pokemon.inParty(extraEncounter)
local extraCount = extraEncounter and Pokemon.inParty(extraEncounter)
if not extraCount or encounters > maxEncounters + 1 then
strategies.reset("Too many encounters", encounters)
Strategies.reset("Too many encounters", encounters)
return false
end
end
@ -178,27 +176,27 @@ function control.shouldCatch(partySize)
return false
end
if not partySize then
partySize = memory.value("player", "party_size")
partySize = Memory.value("player", "party_size")
end
if partySize == 4 then
shouldCatch = nil
return false
end
if not control.canCatch(partySize) then
if not Control.canCatch(partySize) then
return true
end
local oid = memory.value("battle", "opponent_id")
local oid = Memory.value("battle", "opponent_id")
for i,poke in ipairs(shouldCatch) do
if oid == pokemon.getID(poke.name) and not pokemon.inParty(poke.name, poke.alt) then
if not poke.lvl or utils.match(memory.value("battle", "opponent_level"), poke.lvl) then
local penultimate = poke.hp and memory.double("battle", "opponent_hp") > poke.hp
if oid == Pokemon.getID(poke.name) and not Pokemon.inParty(poke.name, poke.alt) then
if not poke.lvl or Utils.match(Memory.value("battle", "opponent_level"), poke.lvl) then
local penultimate = poke.hp and Memory.double("battle", "opponent_hp") > poke.hp
if penultimate then
penultimate = combat.nonKill()
penultimate = Combat.nonKill()
end
if penultimate then
require("action.battle").fight(penultimate.midx, true)
else
inventory.use("pokeball", nil, true)
Inventory.use("pokeball", nil, true)
end
return true
end
@ -208,36 +206,36 @@ end
-- Items
function control.canRecover()
return potionInBattle and (not battleYolo or not control.yolo)
function Control.canRecover()
return potionInBattle and (not battleYolo or not Control.yolo)
end
function control.set(data)
function Control.set(data)
controlFunctions[data.c](data)
end
function control.setYolo(enabled)
control.yolo = enabled
function Control.setYolo(enabled)
Control.yolo = enabled
end
function control.setPotion(enabled)
function Control.setPotion(enabled)
potionInBattle = enabled
end
function control.encounters()
function Control.encounters()
return encounters
end
function control.wildEncounter()
function Control.wildEncounter()
encounters = encounters + 1
paint.wildEncounters(encounters)
bridge.encounter()
if control.moonEncounters then
control.moonEncounters = control.moonEncounters + 1
Paint.wildEncounters(encounters)
Bridge.encounter()
if Control.moonEncounters then
Control.moonEncounters = Control.moonEncounters + 1
end
end
function control.reset()
function Control.reset()
canDie = false
oneHits = false
shouldCatch = nil
@ -248,12 +246,12 @@ function control.reset()
fightEncounter = 0
caveFights = 0
battleYolo = false
control.yolo = false
Control.yolo = false
maxEncounters = nil
end
function control.init()
strategies = require("ai."..GAME_NAME..".strategies")
function Control.init()
Strategies = require("ai."..GAME_NAME..".strategies")
end
return control
return Control

File diff suppressed because it is too large Load Diff

View File

@ -1,48 +1,48 @@
local strategies = {}
local Strategies = {}
local combat = require "ai.combat"
local control = require "ai.control"
local Combat = require "ai.combat"
local Control = require "ai.control"
local battle = require "action.battle"
local textbox = require "action.textbox"
local walk = require "action.walk"
local Battle = require "action.battle"
local Textbox = require "action.textbox"
local Walk = require "action.walk"
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"
local utils = require "util.utils"
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"
local Utils = require "util.utils"
local inventory = require "storage.inventory"
local pokemon = require "storage.pokemon"
local Inventory = require "storage.inventory"
local Pokemon = require "storage.pokemon"
local splitNumber, splitTime = 0, 0
local resetting
local strategyFunctions
local status = {tries = 0, tempDir = nil, canProgress = nil, initialized = false}
strategies.status = status
strategies.deepRun = false
Strategies.status = status
Strategies.deepRun = false
-- RISK/RESET
strategies.timeRequirements = {}
Strategies.timeRequirements = {}
function strategies.getTimeRequirement(name)
return strategies.timeRequirements[name]()
function Strategies.getTimeRequirement(name)
return Strategies.timeRequirements[name]()
end
function strategies.hardReset(message, extra, wait)
function Strategies.hardReset(message, extra, wait)
resetting = true
if strategies.seed then
if Strategies.seed then
if extra then
extra = extra.." | "..strategies.seed
extra = extra.." | "..Strategies.seed
else
extra = strategies.seed
extra = Strategies.seed
end
end
bridge.chat(message, extra)
Bridge.chat(message, extra)
if wait and INTERNAL and not STREAMING_MODE then
strategyFunctions.wait()
end
@ -50,138 +50,138 @@ function strategies.hardReset(message, extra, wait)
return true
end
function strategies.reset(reason, extra, wait)
local time = utils.elapsedTime()
function Strategies.reset(reason, extra, wait)
local time = Utils.elapsedTime()
local resetString = "Reset"
if time then
resetString = resetString.." after "..time
end
resetString = " "..resetString.." at "..control.areaName
resetString = " "..resetString.." at "..Control.areaName
local separator
if strategies.deepRun and not control.yolo then
if Strategies.deepRun and not Control.yolo then
separator = " BibleThump"
else
separator = ":"
end
resetString = resetString..separator.." "..reason
return strategies.hardReset(resetString, extra, wait)
return Strategies.hardReset(resetString, extra, wait)
end
function strategies.death(extra)
function Strategies.death(extra)
local reason
if strategies.criticaled then
if Strategies.criticaled then
reason = "Critical'd"
elseif control.yolo then
elseif Control.yolo then
reason = "Yolo strats"
else
reason = "Died"
end
return strategies.reset(reason, extra)
return Strategies.reset(reason, extra)
end
function strategies.overMinute(min)
return utils.igt() > min * 60
function Strategies.overMinute(min)
return Utils.igt() > min * 60
end
function strategies.resetTime(timeLimit, reason, once)
if strategies.overMinute(timeLimit) then
function Strategies.resetTime(timeLimit, reason, once)
if Strategies.overMinute(timeLimit) then
reason = "Took too long to "..reason
if RESET_FOR_TIME then
return strategies.reset(reason)
return Strategies.reset(reason)
end
if once then
print(reason.." "..utils.elapsedTime())
print(reason.." "..Utils.elapsedTime())
end
end
end
function strategies.setYolo(name)
function Strategies.setYolo(name)
if not RESET_FOR_TIME then
return false
end
local minimumTime = strategies.getTimeRequirement(name)
local shouldYolo = strategies.overMinute(minimumTime)
if control.yolo ~= shouldYolo then
control.yolo = shouldYolo
control.setYolo(shouldYolo)
local minimumTime = Strategies.getTimeRequirement(name)
local shouldYolo = Strategies.overMinute(minimumTime)
if Control.yolo ~= shouldYolo then
Control.yolo = shouldYolo
Control.setYolo(shouldYolo)
local prefix
if control.yolo then
if Control.yolo then
prefix = "en"
else
prefix = "dis"
end
print("YOLO "..prefix.."abled at "..control.areaName)
print("YOLO "..prefix.."abled at "..Control.areaName)
end
return control.yolo
return Control.yolo
end
-- HELPERS
function strategies.initialize()
function Strategies.initialize()
if not initialized then
initialized = true
return true
end
end
function strategies.canHealFor(damage)
local curr_hp = pokemon.index(0, "hp")
local max_hp = pokemon.index(0, "max_hp")
function Strategies.canHealFor(damage)
local curr_hp = Pokemon.index(0, "hp")
local max_hp = Pokemon.index(0, "max_hp")
if max_hp - curr_hp > 3 then
local healChecks = {"full_restore", "super_potion", "potion"}
for idx,potion in ipairs(healChecks) do
if inventory.contains(potion) and utils.canPotionWith(potion, damage, curr_hp, max_hp) then
if Inventory.contains(potion) and Utils.canPotionWith(potion, damage, curr_hp, max_hp) then
return potion
end
end
end
end
function strategies.hasHealthFor(opponent, extra)
function Strategies.hasHealthFor(opponent, extra)
if not extra then
extra = 0
end
return pokemon.index(0, "hp") + extra > combat.healthFor(opponent)
return Pokemon.index(0, "hp") + extra > Combat.healthFor(opponent)
end
function strategies.damaged(factor)
function Strategies.damaged(factor)
if not factor then
factor = 1
end
return pokemon.index(0, "hp") * factor < pokemon.index(0, "max_hp")
return Pokemon.index(0, "hp") * factor < Pokemon.index(0, "max_hp")
end
function strategies.opponentDamaged(factor)
function Strategies.opponentDamaged(factor)
if not factor then
factor = 1
end
return memory.double("battle", "opponent_hp") * factor < memory.double("battle", "opponent_max_hp")
return Memory.double("battle", "opponent_hp") * factor < Memory.double("battle", "opponent_max_hp")
end
function strategies.redHP()
return math.ceil(pokemon.index(0, "max_hp") * 0.2)
function Strategies.redHP()
return math.ceil(Pokemon.index(0, "max_hp") * 0.2)
end
function strategies.buffTo(buff, defLevel)
if battle.isActive() then
function Strategies.buffTo(buff, defLevel)
if Battle.isActive() then
canProgress = true
local forced
if defLevel and memory.double("battle", "opponent_defense") > defLevel then
if defLevel and Memory.double("battle", "opponent_defense") > defLevel then
forced = buff
end
battle.automate(forced, true)
Battle.automate(forced, true)
elseif canProgress then
return true
else
battle.automate()
Battle.automate()
end
end
function strategies.dodgeUp(npc, sx, sy, dodge, offset)
if not battle.handleWild() then
function Strategies.dodgeUp(npc, sx, sy, dodge, offset)
if not Battle.handleWild() then
return false
end
local px, py = player.position()
local px, py = Player.position()
if py < sy - 1 then
return true
end
@ -189,7 +189,7 @@ function strategies.dodgeUp(npc, sx, sy, dodge, offset)
if py < sy then
wy = py - 1
elseif px == sx or px == dodge then
if px - memory.raw(npc) == offset then
if px - Memory.raw(npc) == offset then
if px == sx then
wx = dodge
else
@ -199,7 +199,7 @@ function strategies.dodgeUp(npc, sx, sy, dodge, offset)
wy = py - 1
end
end
walk.step(wx, wy)
Walk.step(wx, wy)
end
local function dodgeH(options)
@ -207,7 +207,7 @@ local function dodgeH(options)
if options.left then
left = -1
end
local px, py = player.position()
local px, py = Player.position()
if px * left > options.sx * left + (options.dist or 1) * left then
return true
end
@ -215,7 +215,7 @@ local function dodgeH(options)
if px * left > options.sx * left then
wx = px + 1 * left
elseif py == options.sy or py == options.dodge then
if py - memory.raw(options.npc) == options.offset then
if py - Memory.raw(options.npc) == options.offset then
if py == options.sy then
wy = options.dodge
else
@ -225,73 +225,73 @@ local function dodgeH(options)
wx = px + 1 * left
end
end
walk.step(wx, wy)
Walk.step(wx, wy)
end
function strategies.completedMenuFor(data)
local count = inventory.count(data.item)
function Strategies.completedMenuFor(data)
local count = Inventory.count(data.item)
if count == 0 or count + (data.amount or 1) <= status.tries then
return true
end
return false
end
function strategies.closeMenuFor(data)
if (not tempDir and not data.close) or data.chain or menu.close() then
function Strategies.closeMenuFor(data)
if (not tempDir and not data.close) or data.chain or Menu.close() then
return true
end
end
function strategies.useItem(data)
local main = memory.value("menu", "main")
function Strategies.useItem(data)
local main = Memory.value("menu", "main")
if status.tries == 0 then
status.tries = inventory.count(data.item)
status.tries = Inventory.count(data.item)
if status.tries == 0 then
if strategies.closeMenuFor(data) then
if Strategies.closeMenuFor(data) then
return true
end
return false
end
end
if strategies.completedMenuFor(data) then
if strategies.closeMenuFor(data) then
if Strategies.completedMenuFor(data) then
if Strategies.closeMenuFor(data) then
return true
end
else
if inventory.use(data.item, data.poke) then
if Inventory.use(data.item, data.poke) then
tempDir = true
else
menu.pause()
Menu.pause()
end
end
end
local function completedSkillFor(data)
if data.map then
if data.map ~= memory.value("game", "map") then
if data.map ~= Memory.value("game", "map") then
return true
end
elseif data.x or data.y then
local px, py = player.position()
local px, py = Player.position()
if data.x == px or data.y == py then
return true
end
elseif data.done then
if memory.raw(data.done) > (data.val or 0) then
if Memory.raw(data.done) > (data.val or 0) then
return true
end
elseif status.tries > 0 and not menu.isOpen() then
elseif status.tries > 0 and not Menu.isOpen() then
return true
end
return false
end
function strategies.isPrepared(...)
function Strategies.isPrepared(...)
if status.tries == 0 then
status.tries = {}
end
for i,name in ipairs(arg) do
local currentCount = inventory.count(name)
local currentCount = Inventory.count(name)
if currentCount > 0 then
local previousCount = status.tries[name]
if previousCount == nil or currentCount == previousCount then
@ -302,13 +302,13 @@ function strategies.isPrepared(...)
return true
end
function strategies.prepare(...)
function Strategies.prepare(...)
if status.tries == 0 then
status.tries = {}
end
local item
for idx,name in ipairs(arg) do
local currentCount = inventory.count(name)
local currentCount = Inventory.count(name)
local needsItem = currentCount > 0
local previousCount = status.tries[name]
if previousCount == nil then
@ -324,108 +324,108 @@ function strategies.prepare(...)
if not item then
return true
end
if battle.isActive() then
inventory.use(item, nil, true)
if Battle.isActive() then
Inventory.use(item, nil, true)
else
input.cancel()
Input.cancel()
end
end
-- GENERALIZED STRATEGIES
strategies.functions = {
Strategies.functions = {
startFrames = function()
strategies.frames = 0
Strategies.frames = 0
return true
end,
reportFrames = function()
print("FR "..strategies.frames)
local repels = memory.value("player", "repel")
print("FR "..Strategies.frames)
local repels = Memory.value("player", "repel")
if repels > 0 then
print("S "..repels)
end
strategies.frames = nil
Strategies.frames = nil
return true
end,
split = function(data)
bridge.split(data and data.finished)
Bridge.split(data and data.finished)
if not INTERNAL then
splitNumber = splitNumber + 1
local timeDiff
splitTime, timeDiff = utils.timeSince(splitTime)
splitTime, timeDiff = Utils.timeSince(splitTime)
if timeDiff then
print(splitNumber..". "..control.areaName..": "..utils.elapsedTime().." ("..timeDiff..")")
print(splitNumber..". "..Control.areaName..": "..Utils.elapsedTime().." ("..timeDiff..")")
end
end
return true
end,
interact = function(data)
if battle.handleWild() then
if battle.isActive() then
if Battle.handleWild() then
if Battle.isActive() then
return true
end
if textbox.isActive() then
if Textbox.isActive() then
if status.tries > 0 then
return true
end
status.tries = status.tries - 1
input.cancel()
elseif player.interact(data.dir) then
Input.cancel()
elseif Player.interact(data.dir) then
status.tries = status.tries + 1
end
end
end,
confirm = function(data)
if battle.handleWild() then
if textbox.isActive() then
if Battle.handleWild() then
if Textbox.isActive() then
status.tries = status.tries + 1
input.cancel(data.type or "A")
Input.cancel(data.type or "A")
else
if status.tries > 0 then
return true
end
player.interact(data.dir)
Player.interact(data.dir)
end
end
end,
item = function(data)
if battle.handleWild() then
if data.full and not inventory.isFull() then
if strategies.closeMenuFor(data) then
if Battle.handleWild() then
if data.full and not Inventory.isFull() then
if Strategies.closeMenuFor(data) then
return true
end
return false
end
return strategies.useItem(data)
return Strategies.useItem(data)
end
end,
potion = function(data)
local curr_hp = pokemon.index(0, "hp")
local curr_hp = Pokemon.index(0, "hp")
if curr_hp == 0 then
return false
end
local toHP
if control.yolo and data.yolo ~= nil then
if Control.yolo and data.yolo ~= nil then
toHP = data.yolo
else
toHP = data.hp
end
if type(toHP) == "string" then
toHP = combat.healthFor(toHP)
toHP = Combat.healthFor(toHP)
end
local toHeal = toHP - curr_hp
if toHeal > 0 then
local toPotion
if data.forced then
toPotion = inventory.contains(data.forced)
toPotion = Inventory.contains(data.forced)
else
local p_first, p_second, p_third
if toHeal > 50 then
@ -445,24 +445,24 @@ strategies.functions = {
p_third = "full_restore"
end
end
toPotion = inventory.contains(p_first, p_second, p_third)
toPotion = Inventory.contains(p_first, p_second, p_third)
end
if toPotion then
if menu.pause() then
inventory.use(toPotion)
if Menu.pause() then
Inventory.use(toPotion)
tempDir = true
end
return false
end
--TODO report wanted potion
end
if strategies.closeMenuFor(data) then
if Strategies.closeMenuFor(data) then
return true
end
end,
teach = function(data)
if data.full and not inventory.isFull() then
if data.full and not Inventory.isFull() then
return true
end
local itemName
@ -471,8 +471,8 @@ strategies.functions = {
else
itemName = data.move
end
if pokemon.hasMove(data.move) then
local main = memory.value("menu", "main")
if Pokemon.hasMove(data.move) then
local main = Memory.value("menu", "main")
if main == 128 then
if data.chain then
return true
@ -480,44 +480,44 @@ strategies.functions = {
elseif main < 3 then
return true
end
input.press("B")
Input.press("B")
else
if strategies.initialize() then
if not inventory.contains(itemName) then
return strategies.reset("Unable to teach move "..itemName.." to "..data.poke, nil, true)
if Strategies.initialize() then
if not Inventory.contains(itemName) then
return Strategies.reset("Unable to teach move "..itemName.." to "..data.poke, nil, true)
end
end
local replacement
if data.replace then
replacement = pokemon.moveIndex(data.replace, data.poke) - 1
replacement = Pokemon.moveIndex(data.replace, data.poke) - 1
else
replacement = 0
end
if inventory.teach(itemName, data.poke, replacement, data.alt) then
if Inventory.teach(itemName, data.poke, replacement, data.alt) then
tempDir = true
else
menu.pause()
Menu.pause()
end
end
end,
skill = function(data)
if completedSkillFor(data) then
if not textbox.isActive() then
if not Textbox.isActive() then
return true
end
input.press("B")
elseif not data.dir or player.face(data.dir) then
if pokemon.use(data.move) then
Input.press("B")
elseif not data.dir or Player.face(data.dir) then
if Pokemon.use(data.move) then
status.tries = status.tries + 1
else
menu.pause()
Menu.pause()
end
end
end,
fly = function(data)
if memory.value("game", "map") == data.map then
if Memory.value("game", "map") == data.map then
return true
end
local cities = {
@ -529,9 +529,9 @@ strategies.functions = {
cinnabar = {70, "Down"},
}
local main = memory.value("menu", "main")
local main = Memory.value("menu", "main")
if main == 228 then
local currentFly = memory.raw(0x1FEF)
local currentFly = Memory.raw(0x1FEF)
local destination = cities[data.dest]
local press
if destination[1] - currentFly == 0 then
@ -539,25 +539,25 @@ strategies.functions = {
else
press = destination[2]
end
input.press(press)
elseif not pokemon.use("fly") then
menu.pause()
Input.press(press)
elseif not Pokemon.use("fly") then
Menu.pause()
end
end,
bicycle = function()
if memory.raw(0x1700) == 1 then
if textbox.handle() then
if Memory.raw(0x1700) == 1 then
if Textbox.handle() then
return true
end
else
return strategies.useItem({item="bicycle"})
return Strategies.useItem({item="bicycle"})
end
end,
wait = function()
print("Please save state")
input.press("Start", 9001)
Input.press("Start", 9001)
end,
emuSpeed = function(data)
@ -566,66 +566,66 @@ strategies.functions = {
end,
waitToTalk = function()
if battle.isActive() then
if Battle.isActive() then
canProgress = false
battle.automate()
elseif textbox.isActive() then
Battle.automate()
elseif Textbox.isActive() then
canProgress = true
input.cancel()
Input.cancel()
elseif canProgress then
return true
end
end,
waitToPause = function()
local main = memory.value("menu", "main")
local main = Memory.value("menu", "main")
if main == 128 then
if canProgress then
return true
end
elseif battle.isActive() then
elseif Battle.isActive() then
canProgress = false
battle.automate()
Battle.automate()
elseif main == 123 then
canProgress = true
input.press("B")
elseif textbox.handle() then
input.press("Start", 2)
Input.press("B")
elseif Textbox.handle() then
Input.press("Start", 2)
end
end,
waitToFight = function(data)
if battle.isActive() then
if Battle.isActive() then
canProgress = true
battle.automate()
Battle.automate()
elseif canProgress then
return true
elseif textbox.handle() then
elseif Textbox.handle() then
if data.dir then
player.interact(data.dir)
Player.interact(data.dir)
else
input.cancel()
Input.cancel()
end
end
end,
allowDeath = function(data)
control.canDie(data.on)
Control.canDie(data.on)
return true
end,
-- ROUTE
dodgePalletBoy = function()
return strategies.dodgeUp(0x0223, 14, 14, 15, 7)
return Strategies.dodgeUp(0x0223, 14, 14, 15, 7)
end,
helix = function()
if battle.handleWild() then
if inventory.contains("helix_fossil") then
if Battle.handleWild() then
if Inventory.contains("helix_fossil") then
return true
end
player.interact("Up")
Player.interact("Up")
end
end,
@ -651,13 +651,13 @@ strategies.functions = {
end,
playPokeflute = function()
if battle.isActive() then
if Battle.isActive() then
return true
end
if memory.value("battle", "menu") == 95 then
input.press("A")
elseif menu.pause() then
inventory.use("pokeflute")
if Memory.value("battle", "menu") == 95 then
Input.press("A")
elseif Menu.pause() then
Inventory.use("pokeflute")
end
end,
@ -668,19 +668,19 @@ strategies.functions = {
else
pos = data.x
end
local newP = memory.raw(pos)
local newP = Memory.raw(pos)
if status.tries == 0 then
status.tries = {start=newP}
elseif status.tries.start ~= newP then
return true
end
input.press(data.dir, 0)
Input.press(data.dir, 0)
end,
}
strategyFunctions = strategies.functions
strategyFunctions = Strategies.functions
function strategies.execute(data)
function Strategies.execute(data)
if strategyFunctions[data.s](data) then
status = {tries=0}
if resetting then
@ -692,21 +692,21 @@ function strategies.execute(data)
return false
end
function strategies.init(midGame)
function Strategies.init(midGame)
if not STREAMING_MODE then
splitTime = utils.timeSince(0)
splitTime = Utils.timeSince(0)
end
if midGame then
combat.factorPP(true)
Combat.factorPP(true)
end
strategies.initGame(midGame)
Strategies.initGame(midGame)
end
function strategies.softReset()
function Strategies.softReset()
status = {}
splitNumber, splitTime = 0, 0
resetting = nil
strategies.resetGame()
Strategies.resetGame()
end
return strategies
return Strategies

View File

@ -1,4 +1,4 @@
local strategies = require "ai.strategies"
local Strategies = require "ai.strategies"
local combat = require "ai.combat"
local control = require "ai.control"
@ -18,24 +18,24 @@ local utils = require "util.utils"
local inventory = require "storage.inventory"
local pokemon = require "storage.pokemon"
local status = strategies.status
local status = Strategies.status
strategies.timeRequirements = {}
Strategies.timeRequirements = {}
-- STRATEGIES
local strategyFunctions = strategies.functions
local strategyFunctions = Strategies.functions
-- PROCESS
function strategies.initGame(midGame)
function Strategies.initGame(midGame)
if not STREAMING_MODE then
-- strategies.setYolo("")
-- Strategies.setYolo("")
end
end
function strategies.resetGame()
status = strategies.status
function Strategies.resetGame()
status = Strategies.status
end
return strategies
return Strategies

View File

@ -1,4 +1,4 @@
local movelist = {}
local Movelist = {}
-- http://bulbapedia.bulbagarden.net/wiki/List_of_moves#List_of_moves
local moves = {
@ -1513,8 +1513,8 @@ local moves = {
},
}
function movelist.get(id)
function Movelist.get(id)
return moves[id]
end
return movelist
return Movelist

View File

@ -1,4 +1,4 @@
local opponents = {
local Opponents = {
RivalGyarados = {
type1 = "water",
@ -222,4 +222,4 @@ local opponents = {
}
return opponents
return Opponents

View File

@ -1,4 +1,4 @@
local paths = {
local Paths = {
-- Red's room
{38, {3,6}, {5,6}, {5,1}, {7,1}},
-- Red's house
@ -447,4 +447,4 @@ local paths = {
{118, {4,2}, {s="champion"}}
}
return paths
return Paths

View File

@ -1,4 +1,4 @@
local paths = {
local Paths = {
-- Red's room
{38, {3,6}, {5,6}, {5,1}, {7,1}},
-- Red's house
@ -34,4 +34,4 @@ local paths = {
}
return paths
return Paths

150
main.lua
View File

@ -1,4 +1,4 @@
-- SETTINGS
-- OPTIONS
RESET_FOR_TIME = true -- Set to false if you just want to see the bot finish a run
@ -14,23 +14,23 @@ INTERNAL = false
local START_WAIT = 99
local battle = require "action.battle"
local textbox = require "action.textbox"
local walk = require "action.walk"
local Battle = require "action.battle"
local Textbox = require "action.textbox"
local Walk = require "action.walk"
local combat = require "ai.combat"
local control = require "ai.control"
local strategies = require("ai."..GAME_NAME..".strategies")
local Combat = require "ai.combat"
local Control = require "ai.control"
local Strategies = require("ai."..GAME_NAME..".strategies")
local bridge = require "util.bridge"
local input = require "util.input"
local memory = require "util.memory"
local menu = require "util.menu"
local paint = require "util.paint"
local utils = require "util.utils"
local settings = require "util.settings"
local Bridge = require "util.bridge"
local Input = require "util.input"
local Memory = require "util.memory"
local Menu = require "util.menu"
local Paint = require "util.paint"
local Utils = require "util.utils"
local Settings = require "util.settings"
local pokemon = require "storage.pokemon"
local Pokemon = require "storage.pokemon"
local hasAlreadyStartedPlaying = false
local inBattle, oldSecs
@ -42,65 +42,65 @@ local criticaled = false
local function startNewAdventure()
local startMenu, withBattleStyle
if YELLOW then
startMenu = memory.raw(0x0F95) == 0
startMenu = Memory.raw(0x0F95) == 0
withBattleStyle = "battle_style"
else
startMenu = memory.value("player", "name") ~= 0
startMenu = Memory.value("player", "name") ~= 0
end
if startMenu and menu.getCol() ~= 0 then
if settings.set("text_speed", "battle_animation", withBattleStyle) then
menu.select(0)
if startMenu and Menu.getCol() ~= 0 then
if Settings.set("text_speed", "battle_animation", withBattleStyle) then
Menu.select(0)
end
elseif math.random(0, START_WAIT) == 0 then
input.press("Start")
Input.press("Start")
end
end
local function choosePlayerNames()
local name
if memory.value("player", "name2") == 80 then
if Memory.value("player", "name2") == 80 then
name = "E"
else
name = "B"
end
textbox.name(name, true)
Textbox.name(name, true)
end
local function pollForResponse()
local response = bridge.process()
local response = Bridge.process()
if response then
bridge.polling = false
textbox.setName(tonumber(response))
Bridge.polling = false
Textbox.setName(tonumber(response))
end
end
local function resetAll()
strategies.softReset()
combat.reset()
control.reset()
walk.reset()
paint.reset()
bridge.reset()
Strategies.softReset()
Combat.reset()
Control.reset()
Walk.reset()
Paint.reset()
Bridge.reset()
oldSecs = 0
running = false
previousPartySize = 0
-- client.speedmode = 200
if CUSTOM_SEED then
strategies.seed = CUSTOM_SEED
print("RUNNING WITH A FIXED SEED ("..strategies.seed.."), every run will play out identically!")
Strategies.seed = CUSTOM_SEED
print("RUNNING WITH A FIXED SEED ("..Strategies.seed.."), every run will play out identically!")
else
strategies.seed = os.time()
Strategies.seed = os.time()
end
math.randomseed(strategies.seed)
math.randomseed(Strategies.seed)
end
-- EXECUTE
control.init()
Control.init()
print("Welcome to PokeBot "..GAME_NAME.." version "..VERSION)
STREAMING_MODE = not walk.init()
STREAMING_MODE = not Walk.init()
if INTERNAL and STREAMING_MODE then
RESET_FOR_TIME = true
end
@ -108,18 +108,18 @@ end
if CUSTOM_SEED then
client.reboot_core()
else
hasAlreadyStartedPlaying = utils.ingame()
hasAlreadyStartedPlaying = Utils.ingame()
end
strategies.init(hasAlreadyStartedPlaying)
Strategies.init(hasAlreadyStartedPlaying)
if RESET_FOR_TIME and hasAlreadyStartedPlaying then
RESET_FOR_TIME = false
print("Disabling time-limit resets as the game is already running. Please reset the emulator and restart the script if you'd like to go for a fast time.")
end
if STREAMING_MODE then
bridge.init()
Bridge.init()
else
input.setDebug(true)
Input.setDebug(true)
end
-- Main loop
@ -127,23 +127,23 @@ end
local previousMap
while true do
local currentMap = memory.value("game", "map")
local currentMap = Memory.value("game", "map")
if currentMap ~= previousMap then
input.clear()
Input.clear()
previousMap = currentMap
end
if strategies.frames then
if memory.value("game", "battle") == 0 then
strategies.frames = strategies.frames + 1
if Strategies.frames then
if Memory.value("game", "battle") == 0 then
Strategies.frames = Strategies.frames + 1
end
gui.text(0, 80, strategies.frames)
gui.text(0, 80, Strategies.frames)
end
if bridge.polling then
if Bridge.polling then
pollForResponse()
end
if not input.update() then
if not utils.ingame() then
if not Input.update() then
if not Utils.ingame() then
if currentMap == 0 then
if running then
if not hasAlreadyStartedPlaying then
@ -157,69 +157,69 @@ while true do
end
else
if not running then
bridge.liveSplit()
Bridge.liveSplit()
running = true
end
choosePlayerNames()
end
else
local battleState = memory.value("game", "battle")
local battleState = Memory.value("game", "battle")
if battleState > 0 then
if battleState == 1 then
if not inBattle then
control.wildEncounter()
Control.wildEncounter()
inBattle = true
end
end
local isCritical
local battleMenu = memory.value("battle", "menu")
local battleMenu = Memory.value("battle", "menu")
if battleMenu == 94 then
isCritical = false
elseif memory.double("battle", "our_hp") == 0 then
if memory.value("battle", "critical") == 1 then
elseif Memory.double("battle", "our_hp") == 0 then
if Memory.value("battle", "critical") == 1 then
isCritical = true
end
end
if isCritical ~= nil and isCritical ~= criticaled then
criticaled = isCritical
strategies.criticaled = criticaled
Strategies.criticaled = criticaled
end
else
inBattle = false
end
local currentHP = pokemon.index(0, "hp")
local currentHP = Pokemon.index(0, "hp")
-- if currentHP ~= lastHP then
-- bridge.hp(currentHP, pokemon.index(0, "max_hp"))
-- Bridge.hp(currentHP, Pokemon.index(0, "max_hp"))
-- lastHP = currentHP
-- end
if currentHP == 0 and not control.canDie() and pokemon.index(0) > 0 then
strategies.death(currentMap)
elseif walk.strategy then
if strategies.execute(walk.strategy) then
walk.traverse(currentMap)
if currentHP == 0 and not Control.canDie() and Pokemon.index(0) > 0 then
Strategies.death(currentMap)
elseif Walk.strategy then
if Strategies.execute(Walk.strategy) then
Walk.traverse(currentMap)
end
elseif battleState > 0 then
if not control.shouldCatch(partySize) then
battle.automate()
if not Control.shouldCatch(partySize) then
Battle.automate()
end
elseif textbox.handle() then
walk.traverse(currentMap)
elseif Textbox.handle() then
Walk.traverse(currentMap)
end
end
end
if STREAMING_MODE then
local newSecs = memory.raw(0x1A44)
if newSecs ~= oldSecs and (newSecs > 0 or memory.raw(0x1A45) > 0) then
bridge.time(utils.elapsedTime())
local newSecs = Memory.raw(0x1A44)
if newSecs ~= oldSecs and (newSecs > 0 or Memory.raw(0x1A45) > 0) then
Bridge.time(Utils.elapsedTime())
oldSecs = newSecs
end
elseif PAINT_ON then
paint.draw(currentMap)
Paint.draw(currentMap)
end
input.advance()
Input.advance()
emu.frameadvance()
end
bridge.close()
Bridge.close()

View File

@ -1,11 +1,11 @@
local inventory = {}
local Inventory = {}
local pokemon = require "storage.pokemon"
local Input = require "util.input"
local Memory = require "util.memory"
local Menu = require "util.menu"
local Utils = require "util.utils"
local input = require "util.input"
local memory = require "util.memory"
local menu = require "util.menu"
local utils = require "util.utils"
local Pokemon = require "storage.pokemon"
local items = {
pokeball = 4,
@ -56,28 +56,28 @@ local ITEM_BASE = 0x131E
-- Data
function inventory.indexOf(name)
function Inventory.indexOf(name)
local searchID = items[name]
for i=0,19 do
local iidx = ITEM_BASE + i * 2
if memory.raw(iidx) == searchID then
if Memory.raw(iidx) == searchID then
return i
end
end
return -1
end
function inventory.count(name)
local index = inventory.indexOf(name)
function Inventory.count(name)
local index = Inventory.indexOf(name)
if index ~= -1 then
return memory.raw(ITEM_BASE + index * 2 + 1)
return Memory.raw(ITEM_BASE + index * 2 + 1)
end
return 0
end
function inventory.contains(...)
function Inventory.contains(...)
for i,name in ipairs(arg) do
if inventory.count(name) > 0 then
if Inventory.count(name) > 0 then
return name
end
end
@ -85,38 +85,38 @@ end
-- Actions
function inventory.teach(item, poke, replaceIdx, altPoke)
local main = memory.value("menu", "main")
local column = menu.getCol()
function Inventory.teach(item, poke, replaceIdx, altPoke)
local main = Memory.value("menu", "main")
local column = Menu.getCol()
if main == 144 then
if column == 5 then
menu.select(replaceIdx, true)
Menu.select(replaceIdx, true)
else
input.press("A")
Input.press("A")
end
elseif main == 128 then
if column == 5 then
menu.select(inventory.indexOf(item), "accelerate", true)
Menu.select(Inventory.indexOf(item), "accelerate", true)
elseif column == 11 then
menu.select(2, true)
Menu.select(2, true)
elseif column == 14 then
menu.select(0, true)
Menu.select(0, true)
end
elseif main == 103 then
input.press("B")
Input.press("B")
elseif main == 64 or main == 96 or main == 192 then
if column == 5 then
menu.select(replaceIdx, true)
Menu.select(replaceIdx, true)
elseif column == 14 then
input.press("A")
Input.press("A")
elseif column == 15 then
menu.select(0, true)
Menu.select(0, true)
else
local idx = 0
if poke then
idx = pokemon.indexOf(poke, altPoke)
idx = Pokemon.indexOf(poke, altPoke)
end
menu.select(idx, true)
Menu.select(idx, true)
end
else
return false
@ -124,77 +124,77 @@ function inventory.teach(item, poke, replaceIdx, altPoke)
return true
end
function inventory.isFull()
return memory.raw(0x1345) > 0
function Inventory.isFull()
return Memory.raw(0x1345) > 0
end
function inventory.use(item, poke, midfight)
function Inventory.use(item, poke, midfight)
if midfight then
local battleMenu = memory.value("battle", "menu")
local battleMenu = Memory.value("battle", "menu")
if battleMenu == 94 then
local rowSelected = memory.value("menu", "row")
if menu.getCol() == 9 then
local rowSelected = Memory.value("menu", "row")
if Menu.getCol() == 9 then
if rowSelected == 0 then
input.press("Down")
Input.press("Down")
else
input.press("A")
Input.press("A")
end
else
input.press("Left")
Input.press("Left")
end
elseif battleMenu == 233 then
menu.select(inventory.indexOf(item), "accelerate", true)
elseif utils.onPokemonSelect(battleMenu) then
Menu.select(Inventory.indexOf(item), "accelerate", true)
elseif Utils.onPokemonSelect(battleMenu) then
if poke then
if type(poke) == "string" then
poke = pokemon.indexOf(poke)
poke = Pokemon.indexOf(poke)
end
menu.select(poke, true)
Menu.select(poke, true)
else
input.press("A")
Input.press("A")
end
else
input.press("B")
Input.press("B")
end
return
end
local main = memory.value("menu", "main")
local column = menu.getCol()
local main = Memory.value("menu", "main")
local column = Menu.getCol()
if main == 144 then
if memory.value("battle", "menu") == 95 then
input.press("B")
if Memory.value("battle", "menu") == 95 then
Input.press("B")
else
local idx = 0
if poke then
idx = pokemon.indexOf(poke)
idx = Pokemon.indexOf(poke)
end
menu.select(idx, true)
Menu.select(idx, true)
end
elseif main == 128 or main == 60 then
if column == 5 then
menu.select(inventory.indexOf(item), "accelerate", true)
Menu.select(Inventory.indexOf(item), "accelerate", true)
elseif column == 11 then
menu.select(2, true)
Menu.select(2, true)
elseif column == 14 then
menu.select(0, true)
Menu.select(0, true)
else
local index = 0
if poke then
index = pokemon.indexOf(poke)
index = Pokemon.indexOf(poke)
end
menu.select(index, true)
Menu.select(index, true)
end
elseif main == 228 then
if column == 14 and memory.value("battle", "menu") == 95 then
input.press("B")
if column == 14 and Memory.value("battle", "menu") == 95 then
Input.press("B")
end
elseif main == 103 then
input.press("B")
Input.press("B")
else
return false
end
return true
end
return inventory
return Inventory

View File

@ -1,10 +1,9 @@
local pokemon = {}
local Pokemon = {}
local bridge = require "util.bridge"
local input = require "util.input"
local memory = require "util.memory"
local menu = require "util.menu"
local utils = require "util.utils"
local Bridge = require "util.bridge"
local Input = require "util.input"
local Memory = require "util.memory"
local Menu = require "util.menu"
local pokeIDs = {
rhydon = 1,
@ -98,13 +97,13 @@ local function index(index, offset)
double = dataTable[2]
end
local address = getAddress(index) + offset
local value = memory.raw(address)
local value = Memory.raw(address)
if double then
value = value + memory.raw(address + 1)
value = value + Memory.raw(address + 1)
end
return value
end
pokemon.index = index
Pokemon.index = index
local function indexOf(...)
for ni,name in ipairs(arg) do
@ -118,20 +117,20 @@ local function indexOf(...)
end
return -1
end
pokemon.indexOf = indexOf
Pokemon.indexOf = indexOf
-- Table functions
function pokemon.battleMove(name)
function Pokemon.battleMove(name)
local mid = moveList[name]
for i=1,4 do
if mid == memory.raw(0x101B + i) then
if mid == Memory.raw(0x101B + i) then
return i
end
end
end
function pokemon.moveIndex(move, pokemon)
function Pokemon.moveIndex(move, pokemon)
local pokemonIdx
if pokemon then
pokemonIdx = indexOf(pokemon)
@ -141,21 +140,21 @@ function pokemon.moveIndex(move, pokemon)
local address = getAddress(pokemonIdx) + 7
local mid = moveList[move]
for i=1,4 do
if mid == memory.raw(address + i) then
if mid == Memory.raw(address + i) then
return i
end
end
end
function pokemon.info(name, offset)
function Pokemon.info(name, offset)
return index(indexOf(name), offset)
end
function pokemon.getID(name)
function Pokemon.getID(name)
return pokeIDs[name]
end
function pokemon.getName(id)
function Pokemon.getName(id)
for name,pid in pairs(pokeIDs) do
if pid == id then
return name
@ -163,7 +162,7 @@ function pokemon.getName(id)
end
end
function pokemon.getSacrifice(...)
function Pokemon.getSacrifice(...)
for i,name in ipairs(arg) do
local pokemonIndex = indexOf(name)
if pokemonIndex ~= -1 and index(pokemonIndex, "hp") > 0 then
@ -172,7 +171,7 @@ function pokemon.getSacrifice(...)
end
end
function pokemon.inParty(...)
function Pokemon.inParty(...)
for i,name in ipairs(arg) do
if indexOf(name) ~= -1 then
return name
@ -180,12 +179,12 @@ function pokemon.inParty(...)
end
end
function pokemon.forMove(move)
function Pokemon.forMove(move)
local moveID = moveList[move]
for i=0,5 do
local address = getAddress(i)
for j=8,11 do
if memory.raw(address + j) == moveID then
if Memory.raw(address + j) == moveID then
return i
end
end
@ -193,16 +192,16 @@ function pokemon.forMove(move)
return -1
end
function pokemon.hasMove(move)
return pokemon.forMove(move) ~= -1
function Pokemon.hasMove(move)
return Pokemon.forMove(move) ~= -1
end
function pokemon.updateParty()
local partySize = memory.value("player", "party_size")
function Pokemon.updateParty()
local partySize = Memory.value("player", "party_size")
if partySize ~= previousPartySize then
local poke = pokemon.inParty("oddish", "paras", "spearow", "pidgey", "nidoran", "squirtle")
local poke = Pokemon.inParty("oddish", "paras", "spearow", "pidgey", "nidoran", "squirtle")
if poke then
bridge.caught(poke)
Bridge.caught(poke)
previousPartySize = partySize
end
end
@ -210,8 +209,8 @@ end
-- General
function pokemon.isOpponent(...)
local oid = memory.value("battle", "opponent_id")
function Pokemon.isOpponent(...)
local oid = Memory.value("battle", "opponent_id")
for i,name in ipairs(arg) do
if oid == pokeIDs[name] then
return name
@ -219,8 +218,8 @@ function pokemon.isOpponent(...)
end
end
function pokemon.isDeployed(...)
local deployedID = memory.value("battle", "our_id")
function Pokemon.isDeployed(...)
local deployedID = Memory.value("battle", "our_id")
for i,name in ipairs(arg) do
if deployedID == pokeIDs[name] then
return name
@ -228,36 +227,36 @@ function pokemon.isDeployed(...)
end
end
function pokemon.isEvolving()
return memory.value("menu", "pokemon") == 144
function Pokemon.isEvolving()
return Memory.value("menu", "pokemon") == 144
end
function pokemon.getExp()
return memory.raw(0x117A) * 256 + memory.raw(0x117B)
function Pokemon.getExp()
return Memory.raw(0x117A) * 256 + Memory.raw(0x117B)
end
function pokemon.inRedBar()
function Pokemon.inRedBar()
local curr_hp, max_hp = index(0, "hp"), index(0, "max_hp")
return curr_hp / max_hp <= 0.2
end
function pokemon.use(move)
local main = memory.value("menu", "main")
local pokeName = pokemon.forMove(move)
function Pokemon.use(move)
local main = Memory.value("menu", "main")
local pokeName = Pokemon.forMove(move)
if main == 141 then
input.press("A")
Input.press("A")
elseif main == 128 then
local column = menu.getCol()
local column = Menu.getCol()
if column == 11 then
menu.select(1, true)
Menu.select(1, true)
elseif column == 10 or column == 12 then
local midx = 0
local menuSize = memory.value("menu", "size")
local menuSize = Memory.value("menu", "size")
if menuSize == 4 then
if move == "dig" then
midx = 1
elseif move == "surf" then
if pokemon.inParty("paras") then
if Pokemon.inParty("paras") then
midx = 1
end
end
@ -268,18 +267,18 @@ function pokemon.use(move)
midx = 1
end
end
menu.select(midx, true)
Menu.select(midx, true)
else
input.press("B")
Input.press("B")
end
elseif main == 103 then
menu.select(pokeName, true)
Menu.select(pokeName, true)
elseif main == 228 then
input.press("B")
Input.press("B")
else
return false
end
return true
end
return pokemon
return Pokemon

View File

@ -1,4 +1,4 @@
local bridge = {}
local Bridge = {}
local socket
if INTERNAL then
@ -36,7 +36,7 @@ end
-- Wrapper functions
function bridge.init()
function Bridge.init()
if socket then
-- io.popen("java -jar Main.jar")
client = socket.connect("127.0.0.1", 13378)
@ -51,17 +51,17 @@ function bridge.init()
end
end
function bridge.tweet(message) -- Two of the same tweet in a row will only send one
function Bridge.tweet(message) -- Two of the same tweet in a row will only send one
print("tweet::"..message)
return send("tweet", message)
end
function bridge.pollForName()
bridge.polling = true
function Bridge.pollForName()
Bridge.polling = true
send("poll_name")
end
function bridge.chat(message, extra)
function Bridge.chat(message, extra)
if extra then
print(message.." || "..extra)
else
@ -70,25 +70,25 @@ function bridge.chat(message, extra)
return send("msg", message)
end
function bridge.time(message)
function Bridge.time(message)
if not timeStopped then
return send("time", message)
end
end
function bridge.stats(message)
function Bridge.stats(message)
return send("stats", message)
end
function bridge.command(command)
function Bridge.command(command)
return send("livesplit_command", command);
end
function bridge.comparisonTime()
function Bridge.comparisonTime()
return send("livesplit_getcomparisontime");
end
function bridge.process()
function Bridge.process()
local response = readln()
if response then
-- print(">"..response)
@ -100,42 +100,42 @@ function bridge.process()
end
end
function bridge.input(key)
function Bridge.input(key)
send("input", key)
end
function bridge.caught(name)
function Bridge.caught(name)
if name then
send("caught", name)
end
end
function bridge.hp(curr, max)
function Bridge.hp(curr, max)
send("hp", curr..","..max)
end
function bridge.liveSplit()
function Bridge.liveSplit()
send("start")
timeStopped = false
end
function bridge.split(finished)
function Bridge.split(finished)
if finished then
timeStopped = true
end
send("split")
end
function bridge.encounter()
function Bridge.encounter()
send("encounter")
end
function bridge.reset()
function Bridge.reset()
send("reset")
timeStopped = false
end
function bridge.close()
function Bridge.close()
if client then
client:close()
client = nil
@ -143,4 +143,4 @@ function bridge.close()
print("Bridge closed")
end
return bridge
return Bridge

View File

@ -1,7 +1,7 @@
local input = {}
local Input = {}
local bridge = require "util.bridge"
local memory = require "util.memory"
local Bridge = require "util.bridge"
local Memory = require "util.memory"
local lastSend
local currentButton, remainingFrames, setForFrame
@ -11,7 +11,7 @@ local bCancel = true
local function bridgeButton(btn)
if btn ~= lastSend then
lastSend = btn
bridge.input(btn)
Bridge.input(btn)
end
end
@ -28,7 +28,7 @@ local function sendButton(button, ab)
setForFrame = button
end
function input.press(button, frames)
function Input.press(button, frames)
if setForFrame then
print("ERR: Reassigning "..setForFrame.." to "..button)
return
@ -49,9 +49,9 @@ function input.press(button, frames)
sendButton(button)
end
function input.cancel(accept)
if accept and memory.value("menu", "shop_current") == 20 then
input.press(accept)
function Input.cancel(accept)
if accept and Memory.value("menu", "shop_current") == 20 then
Input.press(accept)
else
local button
if bCancel then
@ -65,18 +65,18 @@ function input.cancel(accept)
end
end
function input.escape()
function Input.escape()
local inputTable = {Right=true, Down=true}
joypad.set(inputTable)
bridgeButton("D,R")
end
function input.clear()
function Input.clear()
currentButton = nil
remainingFrames = -1
end
function input.update()
function Input.update()
if currentButton then
remainingFrames = remainingFrames - 1
if remainingFrames >= 0 then
@ -91,19 +91,19 @@ function input.update()
setForFrame = nil
end
function input.advance()
function Input.advance()
if not setForFrame then
bridgeButton("e")
end
end
function input.setDebug(enabled)
function Input.setDebug(enabled)
debug = enabled
end
function input.test(fn, completes)
function Input.test(fn, completes)
while true do
if not input.update() then
if not Input.update() then
if fn() and completes then
break
end
@ -115,4 +115,4 @@ function input.test(fn, completes)
end
end
return input
return Input

View File

@ -1,9 +1,5 @@
local Memory = {}
-- memory.usememorydomain("WRAM")
-- print(memory.getcurrentmemorydomain())
-- print(memory.getcurrentmemorydomainsize())
local memoryNames = {
setting = {
text_speed = 0x0D3D,

View File

@ -1,7 +1,7 @@
local menu = {}
local Menu = {}
local input = require "util.input"
local memory = require "util.memory"
local Input = require "util.input"
local Memory = require "util.memory"
local yellow = GAME_NAME == "yellow"
@ -15,9 +15,9 @@ local function getRow(menuType, scrolls)
else
menuType = "row"
end
local row = memory.value("menu", menuType)
local row = Memory.value("menu", menuType)
if scrolls then
row = row + memory.value("menu", "scroll_offset")
row = row + Memory.value("menu", "scroll_offset")
end
return row
end
@ -39,7 +39,7 @@ local function setRow(desired, throttle, scrolls, menuType, loop)
else
sliding = false
end
return menu.balance(currentRow, desired, true, loop, throttle)
return Menu.balance(currentRow, desired, true, loop, throttle)
end
local function isCurrently(desired, menuType)
@ -48,48 +48,48 @@ local function isCurrently(desired, menuType)
else
menuType = "current"
end
return memory.value("menu", menuType) == desired
return Memory.value("menu", menuType) == desired
end
menu.isCurrently = isCurrently
Menu.isCurrently = isCurrently
-- Menu
function menu.getCol()
return memory.value("menu", "column")
function Menu.getCol()
return Memory.value("menu", "column")
end
function menu.open(desired, atIndex, menuType)
function Menu.open(desired, atIndex, menuType)
if isCurrently(desired, menuType) then
return true
end
menu.select(atIndex, false, false, menuType)
Menu.select(atIndex, false, false, menuType)
return false
end
function menu.select(option, throttle, scrolls, menuType, dontPress, loop)
function Menu.select(option, throttle, scrolls, menuType, dontPress, loop)
if setRow(option, throttle, scrolls, menuType, loop) then
local delay = 1
if throttle then
delay = 2
end
if not dontPress then
input.press("A", delay)
Input.press("A", delay)
end
return true
end
end
function menu.cancel(desired, menuType)
function Menu.cancel(desired, menuType)
if not isCurrently(desired, menuType) then
return true
end
input.press("B")
Input.press("B")
return false
end
-- Selections
function menu.balance(current, desired, inverted, looping, throttle)
function Menu.balance(current, desired, inverted, looping, throttle)
if current == desired then
sliding = false
return true
@ -104,14 +104,14 @@ function menu.balance(current, desired, inverted, looping, throttle)
goUp = not goUp
end
if goUp then
input.press("Up", throttle)
Input.press("Up", throttle)
else
input.press("Down", throttle)
Input.press("Down", throttle)
end
return false
end
function menu.sidle(current, desired, looping, throttle)
function Menu.sidle(current, desired, looping, throttle)
if current == desired then
return true
end
@ -125,29 +125,29 @@ function menu.sidle(current, desired, looping, throttle)
goLeft = not goLeft
end
if goLeft then
input.press("Left", throttle)
Input.press("Left", throttle)
else
input.press("Right", throttle)
Input.press("Right", throttle)
end
return false
end
function menu.setCol(desired)
return menu.sidle(menu.getCol(), desired)
function Menu.setCol(desired)
return Menu.sidle(Menu.getCol(), desired)
end
-- Options
function menu.setOption(name, desired)
function Menu.setOption(name, desired)
if yellow then
local rowFor = {
text_speed = 0,
battle_animation = 1,
battle_style = 2
}
local currentRow = memory.raw(0x0D3D, true)
if menu.balance(currentRow, rowFor[name], true, false, true) then
input.press("Left")
local currentRow = Memory.raw(0x0D3D, true)
if Menu.balance(currentRow, rowFor[name], true, false, true) then
Input.press("Left")
end
else
local rowFor = {
@ -155,11 +155,11 @@ function menu.setOption(name, desired)
battle_animation = 8,
battle_style = 13
}
if memory.value("setting", name) == desired then
if Memory.value("setting", name) == desired then
return true
end
if setRow(rowFor[name], true, false, "settings") then
menu.setCol(desired)
Menu.setCol(desired)
end
end
return false
@ -167,31 +167,31 @@ end
-- Pause menu
function menu.isOpen()
return memory.value("game", "textbox") == 1 or memory.value("menu", "current") == 24
function Menu.isOpen()
return Memory.value("game", "textbox") == 1 or Memory.value("menu", "current") == 24
end
function menu.close()
if memory.value("game", "textbox") == 0 and memory.value("menu", "main") < 8 then
function Menu.close()
if Memory.value("game", "textbox") == 0 and Memory.value("menu", "main") < 8 then
return true
end
input.press("B")
Input.press("B")
end
function menu.pause()
if memory.value("game", "textbox") == 1 then
if memory.value("battle", "menu") == 95 then
input.cancel()
function Menu.pause()
if Memory.value("game", "textbox") == 1 then
if Memory.value("battle", "menu") == 95 then
Input.cancel()
else
local main = memory.value("menu", "main")
local main = Memory.value("menu", "main")
if main > 2 and main ~= 64 then
return true
end
input.press("B")
Input.press("B")
end
else
input.press("Start", 2)
Input.press("Start", 2)
end
end
return menu
return Menu

View File

@ -1,26 +1,25 @@
local paint = {}
local Paint = {}
local memory = require "util.memory"
local player = require "util.player"
local utils = require "util.utils"
local Memory = require "util.memory"
local Player = require "util.player"
local Utils = require "util.utils"
local inventory = require "storage.inventory"
local pokemon = require "storage.pokemon"
local Pokemon = require "storage.pokemon"
local encounters = 0
local elapsedTime = utils.elapsedTime
local elapsedTime = Utils.elapsedTime
function paint.draw(currentMap)
local px, py = player.position()
function Paint.draw(currentMap)
local px, py = Player.position()
gui.text(0, 14, currentMap..": "..px.." "..py)
gui.text(0, 0, elapsedTime())
if memory.value("battle", "our_id") > 0 then
local hp = pokemon.index(0, "hp")
if Memory.value("battle", "our_id") > 0 then
local hp = Pokemon.index(0, "hp")
local hpStatus
if hp == 0 then
hpStatus = "DEAD"
elseif hp <= math.ceil(pokemon.index(0, "max_hp") * 0.2) then
elseif hp <= math.ceil(Pokemon.index(0, "max_hp") * 0.2) then
hpStatus = "RED"
end
if hpStatus then
@ -28,30 +27,30 @@ function paint.draw(currentMap)
end
end
local nidx = pokemon.indexOf("nidoran", "nidorino", "nidoking")
local nidx = Pokemon.indexOf("nidoran", "nidorino", "nidoking")
if nidx ~= -1 then
local att = pokemon.index(nidx, "attack")
local def = pokemon.index(nidx, "defense")
local spd = pokemon.index(nidx, "speed")
local scl = pokemon.index(nidx, "special")
local att = Pokemon.index(nidx, "attack")
local def = Pokemon.index(nidx, "defense")
local spd = Pokemon.index(nidx, "speed")
local scl = Pokemon.index(nidx, "special")
gui.text(100, 0, att.." "..def.." "..spd.." "..scl)
end
local enc = " encounter"
if encounters ~= 1 then
enc = enc.."s"
end
gui.text(0, 116, memory.value("battle", "critical"))
gui.text(0, 125, memory.value("player", "repel"))
gui.text(0, 116, Memory.value("battle", "critical"))
gui.text(0, 125, Memory.value("player", "repel"))
gui.text(0, 134, encounters..enc)
return true
end
function paint.wildEncounters(count)
function Paint.wildEncounters(count)
encounters = count
end
function paint.reset()
function Paint.reset()
encounters = 0
end
return paint
return Paint

View File

@ -1,38 +1,38 @@
local player = {}
local Player = {}
local textbox = require "action.textbox"
local Textbox = require "action.textbox"
local input = require "util.input"
local memory = require "util.memory"
local Input = require "util.input"
local Memory = require "util.memory"
local facingDirections = {Up=8, Right=1, Left=2, Down=4}
function player.isFacing(direction)
return memory.value("player", "facing") == facingDirections[direction]
function Player.isFacing(direction)
return Memory.value("player", "facing") == facingDirections[direction]
end
function player.face(direction)
if player.isFacing(direction) then
function Player.face(direction)
if Player.isFacing(direction) then
return true
end
if textbox.handle() then
input.press(direction, 0)
if Textbox.handle() then
Input.press(direction, 0)
end
end
function player.interact(direction)
if player.face(direction) then
input.press("A", 2)
function Player.interact(direction)
if Player.face(direction) then
Input.press("A", 2)
return true
end
end
function player.isMoving()
return memory.value("player", "moving") ~= 0
function Player.isMoving()
return Memory.value("player", "moving") ~= 0
end
function player.position()
return memory.value("player", "x"), memory.value("player", "y")
function Player.position()
return Memory.value("player", "x"), Memory.value("player", "y")
end
return player
return Player

View File

@ -1,7 +1,7 @@
local settings = {}
local Settings = {}
local memory = require "util.memory"
local menu = require "util.menu"
local Memory = require "util.memory"
local Menu = require "util.menu"
local yellow = YELLOW
@ -30,23 +30,23 @@ local function isEnabled(name)
battle_animation = 128,
battle_style = 64
}
local settingMask = memory.value("setting", "yellow_bitmask", true)
local settingMask = Memory.value("setting", "yellow_bitmask", true)
return bit.band(settingMask, matching[name]) == desired[name]
else
return memory.value("setting", name) == desired[name]
return Memory.value("setting", name) == desired[name]
end
end
function settings.set(...)
function Settings.set(...)
for i,name in ipairs(arg) do
if not isEnabled(name) then
if menu.open(settings_menu, 1) then
menu.setOption(name, desired[name])
if Menu.open(settings_menu, 1) then
Menu.setOption(name, desired[name])
end
return false
end
end
return menu.cancel(settings_menu)
return Menu.cancel(settings_menu)
end
return settings
return Settings

View File

@ -1,20 +1,20 @@
local utils = {}
local Utils = {}
local memory = require "util.memory"
local Memory = require "util.memory"
-- GENERAL
function utils.dist(x1, y1, x2, y2)
function Utils.dist(x1, y1, x2, y2)
return math.sqrt(math.pow(x2 - x1, 2) + math.pow(y2 - y1, 2))
end
function utils.each(table, func)
function Utils.each(table, func)
for key,val in pairs(table) do
func(key.." = "..tostring(val)..",")
end
end
function utils.eachi(table, func)
function Utils.eachi(table, func)
for idx,val in ipairs(table) do
if val then
func(idx.." "..val)
@ -24,7 +24,7 @@ function utils.eachi(table, func)
end
end
function utils.match(needle, haystack)
function Utils.match(needle, haystack)
for i,val in ipairs(haystack) do
if needle == val then
return true
@ -33,7 +33,7 @@ function utils.match(needle, haystack)
return false
end
function utils.key(needle, haystack)
function Utils.key(needle, haystack)
for key,val in pairs(haystack) do
if needle == val then
return key
@ -44,7 +44,7 @@ end
-- GAME
function utils.canPotionWith(potion, forDamage, curr_hp, max_hp)
function Utils.canPotionWith(potion, forDamage, curr_hp, max_hp)
local potion_hp
if potion == "full_restore" then
potion_hp = 9001
@ -56,20 +56,20 @@ function utils.canPotionWith(potion, forDamage, curr_hp, max_hp)
return math.min(curr_hp + potion_hp, max_hp) >= forDamage - 1
end
function utils.ingame()
return memory.raw(0x020E) > 0
function Utils.ingame()
return Memory.raw(0x020E) > 0
end
function utils.onPokemonSelect(battleMenu)
function Utils.onPokemonSelect(battleMenu)
return battleMenu == 8 or battleMenu == 48 or battleMenu == 184 or battleMenu == 224
end
-- TIME
function utils.igt()
local secs = memory.raw(0x1A44)
local mins = memory.raw(0x1A43)
local hours = memory.raw(0x1A41)
function Utils.igt()
local secs = Memory.raw(0x1A44)
local mins = Memory.raw(0x1A43)
local hours = Memory.raw(0x1A41)
return secs + mins * 60 + hours * 3600
end
@ -80,8 +80,8 @@ local function clockSegment(unit)
return unit
end
function utils.timeSince(prevTime)
local currTime = utils.igt()
function Utils.timeSince(prevTime)
local currTime = Utils.igt()
local diff = currTime - prevTime
local timeString
if diff > 0 then
@ -92,23 +92,23 @@ function utils.timeSince(prevTime)
return currTime, timeString
end
function utils.elapsedTime()
local secs = memory.raw(0x1A44)
function Utils.elapsedTime()
local secs = Memory.raw(0x1A44)
if secs < 10 then
secs = "0"..secs
end
local mins = memory.raw(0x1A43)
local mins = Memory.raw(0x1A43)
if mins < 10 then
mins = "0"..mins
end
return memory.raw(0x1A41)..":"..mins..":"..secs
return Memory.raw(0x1A41)..":"..mins..":"..secs
end
function utils.frames()
local totalFrames = memory.raw(0x1A41) * 60
totalFrames = (totalFrames + memory.raw(0x1A43)) * 60
totalFrames = (totalFrames + memory.raw(0x1A44)) * 60
return totalFrames + memory.raw(0x1A45)
function Utils.frames()
local totalFrames = Memory.raw(0x1A41) * 60
totalFrames = (totalFrames + Memory.raw(0x1A43)) * 60
totalFrames = (totalFrames + Memory.raw(0x1A44)) * 60
return totalFrames + Memory.raw(0x1A45)
end
return utils
return Utils