1 /* 2 swauto - SW control of computer player 3 4 Copyright (C) 1984-2003 David L. Clark. 5 This program is free software; you can redistribute it and/or modify it under 6 the terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 2 of the License, or (at your option) any later 8 version. This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 10 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 more details. You should have received a copy of the GNU General Public 12 License along with this program; if not, write to the Free Software Foundation, 13 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 14 15 Author: Dave Clark 16 17 Modification History: 18 84-03-05 Development 19 84-06-12 PCjr Speed-up 20 84-10-31 Atari 21 87-03-09 Microsoft compiler. 22 87-03-12 Wounded airplanes. 23 87-03-12 Smarter shooting. 24 87-03-31 Missiles. 25 87-04-05 Missile and starburst support 26 87-04-06 Computer plane avoiding oxen. 27 87-04-09 Don't attack until closer. 28 2003-01-27 GNU General Public License 29 */ 30 #include "sw.h" 31 32 extern int sintab[]; /* sine table based on angles */ 33 extern GRNDTYPE ground[]; /* Ground height by pixel */ 34 extern GRNDTYPE orground[]; /* Minimum ground height in craters */ 35 extern OBJECTS *nobjects; /* Objects list. */ 36 extern OBJECTS oobjects[]; /* Original plane object description*/ 37 extern OBJECTS *compnear[]; /* Array of planes near computers */ 38 extern OBJECTS *targets[]; /* Target status array */ 39 extern int lcompter[]; /* Computer plane territory */ 40 extern int rcompter[]; /* Computer plane territory */ 41 extern OBJECTS topobj, botobj; 42 extern int dispcomp(), dispplyr(); 43 extern int keydelay; /* Number of displays per keystr */ 44 extern int playmode; /* Play mode */ 45 extern BOOL goingsun; /* Heading for the sun flag */ 46 extern int endcount; 47 extern int gmaxspeed,gminspeed; /* Speed range based on game number */ 48 extern BOOL compplane; /* Moving computer plane flag */ 49 extern BOOL plyrplane; /* Moving player plane flag */ 50 extern int currobx; /* Current object index */ 51 extern int counttick, countmove; /* Performance counters */ 52 53 54 static BOOL correction; /* Course correction flag */ 55 static BOOL goinghome; /* Going home flag */ 56 static OBJECTS obs; /* Saved computer object */ 57 static int courseadj; /* Course adjustment */ 58 59 60 61 62 swauto( ob ) 63 OBJECTS *ob; 64 { 65 register OBJECTS *obt; 66 67 goinghome = FALSE; 68 69 if ( obt = compnear[currobx] ) 70 attack( ob, obt ); 71 else 72 if ( !ob->ob_athome ) 73 cruise( ob ); 74 75 compnear[currobx] = NULL; 76 } 77 78 79 80 81 82 attack( obp, obt ) 83 OBJECTS *obp, *obt; 84 { 85 register OBJECTS *ob; 86 87 courseadj = ( ( countmove & 0x001F ) < 16 ) << 4; 88 ob = obt; 89 if ( ob->ob_speed ) 90 aim( obp, 91 ob->ob_x - ( ( CLOSE * COS( ob->ob_angle ) ) >> 8 ), 92 ob->ob_y - ( ( CLOSE * SIN( ob->ob_angle ) ) >> 8 ), 93 ob, NO ); 94 else 95 aim( obp, ob->ob_x, ob->ob_y + 4, ob, NO ); 96 } 97 98 99 100 101 static cruise( ob ) 102 OBJECTS *ob; 103 { 104 register int orgx; 105 106 courseadj = ( ( countmove & 0x001F ) < 16 ) << 4; 107 orgx = oobjects[currobx].ob_x; 108 aim( ob, ( ( orgx < ( MAX_X / 3 ) ) 109 ? ( MAX_X / 3 ) 110 : ( ( orgx > ( 2 * MAX_X / 3 ) ) 111 ? ( 2 * MAX_X / 3 ) 112 : orgx ) ) + courseadj, 113 MAX_Y - 50 - ( courseadj >> 1 ), 114 NULL, NO ); 115 } 116 117 118 119 120 gohome( obpt ) 121 OBJECTS *obpt; 122 { 123 register OBJECTS *ob, *obp; 124 125 if ( ( obp = obpt )->ob_athome ) 126 return( 0 ); 127 128 ob = &oobjects[currobx]; 129 130 courseadj = ( ( countmove & 0x001F ) < 16 ) << 4; 131 if ( ( abs( obp->ob_x - ob->ob_x ) < HOME ) 132 && ( abs( obp->ob_y - ob->ob_y ) < HOME ) ) { 133 if ( plyrplane ) { 134 initplyr( obp ); 135 initdisp( YES ); 136 } else 137 if ( compplane ) 138 initcomp( obp ); 139 else 140 initpln( obp ); 141 return( 0 ); 142 } 143 goinghome = TRUE; 144 return( aim( obp, ob->ob_x, ob->ob_y, NULL, NO ) ); 145 } 146 147 148 149 150 151 shoot( obt ) 152 OBJECTS *obt; 153 { 154 static OBJECTS obsp, obtsp; 155 int obx, oby, obtx, obty; 156 int nspeed, nangle; 157 int rprev; 158 register int r, i; 159 160 161 movmem( &obs, &obsp, sizeof( OBJECTS ) ); 162 movmem( obt, &obtsp, sizeof( OBJECTS ) ); 163 nspeed = obsp.ob_speed + BULSPEED; 164 setdxdy( &obsp, nspeed * COS( obsp.ob_angle ), 165 nspeed * SIN( obsp.ob_angle ) ); 166 obsp.ob_x += SYM_WDTH / 2; 167 obsp.ob_y -= SYM_HGHT / 2; 168 169 nangle = obtsp.ob_angle; 170 nspeed = obtsp.ob_speed; 171 rprev = NEAR; 172 for ( i = 0; i < BULLIFE; ++i ) { 173 movexy( &obsp, &obx, &oby ); 174 if ( ( ( obtsp.ob_state == FLYING ) 175 || ( obtsp.ob_state == WOUNDED ) ) 176 && ( r = obtsp.ob_flaps ) ) { 177 if ( obtsp.ob_orient ) 178 nangle -= r; 179 else 180 nangle += r; 181 nangle = ( nangle + ANGLES ) % ANGLES; 182 setdxdy( &obtsp, nspeed * COS( nangle ), 183 nspeed * SIN( nangle ) ); 184 } 185 movexy( &obtsp, &obtx, &obty ); 186 r = range( obx, oby, obtx, obty ); 187 if ( ( r < 0 ) || ( r > rprev ) ) 188 return( 0 ); 189 if ( ( obx >= obtx ) 190 && ( obx <= ( obtx + SYM_WDTH - 1 ) ) 191 && ( oby <= obty ) 192 && ( oby >= ( obty - SYM_HGHT + 1 ) ) ) 193 return( 1 + ( i > ( BULLIFE / 3 ) ) ); 194 195 } 196 return( 0 ); 197 } 198 199 200 201 202 abs( x ) 203 int x; 204 { 205 return( ( x < 0 ) ? -x : x ); 206 } 207 208 209 210 211 212 213 214 aim( obo, ax, ay, obt, longway ) 215 OBJECTS *obo, *obt; 216 int ax, ay; 217 BOOL longway; 218 { 219 register OBJECTS *ob, *obp; 220 register int r, rmin, i, n; 221 int x, y, dx, dy, nx, ny; 222 int nangle, nspeed; 223 static int cflaps[3] = { 0, -1, 1 }; 224 static int crange[3],ccrash[3], calt[3]; 225 226 ob = obo; 227 228 correction = FALSE; 229 230 if ( ( ( ob->ob_state == STALLED ) || ( ob->ob_state == WOUNDSTALL ) ) 231 && ( ob->ob_angle != ( 3*ANGLES/4 ))){ 232 ob->ob_flaps = -1; 233 ob->ob_accel = MAX_THROTTLE; 234 return; 235 } 236 237 x = ob->ob_x; 238 y = ob->ob_y; 239 if ( abs( dx = x - ax ) > 160 ) { 240 if ( ob->ob_dx && ( ( dx < 0 ) == ( ob->ob_dx < 0 ) ) ) { 241 if ( !ob->ob_hitcount ) 242 ob->ob_hitcount = 1 + ( y > ( MAX_Y - 50 ) ); 243 return( aim( ob, x, ( ob->ob_hitcount == 1 ) 244 ? ( y + 25 ) : ( y - 25 ), NULL, YES ) ); 245 } 246 ob->ob_hitcount = 0; 247 return( aim( ob, x + ( ( dx < 0 ) ? 150 : -150 ), 248 ( ( ( y += 100 ) > ( MAX_Y - 50 - courseadj ) ) 249 ? ( MAX_Y - 50 - courseadj ) : y ), NULL, YES ) ); 250 } else 251 if ( !longway ) 252 ob->ob_hitcount = 0; 253 254 if ( ob->ob_speed ) 255 if ( correction = ( dy = y - ay ) && ( abs( dy ) < 6 ) ) 256 ob->ob_y = ( dy < 0 ) ? ++y : --y; 257 else 258 if ( correction = dx && ( abs( dx ) < 6 ) ) 259 ob->ob_x = ( dx < 0 ) ? ++x : --x; 260 261 movmem( ob, &obs, sizeof( OBJECTS ) ); 262 if ( ( ( nspeed = obs.ob_speed + 1 ) > gmaxspeed ) 263 && ( obs.ob_type == PLANE ) ) 264 nspeed = gmaxspeed; 265 else 266 if ( nspeed < gminspeed ) 267 nspeed = gminspeed; 268 269 cleartargs(); 270 for ( i = 0; i < 3; ++i ) { 271 nangle = ( obs.ob_angle 272 + ( obs.ob_orient ? -( cflaps[i] ) : cflaps[i] ) 273 + ANGLES ) % ANGLES; 274 setdxdy( &obs, nspeed * COS( nangle ), nspeed * SIN( nangle ) ); 275 movexy( &obs, &nx, &ny ); 276 crange[i] = range( nx, ny, ax, ay ); 277 calt[i] = ny - orground[nx + 8]; 278 ccrash[i] = tstcrash( ob, nx, ny, calt[i] ); 279 movmem( ob, &obs, sizeof( OBJECTS ) ); 280 } 281 282 283 if ( obt && ( i = shoot( obt ) ) ) 284 if ( ob->ob_missiles && ( i == 2 ) ) 285 ob->ob_mfiring = obt->ob_athome ? ob : obt; 286 else 287 ob->ob_firing = obt; 288 289 rmin = 32767; 290 for ( i = 0; i < 3; ++i ) 291 if ( ( ( r = crange[i] ) >= 0 ) 292 && ( r < rmin ) 293 && !ccrash[i] ) { 294 rmin = r; 295 n = i; 296 } 297 if ( rmin == 32767 ) { 298 rmin = -32767; 299 for ( i = 0; i < 3; ++i ) 300 if ( ( ( r = crange[i] ) < 0 ) 301 && ( r > rmin ) 302 && !ccrash[i] ) { 303 rmin = r; 304 n = i; 305 } 306 } 307 308 if ( ob->ob_speed < gminspeed ) 309 ob->ob_accel = MAX_THROTTLE; 310 311 if ( rmin != -32767 ) { 312 if ( ob->ob_accel < MAX_THROTTLE ) 313 ++ob->ob_accel; 314 } else { 315 if ( ob->ob_accel ) 316 --ob->ob_accel; 317 318 n = 0; 319 if ( calt[1] > ( dy = calt[0] ) ) { 320 dy = calt[1]; 321 n = 1; 322 } 323 if ( calt[2] > dy ) 324 n = 2; 325 } 326 327 ob->ob_flaps = cflaps[n]; 328 if ( ( ob->ob_type == PLANE ) && !ob->ob_flaps ) 329 if ( ob->ob_speed ) 330 ob->ob_orient = ( ob->ob_dx < 0 ); 331 332 } 333 334 335 336 static int tl, tr; 337 338 339 340 static cleartargs() 341 { 342 tl = -2; 343 } 344 345 346 347 static testtargs( x, y ) 348 int x, y; 349 { 350 register int i, xl, xr; 351 352 xl = x - 32 - gmaxspeed; 353 xr = x + 32 + gmaxspeed; 354 355 tl = -1; 356 tr = 0; 357 for ( i = 0; i < ( MAX_TARG + MAX_OXEN ); ++i ) 358 if ( targets[i] && ( targets[i]->ob_x >= xl ) ) { 359 tl = i; 360 break; 361 } 362 363 if ( tl == -1 ) 364 return; 365 366 for ( ; ( i < ( MAX_TARG + MAX_OXEN ) ) && targets[i] 367 && ( targets[i]->ob_x < xr ); ++i ); 368 tr = i - 1; 369 } 370 371 372 373 374 static tstcrash( obp, x, y, alt ) 375 int x, y, alt; 376 OBJECTS *obp; 377 { 378 register OBJECTS *ob; 379 register int i, xl, xr, xt, yt; 380 381 if ( alt > 50 ) 382 return( FALSE ); 383 384 if ( alt < 22 ) 385 return( TRUE ); 386 387 ob = obp; 388 if ( tl == -2 ) 389 testtargs( ob->ob_x, ob->ob_y ); 390 391 xl = x - 32; 392 xr = x + 32; 393 394 for ( i = tl; i <= tr; ++i ) { 395 if ( ( xt = ( ob = targets[i] )->ob_x ) < xl ) 396 continue; 397 if ( xt > xr ) 398 return( FALSE ); 399 yt = ob->ob_y + ( ob->ob_state == STANDING ? 16 : 8 ); 400 if ( y <= yt ) 401 return( TRUE ); 402 } 403 return( FALSE ); 404 } 405 406 407 408 409 410 range( x, y, ax, ay ) 411 int x, y, ax, ay; 412 { 413 register int dx, dy; 414 register int t; 415 416 dy = abs( y - ay ); 417 dy += dy >> 1; 418 if ( ( ( dx = abs( x - ax ) ) < 125 ) && ( dy < 125 ) ) 419 return ( dx * dx + dy * dy ); 420 421 if ( dx < dy ) { 422 t = dx; 423 dx = dy; 424 dy = t; 425 } 426 427 return( - ( ( ( 7 * dx ) + ( dy << 2 ) ) >> 3 ) ); 428 } 429 ÿ