diff srogue/things.c @ 36:2128c7dc8a40

Import Super-Rogue 9.0 from the Roguelike Restoration Project (r1490)
author elwin
date Thu, 25 Nov 2010 12:21:41 +0000
parents
children 984f7d5afb6f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/things.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,460 @@
+/*
+ * Contains functions for dealing with things like
+ * potions and scrolls
+ *
+ * @(#)things.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "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 <ctype.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+
+/*
+ * inv_name:
+ *	Return the name of something as it would appear in an inventory.
+ */
+char *
+inv_name(obj, drop)
+struct object *obj;
+bool drop;
+{
+	reg char *pb, *tn, *pl;
+	reg int wh, knowit;
+	char nm[3], *inm, *q;
+
+	wh = obj->o_which;
+	knowit = FALSE;
+	if (obj->o_count > 1)
+		pl = "s";
+	else
+		pl = "";
+	if (obj->o_count > 1)
+		sprintf(nm, "%d", obj->o_count);
+	else
+		strcpy(nm, "A");
+	tn = obj->o_typname;
+	q = "";
+	switch(obj->o_type) {
+	case SCROLL:
+		sprintf(prbuf, "%s %s%s ", nm, tn, pl);
+		pb = &prbuf[strlen(prbuf)];
+		if (s_know[wh] || o_on(obj,ISPOST)) {
+			knowit = TRUE;
+			sprintf(pb, "of %s", s_magic[wh].mi_name);
+		}
+		else if (s_guess[wh])
+			sprintf(pb, "called %s", s_guess[wh]);
+		else
+			sprintf(pb, "titled '%s'", s_names[wh]);
+    when POTION:
+		sprintf(prbuf, "%s %s%s ", nm, tn, pl);
+		pb = &prbuf[strlen(prbuf)];
+		if (p_know[wh] || o_on(obj, ISPOST)) {
+			sprintf(pb, "of %s", p_magic[wh].mi_name);
+			knowit = TRUE;
+			if (p_know[wh]) {
+				pb = &prbuf[strlen(prbuf)];
+				sprintf(pb,"(%s)",p_colors[wh]);
+			}
+		}
+		else if (p_guess[wh])
+			sprintf(pb,"called %s(%s)", p_guess[wh],p_colors[wh]);
+		else
+			sprintf(prbuf,"%s%s %s %s%s", nm, vowelstr(p_colors[wh]),
+				p_colors[wh], tn, pl);
+	when FOOD:
+		if (wh == 1) {
+			if (obj->o_count == 1)
+				q = vowelstr(fruit);
+			sprintf(prbuf, "%s%s %s%s", nm, q, fruit, pl);
+		}
+		else {
+			if (obj->o_count == 1)
+				sprintf(prbuf, "Some %s", tn);
+			else
+				sprintf(prbuf, "%s rations of %s", nm, tn);
+		}
+		knowit = TRUE;
+	when WEAPON:
+		inm = w_magic[wh].mi_name;
+		strcpy(prbuf, nm);
+		if (obj->o_count == 1)
+			q = vowelstr(inm);
+		pb = &prbuf[strlen(prbuf)];
+		if (o_on(obj,ISKNOW | ISPOST)) {
+			knowit = TRUE;
+			sprintf(pb, " %s %s", num(obj->o_hplus, obj->o_dplus), inm);
+		}
+		else
+			sprintf(pb, "%s %s", q, inm);
+		strcat(prbuf, pl);
+	when ARMOR:
+		inm = a_magic[wh].mi_name;
+		if (o_on(obj,ISKNOW | ISPOST)) {
+			knowit = TRUE;
+			sprintf(prbuf, "%s %s",num(armors[wh].a_class - obj->o_ac, 0),
+				inm);
+		}
+		else
+			sprintf(prbuf, "%s", inm);
+	when AMULET:
+		strcpy(prbuf, "The Amulet of Yendor");
+	when STICK: {
+		struct rod *rd;
+
+		rd = &ws_stuff[wh];
+		sprintf(prbuf, "A %s ", rd->ws_type);
+		pb = &prbuf[strlen(prbuf)];
+		if (ws_know[wh] || o_on(obj, ISPOST)) {
+			knowit = TRUE;
+			sprintf(pb,"of %s%s",ws_magic[wh].mi_name,charge_str(obj));
+			if (ws_know[wh]) {
+				pb = &prbuf[strlen(prbuf)];
+				sprintf(pb,"(%s)",rd->ws_made);
+			}
+		}
+		else if (ws_guess[wh])
+			sprintf(pb, "called %s(%s)", ws_guess[wh], rd->ws_made);
+		else
+			sprintf(prbuf, "A%s %s %s", vowelstr(rd->ws_made),
+				rd->ws_made, rd->ws_type);
+	}
+    when RING:
+		if (r_know[wh] || o_on(obj, ISPOST)) {
+			knowit = TRUE;
+			sprintf(prbuf, "A%s %s of %s", ring_num(obj), tn,
+			  r_magic[wh].mi_name);
+			if (r_know[wh]) {
+				pb = &prbuf[strlen(prbuf)];
+				sprintf(pb,"(%s)", r_stones[wh]);
+			}
+		}
+		else if (r_guess[wh])
+			sprintf(prbuf,"A %s called %s(%s)",tn, r_guess[wh],
+				r_stones[wh]);
+		else
+			sprintf(prbuf,"A%s %s %s",vowelstr(r_stones[wh]), 
+				r_stones[wh], tn);
+	otherwise:
+		sprintf(prbuf,"Something bizarre %s", unctrl(obj->o_type));
+	}
+	if (obj == cur_armor)
+		strcat(prbuf, " (being worn)");
+	if (obj == cur_weapon)
+		strcat(prbuf, " (weapon in hand)");
+	if (obj == cur_ring[LEFT])
+		strcat(prbuf, " (on left hand)");
+	else if (obj == cur_ring[RIGHT])
+		strcat(prbuf, " (on right hand)");
+	if (drop && isupper(prbuf[0]))
+		prbuf[0] = tolower(prbuf[0]);
+	else if (!drop && islower(*prbuf))
+		*prbuf = toupper(*prbuf);
+	if (o_on(obj, ISPROT))
+		strcat(prbuf, " [!]");
+	if (o_on(obj, ISPOST))
+		strcat(prbuf, " [$]");
+	if (knowit) {
+		if (o_on(obj, ISCURSED))
+			strcat(prbuf, " [-]");
+		else if (o_on(obj, ISBLESS))
+			strcat(prbuf, " [+]");
+	}
+	if (!drop)
+		strcat(prbuf, ".");
+	return prbuf;
+}
+
+/*
+ * money:
+ *	Add to characters purse
+ */
+money()
+{
+	reg struct room *rp;
+	reg struct linked_list *item;
+	reg struct thing *tp;
+
+	rp = player.t_room;
+	if (rp != NULL && ce(hero, rp->r_gold)) {
+		msg("%d gold pieces.", rp->r_goldval);
+		purse += rp->r_goldval;
+		rp->r_goldval = 0;
+		cmov(rp->r_gold);
+		addch(FLOOR);
+		/*
+		 * once gold is taken, all monsters will chase him
+		 */
+		for (item = mlist; item != NULL; item = next(item)) {
+			tp = THINGPTR(item);
+			if (rnd(100) < 70 && tp->t_room == rp && !iswearing(R_STEALTH)
+			  && ((tp->t_flags & (ISMEAN | ISGREED)) || rnd(1000) < 20))
+				runto(&tp->t_pos, &hero);
+		}
+	}
+	else
+		msg("That gold must have been counterfeit.");
+}
+
+
+/*
+ * drop:
+ *	put something down
+ */
+drop(item)
+struct linked_list *item;
+{
+	reg char ch;
+	reg struct linked_list *ll, *nll;
+	reg struct object *op;
+
+	if (item == NULL) {
+		ch = mvinch(hero.y, hero.x);
+		if (ch != FLOOR && ch != PASSAGE && ch != POOL) {
+			msg("There is something there already.");
+			after = FALSE;
+			return SOMTHERE;
+		}
+		if ((ll = get_item("drop", 0)) == NULL)
+			return FALSE;
+	}
+	else {
+		ll = item;
+	}
+	op = OBJPTR(ll);
+	if (!dropcheck(op))
+		return CANTDROP;
+	/*
+	 * Take it out of the pack
+	 */
+	if (op->o_count >= 2 && op->o_type != WEAPON) {
+		nll = new_item(sizeof *op);
+		op->o_count--;
+		op->o_vol = itemvol(op);
+		op = OBJPTR(nll);
+		*op = *(OBJPTR(ll));
+		op->o_count = 1;
+		op->o_vol = itemvol(op);
+		ll = nll;
+	}
+	else {
+		detach(pack, ll);
+	}
+	if (ch == POOL) {
+		msg("%s sinks out of sight.",inv_name(op, TRUE));
+		discard(ll);
+	}
+	else {			/* put on dungeon floor */
+		if (levtype == POSTLEV) {
+			op->o_pos = hero;	/* same place as hero */
+			fall(ll,FALSE);
+			if (item == NULL)	/* if item wasn't sold */
+				msg("Thanks for your donation to the Fiend's flea market.");
+		}
+		else {
+			attach(lvl_obj, ll);
+			mvaddch(hero.y, hero.x, op->o_type);
+			op->o_pos = hero;
+			msg("Dropped %s", inv_name(op, TRUE));
+		}
+	}
+	updpack();			/* new pack weight */
+	return TRUE;
+}
+
+
+/*
+ * dropcheck:
+ *	Do special checks for dropping or unweilding|unwearing|unringing
+ */
+dropcheck(op)
+struct object *op;
+{
+	if (op == NULL)
+		return TRUE;
+	if (levtype == POSTLEV) {
+		if (o_on(op,ISCURSED) && o_on(op,ISKNOW)) {
+			msg("The trader does not accept shoddy merchandise.");
+			return FALSE;
+		}
+		else {
+			cur_null(op);	/* update cur_weapon, etc */
+			return TRUE;
+		}
+	}
+	if (op != cur_armor && op != cur_weapon
+	  && op != cur_ring[LEFT] && op != cur_ring[RIGHT])
+		return TRUE;
+	if (o_on(op,ISCURSED)) {
+		msg("You can't.  It appears to be cursed.");
+		return FALSE;
+	}
+	if (op == cur_weapon)
+		cur_weapon = NULL;
+	else if (op == cur_armor) {
+		waste_time();
+		cur_armor = NULL;
+	}
+	else if (op == cur_ring[LEFT] || op == cur_ring[RIGHT])
+		toss_ring(op);
+	return TRUE;
+}
+
+
+/*
+ * new_thing:
+ *	Return a new thing
+ */
+struct linked_list *
+new_thing(treas, type, which)
+int type, which;
+bool treas;
+{
+	struct linked_list *item;
+	struct magic_item *mi;
+	struct object *cur;
+	int chance, whi;
+
+	item = new_item(sizeof *cur);
+	cur = OBJPTR(item);
+	basic_init(cur);
+	if (type == DONTCARE) {
+		if (++no_food > 4 && !treas)
+			whi = TYP_FOOD;
+		else
+			whi = pick_one(things);
+	}
+	else {
+		whi = getindex(type);
+	}
+	mi = thnginfo[whi].mf_magic;
+	if (which == DONTCARE) {
+		which = 0;
+		if (mi != NULL)
+			which = pick_one(mi);
+	}
+	cur->o_typname = things[whi].mi_name;
+	cur->o_weight = things[whi].mi_wght;
+	switch (whi) {
+		case TYP_AMULET:
+			cur->o_type = AMULET;
+			cur->o_hplus = 500;
+			strcpy(cur->o_hurldmg,"80d8");	/* if thrown, WOW!!! */
+			cur->o_vol = itemvol(cur);
+		when TYP_POTION:
+			cur->o_type = POTION;
+			cur->o_which = which;
+			cur->o_count += extras();
+			cur->o_vol = itemvol(cur);
+		when TYP_SCROLL:
+			cur->o_type = SCROLL;
+			cur->o_which = which;
+			cur->o_count += extras();
+			cur->o_vol = itemvol(cur);
+		when TYP_FOOD:
+			no_food = 0;
+			initfood(cur);
+		when TYP_WEAPON:
+			cur->o_which = which;
+			init_weapon(cur, which);
+			if ((chance = rnd(100)) < 10) {
+				setoflg(cur,ISCURSED);
+				cur->o_hplus -= rnd(3)+1;
+				cur->o_dplus -= rnd(3)+1;
+			}
+			else if (chance < 15) {
+				cur->o_hplus += rnd(3)+1;
+				cur->o_dplus += rnd(3)+1;
+			}
+		when TYP_ARMOR:
+			cur->o_which = which;
+			initarmor(cur, which);
+			if ((chance = rnd(100)) < 20) {
+				setoflg(cur,ISCURSED);
+				cur->o_ac += rnd(3)+1;
+			}
+			else if (chance < 30)
+				cur->o_ac -= rnd(3)+1;
+		when TYP_RING:
+			cur->o_which = which;
+			init_ring(cur, FALSE);
+		when TYP_STICK:
+		default:
+			cur->o_which = which;
+			fix_stick(cur);
+	}
+	return item;
+}
+
+/*
+ * basic_init:
+ *	Set all params of an object to the basic values.
+ */
+basic_init(cur)
+struct object *cur;
+{
+	cur->o_ac = 11;
+	cur->o_count = 1;
+	cur->o_launch = 0;
+	cur->o_typname = NULL;
+	cur->o_group = newgrp();
+	cur->o_weight = cur->o_vol = 0;
+	cur->o_hplus = cur->o_dplus = 0;
+	strcpy(cur->o_damage,"0d0");
+	strcpy(cur->o_hurldmg,"0d0");
+	cur->o_flags = cur->o_type = cur->o_which = 0;
+}
+
+/*
+ * extras:
+ *	Return the number of extra items to be created
+ */
+extras()
+{
+	reg int i;
+
+	i = rnd(100);
+	if (i < 4)			/* 4% for 2 more */
+		return 2;
+	else if (i < 11)	/* 7% for 1 more */
+		return 1;
+	else				/* otherwise no more */
+		return 0;
+}
+
+
+/*
+ * pick_one:
+ * 	Pick an item out of a list of nitems possible magic items
+ */
+pick_one(mag)
+struct magic_item *mag;
+{
+	reg struct magic_item *start;
+	reg int i;
+
+	start = mag;
+	for (i = rnd(1000); mag->mi_name != NULL; mag++) {
+		if (i < mag->mi_prob)
+			break;
+		if (mag->mi_name == NULL) {
+			if (author() || wizard) {
+				for (mag = start; mag->mi_name != NULL; mag++)
+					msg("%s: %d%%", mag->mi_name, mag->mi_prob);
+			}
+			mag = start;
+		}
+	}
+	return mag - start;
+}