123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- #include <iostream>
- #include <climits>
- #include "Game.h"
- #include "Types.h"
- std::array<Vector, 8> Game::neighbours;
- std::array<Vector, 9 * 5> Game::fieldVectors;
- Game::Game() : active(-1, -1), mustTake(false) {
-
-
-
-
- std::cout << "0\n1\n0\n";
-
-
- neighbours[0].set(1, 0);
- neighbours[1].set(0, 1);
- neighbours[2].set(-1, 0);
- neighbours[3].set(0, -1);
- neighbours[4].set(1, 1);
- neighbours[5].set(-1, 1);
- neighbours[6].set(1, -1);
- neighbours[7].set(-1, -1);
-
- uint index = 0;
- for(uint y = 0; y < 5; y++) {
- for(uint x = 0; x < 9; x++) {
- fieldVectors[index++].set(x, y);
- }
- }
- }
- void Game::readLine() {
- String line;
- while(true) {
-
- char c = std::cin.get();
- if(c == '\n') {
-
- if(parseLine(line)) {
- return;
- }
-
- line.clear();
- } else if(c != '\r') {
-
- line.append(c);
- }
- }
- }
- bool Game::parseLine(const String& line) {
-
- if(line == " 0 1 2 3 4 5 6 7 8") {
- fields.read();
- fields.print(active);
- } else if(line == "Please enter origin x-axis") {
- makeSelection();
- } else if(line == "Please enter destination x-axis") {
- makeMove();
- } else if(line == "Please enter wether you want to Withdraw or Approach [W/A]") {
- takeStone();
- } else if(line == "Do you want to continue with your turn [Y/N]?") {
-
- std::cout << "Y\n";
- } else if(line == "************************Player 1 won!**********************" ||
- line == "************************Player 2 won!**********************") {
-
- std::cerr << line << "\n";
- return true;
- }
- return false;
- }
- bool Game::isInRange(const Vector& v) const {
- return v.x >= 0 && v.x <= 8 && v.y >= 0 && v.y <= 4;
- }
- bool Game::areNeighbors(const Vector& from, const Vector& to) const {
-
- if(from == to) {
- return false;
- }
- Vector diff = from - to;
-
- if(diff.x < -1 || diff.x > 1 || diff.y < -1 || diff.y > 1) {
- return false;
- }
-
- if(diff.x == 0 || diff.y == 0) {
- return true;
- }
-
- return (from.x & 1) == (from.y & 1);
- }
- uint Game::removeLine(const Vector& from, const Vector& to, Fields::State state) {
-
- Vector current = to;
- Vector unit = to - from;
-
- uint rank = 0;
- while(true) {
- current += unit;
-
- if(!isInRange(current) || !fields.hasState(current, state)) {
- return rank;
- }
- fields.setState(current, Fields::EMPTY);
- rank++;
- }
- }
- uint Game::getRank(const Vector& from, const Vector& to, Fields::State state) const {
-
- Vector current = to;
- Vector unit = to - from;
- uint rank = 0;
- while(true) {
- current += unit;
- if(!isInRange(current) || !fields.hasState(current, state)) {
- return rank;
- }
- rank++;
- }
- }
- uint Game::getStoneTakes(const Vector& from, const Vector& to) const {
-
- if(!isInRange(to) || !fields.hasState(to, Fields::EMPTY) || !areNeighbors(from, to) ||
- lastLocations.contains(to) || (to - from) == direction) {
- return 0;
- }
-
- Fields::State enemy = (fields.hasState(from, Fields::BLACK) ? Fields::WHITE : Fields::BLACK);
- if(getRank(from, to, enemy) == 0 && getRank(to, from, enemy) == 0) {
- return 0;
- }
-
- Game copy = *this;
- uint rank = copy.move(from, to);
-
- uint maxRank = 0;
- for(Vector& m : neighbours) {
- uint rank = copy.getStoneTakes(to, to + m);
- if(rank > maxRank) {
- maxRank = rank;
- }
- }
- return rank + maxRank;
- }
- uint Game::getStoneFreedom(const Vector& from, Fields::State state) const {
-
- if(!fields.hasState(from, state)) {
- return 0;
- }
-
- uint counter = 0;
- for(const Vector& m : neighbours) {
- Vector to = from + m;
- if(isInRange(to) && areNeighbors(from, to) && fields.hasState(to, Fields::EMPTY)) {
- counter++;
- }
- }
- return counter;
- }
- uint Game::getFreedom(Fields::State state) const {
- uint sum = 0;
- for(const Vector& v : fieldVectors) {
- sum += getStoneFreedom(v, state);
- }
- return sum;
- }
- uint Game::move(const Vector& from, const Vector& to) {
-
- direction = to - from;
-
- lastLocations.add(from);
-
- fields.setState(to, fields.getState(from));
- fields.setState(from, Fields::EMPTY);
-
- Fields::State enemy = (fields.hasState(to, Fields::BLACK) ? Fields::WHITE : Fields::BLACK);
-
- uint rankA = getRank(from, to, enemy);
- uint rankB = getRank(to, from, enemy);
- if(rankA >= rankB) {
- return removeLine(from, to, enemy);
- }
- return removeLine(to, from, enemy);
- }
- void Game::makeSelection() {
-
- lastLocations.clear();
- direction.set(0, 0);
-
- mustTake = isTakingPossible();
-
- Vector selection(0, 0);
- int maxRank = INT_MIN;
- for(Vector& to : fieldVectors) {
- if(!fields.hasState(to, Fields::EMPTY)) {
- continue;
- }
-
- for(Vector& m : neighbours) {
- Vector from = to + m;
-
- if(!isInRange(from) || !fields.hasState(from, Fields::WHITE) || !areNeighbors(from, to)) {
- continue;
- }
-
- if(mustTake && getRank(from, to, Fields::BLACK) + getRank(to, from, Fields::BLACK) == 0) {
- continue;
- }
-
- int rank = getQuality(from, to);
- if(rank > maxRank) {
- maxRank = rank;
- selection = from;
- }
- }
- }
-
- active = selection;
-
- std::cerr << "Selecting (" << selection.x << ", " << selection.y << ")\n";
-
- fields.print(active);
- std::cout << selection.x << "\n" << selection.y << "\n";
- }
- void Game::makeMove() {
-
- Vector maxTo(0, 0);
- int maxRank = INT_MIN;
- for(Vector& m : neighbours) {
- Vector to = active + m;
-
- if(!isInRange(to) || !fields.hasState(to, Fields::EMPTY) || lastLocations.contains(to) ||
- !areNeighbors(active, to) || m == direction) {
- continue;
- }
-
- if(!lastLocations.isEmpty() || mustTake) {
- int rank = getRank(active, to, Fields::BLACK) + getRank(to, active, Fields::BLACK);
- if(rank == 0) {
- continue;
- }
- }
-
- int rank = getQuality(active, to);
- if(rank > maxRank) {
- maxRank = rank;
- maxTo = to;
- }
- }
-
- lastLocations.add(active);
-
- direction = maxTo - active;
-
- active = maxTo;
-
- std::cerr << "Move to (" << maxTo.x << ", " << maxTo.y << ")\n";
-
- std::cout << maxTo.x << "\n" << maxTo.y << "\n";
- }
- void Game::takeStone() {
-
- uint rankA = getRank(active, active + direction, Fields::BLACK);
- uint rankB = getRank(active + direction, active, Fields::BLACK);
-
- if(rankA >= rankB) {
- std::cout << "W\n";
- } else {
- std::cout << "A\n";
- }
- }
- int Game::getQuality(const Vector& from, const Vector& to) const {
-
- int quality = getStoneTakes(from, to);
-
- Game copy = *this;
- copy.move(from, to);
-
- copy.lastLocations.clear();
- copy.direction.set(0, 0);
-
- int whiteFreedom = copy.getFreedom(Fields::WHITE);
- int blackFreedom = copy.getFreedom(Fields::BLACK);
-
- uint maxRank = copy.getBestEnemyRank();
-
- int black = countBlack();
- if(black >= 8) {
- black = 1;
- }
-
- return quality - maxRank * black + (whiteFreedom - blackFreedom) / 4;
- }
- int Game::countBlack() const {
- int counter = 0;
- for(Vector& v : fieldVectors) {
- counter += fields.hasState(v, Fields::BLACK);
- }
- return counter;
- }
- bool Game::isTakingPossible() const {
-
- for(Vector& to : fieldVectors) {
- if(!fields.hasState(to, Fields::EMPTY)) {
- continue;
- }
-
- for(Vector& m : neighbours) {
- Vector from = to + m;
- if(!isInRange(from) || !areNeighbors(from, to) || !fields.hasState(from, Fields::WHITE)) {
- continue;
- }
-
- if(getRank(from, to, Fields::BLACK) + getRank(to, from, Fields::BLACK) > 0) {
- return true;
- }
- }
- }
- return false;
- }
- uint Game::getBestEnemyRank() const {
- uint maxRank = 0;
-
- for(Vector& to : fieldVectors) {
- if(!fields.hasState(to, Fields::EMPTY)) {
- continue;
- }
-
- for(Vector& m : neighbours) {
- Vector from = to + m;
-
- if(!isInRange(from) || !fields.hasState(from, Fields::BLACK)) {
- continue;
- }
-
- uint rank = getStoneTakes(from, to);
- if(rank > maxRank) {
- maxRank = rank;
- }
- }
- }
- return maxRank;
- }
|