Compare commits

...

15 Commits

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

@ -1,3 +1,4 @@
//2023/12/3 wh
/* NetHack 3.7 alloc.c $NHDT-Date: 1687343500 2023/06/21 10:31:40 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.31 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
@ -122,16 +123,17 @@ static int ptrbufidx = 0;
char *
fmt_ptr(const genericptr ptr)
{
char *buf;
char *buf; // Declare a character pointer variable buf
buf = ptrbuf[ptrbufidx];
if (++ptrbufidx >= PTRBUFCNT)
ptrbufidx = 0;
buf = ptrbuf[ptrbufidx]; // Point buf to the element at index ptrbufidx in the ptrbuf array
if (++ptrbufidx >= PTRBUFCNT) // If ptrbufidx exceeds the range of PTRBUFCNT after incrementing
ptrbufidx = 0; // Reset ptrbufidx to 0
Sprintf(buf, PTR_FMT, (PTR_TYP) ptr);
return buf;
Sprintf(buf, PTR_FMT, (PTR_TYP) ptr); // Use the Sprintf function to format the pointer value into a string and store it in buf
return buf; // Return the formatted string
}
#ifdef MONITOR_HEAP
/* If ${NH_HEAPLOG} is defined and we can create a file by that name,
@ -231,42 +233,42 @@ nhdupstr(const char *string, const char *file, int line)
char *
dupstr(const char *string)
{
unsigned len = FITSuint_(strlen(string), __func__, (int) __LINE__);
unsigned len = FITSuint_(strlen(string), __func__, (int) __LINE__); // Get the length of the input string using strlen() function, and store it in the variable len
return strcpy((char *) alloc(len + 1), string);
return strcpy((char *) alloc(len + 1), string); // Allocate memory for a new string of length len+1, and copy the input string into the newly allocated memory
}
/* similar for reasonable size strings, but return length of input as well */
char *
dupstr_n(const char *string, unsigned int *lenout)
{
size_t len = strlen(string);
size_t len = strlen(string); // Get the length of the input string using strlen() function
if (len >= LARGEST_INT)
panic("string too long");
*lenout = (unsigned int) len;
return strcpy((char *) alloc(len + 1), string);
if (len >= LARGEST_INT) // If the length exceeds a predefined constant LARGEST_INT, which represents the maximum length allowed
panic("string too long"); // Raise an error or handle the situation when the string is too long
*lenout = (unsigned int) len; // Store the length of the input string in the variable lenout
return strcpy((char *) alloc(len + 1), string); // Allocate memory for a new string of length len+1, copy the input string into the newly allocated memory, and return the new string
}
/* cast to int or panic on overflow; use via macro */
int
FITSint_(LUA_INTEGER i, const char *file, int line)
{
int iret = (int) i;
int iret = (int) i; // Cast the input parameter i to int type and store it in the variable iret
if (iret != i)
panic("Overflow at %s:%d", file, line);
return iret;
if (iret != i) // If the casted value is not equal to the original input value
panic("Overflow at %s:%d", file, line); // Raise an error or handle the situation when overflow occurs
return iret; // Return the casted int value
}
unsigned
FITSuint_(unsigned long long ull, const char *file, int line)
{
unsigned uret = (unsigned) ull;
unsigned uret = (unsigned) ull; // Cast the input parameter ull to unsigned type and store it in the variable uret
if (uret != ull)
panic("Overflow at %s:%d", file, line);
return uret;
if (uret != ull) // If the casted value is not equal to the original input value
panic("Overflow at %s:%d", file, line); // Raise an error or handle the situation when overflow occurs
return uret; // Return the casted unsigned value
}
/*alloc.c*/

