You’re right—there’s still a lot of behavior worth pushing into adventure.yaml- driven traversals. - The strongest remaining hardcoded islands are in main.c:playermove and actions.c. - The movement graph is already data-driven in make_dungeon.py, but special-case dispatch is still hardcoded in C. Concrete migration opportunities: 1. main.c: move dest_special handling (currently case 1/2/3 in playermove) out of the switch and into a YAML-driven travel_specials table generated by make_dungeon.py, with IDs defined in adventure.yaml. This isolates one-off movement logic (plover/troll bridge) into declarative data and keeps playermove generic. 2. main.c: replace checkhints() switch (cases 0..9) with per-hint predicates in YAML (e.g., if: [at, object=GRATE, state!=CLOSED] style), then drive evaluation from generic predicate/effect handlers. This turns hint gating logic into declarative condition traversal, still reusing existing game.hints[] output and penalty/question text. 3. main.c: move command rewrite/syntax shortcuts from preprocess_command() into data entries like input_rewrites (pattern + predicate + rewrite). Current hardcodes (ENTER WATER, object+verb swap, grate remap, water/oil plant| door, cage bird) are ideal table rows. 4. actions.c: replace object/verb fanouts in: - attack() (target selection and default behaviors), - vcarry(), - discard(), - fill(), feed(), lock(), pour(), listen(), wave(), read(), throwit(), with YAML-driven action rules keyed by (verb, object, object class/tags, state predicates). This is the biggest remaining surface for data-driven refactor. 5. main.c: move discovery-side effects in listobjects() (e.g., RUG/CHAIN/EGGS special prop mutations, tally decrement timing) into per-object discovery metadata produced by get_objects in make_dungeon.py. That keeps “show object” behavior and scoring side effects in one object-first DSL. 6. actions.c: make action() dispatch itself more declarative by adding verb metadata (default handler, requires-object, intransitive fallback behavior) and avoid giant verb switches where behavior is purely routing (not logic). Keep the C handlers that need heavy state machines (randomized/dwarf interactions), but drive routing from generated data where possible. Implementation sequencing (lowest risk first): - preprocess_command rewrites + playermove special travel dispatch - hint predicates - then object action rule tables (lock/fill/feed/listen/attack high-value clusters)