home *** CD-ROM | disk | FTP | other *** search
- PROGRAM Artillery_Battle ; { Pascal/Z Version }
-
- {$C-, F-, M-, L- (Turn off checking and listing options for better speed) }
-
- { *** 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 by the pseudo-random-number
- procedure, depending on the "seed" number entered at the beginning.
- Each player then enters the angle (in degrees above the horizontal)
- and velocity (in meters per second) of his shot (NOTE that because
- of the console I/O requirements of Pascal/Z, these two numbers MUST
- be separated by a space, not a comma, and followed by <Return>).
- Flight and impact point are displayed for the projectile, 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). You might also try changing the
- scale factor, maximum wind velocity, or wind "coupling factor"
- (its effect on the projectile) to get some other interesting
- variations on the game.
- Note that this version was named "ARTIL/Z" to distinguish it from
- the other version (ARTIL/M) in Pascal/M. Unfortunately, the Pascal/Z
- compiler, assembler, and/or linker will not accept a large number of
- perfectly legal CP/M file names, including that one. Rename it to
- plain "ARTIL" before trying to compile it.
- }
-
-
-
-
- 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 code for "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 ;
- Rand_num : Integer ;
- Answer : Char ;
- Quit : Boolean ;
-
-
- {$IGOTOXY.PSP } { PROCEDURE GotoXY (X_pos, Y_pos : Integer) }
-
-
- {$ICONACT.PSP } { PROCEDURE Conact (Action : Integer) }
-
-
- {$IRANDOM.PSP } { FUNCTION Random (VAR Seed : Integer) : Real }
-
-
- 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 (Rand_num) / 2) ;
- Level_2 := Round (Max_Y * Random (Rand_num) / 2) ;
- Center_ht := Round (Max_Y * Random (Rand_num)) ;
- X_pos_1 := Round ((Side_1 - 3) * Random (Rand_num) + 1) ;
- X_pos_2 := Round ((Side_2 - 3) * Random (Rand_num) + Max_X - Side_2 + 1) ;
- Wind_vel := Round (2 * Max_wind * Random (Rand_num) - 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) : 2, ' meters/sec; ') ;
- Write ('each bar (-) is ', Scale : 3, ' 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) ;
-
- LABEL
- 0 ;
-
- CONST
- Spaces = 11 ;
- Pi = 3.14159 ;
- Half_cir = 180 ; { Number of degrees equal to "Pi" radians }
- Time_int = 100 ;
-
- VAR
- Last_X, Last_Y,
- Next_X, Next_Y,
- X_vel, Y_vel,
- Angle, Init_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 ;
- Goto 0 ;
- END ;
-
- { Set up zero-time co-ordinates and velocities }
- Angle := Angle * (Pi / Half_cir) ; { 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 ;
-
- 0: { Location to jump to in order to exit procedure }
-
- END ; { Fire }
-
-
- PROCEDURE Show_Hit ;
-
- CONST
- End_loop = 600 ; { Used in timing loop for longer "bell" sound }
-
- 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) ;
- Write ('BLEEP!!! Wiped out!!!') ;
-
- FOR N := 1 TO End_loop DO
- Write (Chr (Bell)) ;
-
- END ; { Show_Hit }
-
-
- BEGIN { Main program }
-
- Conact (0) ;
- Writeln ('Welcome to ARTILLERY BATTLE') ;
- Writeln ;
-
- { Initialize pseudo-random-number generator }
- Write ('Enter any number to start the game: ') ;
- Read (Rand_num) ;
-
- 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 }
- (1) ;
- Write ('Another game (Y/n) ? /═J*yº╚╒"P/═B.═╠*┴*∙═I."∙z│╚*:R/âσg"═╢'ß"═½╔*∙σ═*╤"∙*P/┼═ë.┴═╠*╔x2S/y2R/:æ<6 #=┬┘*++"N/╔*P/═*"P/╔*P/σ═*╤*∙y═6."