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.7 by pippijn, Thu Sep 7 10:01:58 2006 UTC vs.
Revision 1.17 by root, Wed Dec 20 09:14:22 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines