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