fixed crash on board size change and turn interaction with explosive cards
This commit is contained in:
parent
8e23e34a66
commit
c09ddcb1a2
13 changed files with 498 additions and 42 deletions
|
|
@ -17,6 +17,7 @@ func reset():
|
||||||
valid = false
|
valid = false
|
||||||
|
|
||||||
func apply_effect(target_piece = null, board_flow = null, game_state = null):
|
func apply_effect(target_piece = null, board_flow = null, game_state = null):
|
||||||
|
print("EXPLOSIVE apply_effect", )
|
||||||
attached_piece = target_piece
|
attached_piece = target_piece
|
||||||
stored_board_flow = board_flow
|
stored_board_flow = board_flow
|
||||||
stored_game_state = game_state
|
stored_game_state = game_state
|
||||||
|
|
@ -26,6 +27,7 @@ func apply_effect(target_piece = null, board_flow = null, game_state = null):
|
||||||
setup_persistent_effect(game_state)
|
setup_persistent_effect(game_state)
|
||||||
# dont apply on card attachment
|
# dont apply on card attachment
|
||||||
if !valid:
|
if !valid:
|
||||||
|
print("EXPLOSIVE apply_effect INVALID", )
|
||||||
return true
|
return true
|
||||||
var piece_pos = target_piece.get_parent().name.split("-")
|
var piece_pos = target_piece.get_parent().name.split("-")
|
||||||
var piece_x = int(piece_pos[0])
|
var piece_x = int(piece_pos[0])
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,14 @@ func _init():
|
||||||
func initializeStartingDeck():
|
func initializeStartingDeck():
|
||||||
deck.clear();
|
deck.clear();
|
||||||
# for i in range(2):
|
# for i in range(2):
|
||||||
# deck.append(DoubleTimeCard.new())
|
# deck.append(DoubleTimeCard.new())
|
||||||
deck.append(HopscotchCard.new())
|
# deck.append(HopscotchCard.new())
|
||||||
deck.append(FieryCapeCard.new())
|
# deck.append(FieryCapeCard.new())
|
||||||
deck.append(FieryTrailCard.new())
|
# deck.append(FieryTrailCard.new())
|
||||||
deck.append(ExplosiveBootsCard.new())
|
deck.append(ExplosiveBootsCard.new())
|
||||||
deck.append(DoubleTimeCard.new())
|
deck.append(DoubleTimeCard.new())
|
||||||
deck.append(DrunkDrivingCard.new())
|
# deck.append(DrunkDrivingCard.new())
|
||||||
deck.append(SupernovaCard.new())
|
# deck.append(SupernovaCard.new())
|
||||||
|
|
||||||
func initializeStartingBank():
|
func initializeStartingBank():
|
||||||
# sample
|
# sample
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
class_name ChessGame extends Control
|
class_name ChessGame extends Control
|
||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
const PieceContainer = preload("res://Systems/PieceContainer.gd")
|
|
||||||
const WHITE = "white"
|
const WHITE = "white"
|
||||||
const BLACK = "black"
|
const BLACK = "black"
|
||||||
const StockfishController = preload("res://Systems/FairyStockfish/StockfishClient.gd")
|
const StockfishController = preload("res://Systems/FairyStockfish/StockfishClient.gd")
|
||||||
|
|
@ -60,6 +59,10 @@ var currentNode = null;
|
||||||
@onready var menuContainer = get_node_or_null("/root/Board/MenuContainer")
|
@onready var menuContainer = get_node_or_null("/root/Board/MenuContainer")
|
||||||
@onready var mapContainer = get_node_or_null("/root/Board/MapScreen")
|
@onready var mapContainer = get_node_or_null("/root/Board/MapScreen")
|
||||||
|
|
||||||
|
var winConditionManager: WinConditionManager
|
||||||
|
var currentWinCondition = Utils.WinConditionType.CAPTURE_UNIT
|
||||||
|
var currentLossCondition = Utils.LossConditionType.UNIT_LOST
|
||||||
|
|
||||||
|
|
||||||
# Export parameters
|
# Export parameters
|
||||||
@export var boardXSize = 12
|
@export var boardXSize = 12
|
||||||
|
|
@ -109,16 +112,20 @@ func _on_new_game_requested(options = {}):
|
||||||
cpuElo = options.metadata.elo
|
cpuElo = options.metadata.elo
|
||||||
if cameraController:
|
if cameraController:
|
||||||
cameraController.reset_view()
|
cameraController.reset_view()
|
||||||
|
if options and "metadata" in options:
|
||||||
|
if winConditionManager:
|
||||||
|
winConditionManager.load_condition_from_metadata(options.metadata)
|
||||||
|
|
||||||
currentNode = options
|
currentNode = options
|
||||||
print("ChessGame FEN ", currentFen)
|
print("ChessGame FEN ", currentFen)
|
||||||
print("ChessGame DIMENSIONS ", get_board_dimensions(currentFen))
|
print("ChessGame DIMENSIONS ", get_board_dimensions(currentFen))
|
||||||
if is_initialized:
|
if is_initialized:
|
||||||
resetBoard()
|
resetBoard()
|
||||||
initializeDeckSystem()
|
initializeDeckSystem()
|
||||||
|
initializeBoard()
|
||||||
if cardDisplay:
|
if cardDisplay:
|
||||||
cardDisplay.visible = true
|
cardDisplay.visible = true
|
||||||
if stateMachine:
|
if stateMachine:
|
||||||
stateMachine.start()
|
|
||||||
stateMachine.transitionToNextState(Constants.WHITE_TURN)
|
stateMachine.transitionToNextState(Constants.WHITE_TURN)
|
||||||
else:
|
else:
|
||||||
initialize_game_system()
|
initialize_game_system()
|
||||||
|
|
@ -126,6 +133,7 @@ func _on_new_game_requested(options = {}):
|
||||||
stockfishController.start_board(cpuElo, get_board_dimensions(currentFen))
|
stockfishController.start_board(cpuElo, get_board_dimensions(currentFen))
|
||||||
else:
|
else:
|
||||||
stockfishController.start_board(cpuElo, "8x8")
|
stockfishController.start_board(cpuElo, "8x8")
|
||||||
|
resetHighlights()
|
||||||
func initialize_game_system():
|
func initialize_game_system():
|
||||||
print("Initializing game system")
|
print("Initializing game system")
|
||||||
# Set up basic styles first
|
# Set up basic styles first
|
||||||
|
|
@ -140,6 +148,11 @@ func initialize_game_system():
|
||||||
add_child(stockfishController)
|
add_child(stockfishController)
|
||||||
stockfishController.connect_to_engine(stockfishPath, self)
|
stockfishController.connect_to_engine(stockfishPath, self)
|
||||||
|
|
||||||
|
winConditionManager = WinConditionManager.new(self)
|
||||||
|
add_child(winConditionManager)
|
||||||
|
winConditionManager.connect("win_condition_met", Callable(self, "_on_win_condition_met"))
|
||||||
|
winConditionManager.connect("loss_condition_met", Callable(self, "_on_loss_condition_met"))
|
||||||
|
|
||||||
# Start the state machine
|
# Start the state machine
|
||||||
if stateMachine:
|
if stateMachine:
|
||||||
stateMachine.start()
|
stateMachine.start()
|
||||||
|
|
@ -217,9 +230,10 @@ func initializeDeckSystem() -> void:
|
||||||
deckManager.shuffleDeck()
|
deckManager.shuffleDeck()
|
||||||
deckManager.drawStartingHand()
|
deckManager.drawStartingHand()
|
||||||
# Initialize the deck manager and card display
|
# Initialize the deck manager and card display
|
||||||
cardDisplay = CardDisplay.new()
|
if cardDisplay == null:
|
||||||
add_child(deckManager)
|
cardDisplay = CardDisplay.new()
|
||||||
add_child(cardDisplay)
|
add_child(cardDisplay)
|
||||||
|
add_child(deckManager)
|
||||||
|
|
||||||
# Set up signals for card interaction
|
# Set up signals for card interaction
|
||||||
if !deckManager.has_user_signal("card_pressed"):
|
if !deckManager.has_user_signal("card_pressed"):
|
||||||
|
|
@ -301,7 +315,17 @@ func get_base_style(is_white: bool) -> StyleBoxFlat:
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
|
|
||||||
func createBoard() -> void:
|
func createBoard() -> void:
|
||||||
boardContainer.add_to_group("Flow")
|
|
||||||
|
for child in boardContainer.get_children():
|
||||||
|
boardContainer.remove_child(child)
|
||||||
|
child.queue_free()
|
||||||
|
|
||||||
|
# Reset container size
|
||||||
|
boardContainer.size = Vector2.ZERO
|
||||||
|
|
||||||
|
# Add to group if not already in it
|
||||||
|
if not boardContainer.is_in_group("Flow"):
|
||||||
|
boardContainer.add_to_group("Flow")
|
||||||
var numberX = 0
|
var numberX = 0
|
||||||
var numberY = 0
|
var numberY = 0
|
||||||
var isWhite = true
|
var isWhite = true
|
||||||
|
|
@ -461,7 +485,6 @@ func _unhandled_input(event: InputEvent) -> void:
|
||||||
func resetBoard() -> void:
|
func resetBoard() -> void:
|
||||||
clearSelection()
|
clearSelection()
|
||||||
clearBoard()
|
clearBoard()
|
||||||
setupPiecesFromFEN()
|
|
||||||
Turn = 0
|
Turn = 0
|
||||||
currentPlayer = WHITE
|
currentPlayer = WHITE
|
||||||
p1Points = 0
|
p1Points = 0
|
||||||
|
|
@ -558,20 +581,48 @@ func executeMove(targetLocation: String) -> void:
|
||||||
hasMoved = true
|
hasMoved = true
|
||||||
currentlyMovingPiece = piece
|
currentlyMovingPiece = piece
|
||||||
resetHighlights()
|
resetHighlights()
|
||||||
|
if winConditionManager:
|
||||||
|
winConditionManager.on_piece_moved(piece, old_location, targetLocation)
|
||||||
|
|
||||||
|
|
||||||
|
# Additional helper function to check if a specific tile has been reached
|
||||||
|
func is_tile_reached(location: String, piece_name: String = "") -> bool:
|
||||||
|
var container = get_node("Flow/" + location) as PieceContainer
|
||||||
|
if container and container.has_piece():
|
||||||
|
var piece = container.get_piece()
|
||||||
|
if piece_name == "" or piece.name == piece_name:
|
||||||
|
return piece.Item_Color == 0 # Player's piece
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
# func resolveMoveEffects() -> void:
|
||||||
|
# # Resolve effects after a move is made
|
||||||
|
# print("resolveMoveEffects", currentlyMovingPiece)
|
||||||
|
# togglePieceChessEffect()
|
||||||
|
|
||||||
|
# selectedNode = ""
|
||||||
|
# Turn = 1 if Turn == 0 else 0
|
||||||
|
# updateTurnIndicator()
|
||||||
|
# resetHighlights()
|
||||||
|
# hasMoved = false
|
||||||
|
# currentlyMovingPiece = null
|
||||||
|
# emit_signal("turn_changed")
|
||||||
|
|
||||||
|
|
||||||
func resolveMoveEffects() -> void:
|
func resolveMoveEffects() -> void:
|
||||||
# Resolve effects after a move is made
|
# Resolve effects after a move is made
|
||||||
print("resolveMoveEffects", currentlyMovingPiece)
|
print("resolveMoveEffects", currentlyMovingPiece)
|
||||||
togglePieceChessEffect()
|
togglePieceChessEffect()
|
||||||
|
|
||||||
selectedNode = ""
|
selectedNode = ""
|
||||||
Turn = 1 if Turn == 0 else 0
|
|
||||||
updateTurnIndicator()
|
|
||||||
resetHighlights()
|
resetHighlights()
|
||||||
hasMoved = false
|
hasMoved = false
|
||||||
currentlyMovingPiece = null
|
currentlyMovingPiece = null
|
||||||
emit_signal("turn_changed")
|
emit_signal("turn_changed")
|
||||||
|
Turn = 1 if Turn == 0 else 0
|
||||||
|
updateTurnIndicator()
|
||||||
|
|
||||||
|
func endTurn() -> void:
|
||||||
|
print("turn_changed")
|
||||||
|
|
||||||
|
|
||||||
func togglePieceChessEffect() -> void:
|
func togglePieceChessEffect() -> void:
|
||||||
|
|
@ -687,27 +738,56 @@ func isNull(location: String) -> bool:
|
||||||
|
|
||||||
func updatePointsAndCapture(capturedPiece: Pawn, animate: bool = true) -> void:
|
func updatePointsAndCapture(capturedPiece: Pawn, animate: bool = true) -> void:
|
||||||
# Update points and handle piece capture
|
# Update points and handle piece capture
|
||||||
if Turn == 0:
|
print(Turn, " updatePointsAndCapture ", capturedPiece.Item_Color)
|
||||||
|
if animate:
|
||||||
|
animatePieceCapture(capturedPiece)
|
||||||
|
if Turn == 0: # Player's turn
|
||||||
gold += capturedPiece.Points;
|
gold += capturedPiece.Points;
|
||||||
p1Points += capturedPiece.Points
|
p1Points += capturedPiece.Points
|
||||||
p1String.text = str(p1Points)
|
p1String.text = str(p1Points)
|
||||||
else:
|
|
||||||
|
# Player captured an enemy piece
|
||||||
|
print("winConditionManager and capturedPiece.Item_Color == 1")
|
||||||
|
if winConditionManager and capturedPiece.Item_Color == 1: # Enemy piece (black)
|
||||||
|
print("Player captured an enemy piece ")
|
||||||
|
winConditionManager.on_piece_captured(capturedPiece)
|
||||||
|
else: # Enemy's turn
|
||||||
p2Points += capturedPiece.Points
|
p2Points += capturedPiece.Points
|
||||||
p2String.text = str(p2Points)
|
p2String.text = str(p2Points)
|
||||||
if animate:
|
|
||||||
animatePieceCapture(capturedPiece)
|
# Enemy captured a player piece
|
||||||
|
print("winConditionManager and capturedPiece.Item_Color == 0")
|
||||||
|
if winConditionManager and capturedPiece.Item_Color == 0: # Player piece (white)
|
||||||
|
print("ENemy captured an player piece ")
|
||||||
|
winConditionManager.on_piece_lost(capturedPiece)
|
||||||
|
|
||||||
|
|
||||||
if capturedPiece.name == "King":
|
if capturedPiece.name == "King":
|
||||||
print("Game Over!")
|
print("Game Over!")
|
||||||
emit_signal("node_completed", {
|
|
||||||
"node": currentNode,
|
|
||||||
"completed": true,
|
|
||||||
"success": true
|
|
||||||
})
|
|
||||||
gamecheckMate = true
|
gamecheckMate = true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func _on_win_condition_met(condition_data):
|
||||||
|
print("Win condition met: ", condition_data)
|
||||||
|
emit_signal("node_completed", {
|
||||||
|
"node": currentNode,
|
||||||
|
"completed": true,
|
||||||
|
"success": true,
|
||||||
|
"condition": condition_data
|
||||||
|
})
|
||||||
|
# endRound()
|
||||||
|
|
||||||
|
func _on_loss_condition_met(condition_data):
|
||||||
|
print("Loss condition met: ", condition_data)
|
||||||
|
emit_signal("node_completed", {
|
||||||
|
"node": currentNode,
|
||||||
|
"completed": true,
|
||||||
|
"success": false,
|
||||||
|
"condition": condition_data
|
||||||
|
})
|
||||||
|
# endRound()
|
||||||
|
|
||||||
func animatePieceCapture(capturedPiece: Pawn) -> void:
|
func animatePieceCapture(capturedPiece: Pawn) -> void:
|
||||||
# Animate the capture of a piece
|
# Animate the capture of a piece
|
||||||
var container = capturedPiece.get_parent() as PieceContainer
|
var container = capturedPiece.get_parent() as PieceContainer
|
||||||
|
|
|
||||||
|
|
@ -299,7 +299,7 @@ func generate_boss_data(node):
|
||||||
"is_escape": node.metadata.is_escape if node.metadata.has("is_escape") else false,
|
"is_escape": node.metadata.is_escape if node.metadata.has("is_escape") else false,
|
||||||
"fen": fen + fen_ending,
|
"fen": fen + fen_ending,
|
||||||
"game_type": "chess",
|
"game_type": "chess",
|
||||||
"win_condition": Utils.WinCondition.King,
|
"win_condition": Utils.WinConditionType.CAPTURE_UNIT,
|
||||||
"reward": {
|
"reward": {
|
||||||
"gold": 50 * node.level,
|
"gold": 50 * node.level,
|
||||||
"cards": [],
|
"cards": [],
|
||||||
|
|
@ -309,8 +309,7 @@ func generate_boss_data(node):
|
||||||
"elo": node.elo,
|
"elo": node.elo,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func generate_shop_data(node):
|
func generate_shop_data(node):
|
||||||
var num_shop_cards = min(randi_range(5, 7), Utils.CardTypes.size())
|
var num_shop_cards = min(randi_range(5, 7), Utils.CardTypes.size())
|
||||||
return {
|
return {
|
||||||
|
|
@ -346,7 +345,7 @@ func generate_event_data(node):
|
||||||
"is_escape": node.metadata.is_escape if node.metadata.has("is_escape") else false,
|
"is_escape": node.metadata.is_escape if node.metadata.has("is_escape") else false,
|
||||||
"fen": "8/4p3/8/8/8/8 w KQkq - 0 1",
|
"fen": "8/4p3/8/8/8/8 w KQkq - 0 1",
|
||||||
"game_type": "maze",
|
"game_type": "maze",
|
||||||
"win_condition": Utils.WinCondition.Tile,
|
"win_condition": Utils.WinConditionType.TILE_REACHED,
|
||||||
"elo": node.elo,
|
"elo": node.elo,
|
||||||
}
|
}
|
||||||
# "rnbqkbnr1/pppppppp1/9/9/9/9/9/PPPPPPPP1/RNBQKBNR1 w KQkq - 0 1"
|
# "rnbqkbnr1/pppppppp1/9/9/9/9/9/PPPPPPPP1/RNBQKBNR1 w KQkq - 0 1"
|
||||||
|
|
@ -384,17 +383,83 @@ func generate_chess_data(node):
|
||||||
fen += pawn_string.to_upper() + "/" + unit_string.to_upper()
|
fen += pawn_string.to_upper() + "/" + unit_string.to_upper()
|
||||||
var fen_ending = " w KQkq - 0 1"
|
var fen_ending = " w KQkq - 0 1"
|
||||||
# print("generate_chess_data ", fen + fen_ending)
|
# print("generate_chess_data ", fen + fen_ending)
|
||||||
return {
|
var win_condition = Utils.WinConditionType.CAPTURE_UNIT # Default
|
||||||
|
var loss_condition = Utils.LossConditionType.UNIT_LOST # Default
|
||||||
|
|
||||||
|
# Randomly select a win condition with increasing variety at higher levels
|
||||||
|
var rng_val = _rng.randf()
|
||||||
|
var conditions_pool = [Utils.WinConditionType.CAPTURE_UNIT] # Default pool
|
||||||
|
|
||||||
|
# # Add more varied win conditions at higher levels
|
||||||
|
# if node.level >= 3:
|
||||||
|
# conditions_pool.append(Utils.WinConditionType.BOARD_CLEARED)
|
||||||
|
# if node.level >= 5:
|
||||||
|
# conditions_pool.append(Utils.WinConditionType.TILE_REACHED)
|
||||||
|
# if node.level >= 7:
|
||||||
|
# conditions_pool.append(Utils.WinConditionType.TURN_NUMBER)
|
||||||
|
|
||||||
|
# # For certain special nodes, always use specific conditions
|
||||||
|
# if node.type == Utils.RoomType.EVENT:
|
||||||
|
# win_condition = Utils.WinConditionType.TILE_REACHED
|
||||||
|
# elif node.type == Utils.RoomType.BOSS and node.level > 5:
|
||||||
|
# # Bosses at higher levels have more varied win conditions
|
||||||
|
# win_condition = conditions_pool[_rng.randi() % conditions_pool.size()]
|
||||||
|
# else:
|
||||||
|
# # Regular nodes have weighted randomness
|
||||||
|
# if rng_val < 0.7: # 70% chance of default capture king
|
||||||
|
# win_condition = Utils.WinConditionType.CAPTURE_UNIT
|
||||||
|
# else:
|
||||||
|
# # Pick randomly from the conditions pool
|
||||||
|
# win_condition = conditions_pool[_rng.randi() % conditions_pool.size()]
|
||||||
|
|
||||||
|
# Create additional metadata for specific win conditions
|
||||||
|
var additional_metadata = {}
|
||||||
|
|
||||||
|
# match win_condition:
|
||||||
|
# Utils.WinConditionType.TILE_REACHED:
|
||||||
|
# # Generate target tiles for the Tile win condition
|
||||||
|
# var target_tiles = []
|
||||||
|
# var target_count = 1 # Default to 1 target tile
|
||||||
|
|
||||||
|
# # Determine target unit (default is any piece)
|
||||||
|
# var target_unit = ""
|
||||||
|
# if _rng.randf() < 0.5: # 50% chance of specific piece
|
||||||
|
# var pieces = ["Pawn", "Knight", "Bishop", "Rook", "Queen"]
|
||||||
|
# target_unit = pieces[_rng.randi() % pieces.size()]
|
||||||
|
|
||||||
|
# # Create target tiles at the enemy's back rank
|
||||||
|
# var target_x = _rng.randi() % unit_string.length()
|
||||||
|
# target_tiles.append(str(target_x) + "-0") # Top row
|
||||||
|
|
||||||
|
# additional_metadata["target_tiles"] = target_tiles
|
||||||
|
# additional_metadata["target_unit"] = target_unit
|
||||||
|
|
||||||
|
# Utils.WinConditionType.TURN_NUMBER:
|
||||||
|
# # Set a target turn number
|
||||||
|
# additional_metadata["target_turn"] = (node.level * 2) + _rng.randi_range(5, 10)
|
||||||
|
|
||||||
|
# # Also add a turn limit for loss condition
|
||||||
|
# loss_condition = Utils.LossConditionType.TURN_NUMBER
|
||||||
|
# additional_metadata["turn_limit"] = additional_metadata["target_turn"] + _rng.randi_range(5, 15)
|
||||||
|
|
||||||
|
# Build the result metadata
|
||||||
|
var result = {
|
||||||
"is_escape": node.metadata.is_escape if node.metadata.has("is_escape") else false,
|
"is_escape": node.metadata.is_escape if node.metadata.has("is_escape") else false,
|
||||||
"fen": fen + fen_ending,
|
"fen": fen + fen_ending,
|
||||||
"game_type": "chess",
|
"game_type": "chess",
|
||||||
"win_condition": Utils.WinCondition.King,
|
"win_condition": win_condition,
|
||||||
|
"loss_condition": loss_condition,
|
||||||
"elo": node.elo,
|
"elo": node.elo,
|
||||||
"reward": {
|
"reward": {
|
||||||
"gold": 50 * node.level
|
"gold": 50 * node.level
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Merge additional metadata
|
||||||
|
for key in additional_metadata:
|
||||||
|
result[key] = additional_metadata[key]
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
func map_to_array_index(current_value, min_value, max_value, min_index, max_index):
|
func map_to_array_index(current_value, min_value, max_value, min_index, max_index):
|
||||||
# Ensure the current value is within bounds
|
# Ensure the current value is within bounds
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ class_name MenuContainer
|
||||||
const VERSION_FILE_PATH = "res://Game.json"
|
const VERSION_FILE_PATH = "res://Game.json"
|
||||||
# Signal to notify parent when a new game is requested
|
# Signal to notify parent when a new game is requested
|
||||||
# signal new_game_requested
|
# signal new_game_requested
|
||||||
|
signal reward_closed
|
||||||
signal new_game_requested(options)
|
signal new_game_requested(options)
|
||||||
signal shop_open_requested(options)
|
signal shop_open_requested(options)
|
||||||
signal reward_open_requested(options)
|
signal reward_open_requested(options)
|
||||||
|
|
@ -28,6 +29,10 @@ signal card_purchased(card, price)
|
||||||
# back up if game isn't loaded yet?
|
# back up if game isn't loaded yet?
|
||||||
var player_gold = 10
|
var player_gold = 10
|
||||||
var back_to_map = false
|
var back_to_map = false
|
||||||
|
var winConditionManager: WinConditionManager
|
||||||
|
var currentWinCondition = Utils.WinConditionType.CAPTURE_UNIT
|
||||||
|
var currentLossCondition = Utils.LossConditionType.UNIT_LOST
|
||||||
|
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
# Connect menu option signals
|
# Connect menu option signals
|
||||||
|
|
|
||||||
297
Systems/Game/WinConditionManager.gd
Normal file
297
Systems/Game/WinConditionManager.gd
Normal file
|
|
@ -0,0 +1,297 @@
|
||||||
|
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()
|
||||||
|
|
||||||
|
func 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
|
||||||
|
reset_conditions()
|
||||||
|
|
||||||
|
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 all conditions after turn change
|
||||||
|
check_conditions()
|
||||||
|
|
||||||
|
func on_piece_captured(piece):
|
||||||
|
# First verify this is an enemy piece (with opposite color to current player)
|
||||||
|
var is_enemy_piece = piece.Item_Color == (1 if chess_game.Turn == 0 else 0)
|
||||||
|
print("on_piece_captured ISEnemy ", is_enemy_piece)
|
||||||
|
if is_enemy_piece:
|
||||||
|
captured_pieces.append(piece)
|
||||||
|
|
||||||
|
# Update progress for board-cleared condition
|
||||||
|
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!"
|
||||||
|
})
|
||||||
|
|
||||||
|
# Check for specific unit capture (default: King)
|
||||||
|
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 all conditions after capture
|
||||||
|
check_conditions()
|
||||||
|
|
||||||
|
func on_piece_lost(piece):
|
||||||
|
# First verify this is a player piece (same color as current player)
|
||||||
|
var is_player_piece = piece.Item_Color == (0 if chess_game.Turn == 0 else 1)
|
||||||
|
print("on_piece_lost isPlayer ", is_player_piece)
|
||||||
|
|
||||||
|
if is_player_piece:
|
||||||
|
# Check for unit loss (default: King)
|
||||||
|
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 all conditions after loss
|
||||||
|
check_conditions()
|
||||||
|
|
||||||
|
func on_piece_moved(piece, from_location, to_location):
|
||||||
|
# Check for tile reached condition
|
||||||
|
if win_condition == Utils.WinConditionType.TILE_REACHED:
|
||||||
|
# Verify this is a player's piece (white if Turn==0, black if Turn==1)
|
||||||
|
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 specific unit is required
|
||||||
|
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 all conditions after move
|
||||||
|
check_conditions()
|
||||||
|
|
||||||
|
func check_conditions():
|
||||||
|
# This allows for custom condition checking beyond the standard events
|
||||||
|
|
||||||
|
# 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!"
|
||||||
|
})
|
||||||
|
|
||||||
|
# Update the UI with current progress
|
||||||
|
emit_signal("condition_progress_updated", condition_progress)
|
||||||
|
|
||||||
|
func count_enemy_pieces() -> int:
|
||||||
|
var count = 0
|
||||||
|
|
||||||
|
# Determine enemy color based on current turn
|
||||||
|
# In your system:
|
||||||
|
# - White pieces have Item_Color == 0
|
||||||
|
# - Black pieces have Item_Color == 1
|
||||||
|
# - Turn == 0 means white's turn, Turn == 1 means black's turn
|
||||||
|
var enemy_color = 1 if chess_game.Turn == 0 else 0
|
||||||
|
|
||||||
|
# Iterate through the board to count enemy pieces
|
||||||
|
for y in range(chess_game.boardYSize):
|
||||||
|
for x in range(chess_game.boardXSize):
|
||||||
|
var piece = chess_game.board[y][x]
|
||||||
|
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):
|
||||||
|
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
|
||||||
|
var target_tiles = metadata.get("target_tiles", [])
|
||||||
|
set_win_condition(Utils.WinConditionType.TILE_REACHED, {"target_tiles": target_tiles, "unit": metadata.get("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("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("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"
|
||||||
1
Systems/Game/WinConditionManager.gd.uid
Normal file
1
Systems/Game/WinConditionManager.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://mgoqcb66wpc3
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
extends "res://Systems/StateMachine/ChessGameState.gd"
|
extends "res://Systems/StateMachine/ChessGameState.gd"
|
||||||
|
|
||||||
const ATTACHMENT_PHASE_DURATION = 15 # Duration in seconds
|
const ATTACHMENT_PHASE_DURATION = 8 # Duration in seconds
|
||||||
var timer: Timer
|
var timer: Timer
|
||||||
var tile_pressed_connection: Signal
|
var tile_pressed_connection: Signal
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ extends "res://Systems/StateMachine/ChessGameState.gd"
|
||||||
|
|
||||||
func enter(_previous: String, data := {}) -> void:
|
func enter(_previous: String, data := {}) -> void:
|
||||||
print("ENTERING STATE ", Constants.CLEANUP)
|
print("ENTERING STATE ", Constants.CLEANUP)
|
||||||
game.cleanupPhase()
|
game.endTurn()
|
||||||
|
|
||||||
if "endCondition" in data:
|
if "endCondition" in data:
|
||||||
finished.emit(Constants.ROUND_END)
|
finished.emit(Constants.ROUND_END)
|
||||||
|
|
|
||||||
|
|
@ -321,7 +321,7 @@ func handleRegularMove(node: PieceContainer, consume: bool, generated: bool = f
|
||||||
func moveAndConsume(node: PieceContainer, consume: bool) -> void:
|
func moveAndConsume(node: PieceContainer, consume: bool) -> void:
|
||||||
var sourceContainer = game.get_node("Flow/" + game.selectedNode) as PieceContainer
|
var sourceContainer = game.get_node("Flow/" + game.selectedNode) as PieceContainer
|
||||||
var piece = sourceContainer.get_piece()
|
var piece = sourceContainer.get_piece()
|
||||||
print("Removing Piece 1")
|
# print("Removing Piece 1")
|
||||||
node.animate_movement(sourceContainer, piece);
|
node.animate_movement(sourceContainer, piece);
|
||||||
game.currentlyMovingPiece = piece
|
game.currentlyMovingPiece = piece
|
||||||
if consume:
|
if consume:
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ extends "res://Systems/StateMachine/ChessGameState.gd"
|
||||||
|
|
||||||
func enter(_previous: String, _data := {}) -> void:
|
func enter(_previous: String, _data := {}) -> void:
|
||||||
print("ENTERING STATE ", Constants.POST_MOVE)
|
print("ENTERING STATE ", Constants.POST_MOVE)
|
||||||
# game.resolveMoveEffects()
|
|
||||||
|
|
||||||
if (game.isPlayerTurn()):
|
if (game.isPlayerTurn()):
|
||||||
game.updateEffectDurations()
|
game.updateEffectDurations()
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ func start() -> void:
|
||||||
|
|
||||||
await owner.ready
|
await owner.ready
|
||||||
state.enter("")
|
state.enter("")
|
||||||
|
func enter() -> void:
|
||||||
|
state.enter("")
|
||||||
|
|
||||||
func unhandledInput(event: InputEvent) -> void:
|
func unhandledInput(event: InputEvent) -> void:
|
||||||
# print("StateMachine received input:", event)
|
# print("StateMachine received input:", event)
|
||||||
|
|
|
||||||
|
|
@ -67,13 +67,18 @@ enum RoomType {
|
||||||
EVENT
|
EVENT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum WinConditionType {
|
||||||
enum WinCondition{
|
CAPTURE_UNIT, # Default: King capture
|
||||||
King,
|
BOARD_CLEARED, # Clear the board of all opponent pieces
|
||||||
Clear,
|
TILE_REACHED, # Reach a specific tile with a specific unit
|
||||||
Tile,
|
TURN_NUMBER # Reach a specific turn number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Loss condition types
|
||||||
|
enum LossConditionType {
|
||||||
|
UNIT_LOST, # Default: King loss
|
||||||
|
TURN_NUMBER # Turn limit reached
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static var CardTypes = [
|
static var CardTypes = [
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue