Robotaxi Tycoon – Scale Your Fleet to $1M! A Python Mini Game Made By ChatGPT

4.7/5 - (3 votes)

I just made this Python mini-game with ChatGPT and Python.

You can try the game on your local machine easily by running pip install pygame and pasting the following code into a Python file “game.py“, followed by running python game.py.

Here’s a screenshot before I give you the code:

If you need help with any step, check out the following tutorials:

So this is the code you need to copy and paste — you can run the game in the background while you “work”. Can you reach a robotaxi profit of $1M? πŸ‘‡πŸ§‘β€πŸ’»

import pygame
import random

# Initialize pygame
pygame.init()

# Constants
WIDTH, HEIGHT = 1000, 800  # Increased dimensions
CELL_SIZE = 20
GRID_WIDTH = 40  # Adjusted for the new width
GRID_HEIGHT = 40  # Adjusted for the new height
MILES_PER_CELL = 10 / GRID_WIDTH  # Assuming the map is 10x10 miles
REV_PER_MILE = 20 # $ Revenue per mile


# Colors
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
BLACK = (0, 0, 0)

# Button constants
BUTTON_WIDTH = 120  # Smaller width
BUTTON_HEIGHT = 30  # Smaller height
BUTTON_COLOR = (0, 0, 255)  # Blue color
BUTTON_HOVER_COLOR = (50, 50, 255)  # Slightly lighter blue for hover
TEXT_COLOR = (255, 255, 255)  # White text


# Custom event for adding new passengers
ADD_PASSENGER_EVENT = pygame.USEREVENT + 1
current_passenger_interval = 5000  # Initial interval is 5 seconds
pygame.time.set_timer(ADD_PASSENGER_EVENT, current_passenger_interval)  # Add a new passenger every 5 seconds


starting_robotaxis = 1
robotaxi_cost = 15000  # $15k per robotaxi
total_revenue = 0.0



