(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
--- 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!
*/