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