├── .gitignore ├── .gitmodules ├── ARTISTIC ├── AUTHORS ├── COPYING ├── Makefile ├── NEWS ├── README.md ├── VERSION ├── contrib ├── README ├── inform-mode.el ├── pblorb.pl └── scanblorb.pl ├── demos ├── README ├── advent.inf ├── adventureland.inf ├── balances.inf ├── museum.inf ├── ruins1.inf ├── ruins2.inf ├── ruins3.inf └── toyshop.inf ├── docs ├── README.glulx ├── README.include ├── README.library ├── README.paths ├── README.translation └── README.version ├── include ├── dmenus.h ├── doors.h ├── doors2.h ├── footnote.h ├── helproutines.h ├── howtoplay.h ├── mistype.h ├── moveclass.h ├── newbiegrammar.h ├── seeno.h ├── shuffle.h ├── smartcantgo.h ├── sound.h ├── tmenus.h ├── torch.h ├── trinitystat.h ├── whowhat.h ├── yesno.h └── zclock.h ├── inform.1 └── tutor ├── README ├── alice.inf ├── alice.txt ├── aloneice.inf ├── house01.inf ├── house02.inf ├── house03.inf ├── house04.inf ├── house05.inf ├── house06.inf └── house07.inf /.gitignore: -------------------------------------------------------------------------------- 1 | *[A-Z]*.h 2 | *.m5 3 | *.z5 4 | 5 | lib/ 6 | src/ 7 | 8 | inform 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib"] 2 | path = lib 3 | url = git://github.com/DavidGriffith/inform6lib.git 4 | [submodule "src"] 5 | path = src 6 | url = git://github.com/DavidKinder/Inform6.git 7 | -------------------------------------------------------------------------------- /ARTISTIC: -------------------------------------------------------------------------------- 1 | The Artistic License 2.0 2 | 3 | Copyright (c) 2000-2006, The Perl Foundation. 4 | 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | This license establishes the terms under which a given free software 11 | Package may be copied, modified, distributed, and/or redistributed. 12 | The intent is that the Copyright Holder maintains some artistic 13 | control over the development of that Package while still keeping the 14 | Package available as open source and free software. 15 | 16 | You are always permitted to make arrangements wholly outside of this 17 | license directly with the Copyright Holder of a given Package. If the 18 | terms of this license do not permit the full use that you propose to 19 | make of the Package, you should contact the Copyright Holder and seek 20 | a different licensing arrangement. 21 | 22 | Definitions 23 | 24 | "Copyright Holder" means the individual(s) or organization(s) 25 | named in the copyright notice for the entire Package. 26 | 27 | "Contributor" means any party that has contributed code or other 28 | material to the Package, in accordance with the Copyright Holder's 29 | procedures. 30 | 31 | "You" and "your" means any person who would like to copy, 32 | distribute, or modify the Package. 33 | 34 | "Package" means the collection of files distributed by the 35 | Copyright Holder, and derivatives of that collection and/or of 36 | those files. A given Package may consist of either the Standard 37 | Version, or a Modified Version. 38 | 39 | "Distribute" means providing a copy of the Package or making it 40 | accessible to anyone else, or in the case of a company or 41 | organization, to others outside of your company or organization. 42 | 43 | "Distributor Fee" means any fee that you charge for Distributing 44 | this Package or providing support for this Package to another 45 | party. It does not mean licensing fees. 46 | 47 | "Standard Version" refers to the Package if it has not been 48 | modified, or has been modified only in ways explicitly requested 49 | by the Copyright Holder. 50 | 51 | "Modified Version" means the Package, if it has been changed, and 52 | such changes were not explicitly requested by the Copyright 53 | Holder. 54 | 55 | "Original License" means this Artistic License as Distributed with 56 | the Standard Version of the Package, in its current version or as 57 | it may be modified by The Perl Foundation in the future. 58 | 59 | "Source" form means the source code, documentation source, and 60 | configuration files for the Package. 61 | 62 | "Compiled" form means the compiled bytecode, object code, binary, 63 | or any other form resulting from mechanical transformation or 64 | translation of the Source form. 65 | 66 | 67 | Permission for Use and Modification Without Distribution 68 | 69 | (1) You are permitted to use the Standard Version and create and use 70 | Modified Versions for any purpose without restriction, provided that 71 | you do not Distribute the Modified Version. 72 | 73 | 74 | Permissions for Redistribution of the Standard Version 75 | 76 | (2) You may Distribute verbatim copies of the Source form of the 77 | Standard Version of this Package in any medium without restriction, 78 | either gratis or for a Distributor Fee, provided that you duplicate 79 | all of the original copyright notices and associated disclaimers. At 80 | your discretion, such verbatim copies may or may not include a 81 | Compiled form of the Package. 82 | 83 | (3) You may apply any bug fixes, portability changes, and other 84 | modifications made available from the Copyright Holder. The resulting 85 | Package will still be considered the Standard Version, and as such 86 | will be subject to the Original License. 87 | 88 | 89 | Distribution of Modified Versions of the Package as Source 90 | 91 | (4) You may Distribute your Modified Version as Source (either gratis 92 | or for a Distributor Fee, and with or without a Compiled form of the 93 | Modified Version) provided that you clearly document how it differs 94 | from the Standard Version, including, but not limited to, documenting 95 | any non-standard features, executables, or modules, and provided that 96 | you do at least ONE of the following: 97 | 98 | (a) make the Modified Version available to the Copyright Holder 99 | of the Standard Version, under the Original License, so that the 100 | Copyright Holder may include your modifications in the Standard 101 | Version. 102 | 103 | (b) ensure that installation of your Modified Version does not 104 | prevent the user installing or running the Standard Version. In 105 | addition, the Modified Version must bear a name that is different 106 | from the name of the Standard Version. 107 | 108 | (c) allow anyone who receives a copy of the Modified Version to 109 | make the Source form of the Modified Version available to others 110 | under 111 | 112 | (i) the Original License or 113 | 114 | (ii) a license that permits the licensee to freely copy, 115 | modify and redistribute the Modified Version using the same 116 | licensing terms that apply to the copy that the licensee 117 | received, and requires that the Source form of the Modified 118 | Version, and of any works derived from it, be made freely 119 | available in that license fees are prohibited but Distributor 120 | Fees are allowed. 121 | 122 | 123 | Distribution of Compiled Forms of the Standard Version 124 | or Modified Versions without the Source 125 | 126 | (5) You may Distribute Compiled forms of the Standard Version without 127 | the Source, provided that you include complete instructions on how to 128 | get the Source of the Standard Version. Such instructions must be 129 | valid at the time of your distribution. If these instructions, at any 130 | time while you are carrying out such distribution, become invalid, you 131 | must provide new instructions on demand or cease further distribution. 132 | If you provide valid instructions or cease distribution within thirty 133 | days after you become aware that the instructions are invalid, then 134 | you do not forfeit any of your rights under this license. 135 | 136 | (6) You may Distribute a Modified Version in Compiled form without 137 | the Source, provided that you comply with Section 4 with respect to 138 | the Source of the Modified Version. 139 | 140 | 141 | Aggregating or Linking the Package 142 | 143 | (7) You may aggregate the Package (either the Standard Version or 144 | Modified Version) with other packages and Distribute the resulting 145 | aggregation provided that you do not charge a licensing fee for the 146 | Package. Distributor Fees are permitted, and licensing fees for other 147 | components in the aggregation are permitted. The terms of this license 148 | apply to the use and Distribution of the Standard or Modified Versions 149 | as included in the aggregation. 150 | 151 | (8) You are permitted to link Modified and Standard Versions with 152 | other works, to embed the Package in a larger work of your own, or to 153 | build stand-alone binary or bytecode versions of applications that 154 | include the Package, and Distribute the result without restriction, 155 | provided the result does not expose a direct interface to the Package. 156 | 157 | 158 | Items That are Not Considered Part of a Modified Version 159 | 160 | (9) Works (including, but not limited to, modules and scripts) that 161 | merely extend or make use of the Package, do not, by themselves, cause 162 | the Package to be a Modified Version. In addition, such works are not 163 | considered parts of the Package itself, and are not subject to the 164 | terms of this license. 165 | 166 | 167 | General Provisions 168 | 169 | (10) Any use, modification, and distribution of the Standard or 170 | Modified Versions is governed by this Artistic License. By using, 171 | modifying or distributing the Package, you accept this license. Do not 172 | use, modify, or distribute the Package, if you do not accept this 173 | license. 174 | 175 | (11) If your Modified Version has been derived from a Modified 176 | Version made by someone other than you, you are nevertheless required 177 | to ensure that your Modified Version complies with the requirements of 178 | this license. 179 | 180 | (12) This license does not grant you the right to use any trademark, 181 | service mark, tradename, or logo of the Copyright Holder. 182 | 183 | (13) This license includes the non-exclusive, worldwide, 184 | free-of-charge patent license to make, have made, use, offer to sell, 185 | sell, import and otherwise transfer the Package with respect to any 186 | patent claims licensable by the Copyright Holder that are necessarily 187 | infringed by the Package. If you institute patent litigation 188 | (including a cross-claim or counterclaim) against any party alleging 189 | that the Package constitutes direct or contributory patent 190 | infringement, then this Artistic License to you shall terminate on the 191 | date that such litigation is filed. 192 | 193 | (14) Disclaimer of Warranty: 194 | THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS 195 | IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED 196 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 197 | NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL 198 | LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL 199 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 200 | DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF 201 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 202 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Here's a list of the people who've contributed to this package. 2 | 3 | The Inform program and its libraries: 4 | Graham Nelson 5 | All the people at www.inform-fiction.org 6 | 7 | Documentation: 8 | Graham Nelson 9 | Gareth Rees 10 | 11 | Demo games: 12 | Graham Nelson 13 | Roger Firth 14 | 15 | Tutorial material: 16 | Gareth Rees 17 | David A. Cornelson 18 | Ethan Dicks 19 | 20 | All the people who contributed include files: 21 | A. C. Murie 22 | Adam Stark 23 | Alan Trewartha 24 | Allen Garvin 25 | Andrew Clover 26 | Andrew MacKinnon 27 | Andrew Plotkin 28 | C. Knight 29 | Chris Hall 30 | Chris Klimas 31 | Daniel Barkalow 32 | David A. Cornelson 33 | David Fillmore 34 | David Glasser 35 | David Griffith 36 | David Wagner 37 | Denis Moskowitz 38 | Emily Short 39 | Erik Hetzner 40 | Francis Irving 41 | Fredrik Ramsberg 42 | Graham Nelson 43 | Gunther Schmidl 44 | Jayson Smith 45 | Jesse Burneko 46 | John Cater 47 | John Colagioia 48 | Jonathan Rosebaugh 49 | L. Ross Raszewski 50 | Marnie Parker 51 | Michael Coyne 52 | Mike Phillips 53 | Neil Brown 54 | Neil Cerutti 55 | Nicholas Daley 56 | Patrick Kellum 57 | Peer Schaefer 58 | Roger Firth 59 | Sam Hulick 60 | Stefano Gaburri 61 | Volker Lanz 62 | 63 | Other contributed stuff: 64 | Gareth Rees 65 | Glenn Hutchings 66 | 67 | Package maintenance: 68 | David Griffith 69 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | The compiler and standard library for Inform6 are licensed under 2 | 1) The traditional Inform license as described by the DM4, or 3 | 2) The Artistic License 2.0 (see ARTISTIC). 4 | 5 | The user is free to choose which license to accept, i.e., free to choose 6 | either set of terms and conditions. 7 | 8 | Here is the relevant bit from the Inform Designer's Manual, 4th edition: 9 | 10 | Copyright on Inform, the program and its source code, its example 11 | games and documentation (including this book) is retained by Graham 12 | Nelson, who asserts the moral right to be identified as the author 13 | under the Copyrights, Designs and Patents Act 1988. Having said 14 | this, I am happy for it to be freely distributed to anybody who wants 15 | a copy, provided that: (a) distributed copies are not substantially 16 | different from those archived by the author, (b) this and other 17 | copyright messages are always retained in full, and (c) no profit is 18 | involved. (Exceptions to these rules must be negotiated directly 19 | with the author.) However, a story file produced with the Inform 20 | compiler (and libraries) then belongs to its author, and may be sold 21 | for profit if desired, provided that its game banner contains the 22 | information that it was compiled by Inform, and the Inform version 23 | number. 24 | 25 | * The license status of the contributed material (demos, include, tutor) is 26 | what it says in each file. 27 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | GIT = git 3 | 4 | #OPTS = -g -Wall -Wextra 5 | 6 | PREFIX = /usr/local 7 | MAN_PREFIX = $(PREFIX) 8 | 9 | COMPVERSION = 6.33 10 | LIBVERSION = 6.12.1 11 | NAME = inform 12 | BINNAME = $(NAME) 13 | BINDIR = $(PREFIX)/bin 14 | DISTNAME = $(BINNAME)-$(COMPVERSION)-$(LIBVERSION) 15 | distdir = $(DISTNAME) 16 | LIBDIR = $(PREFIX)/share/$(BINNAME)/lib 17 | INCLUDEDIR = $(PREFIX)/share/$(BINNAME)/include 18 | MANPAGE = $(NAME).1 19 | MANDIR = $(MAN_PREFIX)/man/man1 20 | 21 | DEFINES= -DUNIX -DInclude_Directory=\",$(INCLUDEDIR),$(LIBDIR)\" -DTemporary_Directory=\"/tmp\" 22 | 23 | SRC = src 24 | LIBSRC = lib 25 | DEMO = demos 26 | TUTOR = tutor 27 | 28 | SOURCES = $(wildcard ${SRC}/*.c) 29 | OBJECTS = $(patsubst %.c,%.o,${SOURCES}) 30 | 31 | LIBRARY = lib 32 | LIB_LINKS = English.h Grammar.h Parser.h Verblib.h VerbLib.h 33 | 34 | DEMO_SRC = $(wildcard ${DEMO}/*.inf) 35 | DEMO_Z5 = $(patsubst %.inf,%.z5,${DEMO}) 36 | DEMODIR = $(PREFIX)/share/$(BINNAME)/demos 37 | 38 | TUTOR_SRC = $(wildcard ${TUTOR}/*.inf) 39 | TUTOR_Z5 = $(patsubst %.inf,%.z5,${TUTOR_SRC}) 40 | TUTORDIR = $(PREFIX)/share/$(BINNAME)/tutor 41 | 42 | .PHONY: all clean lib 43 | 44 | all: lib $(BINNAME) lib demos tutor 45 | 46 | # Rules 47 | %.o: %.c 48 | $(CC) $(DEFINES) $(OPTS) -o $@ -c $< 49 | 50 | $(BINNAME): $(OBJECTS) 51 | $(CC) -o $@ $^ 52 | 53 | %.z5: %.inf $(BINNAME) 54 | $(PWD)/$(BINNAME) +lib $< $@ 55 | 56 | lib: 57 | @ cd $(LIBSRC); \ 58 | for file in $(LIB_LINKS); do \ 59 | realfile=`echo $$file | tr '[A-Z]' '[a-z]'`; \ 60 | echo $$realfile $$file; \ 61 | test -r $$file || ln -s $$realfile $$file; \ 62 | done 63 | 64 | demos: lib $(BINNAME) $(DEMO_Z5) 65 | 66 | tutor: lib $(BINNAME) $(TUTOR_Z5) 67 | 68 | strip: $(BINNAME) 69 | strip $(BINNAME) 70 | 71 | submodule: submodules 72 | submodules: 73 | ifneq ($(and $(wildcard .git),$(shell which git)),) 74 | rm -rf $(SRC) $(LIBSRC) 75 | @$(GIT) submodule init 76 | @$(GIT) submodule update 77 | @$(GIT) submodule update 78 | else 79 | @echo "Not in a git repository or git command missing." 80 | @echo "Just try \"make\" now." 81 | endif 82 | 83 | install: $(BINNAME) lib 84 | install -d -m 755 $(BINDIR) 85 | install -c -m 755 $(BINNAME) $(BINDIR) 86 | install -d -m 755 $(LIBDIR) 87 | install -c -m 644 $(wildcard ${LIBSRC}/*) $(LIBDIR) 88 | install -d -m 755 $(INCLUDEDIR) 89 | install -c -m 644 $(wildcard include/*) $(INCLUDEDIR) 90 | install -d -m 755 $(MANDIR) 91 | install -c -m 644 $(MANPAGE) $(MANDIR) 92 | install -d -m 755 $(DEMODIR) 93 | install -c -m 644 $(wildcard ${DEMO}/*) $(DEMODIR) 94 | install -d -m 755 $(TUTORDIR) 95 | install -c -m 644 $(wildcard ${TUTOR}/*) $(TUTORDIR) 96 | install -c -m 755 contrib/pblorb.pl $(BINDIR) 97 | install -c -m 755 contrib/scanblorb.pl $(BINDIR) 98 | 99 | install-strip: strip install 100 | 101 | uninstall: 102 | rm -f $(PREFIX)/bin/$(BINNAME) 103 | rm -f $(PREFIX)/bin/pblorb.pl 104 | rm -f $(PREFIX)/bin/scanblorb.pl 105 | rm -rf $(LIBDIR) 106 | rm -rf $(INCLUDEDIR) 107 | rm -rf $(DEMODIR) 108 | rm -rf $(TUTORDIR) 109 | 110 | dist: distclean 111 | mkdir $(distdir) 112 | @for file in `ls`; do \ 113 | if test $$file != $(distdir); then \ 114 | cp -Rp $$file $(distdir)/$$file; \ 115 | fi; \ 116 | done 117 | find $(distdir) -type l -exec rm -f {} \; 118 | rm -rf $(distdir)/${SRC}/.git* $(distdir)/${SRC}/.deps 119 | rm -rf $(distdir)/${LIBSRC}/.git* $(distdir)/${LIBSRC}/.deps 120 | tar chof $(distdir).tar $(distdir) 121 | gzip -f --best $(distdir).tar 122 | rm -rf $(distdir) 123 | @echo 124 | @echo "$(distdir).tar.gz created" 125 | @echo 126 | 127 | clean: 128 | rm -f $(BINNAME) 129 | rm -f ${SRC}/*.o 130 | rm -f ${DEMO}/*z5 131 | rm -f ${TUTOR}/*z5 132 | cd $(LIBSRC); \ 133 | for file in $(LIB_LINKS); do \ 134 | rm -f $$file; \ 135 | done 136 | 137 | gitclean: 138 | ifneq ($(and $(wildcard .git),$(shell which git)),) 139 | $(GIT) clean -fdx 140 | else 141 | @echo "Not in a git repository or git command missing." 142 | endif 143 | 144 | distclean: clean 145 | find . -name *core -exec rm -f {} \; 146 | -rm -rf $(distdir) 147 | -rm -f $(distdir).tar $(distdir).tar.gz 148 | 149 | 150 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Version 6.33-6.12.1 (6 June 2016) 2 | ================================= 3 | 4 | * Inform version is now 6.33, with Inform7-related patches and new features. 5 | 6 | * The Inform Library is 6.12.1 with lots of bugfixes and enhancements. 7 | 8 | * Package version scheme changed to indicate both compiler and library 9 | versions included. 10 | 11 | * Include files trimmed to those known to be freely redistributable and 12 | checked to make sure they work. 13 | 14 | * DM4 removed due to license incompatibilities. 15 | 16 | * Added a manpage. 17 | 18 | * Added pblorb.pl and scanblorb.pl utilities for dealing with Blorb files. 19 | 20 | Version 6.32.1 (16 July 2012) 21 | ============================= 22 | 23 | * Inform version is now 6.32, with more patches for use with Inform 7. 24 | 25 | * The Inform program is now distributed under the Artistic License 2.0. 26 | 27 | * The advent.inf example is now at release 9. 28 | 29 | Version 6.31.1 (19 May 2006) 30 | ============================ 31 | 32 | * New version of compiler which fixes several bugs found in the development 33 | of Inform 7. 34 | 35 | * Package now uses the latest autotools. 36 | 37 | Version 6.30.2 (6 Jun 2004) 38 | =========================== 39 | 40 | * The HTML version of the Inform Designer's Manual is now the Fourth 41 | Edition. 42 | 43 | * The Info version of the Designer's Manual has been discontinued, since it 44 | refers to the out-of-date Third Edition. 45 | 46 | * Many more contributed include files from the IF archive are now present 47 | in the package. Some of them come with documentation files, which are 48 | also installed (in the same include directory). 49 | 50 | * Applied long path length fix to all unices (e.g. FreeBSD), not just 51 | Linux. 52 | 53 | * Minor package fixes. 54 | 55 | Version 6.30.1 (27 Feb 2004) 56 | ============================ 57 | 58 | * New version of biplatform compiler. 59 | 60 | * Included DM4 misprints; removed patch directory and bug notice. 61 | 62 | * Long path length is now standard for Linux. 63 | 64 | Version 6.21.4 (17 Jun 2003) 65 | ============================ 66 | 67 | * Applied patches from www.inform-fiction.org to the source and library, as 68 | supplied by Dave Griffith . 69 | 70 | * There's a new Ruins demo game, with more stuff implemented. The previous 71 | Ruins demos have been renamed: ruins -> ruins1, ruinsplus -> ruins2. The 72 | new one is called ruins3. 73 | 74 | * The Alice demo in the 'tutor' directory has been updated to the latest 75 | Inform version. 76 | 77 | * Included a more up-to-date inform-mode.el. 78 | 79 | Version 6.21.3 (6 Nov 2002) 80 | =========================== 81 | 82 | * The Inform included here is now Andrew Plotkin's bi-platform version, 83 | which can compile for Glulx, following a suggestion by Marshall 84 | T. Vandegrift . 85 | 86 | * Now includes HTML version of the Designer's Manual. 87 | 88 | * Several more library include files have been added. 89 | 90 | Version 6.21.2 (15 Aug 2000) 91 | ============================ 92 | 93 | * Minor installation changes for OpenBSD, as suggested by David Leonard 94 | . 95 | 96 | Version 6.21.1 (24 Nov 1999) 97 | ============================ 98 | 99 | * Initial release. 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **This project has moved to https://gitlab.com/DavidGriffith/inform6unix** 2 | 3 | **Welcome to Inform!** 4 | ======================= 5 | 6 | --- 7 | 8 | Inform is an Interactive Fiction (text adventure) game compiler -- it takes 9 | source code you write and turns it into a game data file which is then 10 | played using an *interpreter*. There are several interpreters available 11 | which can play Inform games on different machines (e.g. frotz, jzip) -- you 12 | can probably obtain one from the same place you got this package. 13 | 14 | Inform was originally written by Graham Nelson, and you are free to 15 | redistribute it under certain conditions -- see the file COPYING for 16 | details. 17 | 18 | What's in this distribution? 19 | ---------------------------- 20 | 21 | The following subdirectories are included in the package: 22 | 23 | - ***src*** --- source code for the Inform program 24 | - ***lib*** --- Inform library files 25 | - ***include*** --- selection of useful include files 26 | - ***demos*** --- some Inform demo games (including the classic *advent*) 27 | - ***tutor*** --- some Inform tutorial files 28 | - ***docs*** --- internal Inform documentation and release notes 29 | - ***contrib*** --- other contributed Inform stuff 30 | 31 | How do I install it? 32 | -------------------- 33 | 34 | If you're working from a git repository, do this first: 35 | 36 | make submodules 37 | 38 | Then, here's how to build Inform6: 39 | 40 | make 41 | sudo make install 42 | 43 | This will install the following (assuming default installation): 44 | 45 | Inform executable in /usr/local/bin 46 | Inform library files in /usr/local/share/inform/lib 47 | Inform include files in /usr/local/share/inform/include 48 | Inform tutorial games in /usr/local/share/inform/tutor 49 | Inform demo games in /usr/local/share/inform/demos 50 | 51 | If you want to install Inform somewhere other than /usr/local, edit 52 | Makefile accordingly. 53 | 54 | OK, it's installed. Now what? 55 | ------------------------------ 56 | 57 | There are three canonical works documenting the Inform6 language. These 58 | are the Inform Designers Manual (4th ed), the Inform Beginner's Guide, 59 | and the IF Theory Reader. These are at 60 | http://inform-fiction.org/manual/index.html. At least the the Inform 61 | Designer's Manual is currently available on Amazon as a hardcopy 62 | hardcover book. They're very nice to have on hand when going through 63 | the demos/ and tutor/ directories and follow along with the books. After 64 | that, you're all set to write an IF game! Yay! 65 | 66 | Troubleshooting 67 | --------------- 68 | 69 | If you have any problems with anything, contact the relevant person 70 | listed in the AUTHORS file. If you're not sure who that is, contact me 71 | instead, at the address at the end of this file. 72 | 73 | The Interactive Fiction archive 74 | ------------------------------- 75 | 76 | There's a good chance that you got this package from the IF archive, or one 77 | of its mirrors. But if you didn't, you might like to check it out 78 | http://www.ifarchive.org 79 | 80 | It has lots of great things: games, hints, solutions, authoring systems 81 | (like this one), programs for playing the games, tools for making maps, and 82 | stuff about the late, great Infocom. 83 | 84 | There are also more resources for programming with Inform, including a 85 | version of the Inform Designer's Manual suitable for printing. See the 86 | stuff in the programming/inform6 subdirectory. 87 | 88 | The Inform maintainers 89 | ---------------------- 90 | 91 | An active community of Inform maintainers exists to fix bugs, implement new 92 | features and issue new versions of the program. If you'd like to know 93 | more, or you think you've found a bug, visit them at 94 | http://inform7.com/contribute/report/ 95 | 96 | About this package 97 | ------------------ 98 | 99 | This package was originally created by Glenn Hutchings to address the 100 | tedium of gathering the program, libraries, and documentation for 101 | several different Unix machines. It received blessing from Graham 102 | Nelson. The result is a package that automates the configuration and 103 | installation process. It should build and install on all Unix, Linux, 104 | and Win32/Cygwin system. 105 | 106 | This package is an ideal base for creating pre-compiled packages in the 107 | style of Debian .debs, Redhat .rpms and similar schemes as well as build 108 | trees like FreeBSD ports, NetBSD pkgsrc, and Gentoo portage. 109 | 110 | Many people contributed to the contents of this package. See the file 111 | AUTHORS for more details. 112 | 113 | This package is hosted at Github: 114 | 115 | https://github.com/DavidGriffith/inform6unix 116 | 117 | Feel free to hack on it and send me improvements! 118 | 119 | Finally... 120 | ---------- 121 | 122 | If you have any comments or suggestions (or anything else, for that matter) 123 | feel free to drop me a line. I am: 124 | 125 | David Griffith . 126 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | Inform version 6.33, library version 6/12. 2 | -------------------------------------------------------------------------------- /contrib/README: -------------------------------------------------------------------------------- 1 | This directory contains various contributed files for Inform: 2 | 3 | inform-mode.el A GNU Emacs Inform mode, contributed by 4 | Gareth Rees , and 5 | currently maintained by Rupert Lane 6 | . 7 | 8 | pblorb.pl Generate a blorb file according to a supplied 9 | blurb file. Originally by Graham Nelson. 10 | Currently maintained by David Griffith. 11 | 12 | scanblorb.pl Reads a Blorb interactive fiction resource file, 13 | checks for validity, and reports on its 14 | contents. The contents of the Blorb file can also 15 | be extracted to individual files. 16 | Originally by Graham Nelson. Currently 17 | maintained by David Griffith. 18 | -------------------------------------------------------------------------------- /contrib/scanblorb.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # --------------------------------------------------------------------------- 3 | # scanBlorb: a perl script for scanning Blorb files 4 | # (c) Graham Nelson 1998 5 | # 6 | # Distributed under the terms of the Artistic License 2.0 7 | # 8 | # (c) Richard Poole 2004 9 | # (c) David Griffith 2015 10 | # 11 | # Latest version is at https://github.com/DavidGriffith/blorbtools 12 | # --------------------------------------------------------------------------- 13 | 14 | 15 | use strict; 16 | use Getopt::Long; 17 | use Pod::Usage; 18 | use Encode qw(decode); 19 | 20 | require 5.6.0; 21 | 22 | my $buffer; 23 | my %options; 24 | my %images; 25 | my %sounds; 26 | my %execs; 27 | 28 | my $imagecount; 29 | my $execcount; 30 | my $soundcount; 31 | 32 | my $xmlcount = 0; 33 | my $resocount = 0; 34 | my $apalcount = 0; 35 | my $loopcount = 0; 36 | 37 | GetOptions('usage|?' => \$options{usage}, 38 | 'h|help' => \$options{help}, 39 | 'i|images' => \$options{images}, 40 | 's|sound' => \$options{sound}, 41 | 'e|exec' => \$options{exec}, 42 | 'x|xml' => \$options{xml}, 43 | 'a|all' => \$options{all} 44 | ); 45 | 46 | my $input_filename = $ARGV[0]; 47 | my $output_filename; 48 | 49 | 50 | pod2usage(1) if $options{usage}; 51 | pod2usage(-verbose => 3) if $options{help}; 52 | pod2usage(1) if !$input_filename; 53 | 54 | 55 | 56 | if ($options{all}) { 57 | $options{images} = 1; 58 | $options{sound} = 1; 59 | $options{exec} = 1; 60 | $options{xml} = 1; 61 | } 62 | 63 | sub array_diff(\@\@); 64 | 65 | my $version = "scanBlorb 3.0, part of Blorbtools"; 66 | 67 | my ($sec,$min,$hour,$mday,$month,$year) = (localtime(time))[0, 1, 2, 3, 4, 5]; 68 | 69 | my $blorbdate = sprintf("%04d/%02d/%02d at %02d:%02d.%02d", 70 | $year + 1900, $month + 1, $mday, $hour, $min, $sec); 71 | 72 | my @adrift_magic_380 = (0x3c, 0x42, 0x3f, 0xc9, 73 | 0x6a, 0x87, 0xc2, 0xcf, 74 | 0x94, 0x45, 0x36, 0x61); 75 | 76 | my @adrift_magic_390 = (0x3c, 0x42, 0x3f, 0xc9, 77 | 0x6a, 0x87, 0xc2, 0xcf, 78 | 0x94, 0x45, 0x37, 0x61); 79 | 80 | my @adrift_magic_400 = (0x3c, 0x42, 0x3f, 0xc9, 81 | 0x6a, 0x87, 0xc2, 0xcf, 82 | 0x93, 0x45, 0x3e, 0x61); 83 | 84 | my @adrift_magic_500 = (0x3c, 0x42, 0x3f, 0xc9, 85 | 0x6a, 0x87, 0xc2, 0xcf, 86 | 0x92, 0x45, 0x3e, 0x61); 87 | 88 | print STDOUT "$version [executing on $blorbdate]\n\n"; 89 | 90 | open (BLORB, $input_filename) or die "Can't load $input_filename."; 91 | binmode(BLORB); 92 | 93 | read BLORB, $buffer, 12; 94 | 95 | my ($groupid, $length, $type) = unpack("NNN", $buffer); 96 | 97 | if (!$groupid || ($groupid != 0x464F524D)) { die "Not a valid FORM file!\n";} 98 | 99 | $type == 0x49465253 or die "Not a Blorb file!\n"; 100 | 101 | print "File length is apparently $length bytes\n"; 102 | 103 | my ($size, $pos); 104 | 105 | for($pos = 12; $pos < $length; $pos += $size + ($size % 2) + 8) { 106 | my $chunkdata; 107 | 108 | read(BLORB, $buffer, 8) == 8 109 | or die("Incomplete chunk header at $pos\n"); 110 | 111 | $size = (unpack("NN", $buffer))[1]; # second word of header 112 | my $type = substr($buffer, 0, 4); 113 | printf "%06x: $type chunk with $size bytes of data\n", $pos; 114 | 115 | read(BLORB, $chunkdata, $size) == $size 116 | or die("Incomplete chunk at $pos\n"); 117 | if($size % 2) { read(BLORB, $buffer, 1); } 118 | 119 | # optional chunks 120 | if ($type eq "(c) ") { 121 | print "\tCopyright: $chunkdata\n"; 122 | } 123 | if ($type eq "AUTH") { 124 | print "\tAuthor: $chunkdata\n"; 125 | } 126 | if ($type eq "ANNO") { 127 | print "\tAnnotations: $chunkdata\n"; 128 | } 129 | 130 | # zcode executable: look into its magic insides 131 | if ($type eq "ZCOD") { 132 | my ($version, $release) = (unpack("CCn", $chunkdata))[0,2]; 133 | my $serialcode = substr($chunkdata, 0x12, 6); 134 | print "\t$release.$serialcode (version $version)\n"; 135 | } 136 | 137 | # glulx executable: look into its magic insides 138 | if($type eq "GLUL") { 139 | my ($major, $minor, $minimus) = (unpack("xxxxnCC", $chunkdata))[0,1,2]; 140 | print "\tGlulx version $major.$minor.$minimus\n"; 141 | } 142 | 143 | # adrift executable: look into its magic insides 144 | if ($type eq "ADRI") { 145 | my @adrift_header = unpack("CCCCCCCCCCCC", $chunkdata); 146 | if (!array_diff(@adrift_header, @adrift_magic_380)) { 147 | $version = "3.80"; 148 | } elsif (!array_diff(@adrift_header, @adrift_magic_390)) { 149 | $version = "3.90"; 150 | } elsif (!array_diff(@adrift_header, @adrift_magic_400)) { 151 | $version = "4.00"; 152 | } elsif (!array_diff(@adrift_header, @adrift_magic_500)) { 153 | $version = "5.0"; 154 | } else { 155 | $version = "unknown"; 156 | } 157 | print "\tADRIFT Generator version $version\n"; 158 | } 159 | 160 | # magnetic scrolls executable 161 | if ($type eq "MAGS") { 162 | print "\tMagnetic Scrolls\n"; 163 | } 164 | 165 | # game identifier chunk: probably only if no executable chunk 166 | if ($type eq "IFhd") { 167 | my $release = unpack("n", substr($chunkdata,0,3)); 168 | my $serialcode = substr($chunkdata, 2, 6); 169 | print "\t$release.$serialcode\n"; 170 | } 171 | 172 | # release number chunk: zcode games only 173 | if ($type eq "RelN") { 174 | my $relnum = unpack("n", $chunkdata); 175 | print "\tRelease number $relnum\n"; 176 | } 177 | 178 | # Frontispiece chunk 179 | if ($type eq "Fspc") { 180 | print "\tFrontispiece: " . unpack("n", substr($chunkdata, 2)) . "\n"; 181 | } 182 | 183 | # SNam chunk 184 | if ($type eq "SNam") { 185 | print "\tStory name: " . decode("UTF16-BE", $chunkdata) . "\n"; 186 | } 187 | 188 | # Resolution chunk 189 | if ($options{images} && $type eq "Reso") { 190 | $output_filename = "reso_$resocount"; 191 | $output_filename .= ".bin"; 192 | $resocount++; 193 | dumpchunk($output_filename, $pos, $chunkdata); 194 | } 195 | 196 | # Adaptive Palette chunk 197 | if ($options{images} && $type eq "APal") { 198 | $output_filename = "apal_$apalcount"; 199 | $output_filename .= ".bin"; 200 | $apalcount++; 201 | dumpchunk($output_filename, $pos, $chunkdata); 202 | } 203 | 204 | # IFmd chunk 205 | if ($options{xml} && ($type eq "IFmd")) { 206 | $output_filename = "ifmd_$xmlcount"; 207 | $output_filename .= ".xml"; 208 | $xmlcount++; 209 | dumpchunk($output_filename, $pos, $chunkdata); 210 | } 211 | 212 | # Dumping Exec chunks 213 | if ($options{exec} && ($type eq "ZCOD" or $type eq "GLUL" or 214 | $type eq "MAGS")) { 215 | $output_filename = "exec_"; 216 | $output_filename .= sprintf '%0*d', length($execcount) , $execs{$pos}; 217 | if ($type eq "ZCOD") { 218 | $output_filename .= ".z" . unpack("C", $chunkdata); 219 | } elsif ($type eq "GLUL") { 220 | $output_filename .= ".ulx"; 221 | } elsif ($type eq "ADRI") { 222 | $output_filename .= ".taf"; 223 | } elsif ($type eq "MAGS") { 224 | $output_filename .= ".mag"; 225 | } else { 226 | warn_resource($pos), next; 227 | } 228 | dumpchunk($output_filename, $pos, $chunkdata); 229 | } 230 | 231 | # Dumping Loop chunk 232 | if ($options{sound} && $type eq "Loop") { 233 | $output_filename = "loop_$loopcount" . ".bin"; 234 | $loopcount++; 235 | dumpchunk($output_filename, $pos, $chunkdata); 236 | } 237 | 238 | # Dumping Snd chunks 239 | if ($options{sound} && ($type eq "FORM" or $type eq "MOD " or 240 | $type eq "OGGV" or $type eq "SONG" or 241 | $type eq "MP3 " or $type eq "WAVE" or 242 | $type eq "MIDI")) { 243 | $output_filename = "snd_"; 244 | $output_filename .= sprintf '%0*d', length($soundcount) , $sounds{$pos}; 245 | if ($type eq "FORM") { 246 | $output_filename .= ".aiff"; 247 | $chunkdata = "FORM" . pack("N", $size) . $chunkdata; 248 | } elsif ($type eq "MOD ") { 249 | $output_filename .= ".mod"; 250 | } elsif ($type eq "OGGV") { 251 | $output_filename .= ".ogg"; 252 | } elsif ($type eq "SONG") { 253 | $output_filename .= ".song"; 254 | } elsif ($type eq "MP3 ") { 255 | $output_filename .= ".mp3"; 256 | } elsif ($type eq "WAVE") { 257 | $output_filename .= ".wav"; 258 | } elsif ($type eq "MIDI") { 259 | $output_filename .= ".mid"; 260 | } else { 261 | warn_resource($pos), next; 262 | } 263 | dumpchunk($output_filename, $pos, $chunkdata); 264 | } 265 | 266 | # Dumping Pict chunks 267 | if ($options{images} && ($type eq "PNG " or $type eq "JPEG" or $type eq "GIF " or $type eq "Rect" or $type eq "GFX ")) { 268 | $output_filename = "pict_"; 269 | $output_filename .= sprintf '%0*d', length($imagecount) , $images{$pos}; 270 | if ($type eq "PNG ") { 271 | $output_filename .= ".png"; 272 | } elsif ($type eq "JPEG") { 273 | $output_filename .= ".jpg"; 274 | } elsif ($type eq "GIF ") { 275 | $output_filename .= ".gif"; 276 | } elsif ($type eq "GFX ") { 277 | $output_filename .= ".gfx"; 278 | } elsif ($type eq "Rect") { 279 | my $width = unpack("n", substr($chunkdata, 2)); 280 | my $height = unpack("n", substr($chunkdata, 6)); 281 | $output_filename .= ".rect"; 282 | } else { 283 | warn_resource($pos), next; 284 | } 285 | dumpchunk($output_filename, $pos, $chunkdata); 286 | } 287 | 288 | # resource index chunk: always present 289 | if ($type eq "RIdx") { 290 | print "\tResources index:\n"; 291 | 292 | my $numres = unpack("N", $chunkdata); 293 | substr($chunkdata, 0, 4) = ""; 294 | while($numres--) { 295 | my($usage, $number, $start) = 296 | unpack("a4 NN NN", substr($chunkdata, 0, 12, "")); 297 | printf("\t\t%06x: %s %d\n", $start, $usage, $number); 298 | $images{$start} = $number if $usage eq "Pict"; 299 | $execs{$start} = $number if $usage eq "Exec"; 300 | $sounds{$start} = $number if $usage eq "Snd "; 301 | } 302 | $imagecount = keys %images; 303 | $soundcount = keys %sounds; 304 | $execcount = keys %execs; 305 | } 306 | } 307 | 308 | close(BLORB); 309 | 310 | # --------------------------------------------------------------------------- 311 | 312 | sub array_diff(\@\@) { 313 | my %e = map { $_ => undef } @{$_[1]}; 314 | return @{[ ( grep { (exists $e{$_}) ? ( delete $e{$_} ) : ( 1 ) } @{ $_[0] } ), keys %e ] }; 315 | } 316 | 317 | sub warn_resource { 318 | my ($pos, @junk) = @_; 319 | my $errstr = sprintf("No resource information for chunk at %0x06x\n", $pos); 320 | warn($errstr); 321 | } 322 | 323 | sub dumpchunk { 324 | my ($filename, $pos, $chunkdata, @junk) = @_; 325 | 326 | open CHUNKFH, ">$filename" 327 | or warn "Failed to open handle for $filename: $!\n", next; 328 | binmode CHUNKFH; 329 | $\ = undef; 330 | print CHUNKFH $chunkdata; 331 | close CHUNKFH 332 | or warn "Failed to close handle for $filename: $!\n", next; 333 | } 334 | 335 | # --------------------------------------------------------------------------- 336 | 337 | __END__ 338 | 339 | 340 | =head1 NAME 341 | 342 | scanblorb.pl - Examine a Blorb resource file and optionally dump its contents 343 | 344 | =head1 SYNOPSIS 345 | 346 | B [options...] 347 | 348 | Use -h or --help for verbose help. 349 | 350 | =head1 DESCRIPTION 351 | 352 | Reads a Blorb interactive fiction resource file, checks for validity, 353 | and reports on its contents. The contents of the Blorb file can also be 354 | extracted to individual files. 355 | 356 | =head2 Option flags 357 | B<-?> Print simple usage message. 358 | B<-h --help> Print verbose help message. 359 | B<-a --all> Extract all embedded file chunks. 360 | B<-e --exec> Extract only the executable chunk. 361 | B<-i --images> Extract only image chunks. 362 | B<-s --sound> Extract only sound chunks. 363 | B< > 364 | 365 | =head1 APPLICATION 366 | 367 | This script is intended to assist in dissecting and reverse-engineering 368 | blorb files. Currently chunks having to do with Zcode, Glulx, 369 | ADRIFT, and Magnetic Scrolls executable formats are recognized. 370 | 371 | Running the script without any options on a blorb file will result in a 372 | list of chunks found and some information about them. Chunks that 373 | started off as standalone files may be extracted to the currect 374 | directory by using the appropriate option. The -a option will cause all 375 | embedded files to be extracted. 376 | 377 | Version 3.0 378 | 379 | =head1 NOTES 380 | 381 | The Blorb format was created by Andrew Plotkin in 1998. This script 382 | conforms to version 2.0.4 of the Blorb Specification. See 383 | L 384 | 385 | =head1 AUTHORS 386 | (c) Graham Nelson 1998 (original script up to 1.03) 387 | (c) Richard Poole 2004 (version 2.0) 388 | (c) David Griffith 2015 (version 3.0 and later) 389 | 390 | =cut 391 | -------------------------------------------------------------------------------- /demos/README: -------------------------------------------------------------------------------- 1 | This directory contains the standard demo games for Inform. They get 2 | installed in a directory called 'zcode' in the system data directory (by 3 | default, /usr/local/share). 4 | -------------------------------------------------------------------------------- /demos/museum.inf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidGriffith/inform6unix/5f2abd7e8a61a096f03c55a4669cfeb059778d49/demos/museum.inf -------------------------------------------------------------------------------- /demos/ruins1.inf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidGriffith/inform6unix/5f2abd7e8a61a096f03c55a4669cfeb059778d49/demos/ruins1.inf -------------------------------------------------------------------------------- /demos/ruins2.inf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidGriffith/inform6unix/5f2abd7e8a61a096f03c55a4669cfeb059778d49/demos/ruins2.inf -------------------------------------------------------------------------------- /demos/ruins3.inf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidGriffith/inform6unix/5f2abd7e8a61a096f03c55a4669cfeb059778d49/demos/ruins3.inf -------------------------------------------------------------------------------- /docs/README.include: -------------------------------------------------------------------------------- 1 | Include files 2 | ============= 3 | 4 | The ../include'directory contains many of the include files that various 5 | people have written for Inform over the years. Documentation for most of 6 | them is contained in their own files (but there are extra doc files for 7 | some). 8 | 9 | Note that only some of these headers have been tested with Inform 6. If 10 | you find one that doesn't work as advertised, drop me a line and I'll 11 | attempt to fix it (or, if you've already done that, send me the fix!). 12 | 13 | As with the library headers, all the header file names have been converted 14 | to lower case. Converted lowercase files get symlinked to their original 15 | names on installation, for compatibility with old games that use them. 16 | -------------------------------------------------------------------------------- /docs/README.paths: -------------------------------------------------------------------------------- 1 | Search paths 2 | ============ 3 | 4 | To attempt to emulate the search path facility of the C preprocessor, 5 | Inform is compiled with some built-in search paths. For include files, 6 | this is (in order of searching): 7 | 8 | . current directory 9 | PKGDATA/include local include directory 10 | PKGDATA/lib local library directory 11 | PKGDATA/VERSION/include system include directory 12 | PKGDATA/VERSION/lib system library directory 13 | 14 | where PKGDATA is the package data prefix (default: /usr/local/share/inform) 15 | and VERSION is the Inform version. For modules, the search path is: 16 | 17 | . current directory 18 | PKGDATA/lib local library directory 19 | PKGDATA/VERSION/lib system library directory 20 | 21 | This is as if Inform has been given the +include_file and +module_file 22 | arguments with the comma-separated lists of directories shown above. 23 | However, note that explicitly giving one of these arguments to Inform will 24 | override the default setting, not prepend to it, as with the C 25 | preprocessor. 26 | -------------------------------------------------------------------------------- /docs/README.translation: -------------------------------------------------------------------------------- 1 | Information for translators 2 | =========================== 3 | 4 | The library is designed to be easily translatable, and there are 5 | currently versions available in French, German and several other 6 | languages. If you maintain one of these translations, the following 7 | information may be useful to you. 8 | 9 | English.h 10 | --------- 11 | 12 | This is the "language definition file", and in translation is replaced 13 | by French.h, German.h, etc. The following changes have been made: 14 | 15 | * Class CompassDirection and its objects have been extensively revised. 16 | 17 | * Routine LanguageVerb() has been reworked. 18 | 19 | * Routines LanguageVerbIsDebugging(), LanguageVerbLikesAdverb() and 20 | LanguageVerbMayBeName() have been added to isolate language-specific 21 | tests previously embedded in parserm.h. 22 | 23 | * Constants YOU__TX and COMMA__TX have been added. 24 | 25 | * Routine LanguageLM() has been sorted alphabetically. 26 | 27 | * In that routine, CommandsOff, CommandsOn and CommandsRead have been added. 28 | 29 | * Also in that routine, Exit, Inv, Look, Miscellany, Places, Pronouns 30 | and Score have been extended, and Go has been modified. 31 | 32 | * Constant LIBRARY_ENGLISH has been added. We suggest that translated 33 | versions instead define LIBRARY_DUTCH, LIBRARY_FRENCH, 34 | LIBRARY_GERMAN, LIBRARY_ITALIAN, LIBRARY_SPANISH, LIBRARY_SWEDISH 35 | etc, in case it becomes useful at some time to determine which 36 | language is in force. 37 | 38 | 39 | Grammar.h 40 | --------- 41 | 42 | This file contains grammars for English verbs like TAKE and DROP, and in 43 | translation is replaced by FrenchG.h, GermanG.h, etc. The following 44 | changes have been made: 45 | 46 | * The grammars have been sorted alphabetically. 47 | 48 | * Verb definitions 'recording' and 'replay' are no longer conditional 49 | on DEBUG. 50 | 51 | * Verb definitions 'showobj', 'ask', 'exit', 'look' and 'tell' have 52 | been extended. 53 | 54 | * Verb definition 'pry' 'prise' etc has been added. 55 | 56 | * Constant LIBRARY_GRAMMAR has been added. 57 | -------------------------------------------------------------------------------- /include/doors.h: -------------------------------------------------------------------------------- 1 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2 | ! DOORS An INFORM 6.10 library creating easy-to-code doors 3 | ! By L. Ross Raszewski 4 | ! 5 | ! Updated by David Griffith in October 2012. 6 | ! Corrected bug that prevented moveclass.h NPCs from being able to 7 | ! operate doors. Also reformatted text. 8 | ! 9 | ! 10 | ! According to "The Inform Designer's Manual, 3rd edition" 11 | ! (reprinted without permission) 12 | ! To set up a door: 13 | ! 14 | ! (a) give the object the door attribute; 15 | ! (b) set its door_to property to the destination; 16 | ! (c) set its door_dir property to the direction which that would be, 17 | ! such as n_to; 18 | ! (d) make the room's map connection in that direction point to the door 19 | ! itself. 20 | ! 21 | ! Yeah, right. The majority of doors you'll meet in real life are two-sided 22 | ! and anyone who's tried to code up a two-sided door in Inform knows what 23 | ! they're in for. You'll need something like a 24 | ! door_to [; if (location == shrine) return jungle; return shrine;], 25 | ! and a 26 | ! door_dir [; if (location == shrine) return u_to; return d_to;], 27 | ! Now, I'll agree this isn't all that bad, but I'm sure you've wished it 28 | ! was easier. Many a newbie has died trying to code up something lke this. 29 | ! 30 | ! Not anymore. 31 | ! 32 | ! Observe if you will the Connector class. 33 | ! 34 | ! Suppose you need a door between roomA and roomB, where roomA is to the east 35 | ! of roomB. 36 | ! 37 | ! 38 | ! Connector door "door" 39 | ! with name "door", 40 | ! e_to roomA, 41 | ! w_to roomB, 42 | ! when_open "The door is open", 43 | ! when_closed "The door is closed", 44 | ! has openable; 45 | ! 46 | ! Voila! This simple syntax is equivalent to the conventional syntax: 47 | ! 48 | ! Object door "door" 49 | ! with name "door", 50 | ! door_to [; if (location == roomA) return roomB; return roomA;], 51 | ! door_dir [; if (location == roomB) return e_to; return w_to;], 52 | ! when_open "The door is open", 53 | ! when_closed "The door is closed", 54 | ! found_in roomA roomB; 55 | ! has openable door static; 56 | ! 57 | ! I can hear you now. "What? I save three lousy lines?" Well, yeah, but in 58 | ! a game with a lot of doors, you've saved yourself some syntax. And it 59 | ! certaintly is more intuitive. 60 | ! 61 | ! The only catch, for the sake of economy, is that you have to call the 62 | ! function InitDoors(); in your initialise. 63 | ! 64 | ! Also by the author: 65 | ! The AltMenuing system 66 | ! Center Centers a line of text in either window. 67 | ! Domenu Improved menuing with multiple description lines 68 | ! Altmenu Object oriented menuing system 69 | ! Hints Altmenu hint system 70 | ! Sound The Inform Sound System 71 | ! YesNo pseudo-rhetorical Yes or no questions 72 | ! Date Datekeeping and printing 73 | ! Footnote Autonumbering footnotes 74 | ! Locktest Default key selection 75 | ! Newlock Key-side lock definition 76 | ! Ordinal Ordinal number printing 77 | ! Whatis "What is a" questions 78 | ! Senses Recursive sensory perception 79 | ! Pmove Move objects into the tree as the youngest object 80 | ! Movie Non-interactive cut-scenes 81 | ! Manual inform "instruction manual" system 82 | ! 83 | ! Coming soon: 84 | ! Converse Hit-word based conversation 85 | ! MenuTalk Menu-based Conversation 86 | ! UniCursr Unicursor- Text adventures with the contol simplicity 87 | ! of omnifunction click graphic games (ie. Type "clock" 88 | ! to examine, take, or manipulate the clock) 89 | ! 90 | ! Please write me and tell me what you think. 91 | 92 | Class Connector 93 | with door_dir [; 94 | if (self in self.sidea) return self.dira; 95 | return self.dirb; 96 | ], 97 | door_to [; 98 | if (self in self.sidea) return self.sideb; 99 | return self.sidea; 100 | ], 101 | sidea 0, 102 | dira 0, 103 | sideb 0, 104 | dirb 0, 105 | found_in 0 0, 106 | has door static; 107 | 108 | [ InitDoors o i j; 109 | objectloop (j ofclass Connector) { 110 | objectloop (o in compass) { 111 | i=o.door_dir; 112 | if (j provides i) { 113 | j.sidea=j.i; 114 | j.dirb=i; 115 | }; 116 | }; 117 | objectloop (o in compass) { 118 | i=o.door_dir; 119 | if ((j provides i) && (j.dirb~=i)) { 120 | j.sideb=j.i; 121 | j.dira=i; 122 | }; 123 | }; 124 | j.&found_in-->0=j.sidea; 125 | j.&found_in-->1=j.sideb; 126 | }; 127 | ]; 128 | -------------------------------------------------------------------------------- /include/doors2.h: -------------------------------------------------------------------------------- 1 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2 | ! DOORS2 An INFORM 6.15 library creating doors with 3 | ! parsed names for directions 4 | ! By Max Kalus 5 | ! 6 | ! What can this module do? 7 | ! ======================== 8 | ! In some games doors will be used a great deal. If you do, you might 9 | ! make the experience, that, if you have two doors in one room, the 10 | ! player might want to know which direction each of these leads to. 11 | ! He might even act acordingly, and enter "look at north door". The 12 | ! problem with "north" will be, that on the other side, the door 13 | ! will be "south", so giving "north" and "south" as names might not 14 | ! be the best thing to do. The case gets especially unnerving, if 15 | ! you have two doors in the same room, both leading north-south 16 | ! directions. 17 | ! 18 | ! This module will relieve everybody with above problems. This 19 | ! module provides a class called DirDoor (inherits from Connector if 20 | ! "doors.h" is included, see below). DirDoor's parse_name routine 21 | ! looks up direction names and parses them accordingly. Of course 22 | ! you can still use your name Property for each individual door. 23 | ! DirDoor takes care of these names, too. 24 | ! 25 | ! Example: 26 | ! 27 | ! DirDoor My_Door "door" 28 | ! with 29 | ! name "door" "enchanted" "unbreakable" "boring", 30 | ! s_to Room_A, 31 | ! n_to Room_B; 32 | ! 33 | ! If in Room_A, you could type "look at southern door", while in 34 | ! Room_B you could tell the parser "open north door". Nifty, eh? 35 | ! 36 | ! Using Doors2 with "doors.h" 37 | ! =========================== 38 | ! 39 | ! This module is intended to be used with L. Ross Raszewski's 40 | ! "doors.h", but can be used without it. If you use it with doors.h, 41 | ! please make sure you include "doors2.h" *after* "doors. 42 | 43 | #ifndef Connector; 44 | class Connector; 45 | #endif; 46 | 47 | Class DirDoor 48 | class Connector, 49 | with 50 | parse_name [n word; 51 | word = NextWordStopped(); 52 | while (word ~= -1) 53 | { 54 | if (IsAWordIn(word,self,name) == 1) n++; 55 | if (location == self.s_to && (word == 'north' or 'northern')) n++; 56 | if (location == self.n_to && (word == 'south' or 'southern')) n++; 57 | if (location == self.e_to && (word == 'west' or 'western')) n++; 58 | if (location == self.w_to && (word == 'east' or 'eastern')) n++; 59 | if (location == self.se_to && (word == 'northwest' or 'northeastern')) n++; 60 | if (location == self.sw_to && (word == 'northeast' or 'northeastern')) n++; 61 | if (location == self.ne_to && (word == 'southwest' or 'southwestern')) n++; 62 | if (location == self.nw_to && (word == 'southeast' or 'southeastern')) n++; 63 | word = NextWordStopped(); 64 | } 65 | return n; 66 | ], 67 | has door; 68 | 69 | ! -------------- IsAWordIn ----------------- 70 | #ifndef IsAWordIn; 71 | [ IsAWordIn w obj prop k l m; 72 | k=obj.∝ l=(obj.#prop)/2; 73 | for (m=0:mm) rtrue; 75 | rfalse; 76 | ]; 77 | #endif; 78 | 79 | -------------------------------------------------------------------------------- /include/footnote.h: -------------------------------------------------------------------------------- 1 | ! FOOTNOTE.H An Inform Library Extention for Inform 5.5 or greater 2 | ! To produce sequentially numbered footnotes. 3 | ! L. Ross Raszewski 4 | ! VERSION 2.0 5 | ! New features: *Define Redisplay_Footnotes to 1 before inclusion to prevent 6 | ! the player from seeing the footnote indicator more than once 7 | ! *Define footnote1__tx to the text to be printed before the 8 | ! number and footnote2__tx to the text to be printed after it 9 | ! in order to change the default [footnote #] message 10 | ! (multi-lingual support) 11 | ! 12 | ! 13 | ! 14 | ! 15 | ! This library, based on the excercise in the manual, allows you to integrate 16 | ! footnotes into a game, which are numbered IN THE ORDER THEY APPEAR. It has 17 | ! two advantages over the simple, obvious system (ie. the one used in 18 | ! Hitchhiker's Guide): First, footnotes which have not been mentioned cannot 19 | ! be accessed. Second, the footnotes will always count upward in series, no 20 | ! matter what order they're called in. The example in the manual, I found, 21 | ! sometimes numbers the same footnote twice. I've avoided this, so that the 22 | ! same footnote will have the same number, regardless of how it is called 23 | ! (sort of like Achieved(#);) 24 | ! Include AFTER Grammar.h 25 | ! define the constant MAX_FOOTNOTES to the number of footnotes in the game 26 | ! before inclusion. 27 | ! To print a footnote in running text, call Note() with the number of the 28 | ! footnote (THe number is internal, and may not be the one that apears on the 29 | ! screen. Ex: If two footnotes have already been seen, then the statement: 30 | ! Print "All the world's a stage.", (note) 1; 31 | ! will print "All the world's a stage. [Footnote 3]", with the [Footnote 3] 32 | ! in underline print. Note() prints the text contained in Footnote1__TX 33 | ! and Footnote2__TX, which defaults to having a leading space, but no trailing 34 | ! one. 35 | ! The footnote is read by issuing the command FOOTNOTE 3 (or NOTE 3, or 36 | ! READ FOOTNOTE 3). FOOTNOTE alone will instruct the player on the use of 37 | ! Footnotes. 38 | ! 39 | ! You must define the function Printnote(n); before inclusion. This function 40 | ! actually prints the footnote text after FootnoteSub has printed the words 41 | ! [Footnote #]^ and has converted the number the player typed into its 42 | ! original number in the footnote list A sample PrintNote sub might read: 43 | ! [ PrintNote n; 44 | ! switch(n){ 45 | ! 1: "William Shakespeare"; 46 | ! 2: "Sloathes have no taste"; 47 | ! 3: {Style bold; print "Sesame Street"; style roman; " was \ 48 | ! brought to you by the letter ~K~ and the number 4.";}; 49 | ! }; 50 | ! ]; 51 | ! 52 | ! You can have a footnote do anything you like, even call another footnote. 53 | ! (I've tried it, it seems to work). 54 | ! Word of warning: The footnotes_seen array is a bit array, so I think you 55 | ! can't have more than 256 footnotes. 56 | ! 57 | ! 58 | ! 59 | 60 | System_file; 61 | Array footnotes_seen -> MAX_FOOTNOTES; 62 | Global footnote_count; 63 | #IFNDEF Redisplay_Footnotes; 64 | Constant Redisplay_Footnotes 0; 65 | #ENDIF; 66 | 67 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 68 | ! Multi-lingual block. Define the following 69 | ! contants before inclusion to use alternate 70 | ! Messages 71 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 72 | #IFNDEF Footnote1__TX; 73 | Constant Footnote1__TX "[Footnote "; 74 | #ENDIF; 75 | #IFNDEF Footnote2__TX; 76 | Constant Footnote2__TX "]"; 77 | #ENDIF; 78 | #IFNDEF Footnote3__TX; 79 | Constant Footnote3__TX "Footnotes count upward from 1."; 80 | #ENDIF; 81 | #IFNDEF Footnote4__TX; 82 | Constant Footnote4__TX "That footnote ["; 83 | #ENDIF; 84 | #IFNDEF Footnote5__TX; 85 | Constant Footnote5__TX "] has not been mentioned."; 86 | #ENDIF; 87 | #IFNDEF Footnote6__TX; 88 | Constant Footnote6__TX "To view a footnote, type ~FOOTNOTE #~, where # is 89 | the number of the footnote you wish to read."; 90 | #ENDIF; 91 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 92 | ! End of Multi-lingual block 93 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 94 | 95 | [ FNWarnSub; 96 | print_ret (string) Footnote6__TX; 97 | ]; 98 | [ Note n; 99 | if (footnotes_seen->n~=0 && Redisplay_Footnotes==1) rfalse; 100 | if (footnotes_seen->n==0) { 101 | footnote_count++; footnotes_seen->n=footnote_count;}; 102 | print " "; 103 | style underline; 104 | print (string) Footnote1__TX,footnotes_seen->n, (string) Footnote2__TX; 105 | style roman; 106 | ]; 107 | [ FootnoteSub n; 108 | if (noun>footnote_count) 109 | { print (string) Footnote4__TX,noun, (string) Footnote5__TX, "^"; rtrue; } 110 | if (noun==0) print_ret (string) Footnote3__tx; 111 | for(n=1:(footnotes_seen->n~=noun && n<=(MAX_FOOTNOTES-1)):n++); 112 | style underline; 113 | print (string) Footnote1__TX,noun,(string) Footnote2__tx, "^"; 114 | style roman; 115 | PrintNote(n); 116 | ]; 117 | 118 | Verb meta "footnote" "note" * ->FNWarn 119 | * number ->Footnote; 120 | Extend "read" 121 | * "footnote" number ->Footnote 122 | * "note" number ->Footnote 123 | * "footnote" ->FNWarn 124 | * "footnotes" ->FNWarn; 125 | 126 | #Stub PrintNote 1; 127 | -------------------------------------------------------------------------------- /include/howtoplay.h: -------------------------------------------------------------------------------- 1 | ! howtoplay.h for Inform 6, by Michael Coyne (coyne@mts.net) 2 | ! How to Play text Copyright 2003 Fredrik Ramsberg 3 | ! 4 | ! This code was placed in the public domain by its authors 5 | ! See http://mailman.greennet.org.uk/pipermail/inform-maintenance/2014-May/001966.html 6 | ! and 7 | ! http://mailman.greennet.org.uk/pipermail/inform-maintenance/2014-May/001968.html 8 | ! 9 | ! ---------------------------------------------------------------------------- 10 | ! Installation: add the lines: 11 | ! 12 | ! Include "Menus"; ! optional 13 | ! Include "Howtoplay"; 14 | ! 15 | ! anywhere in your game AFTER the Include "VerbLib"; directive 16 | ! 17 | ! ---------------------------------------------------------------------------- 18 | ! Based on the structure of Roger Firth's ccpl.h 19 | ! 20 | ! Implements a HELP verb which uses Menus.h (or any compatible menu 21 | ! package) to display a menu of Fredrik Ramsberg's "How to Play" 22 | ! instructions from "A Beginner's Guide to Playing Interactive Fiction". 23 | ! Fredrik's full text can be found at: 24 | ! http://IFGuide.ramsberg.net 25 | ! 26 | ! Define NO_HOWTO_GRAMMAR to prevent the Help verb from being included. You 27 | ! will then have to provide an alternate means of running HowToMenu.select() 28 | ! 29 | ! If you are not using Menus, then HowToMenu.select will just dump the 30 | ! text to the screen. 31 | ! 32 | ! If you wish to include this in an existing menu in your game instead of 33 | ! just having it available through the help verb, you can do this: 34 | ! 35 | ! Menu MyMenu "My Menu Object" 36 | ! with description "Please select one of the following items.^", 37 | ! number 2; 38 | ! 39 | ! Option -> "How to Play" 40 | ! with description [; 41 | ! howtoplay.description(); 42 | ! ]; 43 | ! 44 | ! $Log$ 45 | ! Revision 1.1 2004/03/15 18:32:52 glen 46 | ! New file. 47 | ! 48 | ! Revision 1.2 2003/05/24 13:36:34 michael 49 | ! Removed DOS carriage-returns introduced by opening on DOS machine. 50 | ! 51 | ! Revision 1.1 2003/05/24 13:32:44 michael 52 | ! Initial revision. 53 | ! 54 | ! ---------------------------------------------------------------------------- ! 55 | 56 | system_file; 57 | 58 | #ifndef MENU; 59 | Class Menu with select [; 60 | howtoplay.description(); 61 | ]; 62 | #endif; 63 | #ifndef OPTION; 64 | Class Option; 65 | #endif; 66 | 67 | [ bf text; style bold; print (string) text; style roman; ]; 68 | 69 | Menu HowToMenu 70 | with short_name [; 71 | print "How to Play ", (string) Story; 72 | rtrue; 73 | ]; 74 | 75 | Option -> howtoplay 76 | with short_name [; 77 | print "How to Play ", (string) Story; 78 | rtrue; 79 | ], 80 | description [; 81 | print "These general instructions are an excerpt from: 82 | ~A Beginner's Guide to Playing Interactive Fiction~. 83 | The full text can be found at http://IFGuide.ramsberg.net", 84 | 85 | (bf) "^^The game starts"; 86 | print " 87 | ^When you start a game, you will first see an introduction, usually 88 | consisting of one or a few screenfuls of text, giving you some 89 | background on who you are, where you are, and perhaps even what your 90 | objectives in the game are. Whenever the game has printed a 91 | screenful of text, it will wait until you press ENTER or some other 92 | key, so that you get a chance to read everything before it scrolls 93 | off the top of the screen.^", 94 | 95 | (bf) "^How to interact"; 96 | print " 97 | ^When the introduction is over, you will get a prompt, usually ~>~, 98 | but it may be a little different from game to game. The prompt means 99 | that the game is now waiting for you to tell it what you want to do. 100 | You do this by typing in imperative commands, as if you were 101 | commanding someone. Let's say the introduction told you that you are 102 | in a kitchen, and that you can see a closed glass jar standing on 103 | the kitchen counter. Commands you could try at this point include 104 | TAKE THE JAR, or OPEN THE JAR, or perhaps EXAMINE THE JAR 105 | (Throughout this document, things that are written in capital 106 | letters are complete commands that can be typed into an IF game. 107 | They don't have to be typed in capital letters when entered into a 108 | game). If you want to, you can skip the articles: TAKE JAR will work 109 | just at well as TAKE THE JAR. If there are several different jars 110 | you could mean, the game may ask you which one you mean. Just type 111 | one or more words that uniquely identifies one of the items. For 112 | instance, if the game says ~Which jar do you mean, the blue glass 113 | jar or the green glass jar?~, you might reply BLUE to take the blue 114 | one. You can also choose to ignore the question altogether, just 115 | typing a new command.^", 116 | 117 | (bf) "^Movement"; 118 | print " 119 | ^To go to another location, most games expect you to type in which 120 | direction you want to go. You can type GO SOUTH, but just SOUTH will 121 | also do the trick, as will S (which is the commonly accepted 122 | abbreviation for SOUTH). Other directions and their abbreviations 123 | are NORTH (N), EAST (E), WEST (W), NORTHEAST (NE), SOUTHEAST (SE), 124 | NORTHWEST (NW), SOUTHWEST (SW), UP (U), DOWN (D), IN and OUT. If you 125 | are aboard a ship of some kind you may also be able to use FORE, 126 | AFT, STARBOARD and PORT.^ 127 | ^Other ways to move around may include commands like ENTER CAR, GO 128 | CAR, SIT ON MOTORCYCLE, GET ON BIKE, CLIMB ONTO SHIP, JUMP ONTO 129 | PLATFORM, DIVE INTO LAKE, BOARD SHIP, EXIT CAR, EXIT, LEAVE, GET 130 | OUT. Exactly which commands are "; 131 | #ifdef DIALECT_US; 132 | print "recognized"; 133 | #ifnot; 134 | print "recognised"; 135 | #endif; 136 | print " vary from game to game as well as from situation to 137 | situation in those games. When interacting with IF games, always 138 | try to express yourself as simply as possible. 139 | If you have tried several ways of expressing yourself and the game 140 | refuses to understand what you want to do, you are most probably on 141 | the wrong track; it's time to try something completely different.^", 142 | 143 | (bf) "^Common verbs"; 144 | print " 145 | ^As you know by now, you can use the verb TAKE to pick up items in 146 | the game. Of course, you can also use DROP to drop items. Most 147 | modern games actually "; 148 | #ifdef DIALECT_US; 149 | print "recognize"; 150 | #ifnot; 151 | print "recognise"; 152 | #endif; 153 | print " a hundred different verbs or more. With some of the most 154 | used verbs, you can also use multiple items, like this: TAKE GREEN 155 | BALL AND SCREWDRIVER or DROP ALL or PUT ALL BUT HAMMER IN BAG. 156 | You'll find that ALL is often a very useful word, although it only 157 | works with certain verbs, most notably TAKE and 158 | DROP. Here are some of most important verbs, with examples:^"; 159 | 160 | font off; 161 | print "^ 162 | LOOK or L L or LOOK AT BOB or LOOK IN JAR or LOOK UNDER BED^ 163 | TAKE TAKE KNIFE^ 164 | DROP DROP KNIFE^ 165 | EXAMINE or X EXAMINE KNIFE or X KNIFE^ 166 | SEARCH SEARCH DESK^ 167 | INVENTORY or I I^ 168 | OPEN OPEN DRAWER^ 169 | CLOSE CLOSE DRAWER^ 170 | LOCK LOCK DOOR WITH RUSTY KEY^ 171 | UNLOCK UNLOCK DOOR WITH RUSTY KEY^ 172 | ASK ASK JOHN ABOUT POLICE OFFICER^ 173 | TELL TELL JOHN ABOUT MURDER^ 174 | SAY SAY HELLO TO JOHN^ 175 | GIVE GIVE RABBIT TO BOB^ 176 | SHOW SHOW KNIFE TO POLICE OFFICER^ 177 | WAIT or Z Z^ 178 | AGAIN or G G^"; 179 | font on; 180 | 181 | print "^Other verbs you will need from time to time include ATTACK, 182 | BUY, COVER, DRINK, EAT, FILL, JUMP, KISS, KNOCK, LISTEN, MOVE, PULL, 183 | PUSH, REMOVE, READ, SIT, SLEEP, STAND, THROW, TIE, TOUCH, TURN, 184 | TYPE, UNTIE, WEAR. There are lots more. Hopefully they will seem 185 | natural to you when you need them.^", 186 | 187 | (bf) "^How time works"; 188 | print " 189 | ^Almost all IF games count time in turns, rather than hours and 190 | minutes. Every time you type something and press ENTER, one turn 191 | passes. This also means that until you press ENTER, no time passes. 192 | You could think of a turn as being something like a minute, but how 193 | long it actually is depends on what you do during that turn. If you 194 | want time to pass, but don't want to perform any actions, just type 195 | WAIT or Z. This will prove useful while waiting for someone to 196 | arrive or something to get ready in the oven etc (in the game world, 197 | not in the real world!).^ 198 | 199 | ^There are games that use real-time instead of turn-based play, but 200 | they are few and far between, and they will tell you about their 201 | real-time system at the beginning of the game.^", 202 | 203 | (bf) "^Talking to people"; 204 | print " 205 | ^The most useful ways of talking to people usually involve the verbs 206 | ASK and TELL. When using them, try to pin down the best keyword for 207 | what you are interested in, rather than longer constructs. For 208 | example, TELL BOB ABOUT HOW I SAW SHEILA GIVE A STRANGE AMULET TO 209 | ANOTHER WOMAN is not likely to yield any useful results, but TELL 210 | BOB ABOUT AMULET or perhaps TELL BOB ABOUT SHEILA may indeed be 211 | useful. In other words, you tell the game the subject you want to 212 | talk about or ask about, not exactly what to say. The game will try 213 | to make reasonable assumptions on what you want to say regarding the 214 | subject.^"; 215 | 216 | print "^Also note that many games are quite primitive when it comes 217 | to modelling people. The author has to put in an enormous amount of 218 | work to make people in the game behave realistically and respond 219 | well to conversation. In general, don't expect too much from people 220 | in the game, but there are of course games that shine in this area 221 | too. You'll also see that some authors prefer menu-based 222 | conversation, to facilitate interaction.^ 223 | 224 | ^To tell someone else to do something, type the name of the person, 225 | a comma, and then a command. Example: BOB, BREAK THE JAR. Just like 226 | in real life, most people won't automatically do something just 227 | because you tell them to. If you think Bob knows what to do with the 228 | jar, you can also try GIVE JAR TO BOB or SHOW JAR TO BOB.^", 229 | 230 | (bf) "^Special verbs"; 231 | print "^All games "; 232 | #ifdef DIALECT_US; 233 | print "recognize"; 234 | #ifnot; 235 | print "recognise"; 236 | #endif; 237 | print " some verbs that don't do anything in the game world, but 238 | tells the game something about how you want it to behave, 239 | or some special task you want it to peform. These verbs include:^"; 240 | 241 | font off; 242 | print "^ 243 | UNDO Takes back the last move you made.^ 244 | QUIT or Q Ends the current game.^ 245 | RESTART Starts the game over from the beginning.^ 246 | SAVE Saves your current position to a file on disk.^ 247 | RESTORE Loads a previously saved game position.^ 248 | HELP or ABOUT Shows some information about the game and its 249 | author, in some cases even hints to some of the 250 | puzzles.^ 251 | VERBOSE Tells the game you want a long description of every 252 | room you enter, even if you've been there before.^ 253 | BRIEF Tells the game you want a long description the first 254 | time you enter a room, and a short description when 255 | you come back. This is the default mode.^ 256 | SUPERBRIEF Tells the game you always want short descriptions of 257 | all rooms.^"; 258 | font on; 259 | 260 | print (bf) "^Getting stuck and unstuck"; 261 | print " 262 | ^While playing IF, you will get stuck. This is part of the deal -- 263 | where there are puzzles, there will also be stuckness. If you grow 264 | tired of being stuck in the same spot for too long, you can either 265 | type HELP in the game to see if there are any hints available, or 266 | you can ask other players for hints. A good place to ask for hints 267 | is the newsgroup rec.games.int-fiction (can be reached at 268 | http://groups.google.com/groups?group=rec.games.int-fiction ). 269 | That's also one of the best 270 | places to meet other IF players, discuss games you've played, get 271 | tips on games you should play and more.^ 272 | 273 | ^Oh, one last thing about playing interactive fiction. Make a map as 274 | you play. You are very likely to need it."; 275 | 276 | ]; 277 | 278 | [ HowToSub; HowToMenu.select(); ]; 279 | 280 | #IFNDEF NO_HOWTO_GRAMMAR; 281 | Verb meta 'help' 'howto' 'instructions' 282 | * -> HowTo; 283 | #ENDIF; 284 | 285 | ! ---------------------------------------------------------------------------- ! 286 | -------------------------------------------------------------------------------- /include/moveclass.h: -------------------------------------------------------------------------------- 1 | ! - 2 | ! MOVECLASS, a library file to provide random, directed and 'intelligent' 3 | ! movement for NPCs 4 | ! 5 | ! Version 8.10, written by Neil Brown neil@highmount.demon.co.uk 6 | ! and Alan Trewartha alan@alant.demon.co.uk 7 | ! with Glulx additions by Matthew T. Russotto 13 March 2001 8 | ! 9 | ! Last altered 5th April 2001. 10 | ! 11 | ! The functions of this library are too complex to go into here, so please 12 | ! refer to the brief manual which should be near to where you found this 13 | ! file, and is named 'moveman.txt'. 14 | ! 15 | ! If you are including the library file FOLLOWER.H in your game code, please 16 | ! include this file AFTERWARDS and not before, otherwise errors will occur. 17 | ! - 18 | 19 | System_file; 20 | ! This is necessary to compile with Graham's current Inform 6.21 compiler. 21 | #ifndef WORDSIZE; 22 | Constant TARGET_ZCODE; 23 | Constant WORDSIZE 2; 24 | #endif; 25 | 26 | ! NPC PROPERTIES 27 | Property before_action; ! Run before moving. 28 | Property after_action; ! Run after a successful move. 29 | Property caprice alias time_left; ! %age chance of moving when random 30 | 31 | Property npc_open; ! A property of doors 32 | 33 | Global path_size_limit = 10; ! Depth of path searching 34 | 35 | Constant RANDOM_MOVE = 0; ! The different possible move_types 36 | Constant AIMED_MOVE = 1; 37 | Constant NO_MOVE = 2; 38 | Constant PRESET_MOVE = 3; 39 | 40 | Constant ANY_PATH = $$00000000; ! The different types of AIMED_MOVEs. 41 | Constant UNLOCKED_PATH = $$00001000; ! Bitmaps so that they can be combined 42 | Constant OPEN_PATH = $$00010000; ! in principle 43 | Constant DOORLESS_PATH = $$00100000; 44 | 45 | !Ifndef NPCRoom; 46 | ! Class NPCRoom with link_data 0 0 0; 47 | !EndIf; 48 | 49 | #ifdef TARGET_ZCODE; 50 | Class MTR_npcdirclass 51 | with npc_dirs 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; 52 | ! The calculated directions that the NPC takes. 53 | ! Note this is a word array, but the dirs are held as 54 | ! single bytes, so a path of 64 moves is possible. 55 | #ifnot; !TARGET_GLULX 56 | Class MTR_npcdirclass 57 | with npc_dirs 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; 58 | ! The assumption that a direction will be a small 59 | ! (byte-sized) integer is bogus in Glulx 60 | ! However, Glulx allows big properties, so we don't 61 | ! lose. --MTR 62 | #endif; 63 | 64 | 65 | 66 | Class moveclass 67 | class MTR_npcdirclass 68 | with move_type 69 | RANDOM_MOVE, ! The default move_type is to move randomly 70 | caprice 20, ! Chance the NPC will move each turn when RANDOM_MOVE 71 | prepath_name 0, ! The name of the predetermined path array 72 | prepath_size 0, ! The length of the set path 73 | npc_stage 0, ! Position along set path array 74 | npc_target, ! The target destination 75 | npc_blocked [; NPC_Path(self,RANDOM_MOVE); ], 76 | ! Alternatively do nothing and wait for the path to 77 | ! unblock. Or, more intelligently look for a less 78 | ! restrictive path. 79 | npc_ifblocked 0, ! Free for use by npc_blocked 80 | npc_arrived [; NPC_Path(self,RANDOM_MOVE); ], 81 | ! Redefine this within the actual NPC object 82 | ! for more sophisticated results. Deals with what 83 | ! happens when an NPC arrives at its destination. In 84 | ! this case, it returns to random movement. 85 | walkoff "walks off", 86 | walkon "arrives", 87 | follow_action, ! } In case Follower has been included but the NPC 88 | follow_object, ! } isn't of FollowClass. 89 | daemon [ i n k; 90 | if (RunRoutines(self,before_action)) rtrue; 91 | 92 | switch(self.move_type) 93 | { 0, RANDOM_MOVE: ! Random movement 94 | #ifdef DEBUG; 95 | if (parser_trace>1) 96 | print "[RANDOM_MOVE daemon for ", (the) self ,"]^"; 97 | #endif; 98 | if (random(100)>self.caprice) rfalse; 99 | objectloop (i in compass) 100 | if (LeadsTo(i,parent(self),ANY_PATH)) 101 | { n++; 102 | #ifdef DEBUG; 103 | if (parser_trace>1) 104 | print "[Choice ",n, ": ",(GiveDir) i ,"]^"; 105 | #endif; 106 | } 107 | if (n==0) rfalse; 108 | k=random(n); n=0; ! Choose one direction 109 | #ifdef DEBUG; 110 | if (parser_trace>1) 111 | print "[Choosing ",k, "]^"; 112 | #endif; 113 | objectloop (i in compass) 114 | { if (LeadsTo(i,parent(self),ANY_PATH)) n++; 115 | if (n==k) 116 | { MoveNPCDir(self,i); 117 | break; 118 | } 119 | } 120 | 121 | 1, AIMED_MOVE : ! Moving on a calculated path 122 | #ifdef TARGET_ZCODE; 123 | i=self.&npc_dirs->self.npc_stage; 124 | #ifnot; ! TARGET_GLULX 125 | i=self.&npc_dirs-->self.npc_stage; 126 | #endif; ! TARGET 127 | 128 | #ifdef DEBUG; 129 | if (parser_trace>1) 130 | print "[AIMED_MOVE daemon moving ", (the) self, " ", (GiveDir) i,"]^"; 131 | #endif; 132 | if (i==0 || MoveNPCDir(self,i)) ! Routine only called if i~=0 133 | self.npc_stage++; 134 | if (parent(self)==self.npc_target) 135 | self.npc_arrived(); 136 | 137 | 2, NO_MOVE : ! Not moving at all 138 | #ifdef DEBUG; 139 | if (parser_trace>1) 140 | print "[NO_MOVE daemon for ", (the) self, " doing nothing]^"; 141 | #endif; 142 | 143 | 3, PRESET_MOVE : ! Moving on a predetermined path 144 | #ifdef TARGET_ZCODE; 145 | i=(self.prepath_name)->self.npc_stage; 146 | #ifnot; ! TARGET_GLULX 147 | i=(self.prepath_name)-->self.npc_stage; 148 | #endif; ! TARGET 149 | 150 | #ifdef DEBUG; 151 | if (parser_trace>1) 152 | print "[PRESET_MOVE daemon moving ", (the) self," ", (GiveDir) i, "]^"; 153 | #endif; 154 | if (i==0 ||MoveNPCDir(self,i)) ! Routine only called if i~=0 155 | self.npc_stage++; 156 | if (self.npc_stage>=self.prepath_size) 157 | self.npc_arrived(); 158 | 159 | default: "** MoveClass Error: move_type set to an unacceptable 160 | value for ", (the) self, " **"; 161 | } 162 | ]; 163 | 164 | 165 | 166 | [ NPC_path npc movement_type targetroom path_type 167 | steps last_room found i j k; 168 | 169 | if (metaclass(movement_type)==Object && movement_type ofclass NPCRoom) 170 | { path_type=targetroom; 171 | targetroom=movement_type; 172 | movement_type=AIMED_MOVE; ! To stay compatible with old code 173 | } 174 | #ifdef DEBUG; 175 | if (parser_trace>1) 176 | {print "^[NPC_Path setting ", (the) self," to "; 177 | switch (movement_type) 178 | { NO_MOVE: print "NO_MOVE"; 179 | RANDOM_MOVE: print "RANDOM_MOVE"; 180 | PRESET_MOVE: print "PRESET_MOVE"; 181 | AIMED_MOVE: print "AIMED_MOVE towards ", (name) targetroom; 182 | default: print "**UNDEFINED**"; 183 | } 184 | print "]^"; 185 | } 186 | #endif; 187 | 188 | if (~~(npc ofclass moveclass)) 189 | { print "*** MoveClass Error: NPC_path called for non-moveclass object '", 190 | (the) npc, "' ***"; 191 | rfalse; 192 | } 193 | 194 | if (movement_type==NO_MOVE) ! Call to set NO_MOVE 195 | { npc.move_type=NO_MOVE; 196 | rtrue; 197 | } 198 | 199 | if (movement_type==RANDOM_MOVE) ! Call to set RANDOM_MOVE 200 | { npc.move_type=RANDOM_MOVE; 201 | if (path_type~=0) 202 | npc.caprice=path_type; 203 | rtrue; 204 | } 205 | 206 | if (movement_type==PRESET_MOVE) ! Call to set PRESET_MOVE 207 | return NPCprepath(npc,targetroom,path_type); 208 | 209 | if (movement_type~=AIMED_MOVE) 210 | rfalse; 211 | 212 | ! VZEFH check 213 | if (parent(npc)==0) 214 | { print "^*** MoveClas Error: NPC_path called for object '", 215 | (the)npc, "' which has parent==0 ***"; 216 | rfalse; 217 | } 218 | 219 | if (~~(parent(npc) ofclass NPCRoom)) 220 | rfalse; 221 | 222 | 223 | ! link_data-->0 is previous ROOM in the linked list of rooms searched 224 | ! link_data-->1 is previous STEP on the possible path 225 | ! link_data-->2 is previous STEP_DIR along the possible path 226 | 227 | last_room=parent(npc); ! All rooms being searched are linked in a list 228 | last_room.&link_data-->0=0; ! starting with 'last_room' and stepping back 229 | last_room.&link_data-->1=-1; ! along the link_room of each room. 230 | 231 | if (last_room==targetroom) 232 | { found=true; ! Allowing the npc_arrived property to run 233 | steps=0; ! if the npc starts in targetroom 234 | npc.&npc_dirs-->0=0; 235 | } 236 | else 237 | { for (steps=1: steps1==0) ! Only want 'NPCRoom's with a 0 STEP 244 | { k.&link_data-->1=i; ! Add such rooms as a STEP on from 'i' 245 | k.&link_data-->2=j; ! Store direction moved to get there 246 | k.&link_data-->0=last_room; ! Add this room to the linked list 247 | last_room=k; 248 | if (k==targetroom) found=true; 249 | #Ifdef DEBUG; 250 | if (parser_trace>1) print "[Found: ",(name) k, "]^"; 251 | #Endif; 252 | } 253 | if (found) break; 254 | } 255 | if (found) break; 256 | if (i.&link_data-->0==i.&link_data-->1) 257 | i=0; ! If link_data STEP = ROOM then the 258 | else ! remaining rooms on the linked list 259 | i=i.&link_data-->0; ! have already been explored and we 260 | } ! can end this iteration. 261 | if (found) break; 262 | } 263 | } 264 | 265 | if (found) 266 | { npc.move_type=AIMED_MOVE; ! Set NPC to AIMED_MOVE 267 | npc.npc_target=targetroom; ! and fill in all the details 268 | npc.prepath_size=steps; 269 | npc.npc_stage=0; 270 | #ifdef DEBUG; 271 | if (parser_trace>1) 272 | print "[Path has ",steps, " steps...^"; 273 | #endif; 274 | i=last_room; ! Now go back to the end of the list 275 | while (i.&link_data-->1~=-1) 276 | { 277 | #ifdef DEBUG; 278 | if (parser_trace>1) 279 | print (name) i," is ", (GiveDir) i.&link_data-->2, " of...^"; 280 | #endif; 281 | 282 | #ifdef TARGET_ZCODE; 283 | npc.&npc_dirs->(steps-1)=i.&link_data-->2; 284 | #ifnot; ! TARGET_GLULX 285 | npc.&npc_dirs-->(steps-1)=i.&link_data-->2; 286 | #endif; ! TARGET 287 | 288 | steps--; ! Write npc_dirs with the STEP_DIRs 289 | i=i.&link_data-->1; ! And go back along the STEPs 290 | 291 | } 292 | #ifdef DEBUG; 293 | if (parser_trace>1) 294 | print "where we started!]^"; 295 | #endif; 296 | } 297 | #Ifdef DEBUG; 298 | if(parser_trace>1 && found==false) print "[No path found!]^"; 299 | #Endif; 300 | 301 | while (last_room~=0) 302 | { 303 | #ifdef DEBUG; 304 | if (parser_trace>4) 305 | {print "[",(name) last_room," = "; 306 | print (object) last_room.&link_data-->0, ", "; 307 | print (object) last_room.&link_data-->1, ", "; 308 | print (object) last_room.&link_data-->2, "]^"; 309 | } 310 | #endif; 311 | last_room.&link_data-->1=0; ! Go back along the linked list 312 | last_room=last_room.&link_data-->0; ! resetting the STEP data. Only 313 | } ! NPCRooms with a 0 STEP are added to 314 | ! the linked list (see above) 315 | return found; 316 | ]; 317 | 318 | 319 | 320 | [ NPCPrePath npc path_array path_length fakevar; 321 | fakevar=fakevar; ! In case code tries passing a room name too 322 | if (npc ofclass moveclass) 323 | { npc.npc_stage=0; 324 | npc.move_type=PRESET_MOVE; 325 | npc.prepath_name=path_array; 326 | npc.prepath_size=path_length; 327 | } 328 | else 329 | { "*** MoveClass Error: NPCPrePath called for non-moveclass object '", 330 | (the) npc, "' ***"; 331 | } 332 | ]; 333 | 334 | Ifndef NOISY_DIR_TOS; 335 | Message "** MoveClass::LeadsTo assuming quiet *_to (NOISY_DIR_TOS not defined) **"; 336 | Endif; 337 | 338 | [ LeadsTo direction thisroom path_type k tmp tmp2; 339 | #ifdef DEBUG; 340 | if (parser_trace>2) 341 | print "[LeadsTo ", (name)direction, " ", (name)thisroom, "]^"; 342 | #endif; 343 | 344 | if (~~(direction provides door_dir)) rfalse; 345 | if (~~(thisroom provides direction.door_dir)) rfalse; 346 | k=thisroom.(direction.door_dir); 347 | 348 | #ifdef NOISY_DIR_TOS; 349 | if (ZRegion(k)==2) rfalse; 350 | #endif; 351 | 352 | #ifndef NOISY_DIR_TOS; 353 | if (ZRegion(k)==2) 354 | k=RunRoutines(thisroom, direction.door_dir); 355 | #endif; 356 | 357 | if (ZRegion(k)~=1) rfalse; 358 | if (k has door) 359 | { if (path_type & DOORLESS_PATH) rfalse; 360 | if ((path_type & OPEN_PATH) && k hasnt open) rfalse; 361 | if ((path_type & UNLOCKED_PATH) && k has locked) rfalse; 362 | tmp=parent(k); 363 | move k to thisroom; 364 | tmp2=k.door_to(); 365 | if (tmp==0) remove k; else move k to tmp; 366 | k=tmp2; 367 | } 368 | if (~~(k ofclass NPCRoom)) rfalse; 369 | return k; 370 | ]; 371 | 372 | 373 | 374 | [ MoveNpcDir npc direction i j p message; 375 | message=2; 376 | p=parent(npc); 377 | i=LeadsTo(direction,p, ANY_PATH); 378 | if (i==0) 379 | { npc.npc_blocked(); 380 | #ifdef DEBUG; 381 | if (parser_trace>1) 382 | print "[MoveNPCDir blocked: Direction leads nowhere]^"; 383 | #endif; 384 | rfalse; 385 | } 386 | 387 | j=p.(direction.door_dir); 388 | if (ZRegion(j)==2) j=j(); 389 | if (j has door) 390 | { if (j provides npc_open) ! npc_open returns 391 | { message=j.npc_open(npc); ! 2 to go through door as normal 392 | if (message==false) ! 1 to go through door and prevent 393 | { npc.npc_blocked(); ! walkon/walkoff run/printing 394 | #ifdef DEBUG; ! 0 to stop npc using door 395 | if (parser_trace>1) 396 | print "[MoveNPCDir blocked: ", (the) j, "'s npc_open returned false]^"; 397 | #endif; 398 | rfalse; 399 | } 400 | } 401 | else 402 | if (j hasnt open) 403 | { npc.npc_blocked(); 404 | #ifdef DEBUG; 405 | if (parser_trace>1) 406 | print "[MoveNPCDir blocked: ", (the) j, " is closed with no npc_open]^"; 407 | #endif; 408 | rfalse; 409 | } 410 | } 411 | 412 | MoveNPC(npc, i, ##Go, direction); 413 | 414 | if (p==location && message==2) ! If npc_open used then it must return 2 415 | { if (ZRegion(npc.walkoff)==3) ! if it wants walkon/walkoff to execute 416 | print "^", (The) npc, " ", (string) npc.walkoff, 417 | " ", (GiveDir) direction, ".^"; 418 | else 419 | npc.walkoff(direction); 420 | } 421 | 422 | if (parent(npc)==location && message==2) 423 | { if (ZRegion(npc.walkon)==3) 424 | print "^", (The) npc, " ", (string) npc.walkon, ".^"; 425 | else 426 | npc.walkon(direction); 427 | } 428 | 429 | if (npc provides after_action) npc.after_action(); 430 | rtrue; 431 | ]; 432 | 433 | 434 | 435 | Ifndef MoveNPC; ! Provides MoveNPC if program isn't including 'Follower' 436 | [ MoveNPC npc dest actn objn; 437 | move npc to dest; 438 | actn=actn; 439 | objn=objn; 440 | ]; 441 | Endif; 442 | 443 | 444 | 445 | [ GiveDir i; 446 | switch(i) 447 | { n_obj: print "to the north"; 448 | s_obj: print "to the south"; 449 | e_obj: print "to the east"; 450 | w_obj: print "to the west"; 451 | ne_obj: print "to the northeast"; 452 | nw_obj: print "to the northwest"; 453 | se_obj: print "to the southeast"; 454 | sw_obj: print "to the southwest"; 455 | u_obj: print "upwards"; 456 | d_obj: print "downwards"; 457 | in_obj: print "inside"; 458 | out_obj: print "outside"; 459 | } 460 | ]; 461 | -------------------------------------------------------------------------------- /include/seeno.h: -------------------------------------------------------------------------------- 1 | ! seeno.h for Inform 6 with library 6/12 2 | ! 3 | ! This code is distributed under the Artistic License version 2.0. 4 | ! See http://opensource.org/licenses/Artistic-2.0 5 | ! 6 | ! A library to change the standard Inform message 7 | ! "You can't see any such thing." to the more specific 8 | ! "You see no xxx yyy here." Note that this can repeat typing errors 9 | ! back to the player. 10 | ! 11 | ! Written by C Knight. 12 | ! Comments and bug reports welcomed: please see 13 | ! www.metebelis3.free-online.co.uk to email. 14 | ! 15 | ! Based on dunno.h (I don't know the word "kludge") 16 | ! version 1.1 - 2 Apr 2001 by Neil Cerutti (cerutti@together.net) 17 | ! seeno.h is now entirely unlike dunno.h. 18 | ! 19 | ! Updated by David Griffith to support 6/12's first and third person voices. 20 | ! July 24, 2014 21 | ! 22 | ! To use this file, put the command 23 | ! 24 | ! Include "seeno.h"; 25 | ! 26 | ! in your program's source code after including "parser". 27 | ! 28 | ! If you have defined your own ParserError() routine, you might instead 29 | ! call CantSeeError() routine in a LibraryMessages object 30 | ! (Inform Designer's Manual, 4th ed., section 25): 31 | ! 32 | ! Object LibraryMessages with before [; 33 | ! Miscellany: if (lm_n == 30) return CantSeeError(); 34 | ! ]; 35 | ! 36 | ! Version history 1.0 - 16 May 2003 37 | ! Version history 1.1 - 22 Sep 2003. Fixed TAKE ALL FROM X problem. 38 | 39 | ! Can override these constants by defining them before including the file: 40 | ! 41 | ! "You see no " is now generated by CSubjectVerb() 42 | Default SEENO_MSG1 " no "; ! or "You see nothing that can be described as ~" 43 | Default SEENO_MSG2 " here."; 44 | 45 | #ifdef ParserError; 46 | #message "Warning: To use cantsee.h, call it from ParserError or LibraryMessages."; 47 | #ifnot; 48 | [ ParserError pe; 49 | if (pe == CANTSEE_PE) return CantSeeError(); 50 | rfalse; 51 | ]; 52 | #endif; 53 | 54 | [ CantSeeError wordnum word nwords stop pos end; 55 | wordnum=saved_oops; 56 | #ifdef TARGET_GLULX; 57 | nwords=parse-->0; 58 | #ifnot; 59 | nwords=parse->1; ! end of line 60 | #endif; 61 | if (wordnum > 0) 62 | { 63 | #ifdef TARGET_GLULX; 64 | word=parse-->(wordnum*3-2); 65 | #ifnot; 66 | word=parse-->(wordnum*2-1); 67 | #endif; 68 | ! this most likely the result of TAKE ALL FROM X, in which case use the default message 69 | if (word && (word->#dict_par1 & $80) ~= $80) rfalse; 70 | 71 | CSubjectVerb(actor, false, false, "see", 0, "sees"); 72 | print (string) SEENO_MSG1; 73 | do { ! print at least one word, more if the noun phrase needs it 74 | pos=WordAddress(wordnum); end = WordLength(wordnum) + pos; 75 | for (: pos0; 77 | wordnum++; 78 | if (wordnum > nwords) stop=1; ! end of line 79 | else { 80 | #ifdef TARGET_GLULX; 81 | word=parse-->(wordnum*3-2); 82 | #ifnot; 83 | word=parse-->(wordnum*2-1); 84 | #endif; 85 | if (word) { ! recognised 86 | if (word->#dict_par1 & $88 ~= $80) stop=1; ! not noun, or poss prep 87 | if (word == AND1__WD or ',//' or './/' 88 | or BUT1__WD or BUT2__WD) ! conjunction 89 | stop=1; 90 | } 91 | } ! not end of line 92 | if (~~stop) print " "; 93 | } until (stop); 94 | oops_from = saved_oops; 95 | print_ret (string) SEENO_MSG2; 96 | } 97 | else rfalse; 98 | ]; 99 | 100 | ! end seeno.h 101 | -------------------------------------------------------------------------------- /include/shuffle.h: -------------------------------------------------------------------------------- 1 | ! ---------------------------------------------------------------------------- ! 2 | ! Shuffle.h 3 | ! original 1.0 Sep00 by Roger Firth (roger.firth@tesco.net) for Inform 6 4 | ! 5 | ! The license for this code has been changed to Artistic License 2.0 6 | ! See http://mailman.greennet.org.uk/pipermail/inform-maintenance/2014-July/001985.html 7 | ! 8 | ! ---------------------------------------------------------------------------- ! 9 | ! Installation: add the line: 10 | ! 11 | ! Include "Shuffle"; 12 | ! 13 | ! anywhere in your game AFTER the Include "Parser" statement. 14 | ! 15 | ! ---------------------------------------------------------------------------- ! 16 | ! Shuffle() is like random(), in that it returns a random number in the 17 | ! range 1..N. Unlike random, it returns a different value on each call, 18 | ! until all N possible numbers have been used, at which point it starts 19 | ! a new cycle. It's like dealing a shuffled pack of cards: the Two of Clubs 20 | ! might show up at any time, but can appear only once per deal. 21 | ! 22 | ! Shuffle() uses arrays of bit flags to track the numbers which have been 23 | ! used within a cycle. A default set of 56 flags is supplied, so that if you 24 | ! use the routine only once within your program, and you need shuffled numbers 25 | ! only in the range 1..56, then all you need do is to call the routine. 26 | ! For example, to simulate dealing a pack of cards, you might write: 27 | ! 28 | ! for (i=0 : i<52 : i++) { 29 | ! j = Shuffle(52) - 1; 30 | ! suit = j/13; ! 0,1,2,3 31 | ! rank = 1 + j%13; ! 1,2, ... 13 32 | ! ... 33 | ! } 34 | ! 35 | ! More commonly, however, you'll need to use Shuffle() for several different 36 | ! purposes, and here you are advised to create separate flag arrays for each. 37 | ! Declare the arrays as in these examples: 38 | ! 39 | ! Array mySmallFlags -> 2; ! for up to 8 flags 40 | ! Array myBiggerFlags -> 3; ! for up to 16 flags 41 | ! Array myMediumFlags -> 5; ! for up to 32 flags 42 | ! Array myLargeFlags -> 33; ! for up to 256 flags 43 | ! 44 | ! (That is, the data structure is a byte array in which the first byte holds 45 | ! a count 0..255, and the remaining bytes each supply eight flag bits. 46 | ! Note that if you need to generate shuffled numbers in a range greater than 47 | ! 1..256, you must modify the routine so that the count is held as a word.) 48 | ! Then, supply the array name as the second parameter to Shuffle(): 49 | ! 50 | ! j = Shuffle(7, mySmallFlags); 51 | ! j = Shuffle(20, myMediumFlags); 52 | ! 53 | ! The application for which Shuffle() was written was to randomise NPC 54 | ! responses in a number of default situations. For example: 55 | ! 56 | ! Array old_man_give -> 2; 57 | ! Array old_man_show -> 2; 58 | ! Array old_man_tell -> 2; 59 | ! 60 | ! Object old_man "old man" 61 | ! has animate 62 | ! with ... 63 | ! life [; 64 | ! ... 65 | ! Give: switch (Shuffle(2, old_man_give)) { 66 | ! 1: print_ret (The) self, " doesn't want ", (the) noun, "."; 67 | ! 2: print_ret (The) self, " ignores your offering."; 68 | ! } 69 | ! Show: switch (Shuffle(3, old_man_show)) { 70 | ! 1: print_ret (The) self, " isn't interested in ", (the) noun, "."; 71 | ! 2: print_ret (The) self, " peers back distainfully."; 72 | ! 3: "~I've seen hundreds of them in my time.~"; 73 | ! } 74 | ! Tell: switch (Shuffle(5, old_man_tell)) { 75 | ! 1: print_ret "There's no sign that ", (the) self, " has heard you."; 76 | ! 2: print_ret (The) self, " points to his broken hearing-aid."; 77 | ! 3: "~YOU'LL HAVE TO SPEAK UP - I'M A BIT DEAF.~"; 78 | ! 4: "~I don't know any more than you do.~"; 79 | ! 5: "Fancy that, then."; 80 | ! } 81 | ! ]; 82 | ! 83 | ! ---------------------------------------------------------------------------- ! 84 | !#ifdef DEBUG; message "Compiling Shuffle.h"; #endif; 85 | 86 | Array flagBit -> $01 $02 $04 $08 $10 $20 $40 $80; 87 | Array flagDefault -> 8; ! default of count byte + 56 flag bits 88 | 89 | [ Shuffle range flags n x y z; 90 | if (range < 2) return 1; 91 | if (flags == 0) flags = flagDefault; 92 | while (true) { 93 | n = random(range); ! possible return value 94 | x = (n-1)%8; ! bit 0..7 within flag byte 95 | y = 1+(n-1)/8; ! byte 1.. within flag array 96 | if ((flags->y & flagBit->x) == 0) break; 97 | } ! loop until unused flag found 98 | if (flags->0 == range-1) ! last unused flag? 99 | for (z = 1+(range-1)/8 : z>=0 : z--) 100 | flags->z = 0; ! clear count and all flags 101 | flags->0 = flags->0 + 1; ! increment count, set flag 102 | flags->y = (flags->y | flagBit->x); 103 | return n; 104 | ]; 105 | 106 | ! ---------------------------------------------------------------------------- ! 107 | -------------------------------------------------------------------------------- /include/smartcantgo.h: -------------------------------------------------------------------------------- 1 | !==============================================================================! 2 | ! SMARTCANTGO.H 3 | ! David Wagner 4 | ! Version 3 5 | ! 8-Nov-1995 6 | ! Revisited for Inform 6 by Roger Firth 7 | ! Version 5 8 | ! 3-Feb-1999 9 | ! Revisited for Library 6/12 enhancements by David Griffith 10 | ! Version 6 11 | ! 24-Jul-2014 12 | ! 13 | ! This license for this code has been changed to Artistic License 2.0 14 | ! http://mailman.greennet.org.uk/pipermail/inform-maintenance/2014-July/001985.html 15 | ! 16 | ! Defines a routine that can be used for the cant_go property of rooms to 17 | ! helpfully list the exits, instead of saying just "You can't go that way." 18 | ! Store the code in a file "smartcantgo.h" and include it into games with the 19 | ! following line (placed anywhere after the standard Include "Parser";): 20 | ! 21 | ! Include "smartcantgo"; 22 | ! 23 | ! Once the routine has been Included, the following code: 24 | ! 25 | ! Object Crystal_Cave "Crystal Cave" 26 | ! with s_to Narrow_Passage, 27 | ! cant_go [; SmartCantGo(); ] 28 | ! ...; 29 | ! 30 | ! will produce the message "You can go only south." if the player goes 31 | ! the wrong way. 32 | ! 33 | ! Rather than explicitly add the cant_go routine to each room, you can 34 | ! add it to a Room class from which your actual rooms are derived: 35 | ! 36 | ! Class Room 37 | ! with cant_go [; SmartCantGo(); ], 38 | ! has light; 39 | ! 40 | ! In theory, you can instead change the default behaviour of the cant_go 41 | ! routine by adding the following line to your Initialise routine, but in 42 | ! practise there's a library bug/feature which prevents this working properly: 43 | ! 44 | ! ChangeDefault(cant_go, SmartCantGo); 45 | ! 46 | !==============================================================================! 47 | ! NOTES 48 | ! 49 | ! 1. If the room is dark, it prints just "You can't go that way." 50 | ! How could the player know where the exits are? 51 | ! 52 | ! 2. This routine ignores direction properties which point to concealed 53 | ! doors or are strings. Therefore this code won't work quite as intended 54 | ! in the following room: 55 | ! 56 | ! Object Library "Library" 57 | ! with description 58 | ! "A small wood-panelled library. An open window to the west 59 | ! affords a stunning view of the Tuscan coastline.", 60 | ! w_to 61 | ! "Ouch! You discover that the ~window~ is really 62 | ! an incredibly lifelike mural painted on the wall.", 63 | ! ...; 64 | ! 65 | ! 3. This routine does include direction properties that are routines 66 | ! on the assumption that the routine will return something sensible. 67 | ! If your routine returns a concealed door, you will have to do 68 | ! something different. 69 | ! 70 | ! 4. This routine is adequate for the rare occasions when the player types 71 | ! the wrong direction. One might be tempted to use this routine to 72 | ! simplify room descriptions, as in: 73 | ! 74 | ! Object Boring_Room "Boring Room" 75 | ! with description [; 76 | ! print "A small room with white walls. "; 77 | ! SmartCantGo(); 78 | ! ], 79 | ! ...; 80 | ! 81 | ! Don't do this! Part of the interest of a room is a good description 82 | ! of the exits. 83 | ! 84 | !==============================================================================! 85 | [ SmartCantGo room i dest desttype ndir; 86 | 87 | if (location == thedark) { 88 | CSubjectCant(actor, true); 89 | " go that way."; 90 | } 91 | ! Find what room the player is in. 92 | 93 | room = location; 94 | while (parent(room)) room = parent(room); 95 | 96 | ! Count the number of exits -- if a direction property is a string or 97 | ! a concealed door, don't count it; if it is a routine, count it. 98 | 99 | ndir = 0; 100 | objectloop (i in compass) { 101 | dest = room.(i.door_dir); 102 | if (dest) { 103 | desttype = ZRegion(dest); 104 | if ((desttype ~= 3) && 105 | (desttype == 2 || dest hasnt door || dest hasnt concealed)) 106 | ndir++; 107 | } 108 | } 109 | if (ndir == 0) "There are no exits."; 110 | 111 | ! Print the exits. 112 | 113 | CSubjectCan(actor, true); 114 | print " go only "; 115 | objectloop (i in compass) { 116 | dest = room.(i.door_dir); 117 | if (dest) { 118 | desttype = ZRegion(dest); 119 | if ((desttype ~= 3) && 120 | (desttype == 2 || dest hasnt door || dest hasnt concealed)) { 121 | PrintDirectionName(i); 122 | switch (--ndir) { 123 | 0: "."; 124 | 1: print " or "; 125 | default: print ", "; 126 | } 127 | } 128 | } 129 | } 130 | ]; 131 | 132 | !==============================================================================! 133 | [ PrintDirectionName obj; 134 | 135 | switch (obj) { 136 | n_obj: print "north"; 137 | s_obj: print "south"; 138 | e_obj: print "east"; 139 | w_obj: print "west"; 140 | ne_obj: print "northeast"; 141 | se_obj: print "southeast"; 142 | nw_obj: print "northwest"; 143 | sw_obj: print "southwest"; 144 | u_obj: print "up"; 145 | d_obj: print "down"; 146 | in_obj: print "in"; 147 | out_obj: print "out"; 148 | default: print "some unspecified direction"; 149 | } 150 | ]; 151 | 152 | !==============================================================================! 153 | -------------------------------------------------------------------------------- /include/sound.h: -------------------------------------------------------------------------------- 1 | !---------------------------------------------------------------------------- 2 | ! Sound An Inform 6 library by L. Ross Raszewski to handle 3 | ! Inform's sound capabilities. Requires sound card. 4 | ! CAUTION: MAY BEHAVE UNPREDICTABLY ON SOME INTERPRETERS 5 | ! 6 | ! Most notably, the "Sequencer" option intermittenly crashes Frotz on my 7 | ! system rather dramatically. I'm not sure if it's my interpreter or my 8 | ! computer. At any rate, be careful. I've had no trouble with the other 9 | ! operations, but that's no guarantee. 10 | ! 11 | ! This system consumes three global variables and one array: 12 | ! play_sounds - If play_sounds=1, sounds will be played, if 0, they will not. 13 | ! sound_vol - a number from 1 to 8, setting the volume 14 | ! playing - A bit array holding three bites used internally. ->0 indicates 15 | ! whether or not PlaySound has been called yet. 16 | ! ->1 indicates the currenly playing sound effect number 17 | ! ->2 is used by internal operations 18 | ! 19 | ! This library plays sound effects of the formats described in Stefan 20 | ! Jokisch's treatise on Infocom sound formats. The actual conventions of the 21 | ! format are handled by the interpreter, but, and there's a lot more on this in 22 | ! the Specification of the Z-Machine, sound_effects 1 and 2 are beeps, and 3 23 | ! and up are sound files in an arcane and proprietary format. (There's a beta 24 | ! version of SOX that an write to them, however.) Once you have the files where 25 | ! your interpreter wants them (usually the "sound" subdirectory), the 26 | ! @sound_effect opcode plays these sounds. However, the nature of 27 | ! @sound_effect is such that its use isn't intuative. Indeed, there's three 28 | ! lines of assembly I had to stick in to make it work (liberally stolen from 29 | ! Sherlock) This library makes this useable. 30 | ! 31 | ! Usage: 32 | ! To play a sound: 33 | ! PlaySound(sound_number); 34 | ! Options: 35 | ! PlaySound(sound_number,reps); 36 | ! - plays a sound effect a set number of times 37 | ! PlaySound(sound_number,Routine,[option]); 38 | ! - Plays a sound effect, and runs Routine when the effect 39 | ! has finished. The third argument is stored in the global 40 | ! variable sequence. 41 | ! Features: 42 | ! If you're using my footnote library, a footnote will be called 43 | ! the first time PlaySound is used. The number of that footnote 44 | ! should be stored in a constant "SoundNote". Such a footnote 45 | ! could say something like "Type "SOUND OFF" to disable sounds" 46 | ! 47 | ! Routines included: 48 | ! Sequencer: Call PlaySound(Sequencer,array);. This will cause 49 | ! each sound effect in the array to be played in order. 50 | ! array->0 MUST be the number of sounds to play, however. 51 | ! Note: This only works about one time in five on my system 52 | ! if anyone could explain why, I'd be much obliged. 53 | ! Repeat and Fade: Call PlaySound(sound_number,RepAndFade); to 54 | ! cause a sound effect to repeat and fade out. 55 | ! Fade In: Call PlaySound(sound_number, FadeIn); and the sound effect 56 | ! will repeat while fading in. 57 | ! 58 | ! End-User Functions: 59 | ! Sound - Toggles sound on and off 60 | ! Sound On - Turns sound on 61 | ! Sound Off- Turns sound off 62 | ! Sound Up - Turns volume up 63 | ! Sound Down- Turns volume down 64 | ! Sound (number)- Sets volume 65 | ! 66 | ! Debugging Suite: 67 | ! Audio (number)- Plays the corresponding sound effect 68 | ! Audio (2 numbers) Plays the corresponding effect a number of times 69 | ! Audio FIN # - Fades in the sound effect 70 | ! Audio RF # - Repeats and fades sound effect 71 | ! 72 | 73 | 74 | 75 | global play_sounds=1; 76 | global sound_vol=5; 77 | global sequence; 78 | array playing -> 3; 79 | [ PlaySound i Rout k j l; 80 | if (play_sounds==0) rtrue; 81 | #IFDEF SoundNote; 82 | if (playing->0==0) print "^", (Note) SoundNote, "^"; 83 | playing->0=1; 84 | #ENDIF; 85 | if (i ofclass Routine) {sequence=Rout; indirect(i); rtrue;}; 86 | if (~~(Rout ofclass Routine)){j=Rout; Rout=0;}; 87 | if (j==0) j=1; 88 | if (Rout==0) Rout=StopSound; 89 | l=sound_vol; 90 | if (Rout==FadeIn) l=1; 91 | playing->1=i; 92 | sequence=k; 93 | @log_shift j 8 sp; 94 | @or sp l sp; 95 | @sound_effect i 2 sp Rout; 96 | ]; 97 | [ StopSound i; 98 | i=playing->1; 99 | @sound_effect i 4; 100 | ]; 101 | [ FadeIn; 102 | playing->2=1; 103 | FIner(); 104 | ]; 105 | [ FIner i j; 106 | playing->2=playing->2+1; 107 | i=playing->1; 108 | j=playing->2; 109 | @log_shift 1 8 sp; 110 | @or sp j sp; 111 | if (j<=sound_vol) 112 | @sound_effect i 2 sp FIner; 113 | ]; 114 | 115 | [ RepAndFade; 116 | playing->2=sound_vol; 117 | RnF(); 118 | ]; 119 | [ RnF j i; 120 | playing->2=playing->2-1; 121 | i=playing->1; 122 | j=playing->2; 123 | @log_shift 1 8 sp; 124 | @or sp j sp; 125 | if (j>=1) 126 | @sound_effect i 2 sp RnF; 127 | ]; 128 | [ Sequencer; 129 | playing->2=0; 130 | SeqNext(); 131 | ]; 132 | [ SeqNext j i k; 133 | playing->2=playing->2+1; 134 | j=playing->2; 135 | if (j>sequence->0) rtrue; 136 | i=sequence->j; 137 | @log_shift 1 8 k; 138 | @or k sound_vol k; 139 | @sound_effect i 2 k SeqNext; 140 | ]; 141 | 142 | [ SoundToggleSub; 143 | if (play_sounds==1) <>; 144 | if (play_sounds==0) <>; 145 | ]; 146 | [ SoundVolSub; 147 | if (noun>8 || noun <=0) "Please specify a volume level between 1 and 8."; 148 | sound_vol=noun; 149 | "Sound volume set to ", sound_vol, "."; 150 | ]; 151 | [ SoundUpSub; 152 | if (sound_vol==8) "Maximum volume"; 153 | sound_vol++; 154 | "Sound volume set to ", sound_vol, "."; 155 | ]; 156 | [ SoundDownSub; 157 | if (sound_vol==1) "Minimum volume"; 158 | sound_vol--; 159 | "Sound volume set to ", sound_vol, "."; 160 | ]; 161 | [ SoundsOnSub; 162 | play_sounds=1; 163 | "Sound on."; 164 | ]; 165 | [ SoundsOffSub; 166 | play_sounds=0; 167 | "Sound off."; 168 | ]; 169 | verb "sound" "sounds" "volume" * -> SoundToggle 170 | * "on" -> SoundsOn 171 | * "off" -> SoundsOff 172 | * "up" -> SoundUp 173 | * "down" -> SoundDown 174 | * number -> SoundVol; 175 | 176 | #IfDef DEBUG; 177 | [ AudioSub; 178 | PlaySound(noun); 179 | ]; 180 | [ AudioRSub; 181 | PlaySound(noun,RepAndFade); 182 | ]; 183 | [ AudioFINSub; 184 | PlaySound(noun,FadeIn); 185 | ]; 186 | [ AudioXRSub; 187 | PlaySound(noun,second); 188 | ]; 189 | 190 | verb "audio" * number ->Audio 191 | * number number ->AudioXR 192 | * "Fin" number ->AudioFIN 193 | * "RF" number ->AudioR; 194 | #ENDIF; 195 | !--------------------------------------------------------------------------- 196 | -------------------------------------------------------------------------------- /include/torch.h: -------------------------------------------------------------------------------- 1 | ! ------------------------------------------------------------------------- 2 | ! torch.h 3 | ! 4 | ! Copyright 2004 David Griffith 5 | ! This code is distributed under the Artistic License version 2.0. 6 | ! See http://opensource.org/licenses/Artistic-2.0 7 | ! 8 | ! This code allows one to simulate torches (the flaming, wooden kind). 9 | ! One can have good ones (ready to be ignited), burning ones, and 10 | ! burned-out ones. 11 | ! 12 | ! 13 | ! Include this file sometime after VerbLib. 14 | ! 15 | ! 16 | ! Somewhere at the beginning of your code, you'll need to set the 17 | ! following constants: 18 | ! 19 | ! Constant TORCH_COUNT = 18; ! how many torches in the game 20 | ! Constant TORCH_VARIANCE = 7; ! some randomness 21 | ! Constant TORCH_LIFE = 50; ! how many moves a torch will last 22 | ! Constant TORCH_DECLINE = 5; ! torch starts sputtering 23 | ! Constant TORCH_DYING = 1; ! torch is about to go out 24 | ! 25 | ! Here is a handy way to give the player a burning torch at the 26 | ! begining of the game. Use it in the Initialize() function. 27 | ! 28 | ! move players_torch to player; 29 | ! players_torch.power = TORCH_LIFE; 30 | ! StartDaemon(players_torch); 31 | ! 32 | ! Make sure that you've actually created players_torch somewhere outside 33 | ! of the functions. Do it like this: 34 | ! 35 | ! BurningTorch players_torch; 36 | ! 37 | ! Now, when you want to have some torches sitting around for the player 38 | ! to pick up, do this: 39 | ! 40 | ! UnlitTorch ->; 41 | ! 42 | ! That will create one unlit torch. When picked up, the game will 43 | ! respond with "You pull the unlit torch off the wall". Similarly, you 44 | ! can use "BurningTorch ->;" to have a burning torch stuck on a wall. 45 | ! The same goes for a dead torch. Count up all the times you do this 46 | ! and put that number as TORCH_COUNT (see above). 47 | ! 48 | ! You shouldn't need to modify anything below this point. If you do, 49 | ! please let me know why and how you modified the code. 50 | ! 51 | ! Version History: 52 | ! 1.0 - 2004 53 | ! 1.1 - 24 Jul 2014 - Update to use 6/12's CSubject functions. 54 | ! 55 | 56 | Class Torch 57 | with name "torch", 58 | power, 59 | parse_name [ i j w; 60 | if (parser_action == ##TheSame) { 61 | if ((parser_one.&name)-->0 == (parser_two.&name)-->0) { 62 | return -1; 63 | } 64 | return -2; 65 | } 66 | w = (self.&name)-->0; 67 | for (:: i++) { 68 | j = NextWord(); 69 | if (j == 'torches') parser_action=##PluralFound; 70 | else if (j~='torch' or w) return i; 71 | } 72 | ], 73 | daemon [ t newthing i; 74 | t = --(self.power); 75 | if (t == 0) { 76 | give self ~on ~light; 77 | newthing = DeadTorch.create(); 78 | give newthing moved; 79 | move newthing to parent(self); 80 | remove self; 81 | } 82 | if (self in player || self in location) { 83 | objectloop (i in player) { 84 | if (i ofclass BurningTorch) { 85 | if (i.power > TORCH_DECLINE) 86 | rtrue; 87 | } 88 | } 89 | if (t == TORCH_DECLINE + 1) 90 | "^Your torch is beginning to flicker."; 91 | if (t <= TORCH_DECLINE && t > TORCH_DYING) 92 | "^Your torch is flickering and sputtering."; 93 | if (t <= TORCH_DYING && t > 0) 94 | "^Your torch is going out."; 95 | if (t == 0) 96 | "^Your torch goes out with a fizzle."; 97 | } 98 | ], 99 | before [newthing; 100 | Smell: 101 | print "It smells like "; 102 | if (self ofclass UnlitTorch) 103 | "oil and dirt."; 104 | if (self ofclass BurningTorch) 105 | "burning oil and dirt."; 106 | if (self ofclass DeadTorch) 107 | "oily soot."; 108 | "Error in Torch class (Smell)^"; 109 | Examine: 110 | if (self ofclass UnlitTorch) 111 | "It's a torch. An oil-soaked rag is wrapped around it."; 112 | if (self ofclass DeadTorch) 113 | "It's a burned out and useless torch."; 114 | if (self ofclass BurningTorch) { 115 | print "The torch throws "; 116 | if (self.power < TORCH_DECLINE) { 117 | print "feeble"; 118 | } else { 119 | print "dancing"; 120 | } 121 | print " shadows about the place."; 122 | } 123 | "Error in Torch class (Examine)^"; 124 | Burn: 125 | if (second ~= nothing) { 126 | if (second hasnt on) 127 | CSubjectCant(actor, true); 128 | " burn ", (the) self, " with ", (the) 129 | second, "."; 130 | } 131 | if (self has on) "But it's already lit!"; 132 | <>; 133 | SwitchOff: 134 | if (verb_word == 'turn' or 'switch') 135 | "Perhaps snuffing the torch would be more useful."; 136 | if (self ofclass UnlitTorch or DeadTorch) 137 | "But it's not burning."; 138 | if (self ofclass BurningTorch) { 139 | newthing = DeadTorch.create(); 140 | move newthing to parent(self); 141 | give newthing moved; 142 | remove self; 143 | CSubjectVerb(actor, true, "snuff", 0, "snuffs"); 144 | " out the torch."; 145 | } 146 | "Error in Torch class (SwitchOff)^"; 147 | ], 148 | 149 | after [newthing; 150 | Take: 151 | if (self hasnt moved) 152 | CSubjectVerb(actor, true, "pull", 0, "pulls"); 153 | " ", (the) noun, " off the wall."; 154 | 155 | SwitchOn: 156 | if (second == nothing) { 157 | give self ~on; 158 | "Perhaps lighting the torch with something 159 | would be more useful."; 160 | } 161 | if (self ofclass UnlitTorch) { 162 | newthing = BurningTorch.create(); 163 | if (newthing == nothing) { 164 | "Programming error! 165 | Can't light the torch."; 166 | } 167 | move newthing to parent(self); 168 | newthing.power = TORCH_LIFE + random(TORCH_VARIANCE); 169 | remove self; 170 | StartDaemon(newthing); 171 | "The torch burns brightly."; 172 | } 173 | if (self ofclass BurningTorch) 174 | "But it's already burning."; 175 | if (self ofclass DeadTorch) { 176 | give self ~on; 177 | "The dead torch sputters a bit, but 178 | refuses to light."; 179 | } 180 | "Error in Torch class (SwitchOn)^"; 181 | ], 182 | has switchable float; 183 | 184 | 185 | Class UnlitTorch (TORCH_COUNT) 186 | class Torch 187 | with name "unlit" "good" "torch", 188 | short_name "unlit torch", 189 | plural "unlit torches"; 190 | 191 | Class BurningTorch (TORCH_COUNT) 192 | class Torch 193 | with name "burning" "torch", 194 | short_name "burning torch", 195 | plural "burning torches", 196 | has on light; 197 | 198 | Class DeadTorch (TORCH_COUNT) 199 | class Torch 200 | with name "dead" "bad" "torch", 201 | short_name "dead torch", 202 | plural "dead torches"; 203 | -------------------------------------------------------------------------------- /include/trinitystat.h: -------------------------------------------------------------------------------- 1 | ! Trinitystat.h 2 | ! This library gives the ability to switch between the normal statusline and a 3 | ! Trinity style statusline. It works for both the Z-Machine and Glulx, and 4 | ! should work on all three compilers. (G.N.'s Z-Machine compiler, A.P.'s Glulx 5 | ! compiler, and A.P.'s biplatform compiler.) It has only been tested on the 6 | ! biplatform compiler, though. 7 | 8 | ! You must, of course, Replace DrawStatusLine; for this to work. 9 | 10 | ! An object is supplied, statline, with a property trinity. If trinity is true, 11 | ! then you will have a Trinity-style line. Guess what happens if trinity is 12 | ! false? 13 | 14 | ! If you have defined Constant DEBUG;, then you get an extra debugging verb. 15 | ! Typing "trinity" will switch statusline styles. 16 | 17 | ! Copyright (C) 2000 by Jonathan Rosebaugh. Released under GPL version 2. 18 | ! see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 19 | 20 | ! This is necessary to compile with Graham's current Inform 6.21 compiler. 21 | #ifndef WORDSIZE; 22 | Constant TARGET_ZCODE; 23 | Constant WORDSIZE 2; 24 | #endif; 25 | 26 | ! Debugging verb 27 | #ifdef DEBUG; 28 | Object statline with trinity 0; 29 | Verb meta "trinity" 30 | * -> Trinity; 31 | [TrinitySub; 32 | statline.trinity = (~~(statline.trinity)); 33 | ]; 34 | #endif; 35 | 36 | ! Z-Code version 37 | #ifdef TARGET_ZCODE; 38 | Array printed_text table 64; 39 | 40 | #IFV5; 41 | [ DrawStatusLine width posa posb i j; 42 | if (statline.trinity) 43 | { 44 | i = 0->33; if (i==0) i=80; 45 | font off; 46 | @split_window 1; @buffer_mode 0; @set_window 1; 47 | style reverse; @set_cursor 1 1; spaces(i); 48 | printed_text-->0 = 64; 49 | @output_stream 3 printed_text; 50 | if (location == thedark) print (name) location; 51 | else 52 | { FindVisibilityLevels(); 53 | if (visibility_ceiling == location) 54 | print (name) location; 55 | else print (The) visibility_ceiling; 56 | } 57 | @output_stream -3; 58 | j=(i-(printed_text-->0))/2; 59 | @set_cursor 1 j; print (name) location; spaces(j-1); 60 | style roman; 61 | @buffer_mode 1; @set_window 0; font on; 62 | } 63 | else { @split_window 1; @set_window 1; @set_cursor 1 1; style reverse; 64 | width = 0->33; posa = width-26; posb = width-13; 65 | spaces width; 66 | @set_cursor 1 2; 67 | if (location == thedark) print (name) location; 68 | else 69 | { FindVisibilityLevels(); 70 | if (visibility_ceiling == location) 71 | print (name) location; 72 | else print (The) visibility_ceiling; 73 | } 74 | if ((0->1)&2 == 0) 75 | { if (width > 76) 76 | { @set_cursor 1 posa; print (string) SCORE__TX, sline1; 77 | @set_cursor 1 posb; print (string) MOVES__TX, sline2; 78 | } 79 | if (width > 63 && width <= 76) 80 | { @set_cursor 1 posb; print sline1, "/", sline2; 81 | } 82 | } 83 | else 84 | { @set_cursor 1 posa; 85 | print (string) TIME__TX; 86 | LanguageTimeOfDay(sline1, sline2); 87 | } 88 | @set_cursor 1 1; style roman; @set_window 0; 89 | } 90 | ]; 91 | #ENDIF; 92 | 93 | #endif; ! TARGET_ZCODE 94 | 95 | ! Glulx version 96 | #ifdef TARGET_GLULX; 97 | Array bluelalablankage-->1; 98 | 99 | 100 | [ DrawStatusLine width height posa posb centerarea; 101 | ! If we have no status window, we must not try to redraw it. 102 | if (gg_statuswin == 0) 103 | return; 104 | 105 | ! If there is no player location, we shouldn't try either. 106 | if (location == nothing || parent(player) == nothing) 107 | return; 108 | 109 | glk($002F, gg_statuswin); ! set_window 110 | StatusLineHeight(gg_statuswin_size); 111 | 112 | glk($0025, gg_statuswin, gg_arguments, gg_arguments+4); 113 | ! window_get_size 114 | width = gg_arguments-->0; 115 | height = gg_arguments-->1; 116 | posa = width-26; posb = width-13; 117 | 118 | glk($002A, gg_statuswin); ! window_clear 119 | 120 | if (statline.trinity) 121 | { 122 | if (location == thedark) { 123 | centerarea = (width/2) - (PrintAnyToArray(bluelalablankage,0, location)/2); 124 | } 125 | else { 126 | FindVisibilityLevels(); 127 | if (visibility_ceiling == location) 128 | centerarea = (width/2) - ((PrintAnyToArray(bluelalablankage,0, 129 | location)) / 2); 130 | else 131 | centerarea = (width/2) - (PrintAnyToArray(bluelalablankage,0, 132 | visibility_ceiling)/2); 133 | } 134 | glk_window_move_cursor( gg_statuswin, centerarea, 0); 135 | if (visibility_ceiling == location) 136 | print (name) location; 137 | else 138 | print (The) visibility_ceiling; 139 | } 140 | else { 141 | 142 | glk($002B, gg_statuswin, 1, 0); ! window_move_cursor 143 | if (location == thedark) { 144 | print (name) location; 145 | } 146 | else { 147 | FindVisibilityLevels(); 148 | if (visibility_ceiling == location) 149 | print (name) location; 150 | else 151 | print (The) visibility_ceiling; 152 | } 153 | 154 | if (width > 66) { 155 | glk($002B, gg_statuswin, posa-1, 0); ! window_move_cursor 156 | print (string) SCORE__TX, sline1; 157 | glk($002B, gg_statuswin, posb-1, 0); ! window_move_cursor 158 | print (string) MOVES__TX, sline2; 159 | } 160 | if (width > 53 && width <= 66) { 161 | glk($002B, gg_statuswin, posb-1, 0); ! window_move_cursor 162 | print sline1, "/", sline2; 163 | } 164 | } 165 | glk($002F, gg_mainwin); ! set_window 166 | ]; 167 | #endif; ! TARGET_GLULX 168 | 169 | 170 | -------------------------------------------------------------------------------- /include/whowhat.h: -------------------------------------------------------------------------------- 1 | ! 2 | ! WhoWhat.H - Modified from WhatIs.H by A.C. Murie, by David A. Cornelson 3 | ! 4 | ! Note: I felt I abused it enough so that I would call it another name and add different 5 | ! instructions. WhatIs.H ambiguously answered who and what questions and I wanted 6 | ! them to be answered appropriately. So, I 'fixed' it. 7 | ! 8 | ! USAGE 9 | ! 10 | ! Include this file after "parser.h". 11 | ! 12 | ! Add the attribute 'queryable' to your object to allow for WHO am/is/are or WHAT is/am/are 13 | ! queries. 14 | ! 15 | ! Add the whatisit property with a string or function to describe what the object is. 16 | ! 17 | ! Add whoisit property to describe who the object is. 18 | ! 19 | ! Additionally, objects that do not appear in the game may be stored in the object 20 | ! 'QueryObjs'. They will be in scope all the time, and may be used for general game 21 | ! concepts 22 | ! 23 | ! As a final option, the actions WhoIs and WhatIs may be used in an objects 'before' code 24 | ! to print the whoisit or whatisit text. 25 | ! 26 | ! COMMENTS... 27 | ! 28 | ! If you intend to allow the player to change to different player objects using ChangePlayer, 29 | ! then make sure you write functions to determine which response is appropriate for whatisit 30 | ! and whoisit. 31 | ! 32 | ! The WhoIs routine check's if the object is animate before answering. 33 | ! 34 | ! I put smartass comments in for defaults. 35 | ! 36 | 37 | Attribute queryable; 38 | property whoisit; 39 | property whatisit; 40 | 41 | [ IsAmAre w; w=NextWord(); if (w=='is' or 'am' or 'are') return 0; return -1; ]; 42 | [ WhatIsWhatSub; "What is what?"; ]; 43 | [ QueryTopic; while( NextWordStopped() ~= -1 ) ; return 1; ]; 44 | [ WhatisQSub; "Good question."; ]; 45 | 46 | [ WhoAmISub; 47 | if( ZRegion(player.whoisit) == 2 or 3 ) 48 | { 49 | PrintOrRun(player,whoisit); 50 | rtrue; 51 | } 52 | "A serious question, to which you have no answer."; 53 | ]; 54 | 55 | [ WhatAmISub; 56 | if( ZRegion(player.whatisit) == 2 or 3 ) 57 | { 58 | PrintOrRun(player,whatisit); 59 | rtrue; 60 | } 61 | "You're probably human, but one can never tell these days."; 62 | ]; 63 | 64 | [ WhatIsSub; 65 | if( noun hasnt queryable ) "Good question."; 66 | if( ZRegion(noun.whatisit) == 2 or 3 ) 67 | { 68 | PrintOrRun(noun,whatisit); 69 | rtrue; 70 | } 71 | "You're not sure."; 72 | ]; 73 | 74 | [ WhoIsSub; 75 | if( noun hasnt animate) "That's not a 'who', it's a 'what'!"; 76 | if( noun hasnt queryable ) "Good question."; 77 | if( ZRegion(noun.whoisit) == 2 or 3 ) 78 | { 79 | PrintOrRun(noun,whoisit); 80 | rtrue; 81 | } 82 | "You're not sure."; 83 | ]; 84 | 85 | [ QueryScope; 86 | if( scope_stage == 1 ) rfalse; 87 | if( scope_stage == 2 ) 88 | { 89 | ScopeWithin( QueryObjs ); 90 | rfalse; 91 | } 92 | ]; 93 | 94 | Object QueryObjs "Queryable objects"; 95 | 96 | verb meta "who" 97 | * IsAmAre -> WhatIsWhat 98 | * IsAmAre "I" -> WhoAmI 99 | * IsAmAre "I?" -> WhoAmI 100 | * IsAmAre "I" "?" -> WhoAmI 101 | * IsAmAre scope=QueryScope -> WhoIs 102 | * IsAmAre scope=QueryScope "?" -> WhoIs 103 | * QueryTopic -> WhatisQ; 104 | 105 | verb meta "what" 106 | * IsAmAre -> WhatIsWhat 107 | * IsAmAre "I" -> WhatAmI 108 | * IsAmAre "I?" -> WhatAmI 109 | * IsAmAre "I" "?" -> WhatAmI 110 | * IsAmAre scope=QueryScope -> WhatIs 111 | * IsAmAre scope=QueryScope "?" -> WhatIs 112 | * QueryTopic -> WhatisQ; 113 | -------------------------------------------------------------------------------- /include/yesno.h: -------------------------------------------------------------------------------- 1 | !--------------------------------------------------------------------------- 2 | ! YesNo An Inform 6 library to ask a semi-rhetorical 3 | ! Yes or no question, by L. Ross Raszewski 4 | ! (rraszews@skipjack.bluecrab.org) 5 | ! 6 | ! Several infocom games have asked the player yes or no questions which are 7 | ! partially rhetorical (Take Hitchhiker's for example) While Inform's library 8 | ! provides for askinga question and demanding an answer, it makes no such 9 | ! allowance for non-manditory yes or no questions. This does exactly that. 10 | ! send the message YesNo.Ask(ifyes,ifno,ifneither);, where IfYes and IfNo 11 | ! are routines to run or messages to print if the player answers yes or no. 12 | ! Ifneither is the string or routine that is printed if the player says 13 | ! neither yes nor no in the next move. 14 | ! 15 | ! This is my first fully object-oriented library extension, but it seems to 16 | ! work anyway. 17 | ! 18 | ! You can omit any of the three arguments (actually, you have to put a zero in 19 | ! to hold the place if you want to assign an action to ifno, but not ifyes. 20 | ! 21 | ! The answer is only accepted druing the next turn after the question is asked, 22 | ! and uses a timer, so if you're pushing the limit, sorry. 23 | ! 24 | ! If you like it, or if you don't, e-mail me and say so! 25 | 26 | Object YesNo 27 | with react_before [; Yes: if (self has on) return self.ifAff(); 28 | No: if (self has on) return self.ifNeg(); 29 | default: self.ifNeither(); 30 | ], 31 | ifAff 0, 32 | ifNeg 0, 33 | ifNeither 0, 34 | Ask [ ifyes ifno ifnone; 35 | self.ifAff=ifyes; 36 | self.ifNeg=ifno; 37 | self.ifNeither=ifnone; 38 | StartTimer(self,1); 39 | give self on; 40 | ], 41 | time_left 1, 42 | time_out [; self.ifAff=0; self.ifNeg=0; 43 | self.ifNeither=0; 44 | give self ~on;], 45 | found_in [; rtrue;], 46 | has concealed; 47 | -------------------------------------------------------------------------------- /include/zclock.h: -------------------------------------------------------------------------------- 1 | ! zclock.h 2 | ! A nearly exact port of the daemons used in Infocom games. 3 | ! Ported by Allen Garvin, December 6, 2003 4 | ! Use freely! 5 | 6 | ! Some useful constants. Their names come from the ZIL source for minizork 7 | Constant C_ENABLED 0; 8 | Constant C_TICK 1; 9 | Constant C_RTN 2; 10 | Constant C_INTLEN 6; 11 | 12 | ! Modify this to increase the number of possible daemons. 13 | ! It must be a multiple of C_INTLEN (by default, there can be 30 daemons) 14 | Constant C_TABLELEN 180; 15 | 16 | Array C_table --> C_TABLELEN; 17 | Global C_ints = C_TABLELEN; 18 | 19 | ! Queue is the programmer's interface to the daemons. It takes 2 arguments. 20 | ! rtn: The routine to be queued as a timer or daemon 21 | ! ticks: If positive, the timer countdown length. After 'ticks' turns 22 | ! rtn will be called. 23 | ! If negative, then behave like an Inform daemon. 'rtn' will be 24 | ! called every turn. 25 | ! If zero, the daemon or timer will be disabled. 26 | ! A queued event must be explicitly enabled. The return value of the 27 | ! function is the interrupt array for the event. If the first byte is 28 | ! set to 1, it will be enabled. If 0, it will be disabled. 29 | ! Thus: 30 | ! Queue(Foo, 5)-->C_ENABLED = true; Call 'Foo' in 5 turns 31 | ! Queue(Bar, -1)-->C_ENABLED = true; Call 'Bar' every turn 32 | ! Queue(Biff, 20); Place 'Biff' in the queue, but do not start 33 | ! the timer yet. The timer will not decrement. 34 | ! No real purpose I can see, but Infocom did 35 | ! this frequently in their Main routines 36 | ! Queue(Foo); or Queue(Foo, 0); Stop the 'Foo' timer 37 | [ Queue rtn ticks cint ; 38 | cint = QueueInterrupt(rtn); 39 | cint-->C_TICK = ticks; 40 | StartDaemon(zork_daemon); 41 | return cint; 42 | ]; 43 | 44 | ! QueueInterrupt was rarely called directly in Infocom games 45 | [ QueueInterrupt rtn end c int ; 46 | end = C_table + C_TABLELEN; 47 | c = C_table + C_ints; 48 | while( true ) { 49 | if( c ~= end ) { 50 | if( (c-->C_RTN) == rtn ) 51 | return c; 52 | c = c + C_INTLEN; 53 | } else { 54 | C_ints = C_ints - C_INTLEN; 55 | int = C_table + C_ints; 56 | int-->C_RTN = rtn; 57 | return int; 58 | } 59 | } 60 | ]; 61 | 62 | ! I decided to implement the queue by using an object with an Inform daemon. 63 | Object zork_daemon "Daemon" 64 | with name 'zdaemon', 65 | daemon [ c end tick flag; 66 | c = C_table + C_ints; 67 | end = C_table + C_TABLELEN; 68 | 69 | while( true ) { 70 | if( c == end ) { 71 | return flag; 72 | } 73 | if( c-->C_ENABLED ) { 74 | tick = c-->C_TICK; 75 | if( tick ~= 0 ) { 76 | c-->C_TICK = (tick - 1); 77 | if( tick <= 1 && (c-->C_RTN)() ) 78 | flag = 1; 79 | } 80 | } 81 | c = c + C_INTLEN; 82 | } 83 | ]; 84 | 85 | ! Notes: 86 | ! Once a routine is queued, there is no method to remove it from the 87 | ! queue. Thus, there is an absolute number of queues in a game. But 88 | ! Requeueing a routine will use the same slot, instead of using a new one. 89 | ! If you queue a routine with a negative value, there is a bug. When 32767 90 | ! turns have passed, the number will overflow to positive, and the queue 91 | ! will then be a countdown instead of a daemon event. Though easy to fix 92 | ! I decided to leave it bug-compatible with Infocom games. In Zork I, for 93 | ! instance, after 2^15 turns the thief will quit moving around the maze. 94 | ! And neither the thief nor troll will defend themselves when attacked. 95 | -------------------------------------------------------------------------------- /inform.1: -------------------------------------------------------------------------------- 1 | .TH INFORM "1" "2015-12-20" "Inform v6.33" "Inform v6.33 - interactive fiction story file compiler" 2 | .SH NAME 3 | inform \- compile Inform interactive fiction story files to Z-machine or Glulx bytecode 4 | .SH SYNOPSIS 5 | .BI "inform " "[options...] infile [outfile]" 6 | .SH DESCRIPTION 7 | \fBinform\fP compiles an Inform version 6 story file (usually with the 8 | extension \fB.inf\fP) into Z-machine or Glulx bytecode which can then be 9 | executed by a variety of Z-machine or Glulx emulators. If the output 10 | filename is not explicitly given on the command line, it will be 11 | constructed from the input filename. 12 | .PP 13 | \fBinform\fP's mode of operation can be controlled with switches (one- or 14 | two-character expressions preceded by a dash), path modifiers (starting with a 15 | plus sign) and memory strategy modifiers (starting with a dollar sign). 16 | .SS SWITCHES 17 | .TP 18 | .B -a 19 | trace assembly-language (without hex dumps; see \fB-t\fP) 20 | .TP 21 | .B -c 22 | more concise error messages 23 | .TP 24 | .B -d 25 | contract double spaces after full stops in text 26 | .TP 27 | .B -d2 28 | contract double spaces after exclamation and question marks, too 29 | .TP 30 | .B -e 31 | economy mode (slower): make use of declared abbreviations 32 | .TP 33 | .B -f 34 | frequencies mode: show how useful abbreviations are 35 | .TP 36 | .B -g 37 | traces calls to functions (except in the library) 38 | .TP 39 | .B -g2 40 | traces calls to all functions 41 | .TP 42 | .B -h, -h1, -h2 43 | print usage information 44 | .TP 45 | .B -i 46 | ignore default switches set within the file 47 | .TP 48 | .B -j 49 | list objects as constructed 50 | .TP 51 | .B -k 52 | output Infix debugging information to "gameinfo.dbg" (and switch \fB-D\fP on) 53 | .TP 54 | .B -l 55 | list every statement run through Inform 56 | .TP 57 | .B -m 58 | say how much memory has been allocated 59 | .TP 60 | .B -n 61 | print numbers of properties, attributes and actions 62 | .TP 63 | .B -o 64 | print offset addresses 65 | .TP 66 | .B -p 67 | give percentage breakdown of story file 68 | .TP 69 | .B -q 70 | keep quiet about obsolete usages 71 | .TP 72 | .B -r 73 | record all the text to "gametext.txt" 74 | .TP 75 | .B -s 76 | give statistics 77 | .TP 78 | .B -t 79 | trace assembly-language (with full hex dumps; see \fB-a\fP) 80 | .TP 81 | .B -u 82 | work out most useful abbreviations (very very slowly) 83 | .TP 84 | .B -v\fIn\fP 85 | compile to a specific Z-code version; the default is 5. Available versions are: 86 | .RS 87 | .TP 88 | .B 3 89 | version-3 ("Standard") story file 90 | .TP 91 | .B 4 92 | version-4 ("Plus") story file 93 | .TP 94 | .B 5 95 | version-5 ("Advanced") story file 96 | .TP 97 | .B 6 98 | version-6 (graphical) story file 99 | .TP 100 | .B 8 101 | version-8 (expanded "Advanced") story file 102 | .RE 103 | .TP 104 | .B -w 105 | disable warning messages 106 | .TP 107 | .B -x 108 | print # for every 100 lines compiled 109 | .TP 110 | .B -y 111 | trace linking system 112 | .TP 113 | .B -z 114 | print memory map of the Z-machine 115 | .TP 116 | .B -B 117 | use big memory model (for large version-6/version-7 files) 118 | .TP 119 | .B -C\fIn\fP 120 | select text character set (defaults to 1): 121 | .RS 122 | .TP 123 | .B 0 124 | plain ASCII only 125 | .TP 126 | .B 1 127 | ISO 8859-1 (Latin1) 128 | .TP 129 | .B 2 130 | ISO 8859-2 (Latin2) 131 | .TP 132 | .B 3 133 | ISO 8859-3 (Latin3) 134 | .TP 135 | .B 4 136 | ISO 8859-4 (Latin4) 137 | .TP 138 | .B 5 139 | ISO 8859-5 (Cyrillic) 140 | .TP 141 | .B 6 142 | ISO 8859-6 (Arabic) 143 | .TP 144 | .B 7 145 | ISO 8859-7 (Greek) 146 | .TP 147 | .B 8 148 | ISO 8859-8 (Hebrew) 149 | .TP 150 | .B 9 151 | ISO 8859-9 (Latin5) 152 | .RE 153 | .TP 154 | .B -D 155 | insert "Constant DEBUG;" automatically 156 | .TP 157 | .B -E\fIn\fP 158 | select error message style (default is Archimedes): 159 | .RS 160 | .TP 161 | .B 0 162 | Archimedes-style error messages 163 | .TP 164 | .B 1 165 | Microsoft-style error messages 166 | .TP 167 | .B 2 168 | Macintosh MPW-style error messages 169 | .RE 170 | .TP 171 | .B -F1 172 | use temporary files to reduce memory consumption 173 | .TP 174 | .B -G 175 | compile a Glulx game file 176 | .TP 177 | .B -H 178 | use Huffman encoding to compress Glulx strings 179 | .TP 180 | .B -M 181 | compile as a Module for future linking 182 | .TP 183 | .B -S 184 | compile strict error-checking at run-time (on by default) 185 | .TP 186 | .B -U 187 | insert "Constant USE_MODULES;" automatically 188 | .TP 189 | .B -W\fIn\fP 190 | header extension table is at least n words (n = 3 to 99) 191 | .TP 192 | .B -X 193 | compile with INFIX debugging facilities present 194 | .SS PATH MODIFIERS 195 | .TP 196 | .BI + dir 197 | set \fBInclude_Path\fP to this directory 198 | .TP 199 | .BI +PATH= dir 200 | change \fBPATH\fP to this directory 201 | .SS MEMORY STRATEGY MODIFIERS 202 | Note: it may be necessary to quote these parameters to prevent your shell 203 | from expanding them. 204 | .TP 205 | .B $small 206 | adjust memory settings to a small game 207 | .TP 208 | .B $large 209 | adjust memory settings to a large game 210 | .TP 211 | .B $huge 212 | adjust memory settings to a huge game (default) 213 | .TP 214 | .B $list 215 | list current memory allocation settings 216 | .TP 217 | .BI $? parameter 218 | explain memory setting \fIparameter\fP (see \fB$list\fP for available 219 | parameters) 220 | .TP 221 | .BI $ parameter = value 222 | manually set \fIparameter\fP 223 | 224 | .SH CAVEATS 225 | \fBinform\fP is not capable of creating story files conforming to 226 | versions 1 or 2 of the Z-Machine. 227 | .br 228 | Modules cannot be used with Glulx and are deprecated for Z-Machine. 229 | 230 | .SH DOCUMENTATION 231 | The canonical documentation for \fBInform6\fP is the 232 | \fBInform_Designer's Manual\fP. This work can be browsed at 233 | .br 234 | .RI < http://inform-fiction.org/manual/html/contents.html > 235 | downloaded from 236 | .br 237 | .RI < http://inform-fiction.org/manual/DM4.pdf > 238 | and purchased in hardcopy at 239 | .br 240 | .RI < http://amazon.com/ > 241 | 242 | Another noteworthy and somewhat more up-to-date resource is the 243 | \fBInform Beginner's Guide\fP. This work can be downloaded at 244 | .br 245 | .RI < http://inform-fiction.org/manual/download_ibg.html > 246 | 247 | .SH SEE ALSO 248 | .IR zcode-interpreter (6) 249 | and the manuals and language reference which can be found online at 250 | .br 251 | .RI < http://inform-fiction.org/manual/ > 252 | .br 253 | and 254 | .br 255 | .RI < http://inform-fiction.org/inform6.html >. 256 | 257 | .SH AUTHOR 258 | The various iterations of the \fBInform\fP language were created by 259 | Graham Nelson in 1993. 260 | 261 | This manpage was written by Jan Nordholz 262 | for the Debian Project and altered by David Griffith . 263 | 264 | .SH DISTRIBUTION 265 | The compiler and standard library for \fBInform6\fP are licensed under 266 | .IP 1) 267 | The traditional Inform license as described by the DM4, or 268 | .IP 2) 269 | The Artistic License 2.0 . 270 | 271 | .RE 272 | Here is the relevant bit from the Inform Designer's Manual, 4th edition: 273 | 274 | Copyright on Inform, the program and its source code, its example games 275 | and documentation (including this book) is retained by Graham Nelson, 276 | who asserts the moral right to be identified as the author under the 277 | Copyrights, Designs and Patents Act 1988. Having said this, I am happy 278 | for it to be freely distributed to anybody who wants a copy, provided 279 | that: (a) distributed copies are not substantially different from those 280 | archived by the author, (b) this and other copyright messages are always 281 | retained in full, and (c) no profit is involved. (Exceptions to these 282 | rules must be negotiated directly with the author.) However, a story 283 | file produced with the Inform compiler (and libraries) then belongs to 284 | its author, and may be sold for profit if desired, provided that its 285 | game banner contains the information that it was compiled by Inform, and 286 | the Inform version number. 287 | 288 | The Artistic License 2.0 can be found at 289 | .br 290 | https://opensource.org/licenses/Artistic-2.0 291 | .br 292 | and the file \fBARTISTIC\fP in the \fBInform6\fP distribution archive. 293 | -------------------------------------------------------------------------------- /tutor/README: -------------------------------------------------------------------------------- 1 | This directory contains some Inform tutorial files: 2 | 3 | alice.txt Tutorial by Gareth Rees 4 | alice.inf Source code to the tutorial game 5 | 6 | houseXX.inf Tutorial files by David Cornelson 7 | 8 | aloneice.inf Another tutorial game by Ethan Dicks 9 | -------------------------------------------------------------------------------- /tutor/aloneice.inf: -------------------------------------------------------------------------------- 1 | ! ----------------------------------------------------------------------------- 2 | Constant Story "Alone on The Ice"; 3 | 4 | Constant Headline 5 | "^Inform for New Writers^ 6 | ~Alone on The Ice~ - a sample game/tutorial 7 | by Ethan Dicks - Last Compiled: 23-Feb-1998^"; 8 | 9 | Release 1; 10 | Serial "980223"; 11 | 12 | ! The game is meant to be experimented with, so we always define: 13 | Constant DEBUG; 14 | 15 | ! -------------------------------------------------------------------------- 16 | 17 | ! Put your "replaces" here to re-write parts of the Inform libraries 18 | 19 | Include "Parser"; 20 | 21 | ! -------------------------------------------------------------------------- 22 | ! Out on the open ice, every object that might be dropped out there needs to 23 | ! have a property to store its "coordinate". Forgetting this could cause 24 | ! serious bugs. 25 | Property ICELOC 0; ! coordinate of Object in ice field. 26 | 27 | ! -------------------------------------------------------------------------- 28 | 29 | Include "VerbLib"; 30 | 31 | ! -------------------------------------------------------------------------- 32 | ! 33 | ! It all starts here --+ 34 | ! | 35 | ! v 36 | [ Initialise; 37 | location = HUT1; 38 | 39 | thedark.description = "There is nothing here but whiteness. If you move 40 | from this spot, you are likely to be hopelessly lost"; 41 | 42 | "You awake from a dreamless sleep to silence. You look around the room 43 | for Tom, your campmate; he isn't here. Of all the places to go for a 44 | walk by yourself, the middle of the Antarctic plateau isn't one of them. 45 | Despite your training to stay put and wait for him to come back, you 46 | decide to go after him. It's just the two of you here, and no planes 47 | due for weeks."; 48 | ]; 49 | 50 | ! -------------------------------------------------------------------------- 51 | ! 52 | ! Things - the elements of our interactive world 53 | ! 54 | ! -------------------------------------------------------------------------- 55 | 56 | Object HUT1 "A small scientific observation hut" 57 | with description "This cramped insulated box has been your home for 58 | several months now. There is little in here but 59 | some equipment for monitoring the weather and two 60 | cots.", 61 | n_to DOOR1, 62 | has light; 63 | 64 | !---- 65 | Object -> DOOR1 "freezer door" ! An ordinary two-sided door (as implemented 66 | ! in the Inform Designer's Manual, chpt. 12). 67 | with description "There is a door in the wall of the hut, nearly as wide 68 | as the wall. It is large, white and heavy. It does 69 | not appear to have a doornob, as such, but more of a 70 | plunger like you'd find on the inside of a meat locker.", 71 | name "white" "freezer" "door", 72 | when_closed [; rfalse; ], 73 | when_open "The door has been carelessly left open and the cold, 74 | antarctic wind is blowing into the hut, unabated.", 75 | door_to [; if (location==CAMP14) return HUT1; return CAMP14; ], 76 | door_dir [; if (location==CAMP14) return n_to; return s_to; ], 77 | found_in HUT1 CAMP14, 78 | has static door openable; 79 | 80 | !---- 81 | Object -> NOTE "goodbye note" 82 | with initial "There is a piece of paper taped to the door here.", 83 | inven "A note from your campmate.", 84 | name "note" "paper" "piece", 85 | ICELOC 0, 86 | before [; Examine: "The paper appears torn hastily from a notebook, the 87 | writing nearly illegible. It reads:^^Went to get 88 | some smokes. Be back soon.^^^^ --Tom"; 89 | ], 90 | 91 | has ~static; ! make sure it's portable 92 | 93 | !---- 94 | Object -> BOOK "survival guide" 95 | with name "book" "survival" "guide", 96 | initial "A survival guide lies discarded in the corner.", 97 | ICELOC 0, 98 | before [; Examine: "It's a standard issue guide to survival in Antarctica. 99 | You got it on your first day here. On the back cover 100 | is a list of important safety tips: 101 | ^ Black flags mark hazards - do not approach. 102 | ^ Orange flags mean safe travel. 103 | ^ Stick to the flagged routes. 104 | ^ Travel in pairs (I guess Tom forgot that one). 105 | ^ In a white-out, sit down and wait it out.^"; 106 | ], 107 | has ~static; ! make sure it's portable 108 | 109 | !---- 110 | Object CAMP14 "Weather Observation Post 14" 111 | with description "Behind the sign that reads, ~The United States Welcomes 112 | you to Observation Post 14,~ lies your camp: an orange 113 | eight-foot by eight-foot box that you call home. There 114 | is a line of orange trail-marker flags heading off in 115 | the distance to the north. The rest is whiteness", 116 | s_to DOOR1, 117 | n_to 118 | [; 119 | ! Drop the player at the starting poing 120 | PlayerTo(ICE,1); ! Put the player in the "ice room" Object 121 | IGOTO(52); ! Set the starting location (middle of the south edge) 122 | rtrue; ! Tell the parser that it worked. 123 | ], 124 | has light; 125 | 126 | !---- 127 | Object CAMP9 "Weather Observation Post 9" 128 | with description "This is another field camp, the sign here tells you, 129 | ~The United States Welcomes you to Observation Post 9~. 130 | The flagged route goes south from here.", 131 | n_to DOOR2, 132 | s_to 133 | [; 134 | ! Drop the player at the starting poing 135 | PlayerTo(ICE,1); ! Put the player in the "ice room" Object 136 | IGOTO(12); ! Set the starting location (middle of the north edge) 137 | rtrue; ! Tell the parser that it worked. 138 | ], 139 | has light; 140 | 141 | !---- 142 | Object HUT2 "A small scientific observation hut" 143 | with description "This looks like a duplicate of your own observation hut, 144 | down to the scuff marks on the floor.", 145 | 146 | s_to ICE2, 147 | n_to DOOR2, 148 | has light; 149 | 150 | !---- 151 | Object -> DOOR2 "freezer door" ! An ordinary two-sided door (as implemented 152 | ! in the Inform Designer's Manual, chpt. 12). 153 | with description "There is a familiar looking door in the wall of the hut, 154 | with a familiar looking opening plunger.", 155 | name "white" "freezer" "door", 156 | when_closed [; rfalse; ], 157 | when_open "The door has been carelessly left open and the cold, 158 | antarctic wind is blowing into the hut, unabated.", 159 | door_to [; if (location==CAMP9) return HUT2; return CAMP9; ], 160 | door_dir [; if (location==CAMP9) return n_to; return s_to; ], 161 | found_in HUT2 CAMP9, 162 | has static door openable; 163 | 164 | !---- 165 | Object -> TOM "your campmate, Tom" 166 | with name "Tom", 167 | description "Tom, the only other person for a hundred miles, is here, 168 | smoking the foulest smelling cigarettes you have ever 169 | smelled - Penguin Slims", 170 | has proper animate; 171 | 172 | ! In order to create the illusion of an enormous expanse of rooms without 173 | ! having to create one object per location, we simulate a large area with 174 | ! two real rooms and an array. One room (ICE) contains the Player object 175 | ! at all times. The other (ICE2), is a temporary holding area for the 176 | ! objects that are located in various places throughout the virtual space. 177 | ! We use the "ICELOC" property to remember where in the greater area an 178 | ! object was the last time the Player saw it. 179 | ! 180 | Object ICE "Out on the open ice" 181 | with name "ICE", 182 | description 183 | [; IWHERE(); ], 184 | 185 | before 186 | [; Go: 187 | ! Check to see if we are at an exit space, otherwise, just move 188 | ! around the virtual area. 189 | return IEXIT(); 190 | ], 191 | 192 | ! Since we don't move from object to object, all roads lead back here. The 193 | ! only way out is through specially marked spaces. 194 | n_to ICE, s_to ICE, e_to ICE, w_to ICE, 195 | ne_to ICE, nw_to ICE, se_to ICE, u_to ICE, sw_to ICE, 196 | d_to ICE, 197 | 198 | has light static container; 199 | 200 | ! We need a place to stash things that get left out on the ice 201 | Object ICE2 "Ice Box" with name "ICE2", description "Ice Box", has light; 202 | 203 | ! ---------------------------------------- 204 | ! Let's leave a trail for Player to follow 205 | ! 206 | Class Flag 207 | with description "trail flag", 208 | name "marker" "flag" "bamboo" "pole", 209 | initial 210 | [; 211 | "There is ", (a) self, " trail-marker flag here, fluttering 212 | at the end of a bamboo pole"; 213 | ], 214 | After 215 | [; Take: print "You pull the flag from the snow"; ], 216 | 217 | has ~static; ! Let's let the player pick up and move the flags around. 218 | 219 | ! Now, create several instances of the flags and stick them in the holding room 220 | Class Orange_Flag class Flag with name "orange", article "an"; 221 | Class Black_Flag class Flag with name "black", article "a"; 222 | 223 | Orange_Flag O1 "orange flag" ICE2 with plural "orange flags", ICELOC 12; 224 | Orange_Flag O2 "orange flag" ICE2 with plural "orange flags", ICELOC 20; 225 | Orange_Flag O3 "orange flag" ICE2 with plural "orange flags", ICELOC 28; 226 | Orange_Flag O4 "orange flag" ICE2 with plural "orange flags", ICELOC 36; 227 | Orange_Flag O5 "orange flag" ICE2 with plural "orange flags", ICELOC 44; 228 | Orange_Flag O6 "orange flag" ICE2 with plural "orange flags", ICELOC 52; 229 | 230 | Black_Flag BL1 "black flag" ICE2 with plural "black flags", ICELOC 53; 231 | Black_Flag BL2 "black flag" ICE2 with plural "black flags", ICELOC 45; 232 | Black_Flag BL3 "black flag" ICE2 with plural "black flags", ICELOC 37; 233 | Black_Flag BL4 "black flag" ICE2 with plural "black flags", ICELOC 29; 234 | ! ---------------------------------------- 235 | 236 | Global IPLAYER=52; ! Current location of Player on the ice 237 | 238 | !---------- 239 | ! Virtual room array 240 | ! This array is a grid representation of the ice field. Different numbers 241 | ! represent the kind of terrain found in a particular "location". To make 242 | ! life easier for the programmer, positive numbers are inaccessible, zero 243 | ! is flat and level, and negative numbers are used for features such as exits 244 | ! and moveable ice blocks (not implemented in this tutorial). 245 | ! 246 | ! It's best to list this out in table form: 247 | ! 1 is impassable barrier (crevasse) 248 | ! -1 is movable block of ice (Not Implemented Yet) 249 | ! -2 is the passage to the north exit 250 | ! -3 is the passage to the south exit 251 | 252 | Array IVEC --> 0 1 1 1 (-2) 1 1 1 1 253 | 1 0 0 0 0 0 0 1 254 | 1 0 0 0 0 0 0 1 255 | 1 0 0 0 0 1 0 1 256 | 1 0 0 0 0 1 0 1 257 | 1 0 0 0 0 1 0 1 258 | 1 0 0 0 0 1 0 1 259 | 1 1 1 (-3) 1 1 1; 260 | 261 | ! Note the north-south crevasse to the east of the expected path of the Player. 262 | 263 | ! ---------------------------------------- 264 | ! Walking around on the ice field 265 | 266 | ! NB: n_obj is 7. The array has dummy entries to match the array element 267 | ! number with the direction object number. The elements/directions 268 | ! follow the order N, S, E, W, NE, NW, SE, SW. If this changes, this 269 | ! array and it's supporting code must be redesigned. This may not 270 | ! be the best way to do this, but it does work. 271 | ! 272 | ! These numbers are based on an 8x8 grid. A grid of a different size would 273 | ! generate different numbers (i.e., a 4x4 grid would see -4 for -8, -3 for 274 | ! -7, -5 for -9, etc.) 275 | Array IEXITS --> 0 0 0 0 0 0 0 (-8) 8 1 (-1) (-7) (-9) 9 7; 276 | 277 | ! 278 | ! IEXIT - let the player exit the ice field 279 | ! 280 | [ IEXIT; 281 | ! Check to see if the player is in the right place and moving in the right 282 | ! direction (up). 283 | if (IPLAYER==12 or 52) { 284 | ! Is there a way up here? (N.B.: for this example, there always is). 285 | if ((IVEC-->(IPLAYER + IEXITS-->noun)) == -2) { 286 | print "You scramble up the trail and onto the plateau.^"; 287 | give ICE ~visited; 288 | Playerto(CAMP9,2); 289 | rtrue; 290 | } 291 | else if ((IVEC-->(IPLAYER + IEXITS-->noun)) == -3) { 292 | print "You scramble up the trail and back to camp.^"; 293 | give ICE ~visited; 294 | Playerto(CAMP14,2); 295 | rtrue; 296 | } 297 | } 298 | 299 | if (noun==u_obj) { 300 | print "There is nothing but flat, featureless ice here. Nothing to 301 | climb"; 302 | return 3; 303 | } 304 | 305 | ! Don't let them go down, ever. 306 | if (noun==d_obj) { 307 | print "That's not a good idea."; 308 | return 3; 309 | } 310 | 311 | ! If the intended space is empty, let the player move there 312 | if (IVEC-->(IPLAYER + IEXITS-->noun)==0) { 313 | return IGOTO(IPLAYER + IEXITS-->noun); 314 | } 315 | 316 | ! There must be a barrier. Stop them from moving. 317 | print "In the nick of time, you step back from the edge of a yawning 318 | crevasse."; 319 | return 3; 320 | ]; 321 | 322 | 323 | !------ 324 | ! "Move" to new ice room 325 | 326 | [ IGOTO FX x y; 327 | 328 | ! Forget we were ever here. This keeps the descriptions fresh. 329 | give ICE ~visited; 330 | 331 | ! Move stuff out of the old location into the storage space 332 | x = child(ICE); 333 | while (x) { 334 | y=sibling(x); 335 | if ( (x hasnt concealed) && (x ~= Player) ) { 336 | x.ICELOC=IPLAYER; ! Remember where it came from 337 | move x to ICE2; ! Stash it 338 | } 339 | x = y; 340 | } 341 | 342 | ! "move" player to the new location 343 | IPLAYER=FX; 344 | 345 | ! Pull stuff from the storage space to the new location, if it belongs here 346 | x = child(ICE2); 347 | while (x) { 348 | y=sibling(x); 349 | ! see if this Object belongs in our new location 350 | if (x.ICELOC == IPLAYER) { 351 | x.ICELOC=0; ! Forget where it used to be 352 | move x to ICE; ! Put it back in here 353 | } 354 | x = y; 355 | } 356 | 357 | ; 358 | give ICE ~visited; 359 | return 3; 360 | ]; 361 | 362 | ! ---------------------------------------- 363 | ! 364 | ! Describe location out on the open ice. 365 | ! 366 | [ IWHERE N W S E num_crevasse crevasse_dir; 367 | N = IVEC-->(IPLAYER - 8); 368 | S = IVEC-->(IPLAYER + 8); 369 | E = IVEC-->(IPLAYER + 1); 370 | W = IVEC-->(IPLAYER - 1); 371 | 372 | ! print "This is Ice Room #", IPLAYER, ".^"; 373 | 374 | ! See if Player is somewhere safe or not 375 | if ( ON_FLAGGED_ROUTE(IPLAYER) ) 376 | print "You are on the flagged route. "; 377 | else 378 | print "You are out on the open ice, a dangerous thing. "; 379 | 380 | ! Count the crevasses and remember which direction they are in 381 | if (N == 1) { num_crevasse++; crevasse_dir = crevasse_dir + 1; } 382 | if (S == 1) { num_crevasse++; crevasse_dir = crevasse_dir + 2; } 383 | if (E == 1) { num_crevasse++; crevasse_dir = crevasse_dir + 4; } 384 | if (W == 1) { num_crevasse++; crevasse_dir = crevasse_dir + 8; } 385 | 386 | ! If there are any crevasses, warn Player 387 | if (num_crevasse) { 388 | print "There "; 389 | if (num_crevasse == 1) ! How many? 390 | print "is a crevasse to the "; 391 | else 392 | print "are crevasses to the "; 393 | 394 | if (N == 1) { 395 | print "north"; 396 | num_crevasse--; 397 | if (num_crevasse == 1) 398 | print " and "; 399 | else if (num_crevasse > 1) 400 | print ", "; 401 | } 402 | 403 | if (S == 1) { 404 | print "south"; 405 | num_crevasse--; 406 | if (num_crevasse == 1) 407 | print " and "; 408 | else if (num_crevasse > 1) 409 | print ", "; 410 | } 411 | 412 | if (E == 1) { 413 | print "east"; 414 | num_crevasse--; 415 | if (num_crevasse == 1) 416 | print " and "; 417 | else if (num_crevasse > 1) 418 | print ", "; 419 | } 420 | 421 | if (W == 1) 422 | print "west"; 423 | 424 | print "."; 425 | } 426 | 427 | print "^"; 428 | 429 | ! Let's thrown in a colorful phrase, just for fun... 430 | if (IPLAYER==36) 431 | print "(If Nowhere has a Middle, this is it.)^"; 432 | 433 | ! Describe the exits, if present 434 | if (N==-2) 435 | print "There is a plateau to the north here. There appears to be a way to 436 | scramble up to it that avoids the crevasse."; 437 | 438 | if (S==-3) 439 | print "You can see your camp up and to the south.^"; 440 | 441 | ]; 442 | 443 | ! 444 | ! Check to see if Player is on the route 445 | ! 446 | ! To-do: Check for an undisturbed flag along the route 447 | ! 448 | [ ON_FLAGGED_ROUTE location; 449 | if (location == 12 or 20 or 28 or 36 or 44 or 52) 450 | rtrue; 451 | 452 | rfalse; 453 | ]; 454 | 455 | !---- 456 | ! Define verbs here... 457 | 458 | Include "Grammar"; 459 | -------------------------------------------------------------------------------- /tutor/house01.inf: -------------------------------------------------------------------------------- 1 | ! ------------------------------------------------------------------------------ 2 | ! Inform for New Writers 3 | ! 4 | ! The House - Version 1 5 | ! 6 | ! Last Modified: David Cornelson - 03-Jan-1998 7 | ! 8 | ! This work is freely offered to the Public Domain. - DAC 12-12-2015 9 | ! 10 | ! ------------------------------------------------------------------------------ 11 | 12 | ! 13 | ! Q: What are these lines that begin with exclamation points? 14 | ! 15 | ! A: In an Inform program, you may want to place comments or notes before 16 | ! portions of code so that when you make changes, you will remember what 17 | ! you were thinking when you originally wrote the code. It's a great way 18 | ! to "document" your program so that others can understand it as well. 19 | ! 20 | ! Any characters following an exclamation point is considered a comment. 21 | ! The comment ends when you move to a new line. 22 | ! 23 | 24 | ! 25 | ! The constant "Story" contains the name of your story, in this case, 26 | ! "The House". The word "Constant" is an Inform statement that signifies that 27 | ! a token (variable) will have a single, unchangable value within the program. 28 | ! "Story" is the token name and "The House" is the value. Anytime you reference 29 | ! "Story" in your program, it will have the value "The House". 30 | ! 31 | ! The double-quote is used to represent a "string". A string is a type of data that 32 | ! contains letters and words. (As opposed to numbers). A string must begin with 33 | ! a double-quote and end with a double-quote. 34 | ! 35 | ! The semi-colon tells Inform that this statement is complete. You need a 36 | ! semi-colon to end all Inform statements. 37 | ! 38 | Constant Story "The House"; 39 | 40 | ! 41 | ! The constant "Headline" contains the initial banner at the beginning of your 42 | ! game. In this Headline, there are three separate lines. 43 | ! 44 | ! The first line is "Inform for New Writers" 45 | ! The second line is "The House - Version 1" 46 | ! The third line is "By New Writer (1998) - Last Compiled: 03-Jan-1998" 47 | ! 48 | ! The carat "^" character is used to tell Inform that you want to move to a new 49 | ! line. This is called the newline character. Each time the newline character is 50 | ! placed into a string, the game will move to a new line. 51 | ! 52 | ! Here is another example: 53 | ! 54 | ! print "Once upon a time^there was a little bear^^that was all alone.^"; 55 | ! 56 | ! This example will be printed on your screen as... 57 | ! 58 | ! Once upon a time 59 | ! there was a little bear 60 | ! 61 | ! that was all alone. 62 | ! 63 | ! Each newline character caused a break in the text and started at the beginning 64 | ! of a new line. 65 | ! 66 | Constant Headline 67 | "^Inform for New Writers^ 68 | The House - Version 1^ 69 | By New Writer (1998) - Last Compiled: 03-Jan-1998^"; 70 | 71 | ! 72 | ! This constant tells Inform what the maximum score of your game will be. 73 | ! Currently, we have it set to 100. 74 | ! 75 | Constant MAX_SCORE 100; 76 | 77 | ! 78 | ! This constant is the last compile date and can be set by the Inform compiler. 79 | ! 80 | Serial "980103"; 81 | 82 | ! 83 | ! This constant is set by you and tells which release of your game you are 84 | ! working on. It's a good idea to make backups of your program on a regular 85 | ! basis. When you have completed your game, start incrementing the Release value 86 | ! every time you fix bugs or make changes so that players know which release 87 | ! works and which one doesn't. 88 | ! 89 | Release 1; 90 | 91 | ! 92 | ! The Include statement allows Inform to open other files that are important to 93 | ! your program. The following files, "Parser" and "VerbLib" are the foundation 94 | ! of the Inform parser. DON'T REMOVE THESE LINES!!! 95 | ! 96 | Include "Parser"; 97 | Include "VerbLib"; 98 | 99 | !------------------------------------------------------------------------------- 100 | ! Initialise 101 | ! 102 | ! The following "function" is the first portion of code executed by Inform when 103 | ! your game is played. You want to place a statement in this function that will 104 | ! set the first location of the player. We will add more to this section in later 105 | ! versions of "The House". 106 | !------------------------------------------------------------------------------- 107 | 108 | ! FUNCTIONS: Portions of your code will will be in what are called "functions". 109 | ! The syntax of a function is as follows: 110 | ! 111 | ! [ function_name argument argument; 112 | ! ...your code... 113 | ! ...your code... 114 | ! ...your code... 115 | ! ]; 116 | ! 117 | ! Arguments are values passed when calling the function. More 118 | ! information on functions is available in later versions of 119 | ! "The House". 120 | ! 121 | 122 | [ Initialise; 123 | 124 | ! 125 | ! Our first location is the Sidewalk. Inform has a variable that we can set that 126 | ! just happens to be named "location". 127 | ! 128 | ! Sidewalk is a location, but in Inform it is an "Object". When we define the 129 | ! object Sidewalk it will have a unique value associated with it. So, when we 130 | ! set location equal to Sidewalk, the location variable now contains the object 131 | ! value of Sidewalk. 132 | ! 133 | location = Sidewalk; 134 | 135 | ]; 136 | 137 | ! 138 | ! The following function is called by Inform when the player types SCORE or when 139 | ! the player ends the game. As you can see, each range of points has a different 140 | ! string printed. You can modify this function to suit your own story. Remember, 141 | ! the constant MAX_SCORE contains the value that is used by Inform to represent 142 | ! "You have scored out of ", so you want both the Constant 143 | ! and this function to be synchronized. 144 | ! 145 | [ PrintRank; 146 | print ", earning you the rank of "; 147 | if (score >= 100) "the greatest."; 148 | if (score >= 80) "above average."; 149 | if (score >= 60) "average."; 150 | if (score >= 40) "below average."; 151 | if (score >= 20) "the barely living."; 152 | "the living dead."; 153 | ]; 154 | 155 | ! ---------------------------------------------------------------------------- 156 | ! Locations 157 | ! 158 | ! In this section we will define our locations. These are "Objects" to Inform 159 | ! and contain the following elements. 160 | ! 161 | ! - object name 162 | ! The object name represents the variable or handle of the object. 163 | ! - short description 164 | ! The short description is the description printed in bold before the 165 | ! normal description. 166 | ! - initial description 167 | ! The initial description is printed only once when the location is first 168 | ! entered by the player. 169 | ! - normal description 170 | ! The normal description is printed everytime the player enters the location. 171 | ! - directional properties (tells which direction player can move) (optional) 172 | ! These include n_to, ne_to, e_to, up_to, in_to, etc. and are followed by 173 | ! another location object name. 174 | ! - properties 175 | ! Properties are functions that you can add to an object that help determine 176 | ! events and actions. 177 | ! - attributes 178 | ! Attributes are True/False values that help you remember certain states of 179 | ! an object or event, such as whether the lights are on or not. The positive 180 | ! value is represented as "light" and the negative would be "~light". There 181 | ! are standard attributes used by Inform and you can add your own as well. 182 | ! 183 | ! Actually, there's more than this, but we'll add the complicated stuff later! 184 | ! 185 | ! ---------------------------------------------------------------------------- 186 | 187 | ! 188 | ! Define the object "Sidewalk" 189 | ! 190 | ! Object Name: Sidewalk 191 | ! Short Description: "Sidewalk" 192 | ! Initial Description: none 193 | ! Normal Description: "You are standing on the sidewalk in front of a house." 194 | ! Attributes: light 195 | ! 196 | ! The Sidewalk is the first location of our game and includes a description 197 | ! and when we enter it, it will have light. 198 | ! 199 | Object Sidewalk "Sidewalk" 200 | with description 201 | "You are standing on the sidewalk in front of a house.", 202 | has light; 203 | 204 | ! ---------------------------------------------------------------------------- 205 | ! Grammar 206 | ! 207 | ! The grammar section includes the file "Grammar" and will later include 208 | ! extensions to the standard grammar library. 209 | ! 210 | ! ---------------------------------------------------------------------------- 211 | 212 | Include "Grammar"; 213 | 214 | ! ---------------------------------------------------------------------------- 215 | ! Compilation Results 216 | ! ---------------------------------------------------------------------------- 217 | ! Command: INFRMW32 -J HOUSE01.INF 218 | ! 219 | ! PC/Win32 Inform 6.14 (8th September 1997) 220 | ! 6 "compass" 221 | ! 7 "north wall" 222 | ! 8 "south wall" 223 | ! 9 "east wall" 224 | ! 10 "west wall" 225 | ! 11 "northeast wall" 226 | ! 12 "northwest wall" 227 | ! 13 "southeast wall" 228 | ! 14 "southwest wall" 229 | ! 15 "ceiling" 230 | ! 16 "floor" 231 | ! 17 "outside" 232 | ! 18 "inside" 233 | ! 19 "(darkness object)" 234 | ! 20 "(self object)" 235 | ! 21 "(Inform Parser)" 236 | ! 22 "(Inform Library)" 237 | ! 23 "(with no short name)" 238 | ! 24 "Sidewalk" 239 | -------------------------------------------------------------------------------- /tutor/house02.inf: -------------------------------------------------------------------------------- 1 | ! ------------------------------------------------------------------------------ 2 | ! Inform for New Writers 3 | ! 4 | ! The House - Version 2 5 | ! 6 | ! Last Modified: David Cornelson - 04-Jan-1998 7 | ! 8 | ! This work is freely offered to the Public Domain. - DAC 12-12-2015 9 | ! 10 | ! ------------------------------------------------------------------------------ 11 | 12 | Constant Story "The House"; 13 | 14 | Constant Headline 15 | "^Inform for New Writers^ 16 | The House - Version 2^ 17 | By New Writer (1998) - Last Compiled: 04-Jan-1998^"; 18 | 19 | Constant MAX_SCORE 100; 20 | Serial "980104"; 21 | 22 | Release 1; 23 | 24 | Include "Parser"; 25 | Include "VerbLib"; 26 | 27 | !------------------------------------------------------------------------------- 28 | ! Initialise 29 | ! 30 | !------------------------------------------------------------------------------- 31 | 32 | [ Initialise; 33 | 34 | location = Sidewalk; 35 | 36 | ]; 37 | 38 | [ PrintRank; 39 | print ", earning you the rank of "; 40 | if (score >= 100) "the greatest."; 41 | if (score >= 80) "above average."; 42 | if (score >= 60) "average."; 43 | if (score >= 40) "below average."; 44 | if (score >= 20) "the barely living."; 45 | "the living dead."; 46 | ]; 47 | 48 | ! ---------------------------------------------------------------------------- 49 | ! Locations 50 | ! 51 | ! In this section we will define our locations. These are "Objects" to Inform 52 | ! and contain the following elements. 53 | ! 54 | ! - object name 55 | ! The object name represents the variable or handle of the object. 56 | ! - short description 57 | ! The short description is the description printed in bold before the 58 | ! normal description. 59 | ! - initial description 60 | ! The initial description is printed only once when the location is first 61 | ! entered by the player. 62 | ! - normal description 63 | ! The normal description is printed everytime the player enters the location. 64 | ! - directional properties (tells which direction player can move) (optional) 65 | ! These include n_to, ne_to, e_to, up_to, in_to, etc. and are followed by 66 | ! another location object name. 67 | ! - properties 68 | ! Properties are functions that you can add to an object that help determine 69 | ! events and actions. 70 | ! - attributes 71 | ! Attributes are True/False values that help you remember certain states of 72 | ! an object or event, such as whether the lights are on or not. The positive 73 | ! value is represented as "light" and the negative would be "~light". There 74 | ! are standard attributes used by Inform and you can add your own as well. 75 | ! 76 | ! Actually, there's more than this, but we'll add the complicated stuff later! 77 | ! 78 | ! ---------------------------------------------------------------------------- 79 | 80 | Object Sidewalk "Sidewalk" 81 | with description 82 | "You are standing on the sidewalk in front of a house to the west.", 83 | w_to Front_Porch, 84 | has light; 85 | 86 | ! 87 | ! VERSION 2 - Adding more locations to your Inform program 88 | ! 89 | ! We're going to take one small step in this version. Let's add a bunch of 90 | ! locations so that the player can move around a little bit. 91 | ! 92 | ! Notice that in the Sidewalk Object definition we added a direction in the 93 | ! description "to the west" and we added the directional property "w_to" 94 | ! that leads to the "Front_Porch" location that we defined below. 95 | ! 96 | ! If you follow these examples you will see how locations are "connected" 97 | ! or "mapped" together with the directional properties. Feel free to change 98 | ! then around so that they connect in different ways. 99 | ! 100 | ! Q: In the "Front_Porch" definition, the description continues over two 101 | ! lines. Is this okay? 102 | ! 103 | ! A: Inform allows you to extend statements over multiple lines as you 104 | ! need. You may need to write code that extends over multiple lines 105 | ! but mostly it will be descriptions as in "Front_Porch". You don't 106 | ! need to add any extra characters to tell Inform that you've jumped 107 | ! to the next line either...Inform will figure that out when it compiles. 108 | ! 109 | 110 | Object Front_Porch "Front Porch" 111 | with description 112 | "This is the front porch of the house. There is an open door 113 | leading inside to the west.", 114 | e_to Sidewalk, 115 | w_to Foyer, 116 | in_to Foyer, 117 | has light; 118 | 119 | Object Foyer "Foyer" 120 | with description 121 | "You are standing in the foyer of the house. It seems as though 122 | you can go up a staircase, northwest, or back out the front 123 | door to the east.", 124 | out_to Front_Porch, 125 | e_to Front_Porch, 126 | nw_to Hallway, 127 | u_to Upper_Hallway, 128 | has light; 129 | 130 | Object Hallway "Hallway" 131 | with description 132 | "You are in the hallway on the first floor of the house. The 133 | foyer is southeast and the kitchen is west of here.", 134 | se_to Foyer, 135 | w_to Kitchen, 136 | has light; 137 | 138 | Object Kitchen "Kitchen" 139 | with description 140 | "This is the kitchen of the house. A hallway can be seen to the 141 | east.", 142 | e_to Hallway, 143 | has light; 144 | 145 | Object Upper_Hallway "Upper Hallway" 146 | with description 147 | "This is the second floor hallway. Rooms can be seen north and 148 | south and a staircase leads down.", 149 | n_to North_Bedroom, 150 | s_to South_Bedroom, 151 | d_to Foyer, 152 | has light; 153 | 154 | Object North_Bedroom "North Bedroom" 155 | with description 156 | "This is a bedroom on the north side of the house.", 157 | s_to Upper_Hallway, 158 | has light; 159 | 160 | Object South_Bedroom "South Bedroom" 161 | with description 162 | "This is a bedroom on the south side of the house.", 163 | n_to Upper_Hallway, 164 | has light; 165 | 166 | ! ---------------------------------------------------------------------------- 167 | ! Grammar 168 | ! 169 | ! The grammar section includes the file "Grammar" and will later include 170 | ! extensions to the standard grammar library. 171 | ! 172 | ! ---------------------------------------------------------------------------- 173 | 174 | Include "Grammar"; 175 | 176 | ! ---------------------------------------------------------------------------- 177 | ! Compilation Results 178 | ! ---------------------------------------------------------------------------- 179 | ! Command: INFRMW32 -J HOUSE02.INF 180 | ! 181 | ! PC/Win32 Inform 6.14 (8th September 1997) 182 | ! 6 "compass" 183 | ! 7 "north wall" 184 | ! 8 "south wall" 185 | ! 9 "east wall" 186 | ! 10 "west wall" 187 | ! 11 "northeast wall" 188 | ! 12 "northwest wall" 189 | ! 13 "southeast wall" 190 | ! 14 "southwest wall" 191 | ! 15 "ceiling" 192 | ! 16 "floor" 193 | ! 17 "outside" 194 | ! 18 "inside" 195 | ! 19 "(darkness object)" 196 | ! 20 "(self object)" 197 | ! 21 "(Inform Parser)" 198 | ! 22 "(Inform Library)" 199 | ! 23 "(with no short name)" 200 | ! 24 "Sidewalk" 201 | ! 25 "Front Porch" 202 | ! 26 "Foyer" 203 | ! 27 "Hallway" 204 | ! 28 "Kitchen" 205 | ! 29 "Upper Hallway" 206 | ! 30 "North Bedroom" 207 | ! 31 "South Bedroom" 208 | -------------------------------------------------------------------------------- /tutor/house03.inf: -------------------------------------------------------------------------------- 1 | ! ------------------------------------------------------------------------------ 2 | ! Inform for New Writers 3 | ! 4 | ! The House - Version 3 5 | ! 6 | ! Last Modified: David Cornelson - 22-Jan-1998 7 | ! 8 | ! This work is freely offered to the Public Domain. - DAC 12-12-2015 9 | ! 10 | ! ------------------------------------------------------------------------------ 11 | 12 | Constant DEBUG; 13 | 14 | Constant Story "The House"; 15 | 16 | Constant Headline 17 | "^Inform for New Writers^ 18 | The House - Version 3^ 19 | By New Writer (1998) - Last Compiled: 22-Jan-1998^"; 20 | 21 | Constant MAX_SCORE 100; 22 | Serial "980122"; 23 | 24 | Release 2; 25 | 26 | Include "Parser"; 27 | Include "VerbLib"; 28 | 29 | !------------------------------------------------------------------------------- 30 | ! Initialise 31 | ! 32 | !------------------------------------------------------------------------------- 33 | 34 | [ Initialise; 35 | 36 | location = Sidewalk; 37 | 38 | ]; 39 | 40 | [ PrintRank; 41 | print ", earning you the rank of "; 42 | if (score >= 100) "the greatest."; 43 | if (score >= 80) "above average."; 44 | if (score >= 60) "average."; 45 | if (score >= 40) "below average."; 46 | if (score >= 20) "the barely living."; 47 | "the living dead."; 48 | ]; 49 | 50 | ! ---------------------------------------------------------------------------- 51 | ! Locations 52 | ! 53 | ! In this section we will define our locations. These are "Objects" to Inform. 54 | ! 55 | ! ---------------------------------------------------------------------------- 56 | 57 | Object Sidewalk "Sidewalk" 58 | with description 59 | "You are standing on the sidewalk in front of a house to the west.", 60 | w_to Front_Porch, 61 | has light; 62 | 63 | ! 64 | ! Notice we changed the w_to and in_to properties to reflect our new door. 65 | ! We changed the description to reflect our new doors as well... 66 | ! 67 | 68 | Object Front_Porch "Front Porch" 69 | with description 70 | "This is the front porch of the house. There are two doors 71 | leading inside. The door on the left leads west and the 72 | door on the right leads northwest.", 73 | e_to Sidewalk, 74 | w_to Left_Front_Door, 75 | in_to Left_Front_Door, 76 | nw_to Right_Front_Door, 77 | has light; 78 | 79 | ! 80 | ! VERSION 3 - Adding a door 81 | ! 82 | ! Inform allows you to create special objects that represent doors. Doors 83 | ! are simply objects with special "properties" and "attributes". 84 | ! 85 | ! A "property" is a function that can be listed in the "Object" statement. 86 | ! For instance, "e_to" and "w_to" are properties. 87 | ! 88 | ! Properties that are used for doors are: 89 | ! 90 | ! - door_to Tells Inform where the door leads if 'entered'. 91 | ! 92 | ! - door_dir Tells Inform which direction the door faces. 93 | ! 94 | ! - when_open The description of the door when open. 95 | ! 96 | ! - when_closed The description of the door when closed. 97 | ! 98 | ! - found_in A list of locations where the door resides. 99 | ! 100 | ! - with_key Specify which object is needed to lock and unlock door. 101 | ! 102 | ! Attributes that are used for doors: 103 | ! 104 | ! - static OR Tells Inform that the door cannot be carried. 105 | ! - scenery Tells Inform that the door cannot be carried 106 | ! and also is not mentioned in normal location 107 | ! descriptions. 108 | ! 109 | ! - door Mandatory...tells Inform this object is a door. 110 | ! 111 | ! - open Current state of door. To make the door start 112 | ! 'closed', then give the object the attribute 113 | ! ~open. 114 | ! 115 | ! - lockable Can be locked. 116 | ! 117 | ! - locked Starts out locked. Give it ~locked to start 118 | ! it as unlocked. 119 | ! 120 | ! NOTE: A few of the properties and attributes above can be used with other 121 | ! objects. The only ones specific to a door object are the 'door_to' 122 | ! and 'door_dir' properties and the 'door' attribute. 123 | 124 | ! 125 | ! NOTE ABOUT THE TILDE CHARACTER: 126 | ! In evaluations of variables, the tilde character, ~, signifies 127 | ! 'not' or 'false value of'. 128 | ! When you see ~=, this means "not equal to". 129 | ! When you see ~attribute, this means "the false value of attribute". 130 | ! 131 | ! The tilde character, ~, has another use. Inside a string, if you 132 | ! want to print a double-quote, you would use the tilde. For example: 133 | ! 134 | ! print "John said, ~Run spot run!~"; 135 | ! 136 | ! ...would print... 137 | ! 138 | ! John said, "Run spot run!" 139 | ! 140 | 141 | ! 142 | ! We have two front doors built into our house, one leading to the 143 | ! foyer, and the other leading to the den. 144 | ! 145 | ! The left door is a one way door that has no lock. You can enter 146 | ! the door to the west. 147 | ! 148 | ! The right door is a two-way door that is lockable. The key is 149 | ! located in the north bedroom. You enter the door to the northwest. 150 | ! 151 | ! Q: What is the '->' used for? 152 | ! 153 | ! A: This symbol tells Inform that this object is located 'within' the most recent 154 | ! location definition. 155 | ! 156 | ! If two arrows are used, then the object is within the most recent -> object. 157 | ! 158 | ! The 'Left_Front_Door' is a 'child' of the 'Front_Porch' and the 159 | ! 'Front_Porch' is the 'parent' of 'Left_Front_Door'. 160 | 161 | Object -> Left_Front_Door "left front door" 162 | with name "left" "front" "door", 163 | description 164 | "The left front door is made of brass.", 165 | when_open "The left front door is open.", 166 | when_closed "The left front door is closed.", 167 | door_to Foyer, 168 | door_dir w_to, 169 | has static door openable; 170 | 171 | ! 172 | ! The two-way door has 'functions' for the door_to and door_dir properties 173 | ! because you can start on the front porch or the den. The same is true for 174 | ! the directions, you can either be going through the door northwest or 175 | ! southeast. 176 | ! 177 | ! These are 'embedded functions'. They don't need a name or arguments so 178 | ! you place a semi-colon immediately after the first bracket. The end of 179 | ! the function is signified by the closing bracket. You separate embedded 180 | ! functions the same way you separate other properties, with a comma. 181 | ! 182 | ! The 'if' statement within both of the embedded functions is used to 183 | ! determine which location you are starting in for the two-way door. 184 | ! 185 | ! The determination is calculated by comparing the 'location' variable 186 | ! (which Inform ALWAYS sets to the players current location) and the 187 | ! Front_Porch. If this is true, the first statement (until the semi-colon) 188 | ! is executed. If it's false (the player is NOT in the Front_Porch) then 189 | ! the second statement is executed. 190 | ! 191 | ! Notice the 'found_in' property lists both the Front_Porch and Den. This 192 | ! is so you can 'see' the doors in both of these locations. 193 | ! 194 | 195 | Object Right_Front_Door "right front door" 196 | with name "right" "front" "door", 197 | description 198 | "The right front door is made of wood.", 199 | when_open "The right front door is open.", 200 | when_closed "The right front door is closed.", 201 | door_to [; if (location==Front_Porch) return Den; return Front_Porch; ], 202 | door_dir [; if (location==Front_Porch) return nw_to; return se_to; ], 203 | found_in Front_Porch Den, 204 | with_key right_key, 205 | has static door openable lockable locked; 206 | 207 | Object Den "Den" 208 | with description 209 | "You are in the den of the house.", 210 | se_to Right_Front_Door, 211 | out_to Right_Front_Door, 212 | has light; 213 | 214 | Object Foyer "Foyer" 215 | with description 216 | "You are standing in the foyer of the house. It seems as though 217 | you can go up a staircase, northwest, or back out the front 218 | door to the east.", 219 | out_to Front_Porch, 220 | e_to Front_Porch, 221 | nw_to Hallway, 222 | u_to Upper_Hallway, 223 | has light; 224 | 225 | Object Hallway "Hallway" 226 | with description 227 | "You are in the hallway on the first floor of the house. The 228 | foyer is southeast and the kitchen is west of here.", 229 | se_to Foyer, 230 | w_to Kitchen, 231 | has light; 232 | 233 | Object Kitchen "Kitchen" 234 | with description 235 | "This is the kitchen of the house. A hallway can be seen to the 236 | east.", 237 | e_to Hallway, 238 | has light; 239 | 240 | Object Upper_Hallway "Upper Hallway" 241 | with description 242 | "This is the second floor hallway. Rooms can be seen north and 243 | south and a staircase leads down.", 244 | n_to North_Bedroom, 245 | s_to South_Bedroom, 246 | d_to Foyer, 247 | has light; 248 | 249 | Object North_Bedroom "North Bedroom" 250 | with description 251 | "This is a bedroom on the north side of the house.", 252 | s_to Upper_Hallway, 253 | has light; 254 | 255 | ! 256 | ! This is the 'key' for the right front door. There are no directions 257 | ! or attributes since it's a just a simple object. 258 | ! 259 | ! I placed the key here to keep these examples building a workable game. 260 | ! You can move the key anywhere you like though by cutting this line and 261 | ! pasting it 'below' any other location object. 262 | ! 263 | ! Remember, this is the object listed in 'with_key' in the right_door 264 | ! object, so it's the only way to unlock that door. 265 | ! 266 | 267 | Object -> right_key "right key" with name "right" "key"; 268 | 269 | Object South_Bedroom "South Bedroom" 270 | with description 271 | "This is a bedroom on the south side of the house.", 272 | n_to Upper_Hallway, 273 | has light; 274 | 275 | ! ---------------------------------------------------------------------------- 276 | ! Grammar 277 | ! 278 | ! The grammar section includes the file "Grammar" and will later include 279 | ! extensions to the standard grammar library. 280 | ! 281 | ! ---------------------------------------------------------------------------- 282 | 283 | Include "Grammar"; 284 | 285 | ! Compilation results: INFRMW32 -J HOUSE03.INF 286 | ! 287 | !PC/Win32 Inform 6.14 (8th September 1997) 288 | ! 6 "compass" 289 | ! 7 "north wall" 290 | ! 8 "south wall" 291 | ! 9 "east wall" 292 | ! 10 "west wall" 293 | ! 11 "northeast wall" 294 | ! 12 "northwest wall" 295 | ! 13 "southeast wall" 296 | ! 14 "southwest wall" 297 | ! 15 "ceiling" 298 | ! 16 "floor" 299 | ! 17 "outside" 300 | ! 18 "inside" 301 | ! 19 "(darkness object)" 302 | ! 20 "(self object)" 303 | ! 21 "(Inform Parser)" 304 | ! 22 "(Inform Library)" 305 | ! 23 "(with no short name)" 306 | ! 24 "Sidewalk" 307 | ! 25 "Front Porch" 308 | ! 26 "left front door" 309 | ! 27 "right front door" 310 | ! 28 "Den" 311 | ! 29 "Foyer" 312 | ! 30 "Hallway" 313 | ! 31 "Kitchen" 314 | ! 32 "Upper Hallway" 315 | ! 33 "North Bedroom" 316 | ! 34 "right key" 317 | ! 35 "South Bedroom" 318 | -------------------------------------------------------------------------------- /tutor/house05.inf: -------------------------------------------------------------------------------- 1 | ! ------------------------------------------------------------------------------ 2 | ! Inform for New Writers 3 | ! 4 | ! The House - Version 5 5 | ! 6 | ! Last Modified: David Cornelson - 22-Jan-1998 7 | ! 8 | ! This work is freely offered to the Public Domain. - DAC 12-12-2015 9 | ! 10 | ! ------------------------------------------------------------------------------ 11 | 12 | Constant Story "The House"; 13 | 14 | Constant Headline 15 | "^Inform for New Writers^ 16 | The House - Version 5^ 17 | By New Writer (1998) - Last Compiled: 22-Jan-1998^"; 18 | 19 | Constant MAX_SCORE 100; 20 | Serial "980122"; 21 | 22 | Release 2; 23 | 24 | Include "Parser"; 25 | Include "VerbLib"; 26 | 27 | !------------------------------------------------------------------------------- 28 | ! Initialise 29 | ! 30 | !------------------------------------------------------------------------------- 31 | 32 | [ Initialise; 33 | 34 | location = Sidewalk; 35 | 36 | ]; 37 | 38 | [ PrintRank; 39 | print ", earning you the rank of "; 40 | if (score >= 100) "the greatest."; 41 | if (score >= 80) "above average."; 42 | if (score >= 60) "average."; 43 | if (score >= 40) "below average."; 44 | if (score >= 20) "the barely living."; 45 | "the living dead."; 46 | ]; 47 | 48 | ! ---------------------------------------------------------------------------- 49 | ! Locations 50 | ! 51 | ! In this section we will define our locations. These are "Objects" to Inform. 52 | ! 53 | ! ---------------------------------------------------------------------------- 54 | 55 | ! 56 | ! VERSION 5 - Adding a container to your game, functions, verbs, and death. 57 | ! 58 | ! In many cases you will want an object to be able to contain other objects. 59 | ! This may be as simple as creating a 'backpack' that will contain your school 60 | ! papers, apple, and pencil sharpener. In a more complex definition, a container 61 | ! could be a chasm, a bottomless pit, refrigerator, or a television. 62 | ! 63 | ! We're going to create a simple container and a complex container. 64 | ! 65 | ! The simple container is probably very familiar to you. It's a mailbox amd it's 66 | ! right here in front of the house. It contains a letter that can be read as well. 67 | ! 68 | 69 | Object Sidewalk "Sidewalk" 70 | with description 71 | "You are standing on the sidewalk in front of a house to the west.", 72 | w_to Front_Porch, 73 | has light; 74 | 75 | ! 76 | ! Add the mailbox with open and closed descriptions. 77 | ! 78 | Object -> Mailbox "mailbox" 79 | with name "mailbox" "box", 80 | when_open "There is an open mailbox here.", 81 | when_closed "There is a closed mailbox here.", 82 | has static container openable; 83 | 84 | ! 85 | ! Add 'legible' attribute to distinguish something that can be 'read'. 86 | ! This is determined in the verb extension located in the grammar 87 | ! section at the end of this file. 88 | ! 89 | Attribute legible; 90 | 91 | ! 92 | ! And here is the letter, which can be consulted, read, or torn up. If it's 93 | ! torn up, the letter is removed from the game, never to be seen again. 94 | ! 95 | Object -> -> Letter "letter" 96 | with name "letter" "paper", 97 | description 98 | "The letter is a simple page of notebook paper.", 99 | before [; Consult,Read: "The letter contains a vague story about an evil couch, 100 | but you can't make out anymore detail. Interesting 101 | little tidbit though."; 102 | Tear: remove Letter; 103 | "You rip the letter into tiny pieces that blow away in the wind."; 104 | ] 105 | has legible; 106 | 107 | Object Front_Porch "Front Porch" 108 | with description 109 | "This is the front porch of the house. There are two doors 110 | leading inside. The door on the left leads west and the 111 | door on the right leads northwest.", 112 | e_to Sidewalk, 113 | w_to Left_Front_Door, 114 | in_to Left_Front_Door, 115 | nw_to Right_Front_Door, 116 | has light; 117 | 118 | Object -> Left_Front_Door "left front door" 119 | with name "left" "front" "door", 120 | description 121 | "The left front door is made of brass.", 122 | when_open "The left front door is open.", 123 | when_closed "The left front door is closed.", 124 | door_to Foyer, 125 | door_dir w_to, 126 | has static door openable; 127 | 128 | Object Right_Front_Door "right front door" 129 | with name "right" "front" "door", 130 | description 131 | "The right front door is made of wood.", 132 | when_open "The right front door is open.", 133 | when_closed "The right front door is closed.", 134 | door_to [; if (location==Front_Porch) return Den; return Front_Porch; ], 135 | door_dir [; if (location==Front_Porch) return nw_to; return se_to; ], 136 | found_in Front_Porch Den, 137 | with_key right_key, 138 | has static door openable lockable locked; 139 | 140 | Object Den "Den" 141 | with description 142 | "You are in the den of the house. The living room is west of hear 143 | and the front porch is to the southeast.", 144 | se_to Right_Front_Door, 145 | out_to Right_Front_Door, 146 | w_to Living_Room, 147 | has light; 148 | 149 | Object -> Rock "rock" 150 | with name "rock", 151 | description 152 | "It's smooth and flat, perfect for skipping in a pond.", 153 | before [; Insert,PutOn,ThrowAt: 154 | if (second==Evil_Couch) rfalse; ! Allow the rock to be eaten by couch 155 | if (second==Pond) { 156 | print "The rock skips across the water several times and sinks. 157 | Amazingly, after a few moments, the rock washes up at 158 | your feet. Wow, what an undertow!^"; 159 | move Rock to Backyard; 160 | rtrue; 161 | ! 162 | ! Replace rock so that player can try it again.... 163 | ! 164 | } else { 165 | print "You can't throw the rock at ",(the) second, ".^"; 166 | rtrue; 167 | } 168 | ]; 169 | 170 | Object Living_Room "Living Room" 171 | with name "living" "room", 172 | description 173 | "This is the living room of the house. The den is to the east.", 174 | e_to Den, 175 | has light; 176 | 177 | ! 178 | ! And here is our evil couch. Anything put on or in the couch will be 179 | ! 'eaten', including you. In fact, by setting the 'deadflag' to 1, 180 | ! Inform is informed to 'end' the game because you have died. 181 | ! 182 | ! Notice we used the 'before' property and the 'Enter' and 'Receive' 183 | ! verbs to handle the action. 184 | ! 185 | Object -> Evil_Couch "couch" 186 | with name "couch" "sofa", 187 | when_open "There is a filthy, worn down couch here.", 188 | before [; Enter: deadflag=1; 189 | "You are eaten by the couch."; 190 | Receive: remove noun; 191 | "The couch eats ", (the) noun, " and belches."; 192 | ], 193 | has static container open enterable; 194 | 195 | Object Foyer "Foyer" 196 | with description 197 | "You are standing in the foyer of the house. It seems as though 198 | you can go up a staircase, northwest, or back out the front 199 | door to the east.", 200 | out_to Front_Porch, 201 | e_to Front_Porch, 202 | nw_to Hallway, 203 | u_to Upper_Hallway, 204 | has light; 205 | 206 | Object Hallway "Hallway" 207 | with description 208 | "You are in the hallway on the first floor of the house. The 209 | foyer is southeast and the kitchen is west of here.", 210 | se_to Foyer, 211 | w_to Kitchen, 212 | has light; 213 | 214 | Object Kitchen "Kitchen" 215 | with description 216 | "This is the kitchen of the house. A hallway can be seen to the 217 | east and an open doorway to the west leads out to the backyard.", 218 | e_to Hallway, 219 | w_to Backyard, 220 | out_to Backyard, 221 | has light; 222 | 223 | Object Backyard "Backyard" 224 | with name "yard", 225 | description 226 | "This is the backyard behind the house. There is a pond here.", 227 | e_to Kitchen, 228 | in_to Kitchen, 229 | has light; 230 | 231 | Object -> Pond "pond" 232 | with name "pond" "water", 233 | description 234 | "It's a small pond, but wide enough to skip rocks.", 235 | has static concealed container open; 236 | 237 | Object Upper_Hallway "Upper Hallway" 238 | with description 239 | "This is the second floor hallway. Rooms can be seen north and 240 | south and a staircase leads down.", 241 | n_to North_Bedroom, 242 | s_to South_Bedroom, 243 | d_to Foyer, 244 | has light; 245 | 246 | Object North_Bedroom "North Bedroom" 247 | with description 248 | "This is a bedroom on the north side of the house.", 249 | s_to Upper_Hallway, 250 | has light; 251 | 252 | Object -> right_key "right key" with name "right" "key", article "the"; 253 | 254 | Object South_Bedroom "South Bedroom" 255 | with description 256 | "This is a bedroom on the south side of the house.", 257 | n_to Upper_Hallway, 258 | has light; 259 | 260 | ! ---------------------------------------------------------------------------- 261 | ! 262 | ! Functions 263 | ! 264 | ! ---------------------------------------------------------------------------- 265 | 266 | ! 267 | ! Added function ReadSub so that the property 'before' can use it. The default, 268 | ! if there is no 'before read', is to examine the object. 269 | ! 270 | [ ReadSub; <>; ]; 271 | 272 | [ TearSub; "You can't tear that"; ]; 273 | 274 | ! ---------------------------------------------------------------------------- 275 | ! Grammar 276 | ! 277 | ! The grammar section includes the file "Grammar" and will later include 278 | ! extensions to the standard grammar library. 279 | ! 280 | ! ---------------------------------------------------------------------------- 281 | 282 | Include "Grammar"; 283 | 284 | ! 285 | ! We also have to extend the read grammar to call ReadSub 286 | ! by default. 287 | ! 288 | ! We're using the 'Extend' statment because the word "read" is already defined 289 | ! in the grammar file included above. This adds our usage. 290 | ! 291 | ! The 'first' tag is used to indicate to Inform that this usage of the word 292 | ! "read" should be the first one checked. Without 'first', the "read" word 293 | ! will not work the way we want it to because the default usage will get 294 | ! called and will not handle our code properly. 295 | ! 296 | ! 'legible' is the attribute we created and by placing it here, we're telling 297 | ! Inform that this attribute must be present in the object to call this usage 298 | ! of the word "read". 299 | ! 300 | Extend "read" first * legible -> Read; 301 | 302 | ! 303 | ! We've also added the ability to 'tear' an object. Notice 304 | ! we had to specify 'noun' and then direct the default to 305 | ! TearSub. 306 | ! 307 | ! By the way, the 'Sub' is added on automatically by Inform. 308 | ! 309 | ! The word 'noun' tells Inform that the word "tear" must be followed by a 310 | ! noun, otherwise Inform will reply, "What do you want to tear?". 311 | ! 312 | Verb "tear" * noun -> Tear; 313 | ! 314 | ! Q: I'm really confused! Inform uses the words "first", "second", and "noun". 315 | ! Can you explain the difference again? 316 | ! 317 | ! A: Sure. 318 | ! 319 | ! 'first' is a flag used in the grammar statement "Extend" so that the 320 | ! new usage is called before previously defined usages. Without this 321 | ! flag, an older usage might get called and your code may not work. 322 | ! 323 | ! 'second' is a variable that Inform sets if there is a second noun in 324 | ! the player's statement. 325 | ! 326 | ! 'noun' is a variable that Inform sets if there are any nouns in the 327 | ! player's statement. It gets set to the first noun found. 328 | ! 329 | ! > THROW ROCK AT POND 330 | ! 331 | ! ^ ^ 332 | ! noun second 333 | ! 334 | -------------------------------------------------------------------------------- /tutor/house06.inf: -------------------------------------------------------------------------------- 1 | ! ------------------------------------------------------------------------------ 2 | ! Inform for New Writers 3 | ! 4 | ! The House - Version 6 5 | ! 6 | ! Last Modified: David Cornelson - 31-Jan-1998 7 | ! 8 | ! This work is freely offered to the Public Domain. - DAC 12-12-2015 9 | ! 10 | ! ------------------------------------------------------------------------------ 11 | 12 | Constant Story "The House"; 13 | 14 | Constant Headline 15 | "^Inform for New Writers^ 16 | The House - Version 6^ 17 | By New Writer (1998) - Last Compiled: 31-Jan-1998^"; 18 | 19 | Constant MAX_SCORE 100; 20 | Serial "980131"; 21 | 22 | Release 1; 23 | 24 | Include "Parser"; 25 | Include "VerbLib"; 26 | 27 | !------------------------------------------------------------------------------- 28 | ! Initialise 29 | ! 30 | !------------------------------------------------------------------------------- 31 | 32 | ! 33 | ! VERSION 6 - Adding a non-playing character or daemon to your game 34 | ! 35 | ! We are going to add a little pink Jarbigruen to our game, His name is Snark 36 | ! and he tends to be a little inquisitive. In this version of 'The House', he 37 | ! won't really 'do' anything but sit in your arms and blabber a few 38 | ! phrases, which of course you can add to at your discretion. 39 | ! 40 | ! The first thing to do is create the object for Snark. We're going to put him 41 | ! in the mailbox. This means that after the '-> Mailbox' object, we need to add 42 | ! '-> -> Snark' to tell Inform that he is a child object of the mailbox. 43 | ! 44 | ! The Snark daemon will be started the first time you open the mailbox. 45 | 46 | [ Initialise; 47 | 48 | location = Sidewalk; 49 | 50 | ]; 51 | 52 | [ PrintRank; 53 | print ", earning you the rank of "; 54 | if (score >= 100) "the greatest."; 55 | if (score >= 80) "above average."; 56 | if (score >= 60) "average."; 57 | if (score >= 40) "below average."; 58 | if (score >= 20) "the barely living."; 59 | "the living dead."; 60 | ]; 61 | 62 | ! ---------------------------------------------------------------------------- 63 | ! Locations 64 | ! 65 | ! In this section we will define our locations. These are "Objects" to Inform. 66 | ! 67 | ! ---------------------------------------------------------------------------- 68 | 69 | Object Sidewalk "Sidewalk" 70 | with description 71 | "You are standing on the sidewalk in front of a house to the west.", 72 | w_to Front_Porch, 73 | has light; 74 | 75 | Object -> Mailbox "mailbox" 76 | with name "mailbox" "box", 77 | 78 | ! 79 | ! The 'before' property is used to 'catch' verb commands before Inform 80 | ! handles them. In this case, we're going to catch the verb 'Open'. 81 | ! 82 | ! If Snark is in the Mailbox (which he is at the initial start of the 83 | ! game) then we execute some special code. 84 | ! 85 | ! We are writing a 'function'. Remember that functions may have arguments 86 | ! which would be defined before the semi-colon. This is important to 87 | ! Inform so don't forget to begin the 'before' function with the bracket 88 | ! AND the semi-colon. 89 | ! 90 | ! Each verb you intend to 'catch' is started simply by the verb followed 91 | ! by a colon. The verb's execution ends with the next verb or at the end 92 | ! of the function. 93 | ! 94 | before [; Open: ! 95 | ! This function has a special behavior if Snark is 96 | ! in the mailbox, which he is in the beginning. 97 | ! 98 | if (Snark in Mailbox) { 99 | 100 | StartDaemon(Snark); 101 | move Snark to player; 102 | give Mailbox open; 103 | 104 | print "~Hey! It's about time! Why are you piddling 105 | around out there? Don't you know I need air? Who 106 | do you think you are anyway, some big adventurer 107 | or something? Pullllease!~, exclaims a small pink 108 | thing from the mailbox.^^~Hi. I'm Snark, the 109 | Jarbigruen!~, he cries in a high-pitched voice 110 | and then leaps from the mailbox into your 111 | arms.^"; 112 | rtrue; 113 | } 114 | ! 115 | ! This is where the default behavior is executed for 116 | ! the verb open. We don't have to 'do' anything and 117 | ! Inform will know to execute the default processing. 118 | ! 119 | ], 120 | when_open "There is an open mailbox here.", 121 | when_closed "There is a closed mailbox here.", 122 | has static container openable; 123 | 124 | ! SNARK, THE JARBIGRUEN 125 | ! 126 | ! Snark has a lot of different names you can refer to him with so we have to 127 | ! put these in the 'name' property. Each name is separated by a space. 128 | ! 129 | Object -> -> Snark "small pink Jarbigruen" 130 | with name "snark" "jarbigruen" "alien" "monster" "thing", 131 | description 132 | "Snark, a little pink Jarbigruen, stands approximately ten 133 | centimeters tall, has two legs, two arms with tiny little hands, 134 | a wide-eyed face, and a tuft of yellowish hair on his head.", 135 | 136 | ! 137 | ! We want Snark to stay with the player so we catch a 'drop' 138 | ! and 'Insert' before Inform can let that happen. 139 | ! 140 | ! Except if it's the couch...that's handled differently... 141 | ! 142 | before [; Drop,Insert: if (second == Evil_Couch) { 143 | print "You drop Snark onto the couch and the 144 | cushions begin to smother him slowly, 145 | until he completely disappears. After 146 | a few seconds you hear strange noises 147 | and, ** POP **, a pink ball is spit out 148 | of the couch back into your arms!^^ 149 | Snark looks up at you and winks, 150 | ~Jarbigruen's don't go down very easy, 151 | I guess.~^"; 152 | rtrue; 153 | } 154 | print "~Hey! I'm not going anywhere without you!~, 155 | Snark says.^"; 156 | rtrue; 157 | ], 158 | 159 | ! 160 | ! The daemon property is central to handling the characterization 161 | ! of Snark, the Jarbigruen. For each turn the player takes, this 162 | ! property is called. 163 | ! 164 | ! We're not going to do anything complex at this point. Just to 165 | ! show that Snark is alive and kinking, we're going to add random 166 | ! conversation from Snark. We're also adding the 'switch' statement. 167 | ! 168 | ! The 'switch' statement is used to differentiate different values 169 | ! of a variable or expression. For each possible value, you can 170 | ! code a different set of instructions. 171 | ! 172 | ! The random(10) function will return, randomly, a number from 173 | ! 1 to 10. You can make this number anything you like. 174 | ! 175 | ! We're only giving Snark responses for half of the random numbers 176 | ! so he isn't talking all of the time. 177 | ! 178 | daemon [; switch (random(10)) { 179 | 1: "Snark says, ~Isn't it great to be here!~"; 180 | 3: "Snark looks up at you with a glint in his eye and 181 | tickles you."; 182 | 5: "Snark says, ~You are an excellent adventurer!~"; 183 | 7: "Snark cries, ~Stop it! Your holding me too tight!~"; 184 | 9: "Snark rifles through your pockets and sighs, 185 | ~Got any candy?~"; 186 | } 187 | ], 188 | has animate; 189 | 190 | Attribute legible; 191 | 192 | Object -> -> Letter "letter" 193 | with name "letter" "paper", 194 | description 195 | "The letter is a simple page of notebook paper.", 196 | before [; Consult,Read: "The letter contains a vague story about an evil couch, 197 | but you can't make out anymore detail. Interesting 198 | little tidbit though."; 199 | Tear: remove Letter; 200 | "You rip the letter into tiny pieces that blow away in the wind."; 201 | ] 202 | has legible; 203 | 204 | Object Front_Porch "Front Porch" 205 | with description 206 | "This is the front porch of the house. There are two doors 207 | leading inside. The door on the left leads west and the 208 | door on the right leads northwest.", 209 | e_to Sidewalk, 210 | w_to Left_Front_Door, 211 | in_to Left_Front_Door, 212 | nw_to Right_Front_Door, 213 | has light; 214 | 215 | ! 216 | ! I've added the attribute 'open' to both of the doors. I figured we'd 217 | ! had that lesson and there was no need to repeat it. Both doors will 218 | ! be open at the start of the game. You can still close them and lock 219 | ! the right one with the key though. 220 | ! 221 | Object -> Left_Front_Door "left front door" 222 | with name "left" "front" "door", 223 | description 224 | "The left front door is made of brass.", 225 | when_open "The left front door is open.", 226 | when_closed "The left front door is closed.", 227 | door_to Foyer, 228 | door_dir w_to, 229 | has static door openable open; 230 | 231 | Object Right_Front_Door "right front door" 232 | with name "right" "front" "door", 233 | description 234 | "The right front door is made of wood.", 235 | when_open "The right front door is open.", 236 | when_closed "The right front door is closed.", 237 | door_to [; if (location==Front_Porch) return Den; return Front_Porch; ], 238 | door_dir [; if (location==Front_Porch) return nw_to; return se_to; ], 239 | found_in Front_Porch Den, 240 | with_key right_key, 241 | has static door openable lockable locked open; 242 | 243 | Object Den "Den" 244 | with description 245 | "You are in the den of the house. The living room is west of hear 246 | and the front porch is to the southeast.", 247 | se_to Right_Front_Door, 248 | out_to Right_Front_Door, 249 | w_to Living_Room, 250 | has light; 251 | 252 | Object -> Rock "rock" 253 | with name "rock", 254 | description 255 | "It's smooth and flat, perfect for skipping in a pond.", 256 | before [; Insert,PutOn,ThrowAt: 257 | if (second==Evil_Couch) rfalse; ! Allow the rock to be eaten by couch 258 | if (second==Pond) { 259 | print "The rock skips across the water several times and sinks. 260 | Amazingly, after a few moments, the rock washes up at 261 | your feet. Wow, what an undertow!^"; 262 | move Rock to Backyard; 263 | rtrue; 264 | } else { 265 | print "You can't throw the rock at ",(the) second, ".^"; 266 | rtrue; 267 | } 268 | ]; 269 | 270 | Object Living_Room "Living Room" 271 | with name "living" "room", 272 | description 273 | "This is the living room of the house. The den is to the east.", 274 | e_to Den, 275 | has light; 276 | 277 | ! 278 | ! And here is our evil couch. Anything put on or in the couch will be 279 | ! 'eaten', including you. In fact, by setting the 'deadflag' to 1, 280 | ! Inform is informed to 'end' the game because you have died. 281 | ! 282 | ! Notice we used the 'before' property and the 'Enter' and 'Receive' 283 | ! verbs to handle the action. 284 | ! 285 | Object -> Evil_Couch "couch" 286 | with name "couch" "sofa", 287 | when_open "There is a filthy, worn down couch here.", 288 | before [; Enter: deadflag=1; 289 | "You are eaten by the couch. As you flail for your last few 290 | seconds, you see Snark beating on the couch trying to save 291 | you, to no avail."; 292 | Receive: remove noun; 293 | "The couch eats ", (the) noun, " and belches."; 294 | ], 295 | has static container open enterable; 296 | 297 | Object Foyer "Foyer" 298 | with description 299 | "You are standing in the foyer of the house. It seems as though 300 | you can go up a staircase, northwest, or back out the front 301 | door to the east.", 302 | out_to Front_Porch, 303 | e_to Front_Porch, 304 | nw_to Hallway, 305 | u_to Upper_Hallway, 306 | has light; 307 | 308 | Object Hallway "Hallway" 309 | with description 310 | "You are in the hallway on the first floor of the house. The 311 | foyer is southeast and the kitchen is west of here.", 312 | se_to Foyer, 313 | w_to Kitchen, 314 | has light; 315 | 316 | Object Kitchen "Kitchen" 317 | with description 318 | "This is the kitchen of the house. A hallway can be seen to the 319 | east and an open doorway to the west leads out to the backyard.", 320 | e_to Hallway, 321 | w_to Backyard, 322 | out_to Backyard, 323 | has light; 324 | 325 | Object Backyard "Backyard" 326 | with name "yard", 327 | description 328 | "This is the backyard behind the house. There is a pond here.", 329 | e_to Kitchen, 330 | in_to Kitchen, 331 | has light; 332 | 333 | Object -> Pond "pond" 334 | with name "pond" "water", 335 | description 336 | "It's a small pond, but wide enough to skip rocks.", 337 | has static concealed container open; 338 | 339 | Object Upper_Hallway "Upper Hallway" 340 | with description 341 | "This is the second floor hallway. Rooms can be seen north and 342 | south and a staircase leads down.", 343 | n_to North_Bedroom, 344 | s_to South_Bedroom, 345 | d_to Foyer, 346 | has light; 347 | 348 | Object North_Bedroom "North Bedroom" 349 | with description 350 | "This is a bedroom on the north side of the house.", 351 | s_to Upper_Hallway, 352 | has light; 353 | 354 | Object -> right_key "right key" with name "right" "key", article "the"; 355 | 356 | Object South_Bedroom "South Bedroom" 357 | with description 358 | "This is a bedroom on the south side of the house.", 359 | n_to Upper_Hallway, 360 | has light; 361 | 362 | ! ---------------------------------------------------------------------------- 363 | ! 364 | ! Functions 365 | ! 366 | ! ---------------------------------------------------------------------------- 367 | 368 | [ ReadSub; <>; ]; 369 | 370 | [ TearSub; "You can't tear that"; ]; 371 | 372 | ! ---------------------------------------------------------------------------- 373 | ! Grammar 374 | ! 375 | ! The grammar section includes the file "Grammar" and will later include 376 | ! extensions to the standard grammar library. 377 | ! 378 | ! ---------------------------------------------------------------------------- 379 | 380 | Include "Grammar"; 381 | 382 | Extend "read" first * legible -> Read; 383 | 384 | Verb "tear" * noun -> Tear; 385 | -------------------------------------------------------------------------------- /tutor/house07.inf: -------------------------------------------------------------------------------- 1 | ! ------------------------------------------------------------------------------ 2 | ! Inform for New Writers 3 | ! 4 | ! The House - Version 7 5 | ! 6 | ! Last Modified: David Cornelson - 01-Feb-1998 7 | ! 8 | ! This work is freely offered to the Public Domain. - DAC 12-12-2015 9 | ! 10 | ! ------------------------------------------------------------------------------ 11 | 12 | Constant Story "The House"; 13 | 14 | Constant Headline 15 | "^Inform for New Writers^ 16 | The House - Version 7^ 17 | By New Writer (1998) - Last Compiled: 01-Feb-1998^"; 18 | 19 | Constant MAX_SCORE 100; 20 | Serial "980201"; 21 | 22 | Release 1; 23 | 24 | Include "Parser"; 25 | Include "VerbLib"; 26 | 27 | !------------------------------------------------------------------------------- 28 | ! Initialise 29 | ! 30 | !------------------------------------------------------------------------------- 31 | 32 | [ Initialise; 33 | 34 | location = Sidewalk; 35 | 36 | ]; 37 | 38 | [ PrintRank; 39 | print ", earning you the rank of "; 40 | if (score >= 100) "the greatest."; 41 | if (score >= 80) "above average."; 42 | if (score >= 60) "average."; 43 | if (score >= 40) "below average."; 44 | if (score >= 20) "the barely living."; 45 | "the living dead."; 46 | ]; 47 | 48 | ! ---------------------------------------------------------------------------- 49 | ! Locations 50 | ! 51 | ! In this section we will define our locations. These are "Objects" to Inform. 52 | ! 53 | ! ---------------------------------------------------------------------------- 54 | 55 | Object Sidewalk "Sidewalk" 56 | with description 57 | "You are standing on the sidewalk in front of a house to the west.", 58 | w_to Front_Porch, 59 | has light; 60 | 61 | Object -> Mailbox "mailbox" 62 | with name "mailbox" "box", 63 | 64 | before [; Open: if (Snark in Mailbox) { 65 | 66 | StartDaemon(Snark); 67 | move Snark to player; 68 | give Mailbox open; 69 | 70 | print "~Hey! It's about time! Why are you piddling 71 | around out there? Don't you know I need air? Who 72 | do you think you are anyway, some big adventurer 73 | or something? Pullllease!~, exclaims a small pink 74 | thing from the mailbox.^^~Hi. I'm Snark, the 75 | Jarbigruen!~, he cries in a high-pitched voice 76 | and then leaps from the mailbox into your 77 | arms.^"; 78 | rtrue; 79 | } 80 | ], 81 | when_open "There is an open mailbox here.", 82 | when_closed "There is a closed mailbox here.", 83 | has static container openable; 84 | 85 | Object -> -> Snark "small pink Jarbigruen" 86 | with name "snark" "jarbigruen" "alien" "monster" "thing", 87 | description 88 | "Snark, a little pink Jarbigruen, stands approximately ten 89 | centimeters tall, has two legs, two arms with tiny little hands, 90 | a wide-eyed face, and a tuft of yellowish hair on his head.", 91 | 92 | before [; Drop,Insert: if (second == Evil_Couch) { 93 | print "You drop Snark onto the couch and the 94 | cushions begin to smother him slowly, 95 | until he completely disappears. After 96 | a few seconds you hear strange noises 97 | and, ** POP **, a pink ball is spit out 98 | of the couch back into your arms!^^ 99 | Snark looks up at you and winks, 100 | ~Jarbigruen's don't go down very easy, 101 | I guess.~^"; 102 | rtrue; 103 | } 104 | print "~Hey! I'm not going anywhere without you!~, 105 | Snark says.^"; 106 | rtrue; 107 | ], 108 | daemon [; switch (random(10)) { 109 | 1: "Snark says, ~Isn't it great to be here!~"; 110 | 3: "Snark looks up at you with a glint in his eye and 111 | tickles you."; 112 | 5: "Snark says, ~You are an excellent adventurer!~"; 113 | 7: "Snark cries, ~Stop it! Your holding me too tight!~"; 114 | 9: "Snark rifles through your pockets and sighs, 115 | ~Got any candy?~"; 116 | } 117 | ], 118 | has animate; 119 | 120 | Attribute legible; 121 | 122 | Object -> -> Letter "letter" 123 | with name "letter" "paper", 124 | description 125 | "The letter is a simple page of notebook paper.", 126 | before [; Consult,Read: "The letter contains a vague story about an evil couch, 127 | but you can't make out anymore detail. Interesting 128 | little tidbit though."; 129 | Tear: remove Letter; 130 | "You rip the letter into tiny pieces that blow away in the wind."; 131 | ] 132 | has legible; 133 | 134 | Object Front_Porch "Front Porch" 135 | with description 136 | "This is the front porch of the house. There are two doors 137 | leading inside. The door on the left leads west and the 138 | door on the right leads northwest.", 139 | e_to Sidewalk, 140 | w_to Left_Front_Door, 141 | in_to Left_Front_Door, 142 | nw_to Right_Front_Door, 143 | has light; 144 | 145 | ! 146 | ! VERSION 7 - Using a Class statement to create a group of common objects 147 | ! 148 | ! There are times when building your game that you begin building the same 149 | ! types of objects over and over. You end up copying code all over the place 150 | ! and maintaining this code becomes a search and replace chase scene. 151 | ! 152 | ! Well, in some instances, there is a better way. We have to discuss a little 153 | ! bit of methodology first though. 154 | ! 155 | ! Most games hsouldn't be written like 'The House'. You should write out as much 156 | ! of your story and physical world as possible. When you have a fairly complete 157 | ! view of this world, you break down all of aspects into objects. 158 | ! 159 | ! If we designed the current version of 'The House' this way, it would look 160 | ! something like this... 161 | ! 162 | ! ---------------------------- 163 | ! 164 | ! Sidewalk -> Mailbox -> Snark 165 | ! -> Letter 166 | ! 167 | ! Front Porch -> Left Door 168 | ! -> Right Door 169 | ! 170 | ! Foyer 171 | ! 172 | ! Den -> Rock 173 | ! 174 | ! Living Room -> Evil Couch 175 | ! 176 | ! Hallway 177 | ! 178 | ! Upper Hallway 179 | ! 180 | ! North Bedroom -> Key 181 | ! 182 | ! South Bedroom 183 | ! 184 | ! Kitchen 185 | ! 186 | ! Backyard -> Pond 187 | ! 188 | ! ---------------------------- 189 | ! 190 | ! You will likely want to do this BEFORE you begin programming your game. The reason 191 | ! is that you may be able to reduce some of your coding by locating similar objects. 192 | ! 193 | ! Q: What two objects in 'The House' are alike? 194 | ! 195 | ! A: The doors 196 | ! 197 | ! Correct. We are going to rewrite the two door objects, but first we're going to create 198 | ! a class for the foundation of their definition. 199 | ! 200 | 201 | Class Front_Door 202 | with name "front" "door", 203 | has static door openable open; 204 | 205 | ! 206 | ! And now we'll change the each door object to become a subset of this class. 207 | ! Notice that we can leave out the names and attributes in the class. These 208 | ! are 'inherited' by the newly defined objects. 209 | ! 210 | ! In this example, we didn't reduce our code all that much. But in many cases 211 | ! you will reduce your code. A good use of this is when you have an NPC or 212 | ! non-playing character that you want to be seen as learning. You can create 213 | ! a base class object with rudimentary actions and change to other objects 214 | ! when the NPC is supposed to be 'smarter'. 215 | ! 216 | ! Class Base_Snark ... 217 | ! 218 | ! Base_Snark Snark_1 ... 219 | ! Base_Snark Snark_2 ... 220 | ! Base_Snark Snark_3 ... 221 | ! 222 | ! Anything you define in the class object, is inherited by the continuing 223 | ! objects. If you redefine something, such as an attribute or property, 224 | ! then the new definition supercedes the class definition. 225 | ! 226 | 227 | Front_Door -> Left_Front_Door "left front door" 228 | with name "left", 229 | description 230 | "The left front door is made of brass.", 231 | when_open "The left front door is open.", 232 | when_closed "The left front door is closed.", 233 | door_to Foyer, 234 | door_dir w_to; 235 | 236 | Front_Door -> Right_Front_Door "right front door" 237 | with name "right", 238 | description 239 | "The right front door is made of wood.", 240 | when_open "The right front door is open.", 241 | when_closed "The right front door is closed.", 242 | door_to [; if (location==Front_Porch) return Den; return Front_Porch; ], 243 | door_dir [; if (location==Front_Porch) return nw_to; return se_to; ], 244 | found_in Front_Porch Den, 245 | with_key right_key, 246 | has lockable locked; 247 | 248 | Object Den "Den" 249 | with description 250 | "You are in the den of the house. The living room is west of hear 251 | and the front porch is to the southeast.", 252 | se_to Right_Front_Door, 253 | out_to Right_Front_Door, 254 | w_to Living_Room, 255 | has light; 256 | 257 | Object -> Rock "rock" 258 | with name "rock", 259 | description 260 | "It's smooth and flat, perfect for skipping in a pond.", 261 | before [; Insert,PutOn,ThrowAt: 262 | if (second==Evil_Couch) rfalse; ! Allow the rock to be eaten by couch 263 | if (second==Pond) { 264 | print "The rock skips across the water several times and sinks. 265 | Amazingly, after a few moments, the rock washes up at 266 | your feet. Wow, what an undertow!^"; 267 | move Rock to Backyard; 268 | rtrue; 269 | } else { 270 | print "You can't throw the rock at ",(the) second, ".^"; 271 | rtrue; 272 | } 273 | ]; 274 | 275 | Object Living_Room "Living Room" 276 | with name "living" "room", 277 | description 278 | "This is the living room of the house. The den is to the east.", 279 | e_to Den, 280 | has light; 281 | 282 | Object -> Evil_Couch "couch" 283 | with name "couch" "sofa", 284 | when_open "There is a filthy, worn down couch here.", 285 | before [; Enter: deadflag=1; 286 | "You are eaten by the couch. As you flail for your last few 287 | seconds, you see Snark beating on the couch trying to save 288 | you, to no avail."; 289 | Receive: remove noun; 290 | "The couch eats ", (the) noun, " and belches."; 291 | ], 292 | has static container open enterable; 293 | 294 | Object Foyer "Foyer" 295 | with description 296 | "You are standing in the foyer of the house. It seems as though 297 | you can go up a staircase, northwest, or back out the front 298 | door to the east.", 299 | out_to Front_Porch, 300 | e_to Front_Porch, 301 | nw_to Hallway, 302 | u_to Upper_Hallway, 303 | has light; 304 | 305 | Object Hallway "Hallway" 306 | with description 307 | "You are in the hallway on the first floor of the house. The 308 | foyer is southeast and the kitchen is west of here.", 309 | se_to Foyer, 310 | w_to Kitchen, 311 | has light; 312 | 313 | Object Kitchen "Kitchen" 314 | with description 315 | "This is the kitchen of the house. A hallway can be seen to the 316 | east and an open doorway to the west leads out to the backyard.", 317 | e_to Hallway, 318 | w_to Backyard, 319 | out_to Backyard, 320 | has light; 321 | 322 | Object Backyard "Backyard" 323 | with name "yard", 324 | description 325 | "This is the backyard behind the house. There is a pond here.", 326 | e_to Kitchen, 327 | in_to Kitchen, 328 | has light; 329 | 330 | Object -> Pond "pond" 331 | with name "pond" "water", 332 | description 333 | "It's a small pond, but wide enough to skip rocks.", 334 | has static concealed container open; 335 | 336 | Object Upper_Hallway "Upper Hallway" 337 | with description 338 | "This is the second floor hallway. Rooms can be seen north and 339 | south and a staircase leads down.", 340 | n_to North_Bedroom, 341 | s_to South_Bedroom, 342 | d_to Foyer, 343 | has light; 344 | 345 | Object North_Bedroom "North Bedroom" 346 | with description 347 | "This is a bedroom on the north side of the house.", 348 | s_to Upper_Hallway, 349 | has light; 350 | 351 | Object -> right_key "right key" with name "right" "key", article "the"; 352 | 353 | Object South_Bedroom "South Bedroom" 354 | with description 355 | "This is a bedroom on the south side of the house.", 356 | n_to Upper_Hallway, 357 | has light; 358 | 359 | ! ---------------------------------------------------------------------------- 360 | ! 361 | ! Functions 362 | ! 363 | ! ---------------------------------------------------------------------------- 364 | 365 | [ ReadSub; <>; ]; 366 | 367 | [ TearSub; "You can't tear that"; ]; 368 | 369 | ! ---------------------------------------------------------------------------- 370 | ! Grammar 371 | ! 372 | ! The grammar section includes the file "Grammar" and will later include 373 | ! extensions to the standard grammar library. 374 | ! 375 | ! ---------------------------------------------------------------------------- 376 | 377 | Include "Grammar"; 378 | 379 | Extend "read" first * legible -> Read; 380 | 381 | Verb "tear" * noun -> Tear; 382 | --------------------------------------------------------------------------------