diff options
| author | historia <[not public]> | 2026-07-07 16:46:32 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-07-07 16:46:32 -0400 |
| commit | 726997d799edc388cd448e978d5bb0755aaa551c (patch) | |
| tree | b7aa8dc2dc9d2edcad1c0a4012a28d01d348db69 /internal/game | |
| parent | ab2597b22ccdb71116992aec78080d9858358d04 (diff) | |
| download | thehouseoficarus-726997d799edc388cd448e978d5bb0755aaa551c.tar.gz | |
feat: bitpacked and base64 encoded VisitedRooms in player YAML to keep the file human readable
Diffstat (limited to 'internal/game')
| -rw-r--r-- | internal/game/cmd_score.go | 2 | ||||
| -rw-r--r-- | internal/game/exit_migrate.go | 6 | ||||
| -rw-r--r-- | internal/game/exit_migrate_test.go | 8 | ||||
| -rw-r--r-- | internal/game/map_test.go | 4 | ||||
| -rw-r--r-- | internal/game/render_map.go | 16 |
5 files changed, 19 insertions, 17 deletions
diff --git a/internal/game/cmd_score.go b/internal/game/cmd_score.go index b493e80..59cedb1 100644 --- a/internal/game/cmd_score.go +++ b/internal/game/cmd_score.go @@ -174,7 +174,7 @@ func (g *Game) doScore(sess *net.Session) { sep() stats := p.Stats statsLine := fmt.Sprintf("Rooms Explored: %d Kills: %d Deaths: %d", - len(stats.RoomsVisited), stats.TotalKills, stats.Deaths) + stats.RoomsVisited.Len(), stats.TotalKills, stats.Deaths) content(statsLine) content(fmt.Sprintf("APS Nodes Found: %d", len(getKnownApsNodes(p)))) diff --git a/internal/game/exit_migrate.go b/internal/game/exit_migrate.go index 845a6b2..2872f34 100644 --- a/internal/game/exit_migrate.go +++ b/internal/game/exit_migrate.go @@ -10,7 +10,7 @@ import ( // rewritePlayerRoomIDs remaps room-ID-embedded state in a single player per // idMap (oldID -> newID): discovered-exit player flag keys // (hidden_exit_<id>_<dir>), current RoomID, EnterSeqRoom, MapSymbols keys, and -// Stats.RoomsVisited keys. Returns whether any field was changed. +// Stats.RoomsVisited bitset. Returns whether any field was changed. // // idMap is assumed to be a bijection (see Room.RewriteRoomIDs); the flag-key // and int-map rekeys use delete-all-then-set-all so a swap (A<->B) cannot @@ -32,7 +32,9 @@ func rewritePlayerRoomIDs(p *player.Player, idMap map[int]int) bool { if len(p.MapSymbols) > 0 && rekeyIntMap(p.MapSymbols, idMap) { changed = true } - if len(p.Stats.RoomsVisited) > 0 && rekeyIntMap(p.Stats.RoomsVisited, idMap) { + next, moved := p.Stats.RoomsVisited.Rekey(idMap) + if moved { + p.Stats.RoomsVisited = next changed = true } return changed diff --git a/internal/game/exit_migrate_test.go b/internal/game/exit_migrate_test.go index 05edea5..f86b85b 100644 --- a/internal/game/exit_migrate_test.go +++ b/internal/game/exit_migrate_test.go @@ -21,7 +21,7 @@ func TestRewritePlayerRoomIDsRename(t *testing.T) { 30: {Char: "Y"}, }, } - p.Stats.RoomsVisited = map[int]bool{10: true, 40: true} + p.Stats.RoomsVisited = player.NewRoomSetFrom(10, 40) idMap := map[int]int{10: 100, 20: 200} if !rewritePlayerRoomIDs(p, idMap) { @@ -53,13 +53,13 @@ func TestRewritePlayerRoomIDsRename(t *testing.T) { if _, ok := p.MapSymbols[10]; ok { t.Error("MapSymbols should not still have key 10") } - if !p.Stats.RoomsVisited[100] { + if !p.Stats.RoomsVisited.Has(100) { t.Error("RoomsVisited missing key 100") } - if !p.Stats.RoomsVisited[40] { + if !p.Stats.RoomsVisited.Has(40) { t.Error("RoomsVisited missing unchanged key 40") } - if p.Stats.RoomsVisited[10] { + if p.Stats.RoomsVisited.Has(10) { t.Error("RoomsVisited should not still have key 10") } } diff --git a/internal/game/map_test.go b/internal/game/map_test.go index 2fe9c1e..2975551 100644 --- a/internal/game/map_test.go +++ b/internal/game/map_test.go @@ -406,7 +406,7 @@ func TestMap3DDisconnectedComponent(t *testing.T) { // Player has only visited tower 1. Tower 2 should appear but dimmed (unvisited). sess := &net.Session{Player: &player.Player{ - Stats: player.PlayerStats{RoomsVisited: map[int]bool{1: true}}, + Stats: player.PlayerStats{RoomsVisited: player.NewRoomSetFrom(1)}, Flags: map[string]any{}, }} @@ -429,7 +429,7 @@ func TestMap3DDifferentZExcluded(t *testing.T) { g := &Game{Deps: Deps{World: world.New(dir)}, GlobalFlags: NewGlobalFlagStore()} mg := mapGlyphsForPlayer(false) sess := &net.Session{Player: &player.Player{ - Stats: player.PlayerStats{RoomsVisited: map[int]bool{1: true, 2: true}}, + Stats: player.PlayerStats{RoomsVisited: player.NewRoomSetFrom(1, 2)}, Flags: map[string]any{}, }} diff --git a/internal/game/render_map.go b/internal/game/render_map.go index 0177595..3f9c4da 100644 --- a/internal/game/render_map.go +++ b/internal/game/render_map.go @@ -131,7 +131,7 @@ func buildTinyMap(g *Game, sess *net.Session, roomID int, mg mapGlyphs) []string if rid == roomID { grid[gr][gc] = mapCell{char: '@', spec: atSpec} } else { - unvisited := visited != nil && !visited[rid] + unvisited := visited != nil && !visited.Has(rid) ch, spec := roomMapSymbol(g, sess, rid, unvisited) if unvisited { spec = dimSpec @@ -307,7 +307,7 @@ func buildFullMap(g *Game, sess *net.Session, roomID, mapWidth, mapHeight int, m if rid == roomID { grid[gr][gc] = mapCell{char: '@', spec: atSpec} } else { - unvisited := visited != nil && !visited[rid] + unvisited := visited != nil && !visited.Has(rid) ch, spec := roomMapSymbol(g, sess, rid, unvisited) if unvisited { spec = dimSpec @@ -409,9 +409,9 @@ func buildFullMap(g *Game, sess *net.Session, roomID, mapWidth, mapHeight int, m return renderMapCells(grid, colorMode, 0, mapHeight, 0) } -func roomsVisited(sess *net.Session) map[int]bool { +func roomsVisited(sess *net.Session) *player.RoomSet { if sess != nil && sess.Player != nil { - return sess.Player.Stats.RoomsVisited + return &sess.Player.Stats.RoomsVisited } return nil } @@ -457,7 +457,7 @@ type mapRenderCtx struct { g *Game sess *net.Session bg *mapGraph - visited map[int]bool + visited *player.RoomSet currentRoom int atSpec color.ColorSpec dimSpec color.ColorSpec @@ -473,7 +473,7 @@ func (c *mapRenderCtx) nodeSpec(roomID int) color.ColorSpec { if roomID == c.currentRoom { return c.atSpec } - if c.visited != nil && !c.visited[roomID] { + if c.visited != nil && !c.visited.Has(roomID) { return c.dimSpec } _, spec := roomMapSymbol(c.g, c.sess, roomID, false) @@ -548,7 +548,7 @@ func (c *mapRenderCtx) isCourseLink(roomA, roomB int) bool { // courseColoredCell draws a one-way course arrow using the map_course color // (dimmed if either endpoint is unvisited). func (c *mapRenderCtx) courseColoredCell(roomA, roomB int, glyph rune) (mapCell, bool) { - if c.visited != nil && (!c.visited[roomA] || !c.visited[roomB]) { + if c.visited != nil && (!c.visited.Has(roomA) || !c.visited.Has(roomB)) { return mapCell{char: glyph, spec: c.dimSpec}, true } return mapCell{char: glyph, spec: c.courseSpec}, true @@ -557,7 +557,7 @@ func (c *mapRenderCtx) courseColoredCell(roomA, roomB int, glyph rune) (mapCell, // coloredCell applies the shared link coloring logic for bar/arrow glyphs // (dim if either endpoint is unvisited, otherwise the gradient average). func (c *mapRenderCtx) coloredCell(roomA, roomB int, glyph rune) (mapCell, bool) { - if c.visited != nil && (!c.visited[roomA] || !c.visited[roomB]) { + if c.visited != nil && (!c.visited.Has(roomA) || !c.visited.Has(roomB)) { return mapCell{char: glyph, spec: c.dimSpec}, true } return mapCell{char: glyph, spec: color.Average(c.nodeSpec(roomA), c.nodeSpec(roomB))}, true |
