29#include "BrainsFactory.h" 
   30#include "ObjectsGhost.h" 
   32#include "Pac-Man_Evolution.h" 
   33#include "ArtificialNeuralNet.h" 
   34#include "EVNTrainer.h" 
   41    iTargetType = PME_BRAIN_HIGHLEVEL_TARGET;
 
   48Sint32 Brain::think(Actor* pActor, Sint32 &iTX, Sint32 &iTY, GameField* pGF)
 
   50    iTX = Main::Instance().ITool().randWELL() % MAZE_WIDTH;
 
   51    iTY = Main::Instance().ITool().randWELL() % MAZE_HEIGHT;
 
   56void Brain::getName(
string& sN)
 
   62Sint32 Brain::getTargetType()
 
   68BrainEvolved::BrainEvolved() : Brain()
 
   71    pNeuralNet = 
new(std::nothrow) ArtificialNeuralNet();
 
   77BrainEvolved::~BrainEvolved()
 
   79    if(pNeuralNet != 
nullptr) 
delete pNeuralNet;
 
   83Sint32 BrainEvolved::setFitness(
double dF)
 
   90double BrainEvolved::getFitness()
 
   95ArtificialNeuralNet* BrainEvolved::getNeuralNet()
 
   97    if(pNeuralNet) 
return pNeuralNet;
 
  102Sint32 BrainEvolved::load(
string sCDCFile, 
string sXMLName)
 
  105    if(EVNTrainer::Instance().load(sName, pNeuralNet, sCDCFile, sXMLName) != 0)
 
  107        Main::Instance().ILogMgr().get()->msg(LML_NORMAL, 
"  [BrainEvolved] Warning: neural network for ghost '%s' could not be loaded\n", sName.c_str());
 
  109        pNeuralNet = 
nullptr;
 
  114    else if((pNeuralNet->getNumInputs() != iNNInput) || (pNeuralNet->getNumOutputs() != iNNOutput))
 
  116        Main::Instance().ILogMgr().get()->msg(LML_NORMAL, 
"  [BrainEvolved] Warning: neural network loaded for ghost '%s' does not match with expected inputs('%d')/outputs('%d')\n", sName.c_str(), iNNInput, iNNOutput);
 
  118        pNeuralNet = 
