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