Mots-clé : labyrinth

Tableau comparatif des algorithmes

Labyrinthes : différents algorithmes

Tableau comparatif des algorithmes

Traduit en Français par moi-même. Les originaux sont fici.
Si vous voyez des fautes d’orthographe ou des corrections à apporter signalez-le moi je me ferai un plaisir de vous écouter !

Caractéristiques des algorithmes de création de labyrinthes parfaits
Algorithme Impasses % Type Focus Sans biais ? Uniforme ? Mémoire Temps Solution % Source
Unicursal 0 Arbre Mur Oui Jamais N^2 379 100.0 Walter Pullen
Retour-récursif 10 Arbre Passage Oui Jamais N^2 27 19.0 (Générique)
Chasse et tue 11 (21) Arbre Passage Oui Jamais 0 100 (143) 9.5 (3.9) Walter Pullen
Division récursive 23 Arbre Mur Oui Jamais N* 10 7.2 John Perry
Arbre binaire 25 Ensemble Les deux Non Jamais 0* 10 2.0 (Générique)
Sidewinder 27 Ensemble Les deux Non Jamais 0* 12 2.6 Walter Pullen
Algorithme d’Eller 28 Ensemble Les deux Non Non N* 20 4.2 (3.2) Marlin Eller
Algorithme de Wilson 29 Arbre Les deux Oui Oui N^2 48 (25) 4.5 David Wilson
Algorithme d’Aldous-Broder 29 Arbre Les deux Oui Oui 0 279 (208) 4.5 David Aldous & Andrei Broder
Algorithme de Kruskal 30 Ensemble Les deux Oui Non N^2 33 4.1 Joseph Kruskal
Algorithme de Prim (original) 30 Arbre Les deux Oui Non N^2 160 4.1 Robert Prim
Algorithme de Prim (simplifié) 32 Arbre Les deux Oui Non N^2 59 2.3 Robert Prim
Algorithme de Prim (modifié) 36 (31) Arbre Les deux Oui Non N^2 30 2.3 Robert Prim
Algorithme de l’arbre qui grandit 49 (39) Arbre Les deux Oui Non N^2 48 11.0 Walter Pullen
Algorithme de la forêt qui grandit 49 (39) Les deux Les deux Oui Non N^2 76 11.0 Walter Pullen

Ce tableau résume les caractéristiques des algorithmes de création de labyrinthes parfaits mentionnés ci-dessus. L’algorithme de labyrinthe unicursal (les labyrinthes unicursaux sont techniquement parfaits) est inclus à titre de comparaison. Voici les descriptions des colonnes :

Impasses : C’est le pourcentage approximatif de cellules qui sont des impasses dans un labyrinthe créé avec cet algorithme, lorsqu’il est appliqué à un labyrinthe orthogonal 2D. Les algorithmes dans le tableau sont triés selon ce critère. Généralement, créer en ajoutant des murs donne le même résultat que creuser des passages, cependant si la différence est significative, le pourcentage d’ajout de murs est indiqué entre parenthèses. La valeur de l’Arbre qui grandit peut en réalité varier de 10% (toujours choisir la cellule la plus récente) à 49% (toujours échanger avec la cellule la plus ancienne). Avec un facteur de course suffisamment élevé, le Retour-récursif peut descendre en dessous de 1%. Le pourcentage maximum possible d’impasses dans un labyrinthe parfait orthogonal 2D est de 66%, ce qui correspondrait à un passage unicursal avec une série d’impasses d’une unité de longueur de chaque côté.

Type : Il existe deux types d’algorithmes de création de labyrinthes parfaits : Un algorithme basé sur les arbres fait croître le labyrinthe comme un arbre, ajoutant toujours à ce qui est déjà présent, ayant un labyrinthe parfait valide à chaque étape. Un algorithme basé sur les ensembles construit où il le souhaite, gardant la trace des parties du labyrinthe qui sont connectées entre elles, pour s’assurer qu’il peut tout relier pour former un labyrinthe valide une fois terminé. Certains algorithmes comme la Forêt qui grandit font les deux en même temps.

