Let's play Blackjack!
Overview
- Blackjack rules
- Game demo
- Java bot client
- PHP server
Don't play Blackjack in real life - you will most certainly lose.
Demo time!
Source code
Basics
- Players get dealt 2 face up cards each
- Dealer gets dealt 2 cards, but only one is face up
- Get closer to 21 than the dealer
- Over 21? Sorry, you lose.
Basics
- Hit me - get another card
- Stand - next player gets to play
- Split - split a pair or two cards of the same value (except aces)
- Double down - double your bet, but receive only 1 more card
Example






Blackjack!
Not
Example


Split




bet $20
bet $20
bet $20
Example

Double down



bet $20
bet $40

Make your own bot!
public interface BotInterface {
/**
* Bet at the start of the hand.
*
* @param minimum Minimum allowed bet. If you bet less than this, your bet will
* be ignored.
* @param maximum Maximum allowed bet. If you bet more than this, your bet will
* be ignored.
* @param money Available bot funds.
* @return
*/
int bet(int minimum, int maximum, int money);public interface BotInterface {
/**
* Analyze the current hand and dealer's face up card, and return an Action.
* If you return an invalid action, it will count as standing.
*
* @param money Available bot funds.
* @param hand Bot hand.
* @param dealerFaceUpCard Dealer's face up card.
* @return
*/
Action play(int money, Hand hand, Card dealerFaceUpCard);package me.nemanjamiljkovic.blackjack.Bot;
public enum Action {
STAND,
HIT,
SPLIT,
DOUBLE_DOWN
}
@Override
public Action play(int money, Hand hand, Card dealerFaceUpCard) {
// Double down and hope for a 10...
if (hand.getValue() >= 9 && hand.getValue() <= 11) {
return Action.DOUBLE_DOWN;
}
// Split hands if the pairs are 4+
if (hand.canSplit() && hand.getValue() > 8) {
return Action.SPLIT;
}
// Hit if less than 16
if (hand.getValue() < 16) {
return Action.HIT;
}
return Action.STAND;
}try this http://bit.ly/1jyhxNv
public class Card {
public static final int RANK_ACE = 1;
public static final int RANK_JACK = 12;
public static final int RANK_QUEEN = 13;
public static final int RANK_KING = 14;
public enum Suit {
HEARTS, CLUBS, SPADES, DIAMONDS
}
public int getRank() { ... }
public Suit getSuit() { ... }
public int getValue() { ... }
}
public class Hand {
public List<Card> getCards() { ... }
public boolean canSplit() { ... }
public boolean isBlackjack() { ... }
public boolean is21() { ... }
public int getValue() { ... }
}Running the bot
package me.nemanjamiljkovic.blackjack;
import java.net.Socket;
import me.nemanjamiljkovic.blackjack.Bot.Communicator;
import me.nemanjamiljkovic.blackjack.Bot.SimpleBot;
public class Main {
public static void main(String[] args) {
try {
Socket socket = new Socket("blackjack.nemanjamiljkovic.me", 8000);
Communicator.createAndRun(socket, new SimpleBot());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Bot competition
Send your bots to
nemanja.miljkovic@devana.rs
before 1. Nov 2015.
All programming languages allowed.
Under the hood
PHP
Java Bot
Browser
Browser
Browser
Java Bot
Java Bot
Communication
{
"alias": "request_bet",
"data": {
"minimumBet": 50,
"maximumBet": 150,
"money": 5000
}
}Communication
{
"data": {
"money": 4692,
"playerHand": {
"cards": [{
"rank": 7,
"suit": "H"
}, {
"rank": 3,
"suit": "S"
}],
"canSplitHand": false,
"value": 10
},
"dealerCard": {
"rank": 2,
"suit": "S"
}
},
"alias": "request_action"
}Java and JSON
JSONObject message = new JSONObject(stringMessage);
String alias = message.getString("alias");
JSONObject data = message.getJSONObject("data");
int minimum = data.getInt("minimumBet");
int maximum = data.getInt("maximumBet");
int money = data.getInt("money");{
"alias": "request_bet",
"data": {
"minimumBet": 50,
"maximumBet": 150,
"money": 5000
}
}Java and JSON
JSONObject response = new JSONObject();
JSONObject data = new JSONObject();
data.put("amount", 67);
response.put("alias", "bet");
response.put("data", data);
response.toString(); // {"data":{"amount":67},"alias":"bet"}{
"data": {
"amount": 67
},
"alias": "bet"
}The loop
while (socket.isConnected()) {
String stringMessage = in.readLine();
if (stringMessage == null) {
return;
}
try {
JSONObject message = new JSONObject(stringMessage);
this.parseMessage(message);
} catch (JSONException exception) {
continue;
}
}
{
"alias": "request_bet",
"data": {
"minimumBet": 50,
"maximumBet": 150,
"money": 5000
}
}PHP to Java
Java to PHP
{
"data": {
"amount": 67
},
"alias": "bet"
}Betting
phase
Java Bot
Java Bot
Java Bot
Allow 3 seconds to respond
What if
someone responds after 3 seconds?
someone sends an invalid message?
ignore the message
kick the bot
someone doesn't respond or message is ignored?
skip the round
in competition mode, kick the bot
Playing phase
phase
Java Bot
Java Bot
Java Bot
Serially communicate with bots
i.e. finish with bot 1 before communicating with bot 2
What if
someone responds after 3 seconds?
someone sends an invalid message?
ignore the message
kick the bot
someone doesn't respond or message is ignored?
count as Action.STAND
PHP Server
- Up and running for non-stop
- Accepts socket and websocket connections
- Runs game logic and notifies observers of any game changes in real time
PHP Server
- Uses ReactPHP
http://reactphp.org/ - Powered by Ratchet WebSockets
http://socketo.me/ - Delays accomplised by Promise Timer
https://github.com/reactphp/promise-timer
public function startNewHand()
{
if (!$this->running) {
return;
}
$this->resetTable()
->then(function () {
return $this->requestBets();
})
->then(function () {
return $this->dealInitialCards();
})
->then(function () {
return $this->playHand();
})
->then(function () {
return $this->playDealerHand();
})
->then(function () {
return $this->distributeWinnings();
})
->always(function () {
return \Blackjack\Promise\timedResolve(self::LONGEST_PAUSE_SPEED)
->then(function () {
$this->startNewHand();
});
});
}Single threaded event loop
Multiple threads
Single thread
Q&A
Send your bots or questions to
nemanja.miljkovic@devana.rs
Thanks!
Let's play Blackjack!
By binary
Let's play Blackjack!
- 330