AI : Brainstorming

Development directions, tasks, and features being actively implemented or pursued by the development team.
Post Reply
ezee
Intrepid Venturer
Intrepid Venturer
Posts: 703
Joined: Tue Feb 11, 2014 12:47 am
Location: FRANCE
Contact:

AI : Brainstorming

Post by ezee »

Hi .

AI is a subject that passionate me , and it is also a very important part of any video game .
In more than one thread , for different subjects , the case of AI is exposed , alongside of GameLogic .

As we make and play a space shooter ( with sim elements :wink: ) , it's natural to have
an AI able to pilot and fight , follow a path etc ...
That is done actually , implemented in c++ and translated in python :
typedef PythonAI< FireAt >PythonAIFireAt;
PYTHON_BEGIN_INHERIT_CLASS( VS, PythonAIFireAt, FireAt, "PythonAI" )
PYTHON_DEFINE_METHOD_DEFAULT( Class, &FireAt::Execute, "Execute", PythonAI< FireAt >::default_Execute );
PYTHON_DEFINE_METHOD_DEFAULT( Class, &FireAt::ChooseTarget, "ChooseTarget", PythonAI< FireAt >::default_ChooseTarget );
PYTHON_DEFINE_METHOD_DEFAULT( Class, &FireAt::SetParent, "init", PythonAI< FireAt >::default_SetParent );
PYTHON_DEFINE_METHOD( Class, &FireAt::GetParent, "GetParent" );
PYTHON_DEFINE_METHOD( Class, &FireAt::AddReplaceLastOrder, "AddReplaceLastOrder" );
PYTHON_DEFINE_METHOD( Class, &FireAt::ExecuteLastScriptFor, "ExecuteLastScriptFor" );
PYTHON_DEFINE_METHOD( Class, &FireAt::FaceTarget, "FaceTarget" );
PYTHON_DEFINE_METHOD( Class, &FireAt::FaceTargetITTS, "FaceTargetITTS" );
PYTHON_DEFINE_METHOD( Class, &FireAt::MatchLinearVelocity, "MatchLinearVelocity" );
PYTHON_DEFINE_METHOD( Class, &FireAt::MatchAngularVelocity, "MatchAngularVelocity" );
PYTHON_DEFINE_METHOD( Class, &FireAt::ChangeHeading, "ChangeHeading" );
PYTHON_DEFINE_METHOD( Class, &FireAt::ChangeLocalDirection, "ChangeLocalDirection" );
PYTHON_DEFINE_METHOD( Class, &FireAt::MoveTo, "MoveTo" );
PYTHON_DEFINE_METHOD( Class, &FireAt::MatchVelocity, "MatchVelocity" );
PYTHON_DEFINE_METHOD( Class, &FireAt::Cloak, "Cloak" );
PYTHON_DEFINE_METHOD( Class, &FireAt::FormUp, "FormUp" );
PYTHON_DEFINE_METHOD( Class, &FireAt::FormUpToOwner, "FormUpToOwner" );
PYTHON_DEFINE_METHOD( Class, &FireAt::FaceDirection, "FaceDirection" );
PYTHON_DEFINE_METHOD( Class, &FireAt::XMLScript, "XMLScript" );
PYTHON_DEFINE_METHOD( Class, &FireAt::LastPythonScript, "LastPythonScript" );
PYTHON_END_CLASS( VS, FireAt )
The previous list was shown to argument for this idea that AI could ( and should ) be
extended to other categories than FIGHT .

I remember numerous threads were the economical part of the game introduced a specialized gameLogic , probably done through the AI class .

As Klauss is working on the build of TRADE LANES , i think that this is an occasion
to talk about AI for that .
That rely on how the systems are populated , and what the AI is able to do by itself .

The Gamelogic and the Gameplay are certainly the two big components that an AI system
has to deal with .

The GameLogic what is it ?

Perhaps the compound and the result of all the events that occur in the main loop of a game .
In Vegastrike : Explore solar systems , earn money with battle missions , upgrade our ship , try to stay alive and have fun . ( in short )
The GameLogic core is how the program is oriented to achieve that Gameplay .
Today , the Game Logic is scripted , for the most part in python .

What is an AI ?
AI stands for Artificial Intelligence .
Artificial , but limited by what ?
Limited by the number of BEHAVIORS , SENSORS , ACTIONS .
AI could also be considered as a GameLogic Agent , like it's the case today :

You go to the base's computer , choose a mission , take a beer and jump in your cockpit.
You expect a certain action , in this GAMEPLAY .
The GAMELOGIC will launch in the background a flightgroup , to produce content for this specific gameplay .

