1 /* $NetBSD: create.c,v 1.11 2008/02/03 19:29:50 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.11 2008/02/03 19:29:50 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() 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(x) 76 int x; 77 { 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; 88 } 89 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 */ 99 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; 108 } 109 110 /* 111 makemaze(level) 112 int level; 113 114 subroutine to make the caverns for a given level. only walls are made. 115 */ 116 static int mx, mxl, mxh, my, myl, myh, tmp2; 117 118 static void 119 makemaze(k) 120 int k; 121 { 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 */ 127 } 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 */ 140 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); 158 } 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; 164 } 165 } 166 } 167 if (k != MAXLEVEL - 1) { 168 my = rnd(MAXY - 2); 169 for (i = 1; i < MAXX - 1; i++) 170 item[i][my] = 0; 171 } 172 if (k > 1) 173 treasureroom(k); 174 } 175 176 /* 177 function to eat away a filled in maze 178 */ 179 void 180 eat(xx, yy) 181 int xx, yy; 182 { 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; 196 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; 205 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; 214 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; 223 }; 224 if (++dir > 4) { 225 dir = 1; 226 --try; 227 } 228 } 229 } 230 231 /* 232 * function to read in a maze from a data file 233 * 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 236 * 237 * Special characters in maze data file: 238 * 239 * # wall D door . random monster 240 * ~ eye of larn ! cure dianthroritis 241 * - random object 242 */ 243 static int 244 cannedlevel(k) 245 int k; 246 { 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); 254 } 255 i = lgetc(); 256 if (i <= '0') { 257 died(-282); 258 return (0); 259 } 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; 298 }; 299 item[j][i] = it; 300 iarg[j][i] = arg; 301 mitem[j][i] = mit; 302 hitp[j][i] = marg; 303 304 #if WIZID 305 know[j][i] = (wizard) ? 1 : 0; 306 #else 307 know[j][i] = 0; 308 #endif 309 } 310 } 311 lrclose(); 312 return (1); 313 } 314 315 /* 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 319 */ 320 static void 321 treasureroom(lv) 322 int lv; 323 { 324 int tx, ty, xsize, ysize; 325 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)); 335 } 336 } 337 338 /* 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 342 */ 343 static void 344 troom(lv, xsize, ysize, tx, ty, glyph) 345 int lv, xsize, ysize, tx, ty, glyph; 346 { 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; 357 } 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; 362 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; 372 }; 373 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)); 382 } 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)); 388 } 389 390 playerx = tp1; 391 playery = tp2; 392 } 393 394 395 /* 396 *********** 397 MAKE_OBJECT 398 *********** 399 subroutine to create the objects in the maze for the given level 400 */ 401 static void 402 makeobject(j) 403 int j; 404 { 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; 416 } 417 if (j == MAXLEVEL) 418 fillroom(OVOLUP, 0); /* volcano shaft up from the temple */ 419 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); 425 426 /* make the random objects in the maze */ 427 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); 450 } 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; 479 } 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 */ 487 } 488 } 489 } 490 491 /* 492 subroutine to fill in a number of objects of the same kind 493 */ 494 495 static void 496 fillmroom(n, what, arg) 497 int n, arg; 498 char what; 499 { 500 int i; 501 for (i = 0; i < n; i++) 502 fillroom(what, arg); 503 } 504 505 static void 506 froom(int n, int theitem, int arg) 507 { 508 if (rnd(151) < n) 509 fillroom(theitem, arg); 510 } 511 512 /* 513 subroutine to put an object into an empty room 514 * uses a random walk 515 */ 516 static void 517 fillroom(what, arg) 518 int arg; 519 char what; 520 { 521 int x, y; 522 523 #ifdef EXTRA 524 c[FILLROOM]++; 525 #endif 526 527 x = rnd(MAXX - 2); 528 y = rnd(MAXY - 2); 529 while (item[x][y]) { 530 531 #ifdef EXTRA 532 c[RANDOMWALK]++;/* count up these random walks */ 533 #endif 534 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; 545 } 546 item[x][y] = what; 547 iarg[x][y] = arg; 548 } 549 550 /* 551 subroutine to put monsters into an empty room without walls or other 552 monsters 553 */ 554 int 555 fillmonst(what) 556 int what; 557 { 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); 567 } 568 } 569 return (-1); /* creation failure */ 570 } 571 572 /* 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 576 */ 577 static void 578 sethp(flg) 579 int flg; 580 { 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(); 598 } 599 600 /* 601 * Function to destroy all genocided monsters on the present level 602 */ 603 static void 604 checkgen(void) 605 { 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 */ 611 } 612