1 ! Z-Tornado - Two player weather action game
3 ! Tornado is copyright (C) 2000-2002 Oliver Feiler
4 ! http://www.lionking.org/~kiza/linux/tornado
5 ! Inform version copyright (c) 2003 Sophie Frühling (sfruehling@aon.at)
7 ! This program is free software; you can redistribute it and/or modify
8 ! it under the terms of the GNU General Public License as published by
9 ! the Free Software Foundation; either version 2 of the License, or
10 ! (at your option) any later version.
12 ! This program is distributed in the hope that it will be useful,
13 ! but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ! GNU General Public License for more details.
17 ! You should have received a copy of the GNU General Public License
18 ! along with this program; if not, write to the Free Software
19 ! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 Global dialog_x; ! dialog box cursor for player input
28 ! Can be switched off in terps where colour doesn't work properly
29 ! (For all I know only useful in Unix Frotz 2.32, where timed input
30 ! doesn't work like it should either)
34 ! 1 if current player, otherwise 0
37 Array player1_name -> 18;
38 Array player2_name -> 18;
39 Global player1_ai = 0;
40 Global player2_ai = 0;
41 Global player1_left = 100;
42 Global player2_left = 100;
43 ! Can handle scores up to 9999999, which should be more than enough
44 Array player1_score -> 7;
45 Array player2_score -> 7;
48 ! Position relative to screen
53 ! How many spaces does the house initially contain?
59 ! 80 x 24 grid, discounting 1 row for statusline and 4 for cloud
60 Array snow_world -> 1520;
61 ! Actual entries of snow_world
65 Array highscore_file string "ZTORNADO.HGH";
66 Array highscore_array -> 220;
68 ! Add degree character to Zcharacter table
69 Zcharacter table + '@{B0}';
74 Include "weather.inf";
77 if (TestTerp() == 0) return;
80 while ((input = Menu()) ~= 'Q') {
85 if (colour) colour = 0;
100 print "----------------------^";
101 print "(A) About Z-Tornado^",
102 "(C) Toggle colour (currently ";
103 if (colour) print "on";
107 "(P) Play Z-Tornado^",
112 'A', 'C', 'I', 'P', 'Q':
118 [ Game; Init(); Tornado(); Bye(); ];
120 Array score_array->7;
121 [ Tornado quitting tmp_score;
128 windspeed = random(11) - 6;
130 player1 = 0; player2 = 1;
131 quitting = Play(player2_ai);
133 player2 = 0; player1 = 1;
134 quitting = Play(player1_ai);
136 if (player1_left <= 0) {
138 - ((CountDestroyed(' ', house2_x, house2_y, 17, 10) - SPACES)*100)/138;
139 CopyArray(score_array, player2_score);
140 Multiply(player2_score, score_array, tmp_score);
143 if (player2_left <= 0) {
145 - ((CountDestroyed(' ', house1_x, house1_y, 17, 10) - SPACES)*100)/138;
146 CopyArray(score_array, player1_score);
147 Multiply(player1_score, score_array, tmp_score);
150 if (quitting) return;
153 AddToHighScore(player1_name, player1_score);
154 AddToHighScore(player2_name, player2_score);
155 if (ContinueGame() == 'N')
160 [ Play ai x input aim destroyed;
162 ! We have a human player
165 input = PlayerChoice();
168 ! lightning: player doesn't have to aim
169 ! tornado: we'll draw the tornado cloud before aiming
170 if (input == 'L' or 'T')
172 if (input == 'H' or 'R' or 'S') {
178 else if (input == 'O')
181 } else { ! The computer chooses
183 input = ErwinChoice(player1_left);
185 input = ErwinChoice(player2_left);
186 aim = ErwinAim(input);
191 x = cloud_x + random(14) - 1;
192 destroyed = DrawWeather(x, windspeed + aim, ':', 2);
194 x = cloud_x + random(14) - 1;
195 destroyed = DrawWeather(x, windspeed + aim, '/', 1);
197 x = cloud_x + random(14) - 1;
198 DrawSnow(x, windspeed + aim);
200 destroyed = DrawLightning(cloud_x - 7 + random(25));
203 if (ai == 0) aim = GetAim();
204 else Pause(2); ! So the player can see the cloud for a while
205 destroyed = DrawTornado(cloud_x, windspeed + aim);
208 - ((CountDestroyed(' ', house2_x, house2_y, 17, 10)
209 + CountSnow(house2_x, house2_y, 17, 10) - SPACES)*100)/138;
211 - ((CountDestroyed(' ', house1_x, house1_y, 17, 10)
212 + CountSnow(house1_x, house1_y, 17, 10) - SPACES)*100)/138;
213 ! (You get points for destroying your own house, too)
215 CopyArray(score_array, player1_score);
216 AddShort(player1_score, score_array, destroyed*destroyed);
218 CopyArray(score_array, player2_score);
219 AddShort(player2_score, score_array, destroyed*destroyed);
231 'S', 'H', 'T', 'Q', 'R', 'L', 'C', 'O':
232 ClearUserInterface();
242 @set_cursor 8 dialog_x;
244 @set_cursor 9 dialog_x;
246 @set_cursor screen_height 1;
252 ! Get the position of x y in snow_world array
254 if (x < 1 || x > screen_width || y < 5 || y > screen_height)
257 return (y - 5)*screen_width + x;
260 [ CountDestroyed ch x y wid hgt i j n count;
261 for (i = x: i < x + wid: i++) {
262 for (j = y: j < y + hgt: j++) {
264 if (snow_world->n == ch)
271 [ CountSnow xx yy wid hgt;
272 return CountDestroyed('*', xx, yy, wid, hgt);
275 [ ChangeWorld x y num i;
276 for (i = 0: i < num: i++)
277 ChangeSnowWorld(' ', x + i, y);
280 [ ChangeSnowWorld ch xx yy x;
286 ! ----------- Initialising and game ending stuff -------------
289 screen_width = 0->33;
290 screen_height = 0->32;
291 if (screen_width < 64)
292 print "Your interpreter detected a screen width of only ",
294 if (screen_height < 24)
295 print "Your interpreter detected a screen height of only ",
297 if (screen_width < 64 || screen_height < 24) {
298 print "To play Tornado you need at least 64 x 24.^^";
301 if (screen_width > 80) screen_width = 80;
303 if ((0->1) & 128 == 0) {
304 print "Your interpreter apparently doesn't support timed events.",
305 " This game should be pretty tiresome to play without, sorry.^";
309 print "Your interpreter doesn't obey the Z-Machine standard. Z-Tornado",
310 " will probably not work correctly on such an interpreter.^";
317 dialog_x = screen_width/2 - 16;
320 if (colour) @set_colour 9 2;
322 house1_y = screen_height - 10;
323 house2_x = screen_width - 21;
324 house2_y = screen_height - 10;
325 fields = screen_height*screen_width - 5*screen_width;
335 ! There might be some bug in there, because Windows Frotz 2002 doesn't draw
336 ! the dialog window correctly after asking for the first player's name
339 for (i = 2: i < 17: i++) {
340 player1_name->i = ' ';
341 player2_name->i = ' ';
343 @set_cursor 8 dialog_x;
344 print "Please enter your name Player 1";
345 @set_cursor 9 dialog_x;
346 player1_name->0 = 15;
348 if (player1_name->1 == 0) {
349 ("Computer").print_to_array(player1_name);
352 @set_cursor 8 dialog_x;
353 print "Please enter your name Player 2";
354 @set_cursor 9 dialog_x;
356 @set_cursor 9 dialog_x;
357 player2_name->0 = 15;
359 if (player2_name->1 == 0) {
360 ("Computer").print_to_array(player2_name);
363 @set_cursor screen_height 1;
372 Nullify(player1_score);
373 Nullify(player2_score);
380 for (i = 0: i < fields: i++)
390 "/'/////////////`@@92"
398 Array temp_array -> 20;
399 [ InitHouse nr i j x y tmp;
408 for (j = 1: j <= 10: j++) {
409 tmp = GetLoc(x, y + j - 1);
410 (building-->j).print_to_array(temp_array);
411 for (i = 2: i < 19: i++)
412 snow_world->tmp++ = temp_array->i;
416 [ ContinueGame yesno;
420 while (yesno ~= 'Y' && yesno ~= 'N')
428 y = screen_height - 2;
437 print "^^[Trying to save highscore file]^";
438 @save highscore_array 220 highscore_file -> x;
440 print "^[Couldn't save the highscore file, sorry.]^";
441 print "^^Thanks for playing Tornado!^^";
444 ! ---------------- Low level routines ---------------------
446 ! Read in a character/digit from the keyboard
451 ! This should make the random function more random.
452 @read_char 1 1 SeedRand -> k;
453 for (k = 0: k < randseed: k++)
456 ! Convert lower case to upper case so we only have to test
457 ! for half of the cases
458 if ('a' <= x && x <= 'z')
459 return x - ('a' - 'A');
463 [ SeedRand; randseed++; rfalse; ];
465 ! Read in numbers from -99 to 999 (We really only need -9 to 9)
466 ! If the player doesn't type a number, or anything, we return 0.
468 [ ReadNumber x y neg tens sum;
471 if (num_array->1 == 0)
474 if (num_array->2 == '-') {
478 for (sum = 0: x < num_array->1 + 2: x++) {
479 if (num_array->x >= '0' && num_array->x <= '9') {
480 for (tens = 1, y = num_array->1: y + 1 > x: y--)
482 sum = sum + (num_array->x - '0') * tens;
490 ! Pauses for x/10 seconds
492 @read_char 1 x Interrupt -> t;
495 [ Interrupt; rtrue; ];