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