function get_tradables()
{
    global $inventory;
    if (!isset($inventory)) {
        load_inventory();
    }
    $sortorder = get_module_pref('shuffle');
    //	debug($sortorder);
    $tradables = array();
    $found = false;
    $itemsheld = group_items($inventory);
    foreach ($itemsheld as $key => $itemdetails) {
        if (isset($itemdetails['tradable'])) {
            $tradables[] = $itemdetails;
            $found = true;
        }
    }
    if ($found) {
        switch ($sortorder) {
            case 0:
                usort($tradables, 'itemcompare');
                break;
            case 1:
                usort($tradables, 'qtyitemcompare');
                break;
        }
        return $tradables;
    } else {
        return false;
    }
}
function mementos_feelgood_dohook($hookname, $args)
{
    global $session;
    switch ($hookname) {
        case "mementos":
            if (count($args)) {
                require_once "modules/mementos_feelgood/attributes.php";
                $attributes = mementos_feelgood_getattributes();
                foreach ($args as $item => $prefs) {
                    if (isset($prefs['memento_feelgood_attribute'])) {
                        $args[$item]['memento_forge_actions'][] = stripslashes(appoencode("Attribute \"`5" . $attributes[$prefs['memento_feelgood_attribute']]['name'] . "`0\" set<br />", true));
                    } else {
                        $args[$item]['memento_forge_actions'][] = "<a href='runmodule.php?module=mementos_feelgood&op=choosestat&mould=" . $item . "'>Apply an Attribute to this Memento</a><br />";
                        addnav("", "runmodule.php?module=mementos_feelgood&op=choosestat&mould=" . $item);
                    }
                }
            }
            break;
        case "bioinfo":
            //get all items the player carries with the 'memento_feelgood_attribute' flag set
            $inv = load_inventory($args['acctid'], true);
            $stats = array();
            foreach ($inv as $id => $prefs) {
                //debug($prefs);
                if ($prefs['memento_author'] != $args['acctid'] && isset($prefs['memento_feelgood_attribute'])) {
                    $stats[$prefs['memento_feelgood_attribute']] += 1;
                }
            }
            //debug($stats);
            if (count($stats)) {
                require_once "modules/mementos_feelgood/attributes.php";
                $attributes = mementos_feelgood_getattributes();
                output("`bAwesome Things About This Player`b`n");
                foreach ($stats as $key => $points) {
                    if ($points > 1) {
                        $plural = "Points";
                    } else {
                        $plural = "Point";
                    }
                    output("`b%s`b %s in `b%s`b`n%s`n`n", $points, $plural, $attributes[$key]['name'], $attributes[$key]['description']);
                }
            }
            break;
    }
    return $args;
}
function giftstation_dohook($hookname, $args)
{
    global $session;
    switch ($hookname) {
        case "gardens":
            addnav("Gifting Station", "runmodule.php?module=giftstation&op=start");
            break;
        case "newday":
            $gifts = load_inventory("giftstation_" . $session['user']['acctid'], true);
            if (count($gifts) > 0) {
                debug($gifts);
                foreach ($gifts as $boxid => $prefs) {
                    change_item_owner($boxid, $session['user']['acctid']);
                }
                output("`5`b`nThere's a present here!`b  How awesome!  You pick it up and put it in your Backpack.`0`n`n");
            }
            break;
    }
    return $args;
}
$items_useitem = httpget("items_useitem");
$items_discarditem = httpget("items_discarditem");
$items_transferitem = httpget("items_transferitem");
$items_transferto = httpget("items_transferto");
$context = httpget("items_context");
//handle moving, using, discarding, and contexts
if ($items_transferitem && $items_transferto) {
    move_item($items_transferitem, $items_transferto);
}
if ($items_useitem) {
    use_item($items_useitem, $context);
}
if ($items_discarditem) {
    delete_item($items_discarditem);
}
load_inventory();
//debug($inventory);
$hook = array('inventory' => $inventory, 'context' => $context);
$hook = modulehook("inventory-predisplay", $hook);
addnav("Sort by...");
addnav("Recently Acquired", "inventory.php?items_sort=key&items_context={$context}");
addnav("Alphabetical", "inventory.php?items_sort=alpha&items_context={$context}");
addnav("Quantity", "inventory.php?items_sort=qty&items_context={$context}");
$sort = httpget("items_sort");
$gr = group_items($inventory, $sort);
//debug($gr);
// switch ($sort){
// case "key":
// arsort($gr);
// usort($gr, 'sortcarriers');
// break;
function mementos_run()
{
    global $session;
    page_header("Memento Forge");
    $op = httpget('op');
    $pointsavailable = $session['user']['donation'] - $session['user']['donationspent'];
    require_once "modules/wcgpoints.php";
    $cstones = wcgpoints_getpoints();
    switch (httpget('op')) {
        case "start":
            $moulds = load_inventory("mementomoulds_" . $session['user']['acctid'], true);
            if (count($moulds)) {
                output("Here are the original prototypes of Mementos you have made.`n`n");
                rawoutput("<table width=100% style='border: dotted 1px #000000;'>");
                $classcount = 1;
                $moulds = modulehook("mementos", $moulds);
                foreach ($moulds as $id => $prefs) {
                    $classcount++;
                    $class = $classcount % 2 ? "trdark" : "trlight";
                    rawoutput("<tr class='{$class}'><td>");
                    output("`b%s`b`0`n", stripslashes($prefs['verbosename']));
                    output("%s`0`n`n", stripslashes($prefs['description']));
                    output("`bUse Text`b:%s`0`n`n", stripslashes($prefs['usetext']));
                    if ($prefs['mouldusesleft']) {
                        output("You can make another %s of these, at `6`b250`b CobbleStones`0 and `5`b1`b Supporter Point`0 each.`n", $prefs['mouldusesleft']);
                        rawoutput("<a href='runmodule.php?module=mementos&op=makecopy&itemid=" . $id . "'>Make a copy</a><br />");
                    } else {
                        if (!isset($prefs['mouldusesleft'])) {
                            output("You can make a mould for this Memento, enabling you to make copies using `6CobbleStones`0.  It'll cost you `5500 Supporter Points`0.`n");
                            rawoutput("<a href='runmodule.php?module=mementos&op=makecopy&itemid=" . $id . "'>Make a mould</a><br />");
                        } else {
                            output("This mould is too old and knackered to make any more Mementos, but you can re-forge it for `5500 Supporter Points`0.`n");
                            rawoutput("<a href='runmodule.php?module=mementos&op=makecopy&itemid=" . $id . "'>Make a mould</a><br />");
                        }
                    }
                    addnav("", "runmodule.php?module=mementos&op=makecopy&itemid=" . $id);
                    if (is_array($prefs['memento_forge_actions']) && count($prefs['memento_forge_actions'])) {
                        foreach ($prefs['memento_forge_actions'] as $action) {
                            rawoutput($action);
                        }
                    }
                    rawoutput("</td></tr>");
                }
                rawoutput("</table>");
            } else {
                //if there are no moulds
                output("You're about to ask the grinning Joker proprietor about these Memento things you've been hearing about, when suddenly the knowledge rushes into your head unbidden.`n`nMementos are player-created objects that can be given to other players.  They grant no in-game advantages, but are fun for roleplaying.  Players often roleplay giving items to each other, but with Mementos, those items can appear in Inventories and act like 'real' in-game items.`n`n`n`bWhat you need to know about Mementos`b`nMementos are weightless, and occupy the 'Shoebox' portion of the player's Inventory.  Mementos survive Drive Kills, and don't go away when 'used.'  They can only be destroyed by being discarded by the player.  They can also be put down and picked up on map squares, and gifted to other players for free (anonymously if desired) via Common Ground's Gifting Station.`n`nYou can specify the Name (shown in the Inventory) of the Memento, the Plural form of the name, the Description (shown in the Inventory), and the Use Text (shown when the player 'uses' the Memento).`n`n`n`bCosts`b`nYou can create a single Memento at a flat cost of `550 Supporter Points`0.  You can also create Memento Moulds, at a cost of `5500 Supporter Points`0 for the mould and the first Memento, plus `5one Supporter Point`0 and `6250 CobbleStones`0 for each of up to fifty copies of that Memento.  Single Mementos can be upgraded to Memento Moulds later on if you like.`n`n`n`bExample Memento`b`n`bName:`b Red Music Box`n`bPlural:`b Red Music Boxes`n`bDescription:`b An ornate red wooden music box, decorated with cut garnets and shiny stainless-steel edging.`n`bUse Text`b: You open up the music box.  Inside is a tiny demon, smoking a cigarette.  Noticing that his house is open, he hurriedly stamps out his smoke and launches into a stirring rendition of 'NewHome is Full of Noobs.'  You close the lid quickly.`n`nEach Memento can have 100 characters for the Name, 100 characters for the Plural name, 255 characters for the Description, and 1,000 characters for the Use Text.`n`n");
            }
            addnav("Memento Stuff");
            if ($pointsavailable >= 50) {
                addnav("Create new single Memento", "runmodule.php?module=mementos&op=new&type=single");
            } else {
                addnav("You need 50 Supporter Points for a single Memento", "");
            }
            if ($pointsavailable >= 500) {
                addnav("Create new Memento Mould", "runmodule.php?module=mementos&op=new&type=mould");
            } else {
                addnav("You need 500 Supporter Points for a Memento Mould", "");
            }
            break;
        case "makecopy":
            $giveitem = false;
            $itemid = httpget("itemid");
            $name = get_item_pref("verbosename", $itemid);
            $plural = get_item_pref("plural", $itemid);
            $desc = get_item_pref("description", $itemid);
            $usetext = get_item_pref("usetext", $itemid);
            $moulduses = get_item_pref("mouldusesleft", $itemid);
            if ($moulduses > 0) {
                if ($cstones >= $cscost) {
                    output("You've bought a new %s`0 using `6CobbleStones`0!  Would you like to buy another, or head back to the Memento Forge menu?`n`n", $name);
                    $giveitem = true;
                    increment_module_pref("spent", 250, "wcgpoints");
                    $cstones = wcgpoints_getpoints();
                    $session['user']['donationspent'] += 1;
                    //log purchase
                    $logsql = "INSERT INTO " . db_prefix("purchaselog") . " (acctid,purchased,amount,data,giftwrap,timestamp) VALUES ('" . $session['user']['acctid'] . "','memento_copy_cobblestone','1','none','0','" . date("Y-m-d H:i:s") . "')";
                    db_query($logsql);
                } else {
                    output("`4You don't have enough `6CobbleStones`0 to make another copy of that Memento, I'm afraid.`n`n");
                }
            }
            $pointsavailable = $session['user']['donation'] - $session['user']['donationspent'];
            if ($giveitem) {
                $prefs = get_item_prefs($itemid);
                unset($prefs["mouldusesleft"]);
                $prefs['memento_originalitem'] = $itemid;
                give_item("memento", $prefs);
                $moulduses--;
                set_item_pref("mouldusesleft", $moulduses, $itemid);
            }
            if ($moulduses > 0) {
                output("You're about a make a new copy of the Memento called `b%s`b`0.  This will cost `6250 CobbleStones`0 and `5one Supporter Point`0.  You now have `5%s Supporter Points`0 and `6%s CobbleStones`0, and this mould will make `b%s`0 more Mementos.`n`n", $name, number_format($pointsavailable), number_format($cstones), $moulduses);
                addnav("Buy");
                if ($cstones >= $cscost && $pointsavailable) {
                    addnav("Buy a copy", "runmodule.php?module=mementos&op=makecopy&itemid=" . $itemid);
                } else {
                    addnav("Not enough `6CobbleStones`0 (or you don't have a `5Supporter Point`0 left)", "");
                }
            } else {
                output("Either this mould is knackered, or this is a unique Memento.  You can't make any more copies.  However, you can make a new mould if you like, for `5500 Supporter Points`0.  This will enable you to make further copies of the Memento for `5one Supporter Point`0 plus `6250 CobbleStones`0 each.`n`n", $originalcost);
                addnav("Buy");
                if ($pointsavailable >= 500) {
                    addnav("Make a new mould", "runmodule.php?module=mementos&op=reforge&itemid=" . $itemid);
                } else {
                    addnav("Not enough `5Supporter Points`0 to make a new mould", "");
                }
            }
            addnav("Return");
            addnav("Memento Forge", "runmodule.php?module=mementos&op=start");
            break;
        case "reforge":
            $itemid = httpget("itemid");
            output("You've successfully recreated the mould for your Memento.`n`n");
            set_item_pref("mouldusesleft", 50, $itemid);
            addnav("Return");
            addnav("Memento Forge", "runmodule.php?module=mementos&op=start");
            $session['user']['donationspent'] += 500;
            $logsql = "INSERT INTO " . db_prefix("purchaselog") . " (acctid,purchased,amount,data,giftwrap,timestamp) VALUES ('" . $session['user']['acctid'] . "','memento_mould','500','none','0','" . date("Y-m-d H:i:s") . "')";
            db_query($logsql);
            break;
        case "new":
            $type = httpget('type');
            if ($type == 'single') {
                output("You're making a new unique Memento now.  Create your desired item and hit Submit.  You can use colour codes and italics just like in commentary, and you can use bold too, using the ``b switch (remember to close your bolds and italics with another ``b or ``i!).`n`nRemember to use ``n for a new line rather than pressing Enter.  Use ``n``n for a line break between paragraphs.`n`n");
                rawoutput("<form action='runmodule.php?module=mementos&op=check&type=single' method='POST'>Memento Name (maximum 100 characters): <input name='name' id='name'><br /><br />Plural (maximum 100 characters): <input name='plural' id='plural'><br /><br />Memento Description (maximum 255 characters):<br />");
                addnav("", "runmodule.php?module=mementos&op=check&type=single");
            } else {
                if ($type == 'mould') {
                    output("You're making a new Memento Mould now.  Create your desired item and hit Submit.  You can use colour codes and italics just like in commentary, and you can use bold too, using the ``b switch (remember to close your bolds and italics with another ``b or ``i!).`n`nRemember to use ``n for a new line rather than pressing Enter.  Use ``n``n for a line break between paragraphs.`n`n");
                    rawoutput("<form action='runmodule.php?module=mementos&op=check&type=mould' method='POST'>Memento Name (maximum 100 characters): <input name='name' id='name'><br /><br />Plural (maximum 100 characters): <input name='plural' id='plural'><br /><br />Memento Description (maximum 255 characters):<br />");
                    addnav("", "runmodule.php?module=mementos&op=check&type=mould");
                }
            }
            require_once "lib/forms.php";
            previewfield_countup("description");
            rawoutput("<br /><br />Text shown when using the Memento (maximum 1,000 characters):<br />");
            previewfield_countup("usetext");
            rawoutput("<br /><input type=submit>");
            addnav("Start Again");
            addnav("Memento Forge", "runmodule.php?module=mementos&op=start");
            break;
        case "check":
            output("Here's a preview of your Memento:`n`n");
            $rname = httppost("name");
            $rplural = httppost("plural");
            $rdesc = httppost("description");
            $rusetext = httppost("usetext");
            $type = httpget("type");
            $dname = stripslashes($rname);
            $dplural = stripslashes($rplural);
            $ddesc = stripslashes($rdesc);
            $dusetext = stripslashes($rusetext);
            output("`bName:`b %s`0 (%s`0)`n`bDescription:`b %s`0`n`bUse Text:`b %s`0`n`n", $dname, $dplural, $ddesc, $dusetext);
            if (strlen($dname) <= 100 && strlen($dplural) <= 100 && strlen($ddesc) <= 255 && strlen($dusetext) <= 1000) {
                addnav("Confirm");
                if ($type == "single") {
                    addnav("Buy it! (`550 Supporter Points`0)", "runmodule.php?module=mementos&op=confirm&name=" . urlencode($rname) . "&plural=" . urlencode($rplural) . "&desc=" . urlencode($rdesc) . "&usetext=" . urlencode($rusetext) . "&type=single");
                } else {
                    if ($type == "mould") {
                        addnav("Buy it! (`5500 Supporter Points`0)", "runmodule.php?module=mementos&op=confirm&name=" . urlencode($rname) . "&plural=" . urlencode($rplural) . "&desc=" . urlencode($rdesc) . "&usetext=" . urlencode($rusetext) . "&type=mould");
                    }
                }
            } else {
                output("`4`bError: Something is too long.  Titles can be up to 100 characters, descriptions up to 255 characters, and usage texts up to 1,000 characters.`b`0`n`n");
                rawoutput("<form action='runmodule.php?module=mementos&op=check&type=" . $type . "' method='POST'>Memento Name (maximum 100 characters): <input name='name' id='name' value={$rname}><br /><br />Plural (maximum 100 characters): <input name='plural' id='plural' value={$rplural}><br /><br />Memento Description (maximum 255 characters):<br />");
                require_once "lib/forms.php";
                previewfield_countup("description", 255, $rdesc);
                rawoutput("<br /><br />Text shown when using the Memento (maximum 1,000 characters):<br />");
                previewfield_countup("usetext", 1000, $rusetext);
                rawoutput("<br /><input type=submit>");
                addnav("", "runmodule.php?module=mementos&op=check&type=" . $type);
            }
            addnav("Start Again");
            addnav("Memento Forge", "runmodule.php?module=mementos&op=start");
            break;
        case "confirm":
            $type = httpget("type");
            $name = urldecode(httpget("name"));
            $plural = urldecode(httpget("plural"));
            $desc = urldecode(httpget("desc"));
            $usetext = urldecode(httpget("usetext"));
            $prefs = array("verbosename" => $name, "plural" => $plural, "description" => $desc, "usetext" => $usetext, "memento_author" => $session['user']['acctid']);
            if ($type == "single") {
                $cost = 50;
                output("You've made a new Memento.  You can find it in your Inventory!");
            } else {
                if ($type == "mould") {
                    $cost = 500;
                    output("You've made a mould for your new Memento, and the first Memento from that mould is now in your Inventory!");
                    $prefs['mouldusesleft'] = 50;
                }
            }
            $session['user']['donationspent'] += $cost;
            //log purchase
            $logsql = "INSERT INTO " . db_prefix("purchaselog") . " (acctid,purchased,amount,data,giftwrap,timestamp) VALUES ('" . $session['user']['acctid'] . "','memento_" . $type . "','" . $cost . "','none','0','" . date("Y-m-d H:i:s") . "')";
            db_query($logsql);
            //create the mould, track its id
            $id = give_item("memento", $prefs, "mementomoulds_" . $session['user']['acctid'], true);
            //debug($id);
            $prefs['memento_originalitem'] = $id;
            set_item_pref("memento_originalitem", $id, $id);
            //give the player the initial memento
            give_item("memento", $prefs);
            addnav("Return");
            addnav("Memento Forge", "runmodule.php?module=mementos&op=start");
            break;
    }
    addnav("Return");
    addnav("Back to the Hunter's Lodge", "runmodule.php?module=iitems_hunterslodge&op=start");
    page_footer();
}
function improbablehousing_itemlinks($house, $rid)
{
    $hid = $house['id'];
    $items = load_inventory("dwelling_" . $hid . "_" . $rid, true);
    $roomitems = array();
    if (count($items) > 0) {
        foreach ($items as $itemid => $prefs) {
            $roomitems[$prefs['roomslot']] = $itemid;
        }
    }
    $numslots = $house['rooms'][$rid]['itemslots'];
    for ($i = 0; $i <= $numslots; $i++) {
        if ($roomitems[$numslots]) {
            //there's an item here - show its links
            $itemid = $roomitems[$numslots];
            //when the item is occupied or otherwise unusable, change its link text pref and clear its link pref
            addnav("Furniture");
            if (!get_item_pref("dwellings_link", $itemid)) {
                addnav(array("%s", get_item_pref("dwellings_linktext", $itemid)), "runmodule.php?module=improbablehousing&op=useitem&hid={$hid}&rid={$rid}&itemid={$itemid}");
            } else {
                if (get_item_pref("dwellings_linktext", $itemid)) {
                    addnav(array("%s", get_item_pref("dwellings_linktext", $itemid)), "");
                }
            }
            //show a link to pick up the item
            if (improbablehousing_getkeytype($house, $rid) >= 100 && !$vals['occupier']) {
                addnav(array("Pick up %s", get_item_pref("verbosename", $roomitems[$slot])), "runmodule.php?module=improbablehousing&op=pickupitem&hid={$hid}&rid={$rid}&item=" . $roomitems[$slot]);
            }
        } else {
            //there isn't an item here - show links for standard sleeping slots and links to place an item here
            //sigh...
            //TODO
        }
    }
}
function meatsystem_run()
{
    global $session;
    require_once "modules/staminasystem/lib/lib.php";
    page_header("Meat!");
    addnav("Meat Skills");
    $from = httpget('from');
    switch (httpget('op')) {
        case "devour":
            //special ability for Zombies only - Zombies can eat raw meat, so we're giving them the ability to simply devour the carcass where it lies.
            $carcasses = unserialize(get_module_pref("carcasses"));
            if (!is_array($carcasses)) {
                $carcasses = array();
            }
            debug($carcasses);
            foreach ($carcasses as $carcassnum => $creatureid) {
                $sql = "SELECT creaturename FROM " . db_prefix("creatures") . " WHERE creatureid = " . $creatureid . " ";
                $result = db_query_cached($sql, "creaturename-" . $creatureid, 86400);
                $creature = db_fetch_assoc($result);
                output("Giving in to your primal urges, you lean down and begin ripping meat from the still-twitching %s with your teeth.`n`n", $creature['creaturename']);
                $meat1 = get_module_objpref("creatures", $creatureid, "meat1");
                $meat2 = get_module_objpref("creatures", $creatureid, "meat2");
                $meat3 = get_module_objpref("creatures", $creatureid, "meat3");
                for ($i = 0; $i < $meat1; $i++) {
                    increment_module_pref("nutrition", 1, "staminafood");
                    increment_module_pref("fat", 3, "staminafood");
                    increment_module_pref("fullness", 1, "staminafood");
                    addstamina(1000);
                }
                for ($i = 0; $i < $meat2; $i++) {
                    increment_module_pref("nutrition", 2, "staminafood");
                    increment_module_pref("fat", 2, "staminafood");
                    increment_module_pref("fullness", 1, "staminafood");
                    addstamina(2000);
                }
                for ($i = 0; $i < $meat3; $i++) {
                    increment_module_pref("nutrition", 3, "staminafood");
                    increment_module_pref("fat", 1, "staminafood");
                    increment_module_pref("fullness", 1, "staminafood");
                    addstamina(5000);
                }
                output("For the record, and since it's nice to know these things even if you're too busy tearing cartilage and muscle from the bone to really pay attention to them, in this meal you have eaten %s bite's-worth of Crap Meat, %s bite's-worth of Half-Decent Meat, and %s bite's-worth of Tasty Meat.`n", $meat1, $meat2, $meat3);
                $full = get_module_pref("fullness", "staminafood");
                if ($full < 0) {
                    output("You still feel as though you haven't eaten in days.`n`n");
                }
                if ($full >= 0 && $full < 50) {
                    output("You feel a little less hungry.`n`n");
                }
                if ($full >= 50 && $full < 100) {
                    output("You still feel as though you've got room for more!`n`n");
                }
                if ($full >= 100) {
                    output("You're stuffed!  You feel as though you can't possibly eat anything more today.`n`n");
                }
                unset($carcasses[$carcassnum]);
                set_module_pref("carcasses", serialize($carcasses));
            }
            break;
        case "clean":
            $creatureid = httpget('creatureid');
            $carcass = httpget('carcass');
            $meat1 = get_module_objpref("creatures", $creatureid, "meat1");
            $meat2 = get_module_objpref("creatures", $creatureid, "meat2");
            $meat3 = get_module_objpref("creatures", $creatureid, "meat3");
            $amber = get_stamina();
            $return = process_action("Cleaning the Carcass");
            if ($return['lvlinfo']['levelledup'] == true) {
                output("`n`c`b`0You gained a level in Cleaning Carcasses!  You are now level %s!  This action will cost fewer Stamina points now, so you can butcher more creatures each day!`b`c`n", $return['lvlinfo']['newlvl']);
            }
            $failchance = e_rand(0, 100);
            if ($failchance > $amber) {
                //failure - the nice meat gets turned into Crap Meat
                $meat1 += $meat2;
                $meat1 += $meat3;
                output("`4You sit down to clean the carcass.  Your exhausted, clumsy incisions make a mockery of the choicest cuts - what is left over can only be described as Crap Meat.  %s bite's-worth, to be precise.  It looks like it was hacked into chunks by a blind woodsman.", $meat1);
                //todo
                for ($i = 0; $i < $meat1; $i++) {
                    give_item("meat_low", false, false, true);
                }
                load_inventory();
                $carcasses = unserialize(get_module_pref("carcasses"));
                unset($carcasses[$carcass]);
                $carcasses = array_values($carcasses);
                set_module_pref("carcasses", serialize($carcasses));
            } else {
                //success - all meat is sorted
                output("You spend a few minutes up to your elbows in gore, and getting rather hungry.`n");
                if ($meat1 > 0) {
                    output("You tear off enough to make %s rough bite's-worth of what the locals affectionately call Crap Meat.  It's mostly wobbling chunks of stinking yellow fat, intermingled with the occasional squirmy tendon.`n", $meat1);
                }
                if ($meat2 > 0) {
                    output("You make swift work of the fattier muscle, and before too long you have %s rough bite's-worth of Half-Decent Meat.`n", $meat2);
                }
                if ($meat3 > 0) {
                    output("The red, tender slivers of muscle slide easily from the bone, and you wind up with %s rough bite's-worth of Tasty Meat.`n", $meat3);
                }
                //todo
                for ($i = 0; $i < $meat1; $i++) {
                    give_item("meat_low", false, false, true);
                }
                for ($i = 0; $i < $meat2; $i++) {
                    give_item("meat_medium", false, false, true);
                }
                for ($i = 0; $i < $meat3; $i++) {
                    give_item("meat_high", false, false, true);
                }
                load_inventory();
                $carcasses = unserialize(get_module_pref("carcasses"));
                unset($carcasses[$carcass]);
                $carcasses = array_values($carcasses);
                set_module_pref("carcasses", serialize($carcasses));
                $pmeat1 = has_item("meat_low");
                $pmeat2 = has_item("meat_medium");
                $pmeat3 = has_item("meat_high");
                if (($pmeat1 || $pmeat2 || $pmeat3) && $session['user']['race'] != "Robot") {
                    if (get_module_pref("fullness", "staminafood") < 100) {
                        $cookcost = stamina_getdisplaycost("Cooking");
                        addnav(array("Cook up some meat (`Q%s%%`0)", $cookcost), "runmodule.php?module=meatsystem&op=cook&from=" . $from);
                    } else {
                        addnav("You're too full to cook, let alone eat", "");
                    }
                }
            }
            break;
        case "cook":
            $pmeat1qty = has_item_quantity("meat_low");
            $pmeat2qty = has_item_quantity("meat_medium");
            $pmeat3qty = has_item_quantity("meat_high");
            output("You whip out your camping stove.  It's time to cook!`n`nWhat will you put in the pan?  You can fit up to 20 bite's-worth of meat in there.  Right now you have %s bite's-worth of Crap Meat, %s bite's-worth of Half-Decent Meat, and %s bite's-worth of Tasty Meat.`n`n", $pmeat1qty, $pmeat2qty, $pmeat3qty);
            rawoutput("<form action='runmodule.php?module=meatsystem&op=cookfinal&from=" . $from . "' method='POST'>");
            rawoutput("Put in <input name='meat1' width='2' value='0'> bite's-worth of Crap Meat.<br />");
            rawoutput("Put in <input name='meat2' width='2' value='0'> bite's-worth of Half-Decent Meat.<br />");
            rawoutput("Put in <input name='meat3' width='2' value='0'> bite's-worth of Tasty Meat.<br />");
            rawoutput("<input type='submit' class='button' value='" . translate_inline("Cook!") . "'>");
            rawoutput("</form>");
            addnav("", "runmodule.php?module=meatsystem&op=cookfinal&from=" . $from);
            break;
        case "cookfinal":
            $pmeat1qty = has_item_quantity("meat_low");
            $pmeat2qty = has_item_quantity("meat_medium");
            $pmeat3qty = has_item_quantity("meat_high");
            $meat1 = httppost("meat1");
            $meat2 = httppost("meat2");
            $meat3 = httppost("meat3");
            //check for the dumbass player cooking meat that they don't have
            if ($meat1 > $pmeat1qty || $meat2 > $pmeat2qty || $meat3 > $pmeat3qty) {
                output("You don't `ihave`i that much meat!`n`n");
                addnav("Whoops");
                addnav("Sorry, I forgot how to count for a second there.  Let's try this again.", "runmodule.php?module=meatsystem&op=cook&from=" . $from);
                break;
            }
            //check for the dumbass player inputting a negative number
            if ($meat1 < 0 || $meat2 < 0 || $meat3 < 0) {
                page_header("Either taking vegetarianism to whole new levels, or trying to grow meat from an empty pan");
                output("You want to cook `inegative`i meat?  How very Zen of you.`n`n");
                addnav("You sneaky bugger");
                addnav("Abandon your efforts to produce the opposite of meat and try again, pretending that you weren't just trying to cheat.", "runmodule.php?module=meatsystem&op=cook&from=" . $from);
                break;
            }
            //check for the dumbass player trying to put too much meat in the pan
            $totalmeat = $meat1 + $meat2 + $meat3;
            if ($totalmeat > 20) {
                output("Your pan can't hold that much meat, pal.`n`n");
                addnav("Whoops");
                addnav("Try again, without filling the pan up so much", "runmodule.php?module=meatsystem&op=cook&from=" . $from);
                break;
            }
            //check for the dumbass player trying to cook no meat at all
            $totalmeat = $meat1 + $meat2 + $meat3;
            if ($totalmeat == 0) {
                output("You start the process of cooking up your tasty meat.  After a few minutes of poking around in your pan, growing hungrier by the second, you realise that you've forgotten something.`n`n");
                addnav("Whoops");
                addnav("Try again, with meat this time", "runmodule.php?module=meatsystem&op=cook&from=" . $from);
                break;
            }
            //Stamina interaction, including consequences and level-up details.
            $amber = get_stamina();
            $return = process_action("Cooking");
            if ($return['lvlinfo']['levelledup'] == true) {
                output("`n`c`b`0You gained a level in Cooking!  You are now level %s!  This action will cost fewer Stamina points now, so you can cook more tasty meals each day!`b`c`n", $return['lvlinfo']['newlvl']);
            }
            $failchance = e_rand(0, 100);
            if ($failchance > $amber) {
                output("`4You put your meat into the pan, and sit down to stir-fry it.  The hypnotic motion and white-noise sizzling, combined with your tiredness, sends you staring into space.  While your concentration is impaired, the meat bursts into flames.  You jerk back into awareness, and look down sadly at the flaming chunks.  Bummer.");
                for ($i = 0; $i < $meat1; $i++) {
                    delete_item(has_item("meat_low"));
                }
                for ($i = 0; $i < $meat2; $i++) {
                    delete_item(has_item("meat_medium"));
                }
                for ($i = 0; $i < $meat3; $i++) {
                    delete_item(has_item("meat_high"));
                }
                break;
            }
            //we can now assume that the player is not some sort of cheating reprobate, or trying to cook while dog-tired, and do some cooking!
            for ($i = 0; $i < $meat1; $i++) {
                increment_module_pref("nutrition", 1, "staminafood");
                increment_module_pref("fat", 3, "staminafood");
                increment_module_pref("fullness", 1, "staminafood");
                delete_item(has_item("meat_low"));
                addstamina(1000);
            }
            for ($i = 0; $i < $meat2; $i++) {
                increment_module_pref("nutrition", 2, "staminafood");
                increment_module_pref("fat", 2, "staminafood");
                increment_module_pref("fullness", 1, "staminafood");
                delete_item(has_item("meat_medium"));
                addstamina(2000);
            }
            for ($i = 0; $i < $meat3; $i++) {
                increment_module_pref("nutrition", 3, "staminafood");
                increment_module_pref("fat", 1, "staminafood");
                increment_module_pref("fullness", 1, "staminafood");
                delete_item(has_item("meat_high"));
                addstamina(5000);
            }
            output("You fry up your lovely meaty loveliness, and sit down to eat.  You gain some Stamina!`n`n");
            $full = get_module_pref("fullness", "staminafood");
            if ($full < 0) {
                output("You still feel as though you haven't eaten in days.`n`n");
            }
            if ($full >= 0 && $full < 50) {
                output("You feel a little less hungry.`n`n");
            }
            if ($full >= 50 && $full < 100) {
                output("You still feel as though you've got room for more!`n`n");
            }
            if ($full >= 100) {
                output("You're stuffed!  You feel as though you can't possibly eat anything more today.`n`n");
            }
            break;
    }
    $carcasses = unserialize(get_module_pref("carcasses"));
    if (!is_array($carcasses)) {
        $carcasses = array();
    }
    if (count($carcasses) > 0) {
        output("You look at the spoils of your most recent battle.  They lie bloodied and broken on the ground.  What will you do with them?");
        foreach ($carcasses as $carcassnum => $creatureid) {
            $sql = "SELECT creaturename FROM " . db_prefix("creatures") . " WHERE creatureid = " . $creatureid . " ";
            $result = db_query_cached($sql, "creaturename-" . $creatureid, 86400);
            $creature = db_fetch_assoc($result);
            $cleancost = stamina_getdisplaycost("Cleaning the Carcass");
            addnav(array("Clean the carcass of %s (`Q%s%%`0)", $creature['creaturename'], $cleancost), "runmodule.php?module=meatsystem&op=clean&creatureid=" . $creatureid . "&carcass=" . $carcassnum . "&from=" . $from);
        }
    } else {
        if (httpget('op') != "cook" && httpget('op') != "cookfinal") {
            output("Now only bloody bones lie strewn around the area.`n`n");
        }
    }
    addnav("Ah, screw it.");
    if ($from == "forest") {
        addnav("Return to the Jungle", "forest.php");
    } else {
        if ($from == "world") {
            addnav("Return to the World Map", "runmodule.php?module=worldmapen&op=continue");
        }
    }
    page_footer();
    return true;
}
function eboy_run()
{
    global $session, $inventory;
    if (!isset($inventory)) {
        load_inventory();
    }
    page_header("eBoy's Trading Station");
    addnav("Buy Items");
    addnav("Sell Items");
    require_once "modules/cityprefs/lib.php";
    $cid = get_cityprefs_cityid("location", $session['user']['location']);
    $item = httpget('item');
    if ($item) {
        $curstock = get_item_setting("eboy_stock_" . $cid, $item);
        $curprice = get_item_setting("eboy_price_" . $cid, $item);
    }
    eboy_updateprices();
    $eboy_info = get_items_with_settings("eboy");
    if (httpget('op') == "start") {
        output("Already fearing the worst, you head into eBoy's Trading Station.`n`nYour fears are well-founded.  The place is packed with the heaving, sweaty bodies of the hardcore capitalist, shouting \"`iBuy, buy!`i\" and \"`iSell, sell!`i\" and \"`iPut down the chainsaw and let's talk about this!`i\"`n`neBoy himself - although you suspect that this place, like Mike's Chop Shop, is a franchise of which you'll find one in every outpost, so is his name really eBoy?  Whoever he is, he stands on an elevated section of floor behind a tall mahogany counter, grabbing money with one hand and tossing grenades and ration packs over his shoulder with the other.  His arms are a blur.  His speech is the unintelligible, rapid-fire gabble of a professional auctioneer.  His eyes bulge and swivel.  You know he's loving this.`n`n");
    }
    if (httpget('op') == "buy") {
        $pprice = httpget('price');
        if ($pprice == $curprice) {
            if ($curstock > 0) {
                give_item($item);
                $session['user']['gold'] -= $curprice;
                increment_item_setting("eboy_stock_" . $cid, -1, $item);
                output("You fight your way to the front of the crowd and shout your order up to eBoy, slapping your Requisition tokens down on the counter.  Before you can blink, your money is gone and the item you desired sits in its place.  You grab it hastily and stuff it into your backpack as eBoy turns to deal with the next customer.`n`n");
            } else {
                output("eBoy turns to you and gibbers.`n`n\"Sorrymatejustsoldthelastoneyougottabefasteritsthequickandthedeadaroundherepal.\"  He turns to the next customer in line, leaving you trying to piece together whatever it is that he just said.`n`n");
            }
        } else {
            output("You fight your way to the front of the crowd and shout your order up to eBoy, slapping your Requisition tokens down on the counter.  eBoy turns to you and gibbers.`n`n\"Idontmeantobefunnymatebutlookattheboardthepricehasjustbloodychangedagainyousureyoustillwannabuy?\"  After giving you exactly one microsecond to consider what the hell he just asked, he rolls his eyes and turns to the next customer in line.`n`n");
        }
    }
    if (httpget('op') == "sell") {
        $pprice = httpget('price');
        $requiredprefs = array("inventorylocation" => "main");
        $itemid = has_item($item, $requiredprefs);
        if ($pprice == $curprice) {
            delete_item($itemid);
            if ($curstock < 3) {
                $buy = round($curprice * 0.5);
            } else {
                $buy = round($curprice * 0.7);
            }
            $session['user']['gold'] += $buy;
            increment_item_setting("eboy_stock_" . $cid, 1, $item);
            output("You barge your way through the crowd like a battleship through an ice floe, and toss your item up to eBoy.  eBoy snatches the item out of the air with his left hand while tossing your Requisition tokens back at you with his right, and goes on to serve the next customer.`n`n");
        } else {
            output("You fight your way to the front of the crowd and shout your order up to eBoy, slapping your Requisition tokens down on the counter.  eBoy turns to you and gibbers.`n`n\"Idontmeatobefunnymatebutlookattheboardthepricehasjustbloodychangedagainyousureyoustillwannasell?\"  After giving you exactly one microsecond to consider what the hell he just asked, he rolls his eyes and turns to the next customer in line.`n`n");
        }
    }
    output("You look up above eBoy's head at the trading board, the values of each commodity displayed on a mechanical readout which clatters and changes constantly.`n`n");
    $sellable_inventory = array();
    foreach ($inventory as $itemid => $prefs) {
        if (!$prefs['carrieritem'] && $prefs['eboy'] && $prefs['inventorylocation'] == "main") {
            $sellable_inventory[$prefs['item']]['quantity'] += 1;
            $sellable_inventory[$prefs['item']]['itemids'][] = $itemid;
        }
    }
    eboy_updateprices();
    $eboy_info = get_items_with_settings("eboy");
    //inventory-type display routine
    rawoutput("<table width=100% style='border: dotted 1px #000000;'>");
    $classcount = 1;
    foreach ($eboy_info as $item => $settings) {
        if ($settings['eboy_stock_' . $cid] > 0) {
            $stock = number_format($settings['eboy_stock_' . $cid]) . " available";
        } else {
            $stock = "`4Sold Out`0";
        }
        $classcount++;
        $class = $classcount % 2 ? "trdark" : "trlight";
        rawoutput("<tr class='{$class}'><td>");
        if ($settings['image']) {
            rawoutput("<table width=100% cellpadding=0 cellspacing=0><tr><td width=100px align=center><img src=\"images/items/" . $settings['image'] . "\"></td><td>");
        }
        output("`b%s`b`n", stripslashes($settings['verbosename']));
        output("%s`n", stripslashes($settings['description']));
        if ($settings['weight']) {
            output("Weight: %s kg`n", $settings['weight']);
        }
        rawoutput("<table width=100%><tr><td width=50%>");
        output("`bStock:`b %s", $stock);
        if ($settings['eboy_stock_' . $cid] < 3) {
            $buy = round($settings['eboy_price_' . $cid] * 0.5);
        } else {
            $buy = round($settings['eboy_price_' . $cid] * 0.7);
        }
        if ($settings['eboy_price_' . $cid] > 0) {
            output("`n`7Buying at: %s Requisition", number_format($buy));
        } else {
            output("`nNot Buying");
        }
        if ($settings['eboy_stock_' . $cid] > 0) {
            output("`n`2Selling at: %s Requisition`n`n", number_format($settings['eboy_price_' . $cid]));
        } else {
            output("`n`n");
        }
        rawoutput("</td><td width=50%>");
        $requiredprefs = array("inventorylocation" => "main");
        if ($sellable_inventory[$item]) {
            addnav("Sell Items");
            if ($settings['eboy_stock_' . $cid] < 3) {
                $buy = round($settings['eboy_price_' . $cid] * 0.5);
            } else {
                $buy = round($settings['eboy_price_' . $cid] * 0.7);
            }
            if ($sellable_inventory[$item]['quantity'] > 0 && $settings['eboy_price_' . $cid] > 0) {
                addnav(array("%s (%s available)", $settings['verbosename'], $sellable_inventory[$item]['quantity']), "runmodule.php?module=eboy&op=sell&item=" . $item . "&price=" . $settings['eboy_price_' . $cid], true);
                addnav("", "runmodule.php?module=eboy&op=sell&item=" . $item . "&price=" . $settings['eboy_price_' . $cid]);
                rawoutput("<a href=\"runmodule.php?module=eboy&op=sell&item=" . $item . "&price=" . $settings['eboy_price_' . $cid] . "\">Sell for <strong>" . number_format($buy) . " </strong> Requisition (" . $sellable_inventory[$item]['quantity'] . " available to sell)</a><br />");
            }
        } else {
            output("`&You don't have any of this item to sell.`0`n");
        }
        if ($session['user']['gold'] >= $settings['eboy_price_' . $cid] && $settings['eboy_stock_' . $cid]) {
            addnav("Buy Items");
            addnav(array("%s (%s Req)", $settings['verbosename'], $settings['eboy_price_' . $cid]), "runmodule.php?module=eboy&op=buy&item=" . $item . "&price=" . $settings['eboy_price_' . $cid], true);
            addnav("", "runmodule.php?module=eboy&op=buy&item=" . $item . "&price=" . $settings['eboy_price_' . $cid]);
            rawoutput("<a href=\"runmodule.php?module=eboy&op=buy&item=" . $item . "&price=" . $settings['eboy_price_' . $cid] . "\">Buy for <strong>" . number_format($settings['eboy_price_' . $cid]) . "</strong> Requisition</a><br />");
        } else {
            if (!$settings['eboy_stock_' . $cid]) {
                output("`&There are no items of this type available.`0`n");
            } else {
                $difference = $settings['eboy_price_' . $cid] - $session['user']['gold'];
                output("`&You need another %s Requisition to buy this item.`0`n", number_format($difference));
            }
        }
        rawoutput("</td></tr></table>");
        if ($settings['image']) {
            rawoutput("</td></tr></table>");
        }
        rawoutput("</td></tr>");
    }
    rawoutput("</td></tr></table>");
    addnav("Leave");
    addnav("Return to the Outpost", "village.php");
    addnav("Inventory");
    addnav("View your Inventory", "inventory.php?items_context=eboy");
    //set_module_objpref("city",$cid,"eboytrades-intelligent",serialize($info));
    page_footer();
    return true;
}
function items_calculate_weights()
{
    global $session, $inventory;
    if (!isset($inventory)) {
        load_inventory();
    }
    $containerweights = array();
    foreach ($inventory as $itemid => $vals) {
        $containerweights[$vals['inventorylocation']]['weight_current'] += $vals['weight'];
        if ($vals['carrieritem']) {
            $containerweights[$vals['carrieritem']] = array_merge($containerweights[$vals['carrieritem']], $vals);
        }
    }
    return $containerweights;
}
function worldmap_items_dohook($hookname, $args)
{
    global $session, $itemprefs;
    switch ($hookname) {
        case "inventory":
            //debug($args);
            if ($args['context'] == "worldmap") {
                $inv = $args['inventory'];
                $sort = $args['sort'];
                foreach ($inv as $itemid => $prefs) {
                    //debug($prefs);
                    if ($prefs['dropworldmap']) {
                        //						debug("Found something!");
                        addnav("", "inventory.php?items_context=" . $args['context'] . "&items_mapdrop=" . $prefs['itemid'] . "&items_sort={$sort}");
                        $args['inventory'][$itemid]['inventoryactions'] .= "<a href=\"inventory.php?items_context=" . $args['context'] . "&items_mapdrop=" . $prefs['itemid'] . "&items_sort={$sort}\">Drop this item on the Map</a> | ";
                        if ($args['inventory'][$itemid]['quantity'] > 1 && !$prefs['dropworldmap_blockdropall']) {
                            addnav("", "inventory.php?items_context=" . $args['context'] . "&items_mapdrop=" . $prefs['itemid'] . "&items_sort={$sort}&dropall=true");
                            $args['inventory'][$itemid]['inventoryactions'] .= "<a href=\"inventory.php?items_context=" . $args['context'] . "&items_mapdrop=" . $prefs['itemid'] . "&items_sort={$sort}&dropall=true\">Drop all</a> | ";
                        }
                        $args['inventory'][$itemid]['cannotdiscard'] = true;
                    }
                }
            }
            break;
        case "inventory-predisplay":
            if ($args['context'] == "worldmap") {
                $drop = httpget("items_mapdrop");
                if ($drop) {
                    $loc = get_module_pref("worldXYZ", "worldmapen");
                    if (httpget("dropall")) {
                        $todrop = get_all_items($drop);
                        $dropids = array();
                        foreach ($todrop as $id => $vals) {
                            $dropids[] = $id;
                        }
                        change_item_owner($dropids, "worldmap_" . $loc);
                    } else {
                        change_item_owner($drop, "worldmap_" . $loc);
                    }
                }
            }
            break;
        case "worldnav":
            $ploc = implode(",", $args);
            $squarestuff = load_inventory("worldmap_" . $ploc, true);
            $itemid = httpget('item-pickup');
            if ($itemid) {
                //Pick up iitems
                if (httpget('pickupall')) {
                    //Pick up all iitems
                    $itemtype = $squarestuff[$itemid]['item'];
                    $pickup = array();
                    foreach ($squarestuff as $sqitemid => $sqprefs) {
                        //debug($sqprefs);
                        if ($sqprefs['item'] == $itemtype) {
                            $pickup[] = $sqitemid;
                        }
                    }
                    //debug($pickup);
                    change_item_owner($pickup, $session['user']['acctid']);
                    output("`0You pick up the %s.`n", $squarestuff[$itemid]['plural']);
                } else {
                    //Pick up single iitem
                    if ($squarestuff[$itemid]) {
                        output("`0You pick up the %s.`n", $squarestuff[$itemid]['verbosename']);
                        change_item_owner($itemid, $session['user']['acctid']);
                    } else {
                        output("`0You bend over to pick up the item, but it's suddenly not there anymore!  Some crafty bastard has pinched it from right under your nose!`n");
                    }
                }
                //reload this square's inventory
                $squarestuff = load_inventory("worldmap_" . $ploc, true);
            }
            $squarestuff = group_items($squarestuff);
            //debug($squarestuff);
            foreach ($squarestuff as $sortid => $prefs) {
                $itemid = $prefs['itemid'];
                $showmsg = true;
                if ($prefs['quantity'] > 1 && !$prefs['dropworldmap_blockdropall']) {
                    addnav("Pick up items");
                    addnav(array("Pick up %s", $prefs['verbosename']), "runmodule.php?module=worldmapen&op=continue&item-pickup=" . $itemid);
                    addnav(array("Pick up all %s", $prefs['plural']), "runmodule.php?module=worldmapen&op=continue&item-pickup=" . $itemid . "&pickupall=true");
                    output("`0There are %s %s here.`n`n", $prefs['quantity'], $prefs['plural']);
                } else {
                    addnav("Pick up items");
                    addnav(array("Pick up %s", $prefs['verbosename']), "runmodule.php?module=worldmapen&op=continue&item-pickup=" . $itemid);
                    output("`0There is a %s here.`n`n", $prefs['verbosename']);
                }
            }
            if ($showmsg && $session['user']['dragonkills'] < 1 && $session['user']['level'] < 10) {
                output("`JLogs and stone are only really useful if you're building a Dwelling.  To build a Dwelling, you'll need a Land Claim stake from Improbable Central, which will set you back 100 Cigarettes.  If you're not building a Dwelling, then there's not much reason to pick them up (logs and stone are really heavy!).  This message will disappear once you've got a few more levels under your belt.`0`n");
            }
            break;
    }
    return $args;
}
function rail_collector_emptyhand()
{
    // returns the number of cards that have been removed
    global $session, $inventory;
    if (!isset($inventory)) {
        load_inventory();
    }
    $items = group_items($inventory);
    $qty = 0;
    foreach ($items as $ptr => $details) {
        $itemname = $details['item'];
        $pos = strpos($itemname, "railcard");
        if ($pos === 0) {
            // Boolean false if not found; pos 0 if found in, eg, "railcard01"
            $qty = $qty + delete_all_items_of_type($itemname);
        }
    }
    return $qty;
}