Annotated code for enchanting weapon [SPOILY] [LONG]

G

Guest

Guest
Archived from groups: rec.games.roguelike.nethack (More info?)

The response for my first post of annotated code was all positive so
here is the next one.

ANNOTATED CODE FOR ENCHANT WEAPON

This part of code is in file read.c starting from line 960.

1: case SCR_ENCHANT_WEAPON:

Start of the code for enchant weapon handling.

2: if(uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))
3: && confused) {
4: /* oclass check added 10/25/86 GAN */

If enchant weapon is read while confused the fooproofing is done only if
the character is wielding a weapon(tool). So the check is: if something
is wielded and that something is a weapon(tool) and the character is
confused.

The comment tells us when the check for wielded weapon was made in this
part of the code and who made the contribution.

5: uwep->oerodeproof = !(sobj->cursed);

The weapon is made fooproof if the scroll is non-cursed otherwise the
fooproofing is removed. uwep is the pointer to the wielded weapon(tool)
and sobj is the pointer to the scroll.

6: if (Blind) {
7: uwep->rknown = FALSE;
8: Your("weapon feels warm for a moment.");

If the character is blind then the change is not made known and a
suitable message is shown.

9: } else {
10: uwep->rknown = TRUE;
11: Your("%s covered by a %s %s %s!",
12: aobjnam(uwep, "are"),
13: sobj->cursed ? "mottled" : "shimmering",
14: hcolor(sobj->cursed ? NH_PURPLE : NH_GOLDEN),
15: sobj->cursed ? "glow" : "shield");
16: }

If not blind the change is made known and an appropriate message is
generated. The description is 'mottled purple glow' for unfooproofing
and 'shimmering golden shield' for fooproofing.

17: if (uwep->oerodeproof && (uwep->oeroded || uwep->oeroded2)) {
18: uwep->oeroded = uwep->oeroded2 = 0;
19: Your("%s as good as new!",
20: aobjnam(uwep, Blind ? "feel" : "look"));
21: }

If the weapon was fooproofed and was damaged then all the damge is
removed and an approprite message based on blindness is generated.

aobjnam() is a function that returns a pointer to a string which is
properly assembled phrase with the lower case name of the object and the
right tense of the provided verb. In this case you get strings like:

'Sting feels'
'elven arrows look'

There are other functions that produce different strings from the object
names.

22: } else return !chwepon(sobj,
23: sobj->cursed ? -1 :
24: !uwep ? 1 :
25: uwep->spe >= 9 ? (rn2(uwep->spe) == 0) :
26: sobj->blessed ? rnd(3-uwep->spe/3) : 1);

The actual change of enchantment of a weapon is made by a separate
function called chwepon(). The function is described below but let's
check what are all those parameters that are passed here. chwepon()
needs to be called with two parameters called otmp and amount. otmp is a
pointer to an object and amount is an integer that holds the change value.

Here the object is the scroll and

if the scroll is cursed the amount is -1 or
if no weapon is wielded the amount is 1 or
if the current enchantment of the wielded weapon is higher than +8 the
amount is 0 or 1 and propability for 1 is 1 in the current enchantment
(rn2(uwep->spe) returns a value from 0..current enchantment-1 and if
this is 0 then the amount is 1) or
if the scroll is non-cursed the amount is 1 or
if the scroll is blessed the amount is random.

rnd(x) returns a random number in the range 1..x

Here the range is calculated by 3 - current enchantment/3, so for
blessed scrolls the ranges are:

Current enchantment Range
+8 - +6 1
+5 - +3 2
+2 - -2 3
-3 - -5 4
etc.

27: break;

This ends the case of enchant weapon scroll.

This part of code is in file wield.c starting from line 686.

1: int
2: chwepon(otmp, amount)

Here is the function chwepon() and it starts with a function header that
tells the return value (here integer) and the parameters. The return
value tells if the otmp is used up by the function 0=yes, non-zero=no.

