init.c revision 1.3 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
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 #ifndef lint
250 x = (int)((((double)(myrand()-HALFRAND)) *
251 ((double)(myrand()-HALFRAND))/RANDRAND)
252 * 20.0) + xoff; /* pick from -20..20, clumped */
253 #endif
254 break;
255 case 4:
256 if (fscanf(mapfp,"%d %d\n",&ypred,&xpred) == EOF)
257 ydist = xdist = 0;
258 x = xpred + xoff;
259 break;
260 case 5:
261 if (fscanf(mapfp,"%d %d\n",&ypred,&xpred) == EOF)
262 ydist = xdist = 0;
263 x = -xpred + xoff;
264 break;
265 case 6:
266 x += rand_mod(3) - 1;
267 break;
268 }
269 switch (ydist) {
270 case 0:
271 y = rand_mod(YSIZE);
272 break;
273 case 1:
274 #ifndef lint
275 y = (int)((((double)(myrand()-HALFRAND)) *
276 ((double)(myrand()-HALFRAND))/RANDRAND)
277 * 12.0) + yoff; /* pick from -12..12, clumped */
278 #endif
279 break;
280 case 2:
281 #ifndef lint
282 y = (int)((((double)(myrand()-HALFRAND)) *
283 ((double)(myrand()-HALFRAND))/RANDRAND)
284 * 12.0) + yoff + x*YSIZE/XSIZE;
285 /* clumped & skewed */
286 #endif
287 break;
288 case 3:
289 #ifndef lint
290 y = (int)((((double)(myrand()-HALFRAND)) *
291 ((double)(myrand()-HALFRAND))/RANDRAND)
292 * 12.0) + yoff - x*YSIZE/XSIZE;
293 /* clumped & skewed */
294 #endif
295 break;
296 case 4:
297 y = ypred + yoff;
298 break;
299 case 5:
300 y = -ypred + yoff;
301 break;
302 case 6:
303 y += rand_mod(3) - 1;
304 #ifdef lint
305 walksplit = walksplit;
306 #endif
307 if (!rand_mod(walksplit)) {
308 y = rand_mod(YSIZE);
309 x = rand_mod(XSIZE);
310 }
311 break;
312 }
313 while (x<0) x += XSIZE00;
314 while (y<0) y += YSIZE00;
315 x %= XSIZE;
316 y %= YSIZE;
317 } while (occupant[y][x]);
318 e = rand_mod(32768);
319 if (--inhabjackpot > 0 || e >= inhenergy) {
320 ch = '@';
321 if (inhabjackpot && e < 10000)
322 e += 10000;
323 inuminhab = ++numinhab;
324 }
325 else {
326 ch = '*';
327 }
328 obj = make_object(Star,ch,y,x,0,0,e+rand_mod(super*100+1),e/4,&root);
329 obj->flags |= STATIC;
330 }
331 if (inumstars > 30 && inhabjackpot <= 0 &&
332 !rand_mod(3 - (inumstars > 400) - (inhenergy > 32768)) ) {
333 int initx;
334 int inity;
335
336 x = initx = obj->posx;
337 y = inity = obj->posy;
338 while (rand_mod(2) && inuminhab < inumstars/2) {
339 for (i=rand_mod(smarts)*2+20; i; i--) {
340 if ((obj = occupant[y][x]) && obj->image == '*') {
341 setimage(obj,'@');
342 if (obj->energy < 10000)
343 obj->energy += 20000; /* the benefits of civilization */
344 inuminhab = ++numinhab;
345 }
346 if (i&15) {
347 y = (y + rand_mod(3) + YSIZE99) % YSIZE;
348 x = (x + rand_mod(3) + XSIZE99) % XSIZE;
349 }
350 else { /* don't wander too far */
351 y = inity;
352 x = initx;
353 }
354 }
355 x = initx = rand_mod(XSIZE);
356 y = inity = rand_mod(YSIZE);
357 }
358 }
359 if (mapfp != NULL)
360 fclose(mapfp);
361 if (numcrushes) {
362 do {
363 x = rand_mod(XSIZE);
364 y = rand_mod(YSIZE);
365 } while (occupant[y][x]);
366 movers = make_object(Crusher,'<',y,x,0,1,32767L,32768L,&root);
367 possiblescore += 10000;
368 }
369 ient = (numents != 0);
370 if (ient) {
371 do {
372 x = rand_mod(XSIZE);
373 y = rand_mod(YSIZE);
374 } while (occupant[y][x]);
375 e = entmax;
376 ent = make_object(Enterprise,'E',y,x,0,0,e,e/2,&root);
377 if (!movers)
378 movers = ent;
379 }
380 ibase = (numbases != 0);
381 if (ibase) {
382 e = 52-super;
383 do {
384 x = rand_mod(XSIZE);
385 y = rand_mod(YSIZE);
386 } while (occupant[y][x] || lookaround(y,x,Star) * 7 < e--);
387 e = basemax;
388 base = make_object(Base, 'B',y,x,0,0,e,e/4,&root);
389 if (!movers)
390 movers = base;
391 }
392 if (numamoebas) {
393 do {
394 x = rand_mod(XSIZE);
395 y = rand_mod(YSIZE);
396 } while (occupant[y][x]);
397 nuke = make_object(Enemy,'&',y,x,0,0,32767L,
398 (long)entmax+entmax+rand_mod(entmax),&root);
399 possiblescore += 10000;
400 amb[y][x] = '~';
401 if (rand_mod(2))
402 modify_amoeba(y,x,2,'~',(int)rand_mod(smarts<<1));/* just make blob */
403 else {
404 for (i=smarts/10+1; i; i--) {
405 nuke->strategy = rand_mod(256); /* random direction */
406 modify_amoeba(y,x,2,'~',(int)rand_mod(5));
407 modify_amoeba(y,x,2,'~',(int)rand_mod(5));
408 modify_amoeba(y,x,2,'~',(int)rand_mod(5));
409 modify_amoeba(y,x,2,'~',(int)rand_mod(5)); /* extend pseudopod */
410 }
411 }
412 if (!enemies)
413 enemies = nuke;
414 if (!movers)
415 movers = nuke;
416 }
417 if (rand_mod(27-sm50/2) && !romspec && !gornspec)
418 dist = 27-sm50/2;
419 else
420 dist = rand_mod(4) + 1;
421 for (i = 1+inumcrushes+inumamoebas; i <= numenemies; i++) {
422 do {
423 x = rand_mod(XSIZE);
424 y = rand_mod(YSIZE);
425 } while (occupant[y][x]);
426 if (rand_mod(dist)) {
427 if (!tholspec && !tmptholspec && rand_mod((inumstars*3)/sm50+2))
428 ch = 'K';
429 else {
430 ch = 'T';
431 inumthols++;
432 }
433 }
434 else {
435 if (romspec == gornspec)
436 e = 50;
437 else if (gornspec)
438 e = 10;
439 else
440 e = 90;
441 if (rand_mod(100) < e) {
442 ch = 'R';
443 inumroms++;
444 }
445 else {
446 ch = 'G';
447 inumgorns++;
448 }
449 }
450 if (possiblescore > ENTBOUNDARY - 10000)
451 e = (ENTBOUNDARY - possiblescore) / 5;
452 else
453 e = 250 + (sm50-1) * 30 * 20 / numenemies+1;
454 #ifndef lint
455 e = exdis((int)e) + e - exdis((int)e);
456 obj = make_object(Enemy,ch,y,x,0,0,
457 e + rand_mod(super*200+2) + 10000*massacre,e/4,&root);
458 #endif
459 e /= 4;
460 switch (ch) {
461 case 'K':
462 possiblescore += e;
463 break;
464 case 'T':
465 possiblescore += e*3/2;
466 break;
467 case 'G':
468 possiblescore += e*2;
469 break;
470 case 'R':
471 possiblescore += e*3;
472 obj->flags |= CLOAKS;
473 break;
474 }
475 if (!enemies)
476 enemies = obj;
477 if (!movers)
478 movers = obj;
479 }
480 numgorns = inumgorns;
481 for (i=0; i<numfriends; i++) {
482 do {
483 x = rand_mod(XSIZE);
484 y = rand_mod(YSIZE);
485 } while (occupant[y][x]);
486 e = 250 + (sm50-1) * 30 * 20 / numenemies+1;
487 #ifndef lint
488 e = exdis((int)e) + e - exdis((int)e);
489 #endif
490 {
491 static char let[] = "QWYUISDHJLZVMFFFFFFFFF";
492
493 dist = rand_mod(20);
494 ch = let[dist];
495 } /* grr, venix doesn't like indexing into string */
496 obj = make_object(Enemy,ch,y,x,0,0,
497 e + rand_mod(super*200+2),e/4,&root);
498 if (numpirates-- > 0) {
499 obj->flags |= PIRATE;
500 if (smarts >= 20 && !rand_mod(10-smarts/10))
501 obj->flags |= CLOAKS;
502 }
503 obj->flags |= FRIENDLY;
504 if (!enemies)
505 enemies = obj;
506 if (!movers)
507 movers = obj;
508 }
509 if (!movers)
510 movers = &root;
511 if (!enemies)
512 enemies = &root;
513 if (ent)
514 mvaddch(ent->posy+1, ent->posx*2, ent->image);
515 if (base)
516 mvaddch(base->posy+1, base->posx*2, base->image);
517 sleep(2);
518 {
519 OBJECT *curobj;
520
521 for (curobj = root.next; curobj != &root; curobj = curobj->next) {
522 mvaddch(curobj->posy+1, curobj->posx*2, curobj->image);
523 }
524 }
525
526 for (i=0;i<2;i++) for (y=0;y<3;y++) for (x=0;x<3;x++)
527 isatorp[i][y][x]=0;
528
529 whenok = 0;
530 timer = 0;
531 finish = 0;
532 bombed_out = false;
533 if (ent)
534 entmode = status = 0;
535 else
536 if (base)
537 status = 2;
538 else
539 status = 3;
540
541 snprintf(spbuf, sizeof(spbuf),
542 "%-4s E: %4d %2d B: %5d %3d Enemies: %-3d Stars: %-3d Stardate%5d.%1d %9ld",
543 " ", 0, 0, 0, 0, 0, 0, smarts * 100, 0, 0L);
544 mvaddstr(0,0,spbuf);
545 oldeenergy = oldbenergy = oldcurscore =
546 oldstatus = oldetorp = oldbtorp = oldstrs = oldenemies = -1;
547 /* force everything to fill in */
548 damage = olddamage = 0;
549 for (i=0; i<MAXDAMAGE; i++)
550 damflag[i] = 0;
551 btorp = 500;
552 etorp = 50;
553 }
554