Source code for maverick.players.archetypes.shark

from typing import TYPE_CHECKING

from ...player import Player
from ...enums import ActionType
from ...playeraction import PlayerAction
from ...utils import estimate_holding_strength

if TYPE_CHECKING:  # pragma: no cover
    from ...game import Game

__all__ = ["SharkBot"]


[docs] class SharkBot(Player): """A bot that adapts strategy dynamically based on opponent tendencies (exploitative). Uses hand strength evaluation to identify exploitation opportunities. Makes aggressive plays when hand equity is strong and exploitative plays when detecting weakness. Adjusts bet sizing based on hand strength and pot size. - **Key Traits:** Strong reads, targeted adjustments, uses hand equity for exploitation. - **Strengths:** Maximizes profit against weak players, exploits based on hand strength. - **Weaknesses:** Requires constant attention and accurate reads. - **Common At:** Live games and mixed-skill environments. """ cls_uid = "1e411ce49f304f9fa95e16beafd49dda"
[docs] def decide_action( self, *, game: "Game", valid_actions: list[ActionType], min_raise_amount: int, call_amount: int, min_bet_amount: int, ) -> PlayerAction: """Exploit opponent weaknesses with adaptive play based on hand strength.""" # Evaluate hand strength private_cards = self.state.holding.cards community_cards = game.state.community_cards # Get hand equity if community_cards: hand_equity = estimate_holding_strength( private_cards, community_cards=community_cards, n_private=game.rules.showdown.hole_cards_required, n_simulations=800, n_players=len(game.state.get_players_in_hand()), ) else: # Pre-flop estimation hand_equity = estimate_holding_strength( private_cards, n_private=game.rules.showdown.hole_cards_required, n_simulations=300, n_players=len(game.state.get_players_in_hand()), ) # Shark thresholds - exploitative ranges strong_hand = hand_equity > 0.55 exploitable_hand = hand_equity > 0.35 # Willing to bluff # Exploit with aggressive raises when strong if ActionType.RAISE in valid_actions and strong_hand: # Size raises based on pot and exploitation # Calculate raise-to target (75% of pot above current bet), then convert to raise-by raise_to_target = game.state.current_bet + int(game.state.pot * 0.75) raise_amount = raise_to_target - self.state.current_bet # Ensure we meet minimum raise requirement raise_amount = max(raise_amount, min_raise_amount) # Cap at stack raise_amount = min(raise_amount, self.state.stack) return PlayerAction( player_uid=self.uid, action_type=ActionType.RAISE, amount=raise_amount ) # Value bet aggressively when ahead, or bluff with some equity if ActionType.BET in valid_actions and (strong_hand or exploitable_hand): # Exploitative bet sizing - larger for value, smaller for bluffs if strong_hand: bet_amount = min(int(game.state.pot * 0.8), self.state.stack) else: bet_amount = min(int(game.state.pot * 0.5), self.state.stack) if bet_amount < min_bet_amount: bet_amount = min(min_bet_amount * 2, self.state.stack) return PlayerAction( player_uid=self.uid, action_type=ActionType.BET, amount=bet_amount ) # Call when getting good odds or to trap if ActionType.CALL in valid_actions and strong_hand: # Sharks will call lighter in position or against weaker opponents if call_amount <= self.state.stack and call_amount <= game.state.pot * 0.66: return PlayerAction(player_uid=self.uid, action_type=ActionType.CALL) # Check to trap or for pot control if ActionType.CHECK in valid_actions: return PlayerAction(player_uid=self.uid, action_type=ActionType.CHECK) # Fold when exploitative play isn't profitable return PlayerAction(player_uid=self.uid, action_type=ActionType.FOLD)