aboutsummaryrefslogtreecommitdiff
path: root/internal/game/look_room.go
blob: 585efb04ee65af675628f3e1f2ff5780e3699968 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package game

import (
	"fmt"

	"thehouseoficarus/internal/color"
	"thehouseoficarus/internal/net"
	"thehouseoficarus/internal/object"
	"thehouseoficarus/internal/player"
	"thehouseoficarus/internal/world"
)

func (g *Game) showRoomName(sess *net.Session, p *player.Player, room *world.Room) {
	title := fmt.Sprintf("%s (%s)", g.colorize(sess, "room_name", room.Name), g.colorize(sess, "room_number", fmt.Sprintf("#%d", room.ID)))
	if bracket := g.roomSymbolBracket(sess, p, room); bracket != "" {
		title += " " + bracket
	}
	sess.WriteLines("", title)
}

// roomSymbolBracket renders a dim-bracketed colored symbol (e.g. "[D]") when the
// player has set a custom symbol for this room, else "".
func (g *Game) roomSymbolBracket(sess *net.Session, p *player.Player, room *world.Room) string {
	if p == nil {
		return ""
	}
	if _, ok := p.MapSymbols[room.ID]; !ok {
		return ""
	}
	ch, spec := roomMapSymbol(g, sess, room.ID, false)
	mode := g.colorMode(sess)
	dimSpec := g.resolveColor(sess, "dim")
	return color.Render(mode, dimSpec, "[") +
		color.Render(mode, spec, string(ch)) +
		color.Render(mode, dimSpec, "]")
}

func (g *Game) showRoomDescription(sess *net.Session, p *player.Player, room *world.Room) []string {
	descWidth := p.OptionInt("room_desc_width")
	if descWidth <= 0 {
		descWidth = 70
	}
	rawLines := wrapText(g.roomDescription(sess, room), descWidth)
	mode := g.colorMode(sess)
	roomDescSpec := g.resolveColor(sess, "room_desc")
	lines := make([]string, len(rawLines))
	for i, l := range rawLines {
		lines[i] = color.ExpandTagsDefault(mode, roomDescSpec, l)
	}
	return lines
}

// roomDescription resolves the room's effective description for this player,
// picking the first conditional variant whose condition passes.
func (g *Game) roomDescription(sess *net.Session, room *world.Room) string {
	for _, d := range room.Description {
		if d.Condition == nil || g.checkCondition(sess, d.Condition) {
			return d.Text
		}
	}
	return ""
}

// resolveObjDesc resolves the description an object shows to this player.
// The first variant whose condition passes wins; if none pass the object is
// reported as not present (false), so look falls through as if it were not there.
func (g *Game) resolveObjDesc(sess *net.Session, def *object.ObjectDef) (string, bool) {
	for _, d := range def.Description {
		if d.Condition == nil || g.checkCondition(sess, d.Condition) {
			return d.Text, true
		}
	}
	return "", false
}

func (g *Game) showRoomExits(sess *net.Session, p *player.Player, room *world.Room) {
	if len(room.Exits) > 0 {
		sess.WriteLine("")
		if p.OptionBool("exits") {
			sess.WriteLine("Exits:")
			type exitLine struct {
				dir        string
				targetName string
			}
			var lines []exitLine
			maxDirLen := 0
			for _, dir := range world.ExitOrder {
				exitDef, ok := room.Exits[dir]
				if !ok {
					continue
				}
				coloredDir := g.colorize(sess, "exit_direction", string(dir))
				targetRoom, err := g.World.LoadRoom(exitDef.Room)
				targetName := g.colorize(sess, "room_number", fmt.Sprintf("#%d", exitDef.Room))
				if err == nil {
					targetName = g.colorize(sess, "exit_name", targetRoom.Name)
				}
				if exitDef.Condition != nil && !g.checkCondition(sess, exitDef.Condition) {
					targetName += " (blocked)"
				}
				lines = append(lines, exitLine{coloredDir, targetName})
				if visibleLen(coloredDir) > maxDirLen {
					maxDirLen = visibleLen(coloredDir)
				}
			}
			for _, l := range lines {
				pad := maxDirLen + (len(l.dir) - visibleLen(l.dir))
				sess.WriteLine(fmt.Sprintf("  %-*s - %s", pad, l.dir, l.targetName))
			}
		} else {
			sess.Write("Exits: ")
			first := true
			for _, dir := range world.ExitOrder {
				if _, ok := room.Exits[dir]; ok {
					if !first {
						sess.Write(", ")
					}
					sess.Write(g.colorize(sess, "exit_direction", string(dir)))
					first = false
				}
			}
			sess.WriteLine("")
		}
	}
}