(svn r9407) [NoAI] -Add: placing of signs. noai
authorrubidium
Thu, 22 Mar 2007 09:52:12 +0000
branchnoai
changeset 9511 f767ad06e86b
parent 9510 261d33fbabb8
child 9512 36a53e169661
(svn r9407) [NoAI] -Add: placing of signs.
bin/ai/regression/regression.nut
bin/ai/regression/regression.txt
projects/openttd.vcproj
projects/openttd_vs80.vcproj
source.list
src/ai/ai_squirrel.cpp
src/ai/api/ai_object.cpp
src/ai/api/ai_object.hpp
src/ai/api/ai_sign.cpp
src/ai/api/ai_sign.hpp
src/signs.cpp
src/signs.h
--- a/bin/ai/regression/regression.nut	Thu Mar 22 09:10:00 2007 +0000
+++ b/bin/ai/regression/regression.nut	Thu Mar 22 09:52:12 2007 +0000
@@ -102,7 +102,7 @@
 	print("--Industry--");
 	print("  GetMaxIndustryID():  " + industry.GetMaxIndustryID());
 	print("  GetIndustryCount():  " + industry.GetIndustryCount());
-	for (local i = -1; i < industry.GetMaxIndustryID(); i++) {
+	for (local i = -1; i < industry.GetMaxIndustryID() + 1; i++) {
 		if (industry.IsValidIndustry(i)) j++;
 		print("  Industry " + i);
 		print("    IsValidIndustry(): " + industry.IsValidIndustry(i));
@@ -198,6 +198,31 @@
 	print("    BuildRoadStation(bus-drive):   " + road.BuildRoadStation(33416, 33415, true,  true));
 }
 
+function Regression::Sign()
+{
+	local sign = AISign();
+	local j = 0;
+
+	print("");
+	print("--Sign--");
+	print("  BuildSign(33410, 'Some Sign'):       " + sign.BuildSign(33410, "Some Sign"));
+	local sign_id = sign.BuildSign(33409, "Some other Sign");
+	print("  BuildSign(33409, 'Some other Sign'): " + sign_id);
+	print("  RemoveSign(" + sign_id + "):                       " + sign.RemoveSign(sign_id));
+	print("");
+	print("  GetMaxSignID():    " + sign.GetMaxSignID());
+	print("  GetSignCount():    " + sign.GetSignCount());
+	for (local i = -1; i < sign.GetMaxSignID() + 1; i++) {
+		if (sign.IsValidSign(i)) j++;
+		print("  Sign " + i);
+		print("    IsValidSign():   " + sign.IsValidSign(i));
+		print("    GetText():       " + sign.GetText(i));
+		print("    GetLocation():   " + sign.GetLocation(i));
+	}
+	print("  Valid Signs:       " + j);
+	print("  GetSignCount():    " + sign.GetSignCount());
+}
+
 function Regression::Town()
 {
 	local town = AITown();
@@ -207,7 +232,7 @@
 	print("--Town--");
 	print("  GetMaxTownID():    " + town.GetMaxTownID());
 	print("  GetTownCount():    " + town.GetTownCount());
-	for (local i = -1; i < town.GetMaxTownID(); i++) {
+	for (local i = -1; i < town.GetMaxTownID() + 1; i++) {
 		if (town.IsValidTown(i)) j++;
 		print("  Town " + i);
 		print("    IsValidTown():   " + town.IsValidTown(i));
@@ -215,7 +240,7 @@
 		print("    GetPopulation(): " + town.GetPopulation(i));
 		print("    GetLocation():   " + town.GetLocation(i));
 	}
-	print("  Valid Industries:  " + j);
+	print("  Valid Towns:       " + j);
 	print("  GetTownCount():    " + town.GetTownCount());
 }
 
@@ -230,6 +255,7 @@
 	this.Industry();
 	this.Map();
 	this.Road();
+	this.Sign();
 	this.Town();
 }
 
--- a/bin/ai/regression/regression.txt	Thu Mar 22 09:10:00 2007 +0000
+++ b/bin/ai/regression/regression.txt	Thu Mar 22 09:52:12 2007 +0000
@@ -450,6 +450,10 @@
     IsValidIndustry(): false
     GetName():         (null : 0x00000000)
     GetLocation():     -1
+  Industry 71
+    IsValidIndustry(): false
+    GetName():         (null : 0x00000000)
+    GetLocation():     -1
   Valid Industries:    69
   GetIndustryCount():  69
 
@@ -522,6 +526,36 @@
     BuildRoadStation(truck-drive): true
     BuildRoadStation(bus-drive):   true
 
+--Sign--
+  BuildSign(33410, 'Some Sign'):       0
+  BuildSign(33409, 'Some other Sign'): 1
+  RemoveSign(1):                       true
+
+  GetMaxSignID():    3
+  GetSignCount():    1
+  Sign -1
+    IsValidSign():   false
+    GetText():       (null : 0x00000000)
+    GetLocation():   -1
+  Sign 0
+    IsValidSign():   true
+    GetText():       Some Sign
+    GetLocation():   33410
+  Sign 1
+    IsValidSign():   false
+    GetText():       (null : 0x00000000)
+    GetLocation():   -1
+  Sign 2
+    IsValidSign():   false
+    GetText():       (null : 0x00000000)
+    GetLocation():   -1
+  Sign 3
+    IsValidSign():   false
+    GetText():       (null : 0x00000000)
+    GetLocation():   -1
+  Valid Signs:       1
+  GetSignCount():    1
+
 --Town--
   GetMaxTownID():    31
   GetTownCount():    28
@@ -685,5 +719,10 @@
     GetName():       (null : 0x00000000)
     GetPopulation(): 0
     GetLocation():   -1
-  Valid Industries:  28
+  Town 31
+    IsValidTown():   false
+    GetName():       (null : 0x00000000)
+    GetPopulation(): 0
+    GetLocation():   -1
+  Valid Towns:       28
   GetTownCount():    28
--- a/projects/openttd.vcproj	Thu Mar 22 09:10:00 2007 +0000
+++ b/projects/openttd.vcproj	Thu Mar 22 09:52:12 2007 +0000
@@ -1054,6 +1054,9 @@
 				RelativePath=".\..\src\ai\api\ai_settings.hpp">
 			</File>
 			<File
+				RelativePath=".\..\src\ai\api\ai_sign.hpp">
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_town.hpp">
 			</File>
 			<File
@@ -1106,6 +1109,9 @@
 				RelativePath=".\..\src\ai\api\ai_settings.cpp">
 			</File>
 			<File
+				RelativePath=".\..\src\ai\api\ai_sign.cpp">
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_town.cpp">
 			</File>
 			<File
--- a/projects/openttd_vs80.vcproj	Thu Mar 22 09:10:00 2007 +0000
+++ b/projects/openttd_vs80.vcproj	Thu Mar 22 09:52:12 2007 +0000
@@ -1624,6 +1624,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\ai\api\ai_sign.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_town.hpp"
 				>
 			</File>
@@ -1692,6 +1696,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\ai\api\ai_sign.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ai\api\ai_town.cpp"
 				>
 			</File>
--- a/source.list	Thu Mar 22 09:10:00 2007 +0000
+++ b/source.list	Thu Mar 22 09:52:12 2007 +0000
@@ -323,6 +323,7 @@
 ai/api/ai_order.hpp
 ai/api/ai_road.hpp
 ai/api/ai_settings.hpp
+ai/api/ai_sign.hpp
 ai/api/ai_town.hpp
 ai/api/ai_testmode.hpp
 ai/api/ai_transactionmode.hpp
@@ -341,6 +342,7 @@
 ai/api/ai_order.cpp
 ai/api/ai_road.cpp
 ai/api/ai_settings.cpp
+ai/api/ai_sign.cpp
 ai/api/ai_town.cpp
 ai/api/ai_testmode.cpp
 ai/api/ai_transactionmode.cpp
--- a/src/ai/ai_squirrel.cpp	Thu Mar 22 09:10:00 2007 +0000
+++ b/src/ai/ai_squirrel.cpp	Thu Mar 22 09:52:12 2007 +0000
@@ -31,6 +31,7 @@
 #include "api/ai_order.hpp"
 #include "api/ai_road.hpp"
 #include "api/ai_settings.hpp"
+#include "api/ai_sign.hpp"
 #include "api/ai_testmode.hpp"
 #include "api/ai_town.hpp"
 #include "api/ai_transactionmode.hpp"
@@ -196,6 +197,7 @@
 	SQAIMapRegister(this->engine);
 	SQAIOrderRegister(this->engine);
 	SQAIRoadRegister(this->engine);
+	SQAISignRegister(this->engine);
 	SQAISettingsRegister(this->engine);
 	SQAITestModeRegister(this->engine);
 	SQAITownRegister(this->engine);
--- a/src/ai/api/ai_object.cpp	Thu Mar 22 09:10:00 2007 +0000
+++ b/src/ai/api/ai_object.cpp	Thu Mar 22 09:52:12 2007 +0000
@@ -5,6 +5,8 @@
 #include "ai_object.hpp"
 #include "../../command.h"
 #include "../../player.h"
+#include "table/strings.h" // for signs.h
+#include "../../signs.h" // for _new_sign_id
 #include "../ai.h"
 #include "../ai_threads.h"
 
@@ -60,6 +62,16 @@
 	return AIObject::GetDoCommandStruct(_current_player)->new_vehicle_id;
 }
 
