*         1515    030784
*
*
** COLLIDE.S **
** ASTEROIDS FOR THE ATARI 3600 **
** THIS FILE CONTAINS THE COLLISION HANDLING ROUTINE. **
**
**        INDEXING - ROCKS               0 THRU 23
**                   SHIP                24
**                   UFO                 25
**                   UFOSHOT             26 THRU 27
**                   SHIPSHOT            28 THRU 31
**                   SHIP2               32
**
**        STATUS - LO NYBBLE - OBJECT TYPE - 0 - SMALL ROCK
**                                           1 - MEDIUM ROCK
**                                           2 - LARGE ROCK
**                                           3 - SHIP
**                                           4 - SMALL UFO
**                                           5 - LARGE UFO
**                                           6 - SHOT
**                                           7 - SHIP'S PARTS (+MISC JUNK)
**                 HI NYBBLE - OBJECT SIZE - INDEX INTO SIZE TABLES
**                                           (UNUSED, I BELIEVE)
**
**                  < 0 - NULL OBJECT
**
**        USES TEMP LOCATIONS AS FOLLOWS:
**                TEMP                   DX (REUSED LATER)
**                TEMP+1                 DY
**                TEMP+2                 DX+DY (MANHATTAN DISTANCE)
**                TEMP+3,TEMP+4          SAVE AREA FOR INDEX REGISTERS X & Y
**                TEMP+5,TEMP+6          SAVE AREA FOR 'TYPE NYBBLES'
**                                       (IE, LO NYBBLE OF STATUS BYTE)
**                TEMP+7                 ROCK TYPE, IN THE EVENT OF AN EXPLOSION
**                TEMP+8,TEMP+9          SHORT TERM SCRATCH TEMP
**                TEMP+10                SHIP'S DIRECTION INDEX
**
********************************************************************************


COLLIDE:
	LDA	RUBFLAG		;DECREMENT RUBBER SHIP FLAG IF NEEDED
	BMI	ZNODERUB
	DEC	RUBFLAG
ZNODERUB:
	LDX	#32		;START CHECKING WITH SHIP2
COLNXTX:
	LDA	STATUS,X	;IF OBJECT X DOESN'T EXIST THEN
	BMI	DECX		;GO ON TO NEXT X

	LDY	COLTAB-24,X	;FETCH FIRST OBJECT TO CHECK
COLNXTY:
	LDA	STATUS,Y	;IF OBJECT Y DOESN'T EXIST THEN
	BMI	DECY		;GO ON TO NEXT Y

	STX	TEMP+3		;SAVE X AND Y
	STY	TEMP+4

	JMP	COLCHK		;CHECK FOR COLLISION

RESTORE:
	LDX	TEMP+3	;RESTORE X AND Y
	LDY	TEMP+4

DECY:
	DEY
	BPL	COLNXTY
DECX:
	DEX
	CPX	#24
	BPL	COLNXTX
COLRTS:
	RTS



* CHECK FOR AN ACTUAL COLLISION BETWEEN OBJECTS WHOSE INDICES ARE IN X AND Y.
COLCHK:
	LDA	COLXPOSH,X	;COMPUTE DX
	SEC
	SBC	COLXPOSH,Y
	BCS	DXPOS		;TAKE ABSOLUTE VALUE
	EOR	#$FF
;	CLC			;CARRY MUST ALREADY BE CLR (BCS ABOVE)
	ADC	#1

DXPOS:
	CMP	#XPOSMAX-13	;CHECK FOR WRAPAROUND (WIDEST OBJ=12)
	BCC	DXOK		;NO WRAP
	CPX	#25		;DON'T X-WRAP THE UFO
	BEQ	DXOK
	CPY	#25
	BEQ	DXOK
	SEC
	SBC	#XPOSMAX+1	;USE WRAPPED DISTANCE
	EOR	#$FF
;	CLC			;CARRY IS CLEAR FROM SBC (IE, BORROW)
	ADC	#1

DXOK:
	CMP	#10		;FURTHEST COLLISION HAS DX OF ONLY 10
	BCS	NOCOL		; IF >= 11, NO COLLISION.
	STA	TEMP

	LDA	COLYPOSH,X	;COMPUTE DY
	SEC
	SBC	COLYPOSH,Y
	BCS	DYPOS		;TAKE ABSOLUTE VALUE
	EOR	#$FF
