Développement
Programmation de l'IA
- Documentation API
- Introduction
- Fichier info.nut
- Fichier main.nut
- Principes de base
- Détermination de chemin routier
- Détermination de chemin ferroviaire
- Sauver / Charger des données
- Choses à savoir
- Squirrel
- Listes
- Traiter les erreurs OTTD
- Tramways
- Bibliothèques de l'IA
- Forum
- FAQ du forum
- Comportement de l'IA
IAs
Tous les articles de la catégorie NonIA
Contents |
Conditions de prérequis
Avant d'appeler la détermination de chemin, vous devez choisir quel type de voie utiliser. Voici un moyen sûr suggéré par Zutty pour obtenir le premier type de voies de la liste.
local types = AIRailTypeList(); AIRail.SetCurrentRailType(types.Begin());
Initialisation
Vomme pour toute bibliothèque, avant de l'utiliser, vous devez l'importer. Vous pouvez le faire en plaçant la ligne suivante au début de votre code.
import("pathfinder.rail", "RailPathFinder", 1);
Cela importe la détermination de chemin ferroviaire version 1 et l'appelle RailPathFinder
. Vous pouvez maintenant l'instancier comme toute autre classe:
local pathfinder = RailPathFinder();
Avant de commencer à chercher un trajet, vous pouvez positionner quelques paramètres. Ceux qui sont disponibles sont:
Nom | Valeur par défaut | Signification |
---|---|---|
cost.max_cost | 2000000000 | Le coût maximal pour un trajet. |
cost.tile | 100 | Le coût pour une voie non en diagonale. |
cost.diagonal_tile | 70 | Le coût pour une voie en diagonale. |
cost.turn | 50 | Le coût ajouté à cost.tile / cost.diagonal_tile si la direction est modifiée. |
cost.slope | 100 | Le coût supplémentaire si la case est en pente. |
cost.bridge_per_tile | 150 | Le coût par case d'un nouveau pont; il sera ajouté à cost.tile. |
cost.tunnel_per_tile | 120 | Le coût par case d'un nouveau tunnel; il sera ajouté à cost.tile. |
cost.coast | 20 | Le coût supplémentaire d'une case côtière. |
cost.max_bridge_length | 6 | La longueur maximale d'un pont qui peut être construite. |
cost.max_tunnel_length | 6 | La longueur maximale d'un tunnel qui peut être construite. |
Pour fixer un paramètre, utilisez simplement:
pathfinder.cost.tile = 100;
Planifier un trajet
Donc, maintenant que nous savons comment créer une instance de détermination de chemin et fixer les coûts de construction, il est temps de mettre cette connaissance en pratique. Planifions notre première voie ferrée. Tout d'abord, nous avons besoin d'une (ou plusieurs) case(s) de départ et une (ou plusieurs) case(s) de destination. Pour cela, supposons que nous les avons déjà, car expliquer comment les obtenir dépasse le but de cette page. Disons donc, par exemple, que nous voulons construire une voie entre deux gares st_a et st_b. Pour cet exemple, nous supposerons que la direction des gares est NE_SO, et nous voulons relier le côté NE de la gare. Nous appelons d'abord InitializePath
de notre objet de détermination de chemin:
local tile_a = AIStation.GetLocation(st_a); local tile_b = AIStation.GetLocation(st_b); pathfinder.InitializePath([[tile_a, tile_a + AIMap.GetTileIndex(-1, 0)]], [[tile_b + AIMap.GetTileIndex(-1, 0), tile_b]]);
La détermination de chemin attend un tableau de tableaux [case_départ, case_avant_départ] et un tableau de tableaux [case_arrivée, case_après_arrivée]. Comme nous n'avons qu'un seul départ et une seule case d'arrivée, nous créons simplement deux tableaux avec un élément dans chaque. Maintenant, la détermination de chemin est prête à trouver un trajet.
local path = pathfinder.FindPath(-1);
Le paramètre que FindPath
accepte est le nombre d'itérations qu'il doit faire avant de se terminer. -1 signifie boucler jusqu'à ce qu'un chemin soit trouvé. Une fois ceci fait, la fonction renvoie soit le chemin trouvé, soit null pour indiquer qu'aucun trajet n'existe.
Construire le trajet planifié
Supposons que la détermination de chemin a renvoyé un trajet, comment commencer à le construire? Tout d'abord, il est intéressant de savoir que FindPath
renvoie une instance de la classe AyStar.Path
. Pour voir sa documentation, ouvrez bin/ai/library/graph/aystar/main.nut
. Globalement, elle a trois fonctions: GetParent()
, GetCost()
et GetTile()
. GetCost()
n'est pas très utile pour le moment; nous utiliserons donc uniquement GetParent()
et GetTile()
. Pour construire un trajet trouvé par la détermination de chemin, nous appelons path.GetParent()
jusqu'à ce qu'il renvoie null. Comme la détermination de chemin peut renvoyer des ponts et des tunnels, nous devons vérifier la distance entre le nœud courant et le précédent. Si cette distance est supérieure à 1, nous devons construire un pont ou un tunnel.
local prev = null; local prevprev = null; while (path != null) { if (prevprev != null) { if (AIMap.DistanceManhattan(prev, path.GetTile()) > 1) { if (AITunnel.GetOtherTunnelEnd(prev) == path.GetTile()) { AITunnel.BuildTunnel(AIVehicle.VT_RAIL, prev); } else { local bridge_list = AIBridgeList_Length(AIMap.DistanceManhattan(path.GetTile(), prev) + 1); bridge_list.Valuate(AIBridge.GetMaxSpeed); bridge_list.Sort(AIList.SORT_BY_VALUE, false); AIBridge.BuildBridge(AIVehicle.VT_RAIL, bridge_list.Begin(), prev, path.GetTile()); } prevprev = prev; prev = path.GetTile(); path = path.GetParent(); } else { AIRail.BuildRail(prevprev, prev, path.GetTile()); } } if (path != null) { prevprev = prev; prev = path.GetTile(); path = path.GetParent(); } }
Ce code boucle sur toute la longueur du trajet. Pour chaque élément, il tente de construire soit un pont ou un tunnel ou une portion de voie. Remarquez que dans une vraie IA, vous vérifieriez probablement si AIRail.BuildRail
renvoie true, et si non, vous relanceriez la détermination de chemin.