1 /* $NetBSD: create.c,v 1.6 1997/10/18 20:03:09 christos 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.6 1997/10/18 20:03:09 christos Exp $"); 8 #endif /* not lint */ 9 10 #include "header.h" 11 #include "extern.h" 12 #include <unistd.h> 13 static void fillroom __P((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 } 601