I have written a version of Castle that so far plays through the terminal. I have recently refactored my code (which can be found here) to use the MVC design pattern. After I have added a GUI I will add networking capabilities. The game at the moment should be thought of as a local single (human) player game against AI's.
The game controller holds the gameState, gameView and then the business logic to run the game. The business logic is essentially just a loop that loops over the players in turn telling each to pick a move, applying the move to the state and then telling the view to print the state (to the terminal atm).
The game is made up of the 3 types of players:
- An Information Set MCTS AI player
- AI player that just plays a basic strategy of playing the lowest possible card(s)
- Human player
The AI players have a controller that holds the player model and business logic and the player view (but only for human players). The player model is a generic POJO containing hand, castle cards etc. The logic is different from player to player but is all held in the controller. The game controller calls playerController.getMove(), the player then chooses their move depending on their strategy/implementation and returns it to the gameController.
The 'Move' objects are created by the playerController and passed back to the gameController and hold information like the card played or if they can't play then its a PickUp move etc. The move objects hold the choices made by the player and the business logic of how they change the game state.
- GameController calls player.getMove(gameState)
- PlayerController selects a move and returns it
- Game controller calls move.doMove(gameState)
- Next player until someone wins
My first question is, is it ok that the 'Moves' store logic or is there a better way? They are the only components that don't strictly follow MVC.
Secondly and more importantly, I can't seem to get my head around how the game runs using JavaFX as a GUI. I haven't got any experience with JavaFX until now and little UI experience in general but I'm trying. I've read that the Controller/View can become a bit convoluted. I've tried to find videos and resources to help give me some understanding but none seem to be in quite the right context - turn based, animationless (for now), card game. In my head I imagine the GUI displaying the players cards face up and the opponent's cards hidden but displayed with their backs up. The game waits for the human to select the card(s) to play and validates them. Then it updates to show the move completed. On AI opponent turns it waits until a move has been chosen and then updates on screen. But where does this go and how does it interact? I think the GameController/View should display the game state for the player to see and interact with? Is the playerView unnecessary then?
I think I'm struggling to get my head around how the GUI is running all the time for the player and doesn't care about their input until its their turn and how this fits in with the game loop I have created so far.
EDIT:
I have managed to create a scene with ListView's to display the players' cards that have been dealt to them. However, I cannot figure out how my game loop is added to the code.
boolean print = true;
boolean gameOver = false;
do {
for (PlayerController player : players) {
if (gameOver) {
break;
}
boolean playersTurn = true;
while (playersTurn) {
CastleMove move = player.getMove(gameState);
doMove(move);
// If the player does not burn the pile then it is the next players turn
if (!move.burnsPile()) {
playersTurn = false;
}
if (gameState.isGameOver()) {
gameOver = true;
break;
}
}
}
} while (!gameOver);
If I add the code to the start() method then the window displaying the cards never shows because it hasn't been executed yet. Where does it go?