Adopt house golangci-lint config; fix all approved-linter findings
.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.
This commit is contained in:
64
game/rip.go
64
game/rip.go
@@ -11,12 +11,14 @@ import (
|
||||
// that Run recovers, so the terminal is restored by normal unwinding.
|
||||
|
||||
// gameEnd is the sentinel carried by the panic that replaces my_exit().
|
||||
type gameEnd struct{ status int }
|
||||
type gameEnd struct{}
|
||||
|
||||
// myExit leaves the process properly (main.c my_exit): it unwinds to Run.
|
||||
func (g *RogueGame) myExit(st int) {
|
||||
// Every C caller exited with status 0; abnormal exits panic for real.
|
||||
func (g *RogueGame) myExit() {
|
||||
g.Playing = false
|
||||
panic(gameEnd{status: st})
|
||||
|
||||
panic(gameEnd{})
|
||||
}
|
||||
|
||||
var ripArt = []string{
|
||||
@@ -39,39 +41,51 @@ var ripArt = []string{
|
||||
func (g *RogueGame) death(monst byte) {
|
||||
p := &g.Player
|
||||
p.Purse -= p.Purse / 10
|
||||
|
||||
g.clear()
|
||||
|
||||
killer := g.killname(monst, false)
|
||||
if !g.Options.Tombstone {
|
||||
g.scr.Std.MvPrintw(NumLines-2, 0, "Killed by ")
|
||||
g.scr.Std.MvPrintwf(NumLines-2, 0, "Killed by ")
|
||||
|
||||
if monst != 's' && monst != 'h' {
|
||||
g.printw("a%s ", vowelstr(killer))
|
||||
}
|
||||
|
||||
g.printw("%s with %d gold", killer, p.Purse)
|
||||
} else {
|
||||
year := time.Now().Year()
|
||||
|
||||
for i, line := range ripArt {
|
||||
g.scr.Std.MvAddStr(8+i, 0, line)
|
||||
}
|
||||
|
||||
g.mvaddstr(17, center(killer), killer)
|
||||
|
||||
if monst == 's' || monst == 'h' {
|
||||
g.mvaddch(16, 32, ' ')
|
||||
} else {
|
||||
g.mvaddstr(16, 33, vowelstr(killer))
|
||||
}
|
||||
|
||||
g.mvaddstr(14, center(g.Whoami), g.Whoami)
|
||||
|
||||
au := fmt.Sprintf("%d Au", p.Purse)
|
||||
g.mvaddstr(15, center(au), au)
|
||||
g.mvaddstr(18, 26, fmt.Sprintf("%4d", year))
|
||||
}
|
||||
|
||||
g.mvaddstr(NumLines-1, 0, "[Press return to continue]")
|
||||
g.refresh()
|
||||
|
||||
flags := 0
|
||||
if g.HasAmulet {
|
||||
flags = 3
|
||||
}
|
||||
|
||||
g.score(p.Purse, flags, monst)
|
||||
g.waitFor('\n')
|
||||
g.myExit(0)
|
||||
g.myExit()
|
||||
}
|
||||
|
||||
// center returns the column to center the given string on the tombstone
|
||||
@@ -85,6 +99,7 @@ func (g *RogueGame) totalWinner() {
|
||||
p := &g.Player
|
||||
g.clear()
|
||||
g.standout()
|
||||
|
||||
banner := []string{
|
||||
" ",
|
||||
" @ @ @ @ @ @@@ @ @ ",
|
||||
@@ -100,6 +115,7 @@ func (g *RogueGame) totalWinner() {
|
||||
for i, line := range banner {
|
||||
g.scr.Std.MvAddStr(i, 0, line)
|
||||
}
|
||||
|
||||
g.standend()
|
||||
g.scr.Std.MvAddStr(10, 0, "You have joined the elite ranks of those who have escaped the")
|
||||
g.scr.Std.MvAddStr(11, 0, "Dungeons of Doom alive. You journey home and sell all your loot at")
|
||||
@@ -110,11 +126,14 @@ func (g *RogueGame) totalWinner() {
|
||||
g.clear()
|
||||
g.mvaddstr(0, 0, " Worth Item")
|
||||
g.move(1, 0)
|
||||
|
||||
oldpurse := p.Purse
|
||||
line := 1
|
||||
|
||||
for _, obj := range p.Pack {
|
||||
worth := 0
|
||||
it := &g.Items
|
||||
|
||||
switch obj.Kind {
|
||||
case KindFood:
|
||||
worth = 2 * obj.Count
|
||||
@@ -129,21 +148,26 @@ func (g *RogueGame) totalWinner() {
|
||||
obj.Flags.Set(Known)
|
||||
case KindScroll:
|
||||
op := &it.Scrolls[obj.Which]
|
||||
|
||||
worth = op.Worth * obj.Count
|
||||
if !op.Know {
|
||||
worth /= 2
|
||||
}
|
||||
|
||||
op.Know = true
|
||||
case KindPotion:
|
||||
op := &it.Potions[obj.Which]
|
||||
|
||||
worth = op.Worth * obj.Count
|
||||
if !op.Know {
|
||||
worth /= 2
|
||||
}
|
||||
|
||||
op.Know = true
|
||||
case KindRing:
|
||||
op := &it.Rings[obj.Which]
|
||||
worth = op.Worth
|
||||
|
||||
if obj.RingKind() == RingAddStrength || obj.RingKind() == RingIncreaseDamage ||
|
||||
obj.RingKind() == RingProtection || obj.RingKind() == RingDexterity {
|
||||
if obj.Bonus > 0 {
|
||||
@@ -152,35 +176,44 @@ func (g *RogueGame) totalWinner() {
|
||||
worth = 10
|
||||
}
|
||||
}
|
||||
|
||||
if !obj.Flags.Has(Known) {
|
||||
worth /= 2
|
||||
}
|
||||
|
||||
obj.Flags.Set(Known)
|
||||
|
||||
op.Know = true
|
||||
case KindWand:
|
||||
op := &it.Sticks[obj.Which]
|
||||
worth = op.Worth
|
||||
|
||||
worth += 20 * obj.Charges
|
||||
if !obj.Flags.Has(Known) {
|
||||
worth /= 2
|
||||
}
|
||||
|
||||
obj.Flags.Set(Known)
|
||||
|
||||
op.Know = true
|
||||
case KindAmulet:
|
||||
worth = 1000
|
||||
}
|
||||
|
||||
if worth < 0 {
|
||||
worth = 0
|
||||
}
|
||||
g.scr.Std.MvPrintw(line, 0, "%c) %5d %s", obj.PackCh, worth,
|
||||
|
||||
g.scr.Std.MvPrintwf(line, 0, "%c) %5d %s", obj.PackCh, worth,
|
||||
g.invName(obj, false))
|
||||
line++
|
||||
p.Purse += worth
|
||||
}
|
||||
g.scr.Std.MvPrintw(line, 0, " %5d Gold Pieces ", oldpurse)
|
||||
|
||||
g.scr.Std.MvPrintwf(line, 0, " %5d Gold Pieces ", oldpurse)
|
||||
g.refresh()
|
||||
g.score(p.Purse, 2, ' ')
|
||||
g.myExit(0)
|
||||
g.myExit()
|
||||
}
|
||||
|
||||
// killnameTable is the rip.c nlist[]: special death causes.
|
||||
@@ -194,25 +227,32 @@ var killnameTable = []helpEntry{
|
||||
|
||||
// killname converts a code to a monster name (rip.c killname).
|
||||
func (g *RogueGame) killname(monst byte, doart bool) string {
|
||||
var sp string
|
||||
var article bool
|
||||
var (
|
||||
sp string
|
||||
article bool
|
||||
)
|
||||
|
||||
if isUpper(monst) {
|
||||
sp = g.Monsters[monst-'A'].Name
|
||||
article = true
|
||||
} else {
|
||||
sp = "Wally the Wonder Badger"
|
||||
article = false
|
||||
|
||||
for _, hp := range killnameTable {
|
||||
if hp.Ch == monst {
|
||||
sp = hp.Desc
|
||||
article = hp.Print
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if doart && article {
|
||||
return "a" + vowelstr(sp) + " " + sp
|
||||
}
|
||||
|
||||
return sp
|
||||
}
|
||||
|
||||
@@ -224,13 +264,16 @@ func (g *RogueGame) DeathDemo() {
|
||||
if _, ok := r.(gameEnd); ok {
|
||||
return
|
||||
}
|
||||
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
|
||||
dnum := g.rnd(100)
|
||||
for dnum--; dnum > 0; dnum-- {
|
||||
g.rnd(100)
|
||||
}
|
||||
|
||||
g.Player.Purse = g.rnd(100) + 1
|
||||
g.Depth = g.rnd(100) + 1
|
||||
g.death(g.deathMonst())
|
||||
@@ -245,5 +288,6 @@ func (g *RogueGame) deathMonst() byte {
|
||||
'Y', 'Z', 'a', 'b', 'h', 'd', 's',
|
||||
' ', // generates the "Wally the Wonder Badger" message
|
||||
}
|
||||
|
||||
return poss[g.rnd(len(poss))]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user