From 6824d6dec220ecd25aa668003d422ae5e3989b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=86=A0=E5=AE=87?= <1129477164@qq.com> Date: Sun, 3 Dec 2023 22:52:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0dog=E5=92=8Ceat=E7=9A=84?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/NetHack_3.7/src/dog.c | 44 ++++++++++++++-------- src/NetHack_3.7/src/eat.c | 79 ++++++++++++++++++++++++--------------- 2 files changed, 76 insertions(+), 47 deletions(-) diff --git a/src/NetHack_3.7/src/dog.c b/src/NetHack_3.7/src/dog.c index 934d88a..a21b61d 100644 --- a/src/NetHack_3.7/src/dog.c +++ b/src/NetHack_3.7/src/dog.c @@ -19,7 +19,7 @@ enum arrival { }; void -newedog(struct monst *mtmp) +newedog(struct monst *mtmp) /*Create a new dog*/ { if (!mtmp->mextra) mtmp->mextra = newmextra(); @@ -30,26 +30,26 @@ newedog(struct monst *mtmp) } void -free_edog(struct monst *mtmp) +free_edog(struct monst *mtmp) /*This code is about releasing a struct resource called "edog"*/ { - if (mtmp->mextra && EDOG(mtmp)) { - free((genericptr_t) EDOG(mtmp)); - EDOG(mtmp) = (struct edog *) 0; + 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.*/ } mtmp->mtame = 0; } void -initedog(struct monst *mtmp) +initedog(struct monst *mtmp) /*Initialize the dog*/ { - mtmp->mtame = is_domestic(mtmp->data) ? 10 : 5; + 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->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; + EDOG(mtmp)->dropdist = 10000; /*These two lines of code set the dog's item drop time and distance.*/ EDOG(mtmp)->apport = ACURR(A_CHA); EDOG(mtmp)->whistletime = 0; EDOG(mtmp)->hungrytime = 1000 + gm.moves; @@ -61,18 +61,18 @@ initedog(struct monst *mtmp) 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) + if (gu.urole.petnum != NON_PM) /*The number of pets of a user character (possibly a player character in the game) is checked here*/ 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; + 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*/ } 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,7 +434,19 @@ 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; @@ -1246,18 +1258,18 @@ wary_dog(struct monst *mtmp, boolean was_dead) void abuse_dog(struct monst *mtmp) { - if (!mtmp->mtame) + if (!mtmp->mtame) /*If the monster is not tamed (mtame is 0), the function returns directly.*/ return; - if (Aggravate_monster || Conflict) + 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.*/ mtmp->mtame /= 2; else mtmp->mtame--; - if (mtmp->mtame && !mtmp->isminion) + 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*/ EDOG(mtmp)->abuse++; - if (!mtmp->mtame && mtmp->mleashed) + 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.*/ m_unleash(mtmp, TRUE); /* don't make a sound if pet is in the middle of leaving the level */ diff --git a/src/NetHack_3.7/src/eat.c b/src/NetHack_3.7/src/eat.c index 11ec198..e850046 100644 --- a/src/NetHack_3.7/src/eat.c +++ b/src/NetHack_3.7/src/eat.c @@ -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..."); + debugpline0("do_reset_eat..."); /*代码检查gc.context.victual.piece是否为真。gc.context.victual.piece可能代表当前正在被吃的食物或者对象。*/ 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); - if (gn.nomovemsg) { + newuhs(FALSE);// 调用newuhs函数,将FALSE作为参数传入,可能表示角色已经完成了一个周期的活动或状态 + if (gn.nomovemsg) {// 检查gn结构体中的nomovemsg字段,如果存在,并且message为真,则打印一条消息 if (message) pline1(gn.nomovemsg); gn.nomovemsg = 0; } else if (message) { - You("finish %s %s.", + You("finish %s %s.", // 如果nomovemsg字段不存在,并且message为真,则打印一条消息,表示角色已经完成了一个动作,这里可能表示角色已经吃完了一个食物或者对象 (gy.youmonst.data == &mons[PM_FIRE_ELEMENTAL]) ? "consuming" : "eating", food_xname(piece, TRUE)); } - if (piece->otyp == CORPSE || piece->globby) + if (piece->otyp == CORPSE || piece->globby)// 如果食物或对象是一个尸体或者是一个普通的对象,调用cpostfx函数处理它的后效;否则,调用fpostfx函数处理它的后效 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; + int ll_conduct = 0;// 定义一个整型变量ll_conduct并将其初始化为0。这个变量可能用来计数某种行为或条件被满足的次数 if (!u.uconduct.food++) { livelog_printf(LL_CONDUCT, "ate for the first time - %s", @@ -554,18 +554,20 @@ eating_conducts(struct permonst *pd) ll_conduct++; } if (!vegan(pd)) { - if (!u.uconduct.unvegan++ && !ll_conduct) { - livelog_printf(LL_CONDUCT, + if (!u.uconduct.unvegan++ + && !ll_conduct) { // 检查u.uconduct.food的值。如果它为真,那么执行下面的代码。否则,跳过。在这个情况下,由于food的值被递增了,所以它始终为真,这可能是代码的一个错误。 + livelog_printf( + LL_CONDUCT, // 打印一条消息到日志,说明这个生物第一次进食。消息的内容是这个生物的中性名称 "consumed animal products (%s) for the first time", pd->pmnames[NEUTRAL]); - ll_conduct++; + ll_conduct++; // 由于food的值已经被递增,所以ll_conduct的值增加1 } } - if (!vegetarian(pd)) { - if (!u.uconduct.unvegetarian && !ll_conduct) - livelog_printf(LL_CONDUCT, "tasted meat (%s) for the first time", + if (!vegetarian(pd)) {// 检查pd是否是素食的。如果不是,执行下面的代码。否则,跳过。 + if (!u.uconduct.unvegetarian && !ll_conduct)// 如果这个生物第一次消费非素食且之前没有违反任何条件(ll_conduct为0),那么执行下面的代码。 + livelog_printf(LL_CONDUCT, "tasted meat (%s) for the first time",// 打印一条消息到日志,说明这个生物第一次消费动物产品。消息的内容是这个生物的中性名称。 pd->pmnames[NEUTRAL]); - violated_vegetarian(); + violated_vegetarian();// 调用violated_vegetarian函数,可能是处理违反素食规定的情况。 } } @@ -575,6 +577,7 @@ 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; @@ -755,18 +758,25 @@ maybe_cannibal(int pm, boolean allowmsg) static void cprefx(register int pm) { - (void) maybe_cannibal(pm, TRUE); - if (flesh_petrifies(&mons[pm])) { - if (!Stone_resistance - && !(poly_when_stoned(gy.youmonst.data) + (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) // 检查角色是否在变成石头时具有多态性(可以变成其他的怪物) && polymon(PM_STONE_GOLEM))) { - Sprintf(gk.killer.name, "tasting %s meat", + Sprintf(gk.killer.name, "tasting %s meat",// 格式化字符串,将怪物mons[pm]的中性名称添加到字符串中,并存储在gk.killer.name中。这可能表示杀手的名称或者某种杀人行为的描述 mons[pm].pmnames[NEUTRAL]); - gk.killer.format = KILLED_BY; + gk.killer.format = + KILLED_BY; // 设置gk.killer.format为KILLED_BY。这可能是一个标志,表示某种死亡方式,例如被xx杀死 You("turn to stone."); - done(STONING); - if (gc.context.victual.piece) - gc.context.victual.eating = 0; + done(STONING);// 调用done函数,将STONING作为参数传入。这可能表示完成了变成石头的动画或者状态 + if (gc.context.victual.piece)// 检查gc.context.victual.piece是否为真。如果为真,执行下面的代码块 + gc.context.victual.eating = + 0; // 将gc.context.victual.eating设置为0。可能表示停止进食的行为或者重置某种状态 return; /* lifesaved */ } } @@ -960,7 +970,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) +givit(int type, register struct permonst *ptr)//Analysis for different situations { debugpline1("Attempting to give intrinsic %d", type); @@ -1384,9 +1394,11 @@ tin_details(struct obj *obj, int mnum, char *buf) Strcat(buf, " of spinach"); else if (mnum == NON_PM) Strcpy(buf, "empty tin"); - else { + else {//// 如果 obj->cknown 为真或者 iflags.override_ID 为真,并且 obj->spe < 0,那么执行以下代码块。 + // 这可能意味着这是一个已知的、被重定向的、并且其特殊属性小于0的物体。 if ((obj->cknown || iflags.override_ID) && obj->spe < 0) { - if (r == ROTTEN_TIN || r == HOMEMADE_TIN) { + 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) { /* put these before the word tin */ Sprintf(buf2, "%s %s of ", tintxts[r].txt, buf); Strcpy(buf, buf2); @@ -1396,7 +1408,12 @@ tin_details(struct obj *obj, int mnum, char *buf) } else { Strcpy(eos(buf), " of "); } - if (vegetarian(&mons[mnum])) + if (vegetarian( + &mons[mnum])) // 检查 mons[mnum] + // 是否为素食。如果是素食,那么将 + // mons[mnum].pmnames[NEUTRAL] 追加到 buf + // 的末尾。否则,将字符串 "meat" 和 + // mons[mnum].pmnames[NEUTRAL] 追加到 buf 的末尾 Sprintf(eos(buf), "%s", mons[mnum].pmnames[NEUTRAL]); else Sprintf(eos(buf), "%s meat", mons[mnum].pmnames[NEUTRAL]);