!*************************** AMUS Program Label ******************************
! Filename: SHIP.BAS                                        Date: 10/??/90
! Category: GAMES        Hash Code:                      Version: 1.0(100)
! Initials: WENG/AM      Name: Michael Mc Murdie
! Company: Morton & Pitalo, Inc.                   Telephone #: 9169272400
! Related Files: SHIP.CMD, AMIGOS STUFF, INKEY.SBR, SLEEP.SBR, ...
! Min. Op. Sys.: AMOSL 1.3B/AMOS32 1.0         Expertise Level: BEG
! Special: not really...
! Description: Just a silly graphical lunar lander game
!*****************************************************************************
!This is my variation of the lunar lander program. It works as follows:
!The Left/Right arrow keys rotate the ship CCW/CW and each rotation 
!consumes 10 units of fuel. In order to slow the ship press the numbers
! 1 - 9 for variable burn rate of fuel, 1 being the lowest, 9 being the
!highest. The point is to land on the landing pad at a slow speed. The ship
!will continue to move in the direction it is currently going taking into
!account gravity. If you hit the land first you die or if you hit the landing
!pad too fast you also die. Right now this is a REAL simple implementation
!but in the future I would like to see more variation. Such things as a
!variable landscape and location of the landing pad. In addition maybe you
!could offer variable gravity, fuel amount and height of mountains based on
!level of difficulty. In other words run amuk...
!
	PROGRAM SHIP,1.0(100)		!el numero de version...

++INCLUDE AMGSYM.BSI			!grab the AMIGOS defs

	MAP1 GCB,X,50000		!graphics control block

	MAP1 PT'ARY			!point array data structure
	MAP2	PT'CT,B,2		!number of points
	MAP2	PTS(50)			!actual point array
	MAP3		PT'X,B,2	!x values
	MAP3		PT'Y,B,2	!y values

	MAP1 OLD'POS
	MAP2	OLD'CT,B,2
	MAP2	OLD'PTS(50)
	MAP3		OLD'X,B,2
	MAP3		OLD'Y,B,2

!surface is the actual surface of the planet we're landing on
	MAP1 SURFACE			!surface to check
	MAP2	SRF'CT,B,2		!number of points
	MAP2	SRF'PTS(50)		!position of each point
	MAP3		SRF'X,B,2
	MAP3		SRF'Y,B,2

	MAP1 SHIP(20,2),F,6		!array to hold the SHIP shape 
	MAP1 FLAME(10,2),F,6		!flame shape
	MAP1 SHIP'X,F,6			!current SHIP position x
	MAP1 SHIP'Y,F,6			!current SHIP position y
	MAP1 SHIP'ANG,F,6,0		!current SHIP angle index
	MAP1 NO'SHIP'PTS,F,6		!number of points making up the SHIP
	MAP1 CHAR,S,1			!input character

!sine & cosine values are stored in an array to increase speed
	MAP1 SIN'ARY(72),F,6		!sine values
	MAP1 COS'ARY(72),F,6		!cosine values

	MAP1 STAT'STR,S,80

	XCALL AMGSBR,G'OPWK,GCB,"",STATUS	!open the workstation
	XCALL AMGSBR,G'SWM,GCB,1,STATUS		!set XOR mode
	XCALL AMGSBR,G'SPLC,GCB,1,STATUS	!white lines
	XCALL AMGSBR,G'SPLT,GCB,1,STATUS	!solid lines

	CALL BUILD'SHIP
	XCALL NOECHO : ? TAB(-1,29);TAB(-1,0);
	CALL SHOW'BASE
	PT'CT = NO'SHIP'PTS
	OLD'CT = PT'CT
!the following segment sets the initial values change them as desired
	SHIP'X = 2000 : SHIP'Y = 22000 : SHIP'ANG = 17
	VEL'X = 400 : VEL'Y = 75 : FUEL = 2000 : BURN = 0
	GRAVITY = 10

	? tab(-1,11);
	? tab(34,1);
	? "Velocity  X:       Y:";tab(34,31);"Height:";tab(34,46);"Fuel:";
	? TAB(-1,12);
	
	INIT'FLAG = 0 : CLK = 0
