Home » MODDING HQ 1.13 » v1.13 Coding Talk » Learning how the tactical AI works
Learning how the tactical AI works[message #274168] Tue, 22 February 2011 07:54 Go to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
Hey all,

Newbie here, I'm trying to play with the AI a bit.

I've found
\Jagged Alliance 2 v1.13 - Source code [1.0.0.2085]\Build\TacticalAI\DecideAction.cpp
, which returns actions for each soldiers such as "AI_ACTION_FLANK_LEFT", "AI_ACTION_SEEK_OPPONENT" and "AI_ACTION_TAKE_COVER".

However, I can't seem to find where these actions are defined. I've seen the actions names in "AIUtils.cpp" and "AI.h", but this is not where they are defined...


A pointer would be appreciated as my sanity is slowly fading Smile

Also, how does one build the exe to be able to see the "debugmsg" ?

Cheers!

[Updated on: Tue, 22 February 2011 19:02] by Moderator

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274176] Tue, 22 February 2011 10:40 Go to previous messageGo to next message
wanne (aka RoWa21) is currently offline wanne (aka RoWa21)

 
Messages:1961
Registered:October 2005
Location: Austria
Hi,

instead of download the source code from Revision 2085, you should download (SVN) the latest development source code (incl. the additonal GameDir files) from here:

https://81.169.133.124/source/ja2/branches/Wanne/JA2%201.13%20MP

If you want to see the debug messages, you have to compile a "Debug" executable, instead of a Release one.

@AI_Actions: For example, in DecideActions.cpp take a look at the method "DecideActionRed()". There is the following switch condition, which sets the different flank actions:

if ( dist > MIN_FLANK_DIST_YELLOW && dist < MAX_FLANK_DIST_YELLOW  )
{
	INT16 rdm = Random(6);

	switch (rdm)
	{
		case 1:
		case 2:
		case 3:
			if ( pSoldier->aiData.bLastAction != AI_ACTION_FLANK_LEFT && pSoldier->aiData.bLastAction != AI_ACTION_FLANK_RIGHT )
				action = AI_ACTION_FLANK_LEFT ;
			break;
		default:
			if ( pSoldier->aiData.bLastAction != AI_ACTION_FLANK_LEFT && pSoldier->aiData.bLastAction != AI_ACTION_FLANK_RIGHT )
				action = AI_ACTION_FLANK_RIGHT ;
			break;
	}
}
else
	return AI_ACTION_SEEK_NOISE ;




Report message to a moderator

Sergeant Major

Re: Learning how the AI works[message #274195] Tue, 22 February 2011 15:30 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
Thanks Rowa for the link and tips.

My understanding of the code above is that it sets the action of the soldier to be either AI_ACTION_FLANK_LEFT, AI_ACTION_FLANK_RIGHT or AI_ACTION_SEEK_NOISE.

What I meant to say is : Where is the behaviour of a soldier whose action is set to,say, "AI_ACTION_SEEK_NOISE" defined? Something that would look like "move toward sound source, stopping near obstacles that could provide cover, and keeping enough APs for an interrupt".

Cheers!

[Updated on: Tue, 22 February 2011 15:33] by Moderator

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274198] Tue, 22 February 2011 15:52 Go to previous messageGo to next message
wanne (aka RoWa21) is currently offline wanne (aka RoWa21)

 
Messages:1961
Registered:October 2005
Location: Austria
OK, now I understand what you mean Smile

I have not done anything with the AI, but you should contact "SpaceViking". He already has done tweaking the AI. Hope that helps.

Report message to a moderator

Sergeant Major

Re: Learning how the AI works[message #274199] Tue, 22 February 2011 15:57 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
Will do, thanks!

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274211] Tue, 22 February 2011 17:20 Go to previous messageGo to next message
SpaceViking is currently offline SpaceViking

 
Messages:751
Registered:January 2004
Location: Rochester, Minnesota, USA
Just to clear things up I have been working on the strategic AI (how the queen shifts forces around and such), not the tactical AI (how the soldiers act during a battle). I am interested in improving the tactical AI but I've never really looked at it.

Report message to a moderator

First Sergeant

