From 1e7b9ee7b9678f1b259731bfe959df6ab6859b9e Mon Sep 17 00:00:00 2001
From: Francesco Bariatti <francesco.bariatti@insa-rennes.fr>
Date: Sun, 1 May 2016 00:05:18 +0200
Subject: [PATCH] Added click to move penguin: you can now play the game!

---
 gui/src/controller/Controller.java   | 89 +++++++++++++++++++++-------
 gui/src/controller/UpdateThread.java | 37 ++++++++++--
 gui/src/model/GameState.java         | 19 +++---
 gui/src/model/Move.java              | 27 +++++++++
 gui/src/view/TileView.java           |  6 ++
 5 files changed, 141 insertions(+), 37 deletions(-)
 create mode 100644 gui/src/model/Move.java

diff --git a/gui/src/controller/Controller.java b/gui/src/controller/Controller.java
index b5ef51a..c96d1eb 100644
--- a/gui/src/controller/Controller.java
+++ b/gui/src/controller/Controller.java
@@ -11,6 +11,7 @@ import javafx.scene.layout.BorderPane;
 import javafx.scene.paint.Color;
 import javafx.scene.shape.Polygon;
 import model.GameState;
+import model.Move;
 import model.Player;
 import model.Tile;
 import view.TileView;
@@ -72,10 +73,6 @@ public class Controller implements Initializable
 			e.printStackTrace();
 			System.exit(1);
 		}
-		UpdateThread upT = new UpdateThread(gameProcess, this.gameState, this.board, this.boardView);
-		upT.setDaemon(true);
-		upT.start();
-
 		//Choice: who will start?
 		ChoiceDialog<Player> playerChoice = new ChoiceDialog<>(Player.Red, Player.Red, Player.Blue);
 		playerChoice.setTitle("Penguin game!");
@@ -93,6 +90,10 @@ public class Controller implements Initializable
 			else
 				gameInput.println("c");
 		}
+
+		UpdateThread upT = new UpdateThread(gameProcess, this.gameState, this.board, this.boardView, humanPlayer);
+		upT.setDaemon(true);
+		upT.start();
 	}
 
 	/**
@@ -108,14 +109,12 @@ public class Controller implements Initializable
 			this.tileNumber = tileNumber;
 		}
 
-		/**
-		 * Change the tiles' highlighted values to the given value
-		 */
-		private void changeTilesHighlightState(List<Integer> tiles, boolean value)
+		private void unHighlightTiles(List<Integer> tiles)
 		{
 			for (int tile : tiles)
 			{
-				boardView[tile].setHighlighted(value);
+				boardView[tile].setHighlighted(false);
+				boardView[tile].setHighlightMove(null);
 				boardView[tile].update();
 			}
 		}
@@ -129,30 +128,78 @@ public class Controller implements Initializable
 			if (selectedTile == tileNumber) //If we clicked again on the selected tile
 			{
 				//UnSelect and un-highlight previously selected and highlighted tiles
-				boardView[selectedTile].setSelected(true);
+				boardView[selectedTile].setSelected(false);
 				boardView[selectedTile].update();
-				changeTilesHighlightState(gameState.getReachableTiles(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile)), false);
+				unHighlightTiles(gameState.getReachableTiles(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile)));
 				selectedTile = -1;
 				return;
 			}
 
 			//We clicked on a tile that wasn't previously selected
 			int penguinNb = gameState.getPenguinOnTile(humanPlayer, tileNumber);
