1/* SCCS Id: @(#)mplayer.c 3.4 1997/02/04 */ 2/* Copyright (c) Izchak Miller, 1992. */ 3/* NetHack may be freely redistributed. See license for details. */ 4 5#include "hack.h" 6 7STATIC_DCL const char *NDECL(dev_name); 8STATIC_DCL void FDECL(get_mplname, (struct monst *, char *)); 9STATIC_DCL void FDECL(mk_mplayer_armor, (struct monst *, SHORT_P)); 10 11/* These are the names of those who 12 * contributed to the development of NetHack 3.2/3.3/3.4. 13 * 14 * Keep in alphabetical order within teams. 15 * Same first name is entered once within each team. 16 */ 17static const char *developers[] = { 18 /* devteam */ 19 "Dave", "Dean", "Eric", "Izchak", "Janet", "Jessie", 20 "Ken", "Kevin", "Michael", "Mike", "Pat", "Paul", "Steve", "Timo", 21 "Warwick", 22 /* PC team */ 23 "Bill", "Eric", "Keizo", "Ken", "Kevin", "Michael", "Mike", "Paul", 24 "Stephen", "Steve", "Timo", "Yitzhak", 25 /* Amiga team */ 26 "Andy", "Gregg", "Janne", "Keni", "Mike", "Olaf", "Richard", 27 /* Mac team */ 28 "Andy", "Chris", "Dean", "Jon", "Jonathan", "Kevin", "Wang", 29 /* Atari team */ 30 "Eric", "Marvin", "Warwick", 31 /* NT team */ 32 "Alex", "Dion", "Michael", 33 /* OS/2 team */ 34 "Helge", "Ron", "Timo", 35 /* VMS team */ 36 "Joshua", "Pat", 37 ""}; 38 39 40/* return a randomly chosen developer name */ 41STATIC_OVL const char * 42dev_name() 43{ 44 register int i, m = 0, n = SIZE(developers); 45 register struct monst *mtmp; 46 register boolean match; 47 48 do { 49 match = FALSE; 50 i = rn2(n); 51 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 52 if(!is_mplayer(mtmp->data)) continue; 53 if(!strncmp(developers[i], NAME(mtmp), 54 strlen(developers[i]))) { 55 match = TRUE; 56 break; 57 } 58 } 59 m++; 60 } while (match && m < 100); /* m for insurance */ 61 62 if (match) return (const char *)0; 63 return(developers[i]); 64} 65 66STATIC_OVL void 67get_mplname(mtmp, nam) 68register struct monst *mtmp; 69char *nam; 70{ 71 boolean fmlkind = is_female(mtmp->data); 72 const char *devnam; 73 74 devnam = dev_name(); 75 if (!devnam) 76 Strcpy(nam, fmlkind ? "Eve" : "Adam"); 77 else if (fmlkind && !!strcmp(devnam, "Janet")) 78 Strcpy(nam, rn2(2) ? "Maud" : "Eve"); 79 else Strcpy(nam, devnam); 80 81 if (fmlkind || !strcmp(nam, "Janet")) 82 mtmp->female = 1; 83 else 84 mtmp->female = 0; 85 Strcat(nam, " the "); 86 Strcat(nam, rank_of((int)mtmp->m_lev, 87 monsndx(mtmp->data), 88 (boolean)mtmp->female)); 89} 90 91STATIC_OVL void 92mk_mplayer_armor(mon, typ) 93struct monst *mon; 94short typ; 95{ 96 struct obj *obj; 97 98 if (typ == STRANGE_OBJECT) return; 99 obj = mksobj(typ, FALSE, FALSE); 100 if (!rn2(3)) obj->oerodeproof = 1; 101 if (!rn2(3)) curse(obj); 102 if (!rn2(3)) bless(obj); 103 /* Most players who get to the endgame who have cursed equipment 104 * have it because the wizard or other monsters cursed it, so its 105 * chances of having plusses is the same as usual.... 106 */ 107 obj->spe = rn2(10) ? (rn2(3) ? rn2(5) : rn1(4,4)) : -rnd(3); 108 (void) mpickobj(mon, obj); 109} 110 111struct monst * 112mk_mplayer(ptr, x, y, special) 113register struct permonst *ptr; 114xchar x, y; 115register boolean special; 116{ 117 register struct monst *mtmp; 118 char nam[PL_NSIZ]; 119 120 if(!is_mplayer(ptr)) 121 return((struct monst *)0); 122 123 if(MON_AT(x, y)) 124 (void) rloc(m_at(x, y), FALSE); /* insurance */ 125 126 if(!In_endgame(&u.uz)) special = FALSE; 127 128 if ((mtmp = makemon(ptr, x, y, NO_MM_FLAGS)) != 0) { 129 short weapon = rn2(2) ? LONG_SWORD : rnd_class(SPEAR, BULLWHIP); 130 short armor = rnd_class(GRAY_DRAGON_SCALE_MAIL, YELLOW_DRAGON_SCALE_MAIL); 131 short cloak = !rn2(8) ? STRANGE_OBJECT : 132 rnd_class(OILSKIN_CLOAK, CLOAK_OF_DISPLACEMENT); 133 short helm = !rn2(8) ? STRANGE_OBJECT : 134 rnd_class(ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY); 135 short shield = !rn2(8) ? STRANGE_OBJECT : 136 rnd_class(ELVEN_SHIELD, SHIELD_OF_REFLECTION); 137 int quan; 138 struct obj *otmp; 139 140 mtmp->m_lev = (special ? rn1(16,15) : rnd(16)); 141 mtmp->mhp = mtmp->mhpmax = d((int)mtmp->m_lev,10) + 142 (special ? (30 + rnd(30)) : 30); 143 if(special) { 144 get_mplname(mtmp, nam); 145 mtmp = christen_monst(mtmp, nam); 146 /* that's why they are "stuck" in the endgame :-) */ 147 (void)mongets(mtmp, FAKE_AMULET_OF_YENDOR); 148 } 149 mtmp->mpeaceful = 0; 150 set_malign(mtmp); /* peaceful may have changed again */ 151 152 switch(monsndx(ptr)) { 153 case PM_ARCHEOLOGIST: 154 if (rn2(2)) weapon = BULLWHIP; 155 break; 156 case PM_BARBARIAN: 157 if (rn2(2)) { 158 weapon = rn2(2) ? TWO_HANDED_SWORD : BATTLE_AXE; 159 shield = STRANGE_OBJECT; 160 } 161 if (rn2(2)) armor = rnd_class(PLATE_MAIL, CHAIN_MAIL); 162 if (helm == HELM_OF_BRILLIANCE) helm = STRANGE_OBJECT; 163 break; 164 case PM_CAVEMAN: 165 case PM_CAVEWOMAN: 166 if (rn2(4)) weapon = MACE; 167 else if (rn2(2)) weapon = CLUB; 168 if (helm == HELM_OF_BRILLIANCE) helm = STRANGE_OBJECT; 169 break; 170 case PM_HEALER: 171 if (rn2(4)) weapon = QUARTERSTAFF; 172 else if (rn2(2)) weapon = rn2(2) ? UNICORN_HORN : SCALPEL; 173 if (rn2(4)) helm = rn2(2) ? HELM_OF_BRILLIANCE : HELM_OF_TELEPATHY; 174 if (rn2(2)) shield = STRANGE_OBJECT; 175 break; 176 case PM_KNIGHT: 177 if (rn2(4)) weapon = LONG_SWORD; 178 if (rn2(2)) armor = rnd_class(PLATE_MAIL, CHAIN_MAIL); 179 break; 180 case PM_MONK: 181 weapon = STRANGE_OBJECT; 182 armor = STRANGE_OBJECT; 183 cloak = ROBE; 184 if (rn2(2)) shield = STRANGE_OBJECT; 185 break; 186 case PM_PRIEST: 187 case PM_PRIESTESS: 188 if (rn2(2)) weapon = MACE; 189 if (rn2(2)) armor = rnd_class(PLATE_MAIL, CHAIN_MAIL); 190 if (rn2(4)) cloak = ROBE; 191 if (rn2(4)) helm = rn2(2) ? HELM_OF_BRILLIANCE : HELM_OF_TELEPATHY; 192 if (rn2(2)) shield = STRANGE_OBJECT; 193 break; 194 case PM_RANGER: 195 if (rn2(2)) weapon = ELVEN_DAGGER; 196 break; 197 case PM_ROGUE: 198 if (rn2(2)) weapon = SHORT_SWORD; 199 break; 200 case PM_SAMURAI: 201 if (rn2(2)) weapon = KATANA; 202 break; 203#ifdef TOURIST 204 case PM_TOURIST: 205 /* Defaults are just fine */ 206 break; 207#endif 208 case PM_VALKYRIE: 209 if (rn2(2)) weapon = WAR_HAMMER; 210 if (rn2(2)) armor = rnd_class(PLATE_MAIL, CHAIN_MAIL); 211 break; 212 case PM_WIZARD: 213 if (rn2(4)) weapon = rn2(2) ? QUARTERSTAFF : ATHAME; 214 if (rn2(2)) { 215 armor = rn2(2) ? BLACK_DRAGON_SCALE_MAIL : 216 SILVER_DRAGON_SCALE_MAIL; 217 cloak = CLOAK_OF_MAGIC_RESISTANCE; 218 } 219 if (rn2(4)) helm = HELM_OF_BRILLIANCE; 220 shield = STRANGE_OBJECT; 221 break; 222 default: impossible("bad mplayer monster"); 223 weapon = 0; 224 break; 225 } 226 227 if (weapon != STRANGE_OBJECT) { 228 otmp = mksobj(weapon, TRUE, FALSE); 229 otmp->spe = (special ? rn1(5,4) : rn2(4)); 230 if (!rn2(3)) otmp->oerodeproof = 1; 231 else if (!rn2(2)) otmp->greased = 1; 232 if (special && rn2(2)) 233 otmp = mk_artifact(otmp, A_NONE); 234 /* mplayers knew better than to overenchant Magicbane */ 235 if (otmp->oartifact == ART_MAGICBANE) 236 otmp->spe = rnd(4); 237 (void) mpickobj(mtmp, otmp); 238 } 239 240 if(special) { 241 if (!rn2(10)) 242 (void) mongets(mtmp, rn2(3) ? LUCKSTONE : LOADSTONE); 243 mk_mplayer_armor(mtmp, armor); 244 mk_mplayer_armor(mtmp, cloak); 245 mk_mplayer_armor(mtmp, helm); 246 mk_mplayer_armor(mtmp, shield); 247 if (rn2(8)) 248 mk_mplayer_armor(mtmp, rnd_class(LEATHER_GLOVES, 249 GAUNTLETS_OF_DEXTERITY)); 250 if (rn2(8)) 251 mk_mplayer_armor(mtmp, rnd_class(LOW_BOOTS, LEVITATION_BOOTS)); 252 m_dowear(mtmp, TRUE); 253 254 quan = rn2(3) ? rn2(3) : rn2(16); 255 while(quan--) 256 (void)mongets(mtmp, rnd_class(DILITHIUM_CRYSTAL, JADE)); 257 /* To get the gold "right" would mean a player can double his */ 258 /* gold supply by killing one mplayer. Not good. */ 259#ifndef GOLDOBJ 260 mtmp->mgold = rn2(1000); 261#else 262 mkmonmoney(mtmp, rn2(1000)); 263#endif 264 quan = rn2(10); 265 while(quan--) 266 (void) mpickobj(mtmp, mkobj(RANDOM_CLASS, FALSE)); 267 } 268 quan = rnd(3); 269 while(quan--) 270 (void)mongets(mtmp, rnd_offensive_item(mtmp)); 271 quan = rnd(3); 272 while(quan--) 273 (void)mongets(mtmp, rnd_defensive_item(mtmp)); 274 quan = rnd(3); 275 while(quan--) 276 (void)mongets(mtmp, rnd_misc_item(mtmp)); 277 } 278 279 return(mtmp); 280} 281 282/* create the indicated number (num) of monster-players, 283 * randomly chosen, and in randomly chosen (free) locations 284 * on the level. If "special", the size of num should not 285 * be bigger than the number of _non-repeated_ names in the 286 * developers array, otherwise a bunch of Adams and Eves will 287 * fill up the overflow. 288 */ 289void 290create_mplayers(num, special) 291register int num; 292boolean special; 293{ 294 int pm, x, y; 295 struct monst fakemon; 296 297 while(num) { 298 int tryct = 0; 299 300 /* roll for character class */ 301 pm = PM_ARCHEOLOGIST + rn2(PM_WIZARD - PM_ARCHEOLOGIST + 1); 302 fakemon.data = &mons[pm]; 303 304 /* roll for an available location */ 305 do { 306 x = rn1(COLNO-4, 2); 307 y = rnd(ROWNO-2); 308 } while(!goodpos(x, y, &fakemon, 0) && tryct++ <= 50); 309 310 /* if pos not found in 50 tries, don't bother to continue */ 311 if(tryct > 50) return; 312 313 (void) mk_mplayer(&mons[pm], (xchar)x, (xchar)y, special); 314 num--; 315 } 316} 317 318void 319mplayer_talk(mtmp) 320register struct monst *mtmp; 321{ 322 static const char *same_class_msg[3] = { 323 "I can't win, and neither will you!", 324 "You don't deserve to win!", 325 "Mine should be the honor, not yours!", 326 }, *other_class_msg[3] = { 327 "The low-life wants to talk, eh?", 328 "Fight, scum!", 329 "Here is what I have to say!", 330 }; 331 332 if(mtmp->mpeaceful) return; /* will drop to humanoid talk */ 333 334 pline("Talk? -- %s", 335 (mtmp->data == &mons[urole.malenum] || 336 mtmp->data == &mons[urole.femalenum]) ? 337 same_class_msg[rn2(3)] : other_class_msg[rn2(3)]); 338} 339 340/*mplayer.c*/ 341