miserjs 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -12
- package/dist/browser/miserjs-engine-1.0.4.min.js +3 -0
- package/dist/browser/miserjs-engine-1.0.4.min.js.br +0 -0
- package/dist/browser/miserjs-engine-1.0.4.min.js.gz +0 -0
- package/dist/browser/miserjs-engine-1.0.4.min.mjs +1 -0
- package/dist/browser/miserjs-engine-1.0.4.min.mjs.br +0 -0
- package/dist/browser/miserjs-engine-1.0.4.min.mjs.gz +0 -0
- package/dist/engine/miserjs-engine.min.js +1 -750
- package/dist/node/miserjs-node.min.js +1 -24
- package/package.json +1 -1
- package/dist/browser/miserjs-engine-1.0.3.min.js +0 -752
- package/dist/browser/miserjs-engine-1.0.3.min.js.br +0 -0
- package/dist/browser/miserjs-engine-1.0.3.min.js.gz +0 -0
- package/dist/browser/miserjs-engine-1.0.3.min.mjs +0 -750
- package/dist/browser/miserjs-engine-1.0.3.min.mjs.br +0 -0
- package/dist/browser/miserjs-engine-1.0.3.min.mjs.gz +0 -0
|
@@ -1,750 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* I have intentionally used the most primitive types and functions in order to
|
|
3
|
-
* closely match the original Commodore PET source code.
|
|
4
|
-
*
|
|
5
|
-
* There are lots of opportunities for modernizing or optimizing the code in
|
|
6
|
-
* many different languages, including JavaScript here.
|
|
7
|
-
*
|
|
8
|
-
* I thought it best to keep it simple so this code could be ported to
|
|
9
|
-
* non-object-oriented languages such as C, possibly on something as small as an
|
|
10
|
-
* Arduino. It also makes it easier for someone new to programming to add new
|
|
11
|
-
* rooms, floors, or objects.
|
|
12
|
-
*
|
|
13
|
-
*/
|
|
14
|
-
export default class MiserJSEngine{
|
|
15
|
-
/**
|
|
16
|
-
* This is where the response text is built, line by line, possibly from multiple methods.
|
|
17
|
-
* Usually there is some text followed by output from the LOOK command.
|
|
18
|
-
* @type {string}
|
|
19
|
-
*/
|
|
20
|
-
#t="";
|
|
21
|
-
/**
|
|
22
|
-
* @type {MiserState}
|
|
23
|
-
*/
|
|
24
|
-
#e;
|
|
25
|
-
/**
|
|
26
|
-
* Verb.
|
|
27
|
-
* @type {string|null} First word in input: the verb.
|
|
28
|
-
*/
|
|
29
|
-
#s=null;
|
|
30
|
-
/**
|
|
31
|
-
* Object.
|
|
32
|
-
* @type {string|null} Second word in input: the object. Can be used later, as with the SAY verb.
|
|
33
|
-
*/
|
|
34
|
-
#r=null;
|
|
35
|
-
/**
|
|
36
|
-
* If the input is greater than #INPUT_STRING_LIMIT characters, trim it.
|
|
37
|
-
* Change this if you add new commands or object names that would exceed this length.
|
|
38
|
-
* @type {number} To limit how much of the input string is subject to the tokenizer. */
|
|
39
|
-
static#i=40;
|
|
40
|
-
/**
|
|
41
|
-
*
|
|
42
|
-
* @param {MiserState|null} miserState
|
|
43
|
-
*/
|
|
44
|
-
constructor(t=null){
|
|
45
|
-
// ToDo: Check for a valid MiserState object.
|
|
46
|
-
this.#e=t||JSON.parse(JSON.stringify(MiserJSEngine.#n))}newGame(){
|
|
47
|
-
// Deep copy the default state.
|
|
48
|
-
this.#e=JSON.parse(JSON.stringify(MiserJSEngine.#n))}
|
|
49
|
-
/**
|
|
50
|
-
* The primary method for playing the game.
|
|
51
|
-
* @param {string} input Player input text.
|
|
52
|
-
* @returns {MiserResponse}
|
|
53
|
-
*/request(t){this.#t="";
|
|
54
|
-
/**
|
|
55
|
-
* Simple argument checking here, since you will be using
|
|
56
|
-
* this engine behind your own front-end anyway.
|
|
57
|
-
* Do more strict player input sanitization there.
|
|
58
|
-
* You'll probably want to parse the player input in your front-end and
|
|
59
|
-
* add some special commands like 'save', 'load', etc.
|
|
60
|
-
*/
|
|
61
|
-
let e=t;if(!e)return this.#o("No input was provided.",!1,!0);
|
|
62
|
-
// Make sure leading and trailing white-space is deleted.
|
|
63
|
-
e=e.trim(),
|
|
64
|
-
/**
|
|
65
|
-
* If the inputString is greater than #INPUT_STRING_LIMIT characters,
|
|
66
|
-
* trim it, to minimize the work done in the tokenizer below.
|
|
67
|
-
* Change this (above) if you add new commands or object names that would exceed this length.
|
|
68
|
-
* Default value: 40 characters for a "verb object" input line.
|
|
69
|
-
*/
|
|
70
|
-
e.length>MiserJSEngine.#i&&(e=e.substring(0,MiserJSEngine.#i))
|
|
71
|
-
/**
|
|
72
|
-
* Simple tokenizer to get the words.
|
|
73
|
-
*/;let s,r,i=0,n=0,o=[];
|
|
74
|
-
// The following will remove leading spaces, spaces between words, and trailing spaces.
|
|
75
|
-
do{" "!==e.charAt(i)?i++:(i>n&&o.push(e.substring(n,i)),i++,n=i)}while(i<e.length);
|
|
76
|
-
// Get the final word, which might be the entire string if there were no spaces in it.
|
|
77
|
-
// JavaScript substring does not include the character at the end index (stringIndex here).
|
|
78
|
-
switch(i>n&&o.push(e.substring(n,i)),o.length){case 1:
|
|
79
|
-
// Search the verbs list
|
|
80
|
-
return s=this.#a(o[0]),s>0?(this.#s=o[0],this.#h(s,0)):this.#u();case 2:return s=this.#a(o[0]),s>0?(this.#s=o[0],r=this.#p(o[1]),r>0?(this.#r=o[1],this.#h(s,r)):this.#u()):this.#u();default:return this.#o("Please type a one or two word command.\n")}}
|
|
81
|
-
/**
|
|
82
|
-
* Implements the BASIC code at lines 900-920.
|
|
83
|
-
* @param {number} i
|
|
84
|
-
* @param {number} j
|
|
85
|
-
*/#h(t,e){switch(t){case 1:case 2:return this.#l(e);case 3:case 4:case 5:return this.#c(e);case 6:return this.#m(e);case 7:return this.#S(e);case 8:case 29:return this.#d();case 9:return this.#g();case 10:return this.#f(e);case 11:return this.#T(e);case 12:return this.#y(e);case 13:return this.#w(e);case 14:return this.#b(e);case 15:return this.#x();case 16:return this.#k(e);case 17:case 18:return this.#v();case 19:case 20:return this.#I();case 21:case 22:return this.#E();case 23:case 24:return this.#P();case 25:return this.#M();case 26:return this.#Y(e);case 27:return this.#R();case 28:return this.#J();
|
|
86
|
-
// Case 29, INVENTORY, handled above at case 8,29.
|
|
87
|
-
case 30:return this.#O(e);default:throw new Error(`In Action method: Verb '${this.#s}' was defined in the verbs array, but not implemented yet.`)}}
|
|
88
|
-
/**
|
|
89
|
-
* Case 1 and 2: Get, Take
|
|
90
|
-
* @param {number} j Index into objects array.
|
|
91
|
-
* @returns {MiserResponse}
|
|
92
|
-
*/#l(t){if(0==t)return this.#u();if(-1==this.#e.pt[t])return this.#o("I am unable to do that.\n");if(-1==this.#G(t))return this.#o("You're already carrying it.\n");if(this.#G(t)!=this.#e.cp)return this.#N();this.#e.ol[this.#e.pt[t]]=-1,this.#t+="Ok\n";
|
|
93
|
-
// Line 1030
|
|
94
|
-
let e=this.#e.pt[t];return e>3&&e<9||19===e?(this.#e.gt+=1,this.#t+="You got a treasure!\n",this.#o(this.#t)):(2===t&&-2===this.#e.ol[20]&&(
|
|
95
|
-
// Sets key location to Front Porch.
|
|
96
|
-
this.#e.ol[20]=0,this.#t+="You find a door key!\n"),this.#o(this.#t))}
|
|
97
|
-
/**
|
|
98
|
-
* Case 3,4,5: Move, Slide, Push
|
|
99
|
-
* This method implements the functionality of lines 2000-2210 in the original Miser program.
|
|
100
|
-
* @param {number} j Index into objects array.
|
|
101
|
-
* @returns {MiserResponse}
|
|
102
|
-
*/#c(t){if(0==t)
|
|
103
|
-
// Prints the "What?" or "I don't understand that." messages.
|
|
104
|
-
// Lines 210 and 50000 in the original 1981 Miser program.
|
|
105
|
-
return this.#u();
|
|
106
|
-
// Check the pt[] array for a -1, which means this object doesn't move.
|
|
107
|
-
// Skip the check for the cabinet pt[13], since it can be moved conditionally. Checked after this in the switch.
|
|
108
|
-
if(13!=t){if(-1==this.#e.pt[t])return this.#o("That item stays put.\n");if(this.#e.ol[this.#e.pt[t]]!=this.#e.cp&&-1!=this.#e.ol[this.#e.pt[t]])
|
|
109
|
-
// "I don't see it here."
|
|
110
|
-
return this.#N()}
|
|
111
|
-
// Only the CABINET, MAT, and RUG can move.
|
|
112
|
-
switch(t){
|
|
113
|
-
// Mat
|
|
114
|
-
case 2:
|
|
115
|
-
// If brass door key not found/hidden (-2).
|
|
116
|
-
if(-2==this.#e.ol[20])
|
|
117
|
-
// Set object location (ol[20]) of key (20) to the front porch (rString[0]).
|
|
118
|
-
return this.#e.ol[20]=0,this.#o("You find a door key!\n");break;
|
|
119
|
-
// Oriental Rug
|
|
120
|
-
case 10:
|
|
121
|
-
// If trapdoor not found/hidden (-2)
|
|
122
|
-
if(-2==this.#e.ol[16])
|
|
123
|
-
// Found trapdoor. Location is now in the Formal Parlor, so it will be observed on a new LOOK command.
|
|
124
|
-
return this.#t+="You find a trap door!\n",this.#e.ol[16]=6,this.#x();break;
|
|
125
|
-
// Cabinet
|
|
126
|
-
case 13:
|
|
127
|
-
// CP=5=Red-Walled Room rString[5]
|
|
128
|
-
// rPercent(5,3)=0 means EAST direction is unavailable, meaning the vault has not been found yet.
|
|
129
|
-
// So this means, 'If in Red-Walled Room and EAST direction unavailable, move the cabinet and find the vault'.
|
|
130
|
-
return 5==this.#e.cp&&0==this.#e.rPercent[5][3]?(
|
|
131
|
-
// fv is Found Vault: Set it to true.
|
|
132
|
-
this.#e.fv=!0,this.#t+="Behind the cabinet is a vault!\n",this.#x()):this.#o("That item stays put.\n")}return this.#o("Moving it reveals nothing.\n")}
|
|
133
|
-
/**
|
|
134
|
-
* CASE 6: Open.\
|
|
135
|
-
* Lines 4000-4260 in the original Miser program from 1981.
|
|
136
|
-
* The only objects that have a response for open are:
|
|
137
|
-
* Valve (7), Book (11), Door (12), Cabinet (13),
|
|
138
|
-
* Organ (16), Bag (22), and Vault (27).
|
|
139
|
-
* @param {number} j Index into objects array.
|
|
140
|
-
* @returns {MiserResponse}
|
|
141
|
-
*/#m(t){switch(t){case 0:
|
|
142
|
-
// Nothing to open.
|
|
143
|
-
return this.#u();case 7:
|
|
144
|
-
// Valve.
|
|
145
|
-
return this.#o("Try turning it.\n");case 11:
|
|
146
|
-
// Book.
|
|
147
|
-
if(this.#e.ol[this.#e.pt[t]]==this.#e.cp||-1==this.#e.ol[this.#e.pt[t]])return this.#o("Scrawled in blood on the inside front cover is the message, \"'Victory' is a prize-winning word\".\n");break;case 12:
|
|
148
|
-
// Door.
|
|
149
|
-
switch(this.#e.cp){case 0:
|
|
150
|
-
// Front Porch.
|
|
151
|
-
// Door unlocked?
|
|
152
|
-
return this.#e.du?this.#o("It's already open.\n"):this.#o("Sorry, the door is locked.\n");case 6:
|
|
153
|
-
// Formal Parlor.
|
|
154
|
-
return this.#t+="You open the door. You lean over to peer in, and you fall in!\n",this.#e.cp=47,this.#x()}return this.#N();
|
|
155
|
-
// Cabinet
|
|
156
|
-
case 13:
|
|
157
|
-
// In Red-Walled room? (CP=5)
|
|
158
|
-
return this.#e.ol[26]==this.#e.cp?this.#o("The cabinet is empty and dusty.\nScribbled in dust on one shelf are the words, 'behind me'.\n"):this.#N();
|
|
159
|
-
// Organ
|
|
160
|
-
case 16:
|
|
161
|
-
// In Ballroom?
|
|
162
|
-
return 21==this.#e.cp?this.#e.gg?-2!=this.#e.ol[24]?(
|
|
163
|
-
// Hide the 'ORGAN IN THE CORNER' and reveal the 'OPEN ORGAN IN THE CORNER'
|
|
164
|
-
this.#e.ol[24]=-2,this.#e.ol[25]=21,
|
|
165
|
-
// Reveal the Parachute Ripcord
|
|
166
|
-
this.#e.ol[17]=21,
|
|
167
|
-
// Reveal the Ruby Slippers
|
|
168
|
-
this.#e.ol[19]=21,this.#t+="As you open it, several objects suddenly appear!\n",this.#x()):this.#o("It's already open.\n"):this.#o("It's stuck shut.\n"):this.#N();
|
|
169
|
-
// Bag
|
|
170
|
-
case 22:
|
|
171
|
-
// If in the vault or carrying it
|
|
172
|
-
return this.#e.ol[this.#e.pt[t]]==this.#e.cp||-1==this.#e.ol[this.#e.pt[t]]?this.#o("The bag is knotted securely.\nIt won't open.\n"):this.#N();
|
|
173
|
-
// Vault
|
|
174
|
-
case 27:
|
|
175
|
-
// If in Red-Walled Room and FV=true (found vault)
|
|
176
|
-
return 5==this.#e.cp&&this.#e.fv?
|
|
177
|
-
// Vault open?
|
|
178
|
-
this.#e.vo?this.#o("It's already open.\n"):this.#o("I can't, it's locked.\n"):this.#N()}return this.#o("I don't know how to open that.\n")}
|
|
179
|
-
/**
|
|
180
|
-
* CASE 7: Read.
|
|
181
|
-
* Lines 5000-5050 in the original Miser program from 1981.
|
|
182
|
-
* @param {*} j Index into objects array.
|
|
183
|
-
* @returns
|
|
184
|
-
*/#S(t){
|
|
185
|
-
// Second word to act on?
|
|
186
|
-
if(0==t)
|
|
187
|
-
// Returns 'What?' or 'I don't understand that.'.
|
|
188
|
-
return this.#u();if(-1==this.#e.pt[t])return this.#o("There's nothing written on that.\n");if(!this.#j(t))
|
|
189
|
-
// Returns "I don't see it here."
|
|
190
|
-
return this.#N();switch(t){
|
|
191
|
-
// PAPER
|
|
192
|
-
case 3:
|
|
193
|
-
// Player now knows the combination to the vault
|
|
194
|
-
return this.#e.kc=!0,this.#o("It says, '12-35-6'.\nhmm.. looks like a combination.\n");
|
|
195
|
-
// BOOK
|
|
196
|
-
case 11:return this.#o("The front cover is inscribed in Greek.\n");default:return this.#o("There's nothing written on that.\n")}}
|
|
197
|
-
/**
|
|
198
|
-
* Case 8,29: Inventory.
|
|
199
|
-
* Output a list of all objects the player is carrying.
|
|
200
|
-
* Lines 6000-6040 in the original Miser program from 1981.
|
|
201
|
-
* @returns {MiserResponse}
|
|
202
|
-
*/#d(){this.#t+="You are carrying the following:\n\n";let t=0;for(let e=1;e<28;e++)
|
|
203
|
-
// Carrying object omString[x]?
|
|
204
|
-
if(-1==this.#e.ol[e]){
|
|
205
|
-
// Bucket full?
|
|
206
|
-
if(t=1,this.#t+=`${MiserJSEngine.#D[e]}\n`,1==e&&this.#e.bf){this.#t+=" The bucket is full of water.\n";continue}14==e&&(this.#t+=" (Better fix it)\n")}
|
|
207
|
-
// Found items?
|
|
208
|
-
return 1==t?this.#o(this.#t):this.#o(this.#t+="Nothing at all.\n")}
|
|
209
|
-
/**
|
|
210
|
-
* Case 9: Quit.
|
|
211
|
-
* Lines 7000-7150 in the original Miser program from 1981.
|
|
212
|
-
*
|
|
213
|
-
* Special actions for quit should be for the host program to decide.
|
|
214
|
-
* The host could use the method, this.#showFinalOutcome or combine it with a
|
|
215
|
-
* score display, or something else.
|
|
216
|
-
* @returns {MiserResponse}
|
|
217
|
-
*/#g(){
|
|
218
|
-
// Take special action for quit in the host program.
|
|
219
|
-
// The host could use the method, this.showFinalOutcome, or combine it with a score display, or something else.
|
|
220
|
-
return this.#o(this.#t,MiserJSEngine.#A.QUIT)}
|
|
221
|
-
/**
|
|
222
|
-
* Case 10: Drop.
|
|
223
|
-
* Lines 8000-8221 in the original Miser program from 1981.
|
|
224
|
-
* @param {number} j Index into objects array.
|
|
225
|
-
* @returns {MiserResponse}
|
|
226
|
-
*/#f(t){
|
|
227
|
-
// Preservation of bug in original code
|
|
228
|
-
if(-1==this.#e.pt[t])return this.#t+="\n?ILLEGAL QUANTITY ERROR IN 8000\n\n",this.#t+="----------------------------------------",this.#t+="** You have encountered a bug that\n",this.#t+="existed in the original Miser program\n",this.#t+="from 1981. **\n\n",this.#t+="This bug is being reproduced here to\n",this.#t+="preserve the experience a player would\n",this.#t+="have had playing this game in 1981 on\n",this.#t+="one of the Commodore PET computers.\n\n",this.#t+="Except for one thing...the game doesn't\n",this.#t+="just end unexpectedly here as it did\n",this.#t+="back then.\n\n",this.#t+="You get to keep playing as if nothing\n",this.#t+="bad happened!\n",this.#o(this.#t);
|
|
229
|
-
// Carrying this object?
|
|
230
|
-
if(-1!=this.#e.ol[this.#e.pt[t]])return this.#o("You aren't carrying it!\n");
|
|
231
|
-
// Ok, player is carrying the object represented by pt[j], since ol[pt[j]] has a value of -1 here.
|
|
232
|
-
// The only objects that DROP should provide a special response for are the 5 treasures, the Penny, and the Cross.
|
|
233
|
-
// All other objects just get dropped with an 'Ok' response.
|
|
234
|
-
// Check for one of the 5 treasures
|
|
235
|
-
switch(this.#e.pt[t]){
|
|
236
|
-
// One of the 5 treasures
|
|
237
|
-
// Remember that the value of pt[j] is an index into the omString array (om$() in original program).
|
|
238
|
-
case 4:case 5:case 7:case 8:case 19:return this.#o("Don't drop *treasures*!\n")}
|
|
239
|
-
// Check for a Penny or a Cross specifically. All other objects should just be dropped with a response of "Ok"
|
|
240
|
-
switch(t){
|
|
241
|
-
// Drop Penny
|
|
242
|
-
case 19:
|
|
243
|
-
// In Portico?
|
|
244
|
-
if(19==this.#e.cp)
|
|
245
|
-
// The Penny is being carried, and the player is in the Portico.
|
|
246
|
-
// DROP PENNY action
|
|
247
|
-
// Update the EAST (3) direction of the BALLROOM (21) to point toward the CHAPEL (22)
|
|
248
|
-
// Player can now move from the BALLROOM to the CHAPEL.
|
|
249
|
-
// Modifies rPercent array.
|
|
250
|
-
return this.#e.rPercent[21][3]=22,
|
|
251
|
-
// Update object location of the PENNY to 'hidden'(-2)
|
|
252
|
-
this.#e.ol[12]=-2,this.#o("As the penny sinks below the surface of the pool, a fleeting image of a chapel with dancers outside appears.\n");break;
|
|
253
|
-
// Drop Cross.
|
|
254
|
-
case 20:
|
|
255
|
-
// In Chapel?
|
|
256
|
-
if(22==this.#e.cp)
|
|
257
|
-
// "chapel. A tablet says 'drop a religious item or die!!' becomes simply "chapel".
|
|
258
|
-
// rString array was directly modified here in the original source code.
|
|
259
|
-
// This is now handled as a special case in the LOOK command, when in the chapel (index 22 in rString).
|
|
260
|
-
// That way we can keep the rString array as static data that never changes, doesn't have to be saved/restored.
|
|
261
|
-
// DON'T USE NOW: this.#miserState.rString[22] = "chapel";
|
|
262
|
-
// "organ in the corner" becomes "closed organ playing music in the corner"
|
|
263
|
-
// omString array was directly modified here in the original source code.
|
|
264
|
-
// This is now handled as a special case in the LOOK command, when in the ballroom.
|
|
265
|
-
// That way we can keep the omString array as static data that never changes, doesn't have to be saved/restored.
|
|
266
|
-
// DON'T USE NOW: this.#miserState.omString[24] = "closed organ playing music in the corner";
|
|
267
|
-
// The CROSS is being carried, and the player is in the Chapel.
|
|
268
|
-
// DROP CROSS action
|
|
269
|
-
// LINES 8200-8221 in the original program.
|
|
270
|
-
// Still trying to figure out what GG could stand for.
|
|
271
|
-
// If GG is TRUE it means the player can OPEN the ORGAN in the BALLROOM.
|
|
272
|
-
// Prior to dropping the CROSS here, this wasn't possible.
|
|
273
|
-
// GG = 'Got God'? You know...chapel...cross...God...
|
|
274
|
-
return this.#e.gg=!0,
|
|
275
|
-
// RUSTY CROSS becomes 'hidden' (-2)
|
|
276
|
-
this.#e.ol[11]=-2,this.#o("Even before it hits the ground, the cross fades away!\n\nThe tablet has disintegrated.\n\nYou hear music from the organ.\n")}
|
|
277
|
-
// If the PENNY or the CROSS weren't in their special action locations in the above switch statement, they will be dropped here.
|
|
278
|
-
// Any other objects being carried will be dropped here as well.
|
|
279
|
-
// ol[pt[j]] (object location) gets updated to the current position. (CP)
|
|
280
|
-
return this.#e.ol[this.#e.pt[t]]=this.#e.cp,this.#o("Ok\n")}
|
|
281
|
-
/**
|
|
282
|
-
* Case 11: Say.
|
|
283
|
-
* Lines 9000-9300 in the original Miser program from 1981.
|
|
284
|
-
* @param {number} j Index into objects array.
|
|
285
|
-
* @returns {MiserResponse}
|
|
286
|
-
*/#T(t){switch(t){
|
|
287
|
-
// No second word to say
|
|
288
|
-
case 0:return this.#o("Say what???\n");
|
|
289
|
-
// Lines 9100-9120 Say ritnew
|
|
290
|
-
case 14:
|
|
291
|
-
// In Pantry?
|
|
292
|
-
return 4==this.#e.cp?
|
|
293
|
-
// Charmed Snake?
|
|
294
|
-
this.#e.ch?this.#o("Nothing happens.\n"):(this.#e.ch=!0,
|
|
295
|
-
// Vicious snake disappears from conservatory.
|
|
296
|
-
this.#e.ol[2]=-2,
|
|
297
|
-
// Charmed Snake appears in conservatory. (rString[4])
|
|
298
|
-
this.#e.ol[3]=4,this.#o("The snake is charmed by the very utterance of your words.\n")):this.#o("Nothing happens.\n");
|
|
299
|
-
// Lines 9200-9220 Say victory
|
|
300
|
-
case 15:
|
|
301
|
-
// In Trophy room?
|
|
302
|
-
return 8==this.#e.cp?
|
|
303
|
-
// Portal open?
|
|
304
|
-
this.#e.po?this.#o("Nothing happens.\n"):(
|
|
305
|
-
// Set Portal Open
|
|
306
|
-
this.#e.po=!0,
|
|
307
|
-
// Set Trophy Room north direction to point toward rString[17], which is the Game Room.
|
|
308
|
-
// Modifies rPercent array.
|
|
309
|
-
this.#e.rPercent[8][1]=17,
|
|
310
|
-
// 'Portal in the North Wall' appears in the Trophy Room (rString[8]).
|
|
311
|
-
this.#e.ol[18]=8,this.#o("A portal has opened in the north wall!!\n")):this.#o("Nothing happens.\n");
|
|
312
|
-
// Line 9300 Say Xyzzy, Say Plugh (These are magic words used in the 'Colossal Cave Adventure' game from 1975!)
|
|
313
|
-
case 29:case 30:return this.#o("A hollow voice says, 'Wrong adventure'.\n");default:return t<29?this.#o(`Okay, '${this.#r}'.\nNothing happens.\n`):this.#u()}}
|
|
314
|
-
/**
|
|
315
|
-
* CASE 12: Pour.
|
|
316
|
-
* Lines 10000 to 10060 in the original Miser program from 1981.
|
|
317
|
-
* @param {number} j Index into objects array.
|
|
318
|
-
* @returns {MiserResponse}
|
|
319
|
-
*/#y(t){
|
|
320
|
-
// Only the bucket (oString[4]) can be poured.
|
|
321
|
-
if(4!=t)return this.#o("I wouldn't know how.\n");if(!this.#j(t))return this.#N();
|
|
322
|
-
// Is bucket empty?
|
|
323
|
-
if(!this.#e.bf)return this.#o("The bucket is already empty.\n");switch(this.#e.cp){
|
|
324
|
-
// BLUE DRAWING ROOM
|
|
325
|
-
case 10:
|
|
326
|
-
// Is fire burning?
|
|
327
|
-
if(this.#e.fb)
|
|
328
|
-
// Fire Burning becomes FALSE. The fire is out now.
|
|
329
|
-
return this.#e.fb=!1,
|
|
330
|
-
// Bucket is no longer full.
|
|
331
|
-
this.#e.bf=!1,this.#t+="Congratulations! You have vanquished the flames.\n",this.#x();break;
|
|
332
|
-
// PORTICO
|
|
333
|
-
case 19:return this.#o("Ok\n");
|
|
334
|
-
|
|
335
|
-
}return this.#o("The water disappears quickly.\n")}
|
|
336
|
-
/**
|
|
337
|
-
* CASE 13: Fill.
|
|
338
|
-
* Lines 11000-11070 in the original Miser program from 1981.
|
|
339
|
-
* @param {number} j Index into objects array.
|
|
340
|
-
* @returns {MiserResponse}
|
|
341
|
-
*/#w(t){if(0==t)
|
|
342
|
-
// "What?" or "I don't understand that."
|
|
343
|
-
return this.#u();if(-1==this.#e.pt[t])return this.#o("That wouldn't hold anything.\n");if(!this.#j(t))
|
|
344
|
-
// "I don't see it here."
|
|
345
|
-
return this.#N();
|
|
346
|
-
// Is this the bucket?
|
|
347
|
-
if(4==t){
|
|
348
|
-
// Is the bucket full?
|
|
349
|
-
if(this.#e.bf)return this.#o("It's already full.\n");switch(this.#e.cp){
|
|
350
|
-
// Bucket can ony be filled in the PORTICO and BACK YARD near the faucet.
|
|
351
|
-
case 19:case 23:return this.#e.bf=!0,this.#o("Your bucket is now full.\n");
|
|
352
|
-
// POOL AREA
|
|
353
|
-
case 25:if(this.#e.pf)return this.#o("I'd rather stay away from the mercury.\n")}return this.#o("I don't see any water here.\n")}
|
|
354
|
-
// Only the bucket can be filled
|
|
355
|
-
return this.#o("That wouldn't hold anything.\n")}
|
|
356
|
-
/**
|
|
357
|
-
* Unlock.
|
|
358
|
-
* Only the DOOR, TRAPDOOR, and VAULT are acted on here.
|
|
359
|
-
* This method implements the functionality of lines 11000 to 11070
|
|
360
|
-
* in the original Miser program from 1981.
|
|
361
|
-
* @param {number} j Index into objects array.
|
|
362
|
-
* @returns {MiserResponse}
|
|
363
|
-
*/#b(t){
|
|
364
|
-
// Only the DOOR/TRAPDOOR (12) and the VAULT (27) can be unlocked
|
|
365
|
-
switch(t){
|
|
366
|
-
// No object
|
|
367
|
-
case 0:
|
|
368
|
-
// Return "What?" or "I don't understand that."
|
|
369
|
-
return this.#u();
|
|
370
|
-
// Door or Trapdoor
|
|
371
|
-
case 12:switch(this.#e.cp){
|
|
372
|
-
// Door at Front Porch (CP=0)
|
|
373
|
-
case 0:return this.#e.du?this.#o("It's already unlocked.\n"):
|
|
374
|
-
// Carrying the key? (omString[20])
|
|
375
|
-
-1!=this.#e.ol[20]?this.#o("I need a key.\n"):(this.#e.du=!0,this.#t+="The door easily unlocks and swings open.\n",this.#x());
|
|
376
|
-
// Trapdoor in Formal Parlor (CP=6)
|
|
377
|
-
case 6:
|
|
378
|
-
// Trapdoor Hidden?
|
|
379
|
-
return-2!=this.#e.ol[16]?this.#o("The trapdoor has no lock.\n"):this.#o("I don't see it here.\n");default:
|
|
380
|
-
// "I don't see it here."
|
|
381
|
-
return this.#N()}
|
|
382
|
-
// Vault
|
|
383
|
-
case 27:
|
|
384
|
-
// In Red-Walled Room?
|
|
385
|
-
return 5==this.#e.cp?
|
|
386
|
-
// Vault open?
|
|
387
|
-
this.#e.vo?this.#o("It's already open.\n"):
|
|
388
|
-
// Found vault?
|
|
389
|
-
this.#e.fv?
|
|
390
|
-
// Know combination?
|
|
391
|
-
this.#e.kc?(this.#e.vo=!0,
|
|
392
|
-
// Modifies rPercent array.
|
|
393
|
-
this.#e.rPercent[5][3]=46,this.#t+="Ok, let's see. 12..35..6..\n<CLICK!> The door swings open.",this.#x()):this.#o("I don't know the combination.\n"):this.#N():this.#N();default:return this.#o("I wouldn't know how to unlock one.\n")}}
|
|
394
|
-
/**
|
|
395
|
-
* CASE 15: Look.
|
|
396
|
-
* Lines 14000-14170 in the original Miser program from 1981.
|
|
397
|
-
* @returns {MiserResponse}
|
|
398
|
-
*/#x(){
|
|
399
|
-
// Line 14000 - Print current position
|
|
400
|
-
let t=this.#e.cp;22==t&&this.#e.gg?
|
|
401
|
-
// If in chapel, and already dropped the cross, print a different room description.
|
|
402
|
-
this.#t+="\nYou are in the chapel.\n":this.#t+=`\nYou are in the ${MiserJSEngine.#B[t]}.\n`;
|
|
403
|
-
// Lines 14010-14030 Print list of all objects at this location (CP variable)
|
|
404
|
-
for(let e=1;e<29;e++)this.#e.ol[e]==t&&(
|
|
405
|
-
// Object found at this location (CP).
|
|
406
|
-
// Special case for the organ.
|
|
407
|
-
24==e&&this.#e.gg?this.#t+="\nThere is a closed organ playing music in the corner here.\n":this.#t+=`\nThere is a ${MiserJSEngine.#D[e]} here.\n`,
|
|
408
|
-
// If the plastic bucket is here and it is full (BF=true).
|
|
409
|
-
1==e&&this.#e.bf&&(this.#t+=" The bucket is full of water.\n"));
|
|
410
|
-
// Special actions depending on current position (CP)
|
|
411
|
-
switch(this.#e.cp){case 0:
|
|
412
|
-
// Line 14127 Front Porch
|
|
413
|
-
// Door unlocked?
|
|
414
|
-
this.#e.du&&(this.#t+="\nAn open door leads north.\n");break;case 5:
|
|
415
|
-
// Lines 14125-14126 Red-Walled Room
|
|
416
|
-
// Found vault?
|
|
417
|
-
this.#e.fv&&(this.#t+="\nThere is a vault in the east wall.\n"),this.#e.vo&&(this.#t+="The vault is open.\n");break;case 10:
|
|
418
|
-
// Lines 14060-14080 and 14120 Blue Drawing Room
|
|
419
|
-
this.#e.fb?
|
|
420
|
-
// Fire Burning
|
|
421
|
-
this.#t+="\nThere is a hot fire on the south wall!\nIf I go that way I'll burn to death!\n":this.#t+="\nThere is evidence of a recent fire here.\n";break;case 16:
|
|
422
|
-
// Lines 14090-14105 Pantry
|
|
423
|
-
this.#t+="\nA rich, full voice says, 'Ritnew is a charming word'.\n";break;case 23:
|
|
424
|
-
// Line 14115 Back Yard
|
|
425
|
-
this.#t+="\nThere is a leaky faucet nearby.\n";break;case 25:
|
|
426
|
-
// Lines 14040-14056 Pool Area
|
|
427
|
-
// Pool full?
|
|
428
|
-
this.#e.pf?this.#t+="\nThe pool is full of liquid mercury!\n":(this.#t+="\nThe pool's empty.\n",48==this.#e.ol[7]&&(this.#t+="\nI see something shiny in the pool!\n"));break;case 26:
|
|
429
|
-
// Line 14110 Pump House
|
|
430
|
-
this.#t+="\nThere is a valve on one of the pipes.\n";break;case 48:
|
|
431
|
-
// Line 14130 Bottom of Swimming Pool
|
|
432
|
-
// Skip showing obvious exits.
|
|
433
|
-
return this.#o(this.#t)}
|
|
434
|
-
// Lines 14130-14170
|
|
435
|
-
// Print all available direction commands from this location.
|
|
436
|
-
return this.#t+="\nObvious Exits:\n",this.#e.rPercent[this.#e.cp][1]>0&&(this.#t+="N "),this.#e.rPercent[this.#e.cp][2]>0&&(this.#t+="S "),this.#e.rPercent[this.#e.cp][3]>0&&(this.#t+="E "),this.#e.rPercent[this.#e.cp][4]>0&&(this.#t+="W "),
|
|
437
|
-
// Add newline.
|
|
438
|
-
this.#t+="\n",this.#o(this.#t)}
|
|
439
|
-
/**
|
|
440
|
-
* CASE 16: Go.
|
|
441
|
-
* Lines 15000-15080 in the original Miser program from 1981.
|
|
442
|
-
* @param {number} j Index into objects array.
|
|
443
|
-
* @returns {MiserResponse}
|
|
444
|
-
*/#k(t){
|
|
445
|
-
// Valid objects are Ladder(8), Stairs(18), and Pool(28).
|
|
446
|
-
switch(t){
|
|
447
|
-
// Ladder
|
|
448
|
-
case 8:
|
|
449
|
-
// In bottom of pool?
|
|
450
|
-
return 48==this.#e.cp?(
|
|
451
|
-
// Move from 'bottom of swimming pool' to 'Pool Area'
|
|
452
|
-
this.#e.cp=25,this.#x()):this.#N();
|
|
453
|
-
// Stairs
|
|
454
|
-
case 18:
|
|
455
|
-
// In 'Great Hall' or 'Middle of the western hallway'?
|
|
456
|
-
switch(this.#e.cp){
|
|
457
|
-
// Great Hall.
|
|
458
|
-
case 2:
|
|
459
|
-
// Carrying sword?
|
|
460
|
-
return-1==this.#e.ol[9]?(
|
|
461
|
-
// Move from Great Hall to 'Middle of the western hallway'
|
|
462
|
-
this.#e.cp=27,this.#t+="The suits of armor try to stop you, but you fight them off with your sword.\n",this.#x()):this.#o("The suits of armor prevent you from going up!\n");
|
|
463
|
-
// Middle of the western hallway.
|
|
464
|
-
case 27:
|
|
465
|
-
// Move to Great Hall
|
|
466
|
-
return this.#e.cp=2,this.#x();default:
|
|
467
|
-
// Print "I don't see it here."
|
|
468
|
-
return this.#N()}
|
|
469
|
-
// Pool
|
|
470
|
-
case 28:
|
|
471
|
-
// Pool full?
|
|
472
|
-
return this.#e.pf?this.#o("The pool is full of mercury!\n"):(
|
|
473
|
-
// Move to bottom of swimming pool
|
|
474
|
-
this.#e.cp=48,this.#x());default:return this.#u()}}
|
|
475
|
-
/**
|
|
476
|
-
* CASE 17,18: North.
|
|
477
|
-
* Lines 16000-16020 in the original Miser program from 1981.
|
|
478
|
-
* @returns {MiserResponse}
|
|
479
|
-
*/#v(){return 0!=this.#e.cp||this.#e.du?0==this.#e.rPercent[this.#e.cp][1]?this.#C():(0==this.#e.cp&&(this.#t+="\nThe door slams shut behind you!\n"),this.#e.cp=this.#e.rPercent[this.#e.cp][1],this.#x()):(this.#t+="The door is locked shut.\n",this.#o(this.#t))}
|
|
480
|
-
/**
|
|
481
|
-
* CASE 19,20: South.
|
|
482
|
-
* Lines 17000 to 17050 in the original Miser program from 1981.
|
|
483
|
-
* @returns {MiserResponse}
|
|
484
|
-
*/#I(){if(10==this.#e.cp&&this.#e.fb)return this.#t+="You have burnt to a crisp!\n",this.#o(this.#t,MiserJSEngine.#A.DIED);const t=this.#H();return null!=t?t:0==this.#e.rPercent[this.#e.cp][2]?this.#C():(this.#e.cp=this.#e.rPercent[this.#e.cp][2],this.#x())}
|
|
485
|
-
/**
|
|
486
|
-
* CASE 21,22: East.
|
|
487
|
-
* There is a check for the snake every time the player tries to move East,
|
|
488
|
-
* regardless of the current position.
|
|
489
|
-
* Lines 17010 to 17050 in the original Miser program from 1981.
|
|
490
|
-
* @returns {MiserResponse}
|
|
491
|
-
*/#E(){const t=this.#H();return null!=t?t:0==this.#e.rPercent[this.#e.cp][3]?this.#C():(this.#e.cp=this.#e.rPercent[this.#e.cp][3],this.#x())}
|
|
492
|
-
/**
|
|
493
|
-
* CASE 23,24: West.
|
|
494
|
-
* Lines 19000 to 19010 in the original Miser program from 1981.
|
|
495
|
-
* @returns {MiserResponse}
|
|
496
|
-
*/#P(){return 0==this.#e.rPercent[this.#e.cp][4]?this.#C():(this.#e.cp=this.#e.rPercent[this.#e.cp][4],this.#x())}
|
|
497
|
-
/**
|
|
498
|
-
* CASE 25: Score.
|
|
499
|
-
* Lines 20000 to 20060 in the original Miser program from 1981.
|
|
500
|
-
* @returns {MiserResponse}
|
|
501
|
-
*/#M(){this.#t+=`Your current score is: ${20*this.#e.gt} points.\n(100 possible)\n`;let t=this.#e.gt;this.#e.es&&t++,this.#t+=`\nYour rank is: ${MiserJSEngine.#$[t]}\n`;let e=MiserJSEngine.#$.length-1-t;return this.#t+=0==e?" (You have escaped with ALL available treasure!)\n":1==e?" (There is only one rank left for you to achieve!)\n":` (There are ${e} more ranks you can achieve.)\n`,this.#o(this.#t)}
|
|
502
|
-
/**
|
|
503
|
-
* CASE 26: Turn.
|
|
504
|
-
* Only the VALVE can be turned.
|
|
505
|
-
* Lines 21000 to 21070 in the original Miser program from 1981.
|
|
506
|
-
* @param {number} j Index into objects array.
|
|
507
|
-
* @returns {MiserResponse}
|
|
508
|
-
*/#Y(t){return 7!=t?this.#o("I don't know how to turn such a thing.\n"):26!=this.#e.cp?this.#N():(
|
|
509
|
-
// Toggle POOL FULL
|
|
510
|
-
this.#e.pf=!this.#e.pf,this.#o("With much effort, you turn the valve 5 times. You hear the sound of liquid\nflowing through the pipes.\n"))}
|
|
511
|
-
/**
|
|
512
|
-
* CASE 27: Jump.
|
|
513
|
-
* Can only JUMP from MIDDLE OF THE WESTERN HALLWAY, FRONT BALCONY, and REAR BALCONY.
|
|
514
|
-
* Lines 22000 to 22540 in the original Miser program from 1981.
|
|
515
|
-
* @returns {MiserResponse}
|
|
516
|
-
*/#R(){switch(this.#e.cp){case 27:
|
|
517
|
-
// MIDDLE OF THE WESTERN HALLWAY
|
|
518
|
-
return this.#t+="You jump...\n",this.#e.jm?(this.#t+="Now you've done it. You ignored\nmy warning, and as a result\nyou have broken your neck!\n\nYou are dead.",this.#o(this.#t,MiserJSEngine.#A.DIED)):(this.#e.jm=!0,this.#e.cp=2,this.#t+="You have landed down-stairs,\nand narrowly escaped serious\ninjury. Please don't try it again.\n",this.#x());case 29:case 32:
|
|
519
|
-
// Next action depends on the three possible states of the parachute in the players inventory:
|
|
520
|
-
// 1) No parachute. Not in inventory.
|
|
521
|
-
// 2) Carrying the parachute that hasn't been fixed with the ripcord.
|
|
522
|
-
// 3) Carrying a fully functional parachute.
|
|
523
|
-
if(this.#t+="You jump...\n",-1==this.#e.ol[14])
|
|
524
|
-
// Have Parachute with no ripcord.
|
|
525
|
-
return this.#t+="There is no way to open the parachute!\n",this.#t+="You hit the ground.\n",this.#t+="You have broken your neck!\n\n",this.#t+="You are dead.",this.#o(this.#t,MiserJSEngine.#A.DIED);if(-1!=this.#e.ol[27])return this.#t+="You hit the ground.\n",this.#t+="You have broken your neck!\n\n",this.#t+="You are dead.",this.#o(this.#t,MiserJSEngine.#A.DIED);if(
|
|
526
|
-
// Have fully functional parachute.
|
|
527
|
-
this.#t+="You yank the ripcord and the\n'chute comes billowing out.\n",32==this.#e.cp)
|
|
528
|
-
// At rear balcony, so change current position to HEDGE MAZE (40)
|
|
529
|
-
return this.#e.cp=40,this.#x();if(29==this.#e.cp)return this.#t+="You land safely.\n\nCongratulations on escaping!\n",this.#e.es=!0,this.#o(this.#t,MiserJSEngine.#A.ESCAPED);default:return this.#t+="There's nowhere to jump.",this.#o(this.#t)}}
|
|
530
|
-
/**
|
|
531
|
-
* CASE 28: Swim.
|
|
532
|
-
* Lines 24000 to 24030 in the original Miser program from 1981.
|
|
533
|
-
* @returns {MiserResponse}
|
|
534
|
-
*/#J(){switch(this.#e.cp){case 19:
|
|
535
|
-
// Portico.
|
|
536
|
-
return this.#o("The water is only a few inches deep.\n");case 25:
|
|
537
|
-
// Pool area.
|
|
538
|
-
// Pool full?
|
|
539
|
-
return this.#e.pf?this.#o("In mercury? No way!\n"):this.#o("The pool is empty.\n");default:return this.#o("There's nothing here to swim in!\n")}}
|
|
540
|
-
// Case 29: INVENTORY -> Handled at Case 8 above (Case 8,29:)
|
|
541
|
-
/**
|
|
542
|
-
* CASE 30: Fix.
|
|
543
|
-
* Lines 25000 to 25070 in the original Miser program from 1981.
|
|
544
|
-
* @param {number} j Index into objects array.
|
|
545
|
-
* @returns {MiserResponse}
|
|
546
|
-
*/
|
|
547
|
-
#O(t){switch(t){case 0:
|
|
548
|
-
// Nothing to fix
|
|
549
|
-
return this.#u();case 7:
|
|
550
|
-
// Valve
|
|
551
|
-
return this.#o("I ain't no plumber.\n");case 17:
|
|
552
|
-
// If parachute with no ripcord isn't at current position AND not carrying it
|
|
553
|
-
return this.#j(t)?-2==this.#e.ol[14]?this.#o("It's already fixed.\n"):
|
|
554
|
-
// If not carrying the ripcord
|
|
555
|
-
-1!=this.#e.ol[17]?this.#o("I need a ripcord.\n"):(
|
|
556
|
-
// Have parachute with no ripcord, and ripcord is here, so fix the parachute.
|
|
557
|
-
// Reveal 'repaired parachute' at the same location as 'parachute with no ripcord'
|
|
558
|
-
this.#e.ol[27]=this.#e.ol[14],
|
|
559
|
-
// Hide 'parachute with no ripcord'
|
|
560
|
-
this.#e.ol[14]=-2,
|
|
561
|
-
// Update pointer to omString[27] 'repaired parachute'
|
|
562
|
-
this.#e.pt[17]=27,
|
|
563
|
-
// Update parachute ripcord location to the front porch. Weird, but it works to hide it.
|
|
564
|
-
this.#e.ol[17]=0,this.#o("I'm no expert, but I think it'll work.\n")):this.#N();default:return this.#o("I wouldn't know how.\n")}}
|
|
565
|
-
/**
|
|
566
|
-
*
|
|
567
|
-
* @returns {MiserResponse|null}
|
|
568
|
-
*/#H(){return 4!=this.#e.cp||this.#e.ch?null:this.#e.ps?this.#o("The snake bites you!\nYou are dead.\n",MiserJSEngine.#A.DIED):(this.#e.ps=!0,this.#o("The snake is about to attack!\n"))}
|
|
569
|
-
/**
|
|
570
|
-
* Call this method after player dies or escapes, to get the final score and rank.
|
|
571
|
-
* @returns {MiserResponse}
|
|
572
|
-
*/showFinalOutcome(){this.#t=`\nYou accumulated ${this.#e.gt} treasures, \n for a score of ${20*this.#e.gt} points.\n(100 Possible)\n`;let t=this.#e.gt;return this.#e.es?t++:this.#t+="\nHowever, you did not escape.\n",this.#t+=`\nThis puts you in a class of:\n${MiserJSEngine.#$[t]}\n`,6!=t&&(this.#t+="\nBetter luck next time!\n"),this.#o(this.#t,!0)}
|
|
573
|
-
/**
|
|
574
|
-
* Creates new output arguments.
|
|
575
|
-
* @param {string} outputText String to return.
|
|
576
|
-
* @param {boolean|string} [gameOver=false]
|
|
577
|
-
* @param {boolean} [isError=false] Signal an error to the host program.
|
|
578
|
-
* @returns {MiserResponse}
|
|
579
|
-
*/#o(t,e=!1,s=!1){return{text:t,gameOver:e,isError:s}}
|
|
580
|
-
/**
|
|
581
|
-
* Line 810 in original program from 1981.
|
|
582
|
-
* @param {string} s
|
|
583
|
-
* @returns {number} Index into verbs[] array, or 0 if not found.
|
|
584
|
-
*/#a(t){(t=t.toLowerCase()).length>4&&(t=t.substring(0,4))
|
|
585
|
-
/*
|
|
586
|
-
This can be done more efficiently in most languages, but this is how
|
|
587
|
-
it's done in the original 1981 program at Line 810.
|
|
588
|
-
*/;for(let e=1;e<MiserJSEngine.#z.length;e++)if(t===MiserJSEngine.#z[e])
|
|
589
|
-
// Match. Return array index into the verbs array.
|
|
590
|
-
return e;return 0}
|
|
591
|
-
/**
|
|
592
|
-
* @param {string} s
|
|
593
|
-
* @returns {number} Index into objects[] array, or 0 if not found.
|
|
594
|
-
*/#p(t){(t=t.toLowerCase()).length>4&&(t=t.substring(0,4));for(let e=1;e<MiserJSEngine.#F.length;e++)if(t===MiserJSEngine.#F[e])
|
|
595
|
-
// Match. Return array index into the objects array.
|
|
596
|
-
return e;return 0}
|
|
597
|
-
/**
|
|
598
|
-
* Returns one of "What?" or "I don't understand that."
|
|
599
|
-
* @returns {MiserResponse}
|
|
600
|
-
*/#u(){return this.#t+=`${MiserJSEngine.#L[this.#e.em]}\n`,
|
|
601
|
-
// Alternate between hString[1] and hString[2].
|
|
602
|
-
this.#e.em=3-this.#e.em,this.#o(this.#t)}
|
|
603
|
-
/**
|
|
604
|
-
* Returns "I don't see it here."
|
|
605
|
-
* @returns {MiserResponse}
|
|
606
|
-
*/#N(){return this.#t+="I don't see it here.\n",this.#o(this.#t)}
|
|
607
|
-
/**
|
|
608
|
-
* Line 52000 in the original 1981 program.
|
|
609
|
-
* Tried to go in a direction not defined in r%(room number, N, S, E, W)
|
|
610
|
-
* Returns "It's impossible to go that way."
|
|
611
|
-
* @returns {MiserResponse}
|
|
612
|
-
*/#C(){return this.#t+="It's impossible to go that way.\n",this.#o(this.#t)}
|
|
613
|
-
/**
|
|
614
|
-
* If object is at current position (cp) or being carried (-1), it is present.
|
|
615
|
-
* In the 1981 source code, this check is done at multiple locations, using
|
|
616
|
-
* the same line of code:
|
|
617
|
-
* Lines 2020, 4005, 4170, 5005, 11020, 25030
|
|
618
|
-
* @param {number} j
|
|
619
|
-
* @returns {boolean}
|
|
620
|
-
*/#j(t){return this.#G(t)==this.#e.cp||-1==this.#G(t)}
|
|
621
|
-
/**
|
|
622
|
-
* Returns an object location value for the object typed after the verb on an input line.
|
|
623
|
-
* @param {number} x Index into objects array.
|
|
624
|
-
*/#G(t){return this.#e.ol[this.#e.pt[t]]}getCurrentPosition(){return this.#e.cp}
|
|
625
|
-
/**
|
|
626
|
-
* Get a more concise name for the current room/location listed in the rString[] array.
|
|
627
|
-
* @param {number} cp Current position from a MiserState object.
|
|
628
|
-
* @returns {string}
|
|
629
|
-
*/getCurrentPositionShortName(t){return MiserJSEngine.#W[t]}
|
|
630
|
-
/**
|
|
631
|
-
*
|
|
632
|
-
* @param {MiserState} miserState
|
|
633
|
-
*/getInventoryItemCount(t){let e=0;for(const s of t.ol)-1==s&&e++;return e}
|
|
634
|
-
/**
|
|
635
|
-
* Return current game state, so you can save it somewhere.
|
|
636
|
-
* @returns {MiserState}
|
|
637
|
-
*/getGameState(){return this.#e}
|
|
638
|
-
/**
|
|
639
|
-
* Set new game state.
|
|
640
|
-
* Call this after you restore a previously saved game.
|
|
641
|
-
* @param {MiserState} miserState
|
|
642
|
-
*/setGameState(t){this.#e=t}isGameInProgress(){return this.#e.cp>0}
|
|
643
|
-
/* ##### Start of STATIC DATA ###### */
|
|
644
|
-
/* This data is not modified in the original source code. */
|
|
645
|
-
/**
|
|
646
|
-
* List of actions, such as LOOK, GET, MOVE, etc.
|
|
647
|
-
* v$ (verbs) begins at 1 in the original program.
|
|
648
|
-
* Setting index 0 to "" here.
|
|
649
|
-
* Defined at Line 500 in the original program from 1981.
|
|
650
|
-
* STATIC DATA: This array was not modified in the original source code.
|
|
651
|
-
* @type {string[]}
|
|
652
|
-
*/static#z=["","get","take","move","slid","push","open","read","inve","quit","drop","say","pour","fill","unlo","look","go","nort","n","sout","s","east","e","west","w","scor","turn","jump","swim","i","fix"];
|
|
653
|
-
/**
|
|
654
|
-
* List of objects.
|
|
655
|
-
* o$ (objects) begins at 1 in the original program. Setting index 0 to "" here.
|
|
656
|
-
*
|
|
657
|
-
* STATIC DATA: This array was not modified in the original source code.
|
|
658
|
-
* @type {string[]}
|
|
659
|
-
*/
|
|
660
|
-
static#F=["","ripc","mat","pape","buck","swor","key","valv","ladd","slip","rug","book","door","cabi","ritn","vict","orga","para","stai","penn","cros","leaf","bag",">$<",">$<","ring","pain","vaul","pool","xyzz","plug"];
|
|
661
|
-
/**
|
|
662
|
-
* Error messages.
|
|
663
|
-
* Alternates between index 1 and 2 via the em variable.
|
|
664
|
-
* em starts at 1 in the program.
|
|
665
|
-
* em=3-em changes that to em=2 and
|
|
666
|
-
* the next em=3-em changes that em=2 to em=1.
|
|
667
|
-
* STATIC DATA: This array was not modified in the original source code.
|
|
668
|
-
* @type {string[]}
|
|
669
|
-
*/
|
|
670
|
-
static#L=["","What?","I don't understand that."];
|
|
671
|
-
/**
|
|
672
|
-
* Rank descriptions.
|
|
673
|
-
* STATIC DATA.
|
|
674
|
-
* @type {string[]}
|
|
675
|
-
*/
|
|
676
|
-
static#$=["<Beginner Adventurer>","<Amateur Adventurer>","<Journeyman Adventurer>","<Experienced Adventurer>","<Pro Adventurer>","<Master Adventurer>","<Grandmaster Adventurer>"];static#D=["",// om$ begins at 1 in the original program. Setting index 0 to "" here.
|
|
677
|
-
"plastic bucket","vicious snake","charmed snake","*golden leaf*","*bulging moneybag*",">$<","*diamond ring*","*rare painting*","sword","mat","rusty cross","penny","piece of paper","parachute with no ripcord","oriental rug","trapdoor marked 'danger'","parachute ripcord","portal in the north wall","pair of *ruby slippers*","brass door key","majestic staircase leading up","majestic staircase leading down","battered book","organ in the corner","open organ in the corner","cabinet on rollers against one wall over","repaired parachute","sign saying 'drop coins for luck'"];static#B=["front porch","Foyer to a large house. Dust is everywhere","Great Hall. Suits of armor line the walls","Breakfast Room. It is bright and cheery","Conservatory. Through a window you see a hedge-maze","Red-Walled Room","Formal Parlor","Green Drawing Room","Trophy Room. Animal heads line the walls","Den","Blue Drawing Room","Library. Empty shelves line the walls","Dining Room","Chinese Room","$","Kitchen. It is bare","Pantry. Dust covers the mahogany shelves","Game Room","Smoking Room. The air is stale in here","Portico. A murky pool glimmers on the south side","Hall Of Mirrors - a good place to reflect","Ballroom. It has a beautiful wood dance floor","Chapel. A tablet says 'Drop a religious item or die!!'","back yard","forest","Pool Area. There is a large swimming pool here","Pump House. There is pool machinery installed here","middle of the Western Hallway","West Bedroom","Front Balcony. There is a large road below","$","Master Bedroom. There's a huge four-poster bed","Rear Balcony. Below you see a Hedge Maze","East Bedroom","Closet","Junction of the West Hallway and the North-South Hallway","Center of the North-South Hallway","Junction of the East Hallway and the North-South Hallway","Middle of the East Hallway","South end of the East Hallway","hedge maze","hedge maze","hedge maze","hedge maze","hedge maze","hedge maze","walk-in Vault","Dungeon. There is light above and to the south","bottom of the Swimming Pool. A ladder leads up and out"];static#W=["Front Porch","Foyer","Great Hall","Breakfast Room","Conservatory","Red-Walled Room","Formal Parlor","Green Drawing Room","Trophy Room","Den","Blue Drawing Room","Library","Dining Room","Chinese Room","$","Kitchen","Pantry","Game Room","Smoking Room","Portico","Hall of Mirrors","Ballroom","Chapel","Back Yard","Forest","Pool Area","Pump House","Middle of West Hallway","West Bedroom","Front Balcony","$","Master Bedroom","Rear Balcony","East Bedroom","Closet","West Hallway Junction","Center of North-South Hallway","East Hallway Junction","Middle of East Hallway","South End East Hallway","hedge maze","hedge maze","hedge maze","hedge maze","hedge maze","hedge maze","Vault","Dungeon","Swimming Pool"];static#A=Object.freeze({DIED:"died",ESCAPED:"escaped",QUIT:"quit"});
|
|
678
|
-
/* ##### End of STATIC DATA ###### */
|
|
679
|
-
/* ###### Variable Game State Data ###### */
|
|
680
|
-
/* Gets deep copied into a new MiserState object for a new game. */
|
|
681
|
-
/**
|
|
682
|
-
* @type {MiserState}
|
|
683
|
-
*/
|
|
684
|
-
static#n={cp:0,em:1,gt:0,du:!1,pf:!0,fb:!0,bf:!1,fv:!1,vo:!1,po:!1,ch:!1,ps:!1,kc:!1,es:!1,jm:!1,gg:!1,
|
|
685
|
-
/**
|
|
686
|
-
* Object Pointer array.
|
|
687
|
-
* pt starts at index 1 in the original program. I'm keeping that here and just setting index 0 to 0.
|
|
688
|
-
* The index numbers align with the o$ objects array: o$(1)=ripcord, so pt%(1)'s value is an index pointer for the ripcord, into ol% and om$.
|
|
689
|
-
* A (-1) stored here means the object doesn't have an action for it, such as move, open, etc.
|
|
690
|
-
* The original 1981 program will crash when looking up ol%(pt%(object_index)) when pt%(object_index) returns -1.
|
|
691
|
-
* In that case, ol%(-1) produces an ILLEGAL QUANTITY error and the program ends.
|
|
692
|
-
* Many routines will check that pt%(object_index) isn't equal to a -1 before using it with ol% or om$, but some don't.
|
|
693
|
-
* For instance, if you try to DROP the CABINET, ORGAN, STAIRS, or any other object that has a -1 in pt%, the program crashes.
|
|
694
|
-
* (On crash, on the PET or in Vice/XPET on PC: type GOTO 14000 and you can resume the game. 14000=start of LOOK routine.)
|
|
695
|
-
* DYNAMIC DATA.
|
|
696
|
-
* @type {number[]}
|
|
697
|
-
*/
|
|
698
|
-
pt:[0,17,10,13,1,9,20,-1,-1,19,15,23,-1,-1,-1,-1,-1,14,-1,12,11,4,5,-1,-1,7,8,-1,-1,-1,-1],
|
|
699
|
-
/**
|
|
700
|
-
* Object Location array.
|
|
701
|
-
* ol starts at index 1 in the original program. I'm keeping that here and just setting index 0 to 0.
|
|
702
|
-
* A (-1) stored here means the player is carrying the object. It will be listed by the I or INVEntory command.
|
|
703
|
-
* A (-2) stored here means the object is hidden.
|
|
704
|
-
* DYNAMIC DATA.
|
|
705
|
-
* @type {number[]}
|
|
706
|
-
*/
|
|
707
|
-
ol:[0,26,4,-2,45,46,-2,48,39,13,0,// Index 10 - Mat location, 0 = rString[0] = front porch
|
|
708
|
-
23,28,31,34,6,-2,-2,-2,-2,-2,// Index 20 - Brass Door Key, -2 = doesn't exist yet. Will change to 0 (front porch) when the mat is moved
|
|
709
|
-
2,27,11,21,-2,5,-2,19],
|
|
710
|
-
// This entire array is being saved in MiserState.
|
|
711
|
-
// Most of this array is static data, but 3 rooms are modified in the original source code.
|
|
712
|
-
// rPercent[5][3] gets modified. (Red-walled room. East becomes 46, to go into vault. )
|
|
713
|
-
// rPercent[8][1] gets modified. (Trophy room. North becomes 17, to go to Game Room. )
|
|
714
|
-
// rPercent[21][3] gets modified. (Ballroom. East becomes 22, to go to Chapel.)
|
|
715
|
-
// I thought someone might want to add additional floors, rooms, or portals that would require
|
|
716
|
-
// updating even more of these arrays, so I'm treating them all as dynamic/changing/must-save for now.
|
|
717
|
-
rPercent:[[0,1,0,0,0],[0,2,0,0,12],[0,3,1,0,0],[0,0,2,4,16],[0,0,5,7,3],[0,4,6,0,0],[0,5,0,10,0],[0,0,0,8,4],[0,0,9,0,7],[0,8,0,0,10],[0,0,11,9,6],[0,10,0,0,0],[0,0,0,1,13],[0,15,0,12,0],[0,0,0,0,0],[0,23,13,16,0],[0,0,0,3,15],[0,0,8,0,18],[0,21,0,17,19],[0,21,0,18,20],[0,21,21,19,19],[0,0,19,0,20],[0,0,0,0,21],[0,24,15,40,25],[0,24,23,24,24],[0,26,0,23,0],[0,0,25,0,0],[0,35,0,31,28],[0,0,0,27,0],[0,39,0,0,0],[0,0,0,0,0],[0,0,0,38,27],[0,0,36,0,0],[0,34,0,0,38],[0,0,33,0,0],[0,0,27,36,0],[0,32,0,37,35],[0,0,38,0,36],[0,37,39,33,31],[0,38,29,0,0],[0,0,42,0,41],[0,44,42,0,0],[0,41,44,43,0],[0,41,23,0,0],[0,0,42,0,45],[0,0,0,44,0],[0,0,0,0,5],[0,0,40,0,0],[0,0,0,0,0]]}}
|
|
718
|
-
/**
|
|
719
|
-
* @typedef {Object} MiserState
|
|
720
|
-
* @property {number} cp Current Position
|
|
721
|
-
* @property {number} em Error Message.
|
|
722
|
-
* @property {number} gt Got Treasure.
|
|
723
|
-
* @property {boolean} du Door Unlocked.
|
|
724
|
-
* @property {boolean} pf Pool Full.
|
|
725
|
-
* @property {boolean} fb Fire Burning.
|
|
726
|
-
* @property {boolean} bf Bucket Full.
|
|
727
|
-
* @property {boolean} fv Found Vault.
|
|
728
|
-
* @property {boolean} vo Vault Open.
|
|
729
|
-
* @property {boolean} po Portal Open.
|
|
730
|
-
* @property {boolean} ch CHarmed snake.
|
|
731
|
-
* @property {boolean} ps Peeved Snake.
|
|
732
|
-
* @property {boolean} kc Knows Combination.
|
|
733
|
-
* @property {boolean} es EScaped.
|
|
734
|
-
* @property {boolean} jm Jump Made.
|
|
735
|
-
* @property {boolean} gg Got God? [I mean, it is related to the 'drop a religious item or die' and the cross...]
|
|
736
|
-
* @property {number[]} ol Object location array.
|
|
737
|
-
* @property {number[]} pt Object pointer array.
|
|
738
|
-
* @property {Array<number[]>} rPercent Rooms map - N S E W. (new int[49,5])
|
|
739
|
-
*/
|
|
740
|
-
/** @typedef {Object} GameOverReason
|
|
741
|
-
* @property {string} DIED
|
|
742
|
-
* @property {string} ESCAPED
|
|
743
|
-
* @property {string} QUIT
|
|
744
|
-
*/
|
|
745
|
-
/**
|
|
746
|
-
* @typedef {Object} MiserResponse
|
|
747
|
-
* @property {string} text Text that will be displayed to the player.
|
|
748
|
-
* @property {boolean|string} gameOver One of 'died', 'escaped', quit', or false.
|
|
749
|
-
* @property {boolean|string} isError Error text.
|
|
750
|
-
*/
|