Import ztornado by Sophie Frühling
authorJason Self <j@jxself.org>
Wed, 21 Aug 2019 02:15:39 +0000 (19:15 -0700)
committerJason Self <j@jxself.org>
Wed, 21 Aug 2019 02:15:39 +0000 (19:15 -0700)
Release 2

From
http://www.ifarchive.org/if-archive/games/source/inform/ztornado.zip

COPYING [new file with mode: 0644]
Readme [new file with mode: 0644]
draw.inf [new file with mode: 0644]
erwin.inf [new file with mode: 0644]
scores.inf [new file with mode: 0644]
tornado.inf [new file with mode: 0644]
weather.inf [new file with mode: 0644]

diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..a43ea21
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+                   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.
diff --git a/Readme b/Readme
new file mode 100644 (file)
index 0000000..588a3c1
--- /dev/null
+++ b/Readme
@@ -0,0 +1,25 @@
+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!
diff --git a/draw.inf b/draw.inf
new file mode 100644 (file)
index 0000000..065124c
--- /dev/null
+++ b/draw.inf
@@ -0,0 +1,314 @@
+! 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;
+];
+
diff --git a/erwin.inf b/erwin.inf
new file mode 100644 (file)
index 0000000..ea88f9b
--- /dev/null
+++ b/erwin.inf
@@ -0,0 +1,96 @@
+! 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;
+];
diff --git a/scores.inf b/scores.inf
new file mode 100644 (file)
index 0000000..9790882
--- /dev/null
@@ -0,0 +1,211 @@
+! 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;
+];
+
diff --git a/tornado.inf b/tornado.inf
new file mode 100644 (file)
index 0000000..6748476
--- /dev/null
@@ -0,0 +1,495 @@
+! 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; ];
diff --git a/weather.inf b/weather.inf
new file mode 100644 (file)
index 0000000..f70eeb6
--- /dev/null
@@ -0,0 +1,394 @@
+! 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("+", "*");
+  }
+];
+