Re: Learning how the AI works[message #274253] Tue, 22 February 2011 20:03 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
Here's where I am so far in trying to understand what is going on when someone is supposed to go and take cover..

Question: Is InternalGetNewSoldierPath where the actual moving occurs? I'm at a loss (again)
Cheers!



FIRST:
DecideAction (from DecideAction.CPP) returns an action, but it also sets parameters for that action. Example with AI_ACTION_TAKE_COVER, where sBestCover is probably the coordinate of the best cover available...

pSoldier->aiData.usActionData = sBestCover;
return(AI_ACTION_TAKE_COVER);

SECOND:
ExecuteAction (from AIMain.cpp) tries to execute this action.
All the "movement orders" will call the NewDest method (from AIUtils.cpp) to set a new pSoldier->pathing.sDestination based on pSoldier->aiData.usActionData

THIRD:
NewDest
-sets pSoldier->usUIMovementMode (sometimes using AIUtils's DetermineMovementMode() method)
-calls pSoldier->EVENT_InternalGetNewSoldierPath( usGridNo, pSoldier->usUIMovementMode , FALSE, pSoldier->flags.fNoAPToFinishMove );


SOLDIERTYPE::EVENT_InternalGetNewSoldierPath is located in "Soldier control.cpp"

[Updated on: Tue, 22 February 2011 21:24] by Moderator

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274329] Wed, 23 February 2011 15:59 Go to previous messageGo to next message
Buns is currently offline Buns

 
Messages:655
Registered:September 2010
Unfortuantly I cannot help you with the code, but my observation is that AI orders seem to updated, or generated, everytime it reaches a tile. This seems to be the reason behind the AI running in circles and wasting all APs for moving for and back between two adjecting tiles.

You can see this quite frequently when an enemy soldiers is standing behind a row of windows. He will often switch for and back between two windows until having spent all APs. Another very typical situation is an enemy who already has been shooting (means he can see his foe) but then suddenly advances a few tiles only to then run back beyond the tile he had started his movement from.

My guess would be that these orders are not executed (or generated?) en bloc, in the way of "move to tile 114 112 and then take cover", but step by step: "Take cover by moving to tile 114 112" and when the AI has reached this tile a new order is generated, which can include to move back to the tile it just came from.

Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #274337] Wed, 23 February 2011 17:34 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
Buns
Unfortuantly I cannot help you with the code, but my observation is that AI orders seem to updated, or generated, everytime it reaches a tile. This seems to be the reason behind the AI running in circles and wasting all APs for moving for and back between two adjecting tiles.

You can see this quite frequently when an enemy soldiers is standing behind a row of windows. He will often switch for and back between two windows until having spent all APs. Another very typical situation is an enemy who already has been shooting (means he can see his foe) but then suddenly advances a few tiles only to then run back beyond the tile he had started his movement from.

My guess would be that these orders are not executed (or generated?) en bloc, in the way of "move to tile 114 112 and then take cover", but step by step: "Take cover by moving to tile 114 112" and when the AI has reached this tile a new order is generated, which can include to move back to the tile it just came from.


Yup, I have the feeling that's why the AI will move back and forth all the time, I still have to find the code for this though.

This shows how far we are from an AI that coordinates multiple soldiers... Individual soldiers dont even know what they'll do 10 APs from now..



[Updated on: Wed, 23 February 2011 17:40] by Moderator

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274338] Wed, 23 February 2011 17:36 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
Just learned about the "Source Insight" program. Allowed me to generate to the following "relation graphs", might be interesting.

WinMain --> HandledWinMain --> InitializeStandardGamingPlatform --> InitializeGame --> GameScreens --> MainGameScreenHandle --> ExecuteOverhead --> HandleSoldierAI

And then:
HandleSoldierAI calls
1) TurnBasedHandleNPCAI which calls 1a) DecideAction and 1b) ExecuteAction
2) RTHandleAI , which calls 2a) RTDecideAction and 2b) ExecuteAction


DecideAction, ExecuteAction and (eventually) RTDecideAction are where it's at.

Maybe adding an action "Move to cover AND shoot" would be the way to go.

I'll try to figure out how to compile a "debug" version, to see which of the many "move" orders are being used when the AI is stuck on a window...





[Updated on: Wed, 23 February 2011 17:38] by Moderator

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274346] Wed, 23 February 2011 18:24 Go to previous messageGo to next message
Buns is currently offline Buns

 
Messages:655
Registered:September 2010
MorgluM
This shows how far we are from an AI that coordinates multiple soldiers...
Certainly. Anything like flanking manouver, encirclement and refined tactics like that are nothing but SiFi for that AI. I am pretty confident that the random generator in the above code snippet doesn't do it any good either.

If the single soldier would be able to generate an usefull order according to the enemies known to him and his comrades, and he would be acting according to this order until something important new happens (like sighting of a new foe), a lot would be achieved.

On the other hand, we usually handle the mercs the same way: checking each one where he can go to in order to hurt the enemy most, based on the enemies we know of (and those we anticipate because of playing the map for the 100st time - but hey, we are supposed to win each and every engagement with minimal losses).

MorgluM
Maybe adding an action "Move to cover AND shoot" would be the way to go.
I have a strong feeling that this could do the trick. A movement order (unless some default patrolways) should only be given together with the order what to do on the new tile, what should usually be "shoot!". This entire order needs to be saved over the turn and may not be cancelled unless the tile becomes 'invalid' because of new enemies appearing or the enemy moving out of range/sight/whatever.

Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #274360] Wed, 23 February 2011 21:13 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
Buns

Just received my teacher's comment for my master -- looks like I can't procrastinate anymore today.

I'd love to see if I can implement that.

I'm slowly becoming functional. I've installed Visual Studio 2010, and I compiled the "solution" for the latest SVN downloaded with Tortoise.

It runs and the file is called JA2-ENG-DEBUG.EXE. So I assume I compiled the WIN32 DEBUG and not the WIN32 RELEASE version by default, which is great.

Question to coders: When I start JA2-ENG-DEBUG.EXE, it creates a file named AIDEBUG.TXT ("AI DEBUG") in the JA2 program files folder. For some reason it remains empty of text when I play the game. Any reason why?

(some meat that help to answer):
I manually added some text to the AIDEBUG.TXT file and that file was removed (probably by the InitAI method, partially shown below)

I guess this means that "#ifdef JA2TESTVERSION" (from InitAI) is true but "#ifdef DEBUGDECISIONS" (from DecideAction) isnt. I'll dig a bit further to understand what #ifdef means...


