1/* SCCS Id: @(#)minion.c 3.4 2003/01/09 */ 2/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3/* NetHack may be freely redistributed. See license for details. */ 4 5#include "hack.h" 6#include "emin.h" 7#include "epri.h" 8 9void 10msummon(mon) /* mon summons a monster */ 11struct monst *mon; 12{ 13 register struct permonst *ptr; 14 register int dtype = NON_PM, cnt = 0; 15 aligntyp atyp; 16 struct monst *mtmp; 17 18 if (mon) { 19 ptr = mon->data; 20 atyp = (ptr->maligntyp==A_NONE) ? A_NONE : sgn(ptr->maligntyp); 21 if (mon->ispriest || mon->data == &mons[PM_ALIGNED_PRIEST] 22 || mon->data == &mons[PM_ANGEL]) 23 atyp = EPRI(mon)->shralign; 24 } else { 25 ptr = &mons[PM_WIZARD_OF_YENDOR]; 26 atyp = (ptr->maligntyp==A_NONE) ? A_NONE : sgn(ptr->maligntyp); 27 } 28 29 if (is_dprince(ptr) || (ptr == &mons[PM_WIZARD_OF_YENDOR])) { 30 dtype = (!rn2(20)) ? dprince(atyp) : 31 (!rn2(4)) ? dlord(atyp) : ndemon(atyp); 32 cnt = (!rn2(4) && is_ndemon(&mons[dtype])) ? 2 : 1; 33 } else if (is_dlord(ptr)) { 34 dtype = (!rn2(50)) ? dprince(atyp) : 35 (!rn2(20)) ? dlord(atyp) : ndemon(atyp); 36 cnt = (!rn2(4) && is_ndemon(&mons[dtype])) ? 2 : 1; 37 } else if (is_ndemon(ptr)) { 38 dtype = (!rn2(20)) ? dlord(atyp) : 39 (!rn2(6)) ? ndemon(atyp) : monsndx(ptr); 40 cnt = 1; 41 } else if (is_lminion(mon)) { 42 dtype = (is_lord(ptr) && !rn2(20)) ? llord() : 43 (is_lord(ptr) || !rn2(6)) ? lminion() : monsndx(ptr); 44 cnt = (!rn2(4) && !is_lord(&mons[dtype])) ? 2 : 1; 45 } else if (ptr == &mons[PM_ANGEL]) { 46 /* non-lawful angels can also summon */ 47 if (!rn2(6)) { 48 switch (atyp) { /* see summon_minion */ 49 case A_NEUTRAL: 50 dtype = PM_AIR_ELEMENTAL + rn2(4); 51 break; 52 case A_CHAOTIC: 53 case A_NONE: 54 dtype = ndemon(atyp); 55 break; 56 } 57 } else { 58 dtype = PM_ANGEL; 59 } 60 cnt = (!rn2(4) && !is_lord(&mons[dtype])) ? 2 : 1; 61 } 62 63 if (dtype == NON_PM) return; 64 65 /* sanity checks */ 66 if (cnt > 1 && (mons[dtype].geno & G_UNIQ)) cnt = 1; 67 /* 68 * If this daemon is unique and being re-summoned (the only way we 69 * could get this far with an extinct dtype), try another. 70 */ 71 if (mvitals[dtype].mvflags & G_GONE) { 72 dtype = ndemon(atyp); 73 if (dtype == NON_PM) return; 74 } 75 76 while (cnt > 0) { 77 mtmp = makemon(&mons[dtype], u.ux, u.uy, NO_MM_FLAGS); 78 if (mtmp && (dtype == PM_ANGEL)) { 79 /* alignment should match the summoner */ 80 EPRI(mtmp)->shralign = atyp; 81 } 82 cnt--; 83 } 84} 85 86void 87summon_minion(alignment, talk) 88aligntyp alignment; 89boolean talk; 90{ 91 register struct monst *mon; 92 int mnum; 93 94 switch ((int)alignment) { 95 case A_LAWFUL: 96 mnum = lminion(); 97 break; 98 case A_NEUTRAL: 99 mnum = PM_AIR_ELEMENTAL + rn2(4); 100 break; 101 case A_CHAOTIC: 102 case A_NONE: 103 mnum = ndemon(alignment); 104 break; 105 default: 106 impossible("unaligned player?"); 107 mnum = ndemon(A_NONE); 108 break; 109 } 110 if (mnum == NON_PM) { 111 mon = 0; 112 } else if (mons[mnum].pxlth == 0) { 113 struct permonst *pm = &mons[mnum]; 114 mon = makemon(pm, u.ux, u.uy, MM_EMIN); 115 if (mon) { 116 mon->isminion = TRUE; 117 EMIN(mon)->min_align = alignment; 118 } 119 } else if (mnum == PM_ANGEL) { 120 mon = makemon(&mons[mnum], u.ux, u.uy, NO_MM_FLAGS); 121 if (mon) { 122 mon->isminion = TRUE; 123 EPRI(mon)->shralign = alignment; /* always A_LAWFUL here */ 124 } 125 } else 126 mon = makemon(&mons[mnum], u.ux, u.uy, NO_MM_FLAGS); 127 if (mon) { 128 if (talk) { 129 pline_The("voice of %s booms:", align_gname(alignment)); 130 verbalize("Thou shalt pay for thy indiscretion!"); 131 if (!Blind) 132 pline("%s appears before you.", Amonnam(mon)); 133 } 134 mon->mpeaceful = FALSE; 135 /* don't call set_malign(); player was naughty */ 136 } 137} 138 139#define Athome (Inhell && !mtmp->cham) 140 141int 142demon_talk(mtmp) /* returns 1 if it won't attack. */ 143register struct monst *mtmp; 144{ 145 long cash, demand, offer; 146 147 if (uwep && uwep->oartifact == ART_EXCALIBUR) { 148 pline("%s looks very angry.", Amonnam(mtmp)); 149 mtmp->mpeaceful = mtmp->mtame = 0; 150 set_malign(mtmp); 151 newsym(mtmp->mx, mtmp->my); 152 return 0; 153 } 154 155 /* Slight advantage given. */ 156 if (is_dprince(mtmp->data) && mtmp->minvis) { 157 mtmp->minvis = mtmp->perminvis = 0; 158 if (!Blind) pline("%s appears before you.", Amonnam(mtmp)); 159 newsym(mtmp->mx,mtmp->my); 160 } 161 if (youmonst.data->mlet == S_DEMON) { /* Won't blackmail their own. */ 162 pline("%s says, \"Good hunting, %s.\"", 163 Amonnam(mtmp), flags.female ? "Sister" : "Brother"); 164 if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE); 165 return(1); 166 } 167#ifndef GOLDOBJ 168 cash = u.ugold; 169#else 170 cash = money_cnt(invent); 171#endif 172 demand = (cash * (rnd(80) + 20 * Athome)) / 173 (100 * (1 + (sgn(u.ualign.type) == sgn(mtmp->data->maligntyp)))); 174 175 if (!demand) { /* you have no gold */ 176 mtmp->mpeaceful = 0; 177 set_malign(mtmp); 178 return 0; 179 } else { 180 /* make sure that the demand is unmeetable if the monster 181 has the Amulet, preventing monster from being satisified 182 and removed from the game (along with said Amulet...) */ 183 if (mon_has_amulet(mtmp)) 184 demand = cash + (long)rn1(1000,40); 185 186 pline("%s demands %ld %s for safe passage.", 187 Amonnam(mtmp), demand, currency(demand)); 188 189 if ((offer = bribe(mtmp)) >= demand) { 190 pline("%s vanishes, laughing about cowardly mortals.", 191 Amonnam(mtmp)); 192 } else if (offer > 0L && (long)rnd(40) > (demand - offer)) { 193 pline("%s scowls at you menacingly, then vanishes.", 194 Amonnam(mtmp)); 195 } else { 196 pline("%s gets angry...", Amonnam(mtmp)); 197 mtmp->mpeaceful = 0; 198 set_malign(mtmp); 199 return 0; 200 } 201 } 202 mongone(mtmp); 203 return(1); 204} 205 206long 207bribe(mtmp) 208struct monst *mtmp; 209{ 210 char buf[BUFSZ]; 211 long offer; 212#ifdef GOLDOBJ 213 long umoney = money_cnt(invent); 214#endif 215 216 getlin("How much will you offer?", buf); 217 if (sscanf(buf, "%ld", &offer) != 1) offer = 0L; 218 219 /*Michael Paddon -- fix for negative offer to monster*/ 220 /*JAR880815 - */ 221 if (offer < 0L) { 222 You("try to shortchange %s, but fumble.", 223 mon_nam(mtmp)); 224 return 0L; 225 } else if (offer == 0L) { 226 You("refuse."); 227 return 0L; 228#ifndef GOLDOBJ 229 } else if (offer >= u.ugold) { 230 You("give %s all your gold.", mon_nam(mtmp)); 231 offer = u.ugold; 232 } else { 233 You("give %s %ld %s.", mon_nam(mtmp), offer, currency(offer)); 234 } 235 u.ugold -= offer; 236 mtmp->mgold += offer; 237#else 238 } else if (offer >= umoney) { 239 You("give %s all your gold.", mon_nam(mtmp)); 240 offer = umoney; 241 } else { 242 You("give %s %ld %s.", mon_nam(mtmp), offer, currency(offer)); 243 } 244 (void) money2mon(mtmp, offer); 245#endif 246 flags.botl = 1; 247 return(offer); 248} 249 250int 251dprince(atyp) 252aligntyp atyp; 253{ 254 int tryct, pm; 255 256 for (tryct = 0; tryct < 20; tryct++) { 257 pm = rn1(PM_DEMOGORGON + 1 - PM_ORCUS, PM_ORCUS); 258 if (!(mvitals[pm].mvflags & G_GONE) && 259 (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp))) 260 return(pm); 261 } 262 return(dlord(atyp)); /* approximate */ 263} 264 265int 266dlord(atyp) 267aligntyp atyp; 268{ 269 int tryct, pm; 270 271 for (tryct = 0; tryct < 20; tryct++) { 272 pm = rn1(PM_YEENOGHU + 1 - PM_JUIBLEX, PM_JUIBLEX); 273 if (!(mvitals[pm].mvflags & G_GONE) && 274 (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp))) 275 return(pm); 276 } 277 return(ndemon(atyp)); /* approximate */ 278} 279 280/* create lawful (good) lord */ 281int 282llord() 283{ 284 if (!(mvitals[PM_ARCHON].mvflags & G_GONE)) 285 return(PM_ARCHON); 286 287 return(lminion()); /* approximate */ 288} 289 290int 291lminion() 292{ 293 int tryct; 294 struct permonst *ptr; 295 296 for (tryct = 0; tryct < 20; tryct++) { 297 ptr = mkclass(S_ANGEL,0); 298 if (ptr && !is_lord(ptr)) 299 return(monsndx(ptr)); 300 } 301 302 return NON_PM; 303} 304 305int 306ndemon(atyp) 307aligntyp atyp; 308{ 309 int tryct; 310 struct permonst *ptr; 311 312 for (tryct = 0; tryct < 20; tryct++) { 313 ptr = mkclass(S_DEMON, 0); 314 if (ptr && is_ndemon(ptr) && 315 (atyp == A_NONE || sgn(ptr->maligntyp) == sgn(atyp))) 316 return(monsndx(ptr)); 317 } 318 319 return NON_PM; 320} 321 322/*minion.c*/ 323