-			if (penguinNb == -1) //There is no penguin on this tile
+			if (penguinNb != -1) //There is a penguin on this tile: we want to select it
+			{
+				//Unselect previously selected tiles
+				if (selectedTile != -1)
+				{
+					boardView[selectedTile].setSelected(false);
+					boardView[selectedTile].update();
+					unHighlightTiles(gameState.getReachableTiles(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile)));
+				}
+				//Selecting new tile
+				boardView[tileNumber].setSelected(true);
+				boardView[tileNumber].update();
+				selectedTile = tileNumber;
+				for (int i = 1; i <= gameState.getNbMoves(humanPlayer, penguinNb, GameState.Direction.A); i++)
+				{
+					boardView[selectedTile + i * 7].setHighlighted(true);
+					boardView[selectedTile + i * 7].setHighlightMove(new Move(GameState.Direction.A, i));
+					boardView[selectedTile + i * 7].update();
+				}
+				for (int i = 1; i <= gameState.getNbMoves(humanPlayer, penguinNb, GameState.Direction.B); i++)
+				{
+					boardView[selectedTile - i].setHighlighted(true);
+					boardView[selectedTile - i].setHighlightMove(new Move(GameState.Direction.B, i));
+					boardView[selectedTile - i].update();
+				}
+				for (int i = 1; i <= gameState.getNbMoves(humanPlayer, penguinNb, GameState.Direction.C); i++)
+				{
+					boardView[selectedTile - i * 8].setHighlighted(true);
+					boardView[selectedTile - i * 8].setHighlightMove(new Move(GameState.Direction.C, i));
+					boardView[selectedTile - i * 8].update();
+				}
+				for (int i = 1; i <= gameState.getNbMoves(humanPlayer, penguinNb, GameState.Direction.D); i++)
+				{
+					boardView[selectedTile - i * 7].setHighlighted(true);
+					boardView[selectedTile - i * 7].setHighlightMove(new Move(GameState.Direction.D, i));
+					boardView[selectedTile - i * 7].update();
+				}
+				for (int i = 1; i <= gameState.getNbMoves(humanPlayer, penguinNb, GameState.Direction.E); i++)
+				{
+					boardView[selectedTile + i].setHighlighted(true);
+					boardView[selectedTile + i].setHighlightMove(new Move(GameState.Direction.E, i));
+					boardView[selectedTile + i].update();
+				}
+				for (int i = 1; i <= gameState.getNbMoves(humanPlayer, penguinNb, GameState.Direction.F); i++)
+				{
+					boardView[selectedTile + i * 8].setHighlighted(true);
+					boardView[selectedTile + i * 8].setHighlightMove(new Move(GameState.Direction.F, i));
+					boardView[selectedTile + i * 8].update();
+				}
 				return;
-
-			//There is a penguin on the tile: we want to select this tile
-			if (selectedTile != -1) //If there was a tile previously selected
+			}
+			else if (boardView[tileNumber].isHighlighted()) //There is no penguin but this is a possible move for the penguin on the selected tile
 			{
+				Move move = boardView[tileNumber].getHighlightMove();
+				int moveNb = gameState.getPlayerMoveNumber(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile), move.getDirection(), move.getSteps());
+				//Before playing the move: deselect and de-highlight tiles
 				boardView[selectedTile].setSelected(false);
 				boardView[selectedTile].update();
-				changeTilesHighlightState(gameState.getReachableTiles(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile)), false);
+				unHighlightTiles(gameState.getReachableTiles(humanPlayer, gameState.getPenguinOnTile(humanPlayer, selectedTile)));
+				selectedTile = -1;
+				//Play the move
+				gameInput.println(moveNb);
 			}
-			boardView[tileNumber].setSelected(true);
-			boardView[tileNumber].update();
-			changeTilesHighlightState(gameState.getReachableTiles(humanPlayer, penguinNb), true);
-			selectedTile = tileNumber;
-			return;
 		}
 	}
 
diff --git a/gui/src/controller/UpdateThread.java b/gui/src/controller/UpdateThread.java
index f3ed2a9..5a318f0 100644
--- a/gui/src/controller/UpdateThread.java
+++ b/gui/src/controller/UpdateThread.java
@@ -8,23 +8,25 @@ import model.Player;
 import model.Tile;
 import view.TileView;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
+import java.io.*;
 
 public class UpdateThread extends Thread
 {
 	BufferedReader reader;
+	PrintWriter writer;
 	GameState gameState;
 	Tile[] board;
 	TileView[] boardView;
+	Player humanPlayer;
 
-	public UpdateThread(Process program, GameState gameState, Tile[] board, TileView[] boardView)
+	public UpdateThread(Process program, GameState gameState, Tile[] board, TileView[] boardView, Player humanPlayer)
 	{
 		this.reader = new BufferedReader(new InputStreamReader(program.getInputStream()));
+		this.writer = new PrintWriter(new OutputStreamWriter(program.getOutputStream()), true);
 		this.gameState = gameState;
 		this.board = board;
 		this.boardView = boardView;
+		this.humanPlayer = humanPlayer;
 	}
 
 
@@ -39,6 +41,20 @@ public class UpdateThread extends Thread
 				System.out.println(line);
 				if (line == null)
 				{
+					Platform.runLater(() ->
+					{
+						Player computer = Player.Red;
+						if (humanPlayer.equals(Player.Red))
+							computer = Player.Blue;
+						Alert alert = new Alert(Alert.AlertType.INFORMATION);
+						if (gameState.getScore(humanPlayer) > gameState.getScore(computer))
+							alert.setHeaderText("You won!!!!");
+						else if (gameState.getScore(humanPlayer) == gameState.getScore(computer))
+							alert.setHeaderText("That's a draw. Not bad!");
+						else
+							alert.setHeaderText("You just lost the penguin game.");
+						alert.showAndWait();
+					});
 					gameRunning = false;
 				}
 				else if (line.contains("{")) //Line contains JSON
@@ -59,6 +75,19 @@ public class UpdateThread extends Thread
 					//UPDATE VIEW
 					for (int i = 0; i < boardView.length; i++)
 						boardView[i].update();
+
+					if (gameState.getCurrent_player() == humanPlayer)
+					{
+						if (!gameState.getCanPlay(humanPlayer))
+						{
+							Platform.runLater(() ->
+							{
+								Alert alert = new Alert(Alert.AlertType.INFORMATION, "You can't play any move!", ButtonType.OK);
+								alert.showAndWait();
+								writer.println("0"); //This pass the turn
+							});
+						}
+					}
 				}
 			}
 			catch (IOException e)