Focus : La plupart des algorithmes peuvent être implémentés soit en creusant des passages, soit en ajoutant des murs. Quelques-uns ne peuvent être réalisés que d’une seule manière. Les labyrinthes unicursaux sont toujours créés par ajout de murs puisqu’ils impliquent de bissecter des passages avec des murs, bien que le labyrinthe de base puisse être créé des deux façons. Le Retour-récursif ne peut pas être fait en ajoutant des murs car cela tend à donner un chemin solution qui suit le bord extérieur, où l’intérieur entier du labyrinthe est attaché à la bordure par une seule tige. De même, la Division récursive ne peut être faite qu’en ajoutant des murs en raison de son comportement de bissection. Chasse et tue est techniquement uniquement réalisé par creusement de passages pour une raison similaire, bien qu’il puisse être fait par ajout de murs si un effort particulier est fait pour croître vers l’intérieur depuis tous les murs frontières de manière égale.

Sans biais : Ceci indique si l’algorithme traite toutes les directions et tous les côtés du labyrinthe de manière égale, où l’analyse du labyrinthe après coup ne peut révéler aucun biais de passage. L’Arbre binaire est extrêmement biaisé, où il est facile de voyager vers un coin et difficile vers son opposé. Le Sidewinder est également biaisé, où il est facile de voyager vers un bord et difficile vers son opposé. L’algorithme d’Eller tend à avoir un passage à peu près parallèle aux bords de début ou de fin. Chasse et tue est sans biais, tant que la chasse est faite colonne par colonne ainsi que ligne par ligne pour éviter un léger biais le long d’un axe.

Uniforme : Ceci indique si l’algorithme génère tous les labyrinthes possibles avec une probabilité égale. « Oui » signifie que l’algorithme est complètement uniforme. « Non » signifie que l’algorithme peut potentiellement générer tous les labyrinthes possibles dans un espace donné, mais pas avec une probabilité égale. « Jamais » signifie qu’il existe des labyrinthes possibles que l’algorithme ne peut jamais générer. Notez que seuls les algorithmes sans biais peuvent être complètement uniformes.

Mémoire : C’est la quantité de mémoire supplémentaire ou de pile nécessaire pour implémenter l’algorithme. Les algorithmes efficaces ne requièrent et ne regardent que la bitmap du labyrinthe elle-même, tandis que d’autres nécessitent un stockage proportionnel à une seule ligne (N), ou proportionnel au nombre de cellules (N^2). Certains algorithmes n’ont même pas besoin d’avoir le labyrinthe entier en mémoire et peuvent être étendus indéfiniment (ceux-ci sont marqués d’un astérisque). L’algorithme d’Eller nécessite le stockage d’une ligne, mais compense largement cela puisqu’il n’a besoin de stocker que la ligne courante du labyrinthe en mémoire. Sidewinder n’a également besoin de stocker qu’une ligne du labyrinthe, tandis que l’Arbre binaire n’a besoin que de garder trace de la cellule courante. La Division récursive nécessite une pile jusqu’à la taille d’une ligne, mais à part cela n’a pas besoin de regarder la bitmap du labyrinthe.

Temps : Ceci donne une idée du temps nécessaire pour créer un labyrinthe avec cet algorithme, les nombres plus bas étant plus rapides. Les nombres sont seulement relatifs les uns aux autres (l’algorithme le plus rapide étant assigné à la vitesse 10) plutôt qu’en unités spécifiques, car le temps dépend de la taille du labyrinthe et de la vitesse de l’ordinateur. Ces nombres proviennent de la création de labyrinthes de passages 100×100 dans la dernière version de Daedalus. Généralement, créer en ajoutant des murs prend le même temps que creuser des passages, cependant si la différence est significative, le temps d’ajout de murs est indiqué entre parenthèses.

Solution : C’est le pourcentage de cellules du labyrinthe que le chemin solution traverse, pour un labyrinthe typique créé par l’algorithme. Cela suppose que le labyrinthe fait 100×100 passages avec le début et la fin dans des coins opposés. C’est une mesure de la « sinuosité » du chemin solution. Les labyrinthes unicursaux ont une sinuosité maximale, puisque la solution traverse l’ensemble du labyrinthe. L’Arbre binaire a la sinuosité minimale possible, où le chemin solution traverse simplement le labyrinthe et ne dévie jamais ou ne cesse jamais de progresser vers la fin. Généralement, créer en ajoutant des murs a les mêmes propriétés que creuser des passages, cependant si la différence est significative, le pourcentage d’ajout de murs est indiqué entre parenthèses.

