{"_id":"@arcanahq/cardgames","_rev":"2-8340189ddd81cab491d627e99ee5c3d1","name":"@arcanahq/cardgames","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@arcanahq/cardgames","version":"1.0.0","keywords":["contract","engine","assemblyscript","wasm","cardgames","blackjack","poker","utility","library"],"author":"","license":"MIT","_id":"@arcanahq/cardgames@1.0.0","maintainers":[{"name":"tapone","email":"johnny@empyrealsdk.com"}],"dist":{"shasum":"0a62ac868e93ba7505a667e5e1ebc3e9aa973d84","tarball":"https://registry.npmjs.org/@arcanahq/cardgames/-/cardgames-1.0.0.tgz","fileCount":48,"integrity":"sha512-CcEH4v6iJfFpQ0KxpfARvj32ruRXIV5CVsL1uDticIhVhusyW4IsaIJsE6O2Cj3ZK6qV7P/XB061/ap9PrYOPQ==","signatures":[{"sig":"MEUCIDAo/UBLAVJ1e1G88g84qgMAJwpdS7icstlxiSB41xFPAiEAwlmtxfJefH/bHJRK7cpQ9qeGtXX4/zZ+eXCvciy60lE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":329471},"main":"src/index.ts","type":"module","types":"src/index.ts","exports":{".":"./src/index.ts","./assembly/deck":"./assembly/deck/index.ts","./assembly/cards":"./assembly/cards.ts","./assembly/index":"./assembly/index.ts","./assembly/poker":"./assembly/poker.ts","./assembly/cardgames":"./assembly/cardgames.ts","./assembly/poker/game":"./assembly/poker/index.ts","./assembly/blackjack/rules":"./assembly/blackjack/rules.ts","./assembly/blackjack/actions":"./assembly/blackjack/actions.ts","./assembly/blackjack/blackjack":"./assembly/blackjack/blackjack.ts"},"gitHead":"c9e8a602e25807fbcc843c2419f89a89a93bdc25","scripts":{"test":"npx cross-env NODE_OPTIONS='--import tsx' npx as-test --config ./as-test.config.js --testFiles assembly/__tests__/test.ts","build":"asc assembly/index.ts --target release --exportRuntime --disableWarning AS235"},"_npmUser":{"name":"tapone","email":"johnny@empyrealsdk.com"},"_npmVersion":"11.6.2","description":"Utility library for card game logic, blackjack actions, and poker game utilities","directories":{},"_nodeVersion":"25.2.1","dependencies":{"@arcanahq/core":"file:../core"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.7.0","cross-env":"^7.0.3","typescript":"^5.3.3","assemblyscript":"^0.27.0","@assemblyscript/loader":"^0.28.9","assemblyscript-unittest-framework":"^2.1.0"},"_npmOperationalInternal":{"tmp":"tmp/cardgames_1.0.0_1782368361869_0.6619581974781665","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@arcanahq/cardgames","version":"1.0.1","description":"Utility library for card game logic, blackjack actions, and poker game utilities","type":"module","publishConfig":{"access":"public"},"main":"src/index.ts","types":"src/index.ts","exports":{".":"./src/index.ts","./assembly/index":"./assembly/index.ts","./assembly/blackjack/actions":"./assembly/blackjack/actions.ts","./assembly/blackjack/rules":"./assembly/blackjack/rules.ts","./assembly/blackjack/blackjack":"./assembly/blackjack/blackjack.ts","./assembly/cardgames":"./assembly/cardgames.ts","./assembly/cards":"./assembly/cards.ts","./assembly/poker":"./assembly/poker.ts","./assembly/deck":"./assembly/deck/index.ts","./assembly/poker/game":"./assembly/poker/index.ts"},"scripts":{"build":"asc assembly/index.ts --target release --exportRuntime --disableWarning AS235","test":"npx cross-env NODE_OPTIONS='--import tsx' npx as-test --config ./as-test.config.js --testFiles assembly/__tests__/test.ts"},"keywords":["contract","engine","assemblyscript","wasm","cardgames","blackjack","poker","utility","library"],"author":"","license":"MIT","devDependencies":{"@assemblyscript/loader":"^0.28.9","assemblyscript":"^0.27.0","assemblyscript-unittest-framework":"^2.1.0","cross-env":"^7.0.3","tsx":"^4.7.0","typescript":"^5.3.3"},"dependencies":{"@arcanahq/core":"file:../core"},"gitHead":"d6717a1f77ea48b9ac16d75b57d6e727f6b8dd21","_id":"@arcanahq/cardgames@1.0.1","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-6jmd3uZRNrrp0szs1+m9RMTu9qOnWWet2yiekRG4TgCkz7j8I37docMJu4uNJU1tDjITog6NYDtZRxAN2j1SZA==","shasum":"794222b26f51ed6cc42dc7f35122cc9dd0b7b098","tarball":"https://registry.npmjs.org/@arcanahq/cardgames/-/cardgames-1.0.1.tgz","fileCount":58,"unpackedSize":3481031,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIC2x38ZmZ/loQZ+vz7FwBgunYR9MN59Rx5HUdjIwBufCAiBbiyoHd0VJcwhC+ZmlyvClGXN4JKtepDNCY4hvc44IRQ=="}]},"_npmUser":{"name":"tapone","email":"johnny@empyrealsdk.com"},"directories":{},"maintainers":[{"name":"tapone","email":"johnny@empyrealsdk.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cardgames_1.0.1_1782369165461_0.9101601275212554"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-25T06:19:21.761Z","modified":"2026-06-25T06:32:45.780Z","1.0.0":"2026-06-25T06:19:22.024Z","1.0.1":"2026-06-25T06:32:45.653Z"},"license":"MIT","keywords":["contract","engine","assemblyscript","wasm","cardgames","blackjack","poker","utility","library"],"description":"Utility library for card game logic, blackjack actions, and poker game utilities","maintainers":[{"name":"tapone","email":"johnny@empyrealsdk.com"}],"readme":"# @arcanahq/cardgames\n\nCard game utilities and blackjack action processing library for Arcana contracts.\n\n## Overview\n\nThis library provides reusable card game logic that can be shared across different card game implementations. It builds on top of `@arcanahq/core` and provides:\n\n- **Deck Management**: Deterministic shuffling and dealing for both standard (52-card) and Spanish 21 (48-card) decks\n- **Card Index Mapping**: Efficient index-based card representation (0-51 for standard, 0-47 for Spanish 21)\n- **Blackjack Rules Configuration**: Configurable rules for different blackjack variants (standard, Spanish 21, etc.)\n- **Blackjack Action Processing**: Utility functions for validating and processing blackjack actions\n- **Poker Game Utilities**: Hand evaluation, pot management, blinds/antes posting, betting rounds, rake calculation\n- **Cash Game Utilities**: Buy-in validation, rake calculation, rebuy management\n\n## Installation\n\n```bash\nnpm install @arcanahq/cardgames\n```\n\nOr use as a local dependency:\n```json\n{\n  \"dependencies\": {\n    \"@arcanahq/cardgames\": \"file:../packages/cardgames\"\n  }\n}\n```\n\n## Structure\n\n```\n@cardgames/\n├── assembly/\n│   ├── blackjack/\n│   │   ├── rules.ts      # Blackjack rules configuration\n│   │   └── actions.ts    # Blackjack action processing utilities\n│   ├── deck/\n│   │   ├── deck.ts       # Deck management (shuffling, dealing, index mapping)\n│   │   └── index.ts      # Deck module exports\n│   ├── cards.ts          # Card, Suit, Rank classes\n│   ├── cardgames.ts      # Card game utilities (deck creation, shuffling, dealing)\n│   └── index.ts          # Main entry point\n└── package.json\n```\n\n## Usage\n\n### Deck Management\n\n#### Single Deck (52 cards)\n\n```typescript\nimport { DeckConfig, dealCardByIndex, createShuffledDeck } from \"@arcanahq/cardgames/assembly/deck\";\n\nconst config = DeckConfig.standard();\n\n// Deal a card deterministically\nconst card = dealCardByIndex(\"shuffle-id\", \"shuffle-salt\", 0, config);\n\n// Create full shuffled deck\nconst deck = createShuffledDeck(\"shuffle-id\", \"shuffle-salt\", 0, config);\n```\n\n#### Spanish 21 Deck (48 cards, no 10s)\n\n```typescript\nconst config = DeckConfig.spanish21();\n\n// Deal a card from Spanish 21 deck\nconst card = dealCardByIndex(\"shuffle-id\", \"shuffle-salt\", 0, config);\n// card will never be a 10\n\n// Create full shuffled Spanish 21 deck\nconst deck = createShuffledDeck(\"shuffle-id\", \"shuffle-salt\", 0, config);\n```\n\n#### Multi-Deck Shoes\n\n```typescript\nimport { ShoeConfig, dealCardFromShoe, DeckConfig } from \"@arcanahq/cardgames/assembly/deck\";\n\n// Standard shoe with any number of decks\nconst shoe6 = ShoeConfig.standard(6);  // 6-deck shoe (312 cards)\nconst shoe8 = ShoeConfig.standard(8);  // 8-deck shoe (416 cards)\nconst shoeCustom = ShoeConfig.standard(10); // 10-deck shoe (520 cards)\n\n// Spanish 21 shoe with any number of decks\nconst spanishShoe6 = ShoeConfig.spanish21(6);  // 6-deck Spanish 21 (288 cards)\nconst spanishShoe8 = ShoeConfig.spanish21(8);  // 8-deck Spanish 21 (384 cards)\n\n// Create shoe with any custom deck configuration\nconst spanishDeck = DeckConfig.spanish21();\nconst customShoe = ShoeConfig.withDeck(spanishDeck, 6); // 6-deck Spanish 21\n\n// Or with a custom deck config\n// Use standard or Spanish 21, or create your own DeckConfig subclass\nconst customDeck = DeckConfig.standard(); // or DeckConfig.spanish21()\nconst shoe = ShoeConfig.withDeck(customDeck, 4); // 4-deck shoe\n\n// Deal cards from shoe (tracks position, auto-reshuffles when exhausted)\nlet shoePosition = 0;\nconst card1 = dealCardFromShoe(\"shuffle-id\", \"shuffle-salt\", shoePosition++, shoe6);\nconst card2 = dealCardFromShoe(\"shuffle-id\", \"shuffle-salt\", shoePosition++, shoe6);\n// Position persists across game sessions\n```\n\n#### Card Index Mapping\n\n```typescript\nimport { CardIndexMapper } from \"@arcanahq/cardgames/assembly/deck\";\n\nconst config = DeckConfig.standard();\n\n// Convert index to card\nconst card = CardIndexMapper.indexToCard(0, config); // 2 of Spades\nconst card2 = CardIndexMapper.indexToCard(51, config); // Ace of Clubs\n\n// Convert card to index\nconst index = CardIndexMapper.cardToIndex(card, config); // 0\n\n// Create unshuffled deck indices\nconst indices = CardIndexMapper.createUnshuffledDeckIndices(config);\n// [0, 1, 2, ..., 51]\n```\n\n#### Deterministic Shuffling\n\n```typescript\nimport { deterministicShuffleIndices, CardIndexMapper } from \"@arcanahq/cardgames/assembly/deck\";\n\nconst config = DeckConfig.standard();\nconst unshuffledIndices = CardIndexMapper.createUnshuffledDeckIndices(config);\n\n// Shuffle deterministically\nconst shuffledIndices = deterministicShuffleIndices(\n  unshuffledIndices,\n  \"shuffle-id\",\n  \"shuffle-salt\",\n  0 // seedIndex\n);\n\n// Same parameters = same shuffle\nconst shuffled2 = deterministicShuffleIndices(\n  unshuffledIndices,\n  \"shuffle-id\",\n  \"shuffle-salt\",\n  0\n);\n// shuffledIndices === shuffled2\n```\n\n### Blackjack Rules\n\n#### Standard Rules\n\n```typescript\nimport { BlackjackRules } from \"@arcanahq/cardgames/assembly/blackjack/rules\";\n\n// Use standard rules (most common casino rules)\nconst rules = BlackjackRules.standard();\n// - Dealer stands on 17\n// - No hit on soft 17\n// - No double after split\n// - Surrender allowed\n// - Insurance offered\n```\n\n#### Spanish 21 Rules\n\n```typescript\nconst rules = BlackjackRules.spanish21();\n// - 48-card deck (no 10s)\n// - Dealer hits on soft 17\n// - Double after split allowed\n// - No insurance\n```\n\n#### Custom Rules\n\n```typescript\nconst rules = new BlackjackRules(\n  17,        // dealerStandValue\n  false,     // hitOnSoft17\n  4,         // maxSplitHands\n  false,     // doubleAfterSplit\n  true,      // surrenderAllowed\n  false,     // lateSurrender\n  true,      // insuranceOffered\n  false      // isSpanish21\n);\n\n// Or use factory methods\nconst rules = BlackjackRules.dealerHitsSoft17();\nconst rules = BlackjackRules.allowDoubleAfterSplit();\n```\n\n#### Custom Payouts\n\n```typescript\nconst rules = new BlackjackRules(\n  17, false, 4, false, true, false, true, false,\n  2.0,  // payoutBlackjack (6:5 instead of 3:2)\n  1.0,  // payoutWin\n  1.0,  // payoutPush\n  0.0,  // payoutLose\n  0.5,  // payoutSurrender\n  2.0   // payoutInsurance\n);\n```\n\n### Blackjack Action Validation\n\n#### Calculate Available Actions\n\n```typescript\nimport { calculateAvailableActions } from \"@arcanahq/cardgames/assembly/blackjack/actions\";\n\nconst actions = calculateAvailableActions(\n  hand.cards.length,      // handCardsLength\n  hand.isFromSplit,       // handIsFromSplit\n  hand.isSplitAces,       // handIsSplitAces\n  hand.isStanding,        // handIsStanding\n  hand.isBusted,          // handIsBusted\n  state.gamePhase,        // gamePhase\n  state.playerHands.length, // playerHandsCount\n  canSplitCards(hand.cards), // canSplit (pre-calculated)\n  rules\n);\n\n// Use actions\nif (actions.canStand) { /* ... */ }\nif (actions.canDouble) { /* ... */ }\nif (actions.canSplit) { /* ... */ }\nif (actions.canSurrender) { /* ... */ }\n```\n\n#### Validate Actions\n\n```typescript\nimport {\n  validateCanDouble,\n  validateCanSplit,\n  validateCanSurrender,\n  validateCanHit,\n  validateCanStand,\n  validateActionPhase,\n  validateActiveHand\n} from \"@arcanahq/cardgames/assembly/blackjack/actions\";\n\n// Validate double action\nvalidateCanDouble(\n  hand.cards.length,\n  hand.isSplitAces,\n  hand.isFromSplit,\n  rules\n);\n\n// Validate split action\nvalidateCanSplit(\n  hand.cards.length,\n  state.playerHands.length,\n  canSplitCards(hand.cards),\n  rules\n);\n\n// Validate surrender action\nvalidateCanSurrender(\n  hand.cards.length,\n  hand.isFromSplit,\n  rules\n);\n\n// Validate hit action\nvalidateCanHit(\n  hand.isStanding,\n  hand.isBusted,\n  hand.isSplitAces\n);\n\n// Validate stand action\nvalidateCanStand(\n  hand.isStanding,\n  hand.isBusted\n);\n\n// Validate game phase\nvalidateActionPhase(state.gamePhase, \"HIT\", \"PLAYING\");\n\n// Validate active hand\nvalidateActiveHand(currentHandIndex, state.playerHands.length);\n```\n\n### Dealer Logic\n\n```typescript\nimport { shouldDealerHit, shouldOfferInsurance } from \"@arcanahq/cardgames/assembly/blackjack/actions\";\n\n// Check if dealer should hit\nconst dealerShouldHit = shouldDealerHit(\n  dealerHandValue,\n  rules.dealerStandValue,\n  rules.hitOnSoft17,\n  isSoftHand(dealerCards)\n);\n\n// Check if insurance should be offered\nconst offerInsurance = shouldOfferInsurance(\n  dealerUpCard.rank,\n  rules\n);\n```\n\n### Card Types\n\n```typescript\nimport { Card, Suit, Rank } from \"@arcanahq/cardgames/assembly/cards\";\n\n// Create a card\nconst card = new Card(Suit.HEARTS, Rank.ACE);\n\n// Use suit and rank constants\nconst suits = Suit.ALL; // [♠, ♥, ♦, ♣]\nconst ranks = Rank.ALL; // [2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A]\n```\n\n### Card Game Utilities\n\n```typescript\nimport {\n  createStandardDeck,\n  shuffleDeck,\n  dealCard,\n  dealCards,\n  cardToInt,\n  intToCard\n} from \"@arcanahq/cardgames/assembly/cardgames\";\n\n// Create a standard 52-card deck\nconst deck = createStandardDeck();\n\n// Shuffle with deterministic randomness\nconst shuffled = shuffleDeck(deck, seed);\n\n// Deal cards\nconst card = dealCard(deck);\nconst cards = dealCards(deck, 5);\n\n// Convert between Card and integer (0-51)\nconst index = cardToInt(card);\nconst card2 = intToCard(index);\n```\n\n### Core Blackjack Functions\n\n```typescript\nimport {\n  dealerShouldHit,\n  isSoftHand,\n  calculateBlackjackHandValue,\n  isBlackjack,\n  isBusted,\n  canSplitCards\n} from \"@arcanahq/cardgames/assembly/blackjack/rules\";\n\n// Calculate hand value\nconst value = calculateBlackjackHandValue(cards);\n\n// Check for blackjack\nconst hasBlackjack = isBlackjack(cards);\n\n// Check for bust\nconst isBusted = isBusted(cards);\n\n// Check if cards can be split\nconst canSplit = canSplitCards(cards);\n\n// Check if hand is soft\nconst isSoft = isSoftHand(cards);\n\n// Check if dealer should hit\nconst shouldHit = dealerShouldHit(cards, rules);\n```\n\n## Extensibility\n\n### Creating Custom Rule Variants\n\n```typescript\n// Example: European Blackjack (no hole card)\nclass EuropeanBlackjackRules extends BlackjackRules {\n  static create(): BlackjackRules {\n    const rules = BlackjackRules.standard();\n    // Customize for European rules\n    return rules;\n  }\n}\n```\n\n### Adding Custom Actions\n\n```typescript\n// Extend AvailableActions for custom game variants\nclass CustomAvailableActions extends AvailableActions {\n  canInsurance: bool = false;\n  canEvenMoney: bool = false;\n}\n```\n\n## Testing\n\nThe library includes comprehensive test coverage:\n\n```bash\nnpm test\n```\n\nAll core functions are tested with:\n- Standard blackjack rules\n- Spanish 21 rules\n- Custom rule configurations\n- Edge cases and error conditions\n\n## API Reference\n\n### BlackjackRules\n\nConfigurable blackjack rules class with factory methods:\n- `BlackjackRules.standard()` - Standard casino rules\n- `BlackjackRules.spanish21()` - Spanish 21 variant\n- `BlackjackRules.dealerHitsSoft17()` - Dealer hits on soft 17\n- `BlackjackRules.allowDoubleAfterSplit()` - Allow double after split\n\n### AvailableActions\n\nResult class from `calculateAvailableActions()`:\n- `canStand: bool` - Can player stand\n- `canDouble: bool` - Can player double\n- `canSplit: bool` - Can player split\n- `canSurrender: bool` - Can player surrender\n\n### Validation Functions\n\nAll validation functions throw errors on invalid conditions:\n- `validateActionPhase()` - Validates game phase\n- `validateActiveHand()` - Validates hand exists\n- `validateCanHit()` - Validates hit action\n- `validateCanStand()` - Validates stand action\n- `validateCanDouble()` - Validates double action\n- `validateCanSplit()` - Validates split action\n- `validateCanSurrender()` - Validates surrender action\n\n### Utility Functions\n\n- `calculateAvailableActions()` - Calculate all available actions\n- `shouldDealerHit()` - Determine if dealer should hit\n- `shouldOfferInsurance()` - Determine if insurance should be offered\n\n## Dependencies\n\n- `@arcanahq/core`: Core framework for Arcana contracts\n\n## Poker Game Utilities\n\nThe library includes comprehensive utilities for poker-style card games:\n\n### Stakes and Betting\n\n```typescript\nimport { Stakes, AnteType, BettingRoundState, PokerSeatBase } from \"@arcanahq/cardgames/assembly/poker/poker_game_types\";\nimport { \n  calculateAnteAmount, \n  postAntes, \n  postBlinds, \n  getNextActingSeat,\n  validateBuyIn,\n  processBuyIn,\n  isBettingRoundComplete\n} from \"@arcanahq/cardgames/assembly/poker/poker_game_utils\";\n\n// Create stakes configuration\nconst stakes = new Stakes(10, 20, 5); // SB: 10, BB: 20, Ante: 5\n\n// Calculate ante amount\nconst anteAmount = calculateAnteAmount(stakes, AnteType.FIXED, 0.0);\n\n// Post antes for all players\nconst bettingState = new BettingRoundState();\nconst antesResult = postAntes(seats, stakes, AnteType.FIXED, 0.0, bettingState);\n// antesResult.seats - updated seats with antes deducted\n// antesResult.totalAnteCollected - total ante collected\n\n// Post small blind and big blind\nconst blindsResult = postBlinds(seats, stakes, sbSeatId, bbSeatId, bettingState);\n// blindsResult.seats - updated seats with blinds deducted\n// blindsResult.currentBetToMatch - current bet to match (BB amount)\n\n// Get next player to act\nconst nextSeatId = getNextActingSeat(seats, buttonSeatId, true, bettingState); // true = preflop\n\n// Validate and process buy-in\nif (validateBuyIn(buyInAmount, minBuyIn, maxBuyIn)) {\n  const updatedSeat = processBuyIn(seat, buyInAmount, minBuyIn, maxBuyIn);\n}\n\n// Check if betting round is complete\nconst isComplete = isBettingRoundComplete(seats, bettingState);\n```\n\n### Showdown Utilities\n\nThe showdown system uses an interface pattern, allowing different implementations for various poker variants.\n\n#### Standard Hold'em (Default)\n\n```typescript\nimport {\n  compareHandsShowdown,\n  compareFiveCardHands,\n  getPlayerHandRank,\n  getPlayerBestHand,\n  compareTwoHands,\n  StandardShowdownEvaluator\n} from \"@arcanahq/cardgames/assembly/poker/showdown\";\nimport { Card } from \"@arcanahq/cardgames/assembly/cards\";\n\n// Compare multiple players' hands in a showdown\nconst holeCardsMap = new Map<i32, Card[]>();\nholeCardsMap.set(0, player0HoleCards);\nholeCardsMap.set(1, player1HoleCards);\nholeCardsMap.set(2, player2HoleCards);\n\nconst communityCards = [flop, turn, river]; // 5 cards total\n\nconst result = compareHandsShowdown(holeCardsMap, communityCards);\n// result.winners - array of seat IDs that tied for the win\n// result.handRanks - map of seat ID to their HandRank\n// result.bestFiveCards - map of seat ID to their best 5-card hand\n\n// Compare exactly 5-card hands (for games like 5-card draw)\nconst fiveCardHands = new Map<i32, Card[]>();\nfiveCardHands.set(0, player0FiveCards);\nfiveCardHands.set(1, player1FiveCards);\nconst result = compareFiveCardHands(fiveCardHands);\n\n// Get a single player's hand rank\nconst handRank = getPlayerHandRank(holeCards, communityCards);\n\n// Get a single player's best 5-card hand\nconst bestHand = getPlayerBestHand(holeCards, communityCards);\n\n// Compare two specific hands\nconst winner = compareTwoHands(holeCards1, holeCards2, communityCards);\n// Returns: 1 if hand1 wins, -1 if hand2 wins, 0 if tie\n```\n\n#### Six-Plus Hold'em\n\n```typescript\nimport { SixPlusShowdownEvaluator } from \"@arcanahq/cardgames/assembly/poker/six_plus_showdown\";\nimport { Card } from \"@arcanahq/cardgames/assembly/cards\";\n\n// Create Six-Plus evaluator (uses 36-card deck, different hand rankings)\nconst evaluator = new SixPlusShowdownEvaluator();\n\n// Use the evaluator for showdown\nconst result = evaluator.compareHandsShowdown(holeCardsMap, communityCards);\n// result.winners - array of seat IDs that tied for the win\n\n// Six-Plus hand rankings:\n// - Flush beats Full House (opposite of standard)\n// - Three of a Kind beats Straight (opposite of standard)\n```\n\n#### Stud Poker (5-Card and 7-Card)\n\n```typescript\nimport { StudShowdownEvaluator } from \"@arcanahq/cardgames/assembly/poker/stud_evaluator\";\nimport { Card } from \"@arcanahq/cardgames/assembly/cards\";\n\nconst evaluator = new StudShowdownEvaluator();\n\n// For 7-card stud: each player has 7 cards, choose best 5\nconst sevenCardHands = new Map<i32, Card[]>();\nsevenCardHands.set(0, player0SevenCards); // 7 cards\nsevenCardHands.set(1, player1SevenCards); // 7 cards\n\n// No community cards for stud\nconst result = evaluator.compareHandsShowdown(sevenCardHands, new Array<Card>(0));\n\n// For 5-card stud: each player has 5 cards, use all 5\nconst fiveCardHands = new Map<i32, Card[]>();\nfiveCardHands.set(0, player0FiveCards); // 5 cards\nfiveCardHands.set(1, player1FiveCards); // 5 cards\n\nconst result = evaluator.compareHandsShowdown(fiveCardHands, new Array<Card>(0));\n```\n\n#### Omaha\n\n```typescript\nimport { OmahaShowdownEvaluator } from \"@arcanahq/cardgames/assembly/poker/omaha_evaluator\";\nimport { Card } from \"@arcanahq/cardgames/assembly/cards\";\n\nconst evaluator = new OmahaShowdownEvaluator();\n\n// Omaha: 4 hole cards, must use exactly 2 + 3 community cards\nconst holeCardsMap = new Map<i32, Card[]>();\nholeCardsMap.set(0, player0FourCards); // 4 cards\nholeCardsMap.set(1, player1FourCards); // 4 cards\n\nconst communityCards = [flop, turn, river]; // 5 cards\n\nconst result = evaluator.compareHandsShowdown(holeCardsMap, communityCards);\n// Automatically tries all combinations of 2 hole + 3 community cards\n```\n\n#### Using Variant Configurations\n\n```typescript\nimport {\n  VariantConfigs,\n  PokerVariant,\n  getEvaluatorForVariant,\n  createEvaluator\n} from \"@arcanahq/cardgames/assembly/poker/variants\";\nimport { ShowdownEvaluator } from \"@arcanahq/cardgames/assembly/poker/showdown_evaluator\";\n\n// Get evaluator by variant name\nconst holdemEvaluator = getEvaluatorForVariant(PokerVariant.TEXAS_HOLDEM);\nconst studEvaluator = getEvaluatorForVariant(PokerVariant.SEVEN_CARD_STUD);\nconst omahaEvaluator = getEvaluatorForVariant(PokerVariant.OMAHA);\nconst sixPlusEvaluator = getEvaluatorForVariant(PokerVariant.SIX_PLUS_HOLDEM);\n\n// Or use variant configuration\nconst config = VariantConfigs.sevenCardStud();\nconst evaluator = createEvaluator(config);\n\n// Available configurations:\n// - VariantConfigs.texasHoldem()\n// - VariantConfigs.omaha()\n// - VariantConfigs.omahaHiLo()\n// - VariantConfigs.sevenCardStud()\n// - VariantConfigs.fiveCardStud()\n// - VariantConfigs.razz() // Lowball 7-card stud\n// - VariantConfigs.sixPlusHoldem()\n```\n\n#### Custom Evaluator\n\n```typescript\nimport { ShowdownEvaluator, ShowdownResult } from \"@arcanahq/cardgames/assembly/poker/showdown_evaluator\";\nimport { Card, HandRank } from \"@arcanahq/cardgames/assembly/cards\";\n\n// Extend ShowdownEvaluator for custom poker variants\nclass CustomShowdownEvaluator extends ShowdownEvaluator {\n  evaluateHand(holeCards: Card[], communityCards: Card[]): HandRank {\n    // Custom evaluation logic\n  }\n  \n  getBestFiveCards(holeCards: Card[], communityCards: Card[]): Card[] {\n    // Custom best hand selection\n  }\n  \n  compareHands(hand1: HandRank, hand2: HandRank): i32 {\n    // Custom comparison logic\n  }\n}\n\nconst customEvaluator = new CustomShowdownEvaluator();\nconst result = customEvaluator.compareHandsShowdown(holeCardsMap, communityCards);\n```\n\n### Pot Management\n\n```typescript\nimport { \n  constructSidePots, \n  calculatePokerRake, \n  distributePot,\n  splitPotForRuns,\n  lockPots\n} from \"@arcanahq/cardgames/assembly/poker/poker_game_utils\";\n\n// Construct side pots from player contributions\nconst contributions = new Map<i32, i64>();\ncontributions.set(seat1Id, 100);\ncontributions.set(seat2Id, 200); // All-in\nconst pots = constructSidePots(contributions, 0);\n\n// Calculate rake\nconst rakeConfig = new PokerRakeConfig(5.0, 10); // 5% rake, cap at 10\nconst rake = calculatePokerRake(potAmount, rakeConfig);\n\n// Distribute pot to winners\nconst distribution = distributePot(pot, winners, runIndex, buttonSeatId, rakeConfig);\n// distribution.payouts - Map of seat ID to payout amount\n// distribution.rake - Rake amount deducted\n```\n\n### Betting Round State\n\n```typescript\nimport { BettingRoundState } from \"@arcanahq/cardgames/assembly/poker/poker_game_types\";\n\nconst bettingState = new BettingRoundState();\n\n// Track contributions\nbettingState.contribThisRound.set(seatId, amount);\nbettingState.contribTotal.set(seatId, totalAmount);\n\n// Calculate amount to call\nconst toCall = bettingState.calculateToCall(seatId);\n\n// Reset for next street\nbettingState.resetRound();\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}