Item value


Although the central place for design discussion is ##crawl-dev on freenode, some may find it helpful to discuss requests and suggestions here first.

Ziggurat Zagger

Posts: 8786

Joined: Sunday, 5th May 2013, 08:25

Post Sunday, 9th February 2014, 08:53

Item value

Item value is currently rather silly. Boots of running can cost less than a +0 ring mail. A +5, +0 randart hammer of draining with rElec can cost more than a demon whip of electrocution. I think item prices need a complete overhaul.
Here is the current code should anyone be interested in it and too lazy to open shopping.cc for themselves:
  Code:
unsigned int item_value(item_def item, bool ident)
{
    // Note that we pass item in by value, since we want a local
    // copy to mangle as necessary.
    item.flags = (ident) ? (item.flags | ISFLAG_IDENT_MASK) : (item.flags);

    if (is_unrandom_artefact(item)
        && item_ident(item, ISFLAG_KNOW_PROPERTIES))
    {
        const unrandart_entry *entry = get_unrand_entry(item.special);
        if (entry->value != 0)
            return entry->value;
    }

    int valued = 0;

    switch (item.base_type)
    {
    case OBJ_WEAPONS:
        switch (item.sub_type)
        {
        case WPN_CLUB:
            valued += 10;
            break;

        case WPN_SLING:
            valued += 15;
            break;

        case WPN_GIANT_CLUB:
            valued += 17;
            break;

        case WPN_GIANT_SPIKED_CLUB:
            valued += 19;
            break;

        case WPN_DAGGER:
        case WPN_STAFF:
            valued += 20;
            break;

        case WPN_WHIP:
        case WPN_BLOWGUN:
            valued += 25;
            break;

        case WPN_HAND_AXE:
            valued += 28;
            break;

        case WPN_HAMMER:
        case WPN_FALCHION:
        case WPN_MACE:
        case WPN_SCYTHE:
            valued += 30;
            break;

        case WPN_BOW:
            valued += 31;
            break;

        case WPN_SHORT_SWORD:
        case WPN_SPEAR:
            valued += 32;
            break;

        case WPN_FLAIL:
            valued += 35;
            break;

        case WPN_WAR_AXE:
        case WPN_MORNINGSTAR:
        case WPN_CUTLASS:
        case WPN_QUARTERSTAFF:
            valued += 40;
            break;

        case WPN_CROSSBOW:
            valued += 41;
            break;

        case WPN_TRIDENT:
            valued += 42;
            break;

        case WPN_LONG_SWORD:
        case WPN_LONGBOW:
        case WPN_SCIMITAR:
        case WPN_BLESSED_FALCHION:
            valued += 45;
            break;

        case WPN_BLESSED_LONG_SWORD:
        case WPN_BLESSED_SCIMITAR:
            valued += 50;

        case WPN_HALBERD:
            valued += 52;
            break;

        case WPN_GLAIVE:
            valued += 55;
            break;

        case WPN_BROAD_AXE:
        case WPN_GREAT_SWORD:
            valued += 60;
            break;

        case WPN_BATTLEAXE:
        case WPN_GREAT_MACE:
        case WPN_EVENINGSTAR:
            valued += 65;
            break;

        case WPN_DIRE_FLAIL:
        case WPN_BARDICHE:
            valued += 90;
            break;

        case WPN_EXECUTIONERS_AXE:
            valued += 100;
            break;

        case WPN_BASTARD_SWORD:
            valued += 100;
            break;

        case WPN_DEMON_WHIP:
            valued += 130;
            break;

        case WPN_QUICK_BLADE:
        case WPN_DEMON_TRIDENT:
            valued += 150;
            break;

        case WPN_DEMON_BLADE:
        case WPN_CLAYMORE:
        case WPN_EUDEMON_BLADE:
        case WPN_BLESSED_BASTARD_SWORD:
        case WPN_BLESSED_GREAT_SWORD:
        case WPN_BLESSED_CLAYMORE:
        case WPN_SACRED_SCOURGE:
        case WPN_TRISHULA:
        case WPN_LAJATANG:
            valued += 200;
            break;
        }

        if (item_type_known(item))
        {
            switch (get_weapon_brand(item))
            {
            case SPWPN_NORMAL:
            default:            // randart
                valued *= 10;
                break;

            case SPWPN_DRAINING:
                valued *= 64;
                break;

            case SPWPN_VAMPIRICISM:
                valued *= 60;
                break;

            case SPWPN_FLAME:
            case SPWPN_FROST:
            case SPWPN_HOLY_WRATH:
                valued *= 50;
                break;

            case SPWPN_CHAOS:
            case SPWPN_SPEED:
                valued *= 40;
                break;

            case SPWPN_DISTORTION:
            case SPWPN_ELECTROCUTION:
            case SPWPN_PAIN:
                valued *= 30;
                break;

            case SPWPN_FLAMING:
            case SPWPN_FREEZING:
            case SPWPN_DRAGON_SLAYING:
                valued *= 25;
                break;

            case SPWPN_VENOM:
                valued *= 23;
                break;

            case SPWPN_VORPAL:
            case SPWPN_PROTECTION:
            case SPWPN_EVASION:
                valued *= 20;
                break;
            }

            valued /= 10;
        }

        if (get_equip_race(item) == ISFLAG_ELVEN
            || get_equip_race(item) == ISFLAG_DWARVEN)
        {
            valued *= 12;
            valued /= 10;
        }

        if (get_equip_race(item) == ISFLAG_ORCISH)
        {
            valued *= 8;
            valued /= 10;
        }

        if (item_ident(item, ISFLAG_KNOW_PLUSES))
        {
            if (item.plus >= 0)
            {
                valued += item.plus * 2;
                valued *= 10 + 3 * item.plus;
                valued /= 10;
            }

            if (item.plus2 >= 0)
            {
                valued += item.plus2 * 2;
                valued *= 10 + 3 * item.plus2;
                valued /= 10;
            }

            if (item.plus < 0)
            {
                valued -= 5;
                valued += (item.plus * item.plus * item.plus);

                if (valued < 1)
                    valued = 1;
            }

            if (item.plus2 < 0)
            {
                valued -= 5;
                valued += (item.plus2 * item.plus2 * item.plus2);

                if (valued < 1)
                    valued = 1;
            }
        }

        if (is_artefact(item))
        {
            if (item_type_known(item))
                valued += (7 * artefact_value(item));
            else
                valued += 50;
        }
        else if (item_type_known(item)
                 && get_equip_desc(item) != 0)
        {
            valued += 20;
        }

        if (item_known_cursed(item))
        {
            valued *= 6;
            valued /= 10;
        }
        break;

    case OBJ_MISSILES:          // ammunition
        switch (item.sub_type)
        {
        case MI_DART:
        case MI_STONE:
        case MI_NONE:
            valued++;
            break;
        case MI_NEEDLE:
        case MI_ARROW:
        case MI_BOLT:
            valued += 2;
            break;
        case MI_LARGE_ROCK:
            valued += 7;
            break;
        case MI_JAVELIN:
            valued += 8;
            break;
        case MI_THROWING_NET:
            valued += 30;
            break;
        default:
            valued += 5;
            break;
        }

        if (item_type_known(item))
        {
            switch (get_ammo_brand(item))
            {
            case SPMSL_NORMAL:
            default:
                valued *= 10;
                break;

            case SPMSL_RETURNING:
                valued *= 50;
                break;

            case SPMSL_CHAOS:
                valued *= 40;
                break;

            case SPMSL_CURARE:
            case SPMSL_PENETRATION:
            case SPMSL_SILVER:
            case SPMSL_STEEL:
            case SPMSL_DISPERSAL:
            case SPMSL_EXPLODING:
                valued *= 30;
                break;

            case SPMSL_FLAME:
            case SPMSL_FROST:
                valued *= 25;
                break;

            case SPMSL_POISONED:
            case SPMSL_PARALYSIS:
            case SPMSL_SLOW:
            case SPMSL_SLEEP:
            case SPMSL_CONFUSION:
#if TAG_MAJOR_VERSION == 34
            case SPMSL_SICKNESS:
#endif
            case SPMSL_FRENZY:
                valued *= 23;
                break;
            }

            valued /= 10;
        }

        if (get_equip_race(item) == ISFLAG_ELVEN
            || get_equip_race(item) == ISFLAG_DWARVEN)
        {
            valued *= 12;
            valued /= 10;
        }

        if (get_equip_race(item) == ISFLAG_ORCISH)
        {
            valued *= 8;
            valued /= 10;
        }

        if (item_ident(item, ISFLAG_KNOW_PLUSES))
        {
            if (item.plus >= 0)
                valued += (item.plus * 2);

            if (item.plus < 0)
            {
                valued += item.plus * item.plus * item.plus;

                if (valued < 1)
                    valued = 1;
            }
        }
        break;

    case OBJ_ARMOUR:
        switch (item.sub_type)
        {
        case ARM_PEARL_DRAGON_ARMOUR:
        case ARM_GOLD_DRAGON_ARMOUR:
            valued += 1600;
            break;

        case ARM_PEARL_DRAGON_HIDE:
        case ARM_GOLD_DRAGON_HIDE:
            valued += 1400;
            break;

        case ARM_STORM_DRAGON_ARMOUR:
            valued += 1050;
            break;

        case ARM_STORM_DRAGON_HIDE:
            valued += 900;
            break;

        case ARM_FIRE_DRAGON_ARMOUR:
        case ARM_ICE_DRAGON_ARMOUR:
            valued += 750;
            break;

        case ARM_SWAMP_DRAGON_ARMOUR:
            valued += 650;
            break;

        case ARM_FIRE_DRAGON_HIDE:
        case ARM_CRYSTAL_PLATE_ARMOUR:
        case ARM_TROLL_LEATHER_ARMOUR:
        case ARM_ICE_DRAGON_HIDE:
            valued += 500;
            break;

        case ARM_MOTTLED_DRAGON_ARMOUR:
        case ARM_SWAMP_DRAGON_HIDE:
            valued += 400;
            break;

        case ARM_STEAM_DRAGON_ARMOUR:
        case ARM_MOTTLED_DRAGON_HIDE:
            valued += 300;
            break;

        case ARM_PLATE_ARMOUR:
            valued += 230;
            break;

        case ARM_STEAM_DRAGON_HIDE:
            valued += 200;
            break;

        case ARM_CENTAUR_BARDING:
        case ARM_NAGA_BARDING:
            valued += 150;
            break;

        case ARM_TROLL_HIDE:
            valued += 130;
            break;

        case ARM_CHAIN_MAIL:
            valued += 110;
            break;

        case ARM_SCALE_MAIL:
            valued += 83;
            break;

        case ARM_LARGE_SHIELD:
            valued += 75;
            break;

        case ARM_SHIELD:
            valued += 45;
            break;

        case ARM_RING_MAIL:
            valued += 40;
            break;

        case ARM_HELMET:
#if TAG_MAJOR_VERSION == 34
        case ARM_CAP:
#endif
        case ARM_HAT:
        case ARM_BUCKLER:
            valued += 25;
            break;

        case ARM_LEATHER_ARMOUR:
            valued += 20;
            break;

        case ARM_BOOTS:
            valued += 15;
            break;

        case ARM_GLOVES:
            valued += 12;
            break;

        case ARM_CLOAK:
            valued += 10;
            break;

        case ARM_ROBE:
            valued += 7;
            break;

        case ARM_ANIMAL_SKIN:
            valued += 3;
            break;
        }

        if (item_type_known(item))
        {
            const int sparm = get_armour_ego_type(item);
            switch (sparm)
            {
            case SPARM_NORMAL:
            default:
                valued *= 10;
                break;

            case SPARM_ARCHMAGI:
                valued *= 100;
                break;

            case SPARM_DARKNESS:
            case SPARM_RESISTANCE:
            case SPARM_REFLECTION:
                valued *= 60;
                break;

            case SPARM_POSITIVE_ENERGY:
                valued *= 50;
                break;

            case SPARM_MAGIC_RESISTANCE:
            case SPARM_PROTECTION:
            case SPARM_RUNNING:
                valued *= 40;
                break;

            case SPARM_COLD_RESISTANCE:
            case SPARM_DEXTERITY:
            case SPARM_FIRE_RESISTANCE:
            case SPARM_SEE_INVISIBLE:
            case SPARM_INTELLIGENCE:
            case SPARM_FLYING:
            case SPARM_JUMPING:
            case SPARM_PRESERVATION:
            case SPARM_STEALTH:
            case SPARM_STRENGTH:
                valued *= 30;
                break;

            case SPARM_POISON_RESISTANCE:
                valued *= 20;
                break;

            case SPARM_PONDEROUSNESS:
                valued /= 3;
                break;
            }

            valued /= 10;
        }

        if (get_equip_race(item) == ISFLAG_ELVEN
            || get_equip_race(item) == ISFLAG_DWARVEN)
        {
            valued *= 12;
            valued /= 10;
        }

        if (get_equip_race(item) == ISFLAG_ORCISH)
        {
            valued *= 8;
            valued /= 10;
        }

        if (item_ident(item, ISFLAG_KNOW_PLUSES))
        {
            valued += 5;
            if (item.plus >= 0)
            {
                valued += item.plus * 30;
                valued *= 10 + 4 * item.plus;
                valued /= 10;
            }

            if (item.plus < 0)
            {
                valued += item.plus * item.plus * item.plus;

                if (valued < 1)
                    valued = 1;
            }
        }

        if (is_artefact(item))
        {
            if (item_type_known(item))
                valued += (7 * artefact_value(item));
            else
                valued += 50;
        }
        else if (item_type_known(item) && get_equip_desc(item) != 0)
            valued += 20;

        if (item_known_cursed(item))
        {
            valued *= 6;
            valued /= 10;
        }
        break;

    case OBJ_WANDS:
        if (!item_type_known(item))
            valued += 200;
        else
        {
            // true if the wand is of a good type, a type with significant
            // inherent value even when empty. Good wands are less expensive
            // per charge.
            bool good = false;
            switch (item.sub_type)
            {
            case WAND_HASTING:
            case WAND_HEAL_WOUNDS:
                valued += 240;
                good = true;
                break;

            case WAND_TELEPORTATION:
                valued += 120;
                good = true;
                break;

            case WAND_COLD:
            case WAND_FIRE:
            case WAND_FIREBALL:
            case WAND_DIGGING:
                valued += 80;
                good = true;
                break;

            case WAND_INVISIBILITY:
            case WAND_DRAINING:
            case WAND_LIGHTNING:
            case WAND_DISINTEGRATION:
                valued += 40;
                good = true;
                break;

            case WAND_ENSLAVEMENT:
            case WAND_POLYMORPH:
            case WAND_PARALYSIS:
                valued += 20;
                break;

            case WAND_CONFUSION:
            case WAND_SLOWING:
                valued += 15;
                break;

            case WAND_FLAME:
            case WAND_FROST:
            case WAND_RANDOM_EFFECTS:
                valued += 10;
                break;

            case WAND_MAGIC_DARTS:
            default:
                valued += 6;
                break;
            }

            if (item_ident(item, ISFLAG_KNOW_PLUSES))
            {
                if (good) valued += (valued * item.plus) / 4;
                else      valued += (valued * item.plus) / 2;
            }
        }
        break;

    case OBJ_POTIONS:
        if (!item_type_known(item))
            valued += 9;
        else
        {
            switch (item.sub_type)
            {
            case POT_EXPERIENCE:
                valued += 500;
                break;

            case POT_CURE_MUTATION:
#if TAG_MAJOR_VERSION == 34
            case POT_GAIN_DEXTERITY:
            case POT_GAIN_INTELLIGENCE:
            case POT_GAIN_STRENGTH:
#endif
            case POT_BENEFICIAL_MUTATION:
                valued += 350;
                break;

            case POT_MAGIC:
            case POT_RESISTANCE:
                valued += 70;
                break;

            case POT_SPEED:
            case POT_INVISIBILITY:
                valued += 55;
                break;

            case POT_BERSERK_RAGE:
            case POT_HEAL_WOUNDS:
            case POT_RESTORE_ABILITIES:
            case POT_FLIGHT:
            case POT_MUTATION:
            case POT_LIGNIFY:
                valued += 30;
                break;

            case POT_MIGHT:
            case POT_AGILITY:
            case POT_BRILLIANCE:
                valued += 25;
                break;

            case POT_CURING:
            case POT_DECAY:
            case POT_DEGENERATION:
            case POT_STRONG_POISON:
                valued += 20;
                break;

            case POT_BLOOD:
            case POT_PORRIDGE:
            case POT_CONFUSION:
            case POT_PARALYSIS:
            case POT_POISON:
            case POT_SLOWING:
                valued += 10;
                break;

            case POT_BLOOD_COAGULATED:
                valued += 5;
                break;
            }
        }
        break;

    case OBJ_FOOD:
        switch (item.sub_type)
        {
        case FOOD_ROYAL_JELLY:
            valued = 120;
            break;

        case FOOD_MEAT_RATION:
        case FOOD_BREAD_RATION:
            valued = 40;
            break;

        case FOOD_HONEYCOMB:
            valued = 25;
            break;

        case FOOD_BEEF_JERKY:
        case FOOD_PIZZA:
            valued = 18;
            break;

        case FOOD_CHEESE:
        case FOOD_SAUSAGE:
            valued = 15;
            break;

        case FOOD_LEMON:
        case FOOD_ORANGE:
        case FOOD_BANANA:
            valued = 12;
            break;

        case FOOD_APPLE:
        case FOOD_APRICOT:
        case FOOD_PEAR:
            valued = 8;
            break;

        case FOOD_CHUNK:
            if (food_is_rotten(item))
                break;

        case FOOD_CHOKO:
        case FOOD_LYCHEE:
        case FOOD_RAMBUTAN:
        case FOOD_SNOZZCUMBER:
            valued = 4;
            break;

        case FOOD_STRAWBERRY:
        case FOOD_GRAPE:
        case FOOD_SULTANA:
            valued = 1;
            break;
        }
        break;

    case OBJ_SCROLLS:
        if (!item_type_known(item))
            valued += 10;
        else
        {
            switch (item.sub_type)
            {
            case SCR_ACQUIREMENT:
                valued += 520;
                break;

            case SCR_ENCHANT_WEAPON_III:
            case SCR_BRAND_WEAPON:
                valued += 200;
                break;

            case SCR_SUMMONING:
                valued += 95;
                break;

            case SCR_TORMENT:
            case SCR_HOLY_WORD:
            case SCR_SILENCE:
            case SCR_VULNERABILITY:
                valued += 75;
                break;

            case SCR_RECHARGING:
            case SCR_AMNESIA:
            case SCR_ENCHANT_ARMOUR:
            case SCR_ENCHANT_WEAPON_I:
            case SCR_ENCHANT_WEAPON_II:
            case SCR_BLINKING:
                valued += 55;
                break;

            case SCR_FEAR:
            case SCR_IMMOLATION:
            case SCR_MAGIC_MAPPING:
                valued += 35;
                break;

            case SCR_REMOVE_CURSE:
            case SCR_TELEPORTATION:
                valued += 30;
                break;

            case SCR_FOG:
            case SCR_IDENTIFY:
            case SCR_CURSE_ARMOUR:
            case SCR_CURSE_WEAPON:
            case SCR_CURSE_JEWELLERY:
                valued += 20;
                break;

            case SCR_NOISE:
            case SCR_RANDOM_USELESSNESS:
                valued += 10;
                break;
            }
        }
        break;

    case OBJ_JEWELLERY:
        if (item_known_cursed(item))
            valued -= 10;

        if (!item_type_known(item))
            valued += 250;
        else
        {
            // Variable-strength rings.
            if (item_ident(item, ISFLAG_KNOW_PLUSES)
                && (item.sub_type == RING_PROTECTION
                    || item.sub_type == RING_STRENGTH
                    || item.sub_type == RING_EVASION
                    || item.sub_type == RING_DEXTERITY
                    || item.sub_type == RING_INTELLIGENCE
                    || item.sub_type == RING_SLAYING))
            {
                // Formula: price = kn(n+1) / 2, where k depends on the subtype,
                // n is the power. (The base variable is equal to 2n.)
                int base = 0;
                int coefficient = 0;
                if (item.sub_type == RING_SLAYING)
                    base = item.plus + 2 * item.plus2;
                else
                    base = 2 * item.plus;

                switch (item.sub_type)
                {
                case RING_SLAYING:
                    coefficient = 50;
                    break;
                case RING_PROTECTION:
                case RING_EVASION:
                    coefficient = 40;
                    break;
                case RING_STRENGTH:
                case RING_DEXTERITY:
                case RING_INTELLIGENCE:
                    coefficient = 30;
                    break;
                default:
                    break;
                }

                if (base <= 0)
                    valued += 25 * base;
                else
                    valued += (coefficient * base * (base + 1)) / 8;
            }
            else
            {
                switch (item.sub_type)
                {
                case RING_TELEPORT_CONTROL:
                    valued += 500;
                    break;

                case AMU_RESIST_MUTATION:
                case AMU_RAGE:
                    valued += 400;
                    break;

                case RING_INVISIBILITY:
                case RING_REGENERATION:
                case RING_WIZARDRY:
                case AMU_FAITH:
                case AMU_THE_GOURMAND:
                    valued += 300;
                    break;

                case RING_PROTECTION_FROM_COLD:
                case RING_PROTECTION_FROM_FIRE:
                case RING_PROTECTION_FROM_MAGIC:
                case AMU_GUARDIAN_SPIRIT:
                case AMU_CONSERVATION:
                    valued += 250;
                    break;

                case RING_MAGICAL_POWER:
                case RING_FIRE:
                case RING_ICE:
                case RING_LIFE_PROTECTION:
                case RING_POISON_RESISTANCE:
                case AMU_CLARITY:
                case AMU_RESIST_CORROSION:
                    valued += 200;
                    break;

                case RING_SUSTAIN_ABILITIES:
                case RING_SUSTENANCE:
                case RING_TELEPORTATION:
                case RING_FLIGHT:
                case AMU_STASIS:
                    valued += 175;
                    break;

                case RING_SEE_INVISIBLE:
                case AMU_WARDING:
                    valued += 150;
                    break;

                case RING_HUNGER:
                case AMU_INACCURACY:
                    valued -= 300;
                    break;
                    // got to do delusion!
                }
            }

            if (is_artefact(item))
            {
                // in this branch we're guaranteed to know
                // the item type!
                if (valued < 0)
                    valued = (artefact_value(item) - 5) * 7;
                else
                    valued += artefact_value(item) * 7;
            }

            // Hard minimum, as it's worth 20 to ID a ring.
            valued = max(20, valued);
        }
        break;

    case OBJ_MISCELLANY:
        switch (item.sub_type)
        {
        case MISC_RUNE_OF_ZOT:  // upped from 1200 to encourage collecting
            valued += 10000;
            break;

        case MISC_HORN_OF_GERYON:
            valued += 5000;
            break;

        case MISC_DISC_OF_STORMS:
            valued += 2000;
            break;

        case MISC_SACK_OF_SPIDERS:
            valued += 400;
            break;

        case MISC_FAN_OF_GALES:
        case MISC_STONE_OF_TREMORS:
        case MISC_PHIAL_OF_FLOODS:
        case MISC_LAMP_OF_FIRE:
            valued += 1000;
            break;

        case MISC_BOX_OF_BEASTS:
            valued += 500;
            break;

        default:
            if (is_deck(item))
                valued += 200 + item.special * 150;
            else
                valued += 500;
        }
        break;

    case OBJ_BOOKS:
        valued = 150;
        if (item.sub_type == BOOK_DESTRUCTION)
            break;

        if (item_type_known(item))
        {
            double rarity = 0;
            if (is_random_artefact(item))
            {
                // Consider spellbook as rare as the average of its
                // three rarest spells.
                int rarities[SPELLBOOK_SIZE];
                int count_valid = 0;
                for (int i = 0; i < SPELLBOOK_SIZE; i++)
                {
                    spell_type spell = which_spell_in_book(item, i);
                    if (spell == SPELL_NO_SPELL)
                    {
                        rarities[i] = 0;
                        continue;
                    }

                    rarities[i] = spell_rarity(spell);
                    count_valid++;
                }
                ASSERT(count_valid > 0);

                if (count_valid > 3)
                    count_valid = 3;

                sort(rarities, rarities + SPELLBOOK_SIZE);
                for (int i = SPELLBOOK_SIZE - 1;
                     i >= SPELLBOOK_SIZE - count_valid; i--)
                {
                    rarity += rarities[i];
                }

                rarity /= count_valid;

                // Fixed level randarts get a bonus for the really low and
                // really high level spells.
                if (item.sub_type == BOOK_RANDART_LEVEL)
                    valued += 50 * abs(5 - item.plus);
            }
            else
                rarity = book_rarity(item.sub_type);

            valued += (int)(rarity * 50.0);
        }
        break;

    case OBJ_STAVES:
        valued = item_type_known(item) ? 250 : 120;
        break;

    case OBJ_RODS:
        if (!item_type_known(item))
            valued = 120;
        else if (item.sub_type == ROD_STRIKING
                 || item.sub_type == ROD_WARDING)
        {
            valued = 150;
        }
        else
            valued = 250;
        if (item_ident(item, ISFLAG_KNOW_PLUSES))
            valued += 50 * (item.plus2 / ROD_CHARGE_MULT);
        break;

    case OBJ_ORBS:
        valued = 250000;
        break;

    default:
        break;
    }                           // end switch

    if (valued < 1)
        valued = 1;

    valued = stepdown_value(valued, 1000, 1000, 10000, 10000);

    return item.quantity * valued;
}


