summaryrefslogtreecommitdiff
path: root/tests/examplefiles/ms/example.ms
blob: 140a0563c1fa9fa23f3138dc3093f604ace31e9d (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
// MiniScript (https://miniscript.org) example file,
// adapted from: http://rosettacode.org/wiki/RCRPG/MiniScript

pos = [0,0,0]
goal = [floor(rnd*10), floor(rnd*10), floor(3+rnd*5)]
 
dir = {}			// key: direction name; value: [dx, dy, dz]
dirAbbrevs = {}		// key: direction abbrevation; value: full name
dir.up = [0,0,1]
dir.down = [0,0,-1]
dir.north = [0,1,0]
dir.south = [0,-1,0]
dir.east = [1,0,0]
dir.west = [-1,0,0]
for k in dir.indexes
	dirAbbrevs[k[0]] = k
end for
inverseDir = {"up":"down", "down":"up", "east":"west", "west":"east", "north":"south", "south":"north"}
 
descNum = function(count, noun)
	if count == 1 then return "a " + noun
	return str(count) + " " + noun + "s"
end function
 
descList = function(lst)
	if lst.len == 0 then return ""
	if lst.len == 1 then return lst[0]
	if lst.len == 2 then return lst[0] + " and " + lst[1]
	return lst[:-1].join(", ") + ", and " + lst[-1]
end function
 
pickAny = function(options)
	lst = options.split(";")
	return lst[rnd * lst.len]
end function
 
Contents = {}
Contents.ladders = 0
Contents.gold = 0
Contents.hammers = 0  // (note: a "sledge" is a sled or sleigh, not a sledgehammer) 
Contents.desc = function(prefix, postfix=".")
	s = []
	if self.ladders > 0 then s.push descNum(self.ladders, "ladder")
	if self.hammers > 0 then s.push descNum(self.hammers, "sledgehammer")
	if self.gold > 0 then s.push descNum(self.gold, "gold coin")
	if not s then return prefix + " nothing" + postfix
	return prefix + " " + descList(s) + postfix
end function
Contents.initRandom = function()
	self.ladders = (rnd < 0.3)
	self.gold = ceil(rnd * 3) * (rnd < 0.1)
	self.hammers = (rnd < 0.02)
end function
Contents.propName = function(obj)
	if obj == "ladder" or obj == "ladders" then return "ladders"
	if obj == "gold" or obj == "coin" or obj == "coins" then return "gold"
	if obj[:6] == "hammer" or obj[:6] == "sledge" then return "hammers"
	return ""
end function
Contents.hasAny = function(obj)
	pname = Contents.propName(obj)
	if pname == "" then return false
	return self[pname] > 0
end function
Contents.withdraw = function(obj)
	result = new Contents
	if obj == "all" then
		result.ladders = self.ladders
		self.ladders = 0
		result.hammers = self.hammers
		self.hammers = 0
		result.gold = self.gold
		self.gold = 0
	else
		pname = Contents.propName(obj)
		if self[pname] < 1 then return null
		if obj[-1] == "s" then count = self[pname] else count = 1
		self[pname] = self[pname] - count
		result[pname] = count
	end if
	return result
end function
Contents.deposit = function(c)
	self.ladders = self.ladders + c.ladders
	self.hammers = self.hammers + c.hammers
	self.gold = self.gold + c.gold
end function
 
inventory = new Contents
inventory.hammers = 1
 
Room = {}
Room.exits = {}
Room.color = ""
Room.init = function(pos)
	self.contents = new Contents
	self.contents.initRandom
	if pos == goal then
		self.color = "YOU FOUND IT!  This is the mystical Room of MacGuffin!"
	else if rnd < 0.5 then
		// Give a hint about where the goal is.
		opt = floor(rnd * 3)
		if opt == 0 then
			if goal[2] == pos[2] then
				hint = "The MacGuffin lies on this level."
			else if goal[2] > pos[2] then
				hint = "The MacGuffin rests above."
			else
				hint = "The MacGuffin lies below."
			end if
		else if opt == 1 then
			if goal[0] > pos[0] then
				hint = "The MacGuffin lies to the east."
			else if goal[0] < pos[0] then
				hint = "The MacGuffin lies to the west."
			else
				hint = "The MacGuffin lies... <undecipherable>"
			end if
		else
			if goal[1] > pos[1] then
				hint = "The MacGuffin lies to the north."
			else if goal[1] < pos[1] then
				hint = "The MacGuffin lies to the south."
			else
				hint = "The MacGuffin lies... <undecipherable>"
			end if
		end if
		self.color = "Scratched on the wall is a message: " + hint
	else if rnd < 0.5 then
		// Give some random color comment.
		color = []
		opt = floor(rnd * 3)
		if opt == 1 then
			color.push "You detect " + pickAny("a faint;an odd;a musty;a rotten;an unpleasant")
			color.push pickAny("smell;odor;scent;stench") + " here."
		else if opt == 2 then
			color.push "You can hear a" + pickAny(" faint; quiet; soft; strange;n eerie")
			color.push pickAny("dripping;scratching;scrabbling;whistling;moaning")
			color.push pickAny("sound;noise") + " here."
		else
			color.push "The " + pickAny("walls here are;floor here is;ceiling of this room is")
			color.push pickAny("smeared with;discolored by;marred by;covered with")
			color.push pickAny("dried blood;cobwebs;scratches;gouges;scorch marks;soot;mineral deposits;bits of fur") + "."
		end if
		self.color = color.join
	end if
	self.exits = {}
end function
 
rooms = {}  // key: STRING FORM of position; value: Room
getRoom = function(pos=null)
	if pos == null then pos = globals.pos
	key = str(pos)
	if not rooms.hasIndex(key) then
		rooms[key] = new Room
		rooms[key].init pos
	end if
	return rooms[key]
end function
 
// Commands:
commands = {}
help = {}
 
commands.drop = function(obj)
	items = inventory.withdraw(obj)
	if items == null then
		print "You don't have any " + obj + "."
	else
		getRoom.contents.deposit items
		print items.desc("You drop")
	end if
end function
help.drop = "Drops an item from your inventory into the room.  Specify object name or ""all""."
 
commands.go = function(d)
	oldRoom = getRoom
	if dirAbbrevs.hasIndex(d) then d = dirAbbrevs[d]
	if not dir then
		print "Which direction?"
	else if not dir.hasIndex(d) then
		print "That's not a direction I recognize."
	else if d == "up" and oldRoom.contents.ladders == 0 then
		print "There is no ladder in this room to go up."
	else
		if not oldRoom.exits.hasIndex(d) then
			if inventory.hammers < 1 then
				print "There is no exit that way, and you don't have a sledgehammer."
				return
			end if
			wall = "wall"
			if d == "up" then wall = "ceiling"
			if d == "down" then wall = "floor"
			print "You bash the " + wall + " until you make a passage big enough to crawl through."
			oldRoom.exits.push d
		end if
		delta = dir[d]
		pos[0] = pos[0] + delta[0]
		pos[1] = pos[1] + delta[1]
		pos[2] = pos[2] + delta[2]
		newRoom = getRoom
		newRoom.exits.push inverseDir[d]
		verb = "crawl"
		if d == "up" then verb = "climb"
		if d == "down" then
			if newRoom.contents.ladders > 0 then verb = "climb" else verb = "drop"
		end if
		print "You " + verb + " " + d + "."
		commands.look
		if pos == goal then
			print "You have recovered the MacGuffin and " + descNum(inventory.gold, "gold coin") + ".  You win!"
			globals.gameOver = true
		end if
	end if
end function
help.go = "Moves in the given direction, bashing open a passage if necessary."
 
commands.help = function(arg)
	if aliases.hasIndex(arg) then arg = aliases[arg]
	if help.hasIndex(arg) then
		print arg + ": " + help[arg]
	else
		print "Available commands: " + descList(help.indexes.sort)
	end if
end function
help.help = "Prints the help.  Obviously."
 
commands.inventory = function(arg)
	print inventory.desc("You have")
end function
help.inventory = "Lists the items you are carrying."
 
commands.look = function(arg)
	print "You are at " + pos + "."
	room = getRoom
	if room.color != "" then print room.color
	print room.contents.desc("You see", " here.")
	exits = room.exits.indexes
	if exits.len == 0 then
		print "There are no exits."
	else if room.exits.len == 1 then
		print "There is a passage " + exits[0] + "."
	else
		print "There are passages " + descList(exits) + "."
	end if		
end function
help.look = "Prints a description of the room and its contents."
 
commands.quit = function(arg)
	print "Quitter!"
	globals.gameOver = true
end function
help.quit = "Quits the game."
 
commands.take = function(obj)
	roomStuff = getRoom.contents
	items = roomStuff.withdraw(obj)
	if items == null then
		print "You don't see any " + obj + " here."
	else
		inventory.deposit items
		print items.desc("You take")
	end if
end function
help.take = "Picks up an item in the room; specify item name, or ""all""."
 
// Command aliases:
aliases = {"i":"inventory", "inv":"inventory", "l":"look", "get":"take"}
 
// Main game loop
gameOver = false
commands.look
while not gameOver
	cmd = input(">").split(" ", 2)
	if cmd.len == 1 then cmd.push null
	verb = cmd[0]
	if aliases.hasIndex(verb) then verb = aliases[verb]
	if commands.hasIndex(verb) then
		f = commands[verb]
		f cmd[1]
	else if dirAbbrevs.hasIndex(verb) or dir.hasIndex(verb) then
		commands.go verb
	else
		print "Invalid command.  For help, enter: help"
	end if
end while