Changeset - r2684:e4749a613214
[Not reviewed]
master
0 8 0
truelight - 19 years ago 2005-11-22 15:55:38
truelight@openttd.org
(svn r3226) -Fix: GPMI implementation had minor glitches
-Fix: the AI speed control is done by the AI-core, individual AIs don't have to do it (so, AIs were delayed twice ;)
-Add: Support for AI-network-clients (an AI, connecting to a remote server)
-Fix: minor AI-core problems
8 files changed with 64 insertions and 57 deletions:
0 comments (0 inline, 0 general)
ai/ai.c
Show inline comments
 
@@ -84,13 +84,13 @@ int32 AI_DoCommand(uint tile, uint32 p1,
 
	 *   person.. should we check for those funny jokes?
 
	 */
 

	
 
	/* First, do a test-run to see if we can do this */
 
	res = DoCommandByTile(tile, p1, p2, flags & ~DC_EXEC, procc);
 
	/* The command failed, or you didn't want to execute, or you are quering, return */
 
	if ((res & CMD_ERROR) || !(flags & DC_EXEC) || (flags & DC_QUERY_COST))
 
	if ((CmdFailed(res)) || !(flags & DC_EXEC) || (flags & DC_QUERY_COST))
 
		return res;
 

	
 
	/* If we did a DC_EXEC, and the command did not return an error, execute it
 
	    over the network */
 
	if (flags & DC_AUTO)                  procc |= CMD_AUTO;
 
	if (flags & DC_NO_WATER)              procc |= CMD_NO_WATER;
 
@@ -159,16 +159,16 @@ void AI_RunGameLoop(void)
 
	/* Make sure the AI follows the difficulty rule.. */
 
	assert(_opt.diff.competitor_speed <= 4);
 
	if ((_ai.tick & ((1 << (4 - _opt.diff.competitor_speed)) - 1)) != 0)
 
		return;
 

	
 
	/* Check for AI-client (so joining a network with an AI) */
 
	if (_ai.network_client) {
 
	if (_ai.network_client && _ai_player[_ai.network_playas].active) {
 
		/* Run the script */
 
		AI_DequeueCommands(_ai.network_player);
 
		AI_RunTick(_ai.network_player);
 
		AI_DequeueCommands(_ai.network_playas);
 
		AI_RunTick(_ai.network_playas);
 
	} else if (!_networking || _network_server) {
 
		/* Check if we want to run AIs (server or SP only) */
 
		Player *p;
 

	
 
		FOR_ALL_PLAYERS(p) {
 
			if (p->is_active && p->is_ai) {
 
@@ -196,24 +196,31 @@ void AI_StartNewAI(PlayerID player)
 

	
 
/**
 
 * This AI player died. Give it some chance to make a final puf.
 
 */
 
void AI_PlayerDied(PlayerID player)
 
{
 
	if (_ai.network_client && _ai.network_playas == player)
 
		_ai.network_playas = OWNER_SPECTATOR;
 

	
 
	/* Called if this AI died */
 
	_ai_player[player].active = false;
 
}
 

	
 
/**
 
 * Initialize some AI-related stuff.
 
 */
 
void AI_Initialize(void)
 
{
 
	bool ai_network_client = _ai.network_client;
 

	
 
	memset(&_ai, 0, sizeof(_ai));
 
	memset(&_ai_player, 0, sizeof(_ai_player));
 

	
 
	_ai.network_client = ai_network_client;
 
	_ai.network_playas = OWNER_SPECTATOR;
 
	_ai.enabled = true;
 
}
 

	
 
/**
 
 * Deinitializer for AI-related stuff.
 
 */
ai/ai.h
Show inline comments
 
@@ -28,13 +28,13 @@ typedef struct AIStruct {
 
	/* General */
 
	bool enabled;           //! Is AI enabled?
 
	uint tick;              //! The current tick (something like _frame_counter, only for AIs)
 

	
 
	/* For network-clients (a OpenTTD client who acts as an AI connected to a server) */
 
	bool network_client;    //! Are we a network_client?
 
	uint8 network_player;   //! The current network player we are connected as
 
	uint8 network_playas;   //! The current network player we are connected as
 
} AIStruct;
 

	
 
VARDEF AIStruct _ai;
 
VARDEF AIPlayer _ai_player[MAX_PLAYERS];
 

	
 
// ai.c
ai/default/default.c
Show inline comments
 
@@ -3935,30 +3935,12 @@ void AiDoGameLoop(Player *p)
 
	if (IS_HUMAN_PLAYER(_current_player))
 
		return;
 

	
 
	AiAdjustLoan(p);
 
	AiBuildCompanyHQ(p);
 

	
 
	if (_opt.diff.competitor_speed == 4) {
 
		/* ultraspeed */
 
		_ai_actions[p->ai.state](p);
 
		if (p->bankrupt_asked != 0)
 
			return;
 
	} else if (_opt.diff.competitor_speed != 3) {
 
		p->ai.tick++;
 
		if (!(p->ai.tick&1))
 
			return;
 
		if (_opt.diff.competitor_speed != 2) {
 
			if (!(p->ai.tick&2))
 
				return;
 
			if (_opt.diff.competitor_speed == 0) {
 
				if (!(p->ai.tick&4))
 
					return;
 
			}
 
		}
 
	}
 
#if 0
 
	{
 
		static byte old_state = 99;
 
		static bool hasdots = false;
 
		char *_ai_state_names[]={
 
			"AiCase0",
ai/trolly/trolly.c
Show inline comments
 
@@ -41,13 +41,13 @@ static void AiNew_State_FirstTime(Player
 
	//   You have quickly a small mistake in the state-array
 
	//   With that, everything would go wrong. Finding that, is almost impossible
 
	//   With this assert, that problem can never happen.
 
	assert(p->ainew.state == AI_STATE_FIRST_TIME);
 
	// We first have to init some things
 

	
 
	if (_current_player == 1) {
 
	if (_current_player == 1 || _ai.network_client) {
 
		ShowErrorMessage(-1, TEMP_AI_IN_PROGRESS, 0, 0);
 
	}
 

	
 
	// The PathFinder (AyStar)
 
	// TODO: Maybe when an AI goes bankrupt, this is de-init
 
	//  or when coming from a savegame.. should be checked out!
 
@@ -1344,47 +1344,21 @@ static void AiNew_OnTick(Player *p)
 
		_ainew_state[p->ainew.state](p);
 
}
 

	
 

	
 
void AiNewDoGameLoop(Player *p)
 
{
 
	// If it is a human player, it is not an AI, so bubye!
 
	if (IS_HUMAN_PLAYER(_current_player)) return;
 

	
 
	if (p->ainew.state == AI_STATE_STARTUP) {
 
		// The AI just got alive!
 
		p->ainew.state = AI_STATE_FIRST_TIME;
 
		p->ainew.tick = 0;
 

	
 
		// Only startup the AI
 
		return;
 
	}
 

	
 
	// We keep a ticker. We use it for competitor_speed
 
	p->ainew.tick++;
 

	
 
	// See what the speed is
 
	switch (_opt.diff.competitor_speed) {
 
		case 0: // Very slow
 
			if (!(p->ainew.tick&8)) return;
 
			break;
 

	
 
		case 1: // Slow
 
			if (!(p->ainew.tick&4)) return;
 
			break;
 

	
 
		case 2:
 
			if (!(p->ainew.tick&2)) return;
 
			break;
 

	
 
		case 3:
 
			if (!(p->ainew.tick&1)) return;
 
			break;
 

	
 
		case 4: // Very fast
 
		default: // Cool, a new speed setting.. ;) VERY fast ;)
 
			break;
 
	}
 

	
 
	// If we come here, we can do a tick.. do so!
 
	AiNew_OnTick(p);
 
}
economy.c
Show inline comments
 
@@ -474,12 +474,14 @@ static void PlayersCheckBankrupt(Player 
 
				ChangeOwnershipOfPlayerItems(owner, OWNER_SPECTATOR);
 
				// Register the player as not-active
 
				p->is_active = false;
 

	
 
				if (!IS_HUMAN_PLAYER(owner) && (!_networking || _network_server) && _ai.enabled)
 
					AI_PlayerDied(owner);
 
				if (IS_HUMAN_PLAYER(owner) && owner == _local_player && _ai.network_client)
 
					AI_PlayerDied(owner);
 
			}
 
		}
 
	}
 
}
 

	
 
void DrawNewsBankrupcy(Window *w)
network_client.c
Show inline comments
 
@@ -16,12 +16,13 @@
 
#include "command.h"
 
#include "gfx.h"
 
#include "window.h"
 
#include "settings.h"
 
#include "console.h"
 
#include "variables.h"
 
#include "ai/ai.h"
 

	
 

	
 
// This file handles all the client-commands
 

	
 

	
 
extern const char _openttd_revision[];
 
@@ -339,15 +340,24 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
	NetworkRecv_string(MY_CLIENT, p, unique_id, sizeof(unique_id));
 

	
 
	if (MY_CLIENT->quited)
 
		return NETWORK_RECV_STATUS_CONN_LOST;
 

	
 
	/* Do we receive a change of data? Most likely we changed playas */
 
	if (index == _network_own_client_index)
 
	if (index == _network_own_client_index) {
 
		_network_playas = playas;
 

	
 
		/* Are we a ai-network-client? */
 
		if (_ai.network_client) {
 
			if (_ai.network_playas == OWNER_SPECTATOR)
 
				AI_StartNewAI(playas - 1);
 

	
 
			_ai.network_playas = playas - 1;
 
		}
 
	}
 

	
 
	ci = NetworkFindClientInfoFromIndex(index);
 
	if (ci != NULL) {
 
		if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) {
 
			// Client name changed, display the change
 
			NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", name);
 
		} else if (playas != ci->client_playas) {
 
@@ -529,12 +539,23 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
			_local_player = _network_playas - 1;
 
			_patches.autorenew = GetPlayer(_local_player)->engine_renew;
 
			_patches.autorenew_months = GetPlayer(_local_player)->engine_renew_months;
 
			_patches.autorenew_money = GetPlayer(_local_player)->engine_renew_money;
 
			DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
 
		}
 

	
 
		/* Check if we are an ai-network-client, and if so, disable GUI */
 
		if (_ai.network_client) {
 
			_ai.network_playas = _local_player;
 
			_local_player      = OWNER_SPECTATOR;
 

	
 
			if (_ai.network_playas != OWNER_SPECTATOR) {
 
				/* If we didn't join the game as a spectator, activate the AI */
 
				AI_StartNewAI(_ai.network_playas);
 
			}
 
		}
 
	}
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FRAME)
openttd.c
Show inline comments
 
@@ -327,15 +327,15 @@ int ttd_main(int argc, char* argv[])
 

	
 
	// The last param of the following function means this:
 
	//   a letter means: it accepts that param (e.g.: -h)
 
	//   a ':' behind it means: it need a param (e.g.: -m<driver>)
 
	//   a '::' behind it means: it can optional have a param (e.g.: -d<debug>)
 
	#if !defined(__MORPHOS__) && !defined(__AMIGA__) && !defined(WIN32)
 
		optformat = "m:s:v:hDfn::l:eit:d::r:g::G:p:c:";
 
		optformat = "bm:s:v:hDfn::l:eit:d::r:g::G:p:c:";
 
	#else
 
		optformat = "m:s:v:hDn::l:eit:d::r:g::G:p:c:"; // no fork option
 
		optformat = "bm:s:v:hDn::l:eit:d::r:g::G:p:c:"; // no fork option
 
	#endif
 

	
 
	MyGetOptInit(&mgo, argc-1, argv+1, optformat);
 
	while ((i = MyGetOpt(&mgo)) != -1) {
 
		switch(i) {
 
		case 'm': ttd_strlcpy(musicdriver, mgo.opt, sizeof(musicdriver)); break;
 
@@ -355,12 +355,13 @@ int ttd_main(int argc, char* argv[])
 
				if (mgo.opt)
 
					// Optional, you can give an IP
 
					network_conn = mgo.opt;
 
				else
 
					network_conn = NULL;
 
			} break;
 
		case 'b': _ai.network_client = true; break;
 
		case 'r': ParseResolution(resolution, mgo.opt); break;
 
		case 'l': language = mgo.opt; break;
 
		case 't': startdate = atoi(mgo.opt); break;
 
		case 'd': {
 
#if defined(WIN32)
 
				CreateConsole();
 
@@ -392,18 +393,23 @@ int ttd_main(int argc, char* argv[])
 
		case 'h':
 
			showhelp();
 
			return 0;
 
		}
 
	}
 

	
 
	if (_ai.network_client && !network) {
 
		_ai.network_client = false;
 
		DEBUG(ai, 0)("[AI] Can't enable network-AI, because '-n' is not used\n");
 
	}
 

	
 
	DeterminePaths();
 
	CheckExternalFiles();
 

	
 
#ifdef GPMI
 
	/* Set the debug proc */
 
	gpmi_debug_proc    = &gpmi_debug_openttd;
 
	gpmi_debug_proc = &gpmi_debug_openttd;
 

	
 
	/* Initialize GPMI */
 
	gpmi_init();
 

	
 
	/* Add our paths so we can find our own packages */
 
	gpmi_path_append(&gpmi_path_modules, "gpmi/modules");
 
@@ -528,12 +534,17 @@ int ttd_main(int argc, char* argv[])
 
	/* uninitialize variables that are allocated dynamic */
 
	UnInitializeDynamicVariables();
 

	
 
	/* stop the AI */
 
	AI_Uninitialize();
 

	
 
#ifdef GPMI
 
	/* Uninitialize GPMI */
 
	gpmi_uninit();
 
#endif /* GPMI */
 

	
 
	/* Close all and any open filehandles */
 
	FioCloseAll();
 
	UnInitializeGame();
 

	
 
	return 0;
 
}
players.c
Show inline comments
 
@@ -803,16 +803,26 @@ int32 CmdPlayerCtrl(int x, int y, uint32
 
		if (_networking && !_network_server && _local_player == OWNER_SPECTATOR)
 
			/* In case we are a client joining a server... */
 
			DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
 
#endif /* ENABLE_NETWORK */
 

	
 
		if (p != NULL) {
 
			if (_local_player == OWNER_SPECTATOR) {
 
			if (_local_player == OWNER_SPECTATOR && (!_ai.network_client || _ai.network_playas == OWNER_SPECTATOR)) {
 
				/* Check if we do not want to be a spectator in network */
 
				if (!_networking ||  (_network_server && !_network_dedicated) || _network_playas != OWNER_SPECTATOR) {
 
					_local_player = p->index;
 
				if (!_networking || (_network_server && !_network_dedicated) || _network_playas != OWNER_SPECTATOR || _ai.network_client) {
 
					if (_ai.network_client) {
 
						/* As ai-network-client, we have our own rulez (disable GUI and stuff) */
 
						_ai.network_playas = p->index;
 
						_local_player      = OWNER_SPECTATOR;
 
						if (_ai.network_playas != OWNER_SPECTATOR) {
 
							/* If we didn't join the game as a spectator, activate the AI */
 
							AI_StartNewAI(_ai.network_playas);
 
						}
 
					} else {
 
						_local_player = p->index;
 
					}
 
					MarkWholeScreenDirty();
 
				}
 
			} else if (p->index == _local_player) {
 
				DoCommandP(0, (_patches.autorenew << 15 ) | (_patches.autorenew_months << 16) | 4, _patches.autorenew_money, NULL, CMD_REPLACE_VEHICLE);
 
			}
 
#ifdef ENABLE_NETWORK
0 comments (0 inline, 0 general)