Bobot_controller.c

#include "../game/g_local.h"
#include "bobot.h"
#include "bobot_controller.h"
#include "bobot_ga.h"

extern void        UpdateNN(CNeuralNet* neuralNet, double* inputs, double* realOutputs);
extern void        BOBOT_SPAWN_RemoveBot (int clientNum);
extern int        BOBOT_SPAWN_SpawnBot  (char    *team,char *name,int skill,int classe,weapon_t weapon,weapon_t weapon2);
extern gentity_t    *SelectInitialSpawnPoint( vec3_t origin, vec3_t angles );
extern int    timePerGeneration;
extern int    numMoveWeightsEvolving;
extern int    numLookWeightsEvolving;

/*    pour le controller */
SGenome            movePopulation[BOBOT_NUM_BOTS]; // stockage de la population des génomes concernant le déplacement du bot
SGenome            lookPopulation[BOBOT_NUM_BOTS]; // stockage de la population des génomes concernant le déplacement du bot
int                vecBots[BOBOT_NUM_BOTS];        // stockage des numéros de client des bots
int                idController;
CGenAlg            moveGA;                            // l'algo génétique gérant le mouvement
CGenAlg            lookGA;                            // l'algo génétique gérant le regard
int            numTotalBotsCrees = 1;
int            bestBot;
char *pBrain;                                    //Joc pointeur pour lire les fichier

//    double            vecAvFitness[BOBOT_NUM_GENERATIONS];
//    double            vecBestFitness[BOBOT_NUM_GENERATIONS];

void BOBOT_CONTROL_LoadBestBrain(int numClient,CNeuralNet* brain,char* brainName)
{    /*FILE        *pIn;
    char        filename[60];
    double        weight;
    int            i,j,k;

    strcpy(filename,".\\bobot/\brains\\");
    strcat(filename,brainName);
    strcat(filename,".nn");
    if((pIn = fopen(filename, "rt" )) == NULL)
    {   G_Printf("BOBOT: No brain file found... New %s created.\n",brainName);
        return;
    }
    G_Printf("BOBOT: Loading the best bot's %s...",brainName);
    // Reading the brain
    while(!feof(pIn))
    {    fscanf(pIn,"%d %d %d %lf",&i,&j,&k,&weight);
        brain->vecLayers[i].vecNeurons[j].vecWeight[k] = weight;
    }
    fclose(pIn); */
   
    /*****************************
    joc réecris la fonction avec le moteur de quake pour pouvoir mettre
    le .nn dans des pk3 :)
    il faudra faire pareil avec savebrain*/

    char            filename[MAX_QPATH];
    fileHandle_t    f;
    int                len;
    double            weight;
    int                i;
    int                tab[3];
    char            *token;
    Q_strncpyz( filename, "brains/", sizeof(filename) );
    Q_strcat( filename, sizeof(filename), brainName );
    Q_strcat( filename, sizeof(filename), ".nn" );
    len = trap_FS_FOpenFile( filename, &f, FS_READ );
    if( len < 0 )
    {    G_Printf("BOBOT_CONTROL_LoadBestBrain : Brain file %s no found\n",brainName);
        return;
    }
    G_Printf("BOBOT : Loading Best Brain file %s, wait...\n",brainName);
    pBrain = G_Alloc( len + 1 );
    trap_FS_Read( pBrain, len, f );
    *(pBrain + len) = '\0';
    i=0;
    for (token = COM_Parse( &pBrain );token[0] != 0; token = COM_Parse( &pBrain ))
    {    if (i<3)
        {    tab[i]=atoi(token);
            i++;
        }
        else
        {    weight = atof(token);
            brain->vecLayers[tab[0]].vecNeurons[tab[1]].vecWeight[tab[2]] = weight;
            i=0;
        }
    }
    trap_FS_FCloseFile( f );
    G_Printf("BOBOT : The Best Brain file %s is loaded.\n",brainName);
    g_entities[numClient].nextthink = level.time + BOBOT_NEXT_THINK; // Let the bot move
}

