diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d090b5f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Prashant + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/gamesbyexample/alphabet_quiz_highscore.txt b/src/gamesbyexample/alphabet_quiz_highscore.txt new file mode 100644 index 0000000..7fc18d3 --- /dev/null +++ b/src/gamesbyexample/alphabet_quiz_highscore.txt @@ -0,0 +1,2 @@ +letters:3 +numbers:5 diff --git a/src/gamesbyexample/alphabetizequiz.py b/src/gamesbyexample/alphabetizequiz.py index e8344f2..cbc2bce 100644 --- a/src/gamesbyexample/alphabetizequiz.py +++ b/src/gamesbyexample/alphabetizequiz.py @@ -1,74 +1,154 @@ -"""Alphabetize Quiz, by Al Sweigart al@inventwithpython.com -A time-based quiz game to see how fast you can alphabetize letters. -This and other games are available at https://nostarch.com/XX -Tags: short, game, word""" -__version__ = 0 +"""Alphabetize Quiz - Advanced Version +By Al Sweigart (improved by ChatGPT) + +A time-based quiz game to see how fast you can alphabetize letters, words, or numbers. +Now with multiple difficulty levels, countdown timer, and high-score saving! +""" + import random import time +import os +from colorama import Fore, Style, init -# Set up the constants: -# (!) Try changing these constants: -QUESTION_SIZE = 5 # Each question shows 5 letters to alphabetize. -QUIZ_DURATION = 30 # The quiz lasts 30 seconds. +init(autoreset=True) # For colored output +# Constants (you can tweak these) +QUESTION_SIZE = 5 +QUIZ_DURATION = 30 ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' -REVERSE_ALPHABET = 'ZYXWVUTSRQPONMLKJIHGFEDCBA' +NUMBERS = [str(i) for i in range(10)] +HIGHSCORE_FILE = "alphabet_quiz_highscore.txt" def main(): - # Fancy animation for the title: - slowPrint(ALPHABET, 0.02) # (!) Try changing 0.02 to 0.0 or 1.0. - slowPrint(' Alphabetize Quiz', 0.02) - slowPrint(REVERSE_ALPHABET, 0.02) - time.sleep(0.5) - - print('''By Al Sweigart al@inventwithpython.com - -Enter the alphabetical order of the letters shown as fast -as possible. Try to alphabetize as many as possible in {} seconds! - -Example: - P M O T Q <-- The letters. - > mopqt <-- Enter the correct alphabetical order. - '''.format(QUIZ_DURATION)) - input('Press Enter to begin...') - - startTime = time.time() # Get the current time for the start time. - numCorrect = 0 # Number of questions answered correctly. - while True: # Main game loop. - # Come up with letters for the question: - quizLetters = random.sample(ALPHABET, QUESTION_SIZE) - print(' '.join(quizLetters)) - response = input('> ').upper() - response = response.replace(' ', '') # Remove spaces. - - # Check if the quiz's time is up: - if time.time() - 30 > startTime: - print("TIME'S UP!") + showIntro() + + # Difficulty selection + difficulty = chooseDifficulty() + + # Highscore loading + highscore = loadHighScore(difficulty) + + input(Fore.CYAN + "\nPress Enter to begin the quiz...") + + startTime = time.time() + numCorrect = 0 + numAttempted = 0 + + while True: + # Check if time is up + elapsed = time.time() - startTime + if elapsed >= QUIZ_DURATION: + print(Fore.RED + "\nTIME'S UP!") break - # Check if the response is correct: + # Generate question + quizLetters = generateQuestion(difficulty) + print(Fore.YELLOW + " ".join(quizLetters)) + + # Countdown display + remaining = int(QUIZ_DURATION - elapsed) + print(Fore.MAGENTA + f"[{remaining}s left]") + + response = input("> ").upper().replace(" ", "") + numAttempted += 1 + if list(response) == sorted(quizLetters): - print(' Correct!\n') - numCorrect += 1 # Increase the score by 1. + print(Fore.GREEN + " ✅ Correct!\n") + numCorrect += 1 else: - print(' Sorry, wrong. :(\n') + print(Fore.RED + " ❌ Wrong. Answer was:", "".join(sorted(quizLetters)), "\n") + + # Final score + accuracy = (numCorrect / numAttempted * 100) if numAttempted else 0 + print(Style.BRIGHT + f"\n⏱ In {QUIZ_DURATION} seconds you attempted {numAttempted} questions.") + print(Fore.CYAN + f"✔ Correct: {numCorrect}") + print(Fore.RED + f"✘ Wrong: {numAttempted - numCorrect}") + print(Fore.YELLOW + f"🎯 Accuracy: {accuracy:.2f}%") + + # Save high score if beaten + if numCorrect > highscore: + print(Fore.GREEN + f"🏆 NEW HIGHSCORE! You beat the previous best of {highscore}.") + saveHighScore(difficulty, numCorrect) + else: + print(Fore.CYAN + f"Your highscore for {difficulty} is still {highscore}.") + + print(Fore.BLUE + "\nThanks for playing!") - # After the loop exits, the quiz is over. Show the final score: - print('In {} seconds you'.format(QUIZ_DURATION)) - print('got {} correct!'.format(numCorrect)) - print('Thanks for playing!') + +def showIntro(): + """Prints the intro animation and instructions.""" + slowPrint(ALPHABET, 0.01) + slowPrint(" Alphabetize Quiz - Advanced", 0.02) + slowPrint(ALPHABET[::-1], 0.01) + time.sleep(0.3) + + print('''\nWelcome to the Alphabetize Quiz! +Enter the correct alphabetical (or numerical) order of the shown characters. +Try to get as many correct as possible in the given time!\n''') + + +def chooseDifficulty(): + """Let the user select difficulty type.""" + print("\nChoose Difficulty:") + print("1. Letters (easy)") + print("2. Numbers (medium)") + print("3. Words (hard)") + + while True: + choice = input("> ").strip() + if choice == "1": + return "letters" + elif choice == "2": + return "numbers" + elif choice == "3": + return "words" + else: + print("Invalid choice. Enter 1, 2, or 3.") + + +def generateQuestion(difficulty): + """Generate a question based on difficulty.""" + if difficulty == "letters": + return random.sample(ALPHABET, QUESTION_SIZE) + elif difficulty == "numbers": + return random.sample(NUMBERS, QUESTION_SIZE) + elif difficulty == "words": + return random.sample( + ["CAT", "DOG", "MOON", "TREE", "PYTHON", "ZEBRA", "APPLE", "MANGO", "QUIZ", "CODE"], + QUESTION_SIZE + ) def slowPrint(text, pauseAmount=0.1): - """Slowly print out the characters in text one at a time.""" + """Slowly print out characters.""" for character in text: - # Set flush=True here so the text is immediately printed: - print(character, flush=True, end='') # end='' means no newline. - time.sleep(pauseAmount) # Pause in between each character. - print() # Print a newline. + print(character, flush=True, end="") + time.sleep(pauseAmount) + print() + + +def loadHighScore(difficulty): + """Load highscore for selected difficulty.""" + if not os.path.exists(HIGHSCORE_FILE): + return 0 + with open(HIGHSCORE_FILE, "r") as f: + scores = dict(line.strip().split(":") for line in f if ":" in line) + return int(scores.get(difficulty, 0)) + + +def saveHighScore(difficulty, score): + """Save highscore for selected difficulty.""" + scores = {} + if os.path.exists(HIGHSCORE_FILE): + with open(HIGHSCORE_FILE, "r") as f: + scores = dict(line.strip().split(":") for line in f if ":" in line) + scores[difficulty] = str(score) + with open(HIGHSCORE_FILE, "w") as f: + for k, v in scores.items(): + f.write(f"{k}:{v}\n") -# If this program was run (instead of imported), run the game: -if __name__ == '__main__': +# Run game +if __name__ == "__main__": main() diff --git a/src/gamesbyexample/clickbait.py b/src/gamesbyexample/clickbait.py index 5075628..6957723 100644 --- a/src/gamesbyexample/clickbait.py +++ b/src/gamesbyexample/clickbait.py @@ -1,11 +1,9 @@ -"""Clickbait Headline Generator, by Al Sweigart al@inventwithpython.com -A clickbait headline generator for your soulless content farm website. -This code is available at https://nostarch.com/big-book-small-python-programming -Tags: large, beginner, humor, word""" -__version__ = 0 +import tkinter as tk +from tkinter import messagebox, ttk import random +from typing import List -# Set up the constants: +# Data from your code OBJECT_PRONOUNS = ['Her', 'Him', 'Them'] POSSESIVE_PRONOUNS = ['Her', 'His', 'Their'] PERSONAL_PRONOUNS = ['She', 'He', 'They'] @@ -13,119 +11,356 @@ 'Illinois', 'Ohio', 'Georgia', 'North Carolina', 'Michigan'] NOUNS = ['Athlete', 'Clown', 'Shovel', 'Paleo Diet', 'Doctor', 'Parent', 'Cat', 'Dog', 'Chicken', 'Robot', 'Video Game', 'Avocado', - 'Plastic Straw','Serial Killer', 'Telephone Psychic'] + 'Plastic Straw', 'Serial Killer', 'Telephone Psychic'] PLACES = ['House', 'Attic', 'Bank Deposit Box', 'School', 'Basement', 'Workplace', 'Donut Shop', 'Apocalypse Bunker'] WHEN = ['Soon', 'This Year', 'Later Today', 'RIGHT NOW', 'Next Week'] +WEBSITES = ['wobsite', 'blag', 'Facebuuk', 'Googles', 'Facesbook', 'Tweedie', 'Pastagram'] +class ModernClickbaitApp(tk.Tk): + def __init__(self): + super().__init__() + self.title("🔥 Viral Headline Generator 2.0") + self.geometry("700x600") + self.resizable(True, True) + self.configure(bg='#2C2C2C') + + # Modern color scheme + self.colors = { + 'bg': '#2C2C2C', + 'card_bg': '#3A3A3A', + 'accent': '#FF6B35', + 'secondary': '#4ECDC4', + 'text': '#FFFFFF', + 'text_secondary': '#CCCCCC' + } + + self.headlines = [] + self.setup_styles() + self.create_widgets() -def main(): - print('Clickbait Headline Generator') - print('By Al Sweigart al@inventwithpython.com') - print() + def setup_styles(self): + """Configure custom styles for ttk widgets""" + style = ttk.Style() + style.theme_use('clam') + + # Configure styles + style.configure('Accent.TButton', + background=self.colors['accent'], + foreground=self.colors['text'], + borderwidth=0, + focuscolor='none') + style.configure('Secondary.TButton', + background=self.colors['secondary'], + foreground=self.colors['text'], + borderwidth=0) + style.configure('Card.TFrame', + background=self.colors['card_bg']) + style.configure('Title.TLabel', + background=self.colors['bg'], + foreground=self.colors['text'], + font=('Arial', 16, 'bold')) + style.configure('Subtitle.TLabel', + background=self.colors['bg'], + foreground=self.colors['text_secondary'], + font=('Arial', 11)) - print('Our website needs to trick people into looking at ads!') - while True: - print('Enter the number of clickbait headlines to generate:') - response = input('> ') - if not response.isdecimal(): - print('Please enter a number.') + def create_widgets(self): + # Header section + header_frame = tk.Frame(self, bg=self.colors['bg'], pady=20) + header_frame.pack(fill='x', padx=20) + + # Title with emoji + title_label = tk.Label(header_frame, + text="🔥 Viral Headline Generator 2.0", + font=('Arial', 20, 'bold'), + fg=self.colors['accent'], + bg=self.colors['bg']) + title_label.pack() + + subtitle_label = tk.Label(header_frame, + text="Generate click-worthy headlines that drive traffic!", + font=('Arial', 12), + fg=self.colors['text_secondary'], + bg=self.colors['bg']) + subtitle_label.pack(pady=(5, 0)) + + # Main card container + main_card = tk.Frame(self, bg=self.colors['card_bg'], padx=25, pady=20, relief='flat') + main_card.pack(fill='both', expand=True, padx=20, pady=10) + + # Input section + input_frame = tk.Frame(main_card, bg=self.colors['card_bg']) + input_frame.pack(fill='x', pady=(0, 15)) + + # Number of headlines input + input_label = tk.Label(input_frame, + text="Number of headlines to generate:", + font=('Arial', 11, 'bold'), + fg=self.colors['text'], + bg=self.colors['card_bg']) + input_label.pack(anchor='w') + + input_subframe = tk.Frame(input_frame, bg=self.colors['card_bg']) + input_subframe.pack(fill='x', pady=(8, 0)) + + self.num_entry = tk.Entry(input_subframe, + width=8, + font=('Arial', 12), + justify='center', + bg='#4A4A4A', + fg=self.colors['text'], + insertbackground=self.colors['text'], + relief='flat') + self.num_entry.pack(side='left') + self.num_entry.insert(0, "5") + + # Buttons container + buttons_frame = tk.Frame(main_card, bg=self.colors['card_bg']) + buttons_frame.pack(fill='x', pady=(0, 20)) + + # Generate button + gen_btn = tk.Button(buttons_frame, + text="🎯 Generate Headlines", + command=self.generate_headlines, + font=('Arial', 11, 'bold'), + bg=self.colors['accent'], + fg='white', + relief='flat', + padx=20, + pady=10, + cursor='hand2') + gen_btn.pack(side='left', padx=(0, 10)) + + # Save button + save_btn = tk.Button(buttons_frame, + text="💾 Save to File", + command=self.save_headlines, + font=('Arial', 11), + bg=self.colors['secondary'], + fg='white', + relief='flat', + padx=20, + pady=10, + cursor='hand2') + save_btn.pack(side='left', padx=(0, 10)) + + # Copy button + copy_btn = tk.Button(buttons_frame, + text="📋 Copy All", + command=self.copy_headlines, + font=('Arial', 11), + bg='#9C27B0', + fg='white', + relief='flat', + padx=20, + pady=10, + cursor='hand2') + copy_btn.pack(side='left') + + # Results section + results_label = tk.Label(main_card, + text="✨ Generated Headlines:", + font=('Arial', 12, 'bold'), + fg=self.colors['text'], + bg=self.colors['card_bg']) + results_label.pack(anchor='w', pady=(10, 8)) + + # Text widget with scrollbar + text_frame = tk.Frame(main_card, bg=self.colors['card_bg']) + text_frame.pack(fill='both', expand=True) + + # Add scrollbar + scrollbar = tk.Scrollbar(text_frame) + scrollbar.pack(side='right', fill='y') + + self.text = tk.Text(text_frame, + height=12, + wrap="word", + font=('Arial', 10), + bg='#4A4A4A', + fg=self.colors['text'], + insertbackground=self.colors['text'], + selectbackground=self.colors['accent'], + relief='flat', + padx=15, + pady=15, + yscrollcommand=scrollbar.set) + self.text.pack(side='left', fill='both', expand=True) + scrollbar.config(command=self.text.yview) + + # Footer + footer_frame = tk.Frame(self, bg=self.colors['bg'], pady=10) + footer_frame.pack(fill='x', side='bottom') + + footer_label = tk.Label(footer_frame, + text="💡 Pro Tip: Use these headlines for social media, blogs, or marketing campaigns!", + font=('Arial', 9), + fg=self.colors['text_secondary'], + bg=self.colors['bg']) + footer_label.pack() + + # Bind Enter key to generate headlines + self.bind('', lambda e: self.generate_headlines()) + + def generate_headlines(self): + self.text.delete('1.0', tk.END) + try: + count = int(self.num_entry.get()) + if count <= 0: + raise ValueError + if count > 20: + messagebox.showwarning("Too many", "Generating 20 headlines maximum.") + count = 20 + self.num_entry.delete(0, tk.END) + self.num_entry.insert(0, "20") + except ValueError: + messagebox.showerror("Invalid input", "❌ Please enter a positive whole number.") + return + + # Add loading animation + self.text.insert(tk.END, "🎬 Generating viral headlines...\n\n") + self.update() + + self.headlines = [self.generate_random_headline() for _ in range(count)] + + # Clear and display with formatting + self.text.delete('1.0', tk.END) + for i, headline in enumerate(self.headlines, 1): + # Add different emojis based on position + emoji = "🔥" if i == 1 else "🚀" if i == 2 else "💫" if i == 3 else "📈" + self.text.insert(tk.END, f"{emoji} Headline #{i}:\n", 'bold') + self.text.insert(tk.END, f" {headline}\n\n") + + # Configure tags for formatting + self.text.tag_configure('bold', font=('Arial', 10, 'bold'), foreground=self.colors['accent']) + + # Add footer message + website = random.choice(WEBSITES) + when = random.choice(WHEN).lower() + self.text.insert(tk.END, f"\n💡 Post these to {website} {when} for maximum engagement!", 'footer') + self.text.tag_configure('footer', font=('Arial', 9, 'italic'), foreground=self.colors['secondary']) + + def save_headlines(self): + if not self.headlines: + messagebox.showinfo("Info", "📝 No headlines to save. Generate some first!") + return + + filename = "viral_headlines.txt" + try: + with open(filename, 'a', encoding='utf-8') as file: + file.write("=" * 50 + "\n") + file.write(f"Viral Headlines - {self.get_timestamp()}\n") + file.write("=" * 50 + "\n") + for i, headline in enumerate(self.headlines, 1): + file.write(f"{i}. {headline}\n") + file.write("\n" + "=" * 50 + "\n\n") + messagebox.showinfo("✅ Saved", f"Headlines saved to {filename}") + except Exception as e: + messagebox.showerror("❌ Error", f"Failed to save file:\n{e}") + + def copy_headlines(self): + if not self.headlines: + messagebox.showinfo("Info", "📋 No headlines to copy. Generate some first!") + return + + headlines_text = "\n".join([f"{i+1}. {headline}" for i, headline in enumerate(self.headlines)]) + self.clipboard_clear() + self.clipboard_append(headlines_text) + messagebox.showinfo("✅ Copied", "All headlines copied to clipboard!") + + def get_timestamp(self): + from datetime import datetime + return datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + def generate_random_headline(self): + clickbait_type = random.randint(1, 10) + if clickbait_type == 1: + return self.generate_are_millenials_killing_headline() + elif clickbait_type == 2: + return self.generate_what_you_dont_know_headline() + elif clickbait_type == 3: + return self.generate_big_companies_hate_her_headline() + elif clickbait_type == 4: + return self.generate_you_wont_believe_headline() + elif clickbait_type == 5: + return self.generate_dont_want_you_to_know_headline() + elif clickbait_type == 6: + return self.generate_gift_idea_headline() + elif clickbait_type == 7: + return self.generate_reasons_why_headline() + elif clickbait_type == 8: + return self.generate_job_automated_headline() + elif clickbait_type == 9: + return self.generate_shocking_truth_headline() + elif clickbait_type == 10: + return self.generate_secret_revealed_headline() + + # Headline generator methods + def generate_are_millenials_killing_headline(self): + noun = random.choice(NOUNS) + return f"Are Millennials Killing the {noun} Industry? 🤔" + + def generate_what_you_dont_know_headline(self): + noun = random.choice(NOUNS) + plural_noun = random.choice(NOUNS) + 's' + when = random.choice(WHEN) + return f"Without This {noun}, {plural_noun} Could Kill You {when} ⚠️" + + def generate_big_companies_hate_her_headline(self): + pronoun = random.choice(OBJECT_PRONOUNS) + state = random.choice(STATES) + noun1 = random.choice(NOUNS) + noun2 = random.choice(NOUNS) + return f"Big Companies Hate {pronoun}! See How This {state} {noun1} Invented a Cheaper {noun2} 💡" + + def generate_you_wont_believe_headline(self): + state = random.choice(STATES) + noun = random.choice(NOUNS) + pronoun = random.choice(POSSESIVE_PRONOUNS) + place = random.choice(PLACES) + return f"You Won't Believe What This {state} {noun} Found in {pronoun} {place} 🤯" + + def generate_dont_want_you_to_know_headline(self): + plural_noun1 = random.choice(NOUNS) + 's' + plural_noun2 = random.choice(NOUNS) + 's' + return f"What {plural_noun1} Don't Want You To Know About {plural_noun2} 🤫" + + def generate_gift_idea_headline(self): + number = random.randint(7, 15) + noun = random.choice(NOUNS) + state = random.choice(STATES) + return f"{number} Gift Ideas to Give Your {noun} From {state} 🎁" + + def generate_reasons_why_headline(self): + number1 = random.randint(3, 19) + plural_noun = random.choice(NOUNS) + 's' + number2 = random.randint(1, number1) + return (f"{number1} Reasons Why {plural_noun} Are More Interesting Than You Think " + f"(Number {number2} Will Surprise You!) 🎯") + + def generate_job_automated_headline(self): + state = random.choice(STATES) + noun = random.choice(NOUNS) + i = random.randint(0, 2) + pronoun1 = POSSESIVE_PRONOUNS[i] + pronoun2 = PERSONAL_PRONOUNS[i] + if pronoun1 == 'Their': + return f"This {state} {noun} Didn't Think Robots Would Take {pronoun1} Job. {pronoun2} Were Wrong. 🤖" else: - numberOfHeadlines = int(response) - break # Exit the loop once a valid number is entered. - - for i in range(numberOfHeadlines): - clickbaitType = random.randint(1, 8) - - if clickbaitType == 1: - headline = generateAreMillenialsKillingHeadline() - elif clickbaitType == 2: - headline = generateWhatYouDontKnowHeadline() - elif clickbaitType == 3: - headline = generateBigCompaniesHateHerHeadline() - elif clickbaitType == 4: - headline = generateYouWontBelieveHeadline() - elif clickbaitType == 5: - headline = generateDontWantYouToKnowHeadline() - elif clickbaitType == 6: - headline = generateGiftIdeaHeadline() - elif clickbaitType == 7: - headline = generateReasonsWhyHeadline() - elif clickbaitType == 8: - headline = generateJobAutomatedHeadline() - - print(headline) - print() - - website = random.choice(['wobsite', 'blag', 'Facebuuk', 'Googles', - 'Facesbook', 'Tweedie', 'Pastagram']) - when = random.choice(WHEN).lower() - print('Post these to our', website, when, 'or you\'re fired!') - - -# Each of these functions returns a different type of headline: -def generateAreMillenialsKillingHeadline(): - noun = random.choice(NOUNS) - return 'Are Millenials Killing the {} Industry?'.format(noun) - - -def generateWhatYouDontKnowHeadline(): - noun = random.choice(NOUNS) - pluralNoun = random.choice(NOUNS) + 's' - when = random.choice(WHEN) - return 'Without This {}, {} Could Kill You {}'.format(noun, pluralNoun, when) - - -def generateBigCompaniesHateHerHeadline(): - pronoun = random.choice(OBJECT_PRONOUNS) - state = random.choice(STATES) - noun1 = random.choice(NOUNS) - noun2 = random.choice(NOUNS) - return 'Big Companies Hate {}! See How This {} {} Invented a Cheaper {}'.format(pronoun, state, noun1, noun2) - - -def generateYouWontBelieveHeadline(): - state = random.choice(STATES) - noun = random.choice(NOUNS) - pronoun = random.choice(POSSESIVE_PRONOUNS) - place = random.choice(PLACES) - return 'You Won\'t Believe What This {} {} Found in {} {}'.format(state, noun, pronoun, place) - - -def generateDontWantYouToKnowHeadline(): - pluralNoun1 = random.choice(NOUNS) + 's' - pluralNoun2 = random.choice(NOUNS) + 's' - return 'What {} Don\'t Want You To Know About {}'.format(pluralNoun1, pluralNoun2) - - -def generateGiftIdeaHeadline(): - number = random.randint(7, 15) - noun = random.choice(NOUNS) - state = random.choice(STATES) - return '{} Gift Ideas to Give Your {} From {}'.format(number, noun, state) - - -def generateReasonsWhyHeadline(): - number1 = random.randint(3, 19) - pluralNoun = random.choice(NOUNS) + 's' - # number2 should be no larger than number1: - number2 = random.randint(1, number1) - return '{} Reasons Why {} Are More Interesting Than You Think (Number {} Will Surprise You!)'.format(number1, pluralNoun, number2) - - -def generateJobAutomatedHeadline(): - state = random.choice(STATES) - noun = random.choice(NOUNS) - - i = random.randint(0, 2) - pronoun1 = POSSESIVE_PRONOUNS[i] - pronoun2 = PERSONAL_PRONOUNS[i] - if pronoun1 == 'Their': - return 'This {} {} Didn\'t Think Robots Would Take {} Job. {} Were Wrong.'.format(state, noun, pronoun1, pronoun2) - else: - return 'This {} {} Didn\'t Think Robots Would Take {} Job. {} Was Wrong.'.format(state, noun, pronoun1, pronoun2) - - -# If the program is run (instead of imported), run the game: -if __name__ == '__main__': - main() + return f"This {state} {noun} Didn't Think Robots Would Take {pronoun1} Job. {pronoun2} Was Wrong. 🤖" + + def generate_shocking_truth_headline(self): + noun = random.choice(NOUNS) + place = random.choice(PLACES) + return f"The Shocking Truth About {noun}s Hidden in Your {place} 💥" + + def generate_secret_revealed_headline(self): + state = random.choice(STATES) + plural_noun = random.choice(NOUNS) + 's' + return f"Secret Revealed: Why {state} {plural_noun} Are Taking Over the World 🌍" + + +if __name__ == "__main__": + app = ModernClickbaitApp() + app.mainloop() \ No newline at end of file diff --git a/src/gamesbyexample/clickbait_headlines.txt b/src/gamesbyexample/clickbait_headlines.txt new file mode 100644 index 0000000..02430c8 --- /dev/null +++ b/src/gamesbyexample/clickbait_headlines.txt @@ -0,0 +1,12 @@ +You Won't Believe What This New York Parent Found in Their Donut Shop +12 Gift Ideas to Give Your Paleo Diet From Ohio +6 Reasons Why Athletes Are More Interesting Than You Think (Number 2 Will Surprise You!) +You Won't Believe What This Georgia Chicken Found in Her Attic +This Georgia Serial Killer Didn't Think Robots Would Take Her Job. She Was Wrong. +Are Millennials Killing the Serial Killer Industry? +Big Companies Hate Her! See How This Pennsylvania Robot Invented a Cheaper Avocado +You Won't Believe What This Ohio Clown Found in Their Donut Shop +Secret Revealed: Why Illinois Cats Are Taking Over the World +This Illinois Video Game Didn't Think Robots Would Take His Job. He Was Wrong. +You Won't Believe What This Texas Paleo Diet Found in His School +What Chickens Don't Want You To Know About Shovels diff --git a/src/gamesbyexample/cosmic.py b/src/gamesbyexample/cosmic.py new file mode 100644 index 0000000..8642d10 --- /dev/null +++ b/src/gamesbyexample/cosmic.py @@ -0,0 +1,531 @@ +import tkinter as tk +import random +import math +from typing import List, Tuple + +class SpaceShooter: + def __init__(self, root): + self.root = root + self.root.title("🚀 Cosmic Defender") + self.root.resizable(False, False) + self.root.configure(bg="#0a0a2a") + + # Game constants + self.WIDTH = 800 + self.HEIGHT = 600 + self.PLAYER_SPEED = 8 + self.BULLET_SPEED = 12 + self.ENEMY_SPEED = 3 + self.POWERUP_DURATION = 300 # frames + + # Colors + self.BG_COLOR = "#0a0a2a" + self.PLAYER_COLOR = "#4FC3F7" + self.ENEMY_COLOR = "#FF5252" + self.BULLET_COLOR = "#FFEB3B" + self.POWERUP_COLOR = "#69F0AE" + self.TEXT_COLOR = "white" + self.STAR_COLORS = ["#FFFFFF", "#FFEB3B", "#4FC3F7", "#FF5252"] + + # Game state + self.score = 0 + self.high_score = 0 + self.lives = 3 + self.level = 1 + self.game_running = False + self.powerup_active = False + self.powerup_timer = 0 + self.powerup_type = None + + # Game objects + self.player = None + self.bullets: List[dict] = [] + self.enemies: List[dict] = [] + self.powerups: List[dict] = [] + self.particles: List[dict] = [] + self.stars: List[dict] = [] + + # Initialize UI and game + self.setup_ui() + self.init_stars() + self.reset_game() + + def setup_ui(self): + # Header + header_frame = tk.Frame(self.root, bg=self.BG_COLOR) + header_frame.pack(pady=10) + + self.title_label = tk.Label( + header_frame, + text="🚀 Cosmic Defender", + font=("Arial", 24, "bold"), + fg=self.TEXT_COLOR, + bg=self.BG_COLOR + ) + self.title_label.pack() + + # Stats display + stats_frame = tk.Frame(self.root, bg=self.BG_COLOR) + stats_frame.pack(pady=5) + + self.stats_label = tk.Label( + stats_frame, + text="Score: 0 | High Score: 0 | Lives: 3 | Level: 1", + font=("Arial", 12), + fg=self.TEXT_COLOR, + bg=self.BG_COLOR + ) + self.stats_label.pack() + + # Game canvas + self.canvas = tk.Canvas( + self.root, + width=self.WIDTH, + height=self.HEIGHT, + bg=self.BG_COLOR, + highlightthickness=0 + ) + self.canvas.pack(pady=10) + + # Controls info + controls_frame = tk.Frame(self.root, bg=self.BG_COLOR) + controls_frame.pack(pady=5) + + controls_text = "🎮 Controls: Arrow Keys to move | Space to shoot | P to pause | R to restart" + self.controls_label = tk.Label( + controls_frame, + text=controls_text, + font=("Arial", 10), + fg="#AAAAAA", + bg=self.BG_COLOR + ) + self.controls_label.pack() + + # Message display + self.message_label = tk.Label( + self.root, + text="Press SPACE to start!", + font=("Arial", 14, "bold"), + fg="#FFD700", + bg=self.BG_COLOR + ) + self.message_label.pack(pady=5) + + # Bind keys + self.root.bind('', self.move_player) + self.root.bind('', self.move_player) + self.root.bind('', self.move_player) + self.root.bind('', self.move_player) + self.root.bind('', self.shoot) + self.root.bind('p', self.toggle_pause) + self.root.bind('P', self.toggle_pause) + self.root.bind('r', self.reset_game) + self.root.bind('R', self.reset_game) + + def init_stars(self): + """Initialize background stars""" + self.stars = [] + for _ in range(100): + star = { + 'x': random.randint(0, self.WIDTH), + 'y': random.randint(0, self.HEIGHT), + 'size': random.uniform(0.5, 2), + 'speed': random.uniform(0.5, 2), + 'color': random.choice(self.STAR_COLORS) + } + self.stars.append(star) + + def reset_game(self, event=None): + """Reset the game to initial state""" + self.player = {'x': self.WIDTH // 2, 'y': self.HEIGHT - 80, 'width': 50, 'height': 40} + self.bullets = [] + self.enemies = [] + self.powerups = [] + self.particles = [] + self.score = 0 + self.lives = 3 + self.level = 1 + self.game_running = False + self.powerup_active = False + self.powerup_timer = 0 + self.message_label.config(text="Press SPACE to start!") + self.update_stats() + self.draw_game() + + def update_stats(self): + """Update the stats display""" + powerup_text = "" + if self.powerup_active: + powerup_text = f" | 🔥 {self.powerup_type.upper()}" + + self.stats_label.config( + text=f"Score: {self.score} | High Score: {self.high_score} | Lives: {self.lives} | Level: {self.level}{powerup_text}" + ) + + def draw_game(self): + """Draw the current game state""" + self.canvas.delete("all") + + # Draw stars (parallax background) + for star in self.stars: + self.canvas.create_oval( + star['x'], star['y'], + star['x'] + star['size'], star['y'] + star['size'], + fill=star['color'], outline="" + ) + + # Draw player (spaceship) + if self.player: + # Spaceship body + points = [ + self.player['x'], self.player['y'] - 20, + self.player['x'] - 25, self.player['y'] + 20, + self.player['x'] + 25, self.player['y'] + 20 + ] + self.canvas.create_polygon(points, fill=self.PLAYER_COLOR, outline="white", width=2) + + # Cockpit + self.canvas.create_oval( + self.player['x'] - 8, self.player['y'] - 10, + self.player['x'] + 8, self.player['y'] + 5, + fill="#1A237E", outline="white", width=1 + ) + + # Engines + engine_color = "#FF6D00" if random.random() > 0.7 else "#FF9800" + self.canvas.create_polygon([ + self.player['x'] - 15, self.player['y'] + 20, + self.player['x'] - 5, self.player['y'] + 35, + self.player['x'] + 5, self.player['y'] + 35, + self.player['x'] + 15, self.player['y'] + 20 + ], fill=engine_color, outline="") + + # Draw bullets + for bullet in self.bullets: + self.canvas.create_oval( + bullet['x'] - 3, bullet['y'] - 8, + bullet['x'] + 3, bullet['y'] + 8, + fill=self.BULLET_COLOR, outline="" + ) + + # Bullet trail + for i in range(3): + self.canvas.create_oval( + bullet['x'] - 1, bullet['y'] + 8 + i * 4, + bullet['x'] + 1, bullet['y'] + 12 + i * 4, + fill="#FFA000", outline="" + ) + + # Draw enemies + for enemy in self.enemies: + # Enemy ship + points = [ + enemy['x'], enemy['y'] + 20, + enemy['x'] - 20, enemy['y'] - 10, + enemy['x'] - 10, enemy['y'] - 20, + enemy['x'] + 10, enemy['y'] - 20, + enemy['x'] + 20, enemy['y'] - 10 + ] + self.canvas.create_polygon(points, fill=self.ENEMY_COLOR, outline="#B71C1C", width=2) + + # Enemy details + self.canvas.create_oval( + enemy['x'] - 6, enemy['y'] - 5, + enemy['x'] + 6, enemy['y'] + 5, + fill="#1A237E", outline="" + ) + + # Draw powerups + for powerup in self.powerups: + color = self.POWERUP_COLOR + if powerup['type'] == 'rapid': + color = "#FF4081" + elif powerup['type'] == 'shield': + color = "#40C4FF" + + self.canvas.create_rectangle( + powerup['x'] - 15, powerup['y'] - 15, + powerup['x'] + 15, powerup['y'] + 15, + fill=color, outline="white", width=2 + ) + + # Powerup icon + if powerup['type'] == 'rapid': + self.canvas.create_text(powerup['x'], powerup['y'], text="⚡", font=("Arial", 12)) + elif powerup['type'] == 'shield': + self.canvas.create_text(powerup['x'], powerup['y'], text="🛡️", font=("Arial", 12)) + else: + self.canvas.create_text(powerup['x'], powerup['y'], text="💎", font=("Arial", 12)) + + # Draw particles + for particle in self.particles: + self.canvas.create_oval( + particle['x'] - particle['size'], particle['y'] - particle['size'], + particle['x'] + particle['size'], particle['y'] + particle['size'], + fill=particle['color'], outline="" + ) + + # Draw player shield if active + if self.powerup_active and self.powerup_type == 'shield': + self.canvas.create_oval( + self.player['x'] - 35, self.player['y'] - 35, + self.player['x'] + 35, self.player['y'] + 45, + outline="#40C4FF", width=3, dash=(5, 2) + ) + + def move_player(self, event): + """Move the player based on key press""" + if not self.game_running: + return + + if event.keysym == 'Left' and self.player['x'] > 40: + self.player['x'] -= self.PLAYER_SPEED + elif event.keysym == 'Right' and self.player['x'] < self.WIDTH - 40: + self.player['x'] += self.PLAYER_SPEED + elif event.keysym == 'Up' and self.player['y'] > 50: + self.player['y'] -= self.PLAYER_SPEED + elif event.keysym == 'Down' and self.player['y'] < self.HEIGHT - 50: + self.player['y'] += self.PLAYER_SPEED + + def shoot(self, event=None): + """Player shoots a bullet""" + if not self.game_running: + self.start_game() + return + + bullet_speed = self.BULLET_SPEED + if self.powerup_active and self.powerup_type == 'rapid': + bullet_speed *= 1.5 + + self.bullets.append({ + 'x': self.player['x'], + 'y': self.player['y'] - 20, + 'speed': bullet_speed + }) + + # Add muzzle flash particles + for _ in range(5): + self.particles.append({ + 'x': self.player['x'] + random.randint(-10, 10), + 'y': self.player['y'] - 15, + 'vx': random.uniform(-2, 2), + 'vy': random.uniform(-1, 1), + 'size': random.uniform(1, 3), + 'color': random.choice(["#FFEB3B", "#FF9800", "#FF6D00"]), + 'life': 20 + }) + + def start_game(self): + """Start the game""" + self.game_running = True + self.message_label.config(text="") + self.game_loop() + + def toggle_pause(self, event=None): + """Toggle game pause state""" + if self.game_running: + self.game_running = False + self.message_label.config(text="⏸️ Game Paused - Press P to continue") + else: + self.game_running = True + self.message_label.config(text="") + self.game_loop() + + def spawn_enemy(self): + """Spawn a new enemy""" + enemy_types = ['basic', 'fast', 'tank'] + weights = [0.7, 0.2, 0.1] # Probability weights + + enemy_type = random.choices(enemy_types, weights=weights)[0] + + if enemy_type == 'basic': + speed = self.ENEMY_SPEED + self.level * 0.2 + health = 1 + elif enemy_type == 'fast': + speed = self.ENEMY_SPEED * 1.5 + self.level * 0.3 + health = 1 + else: # tank + speed = self.ENEMY_SPEED * 0.7 + self.level * 0.1 + health = 3 + + self.enemies.append({ + 'x': random.randint(50, self.WIDTH - 50), + 'y': random.randint(-100, -40), + 'speed': speed, + 'health': health, + 'type': enemy_type + }) + + def spawn_powerup(self): + """Spawn a powerup with chance""" + if random.random() < 0.02: # 2% chance per frame + powerup_types = ['rapid', 'shield', 'score'] + powerup_type = random.choice(powerup_types) + + self.powerups.append({ + 'x': random.randint(30, self.WIDTH - 30), + 'y': -20, + 'speed': 2, + 'type': powerup_type + }) + + def create_explosion(self, x, y, color="#FF5252"): + """Create explosion particles""" + for _ in range(15): + self.particles.append({ + 'x': x, + 'y': y, + 'vx': random.uniform(-3, 3), + 'vy': random.uniform(-3, 3), + 'size': random.uniform(2, 5), + 'color': color, + 'life': 30 + }) + + def update_particles(self): + """Update and remove old particles""" + new_particles = [] + for particle in self.particles: + particle['x'] += particle['vx'] + particle['y'] += particle['vy'] + particle['life'] -= 1 + + if particle['life'] > 0: + new_particles.append(particle) + self.particles = new_particles + + def update_stars(self): + """Update star positions for parallax effect""" + for star in self.stars: + star['y'] += star['speed'] + if star['y'] > self.HEIGHT: + star['y'] = 0 + star['x'] = random.randint(0, self.WIDTH) + + def game_loop(self): + """Main game loop""" + if not self.game_running: + return + + # Update stars + self.update_stars() + + # Spawn enemies based on level + spawn_chance = 0.03 + (self.level * 0.01) + if random.random() < spawn_chance: + self.spawn_enemy() + + # Spawn powerups + self.spawn_powerup() + + # Update bullets + new_bullets = [] + for bullet in self.bullets: + bullet['y'] -= bullet['speed'] + if bullet['y'] > 0: + new_bullets.append(bullet) + self.bullets = new_bullets + + # Update enemies and check collisions + new_enemies = [] + for enemy in self.enemies: + enemy['y'] += enemy['speed'] + + # Check if enemy hit player + if (abs(enemy['x'] - self.player['x']) < 30 and + abs(enemy['y'] - self.player['y']) < 30): + if not self.powerup_active or self.powerup_type != 'shield': + self.lives -= 1 + self.create_explosion(self.player['x'], self.player['y'], "#4FC3F7") + if self.lives <= 0: + self.game_over() + return + self.create_explosion(enemy['x'], enemy['y']) + continue + + # Check bullet collisions + hit = False + for bullet in self.bullets: + if (abs(bullet['x'] - enemy['x']) < 20 and + abs(bullet['y'] - enemy['y']) < 20): + enemy['health'] -= 1 + self.create_explosion(bullet['x'], bullet['y'], "#FFEB3B") + if enemy['health'] <= 0: + self.score += 10 * self.level + self.create_explosion(enemy['x'], enemy['y']) + hit = True + break + + if not hit and enemy['y'] < self.HEIGHT + 50: + new_enemies.append(enemy) + + self.enemies = new_enemies + + # Update powerups + new_powerups = [] + for powerup in self.powerups: + powerup['y'] += powerup['speed'] + + # Check if player collected powerup + if (abs(powerup['x'] - self.player['x']) < 30 and + abs(powerup['y'] - self.player['y']) < 30): + self.activate_powerup(powerup['type']) + self.create_explosion(powerup['x'], powerup['y'], self.POWERUP_COLOR) + elif powerup['y'] < self.HEIGHT + 20: + new_powerups.append(powerup) + + self.powerups = new_powerups + + # Update powerup timer + if self.powerup_active: + self.powerup_timer -= 1 + if self.powerup_timer <= 0: + self.powerup_active = False + self.powerup_type = None + + # Update particles + self.update_particles() + + # Level up + if self.score >= self.level * 100: + self.level += 1 + self.message_label.config(text=f"🚀 Level {self.level}! Enemies are faster!", fg="#FFD700") + self.root.after(2000, lambda: self.message_label.config(text="")) + + # Update high score + if self.score > self.high_score: + self.high_score = self.score + + self.update_stats() + self.draw_game() + + # Continue game loop + if self.game_running: + self.root.after(16, self.game_loop) # ~60 FPS + + def activate_powerup(self, powerup_type): + """Activate a powerup""" + self.powerup_active = True + self.powerup_type = powerup_type + self.powerup_timer = self.POWERUP_DURATION + + if powerup_type == 'rapid': + self.message_label.config(text="⚡ Rapid Fire Activated!", fg="#FF4081") + elif powerup_type == 'shield': + self.message_label.config(text="🛡️ Shield Activated!", fg="#40C4FF") + else: # score + self.score += 50 + self.message_label.config(text="💎 +50 Points!", fg="#69F0AE") + + self.root.after(1500, lambda: self.message_label.config(text="")) + + def game_over(self): + """Handle game over""" + self.game_running = False + self.message_label.config(text="💥 Game Over! Press R to restart", fg="#FF5252") + self.create_explosion(self.player['x'], self.player['y'], "#4FC3F7") + +if __name__ == "__main__": + root = tk.Tk() + game = SpaceShooter(root) + root.mainloop() \ No newline at end of file diff --git a/src/gamesbyexample/crawler.py b/src/gamesbyexample/crawler.py new file mode 100644 index 0000000..4c82cd2 --- /dev/null +++ b/src/gamesbyexample/crawler.py @@ -0,0 +1,360 @@ +import tkinter as tk +from tkinter import messagebox +import random + +WIDTH = 12 +HEIGHT = 10 +FOW_RADIUS = 3 + +# Emoji tiles +TILE_FLOOR = '·' +TILE_WALL = '🧱' +TILE_PLAYER = '🧙' +TILE_ENEMY = '👹' +TILE_TREASURE = '💰' +TILE_TRAP = '🕳️' +TILE_HEALTH = '❤️' + +DIRECTIONS = {'Up': (-1, 0), 'Down': (1, 0), 'Left': (0, -1), 'Right': (0, 1)} + +class GameApp(tk.Tk): + def __init__(self): + super().__init__() + self.title("🏰 Roguelike Dungeon Crawler 🏰") + self.resizable(False, False) + self.geometry("600x700") + self.configure(bg="#2C2C2C") + + # Style configuration + self.style = { + "bg": "#2C2C2C", + "fg": "white", + "font_title": ("Arial", 18, "bold"), + "font_status": ("Arial", 12), + "font_map": ("Segoe UI Emoji", 20), + "highlight": "#FFD700", + "danger": "#FF6B6B", + "success": "#4ECDC4" + } + + self.game = self.new_game() + + # Header + header_frame = tk.Frame(self, bg=self.style["bg"]) + header_frame.pack(pady=10) + + self.title_label = tk.Label(header_frame, text="🏰 Roguelike Dungeon Crawler 🏰", + font=self.style["font_title"], + bg=self.style["bg"], fg=self.style["highlight"]) + self.title_label.pack() + + # Map display + map_frame = tk.Frame(self, bg=self.style["bg"]) + map_frame.pack(pady=10) + + self.map_text = tk.Text(map_frame, width=WIDTH+2, height=HEIGHT, + font=self.style["font_map"], + bg="black", fg="white", + borderwidth=2, relief="solid", + spacing2=2) + self.map_text.pack() + + # Status display + status_frame = tk.Frame(self, bg=self.style["bg"]) + status_frame.pack(pady=10, fill="x") + + # Health bar + health_frame = tk.Frame(status_frame, bg=self.style["bg"]) + health_frame.pack(fill="x", padx=20) + + self.health_label = tk.Label(health_frame, text="❤️ Health:", + font=self.style["font_status"], + bg=self.style["bg"], fg="white") + self.health_label.pack(side="left") + + self.health_bar = tk.Label(health_frame, text="", + font=self.style["font_status"], + bg=self.style["bg"], fg=self.style["danger"]) + self.health_bar.pack(side="left", padx=(5, 0)) + + # Inventory + inventory_frame = tk.Frame(status_frame, bg=self.style["bg"]) + inventory_frame.pack(fill="x", padx=20, pady=5) + + self.inventory_label = tk.Label(inventory_frame, text="🎒 Inventory:", + font=self.style["font_status"], + bg=self.style["bg"], fg="white") + self.inventory_label.pack(side="left") + + self.inventory_display = tk.Label(inventory_frame, text="", + font=self.style["font_status"], + bg=self.style["bg"], fg=self.style["success"]) + self.inventory_display.pack(side="left", padx=(5, 0)) + + # Message display + message_frame = tk.Frame(self, bg=self.style["bg"], height=60) + message_frame.pack(pady=10, fill="x", padx=20) + message_frame.pack_propagate(False) + + self.message_label = tk.Label(message_frame, text="", + font=self.style["font_status"], + bg="#1A1A1A", fg="white", + wraplength=500, justify="center", + borderwidth=2, relief="solid", padx=10, pady=10) + self.message_label.pack(fill="both", expand=True) + + # Controls help + controls_frame = tk.Frame(self, bg=self.style["bg"]) + controls_frame.pack(pady=10) + + controls_text = "🎮 Controls: Arrow Keys/WASD to move | I for Inventory" + self.controls_label = tk.Label(controls_frame, text=controls_text, + font=("Arial", 10), + bg=self.style["bg"], fg="#AAAAAA") + self.controls_label.pack() + + # Bind keys + self.bind('', self.key_handler) + self.bind('', self.key_handler) + self.bind('', self.key_handler) + self.bind('', self.key_handler) + self.bind('w', self.key_handler) + self.bind('a', self.key_handler) + self.bind('s', self.key_handler) + self.bind('d', self.key_handler) + self.bind('i', self.key_handler) + self.bind('r', self.key_handler) # Restart game + + self.update_ui() + + def new_game(self): + dungeon, rooms = self.make_dungeon() + px, py = random.choice(rooms) + enemies = [] + free_cells = [(i, j) for i in range(HEIGHT) for j in range(WIDTH) + if dungeon[i][j] == TILE_FLOOR and (i, j) != (px, py)] + + # Add enemies, treasures, traps, and health potions + for _ in range(4): + ex, ey = random.choice(free_cells) + free_cells.remove((ex, ey)) + enemies.append({'pos': [ex, ey], 'hp': 5, 'alive': True}) + + return { + 'dungeon': dungeon, + 'player': {'pos': [px, py], 'hp': 15, 'max_hp': 15, 'inventory': []}, + 'enemies': enemies, + 'msg': 'Welcome! Explore the dungeon and collect treasure!', + 'game_over': False + } + + def make_dungeon(self): + dungeon = [[TILE_WALL]*WIDTH for _ in range(HEIGHT)] + rooms = [] + + # Generate rooms + for _ in range(random.randint(4, 6)): + w, h = random.randint(3, 5), random.randint(2, 4) + x, y = random.randint(1, HEIGHT-h-1), random.randint(1, WIDTH-w-1) + for i in range(x, x+h): + for j in range(y, y+w): + dungeon[i][j] = TILE_FLOOR + rooms.append((x+h//2, y+w//2)) + + # Connect rooms with corridors + for i in range(len(rooms)-1): + x1, y1 = rooms[i] + x2, y2 = rooms[i+1] + for i in range(min(x1, x2), max(x1, x2)+1): + dungeon[i][y1] = TILE_FLOOR + for j in range(min(y1, y2), max(y1, y2)+1): + dungeon[x2][j] = TILE_FLOOR + + # Place items + free_cells = [(i, j) for i in range(HEIGHT) for j in range(WIDTH) + if dungeon[i][j] == TILE_FLOOR] + + # Treasures + treasures = random.sample(free_cells, k=3) + for tx, ty in treasures: + dungeon[tx][ty] = 'T' + free_cells.remove((tx, ty)) + + # Traps + traps = random.sample(free_cells, k=3) + for tx, ty in traps: + dungeon[tx][ty] = 'X' + free_cells.remove((tx, ty)) + + # Health potions + healths = random.sample(free_cells, k=2) + for hx, hy in healths: + dungeon[hx][hy] = 'H' + free_cells.remove((hx, hy)) + + return dungeon, rooms + + def update_ui(self): + self.map_text.delete('1.0', tk.END) + px, py = self.game['player']['pos'] + + # Create map with fog of war + for x in range(HEIGHT): + row = '' + for y in range(WIDTH): + # Fog of war - only show tiles within radius + if abs(x - px) + abs(y - py) > FOW_RADIUS: + row += ' ' # Empty space for fog + continue + + tile = self.game['dungeon'][x][y] + + # Player + if (x, y) == (px, py): + row += TILE_PLAYER + ' ' + # Enemies + elif (x, y) in [tuple(e['pos']) for e in self.game['enemies'] if e['alive']]: + row += TILE_ENEMY + ' ' + # Special tiles + elif tile == 'T': + row += TILE_TREASURE + ' ' + elif tile == 'X': + row += TILE_TRAP + ' ' + elif tile == 'H': + row += TILE_HEALTH + ' ' + else: + row += tile + ' ' + + self.map_text.insert(tk.END, row + '\n') + + # Update health bar with visual representation + hp = self.game['player']['hp'] + max_hp = self.game['player']['max_hp'] + health_bar = '❤️' * hp + '♡' * (max_hp - hp) + self.health_bar.config(text=f"{hp}/{max_hp} {health_bar}") + + # Update inventory + inv = self.game['player']['inventory'] + treasure_count = inv.count('treasure') + health_count = inv.count('health_potion') + inventory_text = f"💰×{treasure_count} ❤️×{health_count}" + self.inventory_display.config(text=inventory_text) + + # Update message + self.message_label.config(text=self.game['msg']) + + # Game over check + if self.game['player']['hp'] <= 0 and not self.game['game_over']: + self.game['game_over'] = True + self.game['msg'] = "💀 You died! Game over. Press R to restart." + self.update_ui() + messagebox.showinfo("Game Over", "You have been defeated! Press R to restart.") + + def key_handler(self, event): + if self.game['game_over'] and event.keysym.lower() == 'r': + self.game = self.new_game() + self.update_ui() + return + + if self.game['game_over']: + return + + key = event.keysym.lower() + if key in ['w', 'a', 's', 'd', 'up', 'down', 'left', 'right']: + self.player_move(key) + elif key == 'i': + self.show_inventory() + else: + self.game['msg'] = "Use arrow keys/WASD to move, I for inventory" + self.update_ui() + + def player_move(self, key): + mapping = { + 'w': (-1, 0), 'up': (-1, 0), + 's': (1, 0), 'down': (1, 0), + 'a': (0, -1), 'left': (0, -1), + 'd': (0, 1), 'right': (0, 1) + } + dx, dy = mapping[key] + px, py = self.game['player']['pos'] + nx, ny = px+dx, py+dy + + if 0 <= nx < HEIGHT and 0 <= ny < WIDTH and self.game['dungeon'][nx][ny] != TILE_WALL: + # Check for enemy at destination + enemy_found = None + for e in self.game['enemies']: + if e['alive'] and e['pos'] == [nx, ny]: + enemy_found = e + break + + if enemy_found: + enemy_found['hp'] -= 4 + self.game['msg'] = "⚔️ You hit the enemy for 4 damage!" + if enemy_found['hp'] <= 0: + enemy_found['alive'] = False + self.game['msg'] = "🎯 You defeated the enemy!" + else: + # Move player + self.game['player']['pos'] = [nx, ny] + tile = self.game['dungeon'][nx][ny] + + if tile == 'T': + self.game['player']['inventory'].append('treasure') + self.game['dungeon'][nx][ny] = TILE_FLOOR + self.game['msg'] = "💰 You found treasure!" + elif tile == 'X': + self.game['player']['hp'] -= 3 + self.game['dungeon'][nx][ny] = TILE_FLOOR + self.game['msg'] = "💥 You stepped on a trap! Lost 3 HP!" + elif tile == 'H': + self.game['player']['hp'] = min(self.game['player']['max_hp'], self.game['player']['hp'] + 5) + self.game['player']['inventory'].append('health_potion') + self.game['dungeon'][nx][ny] = TILE_FLOOR + self.game['msg'] = "❤️ You found a health potion! Restored 5 HP!" + else: + self.game['msg'] = "Exploring..." + else: + self.game['msg'] = "🚧 A wall blocks your path." + + self.enemy_turn() + self.update_ui() + + def enemy_turn(self): + if self.game['player']['hp'] <= 0: + return + + px, py = self.game['player']['pos'] + for e in self.game['enemies']: + if not e['alive']: + continue + ex, ey = e['pos'] + dx = max(-1, min(1, px - ex)) + dy = max(-1, min(1, py - ey)) + newpos = [ex+dx, ey+dy] + + # Check if move is valid + if (0 <= newpos[0] < HEIGHT and 0 <= newpos[1] < WIDTH and + self.game['dungeon'][newpos[0]][newpos[1]] != TILE_WALL and + newpos != [px, py] and + not any(ev['alive'] and ev['pos'] == newpos for ev in self.game['enemies'])): + e['pos'] = newpos + + # Attack player if adjacent + if abs(px - e['pos'][0]) + abs(py - e['pos'][1]) == 1: + self.game['player']['hp'] -= 2 + if self.game['player']['hp'] > 0: + self.game['msg'] = "👹 An enemy hit you for 2 damage!" + + def show_inventory(self): + inv = self.game['player']['inventory'] + treasure_count = inv.count('treasure') + health_count = inv.count('health_potion') + + if treasure_count == 0 and health_count == 0: + self.game['msg'] = "🎒 Your inventory is empty." + else: + self.game['msg'] = f"🎒 Inventory: {treasure_count} treasure(s), {health_count} health potion(s)" + self.update_ui() + +if __name__ == '__main__': + GameApp().mainloop() \ No newline at end of file diff --git a/src/gamesbyexample/viral_headlines.txt b/src/gamesbyexample/viral_headlines.txt new file mode 100644 index 0000000..caba425 --- /dev/null +++ b/src/gamesbyexample/viral_headlines.txt @@ -0,0 +1,32 @@ +================================================== +Viral Headlines - 2025-10-30 22:13:09 +================================================== +1. The Shocking Truth About Paleo Diets Hidden in Your Bank Deposit Box 💥 +2. Secret Revealed: Why Illinois Athletes Are Taking Over the World 🌍 +3. This Florida Shovel Didn't Think Robots Would Take Their Job. They Were Wrong. 🤖 +4. 13 Reasons Why Plastic Straws Are More Interesting Than You Think (Number 13 Will Surprise You!) 🎯 +5. Are Millennials Killing the Shovel Industry? 🤔 + +================================================== + +================================================== +Viral Headlines - 2025-10-30 22:13:29 +================================================== +1. Without This Chicken, Serial Killers Could Kill You Soon ⚠️ +2. Big Companies Hate Him! See How This Illinois Shovel Invented a Cheaper Avocado 💡 +3. Secret Revealed: Why Illinois Paleo Diets Are Taking Over the World 🌍 +4. Big Companies Hate Him! See How This New York Clown Invented a Cheaper Dog 💡 +5. Without This Robot, Athletes Could Kill You Soon ⚠️ +6. This Illinois Paleo Diet Didn't Think Robots Would Take His Job. He Was Wrong. 🤖 +7. 17 Reasons Why Athletes Are More Interesting Than You Think (Number 5 Will Surprise You!) 🎯 +8. Without This Chicken, Parents Could Kill You Soon ⚠️ +9. Without This Video Game, Clowns Could Kill You Next Week ⚠️ +10. The Shocking Truth About Plastic Straws Hidden in Your Donut Shop 💥 +11. This Texas Shovel Didn't Think Robots Would Take Their Job. They Were Wrong. 🤖 +12. What Dogs Don't Want You To Know About Serial Killers 🤫 +13. 5 Reasons Why Robots Are More Interesting Than You Think (Number 1 Will Surprise You!) 🎯 +14. Without This Paleo Diet, Avocados Could Kill You This Year ⚠️ +15. This Illinois Clown Didn't Think Robots Would Take His Job. He Was Wrong. 🤖 + +================================================== +