Bobot_mapping.c (1)

/*--------------------------------------------------------------------------
crée par Joc le 1/02/04 et modifié par PAV en 2006.
NODES FUNCTION LISTING
--------------------------------------------------------------------------
FUSION_MAPPING_AddNode
BOBOT_MAPPING_RemoveNode
BOBOT_MAPPING_setNextNodeNoise
BOBOT_MAPPING_ChangeNodeRadius
FUSION_MAPPING_FollowPath
BOBOT_MAPPING_CreateNodeConnection
BOBOT_MAPPING_DestroyNodeConnection
FUSION_MAPPING_ShowNodes
FUSION_MAPPING_ShowConnection
FUSION_MAPPING_SetConnectionCost
BOBOT_MAPPING_PrintType
FUSION_MAPPING_SetNodeType
FUSION_MAPPING_HideNodes
FUSION_MAPPING_SetTouchConnection
FUSION_MAPPING_SetRelocateNode
FUSION_MAPPING_TouchNode
FUSION_MAPPING_CreateVisibleNode

    bobot_mapping.c
    Mapping routines for the FUSION bot.
--------------------------------------------------------------------------*/

#include "../game/g_local.h"
#include "bobot.h"
#include "bobot_extern.h"

int NumClient=0;
int number_conn = 0;
int touch_connections = 0;
int destructionconnex = 0;
int addnodeetcreationconnex=0;
int creationconnex = 0;
qboolean relocate_node = qfalse;
int current_node = -1;
node_t nodes[MAX_NODES];
gentity_t *visible_nodes[MAX_NODES];
gentity_t *connections[MAX_CONNEXIONS];
extern botai_t botai;
char connectionPrint[200];

/* --------------------------------------------- Création d'un node ---------------------------------- */
void FUSION_MAPPING_AddNode( int clientNum )
{    int i;
    int NodeTo=0;
    int NodeFrom=0;
    vec3_t v;

    if(clientNum != NumClient)
    { NumClient=clientNum; }
    if(!shownodes)
    {    AP("cp \"Addnode impossible : Shownodes is OFF\" 1");
        return;
    }

    /*    Si on a voulu déplacer le node. */
    if (relocate_node)
    {    if ((current_node == INVALID) || (current_node > MAX_NODES))
        { return; }
        VectorCopy( g_entities[clientNum].r.currentOrigin, nodes[current_node].origin );
        for (i = 0; i < MAX_NODELINKS; i++)
        {    if (nodes[current_node].links[i].targetNode != INVALID)
            {    VectorSubtract(nodes[current_node].origin,nodes[ nodes[current_node].links[i].targetNode ].origin, v );
                nodes[current_node].links[i].cost = VectorLength( v );
            }
        }
        if (visible_nodes[current_node] != NULL)
        {    G_FreeEntity( visible_nodes[current_node] );
            visible_nodes[current_node] = NULL;
        }
        BOBOT_MAPPING_CalculateVisibleNodes( number_of_nodes );
        AP(va("cp \"\n\n\n\nNode %i relocated\n\" 1",current_node));
    }

    /*    Sinon c'est une création pure de node. */
    else if (number_of_nodes < MAX_NODES)
    {    /*    Calculer sa position d'origine */
        nodes[number_of_nodes].radius = g_radiusnode.integer ;            //Rayon des nodes par défaut
        VectorCopy( g_entities[clientNum].r.currentOrigin, nodes[number_of_nodes].origin );
        nodes[number_of_nodes].type = NODE_MOVE;        // Default node type
   
        /*    Mise à zéro des liens du nouveau node. */
        for (i = 0; i < MAX_NODELINKS; i++)
        { nodes[number_of_nodes].links[i].targetNode = INVALID; }
   
        /*    Création de la connexion entre ce nouveau node et le node précédent */
        if (BOBOT_MAPPING_CreateNodeConnection(current_node,number_of_nodes,touch_connections & ~CONNEC_MASK))
        { NodeFrom=1; }
        if (BOBOT_MAPPING_CreateNodeConnection(number_of_nodes,current_node,touch_connections & ~CONNEC_MASK))
        { NodeTo=1;    }

        /*    Affichage des messages */
        if ((NodeFrom+NodeTo)==2)
        { AP(va("cp \"\n\n\n\nNode %i created. Connections %i <==> %i.\n\" 1", number_of_nodes,number_of_nodes,current_node)); }
        else if (NodeFrom==1)
        { AP(va("cp \"\n\n\n\nNode %i created. Connection %i <== %i.\n\" 1", number_of_nodes,number_of_nodes,current_node)); }
        else if (NodeTo==1)
        { AP(va("cp \"\n\n\n\nNode %i created. Connection %i ==> %i.\n\" 1", number_of_nodes,number_of_nodes,current_node)); }
        else
        { AP(va("cp \"\n\n\n\nNo connection created between the nodes %i and %i.\n\" 1",number_of_nodes ,current_node)); }
        current_node = number_of_nodes;
        number_of_nodes++;
        BOBOT_MAPPING_CalculateVisibleNodes();
    }
    else // Maximum de nodes atteints
    { AP(va("cp \"\n\n\n\nMaximum nodes created (%i).\n\" 1", MAX_NODES)); }
}

