Annotation of early-roguelike/urogue/trader.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: trader.c - Anything to do with trading posts
3:
4: UltraRogue: The Ultimate Adventure in the Dungeons of Doom
5: Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
6: All rights reserved.
7:
8: Based on "Advanced Rogue"
9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
10: All rights reserved.
11:
12: Based on "Rogue: Exploring the Dungeons of Doom"
13: Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
14: All rights reserved.
15:
16: See the file LICENSE.TXT for full copyright and licensing information.
17: */
18:
19: #include <string.h>
20: #include <stdlib.h>
21: #include <ctype.h>
22: #include "rogue.h"
23:
24: #define EFFECTIVE_PURSE ((player.t_ctype==C_PALADIN)?(9 * purse / 10) : purse)
25:
26: /*
27: do_post()
28: Buy and sell things in a trading post
29: */
30:
31: void
32: display_postinfo(void)
33: {
34: wclear(hw);
35: wstandout(hw);
36: mvwaddstr(hw, 0, COLS / 2 - 30,
37: "Welcome to Friendly Fiend's Flea Market" );
38: wstandend(hw);
39: wclrtoeol(hw);
40: trans_line();
41: }
42:
43: void
44: do_post(void)
45: {
46: int bad_letter = FALSE;
47:
48: player.t_trans = 0;
49:
50: for (;;)
51: {
52: if (!open_market())
53: return;
54:
55: display_postinfo();
56:
57: if (bad_letter)
58: {
59: bad_letter = FALSE;
60: wstandout(hw);
61: mvwaddstr(hw, 7, 0, "Type 'i' or 'I' to inventory, "
62: "'l' to leave, 'b' to buy, or 's' to sell");
63: wstandend(hw);
64: }
65:
66: mvwaddstr(hw, 6, 0, "Do you wish to buy, sell, inventory, or leave?");
67: wrefresh(hw);
68:
69: switch(readcharw(hw))
70: {
71: case 'b':
72: mvwaddstr(hw, 7, 0,
73: "Lets go into the buying section of the store...");
74: touchwin(hw);
75: wrefresh(hw);
76: buy_it('\0', ISNORMAL);
77: break;
78:
79: case 's':
80: mvwaddstr(hw, 7, 0,
81: "Lets go into the selling section of the store...");
82: touchwin(hw);
83: wrefresh(hw);
84: sell_it();
85: break;
86:
87: case 'i':
88: inventory(pack, '*');
89: break;
90:
91: case 'I':
92: wclear(hw);
93: wrefresh(hw);
94: inventory(pack, 0);
95: msg(" ");
96: msg("");
97: break;
98:
99: case 'l':
100: wclear(hw);
101: wrefresh(hw);
102: return;
103:
104: default:
105: bad_letter = TRUE;
106: break;
107: }
108: }
109: }
110:
111: void
112: buy_it(char itemtype, int flags)
113: {
114: int i;
115: int blessed = flags & ISBLESSED;
116: int cursed = flags & ISCURSED;
117: int is_spell = flags & SCR_MAGIC;
118: int array_size; /* # of items within type */
119: int which_type = 0; /* Which type to buy */
120: int which_one; /* Which one within type */
121: int plus_or_minus = 0; /* for magic items */
122: const struct magic_item *magic_array = NULL;
123: struct linked_list *item;
124: struct object *obj;
125: char buf[2 * LINELEN];
126:
127: buy_more:
128:
129: display_postinfo();
130:
131: do
132: {
133: array_size = 0;
134:
135: if (itemtype == '\0')
136: {
137: mpos = 0;
138: wmove(hw,10,0);
139: wclrtoeol(hw);
140: mvwaddstr(hw, 11, 0, "WHAT\tTYPE\n! Potion\n? Scroll\n"
141: "= Ring\n/ Stick\n] Armor\n) Weapon\n: Food");
142:
143: if (wizard)
144: mvwaddstr(hw, 19, 0, ", Artifact");
145:
146: mvwaddstr(hw, 9, 0, "What type of item do you want? ");
147: wclrtoeol(hw);
148: touchwin(hw);
149: wrefresh(hw);
150: itemtype = readcharw(hw);
151: }
152:
153: switch(itemtype)
154: {
155: case POTION:
156: which_type = TYP_POTION;
157: array_size = maxpotions;
158: magic_array = p_magic;
159: break;
160:
161: case SCROLL:
162: which_type = TYP_SCROLL;
163: array_size = maxscrolls;
164: magic_array = s_magic;
165: break;
166:
167: case FOOD:
168: which_type = TYP_FOOD;
169: array_size = maxfoods;
170: magic_array = fd_data;
171: break;
172:
173: case WEAPON:
174: which_type = TYP_WEAPON;
175: array_size = maxweapons;
176: break;
177:
178: case ARMOR:
179: which_type = TYP_ARMOR;
180: array_size = maxarmors;
181: break;
182:
183: case RING:
184: which_type = TYP_RING;
185: array_size = maxrings;
186: magic_array = r_magic;
187: break;
188:
189: case STICK:
190: which_type = TYP_STICK;
191: array_size = maxsticks;
192: magic_array = ws_magic;
193: break;
194:
195: case ARTIFACT:
196: if (!wizard)
197: {
198: itemtype = '\0';
199: continue;
200: }
201:
202: which_type = TYP_ARTIFACT;
203: array_size = maxartifact;
204: break;
205:
206: case ESCAPE:
207: return;
208:
209: default:
210: wstandout(hw);
211: mvwaddstr(hw, 10, 0, "We don't stock any of those.");
212: wstandend(hw);
213: itemtype = '\0';
214: continue;
215: }
216: }
217: while (array_size == 0);
218:
219: which_one = array_size;
220:
221: do
222: {
223: const struct magic_item *m_item;
224:
225: display_postinfo();
226:
227: mpos = 0;
228: sprintf(buf, "Which kind of %s do you wish to have (* for list)? ",
229: things[which_type].mi_name);
230:
231: mvwaddstr(hw, 9, 0, buf);
232:
233: touchwin(hw);
234: wrefresh(hw);
235: buf[0] = '\0';
236:
237: switch (get_string(buf, hw))
238: {
239: case QUIT:
240: case ESCAPE:
241: itemtype = '\0';
242: goto buy_more;
243: }
244:
245: if (buf[0] == '*') /* print list */
246: {
247: add_line(" ID BASECOST NAME");
248:
249: switch (which_type)
250: {
251: case TYP_RING:
252: case TYP_POTION:
253: case TYP_STICK:
254: case TYP_SCROLL:
255: case TYP_FOOD:
256:
257: for(i=0,m_item=magic_array; i < array_size; i++, m_item++)
258: if (!is_spell && m_item->mi_worth > 0)
259: {
260: sprintf(buf, "%3d) %8ld %s", i, m_item->mi_worth,
261: m_item->mi_name);
262: add_line(buf);
263: }
264: break;
265:
266: case TYP_ARMOR:
267: for (i = 0; i < array_size; i++)
268: if (!is_spell && armors[i].a_worth > 0)
269: {
270: sprintf(buf, "%3d) %8ld %s", i, armors[i].a_worth,
271: armors[i].a_name);
272:
273: add_line(buf);
274: }
275: break;
276:
277: case TYP_WEAPON:
278: for (i = 0; i < array_size; i++)
279: if (!is_spell && weaps[i].w_worth > 0)
280: {
281: sprintf(buf, "%3d) %8ld %s", i, weaps[i].w_worth,
282: weaps[i].w_name);
283: add_line(buf);
284: }
285: break;
286:
287: case TYP_ARTIFACT:
288: for (i = 0; i < array_size; i++)
289: {
290: sprintf(buf, "%3d) %8d %s", i, arts[i].ar_worth,
291: arts[i].ar_name);
292: add_line(buf);
293: }
294: break;
295:
296: default:
297: add_line("What a strange type.");
298: }
299:
300: end_line();
301: touchwin(hw);
302: wrefresh(hw);
303: continue;
304: }
305:
306: if (isdigit(buf[0]))
307: which_one = atoi(buf);
308: else
309: switch (which_type)
310: {
311: case TYP_RING:
312: case TYP_POTION:
313: case TYP_STICK:
314: case TYP_SCROLL:
315: case TYP_FOOD:
316: for (i=0,m_item=magic_array; i < array_size; i++, m_item++)
317: if (strcmp(buf, m_item->mi_name) == 0)
318: which_one = i;
319: break;
320:
321: case TYP_ARMOR:
322: for (i = 0; i < array_size; i++)
323: if (strcmp(buf, armors[i].a_name) == 0)
324: which_one = i;
325: break;
326:
327: case TYP_WEAPON:
328: for (i = 0; i < array_size; i++)
329: if (strcmp(buf, weaps[i].w_name) == 0)
330: which_one = i;
331: break;
332:
333: case TYP_ARTIFACT:
334: for (i = 0; i < array_size; i++)
335: if (strcmp(buf, arts[i].ar_name) == 0)
336: which_one = i;
337: break;
338:
339: default:
340: msg("What a strange type.");
341: }
342:
343: if (which_one < 0 || which_one >= array_size)
344: {
345: wstandout(hw);
346: mvwaddstr(hw, 10, 0, "Type the name or an ID number.");
347: wstandend(hw);
348: }
349: }
350: while (which_one < 0 || which_one >= array_size);
351:
352: item = new_item(sizeof *obj);
353: obj = OBJPTR(item);
354:
355: if (which_type == TYP_ARTIFACT)
356: {
357: new_artifact(which_one, obj);
358: add_pack(item, NOMESSAGE);
359: itemtype = '\0';
360: goto buy_more;
361: }
362:
363: obj->o_type = itemtype;
364: obj->o_which = which_one;
365: obj->o_mark[0] = '\0';
366: obj->o_group = 0;
367: obj->o_count = 1;
368: obj->o_weight = 0;
369: obj->o_dplus = obj->o_hplus = 0;
370: obj->o_worth = 0;
371:
372: if (!is_spell)
373: {
374: plus_or_minus = -100;
375:
376: do
377: {
378: mvwaddstr(hw, 10, 0, "Do you want the cursed, blessed, or normal"
379: " version? (c, b, n) [n]");
380: touchwin(hw);
381: wrefresh(hw);
382:
383: blessed = cursed = FALSE;
384: switch (readcharw(hw))
385: {
386: case ESCAPE:
387: discard(item);
388: itemtype = '\0';
389: goto buy_more;
390:
391: case 'c':
392: cursed = TRUE;
393: plus_or_minus = 0;
394: break;
395:
396: case 'b':
397: blessed = TRUE;
398: plus_or_minus = 0;
399: break;
400:
401: case 'n':
402: case ' ':
403: plus_or_minus = 0;
404: break;
405:
406: default:
407: wstandout(hw);
408: mvwaddstr(hw,11,0,"Type 'c' for cursed, 'b' for blessed, "
409: "or 'n' for normal");
410: wstandend(hw);
411: }
412: }
413: while (plus_or_minus == -100);
414: }
415:
416: /* else used blessed, cursed from flags parameter */
417:
418: if (which_type == TYP_WEAPON)
419: init_weapon(obj, which_one);
420:
421: obj->o_flags |= ISKNOW;
422:
423: if (cursed)
424: {
425: plus_or_minus = -(rnd(2) + 1);
426: obj->o_flags |= ISCURSED;
427: }
428: else if (blessed)
429: {
430: plus_or_minus = (rnd(3) + 1);
431: obj->o_flags |= ISBLESSED;
432: }
433: else
434: {
435: plus_or_minus = 0;
436: obj->o_flags |= ISNORMAL;
437: }
438:
439: switch (which_type)
440: {
441: case TYP_WEAPON:
442: obj->o_hplus += plus_or_minus;
443: obj->o_dplus += plus_or_minus;
444: break;
445:
446: case TYP_ARMOR:
447: obj->o_weight = armors[which_one].a_wght;
448: obj->o_ac = armors[which_one].a_class - plus_or_minus;
449: break;
450:
451: case TYP_STICK:
452: fix_stick(obj);
453: break;
454:
455: case TYP_RING:
456: obj->o_ac = plus_or_minus;
457: break;
458:
459: case TYP_SCROLL:
460: case TYP_POTION:
461: obj->o_weight = things[which_type].mi_wght;
462: break;
463:
464: case TYP_FOOD:
465: break;
466:
467: default:
468: msg("That's a strange thing to try to own.");
469: discard(item);
470: itemtype = '\0';
471: goto buy_more;
472: }
473:
474: obj->o_worth = get_worth(obj) * (luck + level / 15 + 1);
475: describe_it(obj);
476:
477: if (!wizard && obj->o_worth > EFFECTIVE_PURSE)
478: {
479: wstandout(hw);
480: mvwaddstr(hw, 12, 0, "Unfortunately, you can't afford it.");
481: wstandend(hw);
482: wclrtoeol(hw);
483: touchwin(hw);
484: wrefresh(hw);
485: wait_for(' ');
486: discard(item);
487: itemtype = '\0';
488: goto buy_more;
489: }
490:
491: mvwaddstr(hw, 12, 0, "Do you want it? [y] ");
492: wclrtoeol(hw);
493: touchwin(hw);
494: wrefresh(hw);
495:
496: switch (readcharw(hw))
497: {
498: case ESCAPE:
499: case 'n':
500: msg("");
501: discard(item);
502: itemtype = '\0';
503: goto buy_more;
504: }
505:
506: /* The hero bought the item here */
507:
508: mpos = 0;
509:
510: if (add_pack(item, NOMESSAGE) && !is_spell)
511: {
512: if (!wizard)
513: {
514: purse -= obj->o_worth; /* take his money */
515: ++player.t_trans;
516: }
517:
518: trans_line(); /* show remaining deals */
519:
520: switch(which_type)
521: {
522: case TYP_RING:
523: case TYP_STICK:
524: case TYP_SCROLL:
525: case TYP_POTION:
526: know_items[which_type][which_one] = TRUE;
527: }
528: }
529: }
530:
531: /*
532: sell_it()
533: Sell an item to the trading post
534: */
535:
536: void
537: sell_it(void)
538: {
539: struct object *obj;
540: struct linked_list *item;
541: char buf[2 * LINELEN];
542:
543: wclear(cw);
544:
545: if ((item = get_item("sell", 0)) == NULL)
546: return;
547:
548: obj = OBJPTR(item);
549: msg("");
550: display_postinfo();
551: touchwin(hw);
552: wrefresh(hw);
553:
554: if ((obj->o_type == ARTIFACT) || (obj->o_worth = get_worth(obj)) == 0)
555: {
556: mpos = 0;
557: msg("We don't buy those.");
558:
559: if (is_wearing(R_ADORNMENT) && rnd(10) < 4)
560: msg("How about that %s ring instead?", r_stones[R_ADORNMENT]);
561:
562: return;
563: }
564:
565: describe_it(obj);
566: mvwaddstr(hw, 12, 0, "Do you want to sell it? [n] ");
567: touchwin(hw);
568: wrefresh(hw);
569:
570: switch( readcharw(hw) )
571: {
572: case 'y':
573: break;
574: default:
575: msg("");
576: if (is_wearing(R_ADORNMENT))
577: msg("How about that %s ring instead?",
578: r_stones[R_ADORNMENT]);
579: return;
580: }
581:
582: rem_pack(obj);
583: purse += obj->o_worth; /* give him his money */
584: ++player.t_trans;
585:
586: sprintf(buf, "Sold %s. Hit space to continue.",
587: inv_name(obj, LOWERCASE));
588: discard(item);
589:
590: mvwaddstr(hw, 13, 0, buf);
591: touchwin(hw);
592: wrefresh(hw);
593: wait_for(' ');
594: }
595:
596: /*
597: describe_it()
598: Laud or condemn the object
599: */
600:
601: extern char *inv_name();
602:
603: void
604: describe_it(struct object *obj)
605: {
606: static char *cursed_d[] =
607: {
608: "worthless hunk of junk",
609: "shoddy piece of trash",
610: "piece of rusty garbage",
611: "example of terrible workmanship",
612: "cheap hack"
613: };
614:
615: static char *normal_d[] =
616: {
617: "journeyman's piece",
618: "fine deal",
619: "great bargain",
620: "good find",
621: "real value",
622: "piece of honest workmanship",
623: "steal",
624: "purchase worth making",
625: "inexpensive product"
626: };
627:
628: static char *blessed_d[] =
629: {
630: "magnificant masterpiece",
631: "quality product",
632: "exceptional find",
633: "unbeatable value",
634: "rare beauty",
635: "superior product",
636: "well-crafted item"
637: };
638:
639: char *charp;
640: char buf[2 * LINELEN];
641:
642: if (obj->o_flags & ISBLESSED)
643: charp = blessed_d[rnd(sizeof(blessed_d) / sizeof(char *))];
644: else if (obj->o_flags & ISCURSED)
645: charp = cursed_d[rnd(sizeof(cursed_d) / sizeof(char *))];
646: else
647: charp = normal_d[rnd(sizeof(normal_d) / sizeof(char *))];
648:
649: sprintf(buf, "It's a%s %s worth %ld pieces of gold.",
650: vowelstr(charp), charp, obj->o_worth);
651:
652: mvwaddstr(hw, 10, 0, inv_name(obj, TRUE));
653: mvwaddstr(hw, 11, 0, buf);
654: wclrtoeol(hw);
655: }
656:
657: /*
658: open_market()
659: Retruns TRUE when ok do to transacting
660: */
661:
662: int
663: open_market(void)
664: {
665: int maxtrans = is_wearing(R_ADORNMENT) ? MAXPURCH + 4 : MAXPURCH;
666:
667: if (wizard || player.t_trans < maxtrans || (level == 0))
668: return(TRUE);
669: else
670: {
671: msg("The market is closed. The stairs are that-a-way.");
672: return(FALSE);
673: }
674: }
675:
676: /*
677: get_worth()
678: Calculate an objects worth in gold
679: */
680:
681: int
682: get_worth(struct object *obj)
683: {
684: long worth = 0;
685: int wh = obj->o_which;
686: int blessed = obj->o_flags & ISBLESSED;
687: int cursed = obj->o_flags & ISCURSED;
688:
689: switch (obj->o_type)
690: {
691: case FOOD:
692: if (wh < maxfoods)
693: {
694: worth = obj->o_count * fd_data[wh].mi_worth;
695: if (blessed)
696: worth *= 2;
697: }
698: break;
699:
700: case WEAPON:
701: if (wh < maxweapons)
702: {
703: worth = weaps[wh].w_worth;
704: worth *= obj->o_count * (2 +
705: (4 * obj->o_hplus +
706: 4 * obj->o_dplus));
707:
708: if (obj->o_flags & ISSILVER)
709: worth *= 2;
710:
711: if (obj->o_flags & ISPOISON)
712: worth *= 2;
713:
714: if (obj->o_flags & ISZAPPED)
715: worth += 20 * obj->o_charges;
716: }
717: break;
718:
719: case ARMOR:
720: if (wh < maxarmors)
721: {
722: int plusses = armors[wh].a_class - obj->o_ac;
723:
724: worth = armors[wh].a_worth;
725:
726: if (plusses > 0)
727: worth *= (1 + (10 *
728: (armors[wh].a_class - obj->o_ac)));
729: }
730: break;
731:
732: case SCROLL:
733: if (wh < maxscrolls)
734: worth = s_magic[wh].mi_worth;
735: break;
736:
737: case POTION:
738: if (wh < maxpotions)
739: worth = p_magic[wh].mi_worth;
740: break;
741:
742: case RING:
743: if (wh < maxrings)
744: {
745: worth = r_magic[wh].mi_worth;
746: worth += obj->o_ac * 40;
747: }
748: break;
749:
750: case STICK:
751: if (wh < maxsticks)
752: {
753: worth = ws_magic[wh].mi_worth;
754: worth += 20 * obj->o_charges;
755: }
756: break;
757:
758: case ARTIFACT:
759: if (wh < maxartifact)
760: worth = arts[wh].ar_worth;
761: break;
762:
763: default:
764: worth = 0;
765: }
766:
767: if (obj->o_flags & ISPROT) /* 300% more for protected */
768: worth *= 3;
769:
770: if (blessed) /* 250% more for blessed */
771: worth = 5 * worth / 2;
772: else if (cursed) /* half for cursed */
773: worth /= 2;
774:
775: if (obj->o_flags & (CANRETURN | ISOWNED))
776: worth *= 4;
777: else if (obj->o_flags & CANRETURN)
778: worth *= 2;
779: else if (obj->o_flags & ISLOST)
780: worth /= 3;
781:
782: return(max(0, worth)); /* anything is worth at least one gold piece */
783: }
784:
785: /*
786: trans_line()
787: Show how many transactions the hero has left
788: */
789:
790: void
791: trans_line(void)
792: {
793: char buf[2 * LINELEN];
794: int adorned = is_wearing(R_ADORNMENT);
795:
796: if (level == 0 && purse > 0)
797: sprintf(buf, "You still have %ld pieces of gold left.", purse);
798: else if (purse == 0)
799: sprintf(buf, "You have no money left.");
800: else if (!wizard)
801: sprintf(buf, "You have %d transactions and %ld gold pieces remaining.",
802: max(0, (adorned ? MAXPURCH + 4 : MAXPURCH) - player.t_trans),
803: EFFECTIVE_PURSE);
804: else
805: sprintf(buf, "You have infinite transactions remaining.");
806:
807: mvwaddstr(hw, LINES - 2, 0, buf);
808: }
CVSweb