Browse Source

player is forced to choose which side to take if there are two options

Kajetan Johannes Hammerle 3 years ago
parent
commit
cf7635c781
4 changed files with 108 additions and 9 deletions
  1. 4 1
      Client.cpp
  2. 85 3
      Game.cpp
  3. 10 3
      Game.h
  4. 9 2
      Main.cpp

+ 4 - 1
Client.cpp

@@ -55,7 +55,10 @@ void Client::loop() {
             break;
         }
         String output;
-        game.parse(buffer, output);
+        if(game.parse(buffer, output)) {
+            sendString(output);
+            break;
+        }
         sendString(output);
     }
     std::cout << "client removed\n";

+ 85 - 3
Game.cpp

@@ -20,6 +20,10 @@ void Game::reset() {
     fields[4][2] = EMPTY;
     fields[5][2] = WHITE;
     fields[7][2] = WHITE;
+
+    fields[2][0] = WHITE;
+    fields[1][0] = EMPTY;
+    fields[1][1] = EMPTY;
 }
 
 void Game::reset(String& output) {
@@ -72,7 +76,7 @@ bool Game::parseLocation(const String& input, int& x, int& y) {
     return x >= 9 || y >= 6;
 }
 
-void Game::parse(const String& input, String& output) {
+bool Game::parse(const String& input, String& output) {
     switch(state) {
         case SELECTION:
             parseSelection(input, output);
@@ -83,7 +87,11 @@ void Game::parse(const String& input, String& output) {
         case ANOTHER_MOVE:
             parseAnotherMove(input, output);
             break;
+        case REMOVE_SELECTION:
+            parseRemoveSelection(input, output);
+            break;
     }
+    return shouldEnd();
 }
 
 void Game::parseSelection(const String& input, String& output) {
@@ -124,6 +132,14 @@ void Game::parseMove(const String& input, String& output) {
         output.append("Human Color: White(O)\n\rAIColor: Black(#)\n\rselect location to move: ");
         return;
     }
+    directionX = x - activeX;
+    directionY = y - activeY;
+    if(markHitSides(activeX, activeY, x, y, BLACK)) {
+        state = REMOVE_SELECTION;
+        print(output);
+        output.append("Human Color: White(O)\n\rAIColor: Black(#)\n\rselect stone to take: ");
+        return;
+    }
     lastLocation = 0;
     move(activeX, activeY, x, y);
 
@@ -157,6 +173,14 @@ void Game::parseAnotherMove(const String& input, String& output) {
         output.append("Human Color: White(O)\n\rAIColor: Black(#)\n\rselect location to move: ");
         return;
     }
+    directionX = x - activeX;
+    directionY = y - activeY;
+    if(markHitSides(activeX, activeY, x, y, BLACK)) {
+        state = REMOVE_SELECTION;
+        print(output);
+        output.append("Human Color: White(O)\n\rAIColor: Black(#)\n\rselect stone to take: ");
+        return;
+    }
     move(activeX, activeY, x, y);
 
     bool removed = false;
@@ -179,10 +203,43 @@ void Game::parseAnotherMove(const String& input, String& output) {
     botMove(output);
 }
 
+void Game::parseRemoveSelection(const String& input, String& output) {
+    int x;
+    int y;
+    if(parseLocation(input, x, y) || !((hitA.x == x && hitA.y == y) || (hitB.x == x && hitB.y == y))) {
+        output.append("invalid take location.\n\r");
+        print(output);
+        output.append("Human Color: White(O)\n\rAIColor: Black(#)\n\rselect stone to take: ");
+        return;
+    }
+    int mx = activeX + directionX;
+    int my = activeY + directionY;
+
+    move(activeX, activeY, mx, my);
+
+    if(mx + directionX == x && my + directionY == y) {
+        removeLine(activeX, activeY, mx, my, BLACK);
+    } else {
+        removeLine(mx, my, activeX, activeY, BLACK);
+    }
+
+    activeX = mx;
+    activeY = my;
+    print(output);
+    if(isAnotherTurnPossible()) {
+        state = ANOTHER_MOVE;
+        output.append("Human Color: White(O)\n\rAIColor: Black(#)\n\rselect location to move: ");
+        return;
+    }
+    state = SELECTION;
+    output.append("Human Color: White(O)\n\rAIColor: Black(#)\n\rAI turn\n\r");
+    activeX = -1;
+    activeY = -1;
+    botMove(output);
+}
+
 void Game::move(int fromX, int fromY, int toX, int toY) {
     addLocation(fromX, fromY);
-    directionX = toX - fromX;
-    directionY = toY - fromY;
     fields[fromX][fromY] = EMPTY;
     fields[toX][toY] = WHITE;
 }
@@ -233,6 +290,9 @@ bool Game::removeLine(int x, int y, int x2, int y2, FieldState remove) {
 }
 
 void Game::botMove(String& output) {
+    if(shouldEnd()) {
+        return;
+    }
     while(true) {
         int x = 0;
         int y = 0;
@@ -299,4 +359,26 @@ bool Game::isAnotherTurnPossible() const {
     return canMoveActiveStoneTo(-1, -1) || canMoveActiveStoneTo(0, -1) || canMoveActiveStoneTo(1, -1) ||
             canMoveActiveStoneTo(-1, 0) || canMoveActiveStoneTo(1, 0) ||
             canMoveActiveStoneTo(-1, 1) || canMoveActiveStoneTo(0, 1) || canMoveActiveStoneTo(1, 1);
+}
+
+bool Game::markHitSides(int x1, int y1, int x2, int y2, FieldState state) {
+    hitA.x = x1 + (x1 - x2);
+    hitA.y = y1 + (y1 - y2);
+    hitB.x = x2 + (x2 - x1);
+    hitB.y = y2 + (y2 - y1);
+    return isInRange(hitA.x, hitA.y) && isInRange(hitB.x, hitB.y) &&
+            areNeighbours(x1, y1, hitA.x, hitA.y) && areNeighbours(x2, y2, hitB.x, hitB.y) &&
+            fields[hitA.x][ hitA.y] == state && fields[hitB.x][ hitB.y] == state;
+}
+
+bool Game::shouldEnd() const {
+    int player = 0;
+    int ai = 0;
+    for(uint x = 0; x < 9; x++) {
+        for(uint y = 0; y < 5; y++) {
+            player += fields[x][y] == WHITE;
+            ai += fields[x][y] == BLACK;
+        }
+    }
+    return player == 0 || ai == 0;
 }

+ 10 - 3
Game.h

@@ -14,19 +14,20 @@ public:
     };
 
     enum State {
-        SELECTION, MOVE, ANOTHER_MOVE
+        SELECTION, MOVE, ANOTHER_MOVE, REMOVE_SELECTION
     };
 
     Game();
 
     void reset(String& output);
-    void parse(const String& input, String& output);
+    bool parse(const String& input, String& output);
 
 private:
     bool parseLocation(const String& input, int& x, int& y);
     void parseSelection(const String& input, String& output);
     void parseMove(const String& input, String& output);
     void parseAnotherMove(const String& input, String& output);
+    void parseRemoveSelection(const String& input, String& output);
 
     void move(int fromX, int fromY, int toX, int toY);
     bool isDigit(char c) const;
@@ -38,12 +39,15 @@ private:
     void revertToSelection(String& output);
     bool areNeighbours(int x, int y, int x2, int y2) const;
     void botMove(String& output);
-    
+
     void addLocation(int x, int y);
     bool isInQueue(int x, int y) const;
     bool canMoveActiveStoneTo(int dirX, int dirY) const;
     bool isAnotherTurnPossible() const;
 
+    bool markHitSides(int x1, int y1, int x2, int y2, FieldState state);
+    bool shouldEnd() const;
+
     FieldState fields[9][5];
     int activeX;
     int activeY;
@@ -57,6 +61,9 @@ private:
     };
     std::array<Location, 20> lastLocations;
     uint lastLocation;
+    
+    Location hitA;
+    Location hitB;
 };
 
 #endif

+ 9 - 2
Main.cpp

@@ -1,6 +1,8 @@
 #include <iostream>
 #include <array>
 
+#include <unistd.h>
+
 #include "Socket.h" 
 #include "Client.h"
 #include "Game.h" 
@@ -10,17 +12,22 @@ int main() {
     if(socket.start(4455)) {
         return 0;
     }
-    std::array<Client, 20> clients;
+    std::array<Client, 1> clients;
     while(true) {
         int clientId = socket.waitForClients(100);
         if(clientId != -1) {
             for(Client& client : clients) {
                 if(client.isFree()) {
                     client.start(clientId);
+                    clientId = -1;
+                    std::cout << "client added" << "\n";
                     break;
                 }
             }
-            std::cout << "client added" << "\n";
+            if(clientId != -1) {
+                std::cout << "client disconnected - full server" << "\n";
+                close(clientId);
+            }
         }
 
         char buffer[256];