/*--------------------------------------------------------------------------
Joc : NE PAS UTILISER CETTE FONCTION !
elle ne gere pas les différents types de nodes ...
--------------------------------------------------------------------------*/
void BOBOT_MAPPING_RemoveNode()
{    int i;
    qboolean newConnections[MAX_NODES][MAX_NODES];

    if (current_node == INVALID || current_node > MAX_NODES)
    { return; }
    for(i=0; i < MAX_NODES; i++)
    {    int j;
        for(j=0;j<MAX_NODES;j++)
        { newConnections[i][j] = qfalse; }
    }
    //G_Printf("\n\n");
    for(i=0; i < number_of_nodes; i++)
    {    int link;
        for(link=0; link < MAX_NODELINKS; link++)
        {    if(nodes[i].links[link].targetNode == current_node)
            { nodes[i].links[link].targetNode = INVALID; }    // détruire les connexions des autres nodes avec ce node
        }
    }
    for(i=current_node; i<number_of_nodes-1; i++)
    {    if(i+1 < MAX_NODES)
        { nodes[i] = nodes[i+1]; }
    }
    number_of_nodes--;
    for(i=0; i < number_of_nodes; i++)
    {    int link,other,link2,node;
        for(link=0; link < MAX_NODELINKS; link++)
        {    other = nodes[i].links[link].targetNode;
            if( other != INVALID && other > current_node)    // si ce node change de numéro
            {    if(newConnections[i][other] == qfalse)        // si la connection qu'on vient de trouver n'est pas nouvelle
                {    if(i+1 > current_node)                    // si le node de départ change de numéro
                    {    node = i+1;
                        if (PrintDebug)
                        { G_Printf("\nConnection beetwen last %d et last %d destroyed",node,other); }
                    }
                    else
                    {    node = i;
                        if (PrintDebug)
                        { G_Printf("\nConnection beetwen last %d et last %d destroyed",node,other); }
                    }
                    nodes[i].links[link].targetNode = INVALID;                    // on défait la connexion
                    BOBOT_MAPPING_CreateNodeConnection(i,other-1,0);            // on la refait
                    newConnections[i][other-1] = qtrue;
                    for(link2=0; link2 < MAX_NODELINKS; link2++)
                    {    if(nodes[other].links[link2].targetNode == node)
                        {    nodes[other].links[link2].targetNode = INVALID;        // on défait la connexion dans l'autre sens
                            BOBOT_MAPPING_CreateNodeConnection(other-1,i,0);    // on la refait
                            newConnections[other-1][i] = qtrue;
                        }
                    }
                }
            }
        }
    }

    /*    Recreate visible entity if necessary */
    for(i=current_node; i< number_of_nodes+1; i++)
    {    if (visible_nodes[i] != NULL)
        {    G_FreeEntity( visible_nodes[i] );
            visible_nodes[i] = NULL;
        }
    }   
    current_node = number_of_nodes-1;
    //G_Printf("\nNode en cours = %d",current_node);
    BOBOT_MAPPING_CalculateVisibleNodes();
}

/*--------------------------------------------------------------------------
Ajoutons du bruit à la localisation du node que doit atteindre le bot
pour que les bots n'aillent pas toujours au même endroit
PAV : ça permet de ne pas cibler le centre du node mais le diamètre.
--------------------------------------------------------------------------*/
void BOBOT_MAPPING_setNextNodeNoise(Sbobot *bobotAI)
{    vec_t    pitchNoise,yawNoise;

    pitchNoise = RandomClamped()*nodes[bobotAI->next_node].radius*0.7;
    yawNoise   = RandomClamped()*nodes[bobotAI->next_node].radius*0.7;
    VectorSet(bobotAI->next_node_noise,pitchNoise,yawNoise,0);
}