void BOBOT_CONTROL_SaveBestBrain(int option,int brainType)
{    FILE        *pOut;
    char        filename[60];
    int            i,j,k;
    gentity_t    *bobot;
    Sbobot        *bobotAI;
    CNeuralNet    *brain = NULL;

    bobot        = &(g_entities[bestBot]);
    bobotAI        = &bobots[bobot->s.clientNum];
    strcpy(filename,".\\bobot\\brains\\");
    switch(brainType)
    {
        case BOBOT_MOVE_BRAIN :
            brain = &(bobotAI->itsMoveBrain);
            strcat(filename,BOBOT_MOVE_BRAIN__BRAIN_NAME);
            break;
        case BOBOT_LOOK_BRAIN :
            brain = &(bobotAI->itsLookBrain);
            strcat(filename,BOBOT_LOOK_BRAIN__BRAIN_NAME);
            break;
        default :
            G_Printf("BOBOT ERROR : SaveBestBrain : bad brain type\n");
            return;
            break;
    }
    if(option == BOBOT_LAST_BEST)
    { G_Printf("BOBOT: Saving the best bot's brain..."); }
    if(option == BOBOT_BEST_SO_FAR)
    { strcat(filename,"BestSoFar"); }
    strcat(filename,".nn");
    //if((pOut = fopen(filename, "wb" )) == NULL)
    if((pOut = fopen(filename, "wt" )) == NULL)
    { return; }        // fail

    /*    Write NN  */
    /*    for each layer */
    for (i=0; i<brain->m_NumHiddenLayers + 1; ++i)
    {    /*    for each neuron */
        for (j=0; j<brain->vecLayers[i].m_NumNeurons; ++j)
        {    /*    for each weight */
            for (k=0; k<brain->vecLayers[i].vecNeurons[j].m_NumInputs; ++k)
            {    fprintf(pOut,"%d %d %d %lf ",i,j,k,brain->vecLayers[i].vecNeurons[j].vecWeight[k]);
                fprintf(pOut,"\n");
            }
        }
    }
    fclose(pOut);
     if(option == BOBOT_LAST_BEST)
    { G_Printf("done.\n"); }
}

void BOBOT_CONTROL_init(gentity_t *bobot)
{    int i;
    Sbobot        *bobotAI;

    bobotAI =    &bobots[bobot->s.clientNum];
    bobotAI->moveFitness = 0;
    bobotAI->lookFitness = 0;
    bobotAI->last_seeRight = 0;
    bobotAI->last_seeUp = 0;
    bobotAI->last_lookRight = 0;
    bobotAI->last_lookUp = 0;
    bobotAI->last_health = 100;
    bobotAI->is_jumping = qfalse;
    bobotAI->frag = qfalse;
    bobotAI->killed = qfalse;
    VectorCopy(bobot->client->ps.viewangles,bobotAI->move_angles);
    for(i=0;i<bobotAI->itsMoveBrain.m_NumOutputs;i++)
    { bobotAI->last_moveOutputs[i] = 0; }
    for(i=0;i<bobotAI->itsLookBrain.m_NumOutputs;i++)
    { bobotAI->last_lookOutputs[i] = 0; }
    bobot->nextthink    = level.time + BOBOT_NEXT_THINK;
}

/*    retire les bots et en fait spawn des nouveaux */
void BOBOT_CONTROL_ResetBots(gentity_t *controller)
{    int            i;   
    Sbobot        *bobotAI;
    gentity_t    *bobot;

    for(i=0;i<BOBOT_NUM_BOTS;i++)
    {    bobot = &(g_entities[vecBots[i]]);
        bobotAI = &bobots[bobot->s.clientNum];
        respawn(bobot); // respawn the bot

        /*    This should make sure the procedure for movement restarts */
        bobotAI->state        = BOT_STATE_POSITION;
        bobotAI->goal_node    = INVALID;
        bobotAI->next_node    = INVALID;
        bobot->current_node = INVALID;
        BOBOT_CONTROL_init(bobot);
    }
}

