online multiplayer chess game (note server currently down)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
extends Node2D
class_name Piece, "res://assets/pieces/california/wP.png"

var real_position := Vector2.ZERO
var white := true
var shortname := ""
var mininame := "♙"
var has_moved := false
var frameon := false
var team := "w"

onready var sprite := $Sprite
onready var tween := $Tween
onready var anim := $AnimationPlayer
onready var rotate := $RotatePlayer
onready var colorrect := $ColorRect
onready var frame := $Frame


func _ready() -> void:
	team = "w" if white else "b"
	sprite.position = Globals.grid.piece_size / 2
	var tmp: Array = Utils.get_node_name(self)
	mininame = tmp[0]
	shortname = tmp[1]
	frame.position = Globals.grid.piece_size / 2
	frame.modulate = Globals.grid.overlay_color
	colorrect.color = Globals.grid.overlay_color
	colorrect.rect_size = Globals.grid.piece_size
	load_texture()


func load_texture(path := "%s%s%s.png" % [Globals.grid.ASSETS_PATH, team, shortname.to_upper()]) -> void:
	sprite.texture = load(path)


func clicked() -> void:
	colorrect.show()
	set_circle(get_moves())
	set_circle(get_attacks(), "take")


func clear_clicked() -> void:
	colorrect.hide()
	Globals.grid.clear_fx()


func algebraic_take_notation(position: Vector2, startpos: Vector2 = real_position) -> String:
	var starter := shortname if shortname != "p" else Utils.to_algebraic(startpos)[0]
	return starter + "x" + Utils.to_algebraic(position)


func algebraic_move_notation(position: Vector2) -> String:
	var starter := shortname if shortname != "p" else ""
	return starter + Utils.to_algebraic(position)


func move(newpos: Vector2) -> void:  # dont use directly; use moveto
	tween.interpolate_property(self, "position", position, newpos * Globals.grid.piece_size, 0.3, Tween.TRANS_BACK)
	var signresult := sign(newpos.x * Globals.grid.piece_size.x - global_position.x)
	Log.debug("signresult: " + str(signresult))
	if signresult == 1:
		rotate.play("Right")
	elif signresult == -1:
		rotate.play("Left")
	anim.play("Move")
	tween.start()


func moveto(pos: Vector2, real := true) -> void:
	Globals.grid.matrix[real_position.y][real_position.x] = null
	Globals.grid.matrix[pos.y][pos.x] = self
	if real:
		real_position = pos
		move(real_position)
		SoundFx.play("Move")
		has_moved = true


func pos_around(around_vector: Vector2) -> Vector2:
	return real_position + around_vector


static func all_dirs() -> PoolVector2Array:
	return PoolVector2Array(
		[
			Vector2.UP,
			Vector2.DOWN,
			Vector2.LEFT,
			Vector2.RIGHT,
			Vector2(1, 1),
			Vector2(1, -1),
			Vector2(-1, 1),
			Vector2(-1, -1)
		]
	)


func traverse(arr: PoolVector2Array = [], no_enemys := false, check_spots_check := true) -> PoolVector2Array:
	var circle_array: PoolVector2Array = []
	for i in arr:
		var pos := real_position
		while true:
			pos += i
			if !is_on_board(pos):
				break
			if at_pos(pos) != null:
				if at_pos(pos).white == white:  # fren
					break
				# certaintly a enemy
				if no_enemys:  # do we want enemys?
					break
				circle_array.append(pos)
				break
			if check_spots_check and checkcheck(pos):
				continue
			circle_array.append(pos)
	return circle_array


static func at_pos(vector: Vector2) -> Piece:
	if is_instance_valid(Globals.grid):
		return Globals.grid.matrix[vector.y][vector.x]
	return null


func can_move() -> bool:  # checks if you can legally move
	if get_moves().size() != 0 or get_attacks().size() != 0:
		return true
	return false


func get_moves(_no_enemys := false, _check_spots_check := true) -> PoolVector2Array:  # @Override
	return PoolVector2Array()


func get_attacks(check_spots_check := true) -> PoolVector2Array:  # @Override
	var moves := get_moves(false, check_spots_check)  # assumes the attacks are same as moves
	var final: PoolVector2Array = []
	for i in moves:
		if at_pos(i) != null:
			if at_pos(i).white != white:  # attack ze enemie
				if check_spots_check and checkcheck(i):
					continue
				final.append(i)
	return final


func can_attack_piece(piece: Piece) -> bool:  ##i cant use pos in get_attacks for some bizarre reasons
	for pos in get_attacks(false):
		if at_pos(pos) == piece:
			return true
	return false


func can_touch(pos: Vector2, attack := true, move := true) -> bool:
	if attack and move:
		return pos in get_attacks() or pos in get_moves()
	elif attack:
		return pos in get_attacks()
	elif move:
		return pos in get_moves()
	else:
		return false


static func create_move_circles(pos: Vector2) -> void:
	Globals.grid.background_matrix[pos.x][pos.y].set_circle(true)  # make the move circle


static func create_take_circles(spot: Piece) -> void:  # create take circles
	spot.set_frame()  # turn on the little take frame on the piece, to show its takeable


static func set_circle(positions: Array, type := "move") -> void:
	for pos in positions:
		var spot := at_pos(pos)  # get the piece at the position
		if type == "move":
			create_move_circles(pos)  # create the move circle
		elif type == "take":
			create_take_circles(spot)  # if the king is in check, return true


func checkcheck(pos) -> bool:  # moves to position, then checks if your king is in check
	# TODO: figure out why this function isnt working with can_move()
	var mat: Array = Globals.grid.matrix.duplicate(true)  # make a copy of the matrix
	moveto(pos, false)  # move to the position
	if Globals.grid.check_in_check():  # if you are still in check
		Globals.grid.matrix = mat  # revert changes on the matrix
		return true
	Globals.grid.matrix = mat
	return false


static func is_on_board(vector: Vector2) -> bool:  # limit the vector to the board
	if vector.y < 0 or vector.y > 7 or vector.x < 0 or vector.x > 7:
		return false
	return true


func take(piece: Piece) -> void:
	clear_clicked()
	piece.took()
	moveto(piece.real_position, true)
	Globals.reset_halfmove()


func took() -> void:  # called when piece is taken
	SoundFx.play("Capture")
	Globals.grid.matrix[real_position.y][real_position.x] = null
	anim.play("Take")


func set_frame(value := true) -> void:
	frameon = value
	frame.visible = value