3: register struct obj *otmp;
4: register int amount;

The parameters have to be defined so here is the definiftions. otmp is
pointer to an object structure and amount is an integer. Remember that
the call of the function from the enchant weapon handling set the object
pointer to point to the scroll not the weapon.

5: {

This starts the function body.

6: const char *color = hcolor((amount < 0) ? NH_BLACK : NH_BLUE);
7: const char *xtime;
8: int otyp = STRANGE_OBJECT;

Three additional variables are declared:
color is a pointer to a string NH_BLACK if the amount is negative
otherwise NH_BLUE,
xtime is a pointer to a string that is later used to point to right
duration word and
otyp is an integer that is initialized for the id of non-existing type.

9: if(!uwep || (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep))) {

If nothing is wielded or the wielded object is not a weapon(tool)

10: char buf[BUFSZ];

A buffer to hold the string to add to the message.

11: Sprintf(buf, "Your %s %s.", makeplural(body_part(HAND)),
12: (amount >= 0) ? "twitch" : "itch");

In the buffer is composed a string which has the correct name for
whatever goes as the characters hands in her current form and the verb
selected by the amount. So cursed scroll makes your hands itch
non-cursed twitch.

makeplural(body_part(HAND)) is nice construction:

makeplural() is a function that pluralizes the noun given.
body_part() is a function that gives the right name for a (polymorphed)
characters bodypart given the identifier of that bodypart.

13: strange_feeling(otmp, buf);

strange_feeling() is a function that either prints the given text or
just a strange feeling text based on the characters experience. It also
let's you give the object a name if the object is unidentified and
unnamed. Lastly it removes the object from the memory with all
references to it and frees the memory.

14: exercise(A_DEX, (boolean) (amount >= 0));

This excercises dexterity positively if the amount is non-negative
negatively otherwise.

15: return(0);

The function returns with return value of 0.

16: }

End of no weapon(tool) wielded. From this point on we know that uwep
points to a wielded weapon(tool).

17: if (otmp && otmp->oclass == SCROLL_CLASS) otyp = otmp->otyp;

If otmp point to an object and the object's class is scroll then the
variable otyp is made to hold the value of the object's type.

18: if(uwep->otyp == WORM_TOOTH && amount >= 0) {
19: uwep->otyp = CRYSKNIFE;

If the wielded weapon is worm tooth and the amount is non-negative then
the tooth is changed to a cryssknife.

20: uwep->oerodeproof = 0;

The knife unfooproofed.

21: Your("weapon seems sharper now.");

A message is printed.

22: uwep->cursed = 0;

The knife is made non-cursed.

23: if (otyp != STRANGE_OBJECT) makeknown(otyp);

If the otmp was scroll make the scroll identified.

24: return(1);

The function returns 1 if wormtooth was converted.

25: }

End of worm tooth handling.

26: if(uwep->otyp == CRYSKNIFE && amount < 0) {
27: uwep->otyp = WORM_TOOTH;

If crysknife is wielded and the amount is negative then a cryssknife is
changed into a worm tooth.

28: uwep->oerodeproof = 0;

The tooth is unfooproofed.

29: Your("weapon seems duller now.");

The message is shown.

30: if (otyp != STRANGE_OBJECT && otmp->bknown) makeknown(otyp);

If the otmp was scroll and buc-identified make the scroll identified.

31: return(1);

The function returns 1 if crysknife was converted.

32: }

End of crysknife handling.

33: if (amount < 0 && uwep->oartifact && restrict_name(uwep,
ONAME(uwep))) {
34: if (!Blind)
35: Your("%s %s.", aobjnam(uwep, "faintly glow"), color);
36: return(1);
37: }

Artifacts don't care about negative amount so print a message if not
blind and return with 1.

