Replace .golangci.yml with the shared canonical config. The old
config's top-level linters-settings block was silently ignored under
the v2 schema, so the lll/funlen/cyclop/dupl thresholds now actually
apply. The four repo-specific disables (mnd, exhaustive, paralleltest,
testpackage) move out of the config into targeted in-code nolint
directives carrying their original approval dates, keeping the config
byte-identical to the canonical one.
Fixes surfaced by the stricter settings: t.Parallel() added to all 32
tests, 24 overlong lines wrapped or their comments tightened, tcell
control-code returns rewritten as character literals, dupl markers on
the identically-shaped item data tables, and two wsl_v5 defer cuddles.
No behavior changes. The repo has no golangci-lint version pin (no
Dockerfile or CI; make lint runs the host binary, currently v2.12.2),
so there was nothing to bump.
NewGame(Config) becomes New(Params), and Restore takes Params too, so
the package's primary type gets the canonical New() constructor with a
named-field Params struct (styleguide points 139, 159). cmd/rogue and
all tests updated; ARCHITECTURE.md constructor references corrected.
Pure rename, suite green.
Refactor step 4. Renames (C breadcrumbs kept in doc comments):
doMove→moveHero, beTrapped→springTrap, rndmove→randomStep,
doRooms→digRooms, doPassages→digPassages, doMaze→digMaze,
chgStr→changeStrength, doRun→startRun, moveStuff→finishMove,
turnref→turnRefresh, moveMonst→moveMonster, doChase→chaseStep,
setOldch→setOldChar, cansee→canSee, roomin→roomIn, runto→runTo,
conn→connectRooms, putpass→putPassage, passnum→numberPassages,
numpass→numberPassage, rndPos→randomPos, rndRoom→randomRoom,
treasRoom→treasureRoom, accntMaze→accountMaze.
All goto/label flows are gone: moveHero uses a retry loop with the
PASSGO corner logic extracted into passageTurn; dispatch re-dispatches
via a loop; chaseStep re-checks via a loop; saveGame uses a labeled
prompt loop. Control flow and RNG call order are unchanged; suite
green.
.golangci.yml is the prompts-repo standard verbatim plus one approved
exception (paralleltest, sneak 2026-07-06). Roughly 1,500 findings
fixed:
- autofix sweep (wsl_v5/nlreturn/intrange/modernize formatting), with
the misspell autofix REVERTED where it rewrote authentic C game text
("missle vanishes" stays, with nolint and a comment)
- error handling: errcheck sites get real handling — saveFile now
closes explicitly and removes corrupt saves, scoreboard writes are
documented best-effort, err113 sentinel errors (ErrSaveOutOfDate,
ErrScreenTooSmall); panics allowed for unrecoverable states per
MEMORY.md policy
- gosec: real fixes (ParseInt for SEED, 0600 scorefile) and justified
per-line nolints for provably-bounded conversions (randomMonsterLetter
helper collapses eight rnd(26)+'A' sites)
- API tidying from linters: pointer receivers on flag types
(recvcheck), msg helpers renamed addmsgf/doaddf/Printwf/MvPrintwf
(goprintffuncname), myExit()/findFloor(monst)/mkGameInput(t) drop
always-constant params (unparam), gameEnd carries no status
- gocritic/staticcheck: if-else chains to switches, the pack.c
inventory filter untangled into matchesFilter, main.go split so
defers run before exit (exitAfterDefer, funlen)
- revive doc comments on all exported flag types/consts/methods
Remaining findings are confined to linters pending sneak's exception
decision (mnd, gochecknoglobals, cyclop, nestif, gocognit, exhaustive,
goconst, testpackage); TODO.md records the state. MEMORY.md added at
repo root as the project's agent working notes.
Object.Arm carried four meanings in C (o_arm/o_charges/o_goldval plus
ring bonuses); it is now four fields: ArmorClass, Charges, GoldValue,
and Bonus. Stats.Arm becomes Stats.ArmorClass. The Charges()/GoldVal()
accessor pair is gone.
Damage dice strings ("1x4/1x2") are parsed once into DiceSpec — at
table definition for the bestiary and weapon tables, at creation for
items — instead of re-parsed with atoi on every swing as fight.c
roll_em did. ParseDice preserves the C parse semantics exactly,
including the junk-tolerant "%%%x0" bestiary placeholder and the
"000x0" flytrap reset (regression-tested in dice_test.go); the
flytrap's growing grip becomes DiceSpec{{VfHit, 1}}.
Save format bumps to 5.4.4-go3 (field renames and retypes would
silently zero under gob's match-by-name decoding).
No behavior change; full suite green.
ObjectKind separates what an item is from how it draws: Object.Type
(a byte that doubled as the map character) becomes Kind ObjectKind,
with Glyph() producing the display character and objectKindForGlyph
converting back at the map boundary. KindWand covers the C 'stick'
category. The magic-missile bolt uses KindGold, matching C's literal
o_type='*' trick, with a comment.
PotionKind, ScrollKind, RingKind, WandKind, WeaponKind, ArmorKind and
TrapKind are now iota enums with Stringer (names come from the base
info tables); Object gains typed accessors (obj.RingKind(), ...) and
Launch is typed WeaponKind. beTrapped returns TrapKind. The
getItem/inventory/whatis prompt filters take ObjectKind, with
KindCallable/KindRingOrStick replacing the C CALLABLE/R_OR_S
sentinels; wizard.c's type_name table is subsumed by
ObjectKind.String(). IsRing/IsWearing/initWeapon/doPot signatures are
typed accordingly.
The save format version becomes 5.4.4-go2: the gob field rename would
otherwise silently zero Kind when reading old saves.
No behavior change; full suite green.
- potions.c completed: quaff with all 14 potion effects, the PACT
standard-fuse table (do_pot), raise_level; the see-invisible fruit-
juice message is computed at quaff time as in C
- scrolls.c in full: read_scroll with all 18 scroll effects including
the magic-mapping map rewrite and identify dispatch, uncurse
- options.c in full: the interactive options screen, get_bool/get_str/
get_inv_t/get_sf editors, ROGUEOPTS parsing (prefix matching, no-
prefixed booleans, ~ expansion), strucpy
- misc.c call_it via the get_str line editor
- turn_see gets a DaemonID (C casts it to a fuse callback for the
monster-detection potion)
Tests: healing/confusion potions with fuse burn-down, enchant armor,
hold monster, slow-monster zap, ROGUEOPTS parsing, and a regression
test documenting the C wake_monster ISGREED/ISHELD quirk the port
keeps faithfully.