LOOP:	NEW'VEL'Y = VEL'Y - BURN + GRAVITY	!get new velocity
	SHIP'Y = SHIP'Y - 0.5*(NEW'VEL'Y + VEL'Y)	!new y position
	SHIP'X = SHIP'X + VEL'X			!new x position
	VEL'Y = NEW'VEL'Y
	? TAB(34,13);VEL'X USING "####";	!show current x velocity
	? TAB(34,22);VEL'Y USING "####";	!show current y velocity
	? TAB(34,38);SHIP'Y USING "#####";	!show height
	? TAB(34,51);FUEL USING "####";		!show fuel left
!	? TAB(34,61);CLK USING "#######";	!show elapsed time

	BURN = 0
	CALL CHECK'COLLISION			!how's my driving?
	CALL SHOW'SHIP				!update ship position
	XCALL INKEY,CHAR			!key press waiting?
	CHAR = UCS(CHAR)
	IF CHAR=CHR(12) CALL ROTATE'RIGHT
	IF CHAR=CHR( 8) CALL ROTATE'LEFT
	IF CHAR >= "0" AND CHAR <= "9" CALL BURN'FUEL
	IF CHAR="Q" GOTO QUIT'SHIP		!quiters never win ... wimp!
	IF CHAR="" XCALL SLEEP,0.1		!nothing, just snooze...
	CLK = CLK + 1
	GOTO LOOP

QUIT'SHIP:
	CALL ERASE'SHIP
	XCALL AMGSBR,G'CLWK,GCB,STATUS		!close the workstation
	? TAB(-1,0);TAB(-1,28);
	CHAIN "DSK0:COGO[15,1]"			!this is only for our system
	END

SHOW'SHIP:
	!draw the ship at the current x & y position
	FOR I=1 TO NO'SHIP'PTS
	  ARY'INDEX = SHIP'ANG + SHIP(I,2)
	  IF ARY'INDEX > 72 ARY'INDEX = ARY'INDEX - 72
	  PT'X(I) = SHIP'X + COS'ARY(ARY'INDEX)*SHIP(I,1)
	  PT'Y(I) = SHIP'Y + SIN'ARY(ARY'INDEX)*SHIP(I,1)
	NEXT I
	IF INIT'FLAG XCALL AMGSBR,G'PL,GCB,OLD'POS,STATUS
	XCALL AMGSBR,G'PL,GCB,PT'ARY,STATUS
	OLD'POS = PT'ARY
	INIT'FLAG = 1
	RETURN

!since were using XOR writing mode, just redraw the ship and it disappears...
ERASE'SHIP:
	XCALL AMGSBR,G'PL,GCB,PT'ARY,STATUS
	RETURN

ROTATE'LEFT:				!rotate ship CCW
	IF FUEL < 10 RETURN		!check GAS
	FUEL = FUEL - 10		!burn some fuel
	SHIP'ANG = SHIP'ANG - 2		!change angle by 10 degrees
	IF SHIP'ANG < 1 SHIP'ANG = SHIP'ANG + 72	!adjust array index
	RETURN

ROTATE'RIGHT:				!rotate ship CW
	IF FUEL < 10 RETURN		!any gas left?
	FUEL = FUEL - 10		!burn some fuel
	SHIP'ANG = SHIP'ANG + 2		!change angle by 10 degrees
	IF SHIP'ANG > 72 SHIP'ANG = SHIP'ANG - 72	!adjust index
	RETURN

BUILD'SHIP:
!this SHIP array holds the dimensions of the ship. Each measurement is
!taken as a distance and an angle from this center point. Each angle
!is actually a reference into the sine & cosine arrays.
! SHIP( 1,1) = 500 ... 500 units from center to 1st point
! SHIP( 1,2) = 18  ...  18*5 or 90 degrees from horizontal, references
!                       18th position in sine & cosine arrays...

