#include #include "Game.h" #include "Types.h" Game::Game() : activeX(-1), activeY(-1), directionX(0), directionY(0), lastLocation(0) { } void Game::print(String& s) const { s.append("\n\r 0 1 2 3 4 5 6 7 8\n\r"); printLine(s, 0); s.append(" |\\|/|\\|/|\\|/|\\|/|\n\r"); printLine(s, 1); s.append(" |/|\\|/|\\|/|\\|/|\\|\n\r"); printLine(s, 2); s.append(" |\\|/|\\|/|\\|/|\\|/|\n\r"); printLine(s, 3); s.append(" |/|\\|/|\\|/|\\|/|\\|\n\r"); printLine(s, 4); s.append("\n\r"); } void Game::printLine(String& s, int index) const { static const char map[] = { '#', 'O', '.' }; s.append(index + '0').append(' '); for(int x = 0; x < 8; x++) { if(x == activeX && index == activeY) { s.append("*-"); continue; } s.append(map[fields[x][index]]).append('-'); } if(8 == activeX && index == activeY) { s.append('*'); } else { s.append(map[fields[8][index]]); } s.append("\n\r"); } void Game::parse() { String s; while(true) { char c = std::cin.get(); if(c == '0') { parseFields(); continue; } if(c == '\n' || c == '\r') { std::cerr << s << "\n"; s.clear(); continue; } s.append(c); if(s == "select stone:") { std::cerr << s; s.clear(); selectStone(); } else if(s == "select location to move:") { std::cerr << s; s.clear(); selectLocationToMove(); } else if(s == "select stone to take:") { std::cerr << s; s.clear(); selectStoneToTake(); } } } void Game::consumeLine() const { while(std::cin.get() != '\n'); while(true) { char c = std::cin.peek(); if(c != '\r') { break; } std::cin.get(); } } void Game::consumeLine(uint index) { std::cin.get(); std::cin.get(); for(uint i = 0; i < 9; i++) { char c = std::cin.get(); if(c == '#') { fields[i][index] = BLACK; } else if(c == '.') { fields[i][index] = EMPTY; } else if(c == 'O') { fields[i][index] = WHITE; } else if(c == '*') { activeX = i; activeY = index; fields[i][index] = WHITE; } else { std::cerr << "game field parsing error\n"; } std::cin.get(); } } void Game::parseFields() { for(uint i = 0; i < 5; i++) { consumeLine(); consumeLine(i); } String s; print(s); std::cerr << s; } void Game::selectStone() { lastLocation = 0; directionX = 0; directionY = 0; Location from; int rank = -1; for(int bx = 0; bx < 9; bx++) { for(int by = 0; by < 5; by++) { if(fields[bx][by] != EMPTY) { continue; } for(int mx = -1; mx <= 1; mx++) { for(int my = -1; my <= 1; my++) { int x = bx + mx; int y = by + my; if((mx == 0 && my == 0) || !isInRange(x, y) || !areNeighbours(bx, by, x, y) || fields[x][y] != WHITE) { continue; } int rankA = getRank(bx, by, x, y); int rankB = getRank(x, y, bx, by); if(rankA > rank) { rank = rankA; from = {x, y}; } if(rankB > rank) { rank = rankB; from = {x, y}; } } } } } std::cout << from.x << " " << from.y << "\n"; } void Game::selectLocationToMove() { Location to; int rank = -1; for(int mx = -1; mx <= 1; mx++) { for(int my = -1; my <= 1; my++) { int x = activeX + mx; int y = activeY + my; if((mx == 0 && my == 0) || (mx == directionX && my == directionY) || !isInRange(x, y) || !areNeighbours(activeX, activeY, x, y) || fields[x][y] != EMPTY || isInQueue(x, y)) { continue; } int rankA = getRank(x, y, activeX, activeY); int rankB = getRank(activeX, activeY, x, y); if(rankA > rank) { rank = rankA; to = {x, y}; } if(rankB > rank) { rank = rankB; to = {x, y}; } } } addLocation(activeX, activeY); directionX = to.x - activeX; directionY = to.y - activeY; std::cout << to.x << " " << to.y << "\n"; } void Game::selectStoneToTake() { int rankA = getRank(activeX, activeY, activeX + directionX, activeY + directionY); int rankB = getRank(activeX + directionX, activeY + directionY, activeX, activeY); if(rankA > rankB) { std::cout << (activeX + directionX * 2) << " " << (activeY + directionY * 2) << "\n"; } else { std::cout << (activeX - directionX) << " " << (activeY - directionY) << "\n"; } } bool Game::isInRange(int x, int y) const { return x >= 0 && x <= 8 && y >= 0 && y <= 4; } bool Game::areNeighbours(int x, int y, int x2, int y2) const { if(x == x2 && y == y2) { return false; } int diffX = x - x2; int diffY = y - y2; if(diffX < -1 || diffX > 1 || diffY < -1 || diffY > 1) { return false; } if(diffX == 0 || diffY == 0) { return true; } return !((x & 1) ^ (y & 1)); } int Game::getRank(int x, int y, int x2, int y2) const { int diffX = x2 - x; int diffY = y2 - y; int rank = 0; while(true) { x2 += diffX; y2 += diffY; if(!isInRange(x2, y2) || fields[x2][y2] != BLACK) { return rank; } rank++; } } void Game::addLocation(int x, int y) { if(lastLocation >= lastLocations.size()) { // safely to ignore, such long turns will never happen return; } lastLocations[lastLocation].x = x; lastLocations[lastLocation].y = y; lastLocation++; } bool Game::isInQueue(int x, int y) const { for(uint i = 0; i < lastLocation; i++) { if(lastLocations[i].x == x && lastLocations[i].y == y) { return true; } } return false; }