/*--------------------------------------------------------------------------
    BOBOT_MAPPING_ChangeNodeRadius
--------------------------------------------------------------------------*/
void BOBOT_MAPPING_ChangeNodeRadius(int deltaradius)
{   
    if(!shownodes)
    { return; }
    nodes[current_node].radius += deltaradius;
    if (nodes[current_node].radius < 10)
    { nodes[current_node].radius = 10; }
    if (visible_nodes[current_node] != NULL)
    {    G_FreeEntity(visible_nodes[current_node]);
        FUSION_MAPPING_CreateVisibleNode(current_node);
    }
    AP(va("cp \"\n\n\n\nRadius of the node %d : %d\n\" 1",current_node,(int)nodes[current_node].radius));
}

/*--------------------------------------------------------------------------
    FUSION_MAPPING_FollowPath
--------------------------------------------------------------------------*/
qboolean FUSION_MAPPING_FollowPath(gentity_t *bobot)
{   vec3_t v;
    Sbobot *bobotAI;
    int    i;
    float (*MinCost)[MAX_NODES][MAX_NODES];                                //Joc 2 tableaux MinCost !

    bobotAI = &bobots[bobot->s.clientNum];

    /*    utilisation de AlliesMinCost ou AxisMinCost en fonction de la team du bot */
    //MinCost = (bobotAI->myteam == TEAM_ALLIES ? &AlliesMinCost : &AxisMinCost);

    // Les coverts déguisés utilisent le Mincost adverse.
    if(bobotAI->myteam == TEAM_AXIS)
    {    if(bobot->client->ps.powerups[PW_OPS_DISGUISED])
            MinCost = &AlliesMinCost;
        else
            MinCost = &AxisMinCost;
    }
    else if(bobotAI->myteam == TEAM_ALLIES)
    {    if(bobot->client->ps.powerups[PW_OPS_DISGUISED])
            MinCost = &AxisMinCost;
        else
            MinCost = &AlliesMinCost;
    }

    /*    If no current node, BUT there's a next node, move to the next, next_node should be the closest node */
    if ( bobot->current_node == INVALID && bobotAI->next_node != INVALID)
    {    /*    See if we're there yet */
        VectorSubtract( bobot->r.currentOrigin, nodes[bobotAI->next_node].origin, v );
        if ( VectorLength(v) < nodes[bobotAI->next_node].radius )
        {    bobotAI->node_timeout    = 0;
            bobotAI->tries        = 0;
            bobot->current_node    = bobotAI->next_node;
            bobotAI->next_node    = INVALID;
            if (bobotAI->goal_node == INVALID)
            { bobotAI->state    = BOT_STATE_POSITION; }                    // Else leave me in same move state
        }

        /*    on verifie si on ne touche pas un autre node */
        else       
        {    for (i=0;i<number_of_nodes;i++)
            {    VectorSubtract( bobot->r.currentOrigin, nodes[i].origin, v );
                if ( VectorLength(v) < nodes[i].radius )
                {    bobotAI->node_timeout    = 0;
                    bobotAI->tries        = 0;
                    bobot->current_node    = i;
                    bobotAI->next_node    = INVALID;
                    if (bobotAI->goal_node == INVALID)
                    { bobotAI->state = BOT_STATE_POSITION; }            // Else leave me in same move state
                }
            }

            /*    on ne touche pas de node ce coup ci Direct to the next node */
            if(bobotAI->next_node != INVALID)
            {    VectorSubtract( nodes[bobotAI->next_node].origin,bobot->r.currentOrigin , bobotAI->move_vector);
                VectorAdd(bobotAI->move_vector,bobotAI->next_node_noise,bobotAI->move_vector);
            }
        }
        return qtrue;
    }
    if ( bobotAI->goal_node != INVALID )
    {    /*    We are supposed to move to a goal_node, but from a current_node */
        if ( bobot->current_node != INVALID )
        {    /*    Okay, see if there's a next_node set, if not, get one from the path */
            if ( bobotAI->next_node == INVALID )
            {    int node_possible[MAX_NODELINKS];
                int numnode,j;
                if (PrintDebug)
                { G_Printf("FUSION_MAPPING_FollowPath : %s sur le node %d  \n",bobot->client->pers.netname,bobot->current_node); }
                j=0;
                for(i=0;i<MAX_NODELINKS;i++)
                {   numnode = nodes[bobot->current_node].links[i].targetNode;
                    if ((*MinCost)[numnode][bobotAI->goal_node] < (*MinCost)[bobot->current_node][bobotAI->goal_node] &&
                        numnode != INVALID && nodes[numnode].type & NODE_MOVE)
                    {    node_possible[j] = numnode;
                        j++;
                    }
                }
                if(j==0)
                {    if(bobot->current_node == bobotAI->goal_node)        // si on est sur le goal_node
                    {    bobotAI->next_node     = bobotAI->goal_node;
                        bobotAI->state        = BOT_STATE_POSITION;
                        bobotAI->goal_node    = INVALID;
                        return qtrue;
                    }
                    else                                                //y'a un pb on ne peut pas se rapprocher du goal
                    {    if (PrintDebug)
                        {   Bobot_Printf("%s pas de node plus proche que celui en cours ! \n",bobot->client->pers.netname);
                            Bobot_Printf("current_node : %i , goalnode : %i \n",bobot->current_node,bobotAI->goal_node);
                        }     
                        return qfalse;
                    }
                }
                else
                {    bobotAI->next_node = node_possible[rand()%j];
                    bobotAI->state    = BOT_STATE_MOVE;
                    bobotAI->passeporte = qfalse;
                    for(i=0;i<MAX_NODELINKS;i++)
                    {  if(nodes[bobot->current_node].links[i].targetNode == bobotAI->next_node)
                       {    if(nodes[bobot->current_node].links[i].type & CONNEC_ECHELLE)
                            { bobotAI->state = BOT_STATE_SPECIAL_MOVE; }
                            if(nodes[bobot->current_node].links[i].type & CONNEC_TOUT_DROIT)
                            { bobotAI->state = BOT_STATE_TOUT_DROIT; }
                            if(nodes[bobot->current_node].links[i].type & CONNEC_ALLIES)
                            {    bobotAI->state = BOT_STATE_TOUT_DROIT;
                                if (bobot->client->sess.sessionTeam == TEAM_ALLIES)
                                    bobotAI->passeporte = qtrue;
                                else if(bobot->client->sess.sessionTeam == TEAM_AXIS)
                                {    if(bobot->client->ps.powerups[PW_OPS_DISGUISED])
                                        bobotAI->passeporte = qtrue;
                                    else
                                        bobotAI->next_node = INVALID;
                                }
                                /*else
                                    bobotAI->next_node = INVALID;*/
                            }
                            if(nodes[bobot->current_node].links[i].type & CONNEC_AXIS) //|| (nodes[bobot->current_node].links[i].type & CONNEC_DOOR))
                            {    bobotAI->state = BOT_STATE_TOUT_DROIT;
                                if (bobot->client->sess.sessionTeam == TEAM_AXIS)
                                    bobotAI->passeporte = qtrue;
                                else if(bobot->client->sess.sessionTeam == TEAM_ALLIES)
                                {    if(bobot->client->ps.powerups[PW_OPS_DISGUISED])
                                        bobotAI->passeporte = qtrue;
                                    else
                                        bobotAI->next_node = INVALID;
                                }
                                /*else
                                    bobotAI->next_node = INVALID;*/
                            }
                       }
                    }
                }

                /*    ajout de bruit à la localisation du next node */
                BOBOT_MAPPING_setNextNodeNoise(bobotAI);

                /*    le précédent node a été atteint
                    on calcule au départ d'un mouvement la distance initiale par rapport au next node */
                VectorSubtract( bobot->r.currentOrigin, nodes[bobotAI->next_node].origin, v );
                bobotAI->minDistanceFromNextNode = VectorLength(v);
                bobotAI->maxDistanceFromNextNode = bobotAI->minDistanceFromNextNode;
                bobotAI->lastDistanceFromNextNode = bobotAI->minDistanceFromNextNode;
               
                /*    If next_node is still INVALID, then the goal_node is not reachable */
                if ( bobotAI->next_node == INVALID )
                {    if(random() < 0.05)
                    { G_Say(bobot, NULL, SAY_TEAM, "^7Impossible to find a passage!"); }
                    return qfalse;
                }
            }
           
            /*    We have next_node, move towards it */
            VectorSubtract( bobot->r.currentOrigin, nodes[bobotAI->next_node].origin, v );
           
            /*    Joc debug
                Bobot_Printf("distance restante : %lf  rayon %lf \n",VectorLength(v),nodes[bobotAI->next_node].radius); */

            if ( VectorLength(v) < nodes[bobotAI->next_node].radius )        // We're there
            {    bobotAI->tries = 0;
                bobotAI->node_timeout = 0;
                bobot->current_node    = bobotAI->next_node;
                if ( bobotAI->next_node == bobotAI->goal_node )                // We've reached the goal
                { BOBOT_ENGINEER_Choix_ActionGoal(bobot); }
                bobotAI->next_node    = INVALID;
                return qtrue;
            }

            /*    on verifie si on ne touche pas un autre node
                cette fonction risque de bouffer pas mal de proc mais je vois pas d'autre moyen */
            else       
            {    for (i=0;i<number_of_nodes;i++)
                 { if (i==bobot->current_node)                                // fixe le bug des nodes à grand radius...
                    { continue; }                                            // si on est tjs pres du node ou l'on est il faut ignorer
                    VectorSubtract( bobot->r.currentOrigin, nodes[i].origin, v );
                    if ( VectorLength(v) < nodes[i].radius )
                    {    bobotAI->node_timeout    = 0;
                        bobotAI->tries            = 0;
                        bobot->current_node        = i;
                        bobotAI->next_node        = INVALID;
                        if ( i == bobotAI->goal_node )                        // But trouvé, déclanche ingénieur action.
                        { BOBOT_ENGINEER_Choix_ActionGoal(bobot); }
                        return qtrue;
                    }
                }

                /*    go to the next node */
                VectorSubtract( nodes[bobotAI->next_node].origin,bobot->r.currentOrigin , bobotAI->move_vector );
                VectorAdd(bobotAI->move_vector,bobotAI->next_node_noise,bobotAI->move_vector);
            }
            return qtrue;
        }
    }
    else
    { return qfalse; }    // No goal_node ??? We're heading nowhere !
                        // We should return qfalse here at some point, so we would stop 'following' this path
    return qtrue;
}

