mirror of
https://github.com/inf112-v20/Fiasko.git
synced 2025-01-31 23:29:36 +01:00
Oppdaterer brettet med nødvendige metoder for å kunne flytte en robot
Legger til tester for brettet
This commit is contained in:
parent
248b842536
commit
544e5d9e04
@ -1,36 +1,211 @@
|
||||
package inf112.fiasko.roborally.objects;
|
||||
|
||||
import inf112.fiasko.roborally.element_properties.Direction;
|
||||
import inf112.fiasko.roborally.element_properties.Position;
|
||||
import inf112.fiasko.roborally.element_properties.RobotID;
|
||||
import inf112.fiasko.roborally.element_properties.TileType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class represents a board
|
||||
*/
|
||||
|
||||
public class Board {
|
||||
private Grid walls;
|
||||
private Grid otherObjects;
|
||||
private ArrayList<Robot> deadRobots = new ArrayList<>();
|
||||
private ArrayList<Robot> aliveRobots;
|
||||
private int boardHeight;
|
||||
private int boardWidth;
|
||||
private IGrid<Wall> walls;
|
||||
private IGrid<Tile> tiles;
|
||||
private Map<RobotID, Robot> robots;
|
||||
private List<Robot> deadRobots;
|
||||
|
||||
/**
|
||||
* Initializes the board
|
||||
* @param walls a grid containing all the walls
|
||||
* @param otherObjects a grid containing all the other Objects like flags and conveyor belts
|
||||
* @param aliveRobots a list of all the robots that are currently alive
|
||||
* @param tiles A grid containing all tiles
|
||||
* @param walls A grid containing all walls
|
||||
* @param robots A list of all robots in the game
|
||||
*/
|
||||
public Board(Grid walls, Grid otherObjects, ArrayList aliveRobots){
|
||||
this.walls=walls;
|
||||
this.otherObjects=otherObjects;
|
||||
this.aliveRobots=aliveRobots;
|
||||
public Board(IGrid<Tile> tiles, IGrid<Wall> walls, List<Robot> robots) {
|
||||
if (walls.getWidth() != tiles.getWidth() || walls.getHeight() != tiles.getHeight()) {
|
||||
throw new IllegalArgumentException("The grids in the input don't have the same dimensions.");
|
||||
}
|
||||
this.robots = new HashMap<>();
|
||||
for (Robot robot : robots) {
|
||||
if (this.robots.get(robot.getRobotId()) != null) {
|
||||
throw new IllegalArgumentException("There can't be two robots with the same robot id.");
|
||||
}
|
||||
this.robots.put(robot.getRobotId(), robot);
|
||||
}
|
||||
this.deadRobots = new ArrayList<>();
|
||||
this.boardWidth = tiles.getWidth();
|
||||
this.boardHeight = tiles.getHeight();
|
||||
this.walls = walls;
|
||||
this.tiles = tiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a dead robot from the board over to the dead robot list.
|
||||
* Gets the height of the board
|
||||
* @return The height of the board
|
||||
*/
|
||||
public int getBoardHeight() {
|
||||
return boardHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the width of the board
|
||||
* @return The width of the board
|
||||
*/
|
||||
public int getBoardWidth() {
|
||||
return boardWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves all dead robots to their backups and makes them part of the board again
|
||||
*/
|
||||
public void respawnRobots() {
|
||||
//TODO: Account for several robots re-spawning at same backup
|
||||
for (Robot robot : deadRobots) {
|
||||
robot.setPosition(robot.getBackupPosition());
|
||||
robots.put(robot.getRobotId(), robot);
|
||||
}
|
||||
deadRobots = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a dead robot from the board over to the dead robot list
|
||||
* @param robot the dead robot
|
||||
*/
|
||||
public void removeDeadRobotFromBoard(Robot robot){
|
||||
aliveRobots.remove(robot);
|
||||
public void removeDeadRobotFromBoard(Robot robot) {
|
||||
robots.remove(robot.getRobotId());
|
||||
deadRobots.add(robot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a robot one unit in a specified direction
|
||||
* @param robotID ID of the robot to move
|
||||
* @param direction The direction to move the robot
|
||||
* @return True if the robot moved away from its old position
|
||||
*/
|
||||
public boolean moveRobot(RobotID robotID, Direction direction) {
|
||||
Robot robot = robots.get(robotID);
|
||||
Position robotPosition = robot.getPosition();
|
||||
Position newPosition = getNewPosition(robotPosition, direction);
|
||||
//Robot tried to go outside of the map. Kill it.
|
||||
if (newPosition.getXCoordinate() < 0
|
||||
|| newPosition.getXCoordinate() >= boardWidth
|
||||
|| newPosition.getYCoordinate() < 0
|
||||
|| newPosition.getYCoordinate() >= boardHeight) {
|
||||
killRobot(robot);
|
||||
return true;
|
||||
}
|
||||
//There is a wall blocking the robot. It can't proceed.
|
||||
if (hasWallFacing(robotPosition, direction) ||
|
||||
hasWallFacing(newPosition, Direction.getReverseDirection(direction))) {
|
||||
return false;
|
||||
}
|
||||
//If another robot is blocking this robot's path, try to shove it.
|
||||
if (hasRobotOnPosition(newPosition)) {
|
||||
RobotID otherRobotID = getRobotOnPosition(newPosition);
|
||||
if (otherRobotID != null && !moveRobot(otherRobotID, direction)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//Some tiles may kill the robot if stepped on.
|
||||
Tile tileRobotStepsOn = tiles.getElement(newPosition.getXCoordinate(), newPosition.getYCoordinate());
|
||||
if (tileRobotStepsOn == null) {
|
||||
throw new IllegalArgumentException("The game board is missing a tile. This should not happen.");
|
||||
}
|
||||
TileType tileTypeRobotStepsOn = tileRobotStepsOn.getTileType();
|
||||
if (tileTypeRobotStepsOn == TileType.HOLE || tileTypeRobotStepsOn == TileType.DEATH_TILE) {
|
||||
killRobot(robot);
|
||||
return true;
|
||||
}
|
||||
robot.setPosition(newPosition);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kills the robot
|
||||
*
|
||||
* If the robot steps outside of the board, steps on a hole or takes too much damage, this method should be used to
|
||||
* properly dispose of the robot until the next round.
|
||||
*
|
||||
* @param robot The robot to kill
|
||||
*/
|
||||
private void killRobot(Robot robot) {
|
||||
//TODO: Must remove a life from the robot/player
|
||||
removeDeadRobotFromBoard(robot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a robot id for a robot on a specific position if such a robot exists
|
||||
* @param position The position to check
|
||||
* @return The robot id of the robot on the position or null if there is no robot there
|
||||
*/
|
||||
private RobotID getRobotOnPosition(Position position) {
|
||||
for (RobotID robotID : robots.keySet()) {
|
||||
Robot robot = robots.get(robotID);
|
||||
if (position.equals(robot.getPosition())) {
|
||||
return robotID;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there exists a robot on a specific position
|
||||
* @param position The position to check
|
||||
* @return True if there is a robot on the specified position
|
||||
*/
|
||||
private boolean hasRobotOnPosition(Position position) {
|
||||
return getRobotOnPosition(position) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a position has a wall facing a specific direction
|
||||
* @param position The position to check
|
||||
* @param direction The direction of the wall to check for
|
||||
* @return True if there is a wall on the position facing the input direction
|
||||
*/
|
||||
private boolean hasWallFacing(Position position, Direction direction) {
|
||||
Wall wall = walls.getElement(position.getXCoordinate(), position.getYCoordinate());
|
||||
if (wall == null) {
|
||||
return false;
|
||||
}
|
||||
switch (wall.getDirection()) {
|
||||
case NORTH_EAST:
|
||||
return direction == Direction.NORTH || direction == Direction.EAST;
|
||||
case NORTH_WEST:
|
||||
return direction == Direction.NORTH || direction == Direction.WEST;
|
||||
case SOUTH_WEST:
|
||||
return direction == Direction.SOUTH || direction == Direction.WEST;
|
||||
case SOUTH_EAST:
|
||||
return direction == Direction.SOUTH || direction == Direction.EAST;
|
||||
}
|
||||
return wall.getDirection() == direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position 1 unit in a specific direction from another position
|
||||
* @param oldPosition The old/current position of the element
|
||||
* @param direction The direction to move the element
|
||||
* @return The new position of the element
|
||||
*/
|
||||
private Position getNewPosition(Position oldPosition, Direction direction) {
|
||||
//TODO: Make sure we're accounting for the flipped y axis in libgdx
|
||||
switch (direction) {
|
||||
case NORTH:
|
||||
return new Position(oldPosition.getXCoordinate(), oldPosition.getYCoordinate() + 1);
|
||||
case SOUTH:
|
||||
return new Position(oldPosition.getXCoordinate(), oldPosition.getYCoordinate() - 1);
|
||||
case EAST:
|
||||
return new Position(oldPosition.getXCoordinate() + 1, oldPosition.getYCoordinate());
|
||||
case WEST:
|
||||
return new Position(oldPosition.getXCoordinate() - 1, oldPosition.getYCoordinate());
|
||||
default:
|
||||
throw new IllegalArgumentException("It's not possible to move in that direction.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
65
src/test/java/inf112/fiasko/roborally/objects/BoardTest.java
Normal file
65
src/test/java/inf112/fiasko/roborally/objects/BoardTest.java
Normal file
@ -0,0 +1,65 @@
|
||||
package inf112.fiasko.roborally.objects;
|
||||
|
||||
import inf112.fiasko.roborally.element_properties.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class BoardTest {
|
||||
private Grid<Tile> tileGrid;
|
||||
private Grid<Wall> wallGrid;
|
||||
private Position someValidPosition;
|
||||
private List<Robot> robotList;
|
||||
private Board board;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
tileGrid = new Grid<>(5, 5, new Tile(TileType.TILE, Direction.NORTH));
|
||||
wallGrid = new Grid<>(5, 5);
|
||||
someValidPosition = new Position(2, 2);
|
||||
robotList = new ArrayList<>();
|
||||
robotList.add(new Robot(RobotID.ROBOT_1, someValidPosition));
|
||||
wallGrid.setElement(2, 3, new Wall(WallType.WALL_NORMAL, Direction.SOUTH));
|
||||
wallGrid.setElement(2, 2, new Wall(WallType.WALL_NORMAL, Direction.EAST));
|
||||
wallGrid.setElement(1, 2, new Wall(WallType.WALL_CORNER, Direction.NORTH_EAST));
|
||||
board = new Board(tileGrid, wallGrid, robotList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void robotCanMove() {
|
||||
assertTrue(board.moveRobot(RobotID.ROBOT_1, Direction.SOUTH));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void robotIsStoppedByWallOnSameTile() {
|
||||
assertFalse(board.moveRobot(RobotID.ROBOT_1, Direction.EAST));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void robotIsStoppedByWallOnAdjacentTile() {
|
||||
assertFalse(board.moveRobot(RobotID.ROBOT_1, Direction.NORTH));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void robotIsStoppedByCornerWall() {
|
||||
assertFalse(board.moveRobot(RobotID.ROBOT_1, Direction.WEST));
|
||||
}
|
||||
|
||||
@Test (expected = IllegalArgumentException.class)
|
||||
public void gridsOfDifferentSizeThrowsError() {
|
||||
IGrid<Wall> wallGrid = new Grid<>(1, 1);
|
||||
new Board(tileGrid, wallGrid, robotList);
|
||||
}
|
||||
|
||||
@Test (expected = IllegalArgumentException.class)
|
||||
public void multipleRobotsWithSameIDThrowsError() {
|
||||
Robot robot = new Robot(RobotID.ROBOT_1, someValidPosition);
|
||||
robotList.add(robot);
|
||||
new Board(tileGrid, wallGrid, robotList);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user