zmachine experiments

This commit is contained in:
Steven Hugg 2020-07-06 18:53:20 -05:00
parent 0f284531db
commit 741df9f5b8
34 changed files with 59739 additions and 28 deletions

View File

@ -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

View File

@ -568,4 +568,49 @@ div.asset_toolbar {
font-family: "Andale Mono", "Menlo", "Lucida Console", monospace;
font-size: 10pt;
line-height: 1.2;
}
}
.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;
}

View File

@ -218,6 +218,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<li><a class="dropdown-item" href="?platform=atari8-5200.mame">Atari 5200 (MAME)</a></li>
<li><a class="dropdown-item" href="?platform=vector-ataricolor">Atari Color Vector (6502)</a></li>
<li><a class="dropdown-item" href="?platform=markdown">Markdown</a></li>
<li><a class="dropdown-item" href="?platform=zmachine">Z-Machine (Inform 6)</a></li>
</ul>
</li>
</ul>
@ -311,6 +312,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<!-- emulator video -->
<div id="emuscreen">
</div>
<!-- for Javatari only -->
<div id="javatari-div" style="float:center;margin:10px;display:none">
<div id="javatari-screen" style="margin: 0 auto; box-shadow: 2px 2px 10px rgb(60, 60, 60);"></div>
<div id="javatari-console-panel" style="margin: 0 auto; box-shadow: 2px 2px 10px rgb(60, 60, 60);"></div>
@ -538,6 +540,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<script src="codemirror/mode/gas/gas.js"></script>
<script src="src/codemirror/6502.js"></script>
<script src="src/codemirror/bataribasic.js"></script>
<script src="src/codemirror/inform6.js"></script>
<link rel="stylesheet" href="css/codemirror.css">
<script src="codemirror/addon/edit/matchbrackets.js"></script>
<script src="codemirror/addon/search/search.js"></script>

3
lib/zvm/ifvms.min.js vendored Normal file

File diff suppressed because one or more lines are too long

4003
presets/zmachine/advent.inf Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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.";
<<Fill bottle>>;
Insert: if (second == bottle) <<Fill bottle>>;
"You have nothing in which to carry the water.";
Receive: if (noun == bottle) <<Fill 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: <<Enter self>>;
],
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: <<Enter self>>;
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 self wine_bladder>>;
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) <<Fill self>>;
"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: <<SwitchOn self>>;
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; <<Drink water>>;
],
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) <<Fill bottle>>;
"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.";
<<Insert gas self>>;
];
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: <<Sing>>;
Attack, ThrowAt:
if (self has general) <WakeOther self>;
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...";
<<Inv>>;
}
"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;
! ----------------------------------------------------------------------------

469
presets/zmachine/alice.inf Normal file
View File

@ -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: <<Examine self>>;
];
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;

View File

@ -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;
}
<Look>;
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";

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
[ Main;
print "Hello, World!^";
];

View File

@ -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 <score> out of <MAX_SCORE>", 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";

View File

@ -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";

View File

@ -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";

View File

@ -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";

View File

