State information is read directly from RAM. The three primary files are:
stateinfo.lua
, which lazily reads dungeon information such as the dungeon layout, entities in the dungeon, and the player's bag.visibleinfo.lua
, which filters the full state information fromstateinfo
into a model containing only information that would be accessible to a human player.menuinfo.lua
, which reads information related to menuing, such as the current menu open and the position of the menu cursor.
The StateData
class handles caching and lazy reading of dungeon information. These objects form the basis of the dungeon state model used by the bot to access environmental information (through the variables state
and visible
in Agent:act(state, visible)
). All StateData
instances behave as follows:
- When called, they return the data they represent.
- Have the field
doesCache
that determines whether or not they should cache their data after the first read. This defaults to true, but can be set in the constructor. - Store any cached data in the
cache
field. - Have an internal flag
isStale
that controls if the cache should be refreshed upon the next call. This should be set to true by calling theflagForReload()
method. - Implement a
read()
method that retrieves the necessary data from memory (without regards to any caching behavior).
The bot accesses the entire dungeon state as a single object (stateinfo.state
), defined in stateinfo.lua
. The data is organized in a tree structure with the following format:
state
: The state model objectdungeon
: Subcontainer for "external" informationdungeonID()
: The dungeon ID of the current dungeonvisibilityRadius()
: How far away the player can see enemies in a dark hallway. Also controls how many tiles around the leader get revealed on the map during exploration.floor()
: Current floor numberlayout()
: Grid of tiles on the floor, ordered by position. Access usinglayout()[y][x]
.stairs()
: Location of stairs on the floor. Returns two values (x, y). Could be normal or hidden stairs.entities
: Subcontainer for entities in the dungeonteam()
: Ordered list of monsters currently in the player's partyenemies()
: Ordered list of monsters not in the player's partyitems()
: Ordered list of items on the floortraps()
: Ordered list of traps on the floorhiddenStairs()
: Hidden stairs on the floor. Will benil
if there are none.
conditions
: Subcontainer for floor-wide conditionsweather()
: The ID for the current weather conditionnaturalWeather()
: The weather that the floor will revert to if no artificial weather is in effectweatherTurnsLeft()
: Turns left for artificial weather, if applicableweatherIsNullified()
: Flag for whether Cloud Nine/Air Lock is in effectmudSportTurnsLeft()
: Turns left for the effects of Mud Sport. Will be 0 if Mud Sport is inactive.mudSport()
: Whether or not Mud Sport is in effect (convenience field based onmudSportTurnsLeft()
)waterSportTurnsLeft()
: Turns left for the effects of Water Sport. Will be 0 if Water Sport is inactive.waterSport()
: Whether or not Water Sport is in effect (convenience field based onwaterSportTurnsLeft()
)thiefAlert()
: Flag for whether you've stolen from Kecleongravity()
: Flag for whether gravity is in effectluminous()
: Flag for whether the floor is luminous (no darkness, with floor layout and enemies visible)darkness()
: Flag for whether the floor is dark (affects visibility in halls)
counters
: Subcontainer for "dungeon counters" that tick every turnwind()
: Turns left before the dungeon wind blows you outwindWarnings()
: Number of warnings the player has received about the approaching wind (convenience field based onwind()
)weatherDamage()
: Turns left before getting damaged by weather, if applicable. Counts from 9 to 0, damage occurs when it resets to 9.turnsSinceWeatherDamage()
: Number of turns that have passed since the last round of passive damage from inclement weather, ornil
if the current weather is non-damaging (convenience field based onweather()
andweatherDamage()
)enemySpawn()
: Counter for new enemy spawns in the dungeon.
player
: Subcontainer for "internal" information about the playerteam()
: Alias forstate.dungeon.entities.team()
leader()
: Alias for the first team membermoney()
: Amount of money carriedbag()
: Ordered list of items currently in the bagbagCapacity()
: Maximum number of items the player can carry in the bagcanSeeEnemies()
: Flag for whether the player can see all enemies on the floorcanSeeItems()
: Flag for whether the player can see all items on the floorcanSeeTrapsAndHiddenStairs()
: Flag for whether the player can see unrevealed traps and hidden stairscanSeeStairs()
: Flag for whether the player can see location of the stairs (both normal and hidden) without having found them through exploration
Nodes with parentheses after their names are StateData
objects, whose value should be accessed by calling them. Otherwise, they're just normal table fields (accessed without a call).
Returned in a grid by the layout()
field. Tiles have the following fields:
terrain
: The tile's terrain codeisJunction
: Flag for whether or not the tile is a junction (includes the exits of a room, and branch points in hallways)inShop
: Flag for whether or not the tile is in a Kecleon shopinMonsterHouse
: Flag for whether or not the tile is in a Monster HouseisStairs
: Flag for whether or not the tile is a floor exit (includes normal stairs, hidden stairs, and Warp Zones)visibleOnMap
: Flag for whether or not the tile is visible on the player's mapvisited
: Flag for whether or not the tile has been visited by the playerroom
: The ID of the room the tile is in. Will be -1 if in a hallway.
Returned in a list by the team()
and enemies()
fields, and also returned by the leader()
field. Monsters have the following structure:
index
: The monster's internal index. This is an integer from 0-19 (inclusive) that will be unique while the monster is active. Team members will have indexes from 0-3 and enemies will have indexes from 4-19. Note that when an enemy becomes inactive, it gives up ownership of the index, and new enemies that spawn (even on the same turn) can claim it.xPosition
: The monster's x position in the dungeonyPosition
: The monster's y position in the dungeonisEnemy
: Flag for whether or not the monster is an enemyisLeader
: Flag for whether or not the monster is the party leaderisAlly
: Flag for whether or not an "enemy" is actually an ally (appears yellow on the map)isShopkeeper
: Flag for whether or not the monster is a (still friendly) Kecleon shopkeeperdirection
: The direction that the monster is facingheldItemQuantity
: The quantity of the monster's held item, if applicableheldItem
: The item ID of the monster's held itembelly
: The amount of belly the monster hasfeatures
: Mostly stuff on the "Features" page in-gamespecies
: The species IDapparentSpecies
: The apparent species ID. Normally the same asspecies
, but can differ if the monster used Transform.gender
: The gender ID. Note that gender is not usually random, and will typically be set to its default for the species.primaryType
: The type ID of the monster's primary typesecondaryType
: The type ID of the monster's secondary typeprimaryAbility
: The ability ID of the monster's primary abilitysecondaryAbility
: The ability ID of the monster's secondary ability
stats
: Mostly stuff seen on the "Stats" page in-gamelevel
: The monster's levelIQ
: The monster's IQ statHP
: The monster's current HPmaxHP
: The monster's maximum HPattack
: The monster's Attack statspecialAttack
: The monster's Special Attack statdefense
: The monster's Defense statspecialDefense
: The monster's Special Defense statexperience
: The amount of experience the monster hasmodifiers
: Table of stat modifiers. For most stats (except speed), the normal value is 10, and it goes up to 20 and down to 0.attackStage
: The monster's Attack stagespecialAttackStage
: The monster's Special Attack stagedefenseStage
: The monster's Defense stagespecialDefenseStage
: The monster's Special Defense stageaccuracyStage
: The monster's accuracy stageevasionStage
: The monster's evasion stagespeedStage
: The monster's speed stage. The normal value is 1, and it goes up to 4 and down to 0.speedCounters
: Lists of "speed counters" that tick down to 0. The current speed stage is equal to(# nonzero up) - (# nonzero down)
, but kept in the range 0-4.up
: List of the 5 "up" countersdown
: List of the 5 "down" counters
statuses
: List of status effects on the monstermoves
: List of the monster's moves
Stored in a list in a monster's statuses
field. Statuses have the following (nil if not applicable) fields:
statusType
: The status IDturnsLeft
: The number of turns left of the statuseffectCountdown
: The number of turns left for a recurring effect of the status to occur, such as damage or healing
Note: the Stockpile status is special, and has the field stage
that holds the stockpile stage.
Stored in a list in a monster's moves
field. Moves have the following fields:
subsequentInLinkChain
: Flag for whether or not the move is in a link chain and isn't the starting moveisSet
: Flag for whether or not the move is setisLastUsed
: Flag for whether or not the move was the last one used (important for Encore)isDisabled
: Flag for whether or not the move is disabled (e.g. by Torment)isSealed
: Flag for whether or not the move is sealed (e.g. by a Seal Trap)moveID
: The move IDPP
: The amount of PP left for the moveginsengBoost
: The number of Ginseng boosts on the move
Returned in a list by the items()
and bag()
fields. Items have the following fields:
xPosition
: The item's x position in the dungeon, if on the groundyPosition
: The item's y position in the dungeon, if on the groundinShop
: Flag for whether or not the item is in a Kecleon shopisSticky
: Flag for whether or not the item is stickyisSet
: Flag for whether or not the item is set, if in the bagheldBy
: Index of the party member holding the item, if in the bag. For items on the ground, this will always be zero.droppedBy
: This is a special field that will normally benil
. It will only be set if an item previously held by a party member is forcibly dropped due to a Trip Trap, Knock Off, etc. and hasn't yet been picked up again (by the player; an enemy picking the item up will not cause an update). The value will be the index of the party member that dropped the item.amount
: Amount code, if applicable. Note: seems like for Poké this value doesn't correspond to the literal amount.itemType
: The item IDsprite
: The item sprite when the item is on the floortype
: The item sprite IDcolor
: The main color ID of sprite
Returned in a list by the traps()
field. Traps have the following fields:
xPosition
: The trap's x position in the dungeonyPosition
: The trap's y position in the dungeonisRevealed
: Flag for whether or not the trap is revealed to the playertrapType
: The trap IDisTriggerableByTeam
: Whether or not the trap will trigger when a team member steps on itisTriggerableByEnemies
: Whether or not the trap will trigger when an enemy steps on it
A lot of the dungeon state model uses caching, so that the bot doesn't need to reload the entire dungeon state every turn. Information to be reloaded every turn is designated in stateinfo.reloadEveryTurn()
, while information to be reloaded only once per floor is designated in stateinfo.reloadEveryFloor()
.
The bot can also access the visible dungeon state as a single object (visibleinfo.state
), defined in visibleinfo.lua
. The data model follows almost exactly the same format as the full dungeon state object (stateinfo.state
), except with fields containing inaccessible information set to nil
. In most cases, only leaf nodes in the state model (non-table fields) are set to nil
, so as to avoid causing errors in code from accessing fields in invalid subtables. Notable exceptions to this general format are described in the following sections.
Certain fields are completely inaccessible to the player, and as such are removed entirely from the state model in visibleinfo.state
. Removed fields include:
dungeon.conditions.naturalWeather()
dungeon.conditions.weatherTurnsLeft()
dungeon.conditions.mudSportTurnsLeft()
- Note:
dungeon.conditions.mudSport()
is still accessible
- Note:
dungeon.conditions.waterSportTurnsLeft()
- Note:
dungeon.conditions.waterSport()
is still accessible
- Note:
dungeon.counters.wind()
- Note:
dungeon.counters.windWarnings()
is still accessible
- Note:
dungeon.counters.weatherDamage()
- Note:
dungeon.counters.turnsSinceWeatherDamage()
is still accessible
- Note:
dungeon.counters.enemySpawn()
Empty tables already have a well-defined meaning with variable-length array fields. As such, they will instead be set to nil
in visibleinfo.state
if their values are unknown. The following fields are nullable variable-length arrays:
monster.statuses
monster.moves