426 lines
12 KiB
GDScript
426 lines
12 KiB
GDScript
class_name ChessGame extends Control
|
|
|
|
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 activeEffects: 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
|
|
|
|
@onready var boardContainer: FlowContainer = $Flow
|
|
@onready var stateMachine: StateMachine = $StateMachine
|
|
|
|
var lightStyle = null
|
|
|
|
var darkStyle = null
|
|
var highlightStyle = null
|
|
|
|
func _ready() -> void:
|
|
initializeGame()
|
|
stateMachine.transitionToNextState(Constants.WHITE_TURN)
|
|
# initializeTiles()
|
|
|
|
|
|
# func initializeTiles() -> void:
|
|
# tileManager = TileManager.new(boardContainer, self)
|
|
# add_child(tileManager)
|
|
# tileManager.setup_initial_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()
|
|
initializeBoard()
|
|
setupUI()
|
|
initializeDeckSystem()
|
|
initializeCardPreview()
|
|
|
|
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 = Button.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 = Color(0.8, 0.8, 0.8, 1)
|
|
|
|
darkStyle = StyleBoxFlat.new()
|
|
darkStyle.bg_color = Color(0.2, 0.2, 0.2, 1)
|
|
|
|
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 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.get_child_count() > 0:
|
|
child.get_child(0).queue_free()
|
|
|
|
|
|
# func prepareHand() -> void:
|
|
# if deckManager.hand.size() < 5:
|
|
# deckManager.drawCard()
|
|
# pass
|
|
|
|
func updateEffectDurations() -> void:
|
|
for effect in activeEffects:
|
|
effect.duration -= 1
|
|
if effect.duration <= 0:
|
|
activeEffects.erase(effect)
|
|
|
|
func applyTileEffects() -> void:
|
|
for piece in get_tree().get_nodes_in_group("Pieces"):
|
|
var tile = piece.get_parent()
|
|
if tile.has_effect():
|
|
tile.apply_effect(piece)
|
|
|
|
|
|
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)
|
|
if node.get_child_count() == 0 || node.get_child(0).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 piece = get_node("Flow/" + selectedNode).get_child(0)
|
|
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:
|
|
# print("HIGHLIGHTING VALID MOVES")
|
|
for move in areas:
|
|
var button = boardContainer.get_node(move)
|
|
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 targetNode = get_node("Flow/" + targetLocation)
|
|
var piece = get_node("Flow/" + selectedNode).get_child(0)
|
|
var old_location = selectedNode
|
|
# print("piece", piece)
|
|
# tileManager.process_tile_effect(old_location, piece, false) # Exiting old tile
|
|
|
|
if targetNode.get_child_count() != 0:
|
|
var capturedPiece = targetNode.get_child(0)
|
|
if Turn == 0:
|
|
p1Points += capturedPiece.Points
|
|
p1String.text = str(p1Points)
|
|
else:
|
|
p2Points += capturedPiece.Points
|
|
p2String.text = str(p2Points)
|
|
capturedPiece.free()
|
|
|
|
piece.reparent(targetNode)
|
|
piece.position = Vector2(25, 25)
|
|
# print("piece2", piece)
|
|
hasMoved = true
|
|
currentlyMovingPiece = piece
|
|
# tileManager.process_tile_effect(targetLocation, piece, true) # Entering new tile
|
|
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
|
|
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
|