here's the code for the DebugAI method, which is called a lot by the DecideAction, but only if "#ifdef DEBUGDECISIONS" is true... any idea how to set it on?
void DebugAI( STR szOutput )
{
#ifdef DEBUGDECISIONS
	// Send regular debug msg AND AI debug message
	FILE *		DebugFile;

	DebugMsg( TOPIC_JA2, DBG_LEVEL_3, szOutput );
	if ((DebugFile = fopen( "aidebug.txt", "a+t" )) != NULL)
	{
		fputs( szOutput, DebugFile );
		fputs( "
", DebugFile );
		fclose( DebugFile );
	}
	else {ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Debug: AIDEBUG.TXT = NULL" );}  // SIMON
#endif
}

Here's the beginning of the InitAI method:

BOOLEAN InitAI( void )
{
#ifdef JA2TESTVERSION
	FILE *		DebugFile;
#endif

#ifdef _DEBUG
	if (gfDisplayCoverValues)
	{
		//memset( gsCoverValue, 0x7F, sizeof( INT16 ) * WORLD_MAX );
	}
#endif

	//If we are not loading a saved game ( if we are, this has already been called )
	if( !( gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) )
	{
		//init the panic system
		InitPanicSystem();
	}

#ifdef JA2TESTVERSION
	// Clear the AI debug txt file to prevent it from getting huge
	if ((DebugFile = fopen( "aidebug.txt", "w" )) != NULL)
	{
		fputs( "
", DebugFile );
		fclose( DebugFile );
	}
#endif



some code in the DecideAction method:
#ifdef DEBUGDECISIONS
	sprintf( tempstr,"DecideAction: selected action %d, actionData %d

",bAction,pSoldier->aiData.usActionData);
	DebugAI( tempstr );
#endif

[Updated on: Wed, 23 February 2011 21:23] by Moderator

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274361] Wed, 23 February 2011 21:27 Go to previous messageGo to next message
JMich is currently offline JMich

 
Messages:546
Registered:January 2011
Location: Greece
the part that says
#Ifdef DEBUGDECISIONS
is false, so anything between that and #endif will not be processed. You will have to
#define DEBUGDECISIONS = 1
for any debugdecisions blocks to be processed.

Also, the Tactical AI is quite complex, and you will see that it is being referenced in many places. In DecideAction.cpp we have 4 routines to decide what action the unit (and it is unit, wheter civilian, monster, bloodcat, soldier or in some cases pcs), 1 for each of the alert status (stati?).

For the part of "do this, and then do that", take a look at the function
INT8 DecideActionSchedule( SOLDIERTYPE * pSoldier )
in decideaction.cpp, the one for going through closed doors.

Since you are using VS, run the game by pressing F5, which is the debug mode of VS, and run the game in window. This will allow you to set breakpoints that will stop the execution when a breakpoint is reached, but before it's calculated. For example, if you set a breakpoint at
INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
the execution will stop once the function is to be called, which will allow you to see the value of
SOLDIERTYPE *pSoldier
and if you want to see what this soldier will do, you can set more breakpoints.

P.S. in VS, if you hover your mouse over any declarations, it will tell you its definition and whether it has a value defined or not.
P.P.S. I usually lurk in irc if you think I can help you more, but I am not yet that confident of my ability to understand code.

Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #274362] Wed, 23 February 2011 21:32 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
think I found it
simply un-comment
//#define DEBUGDECISIONS
in the file BuildDefines.h

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274363] Wed, 23 February 2011 21:42 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
JMich
.

Great stuff- thanks

By the way, I tried uncommenting #define DEBUGDECISIONS like I said in my previous post, and now I get these errors when compiling.
Bugger.

>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(146): error C2065: 'sGridno' : undeclared identifier
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(344): error C2664: 'sprintf' : cannot convert parameter 1 from 'STR16' to 'char *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(345): error C3861: 'AIPopMessage': identifier not found
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(434): error C2664: 'sprintf' : cannot convert parameter 1 from 'STR16' to 'char *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(435): error C3861: 'AIPopMessage': identifier not found
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(498): error C2664: 'sprintf' : cannot convert parameter 1 from 'STR16' to 'char *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(499): error C3861: 'AIPopMessage': identifier not found
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(544): error C3861: 'AIPopMessage': identifier not found
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(591): error C3861: 'AINumMessage': identifier not found
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(601): error C3861: 'AINumMessage': identifier not found
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(617): error C3861: 'AINumMessage': identifier not found
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(618): error C3861: 'AINumMessage': identifier not found
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(755): error C2664: 'sprintf' : cannot convert parameter 1 from 'STR16' to 'char *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>d:\documents and settings\temp\desktop\downloadsvn\build\tacticalai\movement.cpp(756): error C3861: 'AIPopMessage': identifier not found
1>  Medical.cpp

[Updated on: Wed, 23 February 2011 21:48] by Moderator

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274364] Wed, 23 February 2011 21:57 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
Just to make my current objectives clear. At this stage, I'd be very happy if I could just get the following to work:

1) Decisions are written to aidebug.txt
2) Create a decision where the unit moves 1 square right then stop for the rest of the turn. If it cannot go right, then go left/north/south...
This would probably require using "Schedule" which I am very glad was mentionned above




edit: Also, is anyone aware oh how the "pSoldiers" are chosen? Are they simply played one after the other, always in the same order (say, by increasing ID#?)

edit2 : Running debugging mode using F5 doesnt work because
"\Build\ext\vfs\build\...... \lib\vs2010\debug\VFS.lib is an unrecognized or unsupported binary format"

[Updated on: Wed, 23 February 2011 22:42] by Moderator

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274380] Thu, 24 February 2011 01:22 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
hey all!

Again, working on the v1.13 code, only difference is that I: uncommented #define DEBUGDECISIONS in builddefine.h . It didnt compile, so I did the following

I tried the following solution:
1) replace AIPopMessage(str16) by DebugAI(str)
2) commenting out AINumMessage and AINameMessage

Now it compiles, but when I start or load a game it crashes.

Damn it



