Track data over the course of each run
This commit is contained in:
parent
7dfb5c7978
commit
9fad2ec9e5
|
@ -4,6 +4,8 @@ local Input = require "util.input"
|
|||
local Memory = require "util.memory"
|
||||
local Menu = require "util.menu"
|
||||
|
||||
local Data = require "data.data"
|
||||
|
||||
local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ *():;[]ab-?!mf/.,"
|
||||
-- local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ *():;[]ポモ-?!♂♀/.,"
|
||||
|
||||
|
@ -82,6 +84,7 @@ function Textbox.setName(name)
|
|||
nidoIdx = name + 1
|
||||
nidoName = getLetterAt(name)
|
||||
end
|
||||
Data.run.voted_name = nidoName
|
||||
end
|
||||
|
||||
function Textbox.isActive()
|
||||
|
|
|
@ -9,6 +9,7 @@ local Memory = require "util.memory"
|
|||
local Paint = require "util.paint"
|
||||
local Utils = require "util.utils"
|
||||
|
||||
local Data = require "data.data"
|
||||
local Inventory = require "storage.inventory"
|
||||
local Pokemon = require "storage.pokemon"
|
||||
|
||||
|
@ -19,11 +20,11 @@ local canDie, shouldFight, minExp
|
|||
local shouldCatch, attackIdx
|
||||
local extraEncounter, maxEncounters
|
||||
local battleYolo
|
||||
local encountersSection
|
||||
|
||||
local yellow = YELLOW
|
||||
|
||||
Control.areaName = "Unknown"
|
||||
Control.moonEncounters = nil
|
||||
Control.getMoonExp = true
|
||||
Control.yolo = false
|
||||
|
||||
|
@ -82,8 +83,17 @@ local controlFunctions = {
|
|||
shouldFight = {{name="rattata"}, {name="pidgey"}, {name="nidoran"}, {name="nidoranf",levels={2}}}
|
||||
end,
|
||||
|
||||
trackEncounters = function(data)
|
||||
local area = data.area
|
||||
if area then
|
||||
encountersSection = "encounters_"..area
|
||||
Data.run[encountersSection] = 0
|
||||
else
|
||||
encountersSection = nil
|
||||
end
|
||||
end,
|
||||
|
||||
startMtMoon = function()
|
||||
Control.moonEncounters = 0
|
||||
Control.canDie(false)
|
||||
Control.getMoonExp = not yellow
|
||||
end,
|
||||
|
@ -203,7 +213,7 @@ function Control.canCatch(partySize)
|
|||
if yellow and Pokemon.inParty("nidoran", "nidorino", "nidoking") and Pokemon.inParty("pidgey", "spearow") then
|
||||
return false
|
||||
end
|
||||
Strategies.reset("Not enough PokeBalls", pokeballs)
|
||||
Strategies.reset("pokeballs", "Not enough PokeBalls", pokeballs)
|
||||
return false
|
||||
end
|
||||
return true
|
||||
|
@ -213,7 +223,7 @@ function Control.shouldCatch(partySize)
|
|||
if maxEncounters and encounters > maxEncounters then
|
||||
local extraCount = extraEncounter and Pokemon.inParty(extraEncounter)
|
||||
if not extraCount or encounters > maxEncounters + 1 then
|
||||
Strategies.reset("Too many encounters", encounters)
|
||||
Strategies.reset("encounters", "Too many encounters", encounters)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
@ -301,11 +311,13 @@ function Control.encounter(battleState)
|
|||
Bridge.chat("gen 1 missed :( (1 in 256 chance)")
|
||||
end
|
||||
Control.missed = true
|
||||
Data.increment("misses")
|
||||
end
|
||||
end
|
||||
end
|
||||
if isCritical ~= nil and isCritical ~= Control.criticaled then
|
||||
Control.criticaled = isCritical
|
||||
Data.increment("criticals")
|
||||
end
|
||||
if wildBattle then
|
||||
local opponentAlive = Battle.opponentAlive()
|
||||
|
@ -316,11 +328,16 @@ function Control.encounter(battleState)
|
|||
encounters = encounters + 1
|
||||
Paint.wildEncounters(encounters)
|
||||
Bridge.encounter()
|
||||
if Control.moonEncounters then
|
||||
if INTERNAL and STREAMING_MODE and Pokemon.isOpponent("zubat") then
|
||||
Bridge.chat("NightBat")
|
||||
if encountersSection then
|
||||
Data.increment(encountersSection)
|
||||
|
||||
if Pokemon.isOpponent("zubat") then
|
||||
local zubatCount = Data.increment("encounters_zubats")
|
||||
Data.run.encounters_zubats = zubatCount
|
||||
if INTERNAL and STREAMING_MODE then
|
||||
Bridge.chat(Utils.multiplyString("NightBat", zubatCount))
|
||||
end
|
||||
end
|
||||
Control.moonEncounters = Control.moonEncounters + 1
|
||||
end
|
||||
end
|
||||
else
|
||||
|
|
|
@ -15,6 +15,7 @@ local Menu = require "util.menu"
|
|||
local Player = require "util.player"
|
||||
local Utils = require "util.utils"
|
||||
|
||||
local Data = require "data.data"
|
||||
local Inventory = require "storage.inventory"
|
||||
local Pokemon = require "storage.pokemon"
|
||||
|
||||
|
@ -306,7 +307,7 @@ strategyFunctions.fightBulbasaur = function()
|
|||
special = Pokemon.index(0, "special"),
|
||||
}
|
||||
if stats.squirtle.attack < 11 and stats.squirtle.special < 12 then
|
||||
return Strategies.reset("Bad Squirtle - "..stats.squirtle.attack.." attack, "..stats.squirtle.special.." special")
|
||||
return Strategies.reset("stats", "Bad Squirtle - "..stats.squirtle.attack.." attack, "..stats.squirtle.special.." special")
|
||||
end
|
||||
status.tries = 9001
|
||||
else
|
||||
|
@ -339,7 +340,7 @@ strategyFunctions.catchNidoran = function()
|
|||
local pokeballs = Inventory.count("pokeball")
|
||||
local caught = Memory.value("player", "party_size") - 1
|
||||
if pokeballs < 5 - caught * 2 then
|
||||
return Strategies.reset("Ran too low on PokeBalls", pokeballs)
|
||||
return Strategies.reset("pokeballs", "Ran too low on PokeBalls", pokeballs)
|
||||
end
|
||||
if Battle.isActive() then
|
||||
local isNidoran = Pokemon.isOpponent("nidoran")
|
||||
|
@ -363,7 +364,11 @@ strategyFunctions.catchNidoran = function()
|
|||
end
|
||||
else
|
||||
local enableDSum = true
|
||||
|
||||
Pokemon.updateParty()
|
||||
if not Data.run.early_flier then
|
||||
Data.run.early_flier = Pokemon.inParty("spearow") ~= nil
|
||||
end
|
||||
local hasNidoran = Pokemon.inParty("nidoran")
|
||||
if hasNidoran then
|
||||
local gotExperience = Pokemon.getExp() > 205
|
||||
|
@ -465,7 +470,7 @@ strategyFunctions.fightWeedle = function()
|
|||
if Battle.isTrainer() then
|
||||
status.canProgress = true
|
||||
if Memory.value("battle", "our_status") > 0 and not Inventory.contains("antidote") then
|
||||
return Strategies.reset("Poisoned, but we skipped the antidote")
|
||||
return Strategies.reset("antidote", "Poisoned, but we skipped the antidote")
|
||||
end
|
||||
return Strategies.buffTo("tail_whip", 5)
|
||||
elseif status.canProgress then
|
||||
|
@ -476,7 +481,7 @@ end
|
|||
strategyFunctions.equipForBrock = function(data)
|
||||
if Strategies.initialize() then
|
||||
if Pokemon.info("squirtle", "level") < 8 then
|
||||
return Strategies.reset("Did not reach level 8 before Brock", Pokemon.getExp(), true)
|
||||
return Strategies.reset("level8", "Did not reach level 8 before Brock", Pokemon.getExp(), true)
|
||||
end
|
||||
if data.anti then
|
||||
local poisoned = Pokemon.info("squirtle", "status") > 0
|
||||
|
@ -484,7 +489,7 @@ strategyFunctions.equipForBrock = function(data)
|
|||
return true
|
||||
end
|
||||
if not Inventory.contains("antidote") then
|
||||
return Strategies.reset("Poisoned, but we risked skipping the antidote")
|
||||
return Strategies.reset("antidote", "Poisoned, but we risked skipping the antidote")
|
||||
end
|
||||
local curr_hp = Pokemon.info("squirtle", "hp")
|
||||
if Inventory.contains("potion") and curr_hp > 8 and curr_hp < 18 then
|
||||
|
@ -562,7 +567,7 @@ strategyFunctions.fightBrock = function()
|
|||
|
||||
local nidoranStatus = "Att: "..att..", Def: "..def..", Speed: "..spd..", Special: "..scl
|
||||
if resetsForStats then
|
||||
return Strategies.reset("Bad Nidoran - "..nidoranStatus)
|
||||
return Strategies.reset("stats", "Bad Nidoran - "..nidoranStatus)
|
||||
end
|
||||
status.tries = 9001
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ local Player = require "util.player"
|
|||
local Shop = require "action.shop"
|
||||
local Utils = require "util.utils"
|
||||
|
||||
local Data = require "data.data"
|
||||
local Inventory = require "storage.inventory"
|
||||
local Pokemon = require "storage.pokemon"
|
||||
|
||||
|
@ -37,15 +38,19 @@ function Strategies.getTimeRequirement(name)
|
|||
return Strategies.timeRequirements[name]()
|
||||
end
|
||||
|
||||
function Strategies.hardReset(message, extra, wait)
|
||||
function Strategies.hardReset(reason, message, extra, wait)
|
||||
resetting = true
|
||||
if Strategies.seed then
|
||||
if Data.run.seed then
|
||||
if extra then
|
||||
extra = extra.." | "..Strategies.seed
|
||||
extra = extra.." | "..Data.run.seed
|
||||
else
|
||||
extra = Strategies.seed
|
||||
extra = Data.run.seed
|
||||
end
|
||||
end
|
||||
|
||||
local map, px, py = Memory.value("game", "map"), Player.position()
|
||||
Data.reset(reason, Control.areaName, map, px, py)
|
||||
|
||||
Bridge.chat(message, extra)
|
||||
if wait and INTERNAL and not STREAMING_MODE then
|
||||
strategyFunctions.wait()
|
||||
|
@ -55,7 +60,7 @@ function Strategies.hardReset(message, extra, wait)
|
|||
return true
|
||||
end
|
||||
|
||||
function Strategies.reset(reason, extra, wait)
|
||||
function Strategies.reset(reason, explanation, extra, wait)
|
||||
local time = Utils.elapsedTime()
|
||||
local resetMessage = "reset"
|
||||
if time then
|
||||
|
@ -68,25 +73,29 @@ function Strategies.reset(reason, extra, wait)
|
|||
else
|
||||
separator = ":"
|
||||
end
|
||||
resetMessage = resetMessage..separator.." "..reason
|
||||
resetMessage = resetMessage..separator.." "..explanation
|
||||
if status.tweeted then
|
||||
Strategies.tweetProgress(resetMessage)
|
||||
end
|
||||
return Strategies.hardReset(resetMessage, extra, wait)
|
||||
return Strategies.hardReset(reason, resetMessage, extra, wait)
|
||||
end
|
||||
|
||||
function Strategies.death(extra)
|
||||
local reason
|
||||
local reason, explanation
|
||||
if Control.missed then
|
||||
reason = "Missed"
|
||||
explanation = "Missed"
|
||||
reason = "miss"
|
||||
elseif Control.criticaled then
|
||||
reason = "Critical'd"
|
||||
explanation = "Critical'd"
|
||||
reason = "critical"
|
||||
elseif Control.yolo then
|
||||
reason = "Yolo strats"
|
||||
explanation = "Yolo strats"
|
||||
reason = "yolo"
|
||||
else
|
||||
reason = "Died"
|
||||
explanation = "Died"
|
||||
reason = "death"
|
||||
end
|
||||
return Strategies.reset(reason, extra)
|
||||
return Strategies.reset(reason, explanation, extra)
|
||||
end
|
||||
|
||||
function Strategies.overMinute(min)
|
||||
|
@ -96,14 +105,14 @@ function Strategies.overMinute(min)
|
|||
return Utils.igt() > (min * 60)
|
||||
end
|
||||
|
||||
function Strategies.resetTime(timeLimit, reason, once)
|
||||
function Strategies.resetTime(timeLimit, explanation, once)
|
||||
if Strategies.overMinute(timeLimit) then
|
||||
reason = "Took too long to "..reason
|
||||
explanation = "Took too long to "..explanation
|
||||
if RESET_FOR_TIME then
|
||||
return Strategies.reset(reason)
|
||||
return Strategies.reset("time", explanation)
|
||||
end
|
||||
if once then
|
||||
print(reason.." "..Utils.elapsedTime())
|
||||
print(explanation.." "..Utils.elapsedTime())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -500,6 +509,8 @@ Strategies.functions = {
|
|||
end,
|
||||
|
||||
split = function(data)
|
||||
Data.increment("reset_split")
|
||||
|
||||
Bridge.split(data and data.finished)
|
||||
if Strategies.replay then
|
||||
splitNumber = splitNumber + 1
|
||||
|
@ -634,7 +645,7 @@ Strategies.functions = {
|
|||
if not status.triedTeaching then
|
||||
status.triedTeaching = true
|
||||
if not Inventory.contains(itemName) then
|
||||
return Strategies.reset("Unable to teach move "..itemName.." to "..data.poke, nil, true)
|
||||
return Strategies.reset("error", "Unable to teach move "..itemName.." to "..data.poke, nil, true)
|
||||
end
|
||||
end
|
||||
local replacement
|
||||
|
@ -1050,12 +1061,13 @@ Strategies.functions = {
|
|||
if Battle.pp("horn_attack") == 0 then
|
||||
print("ERR: Ran out of Horn Attacks")
|
||||
end
|
||||
if Control.moonEncounters then
|
||||
local moonEncounters = Data.run.encounters_moon
|
||||
if moonEncounters then
|
||||
local catchPokemon = yellow and "sandshrew" or "paras"
|
||||
local capsName = Utils.capitalize(catchPokemon)
|
||||
local parasStatus
|
||||
local conjunction = "but"
|
||||
local goodEncounters = Control.moonEncounters < 10
|
||||
local goodEncounters = moonEncounters < 10
|
||||
local catchDescription
|
||||
if Pokemon.inParty(catchPokemon) then
|
||||
catchDescription = catchPokemon
|
||||
|
@ -1071,8 +1083,7 @@ Strategies.functions = {
|
|||
parasStatus = "we didn't catch a "..capsName.." :("
|
||||
end
|
||||
Bridge.caught(catchDescription)
|
||||
Bridge.chat(Control.moonEncounters.." Moon encounters, "..conjunction.." "..parasStatus)
|
||||
Control.moonEncounters = nil
|
||||
Bridge.chat(moonEncounters.." Moon encounters, "..conjunction.." "..parasStatus)
|
||||
end
|
||||
|
||||
Strategies.resetTime("mt_moon", "complete Mt. Moon", true)
|
||||
|
@ -1555,7 +1566,7 @@ Strategies.functions = {
|
|||
end
|
||||
local px, py = Player.position()
|
||||
if px > 7 then
|
||||
return Strategies.reset("Accidentally walked on the island :(", px, true)
|
||||
return Strategies.reset("error", "Accidentally walked on the island :(", px, true)
|
||||
end
|
||||
if Memory.value("player", "moving") == 0 then
|
||||
Player.interact("Right")
|
||||
|
@ -1587,15 +1598,16 @@ Strategies.functions = {
|
|||
victoryMessage = victoryMessage..", a new PB!"
|
||||
end
|
||||
Strategies.tweetProgress(victoryMessage)
|
||||
if Strategies.seed then
|
||||
print("v"..VERSION..": "..Utils.frames().." frames, with seed "..Strategies.seed)
|
||||
if Data.run.seed then
|
||||
Data.run.frames = Utils.frames()
|
||||
print("v"..VERSION..": "..Data.run.frames.." frames, with seed "..Data.run.seed)
|
||||
|
||||
if STREAMING_MODE and not Strategies.replay then
|
||||
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)
|
||||
gui.text(0, 7, "Seed: "..Strategies.seed)
|
||||
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())
|
||||
|
@ -1609,7 +1621,7 @@ Strategies.functions = {
|
|||
elseif status.frames == 500 then
|
||||
Bridge.chat("beat the game in "..status.finishTime.."!")
|
||||
elseif status.frames > 2000 then
|
||||
return Strategies.hardReset("Back to the grind - you can follow on Twitter for updates on our next good run! https://twitter.com/thepokebot")
|
||||
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
|
||||
|
|
|
@ -257,7 +257,7 @@ strategyFunctions.catchNidoran = function()
|
|||
local pokeballs = Inventory.count("pokeball")
|
||||
local caught = Memory.value("player", "party_size") > 1
|
||||
if pokeballs < (caught and 1 or 2) then
|
||||
return Strategies.reset("Ran too low on PokeBalls", pokeballs)
|
||||
return Strategies.reset("pokeballs", "Ran too low on PokeBalls", pokeballs)
|
||||
end
|
||||
if Battle.isActive() then
|
||||
status.path = nil
|
||||
|
@ -332,7 +332,7 @@ strategyFunctions.checkNidoStats = function()
|
|||
local resets = att < 15 or spd < 14 or scl < 12 --RISK
|
||||
local nidoranStatus = "Att: "..att..", Def: "..def..", Speed: "..spd..", Special: "..scl
|
||||
if resets then
|
||||
return Strategies.reset("Bad Nidoran - "..nidoranStatus)
|
||||
return Strategies.reset("stats", "Bad Nidoran - "..nidoranStatus)
|
||||
end
|
||||
-- if def < 12 then
|
||||
-- statDiff = statDiff + 1
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
local Data
|
||||
|
||||
local Bridge = require "util.bridge"
|
||||
local Utils = require "util.utils"
|
||||
local Pokemon = require "storage.pokemon"
|
||||
|
||||
local version = 0
|
||||
local vIndex = 2
|
||||
for segment in string.gmatch(VERSION, "([^.]+)") do
|
||||
version = version + tonumber(segment) * 100 ^ vIndex
|
||||
vIndex = vIndex - 1
|
||||
end
|
||||
|
||||
Data = {
|
||||
run = {},
|
||||
|
||||
versionNumber = version,
|
||||
}
|
||||
|
||||
function Data.increment(key)
|
||||
local incremented = Utils.increment(Data.run[key])
|
||||
Data.run[key] = incremented
|
||||
return incremented
|
||||
end
|
||||
|
||||
function Data.reset(reason, areaName, map, px, py)
|
||||
-- if INTERNAL and STREAMING_MODE then --TODO
|
||||
if INTERNAL then
|
||||
local report = Data.run
|
||||
report.cutter = Pokemon.inParty("paras", "oddish", "sandshrew", "charmander")
|
||||
|
||||
for key,value in pairs(report) do
|
||||
if value == true or value == false then
|
||||
report[key] = value == true and 1 or 0
|
||||
end
|
||||
end
|
||||
|
||||
report.version = Data.versionNumber
|
||||
report.reset_area = areaName
|
||||
report.reset_map = map
|
||||
report.reset_x = px
|
||||
report.reset_y = py
|
||||
report.reset_reason = reason
|
||||
|
||||
if not report.frames then
|
||||
report.frames = Utils.frames()
|
||||
end
|
||||
|
||||
Bridge.report(report)
|
||||
end
|
||||
Data.run = {}
|
||||
end
|
||||
|
||||
return Data
|
|
@ -12,7 +12,7 @@ local Paths = {
|
|||
-- 1: RIVAL 1
|
||||
|
||||
-- Let's try this escape again
|
||||
{0, {12,12}, {c="a",a="Pallet Town"}, {c="viridianExp"}, {c="encounters",limit=4}, {9,12}, {9,2}, {10,2}, {10,-1}},
|
||||
{0, {12,12}, {c="a",a="Pallet Town"}, {c="viridianExp"}, {c="encounters",limit=4}, {c="trackEncounters",area="route1"}, {9,12}, {9,2}, {10,2}, {10,-1}},
|
||||
-- First encounters
|
||||
{12, {10,35}, {10,30}, {8,30}, {8,24}, {12,24}, {12,20}, {9,20}, {9,14}, {14,14}, {s="dodgePalletBoy"}, {14,2}, {11,2}, {11,-1}},
|
||||
-- To the Mart
|
||||
|
@ -36,7 +36,7 @@ local Paths = {
|
|||
-- Viridian Mart redux
|
||||
{42, {3,7}, {3,5}, {2,5}, {s="shopViridianPokeballs"}, {3,5}, {3,8}},
|
||||
-- Sidequest
|
||||
{1, {29,20}, {15,20}, {15,17}, {-1, 17}},
|
||||
{1, {29,20}, {c="trackEncounters",area="nidoran"}, {15,20}, {15,17}, {-1, 17}},
|
||||
-- Nidoran
|
||||
{33, {39, 9}, {c="a",a="Nidoran grass"}, {c="nidoranBackupExp"}, {c="encounters",limit=7,extra="spearow"}, {35, 9}, {35,12}, {33,12}, {c="catchNidoran"}, {s="catchNidoran"}, {33,12}, {s="split"}, {37,12}, {37,9}, {40,9}},
|
||||
|
||||
|
@ -47,7 +47,7 @@ local Paths = {
|
|||
-- To the Forest
|
||||
{13, {7,71}, {7,57}, {4,57}, {4,52}, {10,52}, {10,44}, {3,44}, {3,43}},
|
||||
-- Forest entrance
|
||||
{50, {4,7}, {c="a",a="Viridian Forest"}, {4,1}, {5,1}, {5,0}},
|
||||
{50, {4,7}, {c="a",a="Viridian Forest"}, {c="trackEncounters",area="forest"}, {4,1}, {5,1}, {5,0}},
|
||||
-- Viridian Forest
|
||||
{51, {17,47}, {17,43}, {26,43}, {26,34}, {25,34}, {25,32}, {27,32}, {27,20}, {25,20}, {25,12}, {s="grabAntidote"}, {25,9}, {17,9}, {17,16}, {13,16}, {13,3}, {7,3}, {7,22}, {1,22}, {1,19}, {s="grabForestPotion"}, {1,18}, {s="fightWeedle"}, {c="encounters",limit=22,extra="paras"}, {1,16}, {c="potion",b=false}, {s="equipForBrock",anti=true}, {1,5}, {s="equipForBrock"}, {1,-1}},
|
||||
-- Forest exit
|
||||
|
@ -68,7 +68,7 @@ local Paths = {
|
|||
-- Leaving Pewter City
|
||||
{2, {23,18}, {40,18}},
|
||||
-- Route 3
|
||||
{14, {0,10}, {c="a",a="Route 3"}, {c="catchFlier"}, {c="pp",on=true}, {s="battleModeSet"}, {8,10}, {8,8}, {11,8}, {11,6}, {s="bugCatcher"}, {11,4}, {12,4}, {s="potion",hp=19}, {13,4}, {s="talk",dir="Right"}, {s="shortsKid"}, {s="tweetAfterBrock"}, {13,5}, {s="potionBeforeCocoons"}, {18,5}, {s="talk",dir="Right"}, {s="swapMove",move="horn_attack",to=0}, {18,6}, {22,6}, {22,5}, {s="potion",hp=4}, {24,5}, {s="talk",dir="Down"}, {s="fightMetapod"}, {27,5}, {27,9}, {s="catchFlierBackup"}, {37,8}, {37,5}, {49,5}, {49,10}, {57,10}, {57,8}, {59,8}, {59,-1}},
|
||||
{14, {0,10}, {c="a",a="Route 3"}, {c="catchFlier"}, {c="pp",on=true}, {c="trackEncounters",area="route3"}, {s="battleModeSet"}, {8,10}, {8,8}, {11,8}, {11,6}, {s="bugCatcher"}, {11,4}, {12,4}, {c="a",a="Shorts Kid"}, {s="potion",hp=19}, {13,4}, {s="talk",dir="Right"}, {s="shortsKid"}, {s="tweetAfterBrock"}, {13,5}, {c="a",a="Route 3"}, {s="potionBeforeCocoons"}, {18,5}, {s="talk",dir="Right"}, {s="swapMove",move="horn_attack",to=0}, {18,6}, {22,6}, {22,5}, {s="potion",hp=4}, {24,5}, {s="talk",dir="Down"}, {s="fightMetapod"}, {27,5}, {27,9}, {s="catchFlierBackup"}, {37,8}, {37,5}, {49,5}, {49,10}, {57,10}, {57,8}, {59,8}, {59,-1}},
|
||||
-- To the Center
|
||||
{15, {9,16}, {c="pp",on=false}, {12,16}, {12,6}, {11,6}, {11,5}},
|
||||
-- PP up
|
||||
|
@ -79,7 +79,7 @@ local Paths = {
|
|||
-- 4: ROUTE 3
|
||||
|
||||
-- Mt. Moon F1
|
||||
{59, {14,35}, {c="a",a="Mt. Moon"}, {c="startMtMoon"}, {c="catchParas"}, {14,22}, {21,22}, {21,15}, {24,15}, {24,27}, {25,27}, {25,31}, {s="talk",dir="Left"}, {25,32}, {33,32}, {33,31}, {34,31}, {s="take",dir="Right"}, {35,31}, {35,23}, {s="take",dir="Right"}, {35,7}, {30,7}, {s="evolveNidorino"}, {c="moon1Exp"}, {28,7}, {16,7}, {16,17}, {2,17}, {2,3}, {s="take",dir="Up"}, {5,3}, {5,5}},
|
||||
{59, {14,35}, {c="a",a="Mt. Moon"}, {c="trackEncounters",area="moon"}, {c="startMtMoon"}, {c="catchParas"}, {14,22}, {21,22}, {21,15}, {24,15}, {24,27}, {25,27}, {25,31}, {s="talk",dir="Left"}, {25,32}, {33,32}, {33,31}, {34,31}, {s="take",dir="Right"}, {35,31}, {35,23}, {s="take",dir="Right"}, {35,7}, {30,7}, {s="evolveNidorino"}, {c="moon1Exp"}, {28,7}, {16,7}, {16,17}, {2,17}, {2,3}, {s="take",dir="Up"}, {5,3}, {5,5}},
|
||||
-- Mt. Moon B2
|
||||
{60, {5,5}, {5,17}, {21,17}},
|
||||
-- Mt. Moon B3
|
||||
|
@ -90,7 +90,7 @@ local Paths = {
|
|||
-- 5: MT. MOON
|
||||
|
||||
-- To Cerulean
|
||||
{15, {24,6}, {s="reportMtMoon"}, {s="split"}, {24,8}, {35,8}, {35,10}, {61,10}, {61,8}, {79,8}, {79,10}, {90,10}},
|
||||
{15, {24,6}, {s="reportMtMoon"}, {c="trackEncounters",area=nil}, {s="split"}, {24,8}, {35,8}, {35,10}, {61,10}, {61,8}, {79,8}, {79,10}, {90,10}},
|
||||
-- Enter Cerulean
|
||||
{3, {0,18}, {c="a",a="Cerulean"}, {14,18}, {s="dodgeCerulean"}, {19,18}, {19,17}},
|
||||
-- Cerulean Center
|
||||
|
@ -106,7 +106,7 @@ local Paths = {
|
|||
-- Rival 2
|
||||
{3, {9,12}, {c="a",a="Cerulean Rival"}, {21,12}, {21,6}, {s="rivalSandAttack"}, {21,-1}},
|
||||
-- Nugget bridge
|
||||
{35, {11,35}, {c="a",a="Nugget Bridge"}, {11,32}, {s="talk",dir="Up"}, {s="hornAttackCaterpie"}, {10,32}, {10,29}, {s="potion",hp=12,yolo=10}, {s="talk",dir="Up"}, {11,29}, {11,27}, {s="rareCandyEarly",close=true}, {s="potion",hp=10,yolo=8,close=true}, {11,26}, {s="talk",dir="Up"}, {s="swapThrash"}, {10,26}, {10,24}, {s="teachThrash"}, {s="potion",hp=4}, {10,23}, {s="talk",dir="Up"}, {s="swapThrash"}, {11,23}, {11,21}, {s="teachThrash"}, {s="potionForMankey"}, {11,20}, {s="talk",dir="Up"}, {s="redbarMankey"}, {s="swapThrash"}, {10,20}, {10,19}, {s="teachThrash"}, {10,15}, {s="learnThrash"}, {s="swapThrash"}, {s="waitToFight"}, {s="teachThrash"}, {s="split"}, {10,8}, {20,8}},
|
||||
{35, {11,35}, {c="a",a="Nugget Bridge"}, {11,32}, {s="talk",dir="Up"}, {s="hornAttackCaterpie"}, {10,32}, {10,29}, {s="potion",hp=12,yolo=10}, {s="talk",dir="Up"}, {11,29}, {11,27}, {s="rareCandyEarly",close=true}, {s="potion",hp=10,yolo=8,close=true}, {11,26}, {s="talk",dir="Up"}, {s="swapThrash"}, {10,26}, {10,24}, {s="teachThrash"}, {s="potion",hp=4}, {10,23}, {s="talk",dir="Up"}, {s="swapThrash"}, {11,23}, {11,21}, {s="teachThrash"}, {s="potionForMankey"}, {11,20}, {s="talk",dir="Up"}, {s="swapThrash"}, {s="redbarMankey"}, {10,20}, {10,19}, {s="teachThrash"}, {10,15}, {s="learnThrash"}, {s="swapThrash"}, {s="waitToFight"}, {s="teachThrash"}, {s="split"}, {10,8}, {20,8}},
|
||||
|
||||
-- 6: NUGGET BRIDGE
|
||||
|
||||
|
@ -445,7 +445,7 @@ local Paths = {
|
|||
-- Blue
|
||||
{120, {4,3}, {c="a",a="Blue"}, {s="blue"}, {3,0}},
|
||||
-- Champion
|
||||
{118, {4,2}, {s="champion"}}
|
||||
{118, {4,2}, {c="a",a="Champion"}, {s="champion"}}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,417 @@
|
|||
-----------------------------------------------------------------------------
|
||||
-- JSON4Lua: JSON encoding / decoding support for the Lua language.
|
||||
-- json Module.
|
||||
-- Author: Craig Mason-Jones
|
||||
-- Homepage: http://github.com/craigmj/json4lua/
|
||||
-- Version: 1.0.0
|
||||
-- This module is released under the MIT License (MIT).
|
||||
-- Please see LICENCE.txt for details.
|
||||
--
|
||||
-- USAGE:
|
||||
-- This module exposes two functions:
|
||||
-- json.encode(o)
|
||||
-- Returns the table / string / boolean / number / nil / json.null value as a JSON-encoded string.
|
||||
-- json.decode(json_string)
|
||||
-- Returns a Lua object populated with the data encoded in the JSON string json_string.
|
||||
--
|
||||
-- REQUIREMENTS:
|
||||
-- compat-5.1 if using Lua 5.0
|
||||
--
|
||||
-- CHANGELOG
|
||||
-- 0.9.20 Introduction of local Lua functions for private functions (removed _ function prefix).
|
||||
-- Fixed Lua 5.1 compatibility issues.
|
||||
-- Introduced json.null to have null values in associative arrays.
|
||||
-- json.encode() performance improvement (more than 50%) through table.concat rather than ..
|
||||
-- Introduced decode ability to ignore /**/ comments in the JSON string.
|
||||
-- 0.9.10 Fix to array encoding / decoding to correctly manage nil/null values in arrays.
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Imports and dependencies
|
||||
-----------------------------------------------------------------------------
|
||||
local math = require('math')
|
||||
local string = require("string")
|
||||
local table = require("table")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Module declaration
|
||||
-----------------------------------------------------------------------------
|
||||
local json = {} -- Public namespace
|
||||
local json_private = {} -- Private namespace
|
||||
|
||||
-- Public functions
|
||||
|
||||
-- Private functions
|
||||
local decode_scanArray
|
||||
local decode_scanComment
|
||||
local decode_scanConstant
|
||||
local decode_scanNumber
|
||||
local decode_scanObject
|
||||
local decode_scanString
|
||||
local decode_scanWhitespace
|
||||
local encodeString
|
||||
local isArray
|
||||
local isEncodable
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- PUBLIC FUNCTIONS
|
||||
-----------------------------------------------------------------------------
|
||||
--- Encodes an arbitrary Lua object / variable.
|
||||
-- @param v The Lua object / variable to be JSON encoded.
|
||||
-- @return String containing the JSON encoding in internal Lua string format (i.e. not unicode)
|
||||
function json.encode (v)
|
||||
-- Handle nil values
|
||||
if v==nil then
|
||||
return "null"
|
||||
end
|
||||
|
||||
local vtype = type(v)
|
||||
|
||||
-- Handle strings
|
||||
if vtype=='string' then
|
||||
return '"' .. json_private.encodeString(v) .. '"' -- Need to handle encoding in string
|
||||
end
|
||||
|
||||
-- Handle booleans
|
||||
if vtype=='number' or vtype=='boolean' then
|
||||
return tostring(v)
|
||||
end
|
||||
|
||||
-- Handle tables
|
||||
if vtype=='table' then
|
||||
local rval = {}
|
||||
-- Consider arrays separately
|
||||
local bArray, maxCount = isArray(v)
|
||||
if bArray then
|
||||
for i = 1,maxCount do
|
||||
table.insert(rval, json.encode(v[i]))
|
||||
end
|
||||
else -- An object, not an array
|
||||
for i,j in pairs(v) do
|
||||
if isEncodable(i) and isEncodable(j) then
|
||||
table.insert(rval, '"' .. json_private.encodeString(i) .. '":' .. json.encode(j))
|
||||
end
|
||||
end
|
||||
end
|
||||
if bArray then
|
||||
return '[' .. table.concat(rval,',') ..']'
|
||||
else
|
||||
return '{' .. table.concat(rval,',') .. '}'
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle null values
|
||||
if vtype=='function' and v==null then
|
||||
return 'null'
|
||||
end
|
||||
|
||||
assert(false,'encode attempt to encode unsupported type ' .. vtype .. ':' .. tostring(v))
|
||||
end
|
||||
|
||||
|
||||
--- Decodes a JSON string and returns the decoded value as a Lua data structure / value.
|
||||
-- @param s The string to scan.
|
||||
-- @param [startPos] Optional starting position where the JSON string is located. Defaults to 1.
|
||||
-- @param Lua object, number The object that was scanned, as a Lua table / string / number / boolean or nil,
|
||||
-- and the position of the first character after
|
||||
-- the scanned JSON object.
|
||||
function json.decode(s, startPos)
|
||||
startPos = startPos and startPos or 1
|
||||
startPos = decode_scanWhitespace(s,startPos)
|
||||
assert(startPos<=string.len(s), 'Unterminated JSON encoded object found at position in [' .. s .. ']')
|
||||
local curChar = string.sub(s,startPos,startPos)
|
||||
-- Object
|
||||
if curChar=='{' then
|
||||
return decode_scanObject(s,startPos)
|
||||
end
|
||||
-- Array
|
||||
if curChar=='[' then
|
||||
return decode_scanArray(s,startPos)
|
||||
end
|
||||
-- Number
|
||||
if string.find("+-0123456789.e", curChar, 1, true) then
|
||||
return decode_scanNumber(s,startPos)
|
||||
end
|
||||
-- String
|
||||
if curChar==[["]] or curChar==[[']] then
|
||||
return decode_scanString(s,startPos)
|
||||
end
|
||||
if string.sub(s,startPos,startPos+1)=='/*' then
|
||||
return decode(s, decode_scanComment(s,startPos))
|
||||
end
|
||||
-- Otherwise, it must be a constant
|
||||
return decode_scanConstant(s,startPos)
|
||||
end
|
||||
|
||||
--- The null function allows one to specify a null value in an associative array (which is otherwise
|
||||
-- discarded if you set the value with 'nil' in Lua. Simply set t = { first=json.null }
|
||||
function null()
|
||||
return null -- so json.null() will also return null ;-)
|
||||
end
|
||||
-----------------------------------------------------------------------------
|
||||
-- Internal, PRIVATE functions.
|
||||
-- Following a Python-like convention, I have prefixed all these 'PRIVATE'
|
||||
-- functions with an underscore.
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
--- Scans an array from JSON into a Lua object
|
||||
-- startPos begins at the start of the array.
|
||||
-- Returns the array and the next starting position
|
||||
-- @param s The string being scanned.
|
||||
-- @param startPos The starting position for the scan.
|
||||
-- @return table, int The scanned array as a table, and the position of the next character to scan.
|
||||
function decode_scanArray(s,startPos)
|
||||
local array = {} -- The return value
|
||||
local stringLen = string.len(s)
|
||||
assert(string.sub(s,startPos,startPos)=='[','decode_scanArray called but array does not start at position ' .. startPos .. ' in string:\n'..s )
|
||||
startPos = startPos + 1
|
||||
-- Infinite loop for array elements
|
||||
repeat
|
||||
startPos = decode_scanWhitespace(s,startPos)
|
||||
assert(startPos<=stringLen,'JSON String ended unexpectedly scanning array.')
|
||||
local curChar = string.sub(s,startPos,startPos)
|
||||
if (curChar==']') then
|
||||
return array, startPos+1
|
||||
end
|
||||
if (curChar==',') then
|
||||
startPos = decode_scanWhitespace(s,startPos+1)
|
||||
end
|
||||
assert(startPos<=stringLen, 'JSON String ended unexpectedly scanning array.')
|
||||
object, startPos = json.decode(s,startPos)
|
||||
table.insert(array,object)
|
||||
until false
|
||||
end
|
||||
|
||||
--- Scans a comment and discards the comment.
|
||||
-- Returns the position of the next character following the comment.
|
||||
-- @param string s The JSON string to scan.
|
||||
-- @param int startPos The starting position of the comment
|
||||
function decode_scanComment(s, startPos)
|
||||
assert( string.sub(s,startPos,startPos+1)=='/*', "decode_scanComment called but comment does not start at position " .. startPos)
|
||||
local endPos = string.find(s,'*/',startPos+2)
|
||||
assert(endPos~=nil, "Unterminated comment in string at " .. startPos)
|
||||
return endPos+2
|
||||
end
|
||||
|
||||
--- Scans for given constants: true, false or null
|
||||
-- Returns the appropriate Lua type, and the position of the next character to read.
|
||||
-- @param s The string being scanned.
|
||||
-- @param startPos The position in the string at which to start scanning.
|
||||
-- @return object, int The object (true, false or nil) and the position at which the next character should be
|
||||
-- scanned.
|
||||
function decode_scanConstant(s, startPos)
|
||||
local consts = { ["true"] = true, ["false"] = false, ["null"] = nil }
|
||||
local constNames = {"true","false","null"}
|
||||
|
||||
for i,k in pairs(constNames) do
|
||||
if string.sub(s,startPos, startPos + string.len(k) -1 )==k then
|
||||
return consts[k], startPos + string.len(k)
|
||||
end
|
||||
end
|
||||
assert(nil, 'Failed to scan constant from string ' .. s .. ' at starting position ' .. startPos)
|
||||
end
|
||||
|
||||
--- Scans a number from the JSON encoded string.
|
||||
-- (in fact, also is able to scan numeric +- eqns, which is not
|
||||
-- in the JSON spec.)
|
||||
-- Returns the number, and the position of the next character
|
||||
-- after the number.
|
||||
-- @param s The string being scanned.
|
||||
-- @param startPos The position at which to start scanning.
|
||||
-- @return number, int The extracted number and the position of the next character to scan.
|
||||
function decode_scanNumber(s,startPos)
|
||||
local endPos = startPos+1
|
||||
local stringLen = string.len(s)
|
||||
local acceptableChars = "+-0123456789.e"
|
||||
while (string.find(acceptableChars, string.sub(s,endPos,endPos), 1, true)
|
||||
and endPos<=stringLen
|
||||
) do
|
||||
endPos = endPos + 1
|
||||
end
|
||||
local stringValue = 'return ' .. string.sub(s,startPos, endPos-1)
|
||||
local stringEval = loadstring(stringValue)
|
||||
assert(stringEval, 'Failed to scan number [ ' .. stringValue .. '] in JSON string at position ' .. startPos .. ' : ' .. endPos)
|
||||
return stringEval(), endPos
|
||||
end
|
||||
|
||||
--- Scans a JSON object into a Lua object.
|
||||
-- startPos begins at the start of the object.
|
||||
-- Returns the object and the next starting position.
|
||||
-- @param s The string being scanned.
|
||||
-- @param startPos The starting position of the scan.
|
||||
-- @return table, int The scanned object as a table and the position of the next character to scan.
|
||||
function decode_scanObject(s,startPos)
|
||||
local object = {}
|
||||
local stringLen = string.len(s)
|
||||
local key, value
|
||||
assert(string.sub(s,startPos,startPos)=='{','decode_scanObject called but object does not start at position ' .. startPos .. ' in string:\n' .. s)
|
||||
startPos = startPos + 1
|
||||
repeat
|
||||
startPos = decode_scanWhitespace(s,startPos)
|
||||
assert(startPos<=stringLen, 'JSON string ended unexpectedly while scanning object.')
|
||||
local curChar = string.sub(s,startPos,startPos)
|
||||
if (curChar=='}') then
|
||||
return object,startPos+1
|
||||
end
|
||||
if (curChar==',') then
|
||||
startPos = decode_scanWhitespace(s,startPos+1)
|
||||
end
|
||||
assert(startPos<=stringLen, 'JSON string ended unexpectedly scanning object.')
|
||||
-- Scan the key
|
||||
key, startPos = json.decode(s,startPos)
|
||||
assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
|
||||
startPos = decode_scanWhitespace(s,startPos)
|
||||
assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
|
||||
assert(string.sub(s,startPos,startPos)==':','JSON object key-value assignment mal-formed at ' .. startPos)
|
||||
startPos = decode_scanWhitespace(s,startPos+1)
|
||||
assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)
|
||||
value, startPos = json.decode(s,startPos)
|
||||
object[key]=value
|
||||
until false -- infinite loop while key-value pairs are found
|
||||
end
|
||||
|
||||
-- START SoniEx2
|
||||
-- Initialize some things used by decode_scanString
|
||||
-- You know, for efficiency
|
||||
local escapeSequences = {
|
||||
["\\t"] = "\t",
|
||||
["\\f"] = "\f",
|
||||
["\\r"] = "\r",
|
||||
["\\n"] = "\n",
|
||||
["\\b"] = "\b"
|
||||
}
|
||||
setmetatable(escapeSequences, {__index = function(t,k)
|
||||
-- skip "\" aka strip escape
|
||||
return string.sub(k,2)
|
||||
end})
|
||||
-- END SoniEx2
|
||||
|
||||
--- Scans a JSON string from the opening inverted comma or single quote to the
|
||||
-- end of the string.
|
||||
-- Returns the string extracted as a Lua string,
|
||||
-- and the position of the next non-string character
|
||||
-- (after the closing inverted comma or single quote).
|
||||
-- @param s The string being scanned.
|
||||
-- @param startPos The starting position of the scan.
|
||||
-- @return string, int The extracted string as a Lua string, and the next character to parse.
|
||||
function decode_scanString(s,startPos)
|
||||
assert(startPos, 'decode_scanString(..) called without start position')
|
||||
local startChar = string.sub(s,startPos,startPos)
|
||||
-- START SoniEx2
|
||||
-- PS: I don't think single quotes are valid JSON
|
||||
assert(startChar == [["]] or startChar == [[']],'decode_scanString called for a non-string')
|
||||
--assert(startPos, "String decoding failed: missing closing " .. startChar .. " for string at position " .. oldStart)
|
||||
local t = {}
|
||||
local i,j = startPos,startPos
|
||||
while string.find(s, startChar, j+1) ~= j+1 do
|
||||
local oldj = j
|
||||
i,j = string.find(s, "\\.", j+1)
|
||||
local x,y = string.find(s, startChar, oldj+1)
|
||||
if not i or x < i then
|
||||
i,j = x,y-1
|
||||
end
|
||||
table.insert(t, string.sub(s, oldj+1, i-1))
|
||||
if string.sub(s, i, j) == "\\u" then
|
||||
local a = string.sub(s,j+1,j+4)
|
||||
j = j + 4
|
||||
local n = tonumber(a, 16)
|
||||
assert(n, "String decoding failed: bad Unicode escape " .. a .. " at position " .. i .. " : " .. j)
|
||||
-- math.floor(x/2^y) == lazy right shift
|
||||
-- a % 2^b == bitwise_and(a, (2^b)-1)
|
||||
-- 64 = 2^6
|
||||
-- 4096 = 2^12 (or 2^6 * 2^6)
|
||||
local x
|
||||
if n < 0x80 then
|
||||
x = string.char(n % 0x80)
|
||||
elseif n < 0x800 then
|
||||
-- [110x xxxx] [10xx xxxx]
|
||||
x = string.char(0xC0 + (math.floor(n/64) % 0x20), 0x80 + (n % 0x40))
|
||||
else
|
||||
-- [1110 xxxx] [10xx xxxx] [10xx xxxx]
|
||||
x = string.char(0xE0 + (math.floor(n/4096) % 0x10), 0x80 + (math.floor(n/64) % 0x40), 0x80 + (n % 0x40))
|
||||
end
|
||||
table.insert(t, x)
|
||||
else
|
||||
table.insert(t, escapeSequences[string.sub(s, i, j)])
|
||||
end
|
||||
end
|
||||
table.insert(t,string.sub(j, j+1))
|
||||
assert(string.find(s, startChar, j+1), "String decoding failed: missing closing " .. startChar .. " at position " .. j .. "(for string at position " .. startPos .. ")")
|
||||
return table.concat(t,""), j+2
|
||||
-- END SoniEx2
|
||||
end
|
||||
|
||||
--- Scans a JSON string skipping all whitespace from the current start position.
|
||||
-- Returns the position of the first non-whitespace character, or nil if the whole end of string is reached.
|
||||
-- @param s The string being scanned
|
||||
-- @param startPos The starting position where we should begin removing whitespace.
|
||||
-- @return int The first position where non-whitespace was encountered, or string.len(s)+1 if the end of string
|
||||
-- was reached.
|
||||
function decode_scanWhitespace(s,startPos)
|
||||
local whitespace=" \n\r\t"
|
||||
local stringLen = string.len(s)
|
||||
while ( string.find(whitespace, string.sub(s,startPos,startPos), 1, true) and startPos <= stringLen) do
|
||||
startPos = startPos + 1
|
||||
end
|
||||
return startPos
|
||||
end
|
||||
|
||||
--- Encodes a string to be JSON-compatible.
|
||||
-- This just involves back-quoting inverted commas, back-quotes and newlines, I think ;-)
|
||||
-- @param s The string to return as a JSON encoded (i.e. backquoted string)
|
||||
-- @return The string appropriately escaped.
|
||||
|
||||
local escapeList = {
|
||||
['"'] = '\\"',
|
||||
['\\'] = '\\\\',
|
||||
['/'] = '\\/',
|
||||
['\b'] = '\\b',
|
||||
['\f'] = '\\f',
|
||||
['\n'] = '\\n',
|
||||
['\r'] = '\\r',
|
||||
['\t'] = '\\t'
|
||||
}
|
||||
|
||||
function json_private.encodeString(s)
|
||||
local s = tostring(s)
|
||||
return s:gsub(".", function(c) return escapeList[c] end) -- SoniEx2: 5.0 compat
|
||||
end
|
||||
|
||||
-- Determines whether the given Lua type is an array or a table / dictionary.
|
||||
-- We consider any table an array if it has indexes 1..n for its n items, and no
|
||||
-- other data in the table.
|
||||
-- I think this method is currently a little 'flaky', but can't think of a good way around it yet...
|
||||
-- @param t The table to evaluate as an array
|
||||
-- @return boolean, number True if the table can be represented as an array, false otherwise. If true,
|
||||
-- the second returned value is the maximum
|
||||
-- number of indexed elements in the array.
|
||||
function isArray(t)
|
||||
-- Next we count all the elements, ensuring that any non-indexed elements are not-encodable
|
||||
-- (with the possible exception of 'n')
|
||||
local maxIndex = 0
|
||||
for k,v in pairs(t) do
|
||||
if (type(k)=='number' and math.floor(k)==k and 1<=k) then -- k,v is an indexed pair
|
||||
if (not isEncodable(v)) then return false end -- All array elements must be encodable
|
||||
maxIndex = math.max(maxIndex,k)
|
||||
else
|
||||
if (k=='n') then
|
||||
if v ~= table.getn(t) then return false end -- False if n does not hold the number of elements
|
||||
else -- Else of (k=='n')
|
||||
if isEncodable(v) then return false end
|
||||
end -- End of (k~='n')
|
||||
end -- End of k,v not an indexed pair
|
||||
end -- End of loop across all pairs
|
||||
return true, maxIndex
|
||||
end
|
||||
|
||||
--- Determines whether the given Lua object / table / variable can be JSON encoded. The only
|
||||
-- types that are JSON encodable are: string, boolean, number, nil, table and json.null.
|
||||
-- In this implementation, all other types are ignored.
|
||||
-- @param o The object to examine.
|
||||
-- @return boolean True if the object should be JSON encoded, false if it should be ignored.
|
||||
function isEncodable(o)
|
||||
local t = type(o)
|
||||
return (t=='string' or t=='boolean' or t=='number' or t=='nil' or t=='table') or (t=='function' and o==null)
|
||||
end
|
||||
|
||||
return json
|
12
main.lua
12
main.lua
|
@ -30,6 +30,7 @@ local Paint = require "util.paint"
|
|||
local Utils = require "util.utils"
|
||||
local Settings = require "util.settings"
|
||||
|
||||
local Data = require "data.data"
|
||||
local Pokemon = require "storage.pokemon"
|
||||
|
||||
local hasAlreadyStartedPlaying = false
|
||||
|
@ -48,17 +49,16 @@ local function resetAll()
|
|||
Bridge.reset()
|
||||
oldSeconds = 0
|
||||
running = false
|
||||
-- client.speedmode = 200
|
||||
|
||||
if CUSTOM_SEED then
|
||||
Strategies.seed = CUSTOM_SEED
|
||||
Data.run.seed = CUSTOM_SEED
|
||||
Strategies.replay = true
|
||||
p("RUNNING WITH A FIXED SEED ("..NIDORAN_NAME.." "..Strategies.seed.."), every run will play out identically!", true)
|
||||
p("RUNNING WITH A FIXED SEED ("..NIDORAN_NAME.." "..Data.run.seed.."), every run will play out identically!", true)
|
||||
else
|
||||
Strategies.seed = os.time()
|
||||
print("PokeBot v"..VERSION..": starting a new run with seed "..Strategies.seed)
|
||||
Data.run.seed = os.time()
|
||||
print("PokeBot v"..VERSION..": starting a new run with seed "..Data.run.seed)
|
||||
end
|
||||
math.randomseed(Strategies.seed)
|
||||
math.randomseed(Data.run.seed)
|
||||
end
|
||||
|
||||
-- EXECUTE
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
local Bridge = {}
|
||||
|
||||
local json = require("external.json")
|
||||
|
||||
local socket
|
||||
if INTERNAL then
|
||||
socket = require("socket")
|
||||
|
@ -132,6 +134,13 @@ function Bridge.encounter()
|
|||
send("encounter")
|
||||
end
|
||||
|
||||
function Bridge.report(report)
|
||||
if not STREAMING_MODE then
|
||||
print(json.encode(report))
|
||||
end
|
||||
send("report", json.encode(report))
|
||||
end
|
||||
|
||||
function Bridge.reset()
|
||||
send("reset")
|
||||
timeStopped = false
|
||||
|
|
|
@ -8,6 +8,8 @@ local Input = require "util.input"
|
|||
local Memory = require "util.memory"
|
||||
local Menu = require "util.menu"
|
||||
|
||||
local Data = require "data.data"
|
||||
|
||||
local START_WAIT = 99
|
||||
|
||||
local yellow = YELLOW
|
||||
|
@ -91,6 +93,7 @@ function Settings.pollForResponse(forcedName)
|
|||
response = forcedName
|
||||
elseif response then
|
||||
response = tonumber(response)
|
||||
Data.run.voted_for_name = true
|
||||
end
|
||||
if response then
|
||||
Bridge.polling = false
|
||||
|
|
|
@ -79,6 +79,20 @@ function Utils.nextCircularIndex(index, direction, totalCount)
|
|||
return nextIndex
|
||||
end
|
||||
|
||||
function Utils.increment(amount)
|
||||
if not amount then
|
||||
return 1
|
||||
end
|
||||
return amount + 1
|
||||
end
|
||||
|
||||
function Utils.multiplyString(string, times)
|
||||
for i=1, times-1 do
|
||||
string = string.." "..string
|
||||
end
|
||||
return string
|
||||
end
|
||||
|
||||
-- GAME
|
||||
|
||||
function Utils.canPotionWith(potion, forDamage, curr_hp, max_hp)
|
||||
|
|
Loading…
Reference in New Issue