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 $ */ /* 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) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */
@ -122,16 +123,17 @@ static int ptrbufidx = 0;
char * char *
fmt_ptr(const genericptr ptr) fmt_ptr(const genericptr ptr)
{ {
char *buf; char *buf; // Declare a character pointer variable buf
buf = ptrbuf[ptrbufidx]; buf = ptrbuf[ptrbufidx]; // Point buf to the element at index ptrbufidx in the ptrbuf array
if (++ptrbufidx >= PTRBUFCNT) if (++ptrbufidx >= PTRBUFCNT) // If ptrbufidx exceeds the range of PTRBUFCNT after incrementing
ptrbufidx = 0; ptrbufidx = 0; // Reset ptrbufidx to 0
Sprintf(buf, PTR_FMT, (PTR_TYP) ptr); 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 buf; // Return the formatted string
} }
#ifdef MONITOR_HEAP #ifdef MONITOR_HEAP
/* If ${NH_HEAPLOG} is defined and we can create a file by that name, /* 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 * char *
dupstr(const char *string) 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 */ /* similar for reasonable size strings, but return length of input as well */
char * char *
dupstr_n(const char *string, unsigned int *lenout) 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) if (len >= LARGEST_INT) // If the length exceeds a predefined constant LARGEST_INT, which represents the maximum length allowed
panic("string too long"); panic("string too long"); // Raise an error or handle the situation when the string is too long
*lenout = (unsigned int) len; *lenout = (unsigned int) len; // Store the length of the input string in the variable lenout
return strcpy((char *) alloc(len + 1), string); 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 */ /* cast to int or panic on overflow; use via macro */
int int
FITSint_(LUA_INTEGER i, const char *file, int line) 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) if (iret != i) // If the casted value is not equal to the original input value
panic("Overflow at %s:%d", file, line); panic("Overflow at %s:%d", file, line); // Raise an error or handle the situation when overflow occurs
return iret; return iret; // Return the casted int value
} }
unsigned unsigned
FITSuint_(unsigned long long ull, const char *file, int line) 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) if (uret != ull) // If the casted value is not equal to the original input value
panic("Overflow at %s:%d", file, line); panic("Overflow at %s:%d", file, line); // Raise an error or handle the situation when overflow occurs
return uret; return uret; // Return the casted unsigned value
} }
/*alloc.c*/ /*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 $ */ /* 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) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */
@ -97,18 +98,18 @@ use_camera(struct obj *obj)
static int static int
use_towel(struct obj *obj) use_towel(struct obj *obj)
{ {
boolean drying_feedback = (obj == uwep); boolean drying_feedback = (obj == uwep); // Check if the object being used is the player's wielded weapon
if (!freehand()) { if (!freehand()) { // If the player doesn't have a free hand
You("have no free %s!", body_part(HAND)); You("have no free %s!", body_part(HAND)); // Display a message indicating that the player has no free hand
return ECMD_OK; return ECMD_OK; // Return with the result code ECMD_OK to indicate successful execution
} else if (obj == ublindf) { } else if (obj == ublindf) { // If the object being used is the player's blindfold
You("cannot use it while you're wearing it!"); 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 ECMD_OK; // Return with the result code ECMD_OK to indicate successful execution
} else if (obj->cursed) { } else if (obj->cursed) { // If the object being used is cursed
long old; long old;
switch (rn2(3)) { switch (rn2(3)) { // Randomly choose one of three cases
case 2: case 2:
old = (Glib & TIMEOUT); old = (Glib & TIMEOUT);
make_glib((int) old + rn1(10, 3)); /* + 3..12 */ 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")); (old ? "are filthier than ever" : "get slimy"));
if (is_wet_towel(obj)) if (is_wet_towel(obj))
dry_a_towel(obj, -1, drying_feedback); 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: case 1:
if (!ublindf) { if (!ublindf) {
old = u.ucreamed; old = u.ucreamed;
@ -143,20 +144,20 @@ use_towel(struct obj *obj)
} }
if (is_wet_towel(obj)) if (is_wet_towel(obj))
dry_a_towel(obj, -1, drying_feedback); 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: case 0:
break; break;
} }
} }
if (Glib) { if (Glib) { // If the player's hands are slippery
make_glib(0); make_glib(0); // Remove slipperiness from the player's hands
You("wipe off your %s.", You("wipe off your %s.",
!uarmg ? makeplural(body_part(HAND)) : gloves_simple_name(uarmg)); !uarmg ? makeplural(body_part(HAND)) : gloves_simple_name(uarmg));
if (is_wet_towel(obj)) if (is_wet_towel(obj))
dry_a_towel(obj, -1, drying_feedback); 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
} else if (u.ucreamed) { } else if (u.ucreamed) { // If the player's face is creamed
incr_itimeout(&HBlinded, (-1 * (int) u.ucreamed)); incr_itimeout(&HBlinded, (-1 * (int) u.ucreamed));
u.ucreamed = 0; u.ucreamed = 0;
if (!Blinded) { if (!Blinded) {
@ -170,13 +171,13 @@ use_towel(struct obj *obj)
} }
if (is_wet_towel(obj)) if (is_wet_towel(obj))
dry_a_towel(obj, -1, drying_feedback); 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), Your("%s and %s are already clean.", body_part(FACE),
makeplural(body_part(HAND))); 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 */ /* maybe give a stethoscope message based on floor objects */

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

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

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

@ -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 $ */ /* 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 */ /* Copyright (c) 1989 by Jean-Christophe Collet */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@ -58,72 +59,67 @@ is_pool(coordxy x, coordxy y)
return FALSE; return FALSE;
} }
boolean boolean is_lava(coordxy x, coordxy y)
is_lava(coordxy x, coordxy y)
{ {
schar ltyp; schar ltyp;
if (!isok(x, y)) if (!isok(x, y)) // If the coordinates are not within the game map
return FALSE; return FALSE; // Return FALSE to indicate that it is not lava
ltyp = levl[x][y].typ; ltyp = levl[x][y].typ; // Get the terrain type at the coordinates
if (ltyp == LAVAPOOL || ltyp == LAVAWALL if (ltyp == LAVAPOOL || ltyp == LAVAWALL
|| (ltyp == DRAWBRIDGE_UP || (ltyp == DRAWBRIDGE_UP
&& (levl[x][y].drawbridgemask & DB_UNDER) == DB_LAVA)) && (levl[x][y].drawbridgemask & DB_UNDER) == DB_LAVA))
return TRUE; return TRUE; // Return TRUE if the terrain type is lava or a drawbridge over lava
return FALSE; return FALSE; // Otherwise, return FALSE
} }
boolean boolean is_pool_or_lava(coordxy x, coordxy y)
is_pool_or_lava(coordxy x, coordxy y)
{ {
if (is_pool(x, y) || is_lava(x, 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 else
return FALSE; return FALSE; // Otherwise, return FALSE
} }
boolean boolean is_ice(coordxy x, coordxy y)
is_ice(coordxy x, coordxy y)
{ {
schar ltyp; schar ltyp;
if (!isok(x, y)) if (!isok(x, y)) // If the coordinates are not within the game map
return FALSE; return FALSE; // Return FALSE to indicate that it is not ice
ltyp = levl[x][y].typ; ltyp = levl[x][y].typ; // Get the terrain type at the coordinates
if (ltyp == ICE || (ltyp == DRAWBRIDGE_UP if (ltyp == ICE || (ltyp == DRAWBRIDGE_UP
&& (levl[x][y].drawbridgemask & DB_UNDER) == DB_ICE)) && (levl[x][y].drawbridgemask & DB_UNDER) == DB_ICE))
return TRUE; return TRUE; // Return TRUE if the terrain type is ice or a drawbridge over ice
return FALSE; return FALSE; // Otherwise, return FALSE
} }
boolean boolean is_moat(coordxy x, coordxy y)
is_moat(coordxy x, coordxy y)
{ {
schar ltyp; schar ltyp;
if (!isok(x, y)) if (!isok(x, y)) // If the coordinates are not within the game map
return FALSE; return FALSE; // Return FALSE to indicate that it is not a moat
ltyp = levl[x][y].typ; ltyp = levl[x][y].typ; // Get the terrain type at the coordinates
if (!Is_juiblex_level(&u.uz) if (!Is_juiblex_level(&u.uz)
&& (ltyp == MOAT && (ltyp == MOAT
|| (ltyp == DRAWBRIDGE_UP || (ltyp == DRAWBRIDGE_UP
&& (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT))) && (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT)))
return TRUE; return TRUE; // Return TRUE if the terrain type is a moat or a drawbridge over a moat (excluding Juiblex's level)
return FALSE; return FALSE; // Otherwise, return FALSE
} }
schar schar db_under_typ(int mask)
db_under_typ(int mask)
{ {
switch (mask & DB_UNDER) { switch (mask & DB_UNDER) {
case DB_ICE: case DB_ICE:
return ICE; return ICE; // Return the terrain type as ice if the mask corresponds to ice
case DB_LAVA: case DB_LAVA:
return LAVAPOOL; return LAVAPOOL; // Return the terrain type as lava if the mask corresponds to lava
case DB_MOAT: case DB_MOAT:
return MOAT; return MOAT; // Return the terrain type as a moat if the mask corresponds to a moat
default: 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 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. */ /* 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, the discoveries list and aren't present in current inventory,
so some scrolls with ought to yield True will end up False */ so some scrolls with ought to yield True will end up False */
static boolean static boolean
//判断一个玩家是否知道某个卷轴的名称
label_known(int scrolltype, struct obj *objlist) label_known(int scrolltype, struct obj *objlist)
{ {
struct obj *otmp; struct obj *otmp;
@ -69,24 +71,30 @@ label_known(int scrolltype, struct obj *objlist)
/* only scrolls */ /* only scrolls */
if (objects[scrolltype].oc_class != SCROLL_CLASS) if (objects[scrolltype].oc_class != SCROLL_CLASS)
return FALSE; return FALSE;
/* type known implies full discovery; otherwise, /* type known implies full discovery; otherwise,
user-assigned name implies partial discovery */ user-assigned name implies partial discovery */
if (objects[scrolltype].oc_name_known || objects[scrolltype].oc_uname) if (objects[scrolltype].oc_name_known || objects[scrolltype].oc_uname)
return TRUE; return TRUE;
/* check inventory, including carried containers with known contents */ /* check inventory, including carried containers with known contents */
for (otmp = objlist; otmp; otmp = otmp->nobj) { for (otmp = objlist; otmp; otmp = otmp->nobj) {
if (otmp->otyp == scrolltype && otmp->dknown) if (otmp->otyp == scrolltype && otmp->dknown) // 检查物品种类和标记为已识别的卷轴
return TRUE; 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; return TRUE;
} }
/* not found */ /* not found */
return FALSE; return FALSE;
} }
/* getobj callback for object to write on */ /* getobj callback for object to write on */
static int static int
//用于确定物品是否可以写入(即在其上书写符文或咒语)
write_ok(struct obj *obj) write_ok(struct obj *obj)
{ {
if (!obj || (obj->oclass != SCROLL_CLASS && obj->oclass != SPBOOK_CLASS)) if (!obj || (obj->oclass != SCROLL_CLASS && obj->oclass != SPBOOK_CLASS))
@ -237,10 +245,12 @@ dowrite(struct obj *pen)
found: found:
if (i == SCR_BLANK_PAPER || i == SPE_BLANK_PAPER) { if (i == SCR_BLANK_PAPER || i == SPE_BLANK_PAPER) {
You_cant("write that!"); // 如果玩家尝试在空白卷轴或空白法术书上书写
pline("It's obscene!"); You_cant("write that!"); // 提示玩家无法这样做
return ECMD_TIME; pline("It's obscene!"); // 发出警告
return ECMD_TIME; // 返回时间消耗
} else if (i == SPE_NOVEL) { } else if (i == SPE_NOVEL) {
// 如果玩家尝试在小说上书写
boolean fanfic = !rn2(3), tearup = !rn2(3); boolean fanfic = !rn2(3), tearup = !rn2(3);
if (!fanfic) { if (!fanfic) {
@ -256,9 +266,11 @@ dowrite(struct obj *pen)
You("give up on the idea."); You("give up on the idea.");
} else { } else {
You("tear it up."); You("tear it up.");
useup(paper); useup(paper); // 销毁使用的纸张
} }
return ECMD_TIME; return ECMD_TIME; // 返回时间消耗
}
} else if (i == SPE_BOOK_OF_THE_DEAD) { } else if (i == SPE_BOOK_OF_THE_DEAD) {
pline("No mere dungeon adventurer could write that."); pline("No mere dungeon adventurer could write that.");
return ECMD_TIME; 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