;	CLC		;CARRY MUST ALREADY BE CLR (BCS ABOVE)
	ADC	#1

DYPOS:
	CMP	#YPOSMAX-17	;CHECK FOR WRAPAROUND (TALLEST OBJ=16)
	BCC	DYOK		;NO WRAP
	SBC	#YPOSMAX+1	;USE WRAPPED DISTANCE
	EOR	#$FF
;	CLC		;CARRY IS CLEAR FROM SBC (IE, BORROW)
	ADC	#1

DYOK:
	CMP	#14		;FURTHEST COLLISION HAS DY OF ONLY 14
	BCS	NOCOL		; IF >= 15, NO COLLISION.
	STA	TEMP+1

* AT THIS POINT, WE MUST DO CLOSER INSPECTION, SINCE THE OBJECTS ARE CLOSE.
	CLC			;COMPUTE MANHATTAN DISTANCE (DX+DY)
	ADC	TEMP
	STA	TEMP+2

	LDA	STATUS,X	;TEMP+5 <- TYPE OF OBJECT X
	AND	#$0F
	STA	TEMP+5

	LDA	STATUS,Y	;TEMP+6 <- TYPE OF OBJECT Y
	AND	#$0F
	STA	TEMP+6

	STY	TEMP+9		;SAVE Y, WE NEED AN INDEX REGISTER!

	TAY
	LDA	OBJDIAG,Y	;GET WIDTH OF SECOND OBJECT
	LDY	TEMP+5
	ADC	OBJDIAG,Y	;ADD IN WIDTH OF FIRST OBJECT
	CMP	TEMP+2		;COMPARE WITH MANHATTAN DISTANCE
	BMI	NOCOL1		;TOO FAR AWAY, NO COLLISION.

	LDA	OBJWID,Y	;DO MORE PRECISE XTENT CHECKING
	LDY	TEMP+6
	CLC
	ADC	OBJWID,Y
	CMP	TEMP
	BCC	NOCOL1		;TOO FAR TO THE SIDE: NO COLLISION

	LDA	OBJHEIT,Y	;DO MORE PRECISE YTENT CHECKING
	LDY	TEMP+5
	CLC
	ADC	OBJHEIT,Y
	CMP	TEMP+1
	BCS	YESCOL	;WE HAVE A COLLISION.


NOCOL1:
	LDY	TEMP+9	;RESTORE Y
NOCOL:
	CPY	#40		;DECREMENT INDICES WITHOUT RESTORING
	BEQ	COLSETX		; IF WE ARE DOING SPECIAL CHECKING
	BCS	DECY1
	CPX	#40
	BEQ	RESTORE1
	CPX	#37
	BCC	RESTORE1
	BCS	DECX1		;(UNCONDITIONAL)

COLSETX:
	CPX	#37		;SET X AND Y TO LOOP OVER SHIP'S PARTS
	BCC	RESTORE1
	BCS	COLSETY		;(UNCONDITIONAL)

COLSETY:
	LDY	#43		;RESET Y FOR NEXT ROUND
DECX1:
	DEX
	JMP	COLCHK
DECY1:
	DEY
	JMP	COLCHK


* COME HERE IN THE EVENT OF A POSSIBLE COLLISION.
YESCOL:
	;COMPUTE LOWEST P2 BULLET OR SHIP FOR THIS MODE.  IN TEAM MODES
	;WE SHARE BULLETS.  RESULT IS LEFT IN TEMP FOR LATER.
	LDA	#32		;ASSUME 30 AND 31 ARE NOT P2'S
	LDY	MODE
	CPY	#1
	BMI	NOTEAMSC	;NOT TEAMPLAY, DON'T SPLIT BULLETS
	LDA	#30		;30 AND 31 ARE P2'S
NOTEAMSC:
	STA	TEMP

	LDY	TEMP+9		;RESTORE Y