Source : C’est la source de l’algorithme, ce qui signifie par qui il est nommé, ou qui l’a inventé ou popularisé. Certains sont listés comme « génériques », ce qui signifie qu’ils sont si évidents qu’ils ont été imaginés ou implémentés par de nombreuses personnes indépendamment. Walter Pullen a nommé « Chasse et tue », mais n’a pas inventé la technique, dont on peut trouver des implémentations datant de nombreuses années.

Labyrinthes Sidewinder

Labyrinthes : différents algorithmes

Labyrinthe Sidewinder

Traduit en Français par moi-même. Les originaux sont ici.
Si vous voyez des fautes d’orthographe ou des corrections à apporter signalez-le moi je me ferai un plaisir de vous écouter !

Labyrinthe Sidewinder

Cet algorithme simple est très similaire à l’algorithme de l’arbre binaire, et seulement légèrement plus compliqué. Le labyrinthe est généré ligne par ligne : Pour chaque cellule, décidez au hasard de creuser un passage vers la droite. Si un passage n’est pas creusé, alors considérez le passage horizontal qui vient d’être complété, formé par la cellule actuelle et toutes les cellules à gauche qui ont creusé des passages menant jusqu’à elle. Choisissez au hasard une cellule le long de ce passage, et creusez un passage vers le haut à partir de celle-ci (qui doit être la cellule actuelle si la cellule adjacente n’a pas creusé). Alors qu’un labyrinthe en arbre binaire monte toujours depuis la cellule la plus à gauche d’un passage horizontal, un labyrinthe Sidewinder monte depuis une cellule aléatoire. Alors qu’un arbre binaire a les bords supérieur et gauche du labyrinthe formant un long passage, un labyrinthe Sidewinder n’a que le bord supérieur formant un long passage. Comme l’arbre binaire, un labyrinthe Sidewinder peut être résolu de manière déterministe sans erreur de bas en haut, car à chaque ligne, il y aura toujours exactement un passage menant vers le haut. Une solution à un labyrinthe Sidewinder ne reviendra jamais sur elle-même ou ne visitera jamais une ligne plus d’une fois, bien qu’elle « serpente de côté en côté ». Le seul type de cellule qui ne peut pas exister dans un labyrinthe Sidewinder est une impasse avec le passage orienté vers le bas, car cela contredirait le fait que chaque passage montant mène au début. Un labyrinthe Sidewinder a tendance à avoir une solution élitiste, où le bon chemin est très direct, mais il y a beaucoup de longs faux chemins descendant du haut à côté de lui.

Labyrinthes en arbre binaire

Labyrinthes : différents algorithmes

Labyrinthes en arbre binaire

Traduit en Français par moi-même. Les originaux sont ici.
Si vous voyez des fautes d’orthographe ou des corrections à apporter signalez-le moi je me ferai un plaisir de vous écouter !

Labyrinthes en arbre binaire

C’est fondamentalement l’algorithme le plus simple et le plus rapide possible, cependant les labyrinthes qu’il produit ont une texture très biaisée. Pour chaque cellule, creusez un passage soit vers le haut, soit vers la gauche, mais pas les deux. Dans la version avec ajout de murs, pour chaque sommet ajoutez un segment de mur menant vers le bas ou vers la droite, mais pas les deux. Chaque cellule est indépendante de toutes les autres cellules, où vous n’avez pas besoin de vous référer à l’état des autres cellules lors de sa création. Par conséquent, c’est un véritable algorithme de génération de labyrinthe sans mémoire, sans limite de taille du labyrinthe que vous pouvez créer.
C’est fondamentalement un arbre binaire au sens informatique, si vous considérez le coin supérieur gauche comme la racine, où chaque nœud ou cellule a un parent unique qui est la cellule au-dessus ou à gauche de celle-ci. Les labyrinthes en arbre binaire sont différents des labyrinthes parfaits standards, puisqu’environ la moitié des types de cellules ne peuvent jamais exister en eux. Par exemple, il n’y aura jamais de carrefour, et toutes les impasses ont des passages pointant vers le haut ou vers la gauche, et jamais vers le bas ou vers la droite.
Le labyrinthe a tendance à avoir des passages menant en diagonale du coin supérieur gauche au coin inférieur droit, ce qui rend le labyrinthe beaucoup plus facile à naviguer du coin inférieur droit vers le coin supérieur gauche. Vous pourrez toujours voyager vers le haut ou vers la gauche, mais jamais les deux, donc vous pouvez toujours voyager de manière déterministe en diagonale vers le haut et vers la gauche sans rencontrer d’obstacles. C’est en voyageant vers le bas et vers la droite que vous rencontrerez des choix et des impasses. Notez que si vous retournez un labyrinthe en arbre binaire à l’envers et traitez les passages comme des murs et vice versa, le résultat est fondamentalement un autre arbre binaire.

