Annotation of early-roguelike/urogue/weapons.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: weapons.c - Functions for dealing with problems brought about by weapons
! 3:
! 4: UltraRogue: The Ultimate Adventure in the Dungeons of Doom
! 5: Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
! 6: All rights reserved.
! 7:
! 8: Based on "Advanced Rogue"
! 9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
! 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 <ctype.h>
! 20: #include <string.h>
! 21: #include "rogue.h"
! 22:
! 23: /*
! 24: missile()
! 25: Fire a missile in a given direction
! 26: */
! 27:
! 28: void
! 29: missile(int ydelta, int xdelta, struct linked_list *item, struct thing *tp)
! 30: {
! 31: struct object *obj;
! 32: struct linked_list *nitem;
! 33:
! 34: if (item == NULL) /* Get which thing we are hurling */
! 35: return;
! 36:
! 37: obj = OBJPTR(item);
! 38:
! 39: if (!dropcheck(obj) || is_current(obj))
! 40: return;
! 41:
! 42: /*
! 43: * Get rid of the thing. If it is a non-multiple item object, or if
! 44: * it is the last thing, just drop it. Otherwise, create a new item
! 45: * with a count of one.
! 46: */
! 47:
! 48: if (obj->o_count < 2)
! 49: {
! 50: if (tp->t_pack == pack)
! 51: rem_pack(obj);
! 52: else
! 53: detach(tp->t_pack, item);
! 54: }
! 55: else
! 56: {
! 57: obj->o_count--;
! 58: nitem = (struct linked_list *) new_item(sizeof *obj);
! 59: obj = OBJPTR(nitem);
! 60: *obj = *(OBJPTR(item));
! 61: obj->o_count = 1;
! 62: item = nitem;
! 63: }
! 64:
! 65: switch (obj->o_type)
! 66: {
! 67: case ARTIFACT:
! 68: has_artifact &= ~(1 << obj->o_which);
! 69: break;
! 70:
! 71: case SCROLL:
! 72: if (obj->o_which == S_SCARE && obj->o_flags & ISBLESSED)
! 73: obj->o_flags &= ~ISBLESSED;
! 74: else
! 75: obj->o_flags |= ISCURSED;
! 76: }
! 77:
! 78: updpack();
! 79: obj->o_pos = do_motion(obj->o_type, ydelta, xdelta, tp);
! 80:
! 81: /*
! 82: * AHA! Here it has hit something. If it is a wall or a door, or if
! 83: * it misses (combat) the monster, put it on the floor
! 84: */
! 85:
! 86: if (!hit_monster(obj->o_pos.y, obj->o_pos.x, obj, tp))
! 87: {
! 88: if (obj->o_type == WEAPON && obj->o_which == GRENADE)
! 89: {
! 90: hearmsg("BOOOM!");
! 91: aggravate();
! 92:
! 93: if (ntraps + 1 < 2 * MAXTRAPS &&
! 94: fallpos(obj->o_pos, &traps[ntraps].tr_pos))
! 95: {
! 96: mvaddch(traps[ntraps].tr_pos.y, traps[ntraps].tr_pos.x,
! 97: TRAPDOOR);
! 98: traps[ntraps].tr_type = TRAPDOOR;
! 99: traps[ntraps].tr_flags = ISFOUND;
! 100: traps[ntraps].tr_show = TRAPDOOR;
! 101: ntraps++;
! 102: light(&hero);
! 103: }
! 104: discard(item);
! 105: }
! 106: else if (obj->o_flags & ISLOST)
! 107: {
! 108: if (obj->o_type == WEAPON)
! 109: addmsg("The %s", weaps[obj->o_which].w_name);
! 110: else
! 111: addmsg(inv_name(obj, LOWERCASE));
! 112:
! 113: msg(" vanishes in a puff of greasy smoke.");
! 114: discard(item);
! 115: }
! 116: else
! 117: {
! 118: fall(&player, item, TRUE, TRUE);
! 119:
! 120: if (obj->o_flags & CANRETURN)
! 121: msg("You have %s.", inv_name(obj, LOWERCASE));
! 122: }
! 123: }
! 124: else if (obj->o_flags & ISOWNED)
! 125: {
! 126: add_pack(item, NOMESSAGE);
! 127: msg("You have %s.", inv_name(obj, LOWERCASE));
! 128: }
! 129:
! 130: mvwaddch(cw, hero.y, hero.x, PLAYER);
! 131: }
! 132:
! 133: /*
! 134: do_motion()
! 135: do the actual motion on the screen done by an object
! 136: traveling across the room
! 137: */
! 138:
! 139: coord
! 140: do_motion(int ob, int ydelta, int xdelta, struct thing *tp)
! 141: {
! 142: coord pos;
! 143: /* Come fly with us ... */
! 144:
! 145: pos = tp->t_pos;
! 146:
! 147: for (;;)
! 148: {
! 149: int ch;
! 150:
! 151: /* Erase the old one */
! 152:
! 153: if (!ce(pos, tp->t_pos) &&
! 154: cansee(pos.y, pos.x) &&
! 155: mvwinch(cw, pos.y, pos.x) != ' ')
! 156: {
! 157: mvwaddch(cw, pos.y, pos.x, show(pos.y, pos.x));
! 158: }
! 159:
! 160: /* Get the new position */
! 161:
! 162: pos.y += ydelta;
! 163: pos.x += xdelta;
! 164:
! 165: if (shoot_ok(ch = winat(pos.y, pos.x)) &&
! 166: ch != DOOR && !ce(pos, hero))
! 167: {
! 168: /* It hasn't hit anything yet, so display it if it alright. */
! 169:
! 170: if (cansee(pos.y, pos.x) &&
! 171: mvwinch(cw, pos.y, pos.x) != ' ')
! 172: {
! 173: mvwaddch(cw, pos.y, pos.x, ob);
! 174: wrefresh(cw);
! 175: }
! 176:
! 177: continue;
! 178:
! 179: }
! 180: break;
! 181: }
! 182:
! 183: return(pos);
! 184: }
! 185:
! 186: /*
! 187: fall()
! 188: Drop an item someplace around here.
! 189: */
! 190:
! 191: void
! 192: fall(struct thing *tp, struct linked_list *item, int pr, int player_owned)
! 193: {
! 194: struct object *obj;
! 195: struct room *rp;
! 196: coord fpos;
! 197:
! 198: obj = OBJPTR(item);
! 199: rp = roomin(tp->t_pos);
! 200:
! 201: if (player_owned && obj->o_flags & CANRETURN)
! 202: {
! 203: add_pack(item, NOMESSAGE);
! 204: msg("You have %s.", inv_name(obj, LOWERCASE));
! 205: return;
! 206: }
! 207: else if (fallpos(obj->o_pos, &fpos))
! 208: {
! 209: if (obj->o_flags & CANBURN && obj->o_type == WEAPON
! 210: && obj->o_which == MOLOTOV
! 211: && ntraps + 1 < 2 * MAXTRAPS)
! 212: {
! 213: mvaddch(fpos.y, fpos.x, FIRETRAP);
! 214: traps[ntraps].tr_type = FIRETRAP;
! 215: traps[ntraps].tr_flags = ISFOUND;
! 216: traps[ntraps].tr_show = FIRETRAP;
! 217: traps[ntraps].tr_pos = fpos;
! 218: ntraps++;
! 219:
! 220: if (rp != NULL)
! 221: rp->r_flags &= ~ISDARK;
! 222: }
! 223: else
! 224: {
! 225: obj->o_pos = fpos;
! 226: add_obj(item, fpos.y, fpos.x);
! 227: }
! 228:
! 229: if (rp != NULL &&
! 230: (!(rp->r_flags & ISDARK) ||
! 231: (rp->r_flags & HASFIRE)))
! 232: {
! 233: light(&hero);
! 234: mvwaddch(cw, hero.y, hero.x, PLAYER);
! 235: }
! 236: return;
! 237: }
! 238:
! 239: /* get here only if there isn't a place to put it */
! 240:
! 241: if (pr)
! 242: {
! 243: if (cansee(obj->o_pos.y, obj->o_pos.x))
! 244: {
! 245: if (obj->o_type == WEAPON)
! 246: addmsg("The %s", weaps[obj->o_which].w_name);
! 247: else
! 248: addmsg(inv_name(obj, LOWERCASE));
! 249:
! 250: msg(" vanishes as it hits the ground.");
! 251: }
! 252: }
! 253: discard(item);
! 254: }
! 255:
! 256: /*
! 257: init_weapon()
! 258: Set up the initial goodies for a weapon
! 259: */
! 260:
! 261: void
! 262: init_weapon(struct object *weap, int type)
! 263: {
! 264: struct init_weps *iwp = &weaps[type];
! 265:
! 266: weap->o_damage = iwp->w_dam;
! 267: weap->o_hurldmg = iwp->w_hrl;
! 268: weap->o_launch = iwp->w_launch;
! 269: weap->o_flags = iwp->w_flags;
! 270: weap->o_weight = iwp->w_wght;
! 271:
! 272: if (weap->o_flags & ISMANY)
! 273: {
! 274: weap->o_count = rnd(8) + 8;
! 275: weap->o_group = ++group;
! 276: }
! 277: else
! 278: weap->o_count = 1;
! 279: }
! 280:
! 281: /*
! 282: hit_monster()
! 283: does the missile hit the target?
! 284: */
! 285:
! 286: int
! 287: hit_monster(int y, int x, struct object *weapon, struct thing *thrower)
! 288: {
! 289: struct linked_list *mon;
! 290: coord target;
! 291:
! 292: target.y = y;
! 293: target.x = x;
! 294:
! 295: if (thrower == &player)
! 296: return(fight(&target, weapon, THROWN));
! 297:
! 298: if (ce(target, hero))
! 299: {
! 300: if (good_monster(*thrower))
! 301: {
! 302: if (on(*thrower, ISFAMILIAR))
! 303: msg("Please get out of the way, Master! I nearly hit you.");
! 304: else
! 305: msg("Get out of the way %s!", whoami);
! 306:
! 307: return(FALSE);
! 308: }
! 309:
! 310: return(attack(thrower, weapon, THROWN));
! 311: }
! 312:
! 313: if ((mon = find_mons(y, x)) != NULL)
! 314: return(mon_mon_attack(thrower, mon, weapon, THROWN));
! 315: else
! 316: return(FALSE);
! 317: }
! 318:
! 319:
! 320: /*
! 321: num()
! 322: Figure out the plus number for armor/weapons
! 323: */
! 324:
! 325: char *
! 326: num(int n1, int n2, char *buf)
! 327: {
! 328: if (buf == NULL)
! 329: return("UltraRogue Error #104");
! 330:
! 331: if (n1 == 0 && n2 == 0)
! 332: {
! 333: strcpy(buf,"+0");
! 334: return(buf);
! 335: }
! 336:
! 337: if (n2 == 0)
! 338: sprintf(buf, "%s%d", n1 < 0 ? "" : "+", n1);
! 339: else
! 340: sprintf(buf, "%s%d, %s%d", n1 < 0 ? "" : "+",
! 341: n1, n2 < 0 ? "" : "+", n2);
! 342:
! 343: return(buf);
! 344: }
! 345:
! 346: /*
! 347: wield()
! 348: Pull out a certain weapon
! 349: */
! 350:
! 351: void
! 352: wield(void)
! 353: {
! 354: struct linked_list *item;
! 355: struct object *obj, *oweapon;
! 356:
! 357: oweapon = cur_weapon;
! 358:
! 359: if (!dropcheck(cur_weapon))
! 360: {
! 361: cur_weapon = oweapon;
! 362: return;
! 363: }
! 364:
! 365: cur_weapon = oweapon;
! 366:
! 367: if ((item = get_item("wield", WEAPON)) == NULL)
! 368: {
! 369: after = FALSE;
! 370: return;
! 371: }
! 372:
! 373: obj = OBJPTR(item);
! 374:
! 375: if (is_current(obj))
! 376: {
! 377: after = FALSE;
! 378: return;
! 379: }
! 380:
! 381: wield_ok(&player, obj, TRUE);
! 382:
! 383: msg("You are now wielding %s.", inv_name(obj, LOWERCASE));
! 384:
! 385: cur_weapon = obj;
! 386: }
! 387:
! 388: /*
! 389: fallpos()
! 390: pick a random position around the given (y, x) coordinates
! 391: */
! 392:
! 393: int
! 394: fallpos(coord pos, coord *newpos) /*ARGSUSED*/
! 395: {
! 396: int y, x, cnt;
! 397: coord places[9];
! 398:
! 399: cnt = 0;
! 400:
! 401: /* look for all the places that qualify */
! 402:
! 403: for (y = pos.y - 1; y <= pos.y + 1; y++)
! 404: {
! 405: for (x = pos.x - 1; x <= pos.x + 1; x++)
! 406: {
! 407: switch(CCHAR(mvwinch(stdscr,y,x)))
! 408: {
! 409: case GOLD:
! 410: case POTION:
! 411: case SCROLL:
! 412: case FOOD:
! 413: case WEAPON:
! 414: case ARMOR:
! 415: case RING:
! 416: case STICK:
! 417: case FLOOR:
! 418: case PASSAGE:
! 419: case ARTIFACT:
! 420: places[cnt].y = y;
! 421: places[cnt].x = x;
! 422: cnt++;
! 423: }
! 424: }
! 425: }
! 426:
! 427: /* now, pick one of the places, if there are any */
! 428:
! 429: if (cnt > 0)
! 430: {
! 431: int which = rnd(cnt);
! 432:
! 433: newpos->y = places[which].y;
! 434: newpos->x = places[which].x;
! 435:
! 436: debug("Dropping object at %d, %d", newpos->y, newpos->x);
! 437: }
! 438:
! 439: return(cnt);
! 440: }
! 441:
! 442: /*
! 443: wield_ok()
! 444: enforce player class weapons restrictions
! 445: */
! 446:
! 447: int
! 448: wield_ok(struct thing *wieldee, struct object *obj, int print_message)
! 449: {
! 450: int ret_val = TRUE;
! 451: int class_type = wieldee->t_ctype;
! 452:
! 453: if (obj->o_type != WEAPON)
! 454: {
! 455: ret_val = FALSE;
! 456: return(ret_val);
! 457: }
! 458: else
! 459: switch (class_type)
! 460: {
! 461: case C_MAGICIAN: /* need one hand free */
! 462: case C_ILLUSION:
! 463: if (obj->o_flags & ISTWOH)
! 464: ret_val = FALSE;
! 465: break;
! 466:
! 467: case C_THIEF: /* need portable weapon */
! 468: case C_ASSASIN:
! 469: case C_NINJA:
! 470: if (obj->o_flags & ISTWOH)
! 471: ret_val = FALSE;
! 472: break;
! 473:
! 474: case C_CLERIC: /* No sharp weapons */
! 475: if (obj->o_flags & ISSHARP)
! 476: ret_val = FALSE;
! 477: break;
! 478:
! 479: case C_DRUID: /* No non-silver metal weapons */
! 480: if (obj->o_flags & ISMETAL && !(obj->o_flags & ISSILVER))
! 481: ret_val = FALSE;
! 482: break;
! 483:
! 484: case C_PALADIN: /* must wield sharp stuff */
! 485: if ((obj->o_flags & ISSHARP) == FALSE)
! 486: ret_val = FALSE;
! 487: break;
! 488:
! 489: case C_FIGHTER: /* wield anything */
! 490: case C_RANGER:
! 491: case C_MONSTER:
! 492: break;
! 493:
! 494: default: /* Unknown class */
! 495: debug("Unknown class %d.", class_type);
! 496: break;
! 497: }
! 498:
! 499: if (itemweight(obj) > 18 * pstats.s_str)
! 500: {
! 501: if (wieldee == &player && print_message == TRUE)
! 502: msg("That is too heavy for you to swing effectively!");
! 503:
! 504: ret_val = FALSE;
! 505: return(ret_val);
! 506: }
! 507:
! 508: if (ret_val == FALSE && print_message == MESSAGE)
! 509: switch (class_type)
! 510: {
! 511: case C_MAGICIAN:
! 512: case C_ILLUSION:
! 513: msg("You'll find it hard to cast spells while wielding that!");
! 514: break;
! 515:
! 516: case C_THIEF:
! 517: case C_ASSASIN:
! 518: case C_NINJA:
! 519: msg("Don't expect to backstab anyone while wielding that!");
! 520: break;
! 521:
! 522: case C_CLERIC:
! 523: case C_DRUID:
! 524: case C_PALADIN:
! 525: msg("Your god strongly disapproves of your wielding that!");
! 526: break;
! 527:
! 528: case C_FIGHTER:
! 529: case C_RANGER:
! 530: case C_MONSTER:
! 531: break;
! 532: }
! 533:
! 534: return(ret_val);
! 535: }
! 536:
! 537: /*
! 538: shoot_ok()
! 539: returns true if it is ok for type to shoot over ch
! 540: */
! 541:
! 542: int
! 543: shoot_ok(int ch)
! 544: {
! 545: switch(ch)
! 546: {
! 547: case ' ':
! 548: case '|':
! 549: case '-':
! 550: case SECRETDOOR:
! 551: return(FALSE);
! 552:
! 553: default:
! 554: return(!isalpha(ch));
! 555: }
! 556: }
CVSweb