Contributed by entrez Also, remove the iflags.use_color test from the many if-statements in reset_glyphmap(), and test and/or override it once before the assignment to gmap->color.
381 lines
12 KiB
C
381 lines
12 KiB
C
/* NetHack 3.7 symbols.c $NHDT-Date: 1596498214 2020/08/03 23:43:34 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.77 $ */
|
|
/* Copyright (c) NetHack Development Team 2020. */
|
|
/* NetHack may be freely redistributed. See license for details. */
|
|
|
|
#include "hack.h"
|
|
#include "tcap.h"
|
|
|
|
extern const uchar def_r_oc_syms[MAXOCLASSES]; /* drawing.c */
|
|
|
|
#if defined(TERMLIB) || defined(CURSES_GRAPHICS)
|
|
void (*decgraphics_mode_callback)(void) = 0; /* set in tty_start_screen() */
|
|
#endif /* TERMLIB || CURSES */
|
|
|
|
#ifdef PC9800
|
|
void (*ibmgraphics_mode_callback)(void) = 0; /* set in tty_start_screen() */
|
|
void (*ascgraphics_mode_callback)(void) = 0; /* set in tty_start_screen() */
|
|
#endif
|
|
#ifdef WIN32
|
|
void (*ibmgraphics_mode_callback)(void) = 0; /* set in tty_start_screen() */
|
|
#endif
|
|
#ifdef CURSES_GRAPHICS
|
|
void (*cursesgraphics_mode_callback)(void) = 0;
|
|
#endif
|
|
/*
|
|
* Explanations of the functions found below:
|
|
*
|
|
* init_symbols()
|
|
* Sets the current display symbols, the
|
|
* loadable symbols to the default NetHack
|
|
* symbols, including the rogue_syms rogue level
|
|
* symbols. This would typically be done
|
|
* immediately after execution begins. Any
|
|
* previously loaded external symbol sets are
|
|
* discarded.
|
|
*
|
|
* switch_symbols(arg)
|
|
* Called to swap in new current display symbols
|
|
* (showsyms) from either the default symbols,
|
|
* or from the loaded symbols.
|
|
*
|
|
* If (arg == 0) then showsyms are taken from
|
|
* defsyms, def_oc_syms, and def_monsyms.
|
|
*
|
|
* If (arg != 0), which is the normal expected
|
|
* usage, then showsyms are taken from the
|
|
* adjustable display symbols found in g.primary_syms.
|
|
* g.primary_syms may have been loaded from an external
|
|
* symbol file by config file options or interactively
|
|
* in the Options menu.
|
|
*
|
|
* assign_graphics(arg)
|
|
*
|
|
* This is used in the game core to toggle in and
|
|
* out of other {rogue} level display modes.
|
|
*
|
|
* If arg is ROGUESET, this places the rogue level
|
|
* symbols from g.rogue_syms into g.showsyms.
|
|
*
|
|
* If arg is PRIMARY, this places the symbols
|
|
* from g.primary_syms into g.showsyms.
|
|
*
|
|
* update_primary_symset()
|
|
* Update a member of the primary(primary_*) symbol set.
|
|
*
|
|
* update_rogue_symset()
|
|
* Update a member of the rogue (rogue_*) symbol set.
|
|
*
|
|
* update_ov_primary_symset()
|
|
* Update a member of the overrides for primary symbol set.
|
|
*
|
|
* update_ov_rogue_symset()
|
|
* Update a member of the overrides for rogue symbol set.
|
|
*
|
|
*/
|
|
|
|
void
|
|
init_symbols(void)
|
|
{
|
|
init_ov_primary_symbols();
|
|
init_ov_rogue_symbols();
|
|
init_primary_symbols();
|
|
init_showsyms();
|
|
init_rogue_symbols();
|
|
}
|
|
|
|
void
|
|
init_showsyms(void)
|
|
{
|
|
register int i;
|
|
|
|
for (i = 0; i < MAXPCHARS; i++)
|
|
g.showsyms[i + SYM_OFF_P] = defsyms[i].sym;
|
|
for (i = 0; i < MAXOCLASSES; i++)
|
|
g.showsyms[i + SYM_OFF_O] = def_oc_syms[i].sym;
|
|
for (i = 0; i < MAXMCLASSES; i++)
|
|
g.showsyms[i + SYM_OFF_M] = def_monsyms[i].sym;
|
|
for (i = 0; i < WARNCOUNT; i++)
|
|
g.showsyms[i + SYM_OFF_W] = def_warnsyms[i].sym;
|
|
for (i = 0; i < MAXOTHER; i++)
|
|
g.showsyms[i + SYM_OFF_X] = get_othersym(i, PRIMARY);
|
|
}
|
|
|
|
/* initialize defaults for the overrides to the rogue symset */
|
|
void
|
|
init_ov_rogue_symbols(void)
|
|
{
|
|
register int i;
|
|
|
|
for (i = 0; i < SYM_MAX; i++)
|
|
g.ov_rogue_syms[i] = (nhsym) 0;
|
|
}
|
|
/* initialize defaults for the overrides to the primary symset */
|
|
void
|
|
init_ov_primary_symbols(void)
|
|
{
|
|
register int i;
|
|
|
|
for (i = 0; i < SYM_MAX; i++)
|
|
g.ov_primary_syms[i] = (nhsym) 0;
|
|
}
|
|
|
|
nhsym
|
|
get_othersym(int idx, int which_set)
|
|
{
|
|
nhsym sym = (nhsym) 0;
|
|
int oidx = idx + SYM_OFF_X;
|
|
|
|
if (which_set == ROGUESET)
|
|
sym = g.ov_rogue_syms[oidx] ? g.ov_rogue_syms[oidx]
|
|
: g.rogue_syms[oidx];
|
|
else
|
|
sym = g.ov_primary_syms[oidx] ? g.ov_primary_syms[oidx]
|
|
: g.primary_syms[oidx];
|
|
if (!sym) {
|
|
switch(idx) {
|
|
case SYM_NOTHING:
|
|
case SYM_UNEXPLORED:
|
|
sym = DEF_NOTHING;
|
|
break;
|
|
case SYM_BOULDER:
|
|
sym = def_oc_syms[ROCK_CLASS].sym;
|
|
break;
|
|
case SYM_INVISIBLE:
|
|
sym = DEF_INVISIBLE;
|
|
break;
|
|
#if 0
|
|
/* these intentionally have no defaults */
|
|
case SYM_PET_OVERRIDE:
|
|
case SYM_HERO_OVERRIDE:
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
return sym;
|
|
}
|
|
|
|
/* initialize defaults for the primary symset */
|
|
void
|
|
init_primary_symbols(void)
|
|
{
|
|
register int i;
|
|
|
|
for (i = 0; i < MAXPCHARS; i++)
|
|
g.primary_syms[i + SYM_OFF_P] = defsyms[i].sym;
|
|
for (i = 0; i < MAXOCLASSES; i++)
|
|
g.primary_syms[i + SYM_OFF_O] = def_oc_syms[i].sym;
|
|
for (i = 0; i < MAXMCLASSES; i++)
|
|
g.primary_syms[i + SYM_OFF_M] = def_monsyms[i].sym;
|
|
for (i = 0; i < WARNCOUNT; i++)
|
|
g.primary_syms[i + SYM_OFF_W] = def_warnsyms[i].sym;
|
|
for (i = 0; i < MAXOTHER; i++)
|
|
g.primary_syms[i + SYM_OFF_X] = get_othersym(i, PRIMARY);
|
|
|
|
clear_symsetentry(PRIMARY, FALSE);
|
|
}
|
|
|
|
/* initialize defaults for the rogue symset */
|
|
void
|
|
init_rogue_symbols(void)
|
|
{
|
|
register int i;
|
|
|
|
/* These are defaults that can get overwritten
|
|
later by the roguesymbols option */
|
|
|
|
for (i = 0; i < MAXPCHARS; i++)
|
|
g.rogue_syms[i + SYM_OFF_P] = defsyms[i].sym;
|
|
g.rogue_syms[S_vodoor] = g.rogue_syms[S_hodoor] = g.rogue_syms[S_ndoor] = '+';
|
|
g.rogue_syms[S_upstair] = g.rogue_syms[S_dnstair] = '%';
|
|
|
|
for (i = 0; i < MAXOCLASSES; i++)
|
|
g.rogue_syms[i + SYM_OFF_O] = def_r_oc_syms[i];
|
|
for (i = 0; i < MAXMCLASSES; i++)
|
|
g.rogue_syms[i + SYM_OFF_M] = def_monsyms[i].sym;
|
|
for (i = 0; i < WARNCOUNT; i++)
|
|
g.rogue_syms[i + SYM_OFF_W] = def_warnsyms[i].sym;
|
|
for (i = 0; i < MAXOTHER; i++)
|
|
g.rogue_syms[i + SYM_OFF_X] = get_othersym(i, ROGUESET);
|
|
|
|
clear_symsetentry(ROGUESET, FALSE);
|
|
/* default on Rogue level is no color
|
|
* but some symbol sets can override that
|
|
*/
|
|
g.symset[ROGUESET].nocolor = 1;
|
|
}
|
|
|
|
void
|
|
assign_graphics(int whichset)
|
|
{
|
|
register int i;
|
|
|
|
switch (whichset) {
|
|
case ROGUESET:
|
|
/* Adjust graphics display characters on Rogue levels */
|
|
|
|
for (i = 0; i < SYM_MAX; i++)
|
|
g.showsyms[i] = g.ov_rogue_syms[i] ? g.ov_rogue_syms[i]
|
|
: g.rogue_syms[i];
|
|
|
|
#if defined(MSDOS) && defined(USE_TILES)
|
|
if (iflags.grmode)
|
|
tileview(FALSE);
|
|
#endif
|
|
g.currentgraphics = ROGUESET;
|
|
break;
|
|
|
|
case PRIMARY:
|
|
default:
|
|
for (i = 0; i < SYM_MAX; i++)
|
|
g.showsyms[i] = g.ov_primary_syms[i] ? g.ov_primary_syms[i]
|
|
: g.primary_syms[i];
|
|
|
|
#if defined(MSDOS) && defined(USE_TILES)
|
|
if (iflags.grmode)
|
|
tileview(TRUE);
|
|
#endif
|
|
g.currentgraphics = PRIMARY;
|
|
break;
|
|
}
|
|
reset_glyphmap(gm_symchange);
|
|
}
|
|
|
|
void
|
|
switch_symbols(int nondefault)
|
|
{
|
|
register int i;
|
|
|
|
if (nondefault) {
|
|
for (i = 0; i < SYM_MAX; i++)
|
|
g.showsyms[i] = g.ov_primary_syms[i] ? g.ov_primary_syms[i]
|
|
: g.primary_syms[i];
|
|
#ifdef PC9800
|
|
if (SYMHANDLING(H_IBM) && ibmgraphics_mode_callback)
|
|
(*ibmgraphics_mode_callback)();
|
|
else if (SYMHANDLING(H_UNK) && ascgraphics_mode_callback)
|
|
(*ascgraphics_mode_callback)();
|
|
#endif
|
|
#if defined(TERMLIB) || defined(CURSES_GRAPHICS)
|
|
/* curses doesn't assign any routine to dec..._callback but
|
|
probably does the expected initialization under the hood
|
|
for terminals capable of rendering DECgraphics */
|
|
if (SYMHANDLING(H_DEC) && decgraphics_mode_callback)
|
|
(*decgraphics_mode_callback)();
|
|
# ifdef CURSES_GRAPHICS
|
|
/* there aren't any symbol sets with CURS handling, and the
|
|
curses interface never assigns a routine to curses..._callback */
|
|
if (SYMHANDLING(H_CURS) && cursesgraphics_mode_callback)
|
|
(*cursesgraphics_mode_callback)();
|
|
# endif
|
|
#endif
|
|
} else {
|
|
init_primary_symbols();
|
|
init_showsyms();
|
|
}
|
|
}
|
|
|
|
void
|
|
update_ov_primary_symset(struct symparse* symp, int val)
|
|
{
|
|
g.ov_primary_syms[symp->idx] = val;
|
|
}
|
|
|
|
void
|
|
update_ov_rogue_symset(struct symparse* symp, int val)
|
|
{
|
|
g.ov_rogue_syms[symp->idx] = val;
|
|
}
|
|
|
|
void
|
|
update_primary_symset(struct symparse* symp, int val)
|
|
{
|
|
g.primary_syms[symp->idx] = val;
|
|
}
|
|
|
|
void
|
|
update_rogue_symset(struct symparse* symp, int val)
|
|
{
|
|
g.rogue_syms[symp->idx] = val;
|
|
}
|
|
|
|
void
|
|
clear_symsetentry(int which_set, boolean name_too)
|
|
{
|
|
if (g.symset[which_set].desc)
|
|
free((genericptr_t) g.symset[which_set].desc);
|
|
g.symset[which_set].desc = (char *) 0;
|
|
|
|
g.symset[which_set].handling = H_UNK;
|
|
g.symset[which_set].nocolor = 0;
|
|
/* initialize restriction bits */
|
|
g.symset[which_set].primary = 0;
|
|
g.symset[which_set].rogue = 0;
|
|
|
|
if (name_too) {
|
|
if (g.symset[which_set].name)
|
|
free((genericptr_t) g.symset[which_set].name);
|
|
g.symset[which_set].name = (char *) 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If you are adding code somewhere to be able to recognize
|
|
* particular types of symset "handling", define a
|
|
* H_XXX macro in include/sym.h and add the name
|
|
* to this array at the matching offset.
|
|
*/
|
|
const char *known_handling[] = {
|
|
"UNKNOWN", /* H_UNK */
|
|
"IBM", /* H_IBM */
|
|
"DEC", /* H_DEC */
|
|
"CURS", /* H_CURS */
|
|
"MAC", /* H_MAC -- pre-OSX MACgraphics */
|
|
(const char *) 0,
|
|
};
|
|
|
|
/*
|
|
* Accepted keywords for symset restrictions.
|
|
* These can be virtually anything that you want to
|
|
* be able to test in the code someplace.
|
|
* Be sure to:
|
|
* - add a corresponding Bitfield to the symsetentry struct in sym.h
|
|
* - initialize the field to zero in parse_sym_line in the SYM_CONTROL
|
|
* case 0 section of the idx switch. The location is prefaced with
|
|
* with a comment stating "initialize restriction bits".
|
|
* - set the value appropriately based on the index of your keyword
|
|
* under the case 5 sections of the same SYM_CONTROL idx switches.
|
|
* - add the field to clear_symsetentry()
|
|
*/
|
|
const char *known_restrictions[] = {
|
|
"primary", "rogue", (const char *) 0,
|
|
};
|
|
|
|
const struct symparse loadsyms[] = {
|
|
{ SYM_CONTROL, 0, "start" },
|
|
{ SYM_CONTROL, 0, "begin" },
|
|
{ SYM_CONTROL, 1, "finish" },
|
|
{ SYM_CONTROL, 2, "handling" },
|
|
{ SYM_CONTROL, 3, "description" },
|
|
{ SYM_CONTROL, 4, "color" },
|
|
{ SYM_CONTROL, 4, "colour" },
|
|
{ SYM_CONTROL, 5, "restrictions" },
|
|
#define PCHAR_PARSE
|
|
#include "defsym.h"
|
|
#undef PCHAR_PARSE
|
|
#define OBJCLASS_PARSE
|
|
#include "defsym.h"
|
|
#undef OBJCLASS_PARSE
|
|
#define MONSYMS_PARSE
|
|
#include "defsym.h"
|
|
#undef MONSYMS_PARSE
|
|
{ SYM_OTH, SYM_NOTHING + SYM_OFF_X, "S_nothing" },
|
|
{ SYM_OTH, SYM_UNEXPLORED + SYM_OFF_X, "S_unexplored" },
|
|
{ SYM_OTH, SYM_BOULDER + SYM_OFF_X, "S_boulder" },
|
|
{ SYM_OTH, SYM_INVISIBLE + SYM_OFF_X, "S_invisible" },
|
|
{ SYM_OTH, SYM_PET_OVERRIDE + SYM_OFF_X, "S_pet_override" },
|
|
{ SYM_OTH, SYM_HERO_OVERRIDE + SYM_OFF_X, "S_hero_override" },
|
|
{ 0, 0, (const char *) 0 } /* fence post */
|
|
};
|
|
|
|
/*symbols.c*/
|