Algorithme de la Division récursive

Labyrinthes : différents algorithmes

Algorithme de la Division récursive

Traduit en Français par moi-même. Les originaux sont ici.
Si vous voyez des fautes d’orthographe ou des corrections à apporter signalez-le moi je me ferai un plaisir de vous écouter !

Algorithme de la Division récursive

Cet algorithme est un peu similaire au retour-récursif, puisqu’ils sont tous deux basés sur une pile, sauf que celui-ci se concentre sur les murs plutôt que sur les passages. Commencez par créer un mur horizontal ou vertical aléatoire traversant la zone disponible dans une rangée ou une colonne aléatoire, avec une ouverture placée au hasard le long de celui-ci. Ensuite, répétez le processus de manière récursive sur les deux sous-zones générées par le mur de division. Pour de meilleurs résultats, privilégiez le choix horizontal ou vertical en fonction des proportions de la zone, par exemple une zone deux fois plus large que haute devrait être divisée plus souvent par un mur vertical. C’est l’algorithme le plus rapide sans biais directionnel, et peut même rivaliser avec les labyrinthes en arbre binaire car il peut terminer plusieurs cellules à la fois, bien qu’il ait le défaut évident de longs murs traversant l’intérieur. Cet algorithme est une forme de labyrinthes fractals imbriqués, sauf qu’au lieu de toujours créer des labyrinthes de taille de cellule fixe avec des labyrinthes de même taille dans chaque cellule, il divise la zone donnée de manière aléatoire en un labyrinthe de taille aléatoire 1×2 ou 2×1. La division récursive ne fonctionne pas comme un creuseur de passages, car cela aboutirait à un chemin de solution évident qui suit soit le bord extérieur, soit traverse directement l’intérieur.

Algorithme de Prim (modifié)

Labyrinthes : différents algorithmes

Algorithme de Prim (modifié)

Traduit en Français par moi-même. Les originaux sont ici.
Si vous voyez des fautes d’orthographe ou des corrections à apporter signalez-le moi je me ferai un plaisir de vous écouter !

Algorithme de Prim (modifié)

C’est l’algorithme de Prim pour produire un arbre couvrant minimal, modifié de sorte que tous les poids des arêtes soient les mêmes, mais également implémenté en regardant les cellules plutôt que les arêtes. Il nécessite un espace de stockage proportionnel à la taille du labyrinthe. Pendant la création, chaque cellule est d’un des trois types : (1) « Dedans » : La cellule fait partie du labyrinthe et a déjà été creusée, (2) « Frontière » : La cellule ne fait pas partie du labyrinthe et n’a pas encore été creusée, mais est à côté d’une cellule qui est déjà « dedans », et (3) « Dehors » : La cellule ne fait pas encore partie du labyrinthe, et aucun de ses voisins n’est « dedans » non plus.

Commencez par choisir une cellule, la mettre « dedans », et définir tous ses voisins comme « frontière ». Continuez en choisissant une cellule « frontière » au hasard, et en creusant vers elle à partir d’une de ses cellules voisines qui sont « dedans ». Changez cette cellule « frontière » en « dedans », et mettez à jour tous ses voisins qui sont « dehors » en « frontière ». Le labyrinthe est terminé quand il n’y a plus de cellules « frontière » (ce qui signifie qu’il n’y a plus de cellules « dehors » non plus, donc elles sont toutes « dedans »).

Cet algorithme donne des labyrinthes avec un facteur « rivière » très bas avec beaucoup d’impasses courtes, et une solution plutôt directe. Le labyrinthe résultant est très similaire à l’algorithme de Prim simplifié, avec seulement la subtile distinction que les indentations dans l’arbre en expansion ne sont remplies que si cette cellule frontière est sélectionnée au hasard, contrairement au fait d’avoir trois fois plus de chances de remplir cette cellule via une des arêtes frontières menant à elle. Il s’exécute également très rapidement, plus rapidement que l’algorithme de Prim simplifié car il n’a pas besoin de composer et de maintenir une liste d’arêtes.

Algorithme de Prim (simplifié)

Labyrinthes : différents algorithmes

Algorithme de Prim (simplifié)