/*    lance une nouvelle génération */
void BOBOT_CONTROL_ControllerThink(gentity_t *controller)
{    int i;
    G_Printf("\n\n\n__________________________________________________________\n");
    G_Printf("GENERATION %d | ",moveGA.generationCounter);

    if(moveGA.generationCounter > 0)
    {    /*    Another generation has been completed. récupération des fitness */
        for(i=0; i<moveGA.popSize;i++)
        { movePopulation[i].dFitness = bobots[vecBots[i]].moveFitness; }
        for(i=0; i<lookGA.popSize;i++)
        { lookPopulation[i].dFitness = bobots[vecBots[i]].lookFitness; }

        /*    Time to run the GA and update the bots with their new NNs
            update the stats to be used in our stat window */

        //vecAvFitness[moveGA.generationCounter] = AverageFitness(&(controller->moveGA));
        //vecBestFitness[moveGA.generationCounter] = BestFitness(&(controller->moveGA));

        /*    run the moveGA to create a new population */
        if(BOBOT_MOVE_BRAIN__IS_LEARNING)
        { Epoch(&moveGA,movePopulation); }
        if(BOBOT_LOOK_BRAIN__IS_LEARNING)
        { Epoch(&lookGA,lookPopulation); }
   
        /*     Respawn the bots */
        BOBOT_CONTROL_ResetBots(controller);

        /*    Insert the new (hopefully)improved brains back into the bots */
        if(BOBOT_MOVE_BRAIN__IS_LEARNING)
        {    for (i=0; i<moveGA.popSize; ++i)
            { PutWeights(&(bobots[vecBots[i]].itsMoveBrain),movePopulation[i].vecWeights); }
        }
        if(BOBOT_LOOK_BRAIN__IS_LEARNING)
        {    for (i=0; i<moveGA.popSize; ++i)
            { PutWeights(&(bobots[vecBots[i]].itsLookBrain),lookPopulation[i].vecWeights); }
        }
    }

    /*    incrémente le compteur de générations */
    moveGA.generationCounter++;
    lookGA.generationCounter++; // ne sert à rien
    if(BOBOT_MOVE_BRAIN__IS_LEARNING)
    {    G_Printf("Best : %f (bot %d) | ",moveGA.reallyBestFitness,moveGA.reallyFittestGenome);
        G_Printf("Average : %f | ",moveGA.reallyAverageFitness);
        G_Printf("Worst : %f",moveGA.reallyWorstFitness);
        G_Printf("\n");
    }
    if(BOBOT_LOOK_BRAIN__IS_LEARNING)
    {    G_Printf("Best : %f (bot %d) | ",lookGA.reallyBestFitness,lookGA.reallyFittestGenome);
        G_Printf("Average : %f | ",lookGA.reallyAverageFitness);
        G_Printf("Worst : %f",lookGA.reallyWorstFitness);
        G_Printf("\n");
    }
    controller->nextthink = level.time + timePerGeneration;
}

void BOBOT_CONTROL_bestBotFlagThink(gentity_t *bestBotFlag)
{    int            i;
    double        maxFitness = -99999999;
    Sbobot        *bobotAI;
    gentity_t    *bobot;
    double        fitness;

    for(i=0; i < BOBOT_NUM_BOTS; i++)
    {    bobot = &(g_entities[vecBots[i]]);
        bobotAI = &bobots[bobot->s.clientNum];
        fitness = bobotAI->moveFitness + bobotAI->lookFitness; // on additionne le fitness de tous les NN
        if(fitness > maxFitness)
        {    maxFitness = fitness;
            bestBot = bobot->s.clientNum;
        }
    }
    //G_Printf("bestBot : %d, %f\n",bestBot-1,maxFitness);
    bobot = &(g_entities[bestBot]);
    VectorCopy(bobot->r.currentOrigin, bestBotFlag->s.origin);
    bestBotFlag->s.origin[2] += 200;
    G_SetOrigin (bestBotFlag, bestBotFlag->s.origin);
    G_SetAngle (bestBotFlag, bestBotFlag->s.angles);
    bestBotFlag->nextthink = level.time + BOBOT_NEXT_THINK;
}

void BOBOT_CONTROL_AddBot(int clientNum)
{    Sbobot        *bobotAI;

    bobotAI = &bobots[clientNum];
   
    /*     création du réseau de neurones digireant les mouvements du bot*/
    CreateNeuralNet(&(bobotAI->itsMoveBrain),BOBOT_MOVE_BRAIN__NUM_INPUTS,BOBOT_MOVE_BRAIN__NUM_OUTPUTS,BOBOT_MOVE_BRAIN__NUM_HIDDEN_LAYERS,BOBOT_MOVE_BRAIN__NUM_NEURONS_PER_HIDDEN_LAYER);
    BOBOT_CONTROL_LoadBestBrain(clientNum,&(bobotAI->itsMoveBrain),BOBOT_MOVE_BRAIN__BRAIN_NAME);
   
    /*    création du réseau de neurones digireant la direction du regard du bot */
    CreateNeuralNet(&(bobotAI->itsLookBrain),BOBOT_LOOK_BRAIN__NUM_INPUTS,BOBOT_LOOK_BRAIN__NUM_OUTPUTS,BOBOT_LOOK_BRAIN__NUM_HIDDEN_LAYERS,BOBOT_LOOK_BRAIN__NUM_NEURONS_PER_HIDDEN_LAYER);
    BOBOT_CONTROL_LoadBestBrain(clientNum,&(bobotAI->itsLookBrain),BOBOT_LOOK_BRAIN__BRAIN_NAME);
}

