xref: /netbsd-src/games/warp/init.c (revision 1182a44c59cae4d586117d55eca24b4b8b173211)
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 
36 void
initialize(void)37 initialize(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 
166 stars_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