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 $ */
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);
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
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*/
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);
42 gtime
=0; /* time clock starts at zero */
44 for (i
=0; i
<6; i
++) c
[i
]=12; /* make the attributes, ie str, int, etc. */
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.
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);
74 for (j
=0; j
<MAXY
; j
++)
75 for (i
=0; i
<MAXX
; i
++)
77 chgn
: checkgen(); /* wipe out any genocided monsters */
84 subroutine to make the caverns for a given level. only walls are made.
86 static int mx
,mxl
,mxh
,my
,myl
,myh
,tmp2
;
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 */
106 for (tmp
=0; tmp
<tmp2
; tmp
++)
108 my
= rnd(11)+2; myl
= my
- rnd(2); myh
= my
+ rnd(2);
111 mx
= rnd(44)+5; mxl
= mx
- rnd(4); mxh
= mx
+ rnd(12)+3;
116 mx
= rnd(60)+3; mxl
= mx
- rnd(2); mxh
= mx
+ rnd(2);
119 for (i
=mxl
; i
<mxh
; i
++) for (j
=myl
; j
<myh
; j
++)
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
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;
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;
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;
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;
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
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
++)
192 for (j
=0; j
<MAXX
; j
++)
194 it
= mit
= arg
= marg
= 0;
197 case '#': it
= OWALL
; break;
198 case 'D': it
= OCLOSEDDOOR
; arg
= rnd(30); break;
199 case '~': if (k
!=MAXLEVEL
-1) break;
201 mit
= rund(8)+DEMONLORD
;
202 marg
= monster
[mit
].hitpoints
; break;
203 case '!': if (k
!=MAXLEVEL
+MAXVLEVEL
-1) break;
204 it
= OPOTION
; arg
= 21;
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
;
216 know
[j
][i
] = (wizard
) ? 1 : 0;
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
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
253 troom(int lv
, int xsize
, int ysize
, int tx
, int ty
, int glyph
)
257 for (j
=ty
-1; j
<=ty
+ysize
; j
++)
258 for (i
=tx
-1; i
<=tx
+xsize
; i
++) /* clear out space for room */
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 */
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 */
274 case 2: item
[i
=tx
+(xsize
-1)*rund(2)][j
=ty
+rund(ysize
)]=OCLOSEDDOOR
;
275 iarg
[i
][j
] = glyph
; /* on vertical walls */
279 tp1
=playerx
; tp2
=playery
; playery
=ty
+(ysize
>>1);
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)); }
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
;
296 subroutine to create the objects in the maze for the given level
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 */
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);
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 */
367 froom(4,OHAMMER
,0);/*Bessman's flailing hammer*/ c
[BESSMANN
]=1;
369 if (c
[HARDGAME
]<3 || (rnd(4)==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
386 fillmroom(int n
, char what
, int arg
)
389 for (i
=0; i
<n
; i
++) fillroom(what
,arg
);
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
401 fillroom(char what
, int arg
)
409 x
=rnd(MAXX
-2); y
=rnd(MAXY
-2);
414 c
[RANDOMWALK
]++; /* count up these random walks */
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
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
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
));
461 * Function to destroy all genocided monsters on the present level
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 */