(svn r12885) [NoAI] -Add: added AISubsidy and AIEventSubsidyNNN (Yexo) noai
authortruebrain
Fri, 25 Apr 2008 00:22:41 +0000
branchnoai
changeset 10344 b7e9f5c65e30
parent 10343 0ccd326f082e
child 10353 adf5a495f0e2
(svn r12885) [NoAI] -Add: added AISubsidy and AIEventSubsidyNNN (Yexo)
bin/ai/regression/regression.nut
bin/ai/regression/regression.txt
projects/openttd_vs80.vcproj
projects/openttd_vs90.vcproj
source.list
src/ai/ai_squirrel.cpp
src/ai/api/ai_event.hpp
src/ai/api/ai_event.hpp.sq
src/ai/api/ai_event_types.hpp
src/ai/api/ai_event_types.hpp.sq
src/ai/api/ai_subsidy.cpp
src/ai/api/ai_subsidy.hpp
src/ai/api/ai_subsidy.hpp.sq
src/ai/api/ai_subsidylist.cpp
src/ai/api/ai_subsidylist.hpp
src/ai/api/ai_subsidylist.hpp.sq
src/ai/api/ai_types.hpp
src/economy.cpp
--- a/bin/ai/regression/regression.nut	Thu Apr 24 23:57:19 2008 +0000
+++ b/bin/ai/regression/regression.nut	Fri Apr 25 00:22:41 2008 +0000
@@ -1176,6 +1176,20 @@
 	}
 }
 
