Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / games / larn / create.c
blob7b1e8d8e25159ab91f34f4238aec4f36b2d96ffb
1 /* $NetBSD: create.c,v 1.10 2008/02/03 19:20:40 dholland Exp $ */
3 /* create.c Larn is copyrighted 1986 by Noah Morgan. */
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 */
10 #include "header.h"
11 #include "extern.h"
12 #include <unistd.h>
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);
26 makeplayer()
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
31 void
32 makeplayer()
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;
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();
65 newcavelevel(level)
66 int level;
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.
74 void
75 newcavelevel(x)
76 int x;
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;
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 */
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;
111 makemaze(level)
112 int level;
114 subroutine to make the caverns for a given level. only walls are made.
116 static int mx, mxl, mxh, my, myl, myh, tmp2;
118 static void
119 makemaze(k)
120 int k;
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 */
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 */
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);
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;
167 if (k != MAXLEVEL - 1) {
168 my = rnd(MAXY - 2);
169 for (i = 1; i < MAXX - 1; i++)
170 item[i][my] = 0;
172 if (k > 1)
173 treasureroom(k);
177 function to eat away a filled in maze
179 void
180 eat(xx, yy)
181 int xx, yy;
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;
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;
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;
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;
224 if (++dir > 4) {
225 dir = 1;
226 --try;
232 * function to read in a maze from a data file
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
237 * Special characters in maze data file:
239 * # wall D door . random monster
240 * ~ eye of larn ! cure dianthroritis
241 * - random object
243 static int
244 cannedlevel(k)
245 int k;
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);
255 i = lgetc();
256 if (i <= '0') {
257 died(-282);
258 return (0);
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;
299 item[j][i] = it;
300 iarg[j][i] = arg;
301 mitem[j][i] = mit;
302 hitp[j][i] = marg;
304 #if WIZID
305 know[j][i] = (wizard) ? 1 : 0;
306 #else
307 know[j][i] = 0;
308 #endif
311 lrclose();
312 return (1);
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
320 static void
321 treasureroom(lv)
322 int lv;
324 int tx, ty, xsize, ysize;
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));
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
343 static void
344 troom(lv, xsize, ysize, tx, ty, glyph)
345 int lv, xsize, ysize, tx, ty, glyph;
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;
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;
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;
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));
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));
390 playerx = tp1;
391 playery = tp2;
396 ***********
397 MAKE_OBJECT
398 ***********
399 subroutine to create the objects in the maze for the given level
401 static void
402 makeobject(j)
403 int j;
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;
417 if (j == MAXLEVEL)
418 fillroom(OVOLUP, 0); /* volcano shaft up from the temple */
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);
426 /* make the random objects in the maze */
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);
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;
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 */
492 subroutine to fill in a number of objects of the same kind
495 static void
496 fillmroom(n, what, arg)
497 int n, arg;
498 char what;
500 int i;
501 for (i = 0; i < n; i++)
502 fillroom(what, arg);
505 static void
506 froom(int n, int theitem, int arg)
508 if (rnd(151) < n)
509 fillroom(theitem, arg);
513 subroutine to put an object into an empty room
514 * uses a random walk
516 static void
517 fillroom(what, arg)
518 int arg;
519 char what;
521 int x, y;
523 #ifdef EXTRA
524 c[FILLROOM]++;
525 #endif
527 x = rnd(MAXX - 2);
528 y = rnd(MAXY - 2);
529 while (item[x][y]) {
531 #ifdef EXTRA
532 c[RANDOMWALK]++;/* count up these random walks */
533 #endif
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;
546 item[x][y] = what;
547 iarg[x][y] = arg;
551 subroutine to put monsters into an empty room without walls or other
552 monsters
555 fillmonst(what)
556 int what;
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);
569 return (-1); /* creation failure */
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
577 static void
578 sethp(flg)
579 int flg;
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();
601 * Function to destroy all genocided monsters on the present level
603 static void
604 checkgen(void)
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 */