1;; ======================================================================== ;;
2;;  Bad guy thinker routines                                                ;;
3;;                                                                          ;;
4;;  These are called when their timers expire.  Timers are counted down     ;;
5;;  at a 30Hz rate.                                                         ;;
6;;                                                                          ;;
7;;  Thinkers have 2 bytes of state at their disposal, and can call BGRAND,  ;;
8;;  which returns a predictable hash of level-offset, elapsed time, R1, R3. ;;
9;;  The first byte of state is initialized when the bad-guy is spawned.     ;;
10;;  The intended use of this bytes is to specify "aggressiveness" and       ;;
11;;  "evasiveness."  Aggressiveness is how often the bad-guy fires.          ;;
12;;  Evasiveness is how much the bad guy tries to stay away from the tank.   ;;
13;;                                                                          ;;
14;;  Thinkers:                                                               ;;
15;;                                                                          ;;
16;;      BGT_SAUCxx  -- saucer flight programs.                              ;;
17;;      BGT_BOULDER -- rolling boulder program (set hscroll, roll)          ;;
18;;      BGT_TURRET  -- turret firing program (set hscroll, fire)            ;;
19;;      BGT_MINE    -- Land mine:  (set hscroll, blink randomly)            ;;
20;;      BGT_PLANT   -- space-plant program:  duck up/down randomly          ;;
21;;                                                                          ;;
22;;  Support (implemented):                                                  ;;
23;;                                                                          ;;
24;;      BGRAND      -- predictable RAND                                     ;;
25;;      BGBRAND     -- predictable RAND, bounded by R2                      ;;
26;;      BGFIRE      -- make a bad guy fire                                  ;;
27;;      BGKILL      -- remove bad guy from list of bad guys                 ;;
28;;                                                                          ;;
29;;  Support (todo -- maybe won't bother):                                   ;;
30;;                                                                          ;;
31;;      BGSETHS     -- Set horiz-scroll bit for this bad-guy                ;;
32;;      BGSETVEL    -- Set velocity for this bad-guy                        ;;
33;;      BGSETATTR   -- Set attribute number for this bad-guy                ;;
34;;                                                                          ;;
35;;  The thinkers are called with R1 == slot #, R3 == state pointer.         ;;
36;;  R0, R2, R4 are available as scratch.                                    ;;
37;;                                                                          ;;
38;;  Thinkers return with delay in R0.                                       ;;
39;; ======================================================================== ;;
40
41;; ======================================================================== ;;
42;;  BGRAND  -- A purposefully not-very-random random.  The LSBs are the     ;;
43;;             only useful bits.                                            ;;
44;; ======================================================================== ;;
45BGRAND      PROC
46
47            MVI     RCIDX,  R0      ; mix in rock/crater/spawn index
48            ADDR    R3,     R0      ; add BGMPTBL pointer
49            XORR    R1,     R0      ; mix in slot number
50            ADD     TIMSEC, R0      ; add time in seconds.
51
52            JR      R5
53            ENDP
54
55;; ======================================================================== ;;
56;;  BGBRAND -- Like BGRAND, only bounded to the range specified in R2.      ;;
57;; ======================================================================== ;;
58BGBRAND     PROC
59
60            CLRR    R0
61            CMPR    R2,     R0
62            BEQ     @@leave
63
64@@l1        SETC
65            RLC     R0,     1
66            CMPR    R2,     R0
67            BNC     @@l1
68
69            ; add a couple extra bits to mask.
70            ; this hopefully reduces the bias we give to certain numbers
71            ; with our crappy modulo technique.
72            SLLC    R0,     2
73            ADDI    #3,     R0
74
75            PSHR    R0
76
77            MVI     RCIDX,  R0      ; mix in rock/crater/spawn index
78            ADDR    R3,     R0      ; add BGMPTBL pointer
79            XORR    R1,     R0      ; mix in slot number
80            ADD     TIMSEC, R0      ; add time in seconds.
81
82            PSHR    R0              ;\
83            SWAP    R0              ; |-- fold upper, lower halves
84            XOR@    R6,     R0      ;/
85
86            AND@    R6,     R0      ; mask approximately into range.
87
88@@l2        SUBR    R2,     R0
89            BPL     @@l2
90
91            ADDR    R2,     R0
92@@leave:
93            JR      R5
94            ENDP
95
96;; ======================================================================== ;;
97;;  BGT_TURRET0:  Set horiz scroll, then set thinker to fire program.       ;;
98;; ======================================================================== ;;
99BGT_TURRET0 PROC
100
101            ;; ------------------------------------------------------------ ;;
102            ;;  Set up thinker for turret to just fire occasionally.        ;;
103            ;; ------------------------------------------------------------ ;;
104            MVII    #BGI.turret1, R0
105            B       BG_SETTHINK
106
107            ENDP
108
109;; ======================================================================== ;;
110;;  BGT_BOULDER0:  Set horiz scroll + left vel, then set thinker to roller. ;;
111;; ======================================================================== ;;
112BGT_BOULDER0 PROC
113
114            ;; ------------------------------------------------------------ ;;
115            ;;  Set up boulder to have some leftward velocity in addition   ;;
116            ;;  to what hscroll will give us.                               ;;
117            ;; ------------------------------------------------------------ ;;
118            MOVR    R1,     R2
119            ADDR    R1,     R2
120            ADDI    #SPXYV, R2
121
122            MVII    #$A8FF, R0
123            MVO@    R0,     R2
124
125            ; Set up thinker for boulder to just animate.
126            MVII    #BGI.boulder1, R0
127            B       BG_SETTHINK
128
129            ENDP
130
131;; ======================================================================== ;;
132;;  BGT_PLANT0: Set horizontal-scroll, and then set ducker as thinker.      ;;
133;; ======================================================================== ;;
134BGT_PLANT0  PROC
135
136            MVII    #BGI.plant1, R0
137            B       BG_SETTHINK
138
139            ENDP
140
141;; ======================================================================== ;;
142;;  BGT_MINE0:  Set horizontal-scroll, and then set blinker as thinker.     ;;
143;; ======================================================================== ;;
144BGT_MINE0   PROC
145
146            ;; ------------------------------------------------------------ ;;
147            ;;  The mines just blink after they've been set h-scroll.       ;;
148            ;; ------------------------------------------------------------ ;;
149            MVII    #BGI.mine1, R0          ;   Get address of main thinker
150;           B       BG_SETTHINK
151            ; XXX: fall through to BG_SETTHINK
152
153            ENDP
154
155
156;; ======================================================================== ;;
157;;  BG_SETTHINK                                                             ;;
158;;  This changes the thinker for the bad-guy in R1.                         ;;
159;;  R3 is expected to point to offset 3 in the BGMPTBL record (the first    ;;
160;;  "status" byte).                                                         ;;
161;; ======================================================================== ;;
162BG_SETTHINK PROC
163            ;; ------------------------------------------------------------ ;;
164            ;;  Set the thinker-pointer for this bad-guy.                   ;;
165            ;; ------------------------------------------------------------ ;;
166            SUBI    #2,     R3              ;   Rewind to program pointer
167@@1:        MVO@    R0,     R3              ;   Set thinker to R0
168            ADDI    #2,     R3              ;   Restore R3
169
170            ;; ------------------------------------------------------------ ;;
171            ;;  Return a delay of 1 + (slot >> 1) for this MOB to stagger   ;;
172            ;;  the thinking out over multiple frames.  This should help    ;;
173            ;;  stagger boulders/mines that cue as a group.                 ;;
174            ;; ------------------------------------------------------------ ;;
175            MOVR    R1,     R0
176            SLR     R0,     1
177            INCR    R0
178
179            B       BGT_RET
180            ENDP
181
182
183;; ======================================================================== ;;
184;;  BGT_MINE1:  Just blink pseudo-randomly.                                 ;;
185;; ======================================================================== ;;
186BGT_MINE1   PROC
187
188            CALL    BGRAND                  ;   random number to R0
189            ADD@    R3,     R0              ;   Get status byte 1
190            MVO@    R0,     R3
191
192
193            SARC    R0
194
195            ; Set Red/White based on lsb of status byte.
196            PSHR    R0                      ;
197
198            MVII    #SPATBL.lmna,   R0
199            BC      @@not1
200            MVII    #SPATBL.lmnb,   R0
201@@not1:
202            MVII    #SPAT,  R2              ;
203            ADDR    R1,     R2              ;
204
205            MVO@    R0,     R2
206
207            PULR    R0
208
209            ; delay randomly from 4 to 11
210            ANDI    #7,     R0
211            ADDI    #4,     R0
212
213            B       BGT_RET
214            ENDP
215
216
217;; ======================================================================== ;;
218;;  BGT_PLANT1:  Just duck pseudo-randomly.                                 ;;
219;; ======================================================================== ;;
220BGT_PLANT1  PROC
221
222            MVII    #SPAT,  R2              ;
223            ADDR    R1,     R2              ;
224            MVI@    R2,     R0
225            CMPI    #SPATBL.plta,   R0
226            BEQ     @@pltb
227            CMPI    #SPATBL.pltb,   R0
228            BEQ     @@plta
229            CMPI    #SPATBL.pltc,   R0
230            BEQ     @@pltd
231@@pltc      MVII    #SPATBL.pltc,   R0
232            B       @@done
233@@pltd      MVII    #SPATBL.pltd,   R0
234            B       @@done
235@@plta      MVII    #SPATBL.plta,   R0
236            B       @@done
237@@pltb      MVII    #SPATBL.pltb,   R0
238@@done:
239
240            MVO@    R0,     R2
241
242            CALL    BGRAND                  ;   random number to R0
243            ADD@    R3,     R0              ;   Get status byte 1
244            MVO@    R0,     R3
245            ; delay randomly from 5 to 12
246            ANDI    #7,     R0
247            ADDI    #5,     R0
248
249            B       BGT_RET
250            ENDP
251
252;; ======================================================================== ;;
253;;  BGT_TURRET1 -- turret firing program                                    ;;
254;; ======================================================================== ;;
255BGT_TURRET1 PROC
256
257            MVI@    R3,     R0
258            TSTR    R0
259            BEQ     @@not_1st
260@@1st       MVII    #15,    R0          ;   First time 'round, wait 16 tics
261            MVO@    R0,     R3          ;   Initialize flag saying "not 1st"
262            B       BGT_RET
263
264@@not_1st:                              ;   2nd and subsequent times,
265            MVI     HBCOL1, R0
266            SLL     R0,     1
267            BEQ     @@ok_fire
268            ADDI    #8,     R0
269
270            MOVR    R1,     R2
271            SLL     R2,     1
272            ADDI    #SPXYP, R2
273
274            MVI@    R2,     R4
275            ANDI    #$FF,   R4
276            CMPR    R0,     R4
277            BLT     @@no_fire           ; don't fire -- bullet too close
278
279
280@@ok_fire   CALL    BGFIRE.c            ;   fire every 45 tics.
281@@no_fire   MVII    #44,    R0
282            B       BGT_RET
283            ENDP
284
285;; ======================================================================== ;;
286;;  BGT_STAL0    -- Stalactite:  Shudder when nearing fall point.           ;;
287;; ======================================================================== ;;
288BGT_STAL0   PROC
289
290            MOVR    R1,     R2
291            SLL     R2,     1
292            ADDI    #SPXYP, R2
293
294            MVI@    R2,     R4
295            SUBI    #16,    R4
296            ANDI    #$FF,   R4
297
298            CLRR    R0
299            CMP@    R3,     R4
300
301            BGT     BGT_RET
302
303            MVII    #SPATBL.stala, R0
304            MVII    #BGI.stal1, R4
305
306@@1:        MVII    #SPAT,  R2
307            ADDR    R1,     R2
308            MVO@    R0,     R2
309
310
311            MOVR    R3,     R2
312            SUBI    #2,     R2
313            MVO@    R4,     R2
314
315            CLRR    R0
316            B       BGT_RET
317
318            ENDP
319
320;; ======================================================================== ;;
321;;  BGT_STAL1    -- Stalactite:  Fall once X gets below state byte 1.       ;;
322;;                  Then go to STAL2, which is for accel and landing.       ;;
323;; ======================================================================== ;;
324BGT_STAL1   PROC
325
326            MOVR    R1,     R2
327            SLL     R2,     1
328            ADDI    #SPXYP, R2
329
330            MVI@    R2,     R4
331            ANDI    #$FF,   R4
332
333            CLRR    R0
334            CMP@    R3,     R4
335
336            BGT     BGT_RET
337
338
339            MVII    #SPATBL.stal, R0
340            MVII    #BGI.stal2, R4
341            B       BGT_STAL0.1
342
343            ENDP
344
345
346;; ======================================================================== ;;
347;;  BGT_STAL2    -- Fall, and then stick in the ground once we get there.   ;;
348;; ======================================================================== ;;
349BGT_STAL2   PROC
350
351            MOVR    R1,         R2          ;
352            SLL     R2,         1           ;
353
354            ADDI    #SPXYP+1,   R2          ; \
355            MVI@    R2,         R0          ;  |_ Are we on the ground yet?
356            SWAP    R0                      ;  |
357            CMPI    #$4500,     R0          ; /
358            BGE     @@hit
359
360            ADDI    #SPXYV-SPXYP,R2         ;
361            MVI@    R2,         R4          ; \
362            ADDI    #$4000,     R4          ;  |_ accelerate by $00.40
363            ADCR    R4                      ;  |
364            MVO@    R4,         R2          ; /
365
366            CLRR    R0
367            B       BGT_RET
368
369@@hit
370            MVII    #$4A,       R0          ; \_ stick in the ground
371            MVO@    R0,         R2          ; /
372            ADDI    #SPXYV-SPXYP,R2         ;
373            CLRR    R0                      ; \_ zero out our velocity
374            MVO@    R0,         R2          ; /
375            MVII    #SPAT,      R2          ;
376            ADDR    R1,         R2          ;
377
378            MVII    #SPATBL.stalf, R0       ; \_ Set prio so we're behind
379            MVO@    R0,         R2          ; /  the ground
380
381;           PSHR    R1
382            CALL    PLAYSFX
383            DECLE   FXSMEXP
384;           PULR    R1
385
386            MVII    #BGI.null, R0
387            B       BG_SETTHINK
388            ENDP
389
390;; ======================================================================== ;;
391;;  See 'bgsaucer.asm' for the Pink/Blue/White saucer motion programs.      ;;
392;; ======================================================================== ;;
393