* PERFORM ACTIONS DEPENDENT UPON THE SPECIAL CASE OBJECTS
	CPX	#32
	BEQ	COLP2X		;FIRST OBJECT IS P2 SHIP
	CPX	#24
	BEQ	COLP1X		;FIRST OBJECT IS P1 SHIP
	CPY	#24
	BEQ	COLP1Y		;SECOND OBJECT IS P1 SHIP

	LDX	TEMP+3		;RESTORE X AND Y
	LDY	TEMP+4
	JSR	DOCOL		;DO THE COLLISION
	JMP	DECX		;AND THE NEXT ITERATION
RESTORE1:
	JMP	RESTORE		;AND CONTINUE


COLP2X:
	LDA	STATE+1		;DON'T COLLIDE IF SHIP ISN'T OK
	BNE	RESTORE1

	LDA	MODE		;IN COMPETITIVE, P1'S SHOTS KILL P2
	CMP	#2
	BEQ	COLP2XGO
	CPY	#28		; (P1'S SHOTS ARE 28 AND 29)
	BCS	RESTORE1	;OTHERWISE, IGNORE THEM
COLP2XGO:
	LDX	#39		;POINT TO SHIP2'S PARTS
	JSR	P2SETUP		;SET UP FOR SPECIAL P2 CHECKING
	CPY	#24		;IS IT SHIP1 VS SHIP2?
	BNE	COLNOP1Y	;NOPE
	LDA	MODE
	CMP	#2		;IN COMPETITIVE PLAY, DON'T BOUNCE,
	BEQ	COLP1Y		; COLLIDE!

	LDA	STATE		;IF SHIP NOT OK, DON'T COLLIDE
	BNE	RESTORE1
	JMP	RUBBERS		;LET'S GO BOUNCY BOUNCY...

COLP1Y:
	LDA	STATE		;DON'T COLLIDE IF SHIP ISN'T OK
	BNE	RESTORE1

	CPX	#28		;ANYTHING LESS THAN 28 IS HARMFUL
	BCC	COLP1YGO

	;IN TEAM PLAY, IGNORE THE COLLISION: THEY ARE FRIENDS
	LDA	MODE
	CMP	#1
	BEQ	RESTORE1

	CPX	TEMP		;CHECK AGAINST P2'S BULLETS.
	BCC	RESTORE1	; IF < TEMP, IT IS SAFE

	;NOT SAFE: CHECK SHIP'S PARTS
COLP1YGO:
	LDY	#43		;POINT TO SHIP1'S PARTS
COLP1GO:
	JSR	P1SETUP		;SET THEM UP
COLNOP1Y:
	JMP	COLCHK		;AND CONTINUE


COLP1X:
	LDA	STATE		;DON'T COLLIDE IF SHIP ISN'T OK
	BNE	RESTORE1

	LDX	#43		;POINT TO SHIP1'S PARTS
	BNE	COLP1GO		;CONTINUE AS ABOVE (UNCONDITIONAL)


* P1SETUP: SET UP STATUS ENTRIES FOR THE PARTS OF THE SHIP TO CHECK
P1SETUP:
	STX	TEMP+8
	LDA	SHIPDIR		;GENERATE SHIP DIRECTION INDEX
	LSR
	LSR
	LSR
	LSR
	TAX
	LDA	SHNOSEX,X
	CLC
	ADC	XPOSH+24
	STA	COLXPOSH+40
	LDA	SHNOSEY,X
	ADC	YPOSH+24
	STA	COLYPOSH+40

	LDA	SHRTAILX,X
;	CLC
	ADC	XPOSH+24
	STA	COLXPOSH+41
	LDA	SHRTAILY,X
	ADC	YPOSH+24
	STA	COLYPOSH+41

	LDA	SHLTAILX,X
;	CLC
	ADC	XPOSH+24
	STA	COLXPOSH+42
	LDA	SHLTAILY,X
	ADC	YPOSH+24
	STA	COLYPOSH+42

	LDA	COLXPOSH+24
	STA	COLXPOSH+43
	LDA	COLYPOSH+24
	STA	COLYPOSH+43

	LDX	TEMP+8
	RTS

