Module:LootChest

local p = {

-- these define which sprite and label to use, in the result table -- NOTE: order in this list doesn't matter. --      * in the grid, will sort by chance, then by avg#, then alphabetically, --      * then finally by the ordinal number z in {x,y,z}

items = { ["bread"]              = { "item", "Bread", 0 }, ["apple"]              = { "item", "Apple", 0 }, ["stick"]              = { "item", "Stick", 1 }, ["wood-planks"]        = { "block", "Oak Planks", 2 }, ["oak-wood"]           = { "block", "Oak Wood", 3 }, ["acacia-wood"]        = { "block", "Acacia Wood", 4 }, ["coal"]               = { "item", "Coal", 5 }, ["paper"]              = { "item", "Paper", 5 }, ["oak-sapling"]        = { "block", "Oak Sapling", 6 }, ["flint-and-steel"]    = { "item", "Flint and Steel", 6 }, ["string"]             = { "item", "String", 6 }, ["wheat"]              = { "item", "Wheat", 6 }, ["bone"]               = { "item", "Bone", 7 }, ["rotten-flesh"]       = { "item", "Rotten Flesh", 7 }, ["stone-axe"]          = { "item", "Stone Axe", 50 }, ["wooden-axe"]         = { "item", "Wooden Axe", 51 }, ["stone-pickaxe"]      = { "item", "Stone Pickaxe", 52 }, ["wooden-pickaxe"]     = { "item", "Wooden Pickaxe", 53 }, ["iron-pickaxe"]       = { "item", "Iron Pickaxe", 54 }, ["iron-sword"]         = { "item", "Iron Sword", 55 }, ["iron-chestplate"]    = { "item", "Iron Chestplace", 56 }, ["iron-helmet"]        = { "item", "Iron Helmet", 57 }, ["iron-leggings"]      = { "item", "Iron Leggings", 58 }, ["iron-boots"]         = { "item", "Iron Boots", 59 }, ["golden-sword"]       = { "item", "Golden Sword", 60 }, ["golden-chestplate"]  = { "item", "Golden Chestplate", 61 }, ["melon-seeds"]        = { "item", "Melon Seeds", 70 }, ["pumpkin-seeds"]      = { "item", "Pumpkin Seeds", 70 }, ["nether-wart"]        = { "item", "Nether Wart", 71 }, ["gunpowder"]          = { "item", "Gunpowder", 72 }, ["bucket"]             = { "item", "Bucket", 72 }, ["rail"]               = { "block", "Rail", 72 }, ["obsidian"]           = { "block", "Obsidian", 72 }, ["ender-pearl"]        = { "item", "Ender Pearl", 80 }, ["book"]               = { "item", "Book", 80 }, ["map"]                = { "item", "Map", 81 }, ["compass"]            = { "item", "Compass", 81 }, ["iron-ingot"]         = { "item", "Iron Ingot", 90 }, ["gold-ingot"]         = { "item", "Gold Ingot", 91 }, ["redstone"]           = { "item", "Redstone", 92 }, ["lapis-lazuli"]       = { "item", "Lapis Lazuli", 93 }, ["emerald"]            = { "item", "Emerald", 94 }, ["diamond"]            = { "item", "Diamond", 95 }, ["disc-13"]            = { "item", "Record 13", 110 }, ["disc-cat"]           = { "item", "Record Cat", 110 }, ["saddle"]             = { "item", "Saddle", 120 }, ["name-tag"]           = { "item", "Nametag", 120 }, ["horse-armor-iron"]   = { "item", "Iron Horse Armor", 130 }, ["horse-armor-gold"]   = { "item", "Gold Horse Armor", 131 }, ["horse-armor-diamond"] = { "item", "Diamond Horse Armor", 132 }, ["golden-apple"]       = { "item", "Golden Apple", 140 }, ["enchanted-book"]     = { "item", "Enchanted Book", 141 } },	-- accurate as of 1.8 -- NOTE: order here doesn't matter. --		 * chests will sort by argument order, unless 'all', then this order. --      * items will sort by chance, then by avg#, then alphabetically. -- NOTE: any invalid item-id here will print as ??? chests = { ["village"] = { numstacks  = {3,8}, totalweight = nil, header     = "Village", items = { ["diamond"]            = {1,3,3}, ["iron-ingot"]         = {1,5,10}, ["gold-ingot"]         = {1,3,5}, ["bread"]              = {1,3,15}, ["apple"]              = {1,3,15}, ["iron-pickaxe"]       = {1,1,5}, ["iron-sword"]         = {1,1,5}, ["iron-chestplate"]    = {1,1,5}, ["iron-helmet"]        = {1,1,5}, ["iron-leggings"]      = {1,1,5}, ["iron-boots"]         = {1,1,5}, ["obsidian"]           = {3,7,5}, ["oak-sapling"]        = {3,7,5}, ["horse-armor-iron"]   = {1,1,1}, ["horse-armor-gold"]   = {1,1,1}, ["horse-armor-diamond"] = {1,1,1}, ["saddle"]             = {1,1,3} }		},		["stronghold-altar"] = { numstacks  = {2,4}, totalweight = nil, header     = "Altar", superheader = "Stronghold", items      = { ["diamond"]            = {1,3,3}, ["iron-ingot"]         = {1,5,10}, ["gold-ingot"]         = {1,3,5}, ["bread"]              = {1,3,5}, ["apple"]              = {1,3,15}, ["iron-pickaxe"]       = {1,1,5}, ["iron-sword"]         = {1,1,5}, ["iron-chestplate"]    = {1,1,5}, ["iron-helmet"]        = {1,1,5}, ["iron-leggings"]      = {1,1,5}, ["iron-boots"]         = {1,1,5}, ["horse-armor-iron"]   = {1,1,1}, ["horse-armor-gold"]   = {1,1,1}, ["horse-armor-diamond"] = {1,1,1}, ["ender-pearl"]        = {1,1,10}, ["redstone"]           = {4,9,5}, ["golden-apple"]       = {1,1,1}, ["saddle"]             = {1,1,1}, ["enchanted-book"]     = {1,1,1} }		},		["stronghold-library"] = { numstacks  = {1,4}, totalweight = nil, header     = "Library", superheader = "Stronghold", items      = { ["enchanted-book"]     = {1,5,2}, ["book"]               = {1,3,20}, ["paper"]              = {2,7,20}, ["map"]                = {1,1,1}, ["compass"]            = {1,1,1} }		},		["stronghold-storeroom"] = { numstacks  = {1,4}, totalweight = nil, header     = "Storeroom", superheader = "Stronghold", items      = { ["iron-ingot"]         = {1,5,10}, ["gold-ingot"]         = {1,3,5}, ["bread"]              = {1,3,5}, ["apple"]              = {1,3,5}, ["iron-pickaxe"]       = {1,1,1}, ["redstone"]           = {4,9,5}, ["enchanted-book"]     = {1,1,1}, ["coal"]               = {3,8,10} }		},		["bonus"] = { numstacks  = {10,10}, totalweight = nil, header     = "Bonus", items      = { ["bread"]              = {2,3,3}, ["apple"]              = {2,3,5}, ["stick"]              = {1,3,10}, ["wood-planks"]        = {1,3,10}, ["oak-wood"]           = {1,3,10}, ["acacia-wood"]        = {1,3,10}, ["stone-axe"]          = {1,1,3}, ["wooden-axe"]         = {1,1,5}, ["stone-pickaxe"]      = {1,1,3}, ["wooden-pickaxe"]     = {1,1,5} }		},		["dungeon"] = { numstacks  = {8,8}, totalweight = nil, header     = "Dungeon", items      = { ["iron-ingot"]         = {1,4,10}, ["bread"]              = {1,4,10}, ["horse-armor-iron"]   = {1,1,5}, ["horse-armor-gold"]   = {1,1,2}, ["horse-armor-diamond"] = {1,1,1}, ["redstone"]           = {1,4,10}, ["golden-apple"]       = {1,1,1}, ["saddle"]             = {1,1,10}, ["wheat"]              = {1,4,10}, ["gunpowder"]          = {1,4,10}, ["string"]             = {1,4,10}, ["bucket"]             = {1,1,10}, ["disc-13"]            = {1,1,4}, ["disc-cat"]           = {1,1,4}, ["name-tag"]           = {1,1,10} }		},		["mineshaft"] = { numstacks  = {3,6}, totalweight = nil, header     = "Mineshaft", items      = { ["diamond"]            = {1,2,3}, ["iron-ingot"]         = {1,5,10}, ["gold-ingot"]         = {1,3,5}, ["bread"]              = {1,3,15}, ["iron-pickaxe"]       = {1,1,1}, ["horse-armor-iron"]   = {1,1,1}, ["redstone"]           = {4,9,5}, ["lapis-lazuli"]       = {4,9,5}, ["saddle"]             = {1,1,3}, ["enchanted-book"]     = {1,1,1}, ["coal"]               = {3,8,10}, ["rail"]               = {4,8,1}, ["melon-seeds"]        = {2,4,10}, ["pumpkin-seeds"]      = {2,4,10} }		},		["nether-fortress"] = { numstacks  = {2,5}, totalweight = nil, header     = "Nether fortress", items      = { ["diamond"]            = {1,3,5}, ["iron-ingot"]         = {1,5,5}, ["gold-ingot"]         = {1,3,15}, ["obsidian"]           = {2,4,2}, ["horse-armor-iron"]   = {1,1,5}, ["horse-armor-gold"]   = {1,1,8}, ["horse-armor-diamond"] = {1,1,3}, ["saddle"]             = {1,1,10}, ["golden-sword"]       = {1,1,5}, ["golden-chestplate"]  = {1,1,5}, ["flint-and-steel"]    = {1,1,5}, ["nether-wart"]        = {5,7,5} }		},		["desert-jungle-temple"] = { numstacks  = {2,6}, totalweight = nil, header     = "Desert temple & jungle temple", items      = { ["diamond"]            = {1,3,3}, ["iron-ingot"]         = {1,5,10}, ["gold-ingot"]         = {2,7,15}, ["emerald"]            = {1,3,2}, ["horse-armor-iron"]   = {1,1,1}, ["horse-armor-gold"]   = {1,1,1}, ["horse-armor-diamond"] = {1,1,1}, ["saddle"]             = {1,1,3}, ["enchanted-book"]     = {1,1,1}, ["bone"]               = {4,6,20}, ["rotten-flesh"]       = {3,7,16} }		}	} }

local q = {}

function q.massageArgs( chests )

if #chests == 0 then chests = {"all"} end -- if argument 'all' exists, repopulate 'chests' arguments with all chests

isall = false for k, _arg in pairs(chests) do		if _arg == "all" then chests = {} isall = true for chest_name, chest in pairs(p.chests) do				table.insert( chests, chest_name ) end break end end -- otherwise, remove invalid chest arguments

if not isall then for idx = #chests, 1, -1 do			if p.chests[chests[idx]] == nil then table.remove( chests, idx ) end end end

return chests end

function q.findChestTotalWeights( chests )

for k, chestname in pairs(chests) do		local chest = p.chests[chestname] if chest == nil then break end local total_weight = 0 for itemname, item in pairs(chest.items) do			total_weight = total_weight + item[3] end chest.totalweight = total_weight end

end

function q.findChestItemDetails( chests )

for key, chestname in pairs(chests) do		local chest = p.chests[chestname] if chest == nil then break end local avg_numstacks = ( chest.numstacks[1] + chest.numstacks[2] ) / 2 for itemname, item in pairs(chest.items) do			local avg_stacksize = ( item[1] + item[2] ) / 2 local item_weight = item[3] p.chests[chestname].items[itemname].avgamount = avg_numstacks * avg_stacksize * item_weight / chest.totalweight p.chests[chestname].items[itemname].chanceany = avg_numstacks * item_weight / chest.totalweight p.chests[chestname].items[itemname].itemname = itemname -- for sorting later end end end

function q.constructFirstChestOrdered( chests )

local items_from_first_table = {} local item_chests = {} local item_names_ordered = {} for item_name, item in pairs( p.chests[chests[1]].items ) do		table.insert( items_from_first_table, item ) end table.sort( items_from_first_table, function( e1, e2 )		if not ( e1.chanceany == e2.chanceany ) then return ( e1.chanceany > e2.chanceany ) end		if not ( e1.avgamount == e2.avgamount ) then return ( e1.avgamount > e2.avgamount ) end		return ( e1.itemname < e2.itemname )	end ) for k, item in pairs( items_from_first_table ) do		table.insert( item_names_ordered, item.itemname ) item_chests[item.itemname] = true end return item_names_ordered, item_chests

end

function q.itemsFromOtherChestInOrder( item_chests )

local items_not_from_first_table = {} for item_name, item in pairs( p.items ) do		if item_chests[item_name] == nil then p.items[item_name].itemname = item_name table.insert( items_not_from_first_table, p.items[item_name] ) end end table.sort( items_not_from_first_table, function( e1, e2 )		return ( e1[3] < e2[3] )	end ) return items_not_from_first_table end

function q.addItemsFromOtherChestsToOrderedList( chests, item_names_ordered, item_chests, items_not_from_first_table )

for k, item in pairs( items_not_from_first_table ) do		for idx = 2, #chests do			if not ( p.chests[chests[idx]].items[item.itemname] == nil ) and ( item_chests[item.itemname] == nil ) then table.insert( item_names_ordered, item.itemname ) item_chests[item.itemname] = true break end end end return item_names_ordered end

function q.setUpItemRowDetails( chests, item_names_ordered )

for k, itemname in pairs(item_names_ordered) do		item_names_ordered[k] = {} for idx = 1, #chests do			local item_data = p.chests[chests[idx]].items[itemname] if item_data == nil then table.insert( item_names_ordered[k], false ) else table.insert( item_data, itemname ) table.insert( item_data, p.items[itemname][1] ) table.insert( item_data, p.items[itemname][2] ) table.insert( item_names_ordered[k], item_data ) end end end

return item_names_ordered end

function q.constructItemRowsOrdered( chests )

-- for the first chest, sort its by chance desc, then by avg amount desc, then alphabetically asc local item_names_ordered, item_chests = q.constructFirstChestOrdered( chests ) if #chests > 1 then -- after that, sort all the remaining items in list order local items_not_from_first_table = q.itemsFromOtherChestInOrder( item_chests ) item_names_ordered = q.addItemsFromOtherChestsToOrderedList( chests, item_names_ordered, item_chests, items_not_from_first_table ) end

-- set up item_names_ordered so that each is a row, representing chest values item_names_ordered = q.setUpItemRowDetails( chests, item_names_ordered ) return item_names_ordered end

function q.debugPrint( item_names_ordered )

local returnable = "[" for i = 1, #item_names_ordered do		if type( item_names_ordered[i] ) == "table" then returnable = returnable .. " ["			for j = 1, #item_names_ordered[i] do				if type( item_names_ordered[i][j] ) == "table" then returnable = returnable .. "\n   [" .. table.concat(item_names_ordered[i][j],",") .. "]"				elseif type( item_names_ordered[i][j] ) == "boolean" then returnable = returnable .. "\n   " .. tostring(item_names_ordered[i][j]) else returnable = returnable .. "\n   " .. item_names_ordered[i][j] end end returnable = returnable .. "\n ]" else returnable = returnable .. "\n " .. item_names_ordered[i] end end returnable = returnable .. "\n]"

return returnable end

function q.tablePrint( item_names_ordered )

-- do some printing

-- local returnable = " " -- return returnable -- TODO: -- column headers -- make item rows that are sorted appropriately to the first chest, with the remaining items sorted alphabetically

return q.debugPrint( item_names_ordered )

end

function p.base( ... ) local args = arg[1] if args == mw.getCurrentFrame then args = require( 'Module:ProcessArgs' ).merge( true ) else args = arg end -- transform args into usable list local chests = q.massageArgs( args ) if #chests == 0 then return "no valid arguments" end

q.findChestTotalWeights( chests ) q.findChestItemDetails( chests ) -- construct an ordered list dictating the order of the rows local item_names_ordered = q.constructItemRowsOrdered( chests ) -- return q.debugPrint( item_names_ordered ) return q.tablePrint( item_names_ordered )

end

function p.doc

local keys = {} for key, val in pairs(p.chests) do		table.insert( keys, key ) end table.insert( keys, "all" ) table.sort(keys) return table.concat( keys, ", " )

end

return p