JRPG KGraph Parser & Automated Playthrough, Part 2: Rebuilding Final Fantasy (1990 NES) from Coneria to Defeating Garland
In Part 1 we introduced robos-jrpg-parser and the beginner bootcamp on Ember Quest and Quest: Warrior Dragon. In Part 2 we walk through our separate, full-scale build of the 1990 North American NES release of Final Fantasy: harvesting 82 reference files into a private folder, closing the 5 gameplay blockers from the 6502 disassembly (including the critical-hit index bug and indoor ceiling palette swap), building the 4-hero Godot 4.3 engine with 2-step NES shop interiors, passing 7 isolated headless Cucumber suites, and clearing all 12 Chapter 1 milestones to defeat Garland in the RobOS Game Playthrough viewer.
In Part 1 of this series (and the companion Part 1 eLearning course), we introduced packages/robos-jrpg-parser on a compact practice game (Ember Quest) and a single-hero Godot 4 bootcamp (Quest: Warrior Dragon). In parallel, we ran the exact same pipeline against a much larger target in a separate private workspace: the 1990 North American NES release of Final Fantasy.
Today we are publishing Part 2 of the Interactive eLearning Course (/elearning/how-to-recreate-classic-jrpg-using-kgraph-parsing-with-automated-playthrough-part-2/) alongside this technical deep dive, walking through every engineering hurdle we hit taking the 4 Light Warriors from the title screen through Coneria's shops, Coneria Castle, and the Temple of Fiends to defeat Garland—and documenting exactly where the build left off at the North Bridge gateway to Chapter 2.
packages/game-playthrough --game-dir ~/Downloads/ff1/ff1-game) after completing all 12 Chapter 1 milestones in 100.9 seconds with 0 deaths: Garland (106 HP) is defeated, Princess Sara is rescued, and the North Bridge is built.1. Harvesting 82 Mixed Reference Files & Quarantining GBA/PS1 Remakes
Scaling from a 12-file demo to a real 1990 cartridge begins with reusable acquisition. Rather than hardcoding URLs for one game, packages/robos-jrpg-parser/tools/harvest_jrpg_assets.py reads a saved VGMaps NES index page, matches all 27 FinalFantasy-*.png atlas sheets, queues 14 StrategyWiki guide pages, and writes both ~/Downloads/ff1/sources-manifest.json and ~/Downloads/ff1/download-receipt.json (recording SHA-256 hashes and PNG IHDR dimensions).
Inspecting download-receipt.json exposed two immediate physical facts:
- Exact Overworld vs. Cropped Town Sheets: While
FinalFantasy-World(Unmarked).pngis4096×4096pixels (an exact256×256grid of16×16tiles), VGMaps town and dungeon PNGs such asFinalFantasy-Coneria.png(987×544) andFinalFantasy-TempleOfFiends(Present).png(805×594) are cropped reference sheets where human mappers trimmed repeating outer border trees and composited multiple floors onto one canvas. - Remake & Balance-Mod Contamination: Real community folders mix editions. Running
jrpg-parser.js scan ~/Downloads/ff1 --edition "NES (USA)"classified 61 authentic NES files as usable, skipped 12 saved-page_files/directories, and quarantined 9 non-NES files—including GBA Dawn of Souls screenshots, PS1 Origins battle sheets, and a saved forum thread (shop.html, "Let's Play Dawn of Souls FF1: Mod of Balance!") whose rebalanced 50 G spell prices would otherwise overwrite the 100 G 1990 NES magic tables.
IHDR dimensions in download-receipt.json before slicing a single tile.
jrpg-parser.js scan quarantines GBA, PS1, PSP, and modded files (usable: false) so remake numbers never enter the NES graph.2. The Verbatim Quote Gate & Why Fan Guides Left 5 Engine Blockers
During jrpg-parser.js parse, structured HTML and Markdown tables are parsed deterministically by lib/charts.js, while unstructured walkthrough prose is extracted through lib/extract.js behind a hard verbatim quote gate: if the quote field returned by the AI agent is not literally present in the local file on disk, the record is dropped. In our FF1 run, that gate caught and dropped 4 unverified records where the model attempted to supply remake facts from pretraining memory, and parsed.json surfaced 5 cross-source conflicts (such as normalizing a prose walkthrough's GBA Mythril Sword alias to the 1990 NES Silver Sword).
Even more importantly, running jrpg-parser.js coverage --out ~/kgraphs/final-fantasy-nes after scraping the web guides and the 84-page Nintendo manual (CLV-P-NAAAE.pdf) showed why prose guides alone cannot run a game engine. Guides record what players see in menus (monster HP/XP/Gold, spell names and prices), leaving five engine blockers: missing enemy combat stats (ATK, ACC, Hits, CRT, DEF, EVA, MDEF), missing 8-slot encounter formation tables, missing 50-level class stat/XP curves, missing numeric spell Effectivity (Power E) and Accuracy bytes, and missing 64×64 walkable tile grids with exact door and chest coordinates.
lib/extract.js.
3. Closing the Gaps from the 6502 Disassembly (Including 3 Famous 1990 NES Quirks)
To close all five blockers with 100% hardware accuracy, we cross-referenced Disch's commented 6502 disassembly (~/Downloads/ff1/nes_disassembly/) with AstralEsper's NES Game Mechanics Guide and wrote build_ff1_resources.py + update_reference_guide.py. That decoded all 128 enemies, 64 spells, 12 classes across 50 levels, 84 encounter zones, 256 treasure chests, and 61 RLE-compressed 64×64 map grids into ~/Downloads/ff1/nes_data/ and map_grids/, and appended structured Markdown tables to ff1_nes_agent_reference_guide.md.
Reading the 6502 assembly also preserved three famous 1990 NES quirks in our engine:
- The Weapon Critical Hit Index Bug: In
LoadOneCharacterIBStats, a pointer bug loads the weapon's 1-based inventory index (1..40) instead of its critical byte, giving the Wooden Nunchuck (ID 1) a1/201crit rate and the Masamune (ID 40) a40/201(~19.9%) crit rate. - The Level-Up HP & Strong-Level Bitmask: Every level-up grants
floor(VIT / 4) + 1HP, plus20..25bonus HP on levels flagged in the class's 49-level strong-HP bitmask table. - The INT Magic Bug: Caster
INTnever scales magic in the 1990 NES release; Level 1CURE(E=16) heals16..32 HPand Level 1FIRE(E=10, ACC=24) rolls10..20(doubling to20..40when0..255 < 148 + Spell_Acc - Target_MDEF).
IMP (8 HP) and GARLAND (106 HP, 15 ATK, 10 DEF) alongside numeric spell power bytes.
jrpg-parser.js parse produces 1,206 validated OSLC JSON-LD nodes across 13 RDF types with zero blockers.4. 64×64 Walkable Grids, the Tree Spawn Bug, and the Indoor Ceiling Palette Swap
When we first booted our Godot 4.3 project (~/Downloads/ff1/ff1-game) and ran our opening Gherkin scenario, every step passed—yet inspecting the recorded video frames exposed two classic visual bugs that unit tests never see:
- The South Gate Border Tree at
(15, 22): Checking rowy=21ofmap_00_coneria.json([14, 14, 16, 14, 14]) showed that Coneria's south entrance is a single brick column wide atx=16(tileId=16, matchinglut_EntrTele_X = 16) flanked by unwalkable border trees atx=15andx=17(tileId=14). Movingspawn_tilefrom(15, 22)toVector2i(16, 21)placed the party squarely on the brick street. - Outside-Room Ceiling Palette vs. Inside-Room Chest Palette: In
lut_SMPalettes($A000), Outside-Room Palette 0 (+0x00) is[0x0F, 0x30, 0x30, 0x30](solid white) so the NES PPU can hide unentered rooms behind a white ceiling, while Inside-Room Palette 0 (+0x20) is[0x0F, 0x10, 0x17, 0x0F](black, silver, and wood brown). Swapping in Inside-Room Palette 0 and removing a debugColorRectoverlay turned flat teal squares back into crisp silver-and-brown treasure chests.
map_00_coneria.json showing the 1-tile brick corridor at x=16 and Coneria's shop door coordinates.
+0x00) for Inside-Room Palette 0 (+0x20) restores the indoor floor and silver-and-brown chests.5. Clean-Room Art & the Authentic 2-Step NES Shop Interior
Using jrpg-generate-art (packages/robos-lib/ai-image.js + nesify.py), we generated 50 clean-room NES-quantized sprites, backdrops, and maps and ran jrpg-parser.js publish to export ~/kgraphs/final-fantasy-nes-public (1,184 fact nodes + 50 clean-room images, zero source filenames or quotes).
Next came the most important interactive fix of Chapter 1. When we first let the AI player loose in Coneria to buy gear before fighting Garland, it walked onto the Coneria Weapon Shop door at (11, 10) and got stuck in an infinite loop. To fix both the visual presentation and the state machine, we built the authentic NES 2-step Shop interior inside FF1MapScene.gd for all six shop types (WEAPON, ARMOR, WHITE, BLACK, INN, ITEM):
- Stepping onto a shop door opens the royal-blue NES shop layout with the top-left shop banner, the center shopkeeper counter, the item/spell price list on the right, the greeting dialogue box, the live Gold box (
400 G), and the white pointing-hand glove cursor positioned onBuy(shop_cursor = 0). - Pressing
ui_acceptonBuyequips the class-appropriate upgrades (RapieronZEST,HammeronROBO,Chain Mailat the Armor Shop,CURE/RUSEat White Magic,FIRE/LITat Black Magic), deducts Gold live, sets the milestone flag, and automatically advances the pointing-hand cursor toExit(shop_cursor = 1). - Pressing
ui_acceptonExitcloses the shop overlay and steps the party one tile south off the doorway trigger so it never re-enters the shop in a loop.
(11, 10) places the white pointing-hand cursor on Buy (index 0) with 400 G.
ui_accept buys and equips Rapier & Hammer, updates Gold to 380 G, and moves the cursor to Exit (index 1).6. Seven Isolated Headless Cucumber Suites → 12-Milestone Stepped Playthrough
Rather than discovering mechanic bugs midway through a full-game run, we built and passed 7 headless Cucumber suites in ~/Downloads/ff1/ff1-game/tests/e2e/features/:
01_start_new_game_and_create_party.feature—TitleScreen→PartyCreate(ZEST,SAIL,ROBO,MAGE) →Coneria (16, 21).02_smoke_maps_and_transitions.feature— Town, Overworld, Castle 1F/2F, and Temple of Fiends transitions.03_npc_dialogues.feature— Facing the Coneria town guard and the King of Coneria and dismissing dialogues cleanly.04_shops_and_inn.feature— All 6 Coneria shop and Inn scenarios (46 steps passed in11.3s).05_treasure_chests.feature— LootingHeal Potion(3,3),Cabin(2,3), andLeather Cap(4,14)in the Temple of Fiends with open-chest persistence.06_random_encounters_and_boss.feature— OverworldIMPencounter and theGARLANDboss fight (106 HP) at(19, 5).07_checkpoint_kill_garland_1.feature— Checkpoint-chained Act I verification across Milestones1..6,7..8, and9..12(21 steps passed in72.1s).
04_shops_and_inn.feature verifies Weapon, Armor, White Magic, Black Magic, Item, and Inn interiors headlessly in 11.3 seconds.
106 HP) in the Temple of Fiends at the end of 07_checkpoint_kill_garland_1.feature.7. Where We Left Off & The Gateway to Chapter 2
With all 7 isolated suites green, running python3 tests/e2e/play_full_game.py --fresh --stepped --time-scale 3.0 clears all 12 Chapter 1 milestones in 100.9s with 0 deaths, writing 12 per-milestone MP4 videos, 12 JSON save checkpoints, and 12 PNG screenshots into tests/e2e/reports/playthrough/ for inspection in the RobOS Game Playthrough viewer.
--stepped --only 3) in 8.4 seconds and inspecting checkpoints/12-defeat-garland-1.json.Where the FF1 project sits right now: At the end of Milestone #12 (checkpoints/12-defeat-garland-1.json), the Light Warriors have defeated Garland in the Temple of Fiends, rescued Princess Sara, and unlocked the North Bridge (bridge_built: true). Because our 1,206-node Knowledge Graph in ~/kgraphs/final-fantasy-nes and the 61 decompressed 64×64 map grids in ~/Downloads/ff1/map_grids/ already contain every town, dungeon, monster, spell, shop, and treasure chest in the 1990 NES cartridge, Chapter 2 picks up directly at Checkpoint #12: crossing the North Bridge to Pravoka, defeating Bikke's Pirates to win the Ship, sailing to Elfland, looting the Crown from the Marsh Cave, and defeating Astos.