diff srogue/trader.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 94a0d9dd5ce1
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/trader.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,497 @@
+/*
+ * Anything to do with trading posts & mazes
+ *
+ * @(#)trader.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdlib.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+#define NOTPRICED -1
+
+/*
+ * do_post:
+ *	Put a trading post room and stuff on the screen
+ */
+do_post()
+{
+	struct coord tp;
+	reg int i;
+	reg struct room *rp;
+	reg struct object *op;
+	reg struct linked_list *ll;
+
+	free_list(lvl_obj);		/* throw old items away */
+
+	for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
+		rp->r_goldval = 0;			/* no gold */
+		rp->r_nexits = 0;			/* no exits */
+		rp->r_flags = ISGONE;		/* kill all rooms */
+	}
+	rp = &rooms[0];					/* point to only room */
+	rp->r_flags = 0;				/* this room NOT gone */
+	rp->r_max.x = 40;
+	rp->r_max.y = 10;				/* 10 * 40 room */
+	rp->r_pos.x = (COLS - rp->r_max.x) / 2;	/* center horizontal */
+	rp->r_pos.y = 1;				/* 2nd line */
+	draw_room(rp);					/* draw the only room */
+	i = roll(4,10);					/* 10 to 40 items */
+	for (; i > 0 ; i--) {			/* place all the items */
+		ll = new_thing(FALSE, ANYTHING);		/* get something */
+		attach(lvl_obj, ll);
+		op = OBJPTR(ll);
+		setoflg(op, ISPOST);		/* object in trading post */
+		tp = *rnd_pos(rp);
+		op->o_pos = tp;
+		mvaddch(tp.y,tp.x,op->o_type);
+	}
+	trader = 0;
+	wmove(cw,12,0);
+	waddstr(cw,"Welcome to Friendly Fiend's Flea Market\n\r");
+	waddstr(cw,"=======================================\n\r");
+	waddstr(cw,"$: Prices object that you stand upon.\n\r");
+	waddstr(cw,"#: Buys the object that you stand upon.\n\r");
+	waddstr(cw,"%: Trades in something in your pack for gold.\n\r");
+	trans_line();
+}
+
+/*
+ * price_it:
+ *	Price the object that the hero stands on
+ */
+price_it()
+{
+	static char *bargain[] = {
+		"great bargain",
+		"quality product",
+		"exceptional find",
+	};
+	reg struct linked_list *item;
+	reg struct object *obj;
+	reg int worth;
+
+	if (!open_market())		/* after buying hours */
+		return FALSE;
+	if ((item = find_obj(hero.y,hero.x)) == NULL)
+		return FALSE;
+	obj = OBJPTR(item);
+	if (curprice == NOTPRICED) {
+		worth = get_worth(obj);
+		worth += 50 - rnd(100);
+		if (worth < 25)
+			worth = 25;
+		worth *= 3;							/* slightly expensive */
+		curprice = worth;					/* save price */
+		strcpy(curpurch, obj->o_typname);	/* save item */
+	}
+	msg("That %s is a %s for only %d pieces of gold", curpurch,
+	  bargain[rnd(3)], curprice);
+	return TRUE;
+}
+
+/*
+ * buy_it:
+ *	Buy the item on which the hero stands
+ */
+buy_it()
+{
+	reg int wh;
+
+	if (purse <= 0) {
+		msg("You have no money.");
+		return;
+	}
+	if (curprice < 0) {		/* if not yet priced */
+		wh = price_it();
+		if (!wh)			/* nothing to price */
+			return;
+		msg("Do you want to buy it? ");
+		do {
+			wh = readchar();
+			if (isupper(wh))
+				wh = tolower(wh);
+			if (wh == ESCAPE || wh == 'n') {
+				msg("");
+				return;
+			}
+		} until(wh == 'y');
+	}
+	mpos = 0;
+	if (curprice > purse) {
+		msg("You can't afford to buy that %s !",curpurch);
+		return;
+	}
+	/*
+	 * See if the hero has done all his transacting
+	 */
+	if (!open_market())
+		return;
+	/*
+	 * The hero bought the item here
+	 */
+	mpos = 0;
+	wh = add_pack(NULL,FALSE);	/* try to put it in his pack */
+	if (wh) {					/* he could get it */
+		purse -= curprice;		/* take his money */
+		++trader;				/* another transaction */
+		trans_line();			/* show remaining deals */
+		curprice = NOTPRICED;
+		curpurch[0] = '\0';
+	}
+}
+
+/*
+ * sell_it:
+ *	Sell an item to the trading post
+ */
+sell_it()
+{
+	reg struct linked_list *item;
+	reg struct object *obj;
+	reg int wo, ch;
+
+	if (!open_market())		/* after selling hours */
+		return;
+
+	if ((item = get_item("sell",0)) == NULL)
+		return;
+	obj = OBJPTR(item);
+	wo = get_worth(obj);
+	if (wo <= 0) {
+		mpos = 0;
+		msg("We don't buy those.");
+		return;
+	}
+	if (wo < 25)
+		wo = 25;
+	msg("Your %s is worth %d pieces of gold.", obj->o_typname, wo);
+	msg("Do you want to sell it? ");
+	do {
+		ch = readchar();
+		if (isupper(ch))
+			ch = tolower(ch);
+		if (ch == ESCAPE || ch == 'n') {
+			msg("");
+			return;
+		}
+	} until (ch == 'y');
+	mpos = 0;
+	if (drop(item) == TRUE) {		/* drop this item */	
+		nochange = FALSE;		/* show gold value */
+		purse += wo;			/* give him his money */
+		++trader;			/* another transaction */
+		wo = obj->o_count;
+		obj->o_count = 1;
+		msg("Sold %s",inv_name(obj,TRUE));
+		obj->o_count = wo;
+		trans_line();			/* show remaining deals */
+	}
+}
+
+/*
+ * open_market:
+ *	Retruns TRUE when ok do to transacting
+ */
+open_market()
+{
+	if (trader >= MAXPURCH) {
+		msg("The market is closed. The stairs are that-a-way.");
+		return FALSE;
+	}
+	else
+		return TRUE;
+}
+
+/*
+ * get_worth:
+ *	Calculate an objects worth in gold
+ */
+get_worth(obj)
+struct object *obj;
+{
+	reg int worth, wh;
+
+	worth = 0;
+	wh = obj->o_which;
+	switch (obj->o_type) {
+	case FOOD:
+		worth = 2;
+	when WEAPON:
+		if (wh < MAXWEAPONS) {
+			worth = w_magic[wh].mi_worth;
+			worth *= (2 + (4 * obj->o_hplus + 4 * obj->o_dplus));
+		}
+	when ARMOR:
+		if (wh < MAXARMORS) {
+			worth = a_magic[wh].mi_worth;
+			worth *= (1 + (10 * (armors[wh].a_class - obj->o_ac)));
+		}
+	when SCROLL:
+		if (wh < MAXSCROLLS)
+			worth = s_magic[wh].mi_worth;
+	when POTION:
+		if (wh < MAXPOTIONS)
+			worth = p_magic[wh].mi_worth;
+	when RING:
+		if (wh < MAXRINGS) {
+			worth = r_magic[wh].mi_worth;
+			if (magring(obj)) {
+				if (obj->o_ac > 0)
+					worth += obj->o_ac * 40;
+				else
+					worth = 50;
+			}
+		}
+	when STICK:
+		if (wh < MAXSTICKS) {
+			worth = ws_magic[wh].mi_worth;
+			worth += 20 * obj->o_charges;
+		}
+	when AMULET:
+		worth = 1000;
+	otherwise:
+		worth = 0;
+	}
+	if (worth < 0)
+		worth = 0;
+	if (o_on(obj, ISPROT))		/* 300% more for protected */
+		worth *= 3;
+	if (o_on(obj, ISBLESS))		/* 50% more for blessed */
+		worth = worth * 3 / 2;
+	return worth;
+}
+
+/*
+ * trans_line:
+ *	Show how many transactions the hero has left
+ */
+trans_line()
+{
+	sprintf(prbuf,"You have %d transactions remaining.",MAXPURCH-trader);
+	mvwaddstr(cw, LINES - 4, 0, prbuf);
+}
+
+/*
+ * domaze:
+ *	Draw the maze on this level.
+ */
+do_maze()
+{
+	struct coord tp;
+	reg int i, least;
+	reg struct room *rp;
+	bool treas;
+
+	for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
+		rp->r_goldval = 0;
+		rp->r_nexits = 0;			/* no exits */
+		rp->r_flags = ISGONE;		/* kill all rooms */
+	}
+	rp = &rooms[0];					/* point to only room */
+	rp->r_flags = ISDARK;			/* mazes always dark */
+	rp->r_pos.x = 0;				/* room fills whole screen */
+	rp->r_pos.y = 1;
+	rp->r_max.x = COLS - 1;
+	rp->r_max.y = LINES - 2;
+	rp->r_goldval = 500 + (rnd(10) + 1) * GOLDCALC;
+	draw_maze();				/* put maze into window */
+	rp->r_gold = *rnd_pos(rp);
+	mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);
+	if (rnd(100) < 3) {			/* 3% for treasure maze level */
+		treas = TRUE;
+		least = 6;
+		rp->r_flags |= ISTREAS;
+	}
+	else {						/* normal maze level */
+		least = 1;
+		treas = FALSE;
+	}
+	for (i = 0; i < level + least; i++)
+		if (treas || rnd(100) < 50)		/* put in some little buggers */
+			add_mon(rp, treas);
+}
+
+struct cell {
+	char y_pos;
+	char x_pos;
+};
+struct bordercells {
+	char num_pos;			/* number of frontier cells next to you */
+	struct cell conn[4];	/* the y,x position of above cell */
+} mborder;
+
+char *frontier, *bits;
+char *moffset(), *foffset();
+int tlines, tcols;
+
+/*
+ * draw_maze:
+ *	Generate and draw the maze on the screen
+ */
+draw_maze()
+{
+	reg int i, j, more;
+	reg char *ptr;
+
+	tlines = (LINES - 3) / 2;
+	tcols = (COLS - 1) / 2;
+	bits = ALLOC((LINES - 3) * (COLS - 1));
+	frontier = ALLOC(tlines * tcols);
+	ptr = frontier;
+	while (ptr < (frontier + (tlines * tcols)))
+		*ptr++ = TRUE;
+	for (i = 0; i < LINES - 3; i++) {
+		for (j = 0; j < COLS - 1; j++) {
+			if (i % 2 == 1 && j % 2 == 1)
+				*moffset(i, j) = FALSE;		/* floor */
+			else
+				*moffset(i, j) = TRUE;		/* wall */
+		}
+	}
+	for (i = 0; i < tlines; i++) {
+		for (j = 0; j < tcols; j++) {
+			do
+				more = findcells(i,j);
+			while(more != 0);
+		}
+	}
+	crankout();
+	FREE(frontier);
+	FREE(bits);
+}
+
+/*
+ * moffset:
+ *	Calculate memory address for bits
+ */
+char *
+moffset(y, x)
+int y, x;
+{
+	char *ptr;
+
+	ptr = bits + (y * (COLS - 1)) + x;
+	return ptr;
+}
+
+/*
+ * foffset:
+ *	Calculate memory address for frontier
+ */
+char *
+foffset(y, x)
+int y, x;
+{
+	char *ptr;
+
+	ptr = frontier + (y * tcols) + x;
+	return ptr;
+}
+
+/*
+ * findcells:
+ *	Figure out cells to open up 
+ */
+findcells(y,x)
+int x, y;
+{
+	reg int rtpos, i;
+
+	*foffset(y, x) = FALSE;
+	mborder.num_pos = 0;
+	if (y < tlines - 1) {				/* look below */
+		if (*foffset(y + 1, x)) {
+			mborder.conn[mborder.num_pos].y_pos = y + 1;
+			mborder.conn[mborder.num_pos].x_pos = x;
+			mborder.num_pos += 1;
+		}
+	}
+	if (y > 0) {						/* look above */
+		if (*foffset(y - 1, x)) {
+			mborder.conn[mborder.num_pos].y_pos = y - 1;
+			mborder.conn[mborder.num_pos].x_pos = x;
+			mborder.num_pos += 1;
+
+		}
+	}
+	if (x < tcols - 1) {					/* look right */
+		if (*foffset(y, x + 1)) {
+			mborder.conn[mborder.num_pos].y_pos = y;
+			mborder.conn[mborder.num_pos].x_pos = x + 1;
+			mborder.num_pos += 1;
+		}
+	}
+	if (x > 0) {						/* look left */
+		if (*foffset(y, x - 1)) {
+			mborder.conn[mborder.num_pos].y_pos = y;
+			mborder.conn[mborder.num_pos].x_pos = x - 1;
+			mborder.num_pos += 1;
+
+		}
+	}
+	if (mborder.num_pos == 0)			/* no neighbors available */
+		return 0;
+	else {
+		i = rnd(mborder.num_pos);
+		rtpos = mborder.num_pos - 1;
+		rmwall(mborder.conn[i].y_pos, mborder.conn[i].x_pos, y, x);
+		return rtpos;
+	}
+}
+
+/*
+ * rmwall:
+ *	Removes appropriate walls from the maze
+ */
+rmwall(newy, newx, oldy, oldx)
+int newy, newx, oldy, oldx;
+{
+	reg int xdif,ydif;
+	
+	xdif = newx - oldx;
+	ydif = newy - oldy;
+
+	*moffset((oldy * 2) + ydif + 1, (oldx * 2) + xdif + 1) = FALSE;
+	findcells(newy, newx);
+}
+
+
+/*
+ * crankout:
+ *	Does actual drawing of maze to window
+ */
+crankout()
+{
+	reg int x, y, i;
+
+	for (y = 0; y < LINES - 3; y++) {
+		move(y + 1, 0);
+		for (x = 0; x < COLS - 1; x++) {
+			if (*moffset(y, x)) {				/* here is a wall */
+				if (y == 0 || y == LINES - 4)	/* top or bottom line */
+					addch('-');
+				else if (x == 0 || x == COLS - 2)	/* left | right side */
+					addch('|');
+				else if (y % 2 == 0 && x % 2 == 0) {
+					if (*moffset(y, x - 1) || *moffset(y, x + 1))
+						addch('-');
+					else
+						addch('|');
+				}
+				else if (y % 2 == 0)
+					addch('-');
+				else
+					addch('|');
+			}
+			else
+				addch(FLOOR);
+		}
+	}
+}