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;<