@ -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; <<Examine noun>>; ];
[ 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
!

View File

@ -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; <<Examine noun>>; ];
[ 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;

View File

@ -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; <<Examine noun>>; ];
[ 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;

2169
presets/zmachine/museum.inf Normal file

File diff suppressed because it is too large Load Diff

691
presets/zmachine/ruins1.inf Normal file
View File

@ -0,0 +1,691 @@
!==============================================================================!
! The Inform Designer's Manual (16May97) includes various references to a
! sample game called "Ruins", which unfortunately is not supplied with the
! compiler. This file attempts to knit together several of the fragments from
! the DM into a small but complete game, intended primarily as an example for
! novices of a typical way to use Inform features, and as a starting point
! for experimentation.
!
! In order to keep the game manageably small, the following references from
! the DM have been omitted:
! parrot, low mist, chasm, pumice-stone ball, glyphs, dictionary,
! food rations, sodium lamp, cage.
! Other items have been changed as necessary for simplicity and consistency.
!
! Object definitions explicitly state the name of their parent object (if
! appropriate), rather than using the "->" construct.
!
! Once you've played the game and (hopefully) understood how it works, you
! are strongly encouraged to try modifying or extending it. For instance:
! - add the low mist in the Forest and Square_Chamber. In the DM it smells of
! broth, so perhaps you should provide a source for the smell (or just
! change the description)?
! - implement the parrot, perhaps having it fly into the Forest once the plane
! has departed?
! - extend the number of rooms. There's a suggestion that you could Down from
! the Shrine, or perhaps you could add a dark passage leading West from the
! Corridor?
! - if the passage is dark, perhaps a lamp would be useful?
! - if you've got a lamp, the maze in the Web becomes much less daunting
! (and the descriptions will need beefing up too). So perhaps it's the lamp
! rather than the bangle which you find on your exit from the darkened Web?
! - the DM is a bit unclear about the role(!) of the pumice-stone ball, but
! it seems to need pushing into the chasm. Maybe it blocks the gap and
! allows you to cross to the other side (in order to reach the bangle)?
! - there are a couple of daemons in the example, but no timer. How about
! extending the Honeycomb so that if dropped it prints a warning and starts
! a timer causing itself to melt unless picked up again within two turns?
!
! Of course, it isn't worth spending too long on Ruins, since it's only a
! somewhat dull and well-visited example. As soon as you start to feel
! comfortable with the way that an Inform game is constructed...
!
! ...have a go at writing one of your own. Good luck!
!==============================================================================!
! Every game needs a Story and Headline, and must include Parser and VerbLib.
! As DM <20>§7 except: Release, Serial and MAX_SCORE defined.
!
Constant Story "RUINS";
Constant Headline
"^An Interactive Worked Example^
Copyright (c) 1995 by Graham Nelson.^
Revisited 1998 by Roger Firth.^";
Release 2;
Serial "981117";
Constant MAX_SCORE 100;
Include "Parser";
Include "VerbLib";
!==============================================================================!
! Every game needs an Initialise routine, whose primary role is to set the
! player's location (i.e. you) at the start of the game.
! As DM <20>§7 and 19 except: StartDaemon() call added, no TitlePage().
!
[ Initialise;
location = Forest;
thedark.description =
"The darkness of ages presses in on you, and you feel claustrophobic.";
StartDaemon(Packing_Case);
"^^^^^Days of searching, days of thirsty hacking through the briars of
the forest, but at last your patience was rewarded. A discovery!^";
];
!==============================================================================!
! As DM <20>§20. PrintRank, if defined, is called when printing the score.
!
[ PrintRank;
print ", earning you the rank of ";
switch (score) {
0 to 9: "humble rainforest Tourist.";
10 to 39: "Investigator.";
40 to 69: "Acquisitor.";
70 to 99: "Archaeologist.";
100: "Master Archaeologist.";
}
];
!==============================================================================!
! As DM <20>§11 except: daemon added, to bring the immovable crate at the start,
! and take it (and you) away at the end.
!
Object Packing_Case "packing case"
with name 'packing' 'case' 'crate' 'box' 'strongbox',
initial
"Your packing case rests here, ready for you to hold any important
cultural finds you might make, for shipping back to civilisation.",
description
"A stout wooden crate, only slightly battered by its fall through
the branches.",
before [;
PushDir, Remove, Take:
"The case is too heavy to bother moving, as long as your
expedition is still incomplete.
It'll probably have to be taken out by helicopter.";
],
number 0, ! <-- used by the daemon
daemon [;
switch (++self.number) {
!-- Start of game
1: "^You hear the distant drone of an aeroplane.";
2: "^The plane is much louder, and seems to be flying very
low. Terrified birds rise in screeching flocks.";
3: move self to Forest;
if (location == Forest)
"^You involuntarily crouch as the plane flies directly
overhead, seemingly only inches above the treetops.
With a loud thump, something drops heavily to the
ground.";
"^Even underground, the engine roar is deafening.
Then there's a dull thump overhead and a little dust
falls from the ceiling.";
4: StopDaemon(self);
"^The roar dies away; calm returns to the forest.";
!-- End of game
5: "^A deep throbbing noise can be heard.";
6: "^A helicopter appears, hovering overhead.";
7: StopDaemon(self);
remove self;
deadflag = 2; ! <-- You win!
"^The helicopter lowers a rope; you tie it around the
packing case, which is hauled up into the air,
then a rope ladder comes dangling down.
With one last look around the clearing, you climb the
ladder into the waiting craft.
Back to civilisation, and a decent pint of Brakspear's!";
}
],
has container open openable static;
!==============================================================================!
! As DM <20>§8 except: started endgame processing when all treasure has been
! found. Added Bangle and Ruby treasures. "Undiscovered" is useful when
! ensuring that treasures can't be found twice.
!
Class Treasure
with cultural_value 10,
before [;
Remove, Take:
if (self in Packing_Case)
"Unpacking such a priceless artifact had best wait
until the Metropolitan Museum can do it.";
],
after [;
Insert:
if (second == Packing_Case) {
score = score + self.cultural_value;
print "Safely packed away.^";
}
if (score == MAX_SCORE) {
StartDaemon(Packing_Case);
"^The case is full, and you're feeling really homesick.
Now, how to get out of here?";
}
rtrue; ! <-- print nothing further
];
Object Undiscovered "hidden treasure room"
with description "How the heck did you get here!?.";
Treasure Statuette "pygmy statuette" Undiscovered
with name 'pygmy' 'statuette' 'statue' 'mayan' 'snake' 'spirit',
description
"A menacing, almost cartoon-like statuette of a pygmy spirit
with an enormous snake around its neck.";
Treasure Bangle "silver bangle" Undiscovered
with name 'silver' 'bangle' 'bracelet' 'ring',
cultural_value 20,
description "An intricately chased piece of jewellery.";
Treasure Ruby "blood-red ruby" Undiscovered
with name 'blood' 'red' 'blood-red' 'ruby' 'stone' 'jewel',
cultural_value 30,
description "A vivid red jewel, as large as a hen's egg.";
Treasure Honeycomb "lump of wax" Undiscovered
with name 'ancient' 'honeycomb' 'old' 'honey' 'comb' 'wax' 'lump',
cultural_value 40,
description
"On closer examination, the lump appears to be an old honeycomb.",
after [;
Eat:
"Perhaps the most expensive meal of your life.
The honey tastes odd, perhaps because it was used to store the
entrails of the king buried here, but still like honey.";
],
has edible;
!==============================================================================!
! Not in the DM as such, but useful (a) to distinguish room definitions from
! those of ordinary objects in the file, and (b) to provide light everywhere
! (unless overruled). See DM <20>§3.8.
!
Class Room
has light;
!==============================================================================!
! As DM <20>§7 and 10.
!
Room Forest "Dark Forest"
with name 'forest' 'jungle' 'clearing' 'olive' 'tree' 'trees' 'midges',
description
"In this tiny clearing, the pine-needle carpet is broken by
stone-cut steps leading down into the darkness.
Dark olive trees crowd in on all sides, the air steams with
warm recent rain, midges hang in the air.",
d_to Stone_Steps,
u_to
"The trees are spiny and you'd cut your hands to ribbons
trying to climb them.",
cant_go
"The rainforest-jungle is dense, and you haven't hacked through it
for days to abandon your discovery now.
Really, you need a good few artifacts to take back to civilisation
before you can justify giving up the expedition.";
!==============================================================================!
! As DM <20>§7 and 8 except: added discovery of Statuette on picking the
! mushroom.
!
Object Mushroom "speckled mushroom" Forest
with name 'speckled' 'mushroom' 'fungus' 'toadstool',
initial
"A speckled mushroom grows out of the sodden earth,
on a long stalk.",
description
"The mushroom is capped with blotches,
and you aren't at all sure it's not a toadstool.",
before [;
Eat:
if (random(100) > 30)
"You nibble at one corner,
but the curious taste repels you.";
deadflag = 1; ! <-- You die!
"The tiniest nibble is enough.
It was a toadstool, and a poisoned one at that!";
],
after [;
Drop:
"The mushroom drops to the ground, battered slightly.";
Take:
if (self has general)
"You pick up the slowly-disintegrating mushroom.";
give self general;
move Statuette to location;
"You stoop to pick the mushroom, neatly cleaving its thin stalk.
As you straighten up, you notice what looks like a
snake in the grass.";
],
has edible;
!==============================================================================!
! As DM <20>§7 and 8 except: replaced "first feet" by cobwebs.
!
Object Stone_Steps "stone-cut steps" Forest
with name 'stone' 'stone-cut' 'steps' 'stairs' 'cobwebs',
description [;
print "The cracked and worn steps descend into a dim chamber. ";
if (Square_Chamber has visited)
"The filmy cobwebs which once spanned the entrance
now hang in tatters.";
else
"Cobwebs form a flimsy barrier,
unlikely to impede your descent.";
],
door_to Square_Chamber, door_dir d_to,
has door open scenery;
!==============================================================================!
! As DM <20>§10 except: added examination of floor, word on east lintel,
! insect trails when mushroom bursts.
!
Room Square_Chamber "Square Chamber"
with name 'square' 'chamber' 'sand' 'dust' 'lintel' 'lintels' 'lintelled'
'east' 'south' 'doorways' 'doors' 'steps',
description
"A sunken, gloomy stone chamber, ten yards across,
whose floor is covered with fine sandy dust.
A shaft of sunlight cuts in from the steps above,
giving the chamber a diffuse light, but in the shadows low
lintelled doorways to east and south
lead into the deeper darkness of the Temple.",
before [;
Drop:
if (noun == mushroom)
<<Insert Mushroom Sunlight>>;
Examine:
if (noun == d_obj) {
if (Trails in location)
<<Examine Trails>>;
"Only your own footprints disturb the dust.";
}
Go: if (noun == e_obj) {
print "As you move into the eastern shadows, you seem to
glimpse the word SENE scratched on the lintel,
but before you can stop to inspect it more closely,
you find yourself in...^";
rfalse; ! <-- continue with the regular action
}
Insert:
if ((noun == Mushroom) && (second == Sunlight)) {
remove Mushroom;
move Trails to location;
"You drop the mushroom on the floor, in the glare of the
shaft of sunlight.
It bubbles obscenely, distends and then bursts into a
hundred tiny insects which run for the darkness in every
direction, leaving strange trails in the sandy floor.
No trace of fungus remain.";
}
],
u_to Forest,
e_to Inner_Web,
s_to Corridor;
!==============================================================================!
! As DM <20>§10.
!
Object Sunlight "shaft of sunlight" Square_Chamber
with name 'shaft' 'of' 'sunlight' 'sun' 'light' 'beam' 'sunbeam' 'ray'
'rays' 'sun^s',
description
"The shaft of sunlight glimmers motes of dust in the air,
making it seem almost solid.",
before [;
Examine, Search:
;
default:
"It's only an insubstantial shaft of sunlight.";
],
has scenery;
!==============================================================================!
! Not in the DM as such, but useful because employed twice. It seemed easier
! to have two sets of carvings rather just one plus a lot of if... tests.
! See DM <20>§3.8.
!
Class Carved
with name 'carved' 'inscription' 'inscriptions' 'carving' 'carvings'
'group' 'of',
initial "Carved inscriptions crowd the walls and ceiling.",
has container open pluralname static;
!==============================================================================!
! As DM <20>§10 except: changed to include insect trails suggesting a carving,
! and pressable carving which reveals cavity.
!
Carved Carvings "carved inscriptions" Square_Chamber
with description [;
print "The carvings cut deep into the rocks from which the
chamber is built, forming swirling sinuous patterns.";
if (cavity in self)
print " In the middle of one wall, a small cavity can be seen.";
new_line;
],
before [;
Push:
"Pressing the carved rock walls at random is unlikely
to be revealing.";
Touch:
"The carvings are warm and smooth to the touch.";
];
Carved Other_Carvings "carved inscriptions"
with description
"You stare at a group of carvings in the middle of one wall,
uncannily resembling the insects' trail left in the sand,
and feel your hand reaching out in that direction.",
before [;
Push:
remove Other_Carvings;
move Carvings to location;
move Cavity to Carvings;
"The carvings slide inwards, revealing a small cavity.";
Touch:
"The carvings seems to shift slightly under your hand.
Perhaps with a little more pressure...?";
];
Object Cavity "cavity among the carvings"
with name 'cavity' 'hole' 'deep' 'gloomy',
description
"The cavity, a few inches across, is deep and gloomy.",
has container open static;
Object Trails "trails in the sand"
with name 'trail' 'trails' 'sand' 'sandy' 'pattern' 'insect' 'insects',
initial "Strange trails swirl on the sandy floor.",
description [;
if (self has general) {
remove Carvings;
move Other_Carvings to location;
give self ~general;
}
"The insect trails seem to resemble one particular group of
carvings on the wall.";
],
has general pluralname static;
!==============================================================================!
! A Web room is implied at DM <20>§10, but not defined. Here, it's implemented
! as a simple dark maze of two rooms, once of which is home to the
! scuttling claws described in Example 37. The Bangle is here.
!
Class Maze
class Room,
with name 'dark' 'darkness' 'web',
description "Without a light, you'll never see anything here!",
cant_go
"Blundering around in the dark, it's impossible to tell
which direction is which.",
has ~light;
Maze Inner_Web "Web of Darkness"
with se_to Outer_Web,
ne_to Inner_Web,
n_to Inner_Web, s_to Inner_Web, e_to Inner_Web, w_to Inner_Web,
nw_to Inner_Web, sw_to Inner_Web,
u_to Inner_Web, d_to Inner_Web;
Maze Outer_Web "Web of Darkness"
with se_to Outer_Web,
ne_to Square_Chamber,
n_to Inner_Web, s_to Inner_Web, e_to Inner_Web, w_to Inner_Web,
nw_to Inner_Web, sw_to Inner_Web,
u_to Inner_Web, d_to Inner_Web,
before [;
Go: if ((noun == ne_obj) && (Bangle in Undiscovered)) {
move Bangle to player;
print "Sensing a slight draught you move in that direction,
stumbling over something lying on the ground in the dark.
Almost inadvertently you grab it before gratefully
emerging into the gloomy chamber.^";
rfalse; ! <-- continue with the regular action
}
];
!==============================================================================!
! As DM Ex.37 except: daemon runs only in the Inner_Web room.
!
Object Tiny_Claws "sound of tiny claws" thedark
with name 'tiny' 'claws' 'sound' 'of' 'scuttling' 'scuttle' 'things'
'creatures' 'insects' 'monsters',
article "the",
initial "Somewhere, tiny claws are scuttling.",
description "Without a light, you'll never see anything here!",
before [;
Attack: "They easily avoid your flailing about in the dark.";
Listen: "How intelligent they sound, for mere insects.";
Smell: "You can smell only your own fear.";
Taste, Touch:
"You wouldn't want to. Really.";
default:
"The creatures evade you, chittering.";
],
number 0, ! <-- used by the daemon
each_turn [; StartDaemon(self); ],
daemon [;
if (real_location ~= Inner_Web) { ! location just has "thedark"
self.number = 0;
StopDaemon(self);
rtrue; ! <-- ?
}
switch(++self.number) {
1: "^The scuttling draws a little nearer,
and your breathing grows load and hoarse.";
2: "^The perspiration of terror runs off your brow.
The creatures are almost here!";
3: "^You feel a tickling at your extremities and kick outward,
shaking something chitinous off.
Their sound alone is a menacing rasp.";
4: deadflag = 1; ! <-- You die!
"^Suddenly there is a tiny pain, of a hypodermic-sharp
fang at your calf.
Almost at once your limbs go into spasm, your shoulders
and knee-joints lock, your tongue swells...";
}
];
!==============================================================================!
! As DM <20>§12 except: added the moss concealing the Ruby.
!
Room Corridor "Stooped Corridor"
with name 'low' 'stooped' 'corridor',
description
"A low, square-cut corridor, running north to south,
stooping over you.
Patches of moss emit a faint green fluorescent glow,
just enough that you can see your surroundings.",
n_to Square_Chamber,
s_to Stone_Door,
has ;
Object Moss "mossy patches" Corridor
with name 'moss' 'mossy' 'patches' 'green' 'fluorescent' 'glow' 'clumps',
description [;
if (Ruby in Undiscovered)
"The moss grows in rough clumps, surprisingly thick in places.
Is that a hint of red hidden among all the greenery?";
"The moss, now somewhat raggy, grows in rough clumps.";
],
before [;
Search:
if (Ruby in Undiscovered) {
move Ruby to location;
"Something rolls from the moss onto the ground.";
}
],
has pluralname scenery;
!==============================================================================!
! As DM <20>§12. The key isn't actually defined in the DM.
!
Object Stone_Door "stone door"
with name 'stone' 'door' 'big' 'massive' 'yellow',
description "It's just a big stone door.",
when_closed "The passage is barred by a massive door of yellow stone.",
when_open "The massive yellow stone door is open.",
door_to
[; if (location == Corridor) return Shrine; return Corridor; ],
door_dir
[; if (location == Corridor) return s_to; return n_to; ],
with_key Stone_Key,
found_in Corridor Shrine,
has door lockable locked openable static;
Object Stone_Key "huge iron key" Cavity
with name 'huge' 'iron' 'key',
description "It must be a pretty big door to need a key like this.";
!==============================================================================!
! A Shrine room is implied at DM <20>§10, but not defined.
!
Room Shrine "Lofty Shrine"
with name 'lofty' 'shrine' 'haze' 'hazy' 'craggy' 'walls' 'quartz',
description
"For an underground chamber, the Shrine is remarkably high,
though its upper half is hazy and difficult to see clearly.
The craggy walls are polished natural rock, in which tiny
flecks of quartz catch the light of the flickering candle.",
n_to Stone_Door;
!==============================================================================!
! As DM <20>§14 except: added processing of objects placed on the altar.
!
Object Stone_Table "slab altar" Shrine
with name 'stone' 'table' 'slab' 'altar' 'great',
initial "A great stone slab of a table dominates the Shrine.",
description
"It's big enough to lie on, though in the circumstances
that might prove to be a A Really Bad Idea.",
after [;
Enter:
deadflag = 1; ! <-- You die!
"With astonishing speed, the horror-struck priest plucks
a bronze dagger from his tattered robe, and stabs you
in your sacrilegious heart.";
Receive:
remove noun;
switch (noun) {
Stone_Key:
move Honeycomb to player;
"His eyes dimly agleam with gratitude, the priest takes
the key and conceals it among his rags.
Then, lifting the candle, he carefully detaches a large
lump of the mottled wax, and gives it to you.";
Honeycomb:
move Honeycomb to player;
"~For returning the key, that is yours to keep.~";
}
print "The priest takes ", (the) noun, " and conceals it
among his rags.^";
rtrue; ! <-- print nothing further
],
has enterable supporter static;
!==============================================================================!
! Not in the DM as such, but added to provide light, and as a source for
! the Honeycomb.
!
Object Candle "flickering candle" Stone_Table
with name 'flickering' 'candle' 'flame',
initial
"A flickering candle at one end of the slab casts
grotesque shadows on the walls.",
description
"The candle is little more than a crudely moulded lump of wax.
Its texture is vaguely crystalline, with small fragments
embedded within.",
has static;
!==============================================================================!
! As DM <20>§16 except: the priest deal in objects, not the dictionary.
!
Object Priest "mummified priest" Shrine
with name 'mummified' 'priest' 'old' 'ancient' 'dessicated',
initial
"Behind the slab, a mummified priest stands waiting,
barely alive at best, impossibly venerable.",
description
"He is dessicated and hangs together only by will-power.
Though his first language is presumably local Mayan, you have
the curious instinct that he will understand your speech.",
life [;
Answer:
switch (noun) {
'hello', 'hi', 'bye', 'goodbye', 'good-bye', 'cheerio',
'thanks', 'thank', 'thankyou', 'you', 'cheers', 'ta':
"Silently, carefully, the priest nods his head.";
}
"The priest coughs, and almost falls apart.";
Ask:
switch (second) {
'king', 'tomb', 'shrine', 'temple', 'altar', 'slab':
"~The King (life! propserity! happiness!) is buried
deep under this Shrine, where you will never go.~";
'silver', 'bangle', 'bracelet', 'ring',
'blood', 'red', 'blood-red', 'ruby', 'stone', 'jewel',
'pygmy', 'statuette', 'statue', 'mayan', 'snake', 'spirit':
"~That is one of my people's sacred relics.~";
'ancient', 'honeycomb', 'old', 'honey', 'comb', 'wax',
'lump':
"~That is the most sacred of all my people's relics.~";
'huge', 'iron', 'key':
if (parent(Stone_Key) == nothing)
"~Now my people will be able to visit the Shrine.~";
"~That has been lost for generations.
My gratitude to anyone who returns it will be
overwhelming.~";
}
"~You must find your own answer.~";
Attack, Kiss:
remove self;
"The priest desiccates away into dust until nothing remains,
not a breeze or a bone.";
Give, Show:
switch (noun) {
Bangle, Ruby, Statuette:
"~I would be grateful if you placed that before me.~";
Honeycomb:
"~For returning the key, that is yours to keep.~";
Stone_Key:
"~I would be profoundly grateful if you placed that
before me.~";
}
"The priest is indifferent to earthly things.";
Tell:
"The priest has no interest in your sordid life.";
ThrowAt:
move noun to location;
<<Attack self>>;
],
orders [;
Go: "~I must not leave the Shrine.~";
NotUnderstood:
switch (noun) {
'hello', 'hi', 'bye', 'goodbye', 'good-bye', 'cheerio',
'thanks', 'thank', 'thankyou', 'you', 'cheers', 'ta':
"Silently, carefully, the priest nods his head.";
}
"~You speak in riddles~";
default:
"~It is not your orders that I serve.~";
],
has animate;
!==============================================================================!
! Every game needs to include the Grammar.
!
Include "Grammar";
!==============================================================================!
! Added to enable you to "pick" the mushroom (as well as the usual "take",
! "get", "pick up", etc). See DM <20>§26.
!
Extend "pick" * edible -> Take;
!==============================================================================!

1025
presets/zmachine/ruins2.inf Normal file

File diff suppressed because it is too large Load Diff

994
presets/zmachine/ruins3.inf Normal file
View File

@ -0,0 +1,994 @@
Constant Story "RUINS";
Constant Headline "^An Interactive Worked Example^
Copyright (c) 1999 by Angela M. Horns.^";
! ---------------------------------------------------------------------------- !
! This version recreated by Roger Firth in May 2001, using the simple
! (albeit time-consuming) process of combining the various fragments
! of "Ruins" quoted in Edition 4/1 of the Inform Designer's Manual.
!
! PLAYER
! lamp,dictionary,map
! GREAT PLAZA
! | mushroom,packing-case,camera,newspaper,steps
! |
! |
! SQUARE CHAMBER -------------------- WORMCAST
! | inscriptions,sunlight,(key) eggsac
! |
! |
! STOOPED CORRIDOR
! | statuette,door
! |
! |
! UPPER CANYON SHRINE
! | ball / \ paintings,altar,mask,(priest)
! | ---------- ----------
! | / \
! XIBALBÁ ANTECHAMBER
! | stela | cage,skeletons,(warthog)
! | |
! | |
! LOWER CANYON BURIAL SHAFT
! | chasm honeycomb
! |
! |
! PUMICE LEDGE
! bone
!
! ---------------------------------------------------------------------------- !
Constant MAX_CARRIED = 7; ! Defined in DM4 §22
Constant MAX_SCORE = 30; ! Defined in DM4 §22
Include "Parser";
Include "VerbLib";
! ---------------------------------------------------------------------------- !
! The TREASURE class definition.
!
! Defined in DM4 §5, modified in §23
Class Treasure
with before [;
Take, Remove:
if (self in packing_case)
"Unpacking such a priceless artifact had best wait until
the Carnegie Institution can do it.";
if (self.photographed_in_situ == false)
"This is the 1930s, not the bad old days. Taking an
artifact without recording its context is simply looting.";
Photograph:
if (self has moved) "What, and fake the archaeological record?";
if (self.photographed_in_situ) "Not again.";
],
after [;
Insert:
if (second == packing_case) {
score = score + self.cultural_value;
if (score == MAX_SCORE) {
deadflag = 2;
print_ret "As you carefully pack away ",
(the) noun,
" a red-tailed macaw flutters down from the
tree-tops, feathers heavy in the recent rain,
the sound of its beating wings almost
deafening, stone falling against stone...
As the skies clear, a crescent moon rises
above a peaceful jungle. It is the end of
March, 1938, and it is time to go home.";
}
"Safely packed away.";
}
Photograph:
self.photographed_in_situ = true;
],
cultural_value 5,
photographed_in_situ false;
! ---------------------------------------------------------------------------- !
! The game beings in the GRAND PLAZA.
!
! Defined in DM4 §4, modified in §8, §9 and §23
Object Forest "~Great Plaza~"
with description
"Or so your notes call this low escarpment of limestone, but the
rainforest has claimed it back. Dark olive trees crowd in on all
sides, the air steams with the mist of a warm recent rain, midges
hang in the air. ~Structure 10~ is a shambles of masonry which
might once have been a burial pyramid, and little survives
except stone-cut steps leading down into darkness below.",
d_to steps,
in_to steps,
u_to
"The trees are spiny and you'd cut your hands to ribbons
trying to climb them.",
cant_go
"The rainforest is dense, and you haven't hacked through it for days
to abandon your discovery now. Really, you need a good few
artifacts to take back to civilization before you can justify
giving up the expedition.",
before [; Listen: "Howler monkeys, bats, parrots, macaw."; ],
has light;
! Defined in DM4 §4, modified in Exercise 1 and §23
Object -> mushroom "speckled mushroom"
with name 'speckled' 'mushroom' 'fungus' 'toadstool',
initial
"A speckled mushroom grows out of the sodden earth, on
a long stalk.",
description
"The mushroom is capped with blotches, and you aren't
at all sure it's not a toadstool.",
after [;
Take:
if (self.mushroom_picked)
"You pick up the slowly-disintegrating mushroom.";
self.mushroom_picked = true;
"You pick the mushroom, neatly cleaving its thin stalk.";
Drop:
"The mushroom drops to the ground, battered slightly.";
Eat:
steps.rubble_filled = false;
"You nibble at one corner, unable to trace the source of an
acrid taste, distracted by the flight of a macaw overhead
which seems to burst out of the sun, the sound of the beating
of its wings almost deafening, stone falling against stone.";
],
mushroom_picked false,
has edible;
! Defined in DM4 §12
Object -> packing_case "packing case"
with name 'packing' 'case' 'box' 'strongbox',
initial
"Your packing case rests here, ready to hold any important
cultural finds you might make, for shipping back to civilisation.",
before [;
Take, Remove, PushDir:
"The case is too heavy to bother moving, as long as your
expedition is still incomplete.";
],
has static container open openable;
! Defined in DM4 §6
Object -> -> camera "wet-plate camera"
with name 'wet-plate' 'plate' 'wet' 'camera',
description
"A cumbersome, sturdy, stubborn wooden-framed wet plate
model: like all archaeologists, you have a love-hate
relationship with your camera.";
! Defined in DM4 §23
Object -> -> newspaper "month-old newspaper"
with name 'times' 'newspaper' 'paper' 'month-old' 'old',
description
"~The Times~ for 26 February, 1938, at once damp and brittle
after a month's exposure to the climate, which is much the way you
feel yourself. Perhaps there is fog in London.
Perhaps there are bombs.";
! Defined in DM4 §4, modified in §5 and §23
Object -> steps "stone-cut steps"
with name 'steps' 'stone' 'stairs' 'stone-cut' 'pyramid' 'burial'
'structure' 'ten' '10',
description [;
if (self.rubble_filled)
"Rubble blocks the way after only a few steps.";
print "The cracked and worn steps descend into a dim
chamber. Yours might ";
if (Square_Chamber hasnt visited)
print "be the first feet to tread";
else
print "have been the first feet to have trodden";
" them for five hundred years. On the top step is
inscribed the glyph Q1.";
],
door_to [;
if (self.rubble_filled)
"Rubble blocks the way after only a few steps.";
return Square_Chamber;
],
door_dir d_to,
rubble_filled true,
has scenery door open;
! ---------------------------------------------------------------------------- !
! The SQUARE CHAMBER.
!
! Defined in DM4 Exercise 2, modified in $8 and $9
Object Square_Chamber "Square Chamber"
with name 'lintelled' 'lintel' 'lintels' 'east' 'south' 'doorways',
description
"A sunken, gloomy stone chamber, ten yards across. A shaft of
sunlight cuts in from the steps above, giving the chamber a
diffuse light, but in the shadows low lintelled doorways to
east and south lead into the deeper darkness of the Temple.",
u_to Forest,
e_to Wormcast,
s_to Corridor,
before [;
Insert:
if (noun == eggsac && second == sunlight) {
remove eggsac;
move stone_key to self;
"You drop the eggsac into the glare of the shaft of
sunlight. It bubbles obscenely, distends and then bursts
into a hundred tiny insects which run in all directions
into the darkness. Only spatters of slime and a curious
yellow-stone key remain on the chamber floor.";
}
],
has light;
! Defined in DM4 §8
Object -> "carved inscriptions"
with name 'carved' 'inscriptions' 'carvings' 'marks' 'markings' 'symbols'
'moving' 'scuttling' 'crowd' 'of',
initial
"Carved inscriptions crowd the walls, floor and ceiling.",
description
"Each time you look at the carvings closely, they seem to be still.
But you have the uneasy feeling when you look away that they're
scuttling, moving about.
Two glyphs are prominent: Arrow and Circle.",
has static pluralname;
! Defined in DM4 §8
Object -> sunlight "shaft of sunlight"
with name 'shaft' 'of' 'sunlight' 'sun' 'light' 'beam' 'sunbeam'
'ray' 'rays' 'sun^s' 'sunlit' 'air' 'motes' 'dust',
description
"Motes of dust glimmer in the shaft of sunlit air, so that it seems
almost solid.",
before [;
Examine, Search:
;
default:
"It's only an insubstantial shaft of sunlight.";
],
has scenery;
! ---------------------------------------------------------------------------- !
! The STOOPED CORRIDOR.
!
! Defined in DM4 §13
Object Corridor "Stooped Corridor"
with description
"A low, square-cut corridor, running north to south,
stooping you over.",
n_to Square_Chamber,
s_to StoneDoor;
! Defined in DM4 §5
Treasure -> statuette "pygmy statuette"
with name 'snake' 'mayan' 'pygmy' 'spirit' 'precious' 'statuette',
initial
"A precious Mayan statuette rests here!",
description
"A menacing, almost cartoon-like statuette of a pygmy spirit
with a snake around its neck.";
! Defined in DM4 §13
Object -> StoneDoor "stone door"
with name 'door' 'massive' 'big' 'stone' 'yellow',
description
"It's just a big stone door.",
when_closed
"The passage is barred by a massive door of yellow stone.",
when_open
"The great yellow stone door is open.",
door_to [; if (self in Corridor) return Shrine; return Corridor; ],
door_dir [; if (self in Shrine) return n_to; return s_to; ],
with_key stone_key,
found_in Corridor Shrine,
has static door openable lockable locked;
! ---------------------------------------------------------------------------- !
! The SHRINE.
!
! Defined in DM4 §23
Object Shrine "Shrine"
with description
"This magnificent Shrine shows signs of being hollowed out from
already-existing limestone caves, especially in the western of the
two long eaves to the south.",
n_to StoneDoor,
se_to Antechamber,
sw_to
"The eaves taper out into a crevice which would wind further if it
weren't jammed tight with icicles. The glyph of the Crescent is
not quite obscured by ice.";
! Defined in DM4 §23
Object -> paintings "paintings"
with name 'painting' 'paintings' 'lord' 'captive',
initial
"Vividly busy paintings, of the armoured Lord trampling on a
captive, are almost too bright to look at, the graffiti of an
organised mob.",
description
"The flesh on the bodies is blood-red. The markers of the Long Count
date the event to 10 baktun 4 katun 0 tun 0 uinal 0 kin, the sort
of anniversary when one Lord would finally decapitate a captured
rival who had been ritually tortured over a period of some years,
in the Balkanised insanity of the Maya city states.",
has static;
! Defined in DM4 §12 and §15
Object -> stone_table "slab altar"
with name 'stone' 'table' 'slab' 'altar' 'great',
initial
"A great stone slab of a table, or altar, dominates the Shrine.",
has enterable supporter static;
! Defined in DM4 §11
Treasure -> -> mask "jade mosaic face-mask"
with name 'jade' 'mosaic' 'face-mask' 'mask' 'face',
initial
"Resting on the altar is a jade mosaic face-mask.",
description
"How exquisite it would look in the Museum.",
after [;
Wear:
move priest to Shrine;
if (location == Shrine)
"Looking through the obsidian eyeslits of the mosaic mask,
a ghostly presence reveals itself: a mummified calendrical
priest, attending your word.";
Disrobe:
remove priest;
],
cultural_value 10,
has clothing;
! ---------------------------------------------------------------------------- !
! The UPPER/NORTH CANYON.
!
! Defined in DM4 §23
Object Canyon_N "Upper End of Canyon"
with description
"The higher, broader northern end of the canyon rises only to an
uneven wall of volcanic karst.",
s_to Junction,
d_to Junction,
has light;
! Defined in DM4 §15, modified in Exercise 24 and §23
Object -> huge_ball "huge pumice-stone ball"
with name 'huge' 'pumice' 'pumice-stone' 'stone' 'ball',
initial
"A huge pumice-stone ball rests here, eight feet wide.",
description
"A good eight feet across, though fairly lightweight.",
before [;
PushDir:
if (location == Junction && second == ne_obj)
"The Shrine entrance is far less than eight feet wide.";
AllowPushDir();
rtrue;
Pull, Push, Turn:
"It wouldn't be so very hard to get rolling.";
Take, Remove:
"There's a lot of stone in an eight-foot sphere.";
],
after [;
PushDir:
if (second == n_obj) "You strain to push the ball uphill.";
if (second == u_obj) <<PushDir self n_obj>>;
if (second == s_obj) "The ball is hard to stop once underway.";
if (second == d_obj) <<PushDir self s_obj>>;
],
has static;
! ---------------------------------------------------------------------------- !
! The XIBALBÁ/JUNCTION.
! Defined in DM4 §23
Object Junction "Xibalb@'a"
with description
"Fifty metres beneath rainforest, and the sound of water is
everywhere: these deep, eroded limestone caves extend like
taproots. A slither northeast by a broad collapsed column of
ice-covered rock leads back to the Shrine, while a kind of canyon
floor extends uphill to the north and downwards to south,
pale white like shark's teeth in the diffused light from the
sodium lamp above.",
ne_to Shrine,
n_to Canyon_N,
u_to Canyon_N,
s_to Canyon_S,
d_to Canyon_S,
has light;
! Defined in DM4 §23
Treasure -> stela "stela"
with name 'stela' 'boundary' 'stone' 'marker',
initial
"A modest-sized stela, or boundary stone, rests on a ledge
at head height.",
description
"The carvings appear to warn that the boundary of Xibalb@'a,
Place of Fright, is near. The Bird glyph is prominent.";
! ---------------------------------------------------------------------------- !
! The LOWER/SOUTH CANYON.
!
! Defined in DM4 §23
Object Canyon_S "Lower End of Canyon"
with description
"At the lower, and narrower, southern end, the canyon stops dead at
a chasm of vertiginous blackness. Nothing can be seen or heard
from below.",
n_to Junction,
u_to Junction,
s_to "Into the chasm?",
d_to nothing,
has light;
! Defined in DM4 §12, modified in §21 and §23
Object -> chasm "horrifying chasm"
with name 'blackness' 'chasm' 'pit' 'horrifying' 'bottomless',
before [;
Enter:
deadflag = 3;
"You plummet through the silent void of darkness, cracking
your skull against an outcrop of rock. Amidst the pain and
redness, you dimly make out the God with the Owl-Headdress...";
JumpOver:
"It's far too wide.";
],
after [;
Receive:
remove noun;
print_ret (The) noun,
" tumbles silently into the darkness of the chasm.";
Search:
"The chasm is deep and murky.";
],
react_before [;
Jump:
<<Enter self>>;
Go:
if (noun == d_obj) <<Enter self>>;
],
each_turn [;
if (huge_ball in parent(self)) {
remove huge_ball;
Canyon_S.s_to = On_Ball;
Canyon_S.description =
"The southern end of the canyon now continues onto the
pumice-stone ball, wedged into the chasm.";
"^The pumice-stone ball rolls out of control down the last few
feet of the canyon before shuddering into the jaws of the
chasm, bouncing back a little and catching you a blow on the
side of the forehead. You slump forward, bleeding, and...
the pumice-stone shrinks, or else your hand grows, because you
seem now to be holding it, staring at Alligator, son of
seven-Macaw, across the ball-court of the Plaza, the heads of
his last opponents impaled on spikes, a congregation baying
for your blood, and there is nothing to do but to throw anyway,
and... but this is all nonsense,
and you have a splitting headache.";
}
],
has scenery open container;
! ---------------------------------------------------------------------------- !
! The PUMICE LEDGE.
!
! Defined in DM4 §23
Object On_Ball "Pumice-Stone Ledge"
with description
"An impromptu ledge formed by the pumice-stone ball, wedged into
place in the chasm. The canyon nevertheless ends here.",
n_to Canyon_S,
d_to Canyon_S,
u_to Canyon_S,
has light;
! Defined in DM4 §23
Treasure -> "incised bone"
with name 'incised' 'carved' 'bone',
initial
"Of all the sacrificial goods thrown into the chasm, perhaps
nothing will be reclaimed: nothing but an incised bone, lighter
than it looks, which projects from a pocket of wet silt in the
canyon wall.",
description
"A hand holding a brush pen appears from the jaws of Itzamn@'a,
inventor of writing, in his serpent form.";
! ---------------------------------------------------------------------------- !
! The ANTECHAMBER.
!
! Defined in DM4 §23
Object Antechamber "Antechamber"
with description
"The southeastern eaves of the Shrine make a curious antechamber.",
nw_to Shrine;
! Defined in DM4 Exercise 22, modified in Exercise 55
Object -> cage "iron cage"
with name 'iron' 'cage' 'bars' 'barred' 'frame' 'glyphs',
description
"The glyphs read: Bird Arrow Warthog.",
inside_description [;
if (self.floor_open)
"From the floor of the cage, an open earthen pit cuts
down into the burial chamber.";
"The bars of the cage surround you.";
],
when_open
"An iron-barred cage, large enough to stoop over inside, looms
ominously here, its door open. There are some glyphs on the
frame.",
when_closed
"The iron cage is closed.",
after [;
Enter:
print "The skeletons inhabiting the cage come alive, locking
bony hands about you, crushing and pummelling. You lose
consciousness, and when you recover something grotesque
and impossible has occurred...^";
move warthog to Antechamber;
remove skeletons;
give self ~open;
give warthog light;
self.after = 0;
ChangePlayer(warthog, 1);
<<Look>>;
],
react_before [;
Go:
if (noun == d_obj && self.floor_open) {
PlayerTo(Burial_Shaft);
rtrue;
}
],
floor_open false,
has enterable transparent container openable open static;
! Defined in Exercise 55
Object -> -> skeletons "skeletons"
with name 'skeletons' 'skeleton' 'bone' 'skull' 'bones' 'skulls',
article "deranged",
has pluralname static;
! ---------------------------------------------------------------------------- !
! The BURIAL SHAFT.
!
! Defined in Exercise 55
Object Burial_Shaft "Burial Shaft"
with description
"In your eventual field notes, this will read:
~A corbel-vaulted crypt with an impacted earthen plug as seal
above, and painted figures conjecturally representing the Nine
Lords of the Night. Dispersed bones appear to be those of one
elderly man and several child sacrifices, while other funerary
remains include jaguar paws.~ (In field notes, it is essential
not to give any sense of when you are scared witless.)",
n_to Wormcast,
u_to [;
cage.floor_open = true;
self.u_to = self.opened_u_to;
move selfobj to self;
print "Making a mighty warthog-leap, you butt at the earthen-plug
seal above the chamber, collapsing your world in ashes and
earth. Something lifeless and terribly heavy falls on top of
you: you lose consciousness, and when you recover, something
impossible and grotesque has happened...^";
ChangePlayer(selfobj);
give warthog ~light;
<<Look>>;
],
cant_go
"The architects of this chamber were less than generous in
providing exits. Some warthog seems to have burrowed in from the
north, though.",
before [; Jump: <<Go u_obj>>; ],
opened_u_to [; PlayerTo(cage); rtrue; ],
has light;
! Defined in DM4 §5
Treasure -> honeycomb "ancient honeycomb"
with name 'ancient' 'old' 'honey' 'honeycomb',
article "an",
initial
"An exquisitely preserved, ancient honeycomb rests here!",
description
"Perhaps some kind of funerary votive offering.",
after [;
Eat:
"Perhaps the most expensive meal of your life. The honey tastes
odd, perhaps because it was used to store the entrails of the
Lord buried here, but still like honey.";
],
has edible;
! ---------------------------------------------------------------------------- !
! The WORMCAST.
!
! Defined in DM4 Exercises 7 and 8, modified in Exercise 54
Object Wormcast "Wormcast"
with description
"A disturbed place of hollows carved like a spider's web, strands of
empty space hanging in stone. The only burrows wide enough to crawl
through begin by running northeast, south and upwards.",
w_to Square_Chamber,
s_to [;
print "The wormcast becomes slippery around you, as though your
body-heat is melting long hardened resins, and you shut your
eyes tightly as you burrow through darkness.^";
if (eggsac in player) return Square_Chamber;
return random(Square_Chamber, Corridor, Forest);
],
ne_to [; return self.s_to(); ],
u_to [; return self.s_to(); ],
cant_go [;
if (player ~= warthog)
"Though you begin to feel certain that something lies behind
and through the wormcast, this way must be an animal-run at
best: it's far too narrow for your armchair-archaeologist's
paunch.";
print "The wormcast becomes slippery around your warthog body, and
you squeal involuntarily as you burrow through the darkness,
falling finally southwards to...^";
PlayerTo(Burial_Shaft);
rtrue;
],
after [;
Drop:
move noun to Square_Chamber;
print_ret (The) noun,
" slips through one of the burrows and is quickly
lost from sight.";
],
has light;
! Defined in DM4 §23
Object -> eggsac "glistening white eggsac",
with name 'egg' 'sac' 'eggs' 'eggsac',
initial
"A glistening white eggsac, like a clump of frogspawn the size of a
beach ball, has adhered itself to something in a crevice in one
wall.",
after [; Take: "Oh my."; ],
react_before [;
Go:
if (location == Square_Chamber && noun == u_obj) {
deadflag = true;
"The moment that natural light falls upon the eggsac, it
bubbles obscenely and distends. Before you can throw it
away, it bursts into a hundred tiny, birth-hungry
insects...";
}
];
! ---------------------------------------------------------------------------- !
! These objects are moved into place as the game proceeds.
!
! Defined in DM4 §14, modified in §23
Object sodium_lamp "sodium lamp"
with name 'sodium' 'lamp' 'heavy',
describe [;
if (self has on)
"^The sodium lamp squats on the ground, burning away.";
"^The sodium lamp squats heavily on the ground.";
],
before [;
Examine:
print "It is a heavy-duty archaeologist's lamp, ";
if (self hasnt on) "currently off.";
if (self.battery_power < 10) "glowing a dim yellow.";
"blazing with brilliant yellow light.";
Burn:
<<SwitchOn self>>;
SwitchOn:
if (self.battery_power <= 0)
"Unfortunately, the battery seems to be dead.";
if (parent(self) hasnt supporter && self notin location)
"The lamp must be securely placed before being lit.";
Take, Remove:
if (self has on)
"The bulb's too delicate and the metal handle's too hot
to lift the lamp while it's switched on.";
PushDir:
if (location == Shrine && second == sw_obj)
"The nearest you can do is to push the sodium lamp to the
very lip of the Shrine, where the cave floor falls away.";
AllowPushDir();
rtrue;
],
after [;
SwitchOn:
give self light;
SwitchOff:
give self ~light;
],
daemon [;
if (self hasnt on) return;
if (--self.battery_power == 0) give self ~light ~on;
if (self in location) {
switch (self.battery_power) {
10: "^The sodium lamp is getting dimmer!";
5: "^The sodium lamp can't last much longer.";
0: "^The sodium lamp fades and suddenly dies.";
}
}
],
battery_power 100,
has switchable;
! Defined in DM4 §16
Object dictionary "Waldeck's Mayan dictionary"
with name 'dictionary' 'local' 'guide' 'book' 'mayan' 'waldeck'
'waldeck^s',
description
"Compiled from the unreliable lithographs of the legendary raconteur
and explorer ~Count~ Jean Frederic Maximilien Waldeck
(1766??-1875), this guide contains what little is known of the
glyphs used in the local ancient dialect.",
before [ w1 w2 glyph;
Consult:
wn = consult_from;
w1 = NextWord(); ! First word of subject
w2 = NextWord(); ! Second word (if any) of subject
if (consult_words==1 && w1~='glyph' or 'glyphs') glyph = w1;
else if (consult_words==2 && w1=='glyph') glyph = w2;
else if (consult_words==2 && w2=='glyph') glyph = w1;
else "Try ~look up <name of glyph> in book~.";
switch (glyph) {
'q1': "(This is one glyph you have memorised!)^^
Q1: ~sacred site~.";
'crescent': "Crescent: believed pronounced ~xibalba~,
though its meaning is unknown.";
'arrow': "Arrow: ~journey; becoming~.";
'skull': "Skull: ~death, doom; fate (not nec. bad)~.";
'circle': "Circle: ~the Sun; also life, lifetime~.";
'jaguar': "Jaguar: ~lord~.";
'monkey': "Monkey: ~priest?~.";
'bird': if (self.correct) "Bird: ~dead as a stone~.";
"Bird: ~rich, affluent?~.";
default: "That glyph is so far unrecorded.";
}
],
correct false,
has proper;
! Defined in DM4 §23
Object map "sketch-map of Quintana Roo"
with name 'map' 'sketch' 'sketch-map' 'quintana' 'roo',
description
"This map marks little more than the creek which brought you
here, off the south-east edge of Mexico and into deepest
rainforest, broken only by this raised plateau.";
! Defined in DM4 §23
Object stone_key "stone key"
with name 'stone' 'key';
! Defined in DM4 §17, modified in §18 and §23
Object priest "mummified priest"
with name 'mummified' 'priest',
initial
"Behind the slab, a mummified priest stands waiting,
barely alive at best, impossibly venerable.",
description
"He is desiccated and hangs together only by will-power. Though his
first language is presumably local Mayan, you have the curious
instinct that he will understand your speech.",
life [;
Answer:
"The priest coughs, and almost falls apart.";
Ask: switch (second) {
'dictionary', 'book':
if (dictionary.correct == false)
"~The ~bird~ glyph... very funny.~";
"~A dictionary? Really?~";
'glyph', 'glyphs', 'mayan', 'dialect':
"~In our culture, the Priests are ever literate.~";
'lord', 'tomb', 'shrine', 'temple':
"~This is a private matter.~";
'paintings':
"The calendrical priest frowns. ~10 baktun, 4 katun,
that makes 1,468,800 days since the beginning of time:
in your calendar 19 January 909.~";
'ruins':
"~The ruins will ever defeat thieves. In the underworld,
looters are tortured throughout eternity.~ A pause.
~As are archaeologists.~";
'web', 'wormcast':
"~No man can pass the Wormcast.~";
'xibalba':
if (Shrine.sw_to == Junction)
"The priest shakes his bony finger.";
Shrine.sw_to = Junction;
"The priest extends one bony finger southwest toward the
icicles, which vanish like frost as he speaks. ~Xibalb@'a,
the Underworld.~";
}
"~You must find your own answer.~";
Tell:
"The priest has no interest in your sordid life.";
Attack, Kiss:
remove self;
"The priest desiccates away into dust until nothing remains,
not a breeze nor a bone.";
ThrowAt:
move noun to location; <<Attack self>>;
Show, Give:
if (noun == dictionary && dictionary.correct == false) {
dictionary.correct = true;
"The priest reads a little of the book, laughing in a
hollow, whispering way. Unable to restrain his mirth,
he scratches in a correction somewhere before returning
the book.";
}
if (noun == newspaper)
"He looks at the date. ~12 baktun 16 katun 4 tun 1 uinal
12 kin~, he declares before browsing the front page.
~Ah. Progress, I see.~";
"The priest is not interested in earthly things.";
],
orders [;
Go:
"~I must not leave the Shrine.~";
NotUnderstood:
"~You speak in riddles.~";
default:
"~It is not your orders I serve.~";
],
has animate;
! Defined in DM4 Exercise 53
Object warthog "Warthog"
with name 'wart' 'hog' 'warthog',
initial
"A warthog snuffles and grunts about in the ashes.",
description
"Muddy and grunting.",
orders [;
Go, Look, Examine, Smell, Taste, Touch, Search,Jump, Enter:
rfalse;
Eat:
"You haven't the knack of snuffling up to food yet.";
default:
"Warthogs can't do anything so involved. If it weren't for the
nocturnal eyesight and the lost weight, they'd be worse off
all round than people.";
],
has animate proper;
! Defined in DM4 §8
Object low_mist "low mist"
with name 'low' 'swirling' 'mist',
description "The mist has an aroma reminiscent of tortilla.",
before [;
Examine, Search:
;
Smell:
<<Examine self>>;
default:
"The mist is too insubstantial.";
],
react_before [; Smell: if (noun == nothing) <<Smell self>>; ],
found_in Square_Chamber Forest,
has scenery;
! Defined in DM4 Exercise 46
Object tiny_claws "sound of tiny claws" thedark
with name 'tiny' 'claws' 'sound' 'of' 'scuttling' 'scuttle' 'things'
'creatures' 'monsters' 'insects',
article "the",
initial
"Somewhere, tiny claws are scuttling.",
before [;
Listen:
"How intelligent they sound, for mere insects.";
Touch, Taste:
"You wouldn't want to. Really.";
Smell:
"You can only smell your own fear.";
Attack:
"They easily evade your flailing about.";
default:
"The creatures evade you, chittering.";
],
each_turn [; StartDaemon(self); ],
daemon [;
if (location ~= thedark) {
self.turns_active = 0;
StopDaemon(self);
rtrue;
}
switch (++(self.turns_active)) {
1: "^The scuttling draws a little nearer, and your breathing
grows loud and hoarse.";
2: "^The perspiration of terror runs off your brow. The
creatures are almost here!";
3: "^You feel a tickling at your extremities and kick outward,
shaking something chitinous off. Their sound alone is a
menacing rasp.";
4: deadflag = true;
"^Suddenly there is a tiny pain, of a hypodermic-sharp fang
at your calf. Almost at once your limbs go into spasm, your
shoulders and knee-joints lock, your tongue swells...";
}
],
turns_active 0;
! ---------------------------------------------------------------------------- !
! Utility routines.
! Defined in DM4 §4, modified in §21 and §23
[ Initialise;
TitlePage();
location = Forest;
move map to player;
move sodium_lamp to player;
move dictionary to player;
StartDaemon(sodium_lamp);
thedark.description =
"The darkness of ages presses in on you, and you feel
claustrophobic.";
"^^^Days of searching, days of thirsty hacking through the briars of
the forest, but at last your patience was rewarded. A discovery!^";
];
! Defined in DM4 Exercise 123
[ TitlePage i;
@erase_window -1; print "^^^^^^^^^^^^^";
i = 0->33; if (i > 30) i = (i-30)/2;
style bold; font off; spaces(i);
print " RUINS^";
style roman; print "^^"; spaces(i);
print "[Please press SPACE to begin.]^";
font on;
box "But Alligator was not digging the bottom of the hole"
"Which was to be his grave,"
"But rather he was digging his own hole"
"As a shelter for himself."
""
"-- from the Popol Vuh";
@read_char 1 -> i;
@erase_window -1;
];
! Defined in DM4 §22
[ PrintRank;
print ", earning you the rank of ";
if (score == 30) "Director of the Carnegie Institution.";
if (score >= 20) "Archaeologist.";
if (score >= 10) "Curiosity-seeker.";
if (score >= 5) "Explorer.";
"Tourist.";
];
! Defined in DM4 §21
[ DeathMessage;
if (deadflag == 3) print "You have been captured";
];
! ---------------------------------------------------------------------------- !
Include "Grammar";
! Defined in DM4 §6
[ PhotographSub;
if (camera notin player) "Not without the use of your camera.";
if (noun == player) "Best not. You haven't shaved since Mexico.";
if (children(player) > 1)
"Photography is a cumbersome business, needing the use of both
hands. You'll have to put everything else down.";
if (location == Forest) "In this rain-soaked forest, best not.";
if (location == thedark) "It is far too dark.";
if (AfterRoutines()) return;
print_ret "You set up the elephantine, large-format, wet-plate camera,
adjust the sodium lamp and make a patient exposure of ",
(the) noun, ".";
];
Verb 'photograph'
* noun -> Photograph;
! ---------------------------------------------------------------------------- !

View File

@ -0,0 +1,942 @@
! ----------------------------------------------------------------------------
! Toyshop 961111 One of the standard Inform 6 example games
!
! This is not a real game. The main example game for Inform is "Advent",
! a port of Colossal Cave. Since that's something of an antique, and most
! of the objects in it are rather simple, this is a collection of more
! exotic features and peculiar objects. Note that "Advent" has plenty of
! interesting doors, a good lantern and bottled oil and water, so those
! won't be part of the Toyshop.
!
! Needs Inform 6 with library 6/1 or later to compile.
!
! To win, simply find 6 interesting things to do and leave by the main exit!
!
! Object Is an example of...
!
! >SA satchel Container into which the game silently puts things
! >HE helium balloon Something moving under the control of a daemon
! >CA little red car Vehicle, and pushable from place to place
! >PF padded floor Scenery present in several rooms at once
! >GR hand grenade Timed events: a grenade and its pin
! >MA matchbook Simple fire and matches; changing inventory styles
! >WC white candles A stock of objects identical to each other
! >GL white gloves Two independent objects which can behave as a pair
! >CO green cone Easy before and after rules
! >HW high window Starting and stopping daemons
! >BC bolted cupboard A typical locked container (with key)
! >GB glass box Container light can get through
! >SB steel box Container light can't get through
! >BL building blocks A complicated class definition; piles of objects
! >CH Christopher Someone you can talk to, and persuade to do things
! >OF Office Rules about moving in a particular direction
! >TB toothed bag A container with ideas about what it will allow
! >SL spirit level Something to put on top of things
! >BB blackboard A blackboard to write messages on
!
! (The code is marked with >SA and so on for easy access with a text editor)
! ----------------------------------------------------------------------------
Constant DEBUG;
Constant Story "TOYSHOP";
Constant Headline "^An Interactive Demonstration^
Copyright (c) 1994 by Graham Nelson. All rights given away.^";
Release 4;
Serial "961111"; ! This sets the serial date to the date of this source
! file, not to the date of compilation.
! Now we serve notice to Inform that we do not wish to use the standard
! routine for the Burn action, and will instead be defining our own:
Replace BurnSub;
! Next include the first of the three standard library files:
Include "Parser";
! ----------------------------------------------------------------------------
! >SA Ungenerously, the player can only carry at most 4 things, but there's
! a satchel to carry other things around in...
! ----------------------------------------------------------------------------
Constant MAX_CARRIED = 4;
Constant SACK_OBJECT = satchel;
Object satchel "satchel"
with description "Big and with a smile painted on it.",
name "satchel", article "your",
when_closed "Your satchel lies on the floor.",
when_open "Your satchel lies open on the floor.",
has container open openable;
! We're going to use the most elaborate scoring system the
! library provides (even though we're going to make the six tasks all
! score only 1 point each), so we define all this...
Constant TASKS_PROVIDED;
Constant NUMBER_TASKS = 6;
Array task_scores -> 1 1 1 1 1 1;
Constant MAX_SCORE = 6;
! And include the library of standard verbs and actions.
Include "VerbLib";
! ----------------------------------------------------------------------------
! Off we go into the Toyshop...
! ----------------------------------------------------------------------------
Class Toyroom
has light;
Toyroom Toyshop "Toyshop"
with description
"The centre of a long east-west hall. Shelves are lined
with toys, painted clowns face you from the walls and
the floor is lightly padded with colourful mats. A doorway
leads north, with a red warning triangle above it.",
name "clowns" "painted" "shelves" "triangle",
e_to East_End, w_to West_End, n_to Danger_Zone;
Object -> chair "high chair"
with name "chair" "high"
has supporter enterable;
! ----------------------------------------------------------------------------
! >HE The balloon is completely self-contained as a piece of code, except
! that it does not set itself going (though even this could have been
! arranged): it is set going in the Initialise() routine.
!
! Notice that the "after" for Drop takes away the "moved" attribute.
! This is one way to ensure that the "initial" message will always be
! the one displayed. (Alternatively, we could have given it a "describe"
! property.)
! ----------------------------------------------------------------------------
Object -> balloon "helium balloon"
with description "Blue, with a yellow smile.",
name "helium" "balloon" "blue" "string",
initial "A balloon nestles on the ceiling, its long string hanging.",
before
[; Attack: remove self; StopDaemon(self);
"Easily, you burst the balloon. Pop!^^
Shame it was irreplaceable, really.";
],
after
[; Take: "You take the balloon by its string. It's buoyant!";
Drop: give balloon ~moved;
"The balloon rises gracefully to the ceiling.";
],
daemon
[ from_room to_room;
if (random(3)~=1) rfalse;
from_room=parent(self);
if (from_room==East_End or West_End) to_room=Toyshop;
if (from_room==Toyshop)
{ if (random(2)==1) to_room=East_End;
else to_room=West_End;
}
if (to_room==0) rfalse;
move self to to_room;
if (location==from_room)
"^A breeze blows the balloon away to the ", (name) to_room, ".";
if (location==to_room)
"^A breeze blows the balloon in from the ", (name) from_room, ".";
];
! ----------------------------------------------------------------------------
! >CA There are two exceptions to the ordinary before/after rules, for
! vehicles and things which can be pushed from place to place: this car
! demonstrates both at once.
!
! The "before" for PushDir (push in a named direction) must call
! AllowPushDir and then return true to signify that the push is legal.
!
! The "before" for Go must return true to signify that travelling in
! the object is legal. (Note that it must also be enterable.)
! ----------------------------------------------------------------------------
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!";
! ----------------------------------------------------------------------------
! >PF An example of an object spread across several (three) rooms:
! ----------------------------------------------------------------------------
Object padded_floor "padded floor"
with name "padded" "floor" "mats" "padding",
description "To protect little children and adventurers.",
before
[; Take: "It is protected from little children and adventurers.";
],
found_in East_End Toyshop West_End
has scenery;
! ----------------------------------------------------------------------------
Toyroom Danger_Zone "Danger Zone"
with description
"This is the Danger Zone, which you should know better
than to go into. A single door leads back south.",
s_to Toyshop;
! ----------------------------------------------------------------------------
! >GR A classic example of a timer (or, as some people call them and
! appropriately so in this case, a fuse). To demonstrate stopping
! a timer before the alarm (and for fun), there is also a pin:
! ----------------------------------------------------------------------------
Object -> grenade "nasty-looking hand grenade"
with name "hand" "grenade" "nasty" "nasty-looking",
initial "A nasty-looking hand grenade (there is no other kind)
rolls about irresponsibly on the floor.",
description "Not recommended for children under 90.",
before
[; Pull: if (self has general) "Too late for that.";
StartTimer(self, 5); give self general;
move the_pin to player;
"You pull the pin out, an irrevocable act.";
],
time_left 0,
time_out
[; deadflag=1;
"^An immense explosion suddenly demolishes the toyshop!^^
Will you never learn?";
],
has transparent;
Object -> -> the_pin "pin"
with name "pin",
description "The pin is designed to be easy to pull.",
before
[; Take, Pull: if (self in grenade) <<Pull grenade>>;
Insert:
if (self notin grenade && second==grenade)
{ StopTimer(grenade); move self to grenade;
give grenade ~general;
"Amazing! You got the pin back into the grenade!";
}
];
! ----------------------------------------------------------------------------
! >MA This is a matchbook of five matches, which is quite simple in that you
! can only actually have one match at a time: otherwise, it's quite
! a full implementation. Note that the inventory lines for the match
! and the matchbook are coded here. Note also that the "match" object
! returns to the book even when the book is empty, so that the parser
! will still understand requests for matches - which the "before" rule,
! which automatically removes matches when needed, can then turn down.
!
! The matchbook has a daemon whose job is to tidy up lost matches. One
! might expect this rule to be coded with an "after" routine, to trap
! the player dropping matches. But suppose there were a magpie in the
! game, and it flew down and stole the match but left the matchbook!
! As it happens there isn't, but this is better form.
! ----------------------------------------------------------------------------
Object -> matchbook "matchbook"
with name "matchbook" "book" "matches",
number 5,
before
[; Burn: if (match has light)
{ remove match; remove matchbook;
"What a waste of matches!";
}
],
invent
[; if (inventory_stage==2)
{ switch(self.number)
{ 0: print " (empty)";
1: print " (1 match left)";
default: print " (", self.number, " matches left)";
}
}
],
description
[; print "The cover advertisement reads
~Curses - Adventure of a Lunchtime~. The book ";
switch(self.number)
{ 0: "is empty.";
1: "has a single match left.";
default:
print_ret "contains ", self.number, " matches.";
}
],
daemon
[; if (match notin matchbook && match notin player)
{ move match to matchbook;
if (match has light)
{ give match ~light; StopTimer(match); }
StopDaemon(self);
}
],
has transparent;
Object -> -> match "match"
with parse_name
[ i j; if (self has light) j='burning'; else j='unlit';
while (NextWord()=='match' or j) i++;
return i;
],
article "an",
before
[ i; if (self in matchbook)
{ i=matchbook.number;
if (i==0) "There are no matches left in the book.";
i--; matchbook.number=i;
move self to player; StartDaemon(matchbook);
print "(taking a match from the book, which ";
if (i==0) print "is now empty)^";
if (i==1) print "has one more left)^";
if (i>1) print "has ", i, " left)^";
self.article = "an";
}
Take, Remove: if (self in player) "Done.";
Burn:
if (self has light) "The match is already alight.";
if (matchbook notin player)
"You need the matchbook to strike the match.";
give self light; StartTimer(self, 2+random(3));
self.article = "a";
"You strike the match.";
],
short_name
[; if (self has light) print "burning match";
else print "unlit match";
rtrue;
],
time_left,
time_out
[; move self to matchbook; give self ~light;
"^You drop the match as the flame reaches your finger.";
];
! ----------------------------------------------------------------------------
! >WC A box of eight candles.
!
! This is a simple way to code up duplicate objects. For one thing,
! > take candles
! does not quite behave as we would hope: it'll only pick up one candle
! (though "> take four candles" will work). See the "Block" class
! below for a way to make good.
!
! If we had needed a much greater number of candles, we could have used
! object creation and destruction during play. See the "Ticket" class
! from the "Balances" example game.
! ----------------------------------------------------------------------------
Class Candle
with name "wax" "candle" "candles",
short_name "wax candle", plural "wax candles",
description "It looks just like all the other candles.",
before
[; Burn: "Disappointingly, the wick refuses to burn."; ];
Object -> "grey tin box"
with name "tin" "box" "grey",
description
"A grey tin box of ~Major's Candles~.",
has container openable;
Candle -> ->;
Candle -> ->;
Candle -> ->;
Candle -> ->;
Candle -> ->;
Candle -> ->;
Candle -> ->;
Candle -> ->;
Toyroom East_End "East End"
with name "dolls" "nurses",
description
"The eastern end of the toyshop is pink, and dolls and
nurses line the shelves right up to the high window.
A dark doorway leads to a northern side chamber.",
w_to Toyshop, n_to DarkRoom;
! ----------------------------------------------------------------------------
! >GL The following example, suggested to the author by Richard Tucker,
! demonstrates an apparently tricky case of objects with associated
! sub-objects. The pair of white gloves behaves just like any other item
! of clothing - but the player can also use the left and right gloves
! independently, can take away or wear only one and so on. When they
! come back together (even in a cupboard, say, or on a mantelpiece)
! they are called a pair again.
!
! We can do this with only three objects, one daemon and one rule.
!
! When the gloves are together, and the player refers to an individual
! glove, the before rule splits up the pair and starts the daemon.
! Once active, the daemon tries every turn to re-join them into a pair.
! (If it succeeds, it turns itself off.)
!
! Note that the "pair of gloves" object has the "general" attribute exactly
! when the gloves are apart. Otherwise the pair-object contains both
! glove objects, and has "transparent" so that the parser knows the player
! can see and refer to them.
! ----------------------------------------------------------------------------
Object -> gloves "white gloves"
with article "a pair of",
name "white" "gloves" "pair" "of",
daemon
[; if (parent(right_glove) ~= parent(left_glove)) return;
if ((left_glove has worn && right_glove hasnt worn)
|| (left_glove hasnt worn && right_glove has worn)) return;
if (left_glove has worn) give gloves worn; else give gloves ~worn;
move gloves to parent(right_glove); give gloves ~general;
move right_glove to gloves; move left_glove to gloves;
give right_glove ~worn; give left_glove ~worn;
StopDaemon(self);
],
has clothing transparent;
Class Glove
with article "the",
name "white" "glove",
before
[; if (self notin gloves) rfalse;
move left_glove to parent(gloves); move right_glove to parent(gloves);
if (gloves has worn)
{ give left_glove worn; give right_glove worn;
}
give gloves general; remove gloves;
StartDaemon(gloves);
],
has clothing;
Glove -> -> left_glove "left glove"
with description "White silk, monogrammed with a scarlet R.",
name "left";
Glove -> -> right_glove "right glove"
with description "White silk, monogrammed with a scarlet T.",
name "right";
! ----------------------------------------------------------------------------
! ...and that's all: the "gloves" code is self-contained.
!
! Exercise for the reader: hide a (sharp) jewel inside the left glove.
! (Alter the glove class to make them containers open only when not worn.
! Add two "after" rules to warn the player if there's something sharp
! to the touch, one for putting on the pair of gloves, one for putting on
! an individual glove.)
! ----------------------------------------------------------------------------
! ----------------------------------------------------------------------------
! >CO A traditional Inform example object:
! ----------------------------------------------------------------------------
Object -> cone "green cone"
with name "green" "cone" "emerald" "marzipan",
describe
[; if (cone has moved)
"^A misshapen cone of green marzipan sits here.";
"^Nearby is an emerald green cone, one foot high.";
],
description "The cone seems to be made of emerald-coloured
marzipan.",
before
[; Eat: if (random(100) <= 30)
{ deadflag = 1;
"Unfortunately, you seem to be allergic to almonds.";
}
"You nibble at a corner of the cone.";
],
after
[; Take: "Taken. (Your hands are smeared with marzipan.)";
Drop: cone.description = "The cone is a vague green mess.";
"The cone drops to the floor and sags a little.";
],
has edible;
! ----------------------------------------------------------------------------
! >HW It's the draught from this slightly-concealed window which propels the
! balloon:
! ----------------------------------------------------------------------------
Object -> "high window"
with name "high" "window",
description
[; print "A narrow, high window ";
if (self has open) "through which a draught blows.";
"which is closed.";
],
after
[; Open: StartDaemon(balloon);
Close: Achieved(2); StopDaemon(balloon);
],
has scenery openable open;
! ----------------------------------------------------------------------------
! >BC A typical locked container, containing a rather pathetic prize...
! ----------------------------------------------------------------------------
Object -> "bolted cupboard"
with name "bolted" "cupboard",
describe
[; if (self hasnt open) "^A shut cupboard is bolted to one wall.";
"^Bolted up on one wall is an open cupboard.";
],
with_key key
has locked container openable lockable static;
Object -> -> "boiled sweet"
with name "boiled" "sweet",
after
[; Eat: Achieved(0);
"It takes an irritatingly long time to eat.";
],
has edible;
! ----------------------------------------------------------------------------
! >GB This is really to demonstrate "transparent". Shutting up the glowing
! >SB ball in the glass box does not make the room go dark: shutting it up
! in the steel box does. Also, you can examine things in the glass box
! even when the glass box is shut.
! (Note also that the Dark Room is explicitly told not to have "light",
! which it would otherwise inherit from the "Toyroom" class.)
! ----------------------------------------------------------------------------
Toyroom DarkRoom "Dark Room"
with description "A featureless storage room, hardly worth illumination.",
cant_go "The only exit is back south.",
s_to East_End
has ~light;
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;
Toyroom West_End "West End"
with name "soldiers" "model" "aircraft" "planes",
description
"The western end of the toyshop is blue, and soldiers and
model aircraft line the shelves. A small office lies to
the south.",
e_to Toyshop, s_to Office;
! ----------------------------------------------------------------------------
! >BL The class Block provides for stackable building blocks.
!
! Note that with the "describe" routine missing, the game would still
! correctly describe stacks of blocks: just a little less elegantly.
! ----------------------------------------------------------------------------
Class Block
with description "Just a child's building block, four inches on a side.",
! The parse_name routine below ensures that "take blocks"
! works correctly:
parse_name
[ i j;
for (::)
{ j=NextWord();
if (j=='block' or 'cube' or 'building' or (self.name)) i++;
else
{ if (j=='blocks' or 'cubes')
{ parser_action=##PluralFound; i++; }
else return i;
}
}
],
describe
[ c d e;
d = child(self);
while (d~=0 && d ofclass Block)
{ c++; e=d; d=child(d); }
if (c==0) rfalse;
print "^There is a pile of building blocks here, ";
while (c>=0)
{ print (address) e.name; ! Sneaky: print the "name" out
if (c>0) print " on "; ! using its dictionary address
c--; e=parent(e);
}
".";
],
before
[ c;
PutOn:
if (second ofclass Block)
{ if (child(second)~=0 && child(second) ofclass Block)
"There's no room on the top of one cube for two more, side
by side.";
}
else
print "(They're really intended
to be piled on top of each other.)^";
c=second; while (c ofclass Block) c=parent(c);
if (c~=location or mantelpiece) "Too unsteady a base.";
],
after
[ c stack;
PutOn:
stack=noun;
while (parent(stack) ofclass Block) { stack=parent(stack); c++; }
if (c<2)
{ if (Chris has general) rtrue;
rfalse;
}
if (c==2) "The pile of three cubes is unsteady, but viable.";
if (Chris has general)
{ Achieved(3);
"^Expertly he keeps the pile of four cubes stable.";
}
stack=noun;
while (parent(stack) ofclass Block)
{ c=stack; stack=parent(stack); move c to location; }
"The pile of four cubes wobbles, wobbles, steadies... and suddenly
collapses!";
Take:
stack=child(noun); if (stack==0) rfalse;
while (stack~=0)
{ c=stack; stack=child(stack); move c to location; }
"Your pile of cubes is collapsed as a result.";
],
has supporter;
Block -> "green cube"
with name "green";
Block -> "red cube"
with name "red";
Block -> "yellow cube"
with name "yellow";
Block -> "blue cube"
with name "blue";
! ----------------------------------------------------------------------------
! >CH A guest appearance by my cousin Christopher, aged six (*), who plays
! with one thing at a time (easily forgetting which). Being "transparent"
! (no reflection on him!) means the parser allows the player to examine
! whatever he's playing with... but not to take it from him.
! (* In 1993, when this game was first written.)
! ----------------------------------------------------------------------------
Object -> Chris "Christopher"
with name "child" "boy" "chris" "christopher",
describe
[; print "^A boy called Christopher sits here";
if (child(Chris) ~= nothing)
print ", playing with ", (a) child(Chris);
".";
],
life
[ x;
Ask:
switch(second)
{ 'juggling', 'fluorescent', 'ball': "~That's mine!~";
'helium', 'balloon': "Christopher yawns.";
'cube', 'cubes': "~Bet I can make a higher tower than you.~";
'toys', 'toyshop': "~Isn't it fabulous here?~";
default: "~Dunno.~";
}
Answer:
switch(noun)
{ 'hello', 'hallo', 'hi':
"~Hello,~ says Christopher cheerfully.";
default: "Christopher seems preoccupied.";
}
Attack: remove self;
"Christopher makes a run for it, effortlessly slipping past you!";
Kiss: "~That's soppy, that is.~";
Give:
if (noun==balloon) "He's too bored by the balloon.";
x=child(Chris);
if (x~=0)
{ move x to location;
print "He forgets about ", (the) x, " and ";
}
else print "He ";
print "eagerly grabs ", (the) noun; move noun to Chris; ".";
],
orders
[; Drop: if (noun in Chris) "~Won't! It's mine!~";
Take: "Christopher can't be bothered.";
Give: if (second==player) "~Get your own!~";
Go: "~But I like it here!~";
PutOn: if (noun notin Chris) "He is mightily confused.";
if (~~(noun ofclass Block && second ofclass Block))
"He can't see the point of this.";
print "Christopher leans over with great concentration
and does so.^";
move noun to player; give self general;
<PutOn noun second>;
give self ~general; rtrue;
],
each_turn
[; if (random(3)~=1) rtrue;
print "^Christopher ";
switch(random(4))
{ 1: "yawns."; 2: "frowns.";
3: "stretches."; 4: "hums tonelessly.";
}
],
has animate proper transparent;
Object "fluorescent juggling ball" Chris
with initial "On the floor is a fluorescent juggling ball!",
name "fluorescent" "juggling" "ball",
description "It glows with soft light."
has light;
! ----------------------------------------------------------------------------
! >OF A simple movement rule.
! ----------------------------------------------------------------------------
Toyroom Office "Office"
with description
"A small, grey office, with a broad stone mantelpiece.
In the east wall is a doorway marked ~Exit~, and the Toyshop,
of course, lies north.",
cant_go "The Toyshop floor lies north.",
n_to West_End,
e_to
[; if (score~=MAX_SCORE)
"A gong sounds. ~You cannot leave the Toyshop until
you have done six interesting things!~";
deadflag=2;
"A gong sounds. ~Congratulations! You may now leave the Toyshop
and begin writing your own Inform game!~";
];
! ----------------------------------------------------------------------------
! >TB A somewhat acquisitive container... but it can be taught to behave.
! ----------------------------------------------------------------------------
Object -> "toothed bag"
with name "toothed" "bag",
initial "In one corner is a curious, toothed bag.",
description "A capacious bag with a toothed mouth.",
before
[; LetGo: "The bag defiantly bites itself
shut on your hand until you desist.";
],
after
[; Receive:
if (noun==cone)
{ self.before=0; self.after=0;
"The bag wriggles interminably as it tries
to eat the enormous mass of marzipan. That'll
teach it.";
}
"The bag wriggles hideously as it swallows ", (the) noun, ".";
],
has container open;
! ----------------------------------------------------------------------------
! >SL Which can be put on the mantelpiece: the first time this is done, the
! game randomly decides which end is higher, and sticks to this decision.
! ----------------------------------------------------------------------------
Object -> -> spirit_level "spirit level"
with name "spirit" "level" "wood" "flask",
number 0,
description "A length of wood containing a flask of viscous
green liquid, in which a bubble is trapped.",
before
[; Examine:
if (spirit_level in mantelpiece)
{ print "The bubble is at the ";
if (self.number==1) "northeast end.";
"southeast end.";
}
],
after
[; PutOn: if (second~=mantelpiece) rfalse;
if (spirit_level hasnt general) self.number=random(2);
give spirit_level general; Achieved(4);
print "You put the spirit level on the mantelpiece,
and the bubble slowly drifts towards the ";
if (self.number==1) "northeast.";
"southwest.";
];
Object -> mantelpiece "mantelpiece"
with name "mantel" "mantle" "piece" "mantelpiece"
has scenery supporter;
Object -> -> key "iron key"
with name "iron" "key", article "an";
! ----------------------------------------------------------------------------
! >BB A blackboard which can be written on or wiped clear.
! ----------------------------------------------------------------------------
Object -> -> chalk "stick of chalk"
with name "stick" "of" "chalk";
Array boardtext string 64;
Object -> blackboard "blackboard"
with name "board" "blackboard" "black",
describe
[; <<Examine self>>; ],
before
[ i f;
Examine:
for (i=1:i<=boardtext->0:i++)
if (boardtext->i~=' ' or 0) f=1;
if (f==0)
{ print "^The office blackboard is wiped clean.^";
if (self hasnt general)
{ give self general;
"^[To write on it, try > write ~message...~]";
}
rtrue;
}
print "^The office blackboard bears the message:^ ";
for (i=1:i<=boardtext->0:i++)
{ f=boardtext->i;
if (f~=0) print (char) f;
}
new_line; rtrue;
Rub: for (i=1:i<=boardtext->0:i++) boardtext->i = ' ';
"You wipe the blackboard clean.";
],
has static;
Global from_char; Global to_char;
[ 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 1;
}
return -1;
];
[ WriteSub i j;
if (chalk notin player) "You're holding nothing to write with.";
if (blackboard notin location) "The blackboard is elsewhere.";
for (i=from_char,j=1:i<=to_char && j<boardtext->0:i++,j++)
boardtext->j = buffer->i;
for (:j<boardtext->0:j++) boardtext->j=0;
Achieved(5);
<<Examine blackboard>>;
];
! ----------------------------------------------------------------------------
! End of object definitions.
! ----------------------------------------------------------------------------
!
! Routines and Entry Points
!
! (Fuller examples of which can be found in the "Advent" example game.)
!
! Initialise() just sets up the initial state of the game.
! We are required to set "location" to the start location of the
! player; the rest is optional.
!
! StartDaemon(balloon) starts the process which blows the balloon back
! and forth.
! ----------------------------------------------------------------------------
[ Initialise;
location=chair; move satchel to player;
print "^^^^^~What's so special about Inform,~ is the last thing you
remember saying to the mad alchemist. Big mistake...^^";
StartDaemon(balloon);
];
! ----------------------------------------------------------------------------
! Print names of tasks out (when the library asks us to). Note that they
! are numbered from 0 to NUMBER_TASKS-1.
! ----------------------------------------------------------------------------
[ PrintTaskName achievement;
switch(achievement)
{ 0: "eating a sweet";
1: "driving the car";
2: "shutting out the draught";
3: "building a tower of four";
4: "seeing which way the mantelpiece leans";
5: "writing on the blackboard";
}
];
[ PrintRank;
print ", earning you the rank of ";
if (score >= 6) "Toyshop manager.";
if (score >= 5) "management trainee.";
if (score >= 4) "undergraduate.";
if (score >= 3) "schoolchild.";
if (score >= 2) "nursery-school child.";
if (score >= 1) "toddler.";
"newborn baby.";
];
! ----------------------------------------------------------------------------
! Now (as promised earlier) we provide the replacement for BurnSub,
! specially adapted to the rules of the Toyshop:
! ----------------------------------------------------------------------------
[ BurnSub;
if (match hasnt light) "You have no source of flame.";
if (noun has animate) <<Attack noun>>;
if (noun==padded_floor)
{ deadflag=1;
"A gong sounds, but before a sepulchral voice finishes clearing
its throat, the whole padded floor goes up in an inferno.";
}
"A gong sounds, and a sepulchral, rather disappointed voice says:
~It is forbidden to play with fire in the Toyshop.~";
];
! ----------------------------------------------------------------------------
! And we provide one new action, "Burst", which in fact just passes over to
! "Attack", plus one for writing on the board:
! ----------------------------------------------------------------------------
[ BurstSub; <<Attack noun>>; ];
Include "Grammar";
Verb "burst" "pop" "prick" "stab" "pierce"
* noun -> Burst;
Verb "write" * QuotedText -> Write;
! ----------------------------------------------------------------------------

