fix: refine game mode state tracking and turn handling
* Centralize ball state generation in `BaseMode` * Track turn count, player, and ball state consistently * Prevent 8-ball, 9-ball, and colored snooker balls from being marked valid when reaped/sunk * Update mode initialization and ball-state assignment * Normalize Free Ball mode node name to `freeball`
This commit is contained in:
@@ -1,11 +1,15 @@
|
|||||||
class_name Ball8 extends BaseMode
|
class_name Ball8 extends BaseMode
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
func reap_ball(ball: Node3D) -> void:
|
func reap_ball(ball: Node3D) -> void:
|
||||||
super(ball)
|
super(ball)
|
||||||
|
|
||||||
if ball.name == "08_ball":
|
if ball.name == "08_ball":
|
||||||
# TODO: 8 ball must not be be destroyed. Handle rule...
|
# TODO: 8 ball must not be be destroyed. Handle rule...
|
||||||
|
ball_state[ball.name]["valid_end"] = false
|
||||||
pass
|
pass
|
||||||
|
|
||||||
func process_ball(ball: Node3D) -> void:
|
func process_ball(ball: Node3D) -> void:
|
||||||
@@ -13,6 +17,7 @@ func process_ball(ball: Node3D) -> void:
|
|||||||
|
|
||||||
if ball.name == "08_ball":
|
if ball.name == "08_ball":
|
||||||
# TODO: 8 ball must be sunk last. Handle rule...
|
# TODO: 8 ball must be sunk last. Handle rule...
|
||||||
|
ball_state[ball.name]["valid_end"] = false
|
||||||
pass
|
pass
|
||||||
|
|
||||||
func handle_switch_user() -> void:
|
func handle_switch_user() -> void:
|
||||||
@@ -25,9 +30,11 @@ func handle_switch_user() -> void:
|
|||||||
|
|
||||||
if balls_sunk.is_empty():
|
if balls_sunk.is_empty():
|
||||||
Globals.game_state.switch_active_player()
|
Globals.game_state.switch_active_player()
|
||||||
|
turn_count += 1
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO: Handle points, etc
|
# TODO: Handle points, etc
|
||||||
# Globals.multiplayer_data.current_turn_player_id
|
# Globals.multiplayer_data.current_turn_player_id
|
||||||
|
|
||||||
balls_sunk.clear()
|
balls_sunk.clear()
|
||||||
|
turn_count += 1
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
class_name Ball9 extends BaseMode
|
class_name Ball9 extends BaseMode
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
func reap_ball(ball: Node3D) -> void:
|
func reap_ball(ball: Node3D) -> void:
|
||||||
super(ball)
|
super(ball)
|
||||||
|
|
||||||
if ball.name == "09_ball":
|
if ball.name == "09_ball":
|
||||||
# TODO: 9 ball must not be be destroyed. Handle rule...
|
# TODO: 9 ball must not be be destroyed. Handle rule...
|
||||||
|
ball_state[ball.name]["valid_end"] = false
|
||||||
pass
|
pass
|
||||||
|
|
||||||
func process_ball(ball: Node3D) -> void:
|
func process_ball(ball: Node3D) -> void:
|
||||||
@@ -13,6 +17,7 @@ func process_ball(ball: Node3D) -> void:
|
|||||||
|
|
||||||
if ball.name == "09_ball":
|
if ball.name == "09_ball":
|
||||||
# TODO: 9 ball must be sunk last. Handle rule...
|
# TODO: 9 ball must be sunk last. Handle rule...
|
||||||
|
ball_state[ball.name]["valid_end"] = false
|
||||||
pass
|
pass
|
||||||
|
|
||||||
func handle_switch_user() -> void:
|
func handle_switch_user() -> void:
|
||||||
@@ -25,9 +30,11 @@ func handle_switch_user() -> void:
|
|||||||
|
|
||||||
if balls_sunk.is_empty():
|
if balls_sunk.is_empty():
|
||||||
Globals.game_state.switch_active_player()
|
Globals.game_state.switch_active_player()
|
||||||
|
turn_count += 1
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO: Handle points, etc
|
# TODO: Handle points, etc
|
||||||
# Globals.multiplayer_data.current_turn_player_id
|
# Globals.multiplayer_data.current_turn_player_id
|
||||||
|
|
||||||
balls_sunk.clear()
|
balls_sunk.clear()
|
||||||
|
turn_count += 1
|
||||||
|
|||||||
@@ -4,37 +4,43 @@ class_name BaseMode extends Node
|
|||||||
# these signals to handle game related rules regarding ball sinks.
|
# these signals to handle game related rules regarding ball sinks.
|
||||||
|
|
||||||
|
|
||||||
|
var turn_count: int = 1
|
||||||
var player_1_points: int = 0
|
var player_1_points: int = 0
|
||||||
var player_2_points: int = 0
|
var player_2_points: int = 0
|
||||||
|
|
||||||
var ball_state := generate_ball_state()
|
# NOTE: Kinda a super tracker of balls. Not all entries
|
||||||
var balls_sunk := []
|
# generated are used depending on the game type.
|
||||||
var balls_reaped := []
|
var ball_state: Dictionary = {}
|
||||||
|
|
||||||
var STATE: Dictionary = {
|
# NOTE: Used to track handoff logic and is cleared after eah switch accordingly.
|
||||||
|
var balls_sunk: Array = []
|
||||||
|
var balls_reaped: Array = []
|
||||||
|
|
||||||
|
# NOTE: Kinda a super tracker of the state of a ball.
|
||||||
|
# Not all entries are used depending on the game type.
|
||||||
|
var BALL_STATE: Dictionary = {
|
||||||
|
"turn": 0,
|
||||||
|
"player": "",
|
||||||
"sunk": false,
|
"sunk": false,
|
||||||
"reaped": false,
|
"reaped": false,
|
||||||
"player": ""
|
"valid_end": true,
|
||||||
|
"points": 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
var COLORED_BALLS: Array = [
|
|
||||||
"yellow_ball", "green_ball", "brown_ball",
|
func _init() -> void:
|
||||||
"blue_ball", "pink_ball", "black_ball"
|
pass
|
||||||
]
|
|
||||||
|
|
||||||
func generate_ball_state() -> Dictionary:
|
func generate_ball_state() -> Dictionary:
|
||||||
var state := {}
|
var state := {}
|
||||||
|
|
||||||
for ball_name: String in COLORED_BALLS:
|
|
||||||
state[ball_name] = STATE.duplicate_deep()
|
|
||||||
|
|
||||||
for i: int in range(1, 16):
|
for i: int in range(1, 16):
|
||||||
state["%02d_ball" % i] = STATE.duplicate_deep()
|
var ball_name = "%02d_ball" % i
|
||||||
|
state[ball_name] = BALL_STATE.duplicate_deep()
|
||||||
|
state[ball_name]["points"] = i
|
||||||
|
|
||||||
return state
|
return state
|
||||||
|
|
||||||
func is_colored_ball(ball_name: String) -> bool:
|
|
||||||
return ball_name in COLORED_BALLS
|
|
||||||
|
|
||||||
func which_player() -> String:
|
func which_player() -> String:
|
||||||
return \
|
return \
|
||||||
@@ -46,14 +52,17 @@ func which_player() -> String:
|
|||||||
|
|
||||||
func reap_ball(ball: Node3D) -> void:
|
func reap_ball(ball: Node3D) -> void:
|
||||||
balls_reaped.append(ball.name)
|
balls_reaped.append(ball.name)
|
||||||
ball_state[ball.name]["reaped"] = not ball_state[ball.name]["reaped"]
|
|
||||||
|
ball_state[ball.name]["turn"] = turn_count
|
||||||
ball_state[ball.name]["player"] = which_player()
|
ball_state[ball.name]["player"] = which_player()
|
||||||
|
ball_state[ball.name]["reaped"] = not ball_state[ball.name]["reaped"]
|
||||||
|
|
||||||
func process_ball(ball: Node3D) -> void:
|
func process_ball(ball: Node3D) -> void:
|
||||||
balls_sunk.append(ball.name)
|
balls_sunk.append(ball.name)
|
||||||
|
|
||||||
ball_state[ball.name]["sunk"] = not ball_state[ball.name]["sunk"]
|
ball_state[ball.name]["turn"] = turn_count
|
||||||
ball_state[ball.name]["player"] = which_player()
|
ball_state[ball.name]["player"] = which_player()
|
||||||
|
ball_state[ball.name]["sunk"] = not ball_state[ball.name]["sunk"]
|
||||||
|
|
||||||
func handle_switch_user() -> void:
|
func handle_switch_user() -> void:
|
||||||
assert(false, "This method needs to be overridden...")
|
assert(false, "This method needs to be overridden...")
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
class_name FreeBall extends BaseMode
|
class_name FreeBall extends BaseMode
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
func reap_ball(ball: Node3D) -> void:
|
func reap_ball(ball: Node3D) -> void:
|
||||||
super(ball)
|
super(ball)
|
||||||
|
|
||||||
@@ -17,9 +20,11 @@ func handle_switch_user() -> void:
|
|||||||
|
|
||||||
if balls_sunk.is_empty():
|
if balls_sunk.is_empty():
|
||||||
Globals.game_state.switch_active_player()
|
Globals.game_state.switch_active_player()
|
||||||
|
turn_count += 1
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO: Handle points, etc
|
# TODO: Handle points, etc
|
||||||
# Globals.multiplayer_data.current_turn_player_id
|
# Globals.multiplayer_data.current_turn_player_id
|
||||||
|
|
||||||
balls_sunk.clear()
|
balls_sunk.clear()
|
||||||
|
turn_count += 1
|
||||||
|
|||||||
@@ -22,4 +22,4 @@ func _balls_stopped_moving() -> void:
|
|||||||
|
|
||||||
func set_mode(game_mode) -> void:
|
func set_mode(game_mode) -> void:
|
||||||
mode = Globals.game_data.GameMode.get(game_mode).new()
|
mode = Globals.game_data.GameMode.get(game_mode).new()
|
||||||
mode.generate_ball_state()
|
mode.ball_state = mode.generate_ball_state()
|
||||||
|
|||||||
@@ -1,16 +1,51 @@
|
|||||||
class_name Snooker extends BaseMode
|
class_name Snooker extends BaseMode
|
||||||
|
|
||||||
|
|
||||||
# NOTE: The game is sometimes played with fewer red balls- commonly 6 or 10.
|
# NOTE: The game is sometimes played with fewer red balls- commonly 6 or 10.
|
||||||
# Normally, 15 red balls (1 point) and 6 balls of different colors:
|
# Normally, 15 red balls (1 point) and 6 balls of different colors:
|
||||||
# yellow (2 points), green (3), brown (4), blue (5), pink (6), black (7).
|
# yellow (2 points), green (3), brown (4), blue (5), pink (6), black (7).
|
||||||
|
|
||||||
|
|
||||||
|
var COLORED_BALLS: Array[String] = [
|
||||||
|
"yellow_ball", "green_ball", "brown_ball",
|
||||||
|
"blue_ball", "pink_ball", "black_ball"
|
||||||
|
]
|
||||||
|
|
||||||
|
var COLORED_BALLS_POINTS: Array[int] = [
|
||||||
|
2, 3, 4,
|
||||||
|
5, 6, 7
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func generate_ball_state() -> Dictionary:
|
||||||
|
var state: Dictionary = {}
|
||||||
|
|
||||||
|
for i in COLORED_BALLS.size():
|
||||||
|
var ball_name = COLORED_BALLS[i]
|
||||||
|
var points = COLORED_BALLS_POINTS[i]
|
||||||
|
|
||||||
|
state[ball_name] = BALL_STATE.duplicate_deep()
|
||||||
|
state[ball_name]["points"] = points
|
||||||
|
|
||||||
|
# NOTE: Red balls
|
||||||
|
for i: int in range(1, 16):
|
||||||
|
var ball_name = "%02d_ball" % i
|
||||||
|
state[ball_name] = BALL_STATE.duplicate_deep()
|
||||||
|
state[ball_name]["points"] = 1
|
||||||
|
|
||||||
|
ball_state = state
|
||||||
|
return state
|
||||||
|
|
||||||
|
func is_colored_ball(ball_name: String) -> bool:
|
||||||
|
return ball_name in COLORED_BALLS
|
||||||
|
|
||||||
func reap_ball(ball: Node3D) -> void:
|
func reap_ball(ball: Node3D) -> void:
|
||||||
super(ball)
|
super(ball)
|
||||||
|
|
||||||
if is_colored_ball(ball.name):
|
if is_colored_ball(ball.name):
|
||||||
# TODO: Colored ball must not be be destroyed. Handle rule...
|
# TODO: Colored ball must not be be destroyed. Handle rule...
|
||||||
|
ball_state[ball.name]["valid_end"] = false
|
||||||
pass
|
pass
|
||||||
|
|
||||||
func process_ball(ball: Node3D) -> void:
|
func process_ball(ball: Node3D) -> void:
|
||||||
@@ -19,6 +54,9 @@ func process_ball(ball: Node3D) -> void:
|
|||||||
if is_colored_ball(ball.name):
|
if is_colored_ball(ball.name):
|
||||||
# TODO: Colored ball must not be be processed before red ball sunk.
|
# TODO: Colored ball must not be be processed before red ball sunk.
|
||||||
# Handle rule...
|
# Handle rule...
|
||||||
|
var red_ball_sunk = true
|
||||||
|
if not red_ball_sunk:
|
||||||
|
pass
|
||||||
pass
|
pass
|
||||||
|
|
||||||
func handle_switch_user() -> void:
|
func handle_switch_user() -> void:
|
||||||
@@ -31,9 +69,11 @@ func handle_switch_user() -> void:
|
|||||||
|
|
||||||
if balls_sunk.is_empty():
|
if balls_sunk.is_empty():
|
||||||
Globals.game_state.switch_active_player()
|
Globals.game_state.switch_active_player()
|
||||||
|
turn_count += 1
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO: Handle points, etc
|
# TODO: Handle points, etc
|
||||||
# Globals.multiplayer_data.current_turn_player_id
|
# Globals.multiplayer_data.current_turn_player_id
|
||||||
|
|
||||||
balls_sunk.clear()
|
balls_sunk.clear()
|
||||||
|
turn_count += 1
|
||||||
|
|||||||
@@ -41,6 +41,6 @@ script = ExtResource("4_glu7g")
|
|||||||
[connection signal="pressed" from="ui/body/right_body/vbox/8ball" to="." method="_on_mode_bttn_pressed" flags=18]
|
[connection signal="pressed" from="ui/body/right_body/vbox/8ball" to="." method="_on_mode_bttn_pressed" flags=18]
|
||||||
[connection signal="pressed" from="ui/body/right_body/vbox/9ball" to="." method="_on_mode_bttn_pressed" flags=18]
|
[connection signal="pressed" from="ui/body/right_body/vbox/9ball" to="." method="_on_mode_bttn_pressed" flags=18]
|
||||||
[connection signal="pressed" from="ui/body/right_body/vbox/snooker" to="." method="_on_mode_bttn_pressed" flags=18]
|
[connection signal="pressed" from="ui/body/right_body/vbox/snooker" to="." method="_on_mode_bttn_pressed" flags=18]
|
||||||
[connection signal="pressed" from="ui/body/right_body/vbox/free_ball" to="." method="_on_mode_bttn_pressed" flags=18]
|
[connection signal="pressed" from="ui/body/right_body/vbox/freeball" to="." method="_on_mode_bttn_pressed" flags=18]
|
||||||
|
|
||||||
[editable path="ui"]
|
[editable path="ui"]
|
||||||
|
|||||||
@@ -60,4 +60,4 @@ func _on_match_create_bttn_pressed() -> void:
|
|||||||
MessageBus.emit_request.rpc("match_list_add_entry", match_entry)
|
MessageBus.emit_request.rpc("match_list_add_entry", match_entry)
|
||||||
|
|
||||||
func _on_mode_bttn_pressed(button: Button) -> void:
|
func _on_mode_bttn_pressed(button: Button) -> void:
|
||||||
active_mode = button.name.remove_chars("_").to_lower()
|
active_mode = button.name.to_lower()
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ mouse_default_cursor_shape = 2
|
|||||||
disabled = true
|
disabled = true
|
||||||
text = "Snooker"
|
text = "Snooker"
|
||||||
|
|
||||||
[node name="free_ball" type="Button" parent="body/right_body/vbox"]
|
[node name="freeball" type="Button" parent="body/right_body/vbox"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
mouse_default_cursor_shape = 2
|
mouse_default_cursor_shape = 2
|
||||||
text = "Free Ball"
|
text = "Free Ball"
|
||||||
|
|||||||
Reference in New Issue
Block a user