Home | History | Annotate | Line # | Download | only in warp
them.c revision 1.1
      1 /* $Header: /tank/opengrok/rsync2/NetBSD/src/games/warp/them.c,v 1.1 2020/11/09 23:37:05 kamil Exp $ */
      2 
      3 /* $Log: them.c,v $
      4 /* Revision 1.1  2020/11/09 23:37:05  kamil
      5 /* Add Warp Kit, Version 7.0 by Larry Wall
      6 /*
      7 /* Warp is a real-time space war game that doesn't get boring very quickly.
      8 /* Read warp.doc and the manual page for more information.
      9 /*
     10 /* games/warp originally distributed with 4.3BSD-Reno, is back to the BSD
     11 /* world via NetBSD. Its remnants were still mentioned in games/Makefile.
     12 /*
     13 /* Larry Wall, the original author and the copyright holder, generously
     14 /* donated the game and copyright to The NetBSD Foundation, Inc.
     15 /*
     16 /* Import the game sources as-is from 4.3BSD-Reno, with the cession
     17 /* of the copyright and license to BSD-2-clause NetBSD-style.
     18 /*
     19 /* Signed-off-by: Larry Wall <larry (at) wall.org>
     20 /* Signed-off-by: Kamil Rytarowski <kamil (at) netbsd.org>
     21 /*
     22  * Revision 7.0.1.5  86/12/12  17:05:41  lwall
     23  * Baseline for net release.
     24  *
     25  * Revision 7.0.1.4  86/10/20  12:32:38  lwall
     26  * Wasn't clearing FRIENDLY flag on pirate creation.
     27  *
     28  * Revision 7.0.1.3  86/10/20  12:15:33  lwall
     29  * Was trying to create pirates from cloaked pirates.
     30  *
     31  * Revision 7.0.1.2  86/10/17  10:03:44  lwall
     32  * Fixed Romulan writing spaces while cloaked.
     33  *
     34  * Revision 7.0.1.1  86/10/16  10:53:39  lwall
     35  * Added Damage.  Fixed random bugs.
     36  *
     37  * Revision 7.0  86/10/08  15:14:15  lwall
     38  * Split into separate files.  Added amoebas and pirates.
     39  *
     40  */
     41 
     42 #include "EXTERN.h"
     43 #include "warp.h"
     44 #include "bang.h"
     45 #include "object.h"
     46 #include "move.h"
     47 #include "score.h"
     48 #include "term.h"
     49 #include "us.h"
     50 #include "util.h"
     51 #include "weapon.h"
     52 #include "INTERN.h"
     53 #include "them.h"
     54 
     55 void
     56 them_init()
     57 {
     58     ;
     59 }
     60 
     61 void
     62 their_smarts()
     63 {
     64     Reg1 OBJECT *curkl;
     65     Reg2 OBJECT *obj;
     66     Reg3 int prob;
     67     Reg4 int count;
     68     Reg5 int y;
     69     Reg6 int x;
     70 
     71     if (numcrushes && (obj=movers)->type == Crusher) {
     72 	if (numamoebas) {
     73 	    y = obj->posy;
     74 	    x = (obj->posx+(obj->image=='<'?1:-1)+XSIZE00)%XSIZE;
     75 	    if (amb[y][x] == '~') {
     76 		obj->velx = 0;		/* stop and munch amoeba */
     77 		modify_amoeba(y,x,1,' ',(int)rand_mod(5+ambsize/10)+1);
     78 		if (occupant[y][x] == nuke)	/* except go for nucleus */
     79 		    obj->velx = (obj->image=='<' ? 1 : -1);
     80 	    }
     81 	    else if (!obj->velx) {
     82 		if (!rand_mod(4))
     83 		    obj->image = rand_mod(2) ? '<' : '>';
     84 		obj->velx = obj->image == '<' ? 1 : -1;
     85 	    }
     86 	}
     87 	obj->vely += (rand_mod(222) - 111) / 100;
     88 	if (!(rand_mod(100))) {
     89 	    setimage(obj, (obj->velx *= -1) < 0 ? '>' : '<');
     90 	}
     91     }
     92     if (numamoebas) {
     93 	if (!rand_mod(3))
     94 	    nuke->velx = nuke->vely = 0;
     95 	if (nuke->strategy && ambsize < 90 && !rand_mod(200-smarts))
     96 	    modify_amoeba(0,0,0,'~',(int)rand_mod(10));
     97 	if (ambsize > 200 || (ambsize > 100 && !rand_mod(15)))
     98 	    modify_amoeba(yamblast,xamblast,2,' ',(ambsize-100)/5);
     99     }
    100     for (curkl = enemies; curkl->type == Enemy; curkl = curkl->next) {
    101 	if ((curkl->flags & (CLOAKS|FRIENDLY)) == CLOAKS &&
    102 	    (curkl->image != ' ') &&
    103 	    (curkl->energy > 300 || massacre) ) {
    104 	    setimage(curkl, ' ');
    105 	}
    106 	if (madgorns)
    107 	    prob = 3;
    108 	else if (curkl->vely || curkl->velx)
    109 	    prob = massacre?10:20;
    110 	else if ((curkl->flags & (PIRATE|FRIENDLY)) == PIRATE) {
    111 				/* pirates want to sit sometimes */
    112 	    if (curkl->strategy) {
    113 		if ((obj = lookimg(curkl->posy, curkl->posx, '@')) ||
    114 		    (obj = lookimg(curkl->posy, curkl->posx, 'B')) ) {
    115 		    make_plink(obj->posy, obj->posx);
    116 		    if (!--curkl->strategy) {	/* clock ran down */
    117 			if (obj->image == '@') {
    118 			    obj->image = '*';
    119 			    numinhab--;
    120 			    if (obj->flags & STATIC)
    121 				mvaddch(obj->posy+1,obj->posx*2,obj->image);
    122 			    if (curkl->energy < 20000)
    123 				curkl->energy += 5000;
    124 			}
    125 			prob = 2;	/* our work here is done */
    126 		    }
    127 		    else if (obj->image == 'B') {
    128 			btorp -= rand_mod(50);
    129 			if (btorp < 0)
    130 			    btorp = 0;
    131 			obj->energy -= rand_mod(500);
    132 			if (obj->energy < 0)
    133 			    obj->energy = 0;
    134 			prob = 10000;		/* stay here */
    135 		    }
    136 		    else
    137 			prob = 10000;
    138 		}
    139 		else {		/* it went away--go elsewhere */
    140 		    prob = 4;
    141 		    curkl->strategy = 0;
    142 		}
    143 	    }
    144 	    else if (lookimg(curkl->posy, curkl->posx, '@') ||
    145 		     lookimg(curkl->posy, curkl->posx, 'B')) {
    146 		curkl->strategy = rand_mod(15)+5;
    147 		prob = 10000;
    148 	    }
    149 	    else
    150 		prob = 4;
    151 	}
    152 	else if (curkl->image == 'M') {	/* Mudd wants to sit sometimes */
    153 	    if ((obj = lookimg(curkl->posy, curkl->posx, 'E')) ||
    154 		(obj = lookimg(curkl->posy, curkl->posx, 'B')) ) {
    155 		if (obj->image == 'B') {
    156 		    btorp -= rand_mod(40);
    157 		    if (btorp < 0)
    158 			btorp = 0;
    159 		    obj->energy -= rand_mod(100);
    160 		    if (obj->energy < 0)
    161 			obj->energy = 0;
    162 		}
    163 		else if (!obj->vely && !obj->velx) {
    164 		    etorp -= rand_mod(10);
    165 		    if (etorp < 0)
    166 			etorp = 0;
    167 		    obj->energy -= rand_mod(20);
    168 		    if (obj->energy < 0)
    169 			obj->energy = 0;
    170 		}
    171 		prob = 10000;		/* stay here */
    172 	    }
    173 	    else		/* it went away--go elsewhere */
    174 		prob = 4;
    175 	}
    176 	else if (curkl->flags & FRIENDLY) {
    177 	    if (curkl->energy < 10000 &&
    178 	      lookimg(curkl->posy, curkl->posx, '@') ) {
    179 		curkl->energy += 100;
    180 		prob = 20;	/* do some loading */
    181 	    }
    182 	    else
    183 		prob = 4;
    184 	}
    185 	else if (curkl->image == '&') {
    186 	    if (curkl->flags & COUNTDOWN) {
    187 		if (curkl->strategy)
    188 		    curkl->strategy--;
    189 		else
    190 		    curkl->flags &= ~COUNTDOWN;
    191 		prob = 100;	/* someone's feeding us, so sit still */
    192 	    }
    193 	    else
    194 		prob = 4;
    195 	}
    196 	else
    197 	    prob = 4;			/* don't sit still too long */
    198 	count = 11;
    199 	for (;;) {
    200 	    if (--count <= 0)		/* no opening, just ram something */
    201 		break;
    202 
    203 #ifdef lint
    204 	    prob = prob;
    205 #endif
    206 	    if (!(rand_mod(prob)))	/* turn randomly occasionally */
    207 		goto accell;
    208 
    209 	    y=(curkl->posy+curkl->vely+YSIZE00)%YSIZE;	/* find prospective */
    210 	    x=(curkl->posx+curkl->velx+XSIZE00)%XSIZE;	/*   new position */
    211 
    212 	    if (numamoebas) {
    213 		if (curkl == nuke) {
    214 		    if (amb[y][x] != '~')
    215 			goto accell;	/* never move nucleus from protoplasm */
    216 		}
    217 		else {
    218 		    if (amb[y][x] == '~' && rand_mod(2)) {
    219 			yamblast = y;
    220 			xamblast = x;
    221 			goto accell;
    222 		    }
    223 		}
    224 	    }
    225 
    226 	    obj = occupant[y][x];
    227 	    if (!obj) break;		/* is anyone there? */
    228 
    229 	    switch (obj->type) {
    230 	    case Star:
    231 		if (obj->image == '@' && (curkl->flags & PIRATE)) {
    232 		    if (curkl->image != 'P' && curkl->image != ' ') {
    233 			if (curkl->flags & FRIENDLY) {
    234 			    curkl->flags &= ~FRIENDLY;
    235 			    curkl->energy += 1000;
    236 			    possiblescore += curkl->mass;
    237 			    inumfriends--;
    238 			    numfriends--;
    239 			    inumenemies++;
    240 			    numenemies++;
    241 			}
    242 			curkl->image = 'P';
    243 		    }
    244 		    break;		/* go ahead and ram the star */
    245 		}
    246 		goto accell;		/* try not to ram stars */
    247 	    case Torp:
    248 		if (!obj->vely && !obj->velx && (rand_mod(100) <= smarts) &&
    249 		  (obj->image == 'o' || obj->image == 'O' || obj->image == 'X'))
    250 		    goto accell;	/* try not to ram "friendly" torps */
    251 		break;
    252 	    case Web:
    253 		if (curkl->image != 'T')
    254 		    goto accell;	/* non-Tholians shouldn't ram web */
    255 		if (count <= 5)
    256 		    break;		/* Tholians retrace web if desperate */
    257 		if (obj->image ==
    258 		    (curkl->vely?
    259 		     (curkl->velx?
    260 		      (curkl->velx==curkl->vely?
    261 		       '\\'
    262 		      :
    263 		       '/'
    264 		      )
    265 		     :
    266 		      '|'
    267 		     )
    268 		    :
    269 		     '-'
    270 		    )
    271 		   ) goto accell;	/* Tholians try not to retrace web */
    272 		break;			/* No problem with crossing web */
    273 	    }
    274 	    break;			/* okay to move over object */
    275 
    276 	accell:
    277 	    /* determine maximum velocity */
    278 	    if (massacre && curkl->image != 'T') {
    279 		curkl->vely = rand_mod(7) - 3;
    280 		curkl->velx = rand_mod(7) - 3;
    281 	    }
    282 	    else if (curkl->image == '&') {
    283 		if (rand_mod(2)) {
    284 		    curkl->vely = rand_mod(3) - 1;
    285 		    curkl->velx = rand_mod(3) - 1;
    286 		}
    287 		else {
    288 		    curkl->vely = curkl->strategy & 3;
    289 		    if (curkl->vely & 2)
    290 			curkl->vely = -1;
    291 		    curkl->velx = (curkl->strategy >> 2) & 3;
    292 		    if (curkl->velx & 2)
    293 			curkl->velx = -1;
    294 		}
    295 	    }
    296 	    else if (curkl->energy >= 2500 && curkl->image != 'T') {
    297 		curkl->vely = rand_mod(5) - 2;
    298 		curkl->velx = rand_mod(5) - 2;
    299 	    }
    300 	    else {
    301 		curkl->vely = rand_mod(3) - 1;
    302 		curkl->velx = rand_mod(3) - 1;
    303 	    }
    304 	}
    305 	if (count != 10) {
    306 	    if (curkl->image == ' ') {
    307 		setimage(curkl, curkl->flags & PIRATE ? 'P' : 'R');
    308 	    }
    309 	    if (!count) {
    310 		curkl->vely = 0;
    311 		curkl->velx = 0;
    312 	    }
    313 	}
    314 	if (curkl->image == 'G' && (base||ent) &&
    315 	    !rand_mod((103-smarts)*10) ) {
    316 	    int xxx,yyy;
    317 
    318 	    for (xxx = -1; xxx<=1; xxx++)
    319 		for (yyy = -1; yyy<=1; yyy++)
    320 		    if ((xxx||yyy) && rand_mod(2))
    321 			fire_torp(curkl,yyy,xxx);
    322 	}
    323 	else if (curkl->image == 'T' && (curkl->velx || curkl->vely)) {
    324 	    Make_object(Web,
    325             curkl->vely?
    326 	     (curkl->velx?
    327 	      (curkl->velx==curkl->vely?
    328 	       '\\'
    329 	      :
    330 	       '/'
    331 	      )
    332 	     :
    333 	      '|'
    334 	     )
    335 	    :
    336 	     '-',
    337 	    curkl->posy,curkl->posx,0,0,32767L,32767L,&root);
    338 	    if (obj && obj->type == Web) {
    339 		unmake_object(obj);
    340 		occupant[y][x] = Null(OBJECT*);
    341 	    }
    342 	}
    343     }
    344     /* klingon-style fighting */
    345     if (numamoebas)
    346 	attack(nuke);
    347     attack(base);
    348     if (ent && (!cloaked || ent->image=='E' || ent->image=='e'))
    349 	attack(ent);
    350 }
    351 
    352 void
    353 modify_amoeba(y,x,where,ch,quant)
    354 Reg1 int y;
    355 Reg2 int x;
    356 int where;
    357 Reg6 int ch;
    358 Reg7 int quant;
    359 {
    360     Reg3 int dy;
    361     Reg4 int dx;
    362     Reg5 int count = 15;
    363 
    364     if (!numamoebas)
    365 	return;
    366     if (!where || (where==1 && rand_mod(2))) {
    367 	y = nuke->posy;
    368 	x = nuke->posx;
    369     }
    370     if (nuke->strategy && rand_mod(3)) {
    371 	dy = nuke->strategy & 3;
    372 	if (dy & 2)
    373 	    dy = -1;
    374 	dx = (nuke->strategy >> 2) & 3;
    375 	if (dx & 2)
    376 	    dx = -1;
    377 	if (ch == ' ') {		/* take from the tail */
    378 	    dy = -dy;
    379 	    dx = -dx;
    380 	}
    381 	if (!rand_mod(100))
    382 	    nuke->strategy = rand_mod(256);
    383     }
    384     else {
    385 	dy = rand_mod(3) - 1;
    386 	dx = rand_mod(3) - 1;
    387     }
    388     if (!dy && !dx)
    389 	return;
    390     do {
    391 	if (--count < 0)
    392 	    return;
    393 	y = (y + dy + YSIZE00) % YSIZE;
    394 	x = (x + dx + XSIZE00) % XSIZE;
    395     } while (amb[y][x] != ' ');
    396     if (ch == ' ') {
    397 	y = (y - dy + YSIZE00) % YSIZE;
    398 	x = (x - dx + XSIZE00) % XSIZE;
    399     }
    400     if (ambsize > 100 && quant > 2) {
    401 	quant >>= (ambsize/100);
    402     }
    403     if ((nuke->energy += quant << 6) > 32767)
    404 	nuke->energy = 32767;
    405     count = quant << 3;		/* endless loop catcher */
    406     while (count-- > 0 && quant > 0) {
    407 	if (amb[y][x] != ch) {
    408 	    quant--;
    409 	    amb[y][x] = ch;
    410 	    if (ch == '~') {
    411 		ambsize++;
    412 		yblasted[y] |= 2;
    413 		xblasted[x] |= 2;
    414 		blasted = TRUE;
    415 	    }
    416 	    else
    417 		ambsize--;
    418 	    if (!occupant[y][x])
    419 		mvaddch(y+1,x*2,ch);
    420 	}
    421 	y = (y + rand_mod(3) + YSIZE99) % YSIZE;
    422 	x = (x + rand_mod(3) + XSIZE99) % XSIZE;
    423     }
    424 }
    425