The general design I've come up with is: item prices should come from additive values for the most part. The only exception to this that I like is weapon and missile brands; it makes sense for them to have a multiplicative effect on price since their usefulness depends on the quality of the weapon (a vampiric great sword is extremely good, a vampiric hammer is still crap).

Here's a simple price list I came up with (terribly formatted). It is not precisely calculated or anything, just better than what is currently there.

  Code:
Weapons:
        case WPN_CLUB:
            valued += 10;
            break;

        case WPN_SLING:
        case WPN_STAFF:
            valued += 15;
            break;

        case WPN_GIANT_CLUB:
            valued += 17;
            break;

        case WPN_GIANT_SPIKED_CLUB:
            valued += 19;
            break;

        case WPN_DAGGER:
            valued += 20;
            break;

        case WPN_BLOWGUN:
        case WPN_HAMMER:
        case WPN_WHIP:
            valued += 25;
            break;

        case WPN_BOW:
        case WPN_HAND_AXE:
        case WPN_FALCHION:
        case WPN_MACE:
        case WPN_SCYTHE:
        case WPN_SHORT_SWORD:
        case WPN_SPEAR:
            valued += 30;
            break;

        case WPN_BLESSED_FALCHION:
        case WPN_WAR_AXE:
        case WPN_FLAIL:
        case WPN_LONG_SWORD:
        case WPN_TRIDENT:
            valued += 35;
            break;

        case WPN_BLESSED_LONG_SWORD:
        case WPN_BROAD_AXE:
        case WPN_CUTLASS:
        case WPN_DIRE_FLAIL:
        case WPN_HALBERD:
        case WPN_MORNINGSTAR:
        case WPN_QUARTERSTAFF:
        case WPN_SCIMITAR:
            valued += 40;
            break;

        case WPN_CROSSBOW:
            valued += 41;
            break;

        case WPN_LONGBOW:
            valued += 45;
            break;

        case WPN_BATTLEAXE:
        case WPN_GLAIVE:
        case WPN_GREAT_MACE:
        case WPN_GREAT_SWORD:
            valued += 65;
            break;

        case WPN_BARDICHE:
            valued += 90;
            break;

        case WPN_CLAYMORE:
        case WPN_EXECUTIONERS_AXE:
            valued += 100;
            break;

        case WPN_BASTARD_SWORD:
        case WPN_BLESSED_GREAT_SWORD:
        case WPN_BLESSED_SCIMITAR:
        case WPN_DEMON_WHIP:
        case WPN_DEMON_TRIDENT:
        case WPN_DEMON_BLADE:
        case WPN_EVENINGSTAR:
        case WPN_LAJATANG:
        case WPN_QUICK_BLADE:
            valued += 150;
            break;

        case WPN_BLESSED_BASTARD_SWORD:
        case WPN_BLESSED_CLAYMORE:
        case WPN_EUDEMON_BLADE:
        case WPN_SACRED_SCOURGE:
        case WPN_TRISHULA:
            valued += 200;
            break;
   --------------------------------------------------------------------------------
   Egos:
          case SPWPN_NORMAL:
          default:            // randart
              valued *= 10;
              break;

          case SPWPN_SPEED:
          case SPWPN_VAMPIRICISM:
              valued *= 30;
              break;

          case SPWPN_DISTORTION:
          case SPWPN_ELECTROCUTION:
          case SPWPN_PAIN:
              valued *= 25;
              break;

          case SPWPN_CHAOS:
          case SPWPN_DRAINING:
          case SPWPN_FLAME:
          case SPWPN_FLAMING:
          case SPWPN_FREEZING:
          case SPWPN_FROST:
          case SPWPN_HOLY_WRATH:
              valued *= 18;
              break;

          case SPWPN_VORPAL:
              valued *= 15;
              break;

          case SPWPN_DRAGON_SLAYING:
          case SPWPN_EVASION:
          case SPWPN_PROTECTION:
          case SPWPN_VENOM:
              valued *= 12;
              break;
          }

          valued /= 10;
   --------------------------------------------------------------------------------
   Enchantment: I'd say from +10 for each point of to-hit and +50 for damage. Yes,
   it's tempting to make this non-linear but then you overprice stuff that's over +9.

   Race: I think racial items should be removed entirely, but if they stay then you
   could do like +1 for elven or dwarven I suppose.





