1 /* File: cmd2.c */
2 
3 /* Purpose: Movement commands (part 2) */
4 
5 /*
6  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
7  *
8  * This software may be copied and distributed for educational, research, and
9  * not for profit purposes provided that this copyright and statement are
10  * included in all such copies.
11  */
12 
13 #include "mangband.h"
14 
15 
16 
17 /*
18  * Go up one level					-RAK-
19  */
do_cmd_go_up(player_type * p_ptr)20 void do_cmd_go_up(player_type *p_ptr)
21 {
22 	int Depth = p_ptr->dun_depth;
23 
24 	cave_type *c_ptr;
25 
26 	/* Make sure he hasn't just changed depth */
27 	if (p_ptr->new_level_flag)
28 		return;
29 
30 	/* Check preventive inscription '^<' */
31 	__trap(p_ptr, CPI(p_ptr, '<'));
32 
33 	/* Player grid */
34 	c_ptr = &cave[Depth][p_ptr->py][p_ptr->px];
35 
36 	/* Verify stairs if not a ghost, or admin wizard */
37 	if (!p_ptr->ghost && c_ptr->feat != FEAT_LESS)
38 	{
39 		msg_print(p_ptr, "I see no up staircase here.");
40 		return;
41 	}
42 	else
43 	{
44 		if (p_ptr->dun_depth <= 0)
45 		{
46 			msg_print(p_ptr, "There is nothing above you.");
47 			return;
48 		}
49 	}
50 
51 	if (cfg_ironman)
52 	{
53 		/*
54 		 * Ironmen don't go up
55 		 */
56 		if(!is_dm_p(p_ptr))
57 		{
58 			msg_print(p_ptr, "Morgoth awaits you in the darkness below.");
59 			return;
60 		}
61 	}
62 
63 	/* Remove the player from the old location */
64 	c_ptr->m_idx = 0;
65 
66 	/* Show everyone that's he left */
67 	everyone_lite_spot(Depth, p_ptr->py, p_ptr->px);
68 
69 	/* Tell everyone to re-calculate visiblity for this player */
70 	update_player(p_ptr);
71 
72 	/* Forget his lite and viewing area */
73 	forget_lite(p_ptr);
74 	forget_view(p_ptr);
75 
76 	/* Hack -- take a turn */
77 	p_ptr->energy -= level_speed(p_ptr->dun_depth);
78 
79 	/* Success */
80 	if (c_ptr->feat == FEAT_LESS)
81 	{
82 		msg_print(p_ptr, "You enter a maze of up staircases.");
83 		sound(p_ptr, MSG_STAIRS_UP);
84 		p_ptr->new_level_method = LEVEL_UP;
85 	}
86 	else
87 	{
88 		msg_print(p_ptr, "You float upwards.");
89 		p_ptr->new_level_method = LEVEL_GHOST;
90 	}
91 
92 	/* A player has left this depth */
93 	players_on_depth[p_ptr->dun_depth]--;
94 
95 	/* Go up the stairs */
96 	p_ptr->dun_depth--;
97 
98 	/* And another player has entered this depth */
99 	players_on_depth[p_ptr->dun_depth]++;
100 
101 	p_ptr->new_level_flag = TRUE;
102 
103 	/* Create a way back */
104 	create_down_stair = TRUE;
105 }
106 
107 
108 /*
109  * Go down one level
110  */
do_cmd_go_down(player_type * p_ptr)111 void do_cmd_go_down(player_type *p_ptr)
112 {
113 	int Depth = p_ptr->dun_depth;
114 
115 	cave_type *c_ptr;
116 
117 	/* Make sure he hasn't just changed depth */
118 	if (p_ptr->new_level_flag)
119 		return;
120 
121 	/* Check preventive inscription '^>' */
122 	__trap(p_ptr, CPI(p_ptr, '>'));
123 
124 	/* Player grid */
125 	c_ptr = &cave[Depth][p_ptr->py][p_ptr->px];
126 
127 	/* Verify stairs */
128 	if (!p_ptr->ghost && c_ptr->feat != FEAT_MORE)
129 	{
130 		msg_print(p_ptr, "I see no down staircase here.");
131 		return;
132 	}
133 	else
134 	{
135 		/* No ghost diving unless DM or allowed in config */
136 		if (p_ptr->ghost && !cfg_ghost_diving && !is_dm_p(p_ptr)) {
137 			msg_print(p_ptr, "You seem unable to go down.  Try going up.");
138 			return;
139 		};
140 
141 		/* Can't go down on a "quest" level */
142 		if (is_quest_level(p_ptr, p_ptr->dun_depth)
143 			/* Hack -- ..but not in Ironman mode. See #1365 */
144 			&& !cfg_ironman
145 		)
146 		{
147 			/* Inform */
148 			msg_print(p_ptr, "An unvanquished adversary pulls you back, you can descend no further.");
149 			return;
150 		}
151 
152 		/* Can't go down in the wilderness */
153 		if (p_ptr->dun_depth < 0)
154 		{
155 			msg_print(p_ptr, "There is nothing below you.");
156 			return;
157 		}
158 
159 		/* Verify maximum depth */
160 		if (p_ptr->dun_depth >= 127)
161 		{
162 			msg_print(p_ptr, "You are at the bottom of the dungeon.");
163 			return;
164 		}
165 	}
166 
167 	/* Remove the player from the old location */
168 	c_ptr->m_idx = 0;
169 
170 	/* Show everyone that's he left */
171 	everyone_lite_spot(Depth, p_ptr->py, p_ptr->px);
172 
173 	/* Tell everyone to re-calculate visiblity for this player */
174 	update_player(p_ptr);
175 
176 	/* Forget his lite and viewing area */
177 	forget_lite(p_ptr);
178 	forget_view(p_ptr);
179 
180 	/* Hack -- take a turn */
181 	p_ptr->energy -= level_speed(p_ptr->dun_depth);
182 
183 	/* Success */
184 	if (c_ptr->feat == FEAT_MORE)
185 	{
186 		msg_print(p_ptr, "You enter a maze of down staircases.");
187 		sound(p_ptr, MSG_STAIRS_DOWN);
188 		p_ptr->new_level_method = LEVEL_DOWN;
189 	}
190 	else
191 	{
192 		msg_print(p_ptr, "You float downwards.");
193 		p_ptr->new_level_method = LEVEL_GHOST;
194 	}
195 
196 	/* A player has left this depth */
197 	players_on_depth[p_ptr->dun_depth]--;
198 
199 	/* Go down */
200 	p_ptr->dun_depth++;
201 
202 	/* Another player has entered this depth */
203 	players_on_depth[p_ptr->dun_depth]++;
204 
205 	p_ptr->new_level_flag = TRUE;
206 
207 	/* Create a way back */
208 	create_up_stair = TRUE;
209 }
210 
211 
212 
213 /*
214  * Simple command to "search" for one turn
215  */
do_cmd_search(player_type * p_ptr)216 void do_cmd_search(player_type *p_ptr)
217 {
218 	/* Allow repeated command */
219 	if (p_ptr->command_arg)
220 	{
221 		/* Set repeat count */
222 		/*command_rep = command_arg - 1;*/
223 
224 		/* Redraw the state */
225 		p_ptr->redraw |= (PR_STATE);
226 
227 		/* Cancel the arg */
228 		p_ptr->command_arg = 0;
229 	}
230 
231 	/* Take a turn */
232 	p_ptr->energy -= level_speed(p_ptr->dun_depth);
233 
234 	/* Search */
235 	search(p_ptr);
236 }
237 
238 
239 /*
240  * Hack -- toggle search mode
241  */
do_cmd_toggle_search(player_type * p_ptr)242 void do_cmd_toggle_search(player_type *p_ptr)
243 {
244 	/* Stop searching */
245 	if (p_ptr->searching)
246 	{
247 		/* Clear the searching flag */
248 		p_ptr->searching = FALSE;
249 
250 		/* Recalculate bonuses */
251 		p_ptr->update |= (PU_BONUS);
252 
253 		/* Redraw the state */
254 		p_ptr->redraw |= (PR_STATE);
255 	}
256 
257 	/* Start searching */
258 	else
259 	{
260 		/* Set the searching flag */
261 		p_ptr->searching = TRUE;
262 
263 		/* Update stuff */
264 		p_ptr->update |= (PU_BONUS);
265 
266 		/* Redraw stuff */
267 		p_ptr->redraw |= (PR_STATE | PR_SPEED);
268 	}
269 }
270 
271 
272 
273 /*
274  * Allocates objects upon opening a chest    -BEN-
275  *
276  * Disperse treasures from the chest "o_ptr", centered at (x,y).
277  *
278  * Small chests often contain "gold", while Large chests always contain
279  * items.  Wooden chests contain 2 items, Iron chests contain 4 items,
280  * and Steel chests contain 6 items.  The "value" of the items in a
281  * chest is based on the "power" of the chest, which is in turn based
282  * on the level on which the chest is generated.
283  */
chest_death(player_type * p_ptr,int y,int x,object_type * o_ptr)284 static void chest_death(player_type *p_ptr, int y, int x, object_type *o_ptr)
285 {
286 	int Depth = p_ptr->dun_depth;
287 
288 	int		i, d, ny, nx;
289 	int		number, small_;
290 
291 
292 	/* Must be a chest */
293 	if (o_ptr->tval != TV_CHEST) return;
294 
295 	/* Small chests often hold "gold" */
296 	small_ = (o_ptr->sval < SV_CHEST_MIN_LARGE);
297 
298 	/* Determine how much to drop (see above) */
299 	number = (o_ptr->sval % SV_CHEST_MIN_LARGE) * 2;
300 
301 	/* Generate some treasure */
302 	if (o_ptr->pval && (number > 0))
303 	{
304 		/* Drop some objects (non-chests) */
305 		for (; number > 0; --number)
306 		{
307 			/* Try 20 times per item */
308 			for (i = 0; i < 20; ++i)
309 			{
310 				/* Pick a distance */
311 				d = ((i + 15) / 15);
312 
313 				/* Pick a location */
314 				scatter(Depth, &ny, &nx, y, x, d, 0);
315 
316 				/* Must be a clean floor grid */
317 				if (!cave_clean_bold(Depth, ny, nx)) continue;
318 
319 				/* Opening a chest */
320 				opening_chest = TRUE;
321 
322 				/* Determine the "value" of the items */
323 				object_level = ABS(o_ptr->pval) + 10;
324 
325 				/* Small chests often drop gold */
326 				if (small_ && (randint0(100) < 75))
327 				{
328 					place_gold(Depth, ny, nx);
329 				}
330 
331 				/* Otherwise drop an item */
332 				else
333 				{
334 					object_type *j_ptr;
335 					j_ptr = place_object(Depth, ny, nx, FALSE, FALSE, 0);
336 					if (j_ptr)
337 					{
338 						j_ptr->origin = ORIGIN_CHEST;
339 						j_ptr->origin_depth = o_ptr->origin_depth;
340 					}
341 				}
342 
343 				/* Reset the object level */
344 				object_level = Depth;
345 
346 				/* No longer opening a chest */
347 				opening_chest = FALSE;
348 
349 				/* Successful placement */
350 				break;
351 			}
352 		}
353 	}
354 
355 	/* Empty */
356 	o_ptr->pval = 0;
357 
358 	/* Known */
359 	object_known(o_ptr);
360 }
361 
362 
363 /*
364  * Chests have traps too.
365  *
366  * Exploding chest destroys contents (and traps).
367  * Note that the chest itself is never destroyed.
368  */
chest_trap(player_type * p_ptr,int y,int x,object_type * o_ptr)369 static void chest_trap(player_type *p_ptr, int y, int x, object_type *o_ptr)
370 {
371 	int  i, trap;
372 
373 
374 	/* Only analyze chests */
375 	if (o_ptr->tval != TV_CHEST) return;
376 
377 	/* Ignore disarmed chests */
378 	if (o_ptr->pval <= 0) return;
379 
380 	/* Obtain the traps */
381 	trap = chest_traps[o_ptr->pval];
382 
383 	/* Lose strength */
384 	if (trap & CHEST_LOSE_STR)
385 	{
386 		msg_print(p_ptr, "A small needle has pricked you!");
387 		take_hit(p_ptr, damroll(1, 4), "a poison needle");
388 		(void)do_dec_stat(p_ptr, A_STR);
389 	}
390 
391 	/* Lose constitution */
392 	if (trap & CHEST_LOSE_CON)
393 	{
394 		msg_print(p_ptr, "A small needle has pricked you!");
395 		take_hit(p_ptr, damroll(1, 4), "a poison needle");
396 		(void)do_dec_stat(p_ptr, A_CON);
397 	}
398 
399 	/* Poison */
400 	if (trap & CHEST_POISON)
401 	{
402 		msg_print(p_ptr, "A puff of green gas surrounds you!");
403 		if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
404 		{
405 			(void)set_poisoned(p_ptr, p_ptr->poisoned + 10 + randint1(20));
406 		}
407 	}
408 
409 	/* Paralyze */
410 	if (trap & CHEST_PARALYZE)
411 	{
412 		msg_print(p_ptr, "A puff of yellow gas surrounds you!");
413 		if (!p_ptr->free_act)
414 		{
415 			(void)set_paralyzed(p_ptr, p_ptr->paralyzed + 10 + randint1(20));
416 		}
417 	}
418 
419 	/* Summon monsters */
420 	if (trap & CHEST_SUMMON)
421 	{
422 		int num = 2 + randint1(3);
423 		msg_print(p_ptr, "You are enveloped in a cloud of smoke!");
424 		sound(p_ptr, MSG_SUM_MONSTER);
425 		for (i = 0; i < num; i++)
426 		{
427 			(void)summon_specific(p_ptr->dun_depth, y, x, p_ptr->dun_depth, 0);
428 		}
429 	}
430 
431 	/* Explode */
432 	if (trap & CHEST_EXPLODE)
433 	{
434 		msg_print(p_ptr, "There is a sudden explosion!");
435 		msg_print(p_ptr, "Everything inside the chest is destroyed!");
436 		o_ptr->pval = 0;
437 		take_hit(p_ptr, damroll(5, 8), "an exploding chest");
438 	}
439 }
440 
441 
442 /*
443  * Return the index of a house given an coordinate pair
444  */
pick_house(int Depth,int y,int x)445 int pick_house(int Depth, int y, int x)
446 {
447 	int i;
448 
449 	/* Check each house */
450 	for (i = 0; i < num_houses; i++)
451 	{
452 		/* Check this one */
453 		if (houses[i].door_x == x && houses[i].door_y == y && houses[i].depth == Depth)
454 		{
455 			/* Return */
456 			return i;
457 		}
458 	}
459 
460 	/* Failure */
461 	return -1;
462 }
463 
464 /*
465  * Determine if the player is inside the house
466  */
house_inside(player_type * p_ptr,int house)467 bool house_inside(player_type *p_ptr, int house)
468 {
469 	if (house >= 0 && house < num_houses)
470 	{
471 		if (houses[house].depth == p_ptr->dun_depth
472 			&& p_ptr->px >= houses[house].x_1 && p_ptr->px <= houses[house].x_2
473 			&& p_ptr->py >= houses[house].y_1 && p_ptr->py <= houses[house].y_2)
474 		{
475 			return TRUE;
476 		}
477 	}
478 
479 	return FALSE;
480 }
481 
482 /*
483  * Determine if the given house is owned
484  */
house_owned(int house)485 bool house_owned(int house)
486 {
487 	if (house >= 0 && house < num_houses)
488 	{
489 		if (houses[house].owned[0])
490 		{
491 			return TRUE;
492 		}
493 	}
494 	return FALSE;
495 }
496 
497 /*
498  * Determine if the given player owns the given house
499  */
house_owned_by(player_type * p_ptr,int house)500 bool house_owned_by(player_type *p_ptr, int house)
501 {
502 	/* If not owned at all, obviously not owned by this player */
503 	if (!house_owned(house)) return FALSE;
504 
505 	/* It's owned, is it by this player */
506 	if (!strcmp(p_ptr->name,houses[house].owned))
507 	{
508 		return TRUE;
509 	}
510 	return FALSE;
511 }
512 
513 /*
514  * Return the number of houses owned by the player
515  */
houses_owned(player_type * p_ptr)516 int houses_owned(player_type *p_ptr)
517 {
518 	int i;
519 	int owned = 0;
520 
521 	/* Check each house */
522 	for (i = 0; i < num_houses; i++)
523 	{
524 		if (house_owned_by(p_ptr, i))
525 		{
526 			owned++;
527 		}
528 	}
529 
530 	return owned;
531 }
532 
533 /*
534  * Given coordinates return a house to which they belong.
535  * Houses can be overlapping, so a single coordinate pair may match several
536  * houses.  The offset parameter allows searching for the next match.
537  */
find_house(int Depth,int x,int y,int offset)538 int find_house(int Depth, int x, int y, int offset)
539 {
540 	int i;
541 
542 	for (i = offset; i < num_houses; i++)
543 	{
544 		/* Check the house position *including* the walls */
545 		if (houses[i].depth == Depth
546 			&& x >= houses[i].x_1-1 && x <= houses[i].x_2+1
547 			&& y >= houses[i].y_1-1 && y <= houses[i].y_2+1)
548 		{
549 			/* We found the house this section of wall belongs to */
550 			return i;
551 		}
552 	}
553 	return -1;
554 }
555 
556 /*
557  * Determine if the given location is ok to use as part of the foundation
558  * of a house.
559  */
is_valid_foundation(player_type * p_ptr,int x,int y)560 bool is_valid_foundation(player_type *p_ptr, int x, int y)
561 {
562 	int house;
563 	cave_type *c_ptr;
564 	object_type	*o_ptr;
565 
566 	/* Foundation stones are always valid */
567 	o_ptr = &o_list[cave[p_ptr->dun_depth][y][x].o_idx];
568 	if (o_ptr->tval == TV_JUNK && o_ptr->sval == SV_HOUSE_FOUNDATION)
569 	{
570 		return TRUE;
571 	}
572 
573 	/* Perma walls and doors are valid if they are part of a house owned
574 	 * by this player */
575 	c_ptr = &cave[p_ptr->dun_depth][y][x];
576 	if( (c_ptr->feat == FEAT_PERM_EXTRA)
577 		|| (c_ptr->feat >= FEAT_HOME_HEAD && c_ptr->feat <= FEAT_HOME_TAIL))
578 	{
579 		/* Looks like part of a house, which house? */
580 		house = find_house(p_ptr->dun_depth, x, y, 0);
581 		if(house >= 0)
582 		{
583 			/* Do we own this house? */
584 			if (house_owned_by(p_ptr, house))
585 			{
586 				/* Valid, a wall or door in our own house. */
587 				return TRUE;
588 			}
589 		}
590 	}
591 	return FALSE;
592 }
593 
594 /*
595  * Create a new house door at the given location.
596  * Due to the fact that houses can overlap (i.e. share a common wall) it
597  * may not be possible to identify the house to which the door should belong.
598  *
599  * For example, on the left below, we have two houses overlapping, neither
600  * have doors. On the right the player creates a door, but to which house does
601  * it belong?
602  *
603  *   ####                        ####
604  *   #  #@                       #  #@
605  *   #  ###                      #  +##
606  *   #### #                      #### #
607  *      # #                         # #
608  *      ###                         ###
609  *
610  * It is therefore possible to create a complex of houses such that the player
611  * owned shop mechanism becomes confused.  When a player bumps one door they
612  * see the contents of a different room listed.
613  *
614  * FIXME Therefore the player owned shop mechanism should treat overlapping
615  * player created houses as a *single* house and present all goods in all
616  * attached houses.
617  */
create_house_door(player_type * p_ptr,int x,int y)618 bool create_house_door(player_type *p_ptr, int x, int y)
619 {
620 	int house, i, lastmatch;
621 	cave_type		*c_ptr;
622 
623 	/* Which house is the given location part of? */
624 	lastmatch = 0;
625 	while( (house = find_house(p_ptr->dun_depth,x,y,lastmatch)) > -1 )
626 	{
627 		lastmatch = house+1;
628 
629 		/* Do we own this house? */
630 		if (!house_owned_by(p_ptr, house))
631 		{
632 			/* If we don't own this one, we can't own any overlapping ones */
633 			msg_print(p_ptr, "You do not own this house");
634 			return FALSE;
635 		}
636 
637 		/* Does it already have a door? */
638 		if(houses[house].door_y == 0 && houses[house].door_x == 0)
639 		{
640 			/* No door, so create one! */
641 			houses[house].door_y = y;
642 			houses[house].door_x = x;
643 			c_ptr = &cave[p_ptr->dun_depth][y][x];
644 			c_ptr->feat = FEAT_HOME_HEAD;
645 			everyone_lite_spot(p_ptr->dun_depth, y, x);
646 			msg_print(p_ptr, "You create a door for your house!");
647 			return TRUE;
648 		}
649 	}
650 	/* We searched all matching houses and none needed a door */
651 	return FALSE;
652 }
653 
654 /*
655  * Determine the area for a house foundation.
656  *
657  * Although an individual house must be rectangular, a foundation
658  * can be non-rectangular.  This is because we allow existing walls to
659  * form part of our foundation, and therefore allow complex shaped houses
660  * to be consructed.
661  *                                              ~~~
662  * For example this is a legal foundation:   ~~~~~~
663  *                                           ~~~~~~
664  * In this sitation:
665  *
666  *   #####                               #####
667  *   #   #                               #   #
668  *   #   #      Forming a final shape:   #   #
669  *   #####~~~                            ###+####
670  *     ~~~~~~                              #    #
671  *     ~~~~~~                              ######
672  *
673  * This function is also responsible for rejecting illegal shapes and sizes.
674  *
675  * We start from the player location (who must be stood on a foundation stone)
676  * and work our way outwards to find the bounding rectange of the foundation.
677  * Conceptually imagine a box radiating out from the player, we keep extending
678  * the box in each dimension for as long as all points on the perimeter are
679  * either foundation stones or walls of houses the player owns.
680  *
681  */
get_house_foundation(player_type * p_ptr,int * px1,int * py1,int * px2,int * py2)682 bool get_house_foundation(player_type *p_ptr, int *px1, int *py1, int *px2, int *py2)
683 {
684 	int x, y, x1, y1, x2, y2;
685 	bool done;
686 	bool n,s,e,w,ne,nw,se,sw;
687 	object_type	*o_ptr;
688 
689 	plog(format("Player is at x,y %d, %d",p_ptr->px, p_ptr->py));
690 
691 	/* We must be stood on a house foundation */
692 	o_ptr = &o_list[cave[p_ptr->dun_depth][p_ptr->py][p_ptr->px].o_idx];
693 	if (o_ptr->tval != TV_JUNK || o_ptr->sval != SV_HOUSE_FOUNDATION)
694 	{
695 		msg_print(p_ptr, "There is no house foundation here.");
696 		return FALSE;
697 	}
698 
699 	/* Start from the players position */
700 	x1 = p_ptr->px;
701 	x2 = p_ptr->px;
702 	y1 = p_ptr->py;
703 	y2 = p_ptr->py;
704 
705 	done = FALSE;
706 	while(!done)
707 	{
708 		n = s = e = w = ne = nw = se = sw = FALSE;
709 
710 		/* Could we expand north? */
711 		n = TRUE;
712 		for(x = x1; x <= x2; x++)
713 		{
714 			/* Is this a valid location for part of our house? */
715 			if(!is_valid_foundation(p_ptr, x, y1-1))
716 			{
717 				/* Not a valid perimeter */
718 				n = FALSE;
719 				break;
720 			}
721 		}
722 
723 		/* Could we expand east? */
724 		e = TRUE;
725 		for(y = y1; y <= y2; y++)
726 		{
727 			/* Is this a valid location for part of our house? */
728 			if(!is_valid_foundation(p_ptr, x2+1, y))
729 			{
730 				/* Not a valid perimeter */
731 				e = FALSE;
732 				break;
733 			}
734 		}
735 
736 		/* Could we expend south? */
737 		s = TRUE;
738 		for(x = x1; x <= x2; x++)
739 		{
740 			/* Is this a valid location for part of our house? */
741 			if(!is_valid_foundation(p_ptr, x, y2+1))
742 			{
743 				/* Not a valid perimeter */
744 				s = FALSE;
745 				break;
746 			}
747 		}
748 
749 		/* Could we expand west? */
750 		w = TRUE;
751 		for(y = y1; y <= y2; y++)
752 		{
753 			/* Is this a valid location for part of our house? */
754 			if(!is_valid_foundation(p_ptr, x1-1, y))
755 			{
756 				/* Not a valid perimeter */
757 				w = FALSE;
758 				break;
759 			}
760 		}
761 
762 		/* Could we expand the corners? */
763 		ne = is_valid_foundation(p_ptr, x2+1, y1-1);
764 		nw = is_valid_foundation(p_ptr, x1-1, y1-1);
765 		se = is_valid_foundation(p_ptr, x2+1, y2+1);
766 		sw = is_valid_foundation(p_ptr, x1-1, y2+1);
767 
768 		/* Only permit expansion in a way that maintains a rectangle, we don't
769 		 * want to create fancy polygons. */
770 		if( n ) n = (!e && !w) || ( e && ne ) || ( w && nw );
771 		if( e ) e = (!n && !s) || ( n && ne ) || ( s && se );
772 		if( s ) s = (!e && !w) || ( e && se ) || ( w && sw );
773 		if( w ) w = (!n && !s) || ( n && nw ) || ( s && sw );
774 
775 		/* Actually expand the boundary */
776 		if( n ) y1--;
777 		if( s ) y2++;
778 		if( w ) x1--;
779 		if( e ) x2++;
780 
781 		/* Stop if we couldn't expand */
782 		done = !(n || s || w || e);
783 
784 	}
785 
786 	plog(format("Proposed house is at x1,y1,x2,y2 %d,%d,%d,%d",x1,y1,x2,y2));
787 
788 	/* Is the bounding rectangle we found big enough? */
789 	if(x2-x1 < 2 || y2-y1 < 2)
790 	{
791 		msg_print(p_ptr, "The foundation is too small.");
792 		return FALSE;
793 	}
794 
795 	/* Return the area */
796 	*px1 = x1;
797 	*px2 = x2;
798 	*py1 = y1;
799 	*py2 = y2;
800 	return TRUE;
801 }
802 
803 /*
804  * Create a new house.
805  * The creating player owns the house.
806  */
create_house(player_type * p_ptr)807 bool create_house(player_type *p_ptr)
808 {
809 	int x1, x2, y1, y2, x, y;
810 	cave_type *c_ptr;
811 
812 	/* Not in dungeon, not in town */
813 	if (p_ptr->dun_depth >= 0 || check_special_level(p_ptr->dun_depth))
814 	{
815 		msg_print(p_ptr, "The surrounding magic is too strong for House Creation.");
816 		return FALSE;
817 	}
818 
819 	/* Determine the area of the house foundation */
820 	if (!get_house_foundation(p_ptr, &x1, &y1, &x2, &y2))
821 	{
822 		return FALSE;
823 	}
824 
825 	/* Is the location allowed? */
826 	/* XXX We should check if too near other houses, roads, level edges, etc */
827 
828 	/* Add a house to our houses list */
829 	houses[num_houses].price = 0;	/* XXX */
830 	houses[num_houses].x_1 = x1+1;
831 	houses[num_houses].y_1 = y1+1;
832 	houses[num_houses].x_2 = x2-1;
833 	houses[num_houses].y_2 = y2-1;
834 	houses[num_houses].depth = p_ptr->dun_depth;
835 	houses[num_houses].door_y = 0;
836 	houses[num_houses].door_x = 0;
837 	set_house_owner(p_ptr, num_houses);
838 	num_houses++;
839 
840 	/* Render into the terrain */
841 	for (y = y1; y <= y2; y++)
842 	{
843 		for (x = x1; x <= x2; x++)
844 		{
845 			/* Get the grid */
846 			c_ptr = &cave[p_ptr->dun_depth][y][x];
847 
848 			/* Delete any object */
849 			delete_object(p_ptr->dun_depth, y, x);
850 
851 			/* Build a wall, but don't destroy any existing door */
852 			if( c_ptr->feat < FEAT_HOME_HEAD || c_ptr->feat > FEAT_HOME_TAIL)
853 			{
854 				c_ptr->feat = FEAT_PERM_EXTRA;
855 			}
856 
857 			/* Update the spot */
858 			everyone_lite_spot(p_ptr->dun_depth, y, x);
859 		}
860 	}
861 	for (y = y1 + 1; y < y2; y++)
862 	{
863 		for (x = x1 + 1; x < x2; x++)
864 		{
865 			/* Get the grid */
866 			c_ptr = &cave[p_ptr->dun_depth][y][x];
867 
868 			/* Delete any object */
869 			delete_object(p_ptr->dun_depth, y, x);
870 
871 			/* Fill with floor */
872 			c_ptr->feat = FEAT_FLOOR;
873 
874 			/* Make it "icky" */
875 			c_ptr->info |= CAVE_ICKY;
876 
877 			/* Update the spot */
878 			everyone_lite_spot(p_ptr->dun_depth, y, x);
879 		}
880 	}
881 	return TRUE;
882 }
883 
884 /*
885  * Set the owner of the given house
886  */
set_house_owner(player_type * p_ptr,int house)887 bool set_house_owner(player_type *p_ptr, int house)
888 {
889 	/* Not if it's already owned */
890 	if (house_owned(house)) return FALSE;
891 
892 	/* Set the player as the owner */
893 	my_strcpy(houses[house].owned, p_ptr->name, MAX_NAME_LEN+1);
894 
895 	return TRUE;
896 }
897 
898 /*
899  * Set the given house as unowned
900  */
disown_house(int house)901 void disown_house(int house)
902 {
903 	cave_type *c_ptr;
904 	int i,j, Depth;
905 
906 	if (house >= 0 && house < num_houses)
907 	{
908 		Depth = houses[house].depth;
909 		houses[house].owned[0] = '\0';
910 		houses[house].strength = 0;
911 		/* Remove all players from the house */
912 		for (i = 1; i <= NumPlayers; i++)
913 		{
914 			if (house_inside(Players[i], house))
915 			{
916 				msg_print(Players[i], "You have been expelled from the house.");
917 				teleport_player(Players[i], 5);
918 			}
919 		}
920 		/* Clear any items from the house */
921 		for (i = houses[house].y_1; i <= houses[house].y_2; i++)
922 		{
923 			for (j = houses[house].x_1; j <= houses[house].x_2; j++)
924 			{
925 				delete_object(houses[house].depth,i,j);
926 			}
927 		}
928 
929 		/* Paranoia! */
930 		if (!cave[Depth]) return;
931 
932 		/* Get requested grid */
933 		c_ptr = &cave[Depth][houses[house].door_y][houses[house].door_x];
934 
935 		/* Close the door */
936 		c_ptr->feat = FEAT_HOME_HEAD + houses[house].strength;
937 
938 		/* Reshow */
939 		everyone_lite_spot(Depth, houses[house].door_y, houses[house].door_x);
940 
941 	}
942 }
943 
944 /*
945  * Attempt to open the given chest at the given location
946  *
947  * Assume there is no monster blocking the destination
948  *
949  * Returns TRUE if repeated commands may continue
950  */
do_cmd_open_chest(player_type * p_ptr,int y,int x,s16b o_idx)951 static bool do_cmd_open_chest(player_type *p_ptr, int y, int x, s16b o_idx)
952 {
953 	int i, j;
954 
955 	bool flag = TRUE;
956 
957 	bool more = FALSE;
958 
959 	object_type *o_ptr = &o_list[o_idx];
960 
961 
962 	/* Attempt to unlock it */
963 	if (o_ptr->pval > 0)
964 	{
965 		/* Assume locked, and thus not open */
966 		flag = FALSE;
967 
968 		/* Get the "disarm" factor */
969 		i = p_ptr->skill_dis;
970 
971 		/* Penalize some conditions */
972 		if (p_ptr->blind || no_lite(p_ptr)) i = i / 10;
973 		if (p_ptr->confused || p_ptr->image) i = i / 10;
974 
975 		/* Extract the difficulty */
976 		j = i - o_ptr->pval;
977 
978 		/* Always have a small chance of success */
979 		if (j < 2) j = 2;
980 
981 		/* Success -- May still have traps */
982 		if (randint0(100) < j)
983 		{
984 			msg_print_aux(p_ptr, "You have picked the lock.", MSG_LOCKPICK);
985 			sound(p_ptr, MSG_LOCKPICK);
986 			gain_exp(p_ptr, 1);
987 			flag = TRUE;
988 		}
989 
990 		/* Failure -- Keep trying */
991 		else
992 		{
993 			/* We may continue repeating */
994 			more = TRUE;
995 			/*if (flush_failure) flush();*/
996 			msg_print_aux(p_ptr, "You failed to pick the lock.", MSG_LOCKPICK_FAIL);
997 			sound(p_ptr, MSG_LOCKPICK_FAIL);
998 		}
999 	}
1000 
1001 	/* Allowed to open */
1002 	if (flag)
1003 	{
1004 		/* Apply chest traps, if any */
1005 		chest_trap(p_ptr, y, x, o_ptr);
1006 
1007 		/* Let the Chest drop items */
1008 		chest_death(p_ptr, y, x, o_ptr);
1009 	}
1010 
1011 	/* Result */
1012 	return (more);
1013 }
1014 
1015 /*
1016  * Attempt to disarm the chest at the given location
1017  *
1018  * Assume there is no monster blocking the destination
1019  *
1020  * Returns TRUE if repeated commands may continue
1021  */
do_cmd_disarm_chest(player_type * p_ptr,int y,int x,s16b o_idx)1022 static bool do_cmd_disarm_chest(player_type *p_ptr, int y, int x, s16b o_idx)
1023 {
1024 	int i, j;
1025 
1026 	bool more = FALSE;
1027 
1028 	object_type *o_ptr = &o_list[o_idx];
1029 
1030 
1031 	/* Get the "disarm" factor */
1032 	i = p_ptr->skill_dis;
1033 
1034 	/* Penalize some conditions */
1035 	if (p_ptr->blind || no_lite(p_ptr)) i = i / 10;
1036 	if (p_ptr->confused || p_ptr->image) i = i / 10;
1037 
1038 	/* Extract the difficulty */
1039 	j = i - o_ptr->pval;
1040 
1041 	/* Always have a small chance of success */
1042 	if (j < 2) j = 2;
1043 
1044 	/* Must find the trap first. */
1045 	if (!object_known_p(p_ptr, o_ptr))
1046 	{
1047 		msg_print(p_ptr, "I don't see any traps.");
1048 	}
1049 
1050 	/* Already disarmed/unlocked */
1051 	else if (o_ptr->pval <= 0)
1052 	{
1053 		msg_print(p_ptr, "The chest is not trapped.");
1054 	}
1055 
1056 	/* No traps to find. */
1057 	else if (!chest_traps[o_ptr->pval])
1058 	{
1059 		msg_print(p_ptr, "The chest is not trapped.");
1060 	}
1061 
1062 	/* Success (get a lot of experience) */
1063 	else if (randint0(100) < j)
1064 	{
1065 		msg_print_aux(p_ptr, "You have disarmed the chest.", MSG_DISARM);
1066 		sound(p_ptr, MSG_DISARM);
1067 		gain_exp(p_ptr, o_ptr->pval);
1068 		o_ptr->pval = (0 - o_ptr->pval);
1069 	}
1070 
1071 	/* Failure -- Keep trying */
1072 	else if ((i > 5) && (randint1(i) > 5))
1073 	{
1074 		/* We may keep trying */
1075 		more = TRUE;
1076 		/*if (flush_failure) flush();*/
1077 		msg_print(p_ptr, "You failed to disarm the chest.");
1078 	}
1079 
1080 	/* Failure -- Set off the trap */
1081 	else
1082 	{
1083 		msg_print(p_ptr, "You set off a trap!");
1084 		chest_trap(p_ptr, y, x, o_ptr);
1085 	}
1086 
1087 	/* Result */
1088 	return (more);
1089 }
1090 
1091 
1092 
1093 
1094 /*
1095  * Tunnel through wall.  Assumes valid location.
1096  *
1097  * Note that it is impossible to "extend" rooms past their
1098  * outer walls (which are actually part of the room).
1099  *
1100  * This will, however, produce grids which are NOT illuminated
1101  * (or darkened) along with the rest of the room.
1102  */
twall(player_type * p_ptr,int y,int x)1103 static bool twall(player_type *p_ptr, int y, int x)
1104 {
1105 	int Depth = p_ptr->dun_depth;
1106 
1107 	/* Paranoia -- Require a wall or door or some such */
1108 	if (cave_floor_bold(Depth, y, x)) return (FALSE);
1109 
1110 	/* Sound */
1111 	sound(p_ptr, MSG_DIG);
1112 
1113 	/* Forget the wall */
1114 	everyone_forget_spot(Depth, y, x);
1115 
1116 	/* Remove the feature */
1117 	if (Depth > 0)
1118 		cave_set_feat(Depth, y, x, FEAT_FLOOR);
1119 	else
1120 		cave_set_feat(Depth, y, x, FEAT_DIRT);
1121 
1122 	/* Note: cave_set_feat has handled updates for all players! */
1123 
1124 	/* Result */
1125 	return (TRUE);
1126 }
1127 
1128 /*
1129  * Determine if a given grid may be "opened"
1130  */
do_cmd_open_test(player_type * p_ptr,int y,int x)1131 static bool do_cmd_open_test(player_type *p_ptr, int y, int x)
1132 {
1133 	int Depth = p_ptr->dun_depth;
1134 
1135 	cave_type		*c_ptr;
1136 
1137 	/* Ghosts cannot open */
1138 	if ( (p_ptr->ghost || p_ptr->fruit_bat) && !(p_ptr->dm_flags & DM_GHOST_HANDS) )
1139 	{
1140 		/* Message */
1141 		msg_print(p_ptr, "You cannot open things!");
1142 
1143 		return (FALSE);
1144 	}
1145 
1146 	/* Get grid and contents */
1147 	c_ptr = &cave[Depth][y][x];
1148 
1149 	/* Must have knowledge */
1150 	if (!(p_ptr->cave_flag[y][x] & (CAVE_MARK)))
1151 	{
1152 		/* Message */
1153 		msg_print(p_ptr, "You see nothing there.");
1154 
1155 		/* Nope */
1156 		return (FALSE);
1157 	}
1158 
1159 	/* Must be a closed door */
1160 	if (!((c_ptr->feat >= FEAT_DOOR_HEAD) &&
1161 	      (c_ptr->feat <= FEAT_DOOR_TAIL)) &&
1162 	      /* OR MAngband-specific: Player house doors */
1163 	    !((c_ptr->feat >= FEAT_HOME_HEAD) &&
1164 	      (c_ptr->feat <= FEAT_HOME_TAIL)) &&
1165 	      /* OR MAngband-specific: House Creation */
1166 	     !(c_ptr->feat == FEAT_PERM_EXTRA))
1167 	{
1168 		/* Message */
1169 		msg_print_aux(p_ptr, "You see nothing there to open.", MSG_NOTHING_TO_OPEN);
1170 		sound(p_ptr, MSG_NOTHING_TO_OPEN);
1171 
1172 		/* Nope */
1173 		return (FALSE);
1174 	}
1175 
1176 	/* Okay */
1177 	return (TRUE);
1178 }
1179 
1180 
1181 /*
1182  * Perform the basic "open" command on doors
1183  *
1184  * Assume there is no monster blocking the destination
1185  *
1186  * Returns TRUE if repeated commands may continue
1187  */
do_cmd_open_aux(player_type * p_ptr,int y,int x)1188 static bool do_cmd_open_aux(player_type *p_ptr, int y, int x)
1189 {
1190 	int Depth = p_ptr->dun_depth;
1191 
1192 	cave_type		*c_ptr;
1193 
1194 	int i, j, k;
1195 
1196 	bool more = FALSE;
1197 
1198 
1199 	/* Verify legality */
1200 	if (!do_cmd_open_test(p_ptr, y, x)) return (FALSE);
1201 
1202 	/* Get grid and contents */
1203 	c_ptr = &cave[Depth][y][x];
1204 
1205 
1206 	/* We put MAngband-specific tests on top, as new FEATs are larger */
1207 	/* Player Houses */
1208 	if (c_ptr->feat >= FEAT_HOME_HEAD && c_ptr->feat <= FEAT_HOME_TAIL)
1209 	{
1210 		i = pick_house(Depth, y, x);
1211 
1212 		if (i == -1)
1213 		{
1214 			debug(format("No house found at Depth %d, X=%d, Y=%d !", Depth, y, x));
1215 			return (FALSE);
1216 		}
1217 
1218 		/* Do we own this house? */
1219 		if (house_owned_by(p_ptr, i) || (p_ptr->dm_flags & DM_HOUSE_CONTROL) )
1220 		{
1221 
1222 			/* If someone is in our store, we eject them (anti-exploit) */
1223 			for (k = 1; k <= NumPlayers; k++ )
1224 			{
1225 				/* We don't block if the owner is getting out! */
1226 				player_type *q_ptr = Players[k];
1227 				if (q_ptr && !same_player(p_ptr, q_ptr))
1228 				{
1229 					/* We do block if the owner is getting in */
1230 					if(q_ptr->player_store_num == i && q_ptr->store_num == 8)
1231 					{
1232 						q_ptr->store_num = -1;
1233 						send_store_leave(q_ptr);
1234 						msg_print(q_ptr, "The shopkeeper locks the doors.");
1235 					}
1236 				}
1237 			}
1238 
1239 			/* Open the door */
1240 			c_ptr->feat = FEAT_HOME_OPEN;
1241 
1242 			/* Notice */
1243 			note_spot_depth(Depth, y, x);
1244 
1245 			/* Redraw */
1246 			everyone_lite_spot(Depth, y, x);
1247 
1248 			/* Update some things */
1249 			p_ptr->update |= (PU_VIEW | PU_LITE | PU_MONSTERS);
1250 		}
1251 
1252 		/* He's not the owner, check if owned */
1253 		else if (house_owned(i))
1254 		{
1255 			/* Player owned store! */
1256 
1257 			/* Disturb */
1258 			disturb(p_ptr, 0, 0);
1259 
1260 			/* Hack -- Enter store */
1261 			/*command_new = '_';*/
1262 			do_cmd_store(p_ptr, i);
1263 		}
1264 		else
1265 		{
1266 			int price, factor;
1267 
1268 			/* Take CHR into account */
1269 			factor = adj_chr_gold[p_ptr->stat_ind[A_CHR]];
1270             price = (unsigned long) houses[i].price * factor / 100;
1271 			if(Depth==0) {
1272 				price = (unsigned long)price *5L;
1273 			};
1274 
1275 			/* Tell him the price */
1276 			msg_format(p_ptr, "This house costs %ld gold.", price);
1277 		}
1278 	}
1279 
1280 	/* Open a perma wall */
1281 	else if (c_ptr->feat == FEAT_PERM_EXTRA)
1282 	{
1283 		/* Opening a wall?  Either the player has lost his mind or he
1284 		 * is trying to create a door! */
1285 		create_house_door(p_ptr, x, y);
1286 	}
1287 
1288 	/* Jammed door */
1289 	else if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x08)
1290 	{
1291 		/* Stuck */
1292 		msg_print(p_ptr, "The door appears to be stuck.");
1293 	}
1294 
1295 	/* Locked door */
1296 	else if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x01)
1297 	{
1298 		/* Disarm factor */
1299 		i = p_ptr->skill_dis;
1300 
1301 		/* Penalize some conditions */
1302 		if (p_ptr->blind || no_lite(p_ptr)) i = i / 10;
1303 		if (p_ptr->confused || p_ptr->image) i = i / 10;
1304 
1305 		/* Extract the lock power */
1306 		j = c_ptr->feat - FEAT_DOOR_HEAD;
1307 
1308 		/* Extract the difficulty XXX XXX XXX */
1309 		j = i - (j * 4);
1310 
1311 		/* Always have a small chance of success */
1312 		if (j < 2) j = 2;
1313 
1314 		/* Success */
1315 		if (randint0(100) < j)
1316 		{
1317 			/* Message */
1318 			msg_print_aux(p_ptr, "You have picked the lock.", MSG_LOCKPICK);
1319 			sound(p_ptr, MSG_LOCKPICK);
1320 
1321 			/* Open the door */
1322 			cave_set_feat(Depth, y, x, FEAT_OPEN);
1323 
1324 			/* Experience */
1325 			gain_exp(p_ptr, 1);
1326 		}
1327 
1328 		/* Failure */
1329 		else
1330 		{
1331 			/* Failure */
1332 			/*if (flush_failure) flush();*/
1333 
1334 			/* Message */
1335 			msg_print_aux(p_ptr, "You failed to pick the lock.", MSG_LOCKPICK_FAIL);
1336 			sound(p_ptr, MSG_LOCKPICK_FAIL);
1337 
1338 			/* We may keep trying */
1339 			more = TRUE;
1340 		}
1341 	}
1342 
1343 	/* Closed door */
1344 	else
1345 	{
1346 		/* Open the door */
1347 		/*cave_set_feat(y, x, FEAT_OPEN);*/
1348 		c_ptr->feat = FEAT_OPEN;
1349 
1350 		/* Notice */
1351 		note_spot_depth(Depth, y, x);
1352 
1353 		/* Redraw */
1354 		everyone_lite_spot(Depth, y, x);
1355 
1356 		/* Update some things */
1357 		p_ptr->update |= (PU_VIEW | PU_LITE | PU_MONSTERS);
1358 
1359 		/* Sound */
1360 		sound(p_ptr, MSG_OPENDOOR);
1361 	}
1362 
1363 	/* Result */
1364 	return (more);
1365 }
1366 
1367 
1368 
1369 /*
1370  * Open a closed/locked/jammed door or a closed/locked chest.
1371  *
1372  * Unlocking a locked door/chest is worth one experience point.
1373  */
do_cmd_open(player_type * p_ptr,int dir)1374 void do_cmd_open(player_type *p_ptr, int dir)
1375 {
1376 	int Depth = p_ptr->dun_depth;
1377 
1378 	cave_type		*c_ptr;
1379 	object_type		*o_ptr;
1380 
1381 	int y, x;
1382 
1383 	s16b o_idx;
1384 
1385 	bool more = FALSE;
1386 
1387 #if 0
1388 	/* Easy Open */
1389 	if (p_ptr->easy_open)
1390 	{
1391 		int num_doors, num_chests;
1392 
1393 		/* Count closed doors */
1394 		num_doors = count_feats(&y, &x, is_closed, FALSE);
1395 
1396 		/* Count chests (locked) */
1397 		num_chests = count_chests(&y, &x, FALSE);
1398 
1399 		/* See if only one target */
1400 		if ((num_doors + num_chests) == 1)
1401 		{
1402 			p_ptr->command_dir = motion_dir(p_ptr->py, p_ptr->px, y, x);
1403 		}
1404 	}
1405 #endif
1406 	/* Get a direction (or abort) */
1407 	/*if (!get_rep_dir(&dir)) return;*/
1408 	if (!VALID_DIR(dir)) return;
1409 
1410 	/* Get location */
1411 	y = p_ptr->py + ddy[dir];
1412 	x = p_ptr->px + ddx[dir];
1413 
1414 	/* Get grid and contents */
1415 	c_ptr = &cave[Depth][y][x];
1416 
1417 	/* Access the item */
1418 	o_ptr = &o_list[c_ptr->o_idx];
1419 
1420 	/* Check for chests */
1421 	o_idx = (o_ptr->tval == TV_CHEST ? c_ptr->o_idx : 0);
1422 
1423 
1424 	/* Verify legality */
1425 	if (!o_idx && !do_cmd_open_test(p_ptr, y, x)) return;
1426 
1427 
1428 	/* Take a turn */
1429 	p_ptr->energy -= level_speed(p_ptr->dun_depth);
1430 
1431 	/* Apply confusion */
1432 	if (confuse_dir((bool)p_ptr->confused, &dir))
1433 	{
1434 		/* Get location */
1435 		y = p_ptr->py + ddy[dir];
1436 		x = p_ptr->px + ddx[dir];
1437 
1438 		/* Get grid and contents */
1439 		c_ptr = &cave[Depth][y][x];
1440 
1441 		/* Access the item */
1442 		o_ptr = &o_list[c_ptr->o_idx];
1443 
1444 		/* Check for chest */
1445 		o_idx = (o_ptr->tval == TV_CHEST ? c_ptr->o_idx : 0);
1446 	}
1447 
1448 
1449 	/* Allow repeated command */
1450 	if (p_ptr->command_arg)
1451 	{
1452 		/* Set repeat count */
1453 		/*p_ptr->command_rep = p_ptr->command_arg - 1;*/
1454 
1455 		/* Redraw the state */
1456 		p_ptr->redraw |= (PR_STATE);
1457 
1458 		/* Cancel the arg */
1459 		p_ptr->command_arg = 0;
1460 	}
1461 
1462 	/* Monster */
1463 	if (c_ptr->m_idx > 0)
1464 	{
1465 		/* Message */
1466 		msg_print(p_ptr, "There is a monster in the way!");
1467 
1468 		/* Attack */
1469 		py_attack(p_ptr, y, x);
1470 	}
1471 
1472 	/* Player in the way */
1473 	else if (c_ptr->m_idx < 0)
1474 	{
1475 		/* Take a turn */
1476 		p_ptr->energy -= level_speed(p_ptr->dun_depth);
1477 
1478 		/* Message */
1479 		msg_print(p_ptr, "There is a player in the way!");
1480 
1481 	}
1482 
1483 	/* Chest */
1484 	else if (o_idx)
1485 	{
1486 		/* Open the chest */
1487 		more = do_cmd_open_chest(p_ptr, y, x, o_idx);
1488 	}
1489 
1490 	/* Door */
1491 	else
1492 	{
1493 		/* Open the door */
1494 		more = do_cmd_open_aux(p_ptr, y, x);
1495 	}
1496 
1497 	/* Cancel repeat unless we may continue */
1498 	if (!more) disturb(p_ptr, 0, 0);
1499 }
1500 
1501 
1502 /*
1503  * Determine if a given grid may be "closed"
1504  */
do_cmd_close_test(player_type * p_ptr,int y,int x)1505 static bool do_cmd_close_test(player_type *p_ptr, int y, int x)
1506 {
1507 	int Depth = p_ptr->dun_depth;
1508 
1509 	cave_type		*c_ptr;
1510 
1511 #if 0
1512 	/* Ghosts cannot close */
1513 	if ( (p_ptr->ghost || p_ptr->fruit_bat) && !(p_ptr->dm_flags & DM_GHOST_HANDS) )
1514 	{
1515 		/* Message */
1516 		msg_print(p_ptr, "You cannot close things!");
1517 
1518 		return (FALSE);
1519 	}
1520 #endif
1521 	/* Get grid and contents */
1522 	c_ptr = &cave[Depth][y][x];
1523 
1524 	/* Must have knowledge */
1525 	if (!(p_ptr->cave_flag[y][x] & (CAVE_MARK)))
1526 	{
1527 		/* Message */
1528 		msg_print(p_ptr, "You see nothing there.");
1529 
1530 		/* Nope */
1531 		return (FALSE);
1532 	}
1533 
1534  	/* Require open/broken door */
1535 	if ((c_ptr->feat != FEAT_OPEN) &&
1536 	    (c_ptr->feat != FEAT_BROKEN) &&
1537 	    (c_ptr->feat != FEAT_HOME_OPEN))
1538 	{
1539 		/* Message */
1540 		msg_print(p_ptr, "You see nothing there to close.");
1541 
1542 		/* Nope */
1543 		return (FALSE);
1544 	}
1545 
1546 	/* Okay */
1547 	return (TRUE);
1548 }
1549 
1550 
1551 /*
1552  * Perform the basic "close" command
1553  *
1554  * Assume there is no monster blocking the destination
1555  *
1556  * Returns TRUE if repeated commands may continue
1557  */
do_cmd_close_aux(player_type * p_ptr,int y,int x)1558 static bool do_cmd_close_aux(player_type *p_ptr, int y, int x)
1559 {
1560 	int Depth = p_ptr->dun_depth;
1561 
1562 	cave_type		*c_ptr;
1563 
1564 	int 	i;
1565 
1566 	bool more = FALSE;
1567 
1568 	/* Verify legality */
1569 	if (!do_cmd_close_test(p_ptr, y, x)) return (FALSE);
1570 
1571 
1572 	/* Get grid and contents */
1573 	c_ptr = &cave[Depth][y][x];
1574 
1575 
1576 	/* Broken door */
1577 	if (c_ptr->feat == FEAT_BROKEN)
1578 	{
1579 		/* Message */
1580 		msg_print(p_ptr, "The door appears to be broken.");
1581 	}
1582 
1583 	/* (MAngband-specific) House door, close it */
1584 	else if (c_ptr->feat == FEAT_HOME_OPEN)
1585 	{
1586 		/* Find this house */
1587 		i = pick_house(Depth, y, x);
1588 
1589 		/* Close the door */
1590 		c_ptr->feat = FEAT_HOME_HEAD + houses[i].strength;
1591 
1592 		/* Notice */
1593 		note_spot_depth(Depth, y, x);
1594 
1595 		/* Redraw */
1596 		everyone_lite_spot(Depth, y, x);
1597 
1598 		/* Update some things */
1599 		p_ptr->update |= (PU_VIEW | PU_LITE | PU_MONSTERS);
1600 	}
1601 
1602 	/* Open door */
1603 	else
1604 	{
1605 		/* Close the door */
1606 		c_ptr->feat = FEAT_DOOR_HEAD + 0x00;
1607 
1608 		/* Notice */
1609 		note_spot_depth(Depth, y, x);
1610 
1611 		/* Redraw */
1612 		everyone_lite_spot(Depth, y, x);
1613 
1614 		/* Update some things */
1615 		p_ptr->update |= (PU_VIEW | PU_LITE | PU_MONSTERS);
1616 
1617 		/* Sound */
1618 		sound(p_ptr, MSG_SHUTDOOR);
1619 	}
1620 
1621 	/* Result */
1622 	return (more);
1623 }
1624 
1625 
1626 /*
1627  * Close an open door.
1628  */
do_cmd_close(player_type * p_ptr,int dir)1629 void do_cmd_close(player_type *p_ptr, int dir)
1630 {
1631 	int Depth = p_ptr->dun_depth;
1632 
1633 	cave_type		*c_ptr;
1634 
1635 	int y, x;
1636 
1637 	bool more = FALSE;
1638 
1639 	/* Check preventive inscription '^c' */
1640 	__trap(p_ptr, CPI(p_ptr, 'c'));
1641 
1642 #if 0
1643 	/* Easy Close */
1644 	if (p_ptr->easy_open)
1645 	{
1646 		/* Count open doors */
1647 		if (count_feats(&y, &x, is_open, FALSE) == 1)
1648 		{
1649 			p_ptr->command_dir = motion_dir(p_ptr->py, p_ptr->px, y, x);
1650 		}
1651 	}
1652 #endif
1653 	/* Get a direction (or abort) */
1654 	/*if (!get_rep_dir(&dir)) return;*/
1655 	if (!VALID_DIR(dir)) return;
1656 
1657 	/* Get location */
1658 	y = p_ptr->py + ddy[dir];
1659 	x = p_ptr->px + ddx[dir];
1660 
1661 	/* Verify legality */
1662 	if (!do_cmd_close_test(p_ptr, y, x)) return;
1663 
1664 	/* Take a turn */
1665 	p_ptr->energy -= level_speed(p_ptr->dun_depth);
1666 
1667 	/* Apply confusion */
1668 	if (confuse_dir((bool)p_ptr->confused, &dir))
1669 	{
1670 		/* Get location */
1671 		y = p_ptr->py + ddy[dir];
1672 		x = p_ptr->px + ddx[dir];
1673 	}
1674 
1675 	/* Get grid and contents */
1676 	c_ptr = &cave[Depth][y][x];
1677 
1678 	/* Allow repeated command */
1679 	if (p_ptr->command_arg)
1680 	{
1681 		/* Set repeat count */
1682 		/*p_ptr->command_rep = p_ptr->command_arg - 1;*/
1683 
1684 		/* Redraw the state */
1685 		p_ptr->redraw |= (PR_STATE);
1686 
1687 		/* Cancel the arg */
1688 		p_ptr->command_arg = 0;
1689 	}
1690 
1691 	/* Monster */
1692 	if (c_ptr->m_idx > 0)
1693 	{
1694 		/* Message */
1695 		msg_print(p_ptr, "There is a monster in the way!");
1696 
1697 		/* Attack */
1698 		py_attack(p_ptr, y, x);
1699 	}
1700 
1701 	/* Player in the way */
1702 	else if (c_ptr->m_idx < 0)
1703 	{
1704 		/* Message */
1705 		msg_print(p_ptr, "There is a player in the way!");
1706 	}
1707 
1708 	/* Door */
1709 	else
1710 	{
1711 		/* Close door */
1712 		more = do_cmd_close_aux(p_ptr, y, x);
1713 	}
1714 
1715 	/* Cancel repeat unless told not to */
1716 	if (!more) disturb(p_ptr, 0, 0);
1717 }
1718 
1719 
1720 /*
1721  * Determine if a given grid may be "tunneled"
1722  */
do_cmd_tunnel_test(player_type * p_ptr,int y,int x)1723 static bool do_cmd_tunnel_test(player_type *p_ptr, int y, int x)
1724 {
1725 	int Depth = p_ptr->dun_depth;
1726 
1727 	cave_type		*c_ptr;
1728 
1729 
1730 	/* Ghosts cannot tunnel */
1731 	if ( (p_ptr->ghost || p_ptr->fruit_bat) && !(p_ptr->dm_flags & DM_GHOST_HANDS) )
1732 	{
1733 		/* Message */
1734 		msg_print(p_ptr, "You cannot tunnel!");
1735 
1736 		return (FALSE);
1737 	}
1738 
1739 	/* Get grid and contents */
1740 	c_ptr = &cave[Depth][y][x];
1741 
1742 	/* Must have knowledge */
1743 	if (!(p_ptr->cave_flag[y][x] & (CAVE_MARK)))
1744 	{
1745 		/* Message */
1746 		msg_print(p_ptr, "You see nothing there.");
1747 
1748 		/* Nope */
1749 		return (FALSE);
1750 	}
1751 
1752 	/* Must be a wall/door/etc */
1753 	if (cave_floor_bold(Depth, y, x))
1754 	{
1755 		/* Message */
1756 		msg_print(p_ptr, "You see nothing there to tunnel.");
1757 
1758 		/* Nope */
1759 		return (FALSE);
1760 	}
1761 
1762 	/* No tunnelling through house doors */
1763 	if (c_ptr->feat == FEAT_HOME_OPEN ||
1764 		(c_ptr->feat >= FEAT_HOME_HEAD && c_ptr->feat <= FEAT_HOME_TAIL))
1765 	{
1766 		/* Message */
1767 		msg_print(p_ptr, "You cannot tunnel through house doors.");
1768 
1769 		/* Nope */
1770 		return (FALSE);
1771 	}
1772 #if 0
1773 	/* No tunnelling through emptiness */
1774 	if ( (cave_floor_bold(Depth, y, x)) || (c_ptr->feat == FEAT_PERM_CLEAR) )
1775 	{
1776 		/* Message */
1777 		msg_print(p_ptr, "You see nothing there to tunnel through.");
1778 	}
1779 #endif
1780 	/* Okay */
1781 	return (TRUE);
1782 }
1783 
1784 /* Return "cutting bonus" (0-4) based on weapon effeciency against trees
1785  * This macro depends on TV_SWORD SVALues being ordered from less
1786  * powerfull to more powerfull. */
1787 #define wielding_cut(TV,SV) \
1788 	((((TV) == TV_SWORD) ? (((SV) >= SV_LONG_SWORD) ? 2 : \
1789 		(((SV) >= SV_SMALL_SWORD) ? 1 : 0)) : \
1790 	(((TV) == TV_POLEARM) ? (((SV) == SV_SCYTHE_OF_SLICING) ? 4 : \
1791 		(((SV) >= SV_SCYTHE) ? 3 : (((SV) >= SV_BEAKED_AXE) ? 2 : 0))) : 0 )))
1792 
1793 #define wielding_cut_o(O) \
1794 	(wielding_cut((O).tval,(O).sval))
1795 #define wielding_cut_p(P) \
1796 	(wielding_cut_o((P)->inventory[INVEN_WIELD]))
1797 /*
1798  * Perform the basic "tunnel" command
1799  *
1800  * Assumes that no monster is blocking the destination
1801  *
1802  * Uses "twall" (above) to do all "terrain feature changing".
1803  *
1804  * Returns TRUE if repeated commands may continue
1805  */
do_cmd_tunnel_aux(player_type * p_ptr,int y,int x)1806 static bool do_cmd_tunnel_aux(player_type *p_ptr, int y, int x)
1807 {
1808 	int Depth = p_ptr->dun_depth;
1809 
1810 	cave_type		*c_ptr;
1811 
1812 	bool more = FALSE;
1813 
1814 
1815 	/* Verify legality */
1816 	if (!do_cmd_tunnel_test(p_ptr, y, x)) return (FALSE);
1817 
1818 	/* Get grid and contents */
1819 	c_ptr = &cave[Depth][y][x];
1820 
1821 	/* Sound XXX XXX XXX */
1822 	sound(p_ptr, MSG_DIG);
1823 
1824 	/* Hack -- We put MAngband-specific terrain features on top, as they are higher */
1825 
1826 	/* Vegetation */
1827 	if (c_ptr->feat == FEAT_TREE)
1828 	{
1829 		/* Mow down the vegetation */
1830 		if ((p_ptr->skill_dig + wielding_cut_p(p_ptr) * 10 > randint0(400)) && twall(p_ptr, y, x))
1831 		{
1832 			if (Depth == 0) trees_in_town--;
1833 
1834 			/* Message */
1835 			msg_print(p_ptr, "You hack your way through the vegetation.");
1836 		}
1837 		else
1838 		{
1839 			/* Message, keep digging */
1840 			msg_print(p_ptr, "You attempt to clear a path.");
1841 			more = TRUE;
1842 		}
1843 	}
1844 
1845 	else if (c_ptr->feat == FEAT_EVIL_TREE)
1846 	{
1847 		/* Mow down the vegetation */
1848 		if ((p_ptr->skill_dig + wielding_cut_p(p_ptr) * 10 > randint0(600)) && twall(p_ptr, y, x))
1849 		{
1850 			/* Message */
1851 			msg_print(p_ptr, "You hack your way through the vegetation.");
1852 		}
1853 		else
1854 		{
1855 			/* Message, keep digging */
1856 			msg_print(p_ptr, "You attempt to clear a path.");
1857 			more = TRUE;
1858 		}
1859 	}
1860 
1861 	/* Titanium */
1862 	else if (c_ptr->feat >= FEAT_PERM_EXTRA)
1863 	{
1864 		msg_print(p_ptr, "This seems to be permanent rock.");
1865 	}
1866 
1867 	/* Granite */
1868 	else if (c_ptr->feat >= FEAT_WALL_EXTRA)
1869 	{
1870 		/* Tunnel */
1871 		if ((p_ptr->skill_dig > 40 + randint0(1600)) && twall(p_ptr, y, x))
1872 		{
1873 			msg_print(p_ptr, "You have finished the tunnel.");
1874 		}
1875 
1876 		/* Keep trying */
1877 		else
1878 		{
1879 			/* We may continue tunelling */
1880 			msg_print(p_ptr, "You tunnel into the granite wall.");
1881 			more = TRUE;
1882 		}
1883 	}
1884 
1885 	/* Quartz / Magma */
1886 	else if (c_ptr->feat >= FEAT_MAGMA)
1887 	{
1888 		bool okay = FALSE;
1889 		bool gold = FALSE;
1890 		bool hard = FALSE;
1891 
1892 		/* Found gold */
1893 		if (c_ptr->feat >= FEAT_MAGMA_H)
1894 		{
1895 			gold = TRUE;
1896 		}
1897 
1898 		/* Extract "quartz" flag XXX XXX XXX */
1899 		if ((c_ptr->feat - FEAT_MAGMA) & 0x01)
1900 		{
1901 			hard = TRUE;
1902 		}
1903 
1904 		/* Quartz */
1905 		if (hard)
1906 		{
1907 			okay = (p_ptr->skill_dig > 20 + randint0(800));
1908 		}
1909 
1910 		/* Magma */
1911 		else
1912 		{
1913 			okay = (p_ptr->skill_dig > 10 + randint0(400));
1914 		}
1915 
1916 		/* Success */
1917 		if (okay && twall(p_ptr, y, x))
1918 		{
1919 			/* Found treasure */
1920 			if (gold)
1921 			{
1922 				/* Place some gold */
1923 				place_gold(Depth, y, x);
1924 
1925 				/* Message */
1926 				msg_print(p_ptr, "You have found something!");
1927 			}
1928 
1929 			/* Found nothing */
1930 			else
1931 			{
1932 				/* Message */
1933 				msg_print(p_ptr, "You have finished the tunnel.");
1934 			}
1935 		}
1936 
1937 		/* Failure (quartz) */
1938 		else if (hard)
1939 		{
1940 			/* Message, continue digging */
1941 			msg_print(p_ptr, "You tunnel into the quartz vein.");
1942 			more = TRUE;
1943 		}
1944 
1945 		/* Failure (magma) */
1946 		else
1947 		{
1948 			/* Message, continue digging */
1949 			msg_print(p_ptr, "You tunnel into the magma vein.");
1950 			more = TRUE;
1951 		}
1952 	}
1953 
1954 	/* Rubble */
1955 	else if (c_ptr->feat == FEAT_RUBBLE)
1956 	{
1957 		/* Remove the rubble */
1958 		if ((p_ptr->skill_dig > randint0(200)) && twall(p_ptr, y, x))
1959 		{
1960 			/* Message */
1961 			msg_print(p_ptr, "You have removed the rubble.");
1962 
1963 			/* Hack -- place an object */
1964 			if (randint0(100) < 10)
1965 			{
1966 				/* Create a simple object */
1967 				place_object(Depth, y, x, FALSE, FALSE, ORIGIN_RUBBLE);
1968 
1969 				/* Observe new object */
1970 				if (player_can_see_bold(p_ptr, y, x))
1971 				{
1972 					msg_print(p_ptr, "You have found something!");
1973 				}
1974 			}
1975 		}
1976 
1977 		else
1978 		{
1979 			/* Message, keep digging */
1980 			msg_print(p_ptr, "You dig in the rubble.");
1981 			more = TRUE;
1982 		}
1983 	}
1984 
1985 	/* Secret doors */
1986 	else if (c_ptr->feat >= FEAT_SECRET)
1987 	{
1988 		/* Tunnel */
1989 		if ((p_ptr->skill_dig > 30 + randint0(1200)) && twall(p_ptr, y, x))
1990 		{
1991 			msg_print(p_ptr, "You have finished the tunnel.");
1992 		}
1993 
1994 		/* Keep trying */
1995 		else
1996 		{
1997 			/* We may continue tunelling */
1998 			msg_print(p_ptr, "You tunnel into the granite wall.");
1999 			more = TRUE;
2000 
2001 			/* Occasional Search XXX XXX */
2002 			if (randint0(100) < 25) search(p_ptr);
2003 		}
2004 	}
2005 
2006 	/* Doors */
2007 	else
2008 	{
2009 		/* Tunnel */
2010 		if ((p_ptr->skill_dig > 30 + randint0(1200)) && twall(p_ptr, y, x))
2011 		{
2012 			msg_print(p_ptr, "You have finished the tunnel.");
2013 		}
2014 
2015 		/* Keep trying */
2016 		else
2017 		{
2018 			/* We may continue tunelling */
2019 			msg_print(p_ptr, "You tunnel into the door.");
2020 			more = TRUE;
2021 		}
2022 	}
2023 
2024 	/* Result */
2025 	return (more);
2026 }
2027 
2028 
2029 /*
2030  * Tunnel through "walls" (including rubble and secret doors)
2031  *
2032  * Digging is very difficult without a "digger" weapon, but can be
2033  * accomplished by strong players using heavy weapons.
2034  */
do_cmd_tunnel(player_type * p_ptr,int dir)2035 void do_cmd_tunnel(player_type *p_ptr, int dir)
2036 {
2037 	int Depth = p_ptr->dun_depth;
2038 
2039 	cave_type		*c_ptr;
2040 
2041 	int y, x;
2042 
2043 	bool more = FALSE;
2044 
2045 	/* Check preventive inscription '^T' */
2046 	__trap(p_ptr, CPI(p_ptr, 'T'));
2047 
2048 	/* Get a direction (or abort) */
2049 	/*if (!get_rep_dir(&dir)) return;*/
2050 	if (!VALID_DIR(dir)) return;
2051 
2052 	/* Get location */
2053 	y = p_ptr->py + ddy[dir];
2054 	x = p_ptr->px + ddx[dir];
2055 
2056 	/* Oops */
2057 	if (!do_cmd_tunnel_test(p_ptr, y, x)) return;
2058 
2059 	/* Take a turn */
2060 	p_ptr->energy -= level_speed(p_ptr->dun_depth);
2061 
2062 	/* Apply confusion */
2063 	if (confuse_dir((bool)p_ptr->confused, &dir))
2064 	{
2065 		/* Get location */
2066 		y = p_ptr->py + ddy[dir];
2067 		x = p_ptr->px + ddx[dir];
2068 	}
2069 
2070 	/* Get grid and contents */
2071 	c_ptr = &cave[Depth][y][x];
2072 
2073 	/* Allow repeated command */
2074 	if (p_ptr->command_arg)
2075 	{
2076 		/* Set repeat count */
2077 		/* p_ptr->command_rep = p_ptr->command_arg - 1; */
2078 
2079 		/* Redraw the state */
2080 		p_ptr->redraw |= (PR_STATE);
2081 
2082 		/* Cancel the arg */
2083 		p_ptr->command_arg = 0;
2084 	}
2085 
2086 	/* Monster */
2087 	if (c_ptr->m_idx > 0)
2088 	{
2089 		/* Message */
2090 		msg_print(p_ptr, "There is a monster in the way!");
2091 
2092 		/* Attack */
2093 		py_attack(p_ptr, y, x);
2094 	}
2095 
2096 	/* Player in the way */
2097 	else if (c_ptr->m_idx < 0)
2098 	{
2099 		/* Message */
2100 		msg_print(p_ptr, "There is a player in the way!");
2101 	}
2102 
2103 	/* Walls */
2104 	else
2105 	{
2106 		/* Tunnel through walls */
2107 		more = do_cmd_tunnel_aux(p_ptr, y, x);
2108 	}
2109 
2110 	/* Cancel repetition unless we can continue */
2111 	if (!more) disturb(p_ptr, 0, 0);
2112 }
2113 
2114 
2115 /*
2116  * Determine if a given grid may be "disarmed"
2117  */
do_cmd_disarm_test(player_type * p_ptr,int y,int x)2118 static bool do_cmd_disarm_test(player_type *p_ptr, int y, int x)
2119 {
2120 	int Depth = p_ptr->dun_depth;
2121 
2122 	cave_type		*c_ptr;
2123 	object_type		*o_ptr;
2124 
2125 
2126 	/* Ghosts cannot disarm */
2127 	if ( (p_ptr->ghost || p_ptr->fruit_bat) && !(p_ptr->dm_flags & DM_GHOST_HANDS) )
2128 	{
2129 		/* Message */
2130 		msg_print(p_ptr, "You cannot disarm things!");
2131 
2132 		return (FALSE);
2133 	}
2134 
2135 	/* Get grid and contents */
2136 	c_ptr = &cave[Depth][y][x];
2137 
2138 	/* Access the item */
2139 	o_ptr = &o_list[c_ptr->o_idx];
2140 
2141 	/* Must have knowledge */
2142 	if (!(p_ptr->cave_flag[y][x] & (CAVE_MARK)))
2143 	{
2144 		/* Message */
2145 		msg_print(p_ptr, "You see nothing there.");
2146 
2147 		/* Nope */
2148 		return (FALSE);
2149 	}
2150 
2151 	/* Require an actual trap */
2152 	if (!((c_ptr->feat >= FEAT_TRAP_HEAD) &&
2153 	      (c_ptr->feat <= FEAT_TRAP_TAIL)))
2154 	{
2155 		/* Message */
2156 		msg_print(p_ptr, "You see nothing there to disarm.");
2157 
2158 		/* Nope */
2159 		return (FALSE);
2160 	}
2161 
2162 	/* Okay */
2163 	return (TRUE);
2164 }
2165 
2166 
2167 /*
2168  * Perform the basic "disarm" command
2169  *
2170  * Assume there is no monster blocking the destination
2171  *
2172  * Returns TRUE if repeated commands may continue
2173  */
do_cmd_disarm_aux(player_type * p_ptr,int y,int x,int dir)2174 static bool do_cmd_disarm_aux(player_type *p_ptr, int y, int x, int dir)
2175 {
2176 	int Depth = p_ptr->dun_depth;
2177 
2178 	cave_type		*c_ptr;
2179 
2180 	int i, j, power;
2181 
2182 	cptr name;
2183 
2184 	bool more = FALSE;
2185 
2186 
2187 	/* Verify legality */
2188 	if (!do_cmd_disarm_test(p_ptr, y, x)) return (FALSE);
2189 
2190 	/* Get grid and contents */
2191 	c_ptr = &cave[Depth][y][x];
2192 
2193 	/* Get the trap name */
2194 	name = (f_name + f_info[c_ptr->feat].name);
2195 
2196 	/* Get the "disarm" factor */
2197 	i = p_ptr->skill_dis;
2198 
2199 	/* Penalize some conditions */
2200 	if (p_ptr->blind || no_lite(p_ptr)) i = i / 10;
2201 	if (p_ptr->confused || p_ptr->image) i = i / 10;
2202 
2203 	/* XXX XXX XXX Variable power? */
2204 
2205 	/* Extract trap "power" */
2206 	power = 5;
2207 
2208 	/* Extract the difficulty */
2209 	j = i - power;
2210 
2211 	/* Always have a small chance of success */
2212 	if (j < 2) j = 2;
2213 
2214 	/* Success */
2215 	if (randint0(100) < j)
2216 	{
2217 		/* Message */
2218 		msg_format_type(p_ptr, MSG_DISARM, "You have disarmed the %s.", name);
2219 		sound(p_ptr, MSG_DISARM);
2220 
2221 		/* Reward */
2222 		gain_exp(p_ptr, power);
2223 
2224 		/* Forget the trap */
2225 		everyone_forget_spot(Depth, y, x);
2226 
2227 		/* Remove the trap */
2228 		/* cave_set_feat(Depth, y, x, FEAT_FLOOR); */
2229 		c_ptr->feat = FEAT_FLOOR;
2230 
2231 		/* Notice */
2232 		note_spot_depth(Depth, y, x);
2233 
2234 		/* Redisplay the grid */
2235 		everyone_lite_spot(Depth, y, x);
2236 #if 0
2237 		/* move the player onto the trap grid */
2238 		move_player(p_ptr, dir, FALSE);
2239 #endif
2240 	}
2241 
2242 	/* Failure -- Keep trying */
2243 	else if ((i > 5) && (randint1(i) > 5))
2244 	{
2245 		/* Failure */
2246 		/*if (flush_failure) flush();*/
2247 
2248 		/* Message */
2249 		msg_format(p_ptr, "You failed to disarm the %s.", name);
2250 
2251 		/* We may keep trying */
2252 		more = TRUE;
2253 	}
2254 
2255 	/* Failure -- Set off the trap */
2256 	else
2257 	{
2258 		/* Message */
2259 		msg_format(p_ptr, "You set off the %s!", name);
2260 
2261 		/* Hit the trap */
2262 		/*hit_trap(y, x); in MAngband we move.. some hack..? */
2263 		/* Move the player onto the trap */
2264 		move_player(p_ptr, dir, FALSE);
2265 	}
2266 
2267 	/* Result */
2268 	return (more);
2269 }
2270 
2271 
2272 /*
2273  * Disarms a trap, or a chest
2274  */
do_cmd_disarm(player_type * p_ptr,int dir)2275 void do_cmd_disarm(player_type *p_ptr, int dir)
2276 {
2277 	int Depth = p_ptr->dun_depth;
2278 
2279 	cave_type		*c_ptr;
2280 	object_type		*o_ptr;
2281 
2282 	int y, x;
2283 
2284 	s16b o_idx;
2285 
2286 	bool more = FALSE;
2287 
2288 	/* Check preventive inscription '^D' */
2289 	__trap(p_ptr, CPI(p_ptr, 'D'));
2290 
2291 #if 0
2292 	/* Easy Disarm */
2293 	if (p_ptr->easy_open)
2294 	{
2295 		int num_traps, num_chests;
2296 
2297 		/* Count visible traps */
2298 		num_traps = count_feats(&y, &x, is_trap, TRUE);
2299 
2300 		/* Count chests (trapped) */
2301 		num_chests = count_chests(&y, &x, TRUE);
2302 
2303 		/* See if only one target */
2304 		if (num_traps || num_chests)
2305 		{
2306 			if (num_traps + num_chests <= 1)
2307 				p_ptr->command_dir = motion_dir(p_ptr->py, p_ptr->px, y, x);
2308 		}
2309 	}
2310 
2311 	/* Get a direction (or abort) */
2312 	if (!get_rep_dir(&dir)) return;
2313 #endif
2314 	if (!VALID_DIR(dir)) return;
2315 
2316 	/* Get location */
2317 	y = p_ptr->py + ddy[dir];
2318 	x = p_ptr->px + ddx[dir];
2319 
2320 	/* Get grid and contents */
2321 	c_ptr = &cave[Depth][y][x];
2322 
2323 	/* Access the item */
2324 	o_ptr = &o_list[c_ptr->o_idx];
2325 
2326 	/* Check for chests */
2327 	o_idx = (o_ptr->tval == TV_CHEST ? c_ptr->o_idx : 0);
2328 
2329 
2330 	/* Verify legality */
2331 	if (!o_idx && !do_cmd_disarm_test(p_ptr, y, x)) return;
2332 
2333 
2334 	/* Take a turn */
2335 	p_ptr->energy -= level_speed(p_ptr->dun_depth);
2336 
2337 	/* Apply confusion */
2338 	if (confuse_dir((bool)p_ptr->confused, &dir))
2339 	{
2340 		/* Get location */
2341 		y = p_ptr->py + ddy[dir];
2342 		x = p_ptr->px + ddx[dir];
2343 
2344 		/* Get grid and contents */
2345 		c_ptr = &cave[Depth][y][x];
2346 
2347 		/* Access the item */
2348 		o_ptr = &o_list[c_ptr->o_idx];
2349 
2350 		/* Check for chests */
2351 		o_idx = (o_ptr->tval == TV_CHEST ? c_ptr->o_idx : 0);
2352 	}
2353 
2354 
2355 	/* Allow repeated command */
2356 	if (p_ptr->command_arg)
2357 	{
2358 		/* Set repeat count */
2359 		/* p_ptr->command_rep = p_ptr->command_arg - 1; */
2360 
2361 		/* Redraw the state */
2362 		p_ptr->redraw |= (PR_STATE);
2363 
2364 		/* Cancel the arg */
2365 		p_ptr->command_arg = 0;
2366 	}
2367 
2368 	/* Monster */
2369 	if (c_ptr->m_idx > 0)
2370 	{
2371 		/* Message */
2372 		msg_print(p_ptr, "There is a monster in the way!");
2373 
2374 		/* Attack */
2375 		py_attack(p_ptr, y, x);
2376 	}
2377 
2378 	/* Player in the way */
2379 	else if (c_ptr->m_idx < 0)
2380 	{
2381 		/* Message */
2382 		msg_print(p_ptr, "There is a player in the way!");
2383 	}
2384 
2385 	/* Chest */
2386 	else if (o_idx)
2387 	{
2388 		/* Disarm the chest */
2389 		more = do_cmd_disarm_chest(p_ptr, y, x, o_idx);
2390 	}
2391 
2392 	/* Disarm trap */
2393 	else
2394 	{
2395 		/* Disarm the trap */
2396 		more = do_cmd_disarm_aux(p_ptr, y, x, dir);
2397 	}
2398 
2399 	/* Cancel repeat unless told not to */
2400 	if (!more) disturb(p_ptr, 0, 0);
2401 }
2402 
2403 /*
2404  * Determine if a given grid may be "bashed"
2405  */
do_cmd_bash_test(player_type * p_ptr,int y,int x)2406 static bool do_cmd_bash_test(player_type *p_ptr, int y, int x)
2407 {
2408 	int Depth = p_ptr->dun_depth;
2409 
2410 	cave_type		*c_ptr;
2411 
2412 
2413 	/* Ghosts cannot bash */
2414 	if ( (p_ptr->ghost || p_ptr->fruit_bat) && !(p_ptr->dm_flags & DM_GHOST_HANDS) )
2415 	{
2416 		/* Message */
2417 		msg_print(p_ptr, "You cannot bash things!");
2418 
2419 		return (FALSE);
2420 	}
2421 
2422 	/* Get grid and contents */
2423 	c_ptr = &cave[Depth][y][x];
2424 
2425 	/* Must have knowledge */
2426 	if (!(p_ptr->cave_flag[y][x] & (CAVE_MARK)))
2427 	{
2428 		/* Message */
2429 		msg_print(p_ptr, "You see nothing there.");
2430 
2431 		/* Nope */
2432 		return (FALSE);
2433 	}
2434 
2435 	/* Require a door */
2436 	if (!((c_ptr->feat >= FEAT_DOOR_HEAD) &&
2437 	      (c_ptr->feat <= FEAT_DOOR_TAIL)))
2438 	{
2439 		/* Message */
2440 		msg_print(p_ptr, "You see nothing there to bash.");
2441 
2442 		/* Nope */
2443 		return (FALSE);
2444 	}
2445 
2446 	/* Okay */
2447 	return (TRUE);
2448 }
2449 
2450 
2451 /*
2452  * Perform the basic "bash" command
2453  *
2454  * Assume there is no monster blocking the destination
2455  *
2456  * Returns TRUE if repeated commands may continue
2457  */
do_cmd_bash_aux(player_type * p_ptr,int y,int x)2458 static bool do_cmd_bash_aux(player_type *p_ptr, int y, int x)
2459 {
2460 	int Depth = p_ptr->dun_depth;
2461 
2462 	cave_type		*c_ptr;
2463 
2464 	int bash, temp;
2465 
2466 	bool more = FALSE;
2467 
2468 
2469 	/* Verify legality */
2470 	if (!do_cmd_bash_test(p_ptr, y, x)) return (FALSE);
2471 
2472 	/* Get grid and contents */
2473 	c_ptr = &cave[Depth][y][x];
2474 
2475 	/* Message */
2476 	msg_print(p_ptr, "You smash into the door!");
2477 
2478 	/* Hack -- Bash power based on strength */
2479 	/* (Ranges from 3 to 20 to 100 to 200) */
2480 	bash = adj_str_blow[p_ptr->stat_ind[A_STR]];
2481 
2482 	/* Extract door power */
2483 	temp = ((c_ptr->feat - FEAT_DOOR_HEAD) & 0x07);
2484 
2485 	/* Compare bash power to door power XXX XXX XXX */
2486 	temp = (bash - (temp * 10));
2487 
2488 	/* Hack -- always have a chance */
2489 	if (temp < 1) temp = 1;
2490 
2491 	/* Hack -- attempt to bash down the door */
2492 	if (randint0(100) < temp)
2493 	{
2494 		/* Message */
2495 		msg_print_aux(p_ptr, "The door crashes open!", MSG_OPENDOOR);
2496 		sound(p_ptr, MSG_OPENDOOR);
2497 
2498 		/* Break down the door */
2499 		if (randint0(100) < 50)
2500 		{
2501 			c_ptr->feat = FEAT_BROKEN;
2502 		}
2503 
2504 		/* Open the door */
2505 		else
2506 		{
2507 			c_ptr->feat = FEAT_OPEN;
2508 		}
2509 
2510 		/* Notice */
2511 		note_spot_depth(Depth, y, x);
2512 
2513 		/* Redraw */
2514 		everyone_lite_spot(Depth, y, x);
2515 #if 0
2516 		/* Hack -- Fall through the door */
2517 		move_player(p_ptr, dir, FALSE);
2518 #endif
2519 		/* Update some things */
2520 		p_ptr->update |= (PU_VIEW | PU_LITE);
2521 		p_ptr->update |= (PU_DISTANCE);
2522 	}
2523 
2524 	/* Saving throw against stun */
2525 	else if (randint0(100) < adj_dex_safe[p_ptr->stat_ind[A_DEX]] +
2526 	         p_ptr->lev)
2527 	{
2528 		/* Message */
2529 		msg_print(p_ptr, "The door holds firm.");
2530 
2531 		/* Allow repeated bashing */
2532 		more = TRUE;
2533 	}
2534 
2535 	/* High dexterity yields coolness */
2536 	else
2537 	{
2538 		/* Message */
2539 		msg_print(p_ptr, "You are off-balance.");
2540 
2541 		/* Hack -- Lose balance ala paralysis */
2542 		(void)set_paralyzed(p_ptr, p_ptr->paralyzed + 2 + randint0(2));
2543 	}
2544 
2545 	/* Result */
2546 	return (more);
2547 }
2548 
2549 
2550 /*
2551  * Bash open a door, success based on character strength
2552  *
2553  * For a closed door, pval is positive if locked; negative if stuck.
2554  *
2555  * For an open door, pval is positive for a broken door.
2556  *
2557  * A closed door can be opened - harder if locked. Any door might be
2558  * bashed open (and thereby broken). Bashing a door is (potentially)
2559  * faster! You move into the door way. To open a stuck door, it must
2560  * be bashed. A closed door can be jammed (see do_cmd_spike()).
2561  *
2562  * Creatures can also open or bash doors, see elsewhere.
2563  */
do_cmd_bash(player_type * p_ptr,int dir)2564 void do_cmd_bash(player_type *p_ptr, int dir)
2565 {
2566 	int Depth = p_ptr->dun_depth;
2567 
2568 	cave_type		*c_ptr;
2569 
2570 	int y, x;
2571 
2572 	/* Check preventive inscription '^B' */
2573 	__trap(p_ptr, CPI(p_ptr, 'B'));
2574 
2575 	/* Get a direction (or abort) */
2576 	/* if (!get_rep_dir(&dir)) return; */
2577 	if (!VALID_DIR(dir)) return;
2578 
2579 	/* Get location */
2580 	y = p_ptr->py + ddy[dir];
2581 	x = p_ptr->px + ddx[dir];
2582 
2583 	/* Verify legality */
2584 	if (!do_cmd_bash_test(p_ptr, y, x)) return;
2585 
2586 
2587 	/* Take a turn */
2588 	p_ptr->energy -= level_speed(p_ptr->dun_depth);
2589 
2590 	/* Apply confusion */
2591 	if (confuse_dir((bool)p_ptr->confused, &dir))
2592 	{
2593 		/* Get location */
2594 		y = p_ptr->py + ddy[dir];
2595 		x = p_ptr->px + ddx[dir];
2596 	}
2597 
2598 	/* Get grid */
2599 	c_ptr = &cave[Depth][y][x];
2600 
2601 	/* Allow repeated command */
2602 	if (p_ptr->command_arg)
2603 	{
2604 		/* Set repeat count */
2605 		/*p_ptr->command_rep = p_ptr->command_arg - 1;*/
2606 
2607 		/* Redraw the state */
2608 		p_ptr->redraw |= (PR_STATE);
2609 
2610 		/* Cancel the arg */
2611 		p_ptr->command_arg = 0;
2612 	}
2613 
2614 	/* Monster */
2615 	if (c_ptr->m_idx > 0)
2616 	{
2617 		/* Message */
2618 		msg_print(p_ptr, "There is a monster in the way!");
2619 
2620 		/* Attack */
2621 		py_attack(p_ptr, y, x);
2622 	}
2623 
2624 	/* Player in the way */
2625 	else if (c_ptr->m_idx < 0)
2626 	{
2627 		/* Message */
2628 		msg_print(p_ptr, "There is a player in the way!");
2629 	}
2630 
2631 	/* Door */
2632 	else
2633 	{
2634 		/* Bash the door */
2635 		if (!do_cmd_bash_aux(p_ptr, y, x))
2636 		{
2637 			/* Cancel repeat */
2638 			disturb(p_ptr, 0, 0);
2639 		}
2640 	}
2641 }
2642 
2643 
2644 
2645 
2646 
2647 
2648 /*
2649  * Manipulate an adjacent grid in some way
2650  *
2651  * Attack monsters, tunnel through walls, disarm traps, open doors.
2652  *
2653  * <s>This command must always take energy, to prevent free detection
2654  * of invisible monsters.</s>
2655  * REVISED FOR MAngband-specific reasons: we don't care if someone
2656  * detects a monster by tunneling into it, and treat "tunnel air" as an
2657  * error, which DOES NOT spend player's energy. This is a classic MAnghack,
2658  * updated to newer V306 realities.
2659  *
2660  * The "semantics" of this command must be chosen before the player
2661  * is confused, and it must be verified against the new grid.
2662  */
do_cmd_alter(player_type * p_ptr,int dir)2663 void do_cmd_alter(player_type *p_ptr, int dir)
2664 {
2665 	int Depth = p_ptr->dun_depth;
2666 	int y, x;
2667 
2668 	int feat;
2669 
2670 	bool more = FALSE;
2671 	bool spend = TRUE;
2672 
2673 	cave_type		*c_ptr;
2674 
2675 	/* Check preventive inscription '^+' */
2676 	__trap(p_ptr, CPI(p_ptr, '+'));
2677 
2678 	/* Get a direction */
2679 	if (!VALID_DIR(dir)) return;
2680 
2681 	/* Apply confusion */
2682 	confuse_dir((bool)p_ptr->confused, &dir);
2683 
2684 	/* Get location */
2685 	y = p_ptr->py + ddy[dir];
2686 	x = p_ptr->px + ddx[dir];
2687 
2688 	/* MEGA-HACK! DM HOOK! */
2689 	if (p_ptr->master_hook[1])
2690 		master_new_hook(p_ptr, 'a', y, x);
2691 
2692 	/* Get grid */
2693 	c_ptr = &cave[Depth][y][x];
2694 
2695 	/* Original feature */
2696 	feat = c_ptr->feat;
2697 
2698 	/* Must have knowledge to know feature XXX XXX */
2699 	if (!(p_ptr->cave_flag[y][x] & (CAVE_MARK))) feat = FEAT_NONE;
2700 
2701 	/* Allow repeated command */
2702 	if (p_ptr->command_arg)
2703 	{
2704 		/* Set repeat count */
2705 		/*p_ptr->command_rep = p_ptr->command_arg - 1;*/
2706 
2707 		/* Redraw the state */
2708 		p_ptr->redraw |= (PR_STATE);
2709 
2710 		/* Cancel the arg */
2711 		p_ptr->command_arg = 0;
2712 	}
2713 
2714 	/* Attack monsters */
2715 	if (c_ptr->m_idx > 0)
2716 	{
2717 		/* Attack */
2718 		py_attack(p_ptr, y, x);
2719 	}
2720 
2721 	/* MAngband-specific: Open closed House doors */
2722 	else if (feat >= FEAT_HOME_HEAD && feat <= FEAT_HOME_TAIL)
2723 	{
2724 		/* Open */
2725 		more = do_cmd_open_aux(p_ptr, y, x);
2726 	}
2727 
2728 	/* MAngband-specific: Open walls (House Creation) */
2729 	else if (feat == FEAT_PERM_EXTRA)
2730 	{
2731 		/* Open */
2732 		more = do_cmd_open_aux(p_ptr, y, x);
2733 	}
2734 
2735 	/* Tunnel through walls */
2736 	else if (feat >= FEAT_SECRET)
2737 	{
2738 		/* Tunnel */
2739 		more = do_cmd_tunnel_aux(p_ptr, y, x);
2740 	}
2741 #if 0
2742 	/* Bash jammed doors */
2743 	else if (feat >= FEAT_DOOR_HEAD + 0x08)
2744 	{
2745 		/* Bash */
2746 		more = do_cmd_bash_aux(p_ptr, y, x);
2747 	}
2748 #endif /* 0 */
2749 	/* Open closed doors */
2750 	else if (feat >= FEAT_DOOR_HEAD)
2751 	{
2752 		/* Open */
2753 		more = do_cmd_open_aux(p_ptr, y, x);
2754 	}
2755 
2756 	/* Disarm traps */
2757 	else if (feat >= FEAT_TRAP_HEAD)
2758 	{
2759 		/* Disarm */
2760 		more = do_cmd_disarm_aux(p_ptr, y, x, dir);
2761 	}
2762 #if 0
2763 	/* Close open doors */
2764 	else if (feat == FEAT_OPEN)
2765 	{
2766 		/* Close */
2767 		more = do_cmd_close_aux(y, x);
2768 	}
2769 #endif
2770 
2771 	/* Oops */
2772 	else
2773 	{
2774 		/* Oops */
2775 		msg_print(p_ptr, "You spin around.");
2776 		/* Do not spend energy. */
2777 		spend = FALSE;
2778 	}
2779 
2780 	if (spend)
2781 	{
2782 		/* Take a turn */
2783 		p_ptr->energy -= level_speed(p_ptr->dun_depth);
2784 	}
2785 
2786 	/* Cancel repetition unless we can continue */
2787 	if (!more) disturb(p_ptr, 0, 0);
2788 }
2789 
2790 
2791 
2792 /*
2793  * Find the index of some "spikes", if possible.
2794  *
2795  * XXX XXX XXX Let user choose a pile of spikes, perhaps?
2796  */
get_spike(player_type * p_ptr,int * ip)2797 static bool get_spike(player_type *p_ptr, int *ip)
2798 {
2799 	int i;
2800 
2801 	/* Check every item in the pack */
2802 	for (i = 0; i < INVEN_PACK; i++)
2803 	{
2804 		object_type *o_ptr = &(p_ptr->inventory[i]);
2805 
2806 		/* Check the "tval" code */
2807 		if (o_ptr->tval == TV_SPIKE)
2808 		{
2809 			/* Save the spike index */
2810 			(*ip) = i;
2811 
2812 			/* Success */
2813 			return (TRUE);
2814 		}
2815 	}
2816 
2817 	/* Oops */
2818 	return (FALSE);
2819 }
2820 
2821 
2822 /*
2823  * Jam a closed door with a spike
2824  *
2825  * This command may NOT be repeated
2826  */
do_cmd_spike(player_type * p_ptr,int dir)2827 void do_cmd_spike(player_type *p_ptr, int dir)
2828 {
2829 	int Depth = p_ptr->dun_depth;
2830 
2831 	int                  y, x, item;
2832 
2833 	cave_type		*c_ptr;
2834 
2835 	/* Check preventive inscription '^j' */
2836 	__trap(p_ptr, CPI(p_ptr, 'j'));
2837 
2838 	/* Ghosts cannot spike */
2839 	if ( (p_ptr->ghost || p_ptr->fruit_bat) && !(p_ptr->dm_flags & DM_GHOST_HANDS) )
2840 	{
2841 		/* Message */
2842 		msg_print(p_ptr, "You cannot spike doors!");
2843 
2844 		return;
2845 	}
2846 
2847 	/* Get a "repeated" direction */
2848 	if (VALID_DIR(dir))
2849 	{
2850 		/* Get location */
2851 		y = p_ptr->py + ddy[dir];
2852 		x = p_ptr->px + ddx[dir];
2853 
2854 		/* Get grid and contents */
2855 		c_ptr = &cave[Depth][y][x];
2856 
2857 		/* Require closed door */
2858 		if (!((c_ptr->feat >= FEAT_DOOR_HEAD) &&
2859 		      (c_ptr->feat <= FEAT_DOOR_TAIL)))
2860 		{
2861 			/* Message */
2862 			msg_print(p_ptr, "You see nothing there to spike.");
2863 		}
2864 
2865 		/* Get a spike */
2866 		else if (!get_spike(p_ptr, &item))
2867 		{
2868 			/* Message */
2869 			msg_print(p_ptr, "You have no spikes!");
2870 		}
2871 
2872 		/* Is a monster in the way? */
2873 		else if (c_ptr->m_idx > 0)
2874 		{
2875 			/* Take a turn */
2876 			p_ptr->energy -= level_speed(p_ptr->dun_depth);
2877 
2878 			/* Message */
2879 			msg_print(p_ptr, "There is a monster in the way!");
2880 
2881 			/* Attack */
2882 			py_attack(p_ptr, y, x);
2883 		}
2884 
2885 		/* Go for it */
2886 		else
2887 		{
2888 			/* Take a turn */
2889 			p_ptr->energy -= level_speed(p_ptr->dun_depth);
2890 
2891 			/* Successful jamming */
2892 			msg_print(p_ptr, "You jam the door with a spike.");
2893 
2894 			/* Convert "locked" to "stuck" XXX XXX XXX */
2895 			if (c_ptr->feat < FEAT_DOOR_HEAD + 0x08) c_ptr->feat += 0x08;
2896 
2897 			/* Add one spike to the door */
2898 			if (c_ptr->feat < FEAT_DOOR_TAIL) c_ptr->feat++;
2899 
2900 			/* Use up, and describe, a single spike, from the bottom */
2901 			inven_item_increase(p_ptr, item, -1);
2902 			inven_item_describe(p_ptr, item);
2903 			inven_item_optimize(p_ptr, item);
2904 		}
2905 	}
2906 }
2907 
2908 /*
2909  * Clicked somewhere on the dungeon.
2910  *
2911  * "mod" can contain any MCURSOR_XXX flag, except for
2912  *  MCURSOR_EMB and MCURSOR_META (so buttons 1, 2, 3 and
2913  *  modifiers CTRL, ALT, SHIFT).
2914  */
do_cmd_mouseclick(player_type * p_ptr,int mod,int y,int x)2915 void do_cmd_mouseclick(player_type *p_ptr, int mod, int y, int x)
2916 {
2917 	/* Right now, we only support 1 mouse button */
2918 	if (!(mod & MCURSOR_LMB)) return;
2919 
2920 	y = y + p_ptr->panel_row_min;
2921 	x = x + p_ptr->panel_col_min;
2922 
2923 	if (x < p_ptr->panel_col_min) x = p_ptr->panel_col_min;
2924 	if (y < p_ptr->panel_row_min) y = p_ptr->panel_row_min;
2925 	if (x > p_ptr->panel_col_max) x = p_ptr->panel_col_max;
2926 	if (y > p_ptr->panel_row_max) y = p_ptr->panel_row_max;
2927 
2928 	/* Hack -- execute '_' ? */
2929 	if ((mod & MCURSOR_LMB) && (mod & MCURSOR_SHFT))
2930 	{
2931 		/* Grid offset is 0 (standing on) */
2932 		if (p_ptr->px == x && p_ptr->py == y)
2933 		{
2934 			do_cmd_enterfeat(p_ptr);
2935 		}
2936 		return;
2937 	}
2938 
2939 	/* Hack -- execute alter? */
2940 	if ((mod & MCURSOR_LMB) && (mod & MCURSOR_KTRL))
2941 	{
2942 		/* Grid is nearby */
2943 		if (ABS(p_ptr->px - x) <= 1 && ABS(p_ptr->py - y) <= 1)
2944 		{
2945 			int dir = motion_dir(p_ptr->py, p_ptr->px, y, x);
2946 			do_cmd_alter(p_ptr, dir);
2947 		}
2948 		return;
2949 	}
2950 
2951 	do_cmd_pathfind(p_ptr, y, x);
2952 }
2953 
2954 
2955 /*
2956  * Support code for the "Walk" and "Jump" commands
2957  */
do_cmd_walk(player_type * p_ptr,int dir,int pickup)2958 void do_cmd_walk(player_type *p_ptr, int dir, int pickup)
2959 {
2960 	cave_type *c_ptr;
2961 
2962 	bool more = FALSE;
2963 
2964 	/* Check preventive inscription '^;' */
2965 	__trap(p_ptr, CPI(p_ptr, ';'));
2966 
2967 	/* Make sure he hasn't just switched levels */
2968 	if (p_ptr->new_level_flag) return;
2969 
2970 	/* Allow repeated command */
2971 	if (p_ptr->command_arg)
2972 	{
2973 		/* Set repeat count */
2974 		/*command_rep = command_arg - 1;*/
2975 
2976 		/* Redraw the state */
2977 		p_ptr->redraw |= (PR_STATE);
2978 
2979 		/* Cancel the arg */
2980 		p_ptr->command_arg = 0;
2981 	}
2982 
2983 	/* Get a "repeated" direction */
2984 	if (VALID_DIR(dir))
2985 	{
2986 		/* Hack -- handle confusion */
2987 		if (p_ptr->confused)
2988 		{
2989 			dir = 5;
2990 
2991 			/* Prevent walking nowhere */
2992 			while (dir == 5)
2993 				dir = ddd[randint0(8)];
2994 		}
2995 
2996 		/* Handle the "easy_alter" option */
2997 		if (option_p(p_ptr,EASY_ALTER))
2998 		{
2999 			/* Get requested grid */
3000 			c_ptr = &cave[p_ptr->dun_depth][p_ptr->py+ddy[dir]][p_ptr->px+ddx[dir]];
3001 
3002 			if ((p_ptr->cave_flag[p_ptr->py+ddy[dir]][p_ptr->px+ddx[dir]] & (CAVE_MARK)) &&
3003 				(((c_ptr->feat >= FEAT_TRAP_HEAD) &&
3004 			      (c_ptr->feat <= FEAT_DOOR_TAIL)) ||
3005 			    ((c_ptr->feat >= FEAT_HOME_HEAD) &&
3006 			      (c_ptr->feat <= FEAT_HOME_TAIL))))
3007 			{
3008 				do_cmd_alter(p_ptr, dir);
3009 				return;
3010 			}
3011 		}
3012 
3013 		/* Handle the "bump_open" option */
3014 		/* Hack -- Same as "easy_alter", but ignores traps */
3015 		if (option_p(p_ptr,BUMP_OPEN))
3016 		{
3017 			/* Get requested grid */
3018 			c_ptr = &cave[p_ptr->dun_depth][p_ptr->py+ddy[dir]][p_ptr->px+ddx[dir]];
3019 
3020 			if ((p_ptr->cave_flag[p_ptr->py+ddy[dir]][p_ptr->px+ddx[dir]] & (CAVE_MARK)) &&
3021 			    (((c_ptr->feat >= FEAT_DOOR_HEAD) &&
3022 			      (c_ptr->feat <= FEAT_DOOR_TAIL)) ||
3023 			    ((c_ptr->feat >= FEAT_HOME_HEAD) &&
3024 			      (c_ptr->feat <= FEAT_HOME_TAIL))))
3025 			{
3026 				do_cmd_alter(p_ptr, dir);
3027 				return;
3028 			}
3029 		}
3030 
3031 		/* Actually move the character */
3032 		move_player(p_ptr, dir, pickup);
3033 
3034 		/* Hack -- don't spend energy if player attacked someone */
3035 		/* Because we have already spent an appropriate amount elsewhere */
3036 		if (!p_ptr->dealt_blows) {
3037 
3038 		/* Take a turn */
3039 		p_ptr->energy -= level_speed(p_ptr->dun_depth);
3040 
3041 		}/* End Hack */
3042 
3043 		/* Allow more walking */
3044 		more = TRUE;
3045 	}
3046 
3047 	/* Cancel repeat unless we may continue */
3048 	if (!more) disturb(p_ptr, 0, 0);
3049 }
3050 
3051 
3052 
3053 /*
3054  * Start running.
3055  */
do_cmd_run(player_type * p_ptr,int dir)3056 int do_cmd_run(player_type *p_ptr, int dir)
3057 {
3058 	cave_type *c_ptr;
3059 
3060 	/* Check preventive inscription '^.' */
3061 	if (CPI(p_ptr, '.')) { msg_print(p_ptr, "The item's inscription prevents it."); return 0; }
3062 
3063 	/* Classic MAnghack #3. */
3064 	/* Treat this as a walk request
3065 	 * -- instead of disallowing running when confused */
3066 	if (p_ptr->confused)
3067 	{
3068 		/* BUT NOT IN TOWN ... */
3069 		if (p_ptr->dun_depth)
3070 		{
3071 			do_cmd_walk(p_ptr, dir, option_p(p_ptr, ALWAYS_PICKUP));
3072 			return 1;
3073 		}
3074 	}
3075 
3076 	if (p_ptr->confused)
3077 	{
3078 		msg_print(p_ptr, "You are too confused!");
3079 		return 0;
3080 	}
3081 
3082 	/* Ignore if we are already running in this direction */
3083 	if (p_ptr->running && (dir == p_ptr->find_current) ) return 1;
3084 
3085 	/* Get a "repeated" direction */
3086 	if (VALID_DIR(dir))
3087 	{
3088 		/* Make sure we have an empty space to run into */
3089 		if (see_wall(p_ptr, dir, p_ptr->py, p_ptr->px) && p_ptr->energy >= level_speed(p_ptr->dun_depth))
3090 		{
3091 			/* Handle the "easy_alter" option */
3092 			if (option_p(p_ptr,EASY_ALTER))
3093 			{
3094 				/* Get requested grid */
3095 				c_ptr = &cave[p_ptr->dun_depth][p_ptr->py+ddy[dir]][p_ptr->px+ddx[dir]];
3096 
3097 				if ((p_ptr->cave_flag[p_ptr->py+ddy[dir]][p_ptr->px+ddx[dir]] & (CAVE_MARK)) &&
3098 					(((c_ptr->feat >= FEAT_TRAP_HEAD) &&
3099 				      (c_ptr->feat <= FEAT_DOOR_TAIL)) ||
3100 				    ((c_ptr->feat >= FEAT_HOME_HEAD) &&
3101 				      (c_ptr->feat <= FEAT_HOME_TAIL))))
3102 				{
3103 					/* Check if we have enough energy to alter grid */
3104 					if (p_ptr->energy >= level_speed(p_ptr->dun_depth))
3105 					{
3106 						/* If so, do it. */
3107 						do_cmd_alter(p_ptr, dir);
3108 					}
3109 					return 1;
3110 				}
3111 			}
3112 
3113 			/* Handle the "bump_open" option */
3114 			/* Hack -- same as "easy_alter", but ignores traps */
3115 			if (option_p(p_ptr,BUMP_OPEN))
3116 			{
3117 				/* Get requested grid */
3118 				c_ptr = &cave[p_ptr->dun_depth][p_ptr->py+ddy[dir]][p_ptr->px+ddx[dir]];
3119 
3120 				if ((p_ptr->cave_flag[p_ptr->py+ddy[dir]][p_ptr->px+ddx[dir]] & (CAVE_MARK)) &&
3121 				    (((c_ptr->feat >= FEAT_DOOR_HEAD) &&
3122 				      (c_ptr->feat <= FEAT_DOOR_TAIL)) ||
3123 				    ((c_ptr->feat >= FEAT_HOME_HEAD) &&
3124 				      (c_ptr->feat <= FEAT_HOME_TAIL))))
3125 				{
3126 					/* Check if we have enough energy to alter grid */
3127 					if (p_ptr->energy >= level_speed(p_ptr->dun_depth))
3128 					{
3129 						/* If so, do it. */
3130 						do_cmd_alter(p_ptr, dir);
3131 					}
3132 					return 1;
3133 				}
3134 			}
3135 
3136 			/* Message */
3137 			msg_print(p_ptr, "You cannot run in that direction.");
3138 
3139 			/* Disturb */
3140 			disturb(p_ptr, 0, 0);
3141 
3142 			return 1;
3143 		}
3144 
3145 		/* Initialise running */
3146 		p_ptr->run_request = dir;
3147 		p_ptr->running = FALSE;
3148 		p_ptr->ran_tiles = 0;
3149 	}
3150 	return 1;
3151 }
3152 
3153 
3154 
3155 /*
3156  * Stay still.  Search.  Enter stores.
3157  * Pick up treasure if "pickup" is true.
3158  */
do_cmd_hold_or_stay(player_type * p_ptr,int pickup,int take_stairs)3159 void do_cmd_hold_or_stay(player_type *p_ptr, int pickup, int take_stairs)
3160 {
3161 	int Depth = p_ptr->dun_depth;
3162 	cave_type *c_ptr;
3163 
3164 	if (p_ptr->new_level_flag) return;
3165 
3166 	c_ptr = &cave[Depth][p_ptr->py][p_ptr->px];
3167 
3168 
3169 	/* Allow repeated command */
3170 	if (p_ptr->command_arg)
3171 	{
3172 		/* Set repeat count */
3173 		/*command_rep = command_arg - 1;*/
3174 
3175 		/* Redraw the state */
3176 		p_ptr->redraw |= (PR_STATE);
3177 
3178 		/* Cancel the arg */
3179 		p_ptr->command_arg = 0;
3180 	}
3181 
3182 
3183 /* We don't want any of this */
3184 #if 0
3185 	/* Take a turn */
3186 	p_ptr->energy -= level_speed(p_ptr->dun_depth);
3187 
3188 
3189 	/* Spontaneous Searching */
3190 	if ((p_ptr->skill_fos >= 50) || (0 == randint0(50 - p_ptr->skill_fos)))
3191 	{
3192 		search(p_ptr);
3193 	}
3194 
3195 	/* Continuous Searching */
3196 	if (p_ptr->searching)
3197 	{
3198 		search(p_ptr);
3199 	}
3200 #endif
3201 
3202 
3203 	/* Hack -- enter a store if we are on one */
3204 	if ((c_ptr->feat >= FEAT_SHOP_HEAD) &&
3205 	    (c_ptr->feat <= FEAT_SHOP_TAIL))
3206 	{
3207 		/* Disturb */
3208 		disturb(p_ptr, 0, 0);
3209 
3210 		/* Hack -- enter store */
3211 		/*command_new = '_';*/
3212 	}
3213 
3214 
3215 	/* Try to Pick up anything under us */
3216 	carry(p_ptr, pickup, 0);
3217 
3218 	/* Hack -- enter stairs if we are on one */
3219 	if (take_stairs)
3220 	{
3221 		if (c_ptr->feat == FEAT_MORE)
3222 		{
3223 			do_cmd_go_down(p_ptr);
3224 		}
3225 		if (c_ptr->feat == FEAT_LESS)
3226 		{
3227 			do_cmd_go_up(p_ptr);
3228 		}
3229 	}
3230 }
3231 
3232 /*
3233  * Hold still (always pickup and enter stairs)
3234  */
do_cmd_enterfeat(player_type * p_ptr)3235 void do_cmd_enterfeat(player_type *p_ptr)
3236 {
3237 	/* Hold still (always pickup, enter stairs) */
3238 	do_cmd_hold_or_stay(p_ptr, TRUE, TRUE);
3239 }
3240 
3241 /*
3242  * Hold still (always pickup)
3243  */
do_cmd_hold(player_type * p_ptr)3244 void do_cmd_hold(player_type *p_ptr)
3245 {
3246 	/* Hold still (always pickup) */
3247 	do_cmd_hold_or_stay(p_ptr, TRUE, FALSE);
3248 }
3249 
3250 /*
3251  * Stay still (usually do not pickup)
3252  */
do_cmd_stay(player_type * p_ptr)3253 void do_cmd_stay(player_type *p_ptr)
3254 {
3255 	/* Stay still (usually do not pickup) */
3256 	do_cmd_hold_or_stay(p_ptr, !option_p(p_ptr,ALWAYS_PICKUP), FALSE);
3257 }
3258 
3259 
3260 
3261 /*
3262  * Toggle rest mode.
3263  */
do_cmd_toggle_rest(player_type * p_ptr)3264 void do_cmd_toggle_rest(player_type *p_ptr)
3265 {
3266 	/* Set flag */
3267 	p_ptr->resting = TRUE;
3268 
3269 	/* Make sure we aren't running */
3270 	p_ptr->running = FALSE;
3271 
3272 	/* Take a lot of energy to enter "rest mode" */
3273 	p_ptr->energy -= (level_speed(p_ptr->dun_depth));
3274 
3275 	/* Redraw */
3276 	p_ptr->redraw |= (PR_STATE);
3277 }
3278 
3279 /*
3280  * Resting allows a player to safely restore his hp	-RAK-
3281  */
3282 #if 0
3283 void do_cmd_rest(void)
3284 {
3285 	/* Prompt for time if needed */
3286 	if (p_ptr->command_arg <= 0)
3287 	{
3288 		cptr p = "Rest (0-9999, '*' for HP/SP, '&' as needed): ";
3289 
3290 		char out_val[80];
3291 
3292 		/* Default */
3293 		strcpy(out_val, "&");
3294 
3295 		/* Ask for duration */
3296 		if (!get_string(p, out_val, 4)) return;
3297 
3298 		/* Rest until done */
3299 		if (out_val[0] == '&')
3300 		{
3301 			p_ptr->command_arg = (-2);
3302 		}
3303 
3304 		/* Rest a lot */
3305 		else if (out_val[0] == '*')
3306 		{
3307 			p_ptr->command_arg = (-1);
3308 		}
3309 
3310 		/* Rest some */
3311 		else
3312 		{
3313 			p_ptr->command_arg = atoi(out_val);
3314 			if (p_ptr->command_arg <= 0) return;
3315 		}
3316 	}
3317 
3318 
3319 	/* Paranoia */
3320 	if (p_ptr->command_arg > 9999) p_ptr->command_arg = 9999;
3321 
3322 
3323 	/* Take a turn XXX XXX XXX (?) */
3324 	energy -= level_speed(p_ptr->dun_depth);
3325 
3326 	/* Save the rest code */
3327 	resting = p_ptr->command_arg;
3328 
3329 	/* Cancel searching */
3330 	p_ptr->searching = FALSE;
3331 
3332 	/* Recalculate bonuses */
3333 	p_ptr->update |= (PU_BONUS);
3334 
3335 	/* Redraw the state */
3336 	p_ptr->redraw |= (PR_STATE);
3337 
3338 	/* Handle stuff */
3339 	handle_stuff();
3340 
3341 	/* Refresh */
3342 	Term_fresh();
3343 }
3344 #endif
3345 
3346 
3347 /*
3348  * Start running with pathfinder.
3349  *
3350  * Note that running while confused is not allowed.
3351  */
do_cmd_pathfind(player_type * p_ptr,int y,int x)3352 void do_cmd_pathfind(player_type *p_ptr, int y, int x)
3353 {
3354 	/* Hack -- translate nearby grid into walk request */
3355 	if (ABS(p_ptr->px - x) <= 1 && ABS(p_ptr->py - y) <= 1)
3356 	{
3357 		int dir = motion_dir(p_ptr->py, p_ptr->px, y, x);
3358 		do_cmd_walk(p_ptr, dir, option_p(p_ptr, ALWAYS_PICKUP));
3359 		return;
3360 	}
3361 
3362 	/* Hack XXX XXX XXX */
3363 	if (p_ptr->confused)
3364 	{
3365 		/* TODO: Maybe convert to walk request? */
3366 		msg_print(p_ptr, "You are too confused!");
3367 		return;
3368 	}
3369 
3370 	if (findpath(p_ptr, y, x))
3371 	{
3372 		p_ptr->running_withpathfind = TRUE;
3373 		p_ptr->run_request = -1;
3374 #if 0 /* In MAngband, we just schedule for later */
3375 //		/* Calculate torch radius */
3376 //		p_ptr->update |= (PU_TORCH);
3377 //		run_step(p_ptr, 0);
3378 #endif
3379 	}
3380 }
3381 
3382 
3383 
3384 
3385 /*
3386  * Determines the odds of an object breaking when thrown at a monster
3387  *
3388  * Note that artifacts never break, see the "drop_near()" function.
3389  */
breakage_chance(object_type * o_ptr)3390 static int breakage_chance(object_type *o_ptr)
3391 {
3392 	/* Examine the item type */
3393 	switch (o_ptr->tval)
3394 	{
3395 		/* Always break */
3396 		case TV_FLASK:
3397 		case TV_POTION:
3398 		case TV_BOTTLE:
3399 		case TV_FOOD:
3400 		case TV_JUNK:
3401 		{
3402 			return (100);
3403 		}
3404 
3405 		/* Often break */
3406 		case TV_LITE:
3407 		case TV_SCROLL:
3408 		case TV_ARROW:
3409 		case TV_SKELETON:
3410 		{
3411 			return (50);
3412 		}
3413 
3414 		/* Sometimes break */
3415 		case TV_WAND:
3416 		case TV_SHOT:
3417 		case TV_BOLT:
3418 		case TV_SPIKE:
3419 		{
3420 			return (25);
3421 		}
3422 	}
3423 
3424 	/* Rarely break */
3425 	return (10);
3426 }
3427 
3428 
3429 /*
3430  * Fire an object from the pack or floor.
3431  *
3432  * You may only fire items that "match" your missile launcher.
3433  *
3434  * You must use slings + pebbles/shots, bows + arrows, xbows + bolts.
3435  *
3436  * See "calc_bonuses()" for more calculations and such.
3437  *
3438  * Note that "firing" a missile is MUCH better than "throwing" it.
3439  *
3440  * Note: "unseen" monsters are very hard to hit.
3441  *
3442  * Objects are more likely to break if they "attempt" to hit a monster.
3443  *
3444  * Rangers (with Bows) and Anyone (with "Extra Shots") get extra shots.
3445  *
3446  * The "extra shot" code works by decreasing the amount of energy
3447  * required to make each shot, spreading the shots out over time.
3448  *
3449  * Note that when firing missiles, the launcher multiplier is applied
3450  * after all the bonuses are added in, making multipliers very useful.
3451  *
3452  * Note that Bows of "Extra Might" get extra range and an extra bonus
3453  * for the damage multiplier.
3454  *
3455  * Note that Bows of "Extra Shots" give an extra shot.
3456  */
do_cmd_fire(player_type * p_ptr,int item,int dir)3457 void do_cmd_fire(player_type *p_ptr, int item, int dir)
3458 {
3459 	player_type *q_ptr;
3460 	int Depth = p_ptr->dun_depth;
3461 
3462 	int			i, j, y, x, ny, nx, ty, tx;
3463 	int			tdam, tdis, thits, tmul;
3464 	int			bonus, chance;
3465 	int			cur_dis, visible;
3466 
3467 	object_type         throw_obj;
3468 	object_type		*o_ptr;
3469 
3470 	object_type		*j_ptr;
3471 
3472 	bool		hit_body = FALSE;
3473 
3474 	int			missile_attr;
3475 	int			missile_char;
3476 
3477 	char		o_name[80];
3478 	bool		magic = FALSE;
3479 
3480 	/* Check preventive inscription '^f' */
3481 	__trap(p_ptr, CPI(p_ptr, 'f'));
3482 
3483 	/* Restrict ghosts */
3484 	if ( (p_ptr->ghost || p_ptr->fruit_bat) && !(p_ptr->dm_flags & DM_GHOST_HANDS) )
3485 	{
3486 		msg_print(p_ptr, "You cannot shoot!");
3487 		return;
3488 	}
3489 
3490 	/* Get the "bow" (if any) */
3491 	j_ptr = &(p_ptr->inventory[INVEN_BOW]);
3492 
3493 	/* Require a launcher */
3494 	if (!j_ptr->tval)
3495 	{
3496 		msg_print(p_ptr, "You have nothing to fire with.");
3497 		return;
3498 	}
3499 
3500 
3501 	/* Require proper missile */
3502 	item_tester_tval = p_ptr->tval_ammo;
3503 
3504 	if (!item_tester_tval)
3505 	{
3506 		msg_print(p_ptr, "You have nothing to fire.");
3507 		return;
3508 	}
3509 
3510 	/* Access the item (if in the pack) */
3511 	if (item >= 0)
3512 	{
3513 		o_ptr = &(p_ptr->inventory[item]);
3514 	}
3515 	else
3516 	{
3517 		item = -cave[p_ptr->dun_depth][p_ptr->py][p_ptr->px].o_idx;
3518 		o_ptr = &o_list[0 - item];
3519 	}
3520 
3521 	/* Check guard inscription '!f' */
3522 	__trap(p_ptr, CGI(o_ptr, 'f'));
3523 
3524 	if (o_ptr->tval != p_ptr->tval_ammo)
3525 	{
3526 		msg_print(p_ptr, "You cannot fire that!");
3527 		return;
3528 	}
3529 
3530 	if (!o_ptr->tval)
3531 	{
3532 		msg_print(p_ptr, "You cannot fire that!");
3533 		return;
3534 	}
3535 
3536 	/* Magic ammo */
3537 	if ((o_ptr->sval == SV_AMMO_MAGIC) || artifact_p(o_ptr))
3538 		magic = TRUE;
3539 
3540 	/* Get a direction (or cancel) */
3541 	p_ptr->command_dir = dir;
3542 	if (!get_aim_dir(p_ptr, &dir)) return;
3543 
3544 	/* Create a "local missile object" */
3545 	throw_obj = *o_ptr;
3546 	throw_obj.number = 1;
3547 
3548 	if (!magic)
3549 	{
3550 		/* Reduce and describe inventory */
3551 		if (item >= 0)
3552 		{
3553 			inven_item_increase(p_ptr, item, -1);
3554 			inven_item_describe(p_ptr, item);
3555 			inven_item_optimize(p_ptr, item);
3556 		}
3557 
3558 		/* Reduce and describe floor item */
3559 		else
3560 		{
3561 			floor_item_increase(0 - item, -1);
3562 			floor_item_optimize(0 - item);
3563 			floor_item_notify(p_ptr, 0 - item, TRUE);
3564 		}
3565 	}
3566 
3567 	/* Use the missile object */
3568 	o_ptr = &throw_obj;
3569 
3570 	/* Sound */
3571 	sound(p_ptr, MSG_SHOOT);
3572 
3573 	/* Describe the object */
3574 	object_desc(p_ptr, o_name, sizeof(o_name), o_ptr, FALSE, 3);
3575 
3576 	/* Find the color and symbol for the object for throwing */
3577 	missile_attr = object_attr_p(p_ptr, o_ptr);
3578 	missile_char = object_char_p(p_ptr, o_ptr);
3579 
3580 
3581 	/* Use the proper number of shots */
3582 	thits = p_ptr->num_fire;
3583 
3584 	/* Use a base distance */
3585 	tdis = 10;
3586 
3587 	/* Base damage from thrown object plus launcher bonus */
3588 	tdam = damroll(o_ptr->dd, o_ptr->ds) + o_ptr->to_d + j_ptr->to_d;
3589 
3590 	/* Actually "fire" the object */
3591 	bonus = (p_ptr->to_h + o_ptr->to_h + j_ptr->to_h);
3592 	chance = (p_ptr->skill_thb + (bonus * BTH_PLUS_ADJ));
3593 
3594 	/* Assume a base multiplier */
3595 	tmul = 1;
3596 
3597 	/* Analyze the launcher */
3598 	switch (j_ptr->sval)
3599 	{
3600 		/* Sling and ammo */
3601 		case SV_SLING:
3602 		{
3603 			tmul = 2;
3604 			break;
3605 		}
3606 
3607 		/* Short Bow and Arrow */
3608 		case SV_SHORT_BOW:
3609 		{
3610 			tmul = 2;
3611 			break;
3612 		}
3613 
3614 		/* Long Bow and Arrow */
3615 		case SV_LONG_BOW:
3616 		{
3617 			tmul = 3;
3618 			break;
3619 		}
3620 
3621 		/* Light Crossbow and Bolt */
3622 		case SV_LIGHT_XBOW:
3623 		{
3624 			tmul = 3;
3625 			break;
3626 		}
3627 
3628 		/* Heavy Crossbow and Bolt */
3629 		case SV_HEAVY_XBOW:
3630 		{
3631 			tmul = 4;
3632 			break;
3633 		}
3634 	}
3635 
3636 	/* Get extra "power" from "extra might" */
3637 	if (p_ptr->xtra_might) tmul++;
3638 
3639 	/* Boost the damage */
3640 	tdam *= tmul;
3641 
3642 	/* Base range */
3643 	tdis = 10 + 5 * tmul;
3644 
3645 
3646 	/* Take a (partial) turn */
3647 	p_ptr->energy -= (level_speed(p_ptr->dun_depth) / thits);
3648 
3649 
3650 	/* Start at the player */
3651 	y = p_ptr->py;
3652 	x = p_ptr->px;
3653 
3654 	/* Predict the "target" location */
3655 	tx = p_ptr->px + 99 * ddx[dir];
3656 	ty = p_ptr->py + 99 * ddy[dir];
3657 
3658 	/* Check for "target request" */
3659 	if ((dir == 5) && target_okay(p_ptr))
3660 	{
3661 		tx = p_ptr->target_col;
3662 		ty = p_ptr->target_row;
3663 	}
3664 
3665 
3666 	/* Hack -- Handle stuff */
3667 	handle_stuff(p_ptr);
3668 
3669 
3670 	/* Travel until stopped */
3671 	for (cur_dis = 0; cur_dis <= tdis; )
3672 	{
3673 		/* Hack -- Stop at the target */
3674 		if ((y == ty) && (x == tx)) break;
3675 
3676 		/* Calculate the new location (see "project()") */
3677 		ny = y;
3678 		nx = x;
3679 		mmove2(&ny, &nx, p_ptr->py, p_ptr->px, ty, tx);
3680 
3681 		/* Stopped by walls/doors */
3682 		if (!cave_floor_bold(Depth, ny, nx)) break;
3683 
3684 		/* Advance the distance */
3685 		cur_dis++;
3686 
3687 		/* Save the new location */
3688 		x = nx;
3689 		y = ny;
3690 
3691 		/* Save the old "player pointer" */
3692 		q_ptr = p_ptr;
3693 
3694 		/* Display it for each player */
3695 		for (i = 1; i <= NumPlayers; i++)
3696 		{
3697 			int dispx, dispy;
3698 
3699 			/* Use this player */
3700 			p_ptr = Players[i];
3701 
3702 			/* If he's not here, skip him */
3703 			if (p_ptr->dun_depth != Depth)
3704 				continue;
3705 
3706 			/* The player can see the (on screen) missile */
3707 			if (panel_contains(p_ptr, y, x) && player_can_see_bold(p_ptr, y, x))
3708 			{
3709 				/* Draw, Hilite, Fresh, Pause, Erase */
3710 				dispy = y - p_ptr->panel_row_prt;
3711 				dispx = x - p_ptr->panel_col_prt;
3712 
3713 				/* Remember the projectile */
3714 				//p_ptr->scr_info[dispy][dispx].c = missile_char;
3715 				//p_ptr->scr_info[dispy][dispx].a = missile_attr;
3716 
3717 				/* Tell the client */
3718 				//Stream_tile(i, p_ptr, dispy, dispx);
3719 
3720 				/* Tell the client */
3721 				(void)send_air_char(p_ptr, dispy, dispx, missile_attr, missile_char, cur_dis, 1);
3722 
3723 				/* Flush and wait */
3724 				//if (cur_dis % tmul) Send_flush(i);
3725 
3726 				/* Restore */
3727 				//lite_spot(i, y, x);
3728 			}
3729 
3730 			/* The player cannot see the missile */
3731 			else
3732 			{
3733 				/* Pause anyway, for consistancy */
3734 				/*Term_xtra(TERM_XTRA_DELAY, msec);*/
3735 			}
3736 		}
3737 
3738 		/* Restore the player pointer */
3739 		p_ptr = q_ptr;
3740 
3741 		/* Player here, hit him */
3742 		if (cave[Depth][y][x].m_idx < 0)
3743 		{
3744 			cave_type *c_ptr = &cave[Depth][y][x];
3745 
3746 			q_ptr = Players[0 - c_ptr->m_idx];
3747 
3748 			/* AD hack cntd -- "pass over" if players aren't hostile */
3749 			if (!pvp_okay(p_ptr, q_ptr, (p_ptr->target_who == c_ptr->m_idx ? 2 : 3) ))
3750 			{
3751 				continue;
3752 			}
3753 
3754 			/* Check the visibility */
3755 			visible = p_ptr->play_vis[0 - c_ptr->m_idx];
3756 
3757 			/* Note the collision */
3758 			hit_body = TRUE;
3759 
3760 			/* Did we hit it (penalize range) */
3761 			if (test_hit_fire(chance - cur_dis, q_ptr->ac + q_ptr->to_a, visible))
3762 			{
3763 				char pvp_name[80];
3764 
3765 				/* Get the name */
3766 				my_strcpy(pvp_name, q_ptr->name, 80);
3767 
3768 				/* Handle unseen player */
3769 				if (!visible)
3770 				{
3771 					/* Invisible player */
3772 					msg_format(p_ptr, "The %s finds a mark.", o_name);
3773 					sound(p_ptr, MSG_SHOOT_HIT);
3774 					msg_format(q_ptr, "You are hit by a %s!", o_name);
3775 				}
3776 
3777 				/* Handle visible player */
3778 				else
3779 				{
3780 					/* Messages */
3781 					msg_format(p_ptr, "The %s hits %s.", o_name, pvp_name);
3782 					sound(p_ptr, MSG_SHOOT_HIT);
3783 					msg_format(q_ptr, "%^s hits you with a %s.", p_ptr->name, o_name);
3784 
3785 					/* Track this player's health */
3786 					health_track(p_ptr, c_ptr->m_idx);
3787 				}
3788 
3789 				/* Apply special damage XXX XXX XXX */
3790 				tdam = tot_dam_aux_player(o_ptr, tdam, q_ptr);
3791 				tdam = critical_shot(p_ptr, o_ptr->weight, o_ptr->to_h, tdam);
3792 
3793 				/* No negative damage */
3794 				if (tdam < 0) tdam = 0;
3795 
3796 				/* XXX Reduce damage by 1/3 */
3797 				tdam = (tdam + 2) / 3;
3798 
3799 				/* Take damage */
3800 				take_hit(q_ptr, tdam, p_ptr->name);
3801 
3802 				/* Stop looking */
3803 				break;
3804 			}
3805 		}
3806 
3807 		/* Monster here, Try to hit it */
3808 		if (cave[Depth][y][x].m_idx > 0)
3809 		{
3810 			cave_type *c_ptr = &cave[Depth][y][x];
3811 
3812 			monster_type *m_ptr = &m_list[c_ptr->m_idx];
3813 			monster_race *r_ptr = &r_info[m_ptr->r_idx];
3814 
3815 			/* Check the visibility */
3816 			visible = p_ptr->mon_vis[c_ptr->m_idx];
3817 
3818 			/* Note the collision */
3819 			hit_body = TRUE;
3820 
3821 			/* Did we hit it (penalize range) */
3822 			if (test_hit_fire(chance - cur_dis, r_ptr->ac, visible))
3823 			{
3824 				bool fear = FALSE;
3825 
3826 				/* Assume a default death */
3827 				cptr note_dies = " dies.";
3828 
3829 				/* Some monsters get "destroyed" */
3830 				if ((r_ptr->flags3 & RF3_DEMON) ||
3831 				    (r_ptr->flags3 & RF3_UNDEAD) ||
3832 				    (r_ptr->flags2 & RF2_STUPID) ||
3833 				    (strchr("Evg", r_ptr->d_char)))
3834 				{
3835 					/* Special note at death */
3836 					note_dies = " is destroyed.";
3837 				}
3838 
3839 
3840 				/* Handle unseen monster */
3841 				if (!visible)
3842 				{
3843 					/* Invisible monster */
3844 					msg_format(p_ptr, "The %s finds a mark.", o_name);
3845 				}
3846 
3847 				/* Handle visible monster */
3848 				else
3849 				{
3850 					char m_name[80];
3851 
3852 					/* Get "the monster" or "it" */
3853 					monster_desc(p_ptr, m_name, c_ptr->m_idx, 0);
3854 
3855 					/* Message */
3856 					msg_format(p_ptr, "The %s hits %s.", o_name, m_name);
3857 
3858 					/* Hack -- Track this monster race */
3859 					if (visible) monster_race_track(p_ptr, m_ptr->r_idx);
3860 
3861 					/* Hack -- Track this monster */
3862 					if (visible) health_track(p_ptr, c_ptr->m_idx);
3863 				}
3864 
3865 				/* Apply special damage XXX XXX XXX */
3866 				tdam = tot_dam_aux(p_ptr, o_ptr, tdam, m_ptr, p_ptr->mon_vis[c_ptr->m_idx]);
3867 				tdam = critical_shot(p_ptr, o_ptr->weight, o_ptr->to_h, tdam);
3868 
3869 				/* No negative damage */
3870 				if (tdam < 0) tdam = 0;
3871 
3872 				/* Complex message */
3873 				if (is_dm_p(p_ptr))
3874 				{
3875 					msg_format(p_ptr, "You do %d (out of %d) damage.",
3876 					           tdam, m_ptr->hp);
3877 				}
3878 
3879 				/* Hit the monster, check for death */
3880 				if (mon_take_hit(p_ptr, c_ptr->m_idx, tdam, &fear, note_dies))
3881 				{
3882 					/* Dead monster */
3883 				}
3884 
3885 				/* No death */
3886 				else
3887 				{
3888 					/* Message */
3889 					message_pain(p_ptr, c_ptr->m_idx, tdam);
3890 
3891 					/* Take note */
3892 					if (fear && visible && !(r_ptr->flags2 & RF2_WANDERER))
3893 					{
3894 						char m_name[80];
3895 
3896 						/* Sound */
3897 						sound(p_ptr, MSG_FLEE);
3898 
3899 						/* Get the monster name (or "it") */
3900 						monster_desc(p_ptr, m_name, c_ptr->m_idx, 0);
3901 
3902 						/* Message */
3903 						msg_format(p_ptr, "%^s flees in terror!", m_name);
3904 					}
3905 				}
3906 
3907 				/* Stop looking */
3908 				break;
3909 			}
3910 		}
3911 	}
3912 
3913 	/* Chance of breakage (during attacks) */
3914 	j = (hit_body ? breakage_chance(o_ptr) : 0);
3915 
3916 	/* Drop (or break) near that location */
3917 	if (!magic) drop_near(o_ptr, j, Depth, y, x);
3918 }
3919 
3920 
3921 
3922 /*
3923  * Throw an object from the pack or floor.
3924  *
3925  * Note: "unseen" monsters are very hard to hit.
3926  *
3927  * Should throwing a weapon do full damage?  Should it allow the magic
3928  * to hit bonus of the weapon to have an effect?  Should it ever cause
3929  * the item to be destroyed?  Should it do any damage at all?
3930  */
do_cmd_throw(player_type * p_ptr,int item,int dir)3931 void do_cmd_throw(player_type *p_ptr, int item, int dir)
3932 {
3933 	player_type *q_ptr;
3934 	int Depth = p_ptr->dun_depth;
3935 
3936 	int			i, j, y, x, ny, nx, ty, tx;
3937 	int			chance, tdam, tdis;
3938 	int			mul, div;
3939 	int			cur_dis, visible;
3940 
3941 	object_type         throw_obj;
3942 	object_type		*o_ptr;
3943 
3944 	bool		hit_body = FALSE;
3945 
3946 	int			missile_attr;
3947 	int			missile_char;
3948 	byte			item_color;
3949 
3950 	char		o_name[80];
3951 
3952 	/* Check preventive inscription '^v' */
3953 	__trap(p_ptr, CPI(p_ptr, 'v'));
3954 
3955 	/*int			msec = delay_factor * delay_factor * delay_factor;*/
3956 
3957 	/* Restrict ghosts */
3958 	if ( ((p_ptr->ghost) || (p_ptr->fruit_bat && item >= 0)) && !(p_ptr->dm_flags & DM_GHOST_HANDS) )
3959 	{
3960 		msg_print(p_ptr, "You cannot throw things!");
3961 		return;
3962 	}
3963 
3964 	/* Access the item (if in the pack) */
3965 	if (item >= 0)
3966 	{
3967 		o_ptr = &(p_ptr->inventory[item]);
3968 	}
3969 	else
3970 	{
3971 		item = -cave[p_ptr->dun_depth][p_ptr->py][p_ptr->px].o_idx;
3972 		o_ptr = &o_list[0 - item];
3973 	}
3974 	if (!o_ptr->tval)
3975 	{
3976 		msg_print(p_ptr, "There is nothing there to throw");
3977 		return;
3978 	}
3979 
3980 	/* Check guard inscription '!v' */
3981 	__trap(p_ptr, CGI(o_ptr, 'v'));
3982 
3983 	/* Never throw artifacts */
3984 	if (true_artifact_p(o_ptr))
3985 	{
3986 		msg_print(p_ptr, "You can not throw this!");
3987 		return;
3988 	}
3989 
3990 	/* Get a direction (or cancel) */
3991 	p_ptr->command_dir = dir;
3992 	if (!get_aim_dir(p_ptr, &dir)) return;
3993 
3994 	/* Create a "local missile object" */
3995 	throw_obj = *o_ptr;
3996 	throw_obj.number = 1;
3997 
3998 	/* Distribute charges of wands, staves, or rods */
3999 	distribute_charges(o_ptr, &throw_obj, 1);
4000 
4001 	/* Reduce and describe inventory */
4002 	if (item >= 0)
4003 	{
4004 		inven_item_increase(p_ptr, item, -1);
4005 		inven_item_describe(p_ptr, item);
4006 		inven_item_optimize(p_ptr, item);
4007 	}
4008 
4009 	/* Reduce and describe floor item */
4010 	else
4011 	{
4012 		floor_item_increase(0 - item, -1);
4013 		floor_item_optimize(0 - item);
4014 		floor_item_notify(p_ptr, 0 - item, TRUE);
4015 	}
4016 
4017 	/* Use the local object */
4018 	o_ptr = &throw_obj;
4019 
4020 	/* Description */
4021 	object_desc(p_ptr, o_name, sizeof(o_name), o_ptr, FALSE, 3);
4022 
4023 	/* Find the color and symbol for the object for throwing */
4024 	missile_attr = object_attr_p(p_ptr, o_ptr);
4025 	missile_char = object_char_p(p_ptr, o_ptr);
4026 
4027 
4028 	/* Extract a "distance multiplier" */
4029 	mul = 10;
4030 
4031 	/* Enforce a minimum "weight" of one pound */
4032 	div = ((o_ptr->weight > 10) ? o_ptr->weight : 10);
4033 
4034 	/* Hack -- Distance -- Reward strength, penalize weight */
4035 	tdis = (adj_str_blow[p_ptr->stat_ind[A_STR]] + 20) * mul / div;
4036 
4037 	/* Max distance of 10 */
4038 	if (tdis > 10) tdis = 10;
4039 
4040 	/* Hack -- Base damage from thrown object */
4041 	tdam = damroll(o_ptr->dd, o_ptr->ds) + o_ptr->to_d;
4042 
4043 	/* Chance of hitting */
4044 	chance = (p_ptr->skill_tht + (p_ptr->to_h * BTH_PLUS_ADJ));
4045 
4046 
4047 	/* Take a turn */
4048 	p_ptr->energy -= level_speed(p_ptr->dun_depth);
4049 
4050 
4051 	/* Start at the player */
4052 	y = p_ptr->py;
4053 	x = p_ptr->px;
4054 
4055 	/* Predict the "target" location */
4056 	tx = p_ptr->px + 99 * ddx[dir];
4057 	ty = p_ptr->py + 99 * ddy[dir];
4058 
4059 	/* Check for "target request" */
4060 	if ((dir == 5) && target_okay(p_ptr))
4061 	{
4062 		tx = p_ptr->target_col;
4063 		ty = p_ptr->target_row;
4064 	}
4065 
4066 
4067 	/* Hack -- Handle stuff */
4068 	handle_stuff(p_ptr);
4069 
4070 
4071 	/* Travel until stopped */
4072 	for (cur_dis = 0; cur_dis <= tdis; )
4073 	{
4074 		/* Hack -- Stop at the target */
4075 		if ((y == ty) && (x == tx)) break;
4076 
4077 		/* Calculate the new location (see "project()") */
4078 		ny = y;
4079 		nx = x;
4080 		mmove2(&ny, &nx, p_ptr->py, p_ptr->px, ty, tx);
4081 
4082 		/* Stopped by walls/doors */
4083 		if (!cave_floor_bold(Depth, ny, nx))
4084 		{
4085 			/* Special case: potion VS house door */
4086 			if (o_ptr->tval == TV_POTION &&
4087 				 cave[Depth][ny][nx].feat >= FEAT_HOME_HEAD &&
4088 				 cave[Depth][ny][nx].feat <= FEAT_HOME_TAIL)
4089 			{
4090 				/* Break it */
4091 				hit_body = TRUE;
4092 
4093 				/* Potion color should ignore player's awareness and visuals */
4094 				item_color = k_info[o_ptr->k_idx].flavor ?
4095 						flavor_info[k_info[o_ptr->k_idx].flavor].d_attr :
4096 						k_info[o_ptr->k_idx].d_attr;
4097 
4098 				/* Find suitable color */
4099 				for (i = FEAT_HOME_HEAD; i < FEAT_HOME_TAIL + 1; i++)
4100 				{
4101 					if (f_info[i].d_attr == item_color || f_info[i].d_attr == color_opposite(item_color))
4102 					{
4103 						/* Pick a house */
4104 						if ((j = pick_house(Depth, ny, nx)) == -1) break;
4105 
4106 						/* Must own the house */
4107 						if (!house_owned_by(p_ptr, j)) break;
4108 
4109 						/* Chance to fail */
4110 						if (randint1(100) > p_ptr->sc) break;
4111 
4112 						/* Perform colorization */
4113 						houses[j].strength = i - FEAT_HOME_HEAD;
4114 						cave[Depth][ny][nx].feat = i;
4115 						everyone_lite_spot(Depth, ny, nx);
4116 
4117 						/* Done */
4118 						break;
4119 					}
4120 				}
4121 			}
4122 			break;
4123 		}
4124 
4125 		/* Advance the distance */
4126 		cur_dis++;
4127 
4128 		/* Save the new location */
4129 		x = nx;
4130 		y = ny;
4131 
4132 		/* Save the old "player pointer" */
4133 		q_ptr = p_ptr;
4134 
4135 		/* Display it for each player */
4136 		for (i = 1; i <= NumPlayers; i++)
4137 		{
4138 			int dispx, dispy;
4139 
4140 			/* Use this player */
4141 			p_ptr = Players[i];
4142 
4143 			/* If he's not here, skip him */
4144 			if (p_ptr->dun_depth != Depth)
4145 				continue;
4146 
4147 			/* The player can see the (on screen) missile */
4148 			if (panel_contains(p_ptr, y, x) && player_can_see_bold(p_ptr, y, x))
4149 			{
4150 				/* Draw, Hilite, Fresh, Pause, Erase */
4151 				dispy = y - p_ptr->panel_row_prt;
4152 				dispx = x - p_ptr->panel_col_prt;
4153 
4154 				/* Remember the projectile */
4155 				//p_ptr->scr_info[dispy][dispx].c = missile_char;
4156 				//p_ptr->scr_info[dispy][dispx].a = missile_attr;
4157 
4158 				/* Tell the client */
4159 				//Stream_tile(i, p_ptr, dispy, dispx);
4160 
4161 				/* Tell the client */
4162 				(void)send_air_char(p_ptr, dispy, dispx, missile_attr, missile_char, cur_dis, 1);
4163 
4164 				/* Flush and wait */
4165 				//if (cur_dis % 2) Send_flush(i);
4166 
4167 				/* Restore */
4168 				//lite_spot(i, y, x);
4169 			}
4170 
4171 			/* The player cannot see the missile */
4172 			else
4173 			{
4174 				/* Pause anyway, for consistancy */
4175 				/*Term_xtra(TERM_XTRA_DELAY, msec);*/
4176 			}
4177 		}
4178 
4179 		/* Restore the player pointer */
4180 		p_ptr = q_ptr;
4181 
4182 
4183 		/* Player here, try to hit him */
4184 		if (cave[Depth][y][x].m_idx < 0)
4185 		{
4186 			cave_type *c_ptr = &cave[Depth][y][x];
4187 
4188 			q_ptr = Players[0 - c_ptr->m_idx];
4189 
4190 			/* Check the visibility */
4191 			visible = p_ptr->play_vis[0 - c_ptr->m_idx];
4192 
4193 			/* Note the collision */
4194 			hit_body = TRUE;
4195 
4196 			/* Did we hit him (penalize range) */
4197 			if (test_hit_fire(chance - cur_dis, q_ptr->ac + q_ptr->to_a, visible))
4198 			{
4199 				/* Handle unseen player */
4200 				if (!visible)
4201 				{
4202 					/* Messages */
4203 					msg_format(p_ptr, "The %s finds a mark!", o_name);
4204 					msg_format(q_ptr, "You are hit by a %s!", o_name);
4205 				}
4206 
4207 				/* Don't do damage if players aren't hostile */
4208 				if (!pvp_okay(p_ptr, q_ptr, 0))
4209 				{
4210 					hit_body = FALSE;
4211 
4212 					/* Messages */
4213 					if (visible)
4214 					{
4215 						msg_format(p_ptr, "%s shrugs off the %s.", q_ptr->name, o_name);
4216 						msg_format(q_ptr, "%s throws you %s %s!", p_ptr->name,
4217 							(is_a_vowel(o_name[0]) ? "an" : "a"), o_name);
4218 					}
4219 					/* Stop */
4220 					break;
4221 				}
4222 
4223 				/* Handle visible player */
4224 				if (visible)
4225 				{
4226 					/* Messages */
4227 					msg_format(p_ptr, "The %s hits %s.", o_name, q_ptr->name);
4228 					msg_format(q_ptr, "%s hits you with %s %s!", p_ptr->name,
4229 							(is_a_vowel(o_name[0]) ? "an" : "a"), o_name);
4230 
4231 					/* Track player's health */
4232 					health_track(p_ptr, c_ptr->m_idx);
4233 				}
4234 
4235 				/* Apply special damage XXX XXX XXX */
4236 				tdam = tot_dam_aux_player(o_ptr, tdam, q_ptr);
4237 				tdam = critical_shot(p_ptr, o_ptr->weight, o_ptr->to_h, tdam);
4238 
4239 				/* No negative damage */
4240 				if (tdam < 0) tdam = 0;
4241 
4242 				/* XXX Reduce damage by 1/3 */
4243 				tdam = (tdam + 2) / 3;
4244 
4245 				/* Take damage */
4246 				take_hit(q_ptr, tdam, p_ptr->name);
4247 
4248 				/* Stop looking */
4249 				break;
4250 			}
4251 		}
4252 
4253 		/* Monster here, Try to hit it */
4254 		if (cave[Depth][y][x].m_idx > 0)
4255 		{
4256 			cave_type *c_ptr = &cave[Depth][y][x];
4257 
4258 			monster_type *m_ptr = &m_list[c_ptr->m_idx];
4259 			monster_race *r_ptr = &r_info[m_ptr->r_idx];
4260 
4261 			/* Check the visibility */
4262 			visible = p_ptr->mon_vis[c_ptr->m_idx];
4263 
4264 			/* Note the collision */
4265 			hit_body = TRUE;
4266 
4267 			/* Did we hit it (penalize range) */
4268 			if (test_hit_fire(chance - cur_dis, r_ptr->ac, visible))
4269 			{
4270 				bool fear = FALSE;
4271 
4272 				/* Assume a default death */
4273 				cptr note_dies = " dies.";
4274 
4275 				/* Some monsters get "destroyed" */
4276 				if ((r_ptr->flags3 & RF3_DEMON) ||
4277 				    (r_ptr->flags3 & RF3_UNDEAD) ||
4278 				    (r_ptr->flags2 & RF2_STUPID) ||
4279 				    (strchr("Evg", r_ptr->d_char)))
4280 				{
4281 					/* Special note at death */
4282 					note_dies = " is destroyed.";
4283 				}
4284 
4285 
4286 				/* Handle unseen monster */
4287 				if (!visible)
4288 				{
4289 					/* Invisible monster */
4290 					msg_format(p_ptr, "The %s finds a mark.", o_name);
4291 				}
4292 
4293 				/* Handle visible monster */
4294 				else
4295 				{
4296 					char m_name[80];
4297 
4298 					/* Get "the monster" or "it" */
4299 					monster_desc(p_ptr, m_name, c_ptr->m_idx, 0);
4300 
4301 					/* Message */
4302 					msg_format(p_ptr, "The %s hits %s.", o_name, m_name);
4303 
4304 					/* Hack -- Track this monster race */
4305 					if (visible) monster_race_track(p_ptr, m_ptr->r_idx);
4306 
4307 					/* Hack -- Track this monster */
4308 					if (visible) health_track(p_ptr, c_ptr->m_idx);
4309 				}
4310 
4311 				/* Apply special damage XXX XXX XXX */
4312 				tdam = tot_dam_aux(p_ptr, o_ptr, tdam, m_ptr, p_ptr->mon_vis[c_ptr->m_idx]);
4313 				tdam = critical_shot(p_ptr, o_ptr->weight, o_ptr->to_h, tdam);
4314 
4315 				/* No negative damage */
4316 				if (tdam < 0) tdam = 0;
4317 
4318 				/* Complex message */
4319 				if (is_dm_p(p_ptr))
4320 				{
4321 					msg_format(p_ptr, "You do %d (out of %d) damage.",
4322 					           tdam, m_ptr->hp);
4323 				}
4324 
4325 				/* Hit the monster, check for death */
4326 				if (mon_take_hit(p_ptr, c_ptr->m_idx, tdam, &fear, note_dies))
4327 				{
4328 					/* Dead monster */
4329 				}
4330 
4331 				/* No death */
4332 				else
4333 				{
4334 					/* Message */
4335 					message_pain(p_ptr, c_ptr->m_idx, tdam);
4336 
4337 					/* Take note */
4338 					if (fear && visible && !(r_ptr->flags2 & RF2_WANDERER))
4339 					{
4340 						char m_name[80];
4341 
4342 						/* Sound */
4343 						sound(p_ptr, MSG_FLEE);
4344 
4345 						/* Get the monster name (or "it") */
4346 						monster_desc(p_ptr, m_name, c_ptr->m_idx, 0);
4347 
4348 						/* Message */
4349 						msg_format(p_ptr, "%^s flees in terror!", m_name);
4350 					}
4351 				}
4352 
4353 				/* Stop looking */
4354 				break;
4355 			}
4356 		}
4357 	}
4358 
4359 	/* Chance of breakage (during attacks) */
4360 	j = (hit_body ? breakage_chance(o_ptr) : 0);
4361 
4362 	/* Hack -- newbies_cannot_drop -- break item when throwing */
4363 	if ((p_ptr->lev == 1) && (cfg_newbies_cannot_drop))
4364 		j = 100;
4365 
4366 	/* Drop (or break) near that location */
4367 	drop_near(o_ptr, j, Depth, y, x);
4368 }
4369 
4370 
4371 /*
4372  * Buy a house.  It is assumed that the player already knows the
4373  * price.
4374 
4375  Hacked to sell houses for half price. -APD-
4376 
4377  */
do_cmd_purchase_house(player_type * p_ptr,int dir)4378 void do_cmd_purchase_house(player_type *p_ptr, int dir)
4379 {
4380 	int Depth = p_ptr->dun_depth;
4381 
4382 	int y, x, i, factor, price;
4383 	cave_type *c_ptr;
4384 
4385 	/* Check preventive inscription '^h' */
4386 	__trap(p_ptr, CPI(p_ptr, 'h'));
4387 
4388 	/* Ghosts cannot buy houses */
4389 	if(!(p_ptr->dm_flags & DM_HOUSE_CONTROL))  {
4390 		if ( (p_ptr->ghost) || (p_ptr->fruit_bat) )
4391 		{
4392 			/* Message */
4393 			msg_print(p_ptr, "You cannot buy a house.");
4394 
4395 			return;
4396 		}
4397 	}
4398 
4399 	/* Check for no-direction -- confirmation (when selling house) */
4400 	if (!VALID_DIR(dir))
4401 	{
4402 			i = p_ptr->current_house;
4403 			p_ptr->current_house = -1;
4404 
4405 			if (i == -1)
4406 			{
4407 				/* No house, message */
4408 				msg_print(p_ptr, "You see nothing to sell there.");
4409 				return;
4410 			}
4411 
4412 			/* Get requested grid */
4413 			c_ptr = &cave[Depth][houses[i].door_y][houses[i].door_x];
4414 
4415 			/* Take player's CHR into account */
4416 			factor = adj_chr_gold[p_ptr->stat_ind[A_CHR]];
4417 			price = (unsigned long) houses[i].price * factor / 100;
4418 
4419 			if (house_owned(i))
4420 			{
4421 				/* Is it owned by this player? */
4422 				if (house_owned_by(p_ptr, i))
4423 				{
4424 					/* house is no longer owned */
4425 					disown_house(i);
4426 
4427 					msg_format(p_ptr, "You sell your house for %ld gold.", price/2);
4428 
4429 					 /* Get the money */
4430 					p_ptr->au += price / 2;
4431 
4432 					/* Redraw */
4433 					p_ptr->redraw |= (PR_GOLD);
4434 
4435 					/* Done */
4436 					return;
4437 					}
4438 			}
4439 
4440 			/* No house, message */
4441 			msg_print(p_ptr, "You don't own this house.");
4442 			return;
4443 	}
4444 
4445 	/* Be sure we have a direction */
4446 	if (VALID_DIR(dir))
4447 	{
4448 		/* Get requested direction */
4449 		y = p_ptr->py + ddy[dir];
4450 		x = p_ptr->px + ddx[dir];
4451 
4452 		/* Get requested grid */
4453 		c_ptr = &cave[Depth][y][x];
4454 
4455 		/* Check for a house */
4456 		if ((i = pick_house(Depth, y, x)) == -1)
4457 		{
4458 			/* No house, message */
4459 			msg_print(p_ptr, "You see nothing to buy there.");
4460 			return;
4461 		}
4462 
4463 		/* Take player's CHR into account */
4464 		factor = adj_chr_gold[p_ptr->stat_ind[A_CHR]];
4465 		price = (unsigned long) houses[i].price * factor / 100;
4466 
4467 
4468 		/* Check for already-owned house */
4469 		if (house_owned(i))
4470 		{
4471 
4472 			/* Is it owned by this player? */
4473 			if (house_owned_by(p_ptr, i))
4474 			{
4475 				if (house_inside(p_ptr, i))
4476 				{
4477 					/* Hack -- Enter own store */
4478 					/*command_new = '_';*/
4479 					do_cmd_store(p_ptr, i);
4480 				}
4481 				else
4482 				{
4483 					/* Delay house transaction */
4484 					p_ptr->current_house = i;
4485 					/* Tell the client about the price */
4486 					send_store_sell(p_ptr, price/2);
4487 				}
4488 				return;
4489 			}
4490 
4491 			if (p_ptr->dm_flags & DM_HOUSE_CONTROL)
4492 			{
4493 				disown_house(i);
4494 
4495 				msg_format(p_ptr, "The house has been reset.");
4496 
4497 				return;
4498 			}
4499 
4500 			/* Message */
4501 			msg_print(p_ptr, "That house is already owned.");
4502 
4503 			/* No sale */
4504 			return;
4505 		}
4506 
4507 		if (Depth == 0)
4508 		{
4509 			/* houses in town are *ASTRONOMICAL* in price due to location, location, location. */
4510 			price =(unsigned long)price *5L;
4511 		}
4512 
4513 		/* Check for enough funds */
4514 		if (price > p_ptr->au)
4515 		{
4516 			/* Not enough money, message */
4517 			msg_print(p_ptr, "You do not have enough money.");
4518 			return;
4519 		}
4520 
4521 		/* Check if we have too many houses already */
4522 		if( cfg_max_houses && houses_owned(p_ptr) >= cfg_max_houses )
4523 		{
4524 			/* Too many houses owned already */
4525 			msg_print(p_ptr, "You own too many houses already.");
4526 			return;
4527 		}
4528 
4529 		/* Open the door */
4530 		c_ptr->feat = FEAT_HOME_OPEN;
4531 
4532 		/* Reshow */
4533 		everyone_lite_spot(Depth, y, x);
4534 
4535 		/* Take some of the player's money */
4536 		p_ptr->au -= price;
4537 
4538 		/* The house is now owned */
4539 		set_house_owner(p_ptr, i);
4540 
4541 		/* Redraw */
4542 		p_ptr->redraw |= (PR_GOLD);
4543 	}
4544 }
4545