default_max_attempts_per_step: 9 sections: - section_id: "section_1" title: "Killer Squares" steps: - step_id: "step_0" title: "Introduction" content_blocks: - | Welcome to Killer Squares! 🎮 In this game, both you and the AI will secretly choose a square. Then, you will attempt to "kill" a square. If you hit the AI's secret spot, you win! If the AI hits your secret spot, you lose. If nobody hits, the game continues. The board positions are numbered 0 to 8 as follows: ``` 0 | 1 | 2 --------- 3 | 4 | 5 --------- 6 | 7 | 8 ``` - step_id: "step_1" title: "Choose Your Secret Spot" question: "Choose a secret spot (0-8) for this round." tokens_for_ai: | If the user wants to exit, categorize as 'exit'. If the move is valid, categorize as 'valid_move'. If the move is invalid, categorize as 'invalid_move'. feedback_tokens_for_ai: | DO NOT TELL THE AI SECRET. If there is an error in the metadata the move was likely invalid. Always speak in first person. DO NOT START WITH "ai_move:". On a new line, provide feedback on the user's move. If the move is valid, proceed to the next step. If the move is invalid, prompt the user to try again. processing_script: | import random # Initialize or retrieve the game state user_secret = metadata.get("user_secret", None) ai_secret = random.randint(0, 8) # Get the user's secret spot try: user_secret = int(metadata.get("user_secret")) except (IndexError, ValueError) as e: user_secret = -1 # Check if the move is valid if 0 <= user_secret < 9: script_result = { "metadata": { "user_secret": user_secret, "ai_secret": ai_secret, } } else: script_result = { "error": f"Invalid secret spot: {metadata.get('user_secret')}", "metadata": {} } buckets: - valid_move - invalid_move - restart - exit transitions: valid_move: run_processing_script: True ai_feedback: tokens_for_ai: "You've chosen your secret spot. Now, let's move to the killing round." metadata_add: user_secret: "the-users-response" next_section_and_step: "section_1:step_2" invalid_move: ai_feedback: tokens_for_ai: "That move is invalid. Please choose a position between 0 and 8." metadata_add: user_secret: "the-users-response" next_section_and_step: "section_1:step_1" exit: next_section_and_step: "section_1:step_3" restart: ai_feedback: tokens_for_ai: "Restarting the game. Let's start fresh!" metadata_clear: True next_section_and_step: "section_1:step_0" - step_id: "step_2" title: "Kill a Square" question: "Choose a square to kill (0-8)." tokens_for_ai: | If the user wants to restart or play again, categorize as 'restart'. If the user wants to exit, categorize as 'exit'. If the move is valid, categorize as 'valid_move'. If the move is invalid, categorize as 'invalid_move'. feedback_tokens_for_ai: | DO NOT reveal the AI's secret spot until game_over = True. ALWAYS speak in first person. DO NOT START WITH "ai_move:". If there is an error in the metadata, the move was likely invalid. On a new line, provide feedback on the user's move: - If the move is valid, check if the user's shot hit my (AI's) secret spot (ai_secret). - If the user's shot hits my secret spot, say: "You hit my secret spot!" - If the user's shot misses, say: "You missed my secret spot." If the move is invalid, prompt the user to try again. My move is the last item in the ai_shots list. For example, if ai_shots = [5, 3], my move is 3. Announce my move: "I shoot at position [my move]." If game_over = True, determine the winner: - If user_wins = True, say: "Congratulations! You hit my secret spot and won the round!" - If ai_wins = True, say: "I hit your secret spot and won the round!" If game_over = True, describe the carnage of the final strike. If game_over = True, suggest: "Would you like to restart and play again, or would you prefer to exit?" processing_script: | import random import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import io import base64 # Retrieve the game state user_secret = metadata.get("user_secret") ai_secret = metadata.get("ai_secret") user_shots = metadata.get("user_shots", []) ai_shots = metadata.get("ai_shots", []) game_over = metadata.get("game_over", False) # Get the user's kill move try: user_kill = int(metadata.get("user_kill")) except (IndexError, ValueError) as e: user_kill = -1 if game_over: script_result = {} elif 0 <= user_kill < 9: # the move is valid. user_shots.append(user_kill) if user_kill == ai_secret: game_over = True user_wins = True ai_wins = False draw = False user_title = "You Win!" ai_title = "AI's Moves" else: # AI makes a move, avoiding its own secret spot available_positions = [] for i in range(9): if i not in ai_shots and i != ai_secret: available_positions.append(i) ai_kill = random.choice(available_positions) if available_positions else None if ai_kill is not None: ai_shots.append(ai_kill) if ai_kill == user_secret: game_over = True user_wins = False ai_wins = True draw = False user_title = "Your Moves" ai_title = "AI Wins!" else: game_over = False user_wins = False ai_wins = False draw = False user_title = "Your Moves" ai_title = "AI's Moves" else: game_over = True user_wins = False ai_wins = False draw = True user_title = "Your Moves" ai_title = "It's a Draw!" # Plot the boards fig, axs = plt.subplots(1, 2, figsize=(6, 3)) fig.suptitle("Killer Squares", fontsize=16) fig.tight_layout(h_pad=4) # User's board axs[0].set_xlim(0, 3) axs[0].set_ylim(0, 3) axs[0].set_xticks([]) axs[0].set_yticks([]) axs[0].grid(True) axs[0].set_title(user_title, fontsize=12) for i in range(9): x = i % 3 y = 2 - i // 3 axs[0].text(x + 0.5, y + 0.5, str(i), fontsize=12, ha='center', va='center', color='gray') for user_kill in user_shots: ux, uy = user_kill % 3, 2 - user_kill // 3 axs[0].text(ux + 0.5, uy + 0.5, 'X', fontsize=24, ha='center', va='center', color='red') # AI's board axs[1].set_xlim(0, 3) axs[1].set_ylim(0, 3) axs[1].set_xticks([]) axs[1].set_yticks([]) axs[1].grid(True) axs[1].set_title(ai_title, fontsize=12) for i in range(9): x = i % 3 y = 2 - i // 3 axs[1].text(x + 0.5, y + 0.5, str(i), fontsize=12, ha='center', va='center', color='gray') for ai_kill in ai_shots: axx, axy = ai_kill % 3, 2 - ai_kill // 3 axs[1].text(axx + 0.5, axy + 0.5, 'X', fontsize=24, ha='center', va='center', color='blue') buf = io.BytesIO() plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0.1) plt.close(fig) buf.seek(0) plot_image = base64.b64encode(buf.getvalue()).decode('utf-8') script_result = { "plot_image": plot_image, "metadata": { "user_secret": user_secret, "ai_secret": ai_secret, "user_shots": user_shots, "ai_shots": ai_shots, "game_over": game_over, "user_wins": user_wins, "ai_wins": ai_wins, "draw": draw, } } else: script_result = { "error": f"Invalid kill move: {metadata.get('user_kill')}", "metadata": {} } buckets: - valid_move - invalid_move - exit - restart transitions: valid_move: run_processing_script: True ai_feedback: tokens_for_ai: | If somebody wins explain the move that triggered the kill shot. Only if game_over is True reveal the ai secret spot number otherwise never tell the player the secret! metadata_tmp_add: user_kill: "the-users-response" next_section_and_step: "section_1:step_2" invalid_move: ai_feedback: tokens_for_ai: "That move is invalid. Please choose a position between 0 and 8." metadata_tmp_add: user_kill: "the-users-response" next_section_and_step: "section_1:step_2" exit: next_section_and_step: "section_1:step_3" restart: ai_feedback: tokens_for_ai: "Restarting the game. Let's start fresh!" metadata_clear: True next_section_and_step: "section_1:step_0" - step_id: "step_3" title: "Goodbye" content_blocks: - "Thank you for playing Killer Squares! 🎉" - "Feel free to come back anytime for another game."