diff options
| author | historia <[not public]> | 2026-07-05 22:35:21 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-07-05 22:35:21 -0400 |
| commit | 94823b52168b44894fb5e9c960358ed02ebb122b (patch) | |
| tree | 3060799b89bb7edfa708c72bdd981107d40f4d09 /internal/game/render_map.go | |
| parent | 843fa6db681e494bf46e191655323a40577542b5 (diff) | |
| download | thehouseoficarus-94823b52168b44894fb5e9c960358ed02ebb122b.tar.gz | |
feat: courses gui overhaul, add course tab to map, add hidden exits to give courses structure
Diffstat (limited to 'internal/game/render_map.go')
| -rw-r--r-- | internal/game/render_map.go | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/internal/game/render_map.go b/internal/game/render_map.go index 179277a..1bc9adc 100644 --- a/internal/game/render_map.go +++ b/internal/game/render_map.go @@ -95,7 +95,7 @@ func buildTinyMap(g *Game, sess *net.Session, roomID int, mg mapGlyphs) []string dimSpec := resolveDim(g, sess) ctx := &mapRenderCtx{ g: g, sess: sess, bg: bg, visited: visited, currentRoom: roomID, - atSpec: atSpec, dimSpec: dimSpec, blockedSpec: resolveMapBlocked(g, sess), mg: mg, + atSpec: atSpec, dimSpec: dimSpec, blockedSpec: resolveMapBlocked(g, sess), courseSpec: resolveMapCourse(g, sess), mg: mg, diagPairs: make(map[[2]int][2]int), } @@ -268,7 +268,7 @@ func buildFullMap(g *Game, sess *net.Session, roomID, mapWidth, mapHeight int, m dimSpec := resolveDim(g, sess) ctx := &mapRenderCtx{ g: g, sess: sess, bg: bg, visited: visited, currentRoom: roomID, - atSpec: atSpec, dimSpec: dimSpec, blockedSpec: resolveMapBlocked(g, sess), mg: mg, + atSpec: atSpec, dimSpec: dimSpec, blockedSpec: resolveMapBlocked(g, sess), courseSpec: resolveMapCourse(g, sess), mg: mg, diagPairs: make(map[[2]int][2]int), } @@ -433,6 +433,13 @@ func resolveMapBlocked(g *Game, sess *net.Session) color.ColorSpec { return color.Parse("C4") } +func resolveMapCourse(g *Game, sess *net.Session) color.ColorSpec { + if sess != nil { + return g.resolveColor(sess, "map_course") + } + return color.Parse("1B") +} + // mapRenderCtx bundles the per-render state shared by node and connector drawing // so the tiny and full maps build cells the same way. type mapRenderCtx struct { @@ -444,6 +451,7 @@ type mapRenderCtx struct { atSpec color.ColorSpec dimSpec color.ColorSpec blockedSpec color.ColorSpec + courseSpec color.ColorSpec mg mapGlyphs diagPairs map[[2]int][2]int } @@ -497,14 +505,44 @@ func (c *mapRenderCtx) connectorCell(roomA, roomB int, dirAB, dirBA world.ExitDi switch { case out == exitOpen: + if c.isCourseLink(roomA, roomB) { + return c.courseColoredCell(roomA, roomB, arrowGlyph(c.mg, outDir)) + } return c.coloredCell(roomA, roomB, arrowGlyph(c.mg, outDir)) case out == exitAbsent && in == exitOpen: + if c.isCourseLink(roomA, roomB) { + return c.courseColoredCell(roomA, roomB, arrowGlyph(c.mg, inDir)) + } return c.coloredCell(roomA, roomB, arrowGlyph(c.mg, inDir)) default: return mapCell{char: 'X', spec: c.blockedSpec}, true } } +// isCourseLink reports whether roomA and roomB are consecutive obstacles in +// the same agility course (one's NextRoom equals the other's room id). +func (c *mapRenderCtx) isCourseLink(roomA, roomB int) bool { + if c.g == nil || c.g.CourseStore == nil { + return false + } + if info := c.g.CourseStore.GetObstacle(roomA); info != nil && info.NextRoom == roomB { + return true + } + if info := c.g.CourseStore.GetObstacle(roomB); info != nil && info.NextRoom == roomA { + return true + } + return false +} + +// 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]) { + return mapCell{char: glyph, spec: c.dimSpec}, true + } + return mapCell{char: glyph, spec: c.courseSpec}, true +} + // 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) { @@ -564,6 +602,11 @@ func exitStateTo(g *Game, sess *net.Session, from int, dir world.ExitDir, neighb if !ok || exit.Room != neighbor { return exitAbsent } + // Hidden exits are non-traversable to players but are followed by the map + // layout BFS, so they always render as traversable (open) connectors. + if exit.Hidden { + return exitOpen + } if exit.Condition == nil || sess == nil || sess.Player == nil { return exitOpen } |
