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