* P2SETUP: SET UP STATUS ENTRIES FOR THE PARTS OF THE SHIP TO CHECK
P2SETUP:
	STX	TEMP+8
	LDA	SHIPDIR+1	;GENERATE SHIP DIRECTION INDEX
	LSR
	LSR
	LSR
	LSR
	TAX
	LDA	SHNOSEX,X
	CLC
	ADC	XPOSH+32
	STA	COLXPOSH+36
	LDA	SHNOSEY,X
	ADC	YPOSH+32
	STA	COLYPOSH+36

	LDA	SHRTAILX,X
;	CLC
	ADC	XPOSH+32
	STA	COLXPOSH+37
	LDA	SHRTAILY,X
	ADC	YPOSH+32
	STA	COLYPOSH+37

	LDA	SHLTAILX,X
;	CLC
	ADC	XPOSH+32
	STA	COLXPOSH+38
	LDA	SHLTAILY,X
	ADC	YPOSH+32
	STA	COLYPOSH+38

	LDA	COLXPOSH+32
	STA	COLXPOSH+39
	LDA	COLYPOSH+32
	STA	COLYPOSH+39

	LDX	TEMP+8
	RTS

* DOCOL1: PERFORM CERTAIN COMMON ACTIONS ON AN OBJECT EXPLODING.
* ON ENTRANCE, X IS THE INDEX OF OBJECT COLLIDING.  ON EXIT, TEMP+6 HAS THE
* 'TYPE NYBBLE'.  OH, AND BY THE WAY, X AND Y ARE TRASHED.
DOCOL1:
	STX	TEMP+8		;SAVE X
	LDA	STATUS,X
	ORA	#$80		;TAG THIS OBJECT AS "EXPLODING"
	STA	STATUS,X
	AND	#$0F		;COMPUTE OBJECT TYPE (AGAIN)
	STA	TEMP+6		;STORE IT

	CMP	#6
	BCS	NOEXPSND	;OBJECTS >= 6 MAKE NO EXPLOSION SOUNDS
	CMP	#4
	BCS	COLUFO		;UFO COLLIDING: HANDLE IT
	CMP	#3
	BCS	COLSHIP		;SHIP COLLIDING: HANDLE IT

;	CLC			;CARRY IS CLEAR
	ADC	#$0A		;ADD OFFSET OF ROCK TUNES
	PHA			;THIS IS 'ROCKSND'
	LDA	#$0A		; (KILL OFF ANY CURRENT ROCK SOUNDS)
	JSR	KILLTUNE
	LDA	#$0B
	JSR	KILLTUNE
	LDA	#$0C
	JSR	KILLTUNE
	PLA

CONT:
	JSR	DOTUNE
	LDX	TEMP+8		;RESTORE X, TRASHED BY DOTUNE
NOEXPSND:
	LDY	TEMP+6		;GET TYPE NYBBLE
	LDA	ELBOUND,Y	;SET UP EXPLOSION ANIMATION
	STA	ACYC,X
	RTS

COLUFO:
	TAX
	SEC
	SBC	#2		;COMPUTE INDEX INTO LVLINC
	JSR	INCLVL		;MAKE IT HARDER NOW
	CPX	#4		;ONLY MR. BILL CHANGES ACCURACY
	BNE	ZNOBILAC
	LDA	UFOACC
	CMP	#4		;DON'T GO BELOW 3
	BCC	ZNOBILAC
	DEC	UFOACC		;TIGHTEN UP MR. BILL'S ACCURACY
ZNOBILAC:
	TXA			;DO TUNES: CANCEL THEME AND PLAY EXPL.
	CLC
	ADC	#2		;EXPLOSION = TYPE + 2
	PHA			;PUSH IT FOR LATER
	ADC	#2		;THEME = TYPE + 4
	JSR	KILLTUNE
	PLA			;PULL EXPLOSION SOUND
	BPL	CONT		;BPL = JMP

COLSHIP:
	LDA	TEMP+8		;FIGURE OUT WHICH SHIP DIED
	LDX	#0		;DEFAULT TO SHIP 1
	CMP	#32		;FIGURE OUT WHICH SHIP DIED
	BNE	NOP2DIE
	INX			;INCREMENT TO SHIP 2
NOP2DIE:
	LDA	#DEATH		;INDUCE A FATAL DEATH
	STA	STATE,X
	LDA	#DIET+$28	;AT TIMER 'DIE TIME' + $28
	STA	TIMER,X

	LDA	#$05		;SHIP EXPLOSION = 05
	BPL	CONT		;BPL = JMP

