ver 1.0
This commit is contained in:
parent
3ebd817ef6
commit
906107995c
648
chess_open_world.py
Normal file
648
chess_open_world.py
Normal file
@ -0,0 +1,648 @@
|
||||
import pygame
|
||||
import sys
|
||||
import random
|
||||
|
||||
pygame.init()
|
||||
|
||||
# --- ПАРАМЕТРЫ ПОЛЯ ---
|
||||
CELL_SIZE = 32
|
||||
GRID_WIDTH = 30
|
||||
GRID_HEIGHT = 30
|
||||
WINDOW_WIDTH = CELL_SIZE * GRID_WIDTH
|
||||
WINDOW_HEIGHT = CELL_SIZE * GRID_HEIGHT
|
||||
|
||||
# --- ЦВЕТА ---
|
||||
COLOR_BG = (30, 30, 30)
|
||||
COLOR_GRID = (50, 50, 50)
|
||||
COLOR_FOG = (20, 20, 20)
|
||||
COLOR_SELECTED = (255, 0, 0)
|
||||
COLOR_MOVE = (0, 255, 0)
|
||||
|
||||
COLOR_WHITE_PIECE = (255, 255, 255) # Заливка белых фигур
|
||||
COLOR_BLACK_PIECE = (0, 0, 0) # Заливка чёрных фигур
|
||||
|
||||
# Новые цвета для бонусов
|
||||
COLOR_REGEN = (0, 255, 0) # Зелёный
|
||||
COLOR_HP_UPGRADE = (0, 128, 255) # Синий
|
||||
COLOR_DAMAGE = (255, 0, 0) # Красный
|
||||
COLOR_KING_HP_UPGRADE = (255, 215, 0) # Золотой
|
||||
COLOR_ADD_PIECE = (255, 255, 255) # Белый (с плюсом)
|
||||
COLOR_ADD_PIECE_PINK = (255, 192, 203) # Розовый
|
||||
|
||||
# Цвет текущего хода
|
||||
COLOR_TURN_TEXT = (255, 255, 255) # Белый
|
||||
|
||||
# Новый цвет для пометки клеток, которые скоро уйдут в туман войны
|
||||
COLOR_PRE_FOG = (169, 169, 169) # Светло-серый
|
||||
|
||||
screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
|
||||
pygame.display.set_caption("Шахматы с открытым миром 1.0")
|
||||
|
||||
# Шрифты
|
||||
font = pygame.font.SysFont(None, CELL_SIZE // 2)
|
||||
victory_font = pygame.font.SysFont(None, 60)
|
||||
turn_font = pygame.font.SysFont(None, 30)
|
||||
|
||||
# --- Глобальное множество открытых клеток (туман войны) ---
|
||||
global_revealed = set()
|
||||
|
||||
# --- Словарь символов ---
|
||||
piece_symbols = {
|
||||
'rook': 'Л',
|
||||
'knight': 'К',
|
||||
'bishop': 'С',
|
||||
'queen': 'Ф',
|
||||
'king': 'К', # Король (можно заменить на 'K' или другой символ)
|
||||
'pawn': 'П'
|
||||
}
|
||||
|
||||
# === МЕХАНИКА БОНУСОВ ===
|
||||
# Храним в глобальном словаре bonus_cells: {(x,y): {'type': ...}}
|
||||
bonus_cells = {}
|
||||
|
||||
# Вероятности появления различных типов бонусов
|
||||
bonus_probabilities = {
|
||||
'regen': 0.42, # 42%
|
||||
'hp_upgrade': 0.32, # 32%
|
||||
'damage': 0.2, # 20%
|
||||
'king_hp_upgrade': 0.05, # 5%
|
||||
'add_piece': 0.01 # 1%
|
||||
}
|
||||
|
||||
# Функция для выбора бонуса на основе вероятностей
|
||||
def choose_bonus_type():
|
||||
rand = random.random()
|
||||
cumulative = 0
|
||||
for bonus_type, prob in bonus_probabilities.items():
|
||||
cumulative += prob
|
||||
if rand < cumulative:
|
||||
return bonus_type
|
||||
return 'regen' # По умолчанию
|
||||
|
||||
def initialize_bonus_cells(pieces, num_each=10):
|
||||
"""
|
||||
Создаём случайно бонусных клеток.
|
||||
Включает три типа изначально: 'hp_upgrade', 'regen', 'king_hp_upgrade'.
|
||||
Бонусы не размещаются под стартовыми позициями фигур.
|
||||
"""
|
||||
global bonus_cells
|
||||
all_positions = [(x, y) for x in range(GRID_WIDTH) for y in range(GRID_HEIGHT)]
|
||||
random.shuffle(all_positions)
|
||||
i_pos = 0
|
||||
types = ['hp_upgrade', 'regen', 'king_hp_upgrade']
|
||||
for t in types:
|
||||
for _ in range(num_each):
|
||||
while i_pos < len(all_positions):
|
||||
(xx, yy) = all_positions[i_pos]
|
||||
i_pos += 1
|
||||
# Проверка, чтобы клетка не занята фигурой
|
||||
if not any(p.x == xx and p.y == yy for p in pieces):
|
||||
bonus_cells[(xx, yy)] = {'type': t}
|
||||
break
|
||||
|
||||
def apply_bonus(piece, bonus_type, pieces):
|
||||
"""Применяем эффект бонуса к фигуре piece в зависимости от типа."""
|
||||
if bonus_type == 'regen':
|
||||
# Регенерация (1..2) для НЕ короля
|
||||
if piece.name != 'king':
|
||||
amt = random.randint(1, 2)
|
||||
piece.hp = min(piece.hp + amt, piece.max_hp)
|
||||
|
||||
elif bonus_type == 'hp_upgrade':
|
||||
# Повышение max_hp только НЕ королю без восстановления HP
|
||||
if piece.name != 'king':
|
||||
piece.max_hp += 1
|
||||
# piece.hp остается неизменным
|
||||
|
||||
elif bonus_type == 'king_hp_upgrade':
|
||||
# Только для короля, бонус активируется другим игроком
|
||||
if piece.name != 'king':
|
||||
# Найти короля той же команды
|
||||
king = next((p for p in pieces if p.name == 'king' and p.color == piece.color), None)
|
||||
if king:
|
||||
if king.hp == king.max_hp:
|
||||
# Если король на полном здоровье,
|
||||
# то увеличиваем max_hp на 1
|
||||
king.max_hp += 1
|
||||
king.hp = king.max_hp
|
||||
else:
|
||||
# Если король не на полном, то
|
||||
# просто восстанавливаем HP до max
|
||||
king.hp = min(king.hp + 1, king.max_hp)
|
||||
|
||||
elif bonus_type == 'damage':
|
||||
# Нанесение урона (0..5)
|
||||
damage = random.randint(0, 5)
|
||||
piece.hp = max(piece.hp - damage, 0)
|
||||
if piece.hp == 0:
|
||||
# Удаляем фигуру, если HP равен 0
|
||||
pieces.remove(piece)
|
||||
if piece.name == 'king':
|
||||
global winner, game_over
|
||||
winner = 'black' if piece.color == 'white' else 'white'
|
||||
game_over = True
|
||||
|
||||
elif bonus_type == 'add_piece':
|
||||
# Добавление новой фигуры рядом, если возможно и не король
|
||||
if piece.name != 'king':
|
||||
# Определяем возможные соседние клетки
|
||||
directions = [(-1,0),(1,0),(0,-1),(0,1), (-1,-1),(1,-1),(1,1),(-1,1)]
|
||||
random.shuffle(directions)
|
||||
for dx, dy in directions:
|
||||
nx = piece.x + dx
|
||||
ny = piece.y + dy
|
||||
if 0 <= nx < GRID_WIDTH and 0 <= ny < GRID_HEIGHT:
|
||||
# Проверяем, что клетка пуста
|
||||
if not any(p.x == nx and p.y == ny for p in pieces) and (nx, ny) not in bonus_cells:
|
||||
# Создаём новую фигуру того же типа
|
||||
new_piece = Piece(piece.name, piece.color, nx, ny)
|
||||
pieces.append(new_piece)
|
||||
break
|
||||
# Если не удалось разместить, бонус не активируется
|
||||
|
||||
# === МЕХАНИКА БОЯ ===
|
||||
def resolve_combat(attacker, defender):
|
||||
"""
|
||||
Атакующая фигура (A) идёт на клетку защитника (B).
|
||||
HP(A)=a, HP(B)=b.
|
||||
- Если a < b: B теряет a (b := b-a), A погибает.
|
||||
- Если a > b: A теряет b (a := a-b), B погибает.
|
||||
- Если a == b: A побеждает, убивает B, а у A остаётся 1 HP.
|
||||
Возвращаем кортеж: (attacker_alive, defender_alive)
|
||||
при этом изменяем HP в самих объектах.
|
||||
"""
|
||||
a = attacker.hp
|
||||
b = defender.hp
|
||||
|
||||
if a < b:
|
||||
# Защитник теряет a HP
|
||||
defender.hp = b - a
|
||||
# Атакующая погибает
|
||||
attacker.hp = 0
|
||||
return (False, True)
|
||||
|
||||
elif a > b:
|
||||
# Атакующая теряет b HP
|
||||
attacker.hp = a - b
|
||||
# Защитник погибает
|
||||
defender.hp = 0
|
||||
return (True, False)
|
||||
|
||||
else:
|
||||
# a == b
|
||||
# Атакующая побеждает, остаётся с 1 HP
|
||||
attacker.hp = 1
|
||||
defender.hp = 0
|
||||
return (True, False)
|
||||
|
||||
# === КЛАСС ФИГУРЫ ===
|
||||
class Piece:
|
||||
def __init__(self, name, color, x, y):
|
||||
self.name = name
|
||||
self.color = color # 'white' или 'black'
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.selected = False
|
||||
|
||||
# Инициализация HP
|
||||
if self.name == 'king':
|
||||
self.max_hp = 5
|
||||
self.hp = 5
|
||||
elif self.name in ['rook', 'knight', 'bishop', 'queen']:
|
||||
self.max_hp = 3
|
||||
self.hp = 3
|
||||
elif self.name == 'pawn':
|
||||
self.max_hp = 1
|
||||
self.hp = 1
|
||||
|
||||
def get_possible_moves(self, pieces):
|
||||
moves = []
|
||||
if self.name == 'pawn':
|
||||
directions = [
|
||||
(-1,-1), (0,-1), (1,-1),
|
||||
(-1, 0), (1, 0),
|
||||
(-1, 1), (0, 1), (1, 1)
|
||||
]
|
||||
for dx, dy in directions:
|
||||
nx = self.x + dx
|
||||
ny = self.y + dy
|
||||
if 0 <= nx < GRID_WIDTH and 0 <= ny < GRID_HEIGHT:
|
||||
blocking = next((p for p in pieces if p.x == nx and p.y == ny), None)
|
||||
# Можем ходить, если клетка пуста или там враг
|
||||
if not blocking or blocking.color != self.color:
|
||||
moves.append((nx, ny))
|
||||
|
||||
elif self.name in ['rook', 'bishop', 'queen']:
|
||||
# Ограничиваем движение до 5 клеток
|
||||
if self.name == 'rook':
|
||||
directions = [(-1,0),(1,0),(0,-1),(0,1)]
|
||||
elif self.name == 'bishop':
|
||||
directions = [(-1,-1),(1,-1),(1,1),(-1,1)]
|
||||
elif self.name == 'queen':
|
||||
directions = [
|
||||
(-1,0),(1,0),(0,-1),(0,1),
|
||||
(-1,-1),(1,-1),(1,1),(-1,1)
|
||||
]
|
||||
for dx, dy in directions:
|
||||
for step in range(1, 6): # До 5 клеток
|
||||
nx = self.x + dx * step
|
||||
ny = self.y + dy * step
|
||||
if 0 <= nx < GRID_WIDTH and 0 <= ny < GRID_HEIGHT:
|
||||
blocking = next((p for p in pieces if p.x == nx and p.y == ny), None)
|
||||
if blocking:
|
||||
if blocking.color != self.color:
|
||||
moves.append((nx, ny))
|
||||
break
|
||||
moves.append((nx, ny))
|
||||
else:
|
||||
break
|
||||
|
||||
elif self.name == 'knight':
|
||||
deltas = [(-2,-1),(-1,-2),(1,-2),(2,-1),
|
||||
(2,1),(1,2),(-1,2),(-2,1)]
|
||||
for dx, dy in deltas:
|
||||
nx, ny = self.x+dx, self.y+dy
|
||||
if 0 <= nx < GRID_WIDTH and 0 <= ny < GRID_HEIGHT:
|
||||
blocking = next((p for p in pieces if p.x == nx and p.y == ny), None)
|
||||
if not blocking or blocking.color != self.color:
|
||||
moves.append((nx, ny))
|
||||
|
||||
elif self.name == 'king':
|
||||
directions = [
|
||||
(-1,0),(1,0),(0,-1),(0,1),
|
||||
(-1,-1),(1,-1),(1,1),(-1,1)
|
||||
]
|
||||
for dx, dy in directions:
|
||||
nx, ny = self.x+dx, self.y+dy
|
||||
if 0 <= nx < GRID_WIDTH and 0 <= ny < GRID_HEIGHT:
|
||||
blocking = next((p for p in pieces if p.x == nx and p.y == ny), None)
|
||||
if not blocking or blocking.color != self.color:
|
||||
moves.append((nx, ny))
|
||||
|
||||
return moves
|
||||
|
||||
# --- Инициализация фигур ---
|
||||
def initialize_pieces():
|
||||
"""Чёрные: y=2(back), y=3(pawns). Белые: y=27(back), y=26(pawns)."""
|
||||
pieces = []
|
||||
cx = GRID_WIDTH//2
|
||||
|
||||
# ЧЁРНЫЕ
|
||||
black_back = ['rook','knight','bishop','king','queen','bishop','knight','rook']
|
||||
for i,pname in enumerate(black_back):
|
||||
x = cx - 3 + i
|
||||
y = 2
|
||||
pieces.append(Piece(pname,'black',x,y))
|
||||
for i in range(8):
|
||||
x = cx-3 + i
|
||||
y = 3
|
||||
pieces.append(Piece('pawn','black',x,y))
|
||||
|
||||
# БЕЛЫЕ
|
||||
white_back = ['rook','knight','bishop','king','queen','bishop','knight','rook']
|
||||
for i,pname in enumerate(white_back):
|
||||
x = cx - 3 + i
|
||||
y = 27
|
||||
pieces.append(Piece(pname,'white',x,y))
|
||||
for i in range(8):
|
||||
x = cx-3 + i
|
||||
y = 26
|
||||
pieces.append(Piece('pawn','white',x,y))
|
||||
|
||||
return pieces
|
||||
|
||||
# Инициализация фигур до инициализации бонусов
|
||||
pieces = initialize_pieces()
|
||||
initialize_bonus_cells(pieces, num_each=10)
|
||||
|
||||
selected_piece = None
|
||||
possible_moves = []
|
||||
game_over = False
|
||||
winner = None
|
||||
|
||||
# --- Туман войны ---
|
||||
cell_counters = {} # {(x,y): turns_since_last_revealed}
|
||||
BONUS_GENERATION_CHANCE = 0.1 # 10% шанс появления бонуса при повторном открытии
|
||||
|
||||
# --- Система ходов ---
|
||||
current_turn = 'white' # Начинаем с белых
|
||||
|
||||
def update_fog():
|
||||
"""
|
||||
Обновляет туман войны:
|
||||
- Открытые клетки остаются открытыми.
|
||||
- Закрытые клетки, которые не находятся рядом с любыми фигурами на расстоянии 2 клеток,
|
||||
становятся закрытыми через 5 ходов.
|
||||
- При повторном открытии клетки шанс на появление нового бонуса.
|
||||
"""
|
||||
global global_revealed, bonus_cells
|
||||
|
||||
# Сохраняем предыдущее состояние открытых клеток
|
||||
previous_revealed = global_revealed.copy()
|
||||
|
||||
# Определяем все открытые клетки на основе позиций фигур
|
||||
new_revealed = set()
|
||||
for p in pieces:
|
||||
for dx in range(-2, 3):
|
||||
for dy in range(-2, 3):
|
||||
nx = p.x + dx
|
||||
ny = p.y + dy
|
||||
if 0 <= nx < GRID_WIDTH and 0 <= ny < GRID_HEIGHT:
|
||||
new_revealed.add((nx, ny))
|
||||
|
||||
# Определяем только новые открытые клетки
|
||||
newly_revealed = new_revealed - previous_revealed
|
||||
|
||||
# Обрабатываем все клетки
|
||||
for y in range(GRID_HEIGHT):
|
||||
for x in range(GRID_WIDTH):
|
||||
pos = (x, y)
|
||||
if pos in new_revealed:
|
||||
# Если клетка видна, сбрасываем счетчик
|
||||
cell_counters[pos] = 0
|
||||
global_revealed.add(pos)
|
||||
else:
|
||||
# Если клетка не видна, увеличиваем счетчик
|
||||
if pos in cell_counters:
|
||||
cell_counters[pos] += 1
|
||||
else:
|
||||
cell_counters[pos] = 1
|
||||
|
||||
# Если счетчик достигает 5, закрываем клетку
|
||||
if cell_counters[pos] >= 5:
|
||||
if pos in global_revealed:
|
||||
global_revealed.remove(pos)
|
||||
# Удаляем бонус, если клетка закрывается и бонус не является 'damage'
|
||||
if pos in bonus_cells and bonus_cells[pos]['type'] != 'damage':
|
||||
del bonus_cells[pos]
|
||||
|
||||
# Генерируем бонусы только на новых открытых клетках
|
||||
for pos in newly_revealed:
|
||||
if pos not in bonus_cells and random.random() < BONUS_GENERATION_CHANCE:
|
||||
bonus_type = choose_bonus_type()
|
||||
# Проверяем, чтобы бонус не был под фигурой
|
||||
if not any(p.x == pos[0] and p.y == pos[1] for p in pieces):
|
||||
bonus_cells[pos] = {'type': bonus_type}
|
||||
|
||||
def draw_grid():
|
||||
for x in range(0, WINDOW_WIDTH, CELL_SIZE):
|
||||
pygame.draw.line(screen, COLOR_GRID, (x, 0), (x, WINDOW_HEIGHT))
|
||||
for y in range(0, WINDOW_HEIGHT, CELL_SIZE):
|
||||
pygame.draw.line(screen, COLOR_GRID, (0, y), (WINDOW_WIDTH, y))
|
||||
|
||||
def draw_fog():
|
||||
for y in range(GRID_HEIGHT):
|
||||
for x in range(GRID_WIDTH):
|
||||
pos = (x, y)
|
||||
if pos not in global_revealed:
|
||||
rect = pygame.Rect(x*CELL_SIZE, y*CELL_SIZE, CELL_SIZE, CELL_SIZE)
|
||||
pygame.draw.rect(screen, COLOR_FOG, rect)
|
||||
else:
|
||||
# Проверяем, будет ли клетка закрыта в следующем ходу
|
||||
if cell_counters.get(pos, 0) == 4:
|
||||
# Помечаем клетку светло-серым
|
||||
rect = pygame.Rect(x*CELL_SIZE, y*CELL_SIZE, CELL_SIZE, CELL_SIZE)
|
||||
pygame.draw.rect(screen, COLOR_PRE_FOG, rect)
|
||||
|
||||
def draw_bonus_cells():
|
||||
"""
|
||||
Отрисовка бонусов (если клетка открыта или бонус типа 'damage').
|
||||
Цвета:
|
||||
- 'regen': (0,255,0) зелёный
|
||||
- 'hp_upgrade': (0,128,255) синий
|
||||
- 'damage': (255,0,0) красный
|
||||
- 'king_hp_upgrade': (255,215,0) золотой
|
||||
- 'add_piece': (255,255,255) белый с плюсом или розовый
|
||||
"""
|
||||
for (bx, by), info in bonus_cells.items():
|
||||
# Для 'damage' бонусов отображаем всегда, иначе только если клетка видна
|
||||
if info['type'] != 'damage' and (bx, by) not in global_revealed:
|
||||
continue
|
||||
cx = bx*CELL_SIZE + CELL_SIZE//2
|
||||
cy = by*CELL_SIZE + CELL_SIZE//2
|
||||
bonus_type = info['type']
|
||||
if bonus_type == 'regen':
|
||||
color = COLOR_REGEN
|
||||
pygame.draw.circle(screen, color, (cx, cy), CELL_SIZE//4)
|
||||
elif bonus_type == 'hp_upgrade':
|
||||
color = COLOR_HP_UPGRADE
|
||||
pygame.draw.circle(screen, color, (cx, cy), CELL_SIZE//4)
|
||||
elif bonus_type == 'damage':
|
||||
color = COLOR_DAMAGE
|
||||
pygame.draw.circle(screen, color, (cx, cy), CELL_SIZE//4)
|
||||
elif bonus_type == 'king_hp_upgrade':
|
||||
color = COLOR_KING_HP_UPGRADE
|
||||
pygame.draw.circle(screen, color, (cx, cy), CELL_SIZE//4)
|
||||
elif bonus_type == 'add_piece':
|
||||
# Проверяем, возможно ли добавить фигуру рядом
|
||||
possible = False
|
||||
for dx, dy in [(-1,0),(1,0),(0,-1),(0,1), (-1,-1),(1,-1),(1,1),(-1,1)]:
|
||||
nx = bx + dx
|
||||
ny = by + dy
|
||||
if 0 <= nx < GRID_WIDTH and 0 <= ny < GRID_HEIGHT:
|
||||
if not any(p.x == nx and p.y == ny for p in pieces):
|
||||
possible = True
|
||||
break
|
||||
color = COLOR_ADD_PIECE if possible else COLOR_ADD_PIECE_PINK
|
||||
pygame.draw.circle(screen, color, (cx, cy), CELL_SIZE//4)
|
||||
# Рисуем плюс
|
||||
pygame.draw.line(screen, (0,0,0), (cx - CELL_SIZE//8, cy), (cx + CELL_SIZE//8, cy), 2)
|
||||
pygame.draw.line(screen, (0,0,0), (cx, cy - CELL_SIZE//8), (cx, cy + CELL_SIZE//8), 2)
|
||||
|
||||
def draw_pieces(pieces):
|
||||
"""Рисуем фигуры, их HP и подсвечиваем ходы."""
|
||||
for p in pieces:
|
||||
rect = pygame.Rect(p.x*CELL_SIZE, p.y*CELL_SIZE, CELL_SIZE, CELL_SIZE)
|
||||
|
||||
if p.color == 'white':
|
||||
pygame.draw.rect(screen, COLOR_WHITE_PIECE, rect)
|
||||
symbol = piece_symbols.get(p.name,'?')
|
||||
text = font.render(symbol, True, (255,0,0))
|
||||
text_rect = text.get_rect(center=rect.center)
|
||||
screen.blit(text, text_rect)
|
||||
# HP чёрным
|
||||
hp_str = f"{p.hp}/{p.max_hp}"
|
||||
hp_text = font.render(hp_str, True, (0,0,0))
|
||||
screen.blit(hp_text, (rect.x+2, rect.y+2))
|
||||
else:
|
||||
pygame.draw.rect(screen, COLOR_BLACK_PIECE, rect)
|
||||
symbol = piece_symbols.get(p.name,'?')
|
||||
text = font.render(symbol, True, (255,0,0))
|
||||
text_rect = text.get_rect(center=rect.center)
|
||||
screen.blit(text, text_rect)
|
||||
# HP белым
|
||||
hp_str = f"{p.hp}/{p.max_hp}"
|
||||
hp_text = font.render(hp_str, True, (255,255,255))
|
||||
screen.blit(hp_text, (rect.x+2, rect.y+2))
|
||||
|
||||
if p.selected:
|
||||
pygame.draw.rect(screen, COLOR_SELECTED, rect, 2)
|
||||
|
||||
for (mx, my) in possible_moves:
|
||||
r = pygame.Rect(mx*CELL_SIZE, my*CELL_SIZE, CELL_SIZE, CELL_SIZE)
|
||||
pygame.draw.rect(screen, COLOR_MOVE, r, 2)
|
||||
|
||||
def display_victory(winner):
|
||||
text = victory_font.render(f"{winner.capitalize()} победил!", True, (255, 255, 255))
|
||||
text_rect = text.get_rect(center=(WINDOW_WIDTH//2, WINDOW_HEIGHT//2))
|
||||
screen.blit(text, text_rect)
|
||||
|
||||
def display_turn(current_turn):
|
||||
text = turn_font.render(f"Текущий ход: {current_turn.capitalize()}", True, COLOR_TURN_TEXT)
|
||||
screen.blit(text, (10, WINDOW_HEIGHT - 30))
|
||||
|
||||
running = True
|
||||
clock = pygame.time.Clock()
|
||||
|
||||
# Инициализируем туман войны в начале игры
|
||||
update_fog()
|
||||
|
||||
while running:
|
||||
clock.tick(30)
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN and not game_over:
|
||||
mx, my = pygame.mouse.get_pos()
|
||||
gx = mx // CELL_SIZE
|
||||
gy = my // CELL_SIZE
|
||||
|
||||
clicked_piece = next((p for p in pieces if p.x == gx and p.y == gy), None)
|
||||
|
||||
if selected_piece:
|
||||
if (gx, gy) in possible_moves:
|
||||
# Проверяем бонус
|
||||
if (gx, gy) in bonus_cells:
|
||||
bonus_type = bonus_cells[(gx, gy)]['type']
|
||||
apply_bonus(selected_piece, bonus_type, pieces)
|
||||
del bonus_cells[(gx, gy)]
|
||||
|
||||
# Проверяем, есть ли там вражеская фигура
|
||||
defender = next((p for p in pieces if p.x == gx and p.y == gy), None)
|
||||
if defender:
|
||||
# Проводим бой
|
||||
attacker = selected_piece
|
||||
attacker_alive, defender_alive = resolve_combat(attacker, defender)
|
||||
if not defender_alive:
|
||||
# Защитник погиб
|
||||
if defender.name == 'king':
|
||||
winner = attacker.color
|
||||
game_over = True
|
||||
pieces.remove(defender)
|
||||
if not attacker_alive:
|
||||
# Атакующая погибла
|
||||
pieces.remove(attacker)
|
||||
# Снимаем выделение
|
||||
selected_piece = None
|
||||
possible_moves.clear()
|
||||
# После изменения позиций фигур обновляем туман войны
|
||||
update_fog()
|
||||
# Смена хода
|
||||
current_turn = 'black' if current_turn == 'white' else 'white'
|
||||
continue
|
||||
else:
|
||||
# Атакующая жива, перемещаем её
|
||||
# Проверка прохождения через клетки (для длинных ходов)
|
||||
path = []
|
||||
if attacker.name in ['rook', 'bishop', 'queen']:
|
||||
dx = gx - attacker.x
|
||||
dy = gy - attacker.y
|
||||
if dx != 0:
|
||||
dx = dx // abs(dx)
|
||||
if dy != 0:
|
||||
dy = dy // abs(dy)
|
||||
for step in range(1, max(abs(gx - attacker.x), abs(gy - attacker.y))):
|
||||
path_x = attacker.x + dx * step
|
||||
path_y = attacker.y + dy * step
|
||||
path.append((path_x, path_y))
|
||||
# Применяем урон при прохождении через клетки и удаляем 'damage' клетки
|
||||
survived = True
|
||||
for pos in path:
|
||||
if pos in bonus_cells and bonus_cells[pos]['type'] == 'damage':
|
||||
damage = random.randint(0,5)
|
||||
attacker.hp = max(attacker.hp - damage, 0)
|
||||
# Удаляем 'damage' клетку как использованную
|
||||
del bonus_cells[pos]
|
||||
if attacker.hp == 0:
|
||||
pieces.remove(attacker)
|
||||
selected_piece = None
|
||||
possible_moves.clear()
|
||||
survived = False
|
||||
break
|
||||
if survived:
|
||||
attacker.x = gx
|
||||
attacker.y = gy
|
||||
attacker.selected = False
|
||||
selected_piece = None
|
||||
possible_moves.clear()
|
||||
# Смена хода
|
||||
current_turn = 'black' if current_turn == 'white' else 'white'
|
||||
|
||||
else:
|
||||
# Пустая клетка — просто ходим
|
||||
# Проверка прохождения через клетки (для длинных ходов)
|
||||
path = []
|
||||
if selected_piece.name in ['rook', 'bishop', 'queen']:
|
||||
dx = gx - selected_piece.x
|
||||
dy = gy - selected_piece.y
|
||||
if dx != 0:
|
||||
dx = dx // abs(dx)
|
||||
if dy != 0:
|
||||
dy = dy // abs(dy)
|
||||
for step in range(1, max(abs(gx - selected_piece.x), abs(gy - selected_piece.y))):
|
||||
path_x = selected_piece.x + dx * step
|
||||
path_y = selected_piece.y + dy * step
|
||||
path.append((path_x, path_y))
|
||||
# Применяем урон при прохождении через клетки и удаляем 'damage' клетки
|
||||
survived = True
|
||||
for pos in path:
|
||||
if pos in bonus_cells and bonus_cells[pos]['type'] == 'damage':
|
||||
damage = random.randint(0,5)
|
||||
selected_piece.hp = max(selected_piece.hp - damage, 0)
|
||||
# Удаляем 'damage' клетку как использованную
|
||||
del bonus_cells[pos]
|
||||
if selected_piece.hp == 0:
|
||||
pieces.remove(selected_piece)
|
||||
selected_piece = None
|
||||
possible_moves.clear()
|
||||
survived = False
|
||||
break
|
||||
if survived:
|
||||
selected_piece.x = gx
|
||||
selected_piece.y = gy
|
||||
selected_piece.selected = False
|
||||
selected_piece = None
|
||||
possible_moves.clear()
|
||||
# Смена хода
|
||||
current_turn = 'black' if current_turn == 'white' else 'white'
|
||||
|
||||
# После успешного хода обновляем туман войны
|
||||
update_fog()
|
||||
else:
|
||||
# Клик вне возможных ходов
|
||||
selected_piece.selected = False
|
||||
selected_piece = None
|
||||
possible_moves.clear()
|
||||
|
||||
else:
|
||||
# Выбираем фигуру только если клетка видима и соответствует текущему ходу
|
||||
if clicked_piece and (gx, gy) in global_revealed and clicked_piece.color == current_turn:
|
||||
selected_piece = clicked_piece
|
||||
selected_piece.selected = True
|
||||
possible_moves = selected_piece.get_possible_moves(pieces)
|
||||
|
||||
# Отрисовка
|
||||
screen.fill(COLOR_BG)
|
||||
draw_grid()
|
||||
draw_fog()
|
||||
draw_bonus_cells()
|
||||
draw_pieces(pieces)
|
||||
if game_over and winner:
|
||||
display_victory(winner)
|
||||
else:
|
||||
display_turn(current_turn)
|
||||
pygame.display.flip()
|
||||
|
||||
pygame.quit()
|
||||
sys.exit()
|
Loading…
x
Reference in New Issue
Block a user