Some API extension ideas

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
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: Some API extension ideas

Post by Zuu »

Note: I leave it like this for tonight, I haven't checked against other sources than this thread to see what has already been implemented. If someone wants to take on that work, feel free to get started. :-) Hint: Quote my post, to get the source code with all url-tags etc.


Okay, so I went back a while and found a todo-list summary by Yexo from 29 Jan 2010 - http://www.tt-forums.net/viewtopic.php?p=852093#p852093
Yexo wrote:Todo:
  • Break AI on specific string (patch done by Zuu)
  • ChangeServicingInterval (probably won't make 1.0)
  • Check vehicles/stations belonging to other companies (probably won't make 1.0)
  • AIEventVehicleHasVoidOrder (not sure if this is really needed)
From there on I've skimmed and only added things that has not been rejected or implemented. Requests from the same post are grouped.
  • ChangeServicingInterval (probably won't make 1.0)
  • Check vehicles/stations belonging to other companies (probably won't make 1.0)
  • AIEventVehicleHasVoidOrder (not sure if this is really needed)
  • Get the annually maintenance cost of having transport mode at a station. Post
  • Get the build cost of stations/depots/waypoints
  • Get figures from the economy window for estimating how quick the company will earn X amount of money
  • AICompany.IsTownOwner(company_id) - So that you can determine if something is owned by a company or a town. Post
  • there is BuildNewGRFRailStation
    is it possible to have BuildNewGRFTileWithWaitingCargo
    or even BuildNewGRFTileWithBuilding?

    use: extending station coverage using rail station in looking-like-no-cheat-and-stupid-exploit way. Post
  • AIStation.GetAgeOfStation(station) http://www.tt-forums.net/viewtopic.php?p=866342#p866342
  • AICompany.ChangeCompanyColourTo(colour)
  • AICompany.GetCompanyColour()
  • AIVehicle.GetDirection(vehicle_id) Post
  • AIStation.IsCargoAccepted
  • AIVehicle.GetWeight(vehicle_id) Post
  • AIEngine.GetWeightOfFullyLoaded(engine_id) Post
  • AIMap::DistanceMin(TileIndex tile_from, TileIndex tile_to) Post
  • AIRail.GetRailwayTypeName(railway_type) Post
  • TileIndex AIVehicle.GetCargoOrigin(VehicleID,CargoID) Post
  • GetNextNearestTown() Post
  • Perhaps we could have the routine return the refit capacity for road vehicles, ships and planes, but not trains. These are the vehicle types that need this most and for these types the return values should be accurate, no? Post
  • I just got to the point in my AI where it started to transport goods to a town. At some point a message popped up that said the station no longer accepts goods and my trucks would run around without unloading. It would be very useful to get an Event for this that the AI can detect.http://www.tt-forums.net/viewtopic.php?p=890973#p890973 (several posts discussing this)
  • If it was possible to get these value... (amount of cargo delivered to towns) Post
  • AICompany.[Get/Set]CompanyColour(); Post
  • AICompany.IsSecondCompanyColourUsed();
  • AICompany.[Get/Set]SecondCompanyColour();
  • AICompany.[Get/Set]PresidentFace(*company-id*, *newgrf-style-input*); (if you get what i mean, like what is stored in openttd.cfg)
  • AIEventTownFounded Post
  • bool AIInfo::UseAsReplacementAI (like bool AIInfo::UseAsRandomAI ) Post
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Kogut
Tycoon
Tycoon
Posts: 2493
Joined: 26 Aug 2009 06:33
Location: Poland

Re: Some API extension ideas

Post by Kogut »

Update
-company colour (rejected)

Note: I leave it like this for tonight, I haven't checked against other sources than this thread to see what has already been implemented. If someone wants to take on that work, feel free to get started. :-) Hint: Quote my post, to get the source code with all url-tags etc.


Okay, so I went back a while and found a todo-list summary by Yexo from 29 Jan 2010 - http://www.tt-forums.net/viewtopic.php?p=852093#p852093
Yexo wrote:Todo:
  • Break AI on specific string (patch done by Zuu)
  • ChangeServicingInterval (probably won't make 1.0)
  • Check vehicles/stations belonging to other companies (probably won't make 1.0)
  • AIEventVehicleHasVoidOrder (not sure if this is really needed)
From there on I've skimmed and only added things that has not been rejected or implemented. Requests from the same post are grouped.
  • ChangeServicingInterval (probably won't make 1.0)
  • Check vehicles/stations belonging to other companies (probably won't make 1.0)
  • AIEventVehicleHasVoidOrder (not sure if this is really needed)
  • Get the annually maintenance cost of having transport mode at a station. Post
  • Get the build cost of stations/depots/waypoints
  • Get figures from the economy window for estimating how quick the company will earn X amount of money
  • AICompany.IsTownOwner(company_id) - So that you can determine if something is owned by a company or a town. Post
  • there is BuildNewGRFRailStation
    is it possible to have BuildNewGRFTileWithWaitingCargo
    or even BuildNewGRFTileWithBuilding?

    use: extending station coverage using rail station in looking-like-no-cheat-and-stupid-exploit way. Post
  • AIStation.GetAgeOfStation(station) http://www.tt-forums.net/viewtopic.php?p=866342#p866342
  • AIVehicle.GetDirection(vehicle_id) Post
  • AIStation.IsCargoAccepted
  • AIVehicle.GetWeight(vehicle_id) Post
  • AIEngine.GetWeightOfFullyLoaded(engine_id) Post
  • AIMap::DistanceMin(TileIndex tile_from, TileIndex tile_to) Post
  • AIRail.GetRailwayTypeName(railway_type) Post
  • TileIndex AIVehicle.GetCargoOrigin(VehicleID,CargoID) Post
  • GetNextNearestTown() Post
  • Perhaps we could have the routine return the refit capacity for road vehicles, ships and planes, but not trains. These are the vehicle types that need this most and for these types the return values should be accurate, no? Post
  • I just got to the point in my AI where it started to transport goods to a town. At some point a message popped up that said the station no longer accepts goods and my trucks would run around without unloading. It would be very useful to get an Event for this that the AI can detect.http://www.tt-forums.net/viewtopic.php?p=890973#p890973 (several posts discussing this)
  • If it was possible to get these value... (amount of cargo delivered to towns) Post
  • AICompany.[Get/Set]PresidentFace(*company-id*, *newgrf-style-input*); (if you get what i mean, like what is stored in openttd.cfg)
  • AIEventTownFounded Post
  • bool AIInfo::UseAsReplacementAI (like bool AIInfo::UseAsRandomAI ) Post
Correct me If I am wrong - PM me if my English is bad
AIAI - AI for OpenTTD
Hephi
Engineer
Engineer
Posts: 72
Joined: 25 Oct 2009 09:56
Location: Belgium

Re: Some API extension ideas

Post by Hephi »

why AIVehicle.GetWeight(vehicle_id) if you have AIEngine.GetWeight(AIVehicle.GetEngineType(vehicle_id)?

I'm still rooting for company colour though. :)

I've also been looking for something like AITown.GetTownStatus(id) which returns something like AITown.TOWN or AITOWN.CITY
Last edited by Hephi on 30 Nov 2010 20:00, edited 1 time in total.
--------------------------------------------------
MailAI, a casual postal service for openTTD.
--------------------------------------------------
Kogut
Tycoon
Tycoon
Posts: 2493
Joined: 26 Aug 2009 06:33
Location: Poland

Re: Some API extension ideas

Post by Kogut »

Update
-without AIVehicle.GetWeight(vehicle_id) Post
-company colour (rejected)
+AITown.IsCity(id) -> Patch

Note: I leave it like this for tonight, I haven't checked against other sources than this thread to see what has already been implemented. If someone wants to take on that work, feel free to get started. :-) Hint: Quote my post, to get the source code with all url-tags etc.


Okay, so I went back a while and found a todo-list summary by Yexo from 29 Jan 2010 - http://www.tt-forums.net/viewtopic.php?p=852093#p852093
Yexo wrote:Todo:
  • Break AI on specific string (patch done by Zuu)
  • ChangeServicingInterval (probably won't make 1.0)
  • Check vehicles/stations belonging to other companies (probably won't make 1.0)
  • AIEventVehicleHasVoidOrder (not sure if this is really needed)
From there on I've skimmed and only added things that has not been rejected or implemented. Requests from the same post are grouped.
  • ChangeServicingInterval (probably won't make 1.0)
  • Check vehicles/stations belonging to other companies (probably won't make 1.0)
  • AIEventVehicleHasVoidOrder (not sure if this is really needed)
  • Get the annually maintenance cost of having transport mode at a station. Post
  • Get the build cost of stations/depots/waypoints
  • Get figures from the economy window for estimating how quick the company will earn X amount of money
  • AICompany.IsTownOwner(company_id) - So that you can determine if something is owned by a company or a town. Post
  • there is BuildNewGRFRailStation
    is it possible to have BuildNewGRFTileWithWaitingCargo
    or even BuildNewGRFTileWithBuilding?

    use: extending station coverage using rail station in looking-like-no-cheat-and-stupid-exploit way. Post
  • AIStation.GetAgeOfStation(station) http://www.tt-forums.net/viewtopic.php?p=866342#p866342
  • AIVehicle.GetDirection(vehicle_id) Post
  • AIStation.IsCargoAccepted
  • AIEngine.GetWeightOfFullyLoaded(engine_id) Post
  • AIMap::DistanceMin(TileIndex tile_from, TileIndex tile_to) Post
  • AIRail.GetRailwayTypeName(railway_type) Post
  • TileIndex AIVehicle.GetCargoOrigin(VehicleID,CargoID) Post
  • GetNextNearestTown() Post
  • Perhaps we could have the routine return the refit capacity for road vehicles, ships and planes, but not trains. These are the vehicle types that need this most and for these types the return values should be accurate, no? Post
  • I just got to the point in my AI where it started to transport goods to a town. At some point a message popped up that said the station no longer accepts goods and my trucks would run around without unloading. It would be very useful to get an Event for this that the AI can detect.http://www.tt-forums.net/viewtopic.php?p=890973#p890973 (several posts discussing this)
  • If it was possible to get these value... (amount of cargo delivered to towns) Post
  • AICompany.[Get/Set]PresidentFace(*company-id*, *newgrf-style-input*); (if you get what i mean, like what is stored in openttd.cfg)
  • AIEventTownFounded Post
  • bool AIInfo::UseAsReplacementAI (like bool AIInfo::UseAsRandomAI ) Post
  • AITown.GetTownStatus(id) which returns something like AITown.TOWN or AITOWN.CITY
Correct me If I am wrong - PM me if my English is bad
AIAI - AI for OpenTTD
Attila7
Engineer
Engineer
Posts: 37
Joined: 31 May 2010 21:06

Re: Some API extension ideas

Post by Attila7 »

About the company color. When debugging or playing for that matter, I have a preferred color, that I get used to and recognize when I look at the game. I think the game needs a setup setting so the player can specify that she ALWAYS wants a specific color to be assigned. It is a chore to switch colors around so I can get my preferred color every time I run a test against other AIs. This could be restricted to single-player mode only.
Attila
"Artificial intelligence is no match for natural stupidity."
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: Some API extension ideas

Post by Yexo »

A big thanks to Zuu and Kogut for creating the list. I've copied it over to the wiki so everyone can keep it up to date. Please keep making suggestions here and only add them to the wiki after they have been discussed. I haven't included the rejected suggestions, if anyone really wants to feel free to put those on a separate page in the wiki. Suggestions list on the wiki

Here a short answer to those items I've not included on the list because I don't think it'd be a good idea to implement them. Note that there are a few ideas that are listed both here (because I've doubts about them) but also in the api suggestion list on the wiki to make sure they're not forgotten.
[*] there is BuildNewGRFRailStation
is it possible to have BuildNewGRFTileWithWaitingCargo
or even BuildNewGRFTileWithBuilding?

use: extending station coverage using rail station in looking-like-no-cheat-and-stupid-exploit way. Post
No, not possible with the current newgrf spec.
[*] AIEngine.GetWeightOfFullyLoaded(engine_id) Post
What should be implemented for this is something like AICargo::GetWeight(), than you could implement an approximation of this in squirrel. A perfect implementation isn't possible because the weight of a fully loaded engine depends on the capacity and the cargo type. You can read back the earlier discussion about the capacity after refit not being known to see why it's not possible.
[*] TileIndex AIVehicle.GetCargoOrigin(VehicleID,CargoID) Post
Each vehicle can have cargo from multiple origins, so returning a single origin isn't possible.
[*] GetNextNearestTown() Post
I honestly don't see the use of this. If you need this create a list of towns and sort them by distance, than take the first 2 instead of only the top one.
[*] Perhaps we could have the routine return the refit capacity for road vehicles, ships and planes, but not trains. These are the vehicle types that need this most and for these types the return values should be accurate, no? Post
Not possible, the problems for the other vehicle types are the same as those for trains.
[*] AICompany.[Get/Set]PresidentFace(*company-id*, *newgrf-style-input*); (if you get what i mean, like what is stored in openttd.cfg)
Same as color, is this really something an AI should do?
[*] bool AIInfo::UseAsReplacementAI (like bool AIInfo::UseAsRandomAI ) Post
Wouldn't every AI author implement this and return false? If so, there would never by any Ai available to replace the original AI from old savegames, and those savegames would be completely broken. I prefer the current solution where an AI is forced to take over and at least keeps doing something. Just try to prepare your Ai for this case as good as possible. Note that one option in doing so would be to detect things you don't support and sell the corresponding vehicles/stations.
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: Some API extension ideas

Post by Zuu »

Yexo wrote:
[*] bool AIInfo::UseAsReplacementAI (like bool AIInfo::UseAsRandomAI ) Post
Wouldn't every AI author implement this and return false? If so, there would never by any Ai available to replace the original AI from old savegames, and those savegames would be completely broken. I prefer the current solution where an AI is forced to take over and at least keeps doing something. Just try to prepare your Ai for this case as good as possible. Note that one option in doing so would be to detect things you don't support and sell the corresponding vehicles/stations.
Just for the record, I would probably do like this:
CluelessPlus: Allow takeover
PAXLink: Allow takeover
TownCars: Don't take over
IdleMore: Don't take over

I agree with you that it is good if most AIs can take over as users with old saves either from the old AI or that got from someone or an other computer which had some AIs not hon his/her current computer. It's good then if chances are high that one of the AIs can take over and run the AI company.

Hmm, I think it might be useful to have a console command to force an AI to take over a company number to test the take-over ability of your AI.


One thing that is a bit annoying is the Idle AI which has not declared that it shall not be chosen as a random AI. I don't know if it is a fair solution, but one solution would be to default to not including AIs as random AI just to enforce that the author at least have made a choice.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: Some API extension ideas

Post by Yexo »

I'm not 100% sure, but I think it will already exclude AIs that are marked as "don't chose this AI as random AI". Your post seems to support that, with TownCars and IdleMore both marked as "not as random AI".
Zuu wrote:One thing that is a bit annoying is the Idle AI which has not declared that it shall not be chosen as a random AI. I don't know if it is a fair solution, but one solution would be to default to not including AIs as random AI just to enforce that the author at least have made a choice.
Agreed, but the only thing we can do about that is complain to the author of Idle and keep suggestion to everyone to use IdleMore instead of Idle.
User avatar
Lord Aro
Tycoon
Tycoon
Posts: 2369
Joined: 25 Jun 2009 16:42
Location: Location, Location
Contact:

Re: Some API extension ideas

Post by Lord Aro »

Yexo wrote:
[*] bool AIInfo::UseAsReplacementAI (like bool AIInfo::UseAsRandomAI ) Post
Wouldn't every AI author implement this and return false? If so, there would never by any Ai available to replace the original AI from old savegames, and those savegames would be completely broken. I prefer the current solution where an AI is forced to take over and at least keeps doing something. Just try to prepare your Ai for this case as good as possible. Note that one option in doing so would be to detect things you don't support and sell the corresponding vehicles/stations.
i would say, if AIInfo::UseAsRandomAI is set (to false), then it should be implicit in that it is not used as a 'replacement' AI as well...

EDIT: ...
Last edited by Lord Aro on 29 Dec 2010 21:23, edited 1 time 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
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: Some API extension ideas

Post by Zuu »

So only those AIs that are NOT selected as random AI should be used as replacement AIs? What is the logic here?
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: Some API extension ideas

Post by Lord Aro »

no, read it again ;)

AIs that should NOT be used as randomAIs should NOT be used as replacement AIs
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: Some API extension ideas

Post by Zuu »

So I should have quoted you just so you shouldn't be able to change it and make me look stupid? :-p
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: Some API extension ideas

Post by Lord Aro »

yup :p
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: Some API extension ideas

Post by Kogut »

Is it possible to introduce AICompany::GetInauguratedDate?

And possibility to create separate waypoint, next to existing (effect od ctrl+click), (see AIRail::BuildRailStation)
Correct me If I am wrong - PM me if my English is bad
AIAI - AI for OpenTTD
Kogut
Tycoon
Tycoon
Posts: 2493
Joined: 26 Aug 2009 06:33
Location: Poland

Re: Some API extension ideas

Post by Kogut »

@waypoint - it is even worse, in situation like below AI is completely unable to place waypoint in marked place
Attachments
Przechwytywanie.PNG
Przechwytywanie.PNG (31.84 KiB) Viewed 7585 times
Correct me If I am wrong - PM me if my English is bad
AIAI - AI for OpenTTD
Kogut
Tycoon
Tycoon
Posts: 2493
Joined: 26 Aug 2009 06:33
Location: Poland

Re: Some API extension ideas

Post by Kogut »

Patch. Yexo suggested BuldRailWaypointTileRectangle, but as start this is something.

Code: Select all


Index: src/ai/api/ai_rail.cpp
===================================================================
--- src/ai/api/ai_rail.cpp	(revision 22987)
+++ src/ai/api/ai_rail.cpp	(working copy)
@@ -13,6 +13,7 @@
 #include "ai_rail.hpp"
 #include "ai_map.hpp"
 #include "ai_station.hpp"
+#include "ai_waypoint.hpp"
 #include "ai_industrytype.hpp"
 #include "ai_cargo.hpp"
 #include "../../debug.h"
@@ -205,6 +206,17 @@
 	return AIObject::DoCommand(tile, GetCurrentRailType() | (GetRailTracks(tile) == RAILTRACK_NE_SW ? AXIS_X : AXIS_Y) << 4 | 1 << 8 | 1 << 16, STAT_CLASS_WAYP | INVALID_STATION << 16, CMD_BUILD_RAIL_WAYPOINT);
 }
 
+/* static */ bool AIRail::BuildRailWaypointCtrl(TileIndex tile, StationID waypoint_id)
+{
+	EnforcePrecondition(false, ::IsValidTile(tile));
+	EnforcePrecondition(false, IsRailTile(tile));
+	EnforcePrecondition(false, GetRailTracks(tile) == RAILTRACK_NE_SW || GetRailTracks(tile) == RAILTRACK_NW_SE);
+	EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
+	EnforcePrecondition(false, waypoint_id == AIStation::STATION_NEW || waypoint_id == AIStation::STATION_JOIN_ADJACENT || AIWaypoint::IsValidWaypoint(waypoint_id));
+
+	return AIObject::DoCommand(tile, GetCurrentRailType() | (GetRailTracks(tile) == RAILTRACK_NE_SW ? AXIS_X : AXIS_Y) << 4 | 1 << 8 | 1 << 16 | ((waypoint_id != AIStation::STATION_JOIN_ADJACENT)? 1 : 0) << 24, STAT_CLASS_WAYP | (AIWaypoint::IsValidWaypoint(waypoint_id) ? waypoint_id : INVALID_STATION) << 16, CMD_BUILD_RAIL_WAYPOINT);
+}
+
 /* static */ bool AIRail::RemoveRailWaypointTileRectangle(TileIndex tile, TileIndex tile2, bool keep_rail)
 {
 	EnforcePrecondition(false, ::IsValidTile(tile));
Index: src/ai/api/ai_rail.hpp
===================================================================
--- src/ai/api/ai_rail.hpp	(revision 22987)
+++ src/ai/api/ai_rail.hpp	(working copy)
@@ -305,6 +305,19 @@
 	static bool BuildRailWaypoint(TileIndex tile);
 
 	/**
+	 * Build a rail waypoint.
+	 * @param tile Place to build the waypoint.
+	 * @param waypoint_id The waypoint to join, AIStation::STATION_NEW or AIStation::STATION_JOIN_ADJACENT.
+	 * @pre AIMap::IsValidTile(tile).
+	 * @pre IsRailTile(tile).
+	 * @pre GetRailTracks(tile) == RAILTRACK_NE_SW || GetRailTracks(tile) == RAILTRACK_NW_SE.
+	 * @pre IsRailTypeAvailable(GetCurrentRailType()).
+	 * @exception AIError::ERR_FLAT_LAND_REQUIRED
+	 * @return Whether the rail waypoint has been/can be build or not.
+	 */
+	static bool BuildRailWaypointCtrl(TileIndex tile, StationID waypoint_id);
+
+	/**
 	 * Remove all rail waypoint pieces within a rectangle on the map.
 	 * @param tile One corner of the rectangle to clear.
 	 * @param tile2 The oppposite corner.
Index: src/ai/api/ai_rail.hpp.sq
===================================================================
--- src/ai/api/ai_rail.hpp.sq	(revision 22987)
+++ src/ai/api/ai_rail.hpp.sq	(working copy)
@@ -95,6 +95,7 @@
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::BuildRailStation,                "BuildRailStation",                6, ".iiiii");
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::BuildNewGRFRailStation,          "BuildNewGRFRailStation",          11, ".iiiiiiiiib");
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::BuildRailWaypoint,               "BuildRailWaypoint",               2, ".i");
+	SQAIRail.DefSQStaticMethod(engine, &AIRail::BuildRailWaypointCtrl,           "BuildRailWaypointCtrl",           3, ".ii");
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::RemoveRailWaypointTileRectangle, "RemoveRailWaypointTileRectangle", 4, ".iib");
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::RemoveRailStationTileRectangle,  "RemoveRailStationTileRectangle",  4, ".iib");
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::GetRailTracks,                   "GetRailTracks",                   2, ".i");

Correct me If I am wrong - PM me if my English is bad
AIAI - AI for OpenTTD
Kogut
Tycoon
Tycoon
Posts: 2493
Joined: 26 Aug 2009 06:33
Location: Poland

Re: Some API extension ideas

Post by Kogut »

New version

Code: Select all

Index: src/ai/api/ai_rail.cpp
===================================================================
--- src/ai/api/ai_rail.cpp	(revision 22987)
+++ src/ai/api/ai_rail.cpp	(working copy)
@@ -13,6 +13,7 @@
 #include "ai_rail.hpp"
 #include "ai_map.hpp"
 #include "ai_station.hpp"
+#include "ai_waypoint.hpp"
 #include "ai_industrytype.hpp"
 #include "ai_cargo.hpp"
 #include "../../debug.h"
@@ -205,6 +206,30 @@
 	return AIObject::DoCommand(tile, GetCurrentRailType() | (GetRailTracks(tile) == RAILTRACK_NE_SW ? AXIS_X : AXIS_Y) << 4 | 1 << 8 | 1 << 16, STAT_CLASS_WAYP | INVALID_STATION << 16, CMD_BUILD_RAIL_WAYPOINT);
 }
 
+/* static */ bool AIRail::BuildRailWaypointTileRectangle(TileIndex tile, TileIndex tile2, StationID waypoint_id)
+{
+	EnforcePrecondition(false, ::IsValidTile(tile));
+	EnforcePrecondition(false, IsRailTile(tile));
+	EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
+	EnforcePrecondition(false, waypoint_id == AIStation::STATION_NEW || waypoint_id == AIStation::STATION_JOIN_ADJACENT || AIWaypoint::IsValidWaypoint(waypoint_id));
+	
+	Axis axis = GetRailTracks(tile) == RAILTRACK_NE_SW ? AXIS_X : AXIS_Y;
+	if (AIMap::GetTileY(tile)-AIMap::GetTileY(tile2)>0 || AIMap::GetTileX(tile)-AIMap::GetTileX(tile2>0))
+		{
+		TileIndex swap = tile;
+		tile=tile2;
+		tile2=swap;
+		DEBUG(misc, 0, "swap");
+		}
+
+	byte height = -(AIMap::GetTileY(tile2)-AIMap::GetTileY(tile))+1;
+	byte width = -(AIMap::GetTileX(tile2)-AIMap::GetTileX(tile))+1;
+	int print_width = width;
+	int print_height = height;
+
+	return AIObject::DoCommand(tile2, GetCurrentRailType() | axis << 4 | width << 8 | height << 16 | ((waypoint_id != AIStation::STATION_JOIN_ADJACENT)? 1 : 0) << 24, STAT_CLASS_WAYP | (AIWaypoint::IsValidWaypoint(waypoint_id) ? waypoint_id : INVALID_STATION) << 16, CMD_BUILD_RAIL_WAYPOINT);
+}
+
 /* static */ bool AIRail::RemoveRailWaypointTileRectangle(TileIndex tile, TileIndex tile2, bool keep_rail)
 {
 	EnforcePrecondition(false, ::IsValidTile(tile));
Index: src/ai/api/ai_rail.hpp
===================================================================
--- src/ai/api/ai_rail.hpp	(revision 22987)
+++ src/ai/api/ai_rail.hpp	(working copy)
@@ -305,13 +305,25 @@
 	static bool BuildRailWaypoint(TileIndex tile);
 
 	/**
+	 * Build a rail waypoint.
+	 * @param tile Place to build the waypoint.
+	 * @param waypoint_id The waypoint to join, AIStation::STATION_NEW or AIStation::STATION_JOIN_ADJACENT.
+	 * @pre AIMap::IsValidTile(tile).
+	 * @pre IsRailTile(tile).
+	 * @pre GetRailTracks(tile) == RAILTRACK_NE_SW || GetRailTracks(tile) == RAILTRACK_NW_SE.
+	 * @pre IsRailTypeAvailable(GetCurrentRailType()).
+	 * @exception AIError::ERR_FLAT_LAND_REQUIRED
+	 * @return Whether the rail waypoint has been/can be build or not.
+	 */
+	static bool BuildRailWaypointTileRectangle(TileIndex tile, TileIndex tile2, StationID waypoint_id);
+
+	/**
 	 * Remove all rail waypoint pieces within a rectangle on the map.
 	 * @param tile One corner of the rectangle to clear.
 	 * @param tile2 The oppposite corner.
-	 * @param keep_rail Whether to keep the rail after removal.
 	 * @pre IsValidTile(tile).
 	 * @pre IsValidTile(tile2).
-	 * @return Whether at least one tile has been/can be cleared or not.
+	 * @return Whether the rail waypoint has been/can be build or not.
 	 */
 	static bool RemoveRailWaypointTileRectangle(TileIndex tile, TileIndex tile2, bool keep_rail);
 
Index: src/ai/api/ai_rail.hpp.sq
===================================================================
--- src/ai/api/ai_rail.hpp.sq	(revision 22987)
+++ src/ai/api/ai_rail.hpp.sq	(working copy)
@@ -95,6 +95,7 @@
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::BuildRailStation,                "BuildRailStation",                6, ".iiiii");
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::BuildNewGRFRailStation,          "BuildNewGRFRailStation",          11, ".iiiiiiiiib");
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::BuildRailWaypoint,               "BuildRailWaypoint",               2, ".i");
+	SQAIRail.DefSQStaticMethod(engine, &AIRail::BuildRailWaypointTileRectangle,  "BuildRailWaypointTileRectangle",  4, ".iii");
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::RemoveRailWaypointTileRectangle, "RemoveRailWaypointTileRectangle", 4, ".iib");
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::RemoveRailStationTileRectangle,  "RemoveRailStationTileRectangle",  4, ".iib");
 	SQAIRail.DefSQStaticMethod(engine, &AIRail::GetRailTracks,                   "GetRailTracks",                   2, ".i");
Correct me If I am wrong - PM me if my English is bad
AIAI - AI for OpenTTD
Kogut
Tycoon
Tycoon
Posts: 2493
Joined: 26 Aug 2009 06:33
Location: Poland

Re: Some API extension ideas

Post by Kogut »

+
Attachments
lasta.patch
(4.98 KiB) Downloaded 237 times
Correct me If I am wrong - PM me if my English is bad
AIAI - AI for OpenTTD
Lowkee33
Engineer
Engineer
Posts: 20
Joined: 25 Nov 2011 20:49

Re: Some API extension ideas

Post by Lowkee33 »

Bounced around the internet, this seems like a good thread...

I'm trying to get the actual coverage area of a station, right now it is a little long winded: if a station type exists on a stationID, get the list of tiles that are of that type. Get the coverage radius of the type, and for every tile in the the previous list, add a rectangle the size of the radius. Do that for every station type on that stationID, and then add all of the lists together in one big list...

Figuring out what to do with that list will be another story.. This might not work?

Code: Select all

GetCargoProduction (TileIndex tile, CargoID cargo_type, int width, int height, int radius)
The main reason for this post is that this function returns -1:

Code: Select all

AIStation.GetCoverageRadius (AIStation.STATION_AIRPORT);
Rather, one needs to do something like this in order to get the actual radius:

Code: Select all

AIAirport.GetAirportCoverageRadius (AIAirport.AT_SMALL);
Could it be considered that the GetCoverageRadius have a note next to it that it doesn't work for airports? Thanks
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: Some API extension ideas

Post by Yexo »

Lowkee33 wrote:I'm trying to get the actual coverage area of a station, right now it is a little long winded: if a station type exists on a stationID, get the list of tiles that are of that type. Get the coverage radius of the type, and for every tile in the the previous list, add a rectangle the size of the radius. Do that for every station type on that stationID, and then add all of the lists together in one big list...
Actually you'd have to get the radius of the station first, than apply that to all tiles. The radius of the station is the maximum of the radii of the types the station has. If you use r23453 or later you can simply call AIStation.GetStationCoverageRadius(StationID) to get that, otherwise it's this:

Code: Select all

local radius = 0;
local types = [AIStation.STATION_TRAIN, AIStation.STATION_TRUCK_STOP, AIStation.STATION_BUS_STOP, AIStation.STATION_DOCK];

for (type in types) {
  if (AIStation.HasStationType(station_id, type)) {
    radius = max(radius, AIStation.GetCoverageRadius(type));
  }
}
if (AIStation.HasStationType(station_id, AIStation.STATION_AIRPORT)) {
  local list = AITileList_StationType(station_id, AIStation.STATION_AIRPORT);
  radius = max(radius, AIAirport.GetAirportCoverageRadius(AIAirport.GetAirportType(list.Begin())));
}
Note: I didn't actually test the code above. As I said before, in OpenTTD r23453 this can be replaced with:

Code: Select all

local radius = AIStation.GetStationCoverageRadius(station_id);
Figuring out what to do with that list will be another story..
I currently can't remember nor bothered to look up how exactly production and acceptance works. The wiki has a good explanation somewhere, just trying out in-game might also tell you how it works. This is complicated indeed.
Could it be considered that the GetCoverageRadius have a note next to it that it doesn't work for airports? Thanks
I've added that note in r23452.
Post Reply

Return to “OpenTTD AIs and Game Scripts”

Who is online

Users browsing this forum: No registered users and 12 guests