Make this compile with gcc40: rename variables so that they don't collide
[dragonfly.git] / games / larn / create.c
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 \f
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 \f
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         }