]> granicus.if.org Git - nethack/commitdiff
Unlock your quest by killing your quest leader
authorPasi Kallinen <paxed@alt.org>
Sun, 23 May 2021 05:55:58 +0000 (08:55 +0300)
committerPasi Kallinen <paxed@alt.org>
Sun, 23 May 2021 08:11:58 +0000 (11:11 +0300)
Allow killing your quest leader, just to make games winnable if you
converted before doing the quest.
Boost the quest leaders and give them some equipment. King Arthur
gets Excalibur. Killing quest leader gives really bad luck and
makes your god angry at you, and killing quest guardians gives
smaller penalties.

This is based on both the EvilHack implementation by
k21971 <keith.simpson1971@gmail.com>, and xNetHack
implementation by copperwater <aosdict@gmail.com>.

21 files changed:
dat/Arc-strt.lua
dat/Bar-strt.lua
dat/Cav-strt.lua
dat/Hea-strt.lua
dat/Kni-strt.lua
dat/Mon-strt.lua
dat/Pri-strt.lua
dat/Ran-strt.lua
dat/Rog-strt.lua
dat/Sam-strt.lua
dat/Tou-strt.lua
dat/Val-strt.lua
dat/Wiz-strt.lua
doc/fixes37.0
include/extern.h
include/patchlevel.h
include/quest.h
src/mon.c
src/monst.c
src/quest.c
src/timeout.c

index 5f759b575a01133ac2e2ab0931ecfcd26716793f..4bccd8441578b9f3ff30d316b53933fa8ae1ad01 100644 (file)
@@ -70,7 +70,10 @@ des.door("locked",24,14)
 des.door("closed",31,14)
 des.door("locked",49,14)
 -- Lord Carnarvon
-des.monster("Lord Carnarvon", 25, 10)
+des.monster({ id = "Lord Carnarvon", coord = {25, 10}, inventory = function()
+   des.object({ id = "fedora", spe = 5 });
+   des.object({ id = "bullwhip", spe = 4 });
+end })
 -- The treasure of Lord Carnarvon
 des.object("chest", 25, 10)
 -- student guards for the audience chamber
index 79df053e79896ce61549fb1ae1015913a1585ffc..57297b73a1b68271c69670ce30c2c00f8b17b0c6 100644 (file)
@@ -69,7 +69,10 @@ des.door("open",23,13)
 des.door("open",25,10)
 des.door("open",28,05)
 -- Elder
-des.monster("Pelias", 10, 07)
+des.monster({ id = "Pelias", coord = {10, 07}, inventory = function()
+   des.object({ id = "runesword", spe = 5 });
+   des.object({ id = "chain mail", spe = 5 });
+end })
 -- The treasure of Pelias
 des.object("chest", 09, 05)
 -- chieftain guards for the audience chamber
index 83c071d0c34f2a7b6eb089d0401248f9055cdcbf..d4b974bd2101426a9985894e0b7a5b3bab7374e5 100644 (file)
@@ -54,7 +54,10 @@ des.door("locked",19,06)
 -- The temple altar (this will force a priest(ess) to be created)
 des.altar({ x=36,y=02, align="coaligned", type="shrine" })
 -- Shaman Karnov
-des.monster("Shaman Karnov", 35, 02)
+des.monster({ id = "Shaman Karnov", coord = {35, 02}, inventory = function()
+   des.object({ id = "leather armor", spe = 5 });
+   des.object({ id = "club", spe = 5 });
+end })
 -- The treasure of Shaman Karnov
 des.object("chest", 34, 02)
 -- neanderthal guards for the audience chamber
index 1a2f64acc236dcf54ab794a7c03b308a1c9e370b..a936f0212c760b04d5b471a8bd0d701d7f7a8589 100644 (file)
@@ -60,7 +60,9 @@ des.door("closed",47,08)
 des.door("closed",48,12)
 des.door("locked",50,10)
 -- Hippocrates
-des.monster("Hippocrates", 37, 10)
+des.monster({ id = "Hippocrates", coord = {37, 10}, inventory = function()
+   des.object({ id = "silver dagger", spe = 5 });
+end })
 -- The treasure of Hippocrates
 des.object("chest", 37, 10)
 -- intern guards for the audience chamber