121
src/codemirror/inform6.js Normal file
View File

@ -0,0 +1,121 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
// inform6 DASM syntax
CodeMirror.defineMode('inform6', function(_config, parserConfig) {
var keywords1, keywords2;
var keywords_list = "box|break|continue|do|else|fonton|fontoff|for|give|if|jump|new_line|objectloop|print|print_ret|remove|return|rfalse|rtrue|spaces|string|styleroman|stylebold|styleunderline|stylereverse|stylefixed|switch|until|while|has|hasnt|with|in|notin|ofclass|provides|or".split("|");
var directives_list = "Abbreviate|Array|Attribute|Class|Constant|Default|End|Endif|Extend|Global|Ifdef|Ifndef|Ifnot|Iftrue|Iffalse|Import|Include|Link|Lowstring|Message|Object|Property|Release|Replace|Serial|Switches|Statuslinescore|Statuslinetime|System_file|Verb|Zcharacter".toLowerCase().split("|");
var properties_list = "add_to_scope|after|article|articles|before|cant_go|capacity|d_to|daemon|describe|description|door_dir|door_to|e_to|each_turn|found_in|grammar|in_to|initial|inside_description|invent|life|list_together|name|n_to|ne_to|number|nw_to|orders|out_to|parse_name|plural|react_after|react_before|s_to|se_to|short_name|short_name_indef|sw_to|time_left|time_out|u_to|w_to|when_closed|when_open|when_on|when_off|with_key".split("|");
var attributes_list = "absent|animate|clothing|concealed|container|door|edible|enterable|female|general|light|lockable|locked|male|moved|neuter|open|openable|pluralname|proper|scenery|scored|static|supporter|switchable|talkable|transparent|visited|workflag|worn".split("|");
var actions_list = "Pronouns|Quit|Restart|Restore|Save|Verify|ScriptOn|ScriptOff|NotifyOn|NotifyOff|Places|Objects|Score|FullScore|Version|LMode1|LMode2|LMode3|Look|Examine|Search|Inv|InvTall|InvWide|Take|Drop|Remove|PutOn|Insert|LetGo|Receive|Empty|EmptyT|Remove|Transfer|Go|Enter|GetOff|GoIn|Exit|Unlock|Lock|SwitchOn|SwitchOff|Open|Close|Disrobe|Wear|Eat|Wait|LookUnder|Listen|Taste|Touch|Pull|Push|Wave|Turn|PushDir|ThrowAt|ThrownAt|JumpOver|Tie|Drink|Fill|Attack|Swing|Blow|Rub|Set|SetTo|Buy|Climb|Squeeze|Burn|Dig|Cut|Consult|Tell|Answer|Ask|Give|Show|AskFor|WakeOther|Kiss|Sleep|Sing|WaveHands|Swim|Sorry|Strong|Mild|Jump|Think|Smell|Pray|VagueGo|Yes|No|Wake|Answer|Ask|Attack|Give|Kiss|Order|Show|Tell|ThrowAt|WakeOther".toLowerCase().split("|");
var directives = new Map();
directives_list.forEach(function(s) { directives.set(s, 'keyword'); });
keywords_list.forEach(function(s) { directives.set(s, 'keyword'); });
properties_list.forEach(function(s) { directives.set(s, 'keyword'); });
attributes_list.forEach(function(s) { directives.set(s, 'keyword'); });
actions_list.forEach(function(s) { directives.set(s, 'keyword'); });
var numbers = /^([\da-f]+h|[0-7]+o|[01]+b|\d+d?)\b/i;
/*
var type, content;
function ret(tp, style, cont) {
type = tp; content = cont;
return style;
}
*/
function tokenBase(stream, state) {
if (stream.eatSpace())
return null;
var w;
if (stream.eatWhile(/\w/)) {
w = stream.current();
var cur = w.toLowerCase();
var style = directives.get(cur);
if (style)
return style;
if (numbers.test(w)) {
return 'number';
} else if (stream.match(numbers)) {
return 'number';
} else {
return null;
}
} else if (stream.eat('!')) {
stream.skipToEnd();
return 'comment';
} else if (stream.match(/\]|\[|\}|\{/)) {
return 'bracket';
} else if (stream.match(/\<\<|\>\>/)) {
return 'bracket';
} else if (stream.match(/[#]+\w+/)) {
return 'number';
} else if (stream.eat('"')) {
state.tokenize = tokenString;
return tokenString(stream, state);
} else if (stream.eat('\'')) {
return tokenString2(stream, state);
} else if (stream.eat('$')) {
if (stream.eatWhile(/[^;]/i))
return 'number';
} else {
stream.next();
}
return null;
}
function tokenString(stream, state) {
var ch;
while (ch = stream.next()) {
if (ch == '"') {
state.tokenize = tokenBase;
break;
}
}
return "string";
}
function tokenString2(stream, state) {
var ch;
while (ch = stream.next()) {
if (ch == "'") {
state.tokenize = tokenBase;
break;
}
}
return "meta";
}
return {
startState: function() {
return {
context: 0,
tokenize: tokenBase
};
},
token: function(stream, state) {
return state.tokenize(stream, state);
}
}
});
CodeMirror.defineMIME("text/x-inform6", "inform6");
});

