]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - larn/create.c
ctime can return NULL.
[bsdgames-darwin.git] / larn / create.c
1 /* $NetBSD: create.c,v 1.11 2008/02/03 19:29:50 dholland Exp $ */
2
3 /* create.c Larn is copyrighted 1986 by Noah Morgan. */
4
5 #include <sys/cdefs.h>
6 #ifndef lint
7 __RCSID("$NetBSD: create.c,v 1.11 2008/02/03 19:29:50 dholland Exp $");
8 #endif /* not lint */
9
10 #include "header.h"
11 #include "extern.h"
12 #include <unistd.h>
13
14 static void makemaze(int);
15 static int cannedlevel(int);
16 static void treasureroom(int);
17 static void troom(int, int, int, int, int, int);
18 static void makeobject(int);
19 static void fillmroom(int, int, int);
20 static void froom(int, int, int);
21 static void fillroom(int, int);
22 static void sethp(int);
23 static void checkgen(void);
24
25 /*
26 makeplayer()
27
28 subroutine to create the player and the players attributes
29 this is called at the beginning of a game and at no other time
30 */
31 void
32 makeplayer()
33 {
34 int i;
35 scbr();
36 clear();
37 c[HPMAX] = c[HP] = 10; /* start player off with 15 hit points */
38 c[LEVEL] = 1; /* player starts at level one */
39 c[SPELLMAX] = c[SPELLS] = 1; /* total # spells starts off as 3 */
40 c[REGENCOUNTER] = 16;
41 c[ECOUNTER] = 96; /* start regeneration correctly */
42 c[SHIELD] = c[WEAR] = c[WIELD] = -1;
43 for (i = 0; i < 26; i++)
44 iven[i] = 0;
45 spelknow[0] = spelknow[1] = 1; /* he knows protection, magic missile */
46 if (c[HARDGAME] <= 0) {
47 iven[0] = OLEATHER;
48 iven[1] = ODAGGER;
49 ivenarg[1] = ivenarg[0] = c[WEAR] = 0;
50 c[WIELD] = 1;
51 }
52 playerx = rnd(MAXX - 2);
53 playery = rnd(MAXY - 2);
54 oldx = 0;
55 oldy = 25;
56 gltime = 0; /* time clock starts at zero */
57 cbak[SPELLS] = -50;
58 for (i = 0; i < 6; i++)
59 c[i] = 12; /* make the attributes, ie str, int, etc. */
60 recalc();
61 }
62
63
64 /*
65 newcavelevel(level)
66 int level;
67
68 function to enter a new level. This routine must be called anytime the
69 player changes levels. If that level is unknown it will be created.
70 A new set of monsters will be created for a new level, and existing
71 levels will get a few more monsters.
72 Note that it is here we remove genocided monsters from the present level.
73 */
74 void
75 newcavelevel(x)
76 int x;
77 {
78 int i, j;
79 if (beenhere[level])
80 savelevel(); /* put the level back into storage */
81 level = x; /* get the new level and put in working
82 * storage */
83 if (beenhere[x]) {
84 getlevel();
85 sethp(0);
86 checkgen();
87 return;
88 }
89
90 /* fill in new level */
91 for (i = 0; i < MAXY; i++)
92 for (j = 0; j < MAXX; j++)
93 know[j][i] = mitem[j][i] = 0;
94 makemaze(x);
95 makeobject(x);
96 beenhere[x] = 1;
97 sethp(1);
98 checkgen(); /* wipe out any genocided monsters */
99
100 #if WIZID
101 if (wizard || x == 0)
102 #else
103 if (x == 0)
104 #endif
105 for (j = 0; j < MAXY; j++)
106 for (i = 0; i < MAXX; i++)
107 know[i][j] = 1;
108 }
109
110 /*
111 makemaze(level)
112 int level;
113
114 subroutine to make the caverns for a given level. only walls are made.
115 */
116 static int mx, mxl, mxh, my, myl, myh, tmp2;
117
118 static void
119 makemaze(k)
120 int k;
121 {
122 int i, j, tmp;
123 int z;
124 if (k > 1 && (rnd(17) <= 4 || k == MAXLEVEL - 1 || k == MAXLEVEL + MAXVLEVEL - 1)) {
125 if (cannedlevel(k))
126 return; /* read maze from data file */
127 }
128 if (k == 0)
129 tmp = 0;
130 else
131 tmp = OWALL;
132 for (i = 0; i < MAXY; i++)
133 for (j = 0; j < MAXX; j++)
134 item[j][i] = tmp;
135 if (k == 0)
136 return;
137 eat(1, 1);
138 if (k == 1)
139 item[33][MAXY - 1] = 0; /* exit from dungeon */
140
141 /* now for open spaces -- not on level 10 */
142 if (k != MAXLEVEL - 1) {
143 tmp2 = rnd(3) + 3;
144 for (tmp = 0; tmp < tmp2; tmp++) {
145 my = rnd(11) + 2;
146 myl = my - rnd(2);
147 myh = my + rnd(2);
148 if (k < MAXLEVEL) {
149 mx = rnd(44) + 5;
150 mxl = mx - rnd(4);
151 mxh = mx + rnd(12) + 3;
152 z = 0;
153 } else {
154 mx = rnd(60) + 3;
155 mxl = mx - rnd(2);
156 mxh = mx + rnd(2);
157 z = makemonst(k);
158 }
159 for (i = mxl; i < mxh; i++)
160 for (j = myl; j < myh; j++) {
161 item[i][j] = 0;
162 if ((mitem[i][j] = z))
163 hitp[i][j] = monster[z].hitpoints;
164 }
165 }
166 }
167 if (k != MAXLEVEL - 1) {
168 my = rnd(MAXY - 2);
169 for (i = 1; i < MAXX - 1; i++)
170 item[i][my] = 0;
171 }
172 if (k > 1)
173 treasureroom(k);
174 }
175
176 /*
177 function to eat away a filled in maze
178 */
179 void
180 eat(xx, yy)
181 int xx, yy;
182 {
183 int dir, try;
184 dir = rnd(4);
185 try = 2;
186 while (try) {
187 switch (dir) {
188 case 1:
189 if (xx <= 2)
190 break; /* west */
191 if ((item[xx - 1][yy] != OWALL) || (item[xx - 2][yy] != OWALL))
192 break;
193 item[xx - 1][yy] = item[xx - 2][yy] = 0;
194 eat(xx - 2, yy);
195 break;
196
197 case 2:
198 if (xx >= MAXX - 3)
199 break; /* east */
200 if ((item[xx + 1][yy] != OWALL) || (item[xx + 2][yy] != OWALL))
201 break;
202 item[xx + 1][yy] = item[xx + 2][yy] = 0;
203 eat(xx + 2, yy);
204 break;
205
206 case 3:
207 if (yy <= 2)
208 break; /* south */
209 if ((item[xx][yy - 1] != OWALL) || (item[xx][yy - 2] != OWALL))
210 break;
211 item[xx][yy - 1] = item[xx][yy - 2] = 0;
212 eat(xx, yy - 2);
213 break;
214
215 case 4:
216 if (yy >= MAXY - 3)
217 break; /* north */
218 if ((item[xx][yy + 1] != OWALL) || (item[xx][yy + 2] != OWALL))
219 break;
220 item[xx][yy + 1] = item[xx][yy + 2] = 0;
221 eat(xx, yy + 2);
222 break;
223 };
224 if (++dir > 4) {
225 dir = 1;
226 --try;
227 }
228 }
229 }
230
231 /*
232 * function to read in a maze from a data file
233 *
234 * Format of maze data file: 1st character = # of mazes in file (ascii digit)
235 * For each maze: 18 lines (1st 17 used) 67 characters per line
236 *
237 * Special characters in maze data file:
238 *
239 * # wall D door . random monster
240 * ~ eye of larn ! cure dianthroritis
241 * - random object
242 */
243 static int
244 cannedlevel(k)
245 int k;
246 {
247 char *row;
248 int i, j;
249 int it, arg, mit, marg;
250 if (lopen(larnlevels) < 0) {
251 write(1, "Can't open the maze data file\n", 30);
252 died(-282);
253 return (0);
254 }
255 i = lgetc();
256 if (i <= '0') {
257 died(-282);
258 return (0);
259 }
260 for (i = 18 * rund(i - '0'); i > 0; i--)
261 lgetl(); /* advance to desired maze */
262 for (i = 0; i < MAXY; i++) {
263 row = lgetl();
264 for (j = 0; j < MAXX; j++) {
265 it = mit = arg = marg = 0;
266 switch (*row++) {
267 case '#':
268 it = OWALL;
269 break;
270 case 'D':
271 it = OCLOSEDDOOR;
272 arg = rnd(30);
273 break;
274 case '~':
275 if (k != MAXLEVEL - 1)
276 break;
277 it = OLARNEYE;
278 mit = rund(8) + DEMONLORD;
279 marg = monster[mit].hitpoints;
280 break;
281 case '!':
282 if (k != MAXLEVEL + MAXVLEVEL - 1)
283 break;
284 it = OPOTION;
285 arg = 21;
286 mit = DEMONLORD + 7;
287 marg = monster[mit].hitpoints;
288 break;
289 case '.':
290 if (k < MAXLEVEL)
291 break;
292 mit = makemonst(k + 1);
293 marg = monster[mit].hitpoints;
294 break;
295 case '-':
296 it = newobject(k + 1, &arg);
297 break;
298 };
299 item[j][i] = it;
300 iarg[j][i] = arg;
301 mitem[j][i] = mit;
302 hitp[j][i] = marg;
303
304 #if WIZID
305 know[j][i] = (wizard) ? 1 : 0;
306 #else
307 know[j][i] = 0;
308 #endif
309 }
310 }
311 lrclose();
312 return (1);
313 }
314
315 /*
316 function to make a treasure room on a level
317 level 10's treasure room has the eye in it and demon lords
318 level V3 has potion of cure dianthroritis and demon prince
319 */
320 static void
321 treasureroom(lv)
322 int lv;
323 {
324 int tx, ty, xsize, ysize;
325
326 for (tx = 1 + rnd(10); tx < MAXX - 10; tx += 10)
327 if ((lv == MAXLEVEL - 1) || (lv == MAXLEVEL + MAXVLEVEL - 1) || rnd(13) == 2) {
328 xsize = rnd(6) + 3;
329 ysize = rnd(3) + 3;
330 ty = rnd(MAXY - 9) + 1; /* upper left corner of room */
331 if (lv == MAXLEVEL - 1 || lv == MAXLEVEL + MAXVLEVEL - 1)
332 troom(lv, xsize, ysize, tx = tx + rnd(MAXX - 24), ty, rnd(3) + 6);
333 else
334 troom(lv, xsize, ysize, tx, ty, rnd(9));
335 }
336 }
337
338 /*
339 * subroutine to create a treasure room of any size at a given location
340 * room is filled with objects and monsters
341 * the coordinate given is that of the upper left corner of the room
342 */
343 static void
344 troom(lv, xsize, ysize, tx, ty, glyph)
345 int lv, xsize, ysize, tx, ty, glyph;
346 {
347 int i, j;
348 int tp1, tp2;
349 for (j = ty - 1; j <= ty + ysize; j++)
350 for (i = tx - 1; i <= tx + xsize; i++) /* clear out space for
351 * room */
352 item[i][j] = 0;
353 for (j = ty; j < ty + ysize; j++)
354 for (i = tx; i < tx + xsize; i++) { /* now put in the walls */
355 item[i][j] = OWALL;
356 mitem[i][j] = 0;
357 }
358 for (j = ty + 1; j < ty + ysize - 1; j++)
359 for (i = tx + 1; i < tx + xsize - 1; i++) /* now clear out
360 * interior */
361 item[i][j] = 0;
362
363 switch (rnd(2)) { /* locate the door on the treasure room */
364 case 1:
365 item[i = tx + rund(xsize)][j = ty + (ysize - 1) * rund(2)] = OCLOSEDDOOR;
366 iarg[i][j] = glyph; /* on horizontal walls */
367 break;
368 case 2:
369 item[i = tx + (xsize - 1) * rund(2)][j = ty + rund(ysize)] = OCLOSEDDOOR;
370 iarg[i][j] = glyph; /* on vertical walls */
371 break;
372 };
373
374 tp1 = playerx;
375 tp2 = playery;
376 playery = ty + (ysize >> 1);
377 if (c[HARDGAME] < 2)
378 for (playerx = tx + 1; playerx <= tx + xsize - 2; playerx += 2)
379 for (i = 0, j = rnd(6); i <= j; i++) {
380 something(lv + 2);
381 createmonster(makemonst(lv + 1));
382 }
383 else
384 for (playerx = tx + 1; playerx <= tx + xsize - 2; playerx += 2)
385 for (i = 0, j = rnd(4); i <= j; i++) {
386 something(lv + 2);
387 createmonster(makemonst(lv + 3));
388 }
389
390 playerx = tp1;
391 playery = tp2;
392 }
393
394
395 /*
396 ***********
397 MAKE_OBJECT
398 ***********
399 subroutine to create the objects in the maze for the given level
400 */
401 static void
402 makeobject(j)
403 int j;
404 {
405 int i;
406 if (j == 0) {
407 fillroom(OENTRANCE, 0); /* entrance to dungeon */
408 fillroom(ODNDSTORE, 0); /* the DND STORE */
409 fillroom(OSCHOOL, 0); /* college of Larn */
410 fillroom(OBANK, 0); /* 1st national bank of larn */
411 fillroom(OVOLDOWN, 0); /* volcano shaft to temple */
412 fillroom(OHOME, 0); /* the players home & family */
413 fillroom(OTRADEPOST, 0); /* the trading post */
414 fillroom(OLRS, 0); /* the larn revenue service */
415 return;
416 }
417 if (j == MAXLEVEL)
418 fillroom(OVOLUP, 0); /* volcano shaft up from the temple */
419
420 /* make the fixed objects in the maze STAIRS */
421 if ((j > 0) && (j != MAXLEVEL - 1) && (j != MAXLEVEL + MAXVLEVEL - 1))
422 fillroom(OSTAIRSDOWN, 0);
423 if ((j > 1) && (j != MAXLEVEL))
424 fillroom(OSTAIRSUP, 0);
425
426 /* make the random objects in the maze */
427
428 fillmroom(rund(3), OBOOK, j);
429 fillmroom(rund(3), OALTAR, 0);
430 fillmroom(rund(3), OSTATUE, 0);
431 fillmroom(rund(3), OPIT, 0);
432 fillmroom(rund(3), OFOUNTAIN, 0);
433 fillmroom(rnd(3) - 2, OIVTELETRAP, 0);
434 fillmroom(rund(2), OTHRONE, 0);
435 fillmroom(rund(2), OMIRROR, 0);
436 fillmroom(rund(2), OTRAPARROWIV, 0);
437 fillmroom(rnd(3) - 2, OIVDARTRAP, 0);
438 fillmroom(rund(3), OCOOKIE, 0);
439 if (j == 1)
440 fillmroom(1, OCHEST, j);
441 else
442 fillmroom(rund(2), OCHEST, j);
443 if ((j != MAXLEVEL - 1) && (j != MAXLEVEL + MAXVLEVEL - 1))
444 fillmroom(rund(2), OIVTRAPDOOR, 0);
445 if (j <= 10) {
446 fillmroom((rund(2)), ODIAMOND, rnd(10 * j + 1) + 10);
447 fillmroom(rund(2), ORUBY, rnd(6 * j + 1) + 6);
448 fillmroom(rund(2), OEMERALD, rnd(4 * j + 1) + 4);
449 fillmroom(rund(2), OSAPPHIRE, rnd(3 * j + 1) + 2);
450 }
451 for (i = 0; i < rnd(4) + 3; i++)
452 fillroom(OPOTION, newpotion()); /* make a POTION */
453 for (i = 0; i < rnd(5) + 3; i++)
454 fillroom(OSCROLL, newscroll()); /* make a SCROLL */
455 for (i = 0; i < rnd(12) + 11; i++)
456 fillroom(OGOLDPILE, 12 * rnd(j + 1) + (j << 3) + 10); /* make GOLD */
457 if (j == 5)
458 fillroom(OBANK2, 0); /* branch office of the bank */
459 froom(2, ORING, 0); /* a ring mail */
460 froom(1, OSTUDLEATHER, 0); /* a studded leather */
461 froom(3, OSPLINT, 0); /* a splint mail */
462 froom(5, OSHIELD, rund(3)); /* a shield */
463 froom(2, OBATTLEAXE, rund(3)); /* a battle axe */
464 froom(5, OLONGSWORD, rund(3)); /* a long sword */
465 froom(5, OFLAIL, rund(3)); /* a flail */
466 froom(4, OREGENRING, rund(3)); /* ring of regeneration */
467 froom(1, OPROTRING, rund(3)); /* ring of protection */
468 froom(2, OSTRRING, 4); /* ring of strength + 4 */
469 froom(7, OSPEAR, rnd(5)); /* a spear */
470 froom(3, OORBOFDRAGON, 0); /* orb of dragon slaying */
471 froom(4, OSPIRITSCARAB, 0); /* scarab of negate spirit */
472 froom(4, OCUBEofUNDEAD, 0); /* cube of undead control */
473 froom(2, ORINGOFEXTRA, 0); /* ring of extra regen */
474 froom(3, ONOTHEFT, 0); /* device of antitheft */
475 froom(2, OSWORDofSLASHING, 0); /* sword of slashing */
476 if (c[BESSMANN] == 0) {
477 froom(4, OHAMMER, 0); /* Bessman's flailing hammer */
478 c[BESSMANN] = 1;
479 }
480 if (c[HARDGAME] < 3 || (rnd(4) == 3)) {
481 if (j > 3) {
482 froom(3, OSWORD, 3); /* sunsword + 3 */
483 froom(5, O2SWORD, rnd(4)); /* a two handed sword */
484 froom(3, OBELT, 4); /* belt of striking */
485 froom(3, OENERGYRING, 3); /* energy ring */
486 froom(4, OPLATE, 5); /* platemail + 5 */
487 }
488 }
489 }
490
491 /*
492 subroutine to fill in a number of objects of the same kind
493 */
494
495 static void
496 fillmroom(n, what, arg)
497 int n, arg;
498 char what;
499 {
500 int i;
501 for (i = 0; i < n; i++)
502 fillroom(what, arg);
503 }
504
505 static void
506 froom(int n, int theitem, int arg)
507 {
508 if (rnd(151) < n)
509 fillroom(theitem, arg);
510 }
511
512 /*
513 subroutine to put an object into an empty room
514 * uses a random walk
515 */
516 static void
517 fillroom(what, arg)
518 int arg;
519 char what;
520 {
521 int x, y;
522
523 #ifdef EXTRA
524 c[FILLROOM]++;
525 #endif
526
527 x = rnd(MAXX - 2);
528 y = rnd(MAXY - 2);
529 while (item[x][y]) {
530
531 #ifdef EXTRA
532 c[RANDOMWALK]++;/* count up these random walks */
533 #endif
534
535 x += rnd(3) - 2;
536 y += rnd(3) - 2;
537 if (x > MAXX - 2)
538 x = 1;
539 if (x < 1)
540 x = MAXX - 2;
541 if (y > MAXY - 2)
542 y = 1;
543 if (y < 1)
544 y = MAXY - 2;
545 }
546 item[x][y] = what;
547 iarg[x][y] = arg;
548 }
549
550 /*
551 subroutine to put monsters into an empty room without walls or other
552 monsters
553 */
554 int
555 fillmonst(what)
556 int what;
557 {
558 int x, y, trys;
559 for (trys = 5; trys > 0; --trys) { /* max # of creation attempts */
560 x = rnd(MAXX - 2);
561 y = rnd(MAXY - 2);
562 if ((item[x][y] == 0) && (mitem[x][y] == 0) && ((playerx != x) || (playery != y))) {
563 mitem[x][y] = what;
564 know[x][y] = 0;
565 hitp[x][y] = monster[what].hitpoints;
566 return (0);
567 }
568 }
569 return (-1); /* creation failure */
570 }
571
572 /*
573 creates an entire set of monsters for a level
574 must be done when entering a new level
575 if sethp(1) then wipe out old monsters else leave them there
576 */
577 static void
578 sethp(flg)
579 int flg;
580 {
581 int i, j;
582 if (flg)
583 for (i = 0; i < MAXY; i++)
584 for (j = 0; j < MAXX; j++)
585 stealth[j][i] = 0;
586 if (level == 0) {
587 c[TELEFLAG] = 0;
588 return;
589 } /* if teleported and found level 1 then know
590 * level we are on */
591 if (flg)
592 j = rnd(12) + 2 + (level >> 1);
593 else
594 j = (level >> 1) + 1;
595 for (i = 0; i < j; i++)
596 fillmonst(makemonst(level));
597 positionplayer();
598 }
599
600 /*
601 * Function to destroy all genocided monsters on the present level
602 */
603 static void
604 checkgen(void)
605 {
606 int x, y;
607 for (y = 0; y < MAXY; y++)
608 for (x = 0; x < MAXX; x++)
609 if (monster[mitem[x][y]].genocided)
610 mitem[x][y] = 0; /* no more monster */
611 }