index 4442d93a765ee58bb2f2754b3d623e2d9746267e..d7f9284c5606d380de376b9da1d75212d75b96f6 100644 (file)
@@ -62,7 +62,10 @@ des.door("closed",45,03)
 des.door("closed",04,12)
 des.door("closed",45,12)
 -- King Arthur
-des.monster("King Arthur", 09, 07)
+des.monster({ id = "King Arthur", coord = {09, 07}, inventory = function()
+   des.object({ id = "long sword", spe = 4, buc = "blessed", name = "Excalibur" });
+   des.object({ id = "plate mail", spe = 4 });
+end })
 -- The treasure of King Arthur
 des.object("chest", 09, 07)
 -- knight guards for the watchrooms
index ae1ad77d051348881b5762296ce254facacc5262..0ae685a698c57fa5f511e30e86fc3fe9fddf57c8 100644 (file)
@@ -71,7 +71,9 @@ des.door("closed",52,14)
 -- Unattended Altar - unaligned due to conflict - player must align it.
 des.altar({ x=28,y=09, align="noalign", type="altar" })
 -- The Grand Master
-des.monster("Grand Master", 28, 10)
+des.monster({ id = "Grand Master", coord = {28, 10}, inventory = function()
+   des.object({ id = "robe", spe = 6 });
+end })
 -- No treasure chest!
 -- guards for the audience chamber
 des.monster("abbot", 32, 07)
index 480a6276d913c0c3be1e5039724f28ab9297d8e2..fb66e64925b236480ff8741a7475eee81f166eb6 100644 (file)
@@ -71,7 +71,10 @@ des.door("closed",52,14)
 -- Unattended Altar - unaligned due to conflict - player must align it.
 des.altar({ x=28, y=09, align="noalign", type="altar" })
 -- High Priest
-des.monster("Arch Priest", 28, 10)
+des.monster({ id = "Arch Priest", coord = {28, 10}, inventory = function()
+   des.object({ id = "robe", spe = 4 });
+   des.object({ id = "mace", spe = 4 });
+end })
 -- The treasure of High Priest
 des.object("chest", 27, 10)
 -- knight guards for the audience chamber
index 69004ebb6a352efd2f91df1a027962cf9149268a..388dd7e9c901a181e14b67f3ff30158e2e7e9d0d 100644 (file)
@@ -46,7 +46,11 @@ des.stair("down", 10,10)
 -- Portal arrival point; just about anywhere on the right hand side of the map
 des.levregion({ region = {51,2,77,18}, region_islev = 1, type="branch" })
 -- Orion
-des.monster("Orion", 20, 10)
+des.monster({ id = "Orion", coord = {20, 10}, inventory = function()
+   des.object({ id = "leather armor", spe = 4 });
+   des.object({ id = "yumi", spe = 4 });
+   des.object({ id = "arrow", spe = 4, quantity = 50 });
+end })
 -- The treasure of Orion
 des.object("chest", 20, 10)
 -- Guards for the audience chamber
index 58f27f6966e9557dd05d192bd093b18270e599a2..b2fd32a792b3ec5ae5937e8ca78516ec8ba81864 100644 (file)
@@ -103,7 +103,11 @@ des.door("closed",  6,18)
 des.door("closed", 65,18)
 des.door("closed", 68,18)
 -- Master of Thieves
-des.monster("Master of Thieves", 36, 11)
+des.monster({ id = "Master of Thieves", coord = {36, 11}, inventory = function()
+   des.object({ id = "leather armor", spe = 5 });
+   des.object({ id = "silver dagger", spe = 4 });
+   des.object({ id = "dagger", spe = 2, quantity = d(2,4), buc = "not-cursed" });
+end })
 -- The treasure of Master of Thieves
 des.object("chest", 36, 11)
 -- thug guards, room #1
index 8186c3cb43bd61dc741348860f832ba37bf10f2b..e7c930bee8d0a3b6d02624f991a9deff1c568be2 100644 (file)
@@ -54,7 +54,10 @@ des.door("locked",39,08)
 des.door("closed",50,04)
 des.door("closed",50,06)
 -- Lord Sato
-des.monster("Lord Sato", 20, 04)
+des.monster({ id = "Lord Sato", coord = {20, 04}, inventory = function()
+   des.object({ id = "splint mail", spe = 5 });
+   des.object({ id = "katana", spe = 4 });
+end })
 -- The treasure of Lord Sato
 des.object("chest", 20, 04)
 -- roshi guards for the audience chamber
