aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_map.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/cmd_map.go')
-rw-r--r--internal/game/cmd_map.go140
1 files changed, 140 insertions, 0 deletions
diff --git a/internal/game/cmd_map.go b/internal/game/cmd_map.go
new file mode 100644
index 0000000..7c506f9
--- /dev/null
+++ b/internal/game/cmd_map.go
@@ -0,0 +1,140 @@
+package game
+
+import (
+ "strings"
+
+ "thirdcollapse/internal/net"
+ "thirdcollapse/internal/player"
+ "thirdcollapse/internal/world"
+)
+
+func (g *Game) doMap(sess *net.Session) {
+ p := sess.Player.(*player.Player)
+ mapWidth := p.OptionInt("mapwidth")
+ mapHeight := p.OptionInt("mapheight")
+ if mapWidth < 5 {
+ mapWidth = 5
+ }
+ if mapHeight < 5 {
+ mapHeight = 5
+ }
+
+ lines := buildFullMap(g, p.RoomID, mapWidth, mapHeight)
+
+ mode := p.OptionString("mappadding")
+ if mode == "none" || mode == "x" {
+ lines = stripBlankRows(lines)
+ }
+ if mode == "none" || mode == "y" {
+ lines = leftTrimCommon(lines)
+ }
+
+ if len(lines) == 0 {
+ sess.WriteLine("\nNo map data to display.")
+ return
+ }
+ sess.WriteLine("")
+ for _, line := range lines {
+ sess.WriteLine(line)
+ }
+}
+
+func stripBlankRows(lines []string) []string {
+ var out []string
+ for _, line := range lines {
+ if strings.TrimSpace(line) != "" {
+ out = append(out, line)
+ }
+ }
+ return out
+}
+
+func leftTrimCommon(lines []string) []string {
+ min := -1
+ for _, line := range lines {
+ if strings.TrimSpace(line) == "" {
+ continue
+ }
+ n := 0
+ for _, r := range line {
+ if r == ' ' {
+ n++
+ } else {
+ break
+ }
+ }
+ if min < 0 || n < min {
+ min = n
+ }
+ }
+ if min <= 0 {
+ return lines
+ }
+ result := make([]string, len(lines))
+ for i, line := range lines {
+ if len(line) <= min {
+ result[i] = ""
+ } else {
+ result[i] = line[min:]
+ }
+ }
+ return result
+}
+
+func buildFullMap(g *Game, roomID, mapWidth, mapHeight int) []string {
+ mg := buildGraph(g, roomID)
+
+ grid := make([][]rune, mapHeight)
+ for i := range grid {
+ grid[i] = make([]rune, mapWidth)
+ for j := range grid[i] {
+ grid[i][j] = ' '
+ }
+ }
+
+ cx := mapWidth / 2
+ cy := mapHeight / 2
+
+ for pos, rid := range mg.posToRoom {
+ gr := cy + pos[1]*2
+ gc := cx + pos[0]*2
+ if gr < 0 || gr >= mapHeight || gc < 0 || gc >= mapWidth {
+ continue
+ }
+ if rid == roomID {
+ grid[gr][gc] = '@'
+ } else {
+ grid[gr][gc] = roomMapSymbol(g, rid)
+ }
+ }
+
+ for pos, rid := range mg.posToRoom {
+ x, y := pos[0], pos[1]
+
+ if rightID, ok := mg.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] = '─'
+ }
+ }
+ }
+
+ if bottomID, ok := mg.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] = '│'
+ }
+ }
+ }
+ }
+
+ lines := make([]string, mapHeight)
+ for i := range grid {
+ lines[i] = string(grid[i])
+ }
+ return lines
+}