zzzzz eeee aaaa l z e e a a l zz eeeee a a l zz e a a l z e e a aa l zzzzz eeee aaa a lll zeal 1.1 readme jeremy condit -------------------------------------------------------------------------- welcome to zeal! contents: i. what is zeal? ii. compiling zeal iii. using zeal iv. known bugs and shortcomings v. notes for nerds vi. copying zeal vii. acknowledgments viii. contact info -------------------------------------------------------------------------- i. what is zeal? zeal is a z-code interpreter capable of running version 1-5 and 7-8 story files. if you don't know what this means, have a look at graham nelson's inform page for more info about interactive fiction, the z-machine, and inform. also, the if-archive at gmd.de has tons of software and information related to interactive fiction. http://www.gnelson.demon.co.uk/inform/ ftp://ftp.gmd.de/if-archive/ zeal is written from scratch in c++ and uses the glk interactive fiction i/o api and a pseudo-random number generator called mersenne twister (see acknowledgments below). it relies on very few machine or system dependent features, and those that it does rely on it attempts to abstract away. some parts of the z-machine specification are as yet unimplemented, but those parts are infrequently used by games; in fact, every game i've tried to play with zeal works just fine or doesn't work for a "good" (i.e. known) reason. if i was selling zeal, i'd put these bullets on the box: o runs version 1-5 and 7-8 story files o supports quetzal saved-game format o supports standard strictz levels o uses the glk api o uses a slick random number generator o portable to be perfectly honest, though, zeal's feature set is basically a subset of the features offered by some of the other interpreters available (most notably nitfol). why bother, then? zeal actually started as a random coding challenge and ultimately became a usable program, so i figured i'd give it away to anybody who happens to be interested. enjoy! -------------------------------------------------------------------------- ii. compiling zeal if you downloaded a compiled application for a specific platform, skip to the next section. * unix: zeal should work with either the xglk or glkterm libraries, which you can obtain from the following url: http://eblong.com/zarf/glk/ compile whichever glk library you chose. if you're using glkterm or xglk, put their directory and the zeal directory in the same parent directory, and then set the GLKLIB variable in zeal's makefile to the glk library you're using. (if you're using something other than glkterm or xglk, you'll need to add a few extra lines to the makefile.) cross your fingers, and try compiling with the following: make depend make if all goes well, you should have a zeal binary available. if not, try changing the compiler or the compiler flags to suit your particular machine. note that you may need to change the definitions of glui32 and glsi32 in glk.h. (you're on your own from this point forward, but if you fix the makefile for a particular unix os, please let me know what you did!) i've successfully compiled zeal under digital unix, linux, and freebsd. for freebsd, i had to use c++ instead of g++ to compile, but otherwise things worked fine. note that zeal does not use glk's 32-bit integers to store pointers, so you can safely compile zeal on a 64-bit machine (e.g. an alpha) without modifications, though you may need to remove some warnings from glkterm and adjust the types in glk.h. * mac & windows: you're more or less on your own here. code and resources for interfacing with macglk and windowsglk are provided in mac.* and win.*; follow directions accompanying these glk libraries to figure out how to build zeal for your favorite os. you'll probably need to tweak include paths and that kind of thing, but you shouldn't need to write any new code. * and finally: please see the notes about copying/distribution of zeal source and executables (below) if you intend to do so! -------------------------------------------------------------------------- iii. using zeal * unix: under unix systems running glkterm or xglk, zeal can be run from the command line using the following syntax: zeal [-d] [-strictz n] [filename] xzeal [-d] [-strictz n] [filename] the options are as follows: -d turns on debug mode. a trace will be written to the file debug.log during execution. -strictz n set the strictz value for the game being played. strictz determines the level of warnings issued by the interpreter for story files that use the z-machine improperly but in a non-fatal way. the value of n determines the behavior on such an error as follows: 0: do nothing 1: issue a warning once for each type of error (default) 2: issue a warning on every occurrence of every error 3: halt on the first occurrence of an error filename the name of story file with a game to be run. the glk library may provide additional options; run zeal with an invalid flag (say, -h) or look at the library documentation to learn about those options. of course, the options above apply only to the glkterm/xglk version of zeal. * mac & pc: run zeal by double-clicking the application and then select the game you'd like to play using the dialog that pops up. * and finally: as with zip, you are expressly forbidden to use this program on an infocom game data file if, in so doing, you violate the copyright notice supplied with the original infocom game. (thanks to the xzip man page for the wording of this notice.) -------------------------------------------------------------------------- iv. known bugs and shortcomings zeal works well with the vast majority of z-machine games out there, but there are still a bunch of issues to be addressed: o a few opcodes aren't implemented (e.g. catch, throw, unicode stuff) o text style support is shaky o no color o no sound -------------------------------------------------------------------------- v. notes for nerds if you're interested in zeal's design, here are a few quick thoughts. the basic design principle is encapsulation of structured portions of the z-machine's memory with c++ classes. that is, certain data structures in the z-machine's memory (e.g. alphabet tables, dictionaries, objects, and properties) can be represented in the interpreter as objects of classes. the objects themselves just store an address within the machine's memory, but they export a higher-level interface for these objects. the rest of the interpreter is clumped together at a very high level. there are classes for the machine itself (memory plus variables plus stacks) and for the i/o interface. an abstract class is used to represent os-dependent features, and a set of classes are used to represent the string decoder and objects to which the decoder can send data (i.e. different kinds of streams). the highest levels of the interpreter are in glk_main (zeal.cc), which has initialization and main loop code, and in machine::one_inst (machine.cc), which has instruction fetch and decode algorithms. each instruction is handled by looking up a function corresponding to that instruction in a table. each instruction handler then passes control to one of the classes described above, as appropriate. i've tried to keep most of the complexity out of the instruction handlers. global data includes three pointers: m (the machine itself), io (the i/o class), and os (the os-dependent parts). the io object could probably be nested within the m object, but i didn't feel like doing this just yet. what i like about zeal: o instruction decoding by table lookup and function pointers o mapping c++ classes onto structured parts of z-machine memory (eliminates lots of errors!) o encapsulation of memory operations (machine), i/o operations (iface), and os-dependent features (osdep) o cool random number generator (see acknowledgments below) o my own (v)snprintf, so i don't have to rely on the system providing one (many systems don't) o useful error-reporting system what i don't like about zeal: o the machine and iface classes aren't very well split up--there are a few monolithic classes that are instantiated once, stuck in a global variable, and referenced everywhere o instruction handlers aren't a member of any class--they could probably be put in the machine class, but that would make the machine class even more bloated, which is why i'm hesitant to do it o i'm still unsure of the decoding mechanism for strings of z-chars (the bfish class)--it is designed to produce output by calling another component's put_char function for each resulting character, which seems to work reasonably well, but i still can't convince myself that there's not a better way -------------------------------------------------------------------------- vi. copying zeal zeal has been released under the gnu general public license. for a copy, look at the COPYING file that should have accompanied this distribution. basically, the GPL says that you are free to copy, modify, and redistribute zeal as long as you make the complete source code available when you do so. zeal uses a third-party random number generator library (see the acknowledgments below) that is released under the LGPL. see the COPYING.LIB file for a copy of the license for this library. if you did not receive the source code for zeal with this distribution, it can be obtained from one of the urls listed in the contact info section below. IMPORTANT NOTE ABOUT ZEAL EXECUTABLES: i'm no lawyer, but it looks like section 6 of the LGPL prohibits distribution of binaries compiled using commercial compilers/libraries. so, please do not distribute executables for any platform without first removing the LGPL'ed random number generator or obtaining appropriate permission (or proving me wrong). i personally have no problem with people distributing zeal executables that have been compiled with commercial compilers and linked against their libraries--if you'd like to do so, go right ahead, as long as you adhere to the notice above. however, if you make any modifications to zeal itself, you are required to distribute the source for your modifications as well. -------------------------------------------------------------------------- vii. acknowledgments thanks to andrew plotkin for designing glk and implementing glkterm and xglk. glk information can be found at the following url: http://eblong.com/zarf/glk/ more thanks to andrew for supplying the code and resources for interfacing with the macglk library. thanks to m. matsumoto and t. nishimura for the mersenne twister pseudo-random number generator. i'm using a version that generates numbers in the range [0,1), which was coded by t. nishimura, using suggestions by topher cooper and marc rieffel. this library was released under the LGPL; see random.cc for code and contact information, and see the COPYING.LIB file for the LGPL. the following url provides more information about mersenne twister: http://www.math.keio.ac.jp/~matumoto/emt.html thanks to glkzip (by daniel schepler) for ideas about structuring the makefile. thanks to mike for listening to me babble about this program all the time, and thanks to norman for getting me interested in interactive fiction again. -------------------------------------------------------------------------- viii. contact info if you'd like to contact me for any reason, feel free to write to jcondit@eecs.harvard.edu. you can obtain the latest version of zeal from the following urls: http://www.eecs.harvard.edu/~jcondit/zeal/ ftp://ftp.gmd.de/if-archive/