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