Voici un prototype simplifié, sans gérer le sexe (qu'on peut choisir simplement grâce à du rand(1,2) en php - sauf si c'est comme les poules chez qui la température de couvaison détermine le sexe – à vérifier ) ; sans gérer l'évolution non plus, que j'aurais mise en surcouche une fois mon algo fini.
Je l'ai fait en php mais c'est 100 fois plus marrant en erlang !
Le modèle de données est bien sur discutable, on pourrait bosser sur des int au lieu de strings, mais là c'est plus lisible
Je l'ai fait en php mais c'est 100 fois plus marrant en erlang !
<?php
class genome_koi {
const recessive = 1;
const dominant = 2;
/* schéma des données,
* on peut le modéliser dans une base de données facilement
*/
static public function genes () {
return array(
'CF' => array(
'name' => 'Couleur de fond',
'alleles' => array(
// nom => type, valeur, chance contre un autre du même type
'CF1' => array(self::recessive, 'red', 50),
'CF2' => array(self::recessive, 'white', 50),
'CF3' => array(self::dominant, 'black', 100),
'CF4' => array(self::dominant, 'gold', 0)
),
'evolution_chances_percent' => 2,
'evolution_directions' => array(
'CF3' => 'CF2',
'CF1' => 'CF4'
)
),
'CP' => array(
'name' => 'Couleur principale',
'alleles' => array(
// nom => type, valeur, chance contre un autre du même type
'CP1' => array(self::recessive, 'red', 50),
'CP2' => array(self::recessive, 'white', 50),
'CP3' => array(self::dominant, 'black', 100)
)
),
'T1V' => array(
'name' => 'Tache 1 visible',
'alleles' => array(
// nom => type, valeur, chance contre un autre du même type
'T1Vt' => array(self::recessive, true, 100),
'T1Vf' => array(self::dominant, false, 100)
)
),
'T1C' => array(
'name' => 'Tache 1 couleur',
'alleles' => array(
// nom => type, valeur, chance contre un autre du même type
'T1C1' => array(self::recessive, 'red', 50),
'T1C2' => array(self::recessive, 'white', 50),
'T1C3' => array(self::dominant, 'black', 100)
)
)
);
}
static function create_child($c1, $c2) { // chromosome 1, chromosome 2
/* Ici on va déterminer un enfant grâce aux deux
* chromosomes
*/
$genes = self::genes();
$genes_names = array_keys(self::genes());
$child_genes = array();
foreach ($genes_names as $name) {
list($type1, $value1, $chances1) = $genes[$name]['alleles'][$c1[$name]];
list($type2, $value2, $chances2) = $genes[$name]['alleles'][$c2[$name]];
if ($type1 > $type2) // chromosome 1 a un allele dominant, c2 récessif
$child_genes[$name] = $c1[$name];
elseif ($type2 > $type1) // l'inverse
$child_genes[$name] = $c2[$name];
else { // if type 1 == type 2
/* ici on en tire un au hasard en fonction de leurs chances */
$child_genes[$name] = ${'c'.self::random_allele($chances1, $chances2)}[$name];
}
}
return $child_genes;
}
static function random_allele($chances1, $chances2) {
$chances2 += $chances1;
$r = rand(1,$chances2);
return ($r > $chances1) ? 2 : 1;
}
}
function chromosome_exemple_1() {
return array(
'CF' => 'CF1',
'CP' => 'CP2',
'T1V' => 'T1Vt',
'T1C' => 'T1C3'
);
}
function chromosome_exemple_2() {
return array(
'CF' => 'CF2',
'CP' => 'CP3',
'T1V' => 'T1Vf',
'T1C' => 'T1C1'
);
}
var_dump(genome_koi::create_child(chromosome_exemple_1(),chromosome_exemple_2()));
Le modèle de données est bien sur discutable, on pourrait bosser sur des int au lieu de strings, mais là c'est plus lisible