Original code (snipped from various .cpp files)
void DebugAI( STR szOutput )
{
#ifdef DEBUGDECISIONS
	// Send regular debug msg AND AI debug message
	FILE *		DebugFile;

	DebugMsg( TOPIC_JA2, DBG_LEVEL_3, szOutput );
	if ((DebugFile = fopen( "aidebug.txt", "a+t" )) != NULL)
	{
		fputs( szOutput, DebugFile );
		fputs( "
", DebugFile );
		fclose( DebugFile );
	}
	else {ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Debug: AIDEBUG.TXT = NULL" );}  // SIMON
#endif
}

void AIPopMessage ( STR16 str )
{
	DebugAI(str);
}

	#ifdef DEBUGDECISIONS
		STR16 tempstr;
	#endif

#ifdef DEBUGDECISIONS
sprintf(tempstr,"%s- GETTING CLOSER to PANIC TRIGGER at grid %d (Trigger at %d)",pSoldier->name ,pSoldier->aiData.usActionData,sPanicTriggerGridNo);
AIPopMessage(tempstr);							
#endif



This code gets an error where sprintf refuses to convert a STR16 string to CHAR.. or something to that effect. Could that simply because STR16 can't fit the whole text??

Anyway, I tried replacing STR16 by STR and skipping AIPopMessage (which takes a STR16 and outputs a STR to DebugAI) and it seems to work now...


#ifdef DEBUGDECISIONS
STR tempstr;
sprintf(tempstr,"%s- GETTING CLOSER to PANIC TRIGGER at grid %d (Trigger at %d)",pSoldier->name ,pSoldier->aiData.usActionData,sPanicTriggerGridNo);
DebugAI(tempstr);							
#endif



Thing is, I will need to replace this in a lot of the CPP files, so I want to get your input as to whether or not this will work...

Also, I get an error for the following method (located in AIUtils)"1>c:\svn_ja2\build\tacticalai\movement.cpp(595): error C3861: 'AINumMessage': identifier not found"

void AINumMessage(const STR8	str, INT32 num)
{
	STR tempstr;
	sprintf( tempstr,"%s %d", str, num);
	DebugAI(tempstr);
}

which is called in the following fashion in Movement.cpp :
#ifdef DEBUGDECISIONS
   AINumMessage("Found a spot!	ubDirection = ",ubDirection + 1);
#endif




[Updated on: Thu, 24 February 2011 04:20] by Moderator

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274485] Thu, 24 February 2011 23:27 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
Almost there! Just the one error left and it should be an easy one.
This codes:

--

#ifdef DEBUGDECISIONS
STR tempstr;
sprintf(tempstr, "%d CONTINUES MOVEMENT to gridno %d... ", pSoldier->ubID,sGridNo );
DebugAI( tempstr );
#endif

Gives me the following error (line 149 is the sprintf line)

>c:\svn_ja2\build\tacticalai\movement.cpp(149): warning C4700: uninitialized local variable 'tempstr' used

I just initialized the damn variable!
any idea?

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274486] Thu, 24 February 2011 23:41 Go to previous messageGo to next message
JMich is currently offline JMich

 
Messages:546
Registered:January 2011
Location: Greece
to get F5 (Start Debugging) to work in VS2010, right click on project ja2, click properties, and then select Configuration Properties->General. The first field is called "Output Directory", which is where the executable will be built. Set this to your JA2 testing directory, for example "C:\JA2\Debug build\".
Then go to Configuration Properties->Debugging and set the "Working Directory" to the directory you set before. These 2 directories mean that any time you build your solution, you will built it in the directory it should go (instead of copying it afterwards) and you can also use F5 (Start Debugging) to run your build, whether it's a debug build or not. Do this with a version you can compile (eg svn version without any changes) and it should work. It is possible that I forgot a change, if so I will look at it again tomorrow, after I have managed to sleep.

I am also trying to see what needs to be changed so the code can compile with Define Debugdecisions but it is quite a mess, will update if I manage to compile it.

Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #274489] Fri, 25 February 2011 00:07 Go to previous messageGo to next message
tais

 
Messages:656
Registered:February 2008
Location: NL
MorgluM
Almost there! Just the one error left and it should be an easy one.
This codes:

--

#ifdef DEBUGDECISIONS
STR tempstr;
sprintf(tempstr, "%d CONTINUES MOVEMENT to gridno %d... ", pSoldier->ubID,sGridNo );
DebugAI( tempstr );
#endif

Gives me the following error (line 149 is the sprintf line)

>c:\svn_ja2\build\tacticalai\movement.cpp(149): warning C4700: uninitialized local variable 'tempstr' used

I just initialized the damn variable!
any idea?


Well as far as I can see you're only declaring the variable, not initializing it..
On the other hand it should work this way.. how about you change it in STR tempstr = ""; ?

[Updated on: Fri, 25 February 2011 00:07] by Moderator

Report message to a moderator

First Sergeant

Re: Learning how the AI works[message #274502] Fri, 25 February 2011 06:02 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
JMich
to get F5 (Start Debugging) to work in VS2010, right click on project ja2, click properties, and then select Configuration Properties->General. The first field is called "Output Directory", which is where the executable will be built. Set this to your JA2 testing directory, for example "C:\JA2\Debug build\".
Then go to Configuration Properties->Debugging and set the "Working Directory" to the directory you set before. These 2 directories mean that any time you build your solution, you will built it in the directory it should go (instead of copying it afterwards) and you can also use F5 (Start Debugging) to run your build, whether it's a debug build or not. Do this with a version you can compile (eg svn version without any changes) and it should work. It is possible that I forgot a change, if so I will look at it again tomorrow, after I have managed to sleep.

I am also trying to see what needs to be changed so the code can compile with Define Debugdecisions but it is quite a mess, will update if I manage to compile it.


Re: starting debbugging.
Thanks for the tip, here's how I was doing so far:
1) I copied the .PDB , the .ILK and the .EXE files that compiled to my JA2 folder
2) Run JA2 in windowed mode. To do that, edit JA2.INI and set windowed to =1
3) In VS2010, Debug-->Attach process, then look at the output from "Debug".


Re:Compiling with Define DebugDecisions, I found the following things:

