Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions projects/example-improve/controller.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
# --- controller.py ---
import keyboard

from model import Point # Import Point to define directions


class Controller:
def __init__(self, game, view):
self.game = game
self.view = view

def handle_input(self):
if keyboard.is_pressed("up") and not hasattr(self, "last_key_pressed"):
self.game.move("down")
self.last_key_pressed = "up"
elif hasattr(self, "last_key_pressed") and self.last_key_pressed == "up":
self.game.move("right")
del self.last_key_pressed
# We need a reference to the snake to change its direction
snake = self.game.snake

# Check for key presses and set the snake's direction using Point objects.
# Note: We must call set_direction on the snake object.

# UP: Change Y by -1
if keyboard.is_pressed("up"):
snake.set_direction(Point(0, -1))

# DOWN: Change Y by +1
elif keyboard.is_pressed("down"):
self.game.move("up")
snake.set_direction(Point(0, 1))

# LEFT: Change X by -1
elif keyboard.is_pressed("left"):
self.game.move("right")
snake.set_direction(Point(-1, 0))

# RIGHT: Change X by +1
elif keyboard.is_pressed("right"):
self.game.move("left")
snake.set_direction(Point(1, 0))

# Optional: Add an exit key
elif keyboard.is_pressed("esc"):
self.game.is_running = False
102 changes: 102 additions & 0 deletions projects/example-improve/main.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,111 @@
import os
import platform
import subprocess
import sys

from importlib.metadata import distributions

from controller import Controller
from model import Game
from rich.console import Console
from rich.table import Table
from view import View

# Sensitive environment variables to mask
SENSITIVE_KEYS = ["OPENAI_API_KEY", "API_KEY", "SECRET", "TOKEN"]


def get_command_version(command):
"""Run a command and return its version, or 'Not found'."""
try:
result = subprocess.run(command, shell=True, capture_output=True, text=True)
if result.returncode == 0:
return result.stdout.strip().split("\n")[0]
return "Not found"
except Exception:
return "Not found"


def get_env_variables():
"""Return filtered environment variables with sensitive ones masked."""
filtered = {}
for key, value in os.environ.items():
if key in SENSITIVE_KEYS:
filtered[key] = "*****"
elif key in ["PATH", "PYTHONPATH", "VIRTUAL_ENV"]:
filtered[key] = value
return filtered


def get_installed_packages():
"""Return a dict of installed Python packages and versions."""
packages = {}
for dist in distributions():
name = dist.metadata["Name"]
version = dist.version
if name:
packages[name] = version
return packages


def sysinfo():
info = {
"gpt_engineer_version": "0.1.0", # Change if your package version differs
"os": platform.system(),
"os_version": platform.version(),
"architecture": platform.machine(),
"python_version": sys.version.split()[0],
"pip_version": get_command_version("pip --version"),
"git_version": get_command_version("git --version"),
"node_version": get_command_version("node --version"),
"env_variables": get_env_variables(),
"installed_packages": get_installed_packages(),
}

# Pretty print using Rich
console = Console()
console.print("\n[bold cyan]=== System Information ===[/bold cyan]\n")

table = Table(show_header=True, header_style="bold magenta")
table.add_column("Key", style="cyan", no_wrap=True)
table.add_column("Value", style="green")

# Top-level info
for key in [
"gpt_engineer_version",
"os",
"os_version",
"architecture",
"python_version",
"pip_version",
"git_version",
"node_version",
]:
table.add_row(key, str(info[key]))

console.print(table)

# Environment variables
console.print("\n[bold cyan]Environment Variables:[/bold cyan]")
for k, v in info["env_variables"].items():
console.print(f"{k}: {v}")

# Installed packages (optional: print first 30 only)
console.print("\n[bold cyan]Installed Packages (first 30 shown):[/bold cyan]")
for i, (pkg, ver) in enumerate(info["installed_packages"].items()):
if i >= 30:
console.print(f"... ({len(info['installed_packages'])-30} more packages)")
break
console.print(f"{pkg}: {ver}")


def main():
# Check if --sysinfo argument is provided
if "--sysinfo" in sys.argv:
sysinfo()
return

# Regular game loop
game = Game()
view = View(game)
controller = Controller(game, view)
Expand Down
70 changes: 63 additions & 7 deletions projects/example-improve/model.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,88 @@
# --- model.py ---
import random

from dataclasses import dataclass


# ------------------------------
# Data Structures
# ------------------------------
@dataclass
class Point:
x: int
y: int


# ------------------------------
# Snake Class
# ------------------------------
class Snake:
def __init__(self, initial_position: Point):
self.body: list[Point] = [initial_position] # Snake starts with one segment
self.direction = Point(1, 0) # Moving right initially
self.grow_next_move = False # Flag to handle growth

@property
def head(self) -> Point:
"""Return the current head of the snake."""
return self.body[0]

def set_direction(self, new_direction: Point):
"""Change direction if not opposite to current."""
if (
self.direction.x + new_direction.x != 0
or self.direction.y + new_direction.y != 0
):
self.direction = new_direction

def move(self):
"""Move the snake in the current direction."""
new_head = Point(self.head.x + self.direction.x, self.head.y + self.direction.y)
self.body.insert(0, new_head) # Add new head
if self.grow_next_move:
self.grow_next_move = False # Growth applied, reset flag
else:
self.body.pop() # Remove tail if not growing

def grow(self):
"""Trigger growth on the next move."""
self.grow_next_move = True


# ------------------------------
# Game Class
# ------------------------------
class Game:
def __init__(self):
self.snake = [Point(5, 5)]
def __init__(self, size: int = 10):
self.size = size # Board size (size x size)
self.snake = Snake(initial_position=Point(size // 2, size // 2))
self.food = self.generate_food()
self.is_running = True

def generate_food(self):
return Point(random.randint(0, 10), random.randint(0, 10))
"""Generate food not overlapping with the snake."""
while True:
food_point = Point(
random.randint(0, self.size - 1), random.randint(0, self.size - 1)
)
if food_point not in self.snake.body:
return food_point

def update(self):
# Move the snake
"""Update the game state: move snake, handle collisions."""
self.snake.move()

# Check for collision with food
# Check for food collision
if self.snake.head == self.food:
self.snake.grow()
self.food = self.generate_food()

# Check for collision with boundaries
if not (0 <= self.snake.head.x < 10 and 0 <= self.snake.head.y < 10):
# Check for wall collisions
if not (
0 <= self.snake.head.x < self.size and 0 <= self.snake.head.y < self.size
):
self.is_running = False

# Check for self-collision
if self.snake.head in self.snake.body[1:]:
self.is_running = False
19 changes: 11 additions & 8 deletions projects/example-improve/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ def __init__(self, game):
self.game = game

def render(self):
# Print the game state
for y in range(10):
for x in range(10):
if Point(x, y) in self.game.snake:
print("S", end="")
elif Point(x, y) == self.game.food:
print("F", end="")
# Print the game state (10x10 board)
for y in range(self.game.size):
for x in range(self.game.size):
current = Point(x, y)
if current == self.game.snake.head:
print("H", end="") # Head of the snake
elif current in self.game.snake.body[1:]:
print("S", end="") # Body of the snake
elif current == self.game.food:
print("F", end="") # Food
else:
print(".", end="")
print(".", end="") # Empty space
print()
print()
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pillow = "^10.2.0"
datasets = "^2.17.1"
black = "23.3.0"
langchain-community = "^0.2.0"
packaging = ">=23.1"

[tool.poetry.group.dev.dependencies]
pytest = ">=7.3.1"
Expand Down
Loading