1 /* omega copyright (c) 1987,1988,1989 by Laurence Raphael Brothers */
2 /* mon.c */
3 /* various functions to do with monsters */
4
5 #include "glob.h"
6
7
8
9 /* Revised function */
10 /* WDT: code contributed by David J. Robertson */
11 /* consider one monster's action */
m_pulse(m)12 void m_pulse(m)
13 struct monster *m;
14 {
15 int range = distance(m->x, m->y, Player.x,Player.y);
16 int STRIKE=FALSE;
17 pol prev;
18
19 if (Time % 10 == 0)
20 if (m->hp < Monsters[m->id].hp)
21 m->hp++;
22
23 if ((! m_statusp(m,AWAKE)) && (range <= m->wakeup)) {
24 m_status_set(m,AWAKE);
25 resetgamestatus(FAST_MOVE);
26 }
27
28 if (m_statusp(m,AWAKE)) {
29 if (m_statusp(m,WANDERING)) {
30 if (m_statusp(m,MOBILE)) m_random_move(m);
31 if (range <= m->sense && (m_statusp(m, HOSTILE) ||
32 m_statusp(m, NEEDY)))
33 m_status_reset(m,WANDERING);
34 }
35 else /* not wandering */ {
36 if (m_statusp(m,HOSTILE))
37 if ((range > 2) && (range < m->sense) && (random_range(2) == 1))
38 if (los_p(m->x,m->y,Player.x,Player.y) &&
39 (Player.status[INVISIBLE] == 0)) {
40 STRIKE=TRUE;
41 monster_strike(m);
42 }
43
44 if ((m_statusp(m,HOSTILE) || m_statusp(m,NEEDY))
45 && (range > 1) && m_statusp(m,MOBILE) &&
46 (!STRIKE || (random_range(2) == 1)))
47 monster_move(m);
48 else
49 if (m_statusp(m,HOSTILE) && (range ==1)) {
50 resetgamestatus(FAST_MOVE);
51 tacmonster(m);
52 }
53 }
54 /* if monster is greedy, picks up treasure it finds */
55 if (m_statusp(m,GREEDY) && (m->hp >0) )
56 while (Level->site[m->x][m->y].things != NULL) {
57 m_pickup(m,Level->site[m->x][m->y].things->thing);
58 prev = Level->site[m->x][m->y].things;
59 Level->site[m->x][m->y].things =
60 Level->site[m->x][m->y].things->next;
61 free((char *) prev);
62 }
63 /* prevents monsters from casting spells from other side of dungeon */
64 if ((range < max(5,m->level)) && (m->hp > 0) &&
65 (random_range(2) == 1))
66 monster_special(m);
67 }
68 }
69
70 /* actually make a move */
movemonster(m,newx,newy)71 void movemonster(m,newx,newy)
72 struct monster *m;
73 int newx,newy;
74 {
75 if (Level->site[newx][newy].creature != NULL)
76 return;
77 if (Level->site[m->x][m->y].creature == m)
78 Level->site[m->x][m->y].creature = NULL;
79 m->x = newx;
80 m->y = newy;
81 Level->site[m->x][m->y].creature = m;
82 m_movefunction(m,Level->site[m->x][m->y].p_locf);
83 }
84
85
86 /* give object o to monster m */
m_pickup(m,o)87 void m_pickup(m,o)
88 struct monster *m;
89 struct object *o;
90 {
91 pol tmp = ((pol) checkmalloc(sizeof(oltype)));
92 tmp->thing = o;
93 tmp->next = m->possessions;
94 m->possessions = tmp;
95 }
96
m_dropstuff(m)97 void m_dropstuff(m)
98 struct monster *m;
99 {
100 pol tmp = m->possessions;
101 if (tmp != NULL) {
102 while (tmp->next != NULL)
103 tmp = tmp->next;
104
105 tmp->next = Level->site[m->x][m->y].things;
106 Level->site[m->x][m->y].things = m->possessions;
107 m->possessions = NULL;
108 }
109 }
110
111
112
m_damage(m,dmg,dtype)113 void m_damage(m,dmg,dtype)
114 struct monster *m;
115 int dmg,dtype;
116 {
117 m_status_set(m,AWAKE);
118 m_status_set(m,HOSTILE);
119 if (m_immunityp(m,dtype)) {
120 if (los_p(Player.x,Player.y,m->x,m->y)) {
121 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
122 else {
123 strcpy(Str1,"The ");
124 strcat(Str1,m->monstring);
125 }
126 strcat(Str1," ignores the attack!");
127 mprint(Str1);
128 }
129 }
130 else if ((m->hp -= dmg) < 1) m_death(m);
131 }
132
133
m_death(m)134 void m_death(m)
135 struct monster *m;
136 {
137 pob corpse;
138 pml ml;
139 int x,y,found=FALSE;
140 pol curr, prev = NULL;
141
142 m->hp = -1;
143 if (los_p(Player.x,Player.y,m->x,m->y)) {
144 gain_experience(m->xpv);
145 calc_melee();
146 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
147 else {
148 strcpy(Str1,"The ");
149 strcat(Str1,m->monstring);
150 }
151 strcat(Str1," is dead! ");
152 mprint(Str1);
153 }
154 m_dropstuff(m);
155 if (m->id == DEATH) { /* Death */
156 mprint("Death lies sprawled out on the ground......");
157 mprint("Death laughs ironically and gets back to its feet.");
158 mprint("It gestures and another scythe appears in its hands.");
159 switch(random_range(10)) {
160 case 0:
161 mprint("Death performs a little bow and goes back on guard.");
162 break;
163 case 1:
164 mprint("'A hit! A palpable hit!' Death goes back on the attack.");
165 break;
166 case 2:
167 mprint("'Ah, if only it could be so simple!' snickers Death.");
168 break;
169 case 3:
170 mprint("'You think Death can be slain? What a jest!' says Death.");
171 break;
172 case 4:
173 mprint("'Your point is well taken.' says Death, attacking again.");
174 break;
175 case 5:
176 mprint("'Oh, come now, stop delaying the inevitable.' says Death.");
177 break;
178 case 6:
179 mprint("'Your destiny ends here with me.' says Death, scythe raised.");
180 break;
181 case 7:
182 mprint("'I almost felt that.' says Death, smiling.");
183 break;
184 case 8:
185 mprint("'Timeo Mortis?' asks Death quizzically, 'Not me!'");
186 break;
187 case 9:
188 mprint("Death sighs theatrically. 'They never learn.'");
189 break;
190 }
191 strengthen_death(m);
192 }
193 else {
194 Level->site[m->x][m->y].creature = NULL;
195 if (m == Arena_Monster)
196 Arena_Victory = TRUE; /* won this round of arena combat */
197 if (random_range(2) || (m->uniqueness != COMMON)) {
198 corpse=((pob) checkmalloc(sizeof(objtype)));
199 make_corpse(corpse,m);
200 drop_at(m->x,m->y,corpse);
201 }
202 plotspot(m->x,m->y,FALSE);
203 switch(m->id) {
204 case HISCORE_NPC:
205 switch(m->aux2) {
206 case 0:
207 mprint("You hear a faroff dirge. You feel a sense of triumph.");
208 break;
209 case 1:case 2: case 3:case 4:case 5:case 6:
210 mprint("You hear a faroff sound like angels crying....");
211 strcpy(Priest[m->aux2],nameprint());
212 Priestbehavior[m->aux2] = 2933;
213 break;
214 case 7:
215 mprint("A furtive figure dashes out of the shadows, takes a look at");
216 mprint("the corpse, and runs away!");
217 strcpy(Shadowlord,nameprint());
218 Shadowlordbehavior = 2912;
219 break;
220 case 8:
221 mprint("An aide-de-camp approaches, removes the corpse's insignia,");
222 mprint("and departs.");
223 strcpy(Commandant,nameprint());
224 Commandantbehavior = 2912;
225 break;
226 case 9:
227 mprint("An odd glow surrounds the corpse, and slowly fades.");
228 strcpy(Archmage,nameprint());
229 Archmagebehavior = 2933;
230 break;
231 case 10:
232 mprint("A demon materializes, takes a quick look at the corpse,");
233 mprint("and teleports away with a faint popping noise.");
234 strcpy(Prime,nameprint());
235 Primebehavior = 2932;
236 break;
237 case 11:
238 mprint("A sports columnist rushes forward and takes a quick photo");
239 mprint("of the corpse and rushes off muttering about a deadline.");
240 strcpy(Champion,nameprint());
241 Championbehavior = 2913;
242 break;
243 case 12:
244 mprint("You hear a fanfare in the distance, and feel dismayed.");
245 strcpy(Duke,nameprint());
246 Dukebehavior = 2911;
247 break;
248 case 13:
249 if (Player.alignment > 10) mprint("You feel smug.");
250 else if (Player.alignment < 10) mprint("You feel ashamed.");
251 strcpy(Chaoslord,nameprint());
252 Chaoslordbehavior = 2912;
253 break;
254 case 14:
255 if (Player.alignment < 10) mprint("You feel smug.");
256 else if (Player.alignment > 10) mprint("You feel ashamed.");
257 strcpy(Lawlord,nameprint());
258 Lawlordbehavior = 2911;
259 break;
260 case 15:
261 /* just a tad complicated. Promote a new justiciar if any
262 guards are left in the city, otherwise Destroy the Order! */
263 Player.alignment -= 100;
264 if (! gamestatusp(DESTROYED_ORDER)) {
265 curr = Level->site[m->x][m->y].things;
266 while (curr && curr->thing->id != THINGID + 16) {
267 prev = curr;
268 curr = curr->next;
269 }
270 strcpy(Justiciar,nameprint());
271 Justiciarbehavior = 2911;
272 mprint("In the distance you hear a trumpet. A Servant of Law");
273 /* promote one of the city guards to be justiciar */
274 ml = City->mlist;
275 while ((! found) && (ml != NULL)) {
276 found = ((ml->m->id == GUARD) && (ml->m->hp > 0));
277 if (! found) ml=ml->next;
278 }
279 if (ml != NULL) {
280 if (curr) {
281 mprint("materializes, sheds a tear, picks up the badge, and leaves.");
282 m_pickup(ml->m, curr->thing);
283 if (prev)
284 prev->next = curr->next;
285 else
286 Level->site[m->x][m->y].things = curr->next;
287 free(curr);
288 }
289 else
290 mprint("materializes, sheds a tear, and leaves.");
291 mprint("A new justiciar has been promoted!");
292 x = ml->m->x; y = ml->m->y;
293 make_hiscore_npc(ml->m,15);
294 ml->m->x = x;
295 ml->m->y = y;
296 ml->m->click = (Tick + 1) % 60;
297 m_status_reset(ml->m,AWAKE);
298 m_status_reset(ml->m,HOSTILE);
299 }
300 else {
301 mprint("materializes, sheds a tear, and leaves.");
302 morewait();
303 }
304 alert_guards();
305 /* will cause order to be destroyed if no guards or justiciar*/
306 }
307 else {
308 mprint("A Servant of Chaos materializes, grabs the corpse,");
309 mprint("snickers a bit, and vanishes.");
310 }
311 break;
312 }
313 save_hiscore_npc(m->aux2);
314 break;
315 case GUARD: /* guard */
316 Player.alignment -= 10;
317 if ((Current_Environment == E_CITY) ||
318 (Current_Environment == E_VILLAGE))
319 alert_guards();
320 break;
321 case GOBLIN_KING:
322 if (! gamestatusp(ATTACKED_ORACLE)) {
323 mprint("You seem to hear a woman's voice from far off:");
324 mprint("'Well done! Come to me now....'");
325 }
326 setgamestatus(COMPLETED_CAVES);
327 break; /* gob king */
328 case GREAT_WYRM:
329 if (! gamestatusp(ATTACKED_ORACLE)) {
330 mprint("A female voice sounds from just behind your ear:");
331 mprint("'Well fought! I have some new advice for you....'");
332 }
333 setgamestatus(COMPLETED_SEWERS);
334 break; /*grt worm */
335 case EATER:
336 setgamestatus(KILLED_EATER);
337 break;
338 case LAWBRINGER:
339 setgamestatus(KILLED_LAWBRINGER);
340 break;
341 case DRAGON_LORD:
342 setgamestatus(KILLED_DRAGONLORD);
343 break;
344 case DEMON_EMP:
345 setgamestatus(COMPLETED_VOLCANO);
346 if (! gamestatusp(ATTACKED_ORACLE)) {
347 mprint("You feel a soft touch on your shoulder...");
348 mprint("You turn around but there is no one there!");
349 mprint("You turn back and see a note: 'See me soon.'");
350 mprint("The note vanishes in a burst of blue fire!");
351 }
352 break;
353 case ELEM_MASTER:
354 if (! gamestatusp(ATTACKED_ORACLE)) {
355 mprint("Words appear before you, traced in blue flame!");
356 mprint("'Return to the Prime Plane via the Circle of Sorcerors....'");
357 }
358 break; /* elem mast */
359 }
360 switch (m->specialf) {
361 case M_SP_COURT:
362 case M_SP_LAIR:
363 m_status_set(m,HOSTILE);
364 monster_action(m, m->specialf);
365 }
366 }
367 }
368
369
370
371
372
373
374
monster_move(m)375 void monster_move(m)
376 struct monster *m;
377 {
378 monster_action(m,m->movef);
379 }
380
381
382
383
384
385
386
387
388
monster_strike(m)389 void monster_strike(m)
390 struct monster *m;
391 {
392 if (player_on_sanctuary())
393 print1("The aegis of your deity protects you!");
394 else {
395 /* It's lawful to wait to be attacked */
396 if (m->attacked==0) Player.alignment++;
397 m->attacked++;
398 monster_action(m,m->strikef);
399 }
400 }
401
monster_special(m)402 void monster_special(m)
403 struct monster *m;
404 {
405 /* since many special functions are really attacks, cancel them
406 all if on sanctuary */
407 if (! player_on_sanctuary())
408 monster_action(m,m->specialf);
409 }
410
411
monster_talk(m)412 void monster_talk(m)
413 struct monster *m;
414 {
415 monster_action(m,m->talkf);
416 }
417
monster_action(m,action)418 void monster_action(m,action)
419 struct monster *m;
420 int action;
421 {
422 int meleef;
423 if ((action >= M_MELEE_NORMAL) && (action < M_MOVE_NORMAL)) {
424 /* kluge allows multiple attack forms */
425 if (distance(m->x,m->y,Player.x,Player.y)<2) {
426 meleef = m->meleef;
427 m->meleef = action;
428 tacmonster(m);
429 m->meleef = meleef;
430 }
431 }
432 else switch(action) {
433
434 case M_NO_OP:m_no_op(m); break;
435
436 case M_MOVE_NORMAL:m_normal_move(m); break;
437 case M_MOVE_FLUTTER:m_flutter_move(m); break;
438 case M_MOVE_FOLLOW:m_follow_move(m); break;
439 case M_MOVE_TELEPORT:m_teleport(m); break;
440 case M_MOVE_RANDOM:m_random_move(m); break;
441 case M_MOVE_SMART:m_smart_move(m); break;
442 case M_MOVE_SPIRIT:m_spirit_move(m); break;
443 case M_MOVE_CONFUSED:m_confused_move(m); break;
444 case M_MOVE_SCAREDY:m_scaredy_move(m); break;
445 case M_MOVE_ANIMAL:m_move_animal(m); break;
446 case M_MOVE_LEASH:m_move_leash(m); break;
447
448 case M_STRIKE_MISSILE:m_nbolt(m); break;
449 case M_STRIKE_FBOLT:m_firebolt(m); break;
450 case M_STRIKE_LBALL:m_lball(m); break;
451 case M_STRIKE_FBALL:m_fireball(m); break;
452 case M_STRIKE_SNOWBALL:m_snowball(m); break;
453 case M_STRIKE_BLIND:m_blind_strike(m); break;
454 case M_STRIKE_SONIC:m_strike_sonic(m); break;
455
456 case M_TALK_HORSE:m_talk_horse(m); break;
457 case M_TALK_THIEF:m_talk_thief(m);break;
458 case M_TALK_STUPID:m_talk_stupid(m); break;
459 case M_TALK_SILENT:m_talk_silent(m); break;
460 case M_TALK_HUNGRY:m_talk_hungry(m); break;
461 case M_TALK_GREEDY:m_talk_greedy(m); break;
462 case M_TALK_TITTER:m_talk_titter(m); break;
463 case M_TALK_MP:m_talk_mp(m); break;
464 case M_TALK_IM:m_talk_im(m); break;
465 case M_TALK_MAN:m_talk_man(m); break;
466 case M_TALK_ROBOT:m_talk_robot(m); break;
467 case M_TALK_EVIL:m_talk_evil(m); break;
468 case M_TALK_GUARD:m_talk_guard(m); break;
469 case M_TALK_MIMSY:m_talk_mimsy(m); break;
470 case M_TALK_SLITHY:m_talk_slithy(m); break;
471 case M_TALK_BURBLE:m_talk_burble(m); break;
472 case M_TALK_BEG:m_talk_beg(m); break;
473 case M_TALK_HINT:m_talk_hint(m); break;
474 case M_TALK_EF:m_talk_ef(m); break;
475 case M_TALK_GF:m_talk_gf(m); break;
476 case M_TALK_SEDUCTOR:m_talk_seductor(m); break;
477 case M_TALK_DEMONLOVER:m_talk_demonlover(m); break;
478 case M_TALK_NINJA:m_talk_ninja(m); break;
479 case M_TALK_ASSASSIN:m_talk_assassin(m); break;
480 case M_TALK_SERVANT: m_talk_servant(m); break;
481 case M_TALK_ANIMAL: m_talk_animal(m); break;
482 case M_TALK_SCREAM: m_talk_scream(m); break;
483 case M_TALK_PARROT: m_talk_parrot(m); break;
484 case M_TALK_HYENA: m_talk_hyena(m); break;
485 case M_TALK_DRUID: m_talk_druid(m); break;
486 case M_TALK_ARCHMAGE: m_talk_archmage(m); break;
487 case M_TALK_MERCHANT: m_talk_merchant(m); break;
488 case M_TALK_PRIME: m_talk_prime(m); break;
489
490 case M_SP_BOG:m_sp_bogthing(m); break;
491 case M_SP_WERE:m_sp_were(m); break;
492 case M_SP_WHISTLEBLOWER:m_sp_whistleblower(m); break;
493 case M_SP_MERCHANT:m_sp_merchant(m); break;
494 case M_SP_SURPRISE:m_sp_surprise(m); break;
495 case M_SP_MP:m_sp_mp(m); break;
496 case M_SP_THIEF:m_thief_f(m); break;
497 case M_SP_DEMONLOVER:m_sp_demonlover(m); break;
498 case M_SP_AGGRAVATE:m_aggravate(m); break;
499 case M_SP_POISON_CLOUD:m_sp_poison_cloud(m); break;
500 case M_SP_HUGE:m_huge_sounds(m); break;
501 case M_SP_SUMMON:m_summon(m); break;
502 case M_SP_ILLUSION:m_illusion(m); break;
503 case M_SP_ESCAPE:m_sp_escape(m); break;
504 case M_SP_FLUTTER:m_flutter_move(m); break;
505 case M_SP_EXPLODE:m_sp_explode(m); break;
506 case M_SP_DEMON:m_sp_demon(m); break;
507 case M_SP_ACID_CLOUD:m_sp_acid_cloud(m); break;
508 case M_SP_GHOST:m_sp_ghost(m); break;
509 case M_SP_SPELL:m_sp_spell(m); break;
510 case M_SP_SEDUCTOR:m_sp_seductor(m); break;
511 case M_SP_EATER:m_sp_eater(m); break;
512 case M_SP_DRAGONLORD:m_sp_dragonlord(m); break;
513 case M_SP_BLACKOUT:m_sp_blackout(m); break;
514 case M_SP_SWARM: m_sp_swarm(m); break;
515 case M_SP_ANGEL: m_sp_angel(m); break;
516 case M_SP_SERVANT: m_sp_servant(m); break;
517 case M_SP_AV: m_sp_av(m); break;
518 case M_SP_LW: m_sp_lw(m); break;
519 case M_SP_MB: m_sp_mb(m); break;
520 case M_SP_RAISE: m_sp_raise(m); break;
521 case M_SP_MIRROR: m_sp_mirror(m); break;
522 case M_SP_COURT: m_sp_court(m); break;
523 case M_SP_LAIR: m_sp_lair(m); break;
524 case M_SP_PRIME: m_sp_prime(m); break;
525 }
526 }
527
528 /* makes one of the highscore npcs */
make_hiscore_npc(npc,npcid)529 void make_hiscore_npc(npc,npcid)
530 pmt npc;
531 int npcid;
532 {
533 int st = -1;
534 pob ob;
535 *npc = Monsters[HISCORE_NPC];
536 npc->aux2 = npcid;
537 /* each of the high score npcs can be created here */
538 switch(npcid) {
539 case 0:
540 strcpy(Str2,Hiscorer);
541 determine_npc_behavior(npc,Hilevel,Hibehavior);
542 break;
543 case 1: case 2: case 3: case 4: case 5: case 6:
544 strcpy(Str2,Priest[npcid]);
545 determine_npc_behavior(npc,Priestlevel[npcid],Priestbehavior[npcid]);
546 st = ARTIFACTID+13+npcid; /* appropriate holy symbol... */
547 Objects[st].uniqueness = UNIQUE_MADE;
548 if (npcid == DRUID)
549 npc->talkf = M_TALK_DRUID;
550 if (Player.patron == npcid)
551 m_status_reset(npc, HOSTILE);
552 break;
553 case 7:
554 strcpy(Str2,Shadowlord);
555 determine_npc_behavior(npc,Shadowlordlevel,Shadowlordbehavior);
556 break;
557 case 8:
558 strcpy(Str2,Commandant);
559 determine_npc_behavior(npc,Commandantlevel,Commandantbehavior);
560 if (Player.rank[LEGION])
561 m_status_reset(npc, HOSTILE);
562 break;
563 case 9:
564 strcpy(Str2,Archmage);
565 determine_npc_behavior(npc,Archmagelevel,Archmagebehavior);
566 st = ARTIFACTID+9; /* kolwynia */
567 npc->talkf = M_TALK_ARCHMAGE;
568 m_status_reset(npc, WANDERING);
569 m_status_reset(npc, HOSTILE);
570 break;
571 case 10:
572 strcpy(Str2,Prime);
573 determine_npc_behavior(npc,Primelevel,Primebehavior);
574 npc->talkf = M_TALK_PRIME;
575 npc->specialf = M_SP_PRIME;
576 if (Player.alignment < 0)
577 m_status_reset(npc, HOSTILE);
578 break;
579 case 11:
580 strcpy(Str2,Champion);
581 determine_npc_behavior(npc,Championlevel,Championbehavior);
582 if (Player.rank[ARENA])
583 m_status_reset(npc, HOSTILE);
584 break;
585 case 12:
586 strcpy(Str2,Duke);
587 determine_npc_behavior(npc,Dukelevel,Dukebehavior);
588 break;
589 case 13:
590 strcpy(Str2,Chaoslord);
591 determine_npc_behavior(npc,Chaoslordlevel,Chaoslordbehavior);
592 if (Player.alignment < 0 && random_range(2))
593 m_status_reset(npc, HOSTILE);
594 break;
595 case 14:
596 strcpy(Str2,Lawlord);
597 determine_npc_behavior(npc,Lawlordlevel,Lawlordbehavior);
598 if (Player.alignment > 0)
599 m_status_reset(npc, HOSTILE);
600 break;
601 case 15:
602 strcpy(Str2,Justiciar);
603 determine_npc_behavior(npc,Justiciarlevel,Justiciarbehavior);
604 st = THINGID+16; /* badge */
605 npc->talkf = M_TALK_GUARD;
606 npc->specialf = M_SP_WHISTLEBLOWER;
607 m_status_reset(npc, WANDERING);
608 m_status_reset(npc, HOSTILE);
609 break;
610 }
611 if (st > -1 && Objects[st].uniqueness == UNIQUE_MADE) {
612 ob = ((pob) checkmalloc(sizeof(objtype)));
613 *ob = Objects[st];
614 m_pickup(npc,ob);
615 }
616 npc->monstring = salloc(Str2);
617 strcpy(Str1,"The body of ");
618 strcat(Str1,Str2);
619 npc->corpsestr = salloc(Str1);
620 }
621
622
623
624
625 /* sets npc behavior given level and behavior code */
determine_npc_behavior(npc,level,behavior)626 void determine_npc_behavior(npc,level,behavior)
627 pmt npc;
628 int level,behavior;
629 {
630 int combatype,competence,talktype;
631 npc->hp = (level+1)*20;
632 npc->status = AWAKE+MOBILE+WANDERING;
633 combatype = (behavior % 100) / 10;
634 competence = (behavior % 1000) / 100;
635 talktype = behavior / 1000;
636 npc->level = competence;
637 if (npc->level < 2*difficulty()) npc->status += HOSTILE;
638 npc->xpv = npc->level*20;
639 switch (combatype) {
640 case 1: /* melee */
641 npc->meleef = M_MELEE_NORMAL;
642 npc->dmg = competence*5;
643 npc->hit = competence*3;
644 npc->speed = 3;
645 break;
646 case 2: /*missile*/
647 npc->meleef = M_MELEE_NORMAL;
648 npc->strikef = M_STRIKE_MISSILE;
649 npc->dmg = competence*3;
650 npc->hit = competence*2;
651 npc->speed = 4;
652 break;
653 case 3: /* spellcasting */
654 npc->meleef = M_MELEE_NORMAL;
655 npc->dmg = competence;
656 npc->hit = competence;
657 npc->specialf = M_SP_SPELL;
658 npc->speed = 6;
659 break;
660 case 4: /* thievery */
661 npc->meleef = M_MELEE_NORMAL;
662 npc->dmg = competence;
663 npc->hit = competence;
664 npc->specialf=M_SP_THIEF;
665 npc->speed = 3;
666 break;
667 case 5: /* flee */
668 npc->dmg = competence;
669 npc->hit = competence;
670 npc->meleef = M_MELEE_NORMAL;
671 npc->specialf = M_MOVE_SCAREDY;
672 npc->speed = 3;
673 break;
674 }
675 if (npc->talkf == M_TALK_MAN)
676 switch (talktype) {
677 case 1: npc->talkf = M_TALK_EVIL; break;
678 case 2: npc->talkf = M_TALK_MAN; break;
679 case 3: npc->talkf = M_TALK_HINT; break;
680 case 4: npc->talkf = M_TALK_BEG; break;
681 case 5: npc->talkf = M_TALK_SILENT; break;
682 default: mprint("Say Whutt? (npc talk weirdness)"); break;
683 }
684 npc->uniqueness = UNIQUE_MADE;
685 }
686
687
688 /* makes an ordinary npc (maybe undead) */
make_log_npc(npc)689 void make_log_npc(npc)
690 struct monster *npc;
691 {
692 int i,n;
693 int behavior,status,level;
694 FILE *fd;
695
696 /* in case the log file is null */
697 behavior = 2718;
698 level = 1;
699 status = 2;
700 strcpy(Str2,"Malaprop the Misnamed");
701
702 strcpy(Str1,Omegalib);
703 strcat(Str1,"omega.log");
704 fd = checkfopen(Str1,"r");
705 n = 1;
706 while(fgets(Str1,STRING_LEN, fd)) {
707 if (random_range(n) == 0) { /* this algo. from Knuth 2 - cute, eh? */
708 sscanf(Str1,"%d %d %d",&status,&level,&behavior);
709 for (i = 0; (Str1[i] < 'a' || Str1[i] > 'z') &&
710 (Str1[i] < 'A' || Str1[i] > 'Z'); i++)
711 ;
712 strcpy(Str2, Str1 + i);
713 Str2[strlen(Str2) - 1] = '\0'; /* 'cos fgets reads in the \n */
714 }
715 n++;
716 }
717 fclose(fd);
718 npc->hp = level*20;
719 if (status==1) {
720 if (level < 3) {
721 *npc = Monsters[GHOST];
722 strcpy(Str1,"ghost named ");
723 }
724 else if (level < 7) {
725 *npc = Monsters[HAUNT];
726 strcpy(Str1,"haunt named ");
727 }
728 else if (level < 12) {
729 *npc = Monsters[SPECTRE];
730 strcpy(Str1,"spectre named ");
731 }
732 else {
733 *npc = Monsters[LICHE];
734 strcpy(Str1,"lich named ");
735 }
736 strcat(Str1,Str2);
737 npc->monstring = salloc(Str1);
738 strcpy(Str3,"the mortal remains of ");
739 strcat(Str3,Str2);
740 npc->corpsestr = salloc(Str3);
741 }
742 else {
743 npc->monstring=salloc(Str2);
744 strcpy(Str3,"the corpse of ");
745 strcat(Str3,Str2);
746 npc->corpsestr = salloc(Str3);
747 }
748 determine_npc_behavior(npc,level,behavior);
749 }
750
751
752
753
754
m_trap_dart(m)755 void m_trap_dart(m)
756 struct monster *m;
757 {
758 if (los_p(m->x,m->y,Player.x,Player.y)) {
759 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
760 else {
761 strcpy(Str1,"The ");
762 strcat(Str1,m->monstring);
763 }
764 strcat(Str1," was hit by a dart!");
765 mprint(Str1);
766 Level->site[m->x][m->y].locchar = TRAP;
767 lset(m->x, m->y, CHANGED);
768 }
769 m_damage(m,difficulty()*2,NORMAL_DAMAGE);
770 }
771
m_trap_pit(m)772 void m_trap_pit(m)
773 struct monster *m;
774 {
775 if (los_p(m->x,m->y,Player.x,Player.y)) {
776 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
777 else {
778 strcpy(Str1,"The ");
779 strcat(Str1,m->monstring);
780 }
781 strcat(Str1," fell into a pit!");
782 mprint(Str1);
783 Level->site[m->x][m->y].locchar = TRAP;
784 lset(m->x, m->y, CHANGED);
785 }
786 if (! m_statusp(m,INTANGIBLE))
787 m_status_reset(m,MOBILE);
788 m_damage(m,difficulty()*5,NORMAL_DAMAGE);
789
790 }
791
m_trap_door(m)792 void m_trap_door(m)
793 struct monster *m;
794 {
795 if (los_p(m->x,m->y,Player.x,Player.y)) {
796 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
797 else {
798 strcpy(Str1,"The ");
799 strcat(Str1,m->monstring);
800 }
801 strcat(Str1," fell into a trap door!");
802 mprint(Str1);
803 Level->site[m->x][m->y].locchar = TRAP;
804 lset(m->x, m->y, CHANGED);
805 }
806 m_vanish(m);
807 }
808
m_trap_abyss(m)809 void m_trap_abyss(m)
810 struct monster *m;
811 {
812 char Str1[80];
813 if (los_p(m->x,m->y,Player.x,Player.y)) {
814 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
815 else {
816 strcpy(Str1,"The ");
817 strcat(Str1,m->monstring);
818 }
819 strcat(Str1," fell into the infinite abyss!");
820 mprint(Str1);
821 Level->site[m->x][m->y].locchar = ABYSS;
822 lset(m->x, m->y, CHANGED);
823 Level->site[m->x][m->y].p_locf = L_ABYSS;
824 lset(m->x, m->y, CHANGED);
825 }
826 setgamestatus(SUPPRESS_PRINTING);
827 m_vanish(m);
828 resetgamestatus(SUPPRESS_PRINTING);
829 }
830
m_trap_snare(m)831 void m_trap_snare(m)
832 struct monster *m;
833 {
834 char Str1[80];
835 Level->site[m->x][m->y].locchar = TRAP;
836 lset(m->x, m->y, CHANGED);
837 if (los_p(m->x,m->y,Player.x,Player.y)) {
838 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
839 else {
840 strcpy(Str1,"The ");
841 strcat(Str1,m->monstring);
842 }
843 strcat(Str1," was caught in a snare!");
844 mprint(Str1);
845 }
846 if (! m_statusp(m,INTANGIBLE)) m_status_reset(m,MOBILE);
847 }
848
m_trap_blade(m)849 void m_trap_blade(m)
850 struct monster *m;
851 {
852 char Str1[80];
853 Level->site[m->x][m->y].locchar = TRAP;
854 lset(m->x, m->y, CHANGED);
855 if (los_p(m->x,m->y,Player.x,Player.y)) {
856 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
857 else {
858 strcpy(Str1,"The ");
859 strcat(Str1,m->monstring);
860 }
861 strcat(Str1," was hit by a blade trap!");
862 mprint(Str1); }
863 m_damage(m,(difficulty()+1)*7-Player.defense,NORMAL_DAMAGE);
864 }
865
m_trap_fire(m)866 void m_trap_fire(m)
867 struct monster *m;
868 {
869 char Str1[80];
870 Level->site[m->x][m->y].locchar = TRAP;
871 lset(m->x, m->y, CHANGED);
872 if (los_p(m->x,m->y,Player.x,Player.y)) {
873 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
874 else {
875 strcpy(Str1,"The ");
876 strcat(Str1,m->monstring);
877 }
878 strcat(Str1," was hit by a fire trap!");
879 mprint(Str1);
880 }
881 m_damage(m,(difficulty()+1)*5,FLAME);
882 }
883
884
m_fire(m)885 void m_fire(m)
886 struct monster *m;
887 {
888 char Str1[80];
889 if (los_p(m->x,m->y,Player.x,Player.y)) {
890 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
891 else {
892 strcpy(Str1,"The ");
893 strcat(Str1,m->monstring);
894 }
895 strcat(Str1," was blasted by fire!");
896 mprint(Str1);
897 }
898 m_damage(m,random_range(100),FLAME);
899 }
900
m_trap_teleport(m)901 void m_trap_teleport(m)
902 struct monster *m;
903 {
904 char Str1[80];
905 Level->site[m->x][m->y].locchar = TRAP;
906 lset(m->x, m->y, CHANGED);
907 if (los_p(m->x,m->y,Player.x,Player.y)) {
908 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
909 else {
910 strcpy(Str1,"The ");
911 strcat(Str1,m->monstring);
912 }
913 strcat(Str1," walked into a teleport trap!");
914 mprint(Str1);
915 }
916 m_teleport(m);
917 }
918
m_trap_disintegrate(m)919 void m_trap_disintegrate(m)
920 struct monster *m;
921 {
922 char Str1[80];
923 if (los_p(m->x,m->y,Player.x,Player.y)) {
924 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
925 else {
926 strcpy(Str1,"The ");
927 strcat(Str1,m->monstring);
928 }
929 strcat(Str1," walked into a disintegration trap!");
930 mprint(Str1);
931 Level->site[m->x][m->y].locchar = TRAP;
932 lset(m->x, m->y, CHANGED);
933 }
934 disintegrate(m->x,m->y);
935 }
936
m_trap_sleepgas(m)937 void m_trap_sleepgas(m)
938 struct monster *m;
939 {
940 char Str1[80];
941 if (los_p(m->x,m->y,Player.x,Player.y)) {
942 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
943 else {
944 strcpy(Str1,"The ");
945 strcat(Str1,m->monstring);
946 }
947 strcat(Str1," walked into a sleepgas trap!");
948 mprint(Str1);
949 Level->site[m->x][m->y].locchar = TRAP;
950 lset(m->x, m->y, CHANGED);
951 }
952 if (! m_immunityp(m,SLEEP)) m_status_reset(m,AWAKE);
953 }
954
m_trap_acid(m)955 void m_trap_acid(m)
956 struct monster *m;
957 {
958 char Str1[80];
959 if (los_p(m->x,m->y,Player.x,Player.y)) {
960 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
961 else {
962 strcpy(Str1,"The ");
963 strcat(Str1,m->monstring);
964 }
965 strcat(Str1," walked into an acid bath trap!");
966 mprint(Str1);
967 Level->site[m->x][m->y].locchar = TRAP;
968 lset(m->x, m->y, CHANGED);
969 }
970 m_damage(m,random_range(difficulty()*difficulty()),ACID);
971 }
972
m_trap_manadrain(m)973 void m_trap_manadrain(m)
974 struct monster *m;
975 {
976 char Str1[80];
977 if (los_p(m->x,m->y,Player.x,Player.y)) {
978 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
979 else {
980 strcpy(Str1,"The ");
981 strcat(Str1,m->monstring);
982 }
983 strcat(Str1," walked into a manadrain trap!");
984 mprint(Str1);
985 Level->site[m->x][m->y].locchar = TRAP;
986 lset(m->x, m->y, CHANGED);
987 }
988 if (m->specialf == M_SP_SPELL) m->specialf = M_NO_OP;
989 }
990
991
m_water(m)992 void m_water(m)
993 struct monster *m;
994 {
995 char Str1[80];
996 if ((! m_statusp(m,INTANGIBLE)) &&
997 (! m_statusp(m,SWIMMING)) &&
998 (! m_statusp(m,ONLYSWIM))) {
999 if (los_p(m->x,m->y,Player.x,Player.y)) {
1000 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
1001 else {
1002 strcpy(Str1,"The ");
1003 strcat(Str1,m->monstring);
1004 }
1005 strcat(Str1," drowned!");
1006 mprint(Str1);
1007 }
1008 m_death(m);
1009 }
1010 }
1011
1012
m_abyss(m)1013 void m_abyss(m)
1014 struct monster *m;
1015 {
1016 char Str1[80];
1017 if (los_p(m->x,m->y,Player.x,Player.y)) {
1018 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
1019 else {
1020 strcpy(Str1,"The ");
1021 strcat(Str1,m->monstring);
1022 }
1023 strcat(Str1," fell into the infinite abyss!");
1024 mprint(Str1);
1025 }
1026 m_vanish(m);
1027 }
1028
1029
1030
m_lava(m)1031 void m_lava(m)
1032 struct monster *m;
1033 {
1034 char Str1[80];
1035 if ((! m_immunityp(m,FLAME)) ||
1036 ((! m_statusp(m,SWIMMING))&& (! m_statusp(m,ONLYSWIM)))) {
1037 if (los_p(m->x,m->y,Player.x,Player.y)) {
1038 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
1039 else {
1040 strcpy(Str1,"The ");
1041 strcat(Str1,m->monstring);
1042 }
1043 strcat(Str1," died in a pool of lava!");
1044 mprint(Str1);
1045 }
1046 m_death(m);
1047 }
1048 }
1049
m_altar(m)1050 void m_altar(m)
1051 struct monster *m;
1052 {
1053 int visible = view_los_p(Player.x,Player.y,m->x,m->y);
1054 int reaction = 0;
1055 int altar = Level->site[m->x][m->y].aux;
1056
1057 if (visible) {
1058 if (m->uniqueness != COMMON) strcpy(Str1,m->monstring);
1059 else {
1060 strcpy(Str1,"The ");
1061 strcat(Str1,m->monstring);
1062 }
1063 strcat(Str1," walks next to an altar...");
1064 mprint(Str1);
1065 }
1066 if (!m_statusp(m, HOSTILE))
1067 reaction = 0;
1068 else if (m->id == HISCORE_NPC && m->aux2 == altar)
1069 reaction = 1; /* high priest of same deity */
1070 else if ((m->id == ANGEL || m->id == HIGH_ANGEL || m->id == ARCHANGEL) &&
1071 m->aux1 == altar)
1072 reaction = 1; /* angel of same deity */
1073 else if (altar == Player.patron)
1074 reaction = -1; /* friendly deity will zap hostile monster */
1075 else if (((Player.patron == ODIN || Player.patron == ATHENA) &&
1076 (altar == SET || altar == HECATE)) ||
1077 ((Player.patron == SET || Player.patron == HECATE) &&
1078 (altar == ODIN || altar == ATHENA)))
1079 reaction = 1; /* hostile deity will help hostile monster */
1080 switch (reaction) {
1081 case -1:
1082 if (visible) {
1083 mprint("Your deity is angry!");
1084 mprint("A bolt of godsfire strikes the monster....");
1085 }
1086 disrupt(m->x,m->y,Player.rank[PRIESTHOOD]*50);
1087 break;
1088 case 1:
1089 if (visible) {
1090 mprint("The deity of the altar smiles on the monster....");
1091 mprint("A shaft of light zaps the altar...");
1092 }
1093 m->hp = Monsters[m->id].hp*2;
1094 break;
1095 default:
1096 if (visible)
1097 mprint("but nothing much seems to happen");
1098 break;
1099 }
1100 }
1101
1102
mantype()1103 char *mantype()
1104 {
1105 switch(random_range(20)) {
1106 case 0: return "janitor";
1107 case 1: return "beggar";
1108 case 2: return "barbarian";
1109 case 3: return "hairdresser";
1110 case 4: return "accountant";
1111 case 5: return "lawyer";
1112 case 6: return "indian chief";
1113 case 7: return "tinker";
1114 case 8: return "tailor";
1115 case 9: return "soldier";
1116 case 10: return "spy";
1117 case 11: return "doctor";
1118 case 12: return "miner";
1119 case 13: return "noble";
1120 case 14: return "serf";
1121 case 15: return "neer-do-well";
1122 case 16: return "vendor";
1123 case 17: return "dilettante";
1124 case 18: return "surveyor";
1125 default:
1126 case 19: return "jongleur";
1127 }
1128 }
1129
1130
strengthen_death(m)1131 void strengthen_death(m)
1132 struct monster *m;
1133 {
1134 pol ol = ((pol)checkmalloc(sizeof(oltype)));
1135 pob scythe = ((pob)checkmalloc(sizeof(objtype)));
1136 #ifdef MSDOS_SUPPORTED_ANTIQUE
1137 unsigned tmp;
1138 #endif
1139 m->xpv += min(10000,m->xpv+1000);
1140 m->hit += min(1000,m->hit+10);
1141 m->dmg = min(10000,m->dmg*2);
1142 m->ac += min(1000,m->ac+10);
1143 m->speed = max(m->speed-1,1);
1144 m->movef = M_MOVE_SMART;
1145 #ifndef MSDOS_SUPPORTED_ANTIQUE
1146 m->hp = min(100000,100+m->dmg*10);
1147 #else
1148 /* In order not to have to make the hp's into longs or unsigned,
1149 which would involve lots of changes, I'll make it max out at 30000. */
1150 tmp = 100+m->dmg*10;
1151 m->hp = (tmp > 30000) ? 30000 : tmp;
1152 #endif
1153 *scythe = Objects[WEAPONID+39];
1154 ol->thing = scythe;
1155 ol->next = NULL;
1156 m->possessions = ol;
1157 }
1158
1159
1160
1161
m_no_op(m)1162 void m_no_op(m)
1163 struct monster *m;
1164 {
1165 }
1166