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("")
}
}
}
|