Annotation of early-roguelike/srogue/trader.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: * Anything to do with trading posts & mazes
3: *
4: * @(#)trader.c 9.0 (rdk) 7/17/84
5: *
6: * Super-Rogue
7: * Copyright (C) 1984 Robert D. Kindelberger
8: * All rights reserved.
9: *
10: * See the file LICENSE.TXT for full copyright and licensing information.
11: */
12:
13: #include <stdlib.h>
14: #include <string.h>
15: #include "rogue.h"
16: #include "rogue.ext"
17:
18: #define NOTPRICED -1
19:
20: bool open_market(void);
21: void trans_line(void);
22: void draw_maze(void);
23: int findcells(int y, int x);
24: void rmwall(int newy, int newx, int oldy, int oldx);
25: void crankout(void);
26:
27: /*
28: * do_post:
29: * Put a trading post room and stuff on the screen
30: */
31: void
32: do_post(void)
33: {
34: struct coord tp;
35: reg int i;
36: reg struct room *rp;
37: reg struct object *op;
38: reg struct linked_list *ll;
39:
40: free_list(lvl_obj); /* throw old items away */
41:
42: for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
43: rp->r_goldval = 0; /* no gold */
44: rp->r_nexits = 0; /* no exits */
45: rp->r_flags = ISGONE; /* kill all rooms */
46: }
47: rp = &rooms[0]; /* point to only room */
48: rp->r_flags = 0; /* this room NOT gone */
49: rp->r_max.x = 40;
50: rp->r_max.y = 10; /* 10 * 40 room */
51: rp->r_pos.x = (COLS - rp->r_max.x) / 2; /* center horizontal */
52: rp->r_pos.y = 1; /* 2nd line */
53: draw_room(rp); /* draw the only room */
54: i = roll(4,10); /* 10 to 40 items */
55: for (; i > 0 ; i--) { /* place all the items */
56: ll = new_thing(FALSE, ANYTHING); /* get something */
57: attach(lvl_obj, ll);
58: op = OBJPTR(ll);
59: setoflg(op, ISPOST); /* object in trading post */
60: tp = *rnd_pos(rp);
61: op->o_pos = tp;
62: mvaddch(tp.y,tp.x,op->o_type);
63: }
64: trader = 0;
65: wmove(cw,12,0);
66: waddstr(cw,"Welcome to Friendly Fiend's Flea Market\n\r");
67: waddstr(cw,"=======================================\n\r");
68: waddstr(cw,"$: Prices object that you stand upon.\n\r");
69: waddstr(cw,"#: Buys the object that you stand upon.\n\r");
70: waddstr(cw,"%: Trades in something in your pack for gold.\n\r");
71: trans_line();
72: }
73:
74: /*
75: * price_it:
76: * Price the object that the hero stands on
77: */
78: bool
79: price_it(void)
80: {
81: static char *bargain[] = {
82: "great bargain",
83: "quality product",
84: "exceptional find",
85: };
86: reg struct linked_list *item;
87: reg struct object *obj;
88: reg int worth;
89:
90: if (!open_market()) /* after buying hours */
91: return FALSE;
92: if ((item = find_obj(hero.y,hero.x)) == NULL)
93: return FALSE;
94: obj = OBJPTR(item);
95: if (curprice == NOTPRICED) {
96: worth = get_worth(obj);
97: worth += 50 - rnd(100);
98: if (worth < 25)
99: worth = 25;
100: worth *= 3; /* slightly expensive */
101: curprice = worth; /* save price */
102: strcpy(curpurch, obj->o_typname); /* save item */
103: }
104: msg("That %s is a %s for only %d pieces of gold", curpurch,
105: bargain[rnd(3)], curprice);
106: return TRUE;
107: }
108:
109: /*
110: * buy_it:
111: * Buy the item on which the hero stands
112: */
113: void
114: buy_it(void)
115: {
116: reg int wh;
117:
118: if (purse <= 0) {
119: msg("You have no money.");
120: return;
121: }
122: if (curprice < 0) { /* if not yet priced */
123: wh = price_it();
124: if (!wh) /* nothing to price */
125: return;
126: msg("Do you want to buy it? ");
127: do {
128: wh = readchar();
129: if (isupper(wh))
130: wh = tolower(wh);
131: if (wh == ESCAPE || wh == 'n') {
132: msg("");
133: return;
134: }
135: } until(wh == 'y');
136: }
137: mpos = 0;
138: if (curprice > purse) {
139: msg("You can't afford to buy that %s !",curpurch);
140: return;
141: }
142: /*
143: * See if the hero has done all his transacting
144: */
145: if (!open_market())
146: return;
147: /*
148: * The hero bought the item here
149: */
150: mpos = 0;
151: wh = add_pack(NULL,FALSE); /* try to put it in his pack */
152: if (wh) { /* he could get it */
153: purse -= curprice; /* take his money */
154: ++trader; /* another transaction */
155: trans_line(); /* show remaining deals */
156: curprice = NOTPRICED;
157: curpurch[0] = '\0';
158: }
159: }
160:
161: /*
162: * sell_it:
163: * Sell an item to the trading post
164: */
165: void
166: sell_it(void)
167: {
168: reg struct linked_list *item;
169: reg struct object *obj;
170: reg int wo, ch;
171:
172: if (!open_market()) /* after selling hours */
173: return;
174:
175: if ((item = get_item("sell",0)) == NULL)
176: return;
177: obj = OBJPTR(item);
178: wo = get_worth(obj);
179: if (wo <= 0) {
180: mpos = 0;
181: msg("We don't buy those.");
182: return;
183: }
184: if (wo < 25)
185: wo = 25;
186: msg("Your %s is worth %d pieces of gold.", obj->o_typname, wo);
187: msg("Do you want to sell it? ");
188: do {
189: ch = readchar();
190: if (isupper(ch))
191: ch = tolower(ch);
192: if (ch == ESCAPE || ch == 'n') {
193: msg("");
194: return;
195: }
196: } until (ch == 'y');
197: mpos = 0;
198: if (drop(item) == TRUE) { /* drop this item */
199: nochange = FALSE; /* show gold value */
200: purse += wo; /* give him his money */
201: ++trader; /* another transaction */
202: wo = obj->o_count;
203: obj->o_count = 1;
204: msg("Sold %s",inv_name(obj,TRUE));
205: obj->o_count = wo;
206: trans_line(); /* show remaining deals */
207: }
208: }
209:
210: /*
211: * open_market:
212: * Retruns TRUE when ok do to transacting
213: */
214: bool
215: open_market(void)
216: {
217: if (trader >= MAXPURCH) {
218: msg("The market is closed. The stairs are that-a-way.");
219: return FALSE;
220: }
221: else
222: return TRUE;
223: }
224:
225: /*
226: * get_worth:
227: * Calculate an objects worth in gold
228: */
229: int
230: get_worth(struct object *obj)
231: {
232: reg int worth, wh;
233:
234: worth = 0;
235: wh = obj->o_which;
236: switch (obj->o_type) {
237: case FOOD:
238: worth = 2;
239: when WEAPON:
240: if (wh < MAXWEAPONS) {
241: worth = w_magic[wh].mi_worth;
242: worth *= (2 + (4 * obj->o_hplus + 4 * obj->o_dplus));
243: }
244: when ARMOR:
245: if (wh < MAXARMORS) {
246: worth = a_magic[wh].mi_worth;
247: worth *= (1 + (10 * (armors[wh].a_class - obj->o_ac)));
248: }
249: when SCROLL:
250: if (wh < MAXSCROLLS)
251: worth = s_magic[wh].mi_worth;
252: when POTION:
253: if (wh < MAXPOTIONS)
254: worth = p_magic[wh].mi_worth;
255: when RING:
256: if (wh < MAXRINGS) {
257: worth = r_magic[wh].mi_worth;
258: if (magring(obj)) {
259: if (obj->o_ac > 0)
260: worth += obj->o_ac * 40;
261: else
262: worth = 50;
263: }
264: }
265: when STICK:
266: if (wh < MAXSTICKS) {
267: worth = ws_magic[wh].mi_worth;
268: worth += 20 * obj->o_charges;
269: }
270: when AMULET:
271: worth = 1000;
272: otherwise:
273: worth = 0;
274: }
275: if (worth < 0)
276: worth = 0;
277: if (o_on(obj, ISPROT)) /* 300% more for protected */
278: worth *= 3;
279: if (o_on(obj, ISBLESS)) /* 50% more for blessed */
280: worth = worth * 3 / 2;
281: return worth;
282: }
283:
284: /*
285: * trans_line:
286: * Show how many transactions the hero has left
287: */
288: void
289: trans_line(void)
290: {
291: sprintf(prbuf,"You have %d transactions remaining.",MAXPURCH-trader);
292: mvwaddstr(cw, LINES - 4, 0, prbuf);
293: }
294:
295: /*
296: * domaze:
297: * Draw the maze on this level.
298: */
299: void
300: do_maze(void)
301: {
302: struct coord tp;
303: reg int i, least;
304: reg struct room *rp;
305: bool treas;
306:
307: for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
308: rp->r_goldval = 0;
309: rp->r_nexits = 0; /* no exits */
310: rp->r_flags = ISGONE; /* kill all rooms */
311: }
312: rp = &rooms[0]; /* point to only room */
313: rp->r_flags = ISDARK; /* mazes always dark */
314: rp->r_pos.x = 0; /* room fills whole screen */
315: rp->r_pos.y = 1;
316: rp->r_max.x = COLS - 1;
317: rp->r_max.y = LINES - 2;
318: rp->r_goldval = 500 + (rnd(10) + 1) * GOLDCALC;
319: draw_maze(); /* put maze into window */
320: rp->r_gold = *rnd_pos(rp);
321: mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);
322: if (rnd(100) < 3) { /* 3% for treasure maze level */
323: treas = TRUE;
324: least = 6;
325: rp->r_flags |= ISTREAS;
326: }
327: else { /* normal maze level */
328: least = 1;
329: treas = FALSE;
330: }
331: for (i = 0; i < level + least; i++)
332: if (treas || rnd(100) < 50) /* put in some little buggers */
333: add_mon(rp, treas);
334: }
335:
336: struct cell {
337: char y_pos;
338: char x_pos;
339: };
340: struct bordercells {
341: unsigned char num_pos; /* number of frontier cells next to you */
342: struct cell conn[4]; /* the y,x position of above cell */
343: } mborder;
344:
345: char *frontier, *bits;
346: char *moffset(int y, int x);
347: char *foffset(int y, int x);
348: int tlines, tcols;
349:
350: /*
351: * draw_maze:
352: * Generate and draw the maze on the screen
353: */
354: void
355: draw_maze(void)
356: {
357: reg int i, j, more;
358: reg char *ptr;
359:
360: tlines = (LINES - 3) / 2;
361: tcols = (COLS - 1) / 2;
362: bits = ALLOC((LINES - 3) * (COLS - 1));
363: frontier = ALLOC(tlines * tcols);
364: ptr = frontier;
365: while (ptr < (frontier + (tlines * tcols)))
366: *ptr++ = TRUE;
367: for (i = 0; i < LINES - 3; i++) {
368: for (j = 0; j < COLS - 1; j++) {
369: if (i % 2 == 1 && j % 2 == 1)
370: *moffset(i, j) = FALSE; /* floor */
371: else
372: *moffset(i, j) = TRUE; /* wall */
373: }
374: }
375: for (i = 0; i < tlines; i++) {
376: for (j = 0; j < tcols; j++) {
377: do
378: more = findcells(i,j);
379: while(more != 0);
380: }
381: }
382: crankout();
383: FREE(frontier);
384: FREE(bits);
385: }
386:
387: /*
388: * moffset:
389: * Calculate memory address for bits
390: */
391: char *
392: moffset(int y, int x)
393: {
394: char *ptr;
395:
396: ptr = bits + (y * (COLS - 1)) + x;
397: return ptr;
398: }
399:
400: /*
401: * foffset:
402: * Calculate memory address for frontier
403: */
404: char *
405: foffset(int y, int x)
406: {
407: char *ptr;
408:
409: ptr = frontier + (y * tcols) + x;
410: return ptr;
411: }
412:
413: /*
414: * findcells:
415: * Figure out cells to open up
416: */
417: int
418: findcells(int y, int x)
419: {
420: reg int rtpos, i;
421:
422: *foffset(y, x) = FALSE;
423: mborder.num_pos = 0;
424: if (y < tlines - 1) { /* look below */
425: if (*foffset(y + 1, x)) {
426: mborder.conn[mborder.num_pos].y_pos = y + 1;
427: mborder.conn[mborder.num_pos].x_pos = x;
428: mborder.num_pos += 1;
429: }
430: }
431: if (y > 0) { /* look above */
432: if (*foffset(y - 1, x)) {
433: mborder.conn[mborder.num_pos].y_pos = y - 1;
434: mborder.conn[mborder.num_pos].x_pos = x;
435: mborder.num_pos += 1;
436:
437: }
438: }
439: if (x < tcols - 1) { /* look right */
440: if (*foffset(y, x + 1)) {
441: mborder.conn[mborder.num_pos].y_pos = y;
442: mborder.conn[mborder.num_pos].x_pos = x + 1;
443: mborder.num_pos += 1;
444: }
445: }
446: if (x > 0) { /* look left */
447: if (*foffset(y, x - 1)) {
448: mborder.conn[mborder.num_pos].y_pos = y;
449: mborder.conn[mborder.num_pos].x_pos = x - 1;
450: mborder.num_pos += 1;
451:
452: }
453: }
454: if (mborder.num_pos == 0) /* no neighbors available */
455: return 0;
456: else {
457: i = rnd(mborder.num_pos);
458: rtpos = mborder.num_pos - 1;
459: rmwall(mborder.conn[i].y_pos, mborder.conn[i].x_pos, y, x);
460: return rtpos;
461: }
462: }
463:
464: /*
465: * rmwall:
466: * Removes appropriate walls from the maze
467: */
468: void
469: rmwall(int newy, int newx, int oldy, int oldx)
470: {
471: reg int xdif,ydif;
472:
473: xdif = newx - oldx;
474: ydif = newy - oldy;
475:
476: *moffset((oldy * 2) + ydif + 1, (oldx * 2) + xdif + 1) = FALSE;
477: findcells(newy, newx);
478: }
479:
480:
481: /*
482: * crankout:
483: * Does actual drawing of maze to window
484: */
485: void
486: crankout(void)
487: {
488: reg int x, y, i;
489:
490: for (y = 0; y < LINES - 3; y++) {
491: move(y + 1, 0);
492: for (x = 0; x < COLS - 1; x++) {
493: if (*moffset(y, x)) { /* here is a wall */
494: if (y == 0 || y == LINES - 4) /* top or bottom line */
495: addch('-');
496: else if (x == 0 || x == COLS - 2) /* left | right side */
497: addch('|');
498: else if (y % 2 == 0 && x % 2 == 0) {
499: if (*moffset(y, x - 1) || *moffset(y, x + 1))
500: addch('-');
501: else
502: addch('|');
503: }
504: else if (y % 2 == 0)
505: addch('-');
506: else
507: addch('|');
508: }
509: else
510: addch(FLOOR);
511: }
512: }
513: }
CVSweb