AI Question: get event name

Discuss the new AI features ("NoAI") introduced into OpenTTD 0.7, allowing you to implement custom AIs, and the new Game Scripts available in OpenTTD 1.2 and higher.

Moderator: OpenTTD Developers

User avatar
Lord Aro
Tycoon
Tycoon
Posts: 2369
Joined: 25 Jun 2009 16:42
Location: Location, Location
Contact:

AI Question: get event name

Post by Lord Aro »

on my AI that i'm (very slowly) making i have used the code from Rondje (and simpleai) to build the company's HQ

Code: Select all

function AroAI::BuildHQ() //from Rondje
{
if(AIMap.IsValidTile(AICompany.GetCompanyHQ(AICompany.COMPANY_SELF))) return;//from simpleai

// Find biggest town for HQ
local towns = AITownList();
towns.Valuate(AITown.GetPopulation);
towns.Sort(AIAbstractList.SORT_BY_VALUE, false);
local town = towns.Begin();

// Find empty 2x2 square as close to town centre as possible
local maxRange = Sqrt(AITown.GetPopulation(town)/100) + 5; //TODO check value correctness
local HQArea = AITileList();
HQArea.AddRectangle(AITown.GetLocation(town) - AIMap.GetTileIndex(maxRange, maxRange), 
AITown.GetLocation(town) + AIMap.GetTileIndex(maxRange, maxRange));
HQArea.Valuate(AITile.IsBuildableRectangle, 2, 2);
HQArea.KeepValue(1);
HQArea.Valuate(AIMap.DistanceManhattan, AITown.GetLocation(town))
HQArea.Sort(AIList.SORT_BY_VALUE, true);
for (local tile = HQArea.Begin(); HQArea.IsEnd(); tile = HQArea.Next())
{
if (AICompany.BuildCompanyHQ(tile)) 
	{AISign.BuildSign(tile, "AroAI HQ");
		return;
	}
}
the offending area is the:

Code: Select all

for (local tile = HQArea.Begin(); HQArea.IsEnd(); tile = HQArea.Next())
specifically the

Code: Select all

HQArea.IsEnd()
i have already changed it from

Code: Select all

HQArea.HasNext()
as that has been changed

the trouble is that whenever my ai runs now, it always fails to build an HQ
any comments?
i'm a real beginner at this, but i am learning, so please be patient :bow:

hope this makes some sort of sense,

EDITS: topic name change
Last edited by Lord Aro on 02 Oct 2010 12:44, edited 10 times in total.
AroAI - A really feeble attempt at an AI

It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration. --Edsger Dijkstra
User avatar
Michiel
Transport Coordinator
Transport Coordinator
Posts: 339
Joined: 13 Jul 2008 00:57
Contact:

Re: converting HasNext() to trunk

Post by Michiel »

I think IsEnd() has the inverse meaning of HasNext(), so you'll need a "not" in the condition:

Code: Select all

for (local tile = HQArea.Begin(); !HQArea.IsEnd(); tile = HQArea.Next())
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: converting HasNext() to trunk

Post by Zuu »

Or you can use a foreach-loop.

Code: Select all

foreach (tile, _ in HQArea)

Mind the underscore (_). If you omit ", _", then you'll loop over all the values associated with the tiles, not the tiles themself.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
User avatar
Lord Aro
Tycoon
Tycoon
Posts: 2369
Joined: 25 Jun 2009 16:42
Location: Location, Location
Contact:

Re: Lord Aro's coding problems

Post by Lord Aro »

thanks chaps :roll:
i used Michiel's because it was easiest, although i should know that
you're still both awesome :bow:

Next Problem:
i want my ai to do something on a certain date - e.g. new years day
my current code is something like:

Code: Select all

...
if (AIDate.GetMonth==1);
if (AIDate.GetDayOfMonth==1);
{AILog.Info("Happy New Year!");}
...
AroAI - A really feeble attempt at an AI

It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration. --Edsger Dijkstra
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: Lord Aro's coding problems

Post by Zuu »

Don't put a semicolon after a if, for or while statement unless you know what you are doing. They are in most cases evil!

An if statement will execute the next line of code or block if the condition is true. A semicolon after the ending bracket will create a statement that do nothing. That results in the block of code after your if-statement always being executed.

This is ok:

Code: Select all

if (a == b)
{
  do_something();
}
This is also ok:

Code: Select all

if (a == b)
  do_something();
And this is ok:

Code: Select all

if (a == b) do_something();

This is how your code looks. It is valid code, but the do_something function will always get called even if a is not equal to b. This because of the empty statement at the same row as your if statement.

Code: Select all

if (a == b);
  do_something();

This is how I would re-write your code:

Code: Select all

if (AIDate.GetMonth() == 1 && AIDate.GetDayOfMonth() == 1) {
  AILog.Info("Happy New Year!");
}
While re-writing your code I also noticed that you forgot the empty brackets after GetMonth and GetDayOfMonth. In contrast to Delphi, VB(A), Ruby and some other languages, you must always include the brackets after the function name of the function that you want to call, even if you don't send any parameters. Otherwise you don't call the function.


Another problem with your code is that unless you do that check several times a day, you will have a chance of not finding out that there is a new year. The opposite could also become a problem. If you make that check more than once a day, then you will do your actions several times that day.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
User avatar
Lord Aro
Tycoon
Tycoon
Posts: 2369
Joined: 25 Jun 2009 16:42
Location: Location, Location
Contact:

Re: Lord Aro's coding problems

Post by Lord Aro »

thanks zuu :bow:
i really should make sure of silly mistakes like missing () out before i post :rolleyes:
i was thinking of having a looping function, not unlike the while(true) bit in Start()
i'll see if that works or whether it uses up too many opcodes (or whatever, im not sure what im talking about really)

more silly and basic problems coming soon! :lol:
AroAI - A really feeble attempt at an AI

It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration. --Edsger Dijkstra
User avatar
Lord Aro
Tycoon
Tycoon
Posts: 2369
Joined: 25 Jun 2009 16:42
Location: Location, Location
Contact:

Re: Lord Aro's coding problems

Post by Lord Aro »

problem: your script doesn't work! :(

debug=

Code: Select all

dbg: [ai] [1] [S] Your script made an error: wrong number of parameters
dbg: [ai] [1] [S] 
dbg: [ai] [1] [S] *FUNCTION [Start()] AroAI_RC1/main.nut line [22]
dbg: [ai] [1] [S] 
dbg: [ai] [1] [S] [types] INSTANCE
dbg: [ai] [1] [S] [this] INSTANCE
dbg: [ai] The AI died unexpectedly.
line 22 on my script=

Code: Select all

if (AIDate.GetMonth() == 1 && AIDate.GetDayOfMonth() == 1) {
:? :bow: etc. :lol:
AroAI - A really feeble attempt at an AI

It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration. --Edsger Dijkstra
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: Lord Aro's coding problems

Post by Yexo »

See the docs: http://noai.openttd.org/docs/trunk/classAIDate.html

Both GetMonth() and GetDayOfMonth() expect a date as parameter.
User avatar
Lord Aro
Tycoon
Tycoon
Posts: 2369
Joined: 25 Jun 2009 16:42
Location: Location, Location
Contact:

Re: Lord Aro's coding problems

Post by Lord Aro »

Code: Select all

Debugs.Info("Your Version is " + ((version & (15 << 28)) >> 28) + "." + ((version & (15 << 24)) >> 24) + " Build " + ((version & (15 << 20)) >> 20) + "" + (((version & (1 << 19)) >> 19)?" stable release, ":" r") + ((version & ((1 << 18) - 1))));
i have copied this code from Chopper - i've changed the words a bit, but it's essentially the same
the main problem is that i'm not sure what it does, if someone could explain in words what it's doing, that would be much appreciated :roll:
i would like it to eventually display the version number, e.g.

Code: Select all

Your Version is r20000
[or]
Your Version is 1.02
[or even]
Your Version is r20000 ez r45
is that last one possible?
is there an esay way to get whatever the name-version of the current openttd playing? we can find out prety easily (look at title bar)
AroAI - A really feeble attempt at an AI

It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration. --Edsger Dijkstra
User avatar
planetmaker
OpenTTD Developer
OpenTTD Developer
Posts: 9432
Joined: 07 Nov 2007 22:44
Location: Sol d

Re: Lord Aro's coding problems

Post by planetmaker »

Lord Aro wrote:

Code: Select all

Debugs.Info("Your Version is " + ((version & (15 << 28)) >> 28) + "." + ((version & (15 << 24)) >> 24) + " Build " +
 ((version & (15 << 20)) >> 20) + "" + (((version & (1 << 19)) >> 19)?" stable release, ":" r") + ((version & ((1 << 18) - 1))));
The code pasted will give you either "1.0 Build 2 stable release 20000" or "1.1 Build 0 r20009" for the current stable and somewhat current nightly respectively. If you replace the " Build " by a "." then you'll get a format more well known ;-)
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: Getting openttd version number

Post by Zuu »

You might also want to checkout AILib.Common which has a function for getting the OpenTTD version:

Code: Select all

    /**
     * Get current OpenTTD version.
     * @return A table with separate fields for each version part:
     * - Major: the major version
     * - Minor: the minor version
     * - Build: the build
     * - IsRelease: is this an stable release
     * - Revision: the svn revision of this build
     */
    static function GetVersion()
( Copied from http://noai.openttd.org/svn/lib-common/trunk/main.nut )
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
User avatar
Lord Aro
Tycoon
Tycoon
Posts: 2369
Joined: 25 Jun 2009 16:42
Location: Location, Location
Contact:

Re: Getting openttd version number

Post by Lord Aro »

thanks for that, i'll have a look at it
out of interest, what does either of them display if playing something such as cargodist?
can you possibly get it to display cargodist?
AroAI - A really feeble attempt at an AI

It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration. --Edsger Dijkstra
User avatar
Lord Aro
Tycoon
Tycoon
Posts: 2369
Joined: 25 Jun 2009 16:42
Location: Location, Location
Contact:

Re: Getting openttd version number

Post by Lord Aro »

next question:

how to get a list of towns within 50-ish tiles?
something to do with AIAbstractList i know
AroAI - A really feeble attempt at an AI

It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration. --Edsger Dijkstra
Kogut
Tycoon
Tycoon
Posts: 2493
Joined: 26 Aug 2009 06:33
Location: Poland

Re: get list of towns within certain distance of town or other

Post by Kogut »

your_valuated_town_list.KeepBelowValue(50);
Correct me If I am wrong - PM me if my English is bad
AIAI - AI for OpenTTD
User avatar
Lord Aro
Tycoon
Tycoon
Posts: 2369
Joined: 25 Jun 2009 16:42
Location: Location, Location
Contact:

Re: get list of towns within certain distance of town or other

Post by Lord Aro »

Kogut wrote:your_valuated_town_list.KeepBelowValue(50);
yes but what's: your_valuated_town_list?
AroAI - A really feeble attempt at an AI

It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration. --Edsger Dijkstra
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: get list of towns within certain distance of town or other

Post by Zuu »

Take a look here: http://wiki.openttd.org/AI:Lists

(also it is a good idea to read through all the NoAI-pages in the wiki as they contain useful information)
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
User avatar
Lord Aro
Tycoon
Tycoon
Posts: 2369
Joined: 25 Jun 2009 16:42
Location: Location, Location
Contact:

Re: get list of towns within certain distance of town or other

Post by Lord Aro »

1. ok, here's my code for my busroutebuilder

Code: Select all

import("pathfinder.road", "RoadPathFinder", 3);

class builder
 {
  constructor()
  {
  }
  town_list = 0;
 }

function builder::BuildBusRoute()
 {
  Debugs.Info("Planning on building bus route");
  AIRoad.SetCurrentRoadType(AIRoad.ROADTYPE_ROAD);
  town_list = AITownList();
  town_list.Valuate(AITown.GetPopulation());
  town_list.Sort(AIAbstractList.SORT_BY_VALUE, false);

  local town_a = town_list.Begin();
  local town_b = town_list.Next()
  if(GetDistanceManhattanToTile(town_a,GetTile(town_list.Next())) > 50)
  {
   town_list.RemoveValue(town_b);
    return;
  }
  else
  {
   *build bus route* //this definitely works
  }
it comes up with the error:

Code: Select all

Your script made an error: the index 'town_list' does not exist
it also points to line 13, but thats obvious due to that being the first place 'town_list' is mentioned


2. Also, could someone explain to me what the point of Stop(); and the constructor bit of the class is, becasue i don't know :]
AroAI - A really feeble attempt at an AI

It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration. --Edsger Dijkstra
Morloth
Transport Coordinator
Transport Coordinator
Posts: 378
Joined: 07 Feb 2008 14:06
Location: Glasgow

Re: get list of towns within certain distance of town or other

Post by Morloth »

1) I think the answer to this question is partially explained by your second question regarding the use of the contructor. I expect that you call the function like so:

Code: Select all

builder.BuildBusRoute();
which will not work. Squirrel is an object oriented language which means that every class like yours above are a blueprint. In order to use them you'll have to make an explicit instantiation of it like so:

Code: Select all

local bus_builder = builder();
When an instantiation is created the constructor is called. This is usually used to prepare the instantiation for usage. In your case you could - for example - construct the town_list. In brief this is the proper use of the above class:

Code: Select all

local bus_builder = builder();
bus_builder.BuildBusRoute();
Alternatively you could also make your function static which means it can be called without having to instantiate the class, but that's probably not what you want in this case.

Hope this helps,
Bram
Kogut
Tycoon
Tycoon
Posts: 2493
Joined: 26 Aug 2009 06:33
Location: Poland

Re: get list of towns within certain distance of town or other

Post by Kogut »

bad

Code: Select all

class builder
 {
  constructor()
  {
  }
  town_list = 0; //you mess with undeclared variable!
 }
good

Code: Select all

class builder
 {
town_list = null;
  constructor()
  {
  }
  town_list = 0;
 }
Correct me If I am wrong - PM me if my English is bad
AIAI - AI for OpenTTD
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: get list of towns within certain distance of town or other

Post by Zuu »

Kogut wrote: good

Code: Select all

class builder
 {
town_list = null;
  constructor()
  {
  }
  town_list = 0;
 }
better

Code: Select all

class builder
 {
town_list = null;
  constructor()
  {
    town_list = 0;
  }
 }
Do the initialization inside the constructor body. The "town_list = null;" is good to define the variable but you need to clear it inside the constructor to make sure it get cleared for each instance that is created of this class.

If you only create one builder, then you probably won't note any difference, but if you create many, then it becomes important to do the initialization properly in the constructor.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Post Reply

Return to “OpenTTD AIs and Game Scripts”

Who is online

Users browsing this forum: No registered users and 7 guests