1
0
Fork 0
mirror of https://codeberg.org/noisytoot/notnotdnethack.git synced 2025-05-05 14:55:10 +01:00

Fix altar display in mapseen

Previously, #overview would show the altar's god as being to your god
if it's of your alignment (regardless of the altar's actual god), and
doesn't show anything about the altar's god/alignment otherwise.  This
commit makes it always show the altar's correct god if all altars on
the level are to the same god.

mapseen-related stuff is moved from dungeon.h to mapseen.h, to avoid a
circular makedefs -> dungeon.h -> gnames.h -> makedefs dependency.
gnames.h needs to be included for MAX_GOD.
This commit is contained in:
Ron Nazarov 2025-01-14 23:24:01 +00:00
parent f71eded468
commit 36727f4dac
Signed by: noisytoot
GPG key ID: 1D43EF4F4492268B
4 changed files with 150 additions and 89 deletions

View file

@ -317,85 +317,4 @@ struct linfo {
};
/* types and structures for dungeon map recording
*
* It is designed to eliminate the need for an external notes file for some of
* the more mundane dungeon elements. "Where was the last altar I passed?" etc...
* Presumably the character can remember this sort of thing even if, months
* later in real time picking up an old save game, I can't.
*
* To be consistent, one can assume that this map is in the player's mind and
* has no physical correspondence (eliminating illiteracy/blind/hands/hands free
* concerns.) Therefore, this map is not exaustive nor detailed ("some fountains").
* This makes it also subject to player conditions (amnesia).
*/
/* Because clearly Nethack needs more ways to specify alignment */
#define Align2msa(x) ((x) == A_LAWFUL ? MSA_LAWFUL : \
(x) == A_NEUTRAL ? MSA_NEUTRAL : \
(x) == A_CHAOTIC ? MSA_CHAOTIC : \
(x) == A_NONE ? MSA_UNALI : \
(x) == A_VOID ? MSA_VOID : \
MSA_MULTI)
#define Msa2align(x) ((x) == MSA_LAWFUL ? A_LAWFUL : \
(x) == MSA_NEUTRAL ? A_NEUTRAL : \
(x) == MSA_CHAOTIC ? A_CHAOTIC : \
(x) == MSA_UNALI ? A_NONE : \
(x) == MSA_VOID ? A_VOID : \
A_NONE) /* A_NONE is technically bad and overlaps with MSA_UNALI */
#define MSA_MULTI 0 /* multiple alignments */
#define MSA_LAWFUL 1
#define MSA_NEUTRAL 2
#define MSA_CHAOTIC 3
#define MSA_UNALI 4
#define MSA_VOID 5
typedef struct mapseen_feat {
/* feature knowledge that must be calculated from levl array */
Bitfield(nfount, 2);
Bitfield(nforge, 2);
Bitfield(nsink, 2);
Bitfield(naltar, 2);
Bitfield(msalign, 3); /* corresponds to MSA_* above */
Bitfield(ngrave, 2);
Bitfield(nthrone, 2);
Bitfield(ntree, 2);
/* water, lava, ice are too verbose so commented out for now */
/*
Bitfield(water, 1);
Bitfield(lava, 1);
Bitfield(ice, 1);
*/
/* calculated from rooms array */
Bitfield(nshop, 2);
Bitfield(nmorgue, 2);
Bitfield(ntemple, 2);
Bitfield(shoptype, 5);
Bitfield(forgot, 1); /* player has forgotten about this level? */
} mapseen_feat;
/* for mapseen->rooms */
#define MSR_SEEN 1
/* what the player knows about a single dungeon level */
/* initialized in mklev() */
typedef struct mapseen {
struct mapseen *next; /* next map in the chain */
branch *br; /* knows about branch via taking it in goto_level */
d_level lev; /* corresponding dungeon level */
mapseen_feat feat;
/* custom naming */
char *custom;
unsigned custom_lth;
/* maybe this should just be in struct mkroom? */
schar rooms[(MAXNROFROOMS+1)*2];
} mapseen;
#endif /* DUNGEON_H */

75
include/mapseen.h Normal file
View file

@ -0,0 +1,75 @@
/* SPDX-License-Identifier: NGPL */
#ifndef MAPSEEN_H
#define MAPSEEN_H
#include "gnames.h"
/*
* This has to be in its own header to avoid a circular makedefs ->
* dungeon.h -> gnames.h -> makedefs dependency. gnames.h needs to be
* included for MAX_GOD.
*/
/* types and structures for dungeon map recording
*
* It is designed to eliminate the need for an external notes file for some of
* the more mundane dungeon elements. "Where was the last altar I passed?" etc...
* Presumably the character can remember this sort of thing even if, months
* later in real time picking up an old save game, I can't.
*
* To be consistent, one can assume that this map is in the player's mind and
* has no physical correspondence (eliminating illiteracy/blind/hands/hands free
* concerns.) Therefore, this map is not exaustive nor detailed ("some fountains").
* This makes it also subject to player conditions (amnesia).
*/
typedef struct mapseen_feat {
/* feature knowledge that must be calculated from levl array */
Bitfield(nfount, 2);
Bitfield(nforge, 2);
Bitfield(nsink, 2);
Bitfield(naltar, 2);
Bitfield(ngrave, 2);
Bitfield(nthrone, 2);
Bitfield(ntree, 2);
/* water, lava, ice are too verbose so commented out for now */
/*
Bitfield(water, 1);
Bitfield(lava, 1);
Bitfield(ice, 1);
*/
/* calculated from rooms array */
Bitfield(nshop, 2);
Bitfield(nmorgue, 2);
Bitfield(ntemple, 2);
Bitfield(shoptype, 5);
Bitfield(forgot, 1); /* player has forgotten about this level? */
#define MSGODS_ARRAY_SIZE (MAX_GOD/8+1)
unsigned int msgods[MSGODS_ARRAY_SIZE];
} mapseen_feat;
/* for mapseen->rooms */
#define MSR_SEEN 1
/* what the player knows about a single dungeon level */
/* initialized in mklev() */
typedef struct mapseen {
struct mapseen *next; /* next map in the chain */
branch *br; /* knows about branch via taking it in goto_level */
d_level lev; /* corresponding dungeon level */
mapseen_feat feat;
/* custom naming */
char *custom;
unsigned custom_lth;
/* maybe this should just be in struct mkroom? */
schar rooms[(MAXNROFROOMS+1)*2];
} mapseen;
#endif /* MAPSEEN_H */

