Unit-test the eight trap effects against the C reference (closes #14)
`trapHandlers` had eight entries and zero direct tests, on the one subsystem besides combat that can kill the hero outright. New `game/traps_test.go` covers all eight arms of `move.c be_trapped`, the prologue every trap runs through, and the `rust_armor` tail `T_RUST` calls. Test-only: no game code changes. Every expected value is transcribed from `origin/c-master` (`move.c`, `misc.c`, `fight.c`, `monsters.c`, `rogue.h`) and quoted in the file. No divergence from C was found. The trap set is `rogue.h` 192-200: there is no separate "poison dart" kind — `T_DART` is the poisoned dart — and `T_MYST`, the eleven-way `rnd(11)` message switch, is the eighth. Details the tests are built around: `BEARTIME`/`SLEEPTIME` are `spread(3)`/`spread(5)`, both of which reduce to `rnd(0)` and so cost no random number, which is asserted as well as their values; `T_ARROW` swings at `s_lvl - 1` and `T_DART` at `s_lvl + 1`; and the strength loss is gated on `!ISWEARING(R_SUSTSTR) && !save(VS_POISON)`, whose short circuit means the ring saves a random draw as well as the strength. Damage dice and swing arguments are checked by sweeps rather than single shots: `rnd(n)` is "raw value % n", so one draw cannot separate a d6 from a d5, and a forced hit or miss cannot see a wrong `at_lvl`. Both shapes were forced by mutation runs that the single-shot versions survived. `be_trapped` takes a coordinate, and which coordinate decides whether `T_TELEP`'s `mvaddch(tc, TRAP)` does anything. Sprung under the hero (`move.go` 105-108, `case Floor`) the line is redundant: `tc` is the hero's square, already stamped `TRAP` by the prologue and redrawn by `teleport()`'s opening `mvaddch(hero, floor_at())`. Walked onto (`move.go` 94-98, `case Trap`) it is the only writer: `tc` is the square being stepped onto while the hero still stands on the previous one, `leave_room` writes blanks and never `TRAP`, and the arm returns before `finishMove` so no `look()` follows. Both shapes are tested. The two death messages are deliberately uncovered: each is printed immediately before `death()`, which reaches `myExit` and `os.Exit`, so provoking either would kill the test binary. The hero is pinned with `fortify()` and the damage is checked by replaying C's arithmetic. They are the only two: `rust_armor`'s `|| ISWEARING(R_SUSTARM)` operand and its `if (!to_death)` message suppression are covered as well.
This commit is contained in:
1140
game/traps_test.go
Normal file
1140
game/traps_test.go
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user