Skip to content
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ The rest are previews and dumps, each driving a real screen or table:
```bash
# the full walked route: Johto, the Hall of Fame, every Kanto gym, and Red
godot --headless --path . -s res://tools/preview_world_story.gd -- crystal 24 7 2 2 1 none home story
# Red, Blue or Yellow from the bedroom to Lt. Surge
# Red, Blue or Yellow from the bedroom to the Hall of Fame
godot --headless --path . -s res://tools/preview_world_story.gd -- red 0 38 3 6 1 none home story
```

Expand Down
7 changes: 0 additions & 7 deletions autoload/diagnostics.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ extends Node

## What a player hands over when something goes wrong: this build, this machine,
## the settings and mods in force, and the engine's own log of the session.
##
## A sink rather than a set of call sites: [Logger] goes in through
## [method OS.add_logger], so every print, warning and runtime error in the game,
## a tool or a mod reaches the report without being routed twice. The file at
Expand Down Expand Up @@ -62,7 +61,6 @@ static func instance() -> Gen2Diagnostics:

## Records one line of context. Safe before the autoload exists and in a tool
## run, so a caller never guards the call itself.
##
## Goes through `print`, which is what puts it in the engine's log file next to
## the errors it explains; the sink below picks it up on the way past.
static func note(topic: String, message: String) -> void:
Expand Down Expand Up @@ -92,7 +90,6 @@ func _ready() -> void:
## Printed rather than written, so it is near the top of the engine's own log
## file: a crash log is then self-describing whether or not the player ever
## reaches the launcher again.
##
## A player's launch only, for the reason [method trace] gives: a check or a
## tool is read for the answer it prints, and a header no one asked for is in
## the way of it.
Expand Down Expand Up @@ -209,7 +206,6 @@ func report() -> String:

## Writes the report and every kept log file into one `.zip` under
## [param folder], and answers the path it wrote.
##
## A zip rather than the log itself because the useful thing is the whole set:
## the session that crashed is usually the file *before* the one this launch is
## writing. An empty [param folder] takes the platform's downloads directory,
Expand Down Expand Up @@ -285,7 +281,6 @@ func log_files(directory: String = DIRECTORY) -> PackedStringArray:

## Drops log files in [param directory] past the count, the age or the total
## size this keeps, whichever bites first, oldest first.
##
## The engine's own rotation counts files at startup and nothing else, so a
## single session that logged for a week, or a build that once wrote under
## another name, would otherwise sit in the player's data directory for good.
Expand Down Expand Up @@ -339,7 +334,6 @@ func record(level: String, message: String) -> void:


## Reads the previous session's marker and raises this one's.
##
## Only a player's own launch writes it. A headless check or a `-s` tool that
## the wall-clock cap kills never reaches [method _exit_tree], so letting those
## write the marker would report a crash to the player at the next launch, and
Expand Down Expand Up @@ -510,7 +504,6 @@ static func _video_adapter() -> String:

## The sink itself, kept beside the autoload rather than in a file of its own:
## it is four lines and it has no other caller.
##
## Nothing here prints. A logger that raised a message of its own would be
## handed it straight back.
class Gen2DiagnosticsSink extends Logger:
Expand Down
3 changes: 0 additions & 3 deletions autoload/game_runtime.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ class_name Gen2GameRuntime
extends Node

## Runtime selection shared by the launcher and screens opened from it.
##
## Cartridge bytes and decoded data stay owned by their existing layers. The
## selected save is the exception: it is mutable, and every screen has to see the
## same instance. Re-reading the slot per call handed a battle result, a party
Expand All @@ -14,7 +13,6 @@ var selected_game_id: StringName = &""
var selected_save_slot: int = -1

## The new game the intro is running for, before it exists on disk.
##
## `NewGame` reaches `InitializeWorld` only after `PlayerProfileSetup` and
## `OakSpeech` have both returned, so there is nothing to write until the intro
## finishes. The launcher stages the slot and the slot's own label here, the
Expand Down Expand Up @@ -99,7 +97,6 @@ var _second_screen_host: Gen2SecondScreenHost = null


