ChessBuilder/Systems/Game/WinConditionManager.gd
2025-03-09 17:13:04 -05:00

283 lines
12 KiB
GDScript

extends Node
class_name WinConditionManager
# Signals
signal win_condition_met(condition_data)
signal loss_condition_met(condition_data)
signal condition_progress_updated(progress_data)
# References
var chess_game: ChessGame
var tile_manager: TileManager
# Condition configuration
var win_condition: Utils.WinConditionType = Utils.WinConditionType.CAPTURE_UNIT
var loss_condition: Utils.LossConditionType = Utils.LossConditionType.UNIT_LOST
var win_condition_data: Dictionary = {}
var loss_condition_data: Dictionary = {}
# Progress tracking
var captured_pieces = []
var turn_count = 0
var target_tiles = []
var condition_progress = {}
func _init(game: ChessGame):
chess_game = game
if chess_game:
tile_manager = chess_game.tileManager
# Connect to relevant signals
chess_game.connect("turn_changed", Callable(self, "_on_turn_changed"))
chess_game.connect("game_initialized", Callable(self, "_on_game_initialized"))
func _on_game_initialized():
# reset_conditions()
print("_on_game_initialized")
func reset_conditions():
print("reset_conditions")
captured_pieces.clear()
turn_count = 0
target_tiles.clear()
condition_progress.clear()
# Setup initial progress tracking
match win_condition:
Utils.WinConditionType.BOARD_CLEARED:
condition_progress["total_enemy_pieces"] = count_enemy_pieces()
condition_progress["remaining_enemy_pieces"] = condition_progress["total_enemy_pieces"]
Utils.WinConditionType.TILE_REACHED:
if "target_tiles" in win_condition_data:
target_tiles = win_condition_data["target_tiles"]
highlight_target_tiles()
condition_progress["tiles_reached"] = []
Utils.WinConditionType.TURN_NUMBER:
if "target_turn" in win_condition_data:
condition_progress["target_turn"] = win_condition_data["target_turn"]
condition_progress["current_turn"] = 0
func highlight_target_tiles():
# Highlight target tiles on the board with a special visual style
for tile_loc in target_tiles:
if tile_manager:
# Create a goal tile if needed
var container = chess_game.get_node("Flow/" + tile_loc) as PieceContainer
if container:
# Create a visual indicator - use a styled container
var style = StyleBoxFlat.new()
style.bg_color = Color(0.2, 0.8, 0.2, 0.4) # Green translucent
style.border_width_all = 2
style.border_color = Color(0.3, 1.0, 0.3, 0.8)
# Apply the style while respecting chess pattern
var coord = tile_loc.split("-")
var isWhiteSquare = (int(coord[0]) + int(coord[1])) % 2 == 0
var baseStyle = chess_game.lightStyle if isWhiteSquare else chess_game.darkStyle
var combinedStyle = StyleBoxFlat.new()
combinedStyle.bg_color = baseStyle.bg_color + style.bg_color
combinedStyle.border_width_all = style.border_width_all
combinedStyle.border_color = style.border_color
container.add_theme_stylebox_override("normal", combinedStyle)
func set_win_condition(type: Utils.WinConditionType, data: Dictionary = {}):
win_condition = type
win_condition_data = data
func set_loss_condition(type: Utils.LossConditionType, data: Dictionary = {}):
loss_condition = type
loss_condition_data = data
# reset_conditions()
func _on_turn_changed():
turn_count += 1
# Update progress for turn-based conditions
if win_condition == Utils.WinConditionType.TURN_NUMBER:
condition_progress["current_turn"] = turn_count
emit_signal("condition_progress_updated", condition_progress)
if "target_turn" in win_condition_data and turn_count >= win_condition_data["target_turn"]:
emit_signal("win_condition_met", {
"type": Utils.WinConditionType.TURN_NUMBER,
"message": "Turn limit reached!"
})
if loss_condition == Utils.LossConditionType.TURN_NUMBER:
if "turn_limit" in loss_condition_data and turn_count >= loss_condition_data["turn_limit"]:
emit_signal("loss_condition_met", {
"type": Utils.LossConditionType.TURN_NUMBER,
"message": "Turn limit exceeded!"
})
check_conditions()
func on_piece_captured(piece):
# print("on_piece_captured ISEnemy ", piece)
var is_enemy_piece = piece.Item_Color == (1 if chess_game.Turn == 1 else 0)
print("on_piece_captured ISEnemy ", is_enemy_piece)
if is_enemy_piece:
captured_pieces.append(piece)
if win_condition == Utils.WinConditionType.BOARD_CLEARED:
condition_progress["remaining_enemy_pieces"] -= 1
emit_signal("condition_progress_updated", condition_progress)
if condition_progress["remaining_enemy_pieces"] <= 0:
emit_signal("win_condition_met", {
"type": Utils.WinConditionType.BOARD_CLEARED,
"message": "Board cleared of enemy pieces!"
})
if win_condition == Utils.WinConditionType.CAPTURE_UNIT:
var target_unit = win_condition_data.get("unit", "King")
if piece.name == target_unit:
emit_signal("win_condition_met", {
"type": Utils.WinConditionType.CAPTURE_UNIT,
"message": "Enemy " + target_unit + " captured!"
})
check_conditions()
func on_piece_lost(piece):
var is_player_piece = piece.Item_Color == (0 if chess_game.Turn == 1 else 1)
print("on_piece_lost isPlayer ", is_player_piece)
if is_player_piece:
if loss_condition == Utils.LossConditionType.UNIT_LOST:
var target_unit = loss_condition_data.get("unit", "King")
if piece.name == target_unit:
emit_signal("loss_condition_met", {
"type": Utils.LossConditionType.UNIT_LOST,
"message": "Your " + target_unit + " was captured!"
})
check_conditions()
func on_piece_moved(piece, from_location, to_location):
if win_condition == Utils.WinConditionType.TILE_REACHED:
var is_player_piece = piece.Item_Color == (0 if chess_game.Turn == 0 else 1)
if is_player_piece and target_tiles.has(to_location):
if "unit" in win_condition_data and win_condition_data["unit"] != "":
if piece.name == win_condition_data["unit"]:
if not condition_progress.has("tiles_reached"):
condition_progress["tiles_reached"] = []
# Avoid duplicates
if not condition_progress["tiles_reached"].has(to_location):
condition_progress["tiles_reached"].append(to_location)
emit_signal("condition_progress_updated", condition_progress)
if condition_progress["tiles_reached"].size() >= target_tiles.size():
emit_signal("win_condition_met", {
"type": Utils.WinConditionType.TILE_REACHED,
"message": "Target tile reached by " + piece.name + "!"
})
else:
# Any player unit can reach the tile
if not condition_progress.has("tiles_reached"):
condition_progress["tiles_reached"] = []
# Avoid duplicates
if not condition_progress["tiles_reached"].has(to_location):
condition_progress["tiles_reached"].append(to_location)
emit_signal("condition_progress_updated", condition_progress)
if condition_progress["tiles_reached"].size() >= target_tiles.size():
emit_signal("win_condition_met", {
"type": Utils.WinConditionType.TILE_REACHED,
"message": "Target tile reached!"
})
check_conditions()
func check_conditions():
# Check board cleared condition
if win_condition == Utils.WinConditionType.BOARD_CLEARED:
var remaining = count_enemy_pieces()
if remaining <= 0:
emit_signal("win_condition_met", {
"type": Utils.WinConditionType.BOARD_CLEARED,
"message": "Board cleared of enemy pieces!"
})
emit_signal("condition_progress_updated", condition_progress)
func count_enemy_pieces() -> int:
var count = 0
var enemy_color = 1 if chess_game.Turn == 0 else 0
for y in range(chess_game.boardYSize):
for x in range(chess_game.boardXSize):
var piece = (chess_game.get_node(str(x) + "-" + str(y)) as PieceContainer).get_piece()
if piece != null and piece.Item_Color == enemy_color:
count += 1
return count
# Helper methods for game integration
func load_condition_from_metadata(metadata: Dictionary):
reset_conditions();
# print("load_condition_from_metadata ", metadata)
if metadata.has("win_condition"):
match metadata["win_condition"]:
Utils.WinConditionType.CAPTURE_UNIT:
set_win_condition(Utils.WinConditionType.CAPTURE_UNIT, {"unit": "King"})
Utils.WinConditionType.TILE_REACHED:
# Get target tiles from metadata if available
target_tiles = metadata.get("win_target", [])
# print("load_condition_from_metadata ", " target_tiles ", target_tiles)
set_win_condition(Utils.WinConditionType.TILE_REACHED, {"target_tiles": target_tiles, "unit": metadata.get("win_target_unit", "")})
Utils.WinConditionType.BOARD_CLEARED:
set_win_condition(Utils.WinConditionType.BOARD_CLEARED)
Utils.WinConditionType.TURN_NUMBER:
set_win_condition(Utils.WinConditionType.TURN_NUMBER, {"target_turn": metadata.get("win_target_turn", 20)})
if metadata.has("loss_condition"):
match metadata["loss_condition"]:
Utils.LossConditionType.UNIT_LOST:
set_loss_condition(Utils.LossConditionType.UNIT_LOST, {"unit": "King"})
Utils.LossConditionType.TURN_NUMBER:
set_loss_condition(Utils.LossConditionType.TURN_NUMBER, {"turn_limit": metadata.get("loss_turn_limit", 50)})
# Debug methods
func print_debug_info():
print("=== WIN CONDITION SYSTEM DEBUG INFO ===")
print("Current win condition: ", _win_condition_type_to_string(win_condition))
print("Current loss condition: ", _loss_condition_type_to_string(loss_condition))
print("Win condition data: ", win_condition_data)
print("Loss condition data: ", loss_condition_data)
print("Turn count: ", turn_count)
print("Target tiles: ", target_tiles)
print("Captured pieces: ", captured_pieces.size())
print("Condition progress: ", condition_progress)
print("Enemy pieces remaining: ", count_enemy_pieces())
print("=====================================")
func _win_condition_type_to_string(type: Utils.WinConditionType) -> String:
match type:
Utils.WinConditionType.CAPTURE_UNIT:
return "CAPTURE_UNIT"
Utils.WinConditionType.BOARD_CLEARED:
return "BOARD_CLEARED"
Utils.WinConditionType.TILE_REACHED:
return "TILE_REACHED"
Utils.WinConditionType.TURN_NUMBER:
return "TURN_NUMBER"
_:
return "UNKNOWN"
func _loss_condition_type_to_string(type: Utils.LossConditionType) -> String:
match type:
Utils.LossConditionType.UNIT_LOST:
return "UNIT_LOST"
Utils.LossConditionType.TURN_NUMBER:
return "TURN_NUMBER"
_:
return "UNKNOWN"