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" 5 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); 16 17 /* 18 makeplayer() 19 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 22 */ 23 void 24 makeplayer(void) 25 { 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; 43 } 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(); 53 } 54 55 /* 56 newcavelevel(level) 57 int level; 58 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. 64 */ 65 void 66 newcavelevel(int x) 67 { 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; 80 } 81 makemaze(x); 82 makeobject(x); 83 beenhere[x] = 1; 84 sethp(1); 85 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 */ 96 } 97 98 /* 99 makemaze(level) 100 int level; 101 102 subroutine to make the caverns for a given level. only walls are made. 103 */ 104 static int mx, mxl, mxh, my, myl, myh, tmp2; 105 106 static void 107 makemaze(int k) 108 { 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; 126 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); 144 } 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; 150 } 151 } 152 } 153 if (k != MAXLEVEL - 1) { 154 my = rnd(MAXY - 2); 155 for (i = 1; i < MAXX - 1; i++) 156 item[i][my] = 0; 157 } 158 if (k > 1) 159 treasureroom(k); 160 } 161 162 /* 163 function to eat away a filled in maze 164 */ 165 void 166 eat(int xx, int yy) 167 { 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; 181 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; 190 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; 199 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; 208 } 209 if (++dir > 4) { 210 dir = 1; 211 --try; 212 } 213 } 214 } 215 216 /* 217 * function to read in a maze from a data file 218 * 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 221 * 222 * Special characters in maze data file: 223 * 224 * # wall D door . random monster 225 * ~ eye of larn ! cure dianthroritis 226 * - random object 227 */ 228 static int 229 cannedlevel(int k) 230 { 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); 238 } 239 i = lgetc(); 240 if (i <= '0') { 241 died(-282); 242 return (0); 243 } 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; 282 } 283 item[j][i] = it; 284 iarg[j][i] = arg; 285 mitem[j][i] = mit; 286 hitp[j][i] = marg; 287 288 #if WIZID 289 know[j][i] = (wizard) ? 1 : 0; 290 #else 291 know[j][i] = 0; 292 #endif 293 } 294 } 295 lrclose(); 296 return (1); 297 } 298 299 /* 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 303 */ 304 static void 305 treasureroom(int lv) 306 { 307 int tx, ty, xsize, ysize; 308 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)); 318 } 319 } 320 321 /* 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 325 */ 326 static void 327 troom(int lv, int xsize, int ysize, int tx, int ty, int glyph) 328 { 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; 338 } 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; 342 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; 352 } 353 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)); 362 } 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)); 368 } 369 370 playerx = tp1; 371 playery = tp2; 372 } 373 374 /* 375 *********** 376 MAKE_OBJECT 377 *********** 378 subroutine to create the objects in the maze for the given level 379 */ 380 static void 381 makeobject(int j) 382 { 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; 394 } 395 if (j == MAXLEVEL) /* volcano shaft up from the temple */ 396 fillroom(OVOLUP, 0); 397 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); 403 404 /* make the random objects in the maze */ 405 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); 428 } 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; 457 } 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 */ 465 } 466 } 467 } 468 469 /* 470 subroutine to fill in a number of objects of the same kind 471 */ 472 static void 473 fillmroom(int n, char what, int arg) 474 { 475 int i; 476 for (i = 0; i < n; i++) 477 fillroom(what, arg); 478 } 479 480 static void 481 froom(int n, char itm, int arg) 482 { 483 if (rnd(151) < n) 484 fillroom(itm, arg); 485 } 486 487 /* 488 subroutine to put an object into an empty room 489 * uses a random walk 490 */ 491 static void 492 fillroom(char what, int arg) 493 { 494 int x, y; 495 496 #ifdef EXTRA 497 c[FILLROOM]++; 498 #endif 499 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 506 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; 517 } 518 item[x][y] = what; 519 iarg[x][y] = arg; 520 } 521 522 /* 523 subroutine to put monsters into an empty room without walls or other 524 monsters 525 */ 526 int 527 fillmonst(char what) 528 { 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); 539 } 540 } 541 return (-1); /* creation failure */ 542 } 543 544 /* 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 548 */ 549 static void 550 sethp(int flg) 551 { 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; 560 } 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(); 569 } 570 571 /* 572 * Function to destroy all genocided monsters on the present level 573 */ 574 static void 575 checkgen(void) 576 { 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 */ 582 } 583