Source:SLASH'EM 0.0.7E7F2/minion.c

Below is the full text to minion.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/minion.c#line123 ]], for example.

The latest source code for vanilla NetHack is at Source code.

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. 9.   void 10.  msummon(mon)		/* mon summons a monster */ 11.  struct 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.    86.   void 87.  summon_minion(alignment, talk) 88.  aligntyp alignment; 89.  boolean 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.  #define Athome	(Inhell && !mtmp->cham) 139.  140.  int 141. demon_talk(mtmp)		/* returns 1 if it won't attack. */ 142.  register struct monst *mtmp; 143. {  144.  	long cash, demand, offer; 145.  146.  	if (uwep && uwep->oartifact == ART_EXCALIBUR) { 147. 	    pline("%s looks very angry.", Amonnam(mtmp)); 148. 	    mtmp->mpeaceful = mtmp->mtame = 0; 149. 	    set_malign(mtmp); 150. 	    newsym(mtmp->mx, mtmp->my); 151. 	    return 0; 152. 	}  153.   154.  	/* Slight advantage given. */ 155.  	if (is_dprince(mtmp->data) && mtmp->minvis) { 156. 	    mtmp->minvis = mtmp->perminvis = 0; 157. 	    if (!Blind) pline("%s appears before you.", Amonnam(mtmp)); 158. 	    newsym(mtmp->mx,mtmp->my); 159. 	}  160.  	if (youmonst.data->mlet == S_DEMON) {	/* Won't blackmail their own. */ 161.  	    pline("%s says, \"Good hunting, %s.\"",  162.  		  Amonnam(mtmp), flags.female ? "Sister" : "Brother"); 163. 	    if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE); 164. 	    return(1); 165. 	}  166.  #ifndef GOLDOBJ 167. 	cash = u.ugold; 168. #else 169. 	cash = money_cnt(invent); 170. #endif 171. 	demand = (cash * (rnd(80) + 20 * Athome)) / 172. 	    (100 * (1 + (sgn(u.ualign.type) == sgn(mtmp->data->maligntyp)))); 173.  174.  	if (!demand) {		/* you have no gold */ 175. 	    mtmp->mpeaceful = 0; 176. 	    set_malign(mtmp); 177. 	    return 0; 178. 	} else { 179. 	    /* make sure that the demand is unmeetable if the monster 180. 	       has the Amulet, preventing monster from being satisified 181. 	       and removed from the game (along with said Amulet...) */ 182. 	    if (mon_has_amulet(mtmp)) 183. 		demand = cash + (long)rn1(1000,40); 184.  185.  	    pline("%s demands %ld %s for safe passage.",  186.  		  Amonnam(mtmp), demand, currency(demand)); 187.  188.  	    if ((offer = bribe(mtmp)) >= demand) { 189. 		pline("%s vanishes, laughing about cowardly mortals.",  190.  		      Amonnam(mtmp)); 191. 	    } else if (offer > 0L && (long)rnd(40) > (demand - offer)) { 192. 		pline("%s scowls at you menacingly, then vanishes.",  193.  		      Amonnam(mtmp)); 194. 	    } else { 195. 		pline("%s gets angry...", Amonnam(mtmp)); 196. 		mtmp->mpeaceful = 0; 197. 		set_malign(mtmp); 198. 		return 0; 199. 	    }  200.  	}  201.  	mongone(mtmp); 202. 	return(1); 203. }  204.   205.  int lawful_minion(int difficulty) 206. /* this routine returns the # of an appropriate minion, 207.    given a difficulty rating from 1 to 30 */ 208. {  209.     difficulty = difficulty + rn2(5) - 2; 210.    if (difficulty < 0) difficulty = 0; 211.    if (difficulty > 30) difficulty = 30; 212.    difficulty /= 3; 213.    switch (difficulty) { 214.       case 0: return PM_TENGU; 215.       case 1: return PM_COUATL; 216.       case 2: return PM_WHITE_UNICORN; 217.       case 3: return PM_MOVANIC_DEVA; 218.       case 4: return PM_MONADIC_DEVA; 219.       case 5: return PM_KI_RIN; 220.       case 6: return PM_ASTRAL_DEVA; 221.       case 7: return PM_ARCHON; 222.       case 8: return PM_PLANETAR; 223.       case 9: return PM_SOLAR; 224.       case 10: return PM_SOLAR; 225.  226.        default: return PM_TENGU; 227.    }  228.  }  229.   230.  int neutral_minion(int difficulty) 231. /* this routine returns the # of an appropriate minion, 232.    given a difficulty rating from 1 to 30 */ 233. {  234.     difficulty = difficulty + rn2(9) - 4; 235.    if (difficulty < 0) difficulty = 0; 236.    if (difficulty > 30) difficulty = 30; 237.    if (difficulty < 6) return PM_GRAY_UNICORN; 238.    if (difficulty < 15) return (PM_AIR_ELEMENTAL+rn2(4)); 239.    return (PM_DJINNI /* +rn2(4) */); 240. }  241.   242.  int chaotic_minion(int difficulty) 243. /* this routine returns the # of an appropriate minion, 244.    given a difficulty rating from 1 to 30 */ 245. {  246.     difficulty = difficulty + rn2(5) - 2; 247.    if (difficulty < 0) difficulty = 0; 248.    if (difficulty > 30) difficulty = 30; 249.    /* KMH, balance patch -- avoid using floating-point (not supported by all ports) */ 250. /*   difficulty = (int)((float)difficulty / 1.5);*/ 251.    difficulty = (difficulty * 2) / 3; 252.    switch (difficulty) { 253.       case 0: return PM_GREMLIN; 254.       case 1: 255.       case 2: return (PM_DRETCH+rn2(5)); 256.       case 3: return PM_BLACK_UNICORN; 257.       case 4: return PM_BLOOD_IMP; 258.       case 5: return PM_SPINED_DEVIL; 259.       case 6: return PM_SHADOW_WOLF; 260.       case 7: return PM_HELL_HOUND; 261.       case 8: return PM_HORNED_DEVIL; 262.       case 9: return PM_BEARDED_DEVIL; 263.       case 10: return PM_BAR_LGURA; 264.       case 11: return PM_CHASME; 265.       case 12: return PM_BARBED_DEVIL; 266.       case 13: return PM_VROCK; 267.       case 14: return PM_BABAU; 268.       case 15: return PM_NALFESHNEE; 269.       case 16: return PM_MARILITH; 270.       case 17: return PM_NABASSU; 271.       case 18: return PM_BONE_DEVIL; 272.       case 19: return PM_ICE_DEVIL; 273.       case 20: return PM_PIT_FIEND; 274.    }  275.     return PM_GREMLIN; 276. }  277.   278.  long 279. bribe(mtmp) 280. struct monst *mtmp; 281. {  282.  	char buf[BUFSZ]; 283. 	long offer; 284. #ifdef GOLDOBJ 285. 	long umoney = money_cnt(invent); 286. #endif 287.  288.  	getlin("How much will you offer?", buf); 289. 	if (sscanf(buf, "%ld", &offer) != 1) offer = 0L; 290.  291.  	/*Michael Paddon -- fix for negative offer to monster*/ 292. 	/*JAR880815 - */ 293. 	if (offer < 0L) { 294. 		You("try to shortchange %s, but fumble.",  295.  			mon_nam(mtmp)); 296. 		return 0L; 297. 	} else if (offer == 0L) { 298. 		You("refuse."); 299. 		return 0L; 300. #ifndef GOLDOBJ 301. 	} else if (offer >= u.ugold) { 302. 		You("give %s all your gold.", mon_nam(mtmp)); 303. 		offer = u.ugold; 304. 	} else { 305. 		You("give %s %ld %s.", mon_nam(mtmp), offer, currency(offer)); 306. 	}  307.  	u.ugold -= offer; 308. 	mtmp->mgold += offer; 309. #else 310. 	} else if (offer >= umoney) { 311. 		You("give %s all your money.", mon_nam(mtmp)); 312. 		offer = umoney; 313. 	} else { 314. 		You("give %s %ld %s.", mon_nam(mtmp), offer, currency(offer)); 315. 	}  316.  	(void) money2mon(mtmp, offer); 317. #endif 318. 	flags.botl = 1; 319. 	return(offer); 320. }  321.   322.  int 323. dprince(atyp) 324. aligntyp atyp; 325. {  326.  	int tryct, pm; 327.  328.  	for (tryct = 0; tryct < 20; tryct++) { 329. 	    pm = rn1(PM_DEMOGORGON + 1 - PM_ORCUS, PM_ORCUS); 330. 	    if (!(mvitals[pm].mvflags & G_GONE) &&  331.  		    (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp))) 332. 		return(pm); 333. 	}  334.  	return(dlord(atyp));	/* approximate */ 335. }  336.   337.  int 338. dlord(atyp) 339. aligntyp atyp; 340. {  341.  	int tryct, pm; 342.  343.  	for (tryct = 0; tryct < 20; tryct++) { 344. 	    pm = rn1(PM_YEENOGHU + 1 - PM_JUIBLEX, PM_JUIBLEX); 345. 	    if (!(mvitals[pm].mvflags & G_GONE) &&  346.  		    (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp))) 347. 		return(pm); 348. 	}  349.  	return(ndemon(atyp));	/* approximate */ 350. }  351.   352.  /* create lawful (good) lord */ 353. int 354. llord 355. {  356.  	if (!(mvitals[PM_ARCHON].mvflags & G_GONE)) 357. 		return(PM_ARCHON); 358.  359.  	return(lminion);	/* approximate */ 360. }  361.   362.  int 363. lminion 364. {  365.  	int	tryct; 366. 	struct	permonst *ptr; 367.  368.  	for (tryct = 0; tryct < 20; tryct++) { 369. 	    ptr = mkclass(S_ANGEL,0); 370. 	    if (ptr && !is_lord(ptr)) 371. 		return(monsndx(ptr)); 372. 	}  373.   374.  	return NON_PM; 375. }  376.   377.  int 378. ndemon(atyp) 379. aligntyp atyp; 380. {  381.  	int	tryct; 382. 	struct	permonst *ptr; 383.  384.  	for (tryct = 0; tryct < 20; tryct++) { 385. 	    ptr = mkclass(S_DEMON, 0); 386. 	    if (ptr && is_ndemon(ptr) &&  387.  		    (atyp == A_NONE || sgn(ptr->maligntyp) == sgn(atyp))) 388. 		return(monsndx(ptr)); 389. 	}  390.   391.  	return NON_PM; 392. }  393.   394.  /*minion.c*/