Gastropoda - racing progress

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.

Gastropoda - create race

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

Gastropoda - open races

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

Gastropoda - open races

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

Gastropoda - race event

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):

Gastropoda - no withdrawal

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:

Gastropoda - finished races

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

Gastropoda - race 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;
                    $snail->raceTime = $raceTime;
                    file_put_contents ( "racelog.txt" , "Snail Finished: " . $snail->currentSpeed . " " . $snail->name . PHP_EOL, FILE_APPEND );

                // 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;

            // Increase the race time

        // 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) {

        // 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 );
        return true;


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.

comments powered by Disqus