Le principe

Après avoir initialisé l'état initial des cellules à un certain pourcentage de remplissage, nous allons calculer une nouvelle génération en suivant ces principes :

  • pour chaque case 'C' (contenant une cellule ou non) on calcule v1 le nombre de cellules présentes parmi les 8 cases candidates alentours :

+ - + - + - +
| 1 | 2 | 3 |
+ - + - + - +
| 4 | C | 5 |
+ - + - + - +
| 6 | 7 | 8 |
+ - + - + - +

  • pour chaque case 'C' (contenant une cellule ou non) on calcule v2 le nombre de cellules présentes parmi les 20 cases candidates alentours :

+ - + - + - + - + - +
| X | 9 | 10| 11| X |
+ - + - + - + - + - +
| 12| 1 | 2 | 3 | 13|
+ - + - + - + - + - +
| 14| 4 | C | 5 | 15|
+ - + - + - + - + - +
| 16| 6 | 7 | 8 | 17|
+ - + - + - + - + - +
| X | 18| 19| 20| X |
+ - + - + - + - + - +

  • si v1 est supérieur ou égal au seuil r1, ou si v2 est inférieur ou égal au seuil r2, une cellule est généré sur la case 'C' à la prochaine génération.
  • sinon une case vide est généré sur la case 'C' à la prochaine génération.

L'algorithme est relancé sur plusieurs générations avec des valeurs identiques r1 et r2.

Il est possible de le relancer ainsi plusieurs fois pendant n générations avec d'autres valeurs r1 et r2.

Quelques valeurs exemple

  • Construction de type 1
    • Initialisation avec un seuil de 40%
    • Calcul de 10 générations avec r1=5, r2=2
    • Calcul de 10 générations avec r1=5, r2=-1
    • Calcul de 1 génération avec r1=5, r2=2
  • Construction de type 2 : création d'une caverne avec des couloirs de 2 cases de large
    • Initialisation avec un seuil de 45%
    • Calcul de 5 générations avec r1=5, r2=-1
    • Calcul de 1 génération avec r1=5, r2=0
  • Construction de type 3 : couloirs de 1 de large
    • Initialisation avec un seuil de 45%
    • Calcul de 5 générations avec r1=5, r2=-1
    • Calcul de 1 génération avec r1=5, r2=1
  • Construction de type 4 : grands espaces ouverts
    • Initialisation avec un seuil de 45%
    • Calcul de 10 générations avec r1=5, r2=2
    • Calcul de 10 générations avec r1=5, r2=-1


Le code

On trouvera ci-dessous les grande lignes du code utilisé pour générer les cavernes. Numeric est ici utilisé pour travailler directement sur les tableaux, plutôt que sur les valeurs de chaque case des tableaux. Le code en est simplifié, et le traitement en est accéléré, puisque les opérations les plus gourmandes en CPU sont traitées au niveau du code compilé de Numeric, et pas du code interprété Python.

Initialisation du tableau de valeurs

On va créer un tableau à deux dimensions, rempli aléatoirement de 0 et de 1. Chaque case du tableau valant 1 correspond à une cellule.

self.zone = RandomArray.randint(0, 100, (self.taille[0]+4, self.taille[1]+4)) < seuil

Cette fonction crée un tableau de valeurs de 0 à 100, puis compare chaque valeur à seuil pour construire self.zone comme un tableau de 0 et de 1, selon un ratio de 'seuil' pour cent.

for i in range(-3,4): self.zone[i,:], self.zone[:,i] = 1, 1

Les bords de self.zone sont forcés à 1 sur trois rangées à droite, à gauche, en haut et en bas.

Calcul des cellules voisines

voisins_1 = ((-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1))
voisins_2 = ((-2,-1), (-2,0), (-2,1), (2,-1), (2,0), (2,1), (-1,-2), (0,-2), (1,-2), (-1,2), (0,2), (1,2))

Deux variables locales permettent de garder en mémoire la position relative des cellules qui nous intéressent autour d'une cellule donnée.

v1 = self.zone[3:-3,3:-3].astype(int)
for voisin in Cave.voisins_1: v1 += self.zone[3+voisin[0]:-3+voisin[0], 3+voisin[1]:-3+voisin[1]]

v1 est un tableau contenant dans chaque case le nombre de cellules présentes parmi les 8 candidates alentours.

v2 = v1.astype(int)
for voisin in Cave.voisins_2: v2 += self.zone[3+voisin[0]:-3+voisin[0], 3+voisin[1]:-3+voisin[1]]

v2 est un tableau contenant dans chaque case le nombre de cellules présentes parmi les 20 candidates alentours.

self.zone[3:-3,3:-3] = (v1 >= r1) | (v2 <= r2)

Une cellule est créée dans self.zone si v1 atteint ou dépasse le seuil r1, ou bien si v2 ne dépasse par le seuil r2. Dans le cas contraire, self.zone contiendra un espace. On utilise ici aussi les opérations sur les tableaux Numeric dont j'ai parlé plus haut.

self.zone = self.zone[2:-2,2:-2]

Pour finir on retire les bords de self.zone sur deux rangées, à droite, à gauche, en haut et en bas.