ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/monster.C
Revision: 1.27
Committed: Mon Apr 30 04:25:30 2007 UTC (17 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.26: +33 -37 lines
Log Message:
This is the first rough cut of the skill use system (use the STABLE tag).

Details will likely change, and combat skills do not work very well, but
it works quite well.

Players no longer have a shoottype or range slots, instead, each player
has these members:

   combat_skill/combat_ob  the currently selected skill (and weapon)
                           for direct attacks.
   ranged_skill/ranged_ob  the currently selected ranged skill (and
                           bow/spell/item)
   golem                   the currently-controlled golem, if any.

File Contents

# Content
1 /*
2 * CrossFire, A Multiplayer game for X-windows
3 *
4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
5 * Copyright (C) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (C) 1992 Frank Tore Johansen
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * The authors can be reached via e-mail at <crossfire@schmorp.de>
23 */
24
25 #include <global.h>
26 #include <sproto.h>
27 #include <spells.h>
28 #include <skills.h>
29
30 #define MIN_MON_RADIUS 3 /* minimum monster detection radius */
31
32 /* checks npc->enemy and returns that enemy if still valid,
33 * NULL otherwise.
34 * this is map tile aware.
35 * If this returns an enemy, the range vector rv should also be
36 * set to sane values.
37 */
38 object *
39 check_enemy (object *npc, rv_vector * rv)
40 {
41
42 /* if this is pet, let him attack the same enemy as his owner
43 * TODO: when there is no ower enemy, try to find a target,
44 * which CAN attack the owner. */
45 if ((npc->attack_movement & HI4) == PETMOVE)
46 {
47 if (npc->owner == NULL)
48 npc->enemy = NULL;
49 else if (npc->enemy == NULL)
50 npc->enemy = npc->owner->enemy;
51 }
52
53 /* periodically, a monster mayu change its target. Also, if the object
54 * has been destroyed, etc, clear the enemy.
55 * TODO: this should be changed, because it invokes to attack forced or
56 * attacked monsters to leave the attacker alone, before it is destroyed
57 */
58 /* i had removed the random target leave, this invokes problems with friendly
59 * objects, getting attacked and defending herself - they don't try to attack
60 * again then but perhaps get attack on and on
61 * If we include a aggravated flag in , we can handle evil vs evil and good vs good
62 * too. */
63
64 if (npc->enemy)
65 {
66 /* I broke these if's apart to better be able to see what
67 * the grouping checks are. Code is the same.
68 */
69 if (QUERY_FLAG (npc->enemy, FLAG_REMOVED) ||
70 QUERY_FLAG (npc->enemy, FLAG_FREED) ||
71 !on_same_map (npc, npc->enemy) || npc == npc->enemy || QUERY_FLAG (npc, FLAG_NEUTRAL) || QUERY_FLAG (npc->enemy, FLAG_NEUTRAL))
72 npc->enemy = NULL;
73
74 else if (QUERY_FLAG (npc, FLAG_FRIENDLY) && ((QUERY_FLAG (npc->enemy, FLAG_FRIENDLY)
75 && !(should_arena_attack (npc, npc->owner, npc->enemy)))
76 || ((npc->enemy->type == PLAYER) && !(should_arena_attack (npc, npc->owner, npc->enemy)))
77 || npc->enemy == npc->owner))
78 npc->enemy = NULL;
79
80
81 else if (!QUERY_FLAG (npc, FLAG_FRIENDLY) && (!QUERY_FLAG (npc->enemy, FLAG_FRIENDLY) && npc->enemy->type != PLAYER))
82 npc->enemy = NULL;
83
84 /* I've noticed that pets could sometimes get an arrow as the
85 * target enemy - this code below makes sure the enemy is something
86 * that should be attacked. My guess is that the arrow hits
87 * the creature/owner, and so the creature then takes that
88 * as the enemy to attack.
89 */
90 else if (!QUERY_FLAG (npc->enemy, FLAG_MONSTER)
91 && !QUERY_FLAG (npc->enemy, FLAG_GENERATOR)
92 && npc->enemy->type != PLAYER
93 && npc->enemy->type != GOLEM)
94 npc->enemy = NULL;
95
96 }
97 return can_detect_enemy (npc, npc->enemy, rv) ? npc->enemy : NULL;
98 }
99
100 /* Returns the nearest living creature (monster or generator).
101 * Modified to deal with tiled maps properly.
102 * Also fixed logic so that monsters in the lower directions were more
103 * likely to be skipped - instead of just skipping the 'start' number
104 * of direction, revisit them after looking at all the other spaces.
105 *
106 * Note that being this may skip some number of spaces, it will
107 * not necessarily find the nearest living creature - it basically
108 * chooses one from within a 3 space radius, and since it skips
109 * the first few directions, it could very well choose something
110 * 3 spaces away even though something directly north is closer.
111 *
112 * this function is map tile aware.
113 */
114 object *
115 find_nearest_living_creature (object *npc)
116 {
117 int i, mflags;
118 sint16 nx, ny;
119 maptile *m;
120 int search_arr[SIZEOFFREE];
121
122 get_search_arr (search_arr);
123
124 for (i = 0; i < SIZEOFFREE; i++)
125 {
126 /* modified to implement smart searching using search_arr
127 * guidance array to determine direction of search order
128 */
129 nx = npc->x + freearr_x[search_arr[i]];
130 ny = npc->y + freearr_y[search_arr[i]];
131 m = npc->map;
132
133 mflags = get_map_flags (m, &m, nx, ny, &nx, &ny);
134
135 if (mflags & P_OUT_OF_MAP)
136 continue;
137
138 if (mflags & P_IS_ALIVE)
139 {
140 for (object *tmp = m->at (nx, ny).top; tmp; tmp = tmp->below)
141 if (tmp->flag [FLAG_MONSTER] || tmp->flag [FLAG_GENERATOR] || tmp->type == PLAYER)
142 if (can_see_monsterP (m, nx, ny, i))
143 return tmp;
144 }
145 }
146
147 return 0;
148 }
149
150
151 /* Tries to find an enmy for npc. We pass the range vector since
152 * our caller will find the information useful.
153 * Currently, only move_monster calls this function.
154 * Fix function so that we always make calls to get_rangevector
155 * if we have a valid target - function as not doing so in
156 * many cases.
157 */
158
159 object *
160 find_enemy (object *npc, rv_vector * rv)
161 {
162 object *attacker, *tmp = NULL;
163
164 attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */
165 npc->attacked_by = 0; /* always clear the attacker entry */
166
167 /* if we berserk, we don't care about others - we attack all we can find */
168 if (QUERY_FLAG (npc, FLAG_BERSERK))
169 {
170 tmp = find_nearest_living_creature (npc);
171
172 if (tmp)
173 get_rangevector (npc, tmp, rv, 0);
174 return tmp;
175 }
176
177 /* Here is the main enemy selection.
178 * We want this: if there is an enemy, attack him until its not possible or
179 * one of both is dead.
180 * If we have no enemy and we are...
181 * a monster: try to find a player, a pet or a friendly monster
182 * a friendly: only target a monster which is targeting you first or targeting a player
183 * a neutral: fight a attacker (but there should be none), then do nothing
184 * a pet: attack player enemy or a monster
185 */
186
187 /* pet move */
188 if ((npc->attack_movement & HI4) == PETMOVE)
189 {
190 tmp = get_pet_enemy (npc, rv);
191
192 if (tmp)
193 get_rangevector (npc, tmp, rv, 0);
194
195 return tmp;
196 }
197
198 /* we check our old enemy. */
199 if (!(tmp = check_enemy (npc, rv)))
200 {
201 if (attacker) /* if we have an attacker, check him */
202 {
203 /* TODO: thats not finished */
204 /* we don't want a fight evil vs evil or good against non evil */
205
206 if (QUERY_FLAG (npc, FLAG_NEUTRAL) || QUERY_FLAG (attacker, FLAG_NEUTRAL) || /* neutral */
207 (QUERY_FLAG (npc, FLAG_FRIENDLY) && QUERY_FLAG (attacker, FLAG_FRIENDLY)) ||
208 (!QUERY_FLAG (npc, FLAG_FRIENDLY) && (!QUERY_FLAG (attacker, FLAG_FRIENDLY) && attacker->type != PLAYER)))
209 CLEAR_FLAG (npc, FLAG_SLEEP); /* skip it, but lets wakeup */
210 else if (on_same_map (npc, attacker)) /* thats the only thing we must know... */
211 {
212 CLEAR_FLAG (npc, FLAG_SLEEP); /* well, NOW we really should wake up! */
213 npc->enemy = attacker;
214 return attacker; /* yes, we face our attacker! */
215 }
216 }
217
218 /* we have no legal enemy or attacker, so we try to target a new one */
219 if (!QUERY_FLAG (npc, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (npc, FLAG_FRIENDLY) && !QUERY_FLAG (npc, FLAG_NEUTRAL))
220 {
221 npc->enemy = get_nearest_player (npc);
222 if (npc->enemy)
223 tmp = check_enemy (npc, rv);
224 }
225
226 }
227
228 return tmp;
229 }
230
231 /* Sees if this monster should wake up.
232 * Currently, this is only called from move_monster, and
233 * if enemy is set, then so should be rv.
234 * returns 1 if the monster should wake up, 0 otherwise.
235 */
236
237 int
238 check_wakeup (object *op, object *enemy, rv_vector * rv)
239 {
240 int radius = op->stats.Wis > MIN_MON_RADIUS ? op->stats.Wis : MIN_MON_RADIUS;
241
242 /* Trim work - if no enemy, no need to do anything below */
243 if (!enemy)
244 return 0;
245
246 /* blinded monsters can only find nearby objects to attack */
247 if (QUERY_FLAG (op, FLAG_BLIND))
248 radius = MIN_MON_RADIUS;
249
250 /* This covers the situation where the monster is in the dark
251 * and has an enemy. If the enemy has no carried light (or isnt
252 * glowing!) then the monster has trouble finding the enemy.
253 * Remember we already checked to see if the monster can see in
254 * the dark. */
255
256 else if (op->map && op->map->darkness > 0 && enemy && !enemy->invisible &&
257 !stand_in_light (enemy) && (!QUERY_FLAG (op, FLAG_SEE_IN_DARK) || !QUERY_FLAG (op, FLAG_SEE_INVISIBLE)))
258 {
259 int dark = radius / (op->map->darkness);
260
261 radius = (dark > MIN_MON_RADIUS) ? (dark + 1) : MIN_MON_RADIUS;
262 }
263 else if (!QUERY_FLAG (op, FLAG_SLEEP))
264 return 1;
265
266 /* enemy should already be on this map, so don't really need to check
267 * for that.
268 */
269 if (rv->distance < (unsigned int) (QUERY_FLAG (enemy, FLAG_STEALTH) ? (radius / 2) + 1 : radius))
270 {
271 CLEAR_FLAG (op, FLAG_SLEEP);
272 return 1;
273 }
274 return 0;
275 }
276
277 int
278 move_randomly (object *op)
279 {
280 int i;
281
282 /* Give up to 15 chances for a monster to move randomly */
283 for (i = 0; i < 15; i++)
284 {
285 if (move_object (op, rndm (8) + 1))
286 return 1;
287 }
288 return 0;
289 }
290
291 /*
292 * Move-monster returns 1 if the object has been freed, otherwise 0.
293 */
294
295 int
296 move_monster (object *op)
297 {
298 int dir, diff, pre_att_dir; /* elmex: pre_att_dir remembers the direction before attack movement */
299 object *owner, *enemy, *part, *oph = op;
300 rv_vector rv;
301
302 /* Monsters not on maps don't do anything. These monsters are things
303 * Like royal guards in city dwellers inventories.
304 */
305 if (!op->map)
306 return 0;
307
308 /* for target facing, we copy this value here for fast access */
309 if (oph->head) /* force update the head - one arch one pic */
310 oph = oph->head;
311
312 if (QUERY_FLAG (op, FLAG_NO_ATTACK)) /* we never ever attack */
313 enemy = op->enemy = NULL;
314 else if ((enemy = find_enemy (op, &rv)))
315 /* we have an enemy, just tell him we want him dead */
316 enemy->attacked_by = op; /* our ptr */
317
318 /* generate hp, if applicable */
319 if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp)
320 {
321
322 /* last heal is in funny units. Dividing by speed puts
323 * the regeneration rate on a basis of time instead of
324 * #moves the monster makes. The scaling by 8 is
325 * to capture 8th's of a hp fraction regens
326 *
327 * Cast to sint32 before comparing to maxhp since otherwise an (sint16)
328 * overflow might produce monsters with negative hp.
329 */
330
331 op->last_heal += (int) ((float) (8 * op->stats.Con) / FABS (op->speed));
332 op->stats.hp = MIN ((sint32) op->stats.hp + op->last_heal / 32, op->stats.maxhp); /* causes Con/4 hp/tick */
333 op->last_heal %= 32;
334
335 /* So if the monster has gained enough HP that they are no longer afraid */
336 if (QUERY_FLAG (op, FLAG_RUN_AWAY) && op->stats.hp >= (signed short) (((float) op->run_away / (float) 100) * (float) op->stats.maxhp))
337 CLEAR_FLAG (op, FLAG_RUN_AWAY);
338
339 if (op->stats.hp > op->stats.maxhp)
340 op->stats.hp = op->stats.maxhp;
341 }
342
343 /* generate sp, if applicable */
344 if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp)
345 {
346
347 /* last_sp is in funny units. Dividing by speed puts
348 * the regeneration rate on a basis of time instead of
349 * #moves the monster makes. The scaling by 8 is
350 * to capture 8th's of a sp fraction regens
351 *
352 * Cast to sint32 before comparing to maxhp since otherwise an (sint16)
353 * overflow might produce monsters with negative sp.
354 */
355
356 op->last_sp += (int) ((float) (8 * op->stats.Pow) / FABS (op->speed));
357 op->stats.sp = MIN (op->stats.sp + op->last_sp / 128, op->stats.maxsp); /* causes Pow/16 sp/tick */
358 op->last_sp %= 128;
359 }
360
361 /* this should probably get modified by many more values.
362 * (eg, creatures resistance to fear, level, etc. )
363 */
364 if (QUERY_FLAG (op, FLAG_SCARED) && !(rndm (20)))
365 {
366 CLEAR_FLAG (op, FLAG_SCARED); /* Time to regain some "guts"... */
367 }
368
369 if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy)))
370 return QUERY_FLAG (op, FLAG_FREED);
371
372 if (QUERY_FLAG (op, FLAG_SLEEP) || QUERY_FLAG (op, FLAG_BLIND) ||
373 ((op->map->darkness > 0) && !QUERY_FLAG (op, FLAG_SEE_IN_DARK) && !QUERY_FLAG (op, FLAG_SEE_INVISIBLE)))
374 {
375 if (!check_wakeup (op, enemy, &rv))
376 return 0;
377 }
378
379 /* check if monster pops out of hidden spot */
380 if (op->hide)
381 do_hidden_move (op);
382
383 if (op->pick_up)
384 monster_check_pickup (op);
385
386 if (op->will_apply)
387 monster_apply_below (op); /* Check for items to apply below */
388
389 /* If we don't have an enemy, do special movement or the like */
390 if (!enemy)
391 {
392 if (QUERY_FLAG (op, FLAG_ONLY_ATTACK))
393 {
394 op->destroy ();
395 return 1;
396 }
397
398 /* Probably really a bug for a creature to have both
399 * stand still and a movement type set.
400 */
401 if (!QUERY_FLAG (op, FLAG_STAND_STILL))
402 {
403 if (op->attack_movement & HI4)
404 {
405 switch (op->attack_movement & HI4)
406 {
407 case (PETMOVE):
408 pet_move (op);
409 break;
410
411 case (CIRCLE1):
412 circ1_move (op);
413 break;
414
415 case (CIRCLE2):
416 circ2_move (op);
417 break;
418
419 case (PACEV):
420 pace_movev (op);
421 break;
422
423 case (PACEH):
424 pace_moveh (op);
425 break;
426
427 case (PACEV2):
428 pace2_movev (op);
429 break;
430
431 case (PACEH2):
432 pace2_moveh (op);
433 break;
434
435 case (RANDO):
436 rand_move (op);
437 break;
438
439 case (RANDO2):
440 move_randomly (op);
441 break;
442 }
443 return 0;
444 }
445 else if (QUERY_FLAG (op, FLAG_RANDOM_MOVE))
446 (void) move_randomly (op);
447
448 } /* stand still */
449 return 0;
450 } /* no enemy */
451
452 /* We have an enemy. Block immediately below is for pets */
453 if ((op->attack_movement & HI4) == PETMOVE
454 && (owner = op->owner) != NULL
455 && !on_same_map (op, owner)
456 && !owner->flag [FLAG_REMOVED])
457 return follow_owner (op, owner);
458
459 /* doppleganger code to change monster facing to that of the nearest
460 * player. Hmm. The code is here, but no monster in the current
461 * arch set uses it.
462 */
463 if ((op->race != NULL) && strcmp (op->race, "doppleganger") == 0)
464 {
465 op->face = enemy->face;
466 op->name = enemy->name;
467 }
468
469 /* Calculate range information for closest body part - this
470 * is used for the 'skill' code, which isn't that smart when
471 * it comes to figuring it out - otherwise, giants throw boulders
472 * into themselves.
473 */
474 get_rangevector (op, enemy, &rv, 0);
475
476 /* Move the check for scared up here - if the monster was scared,
477 * we were not doing any of the logic below, so might as well save
478 * a few cpu cycles.
479 */
480 if (!QUERY_FLAG (op, FLAG_SCARED))
481 {
482 rv_vector rv1;
483
484 /* now we test every part of an object .... this is a real ugly piece of code */
485 for (part = op; part != NULL; part = part->more)
486 {
487 get_rangevector (part, enemy, &rv1, 0x1);
488 dir = rv1.direction;
489
490 /* hm, not sure about this part - in original was a scared flag here too
491 * but that we test above... so can be old code here
492 */
493 if (QUERY_FLAG (op, FLAG_RUN_AWAY))
494 dir = absdir (dir + 4);
495 if (QUERY_FLAG (op, FLAG_CONFUSED))
496 dir = absdir (dir + rndm (3) + rndm (3) - 2);
497
498 if (QUERY_FLAG (op, FLAG_CAST_SPELL) && !(rndm (3)))
499 {
500 if (monster_cast_spell (op, part, enemy, dir, &rv1))
501 return 0;
502 }
503
504 if (QUERY_FLAG (op, FLAG_READY_SCROLL) && !(rndm (3)))
505 {
506 if (monster_use_scroll (op, part, enemy, dir, &rv1))
507 return 0;
508 }
509
510 if (QUERY_FLAG (op, FLAG_READY_RANGE) && !(rndm (3)))
511 {
512 if (monster_use_range (op, part, enemy, dir))
513 return 0;
514 }
515 if (QUERY_FLAG (op, FLAG_READY_SKILL) && !(rndm (3)))
516 {
517 if (monster_use_skill (op, rv.part, enemy, rv.direction))
518 return 0;
519 }
520 if (QUERY_FLAG (op, FLAG_READY_BOW) && !(rndm (2)))
521 {
522 if (monster_use_bow (op, part, enemy, dir))
523 return 0;
524 }
525 } /* for processing of all parts */
526 } /* If not scared */
527
528
529 part = rv.part;
530 dir = rv.direction;
531
532 if (QUERY_FLAG (op, FLAG_SCARED) || QUERY_FLAG (op, FLAG_RUN_AWAY))
533 dir = absdir (dir + 4);
534
535 if (QUERY_FLAG (op, FLAG_CONFUSED))
536 dir = absdir (dir + rndm (3) + rndm (3) - 2);
537
538 pre_att_dir = dir; /* remember the original direction */
539
540 if ((op->attack_movement & LO4) && !QUERY_FLAG (op, FLAG_SCARED))
541 {
542 switch (op->attack_movement & LO4)
543 {
544 case DISTATT:
545 dir = dist_att (dir, op, enemy, part, &rv);
546 break;
547
548 case RUNATT:
549 dir = run_att (dir, op, enemy, part, &rv);
550 break;
551
552 case HITRUN:
553 dir = hitrun_att (dir, op, enemy);
554 break;
555
556 case WAITATT:
557 dir = wait_att (dir, op, enemy, part, &rv);
558 break;
559
560 case RUSH: /* default - monster normally moves towards player */
561 case ALLRUN:
562 break;
563
564 case DISTHIT:
565 dir = disthit_att (dir, op, enemy, part, &rv);
566 break;
567
568 case WAIT2:
569 dir = wait_att2 (dir, op, enemy, part, &rv);
570 break;
571
572 default:
573 LOG (llevDebug, "Illegal low mon-move: %d\n", op->attack_movement & LO4);
574 }
575 }
576
577 if (!dir)
578 return 0;
579
580 if (!QUERY_FLAG (op, FLAG_STAND_STILL))
581 {
582 if (move_object (op, dir)) /* Can the monster move directly toward player? */
583 {
584 /* elmex: Turn our monster after it moved if it has DISTATT attack */
585 if ((op->attack_movement & LO4) == DISTATT)
586 op->direction = pre_att_dir;
587
588 return 0;
589 }
590
591 if (QUERY_FLAG (op, FLAG_SCARED) || !can_hit (part, enemy, &rv) || QUERY_FLAG (op, FLAG_RUN_AWAY))
592 {
593
594 /* Try move around corners if !close */
595 int maxdiff = (QUERY_FLAG (op, FLAG_ONLY_ATTACK) || RANDOM () & 1) ? 1 : 2;
596
597 for (diff = 1; diff <= maxdiff; diff++)
598 {
599 /* try different detours */
600 int m = 1 - (RANDOM () & 2); /* Try left or right first? */
601
602 if (move_object (op, absdir (dir + diff * m)) || move_object (op, absdir (dir - diff * m)))
603 return 0;
604 }
605 }
606 } /* if monster is not standing still */
607
608 /* elmex: Turn our monster after it moved if it has DISTATT attack */
609 if ((op->attack_movement & LO4) == DISTATT)
610 op->direction = pre_att_dir;
611
612 /*
613 * Eneq(@csd.uu.se): Patch to make RUN_AWAY or SCARED monsters move a random
614 * direction if they can't move away.
615 */
616 if (!QUERY_FLAG (op, FLAG_ONLY_ATTACK) && (QUERY_FLAG (op, FLAG_RUN_AWAY) || QUERY_FLAG (op, FLAG_SCARED)))
617 if (move_randomly (op))
618 return 0;
619
620 /*
621 * Try giving the monster a new enemy - the player that is closest
622 * to it. In this way, it won't just keep trying to get to a target
623 * that is inaccessible.
624 * This could be more clever - it should go through a list of several
625 * enemies, as it is now, you could perhaps get situations where there
626 * are two players flanking the monster at close distance, but which
627 * the monster can't get to, and a third one at a far distance that
628 * the monster could get to - as it is, the monster won't look at that
629 * third one.
630 */
631 if (!QUERY_FLAG (op, FLAG_FRIENDLY) && enemy == op->enemy)
632 {
633 object *nearest_player = get_nearest_player (op);
634
635 if (nearest_player && nearest_player != enemy && !can_hit (part, enemy, &rv))
636 {
637 op->enemy = NULL;
638 enemy = nearest_player;
639 }
640 }
641
642 if (!QUERY_FLAG (op, FLAG_SCARED) && can_hit (part, enemy, &rv))
643 {
644 /* The adjustement to wc that was here before looked totally bogus -
645 * since wc can in fact get negative, that would mean by adding
646 * the current wc, the creature gets better? Instead, just
647 * add a fixed amount - nasty creatures that are runny away should
648 * still be pretty nasty.
649 */
650 if (QUERY_FLAG (op, FLAG_RUN_AWAY))
651 {
652 part->stats.wc += 10;
653 (void) skill_attack (enemy, part, 0, NULL, NULL);
654 part->stats.wc -= 10;
655 }
656 else
657 (void) skill_attack (enemy, part, 0, NULL, NULL);
658 } /* if monster is in attack range */
659
660 if (QUERY_FLAG (part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */
661 return 1;
662
663 if (QUERY_FLAG (op, FLAG_ONLY_ATTACK))
664 {
665 op->remove ();
666 op->destroy ();
667 return 1;
668 }
669 return 0;
670 }
671
672 int
673 can_hit (object *ob1, object *ob2, rv_vector * rv)
674 {
675 object *more;
676 rv_vector rv1;
677
678 if (QUERY_FLAG (ob1, FLAG_CONFUSED) && !(rndm (3)))
679 return 0;
680
681 if (abs (rv->distance_x) < 2 && abs (rv->distance_y) < 2)
682 return 1;
683
684 /* check all the parts of ob2 - just because we can't get to
685 * its head doesn't mean we don't want to pound its feet
686 */
687 for (more = ob2->more; more != NULL; more = more->more)
688 {
689 get_rangevector (ob1, more, &rv1, 0);
690 if (abs (rv1.distance_x) < 2 && abs (rv1.distance_y) < 2)
691 return 1;
692 }
693 return 0;
694
695 }
696
697 /* Returns 1 is monster should cast spell sp at an enemy
698 * Returns 0 if the monster should not cast this spell.
699 *
700 * Note that this function does not check to see if the monster can
701 * in fact cast the spell (sp dependencies and what not.) That is because
702 * this function is also sued to see if the monster should use spell items
703 * (rod/horn/wand/scroll).
704 * Note that there are certainly other offensive spells that could be
705 * included, but I decided to leave out the spells that may kill more
706 * monsters than players (eg, disease).
707 *
708 * This could be a lot smarter - if there are few monsters around,
709 * then disease might not be as bad. Likewise, if the monster is damaged,
710 * the right type of healing spell could be useful.
711 */
712
713 static int
714 monster_should_cast_spell (object *monster, object *spell_ob)
715 {
716 if (spell_ob->subtype == SP_BOLT || spell_ob->subtype == SP_BULLET ||
717 spell_ob->subtype == SP_EXPLOSION || spell_ob->subtype == SP_CONE ||
718 spell_ob->subtype == SP_BOMB || spell_ob->subtype == SP_SMITE ||
719 spell_ob->subtype == SP_MAGIC_MISSILE || spell_ob->subtype == SP_SUMMON_GOLEM ||
720 spell_ob->subtype == SP_MAGIC_WALL || spell_ob->subtype == SP_SUMMON_MONSTER ||
721 spell_ob->subtype == SP_MOVING_BALL || spell_ob->subtype == SP_SWARM || spell_ob->subtype == SP_INVISIBLE)
722
723 return 1;
724
725 return 0;
726 }
727
728
729 #define MAX_KNOWN_SPELLS 20
730
731 /* Returns a randomly selected spell. This logic is still
732 * less than ideal. This code also only seems to deal with
733 * wizard spells, as the check is against sp, and not grace.
734 * can mosnters know cleric spells?
735 */
736 object *
737 monster_choose_random_spell (object *monster)
738 {
739 object *altern[MAX_KNOWN_SPELLS];
740 object *tmp;
741 int i = 0;
742
743 for (tmp = monster->inv; tmp != NULL; tmp = tmp->below)
744 if (tmp->type == SPELLBOOK || tmp->type == SPELL)
745 {
746 /* Check and see if it's actually a useful spell.
747 * If its a spellbook, the spell is actually the inventory item.
748 * if it is a spell, then it is just the object itself.
749 */
750 if (monster_should_cast_spell (monster, (tmp->type == SPELLBOOK) ? tmp->inv : tmp))
751 {
752 altern[i++] = tmp;
753 if (i == MAX_KNOWN_SPELLS)
754 break;
755 }
756 }
757 if (!i)
758 return NULL;
759 return altern[RANDOM () % i];
760 }
761
762 /* This checks to see if the monster should cast a spell/ability.
763 * it returns true if the monster casts a spell, 0 if he doesn't.
764 * head is the head of the monster.
765 * part is the part of the monster we are checking against.
766 * pl is the target.
767 * dir is the direction to case.
768 * rv is the vector which describes where the enemy is.
769 */
770
771 int
772 monster_cast_spell (object *head, object *part, object *pl, int dir, rv_vector * rv)
773 {
774 object *spell_item;
775 object *owner;
776 rv_vector rv1;
777
778 /* If you want monsters to cast spells over friends, this spell should
779 * be removed. It probably should be in most cases, since monsters still
780 * don't care about residual effects (ie, casting a cone which may have a
781 * clear path to the player, the side aspects of the code will still hit
782 * other monsters)
783 */
784 if (!(dir = path_to_player (part, pl, 0)))
785 return 0;
786
787 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
788 {
789 get_rangevector (head, owner, &rv1, 0x1);
790 if (dirdiff (dir, rv1.direction) < 2)
791 {
792 return 0; /* Might hit owner with spell */
793 }
794 }
795
796 if (QUERY_FLAG (head, FLAG_CONFUSED))
797 dir = absdir (dir + rndm (3) + rndm (3) - 2);
798
799 /* If the monster hasn't already chosen a spell, choose one
800 * I'm not sure if it really make sense to pre-select spells (events
801 * could be different by the time the monster goes again).
802 */
803 if (head->spellitem == NULL)
804 {
805 if ((spell_item = monster_choose_random_spell (head)) == NULL)
806 {
807 LOG (llevMonster, "Turned off spells in %s\n", &head->name);
808 CLEAR_FLAG (head, FLAG_CAST_SPELL); /* Will be turned on when picking up book */
809 return 0;
810 }
811 if (spell_item->type == SPELLBOOK)
812 {
813 if (!spell_item->inv)
814 {
815 LOG (llevError, "spellbook %s does not contain a spell?\n", &spell_item->name);
816 return 0;
817 }
818 spell_item = spell_item->inv;
819 }
820 }
821 else
822 spell_item = head->spellitem;
823
824 if (!spell_item)
825 return 0;
826
827 /* Best guess this is a defensive/healing spell */
828 if (spell_item->range <= 1 || spell_item->stats.dam < 0)
829 dir = 0;
830
831 /* Monster doesn't have enough spell-points */
832 if (head->stats.sp < SP_level_spellpoint_cost (head, spell_item, SPELL_MANA))
833 return 0;
834
835 if (head->stats.grace < SP_level_spellpoint_cost (head, spell_item, SPELL_GRACE))
836 return 0;
837
838 head->stats.sp -= SP_level_spellpoint_cost (head, spell_item, SPELL_MANA);
839 head->stats.grace -= SP_level_spellpoint_cost (head, spell_item, SPELL_GRACE);
840
841 /* set this to null, so next time monster will choose something different */
842 head->spellitem = NULL;
843
844 return cast_spell (part, part, dir, spell_item, NULL);
845 }
846
847
848 int
849 monster_use_scroll (object *head, object *part, object *pl, int dir, rv_vector * rv)
850 {
851 object *scroll;
852 object *owner;
853 rv_vector rv1;
854
855 /* If you want monsters to cast spells over friends, this spell should
856 * be removed. It probably should be in most cases, since monsters still
857 * don't care about residual effects (ie, casting a cone which may have a
858 * clear path to the player, the side aspects of the code will still hit
859 * other monsters)
860 */
861 if (!(dir = path_to_player (part, pl, 0)))
862 return 0;
863
864 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
865 {
866 get_rangevector (head, owner, &rv1, 0x1);
867 if (dirdiff (dir, rv1.direction) < 2)
868 {
869 return 0; /* Might hit owner with spell */
870 }
871 }
872
873 if (QUERY_FLAG (head, FLAG_CONFUSED))
874 dir = absdir (dir + rndm (3) + rndm (3) - 2);
875
876 for (scroll = head->inv; scroll; scroll = scroll->below)
877 if (scroll->type == SCROLL && monster_should_cast_spell (head, scroll->inv))
878 break;
879
880 /* Used up all his scrolls, so nothing do to */
881 if (!scroll)
882 {
883 CLEAR_FLAG (head, FLAG_READY_SCROLL);
884 return 0;
885 }
886
887 /* Spell should be cast on caster (ie, heal, strength) */
888 if (scroll->inv->range == 0)
889 dir = 0;
890
891 apply_scroll (part, scroll, dir);
892 return 1;
893 }
894
895 /* monster_use_skill()-implemented 95-04-28 to allow monster skill use.
896 * Note that monsters do not need the skills SK_MELEE_WEAPON and
897 * SK_MISSILE_WEAPON to make those respective attacks, if we
898 * required that we would drastically increase the memory
899 * requirements of CF!!
900 *
901 * The skills we are treating here are all but those. -b.t.
902 *
903 * At the moment this is only useful for throwing, perhaps for
904 * stealing. TODO: This should be more integrated in the game. -MT, 25.11.01
905 */
906 int
907 monster_use_skill (object *head, object *part, object *pl, int dir)
908 {
909 object *skill, *owner;
910
911 if (!(dir = path_to_player (part, pl, 0)))
912 return 0;
913
914 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
915 {
916 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
917
918 if (dirdiff (dir, dir2) < 1)
919 return 0; /* Might hit owner with skill -thrown rocks for example ? */
920 }
921
922 if (QUERY_FLAG (head, FLAG_CONFUSED))
923 dir = absdir (dir + rndm (3) + rndm (3) - 2);
924
925 /* skill selection - monster will use the next unused skill.
926 * well...the following scenario will allow the monster to
927 * toggle between 2 skills. One day it would be nice to make
928 * more skills available to monsters.
929 */
930
931 for (skill = head->inv; skill; skill = skill->below)
932 if (skill->type == SKILL && skill != head->chosen_skill)
933 {
934 head->chosen_skill = skill;
935 break;
936 }
937
938 if (!skill && !head->chosen_skill)
939 {
940 LOG (llevDebug, "Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", &head->name, head->count);
941 CLEAR_FLAG (head, FLAG_READY_SKILL);
942 return 0;
943 }
944
945 /* use skill */
946 return do_skill (head, part, head->chosen_skill, dir, NULL);
947 }
948
949 /* Monster will use a ranged spell attack. */
950 int
951 monster_use_range (object *head, object *part, object *pl, int dir)
952 {
953 object *wand, *owner;
954 int at_least_one = 0;
955
956 if (!(dir = path_to_player (part, pl, 0)))
957 return 0;
958
959 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
960 {
961 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
962
963 if (dirdiff (dir, dir2) < 2)
964 return 0; /* Might hit owner with spell */
965 }
966 if (QUERY_FLAG (head, FLAG_CONFUSED))
967 dir = absdir (dir + rndm (3) + rndm (3) - 2);
968
969 for (wand = head->inv; wand; wand = wand->below)
970 {
971 if (wand->type == WAND)
972 {
973 /* Found a wand, let's see if it has charges left */
974 at_least_one = 1;
975 if (wand->stats.food <= 0)
976 continue;
977
978 cast_spell (head, wand, dir, wand->inv, NULL);
979
980 if (!(--wand->stats.food))
981 {
982 if (wand->arch)
983 {
984 CLEAR_FLAG (wand, FLAG_ANIMATE);
985 wand->face = wand->arch->clone.face;
986 wand->set_speed (0);
987 }
988 }
989 /* Success */
990 return 1;
991 }
992 else if (wand->type == ROD || wand->type == HORN)
993 {
994 /* Found rod/horn, let's use it if possible */
995 at_least_one = 1;
996 if (wand->stats.hp < MAX (wand->inv->stats.sp, wand->inv->stats.grace))
997 continue;
998
999 /* drain charge before casting spell - can be a case where the
1000 * spell destroys the monster, and rod, so if done after, results
1001 * in crash.
1002 */
1003 drain_rod_charge (wand);
1004 cast_spell (head, wand, dir, wand->inv, NULL);
1005
1006 /* Success */
1007 return 1;
1008 }
1009 }
1010
1011 if (at_least_one)
1012 return 0;
1013
1014 LOG (llevError, "Error: Monster %s (%d) HAS_READY_RANG() without wand/horn/rod.\n", &head->name, head->count);
1015 CLEAR_FLAG (head, FLAG_READY_RANGE);
1016 return 0;
1017 }
1018
1019 int
1020 monster_use_bow (object *head, object *part, object *pl, int dir)
1021 {
1022 object *owner;
1023
1024 if (!(dir = path_to_player (part, pl, 0)))
1025 return 0;
1026 if (QUERY_FLAG (head, FLAG_CONFUSED))
1027 dir = absdir (dir + rndm (3) + rndm (3) - 2);
1028
1029 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
1030 {
1031 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
1032
1033 if (dirdiff (dir, dir2) < 1)
1034 return 0; /* Might hit owner with arrow */
1035 }
1036
1037 /* in server/player.c */
1038 return fire_bow (head, part, NULL, dir, 0, part->x, part->y);
1039
1040 }
1041
1042 /* Checks if putting on 'item' will make 'who' do more
1043 * damage. This is a very simplistic check - also checking things
1044 * like speed and ac are also relevant.
1045 *
1046 * return true if item is a better object.
1047 */
1048
1049 int
1050 check_good_weapon (object *who, object *item)
1051 {
1052 object *other_weap;
1053 int val = 0, i;
1054
1055 for (other_weap = who->inv; other_weap != NULL; other_weap = other_weap->below)
1056 if (other_weap->type == item->type && QUERY_FLAG (other_weap, FLAG_APPLIED))
1057 break;
1058
1059 if (other_weap == NULL) /* No other weapons */
1060 return 1;
1061
1062 /* Rather than go through and apply the new one, and see if it is
1063 * better, just do some simple checks
1064 * Put some multipliers for things that hvae several effects,
1065 * eg, magic affects both damage and wc, so it has more weight
1066 */
1067
1068 val = item->stats.dam - other_weap->stats.dam;
1069 val += (item->magic - other_weap->magic) * 3;
1070 /* Monsters don't really get benefits from things like regen rates
1071 * from items. But the bonus for their stats are very important.
1072 */
1073 for (i = 0; i < NUM_STATS; i++)
1074 val += (get_attr_value (&item->stats, i) - get_attr_value (&other_weap->stats, i)) * 2;
1075
1076 if (val > 0)
1077 return 1;
1078 else
1079 return 0;
1080 }
1081
1082 int
1083 check_good_armour (object *who, object *item)
1084 {
1085 object *other_armour;
1086 int val = 0, i;
1087
1088 for (other_armour = who->inv; other_armour != NULL; other_armour = other_armour->below)
1089 if (other_armour->type == item->type && QUERY_FLAG (other_armour, FLAG_APPLIED))
1090 break;
1091
1092 if (other_armour == NULL) /* No other armour, use the new */
1093 return 1;
1094
1095 /* Like above function , see which is better */
1096 val = item->stats.ac - other_armour->stats.ac;
1097 val = (item->resist[ATNR_PHYSICAL] - other_armour->resist[ATNR_PHYSICAL]) / 5;
1098 val += (item->magic - other_armour->magic) * 3;
1099
1100 /* for the other protections, do weigh them very much in the equation -
1101 * it is the armor protection which is most important, because there is
1102 * no good way to know what the player may attack the monster with.
1103 * So if the new item has better protection than the old, give that higher
1104 * value. If the reverse, then decrease the value of this item some.
1105 */
1106 for (i = 1; i < NROFATTACKS; i++)
1107 {
1108 if (item->resist[i] > other_armour->resist[i])
1109 val++;
1110 else if (item->resist[i] < other_armour->resist[i])
1111 val--;
1112 }
1113
1114 /* Very few armours have stats, so not much need to worry about those. */
1115
1116 if (val > 0)
1117 return 1;
1118 else
1119 return 0;
1120 }
1121
1122 /*
1123 * monster_check_pickup(): checks for items that monster can pick up.
1124 *
1125 * Vick's (vick@bern.docs.uu.se) fix 921030 for the sweeper blob.
1126 * Each time the blob passes over some treasure, it will
1127 * grab it a.s.a.p.
1128 *
1129 * Eneq(@csd.uu.se): This can now be defined in the archetypes, added code
1130 * to handle this.
1131 *
1132 * This function was seen be continueing looping at one point (tmp->below
1133 * became a recursive loop. It may be better to call monster_check_apply
1134 * after we pick everything up, since that function may call others which
1135 * affect stacking on this space.
1136 */
1137 void
1138 monster_check_pickup (object *monster)
1139 {
1140 object *tmp, *next;
1141
1142 for (tmp = monster->below; tmp != NULL; tmp = next)
1143 {
1144 next = tmp->below;
1145 if (monster_can_pick (monster, tmp))
1146 {
1147 tmp->remove ();
1148 tmp = insert_ob_in_ob (tmp, monster);
1149 (void) monster_check_apply (monster, tmp);
1150 }
1151 /* We could try to re-establish the cycling, of the space, but probably
1152 * not a big deal to just bail out.
1153 */
1154 if (next && next->destroyed ())
1155 return;
1156 }
1157 }
1158
1159 /*
1160 * monster_can_pick(): If the monster is interested in picking up
1161 * the item, then return 0. Otherwise 0.
1162 * Instead of pick_up, flags for "greed", etc, should be used.
1163 * I've already utilized flags for bows, wands, rings, etc, etc. -Frank.
1164 */
1165 int
1166 monster_can_pick (object *monster, object *item)
1167 {
1168 int flag = 0;
1169 int i;
1170
1171 if (!can_pick (monster, item))
1172 return 0;
1173
1174 if (QUERY_FLAG (item, FLAG_UNPAID))
1175 return 0;
1176
1177 if (monster->pick_up & 64) /* All */
1178 flag = 1;
1179
1180 else
1181 switch (item->type)
1182 {
1183 case MONEY:
1184 case GEM:
1185 flag = monster->pick_up & 2;
1186 break;
1187
1188 case FOOD:
1189 flag = monster->pick_up & 4;
1190 break;
1191
1192 case WEAPON:
1193 flag = (monster->pick_up & 8) || QUERY_FLAG (monster, FLAG_USE_WEAPON);
1194 break;
1195
1196 case ARMOUR:
1197 case SHIELD:
1198 case HELMET:
1199 case BOOTS:
1200 case GLOVES:
1201 case GIRDLE:
1202 flag = (monster->pick_up & 16) || QUERY_FLAG (monster, FLAG_USE_ARMOUR);
1203 break;
1204
1205 case SKILL:
1206 flag = QUERY_FLAG (monster, FLAG_CAN_USE_SKILL);
1207 break;
1208
1209 case RING:
1210 flag = QUERY_FLAG (monster, FLAG_USE_RING);
1211 break;
1212
1213 case WAND:
1214 case HORN:
1215 case ROD:
1216 flag = QUERY_FLAG (monster, FLAG_USE_RANGE);
1217 break;
1218
1219 case SPELLBOOK:
1220 flag = (monster->arch != NULL && QUERY_FLAG ((&monster->arch->clone), FLAG_CAST_SPELL));
1221 break;
1222
1223 case SCROLL:
1224 flag = QUERY_FLAG (monster, FLAG_USE_SCROLL);
1225 break;
1226
1227 case BOW:
1228 case ARROW:
1229 flag = QUERY_FLAG (monster, FLAG_USE_BOW);
1230 break;
1231 }
1232
1233 /* Simplistic check - if the monster has a location to equip it, he will
1234 * pick it up. Note that this doesn't handle cases where an item may
1235 * use several locations.
1236 */
1237 for (i = 0; i < NUM_BODY_LOCATIONS; i++)
1238 {
1239 if (monster->body_info[i] && item->body_info[i])
1240 {
1241 flag = 1;
1242 break;
1243 }
1244 }
1245
1246 if (((!(monster->pick_up & 32)) && flag) || ((monster->pick_up & 32) && (!flag)))
1247 return 1;
1248 return 0;
1249 }
1250
1251 /*
1252 * monster_apply_below():
1253 * Vick's (vick@bern.docs.uu.se) @921107 -> If a monster who's
1254 * eager to apply things, encounters something apply-able,
1255 * then make him apply it
1256 */
1257 void
1258 monster_apply_below (object *monster)
1259 {
1260 object *tmp, *next;
1261
1262 for (tmp = monster->below; tmp != NULL; tmp = next)
1263 {
1264 next = tmp->below;
1265 switch (tmp->type)
1266 {
1267 case CF_HANDLE:
1268 case TRIGGER:
1269 if (monster->will_apply & 1)
1270 manual_apply (monster, tmp, 0);
1271 break;
1272
1273 case TREASURE:
1274 if (monster->will_apply & 2)
1275 manual_apply (monster, tmp, 0);
1276 break;
1277
1278 }
1279 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1280 break;
1281 }
1282 }
1283
1284 /*
1285 * monster_check_apply() is meant to be called after an item is
1286 * inserted in a monster.
1287 * If an item becomes outdated (monster found a better item),
1288 * a pointer to that object is returned, so it can be dropped.
1289 * (so that other monsters can pick it up and use it)
1290 * Note that as things are now, monsters never drop something -
1291 * they can pick up all that they can use.
1292 */
1293 /* Sept 96, fixed this so skills will be readied -b.t.*/
1294 void
1295 monster_check_apply (object *mon, object *item)
1296 {
1297 int flag = 0;
1298
1299 if (item->type == SPELLBOOK && mon->arch && (QUERY_FLAG ((&mon->arch->clone), FLAG_CAST_SPELL)))
1300 {
1301 SET_FLAG (mon, FLAG_CAST_SPELL);
1302 return;
1303 }
1304
1305 /* If for some reason, this item is already applied, no more work to do */
1306 if (QUERY_FLAG (item, FLAG_APPLIED))
1307 return;
1308
1309 /* Might be better not to do this - if the monster can fire a bow,
1310 * it is possible in his wanderings, he will find one to use. In
1311 * which case, it would be nice to have ammo for it.
1312 */
1313 if (QUERY_FLAG (mon, FLAG_USE_BOW) && item->type == ARROW)
1314 {
1315 /* Check for the right kind of bow */
1316 object *bow;
1317
1318 for (bow = mon->inv; bow; bow = bow->below)
1319 if (bow->type == BOW && bow->race == item->race)
1320 {
1321 SET_FLAG (mon, FLAG_READY_BOW);
1322 LOG (llevMonster, "Found correct bow for arrows.\n");
1323 return; /* nothing more to do for arrows */
1324 }
1325 }
1326
1327 if (item->type == TREASURE && mon->will_apply & WILL_APPLY_TREASURE)
1328 flag = 1;
1329 /* Eating food gets hp back */
1330 else if (item->type == FOOD && mon->will_apply & WILL_APPLY_FOOD)
1331 flag = 1;
1332 else if (item->type == SCROLL && QUERY_FLAG (mon, FLAG_USE_SCROLL))
1333 {
1334 if (!item->inv)
1335 LOG (llevDebug, "Monster %d having scroll %d with empty inventory!", mon->count, item->count);
1336 else if (monster_should_cast_spell (mon, item->inv))
1337 SET_FLAG (mon, FLAG_READY_SCROLL);
1338 /* Don't use it right now */
1339 return;
1340 }
1341 else if (item->type == WEAPON)
1342 flag = check_good_weapon (mon, item);
1343 else if (item->is_armor ())
1344 flag = check_good_armour (mon, item);
1345 /* Should do something more, like make sure this is a better item */
1346 else if (item->type == RING)
1347 flag = 1;
1348 else if (item->type == WAND || item->type == ROD || item->type == HORN)
1349 {
1350 /* We never really 'ready' the wand/rod/horn, because that would mean the
1351 * weapon would get undone.
1352 */
1353 if (!(can_apply_object (mon, item) & CAN_APPLY_NOT_MASK))
1354 {
1355 SET_FLAG (mon, FLAG_READY_RANGE);
1356 SET_FLAG (item, FLAG_APPLIED);
1357 }
1358 return;
1359 }
1360 else if (item->type == BOW)
1361 {
1362 /* We never really 'ready' the bow, because that would mean the
1363 * weapon would get undone.
1364 */
1365 if (!(can_apply_object (mon, item) & CAN_APPLY_NOT_MASK))
1366 SET_FLAG (mon, FLAG_READY_BOW);
1367 return;
1368 }
1369 else if (item->type == SKILL)
1370 {
1371 /*
1372 * skills are specials: monsters must have the 'FLAG_READY_SKILL' flag set,
1373 * else they can't use the skill...
1374 * Skills also don't need to get applied, so return now.
1375 */
1376 SET_FLAG (mon, FLAG_READY_SKILL);
1377 return;
1378 }
1379
1380 /* if we don't match one of the above types, return now.
1381 * can_apply_object will say that we can apply things like flesh,
1382 * bolts, and whatever else, because it only checks against the
1383 * body_info locations.
1384 */
1385 if (!flag)
1386 return;
1387
1388 /* Check to see if the monster can use this item. If not, no need
1389 * to do further processing. Note that can_apply_object already checks
1390 * for the CAN_USE flags.
1391 */
1392 if (can_apply_object (mon, item) & CAN_APPLY_NOT_MASK)
1393 return;
1394
1395 /* should only be applying this item, not unapplying it.
1396 * also, ignore status of curse so they can take off old armour.
1397 * monsters have some advantages after all.
1398 */
1399 manual_apply (mon, item, AP_APPLY | AP_IGNORE_CURSE);
1400 }
1401
1402 void
1403 npc_call_help (object *op)
1404 {
1405 int x, y, mflags;
1406 object *npc;
1407 sint16 sx, sy;
1408 maptile *m;
1409
1410 for (x = -3; x < 4; x++)
1411 for (y = -3; y < 4; y++)
1412 {
1413 m = op->map;
1414 sx = op->x + x;
1415 sy = op->y + y;
1416 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
1417 /* If nothing alive on this space, no need to search the space. */
1418 if ((mflags & P_OUT_OF_MAP) || !(mflags & P_IS_ALIVE))
1419 continue;
1420
1421 for (npc = GET_MAP_OB (m, sx, sy); npc != NULL; npc = npc->above)
1422 if (QUERY_FLAG (npc, FLAG_ALIVE) && QUERY_FLAG (npc, FLAG_UNAGGRESSIVE))
1423 npc->enemy = op->enemy;
1424 }
1425 }
1426
1427 int
1428 dist_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1429 {
1430 if (can_hit (part, enemy, rv))
1431 return dir;
1432 if (rv->distance < 10)
1433 return absdir (dir + 4);
1434 else if (rv->distance > 18)
1435 return dir;
1436
1437 return 0;
1438 }
1439
1440 int
1441 run_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1442 {
1443 if ((can_hit (part, enemy, rv) && ob->move_status < 20) || ob->move_status < 20)
1444 {
1445 ob->move_status++;
1446 return (dir);
1447 }
1448 else if (ob->move_status > 20)
1449 ob->move_status = 0;
1450
1451 return absdir (dir + 4);
1452 }
1453
1454 int
1455 hitrun_att (int dir, object *ob, object *enemy)
1456 {
1457 if (ob->move_status++ < 25)
1458 return dir;
1459 else if (ob->move_status < 50)
1460 return absdir (dir + 4);
1461 else
1462 ob->move_status = 0;
1463
1464 return absdir (dir + 4);
1465 }
1466
1467 int
1468 wait_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1469 {
1470
1471 int inrange = can_hit (part, enemy, rv);
1472
1473 if (ob->move_status || inrange)
1474 ob->move_status++;
1475
1476 if (ob->move_status == 0)
1477 return 0;
1478 else if (ob->move_status < 10)
1479 return dir;
1480 else if (ob->move_status < 15)
1481 return absdir (dir + 4);
1482
1483 ob->move_status = 0;
1484 return 0;
1485 }
1486
1487 int
1488 disthit_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1489 {
1490
1491 /* The logic below here looked plain wrong before. Basically, what should
1492 * happen is that if the creatures hp percentage falls below run_away,
1493 * the creature should run away (dir+4)
1494 * I think its wrong for a creature to have a zero maxhp value, but
1495 * at least one map has this set, and whatever the map contains, the
1496 * server should try to be resilant enough to avoid the problem
1497 */
1498 if (ob->stats.maxhp && (ob->stats.hp * 100) / ob->stats.maxhp < ob->run_away)
1499 return absdir (dir + 4);
1500
1501 return dist_att (dir, ob, enemy, part, rv);
1502 }
1503
1504 int
1505 wait_att2 (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1506 {
1507 if (rv->distance < 9)
1508 return absdir (dir + 4);
1509
1510 return 0;
1511 }
1512
1513 void
1514 circ1_move (object *ob)
1515 {
1516 static int circle[12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 };
1517
1518 if (++ob->move_status > 11)
1519 ob->move_status = 0;
1520
1521 if (!(move_object (ob, circle[ob->move_status])))
1522 move_object (ob, rndm (8) + 1);
1523 }
1524
1525 void
1526 circ2_move (object *ob)
1527 {
1528 static int circle[20] = { 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 1, 1, 1, 2, 2 };
1529
1530 if (++ob->move_status > 19)
1531 ob->move_status = 0;
1532
1533 if (!(move_object (ob, circle[ob->move_status])))
1534 move_object (ob, rndm (8) + 1);
1535 }
1536
1537 void
1538 pace_movev (object *ob)
1539 {
1540 if (ob->move_status++ > 6)
1541 ob->move_status = 0;
1542
1543 if (ob->move_status < 4)
1544 move_object (ob, 5);
1545 else
1546 move_object (ob, 1);
1547 }
1548
1549 void
1550 pace_moveh (object *ob)
1551 {
1552 if (ob->move_status++ > 6)
1553 ob->move_status = 0;
1554
1555 if (ob->move_status < 4)
1556 move_object (ob, 3);
1557 else
1558 move_object (ob, 7);
1559 }
1560
1561 void
1562 pace2_movev (object *ob)
1563 {
1564 if (ob->move_status++ > 16)
1565 ob->move_status = 0;
1566
1567 if (ob->move_status < 6)
1568 move_object (ob, 5);
1569 else if (ob->move_status < 8)
1570 return;
1571 else if (ob->move_status < 13)
1572 move_object (ob, 1);
1573 else
1574 return;
1575 }
1576
1577 void
1578 pace2_moveh (object *ob)
1579 {
1580 if (ob->move_status++ > 16)
1581 ob->move_status = 0;
1582
1583 if (ob->move_status < 6)
1584 move_object (ob, 3);
1585 else if (ob->move_status < 8)
1586 return;
1587 else if (ob->move_status < 13)
1588 move_object (ob, 7);
1589 else
1590 return;
1591 }
1592
1593 void
1594 rand_move (object *ob)
1595 {
1596 int i;
1597
1598 if (ob->move_status < 1 || ob->move_status > 8 || !(move_object (ob, ob->move_status || !(rndm (9)))))
1599 for (i = 0; i < 5; i++)
1600 if (move_object (ob, ob->move_status = rndm (8) + 1))
1601 return;
1602 }
1603
1604 void
1605 check_earthwalls (object *op, maptile *m, int x, int y)
1606 {
1607 object *tmp;
1608
1609 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
1610 {
1611 if (tmp->type == EARTHWALL)
1612 {
1613 hit_player (tmp, op->stats.dam, op, AT_PHYSICAL, 1);
1614 return;
1615 }
1616 }
1617 }
1618
1619 void
1620 check_doors (object *op, maptile *m, int x, int y)
1621 {
1622 object *tmp;
1623
1624 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
1625 {
1626 if (tmp->type == DOOR)
1627 {
1628 hit_player (tmp, 1000, op, AT_PHYSICAL, 1);
1629 return;
1630 }
1631 }
1632 }
1633
1634 /* find_mon_throw_ob() - modeled on find_throw_ob
1635 * This is probably overly simplistic as it is now - We want
1636 * monsters to throw things like chairs and other pieces of
1637 * furniture, even if they are not good throwable objects.
1638 * Probably better to have the monster throw a throwable object
1639 * first, then throw any non equipped weapon.
1640 */
1641 object *
1642 find_mon_throw_ob (object *op)
1643 {
1644 object *tmp = NULL;
1645
1646 if (op->head)
1647 tmp = op->head;
1648 else
1649 tmp = op;
1650
1651 /* New throw code: look through the inventory. Grap the first legal is_thrown
1652 * marked item and throw it to the enemy.
1653 */
1654 for (tmp = op->inv; tmp; tmp = tmp->below)
1655 {
1656 /* Can't throw invisible objects or items that are applied */
1657 if (tmp->invisible || QUERY_FLAG (tmp, FLAG_APPLIED))
1658 continue;
1659
1660 if (QUERY_FLAG (tmp, FLAG_IS_THROWN))
1661 break;
1662
1663 }
1664
1665 #ifdef DEBUG_THROW
1666 LOG (llevDebug, "%s chooses to throw: %s (%d)\n", op->name, !(tmp) ? "(nothing)" : query_name (tmp), tmp ? tmp->count : -1);
1667 #endif
1668
1669 return tmp;
1670 }
1671
1672 /* determine if we can 'detect' the enemy. Check for walls blocking the
1673 * los. Also, just because its hidden/invisible, we may be sensitive/smart
1674 * enough (based on Wis & Int) to figure out where the enemy is. -b.t.
1675 * modified by MSW to use the get_rangevector so that map tiling works
1676 * properly. I also so odd code in place that checked for x distance
1677 * OR y distance being within some range - that seemed wrong - both should
1678 * be within the valid range. MSW 2001-08-05
1679 * Returns 0 if enemy can not be detected, 1 if it is detected
1680 */
1681
1682 int
1683 can_detect_enemy (object *op, object *enemy, rv_vector * rv)
1684 {
1685 int radius = MIN_MON_RADIUS, hide_discovery;
1686
1687 /* null detection for any of these condtions always */
1688 if (!op || !enemy || !op->map || !enemy->map)
1689 return 0;
1690
1691 /* If the monster (op) has no way to get to the enemy, do nothing */
1692 if (!on_same_map (op, enemy))
1693 return 0;
1694
1695 get_rangevector (op, enemy, rv, 0);
1696
1697 /* Monsters always ignore the DM */
1698 if ((op->type != PLAYER) && QUERY_FLAG (enemy, FLAG_WIZ))
1699 return 0;
1700
1701 /* simple check. Should probably put some range checks in here. */
1702 if (can_see_enemy (op, enemy))
1703 return 1;
1704
1705 /* The rest of this is for monsters. Players are on their own for
1706 * finding enemies!
1707 */
1708 if (op->type == PLAYER)
1709 return 0;
1710
1711 /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE
1712 * flag (which was already checked) in can_see_enmy (). Lets get out of here
1713 */
1714 if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden)))
1715 return 0;
1716
1717 /* use this for invis also */
1718 hide_discovery = op->stats.Int / 5;
1719
1720 /* Determine Detection radii */
1721 if (!enemy->hide) /* to detect non-hidden (eg dark/invis enemy) */
1722 radius = (op->stats.Wis / 5) + 1 > MIN_MON_RADIUS ? (op->stats.Wis / 5) + 1 : MIN_MON_RADIUS;
1723 else
1724 { /* a level/INT/Dex adjustment for hiding */
1725 object *sk_hide;
1726 int bonus = (op->level / 2) + (op->stats.Int / 5);
1727
1728 if (enemy->type == PLAYER)
1729 {
1730 if ((sk_hide = find_skill_by_number (enemy, SK_HIDING)))
1731 bonus -= sk_hide->level;
1732 else
1733 {
1734 LOG (llevError, "can_detect_enemy() got hidden player w/o hiding skill!\n");
1735 make_visible (enemy);
1736 radius = radius < MIN_MON_RADIUS ? MIN_MON_RADIUS : radius;
1737 }
1738 }
1739 else /* enemy is not a player */
1740 bonus -= enemy->level;
1741
1742 radius += bonus / 5;
1743 hide_discovery += bonus * 5;
1744 } /* else creature has modifiers for hiding */
1745
1746 /* Radii stealth adjustment. Only if you are stealthy
1747 * will you be able to sneak up closer to creatures */
1748 if (QUERY_FLAG (enemy, FLAG_STEALTH))
1749 radius = radius / 2, hide_discovery = hide_discovery / 3;
1750
1751 /* Radii adjustment for enemy standing in the dark */
1752 if (op->map->darkness > 0 && !stand_in_light (enemy))
1753 {
1754 /* on dark maps body heat can help indicate location with infravision
1755 * undead don't have body heat, so no benefit detecting them.
1756 */
1757 if (QUERY_FLAG (op, FLAG_SEE_IN_DARK) && !is_true_undead (enemy))
1758 radius += op->map->darkness / 2;
1759 else
1760 radius -= op->map->darkness / 2;
1761
1762 /* op next to a monster (and not in complete darkness)
1763 * the monster should have a chance to see you.
1764 */
1765 if (radius < MIN_MON_RADIUS && op->map->darkness < 5 && rv->distance <= 1)
1766 radius = MIN_MON_RADIUS;
1767 } /* if on dark map */
1768
1769 /* Lets not worry about monsters that have incredible detection
1770 * radii, we only need to worry here about things the player can
1771 * (potentially) see. This is 13, as that is the maximum size the player
1772 * may have for their map - in that way, creatures at the edge will
1773 * do something. Note that the distance field in the
1774 * vector is real distance, so in theory this should be 18 to
1775 * find that.
1776 */
1777 if (radius > 13)
1778 radius = 13;
1779
1780 /* Enemy in range! Now test for detection */
1781 if ((int) rv->distance <= radius)
1782 {
1783 /* ah, we are within range, detected? take cases */
1784 if (!enemy->invisible) /* enemy in dark squares... are seen! */
1785 return 1;
1786
1787 /* hidden or low-quality invisible */
1788 if (enemy->hide && (rv->distance <= 1) && (rndm (100) <= hide_discovery))
1789 {
1790 make_visible (enemy);
1791 /* inform players of new status */
1792 if (enemy->type == PLAYER && player_can_view (enemy, op))
1793 new_draw_info_format (NDI_UNIQUE, 0, enemy, "You are discovered by %s!", &op->name);
1794 return 1; /* detected enemy */
1795 }
1796 else if (enemy->invisible)
1797 {
1798 /* Change this around - instead of negating the invisible, just
1799 * return true so that the mosnter that managed to detect you can
1800 * do something to you. Decreasing the duration of invisible
1801 * doesn't make a lot of sense IMO, as a bunch of stupid creatures
1802 * can then basically negate the spell. The spell isn't negated -
1803 * they just know where you are!
1804 */
1805 if ((rndm (50)) <= hide_discovery)
1806 {
1807 if (enemy->type == PLAYER)
1808 {
1809 new_draw_info_format (NDI_UNIQUE, 0, enemy, "You see %s noticing your position.", query_name (op));
1810 }
1811 return 1;
1812 }
1813 }
1814 } /* within range */
1815
1816 /* Wasn't detected above, so still hidden */
1817 return 0;
1818 }
1819
1820 /* determine if op stands in a lighted square. This is not a very
1821 * intellegent algorithm. For one thing, we ignore los here, SO it
1822 * is possible for a bright light to illuminate a player on the
1823 * other side of a wall (!).
1824 */
1825 int
1826 stand_in_light (object *op)
1827 {
1828 sint16 nx, ny;
1829 maptile *m;
1830
1831 if (!op)
1832 return 0;
1833
1834 if (op->glow_radius > 0)
1835 return 1;
1836
1837 if (op->map)
1838 {
1839 int x, y, x1, y1;
1840
1841 /* Check the spaces with the max light radius to see if any of them
1842 * have lights, and if any of them light the player enough, then return 1.
1843 */
1844 for (x = op->x - MAX_LIGHT_RADII; x <= op->x + MAX_LIGHT_RADII; x++)
1845 {
1846 for (y = op->y - MAX_LIGHT_RADII; y <= op->y + MAX_LIGHT_RADII; y++)
1847 {
1848 m = op->map;
1849 nx = x;
1850 ny = y;
1851
1852 if (get_map_flags (m, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP)
1853 continue;
1854
1855 x1 = abs (x - op->x) * abs (x - op->x);
1856 y1 = abs (y - op->y) * abs (y - op->y);
1857 if (isqrt (x1 + y1) < GET_MAP_LIGHT (m, nx, ny))
1858 return 1;
1859 }
1860 }
1861 }
1862
1863 return 0;
1864 }
1865
1866 /* assuming no walls/barriers, lets check to see if its *possible*
1867 * to see an enemy. Note, "detection" is different from "seeing".
1868 * See can_detect_enemy() for more details. -b.t.
1869 * return 0 if can't be seen, 1 if can be
1870 */
1871 int
1872 can_see_enemy (object *op, object *enemy)
1873 {
1874 object *looker = op->head ? op->head : op;
1875
1876 /* safety */
1877 if (!looker || !enemy || !QUERY_FLAG (looker, FLAG_ALIVE))
1878 return 0;
1879
1880 /* we dont give a full treatment of xrays here (shorter range than normal,
1881 * see through walls). Should we change the code elsewhere to make you
1882 * blind even if you can xray?
1883 */
1884 if (QUERY_FLAG (looker, FLAG_BLIND) && !QUERY_FLAG (looker, FLAG_XRAYS))
1885 return 0;
1886
1887 /* checking for invisible things */
1888 if (enemy->invisible)
1889 {
1890 /* HIDDEN ENEMY. by definition, you can't see hidden stuff!
1891 * However,if you carry any source of light, then the hidden
1892 * creature is seeable (and stupid) */
1893
1894 if (has_carried_lights (enemy))
1895 {
1896 if (enemy->hide)
1897 {
1898 make_visible (enemy);
1899 new_draw_info (NDI_UNIQUE, 0, enemy, "Your light reveals your hiding spot!");
1900 }
1901 return 1;
1902 }
1903 else if (enemy->hide)
1904 return 0;
1905
1906 /* Invisible enemy. Break apart the check for invis undead/invis looker
1907 * into more simple checks - the QUERY_FLAG doesn't return 1/0 values,
1908 * and making it a conditional makes the code pretty ugly.
1909 */
1910 if (!QUERY_FLAG (looker, FLAG_SEE_INVISIBLE))
1911 {
1912 if (makes_invisible_to (enemy, looker))
1913 return 0;
1914 }
1915 }
1916 else if (looker->type == PLAYER) /* for players, a (possible) shortcut */
1917 if (player_can_view (looker, enemy))
1918 return 1;
1919
1920 /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen
1921 * unless they carry a light or stand in light. Darkness doesnt
1922 * inhibit the undead per se (but we should give their archs
1923 * CAN_SEE_IN_DARK, this is just a safety
1924 * we care about the enemy maps status, not the looker.
1925 * only relevant for tiled maps, but it is possible that the
1926 * enemy is on a bright map and the looker on a dark - in that
1927 * case, the looker can still see the enemy
1928 */
1929 if (enemy->map->darkness > 0 && !stand_in_light (enemy)
1930 && (!QUERY_FLAG (looker, FLAG_SEE_IN_DARK) || !is_true_undead (looker) || !QUERY_FLAG (looker, FLAG_XRAYS)))
1931 return 0;
1932
1933 return 1;
1934 }