View File

@ -191,6 +191,9 @@ export abstract class BasePlatform {
this.recorder.recordFrame(this.saveState());
}
}
inspect(sym: string) : string {
return inspectSymbol((this as any) as Platform, sym);
}
}
export abstract class BaseDebugPlatform extends BasePlatform {
@ -352,23 +355,23 @@ export abstract class BaseDebugPlatform extends BasePlatform {
return this.frameCount > frame0;
});
}
}
inspect(sym: string) : string {
if (!this.debugSymbols) return;
var symmap = this.debugSymbols.symbolmap;
var addr2sym = this.debugSymbols.addr2symbol;
if (!symmap || !this.readAddress) return null;
var addr = symmap["_"+sym] || symmap[sym]; // look for C or asm symbol
if (!(typeof addr == 'number')) return null;
var b = this.readAddress(addr);
// don't show 2 bytes if there's a symbol at the next address
if (addr2sym && addr2sym[addr+1] != null) {
return "$"+hex(addr,4) + " = "+hex(b,2);
} else {
var b2 = this.readAddress(addr+1);
var w = b | (b2<<8);
return "$"+hex(addr,4) + " = "+hex(b,2)+" "+hex(b2,2)+" ($"+hex(w,2)+")";
}
export function inspectSymbol(platform : Platform, sym : string) : string {
if (!platform.debugSymbols) return;
var symmap = platform.debugSymbols.symbolmap;
var addr2sym = platform.debugSymbols.addr2symbol;
if (!symmap || !platform.readAddress) return null;
var addr = symmap["_"+sym] || symmap[sym]; // look for C or asm symbol
if (!(typeof addr == 'number')) return null;
var b = platform.readAddress(addr);
// don't show 2 bytes if there's a symbol at the next address
if (addr2sym && addr2sym[addr+1] != null) {
return "$"+hex(addr,4) + " = $"+hex(b,2)+" ("+b+" decimal)"; // unsigned
} else {
let b2 = platform.readAddress(addr+1);
let w = b | (b2<<8);
return "$"+hex(addr,4) + " = $"+hex(b,2)+" $"+hex(b2,2)+" ("+((w<<16)>>16)+" decimal)"; // signed
}
}

View File

@ -79,6 +79,7 @@ var TOOL_TO_SOURCE_STYLE = {
'cmoc': 'text/x-csrc',
'yasm': 'gas',
'smlrc': 'text/x-csrc',
'inform6': 'inform6',
}
function gaEvent(category:string, action:string, label?:string, value?:string) {

View File

@ -62,6 +62,17 @@ function newDiv(parent?, cls? : string) {
const MAX_ERRORS = 200;
const MODEDEFS = {
default: { theme: 'mbo' }, // NOTE: Not merged w/ other modes
'6502': { isAsm: true },
z80: { isAsm: true },
jsasm: { isAsm: true },
gas: { isAsm: true },
inform6: { theme: 'cobalt' },
markdown: { lineWrap: true },
}
export class SourceEditor implements ProjectView {
constructor(path:string, mode:string) {
this.path = path;
@ -92,10 +103,12 @@ export class SourceEditor implements ProjectView {
}
newEditor(parent:HTMLElement, isAsmOverride?:boolean) {
var isAsm = isAsmOverride || this.mode=='6502' || this.mode =='z80' || this.mode=='jsasm' || this.mode=='gas'; // TODO
var lineWrap = this.mode=='markdown';
var modedef = MODEDEFS[this.mode] || MODEDEFS.default;
var isAsm = isAsmOverride || modedef.isAsm;
var lineWrap = modedef.lineWrap;
var theme = modedef.theme || MODEDEFS.default.theme;
this.editor = CodeMirror(parent, {
theme: 'mbo',
theme: theme,
lineNumbers: true,
matchBrackets: true,
tabSize: 8,
@ -525,12 +538,15 @@ export class ListingView extends DisassemblerView implements ProjectView {
refresh(moveCursor: boolean) {
this.refreshListing();
if (!this.assemblyfile || !platform.saveState) return;
var state = lastDebugState || platform.saveState();
var pc = state.c ? (state.c.EPC || state.c.PC) : 0;
// load listing text into editor
if (!this.assemblyfile) return;
var asmtext = this.assemblyfile.text;
var disasmview = this.getDisasmView();
disasmview.setValue(asmtext);
// go to PC
if (!platform.saveState) return;
var state = lastDebugState || platform.saveState();
var pc = state.c ? (state.c.EPC || state.c.PC) : 0;
if (pc >= 0 && this.assemblyfile) {
var res = this.assemblyfile.findLineForOffset(pc, 15);
if (res) {

View File

@ -763,7 +763,7 @@ var VerilogPlatform = function(mainElement, options) {
}
getDefaultExtension() { return ".v"; };
inspect(name) {
inspect(name:string) : string {
if (!gen) return;
if (name && !name.match(/^\w+$/)) return;
var val = gen[name];

714
src/platform/zmachine.ts Normal file
View File

@ -0,0 +1,714 @@
import { Platform, BasePlatform, BaseDebugPlatform, Preset, EmuState, inspectSymbol } from "../common/baseplatform";
import { PLATFORMS, EmuHalt } from "../common/emu";
import { loadScript } from "../ide/ui";
const ZMACHINE_PRESETS = [
{ id: 'hello.inf', name: 'Hello World' },
{ id: 'house01.inf', name: 'House Tutorial #1' },
{ id: 'house02.inf', name: 'House Tutorial #2' },
{ id: 'house03.inf', name: 'House Tutorial #3' },
{ id: 'house04.inf', name: 'House Tutorial #4' },
{ id: 'house05.inf', name: 'House Tutorial #5' },
{ id: 'house06.inf', name: 'House Tutorial #6' },
{ id: 'house07.inf', name: 'House Tutorial #7' },
{ id: 'alice.inf', name: 'Through the Looking-Glass' },
{ id: 'aloneice.inf', name: 'Alone on the Ice' },
{ id: 'adventureland.inf', name: 'Adventureland' },
{ id: 'toyshop.inf', name: 'Toyshop' },
{ id: 'ruins1.inf', name: 'Ruins #1' },
{ id: 'ruins2.inf', name: 'Ruins #2' },
{ id: 'ruins3.inf', name: 'Ruins #3' },
{ id: 'balances.inf', name: 'Balances' },
{ id: 'museum.inf', name: 'Museum of Inform' },
{ id: 'advent.inf', name: 'Colossal Cave Adventure' },
];
declare var ZVM;
// https://github.com/erkyrath/quixe/wiki/Quixe-Without-GlkOte#quixes-api
// https://eblong.com/zarf/glk/glkote/docs.html
// https://inform-fiction.org/zmachine/standards/z1point0/sect15.html#read_char
// https://manpages.debian.org/testing/inform6-compiler/inform6.1.en.html
class GlkWindow {
//area: HTMLElement;
// TODO
}
interface IFZVM {
start();
run();
version : number;
pc : number;
ram : DataView;
stack : DataView;
read_data : {buffer?};
handle_line_input(len:number);
handle_char_input(charcode:number);
}
class GlkImpl {
vm : IFZVM;
page: HTMLElement;
input: HTMLInputElement;
curline: HTMLElement;
curstyle: number;
reverse: boolean;
windows: GlkWindow[];
wnd: GlkWindow;
waitingfor: "line" | "char" | null;
focused = false;
constructor(page: HTMLElement, input: HTMLInputElement) {
this.page = page;
this.input = input;
this.reset();
}
reset() {
this.windows = [];
this.wnd = null;
this.clear();
}
clear() {
this.curline = null;
this.curstyle = 0;
this.reverse = false;
// keep from losing input handlers
this.hideinput();
$(this.page).empty();
}
init(options) {
this.vm = options.vm;
this.vm.start();
}
fatal_error(s:string) {
throw new EmuHalt(s);
}
update() {
// TODO
}
glk_exit() {
this.flushline();
this.addtext("** Game exited **", 1);
}
glk_window_clear(win) {
console.log('glk_window_clear', arguments);
this.clear();
}
glk_request_line_event_uni(win, buf, initlen) {
this.waitingfor = 'line';
this.focusinput();
}
glk_request_char_event_uni(win, buf, initlen) {
this.waitingfor = 'char';
this.focusinput();
}
focusinput() {
this.ensureline();
// don't steal focus while editing
$(this.input).appendTo(this.curline).show()[0].scrollIntoView();
if (this.focused) {
$(this.input).focus();
}
}
hideinput() {
$(this.input).appendTo($(this.page).parent()).hide();
}
clearinput() {
this.input.value = '';
this.waitingfor = null;
}
sendkey(e: KeyboardEvent) {
if (this.waitingfor == 'line') {
if (e.key == "Enter") {
this.sendinput(this.input.value.toString());
}
} else if (this.waitingfor == 'char') {
this.vm.handle_char_input(e.keyCode);
this.vm.run();
e.preventDefault();
}
}
sendinput(s: string) {
this.addtext(s, Const.style_Input);
this.flushline();
if (this.vm.read_data.buffer) {
for (var i = 0; i < s.length; i++) {
this.vm.read_data.buffer[i] = s.charCodeAt(i) & 0xff;
}
this.vm.handle_line_input(s.length);
}
this.clearinput();
this.vm.run();
}
ensureline() {
$(this.input).hide();
if (this.curline == null) {
this.curline = $('<div class="transcript-line"/>')[0];
this.page.appendChild(this.curline);
}
}
flushline() {
this.curline = null;
}
addtext(line: string, style: number) {
this.ensureline();
if (line.length) {
var span = $("<span/>").text(line).appendTo(this.curline);
for (var i=0; i<8; i++) {
if (style & (1<<i))
span.addClass("transcript-style-" + (1<<i));
}
if (this.reverse) span.addClass("transcript-reverse");
span.data('vmip', this.vm.pc);
}
}
glk_put_jstring(val: string, allbytes) {
var lines = val.split("\n");
for (var i = 0; i < lines.length; i++) {
if (i > 0) this.flushline();
this.addtext(lines[i], this.curstyle);
}
}
glk_put_char(ch) {
console.log('glk_put_char', arguments);
}
glk_put_char_stream(str, ch) {
console.log('glk_put_char_stream', arguments);
}
glk_put_string(val) {
console.log('glk_put_string', arguments);
}
glk_put_string_stream(str, val) {
console.log('glk_put_string_stream', arguments);
}
glk_put_buffer(arr) {
console.log('glk_put_buffer', arguments);
}
glk_put_buffer_stream(str, arr) {
console.log('glk_put_buffer_stream', arguments);
}
glk_set_style(val) {
this.curstyle = val;
}
glk_set_style_stream(str, val) {
console.log('glk_set_style_stream', arguments);
}
glk_get_char_stream(str) {
console.log('glk_get_char_stream', arguments);
}
glk_get_line_stream(str, buf) {
console.log('glk_get_line_stream', arguments);
}
glk_get_buffer_stream(str, buf) {
console.log('glk_get_buffer_stream', arguments);
}
glk_char_to_lower(val) {
if (val >= 0x41 && val <= 0x5A)
return val + 0x20;
if (val >= 0xC0 && val <= 0xDE && val != 0xD7)
return val + 0x20;
return val;
}
glk_char_to_upper(val) {
if (val >= 0x61 && val <= 0x7A)
return val - 0x20;
if (val >= 0xE0 && val <= 0xFE && val != 0xF7)
return val - 0x20;
return val;
}
glk_stylehint_set(wintype, styl, hint, value) {
console.log('glk_stylehint_set', arguments);
}
glk_stylehint_clear(wintype, styl, hint) {
console.log('glk_stylehint_clear', arguments);
}
glk_style_distinguish(win, styl1, styl2) {
return 0;
}
glk_style_measure(win, styl, hint, resultref) {
if (resultref)
resultref.set_value(0);
return 0;
}
glk_select(eventref) {
console.log('glk_select', arguments);
}
glk_window_open(splitwin, method, size, wintype, rock) {
console.log('glk_window_open', arguments);
if (splitwin) console.log("split windows are not supported");
return splitwin ? 0 : 1; // 0 = no window, 1 = main window
}
/*
glk_window_close(win) {
console.log('glk_window_close', arguments);
this.windows.pop(); // TODO
}
glk_window_get_parent(win) {
console.log('glk_window_get_parent', arguments);
}
glk_window_set_arrangement(win) {
console.log('glk_window_set_arrangement', arguments);
}
glk_window_get_stream(win) {
console.log('glk_window_get_stream', arguments);
}
*/
glk_set_window(win) {
console.log('glk_set_window', arguments);
//if (!win) gli_currentstr = null;
//else gli_currentstr = win.str;
}
glk_window_get_size(win, widthref, heightref) {
console.log('glk_window_get_size', arguments);
}
garglk_set_reversevideo(val) {
this.reverse = !!val;
}
glk_gestalt(sel, val) {
return this.glk_gestalt_ext(sel, val, null);
}
glk_gestalt_ext(sel, val, arr) {
console.log('glk_gestalt_ext', arguments);
switch (sel) {
case 0: // gestalt_Version
/* This implements Glk spec version 0.7.4? */
return 0x00000101; // 0.1.1
case 1: // gestalt_CharInput
/* This is not a terrific approximation. Return false for function
keys, control keys, and the high-bit non-printables. For
everything else in the Unicode range, return true. */
if (val <= Const.keycode_Left && val >= Const.keycode_End)
return 1;
if (val >= 0x100000000 - Const.keycode_MAXVAL)
return 0;
if (val > 0x10FFFF)
return 0;
if ((val >= 0 && val < 32) || (val >= 127 && val < 160))
return 0;
return 1;
case 2: // gestalt_LineInput
/* Same as the above, except no special keys. */
if (val > 0x10FFFF)
return 0;
if ((val >= 0 && val < 32) || (val >= 127 && val < 160))
return 0;
return 1;
case 3: // gestalt_CharOutput
/* Same thing again. We assume that all printable characters,
as well as the placeholders for nonprintables, are one character
wide. */
if ((val > 0x10FFFF)
|| (val >= 0 && val < 32)
|| (val >= 127 && val < 160)) {
if (arr)
arr[0] = 1;
return 0; // gestalt_CharOutput_CannotPrint
}
if (arr)
arr[0] = 1;
return 2; // gestalt_CharOutput_ExactPrint
case 4: // gestalt_MouseInput
if (val == Const.wintype_TextBuffer)
return 0;
if (val == Const.wintype_Graphics && has_canvas)
return 0;
return 0;
case 5: // gestalt_Timer
return 0;
case 6: // gestalt_Graphics
return 0;
case 7: // gestalt_DrawImage
if (val == Const.wintype_TextBuffer)
return 0;
if (val == Const.wintype_Graphics && has_canvas)
return 0;
return 0;
case 8: // gestalt_Sound
return 0;
case 9: // gestalt_SoundVolume
return 0;
case 10: // gestalt_SoundNotify
return 0;
case 11: // gestalt_Hyperlinks
return 0;
case 12: // gestalt_HyperlinkInput
if (val == 3 || val == 4) // TextBuffer or TextGrid
return 0;
else
return 0;
case 13: // gestalt_SoundMusic
return 0;
case 14: // gestalt_GraphicsTransparency
return 0;
case 15: // gestalt_Unicode
return 1;
case 16: // gestalt_UnicodeNorm
return 1;
case 17: // gestalt_LineInputEcho
return 1;
case 18: // gestalt_LineTerminators
return 1;
case 19: // gestalt_LineTerminatorKey
/* Really this result should be inspected from glkote.js. Since it
isn't, be sure to keep these values in sync with
terminator_key_names. */
if (val == Const.keycode_Escape)
return 0;
if (val >= Const.keycode_Func12 && val <= Const.keycode_Func1)
return 0;
return 0;
case 20: // gestalt_DateTime
return 0;
case 21: // gestalt_Sound2
return 0;
case 22: // gestalt_ResourceStream
return 0;
case 23: // gestalt_GraphicsCharInput
return 0;
case 0x1100: // reverse video, color
return 0;
}
return 0;
}
/* RefBox: Simple class used for "call-by-reference" Glk arguments. The object
is just a box containing a single value, which can be written and read.
*/
RefBox = function () {
this.value = undefined;
this.set_value = function (val) {
this.value = val;
}
this.get_value = function () {
return this.value;
}
}
/* RefStruct: Used for struct-type Glk arguments. After creating the
object, you should call push_field() the appropriate number of times,
to set the initial field values. Then set_field() can be used to
change them, and get_fields() retrieves the list of all fields.
(The usage here is loose, since Javascript is forgiving about arrays.
Really the caller could call set_field() instead of push_field() --
or skip that step entirely, as long as the Glk function later calls
set_field() for each field. Which it should.)
*/
RefStruct = function (numels) {
this.fields = [];
this.push_field = function (val) {
this.fields.push(val);
}
this.set_field = function (pos, val) {
this.fields[pos] = val;
}
this.get_field = function (pos) {
return this.fields[pos];
}
this.get_fields = function () {
return this.fields;
}
}
/* Dummy return value, which means that the Glk call is still in progress,
or will never return at all. This is used by glk_exit(), glk_select(),
and glk_fileref_create_by_prompt().
*/
DidNotReturn = { dummy: 'Glk call has not yet returned' };
}
const has_canvas = typeof window === 'object';
const Const = {
gestalt_Version: 0,
gestalt_CharInput: 1,
gestalt_LineInput: 2,
gestalt_CharOutput: 3,
gestalt_CharOutput_CannotPrint: 0,
gestalt_CharOutput_ApproxPrint: 1,
gestalt_CharOutput_ExactPrint: 2,
gestalt_MouseInput: 4,
gestalt_Timer: 5,
gestalt_Graphics: 6,
gestalt_DrawImage: 7,
gestalt_Sound: 8,
gestalt_SoundVolume: 9,
gestalt_SoundNotify: 10,
gestalt_Hyperlinks: 11,
gestalt_HyperlinkInput: 12,
gestalt_SoundMusic: 13,
gestalt_GraphicsTransparency: 14,
gestalt_Unicode: 15,
gestalt_UnicodeNorm: 16,
gestalt_LineInputEcho: 17,
gestalt_LineTerminators: 18,
gestalt_LineTerminatorKey: 19,
gestalt_DateTime: 20,
gestalt_Sound2: 21,
gestalt_ResourceStream: 22,
gestalt_GraphicsCharInput: 23,
keycode_Unknown: 0xffffffff,
keycode_Left: 0xfffffffe,
keycode_Right: 0xfffffffd,
keycode_Up: 0xfffffffc,
keycode_Down: 0xfffffffb,
keycode_Return: 0xfffffffa,
keycode_Delete: 0xfffffff9,
keycode_Escape: 0xfffffff8,
keycode_Tab: 0xfffffff7,
keycode_PageUp: 0xfffffff6,
keycode_PageDown: 0xfffffff5,
keycode_Home: 0xfffffff4,
keycode_End: 0xfffffff3,
keycode_Func1: 0xffffffef,
keycode_Func2: 0xffffffee,
keycode_Func3: 0xffffffed,
keycode_Func4: 0xffffffec,
keycode_Func5: 0xffffffeb,
keycode_Func6: 0xffffffea,
keycode_Func7: 0xffffffe9,
keycode_Func8: 0xffffffe8,
keycode_Func9: 0xffffffe7,
keycode_Func10: 0xffffffe6,
keycode_Func11: 0xffffffe5,
keycode_Func12: 0xffffffe4,
/* The last keycode is always (0x100000000 - keycode_MAXVAL) */
keycode_MAXVAL: 28,
evtype_None: 0,
evtype_Timer: 1,
evtype_CharInput: 2,
evtype_LineInput: 3,
evtype_MouseInput: 4,
evtype_Arrange: 5,
evtype_Redraw: 6,
evtype_SoundNotify: 7,
evtype_Hyperlink: 8,
evtype_VolumeNotify: 9,
style_Normal: 0,
style_Emphasized: 1,
style_Preformatted: 2,
style_Header: 3,
style_Subheader: 4,
style_Alert: 5,
style_Note: 6,
style_BlockQuote: 7,
style_Input: 8,
style_User1: 9,
style_User2: 10,
style_NUMSTYLES: 11,
wintype_AllTypes: 0,
wintype_Pair: 1,
wintype_Blank: 2,
wintype_TextBuffer: 3,
wintype_TextGrid: 4,
wintype_Graphics: 5,
winmethod_Left: 0x00,
winmethod_Right: 0x01,
winmethod_Above: 0x02,
winmethod_Below: 0x03,
winmethod_DirMask: 0x0f,
winmethod_Fixed: 0x10,
winmethod_Proportional: 0x20,
winmethod_DivisionMask: 0xf0,
winmethod_Border: 0x000,
winmethod_NoBorder: 0x100,
winmethod_BorderMask: 0x100,
fileusage_Data: 0x00,
fileusage_SavedGame: 0x01,
fileusage_Transcript: 0x02,
fileusage_InputRecord: 0x03,
fileusage_TypeMask: 0x0f,
fileusage_TextMode: 0x100,
fileusage_BinaryMode: 0x000,
filemode_Write: 0x01,
filemode_Read: 0x02,
filemode_ReadWrite: 0x03,
filemode_WriteAppend: 0x05,
seekmode_Start: 0,
seekmode_Current: 1,
seekmode_End: 2,
stylehint_Indentation: 0,
stylehint_ParaIndentation: 1,
stylehint_Justification: 2,
stylehint_Size: 3,
stylehint_Weight: 4,
stylehint_Oblique: 5,
stylehint_Proportional: 6,
stylehint_TextColor: 7,
stylehint_BackColor: 8,
stylehint_ReverseColor: 9,
stylehint_NUMHINTS: 10,
stylehint_just_LeftFlush: 0,
stylehint_just_LeftRight: 1,
stylehint_just_Centered: 2,
stylehint_just_RightFlush: 3,
imagealign_InlineUp: 1,
imagealign_InlineDown: 2,
imagealign_InlineCenter: 3,
imagealign_MarginLeft: 4,
imagealign_MarginRight: 5
};
//
class ZmachinePlatform implements Platform {
mainElement: HTMLElement;
zfile : Uint8Array;
zvm;
glk;
focused = false;
constructor(mainElement: HTMLElement) {
this.mainElement = mainElement;
$(mainElement).css('overflowY', 'auto');
}
async start() {
await loadScript('./lib/zvm/ifvms.min.js');
//await loadScript('./lib/zvm/glkote.min.js');
//await loadScript('./lib/zvm/glkapi.js');
//await loadScript('./lib/zvm/parchment.debug.js');
// create divs
var parent = this.mainElement;
var gameport = $('<div id="gameport"/>').appendTo(parent);
var windowport = $('<div id="windowport" class="transcript"/>').appendTo(gameport);
var inputline = $('<input class="transcript-input" type="text"/>').appendTo(gameport).hide();
this.glk = new GlkImpl(windowport[0], inputline[0] as HTMLInputElement);
inputline.on('keypress', (e) => {
this.glk.sendkey(e);
});
inputline.on('focus', (e) => {
this.glk.focused = true;
});
inputline.on('blur', (e) => {
this.glk.focused = false;
});
windowport.on('click', (e) => {
inputline.focus();
});
}
loadROM(title, data) {
this.zfile = data;
this.reset();
}
reset(): void {
if (this.zfile == null) return;
//this.glk = Glk;
//this.glk = new Object();
//Object.setPrototypeOf(this.glk, Glk);
this.zvm = new ZVM();
this.zvm.prepare(this.zfile.slice(0), {
Glk: this.glk,
});
this.glk.reset();
this.glk.init({
vm: this.zvm,
});
console.log(this.zvm);
}
pause(): void {
}
resume(): void {
}
readAddress(a: number) {
return this.zvm && a < this.zvm.ram.byteLength ? this.zvm.ram.getUint8(a) : this.zfile[a];
}
getPC() {
return this.zvm.pc;
}
/*
loadState(state): void {
throw new Error("Method not implemented.");
}
saveState() {
return {
//glk: this.Glk.save_allstate(),
io: $.extend(true, {}, this.zvm.io),
ram: this.zvm.save_file(this.zvm.pc, 1),
read_data: $.extend(true, {}, this.zvm.read_data),
xorshift_seed: this.zvm.xorshift_seed,
}
}
*/
isRunning(): boolean {
return this.zvm != null;
}
advance(novideo?: boolean): number {
// TODO?
return 0;
}
getToolForFilename(s: string): string {
return "inform6";
}
getDefaultExtension(): string {
return ".inf";
}
showHelp(tool:string, ident?:string) {
switch (tool) {
case 'inform6': window.open("https://www.inform-fiction.org/manual/html/"); break;
}
}
getPresets(): Preset[] {
return ZMACHINE_PRESETS;
}
inspect(ident:string) {
return inspectSymbol(this, ident);
}
}
//
PLATFORMS['zmachine'] = ZmachinePlatform;

36946
src/worker/fs/fsinform.data Normal file

File diff suppressed because it is too large Load Diff

201
src/worker/fs/fsinform.js Normal file
View File

@ -0,0 +1,201 @@
var Module = typeof Module !== 'undefined' ? Module : {};
if (!Module.expectedDataFileDownloads) {
Module.expectedDataFileDownloads = 0;
}
Module.expectedDataFileDownloads++;
(function() {
var loadPackage = function(metadata) {
var PACKAGE_PATH;
if (typeof window === 'object') {
PACKAGE_PATH = window['encodeURIComponent'](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf('/')) + '/');
} else if (typeof location !== 'undefined') {
// worker
PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf('/')) + '/');
} else {
throw 'using preloaded data can only be done on a web page or in a web worker';
}
var PACKAGE_NAME = 'fsinform.data';
var REMOTE_PACKAGE_BASE = 'fsinform.data';
if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) {
Module['locateFile'] = Module['locateFilePackage'];
err('warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)');
}
var REMOTE_PACKAGE_NAME = Module['locateFile'] ? Module['locateFile'](REMOTE_PACKAGE_BASE, '') : REMOTE_PACKAGE_BASE;
var REMOTE_PACKAGE_SIZE = metadata['remote_package_size'];
var PACKAGE_UUID = metadata['package_uuid'];
function fetchRemotePackage(packageName, packageSize, callback, errback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', packageName, true);
xhr.responseType = 'arraybuffer';
xhr.onprogress = function(event) {
var url = packageName;
var size = packageSize;
if (event.total) size = event.total;
if (event.loaded) {
if (!xhr.addedTotal) {
xhr.addedTotal = true;
if (!Module.dataFileDownloads) Module.dataFileDownloads = {};
Module.dataFileDownloads[url] = {
loaded: event.loaded,
total: size
};
} else {
Module.dataFileDownloads[url].loaded = event.loaded;
}
var total = 0;
var loaded = 0;
var num = 0;
for (var download in Module.dataFileDownloads) {
var data = Module.dataFileDownloads[download];
total += data.total;
loaded += data.loaded;
num++;
}
total = Math.ceil(total * Module.expectedDataFileDownloads/num);
if (Module['setStatus']) Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')');
} else if (!Module.dataFileDownloads) {
if (Module['setStatus']) Module['setStatus']('Downloading data...');
}
};
xhr.onerror = function(event) {
throw new Error("NetworkError for: " + packageName);
}
xhr.onload = function(event) {
if (xhr.status == 200 || xhr.status == 304 || xhr.status == 206 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
var packageData = xhr.response;
callback(packageData);
} else {
throw new Error(xhr.statusText + " : " + xhr.responseURL);
}
};
xhr.send(null);
};
function handleError(error) {
console.error('package error:', error);
};
var fetchedCallback = null;
var fetched = Module['getPreloadedPackage'] ? Module['getPreloadedPackage'](REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE) : null;
if (!fetched) fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, function(data) {
if (fetchedCallback) {
fetchedCallback(data);
fetchedCallback = null;
} else {
fetched = data;
}
}, handleError);
function runWithFS() {
function assert(check, msg) {
if (!check) throw msg + new Error().stack;
}
Module['FS_createPath']('/', 'include', true, true);
Module['FS_createPath']('/', 'lib', true, true);
/** @constructor */
function DataRequest(start, end, audio) {
this.start = start;
this.end = end;
this.audio = audio;
}
DataRequest.prototype = {
requests: {},
open: function(mode, name) {
this.name = name;
this.requests[name] = this;
Module['addRunDependency']('fp ' + this.name);
},
send: function() {},
onload: function() {
var byteArray = this.byteArray.subarray(this.start, this.end);
this.finish(byteArray);
},
finish: function(byteArray) {
var that = this;
Module['FS_createDataFile'](this.name, null, byteArray, true, true, true); // canOwn this data in the filesystem, it is a slide into the heap that will never change
Module['removeRunDependency']('fp ' + that.name);
this.requests[this.name] = null;
}
};
var files = metadata['files'];
for (var i = 0; i < files.length; ++i) {
new DataRequest(files[i]['start'], files[i]['end'], files[i]['audio']).open('GET', files[i]['filename']);
}
function processPackageData(arrayBuffer) {
assert(arrayBuffer, 'Loading data file failed.');
assert(arrayBuffer instanceof ArrayBuffer, 'bad input to processPackageData');
var byteArray = new Uint8Array(arrayBuffer);
var curr;
// copy the entire loaded file into a spot in the heap. Files will refer to slices in that. They cannot be freed though
// (we may be allocating before malloc is ready, during startup).
var ptr = Module['getMemory'](byteArray.length);
Module['HEAPU8'].set(byteArray, ptr);
DataRequest.prototype.byteArray = Module['HEAPU8'].subarray(ptr, ptr+byteArray.length);
var files = metadata['files'];
for (var i = 0; i < files.length; ++i) {
DataRequest.prototype.requests[files[i].filename].onload();
}
Module['removeRunDependency']('datafile_fsinform.data');
};
Module['addRunDependency']('datafile_fsinform.data');
if (!Module.preloadResults) Module.preloadResults = {};
Module.preloadResults[PACKAGE_NAME] = {fromCache: false};
if (fetched) {
processPackageData(fetched);
fetched = null;
} else {
fetchedCallback = processPackageData;
}
}
if (Module['calledRun']) {
runWithFS();
} else {
if (!Module['preRun']) Module['preRun'] = [];
Module["preRun"].push(runWithFS); // FS is not initialized yet, wait for it
}
Module['removeRunDependency']('fsinform.js.metadata');
}
function runMetaWithFS() {
Module['addRunDependency']('fsinform.js.metadata');
var REMOTE_METADATA_NAME = Module['locateFile'] ? Module['locateFile']('fsinform.js.metadata', '') : 'fsinform.js.metadata';
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
loadPackage(JSON.parse(xhr.responseText));
}
}
xhr.open('GET', REMOTE_METADATA_NAME, true);
xhr.overrideMimeType('application/json');
xhr.send(null);
}
if (Module['calledRun']) {
runMetaWithFS();
} else {
if (!Module['preRun']) Module['preRun'] = [];
Module["preRun"].push(runMetaWithFS);
}
})();

View File

@ -0,0 +1 @@
{"files":[{"start":0,"audio":0,"end":5037,"filename":"/include/trinitystat.h"},{"start":5037,"audio":0,"end":8410,"filename":"/include/zclock.h"},{"start":8410,"audio":0,"end":13401,"filename":"/include/shuffle.h"},{"start":13401,"audio":0,"end":18697,"filename":"/include/smartcantgo.h"},{"start":18697,"audio":0,"end":21791,"filename":"/include/seeno.h"},{"start":21791,"audio":0,"end":23907,"filename":"/include/yesno.h"},{"start":23907,"audio":0,"end":30683,"filename":"/include/sound.h"},{"start":30683,"audio":0,"end":34007,"filename":"/include/whowhat.h"},{"start":34007,"audio":0,"end":39493,"filename":"/include/torch.h"},{"start":39493,"audio":0,"end":54451,"filename":"/include/tmenus.h"},{"start":54451,"audio":0,"end":58829,"filename":"/include/doors.h"},{"start":58829,"audio":0,"end":63925,"filename":"/include/footnote.h"},{"start":63925,"audio":0,"end":66819,"filename":"/include/doors2.h"},{"start":66819,"audio":0,"end":85989,"filename":"/include/newbiegrammar.h"},{"start":85989,"audio":0,"end":111330,"filename":"/include/dmenus.h"},{"start":111330,"audio":0,"end":140985,"filename":"/include/mistype.h"},{"start":140985,"audio":0,"end":155615,"filename":"/include/moveclass.h"},{"start":155615,"audio":0,"end":168639,"filename":"/include/howtoplay.h"},{"start":168639,"audio":0,"end":195354,"filename":"/include/helproutines.h"},{"start":195354,"audio":0,"end":449098,"filename":"/lib/parser.h"},{"start":449098,"audio":0,"end":504806,"filename":"/lib/english.h"},{"start":504806,"audio":0,"end":525313,"filename":"/lib/Grammar.h"},{"start":525313,"audio":0,"end":533851,"filename":"/lib/voices_and_tenses.txt"},{"start":533851,"audio":0,"end":628247,"filename":"/lib/Verblib.h"},{"start":628247,"audio":0,"end":629547,"filename":"/lib/COPYING"},{"start":629547,"audio":0,"end":633148,"filename":"/lib/linklpa.h"},{"start":633148,"audio":0,"end":886892,"filename":"/lib/Parser.h"},{"start":886892,"audio":0,"end":914466,"filename":"/lib/ChangeLog"},{"start":914466,"audio":0,"end":1008862,"filename":"/lib/verblib.h"},{"start":1008862,"audio":0,"end":1030185,"filename":"/lib/infglk.h"},{"start":1030185,"audio":0,"end":1050692,"filename":"/lib/grammar.h"},{"start":1050692,"audio":0,"end":1059586,"filename":"/lib/ARTISTIC"},{"start":1059586,"audio":0,"end":1153982,"filename":"/lib/VerbLib.h"},{"start":1153982,"audio":0,"end":1200623,"filename":"/lib/infix.h"},{"start":1200623,"audio":0,"end":1201343,"filename":"/lib/README.txt"},{"start":1201343,"audio":0,"end":1257051,"filename":"/lib/English.h"}],"remote_package_size":1257051,"package_uuid":"24847113-2ab7-492b-ad8a-665bc1ff1021"}

5781
src/worker/wasm/inform.js Normal file

File diff suppressed because it is too large Load Diff

BIN
src/worker/wasm/inform.wasm Normal file

Binary file not shown.

View File

@ -1,6 +1,6 @@
"use strict";
import { WorkerResult, WorkerFileUpdate, WorkerBuildStep, WorkerMessage, WorkerError, Dependency, SourceLine, CodeListing, CodeListingMap } from "../common/workertypes";
import { WorkerResult, WorkerFileUpdate, WorkerBuildStep, WorkerMessage, WorkerError, Dependency, SourceLine, CodeListing, CodeListingMap, Segment } from "../common/workertypes";
declare var WebAssembly;
declare function importScripts(path:string);
@ -617,10 +617,10 @@ var re_crlf = /\r?\n/;
function parseListing(code:string, lineMatch, iline:number, ioffset:number, iinsns:number, icycles?:number) : SourceLine[] {
var lines : SourceLine[] = [];
for (var line of code.split(re_crlf)) {
code.split(re_crlf).forEach((line, lineindex) => {
var linem = lineMatch.exec(line);
if (linem && linem[1]) {
var linenum = parseInt(linem[iline]);
var linenum = iline < 0 ? lineindex : parseInt(linem[iline]);
var offset = parseInt(linem[ioffset], 16);
var insns = linem[iinsns];
var cycles : number = icycles ? parseInt(linem[icycles]) : null;
@ -635,7 +635,7 @@ function parseListing(code:string, lineMatch, iline:number, ioffset:number, iins
});
}
}
}
});
return lines;
}
@ -2389,6 +2389,125 @@ function assembleYASM(step:BuildStep) {
}
}
interface XMLNode {
type: string;
text: string | null;
children: XMLNode[];
}
function parseXMLPoorly(s: string) : XMLNode {
var re = /[<]([/]?)([?a-z_-]+)([^>]*)[>]+|(\s*[^<]+)/gi;
var m;
var i=0;
var stack = [];
while (m = re.exec(s)) {
var [_m0,close,ident,attrs,content] = m;
//if (i++<100) console.log(close,ident,attrs,content);
if (close) {
var top = stack.pop();
if (top.type != ident) throw "mismatch close tag: " + ident;
stack[stack.length-1].children.push(top);
} else if (ident) {
stack.push({type:ident, text:null, children:[]});
} else if (content != null) {
stack[stack.length-1].text = (content as string).trim();
}
}
return top;
}
function compileInform6(step:BuildStep) {
loadNative("inform");
var errors = [];
gatherFiles(step, {mainFilePath:"main.inf"});
var objpath = step.prefix+".z5";
if (staleFiles(step, [objpath])) {
var errorMatcher = msvcErrorMatcher(errors);
var lstout = "";
var match_fn = (s: string) => {
if (s.indexOf("Error:") >= 0) {
errorMatcher(s);
} else {
lstout += s;
lstout += "\n";
}
}
var args = [ '-afnops', '-v5', '-Cu', '-E1', '-k', '+/share/lib', step.path ];
var inform = emglobal.inform({
instantiateWasm: moduleInstFn('inform'),
noInitialRun:true,
//logReadFiles:true,
print:match_fn,
printErr:match_fn,
});
var FS = inform['FS'];
setupFS(FS, 'inform');
populateFiles(step, FS);
//fixParamsWithDefines(step.path, step.params);
execMain(step, inform, args);
if (errors.length)
return {errors:errors};
var objout = FS.readFile(objpath, {encoding:'binary'});
putWorkFile(objpath, objout);
if (!anyTargetChanged(step, [objpath]))
return;
// parse debug XML
var symbolmap = {};
var entitymap = {'object':{}, 'property':{}, 'constant':{}};
var dbgout = FS.readFile("gameinfo.dbg", {encoding:'utf8'});
var xmlroot = parseXMLPoorly(dbgout);
//console.log(xmlroot);
xmlroot.children.forEach((node) => {
switch (node.type) {
case 'global-variable':
case 'routine':
var ident = node.children.find((c,v) => c.type=='identifier').text;
var address = parseInt(node.children.find((c,v) => c.type=='address').text);
symbolmap[ident] = address;
break;
case 'object':
case 'property':
var ident = node.children.find((c,v) => c.type=='identifier').text;
var value = parseInt(node.children.find((c,v) => c.type=='value').text);
entitymap[node.type][ident] = value;
//symbolmap[ident] = address | 0x1000000;
break;
}
});
// parse segments
var segments : Segment[] = [];
var seglst = lstout.split("Offsets in story file:")[1];
if (seglst) {
let curseg : Segment = {name:'Header',start:0x0,size:0x42,type:'rom'};
segments.push(curseg);
let curtype = 'ram';
let re_seg = /([0-9a-f]{5}) (\w+)/g;
let m;
while (m = re_seg.exec(seglst)) {
var start = parseInt(m[1], 16);
var name = m[2];
if (name == 'Parse') curtype = 'rom';
curseg.size = start - curseg.start;
curseg = {name:name, start:start, size:0, type:curtype};
segments.push(curseg);
}
}
var listings : CodeListingMap = {};
// 35 +00015 <*> call_vs long_19 location long_424 -> sp
var lines = parseListing(lstout, /\s*(\d+)\s+[+]([0-9a-f]+)\s+([<*>]*)\s*(\w+)\s+(.+)/i, -1, 2, 4);
var lstpath = step.prefix + '.lst';
listings[lstpath] = {lines:[], asmlines:lines, text:lstout};
return {
output:objout, //.slice(0),
listings:listings,
errors:errors,
symbolmap:symbolmap,
segments:segments,
//debuginfo:entitymap,
};
}
}
////////////////////////////
var TOOLS = {
@ -2419,6 +2538,7 @@ var TOOLS = {
'bataribasic': compileBatariBasic,
'markdown': translateShowdown,
'js': runJavascript,
'inform6': compileInform6,
}
var TOOL_PRELOADFS = {
@ -2438,6 +2558,7 @@ var TOOL_PRELOADFS = {
'sdcc': 'sdcc',
'sccz80': 'sccz80',
'bataribasic': '2600basic',
'inform6': 'inform',
}
function applyDefaultErrorPath(errors:WorkerError[], path:string) {