1) Do I need to replace all the "STR16 tempstr;" lines by "STR tempstr;" lines in all the .cpp files?
2) I added the following 3 lines to AI.h:
void AIPopMessage ( STR str );
void AINumMessage(const STR	str, INT num);
void AINameMessage(SOLDIERTYPE * pSoldier,const STR8	str,INT32 num);

3) In AIUtils, I replaced the input of AIPopMessage, AINumMessage and AINameMessage from "STR16 str" to "STR str".
4) I forgot which CPP file, but one of the call has a type and asks for "sGridno" (type instead of "sGridNo")
5) In CreatureDecideAction, one of the "AINumMessage" wants to refer to "sClosestFriend" which doesnt exist...

Now I compile, but with warnings.
JA2 will crash when in the tactical screen, because tempstr isnt initialized...

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274504] Fri, 25 February 2011 06:09 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
Tais
STR tempstr = ""; ?

warning is gone.. thanks!

Now I get the following errors when going to the tactical screen:

First-chance exception at 0x010fe72e in JA2_EN_Debug.exe: 0xC0000005: Access violation writing location 0x0119ff46.
Unhandled exception at 0x010fe72e in JA2_EN_Debug.exe: 0xC0000005: Access violation writing location 0x0119ff46.

one in output.c, the other in sprintf.c
This will have to go on the back burner for a while, just thought I'd report on my "progress"

thanks everyone for helping.

[Updated on: Fri, 25 February 2011 06:15] by Moderator

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #274511] Fri, 25 February 2011 09:05 Go to previous messageGo to next message
JMich is currently offline JMich

 
Messages:546
Registered:January 2011
Location: Greece
CreatureDecideAction.cpp 774
Change
pSoldier->name,sClosestFriend,pSoldier->aiData.usActionData);
to
pSoldier->name,pSoldier->aiData.sCallerGridNo,pSoldier->aiData.usActionData);
since the closest friend is actually the one that is calling the soldier.
Now, for the
cannot covnert parameter 1 from str to char *
sprintf(char *, format, parameter value) requires a character array to insert the text, but the tempstr (or whatever else is used) is a string type, thus it cannot be used. The possibilities are either to use a char array for sprintf and then convert it to str, or have the DebugAI and the AI___Message routines use a char array. Not sure how to do either of these things.

P.S.1 I found it easier to change the AIPopMessage routine to
void AIPopMessage ( STR16 str )
{
	STR tempstr;
	sprintf( tempstr, "%s", str);
	DebugAI(tempstr);
}


P.S.2 Reviewing the above piece of code, it seems that sprintf can take a string type as output, but only if using string type as input? no idea exactly what's going on.

P.S.3 Anyone has any idea what the ExtMen is, as it's an undefined identifier, used for example in CreatureDecideAction.cpp, line 1360 (or thereabout). It appears to be a struct, but no idea of what/why/where.

Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #274796] Tue, 01 March 2011 20:08 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
cheers for this !

-I'm off for a biking trip in Cuba... back in April!

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #275347] Tue, 08 March 2011 17:26 Go to previous messageGo to next message
Buns is currently offline Buns

 
Messages:655
Registered:September 2010
From observing the AI, including milita, a bit more closer, and without looking into the code, I think I can name some major problems in its behaviour:

Investigating Sounds
The AI is drilled to investigate suspicious sounds. That makes sense when you sneek into a facility at night, but doesn't make much sense in a shoot-out at daylight. The main problems comes from soldiers not being able to differentiate between an unidentified sound (movement, you throwing a rock) and a shot.

While the first one indeed should trigger a "soldier comes looking"-behaviour, the second one would mean a "contact" that should trigger a different behaviour. The AI is able to identify the tile the sound originated from. This means in case of a shot the AI would be able to identify the tile where an opponent would be sitting and should be acting accordingly.

Latest Sound Rules
It seems the AI only reacts to the latest sound, when having heard a couple of them. When you have several mercs placed all over the map, the AI during its turn will approach the last one of them who had been shooting during your turn. In case another mercs gets an interrupt and shoots, all soldiers with APs left will change direction and move to that tile.

It would make more sense if the AI would be able to "remember" all shots you had fired during your turn, and then each soldier would approach the closest of those contacts assuming an opponent who had just been shooting out of a tile to still be there.

We are no Borg
It doesn't seem that all soldiers are able to see what one soldier sees. Even when one AI soldier has visible contact to an opponent others behave as if they don't know the opponent is there. A typical example is when one soldier is shooting at an opponent from the corner of a building, and a second soldier is around the corner without seeing the opponent. That second soldier during his turn will round the corner, run past his comrad (to investigate the sound he heard, of course), then he sees the opponent and tries to get back to the corner.

This dramatically dumbs down the AI; just imagine one of your mercs would see an enemy but you would be moving the others as if you wouldn't know of that enemy! No chance. When calculating orders and pathfinding during the AI turn, all opponents sighted by that side should be taken into account.

No Blind Shooting
I had once claimed that the AI never is shooting blindly (means on "greyed out enemies"). This is not correct: I had closely observed this during my ongoing campaign and there indeed had been two occasions (in 35 battles!) when the AI had been shooting "surpressive fire" - once of that on my vehicles. OK, in my mod most enemies are armed with bolt-action or semi-automatic rifles, but in larger armies there are usually four or five with SMGs and two or three with LMGs. And there also is no reason to limit blind shooting to autofire.

This basically is the same problem as described above: the AI should take all sightings of that side into account when creating orders for a soldiers. If there is a sighting within range, and the soldier is in a suitable position he might start shooting, even when not having visible contact himself. This would also solve the scope-problem: when the soldier has a scope on his rifle he would then see the enemy while raising the weapon for blind-shooting.

