From 557c368abc264cc2f30b9b6d9e2c93851f63e5ab Mon Sep 17 00:00:00 2001 From: outruncolors <78451621+outruncolors@users.noreply.github.com> Date: Fri, 28 Jan 2022 02:00:15 -0600 Subject: [PATCH] Blackjack (#187) * Filter out slots from the body. (#181) * Slots changes (#182) * Switch slots result to title and fix snappy * These two guys again * These two guys again * Fix breaking-even * ...?? * Initial commit * Finalize initial blackjack attempt * Remove obsolete helper file --- files/classes/__init__.py | 1 + files/classes/blackjack.py | 166 ++++++++++++++++++++++++++++++++++ files/classes/comment.py | 1 + files/classes/slots.py | 18 +++- files/routes/comments.py | 23 ++++- files/templates/comments.html | 35 ++++++- schema.sql | 3 +- 7 files changed, 241 insertions(+), 6 deletions(-) create mode 100644 files/classes/blackjack.py diff --git a/files/classes/__init__.py b/files/classes/__init__.py index a89f72dd6..f3335b7f9 100644 --- a/files/classes/__init__.py +++ b/files/classes/__init__.py @@ -10,6 +10,7 @@ from .submission import * from .votes import * from .domains import * from .slots import * +from .blackjack import * from .subscriptions import * from files.__main__ import app from .mod_logs import * diff --git a/files/classes/blackjack.py b/files/classes/blackjack.py new file mode 100644 index 000000000..661e5558c --- /dev/null +++ b/files/classes/blackjack.py @@ -0,0 +1,166 @@ +from functools import reduce +from json.encoder import INFINITY +import random +from math import floor + +deck_count = 4 +ranks = ["2", "3", "4", "5", "6", "7", "8", "9", "X", "J", "Q", "K", "A"] +suits = ["♠️", "♥️", "♣️", "♦️"] + + +def shuffle(x): + random.shuffle(x) + return x + + +def get_shuffled_deck(): + return shuffle([rank + suit for rank in ranks for suit in suits for _ in range(deck_count)]) + + +def deal_initial_cards(): + deck = get_shuffled_deck() + p1, d1, p2, d2, *rest_of_deck = deck + return [p1, p2], [d1, d2], rest_of_deck + + +def get_card_value(card): + rank = card[0] + return 0 if rank == "A" else min(ranks.index(rank) + 2, 10) + + +def get_hand_value(hand): + without_aces = sum(map(get_card_value, hand)) + ace_count = sum("A" in c for c in hand) + possibilities = [] + + for i in range(ace_count + 1): + value = without_aces + (ace_count - i) + i * 11 + possibilities.append(-1 if value > 21 else value) + + return max(possibilities) + + +def format_cards(hand): + return map(lambda x: "".join(x), hand) + + +def format_all(player_hand, dealer_hand, deck, status, wager): + formatted_player_hand = format_cards(player_hand) + formatted_dealer_hand = format_cards(dealer_hand) + formatted_deck = format_cards(deck) + + return f'{"/".join(formatted_player_hand)}_{"/".join(formatted_dealer_hand)}_{"/".join(formatted_deck)}_{status}_{wager}' + + +class Blackjack: + command_word = "!blackjack" + minimum_bet = 100 + maximum_bet = INFINITY + + def __init__(self, g): + self.db = g.db + + def check_for_blackjack_command(self, in_text, from_user, from_comment): + if self.command_word in in_text: + for word in in_text.split(): + if self.command_word in word: + wager = word[len(self.command_word):] + wager_value = int(wager) + + if (wager_value < self.minimum_bet): + break + elif (wager_value > self.maximum_bet): + break + elif (wager_value > from_user.coins): + break + + from_user.coins -= wager_value + + player_hand, dealer_hand, rest_of_deck = deal_initial_cards() + status = 'active' + player_value = get_hand_value(player_hand) + dealer_value = get_hand_value(dealer_hand) + + if player_value == 21 and dealer_value == 21: + status = 'push' + self.apply_game_result(from_comment, wager, status) + elif player_value == 21: + status = 'blackjack' + self.apply_game_result(from_comment, wager, status) + elif dealer_value == 21: + status = 'lost' + self.apply_game_result(from_comment, wager, status) + + from_comment.blackjack_result = format_all( + player_hand, dealer_hand, rest_of_deck, status, wager) + + self.db.add(from_comment) + self.db.commit() + + def player_hit(self, from_comment): + player_hand, dealer_hand, deck, status, wager = from_comment.blackjack_result.split( + "_") + player_hand = player_hand.split("/") + dealer_hand = dealer_hand.split("/") + deck = deck.split("/") + player_hand.append(deck.pop(0)) + player_value = get_hand_value(player_hand) + + if player_value == -1: + status = 'bust' + self.apply_game_result(from_comment, wager, status) + + from_comment.blackjack_result = format_all( + player_hand, dealer_hand, deck, status, wager) + + self.db.add(from_comment) + self.db.commit() + + if (player_value == 21): + self.player_stayed(from_comment) + + def player_stayed(self, from_comment): + player_hand, dealer_hand, deck, status, wager = from_comment.blackjack_result.split( + "_") + player_hand = player_hand.split("/") + player_value = get_hand_value(player_hand) + dealer_hand = dealer_hand.split("/") + dealer_value = get_hand_value(dealer_hand) + deck = deck.split("/") + + while dealer_value < 17 and dealer_value != -1: + next = deck.pop(0) + dealer_hand.append(next) + dealer_value = get_hand_value(dealer_hand) + + if player_value > dealer_value or dealer_value == -1: + status = 'won' + elif dealer_value > player_value: + status = 'lost' + else: + status = 'push' + + from_comment.blackjack_result = format_all( + player_hand, dealer_hand, deck, status, wager) + + self.db.add(from_comment) + self.db.commit() + + self.apply_game_result(from_comment, wager, status) + + def apply_game_result(self, from_comment, wager, result): + reward = 0 + + if result == 'push': + reward = int(wager) + elif result == 'won': + reward = int(wager) * 2 + elif result == 'blackjack': + reward = floor(int(wager) * (3/2)) + + if (reward > 0): + user = from_comment.author + user.coins += reward + + self.db.add(user) + self.db.commit() \ No newline at end of file diff --git a/files/classes/comment.py b/files/classes/comment.py index 5a088c894..ad4868a0e 100644 --- a/files/classes/comment.py +++ b/files/classes/comment.py @@ -44,6 +44,7 @@ class Comment(Base): body_html = Column(String) ban_reason = Column(String) slots_result = Column(String) + blackjack_result = Column(String) post = relationship("Submission", viewonly=True) author = relationship("User", primaryjoin="User.id==Comment.author_id") diff --git a/files/classes/slots.py b/files/classes/slots.py index ff9cc82bc..c4dd0d812 100644 --- a/files/classes/slots.py +++ b/files/classes/slots.py @@ -92,11 +92,25 @@ class Slots: shuffle(all_symbols) - if for_payout == 0: return "".join([all_symbols[0], all_symbols[1], all_symbols[2]]) - elif for_payout == 1: return "".join([all_symbols[0], all_symbols[0], all_symbols[2]]) + if for_payout == 0: + return "".join([all_symbols[0], all_symbols[1], all_symbols[2]]) + elif for_payout == 1: + indices = shuffle([0, 1, 2]) + symbol_set = ["", "", ""] + match_a = indices[0] + match_b = indices[1] + nonmatch = indices[2] + matching_symbol = all_symbols[0] + other_symbol = all_symbols[1] + symbol_set[match_a] = matching_symbol + symbol_set[match_b] = matching_symbol + symbol_set[nonmatch] = other_symbol + + return "".join(symbol_set) else: relevantSymbols = shuffle(self.payout_to_symbols[for_payout]) symbol = relevantSymbols[0] + return "".join([symbol, symbol, symbol]) def build_text(self, wager_value, result, user, currency): diff --git a/files/routes/comments.py b/files/routes/comments.py index 1251bd773..b99001e3a 100644 --- a/files/routes/comments.py +++ b/files/routes/comments.py @@ -160,7 +160,7 @@ def api_comment(v): else: abort(400) body = request.values.get("body", "").strip()[:10000] - + if v.admin_level == 3 and parent_post.id == 37749: with open(f"snappy_{SITE_NAME}.txt", "a") as f: f.write('\n{[para]}\n' + body) @@ -587,6 +587,9 @@ def api_comment(v): slots = Slots(g) slots.check_for_slots_command(body, v, c) + blackjack = Blackjack(g) + blackjack.check_for_blackjack_command(body, v, c) + g.db.commit() if request.headers.get("Authorization"): return c.json @@ -888,4 +891,20 @@ def unsave_comment(cid, v): g.db.delete(save) g.db.commit() - return {"message": "Comment unsaved!"} \ No newline at end of file + return {"message": "Comment unsaved!"} + +@app.post("/blackjack/") +@limiter.limit("1/second;30/minute;200/hour;1000/day") +@auth_required +def handle_blackjack_action(cid, v): + comment = get_comment(cid) + action = request.values.get("action", "") + blackjack = Blackjack(g) + + if action == 'hit': + blackjack.player_hit(comment) + elif action == 'stay': + blackjack.player_stayed(comment) + + + return { "message" : "..." } \ No newline at end of file diff --git a/files/templates/comments.html b/files/templates/comments.html index c626b010c..1999a3e40 100644 --- a/files/templates/comments.html +++ b/files/templates/comments.html @@ -176,6 +176,14 @@ {% set isreply = False %} {% endif %} +{% if c.blackjack_result %} + {% set split_result = c.blackjack_result.split('_') %} + {% set blackjack_status = split_result[3] %} + {% set player_hand = split_result[0].replace('X', '10') %} + {% set dealer_hand = split_result[1].split('/')[0] if blackjack_status == 'active' else split_result[1] %} + {% set wager = split_result[4] %} +{% endif %} +
{% if not isreply %} @@ -231,7 +239,32 @@ {% endif %} {% if c.slots_result %} - {{c.slots_result}} + {{c.slots_result}} + {% endif %} + + {% if c.blackjack_result %} + {{player_hand}} vs. {{dealer_hand}} + {% if blackjack_status == 'active' and v.id == c.author_id %} + + + {% elif blackjack_status == 'push' %} + Pushed. + {% elif blackjack_status == 'bust' %} + Bust. Lost {{wager}} Coins. + {% elif blackjack_status == 'lost' %} + Lost {{wager}} Coins. + {% elif blackjack_status == 'won' %} + Won {{wager}} Coins. + {% elif blackjack_status == 'blackjack' %} + Blackjack! Won {{wager}} Coins. + + {% endif %} {% endif %}
{% if c.active_flags %} diff --git a/schema.sql b/schema.sql index 1240ed397..c4e457437 100644 --- a/schema.sql +++ b/schema.sql @@ -299,7 +299,8 @@ CREATE TABLE public.comments ( top_comment_id integer, is_pinned_utc integer, ghost boolean, - slots_result character varying(50) + slots_result character varying(50), + blackjack_result character varying(3000) );