test some more
[dragonfly.git] / games / larn / create.c
blob6a1c85159b4a5a19fe7ecc2398a66312853448f7
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"
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);
18 makeplayer()
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
23 void
24 makeplayer(void)
26 int i;
27 scbr(); 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; c[ECOUNTER]=96; /*start regeneration correctly*/
32 c[SHIELD] = c[WEAR] = c[WIELD] = -1;
33 for (i=0; i<26; i++) iven[i]=0;
34 spelknow[0]=spelknow[1]=1; /*he knows protection, magic missile*/
35 if (c[HARDGAME]<=0)
37 iven[0]=OLEATHER; iven[1]=ODAGGER;
38 ivenarg[1]=ivenarg[0]=c[WEAR]=0; c[WIELD]=1;
40 playerx=rnd(MAXX-2); playery=rnd(MAXY-2);
41 oldx=0; oldy=25;
42 gtime=0; /* time clock starts at zero */
43 cbak[SPELLS] = -50;
44 for (i=0; i<6; i++) c[i]=12; /* make the attributes, ie str, int, etc. */
45 recalc();
49 newcavelevel(level)
50 int level;
52 function to enter a new level. This routine must be called anytime the
53 player changes levels. If that level is unknown it will be created.
54 A new set of monsters will be created for a new level, and existing
55 levels will get a few more monsters.
56 Note that it is here we remove genocided monsters from the present level.
58 void
59 newcavelevel(int x)
61 int i,j;
62 if (beenhere[(int)level]) savelevel(); /* put the level back into storage */
63 level = x; /* get the new level and put in working storage */
64 if (beenhere[x]==0) for (i=0; i<MAXY; i++) for (j=0; j<MAXX; j++) know[j][i]=mitem[j][i]=0;
65 else { getlevel(); sethp(0); goto chgn; }
66 makemaze(x); makeobject(x); beenhere[x]=1; sethp(1);
68 #if WIZID
69 if (wizard || x==0)
70 #else
71 if (x==0)
72 #endif
74 for (j=0; j<MAXY; j++)
75 for (i=0; i<MAXX; i++)
76 know[i][j]=1;
77 chgn: checkgen(); /* wipe out any genocided monsters */
81 makemaze(level)
82 int level;
84 subroutine to make the caverns for a given level. only walls are made.
86 static int mx,mxl,mxh,my,myl,myh,tmp2;
88 static void
89 makemaze(int k)
91 int i,j,tmp;
92 int z;
93 if (k > 1 && (rnd(17)<=4 || k==MAXLEVEL-1 || k==MAXLEVEL+MAXVLEVEL-1))
95 if (cannedlevel(k)) return; /* read maze from data file */
97 if (k==0) tmp=0; else tmp=OWALL;
98 for (i=0; i<MAXY; i++) for (j=0; j<MAXX; j++) item[j][i]=tmp;
99 if (k==0) return; eat(1,1);
100 if (k==1) item[33][MAXY-1]=0; /* exit from dungeon */
102 /* now for open spaces -- not on level 10 */
103 if (k != MAXLEVEL-1)
105 tmp2 = rnd(3)+3;
106 for (tmp=0; tmp<tmp2; tmp++)
108 my = rnd(11)+2; myl = my - rnd(2); myh = my + rnd(2);
109 if (k < MAXLEVEL)
111 mx = rnd(44)+5; mxl = mx - rnd(4); mxh = mx + rnd(12)+3;
112 z=0;
114 else
116 mx = rnd(60)+3; mxl = mx - rnd(2); mxh = mx + rnd(2);
117 z = makemonst(k);
119 for (i=mxl; i<mxh; i++) for (j=myl; j<myh; j++)
120 { item[i][j]=0;
121 if ((mitem[i][j]=z)) hitp[i][j]=monster[z].hitpoints;
125 if (k!=MAXLEVEL-1) { my=rnd(MAXY-2); for (i=1; i<MAXX-1; i++) item[i][my] = 0; }
126 if (k>1) treasureroom(k);
130 function to eat away a filled in maze
132 void
133 eat(int xx, int yy)
135 int dir,try;
136 dir = rnd(4); try=2;
137 while (try)
139 switch(dir)
141 case 1: if (xx <= 2) break; /* west */
142 if ((item[xx-1][yy]!=OWALL) || (item[xx-2][yy]!=OWALL)) break;
143 item[xx-1][yy] = item[xx-2][yy] = 0;
144 eat(xx-2,yy); break;
146 case 2: if (xx >= MAXX-3) break; /* east */
147 if ((item[xx+1][yy]!=OWALL) || (item[xx+2][yy]!=OWALL)) break;
148 item[xx+1][yy] = item[xx+2][yy] = 0;
149 eat(xx+2,yy); break;
151 case 3: if (yy <= 2) break; /* south */
152 if ((item[xx][yy-1]!=OWALL) || (item[xx][yy-2]!=OWALL)) break;
153 item[xx][yy-1] = item[xx][yy-2] = 0;
154 eat(xx,yy-2); break;
156 case 4: if (yy >= MAXY-3 ) break; /* north */
157 if ((item[xx][yy+1]!=OWALL) || (item[xx][yy+2]!=OWALL)) break;
158 item[xx][yy+1] = item[xx][yy+2] = 0;
159 eat(xx,yy+2); break;
161 if (++dir > 4) { dir=1; --try; }
166 * function to read in a maze from a data file
168 * Format of maze data file: 1st character = # of mazes in file (ascii digit)
169 * For each maze: 18 lines (1st 17 used) 67 characters per line
171 * Special characters in maze data file:
173 * # wall D door . random monster
174 * ~ eye of larn ! cure dianthroritis
175 * - random object
177 static int
178 cannedlevel(int k)
180 char *row;
181 int i,j;
182 int it,arg,mit,marg;
183 if (lopen(larnlevels)<0)
185 write(1,"Can't open the maze data file\n",30); died(-282); return(0);
187 i=lgetc(); if (i<='0') { died(-282); return(0); }
188 for (i=18*rund(i-'0'); i>0; i--) lgetl(); /* advance to desired maze */
189 for (i=0; i<MAXY; i++)
191 row = lgetl();
192 for (j=0; j<MAXX; j++)
194 it = mit = arg = marg = 0;
195 switch(*row++)
197 case '#': it = OWALL; break;
198 case 'D': it = OCLOSEDDOOR; arg = rnd(30); break;
199 case '~': if (k!=MAXLEVEL-1) break;
200 it = OLARNEYE;
201 mit = rund(8)+DEMONLORD;
202 marg = monster[mit].hitpoints; break;
203 case '!': if (k!=MAXLEVEL+MAXVLEVEL-1) break;
204 it = OPOTION; arg = 21;
205 mit = DEMONLORD+7;
206 marg = monster[mit].hitpoints; break;
207 case '.': if (k<MAXLEVEL) break;
208 mit = makemonst(k+1);
209 marg = monster[mit].hitpoints; break;
210 case '-': it = newobject(k+1,&arg); break;
212 item[j][i] = it; iarg[j][i] = arg;
213 mitem[j][i] = mit; hitp[j][i] = marg;
215 #if WIZID
216 know[j][i] = (wizard) ? 1 : 0;
217 #else
218 know[j][i] = 0;
219 #endif
222 lrclose();
223 return(1);
227 function to make a treasure room on a level
228 level 10's treasure room has the eye in it and demon lords
229 level V3 has potion of cure dianthroritis and demon prince
231 static void
232 treasureroom(int lv)
234 int tx,ty,xsize,ysize;
236 for (tx=1+rnd(10); tx<MAXX-10; tx+=10)
237 if ( (lv==MAXLEVEL-1) || (lv==MAXLEVEL+MAXVLEVEL-1) || rnd(13)==2)
239 xsize = rnd(6)+3; ysize = rnd(3)+3;
240 ty = rnd(MAXY-9)+1; /* upper left corner of room */
241 if (lv==MAXLEVEL-1 || lv==MAXLEVEL+MAXVLEVEL-1)
242 troom(lv,xsize,ysize,tx=tx+rnd(MAXX-24),ty,rnd(3)+6);
243 else troom(lv,xsize,ysize,tx,ty,rnd(9));
248 * subroutine to create a treasure room of any size at a given location
249 * room is filled with objects and monsters
250 * the coordinate given is that of the upper left corner of the room
252 static void
253 troom(int lv, int xsize, int ysize, int tx, int ty, int glyph)
255 int i,j;
256 int tp1,tp2;
257 for (j=ty-1; j<=ty+ysize; j++)
258 for (i=tx-1; i<=tx+xsize; i++) /* clear out space for room */
259 item[i][j]=0;
260 for (j=ty; j<ty+ysize; j++)
261 for (i=tx; i<tx+xsize; i++) /* now put in the walls */
263 item[i][j]=OWALL; mitem[i][j]=0;
265 for (j=ty+1; j<ty+ysize-1; j++)
266 for (i=tx+1; i<tx+xsize-1; i++) /* now clear out interior */
267 item[i][j]=0;
269 switch(rnd(2)) /* locate the door on the treasure room */
271 case 1: item[i=tx+rund(xsize)][j=ty+(ysize-1)*rund(2)]=OCLOSEDDOOR;
272 iarg[i][j] = glyph; /* on horizontal walls */
273 break;
274 case 2: item[i=tx+(xsize-1)*rund(2)][j=ty+rund(ysize)]=OCLOSEDDOOR;
275 iarg[i][j] = glyph; /* on vertical walls */
276 break;
279 tp1=playerx; tp2=playery; playery=ty+(ysize>>1);
280 if (c[HARDGAME]<2)
281 for (playerx=tx+1; playerx<=tx+xsize-2; playerx+=2)
282 for (i=0, j=rnd(6); i<=j; i++)
283 { something(lv+2); createmonster(makemonst(lv+1)); }
284 else
285 for (playerx=tx+1; playerx<=tx+xsize-2; playerx+=2)
286 for (i=0, j=rnd(4); i<=j; i++)
287 { something(lv+2); createmonster(makemonst(lv+3)); }
289 playerx=tp1; playery=tp2;
293 ***********
294 MAKE_OBJECT
295 ***********
296 subroutine to create the objects in the maze for the given level
298 static void
299 makeobject(int j)
301 int i;
302 if (j==0)
304 fillroom(OENTRANCE,0); /* entrance to dungeon */
305 fillroom(ODNDSTORE,0); /* the DND STORE */
306 fillroom(OSCHOOL,0); /* college of Larn */
307 fillroom(OBANK,0); /* 1st national bank of larn */
308 fillroom(OVOLDOWN,0); /* volcano shaft to temple */
309 fillroom(OHOME,0); /* the players home & family */
310 fillroom(OTRADEPOST,0); /* the trading post */
311 fillroom(OLRS,0); /* the larn revenue service */
312 return;
315 if (j==MAXLEVEL) fillroom(OVOLUP,0); /* volcano shaft up from the temple */
317 /* make the fixed objects in the maze STAIRS */
318 if ((j>0) && (j != MAXLEVEL-1) && (j != MAXLEVEL+MAXVLEVEL-1))
319 fillroom(OSTAIRSDOWN,0);
320 if ((j > 1) && (j != MAXLEVEL)) fillroom(OSTAIRSUP,0);
322 /* make the random objects in the maze */
324 fillmroom(rund(3),OBOOK,j); fillmroom(rund(3),OALTAR,0);
325 fillmroom(rund(3),OSTATUE,0); fillmroom(rund(3),OPIT,0);
326 fillmroom(rund(3),OFOUNTAIN,0); fillmroom( rnd(3)-2,OIVTELETRAP,0);
327 fillmroom(rund(2),OTHRONE,0); fillmroom(rund(2),OMIRROR,0);
328 fillmroom(rund(2),OTRAPARROWIV,0); fillmroom( rnd(3)-2,OIVDARTRAP,0);
329 fillmroom(rund(3),OCOOKIE,0);
330 if (j==1) fillmroom(1,OCHEST,j);
331 else fillmroom(rund(2),OCHEST,j);
332 if ((j != MAXLEVEL-1) && (j != MAXLEVEL+MAXVLEVEL-1))
333 fillmroom(rund(2),OIVTRAPDOOR,0);
334 if (j<=10)
336 fillmroom((rund(2)),ODIAMOND,rnd(10*j+1)+10);
337 fillmroom(rund(2),ORUBY,rnd(6*j+1)+6);
338 fillmroom(rund(2),OEMERALD,rnd(4*j+1)+4);
339 fillmroom(rund(2),OSAPPHIRE,rnd(3*j+1)+2);
341 for (i=0; i<rnd(4)+3; i++)
342 fillroom(OPOTION,newpotion()); /* make a POTION */
343 for (i=0; i<rnd(5)+3; i++)
344 fillroom(OSCROLL,newscroll()); /* make a SCROLL */
345 for (i=0; i<rnd(12)+11; i++)
346 fillroom(OGOLDPILE,12*rnd(j+1)+(j<<3)+10); /* make GOLD */
347 if (j==5) fillroom(OBANK2,0); /* branch office of the bank */
348 froom(2,ORING,0); /* a ring mail */
349 froom(1,OSTUDLEATHER,0); /* a studded leather */
350 froom(3,OSPLINT,0); /* a splint mail */
351 froom(5,OSHIELD,rund(3)); /* a shield */
352 froom(2,OBATTLEAXE,rund(3)); /* a battle axe */
353 froom(5,OLONGSWORD,rund(3)); /* a long sword */
354 froom(5,OFLAIL,rund(3)); /* a flail */
355 froom(4,OREGENRING,rund(3)); /* ring of regeneration */
356 froom(1,OPROTRING,rund(3)); /* ring of protection */
357 froom(2,OSTRRING,4); /* ring of strength + 4 */
358 froom(7,OSPEAR,rnd(5)); /* a spear */
359 froom(3,OORBOFDRAGON,0); /* orb of dragon slaying*/
360 froom(4,OSPIRITSCARAB,0); /*scarab of negate spirit*/
361 froom(4,OCUBEofUNDEAD,0); /* cube of undead control */
362 froom(2,ORINGOFEXTRA,0); /* ring of extra regen */
363 froom(3,ONOTHEFT,0); /* device of antitheft */
364 froom(2,OSWORDofSLASHING,0); /* sword of slashing */
365 if (c[BESSMANN]==0)
367 froom(4,OHAMMER,0);/*Bessman's flailing hammer*/ c[BESSMANN]=1;
369 if (c[HARDGAME]<3 || (rnd(4)==3))
371 if (j>3)
373 froom(3,OSWORD,3); /* sunsword + 3 */
374 froom(5,O2SWORD,rnd(4)); /* a two handed sword */
375 froom(3,OBELT,4); /* belt of striking */
376 froom(3,OENERGYRING,3); /* energy ring */
377 froom(4,OPLATE,5); /* platemail + 5 */
383 subroutine to fill in a number of objects of the same kind
385 static void
386 fillmroom(int n, char what, int arg)
388 int i;
389 for (i=0; i<n; i++) fillroom(what,arg);
392 static void
393 froom(int n, char itm, int arg)
394 { if (rnd(151) < n) fillroom(itm,arg); }
397 subroutine to put an object into an empty room
398 * uses a random walk
400 static void
401 fillroom(char what, int arg)
403 int x,y;
405 #ifdef EXTRA
406 c[FILLROOM]++;
407 #endif
409 x=rnd(MAXX-2); y=rnd(MAXY-2);
410 while (item[x][y])
413 #ifdef EXTRA
414 c[RANDOMWALK]++; /* count up these random walks */
415 #endif
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;
421 item[x][y]=what; iarg[x][y]=arg;
425 subroutine to put monsters into an empty room without walls or other
426 monsters
429 fillmonst(char what)
431 int x,y,trys;
432 for (trys=5; trys>0; --trys) /* max # of creation attempts */
434 x=rnd(MAXX-2); y=rnd(MAXY-2);
435 if ((item[x][y]==0) && (mitem[x][y]==0) && ((playerx!=x) || (playery!=y)))
437 mitem[x][y] = what; know[x][y]=0;
438 hitp[x][y] = monster[(int)what].hitpoints; return(0);
441 return(-1); /* creation failure */
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
449 static void
450 sethp(int flg)
452 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();
461 * Function to destroy all genocided monsters on the present level
463 static void
464 checkgen(void)
466 int x,y;
467 for (y=0; y<MAXY; y++)
468 for (x=0; x<MAXX; x++)
469 if (monster[(int)mitem[x][y]].genocided)
470 mitem[x][y]=0; /* no more monster */