38: /* there is a (soft) upper and lower limit to uwep->spe */
39: if(((uwep->spe > 5 && amount >= 0) ||
(uwep->spe < -5 && amount < 0))
40: && rn2(3)) {

If the current enchantment is higher than five and amount is
non-negative or lower than -5 and amount is negative there is 2 in 3
chance that the weapon(tool) evaporates.

41: if (!Blind)
42: Your("%s %s for a while and then %s.",
43: aobjnam(uwep, "violently glow"), color,
44: otense(uwep, "evaporate"));

Message for a non-blind character.

45: else
46: Your("%s.", aobjnam(uwep, "evaporate"));
47:

And one for a blind.

48: useupall(uwep); /* let all of them disappear */

This removes the wielded weapon(s) from existense so that it does not
appear on any internal structures that nethack uses to keep track of the
items and releases all the memory that was used to store the item
information. useupall() function is used as there is a chance that the
object is stacked to remove all of the stack.

49: return(1);

The function returns 1 if the weapon evaporates.

50: }

End of the evaporation case.

From this point starts the actual change of enchantment value of the
wielded weapon(tool).

51: if (!Blind) {

For a non-blind character there is a message and the scroll might get
identified.

52: xtime = (amount*amount == 1) ? "moment" : "while";

If the amount is not 1 or -1 then the glow takes a while instead being
just momentary.

54: Your("%s %s for a %s.",
55: aobjnam(uwep, amount == 0 ? "violently glow" : "glow"),
56: color, xtime);

This prints the message. Violent glowing is used if there is no change
in the enchantment. Remember that this is possible only if the current
enchantment is higher than +8 and in that case we are here only if the
weapon didn't evaporate so the message reflects the evaporation message.

57: if (otyp != STRANGE_OBJECT && uwep->known &&
58: (amount > 0 || (amount < 0 && otmp->bknown)))
59: makeknown(otyp);

The scroll gets identified only if the weapon is identified and the
amount is positive or if the amount is negative and the buc-status of
the scroll is known. Notice this does not happen if character is blind.

60: }

End of non-blinded part. Notice that a blind character gets no message.

61: uwep->spe += amount;

The enchantment level is changed.

62: if(amount > 0) uwep->cursed = 0;

If the amount was postive uncurse the weapon.

63: /*
64: * Enchantment, which normally improves a weapon, has an
65: * addition adverse reaction on Magicbane whose effects are
66: * spe dependent. Give an obscure clue here.
67: */
68: if (uwep->oartifact == ART_MAGICBANE && uwep->spe >= 0) {
69: Your("right %s %sches!",
70: body_part(HAND),
71: (((amount > 1) && (uwep->spe > 1)) ? "flin" : "it"));
72: }

Like the comment says a obscure message is given if Magicbane was
enchanted. If the increase was greater than 1 and the resulting
enchantment is greater than 1 then your right 'hand' flinches otherwise
it itches.

73: /* an elven magic clue, cookie@keebler */
74: /* elven weapons vibrate warningly when enchanted beyond a limit
*/
75: if ((uwep->spe > 5)
76: && (is_elven_weapon(uwep) || uwep->oartifact || !rn2(7)))
77: Your("%s unexpectedly.",
78: aobjnam(uwep, "suddenly vibrate"));

A warning message is printed if the resulting enchantment is higher than
5 and the weapon is elven or artifact. Non-artifact non-elven
weapon(tools) get warned with 1 in 7 propability.

79:
80: return(1);

The function returns 1.

81: }

End of the function.


OK, this is the next installment of the annotated nethack code. If you
want to see some specific parts of the code annotated feel free to make
suggestions.

Topi
--
"The whole problem with the world is that fools and fanatics are
always so certain of themselves, but wiser people so full of doubts."
- Bertrand Russell
"How come he didn't put 'I think' at the end of it?" - Anonymous
 
G

Guest

Guest
Archived from groups: rec.games.roguelike.nethack (More info?)

On Sat, 30 Jul 2005 13:51:48 +0300
Topi Linkala <nes@iki.fi> wrote:

--snipped--

Posted.