From: Jason Self Date: Wed, 21 Aug 2019 02:15:39 +0000 (-0700) Subject: Import ztornado by Sophie Frühling X-Git-Url: https://jxself.org/git/?a=commitdiff_plain;h=ec23fafdb2955dfc079c7a57fffd0f3e85c9dfc5;p=ztornado.git Import ztornado by Sophie Frühling Release 2 From http://www.ifarchive.org/if-archive/games/source/inform/ztornado.zip --- ec23fafdb2955dfc079c7a57fffd0f3e85c9dfc5 diff --git a/COPYING b/COPYING new file mode 100644 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. + + 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.) + +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. + + 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. + + 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 + + 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. + + + Copyright (C) 19yy + + 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. + + , 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 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 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 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 index 0000000..9790882 --- /dev/null +++ b/scores.inf @@ -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 index 0000000..6748476 --- /dev/null +++ b/tornado.inf @@ -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 index 0000000..f70eeb6 --- /dev/null +++ b/weather.inf @@ -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("+", "*"); + } +]; +