index c5efa0d29d7f48f7eae6220fbb97427c6a4fa987..e7a4f7812cc65ff02f3e710814cca1aff340df53 100644 (file)
@@ -95,7 +95,10 @@ des.monster("forest centaur")
 des.monster("forest centaur")
 des.monster("C")
 -- Twoflower
-des.monster("Twoflower", 64, 03)
+des.monster({ id = "Twoflower", coord = {64, 03}, inventory = function()
+   des.object({ id = "walking shoes", spe = 3 });
+   des.object({ id = "hawaiian shirt", spe = 3 });
+end })
 -- The treasure of Twoflower
 des.object("chest", 64, 03)
 -- guides for the audience chamber
index dbce2280dd5eb72120fd82be5dd9e81178f1752c..545dbce6c4140231381ad82ea557b9c4bbce3ba8 100644 (file)
@@ -61,7 +61,10 @@ des.feature("fountain", 53,02)
 des.door("locked",26,10)
 des.door("locked",43,10)
 -- Norn
-des.monster("Norn", 35, 10)
+des.monster({ id = "Norn", coord = {35, 10}, inventory = function()
+   des.object({ id = "banded mail", spe = 5 });
+   des.object({ id = "long sword", spe = 4 });
+end })
 -- The treasure of the Norn
 des.object("chest", 36, 10)
 -- valkyrie guards for the audience chamber
index 715cb5744f867a0281de580fb5d42525942cddca..69172039e2e40982ffff3054d0004f823f22a2df 100644 (file)
@@ -61,7 +61,10 @@ des.door("closed",15,10)
 des.door("locked",19,10)
 des.door("locked",20,10)
 -- Neferet the Green, the quest leader
-des.monster("Neferet the Green", 23, 05)
+des.monster({ id = "Neferet the Green", coord = {23, 05}, inventory = function()
+   des.object({ id = "elven cloak", spe = 5 });
+   des.object({ id = "quarterstaff", spe = 5 });
+end })
 -- The treasure of the quest leader
 des.object("chest", 24, 05)
 -- apprentice guards for the audience chamber
index a06c27ea40d233a605c4924cc167ba9d5d69b6df..5eadb3ae3d8337e3f60609cd99e0fb8ead741de9 100644 (file)
@@ -532,6 +532,8 @@ make anti-magic fields drain more energy and prevent them from showing up
 eating magical monsters such as wizards or shamans may give a mild buzz
 make exploding spheres create an actual explosion
 pets are more careful about attacking monsters at low health
+allow killing your quest leader to open the quest
+give King Arthur Excalibur
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index 548280a509c8d6f2bc3b0fd3d9a346c87b1bbbdc..c9d666210c9f3abf96e8c9831a7c58caea2212d4 100644 (file)
@@ -2064,6 +2064,7 @@ extern void free_epri(struct monst *);
 
 extern void onquest(void);
 extern void nemdead(void);
+extern void leaddead(void);
 extern void artitouch(struct obj *);
 extern boolean ok_to_quest(void);
 extern void leader_speaks(struct monst *);
index 700a805821b04528cc7e516ae9dda84157284c95..9b4b90091c5623d396d4cbdd7b897874124fda8e 100644 (file)
@@ -17,7 +17,7 @@
  * Incrementing EDITLEVEL can be used to force invalidation of old bones
  * and save files.
  */
-#define EDITLEVEL 33
+#define EDITLEVEL 34
 
 /*
  * Development status possibilities.
index 710af02d96ff9365e2244c66ef707045bb623376..88fd47eca76f232e4990cbde6699807994903914 100644 (file)
@@ -11,6 +11,7 @@ struct q_score {              /* Quest "scorecard" */
     Bitfield(not_ready, 3);   /* rejected due to alignment, etc. */
     Bitfield(pissed_off, 1);  /* got the leader angry */
     Bitfield(got_quest, 1);   /* got the quest assignment */
+    Bitfield(killed_leader, 1); /* killed the quest leader */
 
     Bitfield(first_locate, 1); /* only set the first time */
     Bitfield(met_intermed, 1); /* used if the locate is a person. */
@@ -39,7 +40,6 @@ struct q_score {              /* Quest "scorecard" */
     unsigned leader_m_id;
 };
 
