diff --git a/poker-modifier-app/README.md b/poker-modifier-app/README.md new file mode 100644 index 0000000..ffadc1a --- /dev/null +++ b/poker-modifier-app/README.md @@ -0,0 +1,55 @@ +# Texas Hold'em Modifier App + +A fun web application that randomly applies modifiers to Texas Hold'em poker games with configurable probability. + +## Features + +- **Configurable Probability**: Adjust the chance of getting a modifier (0-100%) +- **15 Unique Modifiers**: Various game-changing rules like "High Stakes", "Wild Card", "Reverse Psychology", etc. +- **Statistics Tracking**: Keep track of rounds played and modifiers applied +- **Beautiful UI**: Modern, responsive design with poker-themed styling +- **Smooth Animations**: Visual feedback for button clicks and result displays + +## How to Use + +1. Open `index.html` in your web browser +2. Adjust the "Modifier Probability" slider to set the chance of getting a modifier +3. Click "Start Round" to begin a new round +4. The app will randomly decide whether to apply a modifier based on your probability setting +5. If a modifier is chosen, a random modifier will be selected and displayed + +## Modifiers Included + +- **High Stakes**: All bets are doubled +- **Wild Card**: Next card can be used as any card +- **Bluff Master**: See one opponent's card before betting +- **All-In Fever**: If someone goes all-in, everyone must match or fold +- **Lucky Sevens**: Any hand with a 7 beats a pair +- **Reverse Psychology**: Lowest hand wins +- **Split Pot**: Pot split between top 2 hands +- **Texas Twister**: Each player gets an extra hole card +- **Blind Luck**: Play blind until the river +- **Community Boost**: Extra community card revealed +- **Minimum Madness**: Minimum bet tripled +- **Suit Supremacy**: Random suit cards worth +1 rank +- **Quick Draw**: Betting time cut in half +- **Royal Treatment**: Face cards worth double +- **Chip Challenge**: Winner gets extra house chips + +## Files + +- `index.html`: Main HTML structure +- `style.css`: Styling and responsive design +- `script.js`: JavaScript functionality and modifier logic + +## Customization + +You can easily add new modifiers by using the `addModifier()` method: + +```javascript +window.pokerApp.addModifier("Your Modifier Name", "Description of what it does"); +``` + +## Browser Compatibility + +Works in all modern web browsers (Chrome, Firefox, Safari, Edge). diff --git a/poker-modifier-app/README_python.md b/poker-modifier-app/README_python.md new file mode 100644 index 0000000..846c6ac --- /dev/null +++ b/poker-modifier-app/README_python.md @@ -0,0 +1,135 @@ +# Texas Hold'em Modifier App - Python Version + +A desktop application built with Python and tkinter that randomly applies modifiers to Texas Hold'em poker games with configurable probability. + +## Requirements + +- Python 3.6+ +- tkinter (usually comes with Python) + +## How to Run + +```bash +python poker_modifier_app.py +``` + +## Features + +- **Configurable Probability**: Adjust the chance of getting a modifier (0-100%) with a slider +- **50+ Poker & Drinking Modifiers**: Real poker variations with drinking game twists! +- **Statistics Tracking**: Keep track of rounds played and modifiers applied +- **Modern GUI**: Clean, poker-themed interface with visual feedback +- **Easy to Extend**: Simple methods to add new modifiers + +## How to Use + +1. Run the Python script +2. Adjust the "Modifier Probability" slider to set the chance of getting a modifier +3. Click "Start Round" to begin a new round +4. The app will randomly decide whether to apply a modifier based on your probability setting +5. If a modifier is chosen, a random modifier will be selected and displayed + +## Modifiers Included + +### Classic Poker Modifiers +- **High Stakes**: All bets are doubled +- **Wild Card**: Next card can be used as any card +- **Bluff Master**: See one opponent's card before betting +- **All-In Fever**: If someone goes all-in, everyone must match or fold +- **Lucky Sevens**: Any hand with a 7 beats a pair +- **Reverse Psychology**: Lowest hand wins +- **Split Pot**: Pot split between top 2 hands +- **Texas Twister**: Each player gets an extra hole card +- **Blind Luck**: Play blind until the river +- **Community Boost**: Extra community card revealed +- **Minimum Madness**: Minimum bet tripled +- **Suit Supremacy**: Random suit cards worth +1 rank +- **Quick Draw**: Betting time cut in half +- **Royal Treatment**: Face cards worth double +- **Chip Challenge**: Winner gets extra house chips + +## Modifiers Included + +### Classic Poker Modifiers +- **High Stakes**: All bets are doubled +- **Wild Card**: Next card can be used as any card +- **Bluff Master**: See one opponent's card before betting +- **All-In Fever**: If someone goes all-in, everyone must match or fold +- **Lucky Sevens**: Any hand with a 7 beats a pair +- **Reverse Psychology**: Lowest hand wins +- **Split Pot**: Pot split between top 2 hands +- **Texas Twister**: Each player gets an extra hole card +- **Blind Luck**: Play blind until the river +- **Community Boost**: Extra community card revealed +- **Minimum Madness**: Minimum bet tripled +- **Suit Supremacy**: Random suit cards worth +1 rank +- **Quick Draw**: Betting time cut in half +- **Royal Treatment**: Face cards worth double +- **Chip Challenge**: Winner gets extra house chips + +### Drinking Game Modifiers +- **Red or Black**: Guess community card colors for double winnings +- **Pocket Rockets**: Pocket Aces trigger drinks for everyone else +- **Rainbow Flop**: 3-suit flop boosts flush draws +- **Suited Connectors**: Beat any pocket pair +- **Drink or Fold**: Choose to drink and stay in or fold +- **Shot Clock**: 10 seconds per decision or auto-fold +- **Double Down**: Pay double to see opponent's cards +- **Bad Beat Jackpot**: Losing with full house+ makes others drink +- **Chaser Round**: Previous loser gets bonus stack +- **Face Card Frenzy**: Each face card = take a sip +- **Burn Card Reveal**: Matching burn cards = drinks + chips +- **Pair Tax**: Pocket pairs cost extra or drink +- **Kicker Clash**: Lowest kicker in tie drinks +- **Color Blind**: Red cards +1, black cards -1 +- **Sip and Tell**: Drink and honestly rate your hand +- **Last Call**: Final betting round, no more cards +- **Drink the River**: River helps you = others drink +- **Tipsy Tells**: Must make exaggerated expressions +- **House Rules**: Deuces wild but drink when used +- **Side Bet Madness**: Bet on what flop will contain +- **Fold Penalty**: Folders drink and sit out next hand +- **Straight Shooter**: Complete straight = pick someone to finish drink +- **Flush Rush**: First flush wins side pot from all +- **Ace High Drama**: Ace high wins double but finish drink +- **Bluff Check**: Caught bluffing = drink + penalty +- **Small Ball**: Only minimum bets allowed +- **Position Power**: Button sees everyone's first card +- **Community Chest**: 6 community cards total +- **Heads Up**: Only top 2 hands after flop continue +- **Dealer's Choice**: Dealer picks wild suits +- **Ante Up**: Double ante or take two drinks +- **Showdown Shuffle**: Simultaneous card reveal +- **Lucky Draw**: Extra card, choose best 2 +- **Betting Blind**: First round before looking at cards +- **Chip and a Chair**: Short stack sees early community card +- **All Red**: Red cards boost hand level +- **Mississippi Stud**: Fold after flop for half bet back + +## Code Structure + +- `PokerModifierApp`: Main application class +- `setup_gui()`: Creates the tkinter interface +- `start_round()`: Main game logic for starting rounds +- `apply_random_modifier()`: Selects and displays a random modifier +- `show_no_modifier()`: Displays when no modifier is chosen +- `add_modifier()`: Method to add new modifiers +- `get_stats()`: Returns current statistics + +## Customization + +You can easily add new modifiers programmatically: + +```python +app = PokerModifierApp() +app.add_modifier("Your Modifier Name", "Description of what it does") +app.run() +``` + +## GUI Components + +- **Title**: Application header +- **Settings Panel**: Probability slider +- **Result Display**: Shows modifier or "no modifier" message +- **Start Button**: Triggers new round +- **Statistics**: Displays rounds played and modifiers applied diff --git a/poker-modifier-app/index.html b/poker-modifier-app/index.html new file mode 100644 index 0000000..9789b27 --- /dev/null +++ b/poker-modifier-app/index.html @@ -0,0 +1,45 @@ + + + + + + Texas Hold'em Modifier App + + + +
+