Randomized Movement
It seems large parts of AI movement is by random. You can see it very clearly with militia in tactical combat, because it shows you all their movements, not only that of the ones you see yourself, and not only those that are somewhat involved into combat.

For example, you have militias that move couched despite being far away from anything dangerous, others suddenly get up and start walking around even though in line of fire of the enemy. Most notably is the "running of 8s", which can happen within range of the enemy, but also far away from the frontline. It seems this random behaviour can kick in anytime an AI enters a tile, which can result in the AI wasting all APs for running fore and back between two tiles indentically in coverage and line of fire.

When you have your next defensive battle with militias, just leave the last three or so enemies to them and don't shoot them yourself. You would be surprised how long it can take for 32 militias to kill 3 enemies they know of. After that you wouldn't be surprised why the AI usually has no chance of killing one of your mercs with 32 soldiers.

Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #275355] Tue, 08 March 2011 17:47 Go to previous messageGo to next message
JMich is currently offline JMich

 
Messages:546
Registered:January 2011
Location: Greece
	// THE FOUR (4) POSSIBLE ALERT STATUSES ARE:
	// GREEN - No one seen, no suspicious noise heard, go about regular duties
	// YELLOW - Suspicious noise was heard personally or radioed in by buddy
	// RED - Either saw opponents in person, or definite contact had been radioed
	// BLACK - Currently has one or more opponents in sight
How the AI reacts depends on what state the soldier is currently in. If the soldier is on green and hears a noise, he will (usually) move to investigate, if he is on yellow he has a chance (25% to 65%, depending on orders and attitude) of radioing the noise, if on red he will turn towards the noise and go prone. There is also the "Most Important Noise", which I'm not sure if it's the closest, or the loudest, or if it can tell the difference between a footstep, an explosion, a scream and a shot.

On the borg mentality, there is a chance (again depending on orders and attitudes) that if the soldier knows some enemy positions that his allies do not, he will radio the contact, but how often do we let the enemy enough time to radio in? Usually, only if there are 5+ soldiers, and we cannot kill them all in 1 turn. Same thing also explains the suppression and blind shooting (or lack of).

Finally, the movement mode of the soldiers depends once again on orders and attitude, a cunning soldier for example is more propable to move crouched than an aggressive one. Also, whenever the situation changes (enemy sighted, noise heard, better cover in view), the merc (pc/militia/soldier/civilian) has to reevaluate his/her options, and decide again whether he/she should continue or do something else. This is the reason for the back and forth, since the soldier moves around the corner, sees your pc and has no cover. Best cover is behind the corner, so he/she moves back to cover. Next turn, the soldier again has an idea of where your merc is, but no definite answer, so if he/she goes to look, the same thing will happen.

Hope this helps clarify a few things, and I will suggest you take a look at the code as well, the comments make it easy enough to understand.

Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #275367] Tue, 08 March 2011 19:39 Go to previous messageGo to next message
Buns is currently offline Buns

 
Messages:655
Registered:September 2010
Quote:
Hope this helps clarify a few things, and I will suggest you take a look at the code as well, the comments make it easy enough to understand.
You are of course right, I should have looked into the code before posting, but ATM I don't have the intention to start coding the tactical AI myself, and wished to limit myself to experiences what actually happens in battle.


JMich
How the AI reacts depends on what state the soldier is currently in. If the soldier is on green and hears a noise, he will (usually) move to investigate, if he is on yellow he has a chance (25% to 65%, depending on orders and attitude) of radioing the noise, if on red he will turn towards the noise and go prone. There is also the "Most Important Noise", which I'm not sure if it's the closest, or the loudest, or if it can tell the difference between a footstep, an explosion, a scream and a shot.
This includes some problematic things, I think:

- The AI being required to radio doesn't do it any good: the soldier can either radio or fight (If I see that right radioing costs a lot of APs; at least both enemies and militia often don't do much else than going couched after radioing).

This is a classical dilemma, because whatever he does is wrong. When he radios he can't do anything about the enemies in his sight. So he will be shot the next turn, and whether the guys he radioed will do anything better out of the situation is another question - not to mention that the mercs probably will move on after killing that poor fellow.

When he decides to fight instead he might be able to pin you down, but unless it is a 1:1 situation or other soldiers by chance are close enough to help, he would be left alone and easy prey for your cooperativly working team.

Apart from that, the animation of radioing goes on my nerves.

So this is something I would suggest to skip: When one enemy sees you, all would know of your position (100%). You would either need to shoot him (in this case the enemy would be blind again) or move out of his sight.


Giving the enemy a certain % of what to do next is problematic too: it is difficult to define a suitable behaviour in each situation for the AI at all. Saying that in between 35% to 75% of all cases he wouldn't do even that, do something else or nothing at all means that besides the JA2 enemies already already are dumb AI, they are even coded to behave extra stupied/wrong.



Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #275369] Tue, 08 March 2011 20:13 Go to previous messageGo to next message
JMich is currently offline JMich

 
Messages:546
Registered:January 2011
Location: Greece
Buns
So this is something I would suggest to skip: When one enemy sees you, all would know of your position (100%). You would either need to shoot him (in this case the enemy would be blind again) or move out of his sight.
If when any soldier sees you, all have seen you, that means that all raise their alarm level, and sneaking is harder (if not impossible) to do. Think of what would happen in Alma, you kill the first soldier, and since he has seen you, panic button is pushed, and Sergeant Krott is killed. You have to kill the enemy quietly and without letting him notify to be able to save him and get the Rocket Rifle.Buns
Giving the enemy a certain % of what to do next is problematic too: it is difficult to define a suitable behaviour in each situation for the AI at all. Saying that in between 35% to 75% of all cases he wouldn't do even that, do something else or nothing at all means that besides the JA2 enemies already already are dumb AI, they are even coded to behave extra stupied/wrong.
If soldier.orders->Guard OR soldier.orders->Stationary
then chance = 50
else chance = 25
If soldier.attitude.defensive chance = chance + 15
If random(100) < chance
then radio
else investigate