Armour:
   case ARM_PEARL_DRAGON_ARMOUR:
       valued += 1000;
       break;

   case ARM_PEARL_DRAGON_HIDE:
       valued += 900;
       break;

   case ARM_CRYSTAL_PLATE_ARMOUR:
   case ARM_GOLD_DRAGON_ARMOUR:
   case ARM_STORM_DRAGON_ARMOUR:
       valued += 800;
       break;

   case ARM_GOLD_DRAGON_HIDE:
   case ARM_STORM_DRAGON_HIDE:
       valued += 700;
       break;

   case ARM_FIRE_DRAGON_ARMOUR:
   case ARM_ICE_DRAGON_ARMOUR:
       valued += 600;
       break;

   case ARM_FIRE_DRAGON_HIDE:
   case ARM_ICE_DRAGON_HIDE:
   case ARM_SWAMP_DRAGON_ARMOUR:
       valued += 500;
       break;

   case ARM_MOTTLED_DRAGON_ARMOUR:
   case ARM_STEAM_DRAGON_ARMOUR:
   case ARM_SWAMP_DRAGON_HIDE:
       valued += 400;
       break;

   case ARM_MOTTLED_DRAGON_HIDE:
   case ARM_STEAM_DRAGON_HIDE:
       valued += 300;
       break;

   case ARM_CENTAUR_BARDING:
   case ARM_NAGA_BARDING:
   case ARM_PLATE_ARMOUR:
       valued += 230;
       break;

   case ARM_TROLL_LEATHER_ARMOUR:
       valued += 150;
       break;

   case ARM_CHAIN_MAIL:
   case ARM_HELMET:
