summaryrefslogtreecommitdiff
path: root/src/store.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/store.c')
-rw-r--r--src/store.c4458
1 files changed, 0 insertions, 4458 deletions
diff --git a/src/store.c b/src/store.c
deleted file mode 100644
index 78120846..00000000
--- a/src/store.c
+++ /dev/null
@@ -1,4458 +0,0 @@
-/* File: store.c */
-
-/* Purpose: Store commands */
-
-/*
- * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
- *
- * This software may be copied and distributed for educational, research, and
- * not for profit purposes provided that this copyright and statement are
- * included in all such copies.
- */
-
-#include "angband.h"
-
-
-#define RUMOR_CHANCE 8
-
-#define MAX_COMMENT_1 6
-
-static cptr comment_1[MAX_COMMENT_1] =
-{
- "Okay.",
- "Fine.",
- "Accepted!",
- "Agreed!",
- "Done!",
- "Taken!"
-};
-
-#define MAX_COMMENT_2A 2
-
-static cptr comment_2a[MAX_COMMENT_2A] =
-{
- "You try my patience. %s is final.",
- "My patience grows thin. %s is final."
-};
-
-#define MAX_COMMENT_2B 12
-
-static cptr comment_2b[MAX_COMMENT_2B] =
-{
- "I can take no less than %s gold pieces.",
- "I will accept no less than %s gold pieces.",
- "Ha! No less than %s gold pieces.",
- "You knave! No less than %s gold pieces.",
- "That's a pittance! I want %s gold pieces.",
- "That's an insult! I want %s gold pieces.",
- "As if! How about %s gold pieces?",
- "My gosh! How about %s gold pieces?",
- "May the fleas of 1000 orcs molest you! Try %s gold pieces.",
- "May your most favourite weapons rust! Try %s gold pieces.",
- "May Morgoth find you tasty! Perhaps %s gold pieces?",
- "Your mother was an Ogre! Perhaps %s gold pieces?"
-};
-
-#define MAX_COMMENT_3A 2
-
-static cptr comment_3a[MAX_COMMENT_3A] =
-{
- "You try my patience. %s is final.",
- "My patience grows thin. %s is final."
-};
-
-
-#define MAX_COMMENT_3B 12
-
-static cptr comment_3b[MAX_COMMENT_3B] =
-{
- "Perhaps %s gold pieces?",
- "How about %s gold pieces?",
- "I will pay no more than %s gold pieces.",
- "I can afford no more than %s gold pieces.",
- "Be reasonable. How about %s gold pieces?",
- "I'll buy it as scrap for %s gold pieces.",
- "That is too much! How about %s gold pieces?",
- "That looks war surplus! Say %s gold pieces?",
- "Never! %s is more like it.",
- "That's an insult! %s is more like it.",
- "%s gold pieces and be thankful for it!",
- "%s gold pieces and not a copper more!"
-};
-
-#define MAX_COMMENT_4A 4
-
-static cptr comment_4a[MAX_COMMENT_4A] =
-{
- "Enough! You have abused me once too often!",
- "Arghhh! I have had enough abuse for one day!",
- "That does it! You shall waste my time no more!",
- "This is getting nowhere! I'm going to Londis!"
-};
-
-#define MAX_COMMENT_4B 4
-
-static cptr comment_4b[MAX_COMMENT_4B] =
-{
- "Leave my store!",
- "Get out of my sight!",
- "Begone, you scoundrel!",
- "Out, out, out!"
-};
-
-#define MAX_COMMENT_5 8
-
-static cptr comment_5[MAX_COMMENT_5] =
-{
- "Try again.",
- "Ridiculous!",
- "You will have to do better than that!",
- "Do you wish to do business or not?",
- "You've got to be kidding!",
- "You'd better be kidding!",
- "You try my patience.",
- "Hmmm, nice weather we're having."
-};
-
-#define MAX_COMMENT_6 4
-
-static cptr comment_6[MAX_COMMENT_6] =
-{
- "I must have heard you wrong.",
- "I'm sorry, I missed that.",
- "I'm sorry, what was that?",
- "Sorry, what was that again?"
-};
-
-
-
-/*
- * Successful haggle.
- */
-static void say_comment_1(void)
-{
- char rumour[80];
-
- msg_print(comment_1[rand_int(MAX_COMMENT_1)]);
-
- if (randint(RUMOR_CHANCE) == 1 && speak_unique)
- {
- msg_print("The shopkeeper whispers something into your ear:");
- get_rnd_line("rumors.txt", rumour);
- msg_print(rumour);
- }
-}
-
-
-/*
- * Continue haggling (player is buying)
- */
-static void say_comment_2(s32b value, int annoyed)
-{
- char tmp_val[80];
-
- /* Prepare a string to insert */
- strnfmt(tmp_val, 80, "%ld", (long)value);
-
- /* Final offer */
- if (annoyed > 0)
- {
- /* Formatted message */
- msg_format(comment_2a[rand_int(MAX_COMMENT_2A)], tmp_val);
- }
-
- /* Normal offer */
- else
- {
- /* Formatted message */
- msg_format(comment_2b[rand_int(MAX_COMMENT_2B)], tmp_val);
- }
-}
-
-
-/*
- * Continue haggling (player is selling)
- */
-static void say_comment_3(s32b value, int annoyed)
-{
- char tmp_val[80];
-
- /* Prepare a string to insert */
- strnfmt(tmp_val, 80, "%ld", (long)value);
-
- /* Final offer */
- if (annoyed > 0)
- {
- /* Formatted message */
- msg_format(comment_3a[rand_int(MAX_COMMENT_3A)], tmp_val);
- }
-
- /* Normal offer */
- else
- {
- /* Formatted message */
- msg_format(comment_3b[rand_int(MAX_COMMENT_3B)], tmp_val);
- }
-}
-
-
-/*
- * Kick 'da bum out. -RAK-
- */
-static void say_comment_4(void)
-{
- msg_print(comment_4a[rand_int(MAX_COMMENT_4A)]);
- msg_print(comment_4b[rand_int(MAX_COMMENT_4B)]);
-}
-
-
-/*
- * You are insulting me
- */
-static void say_comment_5(void)
-{
- msg_print(comment_5[rand_int(MAX_COMMENT_5)]);
-}
-
-
-/*
- * That makes no sense.
- */
-static void say_comment_6(void)
-{
- msg_print(comment_6[rand_int(5)]);
-}
-
-
-
-/*
- * Messages for reacting to purchase prices.
- */
-
-#define MAX_COMMENT_7A 4
-
-static cptr comment_7a[MAX_COMMENT_7A] =
-{
- "Arrgghh!",
- "You moron!",
- "You hear someone sobbing...",
- "The shopkeeper howls in agony!"
-};
-
-#define MAX_COMMENT_7B 4
-
-static cptr comment_7b[MAX_COMMENT_7B] =
-{
- "Darn!",
- "You fiend!",
- "The shopkeeper yells at you.",
- "The shopkeeper glares at you."
-};
-
-#define MAX_COMMENT_7C 4
-
-static cptr comment_7c[MAX_COMMENT_7C] =
-{
- "Cool!",
- "You've made my day!",
- "The shopkeeper giggles.",
- "The shopkeeper laughs loudly."
-};
-
-#define MAX_COMMENT_7D 4
-
-static cptr comment_7d[MAX_COMMENT_7D] =
-{
- "Yippee!",
- "I think I'll retire!",
- "The shopkeeper jumps for joy.",
- "The shopkeeper smiles gleefully."
-};
-
-/*
- * Let a shop-keeper React to a purchase
- *
- * We paid "price", it was worth "value", and we thought it was worth "guess"
- */
-static void purchase_analyze(s32b price, s32b value, s32b guess)
-{
- /* Item was worthless, but we bought it */
- if ((value <= 0) && (price > value))
- {
- /* Comment */
- msg_print(comment_7a[rand_int(MAX_COMMENT_7A)]);
-
- /* Sound */
- sound(SOUND_STORE1);
- }
-
- /* Item was cheaper than we thought, and we paid more than necessary */
- else if ((value < guess) && (price > value))
- {
- /* Comment */
- msg_print(comment_7b[rand_int(MAX_COMMENT_7B)]);
-
- /* Sound */
- sound(SOUND_STORE2);
- }
-
- /* Item was a good bargain, and we got away with it */
- else if ((value > guess) && (value < (4 * guess)) && (price < value))
- {
- /* Comment */
- msg_print(comment_7c[rand_int(MAX_COMMENT_7C)]);
-
- /* Sound */
- sound(SOUND_STORE3);
- }
-
- /* Item was a great bargain, and we got away with it */
- else if ((value > guess) && (price < value))
- {
- /* Comment */
- msg_print(comment_7d[rand_int(MAX_COMMENT_7D)]);
-
- /* Sound */
- sound(SOUND_STORE4);
- }
-}
-
-
-
-
-
-/*
- * We store the current "store number" here so everyone can access it
- */
-static int cur_store_num = 7;
-
-/*
- * We store the current "store page" here so everyone can access it
- */
-static int store_top = 0;
-
-/*
- * We store the current "store pointer" here so everyone can access it
- */
-static store_type *st_ptr = NULL;
-
-/*
- * We store the current "owner type" here so everyone can access it
- */
-static owner_type *ot_ptr = NULL;
-
-
-
-/*
- * Determine the price of an item (qty one) in a store.
- *
- * This function takes into account the player's charisma, and the
- * shop-keepers friendliness, and the shop-keeper's base greed, but
- * never lets a shop-keeper lose money in a transaction.
- *
- * The "greed" value should exceed 100 when the player is "buying" the
- * item, and should be less than 100 when the player is "selling" it.
- *
- * Hack -- the black market always charges twice as much as it should.
- *
- * Charisma adjustment runs from 80 to 130
- * Racial adjustment runs from 95 to 130
- *
- * Since greed/charisma/racial adjustments are centered at 100, we need
- * to adjust (by 200) to extract a usable multiplier. Note that the
- * "greed" value is always something (?).
- */
-static s32b price_item(object_type *o_ptr, int greed, bool_ flip)
-{
- int factor;
- int adjust;
- s32b price;
-
-
- /* Get the value of one of the items */
- price = object_value(o_ptr);
-
- /* Worthless items */
- if (price <= 0) return (0L);
-
- /* Compute the racial factor */
- if (is_state(st_ptr, STORE_LIKED))
- {
- factor = ot_ptr->costs[STORE_LIKED];
- }
- else if (is_state(st_ptr, STORE_HATED))
- {
- factor = ot_ptr->costs[STORE_HATED];
- }
- else
- {
- factor = ot_ptr->costs[STORE_NORMAL];
- }
-
- /* Add in the charisma factor */
- factor += adj_chr_gold[p_ptr->stat_ind[A_CHR]];
-
- /* Shop is buying */
- if (flip)
- {
- /* Mega Hack^3 */
- switch (o_ptr->tval)
- {
- case TV_SHOT:
- case TV_ARROW:
- case TV_BOLT:
- price /= 5;
- break;
- }
-
- /* Adjust for greed */
- adjust = 100 + (300 - (greed + factor));
-
- /* Never get "silly" */
- if (adjust > 100) adjust = 100;
-
- /* Mega-Hack -- Black market sucks */
- if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM) price = price / 2;
- }
-
- /* Shop is selling */
- else
- {
- /* Adjust for greed */
- adjust = 100 + ((greed + factor) - 300);
-
- /* Never get "silly" */
- if (adjust < 100) adjust = 100;
-
- /* Mega-Hack -- Black market sucks */
- if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM) price = price * 2;
- }
-
- /* Compute the final price (with rounding) */
- price = (price * adjust + 50L) / 100L;
-
- /* Note -- Never become "free" */
- if (price <= 0L) return (1L);
-
- /* Return the price */
- return (price);
-}
-
-
-/*
- * Special "mass production" computation
- */
-static int mass_roll(int num, int max)
-{
- int i, t = 0;
- for (i = 0; i < num; i++) t += rand_int(max);
- return (t);
-}
-
-
-/*
- * Certain "cheap" objects should be created in "piles"
- * Some objects can be sold at a "discount" (in small piles)
- */
-static void mass_produce(object_type *o_ptr)
-{
- int size = 1;
- int discount = 0;
-
- s32b cost = object_value(o_ptr);
-
-
- /* Analyze the type */
- switch (o_ptr->tval)
- {
- /* Food, Flasks, and Lites */
- case TV_FOOD:
- case TV_FLASK:
- case TV_LITE:
- {
- if (cost <= 5L) size += mass_roll(3, 5);
- if (cost <= 20L) size += mass_roll(3, 5);
- break;
- }
-
- case TV_POTION:
- case TV_POTION2:
- case TV_SCROLL:
- {
- if (cost <= 60L) size += mass_roll(3, 5);
- if (cost <= 240L) size += mass_roll(1, 5);
- break;
- }
-
- case TV_SYMBIOTIC_BOOK:
- case TV_MUSIC_BOOK:
- case TV_DRUID_BOOK:
- case TV_DAEMON_BOOK:
- case TV_BOOK:
- {
- if (cost <= 50L) size += mass_roll(2, 3);
- if (cost <= 500L) size += mass_roll(1, 3);
- break;
- }
-
- case TV_SOFT_ARMOR:
- case TV_HARD_ARMOR:
- case TV_SHIELD:
- case TV_GLOVES:
- case TV_BOOTS:
- case TV_CLOAK:
- case TV_HELM:
- case TV_CROWN:
- case TV_SWORD:
- case TV_AXE:
- case TV_POLEARM:
- case TV_HAFTED:
- case TV_DIGGING:
- case TV_BOW:
- {
- if (o_ptr->name2) break;
- if (cost <= 10L) size += mass_roll(3, 5);
- if (cost <= 100L) size += mass_roll(3, 5);
- break;
- }
-
- case TV_SPIKE:
- case TV_SHOT:
- case TV_ARROW:
- case TV_BOLT:
- {
- if (cost <= 5L) size += mass_roll(5, 5);
- if (cost <= 50L) size += mass_roll(5, 5);
- if (cost <= 500L) size += mass_roll(5, 5);
- break;
- }
-
- /* Because many rods (and a few wands and staffs) are useful mainly
- * in quantity, the Black Market will occasionally have a bunch of
- * one kind. -LM- */
- case TV_ROD:
- case TV_WAND:
- case TV_STAFF:
- {
- if (cost < 1601L) size += mass_roll(1, 5);
- else if (cost < 3201L) size += mass_roll(1, 3);
- break;
- }
- }
-
-
- /* Pick a discount */
- if (cost < 5)
- {
- discount = 0;
- }
- else if (rand_int(25) == 0)
- {
- discount = 25;
- }
- else if (rand_int(150) == 0)
- {
- discount = 50;
- }
- else if (rand_int(300) == 0)
- {
- discount = 75;
- }
- else if (rand_int(500) == 0)
- {
- discount = 90;
- }
-
-
- if (o_ptr->art_name)
- {
- if (cheat_peek && discount)
- {
- msg_print("No discount on random artifacts.");
- }
- discount = 0;
- }
-
- /* Save the discount */
- o_ptr->discount = discount;
-
- /* Save the total pile size */
- o_ptr->number = size - (size * discount / 100);
-}
-
-
-
-
-
-
-
-
-/*
- * Determine if a store item can "absorb" another item
- *
- * See "object_similar()" for the same function for the "player"
- */
-static bool_ store_object_similar(object_type *o_ptr, object_type *j_ptr)
-{
- /* Hack -- Identical items cannot be stacked */
- if (o_ptr == j_ptr) return (0);
-
- /* Different objects cannot be stacked */
- if (o_ptr->k_idx != j_ptr->k_idx) return (0);
-
- /* Different charges (etc) cannot be stacked, unless wands or rods. */
- if ((o_ptr->pval != j_ptr->pval) && (o_ptr->tval != TV_WAND)) return (0);
-
- /* Require many identical values */
- if (o_ptr->pval2 != j_ptr->pval2) return (0);
- if (o_ptr->pval3 != j_ptr->pval3) return (0);
-
- /* Require many identical values */
- if (o_ptr->to_h != j_ptr->to_h) return (0);
- if (o_ptr->to_d != j_ptr->to_d) return (0);
- if (o_ptr->to_a != j_ptr->to_a) return (0);
-
- /* Require identical "artifact" names */
- if (o_ptr->name1 != j_ptr->name1) return (0);
-
- /* Require identical "ego-item" names */
- if (o_ptr->name2 != j_ptr->name2) return (0);
-
- /* Require identical "ego-item" names */
- if (o_ptr->name2b != j_ptr->name2b) return (0);
-
- /* Random artifacts don't stack !*/
- if (o_ptr->art_name || j_ptr->art_name) return (0);
-
- /* Hack -- Identical art_flags! */
- if ((o_ptr->art_flags1 != j_ptr->art_flags1) ||
- (o_ptr->art_flags2 != j_ptr->art_flags2) ||
- (o_ptr->art_flags3 != j_ptr->art_flags3))
- return (0);
-
- /* Hack -- Never stack "powerful" items */
- if (o_ptr->xtra1 || j_ptr->xtra1) return (0);
-
- if (o_ptr->tval == TV_LITE)
- {
- /* Require identical "turns of light" */
- if (o_ptr->timeout != j_ptr->timeout) return (0);
- }
- else
- {
- /* Hack -- Never stack recharging items */
- if (o_ptr->timeout || j_ptr->timeout) return (0);
- }
-
- /* Require many identical values */
- if (o_ptr->ac != j_ptr->ac) return (0);
- if (o_ptr->dd != j_ptr->dd) return (0);
- if (o_ptr->ds != j_ptr->ds) return (0);
-
- /* Hack -- Never stack chests */
- if (o_ptr->tval == TV_CHEST) return (0);
-
- /* Require matching discounts */
- if (o_ptr->discount != j_ptr->discount) return (0);
-
- /* They match, so they must be similar */
- return (TRUE);
-}
-
-
-/*
- * Allow a store item to absorb another item
- */
-static void store_object_absorb(object_type *o_ptr, object_type *j_ptr)
-{
- int total = o_ptr->number + j_ptr->number;
-
- /* Combine quantity, lose excess items */
- o_ptr->number = (total > 99) ? 99 : total;
-
- /* Hack -- if wands are stacking, combine the charges. -LM- */
- if (o_ptr->tval == TV_WAND)
- {
- o_ptr->pval += j_ptr->pval;
- }
-}
-
-
-/*
- * Check to see if the shop will be carrying too many objects -RAK-
- * Note that the shop, just like a player, will not accept things
- * it cannot hold. Before, one could "nuke" potions this way.
- */
-static bool_ store_check_num(object_type *o_ptr)
-{
- int i;
- object_type *j_ptr;
-
- /* Free space is always usable */
- if (st_ptr->stock_num < st_ptr->stock_size) return TRUE;
-
- /* The "home" acts like the player */
- if ((cur_store_num == 7) ||
- (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM))
- {
- /* Check all the items */
- for (i = 0; i < st_ptr->stock_num; i++)
- {
- /* Get the existing item */
- j_ptr = &st_ptr->stock[i];
-
- /* Can the new object be combined with the old one? */
- if (object_similar(j_ptr, o_ptr)) return (TRUE);
- }
- }
-
- /* Normal stores do special stuff */
- else
- {
- /* Check all the items */
- for (i = 0; i < st_ptr->stock_num; i++)
- {
- /* Get the existing item */
- j_ptr = &st_ptr->stock[i];
-
- /* Can the new object be combined with the old one? */
- if (store_object_similar(j_ptr, o_ptr)) return (TRUE);
- }
- }
-
- /* But there was no room at the inn... */
- return (FALSE);
-}
-
-
-bool_ is_blessed(object_type *o_ptr)
-{
- u32b f1, f2, f3, f4, f5, esp;
- object_flags_known(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if (f3 & TR3_BLESSED) return (TRUE);
- else return (FALSE);
-}
-
-
-
-/*
- * Determine if the current store will purchase the given item
- *
- * Note that a shop-keeper must refuse to buy "worthless" items
- */
-static bool_ store_will_buy(object_type *o_ptr)
-{
- /* Hack -- The Home is simple */
- if (cur_store_num == 7) return (TRUE);
-
- if (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM) return TRUE;
-
- /* XXX XXX XXX Ignore "worthless" items */
- if (object_value(o_ptr) <= 0) return (FALSE);
-
- /* Lua can define things to buy */
- if (process_hooks_ret(HOOK_STORE_BUY, "d", "(d,s,O)", st_ptr->st_idx, st_info[st_ptr->st_idx].name + st_name, o_ptr))
- {
- return process_hooks_return[0].num;
- }
-
- /* Assume not okay */
- return (FALSE);
-}
-
-
-
-/*
- * Add the item "o_ptr" to the inventory of the "Home"
- *
- * In all cases, return the slot (or -1) where the object was placed
- *
- * Note that this is a hacked up version of "inven_carry()".
- *
- * Also note that it may not correctly "adapt" to "knowledge" bacoming
- * known, the player may have to pick stuff up and drop it again.
- */
-static int home_carry(object_type *o_ptr)
-{
- int slot;
- s32b value, j_value;
- int i;
- object_type *j_ptr;
-
-
- /* Check each existing item (try to combine) */
- for (slot = 0; slot < st_ptr->stock_num; slot++)
- {
- /* Get the existing item */
- j_ptr = &st_ptr->stock[slot];
-
- /* The home acts just like the player */
- if (object_similar(j_ptr, o_ptr))
- {
- /* Save the new number of items */
- object_absorb(j_ptr, o_ptr);
-
- /* All done */
- return (slot);
- }
- }
-
- /* No space? */
- if (st_ptr->stock_num >= st_ptr->stock_size) return ( -1);
-
-
- /* Determine the "value" of the item */
- value = object_value(o_ptr);
-
- /* Check existing slots to see if we must "slide" */
- for (slot = 0; slot < st_ptr->stock_num; slot++)
- {
- /* Get that item */
- j_ptr = &st_ptr->stock[slot];
-
- /* Objects sort by decreasing type */
- if (o_ptr->tval > j_ptr->tval) break;
- if (o_ptr->tval < j_ptr->tval) continue;
-
- /* Can happen in the home */
- if (!object_aware_p(o_ptr)) continue;
- if (!object_aware_p(j_ptr)) break;
-
- /* Objects sort by increasing sval */
- if (o_ptr->sval < j_ptr->sval) break;
- if (o_ptr->sval > j_ptr->sval) continue;
-
- /* Objects in the home can be unknown */
- if (!object_known_p(o_ptr)) continue;
- if (!object_known_p(j_ptr)) break;
-
-
- /*
- * Hack: otherwise identical rods sort by
- * increasing recharge time --dsb
- */
- if (o_ptr->tval == TV_ROD_MAIN)
- {
- if (o_ptr->timeout < j_ptr->timeout) break;
- if (o_ptr->timeout > j_ptr->timeout) continue;
- }
-
- /* Objects sort by decreasing value */
- j_value = object_value(j_ptr);
- if (value > j_value) break;
- if (value < j_value) continue;
- }
-
- /* Slide the others up */
- for (i = st_ptr->stock_num; i > slot; i--)
- {
- st_ptr->stock[i] = st_ptr->stock[i - 1];
- }
-
- /* More stuff now */
- st_ptr->stock_num++;
-
- /* Insert the new item */
- st_ptr->stock[slot] = *o_ptr;
-
- /* Return the location */
- return (slot);
-}
-
-
-/*
- * Add the item "o_ptr" to a real stores inventory.
- *
- * If the item is "worthless", it is thrown away (except in the home).
- *
- * If the item cannot be combined with an object already in the inventory,
- * make a new slot for it, and calculate its "per item" price. Note that
- * this price will be negative, since the price will not be "fixed" yet.
- * Adding an item to a "fixed" price stack will not change the fixed price.
- *
- * In all cases, return the slot (or -1) where the object was placed
- */
-static int store_carry(object_type *o_ptr)
-{
- int i, slot;
- s32b value, j_value;
- object_type *j_ptr;
-
-
- /* Evaluate the object */
- value = object_value(o_ptr);
-
- /* Cursed/Worthless items "disappear" when sold */
- if (value <= 0) return ( -1);
-
- /* All store items are fully *identified* */
- o_ptr->ident |= IDENT_MENTAL;
-
- /* Erase the inscription */
- o_ptr->note = 0;
-
- /* Check each existing item (try to combine) */
- for (slot = 0; slot < st_ptr->stock_num; slot++)
- {
- /* Get the existing item */
- j_ptr = &st_ptr->stock[slot];
-
- /* Can the existing items be incremented? */
- if (store_object_similar(j_ptr, o_ptr))
- {
- /* Hack -- extra items disappear */
- store_object_absorb(j_ptr, o_ptr);
-
- /* All done */
- return (slot);
- }
- }
-
- /* No space? */
- if (st_ptr->stock_num >= st_ptr->stock_size) return ( -1);
-
-
- /* Check existing slots to see if we must "slide" */
- for (slot = 0; slot < st_ptr->stock_num; slot++)
- {
- /* Get that item */
- j_ptr = &st_ptr->stock[slot];
-
- /* Objects sort by decreasing type */
- if (o_ptr->tval > j_ptr->tval) break;
- if (o_ptr->tval < j_ptr->tval) continue;
-
- /* Objects sort by increasing sval */
- if (o_ptr->sval < j_ptr->sval) break;
- if (o_ptr->sval > j_ptr->sval) continue;
-
-
- /*
- * Hack: otherwise identical rods sort by
- * increasing recharge time --dsb
- */
- if (o_ptr->tval == TV_ROD_MAIN)
- {
- if (o_ptr->timeout < j_ptr->timeout) break;
- if (o_ptr->timeout > j_ptr->timeout) continue;
- }
-
- /* Evaluate that slot */
- j_value = object_value(j_ptr);
-
- /* Objects sort by decreasing value */
- if (value > j_value) break;
- if (value < j_value) continue;
- }
-
- /* Slide the others up */
- for (i = st_ptr->stock_num; i > slot; i--)
- {
- st_ptr->stock[i] = st_ptr->stock[i - 1];
- }
-
- /* More stuff now */
- st_ptr->stock_num++;
-
- /* Insert the new item */
- st_ptr->stock[slot] = *o_ptr;
-
- /* Return the location */
- return (slot);
-}
-
-
-/*
- * Increase, by a given amount, the number of a certain item
- * in a certain store. This can result in zero items.
- */
-static void store_item_increase(int item, int num)
-{
- int cnt;
- object_type *o_ptr;
-
- /* Get the item */
- o_ptr = &st_ptr->stock[item];
-
- /* Verify the number */
- cnt = o_ptr->number + num;
- if (cnt > 255) cnt = 255;
- else if (cnt < 0) cnt = 0;
- num = cnt - o_ptr->number;
-
- /* Save the new number */
- o_ptr->number += num;
-}
-
-
-/*
- * Remove a slot if it is empty
- */
-static void store_item_optimize(int item)
-{
- int j;
- object_type *o_ptr;
-
- /* Get the item */
- o_ptr = &st_ptr->stock[item];
-
- /* Must exist */
- if (!o_ptr->k_idx) return;
-
- /* Must have no items */
- if (o_ptr->number) return;
-
- /* One less item */
- st_ptr->stock_num--;
-
- /* Slide everyone */
- for (j = item; j < st_ptr->stock_num; j++)
- {
- st_ptr->stock[j] = st_ptr->stock[j + 1];
- }
-
- /* Nuke the final slot */
- object_wipe(&st_ptr->stock[j]);
-}
-
-
-/*
- * This function will keep 'crap' out of the black market.
- * Crap is defined as any item that is "available" elsewhere
- * Based on a suggestion by "Lee Vogt" <lvogt@cig.mcel.mot.com>
- */
-static bool_ black_market_crap(object_type *o_ptr)
-{
- int i, j;
-
- /* Ego items are never crap */
- if (o_ptr->name2) return (FALSE);
-
- /* Good items are never crap */
- if (o_ptr->to_a > 0) return (FALSE);
- if (o_ptr->to_h > 0) return (FALSE);
- if (o_ptr->to_d > 0) return (FALSE);
-
- /* Check all stores */
- for (i = 0; i < max_st_idx; i++)
- {
- if (i == STORE_HOME) continue;
- if (st_info[i].flags1 & SF1_MUSEUM) continue;
-
- /* Check every item in the store */
- for (j = 0; j < town_info[p_ptr->town_num].store[i].stock_num; j++)
- {
- object_type *j_ptr = &town_info[p_ptr->town_num].store[i].stock[j];
-
- /* Duplicate item "type", assume crappy */
- if (o_ptr->k_idx == j_ptr->k_idx) return (TRUE);
- }
- }
-
- /* Assume okay */
- return (FALSE);
-}
-
-
-/*
- * Attempt to delete (some of) a random item from the store
- * Hack -- we attempt to "maintain" piles of items when possible.
- */
-static void store_delete(void)
-{
- int what, num;
-
- /* Pick a random slot */
- what = rand_int(st_ptr->stock_num);
-
- /* Determine how many items are here */
- num = st_ptr->stock[what].number;
-
- /* Hack -- sometimes, only destroy half the items */
- if (rand_int(100) < 50) num = (num + 1) / 2;
-
- /* Hack -- sometimes, only destroy a single item */
- if (rand_int(100) < 50) num = 1;
-
- /* Hack -- decrement the maximum timeouts and total charges of rods and wands. -LM- */
- if (st_ptr->stock[what].tval == TV_WAND)
- {
- st_ptr->stock[what].pval -= num * st_ptr->stock[what].pval / st_ptr->stock[what].number;
- }
-
- /* Actually destroy (part of) the item */
- store_item_increase(what, -num);
- store_item_optimize(what);
-}
-
-/* Analyze store flags and return a level */
-int return_level()
-{
- store_info_type *sti_ptr = &st_info[st_ptr->st_idx];
- int level;
-
- if (sti_ptr->flags1 & SF1_RANDOM) level = 0;
- else level = rand_range(1, STORE_OBJ_LEVEL);
-
- if (sti_ptr->flags1 & SF1_DEPEND_LEVEL) level += dun_level;
-
- if (sti_ptr->flags1 & SF1_SHALLOW_LEVEL) level += 5 + rand_int(5);
- if (sti_ptr->flags1 & SF1_MEDIUM_LEVEL) level += 25 + rand_int(25);
- if (sti_ptr->flags1 & SF1_DEEP_LEVEL) level += 45 + rand_int(45);
-
- if (sti_ptr->flags1 & SF1_ALL_ITEM) level += p_ptr->lev;
-
- return (level);
-}
-
-/* Is it an ok object ? */
-static int store_tval = 0, store_level = 0;
-
-/*
- * Hack -- determine if a template is "good"
- */
-static bool_ kind_is_storeok(int k_idx)
-{
- object_kind *k_ptr = &k_info[k_idx];
-
- if (k_info[k_idx].flags3 & TR3_NORM_ART)
- return ( FALSE );
-
- if (k_info[k_idx].flags3 & TR3_INSTA_ART)
- return ( FALSE );
-
- if (!kind_is_legal(k_idx)) return FALSE;
-
- if (k_ptr->tval != store_tval) return (FALSE);
- if (k_ptr->level < (store_level / 2)) return (FALSE);
-
- return (TRUE);
-}
-
-/*
- * Creates a random item and gives it to a store
- * This algorithm needs to be rethought. A lot.
- *
- * Note -- the "level" given to "obj_get_num()" is a "favored"
- * level, that is, there is a much higher chance of getting
- * items with a level approaching that of the given level...
- *
- * Should we check for "permission" to have the given item?
- */
-static void store_create(void)
-{
- int i = 0, tries, level = 0, chance, item;
-
- object_type forge;
- object_type *q_ptr = NULL;
- bool_ obj_all_done = FALSE;
-
-
- /* Paranoia -- no room left */
- if (st_ptr->stock_num >= st_ptr->stock_size) return;
-
-
- /* Hack -- consider up to four items */
- for (tries = 0; tries < 4; tries++)
- {
- obj_all_done = FALSE;
-
- /* Lua can define things to buy */
- if (process_hooks_ret(HOOK_STORE_STOCK, "O", "(d,s,d)", st_ptr->st_idx, st_info[st_ptr->st_idx].name + st_name, return_level()))
- {
- obj_all_done = TRUE;
- q_ptr = process_hooks_return[0].o_ptr;
- }
-
- /* Black Market */
- else if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM)
- {
- obj_theme theme;
-
- /* No themes */
- theme.treasure = 100;
- theme.combat = 100;
- theme.magic = 100;
- theme.tools = 100;
- init_match_theme(theme);
-
- /*
- * Even in Black Markets, illegal objects can be
- * problematic -- Oxymoron?
- */
- get_obj_num_hook = kind_is_legal;
-
- /* Rebuild the allocation table */
- get_obj_num_prep();
-
- /* Pick a level for object/magic */
- level = return_level();
-
- /* Random item (usually of given level) */
- i = get_obj_num(level);
-
- /* Invalidate the cached allocation table */
- alloc_kind_table_valid = FALSE;
-
- /* Handle failure */
- if (!i) continue;
-
- }
-
- /* Normal Store */
- else
- {
- /* Hack -- Pick an item to sell */
- item = rand_int(st_info[st_ptr->st_idx].table_num);
- i = st_info[st_ptr->st_idx].table[item][0];
- chance = st_info[st_ptr->st_idx].table[item][1];
-
- /* Don't allow k_info artifacts */
- if ((i <= 10000) && (k_info[i].flags3 & TR3_NORM_ART))
- continue;
-
- /* Does it passes the rarity check ? */
- if (!magik(chance)) continue;
-
- /* Hack -- fake level for apply_magic() */
- level = return_level();
-
- /* Hack -- i > 10000 means it's a tval and all svals are allowed */
- if (i > 10000)
- {
- obj_theme theme;
-
- /* No themes */
- theme.treasure = 100;
- theme.combat = 100;
- theme.magic = 100;
- theme.tools = 100;
- init_match_theme(theme);
-
- /* Activate restriction */
- get_obj_num_hook = kind_is_storeok;
- store_tval = i - 10000;
-
- /* Do we forbid too shallow items ? */
- if (st_info[st_ptr->st_idx].flags1 & SF1_FORCE_LEVEL) store_level = level;
- else store_level = 0;
-
- /* Prepare allocation table */
- get_obj_num_prep();
-
- /* Get it ! */
- i = get_obj_num(level);
-
- /* Invalidate the cached allocation table */
- alloc_kind_table_valid = FALSE;
- }
-
- if (!i) continue;
- }
-
- /* Only if not already done */
- if (!obj_all_done)
- {
- /* Don't allow k_info artifacts */
- if (k_info[i].flags3 & TR3_NORM_ART)
- continue;
-
- /* Don't allow artifacts */
- if (k_info[i].flags3 & TR3_INSTA_ART)
- continue;
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Create a new object of the chosen kind */
- object_prep(q_ptr, i);
-
- /* Apply some "low-level" magic (no artifacts) */
- apply_magic(q_ptr, level, FALSE, FALSE, FALSE);
-
- /* Hack -- Charge lite's */
- if (q_ptr->tval == TV_LITE)
- {
- u32b f1, f2, f3, f4, f5, esp;
-
- object_flags(q_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- if (f4 & TR4_FUEL_LITE) q_ptr->timeout = k_info[q_ptr->k_idx].pval2;
- }
-
- }
-
- /* The item is "known" */
- object_known(q_ptr);
-
- /* Mark it storebought */
- q_ptr->ident |= IDENT_STOREB;
-
- /* Mega-Hack -- no chests in stores */
- if (q_ptr->tval == TV_CHEST) continue;
-
- /* Prune the black market */
- if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM)
- {
- /* Hack -- No "crappy" items */
- if (black_market_crap(q_ptr)) continue;
-
- /* Hack -- No "cheap" items */
- if (object_value(q_ptr) < 10) continue;
- }
-
- /* Prune normal stores */
- else
- {
- /* No "worthless" items */
- if (object_value(q_ptr) <= 0) continue;
- }
-
-
- /* Mass produce and/or Apply discount */
- mass_produce(q_ptr);
-
- /* The charges an wands are per each, so multiply to get correct number */
- if (!obj_all_done && q_ptr->tval == TV_WAND)
- {
- q_ptr->pval *= q_ptr->number;
- }
-
- /* Attempt to carry the (known) item */
- (void)store_carry(q_ptr);
-
- /* Definitely done */
- break;
- }
-}
-
-
-
-/*
- * Eliminate need to bargain if player has haggled well in the past
- */
-static bool_ noneedtobargain(s32b minprice)
-{
- s32b good = st_ptr->good_buy;
- s32b bad = st_ptr->bad_buy;
-
- /* Cheap items are "boring" */
- if (minprice < 10L) return (TRUE);
-
- /* Perfect haggling */
- if (good == MAX_SHORT) return (TRUE);
-
- /* Reward good haggles, punish bad haggles, notice price */
- if (good > ((3 * bad) + (5 + (minprice / 50)))) return (TRUE);
-
- /* Return the flag */
- return (FALSE);
-}
-
-
-/*
- * Update the bargain info
- */
-static void updatebargain(s32b price, s32b minprice)
-{
- /* Hack -- auto-haggle */
- if (auto_haggle) return;
-
- /* Cheap items are "boring" */
- if (minprice < 10L) return;
-
- /* Count the successful haggles */
- if (price == minprice)
- {
- /* Just count the good haggles */
- if (st_ptr->good_buy < MAX_SHORT)
- {
- st_ptr->good_buy++;
- }
- }
-
- /* Count the failed haggles */
- else
- {
- /* Just count the bad haggles */
- if (st_ptr->bad_buy < MAX_SHORT)
- {
- st_ptr->bad_buy++;
- }
- }
-}
-
-
-
-/*
- * Re-displays a single store entry
- */
-static void display_entry(int pos)
-{
- int i, cur_col;
- object_type *o_ptr;
- s32b x;
-
- char o_name[80];
- char out_val[160];
-
-
- int maxwid = 75;
-
- /* Get the item */
- o_ptr = &st_ptr->stock[pos];
-
- /* Get the "offset" */
- i = (pos % 12);
-
- /* Label it, clear the line --(-- */
- strnfmt(out_val, 160, "%c) ", I2A(i));
- c_prt(get_item_letter_color(o_ptr), out_val, i + 6, 0);
-
-
- cur_col = 3;
- if (show_store_graph)
- {
- byte a = object_attr(o_ptr);
- char c = object_char(o_ptr);
-
- if (!o_ptr->k_idx) c = ' ';
-
- Term_draw(cur_col, i + 6, a, c);
- if (use_bigtile)
- {
- cur_col++;
- if (a & 0x80)
- Term_draw(cur_col, i + 6, 255, 255);
- }
- cur_col += 2;
- }
-
- /* Describe an item in the home */
- if ((cur_store_num == 7) ||
- (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM))
- {
- maxwid = 75;
-
- /* Leave room for weights, if necessary -DRS- */
- if (show_weights) maxwid -= 10;
-
- /* Describe the object */
- object_desc(o_name, o_ptr, TRUE, 3);
- o_name[maxwid] = '\0';
- c_put_str(tval_to_attr[o_ptr->tval], o_name, i + 6, cur_col);
-
- /* Show weights */
- if (show_weights)
- {
- /* Only show the weight of an individual item */
- int wgt = o_ptr->weight;
- strnfmt(out_val, 160, "%3d.%d lb", wgt / 10, wgt % 10);
- put_str(out_val, i + 6, 68);
- }
- }
-
- /* Describe an item (fully) in a store */
- else
- {
- byte color = TERM_WHITE;
-
- /* Must leave room for the "price" */
- maxwid = 65;
-
- /* Leave room for weights, if necessary -DRS- */
- if (show_weights) maxwid -= 7;
-
- /* Describe the object (fully) */
- object_desc_store(o_name, o_ptr, TRUE, 3);
- o_name[maxwid] = '\0';
- c_put_str(tval_to_attr[o_ptr->tval], o_name, i + 6, cur_col);
-
- /* Show weights */
- if (show_weights)
- {
- /* Only show the weight of an individual item */
- int wgt = o_ptr->weight;
- strnfmt(out_val, 160, "%3d.%d", wgt / 10, wgt % 10);
- put_str(out_val, i + 6, 61);
- }
-
- /* Display a "fixed" cost */
- if (o_ptr->ident & (IDENT_FIXED))
- {
- /* Extract the "minimum" price */
- x = price_item(o_ptr, ot_ptr->min_inflate, FALSE);
-
- /* Can we buy one ? */
- if (x > p_ptr->au) color = TERM_L_DARK;
-
- /* Actually draw the price (not fixed) */
- strnfmt(out_val, 160, "%9ld F", (long)x);
- c_put_str(color, out_val, i + 6, 68);
- }
-
- /* Display a "taxed" cost */
- else if (auto_haggle)
- {
- /* Extract the "minimum" price */
- x = price_item(o_ptr, ot_ptr->min_inflate, FALSE);
-
- /* Hack -- Apply Sales Tax if needed */
- if (!noneedtobargain(x)) x += x / 10;
-
- /* Can we buy one ? */
- if (x > p_ptr->au) color = TERM_L_DARK;
-
- /* Actually draw the price (with tax) */
- strnfmt(out_val, 160, "%9ld ", (long)x);
- c_put_str(color, out_val, i + 6, 68);
- }
-
- /* Display a "haggle" cost */
- else
- {
- /* Extrect the "maximum" price */
- x = price_item(o_ptr, ot_ptr->max_inflate, FALSE);
-
- /* Can we buy one ? */
- if (x > p_ptr->au) color = TERM_L_DARK;
-
- /* Actually draw the price (not fixed) */
- strnfmt(out_val, 160, "%9ld ", (long)x);
- c_put_str(color, out_val, i + 6, 68);
- }
- }
-}
-
-
-/*
- * Displays a store's inventory -RAK-
- * All prices are listed as "per individual object". -BEN-
- */
-static void display_inventory(void)
-{
- int i, k;
-
- /* Display the next 12 items */
- for (k = 0; k < 12; k++)
- {
- /* Do not display "dead" items */
- if (store_top + k >= st_ptr->stock_num) break;
-
- /* Display that line */
- display_entry(store_top + k);
- }
-
- /* Erase the extra lines and the "more" prompt */
- for (i = k; i < 13; i++) prt("", i + 6, 0);
-
- /* Assume "no current page" */
- put_str(" ", 5, 20);
-
- /* Visual reminder of "more items" */
- if (st_ptr->stock_num > 12)
- {
- /* Show "more" reminder (after the last item) */
- prt("-more-", k + 6, 3);
-
- /* Indicate the "current page" */
- put_str(format("(Page %d) ", store_top / 12 + 1), 5, 20);
- }
-}
-
-
-/*
- * Displays players gold -RAK-
- */
-void store_prt_gold(void)
-{
- char out_val[64];
-
- prt("Gold Remaining: ", 19, 53);
-
- strnfmt(out_val, 64, "%9ld", (long)p_ptr->au);
- prt(out_val, 19, 68);
-}
-
-
-/*
- * Displays store (after clearing screen) -RAK-
- */
-void display_store(void)
-{
- char buf[80];
-
-
- /* Clear screen */
- Term_clear();
-
- /* The "Home" is special */
- if (cur_store_num == 7)
- {
- put_str("Your Home", 3, 30);
-
- /* Label the item descriptions */
- put_str("Item Description", 5, 3);
-
- /* If showing weights, show label */
- if (show_weights)
- {
- put_str("Weight", 5, 70);
- }
- }
-
- else if (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM)
- {
- cptr store_name = (st_name + st_info[cur_store_num].name);
-
- /* Show the name of the store */
- strnfmt(buf, 80, "%s", store_name);
- prt(buf, 3, 30);
-
- /* Label the item descriptions */
- put_str("Item Description", 5, 3);
-
- /* If showing weights, show label */
- if (show_weights)
- {
- put_str("Weight", 5, 70);
- }
- }
-
- /* Normal stores */
- else
- {
- cptr store_name = (st_name + st_info[cur_store_num].name);
- cptr owner_name = (ow_name + ot_ptr->name);
-
- /* Put the owner name and race */
- strnfmt(buf, 80, "%s", owner_name);
- put_str(buf, 3, 10);
-
- /* Show the max price in the store (above prices) */
- strnfmt(buf, 80, "%s (%ld)", store_name, (long)(ot_ptr->max_cost));
- prt(buf, 3, 50);
-
- /* Label the item descriptions */
- put_str("Item Description", 5, 3);
-
- /* If showing weights, show label */
- if (show_weights)
- {
- put_str("Weight", 5, 60);
- }
-
- /* Label the asking price (in stores) */
- put_str("Price", 5, 72);
- }
-
- /* Display the current gold */
- store_prt_gold();
-
- /* Draw in the inventory */
- display_inventory();
-}
-
-
-
-/*
- * Get the ID of a store item and return its value -RAK-
- */
-static int get_stock(int *com_val, cptr pmt, int i, int j)
-{
- char command;
-
- char out_val[160];
-
- /* Get the item index */
- if (repeat_pull(com_val))
- {
-
- /* Verify the item */
- if ((*com_val >= i) && (*com_val <= j))
- {
- /* Success */
- return (TRUE);
- }
- }
-
- /* Paranoia XXX XXX XXX */
- msg_print(NULL);
-
-
- /* Assume failure */
- *com_val = ( -1);
-
- /* Build the prompt */
- strnfmt(out_val, 160, "(Items %c-%c, ESC to exit) %s",
- I2A(i), I2A(j), pmt);
-
- /* Ask until done */
- while (TRUE)
- {
- int k;
-
- /* Escape */
- if (!get_com(out_val, &command)) break;
-
- /* Convert */
- k = (islower(command) ? A2I(command) : -1);
-
- /* Legal responses */
- if ((k >= i) && (k <= j))
- {
- *com_val = k;
- break;
- }
-
- /* Oops */
- bell();
- }
-
- /* Clear the prompt */
- prt("", 0, 0);
-
- /* Cancel */
- if (command == ESCAPE) return (FALSE);
-
- repeat_push(*com_val);
-
- /* Success */
- return (TRUE);
-}
-
-
-/*
- * Increase the insult counter and get angry if too many -RAK-
- */
-static int increase_insults(void)
-{
- /* Increase insults */
- st_ptr->insult_cur++;
-
- /* Become insulted */
- if (st_ptr->insult_cur > ot_ptr->insult_max)
- {
- /* Complain */
- say_comment_4();
-
- /* Reset insults */
- st_ptr->insult_cur = 0;
- st_ptr->good_buy = 0;
- st_ptr->bad_buy = 0;
-
- /* Open tomorrow */
- st_ptr->store_open = turn + 25000 + randint(25000);
-
- /* Closed */
- return (TRUE);
- }
-
- /* Not closed */
- return (FALSE);
-}
-
-
-/*
- * Decrease insults -RAK-
- */
-static void decrease_insults(void)
-{
- /* Decrease insults */
- if (st_ptr->insult_cur) st_ptr->insult_cur--;
-}
-
-
-/*
- * Have insulted while haggling -RAK-
- */
-static int haggle_insults(void)
-{
- /* Increase insults */
- if (increase_insults()) return (TRUE);
-
- /* Display and flush insult */
- say_comment_5();
-
- /* Still okay */
- return (FALSE);
-}
-
-
-/*
- * Mega-Hack -- Enable "increments"
- */
-static bool_ allow_inc = FALSE;
-
-/*
- * Mega-Hack -- Last "increment" during haggling
- */
-static s32b last_inc = 0L;
-
-
-/*
- * Get a haggle
- */
-static int get_haggle(cptr pmt, s32b *poffer, s32b price, int final)
-{
- s32b i;
-
- cptr p;
-
- char buf[128];
- char out_val[160];
-
-
- /* Clear old increment if necessary */
- if (!allow_inc) last_inc = 0L;
-
-
- /* Final offer */
- if (final)
- {
- strnfmt(buf, 128, "%s [accept] ", pmt);
- }
-
- /* Old (negative) increment, and not final */
- else if (last_inc < 0)
- {
- strnfmt(buf, 128, "%s [-%ld] ", pmt, (long)(ABS(last_inc)));
- }
-
- /* Old (positive) increment, and not final */
- else if (last_inc > 0)
- {
- strnfmt(buf, 128, "%s [+%ld] ", pmt, (long)(ABS(last_inc)));
- }
-
- /* Normal haggle */
- else
- {
- strnfmt(buf, 128, "%s ", pmt);
- }
-
-
- /* Paranoia XXX XXX XXX */
- msg_print(NULL);
-
-
- /* Ask until done */
- while (TRUE)
- {
- /* Default */
- strcpy(out_val, "");
-
- /* Ask the user for a response */
- if (!get_string(buf, out_val, 32)) return (FALSE);
-
- /* Skip leading spaces */
- for (p = out_val; *p == ' '; p++) /* loop */;
-
- /* Empty response */
- if (*p == '\0')
- {
- /* Accept current price */
- if (final)
- {
- *poffer = price;
- last_inc = 0L;
- break;
- }
-
- /* Use previous increment */
- if (allow_inc && last_inc)
- {
- *poffer += last_inc;
- break;
- }
- }
-
- /* Normal response */
- else
- {
- /* Extract a number */
- i = atol(p);
-
- /* Handle "incremental" number */
- if ((*p == '+' || *p == '-'))
- {
- /* Allow increments */
- if (allow_inc)
- {
- /* Use the given "increment" */
- *poffer += i;
- last_inc = i;
- break;
- }
- }
-
- /* Handle normal number */
- else
- {
- /* Use the given "number" */
- *poffer = i;
- last_inc = 0L;
- break;
- }
- }
-
- /* Warning */
- msg_print("Invalid response.");
- msg_print(NULL);
- }
-
- /* Success */
- return (TRUE);
-}
-
-
-/*
- * Receive an offer (from the player)
- *
- * Return TRUE if offer is NOT okay
- */
-static bool_ receive_offer(cptr pmt, s32b *poffer,
- s32b last_offer, int factor,
- s32b price, int final)
-{
- /* Haggle till done */
- while (TRUE)
- {
- /* Get a haggle (or cancel) */
- if (!get_haggle(pmt, poffer, price, final)) return (TRUE);
-
- /* Acceptable offer */
- if (((*poffer) * factor) >= (last_offer * factor)) break;
-
- /* Insult, and check for kicked out */
- if (haggle_insults()) return (TRUE);
-
- /* Reject offer (correctly) */
- (*poffer) = last_offer;
- }
-
- /* Success */
- return (FALSE);
-}
-
-
-/*
- * Haggling routine -RAK-
- *
- * Return TRUE if purchase is NOT successful
- */
-static bool_ purchase_haggle(object_type *o_ptr, s32b *price)
-{
- s32b cur_ask, final_ask;
- s32b last_offer, offer;
- s32b x1, x2, x3;
- s32b min_per, max_per;
- int flag, loop_flag, noneed;
- int annoyed = 0, final = FALSE;
-
- bool_ cancel = FALSE;
-
- cptr pmt = "Asking";
-
- char out_val[160];
-
-
- *price = 0;
-
-
- /* Extract the starting offer and the final offer */
- cur_ask = price_item(o_ptr, ot_ptr->max_inflate, FALSE);
- final_ask = price_item(o_ptr, ot_ptr->min_inflate, FALSE);
-
- /* Determine if haggling is necessary */
- noneed = noneedtobargain(final_ask);
-
- /* No need to haggle */
- if (noneed || auto_haggle)
- {
- /* No need to haggle */
- if (noneed)
- {
- /* Message summary */
- msg_print("You eventually agree upon the price.");
- msg_print(NULL);
- }
-
- /* No haggle option */
- else
- {
- /* Message summary */
- msg_print("You quickly agree upon the price.");
- msg_print(NULL);
-
- /* Apply Sales Tax */
- final_ask += final_ask / 10;
- }
-
- /* Final price */
- cur_ask = final_ask;
-
- /* Go to final offer */
- pmt = "Final Offer";
- final = TRUE;
- }
-
-
- /* Haggle for the whole pile */
- cur_ask *= o_ptr->number;
- final_ask *= o_ptr->number;
-
-
- /* Haggle parameters */
- min_per = ot_ptr->haggle_per;
- max_per = min_per * 3;
-
- /* Mega-Hack -- artificial "last offer" value */
- last_offer = object_value(o_ptr) * o_ptr->number;
- last_offer = last_offer * (200 - (int)(ot_ptr->max_inflate)) / 100L;
- if (last_offer <= 0) last_offer = 1;
-
- /* No offer yet */
- offer = 0;
-
- /* No incremental haggling yet */
- allow_inc = FALSE;
-
- /* Haggle until done */
- for (flag = FALSE; !flag; )
- {
- loop_flag = TRUE;
-
- while (!flag && loop_flag)
- {
- strnfmt(out_val, 160, "%s : %ld", pmt, (long)cur_ask);
- put_str(out_val, 1, 0);
- cancel = receive_offer("What do you offer? ",
- &offer, last_offer, 1, cur_ask, final);
-
- if (cancel)
- {
- flag = TRUE;
- }
- else if (offer > cur_ask)
- {
- say_comment_6();
- offer = last_offer;
- }
- else if (offer == cur_ask)
- {
- flag = TRUE;
- *price = offer;
- }
- else
- {
- loop_flag = FALSE;
- }
- }
-
- if (!flag)
- {
- x1 = 100 * (offer - last_offer) / (cur_ask - last_offer);
- if (x1 < min_per)
- {
- if (haggle_insults())
- {
- flag = TRUE;
- cancel = TRUE;
- }
- }
- else if (x1 > max_per)
- {
- x1 = x1 * 3 / 4;
- if (x1 < max_per) x1 = max_per;
- }
- x2 = rand_range(x1 - 2, x1 + 2);
- x3 = ((cur_ask - offer) * x2 / 100L) + 1;
- /* don't let the price go up */
- if (x3 < 0) x3 = 0;
- cur_ask -= x3;
-
- /* Too little */
- if (cur_ask < final_ask)
- {
- final = TRUE;
- cur_ask = final_ask;
- pmt = "Final Offer";
- annoyed++;
- if (annoyed > 3)
- {
- (void)(increase_insults());
- cancel = TRUE;
- flag = TRUE;
- }
- }
- else if (offer >= cur_ask)
- {
- flag = TRUE;
- *price = offer;
- }
-
- if (!flag)
- {
- last_offer = offer;
- allow_inc = TRUE;
- prt("", 1, 0);
- strnfmt(out_val, 160, "Your last offer: %ld",
- (long)last_offer);
- put_str(out_val, 1, 39);
- say_comment_2(cur_ask, annoyed);
- }
- }
- }
-
- /* Cancel */
- if (cancel) return (TRUE);
-
- /* Update bargaining info */
- updatebargain(*price, final_ask);
-
- /* Do not cancel */
- return (FALSE);
-}
-
-
-/*
- * Haggling routine -RAK-
- *
- * Return TRUE if purchase is NOT successful
- */
-static bool_ sell_haggle(object_type *o_ptr, s32b *price)
-{
- s32b purse, cur_ask, final_ask;
- s32b last_offer = 0, offer = 0;
- s32b x1, x2, x3;
- s32b min_per, max_per;
-
- int flag, loop_flag, noneed;
- int annoyed = 0, final = FALSE;
-
- bool_ cancel = FALSE;
-
- cptr pmt = "Offer";
-
- char out_val[160];
-
-
- *price = 0;
-
-
- /* Obtain the starting offer and the final offer */
- cur_ask = price_item(o_ptr, ot_ptr->max_inflate, TRUE);
- final_ask = price_item(o_ptr, ot_ptr->min_inflate, TRUE);
-
- /* Determine if haggling is necessary */
- noneed = noneedtobargain(final_ask);
-
- /* Get the owner's payout limit */
- purse = (s32b)(ot_ptr->max_cost);
-
- /* No need to haggle */
- if (noneed || auto_haggle || (final_ask >= purse))
- {
- /* No reason to haggle */
- if (final_ask >= purse)
- {
- /* Message */
- msg_print("You instantly agree upon the price.");
- msg_print(NULL);
-
- /* Offer full purse */
- final_ask = purse;
- }
-
- /* No need to haggle */
- else if (noneed)
- {
- /* Message */
- msg_print("You eventually agree upon the price.");
- msg_print(NULL);
- }
-
- /* No haggle option */
- else
- {
- /* Message summary */
- msg_print("You quickly agree upon the price.");
- msg_print(NULL);
-
- /* Apply Sales Tax */
- final_ask -= final_ask / 10;
- }
-
- /* Final price */
- cur_ask = final_ask;
-
- /* Final offer */
- final = TRUE;
- pmt = "Final Offer";
- }
-
- /* Haggle for the whole pile */
- cur_ask *= o_ptr->number;
- final_ask *= o_ptr->number;
-
-
- /* XXX XXX XXX Display commands */
-
- /* Haggling parameters */
- min_per = ot_ptr->haggle_per;
- max_per = min_per * 3;
-
- /* Mega-Hack -- artificial "last offer" value */
- last_offer = object_value(o_ptr) * o_ptr->number;
- last_offer = last_offer * ot_ptr->max_inflate / 100L;
-
- /* No offer yet */
- offer = 0;
-
- /* No incremental haggling yet */
- allow_inc = FALSE;
-
- /* Haggle */
- for (flag = FALSE; !flag; )
- {
- while (1)
- {
- loop_flag = TRUE;
-
- strnfmt(out_val, 160, "%s : %ld", pmt, (long)cur_ask);
- put_str(out_val, 1, 0);
- cancel = receive_offer("What price do you ask? ",
- &offer, last_offer, -1, cur_ask, final);
-
- if (cancel)
- {
- flag = TRUE;
- }
- else if (offer < cur_ask)
- {
- say_comment_6();
- /* rejected, reset offer for incremental haggling */
- offer = last_offer;
- }
- else if (offer == cur_ask)
- {
- flag = TRUE;
- *price = offer;
- }
- else
- {
- loop_flag = FALSE;
- }
-
- /* Stop */
- if (flag || !loop_flag) break;
- }
-
- if (!flag)
- {
- x1 = 100 * (last_offer - offer) / (last_offer - cur_ask);
- if (x1 < min_per)
- {
- if (haggle_insults())
- {
- flag = TRUE;
- cancel = TRUE;
- }
- }
- else if (x1 > max_per)
- {
- x1 = x1 * 3 / 4;
- if (x1 < max_per) x1 = max_per;
- }
- x2 = rand_range(x1 - 2, x1 + 2);
- x3 = ((offer - cur_ask) * x2 / 100L) + 1;
- /* don't let the price go down */
- if (x3 < 0) x3 = 0;
- cur_ask += x3;
-
- if (cur_ask > final_ask)
- {
- cur_ask = final_ask;
- final = TRUE;
- pmt = "Final Offer";
- annoyed++;
- if (annoyed > 3)
- {
- flag = TRUE;
- (void)(increase_insults());
- }
- }
- else if (offer <= cur_ask)
- {
- flag = TRUE;
- *price = offer;
- }
-
- if (!flag)
- {
- last_offer = offer;
- allow_inc = TRUE;
- prt("", 1, 0);
- strnfmt(out_val, 160,
- "Your last bid %ld", (long)last_offer);
- put_str(out_val, 1, 39);
- say_comment_3(cur_ask, annoyed);
- }
- }
- }
-
- /* Cancel */
- if (cancel) return (TRUE);
-
- /* Update bargaining info */
- updatebargain(*price, final_ask);
-
- /* Do not cancel */
- return (FALSE);
-}
-
-/*
- * Will the owner retire?
- */
-static bool_ retire_owner_p(void)
-{
- store_info_type *sti_ptr = &st_info[town_info[p_ptr->town_num].store[cur_store_num].st_idx];
-
- if ((sti_ptr->owners[0] == sti_ptr->owners[1]) &&
- (sti_ptr->owners[0] == sti_ptr->owners[2]) &&
- (sti_ptr->owners[0] == sti_ptr->owners[3]))
- {
- /* there is no other owner */
- return FALSE;
- }
-
- if (rand_int(STORE_SHUFFLE) != 0)
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-/*
- * Stole an item from a store -DG-
- */
-void store_stole(void)
-{
- int i, amt;
- int item, item_new;
-
- object_type forge;
- object_type *j_ptr;
-
- object_type *o_ptr;
-
- char o_name[80];
-
- char out_val[160];
-
- if (cur_store_num == 7)
- {
- msg_print("You can't steal from your home!");
- return;
- }
-
- /* Empty? */
- if (st_ptr->stock_num <= 0)
- {
- msg_print("There is no item to steal.");
- return;
- }
-
-
- /* Find the number of objects on this and following pages */
- i = (st_ptr->stock_num - store_top);
-
- /* And then restrict it to the current page */
- if (i > 12) i = 12;
-
- /* Prompt */
- strnfmt(out_val, 160, "Which item do you want to steal? ");
-
- /* Get the item number to be bought */
- if (!get_stock(&item, out_val, 0, i - 1)) return;
-
- /* Get the actual index */
- item = item + store_top;
-
- /* Get the actual item */
- o_ptr = &st_ptr->stock[item];
-
- /* Assume the player wants just one of them */
- amt = 1;
-
- /* Get local object */
- j_ptr = &forge;
-
- /* Get a copy of the object */
- object_copy(j_ptr, o_ptr);
-
- /* Modify quantity */
- j_ptr->number = amt;
-
- /* Hack -- require room in pack */
- if (!inven_carry_okay(j_ptr))
- {
- msg_print("You cannot carry that many different items.");
- return;
- }
-
- /* Find out how many the player wants */
- if (o_ptr->number > 1)
- {
- /* Get a quantity */
- amt = get_quantity(NULL, o_ptr->number);
-
- /* Allow user abort */
- if (amt <= 0) return;
- }
-
- /* Get local object */
- j_ptr = &forge;
-
- /* Get desired object */
- object_copy(j_ptr, o_ptr);
-
- /* Modify quantity */
- j_ptr->number = amt;
-
- /* Hack -- require room in pack */
- if (!inven_carry_okay(j_ptr))
- {
- msg_print("You cannot carry that many items.");
- return;
- }
-
- /* Player tries to stole it */
- if (rand_int((40 - p_ptr->stat_ind[A_DEX]) +
- ((j_ptr->weight * amt) / (5 + get_skill_scale(SKILL_STEALING, 15))) -
- (get_skill_scale(SKILL_STEALING, 15))) <= 10)
- {
- /* Hack -- buying an item makes you aware of it */
- object_aware(j_ptr);
-
- /* Be aware of how you found it */
- j_ptr->found = OBJ_FOUND_STOLEN;
- j_ptr->found_aux1 = st_ptr->st_idx;
-
- /* Hack -- clear the "fixed" flag from the item */
- j_ptr->ident &= ~(IDENT_FIXED);
-
- /* "Hot" merchandise can't be sold back. It doesn't make sense
- to be able to sell back to a guy what you just stole from him.
- Also, without the discount one could fairly easily macro himself
- an infinite money supply */
- j_ptr->discount = 100;
-
- if (o_ptr->tval == TV_WAND)
- {
- j_ptr->pval = o_ptr->pval * amt / o_ptr->number;
- o_ptr->pval -= j_ptr->pval;
- }
-
- /* Describe the transaction */
- object_desc(o_name, j_ptr, TRUE, 3);
-
- /* Message */
- msg_format("You steal %s.", o_name);
-
- /* Erase the inscription */
- j_ptr->note = 0;
-
- /* Give it to the player */
- item_new = inven_carry(j_ptr, FALSE);
-
- /* Describe the final result */
- object_desc(o_name, &p_ptr->inventory[item_new], TRUE, 3);
-
- /* Message */
- msg_format("You have %s (%c).",
- o_name, index_to_label(item_new));
-
- /* Handle stuff */
- handle_stuff();
-
- /* Note how many slots the store used to have */
- i = st_ptr->stock_num;
-
- /* Remove the bought items from the store */
- store_item_increase(item, -amt);
- store_item_optimize(item);
-
- /* Store is empty */
- if (st_ptr->stock_num == 0)
- {
- /* Shuffle */
- if (retire_owner_p())
- {
- /* Message */
- msg_print("The shopkeeper retires.");
-
- /* Shuffle the store */
- store_shuffle(cur_store_num);
- }
-
- /* Maintain */
- else
- {
- /* Message */
- msg_print("The shopkeeper brings out some new stock.");
- }
-
- /* New inventory */
- for (i = 0; i < 10; i++)
- {
- /* Maintain the store */
- store_maint(p_ptr->town_num, cur_store_num);
- }
-
- /* Start over */
- store_top = 0;
-
- /* Redraw everything */
- display_inventory();
- }
-
- /* The item is gone */
- else if (st_ptr->stock_num != i)
- {
- /* Pick the correct screen */
- if (store_top >= st_ptr->stock_num) store_top -= 12;
-
- /* Redraw everything */
- display_inventory();
- }
-
- /* Item is still here */
- else
- {
- /* Redraw the item */
- display_entry(item);
- }
- }
- else
- {
- /* Complain */
- say_comment_4();
-
- /* Reset insults */
- st_ptr->insult_cur = 0;
- st_ptr->good_buy = 0;
- st_ptr->bad_buy = 0;
-
- /* Kicked out for a LONG time */
- st_ptr->store_open = turn + 500000 + randint(500000);
- }
-
- /* Not kicked out */
- return;
-}
-
-/*
- * Buy an item from a store -RAK-
- */
-void store_purchase(void)
-{
- int i, amt = 1, choice;
- int item, item_new;
-
- s32b price, best;
-
- object_type forge;
- object_type *j_ptr;
-
- object_type *o_ptr;
-
- char o_name[80];
-
- char out_val[160];
-
- /* Museum? */
- if (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM)
- {
- msg_print("You cannot take items from the museum!");
- return;
- }
-
- /* Empty? */
- if (st_ptr->stock_num <= 0)
- {
- if (cur_store_num == 7) msg_print("Your home is empty.");
- else msg_print("I am currently out of stock.");
- return;
- }
-
-
- /* Find the number of objects on this and following pages */
- i = (st_ptr->stock_num - store_top);
-
- /* And then restrict it to the current page */
- if (i > 12) i = 12;
-
- /* Prompt */
- if (cur_store_num == 7)
- {
- strnfmt(out_val, 160, "Which item do you want to take? ");
- }
- else
- {
- strnfmt(out_val, 160, "Which item are you interested in? ");
- }
-
- /* Get the item number to be bought */
- if (!get_stock(&item, out_val, 0, i - 1)) return;
-
- /* Get the actual index */
- item = item + store_top;
-
- /* Get the actual item */
- o_ptr = &st_ptr->stock[item];
-
- /* Get local object */
- j_ptr = &forge;
-
- /* Get a copy of one object to determine the price */
- object_copy(j_ptr, o_ptr);
-
- /* Modify quantity */
- j_ptr->number = 1;
-
- /* Hack -- If a wand, allocate the number of charges of one wand */
- if (j_ptr->tval == TV_WAND)
- {
- j_ptr->pval = o_ptr->pval / o_ptr->number;
- }
-
- /* Hack -- require room in pack */
- if (!inven_carry_okay(j_ptr))
- {
- msg_print("You cannot carry that many different items.");
- return;
- }
-
- /* Determine the "best" price (per item) */
- best = price_item(j_ptr, ot_ptr->min_inflate, FALSE);
-
- /* Find out how many the player wants */
- if (o_ptr->number > 1)
- {
- s32b q;
-
-
- /* Hack -- note cost of "fixed" items */
- if ((cur_store_num != 7) && (o_ptr->ident & (IDENT_FIXED)))
- {
- msg_format("That costs %ld gold per item.", (long)(best));
- }
-
- /* How many can we buy ? 99 if price is 0*/
- if (cur_store_num == STORE_HOME)
- {
- q = 99;
- }
- else if (best == 0)
- {
- q = 99;
- }
- else
- {
- if (auto_haggle)
- q = p_ptr->au / (best + (best / 10));
- else
- q = p_ptr->au / best;
- }
- if (o_ptr->number < q)
- q = o_ptr->number;
-
- /* None ? ahh too bad */
- if (!q)
- {
- msg_print("You do not have enough gold to buy one.");
- return;
- }
-
- /* Get a quantity */
- amt = get_quantity(NULL, q);
-
- /* Allow user abort */
- if (amt <= 0) return;
- }
-
- /* Get local object */
- j_ptr = &forge;
-
- /* Get desired object */
- object_copy(j_ptr, o_ptr);
-
- /* Modify quantity */
- j_ptr->number = amt;
-
- /* Hack -- If a rod or wand, allocate total maximum timeouts or charges
- * between those purchased and left on the shelf. -LM-
- */
- if (o_ptr->tval == TV_WAND)
- {
- j_ptr->pval = o_ptr->pval * amt / o_ptr->number;
- }
-
- /* Hack -- require room in pack */
- if (!inven_carry_okay(j_ptr))
- {
- msg_print("You cannot carry that many items.");
- return;
- }
-
- /* Attempt to buy it */
- if (cur_store_num != 7)
- {
- /* Fixed price, quick buy */
- if (o_ptr->ident & (IDENT_FIXED))
- {
- /* Assume accept */
- choice = 0;
-
- /* Go directly to the "best" deal */
- price = (best * j_ptr->number);
- }
-
- /* Haggle for it */
- else
- {
- /* Describe the object (fully) */
- object_desc_store(o_name, j_ptr, TRUE, 3);
-
- /* Message */
- msg_format("Buying %s (%c).", o_name, I2A(item));
- msg_print(NULL);
-
- /* Haggle for a final price */
- choice = purchase_haggle(j_ptr, &price);
-
- /* Hack -- Got kicked out */
- if (st_ptr->store_open >= turn) return;
- }
-
-
- /* Player wants it */
- if (choice == 0)
- {
- /* Fix the item price (if "correctly" haggled) */
- if (price == (best * j_ptr->number)) o_ptr->ident |= (IDENT_FIXED);
-
- /* Player can afford it */
- if (p_ptr->au >= price)
- {
- /* Say "okay" */
- say_comment_1();
-
- /* Make a sound */
- sound(SOUND_BUY);
-
- /* Be happy */
- decrease_insults();
-
- /* Spend the money */
- p_ptr->au -= price;
-
- /* Update the display */
- store_prt_gold();
-
- /* Hack -- buying an item makes you aware of it */
- object_aware(j_ptr);
-
- /* Be aware of how you found it */
- j_ptr->found = OBJ_FOUND_STORE;
- j_ptr->found_aux1 = st_ptr->st_idx;
-
- /* Hack -- clear the "fixed" flag from the item */
- j_ptr->ident &= ~(IDENT_FIXED);
-
- /* Describe the transaction */
- object_desc(o_name, j_ptr, TRUE, 3);
-
- /* Message */
- msg_format("You bought %s for %ld gold.", o_name, (long)price);
-
- /* Erase the inscription */
- j_ptr->note = 0;
-
- /* Hack -- If a rod or wand, allocate total maximum
- * timeouts or charges between those picked up and
- * those left behind. -LM-
- */
- if (o_ptr->tval == TV_WAND)
- {
- j_ptr->pval = o_ptr->pval * amt / o_ptr->number;
- o_ptr->pval -= j_ptr->pval;
- }
-
- /* Give it to the player */
- item_new = inven_carry(j_ptr, FALSE);
-
- /* Describe the final result */
- object_desc(o_name, &p_ptr->inventory[item_new], TRUE, 3);
-
- /* Message */
- msg_format("You have %s (%c).",
- o_name, index_to_label(item_new));
-
- /* Handle stuff */
- handle_stuff();
-
- /* Note how many slots the store used to have */
- i = st_ptr->stock_num;
-
- /* Remove the bought items from the store */
- store_item_increase(item, -amt);
- store_item_optimize(item);
-
- /* Store is empty */
- if (st_ptr->stock_num == 0)
- {
- /* Shuffle */
- if (retire_owner_p())
- {
- /* Message */
- msg_print("The shopkeeper retires.");
-
- /* Shuffle the store */
- store_shuffle(cur_store_num);
- }
-
- /* Maintain */
- else
- {
- /* Message */
- msg_print("The shopkeeper brings out some new stock.");
- }
-
- /* New inventory */
- for (i = 0; i < 10; i++)
- {
- /* Maintain the store */
- store_maint(p_ptr->town_num, cur_store_num);
- }
-
- /* Start over */
- store_top = 0;
- }
-
- /* The item is gone */
- else if (st_ptr->stock_num != i)
- {
- /* Pick the correct screen */
- if (store_top >= st_ptr->stock_num) store_top -= 12;
- }
-
- /* Redraw everything */
- display_inventory();
- }
-
- /* Player cannot afford it */
- else
- {
- /* Simple message (no insult) */
- msg_print("You do not have enough gold.");
- }
- }
- }
-
- /* Home is much easier */
- else
- {
- /* Hack -- If a rod or wand, allocate total maximum
- * timeouts or charges between those picked up and
- * those left behind. -LM-
- */
- if (o_ptr->tval == TV_WAND)
- {
- j_ptr->pval = o_ptr->pval * amt / o_ptr->number;
- o_ptr->pval -= j_ptr->pval;
- }
-
- /* Give it to the player */
- item_new = inven_carry(j_ptr, FALSE);
-
- /* Describe just the result */
- object_desc(o_name, &p_ptr->inventory[item_new], TRUE, 3);
-
- /* Message */
- msg_format("You have %s (%c).", o_name, index_to_label(item_new));
-
- /* Handle stuff */
- handle_stuff();
-
- /* Take note if we take the last one */
- i = st_ptr->stock_num;
-
- /* Remove the items from the home */
- store_item_increase(item, -amt);
- store_item_optimize(item);
-
- /* Hack -- Item is still here */
- if (i == st_ptr->stock_num)
- {
- /* Redraw the item */
- display_entry(item);
- }
-
- /* The item is gone */
- else
- {
- /* Nothing left */
- if (st_ptr->stock_num == 0) store_top = 0;
-
- /* Nothing left on that screen */
- else if (store_top >= st_ptr->stock_num) store_top -= 12;
-
- /* Redraw everything */
- display_inventory();
- }
- }
-
- /* Not kicked out */
- return;
-}
-
-
-/*
- * Sell an item to the store (or home)
- */
-void store_sell(void)
-{
- int choice;
- int item, item_pos;
- int amt;
-
- s32b price, value, dummy;
-
- object_type forge;
- object_type *q_ptr;
-
- object_type *o_ptr;
-
- cptr q, s;
-
- char o_name[80];
-
- u32b f1, f2, f3, f4, f5, esp;
-
- bool_ museum = (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM) ? TRUE : FALSE;
-
- /* Prepare a prompt */
- if (cur_store_num == 7) q = "Drop which item? ";
- else if (museum) q = "Donate which item?";
- else q = "Sell which item? ";
-
- /* Only allow items the store will buy */
- item_tester_hook = store_will_buy;
-
- /* Get an item */
- if (cur_store_num == STORE_HOME)
- {
- s = "You have nothing to drop.";
- }
- else if (museum)
- {
- s = "You have nothing to donate.";
- }
- else
- {
- s = "You have nothing that I want.";
- }
- if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN))) return;
-
- /* Get the item */
- o_ptr = get_object(item);
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Hack -- Cannot remove cursed items */
- if (cursed_p(o_ptr))
- {
- if (item >= INVEN_WIELD)
- {
- /* Oops */
- msg_print("Hmmm, it seems to be cursed.");
-
- /* Nope */
- return;
- }
- else
- {
- if (f4 & TR4_CURSE_NO_DROP)
- {
- /* Oops */
- msg_print("Hmmm, you seem to be unable to drop it.");
-
- /* Nope */
- return;
- }
- }
- }
-
-
- /* Assume one item */
- amt = 1;
-
- /* Find out how many the player wants (letter means "all") */
- if (o_ptr->number > 1)
- {
- /* Get a quantity */
- amt = get_quantity(NULL, o_ptr->number);
-
- /* Allow user abort */
- if (amt <= 0) return;
- }
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Get a copy of the object */
- object_copy(q_ptr, o_ptr);
-
- /* Modify quantity */
- q_ptr->number = amt;
-
- /* Hack -- If a rod or wand, allocate total maximum
- * timeouts or charges to those being sold. -LM-
- */
- if (o_ptr->tval == TV_WAND)
- {
- q_ptr->pval = o_ptr->pval * amt / o_ptr->number;
- }
-
- /* Get a full description */
- object_desc(o_name, q_ptr, TRUE, 3);
-
- /* Remove any inscription for stores */
- if ((cur_store_num != 7) && !museum)
- {
- q_ptr->note = 0;
- }
-
- /* Is there room in the store (or the home?) */
- if (!store_check_num(q_ptr))
- {
- if (cur_store_num == 7) msg_print("Your home is full.");
- else if (museum) msg_print("The museum is full.");
- else msg_print("I have not the room in my store to keep it.");
- return;
- }
-
-
- /* Real store */
- if ((cur_store_num != 7) && !museum)
- {
- /* Describe the transaction */
- msg_format("Selling %s (%c).", o_name, index_to_label(item));
- msg_print(NULL);
-
- /* Haggle for it */
- choice = sell_haggle(q_ptr, &price);
-
- /* Kicked out */
- if (st_ptr->store_open >= turn) return;
-
- /* Sold... */
- if (choice == 0)
- {
- /* Say "okay" */
- say_comment_1();
-
- /* Make a sound */
- sound(SOUND_SELL);
-
- /* Be happy */
- decrease_insults();
-
- /* Get some money */
- p_ptr->au += price;
-
- /* Update the display */
- store_prt_gold();
-
- /* Get the "apparent" value */
- dummy = object_value(q_ptr) * q_ptr->number;
-
- /* Identify original item */
- object_aware(o_ptr);
- object_known(o_ptr);
-
- /* Combine / Reorder the pack (later) */
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
-
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Get a copy of the object */
- object_copy(q_ptr, o_ptr);
-
- /* Modify quantity */
- q_ptr->number = amt;
-
- /*
- * Hack -- If a rod or wand, let the shopkeeper know just
- * how many charges he really paid for. -LM-
- */
- if (o_ptr->tval == TV_WAND)
- {
- q_ptr->pval = o_ptr->pval * amt / o_ptr->number;
- }
-
- /* Get the "actual" value */
- value = object_value(q_ptr) * q_ptr->number;
-
- /* Get the description all over again */
- object_desc(o_name, q_ptr, TRUE, 3);
-
- /* Describe the result (in message buffer) */
- msg_format("You sold %s for %ld gold.", o_name, (long)price);
-
- /* Analyze the prices (and comment verbally) */
- purchase_analyze(price, value, dummy);
-
- /*
- * Hack -- Allocate charges between those wands or rods sold
- * and retained, unless all are being sold. -LM-
- */
- if (o_ptr->tval == TV_WAND)
- {
- q_ptr->pval = o_ptr->pval * amt / o_ptr->number;
-
- if (o_ptr->number > amt) o_ptr->pval -= q_ptr->pval;
- }
-
- /* Take the item from the player, describe the result */
- inc_stack_size(item, -amt);
-
- /* Handle stuff */
- handle_stuff();
-
- /* The store gets that (known) item */
- item_pos = store_carry(q_ptr);
-
- /* Re-display if item is now in store */
- if (item_pos >= 0)
- {
- store_top = (item_pos / 12) * 12;
- display_inventory();
- }
- }
- }
-
- /* Player is at museum */
- else if (museum)
- {
- char o2_name[80];
- object_desc(o2_name, q_ptr, TRUE, 0);
-
- msg_print("Once you donate something, you cannot take it back.");
- if (!get_check(format("Do you really want to donate %s?", o2_name))) return;
-
- /* Identify it */
- object_aware(q_ptr);
- object_known(q_ptr);
- q_ptr->ident |= IDENT_MENTAL;
-
- /*
- * Hack -- Allocate charges between those wands or rods sold
- * and retained, unless all are being sold. -LM-
- */
- if (o_ptr->tval == TV_WAND)
- {
- q_ptr->pval = o_ptr->pval * amt / o_ptr->number;
-
- if (o_ptr->number > amt) o_ptr->pval -= q_ptr->pval;
- }
-
-
- /* Describe */
- msg_format("You donate %s (%c).", o_name, index_to_label(item));
-
- choice = 0;
-
- /* Take it from the players inventory */
- inc_stack_size(item, -amt);
-
- /* Handle stuff */
- handle_stuff();
-
- /* Let the home carry it */
- item_pos = home_carry(q_ptr);
-
- /* Update store display */
- if (item_pos >= 0)
- {
- store_top = (item_pos / 12) * 12;
- display_inventory();
- }
- }
-
- /* Player is at home */
- else
- {
- /* Describe */
- msg_format("You drop %s (%c).", o_name, index_to_label(item));
-
- /*
- * Hack -- Allocate charges between those wands or rods sold
- * and retained, unless all are being sold. -LM-
- */
- if (o_ptr->tval == TV_WAND)
- {
- q_ptr->pval = o_ptr->pval * amt / o_ptr->number;
-
- if (o_ptr->number > amt) o_ptr->pval -= q_ptr->pval;
- }
-
- /* Take it from the players inventory */
- inc_stack_size(item, -amt);
-
- /* Handle stuff */
- handle_stuff();
-
- /* Let the home carry it */
- item_pos = home_carry(q_ptr);
-
- /* Update store display */
- if (item_pos >= 0)
- {
- store_top = (item_pos / 12) * 12;
- display_inventory();
- }
- }
-}
-
-
-
-/*
- * Examine an item in a store -JDL-
- */
-void store_examine(void)
-{
- int i;
- int item;
-
- object_type *o_ptr;
-
- char o_name[80];
-
- char out_val[160];
-
-
- /* Empty? */
- if (st_ptr->stock_num <= 0)
- {
- if (cur_store_num == 7) msg_print("Your home is empty.");
- else if (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM) msg_print("The museum is empty.");
- else msg_print("I am currently out of stock.");
- return;
- }
-
-
- /* Find the number of objects on this and following pages */
- i = (st_ptr->stock_num - store_top);
-
- /* And then restrict it to the current page */
- if (i > 12) i = 12;
-
- /* Prompt */
- strnfmt(out_val, 160, "Which item do you want to examine? ");
-
- /* Get the item number to be examined */
- if (!get_stock(&item, out_val, 0, i - 1)) return;
-
- /* Get the actual index */
- item = item + store_top;
-
- /* Get the actual item */
- o_ptr = &st_ptr->stock[item];
-
- /* Debug hack */
- if (wizard)
- {
- drop_near(o_ptr, -1, p_ptr->py, p_ptr->px);
- }
-
- /* Require full knowledge */
- if (!(o_ptr->ident & (IDENT_MENTAL)))
- {
- /* This can only happen in the home */
- msg_print("You have no special knowledge about that item.");
- return;
- }
-
- /* Description */
- object_desc(o_name, o_ptr, TRUE, 3);
-
- /* Describe */
- msg_format("Examining %s...", o_name);
-
- /* Show the object's powers. */
- if (!object_out_desc(o_ptr, NULL, FALSE, TRUE))
- {
- msg_print("You see nothing special.");
- }
-
- /* Show spell listing for instruments, daemonwear and spellbooks. */
- if ((o_ptr->tval == TV_INSTRUMENT) || (o_ptr->tval == TV_DAEMON_BOOK)
- || (o_ptr->tval == TV_BOOK))
- {
- do_cmd_browse_aux(o_ptr);
- }
-
- return;
-}
-
-
-
-
-
-/*
- * Hack -- set this to leave the store
- */
-static bool_ leave_store = FALSE;
-
-
-/*
- * Process a command in a store
- *
- * Note that we must allow the use of a few "special" commands
- * in the stores which are not allowed in the dungeon, and we
- * must disable some commands which are allowed in the dungeon
- * but not in the stores, to prevent chaos.
- */
-static bool_ store_process_command(void)
-{
- bool_ validcmd = FALSE;
- int i;
- store_action_type *ba_ptr;
- bool_ recreate = FALSE;
-
- /* Handle repeating the last command */
- repeat_check();
-
- for (i = 0; i < 6; i++)
- {
- ba_ptr = &ba_info[st_info[st_ptr->st_idx].actions[i]];
-
- if (ba_ptr->letter)
- {
- if (ba_ptr->letter == command_cmd)
- {
- validcmd = TRUE;
- break;
- }
- }
- if (ba_ptr->letter_aux)
- {
- if (ba_ptr->letter_aux == command_cmd)
- {
- validcmd = TRUE;
- break;
- }
- }
- }
-
- if (validcmd)
- {
- recreate = bldg_process_command(st_ptr, i);
- }
- else
- {
- /* Parse the command */
- switch (command_cmd)
- {
- /* Leave */
- case ESCAPE:
- {
- leave_store = TRUE;
- break;
- }
-
- /* Browse */
- case ' ':
- {
- if (st_ptr->stock_num <= 12)
- {
- msg_print("Entire inventory is shown.");
- }
- else
- {
- store_top += 12;
- if (store_top >= st_ptr->stock_num) store_top = 0;
- display_inventory();
- }
- break;
- }
-
- /* Browse backwards */
- case '-':
- {
- if (st_ptr->stock_num <= 12)
- {
- msg_print("Entire inventory is shown.");
- }
- else
- {
- store_top -= 12;
- if (store_top < 0)
- {
- store_top = ((st_ptr->stock_num - 1) / 12) * 12;
- }
- display_inventory();
- }
- }
-
- /* Redraw */
- case KTRL('R'):
- {
- do_cmd_redraw();
- display_store();
- break;
- }
-
- /* Ignore return */
- case '\r':
- {
- break;
- }
-
-
-
- /*** Inventory Commands ***/
-
- /* Wear/wield equipment */
- case 'w':
- {
- do_cmd_wield();
- break;
- }
-
- /* Take off equipment */
- case 't':
- {
- do_cmd_takeoff();
- break;
- }
-
- /* Destroy an item */
- case 'k':
- {
- do_cmd_destroy();
- break;
- }
-
- /* Equipment list */
- case 'e':
- {
- do_cmd_equip();
- break;
- }
-
- /* Inventory list */
- case 'i':
- {
- do_cmd_inven();
- break;
- }
-
-
- /*** Various commands ***/
-
- /* Identify an object */
- case 'I':
- {
- do_cmd_observe();
- break;
- }
-
- /* Hack -- toggle windows */
- case KTRL('I'):
- {
- toggle_inven_equip();
- break;
- }
-
-
-
- /*** Use various objects ***/
-
- /* Browse a book */
- case 'b':
- {
- do_cmd_browse();
- break;
- }
-
- /* Inscribe an object */
- case '{':
- {
- do_cmd_inscribe();
- break;
- }
-
- /* Uninscribe an object */
- case '}':
- {
- do_cmd_uninscribe();
- break;
- }
-
-
-
- /*** Help and Such ***/
-
- /* Help */
- case '?':
- {
- do_cmd_help();
- break;
- }
-
- /* Identify symbol */
- case '/':
- {
- do_cmd_query_symbol();
- break;
- }
-
- /* Character description */
- case 'C':
- {
- do_cmd_change_name();
- display_store();
- break;
- }
-
-
- /*** System Commands ***/
-
- /* Hack -- User interface */
- case '!':
- {
- (void)Term_user(0);
- break;
- }
-
- /* Single line from a pref file */
- case '"':
- {
- do_cmd_pref();
- break;
- }
-
- /* Interact with macros */
- case '@':
- {
- do_cmd_macros();
- break;
- }
-
- /* Interact with visuals */
- case '%':
- {
- do_cmd_visuals();
- break;
- }
-
- /* Interact with colors */
- case '&':
- {
- do_cmd_colors();
- break;
- }
-
- /* Interact with options */
- case '=':
- {
- do_cmd_options();
- break;
- }
-
-
- /*** Misc Commands ***/
-
- /* Take notes */
- case ':':
- {
- do_cmd_note();
- break;
- }
-
- /* Version info */
- case 'V':
- {
- do_cmd_version();
- break;
- }
-
- /* Repeat level feeling */
- case KTRL('F'):
- {
- do_cmd_feeling();
- break;
- }
-
- /* Show previous message */
- case KTRL('O'):
- {
- do_cmd_message_one();
- break;
- }
-
- /* Show previous messages */
- case KTRL('P'):
- {
- do_cmd_messages();
- break;
- }
-
- /* Check artifacts, uniques etc. */
- case '~':
- case '|':
- {
- do_cmd_knowledge();
- break;
- }
-
- /* Load "screen dump" */
- case '(':
- {
- do_cmd_load_screen();
- break;
- }
-
- /* Save "screen dump" */
- case ')':
- {
- do_cmd_save_screen();
- break;
- }
-
-
- /* Hack -- Unknown command */
- default:
- {
- if (st_ptr->st_idx == STORE_HOME)
- msg_print("That command does not work in this home.");
- else
- msg_print("That command does not work in this store.");
- break;
- }
- }
- }
-
- return recreate;
-}
-
-
-/*
- * Enter a store, and interact with it.
- *
- * Note that we use the standard "request_command()" function
- * to get a command, allowing us to use "command_arg" and all
- * command macros and other nifty stuff, but we use the special
- * "shopping" argument, to force certain commands to be converted
- * into other commands, normally, we convert "p" (pray) and "m"
- * (cast magic) into "g" (get), and "s" (search) into "d" (drop).
- */
-void do_cmd_store(void)
-{
- int which;
- int maintain_num;
- int tmp_chr;
- int i;
- bool_ recreate = FALSE;
-
- cave_type *c_ptr;
-
-
- /* Access the player grid */
- c_ptr = &cave[p_ptr->py][p_ptr->px];
-
- /* Verify a store */
- if (c_ptr->feat != FEAT_SHOP)
- {
- msg_print("You see no store here.");
- return;
- }
-
- /* Extract the store code */
- which = c_ptr->special;
-
- /* Hack -- Check the "locked doors" */
- if (town_info[p_ptr->town_num].store[which].store_open >= turn)
- {
- msg_print("The doors are locked.");
- return;
- }
-
- /* Calculate the number of store maintainances since the last visit */
- maintain_num = (turn - town_info[p_ptr->town_num].store[which].last_visit) / (10L * STORE_TURNS);
-
- /* Maintain the store max. 10 times */
- if (maintain_num > 10) maintain_num = 10;
-
- if (maintain_num)
- {
- /* Maintain the store */
- for (i = 0; i < maintain_num; i++)
- store_maint(p_ptr->town_num, which);
-
- /* Save the visit */
- town_info[p_ptr->town_num].store[which].last_visit = turn;
- }
-
- /* Forget the lite */
- /* forget_lite(); */
-
- /* Forget the view */
- forget_view();
-
-
- /* Hack -- Character is in "icky" mode */
- character_icky = TRUE;
-
-
- /* No command argument */
- command_arg = 0;
-
- /* No repeated command */
- command_rep = 0;
-
- /* No automatic command */
- command_new = 0;
-
-
- /* Save the store number */
- cur_store_num = which;
-
- /* Save the store and owner pointers */
- st_ptr = &town_info[p_ptr->town_num].store[cur_store_num];
- ot_ptr = &ow_info[st_ptr->owner];
-
-
- /* Start at the beginning */
- store_top = 0;
-
- /* Display the store */
- display_store();
-
- /* Mega-Hack -- Ignore keymaps on store action letters */
- for (i = 0; i < 6; i++)
- {
- store_action_type *ba_ptr =
- &ba_info[st_info[st_ptr->st_idx].actions[i]];
- request_command_ignore_keymaps[2*i] = ba_ptr->letter;
- request_command_ignore_keymaps[2*i+1] = ba_ptr->letter_aux;
-
- }
-
- /* Do not leave */
- leave_store = FALSE;
-
- /* Interact with player */
- while (!leave_store)
- {
- /* Hack -- Clear line 1 */
- prt("", 1, 0);
-
- /* Hack -- Check the charisma */
- tmp_chr = p_ptr->stat_use[A_CHR];
-
- /* Clear */
- clear_from(21);
-
-
- /* Basic commands */
- c_prt(TERM_YELLOW, " ESC.", 22, 0);
- prt(") Exit.", 22, 4);
-
- /* Browse if necessary */
- if (st_ptr->stock_num > 12)
- {
- c_prt(TERM_YELLOW, " SPACE", 23, 0);
- prt(") Next page", 23, 6);
- }
-
- /* Prompt */
- prt("You may: ", 21, 0);
-
- /* Show the commands */
- show_building(st_ptr);
-
- /* Get a command */
- request_command(TRUE);
-
- /* Process the command */
- if (store_process_command()) recreate = TRUE;
-
- /* Hack -- Character is still in "icky" mode */
- character_icky = TRUE;
-
- /* Notice stuff */
- notice_stuff();
-
- /* Handle stuff */
- handle_stuff();
-
- /* XXX XXX XXX Pack Overflow */
- if (p_ptr->inventory[INVEN_PACK].k_idx)
- {
- int item = INVEN_PACK;
-
- object_type *o_ptr = &p_ptr->inventory[item];
-
- /* Hack -- Flee from the store */
- if (cur_store_num != 7)
- {
- /* Message */
- msg_print("Your pack is so full that you flee the store...");
-
- /* Leave */
- leave_store = TRUE;
- }
-
- /* Hack -- Flee from the home */
- else if (!store_check_num(o_ptr))
- {
- /* Message */
- msg_print("Your pack is so full that you flee your home...");
-
- /* Leave */
- leave_store = TRUE;
- }
-
- /* Hack -- Drop items into the home */
- else
- {
- int item_pos;
-
- object_type forge;
- object_type *q_ptr;
-
- char o_name[80];
-
-
- /* Give a message */
- msg_print("Your pack overflows!");
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Grab a copy of the item */
- object_copy(q_ptr, o_ptr);
-
- /* Describe it */
- object_desc(o_name, q_ptr, TRUE, 3);
-
- /* Message */
- msg_format("You drop %s (%c).", o_name, index_to_label(item));
-
- /* Remove it from the players inventory */
- inc_stack_size(item, -255);
-
- /* Handle stuff */
- handle_stuff();
-
- /* Let the home carry it */
- item_pos = home_carry(q_ptr);
-
- /* Redraw the home */
- if (item_pos >= 0)
- {
- store_top = (item_pos / 12) * 12;
- display_inventory();
- }
- }
- }
-
- /* Hack -- Redisplay store prices if charisma changes */
- if (tmp_chr != p_ptr->stat_use[A_CHR]) display_inventory();
-
- /* Hack -- get kicked out of the store */
- if (st_ptr->store_open >= turn) leave_store = TRUE;
- }
-
- /* Free turn XXX XXX XXX */
- energy_use = 0;
-
- /* Recreate the level only when needed */
- if (recreate)
- {
- /* Reinit wilderness to activate quests ... */
- p_ptr->oldpx = p_ptr->px;
- p_ptr->oldpy = p_ptr->py;
-
- p_ptr->leaving = TRUE;
- }
-
- /* Hack -- Character is no longer in "icky" mode */
- character_icky = FALSE;
-
-
- /* Hack -- Cancel automatic command */
- command_new = 0;
-
- /* Mega-Hack -- Clear the 'ignore-keymaps' list */
- memset(request_command_ignore_keymaps, 0, 12);
-
- /* Flush messages XXX XXX XXX */
- msg_print(NULL);
-
-
- /* Clear the screen */
- Term_clear();
-
-
- /* Update everything */
- p_ptr->update |= (PU_VIEW | PU_MON_LITE);
- p_ptr->update |= (PU_MONSTERS);
-
- /* Redraw entire screen */
- p_ptr->redraw |= (PR_BASIC | PR_EXTRA);
-
- /* Redraw map */
- p_ptr->redraw |= (PR_MAP);
-
- /* Window stuff */
- p_ptr->window |= (PW_OVERHEAD);
-}
-
-
-
-/*
- * Shuffle one of the stores.
- */
-void store_shuffle(int which)
-{
- int i, j;
-
-
- /* Ignore home */
- if (which == STORE_HOME) return;
-
- /* Ignoer Museum */
- if (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM) return;
-
-
- /* Save the store index */
- cur_store_num = which;
-
- /* Activate that store */
- st_ptr = &town_info[p_ptr->town_num].store[cur_store_num];
-
- /* Pick a new owner */
- for (j = st_ptr->owner; j == st_ptr->owner; )
- {
- st_ptr->owner = st_info[st_ptr->st_idx].owners[rand_int(4)];
- }
-
- /* Activate the new owner */
- ot_ptr = &ow_info[st_ptr->owner];
-
-
- /* Reset the owner data */
- st_ptr->insult_cur = 0;
- st_ptr->store_open = 0;
- st_ptr->good_buy = 0;
- st_ptr->bad_buy = 0;
-
-
- /* Hack -- discount all the items */
- for (i = 0; i < st_ptr->stock_num; i++)
- {
- object_type *o_ptr;
-
- /* Get the item */
- o_ptr = &st_ptr->stock[i];
-
- /* Hack -- Sell all old items for "half price" */
- if (!(o_ptr->art_name))
- o_ptr->discount = 50;
-
- /* Hack -- Items are no longer "fixed price" */
- o_ptr->ident &= ~(IDENT_FIXED);
-
- /* Mega-Hack -- Note that the item is "on sale" */
- o_ptr->note = quark_add("on sale");
- }
-}
-
-
-/*
- * Maintain the inventory at the stores.
- */
-void store_maint(int town_num, int store_num)
-{
- int j, tries = 100;
-
- int old_rating = rating;
-
- cur_store_num = store_num;
-
- /* Ignore home */
- if (store_num == STORE_HOME) return;
-
- /* Activate that store */
- st_ptr = &town_info[town_num].store[store_num];
-
- /* Ignoer Museum */
- if (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM) return;
-
- /* Activate the owner */
- ot_ptr = &ow_info[st_ptr->owner];
-
- /* Store keeper forgives the player */
- st_ptr->insult_cur = 0;
-
- /* Mega-Hack -- prune the black market */
- if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM)
- {
- /* Destroy crappy black market items */
- for (j = st_ptr->stock_num - 1; j >= 0; j--)
- {
- object_type *o_ptr = &st_ptr->stock[j];
-
- /* Destroy crappy items */
- if (black_market_crap(o_ptr))
- {
- /* Destroy the item */
- store_item_increase(j, 0 - o_ptr->number);
- store_item_optimize(j);
- }
- }
- }
-
-
- /* Choose the number of slots to keep */
- j = st_ptr->stock_num;
-
- /* Sell a few items */
- j = j - randint(STORE_TURNOVER);
-
- /* Never keep more than "STORE_MAX_KEEP" slots */
- if (j > STORE_MAX_KEEP) j = STORE_MAX_KEEP;
-
- /* Always "keep" at least "STORE_MIN_KEEP" items */
- if (j < STORE_MIN_KEEP) j = STORE_MIN_KEEP;
-
- /* Hack -- prevent "underflow" */
- if (j < 0) j = 0;
-
- /* Destroy objects until only "j" slots are left */
- while (st_ptr->stock_num > j) store_delete();
-
-
- /* Choose the number of slots to fill */
- j = st_ptr->stock_num;
-
- /* Buy some more items */
- j = j + randint(STORE_TURNOVER);
-
- /* Never keep more than "STORE_MAX_KEEP" slots */
- if (j > STORE_MAX_KEEP) j = STORE_MAX_KEEP;
-
- /* Always "keep" at least "STORE_MIN_KEEP" items */
- if (j < STORE_MIN_KEEP) j = STORE_MIN_KEEP;
-
- /* Hack -- prevent "overflow" */
- if (j >= st_ptr->stock_size) j = st_ptr->stock_size - 1;
-
- /* Acquire some new items */
- while ((st_ptr->stock_num < j) && tries)
- {
- store_create();
- tries--;
- }
-
- /* Hack -- Restore the rating */
- rating = old_rating;
-}
-
-
-/*
- * Initialize the stores
- */
-void store_init(int town_num, int store_num)
-{
- int k;
-
- cur_store_num = store_num;
-
- /* Activate that store */
- st_ptr = &town_info[town_num].store[store_num];
-
-
- /* Pick an owner */
- st_ptr->owner = st_info[st_ptr->st_idx].owners[rand_int(4)];
-
- /* Activate the new owner */
- ot_ptr = &ow_info[st_ptr->owner];
-
-
- /* Initialize the store */
- st_ptr->store_open = 0;
- st_ptr->insult_cur = 0;
- st_ptr->good_buy = 0;
- st_ptr->bad_buy = 0;
-
- /* Nothing in stock */
- st_ptr->stock_num = 0;
-
- /*
- * MEGA-HACK - Last visit to store is
- * BEFORE player birth to enable store restocking
- */
- st_ptr->last_visit = -100L * STORE_TURNS;
-
- /* Clear any old items */
- for (k = 0; k < st_ptr->stock_size; k++)
- {
- object_wipe(&st_ptr->stock[k]);
- }
-}
-
-
-void move_to_black_market(object_type * o_ptr)
-{
- st_ptr = &town_info[p_ptr->town_num].store[6];
- o_ptr->ident |= IDENT_STOREB;
- (void)store_carry(o_ptr);
- object_wipe(o_ptr); /* Don't leave a bogus object behind... */
-}
-
-/*
- * Enter the home, and interact with it from the dungeon (trump magic).
- *
- * Note that we use the standard "request_command()" function
- * to get a command, allowing us to use "command_arg" and all
- * command macros and other nifty stuff, but we use the special
- * "shopping" argument, to force certain commands to be converted
- * into other commands, normally, we convert "p" (pray) and "m"
- * (cast magic) into "g" (get), and "s" (search) into "d" (drop).
- */
-void do_cmd_home_trump(void)
-{
- int which;
- int maintain_num;
- int tmp_chr;
- int i;
- int town_num;
-
- /* Extract the store code */
- which = 7;
-
- if (p_ptr->town_num) town_num = p_ptr->town_num;
- else town_num = 1;
-
- /* Hack -- Check the "locked doors" */
- if (town_info[town_num].store[which].store_open >= turn)
- {
- msg_print("The doors are locked.");
- return;
- }
-
- /* Calculate the number of store maintainances since the last visit */
- maintain_num = (turn - town_info[town_num].store[which].last_visit) / (10L * STORE_TURNS);
-
- /* Maintain the store max. 10 times */
- if (maintain_num > 10) maintain_num = 10;
-
- if (maintain_num)
- {
- /* Maintain the store */
- for (i = 0; i < maintain_num; i++)
- store_maint(town_num, which);
-
- /* Save the visit */
- town_info[town_num].store[which].last_visit = turn;
- }
-
- /* Forget the lite */
- /* forget_lite(); */
-
- /* Forget the view */
- forget_view();
-
-
- /* Hack -- Character is in "icky" mode */
- character_icky = TRUE;
-
-
- /* No command argument */
- command_arg = 0;
-
- /* No repeated command */
- command_rep = 0;
-
- /* No automatic command */
- command_new = 0;
-
-
- /* Save the store number */
- cur_store_num = which;
-
- /* Save the store and owner pointers */
- st_ptr = &town_info[town_num].store[cur_store_num];
- ot_ptr = &ow_info[st_ptr->owner];
-
-
- /* Start at the beginning */
- store_top = 0;
-
- /* Display the store */
- display_store();
-
- /* Mega-Hack -- Ignore keymaps on store action letters */
- for (i = 0; i < 6; i++)
- {
- store_action_type *ba_ptr =
- &ba_info[st_info[st_ptr->st_idx].actions[i]];
- request_command_ignore_keymaps[2*i] = ba_ptr->letter;
- request_command_ignore_keymaps[2*i+1] = ba_ptr->letter_aux;
- }
-
- /* Do not leave */
- leave_store = FALSE;
-
- /* Interact with player */
- while (!leave_store)
- {
- /* Hack -- Clear line 1 */
- prt("", 1, 0);
-
- /* Hack -- Check the charisma */
- tmp_chr = p_ptr->stat_use[A_CHR];
-
- /* Clear */
- clear_from(21);
-
-
- /* Basic commands */
- prt(" ESC) Exit from Building.", 22, 0);
-
- /* Browse if necessary */
- if (st_ptr->stock_num > 12)
- {
- prt(" SPACE) Next page of stock", 23, 0);
- }
-
- /* Home commands */
- if (cur_store_num == 7)
- {
- prt(" g) Get an item.", 22, 31);
- prt(" d) Drop an item.", 23, 31);
- }
-
- /* Shop commands XXX XXX XXX */
- else
- {
- prt(" p) Purchase an item.", 22, 31);
- prt(" s) Sell an item.", 23, 31);
- }
-
- /* Add in the eXamine option */
- prt(" x) eXamine an item.", 22, 56);
-
- /* Prompt */
- prt("You may: ", 21, 0);
-
- /* Get a command */
- request_command(TRUE);
-
- /* Process the command */
- store_process_command();
-
- /* Hack -- Character is still in "icky" mode */
- character_icky = TRUE;
-
- /* Notice stuff */
- notice_stuff();
-
- /* Handle stuff */
- handle_stuff();
-
- /* XXX XXX XXX Pack Overflow */
- if (p_ptr->inventory[INVEN_PACK].k_idx)
- {
- int item = INVEN_PACK;
-
- object_type *o_ptr = &p_ptr->inventory[item];
-
- /* Hack -- Flee from the store */
- if (cur_store_num != 7)
- {
- /* Message */
- msg_print("Your pack is so full that you flee the store...");
-
- /* Leave */
- leave_store = TRUE;
- }
-
- /* Hack -- Flee from the home */
- else if (!store_check_num(o_ptr))
- {
- /* Message */
- msg_print("Your pack is so full that you flee your home...");
-
- /* Leave */
- leave_store = TRUE;
- }
-
- /* Hack -- Drop items into the home */
- else
- {
- int item_pos;
-
- object_type forge;
- object_type *q_ptr;
-
- char o_name[80];
-
-
- /* Give a message */
- msg_print("Your pack overflows!");
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Grab a copy of the item */
- object_copy(q_ptr, o_ptr);
-
- /* Describe it */
- object_desc(o_name, q_ptr, TRUE, 3);
-
- /* Message */
- msg_format("You drop %s (%c).", o_name, index_to_label(item));
-
- /* Remove it from the players inventory */
- inc_stack_size(item, -255);
-
- /* Handle stuff */
- handle_stuff();
-
- /* Let the home carry it */
- item_pos = home_carry(q_ptr);
-
- /* Redraw the home */
- if (item_pos >= 0)
- {
- store_top = (item_pos / 12) * 12;
- display_inventory();
- }
- }
- }
-
- /* Hack -- Redisplay store prices if charisma changes */
- if (tmp_chr != p_ptr->stat_use[A_CHR]) display_inventory();
-
- /* Hack -- get kicked out of the store */
- if (st_ptr->store_open >= turn) leave_store = TRUE;
- }
-
-
- /* Hack -- Character is no longer in "icky" mode */
- character_icky = FALSE;
-
-
- /* Hack -- Cancel automatic command */
- command_new = 0;
-
- /* Mega-Hack -- Clear the 'ignore-keymaps' list */
- memset(request_command_ignore_keymaps, 0, 12);
-
- /* Flush messages XXX XXX XXX */
- msg_print(NULL);
-
-
- /* Clear the screen */
- Term_clear();
-
-
- /* Update everything */
- p_ptr->update |= (PU_VIEW | PU_MON_LITE);
- p_ptr->update |= (PU_MONSTERS);
-
- /* Redraw entire screen */
- p_ptr->redraw |= (PR_BASIC | PR_EXTRA);
-
- /* Redraw map */
- p_ptr->redraw |= (PR_MAP);
-
- /* Window stuff */
- p_ptr->window |= (PW_OVERHEAD);
-}
-
-static void pay_for_requested_item(int value, object_type *q_ptr)
-{
- msg_format("It'll cost %i gold pieces. ", value);
-
- if (get_check("Do you wish to pay?"))
- {
- if (p_ptr->au < value)
- msg_print("You don't have enough money for it.");
- else
- {
- if (store_carry(q_ptr) != -1)
- {
- msg_print("The item has arrived in the Black Market.");
- p_ptr->au -= value;
-
- p_ptr->redraw |= PR_GOLD;
- }
- else
- msg_print("There isn't enough room for it.");
- }
- }
-}
-
-/*
- * Request item for merchants
- */
-void store_request_item(void)
-{
- char buf[80], name[80];
- object_type forge, *q_ptr = &forge;
- store_type *ost_ptr = st_ptr;
-
- /* Get the Black Market */
- st_ptr = &town_info[p_ptr->town_num].store[6];
-
- /* Make an empty string */
- buf[0] = 0;
-
- /* Ask for the wish */
- if (!get_string("Request what? ", buf, 80))
- {
- st_ptr = ost_ptr;
- return;
- }
-
- clean_wish_name(buf, name);
-
- if (test_object_wish(name, q_ptr, &forge, "request"))
- {
- int value = object_value_real(q_ptr) * 5;
-
- /* Pay for the delivery */
- pay_for_requested_item(value, q_ptr);
-
- /* Don't search any more */
- st_ptr = ost_ptr;
- return;
- }
-
- st_ptr = ost_ptr;
-}