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

# User Rev Content
1 elmex 1.1 /*
2 pippijn 1.22 * 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 elmex 1.1
25     #include <global.h>
26 root 1.18 #include <sproto.h>
27     #include <spells.h>
28     #include <skills.h>
29 elmex 1.1
30 root 1.8 #define MIN_MON_RADIUS 3 /* minimum monster detection radius */
31 elmex 1.1
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 root 1.8 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 elmex 1.1
64 root 1.8 if (npc->enemy)
65 elmex 1.1 {
66 root 1.8 /* 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 root 1.26 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 root 1.8 npc->enemy = NULL;
95 elmex 1.1
96     }
97 root 1.8 return can_detect_enemy (npc, npc->enemy, rv) ? npc->enemy : NULL;
98 elmex 1.1 }
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 root 1.8 object *
115     find_nearest_living_creature (object *npc)
116     {
117     int i, mflags;
118     sint16 nx, ny;
119 root 1.12 maptile *m;
120 root 1.8 int search_arr[SIZEOFFREE];
121    
122     get_search_arr (search_arr);
123 root 1.21
124 root 1.8 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 root 1.21
135 root 1.8 if (mflags & P_OUT_OF_MAP)
136     continue;
137    
138     if (mflags & P_IS_ALIVE)
139     {
140 root 1.21 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 root 1.8 if (can_see_monsterP (m, nx, ny, i))
143     return tmp;
144 root 1.21 }
145 elmex 1.1 }
146 root 1.21
147     return 0;
148 elmex 1.1 }
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 root 1.8 object *
160     find_enemy (object *npc, rv_vector * rv)
161 elmex 1.1 {
162 root 1.8 object *attacker, *tmp = NULL;
163    
164     attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */
165 root 1.9 npc->attacked_by = 0; /* always clear the attacker entry */
166 elmex 1.1
167 root 1.8 /* 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 root 1.9
172 root 1.8 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 root 1.9
192 root 1.8 if (tmp)
193     get_rangevector (npc, tmp, rv, 0);
194 root 1.9
195 root 1.8 return tmp;
196     }
197 elmex 1.1
198 root 1.8 /* we check our old enemy. */
199 root 1.9 if (!(tmp = check_enemy (npc, rv)))
200 elmex 1.1 {
201 root 1.8 if (attacker) /* if we have an attacker, check him */
202 elmex 1.1 {
203 root 1.9 /* 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 elmex 1.1 {
212 root 1.9 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 elmex 1.1 }
216     }
217 root 1.8
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 elmex 1.1 {
221 root 1.8 npc->enemy = get_nearest_player (npc);
222     if (npc->enemy)
223     tmp = check_enemy (npc, rv);
224 elmex 1.1 }
225 root 1.8
226 elmex 1.1 }
227    
228 root 1.8 return tmp;
229 elmex 1.1 }
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 root 1.8 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 elmex 1.1
242 root 1.8 /* 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 elmex 1.1
261 root 1.8 radius = (dark > MIN_MON_RADIUS) ? (dark + 1) : MIN_MON_RADIUS;
262     }
263     else if (!QUERY_FLAG (op, FLAG_SLEEP))
264     return 1;
265 elmex 1.1
266 root 1.8 /* 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 elmex 1.1 }
274 root 1.8 return 0;
275 elmex 1.1 }
276    
277 root 1.8 int
278     move_randomly (object *op)
279     {
280     int i;
281 elmex 1.1
282 root 1.8 /* Give up to 15 chances for a monster to move randomly */
283     for (i = 0; i < 15; i++)
284     {
285 root 1.23 if (move_object (op, rndm (8) + 1))
286 root 1.8 return 1;
287 elmex 1.1 }
288 root 1.8 return 0;
289 elmex 1.1 }
290    
291     /*
292     * Move-monster returns 1 if the object has been freed, otherwise 0.
293     */
294    
295 root 1.8 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 root 1.9 /* we have an enemy, just tell him we want him dead */
316     enemy->attacked_by = op; /* our ptr */
317 root 1.8
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 root 1.4
343 root 1.8 /* generate sp, if applicable */
344     if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp)
345     {
346 root 1.4
347 root 1.8 /* 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 elmex 1.1 }
360    
361 root 1.8 /* this should probably get modified by many more values.
362     * (eg, creatures resistance to fear, level, etc. )
363     */
364 root 1.23 if (QUERY_FLAG (op, FLAG_SCARED) && !(rndm (20)))
365 root 1.8 {
366     CLEAR_FLAG (op, FLAG_SCARED); /* Time to regain some "guts"... */
367 elmex 1.1 }
368    
369 root 1.8 if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy)))
370     return QUERY_FLAG (op, FLAG_FREED);
371 elmex 1.1
372 root 1.8 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 root 1.2 }
378    
379 root 1.8 /* check if monster pops out of hidden spot */
380     if (op->hide)
381     do_hidden_move (op);
382 root 1.2
383 root 1.8 if (op->pick_up)
384     monster_check_pickup (op);
385 root 1.2
386 root 1.8 if (op->will_apply)
387     monster_apply_below (op); /* Check for items to apply below */
388 root 1.2
389 root 1.8 /* 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 root 1.14 op->destroy ();
395 root 1.8 return 1;
396 root 1.4 }
397 elmex 1.1
398 root 1.8 /* 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 elmex 1.1 {
405 root 1.8 switch (op->attack_movement & HI4)
406     {
407 root 1.4 case (PETMOVE):
408 root 1.8 pet_move (op);
409     break;
410 root 1.4
411     case (CIRCLE1):
412 root 1.8 circ1_move (op);
413     break;
414 root 1.4
415     case (CIRCLE2):
416 root 1.8 circ2_move (op);
417     break;
418 root 1.4
419     case (PACEV):
420 root 1.8 pace_movev (op);
421     break;
422 root 1.4
423     case (PACEH):
424 root 1.8 pace_moveh (op);
425     break;
426 root 1.4
427     case (PACEV2):
428 root 1.8 pace2_movev (op);
429     break;
430 root 1.4
431     case (PACEH2):
432 root 1.8 pace2_moveh (op);
433     break;
434 root 1.4
435     case (RANDO):
436 root 1.8 rand_move (op);
437     break;
438 root 1.4
439     case (RANDO2):
440 root 1.8 move_randomly (op);
441     break;
442 root 1.4 }
443 root 1.8 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 elmex 1.25 if ((op->attack_movement & HI4) == PETMOVE
454     && (owner = op->owner) != NULL
455     && !on_same_map (op, owner)
456     && !owner->flag [FLAG_REMOVED])
457 root 1.8 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 root 1.23 dir = absdir (dir + rndm (3) + rndm (3) - 2);
497 root 1.8
498 root 1.23 if (QUERY_FLAG (op, FLAG_CAST_SPELL) && !(rndm (3)))
499 root 1.8 {
500     if (monster_cast_spell (op, part, enemy, dir, &rv1))
501 root 1.4 return 0;
502     }
503 elmex 1.1
504 root 1.23 if (QUERY_FLAG (op, FLAG_READY_SCROLL) && !(rndm (3)))
505 root 1.8 {
506     if (monster_use_scroll (op, part, enemy, dir, &rv1))
507     return 0;
508     }
509 elmex 1.1
510 root 1.23 if (QUERY_FLAG (op, FLAG_READY_RANGE) && !(rndm (3)))
511 root 1.8 {
512     if (monster_use_range (op, part, enemy, dir))
513     return 0;
514     }
515 root 1.23 if (QUERY_FLAG (op, FLAG_READY_SKILL) && !(rndm (3)))
516 root 1.8 {
517     if (monster_use_skill (op, rv.part, enemy, rv.direction))
518     return 0;
519     }
520 root 1.23 if (QUERY_FLAG (op, FLAG_READY_BOW) && !(rndm (2)))
521 root 1.8 {
522     if (monster_use_bow (op, part, enemy, dir))
523     return 0;
524     }
525     } /* for processing of all parts */
526     } /* If not scared */
527 root 1.4
528 elmex 1.1
529 root 1.8 part = rv.part;
530     dir = rv.direction;
531 elmex 1.1
532 root 1.8 if (QUERY_FLAG (op, FLAG_SCARED) || QUERY_FLAG (op, FLAG_RUN_AWAY))
533     dir = absdir (dir + 4);
534 elmex 1.1
535 root 1.8 if (QUERY_FLAG (op, FLAG_CONFUSED))
536 root 1.23 dir = absdir (dir + rndm (3) + rndm (3) - 2);
537 elmex 1.1
538 root 1.8 pre_att_dir = dir; /* remember the original direction */
539 elmex 1.1
540 root 1.8 if ((op->attack_movement & LO4) && !QUERY_FLAG (op, FLAG_SCARED))
541     {
542     switch (op->attack_movement & LO4)
543     {
544 root 1.4 case DISTATT:
545 root 1.8 dir = dist_att (dir, op, enemy, part, &rv);
546     break;
547 root 1.4
548     case RUNATT:
549 root 1.8 dir = run_att (dir, op, enemy, part, &rv);
550     break;
551 root 1.4
552     case HITRUN:
553 root 1.8 dir = hitrun_att (dir, op, enemy);
554     break;
555 root 1.4
556     case WAITATT:
557 root 1.8 dir = wait_att (dir, op, enemy, part, &rv);
558     break;
559 root 1.4
560 root 1.8 case RUSH: /* default - monster normally moves towards player */
561 root 1.4 case ALLRUN:
562 root 1.8 break;
563 root 1.4
564     case DISTHIT:
565 root 1.8 dir = disthit_att (dir, op, enemy, part, &rv);
566     break;
567 root 1.4
568     case WAIT2:
569 root 1.8 dir = wait_att2 (dir, op, enemy, part, &rv);
570     break;
571 root 1.4
572     default:
573 root 1.8 LOG (llevDebug, "Illegal low mon-move: %d\n", op->attack_movement & LO4);
574 root 1.4 }
575 elmex 1.1 }
576    
577 root 1.8 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 elmex 1.1
588 root 1.8 return 0;
589     }
590    
591     if (QUERY_FLAG (op, FLAG_SCARED) || !can_hit (part, enemy, &rv) || QUERY_FLAG (op, FLAG_RUN_AWAY))
592     {
593 elmex 1.1
594 root 1.8 /* Try move around corners if !close */
595     int maxdiff = (QUERY_FLAG (op, FLAG_ONLY_ATTACK) || RANDOM () & 1) ? 1 : 2;
596 elmex 1.1
597 root 1.8 for (diff = 1; diff <= maxdiff; diff++)
598     {
599     /* try different detours */
600     int m = 1 - (RANDOM () & 2); /* Try left or right first? */
601 elmex 1.1
602 root 1.8 if (move_object (op, absdir (dir + diff * m)) || move_object (op, absdir (dir - diff * m)))
603 root 1.4 return 0;
604     }
605     }
606 root 1.8 } /* if monster is not standing still */
607 elmex 1.1
608 root 1.8 /* 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 elmex 1.1
635 root 1.8 if (nearest_player && nearest_player != enemy && !can_hit (part, enemy, &rv))
636     {
637     op->enemy = NULL;
638     enemy = nearest_player;
639 root 1.4 }
640 elmex 1.1 }
641    
642 root 1.8 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 elmex 1.1 {
652 root 1.8 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 elmex 1.1
660 root 1.8 if (QUERY_FLAG (part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */
661     return 1;
662 elmex 1.1
663 root 1.8 if (QUERY_FLAG (op, FLAG_ONLY_ATTACK))
664 elmex 1.1 {
665 root 1.13 op->remove ();
666 root 1.14 op->destroy ();
667 root 1.8 return 1;
668 elmex 1.1 }
669 root 1.8 return 0;
670 elmex 1.1 }
671 root 1.5
672 root 1.8 int
673     can_hit (object *ob1, object *ob2, rv_vector * rv)
674     {
675     object *more;
676     rv_vector rv1;
677 elmex 1.1
678 root 1.23 if (QUERY_FLAG (ob1, FLAG_CONFUSED) && !(rndm (3)))
679 root 1.8 return 0;
680 elmex 1.1
681 root 1.8 if (abs (rv->distance_x) < 2 && abs (rv->distance_y) < 2)
682     return 1;
683 elmex 1.1
684 root 1.8 /* 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 elmex 1.1 }
693 root 1.8 return 0;
694 elmex 1.1
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 root 1.8 static int
714     monster_should_cast_spell (object *monster, object *spell_ob)
715 elmex 1.1 {
716 root 1.8 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 elmex 1.1
723 root 1.8 return 1;
724 elmex 1.1
725 root 1.8 return 0;
726 elmex 1.1 }
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 root 1.8 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 elmex 1.1 }
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 root 1.8 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 root 1.15 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
788 root 1.8 {
789     get_rangevector (head, owner, &rv1, 0x1);
790     if (dirdiff (dir, rv1.direction) < 2)
791     {
792     return 0; /* Might hit owner with spell */
793 root 1.4 }
794 elmex 1.1 }
795    
796 root 1.8 if (QUERY_FLAG (head, FLAG_CONFUSED))
797 root 1.23 dir = absdir (dir + rndm (3) + rndm (3) - 2);
798 root 1.8
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 root 1.4 }
811 root 1.8 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 root 1.4 }
818 root 1.8 spell_item = spell_item->inv;
819 root 1.4 }
820 elmex 1.1 }
821 root 1.8 else
822     spell_item = head->spellitem;
823 elmex 1.1
824 root 1.8 if (!spell_item)
825     return 0;
826 elmex 1.1
827 root 1.8 /* 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 elmex 1.1
838 root 1.8 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 elmex 1.1
841 root 1.8 /* set this to null, so next time monster will choose something different */
842     head->spellitem = NULL;
843 elmex 1.1
844 root 1.8 return cast_spell (part, part, dir, spell_item, NULL);
845 elmex 1.1 }
846    
847    
848 root 1.8 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 root 1.15 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
865 root 1.8 {
866     get_rangevector (head, owner, &rv1, 0x1);
867     if (dirdiff (dir, rv1.direction) < 2)
868     {
869     return 0; /* Might hit owner with spell */
870 root 1.4 }
871 elmex 1.1 }
872    
873 root 1.8 if (QUERY_FLAG (head, FLAG_CONFUSED))
874 root 1.23 dir = absdir (dir + rndm (3) + rndm (3) - 2);
875 elmex 1.1
876 root 1.8 for (scroll = head->inv; scroll; scroll = scroll->below)
877     if (scroll->type == SCROLL && monster_should_cast_spell (head, scroll->inv))
878     break;
879 elmex 1.1
880 root 1.8 /* Used up all his scrolls, so nothing do to */
881     if (!scroll)
882     {
883     CLEAR_FLAG (head, FLAG_READY_SCROLL);
884     return 0;
885 elmex 1.1 }
886    
887 root 1.8 /* Spell should be cast on caster (ie, heal, strength) */
888     if (scroll->inv->range == 0)
889     dir = 0;
890 elmex 1.1
891 root 1.8 apply_scroll (part, scroll, dir);
892     return 1;
893 elmex 1.1 }
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 root 1.8 */
906     int
907     monster_use_skill (object *head, object *part, object *pl, int dir)
908     {
909     object *skill, *owner;
910 elmex 1.1
911 root 1.8 if (!(dir = path_to_player (part, pl, 0)))
912     return 0;
913    
914 root 1.15 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
915 root 1.8 {
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 root 1.27
922 root 1.8 if (QUERY_FLAG (head, FLAG_CONFUSED))
923 root 1.23 dir = absdir (dir + rndm (3) + rndm (3) - 2);
924 root 1.8
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 elmex 1.1
931 root 1.27 for (skill = head->inv; skill; skill = skill->below)
932 root 1.8 if (skill->type == SKILL && skill != head->chosen_skill)
933     {
934     head->chosen_skill = skill;
935     break;
936     }
937 elmex 1.1
938 root 1.8 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 elmex 1.1 }
944 root 1.27
945 root 1.8 /* use skill */
946     return do_skill (head, part, head->chosen_skill, dir, NULL);
947 elmex 1.1 }
948    
949     /* Monster will use a ranged spell attack. */
950 root 1.8 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 root 1.15 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
960 elmex 1.1 {
961 root 1.8 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
962 elmex 1.1
963 root 1.8 if (dirdiff (dir, dir2) < 2)
964     return 0; /* Might hit owner with spell */
965 elmex 1.1 }
966 root 1.8 if (QUERY_FLAG (head, FLAG_CONFUSED))
967 root 1.23 dir = absdir (dir + rndm (3) + rndm (3) - 2);
968 elmex 1.1
969 root 1.27 for (wand = head->inv; wand; wand = wand->below)
970 root 1.8 {
971     if (wand->type == WAND)
972 elmex 1.1 {
973 root 1.8 /* 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 elmex 1.1
978 root 1.8 cast_spell (head, wand, dir, wand->inv, NULL);
979 elmex 1.1
980 root 1.8 if (!(--wand->stats.food))
981     {
982     if (wand->arch)
983 elmex 1.1 {
984 root 1.8 CLEAR_FLAG (wand, FLAG_ANIMATE);
985     wand->face = wand->arch->clone.face;
986 root 1.18 wand->set_speed (0);
987 elmex 1.1 }
988     }
989 root 1.8 /* 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 elmex 1.1
999 root 1.8 /* 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 elmex 1.1
1006 root 1.8 /* Success */
1007     return 1;
1008 elmex 1.1 }
1009 root 1.8 }
1010    
1011     if (at_least_one)
1012     return 0;
1013 elmex 1.1
1014 root 1.8 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 elmex 1.1
1019 root 1.8 int
1020     monster_use_bow (object *head, object *part, object *pl, int dir)
1021     {
1022     object *owner;
1023 elmex 1.1
1024 root 1.8 if (!(dir = path_to_player (part, pl, 0)))
1025     return 0;
1026     if (QUERY_FLAG (head, FLAG_CONFUSED))
1027 root 1.23 dir = absdir (dir + rndm (3) + rndm (3) - 2);
1028 elmex 1.1
1029 root 1.15 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
1030 root 1.8 {
1031     int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
1032 elmex 1.1
1033 root 1.8 if (dirdiff (dir, dir2) < 1)
1034     return 0; /* Might hit owner with arrow */
1035 elmex 1.1 }
1036    
1037 root 1.8 /* in server/player.c */
1038     return fire_bow (head, part, NULL, dir, 0, part->x, part->y);
1039 elmex 1.1
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 root 1.8 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 elmex 1.1
1059 root 1.8 if (other_weap == NULL) /* No other weapons */
1060     return 1;
1061 elmex 1.1
1062 root 1.8 /* 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 elmex 1.1
1068 root 1.8 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 elmex 1.1 }
1081    
1082 root 1.8 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 elmex 1.1
1092 root 1.8 if (other_armour == NULL) /* No other armour, use the new */
1093     return 1;
1094 elmex 1.1
1095 root 1.8 /* 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 elmex 1.1 }
1113    
1114 root 1.8 /* Very few armours have stats, so not much need to worry about those. */
1115 elmex 1.1
1116 root 1.8 if (val > 0)
1117     return 1;
1118     else
1119     return 0;
1120 elmex 1.1 }
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 root 1.8 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 root 1.13 tmp->remove ();
1148 root 1.8 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 root 1.11 if (next && next->destroyed ())
1155 root 1.8 return;
1156 elmex 1.1 }
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 root 1.8 int
1166     monster_can_pick (object *monster, object *item)
1167     {
1168     int flag = 0;
1169     int i;
1170 elmex 1.1
1171 root 1.8 if (!can_pick (monster, item))
1172     return 0;
1173 elmex 1.1
1174 root 1.8 if (QUERY_FLAG (item, FLAG_UNPAID))
1175     return 0;
1176 elmex 1.1
1177 root 1.8 if (monster->pick_up & 64) /* All */
1178     flag = 1;
1179 elmex 1.1
1180 root 1.8 else
1181     switch (item->type)
1182     {
1183     case MONEY:
1184     case GEM:
1185     flag = monster->pick_up & 2;
1186 root 1.4 break;
1187    
1188 root 1.8 case FOOD:
1189     flag = monster->pick_up & 4;
1190 root 1.4 break;
1191    
1192 root 1.8 case WEAPON:
1193     flag = (monster->pick_up & 8) || QUERY_FLAG (monster, FLAG_USE_WEAPON);
1194 root 1.4 break;
1195    
1196 root 1.8 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 root 1.4 break;
1204    
1205 root 1.8 case SKILL:
1206     flag = QUERY_FLAG (monster, FLAG_CAN_USE_SKILL);
1207 root 1.4 break;
1208    
1209 root 1.8 case RING:
1210     flag = QUERY_FLAG (monster, FLAG_USE_RING);
1211 root 1.4 break;
1212    
1213 root 1.8 case WAND:
1214     case HORN:
1215     case ROD:
1216     flag = QUERY_FLAG (monster, FLAG_USE_RANGE);
1217 root 1.4 break;
1218    
1219 root 1.8 case SPELLBOOK:
1220     flag = (monster->arch != NULL && QUERY_FLAG ((&monster->arch->clone), FLAG_CAST_SPELL));
1221 root 1.4 break;
1222    
1223 root 1.8 case SCROLL:
1224     flag = QUERY_FLAG (monster, FLAG_USE_SCROLL);
1225 root 1.4 break;
1226    
1227 root 1.8 case BOW:
1228     case ARROW:
1229     flag = QUERY_FLAG (monster, FLAG_USE_BOW);
1230 root 1.4 break;
1231 root 1.8 }
1232 root 1.27
1233 root 1.8 /* 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 root 1.4 }
1244 elmex 1.1 }
1245    
1246 root 1.8 if (((!(monster->pick_up & 32)) && flag) || ((monster->pick_up & 32) && (!flag)))
1247     return 1;
1248     return 0;
1249 elmex 1.1 }
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 root 1.8 void
1258     monster_apply_below (object *monster)
1259     {
1260     object *tmp, *next;
1261 elmex 1.1
1262 root 1.8 for (tmp = monster->below; tmp != NULL; tmp = next)
1263     {
1264     next = tmp->below;
1265     switch (tmp->type)
1266     {
1267 root 1.4 case CF_HANDLE:
1268     case TRIGGER:
1269 root 1.8 if (monster->will_apply & 1)
1270     manual_apply (monster, tmp, 0);
1271     break;
1272 root 1.4
1273     case TREASURE:
1274 root 1.8 if (monster->will_apply & 2)
1275     manual_apply (monster, tmp, 0);
1276     break;
1277 root 1.4
1278     }
1279 root 1.8 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1280     break;
1281 elmex 1.1 }
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 root 1.8 void
1295     monster_check_apply (object *mon, object *item)
1296     {
1297     int flag = 0;
1298 elmex 1.1
1299 root 1.27 if (item->type == SPELLBOOK && mon->arch && (QUERY_FLAG ((&mon->arch->clone), FLAG_CAST_SPELL)))
1300 root 1.8 {
1301     SET_FLAG (mon, FLAG_CAST_SPELL);
1302     return;
1303 elmex 1.1 }
1304    
1305 root 1.8 /* 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 elmex 1.1
1318 root 1.27 for (bow = mon->inv; bow; bow = bow->below)
1319 root 1.8 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 elmex 1.1 }
1326    
1327 root 1.8 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 root 1.16 else if (item->is_armor ())
1344 root 1.8 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 elmex 1.1 }
1379    
1380 root 1.8 /* 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 elmex 1.1
1388 root 1.8 /* 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 elmex 1.1 return;
1394 root 1.8
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 elmex 1.1 }
1401    
1402 root 1.8 void
1403     npc_call_help (object *op)
1404     {
1405     int x, y, mflags;
1406     object *npc;
1407     sint16 sx, sy;
1408 root 1.12 maptile *m;
1409 root 1.8
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 root 1.17 for (npc = GET_MAP_OB (m, sx, sy); npc != NULL; npc = npc->above)
1422 root 1.8 if (QUERY_FLAG (npc, FLAG_ALIVE) && QUERY_FLAG (npc, FLAG_UNAGGRESSIVE))
1423     npc->enemy = op->enemy;
1424     }
1425 elmex 1.1 }
1426    
1427 root 1.8 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 root 1.27
1437 root 1.8 return 0;
1438 elmex 1.1 }
1439    
1440 root 1.8 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 elmex 1.1 }
1448 root 1.8 else if (ob->move_status > 20)
1449     ob->move_status = 0;
1450 root 1.27
1451 root 1.8 return absdir (dir + 4);
1452 elmex 1.1 }
1453    
1454 root 1.8 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 root 1.27
1464 root 1.8 return absdir (dir + 4);
1465 elmex 1.1 }
1466    
1467 root 1.8 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 elmex 1.1
1473 root 1.8 if (ob->move_status || inrange)
1474     ob->move_status++;
1475 elmex 1.1
1476 root 1.8 if (ob->move_status == 0)
1477 elmex 1.1 return 0;
1478 root 1.8 else if (ob->move_status < 10)
1479     return dir;
1480     else if (ob->move_status < 15)
1481     return absdir (dir + 4);
1482 root 1.27
1483 root 1.8 ob->move_status = 0;
1484     return 0;
1485 elmex 1.1 }
1486    
1487 root 1.8 int
1488     disthit_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1489     {
1490 elmex 1.1
1491 root 1.8 /* 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 root 1.27
1501 root 1.8 return dist_att (dir, ob, enemy, part, rv);
1502 elmex 1.1 }
1503    
1504 root 1.8 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 root 1.27
1510 root 1.8 return 0;
1511 elmex 1.1 }
1512    
1513 root 1.8 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 root 1.27
1518 root 1.8 if (++ob->move_status > 11)
1519 elmex 1.1 ob->move_status = 0;
1520 root 1.27
1521 root 1.8 if (!(move_object (ob, circle[ob->move_status])))
1522 root 1.27 move_object (ob, rndm (8) + 1);
1523 elmex 1.1 }
1524    
1525 root 1.8 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 root 1.27
1530 root 1.8 if (++ob->move_status > 19)
1531 elmex 1.1 ob->move_status = 0;
1532 root 1.27
1533 root 1.8 if (!(move_object (ob, circle[ob->move_status])))
1534 root 1.27 move_object (ob, rndm (8) + 1);
1535 elmex 1.1 }
1536    
1537 root 1.8 void
1538     pace_movev (object *ob)
1539     {
1540 elmex 1.1 if (ob->move_status++ > 6)
1541     ob->move_status = 0;
1542 root 1.27
1543 elmex 1.1 if (ob->move_status < 4)
1544 root 1.27 move_object (ob, 5);
1545 elmex 1.1 else
1546 root 1.27 move_object (ob, 1);
1547 elmex 1.1 }
1548    
1549 root 1.8 void
1550     pace_moveh (object *ob)
1551     {
1552 elmex 1.1 if (ob->move_status++ > 6)
1553     ob->move_status = 0;
1554 root 1.27
1555 elmex 1.1 if (ob->move_status < 4)
1556 root 1.27 move_object (ob, 3);
1557 elmex 1.1 else
1558 root 1.27 move_object (ob, 7);
1559 elmex 1.1 }
1560    
1561 root 1.8 void
1562     pace2_movev (object *ob)
1563     {
1564     if (ob->move_status++ > 16)
1565 elmex 1.1 ob->move_status = 0;
1566 root 1.27
1567 root 1.8 if (ob->move_status < 6)
1568 root 1.27 move_object (ob, 5);
1569 elmex 1.1 else if (ob->move_status < 8)
1570     return;
1571 root 1.8 else if (ob->move_status < 13)
1572 root 1.27 move_object (ob, 1);
1573 root 1.8 else
1574     return;
1575     }
1576 elmex 1.1
1577 root 1.8 void
1578     pace2_moveh (object *ob)
1579     {
1580     if (ob->move_status++ > 16)
1581 elmex 1.1 ob->move_status = 0;
1582 root 1.27
1583 root 1.8 if (ob->move_status < 6)
1584 root 1.27 move_object (ob, 3);
1585 elmex 1.1 else if (ob->move_status < 8)
1586     return;
1587 root 1.8 else if (ob->move_status < 13)
1588 root 1.27 move_object (ob, 7);
1589 root 1.8 else
1590     return;
1591     }
1592 elmex 1.1
1593 root 1.8 void
1594     rand_move (object *ob)
1595     {
1596 elmex 1.1 int i;
1597 root 1.8
1598 root 1.23 if (ob->move_status < 1 || ob->move_status > 8 || !(move_object (ob, ob->move_status || !(rndm (9)))))
1599 elmex 1.1 for (i = 0; i < 5; i++)
1600 root 1.23 if (move_object (ob, ob->move_status = rndm (8) + 1))
1601 elmex 1.1 return;
1602     }
1603    
1604 root 1.8 void
1605 root 1.12 check_earthwalls (object *op, maptile *m, int x, int y)
1606 root 1.8 {
1607     object *tmp;
1608    
1609 root 1.17 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
1610 root 1.8 {
1611     if (tmp->type == EARTHWALL)
1612     {
1613     hit_player (tmp, op->stats.dam, op, AT_PHYSICAL, 1);
1614     return;
1615 root 1.4 }
1616 elmex 1.1 }
1617     }
1618    
1619 root 1.8 void
1620 root 1.12 check_doors (object *op, maptile *m, int x, int y)
1621 root 1.8 {
1622     object *tmp;
1623    
1624 root 1.17 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
1625 root 1.8 {
1626     if (tmp->type == DOOR)
1627     {
1628     hit_player (tmp, 1000, op, AT_PHYSICAL, 1);
1629     return;
1630 root 1.4 }
1631 elmex 1.1 }
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 root 1.8 object *
1642     find_mon_throw_ob (object *op)
1643     {
1644     object *tmp = NULL;
1645 elmex 1.1
1646 root 1.8 if (op->head)
1647     tmp = op->head;
1648     else
1649     tmp = op;
1650 elmex 1.1
1651 root 1.8 /* 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 elmex 1.1
1663     }
1664    
1665     #ifdef DEBUG_THROW
1666 root 1.8 LOG (llevDebug, "%s chooses to throw: %s (%d)\n", op->name, !(tmp) ? "(nothing)" : query_name (tmp), tmp ? tmp->count : -1);
1667 elmex 1.1 #endif
1668    
1669 root 1.8 return tmp;
1670 elmex 1.1 }
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 root 1.8 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 elmex 1.1
1691 root 1.8 /* 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 elmex 1.1
1695 root 1.8 get_rangevector (op, enemy, rv, 0);
1696 elmex 1.1
1697 root 1.8 /* Monsters always ignore the DM */
1698     if ((op->type != PLAYER) && QUERY_FLAG (enemy, FLAG_WIZ))
1699     return 0;
1700 elmex 1.1
1701 root 1.8 /* simple check. Should probably put some range checks in here. */
1702     if (can_see_enemy (op, enemy))
1703     return 1;
1704 elmex 1.1
1705 root 1.8 /* 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 elmex 1.1
1711 root 1.8 /* 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 elmex 1.1
1717 root 1.8 /* use this for invis also */
1718     hide_discovery = op->stats.Int / 5;
1719 elmex 1.1
1720 root 1.8 /* 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 root 1.4 }
1738     }
1739 root 1.8 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 elmex 1.1
1769 root 1.8 /* 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 root 1.4
1787 root 1.8 /* hidden or low-quality invisible */
1788 root 1.23 if (enemy->hide && (rv->distance <= 1) && (rndm (100) <= hide_discovery))
1789 root 1.8 {
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 root 1.23 if ((rndm (50)) <= hide_discovery)
1806 root 1.8 {
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 root 1.4 }
1811 root 1.8 return 1;
1812 root 1.4 }
1813     }
1814 root 1.8 } /* within range */
1815 elmex 1.1
1816 root 1.8 /* Wasn't detected above, so still hidden */
1817     return 0;
1818 elmex 1.1 }
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 root 1.8 int
1826     stand_in_light (object *op)
1827     {
1828     sint16 nx, ny;
1829 root 1.12 maptile *m;
1830 root 1.8
1831     if (!op)
1832     return 0;
1833 root 1.27
1834 root 1.8 if (op->glow_radius > 0)
1835     return 1;
1836 elmex 1.1
1837 root 1.8 if (op->map)
1838     {
1839     int x, y, x1, y1;
1840 elmex 1.1
1841 root 1.8 /* 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 root 1.4 }
1860     }
1861 elmex 1.1 }
1862 root 1.27
1863 root 1.8 return 0;
1864 elmex 1.1 }
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 root 1.8 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 elmex 1.1
1880 root 1.8 /* 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 elmex 1.1
1894 root 1.8 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 root 1.4 }
1901 root 1.8 return 1;
1902     }
1903     else if (enemy->hide)
1904     return 0;
1905 root 1.4
1906 root 1.8 /* 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 root 1.4 }
1915 root 1.8 }
1916     else if (looker->type == PLAYER) /* for players, a (possible) shortcut */
1917     if (player_can_view (looker, enemy))
1918     return 1;
1919 elmex 1.1
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 root 1.8 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 elmex 1.1 return 0;
1932    
1933     return 1;
1934     }