OSDN Git Service

shrink mine
[nethackexpress/trunk.git] / win / share / tilemap.c
1 /*      SCCS Id: @(#)tilemap.c  3.4     2000/06/04      */
2 /* NetHack may be freely redistributed.  See license for details. */
3
4 /*
5  *      This source file is compiled twice:
6  *      once without TILETEXT defined to make tilemap.{o,obj},
7  *      then again with it defined to produce tiletxt.{o,obj}.
8  */
9
10 #include "hack.h"
11
12 const char * FDECL(tilename, (int, int));
13 void NDECL(init_tilemap);
14 void FDECL(process_substitutions, (FILE *));
15
16 #if defined(MICRO) || defined(WIN32)
17 #undef exit
18 #if !defined(MSDOS) && !defined(WIN32)
19 extern void FDECL(exit, (int));
20 #endif
21 #endif
22
23 #define MON_GLYPH 1
24 #define OBJ_GLYPH 2
25 #define OTH_GLYPH 3     /* fortunately unnecessary */
26
27 /* note that the ifdefs here should be the opposite sense from monst.c/
28  * objects.c/rm.h
29  */
30
31 struct conditionals {
32         int sequence, predecessor;
33         const char *name;
34 } conditionals[] = {
35 #ifndef CHARON /* not supported yet */
36         { MON_GLYPH, PM_HELL_HOUND, "Cerberus" },
37 #endif
38         /* commented out in monst.c at present */
39         { MON_GLYPH, PM_SHOCKING_SPHERE, "beholder" },
40         { MON_GLYPH, PM_BABY_SILVER_DRAGON, "baby shimmering dragon" },
41         { MON_GLYPH, PM_SILVER_DRAGON, "shimmering dragon" },
42         { MON_GLYPH, PM_JABBERWOCK, "vorpal jabberwock" },
43 #ifndef KOPS
44         { MON_GLYPH, PM_JABBERWOCK, "Keystone Kop" },
45         { MON_GLYPH, PM_JABBERWOCK, "Kop Sergeant" },
46         { MON_GLYPH, PM_JABBERWOCK, "Kop Lieutenant" },
47         { MON_GLYPH, PM_JABBERWOCK, "Kop Kaptain" },
48 #endif
49         { MON_GLYPH, PM_VAMPIRE_LORD, "vampire mage" },
50 #ifndef CHARON /* not supported yet */
51         { MON_GLYPH, PM_CROESUS, "Charon" },
52 #endif
53 #ifndef MAIL
54         { MON_GLYPH, PM_FAMINE, "mail daemon" },
55 #endif
56 #ifndef TOURIST
57         { MON_GLYPH, PM_SAMURAI, "tourist" },
58 #endif
59         /* commented out in monst.c at present */
60         { MON_GLYPH, PM_SHAMAN_KARNOV, "Earendil" },
61         { MON_GLYPH, PM_SHAMAN_KARNOV, "Elwing" },
62 #ifndef TOURIST
63         { MON_GLYPH, PM_LORD_SATO, "Twoflower" },
64 #endif
65         /* commented out in monst.c at present */
66         { MON_GLYPH, PM_CHROMATIC_DRAGON, "Goblin King" },
67         { MON_GLYPH, PM_NEANDERTHAL, "High-elf" },
68 #ifndef TOURIST
69         { MON_GLYPH, PM_ROSHI, "guide" },
70 #endif
71 #ifndef KOPS
72         { OBJ_GLYPH, CLUB, "rubber hose" },
73 #endif
74         /* objects commented out in objects.c at present */
75         { OBJ_GLYPH, SILVER_DRAGON_SCALE_MAIL, "shimmering dragon scale mail" },
76         { OBJ_GLYPH, SILVER_DRAGON_SCALES, "shimmering dragon scales" },
77 #ifndef TOURIST
78         { OBJ_GLYPH, LEATHER_JACKET, "Hawaiian shirt" },
79         { OBJ_GLYPH, LEATHER_JACKET, "T-shirt" },
80         { OBJ_GLYPH, LOCK_PICK, "credit card" },
81         { OBJ_GLYPH, MAGIC_LAMP, "expensive camera" },
82 #endif
83 #ifndef STEED
84         { OBJ_GLYPH, TOWEL, "saddle" },
85 #endif
86         /* allow slime mold to look like slice of pizza, since we
87          * don't know what a slime mold should look like when renamed anyway
88          */
89 #ifndef MAIL
90         { OBJ_GLYPH, SCR_STINKING_CLOUD+4, "stamped / mail" },
91 #endif
92         { 0, 0, 0}
93 };
94
95
96 /*
97  * Some entries in glyph2tile[] should be substituted for on various levels.
98  * The tiles used for the substitute entries will follow the usual ones in
99  * other.til in the order given here, which should have every substitution
100  * for the same set of tiles grouped together.  You will have to change
101  * more code in process_substitutions()/substitute_tiles() if the sets
102  * overlap in the future.
103  */
104 struct substitute {
105         int first_glyph, last_glyph;
106         const char *sub_name;           /* for explanations */
107         const char *level_test;
108 } substitutes[] = {
109         { GLYPH_CMAP_OFF + S_vwall, GLYPH_CMAP_OFF + S_trwall,
110                                         "mine walls", "In_mines(plev)" },
111         { GLYPH_CMAP_OFF + S_vwall, GLYPH_CMAP_OFF + S_trwall,
112                                         "gehennom walls", "In_hell(plev)" },
113         { GLYPH_CMAP_OFF + S_vwall, GLYPH_CMAP_OFF + S_trwall,
114                                         "knox walls", "Is_knox(plev)" },
115         { GLYPH_CMAP_OFF + S_vwall, GLYPH_CMAP_OFF + S_trwall,
116                                         "sokoban walls", "In_sokoban(plev)" }
117 };
118
119
120 #ifdef TILETEXT
121
122 /*
123  * entry is the position of the tile within the monsters/objects/other set
124  */
125 const char *
126 tilename(set, entry)
127 int set, entry;
128 {
129         int i, j, condnum, tilenum;
130         static char buf[BUFSZ];
131
132         /* Note:  these initializers don't do anything except guarantee that
133                 we're linked properly.
134         */
135         monst_init();
136         objects_init();
137         (void) def_char_to_objclass(']');
138
139         condnum = tilenum = 0;
140
141         for (i = 0; i < NUMMONS; i++) {
142                 if (set == MON_GLYPH && tilenum == entry)
143                         return mons[i].mname;
144                 tilenum++;
145                 while (conditionals[condnum].sequence == MON_GLYPH &&
146                         conditionals[condnum].predecessor == i) {
147                         if (set == MON_GLYPH && tilenum == entry)
148                                 return conditionals[condnum].name;
149                         condnum++;
150                         tilenum++;
151                 }
152         }
153         if (set == MON_GLYPH && tilenum == entry)
154                 return "invisible monster";
155
156         tilenum = 0;    /* set-relative number */
157         for (i = 0; i < NUM_OBJECTS; i++) {
158                 /* prefer to give the description - that's all the tile's
159                  * appearance should reveal */
160                 if (set == OBJ_GLYPH && tilenum == entry) {
161                         if ( !obj_descr[i].oc_descr )
162                             return obj_descr[i].oc_name;
163                         if ( !obj_descr[i].oc_name )
164                             return obj_descr[i].oc_descr;
165
166                         Sprintf(buf, "%s / %s",
167                                 obj_descr[i].oc_descr,
168                                 obj_descr[i].oc_name);
169                         return buf;
170                 }
171
172                 tilenum++;
173                 while (conditionals[condnum].sequence == OBJ_GLYPH &&
174                         conditionals[condnum].predecessor == i) {
175                         if (set == OBJ_GLYPH && tilenum == entry)
176                                 return conditionals[condnum].name;
177                         condnum++;
178                         tilenum++;
179                 }
180         }
181
182         tilenum = 0;    /* set-relative number */
183         for (i = 0; i < (MAXPCHARS - MAXEXPCHARS); i++) {
184                 if (set == OTH_GLYPH && tilenum == entry) {
185                         if (*defsyms[i].explanation)
186                                 return defsyms[i].explanation;
187                         else {
188                                 /* if SINKS are turned off, this
189                                  * string won't be there (and can't be there
190                                  * to prevent symbol-identification and
191                                  * special-level mimic appearances from
192                                  * thinking the items exist)
193                                  */
194                                 switch (i) {
195                                     case S_sink:
196                                             Sprintf(buf, "sink");
197                                             break;
198                                     default:
199                                             Sprintf(buf, "cmap %d", tilenum);
200                                             break;
201                                 }
202                                 return buf;
203                         }
204                 }
205                 tilenum++;
206                 while (conditionals[condnum].sequence == OTH_GLYPH &&
207                         conditionals[condnum].predecessor == i) {
208                         if (set == OTH_GLYPH && tilenum == entry)
209                                 return conditionals[condnum].name;
210                         condnum++;
211                         tilenum++;
212                 }
213         }
214         /* explosions */
215         tilenum = MAXPCHARS - MAXEXPCHARS;
216         i = entry - tilenum;
217         if (i < (MAXEXPCHARS * EXPL_MAX)) {
218             if (set == OTH_GLYPH) {
219                 static char *explosion_types[] = { /* hack.h */
220                         "dark", "noxious", "muddy", "wet",
221                         "magical", "fiery", "frosty"
222                 };
223                 Sprintf(buf, "explosion %s %d",
224                         explosion_types[i / MAXEXPCHARS], i % MAXEXPCHARS);
225                 return buf;
226             }
227         }
228         tilenum += (MAXEXPCHARS * EXPL_MAX);
229
230         i = entry - tilenum;
231         if (i < (NUM_ZAP << 2)) {
232                 if (set == OTH_GLYPH) {
233                         Sprintf(buf, "zap %d %d", i/4, i%4);
234                         return buf;
235                 }
236         }
237         tilenum += (NUM_ZAP << 2);
238
239         i = entry - tilenum;
240         if (i < WARNCOUNT) {
241                 if (set == OTH_GLYPH) {
242                         Sprintf(buf, "warning %d", i);
243                         return buf;
244                 }
245         }
246         tilenum += WARNCOUNT;
247
248         for (i = 0; i < SIZE(substitutes); i++) {
249             j = entry - tilenum;
250             if (j <= substitutes[i].last_glyph - substitutes[i].first_glyph) {
251                 if (set == OTH_GLYPH) {
252                     Sprintf(buf, "sub %s %d", substitutes[i].sub_name, j);
253                     return buf;
254                 }
255             }
256             tilenum += substitutes[i].last_glyph
257                                 - substitutes[i].first_glyph + 1;
258         }
259
260         Sprintf(buf, "unknown %d %d", set, entry);
261         return buf;
262 }
263
264 #else   /* TILETEXT */
265
266 #define TILE_FILE       "tile.c"
267
268 #ifdef AMIGA
269 # define SOURCE_TEMPLATE        "NH:src/%s"
270 #else
271 # ifdef MAC
272 #   define SOURCE_TEMPLATE      ":src:%s"
273 # else
274 #   define SOURCE_TEMPLATE      "../src/%s"
275 # endif
276 #endif
277
278 short tilemap[MAX_GLYPH];
279 int lastmontile, lastobjtile, lastothtile;
280
281 /* Number of tiles for invisible monsters */
282 #define NUM_INVIS_TILES 1
283
284 /*
285  * set up array to map glyph numbers to tile numbers
286  *
287  * assumes tiles are numbered sequentially through monsters/objects/other,
288  * with entries for all supported compilation options
289  *
290  * "other" contains cmap and zaps (the swallow sets are a repeated portion
291  * of cmap), as well as the "flash" glyphs for the new warning system
292  * introduced in 3.3.1.
293  */
294 void
295 init_tilemap()
296 {
297         int i, j, condnum, tilenum;
298         int corpsetile, swallowbase;
299
300         for (i = 0; i < MAX_GLYPH; i++) {
301                 tilemap[i] = -1;
302         }
303
304         corpsetile = NUMMONS + NUM_INVIS_TILES + CORPSE;
305         swallowbase= NUMMONS + NUM_INVIS_TILES + NUM_OBJECTS + S_sw_tl;
306
307         /* add number compiled out */
308         for (i = 0; conditionals[i].sequence; i++) {
309                 switch (conditionals[i].sequence) {
310                         case MON_GLYPH:
311                                 corpsetile++;
312                                 swallowbase++;
313                                 break;
314                         case OBJ_GLYPH:
315                                 if (conditionals[i].predecessor < CORPSE)
316                                         corpsetile++;
317                                 swallowbase++;
318                                 break;
319                         case OTH_GLYPH:
320                                 if (conditionals[i].predecessor < S_sw_tl)
321                                         swallowbase++;
322                                 break;
323                 }
324         }
325
326         condnum = tilenum = 0;
327         for (i = 0; i < NUMMONS; i++) {
328                 tilemap[GLYPH_MON_OFF+i] = tilenum;
329                 tilemap[GLYPH_PET_OFF+i] = tilenum;
330                 tilemap[GLYPH_DETECT_OFF+i] = tilenum;
331                 tilemap[GLYPH_RIDDEN_OFF+i] = tilenum;
332                 tilemap[GLYPH_BODY_OFF+i] = corpsetile;
333                 j = GLYPH_SWALLOW_OFF + 8*i;
334                 tilemap[j] = swallowbase;
335                 tilemap[j+1] = swallowbase+1;
336                 tilemap[j+2] = swallowbase+2;
337                 tilemap[j+3] = swallowbase+3;
338                 tilemap[j+4] = swallowbase+4;
339                 tilemap[j+5] = swallowbase+5;
340                 tilemap[j+6] = swallowbase+6;
341                 tilemap[j+7] = swallowbase+7;
342                 tilenum++;
343                 while (conditionals[condnum].sequence == MON_GLYPH &&
344                         conditionals[condnum].predecessor == i) {
345                         condnum++;
346                         tilenum++;
347                 }
348         }
349         tilemap[GLYPH_INVISIBLE] = tilenum++;
350         lastmontile = tilenum - 1;
351
352         for (i = 0; i < NUM_OBJECTS; i++) {
353                 tilemap[GLYPH_OBJ_OFF+i] = tilenum;
354                 tilenum++;
355                 while (conditionals[condnum].sequence == OBJ_GLYPH &&
356                         conditionals[condnum].predecessor == i) {
357                         condnum++;
358                         tilenum++;
359                 }
360         }
361         lastobjtile = tilenum - 1;
362
363         for (i = 0; i < (MAXPCHARS - MAXEXPCHARS); i++) {
364                 tilemap[GLYPH_CMAP_OFF+i] = tilenum;
365                 tilenum++;
366                 while (conditionals[condnum].sequence == OTH_GLYPH &&
367                         conditionals[condnum].predecessor == i) {
368                         condnum++;
369                         tilenum++;
370                 }
371         }
372
373         for (i = 0; i < (MAXEXPCHARS * EXPL_MAX); i++) {
374                 tilemap[GLYPH_EXPLODE_OFF+i] = tilenum;
375                 tilenum++;
376                 while (conditionals[condnum].sequence == OTH_GLYPH &&
377                         conditionals[condnum].predecessor == (i + MAXPCHARS)) {
378                         condnum++;
379                         tilenum++;
380                 }
381         }
382
383         for (i = 0; i < NUM_ZAP << 2; i++) {
384                 tilemap[GLYPH_ZAP_OFF+i] = tilenum;
385                 tilenum++;
386                 while (conditionals[condnum].sequence == OTH_GLYPH &&
387                         conditionals[condnum].predecessor == (i + MAXEXPCHARS)) {
388                         condnum++;
389                         tilenum++;
390                 }
391         }
392
393         for (i = 0; i < WARNCOUNT; i++) {
394                 tilemap[GLYPH_WARNING_OFF+i] = tilenum;
395                 tilenum++;
396         }
397
398         lastothtile = tilenum - 1;
399 }
400
401 const char *prolog[] = {
402         "",
403         "",
404         "void",
405         "substitute_tiles(plev)",
406         "d_level *plev;",
407         "{",
408         "\tint i;",
409         ""
410 };
411
412 const char *epilog[] = {
413         "}"
414 };
415
416 /* write out the substitutions in an easily-used form. */
417 void
418 process_substitutions(ofp)
419 FILE *ofp;
420 {
421         int i, j, k, span, start;
422
423         fprintf(ofp, "\n\n");
424
425         j = 0;  /* unnecessary */
426         span = -1;
427         for (i = 0; i < SIZE(substitutes); i++) {
428             if (i == 0
429                 || substitutes[i].first_glyph != substitutes[j].first_glyph
430                 || substitutes[i].last_glyph != substitutes[j].last_glyph) {
431                         j = i;
432                         span++;
433                         fprintf(ofp, "short std_tiles%d[] = { ", span);
434                         for (k = substitutes[i].first_glyph;
435                                 k < substitutes[i].last_glyph; k++)
436                                         fprintf(ofp, "%d, ", tilemap[k]);
437                         fprintf(ofp, "%d };\n",
438                                 tilemap[substitutes[i].last_glyph]);
439             }
440         }
441
442         for (i = 0; i < SIZE(prolog); i++) {
443                 fprintf(ofp, "%s\n", prolog[i]);
444         }
445         j = -1;
446         span = -1;
447         start = lastothtile + 1;
448         for (i = 0; i < SIZE(substitutes); i++) {
449             if (i == 0
450                     || substitutes[i].first_glyph != substitutes[j].first_glyph
451                     || substitutes[i].last_glyph != substitutes[j].last_glyph) {
452                 if (i != 0) {   /* finish previous span */
453                     fprintf(ofp, "\t} else {\n");
454                     fprintf(ofp, "\t\tfor (i = %d; i <= %d; i++)\n",
455                                         substitutes[j].first_glyph,
456                                         substitutes[j].last_glyph);
457                     fprintf(ofp, "\t\t\tglyph2tile[i] = std_tiles%d[i - %d];\n",
458                                         span, substitutes[j].first_glyph);
459                     fprintf(ofp, "\t}\n\n");
460                 }
461                 j = i;
462                 span++;
463             }
464             if (i != j) fprintf(ofp, "\t} else ");
465             fprintf(ofp, "\tif (%s) {\n", substitutes[i].level_test);
466             fprintf(ofp, "\t\tfor (i = %d; i <= %d; i++)\n",
467                                 substitutes[i].first_glyph,
468                                 substitutes[i].last_glyph);
469             fprintf(ofp, "\t\t\tglyph2tile[i] = %d + i - %d;\n",
470                                 start, substitutes[i].first_glyph);
471             start += substitutes[i].last_glyph - substitutes[i].first_glyph + 1;
472         }
473         /* finish last span */
474         fprintf(ofp, "\t} else {\n");
475         fprintf(ofp, "\t\tfor (i = %d; i <= %d; i++)\n",
476                             substitutes[j].first_glyph,
477                             substitutes[j].last_glyph);
478         fprintf(ofp, "\t\t\tglyph2tile[i] = std_tiles%d[i - %d];\n",
479                             span, substitutes[j].first_glyph);
480         fprintf(ofp, "\t}\n\n");
481
482         for (i = 0; i < SIZE(epilog); i++) {
483                 fprintf(ofp, "%s\n", epilog[i]);
484         }
485
486         fprintf(ofp, "\nint total_tiles_used = %d;\n", start);
487         lastothtile = start - 1;
488 }
489
490 int main()
491 {
492     register int i;
493     char filename[30];
494     FILE *ofp;
495
496     init_tilemap();
497
498     /*
499      * create the source file, "tile.c"
500      */
501     Sprintf(filename, SOURCE_TEMPLATE, TILE_FILE);
502     if (!(ofp = fopen(filename, "w"))) {
503             perror(filename);
504             exit(EXIT_FAILURE);
505     }
506     fprintf(ofp,"/* This file is automatically generated.  Do not edit. */\n");
507     fprintf(ofp,"\n#include \"hack.h\"\n\n");
508     fprintf(ofp,"short glyph2tile[MAX_GLYPH] = {\n");
509
510     for (i = 0; i < MAX_GLYPH; i++) {
511         fprintf(ofp,"%2d,%c", tilemap[i], (i % 12) ? ' ' : '\n');
512     }
513     fprintf(ofp,"%s};\n", (i % 12) ? "\n" : "");
514
515     process_substitutions(ofp);
516
517     fprintf(ofp,"\n#define MAXMONTILE %d\n", lastmontile);
518     fprintf(ofp,"#define MAXOBJTILE %d\n", lastobjtile);
519     fprintf(ofp,"#define MAXOTHTILE %d\n", lastothtile);
520
521     fprintf(ofp,"\n/*tile.c*/\n");
522
523     fclose(ofp);
524     exit(EXIT_SUCCESS);
525     /*NOTREACHED*/
526     return 0;
527 }
528
529 #endif  /* TILETEXT */