aboutsummaryrefslogtreecommitdiff
path: root/internal/game/render_map.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/render_map.go')
-rw-r--r--internal/game/render_map.go77
1 files changed, 33 insertions, 44 deletions
diff --git a/internal/game/render_map.go b/internal/game/render_map.go
index 049db06..ff9ffa5 100644
--- a/internal/game/render_map.go
+++ b/internal/game/render_map.go
@@ -174,8 +174,8 @@ func buildTinyMap(g *Game, sess *net.Session, roomID int, mg mapGlyphs) []string
if !leftOK || !rightOK {
continue
}
- if exitsConnect(g, leftRoom, rightRoom, world.East, world.West) {
- grid[(y+1)*2][(x+1)*2+1] = ctx.connectorCell(leftRoom, rightRoom, world.East, world.West)
+ if cell, ok := ctx.connectorCell(leftRoom, rightRoom, world.East, world.West); ok {
+ grid[(y+1)*2][(x+1)*2+1] = cell
}
}
}
@@ -189,8 +189,8 @@ func buildTinyMap(g *Game, sess *net.Session, roomID int, mg mapGlyphs) []string
if !topOK || !bottomOK {
continue
}
- if exitsConnect(g, topRoom, bottomRoom, world.South, world.North) {
- grid[(y+1)*2+1][(x+1)*2] = ctx.connectorCell(topRoom, bottomRoom, world.South, world.North)
+ if cell, ok := ctx.connectorCell(topRoom, bottomRoom, world.South, world.North); ok {
+ grid[(y+1)*2+1][(x+1)*2] = cell
}
}
}
@@ -260,22 +260,22 @@ func buildFullMap(g *Game, sess *net.Session, roomID, mapWidth, mapHeight int, m
for pos, rid := range bg.posToRoom {
x, y := pos[0], pos[1]
- if rightID, ok := bg.posToRoom[[2]int{x + 1, y}]; ok {
- if exitsConnect(g, rid, rightID, world.East, world.West) {
- gr := cy + y*2
- gc := cx + x*2 + 1
- if gr >= 0 && gr < mapHeight && gc >= 0 && gc < mapWidth {
- grid[gr][gc] = ctx.connectorCell(rid, rightID, world.East, world.West)
+ if rightID, exists := bg.posToRoom[[2]int{x + 1, y}]; exists {
+ gr := cy + y*2
+ gc := cx + x*2 + 1
+ if gr >= 0 && gr < mapHeight && gc >= 0 && gc < mapWidth {
+ if cell, ok := ctx.connectorCell(rid, rightID, world.East, world.West); ok {
+ grid[gr][gc] = cell
}
}
}
- if bottomID, ok := bg.posToRoom[[2]int{x, y + 1}]; ok {
- if exitsConnect(g, rid, bottomID, world.South, world.North) {
- gr := cy + y*2 + 1
- gc := cx + x*2
- if gr >= 0 && gr < mapHeight && gc >= 0 && gc < mapWidth {
- grid[gr][gc] = ctx.connectorCell(rid, bottomID, world.South, world.North)
+ if bottomID, exists := bg.posToRoom[[2]int{x, y + 1}]; exists {
+ gr := cy + y*2 + 1
+ gc := cx + x*2
+ if gr >= 0 && gr < mapHeight && gc >= 0 && gc < mapWidth {
+ if cell, ok := ctx.connectorCell(rid, bottomID, world.South, world.North); ok {
+ grid[gr][gc] = cell
}
}
}
@@ -302,7 +302,7 @@ func resolveMapAt(g *Game, sess *net.Session) color.ColorSpec {
if sess != nil {
return g.resolveColor(sess, "map_at")
}
- return color.NoColor()
+ return color.Parse("0F")
}
func resolveDim(g *Game, sess *net.Session) color.ColorSpec {
@@ -347,17 +347,23 @@ func (c *mapRenderCtx) nodeSpec(roomID int) color.ColorSpec {
}
// connectorCell builds the link cell between two grid-adjacent rooms based on
-// the per-direction traversability of the two exits joining them:
-// - both directions open -> bidirectional bar (- / |)
-// - exactly one open -> arrow pointing along the open direction
-// - neither open (>=1 blocked) -> blocked 'X'
+// the per-direction traversability of the two exits joining them. ok is false
+// when there is no link at all, so the caller draws nothing:
+// - both directions open -> bidirectional bar (- / |)
+// - exactly one open -> arrow pointing along the open direction
+// - >=1 exists but none open -> blocked 'X'
+// - neither exit exists -> ok == false (no cell)
//
// Bars and arrows use the normal link coloring (dim if an endpoint is unvisited,
// otherwise the gradient average); only 'X' uses the blocked color.
-func (c *mapRenderCtx) connectorCell(roomA, roomB int, dirAB, dirBA world.ExitDir) mapCell {
+func (c *mapRenderCtx) connectorCell(roomA, roomB int, dirAB, dirBA world.ExitDir) (mapCell, bool) {
fwd := exitStateTo(c.g, c.sess, roomA, dirAB, roomB) // A -> B
bwd := exitStateTo(c.g, c.sess, roomB, dirBA, roomA) // B -> A
+ if fwd == exitAbsent && bwd == exitAbsent {
+ return mapCell{}, false
+ }
+
var glyph rune
switch {
case fwd == exitOpen && bwd == exitOpen:
@@ -367,15 +373,14 @@ func (c *mapRenderCtx) connectorCell(roomA, roomB int, dirAB, dirBA world.ExitDi
case bwd == exitOpen:
glyph = arrowGlyph(c.mg, dirBA)
default:
- // The caller only draws a connector when at least one exit exists, so
- // reaching here means every existing direction is blocked.
- return mapCell{char: 'X', spec: c.blockedSpec}
+ // At least one exit exists but none are currently traversable.
+ return mapCell{char: 'X', spec: c.blockedSpec}, true
}
if c.visited != nil && (!c.visited[roomA] || !c.visited[roomB]) {
- return mapCell{char: glyph, spec: c.dimSpec}
+ return mapCell{char: glyph, spec: c.dimSpec}, true
}
- return mapCell{char: glyph, spec: color.Average(c.nodeSpec(roomA), c.nodeSpec(roomB))}
+ return mapCell{char: glyph, spec: color.Average(c.nodeSpec(roomA), c.nodeSpec(roomB))}, true
}
type exitState int
@@ -451,7 +456,7 @@ func roomMapSymbol(g *Game, sess *net.Session, roomID int, unvisited bool) (rune
if data.Color != "" {
spec = color.Parse(data.Color)
}
- // ponytail: non-ASCII custom symbols fall back to 'o'
+ // non-ASCII custom symbols fall back to 'o'
// when unicode mode is off, but preserve the color.
if !sess.Player.OptionBool("unicode") && r > 127 {
return 'o', spec
@@ -470,22 +475,6 @@ func roomMapSymbol(g *Game, sess *net.Session, roomID int, unvisited bool) (rune
return '■', roomSpec
}
-func exitsConnect(g *Game, room1, room2 int, dir12, dir21 world.ExitDir) bool {
- r1, ok := loadRoom(g, room1)
- if !ok {
- return false
- }
- if id, ok := exitTarget(r1, dir12); ok && id == room2 {
- return true
- }
- r2, ok := loadRoom(g, room2)
- if !ok {
- return false
- }
- id, ok := exitTarget(r2, dir21)
- return ok && id == room1
-}
-
func exitTarget(room *world.Room, dir world.ExitDir) (int, bool) {
if room == nil {
return 0, false