Compare commits

..

1 Commits

Author SHA1 Message Date
kongju 04751c9b09 cyq
1 year ago

@ -1,4 +1 @@
whatever you do
wherever you gou
i am always here
waitting for you
111

Binary file not shown.

Binary file not shown.

@ -1,34 +0,0 @@
包图:
本部分代码的功能是介绍角色和其宠物的关系。其中角色包括姓名等级是否足够等级是否可以捕捉捕捉类型。宠物包括名字属性等级是否可以捕捉。另外还包括角色的职业,对于宠物还有环境的影响,包括地形周围资源是否可采集资源以及对角色的危险程度等等。

@ -17,7 +17,7 @@ NEARDATA const struct c_color_names c_color_names = {
"black", "amber", "golden", "light blue", "red", "green",
"silver", "blue", "purple", "white", "orange"
};
const char *c_obj_colors[] = {
const char *c_obj_colors[] = { //这里定义了一些物品的颜色
"black", /* CLR_BLACK */
"red", /* CLR_RED */
"green", /* CLR_GREEN */
@ -36,8 +36,8 @@ const char *c_obj_colors[] = {
"white", /* CLR_WHITE */
};
const struct c_common_strings c_common_strings =
{ "Nothing happens.",
const struct c_common_strings c_common_strings = //结构体变量中包含了一些常见的字符串,用于文本输出
{ "Nothing happens.", //在游戏中提供反馈、描述情况,进行交互
"That's enough tries!",
"That is a silly thing to %s.",
"shudder for a moment.",
@ -50,33 +50,34 @@ const struct c_common_strings c_common_strings =
{ "mon", "you" }
};
const struct savefile_info default_sfinfo = {
#ifdef NHSTDC
const struct savefile_info default_sfinfo = { //定义了保存文件的默认信息
#ifdef NHSTDC //用于保存文件格式的标志位
0x00000000UL
#else
0x00000000L
#endif
#if defined(COMPRESS) || defined(ZLIB_COMP)
#if defined(COMPRESS) || defined(ZLIB_COMP) //用于外部压缩标志位
| SFI1_EXTERNALCOMP
#endif
#if defined(ZEROCOMP)
| SFI1_ZEROCOMP
| SFI1_ZEROCOMP //零压缩标志位
#endif
#if defined(RLECOMP)
| SFI1_RLECOMP
| SFI1_RLECOMP //RLE压缩标志
#endif
,
#ifdef NHSTDC
0x00000000UL, 0x00000000UL
0x00000000UL, 0x00000000UL //保留字段
#else
0x00000000L, 0x00000000L
#endif
};
const char disclosure_options[] = "iavgco";
char emptystr[] = {0}; /* non-const */
const char disclosure_options[] = "iavgco"; //是一个字符数组,包含了几个选项。这些选项用于控制信息的披露程度。
char emptystr[] = {0}; /* non-const */ //是一个字符数组,用于表示空字符串。它是非常量数组,可以被修改。
NEARDATA struct flag flags; /* extern declaration is in flag.h, not decl.h */
//是一个结构体变量用于存储游戏中的标志位。该变量在flag.h中有外部声明。
/* Global windowing data, defined here for multi-window-system support */
#ifdef WIN32
@ -84,25 +85,28 @@ boolean fqn_prefix_locked[PREFIX_COUNT] = { FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE,
FALSE };
//是一个布尔数组用于表示文件名前缀是否被锁定。在这段代码中它被初始化为全为FALSE。
#endif
#ifdef PREFIXES_IN_USE
const char *fqn_prefix_names[PREFIX_COUNT] = {
"hackdir", "leveldir", "savedir", "bonesdir", "datadir",
"scoredir", "lockdir", "sysconfdir", "configdir", "troubledir"
};
};//是一个字符串指针数组,包含了一些文件名前缀的名称。这些名称用于指定不同类型文件的存储路径。
#endif
/* x/y/z deltas for the 10 movement directions (8 compass pts, 2 down/up) */
const schar xdir[N_DIRS_Z] = { -1, -1, 0, 1, 1, 1, 0, -1, 0, 0 };
const schar ydir[N_DIRS_Z] = { 0, -1, -1, -1, 0, 1, 1, 1, 0, 0 };
const schar zdir[N_DIRS_Z] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, -1 };
//是三个有符号字符数组分别表示十个移动方向包括八个主要方向和上下方向的x、y和z轴的增量。
/* redordered directions, cardinals first */
const schar dirs_ord[N_DIRS] =
{ DIR_W, DIR_N, DIR_E, DIR_S, DIR_NW, DIR_NE, DIR_SE, DIR_SW };
//是一个有符号字符数组,表示经过重新排序的移动方向。首先是四个基本方向,然后是四个对角线方向。
NEARDATA boolean has_strong_rngseed = FALSE;
NEARDATA boolean has_strong_rngseed = FALSE; //是一个布尔变量,用于表示是否具有强随机种子。
struct engr *head_engr;
NEARDATA struct instance_flags iflags;
NEARDATA struct instance_flags iflags; //是一个结构体变量,用于存储游戏实例的标志位。
/* NOTE: the order of these words exactly corresponds to the
order of oc_material values #define'd in objclass.h. */
const char *materialnm[] = { "mysterious", "liquid", "wax", "organic",
@ -111,29 +115,35 @@ const char *materialnm[] = { "mysterious", "liquid", "wax", "organic",
"metal", "copper", "silver", "gold",
"platinum", "mithril", "plastic", "glass",
"gemstone", "stone" };
const char quitchars[] = " \r\n\033";
NEARDATA struct savefile_info sfcap, sfrestinfo, sfsaveinfo;
const int shield_static[SHIELD_COUNT] = {
//是一个字符串指针数组包含了一些物品材质的名称。这些名称与objclass.h中定义的oc_material值的顺序完全对应。
const char quitchars[] = " \r\n\033";//是一个包含一些表示退出字符的字符串,包括空格、回车、换行和转义字符。
NEARDATA struct savefile_info sfcap, sfrestinfo, sfsaveinfo; //结构体变量,用于保存文件的信息。
const int shield_static[SHIELD_COUNT] = {//是一个整型数组,包含了一些盾牌的静态符号。
S_ss1, S_ss2, S_ss3, S_ss2, S_ss1, S_ss2, S_ss4, /* 7 per row */
S_ss1, S_ss2, S_ss3, S_ss2, S_ss1, S_ss2, S_ss4,
S_ss1, S_ss2, S_ss3, S_ss2, S_ss1, S_ss2, S_ss4,
};
NEARDATA struct you u;
NEARDATA time_t ubirthday;
NEARDATA struct u_realtime urealtime;
NEARDATA struct obj *uwep, *uarm, *uswapwep,
NEARDATA struct you u;//结构体变量,用于表示玩家角色的状态和属性。
NEARDATA time_t ubirthday; //是一个time_t类型的变量表示玩家角色的出生时间。
NEARDATA struct u_realtime urealtime; //用于表示游戏时间的实时信息。
NEARDATA struct obj *uwep, *uarm, *uswapwep, //结构体的指针变量,用于表示玩家角色的装备和物品。
*uquiver, /* quiver */
*uarmu, /* under-wear, so to speak */
*uskin, /* dragon armor, if a dragon */
*uarmc, *uarmh, *uarms, *uarmg,*uarmf, *uamul,
*uright, *uleft, *ublindf, *uchain, *uball;
const char vowels[] = "aeiouAEIOU";
NEARDATA winid WIN_MESSAGE, WIN_STATUS, WIN_MAP, WIN_INVEN;
const char ynchars[] = "yn";
const char vowels[] = "aeiouAEIOU"; //是一个包含元音字母的字符串,包括小写和大写的元音字母。
NEARDATA winid WIN_MESSAGE, WIN_STATUS, WIN_MAP, WIN_INVEN;//是窗口标识符winid类型变量用于表示游戏中的不同窗口。
const char ynchars[] = "yn"; //是包含一些表示"yes"和"no"的字符的字符串。
const char ynqchars[] = "ynq";
const char ynaqchars[] = "ynaq";
const char ynNaqchars[] = "yn#aq";
NEARDATA long yn_number = 0L;
//这些变量的定义用于实现游戏的逻辑和界面显示等功能。
//其中包括随机数种子、文本输出、文件操作、游戏状态、时间管理、玩家角色属性、装备和物品等。
#ifdef PANICTRACE
const char *ARGV0;

@ -19,7 +19,7 @@ enum arrival {
};
void
newedog(struct monst *mtmp) /*Create a new dog*/
newedog(struct monst *mtmp)
{
if (!mtmp->mextra)
mtmp->mextra = newmextra();
@ -30,26 +30,26 @@ newedog(struct monst *mtmp) /*Create a new dog*/
}
void
free_edog(struct monst *mtmp) /*This code is about releasing a struct resource called "edog"*/
free_edog(struct monst *mtmp)
{
if (mtmp->mextra && EDOG(mtmp)) { /*This line of code first checks if the mextra member of mtmp is non-empty, and calls the EDOG(mtmp) macro to get the edog struct associated with mtmp. If both conditions are met, the code in curly braces is executed.*/
free((genericptr_t) EDOG(mtmp)); /*This line of code uses the free function to free up the memory space occupied by the EDOG struct obtained through the EDOG(mtmp) macro. (genericptr_t) EDOG(mtmp) converts Pointers to the edog structure to a generic pointer type to ensure proper memory release.*/
EDOG(mtmp) = (struct edog *) 0; /*This line sets the pointer to the EDOG struct fetched by the EDOG(mtmp) macro to NULL to indicate that the struct has been released.*/
if (mtmp->mextra && EDOG(mtmp)) {
free((genericptr_t) EDOG(mtmp));
EDOG(mtmp) = (struct edog *) 0;
}
mtmp->mtame = 0;
}
void
initedog(struct monst *mtmp) /*Initialize the dog*/
initedog(struct monst *mtmp)
{
mtmp->mtame = is_domestic(mtmp->data) ? 10 : 5; /*This line of code determines whether the dog is a domestic dog, and sets its taming to 10 if it is, or 5 if it is not. is_domestic might be a function that checks whether mtmp->data represents a domestic dog.*/
mtmp->mtame = is_domestic(mtmp->data) ? 10 : 5;
mtmp->mpeaceful = 1;
mtmp->mavenge = 0;
set_malign(mtmp); /* recalc alignment now that it's tamed */
mtmp->mleashed = 0;
mtmp->meating = 0;
EDOG(mtmp)->droptime = 0;
EDOG(mtmp)->dropdist = 10000; /*These two lines of code set the dog's item drop time and distance.*/
EDOG(mtmp)->dropdist = 10000;
EDOG(mtmp)->apport = ACURR(A_CHA);
EDOG(mtmp)->whistletime = 0;
EDOG(mtmp)->hungrytime = 1000 + gm.moves;
@ -61,18 +61,18 @@ initedog(struct monst *mtmp) /*Initialize the dog*/
EDOG(mtmp)->killed_by_u = 0;
u.uconduct.pets++;
}
/*In general, this code initializes a dog's status, including its tame, flatness, marital status, evil, whether it is tied, whether it is eating, the related Settings for item drop, charisma, hunger time, target location, whether it has been abused, whether it has been resurrected, maximum health penalty, and whether it has been killed by the player. At the same time, this code also reflects that in the game, the player can have pets, and the number of pets has been increased during the initialization process.*/
static int
pet_type(void)
{
if (gu.urole.petnum != NON_PM) /*The number of pets of a user character (possibly a player character in the game) is checked here*/
if (gu.urole.petnum != NON_PM)
return gu.urole.petnum;
else if (gp.preferred_pet == 'c')
return PM_KITTEN;
else if (gp.preferred_pet == 'd')
return PM_LITTLE_DOG;
else
return rn2(2) ? PM_KITTEN : PM_LITTLE_DOG; /*A ternary operator is used here. It first calls the function rn2(2) (probably a random number generating function, but the argument 2 May represent some kind of distribution or range) and then decides which pet class to return based on the result of this random number*/
return rn2(2) ? PM_KITTEN : PM_LITTLE_DOG;
}
struct monst *
@ -178,7 +178,7 @@ make_familiar(struct obj *otmp, coordxy x, coordxy y, boolean quietly)
struct monst *
makedog(void)
{ /*When the pet type is 'n', the function returns an empty struct pointer; When the pet type is PM_LITTLE_DOG, set the pet name to gd.dogname. When the pet type is PM_PONY, set the pet name to gh.horsename; Otherwise, set pet name to gc.catname.*/
{
register struct monst *mtmp;
register struct obj *otmp;
const char *petname;
@ -434,19 +434,7 @@ mon_arrive(struct monst *mtmp, int when)
wander = (xint16) min(nmv, 8L);
} else
wander = 0;
/*If the value of xyloc is MIGR_APPROX_XY, the code doesn't do anything, because xlocale and ylocale are already set above.
If xyloc has a value of MIGR_EXACT_XY, set wander's value to 0.
If the value of xyloc is MIGR_WITH_HERO, assign the values U.U.X and U.U.Y to xlocale and ylocale, respectively.
If the value of xyloc is MIGR_STAIRS_UP or MIGR_STAIRS_DOWN, look for stairs starting from the given floor, and if found, assign the x and y coordinates of the stairs to xlocale and ylocale, respectively.
If the value of xyloc is MIGR_LADDER_UP or MIGR_LADDER_DOWN, look for the stairs starting from the given floor, and if found, assign the x and y coordinates of the stairs to xlocale and ylocale, respectively.
If the value of xyloc is MIGR_SSTAIRS, find the stairs for the given floor, and if found, assign the x and y coordinates of the stairs to xlocale and ylocale, respectively.
If the value of xyloc is MIGR_PORTAL, check whether you are in the final game level. If it is, it randomly generates an internal coordinate in the target region and assigns it to xlocale and ylocale.*/
switch (xyloc) {
case MIGR_APPROX_XY: /* {x,y}locale set above */
break;
@ -1258,18 +1246,18 @@ wary_dog(struct monst *mtmp, boolean was_dead)
void
abuse_dog(struct monst *mtmp)
{
if (!mtmp->mtame) /*If the monster is not tamed (mtame is 0), the function returns directly.*/
if (!mtmp->mtame)
return;
if (Aggravate_monster || Conflict) /*If Aggravate_monster or Conflict variables in the game are true, then the monster's tame level (mtame) will be halved. Otherwise, the monster's taming level will be reduced by 1.*/
if (Aggravate_monster || Conflict)
mtmp->mtame /= 2;
else
mtmp->mtame--;
if (mtmp->mtame && !mtmp->isminion) /*If the monster is not a pawn (isminion is 0) and the monster's taming level is greater than 0, the monster's abuse count is increased by 1*/
if (mtmp->mtame && !mtmp->isminion)
EDOG(mtmp)->abuse++;
if (!mtmp->mtame && mtmp->mleashed) /*If the monster has been tamed (mtame greater than or equal to 0) and is tethered (mleashed is true), the monster will be untethered.*/
if (!mtmp->mtame && mtmp->mleashed)
m_unleash(mtmp, TRUE);
/* don't make a sound if pet is in the middle of leaving the level */

@ -4,7 +4,7 @@
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
/*Define the required structure*/
static int eatmdone(void);
static int eatfood(void);
static struct obj *costly_tin(int);
@ -392,7 +392,7 @@ food_disappears(struct obj *obj)
resume eating/opening would restart from scratch */
void
food_substitution(struct obj *old_obj, struct obj *new_obj)
{ /*A declaration of a function, which defines a function named food_substitution and takes two arguments: old_obj and new_obj. Both of these parameters are Pointers to the obj structure.*/
{
if (old_obj == gc.context.victual.piece) {
gc.context.victual.piece = new_obj;
gc.context.victual.o_id = new_obj->o_id;
@ -406,7 +406,7 @@ food_substitution(struct obj *old_obj, struct obj *new_obj)
static void
do_reset_eat(void)
{
debugpline0("do_reset_eat..."); /*代码检查gc.context.victual.piece是否为真。gc.context.victual.piece可能代表当前正在被吃的食物或者对象。*/
debugpline0("do_reset_eat...");
if (gc.context.victual.piece) {
gc.context.victual.o_id = 0;
gc.context.victual.piece = touchfood(gc.context.victual.piece);
@ -513,24 +513,24 @@ eatfood(void)
static void
done_eating(boolean message)
{// 从gc结构体中获取到正在被吃的食物或对象并将其地址赋给piece指针
{
struct obj *piece = gc.context.victual.piece;
// 将该食物或对象标记为正在使用,表示已经被角色选中
piece->in_use = TRUE;
go.occupation = 0; /* do this early, so newuhs() knows we're done */
newuhs(FALSE);// 调用newuhs函数将FALSE作为参数传入可能表示角色已经完成了一个周期的活动或状态
if (gn.nomovemsg) {// 检查gn结构体中的nomovemsg字段如果存在并且message为真则打印一条消息
newuhs(FALSE);
if (gn.nomovemsg) {
if (message)
pline1(gn.nomovemsg);
gn.nomovemsg = 0;
} else if (message) {
You("finish %s %s.", // 如果nomovemsg字段不存在并且message为真则打印一条消息表示角色已经完成了一个动作这里可能表示角色已经吃完了一个食物或者对象
You("finish %s %s.",
(gy.youmonst.data == &mons[PM_FIRE_ELEMENTAL]) ? "consuming"
: "eating",
food_xname(piece, TRUE));
}
if (piece->otyp == CORPSE || piece->globby)// 如果食物或对象是一个尸体或者是一个普通的对象调用cpostfx函数处理它的后效否则调用fpostfx函数处理它的后效
if (piece->otyp == CORPSE || piece->globby)
cpostfx(piece->corpsenm);
else
fpostfx(piece);
@ -539,14 +539,14 @@ done_eating(boolean message)
useup(piece);
else
useupf(piece, 1L);
//将gc结构体中的victual字段重置为零表示角色已经完成了一个进食周期并将食物或对象的指针设置为0以及将其o_id字段也设置为0
gc.context.victual = zero_victual; /* victual.piece = 0, .o_id = 0 */
}
void
eating_conducts(struct permonst *pd)
{
int ll_conduct = 0;// 定义一个整型变量ll_conduct并将其初始化为0。这个变量可能用来计数某种行为或条件被满足的次数
int ll_conduct = 0;
if (!u.uconduct.food++) {
livelog_printf(LL_CONDUCT, "ate for the first time - %s",
@ -554,20 +554,18 @@ eating_conducts(struct permonst *pd)
ll_conduct++;
}
if (!vegan(pd)) {
if (!u.uconduct.unvegan++
&& !ll_conduct) { // 检查u.uconduct.food的值。如果它为真那么执行下面的代码。否则跳过。在这个情况下由于food的值被递增了所以它始终为真这可能是代码的一个错误。
livelog_printf(
LL_CONDUCT, // 打印一条消息到日志,说明这个生物第一次进食。消息的内容是这个生物的中性名称
if (!u.uconduct.unvegan++ && !ll_conduct) {
livelog_printf(LL_CONDUCT,
"consumed animal products (%s) for the first time",
pd->pmnames[NEUTRAL]);
ll_conduct++; // 由于food的值已经被递增所以ll_conduct的值增加1
ll_conduct++;
}
}
if (!vegetarian(pd)) {// 检查pd是否是素食的。如果不是执行下面的代码。否则跳过。
if (!u.uconduct.unvegetarian && !ll_conduct)// 如果这个生物第一次消费非素食且之前没有违反任何条件ll_conduct为0那么执行下面的代码。
livelog_printf(LL_CONDUCT, "tasted meat (%s) for the first time",// 打印一条消息到日志,说明这个生物第一次消费动物产品。消息的内容是这个生物的中性名称。
if (!vegetarian(pd)) {
if (!u.uconduct.unvegetarian && !ll_conduct)
livelog_printf(LL_CONDUCT, "tasted meat (%s) for the first time",
pd->pmnames[NEUTRAL]);
violated_vegetarian();// 调用violated_vegetarian函数可能是处理违反素食规定的情况。
violated_vegetarian();
}
}
@ -577,7 +575,6 @@ eat_brains(
struct monst *magr,
struct monst *mdef,
boolean visflag,
int *dmg_p) /* for dishing out extra damage in lieu of Int loss */
{
struct permonst *pd = mdef->data;
@ -758,25 +755,18 @@ maybe_cannibal(int pm, boolean allowmsg)
static void
cprefx(register int pm)
{
(void) maybe_cannibal(
pm,
TRUE); // 调用maybe_cannibal函数将pm和TRUE作为参数传入。maybe_cannibal函数可能处理关于食人的特定情况
if (flesh_petrifies(&mons[pm])) {// 调用flesh_petrifies函数将mons[pm]的地址作为参数传入。如果该函数返回真,则执行下面的代码块
if (!Stone_resistance// 检查角色是否对石头有抵抗力
&& !(
poly_when_stoned(
gy.youmonst
.data) // 检查角色是否在变成石头时具有多态性(可以变成其他的怪物)
(void) maybe_cannibal(pm, TRUE);
if (flesh_petrifies(&mons[pm])) {
if (!Stone_resistance
&& !(poly_when_stoned(gy.youmonst.data)
&& polymon(PM_STONE_GOLEM))) {
Sprintf(gk.killer.name, "tasting %s meat",// 格式化字符串将怪物mons[pm]的中性名称添加到字符串中并存储在gk.killer.name中。这可能表示杀手的名称或者某种杀人行为的描述
Sprintf(gk.killer.name, "tasting %s meat",
mons[pm].pmnames[NEUTRAL]);
gk.killer.format =
KILLED_BY; // 设置gk.killer.format为KILLED_BY。这可能是一个标志表示某种死亡方式例如被xx杀死
gk.killer.format = KILLED_BY;
You("turn to stone.");
done(STONING);// 调用done函数将STONING作为参数传入。这可能表示完成了变成石头的动画或者状态
if (gc.context.victual.piece)// 检查gc.context.victual.piece是否为真。如果为真执行下面的代码块
gc.context.victual.eating =
0; // 将gc.context.victual.eating设置为0。可能表示停止进食的行为或者重置某种状态
done(STONING);
if (gc.context.victual.piece)
gc.context.victual.eating = 0;
return; /* lifesaved */
}
}
@ -970,7 +960,7 @@ temp_givit(int type, struct permonst *ptr)
* and what type of intrinsic it is trying to give you.
*/
static void
givit(int type, register struct permonst *ptr)//Analysis for different situations
givit(int type, register struct permonst *ptr)
{
debugpline1("Attempting to give intrinsic %d", type);
@ -1394,11 +1384,9 @@ tin_details(struct obj *obj, int mnum, char *buf)
Strcat(buf, " of spinach");
else if (mnum == NON_PM)
Strcpy(buf, "empty tin");
else {//// 如果 obj->cknown 为真或者 iflags.override_ID 为真,并且 obj->spe < 0那么执行以下代码块。
// 这可能意味着这是一个已知的、被重定向的、并且其特殊属性小于0的物体。
else {
if ((obj->cknown || iflags.override_ID) && obj->spe < 0) {
if (r == ROTTEN_TIN || r == HOMEMADE_TIN) {//// 如果 r 的值为 ROTTEN_TIN 或者 HOMEMADE_TIN那么将字符串 " of " 和 tintxts[r].txt 追加到 buf2 中,然后将 buf2 复制到 buf 中。
if (r == ROTTEN_TIN || r == HOMEMADE_TIN) {
if (r == ROTTEN_TIN || r == HOMEMADE_TIN) {
/* put these before the word tin */
Sprintf(buf2, "%s %s of ", tintxts[r].txt, buf);
Strcpy(buf, buf2);
@ -1408,12 +1396,7 @@ tin_details(struct obj *obj, int mnum, char *buf)
} else {
Strcpy(eos(buf), " of ");
}
if (vegetarian(
&mons[mnum])) // 检查 mons[mnum]
// 是否为素食。如果是素食,那么将
// mons[mnum].pmnames[NEUTRAL] 追加到 buf
// 的末尾。否则,将字符串 "meat" 和
// mons[mnum].pmnames[NEUTRAL] 追加到 buf 的末尾
if (vegetarian(&mons[mnum]))
Sprintf(eos(buf), "%s", mons[mnum].pmnames[NEUTRAL]);
else
Sprintf(eos(buf), "%s meat", mons[mnum].pmnames[NEUTRAL]);

Loading…
Cancel
Save