2020-03-02 18:46:45 +01:00
|
|
|
package inf112.fiasko.roborally.objects;
|
2020-02-04 17:52:17 +01:00
|
|
|
|
2020-04-14 14:47:17 +02:00
|
|
|
import com.esotericsoftware.kryonet.Client;
|
|
|
|
import com.esotericsoftware.kryonet.Connection;
|
2020-03-24 12:03:17 +01:00
|
|
|
import inf112.fiasko.roborally.element_properties.Action;
|
|
|
|
import inf112.fiasko.roborally.element_properties.Direction;
|
2020-04-14 12:36:55 +02:00
|
|
|
import inf112.fiasko.roborally.element_properties.GameState;
|
2020-03-24 12:03:17 +01:00
|
|
|
import inf112.fiasko.roborally.element_properties.Position;
|
|
|
|
import inf112.fiasko.roborally.element_properties.RobotID;
|
|
|
|
import inf112.fiasko.roborally.element_properties.TileType;
|
2020-04-14 14:47:17 +02:00
|
|
|
import inf112.fiasko.roborally.networking.RoboRallyClient;
|
|
|
|
import inf112.fiasko.roborally.networking.RoboRallyServer;
|
2020-02-22 23:36:01 +01:00
|
|
|
import inf112.fiasko.roborally.utility.BoardLoaderUtil;
|
2020-03-24 15:26:20 +01:00
|
|
|
import inf112.fiasko.roborally.utility.DeckLoaderUtil;
|
2020-01-31 13:53:08 +01:00
|
|
|
|
2020-02-22 23:36:01 +01:00
|
|
|
import java.io.IOException;
|
2020-02-03 14:10:52 +01:00
|
|
|
import java.util.ArrayList;
|
2020-03-24 21:13:21 +01:00
|
|
|
import java.util.Collections;
|
2020-03-25 13:36:35 +01:00
|
|
|
import java.util.HashMap;
|
2020-01-31 13:53:08 +01:00
|
|
|
import java.util.List;
|
2020-03-25 13:36:35 +01:00
|
|
|
import java.util.Map;
|
2020-02-24 18:07:26 +01:00
|
|
|
import java.util.concurrent.TimeUnit;
|
2020-01-31 13:53:08 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This class represent a game which is drawable using libgdx
|
|
|
|
*/
|
2020-03-02 18:46:45 +01:00
|
|
|
public class RoboRallyGame implements IDrawableGame {
|
2020-02-22 23:36:01 +01:00
|
|
|
private Board gameBoard;
|
2020-03-16 17:55:38 +01:00
|
|
|
private List<BoardElementContainer<Tile>> cogwheels;
|
|
|
|
private List<BoardElementContainer<Tile>> conveyorBelts;
|
2020-03-16 19:37:21 +01:00
|
|
|
private List<BoardElementContainer<Tile>> fastConveyorBelts;
|
2020-04-07 22:37:44 +02:00
|
|
|
private List<BoardElementContainer<Tile>> repairTiles;
|
2020-04-07 22:16:31 +02:00
|
|
|
private final List<Player> playerList;
|
2020-03-30 18:32:55 +02:00
|
|
|
private final boolean host;
|
2020-03-31 15:52:03 +02:00
|
|
|
private Deck<ProgrammingCard> mainDeck;
|
2020-04-14 12:36:55 +02:00
|
|
|
private GameState gameState = GameState.INITIAL_SETUP;
|
2020-04-14 14:47:17 +02:00
|
|
|
private String nameOfPlayer;
|
|
|
|
private RoboRallyClient client;
|
|
|
|
private RoboRallyServer server;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getNameOfPlayer() {
|
|
|
|
return nameOfPlayer;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setNameOfPlayer(String nameOfPlayer) {
|
|
|
|
this.nameOfPlayer = nameOfPlayer;
|
|
|
|
}
|
2020-04-14 12:36:55 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the gameState of the game
|
|
|
|
* @return the gameState of the game
|
|
|
|
*/
|
|
|
|
public GameState getGameState(){
|
|
|
|
return gameState;
|
|
|
|
}
|
|
|
|
|
2020-04-14 14:47:17 +02:00
|
|
|
@Override
|
|
|
|
public RoboRallyClient getClient() {
|
|
|
|
return client;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setClient(RoboRallyClient client) {
|
|
|
|
this.client=client;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setServer(RoboRallyServer server) {
|
|
|
|
this.server=server;
|
|
|
|
}
|
|
|
|
|
2020-04-14 12:36:55 +02:00
|
|
|
/**
|
|
|
|
* Sets the gameState of the game
|
|
|
|
* @param gameState the gameState
|
|
|
|
*/
|
|
|
|
public void setGameState(GameState gameState) {
|
|
|
|
this.gameState = gameState;
|
|
|
|
}
|
2020-04-07 22:16:31 +02:00
|
|
|
|
2020-03-25 09:58:42 +01:00
|
|
|
/**
|
|
|
|
* Instantiates a new robo rally game
|
|
|
|
* @param debug Whether to start the game in debugging mode
|
|
|
|
*/
|
2020-04-14 14:47:17 +02:00
|
|
|
public RoboRallyGame(List<Player> playerList, String boardName, boolean host, boolean debug, String name) {
|
|
|
|
this.nameOfPlayer = name;
|
2020-04-07 22:16:31 +02:00
|
|
|
this.host = host;
|
2020-04-06 16:14:53 +02:00
|
|
|
this.playerList = playerList;
|
2020-02-27 16:44:06 +01:00
|
|
|
if (debug) {
|
|
|
|
initializeDebugMode();
|
|
|
|
} else {
|
2020-04-06 17:09:05 +02:00
|
|
|
initializeGame(boardName);
|
2020-02-27 16:44:06 +01:00
|
|
|
}
|
|
|
|
}
|
2020-03-25 09:58:42 +01:00
|
|
|
/**
|
|
|
|
* Instantiates a new robo rally game
|
|
|
|
*/
|
2020-04-14 14:47:17 +02:00
|
|
|
public RoboRallyGame(List<Player> playerList, String boardName,boolean host,String nameOfPlayer) {
|
|
|
|
this.nameOfPlayer = nameOfPlayer;
|
2020-04-07 22:16:31 +02:00
|
|
|
this.host = host;
|
2020-04-06 16:14:53 +02:00
|
|
|
this.playerList = playerList;
|
2020-04-06 17:09:05 +02:00
|
|
|
initializeGame(boardName);
|
2020-02-27 16:44:06 +01:00
|
|
|
}
|
|
|
|
|
2020-02-28 19:46:40 +01:00
|
|
|
@Override
|
|
|
|
public int getWidth() {
|
|
|
|
return gameBoard.getBoardWidth();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getHeight() {
|
|
|
|
return gameBoard.getBoardHeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public List<Tile> getTilesToDraw() {
|
|
|
|
return gameBoard.getTiles();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public List<Wall> getWallsToDraw() {
|
|
|
|
return gameBoard.getWalls();
|
|
|
|
}
|
|
|
|
|
2020-03-23 13:42:48 +01:00
|
|
|
@Override
|
|
|
|
public List<Particle> getParticlesToDraw() {
|
|
|
|
return gameBoard.getParticles();
|
|
|
|
}
|
|
|
|
|
2020-02-28 19:46:40 +01:00
|
|
|
@Override
|
|
|
|
public List<Robot> getRobotsToDraw() {
|
|
|
|
return gameBoard.getAliveRobots();
|
|
|
|
}
|
|
|
|
|
2020-03-10 17:29:36 +01:00
|
|
|
/**
|
|
|
|
* Makes the game thread wait a given time amount before continuing.
|
|
|
|
* @throws InterruptedException If interrupted while trying to sleep.
|
|
|
|
*/
|
|
|
|
private void sleep() throws InterruptedException {
|
|
|
|
long cycleDelay = 600;
|
|
|
|
TimeUnit.MILLISECONDS.sleep(cycleDelay);
|
|
|
|
}
|
2020-04-07 22:16:31 +02:00
|
|
|
|
2020-02-28 19:46:40 +01:00
|
|
|
/**
|
|
|
|
* Initializes the game with a debugging board
|
|
|
|
*/
|
2020-02-27 16:44:06 +01:00
|
|
|
private void initializeDebugMode() {
|
|
|
|
List<Robot> robots = new ArrayList<>();
|
2020-03-19 13:46:45 +01:00
|
|
|
robots.add(new Robot(RobotID.ROBOT_1, new Position(0, 18)));
|
|
|
|
robots.add(new Robot(RobotID.ROBOT_2, new Position(1, 18)));
|
|
|
|
robots.add(new Robot(RobotID.ROBOT_3, new Position(2, 18)));
|
|
|
|
robots.add(new Robot(RobotID.ROBOT_4, new Position(3, 18)));
|
|
|
|
robots.add(new Robot(RobotID.ROBOT_5, new Position(4, 18)));
|
|
|
|
robots.add(new Robot(RobotID.ROBOT_6, new Position(5, 18)));
|
|
|
|
robots.add(new Robot(RobotID.ROBOT_7, new Position(6, 18)));
|
|
|
|
robots.add(new Robot(RobotID.ROBOT_8, new Position(7, 18)));
|
2020-02-27 16:44:06 +01:00
|
|
|
try {
|
|
|
|
gameBoard = BoardLoaderUtil.loadBoard("boards/all_tiles_test_board.txt", robots);
|
|
|
|
} catch (IOException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-28 19:46:40 +01:00
|
|
|
/**
|
|
|
|
* Initializes the game with a playable board
|
|
|
|
*/
|
2020-04-06 17:09:05 +02:00
|
|
|
private void initializeGame(String boardName) {
|
2020-02-22 23:36:01 +01:00
|
|
|
try {
|
|
|
|
List<Robot> robots = new ArrayList<>();
|
2020-04-07 22:16:31 +02:00
|
|
|
//TODO: Find correct robot spawn positions
|
|
|
|
int posX = 1;
|
|
|
|
for (Player player : playerList) {
|
|
|
|
Position spawn = new Position(posX,1);
|
|
|
|
robots.add(new Robot(player.getRobotID(), spawn));
|
|
|
|
posX++;
|
2020-04-06 17:09:05 +02:00
|
|
|
}
|
|
|
|
|
2020-04-07 22:16:31 +02:00
|
|
|
gameBoard = BoardLoaderUtil.loadBoard("boards/" + boardName, robots);
|
2020-03-26 13:07:53 +01:00
|
|
|
generateTileLists();
|
2020-04-02 12:27:50 +02:00
|
|
|
|
2020-04-02 10:29:37 +02:00
|
|
|
if (host) {
|
|
|
|
mainDeck = DeckLoaderUtil.loadProgrammingCardsDeck();
|
|
|
|
}
|
2020-03-16 17:31:54 +01:00
|
|
|
|
2020-02-24 18:07:26 +01:00
|
|
|
new Thread(() -> {
|
|
|
|
try {
|
2020-04-07 22:16:31 +02:00
|
|
|
runTurn();
|
2020-02-24 18:07:26 +01:00
|
|
|
} catch (InterruptedException e) {
|
2020-02-26 08:10:46 +01:00
|
|
|
Thread.currentThread().interrupt();
|
2020-02-24 18:07:26 +01:00
|
|
|
}
|
|
|
|
}).start();
|
2020-02-22 23:36:01 +01:00
|
|
|
} catch (IOException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
2020-01-31 13:53:08 +01:00
|
|
|
|
2020-03-26 13:07:53 +01:00
|
|
|
/**
|
|
|
|
* Generates lists containing board element containers with all tiles of certain types
|
|
|
|
*/
|
|
|
|
private void generateTileLists() {
|
|
|
|
cogwheels = gameBoard.getPositionsOfTileOnBoard(TileType.COGWHEEL_RIGHT,
|
|
|
|
TileType.COGWHEEL_LEFT);
|
|
|
|
fastConveyorBelts = gameBoard.getPositionsOfTileOnBoard(TileType.CONVEYOR_BELT_FAST,
|
|
|
|
TileType.CONVEYOR_BELT_FAST_RIGHT, TileType.CONVEYOR_BELT_FAST_LEFT,
|
|
|
|
TileType.CONVEYOR_BELT_FAST_SIDE_ENTRANCE_RIGHT,
|
|
|
|
TileType.CONVEYOR_BELT_FAST_SIDE_ENTRANCE_LEFT,
|
|
|
|
TileType.CONVEYOR_BELT_FAST_SIDE_ENTRANCES);
|
|
|
|
conveyorBelts = new ArrayList<>();
|
|
|
|
conveyorBelts.addAll(fastConveyorBelts);
|
|
|
|
conveyorBelts.addAll(gameBoard.getPositionsOfTileOnBoard(TileType.CONVEYOR_BELT_SLOW,
|
|
|
|
TileType.CONVEYOR_BELT_SLOW_RIGHT, TileType.CONVEYOR_BELT_SLOW_LEFT,
|
|
|
|
TileType.CONVEYOR_BELT_SLOW_SIDE_ENTRANCE_RIGHT,
|
|
|
|
TileType.CONVEYOR_BELT_SLOW_SIDE_ENTRANCE_LEFT,
|
|
|
|
TileType.CONVEYOR_BELT_SLOW_SIDE_ENTRANCES));
|
2020-04-07 22:37:44 +02:00
|
|
|
repairTiles = gameBoard.getPositionsOfTileOnBoard(TileType.FLAG_1, TileType.FLAG_2, TileType.FLAG_3,
|
|
|
|
TileType.FLAG_4, TileType.WRENCH, TileType.WRENCH_AND_HAMMER);
|
2020-03-26 13:07:53 +01:00
|
|
|
}
|
2020-04-14 14:47:17 +02:00
|
|
|
private Player getPlayerFromName(String name){
|
|
|
|
for (Player player:playerList) {
|
|
|
|
if(player.getName().equals(name)){
|
|
|
|
return player;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2020-03-26 13:07:53 +01:00
|
|
|
|
2020-03-31 14:34:46 +02:00
|
|
|
/**
|
|
|
|
* Runs all the steps of one turn in the game
|
|
|
|
* @throws InterruptedException If interrupted while trying to sleep
|
|
|
|
*/
|
|
|
|
private void runTurn() throws InterruptedException {
|
|
|
|
// The method should follow this sequence:
|
|
|
|
/*
|
|
|
|
Tilegne programeringskort
|
|
|
|
|
|
|
|
Programmer roboten
|
|
|
|
|
|
|
|
Gå i power down
|
|
|
|
|
|
|
|
Kjør 5 faser
|
|
|
|
|
|
|
|
Flagg + reprasjonstiles reparerer
|
|
|
|
|
|
|
|
Fjerner ulåste programmeringskort
|
|
|
|
|
|
|
|
Spør om de i power down skal fortsette i power down
|
|
|
|
|
|
|
|
Respawn roboter
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Sets the power down status to true on robots that have players who planned one this turn.
|
|
|
|
// Resets players power down for next turn to false.
|
|
|
|
updateRobotPowerDown();
|
|
|
|
// Set damage of robots in power down to 0
|
|
|
|
gameBoard.executePowerdown();
|
|
|
|
if (host) {
|
2020-03-31 15:52:03 +02:00
|
|
|
distributeProgrammingCardsToPlayers();
|
2020-04-14 14:47:17 +02:00
|
|
|
for (Connection connection: server.getPlayerNames().keySet()) {
|
|
|
|
String playerName = server.getPlayerNames().get(connection);
|
|
|
|
Player player = getPlayerFromName(playerName);
|
|
|
|
if(player.getPlayerDeck()!=null) {
|
|
|
|
server.sendToClient(connection, player.getPlayerDeck());
|
|
|
|
}
|
|
|
|
}
|
2020-03-31 14:34:46 +02:00
|
|
|
}
|
2020-04-14 14:47:17 +02:00
|
|
|
setGameState(GameState.CHOOSING_CARDS);
|
2020-03-31 14:34:46 +02:00
|
|
|
// TODO: Make program for this player, if not in power down
|
|
|
|
// TODO: Ask player for new power down
|
|
|
|
// Run the phases of the game
|
2020-04-14 14:47:17 +02:00
|
|
|
while (getGameState()==GameState.CHOOSING_CARDS) {
|
|
|
|
//loops waiting for the player to be done choosing their cards
|
|
|
|
}
|
|
|
|
runPhase(1);
|
|
|
|
runPhase(2);
|
|
|
|
runPhase(3);
|
|
|
|
runPhase(4);
|
|
|
|
runPhase(5);
|
2020-03-31 14:34:46 +02:00
|
|
|
|
|
|
|
// Repair robots on repair tiles
|
2020-03-31 14:36:38 +02:00
|
|
|
repairAllRobotsOnRepairTiles();
|
2020-04-02 12:27:50 +02:00
|
|
|
if (host) {
|
2020-04-07 22:16:31 +02:00
|
|
|
updateLockedProgrammingCardsForAllPlayers();
|
2020-04-02 12:27:50 +02:00
|
|
|
removeNonLockedProgrammingCardsFromPlayers();
|
|
|
|
}
|
2020-03-31 14:34:46 +02:00
|
|
|
// TODO: If this player is in power down, ask if it shall continue
|
|
|
|
// Respawn dead robots, as long as they have more lives left
|
|
|
|
respawnRobots();
|
2020-04-09 19:57:29 +02:00
|
|
|
resetHasTouchedFlagThisTurnForAllRobots();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resets the boolean for if the robot has touched a flag this turn, to set up the next turn.
|
|
|
|
*/
|
|
|
|
private void resetHasTouchedFlagThisTurnForAllRobots() {
|
|
|
|
for (Robot robot : gameBoard.getAliveRobots()) {
|
|
|
|
robot.setHasTouchedFlagThisTurn(false);
|
|
|
|
}
|
2020-03-31 14:34:46 +02:00
|
|
|
}
|
|
|
|
|
2020-04-02 12:27:50 +02:00
|
|
|
/**
|
|
|
|
* Locks the players programming cards in relation to the robots damage
|
|
|
|
*/
|
2020-04-07 22:16:31 +02:00
|
|
|
private void updateLockedProgrammingCardsForAllPlayers() {
|
2020-04-02 12:27:50 +02:00
|
|
|
for (Player player : playerList) {
|
|
|
|
List<ProgrammingCard> playerProgram = player.getProgram();
|
|
|
|
ProgrammingCardDeck playerDeck = player.getPlayerDeck();
|
|
|
|
ProgrammingCardDeck lockedPlayerDeck = player.getLockedPlayerDeck();
|
|
|
|
int robotDamage = gameBoard.getRobotDamage(player.getRobotID());
|
|
|
|
|
2020-04-07 22:16:31 +02:00
|
|
|
//The player has no locked cards. All previously locked cards should go into the free deck
|
2020-04-02 12:27:50 +02:00
|
|
|
if (robotDamage <= 4) {
|
|
|
|
lockedPlayerDeck.emptyInto(player.getPlayerDeck());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-04-07 22:16:31 +02:00
|
|
|
//Goes through locked cards and moves them to the locked player deck
|
|
|
|
for (int i = 1; i <= (robotDamage - 4); i++) {
|
|
|
|
ProgrammingCard card = playerProgram.get(playerProgram.size() - i);
|
|
|
|
moveProgrammingCardToLockedDeck(card, playerDeck, lockedPlayerDeck);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-04-02 12:27:50 +02:00
|
|
|
|
2020-04-07 22:16:31 +02:00
|
|
|
/**
|
|
|
|
* Moves a card from the player's deck to the player's locked deck if found
|
|
|
|
* @param card The card to move to the locked deck
|
|
|
|
* @param playerDeck The deck containing the player's cards
|
|
|
|
* @param lockedPlayerDeck The deck containing the player's locked cards
|
|
|
|
*/
|
|
|
|
private void moveProgrammingCardToLockedDeck(ProgrammingCard card, ProgrammingCardDeck playerDeck,
|
|
|
|
ProgrammingCardDeck lockedPlayerDeck) {
|
|
|
|
for (int i = 0; i < playerDeck.size(); i++) {
|
|
|
|
if (card.equals(playerDeck.peekTop())) {
|
|
|
|
//Found the card. Add to the locked deck
|
|
|
|
lockedPlayerDeck.draw(playerDeck);
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
//Move the card to the bottom of the deck
|
|
|
|
playerDeck.draw(playerDeck);
|
2020-04-02 12:27:50 +02:00
|
|
|
}
|
|
|
|
}
|
2020-04-07 22:16:31 +02:00
|
|
|
|
2020-04-02 12:27:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Moves non-locked player programming cards from their hand back to the main deck
|
|
|
|
*/
|
|
|
|
private void removeNonLockedProgrammingCardsFromPlayers() {
|
|
|
|
for (Player player : playerList) {
|
2020-04-07 22:37:44 +02:00
|
|
|
player.getPlayerDeck().emptyInto(mainDeck);
|
2020-04-02 12:27:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-31 15:53:46 +02:00
|
|
|
/**
|
|
|
|
* Deals correct amount of cards to active players, based on their robots damage
|
|
|
|
*/
|
2020-04-07 22:16:31 +02:00
|
|
|
private void distributeProgrammingCardsToPlayers() {
|
2020-03-31 15:52:03 +02:00
|
|
|
mainDeck.shuffle();
|
|
|
|
for (Player player : playerList) {
|
|
|
|
RobotID robot = player.getRobotID();
|
2020-04-07 22:37:44 +02:00
|
|
|
ProgrammingCardDeck playerDeck = player.getPlayerDeck();
|
|
|
|
int robotDamage = gameBoard.getRobotDamage(robot);
|
|
|
|
//Powered down or heavily damaged robots don't get any cards
|
|
|
|
if (gameBoard.getPowerDown(robot) || robotDamage >= 9) {
|
2020-03-31 15:52:03 +02:00
|
|
|
continue;
|
|
|
|
}
|
2020-04-07 22:37:44 +02:00
|
|
|
if (!playerDeck.isEmpty()) {
|
|
|
|
throw new IllegalStateException("Player deck must be empty when dealing new cards!");
|
2020-03-31 15:52:03 +02:00
|
|
|
}
|
2020-04-07 22:37:44 +02:00
|
|
|
//Gives the player the correct amount of cards
|
|
|
|
playerDeck.draw(mainDeck,9 - robotDamage);
|
2020-03-31 15:52:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-24 12:24:25 +01:00
|
|
|
/**
|
|
|
|
* Runs one phase as defined in the Robo Rally rulebook
|
|
|
|
* @param phaseNumber The number of the phase to run
|
|
|
|
* @throws InterruptedException If interrupted wile trying to sleep
|
|
|
|
*/
|
|
|
|
private void runPhase(int phaseNumber) throws InterruptedException {
|
2020-04-07 22:37:44 +02:00
|
|
|
runProgrammingCards(phaseNumber);
|
2020-03-24 12:24:25 +01:00
|
|
|
|
|
|
|
moveAllConveyorBelts();
|
|
|
|
rotateCogwheels();
|
|
|
|
|
|
|
|
fireAllLasers();
|
|
|
|
checkAllFlags();
|
2020-04-09 20:39:04 +02:00
|
|
|
|
2020-03-24 12:24:25 +01:00
|
|
|
}
|
|
|
|
|
2020-03-10 17:29:36 +01:00
|
|
|
/**
|
|
|
|
* Makes the given robot move according to to the action input.
|
|
|
|
* @param robotID The ID of the robot to move.
|
|
|
|
* @param action The specific movement the robot is to take.
|
|
|
|
* @throws InterruptedException If interrupted wile trying to sleep.
|
|
|
|
*/
|
|
|
|
private void makeMove(RobotID robotID, Action action) throws InterruptedException {
|
|
|
|
if (!gameBoard.isRobotAlive(robotID)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
sleep();
|
|
|
|
switch (action) {
|
|
|
|
case MOVE_1:
|
2020-03-11 08:02:30 +01:00
|
|
|
gameBoard.moveRobotForward(robotID);
|
2020-03-10 17:29:36 +01:00
|
|
|
break;
|
|
|
|
case MOVE_2:
|
2020-03-11 08:02:30 +01:00
|
|
|
gameBoard.moveRobotForward(robotID);
|
2020-03-10 17:29:36 +01:00
|
|
|
moveForward(robotID);
|
|
|
|
break;
|
|
|
|
case MOVE_3:
|
2020-03-11 08:02:30 +01:00
|
|
|
gameBoard.moveRobotForward(robotID);
|
2020-03-10 17:29:36 +01:00
|
|
|
moveForward(robotID);
|
|
|
|
moveForward(robotID);
|
|
|
|
break;
|
|
|
|
case ROTATE_RIGHT:
|
|
|
|
gameBoard.rotateRobotRight(robotID);
|
|
|
|
break;
|
|
|
|
case ROTATE_LEFT:
|
|
|
|
gameBoard.rotateRobotLeft(robotID);
|
|
|
|
break;
|
|
|
|
case U_TURN:
|
|
|
|
gameBoard.rotateRobotLeft(robotID);
|
|
|
|
gameBoard.rotateRobotLeft(robotID);
|
|
|
|
break;
|
|
|
|
case BACK_UP:
|
|
|
|
gameBoard.reverseRobot(robotID);
|
|
|
|
break;
|
2020-03-10 18:26:16 +01:00
|
|
|
default:
|
|
|
|
throw new IllegalArgumentException("Not a recognized action.");
|
2020-03-10 17:29:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper method for makeMove. Takes care of movement forward of given robot.
|
|
|
|
* @param robotID ID of the given robot.
|
|
|
|
* @throws InterruptedException If interrupted wile sleeping.
|
|
|
|
*/
|
|
|
|
private void moveForward(RobotID robotID) throws InterruptedException {
|
|
|
|
if (!gameBoard.isRobotAlive(robotID)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
sleep();
|
|
|
|
gameBoard.moveRobotForward(robotID);
|
2020-02-24 18:07:26 +01:00
|
|
|
}
|
2020-03-12 11:49:14 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Rotates all robots that are standing on cogWheel tiles on the board.
|
|
|
|
* @throws InterruptedException If interrupted while sleeping.
|
|
|
|
*/
|
|
|
|
private void rotateCogwheels() throws InterruptedException {
|
2020-03-12 12:21:31 +01:00
|
|
|
for (BoardElementContainer<Tile> cogwheel : cogwheels) {
|
|
|
|
if (!gameBoard.hasRobotOnPosition(cogwheel.getPosition())) {
|
|
|
|
continue;
|
2020-03-12 11:49:14 +01:00
|
|
|
}
|
|
|
|
sleep();
|
2020-03-16 20:06:35 +01:00
|
|
|
if (cogwheel.getElement().getTileType() == TileType.COGWHEEL_RIGHT) {
|
2020-03-12 12:21:31 +01:00
|
|
|
gameBoard.rotateRobotRight(gameBoard.getRobotOnPosition(cogwheel.getPosition()));
|
|
|
|
} else {
|
|
|
|
gameBoard.rotateRobotLeft(gameBoard.getRobotOnPosition(cogwheel.getPosition()));
|
2020-03-12 11:49:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-16 17:31:54 +01:00
|
|
|
|
2020-03-16 19:37:21 +01:00
|
|
|
/**
|
|
|
|
* Moves robots standing on conveyor belts in the direction of the conveyor belt
|
|
|
|
*
|
|
|
|
* In addition, the function rotates appropriately when arriving at any non-straight conveyor belt
|
|
|
|
*
|
|
|
|
* @throws InterruptedException If disturbed during sleep
|
|
|
|
*/
|
|
|
|
private void moveAllConveyorBelts() throws InterruptedException {
|
2020-03-17 22:00:56 +01:00
|
|
|
sleep();
|
2020-03-16 19:37:21 +01:00
|
|
|
moveConveyorBelts(fastConveyorBelts);
|
2020-03-17 22:00:56 +01:00
|
|
|
sleep();
|
2020-03-16 19:37:21 +01:00
|
|
|
moveConveyorBelts(conveyorBelts);
|
2020-03-16 17:51:06 +01:00
|
|
|
}
|
|
|
|
|
2020-03-16 17:31:54 +01:00
|
|
|
/**
|
2020-03-25 13:36:35 +01:00
|
|
|
* Moves a list of conveyor belts
|
|
|
|
* @param conveyorBelts A list of board element containers containing conveyor belts
|
2020-03-16 17:31:54 +01:00
|
|
|
*/
|
2020-03-17 22:00:56 +01:00
|
|
|
private void moveConveyorBelts(List<BoardElementContainer<Tile>> conveyorBelts) {
|
2020-03-25 13:36:35 +01:00
|
|
|
Map<RobotID, Position> newPositions = new HashMap<>();
|
|
|
|
Map<RobotID, Boolean> moveNormally = new HashMap<>();
|
|
|
|
for (Robot robot : gameBoard.getAliveRobots()) {
|
|
|
|
newPositions.put(robot.getRobotId(), robot.getPosition());
|
2020-03-17 16:22:11 +01:00
|
|
|
}
|
2020-03-25 13:36:35 +01:00
|
|
|
//Updates hash maps containing robot move information
|
2020-03-16 17:31:54 +01:00
|
|
|
for (BoardElementContainer<Tile> conveyorBelt : conveyorBelts) {
|
2020-03-25 13:36:35 +01:00
|
|
|
Position conveyorBeltPosition = conveyorBelt.getPosition();
|
|
|
|
Direction conveyorBeltDirection = conveyorBelt.getElement().getDirection();
|
2020-03-28 15:34:47 +01:00
|
|
|
if (gameBoard.conveyorBeltCanMove(conveyorBelt, 0) &&
|
2020-03-25 13:36:35 +01:00
|
|
|
gameBoard.hasRobotOnPosition(conveyorBeltPosition)) {
|
2020-03-25 14:41:05 +01:00
|
|
|
updateConveyorBeltMaps(conveyorBeltPosition, conveyorBeltDirection, newPositions, moveNormally);
|
2020-03-16 17:31:54 +01:00
|
|
|
}
|
2020-03-17 16:22:11 +01:00
|
|
|
}
|
2020-03-25 13:36:35 +01:00
|
|
|
//Updates position for all robots affected by conveyor belts
|
|
|
|
for (RobotID robotID : RobotID.values()) {
|
|
|
|
if (newPositions.get(robotID) == null || moveNormally.get(robotID) == null) {
|
2020-03-24 21:13:21 +01:00
|
|
|
continue;
|
|
|
|
}
|
2020-03-25 13:36:35 +01:00
|
|
|
if (moveNormally.get(robotID)) {
|
|
|
|
gameBoard.moveRobot(robotID, gameBoard.getTileOnPosition(newPositions.get(robotID)).getDirection());
|
|
|
|
} else {
|
|
|
|
gameBoard.teleportRobot(robotID, newPositions.get(robotID));
|
2020-03-16 17:31:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-16 17:35:01 +01:00
|
|
|
|
2020-03-25 14:41:05 +01:00
|
|
|
/**
|
|
|
|
* Updates maps containing information about what a robot on a conveyor belt should do
|
|
|
|
* @param conveyorBeltPosition The position of the conveyor belt the robot stands on
|
|
|
|
* @param conveyorBeltDirection The direction of the conveyor belt the robot stands on
|
|
|
|
* @param newPositions The map containing new positions for robots
|
|
|
|
* @param moveNormally The map containing whether a robot should move normally following normal rules
|
|
|
|
*/
|
|
|
|
private void updateConveyorBeltMaps(Position conveyorBeltPosition, Direction conveyorBeltDirection,
|
|
|
|
Map<RobotID, Position> newPositions, Map<RobotID, Boolean> moveNormally) {
|
|
|
|
RobotID robotAtConveyorBelt = gameBoard.getRobotOnPosition(conveyorBeltPosition);
|
|
|
|
Position newPosition = gameBoard.getNewPosition(conveyorBeltPosition, conveyorBeltDirection);
|
|
|
|
if (gameBoard.isConveyorBelt(gameBoard.getTileOnPosition(newPosition))) {
|
|
|
|
newPositions.put(robotAtConveyorBelt, newPosition);
|
|
|
|
moveNormally.put(robotAtConveyorBelt, false);
|
|
|
|
Direction newDirection = gameBoard.getTileOnPosition(newPosition).getDirection();
|
|
|
|
if (Direction.getRightRotatedDirection(newDirection) == conveyorBeltDirection) {
|
|
|
|
gameBoard.rotateRobotLeft(robotAtConveyorBelt);
|
|
|
|
} else if (Direction.getLeftRotatedDirection(newDirection) == conveyorBeltDirection) {
|
|
|
|
gameBoard.rotateRobotRight(robotAtConveyorBelt);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
newPositions.put(robotAtConveyorBelt, conveyorBeltPosition);
|
|
|
|
moveNormally.put(robotAtConveyorBelt, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-16 15:52:18 +01:00
|
|
|
/**
|
|
|
|
* Checks all flags for robots. Tries to update the flag of the robot.
|
|
|
|
*/
|
|
|
|
private void checkAllFlags() {
|
|
|
|
List<BoardElementContainer<Tile>> listOfFlags = gameBoard.getPositionsOfTileOnBoard(TileType.FLAG_1,
|
|
|
|
TileType.FLAG_2, TileType.FLAG_3, TileType.FLAG_4);
|
|
|
|
for (BoardElementContainer<Tile> flag:listOfFlags) {
|
|
|
|
Position flagPosition = flag.getPosition();
|
|
|
|
if (gameBoard.hasRobotOnPosition(flagPosition)) {
|
2020-04-09 19:57:29 +02:00
|
|
|
RobotID robotID = gameBoard.getRobotOnPosition(flagPosition);
|
|
|
|
for (Robot robot : gameBoard.getAliveRobots()) {
|
|
|
|
if (robot.getRobotId() != robotID || robot.isHasTouchedFlagThisTurn()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
gameBoard.updateFlagOnRobot(robotID, flag.getElement().getTileType());
|
|
|
|
robot.setHasTouchedFlagThisTurn(true);
|
2020-04-09 20:39:04 +02:00
|
|
|
if (victoryCheck(robot.getLastFlagVisited(), listOfFlags.size())) {
|
|
|
|
Player winningPlayer;
|
|
|
|
for (Player player : playerList) {
|
|
|
|
if (player.getRobotID() != robotID) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
winningPlayer = player;
|
|
|
|
}
|
|
|
|
//TODO: Make win screen announcing the winning player
|
|
|
|
}
|
2020-04-09 19:57:29 +02:00
|
|
|
}
|
2020-03-16 15:52:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-17 17:23:57 +01:00
|
|
|
|
2020-04-09 20:39:04 +02:00
|
|
|
private boolean victoryCheck(int lastFlagVisited, int lastFlag) {
|
|
|
|
return (lastFlagVisited == lastFlag);
|
|
|
|
}
|
2020-03-23 13:42:48 +01:00
|
|
|
/**
|
|
|
|
* Fires all lasers on the game board
|
|
|
|
*/
|
2020-03-23 13:47:34 +01:00
|
|
|
private void fireAllLasers() throws InterruptedException {
|
2020-03-17 17:23:57 +01:00
|
|
|
gameBoard.fireAllLasers();
|
2020-03-23 13:47:34 +01:00
|
|
|
sleep();
|
|
|
|
gameBoard.doLaserCleanup();
|
2020-03-17 17:23:57 +01:00
|
|
|
}
|
2020-03-24 14:02:03 +01:00
|
|
|
|
2020-03-24 14:28:42 +01:00
|
|
|
/**
|
2020-03-24 15:27:38 +01:00
|
|
|
* Runs all programming cards for a phase
|
|
|
|
* @param phase The number of the phase to run cards for
|
|
|
|
* @throws InterruptedException If it gets interrupted while trying to sleep
|
2020-03-24 14:28:42 +01:00
|
|
|
*/
|
2020-04-07 22:37:44 +02:00
|
|
|
private void runProgrammingCards(int phase) throws InterruptedException {
|
2020-03-24 14:02:03 +01:00
|
|
|
List<RobotID> robotsToDoAction = new ArrayList<>();
|
|
|
|
List<ProgrammingCard> programToBeRun = new ArrayList<>();
|
|
|
|
List<Integer> originalPriority = new ArrayList<>();
|
2020-03-24 15:26:20 +01:00
|
|
|
for (Player player : playerList) {
|
2020-03-24 14:02:03 +01:00
|
|
|
List<ProgrammingCard> playerProgram = player.getProgram();
|
|
|
|
if (!playerProgram.isEmpty()) {
|
2020-03-25 13:38:33 +01:00
|
|
|
ProgrammingCard programmingCard = playerProgram.get(phase - 1);
|
2020-03-24 15:26:20 +01:00
|
|
|
originalPriority.add(programmingCard.getPriority());
|
2020-03-24 14:02:03 +01:00
|
|
|
robotsToDoAction.add(player.getRobotID());
|
2020-03-24 15:26:20 +01:00
|
|
|
programToBeRun.add(programmingCard);
|
2020-03-24 14:02:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Collections.sort(programToBeRun);
|
2020-03-24 15:26:20 +01:00
|
|
|
for (ProgrammingCard card : programToBeRun) {
|
2020-03-24 14:02:03 +01:00
|
|
|
int i = originalPriority.indexOf(card.getPriority());
|
|
|
|
RobotID robot = robotsToDoAction.get(i);
|
|
|
|
makeMove(robot, card.getAction());
|
|
|
|
}
|
|
|
|
}
|
2020-03-30 18:32:55 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Respawn all the dead robots with more lives and places them on the game board
|
|
|
|
*/
|
2020-04-07 22:37:44 +02:00
|
|
|
private void respawnRobots() {
|
2020-03-30 18:32:55 +02:00
|
|
|
gameBoard.respawnRobots();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-03-31 13:45:35 +02:00
|
|
|
* repair all robots standing on a repair tile
|
2020-03-30 18:32:55 +02:00
|
|
|
*/
|
2020-04-07 22:37:44 +02:00
|
|
|
private void repairAllRobotsOnRepairTiles() {
|
|
|
|
for (BoardElementContainer<Tile> repairTile : repairTiles) {
|
|
|
|
Position robotOnTilePosition = repairTile.getPosition();
|
|
|
|
if (!gameBoard.hasRobotOnPosition(robotOnTilePosition)) {
|
2020-03-30 18:32:55 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
gameBoard.repairRobotOnTile(gameBoard.getRobotOnPosition(robotOnTilePosition));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-30 18:53:10 +02:00
|
|
|
/**
|
2020-04-07 22:37:44 +02:00
|
|
|
* Sets the robot's power down status to the player's "power down next round" status and sets the players status to false
|
2020-03-30 18:53:10 +02:00
|
|
|
*/
|
2020-04-07 22:37:44 +02:00
|
|
|
private void updateRobotPowerDown() {
|
|
|
|
for (Player player : playerList) {
|
|
|
|
setRobotPowerDown(player, player.getPowerDownNextRound());
|
2020-03-30 18:53:10 +02:00
|
|
|
player.setPowerDownNextRound(false);
|
|
|
|
}
|
|
|
|
}
|
2020-03-31 13:43:23 +02:00
|
|
|
|
|
|
|
/**
|
2020-04-07 22:37:44 +02:00
|
|
|
* Sets the power down status of a robot
|
|
|
|
* @param player The player that owns the robot
|
|
|
|
* @param powerDownStatus The new power down status
|
2020-03-31 13:43:23 +02:00
|
|
|
*/
|
2020-04-07 22:37:44 +02:00
|
|
|
private void setRobotPowerDown(Player player, Boolean powerDownStatus) {
|
|
|
|
gameBoard.setPowerDown(player.getRobotID(), powerDownStatus);
|
2020-03-31 13:43:23 +02:00
|
|
|
}
|
2020-03-12 11:49:14 +01:00
|
|
|
}
|