(svn r12248) [NoAI] -Codechange: last_command_res was in AIThread, while it should be in AIObject, like all other variables like it noai
authortruebrain
Mon, 25 Feb 2008 14:03:14 +0000
branchnoai
changeset 9760 265fdd2130c3
parent 9759 e6c07e89b89f
child 9761 6c3e0f29a232
(svn r12248) [NoAI] -Codechange: last_command_res was in AIThread, while it should be in AIObject, like all other variables like it
[NoAI] -Codechange: minor comment/code update in ai_threads.cpp
src/ai/ai_threads.cpp
src/ai/ai_threads.h
src/ai/api/ai_object.cpp
src/ai/api/ai_object.hpp
--- a/src/ai/ai_threads.cpp	Mon Feb 25 09:23:53 2008 +0000
+++ b/src/ai/ai_threads.cpp	Mon Feb 25 14:03:14 2008 +0000
@@ -40,8 +40,6 @@
 	ThreadState    state;            ///< The current state of the AI
 	int            ticks_to_sleep;   ///< Sleep this many runticks
 	AIController   *controller;      ///< Controller of this AI
-public:
-	bool           last_command_res; ///< The result of the last command
 
 	/**
 	 * Initialize this AI Thread base class for the given controller.
@@ -53,29 +51,29 @@
 protected:
 	AIThread(PlayerID player, AIController *controller)
 	{
-		/* register new thread */
+		assert(s_threads[player] == NULL);
+		/* Register new thread */
 		s_threads[player] = this;
 
-		/* ensure that main thread has its wrapper too */
+		/* Ensure that main thread has its wrapper too */
 		if (player != MAIN_THREAD) stFind(MAIN_THREAD);
 
 		this->state = INITIALIZED;
 		this->fiber_id = player;
 		this->ticks_to_sleep = 0;
 		this->controller = controller;
-		this->last_command_res = false;
 	}
 
 public:
 	virtual ~AIThread()
 	{
-		/* at this point we should be already removed from the thread collection */
+		/* At this point we should be already removed from the thread collection */
 		assert(this->fiber_id == MAIN_THREAD || stFind(this->fiber_id) == NULL);
 	}
 
 	/**
 	 * Start the AI thread and return once the AI calls Sleep or
-	 * any other suspending command.
+	 *  any other suspending command.
 	 * @note should be called after Initialize, but before any other function.
 	 */
 public:
@@ -91,6 +89,7 @@
 		assert(this->state == STARTING);
 		this->state = RUNNING;
 
