Fix: only one skipAction(Del:SkipLower/SkipUpper)

This commit is contained in:
rubenpirreram
2026-05-07 13:12:22 +02:00
parent ee5b69a900
commit 490f8fbfaa
13 changed files with 184 additions and 227 deletions
@@ -47,7 +47,6 @@ public class ClientLauncherTUI {
admissibleChar.add("6"); admissibleChar.add("6");
admissibleChar.add("7"); admissibleChar.add("7");
admissibleChar.add("8"); admissibleChar.add("8");
admissibleChar.add("9");
admissibleChar.add("A"); admissibleChar.add("A");
admissibleChar.add("B"); admissibleChar.add("B");
admissibleChar.add("C"); admissibleChar.add("C");
@@ -138,7 +137,7 @@ public class ClientLauncherTUI {
if(admissibleChar.contains(action)) if(admissibleChar.contains(action))
{ {
if (!action.equals("7") && !action.equals("8") && !action.equals("9") && !action.equals("A") && !action.equals("B") && !action.equals("C")&&!action.equals("a") && !action.equals("b") && !action.equals("c")) { if (!action.equals("7") && !action.equals("8") && !action.equals("A") && !action.equals("B") && !action.equals("C")&&!action.equals("a") && !action.equals("b") && !action.equals("c")) {
try { try {
System.out.println("Insert the required position:"); System.out.println("Insert the required position:");
pos = scanner.nextInt(); pos = scanner.nextInt();
@@ -156,8 +155,7 @@ public class ClientLauncherTUI {
case "5" -> controller.pickOptionalTribeCard(username, pos); case "5" -> controller.pickOptionalTribeCard(username, pos);
case "6" -> controller.pickOptionalBuildingCard(username, pos); case "6" -> controller.pickOptionalBuildingCard(username, pos);
case "7" -> controller.noOptionalCard(username); case "7" -> controller.noOptionalCard(username);
case "8" -> controller.skipUpper(username); case "8" -> controller.skipTurn(username);
case "9" -> controller.skipLower(username);
case "A", "a" -> view.fullRender(); case "A", "a" -> view.fullRender();
case "B", "b" -> view.renderBoard(); case "B", "b" -> view.renderBoard();
case "C", "c" -> view.renderPlayer(); case "C", "c" -> view.renderPlayer();
@@ -173,18 +171,15 @@ public class ClientLauncherTUI {
public static String chooseNetworkInterface(Scanner scanner) throws Exception { public static String chooseNetworkInterface(Scanner scanner) throws Exception {
List<String> ips = new ArrayList<>(); List<String> ips = new ArrayList<>();
// Lista tutte le interfacce attive con IP reale
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) { while (interfaces.hasMoreElements()) {
NetworkInterface ni = interfaces.nextElement(); NetworkInterface ni = interfaces.nextElement();
// Salta loopback, interfacce spente o virtuali
if (!ni.isUp() || ni.isLoopback() || ni.isVirtual()) continue; if (!ni.isUp() || ni.isLoopback() || ni.isVirtual()) continue;
Enumeration<InetAddress> addresses = ni.getInetAddresses(); Enumeration<InetAddress> addresses = ni.getInetAddresses();
while (addresses.hasMoreElements()) { while (addresses.hasMoreElements()) {
InetAddress addr = addresses.nextElement(); InetAddress addr = addresses.nextElement();
// Solo IPv4
if (addr instanceof Inet4Address) { if (addr instanceof Inet4Address) {
System.out.println("[" + ips.size() + "] " + ni.getDisplayName() + " -> " + addr.getHostAddress()); System.out.println("[" + ips.size() + "] " + ni.getDisplayName() + " -> " + addr.getHostAddress());
ips.add(addr.getHostAddress()); ips.add(addr.getHostAddress());
@@ -192,13 +187,13 @@ public class ClientLauncherTUI {
} }
} }
if (ips.isEmpty()) throw new Exception("Nessuna interfaccia disponibile"); if (ips.isEmpty()) throw new Exception("No interface available");
if (ips.size() == 1) { if (ips.size() == 1) {
System.out.println("Una sola interfaccia trovata, uso: " + ips.get(0)); System.out.println("Only one interface found, used: " + ips.get(0));
return ips.get(0); return ips.get(0);
} }
System.out.print("Scegli interfaccia: "); System.out.print("Choose the interface: ");
int choice = scanner.nextInt(); int choice = scanner.nextInt();
return ips.get(choice); return ips.get(choice);
} }
@@ -145,16 +145,16 @@ public class ClientController {
/** /**
* Requests to skip drawing from the upper list. * Requests to skip turn .
* This action is available only when the upper list is empty or the player cannot draw any card. * This action is available only when the player cannot draw any tribe card.
* @param playerUsername the name of the player performing the action * @param playerUsername the name of the player performing the action
*/ */
public void skipUpper(String playerUsername) { public void skipTurn(String playerUsername) {
if(!Objects.equals(playerUsername, localController.getModel().getCurrentState().getCurrentPlayer().getUserName())) if(!Objects.equals(playerUsername, localController.getModel().getCurrentState().getCurrentPlayer().getUserName()))
view.showError("It's not your turn!"); view.showError("It's not your turn!");
else { else {
try { try {
client.skipUpper(playerUsername); client.skipTurn(playerUsername);
} catch (RemoteException e) { } catch (RemoteException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -162,22 +162,6 @@ public class ClientController {
} }
/**
* Requests to skip drawing from the lower list.
* This action is available only when the lower list is empty or the player cannot draw any card.
* @param playerUsername the name of the player performing the action
*/
public void skipLower(String playerUsername) {
if(!Objects.equals(playerUsername, localController.getModel().getCurrentState().getCurrentPlayer().getUserName()))
view.showError("It's not your turn!");
else {
try {
client.skipLower(playerUsername);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
}
/** /**
@@ -119,32 +119,19 @@ public class GameController {
return model.DrawLowerBuildingCardByIndex(model.getPlayerByUsername(playerUsername), pos); return model.DrawLowerBuildingCardByIndex(model.getPlayerByUsername(playerUsername), pos);
} }
/**
* Skips the upper card drawing action for the specified player.
*
* @param playerUsername the username of the player who wants to skip the upper drawing action.
* @return {@code true} if the skip action is valid and successfully performed;
* {@code false} if the player does not exist or the action is not valid.
*/
public boolean SkipUpperDrawing(String playerUsername) {
Player player= model.getPlayerByUsername(playerUsername);
if(player==null)
return false;
return model.SkipUpperDrawing(model.getPlayerByUsername(playerUsername));
}
/** /**
* Skips the lower card drawing action for the specified player. * Skips the card drawing action for the specified player.
* *
* @param playerUsername the username of the player who wants to skip the lower drawing action. * @param playerUsername the username of the player who wants to skip the turn action.
* @return {@code true} if the skip action is valid and successfully performed; * @return {@code true} if the skip action is valid and successfully performed;
* {@code false} if the player does not exist or the action is not valid. * {@code false} if the player does not exist or the action is not valid.
*/ */
public boolean SkipLowerDrawing(String playerUsername) { public boolean SkipNoDrawable(String playerUsername) {
Player player= model.getPlayerByUsername(playerUsername); Player player= model.getPlayerByUsername(playerUsername);
if(player==null) if(player==null)
return false; return false;
return model.SkipLowerDrawing(model.getPlayerByUsername(playerUsername)); return model.SkipNoDrawable(model.getPlayerByUsername(playerUsername));
} }
/** /**
@@ -328,50 +328,16 @@ public class Game implements Serializable {
return true; 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.RES_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. * Skips the turn for the specified player when no drawable cards are available.
* The operation succeeds only if the current game stage is {@code RESOLVING_ACTIONS}, * 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, * the specified player is the current player,
* and there are no drawable lower tribe cards (i.e. all remaining lower tribe cards are event cards) * and the player can't draw tribe card (i.e. all remaining lower tribe cards are event cards).
* and no lower building cards that the player can afford. * @param player the player skipping the turn .
* 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. * @return {@code true} if the skip succeeds, {@code false} otherwise.
*/ */
public boolean SkipLowerDrawing(Player player) { public boolean SkipNoDrawable(Player player) {
if(currentState.getGameStage()!= GameStages.RES_ACTIONS) if(currentState.getGameStage()!= GameStages.RES_ACTIONS)
{ {
return false; return false;
@@ -380,13 +346,15 @@ public class Game implements Serializable {
{ {
return false; return false;
} }
if(currentState.getNLower() <1) if(hasDrawableDown() && currentState.getNLower()>0 )
return false; return false;
if(hasDrawableDown()) if(hasDrawableUp() && currentState.getNUpper()>0)
return false; return false;
currentState.LowerDrawn(); while(currentState.getNLower()>0)
if((currentState.getNLower() ==0 ||( getLowerListBuilding().isEmpty())) && ((currentState.getNUpper() ==0)||(!hasDrawableUp()&&getUpperListBuilding().isEmpty()))) currentState.LowerDrawn();
nextPlayerSetup(); while(currentState.getNUpper()>0)
currentState.UpperDrawn();
nextPlayerSetup();
return true; return true;
} }
@@ -630,83 +598,75 @@ public class Game implements Serializable {
* If no player is available, the game stage is updated to {@code RESOLVING_EVENT}. * If no player is available, the game stage is updated to {@code RESOLVING_EVENT}.
*/ */
private void nextPlayerSetup() { private void nextPlayerSetup() {
if(GameStages.SLOT_CHOICE==currentState.getGameStage()) {
if (GameStages.SLOT_CHOICE == currentState.getGameStage()) {
Player tempPlayer = orderLogicCard.pull(); Player tempPlayer = orderLogicCard.pull();
if(tempPlayer!=null) { if (tempPlayer != null) {
currentState.PlayerUpdate(tempPlayer, null); currentState.PlayerUpdate(tempPlayer, null);
return; return;
} }
// All players have chosen a slot → switch to RES_ACTIONS
currentState.GameStageUpdate(GameStages.RES_ACTIONS); currentState.GameStageUpdate(GameStages.RES_ACTIONS);
boolean anyAssigned = false;
for (Slot s : slotMap.keySet()) { for (Slot s : slotMap.keySet()) {
if (slotMap.get(s) != null) { if (slotMap.get(s) != null) {
currentState.PlayerUpdate(slotMap.get(s), s); currentState.PlayerUpdate(slotMap.get(s), s);
if(!((currentState.getNLower() ==0 ||(!hasDrawableDown() && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||(!hasDrawableUp() && getUpperListBuilding().size()==0))))
break; boolean hasDrawableLower = currentState.getNLower() > 0
else && (hasDrawableDown() || !getLowerListBuilding().isEmpty());
{ boolean hasDrawableUpper = currentState.getNUpper() > 0
&& (hasDrawableUp() || !getUpperListBuilding().isEmpty());
if (!hasDrawableLower && !hasDrawableUpper) {
// This player has nothing drawable, skip them immediately
orderLogicCard.push(currentState.getCurrentPlayer()); orderLogicCard.push(currentState.getCurrentPlayer());
slotMap.put(currentState.getSlot(), null); slotMap.put(currentState.getSlot(), null);
} else {
anyAssigned = true;
break;
} }
} }
} }
return;
// If every player was skipped, jump straight to optional phase
if (!anyAssigned) {
transitionToOptionalOrNextRound();
}
return;
} }
if(GameStages.RES_ACTIONS ==currentState.getGameStage()) {
if (GameStages.RES_ACTIONS == currentState.getGameStage()) {
orderLogicCard.push(currentState.getCurrentPlayer()); orderLogicCard.push(currentState.getCurrentPlayer());
slotMap.put(currentState.getSlot(), null); slotMap.put(currentState.getSlot(), null);
for (Slot s : slotMap.keySet()) { for (Slot s : slotMap.keySet()) {
if (slotMap.get(s) != null) { if (slotMap.get(s) != null) {
currentState.PlayerUpdate(slotMap.get(s), s); currentState.PlayerUpdate(slotMap.get(s), s);
if((currentState.getNLower() ==0 ||(!hasDrawableDown() && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||( !hasDrawableUp() && getUpperListBuilding().size()==0))) {
boolean hasDrawableLower = currentState.getNLower() > 0
&& (hasDrawableDown() || !getLowerListBuilding().isEmpty());
boolean hasDrawableUpper = currentState.getNUpper() > 0
&& (hasDrawableUp() || !getUpperListBuilding().isEmpty());
if (!hasDrawableLower && !hasDrawableUpper) {
// This player also has nothing, skip and continue the loop
orderLogicCard.push(currentState.getCurrentPlayer()); orderLogicCard.push(currentState.getCurrentPlayer());
slotMap.put(currentState.getSlot(), null); slotMap.put(currentState.getSlot(), null);
} } else {
else // Found a player with something to do, stop here
{ return;
break;
} }
} }
} }
if(slotMap.values().stream().allMatch(v -> v == null))
{
currentState.GameStageUpdate(GameStages.OPT_CARD_E);
HashMap<Player,Integer> 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<Player,Integer> e : optional.entrySet())
{
OptionalCardQueue.add(e.getKey());
}
Player optionalPlayer = OptionalCardQueue.poll();
if (optionalPlayer != null) { // All slots are now null → every player is done for this round
currentState.PlayerUpdate(optionalPlayer, null); transitionToOptionalOrNextRound();
return; return;
} }
currentState.GameStageUpdate(GameStages.RES_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.OPT_CARD_E == currentState.getGameStage()) { if (GameStages.OPT_CARD_E == currentState.getGameStage()) {
Player optionalPlayer = OptionalCardQueue.poll(); Player optionalPlayer = OptionalCardQueue.poll();
@@ -718,6 +678,38 @@ public class Game implements Serializable {
currentState.GameStageUpdate(GameStages.RES_EVENT); currentState.GameStageUpdate(GameStages.RES_EVENT);
if (currentState.getRound() < 10) {
nextRound();
currentState.PlayerUpdate(orderLogicCard.pull(), null);
currentState.GameStageUpdate(GameStages.SLOT_CHOICE);
} else {
currentState.GameStageUpdate(GameStages.ENDING);
endGame();
}
}
}
//TODO
private void transitionToOptionalOrNextRound() {
currentState.GameStageUpdate(GameStages.OPT_CARD_E);
OptionalCardQueue = new LinkedList<>();
for (Player p : orderLogicCard.players) {
long count = p.buildingCards.stream().filter(x -> x.getEffectId() == 12).count();
if (count > 0) {
OptionalCardQueue.add(p);
}
}
Player optionalPlayer = OptionalCardQueue.poll();
if (optionalPlayer != null) {
currentState.PlayerUpdate(optionalPlayer, null);
return;
}
// Nobody has optional cards → go straight to event resolution
currentState.GameStageUpdate(GameStages.RES_EVENT);
if (currentState.getRound() < 10) { if (currentState.getRound() < 10) {
nextRound(); nextRound();
currentState.PlayerUpdate(orderLogicCard.pull(), null); currentState.PlayerUpdate(orderLogicCard.pull(), null);
@@ -726,17 +718,7 @@ public class Game implements Serializable {
currentState.GameStageUpdate(GameStages.ENDING); currentState.GameStageUpdate(GameStages.ENDING);
endGame(); 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, * Checks whether there are any drawable upper tribe cards on the board,
* i.e. upper tribe cards that are not event cards. * i.e. upper tribe cards that are not event cards.
@@ -745,7 +727,7 @@ public class Game implements Serializable {
*/ */
private boolean hasDrawableUp() private boolean hasDrawableUp()
{ {
return getUpperListTribeCards().stream().filter(x-> !x.IsEventCard()).count()!=0; return getUpperListTribeCards().stream().anyMatch(x -> !x.IsEventCard());
} }
/** /**
@@ -756,7 +738,7 @@ public class Game implements Serializable {
*/ */
private boolean hasDrawableDown() private boolean hasDrawableDown()
{ {
return getLowerListTribeCards().stream().filter(x-> !x.IsEventCard()).count()!=0; return getLowerListTribeCards().stream().anyMatch(x -> !x.IsEventCard());
} }
/** /**
* Resolves all pending event cards if the current game stage is {@code RESOLVING_EVENT}. * Resolves all pending event cards if the current game stage is {@code RESOLVING_EVENT}.
@@ -17,9 +17,8 @@ public interface IClient {
public void drawLowerBuildingCard(String playerUsername,int pos) throws RemoteException; public void drawLowerBuildingCard(String playerUsername,int pos) throws RemoteException;
public void skipUpper(String playerUsername) throws RemoteException; public void skipTurn(String playerUsername) throws RemoteException;
public void skipLower(String playerUsername) throws RemoteException;
public void pickOptionalTribeCard(String playerUsername,int pos) throws RemoteException; public void pickOptionalTribeCard(String playerUsername,int pos) throws RemoteException;
@@ -3,21 +3,20 @@ package it.polimi.ingsw.gc14.Network.NetworkEvents;
import it.polimi.ingsw.gc14.Controller.GameController; import it.polimi.ingsw.gc14.Controller.GameController;
import it.polimi.ingsw.gc14.Network.EventType; import it.polimi.ingsw.gc14.Network.EventType;
import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.NetworkEvent;
import it.polimi.ingsw.gc14.View.IView;
import java.io.Serializable; import java.io.Serializable;
/** /**
* NetworkEvent to avoid drawing a card from the lower card list * NetworkEvent to avoid drawing a card from the lower card list
*/ */
public class SkipLower extends NetworkEvent implements Serializable{ public class SkipNoDrawable extends NetworkEvent implements Serializable{
/** /**
* Class constructor. * Class constructor.
* Initializes all the attributes. * Initializes all the attributes.
* @param username the name of the player requesting the event * @param username the name of the player requesting the event
*/ */
public SkipLower(String username){ public SkipNoDrawable(String username){
super(username, EventType.SKIP_LOWER, false); super(username, EventType.SKIP_LOWER, false);
} }
@@ -27,7 +26,7 @@ public class SkipLower extends NetworkEvent implements Serializable{
*/ */
@Override @Override
public boolean apply(GameController gameController){ public boolean apply(GameController gameController){
return gameController.SkipLowerDrawing(username); return gameController.SkipNoDrawable(username);
} }
} }
@@ -116,23 +116,15 @@ public class RMIClient implements IClient {
/** /**
* Requests to skip drawing from the upper list. * Requests to skip the turn.
* This action is available only when the upper list is empty or the player cannot draw any card. * This action is available only when the player cannot draw any tribe card, but still can buy some buildings.
* @param playerUsername the name of the player performing the action * @param playerUsername the name of the player performing the action
*/ */
public void skipUpper(String playerUsername) throws RemoteException { public void skipTurn(String playerUsername) throws RemoteException {
stub.skipUpper(playerUsername); stub.skipTurn(playerUsername);
} }
/**
* Requests to skip drawing from the lower list.
* This action is available only when the lower list is empty or the player cannot draw any card.
* @param playerUsername the name of the player performing the action
*/
public void skipLower(String playerUsername) throws RemoteException {
stub.skipLower(playerUsername);
}
/** /**
@@ -39,9 +39,8 @@ public interface IGameServer extends Remote {
void drawLowerBuildingCard(String playerUsername,int pos) throws RemoteException; void drawLowerBuildingCard(String playerUsername,int pos) throws RemoteException;
void skipUpper(String playerUsername) throws RemoteException; void skipTurn(String playerUsername) throws RemoteException;
void skipLower(String playerUsername) throws RemoteException;
void pickOptionalTribeCard(String playerUsername,int pos) throws RemoteException; void pickOptionalTribeCard(String playerUsername,int pos) throws RemoteException;
@@ -8,14 +8,11 @@ import it.polimi.ingsw.gc14.Network.NetworkEvents.*;
import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback; import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback;
import it.polimi.ingsw.gc14.Network.RMI.Common.IGameServer; import it.polimi.ingsw.gc14.Network.RMI.Common.IGameServer;
import java.net.InetAddress;
import java.rmi.RemoteException; import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry; import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry; import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject; import java.rmi.server.UnicastRemoteObject;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@@ -157,24 +154,15 @@ public class RMIServer extends UnicastRemoteObject implements IGameServer {
/** /**
* Requests to skip drawing from the upper list. * Requests to skip the turn.
* This action is available only when the upper list is empty or the player cannot draw any card. * This action is available only when the player cannot draw any tribe card, but still can buy some buildings.
* @param playerUsername the name of the player performing the action * @param playerUsername the name of the player performing the action
*/ */
public void skipUpper(String playerUsername) { public void skipTurn(String playerUsername) {
actionQueue.offer(new SkipUpper(playerUsername)); actionQueue.offer(new SkipNoDrawable(playerUsername));
} }
/**
* Requests to skip drawing from the lower list.
* This action is available only when the lower list is empty or the player cannot draw any card.
* @param playerUsername the name of the player performing the action
*/
public void skipLower(String playerUsername) {
actionQueue.offer(new SkipLower(playerUsername));
}
/** /**
* Used to draw a tribe card from the upper list. * Used to draw a tribe card from the upper list.
@@ -159,23 +159,14 @@ public class TCPClient implements IClient {
} }
/**
* Requests to skip drawing from the upper list.
* This action is available only when the upper list is empty or the player cannot draw any card.
* @param playerUsername the name of the player performing the action
*/
public void skipUpper(String playerUsername) {
doEvent(new SkipUpper(playerUsername));
}
/** /**
* Requests to skip drawing from the lower list. * Requests to skip drawing turn.
* This action is available only when the lower list is empty or the player cannot draw any card. * This action is available only when the player cannot draw any tribe card, but still can buy some buildings.
* @param playerUsername the name of the player performing the action * @param playerUsername the name of the player performing the action
*/ */
public void skipLower(String playerUsername) { public void skipTurn(String playerUsername) {
doEvent(new SkipLower(playerUsername)); doEvent(new SkipNoDrawable(playerUsername));
} }
@@ -195,8 +195,7 @@ public class TUI implements IView {
table.addRow(List.of("5-PickOptionalTribe(pos)", "")); table.addRow(List.of("5-PickOptionalTribe(pos)", ""));
table.addRow(List.of("6-PickOptionalBuilding(pos)", "")); table.addRow(List.of("6-PickOptionalBuilding(pos)", ""));
table.addRow(List.of("7-NoOptional", "")); table.addRow(List.of("7-NoOptional", ""));
table.addRow(List.of("8-NoUpperCard", "")); table.addRow(List.of("8-SkipTurn", ""));
table.addRow(List.of("9-NoLowerCard", ""));
return table.build(); return table.build();
} }
@@ -117,7 +117,7 @@ class GameControllerTest {
return; return;
} }
assertTrue(controller.SkipLowerDrawing(username)); assertTrue(controller.SkipNoDrawable(username));
return; return;
} }
@@ -135,7 +135,7 @@ class GameControllerTest {
return; return;
} }
assertTrue(controller.SkipUpperDrawing(username)); assertTrue(controller.SkipNoDrawable(username));
return; return;
} }
@@ -187,8 +187,7 @@ class GameControllerTest {
assertFalse(controller.drawLowerTribeCard("ghost", 0)); assertFalse(controller.drawLowerTribeCard("ghost", 0));
assertFalse(controller.drawUpperBuildingCard("ghost", 0)); assertFalse(controller.drawUpperBuildingCard("ghost", 0));
assertFalse(controller.drawLowerBuildingCard("ghost", 0)); assertFalse(controller.drawLowerBuildingCard("ghost", 0));
assertFalse(controller.SkipUpperDrawing("ghost")); assertFalse(controller.SkipNoDrawable("ghost"));
assertFalse(controller.SkipLowerDrawing("ghost"));
assertFalse(controller.pickOptionalTribeCard("ghost", 0)); assertFalse(controller.pickOptionalTribeCard("ghost", 0));
assertFalse(controller.pickOptionalBuildingCard("ghost", 0)); assertFalse(controller.pickOptionalBuildingCard("ghost", 0));
assertFalse(controller.noOptionalCard("ghost")); assertFalse(controller.noOptionalCard("ghost"));
@@ -608,7 +607,7 @@ class GameControllerTest {
assertFalse(game.getLowerListTribeCards().isEmpty()); assertFalse(game.getLowerListTribeCards().isEmpty());
assertTrue(firstNonEventIndexOrMinusOne(game.getLowerListTribeCards()) != -1); assertTrue(firstNonEventIndexOrMinusOne(game.getLowerListTribeCards()) != -1);
assertFalse(controller.SkipLowerDrawing(current.getUserName())); assertFalse(controller.SkipNoDrawable(current.getUserName()));
} }
@Test @Test
@@ -627,7 +626,7 @@ class GameControllerTest {
assertFalse(game.getUpperListTribeCards().isEmpty()); assertFalse(game.getUpperListTribeCards().isEmpty());
assertTrue(firstNonEventIndexOrMinusOne(game.getUpperListTribeCards()) != -1); assertTrue(firstNonEventIndexOrMinusOne(game.getUpperListTribeCards()) != -1);
assertFalse(controller.SkipUpperDrawing(current.getUserName())); assertFalse(controller.SkipNoDrawable(current.getUserName()));
} }
@@ -4,6 +4,7 @@ import it.polimi.ingsw.gc14.Model.Cards.BuildingCard;
import it.polimi.ingsw.gc14.Model.Cards.TribeCard; 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.Character;
import it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType;
import it.polimi.ingsw.gc14.Model.GamePackage.Board;
import it.polimi.ingsw.gc14.Model.GamePackage.GameStages; import it.polimi.ingsw.gc14.Model.GamePackage.GameStages;
import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.Artist; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.Artist;
import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.Builder; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.Builder;
@@ -11,6 +12,7 @@ import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.Inventor;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.Timeout;
import java.lang.reflect.Field;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -85,8 +87,12 @@ class GameTest {
return; return;
} }
assertTrue(game.SkipLowerDrawing(current)); if(game.getCurrentState().getNUpper() == 0 || game.getUpperListTribeCards().stream().allMatch(TribeCard::IsEventCard))
return; {
assertTrue(game.SkipNoDrawable(current));
return;
}
} }
if (game.getCurrentState().getNUpper() > 0) { if (game.getCurrentState().getNUpper() > 0) {
@@ -102,8 +108,11 @@ class GameTest {
return; return;
} }
assertTrue(game.SkipUpperDrawing(current)); if(game.getCurrentState().getNLower() == 0 || game.getLowerListTribeCards().stream().allMatch(TribeCard::IsEventCard))
return; {
assertTrue(game.SkipNoDrawable(current));
return;
}
} }
fail( fail(
@@ -1037,6 +1046,25 @@ class GameTest {
Player player = players.get(0); Player player = players.get(0);
try {
Field boardField = Game.class.getDeclaredField("board");
boardField.setAccessible(true);
Board board = (Board) boardField.get(game);
Field upperTribe = Board.class.getDeclaredField("upperListTribe");
upperTribe.setAccessible(true);
List<TribeCard> upper = (List<TribeCard>) upperTribe.get(board);
upper.removeIf(TribeCard::IsEventCard);
Field lowerTribe = Board.class.getDeclaredField("lowerListTribe");
lowerTribe.setAccessible(true);
List<TribeCard> lower = (List<TribeCard>) lowerTribe.get(board);
lower.removeIf(TribeCard::IsEventCard);
} catch (NoSuchFieldException | IllegalAccessException e) {
fail("Reflection fallita: " + e.getMessage());
}
int prestigeBefore = player.getPrestigeValue(); int prestigeBefore = player.getPrestigeValue();
player.buildingCards.add(new BuildingCard(12, 1, 1, 7)); player.buildingCards.add(new BuildingCard(12, 1, 1, 7));
@@ -1074,6 +1102,25 @@ class GameTest {
Player player = players.get(0); Player player = players.get(0);
assertNotNull(player); assertNotNull(player);
try {
Field boardField = Game.class.getDeclaredField("board");
boardField.setAccessible(true);
Board board = (Board) boardField.get(game);
Field upperTribe = Board.class.getDeclaredField("upperListTribe");
upperTribe.setAccessible(true);
List<TribeCard> upper = (List<TribeCard>) upperTribe.get(board);
upper.removeIf(TribeCard::IsEventCard);
Field lowerTribe = Board.class.getDeclaredField("lowerListTribe");
lowerTribe.setAccessible(true);
List<TribeCard> lower = (List<TribeCard>) lowerTribe.get(board);
lower.removeIf(TribeCard::IsEventCard);
} catch (NoSuchFieldException | IllegalAccessException e) {
fail("Reflection fallita: " + e.getMessage());
}
int prestigeBefore = player.getPrestigeValue(); int prestigeBefore = player.getPrestigeValue();
player.builders.add(new Builder(1, 0, 4)); player.builders.add(new Builder(1, 0, 4));
@@ -1110,8 +1157,7 @@ class GameTest {
.findFirst() .findFirst()
.orElseThrow(); .orElseThrow();
assertFalse(game.SkipLowerDrawing(wrongPlayer)); assertFalse(game.SkipNoDrawable(wrongPlayer));
assertFalse(game.SkipUpperDrawing(wrongPlayer));
} }
@Test @Test
@@ -1127,15 +1173,13 @@ class GameTest {
boolean checkedAtLeastOneSkip = false; boolean checkedAtLeastOneSkip = false;
if (game.getCurrentState().getNLower() > 0 if (game.getCurrentState().getNLower() > 0 || game.getLowerListTribeCards().stream().allMatch(TribeCard::IsEventCard)) {
&& firstNonEventIndexOrMinusOne(game.getLowerListTribeCards()) != -1) { assertFalse(game.SkipNoDrawable(current));
assertFalse(game.SkipLowerDrawing(current));
checkedAtLeastOneSkip = true; checkedAtLeastOneSkip = true;
} }
if (game.getCurrentState().getNUpper() > 0 if (game.getCurrentState().getNUpper() > 0|| game.getUpperListTribeCards().stream().allMatch(TribeCard::IsEventCard)) {
&& firstNonEventIndexOrMinusOne(game.getUpperListTribeCards()) != -1) { assertFalse(game.SkipNoDrawable(current));
assertFalse(game.SkipUpperDrawing(current));
checkedAtLeastOneSkip = true; checkedAtLeastOneSkip = true;
} }
@@ -1161,11 +1205,10 @@ class GameTest {
int eventIndex = firstEventIndexOrMinusOne(game.getUpperListTribeCards()); int eventIndex = firstEventIndexOrMinusOne(game.getUpperListTribeCards());
assertNotEquals( if(eventIndex==-1)
-1, {
eventIndex, assertFalse(game.NoOptionalCard(current));
"There should be at least one event card in the upper tribe list to test rejection." }
);
assertFalse(game.PickOptionalTribeCardByIndex(current, eventIndex)); assertFalse(game.PickOptionalTribeCardByIndex(current, eventIndex));
} }