Files
nethack/win/share/tilemap.c
nhmall 2baadd6a29 header files sym.h and defsym.h
There were multiple symbol-related lists that had to be kept
in sync in various places.

Consolidate some of that into a single new file
    defsym.h
with a set of morphing macros that can be custom-called from
the various places that use the sym info without maintaining
multiple occurrences. Most maintenance can be done there.

Rename monsym.h to sym.h since it looks after some
symbols not related to monsters now too.

The defsym.h header file is included in multiple places to
produce different code depending on its use and the controlling
macro definitions in place prior to including it.

Its purpose is to have a definitive source for
pchar, objclass and mon symbol maintenance.

The controlling macros used to morph the resulting code are
used in these places:
  - in include/sym.h for enums of some S_ symbol values
    (define PCHAR_ENUM, MONSYMS_ENUM prior to #include defsym.h)
  - in include/objclass.h for enums of some S_ symbol values
    (define OBJCLASS_ENUM prior to #include defsym.h)
  - in src/symbols.c for parsing S_ entries in config files
    (define PCHAR_PARSE, MONSYMS_PARSE, OBJCLASS_PARSE prior
    to #include defsym.h)
  - in src/drawing.c for initializing some data structures/arrays
    (define PCHAR_DRAWING, MONSYMS_DRAWING, OBJCLASS_DRAWING prior
    to #include defsym.h)
  - in win/share/tilemap.c for processing a tile file
    (define PCHAR_TILES prior to #include defsym.h).
2021-08-10 13:35:25 -04:00

749 lines
24 KiB
C

/* NetHack 3.7 tilemap.c $NHDT-Date: 1596498340 2020/08/03 23:45:40 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.47 $ */
/* Copyright (c) 2016 by Michael Allison */
/* NetHack may be freely redistributed. See license for details. */
/*
* This source file is compiled twice:
* once without TILETEXT defined to make tilemap.{o,obj},
* then again with it defined to produce tiletxt.{o,obj}.
*/
#include "config.h"
#include "pm.h"
#include "onames.h"
#include "permonst.h"
#include "objclass.h"
#include "sym.h"
#include "rm.h"
#include "display.h"
#define Fprintf (void) fprintf
/*
* Defining OBTAIN_TILEMAP to get a listing of the tile-mappings
* for debugging purposes requires that your link to produce
* the tilemap utility must also include:
* objects.o, monst.o drawing.o
*/
/* #define OBTAIN_TILEMAP */
#if defined(OBTAIN_TILEMAP) && !defined(TILETEXT)
FILE *tilemap_file;
#endif
const char *tilename(int, int, int);
void init_tilemap(void);
void process_substitutions(FILE *);
boolean acceptable_tilename(int, int, const char *, const char *);
#if defined(MICRO) || defined(WIN32)
#undef exit
#if !defined(MSDOS) && !defined(WIN32)
extern void exit(int);
#endif
#endif
enum {MON_GLYPH, OBJ_GLYPH, OTH_GLYPH, TERMINATOR = -1};
#define EXTRA_SCROLL_DESCR_COUNT ((SCR_BLANK_PAPER - SCR_STINKING_CLOUD) - 1)
/* note that the ifdefs here should be the opposite sense from monst.c/
* objects.c/rm.h
*/
struct conditionals_t {
int sequence, predecessor;
const char *name;
} conditionals[] = {
#ifndef CHARON /* not supported */
{ MON_GLYPH, PM_HELL_HOUND, "Cerberus" },
#endif
/* commented out in monst.c at present */
{ MON_GLYPH, PM_SHOCKING_SPHERE, "beholder" },
{ MON_GLYPH, PM_BABY_SILVER_DRAGON, "baby shimmering dragon" },
{ MON_GLYPH, PM_SILVER_DRAGON, "shimmering dragon" },
{ MON_GLYPH, PM_JABBERWOCK, "vorpal jabberwock" },
{ MON_GLYPH, PM_VAMPIRE_LEADER, "vampire mage" },
#ifndef CHARON /* not supported yet */
{ MON_GLYPH, PM_CROESUS, "Charon" },
#endif
#ifndef MAIL_STRUCTURES
{ MON_GLYPH, PM_FAMINE, "mail daemon" },
#endif
/* commented out in monst.c at present */
{ MON_GLYPH, PM_SHAMAN_KARNOV, "Earendil" },
{ MON_GLYPH, PM_SHAMAN_KARNOV, "Elwing" },
/* commented out in monst.c at present */
{ MON_GLYPH, PM_CHROMATIC_DRAGON, "Goblin King" },
{ MON_GLYPH, PM_NEANDERTHAL, "High-elf" },
/* objects commented out in objects.c at present */
{ OBJ_GLYPH, SILVER_DRAGON_SCALE_MAIL, "shimmering dragon scale mail" },
{ OBJ_GLYPH, SILVER_DRAGON_SCALES, "shimmering dragon scales" },
/* allow slime mold to look like slice of pizza, since we
* don't know what a slime mold should look like when renamed anyway
*/
#ifndef MAIL_STRUCTURES
{ OBJ_GLYPH, SCR_STINKING_CLOUD + EXTRA_SCROLL_DESCR_COUNT,
"stamped / mail" },
#endif
{ TERMINATOR, 0, 0 }
};
/*
* Some entries in glyph2tile[] should be substituted for on various levels.
* The tiles used for the substitute entries will follow the usual ones in
* other.txt in the order given here, which should have every substitution
* for the same set of tiles grouped together. You will have to change
* more code in process_substitutions()/substitute_tiles() if the sets
* overlap in the future.
*/
struct substitute {
int first_glyph, last_glyph;
const char *sub_name; /* for explanations */
const char *level_test;
} substitutes[] = { { GLYPH_CMAP_OFF + S_vwall, GLYPH_CMAP_OFF + S_trwall,
"mine walls", "In_mines(plev)" },
{ GLYPH_CMAP_OFF + S_vwall, GLYPH_CMAP_OFF + S_trwall,
"gehennom walls", "In_hell(plev)" },
{ GLYPH_CMAP_OFF + S_vwall, GLYPH_CMAP_OFF + S_trwall,
"knox walls", "Is_knox(plev)" },
{ GLYPH_CMAP_OFF + S_vwall, GLYPH_CMAP_OFF + S_trwall,
"sokoban walls", "In_sokoban(plev)" } };
#if defined(TILETEXT) || defined(OBTAIN_TILEMAP)
/*
* file_entry is the position of the tile within the monsters/objects/other set
*/
const char *
tilename(int set, int file_entry, int gend)
{
int i, j, condnum, tilenum, gendnum;
static char buf[BUFSZ];
(void) def_char_to_objclass(']');
condnum = tilenum = gendnum = 0;
for (i = 0; i < NUMMONS; i++) {
if (set == MON_GLYPH && tilenum == file_entry && gend == 0)
return mons[i].pmnames[NEUTRAL];
for (condnum = 0; conditionals[condnum].sequence != -1; ++condnum) {
if (conditionals[condnum].sequence == MON_GLYPH
&& conditionals[condnum].predecessor == i) {
tilenum += 2;
if (set == MON_GLYPH && tilenum == file_entry)
return conditionals[condnum].name;
}
}
tilenum += 2;
}
if (set == MON_GLYPH && tilenum == file_entry)
return "invisible monster";
tilenum = 0; /* set-relative number */
for (i = 0; i < NUM_OBJECTS; i++) {
/* prefer to give the description - that's all the tile's
* appearance should reveal */
if (set == OBJ_GLYPH && tilenum == file_entry) {
if (!obj_descr[i].oc_descr)
return obj_descr[i].oc_name;
if (!obj_descr[i].oc_name)
return obj_descr[i].oc_descr;
Sprintf(buf, "%s / %s", obj_descr[i].oc_descr,
obj_descr[i].oc_name);
return buf;
}
for (condnum = 0; conditionals[condnum].sequence != -1; ++condnum) {
if (conditionals[condnum].sequence == OBJ_GLYPH
&& conditionals[condnum].predecessor == i) {
tilenum++;
if (set == OBJ_GLYPH && tilenum == file_entry)
return conditionals[condnum].name;
}
}
tilenum++;
}
tilenum = 0; /* set-relative number */
for (i = 0; i < (MAXPCHARS - MAXEXPCHARS); i++) {
if (set == OTH_GLYPH && tilenum == file_entry) {
if (*defsyms[i].explanation) {
return defsyms[i].explanation;
} else {
Sprintf(buf, "cmap %d", tilenum);
return buf;
}
}
for (condnum = 0; conditionals[condnum].sequence != -1; ++condnum) {
if (conditionals[condnum].sequence == OTH_GLYPH
&& conditionals[condnum].predecessor == i) {
tilenum++;
if (set == OTH_GLYPH && tilenum == file_entry)
return conditionals[condnum].name;
}
}
tilenum++;
}
/* explosions */
tilenum = MAXPCHARS - MAXEXPCHARS;
i = file_entry - tilenum;
if (i < (MAXEXPCHARS * EXPL_MAX)) {
if (set == OTH_GLYPH) {
static const char *explosion_types[] = {
/* hack.h */
"dark", "noxious", "muddy", "wet", "magical", "fiery",
"frosty"
};
Sprintf(buf, "explosion %s %d", explosion_types[i / MAXEXPCHARS],
i % MAXEXPCHARS);
return buf;
}
}
tilenum += (MAXEXPCHARS * EXPL_MAX);
i = file_entry - tilenum;
if (i < (NUM_ZAP << 2)) {
if (set == OTH_GLYPH) {
Sprintf(buf, "zap %d %d", i / 4, i % 4);
return buf;
}
}
tilenum += (NUM_ZAP << 2);
i = file_entry - tilenum;
if (i < WARNCOUNT) {
if (set == OTH_GLYPH) {
Sprintf(buf, "warning %d", i);
return buf;
}
}
tilenum += WARNCOUNT;
i = file_entry - tilenum;
if (i < 1) {
if (set == OTH_GLYPH) {
Sprintf(buf, "unexplored");
return buf;
}
}
tilenum += 1;
i = file_entry - tilenum;
if (i < 1) {
if (set == OTH_GLYPH) {
Sprintf(buf, "nothing");
return buf;
}
}
tilenum++;
for (i = 0; i < SIZE(substitutes); i++) {
j = file_entry - tilenum;
if (j <= substitutes[i].last_glyph - substitutes[i].first_glyph) {
if (set == OTH_GLYPH) {
Sprintf(buf, "sub %s %d", substitutes[i].sub_name, j);
return buf;
}
}
tilenum += substitutes[i].last_glyph - substitutes[i].first_glyph + 1;
}
Sprintf(buf, "unknown %d %d", set, file_entry);
return buf;
}
#endif
#ifndef TILETEXT
#define TILE_FILE "tile.c"
#ifdef AMIGA
#define SOURCE_TEMPLATE "NH:src/%s"
#else
#ifdef MAC
#define SOURCE_TEMPLATE ":src:%s"
#else
#define SOURCE_TEMPLATE "../src/%s"
#endif
#endif
struct tilemap_t {
short tilenum;
#ifdef OBTAIN_TILEMAP
char name[80];
int glyph;
#endif
} tilemap[MAX_GLYPH];
#ifndef STATUES_DONT_LOOK_LIKE_MONSTERS
int lastmontile, lastobjtile, lastothtile, laststatuetile;
#else
int lastmontile, lastobjtile, lastothtile;
#endif
/* Number of tiles for invisible monsters */
#define NUM_INVIS_TILES 1
/*
* set up array to map glyph numbers to tile numbers
*
* assumes tiles are numbered sequentially through monsters/objects/other,
* with entries for all supported compilation options. monsters have two
* tiles for each (male + female).
*
* "other" contains cmap and zaps (the swallow sets are a repeated portion
* of cmap), as well as the "flash" glyphs for the new warning system
* introduced in 3.3.1.
*/
void
init_tilemap(void)
{
int i, j, condnum, tilenum;
int corpsetile, swallowbase;
int file_entry = 0;
#ifdef OBTAIN_TILEMAP
tilemap_file = fopen("tilemappings.lst", "w");
Fprintf(tilemap_file, "NUMMONS = %d\n", NUMMONS);
Fprintf(tilemap_file, "NUM_OBJECTS = %d\n", NUM_OBJECTS);
Fprintf(tilemap_file, "MAXEXPCHARS = %d\n", MAXEXPCHARS);
Fprintf(tilemap_file, "MAXPCHARS = %d\n", MAXPCHARS);
Fprintf(tilemap_file, "MAX_GLYPH = %d\n", MAX_GLYPH);
Fprintf(tilemap_file, "GLYPH_MON_OFF = %d\n", GLYPH_MON_OFF);
Fprintf(tilemap_file, "GLYPH_PET_OFF = %d\n", GLYPH_PET_OFF);
Fprintf(tilemap_file, "GLYPH_DETECT_OFF = %d\n", GLYPH_DETECT_OFF);
Fprintf(tilemap_file, "GLYPH_RIDDEN_OFF = %d\n", GLYPH_RIDDEN_OFF);
Fprintf(tilemap_file, "GLYPH_BODY_OFF = %d\n", GLYPH_BODY_OFF);
Fprintf(tilemap_file, "GLYPH_SWALLOW_OFF = %d\n", GLYPH_SWALLOW_OFF);
#endif
for (i = 0; i < MAX_GLYPH; i++) {
tilemap[i].tilenum = -1;
}
corpsetile = NUMMONS + NUMMONS + NUM_INVIS_TILES + CORPSE;
swallowbase = NUMMONS + NUMMONS + NUM_INVIS_TILES + NUM_OBJECTS + S_sw_tl;
/* add number compiled out */
for (i = 0; conditionals[i].sequence != TERMINATOR; i++) {
switch (conditionals[i].sequence) {
case MON_GLYPH:
corpsetile += 2;
swallowbase += 2;
break;
case OBJ_GLYPH:
if (conditionals[i].predecessor < CORPSE)
corpsetile++;
swallowbase++;
break;
case OTH_GLYPH:
if (conditionals[i].predecessor < S_sw_tl)
swallowbase++;
break;
}
}
tilenum = 0;
for (i = 0; i < NUMMONS; i++) {
#ifdef OBTAIN_TILEMAP
char buf[256];
#endif
tilemap[GLYPH_MON_OFF + i].tilenum = tilenum;
tilemap[GLYPH_PET_OFF + i].tilenum = tilenum;
tilemap[GLYPH_DETECT_OFF + i].tilenum = tilenum;
tilemap[GLYPH_RIDDEN_OFF + i].tilenum = tilenum;
tilemap[GLYPH_BODY_OFF + i].tilenum = corpsetile;
j = GLYPH_SWALLOW_OFF + 8 * i;
tilemap[j].tilenum = swallowbase;
tilemap[j + 1].tilenum = swallowbase + 1;
tilemap[j + 2].tilenum = swallowbase + 2;
tilemap[j + 3].tilenum = swallowbase + 3;
tilemap[j + 4].tilenum = swallowbase + 4;
tilemap[j + 5].tilenum = swallowbase + 5;
tilemap[j + 6].tilenum = swallowbase + 6;
tilemap[j + 7].tilenum = swallowbase + 7;
#ifdef OBTAIN_TILEMAP
Sprintf(buf, "%s (%d)", tilename(MON_GLYPH, file_entry, 0), file_entry);
Sprintf(tilemap[GLYPH_MON_OFF + i].name,
"%s (%d)", buf, i);
Sprintf(tilemap[GLYPH_PET_OFF + i].name,
"%s %s (%d)", buf, "pet", i);
Sprintf(tilemap[GLYPH_DETECT_OFF + i].name,
"%s %s (%d)", buf, "detected", i);
Sprintf(tilemap[GLYPH_RIDDEN_OFF + i].name,
"%s %s (%d)", buf, "ridden", i);
Sprintf(tilemap[GLYPH_BODY_OFF + i].name,
"%s %s (%d)", buf, "corpse", i);
Sprintf(tilemap[j + 0].name, "%s swallow0 (%d)", buf, i);
Sprintf(tilemap[j + 1].name, "%s swallow1 (%d)", buf, i);
Sprintf(tilemap[j + 2].name, "%s swallow2 (%d)", buf, i);
Sprintf(tilemap[j + 3].name, "%s swallow3 (%d)", buf, i);
Sprintf(tilemap[j + 4].name, "%s swallow4 (%d)", buf, i);
Sprintf(tilemap[j + 5].name, "%s swallow5 (%d)", buf, i);
Sprintf(tilemap[j + 6].name, "%s swallow6 (%d)", buf, i);
Sprintf(tilemap[j + 7].name, "%s swallow7 (%d)", buf, i);
#endif
for (condnum = 0; conditionals[condnum].sequence != -1; condnum++) {
if (conditionals[condnum].sequence == MON_GLYPH
&& conditionals[condnum].predecessor == i) {
tilenum += 2;
file_entry += 2;
#ifdef OBTAIN_TILEMAP
Fprintf(tilemap_file, "skipping monst %s (%d)\n",
tilename(MON_GLYPH, file_entry, 0), file_entry);
#endif
}
}
tilenum += 2; /* male + female tiles for each */
file_entry += 2;
}
tilemap[GLYPH_INVISIBLE].tilenum = tilenum++;
file_entry++;
#ifdef OBTAIN_TILEMAP
Sprintf(tilemap[GLYPH_INVISIBLE].name,
"%s (%d)", "invisible mon", file_entry);
#endif
lastmontile = tilenum - 1;
file_entry = 0;
for (i = 0; i < NUM_OBJECTS; i++) {
tilemap[GLYPH_OBJ_OFF + i].tilenum = tilenum;
#ifdef OBTAIN_TILEMAP
Sprintf(tilemap[GLYPH_OBJ_OFF + i].name, "%s (%d)",
tilename(OBJ_GLYPH, file_entry, 0), file_entry);
#endif
for (condnum = 0; conditionals[condnum].sequence != -1; condnum++) {
if (conditionals[condnum].sequence == OBJ_GLYPH
&& conditionals[condnum].predecessor == i) {
tilenum++;
file_entry++;
#ifdef OBTAIN_TILEMAP
Fprintf(tilemap_file, "skipping obj %s (%d)\n",
tilename(OBJ_GLYPH, file_entry, 0), file_entry);
#endif
}
}
tilenum++;
file_entry++;
}
lastobjtile = tilenum - 1;
file_entry = 0;
for (i = 0; i < (MAXPCHARS - MAXEXPCHARS); i++) {
tilemap[GLYPH_CMAP_OFF + i].tilenum = tilenum;
#ifdef OBTAIN_TILEMAP
Sprintf(tilemap[GLYPH_CMAP_OFF + i].name, "cmap %s (%d)",
tilename(OTH_GLYPH, file_entry, 0), file_entry);
#endif
tilenum++;
file_entry++;
for (condnum = 0; conditionals[condnum].sequence != -1; condnum++) {
if (conditionals[condnum].sequence == OTH_GLYPH
&& conditionals[condnum].predecessor == i) {
tilenum++;
file_entry++;
#ifdef OBTAIN_TILEMAP
Fprintf(tilemap_file, "skipping cmap %s (%d)\n",
tilename(OTH_GLYPH, file_entry, 0), file_entry);
#endif
}
}
}
for (i = 0; i < (MAXEXPCHARS * EXPL_MAX); i++) {
tilemap[GLYPH_EXPLODE_OFF + i].tilenum = tilenum;
#ifdef OBTAIN_TILEMAP
Sprintf(tilemap[GLYPH_EXPLODE_OFF + i].name, "explosion %s (%d)",
tilename(OTH_GLYPH, file_entry, 0), file_entry);
#endif
for (condnum = 0; conditionals[condnum].sequence != -1; condnum++) {
if (conditionals[condnum].sequence == OTH_GLYPH
&& conditionals[condnum].predecessor == i + MAXPCHARS) {
tilenum++;
file_entry++;
#ifdef OBTAIN_TILEMAP
Fprintf(tilemap_file, "skipping explosion %s (%d)\n",
tilename(OTH_GLYPH, file_entry, 0), file_entry);
#endif
}
}
tilenum++;
file_entry++;
}
for (i = 0; i < NUM_ZAP << 2; i++) {
tilemap[GLYPH_ZAP_OFF + i].tilenum = tilenum;
#ifdef OBTAIN_TILEMAP
Sprintf(tilemap[GLYPH_ZAP_OFF + i].name, "zap %s (%d)",
tilename(OTH_GLYPH, file_entry, 0), file_entry);
#endif
tilenum++;
file_entry++;
for (condnum = 0; conditionals[condnum].sequence != -1; condnum++) {
if (conditionals[condnum].sequence == OTH_GLYPH
&& conditionals[condnum].predecessor == (i + MAXEXPCHARS)) {
#ifdef OBTAIN_TILEMAP
Fprintf(tilemap_file, "skipping zap %s (%d)\n",
tilename(OTH_GLYPH, file_entry, 0), file_entry);
#endif
file_entry++;
tilenum++;
}
}
}
for (i = 0; i < WARNCOUNT; i++) {
tilemap[GLYPH_WARNING_OFF + i].tilenum = tilenum;
#ifdef OBTAIN_TILEMAP
Sprintf(tilemap[GLYPH_WARNING_OFF + i].name, "%s (%d)",
tilename(OTH_GLYPH, file_entry, 0), file_entry);
#endif
tilenum++;
file_entry++;
}
for (i = 0; i < 1; i++) {
tilemap[GLYPH_UNEXPLORED_OFF + i].tilenum = tilenum;
#ifdef OBTAIN_TILEMAP
Sprintf(tilemap[GLYPH_UNEXPLORED_OFF + i].name, "unexplored %s (%d)",
tilename(OTH_GLYPH, file_entry, 0), file_entry);
#endif
tilenum++;
file_entry++;
}
for (i = 0; i < 1; i++) {
tilemap[GLYPH_NOTHING + i].tilenum = tilenum;
#ifdef OBTAIN_TILEMAP
Sprintf(tilemap[GLYPH_NOTHING + i].name, " nothing %s (%d)",
tilename(OTH_GLYPH, file_entry, 0), file_entry);
#endif
tilenum++;
file_entry++;
}
#ifdef STATUES_DONT_LOOK_LIKE_MONSTERS
/* statue patch: statues still use the same glyph as in 3.4.x */
for (i = 0; i < NUMMONS; i++) {
tilemap[GLYPH_STATUE_OFF + i].tilenum
= tilemap[GLYPH_OBJ_OFF + STATUE].tilenum;
#ifdef OBTAIN_TILEMAP
Sprintf(tilemap[GLYPH_STATUE_OFF + i].name, "%s (%d)",
tilename(OTH_GLYPH, file_entry, 0), file_entry);
#endif
}
#endif
lastothtile = tilenum - 1;
#ifndef STATUES_DONT_LOOK_LIKE_MONSTERS
file_entry = 0;
/* fast-forward over the substitutes to grayscale statues loc */
for (i = 0; i < SIZE(substitutes); i++) {
tilenum += substitutes[i].last_glyph - substitutes[i].first_glyph + 1;
}
/* statue patch: statues look more like the monster */
for (i = 0; i < NUMMONS; i++) {
tilemap[GLYPH_STATUE_OFF + i].tilenum = tilenum;
#ifdef OBTAIN_TILEMAP
Sprintf(tilemap[GLYPH_STATUE_OFF + i].name, "statue of %s (%d)",
tilename(MON_GLYPH, file_entry, 0), file_entry);
#endif
for (condnum = 0; conditionals[condnum].sequence != -1; condnum++) {
if (conditionals[condnum].sequence == MON_GLYPH
&& conditionals[condnum].predecessor == i) {
file_entry += 2; /* skip female tile too */
tilenum += 2;
#ifdef OBTAIN_TILEMAP
Fprintf(tilemap_file, "skipping statue of %s (%d)\n",
tilename(MON_GLYPH, file_entry, 0), file_entry);
#endif
}
}
tilenum += 2;
file_entry += 2;
}
laststatuetile = tilenum - 2;
#endif /* STATUES_DONT_LOOK_LIKE_MONSTERS */
#ifdef OBTAIN_TILEMAP
for (i = 0; i < MAX_GLYPH; ++i) {
Fprintf(tilemap_file, "[%04d] [%04d] %-80s\n",
i, tilemap[i].tilenum, tilemap[i].name);
}
fclose(tilemap_file);
#endif
}
const char *prolog[] = { "", "void", "substitute_tiles(d_level *plev)",
"{", " int i;", "" };
const char *epilog[] = { " return;", "}" };
/* write out the substitutions in an easily-used form. */
void
process_substitutions(FILE *ofp)
{
static const char Dent[] = " "; /* 4 space indentation */
int i, j, k, span, start;
Fprintf(ofp, "\n");
j = 0; /* unnecessary */
span = -1;
for (i = 0; i < SIZE(substitutes); i++) {
if (i == 0 || substitutes[i].first_glyph != substitutes[j].first_glyph
|| substitutes[i].last_glyph != substitutes[j].last_glyph) {
j = i;
span++;
Fprintf(ofp, "short std_tiles%d[] = { ", span);
for (k = substitutes[i].first_glyph;
k < substitutes[i].last_glyph; k++)
Fprintf(ofp, "%d, ", tilemap[k].tilenum);
Fprintf(ofp, "%d };\n", tilemap[substitutes[i].last_glyph].tilenum);
}
}
for (i = 0; i < SIZE(prolog); i++) {
Fprintf(ofp, "%s\n", prolog[i]);
}
j = -1;
span = -1;
start = lastothtile + 1;
for (i = 0; i < SIZE(substitutes); i++) {
if (i == 0 || substitutes[i].first_glyph != substitutes[j].first_glyph
|| substitutes[i].last_glyph != substitutes[j].last_glyph) {
if (i != 0) { /* finish previous span */
Fprintf(ofp, "%s} else {\n", Dent);
Fprintf(ofp, "%s%sfor (i = %d; i <= %d; i++)\n", Dent, Dent,
substitutes[j].first_glyph, substitutes[j].last_glyph);
Fprintf(ofp, "%s%s%sglyph2tile[i] = std_tiles%d[i - %d];\n",
Dent, Dent, Dent, span, substitutes[j].first_glyph);
Fprintf(ofp, "%s}\n\n", Dent);
}
j = i;
span++;
}
Fprintf(ofp, "%s%sif (%s) {\n", Dent, (i == j) ? "" : "} else ",
substitutes[i].level_test);
Fprintf(ofp, "%s%sfor (i = %d; i <= %d; i++)\n", Dent, Dent,
substitutes[i].first_glyph, substitutes[i].last_glyph);
Fprintf(ofp, "%s%s%sglyph2tile[i] = %d + i - %d;\n",
Dent, Dent, Dent, start, substitutes[i].first_glyph);
start += substitutes[i].last_glyph - substitutes[i].first_glyph + 1;
}
/* finish last span */
Fprintf(ofp, "%s} else {\n", Dent);
Fprintf(ofp, "%s%sfor (i = %d; i <= %d; i++)\n", Dent, Dent,
substitutes[j].first_glyph, substitutes[j].last_glyph);
Fprintf(ofp, "%s%s%sglyph2tile[i] = std_tiles%d[i - %d];\n",
Dent, Dent, Dent, span, substitutes[j].first_glyph);
Fprintf(ofp, "%s}\n", Dent);
for (i = 0; i < SIZE(epilog); i++) {
Fprintf(ofp, "%s\n", epilog[i]);
}
lastothtile = start - 1;
#ifndef STATUES_DONT_LOOK_LIKE_MONSTERS
start = laststatuetile + 1;
#endif
Fprintf(ofp, "\nint total_tiles_used = %d;\n", start);
}
#ifdef OBTAIN_TILEMAP
extern void monst_globals_init(void);
extern void objects_globals_init(void);
#endif
DISABLE_WARNING_UNREACHABLE_CODE
int
main(int argc UNUSED, char *argv[] UNUSED)
{
register int i;
char filename[30];
FILE *ofp;
#ifdef OBTAIN_TILEMAP
objects_globals_init();
monst_globals_init();
#endif
init_tilemap();
/*
* create the source file, "tile.c"
*/
Sprintf(filename, SOURCE_TEMPLATE, TILE_FILE);
if (!(ofp = fopen(filename, "w"))) {
perror(filename);
exit(EXIT_FAILURE);
}
Fprintf(ofp,
"/* This file is automatically generated. Do not edit. */\n");
Fprintf(ofp, "\n#include \"hack.h\"\n");
Fprintf(ofp, "\nshort glyph2tile[MAX_GLYPH] = {\n");
for (i = 0; i < MAX_GLYPH; i++) {
Fprintf(ofp, " %4d,", tilemap[i].tilenum);
if ((i % 12) == 11 || i == MAX_GLYPH - 1)
Fprintf(ofp, "\n");
}
Fprintf(ofp, "};\n");
process_substitutions(ofp);
Fprintf(ofp, "\n#define MAXMONTILE %d\n", lastmontile);
Fprintf(ofp, "#define MAXOBJTILE %d\n", lastobjtile);
Fprintf(ofp, "#define MAXOTHTILE %d\n", lastothtile);
#ifndef STATUES_DONT_LOOK_LIKE_MONSTERS
Fprintf(ofp, "/* #define MAXSTATUETILE %d */\n", laststatuetile);
#endif
Fprintf(ofp, "\n/*tile.c*/\n");
(void) fclose(ofp);
exit(EXIT_SUCCESS);
/*NOTREACHED*/
return 0;
}
RESTORE_WARNINGS
#endif /* TILETEXT */
struct {
int idx;
const char *tilelabel;
const char *expectedlabel;
} altlabels[MAXPCHARS] = {
#define PCHAR_TILES
#include "defsym.h"
#undef PCHAR_TILES
};
boolean
acceptable_tilename(int glyph_set, int idx, const char *encountered,
const char *expected UNUSED)
{
if (glyph_set == OTH_GLYPH) {
if (idx >= 0 && idx < SIZE(altlabels)) {
#if 0
if (!strcmp(altlabels[idx].expectedlabel, expected)) {
if (!strcmp(altlabels[idx].tilelabel, encountered))
return TRUE;
}
#else
if (!strcmp(altlabels[idx].tilelabel, encountered))
return TRUE;
#endif
}
return FALSE;
}
return TRUE;
}
/*tilemap.c*/