šŸƒ Texas Hold'em Modifier

+
+
+

Settings

+
+ + + 30% +
+
+ +
+
+

Click "Start Round" to begin!

+
+
+ + + +
+
+ Rounds Played: + 0 +
+
+ Modifiers Applied: + 0 +
+
+
+
+ + + + diff --git a/poker-modifier-app/poker_modifier_app.py b/poker-modifier-app/poker_modifier_app.py new file mode 100644 index 0000000..ed89c70 --- /dev/null +++ b/poker-modifier-app/poker_modifier_app.py @@ -0,0 +1,831 @@ +import tkinter as tk +from tkinter import ttk +import random +import time + +class PokerModifierApp: + def __init__(self): + self.modifiers = [ + # Hand Bonus Modifiers (Balatro-inspired) + { + "name": "Pair Bonus", + "description": "Any pocket pair: everyone else pays you 1 chip, even if you lose the hand." + }, + { + "name": "Flush Fever", + "description": "Make a flush: collect 1 chip from each other player (separate from main pot)." + }, + { + "name": "Straight Shot", + "description": "Complete a straight: choose one player to pay you half the current pot size." + }, + { + "name": "Full House Party", + "description": "Make full house: everyone else pays 2 chips + takes 2 drinks." + }, + { + "name": "High Card Hero", + "description": "Win with just high card: collect your normal winnings + 1 chip from each player." + }, + + # Card Enhancement Modifiers + { + "name": "Face Card Power", + "description": "All face cards (J, Q, K) count as Aces for this hand." + }, + { + "name": "Red Suit Boost", + "description": "Hearts and Diamonds are worth +1 rank (Jack becomes Queen, etc.)" + }, + { + "name": "Black Magic", + "description": "Spades and Clubs can be used as any suit for straights/flushes." + }, + { + "name": "Lucky Sevens", + "description": "All 7s become wild cards that can be any rank." + }, + { + "name": "Steel Cards", + "description": "Random rank chosen: {steel_rank}. All {steel_rank}s beat everything this hand!" + }, + + # Ante-Based Effects (Clear Money Source) + { + "name": "Bonus Pool", + "description": "Everyone puts 2 chips in bonus pool. First person to make any pair wins it all." + }, + + # Deck Manipulation (Balatro-style) + { + "name": "Deck Shuffle", + "description": "After dealing hole cards, shuffle deck and redeal all community cards." + }, + { + "name": "Extra Draw", + "description": "Deal each player a 3rd hole card. Discard one before the flop." + }, + { + "name": "Phantom Cards", + "description": "Deal 6 community cards, but randomly remove 1 before showdown." + }, + + # Special Betting Rules (Realistic Economics) + { + "name": "Escalation", + "description": "Each raise must be at least 2x the previous raise (not just matching)." + }, + + # Position and Action Modifiers + { + "name": "Button Bonus", + "description": "Dealer button acts last in ALL rounds" + }, + { + "name": "Call Penalty", + "description": "Anyone who only calls (never raises) pays 1 chip penalty to pot." + }, + + # Information Warfare + { + "name": "Poker Face", + "description": "No talking, no expressions allowed. Pure silent poker this hand." + }, + { + "name": "Truth or Consequences", + "description": "If asked 'good hand or bad hand?' you must answer truthfully or pay penalty." + }, + { + "name": "Open Book", + "description": "Everyone plays with one hole card face-up." + }, + + # Drinking Game Integration + { + "name": "Liquid Courage", + "description": "Take a drink before betting to get chip bonus to all your bets." + }, + { + "name": "Last Call", + "description": "Everyone must finish their current drink before the river card." + }, + { + "name": "Shot Clock", + "description": "5 seconds to act or take a shot and auto-fold." + }, + { + "name": "Drink Tax", + "description": "Each red card in your final hand = one sip (reveal afret play) ." + }, + + # Wild and Chaos Effects + { + "name": "Joker's Wild", + "description": "All Jacks become completely wild - any suit, any rank you choose." + }, + { + "name": "Suit Swap", + "description": "Hearts become Spades, Diamonds become Clubs this hand." + }, + { + "name": "Rank Revolution", + "description": "2s beat Aces this hand. All other ranks stay the same." + }, + { + "name": "Time Warp", + "description": "Play the hand completely backwards: showdown first, then remove random cards from table !" + }, + + # Economic Effects (Clear Money Sources) + { + "name": "Poverty Mode", + "description": "All bets limited to 1 chip maximum this hand." + }, + { + "name": "High Roller", + "description": "Minimum bet is 5x the entry this hand." + }, + { + "name": "Charity Case", + "description": "Player with fewest chips get ther ente funded by richest player." + }, + + # Penalty-Based Modifiers (Clear Consequences) + { + "name": "Fold Tax", + "description": "Anyone who folds pays 5 chip to the pot immediately." + }, + { + "name": "Bluff Fine", + "description": "Get caught bluffing = pay 2 chips to next hand's pot." + }, + { + "name": "Speed Fine", + "description": "Take longer than 10 seconds to act = pay 1 chip to pot." + }, + { + "name": "Talk Tax", + "description": "Every word spoken during betting costs 1 chip to the pot." + }, + + # Skill Challenges (With Clear Rewards/Penalties) + { + "name": "Memory Challenge", + "description": " Dealers holder names all community cards in order. Success = collect 1 chip from each player. Fail = pay 1 chip to each player." + }, + { + "name": "Quick Draw", + "description": "Everyone pays 1 chip to quick-draw pot. First to correctly announce their hand wins the pot and cant pass." + }, + { + "name": "Bluff Bonus", + "description": "Successfully bluff with 7-high or worse = collect 2 chips from each other player." + }, + { + "name": "Prediction Pool", + "description": "Everyone puts 1 chip in pool. Guess the river card exactly = win the pool." + }, + + # Partnership Modifiers + { + "name": "Buddy System", + "description": "Each player chooses a partner. Partners share fate - both win or both lose." + }, + { + "name": "Duo Power", + "description": "Partners can combine their hole cards - each player plays with 4 cards total." + }, + { + "name": "Shared Vision", + "description": "Partners can show each other one hole card before betting starts." + }, + { + "name": "Tag Team", + "description": "Partners alternate who plays each betting round (pre-flop, flop, turn, river)." + }, + { + "name": "Power Couple", + "description": "If both partners make it to showdown, they both get +1 chip bonus from other players (revalt at the end of round)." + }, + ] + + # Separate endgame modifiers for special handling + self.endgame_modifiers = [ + # Classic Endgame Modifiers + { + "name": "Final Boss", + "description": "This is the last hand. Winner takes all remaining chips." + }, + { + "name": "Sudden Death", + "description": "Anyone who folds is eliminated from the game." + }, + { + "name": "Comeback Kid", + "description": "Player with the worst hand can't lose chips this round (reveal at the end of round)." + }, + { + "name": "Double or Nothing", + "description": "Winner gets double payout, but everyone else pays double penalty." + }, + + # High Stakes Endgame + { + "name": "All In Madness", + "description": "Everyone must go all-in. No calling, no folding allowed this hand." + }, + { + "name": "Chip Volcano", + "description": "Everyone puts half their remaining chips in the center. Winner takes the mountain." + }, + { + "name": "Last Stand", + "description": "Player with fewest chips gets to act last in ALL betting rounds." + }, + + # Dramatic Reversals + { + "name": "Underdog Victory", + "description": "Worst hand wins the pot instead of best hand this round." + } + # Winner Takes All Variants + { + "name": "Crown Jewels", + "description": "Winner of this hand becomes the 'King' - all other players pay tribute (2 chips each)." + }, + { + "name": "Championship Belt", + "description": "Winner takes 75% of all chips on the table. Remaining 25% goes for the second best." + }, + # Elimination Mechanics + { + "name": "Battle Royale", + "description": "Lowest hand is eliminated. If tied, both eliminated." + }, + { + "name": "Survivor", + "description": "Only players who improve their hand from pre-flop to river survive to next round." + }, + #Time Pressure Endgame + { + "name": "Speed Round", + "description": "3 seconds to act or auto-fold. No exceptions, no delays." + }, + { + "name": "Auction House", + "description": "Players bid chips to see each other's hole cards before betting." + }, + { + "name": "Lightning Round", + "description": "Deal all 5 community cards at once. Betting happens after each card revealed." + }, + + # Psychological Warfare + { + "name": "Confession Booth", + "description": "Each player must truthfully state their biggest bluff this session." + }, + { + "name": "Truth Serum", + "description": "Everyone must honestly rate their hand 1-10 before any betting." + }, + { + "name": "Poker Face Off", + "description": "Staring contest: losers must reveal one hole card to the table." + }, + + # Endgame Economics + { + "name": "Wealth Redistribution", + "description": "Before the hand, richest player gives 3 chips to poorest player." + }, + { + "name": "Emergency Fund", + "description": "All players with less than 5 chips get emergency funding from the pot." + }, + { + "name": "Final Ante", + "description": "Everyone must put in their last 2 chips before seeing cards. No backing out." + }, + + # Apocalypse Modifiers + { + "name": "Nuclear Option", + "description": "Dealer burns the top 3 cards. Play with whatever's left in the deck." + }, + { + "name": "Meteor Strike", + "description": "Remove all face cards from the deck for this hand only." + }, + { + "name": "Solar Flare", + "description": "All suits become the same suit (dealer's choice)." + }, + + # Legacy Modifiers + { + "name": "Hall of Fame", + "description": "Winner's name gets written down as 'Champion of the Session'." + }, + { + "name": "Legendary Hand", + "description": "This hand will be retold as a story. Play like legends." + }, + { + "name": "Photo Finish", + "description": "Take a photo of the winning hand - it goes in the poker hall of fame." + }, + + # Chaos Theory + { + "name": "Butterfly Effect", + "description": "One random decision by dealer changes everything: flip a coin for each community card to reverse it." + }, + { + "name": "Time Paradox", + "description": "Play the hand twice with same cards. Best average result wins." + }, + { + "name": "Multiverse", + "description": "Deal 2 separate boards. Players choose which board to play after seeing both." + } + ] + + # Remove endgame modifiers from regular modifier list + endgame_modifier_names = [mod['name'] for mod in self.endgame_modifiers] + self.modifiers = [mod for mod in self.modifiers if mod['name'] not in endgame_modifier_names] + + # Game state tracking + self.rounds_played = 0 + self.modifiers_applied = 0 + self.total_game_rounds = 20 # Default game length + self.endgame_threshold = 0.8 # Start endgame modifiers at 80% of total rounds + self.debug_mode = False + self.force_endgame = False + + self.setup_gui() + + def setup_gui(self): + # Create main window + self.root = tk.Tk() + self.root.title("šŸƒ Texas Hold'em Modifier") + self.root.geometry("650x750") + self.root.configure(bg='#0f4c3a') + self.root.resizable(True, True) + + # Configure style + style = ttk.Style() + style.theme_use('clam') + + # Main container + main_frame = tk.Frame(self.root, bg='#0f4c3a', padx=20, pady=20) + main_frame.pack(fill=tk.BOTH, expand=True) + + # Title + title_label = tk.Label( + main_frame, + text="šŸƒ Texas Hold'em Modifier", + font=('Arial', 24, 'bold'), + fg='#ffd700', + bg='#0f4c3a' + ) + title_label.pack(pady=(0, 20)) + + # Settings frame + settings_frame = tk.LabelFrame( + main_frame, + text="Settings", + font=('Arial', 12, 'bold'), + fg='#ffd700', + bg='#1a6b4d', + relief=tk.RIDGE, + bd=2 + ) + settings_frame.pack(fill=tk.X, pady=(0, 20), padx=10, ipady=10) + + # Probability setting + prob_frame = tk.Frame(settings_frame, bg='#1a6b4d') + prob_frame.pack(fill=tk.X, padx=10, pady=5) + + tk.Label( + prob_frame, + text="Modifier Probability:", + font=('Arial', 11, 'bold'), + fg='white', + bg='#1a6b4d' + ).pack(side=tk.LEFT) + + self.prob_var = tk.IntVar(value=30) + self.prob_scale = tk.Scale( + prob_frame, + from_=0, + to=100, + orient=tk.HORIZONTAL, + variable=self.prob_var, + command=self.update_prob_display, + bg='#1a6b4d', + fg='white', + highlightbackground='#1a6b4d', + troughcolor='#0f4c3a', + activebackground='#ffd700' + ) + self.prob_scale.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(10, 5)) + + self.prob_label = tk.Label( + prob_frame, + text="30%", + font=('Arial', 11, 'bold'), + fg='#ffd700', + bg='#1a6b4d', + width=5 + ) + self.prob_label.pack(side=tk.RIGHT) + + # Debug controls frame + debug_frame = tk.Frame(settings_frame, bg='#1a6b4d') + debug_frame.pack(fill=tk.X, padx=10, pady=5) + + # Debug mode toggle + self.debug_var = tk.BooleanVar(value=False) + debug_check = tk.Checkbutton( + debug_frame, + text="Debug Mode", + variable=self.debug_var, + command=self.toggle_debug_mode, + bg='#1a6b4d', + fg='white', + selectcolor='#0f4c3a', + activebackground='#1a6b4d', + activeforeground='#ffd700', + font=('Arial', 10, 'bold') + ) + debug_check.pack(side=tk.LEFT, padx=(0, 15)) + + # Force endgame button (only visible in debug mode) + self.force_endgame_button = tk.Button( + debug_frame, + text="Force Endgame", + command=self.toggle_force_endgame, + bg='#ff6b6b', + fg='white', + font=('Arial', 9, 'bold'), + relief=tk.RAISED, + bd=2 + ) + # Initially hidden + + # Game length setting + length_frame = tk.Frame(settings_frame, bg='#1a6b4d') + length_frame.pack(fill=tk.X, padx=10, pady=5) + + tk.Label( + length_frame, + text="Total Game Rounds:", + font=('Arial', 11, 'bold'), + fg='white', + bg='#1a6b4d' + ).pack(side=tk.LEFT) + + self.length_var = tk.IntVar(value=20) + self.length_scale = tk.Scale( + length_frame, + from_=5, + to=50, + orient=tk.HORIZONTAL, + variable=self.length_var, + command=self.update_length_display, + bg='#1a6b4d', + fg='white', + highlightbackground='#1a6b4d', + troughcolor='#0f4c3a', + activebackground='#ffd700' + ) + self.length_scale.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(10, 5)) + + self.length_label = tk.Label( + length_frame, + text="20", + font=('Arial', 11, 'bold'), + fg='#ffd700', + bg='#1a6b4d', + width=5 + ) + self.length_label.pack(side=tk.RIGHT) + + # Result display frame + self.result_frame = tk.Frame( + main_frame, + bg='#2d2d2d', + relief=tk.RIDGE, + bd=3, + height=150 + ) + self.result_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 20), padx=10) + self.result_frame.pack_propagate(False) + + # Initial result text + self.result_label = tk.Label( + self.result_frame, + text="Click 'Start Round' to begin!", + font=('Arial', 14), + fg='#cccccc', + bg='#2d2d2d', + wraplength=500, + justify=tk.CENTER + ) + self.result_label.pack(expand=True, fill=tk.BOTH, padx=20, pady=20) + + # Button frame for Start and Reset + button_frame = tk.Frame(main_frame, bg='#0f4c3a') + button_frame.pack(fill=tk.X, pady=(0, 20), padx=10) + + # Start button + self.start_button = tk.Button( + button_frame, + text="Start Round", + font=('Arial', 18, 'bold'), + bg='#ffd700', + fg='#0f4c3a', + activebackground='#ffed4e', + activeforeground='#0f4c3a', + relief=tk.RAISED, + bd=3, + command=self.start_round, + cursor='hand2' + ) + self.start_button.pack(side=tk.LEFT, fill=tk.X, expand=True, ipady=10, padx=(0, 5)) + + # Reset button + self.reset_button = tk.Button( + button_frame, + text="Reset Game", + font=('Arial', 14, 'bold'), + bg='#ff6b6b', + fg='white', + activebackground='#ff5252', + activeforeground='white', + relief=tk.RAISED, + bd=3, + command=self.reset_game, + cursor='hand2' + ) + self.reset_button.pack(side=tk.RIGHT, ipady=10, padx=(5, 0)) + + # Statistics frame + stats_frame = tk.Frame(main_frame, bg='#0f4c3a') + stats_frame.pack(fill=tk.X, padx=10) + + # Rounds played + rounds_frame = tk.LabelFrame( + stats_frame, + text="Rounds Played", + font=('Arial', 10, 'bold'), + fg='#cccccc', + bg='#1a6b4d', + relief=tk.RIDGE, + bd=2 + ) + rounds_frame.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 3)) + + self.rounds_label = tk.Label( + rounds_frame, + text="0", + font=('Arial', 20, 'bold'), + fg='#ffd700', + bg='#1a6b4d' + ) + self.rounds_label.pack(pady=10) + + # Modifiers applied + mods_frame = tk.LabelFrame( + stats_frame, + text="Modifiers Applied", + font=('Arial', 10, 'bold'), + fg='#cccccc', + bg='#1a6b4d', + relief=tk.RIDGE, + bd=2 + ) + mods_frame.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(3, 3)) + + self.mods_label = tk.Label( + mods_frame, + text="0", + font=('Arial', 20, 'bold'), + fg='#ffd700', + bg='#1a6b4d' + ) + self.mods_label.pack(pady=10) + + # Game phase indicator + phase_frame = tk.LabelFrame( + stats_frame, + text="Game Phase", + font=('Arial', 10, 'bold'), + fg='#cccccc', + bg='#1a6b4d', + relief=tk.RIDGE, + bd=2 + ) + phase_frame.pack(side=tk.RIGHT, fill=tk.X, expand=True, padx=(3, 0)) + + self.phase_label = tk.Label( + phase_frame, + text="Early", + font=('Arial', 16, 'bold'), + fg='#4CAF50', + bg='#1a6b4d' + ) + self.phase_label.pack(pady=10) + + def update_prob_display(self, value): + """Update the probability percentage display""" + self.prob_label.config(text=f"{value}%") + + def update_length_display(self, value): + """Update the game length display""" + self.length_label.config(text=str(value)) + self.total_game_rounds = int(value) + + def toggle_debug_mode(self): + """Toggle debug mode and show/hide debug controls""" + self.debug_mode = self.debug_var.get() + if self.debug_mode: + self.force_endgame_button.pack(side=tk.LEFT, padx=(0, 10)) + print("šŸ› Debug mode enabled") + else: + self.force_endgame_button.pack_forget() + self.force_endgame = False + print("šŸ› Debug mode disabled") + + def toggle_force_endgame(self): + """Toggle forced endgame mode for testing""" + self.force_endgame = not self.force_endgame + if self.force_endgame: + self.force_endgame_button.config(text="Stop Force Endgame", bg='#4CAF50') + print("šŸŽÆ Forcing endgame modifiers") + else: + self.force_endgame_button.config(text="Force Endgame", bg='#ff6b6b') + print("šŸŽÆ Normal modifier selection restored") + + def is_endgame(self): + """Determine if we're in endgame phase""" + if self.debug_mode and self.force_endgame: + return True + + endgame_round = int(self.total_game_rounds * self.endgame_threshold) + return self.rounds_played >= endgame_round + + def start_round(self): + """Start a new poker round and determine if modifier should be applied""" + # Button animation effect + self.start_button.config(relief=tk.SUNKEN) + self.root.after(100, lambda: self.start_button.config(relief=tk.RAISED)) + + # Update round counter + self.rounds_played += 1 + self.rounds_label.config(text=str(self.rounds_played)) + + # Update game phase indicator + self.update_phase_indicator() + + # Get current probability + modifier_chance = self.prob_var.get() + + # Determine if modifier should be applied + random_value = random.random() * 100 + should_apply_modifier = random_value < modifier_chance + + if should_apply_modifier: + self.apply_random_modifier() + else: + self.show_no_modifier() + + def update_phase_indicator(self): + """Update the game phase indicator based on current round""" + if self.is_endgame(): + self.phase_label.config(text="Endgame", fg='#ff6b6b') + elif self.rounds_played >= self.total_game_rounds * 0.6: + self.phase_label.config(text="Late", fg='#ffa500') + elif self.rounds_played >= self.total_game_rounds * 0.3: + self.phase_label.config(text="Mid", fg='#ffeb3b') + else: + self.phase_label.config(text="Early", fg='#4CAF50') + + def apply_random_modifier(self): + """Apply a random modifier and update display""" + # Update modifier counter + self.modifiers_applied += 1 + self.mods_label.config(text=str(self.modifiers_applied)) + + # Determine which modifier pool to use + if self.is_endgame(): + modifier_pool = self.endgame_modifiers + modifier_type = "šŸ ENDGAME" + bg_color = '#4a2d2d' # Darker red for endgame + else: + modifier_pool = self.modifiers + modifier_type = "šŸŽ²" + bg_color = '#2d4a2d' # Green for normal + + # Select random modifier from appropriate pool + selected_modifier = random.choice(modifier_pool).copy() + + # Special handling for Steel Cards - randomize the rank + if selected_modifier['name'] == 'Steel Cards': + ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King', 'Ace'] + steel_rank = random.choice(ranks) + selected_modifier['description'] = selected_modifier['description'].format(steel_rank=steel_rank) + + # Update result frame styling for modifier + self.result_frame.config(bg=bg_color, highlightbackground='#ffd700', highlightthickness=2) + + # Update display with modifier info + modifier_text = f"{modifier_type} {selected_modifier['name']}\n\n{selected_modifier['description']}" + + # Add endgame indicator if applicable + if self.is_endgame(): + rounds_left = self.total_game_rounds - self.rounds_played + if rounds_left > 0: + modifier_text += f"\n\nāš ļø Endgame Phase - {rounds_left} rounds left" + else: + modifier_text += f"\n\nāš ļø FINAL ROUND!" + + self.result_label.config( + text=modifier_text, + fg='#ffd700', + bg=bg_color, + font=('Arial', 14, 'bold') + ) + + def show_no_modifier(self): + """Show no modifier message""" + # Update result frame styling for no modifier + self.result_frame.config(bg='#2d2d2d', highlightbackground='#666666', highlightthickness=1) + + # Update display + self.result_label.config( + text="No modifier this round\n\nPlay normally", + fg='#cccccc', + bg='#2d2d2d', + font=('Arial', 14) + ) + + def reset_game(self): + """Reset the game to initial state""" + self.rounds_played = 0 + self.modifiers_applied = 0 + self.force_endgame = False + + # Update displays + self.rounds_label.config(text="0") + self.mods_label.config(text="0") + self.phase_label.config(text="Early", fg='#4CAF50') + + # Reset result frame + self.result_frame.config(bg='#2d2d2d', highlightbackground='#666666', highlightthickness=1) + self.result_label.config( + text="Click 'Start Round' to begin!", + fg='#cccccc', + bg='#2d2d2d', + font=('Arial', 14) + ) + + # Reset force endgame button if visible + if self.debug_mode: + self.force_endgame_button.config(text="Force Endgame", bg='#ff6b6b') + + print("šŸ”„ Game reset to initial state") + + def add_modifier(self, name, description): + """Add a new modifier to the list""" + self.modifiers.append({"name": name, "description": description}) + + def get_stats(self): + """Get current statistics""" + modifier_rate = 0 if self.rounds_played == 0 else (self.modifiers_applied / self.rounds_played) * 100 + rounds_remaining = max(0, self.total_game_rounds - self.rounds_played) + + return { + "rounds_played": self.rounds_played, + "modifiers_applied": self.modifiers_applied, + "modifier_rate": round(modifier_rate, 1), + "total_game_rounds": self.total_game_rounds, + "rounds_remaining": rounds_remaining, + "is_endgame": self.is_endgame(), + "debug_mode": self.debug_mode, + "force_endgame": self.force_endgame + } + + def run(self): + """Start the application""" + print("šŸƒ Texas Hold'em Modifier App started!") + print("Available methods: app.get_stats(), app.add_modifier(name, description)") + print("Debug features: Toggle debug mode to access force endgame controls") + print(f"Default game length: {self.total_game_rounds} rounds") + print(f"Endgame threshold: {int(self.endgame_threshold * 100)}% ({int(self.total_game_rounds * self.endgame_threshold)} rounds)") + self.root.mainloop() + +if __name__ == "__main__": + app = PokerModifierApp() + app.run() diff --git a/poker-modifier-app/script.js b/poker-modifier-app/script.js new file mode 100644 index 0000000..c0c598f --- /dev/null +++ b/poker-modifier-app/script.js @@ -0,0 +1,175 @@ +class PokerModifierApp { + constructor() { + this.modifiers = [ + { + name: "High Stakes", + description: "All bets are doubled this round!" + }, + { + name: "Wild Card", + description: "The next card revealed can be used as any card!" + }, + { + name: "Bluff Master", + description: "Players can see one opponent's card before betting." + }, + { + name: "All-In Fever", + description: "If someone goes all-in, everyone must match or fold." + }, + { + name: "Lucky Sevens", + description: "Any hand with a 7 beats a pair!" + }, + { + name: "Reverse Psychology", + description: "Lowest hand wins this round!" + }, + { + name: "Split Pot", + description: "The pot is split between the top 2 hands." + }, + { + name: "Texas Twister", + description: "Each player gets an extra hole card this round." + }, + { + name: "Blind Luck", + description: "All players must play blind (no looking at cards) until the river." + }, + { + name: "Community Boost", + description: "An extra community card is revealed (6 total)." + }, + { + name: "Minimum Madness", + description: "Minimum bet is tripled this round." + }, + { + name: "Suit Supremacy", + description: "All cards of the chosen suit (random) are worth +1 rank." + }, + { + name: "Quick Draw", + description: "Betting time is cut in half - make decisions fast!" + }, + { + name: "Royal Treatment", + description: "Face cards (J, Q, K) are worth double." + }, + { + name: "Chip Challenge", + description: "Winner gets extra chips from the house!" + } + ]; + + this.roundsPlayed = 0; + this.modifiersApplied = 0; + + this.initializeElements(); + this.attachEventListeners(); + this.updateChanceDisplay(); + } + + initializeElements() { + this.startButton = document.getElementById('startRoundBtn'); + this.resultDisplay = document.getElementById('resultDisplay'); + this.modifierChanceSlider = document.getElementById('modifierChance'); + this.chanceValueDisplay = document.getElementById('chanceValue'); + this.roundsCountDisplay = document.getElementById('roundsCount'); + this.modifiersCountDisplay = document.getElementById('modifiersCount'); + } + + attachEventListeners() { + this.startButton.addEventListener('click', () => this.startRound()); + this.modifierChanceSlider.addEventListener('input', () => this.updateChanceDisplay()); + } + + updateChanceDisplay() { + const chance = this.modifierChanceSlider.value; + this.chanceValueDisplay.textContent = `${chance}%`; + } + + startRound() { + // Add button animation + this.startButton.style.transform = 'scale(0.95)'; + setTimeout(() => { + this.startButton.style.transform = ''; + }, 150); + + // Update round counter + this.roundsPlayed++; + this.roundsCountDisplay.textContent = this.roundsPlayed; + + // Get current probability + const modifierChance = parseInt(this.modifierChanceSlider.value); + + // Determine if a modifier should be applied + const randomValue = Math.random() * 100; + const shouldApplyModifier = randomValue < modifierChance; + + if (shouldApplyModifier) { + this.applyRandomModifier(); + } else { + this.showNoModifier(); + } + + // Add some visual feedback with animation + this.resultDisplay.style.opacity = '0'; + this.resultDisplay.style.transform = 'scale(0.8)'; + + setTimeout(() => { + this.resultDisplay.style.opacity = '1'; + this.resultDisplay.style.transform = 'scale(1)'; + }, 200); + } + + applyRandomModifier() { + // Update modifier counter + this.modifiersApplied++; + this.modifiersCountDisplay.textContent = this.modifiersApplied; + + // Select random modifier + const randomIndex = Math.floor(Math.random() * this.modifiers.length); + const selectedModifier = this.modifiers[randomIndex]; + + // Update display + this.resultDisplay.className = 'result-display has-modifier'; + this.resultDisplay.innerHTML = ` +
šŸŽ² ${selectedModifier.name}
+
${selectedModifier.description}
+ `; + } + + showNoModifier() { + this.resultDisplay.className = 'result-display no-modifier'; + this.resultDisplay.innerHTML = ` +
No modifier this round
+
Play normally
+ `; + } + + // Method to add new modifiers (for future expansion) + addModifier(name, description) { + this.modifiers.push({ name, description }); + } + + // Method to get statistics + getStats() { + return { + roundsPlayed: this.roundsPlayed, + modifiersApplied: this.modifiersApplied, + modifierRate: this.roundsPlayed > 0 ? (this.modifiersApplied / this.roundsPlayed * 100).toFixed(1) : 0 + }; + } +} + +// Initialize the app when the page loads +document.addEventListener('DOMContentLoaded', () => { + window.pokerApp = new PokerModifierApp(); + + // Add some console info for developers + console.log('šŸƒ Texas Hold\'em Modifier App loaded!'); + console.log('Access the app instance via window.pokerApp'); + console.log('Available methods: getStats(), addModifier(name, description)'); +}); diff --git a/poker-modifier-app/style.css b/poker-modifier-app/style.css new file mode 100644 index 0000000..0b660b8 --- /dev/null +++ b/poker-modifier-app/style.css @@ -0,0 +1,234 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Arial', sans-serif; + background: linear-gradient(135deg, #0f4c3a, #1a6b4d); + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + color: #fff; +} + +.container { + max-width: 600px; + width: 90%; + padding: 2rem; +} + +h1 { + text-align: center; + font-size: 2.5rem; + margin-bottom: 2rem; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3); +} + +.game-area { + background: rgba(255, 255, 255, 0.1); + border-radius: 15px; + padding: 2rem; + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.2); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); +} + +.probability-settings { + margin-bottom: 2rem; + padding: 1rem; + background: rgba(255, 255, 255, 0.05); + border-radius: 10px; + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.probability-settings h3 { + margin-bottom: 1rem; + color: #ffd700; + text-align: center; +} + +.setting { + display: flex; + align-items: center; + gap: 1rem; + flex-wrap: wrap; +} + +.setting label { + font-weight: bold; + min-width: 150px; +} + +#modifierChance { + flex: 1; + min-width: 150px; + height: 8px; + background: rgba(255, 255, 255, 0.2); + border-radius: 5px; + outline: none; + appearance: none; +} + +#modifierChance::-webkit-slider-thumb { + appearance: none; + width: 20px; + height: 20px; + background: #ffd700; + border-radius: 50%; + cursor: pointer; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); +} + +#modifierChance::-moz-range-thumb { + width: 20px; + height: 20px; + background: #ffd700; + border-radius: 50%; + cursor: pointer; + border: none; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); +} + +#chanceValue { + font-weight: bold; + color: #ffd700; + min-width: 40px; + text-align: center; +} + +.result-area { + margin: 2rem 0; + min-height: 120px; + display: flex; + align-items: center; + justify-content: center; +} + +.result-display { + text-align: center; + padding: 2rem; + background: rgba(0, 0, 0, 0.2); + border-radius: 10px; + border: 2px solid rgba(255, 255, 255, 0.1); + min-height: 120px; + display: flex; + flex-direction: column; + justify-content: center; + transition: all 0.3s ease; +} + +.result-display.no-modifier { + border-color: rgba(128, 128, 128, 0.5); + background: rgba(128, 128, 128, 0.1); +} + +.result-display.has-modifier { + border-color: #ffd700; + background: rgba(255, 215, 0, 0.1); + box-shadow: 0 0 20px rgba(255, 215, 0, 0.3); +} + +.modifier-title { + font-size: 1.5rem; + font-weight: bold; + color: #ffd700; + margin-bottom: 0.5rem; +} + +.modifier-description { + font-size: 1rem; + line-height: 1.4; + color: #fff; +} + +.no-modifier-text { + font-size: 1.2rem; + color: #ccc; +} + +.start-button { + width: 100%; + padding: 1rem 2rem; + font-size: 1.5rem; + font-weight: bold; + background: linear-gradient(45deg, #ffd700, #ffed4e); + color: #0f4c3a; + border: none; + border-radius: 10px; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 15px rgba(255, 215, 0, 0.3); + margin-bottom: 2rem; +} + +.start-button:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(255, 215, 0, 0.4); + background: linear-gradient(45deg, #ffed4e, #ffd700); +} + +.start-button:active { + transform: translateY(0); + box-shadow: 0 2px 10px rgba(255, 215, 0, 0.3); +} + +.stats { + display: flex; + justify-content: space-around; + gap: 1rem; + flex-wrap: wrap; +} + +.stat { + background: rgba(255, 255, 255, 0.1); + padding: 1rem; + border-radius: 8px; + text-align: center; + flex: 1; + min-width: 150px; + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.stat-label { + display: block; + font-size: 0.9rem; + color: #ccc; + margin-bottom: 0.5rem; +} + +.stat span:last-child { + font-size: 1.5rem; + font-weight: bold; + color: #ffd700; +} + +@media (max-width: 600px) { + .container { + padding: 1rem; + } + + h1 { + font-size: 2rem; + } + + .game-area { + padding: 1.5rem; + } + + .setting { + flex-direction: column; + align-items: stretch; + } + + .setting label { + min-width: auto; + text-align: center; + } + + .stats { + flex-direction: column; + } +}