So what ?

I think that AI could be more than GameLogic Agents , and that they could be themselves
the GameLogic .

Someone in the wiki said that the NPCs and the AI in general should have a homeland each one .
I think this is the first step in favor of the independance day's of the AI agents .
_ Give them a location in time and space .
_ Give them behaviors in that time and space ( QUIET , AGRESSIVE , CURIOUS , MAD ...)
_ Give them sensors to understand geographical , astronomical , economical , cultural and political events .
_Give them Actions to create or answer to events
_Give them a technology/industry to produce tools .

And watch what will happen ?
( with tools build vessels , with vessels explore , with explore encounter , with encounter
make peace or war )
I would be happy to develop with you this idea .

My first question is :
_ Will we have to code new C++ code or what we already have with python will be sufficient ?

edit : In wiki , Development:Political system , i've found a source of details that could
serve in a political behavior tree http://wiki.vega-strike.org/Development ... cal_system

Code: Select all

 if (!track.HasWeapons())
            {
                // So what are you going to threaten me with? Exhaustion gas?
                return ThreatLevel::None;
            }
Vegastrike evolved
DEV YOUTUBE CHANNEL
Vegastrike evolved wiki
ezee
Intrepid Venturer
Intrepid Venturer
Posts: 703
Joined: Tue Feb 11, 2014 12:47 am
Location: FRANCE
Contact:

Re: AI : Brainstorming

Post by ezee »

I was introducing the Behavior tree as a way to structure the AI Logic .
But Behavior tree is not the only way to code an efficient AI .
There is also Finite State Machine . ( FSM )
What is a State?
A finite state machine is based on the concept of a state, which typically consists of two things:

A set of actions running at the same time (e.g. playing an animation, a sound, or waiting for a certain amount of time).

A set of transitions with a conditional check to determine when to engage the next state.

States can be made quite generic and robust by adding many transitions to support all the desired cases. For simple problems, this is fine, but for large problems you need a more scalable approach.
src : http://aigamedev.com/open/article/fsm-reusable/

Vega-strike already use FSM with AI , that is the core of the communication and relationship between the factions and the players :
http://spacetechs.free.fr/VEGASTRIKEDEV ... f_s_m.html

So we have a working model , that i'm starting to study , to understand how it works
and see how it could be extended .
:)

But before that , let have a look in the scripting engine that AI is using now .

_ HARD CODED SCRIPTS

They are defined in script.cpp :
typedef vsUMap< string, CCScript* >HardCodedMap;
http://spacetechs.free.fr/VEGASTRIKEDEV ... tml#l00015
And stored as static :
static HardCodedMap hard_coded_scripts = MakeHardCodedScripts();
It's easy to understand what hard_coded_scripts is when we look in MakeHardCodedScripts()

