/z now lists all games opened and closed

also fixed two bugs in VoteHandler (Array out of Bound in GhostNPC and in ClientVoteData)
This commit is contained in:
Seraina 2022-04-15 18:47:05 +02:00
parent 1ba30663be
commit 7c70b276cd
12 changed files with 105 additions and 48 deletions

View File

@ -23,8 +23,9 @@ Votes are held in the night for the ghosts to decide who will be next and during
* /w _username$message_ - sends a message to the specified user only.
* /g - create (&join) a new lobby.
* /j _1_ - join lobby 1. To join lobby 2, use /j _2_, etc.
* /l - list all connected clients and all lobbies
* /l - list all connected clients and all lobbies and their status
* /p - list all players in your lobby.
* /z - list all games on the server and their status
* /e - exit your lobby
* /n _name_ - changes player name. If unavailable, it adds a fun and quirky suffix
* /q - quit

View File

@ -1,6 +1,9 @@
package ch.unibas.dmi.dbis.cs108.gamelogic;
import ch.unibas.dmi.dbis.cs108.BudaLogConfig;
import java.util.Arrays;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Data structure that is used to store clientVotes in an array, where the index correponds to the
@ -8,6 +11,8 @@ import java.util.Arrays;
*/
public class ClientVoteData {
public static final Logger LOGGER = LogManager.getLogger();
public static final BudaLogConfig l = new BudaLogConfig(LOGGER);
private int[] vote; //saves vote of clientHandler for later transmission to passenger, by default MAX_VALUE, index corresponds to Passenger position
private boolean[] hasVoted; //saves hasVoted status of clientHandler for later transmission to passenger, by default false, index corresponds to Passenger position
@ -33,7 +38,14 @@ public class ClientVoteData {
* @param vote the vote value
*/
public void setVote(int position, int vote) {
this.vote[position] = vote;
if (vote == Integer.MAX_VALUE) {
setHasVoted(position, false);
}
try {
this.vote[position] = vote;
} catch (IndexOutOfBoundsException e) {
LOGGER.info("Position is: " + position);
}
}
/**

View File

@ -19,9 +19,7 @@ public class Game implements Runnable {
/**
* Can be extended for optional Game-settings
**/
protected final int nrOfPlayers; //sets the length of the train
protected final int nrOfGhosts; // sets how many Ghosts we start witch
protected int nrOfUsers; // safes how many clients are active in this Game
protected GameState gameState;
protected boolean isDay = false; //false means it is night, it is night by default
protected VoteHandler voteHandler = new VoteHandler();
@ -38,36 +36,23 @@ public class Game implements Runnable {
*/
public Game(int nrOfPlayers, int nrOfGhosts, int nrOfUsers, Lobby lobby)
throws TrainOverflow { //ToDo: Who handles Exception how and where
this.nrOfPlayers = nrOfPlayers;
this.nrOfGhosts = nrOfGhosts;
this.nrOfUsers = nrOfUsers;
this.gameState = new GameState(nrOfPlayers, nrOfGhosts, nrOfUsers);
this.lobby = lobby;
nameCounter++;
this.name = "Game-" + nameCounter;
this.name = "Game" + nameCounter;
}
public GameState getGameState() {
return gameState;
}
public int getNrOfGhosts() {
return nrOfGhosts;
}
public int getNrOfPlayers() {
return nrOfPlayers;
}
public int getNrOfUsers() {
return nrOfUsers;
}
public Lobby getLobby() {
return lobby;
}
public boolean getIsDay() {return isDay;}
public boolean getIsDay() {return isDay; }
public String getName() {return name; }
public void setDay(boolean day) {
isDay = day;

View File

@ -76,6 +76,18 @@ public class GameState {
return train;
}
public int getNrOfUsers() {
return nrOfUsers;
}
public int getNrOfPlayers() {
return nrOfPlayers;
}
public int getNrOfGhosts() {
return nrOfGhosts;
}
/**
*
*

View File

@ -11,7 +11,7 @@ import org.apache.logging.log4j.Logger;
* vote / ghost vote) and handles votes accordingly. - Sends voting request to passengers that need
* to be concerned - collects voting results - calculates who was voted for - decides consequence of
* vote: - Is it OG ghost: humans win - Is it last human: ghosts win - Is it just a human: message
* "x is a human" - Is it a peasant ghost -> kickoff
* "x is a human" - Is it a peasant ghost - kickoff
*
* <p>(All messages going to Clients are handled via ServerGameInfoHandler)
*
@ -44,7 +44,7 @@ public class VoteHandler {
* @param passengers: passengers on the train
*/
public void ghostVote(Passenger[] passengers, Game game) {
public String ghostVote(Passenger[] passengers, Game game) {
LOGGER.debug("ghostVote has been called");
LOGGER.info(game.getGameState().toString());
@ -106,12 +106,23 @@ public class VoteHandler {
n.noiseNotifier(passengers, passengers[i], g, game);
}
}
int humanCounter = 0;
for(Passenger passenger : passengers) {
if(!passenger.getIsGhost()) { //if it is a human
humanCounter++;
}
}
if (humanCounter == 0) {
return ClientGameInfoHandler.gameOverGhostsWin;
}
LOGGER.info(game.getGameState().toString());
// set hasVoted to false for all passengers for future votings
for (Passenger passenger : passengers) {
passenger.setHasVoted(false);
}
return "";
}
/**

View File

@ -43,26 +43,31 @@ public class GhostNPC extends Ghost {
* but only for positions where there aren't any ghosts and sets hasVoted to true
* TODO: Make NPC smarter
*/
public void vote(Game game){
public void vote(Game game) {
int ghostCounter = 0;
Passenger[] train = game.getGameState().getPassengerTrain();
for(Passenger passenger : train) {
if(passenger.isGhost) {
for (Passenger passenger : train) {
if (passenger.isGhost) {
ghostCounter++;
}
}
int[] humanPositions = new int[game.getNrOfPlayers() - ghostCounter ];
int j = 0;
for (int i = 0; i < train.length; i++) {
if (!train[i].isGhost) { //is human
humanPositions[j] = train[i].getPosition();
j++;
int[] humanPositions = new int[game.getGameState().getNrOfPlayers() - ghostCounter];
if (humanPositions.length == 0) {
vote = Integer.MAX_VALUE;
} else {
int j = 0;
for (int i = 0; i < train.length; i++) {
if (!train[i].isGhost) { //is human
humanPositions[j] = train[i].getPosition();
j++;
}
}
int randomPosition = (int) (Math.random() * humanPositions.length);
vote = humanPositions[randomPosition];
hasVoted = true;
LOGGER.info("GhostNPC at Position: " + this.getPosition() + " has voted for: " + vote);
}
int randomPosition = (int) (Math.random()*humanPositions.length);
vote = humanPositions[randomPosition];
hasVoted = true;
LOGGER.info("GhostNPC at Position: " + this.getPosition() + " has voted for: " + vote);
}
/**

View File

@ -53,7 +53,7 @@ public class GhostPlayer extends Ghost {
public void getVoteFromGameState(ClientVoteData clientVoteData, Game game) {
vote = clientVoteData.getVote()[position];
hasVoted = clientVoteData.getHasVoted()[position];
clientVoteData.setVote(position,Integer.MAX_VALUE);
clientVoteData.setVote(position, Integer.MAX_VALUE);
clientVoteData.setHasVoted(position,false);
LOGGER.info("Ghost at Pos: " + position + " has voted for: " + vote);
/*

View File

@ -65,6 +65,9 @@ public class MessageFormatter {
case "/p":
stringBuilder.append(Protocol.listPlayersInLobby);
break;
case "/z":
stringBuilder.append(Protocol.listGames);
break;
case "/j":
stringBuilder.append(Protocol.joinLobby + "$");
try {
@ -93,7 +96,6 @@ public class MessageFormatter {
break;
case "/s":
stringBuilder.append(Protocol.startANewGame);
break;
default:
s = msg;

View File

@ -122,10 +122,17 @@ public class Protocol {
/**
* A Client decides to start the game.
* A Client decides to start the game. The game is started in the lobby the message came from.
* Only one game can be started per lobby at a time.
*/
public static final String startANewGame = "STGAM";
/**
* Client request to see a list of all games, ongoing and finished.
*/
public static final String listGames = "LISTG";
/**
* Client informs server that they have voted and delivers this vote in the form of "CVOTE$position$vote"
*/

View File

@ -423,7 +423,7 @@ public class ClientHandler implements Runnable {
*/
public void listLobbies() {
if (Lobby.lobbies.isEmpty()) {
sendAnnouncementToClient("No open Lobbies.");
sendAnnouncementToClient("No Lobbies.");
} else {
for (Lobby l : Lobby.lobbies) {
String lobbyStatus = "closed";
@ -475,6 +475,32 @@ public class ClientHandler implements Runnable {
}
}
/**
* Lists all Games currenty running and already finished and displays it to the client handled by this
*/
public void listGames() {
if (Lobby.runningGames.isEmpty() && Lobby.finishedGames.isEmpty()) {
sendAnnouncementToClient("No Games");
} else {
sendAnnouncementToClient("Running Games:");
try {
for (Game runningGame : Lobby.runningGames) {
sendAnnouncementToClient(" - " + runningGame.getName() + ", Lobby" + runningGame.getLobby().getLobbyID());
}
} catch (Exception e) {
sendAnnouncementToClient(" - No running Games");
}
sendAnnouncementToClient("Finished Games");
try {
for (Game finishedGame : Lobby.finishedGames) {
sendAnnouncementToClient(" - " + finishedGame.getName() + ", Lobby" + finishedGame.getLobby().getLobbyID());
}
} catch (Exception e) {
sendAnnouncementToClient(" - No finished Games");
}
}
}
/**
* Closes the client's socket, in, and out. and removes from global list of clients.
*/

View File

@ -111,6 +111,9 @@ public class JServerProtocolParser {
case Protocol.startANewGame:
h.startNewGame();
break;
case Protocol.listGames:
h.listGames();
break;
default:
System.out.println("Received unknown command");
}

View File

@ -108,13 +108,6 @@ public class Lobby {
return null;
}
public static HashSet<Game> getFinishedGames() {
return finishedGames;
}
public static HashSet<Game> getRunningGames() {
return runningGames;
}
/**
* Returns the game that the clients in this lobby are in