function improbablehousing_getnearbyhouses($loc)
{
    global $session;
    //$sql = "SELECT hid,ownedby FROM " . db_prefix("buildings") . " WHERE location = '$loc'";
    $sql = "SELECT * FROM " . db_prefix("buildings") . " WHERE location = '{$loc}'";
    $result = db_query_cached($sql, "housing/housing_location_" . $loc);
    //$result = db_query($sql);
    //todo: cache this query, or rather, invalidate the cache properly after staking a claim
    $n = db_num_rows($result);
    //debug($n);
    if (!$n) {
        return null;
    } else {
        $r = array();
        for ($i = 0; $i < $n; $i++) {
            $row = db_fetch_assoc($result);
            $house = improbablehousing_gethousedata($row['hid']);
            $r[] = $house;
        }
    }
    return $r;
}
function improbablehousing_furnitureshop_run()
{
    global $session;
    page_header("Cadfael's Furniture");
    //have the beds and such allowed to be carried in backpack (insert suitable hundred-kilo-bed-in-backpack-lols) or carried by a secondary character in a new Inventory space (we'll call it Delivery Boy - will need a suitably silly photo).
    switch (httpget('op')) {
        case "start":
            output("Cadfael greets you with a preposterously strong Welsh accent.  \"`3Well hey there!  Take a look around, all one 'undred per cent natural and me own work!`0\"`n`n");
            //find items that are furniture!
            $furniture = get_items_with_settings("furniture");
            //debug($furniture);
            usort($furniture, 'sortbyprice');
            rawoutput("<table width=100% style='border: dotted 1px #000000;'>");
            foreach ($furniture as $sort => $vals) {
                $key = $vals['item'];
                $classcount += 1;
                $class = $classcount % 2 ? "trdark" : "trlight";
                rawoutput("<tr class='{$class}'><td>");
                if ($vals['image']) {
                    rawoutput("<table width=100% cellpadding=0 cellspacing=0><tr><td width=100px align=center><img src=\"images/items/" . $vals['image'] . "\"></td><td>");
                }
                output("`b%s`b`n", stripslashes($vals['verbosename']));
                output("%s`0`n", stripslashes($vals['description']));
                if ($vals['weight']) {
                    output("Weight: %s kg`n`0", $vals['weight']);
                }
                rawoutput("<table width=100%><tr><td width=50%>");
                if ($vals['goldcost'] && $vals['gemcost']) {
                    $disp = "`b" . number_format($vals['goldcost']) . "`b Requisition and `b" . number_format($vals['gemcost']) . "`b Cigarettes";
                    $sdisp = $vals['goldcost'] . " Req, " . $vals['gemcost'] . " Cigs";
                } else {
                    if ($vals['goldcost']) {
                        $disp = "`b" . number_format($vals['goldcost']) . "`b Requisition";
                        $sdisp = $vals['goldcost'] . " Req";
                    } else {
                        $disp = "`b" . number_format($vals['goldcost']) . "`b Cigarettes";
                        $sdisp = $vals['goldcost'] . " Cigs";
                    }
                }
                if ($session['user']['gold'] >= $vals['goldcost'] && $session['user']['gems'] >= $vals['gemcost']) {
                    addnav("Buy Items");
                    addnav(array("%s (%s)", $vals['verbosename'], $sdisp), "runmodule.php?module=improbablehousing_furnitureshop&op=buy&item=" . $key, true);
                    addnav("", "runmodule.php?module=improbablehousing_furnitureshop&op=buy&item=" . $key);
                    rawoutput("<a href=\"runmodule.php?module=improbablehousing_furnitureshop&op=buy&item=" . $key . "\">Buy for " . appoencode($disp) . "</a><br />");
                } else {
                    output("Price: %s`n", $disp);
                    output("`&You can't afford this item right now.`0`n");
                }
                rawoutput("</td></tr></table>");
                if ($vals['image']) {
                    rawoutput("</td></tr></table>");
                }
                rawoutput("</td></tr>");
            }
            rawoutput("</td></tr></table>");
            break;
        case "buy":
            $item = httpget("item");
            $goldcost = get_item_setting("goldcost", $item);
            $gemcost = get_item_setting("gemcost", $item);
            $name = get_item_setting("verbosename", $item);
            if ($goldcost && $gemcost) {
                $disp = "`b" . number_format($goldcost) . "`b Requisition and `b" . number_format($gemcost) . "`b Cigarettes";
            } else {
                if ($goldcost) {
                    $disp = "`b" . number_format($goldcost) . "`b Requisition";
                } else {
                    $disp = "`b" . number_format($goldcost) . "`b Cigarettes";
                }
            }
            output("Cadfael nods.  \"`3So, you're after a %s then, are ye?  That'll be %s, please.`0\"`n`n", $name, $disp);
            addnav("Confirmation");
            addnav("Confirm sale", "runmodule.php?module=improbablehousing_furnitureshop&op=confirmbuy&item=" . $item);
            addnav("Wait, I've changed my mind!", "runmodule.php?module=improbablehousing_furnitureshop&op=start");
            break;
        case "confirmbuy":
            $item = httpget("item");
            $goldcost = get_item_setting("goldcost", $item);
            $gemcost = get_item_setting("gemcost", $item);
            $name = get_item_setting("verbosename", $item);
            $session['user']['gold'] -= $goldcost;
            $session['user']['gems'] -= $gemcost;
            give_item($item);
            output("You hand over your hard-won currency to Cadfael, who grins and says \"`3Ah, much obliged!  Pleasure doin' business... with...`0\" he stops, bemused.  \"`3Are... are you trying to fit that into a `ibackpack?`i`0\"`n`nAfter several minutes of grunting and sweating, your backpack now resembles a... well, a barely-held-together layer of canvas stretched drum-tight into the shape of a %s.  With a very small %s bent double underneath.  Cadfael shakes his head and mutters something about it taking all sorts.`n`n", $name, $session['user']['race']);
            break;
        case "drop":
            page_header("");
            $itemid = httpget('item');
            debug($itemid);
            $hid = httpget('hid');
            require_once "modules/improbablehousing/lib/lib.php";
            $house = improbablehousing_gethousedata($hid);
            $rid = httpget('rid');
            $slot = httpget('slot');
            $house['data']['rooms'][$rid]['sleepslots'][$slot]['stamina'] = get_item_pref("sleepslot_stamina", $itemid);
            $house['data']['rooms'][$rid]['sleepslots'][$slot]['name'] = get_item_pref("sleepslot_name", $itemid);
            $house['data']['rooms'][$rid]['sleepslots'][$slot]['desc'] = get_item_pref("sleepslot_desc", $itemid);
            use_item($itemid);
            improbablehousing_sethousedata($house);
            addnav("Continue");
            addnav(array("Return to %s", $house['data']['rooms'][$rid]['name']), "runmodule.php?module=improbablehousing&op=interior&hid=" . $hid . "&rid=" . $rid);
            break;
    }
    if (httpget('op') != "drop") {
        addnav("Exit");
        addnav("Back to the Outpost", "village.php");
    }
    page_footer();
    return true;
}
<?php

