History

convert monstdata array to ndb file, make monsters by name. make some types more consistent

mischief committed 11 years ago

Commit 4bbc7bc1 parent c99276c11 files · +312 −134Browse files

Unified · Split

11 files
  1. ai.c +2 −0
  2. dat.h +32 −22
  3. hack9.c +7 −1
  4. level.c +59 −52
  5. mk.common +0 −1
  6. mkfile +3 −1
  7. monst.c +147 −16
  8. monstdata.c +0 −32
  9. monster.ndb +35 −0
  10. ui.c +8 −8
  11. util.c +19 −1
ai.c+2−0
@@ -4,6 +4,7 @@ · 3 unmodified lines
4#include <thread.h>4#include <thread.h>
5 5
6#include "dat.h"6#include "dat.h"
7#include "alg.h"
7 8
8AIState*9AIState*
9mkstate(char *name, Monster *m, void *aux, AIFun enter, AIFun exec, AIFun exit)10mkstate(char *name, Monster *m, void *aux, AIFun enter, AIFun exec, AIFun exit)
@@ -87,6 +88,7 @@ idleexec(AIState *a) · 77 unmodified lines
87 ys = c.y - yd;88 ys = c.y - yd;
88 89
89 Point pts[] = { p, Pt(p.x, ys), Pt(xs, p.y), Pt(xs, ys) };90 Point pts[] = { p, Pt(p.x, ys), Pt(xs, p.y), Pt(xs, ys) };
91 shuffle(pts, 4, sizeof(Point));
90 for(i = 0; i < 4; i++){92 for(i = 0; i < 4; i++){
91 s = pts[i];93 s = pts[i];
92 if(!ptinrect(s, m->l->r))94 if(!ptinrect(s, m->l->r))
dat.h+32−22
@@ -8,6 +8,12 @@ typedef struct MonsterData MonsterData; · 7 unmodified lines
8typedef struct Monster Monster;8typedef struct Monster Monster;
9typedef struct Camera Camera;9typedef struct Camera Camera;
10 10
11/* sizes */
12enum
13{
14 SZMONNAME = 32,
15};
16
11/* hack9.c */17/* hack9.c */
12extern int debug;18extern int debug;
13extern int farmsg;19extern int farmsg;
@@ -62,18 +68,20 @@ void drawtile(Tileset *t, Image *dst, Point p, int i); · 48 unmodified lines
62 68
63struct MonsterData69struct MonsterData
64{70{
65 char *name;71 char name[SZMONNAME];
66 uint basexpl;72 /* offset into tileset */
73 int tile;
74
75 /* base experience level */
76 int basexpl;
67 char align;77 char align;
68 uint mvr;78 int mvr;
69 uint maxhp;79 int maxhp;
70 long def;80 int def;
71 uint rolls;81 int rolls;
72 uint atk;82 int atk;
73};83};
74 84
75extern MonsterData monstdata[1200];
76
77/* possible moves */85/* possible moves */
78enum86enum
79{87{
@@ -93,8 +101,6 @@ struct Monster · 13 unmodified lines
93{101{
94 /* references */102 /* references */
95 Ref ref;103 Ref ref;
96 /* type */
97 int type;
98 104
99 /* current level */105 /* current level */
100 Level *l;106 Level *l;
@@ -105,11 +111,11 @@ struct Monster · 4 unmodified lines
105 char align;111 char align;
106 112
107 /* move rate */113 /* move rate */
108 long mvr;114 int mvr;
109 /* move points */115 /* move points */
110 long mvp;116 int mvp;
111 /* turn counter */117 /* turn counter */
112 long turns;118 int turns;
113 119
114 /* current hp */120 /* current hp */
115 double hp;121 double hp;
@@ -117,15 +123,15 @@ struct Monster · 1 unmodified line
117 double maxhp;123 double maxhp;
118 124
119 /* armor class */125 /* armor class */
120 long ac;126 int ac;
121 127
122 /* kill count */128 /* kill count */
123 long kills;129 int kills;
124 130
125 /* experience level */131 /* experience level */
126 long xpl;132 int xpl;
127 /* experience gained */133 /* experience gained */
128 long xp;134 int xp;
129 135
130 /* flags */136 /* flags */
131 u32int flags;137 u32int flags;
@@ -139,15 +145,17 @@ struct Monster · 7 unmodified lines
139};145};
140 146
141/* monst.c */147/* monst.c */
142Monster *monst(int idx);148int monstdbopen(char *file);
149MonsterData *mdbyname(char *monster);
150Monster *mbyname(char *monster);
143void mfree(Monster *m);151void mfree(Monster *m);
144int mupdate(Monster *m);152int mupdate(Monster *m);
145void mpushstate(Monster *m, AIState *a);153void mpushstate(Monster *m, AIState *a);
146AIState *mpopstate(Monster *m);154AIState *mpopstate(Monster *m);
147int maction(Monster *m, int what, Point where);155int maction(Monster *m, int what, Point where);
148long xpcalc(long level);156int xpcalc(int level);
149 157
150/* well known tiles, also indexes into monstdata */158/* well known tiles, indexes into tileset */
151enum159enum
152{160{
153 /* monsters */161 /* monsters */
@@ -173,6 +181,7 @@ enum · 19 unmodified lines
173 TWATER = 860,181 TWATER = 860,
174 TICE = 861,182 TICE = 861,
175 TLAVA = 862,183 TLAVA = 862,
184 TSPAWN = 888,
176 TPORTAL = 891,185 TPORTAL = 891,
177};186};
178 187
@@ -190,7 +199,7 @@ struct Spawn · 11 unmodified lines
190 /* where spawn occurs */199 /* where spawn occurs */
191 Point pt;200 Point pt;
192 /* what to spawn */201 /* what to spawn */
193 int what;202 char what[SZMONNAME];
194 /* frequency of spawn, modulo turns */203 /* frequency of spawn, modulo turns */
195 int freq;204 int freq;
196};205};
@@ -300,6 +309,7 @@ enum · 103 unmodified lines
300 309
301extern Point cardinals[];310extern Point cardinals[];
302int roll(int count, int sides);311int roll(int count, int sides);
312int parseroll(char *str, int *count, int *sides);
303int min(int a, int b);313int min(int a, int b);
304int max(int a, int b);314int max(int a, int b);
305 315
hack9.c+7−1
@@ -107,6 +107,7 @@ usage(void) · 106 unmodified lines
107void107void
108threadmain(int argc, char *argv[])108threadmain(int argc, char *argv[])
109{109{
110 char buf[256];
110 /* of viewport, in size of tiles */111 /* of viewport, in size of tiles */
111 Tile *t;112 Tile *t;
112 Level *level;113 Level *level;
@@ -129,6 +130,11 @@ threadmain(int argc, char *argv[]) · 16 unmodified lines
129 130
130 uiinit(argv0);131 uiinit(argv0);
131 132
133 snprint(buf, sizeof(buf), "%s/lib/hack9/%s", home, "monster.ndb");
134 if(monstdbopen(buf) < 0)
135 if(monstdbopen("monster.ndb") < 0)
136 sysfatal("monstdbopen: %r");
137
132 /* initial level */138 /* initial level */
133 if(debug > 0){139 if(debug > 0){
134 if((level = genlevel(11, 11, 0)) == nil)140 if((level = genlevel(11, 11, 0)) == nil)
@@ -139,7 +145,7 @@ threadmain(int argc, char *argv[]) · 4 unmodified lines
139 }145 }
140 146
141 /* the player */147 /* the player */
142 player = monst(TWIZARD);148 player = mbyname("wizard");
143 if(player == nil)149 if(player == nil)
144 sysfatal("monst: %r");150 sysfatal("monst: %r");
145 151
level.c+59−52
@@ -108,10 +108,12 @@ redo: · 107 unmodified lines
108 108
109/* create a monster in the idle state */109/* create a monster in the idle state */
110static Monster*110static Monster*
111mkmons(Level *l, Point p, int type)111mkmons(Level *l, Point p, char *type)
112{112{
113 Monster *m;113 Monster *m;
114 m = monst(type);114 m = mbyname(type);
115 if(m == nil)
116 sysfatal("monstbyname: %r");
115 m->l = l;117 m->l = l;
116 m->pt = p;118 m->pt = p;
117 /* setup ai state */119 /* setup ai state */
@@ -121,7 +123,7 @@ mkmons(Level *l, Point p, int type) · 3 unmodified lines
121 123
122/* genmonsters spawns count of type monsters at random places on l. */124/* genmonsters spawns count of type monsters at random places on l. */
123static void125static void
124genmonsters(Level *l, int type, int count)126genmonsters(Level *l, char *type, int count)
125{127{
126 int i;128 int i;
127 Point p;129 Point p;
@@ -133,8 +135,8 @@ genmonsters(Level *l, int type, int count) · 5 unmodified lines
133 }while(hasflagat(l, p, Fhasmonster|Fhasfeature|Fblocked));135 }while(hasflagat(l, p, Fhasmonster|Fhasfeature|Fblocked));
134 136
135 t = tileat(l, p);137 t = tileat(l, p);
136 t->unit = type;
137 t->monst = mkmons(l, p, type);138 t->monst = mkmons(l, p, type);
139 t->unit = t->monst->md->tile;
138 setflagat(l, p, Fhasmonster);140 setflagat(l, p, Fhasmonster);
139 }141 }
140}142}
@@ -147,7 +149,7 @@ genmonsters(Level *l, int type, int count) · 6 unmodified lines
147 * spawns 13 ghosts centered at p on l.149 * spawns 13 ghosts centered at p on l.
148 */150 */
149static void151static void
150several(Level *l, Point *p, int count, int type, int r)152several(Level *l, Point *p, int count, char *type, int r)
151{153{
152 int i, j, n;154 int i, j, n;
153 Point *neigh;155 Point *neigh;
@@ -155,8 +157,8 @@ several(Level *l, Point *p, int count, int type, int r) · 1 unmodified line
155 for(i = 0; i < count; i++){157 for(i = 0; i < count; i++){
156 if(!hasflagat(l, p[i], Fhasmonster|Fblocked)){158 if(!hasflagat(l, p[i], Fhasmonster|Fblocked)){
157 t = tileat(l, p[i]);159 t = tileat(l, p[i]);
158 t->unit = type;
159 t->monst = mkmons(l, p[i], type);160 t->monst = mkmons(l, p[i], type);
161 t->unit = t->monst->md->tile;
160 setflagat(l, p[i], Fhasmonster);162 setflagat(l, p[i], Fhasmonster);
161 }163 }
162 if(r > 0){164 if(r > 0){
@@ -169,10 +171,18 @@ several(Level *l, Point *p, int count, int type, int r) · 6 unmodified lines
169 }171 }
170}172}
171 173
172static void addspawn(Level *l, Point p, int what, int freq)174static void addspawn(Level *l, Point p, char *what, int freq)
173{175{
174 if(l->nspawns < nelem(l->spawns)-1)176 Spawn sp;
175 l->spawns[l->nspawns++] = (Spawn){p, what, freq};177
178 if(l->nspawns < nelem(l->spawns)-1){
179 sp.pt = p;
180 strcpy(sp.what, what);
181 sp.freq = freq;
182 l->spawns[l->nspawns++] = sp;
183 tileat(l, p)->feat = TSPAWN;
184 setflagat(l, p, Fhasfeature);
185 }
176}186}
177 187
178static void188static void
@@ -198,9 +208,9 @@ levelexec(AIState *a) · 19 unmodified lines
198 if(hasflagat(l, np, Fhasmonster)){208 if(hasflagat(l, np, Fhasmonster)){
199 t = tileat(l, np);209 t = tileat(l, np);
200 m = t->monst;210 m = t->monst;
201 md = &monstdata[l->spawns[i].what];211 md = mdbyname(l->spawns[i].what);
202 if(m->type != l->spawns[i].what && abs(m->align - md->align) > 15){212 if(strcmp(m->md->name, l->spawns[i].what) != 0 && abs(m->align - md->align) > 15){
203 several(l, &np, 1, l->spawns[i].what, 1);213 several(l, &p, 1, l->spawns[i].what, 2);
204 }214 }
205 }215 }
206 }216 }
@@ -273,8 +283,8 @@ gen(Level *l, int type) · 66 unmodified lines
273 drunken(l, TTREE, 3, 3, 3);283 drunken(l, TTREE, 3, 3, 3);
274 clear(l, pup, 1);284 clear(l, pup, 1);
275 clear(l, pdown, 1);285 clear(l, pdown, 1);
276 several(l, &l->down, 1, TLICH, 1);286 several(l, &l->down, 1, "lich", 1);
277 several(l, &l->down, 1, TGWIZARD, 1);287 several(l, &l->down, 1, "gnome wizard", 1);
278 break;288 break;
279 break;289 break;
280 case 1:290 case 1:
@@ -287,28 +297,28 @@ gen(Level *l, int type) · 6 unmodified lines
287 return -1;297 return -1;
288 }while(!ptinrect(p, in) || manhattan(p, l->down) < DIST || manhattan(p, l->up) < DIST || hasflagat(l, p, Fblocked|Fhasmonster|Fhasfeature));298 }while(!ptinrect(p, in) || manhattan(p, l->down) < DIST || manhattan(p, l->up) < DIST || hasflagat(l, p, Fblocked|Fhasmonster|Fhasfeature));
289 clear(l, p, 2);299 clear(l, p, 2);
290 several(l, &p, 1, TCAPTAIN, 0);300 several(l, &p, 1, "captain", 0);
291 several(l, &p, 1, TLIEUTENANT, 1);301 several(l, &p, 1, "lieutenant", 1);
292 addspawn(l, p, TSOLDIER, 37);302 addspawn(l, p, "soldier", 37);
293 addspawn(l, p, TSERGEANT, 51);303 addspawn(l, p, "sergeant", 51);
294 addspawn(l, p, TLIEUTENANT, 97);304 addspawn(l, p, "lieutenant", 97);
295 addspawn(l, p, TCAPTAIN, 131);305 addspawn(l, p, "captain", 131);
296 do{306 do{
297 p2 = (Point){nrand(l->width), nrand(l->height)};307 p2 = (Point){nrand(l->width), nrand(l->height)};
298 if(try++ > 10)308 if(try++ > 10)
299 return -1;309 return -1;
300 }while(!ptinrect(p2, in) || manhattan(p, p2) < DIST || manhattan(p, p2) > DIST*2 || manhattan(p2, l->down) < DIST || manhattan(p2, l->up) < DIST || hasflagat(l, p2, Fblocked|Fhasmonster|Fhasfeature));310 }while(!ptinrect(p2, in) || manhattan(p, p2) < DIST || manhattan(p, p2) > DIST*2 || manhattan(p2, l->down) < DIST || manhattan(p2, l->up) < DIST || hasflagat(l, p2, Fblocked|Fhasmonster|Fhasfeature));
301 clear(l, p2, 2);311 clear(l, p2, 2);
302 several(l, &p2, 1, TGNOMEKING, 0);312 several(l, &p2, 1, "gnome king", 0);
303 several(l, &p2, 1, TGWIZARD, 1);313 several(l, &p2, 1, "gnome wizard", 1);
304 addspawn(l, p2, TGNOME, 11);314 addspawn(l, p2, "gnome", 11);
305 addspawn(l, p2, TGNOMELORD, 25);315 addspawn(l, p2, "gnome lord", 25);
306 addspawn(l, p2, TGWIZARD, 73);316 addspawn(l, p2, "gnome wizard", 73);
307 addspawn(l, p2, TGNOMEKING, 131);317 addspawn(l, p2, "gnome king", 131);
308 318
309 /* don't start empty */319 /* don't start empty */
310 genmonsters(l, TGNOMELORD, space/128);320 genmonsters(l, "gnome lord", space/128);
311 genmonsters(l, TSERGEANT, space/128);321 genmonsters(l, "sergeant", space/128);
312 break;322 break;
313 case 2:323 case 2:
314 space += drunken(l, TGRAVE, 2, 4, 4);324 space += drunken(l, TGRAVE, 2, 4, 4);
@@ -320,44 +330,41 @@ gen(Level *l, int type) · 5 unmodified lines
320 return -1;330 return -1;
321 }while(!ptinrect(p, in) || manhattan(p, l->down) < DIST || manhattan(p, l->up) < DIST || hasflagat(l, p, Fblocked|Fhasmonster|Fhasfeature));331 }while(!ptinrect(p, in) || manhattan(p, l->down) < DIST || manhattan(p, l->up) < DIST || hasflagat(l, p, Fblocked|Fhasmonster|Fhasfeature));
322 clear(l, p, 2);332 clear(l, p, 2);
323 addspawn(l, p, TLICH, 31);333 addspawn(l, p, "lich", 31);
324 addspawn(l, p, TGHOST, 5);334 addspawn(l, p, "ghost", 5);
325 do{335 do{
326 p2 = (Point){nrand(l->width), nrand(l->height)};336 p2 = (Point){nrand(l->width), nrand(l->height)};
327 if(try++ > 10)337 if(try++ > 10)
328 return -1;338 return -1;
329 }while(!ptinrect(p2, in) || manhattan(p, p2) < DIST*3 || manhattan(p2, l->down) < DIST || manhattan(p2, l->up) < DIST || hasflagat(l, p2, Fblocked|Fhasmonster|Fhasfeature));339 }while(!ptinrect(p2, in) || manhattan(p, p2) < DIST*3 || manhattan(p2, l->down) < DIST || manhattan(p2, l->up) < DIST || hasflagat(l, p2, Fblocked|Fhasmonster|Fhasfeature));
330 clear(l, p2, 2);340 clear(l, p2, 2);
331 several(l, &p2, 1, TGNOMEKING, 0);341 several(l, &p2, 1, "gnome king", 0);
332 several(l, &p2, 1, TGWIZARD, 1);342 several(l, &p2, 1, "gnome wizard", 1);
333 addspawn(l, p2, TGNOME, 11);343 addspawn(l, p2, "gnome", 11);
334 addspawn(l, p2, TGNOMELORD, 25);344 addspawn(l, p2, "gnome lord", 25);
335 addspawn(l, p2, TGWIZARD, 73);345 addspawn(l, p2, "gnome wizard", 37);
336 addspawn(l, p2, TGNOMEKING, 131);346 addspawn(l, p2, "gnome king", 53);
337 347
338 genmonsters(l, TGHOST, space/64);348 genmonsters(l, "ghost", space/64);
339 genmonsters(l, TGNOME, space/64);349 genmonsters(l, "gnome", space/64);
340 break;350 break;
341 case 3:351 case 3:
342 drunken(l, TLAVA, 2, 1, 1);352 space += drunken(l, TLAVA, 2, 1, 1);
343 clear(l, pup, 2);353 clear(l, pup, 2);
344 clear(l, pdown, 2);354 clear(l, pdown, 2);
345 do{355 do{
346 p = (Point){nrand(l->width), nrand(l->height)};356 p = (Point){nrand(l->width), nrand(l->height)};
347 }while(hasflagat(l, p, Fblocked|Fhasfeature));357 }while(!ptinrect(p, in) || hasflagat(l, p, Fblocked|Fhasfeature));
348 addspawn(l, p, TLARGECAT, 11);358 clear(l, p, 2);
349 do{359 addspawn(l, p, "large cat", 67);
350 p = (Point){nrand(l->width), nrand(l->height)};
351 }while(hasflagat(l, p, Fblocked|Fhasfeature));
352 addspawn(l, p, TLARGECAT, 13);
353 do{
354 p = (Point){nrand(l->width), nrand(l->height)};
355 }while(hasflagat(l, p, Fblocked|Fhasfeature));
356 addspawn(l, p, TGWIZARD, 9);
357 do{360 do{
358 p = (Point){nrand(l->width), nrand(l->height)};361 p = (Point){nrand(l->width), nrand(l->height)};
359 }while(hasflagat(l, p, Fblocked|Fhasfeature));362 }while(!ptinrect(p, in) || hasflagat(l, p, Fblocked|Fhasfeature));
360 addspawn(l, p, TGWIZARD, 15);363 clear(l, p, 2);
364 addspawn(l, p, "gnome lord", 27);
365
366 genmonsters(l, "large cat", space/64);
367 genmonsters(l, "gnome lord", space/64);
361 break;368 break;
362 }369 }
363 370
mk.common+0−1
@@ -11,7 +11,6 @@ OFILES=\ · 10 unmodified lines
11 hack9.$O\11 hack9.$O\
12 level.$O\12 level.$O\
13 monst.$O\13 monst.$O\
14 monstdata.$O\
15 path.$O\14 path.$O\
16 tile.$O\15 tile.$O\
17 ui.$O\16 ui.$O\
mkfile+3−1
@@ -7,7 +7,9 @@ BIN=$home/bin/$objtype · 6 unmodified lines
7</sys/src/cmd/mkone7</sys/src/cmd/mkone
8 8
9install:V: $BIN/$TARG9install:V: $BIN/$TARG
10 cp nethack.32x32 $home/lib/10 mkdir $home/lib/hack9
11 cp nethack.32x32 $home/lib/hack9
12 cp monster.ndb $home/lib/hack9
11 13
12$O.alg: algtest.$O alg.$O14$O.alg: algtest.$O alg.$O
13 $LD -o $target $prereq15 $LD -o $target $prereq
monst.c+147−16
@@ -2,27 +2,157 @@ · 1 unmodified line
2#include <libc.h>2#include <libc.h>
3#include <draw.h>3#include <draw.h>
4#include <thread.h>4#include <thread.h>
5#include <bio.h>
6#include <ndb.h>
5 7
6#include "dat.h"8#include "dat.h"
7 9
8Monster*10enum
9monst(int idx)11{
12 MONNAME = 0,
13 MONTILE,
14 MONXPL,
15 MONALIGN,
16 MONMVRATE,
17 MONHP,
18 MONAC,
19 MONATK,
20};
21
22static char *monstdbcmd[] = {
23[MONNAME] "monster",
24[MONTILE] "tile",
25[MONXPL] "xpl",
26[MONALIGN] "align",
27[MONMVRATE] "mvr",
28[MONHP] "hp",
29[MONAC] "ac",
30[MONATK] "atk",
31};
32
33static Ndb *monstdb;
34
35int
36monstdbopen(char *file)
37{
38 monstdb = ndbopen(file);
39 if(monstdb == nil)
40 return 0;
41 return 1;
42}
43
44typedef struct mdcache mdcache;
45struct mdcache
10{46{
11 Monster *m;
12 MonsterData *md;47 MonsterData *md;
48 mdcache *next;
49};
13 50
14 if(idx < 0 || idx > nelem(monstdata))51static mdcache *monstcache = nil;
15 goto missing;52
53/* TODO: sanity checks */
54static int
55mdaddattr(MonsterData *md, int type, char *attr)
56{
57 switch(type){
58 case MONNAME:
59 strncpy(md->name, attr, sizeof(md->name)-1);
60 md->name[sizeof(md->name)-1] = 0;
61 break;
62 case MONTILE:
63 md->tile = atol(attr);
64 case MONXPL:
65 md->basexpl = atol(attr);
66 break;
67 case MONALIGN:
68 md->align = (char)atol(attr);
69 break;
70 case MONMVRATE:
71 md->mvr = atol(attr);
72 break;
73 case MONHP:
74 md->maxhp = atol(attr);
75 break;
76 case MONAC:
77 md->def = atol(attr);
78 break;
79 case MONATK:
80 if(!parseroll(attr, &md->atk, &md->rolls)){
81 werrstr("bad roll '%s'", attr);
82 return 0;
83 }
84 break;
85 default:
86 return 0;
87 }
88
89 return 1;
90}
91
92MonsterData*
93mdbyname(char *monster)
94{
95 int i;
96 Ndbtuple *t, *nt;
97 Ndbs search;
98 MonsterData *md;
99 mdcache *mdc;
100
101 /* cached? */
102 for(mdc = monstcache; mdc != nil; mdc = mdc->next){
103 if(strcmp(monster, mdc->md->name) == 0){
104 return mdc->md;
105 }
106 }
107
108 t = ndbsearch(monstdb, &search, "monster", monster);
109 if(t == nil)
110 return nil;
111
112 md = mallocz(sizeof(MonsterData), 1);
113 assert(md != nil);
114
115 for(nt = t; nt != nil; nt = nt->entry){
116 for(i = 0; i < nelem(monstdbcmd); i++){
117 if(strcmp(nt->attr, monstdbcmd[i]) == 0){
118 if(!mdaddattr(md, i, nt->val))
119 sysfatal("bad monster value '%s=%s': %r", nt->attr, nt->val);
120 goto okattr;
121 }
122 }
123 sysfatal("unknown monster attribute '%s'", nt->attr);
124okattr:
125 continue;
126 }
127
128 mdc = mallocz(sizeof(mdcache), 1);
129 assert(mdc != nil);
130
131 if(monstcache == nil){
132 monstcache = mdc;
133 monstcache->md = md;
134 } else {
135 mdc->md = md;
136 mdc->next = monstcache;
137 monstcache = mdc;
138 }
139
140 return md;
141}
142
143Monster*
144mbyname(char *monster)
145{
146 MonsterData *md;
147 Monster *m;
16 148
17 md = &monstdata[idx];149 md = mdbyname(monster);
18 if(md->name == nil)150 if(md == nil)
19 goto missing;151 goto missing;
20 152
21 m = mallocz(sizeof(Monster), 1);153 m = mallocz(sizeof(Monster), 1);
22 if(m == nil)154 assert(m != nil);
23 return nil;
24 155
25 m->type = idx;
26 m->align = md->align;156 m->align = md->align;
27 m->mvr = md->mvr;157 m->mvr = md->mvr;
28 m->mvp = nrand(m->mvr);158 m->mvp = nrand(m->mvr);
@@ -30,13 +160,14 @@ monst(int idx) · 1 unmodified line
30 m->maxhp = md->maxhp;160 m->maxhp = md->maxhp;
31 m->ac = md->def;161 m->ac = md->def;
32 m->xpl = md->basexpl;162 m->xpl = md->basexpl;
163
33 m->md = md;164 m->md = md;
34 165
35 incref(&m->ref);166 incref(&m->ref);
36 return m;
37 167
168 return m;
38missing:169missing:
39 werrstr("missing monster %d", idx);170 werrstr("no data for monster '%s'", monster);
40 return nil;171 return nil;
41}172}
42 173
@@ -124,9 +255,9 @@ mpopstate(Monster *m) · 81 unmodified lines
124 255
125/* determines what happens when a monster gets some xp */256/* determines what happens when a monster gets some xp */
126static void257static void
127maddxp(Monster *m, long xp)258maddxp(Monster *m, int xp)
128{259{
129 long hpgain, last;260 int hpgain, last;
130 261
131 dbg("%s get %ld xp total %ld next %ld", m->md->name, xp, m->xp, xpcalc(m->xpl));262 dbg("%s get %ld xp total %ld next %ld", m->md->name, xp, m->xp, xpcalc(m->xpl));
132 263
@@ -283,8 +414,8 @@ maction(Monster *m, int what, Point where) · 150 unmodified lines
283}414}
284 415
285/* return the amount of xp required to gain a level */416/* return the amount of xp required to gain a level */
286long417int
287xpcalc(long level)418xpcalc(int level)
288{419{
289 return 20 + (10 * (2*level) * (level+pow(0.95, level)));420 return 20 + (10 * (2*level) * (level+pow(0.95, level)));
290}421}
monstdata.c+0−32
@@ -1,32 +0,0 @@
1#include <u.h>
2#include <libc.h>
3#include <draw.h>
4#include <thread.h>
5
6#include "dat.h"
7
8enum
9{
10 UNALIGNED = 0,
11 GNOME = 50,
12 UNDEAD = -50,
13 HUMAN = -20,
14
15};
16
17MonsterData monstdata[1200] = {
18 /* name, xpl,align, mvr, hp, ac, rolls, atk */
19[TLARGECAT] {"large cat", 0, UNALIGNED, 16, 16, 8, 1, 3},
20[TGNOME] {"gnome", 1, GNOME, 6, 16, 10, 1, 6},
21[TGNOMELORD] {"gnome lord", 3, GNOME, 8, 32, 10, 1, 8},
22[TGWIZARD] {"gnome wizard", 3, GNOME, 10, 32, 4, 1, 6},
23[TGNOMEKING] {"gnome king", 5, GNOME, 10, 48, 10, 2, 6},
24[TLICH] {"lich", 2, UNDEAD, 6, 32, 3, 3, 2},
25[TSOLDIER] {"soldier", 6, HUMAN, 10, 16, 10, 1, 8},
26[TSERGEANT] {"sergeant", 8, HUMAN, 10, 16, 10, 2, 6},
27[TLIEUTENANT] {"lieutenant", 10, HUMAN, 10, 32, 10, 3, 4},
28[TCAPTAIN] {"captain", 12, HUMAN, 10, 48, 10, 4, 4},
29[TGHOST] {"ghost", 1, UNDEAD, 6, 16, -5, 1, 4},
30[TWIZARD] {"wizard", 0, 127, 14, 64, 5, 2, 3},
31};
32
monster.ndb+35−0
@@ -0,0 +1,35 @@
1# monster database
2
3monster="large cat"
4 tile=39 xpl=6 align=0 mvr=15 hp=16 ac=4 atk=2d4
5
6# gnomes
7monster="gnome"
8 tile=166 xpl=1 align=50 mvr=6 hp=16 ac=10 atk=1d6
9monster="gnome lord"
10 tile=167 xpl=3 align=50 mvr=8 hp=32 ac=10 atk=1d8
11monster="gnome wizard"
12 tile=168 xpl=3 align=50 mvr=10 hp=32 ac=4 atk=1d6
13monster="gnome king"
14 tile=169 xpl=5 align=50 mvr=10 hp=48 ac=10 atk=2d6
15
16# undead
17monster="lich"
18 tile=185 xpl=2 align=-50 mvr=6 hp=32 ac=3 atk=3d2
19monster="ghost"
20 tile=290 xpl=1 align=-50 mvr=6 hp=16 ac=-5 atk=1d4
21
22# military
23monster="soldier"
24 tile=280 xpl=6 align=-20 mvr=10 hp=16 ac=10 atk=1d8
25monster="sergeant"
26 tile=281 xpl=8 align=-20 mvr=10 hp=16 ac=10 atk=2d6
27monster="lieutenant"
28 tile=282 xpl=10 align=-20 mvr=10 hp=32 ac=10 atk=3d4
29monster="captain"
30 tile=283 xpl=12 align=-20 mvr=10 hp=48 ac=10 atk=4d4
31
32# player
33monster="wizard"
34 tile=349 xpl=0 align=127 mvr=14 hp=64 ac=5 atk=2d3
35
ui.c+8−8
@@ -142,9 +142,9 @@ uiinit(char *name) · 141 unmodified lines
142 if(tileset == nil)142 if(tileset == nil)
143 tileset = strdup("nethack.32x32");143 tileset = strdup("nethack.32x32");
144 144
145 snprint(buf, sizeof(buf), "%s/lib/%s", home, tileset);145 snprint(buf, sizeof(buf), "%s/lib/hack9/%s", home, tileset);
146 if((ui.tiles = opentile("nethack.32x32", 32, 32)) == nil)146 if((ui.tiles = opentile(buf, 32, 32)) == nil)
147 if((ui.tiles = opentile(buf, 32, 32)) == nil)147 if((ui.tiles = opentile("nethack.32x32", 32, 32)) == nil)
148 sysfatal("opentile: %r");148 sysfatal("opentile: %r");
149 free(tileset);149 free(tileset);
150 150
@@ -283,7 +283,7 @@ drawlevel(Level *l, Tileset *ts, Rectangle r) · 132 unmodified lines
283 p2 = addpt(sp, bot);283 p2 = addpt(sp, bot);
284 string(screen, p2, c, ZP, smallfont, buf);284 string(screen, p2, c, ZP, smallfont, buf);
285 p2.y -= smallfont->height;285 p2.y -= smallfont->height;
286 snprint(buf, sizeof(buf), "L%ld", m->xpl);286 snprint(buf, sizeof(buf), "L%d", m->xpl);
287 string(screen, p2, display->white, ZP, smallfont, buf);287 string(screen, p2, display->white, ZP, smallfont, buf);
288 /* debugging the ai state */288 /* debugging the ai state */
289 if(debug){289 if(debug){
@@ -334,7 +334,7 @@ drawui(Rectangle r) · 44 unmodified lines
334 p = string(screen, p, display->white, ZP, font, buf);334 p = string(screen, p, display->white, ZP, font, buf);
335 p.x += sw*2;335 p.x += sw*2;
336 336
337 snprint(buf, sizeof(buf), "%ld kills", player->kills);337 snprint(buf, sizeof(buf), "%d kills", player->kills);
338 p = string(screen, p, display->white, ZP, font, buf);338 p = string(screen, p, display->white, ZP, font, buf);
339 339
340 p.x = r.min.x;340 p.x = r.min.x;
@@ -343,7 +343,7 @@ drawui(Rectangle r) · 2 unmodified lines
343 p = string(screen, p, display->white, ZP, font, buf);343 p = string(screen, p, display->white, ZP, font, buf);
344 p.x += sw;344 p.x += sw;
345 345
346 snprint(buf, sizeof(buf), "L:%ld XP:%ld/%ld", player->xpl, player->xp, xpcalc(player->xpl));346 snprint(buf, sizeof(buf), "L:%d XP:%d/%d", player->xpl, player->xp, xpcalc(player->xpl));
347 p = string(screen, p, display->white, ZP, font, buf);347 p = string(screen, p, display->white, ZP, font, buf);
348 p.x += sw;348 p.x += sw;
349 349
@@ -360,7 +360,7 @@ drawui(Rectangle r) · 10 unmodified lines
360 p = string(screen, p, c, ZP, font, buf);360 p = string(screen, p, c, ZP, font, buf);
361 p.x += sw;361 p.x += sw;
362 362
363 snprint(buf, sizeof(buf), "AC:%ld", player->ac);363 snprint(buf, sizeof(buf), "AC:%d", player->ac);
364 p = string(screen, p, display->white, ZP, font, buf);364 p = string(screen, p, display->white, ZP, font, buf);
365 p.x += sw;365 p.x += sw;
366 366
@@ -546,7 +546,7 @@ uiexec(AIState *ai) · 179 unmodified lines
546 player->hp = player->maxhp;546 player->hp = player->maxhp;
547 setflagat(player->l, player->pt, Fhasmonster);547 setflagat(player->l, player->pt, Fhasmonster);
548 tileat(player->l, player->pt)->monst = player;548 tileat(player->l, player->pt)->monst = player;
549 tileat(player->l, player->pt)->unit = player->type;549 tileat(player->l, player->pt)->unit = player->md->tile;
550 gameover = 0;550 gameover = 0;
551 break;551 break;
552 case 2:552 case 2:
util.c+19−1
@@ -19,10 +19,28 @@ roll(int count, int sides) · 18 unmodified lines
19 int d;19 int d;
20 d = 0;20 d = 0;
21 while(count--> 0)21 while(count--> 0)
22 d += 1+nrand(sides);22 d += 1+lnrand(sides);
23 return d;23 return d;
24}24}
25 25
26int
27parseroll(char *str, int *count, int *sides)
28{
29 int i;
30 char *f[2];
31
32 if(str == nil || count == nil || sides == nil)
33 return 0;
34
35 i = gettokens(str, f, 2, "d");
36 if(i != 2)
37 return 0;
38
39 *count = atoi(f[0]);
40 *sides = atoi(f[1]);
41 return 1;
42}
43
26int44int
27min(int a, int b)45min(int a, int b)
28{46{