-
Notifications
You must be signed in to change notification settings - Fork 2
/
teptour.js
4065 lines (3553 loc) · 153 KB
/
teptour.js
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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// teptour.js
//
// The tEp/Xi virtual house tour!
// (c) 2021 tEp/Xi
// tepxi.mit.edu
//
// Authors: Kyle Miller
//
// Adapted from a version in Python from 2011.
//
// (If you're reading this, we want to hear from you!)
"use strict";
// version numbers should only ever be of form 2.222...
world.global.set("release number", "2.2222 (08/2024)");
world.global.set("game title", "The tEp/Xi Virtual House Tour");
world.global.set("game headline", "A factual fantasy");
world.global.set("game author", "tEp/Xi");
world.global.set("game description", `Although you're still where you
were, you're now where you are since [ob 'Irving Q. Tep'] has brought
you to the Purple Palace, 253 Comm. Ave.`);
///
/// Fun and games
///
//// [img] command
var tobii = null;
HTML_abstract_builder.prototype.img = function (path, align) {
if (tobii == null) {
tobii = new Tobii({
counter: false
});
}
out.with_block("div", () => {
if (align === "left") {
out.add_class("desc_img_left");
} else {
out.add_class("desc_img");
}
const img_url = "images/" + path;
out.with_block("a", () => {
out.attr("href", img_url);
out.add_class("lightbox");
out.with_block("img", () => {
let img = out.root;
img.addEventListener("load", function (e) {
scroll_output_to_end();
});
out.attr("src", img_url);
});
tobii.add(out.root);
});
});
};
//// [ask] command
HTML_abstract_builder.prototype.ask = function (topic, text) {
out.wrap_action_link("ask Irving Q. Tep about " + topic, () => {
if (text) {
out.write(text);
} else {
out.write_text(topic);
}
});
};
/* See the section "Consulting Irving Q. Tep..." for how to add things
that one can ask him about. */
/// [em] command
/* here's something that italicizes just a few words for convenience. */
HTML_abstract_builder.prototype.em = function () {
out.with_inline("i", () => {
for (var i = 0; i < arguments.length; i++) {
out.write(arguments[i]);
}
});
};
//// Extra directions
add_direction_pair("northnorthwest", "southsoutheast");
parser.direction.understand("northnorthwest/nnw", parse => "northnorthwest");
parser.direction.understand("southsoutheast/sse", parse => "southsoutheast");
add_direction_pair("northnortheast", "southsouthwest");
parser.direction.understand("northnortheast/nne", parse => "northnortheast");
parser.direction.understand("southsouthwest/ssw", parse => "southsouthwest");
parser.direction.understand(["upstairs", "up stairs", "up the stairs"], parse => "up");
parser.direction.understand(["downstairs", "down stairs", "down the stairs"], parse => "down");
//// Other silly verbs
parser.action.understand("about", parse => asking_about("Irving Q. Tep", "virtual house tour"));
// TODO: make 'quit' have you quit the game, and you end up at a computer in the house
parser.action.understand("quit", parse => making_mistake("{Bobs} should try closing the tab instead."));
all_are_mistakes(["oh/ok"], "Exactly.");
all_are_mistakes(["nice", "nice tour"], `Thanks. Now don't forget to come by real-tEp/Xi\u2122!`);
parser.action.understand("cd ..", parse => exiting());
parser.action.understand("cd [somewhere x]", parse => going_to(parse.x));
parser.action.understand("pwd/dir", parse => looking());
all_are_mistakes(["rm/su/sudo [text x]"], `Nice try, buster.`);
parser.action.understand(["where am i", "where am i ?"], parse => looking());
all_are_mistakes(["cd", "go home"], "But you already are home!");
all_are_mistakes(["honig"], `"Honig!" you shout. You can hear vigorous acclamation all around you.`);
all_are_mistakes(["in the name of honig"], "Amen.");
all_are_mistakes(["what ?"], `You just had to
say that, didn't you. "What?" "What?" "What?" you hear xisters
everywhere yelling back and forth throughout the house. Finally, some
tEp/Xi figures out what's going on and silences them with "No one is
peldging, stop it!"`);
all_are_mistakes(["i wanna peldge"], `This is
virtual tEp/Xi. If you have a bid and you're wanting to peldge, then say
the magic words where real tEp/Xi can hear you!`);
all_are_mistakes(["pray/amen"], `A chorus of
angelic voices augment that of the chaplain, whom you find suddenly
next to you. "In the name of Honig, Amen," he ends. As you turn to
thank him for such a beautiful prayer, you see he has already slipped
away.`);
all_are_mistakes(["tep/xi/tepxi"], "That's where you are.");
all_are_mistakes(["why/how [text x]"], () => {
out.write_text("[");
out.write(`Sometimes while I wait for my hard drive to rev up I
wistfully contemplate what it would have been like to be able to
answer a question like that. Alack-a-day, that was not my fate.`);
out.write_text("]");
});
all_are_mistakes(["pickles ?"], `"I didn't make this tour!"
[ob 'Irving Q. Tep' Irving] explains, "I just repeat what I'm told."`);
all_are_mistakes(["eit", "eit!"], "Eit indeed!");
var faces = [":)", ":-)", ":(", ":-(", ";-)", ":P", ":-P", ":-D", ";)", ";P"];
faces.forEach(face => { // warning: :-/ will cause an error with 'understand'
parser.action.understand(face, parse => making_mistake(() => {
out.write("Oooh! Let me try![para]");
// This should be replaced by some textadv utility function at some point (once it exists)
out.write_text(faces[Math.floor(Math.random() * faces.length)]);
}));
});
parser.action.understand("gruesz [something x]", parse => taking(parse.x));
parser.action.understand("die", parse => attacking(world.actor));
actions.before.add_method({
when: action => action.verb === "attacking",
handle: function (action) {
if (action.dobj === "GRA") {
throw new abort_action(`The GRA wisely stays away from {us}.
"Remember the zeroth [ask 'rules of tEp/Xi' 'rule of tEp/Xi']!"
{we} hear them say from a safe distance, "Don't die!"`);
} else {
throw new abort_action(`The GRA comes out of nowhere, preventing
{us}. "Remember the zeroth [ask 'rules of tEp/Xi' 'rule of tEp/Xi']!"
they say, "Don't die!"`);
}
}
});
all_are_mistakes(["burn down tep"], `The GRA
comes out of nowhere, preventing {us}. "Remember the zeroth
[ask 'rules of tEp/Xi' 'rule of tEp/Xi']!" they say, "Don't die!"`);
all_are_mistakes(["sleep"], `You're too excited about the house tour to sleep right now!`);
// The free willy net says you can't get out even though you can...
all_are_mistakes(
["I thought I/you couldn't [text x]",
"I thought you said [text x]",
"you said [text x]",
"but you said [text x]"],
"Sometimes we make mistakes.");
//// Floors
// Since Avril seems to really want to be able to sit on floors.
def_kind("floor", "supporter");
world.is_scenery.add_method({
when: x => world.is_a(x, "floor"),
handle: x => true
});
world.enterable.add_method({
when: x => world.is_a(x, "floor"),
handle: x => true
});
actions.report.add_method({
when: action => action.verb === "entering" && world.is_a(action.dobj, "floor"),
handle: function (action) {
out.write("{Bobs} {have} sat down on "); out.the(action.dobj); out.write(".");
}
});
var floor_templates = {
"wood": {
words: ["wood", "@floor"],
description: `It's a gorgeous old wood floor that has
possibly been refinished recently.`
},
"carpet": {
name: "carpet",
words: ["carpet", "@carpet", "@floor"],
description: `The floor is covered in a fine-knit
commercial carpet. Luckily it's a dark blue color,
otherwise it wouldn't seem nearly as clean.`
},
"sidewalk": {
name: "sidewalk",
description: `It's a standard concrete sidewalk. Doubtless
you've seen one of these before.`
},
"tile": {
name: "tile floor",
description : `It's a floor made of square tiles which are a
foot to the side.`
}
};
var FLOOR_COUNTER = 0;
function add_floor(location, template, name=null) {
if (name === null) {
name = ":unique floor: " + (++FLOOR_COUNTER);
}
if (typeof template === "string") {
template = floor_templates[template];
}
def_obj(name, "floor", Object.assign({name: "floor"}, template));
world.put_in(name, location);
}
//// Sitting
function sitting() {
return {verb: "sitting"};
}
def_verb("sitting", "sit", "sitting");
parser.action.understand(["sit", "sit down"], parse => sitting());
actions.before.add_method({
name: "sitting find floor or other enterable",
when: action => action.verb === "sitting",
handle: function (action) {
// First try sitting on the floor.
for (var floor of world.all_of_kind("floor")) {
if (world.accessible_to(floor, world.actor)) {
throw new do_instead(entering(floor), true);
}
}
// Next try getting on a supporter.
for (var thing of world.all_of_king("supporter")) {
if (world.enterable(thing) && world.accessible_to(thing, world.actor)) {
throw new do_instead(entering(thing), true);
}
}
throw new abort_action("{We} {don't} want to sit down here.");
}
});
//// Eiting
function eiting(x) {
return {verb: "eiting", dobj: x};
}
def_verb("eiting", "eit", "eiting");
parser.action.understand("eit [something x]", parse => eiting(parse.x));
require_dobj_accessible("eiting");
actions.before.add_method({
name: "eiting default",
when: action => action.verb === "eiting",
handle: function (action) {
throw new abort_action("{Bobs} {don't} think it would be wise to eit that.");
}
});
function eiting_with(x, y) {
return {verb: "eiting with", dobj: x, iobj: y};
}
def_verb("eiting with", "eit", "eiting", "with");
parser.action.understand("eit [something x] with [something y]",
parse => eiting_with(parse.x, parse.y));
require_dobj_accessible("eiting with");
require_iobj_held("eiting with");
actions.before.add_method({
name: "eiting with default",
when: action => action.verb === "eiting with",
handle: function (action) {
throw new abort_action("{Bobs} {don't} think it would be wise to eit that.");
}
});
//// Defilements
// This is carefully set up so that you can ask other people to defile things
// (once textadv supports asking_to).
def_property("defilements", 1, {
doc: "A list of {actor, method} pairs."
});
world.defilements.add_method({
name: "default no defilements",
handle: (x) => []
});
function defiling(x, method) {
return {verb: "defiling", dobj: x, method: method};
}
def_verb("defiling", "defile", "defiling");
parser.action.understand("felch [something x]", parse => defiling(parse.x, "felched"));
parser.action.understand("pee on [something x]", parse => defiling(parse.x, "peed on"));
parser.action.understand("pee in [something x]", parse => defiling(parse.x, "peed in"));
parser.action.understand("poop on [something x]", parse => defiling(parse.x, "pooped on"));
parser.action.understand("poop in [something x]", parse => defiling(parse.x, "pooped in"));
parser.action.understand("poop down [obj 'center stairwell']",
parse => defiling("center stairwell", "pooped down"));
require_dobj_accessible("defiling");
actions.before.add_method({
name: "defile undefiled",
when: action => action.verb === "defiling",
handle: function (action) {
this.next();
for (let {actor, method} of world.defilements(action.dobj)) {
if (actor === world.actor && method === action.method) {
out.write("{Bobs} {have} already ");
out.write_text(method); out.write(" ");
out.the(action.dobj); out.write(".");
throw new abort_action();
}
}
}
});
actions.before.add_method({
name: "defiling in containers",
when: action => action.verb === "defiling" && action.method.endsWith(" in"),
handle: function (action) {
this.next();
if (!world.is_a(action.dobj, "container")) {
throw new abort_action("That can only be done to containers.");
}
if (world.openable(action.dobj) && !world.is_open(action.dobj)) {
out.write("That can only be done when "); out.the(action.dobj);
out.write(" is open.");
throw new abort_action();
}
}
});
actions.carry_out.add_method({
name: "defiling",
when: action => action.verb === "defiling",
handle: function (action) {
world.defilements.set(action.dobj,
world.defilements(action.dobj).concat([{actor: world.actor,
method: action.method}]));
}
});
actions.report.add_method({
name: "defiling",
when: action => action.verb === "defiling",
handle: function (action) {
out.write("The deed has been done.");
}
});
function describe_object_defilements(o) {
out.para();
world.describe_object.described = true;
let ds = world.defilements(o);
for (let culprit of new Set(ds.map(d => d.actor))) {
let methods = ds.filter(d => d.actor === culprit);
if (culprit !== world.actor) {
out.The(culprit); out.write(" has ");
out.serial_comma(methods.map(d => () => out.write_text(d.method)));
out.write(" "); out.the(o); out.write(".");
} else {
out.write("{Bobs} {have} ");
out.serial_comma(methods.map(d => () => out.write_text(d.method)));
out.write(" "); out.the(o); out.write(".");
}
}
}
world.describe_object.add_method({
name: "describe defiled",
when: o => world.defilements(o).length > 0,
handle: function (o) {
this.next();
describe_object_defilements(o);
}
});
//// Ladders
def_property("is_ladder", 1, {
doc: "Represents whether something is a ladder. This means climbing is understood as entering."
});
world.is_ladder.add_method({
name: "default not ladder",
handle: (x) => false
});
instead_of(({verb, dobj}) => verb === "climbing" && world.is_ladder(dobj),
action => entering(action.dobj), true);
parser.action.understand("climb/go up/down [something x]", parse => climbing(parse.x));
///
/// The player
///
def_obj("player", "person", {
proper_named: false,
words: ["@player", "@yourself", "@self", "@me"],
description: "You're figuring stuff out."
}, {put_in: "253 Commonwealth Ave"});
///
/// Irving Q. Tep
///
def_obj("Irving Q. Tep", "person", {
gender: "male",
proper_named : true,
description : `It's Irving Q. Tep, spirit of the house. He
is giving you stories and such [enter_inline i]telepathically[leave] using
images and text. Quite amazing.
[para]You can ask Irving Q. Tep about various concepts. For
instance "[action 'ask about stupidball']" (which is shorthand
for "[action 'ask Irving about stupidball']"), and for your convenience
you can click "ask irving" in the lower right corner to get a list of
everything you can ask about. If you know something
that Irving doesn't yet know but should, please let us know!`
// developers: see [ask ...] for links
}, {make_part_of: "player"});
// Dealing with how there's a period:
parser.anything.understand("irving q. tep", parse => "Irving Q. Tep");
///
/// Objects that are everywhere
///
def_obj("rat", "backdrop", {
backdrop_locations: "everywhere",
added_words: ["@rats"],
description: `It's a big fat rat scurrying around, or so it sounds like (it says well out of view).`,
no_take_msg: `You make a valiant attempt to locate and get ahold of the rat,
but it hides under some old psets and when you peer under them it's gone!`
// what if there is a network of portals the rats use to get to Lake Cujo?
});
def_obj("cat", "backdrop", {
backdrop_locations: "everywhere",
added_words: ["@cats"],
description: `It's a cat! It's also probably why there are so few rats
around tEp/Xi these days.`,
no_take_msg: `You manage to grab ahold of the cat for a while, petting it furiously
and making a wide assortment of "it's a cat!" faces. But it ultimately worms its
way out of your arms and scampers away on important cat business.`
});
def_obj("Xis", "person", {
added_words: ["@xi"],
is_scenery: true,
description: `(Please just imagine there are Xis around doing zany things.
The rush budget went into 600 pounds of oobleck rather than implementing NPCs with
more depth than a puddle of spilled milk.)`
});
actions.before.add_method({
when: action => action.verb === "taking" && action.dobj === "Xis",
handle: function (action) {
throw new abort_action("They wouldn't appreciate that.");
}
});
def_obj("GRA", "person", {
added_words: ["resident", "@advisor"],
is_scenery: true,
description: `Like Spiderman, the GRA can feel when there's trouble,
and they appears when they're needed. And that time is not now.`
});
actions.before.add_method({
when: action => action.verb === "taking" && action.dobj === "GRA",
handle: function (action) {
throw new abort_action(`Assuming you saw them, the GRA wouldn't appreciate that, but you don't so you can't.`);
}
});
world.move_backdrops.add_method({
handle: function () {
this.next();
world.put_in("Xis", world.location(world.actor));
world.put_in("GRA", world.location(world.actor));
}
});
///
/// In front of tEp/Xi: 253 Commonwealth Ave
///
def_obj("253 Commonwealth Ave", "room", {
description: `[img 1/253/look.JPG left]You are standing
outside the illustrious tEp/Xi, the
veritable purple palace. It is a hundred-twenty-two-year-old brownstone
in the middle of Boston's Back Bay. Outside the building is
[a 'purple tree'] and [a 'park bench'].
[para]Just to the north is [ob 'front door' 'the door'] to enter tEp/Xi.
[para]You can look [look east] and [look west] along the
street, [look up] at tEp/Xi, and [look south] toward the mall.`
});
// https://backbayhouses.org/253-commonwealth/ shows was built in 1880-1881 and purchased in 1958
// so the house is actually about 144 years old as of 2024.
// (fun fact: Curry College operated out of 253 in the 1940s, named after Haskell Curry's dad)
add_floor("253 Commonwealth Ave", "sidewalk");
world.direction_description.set("253 Commonwealth Ave", "west", `
[img 1/253/look_w.JPG left]Toward the west, you see that the
[ob 'purple tree'] is the only purple tree along the block.`);
world.direction_description.set("253 Commonwealth Ave", "east", `
[img 1/253/look_e.JPG left]Toward the east, you see that the
[ob 'purple tree'] is the only purple tree along the block.`);
world.direction_description.set("253 Commonwealth Ave", "south", `
[img 1/253/look_s.JPG left]Looking southward, you see the mall, that
grassy area between the two streets of Commonwealth Avenue.
Directly in front of tEp/Xi is a monument to historic women of Boston,
erected after some xisters wrote to the city multiple times
about how unfair it was that our block was the only one without any
kind of monument.`);
world.direction_description.set("253 Commonwealth Ave", "up", `
[img 1/253/look_up.JPG left]You look up and see a bit of the
[ob 'purple tree'] along with a few of the five floors of tEp/Xi.`);
instead_of(({verb, dir}) => (verb === "looking toward" && dir === "north"
&& world.containing_room(world.actor) === "253 Commonwealth Ave"),
action => looking());
instead_of(({verb, dir}) => (verb === "looking toward" && dir === "down"
&& world.containing_room(world.actor) === "253 Commonwealth Ave"),
action => examining("front garden"));
world.no_go_msg.add_method({
when: (x, dir) => x === "253 Commonwealth Ave",
handle: (x, dir) => `You head away from tEp/Xi, but you begin to realize the
rest of the neighborhood is just a dense bank of fog. You've heard this
virtual tEp/Xi is hosted in the cloud, and if you go that way you might fall off!`
});
def_obj("tEp/Xi", "backdrop", {
proper_named: "tEp/Xi",
added_words: ["@house"],
backdrop_locations: ["253 Commonwealth Ave", "The Backlot"]
});
instead_of(({verb, dobj}) => verb === "examining" && dobj === "tEp/Xi",
action => looking(), true);
instead_of(({verb, dobj}) => (verb === "entering" && dobj === "tEp/Xi"
&& world.containing_room(world.actor) === "253 Commonwealth Ave"),
action => going("north"), true);
instead_of(({verb, dobj}) => (verb === "entering" && dobj === "tEp/Xi"
&& world.containing_room(world.actor) === "The Backlot"),
action => going("south"), true);
instead_of(({verb, dir}) => (verb === "going" && dir === "in"
&& world.accessible_to("tEp/Xi", world.actor)),
action => entering("tEp/Xi"), true);
def_obj("front garden", "container", {
is_scenery: true,
enterable: true,
description: `[img 1/253/garden.JPG left]This is the front
garden, in which are [the 'purple tree'] and [a 'park bench'].`
}, {put_in: "253 Commonwealth Ave"});
def_obj("purple tree", "thing", {
is_scenery: true,
is_ladder: true,
description: `[img 1/253/tree.JPG left]Looking both ways,
you see that this is the only purple tree along the entire
avenue. It's very purple. Below it is [the 'front garden'].`,
no_enter_msg: `You have a merry time sitting in the tree, and then you get down.`
}, {put_in: "253 Commonwealth Ave"});
def_obj("park bench", "supporter", {
is_scenery: true,
enterable: true,
description: `[img 1/253/bench.jpg left]Sitting in [the 'front garden']
is this handmade park bench wrought from steel, built by a previous tEp/Xi.
After a few years of use, it's been bent quite out of whack.`
}, {put_in: "front garden"});
actions.report.add_method({
when: action => action.verb === "entering" && action.dobj === "park bench",
handle: function (action) {
out.write(`You sit on [the 'park bench'], while the metal twists and bends under
the load, it holds you well enough.`);
}
});
def_obj("front door", "door", {
added_words: ["@doors"],
reported: false,
lockable: true,
description: `[img 1/253/doors.JPG left]It's a big, old
door. Through the glass, you can make out some blinking LED lights
hanging from the stairwell. Why not [action 'knock']?`,
is_locked: () => world.containing_room(world.actor) === "253 Commonwealth Ave"
});
world.no_lock_msg.set("front door", "no_open", `It's locked. Perhaps you
should ring [the doorbell].`);
world.connect_rooms("253 Commonwealth Ave", "north", "The Foyer", {via: "front door"});
def_obj("doorbell", "thing", {
added_words: ["door", "@bell"],
is_scenery: true,
description: `[img 1/253/doorbell.jpg left]It's a small,
black button, and you almost didn't notice it. The FedEx guy
has said he enjoys this doorbell.`
}, {put_in: "253 Commonwealth Ave"});
parser.action.understand("ring/push/press [obj doorbell]", parse => using("doorbell"));
parser.action.understand("knock", parse => {
if (world.containing_room(world.actor) === "253 Commonwealth Ave") {
return making_mistake(`You knock on the front door, but no one hears you.
Perhaps you should [action 'ring the doorbell'].`);
} else {
return undefined;
}
});
actions.before.add_method({
when: action => action.verb === "using" && action.dobj === "doorbell",
handle: function (action) { }
});
actions.carry_out.add_method({
when: action => action.verb === "using" && action.dobj === "doorbell",
handle: function (action) {
world.put_in("player", "The Foyer");
}
});
actions.report.add_method({
when: action => action.verb === "using" && action.dobj === "doorbell",
handle: function (action) {
out.write(`You hear a loud subwoofer buzzing at 32 Hz, and,
after a few moments, footsteps down the stairs. A young xister opens
the door for you and leads you in. "Ah, I see you're getting the
virtual house tour from [ob 'Irving Q. Tep']," they say. "Those
are really good!" Before running off, they bring you to...`);
}
});
actions.try_before.add_method({
when: action => (action.verb === "going" && action.dir === "north"
&& world.containing_room(world.actor) === "253 Commonwealth Ave"),
handle: function (action) {
out.write(`The door is locked. Looking around the door, you find a
doorbell, and you ring that instead.[para]`);
throw new do_instead(using("doorbell"), true);
}
});
def_obj("car", "thing", {
is_scenery: true,
description: `This is one of those cars that the neighbors like to buy.`
}, {put_in: "253 Commonwealth Ave"});
def_obj("front steps", "supporter", {
added_words: ["@stoop"],
enterable: true,
is_scenery: true,
description: `The front steps are a nice place to sit on when the weather's nice.
They lead up to [the 'front door'] and into tEp/Xi.`
}, {put_in: "253 Commonwealth Ave"});
/*******************/
/*** First floor ***/
/*******************/
///
/// The Foyer
///
def_obj("The Foyer", "room", {
description : `[img 1/foyer/look.jpg left]This is the foyer.
You can keep going [dir northwest] to the center room. You
can see [a subwoofer], [ob 'front desk' 'a desk'],
[ob 'colorful lights'],
and [ob 'foyer mirror' 'a large mirror']. Something about
[the mailboxes] catches your eye.`
});
make_known("The Foyer");
add_floor("The Foyer", "tile");
world.connect_rooms("The Foyer", "northwest", "The Center Room");
world.step_turn.add_method({ /* Close the door behind you. */
when: () => world.containing_room(world.actor) === "253 Commonwealth Ave",
handle: function () {
if (world.is_open("front door")) {
out.write("On your way out, the front door closes behind you.[para]");
world.is_open.set("front door", false);
}
this.next();
}
});
instead_of(({verb, dir}) => (verb === "going" && dir === "up"
&& world.containing_room(world.actor) === "The Foyer"),
action => going_to("The Second Landing"), true);
instead_of(({verb, dir}) => (verb === "going" && dir === "out"
&& world.containing_room(world.actor) === "The Foyer"),
action => going("south"), true);
instead_of(({verb, dir}) => (verb === "going" && dir === "north"
&& world.containing_room(world.actor) === "The Foyer"),
action => going("northwest"), true);
instead_of(({verb, dir}) => (verb === "looking toward" && dir === "north"
&& world.containing_room(world.actor) === "The Foyer"),
action => examining("colorful lights"));
instead_of(({verb, dir}) => (verb === "looking toward" && (dir === "west" || dir === "east")
&& world.containing_room(world.actor) === "The Foyer"),
action => examining("foyer mirror"));
def_obj("subwoofer", "thing", {
is_scenery: true,
no_take_msg: "The subwoofer is too heavy to carry with you.",
description: `[img 1/foyer/subwoofer.JPG left]This is the
combination subwoofer and frequency generator that emits the
32 Hz buzz for the doorbell.`
}, {put_in: "The Foyer"});
def_obj("front desk", "thing", {
is_scenery: true,
description: `[img 1/foyer/desk.JPG left]This is the front
desk, upon which is a cheap computer that people use to check
bus schedules or show people YouTube videos.`
}, {put_in: "The Foyer"});
def_obj("key box", "thing", {
is_scenery: true,
description: `[img 1/foyer/keybox.JPG left]This box of car
keys has a place for every parking spot out back. It helps
prevent people from getting boxed in.`
}, {put_in: "The Foyer"});
def_obj("colorful lights", "thing", {
words: ["colorful", "color", "changing", "color-changing", "@lights"],
is_scenery: true,
description: `[img 1/foyer/lights.jpg left]These are the
color-changing lights you could see from out front.`
}, {put_in: "The Foyer"});
def_obj("mailboxes", "container", {
words: ["mail", "@box", "@boxes", "@mailboxes", "@mailbox"],
is_scenery: true,
description: `[img 1/foyer/mailboxes_2024.jpg left]These boxes
hold mail of current xisters, past tEp/Xis, and summer renters.
Most of the names seem to blur into nothingness, but [ask 'honig' 'one name
in particular stands out to you'].`,
no_take_msg: "That mail is not yours."
}, {put_in: "The Foyer"});
all_are_mistakes(["steal [obj mailboxes]"], `Virtual house tour or not, that is a felony.`);
def_obj("foyer mirror", "thing", {
name: "large mirror",
is_scenery: true,
description: `[img 1/foyer/mirror.JPG left]This is one of
the two large mirrors in the foyer. In it you can see the
other one.`
}, {put_in: "The Foyer"});
def_obj("Op box", "supporter", {
printed_name: "the Op box",
added_words: ["out", "@outbox"],
enterable: true,
proper_named: true,
description : `[img 1/foyer/opbox_2024.jpg left]The Op box is
named after Charles Oppenheimer, the first Captain tEp/Xi. It is
the platform upon which the captain stands to greet his
numerous fans. Because it sits outside of tEp/Xi during rush, it
is also known as the outbox.`,
locale_description : `From atop the Op box, you feel a
powerful urge to find purple spandex tights and put them on.` // TODO have tights somewhere
}, {put_in: "The Foyer"});
///
/// Center Room
///
//TODO: add j'office
def_obj("The Center Room", "room", {
description: `[img 1/center/look_2024.jpg left]This is the
center room, which is a common area at tEp/Xi. Around you are
composite photos from the past decade, and [a 'chandelier']
that seems like it has seen better days. Looking up, you can
see the [ob 'center stairwell'].
[para]You can go [dir south] to the front room, [dir north]
to the dining room, [dir upstairs] to the second floor, [dir
northnortheast] to the back stairwell, or [dir southeast] back to
the foyer, and you can look [look north], [look south],
[look east], [look west], and [look up].`
});
add_floor("The Center Room", "carpet");
make_known("The Center Room");
world.connect_rooms("The Center Room", "up", "The Second Landing");
world.connect_rooms("The Center Room", "south", "The Front Room");
world.connect_rooms("The Center Room", "north", "The Dining Room");
world.connect_rooms("The Center Room", "northeast", "J'Office");
world.connect_rooms("The Center Room", "northnortheast", "back_stairwell_1");
world.direction_description.set("The Center Room", "north", `
[img 1/center/look_n_2024.jpg left]You see the comfy couch,
[the king], [the 'floof'], [the 'bulletin board']. You
can go [dir north] into the dining room, [dir northeast] to the J'Office,
and [dir northnortheast] into the back stairwell.`);
world.direction_description.set("The Center Room", "east", `
[img 1/center/look_e_2024.jpg left]You can see
[the 'floof']. You can go [dir upstairs] to the second landing, [dir northeast]
to the J'Office, and [dir southeast] into the foyer.`);
world.direction_description.set("The Center Room", "south", `
[img 1/center/look_s_2024.jpg left]In the corner is [a 'player piano'].
On the wall is [a 'zombie protection box']. You can go [dir southeast]
into the foyer and [dir south] into the front room.`);
world.direction_description.set("The Center Room", "west", `
[img 1/center/look_w_2024.jpg left]You can see the comfy couch and the
Xi board where xiblings post announcements, jokes, and silly images`);
world.direction_description.set("The Center Room", "up", `
[img 1/center/stairwell.JPG left]Looking up, you see the center
stairwell, which is three flights of stairs capped by a skylight. The
color-changing lights illuminate it dramatically.`);
def_obj("bulletin board", "thing", {
is_scenery: true,
description : `[img 1/center/bulletin_2024.jpg left]This is a
bulletin board on which tEp/Xis affix funny things they found in
the mail, cute things prefrosh wrote, pictures, postcards from
[ask 'druler' drooling] alumni, and other miscellaneous artifacts.`
// TODO every time you look you see a description of an interesting thing on the board
}, {put_in: "The Center Room"});
def_obj("floof", "supporter", {
added_words: ["@beanbag"],
is_scenery: true,
enterable: true,
description: `[img 1/center/floof_2024.jpg left]This is a nice place to rest
after a long day of work. It's also a great place to drop things onto from the
center stairwell. Just make sure to yell "DROP" first!`
}, {put_in: "The Center Room"});
//TODO: closer image of piano
//TODO: capability to play the piano
def_obj("player piano", "thing", {
is_scenery: true,
description: `[img 1/center/playerpiano_2024.jpg left]An xibling long ago got the house
a player piano. As things in this house tend to do, it broke. Later xiblings found
another player piano being donated so we have a piano again. It can be played regularly
or you can place one of our many scrolls in and have it play by itself.`
}, {put_in: "The Center Room"});
// def_obj("comfy couch", "supporter", {
// added_words: ["@sofa"],
// is_scenery: true,
// enterable: true,
// description: `[img 1/center/couch.JPG left]This is perhaps
// the comfiest couch in all of existence. A neighbor came by
// one day and said, "hey, you're a fraternity, so you probably
// like couches. I have a couch." With his help, we then
// brought it to its present location. True couch aficionados
// make a pilgrimage to our center room at least twice a year.`
// }, {put_in: "The Center Room"});
// def_obj("foosball table", "container", {
// added_words: ["foos", "fooz"],
// is_scenery: true,
// openable: true,
// suppress_content_description: (x) => !world.is_open(x),
// description : `[img 1/center/foosball.JPG left]This is a
// commercial-quality foosball table which is covered with flecks
// of colorful paint that, while making it look cool under color
// changing lights, make it hard to play foosball. Alumni have
// looked at it and remininsced to one another, "remember how
// much the foosball table cost us when we got it?"`
// }, {put_in: "The Center Room"});
// def_obj("human skull", "thing", {
// description : `This is a human skull, but it's missing its
// jaw from when some Nokia engineers were playing with it at
// [ask 'hot cocoa' cocoa] one Monday night. It's unknown why there is such a
// thing in the house.`
// }, {put_in: "foosball table"});
// parser.action.understand("play [obj 'foosball table']", action => using("foosball table"));
// actions.before.add_method({
// when: ({verb,dobj}) => verb === "using" && dobj === "foosball table",
// handle: () => {}
// });
// actions.report.add_method({
// when: ({verb,dobj}) => verb === "using" && dobj === "foosball table",
// handle: function () {
// out.write(`"Click! Click!" go the volleys as the ball skids
// across the surface of the foosball table, with some non-negligible
// interference from all the colorful paint. It's a close match, but
// your dexterity at the table is impressive! The game reaches
// sudden death, and your feet playing yellow narrowly beat your
// hands playing black. The handshake is confusing, and your hands
// and feet decide to make it brief. Good show.`);
// }
// });
def_obj("king", "thing", {
printed_name : "The King",
proper_named : true,
is_scenery : true,
no_take_msg: `That's always been there. You shouldn't move it.`, // TODO puzzle to move it?
description: `[img 1/center/king.JPG left]It's a portrait
of The King (that is, Elvis Presley to you younger folk on the
tour), modeled after a ceramic bust that met an explosive end.
[para]It's always been there. According to rumors, it appeared sometime
during the Back Bay reclamation project in this exact position, and, in a move
prefiguring Frank Lloyd Wright, the architect built the house around it.
How an image of Presley was produced in the 19th century is uncertain.`
}, {put_in: "The Center Room"});
def_obj("mantle", "supporter", {
is_scenery: true,
description : `[img 1/center/mantle.JPG left]The mantle
contains random things like awards for our GPA, plaques for
people who won scholarships ten years ago, and a copy of the
MIT yearbook from the 1970s.`
}, {put_in: "The Center Room"});
def_obj("zombie protection box", "thing", {
is_scenery: true,
description: `[img 1/center/zombie.JPG left]This was
recently installed to bring tEp/Xi up to zombie code.`
}, {put_in: "The Center Room"});
def_obj("chandelier", "thing", {
is_scenery: true,
description: `[img 1/center/chandelier.JPG left]This
chandelier, which is affixed to the center of the ceiling, has
clearly been [ask eit eited] many times over the years by the
game of [ask stupidball]. One time, during one particularly
rousing game, all of the sconces exploded simultaneously in a shower of
glittering glass. It was really a sight to see.`
}, {put_in: "The Center Room"});
def_obj("ex_ball", "supporter", {
name: "large green exercise ball",
words: ["big", "large", "green", "exercise", "stupid", "@ball", "@stupidball"],
enterable: true,
description: `[img 1/center/stupidball.jpg]This is a large
green exercise ball that is used to play [ask stupidball].`
}, {put_in: "The Center Room"});
parser.action.understand("play/kick/throw/bounce [obj ex_ball]",
parse => using("ex_ball"));
actions.before.add_method({
when: ({verb,dobj}) => verb === "using" && dobj === "ex_ball",
handle: () => {}
});
actions.report.add_method({
when: ({verb,dobj}) => verb === "using" && dobj === "ex_ball",
handle: function () {
out.write(`A couple of teps come out to join playing [ask stupidball]
you as you kick [the ex_ball] around the room, and you nearly break a
couple of things as the ball whizzes through the air at high velocities.
After much merriment, you all get bored of the game, and put the
ball down.`);
}
});
actions.report.add_method({
when: ({verb,dobj}) => verb === "dropping" && dobj === "ex_ball",
handle: function (action) {
out.write("It bounces a few times before it settles down.");
}
});
world.global.set("ex_ball jump", 0);
actions.carry_out.add_method({
when: action => action.verb === "jumping" && world.location(world.actor) === "ex_ball",
handle: function (action) {
var i = world.global("ex_ball jump");
world.global.set("ex_ball jump", i + 1);
if (i % 2 === 0) {
world.put_in(world.actor, world.parent_enterable("ex_ball"));
action.jump_from = "ex_ball";
}
}