void BOBOT_CONTROL_CreateController()
{    int            i;
    gentity_t        *controller;
    gentity_t        *bestBotFlag;
    char            name[MAX_TOKEN_CHARS]="\0";
    Sbobot            *bobotAI;
    gentity_t        *bobot;

    /*    création de l'entité : Controller */
    controller                = G_Spawn();
    controller->inuse        = qtrue;
    controller->think        = BOBOT_CONTROL_ControllerThink;
    controller->nextthink    = level.time;                        // le controller va agir immédiatement
    idController            = controller->s.number;

    /*    Création de l'entité : Flag au dessus du meilleur bot */
    bestBotFlag                    = G_Spawn();
    bestBotFlag->inuse            = qtrue;
    bestBotFlag->s.modelindex    = G_ModelIndex( "models/mapobjects/flag/flag01.md3" );
    bestBotFlag->think            = BOBOT_CONTROL_bestBotFlagThink;
    bestBotFlag->nextthink        = level.time + 100;
    bestBotFlag->r.svFlags        = SVF_USE_CURRENT_ORIGIN | SVF_BROADCAST;
    trap_LinkEntity(bestBotFlag);
    LoadWeightsNotEvolving(BOBOT_MOVE_BRAIN);
    if(numMoveWeightsEvolving == 0)
    {    G_Printf("BOBOT MOVE : No weight needs to evolve\n");
        return;
    }
    LoadWeightsNotEvolving(BOBOT_LOOK_BRAIN);
    if(numLookWeightsEvolving == 0)
    {    G_Printf("BOBOT LOOK : No weight needs to evolve\n");
        return;
    }

    /*    création de la population de l'algo génétique (sans la remplir tout de suite des réseaux de neurones) */
    CreateCGenAlg(&moveGA,BOBOT_NUM_BOTS,BOBOT_MUTATION_RATE,BOBOT_CROSSOVER_RATE,numMoveWeightsEvolving,BOBOT_MOVE_BRAIN);
    CreateCGenAlg(&lookGA,BOBOT_NUM_BOTS,BOBOT_MUTATION_RATE,BOBOT_CROSSOVER_RATE,numLookWeightsEvolving,BOBOT_LOOK_BRAIN);
   
    /*     creation de la population de bots*/
    for(i=0;i<BOBOT_NUM_BOTS;i++)
    {    if (!Q_stricmp(name,""))
        { Q_strncpyz(name, "bobot", sizeof(name)); }
        name[6] = '\0';
        name[7] = '\0';
        name[8] = '\0';
        //    itoa(i,name+5,10);
        if(i%2)
        { vecBots[i] = BOBOT_SPAWN_SpawnBot ("blue", name, 0,-1,-1,-1); }
        else
        { vecBots[i] = BOBOT_SPAWN_SpawnBot ("red", name, 0,-1,-1,-1); }
        bobot = &(g_entities[vecBots[i]]);
        bobotAI = &bobots[bobot->s.clientNum];
        CreateNeuralNet(&(bobotAI->itsMoveBrain),BOBOT_MOVE_BRAIN__NUM_INPUTS,BOBOT_MOVE_BRAIN__NUM_OUTPUTS,BOBOT_MOVE_BRAIN__NUM_HIDDEN_LAYERS,BOBOT_MOVE_BRAIN__NUM_NEURONS_PER_HIDDEN_LAYER);
        CreateNeuralNet(&(bobotAI->itsLookBrain),BOBOT_LOOK_BRAIN__NUM_INPUTS,BOBOT_LOOK_BRAIN__NUM_OUTPUTS,BOBOT_LOOK_BRAIN__NUM_HIDDEN_LAYERS,BOBOT_LOOK_BRAIN__NUM_NEURONS_PER_HIDDEN_LAYER);
       
        /*     on reprend plusieurs fois le meilleur bot de la session précédente : */
        if(i < BOBOT_NUMBER_OF_BEST_LAST_BOT)
        {    BOBOT_CONTROL_LoadBestBrain(vecBots[i],&(bobotAI->itsMoveBrain),BOBOT_MOVE_BRAIN__BRAIN_NAME);
            BOBOT_CONTROL_LoadBestBrain(vecBots[i],&(bobotAI->itsLookBrain),BOBOT_LOOK_BRAIN__BRAIN_NAME);
        }
        else
        {    if(!BOBOT_MOVE_BRAIN__IS_LEARNING)
            { BOBOT_CONTROL_LoadBestBrain(vecBots[i],&(bobotAI->itsMoveBrain),BOBOT_MOVE_BRAIN__BRAIN_NAME); }
            if(!BOBOT_LOOK_BRAIN__IS_LEARNING)
            { BOBOT_CONTROL_LoadBestBrain(vecBots[i],&(bobotAI->itsLookBrain),BOBOT_LOOK_BRAIN__BRAIN_NAME); }
        }

        /*    mises à zéro */
        BOBOT_CONTROL_init(bobot);       

        /*    on remplit la population du controller avec les réseaux de neurones */
        GetWeights(&(bobotAI->itsMoveBrain),movePopulation[i].vecWeights);
        GetWeights(&(bobotAI->itsLookBrain),lookPopulation[i].vecWeights);
    }
}

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