From 550caeee11086bd56db69176b3149ddfa160ee30 Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Sat, 17 Oct 2015 17:02:24 +0200 Subject: Reverted to a simple decision tree Turns out it's much easier to write a bot by hand with if statements. --- src/brain/neural_network.cpp | 110 ++++++++++++++++++++++---------------- src/brain/neuron.cpp | 14 ++++- src/game_state.cpp | 122 +++++++++++++++++++++---------------------- src/spacebot.cpp | 21 ++++++-- 4 files changed, 154 insertions(+), 113 deletions(-) (limited to 'src') diff --git a/src/brain/neural_network.cpp b/src/brain/neural_network.cpp index 0c23771..c8177e8 100644 --- a/src/brain/neural_network.cpp +++ b/src/brain/neural_network.cpp @@ -12,13 +12,13 @@ NeuralNetwork::NeuralNetwork(std::istream &&networkConfigFile, unsigned int numb for (unsigned int i=0; i(); - _sensors.push_back(sensor); + auto sensor = std::make_shared(i); + _sensors.push_back(sensor); } for (unsigned int i=0; i for (unsigned int i=0; i(); - sensor->setActivation(sensorInitialValues[i] ? 1 : 0); - _sensors.push_back(sensor); + auto sensor = std::make_shared(i); + sensor->setActivation(sensorInitialValues[i] ? 1 : 0); + _sensors.push_back(sensor); } for (unsigned int i=0; i> srcId && - file.ignore(std::numeric_limits::max(), 'n') && - file >> destId && - file >> weight && - file.ignore(std::numeric_limits::max(), '\n')) + file >> srcId && + file.ignore(std::numeric_limits::max(), 'n') && + file >> destId && + file >> weight && + file.ignore(std::numeric_limits::max(), '\n')) { + std::shared_ptr source; + std::shared_ptr destination; + switch (srcType) + { + case 's': + source = findOrAddSensor(srcId); + break; + case 'b': + source = _biasNode; + break; + default: + source = findOrAddNeuron(srcId); + } + destination = findOrAddNeuron(destId); - std::shared_ptr source; - std::shared_ptr destination; - switch (srcType) - { - case 's': - source = findOrAddSensor(srcId); - break; - case 'b': - source = _biasNode; - break; - default: - source = findOrAddNeuron(srcId); - } - destination = findOrAddNeuron(destId); - - addLink(source, destination, weight); + addLink(source, destination, weight); } } @@ -92,8 +91,8 @@ std::shared_ptr NeuralNetwork::findOrAddSensor(unsigned int id) { while (_sensors.size() <= id) { - auto sensor = std::make_shared(); - _sensors.push_back(sensor); + auto sensor = std::make_shared(_sensors.size()); + _sensors.push_back(sensor); } return _sensors.at(id); @@ -103,8 +102,8 @@ std::shared_ptr NeuralNetwork::findOrAddNeuron(unsigned int id) { while (_neurons.size() <= id) { - auto neuron = std::make_shared(); - _neurons.push_back(neuron); + auto neuron = std::make_shared(_neurons.size()); + _neurons.push_back(neuron); } return _neurons.at(id); @@ -121,12 +120,12 @@ unsigned int NeuralNetwork::findMaxOutputIndex() const auto maxIterations = _neurons.size()*10; for (unsigned int iteration=0; anyNodeChanged && iterationcalculateActivation(); - anyNodeChanged = anyNodeChanged || activationChanged; - } + anyNodeChanged = false; + for (auto const& neuron : _neurons) + { + bool activationChanged = neuron->calculateActivation(); + anyNodeChanged = anyNodeChanged || activationChanged; + } } int currentMaxIndex = 0; @@ -134,12 +133,31 @@ unsigned int NeuralNetwork::findMaxOutputIndex() const for (unsigned int i=1; i<_outputs.size(); ++i) { - double activation = _outputs.at(i)->activation(); - if (activation >= currentMaxActivation) - { - currentMaxActivation = activation; - currentMaxIndex = i; - } + double activation = _outputs.at(i)->activation(); + if (activation >= currentMaxActivation) + { + currentMaxActivation = activation; + currentMaxIndex = i; + } } return currentMaxIndex; } + +bool NeuralNetwork::linkExists(std::string srcIdentifier, std::string destIdentifier, double weight) const +{ + std::shared_ptr dest; + + for (auto const& node : _neurons) + { + if (node->identifier() == destIdentifier) + { + dest = node; + } + } + + if (!dest) + { + return false; + } + return dest->hasInputWithWeight(srcIdentifier, weight); +} diff --git a/src/brain/neuron.cpp b/src/brain/neuron.cpp index d1dd338..c7dba2c 100644 --- a/src/brain/neuron.cpp +++ b/src/brain/neuron.cpp @@ -12,7 +12,7 @@ bool Neuron::calculateActivation() double newActivation = 0; for (auto const& link : _inputLinks) { - newActivation += link.weightedActivation(); + newActivation += link.weightedActivation(); } newActivation = sigmoid(newActivation); @@ -26,3 +26,15 @@ void Neuron::addInput(NeuralLink&& link) { _inputLinks.push_back(std::move(link)); } + +bool Neuron::hasInputWithWeight(std::string srcIdentifier, double weight) const +{ + for (auto const& link : _inputLinks) + { + if (link.inputIdentifier() == srcIdentifier && link.weight() == weight) + { + return true; + } + } + return false; +} diff --git a/src/game_state.cpp b/src/game_state.cpp index 29bd75b..952c2f3 100644 --- a/src/game_state.cpp +++ b/src/game_state.cpp @@ -61,17 +61,17 @@ int GameState::addEntity(int x, int y, char type) _shields.push_back(Shield(x,y)); return 1; case Spaceship::ENEMY_MAP_CHAR: - _enemySpaceship = std::unique_ptr(new Spaceship(x+1, y)); - return 3; + _enemySpaceship = std::unique_ptr(new Spaceship(x+1, y)); + return 3; case Spaceship::PLAYER_MAP_CHAR: - _playerSpaceship = std::unique_ptr(new Spaceship(x+1, y)); + _playerSpaceship = std::unique_ptr(new Spaceship(x+1, y)); return 3; case Building::MISSILE_CONTROLLER_CHAR: - _missileControllers.push_back(Building(x+1, y)); - return 3; + _missileControllers.push_back(Building(x+1, y)); + return 3; case Building::ALIEN_FACTORY_CHAR: - _alienFactories.push_back(Building(x+1, y)); - return 3; + _alienFactories.push_back(Building(x+1, y)); + return 3; } return 1; } @@ -96,11 +96,11 @@ void GameState::logState() const } if (_playerSpaceship) { - std::cout << "Player Spaceship" << _playerSpaceship->coords() << std::endl; + std::cout << "Player Spaceship" << _playerSpaceship->coords() << std::endl; } if (_enemySpaceship) { - std::cout << "Enemy Spaceship" << _enemySpaceship->coords() << std::endl; + std::cout << "Enemy Spaceship" << _enemySpaceship->coords() << std::endl; } } @@ -110,25 +110,25 @@ int getPyramidOffset(int bottomWidth, int maxWidth, int x, int y, int resultIfLe int currentRowOffset = 0; for (int i=0; i maxWidth) - { - currentRowWidth = maxWidth; - } + currentRowOffset += currentRowWidth; + currentRowWidth += 2; + if (currentRowWidth > maxWidth) + { + currentRowWidth = maxWidth; + } } if (x > currentRowWidth/2) { - return resultIfRight; + return resultIfRight; } else if (x < -currentRowWidth/2) { - return resultIfLeft; + return resultIfLeft; } else { - return currentRowOffset + currentRowWidth/2 + x; + return currentRowOffset + currentRowWidth/2 + x; } } @@ -154,80 +154,80 @@ std::vector GameState::toBitArray() const int playerY = GAME_AREA_LINES-3; if (_playerSpaceship) { - playerX = _playerSpaceship->x(); + playerX = _playerSpaceship->x(); } for (auto const& alien : _aliens) { - if (alien.y() > playerY-4 || alien.y() < playerY-7 || alien.x() > playerX+4 || alien.x() < playerX-4) - { - continue; - } + if (alien.y() > playerY-4 || alien.y() < playerY-7 || alien.x() > playerX+4 || alien.x() < playerX-4) + { + continue; + } - result.at(alienOffset + getRectangularOffset(9, alien.x()-playerX, playerY-4-alien.y())) = true; + result.at(alienOffset + getRectangularOffset(9, alien.x()-playerX, playerY-4-alien.y())) = true; } for (auto const& bullet : _bullets) { - if (bullet.y() >= playerY || bullet.y() < playerY-3 || bullet.x() > playerX+2 || bullet.x() < playerX-2) - { - continue; - } + if (bullet.y() >= playerY || bullet.y() < playerY-3 || bullet.x() > playerX+2 || bullet.x() < playerX-2) + { + continue; + } - result.at(bulletOffset + getRectangularOffset(5, bullet.x()-playerX, playerY-1-bullet.y())) = true; + result.at(bulletOffset + getRectangularOffset(5, bullet.x()-playerX, playerY-1-bullet.y())) = true; } for (auto const& shield : _shields) { - if (shield.y() < playerY-3 || shield.x() < playerX-1 || shield.x() > playerX+1) - { - continue; - } + if (shield.y() < playerY-3 || shield.x() < playerX-1 || shield.x() > playerX+1) + { + continue; + } - result.at(shieldOffset + shield.x()-playerX+1) = true; + result.at(shieldOffset + shield.x()-playerX+1) = true; } if (_missiles.size() > 0) { - result.at(missileOffset) = true; + result.at(missileOffset) = true; } if (_missiles.size() < 1) { - result.at(missileOffset + 1) = true; + result.at(missileOffset + 1) = true; } if (_playerSpaceship) { - if (playerX <= GAME_WIDTH/3) - { - result.at(positionOffset) = true; - } - else if (playerX >= GAME_WIDTH*2/3) - { - result.at(positionOffset+2) = true; - } - else - { - result.at(positionOffset+1) = true; - } + if (playerX <= GAME_WIDTH/3) + { + result.at(positionOffset) = true; + } + else if (playerX >= GAME_WIDTH*2/3) + { + result.at(positionOffset+2) = true; + } + else + { + result.at(positionOffset+1) = true; + } } result.at(canBuildOffset) = true; for (auto const& missileController : _missileControllers) { - if (missileController.y() < playerY) - { - continue; - } - result.at(existingBuildingsOffset + 0) = true; - if (_missiles.size() < 2) - { - result.at(missileOffset+1) = true; - } - if (abs(missileController.x() - playerX) < 3) - { - result.at(canBuildOffset) = false; - } + if (missileController.y() < playerY) + { + continue; + } + result.at(existingBuildingsOffset + 0) = true; + if (_missiles.size() < 2) + { + result.at(missileOffset+1) = true; + } + if (abs(missileController.x() - playerX) < 3) + { + result.at(canBuildOffset) = false; + } } return result; diff --git a/src/spacebot.cpp b/src/spacebot.cpp index 15f2221..17d20b5 100644 --- a/src/spacebot.cpp +++ b/src/spacebot.cpp @@ -20,12 +20,23 @@ void Spacebot::writeNextMove() Move Spacebot::chooseMove() { auto sensorInputs = _gameState.toBitArray(); - - NeuralNetwork network(std::ifstream(_brainFilename), - sensorInputs, - 7); - return static_cast(network.findMaxOutputIndex()); + if (!sensorInputs.at(51) || !sensorInputs.at(53)) + { + return Move::BUILD_SHIELD; + } + else if (sensorInputs.at(55)) + { + return Move::SHOOT; + } + else if (sensorInputs.at(60) && !sensorInputs.at(59)) + { + return Move::BUILD_MISSILE_CONTROLLER; + } + else + { + return Move::NOTHING; + } } void Spacebot::writeMove(const Move& move) -- cgit v1.2.3