+function Regression::PrintSubsidy(subsidy_id)
+{
+	print("      --Subsidy (" + subsidy_id + ") --");
+	print("        IsValidSubsidy():     " + AISubsidy.IsValidSubsidy(subsidy_id));
+	print("        IsAwarded():          " + AISubsidy.IsAwarded(subsidy_id));
+	print("        GetAwardedTo():       " + AISubsidy.GetAwardedTo(subsidy_id));
+	print("        GetExpireDate():      " + AISubsidy.GetExpireDate(subsidy_id));
+	print("        SourceIsTown():       " + AISubsidy.SourceIsTown(subsidy_id));
+	print("        GetSource():          " + AISubsidy.GetSource(subsidy_id));
+	print("        DestionationIsTown(): " + AISubsidy.DestinationIsTown(subsidy_id));
+	print("        GetDestionation():    " + AISubsidy.GetDestination(subsidy_id));
+	print("        GetCargoType():       " + AISubsidy.GetCargoType(subsidy_id));
+}
+
 
 function Regression::Start()
 {
@@ -1206,6 +1220,7 @@
 	this.Vehicle();
 	/* Order has to be after Vehicle */
 	this.Order();
+	PrintSubsidy(0);
 
 	/* Sleep now, to give time for events to happen */
 	Sleep(4000);
@@ -1218,11 +1233,7 @@
 			case AIEvent.AI_ET_SUBSIDY_OFFER:
 				local c = AIEventSubsidyOffer.Convert(e);
 				print("      EventName:         SubsidyOffer");
-				print("      CargoID:           " + c.GetCargoID());
-				print("      GetFromTownID:     " + c.GetFromTownID());
-				print("      GetToTownID:       " + c.GetToTownID());
-				print("      GetFromIndustryID: " + c.GetFromIndustryID());
-				print("      GetToIndustryID:   " + c.GetToIndustryID());
+				PrintSubsidy(c.GetSubsidyID());
 				break;
 
 			default:
--- a/bin/ai/regression/regression.txt	Thu Apr 24 23:57:19 2008 +0000
+++ b/bin/ai/regression/regression.txt	Fri Apr 25 00:22:41 2008 +0000
@@ -6395,21 +6395,41 @@
   Count():             1
   Location ListDump:
     11 => 33417
+      --Subsidy (0) --
+        IsValidSubsidy():     false
+        IsAwarded():          false
+        GetAwardedTo():       9
+        GetExpireDate():      -1
+        SourceIsTown():       false
+        GetSource():          65535
+        DestionationIsTown(): false
+        GetDestionation():    65535
+        GetCargoType():       255
   GetNextEvent:          instance
     GetEventType:        3
       EventName:         SubsidyOffer
-      CargoID:           6
-      GetFromTownID:     65535
-      GetToTownID:       65535
-      GetFromIndustryID: 54
-      GetToIndustryID:   66
+      --Subsidy (0) --
+        IsValidSubsidy():     true
+        IsAwarded():          false
+        GetAwardedTo():       9
+        GetExpireDate():      712619
+        SourceIsTown():       false
+        GetSource():          54
+        DestionationIsTown(): false
+        GetDestionation():    66
+        GetCargoType():       6
   GetNextEvent:          instance
     GetEventType:        3
       EventName:         SubsidyOffer
-      CargoID:           0
-      GetFromTownID:     0
-      GetToTownID:       16
-      GetFromIndustryID: 65535
-      GetToIndustryID:   65535
+      --Subsidy (1) --
+        IsValidSubsidy():     true
+        IsAwarded():          false
+        GetAwardedTo():       9
+        GetExpireDate():      712647
+        SourceIsTown():       true
+        GetSource():          0
+        DestionationIsTown(): true
+        GetDestionation():    16
+        GetCargoType():       0
   IsEventWaiting:        false
 ERROR: We've got a suicidal AI for player 1
--- a/projects/openttd_vs80.vcproj	Thu Apr 24 23:57:19 2008 +0000
+++ b/projects/openttd_vs80.vcproj	Fri Apr 25 00:22:41 2008 +0000
@@ -2336,6 +2336,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\ai\api\ai_subsidy.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\ai\api\ai_subsidylist.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_testmode.hpp"
 				>
 			</File>
@@ -2500,6 +2508,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\ai\api\ai_subsidy.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\ai\api\ai_subsidylist.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_testmode.cpp"
 				>
 			</File>
--- a/projects/openttd_vs90.vcproj	Thu Apr 24 23:57:19 2008 +0000
+++ b/projects/openttd_vs90.vcproj	Fri Apr 25 00:22:41 2008 +0000
@@ -2333,6 +2333,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\ai\api\ai_subsidy.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\ai\api\ai_subsidylist.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_testmode.hpp"
 				>
 			</File>
@@ -2497,6 +2505,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\ai\api\ai_subsidy.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\ai\api\ai_subsidylist.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_testmode.cpp"
 				>
 			</File>
--- a/source.list	Thu Apr 24 23:57:19 2008 +0000
+++ b/source.list	Fri Apr 25 00:22:41 2008 +0000
@@ -527,6 +527,8 @@
 ai/api/ai_sign.hpp
 ai/api/ai_station.hpp
 ai/api/ai_stationlist.hpp
+ai/api/ai_subsidy.hpp
+ai/api/ai_subsidylist.hpp
 ai/api/ai_testmode.hpp
 ai/api/ai_tile.hpp
 ai/api/ai_tilelist.hpp
@@ -569,6 +571,8 @@
 ai/api/ai_sign.cpp
 ai/api/ai_station.cpp
 ai/api/ai_stationlist.cpp
+ai/api/ai_subsidy.cpp
+ai/api/ai_subsidylist.cpp
 ai/api/ai_testmode.cpp
 ai/api/ai_tile.cpp
 ai/api/ai_tilelist.cpp
--- a/src/ai/ai_squirrel.cpp	Thu Apr 24 23:57:19 2008 +0000
+++ b/src/ai/ai_squirrel.cpp	Fri Apr 25 00:22:41 2008 +0000
@@ -52,6 +52,8 @@
 #include "api/ai_sign.hpp.sq"
 #include "api/ai_station.hpp.sq"
 #include "api/ai_stationlist.hpp.sq"
+#include "api/ai_subsidy.hpp.sq"
+#include "api/ai_subsidylist.hpp.sq"
 #include "api/ai_testmode.hpp.sq"
 #include "api/ai_tile.hpp.sq"
 #include "api/ai_tilelist.hpp.sq"
@@ -231,7 +233,10 @@
 	SQAIEvent_Register(this->engine);
 	SQAIEventController_Register(this->engine);
 	SQAIEventEnginePreview_Register(this->engine);
+	SQAIEventSubsidyAwarded_Register(this->engine);
+	SQAIEventSubsidyExpired_Register(this->engine);
 	SQAIEventSubsidyOffer_Register(this->engine);
+	SQAIEventSubsidyOfferExpired_Register(this->engine);
 	SQAIEventTest_Register(this->engine);
 	SQAIEventVehicleCrash_Register(this->engine);
 	SQAIExecMode_Register(this->engine);
@@ -250,6 +255,8 @@
 	SQAIStation_Register(this->engine);
 	SQAIStationList_Register(this->engine);
 	SQAIStationList_Vehicle_Register(this->engine);
+	SQAISubsidy_Register(this->engine);
+	SQAISubsidyList_Register(this->engine);
 	SQAITestMode_Register(this->engine);
 	SQAITile_Register(this->engine);
 	SQAITileList_Register(this->engine);
--- a/src/ai/api/ai_event.hpp	Thu Apr 24 23:57:19 2008 +0000
+++ b/src/ai/api/ai_event.hpp	Fri Apr 25 00:22:41 2008 +0000
@@ -24,6 +24,9 @@
 		AI_ET_TEST,
 		AI_ET_CRASHED_VEHICLE,
 		AI_ET_SUBSIDY_OFFER,
+		AI_ET_SUBSIDY_OFFER_EXPIRED,
+		AI_ET_SUBSIDY_AWARDED,
+		AI_ET_SUBSIDY_EXPIRED,
 		AI_ET_ENGINE_PREVIEW,
 	};
 
--- a/src/ai/api/ai_event.hpp.sq	Thu Apr 24 23:57:19 2008 +0000
+++ b/src/ai/api/ai_event.hpp.sq	Fri Apr 25 00:22:41 2008 +0000
@@ -21,11 +21,14 @@
 	SQAIEvent.PreRegister(engine);
 	SQAIEvent.AddConstructor<void (AIEvent::*)(AIEvent::AIEventType type), 2>(engine, "xi");
 
-	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_INVALID,         "AI_ET_INVALID");
-	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_TEST,            "AI_ET_TEST");
-	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_CRASHED_VEHICLE, "AI_ET_CRASHED_VEHICLE");
-	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_SUBSIDY_OFFER,   "AI_ET_SUBSIDY_OFFER");
-	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_ENGINE_PREVIEW,  "AI_ET_ENGINE_PREVIEW");
+	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_INVALID,               "AI_ET_INVALID");
+	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_TEST,                  "AI_ET_TEST");
+	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_CRASHED_VEHICLE,       "AI_ET_CRASHED_VEHICLE");
+	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_SUBSIDY_OFFER,         "AI_ET_SUBSIDY_OFFER");
+	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_SUBSIDY_OFFER_EXPIRED, "AI_ET_SUBSIDY_OFFER_EXPIRED");
+	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_SUBSIDY_AWARDED,       "AI_ET_SUBSIDY_AWARDED");
+	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_SUBSIDY_EXPIRED,       "AI_ET_SUBSIDY_EXPIRED");
+	SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_ENGINE_PREVIEW,        "AI_ET_ENGINE_PREVIEW");
 
 	SQAIEvent.DefSQStaticMethod(engine, &AIEvent::GetClassName, "GetClassName", 1, "x");
 
