Skip to content

Commit

Permalink
Merge pull request #14 from Mw3y/step-7
Browse files Browse the repository at this point in the history
Step 7
  • Loading branch information
Mw3y authored Apr 9, 2024
2 parents eaf814f + 1ef3128 commit 7bb5fa0
Show file tree
Hide file tree
Showing 9 changed files with 394 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ChaCuN.iml
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@
<SOURCES />
</library>
</orderEntry>
<orderEntry type="library" name="OpenJFX 22" level="application" />
</component>
</module>
12 changes: 8 additions & 4 deletions src/ch/epfl/chacun/GameState.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ public Set<Occupant> lastTilePotentialOccupants() {
// Prevent the player from placing a pawn on a zone within an occupied area
return switch (zone) {
case Zone.Forest forest -> board.forestArea(forest).isOccupied();
case Zone.River river when occupant.kind() == Occupant.Kind.PAWN -> board.riverArea(river).isOccupied();
case Zone.River river when occupant.kind() == Occupant.Kind.PAWN ->
board.riverArea(river).isOccupied();
case Zone.Meadow meadow -> board.meadowArea(meadow).isOccupied();
case Zone.Water water -> board.riverSystemArea(water).isOccupied();
};
Expand Down Expand Up @@ -275,7 +276,7 @@ private GameState withTurnFinishedIfOccupationImpossible() {
* - Determines whether the current player can play again.<p>
* - Draws from the deck containing the next tile to place all the tiles which can't be placed.<p>
* - Pass to the next player if the current one can't play again.<p>
* - Ends the game when the there is no more normal tiles to place.
* - Ends the game when there is no more normal tiles to place.
*
* @return an updated game state
*/
Expand Down Expand Up @@ -337,7 +338,7 @@ private GameState withTurnFinished() {
* Manages the attribution of the points at the end of the game.
* <p>
* Attributes the points given by : <p>
* - the meadows, considering the presence of the wildfire or the pit trap.<p>
* - the meadows, considering the presence of the wildfire and the pit trap.<p>
* - the river systems, considering the presence of the raft.<p>
* Determines the winners of the game.
*
Expand All @@ -360,10 +361,13 @@ private GameState withFinalPointsCounted() {
updatedBoard = updatedBoard
.withMoreCancelledAnimals(computeCancelledAnimals(meadow, 0));
}
// Check if the meadow contains a pit trap
if (meadow.tileIds().contains(PIT_TRAP_TILE_ID)) {
// Determine the adjacent meadows of the pit trap
Area<Zone.Meadow> adjacentMeadow = updatedBoard
.adjacentMeadow(updatedBoard.tileWithId(PIT_TRAP_TILE_ID).pos(),
(Zone.Meadow) meadow.zoneWithSpecialPower(Zone.SpecialPower.PIT_TRAP));
// Attribute points scored by the pit trap
updatedMessageBoard = updatedMessageBoard
.withScoredPitTrap(adjacentMeadow, updatedBoard.cancelledAnimals());
}
Expand Down Expand Up @@ -449,7 +453,7 @@ private Set<Animal> computeCancelledAnimalsWithPitTrap(Area<Zone.Meadow> meadow,
// Subtract the number of deer which are out of the pit trap reach from the tiger number
tigerNb -= getAnimalsOfKind(Area.animals(outOfReachMeadowArea, Set.of()), Animal.Kind.DEER).size();
// Add the remaining cancelled animals from the adjacent meadows
//cancelledAnimals.addAll(computeCancelledAnimals(adjacentMeadowArea, tigerNb));
if (tigerNb > 0) cancelledAnimals.addAll(computeCancelledAnimals(adjacentMeadowArea, tigerNb));
return cancelledAnimals;
}

Expand Down
6 changes: 5 additions & 1 deletion src/ch/epfl/chacun/TextMaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
import java.util.Map;
import java.util.Set;


/**
* A text maker. It is responsible for generating the text of messages that are displayed to the players.
*
* @author Michel Schinz (sciper: 103610)
*/
public interface TextMaker {
/**
* Returns the name of the player of the given color.
Expand Down
162 changes: 162 additions & 0 deletions src/ch/epfl/chacun/TextMakerFr.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package ch.epfl.chacun;

import java.util.*;

/**
* Implementation of the French text maker.
* It generates the text of French messages that are displayed to the players.
*
* @author Maxence Espagnet (sciper: 372808)
* @author Balthazar Baillat (sciper: 373420)
*/
public final class TextMakerFr implements TextMaker {

private final Map<PlayerColor, String> players;

public TextMakerFr(Map<PlayerColor, String> players) {
this.players = new HashMap<>(players);
}

private String pluralize(String word, boolean isPlural) {
boolean isInclusive = word.contains("·");
return isPlural ? STR."\{word}\{isInclusive ? "·" : ""}s" : word;
}

private <E> String pluralize(String word, Collection<E> values) {
return pluralize(word, values.size() > 1);
}

private String accord(String word, int value) {
return STR."\{value} \{pluralize(word, value > 1)}";
}

private String conjugateEarn(Set<PlayerColor> players) {
return players.size() > 1 ? "ont remporté" : "a remporté";
}

private String humanizedJoin(List<String> strings) {
Preconditions.checkArgument(!strings.isEmpty());
if (strings.size() == 2) {
return String.join(" et ", strings);
}
if (strings.size() > 2) {
String firstHalf = String.join(", ", strings.subList(0, strings.size() - 1));
return STR."\{firstHalf} et \{strings.getLast()}";
}
return strings.getFirst();
}

private String joinPlayerNames(Set<PlayerColor> playerColors) {
return humanizedJoin(playerColors.stream().sorted().map(this::playerName).toList());
}

private String joinAnimalsWithQuantities(Map<Animal.Kind, Integer> animals) {
return humanizedJoin(animals.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.filter(e -> e.getValue() > 0)
.map(e -> accord(getAnimalName(e.getKey()), e.getValue()))
.toList());
}

private String getAnimalName(Animal.Kind kind) {
return switch (kind) {
case MAMMOTH -> "mammouth";
case AUROCHS -> "auroch";
case DEER -> "cerf";
case TIGER -> "smilodon";
};
}

@Override
public String playerName(PlayerColor playerColor) {
return players.get(playerColor);
}

@Override
public String points(int points) {
return accord("point", points);
}

@Override
public String playerClosedForestWithMenhir(PlayerColor player) {
return STR."\{playerName(player)} a fermé une forêt contenant un menhir et peut donc placer une tuile menhir.";
}

@Override
public String playersScoredForest(Set<PlayerColor> scorers, int points, int mushroomGroupCount, int tileCount) {
String mushrooms = mushroomGroupCount > 0 ?
STR." et de \{accord("groupe", mushroomGroupCount)} de champignons" : "";
return STR."\{joinPlayerNames(scorers)} \{conjugateEarn(scorers)} \{points(points)} en tant " +
STR."qu'\{pluralize("occupant·e", scorers)} " +
STR."\{pluralize("majoritaire", scorers)} d'une forêt " +
STR."composée de \{accord("tuile", tileCount)}\{mushroomGroupCount > 0 ? mushrooms : ""}.";
}

@Override
public String playersScoredRiver(Set<PlayerColor> scorers, int points, int fishCount, int tileCount) {
return STR."\{joinPlayerNames(scorers)} \{conjugateEarn(scorers)} \{points(points)} en tant qu'" +
STR."\{pluralize("occupant·e", scorers)} " +
STR."\{pluralize("majoritaire", scorers)} d'une rivière " +
STR."composée de \{accord("tuile", tileCount)}" +
STR."\{fishCount > 0 ? STR." et contenant \{accord("poisson", fishCount)}" : ""}.";
}

@Override
public String playerScoredHuntingTrap(PlayerColor scorer, int points, Map<Animal.Kind, Integer> animals) {
return STR."\{playerName(scorer)} a remporté \{points(points)} en plaçant la fosse à pieux dans un pré " +
STR."dans lequel elle est entourée de \{joinAnimalsWithQuantities(animals)}.";
}

@Override
public String playerScoredLogboat(PlayerColor scorer, int points, int lakeCount) {
return STR."\{playerName(scorer)} a remporté \{points(points)} en plaçant la pirogue dans un réseau " +
STR."hydrographique contenant \{accord("lac", lakeCount)}.";
}

@Override
public String playersScoredMeadow(Set<PlayerColor> scorers, int points, Map<Animal.Kind, Integer> animals) {
return STR."\{joinPlayerNames(scorers)} \{conjugateEarn(scorers)} \{points(points)} en tant qu'" +
STR."\{pluralize("occupant·e", scorers)} " +
STR."\{pluralize("majoritaire", scorers)} d'un pré contenant " +
STR."\{joinAnimalsWithQuantities(animals)}.";
}

@Override
public String playersScoredRiverSystem(Set<PlayerColor> scorers, int points, int fishCount) {
return STR."\{joinPlayerNames(scorers)} \{conjugateEarn(scorers)} \{points(points)} en tant qu'" +
STR."\{pluralize("occupant·e", scorers)} " +
STR."\{pluralize("majoritaire", scorers)} d'un réseau " +
STR."hydrographique contenant \{accord("poisson", fishCount)}.";
}

@Override
public String playersScoredPitTrap(Set<PlayerColor> scorers, int points, Map<Animal.Kind, Integer> animals) {
return STR."\{joinPlayerNames(scorers)} \{conjugateEarn(scorers)} \{points(points)} " +
STR."en tant qu'\{pluralize("occupant·e", scorers)} " +
STR."\{pluralize("majoritaire", scorers)} d'un pré contenant " +
STR."la grande fosse à pieux entourée de \{joinAnimalsWithQuantities(animals)}.";
}

@Override
public String playersScoredRaft(Set<PlayerColor> scorers, int points, int lakeCount) {
return STR."\{joinPlayerNames(scorers)} \{conjugateEarn(scorers)} \{points(points)} en tant " +
STR."qu'\{pluralize("occupant·e", scorers)} " +
STR."\{pluralize("majoritaire", scorers)} " +
STR."d'un réseau hydrographique contenant le radeau et \{accord("lac", lakeCount)}.";
}

@Override
public String playersWon(Set<PlayerColor> winners, int points) {
return STR."\{joinPlayerNames(winners)} \{conjugateEarn(winners)} la partie avec \{points(points)} !";
}

@Override
public String clickToOccupy() {
return "Cliquez sur le pion ou la hutte que vous désirez placer, ou ici pour ne pas en placer.";
}

@Override
public String clickToUnoccupy() {
return "Cliquez sur le pion que vous désirez reprendre, ou ici pour ne pas en reprendre.";
}
}
56 changes: 56 additions & 0 deletions src/ch/epfl/chacun/gui/ColorMap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package ch.epfl.chacun.gui;

import ch.epfl.chacun.PlayerColor;
import javafx.scene.paint.Color;

/**
* Helper class to map player colors to JavaFX colors.
*
* @author Maxence Espagnet (sciper: 372808)
* @author Balthazar Baillat (sciper: 373420)
*/
public final class ColorMap {

/**
* The opacity factor to use for the stroke color.
*/
private static final double STROKE_BRIGHTNESS_FACTOR = .6;

/**
* Non-instantiable class constructor
*/
private ColorMap() {
}

/**
* Returns the fill color for the given player color.
*
* @param playerColor the player color
* @return the fill color
*/
public static Color fillColor(PlayerColor playerColor) {
return switch (playerColor) {
case RED -> Color.RED;
case BLUE -> Color.BLUE;
case GREEN -> Color.LIME;
case YELLOW -> Color.YELLOW;
case PURPLE -> Color.PURPLE;
};
}

/**
* Returns the stroke color for the given player color.
*
* @param playerColor the player color
* @return the stroke color
*/
public static Color strokeColor(PlayerColor playerColor) {
// For better contrast with light colors, use a darker stroke color
if (playerColor == PlayerColor.YELLOW || playerColor == PlayerColor.GREEN)
return fillColor(playerColor)
.deriveColor(0, 1, STROKE_BRIGHTNESS_FACTOR, 1);
// For dark colors, use a lighter stroke color
return Color.WHITE;
}

}
47 changes: 47 additions & 0 deletions src/ch/epfl/chacun/gui/Icon.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package ch.epfl.chacun.gui;

import ch.epfl.chacun.Occupant;
import ch.epfl.chacun.PlayerColor;
import javafx.scene.Node;
import javafx.scene.shape.SVGPath;

/**
* Helper class to create an icon for a player color and occupant kind.
*
* @author Maxence Espagnet (sciper: 372808)
* @author Balthazar Baillat (sciper: 373420)
*/
public final class Icon {

/**
* The pawn icon SVG path
*/
private final static String PAWN_SVG_PATH = "M -10 10 H -4 L 0 2 L 6 10 H 12 L 5 0 L 12 -2 L 12 -4 L 6 -6 L 6 -10 L 0 -10 L -2 -4 L -6 -2 L -8 -10 L -12 -10 L -8 6 Z";

/**
* The hut icon SVG path
*/
private final static String HUT_SVG_PATH = "M -8 10 H 8 V 2 H 12 L 0 -10 L -12 2 H -8 Z";

/**
* Non-instantiable class constructor
*/
private Icon() {
}

/**
* Creates a new icon for the given player color and occupant kind.
*
* @param playerColor the player color
* @param occupantKind the occupant kind
* @return the icon node
*/
public static Node newFor(PlayerColor playerColor, Occupant.Kind occupantKind) {
SVGPath occupantIcon = new SVGPath();
occupantIcon.setFill(ColorMap.fillColor(playerColor));
occupantIcon.setStroke(ColorMap.strokeColor(playerColor));
occupantIcon.setContent(occupantKind == Occupant.Kind.PAWN ? PAWN_SVG_PATH : HUT_SVG_PATH);
return occupantIcon;
}

}
7 changes: 7 additions & 0 deletions src/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module ChaCuN {
requires javafx.controls;
requires java.net.http;

exports ch.epfl.chacun;
exports ch.epfl.chacun.gui;
}
Loading

0 comments on commit 7bb5fa0

Please sign in to comment.