* WE HAVE A COLLISION, FOLKS!  DO WHAT NEEDS TO BE DONE (EXPLODING, SCORING)
DOCOL:
;DEBUGGING PATCH
;	  LDA	  #$0A	;USE SMALL ROCK EXPLOSION SOUND
;	  JSR	  DOTUNE
;	  LDX	  TEMP+3
;	  LDY	  TEMP+4
;	  RTS

* FIRST DO TUNES AND EXPLOSION ANIMATIONS
;	LDX	TEMP+3
	JSR	DOCOL1
	LDA	TEMP+6		;TRANSFER TYPE NYBBLE
	STA	TEMP+5		; TO PROPER PLACE

	LDX	TEMP+4
	JSR	DOCOL1

* NOW DO SCORING
	LDX	TEMP+6		;SCORE ONE OBJECT
	LDY	TEMP+3
	JSR	DOSCOR
	LDX	TEMP+5		;SCORE OTHER OBJECT
	LDY	TEMP+4
	JSR	DOSCOR

	CPY	#24		;SEE IF WE HAVE ANY EXPLODING ROCKS
	BCC	ROCKEXPL
	LDX	TEMP+3		;RESTORE X
	RTS

* SCORE OBJECT OF TYPE X ACCORDINGLY AS IT WERE SHOT BY OBJECT Y
* I.E., IF Y CONTAINS INDEX OF PLAYER ONE'S SHOT, SCORE A HIT ON AN 'X' TO
* PLAYER ONE.
DOSCOR:
	CPY	TEMP		;CHECK P2'S BULLETS OR SHIP
	BPL	SCORP2		;CREDIT OBJECT TO P2'S SCORE
	CPY	#28		;CHECK P1'S BULLETS
	BPL	SCORPL		;CREDIT OBJECT TO CURRENT PLAYER
	CPY	#24		;CHECK P1'S SHIP
	BNE	SCORERTS	;NONE OF THE ABOVE: RTS
	CPX	#3		;IS IT A SHIP THAT #24 IS HITTING?
	BNE	SCORPL		;NO.  JUST SCORE IT.
	LDA	#17		;SOUR THE GOATMILK
	STA	GOATMILK
;	RTS		;RTS IF YOU DON'T WANT TO SCORE THESE.

SCORPL:
	LDA	PLAYER		;SCORE IT TO THE CURRENT PLAYER
SCORIT:
	STA	SCORER		;MARK THE SCORER
	JSR	ADDPOINT	;RACK 'EM UP
SCORERTS:
	RTS

SCORP2:
	LDA	#1		;SCORE FOR P2 REGARDLESS OF PLAYER
	BPL	SCORIT		;BPL = JMP


* HANDLE EXPLODING (="SPLITTING") ROCKS.
ROCKEXPL:
	LDA	STATUS,Y	;CHECK THE EXPLODING ROCK
	SEC
	SBC	#$91		;WIDTH IS LO NYBBLE. IF =1, THEN SMALL
	BMI	SPLITRTS	;THIS IS CLEVER.  B2-91=21, ETC...
	STA	TEMP+7		;SAVE IT FOR NEWROCK TO USE...

	LDA	#$50		;RESET 5.2 SEC UFO COUNTER
	STA	RTIMER

	;CREATE ONE, TWO, OR THREE NEW ROCKS, BASED ON DIFF.
	LDA	DIFF		;UNLESS AT A WHIPPY LEVEL THEN ONE
	BEQ	ONEROCK
	CMP	#3		;AT EXPERT LEVEL, MAYBE > 2 ROCKS!
	BCC	TWOROCKS
	LDA	RANDPTR0	;USE PTR AS RANDOM (NEWRAND SCREWS Y)
	AND	#$03
	BNE	TWOROCKS
	JSR	NEWROCK		;CREATE EACH NEW ROCK IF POSSIBLE;
TWOROCKS:
	JSR	NEWROCK	;NEWROCK RETURNS "EMPTY HANDED" IF NOT.
ONEROCK:
	JSR	NEWROCK

	LDX	TEMP+3		;RESTORE X, TRASHED IN NEWROCK
