New snail shell patterns

This post originally started out like this:

I’ve made a few more shell patterns for the snails!

I then started to descibe how the basic genetics work in the simulation (limited to pattern color). While doing so, I began to realize that it is all wrong. I went back and ripped apart some of the breeding system to get it to a slightly more realistic state. Needless to say it’s still not really correct, but at least it’s a bit closer to what could be some sort of reality. Now I have to go back and clean everything up/rewrite it.

I’ll keep the explanation to pattern color, but there is also pattern shape, shell color, eye color, and shell radius genetic traits (and more background genetic traits that don’t actually translate to anything visually on the snail).

(Sidenote: I’m already noticing bugs with this as I type this…and filing them on the Trello board…this obviously has a long way to go)

For randomly generated wild snails

When generating a random snail, random integers between 0 and 255 are chosen for the pattern color.

    $this->patternColorR = Utility::randomInteger(0,255);
    $this->patternColorG = Utility::randomInteger(0,255);
    $this->patternColorB = Utility::randomInteger(0,255);

{:lang=“php”}

When this and the other genetic traits have been randomly generated, generateGeneString() is run.

    $arrayOfColors = [
        'r' => $this->patternColorR, 
        'g' => $this->patternColorG, 
        'b' => $this->patternColorB
    ];
    $this->patternColorGeneAllele1 = strtoupper($this->findDominantColor($arrayOfColors));
    $this->patternColorGeneAllele2 = $this->pickRandomRecessiveColorAllele($this->patternColorGeneAllele1);

{:lang=“php”}

Why convert the allele to upper case instead of just naming the keys in upper case? I preferred to do it this way because I want it to be clear that the keys in $arrayOfColors do not represent alleles. These refer to color amounts themselves. Alleles are in upper case.

So, to get the first allele in the randomly generated snails we find the dominant color in arrayOfColors and convert it to an allele (in upper case): $this->patternColorGeneAllele1 = strtoupper($this->findDominantColor($arrayOfColors));

When we know the first allele, we need to generate a second one (which the first is dominant over) to complete the desired genotype via $this->patternColorGeneAllele2 = $this->pickRandomRecessiveColorAllele($this->patternColorGeneAllele1);

In pickRandomRecessiveColorAllele there is this:

        $possibleAllelesArray = [];
        switch (true) {
            case ($dominantAllele === 'R'):
                $possibleAllelesArray = ['R','G','B'];
                break;
            case ($dominantAllele === 'G'):
                $possibleAllelesArray = ['G','B'];
                break;
            case ($dominantAllele === 'B'):
                $possibleAllelesArray = ['B'];
                break;
        }
        $allele = Utility::randomInteger(0,count($possibleAllelesArray)-1);
        return $possibleAllelesArray[$allele];

{:lang=“php”}

For newborn snails with two parents

When generating a newborn snail and not just a random snail the process is kind of reversed. We get the alleles first, then the colors themselves:

    $this->patternColorGeneAllele1 = $this->generateAlleles($stag->patternColorGeneAllele1, $stag->patternColorGeneAllele2);
    $this->patternColorGeneAllele2 = $this->generateAlleles($doe->patternColorGeneAllele1, $doe->patternColorGeneAllele2);

{:lang=“php”}

    protected function generateAlleles($traitAllele1, $traitAllele2) {
        // Make an array of the two possibilities
        $possibilities = [$traitAllele1, $traitAllele2]; 
        // Pick one of the elements in the array at random
        $rand = Utility::randomInteger(0,1);
        return $possibilities[$rand];
    }

{:lang=“php”}

We then make an array of each of the parent snails’ pattern colors and run $patternColor = $this->generateVisibleTraits('patternColor', $stagPatternColor, $doePatternColor);