@ -1,3 +1,4 @@
//2023/23/3 wh
/* NetHack 3.7 apply.c $NHDT-Date: 1695159606 2023/09/19 21:40:06 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.422 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
@ -97,18 +98,18 @@ use_camera(struct obj *obj)
static int
use_towel(struct obj *obj)
{
boolean drying_feedback = (obj == uwep);
if (!freehand()) {
You("have no free %s!", body_part(HAND));
return ECMD_OK;
} else if (obj == ublindf) {
You("cannot use it while you're wearing it!");
return ECMD_OK;
} else if (obj->cursed) {
boolean drying_feedback = (obj == uwep); // Check if the object being used is the player's wielded weapon
if (!freehand()) { // If the player doesn't have a free hand
You("have no free %s!", body_part(HAND)); // Display a message indicating that the player has no free hand
return ECMD_OK; // Return with the result code ECMD_OK to indicate successful execution
} else if (obj == ublindf) { // If the object being used is the player's blindfold
You("cannot use it while you're wearing it!"); // Display a message indicating that the player cannot use the blindfold while wearing it
return ECMD_OK; // Return with the result code ECMD_OK to indicate successful execution
} else if (obj->cursed) { // If the object being used is cursed
long old;
switch (rn2(3)) {
switch (rn2(3)) { // Randomly choose one of three cases
case 2:
old = (Glib & TIMEOUT);
make_glib((int) old + rn1(10, 3)); /* + 3..12 */
@ -116,7 +117,7 @@ use_towel(struct obj *obj)
(old ? "are filthier than ever" : "get slimy"));
if (is_wet_towel(obj))
dry_a_towel(obj, -1, drying_feedback);
return ECMD_TIME;
return ECMD_TIME; // Return with the result code ECMD_TIME to indicate that time has passed
case 1:
if (!ublindf) {
old = u.ucreamed;
@ -143,20 +144,20 @@ use_towel(struct obj *obj)
}
if (is_wet_towel(obj))
dry_a_towel(obj, -1, drying_feedback);
return ECMD_TIME;
return ECMD_TIME; // Return with the result code ECMD_TIME to indicate that time has passed
case 0:
break;
}
}
if (Glib) {
make_glib(0);
if (Glib) { // If the player's hands are slippery
make_glib(0); // Remove slipperiness from the player's hands
You("wipe off your %s.",
!uarmg ? makeplural(body_part(HAND)) : gloves_simple_name(uarmg));
if (is_wet_towel(obj))
dry_a_towel(obj, -1, drying_feedback);
return ECMD_TIME;
} else if (u.ucreamed) {
return ECMD_TIME; // Return with the result code ECMD_TIME to indicate that time has passed
} else if (u.ucreamed) { // If the player's face is creamed
incr_itimeout(&HBlinded, (-1 * (int) u.ucreamed));
u.ucreamed = 0;
if (!Blinded) {
@ -170,13 +171,13 @@ use_towel(struct obj *obj)
}
if (is_wet_towel(obj))
dry_a_towel(obj, -1, drying_feedback);
return ECMD_TIME;
return ECMD_TIME; // Return with the result code ECMD_TIME to indicate that time has passed
}
Your("%s and %s are already clean.", body_part(FACE),
makeplural(body_part(HAND)));
return ECMD_OK;
return ECMD_OK; // Return with the result code ECMD_OK to indicate successful execution
}
/* maybe give a stethoscope message based on floor objects */

@ -2,7 +2,7 @@
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#include "artifact.h"
#include "artilist.h"

