From OpenTTD
Jump to: navigation, search



To avoid code-duplication, and every AI creator doing the same work over and over, there is the library system. There are, of course, two sides on this: creating a library, and using a library.

Using Existing Libraries

To use an existing library, you just have to load it into your AI. Doing this is very simple. The layout of the library directory (bin/ai/library/):


Say you want to use the Priority Queue, you simply do:

import("queue.priority_queue", "PriorityQueue", 2);

The first parameter is the category and the implementation, divided with a dot ('.'). The next parameter is the name the library you import will have, in this case PriorityQueue. It can be anything you like, as long as it doesn't exist yet. The last parameter is the version you expect the library to be. To get the current version of a library, open library.nut from the corresponding directory.

The version check is very important. If you expect version 1, but on some users computer the library is in version 2, your AI will refuse to load. This is a good thing, as a new version means something changed with the existing functions, and your AI will most likely act up if you would use it. This early problem detection system should avoid many conflicts in the future.

Now how to use the library? Simple:

local pq = PriorityQueue();

Of course it depends on the library which parameters should be given to the constructor, and which functions exist. You'll have to open queue/priority_queue/main.nut to see all the documentation.

Creating a library

Creating a library is like creating an AI. You create a directory in a category in bin/ai/library, and you put in it a file called 'library.nut'. Now this is almost identical with 'info.nut', as you put in your AI directory, but instead of extending AIInfo, it extends AILibrary, and instead of calling RegisterAI, you need to call RegisterLibrary. All makes sense, not? An example:

class PriorityQueue extends AILibrary {
  function GetAuthor()      { return "OpenTTD NoAI Developers Team"; }
  function GetName()        { return "Priority Queue"; }
  function GetShortName()   { return "QUPQ"; }
  function GetDescription() { return "An implementation of a Priority Queue"; }
  function GetVersion()     { return 2; }
  function GetDate()        { return "2008-06-10"; }
  function CreateInstance() { return "PriorityQueue"; }
  function GetCategory()    { return "Queue"; }


Now what you need to do is to create a file called 'main.nut'. It should contain a class you named at CreateInstance(), like in your AI. Then the same rules apply as an AI. require() works as you expect, and you can define your class how ever you like.

There are some things you can not do:

  • Register 2 libraries in one library.nut
  • Define more than 1 class in the main.nut (or any required file). However, you can define sub-classes. Say you need an extra class in PriorityQueue. You can name it PriorityQueue.Subclass. To access it from within your main class, use this.Subclass. See graph.AyStar for an example how it's done.

Multiple libraries of different versions

It will happen to all of us that you have one AI using version 1 of a library, and an other using version 2. For example we take pathfinder.road. Now version 2 will be in ai/library/pathfinder/road, but where should you put version 1? For that we created a method:

In the directory-name of the library, everything behind any '.' (dot) is ignored. So you can call 'road' 'road.blabla', or 'road.2', it doesn't matter for the internals. Now this also allows multiple libraries of the same name, and different versions. For example, if you put version 1 of the pathfinder.road in 'pathfinder/road.1', and keep version 2 in 'pathfinder/road'. The system will load both, and based on your import line, pick one of them (or throws an error if the version you requested doesn't exist ;)).

The collision system still works. So if you put version 2 in both 'pathfinder/road' and 'pathfinder/road.2', it will complain it found two equal libraries.

Standard libraries

There are several libraries for common tasks bundled together with NoAI. These have been prepared by 'OpenTTD NoAI Developers Team'.

Category: Graph


This is an implementation of AyStar pathfinding algorithm. It solves graphs by finding the fastest route from one point to the other.

Required libraries: queue.binary_heap

Version History:

  • aystar.1: r13461
  • aystar.2: r13463
  • aystar.3: r13496
  • aystar.4: current

Category: Pathfinder


This is an implementation of a basic road pathfinder. You can use it to find the length of existing routes and / or to build new routes. Since version 3 building of tunnels / bridges is supported. For more information, see AI:RoadPathfinder

Required libraries: graph.aystar

Version History:

  • road.1: r13500
  • road.2: r13570
  • road.3: current


This is an implementation of a basic rail pathfinder. You can use it to find a path for new railways. For more information, see AI:RailPathfinder

Required libraries: graph.aystar

Version History:

  • rail.1: r14382

Category: Queue

Binary Heap

This is an implementation of binary heap data structure.

Version History:

  • binary_heap.1: current

Priority Queue

This is an implementation of priority queue data structure.

Version History:

  • priority_queue.1: r13440
  • priority_queue.2: r13447

Fibonacci Heap

This is an implementation of fibonacci heap data structure.

Version History:

  • Fibonacci_heap.1: 14380
Personal tools