Mercurial > hg > early-roguelike
diff rogue5/things.c @ 33:f502bf60e6e4
Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Mon, 24 May 2010 20:10:59 +0000 |
parents | |
children | ded75a57405c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue5/things.c Mon May 24 20:10:59 2010 +0000 @@ -0,0 +1,716 @@ +/* + * Contains functions for dealing with things like potions, scrolls, + * and other items. + * + * @(#)things.c 4.53 (Berkeley) 02/05/99 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +#include <stdlib.h> +#include <curses.h> +#include <string.h> +#include <ctype.h> +#include "rogue.h" + +/* + * inv_name: + * Return the name of something as it would appear in an + * inventory. + */ +char * +inv_name(const THING *obj, int drop) +{ + char *pb; + struct obj_info *op; + const char *sp; + int which; + + pb = prbuf; + which = obj->o_which; + switch (obj->o_type) + { + case POTION: + nameit(obj, "potion", p_colors[which], &pot_info[which], nullstr); + when RING: + nameit(obj, "ring", r_stones[which], &ring_info[which], ring_num); + when STICK: + nameit(obj, ws_type[which], ws_made[which], &ws_info[which], charge_str); + when SCROLL: + if (obj->o_count == 1) + { + strcpy(pb, "A scroll "); + pb = &prbuf[9]; + } + else + { + sprintf(pb, "%d scrolls ", obj->o_count); + pb = &prbuf[strlen(prbuf)]; + } + op = &scr_info[which]; + if (op->oi_know) + sprintf(pb, "of %s", op->oi_name); + else if (op->oi_guess) + sprintf(pb, "called %s", op->oi_guess); + else + sprintf(pb, "titled '%s'", s_names[which]); + when FOOD: + if (which == 1) + if (obj->o_count == 1) + sprintf(pb, "A%s %s", vowelstr(fruit), fruit); + else + sprintf(pb, "%d %ss", obj->o_count, fruit); + else + if (obj->o_count == 1) + strcpy(pb, "Some food"); + else + sprintf(pb, "%d rations of food", obj->o_count); + when WEAPON: + sp = weap_info[which].oi_name; + if (obj->o_count > 1) + sprintf(pb, "%d ", obj->o_count); + else + sprintf(pb, "A%s ", vowelstr(sp)); + pb = &prbuf[strlen(prbuf)]; + if (obj->o_flags & ISKNOW) + sprintf(pb, "%s %s", num(obj->o_hplus,obj->o_dplus,WEAPON), sp); + else + sprintf(pb, "%s", sp); + if (obj->o_count > 1) + strcat(pb, "s"); + if (obj->o_label != NULL) + { + pb = &prbuf[strlen(prbuf)]; + sprintf(pb, " called %s", obj->o_label); + } + when ARMOR: + sp = arm_info[which].oi_name; + if (obj->o_flags & ISKNOW) + { + sprintf(pb, "%s %s [", + num(a_class[which] - obj->o_arm, 0, ARMOR), sp); + if (!terse) + strcat(pb, "protection "); + pb = &prbuf[strlen(prbuf)]; + sprintf(pb, "%d]", 10 - obj->o_arm); + } + else + sprintf(pb, "%s", sp); + if (obj->o_label != NULL) + { + pb = &prbuf[strlen(prbuf)]; + sprintf(pb, " called %s", obj->o_label); + } + when AMULET: + strcpy(pb, "The Amulet of Yendor"); + when GOLD: + sprintf(prbuf, "%d Gold pieces", obj->o_goldval); +#ifdef MASTER + otherwise: + debug("Picked up something funny %s", unctrl(obj->o_type)); + sprintf(pb, "Something bizarre %s", unctrl(obj->o_type)); +#endif + } + if (inv_describe) + { + if (obj == cur_armor) + strcat(pb, " (being worn)"); + if (obj == cur_weapon) + strcat(pb, " (weapon in hand)"); + if (obj == cur_ring[LEFT]) + strcat(pb, " (on left hand)"); + else if (obj == cur_ring[RIGHT]) + strcat(pb, " (on right hand)"); + } + if (drop && isupper((int)prbuf[0])) + prbuf[0] = (char) tolower(prbuf[0]); + else if (!drop && islower((int)*prbuf)) + *prbuf = (char) toupper(*prbuf); + prbuf[MAXSTR-1] = '\0'; + return prbuf; +} + +/* + * drop: + * Put something down + */ + +void +drop(void) +{ + int ch; + THING *obj; + + ch = chat(hero.y, hero.x); + if (ch != FLOOR && ch != PASSAGE) + { + after = FALSE; + msg("there is something there already"); + return; + } + if ((obj = get_item("drop", 0)) == NULL) + return; + if (!dropcheck(obj)) + return; + obj = leave_pack(obj, TRUE, !ISMULT(obj->o_type)); + /* + * Link it into the level object list + */ + attach(lvl_obj, obj); + chat(hero.y, hero.x) = obj->o_type; + flat(hero.y, hero.x) |= F_DROPPED; + obj->o_pos = hero; + if (obj->o_type == AMULET) + amulet = FALSE; + msg("dropped %s", inv_name(obj, TRUE)); +} + +/* + * dropcheck: + * Do special checks for dropping or unweilding|unwearing|unringing + */ +int +dropcheck(const THING *obj) +{ + if (obj == NULL) + return TRUE; + if (obj != cur_armor && obj != cur_weapon + && obj != cur_ring[LEFT] && obj != cur_ring[RIGHT]) + return TRUE; + if (obj->o_flags & ISCURSED) + { + msg("you can't. It appears to be cursed"); + return FALSE; + } + if (obj == cur_weapon) + cur_weapon = NULL; + else if (obj == cur_armor) + { + waste_time(); + cur_armor = NULL; + } + else + { + cur_ring[obj == cur_ring[LEFT] ? LEFT : RIGHT] = NULL; + switch (obj->o_which) + { + case R_ADDSTR: + chg_str(-obj->o_arm); + break; + case R_SEEINVIS: + unsee(); + extinguish(unsee); + break; + } + } + return TRUE; +} + +/* + * new_thing: + * Return a new thing + */ +THING * +new_thing(void) +{ + THING *cur; + int r; + + cur = new_item(); + cur->o_hplus = 0; + cur->o_dplus = 0; + strncpy(cur->o_damage, "0x0", sizeof(cur->o_damage)); + strncpy(cur->o_hurldmg, "0x0", sizeof(cur->o_hurldmg)); + cur->o_arm = 11; + cur->o_count = 1; + cur->o_group = 0; + cur->o_flags = 0; + /* + * Decide what kind of object it will be + * If we haven't had food for a while, let it be food. + */ + switch (no_food > 3 ? 2 : pick_one(things, NUMTHINGS)) + { + case 0: + cur->o_type = POTION; + cur->o_which = pick_one(pot_info, MAXPOTIONS); + when 1: + cur->o_type = SCROLL; + cur->o_which = pick_one(scr_info, MAXSCROLLS); + when 2: + cur->o_type = FOOD; + no_food = 0; + if (rnd(10) != 0) + cur->o_which = 0; + else + cur->o_which = 1; + when 3: + init_weapon(cur, pick_one(weap_info, MAXWEAPONS)); + if ((r = rnd(100)) < 10) + { + cur->o_flags |= ISCURSED; + cur->o_hplus -= rnd(3) + 1; + } + else if (r < 15) + cur->o_hplus += rnd(3) + 1; + when 4: + cur->o_type = ARMOR; + cur->o_which = pick_one(arm_info, MAXARMORS); + cur->o_arm = a_class[cur->o_which]; + if ((r = rnd(100)) < 20) + { + cur->o_flags |= ISCURSED; + cur->o_arm += rnd(3) + 1; + } + else if (r < 28) + cur->o_arm -= rnd(3) + 1; + when 5: + cur->o_type = RING; + cur->o_which = pick_one(ring_info, MAXRINGS); + switch (cur->o_which) + { + case R_ADDSTR: + case R_PROTECT: + case R_ADDHIT: + case R_ADDDAM: + if ((cur->o_arm = rnd(3)) == 0) + { + cur->o_arm = -1; + cur->o_flags |= ISCURSED; + } + when R_AGGR: + case R_TELEPORT: + cur->o_flags |= ISCURSED; + } + when 6: + cur->o_type = STICK; + cur->o_which = pick_one(ws_info, MAXSTICKS); + fix_stick(cur); +#ifdef MASTER + otherwise: + debug("Picked a bad kind of object"); + wait_for(stdscr, ' '); +#endif + } + return cur; +} + +/* + * pick_one: + * Pick an item out of a list of nitems possible objects + */ +int +pick_one(const struct obj_info *info, int nitems) +{ + const struct obj_info *end; + const struct obj_info *start; + int i; + + start = info; + for (end = &info[nitems], i = rnd(100); info < end; info++) + if (i < info->oi_prob) + break; + if (info == end) + { +#ifdef MASTER + if (wizard) + { + msg("bad pick_one: %d from %d items", i, nitems); + for (info = start; info < end; info++) + msg("%s: %d%%", info->oi_name, info->oi_prob); + } +#endif + info = start; + } + return (int)(info - start); +} + +/* + * discovered: + * list what the player has discovered in this game of a certain type + */ +static int line_cnt = 0; + +static int newpage = FALSE; + +static const char *lastfmt, *lastarg; + + +void +discovered(void) +{ + int ch; + int disc_list; + + do { + disc_list = FALSE; + if (!terse) + addmsg("for "); + addmsg("what type"); + if (!terse) + addmsg(" of object do you want a list"); + msg("? (* for all)"); + ch = readchar(); + switch (ch) + { + case ESCAPE: + msg(""); + return; + case POTION: + case SCROLL: + case RING: + case STICK: + case '*': + disc_list = TRUE;<