@ -19,25 +19,34 @@ static int bcrestriction = 0;
static struct breadcrumbs bcpbreadcrumbs = {0}, bcubreadcrumbs = {0};
#endif
void
ballrelease(boolean showmsg)
void ballrelease(boolean showmsg)
{
if (carried(uball) && !welded(uball)) {
// 如果玩家正在携带铁球并且未被焊接
if (showmsg)
pline("Startled, you drop the iron ball.");
// 如果需要显示消息,打印提示信息"Startled, you drop the iron ball."
// 移除铁球作为武器、备用武器或弹药
if (uwep == uball)
setuwep((struct obj *) 0);
// 如果当前武器是铁球,将当前武器设为无
if (uswapwep == uball)
setuswapwep((struct obj *) 0);
// 如果备用武器是铁球,将备用武器设为无
if (uquiver == uball)
setuqwep((struct obj *) 0);
/* [this used to test 'if (uwep != uball)' but that always passes
after the setuwep() above] */
freeinv(uball); /* remove from inventory but don't place on floor */
// 如果弹药是铁球,将弹药设为无
// 从物品栏中移除铁球,但不放置到地面上
freeinv(uball);
// 更新负重状态并显示相关信息
(void) encumber_msg();
}
}
/* ball&chain might hit hero when falling through a trap door */
void
ballfall(void)
@ -176,16 +185,20 @@ unplacebc_core(void)
u.bc_felt = 0; /* feel nothing */
}
static boolean
check_restriction(int restriction)
static boolean check_restriction(int restriction)
{
boolean ret = FALSE;
// 检查是否没有限制或者当前限制与覆盖限制相同
if (!bcrestriction || (restriction == override_restriction))
ret = TRUE;
// 如果满足条件则设置返回值为TRUE
else
ret = (bcrestriction == restriction) ? TRUE : FALSE;
// 否则检查当前限制是否与传入的限制相同并设置返回值为TRUE或者FALSE
return ret;
// 返回结果
}
#ifndef BREADCRUMBS
@ -283,22 +296,28 @@ Placebc(const char *funcnm, int linenum)
placebc_core();
}
void
Unplacebc(const char *funcnm, int linenum)
void Unplacebc(const char *funcnm, int linenum)
{
// 如果存在限制
if (bcrestriction) {
char panicbuf[BUFSZ];
// 创建错误消息字符串
Sprintf(panicbuf, "Unplacebc from %s:%d, when restricted to %s:%d",
funcnm, linenum,
bcubreadcrumbs.funcnm, bcubreadcrumbs.linenum);
// 将错误消息记录到日志中
paniclog("Unplacebc", panicbuf);
}
// 禁用当前限制,启用上一个限制,并更新函数名和行号
bcpbreadcrumbs.in_effect = FALSE;
bcubreadcrumbs.in_effect = TRUE;
bcubreadcrumbs.funcnm = funcnm;
bcubreadcrumbs.linenum = linenum;
// 执行unplacebc_core函数
unplacebc_core();
}

@ -17,18 +17,22 @@ no_bones_level(d_level *lev)
{
s_level *sptr;
// 如果当前d_level不是gs.save_dlevel则将当前d_level赋值为gs.save_dlevel
if (ledger_no(&gs.save_dlevel))
assign_level(lev, &gs.save_dlevel);
return (boolean) (((sptr = Is_special(lev)) != 0 && !sptr->boneid)
// 满足以下条件时返回True表示该层不能生成骨堆
return (boolean) (
// 1. 该层是特殊层并且没有设置骨堆id
((sptr = Is_special(lev)) != 0 && !sptr->boneid)
// 2. 该层所在的地牢中没有设置骨堆id
|| !gd.dungeons[lev->dnum].boneid
/* no bones on the last or multiway branch levels
in any dungeon (level 1 isn't multiway) */
// 3. 该层是地牢中的最后一层或多路分支的末端层(除了第一层)
|| Is_botlevel(lev)
|| (Is_branchlev(lev) && lev->dlevel > 1)
/* no bones in the invocation level */
|| (In_hell(lev)
&& lev->dlevel == dunlevs_in_dungeon(lev) - 1));
// 4. 该层是地狱入口
|| (In_hell(lev) && lev->dlevel == dunlevs_in_dungeon(lev) - 1)
);
}
/* Call this function for each fruit object saved in the bones level: it marks
@ -195,6 +199,7 @@ void
sanitize_name(char *namebuf)
{
int c;
// 是否在终端窗口下且终端不支持8位字符集
boolean strip_8th_bit = (WINDOWPORT(tty)
&& !iflags.wc_eight_bit_input);
@ -202,13 +207,16 @@ sanitize_name(char *namebuf)
only the current player could have left these bones--except
things like "hearse" and other bones exchange schemes make
that assumption false */
// 遍历字符串中的每个字符,进行处理
while (*namebuf) {
// 将字符转换为7位ASCII码值
c = *namebuf & 0177;
if (c < ' ' || c == '\177') {
/* non-printable or undesirable */
/* 非可打印字符或不需要的字符,用'.'代替 */
*namebuf = '.';
} else if (c != *namebuf) {
/* expected to be printable if user wants such things */
/* 如果字符不是可打印字符且用户希望看到可打印字符时,则用'_'代替 */
if (strip_8th_bit)
*namebuf = '_';
}
@ -216,6 +224,7 @@ sanitize_name(char *namebuf)
}
}
/* Give object to a random object-liking monster on or adjacent to x,y
but skipping hero's location.
If no such monster, place object on floor at x,y. */
@ -388,11 +397,15 @@ remove_mon_from_bones(struct monst *mtmp)
{
struct permonst *mptr = mtmp->data;
// If the monster is the Wizard, Medusa, or has specific monster sounds,
// or is Vlad, or is the Oracle (with specific condition), remove it from bones.
if (mtmp->iswiz || mptr == &mons[PM_MEDUSA]
|| mptr->msound == MS_NEMESIS || mptr->msound == MS_LEADER
|| is_Vlad(mtmp) /* mptr == &mons[VLAD_THE_IMPALER] || cham == VLAD */
|| (mptr == &mons[PM_ORACLE] && !fixuporacle(mtmp)))
{
mongone(mtmp);
}
}
/* save bones and possessions of a deceased adventurer */