--- a/src/ai/api/ai_event_types.hpp	Thu Apr 24 23:57:19 2008 +0000
+++ b/src/ai/api/ai_event_types.hpp	Fri Apr 25 00:22:41 2008 +0000
@@ -10,6 +10,7 @@
 #include "ai_town.hpp"
 #include "ai_industry.hpp"
 #include "ai_engine.hpp"
+#include "ai_subsidy.hpp"
 
 /**
  * Event Test: a simple test event, to see if the event system is working.
@@ -99,28 +100,17 @@
 
 /**
  * Event Subsidy Offered, indicating someone offered a subsidy.
- *  You can get the type of cargo the subsidy is for, if it is between
- *  towns or industry, and from where to where (which is either in TownID
- *  or IndustryID).
  */
 class AIEventSubsidyOffer : public AIEvent {
 public:
 	static const char *GetClassName() { return "AIEventSubsidyOffer"; }
 
 	/**
-	 * @param cargo The cargo for the subsidy.
-	 * @param from_town True if 'from' is a town, else it is an industry.
-	 * @param from Either TownID or IndustryID to move the cargo from.
-	 * @param to_town True if 'to' is a town, else it is an industry.
-	 * @param to Either TownID or IndustryID to move the cargo to.
+	 * @param subsidy_id The index of this subsidy in the _subsidies array.
 	 */
-	AIEventSubsidyOffer(CargoID cargo, bool from_town, uint32 from, bool to_town, uint32 to) :
+	AIEventSubsidyOffer(SubsidyID subsidy_id) :
 		AIEvent(AI_ET_SUBSIDY_OFFER),
-		cargo(cargo),
-		from_town(from_town),
-		from(from),
-		to_town(to_town),
-		to(to)
+		subsidy_id(subsidy_id)
 	{}
 
 	/**
@@ -131,41 +121,109 @@
 	static AIEventSubsidyOffer *Convert(AIEvent *instance) { return (AIEventSubsidyOffer *)instance; }
 
 	/**
-	 * Get the CargoID of the subsidy.
-	 * @return The cargo type.
+	 * Get the SubsidyID of the subsidy.
+	 * @return The subsidy id.
 	 */
-	CargoID GetCargoID() { return cargo; }
+	SubsidyID GetSubsidyID() { return subsidy_id; }
 
-	/**
-	 * Get the TownID from where you need to move the cargo.
-	 * @return Either the TownID, or AITown::IsValidTown() returns false.
-	 */
-	TownID GetFromTownID() { return from_town ? from : (TownID)-1; }
+private:
+	SubsidyID subsidy_id;
+};
+
+/**
+ * Event Subsidy Offer Expired, indicating a subsidy will no longer be awarded.
+ */
+class AIEventSubsidyOfferExpired : public AIEvent {
+public:
+	static const char *GetClassName() { return "AIEventSubsidyOfferExpired"; }
 
 	/**
-	 * Get the TownID to where you need to move the cargo.
-	 * @return Either the TownID, or AITown::IsValidTown() returns false.
+	 * @param subsidy_id The index of this subsidy in the _subsidies array.
 	 */
-	TownID GetToTownID() { return to_town ? to : (TownID)-1; }
+	AIEventSubsidyOfferExpired(SubsidyID subsidy_id) :
+		AIEvent(AI_ET_SUBSIDY_OFFER_EXPIRED),
+		subsidy_id(subsidy_id)
+	{}
 
 	/**
-	 * Get the IndustryID from where you need to move the cargo.
-	 * @return Either the IndustryID, or AIIndustry::IsValidIndustry() returns false.
+	 * Convert an AIEvent to the real instance.
+	 * @param instance The instance to convert.
+	 * @return The converted instance.
 	 */
-	IndustryID GetFromIndustryID() { return from_town ? (IndustryID)-1 : from; }
+	static AIEventSubsidyOfferExpired *Convert(AIEvent *instance) { return (AIEventSubsidyOfferExpired *)instance; }
 
 	/**
-	 * Get the IndustryID to where you need to move the cargo.
-	 * @return Either the IndustryID, or AIIndustry::IsValidIndustry() returns false.
+	 * Get the SubsidyID of the subsidy.
+	 * @return The subsidy id.
 	 */
-	IndustryID GetToIndustryID() { return to_town ? (IndustryID)-1 : to; }
+	SubsidyID GetSubsidyID() { return subsidy_id; }
 
 private:
-	CargoID cargo;
-	bool from_town;
-	uint32 from;
-	bool to_town;
-	uint32 to;
+	SubsidyID subsidy_id;
+};
+
+/**
+ * Event Subidy Awarded, indicating a subsidy is awarded to some company.
+ */
+class AIEventSubsidyAwarded : public AIEvent {
+public:
+	static const char *GetClassName() { return "AIEventSubsidyAwarded"; }
+
+	/**
+	 * @param subsidy_id The index of this subsidy in the _subsidies array.
+	 */
+	AIEventSubsidyAwarded(SubsidyID subsidy_id) :
+		AIEvent(AI_ET_SUBSIDY_AWARDED),
+		subsidy_id(subsidy_id)
+	{}
+
+	/**
+	 * Convert an AIEvent to the real instance.
+	 * @param instance The instance to convert.
+	 * @return The converted instance.
+	 */
+	static AIEventSubsidyAwarded *Convert(AIEvent *instance) { return (AIEventSubsidyAwarded *)instance; }
+
+	/**
+	 * Get the SubsidyID of the subsidy.
+	 * @return The subsidy id.
+	 */
+	SubsidyID GetSubsidyID() { return subsidy_id; }
+
+private:
+	SubsidyID subsidy_id;
+};
+
+/**
+ * Event Subsidy Expired, indicating a route that was once subsidized no longer is.
+ */
+class AIEventSubsidyExpired : public AIEvent {
+public:
+	static const char *GetClassName() { return "AIEventSubsidyExpired"; }
+
+	/**
+	 * @param subsidy_id The index of this subsidy in the _subsidies array.
+	 */
+	AIEventSubsidyExpired(SubsidyID subsidy_id) :
+		AIEvent(AI_ET_SUBSIDY_EXPIRED),
+		subsidy_id(subsidy_id)
+	{}
+
+	/**
+	 * Convert an AIEvent to the real instance.
+	 * @param instance The instance to convert.
+	 * @return The converted instance.
+	 */
+	static AIEventSubsidyExpired *Convert(AIEvent *instance) { return (AIEventSubsidyExpired *)instance; }
+
+	/**
+	 * Get the SubsidyID of the subsidy.
+	 * @return The subsidy id.
+	 */
+	 SubsidyID GetSubsidyID() { return subsidy_id; }
+
+private:
+	SubsidyID subsidy_id;
 };
 
 /**
--- a/src/ai/api/ai_event_types.hpp.sq	Thu Apr 24 23:57:19 2008 +0000
+++ b/src/ai/api/ai_event_types.hpp.sq	Fri Apr 25 00:22:41 2008 +0000
@@ -61,21 +61,83 @@
 void SQAIEventSubsidyOffer_Register(Squirrel *engine) {
 	DefSQClass <AIEventSubsidyOffer> SQAIEventSubsidyOffer("AIEventSubsidyOffer");
 	SQAIEventSubsidyOffer.PreRegister(engine, "AIEvent");
-	SQAIEventSubsidyOffer.AddConstructor<void (AIEventSubsidyOffer::*)(CargoID cargo, bool from_town, uint32 from, bool to_town, uint32 to), 6>(engine, "xibibi");
+	SQAIEventSubsidyOffer.AddConstructor<void (AIEventSubsidyOffer::*)(SubsidyID subsidy_id), 2>(engine, "xi");
 
 	SQAIEventSubsidyOffer.DefSQStaticMethod(engine, &AIEventSubsidyOffer::GetClassName, "GetClassName", 1, "x");
 	SQAIEventSubsidyOffer.DefSQStaticMethod(engine, &AIEventSubsidyOffer::Convert,      "Convert",      2, "xx");
 
-	SQAIEventSubsidyOffer.DefSQMethod(engine, &AIEventSubsidyOffer::GetCargoID,        "GetCargoID",        1, "x");
-	SQAIEventSubsidyOffer.DefSQMethod(engine, &AIEventSubsidyOffer::GetFromTownID,     "GetFromTownID",     1, "x");
-	SQAIEventSubsidyOffer.DefSQMethod(engine, &AIEventSubsidyOffer::GetToTownID,       "GetToTownID",       1, "x");
-	SQAIEventSubsidyOffer.DefSQMethod(engine, &AIEventSubsidyOffer::GetFromIndustryID, "GetFromIndustryID", 1, "x");
-	SQAIEventSubsidyOffer.DefSQMethod(engine, &AIEventSubsidyOffer::GetToIndustryID,   "GetToIndustryID",   1, "x");
+	SQAIEventSubsidyOffer.DefSQMethod(engine, &AIEventSubsidyOffer::GetSubsidyID, "GetSubsidyID", 1, "x");
 
 	SQAIEventSubsidyOffer.PostRegister(engine);
 }
 
 namespace SQConvert {
+	/* Allow AIEventSubsidyOfferExpired to be used as Squirrel parameter */
+	template <> AIEventSubsidyOfferExpired *GetParam(ForceType<AIEventSubsidyOfferExpired *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIEventSubsidyOfferExpired *)instance; }
+	template <> AIEventSubsidyOfferExpired &GetParam(ForceType<AIEventSubsidyOfferExpired &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyOfferExpired *)instance; }
+	template <> const AIEventSubsidyOfferExpired *GetParam(ForceType<const AIEventSubsidyOfferExpired *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIEventSubsidyOfferExpired *)instance; }
+	template <> const AIEventSubsidyOfferExpired &GetParam(ForceType<const AIEventSubsidyOfferExpired &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyOfferExpired *)instance; }
+	template <> int Return<AIEventSubsidyOfferExpired *>(HSQUIRRELVM vm, AIEventSubsidyOfferExpired *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventSubsidyOfferExpired", res, NULL, DefSQDestructorCallback<AIEventSubsidyOfferExpired>); return 1; }
+}; // namespace SQConvert
+
+void SQAIEventSubsidyOfferExpired_Register(Squirrel *engine) {
+	DefSQClass <AIEventSubsidyOfferExpired> SQAIEventSubsidyOfferExpired("AIEventSubsidyOfferExpired");
+	SQAIEventSubsidyOfferExpired.PreRegister(engine, "AIEvent");
+	SQAIEventSubsidyOfferExpired.AddConstructor<void (AIEventSubsidyOfferExpired::*)(SubsidyID subsidy_id), 2>(engine, "xi");
+
+	SQAIEventSubsidyOfferExpired.DefSQStaticMethod(engine, &AIEventSubsidyOfferExpired::GetClassName, "GetClassName", 1, "x");
+	SQAIEventSubsidyOfferExpired.DefSQStaticMethod(engine, &AIEventSubsidyOfferExpired::Convert,      "Convert",      2, "xx");
+
+	SQAIEventSubsidyOfferExpired.DefSQMethod(engine, &AIEventSubsidyOfferExpired::GetSubsidyID, "GetSubsidyID", 1, "x");
+
+	SQAIEventSubsidyOfferExpired.PostRegister(engine);
+}
+
+namespace SQConvert {
+	/* Allow AIEventSubsidyAwarded to be used as Squirrel parameter */
+	template <> AIEventSubsidyAwarded *GetParam(ForceType<AIEventSubsidyAwarded *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIEventSubsidyAwarded *)instance; }
+	template <> AIEventSubsidyAwarded &GetParam(ForceType<AIEventSubsidyAwarded &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyAwarded *)instance; }
+	template <> const AIEventSubsidyAwarded *GetParam(ForceType<const AIEventSubsidyAwarded *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIEventSubsidyAwarded *)instance; }
+	template <> const AIEventSubsidyAwarded &GetParam(ForceType<const AIEventSubsidyAwarded &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyAwarded *)instance; }
+	template <> int Return<AIEventSubsidyAwarded *>(HSQUIRRELVM vm, AIEventSubsidyAwarded *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventSubsidyAwarded", res, NULL, DefSQDestructorCallback<AIEventSubsidyAwarded>); return 1; }
+}; // namespace SQConvert
+
+void SQAIEventSubsidyAwarded_Register(Squirrel *engine) {
+	DefSQClass <AIEventSubsidyAwarded> SQAIEventSubsidyAwarded("AIEventSubsidyAwarded");
+	SQAIEventSubsidyAwarded.PreRegister(engine, "AIEvent");
+	SQAIEventSubsidyAwarded.AddConstructor<void (AIEventSubsidyAwarded::*)(SubsidyID subsidy_id), 2>(engine, "xi");
+
+	SQAIEventSubsidyAwarded.DefSQStaticMethod(engine, &AIEventSubsidyAwarded::GetClassName, "GetClassName", 1, "x");
+	SQAIEventSubsidyAwarded.DefSQStaticMethod(engine, &AIEventSubsidyAwarded::Convert,      "Convert",      2, "xx");
+
+	SQAIEventSubsidyAwarded.DefSQMethod(engine, &AIEventSubsidyAwarded::GetSubsidyID, "GetSubsidyID", 1, "x");
+
+	SQAIEventSubsidyAwarded.PostRegister(engine);
+}
+
+namespace SQConvert {
+	/* Allow AIEventSubsidyExpired to be used as Squirrel parameter */
+	template <> AIEventSubsidyExpired *GetParam(ForceType<AIEventSubsidyExpired *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIEventSubsidyExpired *)instance; }
+	template <> AIEventSubsidyExpired &GetParam(ForceType<AIEventSubsidyExpired &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyExpired *)instance; }
+	template <> const AIEventSubsidyExpired *GetParam(ForceType<const AIEventSubsidyExpired *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIEventSubsidyExpired *)instance; }
+	template <> const AIEventSubsidyExpired &GetParam(ForceType<const AIEventSubsidyExpired &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyExpired *)instance; }
+	template <> int Return<AIEventSubsidyExpired *>(HSQUIRRELVM vm, AIEventSubsidyExpired *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventSubsidyExpired", res, NULL, DefSQDestructorCallback<AIEventSubsidyExpired>); return 1; }
+}; // namespace SQConvert
+
+void SQAIEventSubsidyExpired_Register(Squirrel *engine) {
+	DefSQClass <AIEventSubsidyExpired> SQAIEventSubsidyExpired("AIEventSubsidyExpired");
+	SQAIEventSubsidyExpired.PreRegister(engine, "AIEvent");
+	SQAIEventSubsidyExpired.AddConstructor<void (AIEventSubsidyExpired::*)(SubsidyID subsidy_id), 2>(engine, "xi");
+
+	SQAIEventSubsidyExpired.DefSQStaticMethod(engine, &AIEventSubsidyExpired::GetClassName, "GetClassName", 1, "x");
+	SQAIEventSubsidyExpired.DefSQStaticMethod(engine, &AIEventSubsidyExpired::Convert,      "Convert",      2, "xx");
+
+	SQAIEventSubsidyExpired.DefSQMethod(engine, &AIEventSubsidyExpired::GetSubsidyID, "GetSubsidyID", 1, "x");
+
+	SQAIEventSubsidyExpired.PostRegister(engine);
+}
+
+namespace SQConvert {
 	/* Allow AIEventEnginePreview to be used as Squirrel parameter */
 	template <> AIEventEnginePreview *GetParam(ForceType<AIEventEnginePreview *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AIEventEnginePreview *)instance; }
 	template <> AIEventEnginePreview &GetParam(ForceType<AIEventEnginePreview &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventEnginePreview *)instance; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ai/api/ai_subsidy.cpp	Fri Apr 25 00:22:41 2008 +0000
