ChessBuilder/Systems/Game/ChessGame.gd

444 lines
13 KiB
GDScript

class_name ChessGame extends Control
const PieceContainer = preload("res://Systems/PieceContainer.gd")
const WHITE = "white"
const BLACK = "black"
signal tile_pressed(location: String)
signal send_location(location: String)
signal turn_changed
var currentPlayer: String = WHITE
var board: Array
var currentHand: Array
var selectedNode: String = ""
var locationX: String = ""
var locationY: String = ""
var areas: PackedStringArray
var specialArea: PackedStringArray
var gamecheckMate: bool = false
var gamedraw: bool = false
var hasMoved: bool = false
var currentlyMovingPiece = null
var p1Points: int = 0
var p2Points: int = 0
var Turn: int = 0
@onready var turnIndicator: ColorRect = $TurnIndicator
@onready var p1String: RichTextLabel = $Player1Points
@onready var p2String: RichTextLabel = $Player2Points
@onready var deckManager: DeckManager
@onready var tileManager: TileManager
@onready var cardDisplay: CardDisplay
@onready var cardPreview: CardPreview
@export var boardXSize = 8
@export var boardYSize = 8
@export var tileXSize: int = 50
@export var tileYSize: int = 50
@export var windowXSize: int = 1280
@export var windowYSize: int = 720
@onready var boardContainer: FlowContainer = $Flow
@onready var stateMachine: StateMachine = $StateMachine
var lightStyle = null
var darkStyle = null
var highlightStyle = null
func _ready() -> void:
DisplayServer.window_set_size(Vector2i(windowXSize, windowYSize))
initializeGame()
initializeTiles()
stateMachine.transitionToNextState(Constants.WHITE_TURN)
func initializeTiles() -> void:
tileManager = TileManager.new($Flow, self)
add_child(tileManager)
await get_tree().process_frame
tileManager.initialize(boardContainer)
tileManager.place_random_game_tiles()
func get_base_style(is_white: bool) -> StyleBoxFlat:
return lightStyle if is_white else darkStyle
func _unhandled_input(event: InputEvent) -> void:
stateMachine.unhandledInput(event)
func _process(delta: float) -> void:
stateMachine.process(delta)
func initializeGame() -> void:
setupStyles()
setupUI()
initializeDeckSystem()
initializeCardPreview()
initializeBoard()
func initializeCardPreview() -> void:
cardPreview = CardPreview.new()
add_child(cardPreview)
func initializeBoard() -> void:
board = []
for i in range(boardXSize):
var row = []
for j in range(boardYSize):
row.append(null)
board.append(row)
createBoard()
setupPieces()
if !boardContainer.has_user_signal("tile_pressed"):
boardContainer.add_user_signal("tile_pressed")
if !boardContainer.has_user_signal("send_location"):
boardContainer.add_user_signal("send_location")
func setupUI() -> void:
p1String.text = "0"
p2String.text = "0"
updateTurnIndicator()
func initializeDeckSystem() -> void:
deckManager = DeckManager.new()
cardDisplay = CardDisplay.new()
add_child(deckManager)
add_child(cardDisplay)
if !deckManager.has_user_signal("card_pressed"):
deckManager.add_user_signal("card_pressed")
if !deckManager.has_user_signal("hand_updated"):
deckManager.add_user_signal("hand_updated")
cardDisplay.update_hand(deckManager.hand)
deckManager.connect("hand_updated", func(hand): cardDisplay.update_hand(hand))
func createBoard() -> void:
boardContainer.add_to_group("Flow")
var numberX = 0
var numberY = 0
var isWhite = true
while numberY != boardYSize:
boardContainer.size.y += tileYSize + 5
boardContainer.size.x += tileXSize + 5
while numberX != boardXSize:
createTile(numberX, numberY, isWhite)
isWhite = !isWhite
numberX += 1
isWhite = !isWhite
numberY += 1
numberX = 0
func createTile(x: int, y: int, isWhite: bool) -> void:
# print("CreateTile x ", x, " y ", y);
var tile = PieceContainer.new()
tile.set_custom_minimum_size(Vector2(tileXSize, tileYSize))
tile.add_theme_stylebox_override("normal", lightStyle if isWhite else darkStyle)
tile.set_name(str(x) + "-" + str(y))
# tile.pressed.connect(func(): handleTileSelection(tile.name))
tile.pressed.connect(func():
# tile_pressed.emit(tile.name)
boardContainer.emit_signal("tile_pressed", tile.name)
)
boardContainer.add_child(tile)
func clearSelection() :
resetHighlights()
selectedNode = ""
cardPreview.hide_preview()
return
func updatePoints(capturedPiece: Node) -> void:
if Turn == 0:
p1Points += capturedPiece.Points
p1String.text = str(p1Points)
else:
p2Points += capturedPiece.Points
p2String.text = str(p2Points)
if capturedPiece.name == "King":
print("Game Over!")
gamecheckMate = true
func parseLocation(location: String) -> void:
var number = 0
locationX = ""
while location.substr(number, 1) != "-":
locationX += location.substr(number, 1)
number += 1
locationY = location.substr(number + 1)
func setupStyles() -> void:
lightStyle = StyleBoxFlat.new()
lightStyle.bg_color = Utils.LIGHT_CELL
darkStyle = StyleBoxFlat.new()
darkStyle.bg_color = Utils.DARK_CELL
highlightStyle = StyleBoxFlat.new()
highlightStyle.bg_color = Color(0, 0.3, 0, 1)
func updateTurnIndicator():
if Turn == 0: # White's turn
turnIndicator.color = Color(1, 1, 1, 1) # White
else: # Black's turn
turnIndicator.color = Color(0, 0, 0, 1) # Black
func setupPieces() -> void:
# White pieces
placePiece("0-0", "Rook", 1)
placePiece("1-0", "Knight", 1)
placePiece("2-0", "Bishop", 1)
placePiece("3-0", "Queen", 1)
placePiece("4-0", "King", 1)
placePiece("5-0", "Bishop", 1)
placePiece("6-0", "Knight", 1)
placePiece("7-0", "Rook", 1)
for x in range(boardXSize):
placePiece(str(x) + "-1", "Pawn", 1)
# Black pieces
placePiece("0-7", "Rook", 0)
placePiece("1-7", "Knight", 0)
placePiece("2-7", "Bishop", 0)
placePiece("3-7", "Queen", 0)
placePiece("4-7", "King", 0)
placePiece("5-7", "Bishop", 0)
placePiece("6-7", "Knight", 0)
placePiece("7-7", "Rook", 0)
for x in range(boardXSize):
placePiece(str(x) + "-6", "Pawn", 0)
func placePiece(position: String, pieceName: String, color: int) -> void:
var piece = summonPiece(pieceName, color)
# boardContainer.get_node(position).add_child(piece)
var container = boardContainer.get_node(position) as PieceContainer
await container.set_piece(piece, false)
container.remove_piece(true)
container.set_piece(piece, false)
var coords = position.split("-")
board[int(coords[1])][int(coords[0])] = piece
func summonPiece(pieceName: String, color: int) -> Node:
var piece
match pieceName:
"Pawn":
piece = Pawn.new()
piece.name = "Pawn"
"King":
piece = King.new()
piece.name = "King"
"Queen":
piece = Queen.new()
piece.name = "Queen"
"Knight":
piece = Knight.new()
piece.name = "Knight"
"Rook":
piece = Rook.new()
piece.name = "Rook"
"Bishop":
piece = Bishop.new()
piece.name = "Bishop"
piece.Item_Color = color
piece.position = Vector2(tileXSize / 2, tileYSize / 2)
return piece
func clearBoard() -> void:
for child in boardContainer.get_children():
if child is PieceContainer:
child.remove_piece()
# func prepareHand() -> void:
# if deckManager.hand.size() < 5:
# deckManager.drawCard()
# pass
func updateEffectDurations() -> void:
deckManager.updateCardDurations()
tileManager.update_tile_durations()
func applyTileEffects() -> void:
tileManager.apply_tile_effects()
func applyCardEffects() -> void:
pass
func evaluatePosition() -> Dictionary:
var status = {
"checkmate": isCheckmate(),
"draw": isDraw(),
}
return status
func isValidMove(location: String) -> bool:
var node = get_node("Flow/" + location) as PieceContainer
var piece = node.get_piece()
if piece == null || piece.Item_Color != Turn:
for area in areas:
if area == node.name:
return true
return false
func resetBoard() -> void:
clearSelection()
clearBoard()
setupPieces()
Turn = 0
currentPlayer = WHITE
p1Points = 0
p1String.text = str(p1Points)
p2Points = 0
p2String.text = str(p2Points)
gamecheckMate = false;
gamedraw = false;
deckManager.initializeStartingDeck()
areas.clear()
specialArea.clear()
updateTurnIndicator()
func getMovableAreas() -> void:
# print("HIGHLIGHTING getMovableAreas 1")
resetHighlights()
areas.clear()
specialArea.clear()
var container = get_node("Flow/" + selectedNode) as PieceContainer
var piece = container.get_piece()
var piece_id = piece.get_instance_id()
# print("HIGHLIGHTING getMovableAreas 2")
if deckManager.attached_cards.has(piece_id):
var card = deckManager.attached_cards[piece_id]
cardPreview.show_card_preview(card)
if stateMachine.state.name == Constants.MOVEMENT:
var movement_state = stateMachine.state
if piece_id in movement_state.moves_remaining:
var moves_left = movement_state.moves_remaining[piece_id] - 1
cardPreview.update_moves_remaining(moves_left)
else:
cardPreview.hide_preview()
# print("HIGHLIGHTING getMovableAreas 3")
var moves = piece.getValidMoves(boardContainer, selectedNode)
areas = moves.regular_moves
specialArea = moves.special_moves
# print("HIGHLIGHTING getMovableAreas 4")
highlightValidMoves()
func highlightValidMoves() -> void:
for move in areas:
var button = boardContainer.get_node(move)
# If there's an active tile effect, combine with its current style instead
if tileManager && tileManager.get_tile(move):
var current_style = button.get_theme_stylebox("normal")
var highlightedStyle = StyleBoxFlat.new()
highlightedStyle.bg_color = current_style.bg_color + highlightStyle.bg_color
button.add_theme_stylebox_override("normal", highlightedStyle)
else:
# Default chess pattern highlighting
var isWhiteSquare = (int(move.split("-")[0]) + int(move.split("-")[1])) % 2 == 0
var baseStyle = lightStyle if isWhiteSquare else darkStyle
var combinedStyle = StyleBoxFlat.new()
combinedStyle.bg_color = baseStyle.bg_color + highlightStyle.bg_color
button.add_theme_stylebox_override("normal", combinedStyle)
func executeMove(targetLocation: String) -> void:
print("executeMove ", targetLocation)
var targetContainer = get_node("Flow/" + targetLocation) as PieceContainer
var sourceContainer = get_node("Flow/" + selectedNode) as PieceContainer
var piece = sourceContainer.get_piece()
var old_location = selectedNode
# Handle capture if there's a piece in target location
if targetContainer.has_piece():
var capturedPiece = targetContainer.get_piece()
if Turn == 0:
p1Points += capturedPiece.Points
p1String.text = str(p1Points)
else:
p2Points += capturedPiece.Points
p2String.text = str(p2Points)
targetContainer.remove_piece() # This handles freeing the captured piece
# Move piece to new location
sourceContainer.remove_piece(true)
targetContainer.set_piece(piece)
hasMoved = true
currentlyMovingPiece = piece
resetHighlights()
func togglePieceChessEffect() -> void:
var piece = currentlyMovingPiece
if piece.name == "Pawn":
if piece.Double_Start:
piece.En_Passant = true
piece.Double_Start = false
elif piece.name == "King":
piece.Castling = false
elif piece.name == "Rook":
piece.Castling = false
func resolveMoveEffects() -> void:
print("resolveMoveEffects", currentlyMovingPiece)
togglePieceChessEffect()
selectedNode = ""
Turn = 1 if Turn == 0 else 0
updateTurnIndicator()
resetHighlights()
hasMoved = false
currentlyMovingPiece = null
emit_signal("turn_changed")
func isPlayerTurn() -> bool:
return currentPlayer == WHITE
func resetHighlights():
for button in boardContainer.get_children():
if !button.name.contains("-"):
continue
# Skip if this tile has an active effect
if tileManager && tileManager.get_tile(button.name):
continue
var coord = button.name.split("-")
var isWhiteSquare = (int(coord[0]) + int(coord[1])) % 2 == 0
if isWhiteSquare:
button.add_theme_stylebox_override("normal", lightStyle)
else:
button.add_theme_stylebox_override("normal", darkStyle)
func isCheckmate() -> bool:
return gamecheckMate
func isDraw() -> bool:
return gamedraw
func endGame(reason: String) -> void:
pass
func cleanupPhase() -> void:
pass
func isNull(location: String) -> bool:
return get_node_or_null("Flow/" + location) == null