Traduit en Français par moi-même. Les originaux sont ici.
Si vous voyez des fautes d’orthographe ou des corrections à apporter signalez-le moi je me ferai un plaisir de vous écouter !

Algorithme de Prim (simplifié)

C’est l’algorithme de Prim pour produire un arbre couvrant minimal, simplifié de telle sorte que tous les poids des arêtes sont les mêmes. Il nécessite un espace de stockage proportionnel à la taille du labyrinthe. Commencez avec un sommet aléatoire. Continuez en sélectionnant au hasard une arête de passage reliant le labyrinthe à un point qui n’en fait pas encore partie, et attachez-la au labyrinthe. Le labyrinthe est terminé quand il n’y a plus d’arêtes à considérer. Comme les arêtes n’ont pas de poids et ne sont pas ordonnées, elles peuvent être stockées dans une simple liste, ce qui signifie que la sélection d’éléments dans la liste est très rapide et ne prend qu’un temps constant. Par conséquent, c’est beaucoup plus rapide que l’algorithme de Prim original avec des poids d’arêtes aléatoires. La texture du labyrinthe produit aura un facteur « rivière » plus faible et une solution plus simple que l’algorithme de Prim original, car il se répandra uniformément à partir du point de départ comme du sirop versé, au lieu de contourner et de s’écouler autour des groupes d’arêtes de poids plus élevé qui ne sont pas couverts avant plus tard. Copy

Algorithme de Prim (original)

Labyrinthes : différents algorithmes

Algorithme de Prim (original)

Traduit en Français par moi-même. Les originaux sont ici.

Si vous voyez des fautes d’orthographe ou des corrections à apporter signalez-le moi je me ferai un plaisir de vous écouter !

Algorithme de Prim (original)<

C’est l’algorithme de Prim pour produire un arbre couvrant minimal, opérant sur des poids d’arêtes aléatoires uniques. Il nécessite un espace de stockage proportionnel à la taille du labyrinthe.

Fonctionnement de l’algorithme :

  1. Commencez avec n’importe quel sommet (le labyrinthe final sera le même quel que soit le sommet de départ).
  2. Continuez en sélectionnant l’arête de passage ayant le plus petit poids qui relie le labyrinthe à un point qui n’en fait pas encore partie.
  3. Attachez cette arête au labyrinthe.
  4. Le labyrinthe est terminé quand il n’y a plus d’arêtes à considérer.

Pour sélectionner efficacement l’arête suivante, une file de priorité (généralement implémentée avec un tas) est nécessaire pour stocker les arêtes frontières. Malgré cela, cet algorithme est relativement lent, car la sélection d’éléments et la maintenance du tas nécessitent un temps logarithmique (log(n)).

Par conséquent, l’algorithme de Kruskal, qui produit également un arbre couvrant minimal, peut être considéré comme meilleur, car il est plus rapide et produit des labyrinthes avec une texture identique. En fait, avec la même graine de nombres aléatoires, des labyrinthes identiques peuvent être créés avec les algorithmes de Prim et de Kruskal.

Trackmania 2 / ManiaScript, ManiaPlanet et Labyrinthes : génération automatique

Vous avez peut-être vu que j’avais écrit un générateur de labyrinthes en C, qui créait en bout de course un fichier Autohotkey (là aussi je vous laisse vous renseigner). Ce fichier Autohotkey lançait Trackmania United Forever et automatisait la pose de blocs, et au final il y avait une course dans… un labyrinthe de blocs de course. J’avais donc modifié Trackmania afin d’en faire un outil pour jouer dans des labyrinthes !

Trackmania 2 est sorti, en version bêta, avec achat pour 0.01 € de moins.
Comme c’était une offre extraordinaire, j’ai sauté sur l’occasion.

Et dans Trackmania 2, ils ont fait très fort (même si ça n’est pas encore 100 % terminé, c’est déjà très abouti) : dans leur éditeur de maps, ils ont fait un langage de programmation qui leur est propre, une sorte de fils caché entre le JavaScript et XML, avec quelques attouchements de C et de « principes objet ».
Je trouve que ça n’est pas très lisible, et encore moins maintenable, mais bon, c’est pour un jeu, alors il faut pas en demander trop, surtout quand on voit qu’on n’est pas que joueur, mais qu’on peut être acteur !
Ce pseudo-langage de programmation s’appelle «ManiaScript».

