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);