nullptr;
 
  121    if(pNeuralNet) Main::Instance().ILogMgr().get()->msg(LML_INFO, 
"  [BrainEvolved] Info: neural network loaded for ghost '%s' with '%d' inputs, '%d' outputs and '%d' weights\n",
 
  122        sName.c_str(), pNeuralNet->getNumInputs(), pNeuralNet->getNumOutputs(), pNeuralNet->getNumberOfWeights());
 
  130BrainPacManHuman::BrainPacManHuman() : Brain() { sName = 
"PacMan-Human"; iTargetType = PME_BRAIN_IMMEDIATE_TARGET; }
 
  131Sint32 BrainPacManHuman::think(Actor* pActor, Sint32& iTX, Sint32& iTY, GameField* pGF) 
 
  133    Main& mC64 = Main::Instance();
 
  134    Sint32 iTmpX, iTmpY, iDirX, iDirY;
 
  137    pGF->getObjectPosition(PME_OBJECT_PACMAN, iTX, iTY);
 
  142    if(mC64.getKeyState(SDLK_DOWN))
 
  144        if(pGF->getState(iTX, iTY + 1) == PME_STATE_WALKABLE) ++iTY;
 
  146    if(mC64.getKeyState(SDLK_UP))
 
  148        if(pGF->getState(iTX, iTY - 1) == PME_STATE_WALKABLE) --iTY;
 
  150    if(mC64.getKeyState(SDLK_RIGHT))
 
  152        if((iTX + 1) > (MAZE_WIDTH - 1)) ++iTX;
 
  153        else if(pGF->getState(iTX + 1, iTY) == PME_STATE_WALKABLE) ++iTX;
 
  155    if(mC64.getKeyState(SDLK_LEFT))
 
  157        if((iTX - 1) < 0) --iTX;
 
  158        else if(pGF->getState(iTX - 1, iTY) == PME_STATE_WALKABLE) --iTX;        
 
  162    if(iTmpX == iTX && iTmpY == iTY)
 
  165            pGF->getObjectDirection(PME_OBJECT_PACMAN, iDirX, iDirY);
 
  168            iTmpX = iTmpX + 1 * iDirX;
 
  169            iTmpY = iTmpY + 1 * iDirY;
 
  170            if((iTmpX) > (MAZE_WIDTH - 1)) iTX = iTmpX;
 
  171            else if((iTmpX) < 0) iTX = iTmpX;
 
  172            else if(pGF->getState(iTmpX, iTmpY) == PME_STATE_WALKABLE)
 
  182BrainPacMan::BrainPacMan() : Brain() { sName = 
"PacMan-Fixed";  }
 
  183Sint32 BrainPacMan::think(Actor* pActor,Sint32& iTX, Sint32& iTY, GameField* pGF) 
 
  185    vector<MazePoint> vGhosts;
 
  186    MazePoint pointGhost;
 
  188    Sint32 i, iSelected = 0;
 
  189    double dLowest = 1000.0f;
 
  192    pGF->getObjectPosition(PME_OBJECT_PACMAN, iTX, iTY);
 
  195    if(pGF->getObjectPosition(PME_OBJECT_GHOST_RED, pointGhost.iX, pointGhost.iY) == 0)
 
  197        pGF->getObjectStateName(PME_OBJECT_GHOST_RED, sStateName);
 
  198        if(sStateName != 
"Death" && sStateName != 
"Init")
 
  200            pointGhost.iReserved = PME_OBJECT_GHOST_RED;
 
  201            vGhosts.push_back(pointGhost);
 
  204    if(pGF->getObjectPosition(PME_OBJECT_GHOST_PINK, pointGhost.iX, pointGhost.iY) == 0)
 
  206        pGF->getObjectStateName(PME_OBJECT_GHOST_PINK, sStateName);
 
  207        if(sStateName != 
"Death" && sStateName != 
"Init")
 
  209            pointGhost.iReserved = PME_OBJECT_GHOST_PINK;
 
  210            vGhosts.push_back(pointGhost);
 
  213    if(pGF->getObjectPosition(PME_OBJECT_GHOST_BLUE, pointGhost.iX, pointGhost.iY) == 0)
 
  215        pGF->getObjectStateName(PME_OBJECT_GHOST_BLUE, sStateName);
 
  216        if(sStateName != 
"Death" && sStateName != 
"Init")
 
  218            pointGhost.iReserved = PME_OBJECT_GHOST_BLUE;
 
  219            vGhosts.push_back(pointGhost);
 
  222    if(pGF->getObjectPosition(PME_OBJECT_GHOST_ORANGE, pointGhost.iX, pointGhost.iY) == 0)
 
  224        pGF->getObjectStateName(PME_OBJECT_GHOST_ORANGE, sStateName);
 
  225        if(sStateName != 
"Death" && sStateName != 
"Init")
 
  227            pointGhost.iReserved = PME_OBJECT_GHOST_ORANGE;
 
  228            vGhosts.push_back(pointGhost);
 
  233    for(i = 0; i < vGhosts.size(); ++i) pActor->euclideanDistance(iTX, iTY, vGhosts[i]);
 
  236    for(i = 0; i < vGhosts.size(); ++i)
 
  238        if(dLowest > vGhosts[i].dDistance)
 
  240            dLowest = vGhosts[i].dDistance;
 
  246    if(vGhosts.size() == 0)
 
  248        pGF->getClosestPellet(PME_OBJECT_PACMAN, iTX, iTY);
 
  252    else if((pGF->getWaveMode() == PME_GLOBAL_WAVE_EVADING) && (vGhosts[iSelected].dDistance < 10))
 
  254        iTX = vGhosts[iSelected].iX;
 
  255        iTY = vGhosts[iSelected].iY;
 
  258    else if(vGhosts[iSelected].dDistance > 6.0)
 
  260        pGF->getClosestPellet(PME_OBJECT_PACMAN, iTX, iTY);
 
  265        iTX = vGhosts[iSelected].iX + 2 * (iTX - vGhosts[iSelected].iX);
 
  266        iTY = vGhosts[iSelected].iY + 2 * (iTY - vGhosts[iSelected].iY);
 
  274BrainRedGhost::BrainRedGhost() : Brain() { sName = 
"Red-Fixed"; }
 
  275Sint32 BrainRedGhost::think(Actor* pActor, Sint32& iTX, Sint32& iTY, GameField* pGF) 
 
  277    return pGF->getObjectPosition(PME_OBJECT_PACMAN, iTX, iTY);
 
  280BrainEvolvedRedGhost::BrainEvolvedRedGhost(Sint32 iID) : BrainEvolved()
 
  285    if(iID > PME_GA_POPULATION)
 
  287        sName = 
"Red-Unknown";
 
  290    iNNInput = PME_ANN_GHOST_RED_INPUT;
 
  291    iNNOutput = PME_ANN_GHOST_OUTPUT;
 
  296        sName = 
"Red-" + sName;
 
  302        Main::Instance().ITool().intToStrDec(iID, sNumber);
 
  303        sName = 
"Red-Training";
 
  304        sName = sName + 
