Home | History | Annotate | Line # | Download | only in rogue
throw.c revision 1.7.10.2
      1  1.7.10.2     matt /*	throw.c,v 1.7.10.1 2008/01/09 01:30:59 matt Exp	*/
      2       1.3      cgd 
      3       1.1      cgd /*
      4       1.3      cgd  * Copyright (c) 1988, 1993
      5       1.3      cgd  *	The Regents of the University of California.  All rights reserved.
      6       1.1      cgd  *
      7       1.1      cgd  * This code is derived from software contributed to Berkeley by
      8       1.1      cgd  * Timothy C. Stoehr.
      9       1.1      cgd  *
     10       1.1      cgd  * Redistribution and use in source and binary forms, with or without
     11       1.1      cgd  * modification, are permitted provided that the following conditions
     12       1.1      cgd  * are met:
     13       1.1      cgd  * 1. Redistributions of source code must retain the above copyright
     14       1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     15       1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     17       1.1      cgd  *    documentation and/or other materials provided with the distribution.
     18       1.6      agc  * 3. Neither the name of the University nor the names of its contributors
     19       1.1      cgd  *    may be used to endorse or promote products derived from this software
     20       1.1      cgd  *    without specific prior written permission.
     21       1.1      cgd  *
     22       1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23       1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24       1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25       1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26       1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27       1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28       1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29       1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30       1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31       1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32       1.1      cgd  * SUCH DAMAGE.
     33       1.1      cgd  */
     34       1.1      cgd 
     35       1.4    lukem #include <sys/cdefs.h>
     36       1.1      cgd #ifndef lint
     37       1.3      cgd #if 0
     38       1.3      cgd static char sccsid[] = "@(#)throw.c	8.1 (Berkeley) 5/31/93";
     39       1.3      cgd #else
     40  1.7.10.2     matt __RCSID("throw.c,v 1.7.10.1 2008/01/09 01:30:59 matt Exp");
     41       1.3      cgd #endif
     42       1.1      cgd #endif /* not lint */
     43       1.1      cgd 
     44       1.1      cgd /*
     45       1.1      cgd  * throw.c
     46       1.1      cgd  *
     47       1.1      cgd  * This source herein may be modified and/or distributed by anybody who
     48       1.1      cgd  * so desires, with the following restrictions:
     49       1.1      cgd  *    1.)  No portion of this notice shall be removed.
     50       1.1      cgd  *    2.)  Credit shall not be taken for the creation of this source.
     51       1.1      cgd  *    3.)  This code is not to be traded, sold, or used for personal
     52       1.1      cgd  *         gain or profit.
     53       1.1      cgd  *
     54       1.1      cgd  */
     55       1.1      cgd 
     56       1.1      cgd #include "rogue.h"
     57       1.1      cgd 
     58       1.4    lukem void
     59  1.7.10.2     matt throw(void)
     60       1.1      cgd {
     61       1.1      cgd 	short wch, d;
     62       1.1      cgd 	boolean first_miss = 1;
     63       1.1      cgd 	object *weapon;
     64       1.1      cgd 	short dir, row, col;
     65       1.1      cgd 	object *monster;
     66       1.1      cgd 
     67       1.1      cgd 	while (!is_direction(dir = rgetchar(), &d)) {
     68       1.1      cgd 		sound_bell();
     69       1.1      cgd 		if (first_miss) {
     70  1.7.10.1     matt 			messagef(0, "direction? ");
     71       1.1      cgd 			first_miss = 0;
     72       1.1      cgd 		}
     73       1.1      cgd 	}
     74       1.1      cgd 	check_message();
     75       1.1      cgd 	if (dir == CANCEL) {
     76       1.1      cgd 		return;
     77       1.1      cgd 	}
     78       1.1      cgd 	if ((wch = pack_letter("throw what?", WEAPON)) == CANCEL) {
     79       1.1      cgd 		return;
     80       1.1      cgd 	}
     81       1.1      cgd 	check_message();
     82       1.1      cgd 
     83       1.1      cgd 	if (!(weapon = get_letter_object(wch))) {
     84  1.7.10.1     matt 		messagef(0, "no such item.");
     85       1.1      cgd 		return;
     86       1.1      cgd 	}
     87       1.1      cgd 	if ((weapon->in_use_flags & BEING_USED) && weapon->is_cursed) {
     88  1.7.10.1     matt 		messagef(0, curse_message);
     89       1.1      cgd 		return;
     90       1.1      cgd 	}
     91       1.1      cgd 	row = rogue.row; col = rogue.col;
     92       1.1      cgd 
     93       1.1      cgd 	if ((weapon->in_use_flags & BEING_WIELDED) && (weapon->quantity <= 1)) {
     94       1.1      cgd 		unwield(rogue.weapon);
     95       1.1      cgd 	} else if (weapon->in_use_flags & BEING_WORN) {
     96       1.1      cgd 		mv_aquatars();
     97       1.1      cgd 		unwear(rogue.armor);
     98       1.1      cgd 		print_stats(STAT_ARMOR);
     99       1.1      cgd 	} else if (weapon->in_use_flags & ON_EITHER_HAND) {
    100       1.1      cgd 		un_put_on(weapon);
    101       1.1      cgd 	}
    102       1.1      cgd 	monster = get_thrown_at_monster(weapon, d, &row, &col);
    103       1.1      cgd 	mvaddch(rogue.row, rogue.col, rogue.fchar);
    104       1.1      cgd 	refresh();
    105       1.1      cgd 
    106       1.1      cgd 	if (rogue_can_see(row, col) && ((row != rogue.row) || (col != rogue.col))){
    107       1.1      cgd 		mvaddch(row, col, get_dungeon_char(row, col));
    108       1.1      cgd 	}
    109       1.1      cgd 	if (monster) {
    110       1.1      cgd 		wake_up(monster);
    111       1.1      cgd 		check_gold_seeker(monster);
    112       1.1      cgd 
    113       1.1      cgd 		if (!throw_at_monster(monster, weapon)) {
    114       1.1      cgd 			flop_weapon(weapon, row, col);
    115       1.1      cgd 		}
    116       1.1      cgd 	} else {
    117       1.1      cgd 		flop_weapon(weapon, row, col);
    118       1.1      cgd 	}
    119       1.1      cgd 	vanish(weapon, 1, &rogue.pack);
    120       1.1      cgd }
    121       1.1      cgd 
    122       1.4    lukem boolean
    123  1.7.10.2     matt throw_at_monster(object *monster, object *weapon)
    124       1.1      cgd {
    125       1.1      cgd 	short damage, hit_chance;
    126       1.1      cgd 	short t;
    127       1.1      cgd 
    128       1.1      cgd 	hit_chance = get_hit_chance(weapon);
    129       1.1      cgd 	damage = get_weapon_damage(weapon);
    130       1.1      cgd 	if ((weapon->which_kind == ARROW) &&
    131       1.1      cgd 		(rogue.weapon && (rogue.weapon->which_kind == BOW))) {
    132       1.1      cgd 		damage += get_weapon_damage(rogue.weapon);
    133       1.1      cgd 		damage = ((damage * 2) / 3);
    134       1.1      cgd 		hit_chance += (hit_chance / 3);
    135       1.1      cgd 	} else if ((weapon->in_use_flags & BEING_WIELDED) &&
    136       1.1      cgd 		((weapon->which_kind == DAGGER) ||
    137       1.1      cgd 		(weapon->which_kind == SHURIKEN) ||
    138       1.1      cgd 		(weapon->which_kind == DART))) {
    139       1.1      cgd 		damage = ((damage * 3) / 2);
    140       1.1      cgd 		hit_chance += (hit_chance / 3);
    141       1.1      cgd 	}
    142       1.1      cgd 	t = weapon->quantity;
    143       1.1      cgd 	weapon->quantity = 1;
    144  1.7.10.1     matt 	snprintf(hit_message, HIT_MESSAGE_SIZE, "the %s", name_of(weapon));
    145       1.1      cgd 	weapon->quantity = t;
    146       1.1      cgd 
    147       1.1      cgd 	if (!rand_percent(hit_chance)) {
    148  1.7.10.2     matt 		(void)strlcat(hit_message, "misses  ", HIT_MESSAGE_SIZE);
    149       1.1      cgd 		return(0);
    150       1.1      cgd 	}
    151       1.1      cgd 	s_con_mon(monster);
    152  1.7.10.2     matt 	(void)strlcat(hit_message, "hit  ", HIT_MESSAGE_SIZE);
    153  1.7.10.2     matt 	(void)mon_damage(monster, damage);
    154       1.1      cgd 	return(1);
    155       1.1      cgd }
    156       1.1      cgd 
    157       1.1      cgd object *
    158  1.7.10.2     matt get_thrown_at_monster(object *obj, short dir, short *row, short *col)
    159       1.1      cgd {
    160       1.1      cgd 	short orow, ocol;
    161       1.1      cgd 	short i, ch;
    162       1.1      cgd 
    163       1.1      cgd 	orow = *row; ocol = *col;
    164       1.1      cgd 
    165       1.1      cgd 	ch = get_mask_char(obj->what_is);
    166       1.1      cgd 
    167       1.1      cgd 	for (i = 0; i < 24; i++) {
    168       1.1      cgd 		get_dir_rc(dir, row, col, 0);
    169       1.1      cgd 		if (	(((*col <= 0) || (*col >= DCOLS-1)) ||
    170       1.1      cgd 				(dungeon[*row][*col] == NOTHING)) ||
    171       1.1      cgd 				((dungeon[*row][*col] & (HORWALL | VERTWALL | HIDDEN)) &&
    172       1.1      cgd 					(!(dungeon[*row][*col] & TRAP)))) {
    173       1.1      cgd 			*row = orow;
    174       1.1      cgd 			*col = ocol;
    175       1.1      cgd 			return(0);
    176       1.1      cgd 		}
    177       1.1      cgd 		if ((i != 0) && rogue_can_see(orow, ocol)) {
    178       1.1      cgd 			mvaddch(orow, ocol, get_dungeon_char(orow, ocol));
    179       1.1      cgd 		}
    180       1.1      cgd 		if (rogue_can_see(*row, *col)) {
    181       1.1      cgd 			if (!(dungeon[*row][*col] & MONSTER)) {
    182       1.1      cgd 				mvaddch(*row, *col, ch);
    183       1.1      cgd 			}
    184       1.1      cgd 			refresh();
    185       1.1      cgd 		}
    186       1.1      cgd 		orow = *row; ocol = *col;
    187       1.1      cgd 		if (dungeon[*row][*col] & MONSTER) {
    188       1.1      cgd 			if (!imitating(*row, *col)) {
    189       1.1      cgd 				return(object_at(&level_monsters, *row, *col));
    190       1.1      cgd 			}
    191       1.1      cgd 		}
    192       1.1      cgd 		if (dungeon[*row][*col] & TUNNEL) {
    193       1.1      cgd 			i += 2;
    194       1.1      cgd 		}
    195       1.1      cgd 	}
    196       1.1      cgd 	return(0);
    197       1.1      cgd }
    198       1.1      cgd 
    199       1.4    lukem void
    200  1.7.10.2     matt flop_weapon(object *weapon, short row, short col)
    201       1.1      cgd {
    202       1.1      cgd 	object *new_weapon, *monster;
    203       1.1      cgd 	short i = 0;
    204       1.1      cgd 	boolean found = 0;
    205       1.1      cgd 	short mch, dch;
    206       1.1      cgd 	unsigned short mon;
    207       1.1      cgd 
    208       1.7  jnemeth 	if ((row < 0) || (row >= DROWS) || (col < 0) || (col >= DCOLS))
    209       1.7  jnemeth 		clean_up("flop_weapon:  weapon landed outside of dungeon");
    210       1.7  jnemeth 
    211       1.1      cgd 	while ((i < 9) && dungeon[row][col] & ~(FLOOR | TUNNEL | DOOR | MONSTER)) {
    212       1.1      cgd 		rand_around(i++, &row, &col);
    213       1.1      cgd 		if ((row > (DROWS-2)) || (row < MIN_ROW) ||
    214       1.1      cgd 			(col > (DCOLS-1)) || (col < 0) || (!dungeon[row][col]) ||
    215       1.1      cgd 			(dungeon[row][col] & ~(FLOOR | TUNNEL | DOOR | MONSTER))) {
    216       1.1      cgd 			continue;
    217       1.1      cgd 		}
    218       1.1      cgd 		found = 1;
    219       1.1      cgd 		break;
    220       1.1      cgd 	}
    221       1.1      cgd 
    222       1.1      cgd 	if (found || (i == 0)) {
    223       1.1      cgd 		new_weapon = alloc_object();
    224       1.1      cgd 		*new_weapon = *weapon;
    225       1.1      cgd 		new_weapon->in_use_flags = NOT_USED;
    226       1.1      cgd 		new_weapon->quantity = 1;
    227       1.1      cgd 		new_weapon->ichar = 'L';
    228       1.1      cgd 		place_at(new_weapon, row, col);
    229       1.1      cgd 		if (rogue_can_see(row, col) &&
    230       1.1      cgd 				((row != rogue.row) || (col != rogue.col))) {
    231       1.1      cgd 			mon = dungeon[row][col] & MONSTER;
    232       1.1      cgd 			dungeon[row][col] &= (~MONSTER);
    233       1.1      cgd 			dch = get_dungeon_char(row, col);
    234       1.1      cgd 			if (mon) {
    235       1.1      cgd 				mch = mvinch(row, col);
    236       1.4    lukem 				if ((monster = object_at(&level_monsters,
    237       1.4    lukem 				    row, col)) != NULL) {
    238       1.1      cgd 					monster->trail_char = dch;
    239       1.1      cgd 				}
    240       1.1      cgd 				if ((mch < 'A') || (mch > 'Z')) {
    241       1.1      cgd 					mvaddch(row, col, dch);
    242       1.1      cgd 				}
    243       1.1      cgd 			} else {
    244       1.1      cgd 				mvaddch(row, col, dch);
    245       1.1      cgd 			}
    246       1.1      cgd 			dungeon[row][col] |= mon;
    247       1.1      cgd 		}
    248       1.1      cgd 	} else {
    249       1.1      cgd 		short t;
    250       1.1      cgd 
    251       1.1      cgd 		t = weapon->quantity;
    252       1.1      cgd 		weapon->quantity = 1;
    253  1.7.10.1     matt 		messagef(0, "the %svanishes as it hits the ground",
    254  1.7.10.1     matt 			name_of(weapon));
    255       1.1      cgd 		weapon->quantity = t;
    256       1.1      cgd 	}
    257       1.1      cgd }
    258       1.1      cgd 
    259       1.4    lukem void
    260  1.7.10.2     matt rand_around(short i, short *r, short *c)
    261       1.1      cgd {
    262       1.5  hubertf 	static char pos[] = "\010\007\001\003\004\005\002\006\0";
    263       1.1      cgd 	static short row, col;
    264       1.1      cgd 	short j;
    265       1.1      cgd 
    266       1.1      cgd 	if (i == 0) {
    267       1.1      cgd 		short x, y, o, t;
    268       1.1      cgd 
    269       1.1      cgd 		row = *r;
    270       1.1      cgd 		col = *c;
    271       1.1      cgd 
    272       1.1      cgd 		o = get_rand(1, 8);
    273       1.1      cgd 
    274       1.1      cgd 		for (j = 0; j < 5; j++) {
    275       1.1      cgd 			x = get_rand(0, 8);
    276       1.1      cgd 			y = (x + o) % 9;
    277       1.1      cgd 			t = pos[x];
    278       1.1      cgd 			pos[x] = pos[y];
    279       1.1      cgd 			pos[y] = t;
    280       1.1      cgd 		}
    281       1.1      cgd 	}
    282       1.1      cgd 	switch((short)pos[i]) {
    283       1.1      cgd 	case 0:
    284       1.1      cgd 		*r = row + 1;
    285       1.1      cgd 		*c = col + 1;
    286       1.1      cgd 		break;
    287       1.1      cgd 	case 1:
    288       1.1      cgd 		*r = row + 1;
    289       1.1      cgd 		*c = col - 1;
    290       1.1      cgd 		break;
    291       1.1      cgd 	case 2:
    292       1.1      cgd 		*r = row - 1;
    293       1.1      cgd 		*c = col + 1;
    294       1.1      cgd 		break;
    295       1.1      cgd 	case 3:
    296       1.1      cgd 		*r = row - 1;
    297       1.1      cgd 		*c = col - 1;
    298       1.1      cgd 		break;
    299       1.1      cgd 	case 4:
    300       1.1      cgd 		*r = row;
    301       1.1      cgd 		*c = col + 1;
    302       1.1      cgd 		break;
    303       1.1      cgd 	case 5:
    304       1.1      cgd 		*r = row + 1;
    305       1.1      cgd 		*c = col;
    306       1.1      cgd 		break;
    307       1.1      cgd 	case 6:
    308       1.1      cgd 		*r = row;
    309       1.1      cgd 		*c = col;
    310       1.1      cgd 		break;
    311       1.1      cgd 	case 7:
    312       1.1      cgd 		*r = row - 1;
    313       1.1      cgd 		*c = col;
    314       1.1      cgd 		break;
    315       1.1      cgd 	case 8:
    316       1.1      cgd 		*r = row;
    317       1.1      cgd 		*c = col - 1;
    318       1.1      cgd 		break;
    319       1.1      cgd 	}
    320       1.1      cgd }
    321