diff --git a/src/server/BaseGame.java b/src/server/BaseGame.java index 7d1b885..f953a75 100644 --- a/src/server/BaseGame.java +++ b/src/server/BaseGame.java @@ -1,17 +1,12 @@ package server; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; import java.io.IOException; -import java.net.MalformedURLException; -import java.net.ServerSocket; +import java.io.InputStream; import java.net.Socket; -import java.net.UnknownHostException; -import java.util.ArrayList; import java.util.List; -import org.json.*; +import card.Card; +import player.BasePlayer; public abstract class BaseGame { /* @@ -24,8 +19,19 @@ * (COLORED) */ - public enum MSG_TYPES {ERROR, WARNING, INFORMATION, QUESTION}; - + public static final byte[] MAGIC = { 1, 3, 3, 7 }; + public static final byte MOVE_INVALID = 0; + public static final byte MOVE_VALID = 1; + public static final byte MOVE_UPDATE = 5; + public static final byte MOVE_WON = 6; + public static final byte MOVE_LOST = 7; + public static final byte MOVE_DRY = 1 << 6; + public static final byte MOVE_PLACE_CARD = 2; + public static final byte MOVE_TRASH_CARD = 3; + public static final byte MOVE_HINT = 4; + public static final byte HINT_COLOR = 0; + public static final byte HINT_VALUE = 1; + final static int GREEN = 0; final static int RED = 1; final static int YELLOW = 2; @@ -36,23 +42,22 @@ final static int N_CARDS = 50; final static int MAX_HINTS = 8; final static int MAX_FLASHS = 3; - - int N_PLAYERS = 3; + + int nrOfPlayers = 3; static int CARDS_PER_PLAYER; - int CARDS_IN_DECK; - + int cardsInDeck; + int hints; int flashs; Card[][] deck; int[] deckCounter; - ArrayList trash; - AbstractPlayer[] players; + List trash; + BasePlayer[] players; int currentPlayer; - boolean won; - boolean lost; - + + Socket socket; int port; - + List history; public BaseGame(){ @@ -60,349 +65,26 @@ } protected void init(){ - history = new ArrayList<>(); - loadOptions(); - loadFont(); + createHistory(); //establishConnection(); - CARDS_PER_PLAYER = (N_PLAYERS <= 3) ? 5 : 4; + CARDS_PER_PLAYER = (nrOfPlayers <= 3) ? 5 : 4; hints = MAX_HINTS; flashs = 0; - roundsLeft = -1; - createPlayers(); - currentPlayer = 0; - resetMoveValues(); - addCards(); - CARDS_IN_DECK = cards.size(); - createUI(); - dealCards(); + cardsInDeck = N_CARDS; } - protected void createPlayers(){ - players = new AbstractPlayer[N_PLAYERS]; - } - - private void addCards(){ - cards = new ArrayList<>(); - deck = new Card[COLORS][5]; - deckCounter = new int[5]; - for(int i=0; i<5; ++i){ - deckCounter[i] = 0; - } - trash = new ArrayList<>(); - int[] dist = new int[]{3, 2, 2, 2, 1}; - int[][] tmp_cards = new int[][]{ - dist.clone(), - dist.clone(), - dist.clone(), - dist.clone(), - dist.clone() - }; - for(int i=0; i 0){ - int index = random(CARDS_IN_DECK--); - card = cards.remove(index); - } else { - if(roundsLeft == -1) roundsLeft = N_PLAYERS; - card = new Card(3, -1, playerID, this); - } - players[playerID].setCard(cardID, card); - } - - protected void dealCards(){ - int dealtCards = 0; - for(; dealtCards < CARDS_PER_PLAYER; ++dealtCards){ - for(int i=0; i 0; } - - void setWonOrLost(){ - boolean won = true; - boolean lost = false; - for(int i=0; i MAX_HINTS) hints = MAX_HINTS; - } - } - - protected void addThunder(){ - thunders++; - } - - protected void placeCard(Card c, int color, int value){ - deckCounter[color]++; - deck[color][value] = c; - if(value+1 == 5) addHint(); - } - - protected void onNext(){ - if(!checkValidMove()){ - printMessage("Please select all cards of the selected color/value", MSG_TYPES.ERROR); - return; - } - if(roundsLeft >= 0) roundsLeft--; - int selCardIndex = 0; - AbstractPlayer player = players[selectedPlayer]; - for(int i=0; i 0){ - printMessage("Please deselect all cards first", MSG_TYPES.ERROR); - return; - } - useColor = true; - useValue = false; - placeCard = false; - trashCard = false; - } - - protected void onValue(){ - if(!hintAvailable()){ - printMessage("No hints left!", MSG_TYPES.ERROR); - return; - } - if(selectedCards > 0){ - printMessage("Please deselect all cards first", MSG_TYPES.ERROR); - return; - } - useValue = true; - useColor = false; - placeCard = false; - trashCard = false; - } - - protected void onTrash(){ - if(selectedCards > 0){ - printMessage("Please deselect all cards first", MSG_TYPES.ERROR); - return; - } - useColor = false; - useValue = false; - placeCard = false; - trashCard = true; - } - - protected void onPlace(){ - if(selectedCards > 0){ - printMessage("Please deselect all cards first", MSG_TYPES.ERROR); - return; - } - useColor = false; - useValue = false; - placeCard = true; - trashCard = false; - } - - protected abstract void showTrash(); - - /** - * Stores the current state of the game in the history - * @param json the current state as json object - */ - protected void addToHistory(){ - String json = ""; - history.add(json); - } - /** * Returns the state of the game at a given @param move index * @param move the index of the move you want to get. @@ -410,7 +92,33 @@ * Negative values are interpreted as index from the end (-1 is the last state). */ public List getHistory(int move){ - final int index = move >= 0 ? move : history.size()-1; - return history.subList(0, index); + final int index = move>=0 ? move : history.size()+move; + return history.subList(0, index); + } + + protected abstract void receive(); + + class SocketListenerThread implements Runnable { + Socket socket; + + public SocketListenerThread(Socket socket){ + this.socket = socket; + } + + @Override + public void run() { + InputStream inStream = null; + int availableBytes = 0; + try { + inStream = socket.getInputStream(); + availableBytes = inStream.available(); + if(availableBytes > 0){ + receive(); + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } } } \ No newline at end of file diff --git a/src/server/ClientGame.java b/src/server/ClientGame.java index 19db676..90ba19a 100644 --- a/src/server/ClientGame.java +++ b/src/server/ClientGame.java @@ -1,32 +1,40 @@ package server; +import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; -import java.net.Socket; +import java.util.ArrayList; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; -public class ClientGame extends BaseGame { - Socket socket; - - int selectedPlayer; - int selectedCards; - int chosenColor; - int chosenValue; - boolean useColor; - boolean useValue; - boolean placeCard; - boolean trashCard; - +import card.Card; + +public abstract class ClientGame extends BaseGame { + + public enum MSG_TYPES {ERROR, WARNING, INFORMATION, QUESTION}; + //Options stuff final File options = new File("options.json"); JSONObject root; int difficulty; int fontSize; + @Override + protected void init() { + super.init(); + loadOptions(); + loadFont(); + + SocketListenerThread listenThread = new SocketListenerThread(socket); + listenThread.run(); + } + @Override + protected void createHistory() { + history = new ArrayList<>(); + } protected void loadOptions(){ try { JSONTokener tokener = new JSONTokener(options.toURI().toURL().openStream()); @@ -43,65 +51,74 @@ e.printStackTrace(); } } - - public void resetMoveValues(){ - selectedPlayer = -1; - chosenColor = -1; - chosenValue = -1; - selectedCards = 0; - useColor = useValue = trashCard = placeCard = false; + + protected void movePlaceCard(Card c){ + movePlaceCard(c, false); } - boolean checkValidMove(){ - if(selectedCards == 0) return false; - if(!hintAvailable() && (useColor || useValue)) return false; - if((trashCard || placeCard) && selectedCards == 1) return true; - int countCards = 0; - for(int i=0; i cards; - int roundsLeft; + ServerSocket server; + + public enum PROTOCOL { + VIBE_DUMB + }; + + List cards; + long seed; + Random rand; + + int movesLeft; + boolean won; + boolean lost; + + List sockets; + + public ServerGame() { + } + + @Override + protected void init() { + super.init(); + sockets = new ArrayList<>(); + try { + while(nrOfPlayers < 2){ //TODO + socket = server.accept(); + sockets.add(socket); + nrOfPlayers++; + // TODO do this somewhere else + new Thread(new SocketListenerThread(socket)).start(); + } + } catch (IOException e) { + // TODO Auto-generated catch block + // TODO exit + e.printStackTrace(); + } + + seed = 0; + rand = new Random(seed); + movesLeft = -1; + createPlayers(); + currentPlayer = 0; + // shuffleCards(); // TODO use this instead of addCards() + addCards(); + dealCards(); + } + + protected void shuffleCards() { + cards = new ArrayList<>(); + //TODO add cards + //TODO shuffle + } + + // protected void onNext(){ + // if(!checkValidMove()){ + // printMessage("Please select all cards of the selected color/value", + // MSG_TYPES.ERROR); + // return; + // } + // if(roundsLeft >= 0) roundsLeft--; + // int selCardIndex = 0; + // AbstractPlayer player = players[selectedPlayer]; + // for(int i=0; i= 0) movesLeft--; + send(MOVE_UPDATE, toJson().toString()); + } + } + + protected Card getRealCard(Card c, int[] index){ + Card[] cards = getPlayer(currentPlayer).getCards(); + for(int i=0; i(); + deck = new Card[COLORS][5]; + deckCounter = new int[5]; + for (int i = 0; i < 5; ++i) { + deckCounter[i] = 0; + } + trash = new ArrayList<>(); + int[] dist = new int[] { 3, 2, 2, 2, 1 }; + int[][] tmp_cards = new int[][] { dist.clone(), dist.clone(), dist.clone(), dist.clone(), dist.clone() }; + for (int i = 0; i < N_CARDS; ++i) { + int[] p = new int[2]; + do { + p = randomPosition(); + } while (tmp_cards[p[0]][p[1]] == 0); + tmp_cards[p[0]][p[1]]--; + cards.add(new Card(p[0], (p[1] + 1), i)); + } + } + + private int[] randomPosition(){ + int[] p = new int[2]; + p[0] = random(5); + p[1] = random(5); + return p; + } + + private int random(int max){ + return rand.nextInt(max); + } + + private void dealCard(int cardPos, int playerID) { + Card card; + if (cardsInDeck > 0) { + int index = random(cardsInDeck--); + card = cards.remove(index); + // TODO Use this code as soon as shuffle is implemented + // card = getCardFromDeck(); + } else { + if (movesLeft == -1) movesLeft = nrOfPlayers; + card = Card.DUMMY_CARD; + } + players[playerID].setCard(cardPos, card); + } + + void setWonOrLost() { + boolean won = true; + boolean lost = false; + for (int i = 0; i < COLORS; ++i) { + if (deckCounter[i] != 5) { + won = false; + break; + } + } + if (flashs == MAX_FLASHS) { + lost = true; + won = false; + } + if (movesLeft == 0) + lost = true; + if (won){ + send(MOVE_WON); + } + else if (lost){ + send(MOVE_LOST); + } + this.won = won; + this.lost = lost; + } + + protected void send(byte msgType){ + send(msgType, null); + } + + protected void send(byte msgType, String msg){ + DataOutputStream os = null; + try { + os = new DataOutputStream(socket.getOutputStream()); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + try { + os.write(MAGIC); + os.write(ServerGame.PROTOCOL.VIBE_DUMB.ordinal()); + os.write(msgType); + os.write(new byte[]{ 0, 0 }); + if(msg != null) os.writeUTF(msg); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + protected void removeHint() { + hints--; + } + + protected void addHint() { + if (hints != MAX_HINTS) { + hints++; + if (hints > MAX_HINTS) + hints = MAX_HINTS; + } + } + + protected void addFlash() { + flashs++; + } @Override protected void createUI() { // TODO Auto-generated method stub + } + /** + * Stores the current state of the game in the history + * + * @param json + * the current state as json object + */ + protected void addToHistory(String json) { + history.add(json); + } + + protected JSONObject toJson(){ + JSONObject root = new JSONObject(); + root.put("movesLeft", movesLeft); + root.put("cardsInDeck", cardsInDeck); + root.put("hints", hints); + root.put("flashs", flashs); + root.put("movesLeft", movesLeft); + root.put("movesLeft", movesLeft); + root.put("movesLeft", movesLeft); + root.put("movesLeft", movesLeft); + root.put("movesLeft", movesLeft); + JSONArray trashArray = new JSONArray(); + for(Card c : trash){ + trashArray.put(c.toJson()); + } + root.put("trash", trashArray); + + JSONObject deckRow = new JSONObject(); + for(int i=0; i(); } - - @Override - public void loadFont() { - // TODO Auto-generated method stub - - } - - @Override - public Object getFont() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void printMessage(String msg, MSG_TYPES type) { - // TODO Auto-generated method stub - - } - - @Override - protected void showTrash() { - // TODO Auto-generated method stub - - } - }