OSDN Git Service

no bone
[nethackexpress/trunk.git] / src / mplayer.c
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
7 STATIC_DCL const char *NDECL(dev_name);
8 STATIC_DCL void FDECL(get_mplname, (struct monst *, char *));
9 STATIC_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  */
17 static 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 */
41 STATIC_OVL const char *
42 dev_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
66 STATIC_OVL void
67 get_mplname(mtmp, nam)
68 register struct monst *mtmp;
69 char *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
91 STATIC_OVL void
92 mk_mplayer_armor(mon, typ)
93 struct monst *mon;
94 short 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
111 struct monst *
112 mk_mplayer(ptr, x, y, special)
113 register struct permonst *ptr;
114 xchar x, y;
115 register 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  */
289 void
290 create_mplayers(num, special)
291 register int num;
292 boolean 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
318 void
319 mplayer_talk(mtmp)
320 register 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*/