-#define MAX_QUEST_TRIES 7  /* exceed this and you "fail" */
 #define MIN_QUEST_ALIGN 20 /* at least this align.record to start */
 /* note: align 20 matches "pious" as reported by enlightenment (cmd.c) */
 #define MIN_QUEST_LEVEL 14 /* at least this u.ulevel to start */
index 423ff031725a85d70b3a8a0deb778de8a9b5e53c..b63a3ec912bd4ab8952a3d87abe78e4d646db1fc 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -2205,6 +2205,8 @@ m_detach(
         wizdead();
     if (mtmp->data->msound == MS_NEMESIS)
         nemdead();
+    if (mtmp->data->msound == MS_LEADER)
+        leaddead();
     if (mtmp->m_id == g.stealmid)
         thiefdead();
     relobj(mtmp, 0, FALSE);
@@ -2926,12 +2928,17 @@ xkilled(
     /* adjust alignment points */
     if (mtmp->m_id == g.quest_status.leader_m_id) { /* REAL BAD! */
         adjalign(-(u.ualign.record + (int) ALIGNLIM / 2));
+        u.ugangr += 7; /* instantly become "extremely" angry */
+        change_luck(-20);
         pline("That was %sa bad idea...",
               u.uevent.qcompleted ? "probably " : "");
     } else if (mdat->msound == MS_NEMESIS) { /* Real good! */
-        adjalign((int) (ALIGNLIM / 4));
+        if (!g.quest_status.killed_leader)
+            adjalign((int) (ALIGNLIM / 4));
     } else if (mdat->msound == MS_GUARDIAN) { /* Bad */
         adjalign(-(int) (ALIGNLIM / 8));
+        u.ugangr++;
+        change_luck(-4);
         if (!Hallucination)
             pline("That was probably a bad idea...");
         else
@@ -3368,8 +3375,7 @@ setmangry(struct monst* mtmp, boolean via_attack)
     }
 
     /* attacking your own quest leader will anger his or her guardians */
-    if (!g.context.mon_moving /* should always be the case here */
-        && mtmp->data == &mons[quest_info(MS_LEADER)]) {
+    if (mtmp->data == &mons[quest_info(MS_LEADER)]) {
         struct monst *mon;
         struct permonst *q_guardian = &mons[quest_info(MS_GUARDIAN)];
         int got_mad = 0;
index 1da91df093de53b59942c34fa557c07e22ad156c..4f837d1b33d21ced650d24ef524b6a7a3a3a9316 100644 (file)
@@ -2854,25 +2854,25 @@ struct permonst _mons2[] = {
     /*
      * quest leaders
      */
-    MON("Lord Carnarvon", S_HUMAN, LVL(20, 12, 0, 30, 20), (G_NOGEN | G_UNIQ),
-        A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
-          NO_ATTK),
+    MON("Lord Carnarvon", S_HUMAN, LVL(20, 15, 0, 90, 20), (G_NOGEN | G_UNIQ),
+        A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_MAGC, AD_SPEL, 4, 8),
+          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), 0, 0,
         M1_TUNNEL | M1_NEEDPICK | M1_HUMANOID | M1_OMNIVORE,
         M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
             | M2_COLLECT | M2_MAGIC,
         M3_CLOSE | M3_INFRAVISIBLE, 22, HI_LORD),
-    MON("Pelias", S_HUMAN, LVL(20, 12, 0, 30, 0), (G_NOGEN | G_UNIQ),
-        A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
-          NO_ATTK),
+    MON("Pelias", S_HUMAN, LVL(20, 15, 0, 90, 0), (G_NOGEN | G_UNIQ),
+        A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 4, 10),
+          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), MR_POISON, 0,
         M1_HUMANOID | M1_OMNIVORE,
         M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
             | M2_COLLECT | M2_MAGIC,
         M3_CLOSE | M3_INFRAVISIBLE, 22, HI_LORD),
-    MON("Shaman Karnov", S_HUMAN, LVL(20, 12, 0, 30, 20), (G_NOGEN | G_UNIQ),
-        A(ATTK(AT_WEAP, AD_PHYS, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
-          NO_ATTK),
+    MON("Shaman Karnov", S_HUMAN, LVL(20, 15, 0, 90, 20), (G_NOGEN | G_UNIQ),
+        A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_MAGC, AD_CLRC, 2, 8),
+          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), 0, 0,
         M1_HUMANOID | M1_OMNIVORE,
         M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
@@ -2900,23 +2900,23 @@ struct permonst _mons2[] = {
           | M2_FEMALE | M2_COLLECT | M2_MAGIC,
         M3_CLOSE | M3_INFRAVISION | M3_INFRAVISIBLE, 22, HI_LORD),
 #endif
-    MON("Hippocrates", S_HUMAN, LVL(20, 12, 0, 40, 0), (G_NOGEN | G_UNIQ),
-        A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
-          NO_ATTK),
+    MON("Hippocrates", S_HUMAN, LVL(20, 15, 0, 90, 0), (G_NOGEN | G_UNIQ),
+        A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_CLRC, 3, 8),
+          ATTK(AT_MAGC, AD_CLRC, 3, 8), NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), MR_POISON, 0,
         M1_HUMANOID | M1_OMNIVORE,
         M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
             | M2_COLLECT | M2_MAGIC,
         M3_CLOSE | M3_INFRAVISIBLE, 22, HI_LORD),
