(svn r3304) -Add: allow AI-events to see the UID of the command
authortruelight
Wed, 14 Dec 2005 14:38:23 +0000
changeset 2759 c2a6fd12b41f
parent 2758 9cd8a21e9a7b
child 2760 29be62b09f09
(svn r3304) -Add: allow AI-events to see the UID of the command
-Fix: improved the logic of the UID code for AIs
ai/ai.c
ai/ai.h
ai/ai_event.h
command.c
--- a/ai/ai.c	Wed Dec 14 09:15:06 2005 +0000
+++ b/ai/ai.c	Wed Dec 14 14:38:23 2005 +0000
@@ -156,7 +156,7 @@
 int32 AI_DoCommandChecked(uint tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
 {
 	AICommand *new;
-	uint unique_id = uids[_current_player];
+	uint unique_id = uids[_current_player] + 1; // + 1, because 0 is reserved
 	int32 res;
 
 	res = DoCommandByTile(tile, p1, p2, flags & ~DC_EXEC, procc);
@@ -192,13 +192,16 @@
 }
 
 /**
- * A command is executed for real, and is giving us his result (failed yes/no). Inform the AI with it via
- *  an event.Z
+ * Find the right UID for this command.
  */
-void AI_CommandResult(uint32 cmd, uint32 p1, uint32 p2, TileIndex tile, bool succeeded)
+void AI_GetCommandUID(uint32 cmd, uint32 p1, uint32 p2, TileIndex tile)
 {
 	AICommand *command = command_uid[_current_player];
 
+	/* Reset to 0, meaning no UID. Then we start detecting if we have an UID for this command */
+	_ai_current_uid  = 0;
+	_ai_current_tile = INVALID_TILE;
+
 	if (command == NULL)
 		return;
 
@@ -217,15 +220,30 @@
 		return;
 	}
 
+	/* Remove this command from the list */
 	command_uid[_current_player] = command_uid[_current_player]->next;
 	if (command_uid[_current_player] == NULL)
 		command_uid_tail[_current_player] = NULL;
 
-	ai_event(_current_player, succeeded ? ottd_Event_CommandSucceeded : ottd_Event_CommandFailed, tile, command->uid);
+	/* Broadcast our current UID and tile */
+	_ai_current_uid  = command->uid;
+	_ai_current_tile = tile;
 	free(command);
 }
 
 /**
+ * A command is executed for real, and is giving us his result (failed yes/no). Inform the AI with it via
+ *  an event.
+ */
+void AI_CommandResult(bool succeeded)
+{
+	if (_ai_current_uid == 0)
+		return;
+
+	ai_event(_current_player, succeeded ? ottd_Event_CommandSucceeded : ottd_Event_CommandFailed, _ai_current_tile);
+}
+
+/**
  * Run 1 tick of the AI. Don't overdo it, keep it realistic.
  */
 static void AI_RunTick(PlayerID player)
--- a/ai/ai.h	Wed Dec 14 09:15:06 2005 +0000
+++ b/ai/ai.h	Wed Dec 14 14:38:23 2005 +0000
@@ -51,6 +51,8 @@
 
 VARDEF AIStruct _ai;
 VARDEF AIPlayer _ai_player[MAX_PLAYERS];
+VARDEF uint _ai_current_uid; //! Keeps track of the current UID, if any (0 means none)
+VARDEF TileIndex _ai_current_tile; //! Keeps track of the current Tile.
 
 // ai.c
 void AI_StartNewAI(PlayerID player);
@@ -60,7 +62,8 @@
 void AI_Uninitialize(void);
 int32 AI_DoCommand(uint tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
 int32 AI_DoCommandChecked(uint tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
-void AI_CommandResult(uint32 cmd, uint32 p1, uint32 p2, TileIndex tile, bool failed);
+void AI_GetCommandUID(uint32 cmd, uint32 p1, uint32 p2, TileIndex tile);
+void AI_CommandResult(bool failed);
 
 /** Is it allowed to start a new AI.
  * This function checks some boundries to see if we should launch a new AI.
--- a/ai/ai_event.h	Wed Dec 14 09:15:06 2005 +0000
+++ b/ai/ai_event.h	Wed Dec 14 14:38:23 2005 +0000
@@ -13,7 +13,7 @@
  *   tell us ASAP! */
 #	define ai_event(player, event, ...) \
 		if ((player) < MAX_PLAYERS && _ai_player[(player)].module != NULL) \
-			gpmi_event(_ai_player[(player)].module, (event), ##__VA_ARGS__)
+			gpmi_event(_ai_player[(player)].module, (event), _ai_current_uid, ##__VA_ARGS__)
 
 #else /* GPMI */
 
--- a/command.c	Wed Dec 14 09:15:06 2005 +0000
+++ b/command.c	Wed Dec 14 14:38:23 2005 +0000
@@ -403,6 +403,8 @@
 	int x = TileX(tile) * 16;
 	int y = TileY(tile) * 16;
 
+	AI_GetCommandUID(cmd, p1, p2, tile);
+
 	/* Do not even think about executing out-of-bounds tile-commands */
 	if (tile > MapSize()) {
 		_cmd_text = NULL;
@@ -477,12 +479,12 @@
 			if (res & 0xFFFF) _error_message = res & 0xFFFF;
 			/* Trigger an event special for the AI, so it knows the build has failed
 			 *  Because the commands are always delayed, this is the only way. */
-			AI_CommandResult(cmd, p1, p2, tile, false);
+			AI_CommandResult(false);
 			goto show_error;
 		}
 		// no money? Only check if notest is off
 		if (!notest && res != 0 && !CheckPlayerHasMoney(res)) {
-			AI_CommandResult(cmd, p1, p2, tile, false);
+			AI_CommandResult(false);
 			goto show_error;
 		}
 	}
@@ -519,12 +521,12 @@
 	} else {
 		if (CmdFailed(res2)) {
 			if (res2 & 0xFFFF) _error_message = res2 & 0xFFFF;
-			AI_CommandResult(cmd, p1, p2, tile, false);
+			AI_CommandResult(false);
 			goto show_error;
 		}
 	}
 
-	AI_CommandResult(cmd, p1, p2, tile, true);
+	AI_CommandResult(true);
 
 	SubtractMoneyFromPlayer(res2);