ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/monster.C
Revision: 1.36
Committed: Sun Jul 1 05:00:20 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.35: +10 -11 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

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