@@ -0,0 +1,94 @@
+/* $Id$ */
+
+/** @file ai_subsidy.cpp Implementation of AISubsidy. */
+
+#include "ai_subsidy.hpp"
+#include "ai_error.hpp"
+#include "ai_company.hpp"
+#include "ai_date.hpp"
+#include "../../openttd.h"
+#include "../../economy_func.h"
+#include "../../station_base.h"
+#include "../../cargotype.h"
+
+/* static */ bool AISubsidy::IsValidSubsidy(SubsidyID subsidy_id)
+{
+	return subsidy_id < lengthof(_subsidies) && _subsidies[subsidy_id].cargo_type != CT_INVALID;
+}
+
+/* static */ bool AISubsidy::IsAwarded(SubsidyID subsidy_id)
+{
+	if (!IsValidSubsidy(subsidy_id)) return false;
+
+	return _subsidies[subsidy_id].age >= 12;
+}
+
+/* static */ AICompany::CompanyIndex AISubsidy::GetAwardedTo(SubsidyID subsidy_id)
+{
+	if (!IsAwarded(subsidy_id)) return AICompany::INVALID_COMPANY;
+
+	return (AICompany::CompanyIndex)((byte)GetStation(_subsidies[subsidy_id].from)->owner);
+}
+
+/* static */ int32 AISubsidy::GetExpireDate(SubsidyID subsidy_id)
+{
+	if (!IsValidSubsidy(subsidy_id)) return -1;
+
+	int year = AIDate::GetYear(AIDate::GetCurrentDate());
+	int month = AIDate::GetMonth(AIDate::GetCurrentDate());
+
+	if (IsAwarded(subsidy_id)) {
+		month += 24 - _subsidies[subsidy_id].age;
+	} else {
+		month += 12 - _subsidies[subsidy_id].age;
+	}
+
+	year += month / 12;
+	month = month % 12;
+
+	return AIDate::GetDate(year, month, 1);
+}
+
+/* static */ CargoID AISubsidy::GetCargoType(SubsidyID subsidy_id)
+{
+	if (!IsValidSubsidy(subsidy_id)) return CT_INVALID;
+
+	return _subsidies[subsidy_id].cargo_type;
+}
+
+/* static */ bool AISubsidy::SourceIsTown(SubsidyID subsidy_id)
+{
+	if (!IsValidSubsidy(subsidy_id) || IsAwarded(subsidy_id)) return false;
+
+	return GetCargo(GetCargoType(subsidy_id))->town_effect == TE_PASSENGERS ||
+	       GetCargo(GetCargoType(subsidy_id))->town_effect == TE_MAIL;
+}
+
+/* static */ int32 AISubsidy::GetSource(SubsidyID subsidy_id)
+{
+	if (!IsValidSubsidy(subsidy_id)) return INVALID_STATION;
+
+	return _subsidies[subsidy_id].from;
+}
+
+/* static */ bool AISubsidy::DestinationIsTown(SubsidyID subsidy_id)
+{
+	if (!IsValidSubsidy(subsidy_id) || IsAwarded(subsidy_id)) return false;
+
+	switch (GetCargo(GetCargoType(subsidy_id))->town_effect) {
+		case TE_PASSENGERS:
+		case TE_MAIL:
+		case TE_GOODS:
+		case TE_FOOD:
+			return true;
+		default:
+			return false;
+	}
+}
+
+/* static */ int32 AISubsidy::GetDestination(SubsidyID subsidy_id)
+{
+	if (!IsValidSubsidy(subsidy_id)) return INVALID_STATION;
+
+	return _subsidies[subsidy_id].to;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ai/api/ai_subsidy.hpp	Fri Apr 25 00:22:41 2008 +0000
@@ -0,0 +1,101 @@
+/* $Id$ */
+
+/** @file ai_subsidy.hpp Everything to query subsidies. */
+
+#ifndef AI_SUBSIDY_HPP
+#define AI_SUBSIDY_HPP
+
+#include "ai_object.hpp"
+#include "ai_company.hpp"
+
+/**
+ * Class that handles all subsidy related functions.
+ */
+class AISubsidy : public AIObject {
+public:
+	static const char *GetClassName() { return "AISubsidy"; }
+
+	/**
+	 * Check whether this is a valid SubsidyID.
+	 * @param subsidy_id The SubsidyID to check.
+	 * @return True if and only if this subsidy is still valid.
+	 */
+	static bool IsValidSubsidy(SubsidyID subsidy_id);
+
+	/**
+	 * Checks whether this subsidy is already awarded to some company.
+	 * @param subsidy_id The SubsidyID to check.
+	 * @pre IsValidSubsidy(subsidy).
+	 * @return True if and only if this subsidy is already awarded.
+	 */
+	static bool IsAwarded(SubsidyID subsidy_id);
+
+	/**
+	 * Get the company index of the company this subsidy is awarded to.
+	 * @param subsidy_id The SubsidyID to check.
+	 * @pre IsAwarded(subsidy_id).
+	 * @return The companyindex of the company this subsidy is awarded to.
+	 */
+	static AICompany::CompanyIndex GetAwardedTo(SubsidyID subsidy_id);
+
+	/**
+	 * Get the date this subsidy expires. In case the subsidy is already
+	 *  awarded, return the date the subsidy expires, else, return the date the
+	 *  offer expires.
+	 * @param subsidy_id The SubsidyID to check.
+	 * @pre IsValidSubsidy(subsidy_id).
+	 * @return The last valid date of this subsidy.
+	 * @note The return value of this function will change if the subsidy is
+	 *  awarded.
+	 */
+	static int32 GetExpireDate(SubsidyID subsidy_id);
+
+	/**
+	 * Get the cargo type that has to be transported in order to be awarded this
+	 *  subsidy.
+	 * @param subsidy_id The SubsidyID to check.
+	 * @pre IsValidSubsidy(subsidy_id).
+	 * @return The cargo type to transport.
+	 */
+	static CargoID GetCargoType(SubsidyID subsidy_id);
+
+	/**
+	 * Is the source of the subsidy a town or an industry.
+	 * @param subsidy_id The SubsidyID to check.
+	 * @pre IsValidSubsidy(subsidy_id) && !IsAwarded(subsidy_id).
+	 * @return True if the source is a town, false if it is an industry.
+	 */
+	static bool SourceIsTown(SubsidyID subsidy_id);
+
+	/**
+	 * Return the source TownID/IndustryID/StationID the subsidy is for.
+	 * 1) IsAwarded(subsidy_id) -> return the StationID the subsidy is awarded to.
+	 * 2) !IsAwarded(subsidy_id) && SourceIsTown(subsidy_id) -> return the TownID.
+	 * 3) !IsAwarded(subsidy_id) && !SourceIsTown(subsidy_id) -> return the IndustryID.
+	 * @param subsidy_id The SubsidyID to check.
+	 * @pre IsValidSubsidy(subsidy_id).
+	 * @return One of TownID/IndustryID/StationID.
+	 */
+	static int32 GetSource(SubsidyID subsidy_id);
+
+	/**
+	 * Is the destination of the subsidy a town or an industry.
+	 * @param subsidy_id The SubsidyID to check.
+	 * @pre IsValidSubsidy(subsidy_id) && !IsAwarded(subsidy_id).
+	 * @return True if the destination is a town, false if it is an industry.
+	 */
+	static bool DestinationIsTown(SubsidyID subsidy_id);
+
+	/**
+	 * Return the destination TownID/IndustryID/StationID the subsidy is for.
+	 * 1) IsAwarded(subsidy_id) -> return the StationID the subsidy is awarded to.
+	 * 2) !IsAwarded(subsidy_id) && SourceIsTown(subsidy_id) -> return the TownID.
+	 * 3) !IsAwarded(subsidy_id) && !SourceIsTown(subsidy_id) -> return the IndustryID.
+	 * @param subsidy_id the SubsidyID to check.
+	 * @pre IsValidSubsidy(subsidy_id).
+	 * @return One of TownID/IndustryID/StationID.
+	 */
+	static int32 GetDestination(SubsidyID subsidy_id);
+};
+
+#endif /* AI_SUBSIDY_HPP */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ai/api/ai_subsidy.hpp.sq	Fri Apr 25 00:22:41 2008 +0000
@@ -0,0 +1,32 @@
+/* $Id$ */
+/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
+
+#include "ai_subsidy.hpp"
+
+namespace SQConvert {
+	/* Allow AISubsidy to be used as Squirrel parameter */
+	template <> AISubsidy *GetParam(ForceType<AISubsidy *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AISubsidy *)instance; }
+	template <> AISubsidy &GetParam(ForceType<AISubsidy &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AISubsidy *)instance; }
+	template <> const AISubsidy *GetParam(ForceType<const AISubsidy *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AISubsidy *)instance; }
+	template <> const AISubsidy &GetParam(ForceType<const AISubsidy &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AISubsidy *)instance; }
+	template <> int Return<AISubsidy *>(HSQUIRRELVM vm, AISubsidy *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AISubsidy", res, NULL, DefSQDestructorCallback<AISubsidy>); return 1; }
+}; // namespace SQConvert
+
+void SQAISubsidy_Register(Squirrel *engine) {
+	DefSQClass <AISubsidy> SQAISubsidy("AISubsidy");
+	SQAISubsidy.PreRegister(engine);
+	SQAISubsidy.AddConstructor<void (AISubsidy::*)(), 1>(engine, "x");
+
+	SQAISubsidy.DefSQStaticMethod(engine, &AISubsidy::GetClassName,      "GetClassName",      1, "x");
+	SQAISubsidy.DefSQStaticMethod(engine, &AISubsidy::IsValidSubsidy,    "IsValidSubsidy",    2, "xi");
+	SQAISubsidy.DefSQStaticMethod(engine, &AISubsidy::IsAwarded,         "IsAwarded",         2, "xi");
+	SQAISubsidy.DefSQStaticMethod(engine, &AISubsidy::GetAwardedTo,      "GetAwardedTo",      2, "xi");
+	SQAISubsidy.DefSQStaticMethod(engine, &AISubsidy::GetExpireDate,     "GetExpireDate",     2, "xi");
+	SQAISubsidy.DefSQStaticMethod(engine, &AISubsidy::GetCargoType,      "GetCargoType",      2, "xi");
+	SQAISubsidy.DefSQStaticMethod(engine, &AISubsidy::SourceIsTown,      "SourceIsTown",      2, "xi");
+	SQAISubsidy.DefSQStaticMethod(engine, &AISubsidy::GetSource,         "GetSource",         2, "xi");
+	SQAISubsidy.DefSQStaticMethod(engine, &AISubsidy::DestinationIsTown, "DestinationIsTown", 2, "xi");
+	SQAISubsidy.DefSQStaticMethod(engine, &AISubsidy::GetDestination,    "GetDestination",    2, "xi");
+
+	SQAISubsidy.PostRegister(engine);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ai/api/ai_subsidylist.cpp	Fri Apr 25 00:22:41 2008 +0000
@@ -0,0 +1,14 @@
+/* $Id$ */
+
+/** @file ai_subsidylist.cpp Implementation of AISubsidyList. */
+
+#include "ai_subsidylist.hpp"
+#include "ai_subsidy.hpp"
+#include "../../economy_func.h"
+
+AISubsidyList::AISubsidyList()
+{
+	for (uint i = 0; i < lengthof(_subsidies); i++) {
+		if (AISubsidy::IsValidSubsidy(i)) this->AddItem(i);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ai/api/ai_subsidylist.hpp	Fri Apr 25 00:22:41 2008 +0000
@@ -0,0 +1,20 @@
+/* $Id$ */
+
+/** @file ai_subsidylist.hpp List all the subsidies. */
+
+#ifndef AI_SUBSIDYLIST_HPP
+#define AI_SUBSIDYLIST_HPP
+
+#include "ai_abstractlist.hpp"
+
+/**
+ * Creates a list of all current subsidies.
+ * @ingroup AIList
+ */
+class AISubsidyList : public AIAbstractList {
+public:
+	static const char *GetClassName() { return "AISubsidyList"; }
+	AISubsidyList();
+};
+
+#endif /* AI_SUBSIDYLIST_HPP */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ai/api/ai_subsidylist.hpp.sq	Fri Apr 25 00:22:41 2008 +0000
@@ -0,0 +1,23 @@
+/* $Id$ */
+/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
+
+#include "ai_subsidylist.hpp"
+
+namespace SQConvert {
+	/* Allow AISubsidyList to be used as Squirrel parameter */
+	template <> AISubsidyList *GetParam(ForceType<AISubsidyList *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AISubsidyList *)instance; }
+	template <> AISubsidyList &GetParam(ForceType<AISubsidyList &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AISubsidyList *)instance; }
+	template <> const AISubsidyList *GetParam(ForceType<const AISubsidyList *>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AISubsidyList *)instance; }
+	template <> const AISubsidyList &GetParam(ForceType<const AISubsidyList &>, HSQUIRRELVM vm, int index) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AISubsidyList *)instance; }
+	template <> int Return<AISubsidyList *>(HSQUIRRELVM vm, AISubsidyList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AISubsidyList", res, NULL, DefSQDestructorCallback<AISubsidyList>); return 1; }
+}; // namespace SQConvert
+
+void SQAISubsidyList_Register(Squirrel *engine) {
+	DefSQClass <AISubsidyList> SQAISubsidyList("AISubsidyList");
+	SQAISubsidyList.PreRegister(engine, "AIAbstractList");
+	SQAISubsidyList.AddConstructor<void (AISubsidyList::*)(), 1>(engine, "x");
+
+	SQAISubsidyList.DefSQStaticMethod(engine, &AISubsidyList::GetClassName, "GetClassName", 1, "x");
+
+	SQAISubsidyList.PostRegister(engine);
+}
--- a/src/ai/api/ai_types.hpp	Thu Apr 24 23:57:19 2008 +0000
+++ b/src/ai/api/ai_types.hpp	Fri Apr 25 00:22:41 2008 +0000
@@ -25,6 +25,7 @@
 /* Types we defined ourself, as the OpenTTD core doesn't have them (yet) */
 typedef uint AIErrorType;    //!< The types of errors inside the NoAI framework.
 typedef BridgeType BridgeID; //!< The ID of a bridge.
