From: Jason Self Date: Mon, 19 Aug 2019 01:39:31 +0000 (-0700) Subject: Import All Things Devours by Toby Ord (half sick of shadows) X-Git-Url: https://jxself.org/git/?p=devours.git;a=commitdiff_plain;h=e2f75a01f2da1dba54d70c1b996ed6a3f634cc32 Import All Things Devours by Toby Ord (half sick of shadows) Release 3 From http://www.amirrorclear.net/flowers/game/devours/devours.inf --- e2f75a01f2da1dba54d70c1b996ed6a3f634cc32 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7ee403d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +devours.z* \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..dc70f3a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib"] + path = lib + url = https://jxself.org/git/informlib.git diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..be3f7b2 --- /dev/null +++ b/COPYING @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/README b/README new file mode 100644 index 0000000..6c18b4f --- /dev/null +++ b/README @@ -0,0 +1,50 @@ +This repository contains a copy of All Things Devours by Toby Ord +(half sick of shadows). + +The author released the game to the public domain, allowing unlimited +permission to copy and change it. + +https://ifdb.tads.org/viewgame?id=5e23lnq25gon9tp3 +http://mirror.ifarchive.org/if-archive/games/source/inform/devours.inf +http://www.amirrorclear.net/flowers/game/devours/devours.inf + +The recommended way to get a copy of this git repository is a +recursive clone: + + git clone --recursive https://jxself.org/git/?p=devours.git + +This will clone all submodules recurively. If you did not perform a +recurive clone, once you have a copy of this git repository you will +also need the source code for the standard library: + + git submodule update --init --recursive + +To compile this game you will also need version 6 of the Inform +compiler from https://jxself.org/git/?p=inform.git + +Once the compiler has been compiled and is ready for use return to +this directory and run: + + inform +include_path=lib devours.inf + +Or you can run the included build.sh script which does the same thing. + +You will then get the story file for this game that can be run using +any appropriate Z-Machine interpreter, such as Frotz. Your GNU/Linux +distro probably has that packaged already for easy installation. + +-- +Copyright (C) 2019 Jason Self + +This file is free software: you may copy, redistribute and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public +License along with this file. If not, see https://gnu.org/licenses/ \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..884b14b --- /dev/null +++ b/build.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env sh +# +# Copyright (C) 2019 Jason Self +# +# This file is free software: you may copy, redistribute and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with this file. If not, see https://gnu.org/licenses/ + +inform +include_path=lib devours.inf \ No newline at end of file diff --git a/devours.inf b/devours.inf new file mode 100644 index 0000000..e89a039 --- /dev/null +++ b/devours.inf @@ -0,0 +1,5664 @@ +!% +code_path=../../Games/devours +!% $MAX_STATIC_DATA=150000 + + +!============================================================================ + +! This program was written by Toby Ord (half sick of shadows) and has been +! released into the public domain, so you are legally free to be distribute +! and modify it as you see fit. So long as you do so in good faith and with good +! taste (or sufficient taste) then you have my blessing. +! +! Oh, and apologies for the messy code! It was my first program in Inform. + +Constant Story "All Things Devours"; + +Constant Headline + "^Written for IFComp 2004 by half sick of shadows.^ + This is the post-competition release.^ + It is in the public domain and may thus be freely copied or modified.^ + First-time players should type 'about'.^"; + + +Release 3; ! post-competition release, (plus 1 bugfix) + +Replace DrawStatusLine; +Replace ScoreSub; + + +!============================================================================ +! Constants and Globals +! + +Constant DEATH_MENTION_UNDO; + +! EARLIEST_TIME is a time before which no action can happen +! (can't time travel to before this time) +! start_time is when the player arrives. +! From ten seconds earlier, +! the player is outside (and can interfere with escape attempts at this time) +! <<< thus the EARLIEST_TIME must be at least ten seconds before start_time >>> +! FINAL_TIME is when the security team arrive and any attempt to stay beyond this +! will get you caught. + +! the time units are 5 second blocks + +Global my_time; ! used instead of the_time to allow sub-minute turns + +! the timeline has the player in a non-specified 'limbo' from EARLIEST_TIME to + +Constant EARLIEST_TIME = ((4 * 60) + 13) * 12 + 11; +Constant FINAL_TIME = ((4 * 60) + 23) * 12 + 0; + +Global start_time = ((4 * 60) + 17) * 12 + 0; +Global early_guard_time = EARLIEST_TIME; ! but this changes in the challenge mode + +Constant CHALLENGE_EARLY_GUARD_TIME = ((4 * 60) + 15) * 12 + 11; + + +! the times of the two military experiments, if allowed to happen + +Constant EXPERIMENT1_TIME = (( 9 * 60) + 27) * 12 + 3; +Constant EXPERIMENT2_TIME = ((11 * 60) + 33) * 12 + 9; + +Constant GAME_LENGTH = FINAL_TIME - EARLIEST_TIME; + +Constant LATER_ = -1; ! A constant to represent a later time + +Constant DEFAULT_SIREN_TIMEOUT = 16; ! the time before the guard arrives +Constant CHALLENGE_SIREN_TIMEOUT = 11; ! 1:20 vs. 0:55 + +Constant TIME_BEFORE_DRAGGED_OFF = 4; ! the time between arrest and removal + +Constant MAX_TIME_TRAVELS = 2; + +! ***************** Important ******************** +! This MUST be set to be equal to 2 to the power of MAX_TIME_TRAVELS + +Constant MAX_ITEM_COPIES = 4; + +! Constants for death states + +Constant ACCELERATED_ = 4; ! brought about the premature destruction of Boston +Constant USELESS_ = 5; ! achieved nothing of consequence +Constant DELAYED_ = 6; ! delayed the destruction by blowing up prototype +Constant SAVED_DEAD_ = 7; ! saved the city but died +Constant SAVED_CAUGHT_ = 8; ! saved the city but caught +Constant SAVED_FREE_ = 9; ! saved the city and free +Constant SAVED_FREE_CHALLENGE_ = 10; ! saved the city and free and completed the challenge +! Constants for object states + +Constant NA_ = -2; +Constant UNKNOWN_ = -1; +Constant LOCKED_ = 0; +Constant CLOSED_ = 1; +Constant OPEN_ = 2; + +! Potentially dangerous actions: + +Constant NONE_ = 0; +Constant LOCK_ = 1; +!Constant OPEN_ = 2; Not needed since defined above +Constant UNLOCK_ = 3; +Constant X_CCTV_ = 4; +Constant X_UPSTAIRS_CORRIDOR_ = 5; +Constant X_UPSTAIRS_LANDING_ = 6; +Constant X_GROUND_CORRIDOR_ = 7; +Constant X_FOYER_ = 8; +Constant X_BASEMENT_CORRIDOR_ = 9; +Constant X_BASEMENT_LANDING_ = 10; +Constant X_BALCONY_ = 11; +Constant TAKE_FLASHLIGHT_ = 12; +Constant BLOW_BASEMENT_LIGHT_ = 13; +Constant SING_ = 14; ! these are not dangerous in the same way +Constant SHOUT_ = 15; ! but need to be caught and replayed + +Global time_travelled; +Global last_travel_time; + +Global d_paradox; +Global d_caught; +Global d_detained; +Global d_escaped; +Global d_exploded; +Global d_killed_by_bomb; +Global d_injured_by_bomb; +Global d_fs_hears_bomb; +Global d_fs_killed_by_bomb; +Global d_destroyed_notes; +Global d_destroyed_prototype; + + !! The moveable items (which can be taken back in time): + +Array bomb --> MAX_ITEM_COPIES; +Array id_card --> MAX_ITEM_COPIES; +Array equipment_key --> MAX_ITEM_COPIES; +Array deutsch_key --> MAX_ITEM_COPIES; +Array flashlight --> MAX_ITEM_COPIES; +Array battery --> MAX_ITEM_COPIES; +Array cable --> MAX_ITEM_COPIES; +Array crowbar --> MAX_ITEM_COPIES; +Array notes --> MAX_ITEM_COPIES; + +Array former_self --> MAX_TIME_TRAVELS; + + + !! The locations of various things at various times + !! These contain an immense amount of info: + !! Location of each copy of that item at each time for each run through + !! Amongst other things, this allows one to recreate the world at a given time + +Array player_loc --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); + +Array bomb_loc --> (GAME_LENGTH + 1) * + (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1); +Array id_card_loc --> (GAME_LENGTH + 1) * + (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1); +Array equipment_key_loc --> (GAME_LENGTH + 1) * + (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1); +Array deutsch_key_loc --> (GAME_LENGTH + 1) * + (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1); +Array flashlight_loc --> (GAME_LENGTH + 1) * + (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1); +Array battery_loc --> (GAME_LENGTH + 1) * + (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1); +Array cable_loc --> (GAME_LENGTH + 1) * + (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1); +Array crowbar_loc --> (GAME_LENGTH + 1) * + (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1); +Array notes_loc --> (GAME_LENGTH + 1) * + (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1); + + !! The states of various things at various times + +Global prototype_fixed_time = UNKNOWN_; +Global siren_start_time = UNKNOWN_; + +Array flashlight_state --> (GAME_LENGTH + 1) * + (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1); +Array bomb_setting --> (GAME_LENGTH + 1) * + (MAX_ITEM_COPIES) * (MAX_TIME_TRAVELS + 1); + +!! activity_target is used to distinguish which door was (dangerously) locked/unlocked/opened + +Array dangerous_activity --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array activity_target --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); + +Array siren_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array panel_setting --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array ground_equipment_light --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array basement_equipment_light --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); + +Array main_doors_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array basement_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array ground_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array upstairs_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array balcony_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array conference_window_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array deutsch_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array basement_equipment_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array ground_equipment_door_state --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); + +Array main_doors_smashed --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array basement_door_smashed --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array ground_door_smashed --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array upstairs_door_smashed --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); +Array balcony_door_smashed --> (GAME_LENGTH + 1) * (MAX_TIME_TRAVELS + 1); + + +Global poem_interleaving = false; +Global initialising = true; +Global first_turn = true; +Global challenge = false; +Global siren_timeout = DEFAULT_SIREN_TIMEOUT; +Global instant_action_this_turn = false; +Global warned_of_jump = false; +Global id_card_used = false; +Global have_looked_at_bench = false; +Global prototype_seen = false; + +!============================================================================ + + + +Include "Parser"; + +Object LibraryMessages +with before [; + Jump: + if (real_location == balcony) { + Jumped(); + return true; + } + "You jump on the spot, fruitlessly."; + Listen: + if ((siren_start_time ~= UNKNOWN_) && (siren_start_time < my_time)) + return true; + else if (Get2D(dangerous_activity, time_travelled-1, my_time-EARLIEST_TIME) == SHOUT_) + return true; + else if (Get2D(dangerous_activity, time_travelled-1, my_time-EARLIEST_TIME) == SING_) + return true; + else + "You can hear nothing but a soft electric hum."; + Burn: + "You have no source of flame."; + Sing: + "You sing out a few clear notes."; + Miscellany: + if (lm_n == 44) + "It is not clear what you are trying to refer to with 'all'."; +]; + +Include "VerbLib"; + + +!============================================================================ + + +! Object classes + +Class Room + with before [t; + Inv, Look: + if (initialising) { + initialising = false; + return false; + } + instant_action_this_turn = true; + return false; + Sing: + for (t=0 : tt notin limbo) && + ((siren_start_time == UNKNOWN_) || (siren_start_time > my_time))) { + + print "You sing out a few clear notes.^"; + d_paradox = true; + deadflag = 3; + Seperator(); + print (Nearby) 0, "your former self hears the muffled sounds of your + singing.^^Something of an anticlimactic way to kill + so many millions of people...^"; + print "^Time unravels...^"; + Devours(my_time); + return true; + } + } + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,SING_); + return false; + ], + each_turn [t i; + first_turn = false; + if (instant_action_this_turn) { + instant_action_this_turn = false; + return true; + } + MoveFloatingObjects(); + my_time++; + if (time_travelled > 0) { + for(i=0 : i < Exp(2,time_travelled-1) : i++) { + MoveObject(bomb, bomb_loc, i); + MoveObject(id_card, id_card_loc, i); + MoveObject(equipment_key, equipment_key_loc, i); + MoveObject(deutsch_key, deutsch_key_loc, i); + MoveObject(flashlight, flashlight_loc, i); + MoveObject(battery, battery_loc, i); + MoveObject(cable, cable_loc, i); + MoveObject(crowbar, crowbar_loc, i); + MoveObject(notes, notes_loc, i); + } + + if (my_time == prototype_fixed_time) + prototype.fixed = true; + + MaybeSetBombs(); + MaybeSetFlashlights(); + MaybeSetPanel(panel_setting); + MaybeSetBasementLight(basement_equipment_light); + MaybeSetGroundLight(ground_equipment_light); + MaybeSetAutomaticDoor(main_doors, main_doors_state); + MaybeSetAutomaticDoor(basement_door, basement_door_state); + MaybeSetAutomaticDoor(ground_door, ground_door_state); + MaybeSetAutomaticDoor(upstairs_door, upstairs_door_state); + + MaybeBreakDoor(main_doors, main_doors_smashed); + MaybeBreakDoor(basement_door, basement_door_smashed); + MaybeBreakDoor(ground_door, ground_door_smashed); + MaybeBreakDoor(upstairs_door, upstairs_door_smashed); + MaybeBreakDoor(balcony_door, balcony_door_smashed); + + MaybeSing(); + MaybeShout(); + +!-- from here down paradox may occur and we need to be able to stop if one occurs if (~~d_paradox)... + + for(t=0 : t < time_travelled : t++) + MoveFormerSelf(t); + + MaybeSetManualDoor(balcony_door, balcony_door_state); + MaybeSetManualDoor(conference_window, conference_window_state); + MaybeSetManualDoor(deutsch_door, deutsch_door_state); + MaybeSetManualDoor(basement_equipment_door, basement_equipment_door_state); + MaybeSetManualDoor(ground_equipment_door, ground_equipment_door_state); + + } + + MaybeCloseAutomaticDoor(main_doors); + MaybeCloseAutomaticDoor(basement_door); + MaybeCloseAutomaticDoor(ground_door); + MaybeCloseAutomaticDoor(upstairs_door); + + ObserveLocations(); + ObserveBombs(); + ObserveFlashlights(); + ObserveSiren(); + ObservePanel(); + ObserveBasementLight(basement_equipment_light); + ObserveGroundLight(ground_equipment_light); + ObserveAutomaticDoor(main_doors, main_doors_state); + ObserveAutomaticDoor(basement_door, basement_door_state); + ObserveAutomaticDoor(ground_door, ground_door_state); + ObserveAutomaticDoor(upstairs_door, upstairs_door_state); + ObserveManualDoor(balcony_door, balcony_door_state); + ObserveManualDoor(conference_window, conference_window_state); + ObserveManualDoor(deutsch_door, deutsch_door_state); + ObserveManualDoor(basement_equipment_door, basement_equipment_door_state); + ObserveManualDoor(ground_equipment_door, ground_equipment_door_state); + + ObserveBrokenDoor(main_doors, main_doors_smashed); + ObserveBrokenDoor(basement_door, basement_door_smashed); + ObserveBrokenDoor(ground_door, ground_door_smashed); + ObserveBrokenDoor(upstairs_door, upstairs_door_smashed); + ObserveBrokenDoor(balcony_door, balcony_door_smashed); + + CheckPassiveParadox(); + CheckActiveParadox(); + + if (~~(Stopped())) { + if (siren_start_time ~= UNKNOWN_) { + if (my_time - siren_start_time == 1) + print "^A piercing siren rings out.^"; + if (my_time - siren_start_time > 1) { + if (my_time - siren_start_time <= siren_timeout) + print "^The siren wails.^"; + else + CaughtInside(); + } + } + if ((my_time > FINAL_TIME) && (~~Stopped())) + CaughtInside(); + } + + if (main_doors.just_closed) main_doors.closing_message(); + if (basement_door.just_closed) basement_door.closing_message(); + if (ground_door.just_closed) ground_door.closing_message(); + if (upstairs_door.just_closed) upstairs_door.closing_message(); + + MaybeExplodeBombs(); + + ], + + has light; + +Class Sight + with before [; + Examine: return false; + Listen: return false; + default: + print_ret "You cannot do that from here."; + ], + has scenery concealed static; + +Class PluralSight + with before [; + Examine: return false; + default: + print_ret "You cannot do that to all of ", (the) self, " at once."; + ], + has scenery concealed static; + +Class Prop + with before [; + Examine: return false; + default: + print_ret "You don't need to worry about ", (the) self, "."; + ], + has scenery concealed static; + + +Class Furniture + with before [; + Take,Pull,Push,PushDir: + print_ret (The) self, " is too heavy for that."; + ], + has static supporter; + + +Class AutomaticDoor + with before [; + Take,Pull,Push,PushDir: + print_ret (The) self, " is locked in place."; + Lock: + Close: + "Like most automatic doors, this one closes of its own accord."; + Attack: + if (AmHolding(crowbar)) { + print "You swing the crowbar firmly into the door. It shudders, + a star of cracks reaching out from the point of impact, + but the glass stays in place.^"; + self.smashed = true; + StartSiren(); + return true; + } + else + "You don't have anything heavy enough to smash the door with."; + Search: + <>; + ], + just_closed false, + smashed false, + to_close_at UNKNOWN_, + open_self [t; + if (self hasnt open) { + give self open ~locked; + if (self in LocationOf(player)) + print "The door slides open with a soft rattle.^"; + } + self.to_close_at = t; + ], + close_self [; + give self ~open locked; + self.to_close_at = UNKNOWN_; + self.just_closed = true; + ], + closing_message [; + if ((~~Stopped()) && (self in LocationOf(player))) + "The automatic door softly slides closed."; + ], + has static door openable locked; + +Class ManualDoor + with name 'door' 'to' 'the', + before [; + Take,PushDir: + print_ret (The) self, " is locked in place."; + Attack: + if (AmHolding(crowbar)) { + print "You swing the crowbar firmly into the door, + but it barely leaves a mark.^"; + return true; + } + else + "You don't have anything heavy enough to break the door with."; + ], + react_before [; + Go: if (noun.door_dir() == self.door_dir()) + return self.open_by_myself(); + if (noun.door_dir() == out_to) !! XX hack, going 'out' always uses door in this game + return self.open_by_myself(); + Enter: + if (noun == self) return self.open_by_myself(); + ], + open_by_myself [ ks; + if (self has open) + rfalse; + print "(first opening ", (the) self, ")^"; + ks = keep_silent; + keep_silent = true; + ; + keep_silent = ks; + if (self hasnt open) + rtrue; + else { + IncTime(); + if (Stopped()) return true; + } + ], + has static door openable lockable; + + +[LockUnlockParadox; + d_paradox = true; + deadflag = 3; + Seperator(); + print "On the other side of the door, your former self hears you turn the + key in the lock.^"; + print "^Time unravels...^"; + Devours(my_time); +]; + +[OpenParadox; + d_paradox = true; + deadflag = 3; + Seperator(); + print "On the other side, your former self sees the door open in front + of her.^"; + print "^Time unravels...^"; + Devours(my_time); +]; + +[CloseParadox; + d_paradox = true; + deadflag = 3; + Seperator(); + print "On the other side, your former self sees the door close in front + of her.^"; + print "^Time unravels...^"; + Devours(my_time); +]; + +[OpenManualDoor door ks; + if (door has locked) { + if (door.with_key_type == nothing + || ~~AmHolding(door.with_key_type)) + "Try as you might, none of your keys will unlock the door."; + print "(first unlocking ", (the) door, ")^"; + ks = keep_silent; + keep_silent = true; + ; + keep_silent = ks; + if (door has locked) + return true; + else { + IncTime(); + if (Stopped()) return true; + } + } + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,OPEN_); + Put2D(activity_target,time_travelled,my_time-EARLIEST_TIME,door); + return false; +]; + +[UnlockManualDoor door key; + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,UNLOCK_); + Put2D(activity_target,time_travelled,my_time-EARLIEST_TIME,door); + if (door has locked) { + if ( IsOfType(key,door.with_key_type) ) { + give door ~locked; + if (~~keep_silent) + print (The) key, " turns smoothly in the lock.^"; + return true; + } + else + "It does not fit in the lock."; + } + return false; +]; + +[LockManualDoor door key ks; + if (door has open) { + print "(first closing ", (the) door, ")^"; + ks = keep_silent; + keep_silent = true; + ; + keep_silent = ks; + if (door has open) + rtrue; + IncTime(); + if (Stopped()) return true; + } + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,LOCK_); + Put2D(activity_target,time_travelled,my_time-EARLIEST_TIME,door); + if (door hasnt locked) { + if ( IsOfType(key,door.with_key_type) ) { + give door locked; + if (~~keep_silent) + print (The) key, " turns smoothly in the lock.^"; + return true; + } + else + "It does not fit in the lock."; + } + return false; +]; + + +Class FakeDoor + with name 'door' 'to' 'the', + before [; + Take,PushDir: + print_ret (The) self, " is locked in place."; + Unlock: + if (IsOfType(second,crowbar)) + <>; + Attack: + if (AmHolding(crowbar)) { + print "You swing the crowbar firmly into the door, + but it barely leaves a mark.^"; + return true; + } + else + "You don't have anything heavy enough to break the door with."; + Enter: + "The door is locked."; + ], + door_to nothing, + door_dir nothing, + with_key_type nothing, + has static door openable lockable locked; + + +!============================================================================ + +! the moveable objects (defined as classes) +! with trailing _ to avoid ambiguity with individual item names + + +Class Bomb_(MAX_ITEM_COPIES) + with short_name "timed explosive device", + plural "timed explosive devices", + description [t i; + print "A length of steel pipe filled with powder and fused with a digital timer. + Not your most elegant piece of work, but it will + hopefully do the job.^"; + t = (self.time_value - my_time) * 5 + self.left_over_seconds; + if (self.time_value == NA_) + print "^You have not yet set the timer.^"; + else { + if (t == -4) + print "^On the timer's small LED screen, the number 0 + blinks out at you.^"; + else { + print "^On the timer's small LED screen, the numbers "; + for (i = t+4 : (i>t) && (i>0) : i--) + print i, ", "; + if (t < 0) + print 0; + else + print t; + print "... blink out at you insistently, illuminating + the room with faint blue-green flashes.^"; + } + } + ], + name 'time' 'timed' 'explosive' 'device' 'bomb' 'timebomb' 'C4' + 'timer' 'digital' 'pipe' + 'devices//p' 'bombs//p' 'timebombs//p' 'timers//p', + time_value NA_, + left_over_seconds 0, + before [; + Set: + print "To set the explosive device, + you need to specify a number of seconds, + for example, with 'set timer to 30'.^"; + return true; + SetTo: + if (self.time_value ~= NA_) { + print "(first resetting the timer)^"; + self.time_value = NA_; + } + if (second > 0 && second <= 100) { + self.time_value = my_time + (second/5); + self.left_over_seconds = second%5; + print "Time until detonation: ", (self.time_value - my_time) * 5 + + self.left_over_seconds; + print " seconds.^"; + if (parent(self) == player) + print "(you probably don't want to be carrying the device + when that occurs...)^"; + } + else { + print "Your timer only accepts between 1 and + 100 seconds.^"; + } + return true; + Reset: + if (self.time_value ~= NA_) { + self.time_value = NA_; + "You reset the timer."; + } + else + "The timer is not currently set."; + ], + has ; + +Class IDCard_(MAX_ITEM_COPIES) + with short_name "ID card", + plural "ID cards", + description "Natalie Williams.^ + Deutsch Lab.^ + Doctoral Student, MIT^ + ^ + On the right is a familiar photo of you, back when you + wore your hair long. + A black magnetic stripe runs the width of the reverse.", + name 'id' 'card' 'cards', + before[; Insert: + if (second == id_slot){ + if (second in foyer or upstairs_landing) { + "The slot emits a small beep and your card is rejected."; + } + if (second in basement_landing) { + if (~~id_card_used) { + print "You swipe your card through the slot, and hold your breath.^"; + basement_door.open_self(my_time+1); + print "Perfect. Just as you'd hoped. + The bastards hadn't even thought to disable your card.^"; + id_card_used = true; + } + else + basement_door.open_self(my_time+1); + return true; + } + } + if (second == ground_door or upstairs_door + && player in foyer or upstairs_landing) { + "The slot emits a small beep and your card is rejected."; + } + if ((second == basement_door) && (player in basement_landing)) { + basement_door.open_self(my_time+1); + return true; + } + ], + has ; + +Class Crowbar_(MAX_ITEM_COPIES) + with short_name "crowbar", + plural "crowbars", + name 'crow' 'bar' 'crowbar' 'black' 'crowbars//p' 'bars//p', + description "A curved black crowbar.", + has; + +Class Flashlight_(MAX_ITEM_COPIES) + with short_name "flashlight", + plural "flashlights", + name 'flashlight' 'torch' 'flashlights//p' 'torches//p' + 'flash' 'metallic' 'blue' 'metallic-blue', + description "A small metallic-blue flashlight.", + capacity 2, + before [; + SwitchOn: + if (self has on) + "That's already on."; + if (BatteriesContained(self) == 2) { + give self on; + if (real_location == basement_equipment || + (real_location == ground_equipment && ground_equipment.lit == false)) { + ; + instant_action_this_turn = false; + return true; + } + else + "A thin beam of icy light shines forth."; + } + if (BatteriesContained(self) == 1) { + "The switch clicks, but no light is forthcoming. + It looks as if you will need two batteries."; + } + if (BatteriesContained(self) == 0) { + "The switch clicks, but no light is forthcoming. + Not surprising considering flashlights usually need batteries."; + } + SwitchOff: + if (player in basement_equipment) + MoveMoveableChildren(basement_equipment,basement_equipment_gloom); + else if ((player in ground_equipment) && (ground_light_switch hasnt on)) + MoveMoveableChildren(ground_equipment,ground_equipment_gloom); + Receive: + if (~~IsOfType(noun,battery)) + print_ret (The) noun, " won't fit in the flashlight."; + Take: + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,TAKE_FLASHLIGHT_); + return false; + ], + after [; + LetGo: + if (self has on) { + print "As you remove the battery, the light fails.^"; + give self ~on; + if (player in basement_equipment) + MoveMoveableChildren(basement_equipment,basement_equipment_gloom); + else if ((player in ground_equipment) && (ground_light_switch hasnt on)) + MoveMoveableChildren(ground_equipment,ground_equipment_gloom); + return false; + } + ], + has container open switchable; + +Class Battery_(MAX_ITEM_COPIES) + with short_name "battery", + plural "batteries", + name 'battery' 'batteries//p' 'AA', + description "An AA sized battery.", + before [; + Remove: + <>; + ], + has; + +Class Cable_(MAX_ITEM_COPIES) + with short_name "length of ribbon cable", + plural "lengths of ribbon cable", + name 'cable' 'wire' 'cables//p' 'wires//p' 'ribbon' 'length' 'lengths//p' 'of', + description "A 10cm length of ribbon cable. It will do nicely.", + before[; + Tie: + if (second == control_panel or prototype) + <>; + if (second == nothing) + if (real_location == deutsch_lab or prototype_interior) + <>; + else + "There is nothing here that you could attach the cable to."; + else + "You cannot attach the cable to that."; + ], + has; + +Class Notes_(MAX_ITEM_COPIES) + with short_name "collection of notes", + plural "collections of notes", + name 'collection' 'notes' 'collections//p', + description "Your research notes. The hundred or so pages here comprise + everything you have written so far. It would not be easy for + someone else to turn the scribbles herein into another working + prototype, but it may just be possible.", + before[; + Eat: + "You look determinedly at the thick bundle of papers, but there is no + way that you could eat more than a couple of pages. You had better think + of something a little more sensible."; + Attack, Cut: + "There are about a hundred pages and there is no way that you could tear them + up in time."; + ], + has; + +Class EquipmentKey_(MAX_ITEM_COPIES) + with short_name "worn brass key", + plural "worn brass keys", + name 'key' 'equipment' 'brass' 'worn' 'keys//p', + description "A well worn brass key. It opens the various + equipment rooms in the complex.", + has; + +Class DeutschKey_(MAX_ITEM_COPIES) + with short_name "bright steel key", + plural "bright steel keys", + name 'key' 'deutsch' 'steel' 'bright' 'keys//p', + description "A bright steel key. It unlocks the door to the Deutsch lab, downstairs.", + has; + +Class FormerSelf_(MAX_ITEM_COPIES) + with short_name "your former self", + plural "your former selves", + name 'self' 'former' 'past' 'selves//p', + description "She looks strangely familiar.", + has animate proper container concealed; + + +!=============================================================================== +! The one-of-a-kind moveable objects + +Object myselfobj "(self object)" + with + short_name "yourself", + description "Dark hair frames a warm face. Despite the anxiety written now in your + tense brow, the confidence of youth and vibrancy of intellect are clear. + There is a depth in your clear green eyes.", + capacity 100, + number 0, + orders 0, + weakness 0, + has concealed animate proper transparent; + + +Object skeleton_key "skeleton key (fake item to neaten code)" + with + name 'key' 'skeleton', + description "A skeleton key. And I thought they were make-believe!", + has; + + +!=============================================================================== +! The rooms + +!----------------------------------------------- +! Generic props and sights: + +Prop walls "walls" + with name 'wall' 'walls', + found_in [; + if (location ~= prototype_interior) + return true; + else + return false; + ], + has ; + +Prop floor "floor" + with name 'floor' 'ground' 'carpet', + description "The floor is covered by a thin carpet in a dark but warm gray.", + found_in [; + if ((location ~= balcony) && (location ~= prototype_interior)) + return true; + else + return false; + ], + has ; + +Prop ceiling "ceiling" + with name 'ceiling', + found_in [; + if (location ~= prototype_interior) + return true; + else + return false; + ], + has ; + +Sight darkness "darkness" + with name 'darkness' 'dark' 'gloom', + description "You cannot see what lies in the darkness.", + before [; + Examine: + Listen: + return false; + default: + "It is not clear what you mean."; + ], + found_in [; + return true; + ], + has ; + +Sight shadows "shadows" + with name 'shadows' 'shadow' 'corners' 'cobwebs', + description "Shadows fill the corners of the rooms like old cobwebs.", + before [; + Examine: + Listen: + return false; + default: + "It is not clear what you mean."; + ], + found_in [; + return true; + ], + has ; + +Sight complex "complex" + with name 'complex' 'building' 'surface' 'surfaces' 'texture' 'textures', + description "The building has modern but ultimately shallow feel. + There is a preoccupation with surfaces and textures. + Almost everything is coloured with dark, yet somewhat warm, shades of gray, + darkened further by the midnight gloom.", + before [; + Examine: + Listen: + return false; + default: + "It is not clear what you mean."; + ], + found_in [; + return true; + ], + has ; + +Prop lights "lights" + with name 'lights' 'light' 'fluorescent', + description "Most of the overhead lights are currently off, leaving the complex in dim half-light.", + before [; + SwitchOn: + "Switching on the overhead lights would alert security to your presence, and besides, you + can see clearly enough in the gloom."; + ], + found_in [; + if ((location ~= balcony) && (location ~= prototype_interior) && + (location ~= basement_equipment) && (location ~= ground_equipment)) + return true; + else + return false; + ], + has ; + +Prop stairs "stairs" + with name 'stairs' 'staircase', + before [; + Climb: + if (self in foyer or basement_landing) + <>; + if (self in upstairs_landing) + "You are already at the top of the stairs."; + ], + found_in basement_landing foyer upstairs_landing, + has ; + +!----------------------------------------------- +! Item-related props and sights: + +Prop beam "flashlight beam" + with name 'beam' 'blue-white' 'blue' 'white', + description "A thin icy beam that cuts through the darkness.", + found_in [; + if (Flashlit()) + return true; + else + return false; + ], + has ; + +Prop photo "photograph" + with name 'photo' 'photograph' 'long' 'hair', + description "You look young, bright and proud of + your new position at the lab.", + found_in [; + if (AmHolding(id_card) || IsIn(id_card,real_location)) + return true; + else + return false; + ], + has ; + +Prop stripe "magnetic stripe" + with name 'stripe' 'magnetic' 'reverse' 'back', + description "It is the type of magnetic stripe found on the back of a regular credit card, + but is used to open the automatic doors in the building.", + found_in [; + if (AmHolding(id_card) || IsIn(id_card,real_location)) + return true; + else + return false; + ], + has ; + +!----------------------------------------------- + +Room foyer "Foyer" + with name 'foyer', + description + "A darkened foyer, presided over by a security desk near the north wall. + Floating above it in the capacious darkness is + a small landing. A set of stairs both rises up to meet it + and stretches downwards into the dark.", + u_to upstairs_landing, + d_to basement_landing, + n_to ground_door, + s_to main_doors, + cant_go "The only exits are the automatic doors to the north and south, + and the staircases up and down.", + lower_name "the foyer", + has ; + +Furniture security_desk "security desk" foyer + with description "A large black desk equipped with four CCTV screens showing + live feeds from around the complex. ", + before [; + Examine: + print "A large black desk equipped with four CCTV screens showing + live feeds from around the complex. "; + cctv_screens.display(); + print "There are also four buttons, labeled 'basement', + 'first', 'second' and 'alarm'.^"; + return true; + ], + name 'desk' 'security' 'black' 'table', + has scenery; + +Object cctv_screens "CCTV images" foyer + with description [; + print "These screens flash images from the corridors and grounds + of the complex. "; + self.display(); + print "^"; + ], + name 'images' 'CCTV' 'screen' 'screens' 'feed' 'feeds' 'image', + display [; + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_CCTV_); + + if ((my_time == start_time - 1) || (my_time == start_time - 2)) + print "On one of the screens you see your former self approaching the + complex. "; + if (IsIn(former_self,ground_corridor)) + print "On one of the screens you see your former self in the first + floor corridor. "; + if (IsIn(former_self,upstairs_corridor)) + print "On one of the screens you see your former self in the second + floor corridor. "; + if (IsIn(former_self,basement_corridor)) + print "On one of the screens you see your former self in the basement + corridor. "; + ], + has scenery concealed; + + +Object alarm_button "alarm button" foyer + with description "A discrete black button carefully labeled 'alarm'.", + name 'alarm' '^alarm^' 'button' 'black' 'labeled' 'marked', + before [; + Push: + StartSiren(); + return true; + Receive: + "The button is set into a vertical surface, making it impossible + to place objects on top of it."; + ], + has scenery concealed; + +Object first_button "'first' button" foyer + with description "A small black button carefully labeled 'first'.", + name 'first' '^first^' 'floor' 'button' 'black' 'labeled' 'marked', + before [; Push: + ground_door.open_self(my_time+1); + ground_door.known_exterior_opening = true; + return true; + Receive: + "The button is set into a vertical surface, making it impossible + to place objects on top of it."; + ], + has scenery concealed; + +Object basement_button "'basement' button" foyer + with description "A small black button carefully labeled 'basement'.", + name 'basement' '^basement^' 'floor' 'button' 'black' 'labeled' 'marked', + before [; Push: + basement_door.open_self(my_time+1); + "Nothing obvious happens."; + Receive: + "The button is set into a vertical surface, making it impossible + to place objects on top of it."; + ], + has scenery concealed; + +Object second_button "'second' button" foyer + with description "A small black button carefully labeled 'second'.", + name 'second' '^second^' 'floor' 'button' 'black' 'labeled' 'marked', + before [; Push: + upstairs_door.open_self(my_time+1); + "Nothing obvious happens."; + Receive: + "The button is set into a vertical surface, making it impossible + to place objects on top of it."; + ], + has scenery concealed; + +Sight upstairs_landing_from_foyer "upstairs landing" foyer + with description "The landing above is lost in shadow.", + name 'upstairs' 'landing', + has ; + +Sight outside_from_foyer "outside" foyer + with description "The grounds are empty and still on this frosty night.", + name 'grounds' 'outside' 'night', + has ; + +Sight ground_corridor_from_foyer "corridor" foyer + with description [;<>;], + name 'corridor', + has ; + +!----------------------------------------------- + +Room basement_landing "Basement Landing" + with name 'landing', + description + "A cramped space at the bottom of the stairs. + A corridor can be seen to the north through the automatic door, + and the stairs lead back up to the foyer.", + u_to foyer, + n_to basement_door, + cant_go "The only exits are north and up.", + lower_name "the basement landing", + has ; + +Sight foyer_from_basement_landing "foyer" basement_landing + with description "You cannot see the foyer properly from here.", + name 'foyer' 'upstairs', + has ; + +!----------------------------------------------- + +Room upstairs_landing "Upstairs Landing" + with name 'landing', + description + "A small landing, hanging in the still darkness above the foyer.", + d_to foyer, + n_to upstairs_door, + cant_go "The only exits are north and down.", + lower_name "the upstairs landing", + has ; + +Sight foyer_from_upstairs_landing "Foyer" upstairs_landing + with description [; + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_FOYER_); + if (IsIn(former_self,foyer)) { + "From the shadowy landing, you can just make out your former + self alone in the foyer."; + } + else + "From the shadowy landing, you can see much of the empty + foyer stretching out below you."; + ], + name 'foyer', + has ; + +!----------------------------------------------- + +Room ground_corridor "First Floor Corridor" + with name 'first' 'floor' 'ground' 'corridor', + description [; + print "A long north-south corridor, much the same as + those on the other floors. "; + print "Three gray doors line the eastern wall. The first two have small + glass windows, peering into darkened laboratories. The third "; + if (ground_equipment_door has open) + print "is open onto an equipment room.^"; + else + print "is plain and leads to a small equipment room. All three are closed.^"; + ], + s_to ground_door, + se_to saunders_door, + e_to pooley_door, + ne_to ground_equipment_door, + cant_go "The only exits are the three doors lining + the corridor (south-east, east and north-east) and the automatic door + back to the foyer (south).", + lower_name "the first floor corridor", + has ; + +FakeDoor saunders_door "door to the Saunders Lab" ground_corridor + with name 'door' 'grey' 'gray' 'saunders' 'first' 'lab' 'se' 'south-east', + description "A gray door with a small glass window, + looking into a darkened lab. + A small plaque reads: 'Saunders Lab'.", + has locked scenery; + +FakeDoor pooley_door "door to the Pooley Lab" ground_corridor + with name 'door' 'grey' 'gray' 'pooley' 'second' 'lab' 'e\\' 'east', + description "A gray door with a small glass window, + looking into a darkened lab. + A small plaque reads: 'Pooley Lab'.", + has locked scenery; + +Prop door_window "small glass window" + with name 'small' 'glass' 'window' 'windows', + description "You can't see anything of interest through the glass.", + before [; + Take,PushDir: + print_ret (The) self, " is fixed in the door."; + Unlock: + if (IsOfType(second,crowbar)) + <>; + else + "The embedded window does not open."; + Open: + "The embedded window does not open."; + Attack: + if (AmHolding(crowbar)) { + print "You swing the crowbar firmly into the small window, + but it barely leaves a mark.^"; + return true; + } + else + "You don't have anything heavy enough to break the window with."; + Search: + <>; + ], + found_in ground_corridor basement_corridor, + has scenery concealed lockable; + +PluralSight doors_in_ground_corridor "doors" ground_corridor + with name 'doors', + description [; + print "There are three doors on the eastern wall of the corridor, + the first two (to the south-east and east) lead to the Saunders + and Pooley labs. The third (to the north-east) "; + if (ground_equipment_door has open) + print "is open and "; + print "leads to a small equipment room. To the south, the plate glass + automatic door to the foyer "; + if (ground_door has open) + print "lies open.^"; + else + print "stands closed.^"; + ], + has pluralname; + +!----------------------------------------------- + +Room basement_corridor "Basement Corridor" + with name 'basement' 'corridor', + description [; + print "A long north-south corridor, much the same as + those on the other floors. "; + print "Three gray doors line the eastern wall. The first two have small + glass windows, peering into darkened laboratories. The third "; + if (basement_equipment_door has open) + print "is open onto an equipment room.^^"; + else + print "is plain and leads to a small equipment room. All three are closed.^^"; + if (deutsch_door has open) + print "At the north end is an + open door leading to the Deutsch lab.^"; + else + print "At the north end a fourth door leads to + the Deutsch lab.^"; + ], + s_to basement_door, + se_to bostrom_door, + e_to wallace_door, + ne_to basement_equipment_door, + n_to deutsch_door, + cant_go "The only exits are to the Deutsch lab (north) the three doors lining + the corridor (south-east, east and north-east) and the automatic door + back to the landing (south).", + lower_name "the basement corridor", + has ; + +FakeDoor bostrom_door "door to the Bostrom Lab" basement_corridor + with name 'door' 'grey' 'gray' 'bostrom' 'first' 'lab' 'se' 'south-east', + description "A gray door with a small glass window, + looking into a darkened lab. + A small plaque reads: 'Bostrom Lab'.", + has locked scenery; + +FakeDoor wallace_door "door to the Wallace Lab" basement_corridor + with name 'door' 'grey' 'gray' 'wallace' 'second' 'lab' 'e\\' 'east', + description "A gray door with a small glass window, + looking into a darkened lab. + A small plaque reads: 'Wallace Lab'.", + has locked scenery; + +PluralSight doors_in_basement_corridor "doors" basement_corridor + with name 'doors', + description [; + print "There are three doors on the eastern wall of the corridor, + the first two (to the south-east and east) lead to the Bostrom + and Wallace labs. The third (to the north-east) "; + if (basement_equipment_door has open) + print "is open and "; + print "leads to a small equipment room. At the north end is the "; + if (deutsch_door has open) + print "open "; + print "door to the Deutsch lab. "; + print "To the south, the plate glass automatic door to the landing "; + if (basement_door has open) + print "lies open.^"; + else + print "stands closed.^"; + ], + has pluralname; + +!----------------------------------------------- + +Room upstairs_corridor "Second Floor Corridor" + with description + "A long north-south corridor, much the same as + those on the other floors. Three plain gray doors line the eastern wall.", + n_to balcony_door, + ne_to conference_door, + e_to butterfield_door, + se_to brown_door, + s_to upstairs_door, + cant_go "The only exits are to the balcony (north) the three doors lining + the corridor (south-east, east and north-east) and the automatic door + back to the landing (south).", + lower_name "the second floor corridor", + has ; + +FakeDoor brown_door "door to Dr Brown's office" upstairs_corridor + with name 'door' 'grey' 'gray' 'brown' 'office' 'brown^s' 'Dr' 'first' 'se' 'south-east', + description "A simple gray door. + A small plaque reads: 'Dr Brown'.", + has locked scenery; + +FakeDoor butterfield_door "door to Professor Butterfield's office" upstairs_corridor + with name 'door' 'office' 'grey' 'gray' 'butterfield' 'butterfield^s' 'Prof' 'second' + 'e\\' 'east', + description "A simple gray door. + A small plaque reads: 'Prof Butterfield'.", + has locked scenery; + +FakeDoor conference_door "door to the conference room" upstairs_corridor + with name 'door' 'grey' 'gray' 'conference' 'third' 'ne' 'north-east', + description "A plain gray door. + A small plaque reads: 'Conference Room'.", + found_in upstairs_corridor conference_room, + has locked scenery; + +PluralSight doors_in_upstairs_corridor "doors" upstairs_corridor + with name 'doors', + description [; + print "There are three doors on the eastern wall of the corridor, + the first two (to the south-east and east) lead to Dr Brown + and Professor Butterfield's offices. The third (to the north-east) + leads to the conference room. At the north end is the "; + if (balcony_door has open) + print "open "; + print "glass door to the balcony. "; + print "To the south, the plate glass automatic door to the landing "; + if (upstairs_door has open) + print "lies open.^"; + else + print "stands closed.^"; + ], + has pluralname; + +!----------------------------------------------- + +Room deutsch_lab "The Deutsch Laboratory" + with name 'lab' 'deutsch' 'laboratory', + description [; + if (self hasnt visited) { + print "The lab is order and chaos. By the dim blue-green light of a few swirling + screen savers, you can see the cluttered benches of your colleagues, frozen in the + mess of academic creativity. Frozen exactly as they were when badges were flashed, + when we looked on in disbelief as they took control of the lab. Yours however, is clean. + The books and papers are in neat stacks. They have been working here.^ + ^ + Nearby, against the north wall is the prototype, a six foot cylinder of brushed steel cladding. + The door has been taken off and is nowhere to be seen. They have been working on it too. + You wince at the sight.^"; + + if (deutsch_door has open) + print "^To the south, the door to the lab lies open.^"; + else + print "^To the south, the door to the lab stands closed.^"; + + return true; + } + print "The lab is order and chaos. By the dim blue-green light of a few swirling + screen savers, you can see the cluttered benches of your colleagues, frozen in the + mess of academic creativity. Yours however, is clean. + The books and papers are in neat stacks. They have been working here.^ + ^ + Nearby, against the north wall is the prototype, a six foot cylinder of brushed steel cladding. + They have been working on it too. + The door has been taken off and is nowhere to be seen.^"; + + if (deutsch_door has open) + "^To the south, the door to the lab lies open."; + else + "^To the south, the door to the lab stands closed."; + ], + out_to deutsch_door, + s_to deutsch_door, + in_to prototype_interior, + cant_go "The only exits are to the south and in to the prototype.", + lower_name "the Deutsch laboratory", + has proper; + + +Object prototype "prototype" + with description [; + if (~~prototype_seen) { + prototype_seen = true; + print "You had built the prototype to get a strong negative result, + to show that the standard model of Quantum Mechanics + led to demonstrably false claims involving reverse causation. You were mistaken. + One by one, your experiments showed your preliminary calculations to have been correct. + When the military removed you from your project, only one aspect + remained untested -- an aspect + you had been loath to test before you could predict the results -- inconsistent observation.^ + ^ + What would happen if anomalies were observed by those in the original + time-line? Your prior experiments had heavily shielded the prototype from outside interaction + to avoid the very possibility. And as the calculations came out time and again, + that is the only reason you are alive today. + When an observer in the original time-line has an anomalous observation, the wave + function of the temporally relocated object collapses and the relocation retrospectively fails, + preserving chronological consistency. There is just one side effect: + total transformation of the object's mass into a burst of photons -- pure energy.^ + ^ + You tried to tell them over and again. They assumed you were merely jealous of the takeover. + Now, the night before their scheduled 'first main experiment', you have come to + put an end to it all. To destroy your prototype and avoid tomorrow's nightmare.^ + ^ + The prototype itself is a six foot tall, four foot wide cylinder, clad with + brushed steel. The frame and door were fitted with quantum shielding + to prevent decoherence of the wave function, but now the door has been + removed and any use of the machine is potentially disastrous.^"; + } + else + print "The prototype is a six foot tall, four foot wide cylinder clad with + brushed steel. The frame and door were fitted with quantum shielding + to prevent decoherence of the wave function, but now the door has been + removed and any use of the machine is potentially disastrous.^"; + if (~~(self.fixed)) + "^On close inspection, it appears that an attempt is in progress + to move the control panel so that it can be operated from the inside. + As it is, the prototype is currently not functioning, but you think + you could probably complete the modification within a minute or two."; + return true; + ], + name 'prototype' 'time' 'machine' 'six' 'foot' 'cylinder', + fixed, + before [t; + Set: + if (self.fixed) { + if (self in deutsch_lab) + "The prototype has been modified so that the only way to operate it is + to enter it and use the internal control panel."; + if (self in prototype_interior) + <>; + } + else + "You will need to complete the partial modifications to use the prototype."; + SetTo: + if (self.fixed) { + if (self in deutsch_lab) + "The prototype has been modified so that the only way to operate it is + to enter it and use the internal control panel."; + if (self in prototype_interior) + <>; + } + else + "You will need to complete the partial modifications to use the prototype."; + SwitchOn: + if (self.fixed) { + if (self in deutsch_lab) + "The prototype has been modified so that the only way to operate it is + to enter it and use the internal control panel."; + if (self in prototype_interior) { + print "(pressing the silver button)^"; + <>; + } + } + else + "You will need to complete the partial modifications to use the prototype."; + Enter: + <>; + Exit: + if (real_location == prototype_interior) + <>; + Tie: + if (~~d_paradox) { + if (second == nothing) { + if (self.fixed) + "It is already fixed."; + if (AmHolding(cable)) { + if (self in deutsch_lab) { + print "(first entering the prototype)^"; + ; + IncTime(); + if (Stopped()) return true; + print "^"; + } + move GetHeld(cable) to limbo; + print "You begin work completing the modifications...^"; + for (t=0 : t<10 : t++) { + IncTime(); + if (Stopped()) return true; + } + self.fixed = true; + prototype_fixed_time = my_time; + print "After a minute or so, you are done.^"; + return true; + } + else + "After a few moments, you realise that completing the modification + will require a ribbon cable to connect the components. You know the + type of cable well, but don't have any in the lab right now. + Still, the equipment room in the corridor should have one."; + } + } + Attack: + "It won't be enough to smash the prototype by hand as there are too many + circuits buried away inside that would not be harmed. + Besides, that is why you brought the bomb."; + Search: + if (self in deutsch_lab) { + print "(first entering the prototype)^"; + <>; + } + else + <>; + ], + react_before[; + Insert: + if (~~(self.fixed)) + if (IsOfType(noun,cable)) + if ((second == self) || (second == control_panel)) + <>; + if (second == self) { + if (noun == self) + "It wont fit. Obviously. What were you thinking? It is a prototype + chrono-transference device, not some kind of TARDIS."; + if (self in deutsch_lab) { + move noun to prototype_interior; + print "You reach in and place ", (the) noun, " inside the prototype.^"; + return true; + } + else + <>; + } + ], + found_in deutsch_lab prototype_interior, + has scenery concealed; + +Furniture bench "your bench" deutsch_lab + with description "Your bench has clearly been used recently, and not by you.", + before [; + Examine: + print "Your bench has clearly been used recently, and not by you. + Your books and papers are neatly piled to one side, leaving + the largest expanse of bare desk you have ever seen here.^"; + if (~~have_looked_at_bench) { + have_looked_at_bench = true; + "^You suddenly notice that your research notes are not here. + You were sure they would be -- and would thus be destroyed in the blast. + This is bad. Very bad."; + } + return true; + Search: + <>; + ], + name 'bench' 'your' 'benches' 'table' 'desk', + has scenery proper; + +Prop books "text books" deutsch_lab + with description "A few texts on Quantum Mechanics and String Theory + that have served you very well.", + name 'books' 'book' 'texts', + has; + +Prop papers "papers" deutsch_lab + with description [; + print "A collection of photocopied journal papers that you had been reading + a few weeks ago.^"; + if (~~have_looked_at_bench) { + have_looked_at_bench = true; + "^You suddenly notice that your research notes are not here. + You were sure they would be -- and would thus be destroyed in the blast. + This is bad. Very bad."; + } + return true; + ], + name 'papers' 'photocopies' 'stack' 'stacks', + has; + +Prop screen_savers "screen savers" deutsch_lab + with description "Abstract, organic shapes leave glowing phosphor trails as they swirl around + and through themselves.", + name 'screen' 'screens' 'saver' 'savers' 'computer' 'computers' 'light' 'violet' 'green' 'blue' + 'blue-green' 'swirling', + has; + +Prop cladding "cladding" deutsch_lab + with name 'cladding' 'steel' 'brushed' 'frame' 'hatch', + has; + +Prop mess "mess" deutsch_lab + with description "The usual academic mess -- open books, coffee stained mugs, sprawling papers + -- frozen in time.", + name 'mess' 'chaos', + has; + +Sight control_panel_from_lab "control panel" deutsch_lab + with description "You cannot see the control panel clearly from here, and would need to enter the prototype.", + name 'control' 'panel', + before [; + Push: + <>; + Examine: + "You cannot see the control panel clearly from here, and would need to enter the prototype."; + default: + "You would have to enter the prototype to do that."; + ], + has; + +!----------------------------------------------- + +Room prototype_interior "Inside the prototype" + with description [; + if (prototype.fixed) { + print "The interior of the prototype is cramped and dark. + On the wall you see the control panel with a small LED timer + set to ", control_panel.time_value, " seconds, and a silver button. + Through the open hatch you can see some of the Deutsch lab.^"; + } + else + "The interior of the prototype is cramped and dark. + On the wall you can see the half-installed control panel. + Through the open hatch you can see some of the Deutsch lab."; + ], + name 'prototype' 'time' 'machine' 'interior', + out_to deutsch_lab, + lower_name "the prototype", + cant_go "The only exit is out to the Deutsch lab.", + has proper; + +Object control_panel "control panel" prototype_interior + with name 'control' 'panel' 'led' 'timer' 'time' 'screen', + description [; + print "A brushed steel control panel with a blue LED timer, set to ", + control_panel.time_value, " seconds, and a shiny silver button.^"; + ], + time_value, + before [; + Push: + <>; + Set: + if (prototype.fixed) + "To set the control panel, + you need to specify a number of seconds, + for example, with 'set panel to 75'."; + else + "You won't be able to set the control panel + until you complete the modifications."; + SetTo: + if (prototype.fixed) { + if (second > 0 && second <= 500) { + self.time_value = second; + "You quickly type the number in to the control panel."; + } + else { + "The prototype's control panel only accepts + between 1 and 500 seconds."; + } + } + else + "You won't be able to set the control panel + until you complete the modifications."; + SwitchOn: + if (self.fixed) { + print "(pressing the silver button)^"; + <>; + } + else + "You will need to complete the partial modifications to use the prototype."; + ], + has scenery concealed; + +Object silver_button "silver button" prototype_interior + with name 'button' 'silver' 'silvered', + description "A silvered button.", + before [old_value t; + Push: + if (prototype.fixed) { + if (control_panel.time_value == 0) + "The control panel emits a small beep and the number '0' + flashes out at you. Perhaps you should set it first."; + else if (time_travelled < MAX_TIME_TRAVELS) { + old_value = control_panel.time_value; + TravelThroughTime(control_panel.time_value); + if (deadflag) + return true; + for (t=0 : t < time_travelled : t++) + if ((Get2D(player_loc,t,my_time-EARLIEST_TIME) == deutsch_lab) || + (Get2D(player_loc,t,my_time-EARLIEST_TIME) == prototype_interior)) + "You hold your breath and activate the prototype."; + ! this is needed to avoid silly message below, then death + if ((old_value % 5) ~= 0) + "You pause for a moment after pressing the button, + carefully resynchronizing yourself with the + five second turn increments."; + else + "You hold your breath and activate the prototype."; + } + else + "Nothing happens."; + } + else + "The button won't work + until you complete the modifications."; + Receive: + "The button is set into a vertical surface, making it impossible + to place objects on top of it."; + ], + has scenery concealed; + +Sight deutsch_lab_from_prototype "Deutsch lab" prototype_interior + with description "You can't make out much of interest from here, just a few benches + under the shifting blue-violet-green light.", + name 'deutsch' 'lab' 'hatch' 'bench' 'benches', + has; + +Prop surface "inside surface" prototype_interior + with name 'walls' 'interior' 'surface' 'ceiling' 'floor' 'ground', + description "The interior of the prototype is clad + in smooth brushed steel.", + has ; +!----------------------------------------------- + +Room basement_equipment "Basement Equipment Room" + with name 'equipment' 'room', + description [; + if (FlashLit()) { + MoveMoveableChildren(basement_equipment_gloom,self); + print "By the thin blue-white beam of your flashlight, you + see the crowded shelves of the equipment room.^"; + if (basement_equipment_door has open) + print "^To the west, the door to the corridor lies open.^"; + else + print "^To the west, the door to the corridor stands closed.^"; + } + else { + MoveMoveableChildren(self,basement_equipment_gloom); + if (basement_equipment_door has open) + print "It is almost completely dark. Some faint light spills + in from the west through the open door, allowing you to just + discern the outlines of a series of shelves. By the door is + a light switch.^"; + else + print "You are in complete darkness.^"; + } + ], + out_to basement_equipment_door, + w_to basement_equipment_door, + sw_to [;<>;], + cant_go "The only exit is westwards, back to the corridor.", + lit false, + has_been_lit false, + lower_name "the basement equipment room", + has ; + +! A behind-the-scenes 'room' to store the items that should be hidden while the +! basement equipment room is in darkness + +Room basement_equipment_gloom "Dark Basement Equipment Room" + with name 'equipment' 'room' 'dark', + lower_name "the dark basement equipment room", + has ; + +Object basement_light_switch "light switch" basement_equipment + with name 'switch' 'light' 'lights', + before [; + Push: + <>; + SwitchOn: + if (~~self.blown) { + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,BLOW_BASEMENT_LIGHT_); + self.blown = true; + if (FlashLit()) + "The fluorescent lights flicker hopefully, strobing rapidly across the + scattered equipment. Then darkness. You blink away the after-images + and are left with only the faint torchlight."; + else + "The fluorescent lights flicker hopefully, strobing rapidly across the + scattered equipment. Then darkness. Nothing but a few fleeting + after-images of the cluttered room."; + } + else + "Click. Nothing happens."; + ], + react_before [; + Go: + MoveMoveableChildren(basement_equipment,basement_equipment_gloom); + ], + react_after [; + Drop: + if (~~(FlashLit())) { + move noun to basement_equipment_gloom; + } + Go: + if (basement_equipment.lit || FlashLit()) { + MoveMoveableChildren(basement_equipment_gloom,basement_equipment); + } + ], + blown false, + has static scenery concealed switchable; + +!----------------------------------------------- + +Room ground_equipment "First Floor Equipment Room" + with name 'equipment' 'room', + description [; + if (self.lit) { + MoveMoveableChildren(ground_equipment_gloom,self); + print "By the flickering fluorescent lights, you + see the crowded shelves of the equipment room.^"; + if (ground_equipment_door has open) + print "^To the west, the door to the corridor lies open.^"; + else + print "^To the west, the door to the corridor stands closed.^"; + } + else { + if (FlashLit()) { + MoveMoveableChildren(ground_equipment_gloom,self); + print "By the thin blue-white beam of your flashlight, you + see the crowded shelves of the equipment room.^"; + if (ground_equipment_door has open) + print "^To the west, the door to the corridor lies open.^"; + else + print "^To the west, the door to the corridor stands closed.^"; + } + else { + MoveMoveableChildren(self,ground_equipment_gloom); + if (ground_equipment_door has open) + print "It is almost completely dark. Some faint light spills + in from the west through the open door, allowing you to just + discern the outlines of a series of shelves. By the door is + a light switch.^"; + else + print "You are in complete darkness.^"; + } + } + ], + out_to ground_equipment_door, + w_to ground_equipment_door, + sw_to [;<>;], + cant_go "The only exit is westwards, back to the corridor.", + lit false, + has_been_lit false, + lower_name "the first floor equipment room", + has ; + +Room ground_equipment_gloom "Dark First Floor Equipment Room" + with name 'equipment' 'room' 'dark', + lower_name "the dark first floor equipment room", + has ; + +Object ground_light_switch "light switch" ground_equipment + with name 'switch' 'light' 'lights', + before [; + Push: + if (~~ground_equipment.lit) { + <>; + } + else { + <>; + } + SwitchOn: + if (~~ground_equipment.lit) { + ground_equipment.lit = true; + give self on; + print "The lights come on after a brief flicker.^"; + ; + instant_action_this_turn = false; + return true; + } + SwitchOff: + if (ground_equipment.lit) { + ground_equipment.lit = false; + give self ~on; + if (FlashLit()) + "The lights flicker briefly, then go out, + leaving you in the faint torchlight."; + else { + MoveMoveableChildren(ground_equipment,ground_equipment_gloom); + "The lights flicker briefly, then go out, + leaving you in the darkness."; + } + } + ], + react_before [; + Go: + if (~~(ground_equipment.lit)) + MoveMoveableChildren(ground_equipment,ground_equipment_gloom); + ], + react_after [; + Drop: + if (~~(ground_equipment.lit || FlashLit())) { + move noun to ground_equipment_gloom; + } + Go: + if ((ground_equipment.lit) || FlashLit()) { + MoveMoveableChildren(ground_equipment_gloom,ground_equipment); + } + ], + has static scenery concealed switchable; + +Prop shelves "shelves" + with name 'shelf' 'shelves' 'equipment' 'series' 'outlines' 'outline' 'clutter' 'cluttered', + description [; + if (((parent(self)).lit) || (Flashlit())) + "The shelves are filled with assorted lab equipment, but nothing of use + to you now."; + else + "You cannot make out any of the objects on the dark shelves."; + ], + found_in ground_equipment basement_equipment, + has ; + +Prop fluoro_light "fluorescent lights" + with name 'fluoro' 'fluorescent' 'flicker' 'flickering' 'tube', + description [; + if ((parent(self)).lit) + "The fluorescent tubes flicker brightly."; + else + "You can just make out a dark fluorescent tube in the ceiling above."; + ], + found_in ground_equipment basement_equipment, + has ; + +!----------------------------------------------- + +Room balcony "Balcony" + with name 'balcony', + description + "A wide balcony, looking out over the sleeping city. Below you, a lawn slopes gently away + into the gloom, a few silhouetted trees marking the edge of the modest grounds. Above, the + clear sky is a deep black, dusted with glinting stars.", + d_to [;Jumped(); return true;], + n_to [;Jumped(); return true;], + s_to balcony_door, + se_to conference_window, + in_to conference_window, + cant_go [; + if (conference_window has open) + "The only exits are the door back to the corridor (to the south) + and the window into the conference room (to the south-east)."; + else + "The only exit is the door back to the corridor (to the south)."; + ], + lower_name "the balcony", + has ; + +Prop balcony_floor "floor" balcony + with name 'floor' 'ground' 'tiles', + description "The floor is covered in white tiles.", + has ; + +Prop railing "railing" balcony + with name 'rail' 'railing' 'hand' 'handrail', + has ; + +Sight trees "trees" balcony + with name 'tree' 'trees' 'silhouette' 'silhouettes' 'cypress' 'cypresses' 'conifer' 'conifers', + description "The trees are some kind of tall conifer, cypress perhaps. You have fond + memories of dozing under them one afternoon last summer.", + has ; + +Sight grounds "grounds" balcony + with name 'lawn' 'slope' 'slopes' 'grounds' 'grass' 'gloom', + description "The grounds are little more than a well-kept lawn and a few tall trees, but + every night the security guard has to give them a brief inspection.", + has ; + +Sight guard "guard" balcony + with name 'guard' 'security' 'guards', + description "There is no sign of the security guard.", + has ; + +Sight stars "stars" + with name 'stars' 'star' 'black' 'dust' 'constellations', + description "The stars are a beautiful spray of glinting jewels in the blackness above.", + found_in balcony conference_room, + has ; + +Sight night "night" + with name 'night' 'starry', + description "Outside, it is one of the finest fall nights you can recall.", + found_in balcony conference_room, + has ; + +Sight city "city" + with name 'city' 'boston' 'town' 'light' 'rooftops' 'roofs' 'skyscrapers' 'buildings' 'building', + description "Before you, lie the rooftops and skyscrapers of your home town. Here and there + a small yellow light glows, but for now Boston sleeps.", + found_in balcony conference_room, + has ; + + +!----------------------------------------------- + +Room conference_room "Conference Room" + with name 'conference', + description "A rather slick but soulless affair. A large table of dark polished wood + takes pride of place and is surrounded by a half-dozen chairs.", + n_to conference_window, + nw_to conference_window, + out_to conference_window, + w_to conference_door, + cant_go "The only exits are the door to the west and the window to the north.", + lower_name "the conference room", + has ; + +Sight conference_room_sight "room" conference_room + with name 'room' 'conference', + description "A rather slick but soulless affair.", + before [; + Exit: + <>; + ], + has ; + +Furniture conference_table "conference table" conference_room + with description "A large round table of dark polished wood.", + name 'table' 'round' 'large' 'polished' 'dark' 'wood', + has scenery; + +Furniture chair "chair" conference_room + with description "Each chair is of a rather elegant, modern design + in the same dark wood as the table.", + name 'chair' 'chairs' 'seat' 'seats', + has scenery concealed; + +!----------------------------------------------- + +Room outside "Outside" + with description "Outside the lab, the street is quiet.", + n_to main_doors, + lower_name "the night", + has ; + +!----------------------------------------------- + +Room limbo "Night" + with description "The waiting place for unrealised items.", + lower_name "the night", + has ; + + +!------------------------------------------------------------------------ +! +! Door stuff +! + +AutomaticDoor main_doors "main doors" foyer + with description [; + if (self has open) + print "Through the open doors, you can see the quiet grounds. + On the right hand side is a green button.^"; + else + print "A pair of "; + if (self.smashed) print "cracked "; + print "plate glass sliding doors, + through which you can see the quiet grounds. + On the right hand side is a green button.^"; + ], + when_closed "To the south is a set of automatic doors leading + out into the inky night.", + when_open "To the south is an open set of automatic doors leading + out into the inky night.", + name 'doors' 'main' 'south' 'plate' 'glass' 'sliding' 'set' 'auto', + door_to [;Escaped(); return true;], + door_dir s_to, + open_self [t; + if (self hasnt open) { + give self open ~locked; + if (self in LocationOf(player)) + print "The main doors open onto the night.^"; + } + self.to_close_at = t; + if ((player in foyer) && (my_time < start_time-1) && (my_time >= start_time-3)) { + d_paradox = true; + deadflag = 3; + Seperator(); + print "Outside, your former self darts quickly towards the main doors. + When she sees them open, she breaks her stride + and lets out a shocked gasp.^"; + print "^Time unravels...^"; + Devours(my_time); + } + ], + closing_message [; + if ((~~Stopped()) && (self in LocationOf(player))) + "The main doors softly slide closed."; + ], + before [; + Open: + print "(pressing the green exit button)^"; + <>; + Unlock: + if (IsOfType(second,crowbar)) + <>; + else + "You cannot open the door with that."; + Enter: + if (self hasnt open) { + print "(first pressing the green exit button)^"; + ; + IncTime(); + if (Stopped()) return true; + <>; + } + ], + react_before [; Go: + if (noun == s_to && self hasnt open) + <>; + ], + has pluralname; + + +AutomaticDoor ground_door "automatic door" + with description [; + if (self in foyer) { + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_GROUND_CORRIDOR_); + print "A "; + if (self.smashed) print "cracked "; + print "plate glass sliding door, + through which you can see a dim corridor. "; + if (IsIn(former_self,ground_corridor)) + print "In the shadows stands your past self. "; + print "On the right hand side is a slot for an ID card.^"; + } + if (self in ground_corridor) { + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_FOYER_); + print "A "; + if (self.smashed) print "cracked "; + print "plate glass sliding door, + through which you can see the darkened foyer. "; + if (IsIn(former_self,foyer)) + print "In the shadows stands your past self. "; + print "On the right hand side is a green button.^"; + } + ], + when_closed [; + if (self in foyer) + "In the north wall is a closed + automatic door."; + if (self in ground_corridor) + "To the south is a closed automatic door, leading back + to the foyer."; + + ], + when_open [; + if (self in foyer) + "In the north wall is an open + automatic door."; + if (self in ground_corridor) + "To the south is an open automatic door, leading back + to the foyer."; + + ], + name 'north' 'door' 'automatic' 'auto' 'plate' 'glass' 'sliding', + door_to [; + if (self in foyer) + return ground_corridor; + if (self in ground_corridor) + return foyer; + + ], + door_dir [; + if (self in foyer) + return n_to; + if (self in ground_corridor) + return s_to; + + ], + before [; + Unlock: + if (IsOfType(second,crowbar)) + <>; + else if (IsOfType(second,id_card) && (self in foyer)) + <>; + else + "You cannot open the door with that."; + Open: + if (self in foyer) + if (self.known_exterior_opening == 0) + "There is no obvious way to get + the automatic door to open."; + else { + print "You press the button marked 'first'.^"; + <>; + } + if (self in ground_corridor) { + print "(pressing the green exit button)^"; + <>; + } + Enter: + if (self in ground_corridor && self hasnt open) { + print "(first pressing the green exit button)^"; + ; + IncTime(); + if (Stopped()) return true; + <>; + } + if (self in foyer && self hasnt open) { + if (self.known_exterior_opening == true) { + print "(first pressing the button marked 'first')^"; + ; + IncTime(); + if (Stopped()) return true; + <>; + } + else { + "There is no obvious way to get + the automatic door to open."; + } + } + ], + react_before [; Go: + if (noun == n_to && self in foyer && self hasnt open) + <>; + if (noun == s_to && self in ground_corridor && self hasnt open) + <>; + ], + known_exterior_opening, + found_in foyer ground_corridor, + has ; + + +AutomaticDoor basement_door "automatic door" + with description [; + if (self in basement_landing) { + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_BASEMENT_CORRIDOR_); + print "A "; + if (self.smashed) print "cracked "; + print "plate glass sliding door, + through which you can see a dim corridor. "; + if (IsIn(former_self,basement_corridor)) + print "In the shadows stands your past self. "; + print "On the right hand side is a slot for an ID card.^"; + } + if (self in basement_corridor) { + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_BASEMENT_LANDING_); + print "A "; + if (self.smashed) print "cracked "; + print "plate glass sliding door, + through which you can see the small basement landing. "; + if (IsIn(former_self,basement_landing)) + print "In the shadows stands your past self. "; + print "On the right hand side is a green button.^"; + } + ], + name 'door' 'automatic' 'auto' 'plate' 'glass' 'sliding', + when_closed [; + if (self in basement_landing) + "To the north is a closed automatic door."; + if (self in basement_corridor) + "To the south is a closed automatic door, leading back + to the landing."; + + ], + when_open [; + if (self in basement_landing) + "To the north is an open automatic door."; + if (self in basement_corridor) + "To the south is an open automatic door, leading back + to the landing."; + + ], + door_to [; + if (self in basement_landing) + return basement_corridor; + if (self in basement_corridor) + return basement_landing; + + ], + door_dir [; + if (self in basement_landing) + return n_to; + if (self in basement_corridor) + return s_to; + + ], + before [; + Unlock: + if (IsOfType(second,crowbar)) + <>; + else if (IsOfType(second,id_card) && (self in basement_landing)) + <>; + else + "You cannot open the door with that."; + Open: + if (self in basement_landing) { + if ( AmHolding(id_card) ) { + print "(inserting your ID card)^"; + <>; + } + else + "You would need you ID card to do that."; + } + if (self in basement_corridor) { + print "(pressing the green exit button)^"; + <>; + } + Enter: + if (self in basement_corridor && self hasnt open) { + print "(first pressing the green exit button)^"; + ; + IncTime(); + if (Stopped()) return true; + <>; + } + if (self in basement_landing && self hasnt open) { + if ( AmHolding(id_card) ) { + print "(first inserting your ID card)^"; + ; + IncTime(); + if (Stopped()) return true; + <>; + } + else + "You would need you ID card to do that."; + } + ], + react_before [; Go: + if (noun == n_to && self in basement_landing && self hasnt open) + <>; + if (noun == s_to && self in basement_corridor && self hasnt open) + <>; + ], + known_exterior_opening, + found_in basement_landing basement_corridor, + has ; + + +AutomaticDoor upstairs_door "automatic door" + with description [; + if (self in upstairs_landing) { + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_UPSTAIRS_CORRIDOR_); + print "A "; + if (self.smashed) print "cracked "; + print "plate glass sliding door, + through which you can see a dim corridor. "; + if (IsIn(former_self,upstairs_corridor)) + print "In the shadows stands your past self. "; + print "On the right hand side is a slot for an ID card.^"; + } + if (self in upstairs_corridor) { + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_UPSTAIRS_LANDING_); + print "A "; + if (self.smashed) print "cracked "; + print "plate glass sliding door, + through which you can see the upper part of the darkened foyer. "; + if (IsIn(former_self,upstairs_landing)) + print "In the shadows of the landing stands your past self. "; + print "On the right hand side is a green button.^"; + } + ], + name 'door' 'automatic' 'auto' 'plate' 'glass' 'sliding', + when_closed [; + if (self in upstairs_landing) + "On the north wall lies a closed automatic door."; + if (self in upstairs_corridor) + "To the south is a closed automatic door, leading back + to the landing."; + ], + when_open [; + if (self in upstairs_landing) + "On the north wall lies an open automatic door."; + if (self in upstairs_corridor) + "To the south is an open automatic door, leading back + to the landing."; + ], + door_to [; + if (self in upstairs_landing) + return upstairs_corridor; + if (self in upstairs_corridor) + return upstairs_landing; + ], + door_dir [; + if (self in upstairs_landing) + return n_to; + if (self in upstairs_corridor) + return s_to; + ], + before [; + Unlock: + if (IsOfType(second,crowbar)) + <>; + else if (IsOfType(second,id_card) && (self in upstairs_landing)) + <>; + else + "You cannot open the door with that."; + Open: + if (self in upstairs_landing) + if (AmHolding(id_card)) { + print "(inserting your ID card)^"; + <>; + } + if (self in upstairs_corridor) { + print "(pressing the green exit button)^"; + <>; + } + Enter: + if (self in upstairs_corridor && self hasnt open) { + print "(first pressing the green exit button)^"; + ; + if (self has open) { + IncTime(); + if (Stopped()) return true; + <>; + } + return true; + } + if (self in upstairs_landing && self hasnt open) { + "There is no obvious way to get the automatic door to open."; + } + ], + react_before [; Go: + if (noun == s_to && self in upstairs_corridor && self hasnt open) + <>; + ], + found_in upstairs_landing upstairs_corridor, + has ; + +Object exit_button "green exit button" + with description "A green button beside the door.", + name 'green' 'button', + before [; Push: + if (self in ground_corridor) { + ground_door.open_self(my_time+1); + } + if (self in upstairs_corridor) { + if (challenge) + "Nothing happens -- the button must be broken."; + else + upstairs_door.open_self(my_time+1); + } + if (self in basement_corridor) { + basement_door.open_self(my_time+1); + } + if (self in foyer) { + main_doors.open_self(my_time+1); + } + return true; + Receive: + "The button is set into a vertical surface, making it impossible + to place objects on top of it."; + ], + found_in ground_corridor upstairs_corridor basement_corridor foyer, + has scenery concealed; + +Object id_slot "ID card slot" + with description "A narrow slot to the right of the door. + The doors are coded so that only those with legitimate + business can use their card to gain entrance.", + + name 'slot', + found_in foyer upstairs_landing basement_landing, + has scenery concealed; + + +ManualDoor ground_equipment_door "door to the equipment room" + with name 'door' 'equipment' 'room' 'grey' 'gray' 'third' 'plain' 'ne' 'north-east', + description + "A simple gray door.", + door_to [; + if (self in ground_corridor) + return ground_equipment; + if (self in ground_equipment) + return ground_corridor; + ], + door_dir [; + if (self in ground_corridor) + return ne_to; + if (self in ground_equipment) + return w_to; + ], + before [; + Close: + if (((self in ground_equipment) && IsIn(former_self,ground_corridor)) || + ((self in ground_corridor) && IsIn(former_self,ground_equipment)) ) { + CloseParadox(); + return true; + } + Open: + if (((self in ground_equipment) && IsIn(former_self,ground_corridor)) || + ((self in ground_corridor) && IsIn(former_self,ground_equipment)) ) { + OpenParadox(); + return true; + } + else + return (OpenManualDoor(self,second)); + Unlock: + if (IsOfType(second,crowbar)) + <>; + if (((self in ground_equipment) && IsIn(former_self,ground_corridor)) || + ((self in ground_corridor) && IsIn(former_self,ground_equipment)) ) { + LockUnlockParadox(); + return true; + } + else + return (UnlockManualDoor(self,second)); + Lock: + if (((self in ground_equipment) && IsIn(former_self,ground_corridor)) || + ((self in ground_corridor) && IsIn(former_self,ground_equipment)) ) { + LockUnlockParadox(); + return true; + } + else + return (LockManualDoor(self,second)); + ], + with_key_type equipment_key, + found_in ground_corridor ground_equipment, + has locked scenery; + +ManualDoor basement_equipment_door "door to the equipment room" + with name 'door' 'equipment' 'room' 'grey' 'gray' 'third' 'plain' 'ne' 'north-east', + description + "A simple gray door.", + door_to [; + if (self in basement_corridor) + return basement_equipment; + if (self in basement_equipment) + return basement_corridor; + + ], + door_dir [; + if (self in basement_corridor) + return ne_to; + if (self in basement_equipment) + return w_to; + ], + before [; + Close: + if (((self in basement_equipment) && IsIn(former_self,basement_corridor)) || + ((self in basement_corridor) && IsIn(former_self,basement_equipment)) ) { + CloseParadox(); + return true; + } + Open: + if (((self in basement_equipment) && IsIn(former_self,basement_corridor)) || + ((self in basement_corridor) && IsIn(former_self,basement_equipment)) ) { + OpenParadox(); + return true; + } + else + return (OpenManualDoor(self,second)); + Unlock: + if (IsOfType(second,crowbar)) + <>; + if (((self in basement_equipment) && IsIn(former_self,basement_corridor)) || + ((self in basement_corridor) && IsIn(former_self,basement_equipment)) ) { + LockUnlockParadox(); + return true; + } + else + return (UnlockManualDoor(self,second)); + Lock: + if (((self in basement_equipment) && IsIn(former_self,basement_corridor)) || + ((self in basement_corridor) && IsIn(former_self,basement_equipment)) ) { + LockUnlockParadox(); + return true; + } + else + return (LockManualDoor(self,second)); + ], + with_key_type equipment_key, + found_in basement_corridor basement_equipment, + has locked scenery; + +ManualDoor deutsch_door "door to the Deutsch lab" + with name 'door' 'deutsch' 'lab' 'fourth' 'north' 'n\\', + description [; + if (self in basement_corridor) + "A gray door with a small glass window, + looking into the darkened lab."; + if (self in deutsch_lab) + "A gray door with a small glass window, + looking into the darkened corridor."; + ], + door_to [; + if (self in basement_corridor) + return deutsch_lab; + if (self in deutsch_lab) + return basement_corridor; + ], + door_dir [; + if (self in basement_corridor) + return n_to; + if (self in deutsch_lab) + return s_to; + ], + before [; + Close: + if (((self in deutsch_lab) && IsIn(former_self,basement_corridor)) || + ((self in basement_corridor) && IsIn(former_self,deutsch_lab)) ) { + CloseParadox(); + return true; + } + Open: + if (((self in deutsch_lab) && IsIn(former_self,basement_corridor)) || + ((self in basement_corridor) && IsIn(former_self,deutsch_lab)) ) { + OpenParadox(); + return true; + } + else + return (OpenManualDoor(self,second)); + Unlock: + if (IsOfType(second,crowbar)) + <>; + if (((self in deutsch_lab) && IsIn(former_self,basement_corridor)) || + ((self in basement_corridor) && IsIn(former_self,deutsch_lab)) ) { + LockUnlockParadox(); + return true; + } + else + return (UnlockManualDoor(self,second)); + Lock: + if (((self in deutsch_lab) && IsIn(former_self,basement_corridor)) || + ((self in basement_corridor) && IsIn(former_self,deutsch_lab)) ) { + LockUnlockParadox(); + return true; + } + else + return (LockManualDoor(self,second)); + ], + with_key_type deutsch_key, + found_in basement_corridor deutsch_lab, + has locked scenery; + +ManualDoor balcony_door "balcony door" + with name 'door' 'balcony' 'n\\' 'north' 'glass', + description [; + if (self in upstairs_corridor) { + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_BALCONY_); + print "A "; + if (self.smashed) print "cracked "; + print "glass door looking out onto the balcony. "; + if (IsIn(former_self,balcony)) + print "In the shadows you can see your past self.^"; + else + print "^"; + } + if (self in balcony) { + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_UPSTAIRS_CORRIDOR_); + print "A "; + if (self.smashed) print "cracked "; + print "glass door looking into the upstairs corridor. "; + if (IsIn(former_self,upstairs_corridor)) + print "In the shadows you can see your past self.^"; + else + print "^"; + } + ], + when_closed [; + if (self in balcony) + "To the south, the door to the upstairs corridor stands closed."; + else + "At the north end of the corridor is a closed glass door leading out + to the balcony."; + ], + when_open [; + if (self in balcony) + "To the south, the door to the upstairs corridor lies open."; + else + "At the north end of the corridor is an open glass door leading out + to the balcony."; + ], + door_to [; + if (self in upstairs_corridor) + return balcony; + if (self in balcony) + return upstairs_corridor; + + ], + door_dir [; + if (self in upstairs_corridor) + return n_to; + if (self in balcony) + return s_to; + ], + before [; + Close: + if (((self in balcony) && IsIn(former_self,upstairs_corridor)) || + ((self in upstairs_corridor) && IsIn(former_self,balcony)) ) { + CloseParadox(); + return true; + } + Open: + if (((self in balcony) && IsIn(former_self,upstairs_corridor)) || + ((self in upstairs_corridor) && IsIn(former_self,balcony)) ) { + OpenParadox(); + return true; + } + else + return (OpenManualDoor(self,second)); + Unlock: + if (IsOfType(second,crowbar)) + <>; + if (((self in balcony) && IsIn(former_self,upstairs_corridor)) || + ((self in upstairs_corridor) && IsIn(former_self,balcony)) ) { + LockUnlockParadox(); + return true; + } + else + return (UnlockManualDoor(self,second)); + Lock: + if (((self in balcony) && IsIn(former_self,upstairs_corridor)) || + ((self in upstairs_corridor) && IsIn(former_self,balcony)) ) { + LockUnlockParadox(); + return true; + } + else + return (LockManualDoor(self,second)); + Attack: + if (AmHolding(crowbar)) { + print "You swing the crowbar firmly into the door. It shudders, + cracks reaching out from the point of impact, but the glass + stays in place.^"; + self.smashed = true; + StartSiren(); + return true; + } + else + "You don't have anything heavy enough to smash the door with."; + Search: + <>; + ], + smashed false, + with_key_type nothing, + found_in upstairs_corridor balcony, + has ; + +Object conference_window "window into the conference room" + with name 'window' 'glass' 'tinted' 'remains' 'shards', + description [; + if (self in balcony) { + if (self has open) + "The remains of a plate glass window that has been smashed in with + something heavy. Large shards of glass still protrude from the edges, + framing the murky interior of the conference room."; + else if (FlashLit()) + "My God! It's full of stars."; + else + "A plate glass window looking into the murky interior of an conference room."; + } + if (self in conference_room) { + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,X_BALCONY_); + if (self has open) + print "The remains of a plate glass window that has been smashed in with + something heavy. Large shards of glass still protrude from the edges, + framing the starry night beyond. "; + else + "A plate glass window looking out into the starry night. "; + if (IsIn(former_self,balcony)) + print "Against the stars, you can just make out the silhouette of your + past self.^"; + else + print "^"; + } + ], + when_closed [; + if (self in balcony) + "To the south-east is a large, tinted glass window."; + if (self in conference_room) + "To the north is a large plate glass window, amazingly intact."; + + ], + when_open [; + if (self in balcony) + "To the south-east, lie the shattered remains of a window, opening into + a murky conference room."; + + if (self in conference_room) + "To the north, lie the shattered remains of a window, open to + the starry night."; + ], + door_to [; + if (self in balcony) + return conference_room; + if (self in conference_room) + return balcony; + + ], + door_dir [; + if (self in balcony) + return se_to; + if (self in conference_room) + return n_to; + + ], + before [; + Open: + if (second == nothing) + "The window appears to be locked from the inside."; + Unlock: + if (IsOfType(second, crowbar)) + <>; + else if (second ~= nothing) + "You cannot get the window open with that."; + else + "You cannot find the lock."; + Attack: + if (AmHolding(crowbar)) { + if (self has open) + "The window is already thoroughly broken."; + give self open; + print "You swing the crowbar firmly into the window and it shatters with + a loud crash.^"; + StartSiren(); + return true; + } + else + "You don't have anything heavy enough to smash the window with."; + Search: + <>; + ], + with_key_type nothing, + found_in balcony conference_room, + has static locked door lockable; + + + +!============================================================================ +! +! Functions: +! + +!---------------------------------------------------- +! +! Entry point functions: + + +! Puts the time in HH:MM:SS format on the status line + +[ DrawStatusLine width pos; + + ! @split_window 0; + ! return; + + @split_window 1; + @set_window 1; + @set_cursor 1 1; + style reverse; + width = 0->33; + pos = width-20; + spaces (width); + + @set_cursor 1 2; + PrintShortName(location); + + @set_cursor 1 pos; + print (PrintTime) my_time; + + @set_cursor 1 1; + style roman; + @set_window 0; +]; + +[ ScoreSub; + if (deadflag == 0) + "There is no score in this game."; +]; + +[ ChooseObjects obj code; + if (code < 2) { + if (obj has scenery) + return 2; ! exclude scenery from 'get all' commands + if (action_to_be == ##Take && obj has static) + return 2; ! exclude scenery from 'get all' commands + rfalse; + } + if (action_to_be == ##Insert && obj in player) ! prefer to insert into held objects + return 3; ! particularly important with all + ! these duplicates... + if (action_to_be == ##Close && (obj has openable) && (obj has open)) + return 3; + if (action_to_be == ##Open && (obj has openable) && (obj hasnt open)) + return 3; + if (action_to_be == ##Lock && (obj has lockable) && (obj hasnt locked)) + return 3; + if (action_to_be == ##Unlock && (obj has lockable) && (obj has locked)) + return 3; + if (action_to_be == ##LockSimple && (obj has lockable) && (obj hasnt locked)) + return 3; + if (action_to_be == ##UnlockSimple && (obj has lockable) && (obj has locked)) + return 3; + if (action_to_be == ##Take && obj has static) ! prefer to get non-statics + return 1; + if (obj hasnt scenery) ! prefer non-scenery in general + return 2; + return 1; +]; + +[ Initialise i; + + lookmode = 2; ! 'verbose' + + my_time = start_time; + + location = foyer; + + player = myselfobj; + + for (i=0 : i < MAX_ITEM_COPIES : i++) { + bomb-->i = Bomb_.create(); + id_card-->i = IDCard_.create(); + equipment_key-->i = EquipmentKey_.create(); + deutsch_key-->i = DeutschKey_.create(); + flashlight-->i = Flashlight_.create(); + battery-->i = Battery_.create(); + cable-->i = Cable_.create(); + crowbar-->i = Crowbar_.create(); + notes-->i = Notes_.create(); + } + + move bomb-->0 to player; + move id_card-->0 to player; + move deutsch_key-->0 to player; + move equipment_key-->0 to deutsch_lab; + move flashlight-->0 to deutsch_lab; + move battery-->0 to ground_equipment_gloom; + move cable-->0 to ground_equipment_gloom; + move crowbar-->0 to basement_equipment_gloom; + move notes-->0 to conference_table; + + for (i=1 : i < MAX_ITEM_COPIES : i++) { + move bomb-->i to limbo; + move id_card-->i to limbo; + move equipment_key-->i to limbo; + move deutsch_key-->i to limbo; + move flashlight-->i to limbo; + move battery-->i to limbo; + move cable-->i to limbo; + move crowbar-->i to limbo; + move notes-->i to limbo; + } + + for (i=0 : i < MAX_TIME_TRAVELS : i++) { + former_self-->i = FormerSelf_.create(); + move former_self-->i to limbo; + } + + InitHistory(); + + "^ + ^ + You're in.^ + ^ + The plan now is simple: go to your lab, plant the bomb, and run. + The prototype will be destroyed. The military will have no way to + continue the experiment. No-one will die.^ + ^ + The guard is out securing the grounds. The building is empty. You have six minutes.^ + ^ + "; + +]; + +!---------------------------------------------------- +! +! Major tasks: + + +!! Initialises the first self's history for all items +!! First wipe's the history clean with all locations as 'limbo' +!! Next updates pre-start_time histories of all items and the player +!! Then updates the states with the proper pasts and UNKNOWN futures + +[InitHistory t i s; + for (t = EARLIEST_TIME : t <= FINAL_TIME : t++) { + for (i=0 : i < MAX_ITEM_COPIES : i++) { + Put3D(bomb_loc, 0, (t - EARLIEST_TIME), + i, limbo ); + Put3D(id_card_loc, 0, (t - EARLIEST_TIME), + i, limbo ); + Put3D(equipment_key_loc, 0, (t - EARLIEST_TIME), + i, limbo ); + Put3D(deutsch_key_loc, 0, (t - EARLIEST_TIME), + i, limbo ); + Put3D(flashlight_loc, 0, (t - EARLIEST_TIME), + i, limbo ); + Put3D(battery_loc, 0, (t - EARLIEST_TIME), + i, limbo ); + Put3D(cable_loc, 0, (t - EARLIEST_TIME), + i, limbo ); + Put3D(crowbar_loc, 0, (t - EARLIEST_TIME), + i, limbo ); + Put3D(notes_loc, 0, (t - EARLIEST_TIME), + i, limbo ); + + Put3D(flashlight_state, 0, (t - EARLIEST_TIME), + i, UNKNOWN_ ); + Put3D(bomb_setting, 0, (t - EARLIEST_TIME), + i, UNKNOWN_ ); + } + } + + for (t = EARLIEST_TIME : t <= start_time : t++) { + Put3D(bomb_loc, 0, (t - EARLIEST_TIME), + 0, parent(bomb-->0) ); + Put3D(id_card_loc, 0, (t - EARLIEST_TIME), + 0, parent(id_card-->0) ); + Put3D(equipment_key_loc, 0, (t - EARLIEST_TIME), + 0, parent(equipment_key-->0) ); + Put3D(deutsch_key_loc, 0, (t - EARLIEST_TIME), + 0, parent(deutsch_key-->0) ); + Put3D(flashlight_loc, 0, (t - EARLIEST_TIME), + 0, parent(flashlight-->0) ); + Put3D(battery_loc, 0, (t - EARLIEST_TIME), + 0, parent(battery-->0) ); + Put3D(cable_loc, 0, (t - EARLIEST_TIME), + 0, parent(cable-->0) ); + Put3D(crowbar_loc, 0, (t - EARLIEST_TIME), + 0, parent(crowbar-->0) ); + Put3D(notes_loc, 0, (t - EARLIEST_TIME), + 0, parent(notes-->0) ); + } + for (t = EARLIEST_TIME : t < start_time : t++) { + Put2D(player_loc, 0, (t - EARLIEST_TIME), limbo); + } + Put2D(player_loc, 0, start_time - EARLIEST_TIME, foyer); + + for (t = EARLIEST_TIME : t <= start_time : t++) { + for (s=0 : s < MAX_TIME_TRAVELS : s++) { + Put2D(dangerous_activity, s, (t - EARLIEST_TIME), NONE_); + Put2D(activity_target, s, (t - EARLIEST_TIME), nothing); + Put2D(siren_state, s, (t - EARLIEST_TIME), false); + Put2D(panel_setting, s, (t - EARLIEST_TIME), 0); + Put2D(basement_equipment_light, s, (t - EARLIEST_TIME), false); + Put2D(ground_equipment_light, s, (t - EARLIEST_TIME), false); + Put2D(main_doors_state, s, (t - EARLIEST_TIME), LOCKED_); + Put2D(basement_door_state, s, (t - EARLIEST_TIME), LOCKED_); + Put2D(ground_door_state, s, (t - EARLIEST_TIME), LOCKED_); + Put2D(upstairs_door_state, s, (t - EARLIEST_TIME), LOCKED_); + Put2D(balcony_door_state, s, (t - EARLIEST_TIME), CLOSED_); + Put2D(conference_window_state, s, (t - EARLIEST_TIME), LOCKED_); + Put2D(deutsch_door_state, s, (t - EARLIEST_TIME), LOCKED_); + Put2D(basement_equipment_door_state, s, (t - EARLIEST_TIME), LOCKED_); + Put2D(ground_equipment_door_state, s, (t - EARLIEST_TIME), LOCKED_); + + Put2D(main_doors_smashed, s, (t - EARLIEST_TIME), false); + Put2D(basement_door_smashed, s, (t - EARLIEST_TIME), false); + Put2D(ground_door_smashed, s, (t - EARLIEST_TIME), false); + Put2D(upstairs_door_smashed, s, (t - EARLIEST_TIME), false); + Put2D(balcony_door_smashed, s, (t - EARLIEST_TIME), false); + + for (i=0 : i < MAX_ITEM_COPIES : i++) { + Put3D(flashlight_state, 0, (t - EARLIEST_TIME), + i, false ); + Put3D(bomb_setting, 0, (t - EARLIEST_TIME), + i, NA_ ); + } + } + } + + for (t = start_time+1 : t <= FINAL_TIME : t++) { + for (s=0 : s < MAX_TIME_TRAVELS : s++) { + Put2D(dangerous_activity, s, (t - EARLIEST_TIME), NONE_); + Put2D(activity_target, s, (t - EARLIEST_TIME), nothing); + Put2D(siren_state, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(panel_setting, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(basement_equipment_light, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(ground_equipment_light, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(main_doors_state, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(basement_door_state, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(ground_door_state, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(upstairs_door_state, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(balcony_door_state, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(conference_window_state, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(deutsch_door_state, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(basement_equipment_door_state, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(ground_equipment_door_state, s, (t - EARLIEST_TIME), UNKNOWN_); + + Put2D(main_doors_smashed, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(basement_door_smashed, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(ground_door_smashed, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(upstairs_door_smashed, s, (t - EARLIEST_TIME), UNKNOWN_); + Put2D(balcony_door_smashed, s, (t - EARLIEST_TIME), UNKNOWN_); + } + } + +]; + +!! Update the time, remove the old objects that don't travel, +!! create new objects, move them to the appropriate places + +[TravelThroughTime time_amount t s i j; + + last_travel_time = my_time; + + time_amount = time_amount / 5; ! round down to nearest five seconds + if (time_amount == 0) + time_amount = 1; + + my_time = my_time - time_amount; + + if (my_time < early_guard_time) { + d_paradox = true; + deadflag = 3; + Seperator(); + print (Nearby) 0, "the guard gives the inside corridors a last look before + heading out. A small sound from the Deutsch lab. He turns.^"; + print "^Time unravels...^"; + Devours(my_time); + return true; + } + + !! replace those items the player brought with them + + FixBombSettings(time_amount); + FixFlashlightStates(); + + for (j=0 : j < Exp(2,time_travelled) : j++) { + ReplaceTravellingItem(bomb, j); + ReplaceTravellingItem(id_card, j); + ReplaceTravellingItem(equipment_key, j); + ReplaceTravellingItem(deutsch_key, j); + ReplaceTravellingItem(flashlight, j); + + ReplaceTravellingItem(cable, j); + ReplaceTravellingItem(crowbar, j); + ReplaceTravellingItem(notes, j); + + !! tricky battery issues, since they can be in flashlights + !! if other items could be in containers this would hurt here too + + if (PlayerHas(battery-->j)) { + if (battery-->j in player) + move battery-->(j+Exp(2,time_travelled)) to player; + else { + for (i=0 : i < Exp(2,time_travelled) : i++) + if (battery-->j in (flashlight-->i)) + move (battery-->(j+Exp(2,time_travelled))) to (flashlight-->(i+Exp(2,time_travelled))); + } + } + else if (LocationOf(battery-->j) == prototype_interior) { + if (battery-->j in prototype_interior) + move battery-->(j+Exp(2,time_travelled)) to prototype_interior; + else + for (i=0 : i < Exp(2,time_travelled) : i++) + if (battery-->j in flashlight-->i) + move battery-->(j+Exp(2,time_travelled)) to + flashlight-->(i+Exp(2,time_travelled)); + } + + } + + + !! move all the old items and selves into limbo + + for (t=0 : t < Exp(2,time_travelled) : t++) { + move bomb-->t to limbo; + move id_card-->t to limbo; + move equipment_key-->t to limbo; + move deutsch_key-->t to limbo; + move flashlight-->t to limbo; + move battery-->t to limbo; + move cable-->t to limbo; + move crowbar-->t to limbo; + move notes-->t to limbo; + } + + for (t=0 : t < time_travelled : t++) + move former_self-->t to limbo; + + + !! fix up history of immediate past self so 'player' becomes appropriate former self + + for (s = EARLIEST_TIME : s <= FINAL_TIME : s++) { + for (t=0 : t < Exp(2,time_travelled) : t++) { + if (Get3D(bomb_loc, time_travelled, (s - EARLIEST_TIME), t) == player) + Put3D(bomb_loc, time_travelled, (s - EARLIEST_TIME), t, + former_self-->time_travelled); + if (Get3D(id_card_loc, time_travelled, (s - EARLIEST_TIME), t) == player) + Put3D(id_card_loc, time_travelled, (s - EARLIEST_TIME), t, + former_self-->time_travelled); + if (Get3D(equipment_key_loc, time_travelled, (s - EARLIEST_TIME), t) == player) + Put3D(equipment_key_loc, time_travelled, (s - EARLIEST_TIME), t, + former_self-->time_travelled); + if (Get3D(deutsch_key_loc, time_travelled, (s - EARLIEST_TIME), t) == player) + Put3D(deutsch_key_loc, time_travelled, (s - EARLIEST_TIME), t, + former_self-->time_travelled); + if (Get3D(flashlight_loc, time_travelled, (s - EARLIEST_TIME), t) == player) + Put3D(flashlight_loc, time_travelled, (s - EARLIEST_TIME), t, + former_self-->time_travelled); + if (Get3D(battery_loc, time_travelled, (s - EARLIEST_TIME), t) == player) + Put3D(battery_loc, time_travelled, (s - EARLIEST_TIME), t, + former_self-->time_travelled); + if (Get3D(cable_loc, time_travelled, (s - EARLIEST_TIME), t) == player) + Put3D(cable_loc, time_travelled, (s - EARLIEST_TIME), t, + former_self-->time_travelled); + if (Get3D(crowbar_loc, time_travelled, (s - EARLIEST_TIME), t) == player) + Put3D(crowbar_loc, time_travelled, (s - EARLIEST_TIME), t, + former_self-->time_travelled); + if (Get3D(notes_loc, time_travelled, (s - EARLIEST_TIME), t) == player) + Put3D(notes_loc, time_travelled, (s - EARLIEST_TIME), t, + former_self-->time_travelled); + } + } + + !! recreate the world as it was for most recent former self + !! (ie move a lot of old items and selves back to the world) + !! (fix states of doors and machine) + + for (i=0 : i < Exp(2,time_travelled) : i++) { + move bomb-->i to Get3D(bomb_loc,time_travelled,my_time-EARLIEST_TIME,i); + move id_card-->i to Get3D(id_card_loc,time_travelled,my_time-EARLIEST_TIME,i); + move equipment_key-->i to Get3D(equipment_key_loc,time_travelled,my_time-EARLIEST_TIME,i); + move deutsch_key-->i to Get3D(deutsch_key_loc,time_travelled,my_time-EARLIEST_TIME,i); + move flashlight-->i to Get3D(flashlight_loc,time_travelled,my_time-EARLIEST_TIME,i); + move battery-->i to Get3D(battery_loc,time_travelled,my_time-EARLIEST_TIME,i); + move cable-->i to Get3D(cable_loc,time_travelled,my_time-EARLIEST_TIME,i); + move crowbar-->i to Get3D(crowbar_loc,time_travelled,my_time-EARLIEST_TIME,i); + move notes-->i to Get3D(notes_loc,time_travelled,my_time-EARLIEST_TIME,i); + } + for (t=0 : t <= time_travelled : t++) { + if (Get2D(player_loc,t,my_time-EARLIEST_TIME) == nothing) + move former_self-->t to limbo; + else + move former_self-->t to Get2D(player_loc,t,my_time-EARLIEST_TIME); + } + + if (my_time < prototype_fixed_time) + prototype.fixed = false; + + SetBombs(); + SetFlashlights(); + SetPanel(panel_setting); + SetBasementLight(basement_equipment_light); + SetGroundLight(ground_equipment_light); + SetAutomaticDoor(main_doors, main_doors_state); + SetAutomaticDoor(basement_door, basement_door_state); + SetAutomaticDoor(ground_door, ground_door_state); + SetAutomaticDoor(upstairs_door, upstairs_door_state); + SetManualDoor(balcony_door, balcony_door_state); + SetManualDoor(conference_window, conference_window_state); + SetManualDoor(deutsch_door, deutsch_door_state); + SetManualDoor(basement_equipment_door, basement_equipment_door_state); + SetManualDoor(ground_equipment_door, ground_equipment_door_state); + + SetBrokenDoor(main_doors, main_doors_smashed); + SetBrokenDoor(basement_door, basement_door_smashed); + SetBrokenDoor(ground_door, ground_door_smashed); + SetBrokenDoor(upstairs_door, upstairs_door_smashed); + SetBrokenDoor(balcony_door, balcony_door_smashed); + + !! initialise the history for the new self from the most recent self + + for (t = EARLIEST_TIME : t <= FINAL_TIME : t++) { + for (i=0 : i < MAX_ITEM_COPIES : i++) { + Put3D(bomb_loc, time_travelled+1, (t - EARLIEST_TIME), i, + Get3D(bomb_loc, time_travelled, (t - EARLIEST_TIME), i)); + Put3D(id_card_loc, time_travelled+1, (t - EARLIEST_TIME), i, + Get3D(id_card_loc, time_travelled, (t - EARLIEST_TIME), i)); + Put3D(equipment_key_loc, time_travelled+1, (t - EARLIEST_TIME), i, + Get3D(equipment_key_loc, time_travelled, (t - EARLIEST_TIME), i)); + Put3D(deutsch_key_loc, time_travelled+1, (t - EARLIEST_TIME), i, + Get3D(deutsch_key_loc, time_travelled, (t - EARLIEST_TIME), i)); + Put3D(flashlight_loc, time_travelled+1, (t - EARLIEST_TIME), i, + Get3D(flashlight_loc, time_travelled, (t - EARLIEST_TIME), i)); + Put3D(battery_loc, time_travelled+1, (t - EARLIEST_TIME), i, + Get3D(battery_loc, time_travelled, (t - EARLIEST_TIME), i)); + Put3D(cable_loc, time_travelled+1, (t - EARLIEST_TIME), i, + Get3D(cable_loc, time_travelled, (t - EARLIEST_TIME), i)); + Put3D(crowbar_loc, time_travelled+1, (t - EARLIEST_TIME), i, + Get3D(crowbar_loc, time_travelled, (t - EARLIEST_TIME), i)); + Put3D(notes_loc, time_travelled+1, (t - EARLIEST_TIME), i, + Get3D(notes_loc, time_travelled, (t - EARLIEST_TIME), i)); + + Put3D(bomb_setting, time_travelled+1, (t - EARLIEST_TIME), i, + Get3D(bomb_setting, time_travelled, (t - EARLIEST_TIME), i)); + Put3D(flashlight_state, time_travelled+1, (t - EARLIEST_TIME), i, + Get3D(flashlight_state, time_travelled, (t - EARLIEST_TIME), i)); + } + Put2D(dangerous_activity, time_travelled+1, (t - EARLIEST_TIME), + Get2D(dangerous_activity, time_travelled, (t - EARLIEST_TIME))); + Put2D(activity_target, time_travelled+1, (t - EARLIEST_TIME), + Get2D(activity_target, time_travelled, (t - EARLIEST_TIME))); + Put2D(siren_state, time_travelled+1, (t - EARLIEST_TIME), + Get2D(siren_state, time_travelled, (t - EARLIEST_TIME))); + Put2D(panel_setting, time_travelled+1, (t - EARLIEST_TIME), + Get2D(panel_setting, time_travelled, (t - EARLIEST_TIME))); + Put2D(basement_equipment_light, time_travelled+1, (t - EARLIEST_TIME), + Get2D(basement_equipment_light, time_travelled, (t - EARLIEST_TIME))); + Put2D(ground_equipment_light, time_travelled+1, (t - EARLIEST_TIME), + Get2D(ground_equipment_light, time_travelled, (t - EARLIEST_TIME))); + Put2D(main_doors_state, time_travelled+1, (t - EARLIEST_TIME), + Get2D(main_doors_state, time_travelled, (t - EARLIEST_TIME))); + Put2D(basement_door_state, time_travelled+1, (t - EARLIEST_TIME), + Get2D(basement_door_state, time_travelled, (t - EARLIEST_TIME))); + Put2D(ground_door_state, time_travelled+1, (t - EARLIEST_TIME), + Get2D(ground_door_state, time_travelled, (t - EARLIEST_TIME))); + Put2D(upstairs_door_state, time_travelled+1, (t - EARLIEST_TIME), + Get2D(upstairs_door_state, time_travelled, (t - EARLIEST_TIME))); + Put2D(balcony_door_state, time_travelled+1, (t - EARLIEST_TIME), + Get2D(balcony_door_state, time_travelled, (t - EARLIEST_TIME))); + Put2D(conference_window_state, time_travelled+1, (t - EARLIEST_TIME), + Get2D(conference_window_state, time_travelled, (t - EARLIEST_TIME))); + Put2D(deutsch_door_state, time_travelled+1, (t - EARLIEST_TIME), + Get2D(deutsch_door_state, time_travelled, (t - EARLIEST_TIME))); + Put2D(basement_equipment_door_state, time_travelled+1, (t - EARLIEST_TIME), + Get2D(basement_equipment_door_state, time_travelled, (t - EARLIEST_TIME))); + Put2D(ground_equipment_door_state, time_travelled+1, (t - EARLIEST_TIME), + Get2D(ground_equipment_door_state, time_travelled, (t - EARLIEST_TIME))); + + Put2D(main_doors_smashed, time_travelled+1, (t - EARLIEST_TIME), + Get2D(main_doors_smashed, time_travelled, (t - EARLIEST_TIME))); + Put2D(basement_door_smashed, time_travelled+1, (t - EARLIEST_TIME), + Get2D(basement_door_smashed, time_travelled, (t - EARLIEST_TIME))); + Put2D(ground_door_smashed, time_travelled+1, (t - EARLIEST_TIME), + Get2D(ground_door_smashed, time_travelled, (t - EARLIEST_TIME))); + Put2D(upstairs_door_smashed, time_travelled+1, (t - EARLIEST_TIME), + Get2D(upstairs_door_smashed, time_travelled, (t - EARLIEST_TIME))); + Put2D(balcony_door_smashed, time_travelled+1, (t - EARLIEST_TIME), + Get2D(balcony_door_smashed, time_travelled, (t - EARLIEST_TIME))); + } + + time_travelled++; + + return true; +]; + +[ReplaceTravellingItem thing_type i; + if (PlayerHas(thing_type-->i)) + move thing_type-->(i+Exp(2,time_travelled)) to player; + else if (LocationOf(thing_type-->i) == prototype_interior) + move thing_type-->(i+Exp(2,time_travelled)) to prototype_interior; +]; + + +[FixBombSettings time_amount i; + for (i=0 : i < Exp(2,time_travelled) : i++) { + if (PlayerHas(bomb-->i) || (LocationOf(bomb-->i) == prototype_interior)) + if ((bomb-->i).time_value ~= NA_) + (bomb-->(i+Exp(2,time_travelled))).time_value + = (bomb-->i).time_value - time_amount; + (bomb-->i).time_value = NA_; + } +]; + +[FixFlashlightStates i; + for (i=0 : i < Exp(2,time_travelled) : i++) { + if (PlayerHas(flashlight-->i) || (LocationOf(flashlight-->i) == prototype_interior)) { + if (flashlight-->i has on) + give flashlight-->(i+Exp(2,time_travelled)) on; + else + give flashlight-->(i+Exp(2,time_travelled)) ~on; + } + give flashlight-->i ~on; + } +]; + + +!---------------------------------------------------- +! +! Little utility functions: + + +[IsOfType thing thing_type i; + for (i=0 : i < MAX_ITEM_COPIES : i++) + if (thing_type-->i == thing) + return true; + return false; +]; + +[AmHolding thing_type i; + for (i=0 : i < MAX_ITEM_COPIES : i++) + if (thing_type-->i ~= nothing && thing_type-->i in player) + return true; + return false; +]; + +[GetHeld thing_type i; + for (i=0 : i < MAX_ITEM_COPIES : i++) + if (thing_type-->i ~= nothing && thing_type-->i in player) + return thing_type-->i; + return false; +]; + +[IsIn thing_type loc i; + for (i=0 : i < MAX_ITEM_COPIES : i++) + if (thing_type-->i ~= nothing && thing_type-->i in loc) + return true; + return false; +]; + +[GetFrom thing_type loc i; + for (i=0 : i < MAX_ITEM_COPIES : i++) + if (thing_type-->i ~= nothing && thing_type-->i in loc) + return thing_type-->i; + return false; +]; + +![Present thing_type t; +! for (t=0 : t < MAX_ITEM_COPIES : t++) +! if (thing_type-->t ~= nothing && thing_type-->t in real_location) +! return true; +! return false; +!]; + +![GetPresent thing_type t; +! for (t=0 : t < MAX_ITEM_COPIES : t++) +! if (thing_type-->t ~= nothing && thing_type-->t in real_location) +! return thing_type-->t; +! return false; +!]; + +[BatteriesContained thing batteries i; + batteries = 0; + for (i=0 : i < MAX_ITEM_COPIES : i++) + if (battery-->i ~= nothing && battery-->i in thing) + batteries++; + return batteries; +]; + +[StartSiren; + if (siren_start_time == UNKNOWN_ || siren_start_time > my_time) + siren_start_time = my_time; +]; + +[MoveMoveableChildren old_loc new_loc x y; + while (child(old_loc)) { + x = nothing; + y = child(old_loc); + if ((y hasnt static) && (y ~= player)) { + x = y; + } + while (sibling(y)) { + y = sibling(y); + if ((y hasnt static) && (y ~= player)) { + x = y; + } + } + if (x ~= nothing) { + move x to new_loc; + } + else + break; + } +]; + +[ LocationOf x; + if (parent(x) == 0) + return x; + else + return LocationOf(parent(x)); +]; + +[ PlayerHas x; + if (parent(x) == 0) + return false; + if (parent(x) == player) + return true; + return PlayerHas(parent(x)); +]; + +[ Flashlit i; + for (i=0 : i < MAX_ITEM_COPIES : i++) { + if (flashlight-->i ~= nothing && (flashlight-->i in player or real_location) + && flashlight-->i has on) + return true; + } + return false; +]; + +[PrintTime t; + if (t == NA_) + return true; + + print (t/720), ":", ((t/12)%60)/10, (t/12)%10, ":", ((t%12)/2); + if ((t%2) == 0) + print "0"; + else + print "5"; + + if (t/(720*12) == 0) + print " am"; + else + print " pm"; +]; + +[PrintShortTime t; + print (t/720), ":", ((t/12)%60)/10, (t/12)%10; + + if (t/(720*12) == 0) + print " am"; + else + print " pm"; +]; + +[IncTime; + InformLibrary.end_turn_sequence(); +]; + +!! x == run_through, y == time_index + +[Put2D array x y thing; + array-->((x * (GAME_LENGTH+1)) + y) = thing; +]; + +!! x == run_through, y == time_index + +[Get2D array x y; + return array-->((x * (GAME_LENGTH+1)) + y); +]; + +!! x == run_through, y == time_index, z == thing_number + +[Put3D array x y z thing; + array-->( (z*(MAX_TIME_TRAVELS+1) + x)*(GAME_LENGTH+1) + y ) = thing; +]; + +!! x == run_through, y == time_index, z == thing_number + +[Get3D array x y z; + return array-->( (z*(MAX_TIME_TRAVELS+1) + x)*(GAME_LENGTH+1) + y ); +]; + +[Exp b e i result; + result = 1; + for (i=0 : ii).time_value); + } +]; + +[ObserveFlashlights i; + for (i=0 : i < MAX_ITEM_COPIES : i++) { + Put3D(flashlight_state, time_travelled, (my_time - EARLIEST_TIME), i, flashlight-->i has on); + } +]; + +[ObserveSiren siren_on; + siren_on = (siren_start_time ~= UNKNOWN_) && (siren_start_time < my_time); + Put2D(siren_state, time_travelled, my_time - EARLIEST_TIME, siren_on); +]; + +[ObservePanel; + Put2D(panel_setting, time_travelled, my_time - EARLIEST_TIME, control_panel.time_value); +]; + +[ObserveGroundLight light_array; + Put2D(light_array, time_travelled, my_time - EARLIEST_TIME, ground_equipment.lit); +]; + +[ObserveBasementLight light_array; + Put2D(light_array, time_travelled, my_time - EARLIEST_TIME, basement_light_switch.blown); +]; + +[ObserveBrokenDoor door door_smashed; + Put2D(door_smashed, time_travelled, my_time - EARLIEST_TIME, door.smashed); +]; + +[ObserveManualDoor door door_state door_status; + if (door has locked) + door_status = LOCKED_; + else { + if (door has open) + door_status = OPEN_; + else + door_status = CLOSED_; + } + Put2D(door_state, time_travelled, my_time - EARLIEST_TIME, door_status); +]; + +[ObserveAutomaticDoor door door_state door_status; + if (door has locked) + door_status = 0; + else + door_status = door.to_close_at; + Put2D(door_state, time_travelled, my_time - EARLIEST_TIME, door_status); +]; + +[ObserveLocations i; + Put2D(player_loc, time_travelled, (my_time - EARLIEST_TIME), parent(player)); + for (i=0 : i < MAX_ITEM_COPIES : i++) { + Put3D(bomb_loc, time_travelled, (my_time - EARLIEST_TIME), + i, parent(bomb-->i) ); + Put3D(id_card_loc, time_travelled, (my_time - EARLIEST_TIME), + i, parent(id_card-->i) ); + Put3D(equipment_key_loc, time_travelled, (my_time - EARLIEST_TIME), + i, parent(equipment_key-->i) ); + Put3D(deutsch_key_loc, time_travelled, (my_time - EARLIEST_TIME), + i, parent(deutsch_key-->i) ); + Put3D(flashlight_loc, time_travelled, (my_time - EARLIEST_TIME), + i, parent(flashlight-->i) ); + Put3D(battery_loc, time_travelled, (my_time - EARLIEST_TIME), + i, parent(battery-->i) ); + Put3D(cable_loc, time_travelled, (my_time - EARLIEST_TIME), + i, parent(cable-->i) ); + Put3D(crowbar_loc, time_travelled, (my_time - EARLIEST_TIME), + i, parent(crowbar-->i) ); + Put3D(notes_loc, time_travelled, (my_time - EARLIEST_TIME), + i, parent(notes-->i) ); + } +]; + +!---------------------------------------------------- +! +! 'Set' functions: (these take care of certain former actions every turn) + + +[SetBombs setting_now i; + for (i=0 : i < Exp(2,time_travelled) : i++) { + setting_now = Get3D(bomb_setting,time_travelled,my_time-EARLIEST_TIME,i); + (bomb-->i).time_value = setting_now; + } +]; + +[SetFlashlights setting_now i; + for (i=0 : i < Exp(2,time_travelled) : i++) { + setting_now = Get3D(flashlight_state,time_travelled,my_time-EARLIEST_TIME,i); + if (setting_now == true) + give flashlight-->i on; + else + give flashlight-->i ~on; + } +]; + +[SetPanel setting_array setting_now; + setting_now = Get2D(setting_array, time_travelled, my_time - EARLIEST_TIME); + control_panel.time_value = setting_now; +]; + +[SetBasementLight setting_array setting_now; + setting_now = Get2D(setting_array, time_travelled, my_time - EARLIEST_TIME); + basement_light_switch.blown = setting_now; +]; + +[SetGroundLight setting_array setting_now; + setting_now = Get2D(setting_array, time_travelled, my_time - EARLIEST_TIME); + ground_equipment.lit = setting_now; + if (setting_now) + give ground_light_switch on; + else + give ground_light_switch ~on; +]; + +[SetManualDoor door door_state door_status; + door_status = Get2D(door_state, time_travelled, my_time - EARLIEST_TIME); + if (door_status == LOCKED_) { + give door ~open; + give door locked; + } + if (door_status == CLOSED_) { + give door ~open; + give door ~locked; + } + if (door_status == OPEN_) { + give door open; + give door ~locked; + } + if (door_status == UNKNOWN_) { + print "Error: unknown door status needing to be set for some reason."; + } +]; + +[SetAutomaticDoor door door_state door_status; + door_status = Get2D(door_state, time_travelled, my_time - EARLIEST_TIME); + if (door_status == UNKNOWN_) { + give door ~open locked; + } + if (door_status > 0) { + give door open ~locked; + door.to_close_at = door_status; + } +]; + +[SetBrokenDoor door door_smashed door_status; + door_status = Get2D(door_smashed, time_travelled, my_time - EARLIEST_TIME); + if (door_status == UNKNOWN_) { + door.smashed = false; + } + if (door_status == true) { + door.smashed = true; + } + if (door_status == false) { + door.smashed = false; + } +]; + +[MoveFormerSelf run_through loc_next; + loc_next = Get2D(player_loc, run_through, my_time - EARLIEST_TIME); + + if (~~d_paradox) { + if (d_destroyed_prototype && ((former_self-->run_through) in limbo) && + (loc_next == prototype_interior)) { + d_paradox = true; + deadflag = 3; + Seperator(); + print (PrintTime) (my_time), "^^"; + print "Back in the Deutsch lab, the debris from the prototype + lies smoldering on the floor and no past self appears.^"; + print "^Time unravels...^"; + Devours(my_time); + } + else if (d_destroyed_prototype && (my_time == start_time)) { + d_paradox = true; + deadflag = 3; + Seperator(); + print (PrintTime) (my_time), "^^"; + print "Elsewhere, your past self enters the foyer and smells the + bitter smoke from a recent explosion.^"; + print "^Time unravels...^"; + Devours(my_time); + } + else { + if (loc_next == nothing) + move former_self-->run_through to limbo; + else + move former_self-->run_through to loc_next; + } + +! if ((~~d_paradox) && (~~d_escaped) && (~~d_caught)) +! print "<<< former self (", run_through, ") is in: ", (name) loc_next, " >>>^"; + } +]; + +!! Moves an object around according to the actions of former selves +!! Uses the item histories to work out when an item was moved, but since +!! that copy of the item may have been swapped for another (which is fine) +!! we must get the first available copy in the right location to be safe. +!! Also, we don't want to remove all normal objects when someone time-travels +!! so, since this only happens when the player is not present and no other moving +!! happens when the player is not present, we can get around it by only moving +!! objects when a former self is present in the same location. + +[MoveObject thing_type thing_loc i loc_now loc_next; + loc_now = Get3D(thing_loc,time_travelled-1,my_time-EARLIEST_TIME-1,i); + loc_next = Get3D(thing_loc,time_travelled-1,my_time-EARLIEST_TIME,i); + if (loc_now ~= loc_next) { + if (IsIn(thing_type, loc_now)) { + if (IsIn(former_self,LocationOf(GetFrom(thing_type, loc_now)))) { +! print "<<< Moving ", (name) thing_type-->i, " (", i, ") in ", (name) loc_now, +! " to ", (name) loc_next, " >>>^"; + move GetFrom(thing_type, loc_now) to loc_next; + } + else { + !! handle the odd case of object left in prototype when button pressed + if (LocationOf(GetFrom(thing_type, loc_now)) == prototype_interior) { +! print "<<< Moving ", (name) thing_type-->i, " (", i, ") in ", (name) loc_now, +! " to ", (name) loc_next, " >>>^"; + move GetFrom(thing_type, loc_now) to loc_next; + } + else if ((loc_now == basement_equipment_gloom) || (loc_now == ground_equipment_gloom)) { +! print "<<< Moving ", (name) thing_type-->i, " (", i, ") in ", (name) loc_now, +! " to ", (name) loc_next, " >>>^"; + move GetFrom(thing_type, loc_now) to loc_next; + } +! else { +! print "<<< Ignoring ", (name) thing_type-->0, " in ", (name) loc_now, +! " (wanted to move it to ", (name) loc_next, ") >>>^"; +! } + } + } +! else +! print "<<< Missing ", (name) thing_type-->0, " in ", (name) loc_now, +! " (wanted to move it to ", (name) loc_next, ") >>>^"; + } +]; + +!---------------------------------------------------- +! +! 'Maybe' functions: (these take care of former actions) + + +[MaybeExplodeBombs i; + for (i=0 : i < MAX_ITEM_COPIES : i++) + if (bomb-->i ~= nothing) { + if (LocationOf(bomb-->i) ~= limbo) { + if (((bomb-->i).time_value == my_time - 1) && + ((bomb-->i).left_over_seconds == 0)) + ExplodeBomb(i); + else if (((bomb-->i).time_value == my_time - 2) && + ((bomb-->i).left_over_seconds ~=0)) + ExplodeBomb(i); + } + } +]; + +[MaybeSing; + if (Get2D(dangerous_activity, time_travelled-1, my_time-EARLIEST_TIME-1) == SING_) + if (player notin limbo) + "You hear muffled singing from somewhere in the building."; +]; + +[MaybeShout; + if (Get2D(dangerous_activity, time_travelled-1, my_time-EARLIEST_TIME-1) == SHOUT_) + if (player notin limbo) + "You hear muffled shouting from somewhere in the building."; +]; + +!!! a little tricky to ensure that when two bombs are in same room that the one set +!!! has the same original setting as it should (ie is indistinguishable from former one) + +[MaybeSetBombs setting_now setting_next loc_now b i j; + for (i=0 : i < Exp(2,time_travelled-1) : i++) { + setting_now = Get3D(bomb_setting,time_travelled-1,my_time-EARLIEST_TIME-1,i); + setting_next = Get3D(bomb_setting,time_travelled-1,my_time-EARLIEST_TIME,i); + loc_now = Get3D(bomb_loc,time_travelled-1,my_time-EARLIEST_TIME-1,i); + if (setting_now ~= setting_next) { + if (IsIn(bomb, loc_now)) { + if (IsIn(former_self,LocationOf(GetFrom(bomb, loc_now)))) { + for (j=0 : j < MAX_ITEM_COPIES : j++) + if ((bomb-->j ~= nothing) && (bomb-->j in loc_now)) + if ((bomb-->j).time_value == setting_now) + b = bomb-->j; +! print "<<< setting bomb (via maybeset) >>>^"; + if (b ~= nothing) + b.time_value = setting_next; +! else +! print "<<>>^"; + } + } +! else +! print "<<0, " in ", (name) loc_now, +! " (wanted to set it to ", setting_next, ")>>>^"; + } + } +]; + +!!! a little tricky to ensure that when two flashlights are in same room that the one set +!!! has the same original setting as it should (ie is indistinguishable from former one) + +[MaybeSetFlashlights setting_now setting_next loc_now f i j; + for (i=0 : i < Exp(2,time_travelled-1) : i++) { + setting_now = Get3D(flashlight_state,time_travelled-1,my_time-EARLIEST_TIME-1,i); + setting_next = Get3D(flashlight_state,time_travelled-1,my_time-EARLIEST_TIME,i); + loc_now = Get3D(flashlight_loc,time_travelled-1,my_time-EARLIEST_TIME-1,i); + if (setting_now ~= setting_next) { + if (IsIn(flashlight, loc_now)) { + if (IsIn(former_self,LocationOf(GetFrom(flashlight, loc_now)))) { + for (j=0 : j < MAX_ITEM_COPIES : j++) + if ((flashlight-->j ~= nothing) && (flashlight-->j in loc_now)) + if ((flashlight-->j has on) == setting_now) + f = flashlight-->j; +! print "<<< setting flashlight (via maybeset) >>>^"; + if (f ~= nothing) { + if (setting_next == true) + give f on; + else + give f ~on; + } +! else +! print "<<>>^"; + } + } +! else +! print "<<0, " in ", (name) loc_now, +! " (wanted to set it to ", setting_next, ")>>>^"; + } + } +]; + +[MaybeSetPanel setting_array setting_now setting_next; + setting_now = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME - 1); + setting_next = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME); + if (setting_next ~= UNKNOWN_ && setting_next ~= setting_now) { + control_panel.time_value = setting_next; + } +]; + +[MaybeSetBasementLight setting_array setting_now setting_next; + setting_now = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME - 1); + setting_next = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME); + if (setting_next ~= UNKNOWN_ && setting_next ~= setting_now) { + basement_light_switch.blown = setting_next; + } +]; + +[MaybeSetGroundLight setting_array setting_now setting_next; + setting_now = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME - 1); + setting_next = Get2D(setting_array, time_travelled - 1, my_time - EARLIEST_TIME); + if (setting_next ~= UNKNOWN_ && setting_next ~= setting_now) { + ground_equipment.lit = setting_next; + if (setting_next) + give ground_light_switch on; + else + give ground_light_switch ~on; + } +]; + +[MaybeCloseAutomaticDoor door; + if (door.just_closed) + door.just_closed = false; + if (~~deadflag) + if (door.to_close_at == my_time - 1) + door.close_self(); +]; + +!! Opens/closes/locks/unlocks doors for the past self and catches paradoxes that could not +!! be seen, but where the locked/unlocked state of the door differs and interferes with the action. +!! Also works when the former self unlocks an unlocked door or locks +!! a locked door, but this door had the converse state and the key actually turns. + +[MaybeSetManualDoor door door_state past_door_status_now past_door_status_next + present_door_status_now the_action t; + + for (t=0 : ti) in (former_self-->t)) { + flash_i_batteries = BatteriesContained(flashlight-->i); + past_count = 0; + present_count = 0; + for (j=0 : j < MAX_ITEM_COPIES : j++) + if ((flashlight-->j) in (former_self-->t)) + if (BatteriesContained(flashlight-->j) == flash_i_batteries) + present_count++; + for (j=0 : j < MAX_ITEM_COPIES : j++) { + flash_j_loc = Get3D(flashlight_loc,t,my_time-EARLIEST_TIME,j); + flash_j_batteries = 0; + for (k=0 : kj)) + flash_j_batteries++; + } + if (flash_j_loc == former_self-->t) + if (flash_j_batteries == flash_i_batteries) + past_count++; + } + if (present_count ~= past_count) { + too_heavy = (past_count < present_count); + trouble = true; + } + } + } + BLOW_BASEMENT_LIGHT_: + if (Get2D(basement_equipment_light, time_travelled, my_time-EARLIEST_TIME-1) == true) + trouble = true; + } + if (trouble) { + d_paradox = true; + deadflag = 3; + Seperator(); + switch (action_de_jour) { + X_CCTV_: + print "In the foyer, your past self glances at a CCTV screen and sees you in the + shadowed corridor.^"; + X_UPSTAIRS_CORRIDOR_: + if (former_self-->t in balcony) + print "From the chilly balcony, your former self looks through the glass door + and sees you in the shadowed corridor.^"; + else + print "From the upstairs landing, your former self looks through the glass + and sees you in the shadowed corridor.^"; + X_UPSTAIRS_LANDING_: + print "From the second floor corridor, your former self looks through the glass door + and sees you in the shadowy landing.^"; + X_GROUND_CORRIDOR_: + print "From within the foyer, your former self looks through + the glass door and sees you in the shadowed corridor.^"; + X_FOYER_: + if (former_self-->t in upstairs_landing) + print "From the landing above, your former self looks down + and sees you.^"; + else + print "From the first floor corridor, your former self looks through + the glass door and sees you.^"; + X_BASEMENT_CORRIDOR_: + print "From the basement landing, your former self looks through the glass door + and sees you in the shadowed corridor.^"; + X_BASEMENT_LANDING_: + print "From the basement corridor, your former self looks through the glass door + and sees you in the shadowy landing.^"; + X_BALCONY_: + if (former_self-->t in upstairs_corridor) + print "From the second floor corridor, your former self looks through the glass door + and sees you on the chilly balcony.^"; + else + print "From within the darkened conference room, your former self looks out + and sees you on the chilly balcony.^"; + TAKE_FLASHLIGHT_: + if (too_heavy) + print (Nearby) 0, "your past self picks up a flashlight, but finds it + strangely heavy.^"; + else + print (Nearby) 0, "your past self picks up a flashlight, but finds it + strangely light.^"; + BLOW_BASEMENT_LIGHT_: + print "In the basement equipment room, your past self switches on the light + but there is no flicker, for it has already blown.^"; + } + if ((action_de_jour >= X_CCTV_) && (action_de_jour <= X_BALCONY_)) + print "^This is one of the all time most embarrassing ways + to destroy the city of Boston.^"; + print "^Time unravels...^"; + Devours(my_time); + } + } + } +]; + + +[CheckPassiveParadox t; + for (t=0 : t < time_travelled : t++) + if (LocationOf(former_self-->t) ~= limbo) { + CheckPlayerInRoom(t); + CheckStateOfSiren(t); + + CheckStateOfDoors(t); + + CheckStateOfGroundLight(t); + + CheckQuantityInRoom(bomb,bomb_loc,t); + CheckQuantityInRoom(id_card,id_card_loc,t); + CheckQuantityInRoom(equipment_key,equipment_key_loc,t); + CheckQuantityInRoom(deutsch_key,deutsch_key_loc,t); + CheckQuantityInRoom(flashlight,flashlight_loc,t); + CheckQuantityInRoom(battery,battery_loc,t); + CheckQuantityInRoom(cable,cable_loc,t); + CheckQuantityInRoom(crowbar,crowbar_loc,t); + CheckQuantityInRoom(notes,notes_loc,t); + + CheckStateOfFlashlights(t); + + if (former_self-->t in foyer) + CheckObjectsOnDesk(security_desk,t); + if (former_self-->t in conference_room) { + CheckObjectsOnDesk(conference_table,t); + CheckObjectsOnDesk(chair,t); + } + if (former_self-->t in deutsch_lab) + CheckObjectsOnDesk(bench,t); + if (former_self-->t in prototype_interior) + CheckTimeOnPanel(t); + + CheckTimesOnBombs(t); + } +]; + +[CheckStateOfDoors t fs_loc; + fs_loc = LocationOf(former_self-->t); + + switch (fs_loc) { + foyer: + CheckStateOfDoor(main_doors, main_doors_state, t, fs_loc); + CheckStateOfDoor(ground_door, ground_door_state, t, fs_loc); + CheckBrokenDoor(main_doors, main_doors_smashed, t, fs_loc); + CheckBrokenDoor(ground_door, ground_door_smashed, t, fs_loc); + ground_corridor: + CheckStateOfDoor(ground_door, ground_door_state, t, fs_loc); + CheckBrokenDoor(ground_door, ground_door_smashed, t, fs_loc); + CheckStateOfDoor(ground_equipment_door, ground_equipment_door_state, t, fs_loc); + ground_equipment: + CheckStateOfDoor(ground_equipment_door, ground_equipment_door_state, t, fs_loc); + basement_landing: + CheckStateOfDoor(basement_door, basement_door_state, t, fs_loc); + CheckBrokenDoor(basement_door, basement_door_smashed, t, fs_loc); + basement_corridor: + CheckStateOfDoor(basement_door, basement_door_state, t, fs_loc); + CheckBrokenDoor(basement_door, basement_door_smashed, t, fs_loc); + CheckStateOfDoor(basement_equipment_door, basement_equipment_door_state, t, fs_loc); + CheckStateOfDoor(deutsch_door, deutsch_door_state, t, fs_loc); + deutsch_lab: + CheckStateOfDoor(deutsch_door, deutsch_door_state, t, fs_loc); + prototype_interior: + CheckStateOfDoor(deutsch_door, deutsch_door_state, t, fs_loc); + upstairs_landing: + CheckStateOfDoor(upstairs_door, upstairs_door_state, t, fs_loc); + CheckBrokenDoor(upstairs_door, upstairs_door_smashed, t, fs_loc); + upstairs_corridor: + CheckStateOfDoor(upstairs_door, upstairs_door_state, t, fs_loc); + CheckStateOfDoor(balcony_door, balcony_door_state, t, fs_loc); + CheckBrokenDoor(upstairs_door, upstairs_door_smashed, t, fs_loc); + CheckBrokenDoor(balcony_door, balcony_door_smashed, t, fs_loc); + balcony: + CheckStateOfDoor(balcony_door, balcony_door_state, t, fs_loc); + CheckBrokenDoor(balcony_door, balcony_door_smashed, t, fs_loc); + CheckStateOfDoor(conference_window, conference_window_state, t, fs_loc); + conference_room: + CheckStateOfDoor(conference_window, conference_window_state, t, fs_loc); + default: + return false; + } +]; + +! this is a tiny bit of a hack, using the fact that OPEN_ is higher than CLOSED_, LOCKED_. +! and the fact that automatic doors which are open have values higher than OPEN_. + +[CheckStateOfDoor door door_state t fs_loc past_door_state fs_loc_last_turn; + past_door_state = Get2D(door_state,t,my_time-EARLIEST_TIME); + fs_loc_last_turn = Get2D(player_loc,t,my_time-EARLIEST_TIME-1); + + if (~~d_paradox) { + if ((past_door_state >= OPEN_) && (door hasnt open)) { + d_paradox = true; + deadflag = 3; + Seperator(); + print (Nearby) 0, "your former self enters ", (TheLower) fs_loc, + " and sees ", (the) door, " pulled closed.^"; + print "^Time unravels...^"; + Devours(my_time); + } + else if ((past_door_state < OPEN_) && (door has open)) { + d_paradox = true; + deadflag = 3; + Seperator(); + if (door ~= conference_window) { + if (fs_loc_last_turn ~= fs_loc) + print (Nearby) 0, "your former self enters ", (TheLower) fs_loc, + " and sees ", (the) door, " standing open.^"; + else + print (Nearby) 0, "your former self standing in ", (TheLower) fs_loc, + " sees ", (the) door, " open.^"; + } + else + print (Nearby) 0, "your former self enters ", (TheLower) fs_loc, + " and sees the shattered conference room window.^"; + print "^Time unravels...^"; + Devours(my_time); + } + } +]; + + +[CheckBrokenDoor door door_smashed t fs_loc past_door_smashed_now past_door_smashed_next; + past_door_smashed_now = Get2D(door_smashed,t,my_time-EARLIEST_TIME-1); + past_door_smashed_next = Get2D(door_smashed,t,my_time-EARLIEST_TIME); + if (~~d_paradox) { + if ((~~past_door_smashed_next) && door.smashed) { + d_paradox = true; + deadflag = 3; + Seperator(); + if (past_door_smashed_now) + print "In ", (TheLower) fs_loc, ", your former self sees the web of cracks in ", + (the) door, ".^"; + else + print "In ", (TheLower) fs_loc, ", your former self hears the crack of your + crowbar smashing into ", + (the) door, ".^"; + print "^Time unravels...^"; + Devours(my_time); + } + } + +]; + +[CheckTimesOnBombs t i j bomb_i_time bomb_j_time bomb_j_loc + past_count present_count fs_loc; + + fs_loc = LocationOf(former_self-->t); + + if (~~d_paradox) { + for (i=0 : i < MAX_ITEM_COPIES : i++) { + if (LocationOf(bomb-->i) == fs_loc) { + bomb_i_time = (bomb-->i).time_value; + past_count = 0; + present_count = 0; + for (j=0 : j < MAX_ITEM_COPIES : j++) + if (LocationOf(bomb-->j) == fs_loc) + if ((bomb-->j).time_value == bomb_i_time) + present_count++; + for (j=0 : j < MAX_ITEM_COPIES : j++) { + bomb_j_loc = Get3D(bomb_loc,t,my_time-EARLIEST_TIME,j); + bomb_j_time = Get3D(bomb_setting,t,my_time-EARLIEST_TIME,j); + if (((bomb_j_loc == fs_loc) || (parent(bomb_j_loc) == fs_loc))) + if (bomb_j_time == bomb_i_time) + past_count++; + } + if (past_count ~= present_count) { + d_paradox = true; + deadflag = 3; + Seperator(); + print (Nearby) 0, "your former self enters ", (TheLower) fs_loc, + " and sees a different value flashing on the explosive device's + timer.^"; + print "^Time unravels...^"; + Devours(my_time); + } + } + } + } + +]; + +[CheckStateOfFlashlights t i present_flashlights_on past_flashlights_on + fs_loc flash_loc flash_state; + fs_loc = LocationOf(former_self-->t); + if (~~d_paradox) { + for (i=0 : i < MAX_ITEM_COPIES : i++) { + flash_loc = Get3D(flashlight_loc,t,my_time-EARLIEST_TIME,i); + flash_state = Get3D(flashlight_state,t,my_time-EARLIEST_TIME,i); + if (flash_state && ((flash_loc == fs_loc) || (parent(flash_loc) == fs_loc))) + past_flashlights_on++; + if ((flashlight-->i has on) && (LocationOf(flashlight-->i) == fs_loc)) + present_flashlights_on++; + } + if (past_flashlights_on ~= present_flashlights_on) { + d_paradox = true; + deadflag = 3; + Seperator(); + if (past_flashlights_on < present_flashlights_on) + print (Nearby) 0, "your former self enters ", (TheLower) fs_loc, + " and sees a thin white beam of light shining where once + was darkness.^"; + else + print (Nearby) 0, "your former self enters ", (TheLower) fs_loc, + " and sees only darkness where once a thin white beam of light + was shining.^"; + print "^Time unravels...^"; + Devours(my_time); + } + } +]; + +! only need to check if in corridor with open door as this will catch all cases + +[CheckStateOfGroundLight t past_ground_light_state; + past_ground_light_state = Get2D(ground_equipment_light,t,my_time-EARLIEST_TIME); + + if (~~d_paradox) + if ((ground_light_switch has on) ~= past_ground_light_state) { + if ((former_self-->t in ground_corridor) && (ground_equipment_door has open)) { + d_paradox = true; + deadflag = 3; + Seperator(); + if (ground_light_switch has on) { + if (Get2D(ground_equipment_door_state,t,my_time-EARLIEST_TIME-1)==OPEN_) + print (Nearby) 0, "your former self enters the first floor corridor + and sees a pool of light spilling from the equipment room.^"; + else + print (Nearby) 0, "your former self opens the door to the first floor + equipment room and bright fluorescent light + spills over her.^"; + } + else { + if (Get2D(ground_equipment_door_state,t,my_time-EARLIEST_TIME-1)==OPEN_) + print (Nearby) 0, "your former self enters the first floor corridor + but does not see a pool of light spilling from the + equipment room.^"; + else + print (Nearby) 0, "your former self opens the door to the first floor + equipment room but no bright fluorescent light + spills over her.^"; + } + print "^Time unravels...^"; + Devours(my_time); + } + } +]; + +[CheckStateOfSiren t past_state siren_on; + past_state = Get2D(siren_state,t,my_time-EARLIEST_TIME); + siren_on = (siren_start_time ~= UNKNOWN_) && (siren_start_time < my_time); + + if (~~d_paradox) + if (past_state ~= siren_on) { + if (my_time - siren_start_time == 1) + print "^A piercing siren rings out.^"; + if (my_time - siren_start_time > 1) + print "^The siren wails.^"; + d_paradox = true; + deadflag = 3; + Seperator(); + print (Nearby) 0, "your former self cringes from the sound of the siren.^"; + print "^Time unravels...^"; + Devours(my_time); + } +]; + + +!! Only checks the bare contents of the room, not the containers, states etc. + +[CheckQuantityInRoom thing_type thing_loc t i present_count past_count; + present_count = 0; + past_count = 0; + + if (~~d_paradox) { + for (i=0 : i < Exp(2,t+1) : i++) { + if (parent(thing_type-->i) == LocationOf(former_self-->t)) + present_count++; + if (Get3D(thing_loc,t,my_time-EARLIEST_TIME,i) == LocationOf(former_self-->t)) + past_count++; + } + if (past_count ~= present_count) { + d_paradox = true; + deadflag = 3; + Seperator(); + print "Entering ", (TheLower) LocationOf(former_self-->t), + " your past self looks quickly about. "; + if (past_count > present_count) + print "Unlike the last time, her gaze passes straight over the place + where ", (the) thing_type-->0, + " had lain.^"; + else + print "As her glance falls upon ", (the) thing_type-->0, + " a moment of worry passes over her features.^"; + print "^Time unravels...^"; + Devours(my_time); + } + } +]; + +[CheckPlayerInRoom t player_loc_now player_loc_next fs_loc_now fs_loc_next; + + player_loc_now = Get2D(player_loc,time_travelled,my_time-EARLIEST_TIME-1); + player_loc_next = Get2D(player_loc,time_travelled,my_time-EARLIEST_TIME); + fs_loc_now = Get2D(player_loc,t,my_time-EARLIEST_TIME-1); + fs_loc_next = Get2D(player_loc,t,my_time-EARLIEST_TIME); + + if ((player_loc_next == fs_loc_next)) { + if (player_loc_now == nothing) { + d_paradox = true; + deadflag = 3; + Seperator(); + print "Someone appears beside you in the cramped chamber. + Soft hair and anxious eyes. It is you.^"; + print "^Time unravels...^"; + Devours(my_time); + } + else if (player_loc_now ~= player_loc_next) { !! if the player had moved... + d_paradox = true; + deadflag = 3; + Seperator(); + print "As you enter ", (TheLower) player_loc_next, + " you see your former self standing before you. + Hearing your soft footfall, she turns. Horror fills her eyes.^"; + print "^Time unravels...^"; + Devours(my_time); + } + else if (fs_loc_now ~= fs_loc_next) { !! if the former self had moved... + d_paradox = true; + deadflag = 3; + Seperator(); + print "You turn at the sound of footsteps. It is you.^"; + print "^Time unravels...^"; + Devours(my_time); + } + else + print "Error, former self saw player but neither had moved.^"; + } + else if ((player_loc_next == fs_loc_now) && (player_loc_now == fs_loc_next)) { + d_paradox = true; + deadflag = 3; + Seperator(); + print "As you enter ", (TheLower) player_loc_next, + ", your eyes catch upon a figure coming towards you. + She pauses, fear all about her.^"; + print "^Time unravels...^"; + Devours(my_time); + } + else if ((player_loc_next == deutsch_lab) && (fs_loc_next == prototype_interior)) { + d_paradox = true; + deadflag = 3; + Seperator(); + print "Hunched inside the prototype, your former self sees you through the open + hatch.^"; + print "^Time unravels...^"; + Devours(my_time); + } + else if ((player_loc_next == prototype_interior) && (fs_loc_next == deutsch_lab)) { + d_paradox = true; + deadflag = 3; + Seperator(); + print "As your past self looks around, her eyes catch on + something inside the prototype.^"; + print "^Time unravels...^"; + Devours(my_time); + } + +]; + +[CheckObjectsOnDesk desk t; + CheckObjectOnDesk(desk, t, bomb, bomb_loc); + CheckObjectOnDesk(desk, t, id_card, id_card_loc); + CheckObjectOnDesk(desk, t, equipment_key, equipment_key_loc); + CheckObjectOnDesk(desk, t, deutsch_key, deutsch_key_loc); + CheckObjectOnDesk(desk, t, flashlight, flashlight_loc); + CheckObjectOnDesk(desk, t, battery, battery_loc); + CheckObjectOnDesk(desk, t, cable, cable_loc); + CheckObjectOnDesk(desk, t, crowbar, crowbar_loc); + CheckObjectOnDesk(desk, t, notes, notes_loc); +]; + +[CheckObjectOnDesk desk t thing_type thing_loc present_count past_count i; + if (~~d_paradox) { + for (i=0 : i < Exp(2,t+1) : i++) { + if (thing_type-->i in desk) + present_count++; + if (Get3D(thing_loc,t,my_time-EARLIEST_TIME,i) == desk) + past_count++; + } + if (past_count ~= present_count) { + d_paradox = true; + deadflag = 3; + Seperator(); + print "Entering ", (TheLower) LocationOf(former_self-->t), + " your past self looks quickly about. "; + if (past_count > present_count) + print "Unlike the last time, her gaze passes straight over the place + on ", (the) desk, " where ", (the) thing_type-->0, + " had lain.^"; + else + print "As her glance falls upon ", (the) thing_type-->0, + " a moment of worry passes over her features.^"; + print "^Time unravels...^"; + Devours(my_time); + } + } +]; + +[CheckTimeOnPanel t old_setting; + old_setting = Get2D(panel_setting, t, my_time-EARLIEST_TIME); + if (~~d_paradox) + if (control_panel.time_value ~= old_setting) { + d_paradox = true; + deadflag = 3; + Seperator(); + print "Entering the prototype, your past self glances at the control panel, + seeing ", control_panel.time_value, " instead of ", old_setting, ".^"; + print "^Time unravels...^"; + Devours(my_time); + } +]; + + +!---------------------------------------------------- +! +! Endgame functions: + + +[CaughtInside t; + d_caught = true; + +!-- Initial method of being caught: + + if (my_time > FINAL_TIME) + print "^A quick noise from behind, then a strong grip on your wrist. + The guard is back -- time has slipped away from you.^"; + else if ((siren_start_time ~= UNKNOWN_) && (my_time - siren_start_time > siren_timeout)) + print "^As the siren shrieks out around you, you catch a glimpse of movement. + A sudden jolt, then you are wrestled to the ground. Security has arrived.^"; + else + print "Error: unknown reason for being caught^"; + +!-- Allow a small amount of time for bomb to explode before player dragged off... + + for (t=0 : (ti).time_value >= FINAL_TIME) && ~~(bomb-->i in player)) { + d_exploded = true; + if (LocationOf(bomb-->i) == deutsch_lab or prototype_interior) + d_destroyed_prototype = true; + for (j=0 : j < MAX_ITEM_COPIES : j++) + if (InBlastRadius(notes-->j,bomb-->i)) + d_destroyed_notes = true; + } +]; + +[ExplodeBomb i j t; + + if (d_exploded) + return true; + + d_exploded = true; + +!-- what exploded? + + if ((~~(d_escaped || d_detained)) && InBlastRadius(player,bomb-->i) ) + d_killed_by_bomb = true; + if (~~(d_escaped || d_detained)) + d_injured_by_bomb = true; + if (LocationOf(bomb-->i) == deutsch_lab or prototype_interior) + d_destroyed_prototype = true; + for (j=0 : j < MAX_ITEM_COPIES : j++) + if (InBlastRadius(notes-->j,bomb-->i)) + d_destroyed_notes = true; + for (t=0 : t < time_travelled : t++) + if (InBlastRadius(former_self-->t, bomb-->i)) { + d_fs_killed_by_bomb = true; + d_paradox = true; + } + for (t=0 : t < time_travelled : t++) + if ((LocationOf(former_self-->t) ~= limbo)) { + d_fs_hears_bomb = true; + d_paradox = true; + } + +!-- Consequences of explosion + + if (d_killed_by_bomb == true) { + print "^The bomb detonates. A wall of force rips through the room with savage + power, killing you immediately.^"; + if (~~d_fs_hears_bomb) { + for (t=0 : (my_time= FINAL_TIME - 3) { + print "The night beckons you from the open doors, but as you rush + forwards to meet it your hopes fail you -- security has arrived.^"; + d_caught = true; + DragPlayerOff(); + } + else if ((siren_start_time ~= UNKNOWN_) && (my_time - siren_start_time > siren_timeout - 2)) { + print "The night beckons you from the open doors, but as you rush + forwards to meet it your hopes fail you. With the siren shrieking out around you, + security has arrived.^"; + d_caught = true; + DragPlayerOff(); + } + +!-- Deal with the true escapes: + + else { + move player to limbo; + + print "You slip out into the night, darting quickly through the Cambridge + shadows until you reach the quiet corner where you left your car. + Exhausted, you gently start the cold motor and roll off towards the + interstate.^"; + +!-- Step through the rest of the time to check for paradox and/or explosion + + for (t=0 : (my_time About + * 'devours' -> About + * 'all' 'things' 'devours' -> About + * -> About; + +[ WalkthroughSub; + instant_action_this_turn = true; + print_ret "Hints and a walkthrough are located at http://devours.amirrorclear.net^ + You might also want to try the 'about' command.^^ + If you are unfamiliar with text adventures, then you may want to + learn the basics first at an introductory website such as + http://brasslantern.org/beginners/"; ]; + +Verb 'walkthrough' 'walkthru' 'hint' 'hints' 'help' + * -> Walkthrough; + +[ CreditsSub; + instant_action_this_turn = true; + print_ret "Written by half sick of shadows for IFComp 2004.^ + Beta tested by Stephen Bond.^ + Special thanks go to those who submitted detailed bug reports and suggestions + during the competition, notably: Peter Eckersley, Oliver Nash, + Hugo Thorvaldsen and Evin Robertson.^ + ^ + No rights are reserved by the author: + this work is in the public domain and may be freely copied and modified."; +]; + +Verb 'credits' + * -> Credits; + +[ InterleavingOnSub; + instant_action_this_turn = true; + poem_interleaving = true; + "The ending will now be in the original, interleaved, style."; +]; + +[ InterleavingOffSub; + instant_action_this_turn = true; + poem_interleaving = false; + "The ending will now be in the standard style."; +]; + +Verb 'interleaving' + * 'on' -> InterleavingOn + * 'off' -> InterleavingOff; + +[ ResetSub; print_ret "It is not clear what you are trying to do."; ]; + +Verb 'reset' 'stop' 'halt' 'defuse' + * noun -> Reset; + +Verb 'swipe' + * noun 'in' noun -> Insert + * noun 'through' noun -> Insert; + +[ CompleteModificationsSub; + if ((real_location == deutsch_lab) || (real_location == prototype_interior)) + <>; + else + "You would need to be near the prototype to do that."; +]; + +Verb 'complete' 'finish' + * 'modifications' -> CompleteModifications + * 'work' -> CompleteModifications + * 'changes' -> CompleteModifications + * 'alteration' -> CompleteModifications; + +[ ModifySub; + if ((noun == prototype) || (noun == control_panel) || (noun == nothing)) { + if ((real_location == deutsch_lab) || (real_location == prototype_interior)) + <>; + else + "You would need to be near the prototype to do that."; + } + "It is not clear what you are trying to do."; +]; + +Verb 'modify' 'change' 'alter' + * -> Modify + * noun -> Modify; + +[ SwitchSub; + if (noun has on) + <>; + else + <>; +]; + +Verb 'flick' 'flip' + * noun -> Switch; + +Extend 'switch' first + * noun -> Switch; + +[ SwingAtSub; if (second == nothing) + print_ret "You swing ", (the) noun, " through the air, harmlessly."; + else if (IsOfType(noun, crowbar)) + <>; + else if ((second == conference_window) || (second ofclass AutomaticDoor)) { + print_ret (The) noun, " bounces harmlessly off the ", + (the) second, "."; + } + else + <>; +]; + +Extend 'swing' first + * held -> SwingAt + * held 'at' noun -> SwingAt + * held 'into' noun -> SwingAt + * held 'through' noun -> SwingAt; + + +[ AttackWithSub; if (IsOfType(second, crowbar)) + <>; + else if ((noun == conference_window) || (noun ofclass AutomaticDoor)) { + if (second == nothing) + print_ret "You are not strong enough to break ", + (the) noun, " by yourself."; + else + print_ret (The) second, " is not heavy enough to break ", + (the) noun, "."; + } + else + <>; +]; + +Extend 'attack' + * noun 'with' 'fist' -> AttackWith + * noun 'with' 'foot' -> AttackWith + * noun 'with' 'hand' -> AttackWith + * noun 'with' held -> AttackWith; + +[ JumpDownSub; if (real_location == balcony) + Jumped(); + else if ((real_location == upstairs_landing) || (real_location == foyer)) { + print "You hit the ground hard. Maybe you should have used the stairs.^"; + <>; + } + else + "There is nothing to jump down to."; +]; + +Extend 'jump' first + * 'down' -> JumpDown; + +[ ClimbDownSub; if (real_location == balcony) + Jumped(); + else if ((real_location == upstairs_landing) || (real_location == foyer)) + <>; + else + "There is nothing to climb down to."; +]; + +Extend 'climb' first + * 'down' -> ClimbDown; + +[ LockSimpleSub k; +if (noun has lockable) { + if (noun.with_key_type == nothing) + "You do not have the key."; + k = GetHeld(noun.with_key_type); + if (k == nothing) + "You do not have the key."; + <>; + } + else + "That doesn't seem to be something you can lock."; + +]; + +Extend 'lock' first + * noun -> LockSimple; + + +[ UnlockSimpleSub k; +if (noun has lockable) { + if (noun.with_key_type == nothing) + "You do not have the key."; + k = GetHeld(noun.with_key_type); + if (k == nothing) + "You do not have the key."; + <>; + } + else + "That doesn't seem to be something you can unlock."; + +]; + +Extend 'unlock' first + * noun -> UnlockSimple; + +[ UseSub; + "You will have to be more specific about your action."; +]; + +Verb 'use' + * -> Use + * noun -> Use; + +[ PlantSub p; + p = parent(noun); + ; + if (parent(noun) ~= p) + if (noun ofclass Bomb_) + if (noun.time_value == NA_) + "(you may also want to set the timer)"; +]; + +[ PlantInSub p; + p = parent(noun); + ; + if (parent(noun) ~= p) + if (noun ofclass Bomb_) + if (noun.time_value == NA_) + "(you may also want to set the timer)"; +]; + +[ PlantOnSub p; + p = parent(noun); + ; + if (parent(noun) ~= p) + if (noun ofclass Bomb_) + if (noun.time_value == NA_) + "(you may also want to set the timer)"; +]; + +Verb 'plant' + * noun -> Plant + * noun 'in' noun -> PlantIn + * noun 'on' noun -> PlantOn; + +Extend 'look' + * noun -> Examine; + +[ WaitSecondsSub t; + if (noun == 0) { + instant_action_this_turn = true; + "That didn't take long."; + } + if (noun < 0) { + instant_action_this_turn = true; + "If you could do that, you wouldn't have built the prototype."; + } + print "Time passes.^"; + if (noun%5 ~= 0) { + if (noun/5 > 0) + IncTime(); + } + for (t=1 : t FINAL_TIME - my_time) + time_in_turns = FINAL_TIME - my_time + 2; + + if (time_in_turns == 0 && (noun%5 ==0)) { + instant_action_this_turn = true; + "That didn't take long."; + } + if (time_in_turns < 0) { + instant_action_this_turn = true; + "If you could do that, you wouldn't have built the prototype."; + } + print "Time passes.^"; + if (noun%5 ~= 0) { + if (time_in_turns > 0) + IncTime(); + } + for (t=1 : t= 24) return -1; + if (minute >= 60) return -1; + if (second >= 60) return -1; + if (hour > 4) return 18000; ! this is to avoid integer overflow + if (word == 'pm') + return 18000; + + return (hour*60 + minute) * 60 + second; +]; + +! based on the code from the DM4. +! looks for a time in the format 2:39 or 4:17:18 + +[ TimeOfDay first_word second_word at length colons illegal_char digits hr mn se i; + first_word = NextWordStopped(); + if (first_word == -1) + return GPR_FAIL; + at = WordAddress(wn-1); + length = WordLength(wn-1); + for (i=0: ii) { + ':': if (colons == 0 && digits>0 && i 2) + illegal_char = true; + default: illegal_char = true; + } + } + if (length < 3 || length > 8 || illegal_char || colons == 0) + return GPR_FAIL; + for (i=0: at->i~=':': i++, hr=hr*10) + hr = hr + at->i - '0'; + hr = hr/10; + mn = ((at->(i+1) - '0') * 10) + at->(i+2) - '0'; + if (colons == 2) { + i = i+3; + se = ((at->(i+1) - '0') * 10) + at->(i+2) - '0'; + } + second_word = NextWordStopped(); + parsed_number = HoursMinsSecsWordToTime(hr, mn, se, second_word); + if (parsed_number == -1) return GPR_FAIL; if (second_word ~= 'pm' or 'am') wn--; + return GPR_NUMBER; +]; + +Extend 'wait' + * number -> WaitSeconds + * number 'seconds' -> WaitSeconds + * number 'second' -> WaitSeconds + * number 'turns' -> WaitTurns + * number 'turn' -> WaitTurns + * 'until' TimeOfDay -> WaitUntil; + + +[ ShoutSub t; + print "You shout loudly.^"; + for (t=0 : tt notin limbo) && + ((siren_start_time == UNKNOWN_) || (siren_start_time > my_time))) { + + d_paradox = true; + deadflag = 3; + Seperator(); + print (Nearby) 0, "your former self hears the muffled sounds of your + shouting.^^Something of an anticlimactic way to kill + so many millions of people...^"; + print "^Time unravels...^"; + Devours(my_time); + return true; + } + } + Put2D(dangerous_activity,time_travelled,my_time-EARLIEST_TIME,SHOUT_); + MaybeSing(); + return true; +]; + +Extend only 'shout' replace + * -> Shout + * topic -> Shout; + +Verb 'yell' + * -> Shout + * topic -> Shout; + +Verb 'tear' + * noun -> Attack + * 'up' noun -> Attack; + +Extend 'remove' first ! so that 'remove battery' works + * multiinside -> Remove; + +[ HoldDownWithSub; + if (noun == alarm_button || noun == basement_button || noun == first_button || + noun == second_button || noun == silver_button || noun == exit_button ) { + "The button is set into a vertical surface, + making it impossible to hold it down with another object."; + } + else + "It is not clear what that is supposed to accomplish."; +]; + +Extend 'hold' first ! so that 'remove battery' works + * 'down' noun -> Push + * 'down' noun 'with' noun -> HoldDownWith + * 'down' noun 'using' noun -> HoldDownWith; + +[ ChallengeSub; + instant_action_this_turn = true; + if (challenge) + "The challenge has already been initiated."; + if (first_turn) { + challenge = true; + siren_timeout = CHALLENGE_SIREN_TIMEOUT; + early_guard_time = CHALLENGE_EARLY_GUARD_TIME; + "The game is now in its most challenging form. + Three key elements have been changed to make success considerably + more difficult. This challenge is not + required for a successful completion of the game. It is just here + for those who, upon finishing, wish there was a little bit more.^ + ^ + If you do want to take up the challenge, then remember to initiate this + mode each time you begin play."; + } + else + "The challenge can only be initiated in the first turn."; +]; + +[ EndChallengeSub; + instant_action_this_turn = true; + challenge = false; + siren_timeout = DEFAULT_SIREN_TIMEOUT; + early_guard_time = EARLIEST_TIME; + "The game is now at its standard difficulty."; +]; + +Verb 'challenge' + * -> Challenge + * 'on' -> Challenge + * 'mode' 'on' -> Challenge + * 'off' -> EndChallenge + * 'mode' 'off' -> EndChallenge; + +Verb 'start' 'begin' 'initiate' + * 'challenge' -> Challenge + * 'challenge' 'mode' -> Challenge; + +Verb 'end' + * 'challenge' -> EndChallenge + * 'challenge' 'mode' -> EndChallenge; + +!============================================================================ + diff --git a/lib b/lib new file mode 160000 index 0000000..aec9e41 --- /dev/null +++ b/lib @@ -0,0 +1 @@ +Subproject commit aec9e4131b092ed33213b9891e1dc2b9574edf99