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