Mercurial > hg > early-roguelike
diff rogue3/weapons.c @ 0:527e2150eaf0
Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Tue, 13 Oct 2009 13:33:34 +0000 |
parents | |
children | 84651832f967 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/weapons.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,311 @@ +/* + * Functions for dealing with problems brought about by weapons + * + * @(#)weapons.c 3.17 (Berkeley) 6/15/81 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include "curses.h" +#include <ctype.h> +#include <string.h> +#include "rogue.h" + +#define NONE 100 + +char *w_names[MAXWEAPONS] = { + "mace", + "long sword", + "int bow", + "arrow", + "dagger", + "rock", + "two handed sword", + "sling", + "dart", + "crossbow", + "crossbow bolt", + "spear", +}; + +static struct init_weps { + char *iw_dam; + char *iw_hrl; + int iw_launch; + int iw_flags; +} init_dam[MAXWEAPONS] = { + "2d4", "1d3", NONE, 0, /* Mace */ + "1d10", "1d2", NONE,0, /* Long sword */ + "1d1", "1d1", NONE, 0, /* Bow */ + "1d1", "1d6", BOW, ISMANY|ISMISL, /* Arrow */ + "1d6", "1d4", NONE, ISMISL, /* Dagger */ + "1d2", "1d4", SLING,ISMANY|ISMISL, /* Rock */ + "3d6", "1d2", NONE, 0, /* 2h sword */ + "0d0", "0d0", NONE, 0, /* Sling */ + "1d1", "1d3", NONE, ISMANY|ISMISL, /* Dart */ + "1d1", "1d1", NONE, 0, /* Crossbow */ + "1d2", "1d10", CROSSBOW, ISMANY|ISMISL,/* Crossbow bolt */ + "1d8", "1d6", NONE, ISMISL, /* Spear */ +}; + +/* + * missile: + * Fire a missile in a given direction + */ + +void +missile(int ydelta, int xdelta) +{ + struct object *obj; + struct linked_list *item, *nitem; + + /* + * Get which thing we are hurling + */ + if ((item = get_item("throw", WEAPON)) == NULL) + return; + obj = (struct object *) ldata(item); + if (!dropcheck(obj) || is_current(obj)) + return; + /* + * Get rid of the thing. If it is a non-multiple item object, or + * if it is the last thing, just drop it. Otherwise, create a new + * item with a count of one. + */ + if (obj->o_count < 2) + { + detach(pack, item); + inpack--; + } + else + { + obj->o_count--; + if (obj->o_group == 0) + inpack--; + nitem = (struct linked_list *) new_item(sizeof *obj); + obj = (struct object *) ldata(nitem); + *obj = *((struct object *) ldata(item)); + obj->o_count = 1; + item = nitem; + } + do_motion(obj, ydelta, xdelta); + /* + * AHA! Here it has hit something. If it is a wall or a door, + * or if it misses (combat) the mosnter, put it on the floor + */ + if (!isupper(mvwinch(mw, obj->o_pos.y, obj->o_pos.x)) + || !hit_monster(unc(obj->o_pos), obj)) + fall(item, TRUE); + mvwaddch(cw, hero.y, hero.x, PLAYER); +} + +/* + * do the actual motion on the screen done by an object traveling + * across the room + */ +void +do_motion(struct object *obj, int ydelta, int xdelta) +{ + /* + * Come fly with us ... + */ + obj->o_pos = hero; + for (;;) + { + int ch; + + /* + * Erase the old one + */ + if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)) && + mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') + mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, + show(obj->o_pos.y, obj->o_pos.x)); + /* + * Get the new position + */ + obj->o_pos.y += ydelta; + obj->o_pos.x += xdelta; + if (step_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR) + { + /* + * It hasn't hit anything yet, so display it + * If it alright. + */ + if (cansee(unc(obj->o_pos)) && + mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') + { + mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type); + draw(cw); + } + continue; + } + break; + } +} + +/* + * fall: + * Drop an item someplace around here. + */ + +void +fall(struct linked_list *item, int pr) +{ + struct object *obj; + struct room *rp; + static coord fpos; + + obj = (struct object *) ldata(item); + if (fallpos(&obj->o_pos, &fpos, TRUE)) + { + mvaddch(fpos.y, fpos.x, obj->o_type); + obj->o_pos = fpos; + if ((rp = roomin(&hero)) != NULL && !(rp->r_flags & ISDARK)) + { + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + } + attach(lvl_obj, item); + return; + } + if (pr) + if (obj->o_type == WEAPON) /* BUGFUX: Identification trick */ + msg("Your %s vanishes as it hits the ground.", w_names[obj->o_which]); + else + msg("%s vanishes as it hits the ground.", inv_name(obj,TRUE)); + discard(item); +} + +/* + * init_weapon: + * Set up the initial goodies for a weapon + */ + +void +init_weapon(struct object *weap, int type) +{ + struct init_weps *iwp; + + iwp = &init_dam[type]; + strcpy(weap->o_damage,iwp->iw_dam); + strcpy(weap->o_hurldmg,iwp->iw_hrl); + weap->o_launch = iwp->iw_launch; + weap->o_flags = iwp->iw_flags; + if (weap->o_flags & ISMANY) + { + weap->o_count = rnd(8) + 8; + weap->o_group = newgrp(); + } + else + weap->o_count = 1; +} + +/* + * Does the missile hit the monster + */ + +int +hit_monster(int y, int x, struct object *obj) +{ + static coord mp; + + mp.y = y; + mp.x = x; + return fight(&mp, winat(y, x), obj, TRUE); +} + +/* + * num: + * Figure out the plus number for armor/weapons + */ + +char * +num(int n1, int n2) +{ + static char numbuf[80]; + + if (n1 == 0 && n2 == 0) + return "+0"; + if (n2 == 0) + sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1); + else + sprintf(numbuf, "%s%d,%s%d", + n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2); + return numbuf; +} + +/* + * wield: + * Pull out a certain weapon + */ + +void +wield() +{ + struct linked_list *item; + struct object *obj, *oweapon; + + oweapon = cur_weapon; + if (!dropcheck(cur_weapon)) + { + cur_weapon = oweapon; + return; + } + cur_weapon = oweapon; + if ((item = get_item("wield", WEAPON)) == NULL) + { +bad: + after = FALSE; + return; + } + + obj = (struct object *) ldata(item); + if (obj->o_type == ARMOR) + { + msg("You can't wield armor"); + goto bad; + } + if (is_current(obj)) + goto bad; + + if (terse) + addmsg("W"); + else + addmsg("You are now w"); + msg("ielding %s", inv_name(obj, TRUE)); + cur_weapon = obj; +} + +/* + * pick a random position around the give (y, x) coordinates + */ +int +fallpos(coord *pos, coord *newpos, int passages) +{ + int y, x, cnt, ch; + + cnt = 0; + for (y = pos->y - 1; y <= pos->y + 1; y++) + for (x = pos->x - 1; x <= pos->x + 1; x++) + { + /* + * check to make certain the spot is empty, if it is, + * put the object there, set it in the level list + * and re-draw the room if he can see it + */ + if (y == hero.y && x == hero.x) + continue; + if (((ch = winat(y, x)) == FLOOR || (passages && ch == PASSAGE)) + && rnd(++cnt) == 0) + { + newpos->y = y; + newpos->x = x; + } + } + return (cnt != 0); +}