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;
|
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.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a board
|
* This class represents a board
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Board {
|
public class Board {
|
||||||
private Grid walls;
|
private int boardHeight;
|
||||||
private Grid otherObjects;
|
private int boardWidth;
|
||||||
private ArrayList<Robot> deadRobots = new ArrayList<>();
|
private IGrid<Wall> walls;
|
||||||
private ArrayList<Robot> aliveRobots;
|
private IGrid<Tile> tiles;
|
||||||
|
private Map<RobotID, Robot> robots;
|
||||||
|
private List<Robot> deadRobots;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the board
|
* Initializes the board
|
||||||
* @param walls a grid containing all the walls
|
* @param tiles A grid containing all tiles
|
||||||
* @param otherObjects a grid containing all the other Objects like flags and conveyor belts
|
* @param walls A grid containing all walls
|
||||||
* @param aliveRobots a list of all the robots that are currently alive
|
* @param robots A list of all robots in the game
|
||||||
*/
|
*/
|
||||||
public Board(Grid walls, Grid otherObjects, ArrayList aliveRobots){
|
public Board(IGrid<Tile> tiles, IGrid<Wall> walls, List<Robot> robots) {
|
||||||
this.walls=walls;
|
if (walls.getWidth() != tiles.getWidth() || walls.getHeight() != tiles.getHeight()) {
|
||||||
this.otherObjects=otherObjects;
|
throw new IllegalArgumentException("The grids in the input don't have the same dimensions.");
|
||||||
this.aliveRobots=aliveRobots;
|
}
|
||||||
|
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
|
* @param robot the dead robot
|
||||||
*/
|
*/
|
||||||
public void removeDeadRobotFromBoard(Robot robot){
|
public void removeDeadRobotFromBoard(Robot robot) {
|
||||||
aliveRobots.remove(robot);
|
robots.remove(robot.getRobotId());
|
||||||
deadRobots.add(robot);
|
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