At this point I am close to having a working game using local mutiplayer. With that in mind I would like to share what I have accomplished over the past week and a half.
Recently my professor, shout out to you Matt you’re awesome, purchased a book for me that I had found online. The Unity 5.x Game AI Programming Cookbook had been a target of interest for a few weeks now, and after seeing a snippet of what the book could provide me, I had to have it. However, I didn’t know just how much information I was going to get out of it.
My initial plan was to use the sixth chapter of the book on Board AI Programming to get me started on my own AI implementation down the road. After finishing chapter six and learning about using decision tree data structures, minmax, and negamax search algorithms, I decided to back track and check out the rest of the book. This was the best decision I have made in a long time as the book had an entire chapter on handling game states.
What was great about this moment was the fact that I was just starting my implementation of my own state machine in my game. Therefore, when I saw this chapter I became beyond ecstatic and dove right in. Immediately my initial design for my state diagram became much smaller.
What once was 7 states or more had now been compacted to the four you see below:
What I had learned from reading the chapter was mostly mechanical, how to initialize and use states, as well as creating a template to move from one state to another. The important part here is that each state needed its own file to be accessed depending on the state of the game.
Referencing the diagram above, my game has 4 distinctive states: The Player Turn, Comparison, AI Turn, and Game Over. The diagram does not do any justice of explaining the full purpose of each step, so I will be explaining them in depth.
The Player turn state starts off by enabling the ability to move the players card in accordance to which players turn it is. The way the game is set up at this moment always has Player 1 going first. Therefore, player 1 will have the ability to move their cards, but player 2 will not. When the player picks up a card with the mouse, drags it over a spot on the board, and then releases the mouse press that card will be removed from the players hand and placed on that spot on the game board. At this moment the player changes to either player 2 or the AI (which depends on whether the AI is active or not) and the ability of the cards to be dragged is reversed (player 1 no longer has the ability to move their cards but player 2 or the AI gains the ability to).
The comparison state begins by analyzing the last card played to the board to get and store the values of each cardinal power it possess. Afterwards, by using the location of that card that was played, the function will then evaluate all cards around the last card played. If any of the values from the last card played beat a value of a card around it, then that card will become their if and only if it belonged to their opponent. A card that already belongs to a player will not be evaluated in this situation. The game board updates with the new colors to denote which player owns which cards, and the score in the user interface will update in either corner of the screen.
The AI turn is very similar to the Player Turn state as it will do most of the things that the player state can do, such as disabling dragging for the other player and moving a card to the gameboard from their hand. The difference here lies in the choosing which card to play to which location on the gameboard. This will initially be done using a search algorithm called minmax that is based on the decision to minimize the possible loss for the worst case. In other words, it runs on making the AI get the maximum score by comparing the best and worst case scenarios when selecting a move. Once the AI selects and finishes their move, the game will move back to the Comparison stage and will continue to loop.
The game over state is the simplest state of the game. The only thing it does is evaluate if the game board is filled with all 9 cards and if the game board isn’t filled, then continue to the appropriate player/AI state. When all 9 cards are on the game board this state will act as the base case for the recursion that I have implemented in these states, giving the game a way to stop. When the base case is met, the user interface will flash one of four messages on the screen: Player 1 Wins!, Player 2 Wins!, AI Wins!, Tie!. Then the game will end and the player will get a prompt if they would like to play again.
Where I am Currently and My Plan To Move Forward
I have finished the Player Turn state and have it working to the point that each player can play a card then have to wait for the other to play a card before they can play another one. Currently I am implementing the comparison function inside of the Comparison state, although this process is not logically difficult, it is very difficult to keep track of all of the variables that I have floating around inside of this process. This is a slow process as I have to constantly stop and test every little detail as I go to make sure nothing breaks along the way.
Once the Comparison state is complete I will be moving on to the Game over state to get a working local multiplayer game. With that state complete I will be able to add the user interface elements such as the score boards in the corners of the screen, and the game will be completely playable. Once I have a playable game, then I will have to implement the AI opponent. I hope to have the initial AI implemented by next Saturday, but who knows what complications I could run into at this point.