The snail simulation is coming along. Tonight I did some work on racing. The racing formula isn’t anywhere close to final yet, but races do run. Here’s how it works right now:
The gist of it
User creates a race (or enters an existing one, but let’s say they want to create one of their own). They decide that they want to have a minimum of 2 entrants and a maximum of 3.

They can then go to the Track page and see their race in the list of open races:

They can click on the race name to be taken to the race page, where they can enter their own race.

When the minimum number of entrants has been reached (in this case 2), a race event is created in the database.

Also, when the minimum number of snails have entered an event users may no longer withdraw their snails from the race (note the disappearance of the Withdraw button):

When the minimum amount of entrants has been reached, a timer starts (currently 3 minutes). The race will run once this timer is up. The timer will get reset each time a new snail is entered into the race. However, if the maximum number of entrants has been reached the race event will be updated to run immediately (within a minute after the last entrant is registered). This is because there’s no point in waiting for any more entrants - we already have the maximum.
The race runs the next time a cron job triggers it (by looking for unfinished race events with a run time older than the current time). You can then see the result of the race on the main Track page:

You can click on the race name to see the results:

The actual race
This is the part that will be completely overhauled - it’s hacked together quickly to get something running. Here’s how it currently works (see comments). Right now the endurance doesn’t actually get decreased with each step - I haven’t activated that yet because I have been testing that initiative and speed work properly. Eventually a snail will also have a chance to perform some sort of action with each step (this is why I need to count the race step by step).
function RunRace() {
file_put_contents ( "racelog.txt" , "running race" . PHP_EOL, FILE_APPEND );
$snailmanager = new SnailManager();
// Set initial total finished and out count, as well as race time
$totalFinished = 0;
$totalOut = 0;
$raceTime = 0;
// A really dumb way of sorting the array in the right order because I am lazy...
$entrants = Utility::SortArrayofObjectByProperty($this->currentEntrants,"currentInitiative");
$entrants = array_reverse($entrants);
// If not all snails have finished OR been knocked out, run that sucker
while ($totalFinished + $totalOut < count($this->currentEntrants)) {
foreach ($entrants as $snail) {
// If the race has reached the finish, mark it as having finished and get out
if ($snail->racePos >= $this->distance * 10 && !$snail->finished) {
$snail->finished = true;
$totalFinished++;
$snail->raceTime = $raceTime;
file_put_contents ( "racelog.txt" , "Snail Finished: " . $snail->currentSpeed . " " . $snail->name . PHP_EOL, FILE_APPEND );
break;
}
// If the snail is NOT finished and still has some endurance, have it move
if ($snail->currentEndurance > 0 && !$snail->finished) {
$snail->racePos = $snail->racePos + $snail->currentSpeed * 10;
file_put_contents ( "racelog.txt" , "Snail moved: " . $snail->name . " ;Distance: " . $snail->racePos . " ;END " . $snail->currentEndurance . PHP_EOL, FILE_APPEND );
// If the snail has run out of endurance, mark it as OUT
if ($snail->currentEndurance <= 0) {
file_put_contents ( "racelog.txt" , "Snail OUT: " . $snail->name . " END " . $snail->currentEndurance . PHP_EOL, FILE_APPEND );
$snail->outOfRace = true;
$totalOut++;
}
}
}
// Increase the race time
$raceTime++;
}
// When all snails have either finished or been knocked out, sort entrants by race time
$sortedEntrants = Utility::SortArrayofObjectByProperty($this->currentEntrants,"raceTime");
foreach ($sortedEntrants as $snail) {
file_put_contents ( "racelog.txt" , "Snail Name: " . $snail->name . "TIME: " . $snail->raceTime . PHP_EOL, FILE_APPEND );
// If the snail has been knocked out (therefore finish time was never recorded), move it to the end of the sorted entrants array
if ($snail->raceTime == 0) {
array_push($sortedEntrants, $snail);
if(($key = array_search($snail, $sortedEntrants)) !== false) {
unset($sortedEntrants[$key]);
}
}
}
// Record each result's placing.
$place = 1;
foreach ($sortedEntrants as $snail) {
$this->RecordResult($snail, $place);
file_put_contents ( "racelog.txt" , "Snail ID: " . $snail->snailID . " race time: " . $snail->raceTime . PHP_EOL, FILE_APPEND );
$place++;
}
return true;
}
{:lang=“php”}
Currently snails that are knocked out are also still listed in the placings, just at the end. However, when I actually implement endurance they will be listed outside of the main results table.