Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import requests
- import json
- class BlackjackPlayer:
- URL = "https://mohsinq.com/blackjack/"
- API = "https://mohsinq.com/api"
- def __init__(self, player_id=None):
- self.debug = True
- if player_id:
- self.playerId = player_id
- self.playerCredits = 0
- self.betAmount = 0
- self.lastBetAmount = 0
- self.state = ""
- self.message = ""
- self.dealerHand = {}
- self.playerHand = {}
- self.games_played = 0
- self.games_won = 0
- self.throw = False
- def parse_game(self, r_json):
- # Get the one we're given if we don't provide one
- if not self.playerId:
- self.playerId = r_json["id"]
- self.playerCredits = r_json["playerCredits"]
- self.betAmount = r_json["betAmount"]
- self.state = r_json["state"]
- self.message = r_json["message"]
- self.dealerHand = r_json["dealerHand"]
- self.playerHand = r_json["playerHand"]
- self.pdebug(r_json)
- def call_api(self, endpoint, method=requests.post) -> json:
- r = method("{}/{}".format(self.API, endpoint), headers={'id': self.playerId})
- if r.status_code != 200:
- print(r.status_code, r.content)
- return json.loads(r.content)
- def get_game(self):
- """
- endpoint: GET /game
- """
- r_json = self.call_api("game", requests.get)
- self.parse_game(r_json)
- def place_bet(self, amt) -> json:
- """
- endpoint: POST /api/bet/betAmount
- """
- self.lastBetAmount = self.betAmount
- return self.call_api("bet/{}".format(amt))
- def hit(self):
- return self.call_api("hit")
- def stand(self):
- return self.call_api("stand")
- def new_game(self):
- return self.call_api("newGame")
- def replenish(self):
- self.pdebug("Replenish credits")
- return self.call_api("replenish")
- def determine_bet(self) -> int:
- """
- Figure out what to bet
- """
- self.pdebug("Player credits: ", self.playerCredits)
- to_make = min(int(self.playerCredits) // 4, 5000)
- if self.throw:
- to_make = int(self.playerCredits)
- self.pdebug("Bet: ", to_make)
- return to_make
- def determine_action(self) -> bool:
- """
- The meat of this script
- :return: true to hit, false to stand
- """
- self.print_hands()
- pv = self.get_player_val()
- dv = self.get_dealer_val()
- cond = []
- if pv == 21:
- return False
- if not self.player_num_ace():
- # Always hit when below 12
- cond.append(pv < 12)
- cond.append(7 <= dv <= 10 and 12 <= pv <= 16)
- cond.append(dv == 11 and 12 <= pv <= 15)
- cond.append(17 <= dv <= 20 and 12 <= pv <= 16)
- cond.append(18 <= dv <= 20 and pv == 17)
- cond.append(19 <= dv <= 20 and pv == 18)
- cond.append(dv == 20 and pv == 19)
- dna = self.dealer_num_ace()
- if dna:
- cond.append(pv < 12)
- cond.append(dna == 2 and 12 <= pv <= 15)
- if dna != 2:
- hc = lambda v: self.has_card(self.dealerHand, v)
- cond.append(hc(2) and 12 <= pv <= 14)
- cond.append((hc(3) or hc(4)) and 12 <= pv <= 13)
- cond.append(hc(5) and pv == 12)
- cond.append(hc(6) and 12 <= pv <= 16)
- else: # Player has at least one ace
- # Value of player's cards that aren't aces
- pva = self.cards_value({"cards": self.player_non_aces()})
- cond.append(pva < 7)
- cond.append(9 <= dv <= 10 and pva == 7)
- cond.append(18 <= dv <= 20 and pva == 7)
- cond.append(dv == 20 and pva == 7)
- return any(cond)
- def player_num_ace(self) -> int:
- """ :returns: number of aces in hand"""
- return self._has_ace(self.playerHand)
- def dealer_num_ace(self) -> int:
- """ :returns: number of aces in hand"""
- return self._has_ace(self.dealerHand)
- def player_non_aces(self) -> list:
- return self._get_non_aces(self.playerHand)
- def dealer_non_aces(self) -> list:
- return self._get_non_aces(self.dealerHand)
- @staticmethod
- def cards_value(cards: dict) -> int:
- return sum([int(c["cost"]) for c in cards["cards"]])
- @staticmethod
- def has_card(cards, val):
- return any([c for c in cards["cards"] if c["cost"] == val])
- @staticmethod
- def _has_ace(v) -> int:
- return sum([c["value"] == "A" for c in v["cards"]])
- @staticmethod
- def _get_non_aces(v):
- return [c for c in v["cards"] if c["value"] != "A"]
- def get_player_val(self):
- return int(self.playerHand["value"])
- def get_dealer_val(self):
- return int(self.dealerHand["value"])
- def print_hands(self):
- if not self.debug:
- return
- print("Dealer hand: {}".format(["{} of {}".format(c["value"], c["suit"]) for c in self.dealerHand["cards"]]))
- print("Dealer hand value: {}".format(self.dealerHand["value"]))
- print("Player hand: {}".format(["{} of {}".format(c["value"], c["suit"]) for c in self.playerHand["cards"]]))
- print("Player hand value: {}".format(self.playerHand["value"]))
- def handle_replenish(self):
- """
- If we get less than 1k credits, replenish will put us back up to that if we hit 0.
- So start betting our entire pool. If we win, it'll give us a lot and if we lose we will get back up to 1k
- """
- if self.playerCredits == 0:
- self.throw = False
- self.replenish()
- self.parse_game(self.new_game())
- return True
- elif self.playerCredits < 1000:
- self.throw = True
- elif self.playerCredits >= 1000:
- # Abort the throw if we won because we probably won a lot
- self.throw = False
- return False
- def state_transition(self):
- """
- bet -> active -> (win | lose | tie)
- Main screen is bet
- """
- self.pdebug("--- {} ---".format(self.state))
- if self.state == "bet":
- bet = self.determine_bet()
- self.parse_game(self.place_bet(bet))
- elif self.state == "active":
- act = self.determine_action()
- if act:
- # If we hit the game continues
- self.pdebug("Player: hit")
- self.parse_game(self.hit())
- else:
- self.pdebug("Player: stand")
- self.parse_game(self.stand())
- # Standing will end the game, no matter what, so go ahead and advance us one state automatically
- self.state_transition()
- elif self.state == "win" or self.state == "lose" or self.state == "tie":
- self.print_hands()
- self.pdebug("You {}!".format(self.state))
- sign = "+" if self.state == "win" else ("-" if self.state == "lose" else "=")
- self.pdebug("Credits: {} ({}{})".format(self.playerCredits, sign, self.betAmount))
- self.games_played += 1
- if self.state == "win":
- self.games_won += 1
- self.pdebug("--- New Game (won {}/{} WR: {})---".format(self.games_won, self.games_played,
- round((self.games_won/self.games_played)*100)))
- print("Credits: {}, (won {}/{} WR: {})".format(self.playerCredits, self.games_won, self.games_played,
- round((self.games_won/self.games_played)*100)))
- if not self.handle_replenish():
- self.parse_game(self.new_game())
- def state_runner(self):
- """ Top level method to run the state methods """
- # while self.games_played < 10:
- while self.playerCredits < 50000:
- self.state_transition()
- # input("Press enter to progress to next state")
- def pdebug(self, *args):
- if self.debug:
- print(*args)
- if __name__ == '__main__':
- bp = BlackjackPlayer("e3391243-45d6-4f43-9721-30d02ac665c3")
- bp.get_game()
- bp.state_runner()
Add Comment
Please, Sign In to add comment