default_max_attempts_per_step: 9 sections: - section_id: "section_1" title: "Tic Tac Toe" steps: - step_id: "step_0" title: "Introduction" content_blocks: - | Welcome to Tic Tac Toe! 🎮 You will be playing against the AI. You are 'X' and the AI is 'O'. The board positions are numbered 0 to 8 as follows: - step_id: "step_1" title: "Your Move" question: "Enter a position number (0-8) to place your 'X'. Say restart or exit to quit." tokens_for_ai: | Using the metadata, determine if the game is over and 'restart'. If the user wants to restart or play again, categorize as 'restart' If ai_wins or user_wins or is_draw is true, categorize as 'restart'. If the user wants to exit, categorize as 'exit'. If the game_over is True categorize as 'restart'. Finally check: If the move is valid, categorize as 'valid_move'. If the move is invalid, categorize as 'invalid_move'. feedback_tokens_for_ai: | Always speak in first person. DO NOT START WITH "ai_move:". Player is always X, You the AI are always O. If there is an error in the metadata the move was likely invalid. On a new line, provide feedback on the user's move. Only announce a winner or tie if game_over is True. The player makes the first and last move. If the move is invalid, prompt the user to try again. If the move is invalid, give a list of valid moves. If the move is valid & no errors say your move on the last line (ai_move) for example: I move to 8 and draw a O". processing_script: | import random win_conditions = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], # rows [0, 3, 6], [1, 4, 7], [2, 5, 8], # columns [0, 4, 8], [2, 4, 6] # diagonals ] def check_win(board, player, win_conditions): # Check for win and return the winning condition if there is one for condition in win_conditions: win = True for i in condition: if board[i] != player: win = False break if win: return condition return None def plot_board(board, win_line=None): import io import base64 import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize=(3, 3)) ax.set_xlim(0, 3) ax.set_ylim(0, 3) ax.set_xticks([]) ax.set_yticks([]) ax.grid(True) for i, mark in enumerate(board): x = i % 3 y = 2 - i // 3 if mark != " ": ax.text(x + 0.5, y + 0.5, mark, fontsize=24, ha='center', va='center') else: # Plot the cell number if the cell is empty ax.text(x + 0.5, y + 0.5, str(i), fontsize=12, ha='center', va='center', color='gray') # Draw the winning line if there is one if win_line: for i in range(len(win_line) - 1): start = win_line[i] end = win_line[i + 1] x_start, y_start = start % 3 + 0.5, 2 - start // 3 + 0.5 x_end, y_end = end % 3 + 0.5, 2 - end // 3 + 0.5 ax.plot([x_start, x_end], [y_start, y_end], 'r-', linewidth=2) buf = io.BytesIO() plt.savefig(buf, format='png') plt.close(fig) buf.seek(0) return base64.b64encode(buf.getvalue()).decode('utf-8') # Reconstruct the board from moves user_moves = metadata.get("user_moves", []) ai_moves = metadata.get("ai_moves", []) ai_move = None board = [" "] * 9 for move in user_moves: board[int(move)] = "X" for move in ai_moves: board[int(move)] = "O" # Get the user's latest move try: user_move = int(metadata.get("user_move")) except (IndexError, ValueError) as e: # Remove the invalid move from user_moves user_move = -1 # Check if the move is valid if 0 <= user_move < 9 and board[user_move] == " ": board[user_move] = "X" user_moves.append(user_move) user_win_line = check_win(board, "X", win_conditions) if not user_win_line: # ai makes a move. available_positions = [] for i in range(len(board)): if board[i] == " ": available_positions.append(i) if available_positions: ai_move = random.choice(available_positions) board[ai_move] = "O" ai_moves.append(ai_move) ai_win_line = check_win(board, "O", win_conditions) is_draw = True for x in board: if x == " ": is_draw = False break game_over = any([user_win_line, ai_win_line, is_draw]) win_line = user_win_line if user_win_line else ai_win_line script_result = { "plot_image": plot_board(board, win_line), "set_background": not game_over, "ai_move": ai_move, "user_move": user_move, "metadata": { "user_moves": user_moves, "ai_moves": ai_moves, "board": board, "game_over": game_over, "ai_wins": ai_win_line is not None, "user_wins": user_win_line is not None, "is_draw": is_draw } } else: script_result = { "error": f"Invalid move: {metadata.get('user_move')}", "metadata": { "user_moves": user_moves, }, } # Debugging: Print the current board state print("Current board state:", board) buckets: - valid_move - invalid_move - restart - exit transitions: valid_move: run_processing_script: True ai_feedback: tokens_for_ai: | at first glance it seems like a valid user_move. DO NOT: * DRAW THE GAME BOARD * DESCRIBE THE GAME BOARD metadata_tmp_add: user_move: "the-users-response" next_section_and_step: "section_1:step_1" invalid_move: ai_feedback: tokens_for_ai: "That move is invalid. Please choose an empty position between 0 and 8." metadata_tmp_add: user_move: "the-users-response" next_section_and_step: "section_1:step_1" exit: next_section_and_step: "section_1:step_2" 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: "Goodbye" content_blocks: - "Thank you for playing Tic Tac Toe! 🎉" - "Feel free to come back anytime for another game."