-    MON("King Arthur", S_HUMAN, LVL(20, 12, 0, 40, 20), (G_NOGEN | G_UNIQ),
-        A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK,
+    MON("King Arthur", S_HUMAN, LVL(20, 15, 0, 90, 20), (G_NOGEN | G_UNIQ),
+        A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 4, 10), NO_ATTK,
           NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), 0, 0,
         M1_HUMANOID | M1_OMNIVORE,
         M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
             | M2_COLLECT | M2_MAGIC,
         M3_CLOSE | M3_INFRAVISIBLE, 23, HI_LORD),
-    MON("Grand Master", S_HUMAN, LVL(25, 12, 0, 70, 0), (G_NOGEN | G_UNIQ),
+    MON("Grand Master", S_HUMAN, LVL(25, 15, 0, 90, 0), (G_NOGEN | G_UNIQ),
         A(ATTK(AT_CLAW, AD_PHYS, 4, 10), ATTK(AT_KICK, AD_PHYS, 2, 8),
           ATTK(AT_MAGC, AD_CLRC, 2, 8), ATTK(AT_MAGC, AD_CLRC, 2, 8), NO_ATTK,
           NO_ATTK),
@@ -2926,7 +2926,7 @@ struct permonst _mons2[] = {
         M2_NOPOLY | M2_HUMAN | M2_PEACEFUL | M2_STRONG | M2_MALE | M2_NASTY
             | M2_MAGIC,
         M3_CLOSE | M3_INFRAVISIBLE, 30, CLR_BLACK),
-    MON("Arch Priest", S_HUMAN, LVL(25, 12, 7, 70, 0), (G_NOGEN | G_UNIQ),
+    MON("Arch Priest", S_HUMAN, LVL(25, 15, 7, 90, 0), (G_NOGEN | G_UNIQ),
         A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_KICK, AD_PHYS, 2, 8),
           ATTK(AT_MAGC, AD_CLRC, 2, 8), ATTK(AT_MAGC, AD_CLRC, 2, 8), NO_ATTK,
           NO_ATTK),
@@ -2936,9 +2936,9 @@ struct permonst _mons2[] = {
         M2_NOPOLY | M2_HUMAN | M2_PEACEFUL | M2_STRONG | M2_MALE | M2_COLLECT
             | M2_MAGIC,
         M3_CLOSE | M3_INFRAVISIBLE, 30, CLR_WHITE),
-    MON("Orion", S_HUMAN, LVL(20, 12, 0, 30, 0), (G_NOGEN | G_UNIQ),
-        A(ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
-          NO_ATTK),
+    MON("Orion", S_HUMAN, LVL(20, 15, 0, 90, 0), (G_NOGEN | G_UNIQ),
+        A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_MAGC, AD_SPEL, 4, 8),
+          NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(2200, 700, MS_LEADER, MZ_HUGE), 0, 0,
         M1_HUMANOID | M1_OMNIVORE | M1_SEE_INVIS | M1_SWIM | M1_AMPHIBIOUS,
         M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
@@ -2946,43 +2946,43 @@ struct permonst _mons2[] = {
         M3_CLOSE | M3_INFRAVISION | M3_INFRAVISIBLE, 22, HI_LORD),
     /* Note: Master of Thieves is also the Tourist's nemesis.
      */
-    MON("Master of Thieves", S_HUMAN, LVL(20, 12, 0, 30, -20),
+    MON("Master of Thieves", S_HUMAN, LVL(20, 15, 0, 90, -20),
         (G_NOGEN | G_UNIQ),
-        A(ATTK(AT_WEAP, AD_PHYS, 2, 6), ATTK(AT_WEAP, AD_PHYS, 2, 6),
+        A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 2, 6),
           ATTK(AT_CLAW, AD_SAMU, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), MR_STONE, 0,
         M1_HUMANOID | M1_OMNIVORE,
         M2_NOPOLY | M2_HUMAN | M2_PEACEFUL | M2_STRONG | M2_MALE | M2_GREEDY
             | M2_JEWELS | M2_COLLECT | M2_MAGIC,
         M3_CLOSE | M3_INFRAVISIBLE, 24, HI_LORD),
-    MON("Lord Sato", S_HUMAN, LVL(20, 12, 0, 30, 20), (G_NOGEN | G_UNIQ),
-        A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK,
+    MON("Lord Sato", S_HUMAN, LVL(20, 15, 0, 90, 20), (G_NOGEN | G_UNIQ),
+        A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 4, 10), NO_ATTK,
           NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), 0, 0,
         M1_HUMANOID | M1_OMNIVORE,
         M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
             | M2_COLLECT | M2_MAGIC,
         M3_CLOSE | M3_INFRAVISIBLE, 23, HI_LORD),
-    MON("Twoflower", S_HUMAN, LVL(20, 12, 10, 20, 0), (G_NOGEN | G_UNIQ),
-        A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK,
+    MON("Twoflower", S_HUMAN, LVL(20, 15, 10, 90, 0), (G_NOGEN | G_UNIQ),
+        A(ATTK(AT_WEAP, AD_PHYS, 4, 10), NO_ATTK, NO_ATTK,
           NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), 0, 0,
         M1_HUMANOID | M1_OMNIVORE,
         M2_NOPOLY | M2_HUMAN | M2_PNAME | M2_PEACEFUL | M2_STRONG | M2_MALE
             | M2_COLLECT | M2_MAGIC,
         M3_CLOSE | M3_INFRAVISIBLE, 22, HI_DOMESTIC),
-    MON("Norn", S_HUMAN, LVL(20, 12, 0, 80, 0), (G_NOGEN | G_UNIQ),
-        A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 6), NO_ATTK,
+    MON("Norn", S_HUMAN, LVL(20, 15, 0, 90, 0), (G_NOGEN | G_UNIQ),
+        A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 4, 10), NO_ATTK,
           NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(1800, 550, MS_LEADER, MZ_HUGE), MR_COLD, 0,
         M1_HUMANOID | M1_OMNIVORE,
         M2_NOPOLY | M2_HUMAN | M2_PEACEFUL | M2_STRONG | M2_FEMALE
             | M2_COLLECT | M2_MAGIC,
         M3_CLOSE | M3_INFRAVISIBLE, 23, HI_LORD),
-    MON("Neferet the Green", S_HUMAN, LVL(20, 12, 0, 60, 0),
+    MON("Neferet the Green", S_HUMAN, LVL(20, 15, 0, 90, 0),
         (G_NOGEN | G_UNIQ),
-        A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_SPEL, 2, 8), NO_ATTK,
-          NO_ATTK, NO_ATTK, NO_ATTK),
+        A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_MAGC, AD_SPEL, 2, 8),
+          ATTK(AT_MAGC, AD_SPEL, 2, 8), NO_ATTK, NO_ATTK, NO_ATTK),
         SIZ(WT_HUMAN, 400, MS_LEADER, MZ_HUMAN), 0, 0,
         M1_HUMANOID | M1_OMNIVORE,
         M2_NOPOLY | M2_HUMAN | M2_FEMALE | M2_PNAME | M2_PEACEFUL | M2_STRONG
index 575f4fef875b3dd33cb6986961c490a9d496c872..23d7037acdb2dea0bc1994a5ff3849f0513822a0 100644 (file)
@@ -17,7 +17,7 @@ static void on_goal(void);
 static boolean not_capable(void);
 static int is_pure(boolean);
 static void expulsion(boolean);
-static void chat_with_leader(void);
+static void chat_with_leader(struct monst *);
 static void chat_with_nemesis(void);
 static void chat_with_guardian(void);
 static void prisoner_speaks(struct monst *);
@@ -112,6 +112,15 @@ nemdead(void)
     }
 }
 