!define the SHIP shape
	SHIP( 1,1) = 500
	SHIP( 1,2) = 18
	SHIP( 2,1) = 640
	SHIP( 2,2) = 42
	SHIP( 3,1) = 700
	SHIP( 3,2) = 48
	SHIP( 4,1) = 480
	SHIP( 4,2) = 54
	SHIP( 5,1) = 700
	SHIP( 5,2) = 60
	SHIP( 6,1) = 640
	SHIP( 6,2) = 66
	SHIP( 7,1) = 500
	SHIP( 7,2) = 18
	NO'SHIP'PTS = 7
!define the flame shape
	FLAME(1,1) = 600
	FLAME(1,2) = 52
	FLAME(2,1) = 1500
	FLAME(2,2) = 54
	FLAME(3,1) = 600
	FLAME(3,2) = 56
!load the sines & cosines into arrays for speed
!loaded at 5 degree increments.
	? "ANGS INIT"
	FOR I=1 TO 72
	  SIN'ARY(I) = SIN((I-1)*0.087266463)
	  COS'ARY(I) = COS((I-1)*0.087266463)
	  ? ".";
	NEXT I
	? 
	RETURN

!BURN'FUEL at the rate determined by user input. Each burn contributes to
!the x velocity & the y velocity depending on the ship angle.
BURN'FUEL:
	BURN'RATE = VAL(CHAR)*10
	IF FUEL < BURN'RATE CALL NO'GAS : RETURN
	FUEL = FUEL - BURN'RATE
	BURN = BURN'RATE*COS'ARY(SHIP'ANG)
	VEL'X = VEL'X - BURN'RATE*SIN'ARY(SHIP'ANG)
	FOR I=1 TO 3
	  ARY'INDEX = SHIP'ANG + FLAME(I,2)
	  IF ARY'INDEX > 72 ARY'INDEX = ARY'INDEX - 72
	  PT'X(I) = SHIP'X + COS'ARY(ARY'INDEX)*FLAME(I,1)
	  PT'Y(I) = SHIP'Y + SIN'ARY(ARY'INDEX)*FLAME(I,1)
	NEXT I
	PT'CT = 3
	XCALL AMGSBR,G'SPLC,GCB,4,STATUS
	XCALL AMGSBR,G'PL,GCB,PT'ARY,STATUS
	XCALL SLEEP,0.1
	XCALL AMGSBR,G'PL,GCB,PT'ARY,STATUS
	XCALL AMGSBR,G'SPLC,GCB,1,STATUS
	PT'CT = NO'SHIP'PTS
	RETURN

!check to see if the midpoint of the ship has found terra firma anywhere,
!is so we blow up.
CHECK'COLLISION:
	IF SHIP'X < 13500 AND SHIP'X > 9500 GOTO CHECK'LANDING
	I = 2
CC'1:	IF I > SRF'CT GOTO CC'3
	IF SHIP'X <= SRF'X(I) AND SHIP'X >= SRF'X(I-1) GOTO CC'2
	I = I+1
	GOTO CC'1
CC'2:	Y'POS = SRF'Y(I-1) + &
	  (((SHIP'X-SRF'X(I-1))*(SRF'Y(I)-SRF'Y(I-1)))/(SRF'X(I)-SRF'X(I-1)))
	IF Y'POS < SHIP'Y RETURN
CC'3:	GOTO BOOM

!we are over the landing pad...have we landed yet??
CHECK'LANDING:
	LAND'FLAG = 0
	FOR I=1 TO NO'SHIP'PTS		!check all corners of the ship
	  ARY'INDEX = SHIP'ANG + SHIP(I,2)
	  IF ARY'INDEX > 72 ARY'INDEX = ARY'INDEX - 72
	  Y'POS = SHIP'Y + SIN'ARY(ARY'INDEX)*SHIP(I,1)
	  IF Y'POS < 4000 LAND'FLAG = 1
	NEXT I
	IF LAND'FLAG = 0 RETURN
!at this point we know we are on the ground
	? TAB(33,1);