+typedef uint16 SubsidyID;    //!< The ID of a subsidy.
 
 #ifndef _SQUIRREL_H_
 /* Life becomes easier when we can tell about a function it needs the VM, but
--- a/src/economy.cpp	Thu Apr 24 23:57:19 2008 +0000
+++ b/src/economy.cpp	Fri Apr 25 00:22:41 2008 +0000
@@ -1130,6 +1130,9 @@
 			AddNewsItem(STR_202E_OFFER_OF_SUBSIDY_EXPIRED, NM_NORMAL, NF_TILE, NT_SUBSIDIES, DNC_NONE, pair.a, pair.b);
 			s->cargo_type = CT_INVALID;
 			modified = true;
+			for (PlayerID i = PLAYER_FIRST; i != MAX_PLAYERS; i++) {
+				AI_Event(i, new AIEventSubsidyOfferExpired(s - _subsidies));
+			}
 		} else if (s->age == 2*12-1) {
 			st = GetStation(s->to);
 			if (st->owner == _local_player) {
@@ -1138,6 +1141,9 @@
 			}
 			s->cargo_type = CT_INVALID;
 			modified = true;
+			for (PlayerID i = PLAYER_FIRST; i != MAX_PLAYERS; i++) {
+				AI_Event(i, new AIEventSubsidyExpired(s - _subsidies));
+			}
 		} else {
 			s->age++;
 		}
@@ -1175,7 +1181,7 @@
 					pair = SetupSubsidyDecodeParam(s, 0);
 					AddNewsItem(STR_2030_SERVICE_SUBSIDY_OFFERED, NM_NORMAL, NF_TILE, NT_SUBSIDIES, DNC_NONE, pair.a, pair.b);
 					for (PlayerID i = PLAYER_FIRST; i != MAX_PLAYERS; i++) {
-						AI_Event(i, new AIEventSubsidyOffer(s->cargo_type, s->cargo_type == CT_PASSENGERS, s->from, (s->cargo_type == CT_PASSENGERS || GetCargo(s->cargo_type)->town_effect == TE_GOODS || GetCargo(s->cargo_type)->town_effect == TE_FOOD), s->to));
+						AI_Event(i, new AIEventSubsidyOffer(s - _subsidies));
 					}
 					modified = true;
 					break;
@@ -1396,6 +1402,9 @@
 				NM_NORMAL, NF_TILE, NT_SUBSIDIES, DNC_NONE,
 				pair.a, pair.b
 			);
+			for (PlayerID i = PLAYER_FIRST; i != MAX_PLAYERS; i++) {
+				AI_Event(i, new AIEventSubsidyAwarded(s - _subsidies));
+			}
 
 			InvalidateWindow(WC_SUBSIDIES_LIST, 0);
 			return true;