.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.
47 lines
1.2 KiB
Go
47 lines
1.2 KiB
Go
package game
|
|
|
|
import "testing"
|
|
|
|
// ParseDice must keep the exact semantics of the C roll_em parse loop,
|
|
// including its junk-tolerant edges: the bestiary placeholder "%%%x0" and
|
|
// the flytrap reset "000x0" both mean a single 0x0 attack.
|
|
func TestParseDice(t *testing.T) {
|
|
cases := []struct {
|
|
in string
|
|
want string
|
|
len int
|
|
}{
|
|
{"1x4", "1x4", 1},
|
|
{"1x2/1x5/1x5", "1x2/1x5/1x5", 3},
|
|
{"2x12/2x4", "2x12/2x4", 2},
|
|
{"0x0", "0x0", 1},
|
|
{"000x0", "0x0", 1},
|
|
{"%%%x0", "0x0", 1},
|
|
{"", "", 0},
|
|
{"3", "", 0}, // no 'x': C parses nothing
|
|
}
|
|
for _, c := range cases {
|
|
got := ParseDice(c.in)
|
|
if len(got) != c.len || got.String() != c.want {
|
|
t.Errorf("ParseDice(%q) = %v (len %d), want %q (len %d)",
|
|
c.in, got, len(got), c.want, c.len)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The bestiary and weapon tables must parse to at least one attack each so
|
|
// every creature and weapon actually swings.
|
|
func TestTablesHaveDice(t *testing.T) {
|
|
for i, m := range monsterTable {
|
|
if len(m.Stats.Dmg) == 0 {
|
|
t.Errorf("monster %c (%s) has no attacks", 'A'+i, m.Name)
|
|
}
|
|
}
|
|
|
|
for w, iw := range initWeaps {
|
|
if len(iw.dam) == 0 || len(iw.hrl) == 0 {
|
|
t.Errorf("weapon %v has empty dice", WeaponKind(w))
|
|
}
|
|
}
|
|
}
|