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:
123
game/pack.go
123
game/pack.go
@@ -7,10 +7,12 @@ package game
|
||||
func (g *RogueGame) addPack(obj *Object, silent bool) {
|
||||
p := &g.Player
|
||||
fromFloor := false
|
||||
|
||||
if obj == nil {
|
||||
if obj = g.findObj(p.Pos.Y, p.Pos.X); obj == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fromFloor = true
|
||||
}
|
||||
|
||||
@@ -18,12 +20,15 @@ func (g *RogueGame) addPack(obj *Object, silent bool) {
|
||||
if obj.Kind == KindScroll && obj.ScrollKind() == ScrollScareMonster && obj.Flags.Has(WasFound) {
|
||||
detachObj(&g.Level.Objects, obj)
|
||||
g.mvaddch(p.Pos.Y, p.Pos.X, g.floorCh())
|
||||
|
||||
if p.Room.Flags.Has(Gone) {
|
||||
g.Level.SetChar(p.Pos.Y, p.Pos.X, Passage)
|
||||
} else {
|
||||
g.Level.SetChar(p.Pos.Y, p.Pos.X, Floor)
|
||||
}
|
||||
|
||||
g.msg("the scroll turns to dust as you pick it up")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -38,9 +43,11 @@ func (g *RogueGame) addPack(obj *Object, silent bool) {
|
||||
// after; -1 after a merge means no insertion.
|
||||
lp := -1
|
||||
merged := false
|
||||
|
||||
for i := 0; i < len(p.Pack); i++ {
|
||||
if p.Pack[i].Kind != obj.Kind {
|
||||
lp = i
|
||||
|
||||
continue
|
||||
}
|
||||
// found the group of our type: scan for matching subtype
|
||||
@@ -49,19 +56,23 @@ func (g *RogueGame) addPack(obj *Object, silent bool) {
|
||||
if i+1 >= len(p.Pack) {
|
||||
break
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
|
||||
op := p.Pack[i]
|
||||
if op.Kind == obj.Kind && op.Which == obj.Which {
|
||||
if op.Kind.MergesInPack() {
|
||||
switch {
|
||||
case op.Kind.MergesInPack():
|
||||
if !g.packRoom(fromFloor, obj) {
|
||||
return
|
||||
}
|
||||
|
||||
op.Count++
|
||||
obj = op
|
||||
lp = -1
|
||||
merged = true
|
||||
} else if obj.Group != 0 {
|
||||
case obj.Group != 0:
|
||||
lp = i
|
||||
for p.Pack[i].Kind == obj.Kind &&
|
||||
p.Pack[i].Which == obj.Which &&
|
||||
@@ -70,24 +81,29 @@ func (g *RogueGame) addPack(obj *Object, silent bool) {
|
||||
if i+1 >= len(p.Pack) {
|
||||
break
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
|
||||
op = p.Pack[i]
|
||||
if op.Kind == obj.Kind && op.Which == obj.Which &&
|
||||
op.Group == obj.Group {
|
||||
op.Count += obj.Count
|
||||
p.Inpack--
|
||||
|
||||
if !g.packRoom(fromFloor, obj) {
|
||||
return
|
||||
}
|
||||
|
||||
obj = op
|
||||
lp = -1
|
||||
merged = true
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
lp = i
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
@@ -95,6 +111,7 @@ func (g *RogueGame) addPack(obj *Object, silent bool) {
|
||||
if !g.packRoom(fromFloor, obj) {
|
||||
return
|
||||
}
|
||||
|
||||
obj.PackCh = g.packChar()
|
||||
p.Pack = append(p.Pack[:lp+1],
|
||||
append([]*Object{obj}, p.Pack[lp+1:]...)...)
|
||||
@@ -117,8 +134,9 @@ func (g *RogueGame) addPack(obj *Object, silent bool) {
|
||||
// Notify the user
|
||||
if !silent {
|
||||
if !g.Options.Terse {
|
||||
g.addmsg("you now have ")
|
||||
g.addmsgf("you now have ")
|
||||
}
|
||||
|
||||
g.msg("%s (%c)", g.invName(obj, !g.Options.Terse), obj.PackCh)
|
||||
}
|
||||
}
|
||||
@@ -129,29 +147,37 @@ func (g *RogueGame) packRoom(fromFloor bool, obj *Object) bool {
|
||||
p := &g.Player
|
||||
if p.Inpack++; p.Inpack > MaxPack {
|
||||
if !g.Options.Terse {
|
||||
g.addmsg("there's ")
|
||||
g.addmsgf("there's ")
|
||||
}
|
||||
g.addmsg("no room")
|
||||
|
||||
g.addmsgf("no room")
|
||||
|
||||
if !g.Options.Terse {
|
||||
g.addmsg(" in your pack")
|
||||
g.addmsgf(" in your pack")
|
||||
}
|
||||
|
||||
g.endmsg()
|
||||
|
||||
if fromFloor {
|
||||
g.moveMsg(obj)
|
||||
}
|
||||
|
||||
p.Inpack = MaxPack
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if fromFloor {
|
||||
detachObj(&g.Level.Objects, obj)
|
||||
g.mvaddch(p.Pos.Y, p.Pos.X, g.floorCh())
|
||||
|
||||
if p.Room.Flags.Has(Gone) {
|
||||
g.Level.SetChar(p.Pos.Y, p.Pos.X, Passage)
|
||||
} else {
|
||||
g.Level.SetChar(p.Pos.Y, p.Pos.X, Floor)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -159,13 +185,16 @@ func (g *RogueGame) packRoom(fromFloor bool, obj *Object) bool {
|
||||
func (g *RogueGame) leavePack(obj *Object, newobj, all bool) *Object {
|
||||
p := &g.Player
|
||||
p.Inpack--
|
||||
|
||||
nobj := obj
|
||||
if obj.Count > 1 && !all {
|
||||
g.LastPick = obj
|
||||
|
||||
obj.Count--
|
||||
if obj.Group != 0 {
|
||||
p.Inpack++
|
||||
}
|
||||
|
||||
if newobj {
|
||||
copied := *obj
|
||||
nobj = &copied
|
||||
@@ -176,6 +205,7 @@ func (g *RogueGame) leavePack(obj *Object, newobj, all bool) *Object {
|
||||
p.PackUsed[obj.PackCh-'a'] = false
|
||||
detachObj(&p.Pack, obj)
|
||||
}
|
||||
|
||||
return nobj
|
||||
}
|
||||
|
||||
@@ -185,9 +215,11 @@ func (g *RogueGame) packChar() byte {
|
||||
for i := range p.PackUsed {
|
||||
if !p.PackUsed[i] {
|
||||
p.PackUsed[i] = true
|
||||
|
||||
return byte(i) + 'a'
|
||||
}
|
||||
}
|
||||
|
||||
return byte(len(p.PackUsed)) + 'a' // C would walk off the array here
|
||||
}
|
||||
|
||||
@@ -195,24 +227,26 @@ func (g *RogueGame) packChar() byte {
|
||||
// of the given type (pack.c inventory).
|
||||
func (g *RogueGame) inventory(list []*Object, kind ObjectKind) bool {
|
||||
g.NObjs = 0
|
||||
|
||||
for _, item := range list {
|
||||
if kind != KindNone && kind != item.Kind &&
|
||||
!(kind == KindCallable && item.Kind != KindFood &&
|
||||
item.Kind != KindAmulet) &&
|
||||
!(kind == KindRingOrStick &&
|
||||
(item.Kind == KindRing || item.Kind == KindWand)) {
|
||||
if !matchesFilter(kind, item) {
|
||||
continue
|
||||
}
|
||||
|
||||
g.NObjs++
|
||||
g.Msgs.MsgEsc = true
|
||||
|
||||
line := string(item.PackCh) + ") " + g.invName(item, false)
|
||||
if g.addLine("%s", line) == Escape {
|
||||
g.Msgs.MsgEsc = false
|
||||
g.msg("")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
g.Msgs.MsgEsc = false
|
||||
}
|
||||
|
||||
if g.NObjs == 0 {
|
||||
if g.Options.Terse {
|
||||
if kind == KindNone {
|
||||
@@ -227,9 +261,12 @@ func (g *RogueGame) inventory(list []*Object, kind ObjectKind) bool {
|
||||
g.msg("you don't have anything appropriate")
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
g.endLine()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -243,27 +280,49 @@ func (g *RogueGame) pickUp(ch byte) {
|
||||
obj := g.findObj(p.Pos.Y, p.Pos.X)
|
||||
if g.MoveOn {
|
||||
g.moveMsg(obj)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
switch ch {
|
||||
case Gold:
|
||||
if obj == nil {
|
||||
return
|
||||
}
|
||||
|
||||
g.money(obj.GoldValue)
|
||||
detachObj(&g.Level.Objects, obj)
|
||||
|
||||
p.Room.GoldVal = 0
|
||||
default:
|
||||
g.addPack(nil, false)
|
||||
}
|
||||
}
|
||||
|
||||
// matchesFilter reports whether an item passes a get_item/inventory kind
|
||||
// filter (the C condition in pack.c inventory, untangled): KindNone takes
|
||||
// everything, KindCallable takes anything nameable (not food, not the
|
||||
// amulet), KindRingOrStick takes rings and wands.
|
||||
func matchesFilter(kind ObjectKind, item *Object) bool {
|
||||
switch kind {
|
||||
case KindNone:
|
||||
return true
|
||||
case KindCallable:
|
||||
return item.Kind != KindFood && item.Kind != KindAmulet
|
||||
case KindRingOrStick:
|
||||
return item.Kind == KindRing || item.Kind == KindWand
|
||||
default:
|
||||
return item.Kind == kind
|
||||
}
|
||||
}
|
||||
|
||||
// moveMsg prints the message if you are just moving onto an object
|
||||
// (pack.c move_msg).
|
||||
func (g *RogueGame) moveMsg(obj *Object) {
|
||||
if !g.Options.Terse {
|
||||
g.addmsg("you ")
|
||||
g.addmsgf("you ")
|
||||
}
|
||||
|
||||
g.msg("moved onto %s", g.invName(obj, true))
|
||||
}
|
||||
|
||||
@@ -273,25 +332,34 @@ func (g *RogueGame) pickyInven() {
|
||||
p := &g.Player
|
||||
if len(p.Pack) == 0 {
|
||||
g.msg("you aren't carrying anything")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if len(p.Pack) == 1 {
|
||||
g.msg("a) %s", g.invName(p.Pack[0], false))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
g.msg("%s", g.chooseTerse("item: ", "which item do you wish to inventory: "))
|
||||
g.Msgs.Mpos = 0
|
||||
|
||||
mch := g.readchar()
|
||||
if mch == Escape {
|
||||
g.msg("")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for _, obj := range p.Pack {
|
||||
if mch == obj.PackCh {
|
||||
g.msg("%c) %s", mch, g.invName(obj, false))
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
g.msg("'%s' not in pack", unctrl(mch))
|
||||
}
|
||||
|
||||
@@ -300,23 +368,31 @@ func (g *RogueGame) getItem(purpose string, kind ObjectKind) *Object {
|
||||
p := &g.Player
|
||||
if len(p.Pack) == 0 {
|
||||
g.msg("you aren't carrying anything")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if g.Again {
|
||||
if g.LastPick != nil {
|
||||
return g.LastPick
|
||||
}
|
||||
|
||||
g.msg("you ran out")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
for {
|
||||
if !g.Options.Terse {
|
||||
g.addmsg("which object do you want to ")
|
||||
g.addmsgf("which object do you want to ")
|
||||
}
|
||||
g.addmsg("%s", purpose)
|
||||
|
||||
g.addmsgf("%s", purpose)
|
||||
|
||||
if g.Options.Terse {
|
||||
g.addmsg(" what")
|
||||
g.addmsgf(" what")
|
||||
}
|
||||
|
||||
g.msg("? (* for list): ")
|
||||
ch := g.readchar()
|
||||
g.Msgs.Mpos = 0
|
||||
@@ -325,22 +401,28 @@ func (g *RogueGame) getItem(purpose string, kind ObjectKind) *Object {
|
||||
g.resetLast()
|
||||
g.After = false
|
||||
g.msg("")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
g.NObjs = 1 // normal case: person types one char
|
||||
if ch == '*' {
|
||||
g.Msgs.Mpos = 0
|
||||
if !g.inventory(p.Pack, kind) {
|
||||
g.After = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
for _, obj := range p.Pack {
|
||||
if obj.PackCh == ch {
|
||||
return obj
|
||||
}
|
||||
}
|
||||
|
||||
g.msg("'%s' is not a valid item", unctrl(ch))
|
||||
}
|
||||
}
|
||||
@@ -350,15 +432,18 @@ func (g *RogueGame) money(value int) {
|
||||
p := &g.Player
|
||||
p.Purse += value
|
||||
g.mvaddch(p.Pos.Y, p.Pos.X, g.floorCh())
|
||||
|
||||
if p.Room.Flags.Has(Gone) {
|
||||
g.Level.SetChar(p.Pos.Y, p.Pos.X, Passage)
|
||||
} else {
|
||||
g.Level.SetChar(p.Pos.Y, p.Pos.X, Floor)
|
||||
}
|
||||
|
||||
if value > 0 {
|
||||
if !g.Options.Terse {
|
||||
g.addmsg("you found ")
|
||||
g.addmsgf("you found ")
|
||||
}
|
||||
|
||||
g.msg("%d gold pieces", value)
|
||||
}
|
||||
}
|
||||
@@ -369,9 +454,11 @@ func (g *RogueGame) floorCh() byte {
|
||||
if g.Player.Room.Flags.Has(Gone) {
|
||||
return Passage
|
||||
}
|
||||
|
||||
if g.showFloor() {
|
||||
return Floor
|
||||
}
|
||||
|
||||
return ' '
|
||||
}
|
||||
|
||||
@@ -382,6 +469,7 @@ func (g *RogueGame) floorAt() byte {
|
||||
if ch == Floor {
|
||||
ch = g.floorCh()
|
||||
}
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
@@ -398,5 +486,6 @@ func (g *RogueGame) chooseTerse(terse, verbose string) string {
|
||||
if g.Options.Terse {
|
||||
return terse
|
||||
}
|
||||
|
||||
return verbose
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user