function hundredpointrally_run()
{
    global $session;
    page_header("Rally Headquarters");
    $op = httpget('op');
    //load settings
    $joincost = get_module_setting("joincost", "hundredpointrally");
    $data = @unserialize(get_module_setting("data", "hundredpointrally"));
    if (!is_array($data)) {
        $data = array();
        set_module_setting("data", serialize($data), "hundredpointrally");
    }
    //load pref
    $player = @unserialize(get_module_pref("data", "hundredpointrally"));
    if (!is_array($player)) {
        $player = array();
        set_module_pref("data", serialize($player), "hundredpointrally");
    }
    switch ($op) {
        case "start":
            do_forced_nav(false, false);
            require_once "lib/datetime.php";
            $nextstarttime = reltime($data['next']['starttime'], false);
            if (!$data['next']['starttime']) {
                $nextstarttime = "Undetermined amount of time";
            }
            $seed = get_module_setting("jackpotseed", "hundredpointrally");
            if (!isset($data['next']['jackpot']) || $data['next']['jackpot'] < $seed) {
                $data['next']['jackpot'] = $seed;
                set_module_setting("data", serialize($data), "hundredpointrally");
            }
            output("You head into a building decked out with chequered flags.  It smells of petrol and burning rubber, although there are no cars or motorbikes to be seen.  Noticing that the receptionist is a Robot, you surmise that she must be pumping the scent in artificially in order to create atmosphere.  Which figures, really.`n`n\"`7Hello!`0\" she says in a tinny, cheery warble.  \"`7Are you here to sign up for the Hundred-Point Rally?  The next one starts in -`0\" her voice becomes stilted and mechanical for a moment - \"`&%s TO RACE START JACKPOT VALUE OF %s CIGARETTES ENTRY FEE OF %s CIGARETTES`7.`0\"`n`n", strtoupper($nextstarttime), $data['next']['jackpot'], $joincost);
            if ($data['current']['open']) {
                $currentstarttime = reltime($data['current']['starttime'], false);
                output("\"`7Or, if you prefer, the current Rally is still open.  It started -`0\" the same mechanical, halting tone - \"`&%s AGO CURRENT JACKPOT %s CIGARETTES`7.  You'd have a better chance if you waited for the next one, but you can join this one if you're impatient.  It'll cost you the same either way.\"`n`n", strtoupper($currentstarttime), $data['current']['jackpot']);
            }
            addnav("Join a Rally");
            if ($session['user']['gems'] >= $joincost) {
                if (!$player['activenext']) {
                    addnav("Join the `bnext`b Hundred-Point Rally", "runmodule.php?module=hundredpointrally&op=joinnext");
                }
                if (!$player['activecurrent'] && $data['current']['open']) {
                    addnav("Join the `bcurrent`b Hundred-Point Rally", "runmodule.php?module=hundredpointrally&op=joincurrent");
                }
            }
            addnav("What?");
            addnav("Explain this Rally business to me.", "runmodule.php?module=hundredpointrally&op=explain");
            addnav("Exit");
            villagenav();
            break;
        case "explain":
            do_forced_nav(false, false);
            output("\"`7It's very simple,`0\" says the Robot.  \"`7The Hundred-Point Rally is a race around the World Map.  The winner takes the jackpot - the more people signed up for the Rally, the bigger the Jackpot.  You'll be given a series of fifty co-ordinates that you have to visit in sequence, and you'll also be given another fifty co-ordinates that can be visited in any order you like.  The challenge is not only in speed, but also in your ability to determine the most efficient path to hit all one hundred co-ordinates.  Because the race can be quite long, and because the co-ordinates are only revealed once the race has begun, it may or may not be a good idea to spend some time plotting out your route before heading to the first Rally Point.  Each new Rally starts exactly twenty-four hours `&WARNING SYSTEM CLOCK ERROR WHAT THE HELL WHY IS 24 HOURS THE SAME AS SIX DAYS`7 after the last one ends, and a Rally can last for up to 48 hours.`0\"`n`nYou nod.  \"`#Could you explain that part about the system clock error again?`0\"`n`n\"`&What part?`0\"`n`n\"`#Ah.`0\"`n`n`JTo ensure that players from different time zones have a fair shake every now and then, Rallies aren't tied to game time.  When the Robot says \"24 hours,\" she means 24 hours of your time, not game time (which runs six times faster).  If you're signing up for the next Rally and a start time isn't determined yet, you'll get a Distraction exactly 24 hours before the race begins, and another one at the drop of the chequered flag.  We highly recommend that you have Distractions sent to your E-mail if you're a Rally fan, and you can find the relevant option in your Preferences menu in any Outpost.`n`nRallies end as soon as someone hits all one hundred points - so, for example, if a Rally starts at midnight and ends at 2am, the next Rally will start at 2am the next day - and if `ithat`i Rally takes three hours to complete, then the Rally ends at 5am and the next Rally begins at 5am the next day.  This way, we eventually end up going all the way around the clock, giving players in different timezones a chance to compete in the Rally.`0");
            addnav("Okay, then.");
            addnav("Back to Reception", "runmodule.php?module=hundredpointrally&op=start");
            break;
        case "joinnext":
            do_forced_nav(false, false);
            output("You hand over your Cigarettes.  \"`7Very well.  Your entry has been accepted and you will be notified via Distraction when the race starts.  In the meantime, I suggest you buy a very, very fast Mount.`0\"  The Robot tries to smile.  It doesn't come out too well.");
            $data['next']['competitors'][$session['user']['acctid']]['points'] = 0;
            $data['next']['competitors'][$session['user']['acctid']]['name'] = $session['user']['name'];
            $player['activenext'] = true;
            $session['user']['gems'] -= $joincost;
            $data['next']['jackpot'] += floor($joincost * 0.75);
            set_module_pref("data", serialize($player), "hundredpointrally");
            set_module_setting("data", serialize($data), "hundredpointrally");
            addnav("Exit");
            villagenav();
            break;
        case "joincurrent":
            do_forced_nav(false, false);
            output("You hand over your Cigarettes.  \"`7Very well.  Your entry has been accepted.  Now you had better get out there and race!`0\"  The Robot tries to smile.  It doesn't come out too well.");
            $data['current']['competitors'][$session['user']['acctid']]['points'] = 0;
            $data['current']['competitors'][$session['user']['acctid']]['name'] = $session['user']['name'];
            $session['user']['gems'] -= $joincost;
            $data['current']['jackpot'] += floor($joincost * 0.75);
            $player['activecurrent'] = true;
            set_module_pref("data", serialize($player), "hundredpointrally");
            set_module_setting("data", serialize($data), "hundredpointrally");
            addnav("Exit");
            villagenav();
            break;
        case "showpoints":
            popup_header("Rally Points");
            rawoutput("<table cellpadding=5 cellspacing=5 border=0><tr><td valign='top'>");
            output("`0`bSequenced Points`b`nHit each of these World Map points in the prescribed order:`n");
            foreach ($data['current']['sequencedpoints'] as $order => $loc) {
                list($sx, $sy, $sz) = explode(",", $data['current']['sequencedpoints'][$order]);
                if ($player['sequencedpoints'] > $order) {
                    rawoutput("<del>");
                    output("Point %s: `@%s,%s`0`n", $order, $sx, $sy);
                    rawoutput("</del>");
                } else {
                    if ($player['sequencedpoints'] < $order) {
                        output("Point %s: `\$%s,%s`0`n", $order, $sx, $sy);
                    } else {
                        output(">> Point %s: `Q%s,%s`0`n", $order, $sx, $sy);
                    }
                }
            }
            rawoutput("</td><td valign='top'>");
            output("`0`bUnordered Points`b`nHit each of these World Map points in whatever order seems best to you:`n");
            foreach ($data['current']['unorderedpoints'] as $order => $loc) {
                list($ux, $uy, $uz) = explode(",", $loc);
                if (@in_array($loc, $player['unorderedpoints'])) {
                    rawoutput("<del>");
                    output("`@%s,%s`0`n", $ux, $uy);
                    rawoutput("</del>");
                } else {
                    output("`\$%s,%s`0`n", $ux, $uy);
                }
            }
            rawoutput("</td><td valign='top'>");
            $rankings = hundredpointrally_getrankings();
            output("`bCurrent Rankings`b`n");
            foreach ($rankings as $rank => $info) {
                if ($info['acctid'] == $session['user']['acctid']) {
                    output("`J`b>>`b ");
                }
                output("#%s: %s`0 (%s points)`n", $rank + 1, $info['name'], $info['points']);
            }
            rawoutput("</td></tr></table>");
            popup_footer();
            break;
    }
    page_footer();
}
header("Content-Type: text/html; charset=" . getsetting('charset', 'ISO-8859-1'));
if (strtotime("-" . getsetting("LOGINTIMEOUT", 900) . " seconds") > $session['lasthit'] && $session['lasthit'] > 0 && $session['loggedin']) {
    // force the abandoning of the session when the user should have been
    // sent to the fields.
    $session = array();
    // technically we should be able to translate this, but for now,
    // ignore it.
    // 1.1.1 now should be a good time to get it on with it, added tl-inline
    translator_setup();
    $session['message'] .= translate_inline("`nYour session has expired!`n", "common");
}
$session['lasthit'] = strtotime("now");
$cp = $copyright;
$l = $license;
php_generic_environment();
do_forced_nav(ALLOW_ANONYMOUS, OVERRIDE_FORCED_NAV);
$script = substr($SCRIPT_NAME, 0, strrpos($SCRIPT_NAME, "."));
// Commented out because we now cache moduleprefs, and this saves us a db query
// mass_module_prepare(array(
// 'template-header','template-footer','template-statstart','template-stathead','template-statrow','template-statbuff','template-statend',
// 'template-navhead','template-navitem','template-petitioncount','template-adwrapper','template-login','template-loginfull','everyhit',
// "header-$script","footer-$script",'holiday','collapse{','collapse-nav{','}collapse-nav','}collapse','charstats'
// ));
// In the event of redirects, we want to have a version of their session we
// can revert to:
$revertsession = $session;
if (!isset($session['user']['loggedin'])) {
    $session['user']['loggedin'] = false;
}
if (!$session['user']['loggedin']) {
    $session['loggedin'] = false;
        $allowanonymous = false;
    } else {
        $allowanonymous = $info['allowanonymous'];
    }
    if (!isset($info['override_forced_nav'])) {
        $override_forced_nav = false;
    } else {
        $override_forced_nav = $info['override_forced_nav'];
    }
    do_forced_nav($allowanonymous, $override_forced_nav);
    $starttime = getmicrotime();
    $fname = $mostrecentmodule . "_run";
    tlschema("module-{$mostrecentmodule}");
    $fname();
    $endtime = getmicrotime();
    if ($endtime - $starttime >= 1.0 && $session['user']['superuser'] & SU_DEBUG_OUTPUT) {
        debug("Slow Module (" . round($endtime - $starttime, 2) . "s): {$mostrecentmodule}`n");
    }
    tlschema();
} else {
    do_forced_nav(false, false);
    tlschema("badnav");
    page_header("Error");
    if ($session['user']['loggedin']) {
        villagenav();
    } else {
        addnav("L?Return to the Login", "index.php");
    }
    output("You are attempting to use a module which is no longer active, or has been uninstalled.");
    page_footer();
}
function cities_run()
{
    global $session;
    $op = httpget("op");
    $city = urldecode(httpget("city"));
    $continue = httpget("continue");
    $danger = httpget("d");
    $su = httpget("su");
    if ($op != "faq") {
        require_once "lib/forcednavigation.php";
        do_forced_nav(false, false);
    }
    // I really don't like this being out here, but it has to be since
    // events can define their own op=.... and we might need to handle them
    // otherwise things break.
    require_once "lib/events.php";
    if ($session['user']['specialinc'] != "" || httpget("eventhandler")) {
        $in_event = handle_event("travel", "runmodule.php?module=cities&city=" . urlencode($city) . "&d={$danger}&continue=1&", "Travel");
        if ($in_event) {
            addnav("Continue", "runmodule.php?module=cities&op=travel&city=" . urlencode($city) . "&d={$danger}&continue=1");
            module_display_events("travel", "runmodule.php?module=cities&city=" . urlencode($city) . "&d={$danger}&continue=1");
            page_footer();
        }
    }
    if ($op == "travel") {
        $args = modulehook("count-travels", array('available' => 0, 'used' => 0));
        $free = max(0, $args['available'] - $args['used']);
        if ($city == "") {
            require_once "lib/villagenav.php";
            page_header("Travel");
            //modulehook("collapse{", array("name"=>"traveldesc"));
            output("`%Travelling the world can be a dangerous occupation.");
            output("Although other villages might offer things not found in your current one, getting from village to village is no easy task, and might subject you to various dangerous creatures or brigands.");
            output("Be sure you're willing to take on the adventure before you set out, as not everyone arrives at their destination intact.");
            output("Also, pay attention to the signs, some roads are safer than others.`n");
            //modulehook("}collapse");
            addnav("Forget about it");
            villagenav();
            modulehook("pre-travel");
            if (!($session['user']['superuser'] & SU_EDIT_USERS) && $session['user']['turns'] <= 0 && $free == 0) {
                // this line rewritten so as not to clash with the hitch module.
                output("`nYou don't feel as if you could face the prospect of walking to another city today, it's far too exhausting.`n");
            } else {
                addnav("Travel");
                modulehook("travel");
            }
            module_display_events("travel", "runmodule.php?module=cities&city=" . urlencode($city) . "&d={$danger}&continue=1");
            page_footer();
        } else {
            if ($continue != "1" && $su != "1" && !get_module_pref("paidcost")) {
                set_module_pref("paidcost", 1);
                if ($free > 0) {
                    // Only increment travel used if they are still within
                    // their allowance.
                    set_module_pref("traveltoday", get_module_pref("traveltoday") + 1);
                    //do nothing, they're within their travel allowance.
                } elseif ($session['user']['turns'] > 0) {
                    $session['user']['turns']--;
                } else {
                    output("Hey, looks like you managed to travel with out having any forest fights.  How'd you swing that?");
                    debuglog("Travelled with out having any forest fights, how'd they swing that?");
                }
            }
            // Let's give the lower DK people a slightly better chance.
            $dlevel = cities_dangerscale($danger);
            if (e_rand(0, 100) < $dlevel && $su != '1') {
                //they've been waylaid.
                if (module_events("travel", get_module_setting("travelspecialchance"), "runmodule.php?module=cities&city=" . urlencode($city) . "&d={$danger}&continue=1&") != 0) {
                    page_header("Something Special!");
                    if (checknavs()) {
                        page_footer();
                    } else {
                        // Reset the special for good.
                        $session['user']['specialinc'] = "";
                        $session['user']['specialmisc'] = "";
                        $skipvillagedesc = true;
                        $op = "";
                        httpset("op", "");
                        addnav("Continue", "runmodule.php?module=cities&op=travel&city=" . urlencode($city) . "&d={$danger}&continue=1");
                        module_display_events("travel", "runmodule.php?module=cities&city=" . urlencode($city) . "&d={$danger}&continue=1");
                        page_footer();
                    }
                }
                $args = array("soberval" => 0.9, "sobermsg" => "`&Facing your bloodthirsty opponent, the adrenaline rush helps to sober you up slightly.", "schema" => "module-cities");
                modulehook("soberup", $args);
                require_once "lib/forestoutcomes.php";
                $sql = "SELECT * FROM " . db_prefix("creatures") . " WHERE creaturelevel = '{$session['user']['level']}' AND forest = 1 ORDER BY rand(" . e_rand() . ") LIMIT 1";
                $result = db_query($sql);
                restore_buff_fields();
                if (db_num_rows($result) == 0) {
                    // There is nothing in the database to challenge you,
                    // let's give you a doppleganger.
                    $badguy = array();
                    $badguy['creaturename'] = "An evil doppleganger of " . $session['user']['name'];
                    $badguy['creatureweapon'] = $session['user']['weapon'];
                    $badguy['creaturelevel'] = $session['user']['level'];
                    $badguy['creaturegold'] = 0;
                    $badguy['creatureexp'] = round($session['user']['experience'] / 10, 0);
                    $badguy['creaturehealth'] = $session['user']['maxhitpoints'];
                    $badguy['creatureattack'] = $session['user']['attack'];
                    $badguy['creaturedefense'] = $session['user']['defense'];
                } else {
                    $badguy = db_fetch_assoc($result);
                    $badguy = buffbadguy($badguy);
                }
                calculate_buff_fields();
                $badguy['playerstarthp'] = $session['user']['hitpoints'];
                $badguy['diddamage'] = 0;
                $badguy['type'] = 'travel';
                $session['user']['badguy'] = createstring($badguy);
                $battle = true;
            } else {
                set_module_pref("paidcost", 0);
                //they arrive with no further scathing.
                $session['user']['location'] = $city;
                redirect("village.php", "Redirected to Village from Multiple Cities module");
            }
        }
    } elseif ($op == "fight" || $op == "run") {
        if ($op == "run" && e_rand(1, 5) < 3) {
            // They managed to get away.
            page_header("Escape");
            output("You set off running through the forest at a breakneck pace heading back the way you came.`n`n");
            $coward = get_module_setting("coward");
            if ($coward) {
                modulehook("cities-usetravel", array("foresttext" => array("In your terror, you lose your way and become lost, losing time for a forest fight.`n`n", $session['user']['location']), "traveltext" => array("In your terror, you lose your way and become lost, losing precious travel time.`n`n", $session['user']['location'])));
            }
            output("After running for what seems like hours, you finally arrive back at %s.", $session['user']['location']);
            addnav(array("Enter %s", $session['user']['location']), "village.php");
            page_footer();
        }
        $battle = true;
    } elseif ($op == "faq") {
        cities_faq();
    } elseif ($op == "") {
        page_header("Travel");
        output("A divine light ends the fight and you return to the road.");
        addnav("Continue your journey", "runmodule.php?module=cities&op=travel&city=" . urlencode($city) . "&continue=1&d={$danger}");
        module_display_events("travel", "runmodule.php?module=cities&city=" . urlencode($city) . "&d={$danger}&continue=1");
        page_footer();
    }
    if ($battle) {
        page_header("You've been waylaid!");
        require_once "battle.php";
        if ($victory) {
            require_once "lib/forestoutcomes.php";
            forestvictory($newenemies, "This fight would have yielded an extra turn except it was during travel.");
            addnav("Continue your journey", "runmodule.php?module=cities&op=travel&city=" . urlencode($city) . "&continue=1&d={$danger}");
            module_display_events("travel", "runmodule.php?module=cities&city=" . urlencode($city) . "&d={$danger}&continue=1");
        } elseif ($defeat) {
            require_once "lib/forestoutcomes.php";
            forestdefeat($newenemies, array("travelling to %s", $city));
        } else {
            require_once "lib/fightnav.php";
            fightnav(true, true, "runmodule.php?module=cities&city=" . urlencode($city) . "&d={$danger}");
        }
        page_footer();
    }
}