History

rearrange some level gen code

mischief committed 9 years ago

Commit dcb054e1 parent c512cb55 files · +218 −215Browse files

Unified · Split

5 files
  1. dat.h +2 −5
  2. hack9.c +1 −1
  3. level.c +1 −91
  4. levelgen.c +213 −117
  5. monst.c +1 −1
dat.h+2−5
@@ -381,9 +381,7 @@ struct Level · 380 unmodified lines
381381 };
382382
383383 /* level.c */
384−Level *genlevel(int width, int height, int type);
385−void freelevel(Level *l);
386−void addspawn(Level *l, Point p, char *what, int freq, int istrap);
384+void lfree(Level *l);
387385 Tile *tileat(Level *l, Point p);
388386 #define flagat(l, p) (*(l->flags+(p.y*l->width)+p.x))
389387 #define hasflagat(l, p, F) (*(l->flags+(p.y*l->width)+p.x) & (F))
@@ -391,8 +389,7 @@ Tile *tileat(Level *l, Point p); · 1 unmodified line
391389 #define clrflagat(l, p, F) (*(l->flags+(p.y*l->width)+p.x) &= ~(F))
392390
393391 /* levelgen.c */
394−Level *mklevel(int width, int height, int floor, char *name);
395−void several(Level *l, Point *p, int count, char *type, int r);
392+Level *lgenerate(int width, int height, int type);
396393 int mkldebug(Level *l);
397394 int mklforest(Level *l);
398395 int mklgraveyard(Level *l);
hack9.c+1−1
@@ -152,7 +152,7 @@ threadmain(int argc, char *argv[]) · 151 unmodified lines
152152 sysfatal("monstdbopen: %r");
153153
154154 /* initial level */
155− if((level = genlevel(nrand(LSIZE)+LSIZE, nrand(LSIZE)+LSIZE, debug?0:nrand(3)+1)) == nil)
155+ if((level = lgenerate(nrand(LSIZE)+LSIZE, nrand(LSIZE)+LSIZE, debug?0:nrand(3)+1)) == nil)
156156 sysfatal("genlevel: %r");
157157
158158 /* the player */
level.c+1−91
@@ -10,97 +10,7 @@ · 9 unmodified lines
1010 #include "alg.h"
1111
1212 void
13−addspawn(Level *l, Point p, char *what, int freq, int istrap)
14−{
15− Spawn sp;
16−
17− if(l->nspawns < nelem(l->spawns)-1){
18− sp.pt = p;
19− strcpy(sp.what, what);
20− sp.freq = freq;
21− sp.turn = nrand(1000);
22− sp.istrap = istrap;
23− l->spawns[l->nspawns++] = sp;
24− tileat(l, p)->feat = TSPAWN;
25− setflagat(l, p, Fhasfeature);
26− }
27−}
28−
29−static void
30−mkportal(Level *l, Point p, int feat, Level *to, Point tp)
31−{
32− Tile *t;
33−
34− flagat(l, p) = (Fhasfeature|Fportal);
35− t = tileat(l, p);
36− t->feat = feat;
37− t->portal = emalloc(sizeof(Portal));
38− t->portal->to = to;
39− t->portal->pt = tp;
40−}
41−
42−static void
43−lrandstairs(Level *l)
44−{
45− Rectangle in;
46− Point pup, pdown;
47−
48− in = insetrect(l->r, 3);
49−
50− pup = (Point){nrand(Dx(in))+3, nrand(Dy(in))+3};
51− do {
52− pdown = (Point){nrand(Dx(in))+3, nrand(Dy(in))+3};
53− } while(eqpt(pdown, pup) || manhattan(pdown, pup) < ORTHOCOST*15);
54−
55− l->up = pup;
56− l->down = pdown;
57−
58− mkportal(l, pup, TUPSTAIR, nil, ZP);
59− mkportal(l, pdown, TDOWNSTAIR, nil, ZP);
60−}
61−
62−static int
63−gen(Level *l, int type)
64−{
65− lrandstairs(l);
66−
67− switch(type){
68− case 0:
69− mkldebug(l);
70− break;
71− case 1:
72− mklforest(l);
73− break;
74− case 2:
75− mklgraveyard(l);
76− break;
77− case 3:
78− mklvolcano(l);
79− break;
80− }
81−
82− return 0;
83−}
84−
85−Level*
86−genlevel(int width, int height, int type)
87−{
88− Level *l;
89−
90− l = nil;
91−
92− do {
93− if(l != nil)
94− freelevel(l);
95−
96− l = mklevel(width, height, TFLOOR, "somewhere");
97− } while(gen(l, type) < 0);
98−
99− return l;
100−}
101−
102−void
103−freelevel(Level *l)
13+lfree(Level *l)
10414 {
10515 int x, y;
10616 Point p;
levelgen.c+213−117
@@ -61,18 +61,41 @@ lclearrect(Level *l, Rectangle r) · 60 unmodified lines
6161 }
6262
6363 static void
64−lfillrect(Level *l, Rectangle r, int type)
64+lfeature(Level *l, Point p, int type, int flags)
65+{
66+ Tile *t;
67+
68+ t = tileat(l, p);
69+ t->feat = type;
70+
71+ flagat(l, p) = flags;
72+}
73+
74+static void
75+lfeatrect(Level *l, Rectangle r, int type, int flags)
6576 {
6677 Point p;
78+
79+ for(p.x = r.min.x; p.x <= r.max.x; p.x++)
80+ for(p.y = r.min.y; p.y <= r.max.y; p.y++)
81+ lfeature(l, p, type, flags);
82+}
83+
84+static void
85+lportal(Level *l, Point p, int feat, Level *to, Point tp)
86+{
6787 Tile *t;
88+ Portal *port;
6889
69− for(p.x = r.min.x; p.x <= r.max.x; p.x++){
70− for(p.y = r.min.y; p.y <= r.max.y; p.y++){
71− t = tileat(l, p);
72− t->feat = type;
73− flagat(l, p) = (Fblocked|Fhasfeature);
74− }
75− }
90+ lfeature(l, p, feat, Fhasfeature);
91+
92+ port = emalloc(sizeof(Portal));
93+ port->to = to;
94+ port->pt = tp;
95+
96+ t = tileat(l, p);
97+
98+ t->portal = port;
7699 }
77100
78101 static void
@@ -91,93 +114,79 @@ lborder(Level *l, Rectangle r, int i, int type) · 12 unmodified lines
91114
92115 tmp = Rect(r.min.x, r.min.y, r.max.x, r.min.y+i);
93116 lclearrect(l, tmp);
94− lfillrect(l, tmp, type);
117+ lfeatrect(l, tmp, type, Fblocked|Fhasfeature);
95118
96119 tmp = Rect(r.min.x, r.max.y-i, r.max.x, r.max.y);
97120 lclearrect(l, tmp);
98− lfillrect(l, tmp, type);
121+ lfeatrect(l, tmp, type, Fblocked|Fhasfeature);
99122
100123 tmp = Rect(r.min.x, r.min.y+i, r.min.x+i, r.max.y-i);
101124 lclearrect(l, tmp);
102− lfillrect(l, tmp, type);
125+ lfeatrect(l, tmp, type, Fblocked|Fhasfeature);
103126
104127 tmp = Rect(r.max.x-i, r.min.y+i, r.max.x, r.max.y-i);
105128 lclearrect(l, tmp);
106− lfillrect(l, tmp, type);
129+ lfeatrect(l, tmp, type, Fblocked|Fhasfeature);
107130 }
108131
109−/* more sbias makes it straighter. */
110132 static void
111−drunk1(Level *l, Point p, uint count, uint sbias)
133+lspawn(Level *l, Point p, char *what, int freq, int istrap)
112134 {
113− int cur, last;
114− Point next;
115− Rectangle clipr;
116− Tile *t;
117−
118− clipr = insetrect(l->or, 1);
119−
120− last = nrand(NCARDINAL);
121− while(count > 0){
122− if(nrand(sbias+1) == 0)
123− cur = nrand(NCARDINAL);
124− else
125− cur = last;
126− next = addpt(p, cardinals[cur]);
127− if(!ptinrect(next, clipr))
128− continue;
129− last = cur;
130− p = next;
131− if(!eqpt(p, l->up) && !eqpt(p, l->down) && hasflagat(l, p, Fblocked|Fhasfeature)){
132− t = tileat(l, p);
133− t->feat = 0;
134− flagat(l, p) = 0;
135− count--;
136− }
135+ Spawn sp;
136+
137+ if(l->nspawns < nelem(l->spawns)-1){
138+ sp.pt = p;
139+ strcpy(sp.what, what);
140+ sp.freq = freq;
141+ sp.turn = nrand(1000);
142+ sp.istrap = istrap;
143+ l->spawns[l->nspawns++] = sp;
144+ tileat(l, p)->feat = TSPAWN;
145+ setflagat(l, p, Fhasfeature);
137146 }
138147 }
139148
140−/*
141− * drunken performs the drunkard's walk. as s1 and
142− * s2 increase, the paths become more biased toward
143− * 'straight'. it loops until the downstairs is
144− * reachable from the upstairs.
145− */
146−static int
147−drunken(Level *l, int type, int howmuch, int s1, int s2)
149+static void
150+lrandstairs(Level *l)
148151 {
149− int cnt, npath, redos;
150− Point p, *path;
151− Tile *t;
152+ Rectangle in;
153+ Point pup, pdown;
152154
153− cnt = ((l->width * l->height) / howmuch); //* 2;
154− redos = 0;
155+ in = insetrect(l->r, 3);
155156
156−redo:
157− if(redos++ > 10)
158− return 0;
159− /* fill */
160− for(p.x = 0; p.x < l->width; p.x++){
161− for(p.y = 0; p.y < l->height; p.y++){
162− if(!hasflagat(l, p, Fblocked|Fhasfeature)){
163− t = tileat(l, p);
164− t->feat = type;
165− flagat(l, p) = (Fblocked|Fhasfeature);
166− }
167− }
168− }
157+ pup = (Point){nrand(Dx(in))+3, nrand(Dy(in))+3};
158+ do {
159+ pdown = (Point){nrand(Dx(in))+3, nrand(Dy(in))+3};
160+ } while(eqpt(pdown, pup) || manhattan(pdown, pup) < ORTHOCOST*15);
169161
170− drunk1(l, l->up, cnt/2, s1);
171− drunk1(l, l->down, cnt/2, s2);
162+ l->up = pup;
163+ l->down = pdown;
172164
173− /* check reachability */
174− npath = pathfind(l, l->up, l->down, &path, Fblocked);
175− if(npath < 0)
176− goto redo;
177− else
178− free(path);
165+ lportal(l, pup, TUPSTAIR, nil, ZP);
166+ lportal(l, pdown, TDOWNSTAIR, nil, ZP);
167+}
179168
180− return cnt * 2;
169+static int
170+lgen(Level *l, int type)
171+{
172+ lrandstairs(l);
173+
174+ switch(type){
175+ case 0:
176+ mkldebug(l);
177+ break;
178+ case 1:
179+ mklforest(l);
180+ break;
181+ case 2:
182+ mklgraveyard(l);
183+ break;
184+ case 3:
185+ mklvolcano(l);
186+ break;
187+ }
188+
189+ return 0;
181190 }
182191
183192 /* create a monster in the idle state */
@@ -229,28 +238,9 @@ several(Level *l, Point *p, int count, char *type, int r) · 45 unmodified lines
229238 }
230239 }
231240
232−/* genmonsters spawns count of type monsters at random places on l. */
233−static void
234−genmonsters(Level *l, char *type, int count)
235−{
236− int i;
237− Point p;
238− Tile *t;
239−
240− for(i = 0; i < count; i++){
241− do{
242− p = (Point){nrand(l->width), nrand(l->height)};
243− }while(hasflagat(l, p, Fhasmonster|Fhasfeature|Fblocked));
244−
245− t = tileat(l, p);
246− t->monst = mkmons(l, p, type);
247− t->unit = t->monst->md->tile;
248− setflagat(l, p, Fhasmonster);
249− }
250−}
251−
241+/* AI function for levels */
252242 static int
253−levelexec(void *v)
243+lexec(void *v)
254244 {
255245 int i, j, n;
256246 Point p, np, *neigh;
@@ -312,8 +302,8 @@ levelexec(void *v) · 55 unmodified lines
312302 return TASKSUCCESS;
313303 }
314304
315−Level*
316−mklevel(int width, int height, int floor, char *name)
305+static Level*
306+lmk(int width, int height, int floor, char *name)
317307 {
318308 int i;
319309 Point p;
@@ -338,7 +328,7 @@ mklevel(int width, int height, int floor, char *name) · 18 unmodified lines
338328 if(l->flags == nil)
339329 goto err1;
340330
341− l->bt = btleaf("level", levelexec);
331+ l->bt = btleaf("level", lexec);
342332 if(l->bt == nil)
343333 goto err2;
344334
@@ -362,6 +352,112 @@ err0: · 17 unmodified lines
362352 return nil;
363353 }
364354
355+Level*
356+lgenerate(int width, int height, int type)
357+{
358+ Level *l;
359+
360+ l = nil;
361+
362+ do {
363+ if(l != nil)
364+ lfree(l);
365+
366+ l = lmk(width, height, TFLOOR, "somewhere");
367+ } while(lgen(l, type) < 0);
368+
369+ return l;
370+}
371+/* more sbias makes it straighter. */
372+static void
373+drunk1(Level *l, Point p, uint count, uint sbias)
374+{
375+ int cur, last;
376+ Point next;
377+ Rectangle clipr;
378+ Tile *t;
379+
380+ clipr = insetrect(l->or, 1);
381+
382+ last = nrand(NCARDINAL);
383+ while(count > 0){
384+ if(nrand(sbias+1) == 0)
385+ cur = nrand(NCARDINAL);
386+ else
387+ cur = last;
388+ next = addpt(p, cardinals[cur]);
389+ if(!ptinrect(next, clipr))
390+ continue;
391+ last = cur;
392+ p = next;
393+ if(!eqpt(p, l->up) && !eqpt(p, l->down) && hasflagat(l, p, Fblocked|Fhasfeature)){
394+ t = tileat(l, p);
395+ t->feat = 0;
396+ flagat(l, p) = 0;
397+ count--;
398+ }
399+ }
400+}
401+
402+/*
403+ * drunken performs the drunkard's walk. as s1 and
404+ * s2 increase, the paths become more biased toward
405+ * 'straight'. it loops until the downstairs is
406+ * reachable from the upstairs.
407+ */
408+static int
409+drunken(Level *l, int type, int howmuch, int s1, int s2)
410+{
411+ int cnt, npath, redos;
412+ Point p, *path;
413+
414+ cnt = ((l->width * l->height) / howmuch); //* 2;
415+ redos = 0;
416+
417+redo:
418+ if(redos++ > 10)
419+ return 0;
420+ /* fill */
421+ for(p.x = 0; p.x < l->width; p.x++){
422+ for(p.y = 0; p.y < l->height; p.y++){
423+ if(!hasflagat(l, p, Fblocked|Fhasfeature))
424+ lfeature(l, p, type, Fblocked|Fhasfeature);
425+ }
426+ }
427+
428+ drunk1(l, l->up, cnt/2, s1);
429+ drunk1(l, l->down, cnt/2, s2);
430+
431+ /* check reachability */
432+ npath = pathfind(l, l->up, l->down, &path, Fblocked);
433+ if(npath < 0)
434+ goto redo;
435+ else
436+ free(path);
437+
438+ return cnt * 2;
439+}
440+
441+/* genmonsters spawns count of type monsters at random places on l. */
442+static void
443+genmonsters(Level *l, char *type, int count)
444+{
445+ int i;
446+ Point p;
447+ Tile *t;
448+
449+ for(i = 0; i < count; i++){
450+ do{
451+ p = (Point){nrand(l->width), nrand(l->height)};
452+ }while(hasflagat(l, p, Fhasmonster|Fhasfeature|Fblocked));
453+
454+ t = tileat(l, p);
455+ t->monst = mkmons(l, p, type);
456+ t->unit = t->monst->md->tile;
457+ setflagat(l, p, Fhasmonster);
458+ }
459+}
460+
365461 int
366462 mkldebug(Level *l)
367463 {
@@ -401,18 +497,18 @@ mklforest(Level *l) · 33 unmodified lines
401497 lclear(l, p, 2);
402498 several(l, &p, 1, "captain", 0);
403499 several(l, &p, 1, "lieutenant", 1);
404− addspawn(l, p, "soldier", 57, 2);
405− addspawn(l, p, "sergeant", 91, 1);
406− addspawn(l, p, "lieutenant", 97, 1);
407− addspawn(l, p, "captain", 131, 1);
500+ lspawn(l, p, "soldier", 57, 2);
501+ lspawn(l, p, "sergeant", 91, 1);
502+ lspawn(l, p, "lieutenant", 97, 1);
503+ lspawn(l, p, "captain", 131, 1);
408504
409505 lclear(l, p2, 2);
410506 several(l, &p2, 1, "gnome king", 0);
411507 several(l, &p2, 1, "gnome wizard", 1);
412− addspawn(l, p2, "gnome", 13, 1);
413− addspawn(l, p2, "gnome lord", 17, 2);
414− addspawn(l, p2, "gnome wizard", 27, 1);
415− addspawn(l, p2, "gnome king", 101, 1);
508+ lspawn(l, p2, "gnome", 13, 1);
509+ lspawn(l, p2, "gnome lord", 17, 2);
510+ lspawn(l, p2, "gnome wizard", 27, 1);
511+ lspawn(l, p2, "gnome king", 101, 1);
416512
417513 /* don't start empty */
418514 genmonsters(l, "gnome lord", space/128);
@@ -444,18 +540,18 @@ mklgraveyard(Level *l) · 25 unmodified lines
444540 lclear(l, p, 2);
445541 lclear(l, p2, 2);
446542
447− addspawn(l, p, "lich", 101, 1);
448− addspawn(l, p, "demilich", 157, 0);
449− addspawn(l, p, "ghost", 15, 2);
450− addspawn(l, p, "human zombie", 27, 2);
451− addspawn(l, p, "skeleton", 71, 1);
543+ lspawn(l, p, "lich", 101, 1);
544+ lspawn(l, p, "demilich", 157, 0);
545+ lspawn(l, p, "ghost", 15, 2);
546+ lspawn(l, p, "human zombie", 27, 2);
547+ lspawn(l, p, "skeleton", 71, 1);
452548
453549 several(l, &p2, 1, "gnome king", 0);
454550 several(l, &p2, 1, "gnome wizard", 1);
455− addspawn(l, p2, "gnome", 29, 1);
456− addspawn(l, p2, "gnome lord", 45, 2);
457− addspawn(l, p2, "gnome wizard", 57, 2);
458− addspawn(l, p2, "gnome king", 71, 1);
551+ lspawn(l, p2, "gnome", 29, 1);
552+ lspawn(l, p2, "gnome lord", 45, 2);
553+ lspawn(l, p2, "gnome wizard", 57, 2);
554+ lspawn(l, p2, "gnome king", 71, 1);
459555
460556 genmonsters(l, "ghost", space/64);
461557 genmonsters(l, "gnome", space/64);
@@ -486,8 +582,8 @@ mklvolcano(Level *l) · 24 unmodified lines
486582 lclear(l, p, 2);
487583 lclear(l, p2, 2);
488584
489− addspawn(l, p, "large cat", 77, 0);
490− addspawn(l, p2, "gnome lord", 27, 2);
585+ lspawn(l, p, "large cat", 77, 0);
586+ lspawn(l, p2, "gnome lord", 27, 2);
491587
492588 genmonsters(l, "large cat", space/128);
493589 genmonsters(l, "gnome lord", space/64);
@@ -519,7 +615,7 @@ mklcastle(Level *l) · 25 unmodified lines
519615
520616 lclearrect(l, Rpt(p, addpt(p, Pt(0,1))));
521617
522− addspawn(l, addpt(mid.min, Pt(Dx(mid)/2, Dy(mid)/2)), "soldier", 21, 0);
618+ lspawn(l, addpt(mid.min, Pt(Dx(mid)/2, Dy(mid)/2)), "soldier", 21, 0);
523619
524620 l->up = Pt(1,1);
525621 l->down = Pt(4,1);
monst.c+1−1
@@ -439,7 +439,7 @@ maction(Monster *m, int what, Point where) · 438 unmodified lines
439439 m = cur->monst;
440440 cur->monst = nil;
441441 if(cur->portal->to == nil){
442− if((cur->portal->to = genlevel(nrand(20)+50, nrand(20)+20, nrand(3)+1)) == nil)
442+ if((cur->portal->to = lgenerate(nrand(20)+50, nrand(20)+20, nrand(3)+1)) == nil)
443443 sysfatal("genlevel: %r");
444444
445445 cur->portal->pt = cur->portal->to->up;