1/* Header: init.c,v 7.0.1.4 86/12/12 16:58:03 lwall Exp */
2
3/* Log:	init.c,v
4 * Revision 7.0.1.4  86/12/12  16:58:03  lwall
5 * Baseline for net release.
6 *
7 * Revision 7.0.1.3  86/10/20  14:35:31  lwall
8 * Picked some lint.
9 *
10 * Revision 7.0.1.2  86/10/17  15:53:30  lwall
11 * Added random walk star fields.
12 *
13 * Revision 7.0.1.1  86/10/16  10:51:19  lwall
14 * Added Damage.  Fixed random bugs.
15 *
16 * Revision 7.0  86/10/08  15:12:10  lwall
17 * Split into separate files.  Added amoebas and pirates.
18 *
19 */
20
21#include "EXTERN.h"
22#include "warp.h"
23#include "bang.h"
24#include "object.h"
25#include "move.h"
26#include "play.h"
27#include "score.h"
28#include "term.h"
29#include "them.h"
30#include "us.h"
31#include "util.h"
32#include "weapon.h"
33#include "INTERN.h"
34#include "init.h"
35
36void
37initialize(void)
38{
39    int i;
40    int x;
41    int y;
42    int dist;
43    int ydist = 0;
44    int xdist = 0;
45    long e;
46    int yoff = 0, xoff = 0, ypred, xpred;
47    OBJECT *obj = NULL;
48    char ch;
49    FILE *mapfp = NULL;
50    bool tmptholspec;
51    int inhabjackpot;
52    long inhenergy;
53    int walksplit = 200;
54    static const char *distname[] =
55	{" #"," -"," \\"," /",
56	 " |"," *"," `"," '"};
57
58    cloaking = madgorns = false;
59    deados = madfriends = 0;
60    curscore = possiblescore = 0L;
61    yamblast = xamblast = ambsize = 0;
62    if (smarts > 90)
63	massacre = true;
64    scandist = (massacre?20:15);
65    antibase = (smarts>60?1:(smarts>40?2:(smarts>25?4:100)));
66    sm35 = (smarts>35?35:smarts);
67    sm45 = (smarts>45?45:smarts);
68    sm50 = (smarts>50?50:smarts);
69    sm55 = (smarts>55?55:smarts);
70    sm80 = (smarts>80?80:smarts);
71    sm95 = (smarts>95?95:smarts);
72    super = (smarts>50?smarts-50:0);
73    enemshields = 10 + super/2;		/* (scaled by 10) 1 @ 50 .. 3 @ 90 */
74    if (smarts>90)
75	enemshields += (smarts-90)*10;	/* lay it on thick: ~13 @ 99 */
76    entmax = (smarts>=75?5000:(smarts>=50?4000:(smarts>=40?3000:2000)));
77    basemax = (smarts>=75?20000:(smarts>=50?15000:(smarts>=40?12500:10000)));
78
79    clear();
80    while (root.next != &root) {
81	root.next = root.next->next;
82	free_object(root.next->prev);
83    }
84    root.prev = &root;
85    enemies = movers = NULL;
86    numos = numxes = 0;
87#if defined(vax) && XYSIZEx4 == 3680
88    asm("movc5 $0,_occupant,$0,$3680,_occupant");
89    asm("movc5 $0,_blast,$0,$3680,_blast");	/* 3680 = XYSIZEx4 */
90    asm("movc5 $0,_amb,$32,$920,_amb");
91#else
92    for (y=0;y<YSIZE;y++)
93	for (x=0;x<XSIZE;x++) {
94	    occupant[y][x] = 0;
95	    blast[y][x] = 0;
96	    amb[y][x] = ' ';
97	}
98#endif
99    for (y=0; y<YSIZE; y++)
100	yblasted[y] = 0;
101    for (x=0; x<XSIZE; x++)
102	xblasted[x] = 0;
103    blasted = false;
104    if (!starspec) {
105	if (smarts < 15)
106	    inumstars = 50 + rand_mod(50);
107	else if (smarts < 50 || smarts > 85)
108	    inumstars = exdis(800) + rand_mod(100) + 1;
109	else /* too few stars makes 50..85 too hard */
110	    inumstars = exdis(700) + rand_mod(150-super*2) + 50+super*2;
111    }
112    tmptholspec = (smarts > 15 && inumstars < 450 && ! rand_mod(90-sm80));
113    if (!klingspec) {
114	inumenemies = rand_mod((smarts+1)/2) + 1;
115	if (massacre || tmptholspec)
116	    inumenemies += 10;
117    }
118    if (!friendspec)
119	inumfriends = rand_mod(smarts/8+1);
120    if (!piratespec)
121	inumpirates = rand_mod(inumfriends/2+1);
122    if (inumfriends+inumenemies+inumstars > YSIZE*XSIZE-20)
123	inumstars = YSIZE*XSIZE-20 - inumenemies - inumfriends;
124    if (inumstars < 0) {
125	inumfriends += inumstars;
126	inumstars = 0;
127    }
128    if (inumfriends < 0) {
129	inumenemies += inumfriends;
130	inumfriends = 0;
131    }
132    if (inumenemies < 0)
133	inumenemies = 0;
134    numstars = inumstars;
135    inuminhab = numinhab = 0;
136    inumroms = inumthols = inumgorns = 0;
137    numapollos = apolspec || massacre ? 1 :
138       ((!numstars || rand_mod(2) || smarts < 10) ? 0 : 1);
139    inumapollos = apolloflag = 0;
140    realapollo = NULL;
141    inumcrushes = numcrushes =
142	crushspec||massacre?1:(rand_mod(2000) < inumstars);
143    inumenemies += inumcrushes;
144    inumamoebas = numamoebas = (amoebaspec ? 1 :
145	!rand_mod(inumcrushes?3-massacre:8) );	/* < and & are fun together */
146    inumenemies += inumamoebas;
147    if (!rand_mod(40)) {
148	inhabjackpot = 32767;
149	inumfriends += rand_mod(10);
150	inumpirates += rand_mod(10);
151    }
152    else
153	inhabjackpot = inumpirates;
154    inhenergy = 30000-super*150;
155    if (!rand_mod(10))
156	inhenergy = 50000;
157    if (!rand_mod(4))
158	inhenergy += rand_mod(3500+super*150);
159    numfriends = inumfriends;
160    numpirates = inumpirates;
161    numenemies = inumenemies;
162    deadmudds = 0;
163
164    /* do stars */
165
166stars_again:
167    if (prespec)
168	dist = 4;
169    else if (numstars > 750)
170	dist = 0;
171    else
172	dist = rand_mod(starspec||smarts<=5?3:5);
173    if (debugging) {
174	real_y = real_x = -100;
175	printf("\r\n");
176    }
177    switch (dist) {
178    case 0:				/* uniform random */
179	ydist = xdist = 0;
180	if (inumstars < 700 && !rand_mod(3-(inumstars<50))) {
181	    ydist = xdist = 6;		/* well, maybe not so random */
182	    y = rand_mod(YSIZE);
183	    x = rand_mod(XSIZE);
184	    if (rand_mod(2))
185		walksplit = inumstars/(exdis(40)+1);
186	}
187	if (debugging)
188	    printf(" R\r\n");
189	break;
190    case 1: case 2:	/* clumped, maybe skewed, maybe superposed */
191	ydist = rand_mod(4);
192	xdist = rand_mod(2);
193	if (debugging)
194	    printf("%s\r\n",distname[ydist+4*xdist]);
195	yoff = rand_mod(YSIZE);
196	xoff = rand_mod(XSIZE);
197	if (dist == 2)
198	    dist = numstars/2 + exdis(numstars/2) - exdis(numstars/2);
199	else
200	    dist = 0;
201	break;
202    case 3: case 4:			/* predefined or residual */
203      scenario_again:
204	if (debugging)
205	    printf(" P\r\n");
206	dist = 0;
207	snprintf(spbuf, sizeof(spbuf), "smap.%d",
208	    (prescene>=0?prescene:rand_mod(MAPS)) );
209	if ((mapfp = fopen(spbuf,"r")) != NULL &&
210	    fgets(spbuf,10,mapfp) != NULL ) {
211	    inumstars = numstars = atoi(spbuf);
212	    if (inumenemies+inumstars > YSIZE*XSIZE-20)
213		inumstars = numstars = YSIZE*XSIZE-20 - inumenemies;
214	    ydist = rand_mod(2) + 4;	/* flip y axis? */
215	    xdist = rand_mod(2) + 4;	/* flip x axis? */
216	    yoff = rand_mod(YSIZE);	/* how much to shift y */
217	    xoff = rand_mod(XSIZE);	/* how much to shift x */
218	}
219	else {
220	    prespec = false;
221	    prescene = -1;
222	    if (rand_mod(2))
223		goto scenario_again;
224	    goto stars_again;
225	}
226	break;
227    }
228    for (i = 1; i <= numstars; i++) {
229	if (dist && i == dist) {	/* flip to another skewing? */
230	    ydist = rand_mod(4);
231	    xdist = rand_mod(2);
232	    if (!rand_mod(4)) {
233		ydist = xdist = 6;
234		if (debugging)
235		    printf("&\r\n");
236	    }
237	    else if (debugging)
238		printf("%s\r\n",distname[ydist+4*xdist]);
239	    yoff = rand_mod(YSIZE);
240	    xoff = rand_mod(XSIZE);
241	    dist = 0;
242	}
243	do {				/* until an open spot found */
244	    switch (xdist) {
245	    case 0:
246		x = rand_mod(XSIZE);	/* pick from 0..39, uniform */
247		break;
248	    case 1: case 2: case 3:
249		x = (int)((((double)(myrand()-HALFRAND)) *
250		           ((double)(myrand()-HALFRAND))/RANDRAND)
251			  * 20.0) + xoff;	/* pick from -20..20, clumped */
252		break;
253	    case 4:
254		if (fscanf(mapfp,"%d %d\n",&ypred,&xpred) == EOF)
255		    ydist = xdist = 0;
256		x = xpred + xoff;
257		break;
258	    case 5:
259		if (fscanf(mapfp,"%d %d\n",&ypred,&xpred) == EOF)
260		    ydist = xdist = 0;
261		x = -xpred + xoff;
262		break;
263	    case 6:
264		x += rand_mod(3) - 1;
265		break;
266	    }
267	    switch (ydist) {
268	    case 0:
269		y = rand_mod(YSIZE);
270		break;
271	    case 1:
272		y = (int)((((double)(myrand()-HALFRAND)) *
273		           ((double)(myrand()-HALFRAND))/RANDRAND)
274			  * 12.0) + yoff;	/* pick from -12..12, clumped */
275		break;
276	    case 2:
277#ifndef lint
278		y = (int)((((double)(myrand()-HALFRAND)) *
279		           ((double)(myrand()-HALFRAND))/RANDRAND)
280			  * 12.0) + yoff + x*YSIZE/XSIZE;
281				 		/* clumped & skewed */
282#endif
283		break;
284	    case 3:
285#ifndef lint
286		y = (int)((((double)(myrand()-HALFRAND)) *
287		           ((double)(myrand()-HALFRAND))/RANDRAND)
288			  * 12.0) + yoff - x*YSIZE/XSIZE;
289						/* clumped & skewed */
290#endif
291		break;
292	    case 4:
293		y = ypred + yoff;
294		break;
295	    case 5:
296		y = -ypred + yoff;
297		break;
298	    case 6:
299		y += rand_mod(3) - 1;
300#ifdef lint
301		walksplit = walksplit;
302#endif
303		if (!rand_mod(walksplit)) {
304		    y = rand_mod(YSIZE);
305		    x = rand_mod(XSIZE);
306		}
307		break;
308	    }
309	    while (x<0) x += XSIZE00;
310	    while (y<0) y += YSIZE00;
311	    x %= XSIZE;
312	    y %= YSIZE;
313	} while (occupant[y][x]);
314	e = rand_mod(32768);
315	if (--inhabjackpot > 0 || e >= inhenergy) {
316	    ch = '@';
317	    if (inhabjackpot && e < 10000)
318		e += 10000;
319	    inuminhab = ++numinhab;
320	}
321	else {
322	    ch = '*';
323	}
324	obj = make_object(Star,ch,y,x,0,0,e+rand_mod(super*100+1),e/4,&root);
325	obj->flags |= STATIC;
326    }
327    if (inumstars > 30 && inhabjackpot <= 0 &&
328	 !rand_mod(3 - (inumstars > 400) - (inhenergy > 32768)) ) {
329	int initx;
330	int inity;
331
332	x = initx = obj->posx;
333	y = inity = obj->posy;
334	while (rand_mod(2) && inuminhab < inumstars/2) {
335	    for (i=rand_mod(smarts)*2+20; i; i--) {
336		if ((obj = occupant[y][x]) && obj->image == '*') {
337		    setimage(obj,'@');
338		    if (obj->energy < 10000)
339			obj->energy += 20000; /* the benefits of civilization */
340		    inuminhab = ++numinhab;
341		}
342		if (i&15) {
343		    y = (y + rand_mod(3) + YSIZE99) % YSIZE;
344		    x = (x + rand_mod(3) + XSIZE99) % XSIZE;
345		}
346		else {			/* don't wander too far */
347		    y = inity;
348		    x = initx;
349		}
350	    }
351	    x = initx = rand_mod(XSIZE);
352	    y = inity = rand_mod(YSIZE);
353	}
354    }
355    if (mapfp != NULL)
356	fclose(mapfp);
357    if (numcrushes) {
358	do {
359	    x = rand_mod(XSIZE);
360	    y = rand_mod(YSIZE);
361	} while (occupant[y][x]);
362	movers = make_object(Crusher,'<',y,x,0,1,32767L,32768L,&root);
363	possiblescore += 10000;
364    }
365    ient = (numents != 0);
366    if (ient) {
367	do {
368	    x = rand_mod(XSIZE);
369	    y = rand_mod(YSIZE);
370	} while (occupant[y][x]);
371	e = entmax;
372	ent = make_object(Enterprise,'E',y,x,0,0,e,e/2,&root);
373	if (!movers)
374	    movers = ent;
375    }
376    ibase = (numbases != 0);
377    if (ibase) {
378	e = 52-super;
379	do {
380	    x = rand_mod(XSIZE);
381	    y = rand_mod(YSIZE);
382	} while (occupant[y][x] || lookaround(y,x,Star) * 7 < e--);
383	e = basemax;
384	base = make_object(Base, 'B',y,x,0,0,e,e/4,&root);
385	if (!movers)
386	    movers = base;
387    }
388    if (numamoebas) {
389	do {
390	    x = rand_mod(XSIZE);
391	    y = rand_mod(YSIZE);
392	} while (occupant[y][x]);
393	nuke = make_object(Enemy,'&',y,x,0,0,32767L,
394	  (long)entmax+entmax+rand_mod(entmax),&root);
395	possiblescore += 10000;
396	amb[y][x] = '~';
397	if (rand_mod(2))
398	    modify_amoeba(y,x,2,'~',(int)rand_mod(smarts<<1));/* just make blob */
399	else {
400	    for (i=smarts/10+1; i; i--) {
401		nuke->strategy = rand_mod(256);		/* random direction */
402		modify_amoeba(y,x,2,'~',(int)rand_mod(5));
403		modify_amoeba(y,x,2,'~',(int)rand_mod(5));
404		modify_amoeba(y,x,2,'~',(int)rand_mod(5));
405		modify_amoeba(y,x,2,'~',(int)rand_mod(5));	/* extend pseudopod */
406	    }
407	}
408	if (!enemies)
409	    enemies = nuke;
410	if (!movers)
411	    movers = nuke;
412    }
413    if (rand_mod(27-sm50/2) && !romspec && !gornspec)
414	dist = 27-sm50/2;
415    else
416	dist = rand_mod(4) + 1;
417    for (i = 1+inumcrushes+inumamoebas; i <= numenemies; i++) {
418	do {
419	    x = rand_mod(XSIZE);
420	    y = rand_mod(YSIZE);
421	} while (occupant[y][x]);
422	if (rand_mod(dist)) {
423	    if (!tholspec && !tmptholspec && rand_mod((inumstars*3)/sm50+2))
424		ch = 'K';
425	    else {
426		ch = 'T';
427		inumthols++;
428	    }
429	}
430	else {
431	    if (romspec == gornspec)
432		e = 50;
433	    else if (gornspec)
434		e = 10;
435	    else
436		e = 90;
437	    if (rand_mod(100) < e) {
438		ch = 'R';
439		inumroms++;
440	    }
441	    else {
442		ch = 'G';
443		inumgorns++;
444	    }
445	}
446	if (possiblescore > ENTBOUNDARY - 10000)
447	    e = (ENTBOUNDARY - possiblescore) / 5;
448	else
449	    e = 250 + (sm50-1) * 30 * 20 / numenemies+1;
450#ifndef lint
451	e = exdis((int)e) + e - exdis((int)e);
452	obj = make_object(Enemy,ch,y,x,0,0,
453	    e + rand_mod(super*200+2) + 10000*massacre,e/4,&root);
454#endif
455	e /= 4;
456	switch (ch) {
457	case 'K':
458	    possiblescore += e;
459	    break;
460	case 'T':
461	    possiblescore += e*3/2;
462	    break;
463	case 'G':
464	    possiblescore += e*2;
465	    break;
466	case 'R':
467	    possiblescore += e*3;
468	    obj->flags |= CLOAKS;
469	    break;
470	}
471	if (!enemies)
472	    enemies = obj;
473	if (!movers)
474	    movers = obj;
475    }
476    numgorns = inumgorns;
477    for (i=0; i<numfriends; i++) {
478	do {
479	    x = rand_mod(XSIZE);
480	    y = rand_mod(YSIZE);
481	} while (occupant[y][x]);
482	e = 250 + (sm50-1) * 30 * 20 / numenemies+1;
483#ifndef lint
484	e = exdis((int)e) + e - exdis((int)e);
485#endif
486	{
487	    static char let[] = "QWYUISDHJLZVMFFFFFFFFF";
488
489	    dist = rand_mod(20);
490	    ch = let[dist];
491	}		/* grr, venix doesn't like strchring into string */
492	obj = make_object(Enemy,ch,y,x,0,0,
493	    e + rand_mod(super*200+2),e/4,&root);
494	if (numpirates-- > 0) {
495	    obj->flags |= PIRATE;
496	    if (smarts >= 20 && !rand_mod(10-smarts/10))
497		obj->flags |= CLOAKS;
498	}
499	obj->flags |= FRIENDLY;
500	if (!enemies)
501	    enemies = obj;
502	if (!movers)
503	    movers = obj;
504    }
505    if (!movers)
506	movers = &root;
507    if (!enemies)
508	enemies = &root;
509    if (ent)
510	mvaddch(ent->posy+1, ent->posx*2, ent->image);
511    if (base)
512	mvaddch(base->posy+1, base->posx*2, base->image);
513    sleep(2);
514    {
515	OBJECT *curobj;
516
517	for (curobj = root.next; curobj != &root; curobj = curobj->next) {
518	    mvaddch(curobj->posy+1, curobj->posx*2, curobj->image);
519	}
520    }
521
522    for (i=0;i<2;i++) for (y=0;y<3;y++) for (x=0;x<3;x++)
523    isatorp[i][y][x]=0;
524
525    whenok = 0;
526    timer = 0;
527    finish = 0;
528    bombed_out = false;
529    if (ent)
530	entmode = status = 0;
531    else
532	if (base)
533	    status = 2;
534	else
535	    status = 3;
536
537    snprintf(spbuf, sizeof(spbuf),
538    "%-4s E: %4d %2d B: %5d %3d Enemies: %-3d Stars: %-3d Stardate%5d.%1d %9ld",
539	"   ", 0, 0, 0, 0, 0, 0, smarts * 100, 0, 0L);
540    mvaddstr(0,0,spbuf);
541    oldeenergy = oldbenergy = oldcurscore =
542    oldstatus = oldetorp = oldbtorp = oldstrs = oldenemies = -1;
543					/* force everything to fill in */
544    damage = olddamage = 0;
545    for (i=0; i<MAXDAMAGE; i++)
546	damflag[i] = 0;
547    btorp = 500;
548    etorp = 50;
549}
550