There should only be two changes in behavior: arogue7/fight.c, arogue7/fight.c: a to-hit bonus is now correctly applied to characters who are not monks instead of monks who are not empty-handed. urogue/fight.c: fixed an interaction with the "debug" macro that could cause the wrong message to be displayed.
512 lines
10 KiB
C
512 lines
10 KiB
C
/*
|
|
* 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)
|
|
{
|
|
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;
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|