diff --git a/gui/src/model/GameState.java b/gui/src/model/GameState.java
index bab409a..3d3da94 100644
--- a/gui/src/model/GameState.java
+++ b/gui/src/model/GameState.java
@@ -11,14 +11,17 @@ import java.util.Map;
 public class GameState
 {
 	long[] fish; //Array of three bitboards: one for every fish value
-	boolean can_play_red, can_play_blue; //If the red(blue) player can play or if it has no moves left
 	Player current_player;
+	Map<Player, Boolean> can_play; //If the red(blue) player can play or if it has no moves left
 	Map<Player, int[]> penguins; //For every player, the list of his penguins
 	Map<Player, Integer> score; //Score of every player
 
 	public GameState()
 	{
 		fish = new long[3];
+		can_play = new HashMap<>();
+		can_play.put(Player.Red, true);
+		can_play.put(Player.Blue, true);
 		penguins = new HashMap<>();
 		penguins.put(Player.Red, new int[4]);
 		penguins.put(Player.Blue, new int[4]);
@@ -31,8 +34,8 @@ public class GameState
 	{
 		//System.out.println(jsonString);
 		JSONObject json = new JSONObject(jsonString);
-		can_play_red = json.getJSONObject("can_play").getBoolean("red");
-		can_play_blue = json.getJSONObject("can_play").getBoolean("blue");
+		can_play.put(Player.Red, json.getJSONObject("can_play").getBoolean("red"));
+		can_play.put(Player.Blue, json.getJSONObject("can_play").getBoolean("blue"));
 		current_player = Player.valueOf(json.getString("current_player"));
 		fish[0] = json.getJSONObject("bitboards").getLong("onefish");
 		fish[1] = json.getJSONObject("bitboards").getLong("twofish");
@@ -165,15 +168,7 @@ public class GameState
 		return result;
 	}
 
-	public boolean getCan_play_red()
-	{
-		return can_play_red;
-	}
-
-	public boolean getCan_play_blue()
-	{
-		return can_play_blue;
-	}
+	public boolean getCanPlay(Player player) { return can_play.get(player); }
 
 	public Player getCurrent_player()
 	{
diff --git a/gui/src/model/Move.java b/gui/src/model/Move.java
new file mode 100644
index 0000000..8dc29ec
--- /dev/null
+++ b/gui/src/model/Move.java
@@ -0,0 +1,27 @@
+package model;
+
+public class Move
+{
+	GameState.Direction direction;
+	int steps;
+
+	public Move(GameState.Direction direction, int steps)
+	{
+		this.direction = direction;
+		this.steps = steps;
+	}
+
+	@Override
+	public String toString()
+	{
+		return "(" + direction + ", " + steps + ")";
+	}
+
+	public GameState.Direction getDirection() { return direction; }
+
+	public void setDirection(GameState.Direction direction) { this.direction = direction; }
+
+	public int getSteps() { return steps; }
+
+	public void setSteps(int steps) { this.steps = steps; }
+}
diff --git a/gui/src/view/TileView.java b/gui/src/view/TileView.java
index 214de4b..2ebb489 100644
--- a/gui/src/view/TileView.java
+++ b/gui/src/view/TileView.java
@@ -2,6 +2,7 @@ package view;
 
 import javafx.scene.paint.Color;
 import javafx.scene.shape.Polygon;
+import model.Move;
 import model.Tile;
 
 /**
@@ -12,6 +13,7 @@ public class TileView
 	private Polygon fxTile;
 	private Tile modelTile;
 	private boolean selected, highlighted;
+	private Move highlightMove = null; // How do we get here from the selected tile (used when highlighting)
 
 	public TileView(Polygon fxTile, Tile modelTile)
 	{
@@ -69,4 +71,8 @@ public class TileView
 
 	public void setHighlighted(boolean highlighted) { this.highlighted = highlighted; }
 
+	public Move getHighlightMove() { return highlightMove; }
+
+	public void setHighlightMove(Move highlightMove) { this.highlightMove = highlightMove; }
+
 }
-- 
GitLab