home *** CD-ROM | disk | FTP | other *** search
- PROGRAM Artillery_Battle ; { Pascal/M version }
-
- { *** WRITTEN BY Jim Bearden
- Cancer Center, University of Hawaii
- 1236 Lauhala Street
- Honolulu, Hawaii 96813
-
- *** DATE WRITTEN December, 1981
-
- *** PROGRAM SUMMARY:
- This program simulates an artillery battle between two players.
- The initial setup (ground elevation on each side, locations of
- bunkers, height of the central "hill" or "valley", and wind
- direction and velocity) is generated at random for each game.
- Each player then enters the angle (in degrees above the horizontal)
- and velocity (in meters per second) of his shot. Flight of the
- projectile and its point of impact are displayed, as long as it
- remains on the screen. This program uses only ASCII characters and
- cursor positioning (no graphics capability required), so it should
- be usable on any CRT terminal with an addressable cursor (presently
- set up for a 24 x 80 screen size, but may be adapted to other sizes
- by changing constants as shown).
- }
-
- {$D- (Disable "Debug" option for increased speed) }
-
- CONST
- Grnd_sym = '-' ; { Character used to represent ground surface in profile }
- Burst_sym = '*' ; { Represents point of impact on ground }
- Air_sym = '+' ; { Represents projectile in flight }
- Max_X = 79 ; { Number of screen columns - 1 }
- Max_Y = 20 ; { Number of screen lines - 4 }
- Scale = 100 ; { Number of meters represented by each screen unit }
- Max_wind = 25 ; { Maximum allowed wind velocity, in meters/sec }
- Side_1 = 25 ; { Width of level ground section on player 1's side }
- Side_2 = 25 ; { Same, player 2's side }
- Center = 30 ; { Width of center ("hill" or "valley") section }
- { Sum of (Side_1 + Side_2 + Center) must equal width of screen }
- Acc_g = 9.8 ; { Acceleration of normal earth gravity, in meters/sec }
- Bell = 7 ; { ASCII equivalent of "bell" sound }
-
- VAR
- X_pos_1, X_pos_2, { Locations (on X-axis) of bunkers of players 1 and 2 }
- Level_1, Level_2, { Heights of level ground sections on each side }
- Center_ht : 0..Max_X ;
- Wind_vel : -Max_wind..Max_wind ;
- Ground : ARRAY [0..Max_X] OF Integer ;
- Direct_hit : ARRAY [1..2] OF Boolean ;
- Rnd_num : Real ;
- Answer : Char ;
- Quit : Boolean ;
-
- PROCEDURE Set_Up_Game ;
-
- VAR
- X, Y : 0..Max_X ;
-
- BEGIN { Set_Up_Game }
-
- { Set up initial conditions from random-number generator }
- Level_1 := Round (Max_Y * Random (0) / 2) ;
- Level_2 := Round (Max_Y * Random (0) / 2) ;
- Center_ht := Round (Max_Y * Random (0)) ;
- X_pos_1 := Round ((Side_1 - 3) * Random (0) + 1) ;
- X_pos_2 := Round ((Side_2 - 3) * Random (0) + Max_X - Side_2 + 1) ;
- Wind_vel := Round (2 * Max_wind * Random (0) - Max_wind) ;
-
- { Display initial layout and initialize "Ground" values }
- Conact (0) ;
- FOR X := 0 TO (Side_1 - 1) DO
- BEGIN
- Y := Level_1 ;
- GotoXY (X, (Max_Y - Y)) ;
- Write (Grnd_sym) ;
- Ground [X] := Y ;
- END ;
- FOR X := 0 TO (Center DIV 2 - 1) DO
- BEGIN
- Y := Round (Level_1 + (Center_ht - Level_1) * (X + 1) / (Center / 2)) ;
- GotoXY ((X + Side_1), (Max_Y - Y)) ;
- Write (Grnd_sym) ;
- Ground [X + Side_1] := Y ;
- END ;
- FOR X := 0 TO (Center DIV 2 - 1) DO
- BEGIN
- Y := Center_ht - Round ((Center_ht - Level_2) * (X + 1) / (Center / 2)) ;
- GotoXY ((X + Side_1 + Center DIV 2), (Max_Y - Y)) ;
- Write (Grnd_sym) ;
- Ground [X + Side_1 + Center DIV 2] := Y ;
- END ;
- FOR X := 0 TO (Side_2 - 1) DO
- BEGIN
- Y := Level_2 ;
- GotoXY ((X + Side_1 + Center), (Max_Y - Y)) ;
- Write (Grnd_sym) ;
- Ground [X + Side_1 + Center] := Y ;
- END ;
-
- { Show location of both players' bunkers }
- GotoXY (X_pos_1 - 1, (Max_Y - Ground [X_pos_1])) ;
- Write ('[1]') ;
- GotoXY (X_pos_2 - 1, (Max_Y - Ground [X_pos_2])) ;
- Write ('[2]') ;
-
- GotoXY (0, (Max_Y + 2)) ;
- Conact (1) ;
- Write ('Wind is to the ') ;
- IF Wind_vel <= 0 THEN
- Write ('LEFT ')
- ELSE
- Write ('RIGHT ') ;
- Write ('at ', Abs (Wind_vel), ' meters/sec; ') ;
- Write ('each bar (-) is 100 meters.') ;
-
- GotoXY (0, Max_Y + 3) ;
- Conact (1) ;
- Write ('When prompted, enter angle (degrees) and velocity (meters/sec)') ;
- Write (', or 0,0 to quit.') ;
-
- GotoXY (0, (Max_Y - Level_1 + 1)) ;
- Write ('Player #1: ') ;
- GotoXY ((Side_1 + Center), (Max_Y - Level_2 + 1)) ;
- Write ('Player #2: ') ;
-
- FOR X := 1 TO 2 DO
- Direct_hit [X] := False ;
- Quit := False ;
-
- END ; { Set_Up_Game }
-
-
- PROCEDURE Fire (Player : Integer) ;
-
- CONST
- Spaces = 11 ;
- Pi = 3.14159 ;
- Time_int = 100 ;
-
- VAR
- Angle, Init_vel,
- Last_X, Last_Y,
- Next_X, Next_Y,
- X_vel, Y_vel : Real ;
- N, Loc_X, Loc_Y : Integer ;
- Hit, On_screen : Boolean ;
-
- FUNCTION Wind_Fac (X_pos, Y_pos : Real) : Real ;
-
- CONST
- Wind_pct = 0.1 ; { "Coupling factor" between wind and projectile }
-
- VAR
- Shielded : Boolean ;
-
- BEGIN { Wind_Fac }
-
- IF Wind_vel > 0 THEN
- IF Center_ht > Level_1 THEN
- Shielded := (X_pos > (Side_1 + Center DIV 2 + 1)) AND (Y_pos < Center_ht)
- ELSE
- Shielded := (X_pos > Side_1) AND (Y_pos < Level_1)
- ELSE
- IF Center_ht > Level_2 THEN
- Shielded := (X_pos < (Side_1 + Center DIV 2)) AND (Y_pos < Center_ht)
- ELSE
- Shielded := (X_pos < (Side_1 + Center)) AND (Y_pos < Level_2) ;
-
- IF Shielded THEN
- Wind_Fac := 0
- ELSE
- Wind_Fac := Wind_vel * Wind_pct ;
-
- END { Wind_Fac } ;
-
- BEGIN { Fire }
-
- IF Player = 1 THEN
- GotoXY (Spaces, (Max_Y - Level_1 + 1))
- ELSE
- GotoXY ((Side_1 + Center + Spaces), (Max_Y - Level_2 + 1)) ;
- Read (Angle, Init_vel) ;
-
- { Routine for early termination of game by either player }
- IF (Angle <= 0) OR (Init_vel <= 0) THEN
- BEGIN
- Quit := True ;
- Exit (Fire) ;
- END ;
-
- { Set up zero-time co-ordinates and velocities }
- Angle := Angle * Pi / 180 ; { Convert degrees to radians }
- X_vel := Init_vel * Cos (Angle) ;
- IF Player = 2 THEN
- X_vel := -X_vel ;
- Y_vel := Init_vel * Sin (Angle) ;
- IF Player = 1 THEN
- BEGIN
- Last_X := X_pos_1 ;
- Last_Y := Ground [X_pos_1] ;
- END
- ELSE
- BEGIN
- Last_X := X_pos_2 ;
- Last_Y := Ground [X_pos_2] ;
- END ;
- Hit := False ;
- On_screen := False ;
-
- REPEAT
-
- { Compute velocities and positions after next second of travel }
- X_vel := X_vel + Wind_Fac (Last_X, Last_Y) ;
- Y_vel := Y_vel - Acc_g ;
- IF On_screen THEN { Erase last symbol printed during air travel }
- BEGIN
- GotoXY (Loc_X, (Max_Y - Loc_Y)) ;
- Write (' ') ;
- END ;
- Next_X := Last_X + (X_vel / Scale) ;
- Loc_X := Round (Next_X) ;
- Next_Y := Last_Y + (Y_vel / Scale) ;
- Loc_Y := Round (Next_Y) ;
-
- IF (Loc_Y < 0) AND NOT (Loc_X IN [0..Max_X]) THEN { Hit ground off screen }
- BEGIN
- Hit := True ;
- Write (Chr (Bell)) ;
- END
- ELSE IF Loc_X IN [0..Max_X] THEN
- IF Loc_Y <= Ground [Loc_X] THEN { Hit ground on screen }
- BEGIN
- Loc_X := Round (Last_X + (Next_X - Last_X) / (Next_Y - Last_Y)) ;
- Hit := True ;
- Write (Chr (Bell)) ;
- IF (Abs (Loc_X - X_pos_1)) <= 1 THEN
- Direct_hit [1] := True
- ELSE IF (Abs (Loc_X - X_pos_2)) <= 1 THEN
- Direct_hit [2] := True
- ELSE
- BEGIN
- GotoXY (Loc_X, (Max_Y - Ground [Loc_X])) ;
- Write (Burst_sym) ;
- END ;
- END
- ELSE { Still in flight above ground }
- BEGIN
- On_screen := Loc_Y IN [0..Max_Y] ;
- IF On_screen THEN
- BEGIN
- GotoXY (Loc_X, (Max_Y - Loc_Y)) ;
- Write (Air_sym) ;
- END
- ELSE
- GotoXY (Loc_X, 0) ;
- FOR N := 1 TO Time_int DO { Nothing } ;
- { Time delay for display }
- END
- ELSE
- BEGIN
- On_screen := False ;
- GotoXY (0, (Max_Y + 3)) ;
- END ;
-
- { Update co-ordinates for next calculation }
- Last_X := Next_X ;
- Last_Y := Next_Y ;
-
- UNTIL Hit ;
-
- END ; { Fire }
-
-
- PROCEDURE Show_Hit ;
-
- VAR
- N : Integer ;
-
- BEGIN { Show_Hit }
-
- IF Direct_hit [1] THEN
- GotoXY ((X_pos_1 - 1), (Max_Y - Level_1))
- ELSE
- GotoXY ((X_pos_2 - 1), (Max_Y - Level_2)) ;
- FOR N := 1 TO 3 DO
- Write (Burst_sym) ;
-
- IF Direct_hit [1] THEN
- GotoXY (0, (Max_Y - Level_1 + 1))
- ELSE
- GotoXY ((Side_1 + Center), (Max_Y - Level_2 + 1)) ;
- Conact (1) ;
- Writeln ('BLEEP!!! Wiped out!!!') ;
-
- FOR N := 1 TO 200 DO
- Write (Chr (Bell)) ;
-
- END ; { Show_Hit }
-
-
- BEGIN { Main program }
-
- Conact (0) ;
- Writeln ('Welcome to ARTILLERY BATTLE') ;
- Writeln ;
-
- { Routine to randomize pseudo-random-number generator }
- Write ('Press any key to start the game: ') ;
- WHILE Filebusy (Keyboard) DO
- Rnd_num := Random (0) ;
- Read (Keyboard, Answer) ;
-
- REPEAT
-
- Set_Up_Game ;
-
- REPEAT
- Fire (1) ;
- IF NOT (Direct_hit [1] OR Direct_hit [2] OR Quit) THEN
- Fire (2) ;
- UNTIL (Direct_hit [1] OR Direct_hit [2] OR Quit) ;
-
- IF NOT Quit THEN
- Show_hit ;
-
- GotoXY (0, (Max_Y + 2)) ;
- Conact (1) ;
- GotoXY (0, (Max_Y + 3)) ;
- Conact (1) ;
- Write ('Another game (Y/n) ? ') ;
- Read (Answer) ;
-
- UNTIL Answer IN ['N','n'] ;
-
- END . { Main program }
-