+void AIObject::SetNewSignID(SignID sign)
+{
+	AIObject::GetDoCommandStruct(_current_player)->new_sign_id = sign;
+}
+
+SignID AIObject::GetNewSignID()
+{
+	return AIObject::GetDoCommandStruct(_current_player)->new_sign_id;
+}
+
 AIObject::AIDoCommandStruct *AIObject::GetDoCommandStruct(PlayerID player)
 {
 	/* Storage for data on per-AI level */
@@ -130,6 +142,7 @@
 		::DoCommandP(tile, p1, p2, NULL, procc);
 		/* Store some values inside the AIObject static memory */
 		AIObject::SetNewVehicleID(_new_vehicle_id);
+		AIObject::SetNewSignID(_new_sign_id);
 
 		/* Suspend the AI player for 1 tick, so it simulates MultiPlayer */
 		AI_SuspendPlayer(_current_player, AIObject::GetDoCommandDelay());
--- a/src/ai/api/ai_object.hpp	Thu Mar 22 09:10:00 2007 +0000
+++ b/src/ai/api/ai_object.hpp	Thu Mar 22 09:52:12 2007 +0000
@@ -27,6 +27,7 @@
 		uint delay;
 		int32 costs;
 		VehicleID new_vehicle_id;
+		SignID new_sign_id;
 	};
 
 	/**
@@ -85,6 +86,11 @@
 	 */
 	static VehicleID GetNewVehicleID();
 
