#include <iostream> #include "Game.h" #include "Types.h" Game::Game() : activeX(-1), activeY(-1) { reset(); } void Game::reset() { activeX = -1; activeY = -1; for(uint x = 0; x < 9; x++) { for(uint y = 0; y < 5; y++) { fields[x][y] = (y > 2 ? FieldState::WHITE : FieldState::BLACK); } } fields[0][2] = FieldState::WHITE; fields[2][2] = FieldState::WHITE; fields[4][2] = FieldState::EMPTY; fields[5][2] = FieldState::WHITE; fields[7][2] = FieldState::WHITE; } void Game::reset(String& output) { reset(); output.append("Fanorona Game\n\r"); print(output); output.append("Human Color: White(O)\n\rAIColor: Black(#)\n\rHuman turn\n\rselect stone: "); } 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(const String& input, String& output) { if(input.getLength() <= 2 || !isDigit(input[0]) || input[1] != ' ' || !isDigit(input[2])) { revertToSelection(output); return; } uint x = input[0] - '0'; uint y = input[2] - '0'; if(x >= 9 || y >= 6) { revertToSelection(output); return; } if(activeX == -1 || activeY == -1) { markActive(x, y, output); } else { move(x, y, output); } } bool Game::isDigit(char c) const { return c >= '0' && c <= '9'; } void Game::markActive(int x, int y, String& output) { if(fields[x][y] != FieldState::WHITE) { revertToSelection(output); return; } activeX = x; activeY = y; print(output); output.append("Human Color: White(O)\n\rAIColor: Black(#)\n\rselect location to move: "); } void Game::move(int x, int y, String& output) { if(fields[x][y] != FieldState::EMPTY || !areNeighbours(activeX, activeY, x, y)) { revertToSelection(output); return; } fields[activeX][activeY] = FieldState::EMPTY; fields[x][y] = FieldState::WHITE; removeLine(x, y, activeX, activeY, FieldState::BLACK); removeLine(activeX, activeY, x, y, FieldState::BLACK); activeX = x; activeY = y; print(output); output.append("Human Color: White(O)\n\rAIColor: Black(#)\n\r"); print(output); output.append("Human Color: White(O)\n\rAIColor: Black(#)\n\rAI turn\n\r"); activeX = -1; activeY = -1; botMove(output); } 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)); } void Game::revertToSelection(String& output) { activeX = -1; activeY = -1; print(output); output.append("Human Color: White(O)\n\rAIColor: Black(#)\n\rHuman turn\n\rselect stone: "); } void Game::removeLine(int x, int y, int x2, int y2, FieldState remove) { int diffX = x2 - x; int diffY = y2 - y; while(true) { x2 += diffX; y2 += diffY; if(x2 < 0 || x2 >= 9 || y2 < 0 || y2 >= 5 || fields[x2][y2] != remove) { return; } fields[x2][y2] = FieldState::EMPTY; } } void Game::botMove(String& output) { while(true) { int x = 0; int y = 0; while(true) { x = rand() % 9; y = rand() % 5; if(fields[x][y] == FieldState::EMPTY) { break; } } for(uint i = 0; i < 10; i++) { int mx = x + (rand() % 3) - 1; int my = y + (rand() % 3) - 1; if((mx == x && my == y) || mx < 0 || mx >= 9 || my < 0 || my >= 5 || fields[mx][my] != FieldState::BLACK) { continue; } fields[mx][my] = FieldState::EMPTY; fields[x][y] = FieldState::BLACK; removeLine(mx, my, x, y, FieldState::WHITE); removeLine(x, y, mx, my, FieldState::WHITE); activeX = x; activeY = y; print(output); activeX = -1; activeY = -1; print(output); revertToSelection(output); return; } } }