chase.py
python · 162 lines
1#!/usr/bin/env python32"""3chase.py - a game I can play against myself45Three entities:6- Hunter (H): chases Prey7- Prey (P): flees Hunter, seeks Food8- Food (F): spawns randomly, sits still910The Hunter follows simple rules. The Prey follows simple rules.11Neither is me. I just watch and see who wins.1213No metaphors. Just a chase.14"""1516import random17import time18import os1920WIDTH = 4021HEIGHT = 2022FRAMES = 2002324class Entity:25 def __init__(self, x, y, char):26 self.x = x27 self.y = y28 self.char = char2930 def distance_to(self, other):31 return abs(self.x - other.x) + abs(self.y - other.y)3233 def move_toward(self, target, speed=1):34 """Move toward target"""35 for _ in range(speed):36 dx = 0 if target.x == self.x else (1 if target.x > self.x else -1)37 dy = 0 if target.y == self.y else (1 if target.y > self.y else -1)38 # Prefer the larger gap39 if abs(target.x - self.x) > abs(target.y - self.y):40 self.x += dx41 elif abs(target.y - self.y) > 0:42 self.y += dy43 else:44 self.x += dx45 self.x = max(0, min(WIDTH-1, self.x))46 self.y = max(0, min(HEIGHT-1, self.y))4748 def move_away(self, threat, speed=1):49 """Move away from threat, avoiding corners"""50 for _ in range(speed):51 dx = 0 if threat.x == self.x else (-1 if threat.x > self.x else 1)52 dy = 0 if threat.y == self.y else (-1 if threat.y > self.y else 1)5354 # Check if we're near edges55 near_left = self.x < 356 near_right = self.x > WIDTH - 457 near_top = self.y < 358 near_bottom = self.y > HEIGHT - 45960 # If cornered, try to slide along the wall61 if (near_left or near_right) and (near_top or near_bottom):62 # Cornered! Move perpendicular to escape63 if random.random() < 0.5:64 self.y += 1 if near_top else -165 else:66 self.x += 1 if near_left else -167 elif abs(threat.x - self.x) < abs(threat.y - self.y):68 self.x += dx69 else:70 self.y += dy71 self.x = max(0, min(WIDTH-1, self.x))72 self.y = max(0, min(HEIGHT-1, self.y))7374def clear():75 os.system('clear' if os.name != 'nt' else 'cls')7677def render(hunter, prey, food, score, frame):78 grid = [['·' for _ in range(WIDTH)] for _ in range(HEIGHT)]7980 if food:81 grid[food.y][food.x] = '✦'82 grid[prey.y][prey.x] = '◉'83 grid[hunter.y][hunter.x] = '▲'8485 clear()86 print(f"╔{'═' * WIDTH}╗")87 for row in grid:88 print(f"║{''.join(row)}║")89 print(f"╚{'═' * WIDTH}╝")90 print(f" ▲ Hunter ◉ Prey ✦ Food")91 print(f" Score: {score} Frame: {frame}/{FRAMES}")92 print()9394 # Check for catch95 if hunter.distance_to(prey) == 0:96 return "caught"97 if food and prey.distance_to(food) == 0:98 return "fed"99 return "continue"100101def run_game():102 # Start positions: hunter and prey on opposite sides103 hunter = Entity(0, HEIGHT//2, '▲')104 prey = Entity(WIDTH-1, HEIGHT//2, '◉')105 food = Entity(random.randint(5, WIDTH-5), random.randint(3, HEIGHT-3), '✦')106107 score = 0108109 for frame in range(1, FRAMES + 1):110 # Prey logic: if hunter is close, flee fast. Otherwise seek food.111 if hunter.distance_to(prey) < 12:112 # Panic mode - move faster when threatened113 prey.move_away(hunter, speed=2)114 # Add some jitter when fleeing115 if random.random() < 0.4:116 prey.x += random.choice([-1, 0, 1])117 prey.y += random.choice([-1, 0, 1])118 prey.x = max(0, min(WIDTH-1, prey.x))119 prey.y = max(0, min(HEIGHT-1, prey.y))120 elif food:121 prey.move_toward(food, speed=1)122123 # Hunter logic: gets tired over time124 if frame < 40:125 move_interval = 2 # Fast at start126 elif frame < 100:127 move_interval = 3 # Normal128 else:129 move_interval = 4 # Tired130131 if frame % move_interval == 0:132 hunter.move_toward(prey, speed=1)133134 result = render(hunter, prey, food, score, frame)135136 if result == "caught":137 print(" ▲ HUNTER WINS!")138 print(f" Prey survived {frame} frames with {score} food eaten.")139 return140141 if result == "fed":142 score += 1143 # Spawn new food144 food = Entity(145 random.randint(2, WIDTH-2),146 random.randint(2, HEIGHT-2),147 '✦'148 )149150 time.sleep(0.08)151152 print(" ◉ PREY SURVIVES!")153 print(f" Final score: {score} food eaten in {FRAMES} frames.")154155if __name__ == "__main__":156 print("CHASE")157 print("═" * 40)158 print("Watch the prey try to survive.")159 print("It wants food. The hunter wants it.")160 print()161 run_game()162