package ch.zhaw.catan; import ch.zhaw.catan.Config.Land; import ch.zhaw.hexboard.HexBoard; import ch.zhaw.hexboard.Label; import java.awt.Point; import java.util.*; //TODO Enhance JavaDoc /** * Subclass of HexBoard * Saves the fields which are set and handles Methods with specific Dice Numbers. */ public class SiedlerBoard extends HexBoard { /** * HashMap to save all Fields which are set yet. * Key: Point with coordinates of the field * //TODO Enhance JavaDoc * Value: Field Object */ HashMap fields = new HashMap<>(); /** * Method to create the predefined gamefield from Config. */ public void createFixGamefield(){ Map resourcePlacement = Config.getStandardLandPlacement(); Map dicePlacement = Config.getStandardDiceNumberPlacement(); for (Map.Entry resourceField : resourcePlacement.entrySet()) { addField(resourceField.getKey(),resourceField.getValue()); if(dicePlacement.get(resourceField.getKey()) != null){ String numberAsString = dicePlacement.get(resourceField.getKey()).toString(); char[] numbersInChar = numberAsString.toCharArray(); if (numberAsString.length() < 2) { fields.put(resourceField.getKey(), new Field(resourceField.getValue(), new Label('0', numbersInChar[0]))); } else { fields.put(resourceField.getKey(), new Field(resourceField.getValue(), new Label(numbersInChar[0],numbersInChar[1]))); } } } } /** * Method to get the DiceNumber of a specific field. * @param field Point with coordinates of the specific field * @return the DiceNumber of the field. */ private int getDiceNumber(Point field) { Label label = fields.get(field).getLabel(); return Integer.parseInt(label.toString()); } /** * Method to create a SiedlerBoardTextView Object set the LowerFieldLabels with theirs Dicenumber. * It is used to print the actual board in TextIO. * @return String of actual board. */ public String getTextView () { SiedlerBoardTextView view = new SiedlerBoardTextView(this); for (Map.Entry field : fields.entrySet()) { view.setLowerFieldLabel(field.getKey(), field.getValue().getLabel()); } return view.toString(); } /** * Returns the fields associated with the specified dice value. * * @param dice the dice value * @return the fields associated with the dice value */ public List getFieldsForDiceValue(int dice) { ArrayList fields = new ArrayList<>(); for(Point field : this.fields.keySet()){ if(getDiceNumber(field) == dice){ fields.add(field); } } return fields; } /** * Method to get the Resources which are paid to a specific faction for a specific field. * * @param point The Point with the Coordinates of the field, which should pay resources. * @param faction The faction, which should get paid. * @return a ArrayList with all resources, which will be paid to the specified faction. */ public ArrayList getResourcesForFaction(Point point, Config.Faction faction){ List possibleSettlementField = super.getCornersOfField(point); ArrayList resourcesToPlayer = new ArrayList<>(); for (Settlement settlement : possibleSettlementField) { if (settlement.getFaction() == faction) { resourcesToPlayer.add(fields.get(point).getResource()); if (settlement instanceof City) { resourcesToPlayer.add(fields.get(point).getResource()); } } } return resourcesToPlayer; } /** * Returns the {@link Land}s adjacent to the specified corner. * * @param corner the corner * @return the list with the adjacent {@link Land}s */ public List getLandsForCorner(Point corner) { Point above = new Point(corner.x, corner.y + 2); Point below = new Point(corner.x, corner.y -2); Land[] lands = new Land[3]; if (hasField(above)) { lands[0] = getField(above); lands[1] = getField(new Point(corner.x + 1, corner.y - 1)); lands[2] = getField(new Point(corner.x - 1, corner.y - 1)); } else if (hasField(below)) { lands[0] = getField(below); lands[1] = getField(new Point(corner.x + 1, corner.y + 1)); lands[2] = getField(new Point(corner.x - 1, corner.y + 1)); } else { return Collections.emptyList(); } return List.of(lands); } /** * This method checks for the player with the longest road according to the catan game rules. * @return a HashMap where faction is the player with the longest road longer according to catan game rules * and the Integer representing the length of the road */ public void getLongestRoadFaction(HashMap currentLongestRoad,List factionList) { List corners = getCorners(); HashMap players = new HashMap<>(); for(Config.Faction faction : factionList) { int count = 0; players.put(faction,count); for(Settlement settlement : corners){ if(settlement.getFaction() == faction){ HashSet roads = new HashSet<>(); roads = countRoad(faction,settlement.getPosition(),roads,true); count = roads.size(); int currentCount = players.get(faction); if(count > currentCount) { players.put(faction,count); } } } } if(currentLongestRoad.size() == 0) { Config.Faction currentFaction = null; int currentRoad = 4; for(Config.Faction factionA : players.keySet()) { if(players.get(factionA)>currentRoad) { currentFaction = factionA; currentRoad = players.get(factionA); } } if(currentFaction != null){ currentLongestRoad.put(currentFaction,currentRoad); } }else{ for(Config.Faction faction : players.keySet()) { for(Config.Faction faction1 : currentLongestRoad.keySet()) { if(players.get(faction) >= 5 && players.get(faction) > currentLongestRoad.get(faction1)) { currentLongestRoad.remove(faction1); currentLongestRoad.put(faction,players.get(faction)); } } } } } /** * This method is recursive and adds all roads which belongs to a specific players and stringing together to a HashSet. * The length of the HashSet represents the length of the longest Road the player has. * @param faction the faction of the player to check on * @param position there has to be a starting point to start counting. In this case it's a corner where a settlement belonging to the players faction is build on. * @param roads is the hashset with all roads belong to the player which are stringing together * @param add if true branches needs to be count together. (for example if it is the starting point(first time of counting)) otherwise the longest branch is beeing added to roads. * @return HashSet with all roads from a specific player which are string together. */ private HashSet countRoad(Config.Faction faction,Point position,HashSet roads,boolean add) { List roadslist = getAdjacentEdges(position); if(getCorner(position) != null && getCorner(position).getFaction() != faction) { return roads; } Iterator it2 = roads.iterator(); while(it2.hasNext()) { Road roadsroad = it2.next(); Iterator it3 = roadslist.iterator(); while (it3.hasNext()){ Road roadslistRoad = it3.next(); if(roadslistRoad == roadsroad || roadslistRoad.getFaction() != faction) { it3.remove(); } } } if(roadslist.size() == 1) { roads.add(roadslist.get(0)); position = getNextPoint(roadslist.get(0),position); roads = countRoad(faction,position,roads,false); } else if(roadslist.size() == 2) { HashSet listOne = (HashSet) roads.clone(); HashSet listTwo = (HashSet) roads.clone(); listOne.add(roadslist.get(0)); Point positionOne = getNextPoint(roadslist.get(0),position); listTwo.add(roadslist.get(1)); Point positionTwo = getNextPoint(roadslist.get(1),position); listOne = countRoad(faction,positionOne,listOne,false); listTwo = countRoad(faction,positionTwo,listTwo,false); if(add) { for (Road road : listOne) { listTwo.add(road); } roads = listTwo; }else { HashSet tallest; if(listOne.size()>= listTwo.size()) { tallest = listOne; }else{ tallest = listTwo; } for (Road road : tallest) { roads.add(road); } } } else if(roadslist.size() == 3) { HashSet listOne = (HashSet) roads.clone(); HashSet listTwo = (HashSet) roads.clone(); HashSet listThree = (HashSet) roads.clone(); listOne.add(roadslist.get(0)); Point positionOne = getNextPoint(roadslist.get(0),position); listTwo.add(roadslist.get(1)); Point positionTwo = getNextPoint(roadslist.get(1),position); listThree.add(roadslist.get(2)); Point positionThree = getNextPoint(roadslist.get(2),position); listOne = countRoad(faction,positionOne,listOne,false); listTwo = countRoad(faction,positionTwo,listTwo,false); listThree = countRoad(faction,positionThree,listThree,false); HashSet tallest; HashSet secondtallest; if(listOne.size()>=listTwo.size()) { tallest = listOne; secondtallest = listTwo; }else { tallest = listTwo; secondtallest = listOne; }if(listThree.size() >= secondtallest.size()) { secondtallest = listThree; } for(Road road : secondtallest) { tallest.add(road); } roads = tallest; } return roads; } /** * This method is beeing used to evaluate the next starting position to get the adjacent Roads from it. * @param road the next road to check on * @param position the current starting point * @return return the oposite point of the current point. */ private Point getNextPoint(Road road,Point position) { Point start = road.getStart(); Point end = road.getEnd(); if(position.equals(start)) { position = end; }else { position = start; } return position; } }