#if TAG_MAJOR_VERSION == 34
   case ARM_CAP:
#endif
   case ARM_BOOTS:
   case ARM_GLOVES:
   case ARM_CLOAK:
   case ARM_LARGE_SHIELD:
   case ARM_SHIELD:
   case ARM_BUCKLER:
       valued += 45;
       break;

   case ARM_SCALE_MAIL:
   case ARM_TROLL_HIDE:
   case ARM_RING_MAIL:
   case ARM_HAT:
       valued += 40;
       break;

   case ARM_LEATHER_ARMOUR:
       valued += 20;
       break;

   case ARM_ROBE:
       valued += 7;
       break;

   case ARM_ANIMAL_SKIN:
       valued += 3;
       break;
   -----------------------------------------------------------------------
   Egos:
          case SPARM_RUNNING:
          case SPARM_ARCHMAGI:
          case SPARM_PRESERVATION:
          case SPARM_RESISTANCE:
              valued += 250;
              break;

          case SPARM_COLD_RESISTANCE:
          case SPARM_DEXTERITY:
          case SPARM_FIRE_RESISTANCE:
          case SPARM_SEE_INVISIBLE:
          case SPARM_INTELLIGENCE:
          case SPARM_FLYING:
          case SPARM_JUMPING:
          case SPARM_STEALTH:
          case SPARM_STRENGTH:
          case SPARM_DARKNESS:
          case SPARM_MAGIC_RESISTANCE:
          case SPARM_PROTECTION:
              valued += 50;
              break;

          case SPARM_POSITIVE_ENERGY:
          case SPARM_POISON_RESISTANCE:
          case SPARM_REFLECTION:
              valued += 20;
              break;

          case SPARM_PONDEROUSNESS:
              valued -= 250;
              break;
   -----------------------------------------------------------------------
   Enchantment: I went with +50 for each point, but maybe +100 would be better. Again, multiplicative seems like a bad idea.
   
   Racial items: See weapons above.







