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