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
37void
38them_init(void)
39{
40    ;
41}
42
43void
44their_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
334void
335modify_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