package nl.tudelft.bw4t.environmentstore.editor.model; import java.util.ArrayList; import java.util.List; import java.util.Random; import nl.tudelft.bw4t.environmentstore.editor.model.Node.DoorDirection; import nl.tudelft.bw4t.map.BlockColor; import nl.tudelft.bw4t.map.Zone; import nl.tudelft.bw4t.map.Zone.Type; /** * Every space in the map is a Zone that is later changed to a corridor, room * etc. * */ public class ZoneModel { /** max amount spawn points per spawn point */ public static final int SPAWN_POINTS_PER_START_ZONE = 4; private Zone zone; private Type type = Type.CORRIDOR; /** BlockColors the zone contains */ private List<BlockColor> colors = new ArrayList<>(); /** direction for doors */ public static final int NORTH = 0; public static final int EAST = 1; public static final int SOUTH = 2; public static final int WEST = 3; /** true if zone has door for that direction */ private boolean[] doorsbool = new boolean[4]; /** the 4 neighbours of a zone */ private ZoneModel[] neighbours = new ZoneModel[4]; /** true if zone is dropzone */ private boolean isDropZone = false; /** true if zone is startzone */ private boolean isStartZone = false; /** name of the zone on the grid */ private String coordiname = ""; public ZoneModel() { } public ZoneModel(Zone zone) { this.zone = zone; this.type = zone.getType(); this.colors = zone.getBlocks(); this.isStartZone = isStartZone(zone); this.isDropZone = isDropZone(zone); this.doorsbool[0] = zone.hasNorth(); this.doorsbool[1] = zone.hasEast(); this.doorsbool[2] = zone.hasSouth(); this.doorsbool[3] = zone.hasWest(); } public ZoneModel(Node n) { type = n.getType(); Node.DoorDirection dir = n.getDir(); int index; if (type == Type.ROOM) { if (dir == DoorDirection.NORTH) { index = 0; } else if (dir == DoorDirection.EAST) { index = 1; } else if (dir == DoorDirection.SOUTH) { index = 2; } else { index = 3; } doorsbool[index] = true; } } public Zone getZone() { return zone; } public Type getType() { return type; } public void setType(Type t) { type = t; if (type == Type.ROOM && !hasDoors()) { placeDoor(); } changeNeighboursDoor(); } /** Places a door at the first spot it can find. */ private void placeDoor() { if (canPlaceDoor(NORTH)) { setDoor(NORTH, true); } else if (canPlaceDoor(EAST)) { setDoor(EAST, true); } else if (canPlaceDoor(SOUTH)) { setDoor(SOUTH, true); } else if (canPlaceDoor(WEST)) { setDoor(WEST, true); } } /** Removes all doors. */ private void removeDoors() { setDoor(EAST, false); setDoor(NORTH, false); setDoor(SOUTH, false); setDoor(WEST, false); } /** * This ensures that when a change is brought to the map, the doors can * still be reachable for the bots. */ private void changeNeighboursDoor() { changeNeighbourDoor(NORTH, SOUTH); changeNeighbourDoor(EAST, WEST); changeNeighbourDoor(SOUTH, NORTH); changeNeighbourDoor(WEST, EAST); } /** Changes the door of one neighbour. */ private void changeNeighbourDoor(int dir, int oppositdir) { if (neighbours[dir] != null && neighbours[dir].getType() == Type.ROOM && (neighbours[dir].hasDoor(oppositdir) || !neighbours[dir] .hasDoors())) { if (!neighbours[dir].canPlaceDoors()) { neighbours[dir].removeDoors(); } else { neighbours[dir].placeDoor(); } } } /** * If the neighbour is a corridor or charge zone, we can place a door on * this side. */ public boolean canPlaceDoor(int dir) { return getNeighbour(dir) != null && (getNeighbour(dir).type == Type.CORRIDOR || getNeighbour(dir).type == Type.CHARGINGZONE); } /** Returns true if a door can be placed. */ private boolean canPlaceDoors() { return canPlaceDoor(NORTH) || canPlaceDoor(EAST) || canPlaceDoor(SOUTH) || canPlaceDoor(WEST); } /** * Gets the name of the Zone based on the type of Zone. * * @return the name of the zone based on its type. */ public String getName() { if (isDropZone()) { return nl.tudelft.bw4t.map.Zone.DROP_ZONE_NAME; } else if (isStartZone()) { return nl.tudelft.bw4t.map.Zone.START_ZONE_NAME + coordiname; } else if (getType() == Type.BLOCKADE) { return nl.tudelft.bw4t.map.Zone.BLOCKADE_NAME + coordiname; } else if (getType() == Type.CHARGINGZONE) { return nl.tudelft.bw4t.map.Zone.CHARGING_ZONE_NAME + coordiname; } else if (getType() == Type.CORRIDOR) { return nl.tudelft.bw4t.map.Zone.CORRIDOR_NAME + coordiname; } else if (getType() == Type.ROOM) { return nl.tudelft.bw4t.map.Zone.ROOM_NAME + coordiname; } else { return coordiname; } } public void setName(String n) { coordiname = n; } public List<BlockColor> getColors() { if (type == Type.ROOM) { return colors; } else { return new ArrayList<BlockColor>(); } } public void setColors(List<BlockColor> cs) { if (cs == null) { throw new NullPointerException("Null list not allowed for colors"); } colors = cs; } public boolean hasDoor(int dir) { return doorsbool[dir]; } public boolean hasDoors() { return hasDoor(NORTH) || hasDoor(EAST) || hasDoor(SOUTH) || hasDoor(WEST); } public void setDoor(int dir, boolean value) { doorsbool = new boolean[4]; doorsbool[dir] = value; } public boolean isDropZone() { return isDropZone; } public void setDropZone(boolean isDZ) { isDropZone = isDZ; } public boolean isStartZone() { return isStartZone; } public void setStartZone(boolean isSZ) { isStartZone = isSZ; } public boolean[] getDoorsBool() { return doorsbool; } /** * @param zone * The current zone. * @return The row the zone belongs to. */ public static int calcRow(Zone zone) { double y = zone.getBoundingbox().getY(); return calcRow(y - MapConverter.ROOMHEIGHT / 2.); } /** * @param y * The position in y * @return The row the point belongs to. */ public static int calcRow(double y) { return (int) (y / MapConverter.ROOMHEIGHT); } /** * @param zone * The current zone. * @return The column the zone belongs to. */ public static int calcColumn(Zone zone) { double x = zone.getBoundingbox().getX(); return calcColumn(x - MapConverter.ROOMWIDTH / 2.); } /** * @param x * The position in x * @return The column the point belongs to. */ public static int calcColumn(double x) { return (int) (x / MapConverter.ROOMWIDTH); } private boolean isStartZone(Zone zone) { return zone != null && zone.getName() != null && zone.getName().startsWith("StartZone"); } private boolean isDropZone(Zone zone) { return zone != null && zone.getName() != null && zone.getName().startsWith(Zone.DROP_ZONE_NAME); } public int getSpawnCount() { if (isStartZone()) { return SPAWN_POINTS_PER_START_ZONE; } return 0; } /** * Randomizes the blocks in a zone * * @param amount * the max amount of blocks in that zone * @param validcolors * list of colors to choose from */ public void generateRandomBlocks(int amount, List<BlockColor> validcolors) { if (getType() == Type.ROOM && !isDropZone()) { final int numColors = validcolors.size(); Random random = new Random(); ArrayList<BlockColor> colors = new ArrayList<BlockColor>(); for (int i = 0; i < random.nextInt(amount) + 1; i++) { colors.add(validcolors.get(random.nextInt(numColors))); } setColors(colors); } } public void generateNameFromPosition(int row, int col) { StringBuilder sb = new StringBuilder(); while (col >= 26) { sb.append((char) ('A' + (col % 26))); col = col / 26 - 1; } sb.append((char) ('A' + col)); sb.reverse(); sb.append(row + 1); setName(sb.toString()); } public ZoneModel getNeighbour(int pos) { return neighbours[pos]; } public void setNeighbour(int pos, ZoneModel neighbour) { neighbours[pos] = neighbour; } }