1 /* $Id$ */
2 /*
3  * Client-side store stuff.
4  */
5 
6 #include "angband.h"
7 
8 bool leave_store;
9 int store_top = 0;
10 
11 
12 
13 /*
14  * ToME show_building, ripped for client	- Jir -
15  */
display_store_action()16 void display_store_action()
17 {
18 	int i;
19 	/* BIG_MAP leads to big shops */
20 	int spacer = (screen_hgt > SCREEN_HGT) ? 14 : 0;
21 
22 	for (i = 0; i < 6; i++) {
23 		if (!c_store.actions[i]) continue;
24 
25 		c_put_str(c_store.action_attr[i], c_store.action_name[i],
26 				21 + spacer + (i / 2), 20 + (30 * (i % 2)));
27 	}
28 }
29 
display_entry(int pos,int entries)30 static void display_entry(int pos, int entries) {
31 	object_type *o_ptr;
32 	int i, x;
33 	char o_name[ONAME_LEN];
34 	char out_val[MSG_LEN];
35 
36 	int maxwid = 75;
37 
38 	/* Get the item */
39 	o_ptr = &store.stock[pos];
40 
41         /* Get the "offset" */
42         i = (pos % entries);
43 
44         /* Label it, clear the line --(-- */
45         (void)sprintf(out_val, "%c) ", I2A(i));
46         prt(out_val, i + 6, 0);
47 
48         /* Describe an item in the home */
49         if (store_num == STORE_HOME || store_num == STORE_HOME_DUN) {
50                 maxwid = 75;
51 
52                 /* Leave room for weights, if necessary -DRS- */
53                 if (c_cfg.show_weights) maxwid -= 10;
54 
55                 /* Describe the object */
56 		strcpy(o_name, store_names[pos]);
57                 o_name[maxwid] = '\0';
58                 c_put_str(o_ptr->attr, o_name, i + 6, 3);
59 
60                 /* Show weights */
61                 if (c_cfg.show_weights) {
62                         /* Only show the weight of an individual item */
63                         int wgt = o_ptr->weight;
64                         (void)sprintf(out_val, "%3d.%d lb", wgt / 10, wgt % 10);
65                         put_str(out_val, i + 6, 68);
66                 }
67         } else {
68                 /* Must leave room for the "price" */
69                 maxwid = 65;
70 
71                 /* Leave room for weights, if necessary -DRS- */
72                 if (c_cfg.show_weights) maxwid -= 7;
73 
74                 /* Describe the object (fully) */
75 		strcpy(o_name, store_names[pos]);
76                 o_name[maxwid] = '\0';
77                 c_put_str(o_ptr->attr, o_name, i + 6, 3);
78 
79                 /* Show weights */
80                 if (c_cfg.show_weights) {
81                         /* Only show the weight of an individual item */
82                         int wgt = o_ptr->weight;
83                         (void)sprintf(out_val, "%3d.%d", wgt / 10, wgt % 10);
84                         put_str(out_val, i + 6, 61);
85 		}
86 
87 		x = store_prices[pos];
88 		if (x >= 0) {
89 			/* Actually draw the price (not fixed) */
90 			(void)sprintf(out_val, "%9d  ", x);
91 			c_put_str(p_ptr->au < x ? TERM_L_DARK : TERM_WHITE, out_val, i + 6, 68);
92 		}
93         }
94 }
95 
96 
97 
display_inventory(void)98 void display_inventory(void) {
99 	int i, k, entries = 12;
100 
101 	/* BIG_MAP leads to big shops */
102 	if (screen_hgt > SCREEN_HGT) entries = 26; /* we don't have 34 letters in the alphabet =p */
103 
104 	for (k = 0; k < entries; k++) {
105 		/* Do not display "dead" items */
106 		if (store_top + k >= store.stock_num) break;
107 
108 		/* Display that one */
109 		display_entry(store_top + k, entries);
110 	}
111 
112 	/* Erase the extra lines and the "more" prompt */
113 	for (i = k; i <= entries; i++) prt("", i + 6, 0);
114 
115 	/* Assume "no current page" */
116 	put_str("             ", 5, 20);
117 
118 	/* Visual reminder of "more items" */
119 	if (store.stock_num > entries) {
120 		/* Show "more" reminder (after the last item) */
121 		prt("-more-", k + 6, 3);
122 
123 		/* Indicate the "current page" */
124 		put_str(format("(Page %d of %d)%s%s",
125 		    store_top / entries + 1, store.stock_num == 0 ? 1 : (store.stock_num + entries - 1) / entries,
126 		    store_top / entries + 1 >= 10 ? "" : " ", (store.stock_num + entries - 1) / entries >= 10 ? "" : " "),
127 		    5, 20);
128 	}
129 
130 	/* Hack - Get rid of the cursor - mikaelh */
131 	Term->scr->cx = Term->wid;
132 	Term->scr->cu = 1;
133 }
134 
135 /*
136  * Get the ID of a store item and return its value      -RAK-
137  */
get_stock(int * com_val,cptr pmt,int i,int j)138 static int get_stock(int *com_val, cptr pmt, int i, int j)
139 {
140         char    command;
141         char    out_val[160];
142 
143         /* Paranoia XXX XXX XXX */
144         clear_topline_forced();
145 
146         /* Assume failure */
147         *com_val = (-1);
148 
149         /* Build the prompt */
150         (void)sprintf(out_val, "(Items %c-%c, ESC to exit) %s",
151                       I2A(i), I2A(j), pmt);
152 
153         /* Ask until done */
154         while (TRUE)
155         {
156                 int k;
157 
158                 /* Escape */
159                 if (!get_com(out_val, &command)) break;
160 
161                 /* Convert */
162                 k = (islower(command) ? A2I(command) : -1);
163 
164                 /* Legal responses */
165                 if ((k >= i) && (k <= j))
166                 {
167                         *com_val = k;
168                         break;
169                 }
170 
171                 /* Oops */
172                 bell();
173         }
174 
175         /* Clear the prompt */
176         clear_topline();
177 
178         /* Cancel */
179         if (command == ESCAPE) return (FALSE);
180 
181         /* Success */
182         return (TRUE);
183 }
184 
185 
186 
187 
188 /* XXX Bad design.. store code really should be rewritten.	- Jir - */
store_examine(void)189 static void store_examine(void)
190 {
191 	int                     i;
192 	int                     item;
193 
194 	object_type             *o_ptr;
195 	char            out_val[160];
196 
197 	/* BIG_MAP leads to big shops */
198 	int entries = (screen_hgt > SCREEN_HGT) ? 26 : 12;
199 
200 
201 	/* Empty? */
202 	if (store.stock_num <= 0) {
203 		if (store_num == STORE_HOME || store_num == STORE_HOME_DUN)
204 			c_msg_print("Your home is empty.");
205 		else c_msg_print("I am currently out of stock.");
206 		return;
207 	}
208 
209 	/* Find the number of objects on this and following pages */
210 	i = (store.stock_num - store_top);
211 
212 	/* And then restrict it to the current page */
213 	if (i > entries) i = entries;
214 
215 	/* Prompt */
216 	if (store_num == STORE_HOME || store_num == STORE_HOME_DUN)
217 		sprintf(out_val, "Which item do you want to examine? ");
218 	else
219 		sprintf(out_val, "Which item do you want to examine? ");
220 
221 	/* Get the item number to be bought */
222 	if (!get_stock(&item, out_val, 0, i-1)) return;
223 
224 	/* Get the actual index */
225 	item = item + store_top;
226 
227 	/* Get the actual item */
228 	o_ptr = &store.stock[item];
229 
230 	/* Tell the server */
231 	if (is_realm_book(o_ptr)) show_browse(o_ptr);
232 	else if (o_ptr->tval == TV_BOOK &&
233 	    (!is_custom_tome(o_ptr->sval) || o_ptr->xtra1))
234 		browse_school_spell(-(item + 1), o_ptr->sval, o_ptr->pval);
235 	else Send_store_examine(item);
236 }
237 
238 
store_purchase(void)239 static void store_purchase(void) {
240         int                     i, amt, amt_afford;
241         int                     item;
242 
243         object_type             *o_ptr;
244         char            out_val[160];
245 
246 	/* BIG_MAP leads to big shops */
247 	int entries = (screen_hgt > SCREEN_HGT) ? 26 : 12;
248 
249 
250         /* Empty? */
251         if (store.stock_num <= 0) {
252                 if (store_num == STORE_HOME || store_num == STORE_HOME_DUN)
253             		c_msg_print("Your home is empty.");
254                 else c_msg_print("I am currently out of stock.");
255                 return;
256         }
257 
258 
259         /* Find the number of objects on this and following pages */
260         i = (store.stock_num - store_top);
261 
262         /* And then restrict it to the current page */
263         if (i > entries) i = entries;
264 
265         /* Prompt */
266         if (store_num == STORE_HOME || store_num == STORE_HOME_DUN)
267                 sprintf(out_val, "Which item do you want to take? ");
268         else
269                 sprintf(out_val, "Which item are you interested in? ");
270 
271         /* Get the item number to be bought */
272         if (!get_stock(&item, out_val, 0, i-1)) return;
273 
274         /* Get the actual index */
275         item = item + store_top;
276 
277         /* Get the actual item */
278         o_ptr = &store.stock[item];
279 
280 	/* Client-side check already, for item stacks: Too expensive? */
281 	if (store_prices[item] > p_ptr->au) {
282 		c_msg_print("You do not have enough gold.");
283 		return;
284 	}
285 
286         /* Assume the player wants just one of them */
287         amt = 1;
288 
289         /* Find out how many the player wants */
290         if (o_ptr->number > 1) {
291                 /* Hack -- note cost of "fixed" items */
292                 if (store_num != STORE_HOME || store_num == STORE_HOME_DUN) {
293                         c_msg_print(format("That costs %d gold per item.", store_prices[item]));
294 
295 			if (store_prices[item] > 0) amt_afford = p_ptr->au / store_prices[item];
296 			else amt_afford = o_ptr->number;
297 
298 			/* Get a quantity */
299 			if (o_ptr->number <= amt_afford)
300 				amt = c_get_quantity(NULL, o_ptr->number);
301 			else if (amt_afford > 1) {
302 				inkey_letter_all = TRUE;
303 				sprintf(out_val, "Quantity (1-\377y%d\377w, 'a' or spacebar for all): ", amt_afford);
304 				amt = c_get_quantity(out_val, amt_afford);
305 			} else {
306 				sprintf(out_val, "Quantity (\377y1\377w): ");
307 				amt = c_get_quantity(out_val, 1);
308 			}
309 		} else {
310 			/* Get a quantity */
311 			amt = c_get_quantity(NULL, o_ptr->number);
312 		}
313 
314                 /* Allow user abort */
315                 if (amt <= 0) return;
316         }
317 
318 	/* Tell the server */
319 	Send_store_purchase(item, amt);
320 }
321 
322 /* helper functions for store_chat(), also to be used for
323    pasting store items in the middle of a chat line similar to
324    new '\\x' feature for inven/equip-pasting. - C. Blue */
store_paste_where(char * where)325 void store_paste_where(char *where) {
326 	snprintf(where, 17, "\377s(%d,%d) \377%c%c\377s:",
327 	    p_ptr->wpos.wx, p_ptr->wpos.wy,
328 	    color_attr_to_char(c_store.store_attr),
329 	    c_store.store_char);
330 }
store_paste_item(char * out_val,int item)331 void store_paste_item(char *out_val, int item) {
332 	char	price[16];
333 
334 	/* Get shop price if any */
335 	/* Home doesn't price items */
336 	if (store_num == STORE_HOME || store_num == STORE_HOME_DUN) {
337 		sprintf(out_val, " %s", store_names[item]);
338 	/* Player stores with '@S-' inscription neither (museum mode) */
339 	} else if (store_prices[item] < 0) {
340 		sprintf(out_val, " %s", store_names[item]);
341 	/* Normal [player-]store */
342 	} else {
343 		/* Convert the price to more readable format */
344 		if (store_prices[item] >= 10000000)
345 			snprintf(price, 16, "%dM", store_prices[item] / 1000000);
346 		else if (store_prices[item] >= 10000)
347 			snprintf(price, 16, "%dk", store_prices[item] / 1000);
348 		else
349 			snprintf(price, 16, "%d", store_prices[item]);
350 
351 		sprintf(out_val, "%s (%s Au)", store_names[item], price);
352 	}
353 }
354 
store_chat(void)355 static void store_chat(void) {
356 	int	i, item;
357 
358 	char	out_val[MSG_LEN], buf[MSG_LEN];
359 	char	where[17];
360 
361 	/* BIG_MAP leads to big shops */
362 	int entries = (screen_hgt > SCREEN_HGT) ? 26 : 12;
363 
364 
365 	/* Empty? */
366 	if (store.stock_num <= 0) {
367 		if (store_num == STORE_HOME || store_num == STORE_HOME_DUN)
368 			c_msg_print("Your home is empty.");
369 		else c_msg_print("I am currently out of stock.");
370 		return;
371 	}
372 
373 
374 	/* Find the number of objects on this and following pages */
375 	i = (store.stock_num - store_top);
376 
377 	/* And then restrict it to the current page */
378 	if (i > entries) i = entries;
379 
380 	/* Prompt */
381 	if (store_num == STORE_HOME || store_num == STORE_HOME_DUN)
382 		sprintf(out_val, "Which item? ");
383 	else
384 		sprintf(out_val, "Which item? ");
385 
386 	/* Get the item number to be pasted */
387 	if (!get_stock(&item, out_val, 0, i - 1)) return;
388 
389 	/* Get the actual index */
390 	item = item + store_top;
391 
392 	store_paste_where(where);
393 	store_paste_item(out_val, item);
394 
395 	/* Tell the server */
396 	snprintf(buf, MSG_LEN - 1, "%s %s", where, out_val);
397 	buf[MSG_LEN - 1] = 0;
398 	Send_paste_msg(buf);
399 }
400 
store_sell(void)401 static void store_sell(void)
402 {
403 	int item, amt;
404 
405 	if (store_num == STORE_HOME || store_num == STORE_HOME_DUN) {
406 		if (!c_get_item(&item, "Drop what? ", (USE_EQUIP | USE_INVEN)))
407 			return;
408 	} else if (store_num == STORE_MATHOM_HOUSE) {
409 		if (!c_get_item(&item, "Donate what? ", (USE_EQUIP | USE_INVEN)))
410 			return;
411 	} else {
412 		if (!c_get_item(&item, "Sell what? ", (USE_EQUIP | USE_INVEN)))
413 			return;
414 	}
415 
416 	/* Get an amount */
417 	if (inventory[item].number > 1) {
418 		if (is_cheap_misc(inventory[item].tval) && c_cfg.whole_ammo_stack && !verified_item) amt = inventory[item].number;
419 		else {
420 			inkey_letter_all = TRUE;
421 			amt = c_get_quantity("How many ('a' or spacebar for all)? ", inventory[item].number);
422 		}
423 	} else amt = 1;
424 
425 	/* Hack -- verify for Museum(Mathom house) */
426 	if (store_num == STORE_MATHOM_HOUSE)
427 	{
428 		char out_val[160];
429 
430 		if (inventory[item].number == amt)
431 			sprintf(out_val, "Really donate %s?", inventory_name[item]);
432 		else
433 			sprintf(out_val, "Really donate %d of your %s?", amt, inventory_name[item]);
434 		if (!get_check2(out_val, FALSE)) return;
435 	}
436 
437 	/* Tell the server */
438 	Send_store_sell(item, amt);
439 }
440 
store_do_command(int num)441 static void store_do_command(int num) {
442 	int                     i, amt, gold;
443 	int                     item, item2;
444 	u16b action = c_store.actions[num];
445 	u16b bact = c_store.bact[num];
446 	/* BIG_MAP leads to big shops */
447 	int entries = (screen_hgt > SCREEN_HGT) ? 26 : 12;
448 
449 	char            out_val[160];
450 
451 	i = amt = gold = item = item2 = 0;
452 
453 	/* lazy job for 'older' commands */
454 	switch (bact) {
455 		case BACT_SELL:
456 			store_sell();
457 			return;
458 			break;
459 		case BACT_BUY:
460 			store_purchase();
461 			return;
462 			break;
463 		case BACT_EXAMINE:
464 			store_examine();
465 			return;
466 			break;
467 	}
468 
469 	if (c_store.flags[num] & BACT_F_STORE_ITEM) {
470 		/* Empty? */
471 		if (store.stock_num <= 0) {
472 			if (store_num == STORE_HOME || store_num == STORE_HOME_DUN)
473 				c_msg_print("Your home is empty.");
474 			else c_msg_print("I am currently out of stock.");
475 			return;
476 		}
477 
478 
479 		/* Find the number of objects on this and following pages */
480 		i = (store.stock_num - store_top);
481 
482 		/* And then restrict it to the current page */
483 		if (i > entries) i = entries;
484 
485 		/* Prompt */
486 		sprintf(out_val, "Which item? ");
487 
488 		/* Get the item number to be bought */
489 		if (!get_stock(&item, out_val, 0, i-1)) return;
490 
491 		/* Get the actual index */
492 		item = item + store_top;
493 	}
494 
495 	if (c_store.flags[num] & BACT_F_INVENTORY) {
496 		if (!c_get_item(&item, "Which item? ", (USE_EQUIP | USE_INVEN)))
497 			return;
498 	}
499 
500 	if (c_store.flags[num] & BACT_F_GOLD) {
501 		/* Get how much */
502 		inkey_letter_all = TRUE;
503 		gold = c_get_quantity("How much gold ('a' or spacebar for all)? ", -1);
504 
505 		/* Send it */
506 		if (!gold) return;
507 	}
508 
509 	if (c_store.flags[num] & BACT_F_HARDCODE) {
510 		/* Nothing for now */
511 	}
512 
513 	Send_store_command(action, item, item2, amt, gold);
514 }
515 
store_process_command(int cmd)516 static void store_process_command(int cmd) {
517 	int i;
518 	bool allow_w_t = TRUE;
519 
520 	/* BIG_MAP leads to big shops */
521 	int entries = (screen_hgt > SCREEN_HGT) ? 26 : 12;
522 
523 	for (i = 0; i < 6; i++) {
524 		if (!c_store.actions[i]) continue;
525 
526 		if (c_store.letter[i] == cmd) {
527 			store_do_command(i);
528 			return;
529 		}
530 
531 		/* only allow wear/wield and take-off in stores that do not
532 		   already provide special functions of their own on those keys */
533 		if (c_cfg.rogue_like_commands) {
534 			if (c_store.letter[i] == 'w' ||
535 			    //c_store.letter[i] == KTRL('W') ||
536 			    c_store.letter[i] == 'T') allow_w_t = FALSE;
537 		} else {
538 			if (c_store.letter[i] == 'w' ||
539 			    c_store.letter[i] == 'W' ||
540 			    c_store.letter[i] == 't') allow_w_t = FALSE;
541 		}
542 	}
543 
544 	/* hack: translate p/s into d/g and vice versa, for extra comfort */
545 	for (i = 0; i < 6; i++) {
546 		if (!c_store.actions[i]) continue;
547 
548 		switch (c_store.letter[i]) {
549 		case 'p':
550 			if (cmd == 'g') {
551 				store_do_command(i);
552 				return;
553 			}
554 			break;
555 		case 's':
556 			if (cmd == 'd') {
557 				store_do_command(i);
558 				return;
559 			}
560 			break;
561 		case 'g':
562 			if (cmd == 'p') {
563 				store_do_command(i);
564 				return;
565 			}
566 			break;
567 		case 'd':
568 			if (cmd == 's') {
569 				store_do_command(i);
570 				return;
571 			}
572 			break;
573 		case 'x':
574 #if 0 /* nope, change of plans for future changes: use shift+I to inspect _own_ items instead! */
575 		//(future change: replace x by I in ba_info, and I/s by D) -- case 'I':
576 			if (cmd == 'I' || cmd == 'l' || cmd == 'x') {
577 				store_do_command(i);
578 				return;
579 			}
580 #else
581 			if (cmd == 'l' || cmd == 'x') {
582 				store_do_command(i);
583 				return;
584 			}
585 #endif
586 			break;
587 		}
588 	}
589 
590 	/* Parse the command */
591 	i = 0; /* for jumping to page 1/2/3/4 */
592 	switch (cmd) {
593 		/* Leave */
594 		case ESCAPE:
595 		case KTRL('X'):
596 			leave_store = TRUE;
597 			break;
598 
599 		case KTRL('T'):
600 			/* Take a screenshot */
601 			xhtml_screenshot("screenshot????");
602 			break;
603 
604 		/* Browse */
605 		case ' ':
606 			if (store.stock_num <= entries) {
607 				if (store_top) {
608 					/*
609 					 * Hack - Allowing going back to first page after buying
610 					 * last item on the second page. - mikaelh */
611 					store_top = 0;
612 					display_inventory();
613 				} else {
614 					c_msg_print("Entire inventory is shown.");
615 				}
616 			} else {
617 				store_top += entries;
618 				if (store_top >= store.stock_num) store_top = 0;
619 				display_inventory();
620 			}
621 			break;
622 
623 		/* Allow to browse backwards via BACKSPACE */
624 		case '\b':
625 			if (store.stock_num <= entries) {
626 				if (store_top) {
627 					/* see above - C. Blue */
628 					store_top = 0;
629 					display_inventory();
630 				} else {
631 					c_msg_print("Entire inventory is shown.");
632 				}
633 			} else {
634 				store_top -= entries;
635 				if (store_top < 0) store_top = ((store.stock_num - 1) / entries) * entries;
636 				display_inventory();
637 			}
638 			break;
639 
640 		/* go to page n */
641 		case '0': i++;
642 		case '9': i++;
643 		case '8': i++;
644 		case '7': i++;
645 		case '6': i++;
646 		case '5': i++;
647 		case '4': i++;
648 		case '3': i++;
649 		case '2': i++;
650 		case '1':
651 			if (store.stock_num > entries * i) {
652 				store_top = entries * i;
653 				display_inventory();
654 			}
655 #if 0 /* suppress message, in case STORE_INVEN_MAX doesn't actually support all 10 pages. It'd look silyl. */
656 			else c_msg_format("Page %d is empty.", i + 1);
657 #endif
658 			break;
659 
660 		/* Paste on Chat */
661 		case 'c':
662 			store_chat();
663 			break;
664 
665 		/* allow to actually chat from within a store, might be cool for
666 		   notifying others of items other than just pasting into chat */
667 		case ':':
668 			cmd_message();
669 			break;
670 
671 		/* allow inspecting _own_ items while in a store! */
672 		case 'I':
673 			cmd_observe();
674 			break;
675 
676 		/* Ignore return */
677 		case '\r':
678 			break;
679 
680 		/* Equipment list */
681 		case 'e':
682 			cmd_equip();
683 			break;
684 
685 		/* Inventory list */
686 		case 'i':
687 			cmd_inven();
688 			break;
689 
690 #ifdef USE_SOUND_2010
691 		case KTRL('C'):
692 		case KTRL('Q')://rl
693 			toggle_music();
694 			break;
695 		case KTRL('N'):
696 		case KTRL('V')://rl
697 			toggle_audio();
698 			break;
699 #endif
700 
701 		case '{':
702 			cmd_inscribe();
703 			break;
704 		case '}':
705 			cmd_uninscribe();
706 			break;
707 
708 		/* special feat for some stores: allow wear/wield and take-off..
709 		   'emulating' rogue-like key mapping option for now, sigh */
710 		case 'w':
711 			if (allow_w_t) cmd_wield();
712 			else cmd_raw_key(cmd);
713 			break;
714 		case 'W':
715 			if (c_cfg.rogue_like_commands || !allow_w_t) cmd_raw_key(cmd);
716 			else cmd_wield2();
717 			break;
718 		case KTRL('W'):
719 			if (!c_cfg.rogue_like_commands || !allow_w_t) cmd_raw_key(cmd);
720 			else cmd_wield2();
721 			break;
722 		case 't':
723 			if (c_cfg.rogue_like_commands || !allow_w_t) cmd_raw_key(cmd);
724 			else cmd_take_off();
725 			break;
726 		case 'T':
727 			if (!c_cfg.rogue_like_commands || !allow_w_t) cmd_raw_key(cmd);
728 			else cmd_take_off();
729 			break;
730 
731 		default:
732 			cmd_raw_key(cmd);
733 			break;
734 	}
735 }
736 
c_store_prt_gold(void)737 void c_store_prt_gold(void) {
738 	char out_val[64];
739 	/* BIG_MAP leads to big shops */
740 	int spacer = (screen_hgt > SCREEN_HGT) ? 14 : 0;
741 
742 	prt("Gold Remaining: ", 19 + spacer, 53);
743 
744 	sprintf(out_val, "%9d", p_ptr->au);
745 	if (p_ptr->au < 1000000000) strcat(out_val, " "); //hack to correctly clear line for players moving huge amounts
746 	prt(out_val, 19 + spacer, 68);
747 
748 	/* Hack -- show balance (if not 0) */
749 	if (store_num == STORE_MERCHANTS_GUILD && p_ptr->balance) {
750 		prt("Your balance  : ", 20 + spacer, 53);
751 
752 		sprintf(out_val, "%9d", p_ptr->balance);
753 		if (p_ptr->au < 1000000000) strcat(out_val, " ");
754 		prt(out_val, 20 + spacer, 68);
755 	} else {
756 		/* Erase part of the screen */
757 		Term_erase(0, 20 + spacer, 255);
758 	}
759 }
760 
do_redraw_store(void)761 void do_redraw_store(void) {
762 	redraw_store = FALSE;
763 
764 	if (shopping) {
765 		/* hack: Display changed capacity if we just extended the house */
766 		if ((store_num == STORE_HOME || store_num == STORE_HOME_DUN)
767 		    && c_store.max_cost) {
768 			char buf[1024];
769 			sprintf(buf, "%s (Stock: %d/%d)", c_store.store_name, store.stock_num, c_store.max_cost);
770 			prt(buf, 3, 50);
771 		}
772 		display_inventory();
773 	}
774 }
775 
display_store(void)776 void display_store(void) {
777 	int i;
778 	char buf[1024];
779 	/* BIG_MAP leads to big shops */
780 	int spacer = (screen_hgt > SCREEN_HGT) ? 14 : 0;
781 
782 	/* Save the term */
783 	Term_save();
784 
785 	/* We are "shopping" */
786 	shopping = TRUE;
787 
788 	/* Clear screen */
789 	Term_clear();
790 
791 	store_top = 0;
792 
793 	/* The "Home" is special */
794 	if (store_num == STORE_HOME || store_num == STORE_HOME_DUN) {
795 		/* Put the owner name (usually "Your House/Home") */
796 		sprintf(buf, "%s", c_store.owner_name);
797 		put_str(buf, 3, 10);
798 
799 		/* Show the store name (usually blank for houses) and -hack- max_cost is the capacity */
800 		if (c_store.max_cost)
801 			sprintf(buf, "%s (Stock: %d/%d)", c_store.store_name, store.stock_num, c_store.max_cost);
802 		else
803 			sprintf(buf, "%s", c_store.store_name);
804 		prt(buf, 3, 50);
805 
806 		/* Label the item descriptions */
807 		put_str("Item Description", 5, 3);
808 
809 		/* If showing weights, show label */
810 		if (c_cfg.show_weights) put_str("Weight", 5, 70);
811 	}
812 
813 	/* Normal stores */
814 	else {
815 		/* Put the owner name and race */
816 		sprintf(buf, "%s", c_store.owner_name);
817 		put_str(buf, 3, 10);
818 
819 		/* Show the max price in the store (above prices) */
820 		if (!c_store.max_cost) {
821 			/* improve it a bit visually for player stores who don't buy anything */
822 			sprintf(buf, "%s", c_store.store_name);
823 		} else {
824 			sprintf(buf, "%s (%d)", c_store.store_name, c_store.max_cost);
825 		}
826 		prt(buf, 3, 50);
827 
828 		/* Label the item descriptions */
829 		put_str("Item Description", 5, 3);
830 
831 		/* If showing weights, show label */
832 		if (c_cfg.show_weights) put_str("Weight", 5, 60);
833 
834 		/* Label the asking price (in stores) */
835 		put_str("Price", 5, 72);
836 
837 		/* Display the players remaining gold */
838 		c_store_prt_gold();
839 	}
840 
841 	/* Display the inventory */
842 	display_inventory();
843 
844 	/* Don't leave */
845 	leave_store = FALSE;
846 
847 	/* Start at the top */
848 	store_top = 0;
849 
850 	/* Interact with player */
851 	while (!leave_store) {
852 		/* Hack -- Clear line 1 */
853 		prt("", 1, 0);
854 
855 		/* Clear */
856 		clear_from(21 + spacer);
857 
858 		/* Prompt */
859 #if 0
860 		prt("You may: ", 21 + spacer, 0);
861 
862 		/* Basic commands */
863 		prt(" ESC) Exit.", 22 + spacer, 0);
864 
865 		/* Browse if necessary */
866 		if (store.stock_num > 12 + spacer) prt(" SPACE) Next page", 23 + spacer, 0);
867 #else /* new: also show 1..n for jumping directly to a page */
868 		prt("ESC)   Exit store", 21 + spacer, 0);
869 		if (store.stock_num > 12 + spacer) {
870 			prt("SPACE) Next page", 22 + spacer, 0);
871 			prt(format("1-%d)%s  Go to page", (store.stock_num - 1) / (12 + spacer) + 1, (store.stock_num - 1) / (12 + spacer) + 1 >= 10 ? "" : " "), 23 + spacer, 0);
872 		}
873 #endif
874 
875 #if 0
876 		/* Home commands */
877 		if ((store_num == STORE_HOME || store_num == STORE_HOME_DUN) && FALSE) {
878 			prt(" g) Get an item.", 22 + spacer, 30);
879 			prt(" d) Drop an item.", 23 + spacer, 30);
880 
881 			prt(" x) eXamine an item.", 22 + spacer, 60);
882 		}
883 		/* Shop commands XXX XXX XXX */
884 		else
885 #endif
886 			display_store_action();
887 
888 		/* Hack - Get rid of the cursor - mikaelh */
889 		Term->scr->cx = Term->wid;
890 		Term->scr->cu = 1;
891 
892 		i = inkey();
893 
894 		if (i) {
895 			/* Process the command */
896 			store_process_command(i);
897 		}
898 	}
899 
900 	/* Tell the server that we're outta here */
901 	Send_store_leave();
902 
903 	/* Clear the screen */
904 	Term_clear();
905 
906 	/* We are no longer "shopping" */
907 	shopping = FALSE;
908 	store.stock_num = 0;
909 
910 	/* Flush any events that happened */
911 	Flush_queue();
912 
913 	/* reload the term */
914 	Term_load();
915 }
916 
917 /* For the new SPECIAL flag for non-inven stores - C. Blue */
display_store_special(void)918 void display_store_special(void) {
919 	int i;
920 	char buf[1024];
921 	/* BIG_MAP leads to big shops */
922 	int spacer = (screen_hgt > SCREEN_HGT) ? 14 : 0;
923 
924 	/* Save the term */
925 	Term_save();
926 
927 	/* We are "shopping" */
928 	shopping = TRUE;
929 
930 	/* Clear screen */
931 	Term_clear();
932 
933 	/* Put the owner name and race */
934 	sprintf(buf, "%s", c_store.owner_name);
935 	put_str(buf, 3, 10);
936 
937 	sprintf(buf, "%s", c_store.store_name);
938 	prt(buf, 3, 50);
939 
940 	/* Display the players remaining gold */
941 	c_store_prt_gold();
942 
943 	/* Don't leave */
944 	leave_store = FALSE;
945 
946 	/* Start at the top */
947 	store_top = 0;
948 
949 	/* Interact with player */
950 	while (!leave_store) {
951 		/* Hack -- Clear line 1 */
952 		prt("", 1, 0);
953 
954 		/* Clear */
955 		clear_from(21 + spacer);
956 
957 		/* Prompt */
958 #if 0 /* keep consistent with display_store() */
959 		prt("You may: ", 21 + spacer, 0);
960 
961 		/* Basic commands */
962 		prt(" ESC) Exit.", 22 + spacer, 0);
963 #else
964 		prt("ESC)   Exit store", 21 + spacer, 0);
965 #endif
966 
967 #if 0
968 		/* Browse if necessary */
969 		if (store.stock_num > 12 + spacer) prt(" SPACE) Next page", 23 + spacer, 0);
970 #endif
971 
972 		/* Shop commands XXX XXX XXX */
973 		display_store_action();
974 
975 		/* Hack - Get rid of the cursor - mikaelh */
976 		Term->scr->cx = Term->wid;
977 		Term->scr->cu = 1;
978 
979 		i = inkey();
980 
981 		if (i) {
982 			/* Process the command */
983 			store_process_command(i);
984 		}
985 	}
986 
987 	/* Tell the server that we're outta here */
988 	Send_store_leave();
989 
990 	/* Clear the screen */
991 	Term_clear();
992 
993 	/* We are no longer "shopping" */
994 	shopping = FALSE;
995 	store.stock_num = 0;
996 
997 	/* Flush any events that happened */
998 	Flush_queue();
999 
1000 	/* reload the term */
1001 	Term_load();
1002 }
1003