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