Ok ... I checked with one logical table table. Just connect (merge) everything you want to include. (the question is tagged php, so this is a php solution ....)
<?php $weapons = array( array('name'=>'knife', 'type'=>'A', 'weight'=>5), array('name'=>'sword', 'type'=>'A', 'weight'=>6), array('name'=>'axe', 'type'=>'A', 'weight'=>3), array('name'=>'handgun', 'type'=>'B', 'weight'=>7), array('name'=>'rifle', 'type'=>'B', 'weight'=>5), array('name'=>'cannon', 'type'=>'B', 'weight'=>2), array('name'=>'mustard gas', 'type'=>'C', 'weight'=>7), array('name'=>'agent orange', 'type'=>'C', 'weight'=>10), array('name'=>'lewisite', 'type'=>'C', 'weight'=>5), array('name'=>'mind', 'type'=>'D', 'weight'=>8), // must have at least one thing with one... for this to work. // i can definitely work on a solution that doesn't require this // but it would take me a minute to think about it... array('name'=>'words', 'type'=>'D', 'weight'=>1), array('name'=>'hands', 'type'=>'D', 'weight'=>2), array('name'=>'silent treatment','type'=>'D', 'weight'=>5), ); $total_destroyed = 100; $return = get_weapons($weapons, $weapons, $total_destroyed); print_r($return); function get_weapons($orig_weapons, $in_weapons, $n) { // filter for only weapons w/ weight less than $n $in_weapons = array_filter($in_weapons, array(new LowerThanFilter($n), 'isLowerOrEq')); $return = array(); if ($n > 0) { if (empty($in_weapons)) { $return = get_weapons($orig_weapons, $orig_weapons, $n); } else { $found_it = array(); for ($i = 0; $i < count($in_weapons); $i++) { $rand_index = array_rand($in_weapons); $rand_weapon = $in_weapons[$rand_index]; if ($rand_weapon['weight'] <= $n) { break; } } $max_ct = floor($n/$rand_weapon['weight']); $weapon_ct = rand(1,$max_ct); $amount = $weapon_ct * $rand_weapon['weight']; unset($in_weapons[$rand_index]); $get_more = get_weapons($orig_weapons, $in_weapons, $n-$amount); $return = $get_more; $return[] = array_merge($rand_weapon, array( 'count' =>$count, 'amount'=>$amount)); } } return $return; } class LowerThanFilter { // http://stackoverflow.com/a/5483168/623952 private $num; function __construct($num) { $this->num = $num; } function isLowerOrEq($i) { return $i['weight'] <= $this->num; } } ?>
which can be easily reinstalled. the index value refers to the source index of the $weapons array.
Array ( [0] => Array ( [name] => words [type] => D [weight] => 1 [count] => 1 [amount] => 1 ) [1] => Array ( [name] => knife [type] => A [weight] => 5 [count] => 2 [amount] => 10 ) [2] => Array ( [name] => sword [type] => A [weight] => 6 [count] => 1 [amount] => 6 ) [3] => Array ( [name] => agent orange [type] => C [weight] => 10 [count] => 2 [amount] => 20 ) [4] => Array ( [name] => mustard gas [type] => C [weight] => 7 [count] => 9 [amount] => 63 ) )