function binarypuzzle_run()
{
    global $session;
    page_header("Binary Puzzle Thing!");
    addnav("O?Back to the Outpost", "village.php");
    switch (httpget('op')) {
        case "start":
            //first set up the board
            $switches = array(1 => array("val" => 1, "status" => 0), 2 => array("val" => 2, "status" => 0), 3 => array("val" => 4, "status" => 0), 4 => array("val" => 8, "status" => 0), 5 => array("val" => 16, "status" => 0), 6 => array("val" => 32, "status" => 0), 7 => array("val" => 64, "status" => 0), 8 => array("val" => 128, "status" => 0));
            shuffle($switches);
            set_module_pref("switches", serialize($switches));
            //Now set up the clues
            $clues = array();
            for ($i = 1; $i <= 8; $i++) {
                $toprange = $i * 32;
                $bottomrance = $toprange - 32;
                $clues[$i] = e_rand($bottomrange, $toprange);
            }
            $goal = e_rand(129, 255);
            set_module_pref("clues", serialize($clues));
            binarypuzzle_show($switches, $goal);
            break;
        case "switch":
            $sw = httpget('switch');
            $goal = httpget('goal');
            $switches = binarypuzzle_switch($sw);
            binarypuzzle_show($switches, $goal);
            break;
    }
    page_footer();
}
function mutemod_domute($id)
{
    global $session;
    $op = httpget('op');
    if (is_module_active("biocomment") && httpget('refresh')) {
        return false;
    }
    if ($op == "mute") {
        set_module_pref("muted", 1, false, $id);
        modulehook("mute", array("userid" => $id, "staffid" => $session['user']['acctid'], "when" => date("Y-m-d H:i:s")));
        output("`n`\$This player has now been muted!");
        output("`nThis will last until it is lifted, by you or another member of staff!`0`n");
    } elseif ($op == "unmute") {
        set_module_pref("muted", 0, false, $id);
        output("`n`\$This player has now been unmuted!");
        output("`nThey can talk again!`0`n");
    } elseif ($op == "tempmute") {
        set_module_pref("tempmute", 1, false, $id);
        modulehook("tempmute", array("userid" => $id, "staffid" => $session['user']['acctid'], "length" => 1, "when" => date("Y-m-d H:i:s")));
        output("`n`\$This player has now been muted temporarily!");
        output("`nThey cannot talk until the next new day!`0`n");
    } elseif ($op == "untempmute") {
        set_module_pref("tempmute", 0, false, $id);
        output("`n`\$This player has now been unmuted (from a temporary mute)!");
        output("`nThey can talk again!`0`n");
    } elseif ($op == "exttempmute") {
        $tmuted = get_module_pref("tempmute", false, $id) + 1;
        set_module_pref("tempmute", $tmuted, false, $id);
        modulehook("tempmute", array("userid" => $id, "staffid" => $session['user']['acctid'], "length" => $tmuted, "when" => date("Y-m-d H:i:s")));
        output("`n`\$This player´s tempory mute has been extended!");
        output("`nThey cannot talk until %s days have passed!`0`n", $tmuted);
    }
}
function improbablehousing_run()
{
    global $session;
    $op = httpget("op");
    require_once "modules/improbablehousing/run/{$op}.php";
    page_footer();
}
function dwellings_run()
{
    checkday();
    page_header("Dwellings");
    global $session;
    $op = httpget("op");
    $dwid = httpget('dwid');
    $type = httpget('type');
    debug(get_module_pref("location_saver"));
    if ($type == "" && $dwid > 0) {
        $sql = "SELECT type FROM " . db_prefix("dwellings") . " WHERE dwid={$dwid}";
        $result = db_query($sql);
        $row = db_fetch_assoc($result);
        $type = $row['type'];
    }
    $cityid = httpget('cityid');
    require_once "modules/dwellings/run/case_{$op}.php";
    if ($op != "list" && $op != "") {
        addnav("Leave");
        addnav("Return to Hamlet", "runmodule.php?module=dwellings");
    } else {
        addnav("Navigation");
        villagenav();
    }
    page_footer();
}
function titans_run()
{
    global $session;
    $titanop = httpget("titanop");
    require_once "modules/titans/run/{$titanop}.php";
    page_footer();
}
function pinata_runevent($type, $link)
{
    global $session;
    $from = $link;
    $session['user']['specialinc'] = "module:pinata";
    $op = httpget('op');
    if ($op == "") {
        output("`#You discover a small `@bright green dragon pinata `#hanging from the branch of an old oak tree.");
        output("As it twists and turns slightly in the gentle breeze, you wonder what treats may be contained within.`n`n");
        output("Looking for something to swing at the `@pinata, `#you see leaning against the tree a stout branch, stripped of leaves.");
        output("Breaking the `@pinata `#may yield precious resources, or it may result in exhaustion in the attempt to break it.`n`n");
        output("`%Do you wish to take a swing?`0");
        addnav("Swing", $from . "op=swing");
        addnav("Don't Swing", $from . "op=noswing");
    } elseif ($op == "swing") {
        output("`#Knowing that trying to break the `@pinata `#could yield disappointment, you decide to take your chances.`n`n");
        output("Picking up the stout branch in both hands, you take a deep breath as you step up to swing.");
        output("`#You plant your feet and bring your arms back.`n`n");
        output("`i`^The silence around you is broken by the whistle of the branch cutting the air`i.`0`n`n");
        pinata_hit();
        $session['user']['specialinc'] = "";
    } else {
        $session['user']['specialinc'] = "";
        output("`&You are not confident in your ability to strike and break the `@pinata, `&so you return to the forest and leave it gently swaying from the branch waiting for the next warrior to come by.`0");
    }
}
function rail_peddler_run()
{
    global $session, $inventory;
    $op = httpget("op");
    $loc = rail_peddler_getloc();
    $hid = $loc["peddlerhid"];
    $rid = $loc["peddlerrid"];
    $price = get_module_setting("peddlerprice");
    if ($op == "buy") {
        $headertext = "Why sure, I'll take one of those!";
    } else {
        $headertext = "Go away, I'm busy.";
    }
    page_header($headertext);
    switch ($op) {
        case "buy":
            output("The scruffy vendor's eyes gleam. Was that a fla`gs`0h of green, or no? \"`2Verra wise, %s. Ye willna be sorry!`0\"`n`n", translate_inline($session['user']['sex'] ? 'lass' : 'lad'));
            give_item("cardcase");
            //			if (!$success){
            //				output("Then -- a frown. \"`2Wait, no, I canna sell t'ye. Ye'd better petition the Big Boss, tell 'im t'see what's gaen wrong wiv all dis.`0\"`n`n");
            //			} else {
            output("You have a fine leather card case. Pleased, you admire its soft texture. What an excellent purchase you have made!`n`n");
            //			}
            $session['user']['gems'] -= $price;
            break;
        case "pass":
            output("\"`2Bleedin' smart-arse.`0\" The scruffy vendor shrugs and goes off to pester someone else.`n`n");
            break;
    }
    addnav("Back to the Concourse", "runmodule.php?module=improbablehousing&op=interior&hid={$hid}&rid={$rid}");
    page_footer();
}
function sethsong_run()
{
    $op = httpget('op');
    $visits = get_module_setting("visits");
    $been = get_module_pref("been");
    $iname = getsetting("innname", LOCATION_INN);
    tlschema("inn");
    page_header($iname);
    rawoutput("<span style='color: #9900FF'>");
    output_notl("`c`b");
    output($iname);
    output_notl("`b`c");
    tlschema();
    // Short circuit out if we've heard enough
    if ($been >= $visits) {
        output("%s`0 clears his throat and drinks some water.", getsetting("bard", "`^Seth"));
        output("\"I'm sorry, my throat is just too dry.\"");
    } else {
        sethsong_sing();
    }
    addnav("Where to?");
    addnav("I?Return to the Inn", "inn.php");
    villagenav();
    rawoutput("</span>");
    page_footer();
}
function friendlist_unignore()
{
    global $session;
    $ac = httpget('ac');
    $ignored = rexplode(get_module_pref('ignored', 'friendlist', $ac));
    $iveignored = rexplode(get_module_pref('iveignored'));
    if (in_array($ac, $iveignored)) {
        $sql = "SELECT name FROM " . db_prefix("accounts") . " WHERE acctid={$ac} AND locked=0";
        $result = db_query($sql);
        if (db_num_rows($result) > 0) {
            $row = db_fetch_assoc($result);
            $info = sprintf_translate("%s`Q has been removed from your list.", $row['name']);
            require_once "lib/systemmail.php";
            $t = array("`\$Ignore List Removal");
            $mailmessage = array("%s`0`@ has removed you from %s ignore list.", $session['user']['name'], $session['user']['sex'] ? translate_inline("her") : translate_inline("his"));
            systemmail($ac, $t, $mailmessage);
        } else {
            $info = translate_inline("That user no longer exists...");
        }
    }
    $ignored = array_diff($ignored, array($session['user']['acctid']));
    $ignored = rimplode($ignored);
    set_module_pref('ignored', $ignored, 'friendlist', $ac);
    if (in_array($ac, $iveignored)) {
        $iveignored = array_diff($iveignored, array($ac));
        $iveignored = rimplode($iveignored);
        set_module_pref('iveignored', $iveignored);
    }
    output_notl($info);
}
function offering_runevent($type)
{
    global $session;
    $session['user']['specialinc'] = "module:offering";
    $seen = get_module_pref("seen");
    $amt = round(max(1, $session['user']['dragonkills'] * 10) * $session['user']['level'] * max(1, 5000 - $session['user']['maxhitpoints']) / 20000);
    $op = httpget('op');
    if ($op == "") {
        output("`7While you are listening to others chatting, a bizarrely-dressed woman approaches with an outstretched hand. `n`n");
        output("\"`&For the offering!!! `^%s `&gold!`7\"", $amt);
        $seen++;
        set_module_pref("seen", $seen);
        addnav(array("Give her %s gold", $amt), "village.php?op=shop");
        addnav("Walk away", "village.php?op=nope");
    } elseif ($op == "nope") {
        output("`7You decide not to give any gold to this strange woman.`n");
        $session['user']['specialinc'] = "";
    } elseif ($session['user']['gold'] < $amt) {
        output("`7The woman stares at your hand.`n`n");
        output("\"`&No no no no no!!! He would not be pleased!!!`7\"`n`n");
        output("`7Without another word, she walks away.`n");
        $session['user']['specialinc'] = "";
    } else {
        output("`7You hand her `^%s`7 gold, and she lifts her head up, looks intently at something above her that only she can see, and whispers, `&\"%s!`&\" `7with apparent urgency.`n`n", $amt, getsetting("deathoverlord", '`$Ramius'));
        output("`7Without another word she scurries off, a determined look on her face, and a purpose in her stride.`n`n");
        if ($session['user']['dragonkills'] > 30) {
            $session['user']['deathpower'] += 10;
        } else {
            $session['user']['deathpower'] += 15;
        }
        $session['user']['gold'] -= $amt;
    }
}
function cakeordeath_run()
{
    global $session;
    page_header("Cake Or Death");
    switch (httpget("op")) {
        case "examine":
            // Tell the player what the deal with Cake Or Death is
            $counter = number_format(get_module_setting("counter"));
            output("`0A shiny wooden table sits back from the main street.  Behind it, a man sits idly reading the Improbable Island Enquirer.  Before him, sat on the table, is a large sponge cake.  Above him is a banner, displaying the name of his game:`b'`5Cake`0 or `4Death!`0'`b`n`nHe sees you pondering the sign, and calls over to you.  `b'`5Cake`0 or `4Death!`0  `b`5Cake`0 or `4Death!`0' he cries.  'Ninety-nine per cent chance of `b`5Cake`0`b!'`n`nIt's not often that an immaculately-dressed gentleman with glowing green eyes offers you a 99% chance of cake.  What would you like to do?");
            //add navs
            addnav("CAKE!", "runmodule.php?module=cakeordeath&op=play");
            addnav("Back away slowly", "village.php");
            break;
        case "play":
            $counter = get_module_setting("counter");
            addnav("Back to the Outpost", "village.php");
            if ($counter > 0) {
                output("The green-eyed gentleman hands you a slice of cake, on a paper plate.  You thank him, and walk away merrily wolfing down your prize.`n`nYou feel `5Full Of Cake!`0");
                set_module_setting("counter", get_module_setting("counter") - 1);
                apply_buff('tastycake', array("name" => "`5Full Of Cake`0", "rounds" => 10, "atkmod" => 1.1, "defmod" => 1.1, "roundmsg" => "`5The cake you ate earlier has boosted your energy!`n", "schema" => "module-cakeordeath"));
            }
            if ($counter <= 0) {
                output("The green-eyed gentleman hands you a slice of cake, on a paper plate.  You thank him, and walk away merrily wolfing down your prize.`n`nYou feel `5Full Of Cake!`0`n`nMoments later, the slow-acting poison starts to take effect.  The world begins to melt in front of you.  Grey spots dance on the edges of your vision.  Behind you, a green-eyed monster offers you another slice of cake, laughing and pointing.`n`nYou curse your luck as the hallucinations begin to kick in.");
                set_module_setting("counter", 100);
                apply_buff('failcake', array("name" => "`5Full Of FailCake`0", "rounds" => -1, "regen" => -10, "startmsg" => "`5You are walking on pink icing.  The sky is made of jam.  Your eyes are two cherries.  That cake was awesome.`0`n", "roundmsg" => "`5The poisoned cake saps your strength, and you lose ten hitpoints!`0`n", "schema" => "module-cakeordeath"));
                if (is_module_active("medals")) {
                    require_once "modules/medals.php";
                    medals_award_medal("failcake", "Failcake Fancier", "This player was unfortunate at the Cake or Death stand...", "medal_failcake.png");
                }
            }
            break;
    }
    page_footer();
}
function translationconvert_run()
{
    global $session;
    page_header("Translations Convertor Thing");
    output("Outputting all known translations, so that you can do a find-and-replace in the files themselves and we can stop doing this silly translate thing.`n`n");
    if (httpget('delete')) {
        $del = httpget('delete');
        $sql = "UPDATE " . db_prefix("translations") . " SET version='updated' WHERE tid={$del}";
        db_query($sql);
    }
    $sql = "SELECT * FROM " . db_prefix("translations") . " WHERE version='dragonbones' ORDER BY uri";
    $result = db_query($sql);
    $total = 0;
    while ($row = db_fetch_assoc($result)) {
        if ($row['intext'] != $row['outtext']) {
            $total++;
            rawoutput("<a href=\"runmodule.php?module=translationconvert&delete=" . $row['tid'] . "\">MARK</a>");
            addnav("", "runmodule.php?module=translationconvert&delete=" . $row['tid']);
            output_notl("`n`0`b%s`b:", $row['uri']);
            rawoutput("<table width=100%><tr><td width=50% border=1px solid #cccccc>" . $row['intext'] . "</td><td width=50%>" . $row['outtext'] . "</td></tr></table>");
            output_notl("`n`n");
        }
    }
    debug($total);
    addnav("Back to the Grotto", "superuser.php");
    page_footer();
}
function es_bridge_gp_dohook($hook, $args)
{
    global $session, $baseaccount;
    $item = httpget('item');
    $action = httpget('action');
    if ($session['user']['armor'] != $baseaccount['armor'] && ($action == 'weararmor' || $action == 'buyarmor') && $session['user']['armor'] == $item) {
        $category = 'armor';
        $defense = $session['user']['defense'];
    } elseif ($session['user']['weapon'] != $baseaccount['weapon'] && ($action == 'wearweapon' || $action == 'buyweapon') && $session['user']['weapon'] == $item) {
        $category = 'weapon';
        $attack = $session['user']['attack'];
    } else {
        $category = false;
    }
    if ($category && get_module_pref($category, 'mysticalshop')) {
        $current_id = get_module_pref($category . 'id', 'mysticalshop');
        debug("Current ID is {$current_id}");
        require_once './modules/mysticalshop/lib.php';
        mysticalshop_destroyitem($category);
        mysticalshop_resetbuffs($current_id);
        require_once './modules/mysticalshop_buffs/stripbuff.php';
        mysticalshop_buffs_stripbuff();
        if ($category == 'armor') {
            $session['user']['defense'] = $defense;
        } else {
            $session['user']['attack'] = $attack;
        }
        debuglog('es_bridge_gp: ' . $category . ' (ID: ' . $current_id . ') item removed on action "' . $action . '".');
    }
    return $args;
}
function oneshotteleporter_run()
{
    global $session;
    $to = httpget("to");
    if ($to == "") {
        page_header("The Void");
        output("You press the button on your One-Shot Teleporter.  One obligatory blinding flash of light and pain later, you find yourself floating around in empty black nothingness!`n`nA flashing red light and an annoying BEEPing noise from your device insists that you select a destination, and quickly, before you find yourself stuck here or imploded.");
        $vloc = array();
        $vname = getsetting("villagename", LOCATION_FIELDS);
        $vloc[$vname] = "village";
        $vloc = modulehook("validlocation", $vloc);
        ksort($vloc);
        reset($vloc);
        addnav("Choose a Destination");
        foreach ($vloc as $loc => $val) {
            addnav(array("Go to %s", $loc), "runmodule.php?module=oneshotteleporter&to=" . htmlentities($loc));
        }
    } else {
        page_header("Back to Reality");
        output("You quickly select an outpost from the list.  With a sudden jolt, you find yourself standing in the middle of your chosen outpost!  You look around for your teleporting device, but realise that it must have only teleported you, not itself.  What a piece of junk.");
        $session['user']['location'] = $to;
        $session['user']['specialinc'] = "";
        addnav("Continue");
        addnav("Back to the Outpost", "village.php");
    }
    page_footer();
    return true;
}
function worldmapen_editor_real()
{
    global $session;
    page_header("World Editor");
    require_once "lib/superusernav.php";
    superusernav();
    // initialize the internal static maps
    worldmapen_loadMap();
    worldmapen_loadTerrainDefs();
    $op = httpget("op");
    $act = httpget("act");
    $subop = httpget("subop");
    debug("op={$op}, act={$act}, subop={$subop}");
    switch ($subop) {
        case "regen":
            worldmapen_editor_regen($op, $subop, $act);
            break;
        case "manual":
            worldmapen_editor_manual($op, $subop, $act);
            break;
        case "terrain":
            worldmapen_editor_terrain($op, $subop, $act);
            break;
        default:
            worldmapen_viewmap(false);
            break;
    }
    addnav("Replace Cities", "runmodule.php?module=worldmapen&op=edit&subop=regen");
    addnav("Manually Place Cities", "runmodule.php?module=worldmapen&op=edit&subop=manual");
    addnav("Edit terrain type", "runmodule.php?module=worldmapen&op=edit&subop=terrain");
    page_footer();
}
function hepzibah_runevent($type)
{
    global $session;
    $from = "village.php?";
    // Since there is no interaction here, don't even set this
    //$session['user']['specialinc'] = "module:Hepzibah";
    $voucher = get_module_pref("voucher", "marquee");
    $city = $session['user']['location'];
    $op = httpget('op');
    // Since the text in both cases is mostly the same, make it common
    output("`7As you're walking around, admiring the sights, a wizened old woman approaches.`n`n");
    output("Her greying hair stands out in shock, and her nose is hooked and gnarled.");
    output("It takes all your willpower not to run away from this ghastly sight.`n`n");
    output("She smiles the most evil looking smile you have ever encountered.`n`n");
    output("`&\"Hello, warrior!");
    if (!is_module_installed("marquee") || $voucher) {
        output("Enjoying your visit?\"`n`n");
        output("`7Before you can answer, she has wandered off towards another tourist.`n`n");
        output("`7You shudder and head away quickly.`n`n");
    } elseif ($op == "" && !$voucher) {
        output("For you, a gift!\"`n`n");
        output("`7Before you can protest, she has grabbed your wrist, and placed a small voucher into your hand.");
        output("It reads, `Q\"One Free Pizza at the Marquee\".`n`n");
        output("`&\"Enjoy your stay in {$city}, warrior!\" `7she says, before wandering off towards another tourist.`n`n");
        set_module_pref("voucher", 1, "marquee");
    }
    // Since we never set the special inc, we don't need to unset it.
    //if ($op != "") {
    //    $session['user']['specialinc'] = "";
    //}
}
function faqmute_dohook($hookname, $args)
{
    global $session;
    $seen = get_module_pref("seenfaq");
    switch ($hookname) {
        case "insertcomment":
            if (!$seen && !$session['user']['dragonkills']) {
                $args['mute'] = 1;
                $mutemsg = "`n`\$You have to read the FAQ before you can post comments. You can find it in any town.`0`n`n";
                $mutemsg = translate_inline($mutemsg);
                $args['mutemsg'] = $mutemsg;
            }
            break;
        case "faq-posttoc":
            if (!$seen) {
                set_module_pref("seenfaq", true);
            }
            break;
        case "bioinfo":
            $id = $args['acctid'];
            $seen = get_module_pref("seenfaq", false, $id);
            if (httpget("op") == "faqmute") {
                set_module_pref("seenfaq", false, false, $id);
                output("`nPlayer's FAQ seen status reset.`n");
            } elseif ($session['user']['superuser'] & SU_EDIT_COMMENTS && $seen && !$args['dragonkills']) {
                addnav("Mute Player Options");
                addnav("FAQmute player", "bio.php?char=" . $id . "&ret=" . rawurlencode(httpget("ret")) . "&op=faqmute");
            }
            break;
    }
    return $args;
}
function changelog_run()
{
    $op = httpget('op');
    $ret = httpget('ret');
    $offset = httpget('offset') ?: 1;
    $offset = ($offset - 1) * 25;
    $offset = filter_var($offset, FILTER_SANITIZE_NUMBER_INT);
    $gamelog = db_prefix('gamelog');
    $accounts = db_prefix('accounts');
    $category = addslashes(get_module_setting('category'));
    page_header('Server Changelog');
    $sql = db_query("SELECT count(logid) AS n FROM {$gamelog} WHERE category = '{$category}'");
    $row = db_fetch_assoc($sql);
    addnav('Go back', "{$ret}.php");
    addnav('Changes');
    for ($i = 1; $i < $row['n'] / 25 + 1; $i++) {
        addnav(sprintf("%sPage %s (%s-%s)", $offset / 25 + 1 == $i ? '`^' : '', $i, ($i - 1) * 25 + 1, $i * 25 < $row['n'] ? $i * 25 : $row['n']), "runmodule.php?module=changelog&offset={$i}&ret={$ret}");
    }
    $sql = db_query("SELECT g.*, a.name FROM {$gamelog} AS g\n        LEFT JOIN {$accounts} AS a ON g.who = a.acctid\n        WHERE category = '{$category}' ORDER BY logid+0 DESC LIMIT {$offset}, 25");
    output("`c`@`bChangelog`b`c`n");
    while ($row = db_fetch_assoc($sql)) {
        output(get_module_setting('format'), $row['name'], $row['message']);
    }
    page_footer();
}
function staminatest_run()
{
    global $session;
    page_header("Stamina Testing");
    switch (httpget("op")) {
        case "start":
            output("Testing Testing!");
            break;
        case "add":
            output("Attempting to install an action called Sexins, with these parameters:`n`nStarting and Maximum costs: 500`nMinimum cost: 200`nReps for a Reduction: 20`nReduction: 10`n");
            install_action("Sexins", array("maxcost" => 25000, "mincost" => 10000, "expperrep" => 100, "expforlvl" => 1000, "costreduction" => 10, "dkpct" => 2.5));
            break;
        case "process":
            output("Processing the Sexins action");
            process_action("Sexins");
            break;
        case "newday":
            output("Processing a New Day");
            stamina_process_newday();
            break;
        case "buff":
            output("Applying a stamina buff to Sexins for the current user, for 20 rounds, reducing action cost to half.");
            apply_stamina_buff('ultra-sexy-buff-for-sexins', array("name" => "Ultra Sexy Buff for Sexins", "action" => "Sexins", "costmod" => 0.5, "expmod" => 0.8, "rounds" => 5, "roundmsg" => "Round Message!", "wearoffmsg" => "Wearoff Message!"));
            output("Also applying a Stamina Class buff to all Hunting actions, reducing their cost to half for twenty rounds.");
            apply_stamina_buff('huntclasstest', array("name" => "Hunting Class test buff", "class" => "Hunting", "costmod" => 0.5, "expmod" => 0.8, "rounds" => 20, "roundmsg" => "Round Message!", "wearoffmsg" => "Wearoff Message!"));
            break;
        case "get":
            $thingtodebug = get_player_action("Sexins");
            debug($thingtodebug);
            break;
        case "uninstall":
            output("Uninstalling the Sexins action, deleting all actions entries and associated buffs");
            uninstall_action("Sexins");
            break;
        case "dragonkill":
            output("Processing a Dragon Kill");
            stamina_process_dragonkill();
            break;
        case "calcbuffs":
            output("Calculating Buffs");
            stamina_calculate_buffed_cost("Sexins");
            break;
        case "calcexp":
            output("Calculating Buffed EXP");
            stamina_calculate_buffed_exp("Sexins");
            break;
    }
    addnav("Install an action called Sexins", "runmodule.php?module=staminatest&op=add");
    addnav("Uninstall", "runmodule.php?module=staminatest&op=uninstall");
    addnav("Process the Sexins Action for the current user", "runmodule.php?module=staminatest&op=process");
    addnav("Process newday", "runmodule.php?module=staminatest&op=newday");
    addnav("Add a buff", "runmodule.php?module=staminatest&op=buff");
    addnav("Get Stamina", "runmodule.php?module=staminatest&op=get");
    addnav("Process a Dragon Kill", "runmodule.php?module=staminatest&op=dragonkill");
    addnav("Calculate Buffed Cost", "runmodule.php?module=staminatest&op=calcbuffs");
    addnav("Calculate Buffed exp", "runmodule.php?module=staminatest&op=calcexp");
    addnav("Back to the Grotto", "superuser.php");
    page_footer();
    return true;
}
function textme_dohook($hook, $args)
{
    if (httpget('op') == 'send') {
        require_once 'lib/names.php';
        textme_sendmail(httpallpost(), get_player_basename());
    }
    return $args;
}
function lovers_chat_seth()
{
    global $session;
    if (httpget("act") == "") {
        output("You make your way over to where %s`0 is sitting, ale in hand.", getsetting("bard", "`^Seth"));
        output("Sitting down, and waiting for %s`0 to finish a song, you light your pipe.", getsetting("bard", "`^Seth"));
        addnav("Ask about your manliness", "runmodule.php?module=lovers&op=chat&act=armor");
        addnav("Discuss Sports", "runmodule.php?module=lovers&op=chat&act=sports");
    } elseif (httpget("act") == "sports") {
        output("You and %s`0 spend some time talking about the recent dwarf tossing competition.", getsetting("bard", "`^Seth"));
        output("Not wanting to linger around another man for too long, so no one \"wonders\", you decide you should find something else to do.");
    } else {
        $charm = $session['user']['charm'] + e_rand(-1, 1);
        output("%s`0 looks you up and down very seriously.", getsetting("bard", "`^Seth"));
        output("Only a friend can be truly honest, and that is why you asked him.");
        switch ($charm) {
            case -3:
            case -2:
            case -1:
            case 0:
                $msg = translate_inline("You make me glad I'm not gay!");
                break;
            case 1:
            case 2:
            case 3:
                $msg = translate_inline("I've seen some handsome men in my day, but I'm afraid you aren't one of them.");
                break;
            case 4:
            case 5:
            case 6:
                $msg = translate_inline("I've seen worse my friend, but only trailing a horse.");
                break;
            case 7:
            case 8:
            case 9:
                $msg = translate_inline("You're of fairly average appearance my friend.");
                break;
            case 10:
            case 11:
            case 12:
                $msg = translate_inline("You certainly are something to look at, just don't get too big of a head about it, eh?");
                break;
            case 13:
            case 14:
            case 15:
                $msg = translate_inline("You're quite a bit better than average!");
                break;
            case 16:
            case 17:
            case 18:
                $msg = translate_inline("Few women would be able to resist you!");
                break;
            default:
                $msg = translate_inline("I hate you, why, you are simply the most handsome man ever!");
        }
        output("Finally he reaches a conclusion and states, \"%s`0\"", $msg);
    }
}
function pub_newpittsburgh_drinks_dohook($hookname, $args)
{
    global $session;
    $drinks = array("brainhem" => array("price" => 35, "verbosename" => "Brain Hemorrhage"), "monstermash" => array("price" => 50, "verbosename" => "Monster Mash"), "specialsauce" => array("price" => 65, "verbosename" => "Special Sauce"));
    switch ($hookname) {
        case "pub_newpittsburgh_bartender":
            if ($session['user']['race'] == "Robot") {
                if ($session['user']['sex']) {
                    $lovelad = "lad";
                } else {
                    $lovelad = "love";
                }
                $args['text']['hello'] = "George looks you up and down, eyes sliding over your smooth glass skin.  \"`2You're a Robot, aren't you, " . $lovelad . "?`0\"`n`n\"`#That I am.  Are you going to tell me that you don't serve my type in here?`0\"`n`n\"`2On the contrary, Chuck, we'd be `ivery`i pleased to cater to our Robot customers, but we just don't have the power, y'see.  Setting up one of those fancy lamps just takes more amps than our genny can kick out.  You ask most of the pubs on the Island, it's the same way.`0\"`n`n\"`#I see.`0\"`n`n\"`2We've got games, though.  And telly.  You're more than welcome here, it's just...`0\" he shrugs his shoulders and spreads his hands.  \"`2I don't have anything to sell you that you'd want to buy.`0\"`n`n`#Fair enough`0, you suppose.";
            } else {
                $args['drinks'] = $drinks;
            }
            break;
        case "pub_newpittsburgh_drink":
            $drink = httpget("drink");
            switch ($drink) {
                case "brainhem":
                    $session['user']['gold'] -= 35;
                    output("\"`2All right Chuck,`0\" says George, bringing up a jar of pickled brains.  They look far too small to be human, even pickled - perhaps the size of rabbit brains.  The wrinkled grey things bob peacefully around as George carefully pours a measure of the fluid into a shot glass with the help of a funnel.`n`nThe liquid smells a lot like embalming fluid.`n`nTastes like it, too, albeit with a nice alcoholic glow.`n`n");
                    output("You feel `2Energetic!`0`n`n");
                    apply_buff('pub_newpittsburgh_brainhem', array("name" => "`2Brain Hemorrhage Fuzzies", "rounds" => 15, "defmod" => 1.12, "roundmsg" => "Thanks to your Brain Hemorrhage Fuzzies, your defensive movements are more fluid!", "wearoff" => "You feel the effects of the Brain Hemorrhage fade away.", "schema" => "pub_newpittsburgh"));
                    //require_once "modules/staminasystem/lib/lib.php";
                    //addstamina(5000);
                    break;
                case "monstermash":
                    $session['user']['gold'] -= 50;
                    output("George hands you a tall glass filled with artfully-swirled monster grey matter, garnished with a jolly little paper umbrella and a slice of brainstem.`n`n");
                    if ($session['user']['race'] != "Zombie") {
                        output("You take a sip.  It's... honestly, it's awful.  It tastes like a mix of chicken and beef fat, raw eggs, and blood.  Lots of blood.  Not meaning to be impolite you knock the glass back quickly, trying to ignore the cold, semi-solid lumps slowly sliding over your tongue and curling down your throat.`n`n");
                        output("You feel `4Sick and Grumpy!`0`n`n");
                        apply_buff('pub_newpittsburgh_monstermash', array("name" => "`2Monster Mash Grumps", "rounds" => 25, "atkmod" => 1.2, "roundmsg" => "`4The awful Zombie drink makes you feel `\$aggressive!", "wearoff" => "`4You feel the effects of the Monster Mash fade away.  Thank goodness for that.", "schema" => "pub_newpittsburgh"));
                        //require_once "modules/staminasystem/lib/lib.php";
                        //addstamina(5000);
                    } else {
                        output("You down the contents and lick your lips.`n`n");
                        output("You feel `2Energetic!`0`n`n");
                        //require_once "modules/staminasystem/lib/lib.php";
                        //addstamina(10000);
                        increment_module_pref("nutrition", 5, "staminafood");
                        apply_buff('pub_newpittsburgh_monstermash', array("name" => "`2Monster Mash", "rounds" => 25, "atkmod" => 1.2, "defmod" => 1.1, "roundmsg" => "`2The Monster Mash burns warmly in your stomach.  Both your attack and defence are increased!", "wearoff" => "`2The Monster Mash warmth has faded.  Oh well.", "schema" => "pub_newpittsburgh"));
                    }
                    break;
                case "specialsauce":
                    $session['user']['gold'] -= 65;
                    output("George pours you a short glass full of something from a thick blue bottle.  It's the only thing on the menu that doesn't mention brains, though you wonder if the odd blue liquid wasn't distilled from them.  It smells vaguely of formaldehyde, but has enough of a tongue-numbing alcoholic kick that you don't regret ordering it.`n`n");
                    output("You feel `2Warm!`0`n`n");
                    apply_buff('pub_newpittsburgh_specialsauce', array("name" => "`2Special Sauce Warmth", "rounds" => 30, "defmod" => 1.25, "atkmod" => 1.25, "roundmsg" => "That Zombie drink was awesome!  It's like time's slowed down!", "wearoff" => "You feel the effects of the Special Sauce fade away.", "schema" => "pub_newpittsburgh"));
                    break;
            }
            break;
    }
    return $args;
}
function maikopan_run()
{
    global $session;
    switch (httpget('step')) {
        case 1:
            page_header("What's going on at Maiko's Cookery Academy?");
            output("You open the door to Maiko's cookery school, catch a flash of silver metal screaming towards you, and step smartly to your left.  The boning knife embeds itself in the door with a heavy wooden `ithunk`i and vibrates, merrily wibbling back and forth in its new home.  You tear your eyes away from it and towards Maiko, who now stands in the centre of a storm of cookery equipment, her chest heaving, her hair frowzled, her irises tiny green rings around pitch black pits.  Each inhalation snarls through her sinuses, her exhalations expelling little spots of hot saliva.`n`nYou speak very quietly, and very carefully.  \"`#Maiko, what's wrong?`0\"`n`nShe snarls, and begins to stride towards you.  She barely comes up to your shoulders, but you feel a very urgent, very pressing need to get the hell out of her way.  You step again, this time to the right, and she yanks the boning knife out of the door and turns to you.`n`n\"`%Someone stole my frying pan,`0\" she says almost conversationally.`n`nYou look at her carefully.  \"`#Someone stole your frying pan?  That's what this is...`0\"`n`n\"`%IT'S A REALLY.  GOOD.  FRYING.  PAN.`0\"  You're not sure whether Maiko even realises that she's punctuating her words with little stabbing motions.  \"`%MY.  FAVOURITE.  ONE.`0\"`n`n\"`#Okay!`0\" you say, hands upraised palm-out, not noticing that you're backing up.  \"`#Okay, I can help you look for it, I can go out and...`0\"`n`n\"`%And WHAT?  You want to go `ifind`i it for me?!  What the hell do you think this is, a `ifetch quest?`i`0\"  Droplets of hot, mad saliva spatter on your face.  \"`%You, you, you big `istrong`i %s`%, you gonna stride off into the Jungle and find the treasured trinket for the poor helpless lady who `ican't do a damned thing for herself?  WELL BLOODY SOD THAT!`i`0\"  She slips the knife into a holster on her ankle, turns, picks up a meat cleaver as long as your arm, and heads for the door.  \"`%I'm perfectly capable of finding my `iown`i damn pan, THANK YOU `iVERY`i MUCH!`0\"`n`nThe door slams shut, the glass rattling in the windows.`n`nYou stand for a second in the sudden silence, surveying the strewn-about silverware.  It seems impossible that all of these things were in their places, as recently as this morning.`n`nSomewhere in the room, a radio crackles into life with a `\$familiar`0 voice.  \"`&%s`&, it's `\$me`&.  Pick this up if you can.`0\"`n`nYou gingerly tiptoe towards where the sound probably came from, stepping between knives and over pans.  \"`&%s`&, come in, over here.  Just follow the sound of my voice.  God I hope this radio is working...`0\"`n`nYou find the radio on the floor underneath a large black wok.  You kneel down to reach the mic.  \"`#I'm here.`0\"`n`n\"`&Right, then.  I only tuned in a few minutes ago, and this camera's a bit f****d-up.  Am I to understand that Maiko's favourite frying pan has gone walkies?`0\"`n`n\"`#That's the situation, yeah.`0\"  You look around at the chaos.  \"`#She's a bit upset about it.`0\"`n`n\"`&So I gather.  Mate, I need you to go and get that frying pan for her.`0\"`n`nYou shake your head.  \"`#That's a bad idea.  Did you hear what she said?`0\"`n`nThe Watcher speaks slowly.  \"`&Ye-es, and in fact I agree with her.  Maiko `iis`i a strong, independent woman, and `ivery much`i capable of finding her own pan, just like she said.`0\"`n`n\"`#So, should I stay here and try to clean the place up a bit?`0\"`n`n\"`&No, you should go and find whoever took the pan `ibefore Maiko does,`i or at the very least, bloody `iwarn`i them that she's coming, because Maiko is...`0\"  `\$The Watcher`0 thinks for a second.  \"`&I like Maiko, love her to bits, and that's why I'm choosing my words `ivery, very politely indeed...`i  Maiko is a strong, independent woman who is very much capable of finding her own pan.  Finding her own pan `iwith extreme prejudice.`i  Sudden character changes don't make for good television.  I've been trying to show her cute side to the cameras, because... well, you know what television viewers are like, they're not fans of change.  They won't want to see her slicing some poor Midget's bollocks off and wearing them as a hat.`0\"`n`nYou sigh.  \"`#Understood.`0\"`n`n\"`&Try to get it back without bloodshed.  No harm, no foul.`0\"`n`n\"`#Hey, `\$Watcher?`0\" you say.  \"`#What's your name?  I can't really keep going on calling you `\$Watcher`#, it doesn't feel right.`0\"`n`n\"`&Yeah, it's...`0\"`n`nThere's a very, very long pause.`n`n\"`&We don't have time for this right now.  Maiko's on the warpath.  Get out there and stop her from really, `ireally`i hurting someone.`0\"`n`nThe radio crackle dies to silence in your hand.`n`nYou stand up.  Over and out.`n`nLooks like you've got a pan to find.`n", $session['user']['name'], $session['user']['name'], $session['user']['name']);
            set_module_pref("plotpoint1", 1);
            addnav("Continue");
            addnav("Exit to Kittania", "village.php");
            break;
        case 2:
            page_header("Something Improbable!");
            output("As you head into The Sunny Spot, you pass a young KittyMorph on his way out.  As hard as it is to tell the age of KittyMorphs, you peg him at about nineteen, twenty - he's wearing a backpack and what looks like a revolver of some kind stuck into his bandolier, and he seems familiar.  The grey fur over his hands is marred by what looks very, very much like burnt-black grease.  Like you might find on, say, an old and much-loved frying pan.`n`nHe seems familiar because he's been showing up to Maiko's cookery class for the past couple of weeks.`n`nYou collar the KittyMorph and spin him around to face you.  Confused, bright red eyes look up into yours.`n`n\"`#Know anything about a frying pan?`0\"`n`nThe young man stares up at you, opens and closes his mouth once or twice.  \"`4Well... yeah, I do.`0\"`n`n\"`#Well, you're bloody lucky I found you first, 'cause Maiko's frothing at the mouth.`0\"`n`nHis eyes, impossibly, widen even further.  \"`4Really?`0\"`n`n\"`#Carrying a meat cleaver as big as my arm,`0\" you say conversationally.  \"`#In a real black mood.`0\"`n`n\"`4Oh, Jesus!`0\"  The young man's eyes start to water.  \"`4That wasn't supposed to happen!`0\"`n`n\"`#Look,`0\" you say kindly, \"`#we all make mistakes.  Just...`0\"  You blink as a minor detail, casually stored away for evaluation at a later point when you're not so busy, bubbles up to the front of your mind.  You look down.`n`nYou look up again.  \"`#Frilly pink panties?  Seriously?`0\"  You shake your head at the young man.  \"`#Not been here long, have you?  Look, just give me the pan and we'll say no more about it, all right?`0\"`n`n\"`4I don't have it!`0\"`n`nYou sigh.  \"`#Of course you don't.  I know how this works.  You sold it, right?`0\"`n`n\"`4No!`0\"`n`n\"`#No?`0\"`n`n\"`4No, Sheila's got it!`0\"`n`nYou frown.  \"`#Sheila in Kittania?  As in, Sheila's Shack?  She knows Maiko.  She wouldn't put her pan up for sale as a weapon.`0\"`n`n\"`4Exactly!  I took it to Sheila and paid her to restore it!  Reseal the metal, polish it up like new, you know!  It was supposed to be a surprise!  I just came in here for a quick pint while she sorted it!`0\"`n`nYou grip the young man's shoulders, and bring him close to you.  \"`i`#What.`0`i\"`n`n\"`4Restoration job,`0\" whimpers the young KittyMorph, his eyes clearly brimming up now.  \"`4Sheila works with metal, she knows how to do it!  Take off all the years of grease.  New coating.  Good as new, she said!`0\"`n`n\"`#Oh, no...`0\" you whisper, letting go of the young man's shoulders and looking past him, into the middle distance.  You ponder for a moment Maiko's reaction to such a revelation.  It could be even worse than having the pan stolen.`n`n\"`#What's your name?`0\" you say quietly.`n`n\"`4Akira,`0\" sniffles the young man.`n`n\"`#It doesn't suit you.  You ever heard the expression, 'The blacker the wok, the better the cook?'`0\"`n`nYou didn't think Akira's eyes could widen further.  You were wrong.`n`n\"`#I don't think Sheila knows that one, either.  We've got to get it back,`0\" you say.  \"`#Fast.`0\"`n`nAkira nods vigorously.`n`nAs one, you break into a run.");
            addnav("Damn it.");
            addnav("Run back to Sheila's, quick!", "runmodule.php?module=maikopan&step=3");
            break;
        case 3:
            page_header("Sheila's Shack");
            output("You burst into Sheila's Shack, throw yourself onto the counter, and gasp up at her.`n`n\"`#Have you got Maiko's pan?`0\"`n`n\"`6And g'day to you too, mate,`0\" says Sheila.  She looks past you at Akira, standing sheepishly in the doorway.  \"`6'ere, what's going on?  Didn't young Akira here drop it off just recently?  Picked 'imself up something to cover up his nethers at last, too, if I recall.  Looking good, by the way.`0\"`n`n\"`4I made a mistake,`0\" says Akira.`n`n\"`6I couldn't disagree more,`0\" smiles Sheila, leaning over the counter and glancing down.  \"`6I think they suit you just right.  Go on, give us a twirl.`0\"`n`n\"`4No, it's about the pan.  You can keep the money, I just - I need it back, very urgently!`0\"`n`nSheila gives Akira an equally sheepish look.  \"`6You mean the one with the chrome handle, yeah?  With the little recessed heat-treated cherry wood accents?  Well, y'see, here's the thing...`0\"`n`nBoth you and Akira groan.`n`n\"`6The chrome was knackered, right!  All pitted with rust!  So I sent the handle off to me sister, Sheila, up in Cyber City, she was gonna give it a bath in oxalic acid - lovely stuff for chrome, takes the rust right off, the Robots love it...`0\"`n`n\"`#You `idismantled`i it?`0\" you moan.`n`n\"`6Right, and the screws holding the handle together were all rusty and the threads were pretty much gone, so I had a look through me selection for a good match, only I couldn't find one the right thread, yeah?  It's pretty old, an' all I've got is metric.  So I calls up me sister Sheila on the radio, and she might have some old feet-an'-inches ones, so I sent the screws off to 'er in Pleasantville, see if she could find a match for 'em...`0\"`n`n\"`4Oh, no!`0\" cries Akira.`n`n\"`6Well `istrewth`i, lad, it was that or re-thread the holes, an' you said you wanted it like new!  An' the wooden pieces, right, me sister Sheila was always the woodworker in our family, so they've gone back to her in NewHome for refinishin'...`0\"`n`n\"`4I can't believe it's in all these different places!`0\"`n`n\"`#`iI`i can't believe that all the other Sheilas are your `isisters.`i`0\"`n`n\"`6Why did you think we all looked the same?  You think I just follow you around the whole Island, setting up shop wherever you happen to be?  Anyway, the actual bowl part, well,`0\" says Sheila, grinning, \"`6It's here, attached to the 'andle with the screws.`0\"  She lifts up the frying pan.`n`nYou both stare.`n`n\"`6Had you goin', didn't I?`0\" she winks.  \"`6Chasin' all over the Island like that, pickin' up all the different little bits... would've just padded things out pretty pointlessly, don'tcha think?  Here.`0\"  She hands the pan over to you.  \"`6Good as new.  What d'you reckon?`0\"`n`nYou handle the pan carefully.  It's bright, and shiny, and lifeless.  \"`6I had to take me angle grinder to it to get the worst of it off,`0\" says Sheila.  You run your fingers gently over the inside of the bowl - it's as smooth as an unused soul.  \"`6Then I took some polishin' compound an' buffed out all the scratches.  You can see yer face in it, look.`0\"  The memories have been scoured from this pan, Maiko's love dissolved in a bath of oxalic acid.  \"`6I 'ad no idea the metal were that bright underneath.  It's a beaut!  And the stuff that came off it, `istrewth!`i`0\"  You contemplate the years of loving use, years of happy experimentation, the flavours of ten thousand carefully-prepared meals - the experience that took Maiko from an amateur cook to a professional chef.  Irreplacable memories.  \"`6Anyway, it's all gone now, an' it's good as new.`0\"`n`nYou force yourself to smile as convincingly as you can, and look from the dead pan up to Sheila.  \"`#It looks great.  Like it just came out of the factory.  You did great work.`0\"`n`nSheila grins back.  \"`6I try me hardest.`0\"");
            addnav("Now what?");
            addnav("Continue", "runmodule.php?module=maikopan&step=4");
            break;
        case 4:
            page_header("Outside Sheila's Shack");
            output("The pair of you trudge out of Sheila's Shack.  Akira is visibly trembling.  Still looking at the pan in your hand, he says in a voice so small the wind nearly blows it away:`n`n\"`4What are we going to do?`0\"`n`nYou sigh, looking down at the pan.  \"`#I don't think,`0\" you say slowly and quietly, turning the pan over to look at the other side, buffed to a mirror finish, \"`#that there's anything we `ican`i do.`0\"  There's not a single speck of Maiko left in that pan.`n`nAkira looks at the ground.  You look over towards him, then look away again, not sure whether he would want to be seen in that condition.`n`n\"`#Either way,`0\" you continue, more for something to say than anything else, \"`#Maiko's still out there, convinced that someone's stolen her pan.  We have to get to her before she starts cracking heads together.`0\"`n`nAkira mumbles something.`n`n\"`#Say again?`0\"`n`n\"`4Squat Hole,`0\" he says, glancing over to you but not meeting your eyes.  \"`4She'll have suspected the Midgets.  I don't think there's anyone in Kittania stupid enough to want to take her favourite pan.`0\"  He looks away again.  \"`4'cept me, of course.`0\"`n`n\"`#You had good intentions, Akira.`0\"`n`n\"`4I could make a comment about a certain road,`0\" says Akira, reaching into his backpack - \"`4but it's kind of redundant, and we're on a deadline.  I've got a one-shot teleporter.`0\"  He looks up at you.  The fur around his eyes is dark, and damp.  He holds out the teleporter.  \"`4Would you come wi... um.  No, I guess it's my responsi...`0\"`n`n\"`#Oh, for goodness' sake, kid,`0\" you sigh, grabbing his hand and smacking the button.  The teleporter, blackened and smoking, falls to the ground.");
            addnav("Continue");
            addnav("Into Squat Hole", "runmodule.php?module=maikopan&step=5");
            break;
        case 5:
            page_header("Squat Hole");
            output("You arrive with a flash of light and pain in Squat Hole.`n`nIt's surprisingly quiet.`n`n\"`%Now, boys, if we can all just sit quietly,`0\" says a sweet, quiet, but very teacher-like voice somewhere nearby, \"`%and you can tell me - and Mister Cleaver here too, of course -`0\" she giggles, low and dangerous - \"`%which one of you arse-scratching, nose-picking, knee-kicking, snot-swallowing, shit-gargling, goat-f*****g, BNP-voting little toerags -`0\" she pauses, and takes a breath - \"`%has my most precious frying pan?`0\"`n`n\"`#At least she didn't take much finding,`0\" you say to Akira, breaking into a run.`n`nAs you both round the corner, Maiko stands facing a dozen or so remarkably well-behaved Midgets, with her back to you.  A hair's-breadth of time passes between her facing away from you, and facing towards you, the cleaver inches from your face.  You both stop in your tracks.`n`n\"`%Hello Akira,`0\" says Maiko.  \"`%How goes the SpiderKitty leg stew?  And I can see your reflection in my cleaver, you know.`0\"  Behind her, the two Midgets who had stood up, sit back down again with a `isquelch`i.`n`n\"`4It goes pretty well, miss,`0\" says Akira.  \"`4But...`0\"`n`nMaiko sees the damp patches on Akira's cheeks, and her brow creases in an expression of concern.  \"`%What's wrong, Akira?`0\"`n`nWordlessly, Akira holds up the pan.`n`nMaiko's eyes flick down to it, back up to Akira's eyes with a puzzled, querying look, back into her cleaver to check on the Midgets - then, in sudden recognition, they widen, swivel back down to the pan, and stay there.`n`nMaiko's cleaver lowers very gently, as you watch something breaking inside her.  You find yourself wanting very badly to look away, but she's still full of adrenaline, and the cleaver is still in her hand, still sharp.`n`n\"`4I'm sorry, I -`0\" stutters Akira.  \"`4I didn't know, miss.  I took it and had it restored, I thought it'd be a nice surprise.  I didn't know it'd...`0\" he chokes on the words.  You can't blame him.  Saying `i`4I didn't know it would kill it`0`i seems at once both silly and far too true.`n`nThe tip of Maiko's cleaver touches the ground.  The Midgets behind her scatter and disappear so quickly you barely see them move.`n`nShe holds out the hand not holding the cleaver.  Grips the handle of the pan, takes it gently from Akira.`n`nHer eyes screw tightly shut, and she trembles, looking down at the ground.  She breathes out once, through her mouth, and then in, shuddery, through her nose.  She flicks her eyes open, looks Akira in the eye, and says \"`%Thank you.`0\"  A tear soaks into the sandy fur beneath her left eye.  \"`%Nobody else remembered my birthday.`0\"`n`nAkira winces.  So do you.`n`nMaiko notices, and winces herself.  `n`nThe world is very, very still, for a moment.`n`n\"`%You...  You didn't know either, did you?`0\" says Maiko.  \"`%You've only been coming to class a couple of weeks.  You can't have known.`0\"`n`nAkira's lips press tightly together.  Wordlessly, he shakes his head.`n`n\"`%You just did this because you thought it'd be something nice,`0\" says Maiko.  \"`%You didn't even do it for an occasion.`0\"  The tip of her gargantuan meat cleaver draws a razor-sharp line in the dirt as she takes a step towards Akira.  Still holding the cleaver in one hand and the pan in the other, she very slowly, very gently wraps her arms around Akira.`n`nAkira hugs back, carefully.  \"`4I'm sorry,`0\" he whispers.  \"`4I'm so, so sorry.`0\"`n`n\"`%Shush,`0\" mutters Maiko.  \"`%It's just a `ithing.`i`0\"`n`n\"`4It's not, though, is it?`0\" mumbles Akira.`n`nMaiko chuckles softly.  \"`%You're sweet.  I'm sure as I get to know you, you'll f**k up in other charming ways.`0\"  She pulls back, her smile disappearing.  \"`%You're right, it's `inot`i just a thing,`0\" she says quietly, looking down at the shiny, dead pan.  \"`%Well.  It is `inow`i, yes.`0\"  Her eyes brim with tears again.  \"`%I really don't know what to say, I...`0\"  She bites her bottom lip and blinks up at the sky, sniffing and visibly trying not to break down further.  \"`%I `iloved`i that thing, I didn't realise `ihow much`i I loved it, I didn't realise how much it was a `ipart`i of...  And you're so sweet, and so considerate, and so `ibloody stupid,`i you... `iyou`i...`0\" she exhales in a sob as Akira takes a quick step back.  \"`%I'm sorry, that was cruel, I'm just...  I think I'd better just put this cleaver `idown,`i for now, I think...`0\"`n`nThe cleaver clatters to the ground, and you exhale.`n`n\"`%You... `iyou...`i`0\"  She exhales, slowly, calms herself.  \"`%You,`0\" she whispers, eyes closed.  She smiles weakly, opens her eyes, looks at Akira.  \"`%I'd set you on dishwashing duty as punishment, but you might do it too well.`0\"`n`nAll three of you laugh, nervously - not because it was funny, but because it was an invitation to break the tension.`n`nMaiko steps towards Akira.  She puts the pan down on the ground, raises a hand and clips him roughly around the ear.  As he recoils, she raises her other hand and affectionately ruffles his hair.  She picks the pan up, and gently bops him on the back of the head.  The pan makes a hollow `ibong.`i  Then she stands on tiptoes and kisses him on the cheek, and says \"`%Let's go home.`0\"`n`nSniffling but clearly relieved, Akira picks up Maiko's cleaver, and the three of you start walking, in silence, back towards Kittania.");
            addnav("Continue");
            addnav("Begin the journey back", "runmodule.php?module=maikopan&step=6");
            break;
        case 6:
            page_header("The Road Home");
            output("It's a long time before anyone says anything.`n`n\"`%Quiet out, isn't it?`0\" Maiko says, quietly.`n`n\"`#Aye,`0\" you say.  \"`#Very quiet.`0\"`n`n\"`4Yes,`0\" says Akira.`n`nAnd then, silence again.  Your footsteps continue for a few minutes.`n`n\"`%I've been thinking,`0\" says Maiko.  And then stops talking.`n`n\"`#Oh?`0\" you say, after a few seconds.`n`n\"`%Yes.  I've been thinking about... things.  You know, material `ithings.`i  About the things you own owning you.  And about how strange it is that people say 'the road to Hell is paved with good intentions,' but they also say 'two wrongs don't make a right.'  And...`0\" she chews on her lip for a moment.  \"`%And about my pan.  Of course.`0\"  She looks down at it, in her hand, turning it this way and that.  \"`%I think us KittyMorphs probably feel differently about our things than other races do, humans in particular.  Mutants too, I'd imagine.`0\"  She looks over towards you.  \"`%Not to perpetuate stereotypes, but I think we tend to own fewer things, but love them more.`0\"`n`nYou mull it over for a moment.  \"`#Broadly speaking,`0\" you say, \"`#and going only from personal experience...  I think you might be right.`0\"`n`n\"`4I think so too,`0\" says Akira.`n`nMaiko nods, and the three of you carry on in silence for another minute or so.`n`n\"`%Of course,`0\" she says, breaking the silence, \"`%I suppose it's kind of silly to love things at all.`0\"`n`n\"`4I don't know,`0\" says Akira.  \"`4I don't think it's silly.  I mean, I've got some things that my friends gave to me, and I love those things.`0\"`n`n\"`%You love your `ifriends`i,`0\" says Maiko.  \"`%The things they give you just act as a...  I don't know, like a `iconductor`i for the memories.  And for the love.  Take away the thing, the love's still there.  The thing just... `igrounds`i it, I suppose.  Anchors it, in a place that you can see, and touch.  Keeps it all together.`0\"`n`n\"`4Gives it a home,`0\" says Akira.`n`nA bespectacled face appears from a nearby bush.  Maiko swings her pan.`n`n\"`5Hello, I'm a professional romance wri-`0\" `b`iSPANG`i`b \"`5`i-tuuuh...`i`0\"`n`nMaiko smiles.  \"`%Oh, you had the screws re-threaded!  That's `imuch`i better.  The handle's been a bit wobbly for a while, now.`0\"  `n`nAkira chuckles as the creature slowly crumples to the ground.  \"`4Well, `isome`i good came of my bone-headedness, then.`0\"`n`nMaiko looks down at the pan.  \"`%Yeah,`0\" she says, a small grin still lingering.`n`nSome more walking.  Some more silence.`n`nEventually, you have to ask.  \"`#Why didn't you let anyone know your birthday was coming up?`0\" `n`nMaiko shrugs.  \"`%Didn't really know whether or not I wanted to celebrate it.  Forty-nine is a weird one, like that.  It's, like, 'Okay, I'm `inot quite`i fifty, but I'm not quite used to the `iidea`i of being fifty yet.'  I don't know if that makes much sense.  I regret not telling people, anyway.  Usually I just go with celebrating everything that comes my way, because I always regret it afterwards if I don't.`0\"`n`nYou nod.  \"`#Sounds familiar.`0\"`n`nAkira looks confused, but doesn't say anything.  He looks over to you, wide-eyed, and mouths something silently.`n`n`4`iForty-nine?  Really?`i`0`n`nYou shrug, and nod back to him.  `3`iYeah, I know.`i`0`n`nIt's a long walk back to Kittania.");
            addnav("Continue");
            addnav("Enter Kittania", "runmodule.php?module=maikopan&step=7");
            break;
        case 7:
            page_header("The Road Home");
            output("After a long, quiet, somewhat awkward walk, the three of you are back in Kittania once again.`n`n\"`%Well,`0\" says Maiko.  \"`%Here we are.`0\"`n`nAkira snuffles his feet.  Maiko stands with her pan slightly raised.  The three of you look at each other for a second or so.`n`nYou get the feeling that Maiko doesn't want to be alone right now.  You also get the feeling that she doesn't want to draw attention to that.`n`n\"`#Does anyone fancy,`0\" you say, in a slow, musing fashion, slowly bringing your finger up as if to make a point - \"`#a pint?`0\"  You let your eyes drift upward along the line of your finger, towards the Sunny Spot, then drop them back down to your companions.`n`nThey glance at each other, then back to you.`n`n\"`%Yeah,`0\" says Maiko, beginning to walk in that direction.`n`n\"`4Yeah,`0\" says Akira, following her.`n`n\"`i`#Yeah,`0`i\" you grin.`n`n\"`%After you,`0\" says Maiko to Akira, at the base of ladder.  He sets his foot and begins to climb.`n`nMaiko looks up.  She notices you noticing her looking up, and blushes.  \"`%I don't know `ihow`i Sheila talked him into those,`0\" she says, quietly but with a smile, before gripping her pan in her teeth and heading upwards.`n`nYou chuckle to yourself, grip the ladder, and begin to ascend into the shade, then the warmth, then the familiar, heavy scents of beer and tobacco, and the sound of laughter.");
            addnav("Drink and be merry.");
            addnav("It is a new day.", "runmodule.php?module=maikopan&step=8");
            break;
        case 8:
            $body = "The audience loved what you did, there.  Next time, don't try to shoehorn a moral into the story, huh?  It didn't really work, and it left some viewers blinking owlishly at their televisions.  Also, if you're going to do a big dramatic buildup like that, you've got to get some violence going.  Or try to crowbar in a bit of nookie.  Personally I don't think Maiko and Akira will come to anything - they might flirt a bit just 'cause tension works in funny ways sometimes, but I don't think either of them will make a move.  Perhaps next time we'll get a romantic subplot going.  Viewers like that sort of thing.`n`nI dunno what to make of Akira, myself.  I don't know whether he's hot for teacher, or genuinely thoughtful, or just a wee bit simple.  Mind you, I can't honestly imagine Sheila of all people flirting with him quite `ithat`i outrageously if the third option were true.  Keep an eye on him for me, would you?`n`nBut, on the whole, great job!  You did wonderfully, and I thank you for it.`n`n-Wotcha`n`nPS: About what you asked me - I think it begins with an S.";
            require_once "lib/systemmail.php";
            systemmail($session['user']['acctid'], "Wow.", $body, 3517);
            set_module_pref("plotpoint2", 1);
            redirect("newday.php");
            break;
    }
    page_footer();
}
function hunterslodge_customarmour_run()
{
    require_once "lib/sanitize.php";
    require_once "lib/names.php";
    global $session;
    $op = httpget("op");
    $free = httpget("free");
    page_header("Choose your Custom Armour");
    switch ($op) {
        case "change":
            output("Want to change your Custom Armour?  No problem.  Enter your desired armour in the box below.  You've got 25 characters to play around with.`n(leave this blank to disable custom armour naming and return to default, game-supplied armour names)`n`n");
            rawoutput("<form action='runmodule.php?module=hunterslodge_customarmour&op=confirm&free=" . $free . "' method='POST'>");
            $armour = get_module_pref("customarmour");
            rawoutput("<input id='input' name='newarmour' width='25' maxlength='25' value='" . htmlentities($armour, ENT_COMPAT, getsetting("charset", "ISO-8859-1")) . "'>");
            rawoutput("<input type='submit' class='button' value='Preview'>");
            rawoutput("</form>");
            addnav("", "runmodule.php?module=hunterslodge_customarmour&op=confirm&free=" . $free);
            addnav("Cancel");
            addnav("Don't set custom armour, just go back to the Lodge", "runmodule.php?module=iitems_hunterslodge&op=start");
            break;
        case "confirm":
            $newarmour = httppost("newarmour");
            $sub = httpget("sub");
            $newarmour = str_replace("`", "", $newarmour);
            $newarmour = comment_sanitize($newarmour);
            $newarmour = substr($newarmour, 0, 25);
            if ($newarmour) {
                output("Your new custom armour is:`n%s`nWould you like to set your new armour now?`n`n", $newarmour);
            } else {
                output("You've chosen to go back to the default, game-supplied armours.  Are you sure that's what you want?`n`n");
            }
            addnav("Confirm");
            addnav("Set custom armour", "runmodule.php?module=hunterslodge_customarmour&op=set&free={$free}&newarmour=" . rawurlencode($newarmour));
            addnav("Cancel");
            addnav("Don't set custom armour, just go back to the Lodge", "runmodule.php?module=iitems_hunterslodge&op=start");
            break;
        case "set":
            $newarmour = rawurldecode(httpget("newarmour"));
            if ($newarmour == "") {
                output("Your custom armour name has been removed.  The next time you change your armour, you'll return to game-supplied armour names.`n`n");
            } else {
                output("Your custom armour has been set to %s!`n`n", $newarmour);
                $session['user']['armor'] = $newarmour;
            }
            set_module_pref("customarmour", $newarmour);
            if (!$free) {
                require_once "modules/iitems/lib/lib.php";
                $id = has_item("hunterslodge_customarmour");
                delete_item($id);
            }
            addnav("Return");
            addnav("Return to the Lodge", "runmodule.php?module=iitems_hunterslodge&op=start");
            break;
    }
    page_footer();
}
function lights_out_run()
{
    global $session;
    page_header("Lights Out!");
    addnav("O?Back to the Outpost", "village.php");
    //playtesting
    $numlights = 9;
    $lightsperrow = 3;
    $startlights = 5;
    $maxchangesperlight = 4;
    switch (httpget('op')) {
        case "start":
            $lights = array();
            for ($lamp = 1; $lamp <= 9; $lamp++) {
                $lights[$lamp]['status'] = 0;
                $numberofchanges = e_rand(2, 4);
                $lampstochange = array(1 => "1", 2 => "2", 3 => "3", 4 => "4", 5 => "5", 6 => "6", 7 => "7", 8 => "8", 9 => "9");
                unset($lampstochange[$lamp]);
                $switches = array();
                for ($c = 1; $c <= $numberofchanges; $c++) {
                    $sw = array_rand($lampstochange);
                    $switches[] = $sw;
                    unset($lampstochange[$sw]);
                }
                $lights[$lamp]['changes'] = $switches;
            }
            debug($lights);
            //Now randomly poke some lights
            for ($i = 1; $i <= $startlights; $i++) {
                $sw = e_rand(1, $numlights);
                $lights = lights_out_switch($sw, $lights);
            }
            $spref = serialize($lights);
            set_module_pref("lights", $spref);
            $moves = 0;
            $jackpot = 200;
            lights_out_show($lights, $moves, $jackpot);
            break;
        case "switch":
            $moves = httpget('moves');
            $moves++;
            $jackpot = httpget('jackpot');
            output("Current jackpot: %s`n", $jackpot);
            $lights = lights_out_switch(httpget('switch'));
            $jackpot += 5;
            lights_out_show($lights, $moves, $jackpot);
            $lit = lights_out_check($lights);
            if (!$lit) {
                output("Congratulations!  You won %s Req, for your stake of %s!", $jackpot, $moves * 10);
            } else {
                output("There are %s lights left to turn off.  You have made %s moves.`n", $lit, $moves);
            }
            break;
    }
    page_footer();
}
function creatureaddon_run()
{
    global $session, $args;
    $op = httpget('op');
    $header = $args['creaturename'] . " Description";
    popup_header($header);
    $description = get_module_objpref("creatures", $args['creatureid'], "description");
    output($description);
    popup_footer();
}
function dwellingseditor_run()
{
    global $session;
    tlschema("dwellingseditor");
    $op = httpget('op');
    if ($op != "lookup") {
        page_header("Dwellings Editor");
    }
    addnav("Navigation");
    addnav("Back to the Grotto", "superuser.php");
    if ($op != "") {
        addnav("Dwelling List", "runmodule.php?module=dwellingseditor");
    }
    addnav("Find Dwellings by User", "runmodule.php?module=dwellingseditor&op=usersearch");
    addnav("Operations");
    if ($op != "typsu") {
        addnav("Type Pref Editor", "runmodule.php?module=dwellingseditor&op=typesu");
    }
    modulehook("dwellingseditor-main");
    $typeid = httpget("typeid");
    $dwid = httpget('dwid');
    $type = httpget("type");
    if ($type == "" && $dwid > 0) {
        $sql = "SELECT type FROM " . db_prefix("dwellings") . " WHERE dwid={$dwid}";
        $result = db_query($sql);
        $row = db_fetch_assoc($result);
        $type = $row['type'];
    }
    if ($dwid > 0) {
        addnav("Operations");
        if ($op != "edit") {
            addnav("Edit Dwelling Details", "runmodule.php?module=dwellingseditor&op=edit&dwid={$dwid}");
        }
        if ($op != "keys") {
            addnav("Manage Keys", "runmodule.php?module=dwellingseditor&op=keys&dwid={$dwid}");
        }
        if ($session['user']['superuser'] & SU_EDIT_COMMENTS) {
            addnav("Moderate Commentary", "moderate.php?area=dwellings-{$dwid}&dwid={$dwid}");
        }
        if ($op != "delete") {
            addnav("Delete this Dwelling", "runmodule.php?module=dwellingseditor&op=delete&dwid={$dwid}");
        }
        modulehook("dwellingseditor", array("dwid" => $dwid));
        addnav("Navigation");
        if ($op != "coffers") {
            addnav("Coffer Log", "runmodule.php?module=dwellingseditor&op=coffers&dwid={$dwid}");
        }
        if ($op != "dwsu") {
            addnav("Dwelling  Viewer", "runmodule.php?module=dwellingseditor&op=dwsu&dwid={$dwid}");
        }
    }
    require_once "modules/dwellingseditor/case_{$op}.php";
    page_footer();
}
function marriage_run()
{
    global $session;
    require_once "modules/marriage/marriage_func.php";
    $op = httpget('op');
    if ($op == '' || $op == 'chapel' || $op == 'oldchurch') {
        require "./modules/marriage/general.php";
    } else {
        require "./modules/marriage/{$op}.php";
    }
}
function mapchat_run()
{
    global $session;
    $xyz = httpget('xyz');
    page_header("Tent!");
    output("There's a tent here!");
    require_once "lib/commentary.php";
    addcommentary();
    viewcommentary("worldmap" . $xyz, "Map Chat!", 25);
    addnav("Go Back", "runmodule.php?module=worldmapen&op=continue");
    page_footer();
}
function handle_event($location, $baseLink = false, $needHeader = false)
{
    if ($baseLink === false) {
        global $PHP_SELF;
        $baseLink = substr($PHP_SELF, strrpos($PHP_SELF, "/") + 1) . "?";
    } else {
        //debug("Base link was specified as $baseLink");
        //debug(debug_backtrace());
    }
    global $session, $playermount, $badguy;
    $skipdesc = false;
    tlschema("events");
    $allowinactive = false;
    $eventhandler = httpget('eventhandler');
    if ($session['user']['superuser'] & SU_DEVELOPER && $eventhandler != "") {
        $allowinactive = true;
        $array = preg_split("/[:-]/", $eventhandler);
        if ($array[0] == "module") {
            $session['user']['specialinc'] = "module:" . $array[1];
        } else {
            $session['user']['specialinc'] = "";
        }
    }
    $_POST['i_am_a_hack'] = 'true';
    if ($session['user']['specialinc'] != "") {
        $specialinc = $session['user']['specialinc'];
        $session['user']['specialinc'] = "";
        if ($needHeader !== false) {
            page_header($needHeader);
        }
        output("`^`c`bSomething Special!`c`b`0");
        if (strchr($specialinc, ":")) {
            $array = split(":", $specialinc);
            $starttime = getmicrotime();
            module_do_event($location, $array[1], $allowinactive, $baseLink);
            $endtime = getmicrotime();
            if ($endtime - $starttime >= 1.0 && $session['user']['superuser'] & SU_DEBUG_OUTPUT) {
                debug("Slow Event (" . round($endtime - $starttime, 2) . "s): {$hookname} - {$row['modulename']}`n");
            }
        }
        if (checknavs()) {
            // The page rendered some linkage, so we just want to exit.
            page_footer();
        } else {
            $skipdesc = true;
            $session['user']['specialinc'] = "";
            $session['user']['specialmisc'] = "";
            httpset("op", "");
        }
    }
    tlschema();
    return $skipdesc;
}