--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ 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
+this service 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.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+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
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE 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.
+
+ END OF TERMS AND CONDITIONS
+\f
+ Appendix: 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
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+Z-Tornado: A ZSCII-graphics two player weather action game.
+
+This is a port of Tornado (http://www.lionking.org/~kiza/linux/tornado)
+
+Z-Tornado is released under the terms of the GNU General Public License.
+For details, see the file COPYING, which should be part of this source
+distribution.
+
+To build it, you need Inform 6.x (I only tried 6.21, so I don't know about
+other versions). Just compile tornado.inf, which includes all other files.
+You can get Inform at the IF-Archive. See:
+
+http://mirror.ifarchive.org/indexes/if-archiveXinfocomXcompilersXinform6Xexecutables.html
+
+For details on how to compile Inform sources on your platform, please look
+at the documentation of your compiler.
+
+To play it, you need a Z-code interpreter that supports timed input. Look
+at the IF-Archive for an interpreter for your platform:
+
+http://mirror.ifarchive.org/indexes/if-archiveXinfocomXinterpreters.html
+
+You can mail me at sfruehling@aon.at.
+
+Enjoy!
--- /dev/null
+! Z-Tornado - Two player weather action game
+!
+! Tornado is copyright (C) 2000-2002 Oliver Feiler
+! http://www.lionking.org/~kiza/linux/tornado
+! Inform version copyright (c) 2003 Sophie Frühling (sfruehling@aon.at)
+!
+! This program is free software; you can redistribute it and/or modify
+! it under the terms of the GNU General Public License as published by
+! the Free Software Foundation; either version 2 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 General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License
+! along with this program; if not, write to the Free Software
+! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+! Grafix except weather
+
+[ DrawSnowWorld i;
+ @set_cursor 5 1;
+ for (i = 0: i < fields: i++) {
+ print (char) snow_world->i;
+ if (i && i%screen_width == 0) new_line;
+ }
+];
+
+[ DrawUserInterface x;
+ x = dialog_x - 2;
+ @set_cursor 6 x; print ",___________________________________,";
+ @set_cursor 7 x; print "| Z - Tornado |";
+ @set_cursor 8 x; print "| s = Snow r = Rain |";
+ @set_cursor 9 x; print "| h = Hail l = Lightning |";
+ @set_cursor 10 x; print "| t = Tornado c = Current Scores |";
+ @set_cursor 11 x; print "| q = Quit o = Highscores |";
+ @set_cursor 12 x; print "+-----------------------------------+";
+ @set_cursor screen_height 1;
+];
+
+[ ClearUserInterface x y;
+ x = dialog_x - 2;
+ for (y = 6: y <= 12: y++) {
+ @set_cursor y x; spaces (37);
+ }
+];
+
+[ DrawDialogWindow x;
+ x = dialog_x - 2;
+ @set_cursor 6 x; print ",___________________________________,";
+ @set_cursor 7 x; print "| |";
+ @set_cursor 8 x; print "| |";
+ @set_cursor 9 x; print "| |";
+ @set_cursor 10 x; print "| |";
+ @set_cursor 11 x; print "+-----------------------------------+";
+];
+
+[ ClearDialogWindow x y;
+ x = dialog_x - 2; y = 6;
+ for (y = 6: y <= 11: y++) {
+ @set_cursor y x; spaces (37);
+ }
+];
+
+[ DrawStatusLine x y;
+ y = screen_height;
+ @set_cursor y 1;
+ PrintPlayerName(player1, player1_name);
+ x = screen_width/2 - 13;
+ @set_cursor y x;
+ if (player1_left < 100) print " ";
+ if (player1_left < 10) print " ";
+ print player1_left; print "%";
+ print " | Windspeed: ";
+ if (windspeed >= 0) print " ";
+ print windspeed; print " | ";
+ if (player2_left < 100) print " ";
+ if (player2_left < 10) print " ";
+ print player2_left; print "%";
+ x = screen_width - 16;
+ @set_cursor y x;
+ PrintPlayerName(player2, player2_name);
+ @set_cursor screen_height 1;
+];
+
+[ PrintPlayerName current_player the_array i;
+ if (current_player) print "*";
+ else print " ";
+ for (i = 2: i <= the_array->1 + 1: i++)
+ print (char) the_array->i;
+];
+
+[ DrawCurrentScores x;
+ x = dialog_x - 1;
+ DrawDialogWindow();
+ @set_cursor 7 x;
+ PrintPlayerName(0, player1_name);
+ @set_cursor 8 dialog_x;
+ print (longnr) player1_score;
+ @set_cursor 9 x;
+ PrintPlayerName(0, player2_name);
+ @set_cursor 10 dialog_x;
+ print (longnr) player2_score;
+];
+
+[ DrawHighScores x y;
+ x = dialog_x - 2;
+ @set_cursor 5 x; print ",___________________________________,";
+ @set_cursor 6 x; print "| Highscores |";
+ for (y = 7: y < 17: y++) {
+ x = dialog_x - 2;
+ @set_cursor y x; print "|";
+ @set_cursor y dialog_x;
+ PrintHighScoreName(y - 7);
+ x = dialog_x + 26;
+ @set_cursor y x;
+ PrintHighScoreNumber(y - 7);
+ x = dialog_x + 34;
+ @set_cursor y x; print "|";
+ }
+ x = dialog_x - 2;
+ @set_cursor 17 x; print "+-----------------------------------+";
+];
+
+[ ClearHighScoreWindow x y;
+ x = dialog_x - 2;
+ for (y = 5: y <= 17: y++) {
+ @set_cursor y x;
+ spaces (37);
+ }
+];
+
+[ DrawWinningScreen x;
+ x = dialog_x + 9;
+ @set_cursor 7 x; print "Player ";
+ if (player1_left) print 1; else print 2;
+ print " wins!";
+ x = dialog_x + 8;
+ @set_cursor 8 x; print "Your score is ";
+ if (player1_left) print (longnr) player1_score;
+ else print (longnr) player2_score;
+ print ".";
+ x = dialog_x + 3;
+ @set_cursor 9 x; print "Do you want to play again?";
+ x = dialog_x + 13;
+ @set_cursor 10 x; print "(y/n)";
+ @set_cursor screen_height 1;
+];
+
+! ----------- Extra-game information ---------------
+
+[ InfoTitle x;
+ @split_window 1; @set_window 1;
+ @set_cursor 1 1; style reverse;
+ spaces (0->33); x = (0->33)/2 - 10;
+ @set_cursor 1 x;
+ print "Z - T O R N A D O";
+ style roman; @set_window 0;
+];
+
+[ About;
+ @erase_window -1;
+ InfoTitle();
+ print "^^This is a fairly straight port of the C version of ~Tornado~,",
+ " release 1.2, written by Oliver Feiler and Rene Puls in or about",
+ " 2000, which in turn appears to be the port of a C64 game of the",
+ " same name.^^";
+ print "The screen is something between 64 and 80 by 24, instead of 80 x 25.",
+ " There is, of course, no network support, and no demo version. (But",
+ " you can emulate the latter by having the computer play against",
+ " itself. See (I)nstructions for details.)^";
+ print "Apart from that, it should work just like the C version, except that",
+ " it is a little slower, because I can't pause the game for less than",
+ " 1/10 of a second.^^";
+ print "Release 2 features a few cosmetic changes -- it now puts the cursor",
+ " outside the playfield while drawing the weather, which looks a lot",
+ " better -- and bugfixes: most importantly, the tornado used to erase",
+ " completely wrong stuff; there were also a few bugs that crept up when",
+ " piling up snow too high.^^";
+ print "Z-Tornado was written using Inform (http://www.inform-fiction.org),",
+ " and mainly tested on Unix Frotz 2.43.^^";
+ print "Thanks to Kevin Bracey (SameGame.inf), Torbj@:orn Andersson (robots.",
+ "inf) and Julian Arnold (z-life.inf) for inspiration and",
+ " encouragement. (To quote from ~SameGame.inf~, ~Anyone looking at",
+ " this source file for inspiration probably needs their head",
+ " examined.~) Thank you. ;) There are numerous other Z-Machine abuse",
+ " source files, but these were the ones I looked at.^^";
+ print "Thanks to Jim Fisher (http://www.onyxring.org) for the tip on",
+ " randomising random().^^";
+ print "Since the original code was released under GPL, this game is",
+ " released under GPL as well, which means there is ABSOLUTELY NO",
+ " WARRANTY OF ANY KIND, and you can get the messy source code,",
+ " too, from the games/source/inform directory of http://www.",
+ "ifarchive.org or (preferably) one of its mirrors.^^";
+ print "For more information about ~Tornado~, have a look at the webpage at",
+ " http://www.lionking.org/@@126kiza/linux/tornado/.^^";
+ print "[Hit any key]^";
+ Read();
+];
+
+! This is pretty much copy + paste from the man page, plus some more
+[ Instructions;
+ @erase_window -1;
+ InfoTitle();
+ print "^From the "; style bold; print "Tornado"; style roman;
+ print " man page:^^";
+ print "~The object of the game "; style bold; print "tornado"; style roman;
+ print " is to destroy your opponent's house with the powers of rain, snow,",
+ " hail, lightning and the tornado.^^";
+ print "~After the game is started the two players enter their names. If you",
+ " leave the field blank the computer will take the player's part. You",
+ " can see two houses with each player's name in the corner below it and",
+ " a cloud on top of the screen, the sky. The player whose turn it is",
+ " has an asterisk "; style bold; print "*"; style roman;
+ print " next to his name.^^";
+ print "~From the menu in the center of the screen each player now picks a",
+ " weather phenomenon. A second box will appear where you can enter",
+ " the aim you would like to use. You may have noticed the value ";
+ style underline; print "Windspeed"; style roman;
+ print " in the mid bottom of the screen by now. Ideally you would take aim ";
+ style bold; print "2"; style roman;
+ print " if windspeed is "; style bold; print "-2"; style roman;
+ print " for example and then your rain/hail/snow/tornado would go straight",
+ " down the cloud. However, it's chosen randomly if the rain appears on",
+ " the left side of the cloud or the right side, so aiming might be not",
+ " that easy as it looks like.^^";
+ print "~If you hit your opponent's house (or your own) the percentage counter",
+ " will decrease depending on how much damage you did. If the counter is",
+ " down to "; style bold; print "0%"; style roman;
+ print " the player loses the game.^^";
+ print "~The keys you can use in the game are:^";
+ style bold; print "s"; style roman; print " selects snow^";
+ print " Snow is a defensive weapon. If you hit a house with^",
+ " snow, it creates a coating that hail cannot destroy.^",
+ " Only rain can be used to destroy that layer of snow.^",
+ " Lightning and tornado are not effected.^";
+ style bold; print "r"; style roman; print " selects rain^";
+ print " Destroys one row of the house. Can be used to melt a^",
+ " row of snow.^";
+ style bold; print "h"; style roman; print " selects hail^";
+ print " This will destroy two rows of the house, but cannot^",
+ " destroy a snow coating.^";
+ style bold; print "l"; style roman; print " selects lightning^";
+ print " Splits the house into two pieces. Not influenced by^",
+ " wind.^";
+ style bold; print "t"; style roman; print " selects tornado^";
+ print " Not as effective as lightning but the tornado goes^",
+ " straight to the bottom of the house as well.^";
+ style bold; print "q"; style roman; print " quits the game^";
+ style bold; print "o"; style roman; print " show the highscores^";
+ style bold; print "c"; style roman; print " show current player scores~^";
+ print "[End of quote.]^^";
+ print "To run the game in ~demo~ mode, just don't fill in the players'",
+ " names, so the computer has to play against itself. (It can still",
+ " get a highscore.) There is currently no way to stop it during a",
+ " game, though, short of quitting the interpreter. Sorry for the",
+ " inconvenience.^^";
+ print "The ~colour~ referred to by the menu is white on black. If your",
+ " interpreter doesn't support colour like it should (e.g. Unix Frotz",
+ " 2.32) just toggle it off. If your interpreter doesn't support",
+ " colour at all, you won't notice.^^";
+ print "If your interpreter doesn't support timed input properly, I can't",
+ " help you, sorry. You can hit some key repeatedly to make the game",
+ " go on, but it won't be very much fun, I guess.^^";
+ print "Note that you can't change the screen size after starting up, so",
+ " don't do that.^^";
+ print "Enjoy!^^";
+ print "[Hit any key]^";
+ Read();
+];
+
+[ Banner i;
+ style bold;
+ print "Z - T O R N A D O";
+ style roman;
+ print "^A two-player weather action game^";
+ print "Yet another abuse of the Z-Machine^";
+ print "Copyright (c) 2003 by Sophie Fr@:uhling (sfruehling@@64aon.at)^";
+ print "A port of the C port of the C64 game ~Tornado~^";
+ print "The C version is copyright (c) 2000-2002 by Oliver Feiler^";
+ print "Release ", (0-->1) & $03ff, " / Serial number ";
+ for (i = 18: i < 24: i++) print (char) 0->i;
+ print " / Inform v"; inversion; new_line;
+];
+
+[ DrawTitleScreen i;
+ @erase_window -1;
+ print "^^^^^^^^^^^^^^^^^^^";
+ i = 0->33; if (i > 30) i = (i - 30)/2;
+ style bold; font off; spaces(i);
+ print " Z - T O R N A D O^";
+ style roman; new_line; spaces(i);
+ print " [Please press a key]^";
+ font on;
+ box
+ " ,/+++*++***+****++++++***+@@92, "
+ " (*+++*****+++++***+++****++)"
+ " `@@92++******+*++*++*****+++*/'"
+ " `@{B0}*,.,*@{B0}'`@{B0}*,.,*@{B0}`@{B0}*,.,*@{B0}'"
+ " ___ / / / / /"
+ " ||| / / / / /"
+ " /-------'|`-@@92 / / / / /"
+ " /'/////////////`@@92 / / / / /"
+ " |---------------| / / / / /"
+ " |-,_____,--,__,-| / / / / /"
+ " |-|__|__|--|++|-| / / / / /"
+ " |-|__|__|--|o+|-| / / / / /"
+ " |__________|__|_| / / / / /";
+ Read();
+ @erase_window -1;
+];
+
--- /dev/null
+! Z-Tornado - Two player weather action game
+!
+! Tornado is copyright (C) 2000-2002 Oliver Feiler
+! http://www.lionking.org/~kiza/linux/tornado
+! Inform version copyright (c) 2003 Sophie Frühling (sfruehling@aon.at)
+!
+! This program is free software; you can redistribute it and/or modify
+! it under the terms of the GNU General Public License as published by
+! the Free Software Foundation; either version 2 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 General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License
+! along with this program; if not, write to the Free Software
+! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+! (The AI is called Erwin for unknown reasons.)
+
+! The new improved AI (for the old, non-improved version, have a look at
+! the C source :)
+[ ErwinChoice;
+ ! Choose snow randomly from time to time.
+ if (random(5) == 1) return 'S';
+ ! If the cloud is right above the enemy house and it has >75%
+ ! then we strike with lightning to do most damage.
+ ! If the cloud is close to the enemy house and it has >75%
+ ! then we strike with tornado.
+ ! If the cloud is far away from the enemy house
+ ! then we strike with hail.
+ ! If the place where we would like to hit is covered with snow
+ ! then we use rain to get rid of it.
+ if (player1) {
+ if (((CountDestroyed(' ', house2_x, house2_y, 17, 10) - SPACES) < 25)
+ && (cloud_x >= 40))
+ return 'L';
+ else if (((CountDestroyed(' ', house2_x, house2_y, 17, 10) - SPACES) < 25)
+ && (cloud_x >= 30))
+ return 'T';
+ else if (CountSnow(house2_x, house2_y, 17, 10) > 5)
+ return 'R';
+ else
+ return 'H';
+ } else {
+ if (((CountDestroyed(' ', house1_x, house1_y, 17, 10) - SPACES) < 25)
+ && (cloud_x <= 15))
+ return 'L';
+ if (((CountDestroyed(' ', house1_x, house1_y, 17, 10) - SPACES) < 25)
+ && (cloud_x <= 25))
+ return 'T';
+ else if (CountSnow(house1_x, house1_y, 17, 10) > 5)
+ return 'R';
+ else
+ return 'H';
+ }
+];
+
+[ ErwinAim input;
+ ! For lightning, we don't need to aim and can return immediately
+ if (input == 'L') return 0;
+ ! In case of snow, we aim at our own house
+ if (input == 'S') {
+ if (player1) {
+ if (windspeed <= 0)
+ return (Abs(windspeed * 20) + (-3 - cloud_x)) / 20;
+ else
+ return (-Abs(windspeed * 20) + (-3 - cloud_x)) / 20;
+ } else {
+ if (windspeed <= 0)
+ return (Abs(windspeed * 20) + (69 - cloud_x)) / 20;
+ else
+ return (-Abs(windspeed * 20) + (60 - cloud_x)) / 20;
+ }
+ }
+ ! Otherwise, we aim at the opponent's house
+ else if (player1) {
+ if (windspeed <= 0)
+ return (Abs(windspeed * 20) + (69 - cloud_x)) / 20;
+ else
+ return (-Abs(windspeed * 20) + (60 - cloud_x)) / 20;
+ } else {
+ if (windspeed <= 0)
+ return (Abs(windspeed * 20) + (-3 - cloud_x)) / 20;
+ else
+ return (-Abs(windspeed * 20) + (-3 - cloud_x)) / 20;
+ }
+];
+
+[ Abs num;
+ if (num < 0)
+ return -num;
+ return num;
+];
--- /dev/null
+! Z-Tornado - Two player weather action game
+!
+! Tornado is copyright (C) 2000-2002 Oliver Feiler
+! http://www.lionking.org/~kiza/linux/tornado
+! Inform version copyright (c) 2003 Sophie Frühling (sfruehling@aon.at)
+!
+! This program is free software; you can redistribute it and/or modify
+! it under the terms of the GNU General Public License as published by
+! the Free Software Foundation; either version 2 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 General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License
+! along with this program; if not, write to the Free Software
+! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Array hghscr_arr -> 7;
+Array hghscr_tmparr -> 7;
+[ InitHighScores i j tmp;
+ print "^^[Trying to read highscore file]^";
+ @restore highscore_array 220 highscore_file -> i;
+ ! We couldn't read in the highscore file so we set up a new
+ ! highscore
+ if (i < 220) {
+ print "^[Couldn't read highscore file]^^";
+ print "[Please press a key]^"; Read();
+ tmp = 11000;
+ Nullify(hghscr_arr);
+ Nullify(hghscr_tmparr);
+ for (i = 0: i < 10: i++) {
+ for (j = i*22: j < i*22 + 15: j++)
+ highscore_array->j = '-';
+ tmp = tmp - 1000;
+ AddShort(hghscr_arr, hghscr_tmparr, tmp);
+ for (: j < (i+1)*22: j++)
+ highscore_array->j = hghscr_arr->(j - (i*22 + 15));
+ }
+ }
+];
+
+Array tmp_hscr -> 7;
+[ AddToHighScore player_name scr_arr i;
+ for (i = 0: i < 10: i++) {
+ LookUpHighScore(tmp_hscr, i);
+ if (CompareLongs(scr_arr, tmp_hscr) > 0) {
+ InsertScoreTable(player_name, scr_arr, i);
+ rtrue;
+ }
+ }
+];
+
+! Copies the score at num into hs_array
+[ LookUpHighScore hs_array num i tmp;
+ tmp = num*22 + 15;
+ for (i = 0: i < 7: i++, tmp++)
+ hs_array->i = highscore_array->tmp;
+];
+
+[ InsertScoreTable pl_nm scr_arr num i tmp;
+ ! Shift all lower scores by 22
+ for (i = 219: i >= (num + 1)*22: i--)
+ highscore_array->i = highscore_array->(i - 22);
+ ! Insert the name
+ for (i = num*22, tmp = 2: tmp < 17: i++, tmp++)
+ highscore_array->i = pl_nm->tmp;
+ ! Insert the score
+ for (i = num*22 + 15, tmp = 0: tmp < 7: i++, tmp++)
+ highscore_array->i = scr_arr->tmp;
+];
+
+[ ShowCurrentScores;
+ DrawCurrentScores();
+ DrawStatusLine();
+ Read();
+ ClearDialogWindow();
+ DrawSnowWorld();
+];
+
+! The high score window may overlap
+! with some part of a house or snow
+[ ShowHighScores;
+ ClearHighScoreWindow();
+ DrawHighScores();
+ DrawStatusLine();
+ Read();
+ ClearHighScoreWindow();
+ DrawSnowWorld();
+];
+
+[ PrintHighScoreName num i;
+ for (i = num*22 : i < num*22 + 15: i++)
+ print (char) highscore_array->i;
+];
+
+[ PrintHighScoreNumber num i;
+ i = num*22 + 15;
+ ! Right-align numbers
+ while (i < (num+1)*22 - 1 && highscore_array->i == 0) {
+ print (char) ' '; i++;
+ }
+ for (: i < (num+1)*22: i++)
+ print highscore_array->i;
+];
+
+!------------------ Numbers Juggling -----------------
+! Long numbers for calculating and printing out scores
+! The long numbers can have up to 7 digits.
+
+[ Nullify num_array i;
+ for (i = 0: i < 7: i++)
+ num_array->i = 0;
+];
+
+[ CopyArray dest_array src_array i;
+ for (i = 0: i < 7: i++)
+ dest_array->i = src_array->i;
+];
+
+! This appears not to work if dest_array is one of the source arrays
+[ AddLongs dest_array array1 array2 i tmp plus;
+ for (i = 6, plus = 0: i >= 0: i--) {
+ tmp = array1->i + array2->i;
+ if (plus) tmp++;
+ if (tmp > 9) {
+ plus = 1;
+ tmp = tmp%10;
+ }
+ else plus = 0;
+ dest_array->i = tmp;
+ }
+];
+
+Array short_array -> 7;
+[ AddShort dest_array num_array num;
+ ShortToArray(short_array, num);
+ AddLongs(dest_array, num_array, short_array);
+];
+
+[ ShortToArray num_array num i tmp;
+ num_array->0 = 0;
+ num_array->1 = 0;
+ for (i = 2, tmp = 10000: i < 7: i++, tmp = tmp/10) {
+ num_array->i = num/tmp;
+ num = num%tmp;
+ }
+];
+
+Array mult_array -> 7;
+Array culm_array -> 7;
+Array multitmp_array -> 7;
+[ Multiply dest_array num_array num i j tmp plus;
+ if (num == 0) {
+ Nullify(dest_array);
+ rtrue;
+ }
+ Nullify(culm_array);
+ ShortToArray(short_array, num);
+ i = 0;
+ while (short_array->i == 0) i++;
+ for (: i < 7: i++) {
+ Nullify(mult_array);
+ Nullify(multitmp_array);
+ for (j = 6: j >= 0: j--) {
+ tmp = num_array->j * short_array->i;
+ if (plus) tmp = tmp + plus;
+ if (tmp > 9) {
+ plus = tmp/10;
+ tmp = tmp%10;
+ }
+ else plus = 0;
+ mult_array->j = tmp;
+ }
+ Shift(mult_array, 6 - i);
+ AddLongs(multitmp_array, culm_array, mult_array);
+ Nullify(mult_array);
+ AddLongs(culm_array, multitmp_array, mult_array);
+ }
+ CopyArray(dest_array, culm_array);
+];
+
+Array shift_array -> 7;
+[ Shift the_array num i;
+ Nullify(shift_array);
+ for (i = num: i < 7: i++)
+ shift_array->(i-num) = the_array->i;
+ CopyArray(the_array, shift_array);
+];
+
+[ CompareLongs array1 array2 i;
+ for (i = 0: i < 7: i++) {
+ if (array1->i < array2->i)
+ return -1;
+ if (array1->i > array2->i)
+ return 1;
+ }
+ return 0;
+];
+
+[ longnr num_array i;
+ i = 0;
+ ! Don't print out leading zeroes
+ while (i < 6 && num_array->i == 0)
+ i++;
+ for (: i < 7: i++)
+ print num_array->i;
+];
+
--- /dev/null
+! Z-Tornado - Two player weather action game
+!
+! Tornado is copyright (C) 2000-2002 Oliver Feiler
+! http://www.lionking.org/~kiza/linux/tornado
+! Inform version copyright (c) 2003 Sophie Frühling (sfruehling@aon.at)
+!
+! This program is free software; you can redistribute it and/or modify
+! it under the terms of the GNU General Public License as published by
+! the Free Software Foundation; either version 2 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 General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License
+! along with this program; if not, write to the Free Software
+! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Release 2;
+
+! Screen stuff
+Global screen_height;
+Global screen_width;
+Global dialog_x; ! dialog box cursor for player input
+Global cloud_x;
+! Can be switched off in terps where colour doesn't work properly
+! (For all I know only useful in Unix Frotz 2.32, where timed input
+! doesn't work like it should either)
+Global colour = 1;
+
+! Player stuff
+! 1 if current player, otherwise 0
+Global player1;
+Global player2;
+Array player1_name -> 18;
+Array player2_name -> 18;
+Global player1_ai = 0;
+Global player2_ai = 0;
+Global player1_left = 100;
+Global player2_left = 100;
+! Can handle scores up to 9999999, which should be more than enough
+Array player1_score -> 7;
+Array player2_score -> 7;
+
+! House stuff
+! Position relative to screen
+Global house1_x;
+Global house1_y;
+Global house2_x;
+Global house2_y;
+! How many spaces does the house initially contain?
+Constant SPACES = 32;
+
+! Weather stuff
+Global windspeed;
+Global randseed = 0;
+! 80 x 24 grid, discounting 1 row for statusline and 4 for cloud
+Array snow_world -> 1520;
+! Actual entries of snow_world
+Global fields = 0;
+
+! Highscores
+Array highscore_file string "ZTORNADO.HGH";
+Array highscore_array -> 220;
+
+! Add degree character to Zcharacter table
+Zcharacter table + '@{B0}';
+
+Include "draw.inf";
+Include "erwin.inf";
+Include "scores.inf";
+Include "weather.inf";
+
+[ Main input;
+ if (TestTerp() == 0) return;
+ DrawTitleScreen();
+ InitHighScores();
+ while ((input = Menu()) ~= 'Q') {
+ switch (input) {
+ 'A':
+ About();
+ 'C':
+ if (colour) colour = 0;
+ else colour = 1;
+ 'I':
+ Instructions();
+ 'P':
+ Game();
+ }
+ }
+ Quit();
+];
+
+[ Menu ch;
+ @erase_window -1;
+ print "^^^";
+ Banner();
+ print "----------------------^";
+ print "(A) About Z-Tornado^",
+ "(C) Toggle colour (currently ";
+ if (colour) print "on";
+ else print "off";
+ print ")^",
+ "(I) Instructions^",
+ "(P) Play Z-Tornado^",
+ "(Q) Quit^^";
+ while (1) {
+ ch = Read();
+ switch (ch) {
+ 'A', 'C', 'I', 'P', 'Q':
+ return ch;
+ }
+ }
+];
+
+[ Game; Init(); Tornado(); Bye(); ];
+
+Array score_array->7;
+[ Tornado quitting tmp_score;
+ while (1) {
+ InitGame();
+ while (1) {
+ @erase_window 1;
+ DrawSnowWorld();
+ DrawCloud(0);
+ windspeed = random(11) - 6;
+ if (player1) {
+ player1 = 0; player2 = 1;
+ quitting = Play(player2_ai);
+ } else {
+ player2 = 0; player1 = 1;
+ quitting = Play(player1_ai);
+ }
+ if (player1_left <= 0) {
+ tmp_score = 100
+ - ((CountDestroyed(' ', house2_x, house2_y, 17, 10) - SPACES)*100)/138;
+ CopyArray(score_array, player2_score);
+ Multiply(player2_score, score_array, tmp_score);
+ break;
+ }
+ if (player2_left <= 0) {
+ tmp_score = 100
+ - ((CountDestroyed(' ', house1_x, house1_y, 17, 10) - SPACES)*100)/138;
+ CopyArray(score_array, player1_score);
+ Multiply(player1_score, score_array, tmp_score);
+ break;
+ }
+ if (quitting) return;
+ }
+ DrawStatusLine();
+ AddToHighScore(player1_name, player1_score);
+ AddToHighScore(player2_name, player2_score);
+ if (ContinueGame() == 'N')
+ return;
+ }
+];
+
+[ Play ai x input aim destroyed;
+ DrawStatusLine();
+ ! We have a human player
+ if (ai == 0) {
+ while (1) {
+ input = PlayerChoice();
+ if (input == 'Q')
+ rtrue;
+ ! lightning: player doesn't have to aim
+ ! tornado: we'll draw the tornado cloud before aiming
+ if (input == 'L' or 'T')
+ break;
+ if (input == 'H' or 'R' or 'S') {
+ aim = GetAim();
+ break;
+ }
+ if (input == 'C')
+ ShowCurrentScores();
+ else if (input == 'O')
+ ShowHighScores();
+ }
+ } else { ! The computer chooses
+ if (player1)
+ input = ErwinChoice(player1_left);
+ else
+ input = ErwinChoice(player2_left);
+ aim = ErwinAim(input);
+ }
+ destroyed = 0;
+ switch (input) {
+ 'H':
+ x = cloud_x + random(14) - 1;
+ destroyed = DrawWeather(x, windspeed + aim, ':', 2);
+ 'R':
+ x = cloud_x + random(14) - 1;
+ destroyed = DrawWeather(x, windspeed + aim, '/', 1);
+ 'S':
+ x = cloud_x + random(14) - 1;
+ DrawSnow(x, windspeed + aim);
+ 'L':
+ destroyed = DrawLightning(cloud_x - 7 + random(25));
+ 'T':
+ DrawTornadoCloud();
+ if (ai == 0) aim = GetAim();
+ else Pause(2); ! So the player can see the cloud for a while
+ destroyed = DrawTornado(cloud_x, windspeed + aim);
+ }
+ player2_left = 100
+ - ((CountDestroyed(' ', house2_x, house2_y, 17, 10)
+ + CountSnow(house2_x, house2_y, 17, 10) - SPACES)*100)/138;
+ player1_left = 100
+ - ((CountDestroyed(' ', house1_x, house1_y, 17, 10)
+ + CountSnow(house1_x, house1_y, 17, 10) - SPACES)*100)/138;
+ ! (You get points for destroying your own house, too)
+ if (player1) {
+ CopyArray(score_array, player1_score);
+ AddShort(player1_score, score_array, destroyed*destroyed);
+ } else {
+ CopyArray(score_array, player2_score);
+ AddShort(player2_score, score_array, destroyed*destroyed);
+ }
+ DrawStatusLine();
+ rfalse;
+];
+
+[ PlayerChoice ch;
+ DrawUserInterface();
+ DrawStatusLine();
+ while (1) {
+ ch = Read();
+ switch (ch) {
+ 'S', 'H', 'T', 'Q', 'R', 'L', 'C', 'O':
+ ClearUserInterface();
+ DrawSnowWorld();
+ return ch;
+ }
+ }
+];
+
+[ GetAim num;
+ DrawDialogWindow();
+ DrawStatusLine();
+ @set_cursor 8 dialog_x;
+ print "Aim?";
+ @set_cursor 9 dialog_x;
+ num = ReadNumber();
+ @set_cursor screen_height 1;
+ ClearDialogWindow();
+ DrawSnowWorld();
+ return num;
+];
+
+! Get the position of x y in snow_world array
+[ GetLoc x y;
+ if (x < 1 || x > screen_width || y < 5 || y > screen_height)
+ rfalse;
+ if (y == 5) x--;
+ return (y - 5)*screen_width + x;
+];
+
+[ CountDestroyed ch x y wid hgt i j n count;
+ for (i = x: i < x + wid: i++) {
+ for (j = y: j < y + hgt: j++) {
+ n = GetLoc(i, j);
+ if (snow_world->n == ch)
+ count++;
+ }
+ }
+ return count;
+];
+
+[ CountSnow xx yy wid hgt;
+ return CountDestroyed('*', xx, yy, wid, hgt);
+];
+
+[ ChangeWorld x y num i;
+ for (i = 0: i < num: i++)
+ ChangeSnowWorld(' ', x + i, y);
+];
+
+[ ChangeSnowWorld ch xx yy x;
+ x = GetLoc(xx, yy);
+ if (x < fields)
+ snow_world->x = ch;
+];
+
+! ----------- Initialising and game ending stuff -------------
+
+[ TestTerp;
+ screen_width = 0->33;
+ screen_height = 0->32;
+ if (screen_width < 64)
+ print "Your interpreter detected a screen width of only ",
+ screen_width, ".^";
+ if (screen_height < 24)
+ print "Your interpreter detected a screen height of only ",
+ screen_height, ".^";
+ if (screen_width < 64 || screen_height < 24) {
+ print "To play Tornado you need at least 64 x 24.^^";
+ rfalse;
+ }
+ if (screen_width > 80) screen_width = 80;
+ screen_height = 24;
+ if ((0->1) & 128 == 0) {
+ print "Your interpreter apparently doesn't support timed events.",
+ " This game should be pretty tiresome to play without, sorry.^";
+ Read();
+ }
+ if ($32-->0 == 0) {
+ print "Your interpreter doesn't obey the Z-Machine standard. Z-Tornado",
+ " will probably not work correctly on such an interpreter.^";
+ Read();
+ }
+];
+
+[ Init y;
+ y = 0->32;
+ dialog_x = screen_width/2 - 16;
+ @split_window y;
+ @set_window 1;
+ if (colour) @set_colour 9 2;
+ house1_x = 5;
+ house1_y = screen_height - 10;
+ house2_x = screen_width - 21;
+ house2_y = screen_height - 10;
+ fields = screen_height*screen_width - 5*screen_width;
+ InitSnowWorld();
+ @erase_window 1;
+ DrawSnowWorld();
+ DrawCloud(10);
+ player1_ai = 0;
+ player2_ai = 0;
+ GetNames();
+];
+
+! There might be some bug in there, because Windows Frotz 2002 doesn't draw
+! the dialog window correctly after asking for the first player's name
+[ GetNames i;
+ DrawDialogWindow();
+ for (i = 2: i < 17: i++) {
+ player1_name->i = ' ';
+ player2_name->i = ' ';
+ }
+ @set_cursor 8 dialog_x;
+ print "Please enter your name Player 1";
+ @set_cursor 9 dialog_x;
+ player1_name->0 = 15;
+ read player1_name 0;
+ if (player1_name->1 == 0) {
+ ("Computer").print_to_array(player1_name);
+ player1_ai = 1;
+ }
+ @set_cursor 8 dialog_x;
+ print "Please enter your name Player 2";
+ @set_cursor 9 dialog_x;
+ print " ";
+ @set_cursor 9 dialog_x;
+ player2_name->0 = 15;
+ read player2_name 0;
+ if (player2_name->1 == 0) {
+ ("Computer").print_to_array(player2_name);
+ player2_ai = 1;
+ }
+ @set_cursor screen_height 1;
+];
+
+[ InitGame;
+ @erase_window 1;
+ player1_left = 100;
+ player2_left = 100;
+ player1 = 0;
+ player2 = 1;
+ Nullify(player1_score);
+ Nullify(player2_score);
+ InitSnowWorld();
+ DrawSnowWorld();
+ DrawCloud(10);
+];
+
+[ InitSnowWorld i;
+ for (i = 0: i < fields: i++)
+ snow_world->i = ' ';
+ InitHouse(0);
+ InitHouse(1);
+];
+
+Array building table
+ " ___ "
+ " ||| "
+ " /-------'|`-@@92 "
+ "/'/////////////`@@92"
+ "|---------------|"
+ "|-,_____,--,__,-|"
+ "|-|__|__|--|++|-|"
+ "|-|__|__|--|o+|-|"
+ "|----------|++|-|"
+ "|__________|__|_|";
+
+Array temp_array -> 20;
+[ InitHouse nr i j x y tmp;
+ if (nr) {
+ x = house1_x;
+ y = house1_y;
+ } else {
+ x = house2_x;
+ y = house2_y;
+ }
+ temp_array->0 = 17;
+ for (j = 1: j <= 10: j++) {
+ tmp = GetLoc(x, y + j - 1);
+ (building-->j).print_to_array(temp_array);
+ for (i = 2: i < 19: i++)
+ snow_world->tmp++ = temp_array->i;
+ }
+];
+
+[ ContinueGame yesno;
+ DrawDialogWindow();
+ DrawWinningScreen();
+ yesno = Read();
+ while (yesno ~= 'Y' && yesno ~= 'N')
+ yesno = Read();
+ ClearDialogWindow();
+ return yesno;
+];
+
+[ Bye y;
+ @erase_window 1;
+ y = screen_height - 2;
+ @set_cursor y 1;
+ @set_colour 1 1;
+ style roman;
+ @erase_window -1;
+];
+
+[ Quit x;
+ @erase_window -1;
+ print "^^[Trying to save highscore file]^";
+ @save highscore_array 220 highscore_file -> x;
+ if (x == 0)
+ print "^[Couldn't save the highscore file, sorry.]^";
+ print "^^Thanks for playing Tornado!^^";
+];
+
+! ---------------- Low level routines ---------------------
+
+! Read in a character/digit from the keyboard
+[ Read x k;
+ if (randseed > 0)
+ @read_char 1 x;
+ else {
+ ! This should make the random function more random.
+ @read_char 1 1 SeedRand -> k;
+ for (k = 0: k < randseed: k++)
+ random(1);
+ }
+ ! Convert lower case to upper case so we only have to test
+ ! for half of the cases
+ if ('a' <= x && x <= 'z')
+ return x - ('a' - 'A');
+ return x;
+];
+
+[ SeedRand; randseed++; rfalse; ];
+
+! Read in numbers from -99 to 999 (We really only need -9 to 9)
+! If the player doesn't type a number, or anything, we return 0.
+Array num_array->6;
+[ ReadNumber x y neg tens sum;
+ num_array->0 = 3;
+ read num_array 0;
+ if (num_array->1 == 0)
+ return 0;
+ x = 2;
+ if (num_array->2 == '-') {
+ x++;
+ neg = 1;
+ }
+ for (sum = 0: x < num_array->1 + 2: x++) {
+ if (num_array->x >= '0' && num_array->x <= '9') {
+ for (tens = 1, y = num_array->1: y + 1 > x: y--)
+ tens = tens * 10;
+ sum = sum + (num_array->x - '0') * tens;
+ }
+ else break;
+ }
+ if (neg) sum = -sum;
+ return sum;
+];
+
+! Pauses for x/10 seconds
+[ Pause x t;
+ @read_char 1 x Interrupt -> t;
+];
+
+[ Interrupt; rtrue; ];
--- /dev/null
+! Z-Tornado - Two player weather action game
+!
+! Tornado is copyright (C) 2000-2002 Oliver Feiler
+! http://www.lionking.org/~kiza/linux/tornado
+! Inform version copyright (c) 2003 Sophie Frühling (sfruehling@aon.at)
+!
+! This program is free software; you can redistribute it and/or modify
+! it under the terms of the GNU General Public License as published by
+! the Free Software Foundation; either version 2 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 General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License
+! along with this program; if not, write to the Free Software
+! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+! Next Generation Weather Function
+! rain (strength 1) and hail (strength 2)
+Array weather_array -> 13;
+[ DrawWeather x shift ch strength tmp i num_moved num_destroyed xx starty yy;
+ num_destroyed = 0;
+ yy = 5; xx = x;
+ starty = 5;
+ ! Init weather_array
+ for (i = 0: i < 13: i++) {
+ if (i%3 == 0)
+ weather_array->i = ch;
+ else
+ weather_array->i = ' ';
+ }
+ num_moved = 1;
+ while (num_moved > 0) {
+ num_moved = 0;
+ ! move each character
+ for (i = 0: i < 13: i++) {
+ ! bottom, left, or right border
+ if ((yy >= house1_y + 10) || (xx >= screen_width) || (xx <= 1))
+ weather_array->i = strength;
+ ! skip if this object has disappeared (weather_array->i >= strength)
+ if ((weather_array->i ~= ' ' or ch) && weather_array->i >= strength) {
+ xx++; continue;
+ }
+ num_moved++;
+ ! did we hit something?
+ ! no hit (there is a space character at xx yy)
+ if (CountDestroyed(' ', xx, yy, 1, 1) == 1) {
+ if (weather_array->i == ' ' or ch) {
+ @set_cursor yy xx;
+ print (char) weather_array->i;
+ }
+ }
+ ! we have hit something
+ else {
+ if (weather_array->i == ' ' or ch)
+ weather_array->i = 1;
+ else
+ (weather_array->i)++;
+ ! if ch == hail and we've hit snow, don't delete
+ if ((ch == ':') && (CountDestroyed('*', xx, yy, 1, 1) == 1))
+ ! "expire" the object
+ weather_array->i = strength;
+ else {
+ ! draw the object
+ @set_cursor yy xx;
+ print (char) ch;
+ ChangeSnowWorld(' ', xx, yy);
+ num_destroyed++;
+ }
+ }
+ xx++;
+ }
+ yy++;
+ xx = x + shift*(yy - 5);
+ @set_cursor screen_height 1;
+ Pause(2);
+ }
+ @set_cursor screen_height 1;
+ Pause(10);
+ ! delete the rain/hail/whatever (whatever ?)
+ xx = x;
+ num_moved = 1;
+ while (num_moved > 0) {
+ num_moved = 0;
+ for (i = 0: i < 13: i++) {
+ if (starty >= yy || starty >= house1_y + 10)
+ break;
+ if (xx + 13 < 1 || xx > screen_width)
+ continue;
+ tmp = GetLoc(xx, starty);
+ if (tmp < fields && snow_world->tmp == ' ') {
+ @set_cursor starty xx;
+ print (char) ' ';
+ }
+ xx++;
+ num_moved++;
+ }
+ starty++;
+ xx = x + shift*(starty - 5);
+ @set_cursor screen_height 1;
+ Pause(1);
+ }
+ return num_destroyed;
+];
+
+! Kianga's Next Generation Snow Machine
+! Includes Special SnowLogic(tm)
+Array snow_x -> 13;
+Array snow_y -> 13;
+Array snow_startx -> 13;
+Array snow_starty -> 13;
+[ DrawSnow x shift xx yy i num_moved tmp;
+ yy = 5; xx = x;
+ ! Put snow in array
+ for (i = 0: i < 13: i++) {
+ if (i%3 == 0)
+ weather_array->i = '*';
+ else
+ weather_array->i = ' ';
+ snow_x->i = x + i;
+ snow_startx->i = x + i;
+ snow_y->i = yy;
+ snow_starty->i = yy;
+ }
+ num_moved = 1;
+ while (num_moved > 0) {
+ num_moved = 0;
+ ! move each character
+ for (i = 0: i < 13: i++) {
+ ! bottom, left, or right border
+ if ((snow_y->i >= house1_y + 10)
+ || (snow_x->i >= screen_width) || (snow_x->i <= 1))
+ weather_array->i = 1;
+ ! skip if this object has disappeared (weather_array->i >= strength)
+ if ((weather_array->i ~= ' ' or '*') && weather_array->i >= 1)
+ continue;
+ num_moved++;
+ ! did we hit something?
+ ! no hit
+ if (CountDestroyed(' ', snow_x->i, snow_y->i, 1, 1) == 1) {
+ if (weather_array->i == ' ' or '*') {
+ xx = snow_x->i;
+ yy = snow_y->i;
+ @set_cursor yy xx;
+ print (char) weather_array->i;
+ }
+ }
+ ! we've hit something
+ else {
+ weather_array->i = 1;
+ if (snow_y->i > 5) {
+ xx = snow_x->i - shift;
+ yy = snow_y->i - 1;
+ @set_cursor yy xx;
+ print (char) '*';
+ ChangeSnowWorld('*', xx, yy);
+ }
+ }
+ ! bottom
+ if (snow_y->i == screen_height - 1) {
+ weather_array->i = 1;
+ xx = snow_x->i;
+ yy = snow_y->i;
+ if (CountDestroyed(' ', xx, yy, 1, 1) == 1) {
+ @set_cursor yy xx;
+ print (char) '*';
+ ChangeSnowWorld('*', xx, yy);
+ }
+ }
+ ! move the object
+ (snow_y->i)++;
+ snow_x->i = snow_x->i + shift;
+ }
+ @set_cursor screen_height 1;
+ Pause(2);
+ }
+ @set_cursor screen_height 1;
+ Pause(10);
+ ! delete the snow
+ num_moved = 1;
+ while (num_moved > 0) {
+ num_moved = 0;
+ for (i = 0: i < 13: i++) {
+ if (snow_starty->i >= snow_y->i)
+ continue;
+ xx = snow_startx->i;
+ yy = snow_starty->i;
+ tmp = GetLoc(xx, yy);
+ if ((tmp < fields) && (snow_world->tmp == ' ')) {
+ @set_cursor yy xx;
+ print (char) ' ';
+ }
+ num_moved++;
+ (snow_starty->i)++;
+ snow_startx->i = snow_startx->i + shift;
+ }
+ @set_cursor screen_height 1;
+ Pause(1);
+ }
+];
+
+! Probably the ugliest function in the whole program.
+[ DrawLightning x xx y num_destroyed;
+ ! Is needed if screen_width is smaller than 80, maybe due to some
+ ! bug somewhere else
+ DrawStatusLine();
+ xx = x + 6; y = 5;
+ if (player1)
+ num_destroyed = CountDestroyed(' ', house2_x, house2_y, 17, 10);
+ else
+ num_destroyed = CountDestroyed(' ', house1_x, house1_y, 17, 10);
+ ! draw it...
+ @set_cursor 5 xx; print "||";
+ ChangeWorld(xx, 5, 2);
+ @set_cursor 6 xx; print "//";
+ ChangeWorld(xx, 6, 2); xx--;
+ @set_cursor 7 xx; print "//@@92@@92";
+ ChangeWorld(xx, 7, 4); xx--;
+ @set_cursor 8 xx; print "//";
+ ChangeWorld(xx, 8, 2); xx = x + 7;
+ @set_cursor 8 xx; print "@@92@@92";
+ ChangeWorld(xx, 8, 2); xx = x + 3;
+ @set_cursor 9 xx; print "||";
+ ChangeWorld(xx, 9, 2); xx = x + 8;
+ @set_cursor 9 xx; print "@@92@@92";
+ ChangeWorld(xx, 9, 2); xx++;
+ @set_cursor 10 xx; print "@@92@@92";
+ ChangeWorld(xx, 10, 2); xx--;
+ @set_cursor 11 xx; print "//@@92@@92";
+ ChangeWorld(xx, 11, 4); xx--;
+ @set_cursor 12 xx; print "//";
+ ChangeWorld(xx, 12, 2); xx = x + 11;
+ @set_cursor 12 xx; print "@@92@@92";
+ ChangeWorld(xx, 12, 2); xx = x + 7;
+ @set_cursor 13 xx; print "||";
+ ChangeWorld(xx, 13, 2); xx--;
+ @set_cursor screen_height 1;
+ Pause(2);
+ @set_cursor 14 xx; print "//@@92@@92";
+ ChangeWorld(xx, 14, 4); xx--;
+ @set_cursor 15 xx; print "//";
+ ChangeWorld(xx, 15, 2); xx = x + 9;
+ @set_cursor 15 xx; print "@@92@@92";
+ ChangeWorld(xx, 15, 2); xx = x + 4;
+ @set_cursor 16 xx; print "//";
+ ChangeWorld(xx, 16, 2); xx = x + 10;
+ @set_cursor 16 xx; print "@@92@@92";
+ ChangeWorld(xx, 16, 2);
+ @set_cursor 17 xx; print "||";
+ ChangeWorld(xx, 17, 2); xx--;
+ @set_cursor 18 xx; print "//@@92@@92";
+ ChangeWorld(xx, 18, 4); xx--;
+ @set_cursor 19 xx; print "//";
+ ChangeWorld(xx, 19, 2); xx = x + 12;
+ @set_cursor 19 xx; print "@@92@@92";
+ ChangeWorld(xx, 19, 2); xx = x + 7;
+ @set_cursor 20 xx; print "//";
+ ChangeWorld(xx, 20, 2);
+ @set_cursor 21 xx; print "@@92@@92";
+ ChangeWorld(xx, 21, 2); xx++;
+ @set_cursor 22 xx; print "@@92@@92";
+ ChangeWorld(xx, 22, 2); xx++;
+ @set_cursor 23 xx; print "@@92@@92";
+ ChangeWorld(xx, 23, 2);
+ @set_cursor screen_height 1;
+ Pause(10);
+ ! ...and delete it again
+ xx = x + 6;
+ @set_cursor 5 xx; print " ";
+ @set_cursor 6 xx; print " "; xx--;
+ @set_cursor 7 xx; print " "; xx--;
+ @set_cursor 8 xx; print " "; xx = x + 7;
+ @set_cursor 8 xx; print " "; xx = x + 3;
+ @set_cursor 9 xx; print " "; xx = x + 8;
+ @set_cursor 9 xx; print " "; xx++;
+ @set_cursor 10 xx; print " "; xx--;
+ @set_cursor 11 xx; print " "; xx--;
+ @set_cursor 12 xx; print " "; xx = x + 11;
+ @set_cursor 12 xx; print " "; xx = x + 7;
+ @set_cursor 13 xx; print " "; xx--;
+ @set_cursor 14 xx; print " "; xx--;
+ @set_cursor 15 xx; print " "; xx = x + 9;
+ @set_cursor 15 xx; print " "; xx = x + 4;
+ @set_cursor 16 xx; print " "; xx = x + 10;
+ @set_cursor 16 xx; print " ";
+ @set_cursor 17 xx; print " "; xx--;
+ @set_cursor 18 xx; print " "; xx--;
+ @set_cursor 19 xx; print " "; xx = x + 12;
+ @set_cursor 19 xx; print " "; xx = x + 7;
+ @set_cursor 20 xx; print " ";
+ @set_cursor 21 xx; print " "; xx++;
+ @set_cursor 22 xx; print " "; xx++;
+ @set_cursor 23 xx; print " ";
+ @set_cursor screen_height 1;
+ if (player1)
+ return CountDestroyed(' ', house2_x, house2_y, 17, 10) - num_destroyed;
+ return CountDestroyed(' ', house1_x, house1_y, 17, 10) - num_destroyed;
+];
+
+[ DrawTornado x shift xx y shift_right tmp_x tmp_y width width_tmp
+ num_destroyed;
+ xx = 0; y = 4;
+ shift_right = 0;
+ tmp_x = x; tmp_y = y;
+ width = 29;
+ if (player1)
+ num_destroyed = CountDestroyed(' ', house2_x, house2_y, 17, 10);
+ else
+ num_destroyed = CountDestroyed(' ', house1_x, house1_y, 17, 10);
+ while (tmp_y < 24) {
+ if (width > 3) {
+ width = width - 2;
+ shift_right++;
+ }
+ if (tmp_y == 18) width = 2;
+ if (tmp_y == 21) width = 1;
+ if (tmp_y == 23) {
+ width = 7;
+ shift_right = shift_right - 3;
+ }
+ xx = tmp_x + shift_right;
+ ChangeWorld(xx, tmp_y, width);
+ for (width_tmp = 0: width_tmp < width: width_tmp++) {
+ xx = tmp_x + shift_right + width_tmp;
+ if (xx > 0 && xx <= screen_width) {
+ @set_cursor tmp_y xx; print "#";
+ }
+ }
+ tmp_y++;
+ tmp_x = tmp_x + shift;
+ if (xx > 0 && xx <= screen_width) {
+ @set_cursor screen_height 1;
+ Pause(2);
+ }
+ }
+ @set_cursor screen_height 1;
+ Pause(10);
+ tmp_x = x; tmp_y = y;
+ shift_right = 0;
+ width = 29;
+ while (tmp_y < 24) {
+ if (width > 3) {
+ width = width - 2;
+ shift_right++;
+ }
+ if (tmp_y == 18) width = 2;
+ if (tmp_y == 21) width = 1;
+ if (tmp_y == 23) {
+ width = 7;
+ shift_right = shift_right - 3;
+ }
+ for (width_tmp = 0: width_tmp < width: width_tmp++) {
+ xx = tmp_x + shift_right + width_tmp;
+ if (xx > 0 && xx <= screen_width) {
+ @set_cursor tmp_y xx;
+ print " ";
+ }
+ }
+ tmp_y++;
+ tmp_x = tmp_x + shift;
+ if (xx > 0 && xx <= screen_width)
+ @set_cursor screen_height 1;
+ Pause(1);
+ }
+ if (player1)
+ return CountDestroyed(' ', house2_x, house2_y, 17, 10) - num_destroyed;
+ return CountDestroyed(' ', house1_x, house1_y, 17, 10) - num_destroyed;
+];
+
+! This *does* look like a cloud in real life ;)
+! @{B0} is a degree character on decent interpreters
+[ DrawCloud x;
+ if (x ~= 0) cloud_x = x;
+ else cloud_x = random(screen_width - 29);
+ @set_cursor 1 cloud_x; print ",/+++*++***+****++++++***+@@92,";
+ @set_cursor 2 cloud_x; print "(*+++*****+++++***+++****++)";
+ @set_cursor 3 cloud_x; print "`@@92++******+*++*++*****+++*/'";
+ @set_cursor 4 cloud_x; print " `@{B0}*,.,*@{B0}'`@{B0}*,.,",
+ "*@{B0}`@{B0}*,.,*@{B0}'";
+ @set_cursor screen_height 1;
+];
+
+! Replace the normal cloud with a bigger one
+[ DrawTornadoCloud i;
+ for (i = 1: i <= screen_width: i++) {
+ @set_cursor 1 i; print (string) random("+", "*");
+ @set_cursor 2 i; print (string) random("+", "*");
+ @set_cursor 3 i; print (string) random("+", "*");
+ }
+];
+