+void
+leaddead(void)
+{
+    if (!Qstat(killed_leader)) {
+        Qstat(killed_leader) = TRUE;
+        /* TODO: qt_pager("killed_leader"); ? */
+    }
+}
+
 void
 artitouch(struct obj *obj)
 {
@@ -130,8 +139,8 @@ artitouch(struct obj *obj)
 boolean
 ok_to_quest(void)
 {
-    return (boolean) ((Qstat(got_quest) || Qstat(got_thanks))
-                      && is_pure(FALSE) > 0);
+    return (boolean) (((Qstat(got_quest) || Qstat(got_thanks))
+                       && is_pure(FALSE) > 0) || Qstat(killed_leader));
 }
 
 static boolean
@@ -240,8 +249,11 @@ finish_quest(struct obj *obj) /* quest artifact; possibly null if carrying
 }
 
 static void
-chat_with_leader(void)
+chat_with_leader(struct monst *mtmp)
 {
+    if (!mtmp->mpeaceful || Qstat(pissed_off))
+        return;
+
     /*  Rule 0: Cheater checks. */
     if (u.uhave.questart && !Qstat(met_nemesis))
         Qstat(cheater) = TRUE;
@@ -293,18 +305,16 @@ chat_with_leader(void)
             exercise(A_WIS, TRUE);
             expulsion(FALSE);
         } else if ((purity = is_pure(TRUE)) < 0) {
-            com_pager("banished");
-            expulsion(TRUE);
-        } else if (purity == 0) {
-            qt_pager("badalign");
-            if (Qstat(not_ready) == MAX_QUEST_TRIES) {
-                qt_pager("leader_last");
-                expulsion(TRUE);
-            } else {
-                Qstat(not_ready)++;
-                exercise(A_WIS, TRUE);
+            if (!Qstat(pissed_off)) {
+                com_pager("banished");
+                Qstat(pissed_off) = TRUE;
                 expulsion(FALSE);
             }
+        } else if (purity == 0) {
+            qt_pager("badalign");
+            Qstat(not_ready) = 1;
+            exercise(A_WIS, TRUE);
+            expulsion(FALSE);
         } else { /* You are worthy! */
             qt_pager("assignquest");
             exercise(A_WIS, TRUE);
@@ -318,6 +328,12 @@ leader_speaks(struct monst *mtmp)
 {
     /* maybe you attacked leader? */
     if (!mtmp->mpeaceful) {
+        if (!Qstat(pissed_off)) {
+            /* again, don't end it permanently if the leader gets angry
+             * since you're going to have to kill him to go questing... :)
+             * ...but do only show this crap once. */
+            qt_pager("leader_last");
+        }
         Qstat(pissed_off) = TRUE;
         mtmp->mstrategy &= ~STRAT_WAITMASK; /* end the inaction */
     }
@@ -326,11 +342,8 @@ leader_speaks(struct monst *mtmp)
     if (!on_level(&u.uz, &qstart_level))
         return;
 
-    if (Qstat(pissed_off)) {
-        qt_pager("leader_last");
-        expulsion(TRUE);
-    } else
-        chat_with_leader();
+    if (!Qstat(pissed_off))
+        chat_with_leader(mtmp);
 }
 
 static void
@@ -399,7 +412,10 @@ void
 quest_chat(struct monst *mtmp)
 {
     if (mtmp->m_id == Qstat(leader_m_id)) {
-        chat_with_leader();
+        chat_with_leader(mtmp);
+        /* leader might have become pissed during the chat */
+        if (Qstat(pissed_off))
+            setmangry(mtmp, FALSE);
         return;
     }
     switch (mtmp->data->msound) {
index 47434ad7ad0e6059fdc19237d07c16c49c5bac29..bacf359d779dfab3a2317574335bf5aba7748d2b 100644 (file)
@@ -499,6 +499,9 @@ nh_timeout(void)
     if (flags.friday13)
         baseluck -= 1;
 
+    if (g.quest_status.killed_leader)
+        baseluck -= 4;
+
     if (u.uluck != baseluck
         && g.moves % ((u.uhave.amulet || u.ugangr) ? 300 : 600) == 0) {
         /* Cursed luckstones stop bad luck from timing out; blessed luckstones