## Loads installed mods before any screen exists.
##
## A mod registers what it provides and returns, so this must happen before the
## first screen asks the host: a renderer registered after the overworld was
## built would not be offered until the next map. It also means a broken mod is
Expand Down
5 changes: 0 additions & 5 deletions game/battle/accuracy.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ class_name Gen2Accuracy
extends RefCounted

## Whether a move connects.
##
## Accuracy is a byte out of 255, not a percentage: "100%" stores 255 and "90%"
## stores 229. Kept as the byte, because the roll is against it and a stored 255
## is a special case that never misses.
##
## Accuracy and evasion use their own multiplier table, a different shape from
## the other stats', so -1 accuracy and -1 Attack are different fractions.

Expand All @@ -23,10 +21,8 @@ const STAGE_MULTIPLIERS: Array = [


## The chance a move connects, out of 255.
##
## Evasion reads the same table from the other end rather than a second table:
## +2 evasion is the multiplier accuracy uses at -2.
##
## [param foresight] drops both sides' stages, not only evasion, and only when
## the evasion stage is at least the accuracy stage, so it cannot undo an
## accuracy the attacker raised.
Expand Down Expand Up @@ -58,7 +54,6 @@ static func apply_stage(value: int, stage: int) -> int:


## Rolls a hit against a chance out of 255.
##
## A chance of exactly 255 connects without rolling. Rolling would miss one time
## in 256, and Crystal goes out of its way not to. [param generation] is
## `MoveHitTest`, which does not: pret's own comment there says even the highest
Expand Down
4 changes: 0 additions & 4 deletions game/battle/ai.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ class_name Gen2BattleAI
extends RefCounted

## Scores an enemy trainer's move choice the way the cartridge's own AI does.
##
## Every slot starts at 20, or 80 with no PP. Each bit set in the trainer class's
## [constant Gen2Layout.ATTR_AI_MOVE_WEIGHTS] runs one scoring layer over the four
## slots, nudging scores up (discourage) or down (encourage); lowest wins, ties
Expand Down Expand Up @@ -1259,7 +1258,6 @@ static func _smart_pursuit(scores: Array, slot: int, c: Context) -> void:


## `AI_Smart_Protect`: one ladder of tests, first match winning.
##
static func _smart_protect(scores: Array, slot: int, c: Context) -> void:
if c.attacker.protect_count != 0:
_smart_protect_discourage(scores, slot, c, true)
Expand Down Expand Up @@ -1398,7 +1396,6 @@ static func _apply_opportunist(scores: Array, c: Context) -> void:
## whichever deals the most, unless it would cost the mon itself
## ([constant RECKLESS_EFFECTS]) or does one point of damage that is really a
## fixed-damage move ([code]power < 2[/code]).
##
## The estimate is [method _estimate_damage], which is `AIDamageCalc` itself.
static func _apply_aggressive(scores: Array, c: Context) -> void:
var attacker: Gen2BattleMon = c.attacker
Expand Down Expand Up @@ -1450,7 +1447,6 @@ static func _estimate_damage(c: Context, move: Dictionary, constant: bool = true

## [constant Gen2Layout.AI_CAUTIOUS]: discourage [constant RESIDUAL_MOVE_NUMBERS]
## once it is no longer the attacker's first turn.
##
## Diverges from a documented source bug (`docs/bugs_and_glitches.md`,
## "'Cautious' AI may fail to discourage residual moves") unless
## `cautious_ai_abandons_remaining_moves` is on: `ret nc` abandons the remaining
Expand Down
7 changes: 0 additions & 7 deletions game/battle/ai_switch.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ extends RefCounted
## Whether a trainer pulls its Pokemon out, and which one it sends instead:
## `CheckAbleToSwitch` and its five party scans in `engine/battle/ai/switch.asm`,
## plus the three frequency gates in `items.asm`.
##
## The cartridge works in six-bit masks and reuses one variable as both a score
## and a party index; here the masks are arrays of indices and the two uses are
## separate return values. Nothing changes: every scan keeps party order, and
Expand Down Expand Up @@ -51,7 +50,6 @@ const THREAT_LOW: int = 5


## Whether this trainer switches, and to which party index.
##
## Answers [code]{"switch": bool, "index": int}[/code]. [param flags] is the
## class's own [constant Gen2Layout.ATTR_AI_ITEM_SWITCH] word; a class with none
## of the three switch bits never switches, which is `AI_SwitchOrTryItem`'s own
Expand All @@ -75,7 +73,6 @@ static func decide(battle: Gen2Battle, flags: int, rng: RandomNumberGenerator) -

## `FindMonInOTPartyToSwitchIntoBattle`: who the AI would rather have in, with no
## opinion about whether it should switch at all.
##
## [method decide] is the ordinary route and answers both questions at once.
## Baton Pass is the one caller that has already settled the first, so it needs
## the pick on its own. Nobody standing answers -1; a shortlist that resists
Expand Down Expand Up @@ -171,7 +168,6 @@ static func _counter_choice(battle: Gen2Battle, immune: Array) -> Dictionary:

## `CheckPlayerMoveTypeMatchups`: how well the Pokémon that is out is doing,
## starting at [constant BASE_SCORE]. Higher is better for staying in.
##
## The first half reads what the player has actually thrown so far, falling back
## to the player's own types when it has thrown nothing. The second half reads
## what the enemy's own moves would do back.
Expand Down Expand Up @@ -296,7 +292,6 @@ static func _alive_enough_to_switch(battle: Gen2Battle) -> bool:


## `FindEnemyMonsWithAtLeastQuarterMaxHP`, narrowing whoever was passed in.
##
## The name is the only quarter in it. `AICheckEnemyQuarterHP` doubles the HP
## word twice with `sla c / rl b`; this routine writes `srl c / rl b`, so the low
## byte is halved twice while the high byte is doubled twice and picks up the two
Expand All @@ -313,7 +308,6 @@ static func _at_least_quarter_hp(battle: Gen2Battle, candidates: Array) -> Array


## The `srl c / rl b` pair run twice over the HP word, as a number.
##
## For a maximum HP under 256 the whole thing comes to "current HP is not a
## multiple of four": the high byte ends up holding the two bits the low byte
## dropped, so anything but a multiple of four lands over 255 and clears any
Expand Down Expand Up @@ -364,7 +358,6 @@ static func _resisting(battle: Gen2Battle, candidates: Array) -> Array:

## `FindEnemyMonsWithASuperEffectiveMove`, with `FindAliveEnemyMons` folded in
## the way `FindAliveEnemyMonsWithASuperEffectiveMove` folds it.
##
## Answers [code]{"index": int, "quality": int}[/code]: quality 2 for the first
## candidate holding a move that is super effective against whoever the player
## has out, 1 for the first that at least has a neutral one, and 0 for nobody.
Expand Down
9 changes: 0 additions & 9 deletions game/battle/battle.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ extends RefCounted

## A battle: two parties, a turn at a time. Scene-free with randomness injected,
## so a whole battle can be fought in a test with no display.
##
## A turn answers with events carrying their own numbers, never a string:
## sentences, animation and draining bars are the screen's job. A side is a party
## and a wild encounter a party of one. A turn ending with somebody down says so
Expand Down Expand Up @@ -751,7 +750,6 @@ static func use_item(item: int) -> Dictionary:
## `InitEnemyTrainer`: the class's own `TRNATTR_ITEM1` and `TRNATTR_ITEM2` into
## the two working slots, and then `IsGymLeader`'s own party walk. `NO_ITEM` is
## zero and is not carried.
##
## [param rewarded] is false for the two opponents `ReadTrainerParty` returns in
## front of, the Battle Tower's and a link partner's: neither reaches
## `ComputeTrainerReward`, and neither win branch pays money either.
Expand Down Expand Up @@ -1513,12 +1511,10 @@ static func double_reward(amount: int) -> int:


## `BattleWon.give_money`, the whole of what a beaten trainer pays.
##
## [param reward] is [member battle_reward], a quarter of the prize: the Amulet
## Coin doubles that quarter, four quarters are handed out one at a time, and
## the two `.DoubleReward` calls at `.done` put the total back for the line that
## announces it. [param mom_flags] is `wMomSavingMoney`.
##
## Returns the two credits, the figure the line prints and which line it is.
static func prize_money_split(
reward: int, amulet: bool, mom_flags: int, moms_money: int, max_money: int
Expand Down Expand Up @@ -1565,7 +1561,6 @@ func _send_out_animation(enemy_turn: bool, param: int) -> Dictionary:

## `SendOutMonText`, which picks one of four lines off how much of the opponent
## is left. Only the player is ever announced this way; the enemy has one line.
##
## The arithmetic is the source's own: the remaining HP times 25 over the top
## quarter of the maximum, both read as the cartridge reads them, so the answer
## is a percentage that has been through an eight-bit divisor. A maximum below
Expand Down Expand Up @@ -2972,7 +2967,6 @@ func _act(side: int, slot: int, move_number: int, events: Array) -> void:

## The command interpreter: `DoMove`'s own read cycle over the list an effect
## byte picks, with `SkipToBattleCommand` and `endloop`'s rewind to `critical`.
##
## `ResetTurn`, used by Metronome, Mirror Move and Sleep Talk: the called move
## replaces the working one and starts its list from the beginning, without the
## once-per-action status gate. A fresh [Gen2Turn] is that clean move-struct copy,
Expand Down Expand Up @@ -3035,7 +3029,6 @@ func run_move_effect(turn: Gen2Turn, depth: int = 0) -> void:
## calls, `RegionCheck` and `IsGymLeader`. Kept here rather than on the screen
## because every input is battle state: `wBattleType`, `wOtherTrainerClass`,
## `wOtherTrainerID`, `wTimeOfDay` and the map's landmark.
##
## `MUSIC_SUICUNE_BATTLE` exists on Crystal alone; the two `BATTLETYPE_` rows in
## front of the trainer check are the only place either game reaches it, and
## Gold and Silver never write those types.
Expand Down Expand Up @@ -3112,7 +3105,6 @@ const LANDMARK_VICTORY_ROAD: int = 0x58
## does everything below `KANTO_LANDMARK`, and so does Victory Road and every
## landmark above it, because `cp LANDMARK_VICTORY_ROAD / jr c, .kanto` only
## takes the Kanto branch below that row.
##
## The `LANDMARK_SPECIAL` backup lookup in front of it is
## [method Gen2WorldAPI.landmark_backup], which every caller of this resolves
## the landmark through.
Expand All @@ -3125,7 +3117,6 @@ static func region_is_kanto(landmark_id: int, crystal: bool = true) -> bool:


## `PlayBattleMusic`'s answer: the track a battle opens on.
##
## [param landmark_id] is `GetWorldMapLocation`'s, [param trainer_class] and
## [param trainer_id] are `wOtherTrainerClass` and `wOtherTrainerID` (class 0
## being a wild fight), and [param day_period] is `wTimeOfDay`.
Expand Down
3 changes: 0 additions & 3 deletions game/battle/battle_anim_bg_effects.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ extends RefCounted
## The `BATTLE_BG_EFFECT_*` jumptable and the routines it dispatches
## (engine/battle_anims/bg_effects.asm): the screen shakes, the scanline
## deformations, the palette fades and the tilemap edits. Five run at once.
##
## An effect id is profile-local and is never normalised: pokegold ships no
## `BATTLE_BG_EFFECT_BODY_SLAM`, so every id from $25 on names a different effect
## in the two games; both jumptables are kept whole and dispatch is by name. The
Expand Down Expand Up @@ -444,7 +443,6 @@ static func _hues(

## `BGEffect_RapidCyclePals`, the Color branch: one side of the field at a time,
## and the enemy's own states are the two above the player's.
##
## Nothing here ends the walk. The list's own `$ff` only stalls it; the effect is
## retired by the script's `anim_incbgeffect`, which is what steps it onto the
## state that puts the palette back.
Expand Down Expand Up @@ -1336,7 +1334,6 @@ static func _shake_amount(

## `BattleBGEffect_Rollout`: the screen shaken vertically, with the first
## animation object moved the opposite way so the ball it draws stays put.
##
## The source waits a frame here rather than at the bottom of `.playframe`;
## in a player stepped once per frame that is the same one frame either way.
static func _rollout(
Expand Down
4 changes: 0 additions & 4 deletions game/battle/battle_anim_object.gd
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ extends RefCounted
## (engine/battle_anims/core.asm, helpers.asm). `anim_obj` names a row of
## `BattleAnimObjects`, which supplies the frameset, the motion callback, the
## palette and the graphics sheet, and a place to put it.
##
## Every field is a cartridge byte: coordinates wrap at 256, and an object walking
## off one side is that wrap rather than a clamp. `frame` starts at -1 because
## `GetBattleAnimFrame` increments before it reads.
Expand Down Expand Up @@ -108,11 +107,9 @@ func active() -> bool:


## `BattleAnimOAMUpdate`, as the sprites it would write into `wShadowOAM`.
##
## Returns [code]{ deleted, sprites }[/code]. `sprites` is empty for an
## `oamwait`, which is a frame the object is simply not drawn on, and for the
## `oamdelete` that ends it; `deleted` says which of the two happened.
##
## [param enemy_turn] is `hBattleTurn`, the only thing that decides whether the
## coordinates are mirrored onto the other side of the field.
func oam_update(
Expand Down Expand Up @@ -207,7 +204,6 @@ func _attributes(attributes: int, flags: int, object_palette: int) -> int:

## `GetBattleAnimFrame`. Answers the OAM set to draw, or one of the three
## commands, and leaves [member _frame_flags] set for the frame it chose.
##
## While a frame still has duration left it is redrawn without advancing.
## `oamend` steps back two and loops, which redraws the last real frame forever;
## `oamrestart` goes back to -1 and loops, which starts the frameset again.
Expand Down
5 changes: 0 additions & 5 deletions game/battle/battle_anim_script.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ extends RefCounted
## The battle animation command interpreter (engine/battle_anims/anim_commands.asm).
## Nothing here draws, plays a sound or touches a palette: the commands are
## reported and whoever is drawing decides what they look like.
##
## Anything below [constant FIRST_COMMAND] is a delay rather than a command, so
## `anim_wait N` is exactly N frames. The control flow is the cartridge's single
## `wBattleAnimParent` word and single `wBattleAnimLoops` byte, so a call inside a
Expand Down Expand Up @@ -116,7 +115,6 @@ const WOBBLE_CAUGHT: int = 1
const WOBBLE_ESCAPED: int = 2

## How many commands one frame may run before the script is abandoned.
##
## The cartridge has no such limit: `.RunScript` loops until a delay byte or a
## top-level `anim_ret`, and a script that does neither hangs the hardware. This
## is ours, so a malformed cached region or a mod's own script costs a refused
Expand Down Expand Up @@ -151,7 +149,6 @@ var _failed: bool = false

## An interpreter positioned at [param start_address] inside [param region], which
## starts at [param base_address].
##
## [param param] is `wBattleAnimParam`, which the caller sets before playing;
## `wBattleAnimVar` starts at zero because `ClearBattleAnims` clears it.
static func create(
Expand All @@ -173,7 +170,6 @@ static func create(
## [code]{ ok, name, byte, operands, size, target }[/code]; `target` is the
## start_address a branch would take, or -1. A delay byte answers [constant WAIT] with
## its own value as its single operand.
##
## Shared with [Gen2BattleAnimImporter], which walks every body with it, so the
## vocabulary is stated once.
static func decode_command(
Expand Down Expand Up @@ -250,7 +246,6 @@ func variable() -> int:

## One hardware frame of `RunBattleAnimCommand`, as an Array of the commands it
## ran, each [code]{ name, byte, operands }[/code].
##
## Empty while a delay is counting down, which is most frames, and empty once
## the script has stopped. A frame that runs commands ends either on the delay
## byte that set the next pause or on the `anim_ret` that ended the script, and
Expand Down
Loading