"-" + sNumber;
 
  307Sint32 BrainEvolvedRedGhost::think(Actor* pActor, Sint32& iTX, Sint32& iTY, GameField* pGF)
 
  310    vector<double> vInputs, vOutputs;
 
  313    if(pNeuralNet == 
nullptr) 
return 0;
 
  316    pGF->getObjectPosition(PME_OBJECT_PACMAN, iTX, iTY);
 
  321    dTmp = ((double)iTX / (
double)MAZE_WIDTH);
 
  322    vInputs.push_back(dTmp);
 
  323    dTmp = ((double)iTY / (
double)MAZE_HEIGHT);
 
  324    vInputs.push_back(dTmp);
 
  327    vOutputs = pNeuralNet->update(vInputs);
 
  331    if(!vOutputs.empty())
 
  333        iTX = (Sint32)Main::Instance().ITool().round(vOutputs[0] * MAZE_WIDTH);
 
  334        iTY = (Sint32)Main::Instance().ITool().round(vOutputs[1] * MAZE_HEIGHT);
 
  342BrainPinkGhost::BrainPinkGhost() : Brain() { sName = 
"PinkGhost-Fixed"; }
 
  343Sint32 BrainPinkGhost::think(Actor* pActor, Sint32& iTX, Sint32& iTY, GameField* pGF) 
 
  348    pGF->getObjectPosition(PME_OBJECT_PACMAN, iTX, iTY);
 
  349    pGF->getObjectDirection(PME_OBJECT_PACMAN, iDirX, iDirY);
 
  352    iTX = iTX + 4 * iDirX;
 
  353    iTY = iTY + 4 * iDirY;
 
  358BrainEvolvedPinkGhost::BrainEvolvedPinkGhost(Sint32 iID) : BrainEvolved()
 
  363    if(iID > PME_GA_POPULATION)
 
  365        sName = 
"Pink-Unknown";
 
  368    iNNInput = PME_ANN_GHOST_PINK_INPUT;
 
  369    iNNOutput = PME_ANN_GHOST_OUTPUT;
 
  374        sName = 
"Pink-" + sName;
 
  380        Main::Instance().ITool().intToStrDec(iID, sNumber);
 
  381        sName = 
"Pink-Training";
 
  382        sName = sName + 
"-" + sNumber;
 
  385Sint32 BrainEvolvedPinkGhost::think(Actor* pActor, Sint32& iTX, Sint32& iTY, GameField* pGF)
 
  388    vector<double> vInputs, vOutputs;
 
  392    if(pNeuralNet == 
nullptr) 
return 0;
 
  395    pGF->getObjectPosition(PME_OBJECT_PACMAN, iTX, iTY);
 
  396    pGF->getObjectDirection(PME_OBJECT_PACMAN, iDirX, iDirY);
 
  401    dTmp = ((double)iTX / (
double)MAZE_WIDTH);
 
  402    vInputs.push_back(dTmp);
 
  403    dTmp = ((double)iTY / (
double)MAZE_HEIGHT);
 
  404    vInputs.push_back(dTmp);
 
  405    dTmp = ((double)(iTX + 4 * iDirX) / (double)MAZE_HEIGHT);
 
  406    vInputs.push_back(dTmp);
 
  407    dTmp = ((double)(iTY + 4 * iDirY) / (double)MAZE_HEIGHT);
 
  408    vInputs.push_back(dTmp);
 
  411    vOutputs = pNeuralNet->update(vInputs);
 
  415    if(!vOutputs.empty())
 
  417        iTX = (Sint32)Main::Instance().ITool().round(vOutputs[0] * MAZE_WIDTH);
 
  418        iTY = (Sint32)Main::Instance().ITool().round(vOutputs[1] * MAZE_HEIGHT);
 
  426BrainBlueGhost::BrainBlueGhost() : Brain() { sName = 
"BlueGhost-Fixed"; }
 
  427Sint32 BrainBlueGhost::think(Actor* pActor, Sint32& iTX, Sint32& iTY, GameField* pGF) 
 
  429    Sint32 iDirX, iDirY, iGRX, iGRY;
 
  432    pGF->getObjectPosition(PME_OBJECT_PACMAN, iTX, iTY);
 
  433    pGF->getObjectDirection(PME_OBJECT_PACMAN, iDirX, iDirY);
 
  436    iTX = iTX + 2 * iDirX;
 
  437    iTY = iTY + 2 * iDirY;
 
  440    pGF->getObjectPosition(PME_OBJECT_GHOST_RED, iGRX, iGRY);
 
  443    iTX = iGRX + 2 * (iTX - iGRX);
 
  444    iTY = iGRY + 2 * (iTY - iGRY);
 
  450BrainEvolvedBlueGhost::BrainEvolvedBlueGhost(Sint32 iID) : BrainEvolved()
 
  455    if(iID > PME_GA_POPULATION)
 
  457        sName = 