Missiles:
        case MI_DART:
        case MI_STONE:
        case MI_NONE:
            valued++;
            break;
        case MI_NEEDLE:
        case MI_ARROW:
        case MI_BOLT:
            valued += 2;
            break;
        case MI_LARGE_ROCK:
            valued += 7;
            break;
        case MI_JAVELIN:
            valued += 8;
            break;
        case MI_THROWING_NET:
            valued += 30;
            break;
        default:
            valued += 5;
            break;
   -----------------------------------------------------------------------
   Egos:
            case SPMSL_NORMAL:
            default:
                valued *= 10;
                break;

            case SPMSL_CHAOS:
                valued *= 40;
                break;

            case SPMSL_CURARE:
            case SPMSL_PARALYSIS:
            case SPMSL_PENETRATION:
            case SPMSL_SILVER:
            case SPMSL_STEEL:
            case SPMSL_DISPERSAL:
                valued *= 30;
                break;

            case SPMSL_FLAME:
            case SPMSL_FROST:
            case SPMSL_SLEEP:
            case SPMSL_CONFUSION:
                valued *= 25;
                break;

            case SPMSL_EXPLODING:
            case SPMSL_POISONED:
            case SPMSL_RETURNING:
            case SPMSL_SLOW:
#if TAG_MAJOR_VERSION == 34
            case SPMSL_SICKNESS:
#endif
            case SPMSL_FRENZY:
                valued *= 20;
                break;

            valued /= 10;