/*-----------------------------------------------------------------------------
BOBOT_MAPPING_CreateNodeConnection
version légère de creatnode connection
On ne se sert plus de path_table et on crée une connection à sens unique
joc je rajoute le type de la connec sinon ca peut bugger ...
-----------------------------------------------------------------------------*/
qboolean BOBOT_MAPPING_CreateNodeConnection( int from, int to ,int type)
{    qboolean CreatConnexOK = qfalse;
    int i;
    float cost;
    vec3_t v;

    if ( from == -1 || to == -1 || from == to )
    { return CreatConnexOK; }
    VectorSubtract( nodes[from].origin, nodes[to].origin, v );
    cost = VectorLength( v );

    /*    Find a free connection slot, create the connection */
    for (i = 0; i < MAX_NODELINKS; i++)
    {    if (nodes[from].links[i].targetNode == to)                // Seems we already have a connection
        { break; }
        else if (nodes[from].links[i].targetNode == INVALID)    // Okay, create a connection
        {    nodes[from].links[i].targetNode = to;
            nodes[from].links[i].cost        = cost;
            nodes[from].links[i].type        = type;
            CreatConnexOK=qtrue;
            //G_Printf("\nConnections created beetwen the nodes %i and %i.", from, to);
            break;                                                // Added node, break from loop
        }
    }
    return CreatConnexOK;
}