+	/**
+	 * Get the latest stored new_sign_id.
+	 */
+	static SignID GetNewSignID();
+
 public:
 	/**
 	 * Store a new_vehicle_id per player.
@@ -93,6 +99,12 @@
 	static void SetNewVehicleID(VehicleID vehicle);
 
 	/**
+	 * Store a new_sign_id per player.
+	 * @note NEVER use this yourself in your AI!
+	 */
+	static void SetNewSignID(SignID vehicle);
+
+	/**
 	 * If an AI starts, some internals needs to be resetted. This function
 	 *   takes care of that.
 	 * @note NEVER use this yourself in your AI!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ai/api/ai_sign.cpp	Thu Mar 22 09:52:12 2007 +0000
@@ -0,0 +1,67 @@
+/* $Id$ */
+
+/** @file ai_sign.cpp handles all functions of the AISign class */
+
+#include "ai_sign.hpp"
+#include "table/strings.h"
+#include "../../command.h"
+#include "../../signs.h"
+#include "../../strings.h"
+#include "../../variables.h" /* For SetDParam */
+
+SignID AISign::GetMaxSignID()
+{
+	return ::GetMaxSignIndex();
+}
+
+int32 AISign::GetSignCount()
+{
+	return ::GetNumSigns();
+}
+
+/* static */ bool AISign::IsValidSign(SignID sign_id)
+{
+	return ::IsValidSignID(sign_id);
+}
+
+char *AISign::GetText(SignID sign_id)
+{
+	if (!AISign::IsValidSign(sign_id)) return NULL;
+	static const int len = 64;
+	char *sign_name = MallocT<char>(len);
+
+	::GetString(sign_name, ::GetSign(sign_id)->str, &sign_name[len - 1]);
+
+	return sign_name;
+}
+
+TileIndex AISign::GetLocation(SignID sign_id)
+{
+	if (!AISign::IsValidSign(sign_id)) return INVALID_TILE;
+	const Sign *sign = ::GetSign(sign_id);
+	return ::TileVirtXY(sign->x, sign->y);
+}
+
+bool AISign::RemoveSign(SignID sign_id)
+{
+	_cmd_text = "";
+	return this->DoCommand(0, sign_id, 0, CMD_RENAME_SIGN);
+}
+
+SignID AISign::BuildSign(TileIndex location, const char *text)
+{
+	if (!::IsValidTile(location)) return INVALID_SIGN;
+
+	AIObject::SetNewSignID(INVALID_SIGN);
+	bool ret = this->DoCommand(location, 0, 0, CMD_PLACE_SIGN);
+	if (!ret) return INVALID_SIGN;
+
+	SignID new_sign_id = AIObject::GetNewSignID();
+	_cmd_text = text;
+	ret = this->DoCommand(0, new_sign_id, 0, CMD_RENAME_SIGN);
+	if (!ret) {
+		this->RemoveSign(new_sign_id);
+		return INVALID_SIGN;
+	}
+	return new_sign_id;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ai/api/ai_sign.hpp	Thu Mar 22 09:52:12 2007 +0000
@@ -0,0 +1,90 @@
+/* $Id$ */
+
+/** @file ai_sign.hpp Everything to query and build signs */
+
+#ifndef AI_SIGN_HPP
+#define AI_SIGN_HPP
+
+#include "ai_object.hpp"
+
+/**
+ * Class that handles all town related functions.
+ */
+class AISign : public AIObject {
+public:
+	/**
+	 * Gets the maximum sign index; there are no valid signs with a higher index.
+	 * @return the maximum town index.
+	 * @post return value is always non-negative.
+	 */
+	SignID GetMaxSignID();
+
+	/**
+	 * Gets the number of signs. This is different than GetSignTownID()
+	 *   because of the way OpenTTD works internally.
+	 * @return the number of signs.
+	 * @post return value is always non-negative.
+	 */
+	int32 GetSignCount();
+
+	/**
+	 * Checks whether the given sign index is valid.
+	 * @param sign_id the index to check.
+	 * @return true if and only if the sign is valid.
+	 */
+	static bool IsValidSign(SignID sign_id);
+
+	/**
+	 * Get the text on the sign.
+	 * @param sign_id the sign to get the text of.
+	 * @pre sign_id has to be valid (use IsValidSign()).
+	 * @return the text on the sign.
+	 * @note the returned name must be free'd (C++ only).
+	 */
+	char *GetText(SignID sign_id);
+
+	/**
+	 * Gets the location of the sign.
+	 * @param sign_id the sign to get the location of.
+	 * @pre sign_id has to be valid (use IsValidSign()).
+	 * @return the location of the sign.
+	 * @post return value is always positive and below AIMap::GetMapSize().
+	 */
+	TileIndex GetLocation(SignID sign_id);
+
+	/**
+	 * Removes a sign from the map.
+	 * @param sign_id the sign to remove.
+	 * @pre sign_id has to be valid (use IsValidSign()).
+	 * @return true if and only if the sign has been removed.
+	 */
+	bool RemoveSign(SignID sign_id);
+
+	/**
+	 * Builds a sign on the map.
+	 * @param location the place to build the sign.
+	 * @param text     the text to place on the sign.
+	 * @pre location is always positive and below AIMap::GetMapSize()
+	 * @pre text is not NULL and non-empty, i.e. length is positive.
+	 * @return the SignID of the build sign (use IsValidSign() to check for validity).
+	 */
+	SignID BuildSign(TileIndex location, const char *text);
+};
+
+#ifdef DEFINE_SQUIRREL_CLASS
+void SQAISignRegister(Squirrel *engine) {
+	DefSQClass <AISign> SQAISign("AISign");
+	SQAISign.PreRegister(engine);
+	SQAISign.AddConstructor(engine);
+	SQAISign.DefSQFunction(engine, &AISign::GetMaxSignID, "GetMaxSignID");
+	SQAISign.DefSQFunction(engine, &AISign::GetSignCount, "GetSignCount");
+	SQAISign.DefSQFunction(engine, &AISign::IsValidSign,  "IsValidSign");
+	SQAISign.DefSQFunction(engine, &AISign::GetText,      "GetText");
+	SQAISign.DefSQFunction(engine, &AISign::GetLocation,  "GetLocation");
+	SQAISign.DefSQFunction(engine, &AISign::RemoveSign,   "RemoveSign");
+	SQAISign.DefSQFunction(engine, &AISign::BuildSign,    "BuildSign");
+	SQAISign.PostRegister(engine);
+}
+#endif /* SQUIRREL_CLASS */
+
+#endif /* AI_SIGN_HPP */
--- a/src/signs.cpp	Thu Mar 22 09:10:00 2007 +0000
+++ b/src/signs.cpp	Thu Mar 22 09:52:12 2007 +0000
@@ -10,7 +10,8 @@
 #include "command.h"
 #include "variables.h"
 
-static Sign *_new_sign;
+SignID _new_sign_id;
+uint _total_signs;
 
 /**
  * Called if a new block is added to the sign-pool
@@ -132,7 +133,8 @@
 		MarkSignDirty(si);
 		InvalidateWindow(WC_SIGN_LIST, 0);
 		_sign_sort_dirty = true;
-		_new_sign = si;
+		_new_sign_id = si->index;
+		_total_signs++;
 	}
 
 	return 0;
@@ -184,6 +186,7 @@
 
 			InvalidateWindow(WC_SIGN_LIST, 0);
 			_sign_sort_dirty = true;
+			_total_signs--;
 		}
 	}
 
@@ -198,7 +201,7 @@
 void CcPlaceSign(bool success, TileIndex tile, uint32 p1, uint32 p2)
 {
 	if (success) {
-		ShowRenameSignWindow(_new_sign);
+		ShowRenameSignWindow(GetSign(_new_sign_id));
 		ResetObjectToPlace();
 	}
 }
@@ -221,6 +224,7 @@
  */
 void InitializeSigns()
 {
+	_total_signs = 0;
 	CleanPool(&_Sign_pool);
 	AddBlockToPool(&_Sign_pool);
 }
@@ -258,6 +262,7 @@
  */
 static void Load_SIGN()
 {
+	_total_signs = 0;
 	int index;
 	while ((index = SlIterateArray()) != -1) {
 		Sign *si;
@@ -267,6 +272,8 @@
 
 		si = GetSign(index);
 		SlObject(si, _sign_desc);
+
+		_total_signs++;
 	}
 
 	_sign_sort_dirty = true;
--- a/src/signs.h	Thu Mar 22 09:10:00 2007 +0000
+++ b/src/signs.h	Thu Mar 22 09:52:12 2007 +0000
@@ -16,6 +16,12 @@
 	SignID       index;
 };
 
+enum {
+	INVALID_SIGN = 0xFFFF,
+};
+
+extern SignID _new_sign_id;
+
 DECLARE_OLD_POOL(Sign, Sign, 2, 16000)
 
 static inline SignID GetMaxSignIndex()
@@ -30,7 +36,8 @@
 
 static inline uint GetNumSigns()
 {
-	return GetSignPoolSize();
+	extern uint _total_signs;
+	return _total_signs;
 }
 
 /**