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