Je me suis dit : je vais refaire mon générateur de labyrinthes, mais pour «ManiaScript».
J’ai donc commencé à préparer le terrain en «ManiaScript» : j’ai préparé des routines de poses de blocs, des routines pour poser les montées, etc. J’en ai profité pour faire une petite copie d’écran que je vous livre avec plaisir (cliquez dessus pour agrandir) :

Image Trackmania de Labyrinthes

Puis j’en ai profité pour me repencher sur mon ancien générateur, et je me suis dit : je vais le reprendre, afin de lui faire générer des scripts «ManiaScript».

C’est ce que j’ai fait, et au bout de deux soirées passées à tout ré-analyser ce que j’avais fait (même si je mets des tonnes de commentaires, mon générateur est en C pur, donc c’est très dur (pour moi en tous les cas) de me replonger dans le bain), j’ai enfin pu recompiler et générer quelque chose. J’en ai donc fait une copie d’écran que je vous livre avec plaisir (cliquez dessus pour agrandir) :

Image Trackmania de Labyrinthes

Et puis j’ai repassé toute une soirée à réussir à lier les deux. Le plus gros problème vient du fait que je prends les repères mathématiques «classiques» c’est à dire en vertical, Y, à l’horizontal X, et en profondeur Z. Dans Trackmania, le Y et Z sont inversés. Bonjour le casse tête mais je n’étais pas à ça près. J’ai donc réussi : j’ai fait une copie d’écran que je vous livre avec un bien plus grand plaisir que les deux précédents (cliquez dessus pour agrandir) :

Image Trackmania de Labyrinthes

La pose des montées se fait avant la pose des blocs principaux. C’est assez marrant à voir, et comme je suis gentil, je vous ai même fait une copie d’écran (cliquez dessus pour agrandir) :
Image Trackmania de Labyrinthes

Ensuite, j’ai voulu tester les limites de ma machine, et j’ai crée le plus grand labyrinthe possible pour Trackmania 2, et à mon grand plaisir, le jeu n’a pas explosé, comme il le faisait pour Trackmania United. Mattez moi ça (cliquez dessus pour agrandir) :
Image Trackmania de Labyrinthes

Trackmania 2 a une nouveauté extraordinaire : ils précalculent les ombres avec un réalisme époustouflant, et j’ai donc demandé de précalculer avec le maximum de précision (il y a six niveaux, et le plus détaillé prend plusieurs heures de calcul), et voilà ce que ça a donné (cliquez dessus pour agrandir) :
Image Trackmania de Labyrinthes

Ensuite, je me suis dit que les labyrinthes c’est bien joli, mais uniquement des blocs carrés, c’est pas très marrant. Donc j’ai décidé d’améliorer le tout, et j’ai trouvé un truc : après que le labyrinthe ait été posé par le script, j’ai imaginé rajouter en «ManiaScript» du code qui « décore » le labyrinthe. Par exemple, pour les tournants, j’ai mis des blocs de type « route », et j’ai ajouté un bloc « carré » pour terminer tous les cul-de-sac (cliquez dessus pour agrandir) :
Image Trackmania de Labyrinthes

Et puis je me suis aperçu que les blocs avaient la possibilité d’avoir des néons incrustés, et que les tournants étaient éclairés, j’ai essayé de voir ce que ça donnait en mode nuit, et c’est vraiment beau (cliquez dessus pour agrandir) :
Image Trackmania de Labyrinthes

J’ai recalculé le même labyrinthe afin que vous puissiez comparer avec et sans les améliorations (cliquez dessus pour agrandir) :
Image Trackmania de Labyrinthes
Image Trackmania de Labyrinthes

Et le même labyrinthe en mode nuit (cliquez dessus pour agrandir) :
Image Trackmania de Labyrinthes

Ensuite, j’ai trouvé d’autres types de blocs dont j’ai pu me servir pour améliorer encore le rendu, et faire des tunnels. Le rendu de nuit des tunnels est encore plus joli (cliquez dessus pour agrandir) :
Image Trackmania de Labyrinthes

Et puis les dernières captures, qui concernent le seul circuit que j’ai entièrement validé, sur douze étages (cliquez dessus pour agrandir) :
Image Trackmania de Labyrinthes

Et comble de joie, le dernier étage a en plus le tout dernier type de tunnels que j’avais implémenté, mais il ne sort que très rarement sur les labyrinthes qui ne sont pas très larges (celui ci fait 4×4) (cliquez dessus pour agrandir) :
Image Trackmania de Labyrinthes