diff --git a/README.md b/README.md
index 60b2f0da..866374ae 100644
--- a/README.md
+++ b/README.md
@@ -51,6 +51,7 @@ The IDE uses custom forks for many of these, found at https://github.com/sehugg?
* https://github.com/floooh/chips
* https://github.com/DrGoldfire/Z80.js
* http://www.twitchasylum.com/jsvecx/
+* https://github.com/curiousdannii/ifvms.js/
### Compilers
@@ -60,6 +61,7 @@ The IDE uses custom forks for many of these, found at https://github.com/sehugg?
* https://github.com/batari-Basic/batari-Basic
* https://www.veripool.org/wiki/verilator
* http://mcpp.sourceforge.net/
+* http://www.ifarchive.org/indexes/if-archiveXinfocomXcompilersXinform6.html
### Assemblers/Linkers
diff --git a/css/ui.css b/css/ui.css
index 7637994a..5edbf832 100644
--- a/css/ui.css
+++ b/css/ui.css
@@ -568,4 +568,49 @@ div.asset_toolbar {
font-family: "Andale Mono", "Menlo", "Lucida Console", monospace;
font-size: 10pt;
line-height: 1.2;
-}
\ No newline at end of file
+}
+.transcript {
+ background-color: #fff;
+ width: 100%;
+ padding: 1.25em;
+ user-select: text;
+ font-family: Verdana, Geneva, sans-serif;
+}
+.transcript-line {
+ line-height: 1.5;
+ min-height: 1em;
+ white-space: pre-wrap;
+}
+.transcript-style-1 {
+ font-style: italic;
+}
+.transcript-style-2 {
+ white-space: pre-wrap; /* css-3 */
+ font-family: "Andale Mono", "Menlo", "Lucida Console", monospace;
+ line-height: 1;
+ min-height: 0;
+}
+.transcript-style-4 {
+ font-weight: bold;
+}
+.transcript-style-8 { /* input */
+ font-weight: bold;
+ font-variant: small-caps;
+ color: #6666ff;
+ background-color: #eeeeff;
+ padding: 0.25em;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+}
+.transcript-reverse {
+ background-color: #666;
+ color: #ddd;
+}
+.transcript-input {
+ margin:1%;
+ font-weight: bold;
+ font-variant: small-caps;
+ color: #6666ff;
+ background-color: #eeeeff;
+}
+
\ No newline at end of file
diff --git a/index.html b/index.html
index c5986c07..c3498a83 100644
--- a/index.html
+++ b/index.html
@@ -218,6 +218,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
Atari 5200 (MAME)
Atari Color Vector (6502)
Markdown
+ Z-Machine (Inform 6)
@@ -311,6 +312,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
+
@@ -538,6 +540,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
+
diff --git a/lib/zvm/ifvms.min.js b/lib/zvm/ifvms.min.js
new file mode 100644
index 00000000..77e4e42f
--- /dev/null
+++ b/lib/zvm/ifvms.min.js
@@ -0,0 +1,3 @@
+/* ZVM v https://github.com/curiousdannii/ifvms.js */
+(function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"==typeof window?"undefined"==typeof global?"undefined"==typeof self?this:self:global:window,t.ZVM=e()}})(function(){var e=Math.min,t=String.fromCharCode;return function(){function s(l,e,r){function t(o,i){if(!e[o]){if(!l[o]){var _="function"==typeof require&&require;if(!i&&_)return _(o,!0);if(n)return n(o,!0);var g=new Error("Cannot find module '"+o+"'");throw g.code="MODULE_NOT_FOUND",g}var a=e[o]={exports:{}};l[o][0].call(a.exports,function(e){var s=l[o][1][e];return t(s||e)},a,a.exports,s,l,e,r)}return e[o].exports}for(var n="function"==typeof require&&require,a=0;a
--e?"l["+e+"]":"e.m.getUint16("+(this.e.globals+2*(e-15))+")"},store:function(e){var t=this.v;return this.indirect?"e.indirect("+t+","+e+")":this.returnval?"e.variable("+t+","+e+")":0===t?"t="+e+";s[e.sp++]=t":15>--t?"l["+t+"]="+e:"e.ram.setUint16("+(this.e.globals+2*(t-15))+","+e+")"},U2S:function(){return"e.U2S("+this+")"}}),o=r.subClass({init:function(e,t,s,r,i,n){this.e=e,this.context=t,this.code=s,this.pc=r,this.labels=[this.pc+"/"+this.code],this.next=i,this.operands=n,this.post&&this.post()},toString:function(){return this.label()+(this.func?this.func.apply(this,this.operands):"")},args:function(e){return this.operands.join(e)},label:function(){return"/* "+this.labels.join()+" */ "}}),l=o.subClass({stopper:1}),p=l.subClass({post:function(){this.origfunc=this.func,this.func=this.newfunc},newfunc:function(){return"e.stop=1;e.pc="+this.next+";"+this.origfunc.apply(this,arguments)}}),_=p.subClass({storer:1,post:function(){this.storer=this.operands.pop(),this.origfunc=this.func,this.func=this.newfunc}}),g=r.subClass({init:function(e,t){this.ops=e||[],this.code=t||"||"},toString:function(){for(var e,t=0,s=[];ts||s+a>t)throw new Error("IFF chunk out of range");this.chunks.push({type:n.getFourCC(a),offset:a,data:n.getUint8Array(a+8,s)}),a+=8+s,s%2&&a++}}},write:function(){for(var e,t,s=12,n=0,i=12;ni&&(s="ZCOD")),s&&i)return{format:s,version:i,data:e}}}},{"./utils.js":3}],3:[function(e,s){"use strict";function r(){for(var e,t,s=arguments[0],r=1;r>16},S2U16:function(e){return 65535&e},Uint8toUint16Array:n}},{}],4:[function(e,t){"use strict";var s=e("./common/utils.js"),r=e("./common/file.js"),i={stack_len:100000,undo_len:1000000},n=s.Class.subClass(s.extend({init:function(){this.jit={},this.init=this.start},prepare:function(e,t){if(!t.Glk)throw new Error("A reference to Glk is required");this.Glk=t.Glk,this.data=e,this.options=s.extend({},i,t)},start:function(){var e,t=this.Glk;try{if(e=r.identify(this.data),delete this.data,!e||"ZCOD"!==e.format)throw new Error("This is not a Z-Code file");if(0>[3,4,5,8].indexOf(e.version))throw new Error("Unsupported Z-Machine version: "+e.version);this.m=s.MemoryView(e.data),this.staticmem=this.m.getUint16(14),this.ram=s.MemoryView(this.m,0,this.staticmem),this.origram=this.m.getUint8Array(0,this.staticmem);let n="",a=0;for(;30>a;)n+=(16>this.origram[a]?"0":"")+this.origram[a++].toString(16);this.signature=n;let i;const o=this.options.Dialog;if(o)if(this.options.clear_vm_autosave)o.autosave_write(n,null);else if(this.options.do_vm_autosave)try{const e=o.autosave_read(n);e&&(this.do_autorestore(e),i=1)}catch(e){this.log("Autorestore failed, deleting it"),o.autosave_write(n,null)}i||(this.restart(),this.run()),this.quit||(this.glk_event=new t.RefStruct,this.glk_blocking_call?this.glk_event.push_field(this.glk_blocking_call):t.glk_select(this.glk_event)),t.update()}catch(s){t.fatal_error(s),console.log(s)}},resume:function(e){var t,s,r=this.Glk,i=this.glk_event;try{t=i.get_field(0),2===t&&(this.handle_char_input(i.get_field(2)),s=1),3===t&&(this.handle_line_input(i.get_field(2),i.get_field(3)),s=1),5===t&&this.update_screen_size(),"fileref_create_by_prompt"===t&&(s=this.handle_create_fileref(e)),this.glk_blocking_call=null,s&&this.run(),this.quit||(this.glk_event=new r.RefStruct,this.glk_blocking_call?this.glk_event.push_field(this.glk_blocking_call):r.glk_select(this.glk_event)),r.update()}catch(t){r.fatal_error(t),console.log(t)}},get_signature:function(){return this.signature},run:function(){var e,t;for(this.stop=0;!this.stop;)e=this.pc,this.jit[e]||this.compile(),t=this.jit[e](this),isNaN(t)||this.ret(t)},compile:function(){var e=this.disassemble();this.jit[e.pc]=new Function("e",""+e),e.pcs;s++)t.push((192&e)>>6),e<<=2}for(var t,r,i,n,a,o,l,p=this.m,_=this.opcodes,g=new s.RoutineContext(this,this.pc);;){if(r=t=this.pc,n=p.getUint8(t++),190===n?(o=-1,n=p.getUint8(t++)+1e3):128&n?64&n?(o=-1,!(32&n)&&(n&=31)):(o=[(48&n)>>4],3>o[0]&&(n&=207)):(o=[64&n?2:1,32&n?2:1],n&=31),!_[n])throw this.log(""+g),this.stop=1,new Error("Unknown opcode #"+n+" at pc="+r);for(a=_[n].prototype,-1===o&&(o=[],e(p.getUint8(t++),o),(236===n||250===n)&&e(p.getUint8(t++),o)),l=[],i=0;i>18])),a.printer)for(l.push(t);t>5]<<8|t[(31744&e)>>10]}const n=s("../common/utils.js"),a=n.U2S16,o=function(){for(var e={4294967283:146,4294967284:152,4294967285:148,4294967286:154,4294967288:27,4294967289:8,4294967290:13,4294967291:130,4294967292:129,4294967293:132,4294967294:131},t=0;12>t;)e[4294967279-t]=133+t++;return e}(),l=[0,2,1,10,4,9,5,6],p=[65534,65535,0,29,832,957,22944,31775,30624,32767,23254,17969,11627];r.exports={init_io:function(){this.io=this.io||{reverse:0,bold:0,italic:0,mono:2&this.m.getUint8(17),transcript:1&this.m.getUint8(17),streams:[0,1,{},[],{}],currentwin:0,height:0,maxheight:0,seenheight:0,width:0,row:0,col:0},this.open_windows()},erase_line:function(e){if(1===e){var t=this.io,s=t.row,r=t.col;this._print(Array(t.width-t.col+1).join(" ")),this.set_cursor(s,r)}},erase_window:function(e){1>e&&this.Glk.glk_window_clear(this.mainwin),(1===e||-2===e)&&this.upperwin&&(this.Glk.glk_window_clear(this.upperwin),this.set_cursor(0,0)),-1===e&&this.split_window(0)},fileref_create_by_prompt:function(e){"undefined"==typeof e.run&&(e.run=1),this.fileref_data=e,this.glk_blocking_call="fileref_create_by_prompt",this.Glk.glk_fileref_create_by_prompt(e.usage,e.mode,e.rock||0)},fix_upper_window:function(){var e=this.Glk,t=this.io;t.seenheight>=t.maxheight&&(t.maxheight=t.height),this.upperwin&&(0===t.maxheight?(e.glk_window_close(this.upperwin),this.upperwin=null):e.glk_window_set_arrangement(e.glk_window_get_parent(this.upperwin),18,t.maxheight,null)),t.seenheight=t.maxheight,t.maxheight=t.height},format:function(){this.Glk.glk_set_style(l[!!this.io.mono|this.io.italic|this.io.bold]),this.Glk.glk_gestalt(4352,0)&&this.Glk.garglk_set_reversevideo(this.io.reverse)},get_cursor:function(e){this.ram.setUint16(e,this.io.row+1),this.ram.setUint16(e+2,this.io.col+1)},handle_char_input:function(e){var t=this.io.streams[4],s=o[e]||this.reverse_unicode_table[e]||63;this.variable(this.read_data.storer,s),1===t.mode&&(t.cache+=s),2===t.mode&&this.Glk.glk_put_char_stream_uni(t.str,s)},handle_create_fileref:function(e){var t,s=this.Glk,r=this.fileref_data;return e&&(t=r.unicode?s.glk_stream_open_file_uni(e,r.mode,r.rock||0):s.glk_stream_open_file(e,r.mode,r.rock||0),s.glk_fileref_destroy(e)),("restore"===r.func||"save"===r.func)&&this.save_restore_handler(t),"input_stream"===r.func&&(this.io.streams[0]=t),"output_stream"===r.func&&this.output_stream_handler(t),r.run},handle_line_input:function(e,s){var r=this.ram,i=this.read_data,n=this.io.streams,a=t.apply(null,i.buffer.slice(0,e))+"\n",o=this.text_to_zscii(a.slice(0,-1).toLowerCase());1===n[2].mode&&(n[2].cache+=a),2===n[2].mode&&this.Glk.glk_put_jstring_stream(n[2].str,a),1===n[4].mode&&(n[4].cache+=a),2===n[4].mode&&this.Glk.glk_put_jstring_stream(n[4].str,a),5>this.version?(o.push(0),r.setUint8Array(i.bufaddr+1,o)):(r.setUint8(i.bufaddr+1,e),r.setUint8Array(i.bufaddr+2,o),this.variable(i.storer,isNaN(s)?13:s)),i.parseaddr&&this.tokenise(i.bufaddr,i.parseaddr)},input_stream:function(e){var t=this.io;e&&!t.streams[0]&&this.fileref_create_by_prompt({func:"input_stream",mode:2,rock:212,unicode:1,usage:259}),!e&&t.streams[0]&&(this.Glk.glk_stream_close(t.streams[0]),t.streams[0]=0)},open_windows:function(){if(!this.mainwin){const e=this.Glk,t=[1,2,4,5,6,9,10];for(let s=0;7>s;s++)e.glk_stylehint_set(0,t[s],3,0),e.glk_stylehint_set(0,t[s],4,0),e.glk_stylehint_set(0,t[s],5,0),e.glk_stylehint_set(0,t[s],6,1);e.glk_stylehint_set(0,4,4,1),e.glk_stylehint_set(0,1,5,1),e.glk_stylehint_set(0,5,4,1),e.glk_stylehint_set(0,5,5,1),e.glk_stylehint_set(0,2,6,0),e.glk_stylehint_set(0,9,4,1),e.glk_stylehint_set(0,9,6,0),e.glk_stylehint_set(0,10,5,1),e.glk_stylehint_set(0,10,6,0),e.glk_stylehint_set(0,6,4,1),e.glk_stylehint_set(0,6,5,1),e.glk_stylehint_set(0,6,6,0),this.mainwin=e.glk_window_open(0,0,0,3,201),e.glk_set_window(this.mainwin),this.version3&&(this.statuswin=e.glk_window_open(this.mainwin,18,1,4,202),this.statuswin&&e.garglk_set_reversevideo_stream(e.glk_window_get_stream(this.statuswin),1))}},output_stream:function(e,t,s){var r,i,n=this.ram,o=this.io.streams;e=a(e),1===e&&(o[1]=1),-1===e&&(o[1]=0),2!==e||o[2].mode||(this.fileref_create_by_prompt({func:"output_stream",mode:5,rock:210,run:!s,str:2,unicode:1,usage:258}),o[2].cache="",o[2].mode=1,!s&&(this.stop=1)),-2===e&&(n.setUint8(17,254&n.getUint8(17)),2===o[2].mode&&this.Glk.glk_stream_close(o[2].str),o[2].mode=this.io.transcript=0),3===e&&o[3].unshift([t,""]),-3===e&&(r=o[3].shift(),i=this.text_to_zscii(r[1]),n.setUint16(r[0],i.length),n.setUint8Array(r[0]+2,i)),4!==e||o[4].mode||(this.fileref_create_by_prompt({func:"output_stream",mode:5,rock:211,str:4,unicode:1,usage:259}),o[4].cache="",o[4].mode=1,this.stop=1),-4===e&&(2===o[4].mode&&this.Glk.glk_stream_close(o[4].str),o[4].mode=0)},output_stream_handler:function(e){var t=this.ram,s=this.io.streams,r=this.fileref_data;2===r.str&&(t.setUint8(17,254&t.getUint8(17)|(e?1:0)),e?(s[2].mode=2,s[2].str=e,this.io.transcript=1,s[2].cache&&this.Glk.glk_put_jstring_stream(s[2].str,s[2].cache)):s[2].mode=this.io.transcript=0),4===r.str&&(e?(s[4].mode=2,s[4].str=e,s[4].cache&&this.Glk.glk_put_jstring_stream(s[4].str,s[4].cache)):s[4].mode=0)},_print:function(e){var t=this.Glk,s=this.io,r=0;if(s.streams[3].length)s.streams[3][0][1]+=e;else if(e=e.replace(/\r/g,"\n"),(1&this.m.getUint8(17))!==s.transcript&&this.output_stream(s.transcript?-2:2,0,1),(2&this.m.getUint8(17))!=(2&s.mono)&&(s.mono^=2,this.format()),s.currentwin&&this.upperwin)for(;r=s.height&&this.split_window(e+1),this.upperwin&&0<=e&&0<=t&&ta){for(t=s.glk_window_get_stream(this.upperwin);ar.maxheight&&(r.maxheight=e,this.upperwin?s.glk_window_set_arrangement(s.glk_window_get_parent(this.upperwin),18,r.maxheight,null):this.upperwin=s.glk_window_open(this.mainwin,18,r.maxheight,4,203)),e&&(r.row>=e&&this.set_cursor(0,0),this.version3&&s.glk_window_clear(this.upperwin))},update_header:function(){var e=this.ram;return this.xorshift_seed=0,this.update_screen_size(),this.version3?e.setUint8(1,64|(143&e.getUint8(1)|(this.statuswin?32:16))):void(e.setUint8(1,0|(28|(this.Glk.glk_gestalt(4352,0)?1:0))),e.setUint8(17,87&e.getUint8(17)),4=a&&(this.io.col=a-1)},v3_status:function(){if(this.statuswin){var e,t=this.Glk,s=t.glk_window_get_stream(this.statuswin),r=this.m,i=this.io.width,n=r.getUint16(this.globals+2),a=r.getUint16(this.globals+4),o=r.getUint16(this.objects+9*r.getUint16(this.globals)+7),l=""+this.decode(o+1,2*r.getUint8(o));e=2&r.getUint8(1)?"Time: "+(0==n%12?12:n%12)+":"+(10>a?"0":"")+a+" "+(11t?"e.s[e.sp-1]":"e.l["+t+"]")+(1==s?"++":"--")}}),b=n.subClass({brancher:1,toString:function(){return"e.stop=1;e."+(181===this.code?"save":"restore")+"("+(this.pc+1)+")"}}),w=c(o,function(){return"e.restore("+(this.next-1)+")"}),v=c(o,function(){return"e.save("+(this.next-1)+")"});t.exports=function(e){return{1:c(l,function(){return 2===arguments.length?this.args("==="):"e.jeq("+this.args()+")"}),2:c(l,function(e,t){return e.U2S()+"<"+t.U2S()}),3:c(l,function(e,t){return e.U2S()+">"+t.U2S()}),4:c(l,function(e,t){return"e.U2S(e.incdec("+e+",-1))<"+t.U2S()}),5:c(l,function(e,t){return"e.U2S(e.incdec("+e+",1))>"+t.U2S()}),6:c(l,function(){return"e.jin("+this.args()+")"}),7:c(l,function(){return"e.test("+this.args()+")"}),8:c(_,function(){return this.args("|")}),9:c(_,function(){return this.args("&")}),10:c(l,function(){return"e.test_attr("+this.args()+")"}),11:c(i,function(){return"e.set_attr("+this.args()+")"}),12:c(i,function(){return"e.clear_attr("+this.args()+")"}),13:U,14:c(i,function(){return"e.insert_obj("+this.args()+")"}),15:c(_,function(e,t){return"e.m.getUint16(e.S2U("+e+"+2*"+t.U2S()+"))"}),16:c(_,function(e,t){return"e.m.getUint8(e.S2U("+e+"+"+t.U2S()+"))"}),17:c(_,function(){return"e.get_prop("+this.args()+")"}),18:c(_,function(){return"e.find_prop("+this.args()+")"}),19:c(_,function(){return"e.find_prop("+this.args(",0,")+")"}),20:c(_,function(){return"e.S2U("+this.args("+")+")"}),21:c(_,function(){return"e.S2U("+this.args("-")+")"}),22:c(_,function(){return"e.S2U("+this.args("*")+")"}),23:c(_,function(e,t){return"e.S2U(parseInt("+e.U2S()+"/"+t.U2S()+"))"}),24:c(_,function(e,t){return"e.S2U("+e.U2S()+"%"+t.U2S()+")"}),25:u,26:g,27:c(i,function(){return"e.set_colour("+this.args()+")"}),28:c(n,function(e,t){return"while(e.frames.length+1>"+t+"){e.frameptr=e.frames.pop()}return "+e}),128:c(l,function(e){return e+"===0"}),129:c(p,function(e){return"e.get_sibling("+e+")"}),130:c(p,function(e){return"e.get_child("+e+")"}),131:c(_,function(e){return"e.get_parent("+e+")"}),132:c(_,function(e){return"e.get_prop_len("+e+")"}),133:k,134:k,135:c(i,function(e){return"e.print(2,"+e+")"}),136:u,137:c(i,function(e){return"e.remove_obj("+e+")"}),138:c(i,function(e){return"e.print(3,"+e+")"}),139:c(n,function(e){return"return "+e}),140:c(n,function(e){return"e.pc="+e.U2S()+"+"+(this.next-2)}),141:c(i,function(e){return"e.print(2,"+e+"*"+this.e.addr_multipler+")"}),142:U.subClass({storer:1}),143:5>e?h:g,176:c(n,function(){return"return 1"}),177:c(n,function(){return"return 0"}),178:c(i,function(e){return"e.print(2,"+e+")"},{printer:1}),179:c(n,function(e){return"e.print(2,"+e+");e.print(1,13);return 1"},{printer:1}),180:i,181:4>e?b:v,182:4>e?b:w,183:c(n,function(){return"e.erase_window(-1);e.restart()"}),184:c(n,function(e){return"return "+e},{post:function(){this.operands.push(m)}}),185:5>e?c(i,function(){return"s[--e.sp]"}):c(_,function(){return"e.frames.length+1"}),186:c(a,function(){return"e.quit=1;e.Glk.glk_exit()"}),187:c(i,function(){return"e.print(1,13)"}),188:4>e?c(n,function(){return"e.pc="+this.next+";e.v3_status()"}):i,189:f,191:f,224:u,225:c(i,function(e,t,s){return"e.ram.setUint16(e.S2U("+e+"+2*"+t.U2S()+"),"+s+")"}),226:c(i,function(e,t,s){return"e.ram.setUint8(e.S2U("+e+"+"+t.U2S()+"),"+s+")"}),227:c(i,function(){return"e.put_prop("+this.args()+")"}),228:5>e?c(a,function(){return"e.read(0,"+this.args()+")"}):c(o,function(){return"e.read("+this.storer.v+","+this.args()+")"}),229:c(i,function(e){return"e.print(4,"+e+")"}),230:c(i,function(e){return"e.print(0,"+e.U2S()+")"}),231:c(_,function(e){return"e.random("+e.U2S()+")"}),232:c(_,d,{post:function(){this.storer=m},storer:0}),233:U,234:c(i,function(e){return"e.split_window("+e+")"}),235:c(i,function(e){return"e.set_window("+e+")"}),236:u,237:c(i,function(e){return"e.erase_window("+e.U2S()+")"}),238:c(i,function(e){return"e.erase_line("+e+")"}),239:c(i,function(e,t){return"e.set_cursor("+e+"-1,"+t+"-1)"}),240:c(i,function(e){return"e.get_cursor("+e+")"}),241:c(i,function(e){return"e.set_style("+e+")"}),242:i,243:c(n,function(){return"e.pc="+this.next+";e.output_stream("+this.args()+")"}),244:c(a,function(){return"e.input_stream("+this.args()+")"}),245:i,246:c(o,function(){return"e.read_char("+this.storer.v+","+(this.args()||"1")+")"}),247:c(p,function(){return"e.scan_table("+this.args()+")"}),248:h,249:g,250:g,251:c(i,function(){return"e.tokenise("+this.args()+")"}),252:c(i,function(){return"e.encode_text("+this.args()+")"}),253:c(i,function(){return"e.copy_table("+this.args()+")"}),254:c(i,function(){return"e.print_table("+this.args()+")"}),255:c(l,function(e){return"e.stack.getUint8(e.frameptr+5)&(1<<("+e+"-1))"}),1e3:v,1001:w,1002:c(_,function(e,t){return"e.S2U(e.log_shift("+e+","+t.U2S()+"))"}),1003:c(_,function(e,t){return"e.S2U(e.art_shift("+e.U2S()+","+t.U2S()+"))"}),1004:c(_,function(e){return"e.set_font("+e+")"}),1009:c(_,function(){return"e.save_undo("+this.next+","+this.storer.v+")"}),1010:c(i,function(){return"if(e.restore_undo())return"},{storer:1}),1011:c(i,function(e){return"e.print(1,"+e+")"}),1012:c(_,function(){return 3}),1013:c(i,function(){return"e.set_true_colour("+this.args()+")"}),1014:i.subClass({brancher:1}),1030:c(_,function(){return"e.gestalt("+this.args()+")"})}}},{"../common/ast.js":1}],8:[function(e,t){"use strict";function s(e){const t=(e)=>"object"==typeof e?s(e):e,r={};if(Array.isArray(e))return e.map(t);for(let s in e)"buffer"!=s&&"str"!=s&&(r[s]=t(e[s]));return r}function r(e,t,s,r){if(p&&!r)for(;t>-t},call:function(e,t,s,r){if(0===e)return 0<=t&&this.variable(t,0),this.pc=s;this.pc=e*this.addr_multipler;var n=this.m.getUint8(this.pc++),a=this.stack,o=0,i=this.frameptr;for(a.setUint16(i+6,this.sp),this.frames.push(i),i=this.frameptr=this.s.byteOffset+2*this.sp,a.setUint32(i,s<<8),a.setUint8(i+3,(0<=t?0:16)|n),a.setUint8(i+4,0<=t?t:0),a.setUint8(i+5,(1<this.version?this.m.getUint16(this.pc+2*o):0,o++;5>this.version&&(this.pc+=2*n)},clear_attr:function(e,t){var s=0|this.objects+(this.version3?9:14)*e+t/8;this.ram.setUint8(s,this.m.getUint8(s)&~(128>>t%8))},copy_table:function(e,t,s){s=o(s);var r=this.ram,n=0,i=0>s;if(s=Math.abs(s),0===t){for(;nthis.extension_count?0:(s+=2*e,void 0===t?this.m.getUint16(s):void this.ram.setUint16(s,t))},find_prop:function(e,t,s){var r,i,n=this.m,a=this.version3,o=0,l=n.getUint16(this.objects+(a?9:14)*e+(a?7:12));for(l+=2*n.getUint8(l)+1;;){if(r=n.getUint8(l),i=r&(a?31:63),o===s)return i;if(i===t)return l+(!a&&128&r?2:1);if(i>5)+2:128&r?(i=63&n.getUint8(l+1),l+=i?i+2:66):l+=64&r?3:2}},gestalt:function(e){return 1===e?258:0},get_child:function(e){return this.version3?this.m.getUint8(this.objects+9*e+6):this.m.getUint16(this.objects+14*e+10)},get_sibling:function(e){return this.version3?this.m.getUint8(this.objects+9*e+5):this.m.getUint16(this.objects+14*e+8)},get_parent:function(e){return this.version3?this.m.getUint8(this.objects+9*e+4):this.m.getUint16(this.objects+14*e+6)},get_prop:function(e,t){var s,r=this.m,i=this.find_prop(e,t);return i?(s=r.getUint8(i-1),r[(this.version3?s>>5:64&s)?"getUint16":"getUint8"](i)):r.getUint16(this.properties+2*(t-1))},get_prop_len:function(e){if(0===e)return 0;var t=this.m.getUint8(e-1);return this.version3?(t>>5)+1:128&t?(t&=63,0===t?64:t):64&t?2:1},incdec:function(e,t){if(0===e)return this.s[this.sp-1]+=t,this.s[this.sp-1];if(15>--e)return this.l[e]+=t,this.l[e];var s=this.globals+2*(e-15);return this.ram.setUint16(s,this.m.getUint16(s)+t),this.ram.getUint16(s)},indirect:function(e,t){return 0===e?1>>-t},make_stacks:function(){var e=15&this.stack.getUint8(this.frameptr+3);this.l=new Uint16Array(this.stack.buffer,this.frameptr+8,e),this.s=new Uint16Array(this.stack.buffer,this.frameptr+8+2*e)},put_prop:function(e,t,s){var r,i=this.find_prop(e,t);i&&(r=this.m.getUint8(i-1),this.ram[(this.version3?r>>5:64&r)?"setUint16":"setUint8"](i,s))},random:function(e){var t=this.xorshift_seed;return 1>e?(this.xorshift_seed=e,0):0===t?0|1+Math.random()*e:(t^=t<<13,t^=t>>17,this.xorshift_seed=t^=t<<5,1+(32767&t)%e)},remove_obj:function(e){var t,s,r,i=this.get_parent(e);if(0!==i)if(t=this.get_child(i),s=this.get_sibling(e),t===e)this.set_family(e,0,i,s);else{for(;r=this.get_sibling(t),r!==e;)t=r;this.set_family(e,0,0,0,t,s)}},restart:function(){var t=this.ram,s=t.getUint8(0),r=3===s,n=r?2:8===s?8:4,o=t.getUint8(17),l=t.getUint16(10),p=4g;)if(a.getUint8(18+g)!==o.serial[g++])return 0;if(g=0,a.setUint8Array(0,this.origram),o.compressed)for(;g>8,s=this.frameptr=this.frames.pop(),this.make_stacks(),this.sp=t.getUint16(s+6),0<=r&&this.variable(r,e||0)},save:function(e){this.pc=e,this.fileref_create_by_prompt({func:"save",mode:1,usage:1})},save_file:function(e,t){var s,i,o,l=this.m,_=new n.Quetzal,g=a.MemoryView(this.stack.buffer.slice()),u=0,c=this.frameptr;if(_.release=l.getUint16(2),_.serial=l.getUint8Array(18,6),_.checksum=l.getUint16(28),_.pc=e,t)_.memory=this.m.getUint8Array(0,this.staticmem);else{const e=[];for(_.compressed=1,s=0;s>18,!a==!s&&(0===r||1===r?this.ret(r):this.pc+=r-2)):this.variable(i.getUint8(this.pc++),a)},save_undo:function(e,t){var s;return this.undo_len>this.options.undo_len&&(s=this.undo.shift(),this.undo_len-=s.ram.byteLength+s.stack.byteLength),s={frameptr:this.frameptr,frames:this.frames.slice(),pc:e,ram:this.m.getUint8Array(0,this.staticmem),sp:this.sp,stack:this.stack.getUint8Array(0,this.s.byteOffset+2*this.sp),var:t},this.undo_len+=s.ram.byteLength+s.stack.byteLength,this.undo.push(s),1},scan_table:function(e,t,s,r){r=r||130;var i=128&r?"getUint16":"getUint8";for(r&=127,s=t+s*r;t>t%8)},set_family:function(e,t,s,r,i,n){var a=this.ram,o=this.objects;this.version3?(a.setUint8(o+9*e+4,t),s&&a.setUint8(o+9*s+6,r),i&&a.setUint8(o+9*i+5,n)):(a.setUint16(o+14*e+6,t),s&&a.setUint16(o+14*s+10,r),i&&a.setUint16(o+14*i+8,n))},test:function(e,t){return(e&t)===t},test_attr:function(e,t){return 128&this.m.getUint8(0|this.objects+(this.version3?9:14)*e+t/8)<--e){if(r)this.l[e]=t;else return this.l[e];}else if(s=this.globals+2*(e-15),r)this.ram.setUint16(s,t);else return this.m.getUint16(s);return t},U2S:o,S2U:l}},{"../common/file.js":2,"../common/utils.js":3,"./opcodes.js":7}],9:[function(s,r){r.exports={init_text:function(){var e=this,s=this.m,r=4r;)s[0|r/26][r%26]=t[r++];s[2][1]=13,e.alphabets=s}(r?s.getUint8Array(r,78):this.text_to_zscii("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \r0123456789.,!?_#'\"/\\-:()",1)),function(s){for(var r={13:"\r"},n={13:13},a=0;aa;)r[a]=t(a),n[a]=a++;e.unicode_table=r,e.reverse_unicode_table=n}(i?s.getUint16Array(i,n):this.text_to_zscii(unescape("%E4%F6%FC%C4%D6%DC%DF%BB%AB%EB%EF%FF%CB%CF%E1%E9%ED%F3%FA%FD%C1%C9%CD%D3%DA%DD%E0%E8%EC%F2%F9%C0%C8%CC%D2%D9%E2%EA%EE%F4%FB%C2%CA%CE%D4%DB%E5%C5%F8%D8%E3%F1%F5%C3%D1%D5%E6%C6%E7%C7%FE%F0%DE%D0%A3%u0153%u0152%A1%BF"),1)),this.dictionaries={},this.dict=s.getUint16(8),this.parse_dict(this.dict)},decode:function(e,t){var s,r,n,a=this.m,o=e,l=[],p=0,i=0,_=[],g=[],u=0;if(this.jit[e])return this.jit[e];for(t=t?t+e:this.eof;e>10,31&s>>5,31&s),!(32768&s)););for(;pr?(n=1,_.push(-1),g.push("\uE000+this.abbr("+(32*(r-1)+l[p++])+")+\uE000")):6>r?i=r:2==i&&6===r?p+1r&&_.push(this.alphabets[i][r-6]),i=4>i?0:i-3,0==p%3&&(p+=u,u=0);return _=this.zscii_to_text(_,g),n&&(_={toString:Function("return\""+_.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/\r/g,"\\r").replace(/\uE000/g,"\"")+"\"").bind(this)}),o>=this.staticmem&&(this.jit[o]=_),_},encode:function(e){for(var t,s,r=this.alphabets,n=[],a=this.version3?6:9,o=0,i=[];n.length>5,31&t);for(n.length=a,o=0;o>3,(7&n[o++])<<5|n[o++]);return i[i.length-2]|=128,i},zscii_to_text:function(e,t){for(var s,r=0,i=e.length,n=0,a="";r>;
+ ];
+
+Scenic Stream "stream"
+ with name 'stream' 'water' 'brook' 'river' 'lake' 'small' 'tumbling'
+ 'splashing' 'babbling' 'rushing' 'reservoir',
+ found_in At_End_Of_Road In_A_Valley At_Slit_In_Streambed In_Pit
+ In_Cavern_With_Waterfall At_Reservoir Inside_Building,
+ before [;
+ Drink:
+ "You have taken a drink from the stream.
+ The water tastes strongly of minerals, but is not unpleasant.
+ It is extremely cold.";
+ Take:
+ if (bottle notin player)
+ "You have nothing in which to carry the water.";
+ <>;
+ Insert:
+ if (second == bottle) <>;
+ "You have nothing in which to carry the water.";
+ Receive:
+ if (noun == ming_vase) {
+ remove ming_vase;
+ move shards to location;
+ score = score - 5;
+ "The sudden change in temperature has delicately shattered the vase.";
+ }
+ if (noun == bottle) <>;
+ remove noun;
+ if (noun ofclass Treasure) score = score - 5;
+ print_ret (The) noun, " washes away with the stream.";
+ ];
+
+Scenic "road"
+ with name 'road' 'street' 'path' 'dirt',
+ description "The road is dirt, not yellow brick.",
+ found_in At_End_Of_Road At_Hill_In_Road In_Forest_2;
+
+Scenic "forest"
+ with name 'forest' 'tree' 'trees' 'oak' 'maple' 'grove' 'pine' 'spruce'
+ 'birch' 'ash' 'saplings' 'bushes' 'leaves' 'berry' 'berries'
+ 'hardwood',
+ description
+ "The trees of the forest are large hardwood oak and maple,
+ with an occasional grove of pine or spruce.
+ There is quite a bit of undergrowth,
+ largely birch and ash saplings plus nondescript bushes of various sorts.
+ This time of year visibility is quite restricted by all the leaves,
+ but travel is quite easy if you detour around the spruce and berry bushes.",
+ found_in At_End_Of_Road At_Hill_In_Road In_A_Valley In_Forest_1 In_Forest_2,
+ has multitude;
+
+! ------------------------------------------------------------------------------
+
+Aboveground At_Hill_In_Road "At Hill In Road"
+ with name 'hill' 'in' 'road',
+ description
+ "You have walked up a hill, still in the forest.
+ The road slopes back down the other side of the hill.
+ There is a building in the distance.",
+ e_to At_End_Of_Road,
+ n_to At_End_Of_Road,
+ d_to At_End_Of_Road,
+ s_to In_Forest_1;
+
+Scenic -> "hill"
+ with name 'hill' 'bump' 'incline',
+ description "It's just a typical hill.";
+
+Scenic -> "other side of hill"
+ with name 'side' 'other' 'of',
+ article "the",
+ description "Why not explore it yourself?";
+
+! ------------------------------------------------------------------------------
+
+Aboveground Inside_Building "Inside Building"
+ with name 'inside' 'building' 'well' 'house' 'wellhouse',
+ description
+ "You are inside a building, a well house for a large spring.",
+ cant_go
+ "The stream flows out through a pair of 1 foot diameter sewer pipes.
+ The only exit is to the west.",
+ before [;
+ Enter:
+ if (noun == Spring or SewerPipes)
+ "The stream flows out through a pair of 1 foot diameter sewer pipes.
+ It would be advisable to use the exit.";
+ Xyzzy:
+ if (In_Debris_Room hasnt visited) rfalse;
+ PlayerTo(In_Debris_Room);
+ rtrue;
+ Plugh:
+ if (At_Y2 hasnt visited) rfalse;
+ PlayerTo(At_Y2);
+ rtrue;
+ ],
+ w_to At_End_Of_Road,
+ out_to At_End_Of_Road,
+ in_to "The pipes are too small.";
+
+Scenic -> Spring "spring"
+ with name 'spring' 'large',
+ description
+ "The stream flows out through a pair of 1 foot diameter sewer pipes.";
+
+Scenic -> SewerPipes "pair of 1 foot diameter sewer pipes"
+ with name 'pipes' 'pipe' 'one' 'foot' 'diameter' 'sewer' 'sewer-pipes',
+ description "Too small. The only exit is to the west.";
+
+Object -> set_of_keys "set of keys"
+ with name 'keys' 'key' 'keyring' 'set' 'of' 'bunch',
+ description "It's just a normal-looking set of keys.",
+ initial "There are some keys on the ground here.",
+ before [;
+ Count:
+ "A dozen or so keys.";
+ ];
+
+Object -> tasty_food "tasty food"
+ with name 'food' 'ration' 'rations' 'tripe' 'yummy' 'tasty' 'delicious' 'scrumptious',
+ article "some",
+ description "Sure looks yummy!",
+ initial "There is tasty food here.",
+ after [;
+ Eat:
+ "Delicious!";
+ ],
+ has edible;
+
+Object -> brass_lantern "brass lantern"
+ with name 'lamp' 'headlamp' 'headlight' 'lantern' 'light' 'shiny' 'brass',
+ when_off "There is a shiny brass lamp nearby.",
+ when_on "Your lamp is here, gleaming brightly.",
+ daemon [ t;
+ if (self hasnt on) {
+ StopDaemon(self);
+ rtrue;
+ }
+ t = --(self.power_remaining);
+ if (t == 0) give self ~on ~light;
+ if (self in player || self in location) {
+ if (t == 0) {
+ print "Your lamp has run out of power.";
+ if (fresh_batteries notin player && location hasnt light) {
+ deadflag = 3;
+ " You can't explore the cave without a lamp.
+ So let's just call it a day.";
+ }
+ else
+ self.replace_batteries();
+ new_line;
+ rtrue;
+ }
+ if (t == 30) {
+ print "Your lamp is getting dim.";
+ if (fresh_batteries.have_been_used)
+ " You're also out of spare batteries.
+ You'd best start wrapping this up.";
+ if (fresh_batteries in VendingMachine && Dead_End_14 has visited)
+ " You'd best start wrapping this up,
+ unless you can find some fresh batteries.
+ I seem to recall there's a vending machine in the maze.
+ Bring some coins with you.";
+ if (fresh_batteries notin VendingMachine or player or location)
+ " You'd best go back for those batteries.";
+ new_line;
+ rtrue;
+ }
+ }
+ ],
+ before [;
+ Examine:
+ print "It is a shiny brass lamp";
+ if (self hasnt on) ". It is not currently lit.";
+ if (self.power_remaining < 30) ", glowing dimly.";
+ ", glowing brightly.";
+ Burn:
+ <>;
+ Rub:
+ "Rubbing the electric lamp is not particularly rewarding.
+ Anyway, nothing exciting happens.";
+ SwitchOn:
+ if (self.power_remaining <= 0)
+ "Unfortunately, the batteries seem to be dead.";
+ Receive:
+ if (noun == old_batteries)
+ "Those batteries are dead; they won't do any good at all.";
+ if (noun == fresh_batteries) {
+ self.replace_batteries();
+ rtrue;
+ }
+ "The only thing you might successfully put in the lamp
+ is a fresh pair of batteries.";
+ ],
+ after [;
+ SwitchOn:
+ give self light;
+ StartDaemon(self);
+ SwitchOff:
+ give self ~light;
+ ],
+ replace_batteries [;
+ if (fresh_batteries in player or location) {
+ remove fresh_batteries;
+ fresh_batteries.have_been_used = true;
+ move old_batteries to location;
+ self.power_remaining = 2500;
+ "I'm taking the liberty of replacing the batteries.";
+ }
+ ],
+ power_remaining 330,
+ has switchable;
+
+Object -> bottle "small bottle"
+ with name 'bottle' 'jar' 'flask',
+ initial "There is an empty bottle here.",
+ before [;
+ LetGo:
+ if (noun in bottle)
+ "You're holding that already (in the bottle).";
+ Receive:
+ if (noun == stream or Oil)
+ <>;
+ else
+ "The bottle is only supposed to hold liquids.";
+ Fill:
+ if (child(bottle) ~= nothing)
+ "The bottle is full already.";
+ if (stream in location || Spring in location) {
+ move water_in_the_bottle to bottle;
+ "The bottle is now full of water.";
+ }
+ if (Oil in location) {
+ move oil_in_the_bottle to bottle;
+ "The bottle is now full of oil.";
+ }
+ "There is nothing here with which to fill the bottle.";
+ Empty:
+ if (child(bottle) == nothing)
+ "The bottle is already empty!";
+ remove child(bottle);
+ "Your bottle is now empty and the ground is now wet.";
+ ],
+ has container open;
+
+Object water_in_the_bottle "bottled water"
+ with name 'bottled' 'water' 'h2o',
+ article "some",
+ description "It looks like ordinary water to me.",
+ before [;
+ Drink:
+ remove water_in_the_bottle;
+ <>;
+ ];
+
+Object oil_in_the_bottle "bottled oil"
+ with name 'oil' 'bottled' 'lubricant' 'grease',
+ article "some",
+ description "It looks like ordinary oil to me.",
+ before [;
+ Drink:
+ <>;
+ ];
+
+! ------------------------------------------------------------------------------
+
+Aboveground In_Forest_1 "In Forest"
+ with name 'forest',
+ description "You are in open forest, with a deep valley to one side.",
+ e_to In_A_Valley,
+ d_to In_A_Valley,
+ n_to In_Forest_1,
+ w_to In_Forest_1,
+ s_to In_Forest_1,
+ initial [;
+ if (random(2) == 1) PlayerTo(In_Forest_2, 1);
+ ];
+
+Aboveground In_Forest_2 "In Forest"
+ with description "You are in open forest near both a valley and a road.",
+ n_to At_End_Of_Road,
+ e_to In_A_Valley,
+ w_to In_A_Valley,
+ d_to In_A_Valley,
+ s_to In_Forest_1;
+
+Aboveground In_A_Valley "In A Valley"
+ with description
+ "You are in a valley in the forest beside a stream tumbling along a rocky bed.",
+ n_to At_End_Of_Road,
+ e_to In_Forest_1,
+ w_to In_Forest_1,
+ u_to In_Forest_1,
+ s_to At_Slit_In_Streambed,
+ d_to At_Slit_In_Streambed,
+ name 'valley';
+
+Scenic -> "streambed"
+ with name 'bed' 'streambed' 'rock' 'small' 'rocky' 'bare' 'dry';
+
+! ------------------------------------------------------------------------------
+
+Aboveground At_Slit_In_Streambed "At Slit In Streambed"
+ with name 'slit' 'in' 'streambed',
+ description
+ "At your feet all the water of the stream splashes into a 2-inch slit in the rock.
+ Downstream the streambed is bare rock.",
+ n_to In_A_Valley,
+ e_to In_Forest_1,
+ w_to In_Forest_1,
+ s_to Outside_Grate,
+ d_to "You don't fit through a two-inch slit!",
+ in_to "You don't fit through a two-inch slit!";
+
+Scenic -> "2-inch slit"
+ with name 'slit' 'two' 'inch' '2-inch',
+ description
+ "It's just a 2-inch slit in the rock, through which the stream is flowing.",
+ before [;
+ Enter:
+ "You don't fit through a two-inch slit!";
+ ];
+
+! ------------------------------------------------------------------------------
+
+Aboveground Outside_Grate "Outside Grate"
+ with name 'outside' 'grate',
+ description
+ "You are in a 20-foot depression floored with bare dirt.
+ Set into the dirt is a strong steel grate mounted in concrete.
+ A dry streambed leads into the depression.",
+ e_to In_Forest_1,
+ w_to In_Forest_1,
+ s_to In_Forest_1,
+ n_to At_Slit_In_Streambed,
+ d_to [;
+ if (Grate hasnt locked && Grate hasnt open) {
+ print "(first opening the grate)^";
+ give Grate open;
+ }
+ return Grate;
+ ];
+
+Scenic -> "20-foot depression"
+ with name 'depression' 'dirt' 'twenty' 'foot' 'bare' '20-foot',
+ description "You're standing in it.";
+
+Object -> Grate "steel grate"
+ with name 'grate' 'lock' 'gate' 'grille' 'metal' 'strong' 'steel' 'grating',
+ description "It just looks like an ordinary grate mounted in concrete.",
+ with_key set_of_keys,
+ door_dir [;
+ if (location == Below_The_Grate) return u_to;
+ return d_to;
+ ],
+ door_to [;
+ if (location == Below_The_Grate) return Outside_Grate;
+ return Below_The_Grate;
+ ],
+ describe [;
+ if (self has open) "^The grate stands open.";
+ if (self hasnt locked) "^The grate is unlocked but shut.";
+ rtrue;
+ ],
+ found_in Below_The_Grate Outside_Grate,
+ has static door openable lockable locked;
+
+! ------------------------------------------------------------------------------
+! Facilis descensus Averno...
+! ------------------------------------------------------------------------------
+
+Room Below_The_Grate "Below the Grate"
+ with name 'below' 'grate',
+ description
+ "You are in a small chamber beneath a 3x3 steel grate to the surface.
+ A low crawl over cobbles leads inward to the west.",
+ w_to In_Cobble_Crawl,
+ u_to Grate,
+ has light;
+
+Scenic "cobbles"
+ with name 'cobble' 'cobbles' 'cobblestones' 'cobblestone' 'stones' 'stone',
+ description "They're just ordinary cobbles.",
+ found_in In_Cobble_Crawl In_Debris_Room Below_The_Grate,
+ has multitude;
+
+! ------------------------------------------------------------------------------
+
+Room In_Cobble_Crawl "In Cobble Crawl"
+ with name 'cobble' 'crawl',
+ description
+ "You are crawling over cobbles in a low passage.
+ There is a dim light at the east end of the passage.",
+ e_to Below_The_Grate,
+ w_to In_Debris_Room,
+ has light;
+
+Object -> wicker_cage "wicker cage"
+ with name 'cage' 'small' 'wicker',
+ description "It's a small wicker cage.",
+ initial "There is a small wicker cage discarded nearby.",
+ after [;
+ Open:
+ if (little_bird notin self) rfalse;
+ print "(releasing the little bird)^";
+ <>;
+ ],
+ has container open openable transparent;
+
+! ------------------------------------------------------------------------------
+
+Room In_Debris_Room "In Debris Room"
+ with name 'debris' 'room',
+ description
+ "You are in a debris room filled with stuff washed in from the surface.
+ A low wide passage with cobbles becomes plugged with mud and debris here,
+ but an awkward canyon leads upward and west.
+ ^^
+ A note on the wall says, ~Magic word XYZZY.~",
+ e_to In_Cobble_Crawl,
+ u_to In_Awkward_Sloping_E_W_Canyon,
+ w_to In_Awkward_Sloping_E_W_Canyon,
+ before [;
+ Xyzzy:
+ PlayerTo(Inside_Building);
+ rtrue;
+ ],
+ has nodwarf;
+
+Scenic -> "debris"
+ with name 'debris' 'stuff' 'mud',
+ description "Yuck.";
+
+Scenic -> "note"
+ with name 'note',
+ description "The note says ~Magic word XYZZY~.";
+
+Object -> black_rod "black rod with a rusty star on the end"
+ with name 'rod' 'star' 'black' 'rusty' 'star' 'three' 'foot' 'iron',
+ description "It's a three foot black rod with a rusty star on an end.",
+ initial
+ "A three foot black rod with a rusty star on one end lies nearby.",
+ before [;
+ Wave:
+ if (location == West_Side_Of_Fissure or On_East_Bank_Of_Fissure) {
+ if (caves_closed) "Peculiar. Nothing happens.";
+ if (CrystalBridge notin nothing) {
+ remove CrystalBridge;
+ give CrystalBridge absent;
+ West_Side_Of_Fissure.e_to = nothing;
+ On_East_Bank_Of_Fissure.w_to = nothing;
+ "The crystal bridge has vanished!";
+ }
+ else {
+ move CrystalBridge to location;
+ give CrystalBridge ~absent;
+ West_Side_Of_Fissure.e_to = CrystalBridge;
+ On_East_Bank_Of_Fissure.w_to = CrystalBridge;
+ "A crystal bridge now spans the fissure.";
+ }
+ }
+ "Nothing happens.";
+ ];
+
+! ------------------------------------------------------------------------------
+
+Room In_Awkward_Sloping_E_W_Canyon "Sloping E/W Canyon"
+ with name 'sloping' 'e/w' 'canyon',
+ description "You are in an awkward sloping east/west canyon.",
+ d_to In_Debris_Room,
+ e_to In_Debris_Room,
+ u_to In_Bird_Chamber,
+ w_to In_Bird_Chamber,
+ has nodwarf;
+
+! ------------------------------------------------------------------------------
+! The little bird in its natural habitat
+! ------------------------------------------------------------------------------
+
+Room In_Bird_Chamber "Orange River Chamber"
+ with name 'orange' 'river' 'chamber',
+ description
+ "You are in a splendid chamber thirty feet high.
+ The walls are frozen rivers of orange stone.
+ An awkward canyon and a good passage exit from east and west sides of the chamber.",
+ e_to In_Awkward_Sloping_E_W_Canyon,
+ w_to At_Top_Of_Small_Pit,
+ has nodwarf;
+
+Object -> little_bird "little bird"
+ with name 'cheerful' 'mournful' 'little' 'bird',
+ initial "A cheerful little bird is sitting here singing.",
+ before [;
+ Examine:
+ if (self in wicker_cage)
+ "The little bird looks unhappy in the cage.";
+ "The cheerful little bird is sitting here singing.";
+ Insert:
+ if (second == wicker_cage)
+ <>;
+ else
+ "Don't put the poor bird in ", (the) second, "!";
+ Drop, Remove:
+ if (self in wicker_cage) {
+ print "(The bird is released from the cage.)^^";
+ <>;
+ }
+ Take, Catch:
+ if (self in wicker_cage)
+ "You already have the little bird.
+ If you take it out of the cage it will likely fly away from you.";
+ if (wicker_cage notin player)
+ "You can catch the bird, but you cannot carry it.";
+ if (black_rod in player)
+ "The bird was unafraid when you entered,
+ but as you approach it becomes disturbed and you cannot catch it.";
+ move self to wicker_cage;
+ give wicker_cage ~open;
+ "You catch the bird in the wicker cage.";
+ Release:
+ if (self notin wicker_cage)
+ "The bird is not caged now.";
+ give wicker_cage open;
+ move self to location;
+ if (Snake in location) {
+ remove Snake;
+ "The little bird attacks the green snake,
+ and in an astounding flurry drives the snake away.";
+ }
+ if (Dragon in location) {
+ remove self;
+ "The little bird attacks the green dragon,
+ and in an astounding flurry gets burnt to a cinder.
+ The ashes blow away.";
+ }
+ "The little bird flies free.";
+ ],
+ life [;
+ Give:
+ "It's not hungry. (It's merely pinin' for the fjords).
+ Besides, I suspect it would prefer bird seed.";
+ Order, Ask, Answer:
+ "Cheep! Chirp!";
+ Attack:
+ if (self in wicker_cage)
+ "Oh, leave the poor unhappy bird alone.";
+ remove self;
+ "The little bird is now dead. Its body disappears.";
+ ],
+ has animate;
+
+! ------------------------------------------------------------------------------
+
+Room At_Top_Of_Small_Pit "At Top of Small Pit"
+ with name 'top' 'of' 'small' 'pit',
+ description
+ "At your feet is a small pit breathing traces of white mist.
+ A west passage ends here except for a small crack leading on.
+ ^^
+ Rough stone steps lead down the pit.",
+ e_to In_Bird_Chamber,
+ w_to "The crack is far too small for you to follow.",
+ d_to [;
+ if (large_gold_nugget in player) {
+ deadflag = 1;
+ "You are at the bottom of the pit with a broken neck.";
+ }
+ return In_Hall_Of_Mists;
+ ],
+ before [;
+ Enter:
+ if (noun == PitCrack)
+ "The crack is far too small for you to follow.";
+ ],
+ has nodwarf;
+
+Scenic -> "small pit"
+ with name 'pit' 'small',
+ description "The pit is breathing traces of white mist.";
+
+Scenic -> PitCrack "crack"
+ with name 'crack' 'small',
+ description "The crack is very small -- far too small for you to follow.";
+
+Scenic "mist"
+ with name 'mist' 'vapor' 'wisps' 'white',
+ description
+ "Mist is a white vapor, usually water, seen from time to time in caverns.
+ It can be found anywhere but is frequently a sign of a deep pit leading down to water.",
+ found_in
+ At_Top_Of_Small_Pit In_Hall_Of_Mists On_East_Bank_Of_Fissure
+ At_Window_On_Pit_1 At_West_End_Of_Hall_Of_Mists In_Misty_Cavern
+ In_Mirror_Canyon At_Reservoir At_Window_On_Pit_2 On_Sw_Side_Of_Chasm;
+
+! ------------------------------------------------------------------------------
+! The caves open up: The Hall of Mists
+! ------------------------------------------------------------------------------
+
+Room In_Hall_Of_Mists "In Hall of Mists"
+ with name 'hall' 'of' 'mists',
+ description
+ "You are at one end of a vast hall stretching forward out of sight to the west.
+ There are openings to either side.
+ Nearby, a wide stone staircase leads downward.
+ The hall is filled with wisps of white mist swaying to and fro almost as if alive.
+ A cold wind blows up the staircase.
+ There is a passage at the top of a dome behind you.
+ ^^
+ Rough stone steps lead up the dome.",
+ initial [;
+ if (self has visited) rfalse;
+ score = score + 25;
+ ],
+ s_to In_Nugget_Of_Gold_Room,
+ w_to On_East_Bank_Of_Fissure,
+ d_to In_Hall_Of_Mt_King,
+ n_to In_Hall_Of_Mt_King,
+ u_to [;
+ if (large_gold_nugget in player) "The dome is unclimbable.";
+ return At_Top_Of_Small_Pit;
+ ];
+
+Scenic -> "wide stone staircase"
+ with name 'stair' 'stairs' 'staircase' 'wide' 'stone',
+ description "The staircase leads down.";
+
+Scenic -> "rough stone steps"
+ with name 'stair' 'stairs' 'staircase' 'rough' 'stone',
+ description "The rough stone steps lead up the dome.",
+ has multitude;
+
+Scenic -> "dome"
+ with name 'dome',
+ before [;
+ Examine:
+ if (large_gold_nugget in player)
+ "I'm not sure you'll be able to get up it with what you're
+ carrying.";
+ "It looks like you might be able to climb up it.";
+ Climb:
+ MovePlayer(u_obj);
+ rtrue;
+ ];
+
+! ------------------------------------------------------------------------------
+
+Room In_Nugget_Of_Gold_Room "Low Room"
+ with name 'low' 'room',
+ description
+ "This is a low room with a crude note on the wall:
+ ^^
+ ~You won't get it up the steps~.",
+ n_to In_Hall_Of_Mists;
+
+Scenic -> "note"
+ with name 'note' 'crude',
+ description "The note says, ~You won't get it up the steps~.";
+
+Treasure -> large_gold_nugget "large gold nugget"
+ with name 'gold' 'nugget' 'large' 'heavy',
+ description "It's a large sparkling nugget of gold!",
+ initial "There is a large sparkling nugget of gold here!";
+
+! ------------------------------------------------------------------------------
+
+Class FissureRoom
+ class Room
+ with before [;
+ Jump:
+ if (CrystalBridge hasnt absent)
+ "I respectfully suggest you go across the bridge instead of jumping.";
+ deadflag = 1;
+ "You didn't make it.";
+ ],
+ d_to "The fissure is too terrifying!";
+
+FissureRoom On_East_Bank_Of_Fissure "On East Bank of Fissure"
+ with name 'east' 'e//' 'bank' 'side' 'of' 'fissure',
+ description
+ "You are on the east bank of a fissure slicing clear across the hall.
+ The mist is quite thick here, and the fissure is too wide to jump.",
+ e_to In_Hall_Of_Mists,
+ w_to "The fissure is too wide.";
+
+FissureRoom West_Side_Of_Fissure "West Side of Fissure"
+ with name 'west' 'w//' 'bank' 'side' 'of' 'fissure',
+ description
+ "You are on the west side of the fissure in the hall of mists.",
+ w_to At_West_End_Of_Hall_Of_Mists,
+ e_to "The fissure is too wide.",
+ n_to At_West_End_Of_Hall_Of_Mists,
+ before [;
+ Go:
+ if (location == West_Side_Of_Fissure && noun == n_obj)
+ print
+ "You have crawled through a very low wide passage
+ parallel to and north of the hall of mists.^";
+ ];
+
+Treasure -> "diamonds"
+ with name 'diamond' 'diamonds' 'several' 'high' 'quality',
+ article "some",
+ description "They look to be of the highest quality!",
+ initial "There are diamonds here!",
+ has multitude;
+
+Object CrystalBridge "crystal bridge"
+ with name 'crystal' 'bridge',
+ description "It spans the fissure, thereby providing you a way across.",
+ initial "A crystal bridge now spans the fissure.",
+ door_dir [;
+ if (location == West_Side_Of_Fissure) return e_to;
+ return w_to;
+ ],
+ door_to [;
+ if (location == West_Side_Of_Fissure) return On_East_Bank_Of_Fissure;
+ return West_Side_Of_Fissure;
+ ],
+ found_in On_East_Bank_Of_Fissure West_Side_Of_Fissure,
+ has static door open absent;
+
+Scenic "fissure"
+ with name 'wide' 'fissure',
+ description "The fissure looks far too wide to jump.",
+ found_in On_East_Bank_Of_Fissure West_Side_Of_Fissure;
+
+! ------------------------------------------------------------------------------
+
+Room At_West_End_Of_Hall_Of_Mists "At West End of Hall of Mists"
+ with name 'west' 'w//' 'end' 'of' 'hall' 'mists',
+ description
+ "You are at the west end of the hall of mists.
+ A low wide crawl continues west and another goes north.
+ To the south is a little passage 6 feet off the floor.",
+ s_to Alike_Maze_1,
+ u_to Alike_Maze_1,
+ e_to West_Side_Of_Fissure,
+ w_to At_East_End_Of_Long_Hall,
+ n_to West_Side_Of_Fissure,
+ before [;
+ Go:
+ if (noun == n_obj)
+ print
+ "You have crawled through a very low wide passage
+ parallel to and north of the hall of mists.^";
+ ];
+
+! ------------------------------------------------------------------------------
+! Long Hall to the west of the Hall of Mists
+! ------------------------------------------------------------------------------
+
+Room At_East_End_Of_Long_Hall "At East End of Long Hall"
+ with name 'east' 'e//' 'end' 'of' 'long' 'hall',
+ description
+ "You are at the east end of a very long hall apparently without side chambers.
+ To the east a low wide crawl slants up.
+ To the north a round two foot hole slants down.",
+ e_to At_West_End_Of_Hall_Of_Mists,
+ u_to At_West_End_Of_Hall_Of_Mists,
+ w_to At_West_End_Of_Long_Hall,
+ n_to Crossover,
+ d_to Crossover;
+
+! ------------------------------------------------------------------------------
+
+Room At_West_End_Of_Long_Hall "At West End of Long Hall"
+ with name 'west' 'w//' 'end' 'of' 'long' 'hall',
+ description
+ "You are at the west end of a very long featureless hall.
+ The hall joins up with a narrow north/south passage.",
+ e_to At_East_End_Of_Long_Hall,
+ s_to Different_Maze_1,
+ n_to Crossover;
+
+! ------------------------------------------------------------------------------
+
+Room Crossover "N/S and E/W Crossover"
+ with name 'n/s' 'and' 'e/w' 'crossover',
+ description
+ "You are at a crossover of a high N/S passage and a low E/W one.",
+ w_to At_East_End_Of_Long_Hall,
+ n_to Dead_End_7,
+ e_to In_West_Side_Chamber,
+ s_to At_West_End_Of_Long_Hall;
+
+Scenic -> "crossover"
+ with name 'crossover' 'over' 'cross',
+ description "You know as much as I do at this point.";
+
+! ------------------------------------------------------------------------------
+! Many Dead Ends will be needed for the maze below, so define a class:
+! ------------------------------------------------------------------------------
+
+Class DeadendRoom
+ with short_name "Dead End",
+ description "You have reached a dead end.",
+ cant_go "You'll have to go back the way you came.";
+
+DeadendRoom Dead_End_7
+ with s_to Crossover,
+ out_to Crossover;
+
+! ------------------------------------------------------------------------------
+! The Hall of the Mountain King and side chambers
+! ------------------------------------------------------------------------------
+
+Room In_Hall_Of_Mt_King "Hall of the Mountain King"
+ with name 'hall' 'of' 'mountain' 'king',
+ description
+ "You are in the hall of the mountain king, with passages off in all directions.",
+ cant_go "Well, perhaps not quite all directions.",
+ u_to In_Hall_Of_Mists,
+ e_to In_Hall_Of_Mists,
+ n_to Low_N_S_Passage,
+ s_to In_South_Side_Chamber,
+ w_to In_West_Side_Chamber,
+ sw_to In_Secret_E_W_Canyon,
+ before [;
+ Go:
+ if (Snake in self && (noun == n_obj or s_obj or w_obj ||
+ (noun == sw_obj && random(100) <= 35)))
+ "You can't get by the snake.";
+ ];
+
+Object -> Snake "snake"
+ with name 'snake' 'cobra' 'asp' 'huge' 'fierce' 'green' 'ferocious'
+ 'venemous' 'venomous' 'large' 'big' 'killer',
+ description "I wouldn't mess with it if I were you.",
+ initial "A huge green fierce snake bars the way!",
+ life [;
+ Order, Ask, Answer:
+ "Hiss!";
+ ThrowAt:
+ if (noun == axe) <>;
+ <>;
+ Give:
+ if (noun == little_bird) {
+ remove little_bird;
+ "The snake has now devoured your bird.";
+ }
+ "There's nothing here it wants to eat (except perhaps you).";
+ Attack:
+ "Attacking the snake both doesn't work and is very dangerous.";
+ Take:
+ deadflag = 1;
+ "It takes you instead. Glrp!";
+ ],
+ has animate;
+
+! ------------------------------------------------------------------------------
+
+Room Low_N_S_Passage "Low N/S Passage"
+ with name 'low' 'n/s' 'passage',
+ description
+ "You are in a low N/S passage at a hole in the floor.
+ The hole goes down to an E/W passage.",
+ s_to In_Hall_Of_Mt_King,
+ d_to In_Dirty_Passage,
+ n_to At_Y2;
+
+Treasure -> "bars of silver"
+ with name 'silver' 'bars',
+ article "some",
+ description "They're probably worth a fortune!",
+ initial "There are bars of silver here!";
+
+! ------------------------------------------------------------------------------
+
+Room In_South_Side_Chamber "In South Side Chamber"
+ with name 'south' 's//''side' 'chamber',
+ description "You are in the south side chamber.",
+ n_to In_Hall_Of_Mt_King;
+
+Treasure -> "precious jewelry"
+ with name 'jewel' 'jewels' 'jewelry' 'precious' 'exquisite',
+ article "some",
+ description "It's all quite exquisite!",
+ initial "There is precious jewelry here!";
+
+! ------------------------------------------------------------------------------
+
+Room In_West_Side_Chamber "In West Side Chamber"
+ with name 'west' 'w//' 'wide' 'chamber',
+ description
+ "You are in the west side chamber of the hall of the mountain king.
+ A passage continues west and up here.",
+ w_to Crossover,
+ u_to Crossover,
+ e_to In_Hall_Of_Mt_King;
+
+Treasure -> rare_coins "rare coins"
+ with name 'coins' 'rare',
+ article "many",
+ description "They're a numismatist's dream!",
+ initial "There are many coins here!",
+ has multitude;
+
+! ------------------------------------------------------------------------------
+! The Y2 Rock Room and environs, slightly below
+! ------------------------------------------------------------------------------
+
+Room At_Y2 "At ~Y2~"
+ with name 'y2',
+ description
+ "You are in a large room, with a passage to the south,
+ a passage to the west, and a wall of broken rock to the east.
+ There is a large ~Y2~ on a rock in the room's center.",
+ after [;
+ Look:
+ if (random(100) <= 25) print "^A hollow voice says, ~Plugh.~^";
+ ],
+ before [;
+ Plugh:
+ PlayerTo(Inside_Building);
+ rtrue;
+ Plover:
+ if (In_Plover_Room hasnt visited) rfalse;
+ if (egg_sized_emerald in player) {
+ move egg_sized_emerald to In_Plover_Room;
+ score = score - 5;
+ }
+ PlayerTo(In_Plover_Room);
+ rtrue;
+ ],
+ s_to Low_N_S_Passage,
+ e_to Jumble_Of_Rock,
+ w_to At_Window_On_Pit_1;
+
+Scenic -> "~Y2~ rock"
+ with name 'rock' 'y2',
+ description "There is a large ~Y2~ painted on the rock.",
+ has supporter;
+
+! ------------------------------------------------------------------------------
+
+Room Jumble_Of_Rock "Jumble of Rock"
+ with name 'jumble' 'of' 'rock',
+ description "You are in a jumble of rock, with cracks everywhere.",
+ d_to At_Y2,
+ u_to In_Hall_Of_Mists;
+
+! ------------------------------------------------------------------------------
+
+Room At_Window_On_Pit_1 "At Window on Pit"
+ with name 'window' 'on' 'pit' 'east' 'e//',
+ description
+ "You're at a low window overlooking a huge pit, which extends up out of sight.
+ A floor is indistinctly visible over 50 feet below.
+ Traces of white mist cover the floor of the pit, becoming thicker to the right.
+ Marks in the dust around the window would seem to indicate that someone has been here recently.
+ Directly across the pit from you and 25 feet away
+ there is a similar window looking into a lighted room.
+ A shadowy figure can be seen there peering back at you.",
+ before [;
+ WaveHands:
+ "The shadowy figure waves back at you!";
+ ],
+ cant_go "The only passage is back east to Y2.",
+ e_to At_Y2;
+
+Class PitScenic
+ with found_in At_Window_On_Pit_1 At_Window_On_Pit_2,
+ has scenery;
+
+PitScenic "window"
+ with name 'window' 'low',
+ description "It looks like a regular window.",
+ has openable;
+
+PitScenic "huge pit"
+ with name 'pit' 'deep' 'large',
+ description
+ "It's so deep you can barely make out the floor below,
+ and the top isn't visible at all.";
+
+PitScenic "marks in the dust"
+ with name 'marks' 'dust',
+ description "Evidently you're not alone here.",
+ has multitude;
+
+PitScenic "shadowy figure"
+ with name 'figure' 'shadow' 'person' 'individual' 'shadowy' 'mysterious',
+ description
+ "The shadowy figure seems to be trying to attract your attention.";
+
+! ------------------------------------------------------------------------------
+
+Room In_Dirty_Passage "Dirty Passage"
+ with name 'dirty' 'passage',
+ description
+ "You are in a dirty broken passage.
+ To the east is a crawl.
+ To the west is a large passage.
+ Above you is a hole to another passage.",
+ e_to On_Brink_Of_Pit,
+ u_to Low_N_S_Passage,
+ w_to In_Dusty_Rock_Room;
+
+! ------------------------------------------------------------------------------
+
+Room On_Brink_Of_Pit "Brink of Pit"
+ with name 'brink' 'of' 'pit',
+ description
+ "You are on the brink of a small clean climbable pit.
+ A crawl leads west.",
+ w_to In_Dirty_Passage,
+ d_to In_Pit,
+ in_to In_Pit;
+
+Scenic -> "small pit"
+ with name 'pit' 'small' 'clean' 'climbable',
+ description "It looks like you might be able to climb down into it.",
+ before [;
+ Climb, Enter:
+ MovePlayer(d_obj);
+ rtrue;
+ ];
+
+! ------------------------------------------------------------------------------
+
+Room In_Pit "In Pit"
+ with name 'in' 'pit',
+ description
+ "You are in the bottom of a small pit with a little stream,
+ which enters and exits through tiny slits.",
+ u_to On_Brink_Of_Pit,
+ d_to "You don't fit through the tiny slits!",
+ has nodwarf;
+
+Scenic -> "tiny slits"
+ with name 'slit' 'slits' 'tiny',
+ description "The slits form a complex pattern in the rock.",
+ has multitude;
+
+! ------------------------------------------------------------------------------
+
+Room In_Dusty_Rock_Room "In Dusty Rock Room"
+ with name 'dusty' 'rock' 'room',
+ description
+ "You are in a large room full of dusty rocks.
+ There is a big hole in the floor.
+ There are cracks everywhere, and a passage leading east.",
+ e_to In_Dirty_Passage,
+ d_to At_Complex_Junction;
+
+Scenic -> "dusty rocks"
+ with name 'rocks' 'boulders' 'stones' 'rock' 'boulder' 'stone' 'dusty' 'dirty',
+ description "They're just rocks. (Dusty ones, that is.)",
+ before [;
+ LookUnder, Push, Pull:
+ "You'd have to blast your way through.";
+ ],
+ has multitude;
+
+! ------------------------------------------------------------------------------
+! A maze of twisty little passages, all alike...
+! ------------------------------------------------------------------------------
+
+Class MazeRoom
+ with short_name "Maze",
+ description "You are in a maze of twisty little passages, all alike.",
+ out_to "Easier said than done.";
+
+MazeRoom Alike_Maze_1
+ with u_to At_West_End_Of_Hall_Of_Mists,
+ n_to Alike_Maze_1,
+ e_to Alike_Maze_2,
+ s_to Alike_Maze_4,
+ w_to Alike_Maze_11;
+
+MazeRoom Alike_Maze_2
+ with w_to Alike_Maze_1,
+ s_to Alike_Maze_3,
+ e_to Alike_Maze_4;
+
+MazeRoom Alike_Maze_3
+ with e_to Alike_Maze_2,
+ d_to Dead_End_3,
+ s_to Alike_Maze_6,
+ n_to Dead_End_13;
+
+MazeRoom Alike_Maze_4
+ with w_to Alike_Maze_1,
+ n_to Alike_Maze_2,
+ e_to Dead_End_1,
+ s_to Dead_End_2,
+ u_to Alike_Maze_14,
+ d_to Alike_Maze_14;
+
+MazeRoom Alike_Maze_5
+ with e_to Alike_Maze_6,
+ w_to Alike_Maze_7;
+
+MazeRoom Alike_Maze_6
+ with e_to Alike_Maze_3,
+ w_to Alike_Maze_5,
+ d_to Alike_Maze_7,
+ s_to Alike_Maze_8;
+
+DeadendRoom Dead_End_1
+ with w_to Alike_Maze_4,
+ out_to Alike_Maze_4;
+
+DeadendRoom Dead_End_2
+ with w_to Alike_Maze_4,
+ out_to Alike_Maze_4;
+
+DeadendRoom Dead_End_3
+ with u_to Alike_Maze_3,
+ out_to Alike_Maze_3;
+
+MazeRoom Alike_Maze_7
+ with w_to Alike_Maze_5,
+ u_to Alike_Maze_6,
+ e_to Alike_Maze_8,
+ s_to Alike_Maze_9;
+
+MazeRoom Alike_Maze_8
+ with w_to Alike_Maze_6,
+ e_to Alike_Maze_7,
+ s_to Alike_Maze_8,
+ u_to Alike_Maze_9,
+ n_to Alike_Maze_10,
+ d_to Dead_End_12;
+
+MazeRoom Alike_Maze_9
+ with w_to Alike_Maze_7,
+ n_to Alike_Maze_8,
+ s_to Dead_End_4;
+
+DeadendRoom Dead_End_4
+ with w_to Alike_Maze_9,
+ out_to Alike_Maze_9;
+
+MazeRoom Alike_Maze_10
+ with w_to Alike_Maze_8,
+ n_to Alike_Maze_10,
+ d_to Dead_End_5,
+ e_to At_Brink_Of_Pit;
+
+DeadendRoom Dead_End_5
+ with u_to Alike_Maze_10,
+ out_to Alike_Maze_10;
+
+! ------------------------------------------------------------------------------
+
+Room At_Brink_Of_Pit "At Brink of Pit"
+ with name 'brink' 'of' 'pit',
+ description
+ "You are on the brink of a thirty foot pit with a massive orange column down one wall.
+ You could climb down here but you could not get back up.
+ The maze continues at this level.",
+ d_to In_Bird_Chamber,
+ w_to Alike_Maze_10,
+ s_to Dead_End_6,
+ n_to Alike_Maze_12,
+ e_to Alike_Maze_13;
+
+Scenic -> "massive orange column"
+ with name 'column' 'massive' 'orange' 'big' 'huge',
+ description "It looks like you could climb down it.",
+ before [;
+ Climb:
+ MovePlayer(d_obj);
+ rtrue;
+ ];
+
+Scenic -> "pit"
+ with name 'pit' 'thirty' 'foot' 'thirty-foot',
+ description "You'll have to climb down to find out anything more...",
+ before [;
+ Climb:
+ MovePlayer(d_obj);
+ rtrue;
+ ];
+
+DeadendRoom Dead_End_6
+ with e_to At_Brink_Of_Pit,
+ out_to At_Brink_Of_Pit;
+
+! ------------------------------------------------------------------------------
+! A line of three vital junctions, east to west
+! ------------------------------------------------------------------------------
+
+Room At_Complex_Junction "At Complex Junction"
+ with name 'complex' 'junction',
+ description
+ "You are at a complex junction.
+ A low hands and knees passage from the north joins a higher crawl from the east
+ to make a walking passage going west.
+ There is also a large room above.
+ The air is damp here.",
+ u_to In_Dusty_Rock_Room,
+ w_to In_Bedquilt,
+ n_to In_Shell_Room,
+ e_to In_Anteroom;
+
+! ------------------------------------------------------------------------------
+
+Room In_Bedquilt "Bedquilt"
+ with name 'bedquilt',
+ description
+ "You are in bedquilt, a long east/west passage with holes everywhere.
+ To explore at random select north, south, up, or down.",
+ e_to At_Complex_Junction,
+ w_to In_Swiss_Cheese_Room,
+ s_to In_Slab_Room,
+ u_to In_Dusty_Rock_Room,
+ n_to At_Junction_Of_Three,
+ d_to In_Anteroom,
+ before [ destiny;
+ Go:
+ if (noun == s_obj or d_obj && random(100) <= 80) destiny = 1;
+ if (noun == u_obj && random(100) <= 80) destiny = 1;
+ if (noun == u_obj && random(100) <= 50) destiny = In_Secret_N_S_Canyon_1;
+ if (noun == n_obj && random(100) <= 60) destiny = 1;
+ if (noun == n_obj && random(100) <= 75) destiny = In_Large_Low_Room;
+ if (destiny == 1)
+ "You have crawled around in some little holes and wound up back
+ in the main passage.";
+ if (destiny == 0) rfalse;
+ PlayerTo(destiny);
+ rtrue;
+ ];
+
+! ------------------------------------------------------------------------------
+
+Room In_Swiss_Cheese_Room "In Swiss Cheese Room"
+ with name 'swiss' 'cheese' 'room',
+ description
+ "You are in a room whose walls resemble swiss cheese.
+ Obvious passages go west, east, ne, and nw.
+ Part of the room is occupied by a large bedrock block.",
+ w_to At_East_End_Of_Twopit_Room,
+ s_to In_Tall_E_W_Canyon,
+ ne_to In_Bedquilt,
+ nw_to In_Oriental_Room,
+ e_to In_Soft_Room,
+ before [;
+ Go:
+ if ((noun == s_obj && random(100) <= 80) ||
+ (noun == nw_obj && random(100) <= 50))
+ "You have crawled around in some little holes and wound up
+ back in the main passage.";
+ ];
+
+Scenic -> "bedrock block"
+ with name 'block' 'bedrock' 'large',
+ description "It's just a huge block.",
+ before [;
+ LookUnder, Push, Pull, Take:
+ "Surely you're joking.";
+ ];
+
+! ------------------------------------------------------------------------------
+! The Twopit Room area
+! ------------------------------------------------------------------------------
+! Possible heights for the plant:
+! ------------------------------------------------------------------------------
+
+Constant TINY_P = 0;
+Constant TALL_P = 1;
+Constant HUGE_P = 2;
+
+Room At_West_End_Of_Twopit_Room "At West End of Twopit Room"
+ with name 'west' 'w//' 'end' 'of' 'twopit' 'room',
+ description
+ "You are at the west end of the twopit room.
+ There is a large hole in the wall above the pit at this end of the room.",
+ e_to At_East_End_Of_Twopit_Room,
+ w_to In_Slab_Room,
+ d_to In_West_Pit,
+ u_to "It is too far up for you to reach.",
+ before [;
+ Enter:
+ if (noun == HoleAbovePit_1) "It is too far up for you to reach.";
+ ];
+
+Object PlantStickingUp "beanstalk"
+ with name 'plant' 'beanstalk' 'stalk' 'bean' 'giant' 'tiny' 'little'
+ 'murmuring' 'twelve' 'foot' 'tall' 'bellowing',
+ describe [;
+ if (Plant.height == TALL_P)
+ "The top of a 12-foot-tall beanstalk is poking out of the west pit.";
+ "There is a huge beanstalk growing out of the west pit up to the hole.";
+ ],
+ before [;
+ Examine:
+ RunRoutines(self, describe);
+ rtrue;
+ Climb:
+ if (Plant.height == HUGE_P) <>;
+ ],
+ found_in At_West_End_Of_Twopit_Room At_East_End_Of_Twopit_Room,
+ has absent static;
+
+Scenic HoleAbovePit_1 "hole above pit"
+ with name 'hole' 'large' 'above' 'pit',
+ description
+ "The hole is in the wall above the pit at this end of the room.",
+ found_in In_West_Pit At_West_End_Of_Twopit_Room;
+
+! ------------------------------------------------------------------------------
+
+Room In_West_Pit "In West Pit"
+ with name 'in' 'west' 'pit',
+ description
+ "You are at the bottom of the western pit in the twopit room.
+ There is a large hole in the wall about 25 feet above you.",
+ before [;
+ Climb:
+ if (noun == Plant) rfalse;
+ if (Plant.height == TINY_P)
+ "There is nothing here to climb.
+ Use ~up~ or ~out~ to leave the pit.";
+ ],
+ u_to At_West_End_Of_Twopit_Room,
+ has nodwarf;
+
+Object -> Plant "plant"
+ with name 'plant' 'beanstalk' 'stalk' 'bean' 'giant' 'tiny' 'little'
+ 'murmuring' 'twelve' 'foot' 'tall' 'bellowing',
+ describe [;
+ switch (self.height) {
+ TINY_P:
+ "There is a tiny little plant in the pit, murmuring ~Water, water, ...~";
+ TALL_P:
+ "There is a 12-foot-tall beanstalk stretching up out of the pit, bellowing ~Water!! Water!!~";
+ HUGE_P:
+ "There is a gigantic beanstalk stretching all the way up to the hole.";
+ }
+ ],
+ before [;
+ Climb:
+ switch (self.height) {
+ TINY_P:
+ "It's just a little plant!";
+ TALL_P:
+ print
+ "You have climbed up the plant and out of the pit.^";
+ PlayerTo(At_West_End_Of_Twopit_Room);
+ rtrue;
+ HUGE_P:
+ print
+ "You clamber up the plant and scurry through the hole at the top.^";
+ PlayerTo(In_Narrow_Corridor);
+ rtrue;
+ }
+ Take:
+ "The plant has exceptionally deep roots and cannot be pulled free.";
+ Water:
+ if (bottle notin player)
+ "You have nothing to water the plant with.";
+ switch (child(bottle)) {
+ nothing:
+ "The bottle is empty.";
+ oil_in_the_bottle:
+ remove oil_in_the_bottle;
+ "The plant indignantly shakes the oil off its leaves and asks, ~Water?~";
+ }
+ remove water_in_the_bottle;
+ switch ((self.height)++) {
+ TINY_P:
+ print
+ "The plant spurts into furious growth for a few seconds.^^";
+ give PlantStickingUp ~absent;
+ TALL_P:
+ print
+ "The plant grows explosively, almost filling the bottom of the pit.^^";
+ HUGE_P:
+ print
+ "You've over-watered the plant! It's shriveling up! It's, it's...^^";
+ give PlantStickingUp absent;
+ remove PlantStickingUp;
+ self.height = TINY_P;
+ }
+ <>;
+ Oil:
+ <>;
+ Examine:
+ self.describe();
+ rtrue;
+ ],
+ height TINY_P;
+
+! ------------------------------------------------------------------------------
+
+Room At_East_End_Of_Twopit_Room "At East End of Twopit Room"
+ with name 'east' 'e//' 'end' 'of' 'twopit' 'room',
+ description
+ "You are at the east end of the twopit room.
+ The floor here is littered with thin rock slabs, which make it easy to descend the pits.
+ There is a path here bypassing the pits to connect passages from east and west.
+ There are holes all over,
+ but the only big one is on the wall directly over the west pit where you can't get to it.",
+ e_to In_Swiss_Cheese_Room,
+ w_to At_West_End_Of_Twopit_Room,
+ d_to In_East_Pit;
+
+Scenic -> "thin rock slabs"
+ with name 'slabs' 'slab' 'rocks' 'stairs' 'thin' 'rock',
+ description "They almost form natural stairs down into the pit.",
+ before [;
+ LookUnder, Push, Pull, Take:
+ "Surely you're joking. You'd have to blast them aside.";
+ ],
+ has multitude;
+
+! ------------------------------------------------------------------------------
+
+Room In_East_Pit "In East Pit"
+ with name 'in' 'east' 'e//' 'pit',
+ description
+ "You are at the bottom of the eastern pit in the twopit room.
+ There is a small pool of oil in one corner of the pit.",
+ u_to At_East_End_Of_Twopit_Room,
+ has nodwarf;
+
+Scenic -> Oil "pool of oil"
+ with name 'pool' 'oil' 'small',
+ description "It looks like ordinary oil.",
+ before [;
+ Drink:
+ "Absolutely not.";
+ Take:
+ if (bottle notin player)
+ "You have nothing in which to carry the oil.";
+ <>;
+ Insert:
+ if (second == bottle) <>;
+ "You have nothing in which to carry the oil.";
+ ];
+
+Scenic "hole above pit"
+ with name 'hole' 'large' 'above' 'pit',
+ description "The hole is in the wall above you.",
+ found_in In_East_Pit At_East_End_Of_Twopit_Room;
+
+! ------------------------------------------------------------------------------
+
+Room In_Slab_Room "Slab Room"
+ with name 'slab' 'room',
+ description
+ "You are in a large low circular chamber
+ whose floor is an immense slab fallen from the ceiling (slab room).
+ East and west there once were large passages, but they are now filled with boulders.
+ Low small passages go north and south, and the south one quickly bends west around the boulders.",
+ s_to At_West_End_Of_Twopit_Room,
+ u_to In_Secret_N_S_Canyon_0,
+ n_to In_Bedquilt;
+
+Scenic -> "slab"
+ with name 'slab' 'immense',
+ description "It is now the floor here.",
+ before [;
+ LookUnder, Push, Pull, Take:
+ "Surely you're joking.";
+ ];
+
+Scenic -> "boulders"
+ with name 'boulder' 'boulders' 'rocks' 'stones',
+ description "They're just ordinary boulders.",
+ has multitude;
+
+! ------------------------------------------------------------------------------
+! A small network of Canyons, mainly Secret
+! ------------------------------------------------------------------------------
+
+Room In_Secret_N_S_Canyon_0 "Secret N/S Canyon"
+ with name 'secret' 'n/s' 'canyon' '0//',
+ description
+ "You are in a secret N/S canyon above a large room.",
+ d_to In_Slab_Room,
+ s_to In_Secret_Canyon,
+ n_to In_Mirror_Canyon,
+ before [;
+ Go:
+ if (noun == s_obj) canyon_from = self;
+ ];
+
+Room In_Secret_N_S_Canyon_1 "Secret N/S Canyon"
+ with name 'secret' 'n/s' 'canyon' '1//',
+ description "You are in a secret N/S canyon above a sizable passage.",
+ n_to At_Junction_Of_Three,
+ d_to In_Bedquilt,
+ s_to Atop_Stalactite;
+
+Room At_Junction_Of_Three "Junction of Three Secret Canyons"
+ with name 'junction' 'of' 'three' 'secret' 'canyons',
+ description
+ "You are in a secret canyon at a junction of three canyons, bearing north, south, and se.
+ The north one is as tall as the other two combined.",
+ se_to In_Bedquilt,
+ s_to In_Secret_N_S_Canyon_1,
+ n_to At_Window_On_Pit_2;
+
+Room In_Large_Low_Room "Large Low Room"
+ with name 'large' 'low' 'room',
+ description
+ "You are in a large low room. Crawls lead north, se, and sw.",
+ sw_to In_Sloping_Corridor,
+ se_to In_Oriental_Room,
+ n_to Dead_End_Crawl;
+
+Room Dead_End_Crawl "Dead End Crawl"
+ with name 'dead' 'end' 'crawl',
+ description "This is a dead end crawl.",
+ s_to In_Large_Low_Room,
+ out_to In_Large_Low_Room;
+
+Room In_Secret_E_W_Canyon "Secret E/W Canyon Above Tight Canyon"
+ with name 'secret' 'e/w' 'canyon' 'above' 'tight' 'canyon',
+ description
+ "You are in a secret canyon which here runs E/W.
+ It crosses over a very tight canyon 15 feet below.
+ If you go down you may not be able to get back up.",
+ e_to In_Hall_Of_Mt_King,
+ w_to In_Secret_Canyon,
+ before [;
+ Go:
+ if (noun == w_obj) canyon_from = self;
+ ],
+ d_to In_N_S_Canyon;
+
+Room In_N_S_Canyon "N/S Canyon"
+ with name 'n/s' 'canyon',
+ description "You are at a wide place in a very tight N/S canyon.",
+ s_to Canyon_Dead_End,
+ n_to In_Tall_E_W_Canyon;
+
+Room Canyon_Dead_End "Canyon Dead End"
+ with description "The canyon here becomes too tight to go further south.",
+ n_to In_N_S_Canyon;
+
+Room In_Tall_E_W_Canyon "In Tall E/W Canyon"
+ with name 'tall' 'e/w' 'canyon',
+ description
+ "You are in a tall E/W canyon. A low tight crawl goes 3 feet north
+ and seems to open up.",
+ e_to In_N_S_Canyon,
+ w_to Dead_End_8,
+ n_to In_Swiss_Cheese_Room;
+
+! ------------------------------------------------------------------------------
+
+Room Atop_Stalactite "Atop Stalactite"
+ with name 'atop' 'stalactite',
+ description
+ "A large stalactite extends from the roof and almost reaches the floor below.
+ You could climb down it, and jump from it to the floor,
+ but having done so you would be unable to reach it to climb back up.",
+ n_to In_Secret_N_S_Canyon_1,
+ d_to [;
+ if (random(100) <= 40) return Alike_Maze_6;
+ if (random(100) <= 50) return Alike_Maze_9;
+ return Alike_Maze_4;
+ ],
+ before [;
+ Jump, Climb:
+ <>;
+ ];
+
+Scenic -> "stalactite"
+ with name 'stalactite' 'stalagmite' 'stalagtite' 'large',
+ description
+ "You could probably climb down it, but you can forget coming back up.",
+ before [;
+ LookUnder, Push, Take:
+ "Do get a grip on yourself.";
+ ];
+
+! ------------------------------------------------------------------------------
+! Here be dragons
+! ------------------------------------------------------------------------------
+
+Room In_Secret_Canyon "Secret Canyon"
+ with name 'secret' 'canyon',
+ description
+ "You are in a secret canyon which exits to the north and east.",
+ e_to [;
+ if (canyon_from == In_Secret_E_W_Canyon) return canyon_from;
+ if (Dragon in location)
+ "The dragon looks rather nasty. You'd best not try to get by.";
+ return In_Secret_E_W_Canyon;
+ ],
+ n_to [;
+ if (canyon_from == In_Secret_N_S_Canyon_0) return canyon_from;
+ if (Dragon in location)
+ "The dragon looks rather nasty. You'd best not try to get by.";
+ return In_Secret_N_S_Canyon_0;
+ ],
+ out_to [;
+ return canyon_from;
+ ],
+ before [;
+ if (action == ##Yes && Dragon.is_being_attacked) {
+ remove Dragon;
+ move DragonCorpse to location;
+ Dragon.is_being_attacked = false;
+ "Congratulations! You have just vanquished a dragon with your bare hands!
+ (Unbelievable, isn't it?)";
+ }
+ if (action == ##No && Dragon.is_being_attacked) {
+ Dragon.is_being_attacked = false;
+ "I should think not.";
+ }
+ Dragon.is_being_attacked = false;
+ ];
+
+Object -> Dragon "dragon"
+ with name 'dragon' 'monster' 'beast' 'lizard' 'huge' 'green' 'fierce' 'scaly'
+ 'giant' 'ferocious',
+ description "I wouldn't mess with it if I were you.",
+ initial "A huge green fierce dragon bars the way!",
+ life [;
+ Attack:
+ self.is_being_attacked = true;
+ "With what? Your bare hands?";
+ Give:
+ "The dragon is implacable.";
+ ThrowAt:
+ if (noun ~= axe)
+ "You'd probably be better off using your bare hands than that thing!";
+ move axe to location;
+ "The axe bounces harmlessly off the dragon's thick scales.";
+ ],
+ is_being_attacked false,
+ has animate;
+
+Treasure -> "Persian rug"
+ with name 'rug' 'persian' 'persian' 'fine' 'finest' 'dragon^s',
+ describe [;
+ if (Dragon in location)
+ "The dragon is sprawled out on the Persian rug!";
+ "The Persian rug is spread out on the floor here.";
+ ],
+ before [;
+ Take:
+ if (Dragon in location)
+ "You'll need to get the dragon to move first!";
+ ],
+ depositpoints 14;
+
+Object DragonCorpse "dragon's body"
+ with name 'dragon' 'corpse' 'dead' 'dragon^s' 'body',
+ initial "The body of a huge green dead dragon is lying off to one side.",
+ before [;
+ Attack:
+ "You've already done enough damage!";
+ ],
+ has static;
+
+! ------------------------------------------------------------------------------
+! And more of the Alike Maze
+! ------------------------------------------------------------------------------
+
+DeadendRoom Dead_End_8
+ with description "The canyon runs into a mass of boulders -- dead end.",
+ s_to In_Tall_E_W_Canyon,
+ out_to In_Tall_E_W_Canyon;
+
+MazeRoom Alike_Maze_11
+ with n_to Alike_Maze_1,
+ w_to Alike_Maze_11,
+ s_to Alike_Maze_11,
+ e_to Dead_End_9,
+ ne_to Dead_End_10;
+
+DeadendRoom Dead_End_9
+ with w_to Alike_Maze_11,
+ out_to Alike_Maze_11;
+
+DeadendRoom Dead_End_10
+ with s_to Alike_Maze_3,
+ out_to Alike_Maze_3;
+
+MazeRoom Alike_Maze_12
+ with s_to At_Brink_Of_Pit,
+ e_to Alike_Maze_13,
+ w_to Dead_End_11;
+
+MazeRoom Alike_Maze_13
+ with n_to At_Brink_Of_Pit,
+ w_to Alike_Maze_12,
+ nw_to Dead_End_13;
+
+DeadendRoom Dead_End_11
+ with e_to Alike_Maze_12,
+ out_to Alike_Maze_12;
+
+DeadendRoom Dead_End_12
+ with u_to Alike_Maze_8,
+ out_to Alike_Maze_8;
+
+MazeRoom Alike_Maze_14
+ with u_to Alike_Maze_4,
+ d_to Alike_Maze_4;
+
+DeadendRoom Dead_End_13
+ class Room
+ with name 'pirate^s' 'dead' 'end' 'treasure' 'chest',
+ se_to Alike_Maze_13,
+ out_to Alike_Maze_13,
+ description "This is the pirate's dead end.",
+ initial [;
+ StopDaemon(Pirate);
+ if (treasure_chest in self && treasure_chest hasnt moved)
+ "You've found the pirate's treasure chest!";
+ ],
+ has nodwarf;
+
+Treasure -> treasure_chest "treasure chest"
+ with name 'chest' 'box' 'treasure' 'riches' 'pirate' 'pirate^s' 'treasure',
+ description
+ "It's the pirate's treasure chest, filled with riches of all kinds!",
+ initial "The pirate's treasure chest is here!",
+ depositpoints 12;
+
+! ------------------------------------------------------------------------------
+! Above the beanstalk: the Giant Room and the Waterfall
+! ------------------------------------------------------------------------------
+
+Room In_Narrow_Corridor "In Narrow Corridor"
+ with name 'narrow' 'corridor',
+ description
+ "You are in a long, narrow corridor stretching out of sight to the west.
+ At the eastern end is a hole through which you can see a profusion of leaves.",
+ d_to In_West_Pit,
+ w_to In_Giant_Room,
+ e_to In_West_Pit,
+ before [;
+ Jump:
+ deadflag = 1;
+ "You fall and break your neck!";
+ ];
+
+Scenic -> "leaves"
+ with name 'leaf' 'leaves' 'plant' 'tree' 'stalk' 'beanstalk' 'profusion',
+ article "some",
+ description
+ "The leaves appear to be attached to the beanstalk you climbed to get here.",
+ before [;
+ Count:
+ "69,105."; ! (I thank Rene Schnoor for counting them)
+ ];
+
+! ------------------------------------------------------------------------------
+
+Room At_Steep_Incline "Steep Incline Above Large Room"
+ with name 'steep' 'incline' 'above' 'large' 'room',
+ description
+ "You are at the top of a steep incline above a large room.
+ You could climb down here, but you would not be able to climb up.
+ There is a passage leading back to the north.",
+ n_to In_Cavern_With_Waterfall,
+ d_to In_Large_Low_Room;
+
+! ------------------------------------------------------------------------------
+
+Room In_Giant_Room "Giant Room"
+ with name 'giant' 'room',
+ description
+ "You are in the giant room.
+ The ceiling here is too high up for your lamp to show it.
+ Cavernous passages lead east, north, and south.
+ On the west wall is scrawled the inscription, ~Fee fie foe foo~ [sic].",
+ s_to In_Narrow_Corridor,
+ e_to At_Recent_Cave_In,
+ n_to In_Immense_N_S_Passage;
+
+Scenic -> "scrawled inscription"
+ with name 'inscription' 'writing' 'scrawl' 'scrawled',
+ description "It says, ~Fee fie foe foo [sic].~";
+
+Treasure -> golden_eggs "nest of golden eggs"
+ with name 'eggs' 'egg' 'nest' 'golden' 'beautiful',
+ description "The nest is filled with beautiful golden eggs!",
+ initial "There is a large nest here, full of golden eggs!",
+ depositpoints 14,
+ has multitude;
+
+! ------------------------------------------------------------------------------
+
+Room At_Recent_Cave_In "Recent Cave-in"
+ with description "The passage here is blocked by a recent cave-in.",
+ s_to In_Giant_Room;
+
+! ------------------------------------------------------------------------------
+
+Room In_Immense_N_S_Passage "Immense N/S Passage"
+ with name 'immense' 'n/s' 'passage',
+ description "You are at one end of an immense north/south passage.",
+ s_to In_Giant_Room,
+ n_to [;
+ if (RustyDoor has locked) <>;
+ if (RustyDoor hasnt open) {
+ give RustyDoor open;
+ print "(first wrenching the door open)^";
+ }
+ return RustyDoor;
+ ];
+
+Object -> RustyDoor "rusty door"
+ with name 'door' 'hinge' 'hinges' 'massive' 'rusty' 'iron',
+ description "It's just a big iron door.",
+ when_closed "The way north is barred by a massive, rusty, iron door.",
+ when_open "The way north leads through a massive, rusty, iron door.",
+ door_to In_Cavern_With_Waterfall,
+ door_dir n_to,
+ before [;
+ Open:
+ if (self has locked)
+ "The hinges are quite thoroughly rusted now and won't budge.";
+ Close:
+ if (self has open)
+ "With all the effort it took to get the door open,
+ I wouldn't suggest closing it again.";
+ "No problem there -- it already is.";
+ Oil:
+ if (bottle in player && oil_in_the_bottle in bottle) {
+ remove oil_in_the_bottle;
+ give self ~locked openable;
+ "The oil has freed up the hinges so that the door will now move,
+ although it requires some effort.";
+ }
+ else
+ "You have nothing to oil it with.";
+ Water:
+ if (bottle in player && water_in_the_bottle in bottle) {
+ remove water_in_the_bottle;
+ give self locked ~open;
+ "The hinges are quite thoroughly rusted now and won't budge.";
+ }
+ else
+ "You have nothing to water it with.";
+ ],
+ after [;
+ Open:
+ "The door heaves open with a shower of rust.";
+ ],
+ has static door locked;
+
+! ------------------------------------------------------------------------------
+
+Room In_Cavern_With_Waterfall "In Cavern With Waterfall"
+ with name 'cavern' 'with' 'waterfall',
+ description
+ "You are in a magnificent cavern with a rushing stream,
+ which cascades over a sparkling waterfall into a roaring whirlpool
+ which disappears through a hole in the floor.
+ Passages exit to the south and west.",
+ s_to In_Immense_N_S_Passage,
+ w_to At_Steep_Incline;
+
+Scenic -> "waterfall"
+ with name 'waterfall' 'whirlpool' 'sparkling' 'whirling',
+ description "Wouldn't want to go down in in a barrel!";
+
+Treasure -> trident "jeweled trident"
+ with name 'trident' 'jeweled' 'jewel-encrusted' 'encrusted' 'fabulous',
+ description "The trident is covered with fabulous jewels!",
+ initial "There is a jewel-encrusted trident here!",
+ depositpoints 14;
+
+! ------------------------------------------------------------------------------
+! The caves around Bedquilt
+! ------------------------------------------------------------------------------
+
+Room In_Soft_Room "In Soft Room"
+ with name 'soft' 'room',
+ description
+ "You are in the soft room.
+ The walls are covered with heavy curtains, the floor with a thick pile carpet.
+ Moss covers the ceiling.",
+ w_to In_Swiss_Cheese_Room;
+
+Scenic -> "carpet"
+ with name 'carpet' 'shag' 'pile' 'heavy' 'thick',
+ description "The carpet is quite plush.";
+
+Scenic -> "curtains"
+ with name 'curtain' 'curtains' 'heavy' 'thick',
+ description "They seem to absorb sound very well.",
+ before [;
+ Take:
+ "Now don't go ripping up the place!";
+ LookUnder, Search:
+ "You don't find anything exciting behind the curtains.";
+ ];
+
+Scenic -> "moss"
+ with name 'moss' 'typical' 'everyday',
+ description "It just looks like your typical, everyday moss.",
+ before [;
+ Take:
+ "It crumbles to nothing in your hands.";
+ ],
+ has edible;
+
+Object -> velvet_pillow "velvet pillow"
+ with name 'pillow' 'velvet' 'small',
+ description "It's just a small velvet pillow.",
+ initial "A small velvet pillow lies on the floor.";
+
+! ------------------------------------------------------------------------------
+
+Room In_Oriental_Room "Oriental Room"
+ with name 'oriental' 'room',
+ description
+ "This is the oriental room.
+ Ancient oriental cave drawings cover the walls.
+ A gently sloping passage leads upward to the north, another passage leads se,
+ and a hands and knees crawl leads west.",
+ w_to In_Large_Low_Room,
+ se_to In_Swiss_Cheese_Room,
+ u_to In_Misty_Cavern,
+ n_to In_Misty_Cavern;
+
+Scenic -> "ancient oriental drawings"
+ with name 'paintings' 'drawings' 'art' 'cave' 'ancient' 'oriental',
+ description "They seem to depict people and animals.",
+ has multitude;
+
+Treasure -> ming_vase "ming vase"
+ with name 'vase' 'ming' 'delicate',
+ description "It's a delicate, precious, ming vase!",
+ after [;
+ Drop:
+ if (velvet_pillow in location) {
+ print "(coming to rest, delicately, on the velvet pillow)^";
+ rfalse;
+ }
+ remove ming_vase;
+ move shards to location;
+ "The ming vase drops with a delicate crash.";
+ ],
+ before [;
+ Attack:
+ remove ming_vase;
+ move shards to location;
+ "You have taken the vase and
+ hurled it delicately to the ground.";
+ Receive:
+ "The vase is too fragile to use as a container.";
+ ],
+ depositpoints 14;
+
+Object shards "some worthless shards of pottery"
+ with name 'pottery' 'shards' 'remains' 'vase' 'worthless',
+ description
+ "They look to be the remains of what was once a beautiful vase.
+ I guess some oaf must have dropped it.",
+ initial "The floor is littered with worthless shards of pottery.",
+ has multitude;
+
+! ------------------------------------------------------------------------------
+
+Room In_Misty_Cavern "Misty Cavern"
+ with name 'misty' 'cavern',
+ description
+ "You are following a wide path around the outer edge of a large cavern.
+ Far below, through a heavy white mist, strange splashing noises can be heard.
+ The mist rises up through a fissure in the ceiling.
+ The path exits to the south and west.",
+ s_to In_Oriental_Room,
+ w_to In_Alcove;
+
+Scenic -> "fissure"
+ with name 'fissure' 'ceiling',
+ description "You can't really get close enough to examine it.";
+
+! ------------------------------------------------------------------------------
+! Plovers and pyramids
+! ------------------------------------------------------------------------------
+
+Room In_Alcove "Alcove"
+ with name 'alcove',
+ description
+ "You are in an alcove.
+ A small northwest path seems to widen after a short distance.
+ An extremely tight tunnel leads east.
+ It looks like a very tight squeeze.
+ An eerie light can be seen at the other end.",
+ nw_to In_Misty_Cavern,
+ e_to [ j;
+ j = children(player);
+ if (j == 0 || (j == 1 && egg_sized_emerald in player))
+ return In_Plover_Room;
+ "Something you're carrying won't fit through the tunnel with you.
+ You'd best take inventory and drop something.";
+ ];
+
+! ------------------------------------------------------------------------------
+
+Room In_Plover_Room "Plover Room"
+ with name 'plover' 'room',
+ description
+ "You're in a small chamber lit by an eerie green light.
+ An extremely narrow tunnel exits to the west.
+ A dark corridor leads northeast.",
+ ne_to In_Dark_Room,
+ w_to [ j;
+ j = children(player);
+ if (j == 0 || (j == 1 && egg_sized_emerald in player))
+ return In_Alcove;
+ "Something you're carrying won't fit through the tunnel with you.
+ You'd best take inventory and drop something.";
+ ],
+ before [;
+ Plover:
+ if (egg_sized_emerald in player) {
+ move egg_sized_emerald to In_Plover_Room;
+ score = score - 5;
+ }
+ PlayerTo(At_Y2);
+ rtrue;
+ Go:
+ if (noun == out_obj)
+ <>;
+ ],
+ has light;
+
+Treasure -> egg_sized_emerald "emerald the size of a plover's egg"
+ with name 'emerald' 'egg-sized' 'egg' 'sized' 'plover^s',
+ article "an",
+ description "Plover's eggs, by the way, are quite large.",
+ initial "There is an emerald here the size of a plover's egg!",
+ depositpoints 14;
+
+! ------------------------------------------------------------------------------
+
+Room In_Dark_Room "The Dark Room"
+ with name 'dark' 'room',
+ description
+ "You're in the dark-room. A corridor leading south is the only exit.",
+ s_to In_Plover_Room,
+ has nodwarf;
+
+Object -> "stone tablet"
+ with name 'tablet' 'massive' 'stone',
+ initial
+ "A massive stone tablet imbedded in the wall reads:
+ ~Congratulations on bringing light into the dark-room!~",
+ has static;
+
+Treasure -> "platinum pyramid"
+ with name 'platinum' 'pyramid' 'platinum' 'pyramidal',
+ description "The platinum pyramid is 8 inches on a side!",
+ initial "There is a platinum pyramid here, 8 inches on a side!",
+ depositpoints 14;
+
+! ------------------------------------------------------------------------------
+! North of the complex junction: a long up-down corridor
+! ------------------------------------------------------------------------------
+
+Room In_Arched_Hall "Arched Hall"
+ with name 'arched' 'hall',
+ description
+ "You are in an arched hall.
+ A coral passage once continued up and east from here, but is now blocked by debris.
+ The air smells of sea water.",
+ d_to In_Shell_Room;
+
+! ------------------------------------------------------------------------------
+
+Room In_Shell_Room "Shell Room"
+ with name 'shell' 'room',
+ description
+ "You're in a large room carved out of sedimentary rock.
+ The floor and walls are littered with bits of shells imbedded in the stone.
+ A shallow passage proceeds downward, and a somewhat steeper one leads up.
+ A low hands and knees passage enters from the south.",
+ u_to In_Arched_Hall,
+ d_to In_Ragged_Corridor,
+ s_to [;
+ if (giant_bivalve in player) {
+ if (giant_bivalve has open)
+ "You can't fit this five-foot oyster through that little passage!";
+ else
+ "You can't fit this five-foot clam through that little passage!";
+ }
+ return At_Complex_Junction;
+ ];
+
+Object -> giant_bivalve "giant clam"
+ with name 'giant' 'clam' 'oyster' 'bivalve',
+ describe [;
+ if (self.has_been_opened)
+ "There is an enormous oyster here with its shell tightly closed.";
+ "There is an enormous clam here with its shell tightly closed.";
+ ],
+ before [;
+ Examine:
+ if (location == At_Ne_End or At_Sw_End)
+ "Interesting.
+ There seems to be something written on the underside of the oyster:
+ ^^
+ ~There is something strange about this place,
+ such that one of the curses I've always known now has a new effect.~";
+ "A giant bivalve of some kind.";
+ Open:
+ "You aren't strong enough to open the clam with your bare hands.";
+ Unlock:
+ if (second ~= trident)
+ print_ret (The) second, " isn't strong enough to open the clam.";
+ if (self.has_been_opened)
+ "The oyster creaks open, revealing nothing but oyster inside.
+ It promptly snaps shut again.";
+ self.has_been_opened = true;
+ move pearl to In_A_Cul_De_Sac;
+ "A glistening pearl falls out of the clam and rolls away.
+ Goodness, this must really be an oyster.
+ (I never was very good at identifying bivalves.)
+ Whatever it is, it has now snapped shut again.";
+ Attack:
+ "The shell is very strong and is impervious to attack.";
+ ],
+ has_been_opened false;
+
+Treasure pearl "glistening pearl"
+ with name 'pearl' 'glistening' 'incredible' 'incredibly' 'large',
+ description "It's incredibly large!",
+ initial "Off to one side lies a glistening pearl!",
+ depositpoints 14;
+
+! ------------------------------------------------------------------------------
+
+Room In_Ragged_Corridor "Ragged Corridor"
+ with name 'ragged' 'corridor',
+ description "You are in a long sloping corridor with ragged sharp walls.",
+ u_to In_Shell_Room,
+ d_to In_A_Cul_De_Sac;
+
+Room In_A_Cul_De_Sac "Cul-de-Sac"
+ with name 'cul-de-sac' 'cul' 'de' 'sac',
+ description "You are in a cul-de-sac about eight feet across.",
+ u_to In_Ragged_Corridor,
+ out_to In_Ragged_Corridor;
+
+! ------------------------------------------------------------------------------
+! Witt's End: Cave under construction
+! ------------------------------------------------------------------------------
+
+Room In_Anteroom "In Anteroom"
+ with name 'anteroom',
+ description
+ "You are in an anteroom leading to a large passage to the east.
+ Small passages go west and up.
+ The remnants of recent digging are evident.",
+ u_to At_Complex_Junction,
+ w_to In_Bedquilt,
+ e_to At_Witts_End;
+
+Object -> "sign"
+ with name 'sign' 'witt' 'company' 'construction',
+ initial
+ "A sign in midair here says ~Cave under construction beyond this point.
+ Proceed at own risk. [Witt Construction Company]~",
+ before [;
+ Take:
+ "It's hanging way above your head.";
+ ],
+ has static;
+
+Object -> "recent issues of ~Spelunker Today~"
+ with name 'magazines' 'magazine' 'issue' 'issues' 'spelunker' 'today',
+ article "a few",
+ description "I'm afraid the magazines are written in Dwarvish.",
+ initial "There are a few recent issues of ~Spelunker Today~ magazine here.",
+ after [;
+ Take:
+ if (location == At_Witts_End) score--;
+ Drop:
+ if (location == At_Witts_End) {
+ score++;
+ "You really are at wit's end.";
+ }
+ ],
+ has multitude;
+
+! ------------------------------------------------------------------------------
+
+Room At_Witts_End "At Witt's End"
+ with name 'witt^s' 'witts' 'end',
+ description
+ "You are at Witt's End. Passages lead off in *all* directions.",
+ w_to
+ "You have crawled around in some little holes
+ and found your way blocked by a recent cave-in.
+ You are now back in the main passage.",
+ before [;
+ Go:
+ if (noun ~= w_obj && random(100) <= 95)
+ "You have crawled around in some little holes and wound up
+ back in the main passage.";
+ PlayerTo(In_Anteroom);
+ rtrue;
+ ];
+
+! ------------------------------------------------------------------------------
+! North of the secret canyons, on the other side of the pit
+! ------------------------------------------------------------------------------
+
+Room In_Mirror_Canyon "In Mirror Canyon"
+ with name 'mirror' 'canyon',
+ description
+ "You are in a north/south canyon about 25 feet across.
+ The floor is covered by white mist seeping in from the north.
+ The walls extend upward for well over 100 feet.
+ Suspended from some unseen point far above you,
+ an enormous two-sided mirror is hanging parallel to and midway between the canyon walls.
+ ^^
+ A small window can be seen in either wall, some fifty feet up.",
+ s_to In_Secret_N_S_Canyon_0,
+ n_to At_Reservoir;
+
+Object -> "suspended mirror"
+ with name 'mirror' 'massive' 'enormous' 'hanging' 'suspended' 'dwarves^'
+ 'two-sided' 'two' 'sided',
+ description
+ "The mirror is obviously provided for the use of the dwarves who,
+ as you know, are extremely vain.",
+ initial
+ "The mirror is obviously provided for the use of the dwarves,
+ who as you know, are extremely vain.",
+ before [;
+ Attack, Remove:
+ "You can't reach it from here.";
+ ],
+ has static;
+
+! ------------------------------------------------------------------------------
+
+Room At_Window_On_Pit_2 "At Window on Pit"
+ with name 'window' 'on' 'pit' 'west' 'w//',
+ description
+ "You're at a low window overlooking a huge pit, which extends up out of sight.
+ A floor is indistinctly visible over 50 feet below.
+ Traces of white mist cover the floor of the pit, becoming thicker to the left.
+ Marks in the dust around the window would seem to indicate that someone has been here recently.
+ Directly across the pit from you and 25 feet away
+ there is a similar window looking into a lighted room.
+ A shadowy figure can be seen there peering back at you.",
+ w_to At_Junction_Of_Three,
+ cant_go "The only passage is back west to the junction.",
+ before [;
+ Jump:
+ deadflag = 1;
+ "You jump and break your neck!";
+ WaveHands:
+ "The shadowy figure waves back at you!";
+ ];
+
+! ------------------------------------------------------------------------------
+
+Room At_Reservoir "At Reservoir"
+ with name 'reservoir',
+ description
+ "You are at the edge of a large underground reservoir.
+ An opaque cloud of white mist fills the room and rises rapidly upward.
+ The lake is fed by a stream, which tumbles out of a hole in the wall about 10 feet overhead
+ and splashes noisily into the water somewhere within the mist.
+ The only passage goes back toward the south.",
+ s_to In_Mirror_Canyon,
+ out_to In_Mirror_Canyon,
+ before [;
+ Swim:
+ "The water is icy cold, and you would soon freeze to death.";
+ ];
+
+! ------------------------------------------------------------------------------
+! The Chasm and the Troll Bridge
+! ------------------------------------------------------------------------------
+
+Room In_Sloping_Corridor "Sloping Corridor"
+ with name 'sloping' 'corridor',
+ description
+ "You are in a long winding corridor sloping out of sight in both directions.",
+ d_to In_Large_Low_Room,
+ u_to On_Sw_Side_Of_Chasm,
+ cant_go "The corridor slopes steeply up and down.";
+
+Room On_Sw_Side_Of_Chasm "On SW Side of Chasm"
+ with name 'southwest' 'sw' 'side' 'of' 'chasm',
+ description
+ "You are on one side of a large, deep chasm.
+ A heavy white mist rising up from below obscures all view of the far side.
+ A southwest path leads away from the chasm into a winding corridor.",
+ ne_to CrossRicketyBridge,
+ sw_to In_Sloping_Corridor,
+ d_to In_Sloping_Corridor,
+ cant_go "The path winds southwest.",
+ before [;
+ Jump:
+ if (RicketyBridge in self)
+ "I respectfully suggest you go across the bridge instead of jumping.";
+ deadflag = 1;
+ "You didn't make it.";
+ ];
+
+[ CrossRicketyBridge;
+ if (Troll.has_caught_treasure || Troll in nothing) {
+ Troll.has_caught_treasure = false;
+ if (Bear.is_following_you) {
+ remove Bear;
+ remove self;
+ give Wreckage ~absent;
+ remove RicketyBridge;
+ give RicketyBridge absent;
+ StopDaemon(Bear);
+ deadflag = 1;
+ "Just as you reach the other side, the bridge buckles beneath the weight of the bear,
+ which was still following you around.
+ You scrabble desperately for support,
+ but as the bridge collapses you stumble back and fall into the chasm.";
+ }
+ return RicketyBridge;
+ }
+ if (Troll in location) "The troll refuses to let you cross.";
+ move Troll to location;
+ "The troll steps out from beneath the bridge and blocks your way.";
+];
+
+Object -> RicketyBridge "rickety bridge"
+ with name 'bridge' 'rickety' 'unstable' 'wobbly' 'rope',
+ description "It just looks like an ordinary, but unstable, bridge.",
+ describe [;
+ print
+ "A rickety wooden bridge extends across the chasm, vanishing into the mist.
+ ^^
+ A sign posted on the bridge reads, ~Stop! Pay troll!~^";
+ if (Troll notin location)
+ "The troll is nowhere to be seen.";
+ rtrue;
+ ],
+ door_dir [;
+ if (location == On_Sw_Side_Of_Chasm) return ne_to;
+ return sw_to;
+ ],
+ door_to [;
+ if (location == On_Sw_Side_Of_Chasm) return On_Ne_Side_Of_Chasm;
+ return On_Sw_Side_Of_Chasm;
+ ],
+ found_in On_Sw_Side_Of_Chasm On_Ne_Side_Of_Chasm,
+ has static door open;
+
+Object -> -> Troll "burly troll"
+ with name 'troll' 'burly',
+ description
+ "Trolls are close relatives with rocks and have skin as tough as that of a rhinoceros.",
+ initial
+ "A burly troll stands by the bridge
+ and insists you throw him a treasure before you may cross.",
+ life [;
+ Attack:
+ "The troll laughs aloud at your pitiful attempt to injure him.";
+ ThrowAt, Give:
+ if (noun ofclass Treasure) {
+ remove noun;
+ move self to RicketyBridge;
+ self.has_caught_treasure = true;
+ score = score - 5;
+ "The troll catches your treasure and scurries away out of sight.";
+ }
+ if (noun == tasty_food)
+ "Gluttony is not one of the troll's vices. Avarice, however, is.";
+ "The troll deftly catches ", (the) noun,
+ ", examines it carefully, and tosses it back, declaring,
+ ~Good workmanship, but it's not valuable enough.~";
+ Order:
+ "You'll be lucky.";
+ Answer, Ask:
+ "Trolls make poor conversation.";
+ ],
+ has_caught_treasure false,
+ has animate;
+
+Object Wreckage "wreckage of bridge"
+ with name 'wreckage' 'wreck' 'bridge' 'dead' 'bear',
+ initial
+ "The wreckage of the troll bridge (and a dead bear)
+ can be seen at the bottom of the chasm.",
+ before [;
+ "The wreckage is too far below.";
+ ],
+ found_in On_Sw_Side_Of_Chasm On_Ne_Side_Of_Chasm,
+ has static absent;
+
+! ------------------------------------------------------------------------------
+
+Room On_Ne_Side_Of_Chasm "On NE Side of Chasm"
+ with name 'northeast' 'ne' 'side' 'of' 'chasm',
+ description
+ "You are on the far side of the chasm.
+ A northeast path leads away from the chasm on this side.",
+ sw_to CrossRicketyBridge,
+ ne_to In_Corridor,
+ before [;
+ Jump:
+ if (RicketyBridge in self)
+ "I respectfully suggest you go across the bridge instead of jumping.";
+ deadflag = 1;
+ "You didn't make it.";
+ ],
+ has nodwarf;
+
+Room In_Corridor "In Corridor"
+ with name 'corridor',
+ description
+ "You're in a long east/west corridor.
+ A faint rumbling noise can be heard in the distance.",
+ w_to On_Ne_Side_Of_Chasm,
+ e_to At_Fork_In_Path,
+ has nodwarf;
+
+! ------------------------------------------------------------------------------
+! The Volcano
+! ------------------------------------------------------------------------------
+
+Room At_Fork_In_Path "At Fork in Path"
+ with name 'fork' 'in' 'path',
+ description
+ "The path forks here. The left fork leads northeast.
+ A dull rumbling seems to get louder in that direction.
+ The right fork leads southeast down a gentle slope.
+ The main corridor enters from the west.",
+ w_to In_Corridor,
+ ne_to At_Junction_With_Warm_Walls,
+ se_to In_Limestone_Passage,
+ d_to In_Limestone_Passage,
+ has nodwarf;
+
+! ------------------------------------------------------------------------------
+
+Room At_Junction_With_Warm_Walls "At Junction With Warm Walls"
+ with name 'junction' 'with' 'warm' 'walls',
+ description
+ "The walls are quite warm here.
+ From the north can be heard a steady roar,
+ so loud that the entire cave seems to be trembling.
+ Another passage leads south, and a low crawl goes east.",
+ s_to At_Fork_In_Path,
+ n_to At_Breath_Taking_View,
+ e_to In_Chamber_Of_Boulders,
+ has nodwarf;
+
+! ------------------------------------------------------------------------------
+
+Room At_Breath_Taking_View "At Breath-Taking View"
+ with name 'breath-taking' 'breathtaking' 'breath' 'taking' 'view',
+ description
+ "You are on the edge of a breath-taking view.
+ Far below you is an active volcano, from which great gouts of molten lava come surging out,
+ cascading back down into the depths.
+ The glowing rock fills the farthest reaches of the cavern with a blood-red glare,
+ giving everything an eerie, macabre appearance.
+ The air is filled with flickering sparks of ash and a heavy smell of brimstone.
+ The walls are hot to the touch,
+ and the thundering of the volcano drowns out all other sounds.
+ Embedded in the jagged roof far overhead
+ are myriad twisted formations composed of pure white alabaster,
+ which scatter the murky light into sinister apparitions upon the walls.
+ To one side is a deep gorge, filled with a bizarre chaos of tortured rock
+ which seems to have been crafted by the devil himself.
+ An immense river of fire crashes out from the depths of the volcano,
+ burns its way through the gorge, and plummets into a bottomless pit far off to your left.
+ To the right, an immense geyser of blistering steam erupts continuously
+ from a barren island in the center of a sulfurous lake, which bubbles ominously.
+ The far right wall is aflame with an incandescence of its own,
+ which lends an additional infernal splendor to the already hellish scene.
+ A dark, forboding passage exits to the south.",
+ s_to At_Junction_With_Warm_Walls,
+ out_to At_Junction_With_Warm_Walls,
+ d_to "Don't be ridiculous!",
+ before [;
+ Jump:
+ <>;
+ ],
+ has light;
+
+Scenic -> "active volcano"
+ with name 'volcano' 'rock' 'active' 'glowing' 'blood' 'blood-red' 'red'
+ 'eerie' 'macabre',
+ description
+ "Great gouts of molten lava come surging out of the volcano
+ and go cascading back down into the depths.
+ The glowing rock fills the farthest reaches of the cavern with a blood-red glare,
+ giving everything an eerie, macabre appearance.";
+
+Scenic -> "sparks of ash"
+ with name 'spark' 'sparks' 'ash' 'air' 'flickering',
+ description
+ "The sparks too far away for you to get a good look at them.",
+ has multitude;
+
+Scenic -> "jagged roof"
+ with name 'roof' 'formations' 'light' 'apparaitions' 'jagged' 'twsited'
+ 'murky' 'sinister',
+ description
+ "Embedded in the jagged roof far overhead are myriad twisted formations
+ composed of pure white alabaster,
+ which scatter the murky light into sinister apparitions upon the walls.";
+
+Scenic -> "deep gorge"
+ with name 'gorge' 'chaos' 'rock' 'deep' 'bizarre' 'tortured',
+ description
+ "The gorge is filled with a bizarre chaos of tortured rock
+ which seems to have been crafted by the devil himself.";
+
+Scenic -> "river of fire"
+ with name 'river' 'fire' 'depth' 'pit' 'fire' 'fiery' 'bottomless',
+ description
+ "The river of fire crashes out from the depths of the volcano,
+ burns its way through the gorge, and plummets into a bottomless pit far off to your left.";
+
+Scenic -> "immense geyser"
+ with name 'geyser' 'steam' 'island' 'lake' 'immense' 'blistering' 'barren'
+ 'sulfrous' 'sulferous' 'sulpherous' 'sulphrous' 'bubbling',
+ description
+ "The geyser of blistering steam erupts continuously from a barren island
+ in the center of a sulfurous lake, which bubbles ominously.";
+
+! ------------------------------------------------------------------------------
+
+Room In_Chamber_Of_Boulders "In Chamber of Boulders"
+ with name 'chamber' 'of' 'boulders',
+ description
+ "You are in a small chamber filled with large boulders.
+ The walls are very warm, causing the air in the room to be almost stifling from the heat.
+ The only exit is a crawl heading west, through which is coming a low rumbling.",
+ w_to At_Junction_With_Warm_Walls,
+ out_to At_Junction_With_Warm_Walls,
+ has nodwarf;
+
+Scenic -> "boulders"
+ with name 'boulder' 'boulders' 'rocks' 'stones',
+ description "They're just ordinary boulders. They're warm.",
+ before [;
+ LookUnder, Push, Pull:
+ "You'd have to blast them aside.";
+ ],
+ has multitude;
+
+Treasure -> "rare spices"
+ with name 'spices' 'spice' 'rare' 'exotic',
+ article "a selection of",
+ before [;
+ Smell, Examine:
+ "They smell wonderfully exotic!";
+ ],
+ depositpoints 14,
+ has multitude;
+
+! ------------------------------------------------------------------------------
+
+Room In_Limestone_Passage "In Limestone Passage"
+ with name 'limestone' 'passage',
+ description
+ "You are walking along a gently sloping north/south passage
+ lined with oddly shaped limestone formations.",
+ n_to At_Fork_In_Path,
+ u_to At_Fork_In_Path,
+ s_to In_Front_Of_Barren_Room,
+ d_to In_Front_Of_Barren_Room,
+ has nodwarf;
+
+Scenic -> "limestone formations"
+ with name 'formations' 'shape' 'shapes' 'lime' 'limestone' 'stone' 'oddly'
+ 'shaped' 'oddly-shaped',
+ description
+ "Every now and then a particularly strange shape catches your eye.",
+ has multitude;
+
+! ------------------------------------------------------------------------------
+! If you go down to the woods today...
+! ------------------------------------------------------------------------------
+
+Room In_Front_Of_Barren_Room "In Front of Barren Room"
+ with name 'front' 'of' 'entrance' 'to' 'barren' 'room',
+ description
+ "You are standing at the entrance to a large, barren room.
+ A sign posted above the entrance reads: ~Caution! Bear in room!~",
+ w_to In_Limestone_Passage,
+ u_to In_Limestone_Passage,
+ e_to In_Barren_Room,
+ in_to In_Barren_Room,
+ has nodwarf;
+
+Scenic -> "caution sign"
+ with name 'sign' 'barren' 'room' 'caution',
+ description "The sign reads, ~Caution! Bear in room!~";
+
+! ------------------------------------------------------------------------------
+
+Room In_Barren_Room "In Barren Room"
+ with name 'in' 'barren' 'room',
+ description
+ "You are inside a barren room.
+ The center of the room is completely empty except for some dust.
+ Marks in the dust lead away toward the far end of the room.
+ The only exit is the way you came in.",
+ w_to In_Front_Of_Barren_Room,
+ out_to In_Front_Of_Barren_Room,
+ has nodwarf;
+
+Scenic -> "dust"
+ with name 'dust' 'marks',
+ description "It just looks like ordinary dust.";
+
+Object -> Bear "large cave bear"
+ with name 'bear' 'large' 'tame' 'ferocious' 'cave',
+ describe [;
+ if (self.is_following_you)
+ "You are being followed by a very large, tame bear.";
+ if (self.is_friendly == false)
+ "There is a ferocious cave bear eyeing you from the far end of the room!";
+ if (location == In_Barren_Room)
+ "There is a gentle cave bear sitting placidly in one corner.";
+ "There is a contented-looking bear wandering about nearby.";
+ ],
+ life [;
+ Attack:
+ if (axe in player) <>;
+ if (self.is_friendly)
+ "The bear is confused; he only wants to be your friend.";
+ "With what? Your bare hands? Against *his* bear hands??";
+ ThrowAt:
+ if (noun ~= axe) <>;
+ if (self.is_friendly)
+ "The bear is confused; he only wants to be your friend.";
+ move axe to location;
+ axe.is_near_bear = true;
+ "The axe misses and lands near the bear where you can't get at it.";
+ Give:
+ if (noun == tasty_food) {
+ axe.is_near_bear = false;
+ remove tasty_food;
+ self.is_friendly = true;
+ "The bear eagerly wolfs down your food, after which he seems to calm down considerably
+ and even becomes rather friendly.";
+ }
+ if (self.is_friendly)
+ "The bear doesn't seem very interested in your offer.";
+ "Uh-oh -- your offer only makes the bear angrier!";
+ Order, Ask, Answer:
+ "This is a Bear of very little brain.";
+ ],
+ before [;
+ Examine:
+ print "The bear is extremely large, ";
+ if (self.is_friendly) "but appears to be friendly.";
+ "and seems quite ferocious!";
+ Take, Catch:
+ if (self.is_friendly == false) "Surely you're joking!";
+ if (golden_chain has locked)
+ "The bear is still chained to the wall.";
+ self.is_following_you = true;
+ StartDaemon(self);
+ "Ok, the bear's now following you around.";
+ Drop, Release:
+ if (self.is_following_you == false) "What?";
+ self.is_following_you = false;
+ StopDaemon(self);
+ if (Troll in location) {
+ remove Troll;
+ "The bear lumbers toward the troll, who lets out a startled shriek and scurries away.
+ The bear soon gives up the pursuit and wanders back.";
+ }
+ "The bear wanders away from you.";
+ ],
+ daemon [;
+ if (location == thedark) rfalse;
+ if (self in location) {
+ if (location == At_Breath_Taking_View)
+ "^The bear roars with delight.";
+ rfalse;
+ }
+ move self to location;
+ "^The bear lumbers along behind you.";
+ ],
+ is_following_you false,
+ is_friendly false,
+ has animate;
+
+Treasure -> golden_chain "golden chain"
+ with name 'chain' 'links' 'shackles' 'solid' 'gold' 'golden' 'thick' 'chains',
+ description "The chain has thick links of solid gold!",
+ describe [;
+ if (self has locked)
+ "The bear is held back by a solid gold chain.";
+ "A solid golden chain lies in coils on the ground!";
+ ],
+ with_key set_of_keys,
+ before [;
+ Take:
+ if (self has locked) {
+ if (Bear.is_friendly) "It's locked to the friendly bear.";
+ "It's locked to the ferocious bear!";
+ }
+ Unlock:
+ if (Bear.is_friendly == false)
+ "There is no way to get past the bear to unlock the chain,
+ which is probably just as well.";
+ Lock:
+ if (self hasnt locked) "The mechanism won't lock again.";
+ ],
+ after [;
+ Unlock:
+ "You unlock the chain, and set the tame bear free.";
+ ],
+ depositpoints 14,
+ has lockable locked;
+
+! ------------------------------------------------------------------------------
+! The Different Maze
+! ------------------------------------------------------------------------------
+
+Class DiffmazeRoom
+ with short_name "Maze";
+
+DiffmazeRoom Different_Maze_1
+ with description "You are in a maze of twisty little passages, all different.",
+ s_to Different_Maze_3,
+ sw_to Different_Maze_4,
+ ne_to Different_Maze_5,
+ se_to Different_Maze_6,
+ u_to Different_Maze_7,
+ nw_to Different_Maze_8,
+ e_to Different_Maze_9,
+ w_to Different_Maze_10,
+ n_to Different_Maze_11,
+ d_to At_West_End_Of_Long_Hall;
+
+DiffmazeRoom Different_Maze_2
+ with description "You are in a little maze of twisting passages, all different.",
+ sw_to Different_Maze_3,
+ n_to Different_Maze_4,
+ e_to Different_Maze_5,
+ nw_to Different_Maze_6,
+ se_to Different_Maze_7,
+ ne_to Different_Maze_8,
+ w_to Different_Maze_9,
+ d_to Different_Maze_10,
+ u_to Different_Maze_11,
+ s_to Dead_End_14;
+
+DiffmazeRoom Different_Maze_3
+ with description "You are in a maze of twisting little passages, all different.",
+ w_to Different_Maze_1,
+ se_to Different_Maze_4,
+ nw_to Different_Maze_5,
+ sw_to Different_Maze_6,
+ ne_to Different_Maze_7,
+ u_to Different_Maze_8,
+ d_to Different_Maze_9,
+ n_to Different_Maze_10,
+ s_to Different_Maze_11,
+ e_to Different_Maze_2;
+
+DiffmazeRoom Different_Maze_4
+ with description "You are in a little maze of twisty passages, all different.",
+ nw_to Different_Maze_1,
+ u_to Different_Maze_3,
+ n_to Different_Maze_5,
+ s_to Different_Maze_6,
+ w_to Different_Maze_7,
+ sw_to Different_Maze_8,
+ ne_to Different_Maze_9,
+ e_to Different_Maze_10,
+ d_to Different_Maze_11,
+ se_to Different_Maze_2;
+
+DiffmazeRoom Different_Maze_5
+ with description "You are in a twisting maze of little passages, all different.",
+ u_to Different_Maze_1,
+ d_to Different_Maze_3,
+ w_to Different_Maze_4,
+ ne_to Different_Maze_6,
+ sw_to Different_Maze_7,
+ e_to Different_Maze_8,
+ n_to Different_Maze_9,
+ nw_to Different_Maze_10,
+ se_to Different_Maze_11,
+ s_to Different_Maze_2;
+
+DiffmazeRoom Different_Maze_6
+ with description "You are in a twisting little maze of passages, all different.",
+ ne_to Different_Maze_1,
+ n_to Different_Maze_3,
+ nw_to Different_Maze_4,
+ se_to Different_Maze_5,
+ e_to Different_Maze_7,
+ d_to Different_Maze_8,
+ s_to Different_Maze_9,
+ u_to Different_Maze_10,
+ w_to Different_Maze_11,
+ sw_to Different_Maze_2;
+
+DiffmazeRoom Different_Maze_7
+ with description "You are in a twisty little maze of passages, all different.",
+ n_to Different_Maze_1,
+ se_to Different_Maze_3,
+ d_to Different_Maze_4,
+ s_to Different_Maze_5,
+ e_to Different_Maze_6,
+ w_to Different_Maze_8,
+ sw_to Different_Maze_9,
+ ne_to Different_Maze_10,
+ nw_to Different_Maze_11,
+ u_to Different_Maze_2;
+
+DiffmazeRoom Different_Maze_8
+ with description "You are in a twisty maze of little passages, all different.",
+ e_to Different_Maze_1,
+ w_to Different_Maze_3,
+ u_to Different_Maze_4,
+ sw_to Different_Maze_5,
+ d_to Different_Maze_6,
+ s_to Different_Maze_7,
+ nw_to Different_Maze_9,
+ se_to Different_Maze_10,
+ ne_to Different_Maze_11,
+ n_to Different_Maze_2;
+
+DiffmazeRoom Different_Maze_9
+ with description "You are in a little twisty maze of passages, all different.",
+ se_to Different_Maze_1,
+ ne_to Different_Maze_3,
+ s_to Different_Maze_4,
+ d_to Different_Maze_5,
+ u_to Different_Maze_6,
+ nw_to Different_Maze_7,
+ n_to Different_Maze_8,
+ sw_to Different_Maze_10,
+ e_to Different_Maze_11,
+ w_to Different_Maze_2;
+
+DiffmazeRoom Different_Maze_10
+ with description "You are in a maze of little twisting passages, all different.",
+ d_to Different_Maze_1,
+ e_to Different_Maze_3,
+ ne_to Different_Maze_4,
+ u_to Different_Maze_5,
+ w_to Different_Maze_6,
+ n_to Different_Maze_7,
+ s_to Different_Maze_8,
+ se_to Different_Maze_9,
+ sw_to Different_Maze_11,
+ nw_to Different_Maze_2;
+
+DiffmazeRoom Different_Maze_11
+ with description "You are in a maze of little twisty passages, all different.",
+ sw_to Different_Maze_1,
+ nw_to Different_Maze_3,
+ e_to Different_Maze_4,
+ w_to Different_Maze_5,
+ n_to Different_Maze_6,
+ d_to Different_Maze_7,
+ se_to Different_Maze_8,
+ u_to Different_Maze_9,
+ s_to Different_Maze_10,
+ ne_to Different_Maze_2;
+
+! ------------------------------------------------------------------------------
+
+DeadendRoom Dead_End_14
+ class Room
+ with name 'dead' 'end' 'near' 'vending' 'machine',
+ short_name "Dead End, near Vending Machine",
+ description
+ "You have reached a dead end. There is a massive vending machine here.
+ ^^
+ Hmmm... There is a message here scrawled in the dust in a flowery script.",
+ n_to Different_Maze_2,
+ out_to Different_Maze_2,
+ has nodwarf;
+
+Scenic -> "message in the dust"
+ with name 'message' 'scrawl' 'writing' 'script' 'scrawled' 'flowery',
+ description
+ "The message reads, ~This is not the maze where the pirate leaves
+ his treasure chest.~";
+
+Scenic -> VendingMachine "vending machine"
+ with name 'machine' 'slot' 'vending' 'massive' 'battery' 'coin',
+ description
+ "The instructions on the vending machine read,
+ ~Insert coins to receive fresh batteries.~",
+ before [;
+ Receive:
+ if (noun == rare_coins) {
+ move fresh_batteries to location;
+ remove rare_coins;
+ "Soon after you insert the coins in the coin slot,
+ the vending machine makes a grinding sound, and a set of fresh batteries falls at your feet.";
+ }
+ "The machine seems to be designed to take coins.";
+ Attack:
+ "The machine is quite sturdy and survives your attack without getting so much as a scratch.";
+ LookUnder:
+ "You don't find anything under the machine.";
+ Search:
+ "You can't get inside the machine.";
+ Take:
+ "The vending machine is far too heavy to move.";
+ ];
+
+Object fresh_batteries "fresh batteries" VendingMachine
+ with name 'batteries' 'battery' 'fresh',
+ description
+ "They look like ordinary batteries. (A sepulchral voice says, ~Still going!~)",
+ initial "There are fresh batteries here.",
+ before [;
+ Count:
+ "A pair.";
+ ],
+ have_been_used false;
+
+Object old_batteries "worn-out batteries"
+ with name 'batteries' 'battery' 'worn' 'out' 'worn-out',
+ description "They look like ordinary batteries.",
+ initial "Some worn-out batteries have been discarded nearby.",
+ before [;
+ Count:
+ "A pair.";
+ ];
+
+! ------------------------------------------------------------------------------
+! Dwarves!
+! ------------------------------------------------------------------------------
+
+Object dwarf "threatening little dwarf"
+ with name 'dwarf' 'threatening' 'nasty' 'little' 'mean',
+ description
+ "It's probably not a good idea to get too close.
+ Suffice it to say the little guy's pretty aggressive.",
+ initial "A threatening little dwarf hides in the shadows.",
+ number 5,
+ daemon [;
+ if (location == thedark) return;
+ if (self.number == 0) {
+ StopDaemon(self);
+ return;
+ }
+ if (parent(self) == nothing) {
+ if (location has nodwarf || location has light) return;
+ if (random(100) <= self.number) {
+ if (Bear in location || Troll in location) return;
+ new_line;
+ if (Dragon in location) {
+ self.number--;
+ "A dwarf appears, but with one casual blast the dragon vapourises him!";
+ }
+ move self to location;
+ "A threatening little dwarf comes out of the shadows!";
+ }
+ return;
+ }
+ if (parent(self) ~= location) {
+ if (location == thedark) return;
+ if (location has nodwarf || location has light) return;
+ if (random(100) <= 96 && parent(self) ~= In_Mirror_Canyon) {
+ move self to location;
+ print "^The dwarf stalks after you...^";
+ }
+ else {
+ remove self;
+ return;
+ }
+ }
+ if (random(100) <= 75) {
+ new_line;
+ if (self.has_thrown_axe == false) {
+ move axe to location;
+ self.has_thrown_axe = true;
+ remove self;
+ "The dwarf throws a nasty little axe at you, misses,
+ curses, and runs away.";
+ }
+ if (location == In_Mirror_Canyon)
+ "The dwarf admires himself in the mirror.";
+ print "The dwarf throws a nasty little knife at you, ";
+ if (random(1000) <= 95) {
+ deadflag = 1;
+ "and hits!";
+ }
+ "but misses!";
+ }
+ if (random(3) == 1) {
+ remove self;
+ "^Tiring of this, the dwarf slips away.";
+ }
+ ],
+ before [;
+ Kick:
+ "You boot the dwarf across the room. He curses, then gets up and brushes himself off.
+ Now he's madder than ever!";
+ ],
+ life [;
+ ThrowAt:
+ if (noun == axe) {
+ if (random(3) ~= 1) {
+ remove self;
+ move axe to location;
+ self.number--;
+ "You killed a little dwarf! The body vanishes in a cloud of greasy black smoke.";
+ }
+ move axe to location;
+ "Missed! The little dwarf dodges out of the way of the axe.";
+ }
+ <>;
+ Give:
+ if (noun == tasty_food)
+ "You fool, dwarves eat only coal! Now you've made him *really* mad!";
+ "The dwarf is not at all interested in your offer. (The reason being,
+ perhaps, that if he kills you he gets everything you have anyway.)";
+ Attack:
+ "Not with your bare hands. No way.";
+ ],
+ has_thrown_axe false,
+ has animate;
+
+Object axe "dwarvish axe"
+ with name 'axe' 'little' 'dwarvish' 'dwarven',
+ description "It's just a little axe.",
+ initial "There is a little axe here.",
+ before [;
+ if (~~self.is_near_bear) rfalse;
+ Examine:
+ "It's lying beside the bear.";
+ Take:
+ "No chance. It's lying beside the ferocious bear, quite within harm's way.";
+ ],
+ is_near_bear false;
+
+! ------------------------------------------------------------------------------
+! Two brushes with piracy
+! ------------------------------------------------------------------------------
+
+Object pirate
+ with daemon [ obj booty_nearby;
+ if (random(100) > 2 || location == thedark or In_Secret_Canyon ||
+ location has light || location has nodwarf) return;
+ if (dwarf in location)
+ "^A bearded pirate appears, catches sight of the dwarf and runs away.";
+ objectloop (obj ofclass Treasure && obj in player or location)
+ booty_nearby = true;
+ if (booty_nearby == false) {
+ if (self.has_been_spotted) return;
+ self.has_been_spotted = true;
+ if (self.has_stolen_something) StopDaemon(self);
+ "^There are faint rustling noises from the darkness behind you.
+ As you turn toward them, you spot a bearded pirate.
+ He is carrying a large chest.
+ ^^
+ ~Shiver me timbers!~ he cries, ~I've been spotted!
+ I'd best hie meself off to the maze to hide me chest!~
+ ^^
+ With that, he vanishes into the gloom.";
+ }
+ if (self.has_stolen_something) return;
+ self.has_stolen_something = true;
+ if (self.has_been_spotted) StopDaemon(self);
+ objectloop (obj ofclass Treasure && obj in player or location) {
+ if (obj in player) score = score - 5;
+ move obj to Dead_End_13;
+ }
+ "^Out from the shadows behind you pounces a bearded pirate!
+ ~Har, har,~ he chortles. ~I'll just take all this booty and hide it away
+ with me chest deep in the maze!~
+ He snatches your treasure and vanishes into the gloom.";
+ ],
+ has_stolen_something false,
+ has_been_spotted false;
+
+! ----------------------------------------------------------------------------
+! The cave is closing now...
+! ----------------------------------------------------------------------------
+
+Object cave_closer
+ with daemon [;
+ if (treasures_found < MAX_TREASURES) return;
+ StopDaemon(self);
+ caves_closed = true;
+ score = score + 25;
+ remove CrystalBridge;
+ give Grate locked ~open;
+ remove set_of_keys;
+ StopDaemon(dwarf);
+ StopDaemon(pirate);
+ remove Troll;
+ remove Bear;
+ remove Dragon;
+ StartTimer(endgame_timer, 25);
+ "^A sepulchral voice reverberating through the cave says, ~Cave
+ closing soon. All adventurers exit immediately through main office.~";
+ ];
+
+Object endgame_timer
+ with time_left 0,
+ time_out [;
+ score = score + 10;
+ while (child(player)) remove child(player);
+ move bottle to At_Ne_End;
+ if (child(bottle)) remove child(bottle);
+ move giant_bivalve to At_Ne_End;
+ move brass_lantern to At_Ne_End;
+ move black_rod to At_Ne_End;
+ move little_bird to At_Sw_End;
+ move velvet_pillow to At_Sw_End;
+ print
+ "^The sepulchral voice intones, ~The cave is now closed.~
+ As the echoes fade, there is a blinding flash of light
+ (and a small puff of orange smoke). . .
+ ^^
+ As your eyes refocus, you look around...^";
+ PlayerTo(At_Ne_End);
+ ];
+
+! ------------------------------------------------------------------------------
+! The End Game
+! ------------------------------------------------------------------------------
+
+Room At_Ne_End "NE End of Repository"
+ with name 'northeast' 'ne' 'end' 'of' 'repository',
+ description
+ "You are at the northeast end of an immense room, even larger than the giant room.
+ It appears to be a repository for the ~Adventure~ program.
+ Massive torches far overhead bathe the room with smoky yellow light.
+ Scattered about you can be seen a pile of bottles (all of them empty),
+ a nursery of young beanstalks murmuring quietly, a bed of oysters,
+ a bundle of black rods with rusty stars on their ends, and a collection of brass lanterns.
+ Off to one side a great many dwarves are sleeping on the floor, snoring loudly.
+ A sign nearby reads: ~Do not disturb the dwarves!~",
+ sw_to At_Sw_End,
+ has light;
+
+Object -> "enormous mirror"
+ with name 'mirror' 'enormous' 'huge' 'big' 'large' 'suspended' 'hanging'
+ 'vanity' 'dwarvish',
+ description "It looks like an ordinary, albeit enormous, mirror.",
+ initial
+ "An immense mirror is hanging against one wall, and stretches to the other end of the room,
+ where various other sundry objects can be glimpsed dimly in the distance.",
+ before [;
+ Attack:
+ print
+ "You strike the mirror a resounding blow,
+ whereupon it shatters into a myriad tiny fragments.^^";
+ SleepingDwarves.wake_up();
+ rtrue;
+ ],
+ found_in At_Ne_End At_Sw_End,
+ has static;
+
+Scenic -> "collection of adventure game materials"
+ with name 'stuff' 'junk' 'materials' 'torches' 'objects' 'adventure'
+ 'repository' 'massive' 'sundry',
+ description
+ "You've seen everything in here already, albeit in somewhat different contexts.",
+ before [;
+ Take:
+ "Realizing that by removing the loot here you'd be ruining the game for future players,
+ you leave the ~Adventure~ materials where they are.";
+ ];
+
+Scenic -> SleepingDwarves "sleeping dwarves"
+ with name 'dwarf' 'dwarves' 'sleeping' 'snoring' 'dozing' 'snoozing',
+ article "hundreds of angry",
+ description "I wouldn't bother the dwarves if I were you.",
+ before [;
+ Take:
+ "What, all of them?";
+ ],
+ life [;
+ WakeOther:
+ print
+ "You prod the nearest dwarf, who wakes up grumpily,
+ takes one look at you, curses, and grabs for his axe.^^";
+ self.wake_up();
+ rtrue;
+ Attack:
+ self.wake_up();
+ rtrue;
+ ],
+ wake_up [;
+ deadflag = 1;
+ "The resulting ruckus has awakened the dwarves.
+ There are now dozens of threatening little dwarves in the room with you!
+ Most of them throw knives at you! All of them get you!";
+ ],
+ has animate multitude;
+
+! ------------------------------------------------------------------------------
+
+Room At_Sw_End "SW End of Repository"
+ with name 'southwest' 'sw' 'end' 'of' 'repository',
+ description
+ "You are at the southwest end of the repository.
+ To one side is a pit full of fierce green snakes.
+ On the other side is a row of small wicker cages, each of which contains a little sulking bird.
+ In one corner is a bundle of black rods with rusty marks on their ends.
+ A large number of velvet pillows are scattered about on the floor.
+ A vast mirror stretches off to the northeast.
+ At your feet is a large steel grate, next to which is a sign which reads,
+ ~TREASURE VAULT. Keys in main office.~",
+ d_to RepositoryGrate,
+ ne_to At_Ne_End,
+ has light;
+
+Object -> RepositoryGrate "steel grate"
+ with name 'ordinary' 'steel' 'grate' 'grating',
+ description "It just looks like an ordinary steel grate.",
+ when_open "The grate is open.",
+ when_closed "The grate is closed.",
+ door_dir d_to,
+ door_to Outside_Grate,
+ with_key nothing,
+ has static door locked openable;
+
+Scenic -> "collection of adventure game materials"
+ with name 'pit' 'snake' 'snakes' 'fierce' 'green' 'stuff' 'junk' 'materials'
+ 'adventure' 'repository' 'massive' 'sundry',
+ description
+ "You've seen everything in here already, albeit in somewhat different contexts.",
+ before [;
+ Take:
+ "Realizing that by removing the loot here you'd be ruining the game for future players,
+ you leave the ~Adventure~ materials where they are.";
+ ];
+
+Object -> black_mark_rod "black rod with a rusty mark on the end"
+ with name 'rod' 'black' 'rusty' 'mark' 'three' 'foot' 'iron' 'explosive'
+ 'dynamite' 'blast',
+ description "It's a three foot black rod with a rusty mark on an end.",
+ initial
+ "A three foot black rod with a rusty mark on one end lies nearby.",
+ before [;
+ Wave:
+ "Nothing happens.";
+ ];
+
+! ------------------------------------------------------------------------------
+! Some entry points
+! ------------------------------------------------------------------------------
+
+[ Initialise;
+ location = At_End_Of_Road;
+ score = 36;
+ StartDaemon(dwarf);
+ StartDaemon(pirate);
+ StartDaemon(cave_closer);
+ "^^^^^Welcome to Adventure!^
+ (Please type HELP for instructions and information.)^^";
+];
+
+[ PrintRank;
+ print ", earning you the rank of ";
+ if (score >= 348) "Grandmaster Adventurer!";
+ if (score >= 330) "Master, first class.";
+ if (score >= 300) "Master, second class.";
+ if (score >= 200) "Junior Master.";
+ if (score >= 130) "Seasoned Adventurer.";
+ if (score >= 100) "Experienced Adventurer.";
+ if (score >= 35) "Adventurer.";
+ if (score >= 10) "Novice.";
+ "Amateur.";
+];
+
+[ DarkToDark;
+ if (dark_warning == false) {
+ dark_warning = true;
+ "It is now pitch dark. If you proceed you will likely fall into a pit.";
+ }
+ if (random(4) == 1) {
+ deadflag = 1;
+ "You fell into a pit and broke every bone in your body!";
+ }
+ rfalse;
+];
+
+[ UnknownVerb word
+ obj;
+ objectloop (obj ofclass Room) {
+ if (obj has visited && WordInProperty(word, obj, name)) {
+ verb_wordnum = 0;
+ return 'go';
+ }
+ }
+ rfalse;
+];
+
+! ------------------------------------------------------------------------------
+! Resurrection
+! ------------------------------------------------------------------------------
+
+[ AfterLife o;
+ if (deadflag == 3) {
+ deadflag = 1;
+ rfalse;
+ }
+ print "^^";
+ if (caves_closed)
+ "It looks as though you're dead. Well, seeing as how it's so close to closing time anyway,
+ I think we'll just call it a day.";
+ switch (deaths) {
+ 0:
+ print
+ "Oh dear, you seem to have gotten yourself killed.
+ I might be able to help you out, but I've never really done this before.
+ Do you want me to try to reincarnate you?^^";
+ 1:
+ print
+ "You clumsy oaf, you've done it again!
+ I don't know how long I can keep this up.
+ Do you want me to try reincarnating you again?^^";
+ 2:
+ print
+ "Now you've really done it! I'm out of orange smoke!
+ You don't expect me to do a decent reincarnation without any orange smoke, do you?^^";
+ }
+ print "> ";
+ if (YesOrNo() == false) {
+ switch (deaths) {
+ 0: "Very well.";
+ 1: "Probably a wise choice.";
+ 2: "I thought not!";
+ }
+ }
+ switch (deaths) {
+ 0:
+ print
+ "All right. But don't blame me if something goes wr......
+ ^^^^
+ --- POOF!! ---
+ ^^
+ You are engulfed in a cloud of orange smoke.
+ Coughing and gasping, you emerge from the smoke and find that you're....^";
+ 1:
+ print
+ "Okay, now where did I put my orange smoke?.... >POOF!<
+ ^^
+ Everything disappears in a dense cloud of orange smoke.^";
+ 2:
+ "Okay, if you're so smart, do it yourself! I'm leaving!";
+ }
+ deaths++;
+ score = score - 10;
+ if (location ~= thedark) {
+ while (child(player)) {
+ o = child(player);
+ move o to location;
+ if (o ofclass Treasure) score = score - 5;
+ }
+ }
+ else {
+ while (child(player)) {
+ o = child(player);
+ move o to real_location;
+ if (o ofclass Treasure) score = score - 5;
+ }
+ }
+ move brass_lantern to At_End_Of_Road;
+ give brass_lantern ~on ~light;
+ remove dwarf;
+ deadflag = 0;
+ PlayerTo(Inside_Building);
+];
+
+! ------------------------------------------------------------------------------
+! Menu-driven help (not really a part of the game itself)
+! ------------------------------------------------------------------------------
+
+[ HelpMenu;
+ if (menu_item == 0) {
+ item_width = 8;
+ item_name = "About Adventure";
+ if (deadflag == 2) return 4;
+ else return 3;
+ }
+ if (menu_item == 1) {
+ item_width = 6;
+ item_name = "Instructions";
+ }
+ if (menu_item == 2) {
+ item_width = 4;
+ item_name = "History";
+ }
+ if (menu_item == 3) {
+ item_width = 6;
+ item_name = "Authenticity";
+ }
+ if (menu_item == 4) {
+ item_width = 7;
+ item_name = "Did you know...";
+ }
+];
+
+[ HelpInfo;
+ if (menu_item == 1) {
+ print
+ "I know of places, actions, and things.
+ You can guide me using commands that are complete sentences.
+ To move, try commands like ~enter,~ ~east,~ ~west,~ ~north,~ ~south,~
+ ~up,~ ~down,~ ~enter building,~ ~climb pole,~ etc.^^";
+ print
+ "I know about a few special objects, like a black rod hidden in the cave.
+ These objects can be manipulated using some of the action words that I know.
+ Usually you will need to give a verb followed by an object
+ (along with descriptive adjectives when desired),
+ but sometimes I can infer the object from the verb alone.
+ Some objects also imply verbs; in particular, ~inventory~ implies ~take inventory~,
+ which causes me to give you a list of what you're carrying.
+ The objects have side effects; for instance, the rod scares the bird.^^";
+ print
+ "Many commands have abbreviations.
+ For example, you can type ~i~ in place of ~inventory,~
+ ~x object~ instead of ~examine object,~ etc.^^";
+ print
+ "Usually people having trouble moving just need to try a few more words.
+ Usually people trying unsuccessfully to manipulate an object are attempting
+ something beyond their (or my!) capabilities and should try a completely different tack.^^";
+ print
+ "Note that cave passages turn a lot, and that leaving a room to the north
+ does not guarantee entering the next from the south.^^";
+ print
+ "If you want to end your adventure early, type ~quit~.
+ To suspend your adventure such that you can continue later, type ~save,~
+ and to resume a saved game, type ~restore.~
+ To see how well you're doing, type ~score~.
+ To get full credit for a treasure, you must have left it safely in the building,
+ though you get partial credit just for locating it.
+ You lose points for getting killed, or for quitting, though the former costs you more.
+ There are also points based on how much (if any) of the cave you've managed to explore;
+ in particular, there is a large bonus just for getting in
+ (to distinguish the beginners from the rest of the pack),
+ and there are other ways to determine whether you've been through
+ some of the more harrowing sections.^^";
+ print
+ "If you think you've found all the treasures, just keep exploring for a while.
+ If nothing interesting happens, you haven't found them all yet.
+ If something interesting *does* happen, it means you're getting a bonus
+ and have an opportunity to garner many more points in the master's section.^^";
+ "Good luck!";
+ }
+ if (menu_item == 2) {
+ print
+ "Perhaps the first adventurer was a mulatto slave named Stephen Bishop, born about 1820:
+ `slight, graceful, and very handsome'; a `quick, daring, enthusiastic' guide
+ to the Mammoth Cave in the Kentucky karst.
+ The story of the Cave is a curious microcosm of American history.
+ Its discovery is a matter of legend dating back to the 1790s;
+ it is said that a hunter, John Houchin, pursued a wounded bear to a large pit
+ near the Green River and stumbled upon the entrance.
+ The entrance was thick with bats and by the War of 1812 was intensively mined for guano,
+ dissolved into nitrate vats to make saltpetre for gunpowder.
+ After the war prices fell; but the Cave became a minor side-show when a dessicated
+ Indian mummy was found nearby, sitting upright in a stone coffin, surrounded by talismans.
+ In 1815, Fawn Hoof, as she was nicknamed after one of the charms,
+ was taken away by a circus, drawing crowds across America
+ (a tour rather reminiscent of Don McLean's song `The Legend of Andrew McCrew').
+ She ended up in the Smithsonian but by the 1820s the Cave was being called
+ one of the wonders of the world, largely due to her posthumous efforts.^^";
+ print
+ "By the early nineteenth century European caves were big tourist attractions,
+ but hardly anyone visited the Mammoth, `wonder of the world' or not.
+ Nor was it then especially large (the name was a leftover from the miners,
+ who boasted of their mammoth yields of guano).
+ In 1838, Stephen Bishop's owner bought up the Cave.
+ Stephen, as (being a slave) he was invariably called, was by any standards a remarkable man:
+ self-educated in Latin and Greek, he became famous as the `chief ruler' of his underground realm.
+ He explored and named much of the layout in his spare time, doubling the known map in a year.
+ The distinctive flavour of the Cave's names -- half-homespun American, half-classical --
+ started with Stephen: the River Styx, the Snowball Room, Little Bat Avenue, the Giant Dome.
+ Stephen found strange blind fish, snakes, silent crickets, the remains of cave bears
+ (savage, playful creatures, five feet long and four high, which became extinct
+ at the end of the last Ice Age), centuries-old Indian gypsum workings and ever more cave.
+ His 1842 map, drafted entirely from memory, was still in use forty years later.^^";
+ print
+ "As a tourist attraction (and, since Stephen's owner was a philanthropist,
+ briefly a sanatorium for tuberculosis, owing to a hopeless medical theory)
+ the Cave became big business: for decades nearby caves were hotly seized
+ and legal title endlessly challenged.
+ The neighbouring chain, across Houchins Valley in the Flint Ridge,
+ opened the Great Onyx Cave in 1912.
+ By the 1920s, the Kentucky Cave Wars were in full swing.
+ Rival owners diverted tourists with fake policemen, employed stooges
+ to heckle each other's guided tours, burned down ticket huts,
+ put out libellous and forged advertisements.
+ Cave exploration became so dangerous and secretive that finally in 1941 the U.S. Government
+ stepped in, made much of the area a National Park and effectively banned caving.
+ The gold rush of tourists was, in any case, waning.^^";
+ print
+ "Convinced that the Mammoth and Flint Ridge caves were all linked in a huge chain,
+ explorers tried secret entrances for years, eventually winning official backing.
+ Throughout the 1960s all connections from Flint Ridge -- difficult and water-filled tunnels
+ -- ended frustratingly in chokes of boulders.
+ A `reed-thin' physicist, Patricia Crowther, made the breakthrough in 1972
+ when she got through the Tight Spot and found a muddy passage:
+ it was a hidden way into the Mammoth Cave.^^";
+ print
+ "Under the terms of his owner's will, Stephen Bishop was freed in 1856,
+ at which time the cave boasted 226 avenues, 47 domes, 23 pits and 8 waterfalls.
+ He died a year later, before he could buy his wife and son.
+ In the 1970s, Crowther's muddy passage was found on his map.^^";
+ print
+ "The Mammoth Cave is huge, its full extent still a matter of speculation
+ (estimates vary from 300 to 500 miles).
+ Although this game has often been called ~Colossal Cave~,
+ it is actually a simulation of the Bedquilt Cave region.
+ Here is Will Crowther's story of how it came about:^^";
+ print
+ "~I had been involved in a non-computer role-playing game called Dungeons and Dragons
+ at the time, and also I had been actively exploring in caves --
+ Mammoth Cave in Kentucky in particular.
+ Suddenly, I got involved in a divorce, and that left me a bit pulled apart in various ways.
+ In particular I was missing my kids.
+ Also the caving had stopped, because that had become awkward,
+ so I decided I would fool around and write a program that was a re-creation
+ in fantasy of my caving, and also would be a game for the kids,
+ and perhaps some aspects of the Dungeons and Dragons that I had been playing.^^";
+ print
+ "~My idea was that it would be a computer game that would not be intimidating
+ to non-computer people, and that was one of the reasons why I made it so that
+ the player directs the game with natural language input, instead of more standardized commands.
+ My kids thought it was a lot of fun.~
+ [Quoted in ~Genesis II: Creation and Recreation with Computers~, Dale Peterson (1983).]^^";
+ print
+ "Crowther's original FORTRAN program had five or so treasures, but no formal scoring.
+ The challenge was really to explore, though there was opposition from for instance the snake.
+ Like the real Bedquilt region, Crowther's simulation has a map on about four levels
+ of depth and is rich in geological detail.
+ A good example is the orange column which descends to the Orange River Rock room
+ (where the bird lives): the real column is of orange travertine,
+ a beautiful mineral found in wet limestone.^^";
+ print
+ "The game's language is loaded with references to caving, to `domes' and `crawls'.
+ A `slab room', for instance, is a very old cave whose roof has begun to break away
+ into sharp flakes which litter the floor in a crazy heap.
+ The program's use of the word `room' for all manner of caves and places
+ seems slightly sloppy in everyday English, but is widespread in American caving
+ and goes back as far as Stephen Bishop: so the Adventure-games usage of the word `room'
+ to mean `place' may even be bequeathed from him.^^";
+ print
+ "The game took its decisive step toward puzzle-solving when Don Woods, a student at Stanford,
+ debugged and expanded it.
+ He tripled the number of treasures and added the non-geological zones:
+ everything from the Troll Bridge onward, together with most of the antechambers on the Bedquilt level.
+ All of the many imitations and extensions of the original Adventure
+ are essentially based on Woods's 350-point edition.
+ (Many bloated, corrupted or enhanced -- it depends how you see it --
+ versions of the game are in Internet circulation, and the most useful way to identify them
+ is by the maximum attainable score.
+ Many versions exist scoring up to around the 400s and 500s, and one up to 1000.
+ Woods himself continues to release new versions of his game;
+ most of the other extenders haven't his talent.)^^";
+ print
+ "Although the game has veered away from pure simulation, a good deal of it remains realistic.
+ Cavers do turn back when their carbide lamps flicker;
+ there are indeed mysterious markings and initials on the cave walls, some left by the miners,
+ some by Bishop, some by 1920s explorers.
+ Of course there isn't an active volcano in central Kentucky, nor are there dragons and dwarves.
+ But even these embellishments are, in a sense, derived from tradition:
+ like most of the early role-playing games, `Adventure' owes much to J. R. R. Tolkien's
+ `The Hobbit', and the passage through the mountains and Moria of `The Lord of the Rings'
+ (arguably its most dramatic and atmospheric passage).
+ Tolkien himself, the most successful myth-maker of the twentieth century,
+ worked from the example of Icelandic, Finnish and Welsh sagas.^^";
+ print
+ "By 1977 tapes of `Adventure' were being circulated widely, by the Digital user group DECUS,
+ amongst others: taking over lunchtimes and weekends wherever it went... but that's another story.
+ (Tracy Kidder's fascinating book `The Soul of a New Machine', a journalist's-eye-view
+ of a mainframe computer development group, catches it well.)^^";
+ "This is a copy at third or fourth hand: from Will Crowther's original
+ to Donald Woods's 350-point edition to Donald Ekman's PC port to
+ David M. Baggett's excellent TADS version (1993), to this.^^";
+ }
+ if (menu_item == 3) {
+ print
+ "This port is fairly close to the original.
+ The puzzles, items and places of Woods's original 350-point version are exactly those here.^^";
+ print
+ "I have added a few helpful messages, such as ~This is a dead end.~, here and there:
+ and restored some ~initial position~ messages from objects, such as the (rather lame)
+ ^^ There is tasty food here.^^
+ from source files which are certainly early but of doubtful provenance.
+ They seem to sit well with the rest of the text.^^";
+ print
+ "The scoring system is the original, except that you no longer lose 4 points for quitting
+ (since you don't get the score if you quit an Inform game, this makes no difference)
+ and, controversially, I award 5 points for currently carrying a treasure, as some early 1980s ports did.
+ The rank names are tidied up a little.
+ The only significant rule change is that one cannot use magic words
+ until their destinations have been visited.^^";
+ print
+ "The dwarves are simpler in their movements, but on the other hand I have added
+ a very few messages to make them interact better with the rest of the game.
+ The probabilities are as in the original game.^^";
+ print
+ "In the original one could type the name of a room to visit it:
+ for the sake of keeping the code small, I have omitted this feature, but with some regrets.
+ [RF: this feature incorporated into Release 9.]^^";
+ print
+ "The text itself is almost everywhere preserved intact, but I've corrected some
+ spelling and grammatical mistakes (and altered a couple of utterly misleading and gnomic remarks).
+ The instructions have been slightly altered (for obvious reasons) but are basically as written.^^";
+ "A good source for details is David Baggett's source code, which is circulated on the Internet.";
+ }
+ print "Did you know that...^^";
+ print
+ "The five dwarves have a 96% chance of following you, except into light, down pits or
+ when admiring themselves: and the nasty little knives are 9.5% accurate.^^";
+ print "Dragons burn up dwarves (perhaps because dwarves eat only coal).^^";
+ print
+ "The bear (who likes the volcano) is too heavy for the bridge...
+ and you can go back to the scene after being resurrected.^^";
+ print
+ "You can slip past the snake into the secret E/W canyon, 35% of the time at any rate.
+ And walking about in the dark is not all that gruesome:
+ it carries only a 25% risk of falling down a pit.^^";
+ print "The vase does not like being immersed.^^";
+ print "Shadowy figures can wave to each other.^^";
+ print "Watering the hinges of the door rusts them up again.^^";
+ print
+ "When the cave closes, the grate is locked and the keys are thrown away,
+ creatures run off and the crystal bridge vanishes...^^";
+ print
+ "...and a completely useless hint is written on the giant oyster's shell in the end game.
+ (To make this hint slightly fairer, I've altered one word and placed suggestions elsewhere in the game.)^^";
+ "The last lousy point can be won by... but no. That would be telling.";
+];
+
+[ HelpSub;
+ if (deadflag ~= 2)
+ DoMenu(
+ "There is information provided on the following:^
+ ^ Instructions for playing
+ ^ A historical preface
+ ^ How authentic is this edition?^", HelpMenu, HelpInfo);
+ else
+ DoMenu(
+ "There is information provided on the following:^
+ ^ Instructions for playing
+ ^ A historical preface
+ ^ How authentic is this edition?
+ ^ Did you know...^", HelpMenu, HelpInfo);
+];
+
+[ Amusing; HelpSub(); ];
+
+Verb 'help'
+ * -> Help;
+
+! ------------------------------------------------------------------------------
+! Grammar: the usual grammar and some extensions
+! ------------------------------------------------------------------------------
+
+Include "Grammar";
+
+! ------------------------------------------------------------------------------
+
+[ OffSub;
+ if (brass_lantern notin player) "You have no lamp.";
+ <>;
+];
+
+[ OnSub;
+ if (brass_lantern notin player) "You have no lamp.";
+ <>;
+];
+
+Verb 'off'
+ * -> Off;
+
+Verb 'on'
+ * -> On;
+
+! ------------------------------------------------------------------------------
+
+[ CatchSub; "You can't catch ", (the) noun, "."; ];
+
+[ ReleaseSub; "You can't release ", (the) noun, "."; ];
+
+Verb 'catch' 'capture'
+ * creature -> Catch
+ * creature 'with' held -> Catch;
+
+Verb 'release' 'free'
+ * creature -> Release;
+
+! ------------------------------------------------------------------------------
+
+[ WaterSub;
+ if (bottle in player) <>;
+ "Water? What water?";
+];
+
+[ OilSub;
+ if (bottle in player) <>;
+ "Oil? What oil?";
+];
+
+Verb 'water'
+ * noun -> Water;
+
+Verb 'oil' 'grease' 'lubricate'
+ * noun -> Oil;
+
+Verb 'pour' 'douse'
+ * 'water' 'on' noun -> Water
+ * 'oil' 'on' noun -> Oil
+ * noun -> Empty;
+
+! ------------------------------------------------------------------------------
+
+[ BlastSub;
+ if (location ~= At_Sw_End or At_Ne_End) "Frustrating, isn't it?";
+ if (location == At_Sw_End && parent(black_mark_rod) == At_Ne_End) {
+ score = score + 35;
+ deadflag = 2;
+ "There is a loud explosion, and a twenty-foot hole appears in the far wall,
+ burying the dwarves in the rubble.
+ You march through the hole and find yourself in the main office,
+ where a cheering band of friendly elves carry the conquering adventurer off into the sunset.";
+ }
+ if (location == At_Ne_End && parent(black_mark_rod) == At_Sw_End) {
+ score = score + 20;
+ deadflag = 1;
+ "There is a loud explosion, and a twenty-foot hole appears in the far wall,
+ burying the snakes in the rubble.
+ A river of molten lava pours in through the hole, destroying everything in its path, including you!";
+ }
+ deadflag = 1;
+ "There is a loud explosion, and you are suddenly splashed across the walls of the room.";
+];
+
+[ BlastWithSub;
+ if (second ~= black_mark_rod) "Blasting requires dynamite.";
+ "Been eating those funny brownies again?";
+];
+
+Verb 'blast'
+ * -> Blast
+ * noun 'with' held -> BlastWith;
+
+! ------------------------------------------------------------------------------
+
+[ XyzzySub; "Nothing happens."; ];
+
+[ PlughSub; "Nothing happens."; ];
+
+[ PloverSub; "Nothing happens."; ];
+
+[ FeeSub; FthingSub(0); ];
+
+[ FieSub; FthingSub(1); ];
+
+[ FoeSub; FthingSub(2); ];
+
+[ FooSub; FthingSub(3); ];
+
+[ FthingSub i;
+ if (feefie_count ~= i) {
+ feefie_count = 0;
+ "Get it right, dummy!";
+ }
+ if (feefie_count++ == 3) {
+ feefie_count = 0;
+ if (golden_eggs in In_Giant_Room) "Nothing happens.";
+ if ((golden_eggs in player) || (golden_eggs in location))
+ print "The nest of golden eggs has vanished!^";
+ else
+ print "Done!";
+ if (golden_eggs in player) score = score - 5;
+ if (golden_eggs in Inside_Building)
+ score = score - golden_eggs.depositpoints;
+ move golden_eggs to In_Giant_Room;
+ if (location == In_Giant_Room)
+ "^^A large nest full of golden eggs suddenly appears out of nowhere!";
+ }
+ else
+ "Ok.";
+];
+
+[ OldMagicSub; "Good try, but that is an old worn-out magic word."; ];
+
+Verb 'xyzzy'
+ * -> Xyzzy;
+
+Verb 'plugh'
+ * -> Plugh;
+
+Verb 'plover'
+ * -> Plover;
+
+Verb 'fee'
+ * -> Fee;
+
+Verb 'fie'
+ * -> Fie;
+
+Verb 'foe'
+ * -> Foe;
+
+Verb 'foo'
+ * -> Foo;
+
+Verb 'sesame' 'shazam' 'hocus' 'abracadabra' 'foobar' 'open-sesame' 'frotz'
+ * -> OldMagic;
+
+Extend 'say' first
+ * 'blast' -> Blast
+ * 'xyzzy' -> Xyzzy
+ * 'plugh' -> Plugh
+ * 'plover' -> Plover
+ * 'fee' -> Fee
+ * 'fie' -> Fie
+ * 'foe' -> Foe
+ * 'foo' -> Foo
+ * 'sesame'/'shazam'/'hocus'/'abracadabra'/'foobar'/'open-sesame'/'frotz'
+ -> OldMagic;
+
+! ------------------------------------------------------------------------------
+
+[ CountSub;
+ if (noun has multitude) "There are a multitude.";
+ "I see one (1) ", (name) noun, ".";
+];
+
+[ KickSub; <>; ]; ! For kicking dwarves
+
+[ UseSub; "You'll have to be a bit more explicit than that."; ];
+
+Verb 'count'
+ * noun -> Count;
+
+Verb 'kick'
+ * noun -> Kick;
+
+Verb 'use'
+ * -> Use;
+
+! ------------------------------------------------------------------------------
+! Teleportation (uses also UnknownVerb entry point)
+! ------------------------------------------------------------------------------
+
+[ TeleportScope
+ obj;
+ switch (scope_stage) {
+ 1: rfalse;
+ 2: objectloop (obj ofclass Room)
+ if (obj has visited) PlaceInScope(obj);
+ rtrue;
+ 3: return L__M(##Go, 2);
+ }
+];
+
+[ TeleportSub;
+ if (noun == location) "But you're already here!";
+ PlayerTo(noun);
+];
+
+Extend 'go'
+ * scope=TeleportScope -> Teleport
+ * 'to' scope=TeleportScope -> Teleport;
+
+#Ifndef DEBUG;
+
+Verb 'goto'
+ * scope=TeleportScope -> Teleport;
+
+#Endif;
+
+! ------------------------------------------------------------------------------
+! In the test version: no dwarves or pirates, and magic words work from the start
+! ------------------------------------------------------------------------------
+
+#Ifdef TEST_VERSION;
+
+[ XdetermSub;
+ StopDaemon(dwarf);
+ StopDaemon(pirate);
+ give In_Debris_Room visited;
+ give At_Y2 visited;
+ give In_Plover_Room visited;
+];
+
+Verb 'xdeterm'
+ * -> Xdeterm;
+
+#Endif;
+
+! ------------------------------------------------------------------------------
diff --git a/presets/zmachine/adventureland.inf b/presets/zmachine/adventureland.inf
new file mode 100644
index 00000000..5e2ce9b1
--- /dev/null
+++ b/presets/zmachine/adventureland.inf
@@ -0,0 +1,873 @@
+! ----------------------------------------------------------------------------
+! Adventureland 961111 One of the standard Inform 6 example games
+!
+! Designed by Scott Adams: c. 1979
+! Ported to Inform: 16.10.94
+! Slightly corrected: 11.5.96
+! Modernised to Inform 6 and library 6/1 or later: 11.11.96
+! ----------------------------------------------------------------------------
+
+Constant Story "ADVENTURELAND";
+Constant Headline
+ "^An Interactive Classic by Scott Adams (circa 1979/80)^";
+
+Release 1;
+Serial "961111";
+
+Constant MAX_CARRIED = 6;
+Constant MAX_SCORE = 100;
+
+Replace BurnSub;
+
+Include "Parser";
+Include "VerbLib";
+
+Global genie_gifts;
+Global dark_warning;
+
+Class Treasure
+ with depositpoints 7,
+ after
+ [; Take: if (location==Inside_Stump) "Taken!";
+ Drop: if (location==Inside_Stump) "Safely deposited.";
+ ];
+
+Class Sign
+ with name "sign",
+ short_name
+ [; print "sign reads- ", (object) self; rtrue;
+ ],
+ has static;
+
+Class ScottRoom
+ with initial
+ [; give self ~visited;
+ ],
+ describe
+ [ i c d; print (string) self.description;
+ print "^^Obvious exits: ";
+ for (i=n_to: i<=d_to: i++)
+ if (self.i ~= 0) c++;
+ if (c==0) print "none!";
+ else
+ { for (i=n_to: i<=d_to: i++)
+ if (self.i ~= 0)
+ { if (d++>0) print ", ";
+ if (i==n_to) print "North";
+ if (i==s_to) print "South";
+ if (i==e_to) print "East";
+ if (i==w_to) print "West";
+ if (i==u_to) print "Up";
+ if (i==d_to) print "Down";
+ }
+ print ".";
+ }
+ new_line;
+ c=0; d=0;
+ objectloop (i in self)
+ if (i ~= player) { c++; give i concealed; }
+ if (c==0) rtrue;
+ print "^You can also see: ";
+ objectloop (i in self)
+ if (i ~= player)
+ { if (d++>0) print " - "; PrintShortName(i);
+ }
+ new_line; rtrue;
+ ];
+
+[ GamePreRoutine i c d;
+ if (action~=##Inv) rfalse;
+ c=0; d=0;
+ objectloop (i in player) c++;
+ if (c==0) "You're carrying nothing.";
+ print "You're carrying:^";
+ objectloop (i in player)
+ { if (d++>0) print " - "; PrintShortName(i);
+ }
+ new_line; rtrue;
+];
+
+[ GamePostRoutine i;
+ if (action==##Look)
+ objectloop (i in location)
+ if (i ~= player && i has concealed)
+ give i ~concealed;
+ rfalse;
+];
+
+! ----------------------------------------------------------------------------
+! Into Adventureland...
+! ----------------------------------------------------------------------------
+
+ScottRoom Lake_Shore "Lakeside"
+ with description "You're on the shore of a lake.",
+ n_to Forest, s_to Lake_Shore, w_to Dismal_Swamp,
+ d_to Quicksand,
+ before
+ [; Swim: "Below you and before the lake is quicksand.";
+ ],
+ has light;
+Object -> water "water"
+ with name "water", article "some",
+ before
+ [; Drink: "Boy, that really hit the spot.";
+ Take: if (bottle notin player)
+ "You have nothing in which to carry the water.";
+ <>;
+ Insert: if (second == bottle) <>;
+ "You have nothing in which to carry the water.";
+ Receive: if (noun == bottle) <>;
+ remove noun; CDefArt(noun); " washes away into the lake.";
+ ],
+ has scenery;
+Treasure -> "*GOLDEN FISH*"
+ with name "gold" "golden" "fish",
+ each_turn
+ [; if (self notin player) rfalse;
+ if (net notin player && random(100) <= 75)
+ { move self to Lake_Shore;
+ "^The fish escape back to the lake.";
+ }
+ if ((water_in_the_bottle notin bottle
+ || bottle notin player) && random(100)<=50)
+ { remove self; move dead_fish to player;
+ "^Too dry. Fish die.";
+ }
+ ];
+Object -> axe "rusty axe (magic word- BUNYON -on it)"
+ with name "rusty" "axe",
+ description "The magic word BUNYON is written on the haft.";
+Sign -> "NO SWIMMING ALLOWED";
+Object dead_fish "dead fish"
+ with name "dead" "fish"
+ has edible;
+
+ScottRoom Quicksand "Bog"
+ with description "You're in a quick-sand bog.",
+ before
+ [; Swim: if (child(player)==nothing)
+ { PlayerTo(Lake_Shore); rtrue; }
+ "Something's too heavy.";
+ ],
+ has light;
+Treasure -> ox "*SMALL STATUE OF A BLUE OX*"
+ with name "ox" "blue" "small" "statue";
+
+ScottRoom Forest "Forest"
+ with description "You're in a forest.",
+ n_to Forest, s_to Forest, e_to Sunny_Meadow, w_to Forest,
+ u_to trees
+ has light;
+Object -> trees "trees"
+ with name "tree" "trees",
+ before
+ [; Climb: <>;
+ ],
+ door_to Up_Oak, door_dir u_to
+ has open door static;
+
+ScottRoom Up_Oak "Branch"
+ with description "You're in a branch on the top of an old oak tree.^
+ To the east you see a meadow beyond a lake.",
+ d_to Forest,
+ has light;
+
+ScottRoom Sunny_Meadow "Meadow"
+ with description "You're in a sunny meadow.",
+ n_to Lake_Shore, s_to Dismal_Swamp, e_to Lake_Shore,
+ w_to Forest,
+ has light;
+Object -> dragon "sleeping Dragon"
+ with name "dragon" "sleeping" "sleepy",
+ before
+ [; WakeOther: deadflag=1; "The dragon wakes!";
+ ],
+ life
+ [; Order, Answer, Ask: "Shh! You don't want to wake the dragon.";
+ Give: "The dragon is too drowsy to notice.";
+ ThrowAt: if (noun==axe)
+ { move axe to location; "The dragon isn't bothered."; }
+ ],
+ each_turn
+ [; if (mud in location && random(100)<=50)
+ { deadflag=1;
+ "Dragon smells something - awakens - attacks you!";
+ }
+ ],
+ has animate;
+Sign -> "IN SOME CASES MUD IS GOOD, IN OTHERS...";
+Treasure eggs "*DRAGON EGGS* (very rare)"
+ with name "dragon" "eggs" "very" "rare", depositpoints 12;
+Object gore "smoking hole - pieces of dragon and gore"
+ with name "gore" "hole" "dragon" "smoking"
+ has static;
+
+ScottRoom Hidden_Grove "Grove"
+ with description "You're in a hidden grove.",
+ n_to Forest, e_to Dismal_Swamp, w_to Forest,
+ has light;
+Treasure -> "*JEWELLED FRUIT*"
+ with name "jewelled" "jewel" "fruit",
+ after
+ [; Eat: "Boy that really hit the spot!"; ],
+ has edible;
+Sign -> "PAUL'S PLACE";
+
+ScottRoom Dismal_Swamp "Dismal Swamp"
+ with description "You're in a dismal swamp.",
+ n_to Sunny_Meadow, s_to Dismal_Swamp, e_to Dismal_Swamp,
+ w_to Hidden_Grove, in_to 0, u_to cypress_tree
+ has light;
+Object -> cypress_tree "cypress tree"
+ with name "cypress" "tree",
+ before
+ [; Climb: <>;
+ Cut: if (axe notin player) rfalse;
+ remove self; move tree_remains to Dismal_Swamp;
+ Dismal_Swamp.in_to = tree_remains;
+ Dismal_Swamp.u_to = 0;
+ print "TIMBER..";
+ if (keys in Tree_Top)
+ { remove keys;
+ ". Something fell from the treetop and vanished!";
+ }
+ ".";
+ ],
+ door_to Tree_Top, door_dir u_to
+ has open door static;
+
+Object -> mud "evil smelling mud"
+ with name "evil" "smelling" "mud", article "some",
+ after
+ [ f; Take:
+ if (infected_bites in player) { remove infected_bites; f=1; }
+ if (chigger_bites in player) { remove chigger_bites; f=1; }
+ if (f==1) "Boy that really hit the spot!";
+ ],
+ each_turn
+ [; if (self notin player) rtrue;
+ if (random(100)<=5 &&
+ (bottle notin player || water_in_the_bottle notin bottle))
+ { move self to Dismal_Swamp;
+ "The mud dried up and fell off.";
+ }
+ ];
+
+Object -> gas "swamp gas"
+ with name "swamp" "gas", article "some",
+ before
+ [; Take:
+ if (distended_bladder in player) "Bladder full already.";
+ if (wine_bladder notin player) "You have nothing suitable.";
+ <>;
+ Insert:
+ if (second == distended_bladder) "The bladder's full.";
+ if (second ~= wine_bladder)
+ "That won't hold gas.";
+ move distended_bladder to player; remove wine_bladder;
+ itobj = distended_bladder;
+ "The bladder distends with swamp gas.";
+ ],
+ has static;
+Object -> slime "floating patch of oily slime"
+ with name "patch" "oil" "slime" "oily",
+ before
+ [; Take: brass_lantern.time_left=125; give brass_lantern general;
+ remove self; move brass_lantern to player;
+ "Magic oil attracts magic lamp. Lamp is now full.";
+ ],
+ has static;
+Object -> chiggers "chiggers"
+ with name "chiggers", article "a swarm of",
+ daemon
+ [; if (chigger_bites in player && mud notin player && random(100)<=10)
+ { remove chigger_bites; move infected_bites to player;
+ "^Your chigger bites are now infected.";
+ }
+ if (infected_bites in player && random(100)<=8)
+ { deadflag=1;
+ "^The bites have rotted your whole body.";
+ }
+ if (infected_bites notin player
+ && chigger_bites notin player
+ && slime in location && mud notin player
+ && random(100)<=5)
+ { move chigger_bites to player;
+ "^You're bitten by chiggers.";
+ }
+ if (infected_bites notin player
+ && chigger_bites notin player
+ && chiggers in player
+ && random(100)<=30)
+ { move chigger_bites to player;
+ "^You're bitten by chiggers.";
+ }
+ ];
+Object chigger_bites "chigger bites"
+ with name "chigger" "bites", article "some",
+ before [; "The bites are annoying. Perhaps medicine would help?"; ];
+Object infected_bites "infected chigger bites"
+ with name "chigger" "bites" "infected", article "some",
+ before [; "The bites are frightening. Get medicine!"; ];
+
+Object tree_remains "hollow stump and remains of a felled tree"
+ with name "tree" "stump" "hollow" "remains",
+ door_to Inside_Stump, door_dir in_to
+ has open door static;
+
+ScottRoom Tree_Top "Tree Top"
+ with description "You're in the top of a tall cypress tree.",
+ d_to Dismal_Swamp,
+ has light;
+
+Object -> "spider web with writing on it"
+ with name "spider" "web" "writing",
+ description "~CHOP IT DOWN!~",
+ before
+ [; Take: deadflag=1; "You're bitten by a spider.";
+ ];
+Object -> keys "ring of skeleton keys"
+ with name "keys" "ring" "skeleton" "keyring";
+
+ScottRoom Inside_Stump "Inside Stump"
+ with description "You're in a large hollow damp stump in the swamp.",
+ n_to Dismal_Swamp, s_to Dismal_Swamp, e_to Dismal_Swamp,
+ w_to Dismal_Swamp, u_to Dismal_Swamp, d_to Root_Chamber,
+ has light;
+Sign -> "LEAVE TREASURE HERE - (say 'SCORE')";
+Object -> bottle "the bottle"
+ with name "bottle" "jar" "flask",
+ short_name
+ [; if (water_in_the_bottle in self) { print "bottle of water"; rtrue; }
+ if (bees in self) { print "bottle of bees"; rtrue; }
+ print "empty bottle"; rtrue;
+ ],
+ before
+ [ x; LetGo:
+ if (noun in bottle)
+ "You're holding that already (in the bottle).";
+ Receive:
+ if (noun==water or bees) <>;
+ "That won't go in the bottle.";
+ Fill:
+ if (child(bottle)~=0)
+ "The bottle is full already.";
+ if (water in location)
+ { move water_in_the_bottle to bottle;
+ "The bottle is now full of water.";
+ }
+ if (bees in location)
+ { move bees to bottle;
+ "The bottle is now full of bees.";
+ }
+ "There is nothing here with which to fill the bottle.";
+ Empty: if (child(bottle)==0) "The bottle is already empty!";
+ x=child(bottle);
+ remove x;
+ if (x==bees)
+ { move x to location; "You release the bees.";
+ }
+ "Your bottle is now empty and the ground is now wet.";
+ ],
+ has container open;
+
+Object -> brass_lantern "old fashioned lamp"
+ with name "lamp" "fashioned" "lamp", article "an",
+ power 125,
+ time_left 0,
+ daemon
+ [ t; if (self hasnt on) { StopDaemon(self); rtrue; }
+ t=--(self.power);
+ if (t==0) give self ~on ~light;
+ if (self in player or location)
+ { if (t==0) "Your lamp has run out of power.";
+ if (t==30) "Your lamp is getting dim.";
+ }
+ ],
+ before
+ [; Examine: print "It is a shiny brass lamp";
+ if (self hasnt on)
+ ". It is not currently lit.";
+ if (self.power < 30)
+ ", glowing dimly.";
+ ", glowing brightly.";
+ Burn: <>;
+ Rub: if (self has on) "No! It's too hot.";
+ if (self hasnt general) "Nothing happens.";
+ switch(++genie_gifts)
+ { 1: move ring to location;
+ "A glowing genie appears -
+ drops something - then vanishes.";
+ 2: move bracelet to location;
+ "A glowing genie appears -
+ drops something - then vanishes.";
+ 3: if (ring in Inside_Stump)
+ score=score-ring.depositpoints;
+ remove ring; move player to Misty_Room;
+ "A genie appears - says ~boy you're selfish~ - takes
+ something - then vanishes!";
+ 4: if (bracelet in Inside_Stump)
+ score=score-bracelet.depositpoints;
+ remove bracelet; move player to Misty_Room;
+ "A genie appears - says ~boy you're selfish~ - takes
+ something - then vanishes!";
+ default: "Nothing happens.";
+ }
+ SwitchOn: if (self.power <= 0) "It's run out.";
+ Receive, Open:
+ "You can't put things in the lamp.";
+ ],
+ after
+ [; SwitchOn: give self light; StartDaemon(self);
+ "Flameless lamp now on.";
+ SwitchOff: give self ~light;
+ ],
+ has switchable;
+
+Treasure ring "*DIAMOND RING*"
+ with name "diamond" "ring";
+Treasure bracelet "*DIAMOND BRACELET*"
+ with name "diamond" "bracelet";
+
+Object water_in_the_bottle "bottled water" bottle
+ with name "bottled" "water" "h2o", article "some",
+ before
+ [; Drink: remove water_in_the_bottle; <>;
+ ],
+ description "It looks like ordinary water to me.";
+
+ScottRoom Root_Chamber "Root Chamber"
+ with description "You're in a root chamber under the stump.",
+ u_to Inside_Stump, d_to dark_hole,
+ has light;
+Object -> dark_hole "dark hole"
+ with description "Leading below.",
+ door_dir d_to,
+ door_to Semidark_Hole
+ has open door static;
+Treasure -> "*POT OF RUBIES*"
+ with name "pot" "of" "rubies";
+
+ScottRoom Semidark_Hole "Hole"
+ with description "You're in a semi-dark hole by the root chamber.",
+ u_to Root_Chamber, d_to root_door
+ has light;
+Object -> root_door "the door"
+ with name "door",
+ short_name
+ [; if (self has locked) { print "locked door"; rtrue; }
+ if (self has open)
+ { print "open door with a hallway beyond"; rtrue; }
+ print "closed door"; rtrue;
+ ],
+ before
+ [; ThrowAt:
+ if (second==axe)
+ { give self ~locked ~lockable ~openable open;
+ "Lock shatters!";
+ }
+ ],
+ door_to Long_Hall, door_dir d_to, with_key keys
+ has static door openable lockable locked;
+
+ScottRoom Long_Hall "Hall"
+ with description "You're in a long down-sloping hall.",
+ u_to Semidark_Hole, d_to Large_Cavern;
+
+ScottRoom Large_Cavern "Cavern"
+ with description "You're in a large cavern.",
+ n_to Hive, s_to Royal_Anteroom, w_to Memory_RAM,
+ u_to Long_Hall, d_to Maze1;
+
+ScottRoom Hive "Octagonal Hive"
+ with description "You're in a large 8-sided room.",
+ s_to Large_Cavern;
+Treasure -> "*ROYAL HONEY*"
+ with name "royal" "honey", article "some",
+ before
+ [; Take:
+ if (bees in location && mud notin player)
+ { deadflag=1; "Bees sting you."; }
+ Drop:
+ if (bear in location)
+ { remove self; give bear general;
+ "The bear eats the honey and falls asleep.";
+ }
+ ],
+ has edible;
+Object -> bees "large African bees"
+ with name "large" "african" "bees", article "a swarm of",
+ before
+ [; Take:
+ if (mud notin player)
+ { deadflag=1; "Bees sting you."; }
+ if (bottle in player) <>;
+ "You have nothing to carry the bees in.";
+ Drop:
+ if (self in bottle
+ && dragon in location)
+ { move self to location;
+ move eggs to location; remove dragon;
+ "The bees attack the dragon which gets up and flies away...";
+ }
+ if (self in bottle
+ && bear in location)
+ { move self to location;
+ give bear ~general; deadflag=1;
+ "Bees madden the bear. Bear then attacks you!";
+ }
+ ],
+ each_turn
+ [; #IFNDEF DEBUG;
+ ! A completely unfair rule! And in the original the bees are lost.
+ if (self in bottle && random(100)<=8)
+ { move self to Hive; "^The bees in the bottle all suffocated."; }
+ #ENDIF;
+ if (self in bottle) rfalse;
+ if (self in location && mud notin player && mud notin location &&
+ random(100)<=8)
+ { deadflag=1; "Bees sting you."; }
+ ];
+
+ScottRoom Royal_Anteroom "Anteroom"
+ with description "You're in a royal anteroom.",
+ n_to Large_Cavern, u_to Royal_Chamber;
+Object -> wine_bladder "empty wine bladder"
+ with name "empty" "wine" "bladder",
+ before
+ [; Fill: if (gas notin location)
+ "The bladder could only just hold a vapour nowadays.";
+ <>;
+ ];
+Object distended_bladder "distended gas bladder"
+ with name "distended" "gas" "bladder",
+ before
+ [; Open: move wine_bladder to parent(self); remove self;
+ "Gas dissipates!";
+ ];
+
+ScottRoom Maze1 "Maze"
+ with description "You're in a maze of pits.",
+ n_to Maze2, s_to Maze4, e_to Maze4, d_to Maze2;
+
+ScottRoom Maze2 "Maze"
+ with description "You're in a maze of pits.",
+ w_to Maze3, u_to Maze1;
+Object -> flint_and_steel "flint and steel"
+ with name "flint" "steel";
+
+ScottRoom Maze3 "Maze"
+ with description "You're in a maze of pits.",
+ n_to Maze6, s_to Maze1, e_to Maze2, w_to Maze5,
+ u_to Maze5, d_to Maze6;
+Object -> "scratchings"
+ with name "scratchings", article "strange",
+ short_name "strange scratchings on rock reveals- ALADDIN WAS HERE",
+ has static;
+
+ScottRoom Maze4 "Maze"
+ with description "You're in a maze of pits.",
+ n_to Maze1, e_to Maze2, w_to Maze1, u_to Maze2;
+
+ScottRoom Maze5 "Maze"
+ with description "You're in a maze of pits.",
+ s_to Maze6, u_to Maze3, d_to Maze6;
+
+ScottRoom Maze6 "Maze"
+ with description "You're in a maze of pits.",
+ n_to Maze6, s_to Maze1, e_to Maze1, w_to Maze4,
+ u_to Maze3, d_to Chasm_Bottom;
+Treasure -> rug "*THICK PERSIAN RUG*"
+ with name "thick" "persian" "rug" "carpet";
+Object -> "arrow pointing down"
+ with name "arrow"
+ has static;
+
+ScottRoom Chasm_Bottom "Chasm"
+ with description "You're in a bottom of a chasm. Above 2 ledges.
+ One has a bricked up window.",
+ u_to Maze6;
+Treasure -> net "*GOLDEN NET*"
+ with name "gold" "golden" "net";
+Sign -> "MAGIC WORD IS AWAY. X LA -(rest of sign is missing)";
+Object -> lava "the lava"
+ with name "stream" "of" "lava",
+ short_name
+ [; print "stream of lava";
+ if (self has general) print " with a brick dam";
+ rtrue;
+ ],
+ description
+ [; if (self hasnt general)
+ "There's something there all right! Maybe you should go there?";
+ "Just more dammed lava.";
+ ],
+ before
+ [; Enter, Push, Pull, Take: "NO! It's too hot.";
+ ],
+ has static;
+Treasure firestone "*FIRESTONE* (cold now)"
+ with name "firestone", depositpoints 11;
+
+ScottRoom Narrow_Ledge_1 "Ledge"
+ with description "You're on a narrow ledge by a chasm.
+ Across the chasm is a throne room.",
+ before
+ [; Jump: if (firebricks in player)
+ { deadflag=1; "Oh no! Something was too heavy!"; }
+ print "You leap across the chasm...^";
+ PlayerTo(Narrow_Ledge_2); rtrue;
+ ],
+ w_to Royal_Chamber;
+
+ScottRoom Royal_Chamber "Royal Chamber"
+ with description "You're in the Royal Chamber.",
+ d_to Royal_Anteroom, e_to 0;
+Object -> bricked_window "bricked-up window"
+ with name "window" "bricked" "brick" "bricks"
+ has static;
+Object holed_window "bricked up window with a hole in it - beyond is a ledge"
+ with name "window" "bricked" "hole" "ledge",
+ door_dir e_to, door_to Narrow_Ledge_1
+ has static door open;
+Object firebricks "loose fire bricks"
+ with name "loose" "fire" "bricks", article "some",
+ after
+ [; Take: "Taken. (Heavy!)";
+ Drop: if (location~=Chasm_Bottom) rfalse;
+ remove self; give lava general;
+ move firestone to location;
+ "The bricks dam the lava, revealing a *FIRESTONE*!";
+ ];
+
+ScottRoom Narrow_Ledge_2 "Ledge"
+ with description
+ "You're on a narrow ledge by the throne room-across chasm-ledge.",
+ before
+ [; Sing:
+ if (bear in location && bear hasnt general)
+ { move dead_bear to Chasm_Bottom;
+ remove bear;
+ "The bear got startled and fell off the ledge!";
+ }
+ Jump: print "You leap across the chasm...^";
+ PlayerTo(Narrow_Ledge_1); rtrue;
+ ],
+ e_to
+ [; if (bear in location && bear hasnt general)
+ "The bear won't let you!";
+ return Throne_Room;
+ ];
+Treasure -> mirror "*MAGIC MIRROR*"
+ with name "magic" "mirror",
+ side_up 0,
+ before
+ [; Take:
+ if (bear in location && bear hasnt general)
+ "The bear won't let you!";
+ ],
+ after
+ [; Drop:
+ if (rug in location)
+ { print "Mirror lands softly on the rug - lights up and says:^";
+ self.side_up++;
+ if (self.side_up % 2 == 1)
+ "*DRAGON STINGS* and fades. I don't get it - hope you do.";
+ "Don't waste *HONEY*. Get mad instead. Dam lava!";
+ }
+ remove self; move broken_glass to location;
+ "The mirror hits the floor and shatters into a million pieces!";
+ ];
+Object -> bear "the bear"
+ with name "thin" "black" "bear",
+ short_name
+ [; if (self has general) { print "sleeping bear"; rtrue; }
+ print "thin black bear"; rtrue;
+ ],
+ before
+ [; WakeOther: give self ~general; "The bear rouses!^";
+ ],
+ life
+ [; Ask, Order, Answer: <>;
+ Attack, ThrowAt:
+ if (self has general) ;
+ remove mirror; move broken_glass to location;
+ "Oh no...Bear dodges...CRASH!";
+ ],
+ has animate;
+Object broken_glass "broken glass"
+ with name "broken" "glass" "jagged" "fragments", article "some";
+Object dead_bear "dead bear"
+ with name "dead" "bear" "black" "thin"
+ has static;
+
+ScottRoom Throne_Room "Throne Room"
+ with description "You're in a throne room.",
+ w_to Narrow_Ledge_2;
+Treasure -> "*GOLD CROWN*"
+ with name "gold" "golden" "crown";
+
+ScottRoom Real_Trouble "Trouble!"
+ with description
+ "I think you're in real trouble. Here's a guy with a pitchfork!^^
+ You lost *ALL* treasures.",
+ initial
+ [; deadflag=3;
+ ],
+ has light;
+
+ScottRoom Memory_RAM "Ugly Place"
+ with description
+ "You're in the memory RAM of an IBM-PC. You took a wrong turn!",
+ e_to Large_Cavern,
+ has light;
+Sign -> "To the Architects - TSURRIS";
+
+ScottRoom Misty_Room "Misty Room"
+ with description "You're in a large misty room with strange letters
+ over the exits.",
+ s_to Real_Trouble, e_to Forest, w_to Real_Trouble,
+ u_to Up_Oak, d_to Real_Trouble,
+ has light;
+Sign -> "LIMBO. FIND RIGHT EXIT AND LIVE AGAIN!";
+
+! ----------------------------------------------------------------------------
+! A soupcon of code
+! ----------------------------------------------------------------------------
+
+[ Initialise;
+ location=Forest; score = 0;
+
+ StartDaemon(chiggers);
+
+ "^^^^^A voice booms out ...^
+ Treasures have an * in their name. Say 'SCORE'^
+ If you need a hint on something, try 'HELP'.^";
+];
+
+[ TimePasses i;
+ if (location ~= Inside_Stump) rfalse;
+
+ score=0;
+ objectloop (i in Inside_Stump && i ofclass Treasure)
+ score = score + i.depositpoints;
+
+ if (score ~= 100) rfalse;
+
+ deadflag=2;
+ "Congratulations! By finding and depositing all 13 *TREASURES*, you
+ have solved Scott Adams's ~Adventureland~ and it remains only to say
+ that...";
+];
+
+[ AfterLife;
+ if (deadflag==3) { deadflag=1; rfalse; }
+ remove chigger_bites; remove infected_bites;
+ deadflag=0; PlayerTo(Misty_Room);
+];
+
+[ PrintRank; "."; ];
+
+[ DarkToDark;
+ if (dark_warning==0)
+ { dark_warning=1; "It is now pitch dark.
+ If you proceed you will likely fall into a pit.";
+ }
+ if (random(4) == 1)
+ { deadflag=1;
+ "You fell into a pit and broke every bone in your body!";
+ }
+ rfalse;
+];
+
+[ BunyonSub;
+ if (axe notin player) "Nothing happens.";
+ if (ox in player or location)
+ { move ox to Hidden_Grove;
+ move axe to Hidden_Grove;
+ "Something you're holding vibrated and...";
+ }
+ if (player notin Quicksand)
+ { move axe to Hidden_Grove;
+ print "Something you're holding vibrated and...";
+ <>;
+ }
+ "Nothing happens.";
+];
+
+[ TsurrisSub;
+ if (location ~= Memory_RAM) "Nothing happens.";
+ "A voice booms out...^
+ May all your teeth but one fall out, and may that one give you toothache.^
+ (You can't help feeling you have stumbled on a private quarrel which is
+ nothing to do with your game.)";
+];
+
+[ BurnSub;
+ if (flint_and_steel notin player)
+ "You have nothing to strike a light with.";
+ if (noun==gas) "Gas needs to be contained before it will burn.";
+ if (noun==distended_bladder)
+ { if (noun in player)
+ { remove noun; deadflag=1; "Gas bladder blew up in your hands!";
+ }
+ remove noun;
+ print "Gas bladder blew up!^";
+ if (dragon in location)
+ { remove dragon; move gore to location;
+ "The dragon has been blown to bits!";
+ }
+ if (bricked_window in location)
+ { remove bricked_window;
+ move holed_window to location; move firebricks to location;
+ Royal_Chamber.e_to = holed_window;
+ "The bricked window has been blown to bits!";
+ }
+ rtrue;
+ }
+ "That won't ignite.";
+];
+
+[ HelpSub;
+ print "A voice booms out...^";
+ print "Try: LOOK,JUMP,SWIM,CLIMB,THROW,FIND,GO,TAKE,INVENTORY,SCORE.^";
+ if (chigger_bites in player || infected_bites in player)
+ "Medicine is good for bites.";
+ if (location == Quicksand) "You may need magic words here.";
+ if (location == Sunny_Meadow)
+ "Only 3 things will wake the dragon. One of them is dangerous!";
+ if (location == Hive)
+ "Read the sign in the meadow!";
+ if (location == Maze1 or Maze2 or Maze3
+ || location == Maze4 or Maze5 or Maze6)
+ "You may need magic words here.";
+ if (location == Royal_Chamber) "Blow it up. Try the swamp.";
+];
+
+[ AwaySub;
+ if (rug notin player || location~=Maze3) "Nothing happens.";
+ print "Something you're holding vibrates, and...^";
+ PlayerTo(Sunny_Meadow);
+];
+
+[ FindSub;
+ "A voice booms out...^Find it yourself.";
+];
+
+! ----------------------------------------------------------------------------
+! Grammar: the usual grammar and some extensions
+! ----------------------------------------------------------------------------
+
+Include "Grammar";
+
+Extend "cut"
+ * "up" noun -> Cut
+ * "down" noun -> Cut;
+
+Verb "bunyon" * -> Bunyon;
+Verb "away" * -> Away;
+Verb "tsurris" * -> Tsurris;
+Verb "help" * -> Help;
+Verb "find" * special -> Find;
+
+! ----------------------------------------------------------------------------
diff --git a/presets/zmachine/alice.inf b/presets/zmachine/alice.inf
new file mode 100644
index 00000000..8e6dcba0
--- /dev/null
+++ b/presets/zmachine/alice.inf
@@ -0,0 +1,469 @@
+! Through the Looking-Glass
+! An Inform tutorial by Gareth Rees
+! All rights given away
+! Version 3
+!
+! 5/1/2003 - Updated to Inform 6.21 Library 6/10
+!
+
+Constant Story "THROUGH THE LOOKING GLASS";
+Constant Headline "^An Interactive Tutorial^by Gareth Rees^";
+
+Include "parser";
+Include "verblib";
+Include "grammar";
+
+[ Initialise;
+ location = Drawing_Room;
+ StartDaemon(white_kitten);
+ StartDaemon(black_kitten);
+ print "^^^^^It's a cold winter day outside, but in the
+ looking-glass house it's summer. All you need to do is
+ pretend there's a way of getting through into it
+ somehow...^^";
+];
+
+[ UntangleSub; "What curious ideas you have!"; ];
+
+[ ReflectSub;
+ if (second ~= mirror) "What a strange idea!";
+ if (noun == hearth or mirror || (player notin mantelpiece &&
+ player notin armchair))
+ "You can't see that in the looking-glass.";
+ print "The looking-glass ";
+ if (noun == player) print "Alice";
+ else PrintShortName(noun);
+ if (player in mantelpiece) " looks very misty and blurred.";
+ print " looks just like the real ";
+ if (noun == player) print "Alice";
+ else PrintShortName(noun);
+ " only all reversed, left for right.";
+];
+
+Extend "look"
+ * "at" noun "in" noun -> Reflect;
+
+Extend "examine"
+ * noun "in" noun -> Reflect;
+
+Verb "roll" "untangle" "wind"
+ * noun -> Untangle
+ * "up" noun -> Untangle
+ * noun "up" -> Untangle;
+
+Object Drawing_Room "Drawing room"
+ has light
+ with name "snow",
+ description "The gentle sound of snow against the window pane
+ suggests that it's cold outside, and you're glad to be
+ here in the warmth. The drawing-room is reflected in the
+ large looking-glass on the wall above the mantelpiece,
+ and a very comfortable room it is too, with a warm
+ hearth, a soft rug and an arm-chair that you can curl up
+ and sleep in.",
+ before [;
+ if (player in mantelpiece && (action == ##Exit ||
+ (action == ##Go && noun == d_obj or out_obj)))
+ "That's not the way to get down from a mantelpiece!";
+ if (player in mantelpiece &&
+ action ~= ##Examine or ##Enter or ##Go &&
+ action ~= ##ThrownAt or ##ThrowAt or ##Reflect)
+ if ((noun > 0 && noun notin mantelpiece &&
+ noun ~= mantelpiece or mirror && noun notin player) ||
+ (second > 0 && second notin mantelpiece &&
+ second ~= mantelpiece or mirror && second notin player))
+ "Not from up here you can't!";
+ ];
+
+Object red_queen "red queen"
+ has female
+ with name "red" "queen",
+ describe [;
+ if (white_kitten.state == 1 || black_kitten.state == 1)
+ rtrue;
+ ],
+ description "She's a fierce little chess piece.",
+ after [;
+ Take:
+ if (white_kitten.state == 1)
+ white_kitten.state = 3;
+ if (black_kitten.state == 1)
+ black_kitten.state = 3;
+ PutOn,Transfer,Insert:
+ if (second == chess_board)
+ "Alone on the chess board, the red queen is monarch of
+ all she surveys.";
+ ];
+
+Object chess_board "chess board" Drawing_Room
+ has supporter
+ with name "chess" "board" "checker" "chequer" "chessboard",
+ initial "An abandoned chess board lies on the floor.",
+ description "It's left here from the game you were playing
+ just now, but the pieces are all missing - the kittens
+ will insist on playing with them.";
+
+Object hearth "hearth" Drawing_Room
+ has scenery
+ with name "hearth" "fire" "place" "fireplace";
+
+Object rug "rug" Drawing_Room
+ has concealed static supporter enterable
+ ! general if you've found the red queen under it
+ with name "hearthrug" "hearth-rug" "rug" "indian" "arabian" "beautiful"
+ "soft",
+ description "It's a beautiful rug, made in some far off
+ country, perhaps India or Araby, wherever those might
+ be.",
+ before [;
+ Take: "The rug is much too large and heavy for you to carry.";
+ Push,Pull: "But a hearth-rug is meant to be next to the
+ hearth!";
+ LookUnder:
+ if (player in mantelpiece || player in armchair)
+ "You're unable to reach the rug from here.";
+ if (player in self)
+ "You try to lift up a corner of the rug, but fail. After
+ a while, you realise that this is because you are
+ standing on it. How curious the world is!";
+ if (self hasnt general) {
+ give self general;
+ move red_queen to player;
+ "You lift up a corner of the rug and, peering
+ underneath, discover the red queen from the chess
+ set.";
+ }
+ ];
+
+Object armchair "arm-chair" Drawing_Room
+ has static concealed supporter enterable
+ ! general if its by the mantelpiece
+ with name "arm" "chair" "armchair" "arm-chair",
+ description [;
+ print "It's a huge arm-chair, the perfect place for a kitten
+ or a little girl to curl up in and doze. It has been
+ pushed over to the ";
+ if (self has general) "fireplace.";
+ "window.";
+ ],
+ before [ i;
+ Push,Pull:
+ if (player notin Drawing_Room)
+ print_ret "You'll have to get off ", (the) parent(player),
+ " first.";
+ if (white_kitten in player || black_kitten in player)
+ "Not with a kitten in your arms!";
+ if (white_kitten.state == 3) i = white_kitten;
+ else if (black_kitten.state == 3) i = black_kitten;
+ if (i ~= 0)
+ print_ret "You are about to start moving the chair when you
+ notice that ", (the) i, " is right in the way. It's a
+ good thing you spotted it, or you would have squashed
+ flat the poor little thing.";
+ if (self has general) {
+ give self ~general;
+ "You push the arm-chair away from the hearth.";
+ }
+ give self general;
+ "You push the arm-chair over to the hearth.";
+ Climb,Enter:
+ move player to armchair;
+ "You jump into the warm and comfortable arm-chair.";
+ ];
+
+Object mantelpiece "mantelpiece" Drawing_Room
+ has concealed supporter enterable
+ with name "mantel" "mantelpiece",
+ description "It's higher off the ground than your head, but
+ it looks wide enough and sturdy enough to support you.",
+ before [;
+ Enter,Climb:
+ if (player notin armchair)
+ "The mantelpiece is much too high to climb up onto.";
+ if (armchair hasnt general)
+ "You can't reach the mantelpiece from here.";
+ if (children(player) > 0)
+ "Your hands are too full.";
+ move player to mantelpiece;
+ "You scramble up onto the mantelpiece.";
+ PutOn,LetGo:
+ if (player notin self && (player notin armchair ||
+ armchair hasnt general))
+ "The mantelpiece is so high that you can't reach.";
+ ];
+
+Object mirror "looking-glass" Drawing_Room
+ has static concealed
+ with name "mirror" "looking" "glass" "looking-glass",
+ description [;
+ if (player in mantelpiece)
+ "Strangely, the glass is beginning to melt away,
+ just like a bright silvery mist.";
+ if (player in armchair)
+ "In the looking-glass you can see the drawing-room of
+ the looking-glass house. What you can see is very
+ much the same as this drawing-room, only all
+ reversed, left for right. But you are sure that out
+ of the corners of the glass, where you can't see, the
+ looking-glass world is quite different from yours.";
+ "In the looking-glass you can see the ceiling of the
+ drawing-room of the looking-glass house. It looks much
+ the same as the ceiling of your drawing-room.";
+ ],
+ before [;
+ if (action ~= ##Examine or ##ThrownAt or ##Reflect &&
+ player notin mantelpiece)
+ "You can't reach the looking-glass from where you're
+ standing.";
+ Touch,Pull,Push:
+ "Your hand goes right through the silvery mist!";
+ ThrownAt: "You don't want seven years' bad luck, do you?";
+ Enter:
+ ! Really, move Alice to the looking-glass house.
+ deadflag = 2;
+ "Your hand goes right through the silvery mist, and in
+ another moment the rest of you follows, and you are
+ through the glass...";
+ ];
+
+Object worsted "ball of worsted" Drawing_Room
+ ! general if its in a tangle
+ with name "ball" "of" "worsted" "fine" "blue" "wool",
+ describe [;
+ if (white_kitten.state ~= 2 &&
+ black_kitten.state ~= 2)
+ "^A discarded ball of worsted lies on the floor here.";
+ rtrue;
+ ],
+ description [;
+ if (self has general)
+ "It's in a terrible tangle. All that time you spent
+ rolling it up, and now look at it!";
+ "It's a ball of fine blue wool, all rolled up in preparation
+ for some embroidery.";
+ ],
+ before [;
+ Untangle:
+ give self ~general;
+ "You're as quick as can be at rolling up balls of wool,
+ though you say so yourself! Soon it's neat and tidy again.";
+ ],
+ after [;
+ Take:
+ if (white_kitten.state == 2)
+ white_kitten.state = 3;
+ if (black_kitten.state == 2)
+ black_kitten.state = 3;
+ ];
+
+Object chess_pieces "chess pieces" Drawing_Room
+ has scenery
+ with parse_name [ w colour n;
+ w = NextWord();
+ if (w == 'white' or 'red') {
+ n ++;
+ colour = w;
+ w = NextWord();
+ }
+ if (w == 'pawn' or 'rook' or 'castle' ||
+ w == 'knight' or 'horse' or 'bishop' ||
+ w == 'king' || (w == 'queen' &&
+ (colour == 'white' || rug hasnt general))) return n + 1;
+ return 0;
+ ],
+ before [;
+ "Alas, that chess piece seems to be missing. Those
+ naughty kittens!";
+ ];
+
+Object window "window" Drawing_Room
+ has scenery
+ with name "window" "pane",
+ description "Outside the window it's snowing gently, and you're
+ glad to be in here in the warmth.",
+ before [;
+ Open: "You wouldn't want to catch a chill, would you? Better
+ leave the window shut.";
+ Search: <>;
+ ];
+
+Property other_kitten;
+Property state; ! 1=red queen, 2=ball of wool, 3=arm-chair, 0=held
+
+Class Kitten_Class
+ has animate
+ ! general if it's been described this turn
+ with parse_name [ w ok n;
+ do {
+ ok = 0;
+ w = NextWord();
+ if (w == 'kittens' or 'cats') {
+ ok = 1; n++; parser_action=##PluralFound;
+ }
+ if (w == 'kitten' or 'kitty' or 'cat' ||
+ w == ((self.&name)-->0)) {
+ ok = 1; n++;
+ }
+ } until (ok == 0);
+ return n;
+ ],
+ state 3,
+ describe [ i;
+ switch (self.state) {
+ 1: print_ret "^A ", (name) self, " is playing with the red
+ queen.";
+ 2: print_ret "^A ", (name) self, " is playing with a ball of
+ worsted.";
+ 3: if (self has general) rtrue;
+ if ((self.other_kitten).state == 3) {
+ i = self.other_kitten;
+ give i general;
+ "^Two kittens, one white and one black, are playing
+ together by the arm-chair.";
+ }
+ print_ret "^A ", (name) self, " is playing by the
+ arm-chair.";
+ default: rtrue;
+ }
+ ],
+ description [;
+ print_ret "What a beautiful kitten ", (the) self, " is. Why,
+ it's quite definitely your favourite of the pair, and
+ much prettier than that naughty ", (name)
+ self.other_kitten, ".";
+ ],
+ life [;
+ Ask,Answer,Order:
+ print_ret (The) self, " twitches its whiskers and looks at
+ you with such a clever expression that you are certain it
+ understands every word you are saying.";
+ Kiss:
+ print_ret "You give ", (the) self, " a little kiss on its
+ nose, and it looks sweetly and demurely at you.";
+ Attack: "You would never do such a beastly thing to such
+ a defenceless little animal!";
+ Show:
+ print_ret (The) self, " bats a paw at ", (the) noun, ".";
+ Give,ThrowAt:
+ if (noun ~= red_queen or worsted) {
+ if (action == ##ThrowAt) {
+ move noun to Drawing_Room;
+ print "You toss ", (the) noun, " onto the floor, but ",
+ (the) self;
+ }
+ else print (The) self;
+ print_ret " just examines ", (the) noun, " with a
+ quizzical expression.";
+ }
+ print "You toss ", (the) noun, " onto the floor and ", (the) self;
+ if (self in player)
+ print " squirms out of your grasp and";
+ move noun to Drawing_Room;
+ move self to Drawing_Room;
+ print " scampers after it";
+ if (noun == worsted) {
+ give worsted general;
+ self.state = 2;
+ print ", quickly turning the neat ball into a tangle";
+ }
+ else self.state = 1;
+ ".";
+ ],
+ before [;
+ Take:
+ if (self.other_kitten in player)
+ "You can't hold two kittens at once!";
+ self.state = 0;
+ move self to player;
+ print_ret "You pick up ", (the) self, ". What a beautiful
+ creature it is!";
+ ],
+ after [;
+ Drop:
+ self.state = 3;
+ move self to Drawing_Room;
+ print_ret (The) self, " squirms out of your arms and scampers
+ away.";
+ Transfer,PutOn,Insert:
+ self.state = 3;
+ print (The) self, " jumps off ", (the) parent(self);
+ move self to Drawing_Room;
+ ", landing lightly on the floor before scampering away.";
+ ],
+ daemon [ i;
+ give self ~general;
+ self.number = 1 - self.number;
+ if (self.number == 1 || random(3) == 2) rtrue;
+ new_line;
+ print (The) self;
+ switch (self.state) {
+ 0: switch(random(5)) {
+ 1: " mews plaintively.";
+ 2: " purrs quietly to itself.";
+ 3: " purrs contentedly to itself.";
+ 4: " rubs its ears against you.";
+ 5: move self to Drawing_Room;
+ self.state = 3;
+ " squirms out of your arms and scampers away.";
+ }
+ 1: switch (random(5)) {
+ 1: " bats at the red queen with its paw.";
+ 2: " stops playing and sits up, pretending to be
+ innocent of any kittenish tendancies.";
+ 3: " knocks the red queen across the floor and chases
+ after it.";
+ 4: " stops to wash itself.";
+ 5: " bites the red queen and shakes it to make sure that
+ it's dead.";
+ }
+ 2: give worsted general;
+ switch (random(5)) {
+ 1: " bats at the ball of worsted with its paw.";
+ 2: " pushes the ball of worsted across the floor and
+ chases after it.";
+ 3: " leaps onto the ball of worsted and grapples bravely
+ with it.";
+ 4: " jumps into the ball of worsted and gets tangled up
+ in a mess of threads.";
+ 5: " stops playing and scratches its ears.";
+ }
+ 3: if ((self.other_kitten).state == 3 && random(2) == 1) {
+ i = random(5);
+ switch (i) {
+ 1: print " chases after ";
+ 2: print " jumps on top of ";
+ 3: print " washes ";
+ 4: print " scampers around the arm-chair and ";
+ 5: print " bats at ";
+ }
+ print (the) self.other_kitten;
+ switch (i) {
+ 1,3: ".";
+ 2: " and they roll around on the floor.";
+ 4: " chases after it.";
+ 5: " with its paw.";
+ }
+ }
+ switch (random(5)) {
+ 1: " scampers after a speck of dust.";
+ 2: " rolls around on the floor.";
+ 3: " sits up and washes its tail.";
+ 4: " scratches its head on the arm-chair.";
+ 5: " chases its tail.";
+ }
+ }
+ ];
+
+Object white_kitten "white kitten" Drawing_Room
+ class Kitten_Class
+ with name "white",
+ number 0,
+ other_kitten black_kitten;
+
+Object black_kitten "black kitten" Drawing_Room
+ class Kitten_Class
+ with name "black",
+ number 1,
+ other_kitten white_kitten;
+
+End;
\ No newline at end of file
diff --git a/presets/zmachine/aloneice.inf b/presets/zmachine/aloneice.inf
new file mode 100644
index 00000000..7b4c36a4
--- /dev/null
+++ b/presets/zmachine/aloneice.inf
@@ -0,0 +1,458 @@
+! -----------------------------------------------------------------------------
+Constant Story "Alone on The Ice";
+
+Constant Headline
+ "^Inform for New Writers^
+ ~Alone on The Ice~ - a sample game/tutorial
+ by Ethan Dicks - Last Compiled: 23-Feb-1998^";
+
+Release 1;
+Serial "980223";
+
+! The game is meant to be experimented with, so we always define:
+Constant DEBUG;
+
+! --------------------------------------------------------------------------
+
+! Put your "replaces" here to re-write parts of the Inform libraries
+
+Include "Parser";
+
+! --------------------------------------------------------------------------
+! Out on the open ice, every object that might be dropped out there needs to
+! have a property to store its "coordinate". Forgetting this could cause
+! serious bugs.
+Property ICELOC 0; ! coordinate of Object in ice field.
+
+! --------------------------------------------------------------------------
+
+Include "VerbLib";
+
+! --------------------------------------------------------------------------
+!
+! It all starts here --+
+! |
+! v
+[ Initialise;
+ location = HUT1;
+
+thedark.description = "There is nothing here but whiteness. If you move
+from this spot, you are likely to be hopelessly lost";
+
+ "You awake from a dreamless sleep to silence. You look around the room
+ for Tom, your campmate; he isn't here. Of all the places to go for a
+ walk by yourself, the middle of the Antarctic plateau isn't one of them.
+ Despite your training to stay put and wait for him to come back, you
+ decide to go after him. It's just the two of you here, and no planes
+ due for weeks.";
+];
+
+! --------------------------------------------------------------------------
+!
+! Things - the elements of our interactive world
+!
+! --------------------------------------------------------------------------
+
+Object HUT1 "A small scientific observation hut"
+with description "This cramped insulated box has been your home for
+ several months now. There is little in here but
+ some equipment for monitoring the weather and two
+ cots.",
+n_to DOOR1,
+has light;
+
+!----
+Object -> DOOR1 "freezer door" ! An ordinary two-sided door (as implemented
+! in the Inform Designer's Manual, chpt. 12).
+with description "There is a door in the wall of the hut, nearly as wide
+ as the wall. It is large, white and heavy. It does
+ not appear to have a doornob, as such, but more of a
+ plunger like you'd find on the inside of a meat locker.",
+name "white" "freezer" "door",
+when_closed [; rfalse; ],
+when_open "The door has been carelessly left open and the cold,
+ antarctic wind is blowing into the hut, unabated.",
+door_to [; if (location==CAMP14) return HUT1; return CAMP14; ],
+door_dir [; if (location==CAMP14) return n_to; return s_to; ],
+found_in HUT1 CAMP14,
+has static door openable;
+
+!----
+Object -> NOTE "goodbye note"
+with initial "There is a piece of paper taped to the door here.",
+inven "A note from your campmate.",
+name "note" "paper" "piece",
+ICELOC 0,
+before [; Examine: "The paper appears torn hastily from a notebook, the
+ writing nearly illegible. It reads:^^Went to get
+ some smokes. Be back soon.^^^^ --Tom";
+],
+
+has ~static; ! make sure it's portable
+
+!----
+Object -> BOOK "survival guide"
+with name "book" "survival" "guide",
+initial "A survival guide lies discarded in the corner.",
+ICELOC 0,
+before [; Examine: "It's a standard issue guide to survival in Antarctica.
+ You got it on your first day here. On the back cover
+ is a list of important safety tips:
+ ^ Black flags mark hazards - do not approach.
+ ^ Orange flags mean safe travel.
+ ^ Stick to the flagged routes.
+ ^ Travel in pairs (I guess Tom forgot that one).
+ ^ In a white-out, sit down and wait it out.^";
+],
+has ~static; ! make sure it's portable
+
+!----
+Object CAMP14 "Weather Observation Post 14"
+with description "Behind the sign that reads, ~The United States Welcomes
+ you to Observation Post 14,~ lies your camp: an orange
+ eight-foot by eight-foot box that you call home. There
+ is a line of orange trail-marker flags heading off in
+ the distance to the north. The rest is whiteness",
+s_to DOOR1,
+n_to
+ [;
+ ! Drop the player at the starting poing
+ PlayerTo(ICE,1); ! Put the player in the "ice room" Object
+ IGOTO(52); ! Set the starting location (middle of the south edge)
+ rtrue; ! Tell the parser that it worked.
+ ],
+has light;
+
+!----
+Object CAMP9 "Weather Observation Post 9"
+with description "This is another field camp, the sign here tells you,
+ ~The United States Welcomes you to Observation Post 9~.
+ The flagged route goes south from here.",
+n_to DOOR2,
+s_to
+ [;
+ ! Drop the player at the starting poing
+ PlayerTo(ICE,1); ! Put the player in the "ice room" Object
+ IGOTO(12); ! Set the starting location (middle of the north edge)
+ rtrue; ! Tell the parser that it worked.
+ ],
+has light;
+
+!----
+Object HUT2 "A small scientific observation hut"
+with description "This looks like a duplicate of your own observation hut,
+ down to the scuff marks on the floor.",
+
+s_to ICE2,
+n_to DOOR2,
+has light;
+
+!----
+Object -> DOOR2 "freezer door" ! An ordinary two-sided door (as implemented
+! in the Inform Designer's Manual, chpt. 12).
+with description "There is a familiar looking door in the wall of the hut,
+ with a familiar looking opening plunger.",
+name "white" "freezer" "door",
+when_closed [; rfalse; ],
+when_open "The door has been carelessly left open and the cold,
+ antarctic wind is blowing into the hut, unabated.",
+door_to [; if (location==CAMP9) return HUT2; return CAMP9; ],
+door_dir [; if (location==CAMP9) return n_to; return s_to; ],
+found_in HUT2 CAMP9,
+has static door openable;
+
+!----
+Object -> TOM "your campmate, Tom"
+with name "Tom",
+description "Tom, the only other person for a hundred miles, is here,
+ smoking the foulest smelling cigarettes you have ever
+ smelled - Penguin Slims",
+has proper animate;
+
+! In order to create the illusion of an enormous expanse of rooms without
+! having to create one object per location, we simulate a large area with
+! two real rooms and an array. One room (ICE) contains the Player object
+! at all times. The other (ICE2), is a temporary holding area for the
+! objects that are located in various places throughout the virtual space.
+! We use the "ICELOC" property to remember where in the greater area an
+! object was the last time the Player saw it.
+!
+Object ICE "Out on the open ice"
+with name "ICE",
+description
+ [; IWHERE(); ],
+
+ before
+ [; Go:
+! Check to see if we are at an exit space, otherwise, just move
+! around the virtual area.
+return IEXIT();
+ ],
+
+ ! Since we don't move from object to object, all roads lead back here. The
+ ! only way out is through specially marked spaces.
+ n_to ICE, s_to ICE, e_to ICE, w_to ICE,
+ ne_to ICE, nw_to ICE, se_to ICE, u_to ICE, sw_to ICE,
+ d_to ICE,
+
+ has light static container;
+
+! We need a place to stash things that get left out on the ice
+Object ICE2 "Ice Box" with name "ICE2", description "Ice Box", has light;
+
+! ----------------------------------------
+! Let's leave a trail for Player to follow
+!
+Class Flag
+with description "trail flag",
+name "marker" "flag" "bamboo" "pole",
+initial
+ [;
+ "There is ", (a) self, " trail-marker flag here, fluttering
+ at the end of a bamboo pole";
+ ],
+After
+ [; Take: print "You pull the flag from the snow"; ],
+
+has ~static; ! Let's let the player pick up and move the flags around.
+
+! Now, create several instances of the flags and stick them in the holding room
+Class Orange_Flag class Flag with name "orange", article "an";
+Class Black_Flag class Flag with name "black", article "a";
+
+Orange_Flag O1 "orange flag" ICE2 with plural "orange flags", ICELOC 12;
+Orange_Flag O2 "orange flag" ICE2 with plural "orange flags", ICELOC 20;
+Orange_Flag O3 "orange flag" ICE2 with plural "orange flags", ICELOC 28;
+Orange_Flag O4 "orange flag" ICE2 with plural "orange flags", ICELOC 36;
+Orange_Flag O5 "orange flag" ICE2 with plural "orange flags", ICELOC 44;
+Orange_Flag O6 "orange flag" ICE2 with plural "orange flags", ICELOC 52;
+
+Black_Flag BL1 "black flag" ICE2 with plural "black flags", ICELOC 53;
+Black_Flag BL2 "black flag" ICE2 with plural "black flags", ICELOC 45;
+Black_Flag BL3 "black flag" ICE2 with plural "black flags", ICELOC 37;
+Black_Flag BL4 "black flag" ICE2 with plural "black flags", ICELOC 29;
+! ----------------------------------------
+
+Global IPLAYER=52; ! Current location of Player on the ice
+
+!----------
+! Virtual room array
+! This array is a grid representation of the ice field. Different numbers
+! represent the kind of terrain found in a particular "location". To make
+! life easier for the programmer, positive numbers are inaccessible, zero
+! is flat and level, and negative numbers are used for features such as exits
+! and moveable ice blocks (not implemented in this tutorial).
+!
+! It's best to list this out in table form:
+! 1 is impassable barrier (crevasse)
+! -1 is movable block of ice (Not Implemented Yet)
+! -2 is the passage to the north exit
+! -3 is the passage to the south exit
+
+Array IVEC --> 0 1 1 1 (-2) 1 1 1 1
+1 0 0 0 0 0 0 1
+1 0 0 0 0 0 0 1
+1 0 0 0 0 1 0 1
+1 0 0 0 0 1 0 1
+1 0 0 0 0 1 0 1
+1 0 0 0 0 1 0 1
+1 1 1 (-3) 1 1 1;
+
+! Note the north-south crevasse to the east of the expected path of the Player.
+
+! ----------------------------------------
+! Walking around on the ice field
+
+! NB: n_obj is 7. The array has dummy entries to match the array element
+! number with the direction object number. The elements/directions
+! follow the order N, S, E, W, NE, NW, SE, SW. If this changes, this
+! array and it's supporting code must be redesigned. This may not
+! be the best way to do this, but it does work.
+!
+! These numbers are based on an 8x8 grid. A grid of a different size would
+! generate different numbers (i.e., a 4x4 grid would see -4 for -8, -3 for
+! -7, -5 for -9, etc.)
+Array IEXITS --> 0 0 0 0 0 0 0 (-8) 8 1 (-1) (-7) (-9) 9 7;
+
+!
+! IEXIT - let the player exit the ice field
+!
+[ IEXIT;
+ ! Check to see if the player is in the right place and moving in the right
+ ! direction (up).
+ if (IPLAYER==12 or 52) {
+ ! Is there a way up here? (N.B.: for this example, there always is).
+ if ((IVEC-->(IPLAYER + IEXITS-->noun)) == -2) {
+print "You scramble up the trail and onto the plateau.^";
+give ICE ~visited;
+Playerto(CAMP9,2);
+rtrue;
+ }
+ else if ((IVEC-->(IPLAYER + IEXITS-->noun)) == -3) {
+print "You scramble up the trail and back to camp.^";
+give ICE ~visited;
+Playerto(CAMP14,2);
+rtrue;
+ }
+ }
+
+ if (noun==u_obj) {
+ print "There is nothing but flat, featureless ice here. Nothing to
+ climb";
+ return 3;
+ }
+
+ ! Don't let them go down, ever.
+ if (noun==d_obj) {
+ print "That's not a good idea.";
+ return 3;
+ }
+
+ ! If the intended space is empty, let the player move there
+ if (IVEC-->(IPLAYER + IEXITS-->noun)==0) {
+ return IGOTO(IPLAYER + IEXITS-->noun);
+ }
+
+ ! There must be a barrier. Stop them from moving.
+ print "In the nick of time, you step back from the edge of a yawning
+crevasse.";
+ return 3;
+];
+
+
+!------
+! "Move" to new ice room
+
+[ IGOTO FX x y;
+
+ ! Forget we were ever here. This keeps the descriptions fresh.
+ give ICE ~visited;
+
+ ! Move stuff out of the old location into the storage space
+ x = child(ICE);
+ while (x) {
+ y=sibling(x);
+ if ( (x hasnt concealed) && (x ~= Player) ) {
+ x.ICELOC=IPLAYER; ! Remember where it came from
+ move x to ICE2; ! Stash it
+ }
+ x = y;
+ }
+
+ ! "move" player to the new location
+ IPLAYER=FX;
+
+ ! Pull stuff from the storage space to the new location, if it belongs here
+ x = child(ICE2);
+ while (x) {
+ y=sibling(x);
+ ! see if this Object belongs in our new location
+ if (x.ICELOC == IPLAYER) {
+ x.ICELOC=0; ! Forget where it used to be
+ move x to ICE; ! Put it back in here
+ }
+ x = y;
+ }
+
+ ;
+ give ICE ~visited;
+ return 3;
+];
+
+! ----------------------------------------
+!
+! Describe location out on the open ice.
+!
+[ IWHERE N W S E num_crevasse crevasse_dir;
+ N = IVEC-->(IPLAYER - 8);
+ S = IVEC-->(IPLAYER + 8);
+ E = IVEC-->(IPLAYER + 1);
+ W = IVEC-->(IPLAYER - 1);
+
+! print "This is Ice Room #", IPLAYER, ".^";
+
+ ! See if Player is somewhere safe or not
+ if ( ON_FLAGGED_ROUTE(IPLAYER) )
+print "You are on the flagged route. ";
+ else
+print "You are out on the open ice, a dangerous thing. ";
+
+ ! Count the crevasses and remember which direction they are in
+ if (N == 1) { num_crevasse++; crevasse_dir = crevasse_dir + 1; }
+ if (S == 1) { num_crevasse++; crevasse_dir = crevasse_dir + 2; }
+ if (E == 1) { num_crevasse++; crevasse_dir = crevasse_dir + 4; }
+ if (W == 1) { num_crevasse++; crevasse_dir = crevasse_dir + 8; }
+
+ ! If there are any crevasses, warn Player
+ if (num_crevasse) {
+print "There ";
+if (num_crevasse == 1) ! How many?
+print "is a crevasse to the ";
+else
+print "are crevasses to the ";
+
+if (N == 1) {
+print "north";
+num_crevasse--;
+if (num_crevasse == 1)
+print " and ";
+else if (num_crevasse > 1)
+print ", ";
+}
+
+if (S == 1) {
+print "south";
+num_crevasse--;
+if (num_crevasse == 1)
+print " and ";
+else if (num_crevasse > 1)
+print ", ";
+}
+
+if (E == 1) {
+print "east";
+num_crevasse--;
+if (num_crevasse == 1)
+print " and ";
+else if (num_crevasse > 1)
+print ", ";
+}
+
+if (W == 1)
+print "west";
+
+print ".";
+ }
+
+ print "^";
+
+ ! Let's thrown in a colorful phrase, just for fun...
+ if (IPLAYER==36)
+ print "(If Nowhere has a Middle, this is it.)^";
+
+ ! Describe the exits, if present
+ if (N==-2)
+ print "There is a plateau to the north here. There appears to be a way to
+ scramble up to it that avoids the crevasse.";
+
+ if (S==-3)
+ print "You can see your camp up and to the south.^";
+
+];
+
+!
+! Check to see if Player is on the route
+!
+! To-do: Check for an undisturbed flag along the route
+!
+[ ON_FLAGGED_ROUTE location;
+ if (location == 12 or 20 or 28 or 36 or 44 or 52)
+rtrue;
+
+ rfalse;
+];
+
+!----
+! Define verbs here...
+
+Include "Grammar";
diff --git a/presets/zmachine/balances.inf b/presets/zmachine/balances.inf
new file mode 100644
index 00000000..443b425d
--- /dev/null
+++ b/presets/zmachine/balances.inf
@@ -0,0 +1,1932 @@
+! ----------------------------------------------------------------------------
+! Balances 160701 One of the standard Inform 6 example games
+!
+! created: 25.09.1994
+! updated: 06.10.1994
+! modernised: 11.12.1995
+! translated to Inform 6: 08.05.1996
+! minor bugs fixed: 16.12.1996
+! modernised again by Vince Laviano: 01.07.2016
+!
+! This short story was written to demonstrate large-scale programming of
+! the parser, and features multiple objects, complicated plurals, variable
+! verbs, objects named by the player and questions. The spell-casting
+! system is written in a "safe" way so that it could easily be transplanted.
+!
+! Needs Inform 6, library 6/5 or later to compile.
+! ----------------------------------------------------------------------------
+
+Release 6;
+Serial "160701";
+Switches d;
+
+Constant Story "BALANCES";
+Constant Headline "^An Interactive Short Story
+ ^Copyright (c) 1994, 1995, 1996, 2016 by Graham Nelson.^";
+
+Constant OBJECT_SCORE 5;
+Constant MAX_SCORE 51;
+
+Include "Parser";
+Include "VerbLib";
+
+! ----------------------------------------------------------------------------
+! The white featureless cubes from "Spellbreaker", which can be identified
+! by being written on with the magic burin, so that their names are given
+! by the player in the course of play
+!
+! A particularly witty thing to do is to give several of them the same name,
+! or to frotz some of them to distinguish them from the others...
+! And the game will have no problem with this.
+! ----------------------------------------------------------------------------
+
+Array cube_text_buffer -> 8;
+Global the_named_word = 0;
+Global from_char; Global to_char;
+
+Class FeaturelessCube
+ with number 0 0 0 0, ! There's room for 8 bytes of text in these 4 entries
+ description "A perfect white cube, four inches on a side.",
+ parse_name
+ [ i j flag;
+ if (parser_action==##TheSame)
+ { for (i=0:i<8:i++)
+ if ((parser_one.&number)->i
+ ~= (parser_two.&number)->i) return -2;
+ return -1;
+ }
+ for (::i++)
+ { j=NextWord(); flag=0;
+ if (j=='cube' or 'white' ||
+ (j=='featureless' or 'blank' &&
+ ((self.&number)->0) == 0)) flag=1;
+ if (j=='cubes')
+ { flag=1; parser_action=##PluralFound; }
+ if (flag==0 && ((self.&number)->0) ~= 0)
+ { wn--;
+ if (TextReader(0)==0) return i;
+ for (j=0: j<8: j++)
+ if ((self.&number)->j ~= cube_text_buffer->j)
+ return i;
+ flag=1;
+ }
+ if (flag==0) return i;
+ }
+ ],
+ article "a",
+ short_name
+ [ i; if (((self.&number)->0) == 0) print "featureless white cube";
+ else
+ { print "~";
+ while (((self.&number)->i) ~= 0)
+ print (char) (self.&number)->i++;
+ print "~ cube";
+ }
+ rtrue;
+ ],
+ plural
+ [; self.short_name(); print "s";
+ ],
+ baptise
+ [ i; wn = the_named_word;
+ if (TextReader(1)==0) return i;
+ for (i=0: i<8: i++)
+ (self.&number)->i = cube_text_buffer->i;
+ self.article="the";
+ print_ret "It is now called ", (the) self, ".";
+ ],
+ has scored;
+
+! Copies word "wn" from what the player most recently typed, putting it as
+! plain text into cube_text_buffer, returning false if no such word is there
+
+[ TextReader flag point i j len;
+
+ if (flag==1 && from_char~=to_char)
+ { for (i=from_char, j=0:i<=to_char && j<7:i++)
+ { cube_text_buffer->j = buffer->i;
+ if (buffer->i ~= ' ' or ',' or '.') j++;
+ }
+ for (:j<8:j++) cube_text_buffer->j = 0;
+ from_char=0; to_char=0;
+ rtrue;
+ }
+
+ for (i=0:i<8:i++) cube_text_buffer->i = 0;
+ if (wn > parse->1) { wn++; rfalse; }
+ i=wn*4+1; j=parse->i; point=j+buffer; len=parse->(i-1);
+
+ for (i=0:ii = point->i;
+
+ wn++; rtrue;
+];
+
+Object burin "magic burin"
+ with name "magic" "magical" "burin" "pen",
+ description
+ "This is a magical burin, used for inscribing objects with words
+ or runes of magical import. Such a burin also gives you the
+ ability to write spell scrolls.",
+ before
+ [; WriteOn:
+ if (second ofclass FeaturelessCube)
+ { if (second notin player)
+ "Writing on a cube is such a fiddly process that you
+ need to be holding it in your hand first.";
+ if (burin notin player)
+ "You would need some powerful implement for that.";
+ second.baptise();
+ rtrue;
+ }
+ if (second ofclass SpellBook)
+ "If a burin could write in a spell book, you wouldn't need
+ the gnusto spell!";
+ if (second ofclass Scroll)
+ "You cannot write just anything on the magic parchment of
+ a scroll: you can only ~copy~ a spell to it.";
+ ];
+
+[ WriteOnSub; "Graffiti is banned."; ];
+
+[ CopyToSub;
+ if (burin notin player) "You need to be holding the burin to copy a spell.";
+ if (second ofclass SpellBook)
+ "If a burin could write in a spell book, you wouldn't need
+ the gnusto spell!";
+ if (~~(second ofclass Scroll)) "You can only copy spells to scrolls.";
+ if (child(second)~=0)
+ "The scroll is already full of incantation.";
+ "The scroll is not blank, only illegible.";
+];
+
+! ----------------------------------------------------------------------------
+! Now the whole spell-casting system
+! ----------------------------------------------------------------------------
+
+Attribute known_about; ! Player has seen this spell somewhere
+Attribute reversed; ! Effect of this known spell reversed
+
+Attribute is_spell;
+Class Spell
+ with name "spell" "spells", article "the",
+ number 0,
+ word_name
+ [; print (address) (self.&name)-->0;
+ ],
+ short_name
+ [; self.word_name(); print " spell"; give self known_about; rtrue;
+ ],
+ specification
+ [; self.short_name();
+ print ": ", (string) self.purpose;
+ ],
+ before
+ [; Examine: self.specification(); ".";
+ ],
+ has is_spell;
+
+Object memory
+ with capacity 5,
+ number_known 1,
+ describe_contents
+ [ i j k;
+ objectloop (i in self) if (i.number==100) j++;
+ if (j>0)
+ { print "The ";
+ objectloop (i in self)
+ if (i.number==100)
+ { k++; i.word_name();
+ if (k==j-1) print " and ";
+ if (k0)
+ { print "the ";
+ objectloop (i in self)
+ if (i.number<100)
+ { k++;
+ print (name) i;
+ if (i.number==2) print " (twice)";
+ if (i.number==3) print " (thrice)";
+ if (i.number==4) print " (four times)";
+ if (i.number>=5) print " (many times)";
+ if (k==j-1) print " and ";
+ if (k3) print " yet another time.";
+ if (self.number_known <= self.capacity) { new_line; rtrue; }
+ self.forget_spell(sibling(child(self)));
+ " You have so much buzzing around in your head, though,
+ that it's likely something may have been forgotten
+ in the shuffle.";
+ ],
+ forget_spell
+ [ sp;
+ if (sp notin self || sp.number==100) rtrue;
+ self.number_known--;
+ sp.number--;
+ if (sp.number==0) remove sp;
+ rtrue;
+ ];
+
+Spell -> gnusto_spell
+ with name "gnusto",
+ purpose "copy a scroll into your spell book",
+ number 100,
+ magic
+ [ i a_book;
+ if (second ofclass SpellBook)
+ "Unlike scrolls, spell books are magically guarded against
+ the 'theft' of their lore.";
+ if (second==0 || ~~(second ofclass Scroll))
+ "Your spell fizzles vaguely out.";
+ if (second notin player)
+ "A gnusto spell would require close scrutiny of the scroll
+ it is to copy: which you do not seem to be holding.";
+ objectloop (i in player)
+ if (i ofclass SpellBook) a_book=i;
+ if (a_book==0)
+ "Your spell fails, as you have no spell book.";
+ i=child(second);
+ if (i==0 || ~~(i ofclass Spell))
+ { print_ret "Your spell fails, as ", (the) second,
+ " is illegible.";
+ }
+ a_book.learn_spell(i); remove second;
+ print_ret
+ "Your spell book begins to glow softly. Slowly, ornately,
+ the words of ", (the) i, " are inscribed,
+ glowing even more brightly then the book itself.
+ The book's brightness fades, but the spell remains!
+ However, the scroll on which it was written vanishes as
+ the last word is copied.";
+ ];
+
+Class SpellBook
+ with array_of_spells 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0,
+ capacity 16,
+ learn_spell
+ [ sp p i;
+ p = self.&array_of_spells;
+ for (i=0:ii)~=0:i++) ;
+ if (i==self.capacity) rtrue;
+ p-->i = sp;
+ ],
+ before
+ [; Open, Close:
+ print_ret
+ (The) self, " is always open to the right place, but it
+ is also always closed. This eliminates tedious leafing and
+ hunting for spells. Many lives have been saved by this
+ magical innovation.";
+ Attack:
+ print_ret "When you are done, ", (the) self, " remains unmarred.";
+ ],
+ after
+ [ p i j; Examine:
+ p = self.&array_of_spells;
+ for (i=0:ii)~=0:i++)
+ { j=p-->i; ;
+ }
+ rtrue;
+ ];
+
+Class Scroll
+ with parse_name
+ [ i j k; j=-1;
+ if (self has general)
+ { if (child(self)~=0 && child(self) ofclass Spell)
+ j=(child(self).&name)-->0; else j='illegible';
+ }
+ for (::)
+ { k=NextWord();
+ if (k=='scrolls') parser_action=##PluralFound;
+ if ((k=='scrolls' or 'scroll' or j) || k==(self.&name)-->0)
+ i++;
+ else return i;
+ }
+ ],
+ before
+ [ i; Examine:
+ i=child(self);
+ give self general;
+ if (i==0 || ~~(i ofclass Spell))
+ "The scroll has faded, and you cannot read it.";
+ print "The scroll reads ~"; i.specification(); "~.";
+ ],
+ invent
+ [; if (inventory_stage==2 && self has general)
+ { if (child(self)==0 || ~~(child(self) ofclass Spell))
+ print " (which is illegible)";
+ else
+ { print " (of ", (the) child(self), ")"; }
+ }
+ ];
+
+[ ReadableSpell i j k;
+ if (scope_stage==1)
+ { if (action_to_be==##Examine) rfalse;
+ rtrue;
+ }
+ if (scope_stage==2)
+ { objectloop (i in player)
+ if (i ofclass SpellBook)
+ { for (k=0:kk~=0:k++)
+ { j=(i.&array_of_spells)-->k; PlaceInScope(j);
+ }
+ }
+ rtrue;
+ }
+ ! No need for scope_stage 3 (the error stage), because our
+ ! ParserError routine handles that case instead
+];
+
+[ CopyableSpell i j k;
+ if (scope_stage==1) return 1;
+ if (scope_stage==2)
+ { objectloop (i in player)
+ if (i ofclass SpellBook)
+ { for (k=0:kk~=0:k++)
+ { j=(i.&array_of_spells)-->k; PlaceInScope(j);
+ }
+ }
+ rfalse;
+ }
+ ! No need for scope_stage 3 (the error stage), because our
+ ! ParserError routine handles that case instead
+];
+
+[ LearnedSpell i;
+ if (scope_stage==1) rfalse;
+ if (scope_stage==2)
+ { objectloop (i in memory)
+ if (i has is_spell) PlaceInScope(i);
+ rfalse;
+ }
+ ! No need for scope_stage 3 (the error stage), because our
+ ! ParserError routine handles that case instead
+];
+
+[ SpellsSub; memory.describe_contents(); ];
+
+[ LearnSub; if (location==thedark)
+ print "(The magic writing of the spells casts enough light
+ that you can read them.)^";
+ memory.learn_spell(noun);
+];
+
+Global the_spell_was = gnusto_spell;
+
+[ CastOneSub; ; ];
+
+[ CastSub;
+ the_spell_was = noun; memory.forget_spell(noun);
+
+ if (noun has reversed)
+ { give noun ~reversed;
+ if (noun.unmagic() ~= 0) return;
+ "Nothing happens.";
+ }
+
+ if (second ~= 0)
+ { ResetVagueWords(second); ! Set "it", "him", "her"
+ if (second provides before
+ && second.before() ~= 0) return; ! Run before routine(s)
+ }
+ if (noun.magic() ~= 0) return;
+ "Nothing happens.";
+];
+
+[ InScope i;
+ if (verb_word=='c,cast' or 'cast')
+ objectloop (i in memory) PlaceInScope(i);
+ rfalse;
+];
+
+[ ParserError i flag vb;
+ if (etype==VERB_PE or ASKSCOPE_PE)
+ { if (etype==ASKSCOPE_PE)
+ { if (verb_word=='cast') vb=1;
+ if (verb_word=='learn' or 'memorise' or 'memorize') vb=2;
+ if (verb_word=='copy') vb=3;
+ if (vb==0) { etype=CANTSEE_PE; rfalse; }
+ }
+ wn=verb_wordnum; if (vb~=0) wn++;
+ for (i=player+1:i<=top_object:i++)
+ if (i ofclass Spell && Refers(i,wn)==1
+ && i has known_about) flag=1;
+ if (flag==1)
+ { if (vb==0 or 1)
+ "You haven't got that spell committed to memory. [Type ~spells~
+ to see what you do remember.]";
+ if (vb==2)
+ "Your training is such that you can only memorise such a spell
+ with the aid of a spell book containing it.";
+ if (vb==3)
+ "You have no text of that spell to copy.";
+ }
+ if (vb==1)
+ "You haven't learned that spell, if indeed it is a spell.";
+ if (vb==2 or 3)
+ "You haven't access to that spell, if indeed it is a spell.";
+ }
+ rfalse;
+];
+
+[ ChooseObjects obj code;
+ if (code<2) rfalse;
+ if (action_to_be==##WriteOn && obj in player) return 9;
+ return 0;
+];
+
+[ UnknownVerb word i;
+ objectloop (i in memory)
+ if (word==(i.&name)-->0) { the_spell_was = i; return 'c,cast'; }
+ rfalse;
+];
+
+[ PrintVerb v;
+ if (v=='c,cast') { print "cast a spell at"; rtrue; }
+ rfalse;
+];
+
+! ----------------------------------------------------------------------------
+! And now, on with the story. First, some global variables:
+! ----------------------------------------------------------------------------
+
+Global prepared_flag = false; ! Prepared for resurrection?
+Global hearing_good = false; ! Sharp hearing?
+Global number_filled = 0; ! Sockets in the temple filled
+
+! ----------------------------------------------------------------------------
+! A "questions" verb. Thus,
+! "who is my friend helistar"
+! "what was the great change"
+! and so on are recognised.
+! ----------------------------------------------------------------------------
+
+[ QuerySub;
+ noun.description();
+];
+[ Topic i;
+ if (scope_stage==1) return 0;
+ if (scope_stage==2)
+ { objectloop (i ofclass Question) PlaceInScope(i);
+ rtrue;
+ }
+ "At the moment, even the simplest questions confuse you.";
+];
+
+Class Question;
+Question
+ with name "helistar" "my" "friend" "colleague",
+ description
+ "Helistar is your colleague, an Enchanter like you who has been much
+ on your mind lately. She has been investigating some very dark
+ magic indeed, and seems not to be around any more. You feel rather
+ vague about the details.";
+Question
+ with name "magical" "magic" "burin",
+ description "A burin is an engraving and writing tool.";
+Question
+ with name "change" "great",
+ description
+ "Something you had a lot to do with, but what exactly? No, it's gone.";
+Question
+ with name "cyclops",
+ description
+ "A one-eyed giant, usually hostile. (Don't they teach anything at
+ adventurer school these days?)";
+Question
+ with name "grue",
+ description
+ "The grue is a sinister, lurking presence in the dark places of the
+ earth. Its favorite diet is adventurers, but its insatiable appetite
+ is tempered by its fear of light. No grue has ever been seen by the
+ light of day, and few have survived its fearsome jaws to
+ tell the tale.";
+Question
+ with name "grimoire",
+ description
+ "According to Chambers English Dictionary, a grimoire is ~a magician's
+ book for calling up spirits~.";
+Question
+ with name "spells" "work",
+ description
+ "Your memory is still dream-hazed, but it's coming back. As a trained
+ Enchanter, you have the ability to cast spells like ~frotz~, provided
+ you have learned them in advance. Some of these spells can be cast
+ at something; others can be cast alone.
+ ^^Spells are very complicated. Each time you cast one, you forget it
+ (though you can get around this by learning it several times, so as
+ to have several uses up your sleeve). The only way to hang on to
+ a spell is to have it written down, on a scroll or in a spell book.
+ Scrolls are not ideal for this, and you can only learn a spell from
+ your spell book. (But you can add spells to your book.)
+ ^^[Type ~learn frotz~ and then ~frotz coin~ for an example. You can
+ also type ~spells~ to see what you currently have memorised.]";
+
+! ----------------------------------------------------------------------------
+! Some multiple objects, coins in fact, coded in deluxe fashion:
+! ----------------------------------------------------------------------------
+
+Attribute is_coin;
+Class Coin
+ with name "coin",
+ description "A round unstamped disc, presumably part of the local
+ currency.",
+ parse_name
+ [ i j w;
+ if (parser_action==##TheSame)
+ { if ((parser_one.&name)-->0 == (parser_two.&name)-->0) return -1;
+ return -2;
+ }
+ w=(self.&name)-->0;
+ for (::i++)
+ { j=NextWord();
+ if (j=='coins') parser_action=##PluralFound;
+ else if (j~='coin' or w) return i;
+ }
+ ],
+ has is_coin;
+
+Class GoldCoin
+ class Coin,
+ with name "gold",
+ short_name "gold coin",
+ plural "gold coins";
+Class SilverCoin
+ class Coin,
+ with name "silver",
+ short_name "silver coin",
+ plural "silver coins";
+Class BronzeCoin
+ class Coin,
+ with name "bronze",
+ short_name "bronze coin",
+ plural "bronze coins";
+
+SilverCoin players_coin;
+
+[ TossCoinSub; if (noun notin player) "You need to be holding the coin first.";
+ move noun to parent(player);
+ if (location==thedark) "You throw it away into the darkness.";
+ if (random(20)==1)
+ "You toss the coin, and it lands... on its edge, amazingly.";
+ "You toss the coin, and it comes up... blank, since neither side is
+ marked.";
+];
+
+! ----------------------------------------------------------------------------
+! The player's spell book, and three initial spells (to go with gnusto):
+! ----------------------------------------------------------------------------
+
+SpellBook players_book "spell book"
+ with name "spell" "book" "my" "spellbook",
+ description "My Spell Book^";
+
+Spell frotz_spell
+ with name "frotz",
+ purpose "cause an object to give off light",
+ magic
+ [; if (second==0) "There is a brief, blinding flash of light.";
+ if (second has animate)
+ "The spell, not designed for living creatures, goes sour.";
+ if (second in compass)
+ "The spell dissipates vaguely.";
+ give second light;
+ print_ret
+ "There is an almost blinding flash of light as ", (the) second,
+ " begins to glow! It slowly fades to a less painful level, but ",
+ (the) second, " is now quite usable as a light source.";
+ ],
+ unmagic
+ [; if (second==0) "There is a brief moment of deep darkness.";
+ if (second has animate)
+ "The spell, not designed for living creatures, goes sour.";
+ if (second in compass)
+ "The spell dissipates vaguely.";
+ if (second hasnt light)
+ print_ret (The) second, " isn't producing light as it is.";
+ give second ~light;
+ print_ret "A pool of darkness coagulates around ", (the) second,
+ " but slowly fades back to normality. Still, ",
+ (the) second, " is no longer any kind of light source.";
+ ];
+
+Spell rezrov_spell
+ with name "rezrov",
+ purpose "open even locked or enchanted objects",
+ magic
+ [; if (second==0) "The world is open already.";
+ if (second has animate)
+ "It might be a boon to surgeons if it worked, but it doesn't.";
+ if (second has open || second hasnt openable)
+ "It doesn't need opening.";
+ if (second hasnt locked)
+ { give second open;
+ print_ret (The) second, " opens obediently.
+ Like swatting a fly with a sledge hammer, if you ask me.";
+ }
+ give second open ~locked;
+ print "Silently, ", (the) second, " swings open. ";
+ if (second has container) <>; new_line; rtrue;
+ ],
+ unmagic
+ [; if (second==0) "The world is closed already.";
+ if (second has animate)
+ "Happily, that is unnecessary.";
+ if (second has locked || second hasnt lockable)
+ "It doesn't need locking.";
+ give second ~open locked;
+ "Silently, ", (the) second, " swings shut and locks.";
+ ];
+
+Spell yomin_spell
+ with name "yomin",
+ purpose "mind probe",
+ magic
+ [; if (second==0 || second hasnt animate)
+ "That must be either vegetable or mineral.";
+ if (second==player) "You give yourself a mild headache.";
+ print_ret "You look into the rather ordinary thoughts of ",
+ (the) second, ".";
+ ],
+ unmagic
+ [; if (second==0 || second hasnt animate)
+ "That must be either vegetable or mineral.";
+ if (second==player) "You give yourself a mild headache.";
+ print_ret (The) second, " is rather shocked, for some reason.";
+ ];
+
+! ----------------------------------------------------------------------------
+! The first scene: the Hut and its (rather easy) secret
+! ----------------------------------------------------------------------------
+
+Class Place
+ has light;
+
+Place Hut "Ramshackle Hut"
+ with description
+ "Until quite recently, someone lived here, you feel sure.
+ Now the furniture is matchwood and
+ the windows are glassless. Outside, it is a warm, sunny day,
+ and grasslands extend to the low hills on the horizon.",
+ out_to Grasslands, w_to Grasslands,
+ cant_go "There's only the one room: better go ~out~.",
+ name "windows" "grasslands" "grass" "hills";
+
+Object -> furniture "wooden furniture"
+ with name "furniture" "broken" "wood" "wooden",
+ before
+ [; Examine, Search, LookUnder:
+ self.before=0; score=score+5;
+ move h_box to player;
+ "Searching through the furniture, which is good for nothing
+ but firewood now, you come across an old cedarwood box,
+ which you pick up for a closer look.";
+ ],
+ has scenery;
+
+Object h_box "cedarwood box"
+ with name "cedar" "cedarwood" "wooden" "box",
+ description "The box bears the calligraphed initial H."
+ has container openable lockable locked;
+
+SpellBook -> helistars_book "Helistar's grimoire"
+ with name "grimoire" "helistar" "helistars",
+ description "This must be the grimoire of dangerous spells kept by
+ your irresponsible friend Helistar. Many pages are
+ missing, but a few spells remain:^",
+ has proper;
+
+! ----------------------------------------------------------------------------
+! Grasslands and the valley
+! ----------------------------------------------------------------------------
+
+Place Grasslands "Grasslands, near Hut"
+ with name "grasslands" "grass" "hut" "path",
+ description
+ "The grasslands sway over low hills in all directions: it is a
+ peaceful wilderness, broken only by this hut and a faint path
+ to the north.",
+ in_to Hut, e_to Hut,
+ n_to Valley,
+ cant_go "You wander around for a while but end up back at the hut.";
+
+Place Valley "Pocket Valley"
+ with name "valley" "trail",
+ description
+ "A pleasant pocket valley in the grassy hills, through which a
+ trail runs north-to-south.",
+ n_to "The trail runs out to nothing, and you retreat for fear of
+ getting so lost you couldn't find the hut again by nightfall.",
+ cant_go "You wander around the pleasant valley, but are afraid to
+ lose sight of the trail.",
+ s_to Grasslands;
+
+[ RideSub; print_ret "You can hardly ride ", (a) noun, "."; ];
+
+Object -> horse "horse"
+ with short_name
+ [; if (self has general) print "winged horse";
+ else print "chestnut horse";
+ rtrue;
+ ],
+ parse_name
+ [ i j; if (self has general) j='winged'; else j=-1;
+ while (NextWord()==j or 'horse' or 'chestnut') i++;
+ return i;
+ ],
+ describe
+ [; print_ret
+ "There is ", (a) self, " here, munching on a pile of oats.";
+ ],
+ before
+ [; Cast: if (the_spell_was == bozbar_spell)
+ { give self general;
+ "A pair of handsome brown wings suddenly appears on
+ the horse's powerful shoulders. The horse turns in a
+ complete circle, a look of puzzlement on his face.";
+ }
+ if (the_spell_was == yomin_spell)
+ "He is mainly thinking about oats. Partly who you are
+ and what you're up to, but mainly oats.";
+ Enter: <>;
+ Ride: if (horse hasnt general)
+ "You ride around for a while, exercising the horse, but
+ soon enough he tires of this and pointedly brings you
+ back to the oats. Obligingly you dismount and he
+ begins grazing again.";
+
+ print "You begin to ride north. Then, slowly at first but with
+ increasing sureness, the horse begins beating its powerful
+ wings. You rise majestically through the air, sailing
+ gracefully across a chasm where the hills fall away.
+ The horse lands gently on the far side and deposits you,
+ taking to the skies again.^";
+ PlayerTo(Edge); rtrue;
+ ],
+ has animate;
+
+Object -> oats "pile of oats"
+ with name "oats" "pile" "of",
+ before
+ [; Examine, Search, LookUnder:
+ self.before=NULL;
+ move shiny_scroll to player; score=score+5;
+ itobj=shiny_scroll;
+ "Sifting through the oats, you find a shiny scroll! Lucky
+ you got to it before the horse did. As you turn it over
+ in your hands, it seems undamaged.";
+ Take: "What would you want with all those oats?";
+ ],
+ has scenery;
+
+Scroll shiny_scroll "shiny scroll"
+ with name "shiny";
+
+Spell -> bozbar_spell
+ with name "bozbar",
+ purpose "cause an animal to sprout wings",
+ magic
+ [; if (second==0 || second hasnt animate)
+ "The spell dies away in vain.";
+ if (second==player)
+ "Your elbows twitch, but there is no other effect.";
+ print_ret "For a moment, ", (the) second,
+ " looks highly discomforted, but the moment passes.";
+ ],
+ unmagic
+ [; if (second==0 || second hasnt animate)
+ "The spell dies away in vain.";
+ if (second==player) "What wings?";
+ if (second==horse && horse has general)
+ { give horse ~general;
+ "The Enchanter giveth, and the Enchanter taketh away.
+ The horse looks disconsolate but returns to the oats.";
+ }
+ print_ret (The) second, " has no wings to lose.";
+ ];
+
+! ----------------------------------------------------------------------------
+! The Chasm and the snake
+! ----------------------------------------------------------------------------
+
+Place Edge "Edge of Chasm"
+ with name "wide" "chasm" "road" "daffodils" "clump",
+ description
+ "The road ends suddenly at a wide chasm. The road leads upward
+ to the north, and you can see it continuing on the southern side
+ of the chasm.",
+ u_to Up_Road, n_to Up_Road,
+ cant_go "The chasm is too perilous to approach. The only safe way is
+ up and to the north.",
+ before
+ [; Jump: deadflag = true;
+ "You jump bravely into the chasm, and plunge...
+ gracefully through the air. (It gets a bit less noble and
+ airy after that.)";
+ ];
+
+Object -> snake "hissing snake"
+ with name "hissing" "snake",
+ initial
+ "Lying in a tight coil at the edge of the chasm is a hissing snake.",
+ description
+ "It has some V-markings, some scaly parts, colours from grey to
+ reddish-brown. Is that any help?",
+ life
+ [; "The snake hisses angrily!"; ],
+ before
+ [; Cast:
+ switch(the_spell_was)
+ { urbzig_spell:
+ remove self;
+ snakes_cube.initial =
+ "Beside a clump of daffodils is a featureless white cube.";
+ "The snake is replaced by a clump of daffodils.";
+ bozbar_spell:
+ deadflag = true; remove self;
+ snakes_cube.initial =
+ "A featureless cube rests where the snake took off from.";
+ "The snake is transformed into a huge, winged serpent,
+ a dragon which bellows and leaps out into the chasm,
+ backwinging furiously... and knocking you over the
+ edge quite by accident.";
+ yomin_spell:
+ "Horrid reptilian thoughts insinuate their way into you.";
+ }
+ Take, Remove:
+ "The slipperiness of its skin is only one of many reasons
+ why this is ill-advised.";
+ ],
+ has animate;
+
+FeaturelessCube -> snakes_cube "cube"
+ with initial
+ "The snake appears to be curled around a featureless white cube.",
+ before
+ [; if (snake notin nothing) "The snake won't let you near that cube!";
+ ];
+
+! ----------------------------------------------------------------------------
+! The crest of the hill; Icarus the tortoise; the chewed scroll
+! ----------------------------------------------------------------------------
+
+Place Up_Road "Crest of Hill"
+ with description
+ "The road crosses the top of a ridge here, sloping downwards to
+ the south and the northwest. A track diverges to east.",
+ nw_to Cave_Mouth, s_to Edge, d_to Edge, e_to Track;
+
+Object -> tortoise "tortoise"
+ with name "tortoise" "turtle",
+ initial "A tortoise ambles along the road, extremely slowly.",
+ life
+ [; "The tortoise (slowly) turns its neck to look at you (stupidly).";
+ ],
+ before
+ [; Cast: switch(the_spell_was)
+ { urbzig_spell:
+ "Just how safe do you want your surroundings to be?";
+ bozbar_spell:
+ move chewed_scroll to parent(self); remove self;
+ StartDaemon(self); score=score+5;
+ "The tortoise seems to be incapable of expressing
+ surprise, but is now soaring away high in the sky.
+ Something rather grubby is left behind.";
+ yomin_spell:
+ "For a moment you think there is nothing there, as you
+ chew absentmindedly on a leaf. But somewhere inside
+ the tortoise is a sense of wonder at the amazing blue
+ canopy of the sky.";
+ }
+ Take, Remove:
+ "Your parents always warned you not to pick up casual
+ acquaintances met on the road.";
+ ],
+ daemon
+ [ i; if (location ~= Up_Road or Track || random(6)~=1) rfalse;
+ if (random(4)==1 && self hasnt general)
+ { move feather to location; give self general;
+ "^A tortoise-feather flutters to the ground before you!";
+ }
+ i=random(3);
+ switch(i)
+ { 1: print "^High in the sky,";
+ 2: print "^Far above you,";
+ 3: print "^Tiny in the blue sky,";
+ }
+ " a tortoise flaps across the sun.";
+ ],
+ has animate;
+
+Scroll torn_scroll "torn scroll"
+ with name "torn";
+
+Spell -> lobal_spell
+ with name "lobal",
+ purpose "sharpen hearing",
+ magic
+ [; if (second==0 || second hasnt animate)
+ "There is a loud bang in your ear, but no other effect.";
+ if (second==player)
+ { if (hearing_good) "There is no further effect.";
+ hearing_good=1; StartTimer(self, 5);
+ "Nothing happens, possibly because those butterflies on the
+ other side of the hill keep distracting you.";
+ }
+ print_ret (The) second,
+ " is no doubt grateful for the gift of sharper hearing.";
+ ],
+ unmagic
+ [; if (second==0 || second hasnt animate)
+ "There is a brief silence, but no other effect.";
+ if (second==player) { StopTimer(self); hearing_good=0; "Pardon?"; }
+ print_ret (The) second,
+ " is no doubt grateful not to have to listen to you.";
+ ],
+ time_left 0,
+ time_out
+ [; if (hearing_good)
+ { hearing_good = false;
+ "^Those wretched butterflies finally shut up.";
+ }
+ ];
+
+Scroll chewed_scroll "chewed scroll"
+ with initial "It looks as if the tortoise was eating something - once
+ it might have been a scroll, but now it lies there,
+ chewed up like a lettuce leaf.",
+ before
+ [; Cast: if (the_spell_was == caskly_spell)
+ { move torn_scroll to parent(self);
+ remove self; score=score+5;
+ "Before your eyes, the scroll begins to repair itself,
+ failing only at the very last tear. Not quite perfect
+ perhaps, but certainly a readable, if torn scroll.";
+ }
+ Eat: "~Eating your words~ is notoriously dangerous for a wizard.
+ Rearranged in the stomach, a spell might do anything!";
+ ],
+ with name "chewed";
+
+Object feather "tortoise feather"
+ with name "tortoise" "feather",
+ description
+ "Possibly your rarest, and also least valuable, possession.";
+
+! ----------------------------------------------------------------------------
+! The cave mouth and the perfect sapphire
+! ----------------------------------------------------------------------------
+
+Place Cave_Mouth "Cave Mouth"
+ with name "gorse" "footpath" "cave" "mouth",
+ description
+ "This is a cave mouth, at one end of a road which winds southeast
+ over rising ground. The entrance west to the caves is a dark
+ tunnel, and only a footpath runs further north, into gorse.",
+ u_to Up_Road, se_to Up_Road, in_to Iron_Door, w_to Iron_Door,
+ n_to Footpath;
+
+Object -> Iron_Door "iron door"
+ with name "iron" "door" "heavy",
+ description "It just looks like an ordinary heavy iron door.",
+ door_dir
+ [; if (location==Cave_Mouth) return w_to; return e_to;
+ ],
+ door_to
+ [; if (location==Cave_Mouth) return In_Cave;
+ return Cave_Mouth;
+ ],
+ describe
+ [; if (self has open) "^The iron door stands open.";
+ if (self hasnt locked) "^The iron door is unlocked but shut.";
+ "A heavy iron door bars the cave mouth.";
+ ],
+ found_in In_Cave Cave_Mouth
+ has static door openable locked lockable;
+
+! Cf. T. S. Eliot, "Burnt Norton" II:
+! (but see also Mallarme's sonnet from which Eliot borrowed the image)
+
+Object -> sapphire "perfect sapphire"
+ with name "perfect" "sapphire" "gemstone" "gem",
+ initial "Clotted in the mud beside the door is a perfect sapphire.",
+ before
+ [; Examine: remove self; move caskly_spell to memory;
+ players_book.learn_spell(caskly_spell);
+ caskly_spell.number=100;
+ "As you gaze into the perfect blue of the sapphire,
+ you feel your mind begin to reel. Unable to bear
+ the naked sight of perfection, you look away, ashamed.
+ As you do so, the sapphire cracks and wastes away to
+ thin hot dust. But something remains, something in your
+ mind...";
+ ];
+
+Spell caskly_spell
+ with name "caskly",
+ purpose "cause perfection",
+ magic
+ [; if (second==0) "Trying to make everything perfect was a little
+ too ambitious.";
+ if (second==player) "Oh, don't be too hard on yourself.";
+ if (second==helistars_book)
+ "Your spell is not powerful enough to restore the lost pages.";
+ print_ret (The) second, " looks pretty perfect as is.";
+ ];
+
+! ----------------------------------------------------------------------------
+! Inside the Cave, the powerful urbzig spell and its consequences
+! ----------------------------------------------------------------------------
+
+Place In_Cave "Inside Cave"
+ with description
+ "A wide but shallow cave not far inside the hill. There is no
+ obvious exit, except for the way you came in.",
+ out_to
+ [; if (CoinsIn(left_pan)+CoinsIn(right_pan) < 6)
+ "Something bars your way, and you hear
+ the scales jangling militantly. You were trying to
+ steal its coins!";
+ if (scales.number~=0) "Something bars your way, and you hear
+ the scales jangle slightly with energy.";
+ return Iron_Door;
+ ],
+ e_to
+ [; return self.out_to();
+ ],
+ cant_go "The only way is back ~out~ through the iron door.",
+ after
+ [; Take: if (parent(noun)==left_pan or right_pan)
+ print_ret "Taken from ", (the) parent(noun), ".";
+ ],
+ has ~light;
+
+FeaturelessCube -> cave_cube "cube"
+ with initial "Balanced on a rock formation is a featureless white cube.";
+
+Object -> scales "pair of scales"
+ with name "pair" "of" "scales" "pans", number 0,
+ describe
+ [; print "^A fair-sized pair of scales hangs from a bracket in the
+ cave wall. ";
+ if (self.number==0) "The scales are balanced.";
+ if (self.number==1) "The left-hand side is higher.";
+ "The right-hand side is higher.";
+ ],
+ before
+ [; "There are left and right hand pans, which you should refer to
+ individually.";
+ ],
+ has static supporter;
+
+Class ScalePan
+ with name "pan" "side" "tray",
+ before
+ [; Receive:
+ if (noun ofclass Scroll or Coin) rfalse;
+ if (noun==feather) rfalse;
+ "The pans gleam with what almost seems greed, and somehow they
+ contrive to nudge your hand past them with your worthless and
+ boring item.";
+ ],
+ after
+ [ i j d w1 w2; Receive, LetGo: i=scales.number;
+ objectloop (j in left_pan) w1=w1 + WeightOf(j);
+ objectloop (j in right_pan) w2=w2 + WeightOf(j);
+ if (w1==w2) scales.number=0;
+ if (w1 > w2) scales.number=-1;
+ if (w1 < w2) scales.number=1;
+ j=scales.number; d=(w2-w1)*(scales.number);
+ if (j==i) rfalse;
+ if (j==0) "The scales come into balance.";
+ if (j==1) print "The left pan "; else print "The right pan ";
+ if (d==1) "very slowly rises up.";
+ "rises up.";
+ ],
+ has supporter scenery;
+
+[ WeightOf obj;
+ if (obj==bronze_coin) return 2;
+ if (obj ofclass Scroll || obj==feather) return 1;
+ return 3;
+];
+
+[ CoinsIn obj i c;
+ objectloop (i in obj) if (i ofclass Coin) c++;
+ return c;
+];
+
+ScalePan -> right_pan "right pan" with name "right";
+GoldCoin -> ->;
+GoldCoin -> ->;
+GoldCoin -> ->;
+
+ScalePan -> left_pan "left pan" with name "left";
+BronzeCoin -> -> bronze_coin;
+GoldCoin -> ->;
+GoldCoin -> ->;
+
+Scroll -> -> crumpled_scroll "crumpled scroll"
+ with name "crumpled";
+Spell -> -> -> urbzig_spell
+ with name "urbzig",
+ purpose "turn a dangerous object into a harmless one",
+ magic
+ [; if (second==0) "The spell fizzles away.";
+ if (second==player) "It's a matter of opinion, isn't it?";
+ if (second==helistars_book or mace || second ofclass FeaturelessCube)
+ { CDefArt(second); remove second;
+ if (second==mace && cyclops in location)
+ { remove cyclops; move eye_cube to location;
+ " turns into a featureless white cube just as the cyclops
+ was about to hit you with it. Mightily embarrassed
+ by this, he drops the cube and runs off!";
+ }
+ print " turns into a moth and flutters away.^";
+ rtrue;
+ }
+ print_ret "Nothing obvious happens. Perhaps ", (the) second,
+ " isn't so very dangerous after all.";
+ ],
+ unmagic
+ [; if (second==0) "The spell fizzles away.";
+ if (second==player) "It's a matter of opinion, isn't it?";
+ if (second has static || second has scenery)
+ { print_ret "Your spell is too weak for something quite as
+ monumentally harmless as ", (the) second, ".";
+ }
+ if (second==helistars_book or snake or cyclops or mace
+ || second ofclass FeaturelessCube)
+ "Nothing obvious happens.";
+ if (second in player)
+ { remove second; deadflag = true;
+ "Suddenly, a tarantula races up your arm to your throat!
+ Perhaps it was unwise to gizbru something you were
+ actually holding.";
+ }
+ if (cyclops has general)
+ "Nothing happens. Perhaps that's just as well,
+ after the last time.";
+ move cyclops to location;
+ remove second; give cyclops general; StartTimer(cyclops, 5);
+ print_ret (The) second, " is replaced by a buck-toothed cyclops
+ wielding a mace!";
+ ];
+
+Object cyclops "buck-toothed cyclops"
+ with name "buck" "toothed" "buck-toothed" "cyclops",
+ initial "A huge buck-toothed cyclops menaces you, armed with a
+ heavy mace!",
+ before
+ [; Cast: if (the_spell_was == bozbar_spell)
+ "Does the term ~death wish~ mean anything to you?";
+ if (the_spell_was == urbzig_spell)
+ "The cyclops bellows with glee as your spell has
+ no effect. (After all, he wouldn't be ~dangerous~ if
+ an urbzig spell worked on him, would he?)";
+ ],
+ life [; "He roars incoherently, swinging the mace!"; ],
+ time_left 0,
+ time_out
+ [; if (self notin location)
+ { remove self; rtrue;
+ }
+ deadflag = true; remove mace; remove cyclops;
+ "Feeling that he's given you quite long enough to explain why
+ you made such a mess of his life, he swings the great mace
+ maniacally down on you!";
+ ],
+ each_turn
+ [ i; i=random(4); if (i==1) "^The cyclops leaps and bellows!";
+ if (i==2)
+ "^Whirling the mace, the cyclops jabbers at you incoherently.";
+ if (i==3)
+ "^The cyclops is losing patience (the appropriate cyclops
+ word is untranslatable into English, but approximately means
+ ~forbearance in not smashing all nearby skulls~).";
+ "^The cyclops jabs you with the mace, almost breaking your rib.";
+ ],
+ has animate transparent;
+
+Object -> mace "mace"
+ with name "heavy" "mace" "axe",
+ description "It looks much too heavy for you to even lift.";
+
+FeaturelessCube -> eye_cube "cube"
+ with initial
+ "A featureless white cube lies where the cyclops dropped it.";
+
+! ----------------------------------------------------------------------------
+! The Footpath and the carpet
+! ----------------------------------------------------------------------------
+
+Place Footpath "Gorse Bushes"
+ with description
+ "The footpath from the cave mouth runs into dense, impenetrable
+ gorse bushes. Perhaps it wasn't so much a footpath as a rill
+ in the earth where roots wouldn't take; anyway, there's no way
+ but back south.",
+ s_to Cave_Mouth;
+
+Object -> carpet "beautiful red carpet"
+ with name "beautiful" "magic" "red" "carpet",
+ initial
+ "Slung over one of the gorse bushes is a beautiful red carpet.",
+ description
+ "This is a carpet of unusual design. It is red, beautifully woven
+ and bears a pattern of cubes.",
+ before
+ [ i; Receive:
+ if (self notin location || self hasnt moved)
+ "Not until the carpet's on the ground, you can't.";
+ Ride: <>;
+ Enter:
+ if (self notin location || self hasnt moved)
+ "Not until the carpet's on the ground, you can't.";
+ if (location==Balance_Room)
+ "Mysteriously, the carpet rucks and pulls until you're
+ thrown off. It settles back on the white floor with a
+ contented sigh.";
+ if (location==In_Cave)
+ "The carpet rises suddenly, crashing into the roof of
+ the cave and throwing you back off again. Painfully.";
+ if (location==Bazaar) i=Up_Road; else i=Bazaar;
+ print "The carpet rises suddenly into the fluffy white
+ clouds, and after a headlong journey deposits you...^";
+ move self to i;
+ PlayerTo(i,1); move player to self; <>;
+ Take: if (player in self) "Not while you're on it!";
+ for (i=child(self):i~=0:i=child(self))
+ { move i to location;
+ print "(Dislodging ", (the) i, ")^";
+ }
+ ],
+ has supporter enterable;
+
+! ----------------------------------------------------------------------------
+! A Bazaar Lottery
+! ----------------------------------------------------------------------------
+
+Global last_called = 1;
+Global explicit_flag = 0;
+Global tickets_taken = 0;
+
+Class Ticket(6)
+ with number -1, name "ticket",
+ description
+ [; if (self.number==2306) "It is labelled ~First Prize~!";
+ if (self.number==5802) "It is labelled ~Nineteenth Prize~.";
+ "~You lose,~ says the ticket, with a smily face. ~Try again!~";
+ ],
+ short_name
+ [; if (self.number==-1) rfalse;
+ print "lottery ticket ", self.number; rtrue;
+ ],
+ parse_name
+ [ i j w;
+ i=0;
+ if (NextWord()=='lottery') i++; else wn--;
+ if (NextWord()=='tickets')
+ { parser_action=##PluralFound; return i+1; } else wn--;
+ if (NextWord()~='ticket') return 0;
+ i++;
+ w=TryNumber(wn);
+ if (w==-1000) { explicit_flag = false; return i; }
+ if (w==0) return 0;
+ if (self.number==-1)
+ { objectloop(j ofclass Ticket)
+ if (w == j.number) return 0;
+ }
+ else
+ { if (self.number~=w) return 0;
+ }
+ i++; last_called = w; explicit_flag = true; return i;
+ ],
+ before
+ [; Examine:
+ if (self in board)
+ "It would be cheating to see what's written on the curled up
+ tickets still in the board.";
+ Cast: "~Get outta here, bub!~, the barker says, disgusted.";
+ ];
+
+Place Bazaar "Crowded Bazaar"
+ with description
+ "This is a crowded, noisy bazaar. Directly in front of you is
+ a lottery! But the contemptuous-looking barker is doing a
+ very poor trade: hardly anyone wants his first prize, the
+ big cuddly toy elephant, or even his nineteenth prize, a
+ featureless white cube.",
+ each_turn
+ [; switch(random(4))
+ { 1: "^~Roll up! Roll up! One silver piece for three goes!~";
+ 2: "^~Come on, then! Just a silver coin gets you three!~";
+ 3: "^~Think what you could win, all for one silver coin!~";
+ 4: "^~This could be your lucky day!~";
+ }
+ ],
+ before
+ [; Learn:
+ "~None of that!~ snaps the barker angrily, putting you off
+ your study habits. He mutters about ~Enchanter cheats~,
+ but under the circumstances you decide to let the insult
+ pass.";
+ ],
+ cant_go "Everywhere, the crowds of jabbering natives block your way
+ to all the good stalls. In fact, the only one you can get at is
+ this dismal lottery.";
+
+Object -> board "lottery board"
+ with credit 0,
+ name "board" "lottery" "holes",
+ description
+ "There are a hundred holes each way, making, um, let's see, yes,
+ ten thousand tickets in all. Still, there are nineteen prizes,
+ so your odds must be, oh, well, not too awful anyway.",
+ before
+ [ i; LetGo:
+ if (self.credit == 0)
+ "The barker stabs you in the chest with
+ his finger. ~That's a silver coin to you, bub!~";
+
+ if (explicit_flag)
+ { objectloop (i ofclass Ticket)
+ if (last_called == i.number)
+ "That ticket's already taken.";
+ }
+ else
+ { .RandomChoice;
+ last_called = random(10000);
+ objectloop (i ofclass Ticket)
+ if (last_called == i.number)
+ jump RandomChoice;
+ }
+
+ tickets_taken++;
+ self.credit--;
+
+ i = Ticket.create();
+ if (i == 0)
+ "The barker looks metaphysically embarrassed. ~Um,
+ Inform's object creation system seems not to have worked.~";
+
+ i.number = last_called; itobj = i;
+
+ move i to player; give i moved proper;
+ if (explicit_flag==0)
+ print "Randomly picking from the ", 10001-tickets_taken,
+ " numbered holes with tickets in, you ";
+ else print "You ";
+ print_ret "take ", (the) i, " out of the board.";
+
+ Examine: ;
+ Receive:
+ if (noun ofclass Ticket)
+ "~No changes of mind, that's your ticket now! Give it to
+ me if you want to play it.~";
+ <>;
+ default:
+ "The barker is burly, and won't let you
+ tamper with the board.";
+ ],
+ initial
+ "Behind the barker is a huge drilled board, and inside each little
+ numbered hole is a rolled-up lottery ticket."
+ has static container open;
+
+Ticket -> -> ticket_in_board "rolled-up ticket from the board"
+ with article "a";
+
+Object -> barker "barker"
+ with name "barker" "burly" "man",
+ number 0,
+ description
+ "A boxer gone to seed who failed as a magician all down the
+ coast, that'd be your guess.",
+ life
+ [; Attack, Kiss: "No way. He must weigh twice what you do.";
+ Ask: switch(noun)
+ { 'prize', 'prizes':
+ "~Just one silver coin and a prize could be yours!~";
+ 'white', 'featureless', 'cube':
+ "He blows the dust off it. ~Genuine antique, that.~";
+ 'elephant', 'toy', 'cuddly':
+ "~Good quality merchandise,~ he says, in a way that
+ suggests he can only spell one of those three words.";
+ 'ticket', 'tickets', 'lottery':
+ "~Three tickets for one silver coin!~";
+ default: "~Just play the game, bub.~";
+ }
+ Order, Answer: "The barker glowers at you.";
+ Give: if (noun ofclass Ticket)
+ { remove noun;
+ if (noun.number==2306)
+ { move elephant to player; give elephant moved;
+ remove pelephant;
+ Bazaar.description =
+ "This is a crowded, noisy bazaar. Directly in front of you is
+ the lottery!";
+ "With very bad grace, the barker shoves the
+ cuddly toy elephant into your arms.";
+ }
+ if (noun.number==5802)
+ { move barker_cube to player; give barker_cube moved;
+ remove pcube;
+ Bazaar.description =
+ "This is a crowded, noisy bazaar. Directly in front of you is
+ the lottery!";
+ score=score+5;
+ "With concealed relief, the barker shoves the
+ featureless white cube into your hands.";
+ }
+ "~Bad luck! You lose!~";
+ }
+ if (self.number==2) "~You've had enough goes already!~ he
+ growls. No wonder trade is bad.";
+ if (~~(noun ofclass Coin))
+ "~What do you call that? One silver coin to play!~";
+ if ((noun.&name)-->0 == 'bronze')
+ "~Bronze! Not a chance, sunshine.~";
+ remove noun;
+ board.credit = board.credit + 3;
+ self.number++;
+ if ((noun.&name)-->0 == 'gold')
+ "Gleefully the barker snatches the gold coin. ~Sorry
+ bub, no change. Business is slack today!~";
+ "Grudgingly the barker takes the silver coin and stands
+ back to let you at the board, arms folded.";
+ ],
+ before
+ [; Cast: switch(the_spell_was)
+ { bozbar_spell:
+ "He's not that much of an animal.";
+ lobal_spell:
+ "His problem is listening, not hearing.";
+ caskly_spell:
+ "For a moment his hair seems to comb itself.
+ Irritated, he ruffles it again, and the spell dies
+ an ignominious death.";
+ yomin_spell:
+ if (elephant has moved || barker_cube has moved)
+ "The barker's mind is a heap of grumbles about lost
+ prizes and scrawny Enchanters.";
+ if (self hasnt general)
+ { give self general;
+ "~Hope that scrawny Enchanter doesn't pick 2306!~
+ thinks the barker (slowly).";
+ }
+ "~If that mark does win, hope it's only worthless
+ old 5802,~ ponders the barker.";
+ }
+ ],
+ has animate scenery;
+
+Object -> prizes "prizes"
+ with name "prize" "prizes",
+ before [; "~Hands off those prizes!~"; ],
+ has scenery;
+
+Object -> pelephant "prize elephant"
+ with name "prize" "elephant" "cuddly" "toy",
+ description "Pink, cuddly, toy, elephant. Says it all, really.",
+ before [; Examine: ; default: "~Hands off those prizes!~"; ],
+ has scenery;
+
+Object -> pcube "prize cube"
+ with name "prize" "featureless" "white" "cube",
+ description "Wouldn't you like to win it?",
+ before [; Examine: ; default: "~Hands off those prizes!~"; ],
+ has scenery;
+
+Object elephant "cuddly toy elephant"
+ with name "cuddly" "toy" "elephant",
+ description "Pink, cuddly, toy, elephant. Says it all, really.",
+ before
+ [; Cast: if (the_spell_was == bozbar_spell)
+ "Let me get this straight. You, the enchanter who
+ defeated Krill, the head of the Borphee Guild
+ himself... are attempting to grow wings on a pink
+ cuddly elephant?";
+ if (the_spell_was == yomin_spell) "Woolly.";
+ ];
+
+FeaturelessCube barker_cube "cube";
+
+! ----------------------------------------------------------------------------
+! The spells in Helistar's grimoire
+! ----------------------------------------------------------------------------
+
+Spell lleps_spell
+ with name "lleps",
+ purpose "reverse effect of memorised spell",
+ magic
+ [; if (second==0 || second notin memory)
+ "The spell backfires, painfully.";
+ if (second.number==100)
+ "You know that spell too well for your mind to be able
+ to accept the change.";
+ if (second has reversed) give second ~reversed;
+ else give second reversed;
+ if (second==lleps_spell)
+ { memory.forget_spell(second);
+ "Your mind wrenches as the two lleps spells
+ cancel each other out, leaving only a sensation
+ quite like a hangover.";
+ }
+ print_ret "Your mind wrenches as ", (the) second,
+ " reverses itself.";
+ ],
+ unmagic
+ [; return self.magic(); ! The reverse of "lleps" is "lleps"
+ ];
+
+Spell mortin_spell
+ with name "mortin",
+ purpose "cause immediate death of caster",
+ magic
+ [; deadflag = true;
+ "You really can't fault Helistar on this one. Death is
+ absolutely immediate, like a sudden blackout curtain...";
+ ],
+ unmagic
+ [; prepared_flag = true;
+ "Nothing quite happens... and yet you feel enormously more
+ confident as you go about this dangerous world.";
+ ];
+
+! ----------------------------------------------------------------------------
+! Death and the Boneyard
+! ----------------------------------------------------------------------------
+
+[ AfterLife;
+ if (~~prepared_flag) rfalse;
+
+ if (player in Balance_Room)
+ "^^Your foresight in preparing a resurrection was wasted. The
+ tangled magic of the Balance Room coiled around your puny
+ enchantment like a constricting serpent.";
+
+ prepared_flag = false; deadflag = false; hearing_good = false;
+
+ if (memory.capacity >= 2) memory.capacity--;
+
+ while (child(player)~=0) move child(player) to parent(player);
+ move players_book to player;
+
+ print "^^With great foresight you prepared yourself for resurrection...
+ Your mind feels a little weaker, but at least you're alive.^";
+ PlayerTo(Boneyard);
+];
+
+Place Boneyard "Boneyard"
+ with name "bones" "blades" "shoulder" "skulls",
+ description
+ "This is a room of bones. Shoulder blades make up the floor,
+ skulls the walls and leg-bones the door frames. The west exit
+ leads into darkness, but the doorway to the north opens onto a
+ seemingly normal scene.",
+ n_to
+ [; if (scales.number ~= 0) return In_Cave;
+ return Grasslands;
+ ],
+ w_to "Some magical force blocks your way, as though that doorway
+ led into adventures from your past which you cannot rejoin now.",
+ before
+ [; Examine, Search:
+ if (noun==w_obj) "You can make out nothing to the west.";
+ ];
+
+Scroll -> worthless_scroll "worthless scroll"
+ with initial "You are almost treading on a worthless scroll.",
+ name "worthless";
+
+Spell -> -> filfre_spell
+ with name "filfre",
+ purpose "produce gratuitous fireworks",
+ magic
+ [; if (self hasnt scored) { score++; give self scored; }
+ "A brief shower of gratuitous fireworks spells out:
+ ^^The masterly Enchanter trilogy was written by Marc Blank,
+ Dave Lebling and Steve Meretzky.";
+ ],
+ unmagic
+ [; "A lengthy shower of artistically justified fireworks spells out:
+ ^^The masterly Enchanter trilogy was written by Jane Austen,
+ Emily Bronte and Edgar Allen Poe.";
+ ];
+
+! ----------------------------------------------------------------------------
+! The Cubical Temple
+! ----------------------------------------------------------------------------
+
+Place Track "Track, outside Temple"
+ with description
+ "This is the end of a long track winding through desolate hills,
+ which runs back west up to the ridge.",
+ before
+ [; Listen:
+ if (~~hearing_good) "The chanting is too quiet to make out.";
+ "The endlessly repeating threnody of the monks tells of
+ the legend of one who will some day enlighten their order,
+ and so be taken up to a higher plane. He (or she,
+ presumably) is known as The Four-Cubed One.";
+ ],
+ w_to Up_Road, u_to Up_Road;
+
+Object -> Temple "cubical Temple"
+ with name "temple" "cubical" "cube" "enormous",
+ before
+ [ i j;
+ Enter: "The Temple is featureless and unbroken. Perhaps the top
+ is open, because the sound must come from somewhere...
+ but you wouldn't bet on it.";
+ Cast: switch(the_spell_was)
+ { rezrov_spell:
+ "The huge temple remains impassive at your relatively
+ puny enchantment.";
+ frotz_spell:
+ objectloop (i in player)
+ if (i ofclass FeaturelessCube) j++;
+ if (j==0)
+ "The temple shakes, but then is still again.";
+ if (j<4) "The temple shakes! White light plays
+ over your hands and possessions, but then all is
+ still again.";
+ print "The temple shakes and white light bathes you.
+ Smoothly it unfolds itself in a four-dimensional
+ way your senses can barely comprehend. All you
+ know is that when it is over,
+ you find yourself in...^";
+ hearing_good = false; score=score+5;
+ PlayerTo(Balance_Room); rtrue;
+ }
+ ],
+ describe
+ [; print "^You stand outside an enormous temple in the shape of a
+ perfect, featureless white cube, four hundred feet on a
+ side. From somewhere within you hear the ";
+ if (hearing_good) print "bellowing noise";
+ else print "tiny sound";
+ " of the monks chanting.";
+ ],
+ description
+ "It's much like every other gigantic temple in the shape of a
+ featureless white cube you've ever seen. No obvious way in.",
+ has static;
+
+! ----------------------------------------------------------------------------
+! Inside the Temple
+! ----------------------------------------------------------------------------
+
+Place Balance_Room "Balance Room"
+ with description
+ "This seems to be the inside of a featureless white cube, forty
+ feet on a side. The air is stale and there is no exit.";
+
+Object -> balance_meter "image of the scales"
+ with name "image" "scales" "of" "pair", article "the",
+ initial "The image of a pair of scales hangs high in the air. One
+ pan is much lower than the other.",
+ before
+ [; "It's only an image.";
+ ],
+ has static;
+
+Object -> dusty_podium "dusty podium"
+ with name "podium" "dusty" "cobwebs" "cobwebbed",
+ initial "Far below the scales, in the centre of the ~floor~, is a
+ predictably-shaped podium, but it is so dusty and
+ cobwebbed that you can't see what it once was.",
+ before
+ [; Cast: if (the_spell_was == caskly_spell)
+ "Nice try, but it is protected from enchantment.";
+ "However dusty it is, the podium is still protected from
+ casual enchantment.";
+ Rub: remove self; move balance_key to Balance_Room;
+ itobj = balance_key;
+ "No substitute for old-fashioned hard work, sometimes,
+ and after much patient (sneezy) scrubbing, the podium
+ appears in its true white glory. Set into it are four
+ sockets, arranged in a two by two square.";
+ ],
+ has static;
+
+Object balance_key "podium"
+ with name "podium" "pedestal" "platform" "cubical",
+ description "As predicted, it is cubical.",
+ initial "Far below the scales, in the centre of the ~floor~, is a
+ predictably-shaped podium. Set into it are four sockets,
+ arranged in a two by two square.",
+ has static supporter;
+
+Object -> sockets "two by two square"
+ with name "square" "two" "by" "two",
+ before
+ [ i; if (action~=##Examine || number_filled==0)
+ "You'll have to say which socket you mean.
+ (Let's call them ~top left~, ~bottom right~ and so on.)";
+ objectloop (i in self)
+ { print (The) i;
+ if (child(i)==0) print " is empty.^";
+ else { print " contains ", (a) child(i), ".^"; }
+ }
+ rtrue;
+ ],
+ has static;
+
+Class Socket
+ with name "socket", article "the",
+ before
+ [; Cast: "The sockets are proof against magic.";
+ Examine: print (The) self, ", cubical and slightly more
+ than four inches on a side, is decorated with ",
+ (string) self.description;
+ if (child(self) == nothing) ".";
+ print_ret ", and contains ", (a) child(self), ".";
+ Receive: if (~~(noun ofclass FeaturelessCube))
+ "The socket rejects that.";
+ if (child(self) ~= nothing)
+ "There is already a cube in that socket.";
+ ],
+ after
+ [; LetGo: number_filled--;
+ "With much struggle, you manage to pull the cube away.";
+ Receive: number_filled++;
+ if (number_filled==4)
+ { if (snakes_cube in bl_socket
+ && barker_cube in ul_socket
+ && cave_cube in br_socket
+ && eye_cube in ur_socket)
+ { deadflag=2; score=score+5;
+ "As you place the final cube into the sockets, you feel
+ imbued with celestial wisdom (more so than usually).
+ You find yourself growing to the height of the cube, so
+ that you pull the balances back level by hand, and then
+ you grow still further, out of the temple until it is but
+ a cube in your hand, and you are a giant towering over
+ the land.
+ ^^Then, of course, you wake up, glumly realising it's time
+ to go to your job at the new Borphee Laboratories and
+ all those Wheatstone bridge experiments. But at least
+ you can dream about the old days.";
+ }
+ "The sockets are all full now, but that doesn't mean
+ anything's happened.";
+ }
+ "The cube is a predictably perfect fit in the socket.";
+ ],
+ has static container open;
+
+Socket -> bl_socket "bottom left socket"
+ with name "bottom" "left" "serpent",
+ description "a serpent";
+
+Socket -> ul_socket "top left socket"
+ with name "top" "left" "bazaar",
+ description "a scene in a bazaar";
+
+Socket -> br_socket "bottom right socket"
+ with name "bottom" "right" "cave",
+ description "an engraving of a rocky cave";
+
+Socket -> ur_socket "top right socket"
+ with name "top" "right" "eye",
+ description "an eye";
+
+! ----------------------------------------------------------------------------
+! That's all of the object definitions: just a little code and grammar left
+! ----------------------------------------------------------------------------
+
+[ Initialise;
+
+ location = Hut;
+ move burin to player;
+ move players_coin to player;
+ move players_book to player;
+
+ thedark.description =
+ "It is pitch black. You are likely to be eaten by a grue.";
+ ! (In fact you are stone-cold certain not to be, but never mind.)
+
+ players_book.learn_spell(gnusto_spell);
+ players_book.learn_spell(frotz_spell);
+ players_book.learn_spell(yomin_spell);
+ players_book.learn_spell(rezrov_spell);
+
+ helistars_book.learn_spell(frotz_spell);
+ helistars_book.learn_spell(lleps_spell);
+ helistars_book.learn_spell(mortin_spell);
+
+ give gnusto_spell known_about;
+
+ "^^^^^[Welcome to a short story called ~Balances~, one of the example
+ games for the Inform design system. Some people may recognise the
+ setting, but others might like to type ~how do spells work~ -
+ the game responds to a few such questions.]
+ ^^You feel a little confused as to how you got here. Something
+ to do with Helistar! That's right, and how the world is so far
+ off balance nowadays, after the Great Change.^^";
+];
+
+[ PrintRank;
+ print ", earning you the rank of ";
+ if (score >= 50) "Scientist.";
+ if (score >= 40) "Spellbreaker.";
+ if (score >= 30) "Sorcerer.";
+ if (score >= 20) "Enchanter.";
+ if (score >= 10) "novice Enchanter.";
+ "lost dreamer.";
+];
+
+[ DiagnoseSub;
+ switch(memory.capacity)
+ { 5: "You feel fine, and your memory is unimpaired.";
+ 4: "You feel shaky after your brush with death, but your mental
+ faculties seem sound.";
+ 3: "For someone who has died twice, you're in reasonable shape.";
+ }
+ "How many times have you died now? Your memory isn't what it was.";
+];
+
+! ----------------------------------------------------------------------------
+! Grammar extensions needed by the spell-casting and cube-writing rules:
+! ----------------------------------------------------------------------------
+
+Include "Grammar";
+
+[ AnyWord; from_char=0; to_char=0; the_named_word=wn++; return burin; ];
+
+[ QuotedText i j f;
+ i = WordAddress(wn++); i=i-buffer;
+ if (buffer->i=='"')
+ { for (j=i+1:j<=(buffer->1)+1:j++)
+ if (buffer->j=='"') f=j;
+ if (f==0) return -1;
+ from_char = i+1; to_char=f-1;
+ if (from_char>to_char) return -1;
+ while (buffer+f > WordAddress(wn)) wn++; wn++;
+ return burin;
+ }
+ return -1;
+];
+
+Verb "write" "scribe"
+ * AnyWord "on" held -> WriteOn
+ * QuotedText "on" held -> WriteOn;
+Verb "copy" * scope=CopyableSpell "to" noun -> CopyTo;
+Verb "who" "what" "how"
+ * "do" scope=Topic -> Query
+ * "is" scope=Topic -> Query
+ * "was" scope=Topic -> Query;
+Verb "spells" "memory"
+ * -> Spells;
+Verb "learn" "memorise" "memorize"
+ * scope=ReadableSpell -> Learn;
+Extend "examine" first
+ * scope=ReadableSpell -> Examine;
+Verb "c,cast"
+ * -> CastOne
+ * noun -> CastOne;
+Verb "cast"
+ * scope=LearnedSpell -> Cast
+ * scope=LearnedSpell "at" noun -> Cast
+ * scope=LearnedSpell "on" noun -> Cast;
+Verb "diagnose" "health"
+ * -> Diagnose;
+
+! ----------------------------------------------------------------------------
+! And one for the game itself.
+! ----------------------------------------------------------------------------
+
+Verb "ride" "mount" "straddle"
+ * creature -> Ride
+ * noun -> Enter;
+Verb "flip" "toss" * is_coin -> TossCoin;
+! ----------------------------------------------------------------------------
diff --git a/presets/zmachine/hello.inf b/presets/zmachine/hello.inf
new file mode 100644
index 00000000..1ae6a8d8
--- /dev/null
+++ b/presets/zmachine/hello.inf
@@ -0,0 +1,5 @@
+
+[ Main;
+ print "Hello, World!^";
+];
+
diff --git a/presets/zmachine/house01.inf b/presets/zmachine/house01.inf
new file mode 100644
index 00000000..7c869cbf
--- /dev/null
+++ b/presets/zmachine/house01.inf
@@ -0,0 +1,213 @@
+! ------------------------------------------------------------------------------
+! Inform for New Writers
+!
+! The House - Version 1
+!
+! Last Modified: David Cornelson - 03-Jan-1998
+!
+! This work is freely offered to the Public Domain. - DAC 12-12-2015
+!
+! ------------------------------------------------------------------------------
+
+!
+! Q: What are these lines that begin with exclamation points?
+!
+! A: In an Inform program, you may want to place comments or notes before
+! portions of code so that when you make changes, you will remember what
+! you were thinking when you originally wrote the code. It's a great way
+! to "document" your program so that others can understand it as well.
+!
+! Any characters following an exclamation point is considered a comment.
+! The comment ends when you move to a new line.
+!
+
+!
+! The constant "Story" contains the name of your story, in this case,
+! "The House". The word "Constant" is an Inform statement that signifies that
+! a token (variable) will have a single, unchangable value within the program.
+! "Story" is the token name and "The House" is the value. Anytime you reference
+! "Story" in your program, it will have the value "The House".
+!
+! The double-quote is used to represent a "string". A string is a type of data that
+! contains letters and words. (As opposed to numbers). A string must begin with
+! a double-quote and end with a double-quote.
+!
+! The semi-colon tells Inform that this statement is complete. You need a
+! semi-colon to end all Inform statements.
+!
+Constant Story "The House";
+
+!
+! The constant "Headline" contains the initial banner at the beginning of your
+! game. In this Headline, there are three separate lines.
+!
+! The first line is "Inform for New Writers"
+! The second line is "The House - Version 1"
+! The third line is "By New Writer (1998) - Last Compiled: 03-Jan-1998"
+!
+! The carat "^" character is used to tell Inform that you want to move to a new
+! line. This is called the newline character. Each time the newline character is
+! placed into a string, the game will move to a new line.
+!
+! Here is another example:
+!
+! print "Once upon a time^there was a little bear^^that was all alone.^";
+!
+! This example will be printed on your screen as...
+!
+! Once upon a time
+! there was a little bear
+!
+! that was all alone.
+!
+! Each newline character caused a break in the text and started at the beginning
+! of a new line.
+!
+Constant Headline
+ "^Inform for New Writers^
+ The House - Version 1^
+ By New Writer (1998) - Last Compiled: 03-Jan-1998^";
+
+!
+! This constant tells Inform what the maximum score of your game will be.
+! Currently, we have it set to 100.
+!
+Constant MAX_SCORE 100;
+
+!
+! This constant is the last compile date and can be set by the Inform compiler.
+!
+Serial "980103";
+
+!
+! This constant is set by you and tells which release of your game you are
+! working on. It's a good idea to make backups of your program on a regular
+! basis. When you have completed your game, start incrementing the Release value
+! every time you fix bugs or make changes so that players know which release
+! works and which one doesn't.
+!
+Release 1;
+
+!
+! The Include statement allows Inform to open other files that are important to
+! your program. The following files, "Parser" and "VerbLib" are the foundation
+! of the Inform parser. DON'T REMOVE THESE LINES!!!
+!
+Include "Parser";
+Include "VerbLib";
+
+!-------------------------------------------------------------------------------
+! Initialise
+!
+! The following "function" is the first portion of code executed by Inform when
+! your game is played. You want to place a statement in this function that will
+! set the first location of the player. We will add more to this section in later
+! versions of "The House".
+!-------------------------------------------------------------------------------
+
+! FUNCTIONS: Portions of your code will will be in what are called "functions".
+! The syntax of a function is as follows:
+!
+! [ function_name argument argument;
+! ...your code...
+! ...your code...
+! ...your code...
+! ];
+!
+! Arguments are values passed when calling the function. More
+! information on functions is available in later versions of
+! "The House".
+!
+
+[ Initialise;
+
+!
+! Our first location is the Sidewalk. Inform has a variable that we can set that
+! just happens to be named "location".
+!
+! Sidewalk is a location, but in Inform it is an "Object". When we define the
+! object Sidewalk it will have a unique value associated with it. So, when we
+! set location equal to Sidewalk, the location variable now contains the object
+! value of Sidewalk.
+!
+location = Sidewalk;
+
+];
+
+!
+! The following function is called by Inform when the player types SCORE or when
+! the player ends the game. As you can see, each range of points has a different
+! string printed. You can modify this function to suit your own story. Remember,
+! the constant MAX_SCORE contains the value that is used by Inform to represent
+! "You have scored out of ", so you want both the Constant
+! and this function to be synchronized.
+!
+[ PrintRank;
+ print ", earning you the rank of ";
+ if (score >= 100) "the greatest.";
+ if (score >= 80) "above average.";
+ if (score >= 60) "average.";
+ if (score >= 40) "below average.";
+ if (score >= 20) "the barely living.";
+ "the living dead.";
+];
+
+! ----------------------------------------------------------------------------
+! Locations
+!
+! In this section we will define our locations. These are "Objects" to Inform
+! and contain the following elements.
+!
+! - object name
+! The object name represents the variable or handle of the object.
+! - short description
+! The short description is the description printed in bold before the
+! normal description.
+! - initial description
+! The initial description is printed only once when the location is first
+! entered by the player.
+! - normal description
+! The normal description is printed everytime the player enters the location.
+! - directional properties (tells which direction player can move) (optional)
+! These include n_to, ne_to, e_to, up_to, in_to, etc. and are followed by
+! another location object name.
+! - properties
+! Properties are functions that you can add to an object that help determine
+! events and actions.
+! - attributes
+! Attributes are True/False values that help you remember certain states of
+! an object or event, such as whether the lights are on or not. The positive
+! value is represented as "light" and the negative would be "~light". There
+! are standard attributes used by Inform and you can add your own as well.
+!
+! Actually, there's more than this, but we'll add the complicated stuff later!
+!
+! ----------------------------------------------------------------------------
+
+!
+! Define the object "Sidewalk"
+!
+! Object Name: Sidewalk
+! Short Description: "Sidewalk"
+! Initial Description: none
+! Normal Description: "You are standing on the sidewalk in front of a house."
+! Attributes: light
+!
+! The Sidewalk is the first location of our game and includes a description
+! and when we enter it, it will have light.
+!
+Object Sidewalk "Sidewalk"
+ with description
+ "You are standing on the sidewalk in front of a house.",
+ has light;
+
+! ----------------------------------------------------------------------------
+! Grammar
+!
+! The grammar section includes the file "Grammar" and will later include
+! extensions to the standard grammar library.
+!
+! ----------------------------------------------------------------------------
+
+Include "Grammar";
+
diff --git a/presets/zmachine/house02.inf b/presets/zmachine/house02.inf
new file mode 100644
index 00000000..da69871b
--- /dev/null
+++ b/presets/zmachine/house02.inf
@@ -0,0 +1,175 @@
+! ------------------------------------------------------------------------------
+! Inform for New Writers
+!
+! The House - Version 2
+!
+! Last Modified: David Cornelson - 04-Jan-1998
+!
+! This work is freely offered to the Public Domain. - DAC 12-12-2015
+!
+! ------------------------------------------------------------------------------
+
+Constant Story "The House";
+
+Constant Headline
+ "^Inform for New Writers^
+ The House - Version 2^
+ By New Writer (1998) - Last Compiled: 04-Jan-1998^";
+
+Constant MAX_SCORE 100;
+Serial "980104";
+
+Release 1;
+
+Include "Parser";
+Include "VerbLib";
+
+!-------------------------------------------------------------------------------
+! Initialise
+!
+!-------------------------------------------------------------------------------
+
+[ Initialise;
+
+ location = Sidewalk;
+
+];
+
+[ PrintRank;
+ print ", earning you the rank of ";
+ if (score >= 100) "the greatest.";
+ if (score >= 80) "above average.";
+ if (score >= 60) "average.";
+ if (score >= 40) "below average.";
+ if (score >= 20) "the barely living.";
+ "the living dead.";
+];
+
+! ----------------------------------------------------------------------------
+! Locations
+!
+! In this section we will define our locations. These are "Objects" to Inform
+! and contain the following elements.
+!
+! - object name
+! The object name represents the variable or handle of the object.
+! - short description
+! The short description is the description printed in bold before the
+! normal description.
+! - initial description
+! The initial description is printed only once when the location is first
+! entered by the player.
+! - normal description
+! The normal description is printed everytime the player enters the location.
+! - directional properties (tells which direction player can move) (optional)
+! These include n_to, ne_to, e_to, up_to, in_to, etc. and are followed by
+! another location object name.
+! - properties
+! Properties are functions that you can add to an object that help determine
+! events and actions.
+! - attributes
+! Attributes are True/False values that help you remember certain states of
+! an object or event, such as whether the lights are on or not. The positive
+! value is represented as "light" and the negative would be "~light". There
+! are standard attributes used by Inform and you can add your own as well.
+!
+! Actually, there's more than this, but we'll add the complicated stuff later!
+!
+! ----------------------------------------------------------------------------
+
+Object Sidewalk "Sidewalk"
+ with description
+ "You are standing on the sidewalk in front of a house to the west.",
+ w_to Front_Porch,
+ has light;
+
+!
+! VERSION 2 - Adding more locations to your Inform program
+!
+! We're going to take one small step in this version. Let's add a bunch of
+! locations so that the player can move around a little bit.
+!
+! Notice that in the Sidewalk Object definition we added a direction in the
+! description "to the west" and we added the directional property "w_to"
+! that leads to the "Front_Porch" location that we defined below.
+!
+! If you follow these examples you will see how locations are "connected"
+! or "mapped" together with the directional properties. Feel free to change
+! then around so that they connect in different ways.
+!
+! Q: In the "Front_Porch" definition, the description continues over two
+! lines. Is this okay?
+!
+! A: Inform allows you to extend statements over multiple lines as you
+! need. You may need to write code that extends over multiple lines
+! but mostly it will be descriptions as in "Front_Porch". You don't
+! need to add any extra characters to tell Inform that you've jumped
+! to the next line either...Inform will figure that out when it compiles.
+!
+
+Object Front_Porch "Front Porch"
+ with description
+ "This is the front porch of the house. There is an open door
+ leading inside to the west.",
+ e_to Sidewalk,
+ w_to Foyer,
+ in_to Foyer,
+ has light;
+
+Object Foyer "Foyer"
+ with description
+ "You are standing in the foyer of the house. It seems as though
+ you can go up a staircase, northwest, or back out the front
+ door to the east.",
+ out_to Front_Porch,
+ e_to Front_Porch,
+ nw_to Hallway,
+ u_to Upper_Hallway,
+ has light;
+
+Object Hallway "Hallway"
+ with description
+ "You are in the hallway on the first floor of the house. The
+ foyer is southeast and the kitchen is west of here.",
+ se_to Foyer,
+ w_to Kitchen,
+ has light;
+
+Object Kitchen "Kitchen"
+ with description
+ "This is the kitchen of the house. A hallway can be seen to the
+ east.",
+ e_to Hallway,
+ has light;
+
+Object Upper_Hallway "Upper Hallway"
+ with description
+ "This is the second floor hallway. Rooms can be seen north and
+ south and a staircase leads down.",
+ n_to North_Bedroom,
+ s_to South_Bedroom,
+ d_to Foyer,
+ has light;
+
+Object North_Bedroom "North Bedroom"
+ with description
+ "This is a bedroom on the north side of the house.",
+ s_to Upper_Hallway,
+ has light;
+
+Object South_Bedroom "South Bedroom"
+ with description
+ "This is a bedroom on the south side of the house.",
+ n_to Upper_Hallway,
+ has light;
+
+! ----------------------------------------------------------------------------
+! Grammar
+!
+! The grammar section includes the file "Grammar" and will later include
+! extensions to the standard grammar library.
+!
+! ----------------------------------------------------------------------------
+
+Include "Grammar";
+
diff --git a/presets/zmachine/house03.inf b/presets/zmachine/house03.inf
new file mode 100644
index 00000000..4b9aaf04
--- /dev/null
+++ b/presets/zmachine/house03.inf
@@ -0,0 +1,284 @@
+! ------------------------------------------------------------------------------
+! Inform for New Writers
+!
+! The House - Version 3
+!
+! Last Modified: David Cornelson - 22-Jan-1998
+!
+! This work is freely offered to the Public Domain. - DAC 12-12-2015
+!
+! ------------------------------------------------------------------------------
+
+Constant DEBUG;
+
+Constant Story "The House";
+
+Constant Headline
+ "^Inform for New Writers^
+ The House - Version 3^
+ By New Writer (1998) - Last Compiled: 22-Jan-1998^";
+
+Constant MAX_SCORE 100;
+Serial "980122";
+
+Release 2;
+
+Include "Parser";
+Include "VerbLib";
+
+!-------------------------------------------------------------------------------
+! Initialise
+!
+!-------------------------------------------------------------------------------
+
+[ Initialise;
+
+ location = Sidewalk;
+
+];
+
+[ PrintRank;
+ print ", earning you the rank of ";
+ if (score >= 100) "the greatest.";
+ if (score >= 80) "above average.";
+ if (score >= 60) "average.";
+ if (score >= 40) "below average.";
+ if (score >= 20) "the barely living.";
+ "the living dead.";
+];
+
+! ----------------------------------------------------------------------------
+! Locations
+!
+! In this section we will define our locations. These are "Objects" to Inform.
+!
+! ----------------------------------------------------------------------------
+
+Object Sidewalk "Sidewalk"
+ with description
+ "You are standing on the sidewalk in front of a house to the west.",
+ w_to Front_Porch,
+ has light;
+
+!
+! Notice we changed the w_to and in_to properties to reflect our new door.
+! We changed the description to reflect our new doors as well...
+!
+
+Object Front_Porch "Front Porch"
+ with description
+ "This is the front porch of the house. There are two doors
+ leading inside. The door on the left leads west and the
+ door on the right leads northwest.",
+ e_to Sidewalk,
+ w_to Left_Front_Door,
+ in_to Left_Front_Door,
+ nw_to Right_Front_Door,
+ has light;
+
+!
+! VERSION 3 - Adding a door
+!
+! Inform allows you to create special objects that represent doors. Doors
+! are simply objects with special "properties" and "attributes".
+!
+! A "property" is a function that can be listed in the "Object" statement.
+! For instance, "e_to" and "w_to" are properties.
+!
+! Properties that are used for doors are:
+!
+! - door_to Tells Inform where the door leads if 'entered'.
+!
+! - door_dir Tells Inform which direction the door faces.
+!
+! - when_open The description of the door when open.
+!
+! - when_closed The description of the door when closed.
+!
+! - found_in A list of locations where the door resides.
+!
+! - with_key Specify which object is needed to lock and unlock door.
+!
+! Attributes that are used for doors:
+!
+! - static OR Tells Inform that the door cannot be carried.
+! - scenery Tells Inform that the door cannot be carried
+! and also is not mentioned in normal location
+! descriptions.
+!
+! - door Mandatory...tells Inform this object is a door.
+!
+! - open Current state of door. To make the door start
+! 'closed', then give the object the attribute
+! ~open.
+!
+! - lockable Can be locked.
+!
+! - locked Starts out locked. Give it ~locked to start
+! it as unlocked.
+!
+! NOTE: A few of the properties and attributes above can be used with other
+! objects. The only ones specific to a door object are the 'door_to'
+! and 'door_dir' properties and the 'door' attribute.
+
+!
+! NOTE ABOUT THE TILDE CHARACTER:
+! In evaluations of variables, the tilde character, ~, signifies
+! 'not' or 'false value of'.
+! When you see ~=, this means "not equal to".
+! When you see ~attribute, this means "the false value of attribute".
+!
+! The tilde character, ~, has another use. Inside a string, if you
+! want to print a double-quote, you would use the tilde. For example:
+!
+! print "John said, ~Run spot run!~";
+!
+! ...would print...
+!
+! John said, "Run spot run!"
+!
+
+!
+! We have two front doors built into our house, one leading to the
+! foyer, and the other leading to the den.
+!
+! The left door is a one way door that has no lock. You can enter
+! the door to the west.
+!
+! The right door is a two-way door that is lockable. The key is
+! located in the north bedroom. You enter the door to the northwest.
+!
+! Q: What is the '->' used for?
+!
+! A: This symbol tells Inform that this object is located 'within' the most recent
+! location definition.
+!
+! If two arrows are used, then the object is within the most recent -> object.
+!
+! The 'Left_Front_Door' is a 'child' of the 'Front_Porch' and the
+! 'Front_Porch' is the 'parent' of 'Left_Front_Door'.
+
+Object -> Left_Front_Door "left front door"
+ with name "left" "front" "door",
+ description
+ "The left front door is made of brass.",
+ when_open "The left front door is open.",
+ when_closed "The left front door is closed.",
+ door_to Foyer,
+ door_dir w_to,
+ has static door openable;
+
+!
+! The two-way door has 'functions' for the door_to and door_dir properties
+! because you can start on the front porch or the den. The same is true for
+! the directions, you can either be going through the door northwest or
+! southeast.
+!
+! These are 'embedded functions'. They don't need a name or arguments so
+! you place a semi-colon immediately after the first bracket. The end of
+! the function is signified by the closing bracket. You separate embedded
+! functions the same way you separate other properties, with a comma.
+!
+! The 'if' statement within both of the embedded functions is used to
+! determine which location you are starting in for the two-way door.
+!
+! The determination is calculated by comparing the 'location' variable
+! (which Inform ALWAYS sets to the players current location) and the
+! Front_Porch. If this is true, the first statement (until the semi-colon)
+! is executed. If it's false (the player is NOT in the Front_Porch) then
+! the second statement is executed.
+!
+! Notice the 'found_in' property lists both the Front_Porch and Den. This
+! is so you can 'see' the doors in both of these locations.
+!
+
+Object Right_Front_Door "right front door"
+ with name "right" "front" "door",
+ description
+ "The right front door is made of wood.",
+ when_open "The right front door is open.",
+ when_closed "The right front door is closed.",
+ door_to [; if (location==Front_Porch) return Den; return Front_Porch; ],
+ door_dir [; if (location==Front_Porch) return nw_to; return se_to; ],
+ found_in Front_Porch Den,
+ with_key right_key,
+ has static door openable lockable locked;
+
+Object Den "Den"
+ with description
+ "You are in the den of the house.",
+ se_to Right_Front_Door,
+ out_to Right_Front_Door,
+ has light;
+
+Object Foyer "Foyer"
+ with description
+ "You are standing in the foyer of the house. It seems as though
+ you can go up a staircase, northwest, or back out the front
+ door to the east.",
+ out_to Front_Porch,
+ e_to Front_Porch,
+ nw_to Hallway,
+ u_to Upper_Hallway,
+ has light;
+
+Object Hallway "Hallway"
+ with description
+ "You are in the hallway on the first floor of the house. The
+ foyer is southeast and the kitchen is west of here.",
+ se_to Foyer,
+ w_to Kitchen,
+ has light;
+
+Object Kitchen "Kitchen"
+ with description
+ "This is the kitchen of the house. A hallway can be seen to the
+ east.",
+ e_to Hallway,
+ has light;
+
+Object Upper_Hallway "Upper Hallway"
+ with description
+ "This is the second floor hallway. Rooms can be seen north and
+ south and a staircase leads down.",
+ n_to North_Bedroom,
+ s_to South_Bedroom,
+ d_to Foyer,
+ has light;
+
+Object North_Bedroom "North Bedroom"
+ with description
+ "This is a bedroom on the north side of the house.",
+ s_to Upper_Hallway,
+ has light;
+
+!
+! This is the 'key' for the right front door. There are no directions
+! or attributes since it's a just a simple object.
+!
+! I placed the key here to keep these examples building a workable game.
+! You can move the key anywhere you like though by cutting this line and
+! pasting it 'below' any other location object.
+!
+! Remember, this is the object listed in 'with_key' in the right_door
+! object, so it's the only way to unlock that door.
+!
+
+Object -> right_key "right key" with name "right" "key";
+
+Object South_Bedroom "South Bedroom"
+ with description
+ "This is a bedroom on the south side of the house.",
+ n_to Upper_Hallway,
+ has light;
+
+! ----------------------------------------------------------------------------
+! Grammar
+!
+! The grammar section includes the file "Grammar" and will later include
+! extensions to the standard grammar library.
+!
+! ----------------------------------------------------------------------------
+
+Include "Grammar";
+
diff --git a/presets/zmachine/house04.inf b/presets/zmachine/house04.inf
new file mode 100644
index 00000000..dd0f0063
--- /dev/null
+++ b/presets/zmachine/house04.inf
@@ -0,0 +1,422 @@
+! ------------------------------------------------------------------------------
+! Inform for New Writers
+!
+! The House - Version 4
+!
+! Last Modified: David Cornelson - 22-Jan-1998
+!
+! This work is freely offered to the Public Domain. - DAC 12-12-2015
+!
+! ------------------------------------------------------------------------------
+
+Constant DEBUG;
+
+Constant Story "The House";
+
+Constant Headline
+ "^Inform for New Writers^
+ The House - Version 4^
+ By New Writer (1998) - Last Compiled: 22-Jan-1998^";
+
+Constant MAX_SCORE 100;
+Serial "980122";
+
+Release 2;
+
+Include "Parser";
+Include "VerbLib";
+
+!-------------------------------------------------------------------------------
+! Initialise
+!
+!-------------------------------------------------------------------------------
+
+[ Initialise;
+
+ location = Sidewalk;
+
+];
+
+[ PrintRank;
+ print ", earning you the rank of ";
+ if (score >= 100) "the greatest.";
+ if (score >= 80) "above average.";
+ if (score >= 60) "average.";
+ if (score >= 40) "below average.";
+ if (score >= 20) "the barely living.";
+ "the living dead.";
+];
+
+! ----------------------------------------------------------------------------
+! Locations
+!
+! In this section we will define our locations. These are "Objects" to Inform.
+!
+! ----------------------------------------------------------------------------
+
+Object Sidewalk "Sidewalk"
+ with description
+ "You are standing on the sidewalk in front of a house to the west.",
+ w_to Front_Porch,
+ has light;
+
+Object Front_Porch "Front Porch"
+ with description
+ "This is the front porch of the house. There are two doors
+ leading inside. The door on the left leads west and the
+ door on the right leads northwest.",
+ e_to Sidewalk,
+ w_to Left_Front_Door,
+ in_to Left_Front_Door,
+ nw_to Right_Front_Door,
+ has light;
+
+Object -> Left_Front_Door "left front door"
+ with name "left" "front" "door",
+ description
+ "The left front door is made of brass.",
+ when_open "The left front door is open.",
+ when_closed "The left front door is closed.",
+ door_to Foyer,
+ door_dir w_to,
+ has static door openable;
+
+Object Right_Front_Door "right front door"
+ with name "right" "front" "door",
+ description
+ "The right front door is made of wood.",
+ when_open "The right front door is open.",
+ when_closed "The right front door is closed.",
+ door_to [; if (location==Front_Porch) return Den; return Front_Porch; ],
+ door_dir [; if (location==Front_Porch) return nw_to; return se_to; ],
+ found_in Front_Porch Den,
+ with_key right_key,
+ has static door openable lockable locked;
+
+!
+! VERSION 4 - Cause and Effect. Things happen based on what a player does.
+!
+! In this version of The House, we're going to add an object, the rock, and
+! a place where the rock is useful. Unlike version 3 where Inform provides
+! a special 'door' object, we must provide our own logic to 'handle' the rock.
+!
+! To do this, we're going to use what are called 'code blocks'. A code block is a
+! group of statements that combine to handle one particular piece of logic
+!
+! Code blocks contain a decision and/or a loop. A decision is handled by one of two
+! Inform statements, the 'if' statement and the 'switch' statement. We'll talk about
+! the 'switch' statement and 'loops' in later versions of The House.
+!
+! DECISION STATEMENTS
+!
+! THE 'if' STATEMENT
+!
+! The 'if' statement contains a comparison of variables, numbers, and/or text that
+! provides a true or false result. Based on either result (true or false) another
+! code block is written to handle the decision.
+!
+! For example:
+!
+! if (1==1) {
+! print "True";
+! } else {
+! print "False";
+! }
+!
+! In the above example, the word "True" will be printed because the comparison of
+! 1 to 1 is a true statement, 1 certainly does equal 1. If we changed the comparison
+! to:
+!
+! if (1==2) {
+! print "True";
+! } else {
+! print "False";
+! }
+!
+! ...then "False" would be printed because 1 does not equal 2.
+!
+! Here are some more examples of valid 'if' statements...
+!
+! eggs=2;
+! if (eggs<2) {
+! print "You don't have enough eggs!";
+! } else {
+! print "You have enough eggs!";
+! }
+!
+! The above 'if' statement asks if the variable 'eggs' is less than two. If the value
+! is less than two, print "You don't have enough eggs!", otherwise Inform will print
+! "You have two eggs, just enough!" (which is the case since we set the variable 'eggs'
+! to 2 before the 'if' statement).
+!
+! eggs=2;
+! bacon=4;
+! if (eggs<2) {
+! print "You don't have enough eggs!";
+! if (bacon<4) {
+! print "You don't have enough bacon either!";
+! } else {
+! print "You have four strips of bacon though!";
+! }
+! } else {
+! print "You enough eggs!";
+! if (bacon<4) {
+! print "You don't have enough bacon though!";
+! } else {
+! print "You have four strips of bacon too!";
+! }
+! }
+!
+! In the above example, things get more complicated. I'll rewrite it in english so
+! that you can understand what is happening. Many programmers start out writing
+! things in english and they call it 'pseudocode'.
+!
+! set eggs to 2
+! set bacon to 4
+!
+! if there are less than two eggs then
+! print "You don't have enough eggs!"
+! if there are less than four bacon then
+! print "You don't have enough bacon either!"
+! else
+! print "You have four strips of bacon though!"
+! end if
+! else
+! print "You enough eggs!"
+! if there are less than four bacon then
+! print "You don't have enough bacon though!"
+! else
+! print "You have four strips of bacon too!"
+! end if
+! end if
+!
+! Questions: Q: Why is there a double equal sign in the 'if' statement?
+!
+! A: Inform will set variables with one equals sign "=" and compare them
+! when you put two equals signs "==" together. This is important to
+! remember and can cause a lot of 'bugs' in your code. Another exanple
+! explaining this is:
+!
+! if (eggs=2) print "There are two eggs.";
+!
+! This statement will ALWAYS BE TRUE because eggs is being SET to 2, NOT
+! compared.
+!
+! Q: What are the squiggly brackets, '{' and '}', for?
+!
+! A: They signify the beginning and end of an 'if' statement code block.
+! You need them to group more than one statement together. The left
+! squiggly bracket begin the code block and the right squiggly bracket
+! ends the code block.
+!
+! NOTE: You only need the brackets if you have more than one statement
+! in the resulting code block. Another example might be:
+!
+! if (eggs==2) {
+! print "There are a pair of eggs.";
+! bacon=4;
+! }
+! else
+! print "There are ", eggs, " eggs.";
+!
+! In the above example, squiggly brackets were only needed for
+! the 'true' code block because we have two statements where
+! there is only one statement for the 'false' code block.
+!
+! Q: What are the symbols for 'if' statement comparisons?
+!
+! A: They are as follows: ~= not equal
+! == equal
+! < less than
+! <= less than or equal
+! > greater than
+! >= greater than or equal
+! && and
+! || or
+!
+! The '&&' and '||' symbols are used to combine comparisons. For example:
+!
+! if (eggs==2 && bacon==4) print "You have two eggs and four bacon!";
+!
+! if (eggs==2 || bacon==4) print "You have either 2 eggs or 4 bacon!";
+!
+
+!
+! Okay, now let's apply our knowledge of the 'if' statement and write an embedded function
+! that will handle our rock.
+!
+! We've placed the rock in the den, but we're going to put the action in the backyard
+! which is a location we're adding in this version of The House. Skip down by the kitchen for
+! more...
+!
+
+
+Object Den "Den"
+ with description
+ "You are in the den of the house.",
+ se_to Right_Front_Door,
+ out_to Right_Front_Door,
+ has light;
+
+!
+! This is our rock object.
+!
+! We've added the property 'before' with the arguments 'PutOn','Insert', and
+! 'ThrowAt:'. When the rock is thrown at or in anything, this function is executed.
+!
+! In this case, the object being thrown, rock or keys, is the value of the Inform
+! variable 'noun'. If noun equals the object 'Rock', then the true code block is
+! executed, otherwise the false code block is executed.
+!
+! Q: Why is the statement 'rtrue' placed at the end of both code blocks?
+!
+! A: Normally, the Inform parser handles the action of an object being thrown at
+! something else. This is the default processing. If you throw the 'right key'
+! around The House or at the pond, you'll see the 'default' Inform processing.
+!
+! Since we wanted special processing for the rock, we handled the actions on
+! our own through our code. But at the end of handling the thrown rock, we have
+! to let the Inform parser know that we took care of everything and not to do
+! anything.
+!
+! If we return true, Inform understands and leaves everything alone.
+! If we return false, Inform will execute the default processing.
+!
+! By the way, rtrue and rfalse are shortcuts to the statements:
+!
+! return true;
+! return false;
+!
+!
+! Q: Why is the variable 'second' being compared to the object name 'Pond'?
+!
+! A: The variable 'second' is an Inform variable set to the second noun of
+! of a players statement. For example:
+!
+! > THROW ROCK AT POND
+!
+! In this statement, 'rock' is the first noun and Inform determines the object
+! value for 'rock' and sets the variable 'noun' to that value. For the noun
+! 'pond', Inform determines the object value and sets this in the variable
+! 'second'.
+!
+! Q: Why is '(the)' before 'second' in the print statement below?
+!
+! A: This is to force Inform to print the article 'the' before the word. In any
+! object, you can define the article property with a value, such as "the",
+! "your", "an", or "some", so that Inform understands how to refer to the
+! object in sentences.
+!
+
+Object -> Rock "rock"
+ with name "rock",
+ description
+ "It's smooth and flat, perfect for skipping in a pond.",
+ before [; Insert,PutOn,ThrowAt:
+ if (second==Pond) {
+ print "The rock skips across the water several times and sinks.
+ Amazingly, after a few moments, the rock washes up at
+ your feet. Wow, what an undertow!^";
+ move Rock to Backyard;
+ rtrue;
+ !
+ ! Replace rock so that player can try it again....
+ !
+ } else {
+ print "You throw the rock at ",(the) second, " and bounces
+ back into your stomach. Ouch! That hurt.^";
+ rtrue;
+ }
+ ];
+
+Object Foyer "Foyer"
+ with description
+ "You are standing in the foyer of the house. It seems as though
+ you can go up a staircase, northwest, or back out the front
+ door to the east.",
+ out_to Front_Porch,
+ e_to Front_Porch,
+ nw_to Hallway,
+ u_to Upper_Hallway,
+ has light;
+
+Object Hallway "Hallway"
+ with description
+ "You are in the hallway on the first floor of the house. The
+ foyer is southeast and the kitchen is west of here.",
+ se_to Foyer,
+ w_to Kitchen,
+ has light;
+
+!
+! We've added out_to and w_to for a connection to the backyard as well as
+! changing the description to help the player know what's going on.
+!
+
+Object Kitchen "Kitchen"
+ with description
+ "This is the kitchen of the house. A hallway can be seen to the
+ east and an open doorway to the west leads out to the backyard.",
+ e_to Hallway,
+ w_to Backyard,
+ out_to Backyard,
+ has light;
+
+!
+! This is our new location. Notice we added the name "yard" in case the player
+! abbreviates their commands.
+!
+Object Backyard "Backyard"
+ with name "yard",
+ description
+ "This is the backyard behind the house. There is a pond here.",
+ e_to Kitchen,
+ in_to Kitchen,
+ has light;
+
+!
+! This is where we plan to use the rock....
+!
+
+Object -> Pond "pond"
+ with name "pond" "water",
+ description
+ "It's a small pond, but wide enough to skip rocks.",
+ has static concealed container open;
+
+Object Upper_Hallway "Upper Hallway"
+ with description
+ "This is the second floor hallway. Rooms can be seen north and
+ south and a staircase leads down.",
+ n_to North_Bedroom,
+ s_to South_Bedroom,
+ d_to Foyer,
+ has light;
+
+Object North_Bedroom "North Bedroom"
+ with description
+ "This is a bedroom on the north side of the house.",
+ s_to Upper_Hallway,
+ has light;
+
+!
+! Added the article "the"...
+!
+Object -> right_key "right key" with name "right" "key", article "the";
+
+Object South_Bedroom "South Bedroom"
+ with description
+ "This is a bedroom on the south side of the house.",
+ n_to Upper_Hallway,
+ has light;
+
+! ----------------------------------------------------------------------------
+! Grammar
+!
+! The grammar section includes the file "Grammar" and will later include
+! extensions to the standard grammar library.
+!
+! ----------------------------------------------------------------------------
+
+Include "Grammar";
+
diff --git a/presets/zmachine/house05.inf b/presets/zmachine/house05.inf
new file mode 100644
index 00000000..6c86b03a
--- /dev/null
+++ b/presets/zmachine/house05.inf
@@ -0,0 +1,333 @@
+! ------------------------------------------------------------------------------
+! Inform for New Writers
+!
+! The House - Version 5
+!
+! Last Modified: David Cornelson - 22-Jan-1998
+!
+! This work is freely offered to the Public Domain. - DAC 12-12-2015
+!
+! ------------------------------------------------------------------------------
+
+Constant Story "The House";
+
+Constant Headline
+ "^Inform for New Writers^
+ The House - Version 5^
+ By New Writer (1998) - Last Compiled: 22-Jan-1998^";
+
+Constant MAX_SCORE 100;
+Serial "980122";
+
+Release 2;
+
+Include "Parser";
+Include "VerbLib";
+
+!-------------------------------------------------------------------------------
+! Initialise
+!
+!-------------------------------------------------------------------------------
+
+[ Initialise;
+
+ location = Sidewalk;
+
+];
+
+[ PrintRank;
+ print ", earning you the rank of ";
+ if (score >= 100) "the greatest.";
+ if (score >= 80) "above average.";
+ if (score >= 60) "average.";
+ if (score >= 40) "below average.";
+ if (score >= 20) "the barely living.";
+ "the living dead.";
+];
+
+! ----------------------------------------------------------------------------
+! Locations
+!
+! In this section we will define our locations. These are "Objects" to Inform.
+!
+! ----------------------------------------------------------------------------
+
+!
+! VERSION 5 - Adding a container to your game, functions, verbs, and death.
+!
+! In many cases you will want an object to be able to contain other objects.
+! This may be as simple as creating a 'backpack' that will contain your school
+! papers, apple, and pencil sharpener. In a more complex definition, a container
+! could be a chasm, a bottomless pit, refrigerator, or a television.
+!
+! We're going to create a simple container and a complex container.
+!
+! The simple container is probably very familiar to you. It's a mailbox amd it's
+! right here in front of the house. It contains a letter that can be read as well.
+!
+
+Object Sidewalk "Sidewalk"
+ with description
+ "You are standing on the sidewalk in front of a house to the west.",
+ w_to Front_Porch,
+ has light;
+
+!
+! Add the mailbox with open and closed descriptions.
+!
+Object -> Mailbox "mailbox"
+ with name "mailbox" "box",
+ when_open "There is an open mailbox here.",
+ when_closed "There is a closed mailbox here.",
+ has static container openable;
+
+!
+! Add 'legible' attribute to distinguish something that can be 'read'.
+! This is determined in the verb extension located in the grammar
+! section at the end of this file.
+!
+Attribute legible;
+
+!
+! And here is the letter, which can be consulted, read, or torn up. If it's
+! torn up, the letter is removed from the game, never to be seen again.
+!
+Object -> -> Letter "letter"
+ with name "letter" "paper",
+ description
+ "The letter is a simple page of notebook paper.",
+ before [; Consult,Read: "The letter contains a vague story about an evil couch,
+ but you can't make out anymore detail. Interesting
+ little tidbit though.";
+ Tear: remove Letter;
+ "You rip the letter into tiny pieces that blow away in the wind.";
+ ]
+ has legible;
+
+Object Front_Porch "Front Porch"
+ with description
+ "This is the front porch of the house. There are two doors
+ leading inside. The door on the left leads west and the
+ door on the right leads northwest.",
+ e_to Sidewalk,
+ w_to Left_Front_Door,
+ in_to Left_Front_Door,
+ nw_to Right_Front_Door,
+ has light;
+
+Object -> Left_Front_Door "left front door"
+ with name "left" "front" "door",
+ description
+ "The left front door is made of brass.",
+ when_open "The left front door is open.",
+ when_closed "The left front door is closed.",
+ door_to Foyer,
+ door_dir w_to,
+ has static door openable;
+
+Object Right_Front_Door "right front door"
+ with name "right" "front" "door",
+ description
+ "The right front door is made of wood.",
+ when_open "The right front door is open.",
+ when_closed "The right front door is closed.",
+ door_to [; if (location==Front_Porch) return Den; return Front_Porch; ],
+ door_dir [; if (location==Front_Porch) return nw_to; return se_to; ],
+ found_in Front_Porch Den,
+ with_key right_key,
+ has static door openable lockable locked;
+
+Object Den "Den"
+ with description
+ "You are in the den of the house. The living room is west of hear
+ and the front porch is to the southeast.",
+ se_to Right_Front_Door,
+ out_to Right_Front_Door,
+ w_to Living_Room,
+ has light;
+
+Object -> Rock "rock"
+ with name "rock",
+ description
+ "It's smooth and flat, perfect for skipping in a pond.",
+ before [; Insert,PutOn,ThrowAt:
+ if (second==Evil_Couch) rfalse; ! Allow the rock to be eaten by couch
+ if (second==Pond) {
+ print "The rock skips across the water several times and sinks.
+ Amazingly, after a few moments, the rock washes up at
+ your feet. Wow, what an undertow!^";
+ move Rock to Backyard;
+ rtrue;
+ !
+ ! Replace rock so that player can try it again....
+ !
+ } else {
+ print "You can't throw the rock at ",(the) second, ".^";
+ rtrue;
+ }
+ ];
+
+Object Living_Room "Living Room"
+ with name "living" "room",
+ description
+ "This is the living room of the house. The den is to the east.",
+ e_to Den,
+ has light;
+
+!
+! And here is our evil couch. Anything put on or in the couch will be
+! 'eaten', including you. In fact, by setting the 'deadflag' to 1,
+! Inform is informed to 'end' the game because you have died.
+!
+! Notice we used the 'before' property and the 'Enter' and 'Receive'
+! verbs to handle the action.
+!
+Object -> Evil_Couch "couch"
+ with name "couch" "sofa",
+ when_open "There is a filthy, worn down couch here.",
+ before [; Enter: deadflag=1;
+ "You are eaten by the couch.";
+ Receive: remove noun;
+ "The couch eats ", (the) noun, " and belches.";
+ ],
+ has static container open enterable;
+
+Object Foyer "Foyer"
+ with description
+ "You are standing in the foyer of the house. It seems as though
+ you can go up a staircase, northwest, or back out the front
+ door to the east.",
+ out_to Front_Porch,
+ e_to Front_Porch,
+ nw_to Hallway,
+ u_to Upper_Hallway,
+ has light;
+
+Object Hallway "Hallway"
+ with description
+ "You are in the hallway on the first floor of the house. The
+ foyer is southeast and the kitchen is west of here.",
+ se_to Foyer,
+ w_to Kitchen,
+ has light;
+
+Object Kitchen "Kitchen"
+ with description
+ "This is the kitchen of the house. A hallway can be seen to the
+ east and an open doorway to the west leads out to the backyard.",
+ e_to Hallway,
+ w_to Backyard,
+ out_to Backyard,
+ has light;
+
+Object Backyard "Backyard"
+ with name "yard",
+ description
+ "This is the backyard behind the house. There is a pond here.",
+ e_to Kitchen,
+ in_to Kitchen,
+ has light;
+
+Object -> Pond "pond"
+ with name "pond" "water",
+ description
+ "It's a small pond, but wide enough to skip rocks.",
+ has static concealed container open;
+
+Object Upper_Hallway "Upper Hallway"
+ with description
+ "This is the second floor hallway. Rooms can be seen north and
+ south and a staircase leads down.",
+ n_to North_Bedroom,
+ s_to South_Bedroom,
+ d_to Foyer,
+ has light;
+
+Object North_Bedroom "North Bedroom"
+ with description
+ "This is a bedroom on the north side of the house.",
+ s_to Upper_Hallway,
+ has light;
+
+Object -> right_key "right key" with name "right" "key", article "the";
+
+Object South_Bedroom "South Bedroom"
+ with description
+ "This is a bedroom on the south side of the house.",
+ n_to Upper_Hallway,
+ has light;
+
+! ----------------------------------------------------------------------------
+!
+! Functions
+!
+! ----------------------------------------------------------------------------
+
+!
+! Added function ReadSub so that the property 'before' can use it. The default,
+! if there is no 'before read', is to examine the object.
+!
+[ ReadSub; <>; ];
+
+[ TearSub; "You can't tear that"; ];
+
+! ----------------------------------------------------------------------------
+! Grammar
+!
+! The grammar section includes the file "Grammar" and will later include
+! extensions to the standard grammar library.
+!
+! ----------------------------------------------------------------------------
+
+Include "Grammar";
+
+!
+! We also have to extend the read grammar to call ReadSub
+! by default.
+!
+! We're using the 'Extend' statment because the word "read" is already defined
+! in the grammar file included above. This adds our usage.
+!
+! The 'first' tag is used to indicate to Inform that this usage of the word
+! "read" should be the first one checked. Without 'first', the "read" word
+! will not work the way we want it to because the default usage will get
+! called and will not handle our code properly.
+!
+! 'legible' is the attribute we created and by placing it here, we're telling
+! Inform that this attribute must be present in the object to call this usage
+! of the word "read".
+!
+Extend "read" first * legible -> Read;
+
+!
+! We've also added the ability to 'tear' an object. Notice
+! we had to specify 'noun' and then direct the default to
+! TearSub.
+!
+! By the way, the 'Sub' is added on automatically by Inform.
+!
+! The word 'noun' tells Inform that the word "tear" must be followed by a
+! noun, otherwise Inform will reply, "What do you want to tear?".
+!
+Verb "tear" * noun -> Tear;
+!
+! Q: I'm really confused! Inform uses the words "first", "second", and "noun".
+! Can you explain the difference again?
+!
+! A: Sure.
+!
+! 'first' is a flag used in the grammar statement "Extend" so that the
+! new usage is called before previously defined usages. Without this
+! flag, an older usage might get called and your code may not work.
+!
+! 'second' is a variable that Inform sets if there is a second noun in
+! the player's statement.
+!
+! 'noun' is a variable that Inform sets if there are any nouns in the
+! player's statement. It gets set to the first noun found.
+!
+! > THROW ROCK AT POND
+!
+! ^ ^
+! noun second
+!
diff --git a/presets/zmachine/house06.inf b/presets/zmachine/house06.inf
new file mode 100644
index 00000000..be59d7f0
--- /dev/null
+++ b/presets/zmachine/house06.inf
@@ -0,0 +1,384 @@
+! ------------------------------------------------------------------------------
+! Inform for New Writers
+!
+! The House - Version 6
+!
+! Last Modified: David Cornelson - 31-Jan-1998
+!
+! This work is freely offered to the Public Domain. - DAC 12-12-2015
+!
+! ------------------------------------------------------------------------------
+
+Constant Story "The House";
+
+Constant Headline
+ "^Inform for New Writers^
+ The House - Version 6^
+ By New Writer (1998) - Last Compiled: 31-Jan-1998^";
+
+Constant MAX_SCORE 100;
+Serial "980131";
+
+Release 1;
+
+Include "Parser";
+Include "VerbLib";
+
+!-------------------------------------------------------------------------------
+! Initialise
+!
+!-------------------------------------------------------------------------------
+
+!
+! VERSION 6 - Adding a non-playing character or daemon to your game
+!
+! We are going to add a little pink Jarbigruen to our game, His name is Snark
+! and he tends to be a little inquisitive. In this version of 'The House', he
+! won't really 'do' anything but sit in your arms and blabber a few
+! phrases, which of course you can add to at your discretion.
+!
+! The first thing to do is create the object for Snark. We're going to put him
+! in the mailbox. This means that after the '-> Mailbox' object, we need to add
+! '-> -> Snark' to tell Inform that he is a child object of the mailbox.
+!
+! The Snark daemon will be started the first time you open the mailbox.
+
+[ Initialise;
+
+ location = Sidewalk;
+
+];
+
+[ PrintRank;
+ print ", earning you the rank of ";
+ if (score >= 100) "the greatest.";
+ if (score >= 80) "above average.";
+ if (score >= 60) "average.";
+ if (score >= 40) "below average.";
+ if (score >= 20) "the barely living.";
+ "the living dead.";
+];
+
+! ----------------------------------------------------------------------------
+! Locations
+!
+! In this section we will define our locations. These are "Objects" to Inform.
+!
+! ----------------------------------------------------------------------------
+
+Object Sidewalk "Sidewalk"
+ with description
+ "You are standing on the sidewalk in front of a house to the west.",
+ w_to Front_Porch,
+ has light;
+
+Object -> Mailbox "mailbox"
+ with name "mailbox" "box",
+
+ !
+ ! The 'before' property is used to 'catch' verb commands before Inform
+ ! handles them. In this case, we're going to catch the verb 'Open'.
+ !
+ ! If Snark is in the Mailbox (which he is at the initial start of the
+ ! game) then we execute some special code.
+ !
+ ! We are writing a 'function'. Remember that functions may have arguments
+ ! which would be defined before the semi-colon. This is important to
+ ! Inform so don't forget to begin the 'before' function with the bracket
+ ! AND the semi-colon.
+ !
+ ! Each verb you intend to 'catch' is started simply by the verb followed
+ ! by a colon. The verb's execution ends with the next verb or at the end
+ ! of the function.
+ !
+ before [; Open: !
+ ! This function has a special behavior if Snark is
+ ! in the mailbox, which he is in the beginning.
+ !
+ if (Snark in Mailbox) {
+
+ StartDaemon(Snark);
+ move Snark to player;
+ give Mailbox open;
+
+ print "~Hey! It's about time! Why are you piddling
+ around out there? Don't you know I need air? Who
+ do you think you are anyway, some big adventurer
+ or something? Pullllease!~, exclaims a small pink
+ thing from the mailbox.^^~Hi. I'm Snark, the
+ Jarbigruen!~, he cries in a high-pitched voice
+ and then leaps from the mailbox into your
+ arms.^";
+ rtrue;
+ }
+ !
+ ! This is where the default behavior is executed for
+ ! the verb open. We don't have to 'do' anything and
+ ! Inform will know to execute the default processing.
+ !
+ ],
+ when_open "There is an open mailbox here.",
+ when_closed "There is a closed mailbox here.",
+ has static container openable;
+
+! SNARK, THE JARBIGRUEN
+!
+! Snark has a lot of different names you can refer to him with so we have to
+! put these in the 'name' property. Each name is separated by a space.
+!
+Object -> -> Snark "small pink Jarbigruen"
+ with name "snark" "jarbigruen" "alien" "monster" "thing",
+ description
+ "Snark, a little pink Jarbigruen, stands approximately ten
+ centimeters tall, has two legs, two arms with tiny little hands,
+ a wide-eyed face, and a tuft of yellowish hair on his head.",
+
+ !
+ ! We want Snark to stay with the player so we catch a 'drop'
+ ! and 'Insert' before Inform can let that happen.
+ !
+ ! Except if it's the couch...that's handled differently...
+ !
+ before [; Drop,Insert: if (second == Evil_Couch) {
+ print "You drop Snark onto the couch and the
+ cushions begin to smother him slowly,
+ until he completely disappears. After
+ a few seconds you hear strange noises
+ and, ** POP **, a pink ball is spit out
+ of the couch back into your arms!^^
+ Snark looks up at you and winks,
+ ~Jarbigruen's don't go down very easy,
+ I guess.~^";
+ rtrue;
+ }
+ print "~Hey! I'm not going anywhere without you!~,
+ Snark says.^";
+ rtrue;
+ ],
+
+ !
+ ! The daemon property is central to handling the characterization
+ ! of Snark, the Jarbigruen. For each turn the player takes, this
+ ! property is called.
+ !
+ ! We're not going to do anything complex at this point. Just to
+ ! show that Snark is alive and kinking, we're going to add random
+ ! conversation from Snark. We're also adding the 'switch' statement.
+ !
+ ! The 'switch' statement is used to differentiate different values
+ ! of a variable or expression. For each possible value, you can
+ ! code a different set of instructions.
+ !
+ ! The random(10) function will return, randomly, a number from
+ ! 1 to 10. You can make this number anything you like.
+ !
+ ! We're only giving Snark responses for half of the random numbers
+ ! so he isn't talking all of the time.
+ !
+ daemon [; switch (random(10)) {
+ 1: "Snark says, ~Isn't it great to be here!~";
+ 3: "Snark looks up at you with a glint in his eye and
+ tickles you.";
+ 5: "Snark says, ~You are an excellent adventurer!~";
+ 7: "Snark cries, ~Stop it! Your holding me too tight!~";
+ 9: "Snark rifles through your pockets and sighs,
+ ~Got any candy?~";
+ }
+ ],
+ has animate;
+
+Attribute legible;
+
+Object -> -> Letter "letter"
+ with name "letter" "paper",
+ description
+ "The letter is a simple page of notebook paper.",
+ before [; Consult,Read: "The letter contains a vague story about an evil couch,
+ but you can't make out anymore detail. Interesting
+ little tidbit though.";
+ Tear: remove Letter;
+ "You rip the letter into tiny pieces that blow away in the wind.";
+ ]
+ has legible;
+
+Object Front_Porch "Front Porch"
+ with description
+ "This is the front porch of the house. There are two doors
+ leading inside. The door on the left leads west and the
+ door on the right leads northwest.",
+ e_to Sidewalk,
+ w_to Left_Front_Door,
+ in_to Left_Front_Door,
+ nw_to Right_Front_Door,
+ has light;
+
+!
+! I've added the attribute 'open' to both of the doors. I figured we'd
+! had that lesson and there was no need to repeat it. Both doors will
+! be open at the start of the game. You can still close them and lock
+! the right one with the key though.
+!
+Object -> Left_Front_Door "left front door"
+ with name "left" "front" "door",
+ description
+ "The left front door is made of brass.",
+ when_open "The left front door is open.",
+ when_closed "The left front door is closed.",
+ door_to Foyer,
+ door_dir w_to,
+ has static door openable open;
+
+Object Right_Front_Door "right front door"
+ with name "right" "front" "door",
+ description
+ "The right front door is made of wood.",
+ when_open "The right front door is open.",
+ when_closed "The right front door is closed.",
+ door_to [; if (location==Front_Porch) return Den; return Front_Porch; ],
+ door_dir [; if (location==Front_Porch) return nw_to; return se_to; ],
+ found_in Front_Porch Den,
+ with_key right_key,
+ has static door openable lockable locked open;
+
+Object Den "Den"
+ with description
+ "You are in the den of the house. The living room is west of hear
+ and the front porch is to the southeast.",
+ se_to Right_Front_Door,
+ out_to Right_Front_Door,
+ w_to Living_Room,
+ has light;
+
+Object -> Rock "rock"
+ with name "rock",
+ description
+ "It's smooth and flat, perfect for skipping in a pond.",
+ before [; Insert,PutOn,ThrowAt:
+ if (second==Evil_Couch) rfalse; ! Allow the rock to be eaten by couch
+ if (second==Pond) {
+ print "The rock skips across the water several times and sinks.
+ Amazingly, after a few moments, the rock washes up at
+ your feet. Wow, what an undertow!^";
+ move Rock to Backyard;
+ rtrue;
+ } else {
+ print "You can't throw the rock at ",(the) second, ".^";
+ rtrue;
+ }
+ ];
+
+Object Living_Room "Living Room"
+ with name "living" "room",
+ description
+ "This is the living room of the house. The den is to the east.",
+ e_to Den,
+ has light;
+
+!
+! And here is our evil couch. Anything put on or in the couch will be
+! 'eaten', including you. In fact, by setting the 'deadflag' to 1,
+! Inform is informed to 'end' the game because you have died.
+!
+! Notice we used the 'before' property and the 'Enter' and 'Receive'
+! verbs to handle the action.
+!
+Object -> Evil_Couch "couch"
+ with name "couch" "sofa",
+ when_open "There is a filthy, worn down couch here.",
+ before [; Enter: deadflag=1;
+ "You are eaten by the couch. As you flail for your last few
+ seconds, you see Snark beating on the couch trying to save
+ you, to no avail.";
+ Receive: remove noun;
+ "The couch eats ", (the) noun, " and belches.";
+ ],
+ has static container open enterable;
+
+Object Foyer "Foyer"
+ with description
+ "You are standing in the foyer of the house. It seems as though
+ you can go up a staircase, northwest, or back out the front
+ door to the east.",
+ out_to Front_Porch,
+ e_to Front_Porch,
+ nw_to Hallway,
+ u_to Upper_Hallway,
+ has light;
+
+Object Hallway "Hallway"
+ with description
+ "You are in the hallway on the first floor of the house. The
+ foyer is southeast and the kitchen is west of here.",
+ se_to Foyer,
+ w_to Kitchen,
+ has light;
+
+Object Kitchen "Kitchen"
+ with description
+ "This is the kitchen of the house. A hallway can be seen to the
+ east and an open doorway to the west leads out to the backyard.",
+ e_to Hallway,
+ w_to Backyard,
+ out_to Backyard,
+ has light;
+
+Object Backyard "Backyard"
+ with name "yard",
+ description
+ "This is the backyard behind the house. There is a pond here.",
+ e_to Kitchen,
+ in_to Kitchen,
+ has light;
+
+Object -> Pond "pond"
+ with name "pond" "water",
+ description
+ "It's a small pond, but wide enough to skip rocks.",
+ has static concealed container open;
+
+Object Upper_Hallway "Upper Hallway"
+ with description
+ "This is the second floor hallway. Rooms can be seen north and
+ south and a staircase leads down.",
+ n_to North_Bedroom,
+ s_to South_Bedroom,
+ d_to Foyer,
+ has light;
+
+Object North_Bedroom "North Bedroom"
+ with description
+ "This is a bedroom on the north side of the house.",
+ s_to Upper_Hallway,
+ has light;
+
+Object -> right_key "right key" with name "right" "key", article "the";
+
+Object South_Bedroom "South Bedroom"
+ with description
+ "This is a bedroom on the south side of the house.",
+ n_to Upper_Hallway,
+ has light;
+
+! ----------------------------------------------------------------------------
+!
+! Functions
+!
+! ----------------------------------------------------------------------------
+
+[ ReadSub; <>; ];
+
+[ TearSub; "You can't tear that"; ];
+
+! ----------------------------------------------------------------------------
+! Grammar
+!
+! The grammar section includes the file "Grammar" and will later include
+! extensions to the standard grammar library.
+!
+! ----------------------------------------------------------------------------
+
+Include "Grammar";
+
+Extend "read" first * legible -> Read;
+
+Verb "tear" * noun -> Tear;
diff --git a/presets/zmachine/house07.inf b/presets/zmachine/house07.inf
new file mode 100644
index 00000000..06cbaa18
--- /dev/null
+++ b/presets/zmachine/house07.inf
@@ -0,0 +1,381 @@
+! ------------------------------------------------------------------------------
+! Inform for New Writers
+!
+! The House - Version 7
+!
+! Last Modified: David Cornelson - 01-Feb-1998
+!
+! This work is freely offered to the Public Domain. - DAC 12-12-2015
+!
+! ------------------------------------------------------------------------------
+
+Constant Story "The House";
+
+Constant Headline
+ "^Inform for New Writers^
+ The House - Version 7^
+ By New Writer (1998) - Last Compiled: 01-Feb-1998^";
+
+Constant MAX_SCORE 100;
+Serial "980201";
+
+Release 1;
+
+Include "Parser";
+Include "VerbLib";
+
+!-------------------------------------------------------------------------------
+! Initialise
+!
+!-------------------------------------------------------------------------------
+
+[ Initialise;
+
+ location = Sidewalk;
+
+];
+
+[ PrintRank;
+ print ", earning you the rank of ";
+ if (score >= 100) "the greatest.";
+ if (score >= 80) "above average.";
+ if (score >= 60) "average.";
+ if (score >= 40) "below average.";
+ if (score >= 20) "the barely living.";
+ "the living dead.";
+];
+
+! ----------------------------------------------------------------------------
+! Locations
+!
+! In this section we will define our locations. These are "Objects" to Inform.
+!
+! ----------------------------------------------------------------------------
+
+Object Sidewalk "Sidewalk"
+ with description
+ "You are standing on the sidewalk in front of a house to the west.",
+ w_to Front_Porch,
+ has light;
+
+Object -> Mailbox "mailbox"
+ with name "mailbox" "box",
+
+ before [; Open: if (Snark in Mailbox) {
+
+ StartDaemon(Snark);
+ move Snark to player;
+ give Mailbox open;
+
+ print "~Hey! It's about time! Why are you piddling
+ around out there? Don't you know I need air? Who
+ do you think you are anyway, some big adventurer
+ or something? Pullllease!~, exclaims a small pink
+ thing from the mailbox.^^~Hi. I'm Snark, the
+ Jarbigruen!~, he cries in a high-pitched voice
+ and then leaps from the mailbox into your
+ arms.^";
+ rtrue;
+ }
+ ],
+ when_open "There is an open mailbox here.",
+ when_closed "There is a closed mailbox here.",
+ has static container openable;
+
+Object -> -> Snark "small pink Jarbigruen"
+ with name "snark" "jarbigruen" "alien" "monster" "thing",
+ description
+ "Snark, a little pink Jarbigruen, stands approximately ten
+ centimeters tall, has two legs, two arms with tiny little hands,
+ a wide-eyed face, and a tuft of yellowish hair on his head.",
+
+ before [; Drop,Insert: if (second == Evil_Couch) {
+ print "You drop Snark onto the couch and the
+ cushions begin to smother him slowly,
+ until he completely disappears. After
+ a few seconds you hear strange noises
+ and, ** POP **, a pink ball is spit out
+ of the couch back into your arms!^^
+ Snark looks up at you and winks,
+ ~Jarbigruen's don't go down very easy,
+ I guess.~^";
+ rtrue;
+ }
+ print "~Hey! I'm not going anywhere without you!~,
+ Snark says.^";
+ rtrue;
+ ],
+ daemon [; switch (random(10)) {
+ 1: "Snark says, ~Isn't it great to be here!~";
+ 3: "Snark looks up at you with a glint in his eye and
+ tickles you.";
+ 5: "Snark says, ~You are an excellent adventurer!~";
+ 7: "Snark cries, ~Stop it! Your holding me too tight!~";
+ 9: "Snark rifles through your pockets and sighs,
+ ~Got any candy?~";
+ }
+ ],
+ has animate;
+
+Attribute legible;
+
+Object -> -> Letter "letter"
+ with name "letter" "paper",
+ description
+ "The letter is a simple page of notebook paper.",
+ before [; Consult,Read: "The letter contains a vague story about an evil couch,
+ but you can't make out anymore detail. Interesting
+ little tidbit though.";
+ Tear: remove Letter;
+ "You rip the letter into tiny pieces that blow away in the wind.";
+ ]
+ has legible;
+
+Object Front_Porch "Front Porch"
+ with description
+ "This is the front porch of the house. There are two doors
+ leading inside. The door on the left leads west and the
+ door on the right leads northwest.",
+ e_to Sidewalk,
+ w_to Left_Front_Door,
+ in_to Left_Front_Door,
+ nw_to Right_Front_Door,
+ has light;
+
+!
+! VERSION 7 - Using a Class statement to create a group of common objects
+!
+! There are times when building your game that you begin building the same
+! types of objects over and over. You end up copying code all over the place
+! and maintaining this code becomes a search and replace chase scene.
+!
+! Well, in some instances, there is a better way. We have to discuss a little
+! bit of methodology first though.
+!
+! Most games hsouldn't be written like 'The House'. You should write out as much
+! of your story and physical world as possible. When you have a fairly complete
+! view of this world, you break down all of aspects into objects.
+!
+! If we designed the current version of 'The House' this way, it would look
+! something like this...
+!
+! ----------------------------
+!
+! Sidewalk -> Mailbox -> Snark
+! -> Letter
+!
+! Front Porch -> Left Door
+! -> Right Door
+!
+! Foyer
+!
+! Den -> Rock
+!
+! Living Room -> Evil Couch
+!
+! Hallway
+!
+! Upper Hallway
+!
+! North Bedroom -> Key
+!
+! South Bedroom
+!
+! Kitchen
+!
+! Backyard -> Pond
+!
+! ----------------------------
+!
+! You will likely want to do this BEFORE you begin programming your game. The reason
+! is that you may be able to reduce some of your coding by locating similar objects.
+!
+! Q: What two objects in 'The House' are alike?
+!
+! A: The doors
+!
+! Correct. We are going to rewrite the two door objects, but first we're going to create
+! a class for the foundation of their definition.
+!
+
+Class Front_Door
+ with name "front" "door",
+ has static door openable open;
+
+!
+! And now we'll change the each door object to become a subset of this class.
+! Notice that we can leave out the names and attributes in the class. These
+! are 'inherited' by the newly defined objects.
+!
+! In this example, we didn't reduce our code all that much. But in many cases
+! you will reduce your code. A good use of this is when you have an NPC or
+! non-playing character that you want to be seen as learning. You can create
+! a base class object with rudimentary actions and change to other objects
+! when the NPC is supposed to be 'smarter'.
+!
+! Class Base_Snark ...
+!
+! Base_Snark Snark_1 ...
+! Base_Snark Snark_2 ...
+! Base_Snark Snark_3 ...
+!
+! Anything you define in the class object, is inherited by the continuing
+! objects. If you redefine something, such as an attribute or property,
+! then the new definition supercedes the class definition.
+!
+
+Front_Door -> Left_Front_Door "left front door"
+ with name "left",
+ description
+ "The left front door is made of brass.",
+ when_open "The left front door is open.",
+ when_closed "The left front door is closed.",
+ door_to Foyer,
+ door_dir w_to;
+
+Front_Door -> Right_Front_Door "right front door"
+ with name "right",
+ description
+ "The right front door is made of wood.",
+ when_open "The right front door is open.",
+ when_closed "The right front door is closed.",
+ door_to [; if (location==Front_Porch) return Den; return Front_Porch; ],
+ door_dir [; if (location==Front_Porch) return nw_to; return se_to; ],
+ found_in Front_Porch Den,
+ with_key right_key,
+ has lockable locked;
+
+Object Den "Den"
+ with description
+ "You are in the den of the house. The living room is west of hear
+ and the front porch is to the southeast.",
+ se_to Right_Front_Door,
+ out_to Right_Front_Door,
+ w_to Living_Room,
+ has light;
+
+Object -> Rock "rock"
+ with name "rock",
+ description
+ "It's smooth and flat, perfect for skipping in a pond.",
+ before [; Insert,PutOn,ThrowAt:
+ if (second==Evil_Couch) rfalse; ! Allow the rock to be eaten by couch
+ if (second==Pond) {
+ print "The rock skips across the water several times and sinks.
+ Amazingly, after a few moments, the rock washes up at
+ your feet. Wow, what an undertow!^";
+ move Rock to Backyard;
+ rtrue;
+ } else {
+ print "You can't throw the rock at ",(the) second, ".^";
+ rtrue;
+ }
+ ];
+
+Object Living_Room "Living Room"
+ with name "living" "room",
+ description
+ "This is the living room of the house. The den is to the east.",
+ e_to Den,
+ has light;
+
+Object -> Evil_Couch "couch"
+ with name "couch" "sofa",
+ when_open "There is a filthy, worn down couch here.",
+ before [; Enter: deadflag=1;
+ "You are eaten by the couch. As you flail for your last few
+ seconds, you see Snark beating on the couch trying to save
+ you, to no avail.";
+ Receive: remove noun;
+ "The couch eats ", (the) noun, " and belches.";
+ ],
+ has static container open enterable;
+
+Object Foyer "Foyer"
+ with description
+ "You are standing in the foyer of the house. It seems as though
+ you can go up a staircase, northwest, or back out the front
+ door to the east.",
+ out_to Front_Porch,
+ e_to Front_Porch,
+ nw_to Hallway,
+ u_to Upper_Hallway,
+ has light;
+
+Object Hallway "Hallway"
+ with description
+ "You are in the hallway on the first floor of the house. The
+ foyer is southeast and the kitchen is west of here.",
+ se_to Foyer,
+ w_to Kitchen,
+ has light;
+
+Object Kitchen "Kitchen"
+ with description
+ "This is the kitchen of the house. A hallway can be seen to the
+ east and an open doorway to the west leads out to the backyard.",
+ e_to Hallway,
+ w_to Backyard,
+ out_to Backyard,
+ has light;
+
+Object Backyard "Backyard"
+ with name "yard",
+ description
+ "This is the backyard behind the house. There is a pond here.",
+ e_to Kitchen,
+ in_to Kitchen,
+ has light;
+
+Object -> Pond "pond"
+ with name "pond" "water",
+ description
+ "It's a small pond, but wide enough to skip rocks.",
+ has static concealed container open;
+
+Object Upper_Hallway "Upper Hallway"
+ with description
+ "This is the second floor hallway. Rooms can be seen north and
+ south and a staircase leads down.",
+ n_to North_Bedroom,
+ s_to South_Bedroom,
+ d_to Foyer,
+ has light;
+
+Object North_Bedroom "North Bedroom"
+ with description
+ "This is a bedroom on the north side of the house.",
+ s_to Upper_Hallway,
+ has light;
+
+Object -> right_key "right key" with name "right" "key", article "the";
+
+Object South_Bedroom "South Bedroom"
+ with description
+ "This is a bedroom on the south side of the house.",
+ n_to Upper_Hallway,
+ has light;
+
+! ----------------------------------------------------------------------------
+!
+! Functions
+!
+! ----------------------------------------------------------------------------
+
+[ ReadSub; <>; ];
+
+[ TearSub; "You can't tear that"; ];
+
+! ----------------------------------------------------------------------------
+! Grammar
+!
+! The grammar section includes the file "Grammar" and will later include
+! extensions to the standard grammar library.
+!
+! ----------------------------------------------------------------------------
+
+Include "Grammar";
+
+Extend "read" first * legible -> Read;
+
+Verb "tear" * noun -> Tear;
diff --git a/presets/zmachine/museum.inf b/presets/zmachine/museum.inf
new file mode 100644
index 00000000..b8f0ffcc
--- /dev/null
+++ b/presets/zmachine/museum.inf
@@ -0,0 +1,2169 @@
+! ----------------------------------------------------------------------------
+! Museum 961111 One of the standard Inform 6 example games
+!
+! created: 20.12.95
+! translated to Inform 6: 11.11.96
+!
+! This "game" is a compendium of solved exercises from the Designer's
+! Manual. Room numbers are section numbers within the Third Edition.
+! Many of these exercises are difficult, and so is some of the code below.
+! ----------------------------------------------------------------------------
+
+Constant Story "MUSEUM OF INFORM";
+Constant Headline
+ "^An Interactive Companion to the Designer's Manual (Third Edition)^";
+
+! The game is meant to be experimented with, so we always define:
+Constant DEBUG;
+
+Release 2;
+Serial "961111";
+
+Replace DrawStatusLine;
+Include "Parser";
+
+! --------------------------------------------------------------------------
+
+Object samples_bag "samples bag"
+ with description "A capacious SACK_OBJECT (see section 20).",
+ name "samples" "bag", article "your",
+ when_closed "Your samples bag lies on the floor.",
+ when_open "Your samples bag lies open on the floor.",
+ has container open openable;
+
+Constant SACK_OBJECT = samples_bag;
+
+Include "VerbLib";
+
+! --------------------------------------------------------------------------
+
+Attribute crewmember;
+
+Property weight 10;
+
+Class Key with name "key";
+
+! --------------------------------------------------------------------------
+
+Object Foyer "Foyer"
+ has light
+ with description
+ "The foyer of the magnificent Museum of Inform. A flight of
+ stairs sweeps upward to Chapters V and VI, and corridors
+ fan out on this level into Chapter IV. These run:^
+ ^ north into Room 10 (the Halls of Sense and Direction),
+ ^ south along Corridor 12 (doors) to Room 13 (switches),
+ ^ @00 to Room 11 (the Wonderful World of Containers)
+ ^ and @01 to Room 14 (which houses larger exhibits).^^
+ (And a plain ladder descends into the basement; you can also
+ step out onto a balcony.)",
+ e_to Room11, u_to Second_Floor, n_to Room10,
+ s_to Corridor12, w_to Room14,
+ d_to basement, out_to balcony;
+
+Object -> "map"
+ with name "map" "ground" "floor",
+ initial "A map of the ground floor is embossed in one wall.",
+ description
+ [; font off;
+ print
+ "^+------------------------------------------+
+ ^| (mirror) |
+ ^| Weights Room 10 --- Room 10a |
+ ^| Room senses directions |
+ ^| | | |
+ ^| Room 14 --- Foyer --- Room 11 |
+ ^| (changing (you are here) containers |
+ ^| character) | |
+ ^| | |
+ ^| Room 15 --- Corridor 12 |
+ ^| (MS room) (door, curator) |
+ ^| (Bible) | |
+ ^| Switches Hall 13 |
+ ^| (chasm) |
+ ^| | |
+ ^| Far Side of Room 13 |
+ ^+------------------------------------------+^";
+ font on;
+ ],
+ has static;
+
+! --------------------------------------------------------------------------
+
+Object basement "Museum Basement"
+ with u_to Foyer,
+ description
+ "Once Room 17, this space has been abandoned by the curators,
+ who have simply sprayed its walls with moth-repellent and
+ abandoned it.",
+ before
+ [; Smell: "Napthalene.";
+ ];
+
+! --------------------------------------------------------------------------
+
+Object Room10 "Hall of Senses"
+ with description
+ "This is Room 10, north of the foyer. If you try going further
+ north, a string will be printed instead. The exit to the @00
+ has a routine attached, and randomly leads either to the
+ Directions Room or back to the foyer.",
+ s_to Foyer,
+ n_to "This string is the ~n_to~ value for this room.",
+ e_to
+ [; if (random(2)==1) return Foyer; return Room10a; ],
+ has light;
+
+Object -> "TRAP lever"
+ with name "trap" "lever",
+ before
+ [; Pull, Push:
+ if (self has on) <>;
+ <>;
+ ],
+ after
+ [; SwitchOn: move orange_cloud to location;
+ "Clunk! An orange cloud suddenly descends upon you.";
+ SwitchOff: remove orange_cloud;
+ "Click! The orange cloud vanishes.";
+ ],
+ has switchable static;
+
+Object -> "gold watch"
+ with name "gold" "watch",
+ description "The watch has no hands, oddly.",
+ react_before
+ [; Listen: if (noun==0 or self) "The watch ticks loudly."; ];
+
+Object -> "sprig of lavender"
+ with name "sprig" "of" "lavender",
+ react_before
+ [; Smell: if (noun==0 or self) "Lavender-perfume. Ahh!"; ];
+
+Object orange_cloud "orange cloud"
+ with name "orange" "cloud",
+ react_before
+ [; Look: "You can't see for the orange cloud surrounding you.";
+ Go, Exit: "You wander round in circles, choking.";
+ Smell: if (noun==0 or self) "Cinnamon? No, nutmeg.";
+ ],
+ has scenery;
+
+! --------------------------------------------------------------------------
+! For east-west reflection
+! --------------------------------------------------------------------------
+
+Lowstring east_str "east"; Lowstring west_str "west";
+[ NormalWorld; string 0 east_str; string 1 west_str;
+ e_obj.door_dir = e_to; w_obj.door_dir = w_to;
+];
+[ ReversedWorld; string 0 west_str; string 1 east_str;
+ w_obj.door_dir = e_to; e_obj.door_dir = w_to;
+];
+
+Object Room10a "Hall of Directions"
+ with name "mirror",
+ description
+ "An annexe to Room 10: the main exit is back @01, and there's a
+ curiously misty mirror on the north wall. Also, there's an exit
+ in the fourth, ~hyper~ dimension (which is only visible in the
+ weird geometry of this room).",
+ initial
+ [; move hyper to compass; StartDaemon(hyper);
+ ],
+ w_to Room10,
+ n_to
+ [; print "Walking through the mirror is confusing...^";
+ if (self has general) NormalWorld(); else ReversedWorld();
+ if (self has general) give self ~general; else give self general;
+ <>;
+ ],
+ in_to [; print "Amazing! Your body corkscrews as you pass.^";
+ return Room11; ],
+ has light;
+
+Object hyper "hyper-dimensional direction"
+ with name "hyper" "fourth" "dimension", article "the", door_dir in_to,
+ daemon
+ [; if (location ~= Room10a) { remove self; StopDaemon(self); }
+ ],
+ has scenery;
+
+! --------------------------------------------------------------------------
+
+Object Room11 "Wonderful World of Containers"
+ with description
+ "This is Room 11, @00 of the foyer. You notice a typical piece
+ of scenery which turns out to be a supporter: a mantelpiece.",
+ w_to Foyer,
+ has light;
+
+Object -> "bearded psychiatrist"
+ with name "bearded" "doctor" "psychiatrist" "psychologist" "shrink",
+ initial "A bearded psychiatrist has you under observation.",
+ life
+ [; "He is fascinated by your behaviour, but makes no attempt to
+ interfere with it.";
+ ],
+ react_after
+ [; Insert: print "~Subject puts ", (a) noun, " in ", (the) second,
+ ". Interesting.~^";
+ PutOn: print "~Subject puts ", (a) noun, " in ", (the) second,
+ ". Interesting.~^";
+ ],
+ react_before
+ [; Take, Remove: print "~Subject feels lack of ", (the) noun,
+ ". Suppressed Oedipal complex? Mmm.~^";
+ ],
+ has animate;
+
+Object -> "mantelpiece"
+ with name "mantel" "mantle" "piece" "mantelpiece"
+ has scenery supporter;
+
+Object -> "green ball" with name "green" "ball";
+Object -> "red cone" with name "red" "cone";
+Object -> "blue pyramid" with name "blue" "pyramid";
+
+Object -> "plain shopping bag (which can only hold 2 things)"
+ with name "plain" "shopping" "bag", capacity 2,
+ has container open;
+
+Object -> "glass box with a lid" with name "glass" "box" "with" "lid"
+ has container transparent openable open;
+Object -> "steel box with a lid" with name "steel" "box" "with" "lid"
+ has container openable open;
+
+Key -> bolted_key "bolted key" with name "bolted";
+
+Object -> "toothed bag"
+ with name "toothed" "bag",
+ description "A capacious bag with a toothed mouth.",
+ before
+ [; LetGo: "The bag defiantly bites itself
+ shut on your hand until you desist.";
+ Close: "The bag resists all attempts to close it.";
+ ],
+ after
+ [; Receive:
+ "The bag wriggles hideously as it swallows ",
+ (the) noun, ".";
+ ],
+ has container open;
+
+Object -> "bolted cupboard"
+ with name "bolted" "cupboard",
+ describe
+ [; if (self hasnt open)
+ "^A pretty typical shut cupboard is bolted to one wall.";
+ "^Bolted up on one wall is an open cupboard.";
+ ],
+ with_key bolted_key
+ has locked container openable lockable static;
+
+Object -> "portable television set"
+ with name "tv" "television" "set" "portable",
+ initial "A portable television set has two sub-objects attached:
+ a power button and a screen.",
+ before
+ [; SwitchOn: <>;
+ SwitchOff: <>;
+ Examine: <>;
+ ],
+ has transparent;
+Object -> -> power_button "power button"
+ with name "power" "button" "switch",
+ after
+ [; SwitchOn, SwitchOff: <>;
+ ],
+ has switchable;
+Object -> -> screen "television screen"
+ with name "screen",
+ before
+ [; Examine: if (power_button hasnt on) "The screen is black.";
+ "The screen writhes with a strange Japanese cartoon.";
+ ];
+
+Object -> "macrame bag"
+ with name "macrame" "bag" "string" "net" "sack",
+ react_before
+ [; Examine, Search, Listen, Smell: ;
+ default:
+ if (inp1>1 && inp1 in self)
+ print_ret (The) inp1, " is tucked away in the bag.";
+ if (inp2>1 && inp2 in self)
+ print_ret (The) inp2, " is tucked away in the bag.";
+ ],
+ describe
+ [; print "^A macrame bag hangs from the ceiling, shut tight";
+ if (child(self)==0) ".";
+ print ". Inside you can make out ";
+ WriteListFrom(child(self), ENGLISH_BIT); ".";
+ ],
+ has container transparent static;
+Object -> -> "music box"
+ with name "music" "box" "musical",
+ description "Attractively lacquered.",
+ react_before
+ [; Listen: if (noun==0 or self)
+ "The musical box chimes some Tchaikovsky."; ];
+
+! --------------------------------------------------------------------------
+
+Object Corridor12 "Corridor 12"
+ with description
+ "Runs south of the foyer. A side exit leads @01 to Room 15,
+ the manuscripts room.",
+ n_to Foyer, s_to Oak_Door, w_to Room15,
+ has light;
+
+Object -> "sinister curator"
+ with name "sinister" "curator",
+ initial
+ [; if (self hasnt general)
+ "A sinister curator leans against the wall, asleep.";
+ "The curator is here, casting menacing looks.";
+ ],
+ daemon
+ [ i p j n k;
+ if (random(3)~=1 || self hasnt general) rfalse;
+ p=parent(self);
+ objectloop (i in compass)
+ { j=p.(i.door_dir);
+ if (ZRegion(j)==1 && j hasnt door) n++;
+ }
+ if (n==0) rfalse;
+ k=random(n); n=0;
+ objectloop (i in compass)
+ { j=p.(i.door_dir);
+ if (ZRegion(j)==1 && j hasnt door) n++;
+ if (n==k)
+ { move self to j;
+ if (p==location) "^The curator stalks away.";
+ if (j==location) "^The curator stalks in.";
+ rfalse;
+ }
+ }
+ ],
+ orders
+ [; if (self hasnt general) "The curator only snores.";
+ "He raises a skeletal finger to his lips. ~Shh!~";
+ ],
+ life
+ [; WakeOther:
+ if (self hasnt general)
+ { give self general; move self to Foyer;
+ "He wakes and rouses to his feet, pushes past you
+ and stalks away.";
+ }
+ default: "He rears back with disdain.";
+ ],
+ has animate;
+
+Object Oak_Door "oaken door"
+ with name "oak" "door" "oaken",
+ description "Despite appearances, there is no key to this door.",
+ door_dir
+ [; if (location==Corridor12) return s_to; return n_to; ],
+ door_to
+ [; if (location==Corridor12) return Room13; return Corridor12; ],
+ describe
+ [; if (self has open) "^The oaken door stands open.";
+ if (self hasnt locked) "^The corridor ends in an oaken door.";
+ ],
+ found_in Corridor12 Room13
+ has static door openable lockable;
+
+! --------------------------------------------------------------------------
+
+Object Room15 "Manuscripts Room"
+ with description
+ "This is Room 15, adjoining a corridor to the @00.",
+ e_to Corridor12,
+ has light;
+
+Object -> "black Tyndale Bible"
+ with name "bible" "black" "book",
+ initial "A black Bible rests on a spread-eagle lectern.",
+ description "A splendid foot-high Bible, which must have survived
+ the burnings of 1520.",
+ before
+ [ w x; Consult:
+ wn = consult_from; w = NextWord();
+ switch(w)
+ { 'matthew': x="Gospel of St Matthew";
+ 'mark': x="Gospel of St Mark";
+ 'luke': x="Gospel of St Luke";
+ 'john': x="Gospel of St John";
+ default: "There are only the four Gospels.";
+ }
+ if (consult_words==1)
+ "You read the ", (string) x, " right through.";
+ w = TryNumber(wn);
+ if (w==-1000)
+ "I was expecting a chapter number in the ",
+ (string) x, ".";
+ "Chapter ", (number) w, " of the ", (string) x,
+ " is too sacred for you to understand now.";
+ ];
+
+! --------------------------------------------------------------------------
+
+Object Room13 "Switches Hall"
+ with description
+ "This is Room 13, at the south end of a long corridor leading
+ north. Progress further south is blocked by a chasm.",
+ n_to Oak_Door, s_to PlankBridge,
+ has light;
+
+Object -> "Gotham City searchlight"
+ with name "gotham" "city" "search" "light" "template" "searchlight",
+ article "the",
+ description "It has some kind of template on it.",
+ when_on "The old city searchlight shines out a bat against
+ the alabaster ceiling of the Museum.",
+ when_off "The old Gotham city searchlight has been lovingly
+ restored and housed here."
+ has switchable static;
+
+Object -> "basement light switch"
+ with name "basement" "light" "switch",
+ after
+ [; SwitchOn: give basement light; "Click!";
+ SwitchOff: give basement ~light; "Click!";
+ ],
+ has switchable static;
+
+Object -> PlankBridge "plank bridge"
+ with description "Extremely fragile and precarious.",
+ name "precarious" "fragile" "wooden" "plank" "bridge",
+ when_open
+ "A precarious plank bridge spans the chasm.",
+ door_to
+ [; if (children(player)~=0)
+ { deadflag=1;
+ "You step gingerly across the plank, which bows under
+ your weight. But your meagre possessions are the straw
+ which breaks the camel's back! There is a horrid crack...";
+ }
+ print "You step gingerly across the plank, grateful that
+ you're not burdened.^";
+ if (location==Room13) return FarSide; return Room13;
+ ],
+ door_dir
+ [; if (location==Room13) return s_to; return n_to;
+ ],
+ found_in Room13 FarSide,
+ has static door open;
+
+Object FarSide "Far Side of Chasm in Room 13"
+ with description
+ "This side of the chasm is dull and dusty after all.",
+ n_to PlankBridge,
+ has light;
+
+! --------------------------------------------------------------------------
+
+Object Room14 "Large Exhibits Room"
+ with description
+ "This is Room 14, @01 of the foyer, which gives onto the Weights
+ Room to the north.",
+ e_to Foyer, n_to Weights_Room,
+ has light;
+
+Object -> "hypnotic portrait"
+ with name "hypnotic" "portrait" "warthog" "picture" "of" "hog",
+ initial "A somewhat hypnotic full-length portrait of a warthog hangs
+ on the wall.",
+ before
+ [; Examine: ; print "^...and somehow, so do you...^";
+ ChangePlayer(hog); <>;
+ ],
+ has static;
+
+Object -> "Louis XV chair"
+ with name "louis" "xv" "quinze" "chair",
+ initial "A valuable Louis XV chair takes pride of place.",
+ has enterable supporter;
+
+Object -> car "little red car"
+ with name "little" "red" "car" "kar1",
+ description "Large enough to sit inside. Among the controls is a
+ prominent on/off switch. The numberplate is KAR 1.",
+ when_on "The red car sits here, its engine still running.",
+ when_off "A little red car is parked here.",
+ before
+ [; PushDir: AllowPushDir(); rtrue;
+ Go: if (car has on) { Achieved(1); "Brmm! Brmm!"; }
+ print "(The ignition is off at the moment.)^";
+ ],
+ after
+ [; PushDir: "The car rolls very slowly as you push it.";
+ ],
+ has switchable enterable static container open;
+
+Object -> -> "small note"
+ with name "small" "note",
+ description
+ " !!!! FROBOZZ MAGIC CAR COMPANY !!!!^
+ ^Hello, Driver!^
+ ^Instructions for use:^
+ ^Switch on the ignition and off you go!^
+ ^Warranty:^
+ ^This car is guaranteed against all defects for a period of
+ 76 milliseconds from date of purchase or until used,
+ whichever comes first.^
+ ^Good Luck!";
+
+Object -> "Giant"
+ with name "giant",
+ initial "A Giant is here. (And you know the old legend... push a
+ Giant, become a Giant!)",
+ before
+ [; Push: ChangePlayer(self); <>;
+ Take: rtrue;
+ ],
+ number 0,
+ orders
+ [; if (player==self)
+ { if (actor~=self)
+ "You only become tongue-tied and gabble.";
+ if (action==##Push && noun==selfobj)
+ { ChangePlayer(selfobj); <>; }
+ rfalse;
+ }
+ Attack: "The Giant looks at you with doleful eyes.
+ ~Me not be so bad!~";
+ default: "The Giant is unable to comprehend your instructions.";
+ ],
+ has animate;
+
+
+! --------------------------------------------------------------------------
+
+Object "Caldera"
+ with description
+ "An old volcanic crater of mud and ash, from which there is
+ nowhere to go.",
+ has light;
+
+Object -> hog "Warthog"
+ with name "wart" "hog" "warthog",
+ description "Muddy, sniffing and grunting.",
+ number,
+ orders
+ [; if (player~=self || actor~=self) rfalse;
+
+ ! So now we have just the case where the player
+ ! is currently the warthog, ordering himself about:
+
+ Go, Look, Examine, Eat, Smell, Taste, Touch: rfalse;
+ default: "Warthogs can't do anything as tricky as that!";
+ ],
+ has animate proper;
+
+Object -> "red berry"
+ with name "red" "berry" "magic",
+ initial "A magic red berry is half-uncovered in the mud.",
+ before
+ [; Smell, Taste, Touch:
+ print "The blood-smell of the berry brings you back,
+ back...^";
+ ChangePlayer(selfobj); <>;
+ ];
+
+! --------------------------------------------------------------------------
+
+Constant CARRYING_STRENGTH = 500;
+Constant HEAVINESS_THRESHOLD = 100;
+
+Object Weights_Room "Weights Room"
+ with description
+ "This is an annexe, south of Room 14. In here (though nowhere
+ else) objects have given weights, and
+ you can carry only a limited total weight. (Items from elsewhere
+ in the museum all weigh 10 zobs, regardless of what they are.)
+ The longer you carry heavy objects, the more tired you become,
+ until you're forced to drop them; your strength recovers once
+ you're carrying only a light load.",
+ initial [; weight_monitor.activate(); ],
+ s_to Room14,
+ has light;
+
+Object -> "feather" with name "feather", weight 1;
+Object -> "iron anvil" with name "iron" "anvil", article "an", weight 300;
+Object -> "five-zob weight" with name "five" "zob" "weight", weight 5;
+Object -> "ten-zob weight" with name "ten" "zob" "weight", weight 10;
+Object -> "twenty-zob weight" with name "twenty" "zob" "weight", weight 20;
+Object -> "fifty-zob weight" with name "fifty" "zob" "weight", weight 50;
+Object -> "hundred-zob weight" with name "hundred" "zob" "weight", weight 100;
+
+[ WeightOf obj t i;
+ t = obj.weight;
+ objectloop (i in obj) t = t + WeightOf(i);
+ return t;
+];
+
+Object weight_monitor
+ with
+ players_strength,
+ warning_level 5,
+
+ activate
+ [; self.players_strength = CARRYING_STRENGTH; StartDaemon(self);
+ ],
+ daemon
+ [ w s b bw;
+ if (location ~= Weights_Room) { StopDaemon(self); return; }
+
+ s = self.players_strength
+ - WeightOf(player) + HEAVINESS_THRESHOLD;
+ if (s<0) s=0; if (s>CARRYING_STRENGTH) s=CARRYING_STRENGTH;
+ self.players_strength = s;
+
+ if (s==0)
+ { bw=-1;
+ objectloop(b in player)
+ if (WeightOf(b) > bw) { bw = WeightOf(b); w=b; }
+ self.players_strength = self.players_strength + bw;
+ print "^Exhausted with carrying so much, you decide
+ to discard ", (the) w, ": "; <>;
+ }
+
+ w=s/100; if (w==self.warning_level) return;
+
+ self.warning_level = w;
+ switch(w)
+ { 3: "^You are feeling a little tired.";
+ 2: "^You possessions are weighing you down.";
+ 1: "^Carrying so much weight is wearing you out.";
+ 0: "^You're nearly exhausted enough to drop everything
+ at an inconvenient moment.";
+ }
+ ];
+
+! --------------------------------------------------------------------------
+
+Constant SUNRISE 360; ! i.e., 6 am
+Constant SUNSET 1140; ! i.e., 7 pm
+Global day_state = 2;
+
+Object balcony "Balcony"
+ with description
+ [; print "An open-air balcony on the cliffside wall of the
+ cathedral-like Museum, hundreds of feet above ";
+ if (day_state==1) "sunlit plains of farms and settlements.";
+ "a darkling plain. Dim light from the walls above is
+ the only beacon in this vast night.";
+ ],
+ in_to Foyer,
+ cant_go "The only way is back inside.",
+ each_turn
+ [ f;
+ if (the_time >= SUNRISE && the_time < SUNSET) f=1;
+ if (day_state == f) return;
+ if (day_state==2) { day_state = f; return; }
+ day_state = f;
+ if (f==1) "^The sun rises, illuminating the landscape!";
+ "^As the sun sets, the landscape is plunged into darkness.";
+ ],
+ has light;
+
+Object -> "giant clock"
+ with name "giant" "clock" "face" "clockface" "clock-face",
+ before
+ [; Examine: "According to the giant clockface on the wall
+ above, it is now ", the_time/60, ":", (the_time%60)/10,
+ the_time%10, ".";
+ default: "The giant clock-face is too high above you.";
+ ],
+ react_after [; Look: new_line; ; ],
+ has static concealed;
+
+Object -> moth "moth"
+ with name "moth",
+ initial "A catchable moth flits about.";
+
+[ GoMothGo;
+ if (moth in player)
+ { remove moth;
+ "As your eyes try to adjust, you feel a ticklish sensation
+ and hear a tiny fluttering sound.";
+ }
+];
+
+Object -> "Commander Data"
+ with name "data" "commander",
+ orders
+ [; "~I regret that I am only here to make an example work elsewhere.
+ Please proceed upstairs to 10 Forward to see.~";
+ ],
+ has proper animate crewmember;
+
+! ==========================================================================
+
+Object Second_Floor "Mezzanine"
+ with description
+ "Halfway up the marble staircase of the building, a second floor
+ mezzanine which leads south into Grammar Hall (an extension
+ purpose-built for the Room 16 exhibition).",
+ d_to Foyer,
+ s_to Grammar_Hall,
+ u_to Third_Floor,
+ has light;
+
+Object -> "map"
+ with name "map" "mezzanine" "level",
+ initial "A map of the mezzanine level is embossed in one wall.",
+ description
+ [; font off;
+ print
+ "^+------------------------------------------+
+ ^| |
+ ^| |
+ ^| |
+ ^| |
+ ^| Mezzanine |
+ ^| (you are here) |
+ ^| | |
+ ^| | |
+ ^| Grammar Hall 16 |
+ ^| (telepathy, clock) |
+ ^| (Charlotte, Dan) --- Ten Forward |
+ ^| | (replicator) |
+ ^| Liberator (computer) |
+ ^| Bridge (tricorder) |
+ ^| (Zen) |
+ ^+------------------------------------------+^";
+ font on;
+ ],
+ has static;
+
+Object -> "Room 16 exhibition leaflet"
+ with name "leaflet" "exhibition" "guide" "room" "sixteen",
+ initial "An exhibition leaflet has fallen to the floor.",
+ description
+ "Among the rare & fascinating exhibits in Room 16 are:...^^
+ Telekinetic (and telepathic) Martha. In the telepathy
+ booth, you can speak to her as though she were in Room 16
+ with you -- but she's not, she is far away. Tell her to
+ ~look~ to find out where, and you can also ask her to give
+ you things (by telekinesis).^^
+ Charlotte, who is playing Simon Says. She'll obey
+ instructions you give as long as you preface it with
+ ~simon says~. (Though she only knows how to wave, or how to
+ clap many times (just tell her a number).)^^
+ Dyslexic Dan knows how to take and drop things and how to
+ perform an inventory, but unfortunately confuses Take and
+ Drop orders.^^
+ The alarm clock can be told ~on~, ~off~ or a time of day
+ (to set its alarm to).";
+
+! --------------------------------------------------------------------------
+
+Object Grammar_Hall "Grammar Hall"
+ has light,
+ with description
+ "The main exhibit on the second floor: Room 16, south of the
+ mezzanine. A Jeffreys Tube runs @00 into a Star Trek: The
+ Next Generation room, while a hexagonal corridor to the south
+ leads to the bridge of the spaceship ~Liberator~.",
+ n_to Second_Floor, e_to Star_Trek, s_to Blakes_Seven;
+
+Object -> booth "telepathy booth"
+ with name "booth" "telepathy",
+ initial
+ "A telepathy booth stands invitingly open:
+ ~Talk To Telekinetic Martha~.",
+ has enterable static;
+
+Object -> "Charlotte"
+ with name "charlotte" "charlie" "chas",
+ number 0,
+ grammar
+ [; give self ~general;
+ wn=verb_wordnum;
+ if (NextWord()=='simon' && NextWord()=='says')
+ { give self general;
+ verb_wordnum=verb_wordnum+2;
+ }
+ self.number=TryNumber(verb_wordnum);
+ if (self.number~=-1000)
+ { action=##Clap; noun=0; second=0; rtrue; }
+ ],
+ orders
+ [ i; if (self hasnt general) "Charlotte sticks her tongue out.";
+ WaveHands: "Charlotte waves energetically.";
+ Clap: if (self.number==0) "Charlotte folds her arms.";
+ for (i=0:i100)
+ "^^Charlotte's a bit out of breath now.";
+ "^^~Easy!~ says Charlotte.";
+ default: "~Don't know how,~ says Charlotte.";
+ ],
+ initial "Charlotte wants to play Simon Says.",
+ has animate female proper crewmember;
+
+Object -> "Dyslexic Dan"
+ with name "dan" "dyslexic",
+ grammar
+ [; if (verb_word == 'take') { verb_wordnum++; return 'drop'; }
+ if (verb_word == 'drop') { verb_wordnum++; return 'take'; }
+ ],
+ orders
+ [;
+ Take: "~What,~ says Dan, ~ you want me to take ",
+ (the) noun, "?~";
+ Drop: "~What,~ says Dan, ~ you want me to drop ",
+ (the) noun, "?~";
+ Inv: "~That I can do,~ says Dan. ~I'm empty-handed.~";
+ default: "~Don't know how,~ says Dan.";
+ ],
+ initial "Dyslexic Dan is here.",
+ has animate proper crewmember;
+
+[ PrintTime x;
+ print (x/60), ":", (x%60)/10, (x%60)%10;
+];
+
+Object -> "alarm clock"
+ with name "alarm" "clock", article "an",
+ number 480,
+ description
+ [; print "The alarm is ";
+ if (self has general) print "on, "; else print "off, but ";
+ "the clock reads ", (PrintTime) the_time,
+ " and the alarm is set for ", (PrintTime) self.number, ".";
+ ],
+ react_after
+ [; Inv: if (self in player) { new_line; <>; }
+ Look: if (self in location) { new_line; <>; }
+ ],
+ daemon
+ [; if (the_time >= self.number && the_time <= self.number+3
+ && self has general) "^Beep! Beep! The alarm goes off.";
+ ],
+ grammar
+ [; return 'alarm,';
+ ],
+ orders
+ [; SwitchOn: give self general; StartDaemon(self); "~Alarm set.~";
+ SwitchOff: give self ~general; StopDaemon(self);
+ "~Alarm cancelled.~";
+ SetTo: self.number=noun; <>;
+ default: "~Commands are on, off or a time of day only, pliz.~";
+ ],
+ life
+ [; Ask, Answer, Tell:
+ "[Try ~clock, something~ to address the clock.]";
+ ],
+ has talkable;
+
+! --------------------------------------------------------------------------
+
+Object Blakes_Seven "Spaceship Liberator: Bridge"
+ has light,
+ with description
+ "The great serried bridge of the alien spaceship Liberator,
+ captured by Blake's group of revolutionary criminals on the
+ run from the oppressive Earth Federation. (Don't worry --
+ it's just a convincing replica, and the museum still lies
+ back north.)",
+ n_to Grammar_Hall;
+
+Object -> "informative plaque"
+ with name "informative" "plaque",
+ article "an",
+ description
+ "[Among the commands which Zen was often given by the hard-pressed
+ Liberator crew were:^^
+ zen, scan 360 orbital^
+ zen, speed standard by six^
+ zen, clear the neutron blasters for firing^
+ zen, raise the force wall^
+ zen, set course for centauro]",
+ has static;
+
+Object -> "Zen"
+ with name "zen" "flight" "computer",
+ initial
+ "Square lights flicker unpredictably across a hexagonal fascia
+ on one wall, indicating that the flight computer Zen is on-line.",
+ grammar
+ [; return -'zen,';
+ ],
+ orders
+ [; Show: "The main screen shows a starfield,
+ turning through ", noun, " degrees.";
+ Go: "~Confirmed.~ The ship turns to a new bearing.";
+ SetTo: if (noun==0) "~Confirmed.~ The ship comes to a stop.";
+ if (noun>12) "~Standard by ", (number) noun,
+ " exceeds design tolerances.~";
+ "~Confirmed.~ The ship's engines step to
+ standard by ", (number) noun, ".";
+ Take: if (noun~=force_wall) "~Please clarify.~";
+ "~Force wall raised.~";
+ Drop: if (noun~=blasters) "~Please clarify.~";
+ "~Battle-computers on line.
+ Neutron blasters cleared for firing.~";
+ NotUnderstood: "~Language banks unable to decode.~";
+ default: "~Information. That function is unavailable.~";
+ ],
+ has talkable proper static;
+Object -> -> force_wall "force wall" with name "force" "wall" "shields";
+Object -> -> blasters "neutron blasters" with name "neutron" "blasters";
+
+! --------------------------------------------------------------------------
+
+Object "Captain Picard"
+ with name "captain" "picard",
+ has proper animate crewmember;
+
+Object Star_Trek "10 Forward"
+ has light,
+ with description
+ "The starswept observation lounge forward of deck 10
+ of the Starship Enterprise, where many milkshakes have
+ been consumed in crisis situations. (It's only a replica,
+ of course, and the museum lies back @01.)",
+ w_to Grammar_Hall;
+
+Object -> "informative plaque"
+ with name "informative" "plaque",
+ article "an",
+ description
+ "[The computer, called just ~computer~, is useful for locating
+ crew-members: try ~computer, where is commander data~, or
+ ~...captain picard~, or any of the other people who can be
+ found in the Museum.^^
+ The tricorder will scan something if you tell it the name of
+ whom or what you wish to scan.^^
+ The replicator is a superior drinks machine: for instance,
+ Captain Picard is fond of saying ~replicator, tea earl grey~.
+ There's also brandy and distilled water.]",
+ has static;
+
+Object -> "computer"
+ with name "computer",
+ initial "The computer, of course, always responds to your voice here.",
+ grammar
+ [; return 'stc,';
+ ],
+ orders
+ [; Examine:
+ if (parent(noun)==0)
+ "~", (name) noun,
+ " is no longer aboard this demonstration game.~";
+ "~", (name) noun, " is in ", (name) parent(noun), ".~";
+ default: "The computer's only really good for locating the crew.";
+ ],
+ life
+ [; Ask, Answer, Tell: "The computer is too simple.";
+ ],
+ has talkable static;
+
+Object -> "tricorder"
+ with name "tricorder",
+ grammar
+ [; return 'tc,';
+ ],
+ orders
+ [; Examine: if (noun==player) "~You radiate life signs.~";
+ print "~", (The) noun, " radiates ";
+ if (noun hasnt animate) print "no ";
+ "life signs.~";
+ default: "The tricorder bleeps. It can only accept commands
+ ~tricorder, ~.";
+ ],
+ life
+ [; Ask, Answer, Tell: "The tricorder is too simple.";
+ ],
+ has talkable;
+
+Object -> "replicator"
+ with name "replicator",
+ initial
+ "A replicator (i.e. Star Trek drinks machine) occupies a niche
+ in one wall.",
+ grammar
+ [; return 'rc,';
+ ],
+ orders
+ [; Give:
+ "The replicator serves up a cup of ",
+ (name) noun, " which you drink eagerly.";
+ default: "The replicator is unable to oblige. You must give
+ it the name of a drink it knows about.";
+ ],
+ life
+ [; Ask, Answer, Tell: "The replicator has no conversation skill.";
+ ],
+ has talkable static;
+Object -> -> "Earl Grey tea" with name "earl" "grey" "tea";
+Object -> -> "Aldebaran brandy" with name "aldebaran" "brandy";
+Object -> -> "distilled water" with name "distilled" "water";
+
+! --------------------------------------------------------------------------
+
+Object "Sealed Room"
+ with description
+ "I'm in a sealed room, like a squash court without a door,
+ maybe six or seven yards across",
+ has light;
+Object -> "fish" with name "fish";
+Key -> "cadmium key"
+ with name "cadmium",
+ after
+ [; Drop: remove self; "The key smashes into smithereens!";
+ ];
+
+Object -> martha "Martha"
+ has animate female concealed proper crewmember
+ with name "martha",
+ orders
+ [ r; r=parent(self);
+ Give:
+ if (noun notin r) "~That's beyond my telekinesis.~";
+ if (noun==self) "~Teleportation's too hard for me.~";
+ move noun to player;
+ "~Here goes...~ and Martha's telekinetic talents
+ magically bring ", (the) noun, " to your hands.";
+ Look:
+ print "~", (string) r.description;
+ if (children(r)==1) ". There's nothing here but me.~";
+ print ". I can see ";
+ WriteListFrom(child(r),CONCEAL_BIT+ENGLISH_BIT);
+ ".~";
+ default: "~Afraid I can't help you there.~";
+ ],
+ life
+ [; Ask: "~You're on your own this time.~";
+ Tell: "Martha clucks sympathetically.";
+ Answer: "~I'll be darned,~ Martha replies.";
+ ];
+
+! ==========================================================================
+
+Object Third_Floor "Third Floor"
+ with name "trapdoor",
+ description
+ "Atop the marble staircase, this third floor
+ foyer fans out into Rooms from Chapter V. These run:^
+ ^ south to Corridor 22 (inventories)
+ and the List Property Office,
+ ^ @00 to Room 24 (Curious Names),
+ ^ @01 to Room 28, which is divided by a glass window.^
+ ^Only a very rickety
+ ladder goes further up, through an open trapdoor to the roof.",
+ d_to Second_Floor, u_to roof,
+ e_to Room24, w_to window_w, s_to Corridor22,
+ has light;
+
+Object -> "map"
+ with name "map" "third" "floor",
+ initial "A map of the third floor is embossed in one wall.",
+ description
+ [; font off;
+ print
+ "^+------------------------------------------+
+ ^| |
+ ^| (glass |
+ ^| window) |
+ ^| ! |
+ ^| Room ! 28 --- Stairs --- Room 24 |
+ ^| ! (you are here) Names |
+ ^| | | |
+ ^| | Museum Cafe |
+ ^| Corridor 22 |
+ ^| (Inventories) |
+ ^| / | @@92 |
+ ^| / | @@92 |
+ ^| Room 23 W --- Room 23 --- Room 23 E |
+ ^| (listing List Property (I Ching) |
+ ^| machine) Office |
+ ^+------------------------------------------+^";
+ font on;
+ ],
+ has static;
+
+Object -> "Lexicon"
+ with name "lexicon",
+ initial
+ "On the top step is a discarded Lexicon of verbs.",
+ description
+ "(The lexicon has the number 27 written on the spine.)^^
+ Inside are many familiar verbs that you regularly use
+ when navigating through Inform games. There are also
+ some special ones, only available in the Museum...^^
+ ~megalook~ : like ~look~ but much fuller;^
+ ~threefold ~ : this doesn't
+ actually do anything, but it shows how a verb can
+ be parsed which has three objects, not just 0 to 2
+ as usual;^
+ ~time