summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortron <tron@openttd.org>2006-06-04 09:10:24 +0000
committertron <tron@openttd.org>2006-06-04 09:10:24 +0000
commit36e31fa41fceb9044d1a4106e6775af7ab04fc8d (patch)
tree7169789e49a59433f674337c2c7505ad5938e746
parent3e5ef7319e04711fb29aac135ac6a814af4708a7 (diff)
downloadopenttd-36e31fa41fceb9044d1a4106e6775af7ab04fc8d.tar.xz
(svn r5092) -Fix: There was a gross race condition in the AI code which made it pretty random if the AI could give a new vehicle its orders
-rw-r--r--ai/ai.c18
-rw-r--r--ai/ai.h2
-rw-r--r--ai/trolly/build.c21
-rw-r--r--ai/trolly/trolly.c15
-rw-r--r--ai/trolly/trolly.h1
-rw-r--r--callback_table.c3
6 files changed, 41 insertions, 19 deletions
diff --git a/ai/ai.c b/ai/ai.c
index 6754dc82e..6725faaea 100644
--- a/ai/ai.c
+++ b/ai/ai.c
@@ -32,7 +32,7 @@ static void AI_DequeueCommands(PlayerID player)
/* Copy the DP back in place */
_cmd_text = com->text;
- DoCommandP(com->tile, com->p1, com->p2, NULL, com->procc);
+ DoCommandP(com->tile, com->p1, com->p2, com->callback, com->procc);
/* Free item */
entry_com = com->next;
@@ -45,7 +45,7 @@ static void AI_DequeueCommands(PlayerID player)
* Needed for SP; we need to delay DoCommand with 1 tick, because else events
* will make infinite loops (AIScript).
*/
-static void AI_PutCommandInQueue(PlayerID player, TileIndex tile, uint32 p1, uint32 p2, uint procc)
+static void AI_PutCommandInQueue(PlayerID player, TileIndex tile, uint32 p1, uint32 p2, uint procc, CommandCallback* callback)
{
AICommand *com;
@@ -67,6 +67,7 @@ static void AI_PutCommandInQueue(PlayerID player, TileIndex tile, uint32 p1, uin
com->p1 = p1;
com->p2 = p2;
com->procc = procc;
+ com->callback = callback;
com->next = NULL;
com->text = NULL;
@@ -80,7 +81,7 @@ static void AI_PutCommandInQueue(PlayerID player, TileIndex tile, uint32 p1, uin
/**
* Executes a raw DoCommand for the AI.
*/
-int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
+int32 AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback)
{
PlayerID old_lp;
int32 res = 0;
@@ -120,12 +121,12 @@ int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint proc
/* Send the command */
if (_networking)
/* Network is easy, send it to his handler */
- NetworkSend_Command(tile, p1, p2, procc, NULL);
+ NetworkSend_Command(tile, p1, p2, procc, callback);
else
#endif
/* If we execute BuildCommands directly in SP, we have a big problem with events
* so we need to delay is for 1 tick */
- AI_PutCommandInQueue(_current_player, tile, p1, p2, procc);
+ AI_PutCommandInQueue(_current_player, tile, p1, p2, procc, callback);
/* Set _local_player back */
_local_player = old_lp;
@@ -135,6 +136,13 @@ int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint proc
return res;
}
+
+int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
+{
+ return AI_DoCommandCc(tile, p1, p2, flags, procc, NULL);
+}
+
+
/**
* Run 1 tick of the AI. Don't overdo it, keep it realistic.
*/
diff --git a/ai/ai.h b/ai/ai.h
index 76e2dc035..ec06b302f 100644
--- a/ai/ai.h
+++ b/ai/ai.h
@@ -11,6 +11,7 @@ typedef struct AICommand {
uint32 p1;
uint32 p2;
uint32 procc;
+ CommandCallback* callback;
char *text;
uint uid;
@@ -46,6 +47,7 @@ void AI_RunGameLoop(void);
void AI_Initialize(void);
void AI_Uninitialize(void);
int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
+int32 AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback);
/** Is it allowed to start a new AI.
* This function checks some boundries to see if we should launch a new AI.
diff --git a/ai/trolly/build.c b/ai/trolly/build.c
index 2b6342604..1f4324355 100644
--- a/ai/trolly/build.c
+++ b/ai/trolly/build.c
@@ -7,6 +7,7 @@
#include "../../map.h"
#include "../../road_map.h"
#include "../../tile.h"
+#include "../../vehicle.h"
#include "../../command.h"
#include "trolly.h"
#include "../../engine.h"
@@ -249,6 +250,20 @@ EngineID AiNew_PickVehicle(Player *p)
}
+void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
+{
+ Player* p = GetPlayer(_current_player);
+
+ if (success) {
+ p->ainew.state = AI_STATE_GIVE_ORDERS;
+ p->ainew.veh_id = _new_vehicle_id;
+ } else {
+ /* XXX this should be handled more gracefully */
+ p->ainew.state = AI_STATE_NOTHING;
+ }
+}
+
+
// Builds the best vehicle possible
int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
{
@@ -257,7 +272,11 @@ int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
if (i == INVALID_ENGINE) return CMD_ERROR;
if (p->ainew.tbt == AI_TRAIN) return CMD_ERROR;
- return AI_DoCommand(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
+ if (flag & DC_EXEC) {
+ return AI_DoCommandCc(tile, i, 0, flag, CMD_BUILD_ROAD_VEH, CcAI);
+ } else {
+ return AI_DoCommand(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
+ }
}
int AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag)
diff --git a/ai/trolly/trolly.c b/ai/trolly/trolly.c
index 52cf573e3..b003c21df 100644
--- a/ai/trolly/trolly.c
+++ b/ai/trolly/trolly.c
@@ -1155,7 +1155,7 @@ static void AiNew_State_BuildVehicle(Player *p)
// Decrease the total counter
p->ainew.amount_veh--;
// Go give some orders!
- p->ainew.state = AI_STATE_GIVE_ORDERS;
+ p->ainew.state = AI_STATE_WAIT_FOR_BUILD;
}
@@ -1167,18 +1167,6 @@ static void AiNew_State_GiveOrders(Player *p)
assert(p->ainew.state == AI_STATE_GIVE_ORDERS);
- // Get the new ID
- /* XXX -- Because this AI isn't using any event-system, this is VERY dangerous!
- * There is no way telling if the vehicle is already bought (or delayed by the
- * network), and if bought, if not an other vehicle is bought in between.. in
- * other words, there is absolutely no way knowing if this id is the true
- * id.. soon this will all change, but for now, we needed something to test
- * on ;) -- TrueLight -- 21-11-2005 */
- if (p->ainew.tbt == AI_TRAIN) {
- } else {
- p->ainew.veh_id = _new_roadveh_id;
- }
-
if (p->ainew.veh_main_id != INVALID_VEHICLE) {
AI_DoCommand(0, p->ainew.veh_id + (p->ainew.veh_main_id << 16), 0, DC_EXEC, CMD_CLONE_ORDER);
@@ -1323,6 +1311,7 @@ static AiNew_StateFunction* const _ainew_state[] = {
AiNew_State_BuildPath,
AiNew_State_BuildDepot,
AiNew_State_BuildVehicle,
+ NULL,
AiNew_State_GiveOrders,
AiNew_State_StartVehicle,
AiNew_State_RepayMoney,
diff --git a/ai/trolly/trolly.h b/ai/trolly/trolly.h
index 3e364a2b5..e0d70fbf6 100644
--- a/ai/trolly/trolly.h
+++ b/ai/trolly/trolly.h
@@ -187,6 +187,7 @@ enum {
AI_STATE_BUILD_PATH,
AI_STATE_BUILD_DEPOT,
AI_STATE_BUILD_VEHICLE,
+ AI_STATE_WAIT_FOR_BUILD,
AI_STATE_GIVE_ORDERS,
AI_STATE_START_VEHICLE,
AI_STATE_REPAY_MONEY,
diff --git a/callback_table.c b/callback_table.c
index 2c9ff3d84..14203a2c3 100644
--- a/callback_table.c
+++ b/callback_table.c
@@ -53,6 +53,8 @@ CommandCallback CcBuildWagon;
CommandCallback CcBuildLoco;
CommandCallback CcCloneTrain;
+CommandCallback CcAI;
+
CommandCallback *_callback_table[] = {
/* 0x00 */ NULL,
/* 0x01 */ CcBuildAircraft,
@@ -79,6 +81,7 @@ CommandCallback *_callback_table[] = {
/* 0x16 */ CcCloneRoadVeh,
/* 0x17 */ CcCloneShip,
/* 0x18 */ CcCloneTrain,
+ /* 0x19 */ CcAI
};
const int _callback_table_count = lengthof(_callback_table);