/*
* 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 <string.h>
#include "rogue.h"
#include "rogue.ext"
#define NOTPRICED -1
bool open_market(void);
void trans_line(void);
void draw_maze(void);
int findcells(int y, int x);
void rmwall(int newy, int newx, int oldy, int oldx);
void crankout(void);
/*
* do_post:
* Put a trading post room and stuff on the screen
*/
void
do_post(void)
{
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
*/
bool
price_it(void)
{
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
*/
void
buy_it(void)
{
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
*/
void
sell_it(void)
{
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
*/
bool
open_market(void)
{
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
*/
int
get_worth(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
*/
void
trans_line(void)
{
sprintf(prbuf,"You have %d transactions remaining.",MAXPURCH-trader);
mvwaddstr(cw, LINES - 4, 0, prbuf);
}
/*
* domaze:
* Draw the maze on this level.
*/
void
do_maze(void)
{
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 {
unsigned 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(int y, int x);
char *foffset(int y, int x);
int tlines, tcols;
/*
* draw_maze:
* Generate and draw the maze on the screen
*/
void
draw_maze(void)
{
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(int y, int x)
{
char *ptr;
ptr = bits + (y * (COLS - 1)) + x;
return ptr;
}
/*
* foffset:
* Calculate memory address for frontier
*/
char *
foffset(int y, int x)
{
char *ptr;
ptr = frontier + (y * tcols) + x;
return ptr;
}
/*
* findcells:
* Figure out cells to open up
*/
int
findcells(int y, int x)
{
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
*/
void
rmwall(int newy, int newx, int oldy, int 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
*/
void
crankout(void)
{
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);
}
}
}