In generateVisibleTraits() we get the alleles for the trait in the form of an array.

    $alleles = $this->getAllele($trait); // Array (2)
    if ($trait !== 'patternShape' && $trait !== 'patternRadius') {
        $a1 = strtoupper($alleles['allele1']);
        $a2 = strtoupper($alleles['allele2']);
        switch (true) {
        	// If both alleles are identical use both stag and doe traits 
            case ($a1 === 'R' && $a2 === 'R') || ($a1 === 'G' && $a2 === 'G') || ($a1 === 'B' && $a2 === 'B'):
                return $this->pickColor($a1, $stagTrait, $doeTrait);

            // If either allele is R (for red), set it as the color - Red is always dominant
            case $a1 === 'R':
                return $this->pickColor('R', $stagTrait);
            case $a2 === 'R':
                return $this->pickColor('R', $doeTrait);
            // Else if either allele is G (for green), set it as the color - Green is second dominant
            case $a1 === 'G':
                return $this->pickColor('G', $stagTrait);
            case $a2 === 'G':
                return $this->pickColor('G', $doeTrait);
            // Else if either allele is B (for blue), set it as the color - Blue is always submissive
            case $a1 === 'B':
                return $this->pickColor('B', $stagTrait);
            case $a2 === 'B':
                return $this->pickColor('B', $doeTrait);
        }
    }

{:lang=“php”}

In pickColor() you can optionally pass up to two parentTrait arguments. In some cases you don’t need to, but for patternColor there should always be at least one. If there are two, we assume incomplete dominance and return a mix of both parents’ dominant color.

    protected function pickColor($allele, $parentTrait1 = null, $parentTrait2 = null) {
        // RGB min & max values
        $minValue = 0;
        $maxValue = 255;
        $posKeys = ['R','G','B'];
        $color = strtolower($posKeys[array_search($allele, $posKeys)]);

        if (isset($parentTrait1) && isset($parentTrait2)) {
            $minValue = $parentTrait2[$color];
            $maxValue = $parentTrait1[$color];
        }
        else if (isset($parentTrait1)) {
            $minValue = $parentTrait1[$color] - 15;
            $maxValue = $parentTrait1[$color] + 15;
        }

        $randomColorAttributes = "";

        foreach ($posKeys as $key) {
            if ($key === $allele) {
                $min = $minValue;
                $max = $maxValue;
            }
            else {
                $min = 0;
                $max = $minValue;
            }
            $randomColorAttributes .= $min . ',' . $max;
            if ($key !== 'B') {
                $randomColorAttributes .= ',';
            }
        }
        unset($key);
        $randColor = call_user_func_array("Utility::randomColor", str_getcsv($randomColorAttributes));
        return $randColor;
    }

{:lang=“php”}

Breeding example

Here’s an example of a breeding. In the simulation I refer to a snail that bred as a male as a “stag”, female as “doe”, baby snail as “foal”.

In this case Ice (#327) and Fire (#329) were placed in the breeding jar. They were the only two snails in the jar to make sure they bred with each other.

Stag: Ice (#327)

Ice snail
Bred as a male
Shell color genotype: GB
Eye color genotype: RB
Pattern color genotype: BB
Pattern shape genotype: FE
Pattern radius genotype BS

Doe: Fire (#329)

Fire snail
Bred as a female
Shell color genotype: RG
Eye color genotype: GB
Pattern color genotype: RR
Pattern shape genotype: EE
Pattern radius genotype BS

Foal: Unnamed (#330)

Foal snail
Shell color genotype: BG (G > B)
Eye color genotype: RG (R > G)
Pattern color genotype: BR (R > B)
Pattern shape genotype: EE
Pattern radius genotype SS

But the new pattern shapes!

Here are some screenshots of various pattern shape/color combinations in the simulation today. These are still placeholders and will change. I don’t like all the super obvious tacky gradients. But it kind of gives me more variety to work with. There are currently 6 pattern options (one of which is lack of pattern)

Snail patternSnail patternSnail patternSnail patternSnail patternSnail patternSnail patternSnail patternSnail patternSnail patternSnail patternSnail patternSnail patternSnail patternSnail patternSnail patternSnail patternSnail pattern

comments powered by Disqus