View file

@ -101,4 +101,41 @@ void foo VA_DECL(int, arg) --macro expansion has a hidden opening brace
# endif /* __GNUC__ */
#endif /* __has_include(<stdckdint.h>) */
/*
* If we don't have C23 <stdbit.h>, fall back to GCC
* __builtin_popcount and C11 _Generic. If we don't have that either,
* fall back to Brian Kernighan's algorithm and C11 _Generic.
*/
#if __has_include(<stdbit.h>)
# include <stdbit.h>
#else
# ifdef __GNUC__
# define stdc_count_ones_uc(n) (unsigned char)__builtin_popcount((unsigned char)(n))
# define stdc_count_ones_us(n) (unsigned short)__builtin_popcount((unsigned short)(n))
# define stdc_count_ones_ui(n) __builtin_popcount((n))
# define stdc_count_ones_ul(n) __builtin_popcountl((n))
# define stdc_count_ones_ull(n) __builtin_popcountll((n))
# else
# define DEFINE_STDC_COUNT_ONES(suffix, type) \
static inline type stdc_count_ones_##suffix(type n) { \
int count = 0; \
while (n) { n &= n-1; count++; } \
return count; \
}
DEFINE_STDC_COUNT_ONES(uc, unsigned char)
DEFINE_STDC_COUNT_ONES(us, unsigned short)
DEFINE_STDC_COUNT_ONES(ui, unsigned int)
DEFINE_STDC_COUNT_ONES(ul, unsigned long)
DEFINE_STDC_COUNT_ONES(ull, unsigned long long)
# undef DEFINE_STDC_COUNT_ONES
# endif /* __GNUC__ */
#define stdc_count_ones(n) \
_Generic((n), \
unsigned char: stdc_count_ones_uc((n)), \
unsigned short: stdc_count_ones_us((n)), \
unsigned int: stdc_count_ones_ui((n)), \
unsigned long: stdc_count_ones_ul((n)), \
unsigned long long: stdc_count_ones_ull((n)))
#endif /* __has_include(<stdbit.h>) */
#endif /* TRADSTDC_H */

View file

@ -8,6 +8,7 @@
#include "dgn_file.h"
#include "dlb.h"
#include "display.h"
#include "mapseen.h"
//define DUNGEON_FILE "dungeon"
@ -2258,6 +2259,34 @@ donamelevel(void)
return MOVE_CANCELLED;
}
boolean
check_msgod(mapseen *mptr, int godnum)
{
if(godnum >= MAX_GOD || godnum < 1){
impossible("Attempting to check god number %d in mapseen?", godnum);
return FALSE;
}
return !!(mptr->feat.msgods[(godnum-1)/32] & (0x1L << ((godnum-1)%32)));
}
void
add_msgod(mapseen *mptr, int godnum)
{
if(godnum >= MAX_GOD || godnum < 1){
impossible("Attempting to set god number %d in mapseen?", godnum);
}
mptr->feat.msgods[(godnum-1)/32] |= (0x1L << ((godnum-1)%32));
}
int
count_msgods(mapseen *mptr)
{
int count = 0;
for (int i = 0; i < MSGODS_ARRAY_SIZE; i++)
count += stdc_count_ones(mptr->feat.msgods[i]);
return count;
}
/* find the particular mapseen object in the chain */
/* may return 0 */
static mapseen *
@ -2574,11 +2603,7 @@ recalc_mapseen(void)
mptr->feat.nsink = min(mptr->feat.nsink + 1, 3);
break;
case ALTAR:
if (!mptr->feat.naltar)
mptr->feat.msalign = Align2msa(a_align(x,y));
else if (mptr->feat.msalign != Align2msa(a_align(x,y)))
mptr->feat.msalign = MSA_MULTI;
add_msgod(mptr, god_at_altar(x,y));
mptr->feat.naltar = min(mptr->feat.naltar + 1, 3);
break;
}
@ -2874,9 +2899,14 @@ print_mapseen(winid win, mapseen *mptr, boolean printdun)
ADDNTOBUF("altar", mptr->feat.naltar)
else
ADDNTOBUF("temple", mptr->feat.ntemple)
/* and print out altar's god if they are all to your god */
if ((mptr->feat.ntemple || mptr->feat.naltar) && (Msa2align(mptr->feat.msalign) == u.ualign.type))
Sprintf(eos(buf), " to %s", align_gname(u.ualign.type));
/* and print out altar's god if they are all to one god */
if ((mptr->feat.ntemple || mptr->feat.naltar) && count_msgods(mptr) == 1) {
int godnum;
for (godnum = 1; godnum < MAX_GOD; godnum++)
if (check_msgod(mptr, godnum))
break;
Sprintf(eos(buf), " to %s", godname(godnum));
}
ADDNTOBUF("fountain", mptr->feat.nfount)
ADDNTOBUF("forge", mptr->feat.nforge)