Wands:
        if (!item_type_known(item))
            valued += 40;
        else
        {
            // true if the wand is of a good type, a type with significant
            // inherent value even when empty. Good wands are less expensive
            // per charge.
            bool good = false;
            switch (item.sub_type)
            {
            case WAND_HASTING:
            case WAND_HEAL_WOUNDS:
                valued += 240;
                good = true;
                break;

            case WAND_TELEPORTATION:
                valued += 120;
                good = true;
                break;

            case WAND_COLD:
            case WAND_FIRE:
            case WAND_FIREBALL:
            case WAND_DIGGING:
                valued += 80;
                good = true;
                break;

            case WAND_INVISIBILITY:
            case WAND_DRAINING:
            case WAND_LIGHTNING:
            case WAND_DISINTEGRATION:
                valued += 40;
                good = true;
                break;

            case WAND_ENSLAVEMENT:
            case WAND_POLYMORPH:
            case WAND_PARALYSIS:
                valued += 20;
                break;

            case WAND_CONFUSION:
            case WAND_SLOWING:
                valued += 15;
                break;

            case WAND_FLAME:
            case WAND_FROST:
            case WAND_RANDOM_EFFECTS:
                valued += 10;
                break;

            case WAND_MAGIC_DARTS:
            default:
                valued += 6;
                break;
            }
   -----------------------------------------------------------------------
   The main change here is that unidentified wands were way too expensive.








Potions:
        if (!item_type_known(item))
            valued += 9;
        else
        {
            switch (item.sub_type)
            {
            case POT_EXPERIENCE:
                valued += 500;
                break;

            case POT_CURE_MUTATION:
#if TAG_MAJOR_VERSION == 34
            case POT_GAIN_DEXTERITY:
            case POT_GAIN_INTELLIGENCE:
            case POT_GAIN_STRENGTH:
#endif
            case POT_BENEFICIAL_MUTATION:
                valued += 350;
                break;

            case POT_RESISTANCE:
            case POT_SPEED:
                valued += 70;
                break;

            case POT_MAGIC:
            case POT_INVISIBILITY:
                valued += 55;
                break;

            case POT_BERSERK_RAGE:
            case POT_HEAL_WOUNDS:
            case POT_RESTORE_ABILITIES:
            case POT_FLIGHT:
                valued += 30;
                break;

            case POT_MIGHT:
            case POT_AGILITY:
            case POT_BRILLIANCE:
            case POT_MUTATION:
                valued += 25;
                break;

            case POT_CURING:
            case POT_DECAY:
            case POT_DEGENERATION:
            case POT_STRONG_POISON:
            case POT_LIGNIFY:
                valued += 20;
                break;

            case POT_BLOOD:
            case POT_PORRIDGE:
            case POT_CONFUSION:
            case POT_PARALYSIS:
            case POT_POISON:
            case POT_SLOWING:
                valued += 10;
                break;

            case POT_BLOOD_COAGULATED:
                valued += 5;
                break;
            }
        }
        break;









Food:
       case FOOD_AMBROSIA:
        case FOOD_ROYAL_JELLY:
            valued = 120;
            break;

        case FOOD_MEAT_RATION:
            valued = 50;
            break;

        case FOOD_BREAD_RATION:
        default:
            valued = 44;
            break;

        case FOOD_HONEYCOMB:
            valued = 20;
            break;

        case FOOD_BEEF_JERKY:
        case FOOD_PIZZA:
        case FOOD_SNOZZCUMBER:
            valued = 15;
            break;

        case FOOD_CHEESE:
        case FOOD_SAUSAGE:
            valued = 12;
            break;

        case FOOD_LEMON:
        case FOOD_ORANGE:
        case FOOD_BANANA:
            valued = 10;
            break;

        case FOOD_APPLE:
        case FOOD_APRICOT:
        case FOOD_PEAR:
            valued = 7;
            break;

        case FOOD_CHUNK:
            if (food_is_rotten(item))
                break;

        case FOOD_CHOKO:
        case FOOD_LYCHEE:
        case FOOD_RAMBUTAN:
            valued = 6;
            break;

        case FOOD_STRAWBERRY:
            valued = 2;
            break;

        case FOOD_GRAPE:
        case FOOD_SULTANA:
            valued = 1;
            break;
   -----------------------------------------------------------------------
   Food is nutrition/100, unless it's royal jelly or ambrosia. You could
   also take into account eating time and fruit status, but it doesn't really
   seem worth it.







Scrolls:
        if (!item_type_known(item))
            valued += 10;
        else
        {
            switch (item.sub_type)
            {
            case SCR_ACQUIREMENT:
                valued += 520;
                break;

            case SCR_ENCHANT_WEAPON_III:
            case SCR_BRAND_WEAPON:
                valued += 200;
                break;

            case SCR_RECHARGING:
            case SCR_SUMMONING:
                valued += 95;
                break;

            case SCR_BLINKING:
            case SCR_ENCHANT_ARMOUR:
            case SCR_TORMENT:
            case SCR_HOLY_WORD:
            case SCR_SILENCE:
            case SCR_VULNERABILITY:
                valued += 75;
                break;

            case SCR_ENCHANT_WEAPON_II:
                valued += 55;
                break;

            case SCR_AMNESIA:
            case SCR_ENCHANT_WEAPON_I:
            case SCR_FEAR:
            case SCR_IMMOLATION:
            case SCR_MAGIC_MAPPING:
                valued += 35;
                break;

            case SCR_REMOVE_CURSE:
            case SCR_TELEPORTATION:
                valued += 30;
                break;

            case SCR_FOG:
            case SCR_IDENTIFY:
            case SCR_CURSE_ARMOUR:
            case SCR_CURSE_WEAPON:
            case SCR_CURSE_JEWELLERY:
                valued += 20;
                break;

            case SCR_NOISE:
            case SCR_RANDOM_USELESSNESS:
                valued += 10;
                break;
            }
        }







Jewellery:
       if (item_known_cursed(item))
            valued -= 30;

        if (!item_type_known(item))
            valued += 50;
        else
        {
            // Variable-strength rings.
            if (item_ident(item, ISFLAG_KNOW_PLUSES)
                && (item.sub_type == RING_PROTECTION
                    || item.sub_type == RING_STRENGTH
                    || item.sub_type == RING_EVASION
                    || item.sub_type == RING_DEXTERITY
                    || item.sub_type == RING_INTELLIGENCE
                    || item.sub_type == RING_SLAYING))
            {
                // Formula: price = kn(n+1) / 2, where k depends on the subtype,
                // n is the power. (The base variable is equal to 2n.)
                int base = 0;
                int coefficient = 0;
                if (item.sub_type == RING_SLAYING)
                    base = item.plus + 2 * item.plus2;
                else
                    base = 2 * item.plus;

                switch (item.sub_type)
                {
                case RING_SLAYING:
                    coefficient = 50;
                    break;
                case RING_PROTECTION:
                case RING_EVASION:
                    coefficient = 40;
                    break;
                case RING_STRENGTH:
                case RING_DEXTERITY:
                case RING_INTELLIGENCE:
                    coefficient = 30;
                    break;
                default:
                    break;
                }

                if (base <= 0)
                    valued += 25 * base;
                else
                    valued += (coefficient * base * (base + 1)) / 8;
            }
            else
            {
                switch (item.sub_type)
                {
                case RING_TELEPORT_CONTROL:
                    valued += 500;
                    break;

                case AMU_FAITH:
                case AMU_RESIST_MUTATION:
                case AMU_RAGE:
                    valued += 400;
                    break;

                case RING_INVISIBILITY:
                case RING_REGENERATION:
                case RING_WIZARDRY:
                case AMU_GUARDIAN_SPIRIT:
                case AMU_CONSERVATION:
                case AMU_THE_GOURMAND:
                    valued += 300;
                    break;

                case RING_FIRE:
                case RING_ICE:
                case RING_PROTECTION_FROM_COLD:
                case RING_PROTECTION_FROM_FIRE:
                case RING_PROTECTION_FROM_MAGIC:
                    valued += 250;
                    break;

                case RING_MAGICAL_POWER:
                case RING_LIFE_PROTECTION:
                case RING_POISON_RESISTANCE:
                case AMU_CLARITY:
                case AMU_RESIST_CORROSION:
                    valued += 200;
                    break;

                case RING_SUSTAIN_ABILITIES:
                case RING_SUSTENANCE:
                case RING_TELEPORTATION:
                case RING_FLIGHT:
                case AMU_STASIS:
                    valued += 175;
                    break;

                case RING_SEE_INVISIBLE:
                case AMU_WARDING:
                    valued += 150;
                    break;

                case RING_HUNGER:
                case AMU_INACCURACY:
                    valued -= 300;
                    break;
                    // got to do delusion!
                }
            }

            if (is_artefact(item))
            {
                // in this branch we're guaranteed to know
                // the item type!
                if (valued < 0)
                    valued = (artefact_value(item) - 5) * 7;
                else
                    valued += artefact_value(item) * 7;
            }

            // Hard minimum, as it's worth 20 to ID a ring.
            valued = max(20, valued);
        }
   -----------------------------------------------------------------------
   Like wands, unidentified jewellery was massively overpriced.









Miscellany:
        case MISC_RUNE_OF_ZOT:  // upped from 1200 to encourage collecting
            valued += 10000;
            break;

        case MISC_HORN_OF_GERYON:
            valued += 5000;
            break;

        case MISC_FAN_OF_GALES:
        case MISC_STONE_OF_TREMORS:
        case MISC_PHIAL_OF_FLOODS:
        case MISC_LAMP_OF_FIRE:
            valued += 400;
            break;

        case MISC_BOX_OF_BEASTS:
        case MISC_DISC_OF_STORMS:
        case MISC_SACK_OF_SPIDERS:
            valued += 200;
            break;

        default:
            if (is_deck(item))
                valued += 80 + item.special * 60;
            else
                valued += 200;
        }
   -----------------------------------------------------------------------
   All of these were stupidly overpriced.











