Home | History | Annotate | Line # | Download | only in rogue
      1  1.12     joerg /*	$NetBSD: throw.c,v 1.12 2011/05/23 23:01:17 joerg 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.12     joerg __RCSID("$NetBSD: throw.c,v 1.12 2011/05/23 23:01:17 joerg 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.11  dholland static void flop_weapon(object *, short, short);
     59  1.11  dholland static object *get_thrown_at_monster(object *, short, short *, short *);
     60  1.11  dholland static boolean throw_at_monster(object *, object *);
     61  1.11  dholland 
     62   1.4     lukem void
     63  1.10  dholland throw(void)
     64   1.1       cgd {
     65   1.1       cgd 	short wch, d;
     66   1.1       cgd 	boolean first_miss = 1;
     67   1.1       cgd 	object *weapon;
     68   1.1       cgd 	short dir, row, col;
     69   1.1       cgd 	object *monster;
     70   1.1       cgd 
     71   1.1       cgd 	while (!is_direction(dir = rgetchar(), &d)) {
     72   1.1       cgd 		sound_bell();
     73   1.1       cgd 		if (first_miss) {
     74   1.8  dholland 			messagef(0, "direction? ");
     75   1.1       cgd 			first_miss = 0;
     76   1.1       cgd 		}
     77   1.1       cgd 	}
     78   1.1       cgd 	check_message();
     79   1.1       cgd 	if (dir == CANCEL) {
     80   1.1       cgd 		return;
     81   1.1       cgd 	}
     82   1.1       cgd 	if ((wch = pack_letter("throw what?", WEAPON)) == CANCEL) {
     83   1.1       cgd 		return;
     84   1.1       cgd 	}
     85   1.1       cgd 	check_message();
     86   1.1       cgd 
     87   1.1       cgd 	if (!(weapon = get_letter_object(wch))) {
     88   1.8  dholland 		messagef(0, "no such item.");
     89   1.1       cgd 		return;
     90   1.1       cgd 	}
     91   1.1       cgd 	if ((weapon->in_use_flags & BEING_USED) && weapon->is_cursed) {
     92  1.12     joerg 		messagef(0, "%s", curse_message);
     93   1.1       cgd 		return;
     94   1.1       cgd 	}
     95   1.1       cgd 	row = rogue.row; col = rogue.col;
     96   1.1       cgd 
     97   1.1       cgd 	if ((weapon->in_use_flags & BEING_WIELDED) && (weapon->quantity <= 1)) {
     98   1.1       cgd 		unwield(rogue.weapon);
     99   1.1       cgd 	} else if (weapon->in_use_flags & BEING_WORN) {
    100   1.1       cgd 		mv_aquatars();
    101   1.1       cgd 		unwear(rogue.armor);
    102   1.1       cgd 		print_stats(STAT_ARMOR);
    103   1.1       cgd 	} else if (weapon->in_use_flags & ON_EITHER_HAND) {
    104   1.1       cgd 		un_put_on(weapon);
    105   1.1       cgd 	}
    106   1.1       cgd 	monster = get_thrown_at_monster(weapon, d, &row, &col);
    107   1.1       cgd 	mvaddch(rogue.row, rogue.col, rogue.fchar);
    108   1.1       cgd 	refresh();
    109   1.1       cgd 
    110   1.1       cgd 	if (rogue_can_see(row, col) && ((row != rogue.row) || (col != rogue.col))){
    111   1.1       cgd 		mvaddch(row, col, get_dungeon_char(row, col));
    112   1.1       cgd 	}
    113   1.1       cgd 	if (monster) {
    114   1.1       cgd 		wake_up(monster);
    115   1.1       cgd 		check_gold_seeker(monster);
    116   1.1       cgd 
    117   1.1       cgd 		if (!throw_at_monster(monster, weapon)) {
    118   1.1       cgd 			flop_weapon(weapon, row, col);
    119   1.1       cgd 		}
    120   1.1       cgd 	} else {
    121   1.1       cgd 		flop_weapon(weapon, row, col);
    122   1.1       cgd 	}
    123   1.1       cgd 	vanish(weapon, 1, &rogue.pack);
    124   1.1       cgd }
    125   1.1       cgd 
    126   1.4     lukem boolean
    127  1.10  dholland throw_at_monster(object *monster, object *weapon)
    128   1.1       cgd {
    129   1.1       cgd 	short damage, hit_chance;
    130   1.1       cgd 	short t;
    131   1.1       cgd 
    132   1.1       cgd 	hit_chance = get_hit_chance(weapon);
    133   1.1       cgd 	damage = get_weapon_damage(weapon);
    134   1.1       cgd 	if ((weapon->which_kind == ARROW) &&
    135   1.1       cgd 		(rogue.weapon && (rogue.weapon->which_kind == BOW))) {
    136   1.1       cgd 		damage += get_weapon_damage(rogue.weapon);
    137   1.1       cgd 		damage = ((damage * 2) / 3);
    138   1.1       cgd 		hit_chance += (hit_chance / 3);
    139   1.1       cgd 	} else if ((weapon->in_use_flags & BEING_WIELDED) &&
    140   1.1       cgd 		((weapon->which_kind == DAGGER) ||
    141   1.1       cgd 		(weapon->which_kind == SHURIKEN) ||
    142   1.1       cgd 		(weapon->which_kind == DART))) {
    143   1.1       cgd 		damage = ((damage * 3) / 2);
    144   1.1       cgd 		hit_chance += (hit_chance / 3);
    145   1.1       cgd 	}
    146   1.1       cgd 	t = weapon->quantity;
    147   1.1       cgd 	weapon->quantity = 1;
    148   1.8  dholland 	snprintf(hit_message, HIT_MESSAGE_SIZE, "the %s", name_of(weapon));
    149   1.1       cgd 	weapon->quantity = t;
    150   1.1       cgd 
    151   1.1       cgd 	if (!rand_percent(hit_chance)) {
    152   1.9  dholland 		(void)strlcat(hit_message, "misses  ", HIT_MESSAGE_SIZE);
    153   1.1       cgd 		return(0);
    154   1.1       cgd 	}
    155   1.1       cgd 	s_con_mon(monster);
    156   1.9  dholland 	(void)strlcat(hit_message, "hit  ", HIT_MESSAGE_SIZE);
    157   1.9  dholland 	(void)mon_damage(monster, damage);
    158   1.1       cgd 	return(1);
    159   1.1       cgd }
    160   1.1       cgd 
    161   1.1       cgd object *
    162  1.10  dholland get_thrown_at_monster(object *obj, short dir, short *row, short *col)
    163   1.1       cgd {
    164   1.1       cgd 	short orow, ocol;
    165   1.1       cgd 	short i, ch;
    166   1.1       cgd 
    167   1.1       cgd 	orow = *row; ocol = *col;
    168   1.1       cgd 
    169   1.1       cgd 	ch = get_mask_char(obj->what_is);
    170   1.1       cgd 
    171   1.1       cgd 	for (i = 0; i < 24; i++) {
    172   1.1       cgd 		get_dir_rc(dir, row, col, 0);
    173   1.1       cgd 		if (	(((*col <= 0) || (*col >= DCOLS-1)) ||
    174   1.1       cgd 				(dungeon[*row][*col] == NOTHING)) ||
    175   1.1       cgd 				((dungeon[*row][*col] & (HORWALL | VERTWALL | HIDDEN)) &&
    176   1.1       cgd 					(!(dungeon[*row][*col] & TRAP)))) {
    177   1.1       cgd 			*row = orow;
    178   1.1       cgd 			*col = ocol;
    179   1.1       cgd 			return(0);
    180   1.1       cgd 		}
    181   1.1       cgd 		if ((i != 0) && rogue_can_see(orow, ocol)) {
    182   1.1       cgd 			mvaddch(orow, ocol, get_dungeon_char(orow, ocol));
    183   1.1       cgd 		}
    184   1.1       cgd 		if (rogue_can_see(*row, *col)) {
    185   1.1       cgd 			if (!(dungeon[*row][*col] & MONSTER)) {
    186   1.1       cgd 				mvaddch(*row, *col, ch);
    187   1.1       cgd 			}
    188   1.1       cgd 			refresh();
    189   1.1       cgd 		}
    190   1.1       cgd 		orow = *row; ocol = *col;
    191   1.1       cgd 		if (dungeon[*row][*col] & MONSTER) {
    192   1.1       cgd 			if (!imitating(*row, *col)) {
    193   1.1       cgd 				return(object_at(&level_monsters, *row, *col));
    194   1.1       cgd 			}
    195   1.1       cgd 		}
    196   1.1       cgd 		if (dungeon[*row][*col] & TUNNEL) {
    197   1.1       cgd 			i += 2;
    198   1.1       cgd 		}
    199   1.1       cgd 	}
    200   1.1       cgd 	return(0);
    201   1.1       cgd }
    202   1.1       cgd 
    203   1.4     lukem void
    204  1.10  dholland flop_weapon(object *weapon, short row, short col)
    205   1.1       cgd {
    206   1.1       cgd 	object *new_weapon, *monster;
    207   1.1       cgd 	short i = 0;
    208   1.1       cgd 	boolean found = 0;
    209   1.1       cgd 	short mch, dch;
    210   1.1       cgd 	unsigned short mon;
    211   1.1       cgd 
    212   1.7   jnemeth 	if ((row < 0) || (row >= DROWS) || (col < 0) || (col >= DCOLS))
    213   1.7   jnemeth 		clean_up("flop_weapon:  weapon landed outside of dungeon");
    214   1.7   jnemeth 
    215   1.1       cgd 	while ((i < 9) && dungeon[row][col] & ~(FLOOR | TUNNEL | DOOR | MONSTER)) {
    216   1.1       cgd 		rand_around(i++, &row, &col);
    217   1.1       cgd 		if ((row > (DROWS-2)) || (row < MIN_ROW) ||
    218   1.1       cgd 			(col > (DCOLS-1)) || (col < 0) || (!dungeon[row][col]) ||
    219   1.1       cgd 			(dungeon[row][col] & ~(FLOOR | TUNNEL | DOOR | MONSTER))) {
    220   1.1       cgd 			continue;
    221   1.1       cgd 		}
    222   1.1       cgd 		found = 1;
    223   1.1       cgd 		break;
    224   1.1       cgd 	}
    225   1.1       cgd 
    226   1.1       cgd 	if (found || (i == 0)) {
    227   1.1       cgd 		new_weapon = alloc_object();
    228   1.1       cgd 		*new_weapon = *weapon;
    229   1.1       cgd 		new_weapon->in_use_flags = NOT_USED;
    230   1.1       cgd 		new_weapon->quantity = 1;
    231   1.1       cgd 		new_weapon->ichar = 'L';
    232   1.1       cgd 		place_at(new_weapon, row, col);
    233   1.1       cgd 		if (rogue_can_see(row, col) &&
    234   1.1       cgd 				((row != rogue.row) || (col != rogue.col))) {
    235   1.1       cgd 			mon = dungeon[row][col] & MONSTER;
    236   1.1       cgd 			dungeon[row][col] &= (~MONSTER);
    237   1.1       cgd 			dch = get_dungeon_char(row, col);
    238   1.1       cgd 			if (mon) {
    239   1.1       cgd 				mch = mvinch(row, col);
    240   1.4     lukem 				if ((monster = object_at(&level_monsters,
    241   1.4     lukem 				    row, col)) != NULL) {
    242   1.1       cgd 					monster->trail_char = dch;
    243   1.1       cgd 				}
    244   1.1       cgd 				if ((mch < 'A') || (mch > 'Z')) {
    245   1.1       cgd 					mvaddch(row, col, dch);
    246   1.1       cgd 				}
    247   1.1       cgd 			} else {
    248   1.1       cgd 				mvaddch(row, col, dch);
    249   1.1       cgd 			}
    250   1.1       cgd 			dungeon[row][col] |= mon;
    251   1.1       cgd 		}
    252   1.1       cgd 	} else {
    253   1.1       cgd 		short t;
    254   1.1       cgd 
    255   1.1       cgd 		t = weapon->quantity;
    256   1.1       cgd 		weapon->quantity = 1;
    257   1.8  dholland 		messagef(0, "the %svanishes as it hits the ground",
    258   1.8  dholland 			name_of(weapon));
    259   1.1       cgd 		weapon->quantity = t;
    260   1.1       cgd 	}
    261   1.1       cgd }
    262   1.1       cgd 
    263   1.4     lukem void
    264  1.10  dholland rand_around(short i, short *r, short *c)
    265   1.1       cgd {
    266   1.5   hubertf 	static char pos[] = "\010\007\001\003\004\005\002\006\0";
    267   1.1       cgd 	static short row, col;
    268   1.1       cgd 	short j;
    269   1.1       cgd 
    270   1.1       cgd 	if (i == 0) {
    271   1.1       cgd 		short x, y, o, t;
    272   1.1       cgd 
    273   1.1       cgd 		row = *r;
    274   1.1       cgd 		col = *c;
    275   1.1       cgd 
    276   1.1       cgd 		o = get_rand(1, 8);
    277   1.1       cgd 
    278   1.1       cgd 		for (j = 0; j < 5; j++) {
    279   1.1       cgd 			x = get_rand(0, 8);
    280   1.1       cgd 			y = (x + o) % 9;
    281   1.1       cgd 			t = pos[x];
    282   1.1       cgd 			pos[x] = pos[y];
    283   1.1       cgd 			pos[y] = t;
    284   1.1       cgd 		}
    285   1.1       cgd 	}
    286   1.1       cgd 	switch((short)pos[i]) {
    287   1.1       cgd 	case 0:
    288   1.1       cgd 		*r = row + 1;
    289   1.1       cgd 		*c = col + 1;
    290   1.1       cgd 		break;
    291   1.1       cgd 	case 1:
    292   1.1       cgd 		*r = row + 1;
    293   1.1       cgd 		*c = col - 1;
    294   1.1       cgd 		break;
    295   1.1       cgd 	case 2:
    296   1.1       cgd 		*r = row - 1;
    297   1.1       cgd 		*c = col + 1;
    298   1.1       cgd 		break;
    299   1.1       cgd 	case 3:
    300   1.1       cgd 		*r = row - 1;
    301   1.1       cgd 		*c = col - 1;
    302   1.1       cgd 		break;
    303   1.1       cgd 	case 4:
    304   1.1       cgd 		*r = row;
    305   1.1       cgd 		*c = col + 1;
    306   1.1       cgd 		break;
    307   1.1       cgd 	case 5:
    308   1.1       cgd 		*r = row + 1;
    309   1.1       cgd 		*c = col;
    310   1.1       cgd 		break;
    311   1.1       cgd 	case 6:
    312   1.1       cgd 		*r = row;
    313   1.1       cgd 		*c = col;
    314   1.1       cgd 		break;
    315   1.1       cgd 	case 7:
    316   1.1       cgd 		*r = row - 1;
    317   1.1       cgd 		*c = col;
    318   1.1       cgd 		break;
    319   1.1       cgd 	case 8:
    320   1.1       cgd 		*r = row;
    321   1.1       cgd 		*c = col - 1;
    322   1.1       cgd 		break;
    323   1.1       cgd 	}
    324   1.1       cgd }
    325