+		/* Run the AI. If this function ever returns, the AI is dead */
 		this->controller->Start();
 
 		if (this->state != STOPPING) {
@@ -111,18 +110,24 @@
 public:
 	void Suspend(int timeout)
 	{
-		assert(this->fiber_id != MAIN_THREAD); // should not attempt to suspend main fiber
-		assert(this->state == RUNNING); // must be in running state
-		assert(this->CurrentThread() == this); // we can only suspend self
+		/* Should not attempt to suspend main fiber */
+		assert(this->fiber_id != MAIN_THREAD);
+		/* AI fiber should be running */
+		assert(this->state == RUNNING);
+		/* We can only suspend ourself */
+		assert(this->CurrentThread() == this);
 
 		this->ticks_to_sleep = timeout;
 
-		/* when AI thread gets suspended, it switches always to main thread */
+		/* When AI thread gets suspended, it always switches back to main thread */
 		AIThread *main = stFind(MAIN_THREAD);
 		main->SwitchToThis(RUNNING);
+
+		/* The AI is told to die by the main thread */
 		if (this->state == STOPPING) {
 			this->controller->Stop();
 			OnStop();
+			/* XXX -- It might be nice to throw an exception, as it is easier to handle */
 			//throw std::exception();
 			//NOT_REACHED();
 			return;
@@ -137,6 +142,9 @@
 public:
 	void Resume()
 	{
+		/* Should be called from main fiber only */
+		assert(CurrentThread() == stFind(MAIN_THREAD));
+		/* AI fiber should be suspended */
 		assert(this->state == SUSPENDED);
 		/* Normally the ticks_to_sleep hangs at -1 for MP. Possible the MP is
 		 * faster then the delay requested by the user. In this case the value
@@ -156,9 +164,9 @@
 public:
 	void RunTick()
 	{
-		/* should be called from main fiber only */
+		/* Should be called from main fiber only */
 		assert(CurrentThread() == stFind(MAIN_THREAD));
-		/* only AI fibers should be resumed this way */
+		/* Only AI fibers should be resumed this way */
 		assert(this != stFind(MAIN_THREAD));
 		/* AI fiber should be still suspended */
 		assert(this->state == SUSPENDED);
@@ -170,10 +178,11 @@
 		 *  reaches -1, and we 'hang' it there infinitely, until the MP commands
 		 *  comes in. In the case it happens sooner, the Resume() codes handles it
 		 *  nicely and makes the value positive with the remaining ticks to wait. */
-		if (this->ticks_to_sleep < -1) this->ticks_to_sleep++;
-		if (this->ticks_to_sleep < 0) return;   // We have to wait infinitely
+		if (this->ticks_to_sleep < -1)  this->ticks_to_sleep++;
+		if (this->ticks_to_sleep < 0)   return; // We have to wait infinitely
 		if (--this->ticks_to_sleep > 0) return; // We have to wait a little longer
 
+		/* Make the thread running again */
 		this->SwitchToThis(RUNNING);
 	}
 
@@ -192,20 +201,20 @@
 
 	/**
 	 * Called in the context of thread that wants to yield execution and switch
-	 * to 'this' thread. One of those threads should be always the main thread
-	 * (fiber_id == MAIN_THREAD).
+	 *  to 'this' thread. One of those threads should be always the main thread
+	 *  (fiber_id == MAIN_THREAD).
 	 */
 public:
 	virtual void SwitchToThis(ThreadState new_state) = 0;
 
 	/**
-	 * Find and return the thread object by its 'id' (player_id or MAIN_THREAD). Returns
-	 * NULL if such thread object doesn't exist. If fiber_id == MAIN_THREAD and the thread
-	 * object with this id doesn't exist, the new one is created and attached to the current
-	 * (main) thread.
+	 * Find and return the thread object by its 'id' (player_id or MAIN_THREAD).
+	 *  Returns NULL if such thread object doesn't exist. If
+	 *  (fiber_id == MAIN_THREAD) and the thread object with this id doesn't
+	 *  exist, the new one is created and attached to the current (main) thread.
 	 */
 public:
-	static AIThread* stFind(int fiber_id)
+	static AIThread *stFind(int fiber_id)
 	{
 		Threads::iterator it = s_threads.find(fiber_id);
 		if (it == s_threads.end()) {
@@ -230,7 +239,7 @@
 	 * Find the thread object that belongs to the currently running thread (caller).
 	 */
 public:
-	static AIThread* stCurrentThread()
+	static AIThread *stCurrentThread()
 	{
 		AIThread *main = stFind(MAIN_THREAD);
 		AIThread *cur = main->CurrentThread();
@@ -241,13 +250,13 @@
 	 * Find the thread object that belongs to the currently running thread (caller).
 	 */
 public:
-	virtual AIThread* CurrentThread() = 0;
+	virtual AIThread *CurrentThread() = 0;
 
 	/**
 	 * Create new AI thread object for given player and add it into thread collection.
 	 */
 public:
-	static AIThread* stNew(PlayerID player, AIController *controller);
+	static AIThread *stNew(PlayerID player, AIController *controller);
 };
 
 /**
@@ -255,8 +264,6 @@
  */
 /* static */ AIThread::Threads AIThread::s_threads;
 
-
-
 /**
  * AI thread implementation using Win32 thread API. This should be used only on Win95
  * where Fiber API is not supported. Main OTTD thread has assigned the first object
@@ -472,7 +479,7 @@
 	 * Ugly way how to provide stCurrentFiber() functionality for the base class.
 	 */
 protected:
-	/*virtual*/ AIThread* CurrentThread()
+	/*virtual*/ AIThread *CurrentThread()
 	{
 		return stCurrentFiber();
 	}
@@ -633,7 +640,7 @@
 	 * Ugly way how to provide stCurrentFiber() functionality for the base class.
 	 */
 public:
-	/*virtual*/ AIThread* CurrentThread()
+	/* virtual */ AIThread *CurrentThread()
 	{
 		return stCurrentFiber();
 	}
@@ -785,7 +792,7 @@
  * Create, register and return the new AI Thread object. It should choose the best
  * implementation for the current platform.
  */
-/* static */ AIThread* AIThread::stNew(PlayerID player, AIController *controller)
+/* static */ AIThread *AIThread::stNew(PlayerID player, AIController *controller)
 {
 	if (AIThread_Fiber::IsSupported()) {
 		/* Fibers are supported, use them */
@@ -800,7 +807,7 @@
 /**
  * Create, register and return the new AI Thread object.
  */
-/* static */ AIThread* AIThread::stNew(PlayerID player, AIController *controller)
+/* static */ AIThread *AIThread::stNew(PlayerID player, AIController *controller)
 {
 	return new AIThread_MT(player, controller);
 }
@@ -873,25 +880,12 @@
 	DEBUG(ai, 6, "CcAI(%d) from thr %d", _current_player, ThreadObject::CurrentId());
 	AIThread *thr = AIThread::stFind(_current_player);
 	assert(thr != NULL);
-	/* Store if we were a success or not and resume */
-	thr->last_command_res = success;
-
+	/* Store if we were a success or not */
+	AIObject::SetLastCommandRes(success);
 	/* Store some values inside the AIObject static memory */
 	AIObject::SetNewVehicleID(_new_vehicle_id);
 
+	/* Resume the thread now */
 	thr->Resume();
 }
 
-/**
- * Returns the result of the last command which was received by the
- *  MultiPlayer Command Callback.
- * @param player the player to the callback information about
- * @return true if and only if the last sent command succeeded
- */
-bool AI_GetCallbackResult(PlayerID player)
-{
-	DEBUG(ai, 6, "AI_GetCallbackResult(%d) from thr %d", player, ThreadObject::CurrentId());
-	AIThread *thr = AIThread::stFind(player);
-	assert(thr != NULL);
-	return thr->last_command_res;
-}
--- a/src/ai/ai_threads.h	Mon Feb 25 09:23:53 2008 +0000
+++ b/src/ai/ai_threads.h	Mon Feb 25 14:03:14 2008 +0000
@@ -14,6 +14,4 @@
 void AI_RunTick(PlayerID player);
 void AI_StopPlayer(PlayerID player);
 
-bool AI_GetCallbackResult(PlayerID player);
-
 #endif /* AI_THREADS_H */
--- a/src/ai/api/ai_object.cpp	Mon Feb 25 09:23:53 2008 +0000
+++ b/src/ai/api/ai_object.cpp	Mon Feb 25 14:03:14 2008 +0000
@@ -53,6 +53,16 @@
 	return AIObject::GetDoCommandStruct(_current_player)->costs.GetCost();
 }
 
+void AIObject::SetLastCommandRes(bool res)
+{
+	AIObject::GetDoCommandStruct(_current_player)->last_command_res = res;
+}
+
+bool AIObject::GetLastCommandRes()
+{
+	return AIObject::GetDoCommandStruct(_current_player)->last_command_res;
+}
+
 void AIObject::SetNewVehicleID(VehicleID vehicle)
 {
 	AIObject::GetDoCommandStruct(_current_player)->new_vehicle_id = vehicle;
@@ -147,7 +157,7 @@
 		/* Suspend the AI till the command is really executed */
 		AI_SuspendPlayer(_current_player, -(int)AIObject::GetDoCommandDelay());
 		/* Check if the callback still agrees with us, else return error */
-		if (!AI_GetCallbackResult(_current_player)) res = CMD_ERROR;
+		if (!AIObject::GetLastCommandRes()) res = CMD_ERROR;
 	} else {
 #else
 	{
--- a/src/ai/api/ai_object.hpp	Mon Feb 25 09:23:53 2008 +0000
+++ b/src/ai/api/ai_object.hpp	Mon Feb 25 14:03:14 2008 +0000
@@ -27,6 +27,7 @@
 		AIObject *mode_instance;
 		uint delay;
 		CommandCost costs;
+		bool last_command_res;
 		VehicleID new_vehicle_id;
 		SignID new_sign_id;
 		void *event_data;
@@ -84,6 +85,11 @@
 	static uint GetDoCommandDelay();
 
 	/**
+	 * Get the latest result of a DoCommand.
+	 */
+	static bool GetLastCommandRes();
+
+	/**
 	 * Get the latest stored new_vehicle_id.
 	 */
 	static VehicleID GetNewVehicleID();
@@ -100,6 +106,12 @@
 
 public:
 	/**
+	 * Store the latest result of a DoCommand per player.
+	 * @note NEVER use this yourself in your AI!
+	 */
+	static void SetLastCommandRes(bool res);
+
+	/**
 	 * Store a new_vehicle_id per player.
 	 * @note NEVER use this yourself in your AI!
 	 */