Artefacts:
    int ret = 10;
    artefact_properties_t prop;
    artefact_wpn_properties(item, prop);

    // Brands are already accounted for via existing ego checks

    // This should probably be more complex... but this isn't so bad:
    ret += 6 * prop[ ARTP_AC ] + 6 * prop[ ARTP_EVASION ]
            + 3 * prop[ ARTP_ACCURACY ] + 6 * prop[ ARTP_DAMAGE ]
            + 3 * prop[ ARTP_STRENGTH ] + 3 * prop[ ARTP_INTELLIGENCE ]
            + 3 * prop[ ARTP_DEXTERITY ];

    // These resistances have meaningful levels
    if (prop[ ARTP_FIRE ] > 0)
        ret += 5 + 5 * (prop[ ARTP_FIRE ] * prop[ ARTP_FIRE ]);
    else if (prop[ ARTP_FIRE ] < 0)
        ret -= 10;

    if (prop[ ARTP_COLD ] > 0)
        ret += 5 + 5 * (prop[ ARTP_COLD ] * prop[ ARTP_COLD ]);
    else if (prop[ ARTP_COLD ] < 0)
        ret -= 10;

    if (prop[ ARTP_NEGATIVE_ENERGY ] > 0)
        ret += 3 + 3 * (prop[ARTP_NEGATIVE_ENERGY] * prop[ARTP_NEGATIVE_ENERGY]);

    // only one meaningful level:
    if (prop[ ARTP_POISON ])
        ret += 6;

    // only one meaningful level (hard to get):
    if (prop[ ARTP_ELECTRICITY ])
        ret += 10;

    // magic resistance is from 35-100
    if (prop[ ARTP_MAGIC ] > 0)
        ret += 5 + prop[ ARTP_MAGIC ] / 15;
    else if (prop[ ARTP_MAGIC ] < 0)
        ret -= 5;

    if (prop[ ARTP_EYESIGHT ])
        ret += 6;

    // abilities:
    if (prop[ ARTP_FLY ])
        ret += 3;

    if (prop[ ARTP_BLINK ])
        ret += 10;

    if (prop[ ARTP_BERSERK ])
        ret += 5;

    if (prop[ ARTP_INVISIBLE ])
        ret += 10;

    if (prop[ ARTP_ANGRY ])
        ret -= 3;

    if (prop[ ARTP_CAUSE_TELEPORTATION ])
        ret -= 3;

    if (prop[ ARTP_NOISES ])
        ret -= 5;

    if (prop[ ARTP_PREVENT_TELEPORTATION ])
        ret -= 8;

    if (prop[ ARTP_PREVENT_SPELLCASTING ])
        ret -= 10;

    if (prop[ ARTP_MUTAGENIC ])
        ret -= 8;

    // ranges from 1-3
    if (prop[ ARTP_METABOLISM ])
        ret -= (2 * prop[ ARTP_METABOLISM ]);

    return (ret > 0) ? ret : 0;








Other: Known cursed items should probably be -30 (price of remove curse scroll). You could add a special case for cursed distortion weapons if you want to get silly.

Some select stupid things about the current prices that I've fixed here: demon weapons were all different prices, draining and reflection were considered some of the best egos in the game, troll leather armour was the same price as crystal plate armour, strength was considered twice as good as damage slaying or AC on artefacts, orcish items were cheaper.

For this message the author duvessa has received thanks: 8
ackack, Amnesiac, and into, Bloax, johlstei, nagdon, Shard1697, Tiber

Snake Sneak

Posts: 107

Joined: Saturday, 25th February 2012, 10:49

Post Sunday, 9th February 2014, 13:03

Re: Item value

Great suggestion, I particularly support the reduction of the prices of miscellaneous items. Currently when I see a misc item shop I always realize that I'd buy here anything only after exploring all the shop-generating branches and buying all useful items in other shops.

Dis Charger

Posts: 2064

Joined: Wednesday, 9th January 2013, 19:44

Post Sunday, 9th February 2014, 13:19

Re: Item value

I absolutely agree with you. I saw a steam dragon armour for 1950 just a moment ago. And then you buy a +0 cloak of preservation for 64 gold. This shouldn't be.
User avatar

Ziggurat Zagger

Posts: 5832

Joined: Thursday, 10th February 2011, 18:30

Post Sunday, 9th February 2014, 16:05

Re: Item value

Amnesiac wrote:I absolutely agree with you. I saw a steam dragon armour for 1950 just a moment ago. And then you buy a +0 cloak of preservation for 64 gold. This shouldn't be.


But the steam dragon armour might be in fashion, and the shopkeep could be hard up for the gold and have 13 of those cloaks still in stock in the warehouse.
"Be aware that a lot of people on this forum, such as mageykun and XuaXua, have a habit of making things up." - minmay a.k.a. duvessa
Did I make a lame complaint? Check for Bingo!
Totally gracious CSDC Season 2 Division 4 Champeen!

