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