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