EDIT: DOH, I made a variable mistake

Ignore this. I've updated the code to the complete 100% working (including preferred improvement types and counting # of improvements over 1), incase anyone else needs a value calculator

Time to start working on the other item types. Yay.
I've been working on calculating out trader item values (to make improvements to how tradeassist works). So far, I've gotten pretty close (for weapons, that is

). Some items that are improved have the correct value (#3). Others are way off (#4). I am wondering if any dfhack veterans have any suggestions.

[DFHack]# ltradeassist set
In trading viewscreen.
Weapon: ITEM_WEAPON_PICK_BATTLE
Size Multi: 13 Quality Multi: 2 Edged Multi: 2 Material Multi: 5
Quality Multi: 2
Base Value: 260 + Added Value: 20 = 280
Weapon: ITEM_WEAPON_AXE_WOOD
Size Multi: 9 Quality Multi: 2 Edged Multi: 2 Material Multi: 24
Base Value: 864 + Added Value: 0 = 864
Weapon: ITEM_WEAPON_AXE_WOOD
Size Multi: 9 Quality Multi: 3 Edged Multi: 2 Material Multi: 24
Quality Multi: 3
Base Value: 1296 + Added Value: 30 = 1326
Weapon: ITEM_WEAPON_WHIP_THROWING
Size Multi: 3 Quality Multi: 1 Edged Multi: 2 Material Multi: 5
Quality Multi: 1
Quality Multi: 1
Quality Multi: 1
Base Value: 30 + Added Value: 340 = 370
Weapon: ITEM_WEAPON_DAGGER_LARGE
Size Multi: 5 Quality Multi: 1 Edged Multi: 2 Material Multi: 10
Quality Multi: 1
Base Value: 100 + Added Value: 30 = 130
Weapon: ITEM_WEAPON_PICK
Size Multi: 9 Quality Multi: 1 Edged Multi: 2 Material Multi: 10
Base Value: 180 + Added Value: 0 = 180
I have absolutely no idea why ITEM_WEAPON_WHIP_THROWING is so off. It's size is 100 in the raws (a 3 multi), and the material multi is the same as the raws. The calculation is correct for other items (or close enough that I can count the remainder as "trader variation").
[INORGANIC:BISMUTH_BRONZE]
[USE_MATERIAL_TEMPLATE:METAL_TEMPLATE]
[STATE_NAME_ADJ:ALL_SOLID:bismuth bronze]
[STATE_NAME_ADJ:LIQUID:molten bismuth bronze]
[STATE_NAME_ADJ:GAS:boiling bismuth bronze]
[DISPLAY_COLOR:6:6:1] [BUILD_COLOR:6:6:1]
[MATERIAL_VALUE:5]
[SPEC_HEAT:435]
[MELTING_POINT:11868]
[BOILING_POINT:14140]
[ITEMS_WEAPON][ITEMS_WEAPON_RANGED][ITEMS_AMMO][ITEMS_DIGGER][ITEMS_ARMOR]
[SOLID_DENSITY:8250] used bronze
[LIQUID_DENSITY:8020]
[MOLAR_MASS:80000]
[IMPACT_YIELD:602000]
[IMPACT_FRACTURE:843500]
[IMPACT_STRAIN_AT_YIELD:547]
[COMPRESSIVE_YIELD:602000]
[COMPRESSIVE_FRACTURE:843500]
[COMPRESSIVE_STRAIN_AT_YIELD:547] no data, used 110
[TENSILE_YIELD:172000]
[TENSILE_FRACTURE:241000]
[TENSILE_STRAIN_AT_YIELD:156] 110
[TORSION_YIELD:172000]
[TORSION_FRACTURE:241000]
[TORSION_STRAIN_AT_YIELD:156]
[SHEAR_YIELD:172000]
[SHEAR_FRACTURE:241000]
[SHEAR_STRAIN_AT_YIELD:156] no data, used 110
[BENDING_YIELD:172000]
[BENDING_FRACTURE:241000]
[BENDING_STRAIN_AT_YIELD:156]
[MAX_EDGE:10000]
[ITEMS_HARD]
[ITEMS_METAL]
[ITEMS_BARRED]
[ITEMS_SCALED]
[REACTION_CLASS:BRONZE_COATING]
[ITEM_WEAPON:ITEM_WEAPON_WHIP_THROWING]
[NAME:bola thrower:bola throwers]
[SIZE:100]
[SKILL:WHIP]
[RANGED:THROW:WHIP]
[SHOOT_FORCE:2400]
[SHOOT_MAXVEL:1350]
[TWO_HANDED:27500]
[MINIMUM_SIZE:22500]
[MATERIAL_SIZE:3]
[ATTACK:EDGE:20:12000:whip:whips:NO_SUB:1000]
[ATTACK:EDGE:20:12000:cut:cuts:wire:3000]
[ATTACK:EDGE:20:12000:entangle:entangles:long wire:3000]
The code, for anyone interested:
function debug_item_value(item)
local base_value = -1
local added_value = -1
if (iof(df.item_weaponst, item)) then
print("Weapon: "..item.subtype.id)
base_value = GetBaseValue_Weapon(item)
added_value = GetAddedValue(item)
print("Base Value: " .. base_value .. " + Added Value: " .. added_value .. " = " .. (base_value + added_value))
end
end
QUALITY_MAP = { -- http://dwarffortresswiki.org/index.php/DF2012:Item_value#Quality
[0] = 1, -- Ordinary 1x
[1] = 2, -- Well-crafted 2x
[2] = 3, -- Finely-crafted 3x
[3] = 4, -- Superior quality 4x
[4] = 5, -- Exceptional 5x
[6] = 12, -- Masterful 12x
[7] = 120 -- Artifact 120x
}
function GetMaterialValue(item, p)
if p == nil then p = false end
--material = dfhack.matinfo.decode(type,index)
--material multi = multiply_value * material_value
local material = dfhack.matinfo.decode(item)
local currency_value = entity_cv[item.mat_index]
if currency_value == nil then currency_value = 0 end
-- print("Possible currency value? " .. item.mat_index .. " = " .. currency_value)
if p then printall(material) end
if material.mode == "inorganic" then
local inorganic = material.inorganic
if p then printall(inorganic) end
local multiply_value,material_value
multiply_value = read_raw_integer(inorganic.str, "%[MULTIPLY_VALUE:(%d+)%]", 1)
material_value = read_raw_integer(inorganic.str, "%[MATERIAL_VALUE:(%d+)%]", 1)
material_multi = material_value * multiply_value
else
print("NOT AN INORGANIC MATERIAL")
printall(material)
end
return material_multi,currency_value
end
function GetBaseValue_Weapon(item)
local found
--size_multi = (size / 5) + 1 -- size is already /10 from raw.
local size_multi = (item.subtype.size / 5) + 1
local material_multi,currency_value = GetMaterialValue(item)
--edged multi = item.subtype.attacks[x]["edged"] = true then 2 else 1
local edged_multi = 1
found = false
for ik, iv in pairs(item.subtype.attacks) do
if iv.edged then
found = true
break
end
end
if found then edged_multi = 2 end
--quality multi = use map
local quality_multi = QUALITY_MAP[item.quality]
print("Size Multi: "..size_multi.." Quality Multi: "..quality_multi.." Edged Multi: "..edged_multi.." Material Multi: "..material_multi)
local total_value = size_multi * quality_multi * edged_multi * material_multi
return total_value-- + currency_value
end
function GetAddedValue(item)
-- General added value is encrusted items.
local total_value = 0
for ik, iv in pairs(item.improvements) do
-- We should be calling itemimprovement.getType(iv) since it is static.
-- However, lua is awesome.
-- We will call iv.getType(iv)
local imptype = iv.getType(iv)
local defmod = 256
-- Use the type to get the actual modifier
local actmod = entity.entity_raw.habitat.item_improvement_modifier[imptype]
if actmod == nil then actmod = 256 end
-- Calculate actmod / defmod as a number
local type_multi = actmod / defmod
local mat_value,currency_value = GetMaterialValue(iv)
local quality_multi = QUALITY_MAP[iv.quality]
print("Quality Multi: " .. quality_multi)
-- All decorations are a base of 10.
local item_value = (mat_value * 10 * quality_multi * type_multi)-- + currency_value
if item_value ~= nil then total_value = total_value + item_value end
end
local numImprovements = #item.improvements - 1
if numImprovements < 0 then numImprovements = 0 end
total_value = total_value + (10 * numImprovements)
return total_value
end
function read_raw_integer(vector, regex, default)
local val,lstr,found,num
found,lstr = find_string(vector, regex)
if found then
num = tonumber(lstr)
end
if num == nil then num = default end
return num
end
function find_string(vector, str)
for ik, iv in pairs(vector) do
local match = string.match(iv.value, str)
if match ~= nil then
--print(str .. " " .. match)
return true,match
end
end
return false,nil
end