public Set<Location> getPlayerFeatures(Player player, Class<? extends Feature> featureClass) { Set<Location> locations = new HashSet<>(); for (Feature f : features) { if (!featureClass.isInstance(f)) continue; if (f.walk(new IsOccupied().with(player).with(Follower.class))) { locations.add(f.getLocation()); } } return locations; }
public Set<Location> getUnoccupiedScoreables(boolean excludeCompleted) { Set<Location> locations = new HashSet<>(); for (Feature f : features) { // if (f instanceof Farm && !game.hasCapability(Capability.FARM_PLACEMENT)) continue; if (f instanceof Scoreable) { IsOccupied visitor; if (excludeCompleted && f instanceof Completable) { visitor = new IsOccupiedOrCompleted(); } else { visitor = new IsOccupied(); } if (f.walk(visitor)) continue; locations.add(f.getLocation()); } } return locations; }
private void fillHints() { hints.clear(); final Set<Feature> processed = new HashSet<>(); for (Entry<Tile, Map<Location, Area>> entry : areas.entrySet()) { for (Feature f : entry.getKey().getFeatures()) { if (!(f instanceof Farm)) continue; if (processed.contains(f)) continue; FarmHint fh = f.walk( new FeatureVisitor<FarmHint>() { FarmHint result = new FarmHint(new Area(), null); int x = Integer.MAX_VALUE; int y = Integer.MAX_VALUE; int size = 0; boolean hasCity = false; int[] power = new int[getGame().getAllPlayers().length]; @Override public boolean visit(Feature feature) { Farm f = (Farm) feature; processed.add(f); size++; hasCity = hasCity || f.getAdjoiningCities() != null || f.isAdjoiningCityOfCarcassonne(); for (Meeple m : f.getMeeples()) { if (m instanceof Follower) { power[m.getPlayer().getIndex()] += ((Follower) m).getPower(); } if (m instanceof Barn) { power[m.getPlayer().getIndex()] += 1; } } Position pos = f.getTile().getPosition(); if (pos.x < x) { if (x != Integer.MAX_VALUE) result.area.transform( AffineTransform.getTranslateInstance(FULL_SIZE * (x - pos.x), 0)); x = pos.x; } if (pos.y < y) { if (y != Integer.MAX_VALUE) result.area.transform( AffineTransform.getTranslateInstance(0, FULL_SIZE * (y - pos.y))); y = pos.y; } Map<Location, Area> tileAreas = areas.get(f.getTile()); if (tileAreas != null) { // sync issue, feature can be extended in other thread, so it is // not registered in areas yet Area featureArea = new Area(tileAreas.get(f.getLocation())); featureArea.transform( AffineTransform.getTranslateInstance( FULL_SIZE * (pos.x - x), FULL_SIZE * (pos.y - y))); result.area.add(featureArea); } return true; } @Override public FarmHint getResult() { result.position = new Position(x, y); int bestPower = 0; List<Integer> bestPlayerIndexes = new ArrayList<>(); for (int i = 0; i < power.length; i++) { if (power[i] == bestPower) { bestPlayerIndexes.add(i); } if (power[i] > bestPower) { bestPower = power[i]; bestPlayerIndexes.clear(); bestPlayerIndexes.add(i); } } if (bestPower == 0) { if (size < 2 || !hasCity) return null; // don't display unimportant farms result.colors = new Color[] {Color.DARK_GRAY}; } else { result.colors = new Color[bestPlayerIndexes.size()]; int i = 0; for (Integer index : bestPlayerIndexes) { result.colors[i++] = getGame().getPlayer(index).getColors().getMeepleColor(); } } return result; } }); if (fh == null) continue; // to small farm hints.add(fh); } } }