Added Nitfol and Frotz source code.
[projects/chimara/chimara.git] / interpreters / nitfol / nitfol.texi
1 \input texinfo     @c -*-texinfo-*-
2 @setfilename nitfol.info
3 @settitle Nitfol
4
5 @ifinfo
6 @dircategory Games
7 @direntry
8 * nitfol: (nitfol).               Z-code interpreter and debugger.
9 @end direntry
10 @end ifinfo
11
12 @contents
13
14 @node Top , Invoking nitfol , (dir) , (dir)
15 @top Introduction
16
17 @c Workaround for bug in texi2html
18 @ifnotinfo
19 @ifnottex
20 @node Introduction , Top , (dir) , (dir)
21 @chapter Introduction
22 @end ifnottex
23 @end ifnotinfo
24
25 Nitfol is a portable interpreter for Z-machine code, the game format used by Infocom and more recently, @uref{http://www.gnelson.demon.co.uk/inform.html, Inform}.  Nitfol handles versions one through eight of the format, and attempts to comply with version 1.0 of the Z-machine specification.
26
27 You will need game files to use nitfol.  The ``if-archive'' contains a large collection of these, available at @uref{ftp://ftp.gmd.de/if-archive/games/zcode/} or at the USA mirror @uref{http://ifarchive.org/indexes/if-archiveXgamesXzcode.html}.
28
29 This manual describes how to use nitfol and how it differs from other Z-machine interpreters.  This manual was written with @sc{unix}-like systems in mind; ignore that which does not apply to your platform.  Comments on and corrections for this manual and nitfol are appreciated and should be sent to @email{nitfol@@my-deja.com}.
30
31 @menu
32 * Invoking nitfol::               How to start nitfol under @sc{unix}
33 * Features::                      Useful extras
34 * Debugger::                      Built in source-level debugger
35
36 * Bugs::                          What I know is wrong
37 * Thanks::                        List of people who've helped
38 * Games Cited::                   The games used as examples in this manual
39 @end menu
40
41
42
43 @node Invoking nitfol , Features , Top, Top
44 @chapter Invoking nitfol
45
46 Invoke nitfol with the game filename, and options.  If you omit the game filename, nitfol will prompt you for one.  The following options are recognized:
47
48 @table @code
49 @include options.texi
50 @end table
51
52 @node Features , Debugger , Invoking nitfol , Top
53 @chapter Features
54
55 @menu
56 * Preferences::                   Store options in @file{~/.nitfolrc}
57 * Infinite undo/redo::            Erase your mistakes and bad luck
58 * Aliases::                       Abbreviate long/common words
59 * Abbreviation Expansion::        Expand one letter commands
60 * Typo correction::               Nitfol uses a smart tokeniser
61 * Automapping::                   Automatically generate an on-screen map
62 * Quetzal::                       Save files are in Quetzal format
63 * Blorb::                         Nitfol supports Blorb resources
64 @end menu
65
66 @node Preferences , Infinite undo/redo , Features , Features
67 @section Preferences
68
69 If you don't like the default options and don't want to recompile, you can set your preferences by writing a @file{.nitfolrc} in your home directory.
70
71 Each line should be of the form @code{@var{option}=@var{value}}.  Blank lines and lines starting with a @code{#} are ignored.  If you want to specify different options for different copies of nitfol, you can put those options in a block which will only be read by copies of nitfol with a specific name.
72
73 Here's an example @file{.nitfolrc}:
74 @example
75 path=/usr/local/games/infocom
76 alias=v verbose
77 alias=asierra tone cordial. ask sierra about
78 ignore=true
79
80 [strictnitfol]
81 ignore=false
82 spell=false
83 expand=false
84 autoundo=false
85 unalias=v
86 unalias=asierra
87
88 [xnitfol]
89 tandy=true
90 pirate=true
91 @end example
92
93 Nitfol will look in @file{/usr/local/games/infocom} for game files.  Copies of nitfol named @file{strictnitfol} will report Z-machine strictness errors, perform strict tokenisation, and not automatically @code{@@save_undo}.  All others will ignore strictness errors and have two aliases.  @file{xnitfol} will set the Tandy bit and branch on the piracy opcode.
94
95 Options specified in the preference file may be overruled by environment variables and command line options.
96
97
98 @node Infinite undo/redo , Aliases , Preferences , Features
99 @section Infinite undo/redo
100
101 Multiple @code{@@restore_undo} opcodes with no intervening @code{@@save_undo} will restore earlier and earlier saved states.  However, Inform games will not do this, so if you want infinite undo, you must enter the commands @code{/undo} and @code{/redo}. The @code{/@dots{}} commands are part of the debugger, so you will need to compile in debugger support to use this feature.
102
103 Z-machine games prior to version 5 do not provide undo (none of them provide redo), and some version 5 games don't use it (like @cite{Wishbringer}).  If the game performs two @code{@@read} opcodes with no intervening @code{@@save_undo} or @code{@@restore_undo}, nitfol will perform a @code{@@save_undo}.
104
105
106 @node Aliases , Abbreviation Expansion , Infinite undo/redo , Features
107 @section Aliases
108
109 If the game has long words which you wish to abbreviate, you can use aliases.  Use the command @code{/alias @var{name} @var{value}}.  All instances of @var{name} in line input will be replaced with @var{value}.  @var{name} may not contain whitespace.
110
111 Unlike abbreviation expansion and typo correction, alias expansion modifies the text buffer, inserting the requested text.  This is necessary to allow multiple commands to be given in an alias through the use of periods.
112
113 Aliases are not expanded recursively, so you could do something clever like this:
114 @example
115 >@kbd{/alias e w}
116 @kbd{/alias w e}
117 @kbd{/alias nw ne}
118 @kbd{/alias ne nw}
119 @kbd{/alias sw se}
120 @kbd{/alias se sw}
121 @end example
122
123 And your east-west movement will be swapped (@kbd{e} will do a @kbd{w}, though @kbd{east} will still do @kbd{east}).  Aliases expand on all input the game receives using @code{@@read}, including transcripts and directions from the automapper.
124
125 If you want the expansion of the alias to be checked for further aliases, you must use the @code{/ralias} command.  This expansion is stopped when an alias would expand itself.
126 @example
127 >@kbd{/ralias e w}
128 @kbd{/ralias w e}
129 @end example
130
131 Would do nothing, as @kbd{e} is expanded to @kbd{w}, which is expanded to @kbd{e}, and then it stops because the rule for expanding @kbd{e} has already taken place.
132
133 @example
134 >@kbd{/ralias hanoi2 move src to extra. move src to dest. move extra to dest}
135 @kbd{/alias src left}
136 @kbd{/alias dest center}
137 @kbd{/alias extra right}
138 @kbd{hanoi2}
139 You move the small disc from the left peg to the right peg.
140 You move the medium disc from the left peg to the middle peg.
141 You move the small disc from the right peg to the middle peg.
142 >move left to right
143 You move the large disc from the left peg to the right peg.
144 >@kbd{/alias src center}
145 @kbd{/alias dest right}
146 @kbd{/alias extra left}
147 @kbd{hanoi2}
148 You move the small disc from the middle peg to the left peg.
149 You move the medium disc from the middle peg to the right peg.
150 You move the small disc from the left peg to the right peg.
151 @end example
152
153 Ideally you should be able to define an alias which recursively solves any depth by relying on lower levels being solvable, but this isn't yet possible.  You must keep the expansion of aliases to a reasonable size, since Inform has a fairly small buffer size.
154
155 You can remove aliases using the @code{/unalias} command.
156 @example
157 >@kbd{/unalias hanoi2}
158 @end example
159
160 Aliases do not effect @code{/@dots{}} commands; if they did, it wouldn't be possible to @code{/unalias}.
161
162
163 @node Abbreviation Expansion , Typo correction , Aliases , Features
164 @section Abbreviation Expansion
165
166 Early Infocom games don't provide abbreviations like @kbd{x} for @kbd{examine}.  If you enable abbreviation expansion, nitfol will attempt to expand one letter words at the beginning of inputs which are not in the game's dictionary.
167
168 Nitfol supports the following expansions (note that some are non-standard):
169
170 @multitable {i} {inventory} {i} {inventory} {i} {inventory} {i} {inventory}
171 @item c @tab close
172  @tab d @tab down
173  @tab e @tab east
174  @tab g @tab again
175 @item i @tab inventory
176  @tab k @tab attack
177  @tab l @tab look
178  @tab n @tab north
179 @item o @tab oops
180  @tab p @tab open
181  @tab q @tab quit
182  @tab r @tab drop
183 @item s @tab south
184  @tab t @tab take
185  @tab u @tab up
186  @tab w @tab west
187 @item x @tab examine
188  @tab y @tab yes
189  @tab z @tab wait
190 @end multitable
191
192 From @cite{Zork I}:
193 @example
194 @group
195 @strong{West of House}
196 You are standing in an open field west of a white house, with a
197 boarded front door.
198 There is a small mailbox here.
199
200 >@kbd{x mailbox}
201 [x -> examine]
202 The small mailbox is closed.
203 @end group
204
205 @group
206 >@kbd{p it}
207 [p -> open]
208 Opening the small mailbox reveals a leaflet.
209 @end group
210
211 @group
212 >@kbd{t leaflet}
213 [t -> take]
214 Taken.
215 @end group
216 @end example
217
218
219 @node Typo correction , Automapping , Abbreviation Expansion , Features
220 @section Typo correction
221
222 In the Z-machine, the @code{@@read} opcode provides the interpreter with a dictionary to search in order to do tokenisation and word matching.  If you enable typo correction and enter a word not in the provided dictionary, nitfol will search for near misses.
223
224 From @cite{Curses}:
225 @example
226 @group
227 >@kbd{ask jemmia about gloves}
228 [jemmia -> jemima]
229 "Those are my gloves."
230 @end group
231 @end example
232
233 Nitfol takes the following steps to correct typos:
234
235 @enumerate
236 @item
237 If the entered word is in the dictionary, behave as normal.
238
239 @item
240 If the length of the word is less than 3 letters long, give up.  We don't want to make assumptions about what so short words might be.
241
242 @item
243 If the word is the same as a dictionary word with one transposition, assume it is that word.  @kbd{exmaine} becomes @kbd{examine}.
244
245 @item
246 If it is a dictionary word with one deleted letter, assume it is that word.  @kbd{botle} becomes @kbd{bottle}.
247
248 @item
249 If it is a dictionary word with one inserted letter, assume it is that word.  @kbd{tastey} becomes @kbd{tasty}.
250
251 @item
252 If it is a dictionary word with one substitution, assume it is that word.  @kbd{opin} becomes @kbd{open}.
253 @end enumerate
254
255 This behavior can be annoying when nitfol ``corrects'' intentionally entered words which are similar to dictionary words.  Usually this has no effect upon the game, perhaps slightly changing the game's error message, but may have negative effects when it causes an undesired action.  Games like @cite{Beyond Zork} expect you to type words not in their dictionary to name things.  Nitfol might ``correct'' your entered word to a dictionary word, which the game might complain about.
256
257 If typo correction is getting in your way, run nitfol with @samp{-no-smart}, compile it without applying @samp{-DSMART_TOKENISER}, or edit @file{nitfol.opt} to change the compile-time default.
258
259
260 @node Automapping , Quetzal , Typo correction , Features
261 @section Automapping
262
263 Nitfol has the ability to display an on-screen map showing visited rooms and their connections on the current floor.  Below is a map generated from @cite{Enchanter}.
264 @example
265 @group
266                                    *-* *
267                                    |   |
268                    u-*-*-*-*-------*---*
269                    |               |
270        * *   *     |     *---*     |
271        |/ \ /      |    /|\ / \    |
272        *   *       *   / | X * \   *
273       /     \      |  /  |/ v|  \  |
274      /   *   *-*-*-*-*---*---u---*-*-*-@@
275     /    |  /      | |\  |\ ^|  /  |    
276  *-*     * *       | | \ | X * /   *-*
277     \    |/        | |  \|/ \ /    |  
278      *   *         * *   *---*     *
279       \ /          | |             |
280        *           u-d-*-----------*-u
281                                    |  
282                                    *
283                                     \
284                                      *
285 @end group
286 @end example
287
288 The @samp{*}s designate rooms; the @samp{@@} the current room.  Rooms containing staircases are shown with a @samp{u} or @samp{d}, or @samp{b} if the staircase is bi-directional.  If the current room contains a staircase, nitfol draws it with a @samp{U}, @samp{D}, or @samp{B}.  Passageways are shown with lines; the @samp{X}s are crossed lines.  One-way passages are shown as lines with arrows.  Nitfol uses @samp{v}, @samp{^}, @samp{<}, and @samp{>} for arrow heads.
289
290 In Glks which provide mouse events, you can click on rooms and it will display the room name (and number) in the upper left hand corner of the map.  Note that XGlk is slightly broken, so you need to click on the left-hand side of the room.  Clicking on an empty map space clears the name.
291
292 In order to use automapping, you must tell nitfol how to calculate the current location.  You do this by specifying an Inform expression, so you must have debugging enabled.
293
294 Typically the current location is available in a global.  In Z-code versions 3 and prior, the current location is always stored in global zero, so typing @kbd{/automap (global) 0} should work.  In later versions, you must figure out an expression which evaluates to the current location.
295
296 First, find out where the player object is.  Typically, the player object is named @samp{self}, @samp{cretin}, @samp{self-object}, or the name of the PC.  You can use the @code{find} command to search object names.  If this all fails, try @code{object-tree} to find the location number.
297
298 Once you have found the number of the location, you need to figure out which global keeps track of the location.  You can use the @code{globals} command to search the globals.
299
300 From @cite{Spider And Web}:
301 @example
302 @group
303 >@kbd{/find self}
304 20 "(self object)"
305 25 "yourself" in 91 "End of Alley"
306 26 "yourself" in 48 "chair"
307 @kbd{/globals 91}
308 G15 G36 G39
309 @end group
310 @group
311 @kbd{s}
312
313 @strong{Mouth of Alley}
314 You're in the entrance of a narrow brick alley, which runs further
315 in to the north. To the south a broad street courses by, congested
316 with traffic and bicycles, although none of them seem to notice you.
317 @end group
318
319 @group
320 >@kbd{/find self}
321 20 "(self object)"
322 25 "yourself" in 94 "Mouth of Alley"
323 26 "yourself" in 48 "chair"
324 @end group
325 @group
326 @kbd{/globals 94}
327 G15 G36 G39
328 @end group
329 @kbd{/automap (global) 15}
330 @end example
331
332 Obviously we have 3 globals tracking the player location.  Typically there are only two, but some games have more.  In this, we just picked the first one, which is probably the Inform @code{location} variable; another is probably the @code{real_location} variable.  Depending on how you want automapping to behave in the dark, or when dealing with game-specific stuff, you may want to pick a different one.
333
334 To figure out what is in which direction, nitfol checks the current location, tells the game to go north, checks the new location, undoes the north movement, tries to go northeast, and so on.  During all of this, output is disabled.
335
336 Drawing the map is more complicated.  First nitfol looks for cycles in the graph and makes the cycles connect properly.  Then it draws the map.  If parts of the map overlapp, it finds a path connecting the overlapping bits and tries increasing the length of each passage in this path by one, and recalculates cycle connections.  If this solves the problem, it's done; otherwise, it tries increasing the length of two passages, or of one of the passages by two.  If this fails, it gives up.
337
338 This technique isn't perfect.  The implementation of this technique isn't perfect either.  So expect nitfol to misbehave a lot on complex maps, and a little on simple maps.  If you clever ideas on how to improve it, let me know.
339
340 Nitfol makes an effort to simplify the map.  If multiple exits go from the barn to cornfield and you've been to both places, nitfol will draw a single two-way passage if possible.  If both up and west go up the stairs and nitfol knows east returns from the top of the stairs, nitfol will draw it as a simple west-east passage ignoring the up/down.  If east doesn't return from the top of the staircase, nitfol will draw it as up/down, leaving out the west passage.
341
342 If you've been north of a gate, and come up to the gate from the south,
343 and unlock the gate, nitfol will draw it as a one-way passage since last
344 time it was north of the gate, it couldn't go south.
345
346 Some games feature reincarnation, perhaps moving you to a new location.  If movement leads to your death, this makes nitfol think the reincarnation location is in that direction.  Nitfol watches for three asterisks in a row and will assume they mean death instead of a normal passage.
347
348 Some of these problems could be avoided by having nitfol explore each neighboring room, but this would make automapping even slower.
349
350
351 @node Quetzal , Blorb , Automapping , Features
352 @section Quetzal
353
354 Nitfol uses Quetzal version 1.4 for its save format, so you can use your saves between different computers and interpreters.  More information about Quetzal is available at @uref{http://www.geocities.com/SiliconValley/Vista/6631/}.
355
356 If you specify a save-file on the command-line on @sc{unix}, nitfol uses a @code{UNIX} @code{IntD} chunk to locate the game file associated with the save name.  This chunk is included in save games when nitfol can figure out the current filename.  If you compile nitfol with -D__USE_GNU, -D__USE_BSD, or -D__USE_XOPEN_EXTENDED, nitfol will canonicalize the file name, so you don't have to worry about relative file name specifications no longer working if you invoke nitfol from a different directory.
357
358 On MacOS, nitfol uses alias records from a @code{MACS} @code{IntD} chunk to locate the game file.  This won't work for games built-in to the interpreter.
359
360 If no @code{IntD} chunk is included, nitfol searches the environment variable @code{INFOCOM_PATH} for a game with matching release number, serial number, and checksum.
361
362 Looking for games without an @code{IntD} chunk isn't foolproof, but it should work most of the time.  Serial numbers are basically the date and it's extremely unlikely more than ten games will be compiled on the same day (the only time lots of games are compiled on same day is right before competition time).  Assuming they all have the same release number, there's still only a .0686% chance that at least two of these ten will share the same checksum.  If someone reports this as a problem, I'll make nitfol ensure the game contains a @code{save} opcode right before the restored PC.
363
364
365 @node Blorb ,  , Quetzal , Features
366 @section Blorb
367
368 If you wish to hear sounds or see graphics in your games, they must be packaged in Blorb files.  The Z-machine game may included in the Blorb file or may be specified separately.  Nitfol does not support the traditional Infocom @file{.mg1} and @file{.snd} files.
369
370 Note that graphics are displayed incorrectly, and sound has not yet been tested.
371
372 @node Debugger , Bugs , Features , Top
373 @chapter Debugger
374
375 Nitfol debugging mode tries to imitate the GDB interface.  If you're familiar with that, you should have no problem using nitfol (other than dealing with the current incompleteness).
376
377 You need inform 6.21 or later, as earlier versions don't produce correct infix files without a patch.  You then need to compile infix information for your game.  I recommend doing:
378
379 @code{inform -k -~S -~X -~D @var{MyGame}.inf}
380
381 Then your debug information will be in @file{gameinfo.dbg}.  If you have a command-line on your platform, run nitfol like @code{nitfol @var{MyGame}.z5 -symbols gameinfo.dbg}.  Otherwise, start up your game and type @code{/symbol-file gameinfo.dbg} the first time you get a prompt.
382
383 When the game stops to read a line of text, you can begin that line with @kbd{/} to give a debug command.  If you want to pass a line beginning with a @kbd{/} to the game, double the @kbd{/} and the game will be passed the second one.  When at a @code{(nitfol) } prompt, starting commands with @kbd{/} is neither necessary nor recommended.
384
385 All expressions are like the ones used in Inform.
386
387 You can perform casts to get the result in the form you want:
388
389 @table @code
390 @item (number) @var{expression}
391 Use @var{expression} as if it were a number.  Useful when you want to know the number of something, not the object, routine, or string information nitfol normally gives.
392 @item (object) @var{expression}
393 Use @var{expression} as if it were an object.  Most useful when printing the result, as it will show the object's attributes and properties.
394 @item (routine) @var{expression}
395 Use @var{expression} as if it were the packed address of a routine.  Useful if you have the packed address of a routine which you want to set a breakpoint at.
396 @item (string) @var{expression}
397 Use @var{expression} as if it were the packed address of a string.  Useful for printing it.
398 @item (global) @var{expression}
399 Evaluates to the value of a numbered global.  @code{(global) 0} is the player location for version 3 Infocom games.
400 @item (local) @var{expression}
401 Evaluates to the value of a numbered local.  Not terribly useful unless you're debugging something without source.
402 @end table
403
404 Here are short descriptions of the debugger commands.  @inforef{Top,,gdb}, for more information.  Some of these were taken/adapted from GDB's help.
405
406 @ftable @code
407 @include dbg_help.texi
408 @end ftable
409
410 If you're on a @sc{unix} and you don't like the GDB interface, you can compile cheapnitfol and run it as the inferior debugger under Emacs or DDD.  You can also try compiling @code{xnitfol} with @samp{-DSTDOUT_DEBUG} and trying that, but I haven't tested that much.
411
412 @noindent
413 @code{ddd @var{MyGame}.z5 --debugger cheapnitfol -s gameinfo.dbg -prompt "(gdb) "}
414
415 @node Bugs , Thanks , Debugger , Top
416 @chapter Bugs
417
418 A nitfol bug is any behaviour which makes nitfol reliably misbehave, with the exceptions of bugs in Glk libraries.  These include: anything which makes nitfol crash (other than when nitfol reports @samp{FATAL} errors), anything which causes nitfol to contradict the Z-machine standards documents (except for optional enhancements like spelling correction and debug mode), any buffer overflows, and anything which makes nitfol infinite loop other than infinite loops in the game itself.
419
420 Before reporting a bug, make sure the bug is not listed below and your copy of nitfol is not compiled with @samp{-DFAST}.  Please report the version of nitfol, your system type and a series of commands which reliably cause the bug.
421
422 Nitfol is lacking:
423 @itemize @minus
424 @item Graphical font (@cite{Beyond Zork})  (should use images for this)
425 @item Terminating character support (mostly @cite{Beyond Zork})
426 @item Reverse video, full color (should querry Glk more aggressively)
427 @item Unicode support
428 @item keypad character codes
429 @item its own random number generator (relies on system one)
430 @end itemize
431
432 Nitfol does incorrectly:
433 @itemize @minus
434 @item Play is not paused to wait for sounds to complete in @cite{The Lurking Horror}.
435 @item Pictures and text are not placed correctly for v6 games.
436 @item block quotes are placed in the upper window, so @code{cheapnitfol} can't see them.
437 @item Corrupted save files may make nitfol do bad things.
438 @item Should figure out a way to handle buggy games like @cite{AMFV} and @cite{Varicella} which assume the upper window is 80 columns wide.
439 @item Doesn't catch header writing other than @code{@@storeb} and @code{@@storew}.
440 @end itemize
441
442 Debugger problems:
443 @itemize @minus
444 @item Sometimes says there's no code at a location where it could be clever and
445   find some.
446 @item @code{ofclass}, superclass not implemented.
447 @item Should perform more sanity checks everywhere.
448 @item Lots of useful commands not yet implemented.
449 @item @var{object}.@var{function} is handled incorrectly, both for assignments and calls.
450 @item Assumes you know what you're doing, so @code{quit}, @code{run}, etc., don't prompt you for confirmation.
451 @end itemize
452
453 Automapping problems:
454 @itemize @minus
455 @item Doesn't work well for random destinations (the forest in @cite{Advent})
456 @item @code{@@get_cursor} doesn't return the correct value during automapping since output is disabled.
457 @item Requires too much work for the end-user; should put in stuff to make it figure out the location global in 95% of games.
458 @item Doesn't really work if multiple locations are coded as being in the same room (long road in @cite{Enchanter}).
459 @item Doesn't show exits which go nowhere, but change the game.
460 @item Perhaps should use graphics windows when available.
461 @item Movement causing teleportation confuses it.
462 @item Reincarnation handling isn't optimal.
463 @item Still very buggy.
464 @item It's too slow.
465 @item Should realize it can add extra bends (especially in one-way passages).
466 @item Should be able to output nice-looking Postscript.
467 @item Should store map in saved games (wait until automapping code stabilizes).
468 @end itemize
469
470 @node Thanks , Games Cited , Bugs , Top
471 @chapter Thanks
472
473 The following people have given comments, suggestions, bug reports, answered questions, or helped port nitfol (in alphabetical order):
474 @itemize @minus
475 @item John Cater
476 @item Paul David Doherty
477 @item Martin Frost
478 @item Doug Jones
479 @item David Picton
480 @item Andrew Plotkin
481 @item Andrew Pontious
482 @item L. Ross Raszewski
483 @item Dan Shiovitz
484 @end itemize
485
486 @node Games Cited ,  , Thanks , Top
487 @chapter Games Cited
488
489 @noindent
490 @cite{Wishbringer} Copyright @copyright{} 1985, 1988 Infocom Inc.
491
492 @*
493 @noindent
494 @cite{Zork I} Copyright @copyright{} 1981-1986 Infocom Inc.
495
496 @*
497 @noindent
498 @cite{Curses} Copyright @copyright{} 1993-1994 Graham Nelson.
499
500 @uref{http://ifarchive.org/if-archive/games/zcode/curses.z5}
501
502 @*
503 @noindent
504 @cite{Beyond Zork} Copyright @copyright{} 1987 Infocom Inc.
505
506 @*
507 @noindent
508 @cite{Enchanter} Copyright @copyright{} 1983, 1984, 1986 Infocom Inc.
509
510 @*
511 @noindent
512 @cite{Varicella} by Adam Cadre 1999.
513
514 @uref{http://adamcadre.ac/content/vgame.z8}
515
516 @*
517 @noindent
518 @cite{Spider And Web} Copyright @copyright{} 1997-1998 Andrew Plotkin.
519
520 @uref{http://ifarchive.org/if-archive/games/zcode/Tangle.z5}
521
522 @bye
523