@ -1,3 +1,4 @@
//2023/12/3 wh
/* NetHack 3.7 dbridge.c $NHDT-Date: 1596498153 2020/08/03 23:42:33 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.47 $ */
/* Copyright (c) 1989 by Jean-Christophe Collet */
/* NetHack may be freely redistributed. See license for details. */
@ -58,72 +59,67 @@ is_pool(coordxy x, coordxy y)
return FALSE;
}
boolean
is_lava(coordxy x, coordxy y)
boolean is_lava(coordxy x, coordxy y)
{
schar ltyp;
if (!isok(x, y))
return FALSE;
ltyp = levl[x][y].typ;
if (!isok(x, y)) // If the coordinates are not within the game map
return FALSE; // Return FALSE to indicate that it is not lava
ltyp = levl[x][y].typ; // Get the terrain type at the coordinates
if (ltyp == LAVAPOOL || ltyp == LAVAWALL
|| (ltyp == DRAWBRIDGE_UP
&& (levl[x][y].drawbridgemask & DB_UNDER) == DB_LAVA))
return TRUE;
return FALSE;
return TRUE; // Return TRUE if the terrain type is lava or a drawbridge over lava
return FALSE; // Otherwise, return FALSE
}
boolean
is_pool_or_lava(coordxy x, coordxy y)
boolean is_pool_or_lava(coordxy x, coordxy y)
{
if (is_pool(x, y) || is_lava(x, y))
return TRUE;
return TRUE; // Return TRUE if the location is a pool or lava
else
return FALSE;
return FALSE; // Otherwise, return FALSE
}
boolean
is_ice(coordxy x, coordxy y)
boolean is_ice(coordxy x, coordxy y)
{
schar ltyp;
if (!isok(x, y))
return FALSE;
ltyp = levl[x][y].typ;
if (!isok(x, y)) // If the coordinates are not within the game map
return FALSE; // Return FALSE to indicate that it is not ice
ltyp = levl[x][y].typ; // Get the terrain type at the coordinates
if (ltyp == ICE || (ltyp == DRAWBRIDGE_UP
&& (levl[x][y].drawbridgemask & DB_UNDER) == DB_ICE))
return TRUE;
return FALSE;
return TRUE; // Return TRUE if the terrain type is ice or a drawbridge over ice
return FALSE; // Otherwise, return FALSE
}
boolean
is_moat(coordxy x, coordxy y)
boolean is_moat(coordxy x, coordxy y)
{
schar ltyp;
if (!isok(x, y))
return FALSE;
ltyp = levl[x][y].typ;
if (!isok(x, y)) // If the coordinates are not within the game map
return FALSE; // Return FALSE to indicate that it is not a moat
ltyp = levl[x][y].typ; // Get the terrain type at the coordinates
if (!Is_juiblex_level(&u.uz)
&& (ltyp == MOAT
|| (ltyp == DRAWBRIDGE_UP
&& (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT)))
return TRUE;
return FALSE;
return TRUE; // Return TRUE if the terrain type is a moat or a drawbridge over a moat (excluding Juiblex's level)
return FALSE; // Otherwise, return FALSE
}
schar
db_under_typ(int mask)
schar db_under_typ(int mask)
{
switch (mask & DB_UNDER) {
case DB_ICE:
return ICE;
return ICE; // Return the terrain type as ice if the mask corresponds to ice
case DB_LAVA:
return LAVAPOOL;
return LAVAPOOL; // Return the terrain type as lava if the mask corresponds to lava
case DB_MOAT:
return MOAT;
return MOAT; // Return the terrain type as a moat if the mask corresponds to a moat
default:
return STONE;
return STONE; // Return the terrain type as stone for other cases
}
}

@ -1,3 +1,4 @@
//2023/12/3 大致阅读改代码,并对没有英文注释的代码加上了汉文注释
/* NetHack 3.7 write.c $NHDT-Date: 1596498232 2020/08/03 23:43:52 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.26 $ */
/* NetHack may be freely redistributed. See license for details. */
@ -62,6 +63,7 @@ cost(struct obj *otmp)
the discoveries list and aren't present in current inventory,
so some scrolls with ought to yield True will end up False */
static boolean
//判断一个玩家是否知道某个卷轴的名称
label_known(int scrolltype, struct obj *objlist)
{
struct obj *otmp;
@ -69,24 +71,30 @@ label_known(int scrolltype, struct obj *objlist)
/* only scrolls */
if (objects[scrolltype].oc_class != SCROLL_CLASS)
return FALSE;
/* type known implies full discovery; otherwise,
user-assigned name implies partial discovery */
if (objects[scrolltype].oc_name_known || objects[scrolltype].oc_uname)
return TRUE;
/* check inventory, including carried containers with known contents */
for (otmp = objlist; otmp; otmp = otmp->nobj) {
if (otmp->otyp == scrolltype && otmp->dknown)
if (otmp->otyp == scrolltype && otmp->dknown) // 检查物品种类和标记为已识别的卷轴
return TRUE;
if (Has_contents(otmp) && otmp->cknown
&& label_known(scrolltype, otmp->cobj))
if (Has_contents(otmp) && otmp->cknown // 检查物品是否是容器且已知其内容
&& label_known(scrolltype, otmp->cobj)) // 递归地检查容器内的物品
return TRUE;
}
/* not found */
return FALSE;
}
/* getobj callback for object to write on */
static int
//用于确定物品是否可以写入(即在其上书写符文或咒语)
write_ok(struct obj *obj)
{
if (!obj || (obj->oclass != SCROLL_CLASS && obj->oclass != SPBOOK_CLASS))
@ -237,10 +245,12 @@ dowrite(struct obj *pen)
found:
if (i == SCR_BLANK_PAPER || i == SPE_BLANK_PAPER) {
You_cant("write that!");
pline("It's obscene!");
return ECMD_TIME;
} else if (i == SPE_NOVEL) {
// 如果玩家尝试在空白卷轴或空白法术书上书写
You_cant("write that!"); // 提示玩家无法这样做
pline("It's obscene!"); // 发出警告
return ECMD_TIME; // 返回时间消耗
} else if (i == SPE_NOVEL) {
// 如果玩家尝试在小说上书写
boolean fanfic = !rn2(3), tearup = !rn2(3);
if (!fanfic) {
@ -256,9 +266,11 @@ dowrite(struct obj *pen)
You("give up on the idea.");
} else {
You("tear it up.");
useup(paper);
useup(paper); // 销毁使用的纸张
}
return ECMD_TIME;
return ECMD_TIME; // 返回时间消耗
}
} else if (i == SPE_BOOK_OF_THE_DEAD) {
pline("No mere dungeon adventurer could write that.");
return ECMD_TIME;

@ -0,0 +1,79 @@
用例名:道具使用
执行者:玩家
目标:将玩家装备的道具效果提交到属性面板上
前置条件:
玩家拥有至少一件道具
玩家处于可以与道具交互的状态(例如,非战斗状态)
后置条件:
道具使用后,其效果将被应用
玩家的状态可能因道具效果而改变
主要场景:
玩家选择一个道具。
玩家点击或选择“使用”选项。
游戏判断玩家是否满足使用该道具的条件(例如,是否在战斗中,道具是否为可消耗等)。
如果满足条件,游戏将执行道具效果,并在界面上显示相关信息。
如果道具具有持续效果,游戏将在一段时间内保持这些效果。
如果道具为一次性消耗品,使用后将消失。
玩家可以查看道具使用后的效果和状态变化。
交互动作:
1玩家遇到特殊情况后下达命令cmd.c并apply.c执行来选择使用道具
2装备道具后根据更新后属性面板看能否解决当前问题
3如果能解决则根据宝物使用更新内存分配alloc.c并记录时间date.c参数如果不能解决则继续试用其他宝物
用例交互图
| 玩家
| +---------------+ +--------------+ +-------------+ +-----------+ +-----------+
| | 选择道具 |---------->| 判断条件 |---------->| 显示效果 |---------->| 更新状态 |---------->| 更新UI |---------->| 反馈 |
| +---------------+ +--------------+ +-------------+ +-----------+ +-----------+
| | 游戏系统
| +---------------+ +--------------+ +-------------+ +-----------+ +-----------+
| | 触发条件 |---------->| 验证玩家 |---------->| 获取道具信息|---------->| 执行效果|---------->| 更新UI |---------->| 返回结果 |
| +---------------+ +--------------+ +-------------+ +-----------+ +-----------+
alloc.c
描述:处理游戏中的内存分配。
用例:当游戏需要创建新对象或数据结构时,会使用此模块中的函数来分配所需的内存。
apply.c
描述:处理各种应用的逻辑。
用例:当玩家对其他对象(例如对一个门应用钥匙)或自己应用药物时,相关的逻辑会被处理。
artifact.c
描述处理神器Artifact相关的逻辑。
用例:玩家可能会找到神器,并尝试使用它们或与之互动。此模块处理这些交互的逻辑。
attrib.c
描述:处理属性相关的逻辑。
用例:玩家或敌人可能有各种属性,如攻击力、防御力、速度等。此模块处理这些属性的逻辑。
ball.c
描述处理魔法球Ball相关的逻辑。
用例:魔法球是游戏中的一个对象,玩家可以捡起并使用它。此模块处理与魔法球相关的所有逻辑。
bones.c
描述处理骨头Bones相关的逻辑。
用例:骨头是游戏中一种特殊的对象,当玩家死亡后可能会留下。此模块处理与骨头相关的所有逻辑。
botl.c
描述处理宝物Treasure相关的逻辑。
用例:玩家在游戏中可能会找到各种宝物,如金币、宝石等。此模块处理与这些宝物相关的所有逻辑。
cmd.c
描述:处理命令相关的逻辑。
用例:玩家在游戏中会发出各种命令,如移动、攻击、使用物品等。此模块处理这些命令的逻辑。
date.c
描述:处理日期和时间相关的逻辑。
用例:游戏世界有一个时间流逝的机制,此模块处理与时间流逝、日期等相关的逻辑。
dbridge.c
描述处理桥Bridge相关的逻辑。
用例:桥是游戏中一种特殊的对象或地形,玩家可能需要跨过或与之互动。此模块处理与桥相关的所有逻辑。
各个函数的分类属性以及相关的简单逻辑关系如下:
玩家-》通过命令cmd.c再由apply.c来执行
系统运行-》
内存分配alloc.c
时间date.c
显示面板-》
属性面板attrib.c
道具-》
桥dbridge.c
宝物botl.c
骨头bones.c
魔法球ball.c
神器artifact.c
Loading…
Cancel
Save