Участник:Prionosuchus
Материал из Абсурдопедии
Перейти к навигацииПерейти к поискуPrionosuchus — древняя амфибия, жившая в пермском периоде (т.е. до Хренозоя).
Коды для игр[править]
(потом перемещу их в нужную статью, а пока проверяю их здесь)
Щучье озеро[править]
- Щучье озеро — симулятор поведения щук, когда они единственные рыбы водоёма.
- Геймплей: спамить икру или молодых щук, начинать и заканчивать зимний период.
- Цель игры — узнать на какой по счёту рыбе ваш комп взорвётся. Ну или помедитировать на бесконечно плодящихся, друг друга жрущих и умирающих щук.
import pygame
import random
import math
pygame.init()
WIDTH, HEIGHT = 1400, 1000
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Щучье озеро (вид сверху)")
clock = pygame.time.Clock()
FPS = 60
SAND_COLOR = (210, 180, 140)
WATER_CENTER_COLOR = (20, 80, 180)
BLUE = (50, 150, 250)
GREEN = (0, 150, 0)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (200, 0, 0)
DARK_GREEN = (0, 100, 0)
YELLOW = (255, 255, 0)
ORANGE = (255, 165, 0)
MAX_LEECHES = 1000
MAX_EGGS = 3000
EGG_LIFETIME = 10000
GRID_DISPLAY_TIME = 1000
STARVATION_TIME = 60000
DEATH_SPAWN_EGGS = 20
SHORE_WIDTH = 80
SHORE_WIDTH_SMALL = 20
DARKEN_RECT_W = 340
DARKEN_RECT_H = 300
DARKEN_ALPHA = 80
DARKEN_RECT = pygame.Rect(
WIDTH // 2 - DARKEN_RECT_W // 2,
HEIGHT // 2 - DARKEN_RECT_H // 2,
DARKEN_RECT_W,
DARKEN_RECT_H
)
font = pygame.font.SysFont("Arial", 20)
big_font = pygame.font.SysFont("Arial", 36)
speech_font = pygame.font.SysFont("Arial", 18)
help_font = pygame.font.SysFont("Arial", 16)
PHRASES_EAT_LEECH = ["Вкуснятина!", "Ням-ням!", "Пиявка - вкусно!", "Ммм, пиявка!"]
PHRASES_EAT_PIKE = ["Ты слишком мал!", "Каннибализм!", "Я сильнее!", "Ай, как нехорошо!"]
PHRASES_EAT_EGG = ["Икорка!", "Вкусные яйца!", "Ням!"]
PHRASES_SPAWN = ["Потомство будет!", "Я папа!", "Я мама!", "Пора размножаться!"]
PHRASES_DEATH_OLD = ["Я устал, ухожу...", "Прощайте, потомки!", "Старость не радость...", "Тима раков, я ливаю!"]
PHRASES_DEATH_STARVE = ["Я голодал...", "Нет еды...", "Помогите!"]
PHRASES_CAUGHT = ["Ой, блесна!", "Попался!", "Твою дивизию!"]
PHRASES_WINTER = ["Капеееееец", "В спячку!", "Зима близко!", "Холодно"]
PHRASES_POST_WINTER = ["Весна пришла!", "Пора нереститься!", "Рота подъём!!!"]
PHRASES_FLEE = ["Я сделал дело, ухожу!", "Пока!", "Ну его нафиг!"]
PHRASES_RANDOM = ["Где еда?", "Я голоден", "Плыву", "Ой, что-то блестит", "Хочу пиявку", "Кто там?"]
PHRASES_FRY_SPAWN = ["Новая жизнь!", "Вперёд!!!", "Я родился!"]
MAX_MESSAGES = 5
messages = []
def add_message(text, x, y, duration=2000, probability=1.0):
if random.random() > probability:
return
global messages
if len(messages) >= MAX_MESSAGES:
messages.pop(0)
messages.append({'text': text, 'x': x, 'y': y, 'timer': pygame.time.get_ticks() + duration})
def random_leech_position():
if random.random() < 0.7:
side = random.randint(0, 3)
if side == 0:
x = random.uniform(SHORE_WIDTH, 2 * SHORE_WIDTH)
y = random.uniform(SHORE_WIDTH, HEIGHT - SHORE_WIDTH)
elif side == 1:
x = random.uniform(WIDTH - 2 * SHORE_WIDTH, WIDTH - SHORE_WIDTH)
y = random.uniform(SHORE_WIDTH, HEIGHT - SHORE_WIDTH)
elif side == 2:
x = random.uniform(SHORE_WIDTH, WIDTH - SHORE_WIDTH)
y = random.uniform(SHORE_WIDTH, 2 * SHORE_WIDTH)
else:
x = random.uniform(SHORE_WIDTH, WIDTH - SHORE_WIDTH)
y = random.uniform(HEIGHT - 2 * SHORE_WIDTH, HEIGHT - SHORE_WIDTH)
else:
x = random.uniform(2 * SHORE_WIDTH, WIDTH - 2 * SHORE_WIDTH)
y = random.uniform(2 * SHORE_WIDTH, HEIGHT - 2 * SHORE_WIDTH)
return x, y
def random_water_position(small=False):
limit = SHORE_WIDTH_SMALL if small else SHORE_WIDTH
x = random.uniform(limit, WIDTH - limit)
y = random.uniform(limit, HEIGHT - limit)
return x, y
def create_water_surface(width, height, shore_width):
surf = pygame.Surface((width, height), pygame.SRCALPHA)
water_color = WATER_CENTER_COLOR
surf.fill((water_color[0], water_color[1], water_color[2], 255))
for y in range(height):
for x in range(width):
dx = min(x, width - 1 - x)
dy = min(y, height - 1 - y)
d = min(dx, dy)
if d < shore_width:
alpha = int(255 * (d / shore_width))
surf.set_at((x, y), (water_color[0], water_color[1], water_color[2], alpha))
return surf
sand_surf = pygame.Surface((WIDTH, HEIGHT))
sand_surf.fill(SAND_COLOR)
water_surf = create_water_surface(WIDTH, HEIGHT, SHORE_WIDTH)
winter_active = False
ice_surf = None
def create_ice_surface(width, height):
"""Создаёт полупрозрачную ледяную поверхность."""
surf = pygame.Surface((width, height), pygame.SRCALPHA)
surf.fill((200, 230, 255, 80))
for _ in range(500):
x = random.randint(0, width - 1)
y = random.randint(0, height - 1)
alpha = random.randint(30, 100)
surf.set_at((x, y), (255, 255, 255, alpha))
return surf
def toggle_winter():
global winter_active, ice_surf, leeches, pikes, eggs
if not winter_active:
winter_active = True
ice_surf = create_ice_surface(WIDTH, HEIGHT)
if leeches:
leeches = random.sample(leeches, max(1, int(len(leeches) * 0.2)))
pikes = [p for p in pikes if p.length >= 70]
center_rect = DARKEN_RECT
for pike in pikes:
pike.state = "wintering"
pike.target_point = (
random.uniform(center_rect.left, center_rect.right),
random.uniform(center_rect.top, center_rect.bottom)
)
pike.current_speed = pike.base_speed
pike.target = None
pike.has_post_winter_spawned = False
add_message(random.choice(PHRASES_WINTER), pike.x, pike.y, probability=1.0)
else:
winter_active = False
ice_surf = None
for pike in pikes:
if pike.state == "wintering":
pike.state = "post_winter"
side = random.randint(0, 3)
if side == 0:
x = random.uniform(SHORE_WIDTH, 2 * SHORE_WIDTH)
y = random.uniform(SHORE_WIDTH, HEIGHT - SHORE_WIDTH)
elif side == 1:
x = random.uniform(WIDTH - 2 * SHORE_WIDTH, WIDTH - SHORE_WIDTH)
y = random.uniform(SHORE_WIDTH, HEIGHT - SHORE_WIDTH)
elif side == 2:
x = random.uniform(SHORE_WIDTH, WIDTH - SHORE_WIDTH)
y = random.uniform(SHORE_WIDTH, 2 * SHORE_WIDTH)
else:
x = random.uniform(SHORE_WIDTH, WIDTH - SHORE_WIDTH)
y = random.uniform(HEIGHT - 2 * SHORE_WIDTH, HEIGHT - SHORE_WIDTH)
pike.target_point = (x, y)
pike.current_speed = pike.base_speed
pike.target = None
pike.has_post_winter_spawned = False
add_message(random.choice(PHRASES_POST_WINTER), pike.x, pike.y, probability=1.0)
class Leech:
def __init__(self, x, y):
self.x = x
self.y = y
self.length = random.randint(2, 15)
self.angle = random.uniform(0, 2 * math.pi)
self.speed = 0.9
self.segments = 4
self.time = random.random() * 100
def update(self):
if random.random() < 0.02:
self.angle += random.uniform(-0.5, 0.5)
self.x += self.speed * math.cos(self.angle)
self.y += self.speed * math.sin(self.angle)
if self.x < 0:
self.x = 0
self.angle = math.pi - self.angle
if self.x > WIDTH:
self.x = WIDTH
self.angle = math.pi - self.angle
if self.y < 0:
self.y = 0
self.angle = -self.angle
if self.y > HEIGHT:
self.y = HEIGHT
self.angle = -self.angle
self.time += 0.1
def draw(self, screen):
points = []
step = self.length / self.segments
x, y = self.x, self.y
angle = self.angle
for i in range(self.segments + 1):
points.append((x, y))
bend = 0.3 * math.sin(self.time + i * 0.5)
angle += bend * 0.1
x += step * math.cos(angle)
y += step * math.sin(angle)
if len(points) > 1:
pygame.draw.lines(screen, BLACK, False, points, 1)
class Egg:
def __init__(self, x, y):
self.x = x
self.y = y
self.radius = 3
self.born_time = pygame.time.get_ticks()
def update(self, pikes):
if pygame.time.get_ticks() - self.born_time >= EGG_LIFETIME:
fry_x = max(SHORE_WIDTH_SMALL, min(WIDTH - SHORE_WIDTH_SMALL, self.x))
fry_y = max(SHORE_WIDTH_SMALL, min(HEIGHT - SHORE_WIDTH_SMALL, self.y))
fry = Pike(fry_x, fry_y, initial_length=8, state="fleeing_from_spawn")
angle = random.uniform(0, 2 * math.pi)
dist = 50
fry.target_point = (fry_x + dist * math.cos(angle), fry_y + dist * math.sin(angle))
pikes.append(fry)
add_message(random.choice(PHRASES_FRY_SPAWN), fry.x, fry.y, probability=1.0)
return True
return False
def draw(self, screen):
surf = pygame.Surface((self.radius * 2, self.radius * 2), pygame.SRCALPHA)
pygame.draw.circle(surf, (0, 200, 0, 128), (self.radius, self.radius), self.radius)
pygame.draw.circle(surf, (0, 100, 0), (self.radius, self.radius), self.radius, 1)
screen.blit(surf, (self.x - self.radius, self.y - self.radius))
class Bait:
def __init__(self, x, y):
self.x = x
self.y = y
self.width = 12
self.height = 8
self.speed = 5
def update(self, keys):
if keys[pygame.K_UP]:
self.y -= self.speed
if keys[pygame.K_DOWN]:
self.y += self.speed
if keys[pygame.K_LEFT]:
self.x -= self.speed
if keys[pygame.K_RIGHT]:
self.x += self.speed
self.x = max(SHORE_WIDTH + self.width // 2, min(WIDTH - SHORE_WIDTH - self.width // 2, self.x))
self.y = max(SHORE_WIDTH + self.height // 2, min(HEIGHT - SHORE_WIDTH - self.height // 2, self.y))
def draw(self, screen):
pygame.draw.ellipse(screen, RED, (self.x - self.width // 2, self.y - self.height // 2, self.width, self.height))
class Pike:
def __init__(self, x, y, initial_length=12, state="normal"):
self.x = x
self.y = y
self.length = initial_length
self.width = max(5, self.length / 7)
self.angle = random.uniform(0, 2 * math.pi)
self.base_speed = self.calc_base_speed(initial_length)
self.current_speed = self.base_speed
self.target = None
self.state = state
self.target_point = None
self.max_length_reached = False
self.time_at_max = 0
self.last_eat_egg_time = 0
self.last_meal_time = pygame.time.get_ticks()
self.last_update_time = pygame.time.get_ticks()
self.has_spawned_on_death = False
self.has_post_winter_spawned = False
self.last_random_speech = random.randint(0, 5000)
self.generate_sprite()
def calc_base_speed(self, length):
return 3.0 - (length - 8) / 152 * 1.0
def get_shore_limit(self):
return SHORE_WIDTH_SMALL if self.length <= 29 else SHORE_WIDTH
def generate_sprite(self):
w = int(self.length)
h = int(self.width)
if w < 5 or h < 3:
surf = pygame.Surface((w, h), pygame.SRCALPHA)
pygame.draw.ellipse(surf, GREEN, (0, 0, w, h))
self.sprite = surf
return
surf = pygame.Surface((w, h), pygame.SRCALPHA)
body_color = (30, 80, 30)
pygame.draw.ellipse(surf, body_color, (0, 0, w, h))
spine_color = (20, 60, 20)
belly_color = (30, 80, 30)
spine_rect = pygame.Rect(0, 0, w, h // 2 + 2)
pygame.draw.ellipse(surf, spine_color, spine_rect)
belly_rect = pygame.Rect(0, h // 2 - 2, w, h // 2 + 2)
pygame.draw.ellipse(surf, belly_color, belly_rect)
eye_radius = max(2, int(0.09 * h))
pupil_radius = max(1, int(0.05 * h))
eye_x = int(0.8 * w)
eye_y1 = int(0.35 * h)
eye_y2 = int(0.65 * h)
pygame.draw.circle(surf, WHITE, (eye_x, eye_y1), eye_radius)
pygame.draw.circle(surf, WHITE, (eye_x, eye_y2), eye_radius)
pupil_offset = int(0.2 * eye_radius)
pygame.draw.circle(surf, BLACK, (eye_x + pupil_offset, eye_y1), pupil_radius)
pygame.draw.circle(surf, BLACK, (eye_x + pupil_offset, eye_y2), pupil_radius)
dorsal_color = (20, 60, 20)
dorsal_x = int(0.2 * w)
dorsal_w = int(0.5 * w)
dorsal_h = max(2, int(h * 0.25))
pygame.draw.ellipse(surf, dorsal_color, (dorsal_x, 0, dorsal_w, dorsal_h))
pectoral_color = (20, 60, 20)
pect_w = int(0.06 * w)
pect_h = int(0.15 * h)
pygame.draw.ellipse(surf, pectoral_color, (int(0.6 * w), int(0.05 * h), pect_w, pect_h))
pygame.draw.ellipse(surf, pectoral_color, (int(0.6 * w), int(0.8 * h), pect_w, pect_h))
tail_color = ORANGE
tail_w = int(0.3 * w)
tail_h = int(0.9 * h)
tail_x = -tail_w // 2
tail_y = (h - tail_h) // 2
pygame.draw.ellipse(surf, tail_color, (tail_x, tail_y, tail_w, tail_h))
num_spots = random.randint(3, 6)
for _ in range(num_spots):
cx = random.uniform(0.2, 0.8) * w
cy = random.uniform(0.15, 0.4) * h
rx = random.uniform(0.02, 0.08) * w
ry = random.uniform(0.02, 0.08) * h
color = random.choice([(0, 30, 0), (10, 50, 10), (20, 70, 20)])
pygame.draw.ellipse(surf, color, (int(cx - rx / 2), int(cy - ry / 2), int(rx), int(ry)))
pygame.draw.ellipse(surf, color, (int(cx - rx / 2), int(h - cy - ry / 2), int(rx), int(ry)))
for _ in range(random.randint(2, 4)):
cx = random.uniform(0.3, 0.7) * w
cy = random.uniform(0.05, 0.2) * h
rx = random.uniform(0.02, 0.06) * w
ry = random.uniform(0.01, 0.04) * h
pygame.draw.ellipse(surf, (0, 20, 0), (int(cx - rx / 2), int(cy - ry / 2), int(rx), int(ry)))
self.sprite = surf
def get_tint(self):
if DARKEN_RECT.collidepoint(self.x, self.y):
return (0, 0, 0, DARKEN_ALPHA)
return (0, 0, 0, 0)
def find_target(self, leeches, pikes, eggs, bait):
if self.state != "normal":
self.target = None
return
if self.length >= 160 and bait is not None:
self.target = bait
return
min_dist = float('inf')
target = None
if self.length < 40:
for leech in leeches:
dist = math.hypot(self.x - leech.x, self.y - leech.y)
if dist < min_dist:
min_dist = dist
target = leech
if self.length >= 30:
for other in pikes:
if other is self:
continue
if other.length < self.length / 2:
dist = math.hypot(self.x - other.x, self.y - other.y)
if dist < min_dist:
min_dist = dist
target = other
if min_dist == float('inf') or min_dist > 200:
for egg in eggs:
dist = math.hypot(self.x - egg.x, self.y - egg.y)
if dist < min_dist:
min_dist = dist
target = egg
self.target = target
def update(self, leeches, pikes, eggs, bait, current_time):
dt = current_time - self.last_update_time
self.last_update_time = current_time
limit = self.get_shore_limit()
if self.state == "wintering":
if self.target_point is not None:
tx, ty = self.target_point
dx = tx - self.x
dy = ty - self.y
dist = math.hypot(dx, dy)
if dist > 0:
self.angle = math.atan2(dy, dx)
if dist < self.current_speed:
self.x = tx
self.y = ty
self.current_speed = 0
else:
self.x += self.current_speed * dx / dist
self.y += self.current_speed * dy / dist
self.x = max(limit, min(WIDTH - limit, self.x))
self.y = max(limit, min(HEIGHT - limit, self.y))
return
if self.state == "post_winter":
if self.target_point is not None:
tx, ty = self.target_point
dx = tx - self.x
dy = ty - self.y
dist = math.hypot(dx, dy)
if dist > 0:
self.angle = math.atan2(dy, dx)
if dist < self.current_speed:
self.x = tx
self.y = ty
if not self.has_post_winter_spawned:
if self.length >= 50 and len(eggs) < MAX_EGGS:
num_eggs = int(0.5 * self.length)
for _ in range(num_eggs):
angle = random.uniform(0, 2 * math.pi)
dist2 = random.uniform(10, 30)
ex = self.x + dist2 * math.cos(angle)
ey = self.y + dist2 * math.sin(angle)
ex = max(SHORE_WIDTH + 5, min(WIDTH - SHORE_WIDTH - 5, ex))
ey = max(SHORE_WIDTH + 5, min(HEIGHT - SHORE_WIDTH - 5, ey))
eggs.append(Egg(ex, ey))
add_message(random.choice(PHRASES_SPAWN), self.x, self.y, probability=1.0)
self.has_post_winter_spawned = True
self.state = "normal"
self.target_point = None
self.current_speed = self.base_speed
else:
self.x += self.current_speed * dx / dist
self.y += self.current_speed * dy / dist
self.x = max(limit, min(WIDTH - limit, self.x))
self.y = max(limit, min(HEIGHT - limit, self.y))
return
if self.state in ("fleeing_from_spawn", "fleeing_from_eggs"):
if self.target_point is not None:
tx, ty = self.target_point
dx = tx - self.x
dy = ty - self.y
dist = math.hypot(dx, dy)
if dist > 0:
self.angle = math.atan2(dy, dx)
if dist < self.current_speed:
self.x = tx
self.y = ty
else:
self.x += self.current_speed * dx / dist
self.y += self.current_speed * dy / dist
if dist <= self.current_speed + 2:
self.state = "normal"
self.target_point = None
self.current_speed = self.base_speed
else:
self.state = "normal"
self.x = max(limit, min(WIDTH - limit, self.x))
self.y = max(limit, min(HEIGHT - limit, self.y))
return
self.find_target(leeches, pikes, eggs, bait)
if self.target is not None:
dx = self.target.x - self.x
dy = self.target.y - self.y
dist = math.hypot(dx, dy)
if dist > 0:
self.angle = math.atan2(dy, dx)
if dist < self.current_speed:
self.x = self.target.x
self.y = self.target.y
else:
self.x += self.current_speed * dx / dist
self.y += self.current_speed * dy / dist
self.x = max(limit, min(WIDTH - limit, self.x))
self.y = max(limit, min(HEIGHT - limit, self.y))
if self.state == "normal" and current_time - self.last_random_speech > 5000:
if random.random() < 0.01:
phrase = random.choice(PHRASES_RANDOM)
add_message(phrase, self.x, self.y, duration=1500, probability=1.0)
self.last_random_speech = current_time
def check_eat(self, leeches, pikes, eggs, bait, current_time):
if self.state != "normal":
return False
if self.length >= 160 and bait is not None:
dist = math.hypot(self.x - bait.x, self.y - bait.y)
if dist < max(10, self.length / 2 + 5):
add_message(random.choice(PHRASES_CAUGHT), self.x, self.y, probability=1.0)
return "bait_eaten"
if self.length < 40:
for leech in leeches:
dist = math.hypot(self.x - leech.x, self.y - leech.y)
if dist < max(10, self.length / 2 + 5):
leeches.remove(leech)
self.last_meal_time = current_time
if not self.max_length_reached:
self.length += leech.length
self.width = max(5, self.length / 7)
self.generate_sprite()
prob = 1.0 if self.length > 50 else 0.5
add_message(random.choice(PHRASES_EAT_LEECH), self.x, self.y, probability=prob)
return True
if self.length >= 30:
for other in pikes:
if other is self:
continue
if other.length < self.length / 2:
dist = math.hypot(self.x - other.x, self.y - other.y)
if dist < max(10, self.length / 2 + 5):
pikes.remove(other)
self.last_meal_time = current_time
if not self.max_length_reached:
self.length += other.length
self.width = max(5, self.length / 7)
self.generate_sprite()
prob = 1.0 if self.length > 50 else 0.5
add_message(random.choice(PHRASES_EAT_PIKE), self.x, self.y, probability=prob)
return True
if current_time - self.last_eat_egg_time >= 1000:
for egg in eggs:
dist = math.hypot(self.x - egg.x, self.y - egg.y)
if dist < max(10, self.length / 2 + 5):
eggs.remove(egg)
self.last_eat_egg_time = current_time
self.last_meal_time = current_time
if not self.max_length_reached:
self.length += 1
self.width = max(5, self.length / 7)
self.generate_sprite()
prob = 1.0 if self.length > 50 else 0.5
add_message(random.choice(PHRASES_EAT_EGG), self.x, self.y, probability=prob)
return True
return False
def draw(self, screen):
if self.sprite is None:
return
rotated = pygame.transform.rotate(self.sprite, -math.degrees(self.angle))
rect = rotated.get_rect(center=(self.x, self.y))
tint = self.get_tint()
if tint[3] > 0:
tint_surf = pygame.Surface(rotated.get_size(), pygame.SRCALPHA)
tint_surf.fill(tint)
rotated.blit(tint_surf, (0, 0), special_flags=pygame.BLEND_RGBA_MULT)
screen.blit(rotated, rect)
def draw_help_panel(screen):
panel_x = WIDTH - 260
panel_y = 20
panel_w = 240
panel_h = 300
s = pygame.Surface((panel_w, panel_h), pygame.SRCALPHA)
s.fill((0, 0, 0, 80))
screen.blit(s, (panel_x, panel_y))
pygame.draw.rect(screen, WHITE, (panel_x, panel_y, panel_w, panel_h), 1)
lines = [
("Управление:", WHITE),
("Щ - создать щуку", YELLOW),
("1 - установить приманку", YELLOW),
("Стрелки - управлять приманкой", YELLOW),
("И - создать икру", YELLOW),
("З - зима/лето", YELLOW),
("Выделение мышью - поймать", YELLOW),
("существ в области", YELLOW),
]
y_offset = panel_y + 10
for text, color in lines:
surf = help_font.render(text, True, color)
screen.blit(surf, (panel_x + 10, y_offset))
y_offset += 22
leeches = []
for _ in range(100):
x, y = random_leech_position()
leeches.append(Leech(x, y))
pikes = []
eggs = []
bait = None
last_spawn_time = pygame.time.get_ticks()
spawn_interval = 10000
last_reproduction_time = pygame.time.get_ticks()
reproduction_interval = 15000
catch_message = ""
catch_message_timer = 0
selecting = False
select_start = None
select_end = None
grid_rect = None
grid_timer = 0
running = True
while running:
current_time = pygame.time.get_ticks()
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.unicode == 'щ':
x, y = random_water_position(small=True)
pikes.append(Pike(x, y))
if event.key == pygame.K_ESCAPE:
running = False
if event.key == pygame.K_1:
mx, my = pygame.mouse.get_pos()
mx = max(SHORE_WIDTH, min(WIDTH - SHORE_WIDTH, mx))
my = max(SHORE_WIDTH, min(HEIGHT - SHORE_WIDTH, my))
bait = Bait(mx, my)
if event.key == pygame.K_b:
mx, my = pygame.mouse.get_pos()
mx = max(SHORE_WIDTH, min(WIDTH - SHORE_WIDTH, mx))
my = max(SHORE_WIDTH, min(HEIGHT - SHORE_WIDTH, my))
for _ in range(40):
if len(eggs) < MAX_EGGS:
angle = random.uniform(0, 2 * math.pi)
dist = random.uniform(10, 30)
x = mx + dist * math.cos(angle)
y = my + dist * math.sin(angle)
x = max(SHORE_WIDTH + 5, min(WIDTH - SHORE_WIDTH - 5, x))
y = max(SHORE_WIDTH + 5, min(HEIGHT - SHORE_WIDTH - 5, y))
eggs.append(Egg(x, y))
if event.key == pygame.K_p:
toggle_winter()
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
selecting = True
select_start = event.pos
select_end = event.pos
if event.type == pygame.MOUSEMOTION and selecting:
select_end = event.pos
if event.type == pygame.MOUSEBUTTONUP and event.button == 1 and selecting:
selecting = False
x1, y1 = select_start
x2, y2 = select_end
left = min(x1, x2)
right = max(x1, x2)
top = min(y1, y2)
bottom = max(y1, y2)
rect = pygame.Rect(left, top, right - left, bottom - top)
for pike in pikes[:]:
if rect.collidepoint(pike.x, pike.y):
pikes.remove(pike)
for egg in eggs[:]:
if rect.collidepoint(egg.x, egg.y):
eggs.remove(egg)
for leech in leeches[:]:
if rect.collidepoint(leech.x, leech.y):
leeches.remove(leech)
grid_rect = rect
grid_timer = current_time + GRID_DISPLAY_TIME
if not winter_active and current_time - last_spawn_time >= spawn_interval:
last_spawn_time = current_time
current_count = len(leeches)
if current_count < MAX_LEECHES:
new_count = min(current_count * 3, MAX_LEECHES)
for _ in range(new_count - current_count):
x, y = random_leech_position()
leeches.append(Leech(x, y))
if not winter_active and current_time - last_reproduction_time >= reproduction_interval:
last_reproduction_time = current_time
mature = [p for p in pikes if p.length >= 50 and p.state == "normal"]
if len(mature) >= 2:
parent = random.choice(mature)
spawn_x, spawn_y = parent.x, parent.y
num_eggs = int(1 * parent.length)
if len(eggs) + num_eggs <= MAX_EGGS:
for _ in range(num_eggs):
angle = random.uniform(0, 2 * math.pi)
dist = random.uniform(10, 30)
x = spawn_x + dist * math.cos(angle)
y = spawn_y + dist * math.sin(angle)
x = max(SHORE_WIDTH + 5, min(WIDTH - SHORE_WIDTH - 5, x))
y = max(SHORE_WIDTH + 5, min(HEIGHT - SHORE_WIDTH - 5, y))
eggs.append(Egg(x, y))
add_message(random.choice(PHRASES_SPAWN), parent.x, parent.y, probability=1.0)
parent.state = "fleeing_from_eggs"
angle = random.uniform(0, 2 * math.pi)
target_x = spawn_x + 500 * math.cos(angle)
target_y = spawn_y + 500 * math.sin(angle)
target_x = max(SHORE_WIDTH, min(WIDTH - SHORE_WIDTH, target_x))
target_y = max(SHORE_WIDTH, min(HEIGHT - SHORE_WIDTH, target_y))
parent.target_point = (target_x, target_y)
parent.target = None
add_message(random.choice(PHRASES_FLEE), parent.x, parent.y, probability=1.0)
for egg in eggs[:]:
if egg.update(pikes):
eggs.remove(egg)
if bait is not None:
bait.update(keys)
for leech in leeches:
leech.update()
for pike in pikes:
pike.update(leeches, pikes, eggs, bait, current_time)
for pike in pikes[:]:
if pike in pikes:
result = pike.check_eat(leeches, pikes, eggs, bait, current_time)
if result == "bait_eaten":
pikes.remove(pike)
bait = None
catch_message = "Рыба выловлена!"
catch_message_timer = current_time + 3000
for pike in pikes[:]:
if pike.state in ("wintering", "post_winter"):
continue
if not pike.max_length_reached and pike.length >= 160:
pike.max_length_reached = True
pike.time_at_max = current_time
if pike.max_length_reached and (current_time - pike.time_at_max) > 6000:
if not pike.has_spawned_on_death:
pike.has_spawned_on_death = True
for _ in range(DEATH_SPAWN_EGGS):
if len(eggs) < MAX_EGGS:
angle = random.uniform(0, 2 * math.pi)
dist = random.uniform(10, 30)
x = pike.x + dist * math.cos(angle)
y = pike.y + dist * math.sin(angle)
x = max(SHORE_WIDTH + 5, min(WIDTH - SHORE_WIDTH - 5, x))
y = max(SHORE_WIDTH + 5, min(HEIGHT - SHORE_WIDTH - 5, y))
eggs.append(Egg(x, y))
add_message(random.choice(PHRASES_DEATH_OLD), pike.x, pike.y, probability=1.0)
pikes.remove(pike)
continue
if pike.length < 160 and (current_time - pike.last_meal_time) > STARVATION_TIME:
add_message(random.choice(PHRASES_DEATH_STARVE), pike.x, pike.y, probability=1.0)
pikes.remove(pike)
screen.blit(sand_surf, (0, 0))
screen.blit(water_surf, (0, 0))
if ice_surf is not None:
screen.blit(ice_surf, (0, 0))
for leech in leeches:
leech.draw(screen)
for egg in eggs:
egg.draw(screen)
if bait is not None:
bait.draw(screen)
for pike in pikes:
pike.draw(screen)
# Отрисовка панели подсказок (поверх всего)
draw_help_panel(screen)
messages = [msg for msg in messages if msg['timer'] > current_time]
if len(messages) > MAX_MESSAGES:
messages = messages[-MAX_MESSAGES:]
for msg in messages:
text_surf = speech_font.render(msg['text'], True, WHITE)
outline_surf = speech_font.render(msg['text'], True, BLACK)
x_pos = msg['x'] - text_surf.get_width() // 2
y_pos = msg['y'] - 30 - text_surf.get_height() // 2
for dx, dy in [(-1, -1), (-1, 1), (1, -1), (1, 1)]:
screen.blit(outline_surf, (x_pos + dx, y_pos + dy))
screen.blit(text_surf, (x_pos, y_pos))
if selecting and select_start and select_end:
x1, y1 = select_start
x2, y2 = select_end
left = min(x1, x2)
right = max(x1, x2)
top = min(y1, y2)
bottom = max(y1, y2)
s = pygame.Surface((right - left, bottom - top), pygame.SRCALPHA)
s.fill((255, 255, 255, 30))
screen.blit(s, (left, top))
pygame.draw.rect(screen, WHITE, (left, top, right - left, bottom - top), 1)
if grid_rect and current_time < grid_timer:
left, top, w, h = grid_rect
cell_size = 4
for y in range(top, top + h + 1, cell_size):
if y <= HEIGHT:
pygame.draw.line(screen, BLACK, (left, y), (left + w, y), 1)
for x in range(left, left + w + 1, cell_size):
if x <= WIDTH:
pygame.draw.line(screen, BLACK, (x, top), (x, top + h), 1)
if grid_rect and current_time >= grid_timer:
grid_rect = None
text = font.render(f"Пиявок: {len(leeches)} Щук: {len(pikes)} Икринок: {len(eggs)}", True, WHITE)
screen.blit(text, (10, 10))
if catch_message and current_time < catch_message_timer:
msg_surf = big_font.render(catch_message, True, YELLOW)
screen.blit(msg_surf, (WIDTH // 2 - msg_surf.get_width() // 2, 50))
elif catch_message:
catch_message = ""
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
Симулятор эволюции[править]
- (мне надоело создавать одноимённую игру и вот другая, совсем не историчная версия). Игра ещё не смешная, потом исправлю.
- Геймплей: создавать новые виды, совершенствовать их и не дать им быть съеденными. Также можно управлять охотой своих хищников и юзать их интеллект (у травоядных он пока бесполезный). (Если что, y = yes, n = no).
- Цель Игры — набрать максимум очков за turns ходов. (turns можно и нужно выставить), можно создать много хищников и выносить ботов
import random
import sys
turns = int(input("Сколько ходов должна длиться игра(оптимально 3 - 7, меньше точно не нужно, больше - будет слишком долго)"))
# ---------- Классы ----------
class Creature:
def __init__(self, name="Существо"):
self.name = name
self.size = 1
self.population = 1
self.intelligence = 1
self.speed = 1
self.weapons = 1
self.armor = 1
self.camouflage = 1
self.vision = 1
self.is_predator = False
def is_alive(self):
return self.population > 0
def apply_effects(self, effects):
for attr, delta in effects.items():
if hasattr(self, attr) and attr != 'is_predator':
current = getattr(self, attr)
new_val = current + delta
if attr == 'population':
new_val = max(0, min(10, new_val))
else:
new_val = max(1, min(10, new_val))
setattr(self, attr, new_val)
def add_population(self, delta):
new_val = self.population + delta
new_val = max(0, min(10, new_val))
self.population = new_val
def total_score(self):
return (self.size + self.population + self.intelligence +
self.speed + self.weapons + self.armor +
self.camouflage + self.vision)
def __str__(self):
status = "Хищник" if self.is_predator else "Травоядное"
alive = "жив" if self.is_alive() else "ВЫМЕР"
return (f"{self.name} ({status}, {alive}): "
f"Размер={self.size}, Популяция={self.population}, "
f"Интеллект={self.intelligence}, Скорость={self.speed}, "
f"Вооружение={self.weapons}, Защита={self.armor}, "
f"Маскировка={self.camouflage}, Обзор={self.vision}")
class Card:
def __init__(self, name, effects):
self.name = name
self.effects = effects
def apply(self, creature):
creature.apply_effects(self.effects)
def __str__(self):
return self.name
# ---------- Пул карт ----------
def create_card_pool():
base_pool = [
Card("Увеличение размера", {"size": 1}),
Card("Увеличение популяции", {"population": 1}),
Card("Когти", {"weapons": 2, "speed": -1}),
Card("Панцирь", {"armor": 3, "speed": -1}),
Card("Крылья", {"speed": 2, "size": -1}),
Card("Камуфляж", {"camouflage": 2}),
Card("Острое зрение", {"vision": 2}),
Card("Ум", {"intelligence": 2}),
Card("Рога", {"weapons": 1, "size": 1}),
Card("Шипы", {"armor": 1, "weapons": 1}),
Card("Ядовитые зубы", {"weapons": 2, "speed": -1}),
Card("Толстая кожа", {"armor": 2, "speed": -1}),
]
new_cards = [
Card("Быстрое размножение", {"population": 2}),
Card("Укрепление панциря", {"armor": 2, "speed": -1}),
Card("Развитый мозг", {"intelligence": 2}),
Card("Острые когти", {"weapons": 2}),
Card("Длинные ноги", {"speed": 2, "size": -1}),
Card("Миметический камуфляж", {"camouflage": 3, "population": -1}),
Card("Эхолокация", {"vision": 2, "intelligence": 1}),
Card("Ядовитые шипы", {"weapons": 1, "armor": 1}),
Card("Крепкий скелет", {"size": 1, "armor": 1}),
Card("Повышенная плодовитость", {"population": 1, "size": -1}),
Card("Способность к планированию", {"intelligence": 2, "speed": -1}),
Card("Ночное зрение", {"vision": 2, "speed": -1}),
Card("Терморегуляция", {"size": 1, "speed": 1}),
Card("Органы чувств", {"vision": 1, "camouflage": 1}),
Card("Социальность", {"population": 2, "intelligence": 1}),
Card("Хищнические инстинкты", {"weapons": 2, "speed": 1}),
Card("Защитная окраска", {"camouflage": 2, "size": -1}),
Card("Мускулистость", {"speed": 2, "weapons": 1}),
Card("Регенерация", {"armor": 2, "population": 1}),
Card("Симбиоз", {"population": 1, "intelligence": 2}),
Card("Стратегическое мышление", {"intelligence": 3, "speed": -2}),
Card("Сверхчувствительность", {"vision": 3, "camouflage": -1}),
Card("Токсичная кровь", {"weapons": 1, "armor": 2}),
Card("Колючки", {"armor": 2, "speed": -2}),
Card("Гипноз", {"intelligence": 2, "vision": 1}),
]
return base_pool + new_cards
def random_card(pool):
return random.choice(pool)
def generate_cards(pool, count):
return [random_card(pool) for _ in range(count)]
# ---------- Вспомогательные функции ----------
PARAM_NAMES_RU = {
"size": "Размер",
"population": "Популяция",
"intelligence": "Интеллект",
"speed": "Скорость",
"weapons": "Вооружение",
"armor": "Защита",
"camouflage": "Маскировка",
"vision": "Обзор"
}
def print_header():
print("\n" + "=" * 60)
print(" ЭВОЛЮЦИЯ: пошаговая игра (хищники!)")
print("=" * 60)
def print_stats(all_creatures):
alive = [c for c in all_creatures if c.is_alive()]
if not alive:
print("Все существа вымерли!")
return
names = [c.name[:15] for c in alive]
col_width = max(len(name) for name in names) + 2
col_width = max(col_width, 10)
params = ["size", "population", "intelligence", "speed",
"weapons", "armor", "camouflage", "vision"]
param_names = PARAM_NAMES_RU
print("\nТекущее состояние (живые виды):")
header = "Параметр".ljust(col_width)
for c in alive:
status = "Х" if c.is_predator else "Т"
short_name = c.name[:15]
header += f"| {short_name.ljust(col_width-4)} {status}"
print(header)
print("-" * len(header))
for p in params:
row = param_names[p].ljust(col_width)
for c in alive:
val = str(getattr(c, p))
row += f"| {val.ljust(col_width-2)}"
print(row)
print("-" * len(header))
row = "Сумма".ljust(col_width)
for c in alive:
val = str(c.total_score())
row += f"| {val.ljust(col_width-2)}"
print(row)
print()
def get_player_action(card, creature):
while True:
print(f"\nКарта: {card.name}")
effects_parts = []
for key, val in card.effects.items():
ru_name = PARAM_NAMES_RU.get(key, key)
sign = "+" if val >= 0 else ""
effects_parts.append(f"{ru_name}: {sign}{val}")
effects_str = ", ".join(effects_parts)
print(f"Эффекты: {effects_str}")
choice = input("Применить? (y/n): ").strip().lower()
if choice in ('y', 'n'):
return choice == 'y'
print("Введите 'y' или 'n'.")
def bot_turn_for_creature(creature, pool, card_count):
cards = generate_cards(pool, card_count)
for card in cards:
if random.random() < 0.5:
card.apply(creature)
else:
creature.add_population(1)
# ---------- Функции для интеллекта ----------
def apply_temporary_debuff(prey, allocation):
"""Временно уменьшает параметры жертвы, возвращает старые значения."""
old_values = {}
for attr, amount in allocation.items():
if attr in ['vision', 'speed', 'weapons', 'armor']:
old = getattr(prey, attr)
old_values[attr] = old
new_val = max(1, old - amount)
setattr(prey, attr, new_val)
return old_values
def restore_parameters(prey, old_values):
"""Восстанавливает параметры жертвы."""
for attr, val in old_values.items():
setattr(prey, attr, val)
def can_hunt(predator, prey):
if predator is prey:
return False
if not predator.is_alive() or not prey.is_alive():
return False
return (predator.vision >= prey.camouflage and
prey.vision <= predator.camouflage and
predator.speed > prey.speed and
predator.weapons >= prey.armor and
prey.weapons <= predator.armor)
# ---------- Выбор цели для игрока ----------
def choose_prey_for_player(predator, all_creatures, player_creatures, bot_species_list):
"""
Запрашивает у игрока цель для охоты.
Возвращает выбранное существо или None, если охота пропущена.
"""
# Собираем список всех живых существ, кроме хищника
prey_options = [c for c in all_creatures if c.is_alive() and c is not predator]
if not prey_options:
print("Нет доступной добычи.")
return None
# Выводим список с нумерацией
print("\nДоступные цели для охоты:")
# Сначала боты
for bot_idx, bot_species in enumerate(bot_species_list, start=1):
bot_alive = [c for c in bot_species if c.is_alive() and c is not predator]
if bot_alive:
print(f" Бот{bot_idx}:")
for idx, c in enumerate(bot_alive, start=1):
print(f" {bot_idx} {idx} -> {c.name} (поп.{c.population})")
# Затем игрок (свои виды)
player_alive = [c for c in player_creatures if c.is_alive() and c is not predator]
if player_alive:
print(" Игрок:")
for idx, c in enumerate(player_alive, start=1):
print(f" И {idx} -> {c.name} (поп.{c.population})")
while True:
inp = input("Введите 'номер_бота номер_вида' (например, '1 3') или 'И номер_вида' для своего вида, или 0 для пропуска: ").strip()
if inp == '0':
return None
parts = inp.split()
if len(parts) == 2:
if parts[0].upper() == 'И':
try:
idx = int(parts[1]) - 1
if 0 <= idx < len(player_alive):
return player_alive[idx]
else:
print("Неверный номер вида игрока.")
except ValueError:
print("Введите число после 'И'.")
else:
try:
bot_num = int(parts[0]) - 1
species_idx = int(parts[1]) - 1
if 0 <= bot_num < len(bot_species_list):
bot_alive = [c for c in bot_species_list[bot_num] if c.is_alive() and c is not predator]
if 0 <= species_idx < len(bot_alive):
return bot_alive[species_idx]
else:
print("Неверный номер вида для этого бота.")
else:
print("Неверный номер бота (допустимо 1..3).")
except ValueError:
print("Введите числа.")
else:
print("Введите два значения через пробел.")
# ---------- Решение бота использовать интеллект ----------
def bot_decide_intelligence(predator, prey):
"""
Бот использует интеллект только если без него охота невозможна,
а с максимальным ослаблением (используя весь интеллект) становится возможной.
Возвращает allocation (словарь) или None, если интеллект не используется.
"""
if predator.intelligence <= 0:
return None
# Проверяем, возможна ли охота без ослабления
if can_hunt(predator, prey):
return None # уже можно охотиться, не тратим интеллект
# Пытаемся ослабить prey настолько, чтобы охота стала возможной
# Параметры, которые можно ослабить: vision, speed, weapons, armor
attrs = ['vision', 'speed', 'weapons', 'armor']
# Создаём копию prey для тестирования
import copy
test_prey = copy.copy(prey) # неглубокое копирование, но нам нужны только числа
# Применим ослабление по всем параметрам до предела (минимум 1)
alloc = {}
for attr in attrs:
max_dec = getattr(test_prey, attr) - 1
# используем весь интеллект, но не более max_dec
dec = min(predator.intelligence, max_dec)
alloc[attr] = dec
setattr(test_prey, attr, getattr(test_prey, attr) - dec)
# Проверяем, стала ли охота возможной
if can_hunt(predator, test_prey):
# Теперь нужно распределить реально используемые очки (не превышая интеллект)
# Мы уже выделили dec, но сумма может быть меньше интеллекта, если не хватило параметров
# Возвращаем allocation, где сумма <= intel
# Убедимся, что сумма не превышает intel (может быть меньше)
total = sum(alloc.values())
if total > predator.intelligence:
# уменьшаем пропорционально (но это маловероятно, т.к. мы ограничивали)
pass
return alloc
else:
return None
# ---------- Фаза охоты (переработана) ----------
def hunting_phase(all_creatures, player_creatures, bot_species_list):
predators = [c for c in all_creatures if c.is_alive() and c.is_predator]
random.shuffle(predators)
for predator in predators:
is_player = predator in player_creatures
# Выбор цели
if is_player:
prey = choose_prey_for_player(predator, all_creatures, player_creatures, bot_species_list)
if prey is None:
# Игрок пропустил охоту – хищник не ест и вымирает
predator.population = 0
continue
else:
# Бот выбирает случайную живую цель
alive_prey = [c for c in all_creatures if c.is_alive() and c is not predator]
if not alive_prey:
predator.population = 0
continue
prey = random.choice(alive_prey)
# Решение использовать интеллект
use_intel = False
allocation = {}
if is_player:
# Игрок решает сам
choice = input(f"Использовать интеллект ({predator.intelligence}) для ослабления {prey.name}? (y/n): ").strip().lower()
if choice == 'y' and predator.intelligence > 0:
use_intel = True
# Запрос распределения
max_intel = predator.intelligence
print(f"Интеллект: {max_intel}. Распределите очки по параметрам (обзор, скорость, вооружение, защита).")
while True:
try:
inp = input("Введите четыре числа через пробел (сумма <= {}): ".format(max_intel)).strip().split()
if len(inp) != 4:
print("Нужно ровно четыре числа.")
continue
nums = [int(x) for x in inp]
if sum(nums) > max_intel:
print(f"Сумма {sum(nums)} превышает интеллект {max_intel}.")
continue
if any(n < 0 for n in nums):
print("Числа должны быть неотрицательными.")
continue
allocation = {'vision': nums[0], 'speed': nums[1], 'weapons': nums[2], 'armor': nums[3]}
break
except ValueError:
print("Введите целые числа.")
else:
# Бот решает использовать интеллект только если это даёт возможность охоты
alloc = bot_decide_intelligence(predator, prey)
if alloc is not None:
use_intel = True
allocation = alloc
print(f"{predator.name} использует интеллект для ослабления {prey.name}.")
# Применяем ослабление
old_values = {}
if use_intel and allocation:
old_values = apply_temporary_debuff(prey, allocation)
print(f"Ослабление применено: {prey.name} параметры уменьшены.")
# Охота (до 3 попыток)
successful_hunts = 0
for _ in range(3):
if not prey.is_alive():
break
if can_hunt(predator, prey):
prey.add_population(-1)
predator.add_population(1)
successful_hunts += 1
if successful_hunts == 3:
break
# Восстанавливаем параметры жертвы
if old_values:
restore_parameters(prey, old_values)
# Если не удалось съесть ни разу – вымирает
if successful_hunts == 0:
predator.population = 0
def grow_herbivores(all_creatures):
for c in all_creatures:
if c.is_alive() and not c.is_predator:
c.add_population(1)
# ---------- Смена статуса ----------
def player_switch_predator(creature, turn, all_creatures):
if turn <= 1 or not creature.is_alive():
return
while True:
print(f"\n{creature.name}: сейчас вы {'хищник' if creature.is_predator else 'травоядное'}.")
choice = input("Хотите сменить статус? (y/n): ").strip().lower()
if choice == 'n':
break
elif choice == 'y':
if creature.is_predator:
creature.is_predator = False
print("Теперь травоядное.")
break
else:
# Игрок может стать хищником без ограничений
creature.is_predator = True
print("Теперь хищник!")
break
else:
print("Введите 'y' или 'n'.")
def bot_switch_predator(creature, turn, all_creatures):
if turn <= 1 or not creature.is_alive():
return
if random.random() < 0.5:
if not creature.is_predator:
# Бот может стать хищником только если есть добыча
if has_any_prey(creature, all_creatures):
creature.is_predator = True
else:
creature.is_predator = False
def has_any_prey(predator, all_creatures):
for other in all_creatures:
if other is not predator and other.is_alive():
if can_hunt(predator, other):
return True
return False
# ---------- Создание нового вида ----------
def create_new_species_for_player(player_creatures):
candidates = [c for c in player_creatures if c.is_alive() and c.population >= 2]
if not candidates:
print("Нет видов с популяцией ≥2, нельзя создать новый вид.")
return False
print("\n--- Создание нового вида (игрок) ---")
for i, c in enumerate(candidates):
print(f"{i+1}. {c.name} (популяция: {c.population})")
while True:
try:
choice = input(f"Выберите родительский вид (1-{len(candidates)}) или 0 для отмены: ").strip()
if choice == '0':
return False
idx = int(choice) - 1
if 0 <= idx < len(candidates):
parent = candidates[idx]
break
else:
print("Неверный номер.")
except ValueError:
print("Введите число.")
parent.add_population(-2)
child = Creature(f"Игрок, вид{len(player_creatures)+1}")
for attr in ['size', 'intelligence', 'speed', 'weapons', 'armor', 'camouflage', 'vision', 'is_predator']:
setattr(child, attr, getattr(parent, attr))
child.population = 1
player_creatures.append(child)
print(f"Создан новый вид: {child.name} (популяция 1, параметры унаследованы от {parent.name})")
return True
def create_new_species_for_bot(bot_species, bot_name):
candidates = [c for c in bot_species if c.is_alive() and c.population >= 2]
if not candidates:
return False
parent = random.choice(candidates)
parent.add_population(-2)
child = Creature(f"{bot_name}, вид{len(bot_species)+1}")
for attr in ['size', 'intelligence', 'speed', 'weapons', 'armor', 'camouflage', 'vision', 'is_predator']:
setattr(child, attr, getattr(parent, attr))
child.population = 1
bot_species.append(child)
return True
def remove_dead(species_list):
species_list[:] = [c for c in species_list if c.is_alive()]
# ---------- Основная игра ----------
def main():
random.seed()
player_creatures = [Creature("Игрок, вид1")]
bot_species_list = [
[Creature("Бот1, вид1")],
[Creature("Бот2, вид1")],
[Creature("Бот3, вид1")]
]
bot_split_counters = [random.randint(1, 4) for _ in range(3)]
card_pool = create_card_pool()
print_header()
print(f"Игра будет длиться {turns} ходов.")
print("Цель: набрать максимальную сумму очков (суммируются все ваши виды).")
print("В начале каждого хода можно создать новый вид, пожертвовав 2 популяции.")
print("Боты тоже могут создавать новые виды (примерно раз в 2-5 ходов).")
print("Мёртвые виды автоматически удаляются.")
print("Добавлена механика интеллекта: хищник может ослабить жертву перед охотой.")
print("Игрок может стать хищником без ограничений (со 2-го хода).")
print("Охота полностью контролируется игроком – выбор цели перед каждой атакой.")
input("Нажмите Enter, чтобы начать...")
for turn in range(1, turns + 1):
print(f"\n--- Ход {turn} ---")
# 0. Создание новых видов у ботов
for i, bot_species in enumerate(bot_species_list):
bot_split_counters[i] -= 1
if bot_split_counters[i] <= 0:
success = create_new_species_for_bot(bot_species, f"Бот{i+1}")
if success:
print(f"Бот{i+1} создал новый вид!")
bot_split_counters[i] = random.randint(2, 5)
# 1. Создание нового вида у игрока
create_new_species_for_player(player_creatures)
# Собираем всех существ
all_creatures = player_creatures + [c for bot in bot_species_list for c in bot]
# 2. Смена статуса для игрока
for creature in player_creatures:
if creature.is_alive():
player_switch_predator(creature, turn, all_creatures)
# Смена статуса для ботов
for bot_species in bot_species_list:
for creature in bot_species:
if creature.is_alive():
bot_switch_predator(creature, turn, all_creatures)
# 3. Показываем состояние
print_stats(all_creatures)
# 4. Ход каждого вида игрока
for creature in player_creatures:
if not creature.is_alive():
continue
print(f"\n--- Ход вида {creature.name} ---")
cards_for_player = random.randint(2, 5)
player_cards = generate_cards(card_pool, cards_for_player)
print(f"Вы получили {len(player_cards)} карт для {creature.name}:")
for i, card in enumerate(player_cards, 1):
print(f"\nКарта {i}/{len(player_cards)}:")
if get_player_action(card, creature):
card.apply(creature)
print("Карта применена.")
else:
print("Карта пропущена.")
creature.add_population(1)
# 5. Ходы ботов
for bot_species in bot_species_list:
for creature in bot_species:
if not creature.is_alive():
continue
card_count = random.randint(2, 5)
bot_turn_for_creature(creature, card_pool, card_count)
# 6. Обновляем список всех существ (после карт могли появиться новые виды у ботов и игрока)
all_creatures = player_creatures + [c for bot in bot_species_list for c in bot]
# 7. Выводим обновлённую таблицу перед охотой
print("\n--- Состояние перед охотой ---")
print_stats(all_creatures)
# 8. Фаза охоты (с новой логикой управления)
print("\n--- Фаза охоты ---")
hunting_phase(all_creatures, player_creatures, bot_species_list)
# Проверяем, жив ли хоть один вид игрока
player_alive = any(c.is_alive() for c in player_creatures)
if not player_alive:
print("\nВсе ваши виды вымерли! Игра окончена.")
sys.exit(0)
# 9. Прирост травоядных
grow_herbivores(all_creatures)
# 10. Удаляем мёртвых из всех списков
remove_dead(player_creatures)
for bot_species in bot_species_list:
remove_dead(bot_species)
print(f"\n--- Конец хода {turn} ---")
input("Нажмите Enter для следующего хода...")
# Финальная статистика
print("\n" + "=" * 60)
print("ИГРА ОКОНЧЕНА!")
print("=" * 60)
all_creatures = player_creatures + [c for bot in bot_species_list for c in bot]
print_stats(all_creatures)
player_score = sum(c.total_score() for c in player_creatures)
bot_scores = []
for i, bot_species in enumerate(bot_species_list):
score = sum(c.total_score() for c in bot_species)
bot_scores.append((f"Бот{i+1}", score))
print(f"\nИтоговые суммы очков:")
print(f"Игрок: {player_score}")
for name, score in bot_scores:
print(f"{name}: {score}")
all_participants = [("Игрок", player_score)] + bot_scores
max_score = max(score for _, score in all_participants)
winners = [name for name, score in all_participants if score == max_score]
if len(winners) == 1:
print(f"\nПобедитель: {winners[0]} с суммой {max_score} очков!")
if winners[0] == "Игрок":
print("Поздравляем!")
else:
print("Попробуйте снова!")
else:
print(f"\nНичья между {', '.join(winners)} с суммой {max_score} очков!")
if __name__ == "__main__":
main()