package it.polimi.ingsw.gc14.Model; import it.polimi.ingsw.gc14.Model.Cards.Building.EffectType; import it.polimi.ingsw.gc14.Model.Cards.BuildingCard; import it.polimi.ingsw.gc14.Model.Cards.TribeCard; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Character; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.Builder; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.Inventor; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.EventCard; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.EventType; import it.polimi.ingsw.gc14.Model.GamePackage.Board; import it.polimi.ingsw.gc14.Model.GamePackage.CurrentState; import it.polimi.ingsw.gc14.Model.Orders.Order2; import it.polimi.ingsw.gc14.Model.Orders.Order3; import it.polimi.ingsw.gc14.Model.Orders.Order4; import it.polimi.ingsw.gc14.Model.Orders.Order5; import it.polimi.ingsw.gc14.Model.GamePackage.GameStages; import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; import it.polimi.ingsw.gc14.Network.Observer; import it.polimi.ingsw.gc14.View.TUI.AsciiTable; import it.polimi.ingsw.gc14.View.TUI.BorderStyle; /** * Represents the main game model. * A Game object stores the players, the current state of the match, * the slot assignments, the board, and the logic required to manage the game flow. */ public class Game implements Serializable { private transient List observers = new ArrayList<>(); // transient! non serializzare public void addObserver(Observer observer) { observers.add(observer); } private void notifyObservers() { for (Observer o : observers) { o.update(this); } } /** * Returns the list of players participating in the game. * @return */ public List getPlayers() { return playersList; } /** * Returns the current number of players participating in the game. * @return the current number of players. */ public int getCurrentPlayerNumber() { return playersList.size(); } /** * The list of players participating in the game. */ private ArrayList playersList; /** * The current state of the game. */ private CurrentState currentState; /** * The mapping between slots and the players assigned to them. */ private HashMap slotMap; /** * The configured number of players for this game. */ private int nPlayers; /** * The queue of players involved in optional card resolution. */ private Queue OptionalCardQueue; /** * The order logic card associated with this game. */ private OrderLogicCard orderLogicCard; /** * The board associated with this game. */ private Board board; /** * Returns clones of the upper tribe cards currently available on the board. * * @return a list containing clones of the upper tribe cards currently available on the board. */ public ListgetUpperListTribeCards() { List cards = new ArrayList<>(); board.upperListTribe.forEach(x->cards.add(x.clone())); return cards; } /** * Returns clones of the lower tribe cards currently available on the board. * * @return a list containing clones of the lower tribe cards currently available on the board. */ public ListgetLowerListTribeCards() { List cards = new ArrayList<>(); board.lowerListTribe.forEach(x->cards.add(x.clone())); return cards; } /** * Returns clones of the upper building cards currently available on the board. * * @return a list containing clones of the upper building cards currently available on the board. */ public ListgetUpperListBuilding() { List cards = new ArrayList<>(); board.upperListBuilding.forEach(x->cards.add(x.clone())); return cards; } /** * Returns clones of the lower building cards currently available on the board. * * @return a list containing clones of the lower building cards currently available on the board. */ public ListgetLowerListBuilding() { List cards = new ArrayList<>(); board.lowerListBuilding.forEach(x->cards.add(x.clone())); return cards; } /** * Returns the current state of the game. * * @return the current state of the game. */ public CurrentState getCurrentState() { return currentState; }; /** * Returns the player with the specified username, if present. * * @param Username the username of the player to search for. * @return the player with the specified username, or {@code null} if no such player exists. */ public Player getPlayerByUsername(String Username) throws IndexOutOfBoundsException { return playersList.stream().filter(x->x.getUserName().equals(Username)).findFirst().orElse(null); } /** * Returns the configured number of players for this game. * * @return the configured number of players for this game. */ public int getNPlayers() { return nPlayers; } /** * Creates a game with the specified number of players. * * @param nPlayers the configured number of players for the game. * @throws IllegalArgumentException if {@code nPlayers < 0} or {@code nPlayers > 5}. */ public Game(int nPlayers) throws IllegalArgumentException{ if(nPlayers !=0 && (nPlayers < 2 || nPlayers > 5)) { throw new IllegalArgumentException(); } this.nPlayers = nPlayers; board=new Board(nPlayers); slotMap = new LinkedHashMap<>(); for(Slot s :board.getSlotList()) { slotMap.put(s,null); } currentState= new CurrentState(); playersList = new ArrayList<>(); OptionalCardQueue = new LinkedList<>(); } /** * Creates a game with 0 configured players. */ public Game() { this(0); } /** * Attempts to add the specified player to the game. * The operation succeeds only if the configured number of players is not 0, * the current game stage is {@code WAITING}, and the player is not already present. * If the number of players reaches the configured maximum, the game is initialized. * * @param player the player to add to the game. * @return {@code true} if the player is successfully added, {@code false} otherwise. */ public boolean addPlayer(Player player) { if(this.nPlayers==0) { return false; } if(currentState.getGameStage()!= GameStages.WAITING) return false; if(getPlayerByUsername(player.getUserName())!=null) return false; playersList.add(player); if(playersList.size()>=nPlayers) { init(); } return true; } /** * Initializes the game after all required players have been added. * The method creates the appropriate order logic card according to the number of players, * selects the first current player, and updates the game stage to {@code SLOT_CHOICE}. */ public void init() { switch (nPlayers) { case 2: orderLogicCard=new Order2(playersList); break; case 3: orderLogicCard=new Order3(playersList); break; case 4: orderLogicCard=new Order4(playersList); break; case 5: orderLogicCard=new Order5(playersList); break; } currentState.PlayerUpdate(orderLogicCard.pull(),null); currentState.GameStageUpdate(GameStages.SLOT_CHOICE); } //region Controller Methods /** * Attempts to assign the slot at the specified index to the specified player. * The operation succeeds only if the index is valid, the current game stage is {@code SLOT_CHOICE}, * the specified player is the current player, and the selected slot is not already assigned. * If the slot is successfully assigned, the next player setup is triggered. * * @param player the player performing the slot choice. * @param slotIndex the index of the selected slot. * @return {@code true} if the slot choice succeeds, {@code false} otherwise. */ public boolean SlotChoiceByIndex(Player player, int slotIndex) { if(slotIndex<0 || slotIndex>=slotMap.size()) return false; if(currentState.getGameStage()!= GameStages.SLOT_CHOICE) { return false; } if(!player.equals(currentState.getCurrentPlayer())) { return false; } Map.Entry slotPlayerEntry = new ArrayList<>(slotMap.entrySet()).get(slotIndex); if(slotPlayerEntry.getValue()!=null) { return false; } slotMap.put(slotPlayerEntry.getKey(),player); nextPlayerSetup(); return true; } //region Drawing Methods /** * Attempts to draw the upper tribe card at the specified index for the specified player. * The operation succeeds only if the index is valid, the game stage is {@code RESOLVING_ACTIONS}, * the specified player is the current player, at least one upper card draw is still available, * and the selected tribe card is not an event card. * If successful, the card is inserted into the player's collection, removed from the board, * and the number of remaining upper draws is decremented. * If both upper and lower draws become zero, the next player setup is triggered. * * @param player the player performing the draw. * @param cardIndex the index of the upper tribe card to draw. * @return {@code true} if the draw succeeds, {@code false} otherwise. */ public boolean DrawUpperTribeCardByIndex(Player player,int cardIndex) { if( cardIndex<0 || cardIndex >=board.upperListTribe.size()) return false; if(currentState.getGameStage()!= GameStages.RESOLVING_ACTIONS) { return false; } if(!player.equals(currentState.getCurrentPlayer())) { return false; } if(currentState.getNUpper() <1) return false; TribeCard tribeCard = board.upperListTribe.get(cardIndex); if(tribeCard.IsEventCard()) return false; Character tempCard = (Character) tribeCard; tempCard.insert(player); board.removeUpperTribeCard(tempCard); currentState.UpperDrawn(); if((currentState.getNLower() ==0 ||( getLowerListTribeCards().size()==0 && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||( getUpperListTribeCards().size()==0 && getUpperListBuilding().size()==0))) nextPlayerSetup(); return true; } /** * Skips the upper card draw for the specified player when no drawable cards are available. * The operation succeeds only if the current game stage is {@code RESOLVING_ACTIONS}, * the specified player is the current player, at least one upper draw is still available, * and there are no drawable upper tribe cards (i.e. all remaining upper tribe cards are event cards) * and no upper building cards that the player can afford. * If successful, the upper draw counter is decremented. * If both upper and lower draws become zero (or no cards remain drawable), the next player setup is triggered. * * @param player the player skipping the upper draw. * @return {@code true} if the skip succeeds, {@code false} otherwise. */ public boolean SkipUpperDrawing(Player player) { if(currentState.getGameStage()!= GameStages.RESOLVING_ACTIONS) { return false; } if(!player.equals(currentState.getCurrentPlayer())) { return false; } if(currentState.getNUpper() <1) return false; if(hasDrawableUp()) return false; currentState.UpperDrawn(); if((currentState.getNLower() ==0 ||( !hasDrawableDown() && getLowerListBuilding().isEmpty())) && ((currentState.getNUpper() ==0)||(getUpperListBuilding().isEmpty()))) nextPlayerSetup(); return true; } /** * Skips the lower card draw for the specified player when no drawable cards are available. * The operation succeeds only if the current game stage is {@code RESOLVING_ACTIONS}, * the specified player is the current player, at least one lower draw is still available, * and there are no drawable lower tribe cards (i.e. all remaining lower tribe cards are event cards) * and no lower building cards that the player can afford. * If successful, the lower draw counter is decremented. * If both upper and lower draws become zero (or no cards remain drawable), the next player setup is triggered. * * @param player the player skipping the lower draw. * @return {@code true} if the skip succeeds, {@code false} otherwise. */ public boolean SkipLowerDrawing(Player player) { if(currentState.getGameStage()!= GameStages.RESOLVING_ACTIONS) { return false; } if(!player.equals(currentState.getCurrentPlayer())) { return false; } if(currentState.getNLower() <1) return false; if(hasDrawableDown()) return false; currentState.LowerDrawn(); if((currentState.getNLower() ==0 ||( getLowerListBuilding().isEmpty())) && ((currentState.getNUpper() ==0)||(!hasDrawableUp()&&getUpperListBuilding().isEmpty()))) nextPlayerSetup(); return true; } /** * Attempts to draw the lower tribe card at the specified index for the specified player. * The operation succeeds only if the index is valid, the game stage is {@code RESOLVING_ACTIONS}, * the specified player is the current player, at least one lower card draw is still available, * and the selected tribe card is not an event card. * If successful, the card is inserted into the player's collection, removed from the board, * and the number of remaining lower draws is decremented. * If both lower and upper draws become zero, the next player setup is triggered. * * @param player the player performing the draw. * @param cardIndex the index of the lower tribe card to draw. * @return {@code true} if the draw succeeds, {@code false} otherwise. */ public boolean DrawLowerTribeCardByIndex(Player player, int cardIndex) { if( cardIndex<0 || cardIndex >=board.lowerListTribe.size()) return false; if(currentState.getGameStage()!= GameStages.RESOLVING_ACTIONS) { return false; } if(!player.equals(currentState.getCurrentPlayer())) { return false; } if(currentState.getNLower() <1) return false; TribeCard tribeCard = board.lowerListTribe.get(cardIndex); if(tribeCard.IsEventCard()) return false; Character tempCard = (Character) tribeCard; tempCard.insert(player); board.removeLowerTribeCard(tempCard); currentState.LowerDrawn(); if((currentState.getNLower() ==0 ||( getLowerListTribeCards().size()==0 && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||( getUpperListTribeCards().size()==0 && getUpperListBuilding().size()==0))) nextPlayerSetup(); return true; } /** * Attempts to draw the upper building card at the specified index for the specified player. * The operation succeeds only if the index is valid, the game stage is {@code RESOLVING_ACTIONS}, * the specified player is the current player, at least one upper card draw is still available, * and the selected building card can be bought by the player. * If successful, the building card is removed from the board and the number of remaining upper draws is decremented. * If both upper and lower draws become zero, the next player setup is triggered. * * @param player the player performing the draw. * @param cardIndex the index of the upper building card to draw. * @return {@code true} if the draw succeeds, {@code false} otherwise. */ public boolean DrawUpperBuildingCardByIndex(Player player,int cardIndex) { if( cardIndex<0 || cardIndex >=board.upperListBuilding.size()) return false; if(currentState.getGameStage()!= GameStages.RESOLVING_ACTIONS) { return false; } if(!player.equals(currentState.getCurrentPlayer())) { return false; } BuildingCard buildingCard = board.upperListBuilding.get(cardIndex); if(currentState.getNUpper() <1) return false; if(buildingCard.buy(player)) { currentState.UpperDrawn(); board.removeUpperBuildingCard(buildingCard); } else return false; if((currentState.getNLower() ==0 ||( getLowerListTribeCards().size()==0 && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||( getUpperListTribeCards().size()==0 && getUpperListBuilding().size()==0))) nextPlayerSetup(); return true; } /** * Attempts to draw the lower building card at the specified index for the specified player. * The operation succeeds only if the index is valid, the game stage is {@code RESOLVING_ACTIONS}, * the specified player is the current player, at least one lower card draw is still available, * and the selected building card can be bought by the player. * If successful, the building card is removed from the board and the number of remaining lower draws is decremented. * If both lower and upper draws become zero, the next player setup is triggered. * * @param player the player performing the draw. * @param cardIndex the index of the lower building card to draw. * @return {@code true} if the draw succeeds, {@code false} otherwise. */ public boolean DrawLowerBuildingCardByIndex(Player player,int cardIndex) { if( cardIndex<0 || cardIndex >=board.lowerListBuilding.size()) return false; if(currentState.getGameStage()!= GameStages.RESOLVING_ACTIONS) { return false; } if(!player.equals(currentState.getCurrentPlayer())) { return false; } BuildingCard buildingCard = board.lowerListBuilding.get(cardIndex); if(currentState.getNLower() <1) return false; if(buildingCard.buy(player)) { currentState.LowerDrawn(); board.removeLowerBuildingCard(buildingCard); } else return false; if((currentState.getNLower() ==0 ||( getLowerListTribeCards().size()==0 && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||( getUpperListTribeCards().size()==0 && getUpperListBuilding().size()==0))) nextPlayerSetup(); return true; } //endregion //region Optional Card Methods /** * Attempts to pick the upper optional tribe card at the specified index for the specified player. * The operation succeeds only if the current game stage is {@code OPTIONAL_CARD_EFFECT}, * the specified player is the current player, the index is valid, * and the selected tribe card is not an event card. * If successful, the card is inserted into the player's collection, * removed from the board, the player is removed from the optional card queue, * and the next player setup is triggered. * * @param player the player performing the optional tribe card pick. * @param cardIndex the index of the upper optional tribe card to pick. * @return {@code true} if the operation succeeds, {@code false} otherwise. */ public boolean PickOptionalTribeCardByIndex(Player player,int cardIndex) { if(currentState.getGameStage() != GameStages.OPTIONAL_CARD_EFFECT){ return false; } if(!player.equals(currentState.getCurrentPlayer())){ return false; } if( cardIndex<0 || cardIndex >=board.upperListTribe.size()) return false; TribeCard tribeCard = board.upperListTribe.get(cardIndex); if(tribeCard.IsEventCard()) return false; Character tempCard = (Character) tribeCard; tempCard.insert(player); board.removeUpperTribeCard(tempCard); OptionalCardQueue.removeIf(x->x.equals(player)); nextPlayerSetup(); return true; } /** * Attempts to pick the upper optional building card at the specified index for the specified player. * The operation succeeds only if the current game stage is {@code OPTIONAL_CARD_EFFECT}, * the specified player is the current player, the index is valid, * and the selected building card can be bought by the player. * If successful, the card is removed from the board, the next player setup is triggered, * and the player is removed from the optional card queue. * * @param player the player performing the optional building card pick. * @param cardIndex the index of the upper optional building card to pick. * @return {@code true} if the operation succeeds, {@code false} otherwise. */ public boolean PickOptionalBuildingCard(Player player, int cardIndex) { if(currentState.getGameStage() != GameStages.OPTIONAL_CARD_EFFECT){ return false; } if(!player.equals(currentState.getCurrentPlayer())){ return false; } if( cardIndex<0 || cardIndex >=board.upperListBuilding.size()) return false; BuildingCard buildingCard = board.upperListBuilding.get(cardIndex); if(buildingCard.buy(player)) { board.removeUpperBuildingCard(buildingCard); } else { return false; } OptionalCardQueue.removeIf(x->x.equals(player)); nextPlayerSetup(); return true; } /** * Skips the optional card choice for the specified player. * The operation succeeds only if the current game stage is {@code OPTIONAL_CARD_EFFECT} * and the specified player is the current player. * If successful, the player is removed from the optional card queue * and the next player setup is triggered. * * @param player the player skipping the optional card choice. * @return {@code true} if the operation succeeds, {@code false} otherwise. */ public boolean NoOptionalCard(Player player) { if(currentState.getGameStage() != GameStages.OPTIONAL_CARD_EFFECT){ return false; } if(!player.equals(currentState.getCurrentPlayer())){ return false; } OptionalCardQueue.removeIf(x->x.equals(player)); nextPlayerSetup(); return true; } //endregion //endregion /** * Prepares the next player and updates the game state according to the current game stage. * If the current stage is {@code SLOT_CHOICE}, the next player is taken from the order logic card. * If no player is available, the game stage is updated to {@code RESOLVING_ACTIONS} * and the first assigned slot is selected. * If the current stage is {@code RESOLVING_ACTIONS}, the current player is pushed back * into the order logic card, the current slot is freed, and the next assigned slot is selected. * If no assigned slots remain, the game stage is updated to {@code OPTIONAL_CARD_EFFECT}, * the optional card queue is built from players owning building cards with effect id equal to 12, * and the first player in that queue is selected. * If no player is available for optional card resolution, the game stage is updated to * {@code RESOLVING_EVENT}; then, if the round number is less than 10, the next round is prepared, * otherwise event resolution is performed, the game stage is updated to {@code ENDING}, * and the game is ended. * If the current stage is {@code OPTIONAL_CARD_EFFECT}, the next player is taken from the optional card queue. * If no player is available, the game stage is updated to {@code RESOLVING_EVENT}. */ private void nextPlayerSetup() { if(GameStages.SLOT_CHOICE==currentState.getGameStage()) { Player tempPlayer = orderLogicCard.pull(); if(tempPlayer!=null) { currentState.PlayerUpdate(tempPlayer, null); return; } currentState.GameStageUpdate(GameStages.RESOLVING_ACTIONS); for (Slot s : slotMap.keySet()) { if (slotMap.get(s) != null) { currentState.PlayerUpdate(slotMap.get(s), s); if(!((currentState.getNLower() ==0 ||(!hasDrawableDown() && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||(!hasDrawableUp() && getUpperListBuilding().size()==0)))) break; else { orderLogicCard.push(currentState.getCurrentPlayer()); slotMap.put(currentState.getSlot(), null); } } } return; } if(GameStages.RESOLVING_ACTIONS==currentState.getGameStage()) { orderLogicCard.push(currentState.getCurrentPlayer()); slotMap.put(currentState.getSlot(), null); for (Slot s : slotMap.keySet()) { if (slotMap.get(s) != null) { currentState.PlayerUpdate(slotMap.get(s), s); if((currentState.getNLower() ==0 ||(!hasDrawableDown() && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||( !hasDrawableUp() && getUpperListBuilding().size()==0))) { orderLogicCard.push(currentState.getCurrentPlayer()); slotMap.put(currentState.getSlot(), null); } else { break; } } } if(slotMap.values().stream().allMatch(v -> v == null)) { currentState.GameStageUpdate(GameStages.OPTIONAL_CARD_EFFECT); HashMap optional=new LinkedHashMap<>(); for (Player p : orderLogicCard.players) { int tempCount=(int)p.buildingCards.stream().filter(x->x.getEffectId()==12).count(); if(tempCount>0) { optional.put(p,tempCount); } } OptionalCardQueue=new LinkedList<>(); for(Map.Entry e : optional.entrySet()) { OptionalCardQueue.add(e.getKey()); } Player optionalPlayer = OptionalCardQueue.poll(); if (optionalPlayer != null) { currentState.PlayerUpdate(optionalPlayer, null); return; } currentState.GameStageUpdate(GameStages.RESOLVING_EVENT); if (currentState.getRound() < 10) { nextRound(); currentState.PlayerUpdate(orderLogicCard.pull(), null); currentState.GameStageUpdate(GameStages.SLOT_CHOICE); } else { currentState.GameStageUpdate(GameStages.ENDING); endGame(); } return; } } if (GameStages.OPTIONAL_CARD_EFFECT == currentState.getGameStage()) { Player optionalPlayer = OptionalCardQueue.poll(); if (optionalPlayer != null) { currentState.PlayerUpdate(optionalPlayer, null); return; } currentState.GameStageUpdate(GameStages.RESOLVING_EVENT); if (currentState.getRound() < 10) { nextRound(); currentState.PlayerUpdate(orderLogicCard.pull(), null); currentState.GameStageUpdate(GameStages.SLOT_CHOICE); } else { currentState.GameStageUpdate(GameStages.ENDING); endGame(); } return; /** * Checks whether there are any drawable lower tribe cards on the board, * i.e. lower tribe cards that are not event cards. * * @return {@code true} if at least one non-event lower tribe card is available, {@code false} otherwise. */ } } /** * Checks whether there are any drawable upper tribe cards on the board, * i.e. upper tribe cards that are not event cards. * * @return {@code true} if at least one non-event upper tribe card is available, {@code false} otherwise. */ private boolean hasDrawableUp() { return getUpperListTribeCards().stream().filter(x-> !x.IsEventCard()).count()!=0; } /** * Checks whether there are any drawable lower tribe cards on the board, * i.e. lower tribe cards that are not event cards. * * @return {@code true} if at least one non-event lower tribe card is available, {@code false} otherwise. */ private boolean hasDrawableDown() { return getLowerListTribeCards().stream().filter(x-> !x.IsEventCard()).count()!=0; } /** * Resolves all pending event cards if the current game stage is {@code RESOLVING_EVENT}. * All pending events are activated on the player list. * Event cards of type {@code SUSTENANCE} are resolved after all other pending events. */ private void EventResolution() { if(currentState.getGameStage()!= GameStages.RESOLVING_EVENT) { return; } Queue events; events=board.getPendingEvents(); ArrayListsustenance=events.stream().filter(x->x.getType().equals(EventType.SUSTENANCE)).collect(Collectors.toCollection(ArrayList::new)); events.removeAll(sustenance); for(EventCard event:events) { event.activateEvent(playersList); } for(EventCard e : sustenance) { e.activateEvent(playersList); } } /** * Advances the game to the next round. * The method first resolves pending events. * If the current round is 10, the game stage is updated to {@code ENDING} and the game is ended. * Otherwise, the era is updated if the board changes era, and the round number is incremented. */ private void nextRound() { EventResolution(); if(currentState.getRound()==10) { currentState.GameStageUpdate(GameStages.ENDING); endGame(); return; } if(currentState.getEra()!= board.nextRound()) { currentState.EraUpdate(); } currentState.RoundUpdate(); } /** * Ends the game by applying all final building effects owned by each player * and updating the game stage to {@code ENDED}. */ private void endGame() { Queue events; events=Stream.concat(board.lowerListTribe.stream().filter(x->!x.IsEventCard()),board.upperListTribe.stream().filter(x->!x.IsEventCard())).map(x->((EventCard)x)).collect(Collectors.toCollection(LinkedList::new)); ArrayListsustenance=events.stream().filter(x->x.getType().equals(EventType.SUSTENANCE)).collect(Collectors.toCollection(ArrayList::new)); events.removeAll(sustenance); for(EventCard event:events) { event.activateEvent(playersList); } for(EventCard e : sustenance) { e.activateEvent(playersList); } playersList.forEach(p->{ int temp= p.builders.stream().mapToInt(Builder::getPrestigeValue).sum(); p.addPrestige(temp); }); playersList.forEach(p->{ int temp=(int) p.inventors.stream().mapToInt(Inventor::Icon).distinct().count(); p.addPrestige(temp*p.getNType(CharacterType.INVENTOR)); }); playersList.forEach(p->{ p.addPrestige(10 * (p.getNType(CharacterType.ARTIST)/2)); }); playersList.forEach(p->{ int temp= p.buildingCards.stream().mapToInt(BuildingCard::getPrestigeValue).sum(); p.addPrestige(temp); }); playersList.forEach( p -> p.buildingCards.stream().filter(x -> x.getEffectType() == EffectType.FINAL). forEach(x -> x.applyEffect(p)) ); currentState.GameStageUpdate(GameStages.ENDED); } /** * Sets the configured number of players for this game. * The operation succeeds only if the current configured number of players is 0. * * @param nPlayers the new configured number of players. * @return {@code true} if the number of players is updated, {@code false} otherwise. */ public boolean setNPlayer(int nPlayers) { if (this.nPlayers != 0) { return false; } if (nPlayers < 2 || nPlayers > 5) { return false; } this.nPlayers = nPlayers; board = new Board(nPlayers); slotMap = new LinkedHashMap<>(); for (Slot s : board.getSlotList()) { slotMap.put(s, null); } currentState = new CurrentState(); playersList = new ArrayList<>(); OptionalCardQueue = new LinkedList<>(); return true; } /** * Prints a string representation of the {@code Game}. Used in the TUI implementation to draw: *
  • {@link it.polimi.ingsw.gc14.Model.GamePackage.Board Board} *
  • {@link it.polimi.ingsw.gc14.Model.Player Players} *
  • {@link #getUpperListTribeCards() Upper TribeCard List}
  • {@link #getUpperListBuilding() Upper Building List} *
  • {@link #getLowerListTribeCards() Lower TribeCard List}
  • {@link #getLowerListBuilding() Lower Building List} *
  • {@link it.polimi.ingsw.gc14.Model.OrderLogicCard Offer Track} * * @return {@code String} - a string representation of the {@code Game}. */ @Override public String toString() { return PlayersStamp()+"\n"+BoardStamp()+"\n"; } /** * Returns a string representation of all the players currently in the game, * arranged side by side in pairs. * If the number of players is odd, the last player is printed on its own line. * * @return {@code String} - a string representation of all the players. */ public String PlayersStamp() { StringBuilder stringBuilder=new StringBuilder(); for(int i=0;i stringUpOffer=new ArrayList<>(); List stringDownOffer=new ArrayList<>(); int index=0; for(Map.Entry entry:slotMap.entrySet()) { stringDownOffer.add((index++)+"."+entry.getKey().toStringTUI()); if(entry.getValue()!=null) stringUpOffer.add(entry.getValue().getUserName()); else stringUpOffer.add(" "); } var TribeTableUpper = new AsciiTable(BorderStyle.UNICODE,1); var TribeTableLower = new AsciiTable(BorderStyle.UNICODE,1); List stringUpperListTribe=new ArrayList<>(); List stringLowerListTribe=new ArrayList<>(); stringUpperListTribe.add("Char/Events"); stringLowerListTribe.add("Char/Events"); for(int i=0;iTribeTableUpper.addRow(x)); stringLowerListTribe.forEach(x->TribeTableLower.addRow(x)); offerTrack.addRow(stringUpOffer); offerTrack.addRow(stringDownOffer); return "CURRENT STATE\n"+getCurrentState()+"\n"+orderLogicCard.toString()+"\n"+ AsciiTable.sideBySide(Arrays.stream((TribeTableUpper.build().split("\n"))).toList(), Arrays.stream(BuildTableUpper.build().split("\n")).toList(),2)+"\n"+offerTrack.build()+"\n"+AsciiTable.sideBySide(List.of(TribeTableLower.build().split("\n")), Arrays.stream(BuildTableLower.build().split("\n")).toList(),2); } }