1 /* 2 swcollsn - SW collision resolution 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-02-02 Development 19 84-06-12 PCjr Speed-up 20 84-10-31 Atari 21 87-03-09 Microsoft compiler. 22 87-03-11 No explosion on bird-plane collision 23 87-03-12 Wounded airplanes. 24 87-03-12 More than 1 bullet to kill target. 25 87-03-13 Splatted bird symbol. 26 87-03-31 Missiles. 27 87-04-05 Missile and starburst support 28 2003-01-27 GNU General Public License 29 */ 30 #include "sw.h" 31 32 33 extern OBJECTS topobj, botobj; 34 extern OBJECTS oobjects[]; /* Original plane object description*/ 35 extern OBJECTS *nobjects; /* Objects list. */ 36 extern GRNDTYPE ground[]; /* Ground height by pixel */ 37 extern GRNDTYPE orground[]; /* Original ground height by pixel */ 38 extern int playmode; 39 extern int player; 40 extern int shothole; /* Number of window shots to dislay */ 41 extern int splatbird; /* Number of splatted birds */ 42 extern int splatox; /* Display a splatted OX */ 43 extern int numtarg[]; /* Number of active targets */ 44 extern MULTIO *multbuff; 45 extern int gamenum; /* Current game number */ 46 extern int endsts[]; /* End of game status and move count*/ 47 extern int forcdisp; /* Force display of ground */ 48 extern int gmaxspeed,gminspeed; /* Speed range based on game number */ 49 extern int counttick, countmove; /* Performance counters */ 50 51 static OBJECTS *killed[MAX_OBJS << 1], 52 *killer[MAX_OBJS << 1]; 53 static int killptr; 54 55 static int collsdx[MAX_PLYR]; 56 static int collsdy[MAX_PLYR]; 57 static OBJECTS *collsno[MAX_PLYR]; 58 static int collptr; 59 static int collxadj, collyadj; 60 61 62 63 swcollsn() 64 { 65 register OBJECTS *ob, *obp, **obkd, **obkr; 66 register int xmax, ymin, ymax, otype, i; 67 int prevx1, prevx2; 68 69 collptr = killptr = 0; 70 collxadj = 2; 71 collyadj = 1; 72 if ( countmove & 1 ) { 73 collxadj = -collxadj; 74 collyadj = -collyadj; 75 } 76 setadisp(); 77 prevx1 = topobj.ob_x; 78 for ( ob = topobj.ob_xnext; ob != &botobj; ob = ob->ob_xnext ) { 79 prevx2 = prevx1 = ob->ob_x; 80 81 xmax = ob->ob_x + ob->ob_symwdt - 1; 82 ymin = ( ymax = ob->ob_y ) - ob->ob_symhgt + 1; 83 84 for ( obp = ob->ob_xnext; 85 ( obp != &botobj ) && ( obp->ob_x <= xmax ); 86 obp = obp->ob_xnext ) { 87 prevx2 = obp->ob_x; 88 89 if ( ( obp->ob_y >= ymin ) 90 && ( ( obp->ob_y - obp->ob_symhgt + 1 ) <= ymax ) ) 91 colltest( ob, obp ); 92 } 93 94 if ( ( ( ( otype = ob->ob_type ) == PLANE ) 95 && ( ob->ob_state != FINISHED ) 96 && ( ob->ob_state != WAITING ) 97 && ( ob->ob_y < ( ground[ob->ob_x + 8] + 24 ) ) ) 98 || ( ( ( otype == BOMB ) || ( otype == MISSILE ) ) 99 && ( ob->ob_y < ( ground[ob->ob_x + 4] + 12 ) ) ) ) 100 tstcrash( ob ); 101 } 102 103 obkd = killed; 104 obkr = killer; 105 for ( i = 0; i < killptr; ++i, ++obkd, ++obkr ) 106 kill( *obkd, *obkr ); 107 108 obkd = collsno; 109 for ( i = 0; i < collptr; ++i, ++obkd ) { 110 ( ob = *obkd )->ob_dx = collsdx[i]; 111 ob->ob_dy = collsdy[i]; 112 } 113 } 114 115 116 117 118 colltest( ob1, ob2 ) 119 OBJECTS *ob1, *ob2; 120 { 121 register OBJECTS *obt, *ob, *obp; 122 register int otype, ttype; 123 124 ob = ob1; 125 obp = ob2; 126 otype = ob->ob_type; 127 ttype = obp->ob_type; 128 if ( ( ( otype == PLANE ) && ( ob->ob_state >= FINISHED ) ) 129 || ( ( ttype == PLANE ) && ( obp->ob_state >= FINISHED ) ) 130 || ( ( otype == EXPLOSION ) && ( ttype == EXPLOSION ) ) ) 131 return; 132 133 if ( ob->ob_y < obp->ob_y ) { 134 obt = ob; 135 ob = obp; 136 obp = obt; 137 } 138 139 swputsym( 15, 15, ob ); 140 if ( swputcol( obp->ob_x - ob->ob_x + 15, 141 obp->ob_y - ob->ob_y + 15, 142 obp ) ) 143 if ( killptr < ( ( MAX_OBJS << 1 ) - 1 ) ) { 144 killed[killptr] = ob; 145 killer[killptr++] = obp; 146 killed[killptr] = obp; 147 killer[killptr++] = ob; 148 } 149 swclrcol(); 150 } 151 152 153 154 tstcrash( obp ) 155 OBJECTS *obp; 156 { 157 register OBJECTS *ob; 158 register int x, xmax, y; 159 register BOOL hit = FALSE; 160 161 ob = obp; 162 swputsym( 15, 15, ob ); 163 164 xmax = ob->ob_x + ob->ob_symwdt - 1; 165 for ( x = ob->ob_x; x <= xmax; ++x ) { 166 if ( ( y = (int) ground[x] - ob->ob_y + 15 ) > 15 ) { 167 hit = TRUE; 168 break; 169 } 170 if ( y < 0 ) 171 continue; 172 if ( hit = swpntcol( x - ob->ob_x + 15, y, 0x80 ) ) 173 break; 174 } 175 swclrcol(); 176 177 if ( ( hit ) && ( killptr < ( MAX_OBJS << 1 ) ) ){ 178 killed[killptr] = ob; 179 killer[killptr++] = NULL; 180 } 181 } 182 183 184 185 kill( ob1, ob2 ) 186 OBJECTS *ob1, *ob2; 187 { 188 register OBJECTS *ob, *obt; 189 register int state, ttype, i; 190 191 ob = ob1; 192 obt = ob2; 193 ttype = obt ? obt->ob_type : GROUND; 194 if ( ( ( ttype == BIRD ) || ( ttype == FLOCK ) ) 195 && ( ob->ob_type != PLANE ) ) 196 return; 197 198 switch ( ob->ob_type ) { 199 200 case BOMB: 201 case MISSILE: 202 initexpl( ob, 0 ); 203 ob->ob_life = -1; 204 if ( !obt ) 205 crater( ob ); 206 stopsound( ob ); 207 return; 208 209 case SHOT: 210 ob->ob_life = 1; 211 return; 212 213 case STARBURST: 214 if ( ( ttype == MISSILE ) || ( ttype == BOMB ) || !obt ) 215 ob->ob_life = 1; 216 return; 217 218 case EXPLOSION: 219 if ( !obt ) { 220 ob->ob_life = 1; 221 stopsound( ob ); 222 } 223 return; 224 225 case TARGET: 226 if ( ob->ob_state != STANDING ) 227 return; 228 if ( ( ttype == EXPLOSION ) || ( ttype == STARBURST ) ) 229 return; 230 231 if ( ( ttype == SHOT ) 232 && ( ( ob->ob_hitcount += TARGHITCOUNT ) 233 <= ( TARGHITCOUNT * ( gamenum + 1 ) ) ) ) 234 return; 235 236 ob->ob_state = FINISHED; 237 initexpl( ob, 0 ); 238 239 setvdisp(); 240 dispwobj( ob ); 241 setadisp(); 242 243 scoretarg( ob, ( ob->ob_orient == 2 ) ? 200 : 100 ); 244 if ( !--numtarg[ob->ob_clr - 1] ) 245 endgame( ob->ob_clr ); 246 return; 247 248 case PLANE: 249 if ( ( ( state = ob->ob_state ) == CRASHED ) 250 || ( state == GHOSTCRASHED ) ) 251 return; 252 253 if ( endsts[ob->ob_index] == WINNER ) 254 return; 255 256 if ( ( ttype == STARBURST ) 257 || ( ( ttype == BIRD ) && ob->ob_athome ) ) 258 return; 259 260 if ( !obt ) { 261 if ( state == FALLING ) { 262 stopsound( ob ); 263 initexpl( ob, 1 ); 264 crater( ob ); 265 } else 266 if ( state < FINISHED ) { 267 scorepln( ob ); 268 initexpl( ob, 1 ); 269 crater( ob ); 270 } 271 272 crashpln( ob ); 273 return; 274 } 275 276 if ( state >= FINISHED ) 277 return; 278 279 if ( state == FALLING ) { 280 if ( ob->ob_index == player ) 281 if ( ttype == SHOT ) 282 ++shothole; 283 else if ( ( ttype == BIRD ) 284 || ( ttype == FLOCK ) ) 285 ++splatbird; 286 return; 287 } 288 289 if ( ( ttype == SHOT ) || ( ttype == BIRD ) 290 || ( ttype == OX ) || ( ttype == FLOCK ) ) { 291 if ( ob->ob_index == player ) 292 if ( ttype == SHOT ) 293 ++shothole; 294 else if ( ttype == OX ) 295 ++splatox; 296 else 297 ++splatbird; 298 if ( state == FLYING ) { 299 ob->ob_state = WOUNDED; 300 return; 301 } 302 if ( state == STALLED ) { 303 ob->ob_state = WOUNDSTALL; 304 return; 305 } 306 } else { 307 initexpl( ob, 1 ); 308 if ( ttype == PLANE ) { 309 collsdx[collptr] 310 = ( ( ob->ob_dx + obt->ob_dx ) >> 1) 311 + ( collxadj = -collxadj ); 312 collsdy[collptr] 313 = ( ( ob->ob_dy + obt->ob_dy ) >> 1) 314 + ( collyadj = -collyadj ); 315 collsno[collptr++] = ob; 316 } 317 } 318 319 hitpln( ob ); 320 scorepln( ob ); 321 return; 322 323 case BIRD: 324 ob->ob_life = scorepenalty( ttype, obt, 25 ) ? -1 : -2; 325 return; 326 327 case FLOCK: 328 if ( ( ttype != FLOCK ) && ( ttype != BIRD ) 329 && ( ob->ob_state == FLYING ) ) { 330 for ( i = 0; i < 8; ++i ) 331 initbird( ob, i ); 332 ob->ob_life = -1; 333 ob->ob_state = FINISHED; 334 } 335 return; 336 337 case OX: 338 if ( ob->ob_state != STANDING ) 339 return; 340 if ( ( ttype == EXPLOSION ) || ( ttype == STARBURST ) ) 341 return; 342 scorepenalty( ttype, obt, 200 ); 343 ob->ob_state = FINISHED; 344 return; 345 } 346 } 347 348 349 350 static scorepenalty( ttype, ob, score ) 351 int ttype; 352 OBJECTS *ob; 353 int score; 354 { 355 register OBJECTS *obt; 356 357 obt = ob; 358 if ( ( ttype == SHOT ) || ( ttype == BOMB ) || ( ttype == MISSILE ) 359 || ( ( ttype == PLANE ) 360 && ( ( obt->ob_state == FLYING ) 361 || ( obt->ob_state == WOUNDED ) 362 || ( ( obt->ob_state == FALLING ) 363 && ( obt->ob_hitcount == FALLCOUNT ) ) ) 364 && ( !obt->ob_athome ) ) ) { 365 scoretarg( obt, score ); 366 return( TRUE ); 367 } 368 return( FALSE ); 369 } 370 371 372 373 374 static scoretarg( obp, score ) 375 OBJECTS *obp; 376 int score; 377 { 378 register OBJECTS *ob; 379 380 ob = obp; 381 if ( ( ( playmode != MULTIPLE ) && ( playmode != ASYNCH ) ) 382 || ( multbuff->mu_maxplyr == 1 ) ) { 383 if ( ob->ob_clr == 1 ) 384 nobjects[0].ob_score -= score; 385 else 386 nobjects[0].ob_score += score; 387 dispscore( &nobjects[0] ); 388 } else { 389 nobjects[2 - ob->ob_clr].ob_score += score; 390 dispscore( &nobjects[2 - ob->ob_clr] ); 391 } 392 } 393 394 395 396 397 398 scorepln( ob ) 399 OBJECTS *ob; 400 { 401 402 scoretarg( ob, 50 ); 403 } 404 405 406 407 408 dispscore( obp ) 409 OBJECTS *obp; 410 { 411 register OBJECTS *ob; 412 413 swposcur( ( ( ob = obp )->ob_clr - 1 ) * 7 + 2, 24 ); 414 swcolour( ob->ob_clr ); 415 dispd( ob->ob_score, 6 ); 416 } 417 418 419 420 421 dispd( n, size ) 422 int n, size; 423 { 424 register int i = 0; 425 register int d, t; 426 register BOOL first = TRUE; 427 428 if ( n < 0 ) { 429 n = -n; 430 swputc( '-' ); 431 ++i; 432 } 433 for ( t = 10000; t > 1; n %= t, t /= 10 ) 434 if ( ( d = n / t ) || ( !first ) ){ 435 first = FALSE; 436 swputc( d + '0' ); 437 ++i; 438 } 439 swputc( n + '0' ); 440 ++i; 441 while( ++i <= size ) 442 swputc( ' ' ); 443 } 444 445 446 447 448 449 450 static crtdepth[8] = { 1, 2, 2, 3, 3, 2, 2, 1 }; 451 452 static crater( ob ) 453 OBJECTS *ob; 454 { 455 register int i, x, y, ymin, ymax; 456 int xmin, xmax; 457 458 xmin = ob->ob_x + ( ob->ob_symwdt - 8 ) / 2; 459 xmax = xmin + 7; 460 461 for ( x = xmin, i = 0; x <= xmax; ++x, ++i ) { 462 ymax = ground[x]; 463 if ( ( y = orground[x] - 20 ) < 20 ) 464 y = 20; 465 if ( ( ymin = ymax - crtdepth[i] + 1 ) <= y ) 466 ymin = y + 1; 467 ground[x] = ymin - 1; 468 } 469 forcdisp = TRUE; 470 } 471 472 473 474 475 equal( x, y ) 476 int ( *x )(), ( *y )(); 477 { 478 return ( x == y ); 479 } 480 ÿ