P.S. the reason I mention the code is because it is easy to read, and usually understand, even though one may not know C++. I haven't used C in more than 8 years, and the only usage I did was an introductory university course, but I still find the code easy to follow. And after all, the more people reading the code, the more people making suggestions to the code.

Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #275408] Wed, 09 March 2011 14:51 Go to previous messageGo to next message
Buns is currently offline Buns

 
Messages:655
Registered:September 2010
JMich
If when any soldier sees you, all have seen you, that means that all raise their alarm level, and sneaking is harder (if not impossible) to do. Think of what would happen in Alma, you kill the first soldier, and since he has seen you, panic button is pushed, and Sergeant Krott is killed.
This would apply when the soldier sees me during his turn:

(a)
My turn: Soldiers sees me, I see soldier. Soldier gets killed (silenced).
Next AI turn: No more soldier sees me, no alarm, all stay on green alert status

(b)
My turn: Soldiers sees me, I see soldier. Soldier not is killed (missed shot).
Next AI turn: Soldier still sees me; now all enemies know of the position of that merc. They would switch to red alert status and start approaching my position. One will blow up Sergeant Krott.

(c)
My turn: Soldiers sees me, I see soldier. Soldier is killed silenced but had been able to shoot himself before.
Next AI turn: No more soldier sees me, but a shot by a friend had been heard. This would set the others to yellow alert status with the result that they would come looking. Sergeant Krott may live on, for now.

(d)
My turn: Soldiers sees me, I see soldier. Soldier is killed by an unsurpressed shot.
Next AI turn: No more soldier sees me, but a shot by an enemy had been heard. This would set them to red alert and make them approach the concact. Sergeant Krott is blown up.


So removing the need to radio contacts would not make it impossible to sneak into Alma unnoticed, even when an enemy has seen you. You only have to make sure he doesn't survive your turn, and that no one hears you killing him. It's basically as difficult, or easy, as it is now.


But you see it yourself: the major problem is that the AI is coded with keeping in mind to make those special situations possible. This is fine for all those that do nothing but sneaking around at night. All others rather have a WTF?-experience in battle.


Another example: I just had a monster battle with lots of mercs and masses of enemies. The battlefield was stretching from the NW corner of the map to about the center with the enemy getting reinforcements all the time.

On the very western edge of the map six of my mercs had a shootout with a good dozend of enemies; both sides sitting behind rocks. This means the enemy had visible contact to those mercs, was behind suitable cover, and in a position the AI found acceptable for shooting with the weapons it had. This went on for several turns.

In the center two other squads were fighting it out with other enemies. One of these two squads managed to move around the SE flank of those enemies and opened fire at the south-easternmost enemies. The next thing that happened was that the enemies in the NW, those behind the rocks (in range of their opponents, and with visible contact) suddenly all got up and started walking to the SE. Needless to say that none survived the next turn.

A typical example how the AI primarly tries to do investigate new sounds, even when already involved in combat with opponents much closer than any new sound.

Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #275413] Wed, 09 March 2011 16:05 Go to previous messageGo to next message
JMich is currently offline JMich

 
Messages:546
Registered:January 2011
Location: Greece
Intersting thing, though not certain about this.
An opponent in condition black (currently has one or more opponents in view) will not go looking for new enemies, but will turn towards the closest one. So the condition you encountered propably means that (due to cover? distance? other factors?) they couldn't see your merc, however they shouldn't have lost track of your mercs. However the AI does require quite some time to be able to understand what they do, and why.

Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #275417] Wed, 09 March 2011 17:34 Go to previous messageGo to next message
Buns is currently offline Buns

 
Messages:655
Registered:September 2010
JMich
However the AI does require quite some time to be able to understand what they do, and why.
That's for sure. I was more or less throwing around ideas what could be done about the AI and what seems to be going wrong (in game); last but not least to keep this important discussion going.

The final goal would be to have the AI acting as reasonable as the player moves his mercs. This does not mean that I would consider it possible having any refined tactics working for the enemy, but that the AI shows a more reasonable reaction to contacts.


From my gaming experience I would consider the following things either as not covered by the code, or not properly working/broken, or being given the wrong priority:

- The "lemming-behaviour", i.e. soldiers neatly moving one by one on a tile where they will be shot.
- The inability to give closer contacts a higher priority.
- The requirement to establish personal visual contact to (already known) enemies in order to shoot or move into a proper position
- The "self-pinning", means going prone when being shot at and remain in that position even when not being able to return fire and being on a tile with no coverage
- The usage of wrong stances/movings as a result of randomization and/or pre-defined attitude
- The "forming of unions", means the gathering around certain (pointless) tiles in large numbers
- The direct rushing to a tile where opponents had been shooting from, instead of moving to a tile from where they could open fire on the suspected opponent.
- The waisting of APs for pointless, often looping, movement.


Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #276212] Sun, 20 March 2011 14:57 Go to previous messageGo to next message
SharkD is currently offline SharkD

 
Messages:351
Registered:July 2003
I suppose a heavily-scripted demo mission might be a nice feature to sort of walk you through all this stuff...

I.e., have a "narrator" that sort of walks you through the mission and explains why that soldier couldn't hit the target standing 50m in front of him, or why the sneak move was unsuccessful despite being in full cover.


(Of course, doing this on YouTube instead could accomplish the same thing...)

Report message to a moderator

