Compare commits

..

6 Commits

Author SHA1 Message Date
yk e1ed67a1cf yk
2 years ago
yk 862f1a236c yk
2 years ago
yk 7a0a885c06 yk
2 years ago
yk 10a2674705 yk
2 years ago
yk ae47fc013e i miss you
2 years ago
yk c9aefff673 sb
2 years ago

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

@ -230,59 +230,76 @@ kick_monster(struct monst *mon, coordxy x, coordxy y)
* [80%-90%) | 1/3 | 1/2 * [80%-90%) | 1/3 | 1/2
* [90%-100%) | 1/2 | 1 * [90%-100%) | 1/2 | 1
*/ */
/* This is a C language code snippet that describes a player character's kicking action in a game. */
if (i < (j * 3) / 10) { if (i < (j * 3) / 10) {
/* If the condition (i < (j * 3) / 10) is true, execute the following code block: */
if (!rn2((i < j / 10) ? 2 : (i < j / 5) ? 3 : 4)) { if (!rn2((i < j / 10) ? 2 : (i < j / 5) ? 3 : 4)) {
if (martial()) /* If the result of rn2((i < j / 10) ? 2 : (i < j / 5) ? 3 : 4) is false (0), do the following: */
if (martial()) {
goto doit; goto doit;
Your("clumsy kick does no damage."); } else {
(void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE); /* Output "Your clumsy kick does no damage." and call passive() function, then return. */
pline("Your clumsy kick does no damage.");
passive();
return; return;
} }
if (i < j / 10) }
if (i < j / 10) {
clumsy = TRUE; clumsy = TRUE;
else if (!rn2((i < j / 5) ? 2 : 3)) } else if (!rn2((i < j / 5) ? 2 : 3)) {
clumsy = TRUE; clumsy = TRUE;
} }
}
if (Fumbling) if (Fumbling) {
clumsy = TRUE; clumsy = TRUE;
} else if (uarm && objects[uarm->otyp].oc_bulky && ACURR(A_DEX) < rnd(25)) {
else if (uarm && objects[uarm->otyp].oc_bulky && ACURR(A_DEX) < rnd(25))
clumsy = TRUE; clumsy = TRUE;
}
doit: doit:
You("kick %s.", mon_nam(mon)); /* Output "You kick __." where __ is the name of the enemy. */
if (!rn2(clumsy ? 3 : 4) && (clumsy || !bigmonst(mon->data)) pline("You kick %s.", mon_nam(mon));
&& mon->mcansee && !mon->mtrapped && !thick_skinned(mon->data)
&& mon->data->mlet != S_EEL && haseyes(mon->data) && mon->mcanmove if ((!rn2(clumsy ? 3 : 4) || (clumsy || mon->data->msize == MZ_SMALL)) &&
&& !mon->mstun && !mon->mconf && !mon->msleeping mon->mcansee && !mon->mtrapped && !thick_skinned(mon->data) &&
&& mon->data->mmove >= 12) { mon->data->mlet != S_EEL && haseyes(mon->data) &&
mon->mcanmove && !mon->mstun && !mon->mconf && !mon->msleeping &&
mon->data->mmove >= 12) {
if (!nohands(mon->data) && !rn2(martial() ? 5 : 3)) { if (!nohands(mon->data) && !rn2(martial() ? 5 : 3)) {
pline("%s blocks your %skick.", Monnam(mon), /* Output "%s blocks your %skick." where %s is the name of the enemy,
clumsy ? "clumsy " : ""); * %skick can be "clumsy ", and call passive() function, then return. */
(void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE); pline("%s blocks your %skick.", Monnam(mon), clumsy ? "clumsy " : "");
passive();
return; return;
} else { } else {
maybe_mnexto(mon); maybe_mnexto(mon);
if (mon->mx != x || mon->my != y) { if (mon->mx != x || mon->my != y) {
(void) unmap_invisible(x, y); unmap_invisible(x, y);
/* Output "%s %s, %s evading your %skick." where %s is the name of the enemy,
* %s can be "teleports", "floats", "swoops", or "slides",
* %s can be "easily" or "nimbly", and %s can be "clumsy ".
* Then call passive() function, and return. */
pline("%s %s, %s evading your %skick.", Monnam(mon), pline("%s %s, %s evading your %skick.", Monnam(mon),
(can_teleport(mon->data) && !noteleport_level(mon)) teleport_control(mon) ? "teleports" :
? "teleports" is_floater(mon->data) ? "floats" :
: is_floater(mon->data) is_flyer(mon->data) ? "swoops" : "slides",
? "floats" (is_floater(mon->data) || mon->data->mmove >= 12) ? "easily" : "nimbly",
: is_flyer(mon->data) ? "swoops" clumsy ? "clumsy " : "");
: (nolimbs(mon->data) passive();
|| slithy(mon->data))
? "slides"
: "jumps",
clumsy ? "easily" : "nimbly", clumsy ? "clumsy " : "");
(void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
return; return;
} }
} }
} }
kickdmg(mon, clumsy); kickdmg(mon, clumsy);
}
/* /*
* Return TRUE if caught (the gold taken care of), FALSE otherwise. * Return TRUE if caught (the gold taken care of), FALSE otherwise.

@ -97,38 +97,49 @@ const uchar def_r_oc_syms[MAXOCLASSES] = {
* recognized, then MAXOCLASSES is returned. Used in detect.c, invent.c, * recognized, then MAXOCLASSES is returned. Used in detect.c, invent.c,
* objnam.c, options.c, pickup.c, sp_lev.c, lev_main.c, and tilemap.c. * objnam.c, options.c, pickup.c, sp_lev.c, lev_main.c, and tilemap.c.
*/ */
int int def_char_to_objclass(char ch)
def_char_to_objclass(char ch)
{ {
int i; int i;
for (i = 1; i < MAXOCLASSES; i++) // Iterate through the object classes
for (i = 1; i < MAXOCLASSES; i++) {
// Check if the character matches the symbol of the current object class
if (ch == def_oc_syms[i].sym) if (ch == def_oc_syms[i].sym)
break; break;
}
// Return the index representing the object class if a match is found
// If no match is found, return MAXOCLASSES
return i; return i;
} }
/* /*
* Convert a character into a monster class. This returns the _first_ * Convert a character into a monster class. This returns the _first_
* match made. If there are are no matches, return MAXMCLASSES. * match made. If there are are no matches, return MAXMCLASSES.
* Used in detect.c, options.c, read.c, sp_lev.c, and lev_main.c * Used in detect.c, options.c, read.c, sp_lev.c, and lev_main.c
*/ */
int int def_char_to_monclass(char ch)
def_char_to_monclass(char ch)
{ {
int i; int i;
for (i = 1; i < MAXMCLASSES; i++) // Iterate through the monster classes
for (i = 1; i < MAXMCLASSES; i++) {
// Check if the character matches the symbol of the current monster class
if (ch == def_monsyms[i].sym) if (ch == def_monsyms[i].sym)
break; break;
}
// Return the index representing the monster class if a match is found
// If no match is found, return MAXMCLASSES
return i; return i;
} }
/* does 'ch' represent a furniture character? returns index into defsyms[] */ /* does 'ch' represent a furniture character? returns index into defsyms[] */
int int def_char_is_furniture(char ch)
def_char_is_furniture(char ch)
{ {
/* note: these refer to defsyms[] order which is much different from /* Note: these refer to defsyms[] order which is much different from
levl[][].typ order but both keep furniture in a contiguous block */ levl[][].typ order but both keep furniture in a contiguous block */
static const char first_furniture[] = "stair", /* "staircase up" */ static const char first_furniture[] = "stair", /* "staircase up" */
last_furniture[] = "fountain"; last_furniture[] = "fountain";
@ -137,17 +148,22 @@ def_char_is_furniture(char ch)
for (i = 0; i < MAXPCHARS; ++i) { for (i = 0; i < MAXPCHARS; ++i) {
if (!furniture) { if (!furniture) {
// Check if the current explanation matches the start of furniture
if (!strncmp(defsyms[i].explanation, first_furniture, 5)) if (!strncmp(defsyms[i].explanation, first_furniture, 5))
furniture = TRUE; furniture = TRUE;
} }
if (furniture) { if (furniture) {
// If the current symbol matches the input character, return the index
if (defsyms[i].sym == (uchar) ch) if (defsyms[i].sym == (uchar) ch)
return i; return i;
// If the current explanation matches the end of furniture, break the loop
if (!strcmp(defsyms[i].explanation, last_furniture)) if (!strcmp(defsyms[i].explanation, last_furniture))
break; /* reached last furniture */ break; /* reached last furniture */
} }
} }
// If no match is found, return -1
return -1; return -1;
} }
/*drawing.c*/ /*drawing.c*/

@ -8,51 +8,51 @@
#include <limits.h> #include <limits.h>
#endif #endif
static int enermod(int); static int enermod(int en);
long long newuexp(int lev)
newuexp(int lev)
{ {
if (lev < 1) /* for newuexp(u.ulevel - 1) when u.ulevel is 1 */ if (lev < 1) /* for newuexp(u.ulevel - 1) when u.ulevel is 1 */
return 0L; return 0L;
if (lev < 10) if (lev < 10)
return (10L * (1L << lev)); return (10L * (1L << lev)); // Experience calculation for levels 1-9
if (lev < 20) if (lev < 20)
return (10000L * (1L << (lev - 10))); return (10000L * (1L << (lev - 10))); // Experience calculation for levels 10-19
return (10000000L * ((long) (lev - 19))); return (10000000L * ((long) (lev - 19))); // Experience calculation for levels 20 and above
} }
static int static int enermod(int en)
enermod(int en)
{ {
switch (Role_switch) { switch (Role_switch) {
case PM_CLERIC: case PM_CLERIC:
case PM_WIZARD: case PM_WIZARD:
return (2 * en); return (2 * en); // Energy modification for Clerics and Wizards
case PM_HEALER: case PM_HEALER:
case PM_KNIGHT: case PM_KNIGHT:
return ((3 * en) / 2); return ((3 * en) / 2); // Energy modification for Healers and Knights
case PM_BARBARIAN: case PM_BARBARIAN:
case PM_VALKYRIE: case PM_VALKYRIE:
return ((3 * en) / 4); return ((3 * en) / 4); // Energy modification for Barbarians and Valkyries
default: default:
return en; return en; // No modification for other roles
} }
} }
/* calculate spell power/energy points for new level */ /* calculate spell power/energy points for new level */
int int newpw(void)
newpw(void)
{ {
int en = 0, enrnd, enfix; int en = 0, enrnd, enfix;
if (u.ulevel == 0) { if (u.ulevel == 0) {
// For level 0 characters (starting level), calculate initial en based on role and race
en = gu.urole.enadv.infix + gu.urace.enadv.infix; en = gu.urole.enadv.infix + gu.urace.enadv.infix;
if (gu.urole.enadv.inrnd > 0) if (gu.urole.enadv.inrnd > 0)
en += rnd(gu.urole.enadv.inrnd); en += rnd(gu.urole.enadv.inrnd);
if (gu.urace.enadv.inrnd > 0) if (gu.urace.enadv.inrnd > 0)
en += rnd(gu.urace.enadv.inrnd); en += rnd(gu.urace.enadv.inrnd);
} else { } else {
// For higher levels, calculate en based on attributes and role/race modifiers
enrnd = (int) ACURR(A_WIS) / 2; enrnd = (int) ACURR(A_WIS) / 2;
if (u.ulevel < gu.urole.xlev) { if (u.ulevel < gu.urole.xlev) {
enrnd += gu.urole.enadv.lornd + gu.urace.enadv.lornd; enrnd += gu.urole.enadv.lornd + gu.urace.enadv.lornd;
@ -61,23 +61,26 @@ newpw(void)
enrnd += gu.urole.enadv.hirnd + gu.urace.enadv.hirnd; enrnd += gu.urole.enadv.hirnd + gu.urace.enadv.hirnd;
enfix = gu.urole.enadv.hifix + gu.urace.enadv.hifix; enfix = gu.urole.enadv.hifix + gu.urace.enadv.hifix;
} }
en = enermod(rn1(enrnd, enfix)); en = enermod(rn1(enrnd, enfix)); // Apply energy modifier based on role
} }
if (en <= 0) if (en <= 0)
en = 1; en = 1; // If en is negative or zero, set it to 1
if (u.ulevel < MAXULEV) { if (u.ulevel < MAXULEV) {
/* remember increment; future level drain could take it away again */ /* remember increment; future level drain could take it away again */
u.ueninc[u.ulevel] = (xint16) en; u.ueninc[u.ulevel] = (xint16) en; // Store the energy increment for the current level
} else { } else {
/* after level 30, throttle energy gains from extra experience; /* after level 30, throttle energy gains from extra experience;
once max reaches 600, further increments will be just 1 more */ once max reaches 600, further increments will be just 1 more */
char lim = 4 - u.uenmax / 200; char lim = 4 - u.uenmax / 200; // Calculate the maximum limit for energy gain
lim = max(lim, 1); lim = max(lim, 1); // Make sure the limit is at least 1
if (en > lim) if (en > lim)
en = lim; en = lim; // Cap the energy gain to the calculated limit
} }
return en;
return en; // Return the maximum power points (en)
} }
/* return # of exp points for mtmp after nk killed */ /* return # of exp points for mtmp after nk killed */
@ -112,19 +115,28 @@ experience(register struct monst *mtmp, register int nk)
/* For each "special" damage type give extra experience */ /* For each "special" damage type give extra experience */
for (i = 0; i < NATTK; i++) { for (i = 0; i < NATTK; i++) {
tmp2 = ptr->mattk[i].adtyp; tmp2 = ptr->mattk[i].adtyp; // Get the attack type of the monster's attack
if (tmp2 > AD_PHYS && tmp2 < AD_BLND)
// Check various conditions and add the corresponding damage bonus
if (tmp2 > AD_PHYS && tmp2 < AD_BLND) {
tmp += 2 * mtmp->m_lev; tmp += 2 * mtmp->m_lev;
else if ((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || (tmp2 == AD_SLIM)) } else if ((tmp2 == AD_DRLI) || (tmp2 == AD_STON) || (tmp2 == AD_SLIM)) {
tmp += 50; tmp += 50;
else if (tmp2 != AD_PHYS) } else if (tmp2 != AD_PHYS) {
tmp += mtmp->m_lev; tmp += mtmp->m_lev;
/* extra heavy damage bonus */ }
if ((int) (ptr->mattk[i].damd * ptr->mattk[i].damn) > 23)
// Check for an extra heavy damage bonus
if ((int) (ptr->mattk[i].damd * ptr->mattk[i].damn) > 23) {
tmp += mtmp->m_lev; tmp += mtmp->m_lev;
if (tmp2 == AD_WRAP && ptr->mlet == S_EEL && !Amphibious) }
// Add an additional bonus for specific conditions
if (tmp2 == AD_WRAP && ptr->mlet == S_EEL && !Amphibious) {
tmp += 1000; tmp += 1000;
} }
}
/* For certain "extra nasty" monsters, give even more */ /* For certain "extra nasty" monsters, give even more */
if (extra_nasty(ptr)) if (extra_nasty(ptr))
@ -252,37 +264,37 @@ losexp(
we don't allow it to go up because that contradicts assumptions we don't allow it to go up because that contradicts assumptions
elsewhere (such as healing wielder who drains with Stormbringer) */ elsewhere (such as healing wielder who drains with Stormbringer) */
if (u.uhpmax > olduhpmax) if (u.uhpmax > olduhpmax)
setuhpmax(olduhpmax); setuhpmax(olduhpmax); // If the maximum hit points (u.uhpmax) is greater than the previous maximum (olduhpmax), set it to the old maximum
u.uhp -= num; u.uhp -= num; // Subtract 'num' from the current hit points (u.uhp)
if (u.uhp < 1) if (u.uhp < 1)
u.uhp = 1; u.uhp = 1; // If the hit points are less than 1, set them to 1 (minimum value)
else if (u.uhp > u.uhpmax) else if (u.uhp > u.uhpmax)
u.uhp = u.uhpmax; u.uhp = u.uhpmax; // If the hit points are greater than the maximum hit points, set them to the maximum hit points
num = (int) u.ueninc[u.ulevel]; num = (int) u.ueninc[u.ulevel]; // Get the energy increment for the current player level
u.uenmax -= num; u.uenmax -= num; // Subtract 'num' from the maximum energy points (u.uenmax)
if (u.uenmax < 0) if (u.uenmax < 0)
u.uenmax = 0; u.uenmax = 0; // If the maximum energy points are less than 0, set them to 0 (minimum value)
u.uen -= num; u.uen -= num; // Subtract 'num' from the current energy points (u.uen)
if (u.uen < 0) if (u.uen < 0)
u.uen = 0; u.uen = 0; // If the energy points are less than 0, set them to 0 (minimum value)
else if (u.uen > u.uenmax) else if (u.uen > u.uenmax)
u.uen = u.uenmax; u.uen = u.uenmax; // If the energy points are greater than the maximum energy points, set them to the maximum energy points
if (u.uexp > 0) if (u.uexp > 0)
u.uexp = newuexp(u.ulevel) - 1; u.uexp = newuexp(u.ulevel) - 1; // If the experience points (u.uexp) are greater than 0, update them based on the current player level
if (Upolyd) { if (Upolyd) {
num = monhp_per_lvl(&gy.youmonst); num = monhp_per_lvl(&gy.youmonst); // Calculate the hit points per level for the current polymorphed form
u.mhmax -= num; u.mhmax -= num; // Subtract 'num' from the maximum monster hit points (u.mhmax)
u.mh -= num; u.mh -= num; // Subtract 'num' from the current monster hit points (u.mh)
if (u.mh <= 0) if (u.mh <= 0)
rehumanize(); rehumanize(); // If the monster hit points are less than or equal to 0, change back to the player form
} }
gc.context.botl = TRUE; gc.context.botl = TRUE; // Set a flag to indicate that the status line needs to be updated
}
/* /*
* Make experience gaining similar to AD&D(tm), whereby you can at most go * Make experience gaining similar to AD&D(tm), whereby you can at most go

@ -17,122 +17,177 @@ static void roguejoin(coordxy, coordxy, coordxy, coordxy, int);
static void roguecorr(coordxy, coordxy, int); static void roguecorr(coordxy, coordxy, int);
static void miniwalk(coordxy, coordxy); static void miniwalk(coordxy, coordxy);
static static void roguejoin(coordxy x1, coordxy y1, coordxy x2, coordxy y2, int horiz)
void
roguejoin(coordxy x1, coordxy y1, coordxy x2, coordxy y2, int horiz)
{ {
register coordxy x, y, middle; register coordxy x, y, middle;
if (horiz) { if (horiz) {
// Calculate the midpoint for the horizontal corridor
middle = x1 + rn2(x2 - x1 + 1); middle = x1 + rn2(x2 - x1 + 1);
// Create the first segment of the corridor along the x-axis
for (x = min(x1, middle); x <= max(x1, middle); x++) for (x = min(x1, middle); x <= max(x1, middle); x++)
corr(x, y1); corr(x, y1);
// Create the vertical segment of the corridor
for (y = min(y1, y2); y <= max(y1, y2); y++) for (y = min(y1, y2); y <= max(y1, y2); y++)
corr(middle, y); corr(middle, y);
// Create the second segment of the corridor along the x-axis
for (x = min(middle, x2); x <= max(middle, x2); x++) for (x = min(middle, x2); x <= max(middle, x2); x++)
corr(x, y2); corr(x, y2);
} else { } else {
// Calculate the midpoint for the vertical corridor
middle = y1 + rn2(y2 - y1 + 1); middle = y1 + rn2(y2 - y1 + 1);
// Create the first segment of the corridor along the y-axis
for (y = min(y1, middle); y <= max(y1, middle); y++) for (y = min(y1, middle); y <= max(y1, middle); y++)
corr(x1, y); corr(x1, y);
// Create the horizontal segment of the corridor
for (x = min(x1, x2); x <= max(x1, x2); x++) for (x = min(x1, x2); x <= max(x1, x2); x++)
corr(x, middle); corr(x, middle);
// Create the second segment of the corridor along the y-axis
for (y = min(middle, y2); y <= max(middle, y2); y++) for (y = min(middle, y2); y <= max(middle, y2); y++)
corr(x2, y); corr(x2, y);
} }
} }
static static void roguecorr(coordxy x, coordxy y, int dir)
void
roguecorr(coordxy x, coordxy y, int dir)
{ {
register coordxy fromx, fromy, tox, toy; register coordxy fromx, fromy, tox, toy;
if (dir == XL_DOWN) { if (dir == XL_DOWN) {
// Disable the down door in the current room
gr.r[x][y].doortable &= ~XL_DOWN; gr.r[x][y].doortable &= ~XL_DOWN;
if (!gr.r[x][y].real) { if (!gr.r[x][y].real) {
// If the current room is not a real room, calculate the starting coordinates for the virtual room
fromx = gr.r[x][y].rlx; fromx = gr.r[x][y].rlx;
fromy = gr.r[x][y].rly; fromy = gr.r[x][y].rly;
fromx += 1 + 26 * x; fromx += 1 + 26 * x;
fromy += 7 * y; fromy += 7 * y;
} else { } else {
// If the current room is a real room, calculate the starting coordinates based on the room size and position
fromx = gr.r[x][y].rlx + rn2(gr.r[x][y].dx); fromx = gr.r[x][y].rlx + rn2(gr.r[x][y].dx);
fromy = gr.r[x][y].rly + gr.r[x][y].dy; fromy = gr.r[x][y].rly + gr.r[x][y].dy;
fromx += 1 + 26 * x; fromx += 1 + 26 * x;
fromy += 7 * y; fromy += 7 * y;
// Check if there is a wall at the starting coordinates. If not, output an error message.
if (!IS_WALL(levl[fromx][fromy].typ)) if (!IS_WALL(levl[fromx][fromy].typ))
impossible("down: no wall at %d,%d?", fromx, fromy); impossible("down: no wall at %d,%d?", fromx, fromy);
// Create a door at the starting coordinates and mark it as no door
dodoor(fromx, fromy, &gr.rooms[gr.r[x][y].nroom]); dodoor(fromx, fromy, &gr.rooms[gr.r[x][y].nroom]);
levl[fromx][fromy].doormask = D_NODOOR; levl[fromx][fromy].doormask = D_NODOOR;
fromy++; fromy++;
} }
if (y >= 2) { if (y >= 2) {
// If the current row is greater than or equal to 2, output an error message
impossible("down door from %d,%d going nowhere?", x, y); impossible("down door from %d,%d going nowhere?", x, y);
return; return;
} }
// Move to the next row
y++; y++;
// Disable the up door in the next room
gr.r[x][y].doortable &= ~XL_UP; gr.r[x][y].doortable &= ~XL_UP;
if (!gr.r[x][y].real) { if (!gr.r[x][y].real) {
// If the next room is not a real room, calculate the ending coordinates for the virtual room
tox = gr.r[x][y].rlx; tox = gr.r[x][y].rlx;
toy = gr.r[x][y].rly; toy = gr.r[x][y].rly;
tox += 1 + 26 * x; tox += 1 + 26 * x;
toy += 7 * y; toy += 7 * y;
} else { } else {
// If the next room is a real room, calculate the ending coordinates based on the room size and position
tox = gr.r[x][y].rlx + rn2(gr.r[x][y].dx); tox = gr.r[x][y].rlx + rn2(gr.r[x][y].dx);
toy = gr.r[x][y].rly - 1; toy = gr.r[x][y].rly - 1;
tox += 1 + 26 * x; tox += 1 + 26 * x;
toy += 7 * y; toy += 7 * y;
// Check if there is a wall at the ending coordinates. If not, output an error message.
if (!IS_WALL(levl[tox][toy].typ)) if (!IS_WALL(levl[tox][toy].typ))
impossible("up: no wall at %d,%d?", tox, toy); impossible("up: no wall at %d,%d?", tox, toy);
// Create a door at the ending coordinates and mark it as no door
dodoor(tox, toy, &gr.rooms[gr.r[x][y].nroom]); dodoor(tox, toy, &gr.rooms[gr.r[x][y].nroom]);
levl[tox][toy].doormask = D_NODOOR; levl[tox][toy].doormask = D_NODOOR;
toy--; toy--;
} }
// Call the `roguejoin` function to create a corridor connecting the starting and ending coordinates
roguejoin(fromx, fromy, tox, toy, FALSE); roguejoin(fromx, fromy, tox, toy, FALSE);
return; return;
} else if (dir == XL_RIGHT) { } else if (dir == XL_RIGHT) {
// Disable the right door in the current room
gr.r[x][y].doortable &= ~XL_RIGHT; gr.r[x][y].doortable &= ~XL_RIGHT;
if (!gr.r[x][y].real) { if (!gr.r[x][y].real) {
// If the current room is not a real room, calculate the starting coordinates for the virtual room
fromx = gr.r[x][y].rlx; fromx = gr.r[x][y].rlx;
fromy = gr.r[x][y].rly; fromy = gr.r[x][y].rly;
fromx += 1 + 26 * x; fromx += 1 + 26 * x;
fromy += 7 * y; fromy += 7 * y;
} else { } else {
// If the current room is a real room, calculate the starting coordinates based on the room size and position
fromx = gr.r[x][y].rlx + gr.r[x][y].dx; fromx = gr.r[x][y].rlx + gr.r[x][y].dx;
fromy = gr.r[x][y].rly + rn2(gr.r[x][y].dy); fromy = gr.r[x][y].rly + rn2(gr.r[x][y].dy);
fromx += 1 + 26 * x; fromx += 1 + 26 * x;
fromy += 7 * y; fromy += 7 * y;
// Check if there is a wall at the starting coordinates. If not, output an error message.
if (!IS_WALL(levl[fromx][fromy].typ)) if (!IS_WALL(levl[fromx][fromy].typ))
impossible("down: no wall at %d,%d?", fromx, fromy); impossible("down: no wall at %d,%d?", fromx, fromy);
// Create a door at the starting coordinates and mark it as no door
dodoor(fromx, fromy, &gr.rooms[gr.r[x][y].nroom]); dodoor(fromx, fromy, &gr.rooms[gr.r[x][y].nroom]);
levl[fromx][fromy].doormask = D_NODOOR; levl[fromx][fromy].doormask = D_NODOOR;
fromx++; fromx++;
} }
if (x >= 2) { if (x >= 2) {
impossible("right door from %d,%d going nowhere?", x, y); impossible("right door from %d,%d going nowhere?", x, y);
return; return;
} }
// Move to the next column
x++; x++;
// Disable the left door in the next room
gr.r[x][y].doortable &= ~XL_LEFT; gr.r[x][y].doortable &= ~XL_LEFT;
if (!gr.r[x][y].real) { if (!gr.r[x][y].real) {
// If the next room is not a real room, calculate the ending coordinates for the virtual room
tox = gr.r[x][y].rlx; tox = gr.r[x][y].rlx;
toy = gr.r[x][y].rly; toy = gr.r[x][y].rly;
tox += 1 + 26 * x; tox += 1 + 26 * x;
toy += 7 * y; toy += 7 * y;
} else { } else {
// If the next room is a real room, calculate the ending coordinates based on the room size and position
tox = gr.r[x][y].rlx - 1; tox = gr.r[x][y].rlx - 1;
toy = gr.r[x][y].rly + rn2(gr.r[x][y].dy); toy = gr.r[x][y].rly + rn2(gr.r[x][y].dy);
tox += 1 + 26 * x; tox += 1 + 26 * x;
toy += 7 * y; toy += 7 * y;
// Check if there is a wall at the ending coordinates. If not, output an error message.
if (!IS_WALL(levl[tox][toy].typ)) if (!IS_WALL(levl[tox][toy].typ))
impossible("left: no wall at %d,%d?", tox, toy); impossible("left: no wall at %d,%d?", tox, toy);
// Create a door at the ending coordinates and mark it as no door
dodoor(tox, toy, &gr.rooms[gr.r[x][y].nroom]); dodoor(tox, toy, &gr.rooms[gr.r[x][y].nroom]);
levl[tox][toy].doormask = D_NODOOR; levl[tox][toy].doormask = D_NODOOR;
tox--; tox--;
} }
// Call the `roguejoin` function to create a corridor connecting the starting and ending coordinates
roguejoin(fromx, fromy, tox, toy, TRUE); roguejoin(fromx, fromy, tox, toy, TRUE);
return; return;
} else } else {
impossible("corridor in direction %d?", dir); impossible("corridor in direction %d?", dir);
} }
@ -287,9 +342,9 @@ corr(coordxy x, coordxy y)
} }
} }
void void makerogueghost(void)
makerogueghost(void)
{ {
// Declare variables
register struct monst *ghost; register struct monst *ghost;
struct obj *ghostobj; struct obj *ghostobj;
struct mkroom *croom; struct mkroom *croom;
@ -297,14 +352,23 @@ makerogueghost(void)
if (!gn.nroom) if (!gn.nroom)
return; /* Should never happen */ return; /* Should never happen */
// Select a random room
croom = &gr.rooms[rn2(gn.nroom)]; croom = &gr.rooms[rn2(gn.nroom)];
// Select a random coordinate within the room
x = somex(croom); x = somex(croom);
y = somey(croom); y = somey(croom);
// Create a ghost monster at the selected coordinates
if (!(ghost = makemon(&mons[PM_GHOST], x, y, NO_MM_FLAGS))) if (!(ghost = makemon(&mons[PM_GHOST], x, y, NO_MM_FLAGS)))
return; return;
// Make the ghost sleep and give it a name
ghost->msleeping = 1; ghost->msleeping = 1;
ghost = christen_monst(ghost, roguename()); ghost = christen_monst(ghost, roguename());
// Randomly create and place different items near the ghost
if (rn2(4)) { if (rn2(4)) {
ghostobj = mksobj_at(FOOD_RATION, x, y, FALSE, FALSE); ghostobj = mksobj_at(FOOD_RATION, x, y, FALSE, FALSE);
ghostobj->quan = (long) rnd(7); ghostobj->quan = (long) rnd(7);
@ -354,4 +418,5 @@ makerogueghost(void)
} }
} }
/*extralev.c*/ /*extralev.c*/

@ -0,0 +1 @@
i miss you
Loading…
Cancel
Save