SPLITRTS:
	RTS

NEWROCK:
	LDX	#23		;FIND A FREE ROCK SLOT
ROCKLOOP:
	LDA	STATUS,X
	CMP	#$FF
	BEQ	THISROCK
	DEX
	BPL	ROCKLOOP
	RTS

THISROCK:
	LDA	XPOSL,Y		;INITIALIZE NEW ROCK (X) FROM OLD (Y)
	STA	XPOSL,X
	LDA	XPOSH,Y
	STA	XPOSH,X
	LDA	YPOSL,Y
	STA	YPOSL,X
	LDA	YPOSH,Y
	STA	YPOSH,X
	LDA	COLXPOSH,Y	;THESE AREN'T QUITE RIGHT, BUT CLOSE.
	STA	COLXPOSH,X
	LDA	COLYPOSH,Y
	STA	COLYPOSH,X
	LDA	PALS,Y		;ADJUST WIDTH TO SMALLER ROCK SIZE
	CLC
	ADC	#1
	STA	PALS,X

	LDA	TEMP+7		;GIVE IT THE PROPER ROCK TYPE STATUS
	STA	STATUS,X
	AND	#$0F		;SET FIRST ANIMATION FRAME
	TAY
	LDA	ROCKCYC,Y
	STA	ACYC,X
	JSR	RANDVEL		;SET UP RANDOM VELOCITIES.
	LDX	PLAYER
	INC	ROCKTOT,X	;THERE IS NOW ONE MORE ROCK!
	LDY	TEMP+4		;RESTORE Y, TRASHED ABOVE
	RTS

;RUBBER SHIPS
RUBBERS:
	LDA	RUBFLAG		;HAVE WE BEEN HERE BEFORE?
	BPL	ZNORUB		;YUP.  DON'T BOUNCE BACK

	LDA	XVELH+24
	CMP	#$80		;SIGNED 16 BIT DIVIDE BY TWO
	ROR
	PHA
	LDA	XVELL+24
	ROR
	PHA
	LDA	XVELH+32
	CMP	#$80
	ROR
	STA	XVELH+24
	LDA	XVELL+32
	ROR
	STA	XVELL+24
	PLA
	STA	XVELL+32
	PLA
	STA	XVELH+32

	LDA	YVELH+24
	CMP	#$80
	ROR
	PHA
	LDA	YVELL+24
	ROR
	PHA
	LDA	YVELH+32
	CMP	#$80
	ROR
	STA	YVELH+24
	LDA	YVELL+32
	ROR
	STA	YVELL+24
	PLA
	STA	YVELL+32
	PLA
	STA	YVELH+32

ZNORUB:
	LDA	#1		;PREVENT A SECOND BOUNCE
	STA	RUBFLAG
	JMP	RESTORE

* TABLE OF STARTING VALUES FOR 'Y' IN COLLIDE LOOP: ESSENTIALLY, THESE ARE
* THE HIGHEST NUMBERED OBJECTS WE MUST COMPARE TO FOR A GIVEN X.
* THESE ARE OFFSET BY 24, SINCE THE LOWEST X WE CHECK IS 24 (SHIP1)
*
COLTAB:
	.DC.B	23,24,24,24,25,25,25,25,29

* WIDTH TABLES FOR COLLISION PURPOSES
OBJWID:
	.DC.B	 2,4,5,3,2,4,1,1;X-EXTENTS (XTENTS)
OBJHEIT:
	.DC.B	 3,6,8,6,2,3,1,1;Y-EXTENTS (YTENTS)
OBJDIAG:
	.DC.B	 3,6,9,6,2,3,2,1;DIAGONALS

* OFFSET (INTO THE STAMP) OF SHARP POINTS OF THE SHIP
SHLTAILX:
	.DC.B	 1,0,0,1,1,2,3,4,5,5,6,5,5,4,3,2
SHLTAILY:
	.DC.B	 5,7,9,11,12,13,14,14,13,11,9,7,6,5,4,4
SHRTAILX:
	.DC.B	 5,4,3,2,1,1,0,0,1,2,3,4,5,5,6,5
SHRTAILY:
	.DC.B	 5,4,4,5,6,7,9,11,13,14,14,13,12,11,9,7
