Home | History | Annotate | Line # | Download | only in warp
      1 /* Header: weapon.c,v 7.0.1.2 86/10/20 14:36:33 lwall Exp */
      2 
      3 /* Log:	weapon.c,v
      4  * Revision 7.0.1.2  86/10/20  14:36:33  lwall
      5  * Picked some lint.
      6  *
      7  * Revision 7.0.1.1  86/10/16  10:54:42  lwall
      8  * Added Damage.  Fixed random bugs.
      9  *
     10  * Revision 7.0  86/10/08  15:18:08  lwall
     11  * Split into separate files.  Added amoebas and pirates.
     12  *
     13  */
     14 
     15 #include "EXTERN.h"
     16 #include "warp.h"
     17 #include "bang.h"
     18 #include "object.h"
     19 #include "move.h"
     20 #include "score.h"
     21 #include "sig.h"
     22 #include "term.h"
     23 #include "them.h"
     24 #include "us.h"
     25 #include "util.h"
     26 #include "INTERN.h"
     27 #include "weapon.h"
     28 
     29 void
     30 weapon_init(void)
     31 {
     32     ;
     33 }
     34 
     35 void
     36 fire_torp(OBJECT *from, int ydir, int xdir)
     37 {
     38     OBJECT *to;
     39 
     40     if (from->type == Enemy ||
     41        (from == ent && etorp > 0) ||
     42        (from == base && btorp > 0)) {
     43 	to = occupant[(from->posy+from->vely+ydir+YSIZE00)%YSIZE]
     44 		     [(from->posx+from->velx+xdir+XSIZE00)%XSIZE];
     45 	if (from->type != Enemy || !to || to->vely || to->velx) {
     46 	    if (from->type != Enemy &&
     47 		 (to = isatorp[from==base][ydir+1][xdir+1])) {
     48 		to->vely += ydir;
     49 		to->velx += xdir;
     50 	    }
     51 	    else {
     52 		if (from == ent) {
     53 		    to = make_object(Torp, '+', from->posy,from->posx,
     54 			from->vely+ydir,from->velx+xdir, 0L, 1L,&root);
     55 		    aretorps++;
     56 		    isatorp[0][ydir+1][xdir+1] = to;
     57 		    etorp--;
     58 		}
     59 		else if (from == base) {
     60 		    to = make_object(Torp, '+', from->posy,from->posx,
     61 			from->vely+ydir,from->velx+xdir, 0L, 1L,&root);
     62 		    aretorps++;
     63 		    isatorp[1][ydir+1][xdir+1] = to;
     64 		    btorp--;
     65 		}
     66 		else if (from->image == 'G') {
     67 		    numos++;
     68 		    to = make_object(Torp, 'o', from->posy,from->posx,
     69 			from->vely+ydir,from->velx+xdir, 100L, 1L,&root);
     70 		    if (madgorns) {
     71 			possiblescore += 35;
     72 			to->image = '0';
     73 			to->mass = 2000;
     74 			to->energy = 2000;
     75 		    }
     76 		    else if (rand_mod(120)+10 > smarts)
     77 			possiblescore += 100;
     78 		    else {
     79 			possiblescore += 200;
     80 			to->image = 'O';
     81 		    }
     82 		}
     83 		else {
     84 		    to = make_object(Torp, 'x', from->posy,from->posx,
     85 			from->vely+ydir,from->velx+xdir, 0L, 1L,&root);
     86 		    if (rand_mod(160)+10 > smarts)
     87 			possiblescore += 10;
     88 		    else {
     89 			possiblescore += 100;
     90 			to->image = 'X';
     91 			to->mass = 1000+super*20;
     92 			numxes++;
     93 		    }
     94 		}
     95 	    }
     96 	}
     97     }
     98 }
     99 
    100 void
    101 attack(OBJECT *attackee)
    102 {
    103     int dx;
    104     int dy;
    105     int curx;
    106     int cury;
    107     int prob;
    108     OBJECT *obj;
    109     bool torps;
    110     bool webnear = false;
    111     bool thru_stars;
    112     int nukey;
    113     int nukex;
    114     int nukedist;
    115 
    116     if (attackee) {
    117 	if (attackee == nuke) {
    118 	    if (amb[attackee->posy][attackee->posx] != '~')
    119 		return;
    120 	    nukey = nukex = 0;
    121 	    nukedist = 100;
    122 	}
    123 	for (dx= -1; dx<=1 ; dx++) {
    124 	    for (dy= -1; dy<=1; dy++) {
    125 		if (dx||dy) {
    126 		    cury = attackee->posy;
    127 		    curx = attackee->posx;
    128 		    torps = thru_stars = false;
    129 		    if (massacre || madgorns || !rand_mod(53-super) )
    130 			webnear += rand_mod(2);
    131 		    else
    132 			webnear = false;
    133 		    for (prob = scandist;prob;prob--) {
    134 			cury = (cury + dy + YSIZE00) % YSIZE;
    135 			curx = (curx + dx + XSIZE00) % XSIZE;
    136 			if ((obj = occupant[cury][curx]) != NULL) {
    137 			    switch (obj->image) {
    138 			    case 'P': case 'K': case 'R': case ' ':
    139 		pot_shot:
    140 				if (attackee == nuke) {
    141 				    if (rand_mod(2+scandist-prob) <
    142 				      rand_mod(smarts/40+1))
    143 					tract(nuke,dy,dx,rand_mod(3)?1:-1);
    144 				}
    145 				if (rand_mod(51 - sm50) <= prob) {
    146 				    switch (obj->strategy||thru_stars?0:
    147 					  rand_mod(ent?4:2)) {
    148 				    case 1: case 2:
    149 					if (-dy + attackee->vely == obj->vely
    150 					 && -dx + attackee->velx == obj->velx)
    151 					    fire_torp(obj,
    152 					     -dy + attackee->vely,
    153 					     -dx + attackee->velx);
    154 					else
    155 					    fire_torp(obj,
    156 					     -dy + attackee->vely - obj->vely,
    157 					     -dx + attackee->velx - obj->velx);
    158 					if (obj->image == ' ')
    159 					    setimage(obj,
    160 					      obj->flags & PIRATE ? 'P' : 'R');
    161 					break;
    162 				    case 3: {
    163 					int newspeed =
    164 					    rand_mod(prob<5&&smarts>70?4:3)-1;
    165 
    166 					obj->vely = -dy * newspeed;
    167 					obj->velx = -dx * newspeed;
    168 					if (newspeed >= 0 &&
    169 					    !rand_mod(82-sm80)) {
    170 					    obj->vely += attackee->vely;
    171 					    obj->velx += attackee->velx;
    172 					}
    173 					break;
    174 				    }
    175 				    case 0:
    176 					if (!torps && obj->energy > 1000) {
    177 					    fire_phaser(obj, -dy, -dx);
    178 					    if (smarts > 40 &&
    179 					       (scandist-prob > 5
    180 						|| attackee==base) &&
    181 					       (massacre || obj->strategy ||
    182 					        rand_mod(2)))
    183 						while (rand_mod(2))
    184 						    fire_phaser(obj, -dy, -dx);
    185 					    if (obj->image == ' ')
    186 						setimage(obj,
    187 						  obj->flags&PIRATE ? 'P':'R');
    188 					}
    189 					if (obj->strategy) {
    190 					    obj->velx = obj->vely = 0;
    191 					    if (obj->energy < 1000 ||
    192 						  bvely || bvelx)
    193 						obj->strategy = 0;
    194 					}
    195 					else if ((attackee==base ||
    196 						  (cloaking && attackee==ent)
    197 						 ) &&
    198 						 scandist-prob > 5 &&
    199 					         !(rand_mod(
    200 						   ent?antibase*2:antibase)) )
    201 					    obj->strategy = 1;
    202 					break;
    203 				    }
    204 				}
    205 				goto bombout;
    206 			    case 'G':
    207 				if (thru_stars && obj->strategy < 7)
    208 				    goto bombout;
    209 				if (attackee == nuke) {
    210 				    if (rand_mod(2+scandist-prob) <
    211 				      rand_mod(smarts/40+1))
    212 					tract(nuke,dy,dx,rand_mod(3)?1:-1);
    213 				    goto bombout;
    214 				}
    215 				if (obj->strategy) {
    216 				    if (madgorns || !rand_mod(4)) {
    217 					obj->vely = attackee->vely;
    218 					obj->velx = attackee->velx;
    219 				    }
    220 				    obj->strategy += (!torps && deados > 10);
    221 				    if (obj->strategy > 4)
    222 					madgorns = true;
    223 				    if (!torps && obj->strategy > 5) {
    224 					do {
    225 					    fire_phaser(obj, -dy, -dx);
    226 					} while (rand_mod(2));
    227 				    }
    228 				}
    229 				else if (numgorns >= numenemies-1 &&
    230 				    deados > 15+numgorns*5)
    231 				    obj->strategy = 1;
    232 				if (madgorns || rand_mod(51 - sm50) <= prob) {
    233 				    if (-dy + attackee->vely == obj->vely
    234 				     && -dx + attackee->velx == obj->velx)
    235 					fire_torp(obj,
    236 					 -dy + attackee->vely,
    237 					 -dx + attackee->velx);
    238 				    else
    239 					fire_torp(obj,
    240 					 -dy + attackee->vely - obj->vely,
    241 					 -dx + attackee->velx - obj->velx);
    242 				}
    243 				goto bombout;
    244 			    case 'T':
    245 				if (attackee == nuke) {
    246 				    if (rand_mod(2+scandist-prob) <
    247 				      rand_mod(smarts/40+1))
    248 					tract(nuke,dy,dx,rand_mod(3)?1:-1);
    249 				}
    250 				if (thru_stars)
    251 				    goto bombout;
    252 				if (webnear && scandist-prob > 5) {
    253 				    if (massacre || rand_mod(50) < super) {
    254 					if (!torps && obj->energy > 1000) {
    255 					    fire_phaser(obj, -dy, -dx);
    256 					    while (!rand_mod(57-sm55))
    257 						fire_phaser(obj, -dy, -dx);
    258 					}
    259 				    }
    260 				}
    261 				goto bombout;
    262 			    case 'C': case 'c':
    263 				if (thru_stars)
    264 				    goto bombout;
    265 				break;
    266 			    case 'Q': case 'W': case 'Y': case 'U':
    267 			    case 'I': case 'S': case 'D': case 'H': case 'J':
    268 			    case 'L': case 'Z': case 'V': case 'M': case 'F':
    269 				if (attackee == nuke) {
    270 				    if (rand_mod(2+scandist-prob) <
    271 				      rand_mod(smarts/40+1))
    272 					tract(nuke,dy,dx,rand_mod(3)?1:-1);
    273 				    if (rand_mod(2))
    274 					goto pot_shot;
    275 				}
    276 				if (madfriends > 1000) {
    277 				    madfriends -= 200;
    278 				    goto pot_shot;
    279 				}
    280 				/* FALL THROUGH */
    281 			    case '+':
    282 				if (attackee == nuke) {
    283 				    if (smarts > 70) {
    284 					if (
    285 					 (obj->posx + obj->velx + XSIZE00)%XSIZE
    286 					    == attackee->posx &&
    287 					 (obj->posy + obj->vely + YSIZE00)%YSIZE
    288 					    == attackee->posy ) {
    289 					    tract(nuke,dy,dx,-1);
    290 					}
    291 					else
    292 					    while (!rand_mod(82-sm80))
    293 						tract(nuke,dy,dx,-1);
    294 				    }
    295 				    else if (smarts > 60 ||
    296 				      rand_mod(2+scandist-prob) <
    297 				      rand_mod(smarts/20+1))
    298 					tract(nuke,dy,dx,rand_mod(3)?1:-1);
    299 				}
    300 				torps = false;
    301 				thru_stars = false;
    302 				break;
    303 			    case '|': case '-': case '/': case '\\':
    304 				if (thru_stars)
    305 				    goto bombout;
    306 				webnear = (scandist-prob < 3);
    307 				torps = false;
    308 				break;
    309 			    case 'x':
    310 				if (attackee == nuke) {
    311 				    if (rand_mod(2+scandist-prob) <
    312 				      rand_mod(smarts/20+1))
    313 					tract(nuke,dy,dx,rand_mod(3)?1:-1);
    314 				}
    315 				if (thru_stars)
    316 				    goto bombout;
    317 				torps = true;
    318 				break;
    319 			    case 'o': case 'O': case '0':
    320 				if (attackee == nuke) {
    321 				    if (rand_mod(2+scandist-prob) <
    322 				      rand_mod(smarts/20+1))
    323 					tract(nuke,dy,dx,rand_mod(3)?1:-1);
    324 				}
    325 				if (thru_stars)
    326 				    goto bombout;
    327 				torps = true;
    328 				if (rand_mod(99+3*scandist) < smarts+3*prob) {
    329 				    obj->vely = -dy + attackee->vely;
    330 				    obj->velx = -dx + attackee->velx;
    331 				    if (obj->flags & STATIC) {/* not a mover? */
    332 					obj->flags &= ~STATIC;
    333 					obj->prev->next = obj->next;
    334 					obj->next->prev = obj->prev;
    335 					root.prev->next = obj;
    336 					obj->prev = root.prev;
    337 					root.prev = obj;
    338 					obj->next = &root;
    339 				    }
    340 				}
    341 				if (obj->image != '0')
    342 				    break;
    343 			    /*FALLTHROUGH*/
    344 			    case 'X':
    345 				if (attackee == nuke) {
    346 				    if (rand_mod(2+scandist-prob) <
    347 				      rand_mod(smarts/20+1))
    348 					tract(nuke,dy,dx,rand_mod(3)?1:-1);
    349 				}
    350 				torps = true;
    351 				if (thru_stars)
    352 				    goto bombout;
    353 				if (prob == scandist) {
    354 				    int y, x;
    355 
    356 				    blast[y=(obj->posy+obj->vely+YSIZE00)%YSIZE]
    357 					 [x=(obj->posx+obj->velx+XSIZE00)%XSIZE]
    358 				      += (obj->image == '0' ? 2000 : 200);
    359 				    yblasted[y] |= 1;
    360 				    xblasted[x] |= 1;
    361 				    blasted = true;
    362 				}
    363 				break;
    364 			    case 'A':
    365 				if (attackee != nuke) {
    366 				    if (scandist-prob>1 && !rand_mod(51-super))
    367 					tract(obj,-dy,-dx,1);
    368 				}
    369 				/* FALL THROUGH */
    370 			    case '*': case '@':
    371 				if (attackee == nuke) {
    372 				    if (amb[cury][curx] != '~') {
    373 					if (scandist-prob < nukedist) {
    374 					    nukedist = scandist-prob;
    375 					    nukey = dy;	/* nearest food in */
    376 					    nukex = dx;	/*   this direction */
    377 					}
    378 					if (smarts > 55 && scandist-prob > 8) {
    379 					    if (rand_mod(30+scandist-prob) <
    380 					      rand_mod(smarts/20+1))
    381 						tract(nuke,dy,dx,1);
    382 					}
    383 				    }
    384 				    else if (obj->vely || obj->velx) {
    385 					tract(nuke,dy,dx,1); /* for looks */
    386 					obj->vely = obj->velx = 0;
    387 				    }
    388 				}
    389 				if (!thru_stars) {
    390 				    if (rand_mod(97-sm95))
    391 					goto bombout;
    392 				    else
    393 					thru_stars = true;
    394 				}
    395 				break;
    396 			    case '<': case '>':
    397 				if (attackee == nuke) {
    398 				    if ((!dy && scandist-prob < 8) ||
    399 				      rand_mod(2+scandist-prob) <
    400 				      rand_mod(smarts/20+1) ) {
    401 					nuke->mass += 10000;
    402 					tract(nuke,dy,dx,-1);
    403 					nuke->mass -= 10000;
    404 				    }
    405 				}
    406 				goto bombout;
    407 			    case 'E': case 'B':
    408 				if (attackee == nuke) {
    409 				    if (rand_mod(2+scandist-prob) <
    410 				      rand_mod(smarts/40+1))
    411 					tract(nuke,dy,dx,rand_mod(3)?1:-1);
    412 				}
    413 				goto bombout;
    414 			    default:
    415 				goto bombout;
    416 			    }
    417 			}
    418 			else {
    419 			    if (thru_stars)
    420 				goto bombout;
    421 			}
    422 		    }
    423 bombout:            ; /* end of loop */
    424 		}
    425 	    }
    426 	}
    427 	if (attackee == nuke && nukedist < 100) {/* aim amoeba at nearest */
    428 	    if (nukey < 0)			/*   free star */
    429 		nukey = 2;
    430 	    if (nukex < 0)
    431 		nukex = 2;
    432 	    nuke->strategy = nukey + (nukex << 2);
    433 	}
    434     }
    435 }
    436 
    437 void
    438 fire_phaser(OBJECT *obj, int dy, int dx)
    439 {
    440     int y;
    441     int x;
    442     int skipping;
    443     int size=5000;
    444     int decr = 50, oldy, oldx;
    445     static char curchar[] = "@* ";
    446 
    447     if (obj == ent)
    448 	decr = 100;
    449     else if (obj == base) {
    450 	decr = 1000;
    451 	size = 200;
    452     }
    453     if (!dy)
    454 	curchar[2] = '-';
    455     else if (!dx)
    456 	curchar[2] = '!';
    457     else if (dy == dx)
    458 	curchar[2] = '\\';
    459     else
    460 	curchar[2] = '/';
    461     if (obj->energy >= decr) {
    462 	obj->energy -= decr;
    463 	for (
    464 	  /* initialize */
    465 	  skipping = (obj != base),
    466 	  y = (obj->posy+(obj==base?dy*2:dy)+YSIZE00)%YSIZE,
    467 	  x = (obj->posx+(obj==base?dx*2:dx)+XSIZE00)%XSIZE;
    468 	  /* while */
    469 	  size && (!occupant[y][x]||(skipping && occupant[y][x]->type==Star));
    470 	  /* at end of loop */
    471 	  y = (y+dy+YSIZE00) % YSIZE,
    472 	  x = (x+dx+XSIZE00) % XSIZE,
    473 	  size = size * 3 / 4 ) {
    474 	    move(y+1,x*2,0);
    475 	    beg_qwrite();
    476 	    if (obj == base || obj->image == 'T') {
    477 		*filler = '@';
    478 		qwrite();
    479 		*filler = '#';
    480 		qwrite();
    481 		*filler = '~';
    482 		qwrite();
    483 		*filler = '%';
    484 		qwrite();
    485 		*filler = ':';
    486 		qwrite();
    487 		*filler = '@';
    488 	    }
    489 	    else {
    490 		*filler = size >= 500 ?
    491 			  *curchar : (size >= 50 ?
    492 				     curchar[1] :
    493 				     curchar[2]);
    494 	    }
    495 	    qwrite();
    496 	    if (occupant[y][x])
    497 		qaddc(occupant[y][x]->image);
    498 	    else {
    499 		if (numamoebas)
    500 		    qaddc(amb[y][x]);
    501 		else
    502 		    qaddspace();
    503 		if (skipping)
    504 		    skipping = 0;
    505 	    }
    506 	    end_qwrite();
    507 	}
    508 	if (size) {
    509 	    char img;
    510 
    511 	    assert(occupant[y][x]);
    512 	    img = occupant[y][x]->image;
    513 	    if (occupant[y][x]->type == Crusher) {
    514 		if (dy)
    515 		    return;
    516 	        if (dx==(img == '<' ? 1 : -1) ) {
    517 		    occupant[y][x]->image =
    518 			(occupant[y][x]->velx *= -1) < 0 ? '>' : '<';
    519 		    return;
    520 		}
    521 	    }
    522 	    else if (occupant[y][x]->flags & FRIENDLY)
    523 		madfriends += 200;
    524 	    if (numamoebas && amb[y][x] == '~' && smarts % 3 &&
    525 		(smarts > 70 || rand_mod(smarts) > rand_mod(20)) ) {
    526 		if (size > 10000)
    527 		    modify_amoeba(y,x,1,'~',10);
    528 		else if (size > 1000)
    529 		    modify_amoeba(y,x,1,'~',7);
    530 		else if (size > 50)
    531 		    modify_amoeba(y,x,1,'~',5);
    532 		else
    533 		    modify_amoeba(y,x,1,'~',2);
    534 		if (occupant[y][x] == nuke) {
    535 		    nuke->strategy = rand_mod(30);
    536 		    nuke->flags |= COUNTDOWN;
    537 		}
    538 		return;
    539 	    }
    540 	    else {
    541 		move(y+1,x*2,0);
    542 		beg_qwrite();
    543 		if (img == ' ') {
    544 		    *filler = occupant[y][x]->flags & PIRATE ? 'P' : 'R';
    545 		    occupant[y][x]->image = *filler;
    546 		    occupant[y][x]->strategy = 0;
    547 		    qwrite();
    548 		    qwrite();
    549 		}
    550 		else if (img == 'C' || img == 'c') {
    551 		    cloaked = 0;
    552 		    img += 2;
    553 		    occupant[y][x]->image = img;
    554 		    *filler = img;
    555 		    qwrite();
    556 		    qwrite();
    557 		}
    558 		else if (img == 'K' && size > 50)
    559 		    occupant[y][x]->strategy = 0;
    560 		*filler = '@';
    561 		qwrite();
    562 		*filler = '#';
    563 		qwrite();
    564 		*filler = '@';
    565 		qwrite();
    566 		*filler = '#';
    567 		qwrite();
    568 		*filler = '@';
    569 		qwrite();
    570 		qaddc(img);
    571 		end_qwrite();
    572 		oldy = y;
    573 		oldx = x;
    574 		y = (occupant[oldy][oldx]->posy + occupant[oldy][oldx]->vely +
    575 			YSIZE00) % YSIZE;
    576 		x = (occupant[oldy][oldx]->posx + occupant[oldy][oldx]->velx +
    577 			XSIZE00) % XSIZE;
    578 		if (occupant[y][x] && occupant[y][x]->type == Star) {
    579 		    y = occupant[oldy][oldx]->posy;
    580 		    x = occupant[oldy][oldx]->posx;
    581 		}
    582 		if (obj==base)
    583 		    blast[y][x] += size>50 ? 15000 : (size>15 ? 1500 : 150);
    584 		else if (obj==ent)
    585 		    blast[y][x] += size*4;
    586 		else if (obj->image=='T')
    587 		    blast[y][x] += 15000;
    588 		else
    589 		    blast[y][x] += size*smarts/25;
    590 		yblasted[y] |= 1;
    591 		xblasted[x] |= 1;
    592 		blasted = true;
    593 	    }
    594 	}
    595     }
    596 }
    597 
    598 int
    599 tract(OBJECT *obj, int dy, int dx, int to_or_fro)
    600 {
    601     int y;
    602     int x;
    603     int size=10;
    604     static char ch;
    605     OBJECT *tractee;
    606 
    607     if (!dy)
    608 	ch = '|';
    609     else if (!dx)
    610 	ch = '-';
    611     else if (dy == dx)
    612 	ch = '/';
    613     else
    614 	ch = '\\';
    615     {
    616 	for (
    617 	  y = (obj->posy+dy+YSIZE00)%YSIZE,
    618 	  x = (obj->posx+dx+XSIZE00)%XSIZE;
    619 	  size && (!occupant[y][x]);
    620 	  y = (y+dy+YSIZE00) % YSIZE, x = (x+dx+XSIZE00) % XSIZE, size--) {
    621 	    move(y+1,x*2,0);
    622 	    beg_qwrite();
    623 	    *filler = ch;
    624 	    qwrite();
    625 	    qwrite();
    626 	    if (numamoebas)
    627 		qaddch(amb[y][x]);
    628 	    else
    629 		qaddspace();
    630 	    end_qwrite();
    631 	}
    632 	tractee = occupant[y][x];
    633 	if (size) {
    634 	    assert(tractee);
    635 	    if (numamoebas && obj != nuke && amb[y][x] == '~') {
    636 		if (to_or_fro > 0)
    637 		    modify_amoeba(y,x,2,'~',size);
    638 		else
    639 		    modify_amoeba(y,x,1,' ',size);
    640 	    }
    641 	    if (tractee->type != Web &&
    642 		(tractee->mass < obj->mass * 5 ||
    643 		 (tractee->type == Crusher && !dx) ) ) {
    644 		if (tractee == ent) {
    645 		    evely -= dy * to_or_fro;
    646 		    evelx -= dx * to_or_fro;
    647 		}
    648 		else if (tractee == base) {
    649 		    bvely -= dy * to_or_fro;
    650 		    bvelx -= dx * to_or_fro;
    651 		}
    652 		else {
    653 		    tractee->vely -= dy * to_or_fro;
    654 		    tractee->velx -= dx * to_or_fro;
    655 		}
    656 		if (tractee->type == Torp ||
    657 		    tractee->type == Star) {
    658 		    if (tractee->flags & STATIC) {  /* not a mover? */
    659 			tractee->flags &= ~STATIC;
    660 			tractee->prev->next = tractee->next;
    661 			tractee->next->prev = tractee->prev;
    662 			root.prev->next = tractee;
    663 			tractee->prev = root.prev;
    664 			root.prev = tractee;
    665 			tractee->next = &root;
    666 		    }
    667 		}
    668 	    }
    669 	    else if (tractee->type == Crusher && !dy &&
    670 	      dx==(tractee->image == '<' ? 1 : -1) ) {
    671 		setimage(tractee, (tractee->velx *= -1) < 0 ? '>' : '<');
    672 	    }
    673 	    if (tractee->mass * 5 > obj->mass)
    674 		return(1);
    675 	}
    676     }
    677     return(0);
    678 }
    679