!could definitely stand a little better messages...
	IF VEL'Y < 50 ? "Good Landing"
	IF VEL'Y > 50 AND VEL'Y < 75 ? "Landed with structural damage"
	IF VEL'Y > 75 AND VEL'Y < 125 ? "Landed, severe damage, few survivors"
	IF VEL'Y > 125 ? "Landed, Ship completely destroyed, all lives lost" : GOTO BOOM
	? TAB(34,13);VEL'X USING "####";
	? TAB(34,22);VEL'Y USING "####";
	? TAB(34,38);SHIP'Y USING "#####";
	? TAB(34,51);FUEL USING "####";
	? TAB(1,1);
	? TAB(-1,28);
	XCALL AMGSBR,G'CLWK,GCB,STATUS		!close the workstation
	END

!we crashed so let's blow up...
BOOM:	XCALL AMGSBR,G'SPLT,GCB,2,STATUS
	XCALL AMGSBR,G'PL,GCB,PT'ARY,STATUS
	XCALL SLEEP,0.1
	XCALL AMGSBR,G'SPLT,GCB,3,STATUS
	XCALL AMGSBR,G'PL,GCB,PT'ARY,STATUS
	XCALL SLEEP,0.1
	CALL ERASE'SHIP
	FOR I=1 TO 10
	  ? TAB(-1,36);
	  XCALL SLEEP,0.1
	  ? TAB(-1,37);
	  XCALL SLEEP,0.1
	NEXT I
	? TAB(1,1);
	? "YOU DIED..."
	? TAB(-1,28);
	XCALL AMGSBR,G'CLWK,GCB,STATUS		!close the workstation
	END

SHOW'BASE:
!in the future, we should alter the landscape for variety,
!possibly using random number generation for the surface.
	SRF'X( 1) = 00000 : SRF'Y( 1) = 2662
	SRF'X( 2) = 00000 : SRF'Y( 2) = 6600
	SRF'X( 3) = 02600 : SRF'Y( 3) = 12500
	SRF'X( 4) = 03600 : SRF'Y( 4) = 5300
	SRF'X( 5) = 06000 : SRF'Y( 5) = 8400
	SRF'X( 6) = 07500 : SRF'Y( 6) = 6000
	SRF'X( 7) = 08200 : SRF'Y( 7) = 9000
	SRF'X( 8) = 09500 : SRF'Y( 8) = 4000
	SRF'X( 9) = 13500 : SRF'Y( 9) = 4000
	SRF'X(10) = 15200 : SRF'Y(10) = 13000
	SRF'X(11) = 16500 : SRF'Y(11) = 7100
	SRF'X(12) = 19400 : SRF'Y(12) = 10000
	SRF'X(13) = 21000 : SRF'Y(13) = 8000
	SRF'X(14) = 24100 : SRF'Y(14) = 13500
	SRF'X(15) = 26200 : SRF'Y(15) = 8700
	SRF'X(16) = 28000 : SRF'Y(16) = 13000
	SRF'X(17) = 29900 : SRF'Y(17) = 8100
	SRF'X(18) = 32000 : SRF'Y(18) = 12000
	SRF'X(19) = 32000 : SRF'Y(19) = 2662
	SRF'X(20) = 00000 : SRF'Y(20) = 2662
	SRF'CT = 20
	XCALL AMGSBR,G'SFAS,GCB,3,STATUS
	XCALL AMGSBR,G'SFAI,GCB,22,STATUS
	XCALL AMGSBR,G'SFAC,GCB,9,STATUS
	XCALL AMGSBR,G'FA,GCB,SURFACE,STATUS
	PT'X(1) = 9500  : PT'Y(1) = 4000
	PT'X(2) = 13500 : PT'Y(2) = 4000
	PT'X(3) = 13500 : PT'Y(3) = 3000
	PT'X(4) = 9500  : PT'Y(4) = 3000
	PT'X(5) = 9500  : PT'Y(5) = 4000
	PT'CT = 5
	XCALL AMGSBR,G'SFAS,GCB,2,STATUS
	XCALL AMGSBR,G'SFAC,GCB,5,STATUS
	XCALL AMGSBR,G'FA,GCB,PT'ARY,STATUS
	RETURN

!no gas left in the tanks...bummer...
NO'GAS:	? TAB(32,1);
	? TAB(-2,1);TAB(-3,4);CHR(7);" INSUFFICIENT FUEL ";
	? TAB(-2,1);TAB(-3,0);
	RETURN