ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/monster.C
(Generate patch)

Comparing deliantra/server/server/monster.C (file contents):
Revision 1.8 by root, Sun Sep 10 15:59:57 2006 UTC vs.
Revision 1.24 by root, Thu Jan 18 21:27:19 2007 UTC

1
2/* 1/*
3 * static char *rcsid_monster_c = 2 * CrossFire, A Multiplayer game for X-windows
4 * "$Id: monster.C,v 1.8 2006/09/10 15:59:57 root Exp $"; 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>
5 */ 23 */
6 24
7/*
8 CrossFire, A Multiplayer game for X-windows
9
10 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
27 The authors can be reached via e-mail at crossfire-devel@real-time.com
28*/
29
30#include <global.h> 25#include <global.h>
31#ifndef __CEXTRACT__
32# include <sproto.h> 26#include <sproto.h>
33# include <spells.h> 27#include <spells.h>
34# include <skills.h> 28#include <skills.h>
35#endif
36
37 29
38#define MIN_MON_RADIUS 3 /* minimum monster detection radius */ 30#define MIN_MON_RADIUS 3 /* minimum monster detection radius */
39
40 31
41/* checks npc->enemy and returns that enemy if still valid, 32/* checks npc->enemy and returns that enemy if still valid,
42 * NULL otherwise. 33 * NULL otherwise.
43 * this is map tile aware. 34 * this is map tile aware.
44 * If this returns an enemy, the range vector rv should also be 35 * If this returns an enemy, the range vector rv should also be
121object * 112object *
122find_nearest_living_creature (object *npc) 113find_nearest_living_creature (object *npc)
123{ 114{
124 int i, mflags; 115 int i, mflags;
125 sint16 nx, ny; 116 sint16 nx, ny;
126 mapstruct *m; 117 maptile *m;
127 object *tmp;
128 int search_arr[SIZEOFFREE]; 118 int search_arr[SIZEOFFREE];
129 119
130 get_search_arr (search_arr); 120 get_search_arr (search_arr);
121
131 for (i = 0; i < SIZEOFFREE; i++) 122 for (i = 0; i < SIZEOFFREE; i++)
132 { 123 {
133 /* modified to implement smart searching using search_arr 124 /* modified to implement smart searching using search_arr
134 * guidance array to determine direction of search order 125 * guidance array to determine direction of search order
135 */ 126 */
136 nx = npc->x + freearr_x[search_arr[i]]; 127 nx = npc->x + freearr_x[search_arr[i]];
137 ny = npc->y + freearr_y[search_arr[i]]; 128 ny = npc->y + freearr_y[search_arr[i]];
138 m = npc->map; 129 m = npc->map;
139 130
140 mflags = get_map_flags (m, &m, nx, ny, &nx, &ny); 131 mflags = get_map_flags (m, &m, nx, ny, &nx, &ny);
132
141 if (mflags & P_OUT_OF_MAP) 133 if (mflags & P_OUT_OF_MAP)
142 continue; 134 continue;
143 135
144 if (mflags & P_IS_ALIVE) 136 if (mflags & P_IS_ALIVE)
145 { 137 {
146 tmp = get_map_ob (m, nx, ny); 138 for (object *tmp = m->at (nx, ny).top; tmp; tmp = tmp->below)
147 while (tmp != NULL && !QUERY_FLAG (tmp, FLAG_MONSTER) && !QUERY_FLAG (tmp, FLAG_GENERATOR) && tmp->type != PLAYER) 139 if (tmp->flag [FLAG_MONSTER] || tmp->flag [FLAG_GENERATOR] || tmp->type == PLAYER)
148 tmp = tmp->above;
149
150 if (!tmp)
151 {
152 LOG (llevDebug, "find_nearest_living_creature: map %s (%d,%d) has is_alive set but did not find a monster?\n",
153 m->path, nx, ny);
154 }
155 else
156 {
157 if (can_see_monsterP (m, nx, ny, i)) 140 if (can_see_monsterP (m, nx, ny, i))
158 return tmp; 141 return tmp;
159 } 142 }
160 } /* is something living on this space */
161 } 143 }
162 return NULL; /* nothing found */ 144
145 return 0;
163} 146}
164 147
165 148
166/* Tries to find an enmy for npc. We pass the range vector since 149/* Tries to find an enmy for npc. We pass the range vector since
167 * our caller will find the information useful. 150 * our caller will find the information useful.
175find_enemy (object *npc, rv_vector * rv) 158find_enemy (object *npc, rv_vector * rv)
176{ 159{
177 object *attacker, *tmp = NULL; 160 object *attacker, *tmp = NULL;
178 161
179 attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */ 162 attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */
180 npc->attacked_by = NULL; /* always clear the attacker entry */ 163 npc->attacked_by = 0; /* always clear the attacker entry */
181 164
182 /* if we berserk, we don't care about others - we attack all we can find */ 165 /* if we berserk, we don't care about others - we attack all we can find */
183 if (QUERY_FLAG (npc, FLAG_BERSERK)) 166 if (QUERY_FLAG (npc, FLAG_BERSERK))
184 { 167 {
185 tmp = find_nearest_living_creature (npc); 168 tmp = find_nearest_living_creature (npc);
169
186 if (tmp) 170 if (tmp)
187 get_rangevector (npc, tmp, rv, 0); 171 get_rangevector (npc, tmp, rv, 0);
188 return tmp; 172 return tmp;
189 } 173 }
190 174
200 184
201 /* pet move */ 185 /* pet move */
202 if ((npc->attack_movement & HI4) == PETMOVE) 186 if ((npc->attack_movement & HI4) == PETMOVE)
203 { 187 {
204 tmp = get_pet_enemy (npc, rv); 188 tmp = get_pet_enemy (npc, rv);
189
205 if (tmp) 190 if (tmp)
206 get_rangevector (npc, tmp, rv, 0); 191 get_rangevector (npc, tmp, rv, 0);
192
207 return tmp; 193 return tmp;
208 } 194 }
209 195
210 /* we check our old enemy. */ 196 /* we check our old enemy. */
211 if ((tmp = check_enemy (npc, rv)) == NULL) 197 if (!(tmp = check_enemy (npc, rv)))
212 { 198 {
213 if (attacker) /* if we have an attacker, check him */ 199 if (attacker) /* if we have an attacker, check him */
214 { 200 {
215 /* we want be sure this is the right one! */ 201 /* TODO: thats not finished */
216 if (attacker->count == npc->attacked_by_count) 202 /* we don't want a fight evil vs evil or good against non evil */
203
204 if (QUERY_FLAG (npc, FLAG_NEUTRAL) || QUERY_FLAG (attacker, FLAG_NEUTRAL) || /* neutral */
205 (QUERY_FLAG (npc, FLAG_FRIENDLY) && QUERY_FLAG (attacker, FLAG_FRIENDLY)) ||
206 (!QUERY_FLAG (npc, FLAG_FRIENDLY) && (!QUERY_FLAG (attacker, FLAG_FRIENDLY) && attacker->type != PLAYER)))
207 CLEAR_FLAG (npc, FLAG_SLEEP); /* skip it, but lets wakeup */
208 else if (on_same_map (npc, attacker)) /* thats the only thing we must know... */
217 { 209 {
218 /* TODO: thats not finished */
219 /* we don't want a fight evil vs evil or good against non evil */
220
221 if (QUERY_FLAG (npc, FLAG_NEUTRAL) || QUERY_FLAG (attacker, FLAG_NEUTRAL) || /* neutral */
222 (QUERY_FLAG (npc, FLAG_FRIENDLY) && QUERY_FLAG (attacker, FLAG_FRIENDLY)) ||
223 (!QUERY_FLAG (npc, FLAG_FRIENDLY) && (!QUERY_FLAG (attacker, FLAG_FRIENDLY) && attacker->type != PLAYER)))
224 CLEAR_FLAG (npc, FLAG_SLEEP); /* skip it, but lets wakeup */
225 else if (on_same_map (npc, attacker)) /* thats the only thing we must know... */
226 {
227 CLEAR_FLAG (npc, FLAG_SLEEP); /* well, NOW we really should wake up! */ 210 CLEAR_FLAG (npc, FLAG_SLEEP); /* well, NOW we really should wake up! */
228 npc->enemy = attacker; 211 npc->enemy = attacker;
229 return attacker; /* yes, we face our attacker! */ 212 return attacker; /* yes, we face our attacker! */
230 }
231 } 213 }
232 } 214 }
233 215
234 /* we have no legal enemy or attacker, so we try to target a new one */ 216 /* we have no legal enemy or attacker, so we try to target a new one */
235 if (!QUERY_FLAG (npc, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (npc, FLAG_FRIENDLY) && !QUERY_FLAG (npc, FLAG_NEUTRAL)) 217 if (!QUERY_FLAG (npc, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (npc, FLAG_FRIENDLY) && !QUERY_FLAG (npc, FLAG_NEUTRAL))
296 int i; 278 int i;
297 279
298 /* Give up to 15 chances for a monster to move randomly */ 280 /* Give up to 15 chances for a monster to move randomly */
299 for (i = 0; i < 15; i++) 281 for (i = 0; i < 15; i++)
300 { 282 {
301 if (move_object (op, RANDOM () % 8 + 1)) 283 if (move_object (op, rndm (8) + 1))
302 return 1; 284 return 1;
303 } 285 }
304 return 0; 286 return 0;
305} 287}
306 288
326 oph = oph->head; 308 oph = oph->head;
327 309
328 if (QUERY_FLAG (op, FLAG_NO_ATTACK)) /* we never ever attack */ 310 if (QUERY_FLAG (op, FLAG_NO_ATTACK)) /* we never ever attack */
329 enemy = op->enemy = NULL; 311 enemy = op->enemy = NULL;
330 else if ((enemy = find_enemy (op, &rv))) 312 else if ((enemy = find_enemy (op, &rv)))
331 {
332 /* we have an enemy, just tell him we want him dead */ 313 /* we have an enemy, just tell him we want him dead */
333 enemy->attacked_by = op; /* our ptr */ 314 enemy->attacked_by = op; /* our ptr */
334 enemy->attacked_by_count = op->count; /* our tag */
335 }
336 315
337 /* generate hp, if applicable */ 316 /* generate hp, if applicable */
338 if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp) 317 if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp)
339 { 318 {
340 319
378 } 357 }
379 358
380 /* this should probably get modified by many more values. 359 /* this should probably get modified by many more values.
381 * (eg, creatures resistance to fear, level, etc. ) 360 * (eg, creatures resistance to fear, level, etc. )
382 */ 361 */
383 if (QUERY_FLAG (op, FLAG_SCARED) && !(RANDOM () % 20)) 362 if (QUERY_FLAG (op, FLAG_SCARED) && !(rndm (20)))
384 { 363 {
385 CLEAR_FLAG (op, FLAG_SCARED); /* Time to regain some "guts"... */ 364 CLEAR_FLAG (op, FLAG_SCARED); /* Time to regain some "guts"... */
386 } 365 }
387 366
388 if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy))) 367 if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy)))
408 /* If we don't have an enemy, do special movement or the like */ 387 /* If we don't have an enemy, do special movement or the like */
409 if (!enemy) 388 if (!enemy)
410 { 389 {
411 if (QUERY_FLAG (op, FLAG_ONLY_ATTACK)) 390 if (QUERY_FLAG (op, FLAG_ONLY_ATTACK))
412 { 391 {
413 remove_ob (op); 392 op->destroy ();
414 free_object (op);
415 return 1; 393 return 1;
416 } 394 }
417 395
418 /* Probably really a bug for a creature to have both 396 /* Probably really a bug for a creature to have both
419 * stand still and a movement type set. 397 * stand still and a movement type set.
468 } /* stand still */ 446 } /* stand still */
469 return 0; 447 return 0;
470 } /* no enemy */ 448 } /* no enemy */
471 449
472 /* We have an enemy. Block immediately below is for pets */ 450 /* We have an enemy. Block immediately below is for pets */
473 if ((op->attack_movement & HI4) == PETMOVE && (owner = get_owner (op)) != NULL && !on_same_map (op, owner)) 451 if ((op->attack_movement & HI4) == PETMOVE && (owner = op->owner) != NULL && !on_same_map (op, owner))
474 return follow_owner (op, owner); 452 return follow_owner (op, owner);
475 453
476 /* doppleganger code to change monster facing to that of the nearest 454 /* doppleganger code to change monster facing to that of the nearest
477 * player. Hmm. The code is here, but no monster in the current 455 * player. Hmm. The code is here, but no monster in the current
478 * arch set uses it. 456 * arch set uses it.
508 * but that we test above... so can be old code here 486 * but that we test above... so can be old code here
509 */ 487 */
510 if (QUERY_FLAG (op, FLAG_RUN_AWAY)) 488 if (QUERY_FLAG (op, FLAG_RUN_AWAY))
511 dir = absdir (dir + 4); 489 dir = absdir (dir + 4);
512 if (QUERY_FLAG (op, FLAG_CONFUSED)) 490 if (QUERY_FLAG (op, FLAG_CONFUSED))
513 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 491 dir = absdir (dir + rndm (3) + rndm (3) - 2);
514 492
515 if (QUERY_FLAG (op, FLAG_CAST_SPELL) && !(RANDOM () % 3)) 493 if (QUERY_FLAG (op, FLAG_CAST_SPELL) && !(rndm (3)))
516 { 494 {
517 if (monster_cast_spell (op, part, enemy, dir, &rv1)) 495 if (monster_cast_spell (op, part, enemy, dir, &rv1))
518 return 0; 496 return 0;
519 } 497 }
520 498
521 if (QUERY_FLAG (op, FLAG_READY_SCROLL) && !(RANDOM () % 3)) 499 if (QUERY_FLAG (op, FLAG_READY_SCROLL) && !(rndm (3)))
522 { 500 {
523 if (monster_use_scroll (op, part, enemy, dir, &rv1)) 501 if (monster_use_scroll (op, part, enemy, dir, &rv1))
524 return 0; 502 return 0;
525 } 503 }
526 504
527 if (QUERY_FLAG (op, FLAG_READY_RANGE) && !(RANDOM () % 3)) 505 if (QUERY_FLAG (op, FLAG_READY_RANGE) && !(rndm (3)))
528 { 506 {
529 if (monster_use_range (op, part, enemy, dir)) 507 if (monster_use_range (op, part, enemy, dir))
530 return 0; 508 return 0;
531 } 509 }
532 if (QUERY_FLAG (op, FLAG_READY_SKILL) && !(RANDOM () % 3)) 510 if (QUERY_FLAG (op, FLAG_READY_SKILL) && !(rndm (3)))
533 { 511 {
534 if (monster_use_skill (op, rv.part, enemy, rv.direction)) 512 if (monster_use_skill (op, rv.part, enemy, rv.direction))
535 return 0; 513 return 0;
536 } 514 }
537 if (QUERY_FLAG (op, FLAG_READY_BOW) && !(RANDOM () % 2)) 515 if (QUERY_FLAG (op, FLAG_READY_BOW) && !(rndm (2)))
538 { 516 {
539 if (monster_use_bow (op, part, enemy, dir)) 517 if (monster_use_bow (op, part, enemy, dir))
540 return 0; 518 return 0;
541 } 519 }
542 } /* for processing of all parts */ 520 } /* for processing of all parts */
548 526
549 if (QUERY_FLAG (op, FLAG_SCARED) || QUERY_FLAG (op, FLAG_RUN_AWAY)) 527 if (QUERY_FLAG (op, FLAG_SCARED) || QUERY_FLAG (op, FLAG_RUN_AWAY))
550 dir = absdir (dir + 4); 528 dir = absdir (dir + 4);
551 529
552 if (QUERY_FLAG (op, FLAG_CONFUSED)) 530 if (QUERY_FLAG (op, FLAG_CONFUSED))
553 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 531 dir = absdir (dir + rndm (3) + rndm (3) - 2);
554 532
555 pre_att_dir = dir; /* remember the original direction */ 533 pre_att_dir = dir; /* remember the original direction */
556 534
557 if ((op->attack_movement & LO4) && !QUERY_FLAG (op, FLAG_SCARED)) 535 if ((op->attack_movement & LO4) && !QUERY_FLAG (op, FLAG_SCARED))
558 { 536 {
677 if (QUERY_FLAG (part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */ 655 if (QUERY_FLAG (part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */
678 return 1; 656 return 1;
679 657
680 if (QUERY_FLAG (op, FLAG_ONLY_ATTACK)) 658 if (QUERY_FLAG (op, FLAG_ONLY_ATTACK))
681 { 659 {
682 remove_ob (op); 660 op->remove ();
683 free_object (op); 661 op->destroy ();
684 return 1; 662 return 1;
685 } 663 }
686 return 0; 664 return 0;
687} 665}
688 666
690can_hit (object *ob1, object *ob2, rv_vector * rv) 668can_hit (object *ob1, object *ob2, rv_vector * rv)
691{ 669{
692 object *more; 670 object *more;
693 rv_vector rv1; 671 rv_vector rv1;
694 672
695 if (QUERY_FLAG (ob1, FLAG_CONFUSED) && !(RANDOM () % 3)) 673 if (QUERY_FLAG (ob1, FLAG_CONFUSED) && !(rndm (3)))
696 return 0; 674 return 0;
697 675
698 if (abs (rv->distance_x) < 2 && abs (rv->distance_y) < 2) 676 if (abs (rv->distance_x) < 2 && abs (rv->distance_y) < 2)
699 return 1; 677 return 1;
700 678
799 * other monsters) 777 * other monsters)
800 */ 778 */
801 if (!(dir = path_to_player (part, pl, 0))) 779 if (!(dir = path_to_player (part, pl, 0)))
802 return 0; 780 return 0;
803 781
804 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = get_owner (head)) != NULL) 782 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
805 { 783 {
806 get_rangevector (head, owner, &rv1, 0x1); 784 get_rangevector (head, owner, &rv1, 0x1);
807 if (dirdiff (dir, rv1.direction) < 2) 785 if (dirdiff (dir, rv1.direction) < 2)
808 { 786 {
809 return 0; /* Might hit owner with spell */ 787 return 0; /* Might hit owner with spell */
810 } 788 }
811 } 789 }
812 790
813 if (QUERY_FLAG (head, FLAG_CONFUSED)) 791 if (QUERY_FLAG (head, FLAG_CONFUSED))
814 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 792 dir = absdir (dir + rndm (3) + rndm (3) - 2);
815 793
816 /* If the monster hasn't already chosen a spell, choose one 794 /* If the monster hasn't already chosen a spell, choose one
817 * I'm not sure if it really make sense to pre-select spells (events 795 * I'm not sure if it really make sense to pre-select spells (events
818 * could be different by the time the monster goes again). 796 * could be different by the time the monster goes again).
819 */ 797 */
876 * other monsters) 854 * other monsters)
877 */ 855 */
878 if (!(dir = path_to_player (part, pl, 0))) 856 if (!(dir = path_to_player (part, pl, 0)))
879 return 0; 857 return 0;
880 858
881 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = get_owner (head)) != NULL) 859 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
882 { 860 {
883 get_rangevector (head, owner, &rv1, 0x1); 861 get_rangevector (head, owner, &rv1, 0x1);
884 if (dirdiff (dir, rv1.direction) < 2) 862 if (dirdiff (dir, rv1.direction) < 2)
885 { 863 {
886 return 0; /* Might hit owner with spell */ 864 return 0; /* Might hit owner with spell */
887 } 865 }
888 } 866 }
889 867
890 if (QUERY_FLAG (head, FLAG_CONFUSED)) 868 if (QUERY_FLAG (head, FLAG_CONFUSED))
891 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 869 dir = absdir (dir + rndm (3) + rndm (3) - 2);
892 870
893 for (scroll = head->inv; scroll; scroll = scroll->below) 871 for (scroll = head->inv; scroll; scroll = scroll->below)
894 if (scroll->type == SCROLL && monster_should_cast_spell (head, scroll->inv)) 872 if (scroll->type == SCROLL && monster_should_cast_spell (head, scroll->inv))
895 break; 873 break;
896 874
927 object *skill, *owner; 905 object *skill, *owner;
928 906
929 if (!(dir = path_to_player (part, pl, 0))) 907 if (!(dir = path_to_player (part, pl, 0)))
930 return 0; 908 return 0;
931 909
932 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = get_owner (head)) != NULL) 910 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
933 { 911 {
934 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y); 912 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
935 913
936 if (dirdiff (dir, dir2) < 1) 914 if (dirdiff (dir, dir2) < 1)
937 return 0; /* Might hit owner with skill -thrown rocks for example ? */ 915 return 0; /* Might hit owner with skill -thrown rocks for example ? */
938 } 916 }
939 if (QUERY_FLAG (head, FLAG_CONFUSED)) 917 if (QUERY_FLAG (head, FLAG_CONFUSED))
940 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 918 dir = absdir (dir + rndm (3) + rndm (3) - 2);
941 919
942 /* skill selection - monster will use the next unused skill. 920 /* skill selection - monster will use the next unused skill.
943 * well...the following scenario will allow the monster to 921 * well...the following scenario will allow the monster to
944 * toggle between 2 skills. One day it would be nice to make 922 * toggle between 2 skills. One day it would be nice to make
945 * more skills available to monsters. 923 * more skills available to monsters.
971 int at_least_one = 0; 949 int at_least_one = 0;
972 950
973 if (!(dir = path_to_player (part, pl, 0))) 951 if (!(dir = path_to_player (part, pl, 0)))
974 return 0; 952 return 0;
975 953
976 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = get_owner (head)) != NULL) 954 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
977 { 955 {
978 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y); 956 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
979 957
980 if (dirdiff (dir, dir2) < 2) 958 if (dirdiff (dir, dir2) < 2)
981 return 0; /* Might hit owner with spell */ 959 return 0; /* Might hit owner with spell */
982 } 960 }
983 if (QUERY_FLAG (head, FLAG_CONFUSED)) 961 if (QUERY_FLAG (head, FLAG_CONFUSED))
984 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 962 dir = absdir (dir + rndm (3) + rndm (3) - 2);
985 963
986 for (wand = head->inv; wand != NULL; wand = wand->below) 964 for (wand = head->inv; wand != NULL; wand = wand->below)
987 { 965 {
988 if (wand->type == WAND) 966 if (wand->type == WAND)
989 { 967 {
998 { 976 {
999 if (wand->arch) 977 if (wand->arch)
1000 { 978 {
1001 CLEAR_FLAG (wand, FLAG_ANIMATE); 979 CLEAR_FLAG (wand, FLAG_ANIMATE);
1002 wand->face = wand->arch->clone.face; 980 wand->face = wand->arch->clone.face;
1003 wand->speed = 0; 981 wand->set_speed (0);
1004 update_ob_speed (wand);
1005 } 982 }
1006 } 983 }
1007 /* Success */ 984 /* Success */
1008 return 1; 985 return 1;
1009 } 986 }
1040 object *owner; 1017 object *owner;
1041 1018
1042 if (!(dir = path_to_player (part, pl, 0))) 1019 if (!(dir = path_to_player (part, pl, 0)))
1043 return 0; 1020 return 0;
1044 if (QUERY_FLAG (head, FLAG_CONFUSED)) 1021 if (QUERY_FLAG (head, FLAG_CONFUSED))
1045 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 1022 dir = absdir (dir + rndm (3) + rndm (3) - 2);
1046 1023
1047 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = get_owner (head)) != NULL) 1024 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
1048 { 1025 {
1049 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y); 1026 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
1050 1027
1051 if (dirdiff (dir, dir2) < 1) 1028 if (dirdiff (dir, dir2) < 1)
1052 return 0; /* Might hit owner with arrow */ 1029 return 0; /* Might hit owner with arrow */
1157 1134
1158void 1135void
1159monster_check_pickup (object *monster) 1136monster_check_pickup (object *monster)
1160{ 1137{
1161 object *tmp, *next; 1138 object *tmp, *next;
1162 int next_tag;
1163 1139
1164 for (tmp = monster->below; tmp != NULL; tmp = next) 1140 for (tmp = monster->below; tmp != NULL; tmp = next)
1165 { 1141 {
1166 next = tmp->below; 1142 next = tmp->below;
1167 next_tag = next ? next->count : 0;
1168 if (monster_can_pick (monster, tmp)) 1143 if (monster_can_pick (monster, tmp))
1169 { 1144 {
1170 remove_ob (tmp); 1145 tmp->remove ();
1171 tmp = insert_ob_in_ob (tmp, monster); 1146 tmp = insert_ob_in_ob (tmp, monster);
1172 (void) monster_check_apply (monster, tmp); 1147 (void) monster_check_apply (monster, tmp);
1173 } 1148 }
1174 /* We could try to re-establish the cycling, of the space, but probably 1149 /* We could try to re-establish the cycling, of the space, but probably
1175 * not a big deal to just bail out. 1150 * not a big deal to just bail out.
1176 */ 1151 */
1177 if (next && was_destroyed (next, next_tag)) 1152 if (next && next->destroyed ())
1178 return; 1153 return;
1179 } 1154 }
1180} 1155}
1181 1156
1182/* 1157/*
1365 /* Don't use it right now */ 1340 /* Don't use it right now */
1366 return; 1341 return;
1367 } 1342 }
1368 else if (item->type == WEAPON) 1343 else if (item->type == WEAPON)
1369 flag = check_good_weapon (mon, item); 1344 flag = check_good_weapon (mon, item);
1370 else if (IS_ARMOR (item)) 1345 else if (item->is_armor ())
1371 flag = check_good_armour (mon, item); 1346 flag = check_good_armour (mon, item);
1372 /* Should do something more, like make sure this is a better item */ 1347 /* Should do something more, like make sure this is a better item */
1373 else if (item->type == RING) 1348 else if (item->type == RING)
1374 flag = 1; 1349 flag = 1;
1375 else if (item->type == WAND || item->type == ROD || item->type == HORN) 1350 else if (item->type == WAND || item->type == ROD || item->type == HORN)
1433npc_call_help (object *op) 1408npc_call_help (object *op)
1434{ 1409{
1435 int x, y, mflags; 1410 int x, y, mflags;
1436 object *npc; 1411 object *npc;
1437 sint16 sx, sy; 1412 sint16 sx, sy;
1438 mapstruct *m; 1413 maptile *m;
1439 1414
1440 for (x = -3; x < 4; x++) 1415 for (x = -3; x < 4; x++)
1441 for (y = -3; y < 4; y++) 1416 for (y = -3; y < 4; y++)
1442 { 1417 {
1443 m = op->map; 1418 m = op->map;
1446 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy); 1421 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
1447 /* If nothing alive on this space, no need to search the space. */ 1422 /* If nothing alive on this space, no need to search the space. */
1448 if ((mflags & P_OUT_OF_MAP) || !(mflags & P_IS_ALIVE)) 1423 if ((mflags & P_OUT_OF_MAP) || !(mflags & P_IS_ALIVE))
1449 continue; 1424 continue;
1450 1425
1451 for (npc = get_map_ob (m, sx, sy); npc != NULL; npc = npc->above) 1426 for (npc = GET_MAP_OB (m, sx, sy); npc != NULL; npc = npc->above)
1452 if (QUERY_FLAG (npc, FLAG_ALIVE) && QUERY_FLAG (npc, FLAG_UNAGGRESSIVE)) 1427 if (QUERY_FLAG (npc, FLAG_ALIVE) && QUERY_FLAG (npc, FLAG_UNAGGRESSIVE))
1453 npc->enemy = op->enemy; 1428 npc->enemy = op->enemy;
1454 } 1429 }
1455} 1430}
1456 1431
1542{ 1517{
1543 static int circle[12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 }; 1518 static int circle[12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 };
1544 if (++ob->move_status > 11) 1519 if (++ob->move_status > 11)
1545 ob->move_status = 0; 1520 ob->move_status = 0;
1546 if (!(move_object (ob, circle[ob->move_status]))) 1521 if (!(move_object (ob, circle[ob->move_status])))
1547 (void) move_object (ob, RANDOM () % 8 + 1); 1522 (void) move_object (ob, rndm (8) + 1);
1548} 1523}
1549 1524
1550void 1525void
1551circ2_move (object *ob) 1526circ2_move (object *ob)
1552{ 1527{
1553 static int circle[20] = { 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 1, 1, 1, 2, 2 }; 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 };
1554 if (++ob->move_status > 19) 1529 if (++ob->move_status > 19)
1555 ob->move_status = 0; 1530 ob->move_status = 0;
1556 if (!(move_object (ob, circle[ob->move_status]))) 1531 if (!(move_object (ob, circle[ob->move_status])))
1557 (void) move_object (ob, RANDOM () % 8 + 1); 1532 (void) move_object (ob, rndm (8) + 1);
1558} 1533}
1559 1534
1560void 1535void
1561pace_movev (object *ob) 1536pace_movev (object *ob)
1562{ 1537{
1612void 1587void
1613rand_move (object *ob) 1588rand_move (object *ob)
1614{ 1589{
1615 int i; 1590 int i;
1616 1591
1617 if (ob->move_status < 1 || ob->move_status > 8 || !(move_object (ob, ob->move_status || !(RANDOM () % 9)))) 1592 if (ob->move_status < 1 || ob->move_status > 8 || !(move_object (ob, ob->move_status || !(rndm (9)))))
1618 for (i = 0; i < 5; i++) 1593 for (i = 0; i < 5; i++)
1619 if (move_object (ob, ob->move_status = RANDOM () % 8 + 1)) 1594 if (move_object (ob, ob->move_status = rndm (8) + 1))
1620 return; 1595 return;
1621} 1596}
1622 1597
1623void 1598void
1624check_earthwalls (object *op, mapstruct *m, int x, int y) 1599check_earthwalls (object *op, maptile *m, int x, int y)
1625{ 1600{
1626 object *tmp; 1601 object *tmp;
1627 1602
1628 for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = tmp->above) 1603 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
1629 { 1604 {
1630 if (tmp->type == EARTHWALL) 1605 if (tmp->type == EARTHWALL)
1631 { 1606 {
1632 hit_player (tmp, op->stats.dam, op, AT_PHYSICAL, 1); 1607 hit_player (tmp, op->stats.dam, op, AT_PHYSICAL, 1);
1633 return; 1608 return;
1634 } 1609 }
1635 } 1610 }
1636} 1611}
1637 1612
1638void 1613void
1639check_doors (object *op, mapstruct *m, int x, int y) 1614check_doors (object *op, maptile *m, int x, int y)
1640{ 1615{
1641 object *tmp; 1616 object *tmp;
1642 1617
1643 for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = tmp->above) 1618 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
1644 { 1619 {
1645 if (tmp->type == DOOR) 1620 if (tmp->type == DOOR)
1646 { 1621 {
1647 hit_player (tmp, 1000, op, AT_PHYSICAL, 1); 1622 hit_player (tmp, 1000, op, AT_PHYSICAL, 1);
1648 return; 1623 return;
1669 tmp = op; 1644 tmp = op;
1670 1645
1671 /* New throw code: look through the inventory. Grap the first legal is_thrown 1646 /* New throw code: look through the inventory. Grap the first legal is_thrown
1672 * marked item and throw it to the enemy. 1647 * marked item and throw it to the enemy.
1673 */ 1648 */
1674
1675 for (tmp = op->inv; tmp; tmp = tmp->below) 1649 for (tmp = op->inv; tmp; tmp = tmp->below)
1676 { 1650 {
1677
1678 /* Can't throw invisible objects or items that are applied */ 1651 /* Can't throw invisible objects or items that are applied */
1679 if (tmp->invisible || QUERY_FLAG (tmp, FLAG_APPLIED)) 1652 if (tmp->invisible || QUERY_FLAG (tmp, FLAG_APPLIED))
1680 continue; 1653 continue;
1681 1654
1682 if (QUERY_FLAG (tmp, FLAG_IS_THROWN)) 1655 if (QUERY_FLAG (tmp, FLAG_IS_THROWN))
1805 /* ah, we are within range, detected? take cases */ 1778 /* ah, we are within range, detected? take cases */
1806 if (!enemy->invisible) /* enemy in dark squares... are seen! */ 1779 if (!enemy->invisible) /* enemy in dark squares... are seen! */
1807 return 1; 1780 return 1;
1808 1781
1809 /* hidden or low-quality invisible */ 1782 /* hidden or low-quality invisible */
1810 if (enemy->hide && (rv->distance <= 1) && (RANDOM () % 100 <= hide_discovery)) 1783 if (enemy->hide && (rv->distance <= 1) && (rndm (100) <= hide_discovery))
1811 { 1784 {
1812 make_visible (enemy); 1785 make_visible (enemy);
1813 /* inform players of new status */ 1786 /* inform players of new status */
1814 if (enemy->type == PLAYER && player_can_view (enemy, op)) 1787 if (enemy->type == PLAYER && player_can_view (enemy, op))
1815 new_draw_info_format (NDI_UNIQUE, 0, enemy, "You are discovered by %s!", &op->name); 1788 new_draw_info_format (NDI_UNIQUE, 0, enemy, "You are discovered by %s!", &op->name);
1822 * do something to you. Decreasing the duration of invisible 1795 * do something to you. Decreasing the duration of invisible
1823 * doesn't make a lot of sense IMO, as a bunch of stupid creatures 1796 * doesn't make a lot of sense IMO, as a bunch of stupid creatures
1824 * can then basically negate the spell. The spell isn't negated - 1797 * can then basically negate the spell. The spell isn't negated -
1825 * they just know where you are! 1798 * they just know where you are!
1826 */ 1799 */
1827 if ((RANDOM () % 50) <= hide_discovery) 1800 if ((rndm (50)) <= hide_discovery)
1828 { 1801 {
1829 if (enemy->type == PLAYER) 1802 if (enemy->type == PLAYER)
1830 { 1803 {
1831 new_draw_info_format (NDI_UNIQUE, 0, enemy, "You see %s noticing your position.", query_name (op)); 1804 new_draw_info_format (NDI_UNIQUE, 0, enemy, "You see %s noticing your position.", query_name (op));
1832 } 1805 }
1847 1820
1848int 1821int
1849stand_in_light (object *op) 1822stand_in_light (object *op)
1850{ 1823{
1851 sint16 nx, ny; 1824 sint16 nx, ny;
1852 mapstruct *m; 1825 maptile *m;
1853 1826
1854 1827
1855 if (!op) 1828 if (!op)
1856 return 0; 1829 return 0;
1857 if (op->glow_radius > 0) 1830 if (op->glow_radius > 0)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines