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