"Blue-Unknown";
 
  460    iNNInput = PME_ANN_GHOST_BLUE_INPUT;
 
  461    iNNOutput = PME_ANN_GHOST_OUTPUT;
 
  466        sName = 
"Blue-" + sName;
 
  472        Main::Instance().ITool().intToStrDec(iID, sNumber);
 
  473        sName = 
"Blue-Training";
 
  474        sName = sName + 
"-" + sNumber;
 
  477Sint32 BrainEvolvedBlueGhost::think(Actor* pActor, Sint32& iTX, Sint32& iTY, GameField* pGF)
 
  480    vector<double> vInputs, vOutputs;
 
  484    if(pNeuralNet == 
nullptr) 
return 0;
 
  487    pGF->getObjectPosition(PME_OBJECT_PACMAN, iTX, iTY);
 
  488    pGF->getObjectPosition(PME_OBJECT_GHOST_RED, pointRed.iX, pointRed.iY);
 
  489    pActor->euclideanDistance(iTX, iTY, pointRed);
 
  494    dTmp = ((double)iTX / (
double)MAZE_WIDTH);
 
  495    vInputs.push_back(dTmp);
 
  496    dTmp = ((double)iTY / (
double)MAZE_HEIGHT);
 
  497    vInputs.push_back(dTmp);
 
  498    dTmp = pointRed.dDistance / 38.0; 
 
  499    vInputs.push_back(dTmp);
 
  502    vOutputs = pNeuralNet->update(vInputs);
 
  506    if(!vOutputs.empty())
 
  508        iTX = (Sint32)Main::Instance().ITool().round(vOutputs[0] * MAZE_WIDTH);
 
  509        iTY = (Sint32)Main::Instance().ITool().round(vOutputs[1] * MAZE_HEIGHT);
 
  517BrainOrangeGhost::BrainOrangeGhost() : Brain() { sName = 
"OrangeGhost-Fixed"; }
 
  518Sint32 BrainOrangeGhost::think(Actor* pActor, Sint32& iTX, Sint32& iTY, GameField* pGF) 
 
  521    MazePoint pointActor;
 
  524    pGF->getObjectPosition(PME_OBJECT_PACMAN, iPX, iPY);
 
  527    pActor->getPositionMaze(pointActor.iX, pointActor.iY);
 
  528    pActor->euclideanDistance(iPX, iPY, pointActor);
 
  531    if(pointActor.dDistance > 8)
 
  537    else reinterpret_cast<Ghost*
>(pActor)->getScatteringTarget(iTX, iTY);        
 
  543BrainEvolvedOrangeGhost::BrainEvolvedOrangeGhost(Sint32 iID) : BrainEvolved()
 
  548    if(iID > PME_GA_POPULATION)
 
  550        sName = 
"Orange-Unknown";
 
  553    iNNInput = PME_ANN_GHOST_ORANGE_INPUT;
 
  554    iNNOutput = PME_ANN_GHOST_OUTPUT;
 
  559        sName = 
"Orange-" + sName;
 
  565        Main::Instance().ITool().intToStrDec(iID, sNumber);
 
  566        sName = 
"Orange-Training";
 
  567        sName = sName + 
"-" + sNumber;
 
  570Sint32 BrainEvolvedOrangeGhost::think(Actor* pActor, Sint32& iTX, Sint32& iTY, GameField* pGF)
 
  573    vector<double> vInputs, vOutputs;
 
  574    MazePoint pointActor;
 
  577    if(pNeuralNet == 
nullptr) 
return 0;
 
  580    pGF->getObjectPosition(PME_OBJECT_PACMAN, iTX, iTY);
 
  581    pActor->getPositionMaze(pointActor.iX, pointActor.iY);
 
  582    pActor->euclideanDistance(iTX, iTY, pointActor);
 
  585    pGF->getClosestPellet(PME_OBJECT_PACMAN, iTX, iTY);
 
  590    dTmp = ((double)iTX / (
double)MAZE_WIDTH);
 
  591    vInputs.push_back(dTmp);
 
  592    dTmp = ((double)iTY / (
double)MAZE_HEIGHT);
 
  593    vInputs.push_back(dTmp);
 
  594    dTmp = pointActor.dDistance / 38.0; 
 
  595    vInputs.push_back(dTmp);
 
  598    vOutputs = pNeuralNet->update(vInputs);
 
  602    if(!vOutputs.empty())
 
  604        iTX = (Sint32)Main::Instance().ITool().round(vOutputs[0] * MAZE_WIDTH);
 
  605        iTY = (Sint32)Main::Instance().ITool().round(vOutputs[1] * MAZE_HEIGHT);