Annotation of early-roguelike/xrogue/weapons.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: weapons.c - Functions for dealing with problems brought about by weapons
! 3:
! 4: XRogue: Expeditions into the Dungeons of Doom
! 5: Copyright (C) 1991 Robert Pietkivitch
! 6: All rights reserved.
! 7:
! 8: Based on "Advanced Rogue"
! 9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
! 10: All rights reserved.
! 11:
! 12: Based on "Rogue: Exploring the Dungeons of Doom"
! 13: Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 14: All rights reserved.
! 15:
! 16: See the file LICENSE.TXT for full copyright and licensing information.
! 17: */
! 18:
! 19: #include <curses.h>
! 20: #include <ctype.h>
! 21: #include <string.h>
! 22: #include "rogue.h"
! 23:
! 24: void
! 25: boomerang(int ydelta, int xdelta, struct linked_list *item, struct thing *tp)
! 26: {
! 27: register struct object *obj;
! 28: struct thing midpoint;
! 29: coord oldpos;
! 30:
! 31: obj = OBJPTR(item);
! 32: oldpos = obj->o_pos;
! 33:
! 34: /*
! 35: * make it appear to fly at the target
! 36: */
! 37: do_motion(obj, ydelta, xdelta, tp);
! 38: hit_monster(unc(obj->o_pos), obj, tp);
! 39:
! 40: /*
! 41: * Now let's make it fly back to the wielder. We need to
! 42: * use midpoint to fool do_motion into thinking the action
! 43: * starts there. Do_motion only looks at the t_pos field.
! 44: */
! 45: midpoint.t_pos = obj->o_pos; /* Simulate a new start position */
! 46: do_motion(obj, -ydelta, -xdelta, &midpoint);
! 47:
! 48: obj->o_pos = oldpos;
! 49: }
! 50:
! 51: /*
! 52: * do the actual motion on the screen done by an object traveling
! 53: * across the room. Note that we should not look at any field in
! 54: * tp other than t_pos unless we change boomerang().
! 55: */
! 56:
! 57: void
! 58: do_motion(struct object *obj, int ydelta, int xdelta, struct thing *tp)
! 59: {
! 60:
! 61: /*
! 62: * Come fly with us ...
! 63: */
! 64: obj->o_pos = tp->t_pos;
! 65: for (;;) {
! 66: register int ch;
! 67: /*
! 68: * Erase the old one
! 69: */
! 70: if (!ce(obj->o_pos, tp->t_pos) &&
! 71: cansee(unc(obj->o_pos)) &&
! 72: mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') {
! 73: mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, show(obj->o_pos.y, obj->o_pos.x));
! 74: }
! 75: /*
! 76: * Get the new position
! 77: */
! 78: obj->o_pos.y += ydelta;
! 79: obj->o_pos.x += xdelta;
! 80: if (shoot_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR && !ce(obj->o_pos, hero)) {
! 81: /*
! 82: * It hasn't hit anything yet, so display it
! 83: * If it alright.
! 84: */
! 85: if (cansee(unc(obj->o_pos)) &&
! 86: mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') {
! 87: if (obj->o_type == MISSILE) nofont(cw);
! 88: mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type);
! 89: newfont(cw);
! 90: draw(cw);
! 91: }
! 92: continue;
! 93: }
! 94:
! 95: /*
! 96: * Did we stop because of a monster or the hero? If we did
! 97: * not, we want to move our position back one because we could
! 98: * not actually make it this far.
! 99: */
! 100: if (!isalpha(ch) &&
! 101: !(obj->o_pos.y == hero.y && obj->o_pos.x == hero.x)) {
! 102: obj->o_pos.y -= ydelta;
! 103: obj->o_pos.x -= xdelta;
! 104: }
! 105:
! 106: break;
! 107: }
! 108: }
! 109:
! 110:
! 111: /*
! 112: * fall:
! 113: * Drop an item someplace around here.
! 114: */
! 115:
! 116: void
! 117: fall(struct linked_list *item, bool pr)
! 118: {
! 119: register struct object *obj;
! 120: register struct room *rp;
! 121: register int i;
! 122: struct object *tobj;
! 123: struct linked_list *titem;
! 124: coord *fpos = NULL;
! 125:
! 126: obj = OBJPTR(item);
! 127: /*
! 128: * try to drop the item, look up to 3 squares away for now
! 129: */
! 130: for (i=1; i<4; i++) {
! 131: if ((fpos = fallpos(&obj->o_pos, FALSE, i)) != NULL)
! 132: break;
! 133: }
! 134:
! 135: if (fpos != NULL) {
! 136: if (obj->o_group) { /* try to add groups together */
! 137: for(titem=lvl_obj; titem!=NULL; titem=next(titem)) {
! 138: tobj = OBJPTR(titem);
! 139: if (tobj->o_group == obj->o_group &&
! 140: tobj->o_pos.y == fpos->y &&
! 141: tobj->o_pos.x == fpos->x) {
! 142: tobj->o_count += obj->o_count;
! 143: o_discard(item);
! 144: return;
! 145: }
! 146: }
! 147: }
! 148: mvaddch(fpos->y, fpos->x, obj->o_type);
! 149: obj->o_pos = *fpos;
! 150: if ((rp = roomin(&hero)) != NULL &&
! 151: lit_room(rp)) {
! 152: light(&hero);
! 153: mvwaddch(cw, hero.y, hero.x, PLAYER);
! 154: }
! 155: attach(lvl_obj, item);
! 156: return;
! 157: }
! 158: if (pr) {
! 159: msg("The %s vanishes as it hits the ground.",
! 160: weaps[obj->o_which].w_name);
! 161: }
! 162: o_discard(item);
! 163: }
! 164:
! 165: /*
! 166: * Does the missile hit the monster
! 167: */
! 168:
! 169: bool
! 170: hit_monster(int y, int x, struct object *obj, struct thing *tp)
! 171: {
! 172: static coord mp;
! 173:
! 174: mp.y = y;
! 175: mp.x = x;
! 176: if (tp == &player) {
! 177: /* Make sure there is a monster where it landed */
! 178: if (!isalpha(mvwinch(mw, y, x))) {
! 179: return(FALSE);
! 180: }
! 181:
! 182: /* Player hits monster */
! 183: return(fight(&mp, obj, TRUE));
! 184: } else {
! 185: if (!ce(mp, hero)) {
! 186: /* Monster hits monster */
! 187: return(skirmish(tp, &mp, obj, TRUE));
! 188: }
! 189:
! 190: /* Monster hits player */
! 191: return(attack(tp, obj, TRUE));
! 192: }
! 193: }
! 194:
! 195: /*
! 196: * init_weapon:
! 197: * Set up the initial goodies for a weapon
! 198: */
! 199:
! 200: void
! 201: init_weapon(struct object *weap, char type)
! 202: {
! 203: register struct init_weps *iwp;
! 204:
! 205: iwp = &weaps[type];
! 206: strcpy(weap->o_damage,iwp->w_dam);
! 207: strcpy(weap->o_hurldmg,iwp->w_hrl);
! 208: weap->o_launch = iwp->w_launch;
! 209: weap->o_flags = iwp->w_flags;
! 210: weap->o_weight = iwp->w_wght;
! 211: if (weap->o_flags & ISMANY) {
! 212: weap->o_count = rnd(8) + 8;
! 213: weap->o_group = newgrp();
! 214: } else {
! 215: weap->o_count = 1;
! 216: }
! 217: }
! 218:
! 219: /*
! 220: * missile:
! 221: * Fire a missile in a given direction
! 222: */
! 223:
! 224: void
! 225: missile(int ydelta, int xdelta, struct linked_list *item, struct thing *tp)
! 226: {
! 227: register struct object *obj;
! 228: register struct linked_list *nitem;
! 229: char ch;
! 230:
! 231: /*
! 232: * Get which thing we are hurling
! 233: */
! 234: if (item == NULL) {
! 235: return;
! 236: }
! 237: obj = OBJPTR(item);
! 238: if (obj->o_type == RELIC && obj->o_which == AXE_AKLAD) {
! 239: boomerang(ydelta, xdelta, item, tp);
! 240: return;
! 241: }
! 242:
! 243: if (!dropcheck(obj)) return; /* Can we get rid of it? */
! 244:
! 245: if(!(obj->o_flags & ISMISL)) {
! 246: for(;;) {
! 247: msg(terse ? "Really throw? (y or n): "
! 248: : "Do you really want to throw %s? (y or n): ",
! 249: inv_name(obj, TRUE));
! 250: mpos = 0;
! 251: ch = wgetch(cw);
! 252: if (ch == 'n' || ch == ESC) {
! 253: after = FALSE;
! 254: return;
! 255: }
! 256: if (ch == 'y')
! 257: break;
! 258: }
! 259: }
! 260: /*
! 261: * Get rid of the thing. If it is a non-multiple item object, or
! 262: * if it is the last thing, just drop it. Otherwise, create a new
! 263: * item with a count of one.
! 264: */
! 265: if (obj->o_count < 2) {
! 266: detach(tp->t_pack, item);
! 267: if (tp->t_pack == pack) {
! 268: inpack--;
! 269: }
! 270: }
! 271: else {
! 272: obj->o_count--;
! 273: nitem = (struct linked_list *) new_item(sizeof *obj);
! 274: obj = OBJPTR(nitem);
! 275: *obj = *(OBJPTR(item));
! 276: obj->o_count = 1;
! 277: item = nitem;
! 278: }
! 279: updpack(FALSE, tp);
! 280: do_motion(obj, ydelta, xdelta, tp);
! 281: /*
! 282: * AHA! Here it has hit something. If it is a wall or a door,
! 283: * or if it misses (combat) the monster, put it on the floor
! 284: */
! 285: if (!hit_monster(unc(obj->o_pos), obj, tp)) {
! 286: fall(item, TRUE);
! 287: }
! 288: else
! 289: o_discard(item);
! 290:
! 291: mvwaddch(cw, hero.y, hero.x, PLAYER);
! 292:
! 293: }
! 294:
! 295: /*
! 296: * num:
! 297: * Figure out the plus number for armor/weapons
! 298: */
! 299:
! 300: char *
! 301: num(int n1, int n2)
! 302: {
! 303: static char numbuf[LINELEN/2];
! 304:
! 305: if (n1 == 0 && n2 == 0) {
! 306: return "+0";
! 307: }
! 308: if (n2 == 0) {
! 309: sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
! 310: } else {
! 311: sprintf(numbuf, "%s%d, %s%d", n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2);
! 312: }
! 313: return(numbuf);
! 314: }
! 315:
! 316: /*
! 317: * wield:
! 318: * Pull out a certain weapon
! 319: */
! 320:
! 321: void
! 322: wield(void)
! 323: {
! 324: register struct linked_list *item;
! 325: register struct object *obj, *oweapon;
! 326:
! 327: /*
! 328: * It takes 2 movement periods to unwield a weapon and 2 movement
! 329: * periods to wield a weapon.
! 330: */
! 331: if (player.t_action != C_WIELD) {
! 332: player.t_action = C_WIELD;
! 333: player.t_using = NULL; /* Make sure this is NULL! */
! 334: if (cur_weapon != NULL) {
! 335: player.t_no_move = 2 * movement(&player);
! 336: return;
! 337: }
! 338: }
! 339:
! 340: if ((oweapon = cur_weapon) != NULL) {
! 341: /* At this point we have waited at least 2 units */
! 342: if (!dropcheck(cur_weapon)) {
! 343: cur_weapon = oweapon;
! 344: player.t_action = A_NIL;
! 345: return;
! 346: }
! 347: if (terse)
! 348: addmsg("Was ");
! 349: else
! 350: addmsg("You were ");
! 351: msg("wielding %s", inv_name(oweapon, TRUE));
! 352: }
! 353:
! 354: /* We we have something picked out? */
! 355: if (player.t_using == NULL) {
! 356: /* Now, what does he want to wield? */
! 357: if ((item = get_item(pack, "wield", WIELDABLE, FALSE, FALSE)) == NULL) {
! 358: player.t_action = A_NIL;
! 359: after = FALSE;
! 360: return;
! 361: }
! 362: player.t_using = item;
! 363: player.t_no_move = 2 * movement(&player);
! 364: return;
! 365: }
! 366:
! 367: /* We have waited our time, let's wield the weapon */
! 368: item = player.t_using;
! 369: player.t_using = NULL;
! 370: player.t_action = A_NIL;
! 371:
! 372: obj = OBJPTR(item);
! 373:
! 374: if (is_current(obj)) {
! 375: msg("Item in use.");
! 376: after = FALSE;
! 377: return;
! 378: }
! 379: if (player.t_ctype != C_FIGHTER &&
! 380: player.t_ctype != C_RANGER &&
! 381: player.t_ctype != C_PALADIN &&
! 382: obj->o_type == WEAPON &&
! 383: obj->o_which == TWOSWORD) {
! 384: switch (rnd(3)) {
! 385: case 0:
! 386: msg("Only fighter types can wield the two-handed sword.");
! 387: when 1:
! 388: msg("Your hand does not fit the two-handed sword.");
! 389: otherwise:
! 390: msg("You can not wield the two-handed sword.");
! 391: }
! 392: return;
! 393: }
! 394: if (player.t_ctype != C_FIGHTER &&
! 395: player.t_ctype != C_ASSASSIN &&
! 396: player.t_ctype != C_THIEF &&
! 397: player.t_ctype != C_MONK &&
! 398: obj->o_type == WEAPON &&
! 399: obj->o_which == BASWORD) {
! 400: switch (rnd(3)) {
! 401: case 0:
! 402: msg("Only thief types can wield the bastard sword.");
! 403: when 1:
! 404: msg("Your hand does not fit the bastard sword.");
! 405: otherwise:
! 406: msg("You can not wield the bastard sword.");
! 407: }
! 408: return;
! 409: }
! 410:
! 411: if (terse) {
! 412: addmsg("W");
! 413: } else {
! 414: addmsg("You are now w");
! 415: }
! 416: msg("ielding %s", inv_name(obj, TRUE));
! 417: cur_weapon = obj;
! 418: }
! 419:
CVSweb