Участник:Славянск1989
import os
import sys
import random
import shutil
import time
import textwrap
if os.name == 'nt':
os.system('chcp 65001 >nul')
def clear_screen():
if os.name == 'nt':
os.system('cls')
else:
print("\033[H\033[J", end="")
def get_input():
if os.name == 'nt':
import msvcrt
while True:
key = msvcrt.getch()
if key in (b'\xe0', b'\x00'):
arr = msvcrt.getch()
if arr == b'H': return (0, -1)
if arr == b'P': return (0, 1)
if arr == b'K': return (-1, 0)
if arr == b'M': return (1, 0)
elif key == b'\x03': return None
else:
try:
k = key.decode('utf-8').lower()
if k == 'w': return (0, -1)
if k == 's': return (0, 1)
if k == 'a': return (-1, 0)
if k == 'd': return (1, 0)
if k == 'q': return None
if k == 'e' or k == ' ': return 'blow'
except: pass
else:
import tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
if ch == '\x1b':
sys.stdin.read(1)
arr = sys.stdin.read(1)
if arr == 'A': return (0, -1)
if arr == 'B': return (0, 1)
if arr == 'D': return (-1, 0)
if arr == 'C': return (1, 0)
elif ch == '\x03': return None
else:
ch = ch.lower()
if ch in ['w', 's', 'a', 'd', 'q', 'e', ' ']:
if ch == 'w': return (0, -1)
if ch == 's': return (0, 1)
if ch == 'a': return (-1, 0)
if ch == 'd': return (1, 0)
if ch == 'q': return None
if ch == 'e' or ch == ' ': return 'blow'
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return (0, 0)
def main():
player_x, player_y = 0, 0
moves = 0
speed = 0 # <-- Скорость на старте теперь 0
last_dx, last_dy = 0, 0
mushrooms = 0
telescopes = 0
dead_wolves = 0
total_combos = 0
combo_streak = 0
turns_without_mushrooms = 0
grid = {}
wolves = []
burning_trees_cells = set()
turn_events = []
combo_msg = ""
feedback_msg = ""
dead = False
death_msg = ""
is_igniting = False
def get_max_radius(t_count):
rem = t_count
V = 6
while rem > 0:
step = min(rem, V + 2)
rem -= step
if step > 0:
V += 1
return V
def is_visible(dx, dy, t_count):
if abs(dx) <= 6 and abs(dy) <= 6:
return True
rem = t_count
V = 6
while rem > 0:
target_V = V + 1
step = min(rem, V + 2)
if max(abs(dx), abs(dy)) == target_V and min(abs(dx), abs(dy)) <= step - 1:
return True
rem -= step
V += 1
return False
def ignite_tree_group(start_x, start_y):
nonlocal dead_wolves, is_igniting
if is_igniting:
return 0, 0
is_igniting = True
try:
burned_count = 0
ignited_trees = 0
visited = set([(start_x, start_y)])
stack = [(start_x, start_y)]
while stack:
cx, cy = stack.pop()
if grid.get((cx, cy)) == '🌲':
grid[(cx, cy)] = '🔥'
burning_trees_cells.add((cx, cy))
ignited_trees += 1
for w in list(wolves):
if abs(w['x'] - cx) <= 1 and abs(w['y'] - cy) <= 1:
wolves.remove(w)
dead_wolves += 1
burned_count += 1
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
if dx == 0 and dy == 0: continue
nx, ny = cx + dx, cy + dy
if (nx, ny) not in visited:
if (nx, ny) not in grid:
generate_cell(nx, ny)
if grid.get((nx, ny)) == '🌲':
visited.add((nx, ny))
stack.append((nx, ny))
return ignited_trees, burned_count
finally:
is_igniting = False
def generate_cell(x, y):
nonlocal is_igniting
if (x, y) in grid:
return
if x == 0 and y == 0:
grid[(x, y)] = '..'
return
mushroom_prob = 0.05
telescope_prob = 0.01
wolf_prob = max(0.0, (moves * 0.001) - (total_combos * 0.005))
tree_prob = 0.20
fire_prob = 0.02
r = random.random()
if r < tree_prob:
grid[(x, y)] = '🌲'
if not is_igniting and any((x+dx, y+dy) in burning_trees_cells for dx in [-1,0,1] for dy in [-1,0,1] if dx!=0 or dy!=0):
_, w_b = ignite_tree_group(x, y)
if w_b > 0:
turn_events.append(f"🔥 Распространяющийся пожар поглотил волков: {w_b}!")
elif r < tree_prob + fire_prob:
is_near_wolf = False
for w in wolves:
if abs(w['x'] - x) <= 1 and abs(w['y'] - y) <= 1:
is_near_wolf = True
break
if not is_near_wolf:
grid[(x, y)] = '🔥'
else:
grid[(x, y)] = '..'
elif r < tree_prob + fire_prob + mushroom_prob:
grid[(x, y)] = '🍄'
elif r < tree_prob + fire_prob + mushroom_prob + telescope_prob:
grid[(x, y)] = '🔭'
elif r < tree_prob + fire_prob + mushroom_prob + telescope_prob + wolf_prob:
is_near_fire = False
for adx in [-1, 0, 1]:
for ady in [-1, 0, 1]:
if grid.get((x + adx, y + ady)) == '🔥':
is_near_fire = True
break
if not is_near_fire:
wolves.append({'x': x, 'y': y, 'just_spawned': True})
grid[(x, y)] = '..'
else:
grid[(x, y)] = '..'
else:
grid[(x, y)] = '..'
def generate_viewport():
R = get_max_radius(telescopes)
for y in range(player_y - R, player_y + R + 1):
for x in range(player_x - R, player_x + R + 1):
if is_visible(x - player_x, y - player_y, telescopes):
generate_cell(x, y)
def is_safe_for_wolf(nx, ny):
if grid.get((nx, ny)) == '🌲': return False
if grid.get((nx, ny)) == '🔥': return False
for adx in [-1, 0, 1]:
for ady in [-1, 0, 1]:
if grid.get((nx + adx, ny + ady)) == '🔥':
return False
if any(other['x'] == nx and other['y'] == ny for other in wolves):
return False
return True
def render_rain():
clear_screen()
term_size = shutil.get_terminal_size((80, 24))
term_width = term_size.columns
term_height = term_size.lines
# Разбиваем стату на 3 компактные строки
h1 = f"🍄 Грибов: {mushrooms} | 🔭 Телескопов: {telescopes}"
h2 = f"💀 Волков: {dead_wolves} | 🔥 Комбо: {total_combos} | ⏱ Ходы: {moves}"
h3 = f"🚀 Скор: 0 🛑 | 💨 Дуть: E/Пробел | Выход: Q"
feedback = "🌧️ ПРОЛИВНОЙ ДОЖДЬ! Скорость потеряна, костры тухнут... 🌧️"
# Переносим длинный текст с помощью textwrap (макс 45 символов, чтобы влезло на смартфонах)
wrapped_feedback = textwrap.wrap(feedback, width=min(term_width, 45))
R = get_max_radius(telescopes)
grid_width_visual = (2 * R + 1) * 2
grid_height = 2 * R + 1
header_height = 3 + len(wrapped_feedback) + 1 # 3 строки статы + строки сообщения + отступ
total_height = header_height + grid_height
v_pad = max(0, (term_height - total_height) // 2)
h_pad_grid = max(0, (term_width - grid_width_visual) // 2)
print("\n" * v_pad, end="")
print(" " * max(0, (term_width - len(h1)) // 2) + h1)
print(" " * max(0, (term_width - len(h2)) // 2) + h2)
print(" " * max(0, (term_width - len(h3)) // 2) + h3)
for line in wrapped_feedback:
print(" " * max(0, (term_width - len(line)) // 2) + line)
print()
for y in range(player_y - R, player_y + R + 1):
row_str = ""
for x in range(player_x - R, player_x + R + 1):
if not is_visible(x - player_x, y - player_y, telescopes):
row_str += " "
elif x == player_x and y == player_y:
row_str += "🚴♀️"
else:
row_str += "🌧️"
print(" " * h_pad_grid + row_str)
def render():
clear_screen()
term_size = shutil.get_terminal_size((80, 24))
term_width = term_size.columns
term_height = term_size.lines
dir_emoji = ""
if last_dx == 0 and last_dy == -1: dir_emoji = "⬆️"
elif last_dx == 0 and last_dy == 1: dir_emoji = "⬇️"
elif last_dx == -1 and last_dy == 0: dir_emoji = "⬅️"
elif last_dx == 1 and last_dy == 0: dir_emoji = "➡️"
elif speed == 0: dir_emoji = "🛑"
speed_str = f"{speed} {dir_emoji}".strip()
# Разделение заголовков на 3 строки
h1 = f"🍄 Грибов: {mushrooms} | 🔭 Телескопов: {telescopes}"
h2 = f"💀 Волков: {dead_wolves} | 🔥 Комбо: {total_combos} | ⏱ Ходы: {moves}"
h3 = f"🚀 Скор: {speed_str} | 💨 Дуть: E/Пробел | Выход: Q"
if feedback_msg:
wrapped_feedback = textwrap.wrap(feedback_msg, width=min(term_width, 45))
else:
wrapped_feedback = []
R = get_max_radius(telescopes)
grid_width_visual = (2 * R + 1) * 2
grid_height = 2 * R + 1
header_height = 3 + max(1, len(wrapped_feedback)) + 1
total_height = header_height + grid_height + (3 if dead else 0)
v_pad = max(0, (term_height - total_height) // 2)
h_pad_grid = max(0, (term_width - grid_width_visual) // 2)
print("\n" * v_pad, end="")
print(" " * max(0, (term_width - len(h1)) // 2) + h1)
print(" " * max(0, (term_width - len(h2)) // 2) + h2)
print(" " * max(0, (term_width - len(h3)) // 2) + h3)
if wrapped_feedback:
for line in wrapped_feedback:
print(" " * max(0, (term_width - len(line)) // 2) + line)
else:
print()
print()
for y in range(player_y - R, player_y + R + 1):
row_str = ""
for x in range(player_x - R, player_x + R + 1):
if not is_visible(x - player_x, y - player_y, telescopes):
row_str += " "
elif dead and x == player_x and y == player_y:
row_str += "💀"
elif not dead and x == player_x and y == player_y:
row_str += "🚴♀️"
else:
is_wolf = any(w['x'] == x and w['y'] == y for w in wolves)
if is_wolf:
row_str += "🐺"
else:
row_str += grid.get((x, y), '..')
print(" " * h_pad_grid + row_str)
if dead:
msg1 = f"💀 ИГРА ОКОНЧЕНА! {death_msg}"
wrapped_death = textwrap.wrap(msg1, width=min(term_width, 45))
msg2 = "Нажмите любую клавишу для выхода..."
print("\n", end="")
for line in wrapped_death:
print(" " * max(0, (term_width - len(line)) // 2) + line)
print(" " * max(0, (term_width - len(msg2)) // 2) + msg2)
generate_viewport()
while True:
if turn_events or combo_msg:
feedback_msg = " | ".join(turn_events)
if combo_msg:
feedback_msg = f"{feedback_msg} {combo_msg}".strip(" | ")
else:
feedback_msg = ""
render()
turn_events = []
combo_msg = ""
if dead:
get_input()
break
inp = get_input()
if inp is None:
break
if inp == (0, 0):
continue
combo_action_this_turn = False
if inp == 'blow':
fires_around = 0
trees_ignited_by_blow = 0
wolves_burned_by_blow = 0
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
if dx == 0 and dy == 0: continue
if grid.get((player_x + dx, player_y + dy)) == '🔥':
fires_around += 1
tx, ty = player_x + 2*dx, player_y + 2*dy
generate_cell(tx, ty)
if grid.get((tx, ty)) == '🌲':
i_t, w_b = ignite_tree_group(tx, ty)
trees_ignited_by_blow += i_t
wolves_burned_by_blow += w_b
speed = 0
last_dx, last_dy = 0, 0
moves += 1
turns_without_mushrooms += 1
if fires_around == 0:
turn_events.append("💨 Вы подули, но костра рядом нет.")
elif trees_ignited_by_blow > 0:
combo_action_this_turn = True
msg = f"🌲 Вы успешно подожгли лес!"
if wolves_burned_by_blow > 0:
msg += f" Волки сгорели: {wolves_burned_by_blow}!"
turn_events.append(msg)
else:
turn_events.append("💨 Вы подули на костёр, но ни одно дерево не загорелось.")
generate_viewport()
else:
dx, dy = inp
if dx == last_dx and dy == last_dy and speed > 0:
current_speed = speed + 1
else:
current_speed = 1
next_x, next_y = player_x + dx, player_y + dy
generate_cell(next_x, next_y)
if grid[(next_x, next_y)] == '🌲':
continue
mushrooms_this_turn = 0
telescopes_this_turn = 0
wolves_killed_this_turn = 0
for step in range(1, current_speed + 1):
cx = player_x + dx * step
cy = player_y + dy * step
generate_cell(cx, cy)
if grid[(cx, cy)] == '🔥':
dead = True
death_msg = "Вы сдуру заехали прямо в костёр и сгорели заживо!"
player_x, player_y = cx, cy
break
if grid[(cx, cy)] == '🌲':
dead = True
death_msg = "Вы на огромной скорости влетели в дерево и разбились!"
player_x, player_y = cx, cy
break
wolf_here = next((w for w in wolves if w['x'] == cx and w['y'] == cy), None)
if wolf_here:
if step == current_speed:
dead = True
death_msg = "Вы остановились прямо перед волком, и он вас загрыз!"
player_x, player_y = cx, cy
wolves.remove(wolf_here)
break
else:
wolves.remove(wolf_here)
dead_wolves += 1
wolves_killed_this_turn += 1
if grid[(cx, cy)] == '🍄':
mushrooms += 1
mushrooms_this_turn += 1
grid[(cx, cy)] = '..'
elif grid[(cx, cy)] == '🔭':
telescopes += 1
telescopes_this_turn += 1
grid[(cx, cy)] = '..'
if not dead:
if wolves_killed_this_turn > 0:
turn_events.append(f"🐺 Вы сбили волков: {wolves_killed_this_turn}!")
if telescopes_this_turn > 0:
turn_events.append(f"🔭 Вы нашли телескопы: {telescopes_this_turn}!")
if mushrooms_this_turn > 0 or wolves_killed_this_turn > 0 or telescopes_this_turn > 0:
combo_action_this_turn = True
if mushrooms_this_turn > 0:
turns_without_mushrooms = 0
else:
turns_without_mushrooms += 1
player_x += dx * current_speed
player_y += dy * current_speed
last_dx, last_dy = dx, dy
speed = current_speed
moves += 1
generate_viewport()
if not dead:
if combo_action_this_turn:
combo_streak += 1
if combo_streak >= 2:
total_combos += 1
exclamations = ["Супер!", "Огонь!", "Отлично!", "Безумие!", "Невероятно!", "Мощно!"]
combo_msg = f"🔥 {random.choice(exclamations)} Комбо x{combo_streak}! 🔥"
else:
combo_streak = 0
for w in wolves:
if w['just_spawned']:
w['just_spawned'] = False
continue
wx, wy = w['x'], w['y']
wdx = (player_x > wx) - (player_x < wx)
wdy = (player_y > wy) - (player_y < wy)
candidates = []
if wdx != 0 and wdy != 0:
candidates = [(wdx, wdy), (wdx, 0), (0, wdy)]
elif wdx != 0:
candidates = [(wdx, 0), (wdx, 1), (wdx, -1)]
elif wdy != 0:
candidates = [(0, wdy), (1, wdy), (-1, wdy)]
for cdx, cdy in candidates:
tx, ty = wx + cdx, wy + cdy
generate_cell(tx, ty)
if not is_safe_for_wolf(tx, ty):
continue
w['x'], w['y'] = tx, ty
break
if w['x'] == player_x and w['y'] == player_y:
dead = True
death_msg = "Голодный волк догнал вас и загрыз!"
wolves.remove(w)
break
if not dead and grid.get((w['x'], w['y'])) in ('🍄', '🔭'):
grid[(w['x'], w['y'])] = '..'
if not dead and turns_without_mushrooms >= 10:
render_rain()
time.sleep(3)
for pos in list(grid.keys()):
if grid[pos] == '🔥':
grid[pos] = '..'
burning_trees_cells.clear()
speed = 0
last_dx, last_dy = 0, 0
turns_without_mushrooms = 0
turn_events.append("🌧️ Прошёл сильный дождь! Вы потеряли скорость, а все костры потухли.")
if __name__ == "__main__":
main()