{
  "id": "P049",
  "slug": "blackjack",
  "key": "P049-blackjack",
  "title": "Blackjack",
  "summary": "Blackjack against the dealer with one deck and a stack of chips: hit, stand or double, aces counted 1 or 11 with soft totals shown, the dealer drawing to 16 and standing on every 17, a blackjack paying 3 to 2. The deck is shuffled by a Fisher-Yates shuffle on EML's own random numbers, so a seed deals the same cards every time.",
  "entry": "main.eml",
  "ui": "terminal",
  "readme": "# P049 - Blackjack\n\nBlackjack against the dealer, with one deck and a stack of chips. Get closer\nto 21 than the dealer without going over. Number cards count their number,\njacks, queens and kings count 10, and an ace counts 1 or 11, whichever\nhelps. You can hit, stand, or double your bet for one more card.\n\n- `main.eml` - the menu, the bets, playing a hand in the order of a real\n  table, and the chips\n- `cards.eml` - the deck and its shuffle, card names, the value of a hand,\n  and how a hand is settled\n- `rng.eml` - random numbers written in EML, the generator of P008\n\nHow each part works:\n\n- The deck is shuffled by Fisher-Yates from the last position down. The\n  card for each position is picked from that position and every one before\n  it, so every order is equally likely, and a card may stay where it was.\n  The corpus case `the-shuffle-left-one-in-place-as-expected` works out\n  that a uniform shuffle leaves one card in place on average; a shuffle\n  that never did would be less random, not more. A new deck is shuffled\n  before a hand when fewer than 15 cards are left. The random numbers come\n  from EML code, so a seed deals the same cards every time.\n- A hand's value counts every ace as 1, then one ace as 11 when that does\n  not go over 21; the hand is then soft. Only one ace can ever count 11,\n  since two would make 22.\n- The cards are dealt you, dealer, you, dealer, with the dealer's second\n  card face down. A blackjack - an ace and a ten-card as the first two -\n  ends the hand at once: yours alone pays 3 to 2, rounded down; the\n  dealer's alone takes your bet; both is a push.\n- You may double on your first two cards when your chips cover twice the\n  bet: the bet doubles and you get exactly one more card. A hand that\n  reaches 21 stops asking.\n- If you bust, you lose and the dealer does not play. Otherwise the dealer\n  turns over the hidden card and draws to 16, standing on every 17,\n  including a soft 17. There is no splitting and no insurance.\n\nWhat is checked: menu choices 1 to 3; a bet from 1 to your chips; h, s and\nd in a hand, where d is only accepted while doubling is allowed; a new game\nwith 10 to 1000 chips and a seed from 0 to 999999999; no hand without\nchips. An empty answer cancels.\n\nSessions: `sessions/basic.in` plays nine hands of the default game (100\nchips, seed 2026):\n- a soft 13 hit to a soft 19, and a push when the dealer draws to 19;\n- two doubles that lose;\n- a blackjack on a bet of 5, which wins 7 (7.5 rounded down);\n- a 9 hit twice to 20, winning against 18;\n- a double that busts;\n- a double that wins when the dealer busts after drawing twice;\n- a new deck before the eighth hand, with 14 cards left, and a bust;\n- the last 7 chips lost to the dealer's blackjack, and the game is out of\n  chips.\n\n`sessions/bad-input.in` gives:\n- menu choices 0 and x;\n- bets 0, 101 and abc, then an empty one;\n- x in a hand, and d after a hit;\n- d with all 100 chips bet, so doubling is not offered. That hand goes from\n  a soft 17 to a hard 15 and busts, and the game is out of chips;\n- a hand with no chips;\n- a new game with chips 9, 1001 and x, cancelled at each question, and then\n  10 chips with seed 7, where a blackjack on a bet of 10 wins 15.\n\nBuilt on the verified corpus case `the-shuffle-left-one-in-place-as-expected`\n(how often a uniform shuffle leaves an item where it was).\n",
  "modules": [
    {
      "name": "main.eml",
      "eml": "# P049 blackjack: get closer to 21 than the dealer without going over. Aces\n# count 1 or 11, faces 10. The dealer draws to 16 and stands on 17, a\n# blackjack pays 3 to 2, and the deck is shuffled by EML's own random\n# numbers, so a seed deals the same cards every time.\nimport cards\nimport rng\n\ndef trim(s):\n    0 => i\n    len(s) => j\n    while i < j and s[i] == \" \":\n        i + 1 => i\n    while j > i and s[j - 1] == \" \":\n        j - 1 => j\n    return s[i:j]\n\ndef number(s):\n    if s == \"\" or len(s) > 9:\n        return -1\n    0 => n\n    for c in s:\n        if not (c in \"0123456789\"):\n            return -1\n        n * 10 + int(c) => n\n    return n\n\ndef counted(n, word):\n    if n == 1:\n        return \"1 \" + word\n    return str(n) + \" \" + word + \"s\"\n\ndef start(chips, seed):\n    (\"A new game: \" + str(chips) + \" chips, seed \" + str(seed) + \".\") ^0\n    # [chips, the generator, the deck, next card, hands, won, lost, pushed]\n    return [chips, rng.Rng(seed), [], 0, 0, 0, 0, 0]\n\ndef shuffle(game):\n    cards.shuffled(cards.new_deck(), game[1]) => game[2]\n    0 => game[3]\n\ndef draw(game):\n    if game[3] == len(game[2]):\n        # Only a very long hand gets here; the cards on the table are not\n        # taken out of the new deck.\n        \"The deck has run out - a new one is shuffled.\" ^0\n        shuffle(game)\n    game[2][game[3]] => card\n    game[3] + 1 => game[3]\n    return card\n\ndef table(player, dealer, hide):\n    (\"Dealer: \" + cards.shown(dealer, hide)) ^0\n    if not hide:\n        (\"        \" + cards.described(dealer)) ^0\n    (\"You:    \" + cards.shown(player, False) + \" - \" + cards.described(player)) ^0\n\ndef settle(game, won):\n    game[0] + won => game[0]\n    game[4] + 1 => game[4]\n    if won > 0:\n        game[5] + 1 => game[5]\n    elif won < 0:\n        game[6] + 1 => game[6]\n    else:\n        game[7] + 1 => game[7]\n    (\"Chips \" + str(game[0]) + \" after \" + counted(game[4], \"hand\") + \": \" + str(game[5]) + \" won, \" + str(game[6]) + \" lost, \" + str(game[7]) + \" pushed.\") ^0\n    if game[0] == 0:\n        \"You are out of chips - start a new game to play on.\" ^0\n\ndef ask_bet(game):\n    while True:\n        trim(input(\"bet (1 to \" + str(game[0]) + \")> \")) => answer\n        if answer == \"\":\n            return -1\n        number(answer) => n\n        if n >= 1 and n <= game[0]:\n            return n\n        (\"Type a bet from 1 to \" + str(game[0]) + \".\") ^0\n\ndef play_hand(game):\n    if game[0] == 0:\n        \"You have no chips left - start a new game.\" ^0\n        return game\n    if len(game[2]) - game[3] < 15:\n        shuffle(game)\n        \"The deck is shuffled.\" ^0\n    ask_bet(game) => bet\n    if bet == -1:\n        \"Cancelled.\" ^0\n        return game\n    # Dealt in turn, as at a table: you, the dealer, you, the dealer - the\n    # dealer's second card face down.\n    [draw(game)] => player\n    [draw(game)] => dealer\n    player + [draw(game)] => player\n    dealer + [draw(game)] => dealer\n    if cards.blackjack(player) or cards.blackjack(dealer):\n        table(player, dealer, False)\n        cards.natural_result(player, dealer, bet) => won\n        if won == 0:\n            \"Both have blackjack - a push, your bet comes back.\" ^0\n        elif won > 0:\n            (\"Blackjack! You win \" + str(won) + \".\") ^0\n        else:\n            (\"The dealer has blackjack - you lose \" + str(bet) + \".\") ^0\n        settle(game, won)\n        return game\n    table(player, dealer, True)\n    bet => stake\n    True => asking\n    while asking and cards.value(player)[0] < 21:\n        (len(player) == 2 and game[0] >= bet * 2) => can_double\n        if can_double:\n            trim(input(\"h) hit  s) stand  d) double> \")) => action\n        else:\n            trim(input(\"h) hit  s) stand> \")) => action\n        if action == \"h\":\n            draw(game) => card\n            player + [card] => player\n            (\"You draw \" + cards.name(card) + \": \" + cards.shown(player, False) + \" - \" + cards.described(player)) ^0\n        elif action == \"s\":\n            False => asking\n        elif action == \"d\" and can_double:\n            bet * 2 => stake\n            draw(game) => card\n            player + [card] => player\n            (\"You double to \" + str(stake) + \" and draw \" + cards.name(card) + \": \" + cards.shown(player, False) + \" - \" + cards.described(player)) ^0\n            False => asking\n        elif can_double:\n            \"Type h to take a card, s to stay, or d to double your bet for one card.\" ^0\n        else:\n            \"Type h to take a card or s to stay.\" ^0\n    if cards.value(player)[0] > 21:\n        (\"Bust - you lose \" + str(stake) + \".\") ^0\n        settle(game, 0 - stake)\n        return game\n    (\"The dealer turns over \" + cards.name(dealer[1]) + \": \" + cards.shown(dealer, False) + \" - \" + cards.described(dealer)) ^0\n    while not cards.dealer_stands(dealer):\n        draw(game) => card\n        dealer + [card] => dealer\n        (\"The dealer draws \" + cards.name(card) + \": \" + cards.shown(dealer, False) + \" - \" + cards.described(dealer)) ^0\n    cards.result(player, dealer, stake) => won\n    cards.value(player)[0] => p\n    cards.value(dealer)[0] => d\n    if d > 21:\n        (\"The dealer busts - you win \" + str(won) + \".\") ^0\n    elif won > 0:\n        (\"You win \" + str(won) + \", \" + str(p) + \" against \" + str(d) + \".\") ^0\n    elif won < 0:\n        (\"The dealer wins, \" + str(d) + \" against \" + str(p) + \" - you lose \" + str(stake) + \".\") ^0\n    else:\n        (\"A push at \" + str(p) + \" - your bet comes back.\") ^0\n    settle(game, won)\n    return game\n\ndef ask_number(prompt, low, high):\n    while True:\n        trim(input(prompt + \" (\" + str(low) + \" to \" + str(high) + \")> \")) => answer\n        if answer == \"\":\n            return -1\n        number(answer) => n\n        if n >= low and n <= high:\n            return n\n        (\"Type a number from \" + str(low) + \" to \" + str(high) + \".\") ^0\n\ndef new_game(game):\n    ask_number(\"chips\", 10, 1000) => chips\n    if chips == -1:\n        \"Cancelled.\" ^0\n        return game\n    ask_number(\"seed\", 0, 999999999) => seed\n    if seed == -1:\n        \"Cancelled.\" ^0\n        return game\n    return start(chips, seed)\n\n\"== Blackjack ==\" ^0\n\"Get closer to 21 than the dealer without going over. The dealer draws to 16 and stands on 17.\" ^0\nstart(100, 2026) => game\nTrue => running\nwhile running:\n    \"\" ^0\n    \"1) play a hand  2) new game  3) quit\" ^0\n    trim(input(\"choice> \")) => choice\n    if choice == \"1\":\n        play_hand(game) => game\n    elif choice == \"2\":\n        new_game(game) => game\n    elif choice == \"3\":\n        False => running\n    else:\n        \"Pick a number from 1 to 3.\" ^0\n\"Bye.\" ^0\n",
      "python": "import cards\nimport rng\n\ndef trim(s):\n    i = 0\n    j = len(s)\n    while i < j and s[i] == \" \":\n        i = i + 1\n    while j > i and s[j - 1] == \" \":\n        j = j - 1\n    return s[i:j]\n\ndef number(s):\n    if s == \"\" or len(s) > 9:\n        return -1\n    n = 0\n    for c in s:\n        if not c in \"0123456789\":\n            return -1\n        n = n * 10 + int(c)\n    return n\n\ndef counted(n, word):\n    if n == 1:\n        return \"1 \" + word\n    return str(n) + \" \" + word + \"s\"\n\ndef start(chips, seed):\n    print(\"A new game: \" + str(chips) + \" chips, seed \" + str(seed) + \".\")\n    return [chips, rng.Rng(seed), [], 0, 0, 0, 0, 0]\n\ndef shuffle(game):\n    game[2] = cards.shuffled(cards.new_deck(), game[1])\n    game[3] = 0\n\ndef draw(game):\n    if game[3] == len(game[2]):\n        print(\"The deck has run out - a new one is shuffled.\")\n        shuffle(game)\n    card = game[2][game[3]]\n    game[3] = game[3] + 1\n    return card\n\ndef table(player, dealer, hide):\n    print(\"Dealer: \" + cards.shown(dealer, hide))\n    if not hide:\n        print(\"        \" + cards.described(dealer))\n    print(\"You:    \" + cards.shown(player, False) + \" - \" + cards.described(player))\n\ndef settle(game, won):\n    game[0] = game[0] + won\n    game[4] = game[4] + 1\n    if won > 0:\n        game[5] = game[5] + 1\n    elif won < 0:\n        game[6] = game[6] + 1\n    else:\n        game[7] = game[7] + 1\n    print(\"Chips \" + str(game[0]) + \" after \" + counted(game[4], \"hand\") + \": \" + str(game[5]) + \" won, \" + str(game[6]) + \" lost, \" + str(game[7]) + \" pushed.\")\n    if game[0] == 0:\n        print(\"You are out of chips - start a new game to play on.\")\n\ndef ask_bet(game):\n    while True:\n        answer = trim(input(\"bet (1 to \" + str(game[0]) + \")> \"))\n        if answer == \"\":\n            return -1\n        n = number(answer)\n        if n >= 1 and n <= game[0]:\n            return n\n        print(\"Type a bet from 1 to \" + str(game[0]) + \".\")\n\ndef play_hand(game):\n    if game[0] == 0:\n        print(\"You have no chips left - start a new game.\")\n        return game\n    if len(game[2]) - game[3] < 15:\n        shuffle(game)\n        print(\"The deck is shuffled.\")\n    bet = ask_bet(game)\n    if bet == -1:\n        print(\"Cancelled.\")\n        return game\n    player = [draw(game)]\n    dealer = [draw(game)]\n    player = player + [draw(game)]\n    dealer = dealer + [draw(game)]\n    if cards.blackjack(player) or cards.blackjack(dealer):\n        table(player, dealer, False)\n        won = cards.natural_result(player, dealer, bet)\n        if won == 0:\n            print(\"Both have blackjack - a push, your bet comes back.\")\n        elif won > 0:\n            print(\"Blackjack! You win \" + str(won) + \".\")\n        else:\n            print(\"The dealer has blackjack - you lose \" + str(bet) + \".\")\n        settle(game, won)\n        return game\n    table(player, dealer, True)\n    stake = bet\n    asking = True\n    while asking and cards.value(player)[0] < 21:\n        can_double = len(player) == 2 and game[0] >= bet * 2\n        if can_double:\n            action = trim(input(\"h) hit  s) stand  d) double> \"))\n        else:\n            action = trim(input(\"h) hit  s) stand> \"))\n        if action == \"h\":\n            card = draw(game)\n            player = player + [card]\n            print(\"You draw \" + cards.name(card) + \": \" + cards.shown(player, False) + \" - \" + cards.described(player))\n        elif action == \"s\":\n            asking = False\n        elif action == \"d\" and can_double:\n            stake = bet * 2\n            card = draw(game)\n            player = player + [card]\n            print(\"You double to \" + str(stake) + \" and draw \" + cards.name(card) + \": \" + cards.shown(player, False) + \" - \" + cards.described(player))\n            asking = False\n        elif can_double:\n            print(\"Type h to take a card, s to stay, or d to double your bet for one card.\")\n        else:\n            print(\"Type h to take a card or s to stay.\")\n    if cards.value(player)[0] > 21:\n        print(\"Bust - you lose \" + str(stake) + \".\")\n        settle(game, 0 - stake)\n        return game\n    print(\"The dealer turns over \" + cards.name(dealer[1]) + \": \" + cards.shown(dealer, False) + \" - \" + cards.described(dealer))\n    while not cards.dealer_stands(dealer):\n        card = draw(game)\n        dealer = dealer + [card]\n        print(\"The dealer draws \" + cards.name(card) + \": \" + cards.shown(dealer, False) + \" - \" + cards.described(dealer))\n    won = cards.result(player, dealer, stake)\n    p = cards.value(player)[0]\n    d = cards.value(dealer)[0]\n    if d > 21:\n        print(\"The dealer busts - you win \" + str(won) + \".\")\n    elif won > 0:\n        print(\"You win \" + str(won) + \", \" + str(p) + \" against \" + str(d) + \".\")\n    elif won < 0:\n        print(\"The dealer wins, \" + str(d) + \" against \" + str(p) + \" - you lose \" + str(stake) + \".\")\n    else:\n        print(\"A push at \" + str(p) + \" - your bet comes back.\")\n    settle(game, won)\n    return game\n\ndef ask_number(prompt, low, high):\n    while True:\n        answer = trim(input(prompt + \" (\" + str(low) + \" to \" + str(high) + \")> \"))\n        if answer == \"\":\n            return -1\n        n = number(answer)\n        if n >= low and n <= high:\n            return n\n        print(\"Type a number from \" + str(low) + \" to \" + str(high) + \".\")\n\ndef new_game(game):\n    chips = ask_number(\"chips\", 10, 1000)\n    if chips == -1:\n        print(\"Cancelled.\")\n        return game\n    seed = ask_number(\"seed\", 0, 999999999)\n    if seed == -1:\n        print(\"Cancelled.\")\n        return game\n    return start(chips, seed)\n\nprint(\"== Blackjack ==\")\nprint(\"Get closer to 21 than the dealer without going over. The dealer draws to 16 and stands on 17.\")\ngame = start(100, 2026)\nrunning = True\nwhile running:\n    print(\"\")\n    print(\"1) play a hand  2) new game  3) quit\")\n    choice = trim(input(\"choice> \"))\n    if choice == \"1\":\n        game = play_hand(game)\n    elif choice == \"2\":\n        game = new_game(game)\n    elif choice == \"3\":\n        running = False\n    else:\n        print(\"Pick a number from 1 to 3.\")\nprint(\"Bye.\")\n"
    },
    {
      "name": "cards.eml",
      "eml": "# P049 blackjack - cards, the deck and the hands. A card is [rank, suit]:\n# rank 1 (ace) to 13 (king), suit 0 to 3 (spades, hearts, diamonds, clubs).\n\ndef new_deck():\n    [] => deck\n    for s in [0:3]:\n        for r in [1:13]:\n            deck + [[r, s]] => deck\n    return deck\n\ndef shuffled(deck, rng):\n    # Fisher-Yates, from the last position down: the card for position i is\n    # picked from positions 0 to i, so every order is equally likely - and a\n    # card may stay where it was. A uniform shuffle leaves one card in place\n    # on average, as the corpus case the-shuffle-left-one-in-place-as-expected\n    # works out; forbidding that would make the shuffle less random, not more.\n    deck[0:len(deck)] => d\n    len(d) => n\n    for k in [0:n - 2]:\n        n - 1 - k => i\n        rng.below(i + 1) => j\n        d[i] => t\n        d[j] => d[i]\n        t => d[j]\n    return d\n\ndef name(card):\n    str(card[0]) => rank\n    if card[0] == 1:\n        \"A\" => rank\n    elif card[0] == 11:\n        \"J\" => rank\n    elif card[0] == 12:\n        \"Q\" => rank\n    elif card[0] == 13:\n        \"K\" => rank\n    return rank + \"SHDC\"[card[1]]\n\ndef points(card):\n    # An ace is 1 here; value() decides when it counts 11.\n    if card[0] > 10:\n        return 10\n    return card[0]\n\ndef value(hand):\n    # [total, soft]. Aces count 1, and one of them counts 11 when that does\n    # not take the hand over 21 - the hand is then soft. Two aces at 11 would\n    # be 22, so at most one ever counts 11.\n    0 => total\n    False => ace\n    for card in hand:\n        total + points(card) => total\n        if card[0] == 1:\n            True => ace\n    if ace and total + 10 <= 21:\n        return [total + 10, True]\n    return [total, False]\n\ndef blackjack(hand):\n    # 21 with the first two cards: an ace and a ten, jack, queen or king.\n    return len(hand) == 2 and value(hand)[0] == 21\n\ndef shown(hand, hide_second):\n    \"\" => s\n    for k in [0:len(hand) - 1]:\n        if k > 0:\n            s + \" \" => s\n        if k == 1 and hide_second:\n            s + \"??\" => s\n        else:\n            s + name(hand[k]) => s\n    return s\n\ndef described(hand):\n    value(hand) => v\n    if v[0] > 21:\n        return str(v[0]) + \", bust\"\n    if blackjack(hand):\n        return \"blackjack\"\n    if v[1]:\n        return \"soft \" + str(v[0])\n    return str(v[0])\n\ndef dealer_stands(hand):\n    # The dealer draws to 16 and stands on every 17, a soft 17 too.\n    return value(hand)[0] >= 17\n\ndef natural_result(player, dealer, bet):\n    # When either first hand is a blackjack the hand ends at once: both is a\n    # push, the player's alone pays 3 to 2 (rounded down), the dealer's alone\n    # takes the bet. Returns the chips won, negative for a loss.\n    if blackjack(player) and blackjack(dealer):\n        return 0\n    if blackjack(player):\n        return int(bet * 3 / 2)\n    return 0 - bet\n\ndef result(player, dealer, stake):\n    # Both hands finished, neither a blackjack: the chips won, negative for\n    # a loss. A player who busts loses even if the dealer would bust too -\n    # the dealer does not play then.\n    value(player)[0] => p\n    value(dealer)[0] => d\n    if p > 21:\n        return 0 - stake\n    if d > 21 or p > d:\n        return stake\n    if p < d:\n        return 0 - stake\n    return 0\n",
      "python": "def new_deck():\n    deck = []\n    for s in range(0, 4):\n        for r in range(1, 14):\n            deck = deck + [[r, s]]\n    return deck\n\ndef shuffled(deck, rng):\n    d = deck[0:len(deck)]\n    n = len(d)\n    for k in range(0, n - 2+1):\n        i = n - 1 - k\n        j = rng.below(i + 1)\n        t = d[i]\n        d[i] = d[j]\n        d[j] = t\n    return d\n\ndef name(card):\n    rank = str(card[0])\n    if card[0] == 1:\n        rank = \"A\"\n    elif card[0] == 11:\n        rank = \"J\"\n    elif card[0] == 12:\n        rank = \"Q\"\n    elif card[0] == 13:\n        rank = \"K\"\n    return rank + \"SHDC\"[card[1]]\n\ndef points(card):\n    if card[0] > 10:\n        return 10\n    return card[0]\n\ndef value(hand):\n    total = 0\n    ace = False\n    for card in hand:\n        total = total + points(card)\n        if card[0] == 1:\n            ace = True\n    if ace and total + 10 <= 21:\n        return [total + 10, True]\n    return [total, False]\n\ndef blackjack(hand):\n    return len(hand) == 2 and value(hand)[0] == 21\n\ndef shown(hand, hide_second):\n    s = \"\"\n    for k in range(0, len(hand)):\n        if k > 0:\n            s = s + \" \"\n        if k == 1 and hide_second:\n            s = s + \"??\"\n        else:\n            s = s + name(hand[k])\n    return s\n\ndef described(hand):\n    v = value(hand)\n    if v[0] > 21:\n        return str(v[0]) + \", bust\"\n    if blackjack(hand):\n        return \"blackjack\"\n    if v[1]:\n        return \"soft \" + str(v[0])\n    return str(v[0])\n\ndef dealer_stands(hand):\n    return value(hand)[0] >= 17\n\ndef natural_result(player, dealer, bet):\n    if blackjack(player) and blackjack(dealer):\n        return 0\n    if blackjack(player):\n        return int(bet * 3 / 2)\n    return 0 - bet\n\ndef result(player, dealer, stake):\n    p = value(player)[0]\n    d = value(dealer)[0]\n    if p > 21:\n        return 0 - stake\n    if d > 21 or p > d:\n        return stake\n    if p < d:\n        return 0 - stake\n    return 0\n"
    },
    {
      "name": "rng.eml",
      "eml": "# P049 blackjack - random numbers written in EML: the linear congruential\n# generator of P008 (number guessing), with the constants of the C\n# standard's example rand(). Python's random module is not used, so a seed\n# gives the same shuffle on every machine, and the interpreter can check a\n# whole session byte for byte.\n\nclass Rng:\n    def __init__(self, seed):\n        seed % 2147483648 => self.state\n\n    def step(self):\n        (1103515245 * self.state + 12345) % 2147483648 => self.state\n        return self.state\n\n    def below(self, n):\n        # A number from 0 to n - 1, taken from the high bits of the state: the\n        # low bits of this generator repeat with short periods. Dividing by\n        # 65536 is exact in a float for a state below 2^31.\n        return int(self.step() / 65536) % n\n",
      "python": "class Rng:\n    def __init__(self, seed):\n        self.state = seed % 2147483648\n    def step(self):\n        self.state = (1103515245 * self.state + 12345) % 2147483648\n        return self.state\n    def below(self, n):\n        return int(self.step() / 65536) % n\n"
    }
  ],
  "sessions": [
    {
      "name": "bad-input",
      "input": "0\nx\n1\n0\n101\nabc\n\n1\n10\nx\nh\nd\ns\n1\n100\nd\nh\nh\nh\n1\n2\n9\n1001\nx\n\n2\n10\n\n2\n10\n7\n1\n10\n3\n",
      "screen": "== Blackjack ==\nGet closer to 21 than the dealer without going over. The dealer draws to 16 and stands on 17.\nA new game: 100 chips, seed 2026.\n\n1) play a hand  2) new game  3) quit\nchoice> 0\nPick a number from 1 to 3.\n\n1) play a hand  2) new game  3) quit\nchoice> x\nPick a number from 1 to 3.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nThe deck is shuffled.\nbet (1 to 100)> 0\nType a bet from 1 to 100.\nbet (1 to 100)> 101\nType a bet from 1 to 100.\nbet (1 to 100)> abc\nType a bet from 1 to 100.\nbet (1 to 100)> \nCancelled.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nbet (1 to 100)> 10\nDealer: 6D ??\nYou:    2C AH - soft 13\nh) hit  s) stand  d) double> x\nType h to take a card, s to stay, or d to double your bet for one card.\nh) hit  s) stand  d) double> h\nYou draw 6H: 2C AH 6H - soft 19\nh) hit  s) stand> d\nType h to take a card or s to stay.\nh) hit  s) stand> s\nThe dealer turns over KS: 6D KS - 16\nThe dealer draws 3H: 6D KS 3H - 19\nA push at 19 - your bet comes back.\nChips 100 after 1 hand: 0 won, 0 lost, 1 pushed.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nbet (1 to 100)> 100\nDealer: 9H ??\nYou:    AC 2D - soft 13\nh) hit  s) stand> d\nType h to take a card or s to stay.\nh) hit  s) stand> h\nYou draw 4H: AC 2D 4H - soft 17\nh) hit  s) stand> h\nYou draw 8D: AC 2D 4H 8D - 15\nh) hit  s) stand> h\nYou draw 10H: AC 2D 4H 8D 10H - 25, bust\nBust - you lose 100.\nChips 0 after 2 hands: 0 won, 1 lost, 1 pushed.\nYou are out of chips - start a new game to play on.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nYou have no chips left - start a new game.\n\n1) play a hand  2) new game  3) quit\nchoice> 2\nchips (10 to 1000)> 9\nType a number from 10 to 1000.\nchips (10 to 1000)> 1001\nType a number from 10 to 1000.\nchips (10 to 1000)> x\nType a number from 10 to 1000.\nchips (10 to 1000)> \nCancelled.\n\n1) play a hand  2) new game  3) quit\nchoice> 2\nchips (10 to 1000)> 10\nseed (0 to 999999999)> \nCancelled.\n\n1) play a hand  2) new game  3) quit\nchoice> 2\nchips (10 to 1000)> 10\nseed (0 to 999999999)> 7\nA new game: 10 chips, seed 7.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nThe deck is shuffled.\nbet (1 to 10)> 10\nDealer: 4C 6S\n        10\nYou:    AH QS - blackjack\nBlackjack! You win 15.\nChips 25 after 1 hand: 1 won, 0 lost, 0 pushed.\n\n1) play a hand  2) new game  3) quit\nchoice> 3\nBye.\n",
      "interpreter": "equal"
    },
    {
      "name": "basic",
      "input": "1\n25\nh\ns\n1\n15\nd\n1\n20\nd\n1\n5\n1\n10\nh\nh\ns\n1\n15\nd\n1\n5\nd\n1\n20\nh\nh\n1\n7\n3\n",
      "screen": "== Blackjack ==\nGet closer to 21 than the dealer without going over. The dealer draws to 16 and stands on 17.\nA new game: 100 chips, seed 2026.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nThe deck is shuffled.\nbet (1 to 100)> 25\nDealer: 6D ??\nYou:    2C AH - soft 13\nh) hit  s) stand  d) double> h\nYou draw 6H: 2C AH 6H - soft 19\nh) hit  s) stand> s\nThe dealer turns over KS: 6D KS - 16\nThe dealer draws 3H: 6D KS 3H - 19\nA push at 19 - your bet comes back.\nChips 100 after 1 hand: 0 won, 0 lost, 1 pushed.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nbet (1 to 100)> 15\nDealer: 9H ??\nYou:    AC 2D - soft 13\nh) hit  s) stand  d) double> d\nYou double to 30 and draw 4H: AC 2D 4H - soft 17\nThe dealer turns over 10D: 9H 10D - 19\nThe dealer wins, 19 against 17 - you lose 30.\nChips 70 after 2 hands: 0 won, 1 lost, 1 pushed.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nbet (1 to 70)> 20\nDealer: 10H ??\nYou:    8D 3C - 11\nh) hit  s) stand  d) double> d\nYou double to 40 and draw 5S: 8D 3C 5S - 16\nThe dealer turns over 9D: 10H 9D - 19\nThe dealer wins, 19 against 16 - you lose 40.\nChips 30 after 3 hands: 0 won, 2 lost, 1 pushed.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nbet (1 to 30)> 5\nDealer: 8H KC\n        18\nYou:    QS AD - blackjack\nBlackjack! You win 7.\nChips 37 after 4 hands: 1 won, 2 lost, 1 pushed.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nbet (1 to 37)> 10\nDealer: 10C ??\nYou:    5C 4S - 9\nh) hit  s) stand  d) double> h\nYou draw 4C: 5C 4S 4C - 13\nh) hit  s) stand> h\nYou draw 7H: 5C 4S 4C 7H - 20\nh) hit  s) stand> s\nThe dealer turns over 8C: 10C 8C - 18\nYou win 10, 20 against 18.\nChips 47 after 5 hands: 2 won, 2 lost, 1 pushed.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nbet (1 to 47)> 15\nDealer: 4D ??\nYou:    8S 7S - 15\nh) hit  s) stand  d) double> d\nYou double to 30 and draw JS: 8S 7S JS - 25, bust\nBust - you lose 30.\nChips 17 after 6 hands: 2 won, 3 lost, 1 pushed.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nbet (1 to 17)> 5\nDealer: JH ??\nYou:    5H 5D - 10\nh) hit  s) stand  d) double> d\nYou double to 10 and draw 3S: 5H 5D 3S - 13\nThe dealer turns over 2H: JH 2H - 12\nThe dealer draws 2S: JH 2H 2S - 14\nThe dealer draws KD: JH 2H 2S KD - 24, bust\nThe dealer busts - you win 10.\nChips 27 after 7 hands: 3 won, 3 lost, 1 pushed.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nThe deck is shuffled.\nbet (1 to 27)> 20\nDealer: JC ??\nYou:    7D 5S - 12\nh) hit  s) stand> h\nYou draw 4D: 7D 5S 4D - 16\nh) hit  s) stand> h\nYou draw 8S: 7D 5S 4D 8S - 24, bust\nBust - you lose 20.\nChips 7 after 8 hands: 3 won, 4 lost, 1 pushed.\n\n1) play a hand  2) new game  3) quit\nchoice> 1\nbet (1 to 7)> 7\nDealer: AS JH\n        blackjack\nYou:    10D 2S - 12\nThe dealer has blackjack - you lose 7.\nChips 0 after 9 hands: 3 won, 5 lost, 1 pushed.\nYou are out of chips - start a new game to play on.\n\n1) play a hand  2) new game  3) quit\nchoice> 3\nBye.\n",
      "interpreter": "equal"
    }
  ],
  "builtOn": [
    {
      "slug": "the-shuffle-left-one-in-place-as-expected",
      "caseId": "880-the-shuffle-left-one-in-place-as-expected",
      "title": "The shuffle left one in place as expected"
    }
  ],
  "updated": "2026-10-10"
}
