From 70ec00285128f8f9f5fa0e848950212e6a235d43 Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Fri, 14 Aug 2015 22:12:56 +0200 Subject: Added missing sensors --- CMakeLists.txt | 2 +- include/brain/neural_network.h | 4 +-- include/brain/neural_node.h | 1 - include/brain/neuron.h | 4 +-- include/building.h | 12 +++++++ include/game_state.h | 10 ++++-- src/brain/neural_network.cpp | 81 ++++++++++++++++++++---------------------- src/brain/neuron.cpp | 7 ++-- src/building.cpp | 6 ++++ src/game_state.cpp | 77 ++++++++++++++++++++++++++++++++++----- src/spacebot.cpp | 6 ++-- 11 files changed, 143 insertions(+), 67 deletions(-) create mode 100644 include/building.h create mode 100644 src/building.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a84f19..fd6a32d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.2.2) project(Spacebot) -set(CMAKE_CXX_FLAGS "-std=c++11") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wpedantic -Wextra") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) diff --git a/include/brain/neural_network.h b/include/brain/neural_network.h index 22e5e42..f75fdea 100644 --- a/include/brain/neural_network.h +++ b/include/brain/neural_network.h @@ -26,8 +26,8 @@ public: private: std::map> _sensors; std::shared_ptr _biasNode; - std::map> _hiddenNodes; - std::map> _outputs; + std::map> _neurons; + std::vector> _outputs; void parseFile(std::istream &&file); diff --git a/include/brain/neural_node.h b/include/brain/neural_node.h index 3c2a6cb..c7b4335 100644 --- a/include/brain/neural_node.h +++ b/include/brain/neural_node.h @@ -4,7 +4,6 @@ class NeuralNode { public: NeuralNode(char type, int id); - virtual ~NeuralNode() {}; virtual double activation() const = 0; diff --git a/include/brain/neuron.h b/include/brain/neuron.h index 810ce5b..d017b0d 100644 --- a/include/brain/neuron.h +++ b/include/brain/neuron.h @@ -13,9 +13,9 @@ public: virtual ~Neuron() {} virtual double activation() const; - void addInput(std::shared_ptr link); + void addInput(std::unique_ptr&& link); private: - std::vector> _inputLinks; + std::vector> _inputLinks; double sigmoid(double input) const; }; diff --git a/include/building.h b/include/building.h new file mode 100644 index 0000000..76d78fd --- /dev/null +++ b/include/building.h @@ -0,0 +1,12 @@ +#pragma once + +#include "game_entity.h" + +class Building : public GameEntity +{ +public: + Building(int x, int y); + const static char MISSILE_CONTROLLER_CHAR = 'M'; + const static char ALIEN_FACTORY_CHAR = 'X'; +}; + diff --git a/include/game_state.h b/include/game_state.h index 880557e..c129d28 100644 --- a/include/game_state.h +++ b/include/game_state.h @@ -5,6 +5,7 @@ #include "player_missile.h" #include "shield.h" #include "spaceship.h" +#include "building.h" #include #include #include @@ -14,12 +15,14 @@ class GameState { public: GameState(std::istream &&mapFile); - void logState(); + void logState() const; const std::vector& aliens() const { return _aliens; } const std::vector& bullets() const { return _bullets; } const std::vector& missiles() const { return _missiles; } const std::vector& shields() const { return _shields; } + const std::vector& missileControllers() const { return _missileControllers; } + const std::vector& alienFactories() const { return _alienFactories; } const std::unique_ptr& playerSpaceship() const { return _playerSpaceship; } const std::unique_ptr& enemySpaceship() const { return _enemySpaceship; } @@ -31,8 +34,11 @@ private: std::vector _bullets; std::vector _missiles; std::vector _shields; + std::vector _missileControllers; + std::vector _alienFactories; + std::unique_ptr _playerSpaceship; std::unique_ptr _enemySpaceship; - + int addEntity(int x, int y, char type); }; diff --git a/src/brain/neural_network.cpp b/src/brain/neural_network.cpp index d6a5e15..9061194 100644 --- a/src/brain/neural_network.cpp +++ b/src/brain/neural_network.cpp @@ -1,5 +1,6 @@ #include "brain/neural_network.h" #include "brain/neuron.h" +#include NeuralNetwork::NeuralNetwork(std::istream &&networkConfigFile, int numberOfSensors, int numberOfOutputs) { @@ -11,7 +12,9 @@ NeuralNetwork::NeuralNetwork(std::istream &&networkConfigFile, int numberOfSenso } for (int i=0; i(i); + auto output = std::make_shared(i); + _outputs.push_back(output); + _neurons[i] = output; } parseFile(std::move(networkConfigFile)); @@ -21,15 +24,17 @@ NeuralNetwork::NeuralNetwork(std::istream &&networkConfigFile, std::vector { _biasNode = std::make_shared(); - for (int i=0; i(i); - sensor->setActivation(sensorInitialValues.at(i) ? 1 : 0); + sensor->setActivation(sensorInitialValues[i] ? 1 : 0); _sensors[i] = sensor; } for (int i=0; i(i); + auto output = std::make_shared(i); + _outputs.push_back(output); + _neurons[i] = output; } parseFile(std::move(networkConfigFile)); @@ -38,14 +43,18 @@ NeuralNetwork::NeuralNetwork(std::istream &&networkConfigFile, std::vector void NeuralNetwork::parseFile(std::istream &&file) { double weight; - for (std::string src, dest; - file >> src && file >> dest && file >> weight; ) - { - char srcType = src.at(0); - int srcId = std::stoi(src.substr(1)); - char destType = dest.at(0); - int destId = std::stoi(dest.substr(1)); + char srcType; + int srcId; + int destId; + while (file.get(srcType) && + 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) @@ -56,21 +65,11 @@ void NeuralNetwork::parseFile(std::istream &&file) case 'b': source = _biasNode; break; - case 'n': - source = findOrAddNeuron(srcId); - break; default: - throw 1; - } - switch (destType) - { - case 'n': - destination = findOrAddNeuron(destId); - break; - default: - throw 1; + source = findOrAddNeuron(srcId); } - + destination = findOrAddNeuron(destId); + addLink(source, destination, weight); } @@ -78,34 +77,30 @@ void NeuralNetwork::parseFile(std::istream &&file) void NeuralNetwork::addLink(std::shared_ptr source, std::shared_ptr destination, double weight) { - auto link = std::make_shared(source, weight); - destination->addInput(link); + std::unique_ptr link(new NeuralLink(source, weight)); + destination->addInput(std::move(link)); } std::shared_ptr NeuralNetwork::findOrAddSensor(int id) { - bool sensorExists = _sensors.count(id) > 0; - if (!sensorExists) + auto sensor = _sensors[id]; + if (!sensor) { - _sensors[id] = std::make_shared(id); + sensor = std::make_shared(id); + _sensors[id] = sensor; } - return _sensors.at(id); + return sensor; } std::shared_ptr NeuralNetwork::findOrAddNeuron(int id) { - bool isOutput = _outputs.count(id) > 0; - if (isOutput) - { - return _outputs.at(id); - } - - bool hiddenNeuronExists = _hiddenNodes.count(id) > 0; - if (!hiddenNeuronExists) + auto neuron = _neurons[id]; + if (!neuron) { - _hiddenNodes[id] = std::make_shared(id); + neuron = std::make_shared(id); + _neurons[id] = neuron; } - return _hiddenNodes.at(id); + return neuron; } void NeuralNetwork::setInput(int inputIndex, double activation) @@ -117,13 +112,13 @@ int NeuralNetwork::findMaxOutputIndex() const { double currentMaxActivation = 0; int currentMaxIndex = 0; - for (std::pair> outputPair : _outputs) + for (unsigned int i=0; i<_outputs.size(); ++i) { - double activation = outputPair.second->activation(); + double activation = _outputs[i]->activation(); if (activation >= currentMaxActivation) { currentMaxActivation = activation; - currentMaxIndex = outputPair.first; + currentMaxIndex = i; } } return currentMaxIndex; diff --git a/src/brain/neuron.cpp b/src/brain/neuron.cpp index 7ea02c6..527e7da 100644 --- a/src/brain/neuron.cpp +++ b/src/brain/neuron.cpp @@ -9,21 +9,20 @@ Neuron::Neuron(int id) double Neuron::sigmoid(double input) const { double slope = 4.924273; - double constant = 2.4621365; return (1/(1+(std::exp(-(slope*input))))); } double Neuron::activation() const { double activationSum = 0; - for (auto link : _inputLinks) + for (auto const& link : _inputLinks) { activationSum += link->weightedActivation(); } return sigmoid(activationSum); } -void Neuron::addInput(std::shared_ptr link) +void Neuron::addInput(std::unique_ptr&& link) { - _inputLinks.push_back(link); + _inputLinks.push_back(std::move(link)); } diff --git a/src/building.cpp b/src/building.cpp new file mode 100644 index 0000000..8da322d --- /dev/null +++ b/src/building.cpp @@ -0,0 +1,6 @@ +#include "building.h" + +Building::Building(int x, int y) + :GameEntity(x, y) +{ +} diff --git a/src/game_state.cpp b/src/game_state.cpp index a302bfc..eb02005 100644 --- a/src/game_state.cpp +++ b/src/game_state.cpp @@ -3,6 +3,7 @@ #include #include #include +#include const int OPENING_LINES = 6; const int GAME_AREA_LINES = 25; @@ -65,25 +66,31 @@ int GameState::addEntity(int x, int y, char type) case Spaceship::PLAYER_MAP_CHAR: _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; + case Building::ALIEN_FACTORY_CHAR: + _alienFactories.push_back(Building(x+1, y)); + return 3; } return 1; } -void GameState::logState() +void GameState::logState() const { - for (auto alien : _aliens) + for (auto const& alien : _aliens) { std::cout << "Alien " << alien.coords() << std::endl; } - for (auto bullet : _bullets) + for (auto const& bullet : _bullets) { std::cout << "Enemy Bullet" << bullet.coords() << std::endl; } - for (auto missile : _missiles) + for (auto const& missile : _missiles) { std::cout << "Player Missile" << missile.coords() << std::endl; } - for (auto shield : _shields) + for (auto const& shield : _shields) { std::cout << "Shield" << shield.coords() << std::endl; } @@ -129,7 +136,7 @@ int getRectangularOffset(int width, int x, int y) std::vector GameState::toBitArray() const { - std::vector result(171); + std::vector result(172); int alienOffset = 0; //Aliens are 0 to 100 int bulletOffset = 101; //Bullets are 101 to 135 @@ -147,7 +154,7 @@ std::vector GameState::toBitArray() const } - for (auto alien : _aliens) + for (auto const& alien : _aliens) { if (alien.y() >= playerY || alien.y() < playerY-9) { @@ -157,7 +164,7 @@ std::vector GameState::toBitArray() const result.at(alienOffset + getPyramidOffset(3, alien.x()-playerX, playerY-1-alien.y(), 99, 100)) = true; } - for (auto bullet : _bullets) + for (auto const& bullet : _bullets) { if (bullet.y() >= playerY || bullet.y() < playerY-5 || bullet.x() > playerX+3 || bullet.x() < playerX-3) { @@ -166,6 +173,60 @@ std::vector GameState::toBitArray() const result.at(bulletOffset + getRectangularOffset(7, bullet.x()-playerX, playerY-1-bullet.y())) = true; } + + for (auto const& shield : _shields) + { + if (shield.y() < playerY-3 || shield.x() < playerX-2 || shield.x() > playerX+2) + { + continue; + } + + result.at(shieldOffset + getRectangularOffset(5, shield.x()-playerX, playerY-1-shield.y())) = true; + } + + if (_missiles.size() > 0) + { + result.at(missileOffset) = true; + } + if (_missiles.size() < 1) + { + result.at(missileOffset + 1) = true; + } + + if (_playerSpaceship) + { + result.at(positionOffset + playerX-2) = 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; + } + } + for (auto const& alienFactory : _alienFactories) + { + if (alienFactory.y() < playerY) + { + continue; + } + result.at(existingBuildingsOffset + 1) = true; + if (abs(alienFactory.x() - playerX) < 3) + { + result.at(canBuildOffset) = false; + } + } return result; } diff --git a/src/spacebot.cpp b/src/spacebot.cpp index 23cce0c..15f2221 100644 --- a/src/spacebot.cpp +++ b/src/spacebot.cpp @@ -20,14 +20,12 @@ void Spacebot::writeNextMove() Move Spacebot::chooseMove() { auto sensorInputs = _gameState.toBitArray(); - std::cout << sensorInputs.size() << std::endl; NeuralNetwork network(std::ifstream(_brainFilename), sensorInputs, - static_cast(Move::BUILD_SHIELD)); + 7); - int moveInt = network.findMaxOutputIndex(); - return static_cast(moveInt); + return static_cast(network.findMaxOutputIndex()); } void Spacebot::writeMove(const Move& move) -- cgit v1.2.3