$hid = httpget('hid');
$rid = httpget('rid');
page_header("Create a new Build Job");
require_once "modules/improbablehousing/lib/lib.php";
$house = improbablehousing_gethousedata($hid);
switch (httpget('sub')) {
    case "increasesize":
        output("Increasing the size of a room allows more people to sleep overnight and get their Stamina boost.`n`nFor a room extension that will allow one more sleeper, you'll have to perform the Masonry action five times, and the Carpentry action twenty times.  Of course, you'll also need the tools and materials associated with those actions.  As with all build jobs, your friends can help too.`n`nYou are about to set up a build job to increase the size of the room called \"`b%s`b.`0\"  Do you want to create this build job?`n`n", $house['data']['rooms'][$rid]['name']);
        $stackedincreases = 0;
        if (count($house['data']['buildjobs']) > 0) {
            foreach ($house['data']['buildjobs'] as $job => $data) {
                if (count($data['completioneffects']['rooms']) > 0) {
                    foreach ($data['completioneffects']['rooms'] as $jobroom => $rdata) {
                        if ($jobroom == $rid && $rdata['deltas']['size']) {
                            $stackedincreases += 1;
                        }
                    }
                }
            }
        }
        if ($stackedincreases) {
            if ($stackedincreases == 1) {
                output("`c`b`\$Careful!`0`b`nYou've already set up a build job to increase the size of this room!  If you add a new build job, then you and your friends will be able to perform this room size increase once the current room size increase is finished.  In other words, you can have multiple build jobs queued up per room, but you can only add materials to them sequentially.`c`n`n");
            } else {
                output("`c`b`\$Careful!`0`b`nYou've already set up %s build jobs to increase the size of this room!  If you add a further build job, then you and your friends will have to complete the room size increases in sequence.`c`n`n", $stackedincreases);
            }
        }
        addnav("Confirm");
        addnav("Yeah, do it!", "runmodule.php?module=improbablehousing&op=buildjobs&sub=increasesize-confirm&hid={$hid}&rid={$rid}");
function improbablehousing_secretrooms_run()
{
    global $session;
    page_header("Secret Rooms");
    require_once "modules/improbablehousing/lib/lib.php";
    $hid = httpget("hid");
    $rid = httpget("rid");
    $house = improbablehousing_gethousedata($hid);
    $cost = get_module_setting("cost");
    $roomname = $house['data']['rooms'][$rid]['name'];
    switch (httpget('op')) {
        case "start":
            output("`5Secret Rooms`0 are rooms that exist in your Dwelling and operate just like normal rooms - except that there's no nav link for players to reach them by.  Instead, a player will be instantly transported from the current room to your `5Secret Room`0 by typing a key phrase into their chat box (the phrase itself won't show up in the chat log - it'd be pretty hard to keep it secret otherwise!).`n`nYou as the secret room owner can assign as many key phrases per room as you would like.  For example, you might assign the key phrases \"`#EXAMINE BOOKCASE`0\", \"`&LOOK BEHIND BOOKCASE`0\", and perhaps a few others, to have the player discover a traditional secret passage.  Or, you could assign the phrase \"`#OPEN SESAME`0\" to reveal a cleverly-hidden door.`n`nIn all other aspects, `5Secret Rooms`0 operate exactly like normal rooms - they can be extended, decorated, and can have more rooms branch from them (including other `5Secret Rooms`0).  They can even be locked just like normal rooms - if a player tries to enter a locked `5Secret Room`0 to which he or she doesn't have access, they'll get bounced straight back as usual.`n`n`5Secret Rooms`0 are a donator-only feature, cost %s Donator Points per room, and come pre-assembled.  No construction materials are necessary; `5Secret Rooms`0 arrive ready to decorate.`n`nYou're currently building a `5Secret Room`0 that can be accessed from the room called \"`b%s`b`0\" - are you sure that this is the room you want to build from?`n`n", $cost, $roomname);
            addnav("Want a Secret Room?");
            $donationavailable = $session['user']['donation'] - $session['user']['donationspent'];
            if ($donationavailable >= $cost) {
                addnav(array("Yes, build a Secret Room branching from this one (%s Points)", $cost), "runmodule.php?module=improbablehousing_secretrooms&op=buy&hid={$hid}&rid={$rid}");
            } else {
                addnav("Ah, but you don't have enough points!", "");
            }
            addnav("Cancel and return to the last room", "runmodule.php?module=improbablehousing&op=interior&hid={$hid}&rid={$rid}");
            break;
        case "buy":
            $session['user']['donationspent'] += $cost;
            output("You've bought a `5Secret Room!`0  To enter it, just type \"`#SECRET`0\" into the chat box in the room called \"%s\" (you can delete this trigger phrase and set up some new ones once you're inside the secret room).`n`nHave fun!`n`n", $roomname);
            $newroom = array("name" => "Secret Room", "size" => 1, "enterfrom" => $rid, "desc" => "You're standing in a small, undecorated secret room.", "sleepslots" => array(), "hidden" => 1, "triggers" => array(0 => "SECRET"), "lockreject" => "You do all the right things, but you still can't get in.  Maybe the room is locked?");
            $house['data']['rooms'][] = $newroom;
            improbablehousing_sethousedata($house);
            addnav("Let's get busy!");
            addnav("Back to your Dwelling", "runmodule.php?module=improbablehousing&op=interior&hid={$hid}&rid={$rid}");
            break;
        case "manage":
            if (httpget("save")) {
                $posted = httpallpost();
                $nphrases = array();
                foreach ($posted as $phrase) {
                    $nphrase = stripslashes($phrase);
                    if ($nphrase != "") {
                        $nphrases[] = strtoupper($nphrase);
                    }
                }
                $house['data']['rooms'][$rid]['triggers'] = $nphrases;
                improbablehousing_sethousedata($house);
            }
            $phrases = $house['data']['rooms'][$rid]['triggers'];
            output("You're currently managing the secret room called \"`b%s`b.`0\"  You can set this room's trigger phrases and lock rejection notices below.`n`nRemember, the text that the player inputs must be an exact match.  There's no extra charge for adding more trigger phrases, so more is often better.`n`nTo erase a trigger phrase, just blank the box.`n`n", $roomname);
            rawoutput("<form action='runmodule.php?module=improbablehousing_secretrooms&op=manage&save=true&hid={$hid}&rid={$rid}' method='POST'>");
            rawoutput("<table border='0' cellpadding='2' cellspacing='2'>");
            $phrasecount = 0;
            foreach ($phrases as $phrase) {
                $class = $phrasecount % 2 ? "trlight" : "trdark";
                $phrasecount++;
                rawoutput("<tr class='{$class}'><td><input name=\"phrase{$phrasecount}\" value=\"{$phrase}\"></td></tr>");
            }
            rawoutput("</table>");
            output("`nNow add up to ten new phrases.  Boxes left blank will be ignored.  To add more, just save and you'll get another ten slots.");
            $extracount = $phrasecount + 10;
            rawoutput("<table border='0' cellpadding='2' cellspacing='2'>");
            for ($i = $phrasecount; $i <= $extracount; $i++) {
                $class = $phrasecount % 2 ? "trlight" : "trdark";
                $phrasecount++;
                rawoutput("<tr class='{$class}'><td><input name=\"phrase{$phrasecount}\" value=''></td></tr>");
            }
            rawoutput("</table>");
            rawoutput("<input type='submit' class='button' value='" . translate_inline("Save") . "'");
            rawoutput("</form>");
            addnav("", "runmodule.php?module=improbablehousing_secretrooms&op=manage&save=true&hid={$hid}&rid={$rid}");
            addnav("Return");
            addnav("Back to the Dwelling", "runmodule.php?module=improbablehousing&op=interior&hid={$hid}&rid={$rid}");
            break;
    }
    page_footer();
    return true;
}
function rail_ironhorse_cleanup($hid)
{
    // code here is copied from exit.php in improbablehousing/run.
    // the train extracts the player from the station dwelling
    //   so we need to remove all traces that they were there.
    global $session;
    $house = improbablehousing_gethousedata($hid);
    // Run through the rooms and make sure the player isn't registered as
    // being in them or sleeping in them
    foreach ($house['data']['rooms'] as $rkey => $rvals) {
        if (isset($rvals['sleepslots'])) {
            foreach ($rvals['sleepslots'] as $skey => $svals) {
                if ($svals['occupier'] == $session['user']['acctid']) {
                    unset($house['data']['rooms'][$rkey]['sleepslots'][$skey]['occupier']);
                }
            }
        }
        if (isset($rvals['occupants'])) {
            foreach ($rvals['occupants'] as $okey => $ovals) {
                //				output("`0Occupant %s: %s`0`n",$okey,$house['data']['rooms'][$rkey]['occupants'][$okey]);
                //				output("okey..%s, acctid..%s`n",$okey,$session['user']['acctid']);
                if ($okey == $session['user']['acctid']) {
                    //					output("- unset`n");
                    unset($house['data']['rooms'][$rkey]['occupants'][$okey]);
                }
            }
        }
    }
    improbablehousing_sethousedata($house);
    clear_module_pref("sleepingat", "improbablehousing");
    return true;
}
function rail_ironhorse_run()
{
    global $session;
    $op = httpget("op");
    $fromhid = httpget("hid");
    $fromrid = httpget("rid");
    $locs = rail_ironhorse_getlocs();
    switch ($op) {
        case "board":
            page_header("On the Train!");
            // Conductor walks through the train here
            if (rail_hascard("railpass_active") || rail_hascard("railpassfirst_active")) {
                // they already have a punched ticket - they're fine
                if (e_rand(1, 20) == 1) {
                    output("`2The `@Conductor `2lurches through the train again, examining passes, taking bribes, exchanging familiar nods with the regular riders.`0`n`n");
                }
            } else {
                if (rail_hascard("railpass") && rail_hascard("railpassfirst")) {
                    // they have both - we have to ask them which they want to use
                    output("`0The `@Conductor `0examines your passes. \"`2Why, you seem to have both regular and first class passes here. Which would you prefer to use today?`0\"`n`n");
                    addnav("Which pass will you use?");
                    addnav("Just the regular today, thanks", "runmodule.php?module=rail_ironhorse&op=choose&hid={$fromhid}&rid={$fromrid}&pass=reg");
                    addnav("It's first class for me, baby", "runmodule.php?module=rail_ironhorse&op=choose&hid={$fromhid}&rid={$fromrid}&pass=first");
                    page_footer();
                    break;
                } else {
                    // they have one or the other but not both - we can punch automatically
                    if (rail_hascard("railpass")) {
                        // they have a regular pass
                        output("`2The `@Conductor `2peers myopically at your Rail Pass and fumbles with a ticket punch. Ka-`btchik`b! Now you're free to ride the train as much as you want for the rest of the day!`0`n`n");
                        rail_ironhorse_activatepass("railpass");
                    } else {
                        // they have a first class pass
                        output("`2The `@Conductor `2inspects your First Class Rail Pass and deferentially produces a ticket punch. Ka-`btchik`b! Now you can ride `ifirst class`i for the rest of the day! Awesome!`0`n`n");
                        rail_ironhorse_activatepass("railpassfirst");
                    }
                }
            }
            $hookargs = array("hid" => $fromhid, "rid" => $fromrid);
            modulehook("ironhorse-onboard", $hookargs);
            set_module_pref("hasridden", 1);
            output("`2The wheels clatter, the car shakes with the astounding speed. Why, you must be going a good twenty-five miles an hour!`0`n`n");
            addnav("Get off!");
            foreach ($locs as $loc => $locarray) {
                if ($loc == "WA" || $loc == "DB") {
                } else {
                    if ($locarray[0] == $fromhid) {
                        addnav(array("`2Back to %s: `0%s", $loc, $locarray[2]), "runmodule.php?module=rail_ironhorse&op=leave&hid={$fromhid}&rid={$fromrid}&loc={$loc}");
                    } else {
                        addnav(array("`2%s: `0%s", $loc, $locarray[2]), "runmodule.php?module=rail_ironhorse&op=leave&hid={$fromhid}&rid={$fromrid}&loc={$loc}");
                    }
                }
            }
            if (rail_hascard("railpassfirst_active")) {
                addnav("First Class");
                addnav("Request Stop", "runmodule.php?module=rail_ironhorse&op=request&hid={$fromhid}&rid=fromrid");
            }
            addcommentary();
            viewcommentary("Riding the Train", "Shout over the engine's thunder:");
            page_footer();
            break;
        case "leave":
            page_header("You have reached your destination!");
            rail_ironhorse_cleanup($fromhid);
            switch (e_rand(1, 200)) {
                // where are we leaving to?
                case 1:
                    $loc = "WA";
                    break;
                case 2:
                    $loc = "DB";
                    break;
                default:
                    $loc = httpget("loc");
                    break;
            }
            $tohid = $locs[$loc][0];
            $torid = $locs[$loc][1];
            $house = improbablehousing_gethousedata($locs[$loc][0]);
            $tohousename = $house['data']['name'];
            set_module_pref("worldXYZ", $house['location'], "worldmapen");
            set_module_pref("lastCity", $locs[$loc][3], "worldmapen");
            $session['user']['location'] = "House: " . $tohousename . ", Room " . $torid . "";
            output("`0The `@Conductor `0smiles toothily as you prepare to disembark. \"`2Thank-you for travelling with the `bImprobable Island Railway Company`b. Please don't forget to take all your luggage with you, and have an improbable day!`0\"`n`n");
            output("`2%s`0`n`n", $locs[$loc][4]);
            addnav("Get off the train");
            addnav(array("`2%s`0 Platform", $locs[$loc][2]), "runmodule.php?module=improbablehousing&op=interior&hid={$tohid}&rid={$torid}");
            if (!($loc == "WA") && !($loc == "DB")) {
                addnav("Wait, I've changed my mind");
                addnav("`2Stay `0 on board", "runmodule.php?module=rail_ironhorse&op=board&hid={$tohid}&rid={$torid}");
            } else {
                output("`2You feel stronger after your pleasant train ride, and rather refreshed!`n`n`0");
                if ($session['user']['hitpoints'] < $session['user']['maxhitpoints']) {
                    $session['user']['hitpoints'] = $session['user']['maxhitpoints'];
                } else {
                    $session['user']['hitpoints'] = $session['user']['hitpoints'] * 1.1;
                    require_once "modules/staminasystem/lib/lib.php";
                    addstamina(25000);
                }
            }
            page_footer();
            break;
        case "request":
            page_header("First Class has its privileges!");
            output("`2As holder of an Improbable Island Railway Company `bFirst Class`b Rail Pass, you have the privilege of asking the train to let you off anywhere on the map. Yes, even in the deepest ocean, should that be your whim! This is, after all, an `iImprobable`i railway system; it can accomplish the seemingly impossible.`n`nSimply tell the `@Conductor `2where on the Island you would like to be dropped off.`0`n`n");
            rawoutput("<form action='runmodule.php?module=rail_ironhorse&op=requestfinish&hid=" . $fromhid . "&rid=" . $fromrid . "' method='POST'>");
            // Note: Width 2 means a 2-digit number. Set the default location to 13,11 Improbable Central.
            rawoutput("X = <input name='stopX' width='2' value='13'> , Y = <input name='stopY' width='2' value='11'><br/><br/>");
            rawoutput("<input type='submit' class='button' value='" . translate_inline("Stop here!") . "'>");
            rawoutput("</form>");
            addnav("", "runmodule.php?module=rail_ironhorse&op=requestfinish&hid={$fromhid}&rid={$fromrid}");
            addnav("Wait, I've changed my mind");
            addnav("`2Stay `0 on board", "runmodule.php?module=rail_ironhorse&op=board&hid={$fromhid}&rid={$fromrid}");
            page_footer();
            break;
        case "requestfinish":
            page_header("First Class has its privileges!");
            $x = httppost("stopX");
            $y = httppost("stopY");
            // strip out any non-numeric characters that got entered by mistake
            $x = ereg_replace("[^0-9]", "", $x);
            $y = ereg_replace("[^0-9]", "", $y);
            // make sure they entered values that are in range for the size of the map.
            $sizeX = get_module_setting("worldmapsizeX", "worldmapen");
            $sizeY = get_module_setting("worldmapsizeY", "worldmapen");
            if ($x <= 0 || $x > $sizeX || $y <= 0 || $y > $sizeY) {
                output("`2Sorry mate, stay on the map. Train service doesn't run outside the Improbability bubble. Nice try though.`0");
                addnav("Oops!");
                addnav("Let's try that again", "runmodule.php?module=rail_ironhorse&op=request&hid={$fromhid}&rid={$fromrid}");
            } else {
                output("`0The `@Conductor `0smiles, all sleek and fangsome, as you prepare to disembark. \"`2Thank-you for travelling with the `bImprobable Island Railway Company`b. Please don't forget to take all your luggage with you, and have an improbable day!`0\"`n`n");
                rail_ironhorse_cleanup($fromhid);
                $maploc = $x . "," . $y . ",1";
                set_module_pref("worldXYZ", $maploc, "worldmapen");
                addnav("Thanks!");
                addnav("`2Leave `0 the train", "runmodule.php?module=worldmapen&op=continue");
            }
            page_footer();
            break;
        case "choose":
            $pass = httpget("pass");
            if ($pass == "first") {
                rail_ironhorse_activatepass("railpassfirst");
            } else {
                rail_ironhorse_activatepass("railpass");
            }
            addnav("", "runmodule.php?module=rail_ironhorse&op=board&hid={$fromhid}&rid={$fromrid}");
            redirect("runmodule.php?module=rail_ironhorse&op=board&hid={$fromhid}&rid={$fromrid}");
            break;
        case "stationmaster":
            page_header("The Stationmaster");
            $val = rail_collector_valuehand();
            // note, we only get here if there's a joker in the hand, so only first class passes
            if ($val['value'] > 2) {
                $phrase = "that's quite a hand you have there. Quite a hand! I think in this case we could even stretch to `b" . $val['value'] . "`b First Class Rail Passes.";
            } else {
                if ($val['value'] > 1) {
                    $phrase = "excellent. For that hand, we could easily give you `btwo`b First Class Rail Passes.";
                } else {
                    $phrase = "no question about it, definitely a `bFirst Class Rail Pass`b.";
                }
            }
            output("`2Having heard that this eccentric railroad company will sometimes give out a rail pass in exchange for used playing cards, you show the Stationmaster your grubby little collection. \"`#Interested?`2\" you ask.`n`n\"`^Why yes. Those would be worth... let me see. Oh, %s`2\"`0`n`n", $phrase);
            addnav("What do you say?");
            addnav("It's a deal!", "runmodule.php?module=rail_ironhorse&op=stationmasterdeal&hid={$fromhid}&rid={$fromrid}");
            addnav("No thanks, I'll wait", "runmodule.php?module=improbablehousing&op=interior&hid={$fromhid}&rid={$fromrid}");
            page_footer();
            break;
        case "stationmasterdeal":
            page_header("The Stationmaster");
            $val = rail_collector_valuehand();
            for ($i = 0; $i < $val['value']; $i++) {
                give_item("railpassfirst");
            }
            $qty = rail_collector_emptyhand();
            output("`2The Stationmaster thanks you, and the two of you make the exchange to your mutual satisfaction. What on earth the Company `iwants`i with all those old playing cards... well. You've naturally wondered about that from time to time, but they're not saying.`0`n`n");
            addnav("Leave");
            addnav("Return to the platform", "runmodule.php?module=improbablehousing&op=interior&hid={$fromhid}&rid={$fromrid}");
            page_footer();
            break;
    }
}
function improbablehousing_mementos_run()
{
    global $session;
    page_header("Memento Effects");
    $hid = httpget("hid");
    $rid = httpget("rid");
    $itemid = httpget("itemid");
    require_once "modules/improbablehousing/lib/lib.php";
    $house = improbablehousing_gethousedata($hid);
    $roomname = $house['data']['rooms'][$rid]['name'];
    $roomdesc = $house['data']['rooms'][$rid]['desc'];
    $pointsavailable = $session['user']['donation'] - $session['user']['donationspent'];
    switch (httpget('op')) {
        case "start":
            output("You can specify some Effect Text to be shown when a player with a specific Memento enters this room.  This costs one Supporter Point per two characters of Effect Text that you want to use.  The extra text cost is independent of the cost to create Mementos (so if you have thirty Mementos, all alike, you only pay once for the effect text).  For example, if you'd made a Memento called 'Bucket of Soapy Frogs' and gave it to someone, you could set things up so that a frog could leap out of the bucket and whisper a secret password to the bearer of this frog when they enter this room.  Each room can have a different thing happen with a different Memento, and each Memento can have something different happen in any given room - the only limit is your own imagination.`n`nHere's a list of all the Mementos that currently exist that were made by you, along with the Effect Text they'll output when the bearer enters this room.`n`n");
            //get all the current Mementos in the game that were made by this player
            $sql = "SELECT * FROM " . db_prefix("items_prefs") . " WHERE setting='memento_author' AND value='" . $session['user']['acctid'] . "'";
            $result = db_query($sql);
            $preload = array();
            while ($row = db_fetch_assoc($result)) {
                $preload[$row['id']] = $row['id'];
            }
            load_item_prefs($preload);
            //debug($preload);
            //group them together by original memento
            $originals = array();
            foreach ($preload as $id) {
                $original = get_item_pref("memento_originalitem", $id);
                if ($original) {
                    $originals[$original] = get_item_prefs($id);
                }
            }
            //debug($originals);
            rawoutput("<table width=100% style='border: dotted 1px #000000;'>");
            $classcount = 1;
            foreach ($originals 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']));
                if ($prefs["memento_dwellingtrigger_" . $hid . "_" . $rid]) {
                    output("`bExtra text for this room:`b`n%s`0`n`n", $prefs["memento_dwellingtrigger_" . $hid . "_" . $rid]);
                }
                rawoutput("<a href='runmodule.php?module=improbablehousing_mementos&op=settext&itemid=" . $id . "&hid=" . $hid . "&rid=" . $rid . "'>Set dwelling text</a>");
                addnav("", "runmodule.php?module=improbablehousing_mementos&op=settext&itemid=" . $id . "&hid=" . $hid . "&rid=" . $rid);
                rawoutput("</td></tr>");
            }
            rawoutput("</table>");
            //okay it's getting late and you're f*****g falling asleep.  Do this in the morning:
            /*
            Get the text that the player wants, and put it in set_item_pref("memento_dwellingtrigger_".$hid."_".$rid);
            			Copy that pref to all the Mementos that are copies of the same original
            */
            break;
        case "settext":
            require_once "lib/forms.php";
            output("You're about to set the Effect Text associated with this Memento, in this room, of this Dwelling.  When a player enters this room with this Memento, this text will be added on to the end of your room description.  You can use all the same colour and formatting codes that you use when Decorating.`n`n");
            //previewfield("newtext","`~",false,false,array("type"=>"textarea", "class"=>"input", "cols"=>"60", "rows"=>"9", "onKeyDown"=>"sizeCount(this);"));
            rawoutput("<form action='runmodule.php?module=improbablehousing_mementos&op=preview&itemid=" . $itemid . "&hid=" . $hid . "&rid=" . $rid . "' method='POST'>");
            addnav("", "runmodule.php?module=improbablehousing_mementos&op=preview&itemid=" . $itemid . "&hid=" . $hid . "&rid=" . $rid);
            previewfield_countup("newtext");
            rawoutput("<br /><input type=submit>");
            rawoutput("</form>");
            addnav("Back");
            addnav("Memento Effects Main Menu", "runmodule.php?module=improbablehousing_mementos&op=start&hid={$hid}&rid={$rid}");
            break;
        case "preview":
            $newtext = httppost("newtext");
            output("The new Effect Text you've chosen to apply is shown below.`n`n-----`n%s`n-----`0`n`n`bRemember`b, this Effect Text applies `ionly`i to this particular Memento (%s`0), in conjunction with this particular room (%s`0).`n`n", $newtext, get_item_pref("verbosename", $itemid), $roomname);
            $cost = ceil(strlen($newtext) / 2);
            output("Total cost: `5`b%s`b Supporter Points`0", $cost);
            if ($pointsavailable >= $cost) {
                addnav("Continue");
                addnav("Buy it!", "runmodule.php?module=improbablehousing_mementos&op=buy&itemid=" . $itemid . "&hid=" . $hid . "&rid=" . $rid . "&text=" . urlencode($newtext));
            } else {
                addnav("Oh dear.");
                addnav("Not enough Supporter Points!", "");
            }
            addnav("Back");
            addnav("Memento Effects Main Menu", "runmodule.php?module=improbablehousing_mementos&op=start&hid={$hid}&rid={$rid}");
            break;
        case "buy":
            $newtext = httpget('text');
            debug($newtext);
            $newtext = urldecode($newtext);
            debug($newtext);
            $cost = ceil(strlen($newtext) / 2);
            $session['user']['donationspent'] += $cost;
            //log purchase
            $sql = "INSERT INTO " . db_prefix("purchaselog") . " (acctid,purchased,amount,data,giftwrap,timestamp) VALUES ('" . $session['user']['acctid'] . "','memento_housing_interaction','" . $cost . "','none','0','" . date("Y-m-d H:i:s") . "')";
            //get all the items like this and apply the pref to all of them
            $sql = "SELECT * FROM " . db_prefix("items_prefs") . " WHERE setting='memento_originalitem' AND value='" . $itemid . "'";
            $result = db_query($sql);
            while ($row = db_fetch_assoc($result)) {
                set_item_pref("memento_dwellingtrigger_" . $hid . "_" . $rid, $newtext, $row['id']);
            }
            set_item_pref("memento_dwellingtrigger_" . $hid . "_" . $rid, $newtext, $itemid);
            output("Your new Effect Text is set!");
            addnav("Back");
            addnav("Memento Effects Main Menu", "runmodule.php?module=improbablehousing_mementos&op=start&hid={$hid}&rid={$rid}");
            break;
    }
    addnav("Back");
    addnav("Return to the Dwelling", "runmodule.php?module=improbablehousing&op=interior&hid={$hid}&rid={$rid}");
    page_footer();
    return true;
}
function improbablehousing_furnitureshop_run()
{
    global $session;
    page_header("Cadfael's Furniture");
    //have the beds and such allowed to be carried in backpack (insert suitable hundred-kilo-bed-in-backpack-lols) or carried by a secondary character in a new Inventory space (we'll call it Delivery Boy - will need a suitably silly photo).
    switch (httpget('op')) {
        case "start":
            output("Cadfael greets you with a preposterously strong Welsh accent.  \"`3Well hey there!  Take a look around, all one 'undred per cent natural and me own work!`0\"`n`n");
            //find items that are furniture!
            $furniture = get_items_with_settings("furniture");
            //debug($furniture);
            usort($furniture, 'sortbyprice');
            rawoutput("<table width=100% style='border: dotted 1px #000000;'>");
            foreach ($furniture as $sort => $vals) {
                $key = $vals['item'];
                $classcount += 1;
                $class = $classcount % 2 ? "trdark" : "trlight";
                rawoutput("<tr class='{$class}'><td>");
                if ($vals['image']) {
                    rawoutput("<table width=100% cellpadding=0 cellspacing=0><tr><td width=100px align=center><img src=\"images/items/" . $vals['image'] . "\"></td><td>");
                }
                output("`b%s`b`n", stripslashes($vals['verbosename']));
                output("%s`0`n", stripslashes($vals['description']));
                if ($vals['weight']) {
                    output("Weight: %s kg`n`0", $vals['weight']);
                }
                rawoutput("<table width=100%><tr><td width=50%>");
                if ($vals['goldcost'] && $vals['gemcost']) {
                    $disp = "`b" . number_format($vals['goldcost']) . "`b Requisition and `b" . number_format($vals['gemcost']) . "`b Cigarettes";
                    $sdisp = $vals['goldcost'] . " Req, " . $vals['gemcost'] . " Cigs";
                } else {
                    if ($vals['goldcost']) {
                        $disp = "`b" . number_format($vals['goldcost']) . "`b Requisition";
                        $sdisp = $vals['goldcost'] . " Req";
                    } else {
                        $disp = "`b" . number_format($vals['goldcost']) . "`b Cigarettes";
                        $sdisp = $vals['goldcost'] . " Cigs";
                    }
                }
                if ($session['user']['gold'] >= $vals['goldcost'] && $session['user']['gems'] >= $vals['gemcost']) {
                    addnav("Buy Items");
                    addnav(array("%s (%s)", $vals['verbosename'], $sdisp), "runmodule.php?module=improbablehousing_furnitureshop&op=buy&item=" . $key, true);
                    addnav("", "runmodule.php?module=improbablehousing_furnitureshop&op=buy&item=" . $key);
                    rawoutput("<a href=\"runmodule.php?module=improbablehousing_furnitureshop&op=buy&item=" . $key . "\">Buy for " . appoencode($disp) . "</a><br />");
                } else {
                    output("Price: %s`n", $disp);
                    output("`&You can't afford this item right now.`0`n");
                }
                rawoutput("</td></tr></table>");
                if ($vals['image']) {
                    rawoutput("</td></tr></table>");
                }
                rawoutput("</td></tr>");
            }
            rawoutput("</td></tr></table>");
            addnav("Custom Furniture");
            addnav("Enquire about Custom Furniture", "runmodule.php?module=improbablehousing_furnitureshop&op=custom&sub=start");
            break;
        case "buy":
            $item = httpget("item");
            $goldcost = get_item_setting("goldcost", $item);
            $gemcost = get_item_setting("gemcost", $item);
            $name = get_item_setting("verbosename", $item);
            if ($goldcost && $gemcost) {
                $disp = "`b" . number_format($goldcost) . "`b Requisition and `b" . number_format($gemcost) . "`b Cigarettes";
            } else {
                if ($goldcost) {
                    $disp = "`b" . number_format($goldcost) . "`b Requisition";
                } else {
                    $disp = "`b" . number_format($goldcost) . "`b Cigarettes";
                }
            }
            output("Cadfael nods.  \"`3So, you're after a %s then, are ye?  That'll be %s, please.`0\"`n`n", $name, $disp);
            addnav("Confirmation");
            addnav("Confirm sale", "runmodule.php?module=improbablehousing_furnitureshop&op=confirmbuy&item=" . $item);
            addnav("Wait, I've changed my mind!", "runmodule.php?module=improbablehousing_furnitureshop&op=start");
            break;
        case "confirmbuy":
            $item = httpget("item");
            $goldcost = get_item_setting("goldcost", $item);
            $gemcost = get_item_setting("gemcost", $item);
            $name = get_item_setting("verbosename", $item);
            $session['user']['gold'] -= $goldcost;
            $session['user']['gems'] -= $gemcost;
            give_item($item);
            output("You hand over your hard-won currency to Cadfael, who grins and says \"`3Ah, much obliged!  Pleasure doin' business... with...`0\" he stops, bemused.  \"`3Are... are you trying to fit that into a `ibackpack?`i`0\"`n`nAfter several minutes of grunting and sweating, your backpack now resembles a... well, a barely-held-together layer of canvas stretched drum-tight into the shape of a %s.  With a very small %s bent double underneath.  Cadfael shakes his head and mutters something about it taking all sorts.`n`n", $name, $session['user']['race']);
            break;
        case "drop":
            page_header("");
            $itemid = httpget('item');
            debug($itemid);
            $hid = httpget('hid');
            require_once "modules/improbablehousing/lib/lib.php";
            $house = improbablehousing_gethousedata($hid);
            $rid = httpget('rid');
            $slot = httpget('slot');
            $house['data']['rooms'][$rid]['sleepslots'][$slot]['stamina'] = get_item_pref("sleepslot_stamina", $itemid);
            $house['data']['rooms'][$rid]['sleepslots'][$slot]['name'] = get_item_pref("sleepslot_name", $itemid);
            $house['data']['rooms'][$rid]['sleepslots'][$slot]['desc'] = get_item_pref("sleepslot_desc", $itemid);
            $house['data']['rooms'][$rid]['sleepslots'][$slot]['multicapacity'] = get_item_pref("sleepslot_multicapacity", $itemid);
            use_item($itemid);
            improbablehousing_sethousedata($house);
            addnav("Continue");
            addnav(array("Return to %s", $house['data']['rooms'][$rid]['name']), "runmodule.php?module=improbablehousing&op=interior&hid=" . $hid . "&rid=" . $rid);
            break;
        case "custom":
            $sub = httpget('sub');
            switch ($sub) {
                case "start":
                    output("\"`3Oh yeah, I get lots of custom orders,`0\" says Cadfael, grinning.  \"`3Mostly for Mutants and Robots.  Interestin' stuff, really, tryin' to figure out where all the extra arms and legs would go.  I can make any of my furniture pieces look like just about anythin'.  Custom work'll set ye back five ciggies as a startin' price, an' goes up from there according to complexity.  You got somethin' in mind?`0\"`n`n`JCadfael can take any piece of furniture intended for sleeping on and assign a new name and description to the sleeping slot that it'll take up.  If you want your houseguests to be able to sleep on top of a bookcase, or inside a cleverly-concealed secret foldaway bed, or in a zero-gravity chamber (yes, Cadfael's carpentry skills are `ijust that good`i), then bring one of his furniture pieces here.`0`n`n");
                    $furniture = get_items_with_prefs("furniture");
                    if (is_array($furniture)) {
                        addnav("Customize Furniture");
                        foreach ($furniture as $key => $vals) {
                            addnav(array("Customize %s", $vals['verbosename']), "runmodule.php?module=improbablehousing_furnitureshop&op=custom&sub=desc&item=" . $key);
                        }
                    }
                    addnav("Return");
                    addnav("Back to the Furniture List", "runmodule.php?module=improbablehousing_furnitureshop&op=start");
                    break;
                case "desc":
                    //get the descriptions from the player
                    $item = httpget('item');
                    output("\"`3Right, then - what'll this be called?`0\"`n`n`0Enter a title for the furniture piece here.  This is what's displayed in the nav links in your Dwelling - it'll read something like \"(your title) Available\" or \"(your title) Occupied by Admin CavemanJoe\" - you've got 25 characters to play about with, and no colour or formatting codes are allowed here.`n`n");
                    $oldtitle = get_item_pref("sleepslot_name", $item);
                    $olddesc = get_item_pref("sleepslot_desc", $item);
                    rawoutput("<form action='runmodule.php?module=improbablehousing_furnitureshop&op=custom&sub=confirm&item=" . $item . "' method='POST'>");
                    rawoutput("<input id='newtitle' name='newtitle' width='25' maxlength='25' value='" . $oldtitle . "'>");
                    output("`n`nNow enter a description for the new furniture piece.  This is what's displayed to players when they settle down for a good night's kip.  The longer the description, the more it'll cost.  You can use colour and formatting codes here - remember to use ``n for new lines.`n`n");
                    rawoutput("<textarea name='newdesc' id='newdesc' rows='6' cols='60'>" . $olddesc . "</textarea><input type=submit></form>");
                    addnav("Return");
                    addnav("Back to the Furniture List", "runmodule.php?module=improbablehousing_furnitureshop&op=start");
                    addnav("", "runmodule.php?module=improbablehousing_furnitureshop&op=custom&sub=confirm&item=" . $item);
                    break;
                case "confirm":
                    $newtitle = httppost('newtitle');
                    $newdesc = httppost('newdesc');
                    $item = httpget('item');
                    $newdesc = str_replace("\n", "`n", $newdesc);
                    $newtitle = str_replace("`", "", $newtitle);
                    $newtitle = substr($newtitle, 0, 25);
                    $newtitle = stripslashes($newtitle);
                    $newdesc = stripslashes($newdesc);
                    //show the descriptions
                    output("Your new title is:`n%s`0`n`nYour new description is:`n%s`0`n`n", $newtitle, $newdesc);
                    $cigcost = 5 + floor(strlen($newdesc) / 50);
                    output("This much work will cost %s cigarettes.`n`n", $cigcost);
                    set_item_pref("proposed_sleepslot_name", $newtitle, $item);
                    set_item_pref("proposed_sleepslot_desc", $newdesc, $item);
                    if ($session['user']['gems'] >= $cigcost) {
                        addnav("Continue");
                        addnav("Pay the man!", "runmodule.php?module=improbablehousing_furnitureshop&op=custom&sub=confirmfinal&item=" . $item . "&cost=" . $cigcost);
                    } else {
                        output("You don't have enough cigarettes for that!`n`n");
                    }
                    addnav("Return");
                    addnav("Back to the Furniture List", "runmodule.php?module=improbablehousing_furnitureshop&op=start");
                    break;
                case "confirmfinal":
                    //take the cigaretes, change the prefs
                    $item = httpget('item');
                    $cost = httpget('cost');
                    $session['user']['gems'] -= $cost;
                    output("Cadfael takes your cigarettes and furniture with a smile, and disappears into the back of the shop.  You hear muffled sounds of sawing, hammering, swearing and so forth, and after half an hour or so he returns.  \"`3Here you go - might not look much different `inow,`i but wait 'til you get it in yer house.`0\"`n`nYour furniture is now customized!");
                    $newtitle = get_item_pref("proposed_sleepslot_name", $item);
                    $newdesc = get_item_pref("proposed_sleepslot_desc", $item);
                    set_item_pref("verbosename", "Customized Furniture (" . $newtitle . ")", $item);
                    set_item_pref("sleepslot_name", $newtitle, $item);
                    set_item_pref("sleepslot_desc", $newdesc, $item);
                    set_item_pref("description", "This furniture was modified at Cadfael's shop in Improbable Central.", $item);
                    addnav("Return");
                    addnav("Back to the Furniture List", "runmodule.php?module=improbablehousing_furnitureshop&op=start");
                    break;
            }
            break;
    }
    if (httpget('op') != "drop") {
        addnav("Exit");
        addnav("Back to the Outpost", "village.php");
    }
    page_footer();
    return true;
}