/*-----------------------------------------------------------------------------
Joc : BOBOT_MAPPING_DestroyNodeConnection()
on ne detruit la connection que dans un sens !!
-----------------------------------------------------------------------------*/
qboolean BOBOT_MAPPING_DestroyNodeConnection( int from, int to )
{    int i;
    qboolean DestructOk=qfalse;

    if ( from == -1 || to == -1 || from == to )
    { return DestructOk; }

    /*    Find the link connection slot, destroy the connection */
    for (i = 0; i < MAX_NODELINKS; i++)
    {    if (nodes[from].links[i].targetNode == to)            //on supprime la connection
        {    nodes[from].links[i].targetNode = INVALID;
            //G_Printf("\nConnections destroyed beetwen the nodes %i and %i.", from, to);
            DestructOk=qtrue;
        }
    }
    return DestructOk;
}

int G_CountPlayers()
{    int i, num;
    gclient_t    *cl;

    num = 0;
    for ( i=0 ; i< g_maxclients.integer ; i++ ) {
        cl = level.clients + i;
        if ( cl->pers.connected != CON_CONNECTED ) {
            continue;
        }
        num++;
    }
    return num;
}

*/-----------------------------------------End part 1 look at part 2

 

Créer un site gratuit avec e-monsite - Signaler un contenu illicite sur ce site