Master Sergeant
Re: Learning how the AI works[message #276214] Sun, 20 March 2011 15:19 Go to previous messageGo to next message
Buns is currently offline Buns

 
Messages:655
Registered:September 2010
Are you sure you are in the right thread?

Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #276322] Tue, 22 March 2011 03:08 Go to previous messageGo to next message
SharkD is currently offline SharkD

 
Messages:351
Registered:July 2003
Yes, but I'm not sure the idea is even any good! Smile

Report message to a moderator

Master Sergeant
Re: Learning how the AI works[message #276383] Tue, 22 March 2011 14:53 Go to previous messageGo to next message
Buns is currently offline Buns

 
Messages:655
Registered:September 2010
I have no definite oppinion on that, but it most likely will not help us in improving the tactical AI, that's for sure.

Report message to a moderator

First Sergeant
Re: Learning how the AI works[message #277357] Wed, 06 April 2011 01:45 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
I'm back!

JMich, dude you manage to get the DebugAI working by any chance?

I'm slowly returning to this grind Smile

Report message to a moderator

Private 1st Class
Re: Learning how the AI works[message #277368] Wed, 06 April 2011 10:39 Go to previous messageGo to next message
JMich is currently offline JMich

 
Messages:546
Registered:January 2011
Location: Greece
Welcome back MorgluM
Unfortunately, work and a few other projects kept me occupied, especially since I do doubt that I would use the DebugAI for debugging.
So far, it seems to me much better to use VS's debugger, especially since it does allow to change values on the fly, and thus test a bit better the AI routines. Also, while I do know how to read and modify code, I doubt I am able to understand why the DebugAI routines do not work Sad.
I do hope you will make more sense out of the AI code than I currently do, and should you want to chat a bit more, do pop over to the IRC channel. Remember though that I am a european living at GMT +2, so don't be surprised if I'm not responding.

Report message to a moderator

First Sergeant
Semi-Success , and question re: working directory[message #277418] Thu, 07 April 2011 15:26 Go to previous messageGo to next message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
1: Semi-Success
I managed to get JA2 to compile and run (for some time) with DEBUGDECISIONS. It posts the AI decision in aidebug.txt (most important noise heard at grid #XX, soldier #XX moving to gridno YY, Soldier ZZ offering to surrender etc...) and works fine, until, I believe, the AI tries to attack. Then, it crashes somewhere in output.c (a file related to the sprintf function, which is used to create the string that is printed to the aidebug.txt file).
Basically, I started definining tempstr as char tempstr [250]="";


2: I can't link VS2010 to JA2 the way JMich described here:
JMich
to get F5 (Start Debugging) to work in VS2010, right click on project ja2, click properties, and then select Configuration Properties->General. The first field is called "Output Directory", which is where the executable will be built. Set this to your JA2 testing directory, for example "C:\JA2\Debug build\".
Then go to Configuration Properties->Debugging and set the "Working Directory" to the directory you set before. These 2 directories mean that any time you build your solution, you will built it in the directory it should go (instead of copying it afterwards) and you can also use F5 (Start Debugging) to run your build, whether it's a debug build or not.


Here is what I see when I go to the properties of the JA2 project. Nothing for "General":
Selecting Properties of the project
No "General" tab
However, when I select the properties of a part of the project, say TacticalAI, then I can see General/Working directory:
TacticalAI properties has a general tab

Any tip would be greatly appreciated

[Updated on: Thu, 07 April 2011 15:27] by Moderator

Report message to a moderator

Private 1st Class
Re: Semi-Success , and question re: working directory[message #277425] Thu, 07 April 2011 16:29 Go to previous messageGo to next message
JMich is currently offline JMich

 
Messages:546
Registered:January 2011
Location: Greece
MorgluM

2: I can't link VS2010 to JA2 the way JMich described here:
JMich
to get F5 (Start Debugging) to work in VS2010, right click on project ja2, click properties, and then select Configuration Properties->General. The first field is called "Output Directory", which is where the executable will be built. Set this to your JA2 testing directory, for example "C:\JA2\Debug build\".
Then go to Configuration Properties->Debugging and set the "Working Directory" to the directory you set before. These 2 directories mean that any time you build your solution, you will built it in the directory it should go (instead of copying it afterwards) and you can also use F5 (Start Debugging) to run your build, whether it's a debug build or not.


Here is what I see when I go to the properties of the JA2 project. Nothing for "General":
Selecting Properties of the project
No "General" tab
However, when I select the properties of a part of the project, say TacticalAI, then I can see General/Working directory:
TacticalAI properties has a general tab

Any tip would be greatly appreciated
You are right-clicking on Solution JA2, not project JA2. You will also have to set JA2 project as the one to start when debugging.
See here

Report message to a moderator

First Sergeant
Re: Semi-Success , and question re: working directory[message #277479] Fri, 08 April 2011 00:46 Go to previous messageGo to previous message
MorgluM is currently offline MorgluM

 
Messages:24
Registered:March 2004
Location: Qu
thanks --
we'll see if that works. Surprised)

Also, I have an error that's been plaguing me for a while when compiling (this is without changing anything). The .EXE does work.


>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppBuild.targets(992,5): warning MSB8012: TargetName(JA2_EN_Debug.exe) does not match the Linker's OutputFile property value (JA2_EN_Debug). This may cause your project to build incorrectly. To correct this, please make sure that $(OutDir), $(TargetName) and $(TargetExt) property values match the value specified in %(Link.OutputFile).

Report message to a moderator

Private 1st Class
Previous Topic: Doubling image size
Next Topic: RII - Resolution Independent Interface [UPDATE :RII v4f]
Goto Forum:
  


Current Time: Mon Feb 10 20:28:10 GMT+2 2025

Total time taken to generate the page: 0.04219 seconds