changeset 3946:de25032d7ef1 draft

(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
author tron <tron@openttd.org>
date Sun, 04 Jun 2006 09:10:24 +0000
parents 44021c8fce85
children b748e6c02a36
files ai/ai.c ai/ai.h ai/trolly/build.c ai/trolly/trolly.c ai/trolly/trolly.h callback_table.c
diffstat 6 files changed, 41 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/ai/ai.c
+++ b/ai/ai.c
@@ -32,7 +32,7 @@
 
 		/* 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 @@
  * 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 @@
 	com->p1    = p1;
 	com->p2    = p2;
 	com->procc = procc;
+	com->callback = callback;
 	com->next  = NULL;
 	com->text  = NULL;
 
@@ -80,7 +81,7 @@
 /**
  * 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 @@
 	/* 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 @@
 	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.
  */
--- a/ai/ai.h
+++ b/ai/ai.h
@@ -11,6 +11,7 @@
 	uint32 p1;
 	uint32 p2;
 	uint32 procc;
+	CommandCallback* callback;
 
 	char *text;
 	uint uid;
@@ -46,6 +47,7 @@
 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.
--- 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 @@
 }
 
 
+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 @@
 	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)
--- a/ai/trolly/trolly.c
+++ b/ai/trolly/trolly.c
@@ -1155,7 +1155,7 @@
 	// 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 @@
 
 	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 @@
 	AiNew_State_BuildPath,
 	AiNew_State_BuildDepot,
 	AiNew_State_BuildVehicle,
+	NULL,
 	AiNew_State_GiveOrders,
 	AiNew_State_StartVehicle,
 	AiNew_State_RepayMoney,
--- a/ai/trolly/trolly.h
+++ b/ai/trolly/trolly.h
@@ -187,6 +187,7 @@
 	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,
--- a/callback_table.c
+++ b/callback_table.c
@@ -53,6 +53,8 @@
 CommandCallback CcBuildLoco;
 CommandCallback CcCloneTrain;
 
+CommandCallback CcAI;
+
 CommandCallback *_callback_table[] = {
 	/* 0x00 */ NULL,
 	/* 0x01 */ CcBuildAircraft,
@@ -79,6 +81,7 @@
 	/* 0x16 */ CcCloneRoadVeh,
 	/* 0x17 */ CcCloneShip,
 	/* 0x18 */ CcCloneTrain,
+	/* 0x19 */ CcAI
 };
 
 const int _callback_table_count = lengthof(_callback_table);