# HG changeset patch # User truebrain # Date 1203948194 0 # Node ID 265fdd2130c3fe55dfd0d5c08de7f3db1e14e213 # Parent e6c07e89b89f1088cc6a40ef11b467567ee4bf95 (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 diff -r e6c07e89b89f -r 265fdd2130c3 src/ai/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; -} diff -r e6c07e89b89f -r 265fdd2130c3 src/ai/ai_threads.h --- 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 */ diff -r e6c07e89b89f -r 265fdd2130c3 src/ai/api/ai_object.cpp --- 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 { diff -r e6c07e89b89f -r 265fdd2130c3 src/ai/api/ai_object.hpp --- 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! */