online multiplayer chess game (note server currently down)
Diffstat (limited to 'ui/board/Board.gd')
-rw-r--r--ui/board/Board.gd143
1 files changed, 97 insertions, 46 deletions
diff --git a/ui/board/Board.gd b/ui/board/Board.gd
index a060366..19a9047 100644
--- a/ui/board/Board.gd
+++ b/ui/board/Board.gd
@@ -13,15 +13,15 @@ signal remove_last
var move_indicators: PoolIntArray = []
var rot: float = 0
-
var piece_size: Vector2
-export(Color) var overlay_color := Color(0.078431, 0.333333, 0.117647, 0.498039)
-export(Color) var last_move_indicator_color := Color(0.74902, 0.662745, 0.223529, 0.498039)
-export(Color) var last_move_take_indicator := Color(0.74902, 0.407843, 0.223529, 0.498039)
-export(Color) var clockrunning_color := Color(0.219608, 0.278431, 0.133333)
-export(Color) var clockrunninglow := Color(0.47451, 0.172549, 0.164706)
-export(Color) var clocklow := Color(0.313726, 0.156863, 0.14902)
+export(Color) var overlay_color: Color
+export(Color) var premove_color: Color
+export(Color) var last_move_indicator_color: Color
+export(Color) var last_move_take_indicator: Color
+export(Color) var clockrunning_color: Color
+export(Color) var clockrunninglow: Color
+export(Color) var clocklow: Color
var board = [] # has `get_piece(algebraic position)` and `set_piece(algebraic position)` for ease of use
@@ -34,19 +34,22 @@ func set_piece(alg: String, p: Piece) -> void:
board[Chess.SQUARE_MAP[alg]] = p
-var flipped = false
-var labels = {numbers = [], letters = []}
-var background_array = []
-var last_clicked
+var flipped := false
+var labels := {numbers = [], letters = []}
+var background_array := []
+var last_clicked: Piece
+var premove: Dictionary = {}
var check_circle: GradientTexture2D = load("res://piece/check-circle.tres")
var take_circle: GradientTexture2D = load("res://piece/takeable-circle.tres")
+var move_circle: GradientTexture2D = load("res://piece/move-circle.tres")
-onready var sidebar := get_node_or_null("%Sidebar")
onready var game: GameUI = owner if owner is GameUI else null
+onready var sidebar := game.get_node_or_null("%Sidebar") if game else null
onready var darken = $Darken
onready var foreground := $Foreground
onready var background := $Background
onready var pieces := $Pieces
+onready var arrows := $"%Arrows"
var chess := Chess.new()
@@ -62,6 +65,8 @@ func _exit_tree():
func _process(_delta):
rect_rotation = rot
foreground.rect_rotation = rot
+ if Input.is_action_just_pressed("debug"):
+ print(chess.ascii())
func _resized():
@@ -73,6 +78,8 @@ func _resized():
check_circle.height = piece_size.y
take_circle.width = piece_size.x
take_circle.height = piece_size.y
+ move_circle.width = piece_size.x
+ move_circle.height = piece_size.y
if foreground:
rect_pivot_offset = (piece_size * 8) / 2
foreground.rect_pivot_offset = rect_pivot_offset
@@ -81,27 +88,27 @@ func _resized():
Log.debug("Resizing board")
+func set_take_move_circle_color(
+ color: Color = Color(overlay_color.r, overlay_color.g, overlay_color.b, .65)
+) -> void:
+ take_circle.gradient.colors[1] = color
+ move_circle.gradient.colors[0] = color
+
+
func _ready():
- take_circle.gradient.colors[1] = Color(overlay_color.r, overlay_color.g, overlay_color.b, 1)
+ set_take_move_circle_color()
_resized()
Events.connect("turn_over", self, "_on_turn_over")
- PacketHandler.connect("move_data", self, "move")
+ PacketHandler.connect("move_data", self, "move", [false, false])
create_pieces()
create_squares()
create_labels()
func resize_board():
- resize_squares()
resize_pieces()
-func resize_squares() -> void:
- for i in Chess.SQUARE_MAP.values():
- var square: BackgroundSquare = background_array[i]
- square.size()
-
-
func create_squares() -> void: # create the board
background_array.resize(128)
for i in Chess.SQUARE_MAP.values():
@@ -112,9 +119,9 @@ func create_squares() -> void: # create the board
square.hint_tooltip = alg
square.color = (Globals.board_color1 if Chess.square_color(alg) == "light" else Globals.board_color2) # set the color
background.add_child(square) # add the square to the background
- square.connect("clicked", self, "square_clicked", [alg]) # connect the clicked event
+ square.connect("clicked", self, "square_clicked", [square]) # connect the clicked event
background_array[i] = square # add the square to the background array
- find_node("Arrows")._setup(self) # initialize the arrows
+ arrows._setup(self) # initialize the arrows
func create_labels() -> void:
@@ -237,24 +244,50 @@ func flip_board() -> void:
flip_labels()
-func square_clicked(clicked_square: String) -> void:
- if chess.turn != Globals.team or Globals.spectating:
+func square_clicked(clicked_square: BackgroundSquare) -> void:
+ if Globals.spectating:
return
- var p := get_piece(clicked_square)
- if !p or p.color != Globals.team:
- if !is_instance_valid(last_clicked):
- return
+
+ var p := get_piece(clicked_square.square)
+
+ if chess.turn != Globals.team and is_instance_valid(last_clicked):
+ # PREMOVE AREA
+ var p_sq: int = Chess.SQUARE_MAP[clicked_square.square]
+ for m in chess.piece_moves(last_clicked.position, last_clicked.type, Globals.team):
+ if m.to == p_sq && m.from == Chess.SQUARE_MAP[last_clicked.position]:
+ if "from" in premove and "to" in premove:
+ background_array[premove.from].premove_indicator.hide() # hide premove indicators
+ background_array[premove.to].premove_indicator.hide()
+ if premove && premove.from == m.from && premove.to == m.to:
+ premove = {}
+ Log.debug("De-selected premove")
+ else:
+ premove = m
+ background_array[premove.from].premove_indicator.show()
+ background_array[premove.to].premove_indicator.show()
+ if premove.flags & Chess.BITS.PROMOTION:
+ p.open_promotion_previews(darken)
+ premove.promotion = yield(p, "promotion_decided")
+ Log.debug("Selected premove: %s" % premove)
+ clear_last_clicked()
+ return
+ elif (!p or p.color != Globals.team) and is_instance_valid(last_clicked):
+ # Attempt to make the move (NORMAL MOVE AREA)
for m in chess.moves({square = last_clicked.position, verbose = true}):
- if m.to == clicked_square && m.from == last_clicked.position:
- move(m.san, false)
- break
- clear_last_clicked()
- return
- last_clicked = p
+ if m.to == clicked_square.square && m.from == last_clicked.position:
+ move(m.san)
+ clear_last_clicked()
+ return
+
+ if p and p.color == Globals.team:
+ if chess.turn != Globals.team:
+ clicked_square.show_premove_indicators()
+ else:
+ clicked_square.show_move_indicators()
+ last_clicked = p
-func move(san: String, is_recieved_move := true) -> void:
- resize_board()
+func move(san: String, send := true, create_promotion_input := true) -> void:
var sound_handled = false
var move_0x88 = chess.__move_from_san(san, true)
var valid_moves = chess.moves({square = chess.algebraic(move_0x88.from), stripped = true})
@@ -279,23 +312,19 @@ func move(san: String, is_recieved_move := true) -> void:
get_piece(rook_pos).move(Chess.offset(move_0x88.to, Vector2(1, 0)))
if move_0x88.flags & Chess.BITS.PROMOTION: #promotion wow
var p: Piece = yield(board[move_0x88.from].move(Chess.algebraic(move_0x88.to), true), "completed")
- if !is_recieved_move: # was my turn, this is my move
- darken.show()
- p.open_promotion_previews()
- yield(p, "promotion_decided") # piece kills itself now
- move_0x88["promotion"] = p.promote_to
+ if create_promotion_input:
+ p.open_promotion_previews(darken)
+ move_0x88.promotion = yield(p, "promotion_decided")
san = chess.__move_to_san(move_0x88) # update the san with new promotion data
- darken.hide()
+ p.queue_free()
else: # was opponents turn, this is opponents move: promotion is already chosen
p.queue_free()
- # the move animation is useless if its not my turn
- # but it changes p.position, so its usefull.
make_piece(p.position, move_0x88.promotion, p.color)
SoundFx.play("Move" if move_0x88.flags & Chess.BITS.NORMAL else "Capture")
sound_handled = true
else: # not promotion: from **always** moves to `to`
var _p = board[move_0x88.from].move(Chess.algebraic(move_0x88.to))
- if !is_recieved_move:
+ if send:
PacketHandler.send_mov(san)
if !sound_handled:
SoundFx.play("Move")
@@ -345,6 +374,28 @@ func undo(two: bool = false) -> void:
func _on_turn_over():
+ if get_parent() == get_viewport(): # for testing
+ Globals.team = chess.turn
+
+ if Globals.grid.chess.turn == Globals.team:
+ set_take_move_circle_color()
+ # use the premove if possible
+ if premove:
+ background_array[premove.from].premove_indicator.hide()
+ background_array[premove.to].premove_indicator.hide()
+ if board[premove.from]: # see if its valid
+ if premove.flags & (Chess.BITS.CAPTURE | Chess.BITS.EP_CAPTURE) && not board[premove.to]:
+ return
+ var san = chess.__move_to_san(premove,chess.__generate_moves({legal = true}),false)
+ if san:
+ var legal_moves = chess.moves({square = chess.algebraic(premove.from), stripped = true})
+ var is_possible_move = legal_moves.find(chess.stripped_san(san)) != -1
+ if chess.__move_from_san(san, true) and (is_possible_move): # it is valid
+ Log.debug(["Executing premove:", san])
+ move(san, true, false) # make the move, send it to the opponent, dont prompt for premoves
+ premove = {}
+ else:
+ set_take_move_circle_color(premove_color)
SaveLoad.save("user://game.json", {pgn = chess.pgn(), fen = chess.fen()})
clear_last_clicked()
check_game_over()