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