Editing the Code
The file you need to edit is Blackjack.cs
The main method of interest is:
CalculateMove()
This receives a package of game state information, including the players’ stack sizes, bet size so far this deal, the round of betting and what cards you have and the dealer's face up cards.
From this information, it is your task to decide one of two things depending on round you are in:
1. What bet size you would like to make
2. What action you would like to take
You specify your decisions by calling ClientMoved with the move package - BlackjackMove
In the betting round use the BetSize parameter to specify your bet size.
In the actions round use the Action parameter to specify your action.
For example:
ClientMoved(new BlackjackMove(){ BetSize = 10 });
Or:
ClientMoved(new BlackjackMove(){ Action = BlackjackRequestMoveType.Hit });
Case Study
Let’s say we would like to implement the following strategy:
1. In the betting round our default move is to bet 10 each time.
2. Randomly, 33% of the time we will play a larger bet size between 20 and 100.
3. In the actions round our default move is to hit for another card.
4. If our cards add up to 17 or more we will stand.
5. If they add up to 16 we will double.
We will use the PlayerCards property of the state to determine our hand value.
We will also create a function to help us calculate hand values.
The RangeRand method returns a random number, optionally rounded down to a round number
The code looks like the following:
BlackjackMove move = new BlackjackMove(); if (state.Round == BlackjackDealRound.SetBetsize) //If we are in the betting round //Default bet when no special cases are identified: move.BetSize = 10; //Bet 10 if (RangeRand(0, 2) == 0) // 1/3 of the time, bet move.BetSize = RangeRand(20, 119, 20); // 20,40,60,80 or 100 with equal likeliness else //Otherwise, if we are in the actions round //Default action when no special cases are identified: move.Action = BlackjackRequestMoveType.Hit; //Hit int handValue = 0; foreach (Card c in state.PlayerCards) //For every card in your hand handValue += blackjackValue(c); //Add the value returned from blackjackValue to the total if(handValue >= 17) //If your hand value is greater than or equal to 17 move.Action = BlackjackRequestMoveType.Stand; //Stand if(handValue == 16)//If your hand value is equal to 16 move.Action = BlackjackRequestMoveType.Double; //Double // call server to process our move ClientMoved(move);
Helper Methods
Below are the helper methods you will need for our case study to work
private int blackjackValue(Card card) { int value; if (card.Index == CardIndexType.Ace) //Is our card an A { value = 11; //Then it has value 11 } else if (card.Index < CardIndexType.Ten) //Is our a 2/3/4/5/6/7/8/9 { value = (int)card.Index; //Then it has value equal to its index } else //Is our card a 10/J/Q/K { value = 10; //Then it has value 10 } return value; } private int RangeRand(int min, int max) { return _random.Next(min, max + 1); } private int RangeRand(int min, int max, int roundTo) { int res = _random.Next(min, max + 1); return (res - res % roundTo); }
Note that an Ace can take values 1 or 11, this case is left to you.
State Values
In the calculate move function, prefix the following properties with "state." to access their values.
List<Card> AllCardsSeen; //List of cards seen in current deal int Bet; //How much you have bet so far this deal List<Card> DealerCards; //The list of cards the dealer has in their hand int DealNumber; //Which deal you are on this game int OpponentStack; //Number of chips your opponent has List<Card> PlayerCards; //The list of cards in your hand int PlayerStack; //Number of chips you have List<Card> PreviousDealDealerCards; //The list of cards the dealer had in their hand last deal List<Card> PreviousDealPlayerCards; //The list of cards you had in your hand last deal BlackjackDealResult PreviousDealResult; //How the last game was won/lost int RemainingCards; //The number of cards left in the deck BlackjackDealRound Round; //Whether you are in the betting, action, or showdown round
Advanced
Also you may like to edit the method:
ProcessGameState()
This is called after any move is made by either player. The function displays the state of the game on the client screen, then only if the IsMover flag is set, it calls CalculateMove(). To maximise your efficiency, you may like to do some processing here while your opponent calculates their move. Note there is a Thread.Sleep in this method which pauses the client for a short time so that the user can see the result of the deal. Example:
protected override void ProcessGameState(BlackjackGameState state) { Show the user the current game state Desk.ShowMove(state); Thread.Sleep(ThinkingTime); if (state.IsMover) CalculateMove(state); else ; // Could do some additional processing here while opponent thinks }