From 9c347983ee2f48a7ffdc9e013f2109552f43973e Mon Sep 17 00:00:00 2001
From: Sage <SageBasilMint@gmail.com>
Date: Sun, 22 Dec 2013 15:31:47 +0000
Subject: [PATCH] Make warnings against penance-causing attacks more
 prominent.

The prompt to hit an enslaved creature differs very little regardless of
your god, even if it would cause penance with that god. This patch makes
such attacks require yes_or_no like walking into a Zot trap instead of
yesno, and explicitly states that it will cause penance with your god.
For reference, only betrayal attacks under Okawaru and the good gods,
attacking neutral creatures under Elyvilon or TSO, unchivalric attacks
under TSO, and plant betrayal under Fedhas is affected; attacks with
brands offensive to your god are not, and neither are attacks which
only cause piety loss.
---
 crawl-ref/source/fight.cc        |    3 ++-
 crawl-ref/source/main.cc         |    9 +++++--
 crawl-ref/source/melee_attack.cc |    3 ++-
 crawl-ref/source/misc.cc         |   55 +++++++++++++++++++++++++++++---------
 crawl-ref/source/misc.h          |    1 +
 5 files changed, 54 insertions(+), 17 deletions(-)

diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 6ae368c..34d7a08 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -339,10 +339,11 @@ bool fight_jump(actor *attacker, actor *defender, coord_def attack_pos,
             {
                 const char* verb = "jump-attack";
                 string junk1, junk2;
+                bool junk3;
                 if (defender)
                 {
                     verb = (bad_attack(defender->as_monster(),
-                                       junk1, junk2)
+                                       junk1, junk2, junk3)
                             ? "jump-attack" : "jump-attack near");
                 }
 
diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc
index eb0b297..9f0a8f8 100644
--- a/crawl-ref/source/main.cc
+++ b/crawl-ref/source/main.cc
@@ -4361,6 +4361,7 @@ static void _move_player(coord_def move)
         dungeon_feature_type dangerous = DNGN_FLOOR;
         monster *bad_mons = 0;
         string bad_suff, bad_adj;
+        bool penance = false;
         for (adjacent_iterator ai(you.pos(), false); ai; ++ai)
         {
             if (is_feat_dangerous(grd(*ai)) && !you.can_cling_to(*ai)
@@ -4373,7 +4374,7 @@ static void _move_player(coord_def move)
             {
                 string suffix, adj;
                 monster *mons = monster_at(*ai);
-                if (mons && bad_attack(mons, adj, suffix))
+                if (mons && bad_attack(mons, adj, suffix, penance))
                 {
                     bad_mons = mons;
                     bad_suff = suffix;
@@ -4404,12 +4405,16 @@ static void _move_player(coord_def move)
             }
             prompt += "?";
 
+            if (penance)
+                prompt += " This attack would put you in penance!";
+
             monster* targ = monster_at(you.pos() + move);
             if (targ && !targ->wont_attack() && you.can_see(targ))
                 prompt += " (Use ctrl+direction to attack without moving)";
 
             if (!crawl_state.disables[DIS_CONFIRMATIONS]
-                && !yesno(prompt.c_str(), false, 'n'))
+                && (penance && !yes_or_no("%s", prompt.c_str())
+                    || !penance && !yesno(prompt.c_str(), false, 'n')))
             {
                 canned_msg(MSG_OK);
                 return;
diff --git a/crawl-ref/source/melee_attack.cc b/crawl-ref/source/melee_attack.cc
index c504faf..ce69995 100644
--- a/crawl-ref/source/melee_attack.cc
+++ b/crawl-ref/source/melee_attack.cc
@@ -246,8 +246,9 @@ bool melee_attack::handle_phase_attempted()
             else
             {
                 string junk1, junk2;
+                bool junk3;
                 const char *verb = (bad_attack(defender->as_monster(),
-                                               junk1, junk2)
+                                               junk1, junk2, junk3)
                                     ? "attack" : "attack near");
                 bool (*aff_func)(const coord_def &) = 0;
                 if (damage_brand == SPWPN_ELECTROCUTION)
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 83990dc..dd3c3fb 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -2196,6 +2196,7 @@ int speed_to_duration(int speed)
 }
 
 bool bad_attack(const monster *mon, string& adj, string& suffix,
+                bool& would_cause_penance,
                 coord_def attack_pos, bool check_landing_only)
 {
     ASSERT(!crawl_state.game_is_arena());
@@ -2223,6 +2224,13 @@ bool bad_attack(const monster *mon, string& adj, string& suffix,
     if (check_landing_only)
         return bad_landing;
 
+    if (you_worship(GOD_JIYVA) && mons_is_slime(mon)
+        && !(mon->is_shapeshifter() && (mon->flags & MF_KNOWN_SHIFTER)))
+    {  
+        would_cause_penance = true;
+        return true;
+    }
+
     if (mon->friendly())
     {
         if (you_worship(GOD_OKAWARU))
@@ -2232,9 +2240,15 @@ bool bad_attack(const monster *mon, string& adj, string& suffix,
             monster_info mi(mon, MILEV_NAME);
             if (!mi.is(MB_NAME_UNQUALIFIED))
                 adj += "the ";
+
+            would_cause_penance = true;
         }
         else
+        {
             adj = "your ";
+            if (is_good_god(you.religion) || fedhas_protects(mon))
+                would_cause_penance = true;
+        }
         return true;
     }
 
@@ -2243,17 +2257,22 @@ bool bad_attack(const monster *mon, string& adj, string& suffix,
         && !tso_unchivalric_attack_safe_monster(mon))
     {
         adj += "helpless ";
+        would_cause_penance = true;
     }
+
     if (mon->neutral() && is_good_god(you.religion))
+    {
         adj += "neutral ";
+        if (you_worship(GOD_SHINING_ONE) || you_worship(GOD_ELYVILON))
+            would_cause_penance = true;
+    }
     else if (mon->wont_attack())
-        adj += "non-hostile ";
-
-    if (you_worship(GOD_JIYVA) && mons_is_slime(mon)
-        && !(mon->is_shapeshifter() && (mon->flags & MF_KNOWN_SHIFTER)))
     {
-        return true;
+        adj += "non-hostile ";
+        if (you_worship(GOD_SHINING_ONE) || you_worship(GOD_ELYVILON))
+            would_cause_penance = true;
     }
+
     return !adj.empty() || !suffix.empty();
 }
 
@@ -2262,6 +2281,8 @@ bool stop_attack_prompt(const monster* mon, bool beam_attack,
                         bool *prompted, coord_def attack_pos,
                         bool check_landing_only)
 {
+    bool penance = false;
+
     if (prompted)
         *prompted = false;
 
@@ -2272,7 +2293,7 @@ bool stop_attack_prompt(const monster* mon, bool beam_attack,
         return false;
 
     string adj, suffix;
-    if (!bad_attack(mon, adj, suffix, attack_pos, check_landing_only))
+    if (!bad_attack(mon, adj, suffix, penance, attack_pos, check_landing_only))
         return false;
 
     // Listed in the form: "your rat", "Blork the orc".
@@ -2303,13 +2324,16 @@ bool stop_attack_prompt(const monster* mon, bool beam_attack,
     else
         verb = "attack ";
 
-    snprintf(info, INFO_SIZE, "Really %s%s%s?",
-             verb.c_str(), mon_name.c_str(), suffix.c_str());
+    snprintf(info, INFO_SIZE, "Really %s%s%s?%s",
+             verb.c_str(), mon_name.c_str(), suffix.c_str(), 
+             penance ? " This attack would put you in penance!" : "");
 
     if (prompted)
         *prompted = true;
 
-    if (yesno(info, false, 'n'))
+    if (penance && yes_or_no("%s", info))
+        return false; 
+    else if (!penance && yesno(info, false, 'n'))
         return false;
     else
     {
@@ -2331,6 +2355,7 @@ bool stop_attack_prompt(targetter &hitfunc, const char* verb,
         return false;
 
     string adj, suffix;
+    bool penance = false;
     counted_monster_list victims;
     for (distance_iterator di(hitfunc.origin, false, true, LOS_RADIUS); di; ++di)
     {
@@ -2342,7 +2367,7 @@ bool stop_attack_prompt(targetter &hitfunc, const char* verb,
         if (affects && !affects(mon))
             continue;
         string adjn, suffixn;
-        if (bad_attack(mon, adjn, suffixn))
+        if (bad_attack(mon, adjn, suffixn, penance))
         {
             if (victims.empty()) // record the adjectives for the first listed
                 adj = adjn, suffix = suffixn;
@@ -2361,12 +2386,16 @@ bool stop_attack_prompt(targetter &hitfunc, const char* verb,
         adj = "the " + adj;
     mon_name = adj + mon_name;
 
-    snprintf(info, INFO_SIZE, "Really %s %s%s?",
-             verb, mon_name.c_str(), suffix.c_str());
+    snprintf(info, INFO_SIZE, "Really %s %s%s?%s",
+             verb, mon_name.c_str(), suffix.c_str(),
+             penance ? " This attack would put you in penance!" : "");
 
     if (prompted)
         *prompted = true;
-    if (yesno(info, false, 'n'))
+
+    if (penance && yes_or_no("%s", info))
+        return false; 
+    else if (!penance && yesno(info, false, 'n'))
         return false;
     else
     {
diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h
index 7dc8a40..45a0f6d 100644
--- a/crawl-ref/source/misc.h
+++ b/crawl-ref/source/misc.h
@@ -114,6 +114,7 @@ bool interrupt_cmd_repeat(activity_interrupt_type ai,
                           const activity_interrupt_data &at);
 
 bool bad_attack(const monster *mon, string& adj, string& suffix,
+                bool& would_cause_penance,
                 coord_def attack_pos = coord_def(0, 0),
                 bool check_landing_only = false);
 
-- 
1.7.9.5

