NoAI Framework

NoAI Main Page


Development milestones
Suggested API changes

AI Programming

API Documentation
info.nut file
main.nut file
Using the road pathfinder
Using the rail pathfinder
Saving / Loading data
Things you need to know
Home page
Common mistakes
Coping with OTTD errors
AI Libraries
Forum FAQ
AI Behavior
ShortNames in use


Comparison of AIs
See forum
See BaNaNaS
All articles in NoAI category

We assume that you read the Introduction, which explains how to add an AI to OpenTTD. This page will explain how to add some simple things to make your AI do something. The result is in the Example AIs.


Naming your company

Of course the first thing you want to do, is name your company. You want to promote yourself, won't you? To change your company name, you need to load up the AICompany class. In Squirrel all classes are pre-loaded, so you can use it directly.

Now let's change our company name. The function to do this, as the API tells us, is SetName. The parameter is a string. So we get:

function MyNewAI::Start()

Now if you payed a bit of attention, you immediately notice that this goes against a rule you learn in the Introduction: the Start() returns, therefore your AI dies. But, this is just for illustration, so it will do fine for now.

Start OpenTTD, start a new map, and see how your AI now makes the company name change of the new player to MyNewAI.

Naming your company (advanced)

But now what happens if your AI starts two times. You can't have two AIs with the same company-name. If you run it, you will see that the second name stays Unnamed. That sucks. Lucky we can check the result of the function if it went okay. So let's extend it a bit, and check the result. If it fails, let's find ourselves an other name.

function MyNewAI::Start()
  if (!AICompany.SetName("MyNewAI")) {
    local i = 2;
    while (!AICompany.SetName("MyNewAI #" + i)) {
      i = i + 1;

What happens here, is that if naming the AI to MyNewAI fails, it tries MyNewAI #2. If that fails, it tries MyNewAI #3, etc etc. At some point it should work, or rather, that is the idea. So there you have it, your first AI that does something ingame.

Printing debug output

To print output to the AI Debug Panel, you can use AILog. These messages are also written to the console (AILog.Info with ai debug level 4 or higher, AILog.Warning with level 3 or higher and AILog.Error with level 1 or higher). Note that these functions only accept a string as parameter. If you want to print anything else, convert it to a string first. The easiest way to do that is appending an empty string, for example:

AILog.Info(some_integer + "");

Event System

The event system is a simple poll system. You will need to poll the event-controller once in a while to see if there are any relevant events for you on the stack. Doing this is relative easy:

while (AIEventController.IsEventWaiting()) {
  local e = AIEventController.GetNextEvent();
  switch (e.GetEventType()) {
      local ec = AIEventVehicleCrashed.Convert(e);
      local v  = ec.GetVehicleID();
      AILog.Info("We have a crashed vehicle (" + v + ")");
      /* Handle the crashed vehicle */

Now what?

How to proceed next depends very much on what you want your AI to do. The best thing to do is to start browsing through the API. We suggest to start with a road-vehicle-only AI. We know it is really boring, but you can really make a lot of money with them, if done correctly. Also, it is much easier to create and understand than trains are. Ships and aircraft are also very doable, but more boring than road-vehicles.

For example, if you want to build road and road-stations, check AIRoad documentation. You will find the right functions there. For station information check AIStation. For vehicle-building and settings orders, check AIVehicle and AIOrder. Sounds all pretty logical, doesn't it?

Of course there are many things that make your life easier. There is for example a piece of code that queues all your commands in a big list and starts executing them on request all at once. Now if one fails, where it didn't before, it rolls everything back. This is very useful from time to time, as when planning a route it might have looked to be no problem to build it, but by the time a road piece is placed, it can be that an other company has taken the tile already. Such pieces of code makes handling those situations a bit easier. Other examples are pathfinders, and more of those things.