Have a look :
static HardCodedMap MakeHardCodedScripts()
{
HardCodedMap tmp; --> our temp HardCodedMap to make
typedef std::pair< std::string, CCScript* >MyPair; -->Contains strings coupled to CCScript*
And now the insertion in the script buffer or the first pair
tmp.insert( MyPair( "loop around fast", &LoopAroundFast ) );
Right now , it is important to notice and remember what is a CCScript object :
typedef void CCScript (Order*script, Unit*un);
So a CCScript is a couple made of an Order and a Unit objects .

And yeah , if we want to implement new AI Script , we'll have to add new CCScript in
the existing suite :
CCScript AfterburnerSlide;
CCScript FlyStraight;
CCScript FlyStraightAfterburner;
CCScript Takeoff;
CCScript DoNothing;
CCScript TakeoffEveryZig;
CCScript AfterburnTurnTowards;
CCScript AfterburnTurnTowardsITTS;
CCScript CloakForScript;
CCScript MoveTo;
CCScript Kickstop;
CCScript MatchVelocity;
CCScript VeerAway;
CCScript VeerAwayITTS;
CCScript CoastToStop;
CCScript SelfDestruct;
CCScript VeerAndVectorAway;
CCScript AfterburnVeerAndVectorAway;
CCScript AfterburnVeerAndTurnAway;
CCScript SheltonSlide;
CCScript SkilledABSlide;
CCScript Stop;
CCScript TurnAway;
CCScript AfterburnTurnAway;
CCScript TurnTowardsITTS;
CCScript TurnTowards;
CCScript BarrelRoll;

CCScript LoopAround;
CCScript AggressiveLoopAround;
CCScript LoopAroundFast;
CCScript AggressiveLoopAroundFast;
CCScript LoopAroundSlow;
CCScript AggressiveLoopAroundSlow;
CCScript DropCargo;
CCScript DropOneCargo;
CCScript DropHalfCargo;
CCScript RollLeft;
CCScript RollRight;
CCScript RollLeftHard;
CCScript RollRightHard;
CCScript EvadeLeftRight;
CCScript EvadeUpDown;
CCScript AfterburnEvadeLeftRight;
CCScript AfterburnEvadeUpDown;
CCScript FacePerpendicularFast;
CCScript FacePerpendicular;
CCScript FacePerpendicularSlow;
CCScript RollFacePerpendicularFast;
CCScript RollFacePerpendicular;
CCScript RollFacePerpendicularSlow;
The name of the scripts let imagine that they are typically ACTIONS in the script engine.
And Actions attributed to a particular Unit .
Let have a look in Order.h to understand what it is :
/**
* Order is the base class for all orders. All orders inherit from Order
* Each fighter may have an order they are currently executing. Orders naturally
* can queue other orders, and decide which orders may be executed in parallel by those orders' bit codes.
* Orders affect their "parent" and may call any function within that parent
* Limitation (perhaps resolvable) Orders do not "know" what their parent
* is until Execute() time. Perhaps "SetParent" Should be made virtual so that
* various variables may be set earlier than at every execution time
*/

Code: Select all

 if (!track.HasWeapons())
            {
                // So what are you going to threaten me with? Exhaustion gas?
                return ThreatLevel::None;
            }
Vegastrike evolved
DEV YOUTUBE CHANNEL
Vegastrike evolved wiki
ezee
Intrepid Venturer
Intrepid Venturer
Posts: 703
Joined: Tue Feb 11, 2014 12:47 am
Location: FRANCE
Contact:

Re: AI : Brainstorming

Post by ezee »

:!: Now tha we have a basic idea of the scripting system , with hardcoded scripts , and
that we know the basic ORDER object , lets look what's next :

class AIScript : public Order
/**
* Loads a script from a given XML file
* FIXME: This data is not cached and is streamed
* from harddrive and expat'ed each time a script is loaded
*/
BAD for the FPS !! Read write ops are not threaded i guess , so they are micro-interruption in the loop ...
Instead of physical files , we could use memory files , and give to the AI the caps to
write these files , that is really dynamic ! :wink:
In that context , actual xml script files would be templates files for the AI .

OK , we have now a child class that inherit from Order .
And extent is functionalities to ... XML !
class AIScript : public Order
{
///File name the AI script takes, to be loaded upon first execute (needs ref to parent)
char *filename;
///Temporary data to hold while AI script loads
AIScriptXML*xml; --> introduced xml stuff
///Loads the XML file, filename when Execute() is called
void LoadXML(); //load the xml
///Internal functions to expat
static void beginElement( void *userData, const XML_Char *name, const XML_Char **atts );
///internal functions for use of expat
static void endElement( void *userData, const XML_Char *name );
///The top float on the current stack
float& topf();
///Rid of the top float on the current stack
void popf();
///The top vector on the current stack
QVector& topv();
///Pop the top vector of teh current stack
void popv();
///member function begin elements... deals with pushing vectors on stack
void beginElement( const string &name, const AttributeList &attributes );
///member function end elements...deals with calling AI scripts from the stack
void endElement( const string &name );
public:
///saves scriptname in the filename var
AIScript( const char *scriptname );
~AIScript();
///Loads the AI script from the hard drive, or executes if loaded
void Execute();
};
So how this class works ?

By a call to his constructor first :
AIScript( const char *scriptname )

then by using the LoadXML().

Right now , we can assume that we'll have to write new c++ code , because of the limited territory of the actual AIXml logic :
struct AIScriptXML
86 {
87 int unitlevel;
88 int acc;
89 vector< float >executefor;
90 bool itts;
91 bool afterburn;
92 bool terminate;
93 char lin;
94 QVector defaultvec;
95 float defaultf;
96 std::stack< QVector >vectors;
97 std::stack< float > floats;
98 std::vector< Order* >orders;
99 };
This struct was designed for AI ships , but not at all for trading , research , politics etc...
So we have two choices :

A_Extent this base struct ( not my favorite :wink: ).
B_Make one or more decicated structs ( my favorite ) .

And in the case of B , probably make a new dedicated AiScript class , derived again from
order class .

That could open the AI brain to a strategy level ( mix of politics and economics )
That new kind of AI could then give orders to standard AI ships :
BECAUSE THEY HAVE THE SAME PARENT ' ORDER ' CLASS .

This is the model i imagine , with the information i have collected .
An example of use could be with a base :
_ The computer mission is now entirely controled by AI .
The missions will be created by the AI , in response of his needs .
And no more by random choice in a list .
_ You ask for docking , but the station is full !
The AI give you patern instruction to wait for a free dock port .
_ The prices of the base's market are dynamic
_...

But lets explore further the actual AI system first .
:wink:

Code: Select all

 if (!track.HasWeapons())
            {
                // So what are you going to threaten me with? Exhaustion gas?
                return ThreatLevel::None;
            }
Vegastrike evolved
DEV YOUTUBE CHANNEL
Vegastrike evolved wiki
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Re: AI : Brainstorming

Post by klauss »

About "bad for FPS", check the source, but AFAIK all file-loaded stuff is cached, so it's loaded only once.

About the FSM, the current system is equivalent to a FSM, but it's not expressed as one, so it's harder to follow in comparison to a plainly specified FSM.

There's noone that really understands the AI scripts still active, AFAIK. I kinda tried to analyze them and got to the conclusion from above: it's an FSM, but not really, lets replace it with a real FSM. Nobody got to replacing it though.

Beyond that, your guess is as good as mine.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
ezee
Intrepid Venturer
Intrepid Venturer
Posts: 703
Joined: Tue Feb 11, 2014 12:47 am
Location: FRANCE
Contact:

Re: AI : Brainstorming

Post by ezee »

:D
Thank you Klauss .
I'm finishing my work with the ingame menu , and will be back for the AI soon .
:wink:

Code: Select all

 if (!track.HasWeapons())
            {
                // So what are you going to threaten me with? Exhaustion gas?
                return ThreatLevel::None;
            }
Vegastrike evolved
DEV YOUTUBE CHANNEL
Vegastrike evolved wiki
ezee
Intrepid Venturer
Intrepid Venturer
Posts: 703
Joined: Tue Feb 11, 2014 12:47 am
Location: FRANCE
Contact:

Re: AI : Brainstorming

Post by ezee »

About the FSM, the current system is equivalent to a FSM, but it's not expressed as one, so it's harder to follow in comparison to a plainly specified FSM.
I have found one of the real use of FSM in Vegastrike :
void CommunicatingAI::ProcessCommMessage( CommunicationMessage &c )
{
if ( messagequeue.back()->curstate < messagequeue.back()->fsm->GetUnDockNode() ) {
Order::ProcessCommMessage( c );
FSM *tmpfsm = c.fsm;
Unit *targ = c.sender.GetUnit();
if ( targ && UnitUtil::getUnitSystemFile( targ ) == UnitUtil::getUnitSystemFile( parent ) && !isDockedAtAll( targ ) ) {
c.fsm = FactionUtil::GetConversation( parent->faction, targ->faction );
FSM::Node *n = c.getCurrentState();
if (n) {
if ( n->edges.size() ) {
Unit *un = c.sender.GetUnit();
if (un) {
int b = selectCommunicationMessage( c, un );
Order *o = un->getAIState();
unsigned char gender;
std::vector< Animation* > *comm_face = parent->pilot->getCommFaces( gender );
if (o)
o->Communicate( CommunicationMessage( parent, un, c, b, comm_face, gender ) );
}
}
}
c.fsm = tmpfsm;
}
}
}
We see that the FSM is used inside of a CommunicationMessage class .
class CommunicationMessage
{
void Init( Unit *send, Unit *recv );
void SetAnimation( std::vector< class Animation* > *ani, unsigned char sex );
public:
FSM *fsm; //the finite state that this communcation stage is in
...
...
And inside the FSM class are declared :
vector< Node >nodes;
nodes are in fact States , and they are accessed by index with :
http://spacetechs.free.fr/VEGASTRIKEDEV ... f_s_m.html
int getDefaultState( float relationship ) const;
int GetUnDockNode() const;
int GetFailDockNode() const;
int GetDockNode() const;
int GetAbleToDockNode() const;
int GetUnAbleToDockNode() const;
int GetYesNode() const;
int GetNoNode() const;
int GetHitNode() const;
int GetDamagedNode() const;
int GetDealtDamageNode() const;
int GetScoreKillNode() const;
int GetRequestLandNode() const;
int GetContrabandInitiateNode() const;
int GetContrabandUnDetectedNode() const;
int GetContrabandDetectedNode() const;
int GetContrabandWobblyNode() const;

Code: Select all

 if (!track.HasWeapons())
            {
                // So what are you going to threaten me with? Exhaustion gas?
                return ThreatLevel::None;
            }
Vegastrike evolved
DEV YOUTUBE CHANNEL
Vegastrike evolved wiki
Post Reply