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