class Passenger:
    def __init__(self):
        self.x = random.randint(0, GRID_WIDTH - 1)
        self.y = random.randint(0, GRID_HEIGHT - 1)
        self.dest_x = random.randint(0, GRID_WIDTH - 1)
        self.dest_y = random.randint(0, GRID_HEIGHT - 1)

    def draw(self, screen):
        pygame.draw.rect(screen, RED, (self.x * CELL_SIZE, self.y * CELL_SIZE, CELL_SIZE, CELL_SIZE))
        pygame.draw.rect(screen, GREEN, (self.dest_x * CELL_SIZE, self.dest_y * CELL_SIZE, CELL_SIZE, CELL_SIZE))
        pygame.draw.line(screen, YELLOW, (self.x * CELL_SIZE + CELL_SIZE // 2, self.y * CELL_SIZE + CELL_SIZE // 2), 
                         (self.dest_x * CELL_SIZE + CELL_SIZE // 2, self.dest_y * CELL_SIZE + CELL_SIZE // 2))


class Robotaxi:
    def __init__(self):
        self.x = random.randint(0, GRID_WIDTH - 1)
        self.y = random.randint(0, GRID_HEIGHT - 1)
        self.passenger = None
        self.revenue = 0.0

    def find_nearest_passenger(self, passengers):
        min_dist = float('inf')
        nearest = None
        for passenger in passengers:
            dist = abs(self.x - passenger.x) + abs(self.y - passenger.y)
            if dist < min_dist:
                min_dist = dist
                nearest = passenger
        return nearest

    def move(self, passengers):
        target_x, target_y = self.x, self.y

        if self.passenger:
            target_x, target_y = self.passenger.dest_x, self.passenger.dest_y
        else:
            nearest_passenger = self.find_nearest_passenger(passengers)
            if nearest_passenger:
                target_x, target_y = nearest_passenger.x, nearest_passenger.y

        if self.x < target_x: self.x += 1
        elif self.x > target_x: self.x -= 1

        if self.y < target_y: self.y += 1
        elif self.y > target_y: self.y -= 1

        # Ensure robotaxi doesn't leave the map
        self.x = max(0, min(GRID_WIDTH - 1, self.x))
        self.y = max(0, min(GRID_HEIGHT - 1, self.y))

        # Check if robotaxi reached a passenger or destination
        if not self.passenger:
            for passenger in passengers:
                if self.x == passenger.x and self.y == passenger.y:
                    self.passenger = passenger
                    passengers.remove(passenger)
                    break

        # Update revenue when dropping off a passenger
        elif self.x == self.passenger.dest_x and self.y == self.passenger.dest_y:
            distance_travelled = abs(self.passenger.x - self.passenger.dest_x) + abs(self.passenger.y - self.passenger.dest_y)
            earned = distance_travelled * MILES_PER_CELL * REV_PER_MILE
            global total_revenue
            total_revenue += earned
            self.passenger = None
            self.revenue += earned

    def draw(self, screen):
        pygame.draw.circle(screen, BLUE, (self.x * CELL_SIZE + CELL_SIZE // 2, self.y * CELL_SIZE + CELL_SIZE // 2), CELL_SIZE // 2)
        if self.passenger:
            pygame.draw.line(screen, YELLOW, (self.x * CELL_SIZE + CELL_SIZE // 2, self.y * CELL_SIZE + CELL_SIZE // 2), 
                             (self.passenger.dest_x * CELL_SIZE + CELL_SIZE // 2, self.passenger.dest_y * CELL_SIZE + CELL_SIZE // 2))

    def display_revenue(self, screen, index):
        font = pygame.font.SysFont(None, 25)
        text = font.render(f"Taxi {index + 1}: ${self.revenue:.2f}", True, BLACK, WHITE)
        screen.blit(text, (10, 10 + index * 30))


class Button:
    def __init__(self, x, y, text):
        self.x = x
        self.y = y
        self.text = text
        self.is_hovered = False

    def draw(self, screen):
        color = BUTTON_HOVER_COLOR if self.is_hovered else BUTTON_COLOR
        pygame.draw.rect(screen, color, (self.x, self.y, BUTTON_WIDTH, BUTTON_HEIGHT))
        font = pygame.font.SysFont(None, 17)  # Smaller font size
        label = font.render(self.text, True, TEXT_COLOR)
        screen.blit(label, (self.x + (BUTTON_WIDTH - label.get_width()) // 2, self.y + (BUTTON_HEIGHT - label.get_height()) // 2))

    def handle_event(self, event):
        if event.type == pygame.MOUSEMOTION:
            self.is_hovered = self.x <= event.pos[0] <= self.x + BUTTON_WIDTH and self.y <= event.pos[1] <= self.y + BUTTON_HEIGHT
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if self.is_hovered:
                return True
        return False


def adjust_passenger_frequency(increase=True):
    global current_passenger_interval
    if increase:
        current_passenger_interval = max(current_passenger_interval // 2, 1)  # Halve the interval, but not less than 1 ms
    else:
        current_passenger_interval = min(current_passenger_interval * 2, 10000)  # Double the interval, but not more than 10 seconds
    pygame.time.set_timer(ADD_PASSENGER_EVENT, current_passenger_interval)

def display_passenger_interval(screen):
    interval_in_seconds = current_passenger_interval / 1000.0
    font = pygame.font.SysFont(None, 25)
    text = font.render(f"Passenger Interval: {interval_in_seconds:.2f} seconds", True, BLACK)
    screen.blit(text, (WIDTH - 300, HEIGHT - 30))


def display_total_profit(screen):
    font = pygame.font.SysFont(None, 25)
    text = font.render(f"Total Profit: ${total_revenue:.2f}", True, BLACK)
    screen.blit(text, (10, HEIGHT - 30))


# Initialize screen and clock
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Robotaxi Fleet")
clock = pygame.time.Clock()

robotaxis = [Robotaxi() for _ in range(starting_robotaxis)]
passengers = [Passenger() for _ in range(3)]

# Create buttons
buttons = [
    Button(820, 10, "Buy Taxi ($15k)"),
    Button(820, 50, "Sell Taxi ($7.5k)")
]


running = True
while running:
    screen.fill(WHITE)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == ADD_PASSENGER_EVENT:
            passengers.append(Passenger())

    for i, button in enumerate(buttons):
        if button.handle_event(event):
            if i == 0:  # MORE TAXIS
                if total_revenue >= robotaxi_cost:

                    robotaxis.append(Robotaxi())
                    total_revenue -= robotaxi_cost
            elif i == 1:  # LESS TAXIS
                if robotaxis:
                    robotaxis.pop()
                    total_revenue += robotaxi_cost * 0.5  # Get half the cost back when selling


    MAX_PASSENGERS = len(robotaxis)
    if len(passengers) < MAX_PASSENGERS:
        probability_of_new_passenger = (MAX_PASSENGERS - len(passengers)) / MAX_PASSENGERS
        if random.random() < probability_of_new_passenger:
            passengers.append(Passenger())



    # Update robotaxis
    for index, taxi in enumerate(robotaxis):
        taxi.move(passengers)
        taxi.draw(screen)
        taxi.display_revenue(screen, index)

    # Draw passengers
    for passenger in passengers:
        passenger.draw(screen)

    # Draw buttons
    for button in buttons:
        button.draw(screen)


    # Display total profit
    display_total_profit(screen)

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

pygame.quit()

This code is a simulation of a fleet of robotaxis picking up and dropping off passengers on a grid. The code uses the pygame library to provide a visual representation of the simulation.

Here’s a breakdown of the code:

  1. Imports and Initialization:
    • pygame is imported for the game engine.
    • random is imported for generating random numbers.
  2. Constants:
    • Dimensions of the screen, grid, and cells are defined.
    • Revenue constants are defined, such as revenue per mile.
    • Colors are defined for different elements in the simulation.
    • Button constants are defined for the UI buttons.
    • A custom event (ADD_PASSENGER_EVENT) is set up to add a new passenger every 5 seconds.
  3. Passenger Class:
    • Represents a passenger with a starting and destination point.
    • The draw method visualizes the passenger and their destination on the screen.
  4. Robotaxi Class:
    • Represents a robotaxi with a position and optional passenger.
    • The find_nearest_passenger method finds the closest passenger to the robotaxi.
    • The move method moves the robotaxi towards a passenger or their destination.
    • The draw method visualizes the robotaxi on the screen.
    • The display_revenue method displays the revenue earned by each robotaxi.
  5. Button Class:
    • Represents a clickable button on the screen.
    • The draw method visualizes the button.
    • The handle_event method checks if the button is clicked or hovered over.
  6. Utility Functions:
    • adjust_passenger_frequency adjusts the frequency of passenger appearance.
    • display_passenger_interval displays the current passenger appearance interval.
    • display_total_profit displays the total profit earned.
  7. Main Loop:
    • The screen is initialized, and the game’s main loop starts.
    • Robotaxis and passengers are initialized.
    • Buttons for buying and selling taxis are created.
    • Inside the loop:
      • The screen is cleared.
      • Events are processed (e.g., quitting the game, adding passengers).
      • Buttons are checked for clicks.
      • The number of passengers is adjusted based on the number of robotaxis.
      • Robotaxis are updated (moved, drawn, and their revenue displayed).
      • Passengers are drawn.
      • Buttons are drawn.
      • Total profit is displayed.
    • The screen is updated, and the loop waits for a short duration before the next iteration.
  8. End:
    • After the main loop, pygame.quit() is called to close the game window.

In summary, this code simulates a fleet of robotaxis that move around a grid to pick up and drop off passengers. The user can buy or sell taxis using the provided buttons, and the simulation displays the revenue earned by each taxi and the total profit.

Prompt Engineering with Python and OpenAI

You can check out the whole course on OpenAI Prompt Engineering using Python on the Finxter academy. We cover topics such as:

  • Embeddings
  • Semantic search
  • Web scraping
  • Query embeddings
  • Movie recommendation
  • Sentiment analysis

πŸ‘¨β€πŸ’» Academy: Prompt Engineering with Python and OpenAI