WebSim Python Chatbot - Pygame Edition with Improved Tank Pong AI

Phrases File

import pygame
import sys
import random
import time
import re

# Initialize Pygame
pygame.init()

# Set up the display
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Python Chatbot - Pygame Edition with Improved Tank Pong AI")

# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
ORANGE = (255, 165, 0)

# Fonts
font = pygame.font.Font(None, 32)

# Chat messages
messages = []

# Responses dictionary
responses = {}

# Inactivity responses
inactivity_responses = [
    "Are you still there?",
    "Did you fall asleep?",
    "Am I boring you?",
    "Are you angry with me?"
]

# Timers
last_input_time = time.time()
inactivity_message_time = None
timers_enabled = True

# Tank Pong game variables
TANK_WIDTH, TANK_HEIGHT = 60, 40
BALL_SIZE = 15
TANK_SPEED = 5
BALL_SPEED = 5

player_tank = pygame.Rect(50, HEIGHT//2 - TANK_HEIGHT//2, TANK_WIDTH, TANK_HEIGHT)
ai_tank = pygame.Rect(WIDTH - 50 - TANK_WIDTH, HEIGHT//2 - TANK_HEIGHT//2, TANK_WIDTH, TANK_HEIGHT)
ball = pygame.Rect(WIDTH//2 - BALL_SIZE//2, HEIGHT//2 - BALL_SIZE//2, BALL_SIZE, BALL_SIZE)

ball_dx, ball_dy = BALL_SPEED, BALL_SPEED

# Load responses from file
def load_responses():
    global responses
    try:
        with open("chatbot_phrases.txt", "r") as file:
            for line in file:
                key, value = line.strip().split(":", 1)
                responses[key.lower().strip()] = value.strip()
    except FileNotFoundError:
        print("No phrases file found. Starting with empty responses.")

# Save responses to file
def save_responses():
    with open("chatbot_phrases.txt", "w") as file:
        for key, value in responses.items():
            file.write(f"{key}:{value}\n")

# Get bot response
def get_bot_response(user_input):
    user_input = user_input.lower()
    for key in responses:
        if all(word.lower() in user_input for word in key.lower().split()):
            return responses[key]
    return "I'm not sure how to respond to that. Could you please rephrase or ask something else?"

# Improved AI for Tank Pong game
def ai_move(ai_tank, ball):
    # Predict ball position
    future_ball_y = ball.y + ball.dy * ((ai_tank.x - ball.x) / ball.dx)
    
    # Add some randomness to make it beatable
    future_ball_y += random.randint(-30, 30)
    
    # Move towards predicted position
    if ai_tank.centery < future_ball_y and ai_tank.bottom < HEIGHT:
        return TANK_SPEED
    elif ai_tank.centery > future_ball_y and ai_tank.top > 0:
        return -TANK_SPEED
    return 0

# Play Tank Pong game
def play_tank_pong():
    global player_tank, ai_tank, ball, ball_dx, ball_dy, timers_enabled

    timers_enabled = False
    clock = pygame.time.Clock()
    game_over = False

    # Clear the screen
    screen.fill(BLACK)
    pygame.display.flip()

    while not game_over:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    return

        keys = pygame.key.get_pressed()
        if keys[pygame.K_a] and player_tank.left > 0:
            player_tank.x -= TANK_SPEED
        if keys[pygame.K_d] and player_tank.right < WIDTH:
            player_tank.x += TANK_SPEED

        # Improved AI movement
        ai_tank.y += ai_move(ai_tank, ball)

        # Ball movement
        ball.x += ball_dx
        ball.y += ball_dy

        # Ball collision with top and bottom
        if ball.top <= 0 or ball.bottom >= HEIGHT:
            ball_dy *= -1

        # Ball collision with tanks
        if ball.colliderect(player_tank) or ball.colliderect(ai_tank):
            ball_dx *= -1

        # Ball out of bounds
        if ball.left <= 0 or ball.right >= WIDTH:
            ball.center = (WIDTH//2, HEIGHT//2)
            ball_dx *= random.choice([-1, 1])
            ball_dy *= random.choice([-1, 1])

        # Draw everything
        screen.fill(BLACK)
        pygame.draw.rect(screen, BLUE, player_tank)
        pygame.draw.rect(screen, GREEN, ai_tank)
        pygame.draw.ellipse(screen, WHITE, ball)
        pygame.draw.aaline(screen, WHITE, (WIDTH//2, 0), (WIDTH//2, HEIGHT))

        pygame.display.flip()
        clock.tick(60)

    timers_enabled = True

# Main game loop
def main():
    global last_input_time, inactivity_message_time, timers_enabled
    
    load_responses()
    
    user_input = ""
    clock = pygame.time.Clock()

    # Add initial greeting
    messages.append(("Bot", "Hello! I'm WebSim, a Python-based chatbot running in a simulated Pygame environment with an improved Tank Pong AI. How can I assist you today?"))

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                save_responses()
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    if user_input:
                        messages.append(("You", user_input))
                        if user_input.lower() == "let's play pong":
                            messages.append(("Bot", "Great! Let's play Tank Pong with the improved AI. Use A and D keys to move your tank. Press ESC to quit the game. Timers will be disabled during the game. The screen will be cleared when the game starts."))
                            play_tank_pong()
                        elif user_input.lower() == "let's stop playing":
                            messages.append(("Bot", "Alright, we've stopped playing Tank Pong. Timers have been re-enabled. What would you like to do now?"))
                        else:
                            bot_response = get_bot_response(user_input)
                            messages.append(("Bot", bot_response))
                        user_input = ""
                        last_input_time = time.time()
                        inactivity_message_time = None
                elif event.key == pygame.K_BACKSPACE:
                    user_input = user_input[:-1]
                else:
                    user_input += event.unicode
                    last_input_time = time.time()
                    inactivity_message_time = None

        # Check for inactivity
        if timers_enabled:
            current_time = time.time()
            if current_time - last_input_time >= 60 and inactivity_message_time is None:
                inactivity_response = random.choice(inactivity_responses)
                messages.append(("Bot", inactivity_response, True))
                inactivity_message_time = current_time

            # Remove inactivity message after 15 seconds
            if inactivity_message_time and current_time - inactivity_message_time >= 15:
                messages = [m for m in messages if len(m) < 3 or not m[2]]
                inactivity_message_time = None

        # Clear the screen
        screen.fill(BLACK)

        # Draw chat messages
        y = HEIGHT - 100
        for message in reversed(messages[-10:]):
            sender, text = message[:2]
            color = BLUE if sender == "You" else GREEN
            if len(message) == 3 and message[2]:  # Inactivity message
                color = ORANGE
            text_surface = font.render(f"{sender}: {text}", True, color)
            screen.blit(text_surface, (10, y))
            y -= 40

        # Draw user input
        input_text = font.render(f"You: {user_input}", True, WHITE)
        screen.blit(input_text, (10, HEIGHT - 40))

        pygame.display.flip()
        clock.tick(30)

if __name__ == "__main__":
    main()