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