Elite on the BBC Micro and NES

# Tactics: TACTICS (Part 7 of 7)

## [BBC Micro disc version, Flight]

```       Name: TACTICS (Part 7 of 7)                                   [Show more]
Type: Subroutine
Category: Tactics
Summary: Apply tactics: Set pitch, roll, and acceleration
Deep dive: Program flow of the tactics routine
Context: See this subroutine in context in the source code
Variations: See code variations for this subroutine in the different versions
References: This subroutine is called as follows:
* DOCKIT calls via TA151
* TACTICS (Part 3 of 7) calls via TA151
* TACTICS (Part 6 of 7) calls via TA9-1

This section looks at manoeuvring the ship. Specifically:

* Work out which direction the ship should be moving, depending on the type
of ship, where it is, which direction it is pointing, and how aggressive
it is

* Set the pitch and roll counters to head in that direction

* Speed up or slow down, depending on where the ship is in relation to us

Other entry points:

TA151                Make the ship head towards the planet

TA9-1                Contains an RTS

.TA4

LDA INWK+7             \ If z_hi >= 3 then the ship is quite far away, so jump
CMP #3                 \ down to TA5
BCS TA5

LDA INWK+1             \ Otherwise set A = x_hi OR y_hi and extract bits 1-7
ORA INWK+4
AND #%11111110

BEQ TA15               \ If A = 0 then the ship is pretty close to us, so jump
\ to TA15 so it heads away from us

.TA5

\ If we get here then the ship is quite far away

JSR DORND              \ Set A and X to random numbers

ORA #%10000000         \ Set bit 7 of A, so A is at least 128

CMP INWK+32            \ If A >= byte #32 (the ship's AI flag) then jump down
BCS TA15               \ to TA15 so it heads away from us

\ We get here if A < byte #32, and the chances of this
\ being true are greater with high values of byte #32,
\ as long as they are at least 128
\
\ In other words, higher byte #32 values increase the
\ chances of a ship changing direction to head towards
\ us - or, to put it another way, ships with higher
\ byte #32 values of 128 or more are spoiling for a
\ fight
\
\ Thargoids have byte #32 set to 255, which explains
\ an awful lot

.TA20

\ If this is a missile we will have jumped straight
\ here, but we also get here if the ship is either far
\ away and aggressive, or not too close

JSR TAS6               \ Call TAS6 to negate the vector in XX15 so it points in
\ the opposite direction

LDA CNT                \ Change the sign of the dot product in CNT, so now it's
EOR #%10000000         \ positive if the ships are facing each other, and
\ negative if they are facing the same way

.TA152

STA CNT                \ Update CNT with the new value in A

.TA15

\ If we get here, then one of the following is true:
\
\   * This is a trader and XX15 is pointing towards the
\     planet
\
\   * The ship is pretty close to us, or it's just not
\     very aggressive (though there is a random factor
\     at play here too). XX15 is still pointing from our
\     ship towards the enemy ship
\
\   * The ship is aggressive (though again, there's an
\     element of randomness here). XX15 is pointing from
\     the enemy ship towards our ship
\
\   * This is a missile heading for a target. XX15 is
\     pointing from the missile towards the target
\
\ We now want to move the ship in the direction of XX15,
\ which will make aggressive ships head towards us, and
\ ships that are too close turn away. Peaceful traders,
\ meanwhile, head off towards the planet in search of a
\ space station, and missiles home in on their targets

LDY #16                \ Set (A X) = roofv . XX15
JSR TAS3               \
\ This will be positive if XX15 is pointing in the same
\ direction as an arrow out of the top of the ship, in
\ other words if the ship should pull up to head in the
\ direction of XX15

TAX                    \ Copy A into X so we can retrieve it below

JSR nroll              \ Call nroll to calculate the value of the ship's pitch
\ counter

STA INWK+30            \ Store the result in the ship's pitch counter

LDA INWK+29            \ Fetch the roll counter from byte #29 into A

ASL A                  \ Shift A left to double it and drop the sign bit

BCS TA6                \ in the process of rolling

LDY #22                \ Set (A X) = sidev . XX15
JSR TAS3               \
\ This will be positive if XX15 is pointing in the same
\ direction as an arrow out of the right side of the
\ ship, in other words if the ship should roll right to
\ head in the direction of XX15

TAX                    \ Copy A into X so we can retrieve it below

EOR INWK+30            \ Give A the correct sign of the dot product * the
\ current pitch direction (i.e. the sign is negative if
\ the pitch counter and dot product have different
\ signs, positive if they have the same sign)

JSR nroll              \ Call nroll to calculate the value of the ship's pitch
\ counter

STA INWK+29            \ Store the result in the ship's roll counter

.TA12

.TA6

LDA CNT                \ Fetch the dot product, and if it's negative jump to
BMI TA9                \ TA9, as the ships are facing away from each other and
\ the ship might want to slow down to take another shot

CMP CNT2               \ The dot product is positive, so the ships are facing
BCC TA9                \ each other. If A < CNT2 then the ships are not heading
\ down

.PH10E

LDA #3                 \ Otherwise set the acceleration in byte #28 to 3
STA INWK+28

RTS                    \ Return from the subroutine

.TA9

AND #%01111111         \ Clear the sign bit of the dot product in A

CMP #18                \ If A < 18 then the ship is way off the XX15 vector, so
BCC TA10               \ return from the subroutine (TA10 contains an RTS)
\ without slowing down, as it still has quite a bit of
\ turning to do to get on course

LDA #&FF               \ Otherwise set A = -1

LDX TYPE               \ If this is not a missile then skip the ASL instruction
CPX #MSL
BNE P%+3

ASL A                  \ This is a missile, so set A = -2, as missiles are more
\ nimble and can brake more quickly

STA INWK+28            \ Set the ship's acceleration to A

.TA10

RTS                    \ Return from the subroutine

.TA151

\ This is called from part 3 with the vector to the
\ planet in XX15, when we want the ship to turn towards
\ the planet. It does the same dot product calculation
\ as part 3, but it can also change the value of RAT2
\ so that roll and pitch is always applied

JSR TAS3-2             \ Set (A X) = nosev . XX15
\
\ The bigger the value of the dot product, the more
\ aligned the two vectors are, with a maximum magnitude
\ in A of 36 (96 * 96 >> 8). If A is positive, the
\ vectors are facing in a similar direction, if it's
\ negative they are facing in opposite directions

CMP #&98               \ If A is positive or A <= -24, jump to ttt
BCC ttt

LDX #0                 \ A > -24, which means the vectors are facing in
STX RAT2               \ opposite directions but are quite aligned, so set
\ RAT2 = 0 instead of the default value of 4, so we
\ always apply roll and pitch when we turn the ship
\ towards the planet

.ttt

JMP TA152              \ Jump to TA152 to store A in CNT and move the ship in
\ the direction of XX15

.nroll

EOR #%10000000         \ Give the ship's pitch counter the opposite sign to the
AND #%10000000         \ dot product result, with a value of 0, and store it in
STA T                  \ T

TXA                    \ Retrieve the original value of A from X

ASL A                  \ Shift A left to double it and drop the sign bit

CMP RAT2               \ If A < RAT2, skip to nroll2 (so if RAT2 = 0, we always
BCC nroll2             \ set the pitch counter to RAT)

LDA RAT                \ Set the magnitude of the ship's pitch counter to RAT
ORA T                  \ (we already set the sign above and stored it in T)

RTS                    \ Return from the subroutine

.nroll2

LDA T                  \ Set A to the value we stored in T above, which has a
\ value of 0 and the opposite sign to the dot product
\ result

RTS                    \ Return from the subroutine
```