Files
rgoue/game/level.go
sneak 63d1e797e2 chore(lint): adopt canonical golangci-lint config
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.
2026-08-07 20:45:02 +00:00

82 lines
2.8 KiB
Go

//nolint:mnd // C-faithful literals; names hurt C-greppability (approved 2026-07-07)
package game
// Place describes a spot on the level map (rogue.h PLACE).
type Place struct {
Ch byte // the base map character
Flags PlaceFlags
Monst *Monster
}
// Level is the current dungeon level: the map and everything on it. It is
// reset in place by NewLevel, matching the C reuse of the global arrays.
type Level struct {
Places [MaxLines * MaxCols]Place
Rooms [MaxRooms]Room
Passages [MaxPass]Room // one pseudo-room per passage network
Objects []*Object // lvl_obj: objects on this level
Monsters []*Monster // mlist: monsters on the level
Stairs Coord // location of the staircase
TrapCount int // number of traps on this level
}
// At returns the map cell at (y, x); the C INDEX(y,x) macro, including its
// column-major (x<<5)+y layout.
func (l *Level) At(y, x int) *Place {
return &l.Places[(x<<5)+y]
}
// Char is the chat(y,x) macro: the base map character at a spot.
func (l *Level) Char(y, x int) byte { return l.At(y, x).Ch }
// SetChar updates the base map character at a spot.
func (l *Level) SetChar(y, x int, ch byte) { l.At(y, x).Ch = ch }
// FlagsAt is the flat(y,x) macro, returned as a pointer so ported
// read-modify-write sites keep their shape.
func (l *Level) FlagsAt(y, x int) *PlaceFlags { return &l.At(y, x).Flags }
// MonsterAt is the moat(y,x) macro: the monster standing at a spot, if any.
func (l *Level) MonsterAt(y, x int) *Monster { return l.At(y, x).Monst }
// SetMonsterAt places (or clears, with nil) the monster at a spot.
func (l *Level) SetMonsterAt(y, x int, m *Monster) { l.At(y, x).Monst = m }
// VisibleChar is the winat(y,x) macro: what is apparently at a spot — a
// monster's disguise if one stands there, else the map character.
func (l *Level) VisibleChar(y, x int) byte {
if m := l.MonsterAt(y, x); m != nil {
return m.Disguise
}
return l.Char(y, x)
}
// ObjectAt finds the unclaimed object at (y, x) (misc.c find_obj).
func (l *Level) ObjectAt(y, x int) *Object {
for _, obj := range l.Objects {
if obj.Pos.Y == y && obj.Pos.X == x {
return obj
}
}
return nil
}
// AddObject puts an object on the level (list.c attach on lvl_obj).
func (l *Level) AddObject(obj *Object) { attachObj(&l.Objects, obj) }
// RemoveObject takes an object off the level (list.c detach on lvl_obj).
func (l *Level) RemoveObject(obj *Object) { detachObj(&l.Objects, obj) }
// AddMonster puts a monster on the level (list.c attach on mlist).
func (l *Level) AddMonster(m *Monster) { attachMon(&l.Monsters, m) }
// RemoveMonster takes a monster off the level (list.c detach on mlist).
func (l *Level) RemoveMonster(m *Monster) { detachMon(&l.Monsters, m) }
// goldCalc is the GOLDCALC macro: how much a gold pile is worth at depth.
func (g *RogueGame) goldCalc() int {
return g.rnd(50+10*g.Depth) + 2
}