Shoals Surfer

Posts: 329

Joined: Tuesday, 7th May 2013, 17:09

Post Sunday, 9th February 2014, 19:18

Re: Item value

I like this. I think making the elite brands substantially more expensive might be the way to go. 450 gold for a 0/0 vampiric demon weapon or lajatang seems very cheap to me. In general, I think a weapon that you're likely to use until the end of the game should be pretty expensive, on par with some of the better books (so 1000-1500). The diminishing returns of enchant weapon scrolls above +4 might give an argument for making higher +s on weapons more expensive (in some hypothetical market where you had access to an infinite supply of ?EW, which is obviously silly). Mostly it makes me think that you don't really need those diminishing returns on scrolls.

EDIT: I've looked less at the prices of other things in detail. The tiers seem basically correct; I would personally make wands of heal wounds and haste considerably more expensive, although it is unclear to me in my brief lookover how the number of charges affect the cost.
User avatar

Ziggurat Zagger

Posts: 5832

Joined: Thursday, 10th February 2011, 18:30

Post Sunday, 9th February 2014, 19:29

Re: Item value

That Crystal Plate is worthless to your Spriggan... unless he has allies, I guess.

Prices could scale relative to demand (based on your skills).
"Be aware that a lot of people on this forum, such as mageykun and XuaXua, have a habit of making things up." - minmay a.k.a. duvessa
Did I make a lame complaint? Check for Bingo!
Totally gracious CSDC Season 2 Division 4 Champeen!

Ziggurat Zagger

Posts: 8786

Joined: Sunday, 5th May 2013, 08:25

Post Sunday, 9th February 2014, 19:58

Re: Item value

ackack wrote:450 gold for a 0/0 vampiric demon weapon or lajatang seems very cheap to me.
The price in an actual shop is almost always higher, because it gets multiplied by a "greed value" (10 is 100%, and yes, level_number is what you think it is):
  Code:
    if (env.shop[i].type == SHOP_FOOD)
        env.shop[i].greed = 10 + random2(5);
    else if (env.shop[i].type != SHOP_WEAPON_ANTIQUE
             && env.shop[i].type != SHOP_ARMOUR_ANTIQUE
             && env.shop[i].type != SHOP_GENERAL_ANTIQUE)
    {
        env.shop[i].greed = 10 + random2(5) + random2(level_number / 2);
    }
    else
        env.shop[i].greed = 15 + random2avg(19, 2) + random2(level_number);

    // Allow bargains in bazaars, prices randomly between 60% and 95%.
    if (player_in_branch(BRANCH_BAZAAR))
    {
        // Need to calculate with factor as greed (uint8_t)
        // is capped at 255.
        int factor = random2(8) + 12;

        dprf("Shop type %d: original greed = %d, factor = %d, discount = %d%%.",
             env.shop[i].type, env.shop[i].greed, factor, (20-factor)*5);

        factor *= env.shop[i].greed;
        factor /= 20;
        env.shop[i].greed = factor;
    }

Tomb Titivator

Posts: 853

Joined: Thursday, 29th August 2013, 18:39

Post Monday, 10th February 2014, 01:08

Re: Item value

XuaXua wrote:That Crystal Plate is worthless to your Spriggan... unless he has allies, I guess.

Prices could scale relative to demand (based on your skills).

Price discrimination was made illegal by voice vote in the last D council meeting.
User avatar

Spider Stomper

Posts: 186

Joined: Friday, 8th March 2013, 13:27

Post Monday, 10th February 2014, 17:15

Re: Item value

Brands effect usually depends on the speed or the damage of a weapon. I'd suggest the following for pricing weapons:

Divide brands in three groups:
speed (e.g electrocution, pain, distortion)
damage (e.g flaming, freezing, vorpal)
other (e.g reaping, protection, chaos)

Then something on the spirit of this:
  Code:
if (brand_type == speed) {
price = (price_of_base_item + speed(weapon_type) * random_value(min max))
}

if (brand_type == damage) {
price = (price_of_base_item + damage(weapon_type) * random_value(min max))
}

if (brand_type == other) {
price = (price_of_base_item + random_value(min max))
}

Dungeon Master

Posts: 634

Joined: Sunday, 22nd September 2013, 14:46

Post Monday, 10th February 2014, 17:20

Re: Item value

"additive" and "multiplicative" would be more clear category names, probably.
User avatar

Tartarus Sorceror

Posts: 1891

Joined: Monday, 1st April 2013, 04:41

Location: Toronto, Canada

Post Tuesday, 11th February 2014, 01:11

Re: Item value

All else aside, the fact that draining is the highest valued weapon brand in the code as-is is absolutely bizarre and should probably be changed post-haste.
take it easy

Mines Malingerer

Posts: 47

Joined: Tuesday, 3rd December 2013, 19:12

Post Tuesday, 11th February 2014, 01:34

Re: Item value

How about also add a step function at 1k and 2k so you don't see 9k and 12k artefacts for sale?

Ziggurat Zagger

Posts: 8786

Joined: Sunday, 5th May 2013, 08:25

Post Tuesday, 11th February 2014, 01:57

Re: Item value

it already has a stepdown, which is shown in the first post

Mines Malingerer

Posts: 47

Joined: Tuesday, 3rd December 2013, 19:12

Post Tuesday, 11th February 2014, 03:29

Re: Item value

Yeah but it still produces 10k+ prices. I would say your version would be better though because it's additive...but it would be nice to soft-ceiling prices at say 2-3k. You can find some of these items just lying on the ground, putting them in a shop shouldn't place them out of the reach of anyone but a pan scummer...
User avatar

Ziggurat Zagger

Posts: 5832

Joined: Thursday, 10th February 2011, 18:30

Post Tuesday, 11th February 2014, 03:53

Re: Item value

Shop of Prior Player's Equipment
"Be aware that a lot of people on this forum, such as mageykun and XuaXua, have a habit of making things up." - minmay a.k.a. duvessa
Did I make a lame complaint? Check for Bingo!
Totally gracious CSDC Season 2 Division 4 Champeen!

Ziggurat Zagger

Posts: 8786

Joined: Sunday, 5th May 2013, 08:25

Post Tuesday, 11th February 2014, 05:16

Re: Item value

araganzar wrote:Yeah but it still produces 10k+ prices.
For a value of 10,000 to remain after that stepdown, the original value has to be 1,023,000.

Dis Charger

Posts: 2064

Joined: Wednesday, 9th January 2013, 19:44

Post Friday, 14th February 2014, 16:40

Re: Item value

Is this going in? I've just bought +0 elven boots of running for 94 gold
User avatar

Dungeon Master

Posts: 762

Joined: Thursday, 25th April 2013, 02:43

Post Friday, 14th February 2014, 18:18

Re: Item value

Amnesiac wrote:Is this going in? I've just bought +0 elven boots of running for 94 gold
Well some dev has to decide to do it, and none of them have even commented on this thread yet. Making it into a patch on mantis might help it happen, as would bringing it up on ##crawl-dev.
On IRC my nick is reaverb. I play online under the name reaver, though.

Return to Game Design Discussion

Who is online

Users browsing this forum: No registered users and 14 guests

cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.