Split scroll effects into separate functions

This commit is contained in:
Pasi Kallinen
2021-07-07 12:02:59 +03:00
parent ee13fb36ac
commit 4b54f4f18a
+468 -205
View File
@@ -24,6 +24,31 @@ static int maybe_tame(struct monst *, struct obj *);
static boolean get_valid_stinking_cloud_pos(int, int); static boolean get_valid_stinking_cloud_pos(int, int);
static boolean is_valid_stinking_cloud_pos(int, int, boolean); static boolean is_valid_stinking_cloud_pos(int, int, boolean);
static void display_stinking_cloud_positions(int); static void display_stinking_cloud_positions(int);
static void seffect_enchant_armor(struct obj **);
static void seffect_destroy_armor(struct obj **);
static void seffect_confuse_monster(struct obj **);
static void seffect_scare_monster(struct obj **);
static void seffect_remove_curse(struct obj **);
static void seffect_create_monster(struct obj **);
static void seffect_enchant_weapon(struct obj **);
static void seffect_taming(struct obj **);
static void seffect_genocide(struct obj **);
static void seffect_light(struct obj **);
static void seffect_charging(struct obj **);
static void seffect_amnesia(struct obj **);
static void seffect_fire(struct obj **);
static void seffect_earth(struct obj **);
static void seffect_punishment(struct obj **);
static void seffect_stinking_cloud(struct obj **);
static void seffect_blank_paper(struct obj **);
static void seffect_teleportation(struct obj **);
static void seffect_gold_detection(struct obj **);
static void seffect_food_detection(struct obj **);
static void seffect_identify(struct obj **);
static void seffect_magic_mapping(struct obj **);
#ifdef MAIL_STRUCTURES
static void seffect_mail(struct obj **);
#endif /* MAIL_STRUCTURES */
static void set_lit(int, int, genericptr); static void set_lit(int, int, genericptr);
static void do_class_genocide(void); static void do_class_genocide(void);
static boolean create_particular_parse(char *, static boolean create_particular_parse(char *,
@@ -932,70 +957,27 @@ display_stinking_cloud_positions(int state)
} }
} }
/* scroll effects; return 1 if we use up the scroll and possibly make it static void
become discovered, 0 if caller should take care of those side-effects */ seffect_enchant_armor(struct obj **sobjp)
int
seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
{ {
int cval, otyp = sobj->otyp; struct obj *sobj = *sobjp;
boolean confused = (Confusion != 0), sblessed = sobj->blessed,
scursed = sobj->cursed, already_known, old_erodeproof,
new_erodeproof;
struct obj *otmp;
if (objects[otyp].oc_magic)
exercise(A_WIS, TRUE); /* just for trying */
already_known = (sobj->oclass == SPBOOK_CLASS /* spell */
|| objects[otyp].oc_name_known);
switch (otyp) {
#ifdef MAIL_STRUCTURES
case SCR_MAIL: {
boolean odd = (sobj->o_id % 2) == 1;
g.known = TRUE;
switch (sobj->spe) {
case 2:
/* "stamped scroll" created via magic marker--without a stamp */
pline("This scroll is marked \"%s\".",
odd ? "Postage Due" : "Return to Sender");
break;
case 1:
/* scroll of mail obtained from bones file or from wishing;
note to the puzzled: the game Larn actually sends you junk
mail if you win! */
pline("This seems to be %s.",
odd ? "a chain letter threatening your luck"
: "junk mail addressed to the finder of the Eye of Larn");
break;
default:
#ifdef MAIL
readmail(sobj);
#else
/* unreachable since with MAIL undefined, sobj->spe won't be 0;
as a precaution, be prepared to give arbitrary feedback;
caller has already reported that it disappears upon reading */
pline("That was a scroll of mail?");
#endif
break;
}
break;
}
#endif
case SCR_ENCHANT_ARMOR: {
register schar s; register schar s;
boolean special_armor; boolean special_armor;
boolean same_color; boolean same_color;
struct obj *otmp = some_armor(&g.youmonst);
boolean sblessed = sobj->blessed;
boolean scursed = sobj->cursed;
boolean confused = (Confusion != 0);
boolean old_erodeproof, new_erodeproof;
otmp = some_armor(&g.youmonst);
if (!otmp) { if (!otmp) {
strange_feeling(sobj, !Blind strange_feeling(sobj, !Blind
? "Your skin glows then fades." ? "Your skin glows then fades."
: "Your skin feels warm for a moment."); : "Your skin feels warm for a moment.");
sobj = 0; /* useup() in strange_feeling() */ *sobjp = 0; /* useup() in strange_feeling() */
exercise(A_CON, !scursed); exercise(A_CON, !scursed);
exercise(A_STR, !scursed); exercise(A_STR, !scursed);
break; return;
} }
if (confused) { if (confused) {
old_erodeproof = (otmp->oerodeproof != 0); old_erodeproof = (otmp->oerodeproof != 0);
@@ -1023,7 +1005,7 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
costly_alteration(otmp, COST_DEGRD); costly_alteration(otmp, COST_DEGRD);
} }
otmp->oerodeproof = new_erodeproof ? 1 : 0; otmp->oerodeproof = new_erodeproof ? 1 : 0;
break; return;
} }
/* elven armor vibrates warningly when enchanted beyond a limit */ /* elven armor vibrates warningly when enchanted beyond a limit */
special_armor = is_elven_armor(otmp) special_armor = is_elven_armor(otmp)
@@ -1050,7 +1032,7 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
otense(otmp, "evaporate")); otense(otmp, "evaporate"));
remove_worn_item(otmp, FALSE); remove_worn_item(otmp, FALSE);
useup(otmp); useup(otmp);
break; return;
} }
s = scursed ? -1 s = scursed ? -1
: (otmp->spe >= 9) : (otmp->spe >= 9)
@@ -1075,7 +1057,7 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
setworn(otmp, W_ARM); setworn(otmp, W_ARM);
if (otmp->unpaid) if (otmp->unpaid)
alter_cost(otmp, 0L); /* shop bill */ alter_cost(otmp, 0L); /* shop bill */
break; return;
} }
pline("%s %s%s%s%s for a %s.", Yname2(otmp), pline("%s %s%s%s%s for a %s.", Yname2(otmp),
(s == 0) ? "violently " : "", (s == 0) ? "violently " : "",
@@ -1114,17 +1096,24 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
&& (special_armor || !rn2(7))) && (special_armor || !rn2(7)))
pline("%s %s.", Yobjnam2(otmp, "suddenly vibrate"), pline("%s %s.", Yobjnam2(otmp, "suddenly vibrate"),
Blind ? "again" : "unexpectedly"); Blind ? "again" : "unexpectedly");
break;
} }
case SCR_DESTROY_ARMOR: {
otmp = some_armor(&g.youmonst); static void
seffect_destroy_armor(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
struct obj *otmp = some_armor(&g.youmonst);
boolean scursed = sobj->cursed;
boolean confused = (Confusion != 0);
boolean old_erodeproof, new_erodeproof;
if (confused) { if (confused) {
if (!otmp) { if (!otmp) {
strange_feeling(sobj, "Your bones itch."); strange_feeling(sobj, "Your bones itch.");
sobj = 0; /* useup() in strange_feeling() */ *sobjp = 0; /* useup() in strange_feeling() */
exercise(A_STR, FALSE); exercise(A_STR, FALSE);
exercise(A_CON, FALSE); exercise(A_CON, FALSE);
break; return;
} }
old_erodeproof = (otmp->oerodeproof != 0); old_erodeproof = (otmp->oerodeproof != 0);
new_erodeproof = scursed; new_erodeproof = scursed;
@@ -1136,15 +1125,15 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
costly_alteration(otmp, COST_DEGRD); costly_alteration(otmp, COST_DEGRD);
} }
otmp->oerodeproof = new_erodeproof ? 1 : 0; otmp->oerodeproof = new_erodeproof ? 1 : 0;
break; return;
} }
if (!scursed || !otmp || !otmp->cursed) { if (!scursed || !otmp || !otmp->cursed) {
if (!destroy_arm(otmp)) { if (!destroy_arm(otmp)) {
strange_feeling(sobj, "Your skin itches."); strange_feeling(sobj, "Your skin itches.");
sobj = 0; /* useup() in strange_feeling() */ *sobjp = 0; /* useup() in strange_feeling() */
exercise(A_STR, FALSE); exercise(A_STR, FALSE);
exercise(A_CON, FALSE); exercise(A_CON, FALSE);
break; return;
} else } else
g.known = TRUE; g.known = TRUE;
} else { /* armor and scroll both cursed */ } else { /* armor and scroll both cursed */
@@ -1155,9 +1144,16 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
} }
make_stunned((HStun & TIMEOUT) + (long) rn1(10, 10), TRUE); make_stunned((HStun & TIMEOUT) + (long) rn1(10, 10), TRUE);
} }
} break; }
case SCR_CONFUSE_MONSTER:
case SPE_CONFUSE_MONSTER: static void
seffect_confuse_monster(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
boolean sblessed = sobj->blessed;
boolean scursed = sobj->cursed;
boolean confused = (Confusion != 0);
if (g.youmonst.data->mlet != S_HUMAN || scursed) { if (g.youmonst.data->mlet != S_HUMAN || scursed) {
if (!HConfusion) if (!HConfusion)
You_feel("confused."); You_feel("confused.");
@@ -1196,9 +1192,15 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
u.umconf += rn1(8, 2); u.umconf += rn1(8, 2);
} }
} }
break; }
case SCR_SCARE_MONSTER:
case SPE_CAUSE_FEAR: { static void
seffect_scare_monster(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
int otyp = sobj->otyp;
boolean scursed = sobj->cursed;
boolean confused = (Confusion != 0);
register int ct = 0; register int ct = 0;
register struct monst *mtmp; register struct monst *mtmp;
@@ -1219,17 +1221,16 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
You_hear("%s %s.", (confused || scursed) ? "sad wailing" You_hear("%s %s.", (confused || scursed) ? "sad wailing"
: "maniacal laughter", : "maniacal laughter",
!ct ? "in the distance" : "close by"); !ct ? "in the distance" : "close by");
break;
} }
case SCR_BLANK_PAPER:
if (Blind) static void
You("don't remember there being any magic words on this scroll."); seffect_remove_curse(struct obj **sobjp)
else {
pline("This scroll seems to be blank."); struct obj *sobj = *sobjp;
g.known = TRUE; int otyp = sobj->otyp;
break; boolean sblessed = sobj->blessed;
case SCR_REMOVE_CURSE: boolean scursed = sobj->cursed;
case SPE_REMOVE_CURSE: { boolean confused = (Confusion != 0);
register struct obj *obj; register struct obj *obj;
You_feel(!Hallucination You_feel(!Hallucination
@@ -1331,10 +1332,16 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
pline_The("clasp on your %s vanishes.", body_part(LEG)); pline_The("clasp on your %s vanishes.", body_part(LEG));
} }
update_inventory(); update_inventory();
break;
} }
case SCR_CREATE_MONSTER:
case SPE_CREATE_MONSTER: static void
seffect_create_monster(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
boolean sblessed = sobj->blessed;
boolean scursed = sobj->cursed;
boolean confused = (Confusion != 0);
if (create_critters(1 + ((confused || scursed) ? 12 : 0) if (create_critters(1 + ((confused || scursed) ? 12 : 0)
+ ((sblessed || rn2(73)) ? 0 : rnd(4)), + ((sblessed || rn2(73)) ? 0 : rnd(4)),
confused ? &mons[PM_ACID_BLOB] confused ? &mons[PM_ACID_BLOB]
@@ -1344,8 +1351,17 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
/* no need to flush monsters; we ask for identification only if the /* no need to flush monsters; we ask for identification only if the
* monsters are not visible * monsters are not visible
*/ */
break; }
case SCR_ENCHANT_WEAPON:
static void
seffect_enchant_weapon(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
boolean sblessed = sobj->blessed;
boolean scursed = sobj->cursed;
boolean confused = (Confusion != 0);
boolean old_erodeproof, new_erodeproof;
/* [What about twoweapon mode? Proofing/repairing/enchanting both /* [What about twoweapon mode? Proofing/repairing/enchanting both
would be too powerful, but shouldn't we choose randomly between would be too powerful, but shouldn't we choose randomly between
primary and secondary instead of always acting on primary?] */ primary and secondary instead of always acting on primary?] */
@@ -1375,19 +1391,23 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
costly_alteration(uwep, COST_DEGRD); costly_alteration(uwep, COST_DEGRD);
} }
uwep->oerodeproof = new_erodeproof ? 1 : 0; uwep->oerodeproof = new_erodeproof ? 1 : 0;
break; return;
} }
if (!chwepon(sobj, scursed ? -1 if (!chwepon(sobj, scursed ? -1
: !uwep ? 1 : !uwep ? 1
: (uwep->spe >= 9) ? !rn2(uwep->spe) : (uwep->spe >= 9) ? !rn2(uwep->spe)
: sblessed ? rnd(3 - uwep->spe / 3) : sblessed ? rnd(3 - uwep->spe / 3)
: 1)) : 1))
sobj = 0; /* nothing enchanted: strange_feeling -> useup */ *sobjp = 0; /* nothing enchanted: strange_feeling -> useup */
if (uwep) if (uwep)
cap_spe(uwep); cap_spe(uwep);
break; }
case SCR_TAMING:
case SPE_CHARM_MONSTER: { static void
seffect_taming(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
boolean confused = (Confusion != 0);
int candidates, res, results, vis_results; int candidates, res, results, vis_results;
if (u.uswallow) { if (u.uswallow) {
@@ -1424,9 +1444,18 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
if (vis_results > 0) if (vis_results > 0)
g.known = TRUE; g.known = TRUE;
} }
break;
} }
case SCR_GENOCIDE:
static void
seffect_genocide(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
int otyp = sobj->otyp;
boolean sblessed = sobj->blessed;
boolean scursed = sobj->cursed;
boolean already_known = (sobj->oclass == SPBOOK_CLASS /* spell */
|| objects[otyp].oc_name_known);
if (!already_known) if (!already_known)
You("have found a scroll of genocide!"); You("have found a scroll of genocide!");
g.known = TRUE; g.known = TRUE;
@@ -1434,8 +1463,16 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
do_class_genocide(); do_class_genocide();
else else
do_genocide((!scursed) | (2 * !!Confusion)); do_genocide((!scursed) | (2 * !!Confusion));
break; }
case SCR_LIGHT:
static void
seffect_light(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
boolean sblessed = sobj->blessed;
boolean scursed = sobj->cursed;
boolean confused = (Confusion != 0);
if (!confused) { if (!confused) {
if (!Blind) if (!Blind)
g.known = TRUE; g.known = TRUE;
@@ -1471,64 +1508,20 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
} }
} }
} }
break;
case SCR_TELEPORTATION:
if (confused || scursed) {
level_tele();
/* gives "materialize on different/same level!" message, must
be a teleport scroll */
g.known = TRUE;
} else {
scrolltele(sobj);
/* this will call learnscroll() as appropriate, and has results
which maybe shouldn't result in the scroll becoming known;
either way, no need to set g.known here */
} }
break;
case SCR_GOLD_DETECTION: static void
if ((confused || scursed) ? trap_detect(sobj) : gold_detect(sobj)) seffect_charging(struct obj **sobjp)
sobj = 0; /* failure: strange_feeling() -> useup() */ {
break; struct obj *sobj = *sobjp;
case SCR_FOOD_DETECTION: int otyp = sobj->otyp;
case SPE_DETECT_FOOD: boolean sblessed = sobj->blessed;
if (food_detect(sobj)) boolean scursed = sobj->cursed;
sobj = 0; /* nothing detected: strange_feeling -> useup */ boolean confused = (Confusion != 0);
break; boolean already_known = (sobj->oclass == SPBOOK_CLASS /* spell */
case SCR_IDENTIFY: || objects[otyp].oc_name_known);
/* known = TRUE; -- handled inline here */ struct obj *otmp;
/* use up the scroll first, before learnscrolltyp() -> makeknown()
performs perm_invent update; also simplifies empty invent check */
useup(sobj);
sobj = 0; /* it's gone */
/* scroll just identifies itself for any scroll read while confused
or for cursed scroll read without knowing identify yet */
if (confused || (scursed && !already_known))
You("identify this as an identify scroll.");
else if (!already_known)
pline("This is an identify scroll.");
if (!already_known)
(void) learnscrolltyp(SCR_IDENTIFY);
if (confused || (scursed && !already_known))
break;
/*FALLTHRU*/
case SPE_IDENTIFY:
if (g.invent) {
cval = 1;
if (sblessed || (!scursed && !rn2(5))) {
cval = rn2(5);
/* note: if cval==0, identify all items */
if (cval == 1 && sblessed && Luck > 0)
++cval;
}
identify_pack(cval, !already_known);
} else {
/* spell cast with inventory empty or scroll read when it's
the only item leaving empty inventory after being used up */
pline("You're not carrying anything%s to be identified.",
(otyp == SCR_IDENTIFY) ? " else" : "");
}
break;
case SCR_CHARGING:
if (confused) { if (confused) {
if (scursed) { if (scursed) {
You_feel("discharged."); You_feel("discharged.");
@@ -1542,7 +1535,7 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
u.uen = u.uenmax; /* otherwise restore current to max */ u.uen = u.uenmax; /* otherwise restore current to max */
} }
g.context.botl = 1; g.context.botl = 1;
break; return;
} }
/* known = TRUE; -- handled inline here */ /* known = TRUE; -- handled inline here */
if (!already_known) { if (!already_known) {
@@ -1553,50 +1546,18 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
getobj picklist because the "disappears" message getobj picklist because the "disappears" message
was already delivered */ was already delivered */
useup(sobj); useup(sobj);
sobj = 0; /* it's gone */ sobjp = 0; /* it's gone */
otmp = getobj("charge", charge_ok, GETOBJ_PROMPT | GETOBJ_ALLOWCNT); otmp = getobj("charge", charge_ok, GETOBJ_PROMPT | GETOBJ_ALLOWCNT);
if (otmp) if (otmp)
recharge(otmp, scursed ? -1 : sblessed ? 1 : 0); recharge(otmp, scursed ? -1 : sblessed ? 1 : 0);
break;
case SCR_MAGIC_MAPPING:
if (g.level.flags.nommap) {
Your("mind is filled with crazy lines!");
if (Hallucination)
pline("Wow! Modern art.");
else
Your("%s spins in bewilderment.", body_part(HEAD));
make_confused(HConfusion + rnd(30), FALSE);
break;
} }
if (sblessed) {
register int x, y;
for (x = 1; x < COLNO; x++) static void
for (y = 0; y < ROWNO; y++) seffect_amnesia(struct obj **sobjp)
if (levl[x][y].typ == SDOOR) {
cvt_sdoor_to_door(&levl[x][y]); struct obj *sobj = *sobjp;
/* do_mapping() already reveals secret passages */ boolean sblessed = sobj->blessed;
}
g.known = TRUE;
/*FALLTHRU*/
case SPE_MAGIC_MAPPING:
if (g.level.flags.nommap) {
Your("%s spins as %s blocks the spell!", body_part(HEAD),
something);
make_confused(HConfusion + rnd(30), FALSE);
break;
}
pline("A map coalesces in your mind!");
cval = (scursed && !confused);
if (cval)
HConfusion = 1; /* to screw up map */
do_mapping();
if (cval) {
HConfusion = 0; /* restore */
pline("Unfortunately, you can't grasp the details.");
}
break;
case SCR_AMNESIA:
g.known = TRUE; g.known = TRUE;
forget((!sblessed ? ALL_SPELLS : 0)); forget((!sblessed ? ALL_SPELLS : 0));
if (Hallucination) /* Ommmmmm! */ if (Hallucination) /* Ommmmmm! */
@@ -1609,17 +1570,26 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
else else
pline("Thinking of Maud you forget everything else."); pline("Thinking of Maud you forget everything else.");
exercise(A_WIS, FALSE); exercise(A_WIS, FALSE);
break; }
case SCR_FIRE: {
static void
seffect_fire(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
int otyp = sobj->otyp;
boolean sblessed = sobj->blessed;
boolean confused = (Confusion != 0);
boolean already_known = (sobj->oclass == SPBOOK_CLASS /* spell */
|| objects[otyp].oc_name_known);
coord cc; coord cc;
int dam; int dam, cval;
cc.x = u.ux; cc.x = u.ux;
cc.y = u.uy; cc.y = u.uy;
cval = bcsign(sobj); cval = bcsign(sobj);
dam = (2 * (rn1(3, 3) + 2 * cval) + 1) / 3; dam = (2 * (rn1(3, 3) + 2 * cval) + 1) / 3;
useup(sobj); useup(sobj);
sobj = 0; /* it's gone */ sobjp = 0; /* it's gone */
if (!already_known) if (!already_known)
(void) learnscrolltyp(SCR_FIRE); (void) learnscrolltyp(SCR_FIRE);
if (confused) { if (confused) {
@@ -1640,7 +1610,7 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
makeplural(body_part(HAND))); makeplural(body_part(HAND)));
losehp(1, "scroll of fire", KILLED_BY_AN); losehp(1, "scroll of fire", KILLED_BY_AN);
} }
break; return;
} }
if (Underwater) { if (Underwater) {
pline_The("%s around you vaporizes violently!", hliquid("water")); pline_The("%s around you vaporizes violently!", hliquid("water"));
@@ -1666,9 +1636,16 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
} }
} }
explode(cc.x, cc.y, 11, dam, SCROLL_CLASS, EXPL_FIERY); explode(cc.x, cc.y, 11, dam, SCROLL_CLASS, EXPL_FIERY);
break;
} }
case SCR_EARTH:
static void
seffect_earth(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
boolean sblessed = sobj->blessed;
boolean scursed = sobj->cursed;
boolean confused = (Confusion != 0);
/* TODO: handle steeds */ /* TODO: handle steeds */
if (!Is_rogue_level(&u.uz) && has_ceiling(&u.uz) if (!Is_rogue_level(&u.uz) && has_ceiling(&u.uz)
&& (!In_endgame(&u.uz) || Is_earthlevel(&u.uz))) { && (!In_endgame(&u.uz) || Is_earthlevel(&u.uz))) {
@@ -1704,16 +1681,30 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
} else if (!nboulders) } else if (!nboulders)
pline("But nothing else happens."); pline("But nothing else happens.");
} }
break; }
case SCR_PUNISHMENT:
static void
seffect_punishment(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
boolean sblessed = sobj->blessed;
boolean confused = (Confusion != 0);
g.known = TRUE; g.known = TRUE;
if (confused || sblessed) { if (confused || sblessed) {
You_feel("guilty."); You_feel("guilty.");
break; return;
} }
punish(sobj); punish(sobj);
break; }
case SCR_STINKING_CLOUD: {
static void
seffect_stinking_cloud(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
int otyp = sobj->otyp;
boolean already_known = (sobj->oclass == SPBOOK_CLASS /* spell */
|| objects[otyp].oc_name_known);
coord cc; coord cc;
if (!already_known) if (!already_known)
@@ -1727,14 +1718,286 @@ seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
get_valid_stinking_cloud_pos); get_valid_stinking_cloud_pos);
if (getpos(&cc, TRUE, "the desired position") < 0) { if (getpos(&cc, TRUE, "the desired position") < 0) {
pline1(Never_mind); pline1(Never_mind);
break; return;
} }
if (!is_valid_stinking_cloud_pos(cc.x, cc.y, TRUE)) if (!is_valid_stinking_cloud_pos(cc.x, cc.y, TRUE))
break; return;
(void) create_gas_cloud(cc.x, cc.y, 3 + bcsign(sobj), (void) create_gas_cloud(cc.x, cc.y, 3 + bcsign(sobj),
8 + 4 * bcsign(sobj)); 8 + 4 * bcsign(sobj));
}
static void
seffect_blank_paper(struct obj **sobjp UNUSED)
{
if (Blind)
You("don't remember there being any magic words on this scroll.");
else
pline("This scroll seems to be blank.");
g.known = TRUE;
}
static void
seffect_teleportation(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
boolean scursed = sobj->cursed;
boolean confused = (Confusion != 0);
if (confused || scursed) {
level_tele();
/* gives "materialize on different/same level!" message, must
be a teleport scroll */
g.known = TRUE;
} else {
scrolltele(sobj);
/* this will call learnscroll() as appropriate, and has results
which maybe shouldn't result in the scroll becoming known;
either way, no need to set g.known here */
}
}
static void
seffect_gold_detection(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
boolean scursed = sobj->cursed;
boolean confused = (Confusion != 0);
if ((confused || scursed) ? trap_detect(sobj) : gold_detect(sobj))
sobjp = 0; /* failure: strange_feeling() -> useup() */
}
static void
seffect_food_detection(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
if (food_detect(sobj))
sobjp = 0; /* nothing detected: strange_feeling -> useup */
}
static void
seffect_identify(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
int otyp = sobj->otyp;
boolean is_scroll = (sobj->oclass == SCROLL_CLASS);
boolean sblessed = sobj->blessed;
boolean scursed = sobj->cursed;
boolean confused = (Confusion != 0);
boolean already_known = (sobj->oclass == SPBOOK_CLASS /* spell */
|| objects[otyp].oc_name_known);
if (is_scroll) { /* scroll of identify */
/* known = TRUE; -- handled inline here */
/* use up the scroll first, before learnscrolltyp() -> makeknown()
performs perm_invent update; also simplifies empty invent check */
useup(sobj);
sobjp = 0; /* it's gone */
/* scroll just identifies itself for any scroll read while confused
or for cursed scroll read without knowing identify yet */
if (confused || (scursed && !already_known))
You("identify this as an identify scroll.");
else if (!already_known)
pline("This is an identify scroll.");
if (!already_known)
(void) learnscrolltyp(SCR_IDENTIFY);
if (confused || (scursed && !already_known))
return;
}
if (g.invent) {
int cval = 1;
if (sblessed || (!scursed && !rn2(5))) {
cval = rn2(5);
/* note: if cval==0, identify all items */
if (cval == 1 && sblessed && Luck > 0)
++cval;
}
identify_pack(cval, !already_known);
} else {
/* spell cast with inventory empty or scroll read when it's
the only item leaving empty inventory after being used up */
pline("You're not carrying anything%s to be identified.",
(is_scroll) ? " else" : "");
}
}
static void
seffect_magic_mapping(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
boolean is_scroll = (sobj->oclass == SCROLL_CLASS);
boolean sblessed = sobj->blessed;
boolean scursed = sobj->cursed;
boolean confused = (Confusion != 0);
int cval;
if (is_scroll) {
if (g.level.flags.nommap) {
Your("mind is filled with crazy lines!");
if (Hallucination)
pline("Wow! Modern art.");
else
Your("%s spins in bewilderment.", body_part(HEAD));
make_confused(HConfusion + rnd(30), FALSE);
return;
}
if (sblessed) {
register int x, y;
for (x = 1; x < COLNO; x++)
for (y = 0; y < ROWNO; y++)
if (levl[x][y].typ == SDOOR)
cvt_sdoor_to_door(&levl[x][y]);
/* do_mapping() already reveals secret passages */
}
g.known = TRUE;
}
if (g.level.flags.nommap) {
Your("%s spins as %s blocks the spell!", body_part(HEAD),
something);
make_confused(HConfusion + rnd(30), FALSE);
return;
}
pline("A map coalesces in your mind!");
cval = (scursed && !confused);
if (cval)
HConfusion = 1; /* to screw up map */
do_mapping();
if (cval) {
HConfusion = 0; /* restore */
pline("Unfortunately, you can't grasp the details.");
}
}
#ifdef MAIL_STRUCTURES
static void
seffect_mail(struct obj **sobjp)
{
struct obj *sobj = *sobjp;
boolean odd = (sobj->o_id % 2) == 1;
g.known = TRUE;
switch (sobj->spe) {
case 2:
/* "stamped scroll" created via magic marker--without a stamp */
pline("This scroll is marked \"%s\".",
odd ? "Postage Due" : "Return to Sender");
break;
case 1:
/* scroll of mail obtained from bones file or from wishing;
note to the puzzled: the game Larn actually sends you junk
mail if you win! */
pline("This seems to be %s.",
odd ? "a chain letter threatening your luck"
: "junk mail addressed to the finder of the Eye of Larn");
break;
default:
#ifdef MAIL
readmail(sobj);
#else
/* unreachable since with MAIL undefined, sobj->spe won't be 0;
as a precaution, be prepared to give arbitrary feedback;
caller has already reported that it disappears upon reading */
pline("That was a scroll of mail?");
#endif
break; break;
} }
}
#endif /* MAIL_STRUCTURES */
/* scroll effects; return 1 if we use up the scroll and possibly make it
become discovered, 0 if caller should take care of those side-effects */
int
seffects(struct obj *sobj) /* sobj - scroll or fake spellbook for spell */
{
int otyp = sobj->otyp;
if (objects[otyp].oc_magic)
exercise(A_WIS, TRUE); /* just for trying */
switch (otyp) {
#ifdef MAIL_STRUCTURES
case SCR_MAIL:
seffect_mail(&sobj);
break;
#endif
case SCR_ENCHANT_ARMOR:
seffect_enchant_armor(&sobj);
break;
case SCR_DESTROY_ARMOR:
seffect_destroy_armor(&sobj);
break;
case SCR_CONFUSE_MONSTER:
case SPE_CONFUSE_MONSTER:
seffect_confuse_monster(&sobj);
break;
case SCR_SCARE_MONSTER:
case SPE_CAUSE_FEAR:
seffect_scare_monster(&sobj);
break;
case SCR_BLANK_PAPER:
seffect_blank_paper(&sobj);
break;
case SCR_REMOVE_CURSE:
case SPE_REMOVE_CURSE:
seffect_remove_curse(&sobj);
break;
case SCR_CREATE_MONSTER:
case SPE_CREATE_MONSTER:
seffect_create_monster(&sobj);
break;
case SCR_ENCHANT_WEAPON:
seffect_enchant_weapon(&sobj);
break;
case SCR_TAMING:
case SPE_CHARM_MONSTER:
seffect_taming(&sobj);
break;
case SCR_GENOCIDE:
seffect_genocide(&sobj);
break;
case SCR_LIGHT:
seffect_light(&sobj);
break;
case SCR_TELEPORTATION:
seffect_teleportation(&sobj);
break;
case SCR_GOLD_DETECTION:
seffect_gold_detection(&sobj);
break;
case SCR_FOOD_DETECTION:
case SPE_DETECT_FOOD:
seffect_food_detection(&sobj);
break;
case SCR_IDENTIFY:
case SPE_IDENTIFY:
seffect_identify(&sobj);
break;
case SCR_CHARGING:
seffect_charging(&sobj);
break;
case SCR_MAGIC_MAPPING:
case SPE_MAGIC_MAPPING:
seffect_magic_mapping(&sobj);
break;
case SCR_AMNESIA:
seffect_amnesia(&sobj);
break;
case SCR_FIRE:
seffect_fire(&sobj);
break;
case SCR_EARTH:
seffect_earth(&sobj);
break;
case SCR_PUNISHMENT:
seffect_punishment(&sobj);
break;
case SCR_STINKING_CLOUD:
seffect_stinking_cloud(&sobj);
break;
default: default:
impossible("What weird effect is this? (%u)", otyp); impossible("What weird effect is this? (%u)", otyp);
} }