implemented maze
This commit is contained in:
parent
5d04deae9f
commit
ef6cee7883
7 changed files with 263 additions and 104 deletions
|
|
@ -42,6 +42,7 @@ var highlightStyle = null
|
|||
var cpuElo = 1500
|
||||
var is_initialized: bool = false
|
||||
var currentNode = null;
|
||||
var has_opponent = true;
|
||||
|
||||
# Node references
|
||||
@onready var turnIndicator: ColorRect = $TurnIndicator
|
||||
|
|
@ -60,9 +61,7 @@ var currentNode = null;
|
|||
|
||||
var captured_pieces_this_turn: Array = []
|
||||
var player_pieces_lost_this_turn: Array = []
|
||||
var winConditionManager: WinConditionManager
|
||||
var currentWinCondition = Utils.WinConditionType.CAPTURE_UNIT
|
||||
var currentLossCondition = Utils.LossConditionType.UNIT_LOST
|
||||
var winConditionManager: WinConditionManager = null
|
||||
|
||||
|
||||
# Export parameters
|
||||
|
|
@ -109,13 +108,21 @@ func _on_new_game_requested(options = {}):
|
|||
captured_pieces_this_turn = []
|
||||
player_pieces_lost_this_turn = []
|
||||
turnIndicator.visible = true
|
||||
if options and "fen" in options.metadata:
|
||||
currentFen = options.metadata.fen
|
||||
if "elo" in options:
|
||||
cpuElo = options.metadata.elo
|
||||
has_opponent = true
|
||||
if cameraController:
|
||||
cameraController.reset_view()
|
||||
if options and "metadata" in options:
|
||||
if options:
|
||||
if "fen" in options.metadata:
|
||||
currentFen = options.metadata.fen
|
||||
if "elo" in options.metadata:
|
||||
cpuElo = options.metadata.elo
|
||||
if "has_opponent" in options.metadata:
|
||||
has_opponent = options.metadata.has_opponent
|
||||
if winConditionManager == null:
|
||||
winConditionManager = WinConditionManager.new(self)
|
||||
add_child(winConditionManager)
|
||||
winConditionManager.connect("win_condition_met", Callable(self, "_on_win_condition_met"))
|
||||
winConditionManager.connect("loss_condition_met", Callable(self, "_on_loss_condition_met"))
|
||||
if winConditionManager:
|
||||
winConditionManager.load_condition_from_metadata(options.metadata)
|
||||
|
||||
|
|
@ -126,6 +133,7 @@ func _on_new_game_requested(options = {}):
|
|||
resetBoard()
|
||||
initializeDeckSystem()
|
||||
initializeBoard()
|
||||
initializeTiles()
|
||||
if cardDisplay:
|
||||
cardDisplay.visible = true
|
||||
if stateMachine:
|
||||
|
|
@ -150,7 +158,7 @@ func initialize_game_system():
|
|||
stockfishController = StockfishController.new()
|
||||
add_child(stockfishController)
|
||||
stockfishController.connect_to_engine(stockfishPath, self)
|
||||
|
||||
if winConditionManager == null:
|
||||
winConditionManager = WinConditionManager.new(self)
|
||||
add_child(winConditionManager)
|
||||
winConditionManager.connect("win_condition_met", Callable(self, "_on_win_condition_met"))
|
||||
|
|
@ -621,10 +629,13 @@ func resolveMoveEffects() -> void:
|
|||
func endTurn() -> void:
|
||||
print("turn_changed")
|
||||
emit_signal("turn_changed")
|
||||
if has_opponent:
|
||||
Turn = 1 if Turn == 0 else 0
|
||||
updateTurnIndicator()
|
||||
if (isPlayerTurn()):
|
||||
updateEffectDurations()
|
||||
|
||||
if winConditionManager.win_condition == Utils.WinConditionType.CAPTURE_UNIT || winConditionManager.loss_condition == Utils.LossConditionType.UNIT_LOST:
|
||||
check_captured_pieces_conditions()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ func _get_random_room_type(level, total_levels):
|
|||
return Utils.RoomType.BOSS
|
||||
elif roll < boss_chance + shop_chance:
|
||||
return Utils.RoomType.SHOP
|
||||
elif roll < boss_chance + shop_chance + event_chance and level > 5:
|
||||
elif roll < boss_chance + shop_chance + event_chance:
|
||||
return Utils.RoomType.EVENT
|
||||
else:
|
||||
return Utils.RoomType.NORMAL
|
||||
|
|
@ -341,12 +341,39 @@ func generate_starting_data(node):
|
|||
}
|
||||
|
||||
func generate_event_data(node):
|
||||
var index = map_to_array_index(node.level, 2, current_max_level - 2, 1, level_unit_distribution.size() - 1);
|
||||
var unit_string = level_unit_distribution[index]
|
||||
|
||||
var height = 6
|
||||
var width = unit_string.length()
|
||||
if node.level > 7 and node.level <= 10:
|
||||
height = node.level
|
||||
elif node.level > 10:
|
||||
height = 10
|
||||
# var mazedata = generate_maze(width, height)
|
||||
var mazedata = generate_maze(16, 16)
|
||||
# print("**************************")
|
||||
# print("**************************")
|
||||
# print("**************************")
|
||||
# print(mazedata)
|
||||
# print("**************************")
|
||||
# print("**************************")
|
||||
# print("**************************")
|
||||
return {
|
||||
"is_escape": node.metadata.is_escape if node.metadata.has("is_escape") else false,
|
||||
"fen": "8/4p3/8/8/8/8 w KQkq - 0 1",
|
||||
"fen": mazedata.fen + " w KQkq - 0 1",
|
||||
"game_type": "maze",
|
||||
"has_opponent": false,
|
||||
"win_condition": Utils.WinConditionType.TILE_REACHED,
|
||||
"win_target": [mazedata.end],
|
||||
"win_target_unit": "King",
|
||||
"elo": node.elo,
|
||||
"reward": {
|
||||
"gold": 150 * node.level,
|
||||
"cards": [],
|
||||
"selection": generate_shop_cards(5),
|
||||
"selection_limit": 1
|
||||
},
|
||||
}
|
||||
# "rnbqkbnr1/pppppppp1/9/9/9/9/9/PPPPPPPP1/RNBQKBNR1 w KQkq - 0 1"
|
||||
func generate_chess_data(node):
|
||||
|
|
@ -475,3 +502,101 @@ func map_to_array_index(current_value, min_value, max_value, min_index, max_inde
|
|||
|
||||
# Ensure we're returning an integer within the valid array index range
|
||||
return int(clamp(mapped_index, min_index, max_index))
|
||||
|
||||
|
||||
|
||||
func generate_maze(width: int, height: int) -> Dictionary:
|
||||
# Ensure dimensions are odd to have proper walls
|
||||
if width % 2 == 0:
|
||||
width += 1
|
||||
if height % 2 == 0:
|
||||
height += 1
|
||||
|
||||
# Initialize the maze with all walls
|
||||
var maze = []
|
||||
for y in range(height):
|
||||
var row = []
|
||||
for x in range(width):
|
||||
row.append("*") # * represents wall
|
||||
maze.append(row)
|
||||
|
||||
# Use a recursive backtracking algorithm to generate the maze
|
||||
var rng = RandomNumberGenerator.new()
|
||||
rng.randomize()
|
||||
|
||||
# Start at a random odd position
|
||||
var start_x = rng.randi_range(0, width/2-1) * 2 + 1
|
||||
var start_y = rng.randi_range(0, height/2-1) * 2 + 1
|
||||
|
||||
# Carve the maze recursively
|
||||
_carve_maze(maze, start_x, start_y, width, height, rng)
|
||||
|
||||
# Pick a random end point (far from start point)
|
||||
var end_x = 0
|
||||
var end_y = 0
|
||||
var max_distance = 0
|
||||
|
||||
for y in range(1, height, 2):
|
||||
for x in range(1, width, 2):
|
||||
if maze[y][x] == " ": # Only consider path cells
|
||||
var distance = abs(x - start_x) + abs(y - start_y)
|
||||
if distance > max_distance:
|
||||
max_distance = distance
|
||||
end_x = x
|
||||
end_y = y
|
||||
|
||||
maze[start_y][start_x] = "k"
|
||||
|
||||
# Mark the end position with a space (keep it as a path)
|
||||
# It's already a space, but we ensure it here
|
||||
maze[end_y][end_x] = " "
|
||||
|
||||
# Convert the maze to a FEN-like string
|
||||
var fen_string = ""
|
||||
for y in range(height):
|
||||
var empty_count = 0
|
||||
for x in range(width):
|
||||
if maze[y][x] == " ": # Empty space
|
||||
empty_count += 1
|
||||
else:
|
||||
if empty_count > 0:
|
||||
fen_string += str(empty_count)
|
||||
empty_count = 0
|
||||
fen_string += maze[y][x]
|
||||
|
||||
# Add any remaining empty count
|
||||
if empty_count > 0:
|
||||
fen_string += str(empty_count)
|
||||
|
||||
# Add row separator (except for the last row)
|
||||
if y < height - 1:
|
||||
fen_string += "/"
|
||||
return {
|
||||
"fen": fen_string,
|
||||
"start": str(start_x) + "-"+ str(start_y),
|
||||
"end": str(end_x) + "-"+ str(end_y)
|
||||
}
|
||||
|
||||
# Recursive function to carve out the maze
|
||||
func _carve_maze(maze, x, y, width, height, rng):
|
||||
# Mark the current cell as a path
|
||||
maze[y][x] = " "
|
||||
|
||||
# Define the four possible directions (up, right, down, left)
|
||||
var directions = [[0, -2], [2, 0], [0, 2], [-2, 0]]
|
||||
|
||||
# Shuffle directions for randomness
|
||||
directions.shuffle()
|
||||
|
||||
# Try each direction
|
||||
for dir in directions:
|
||||
var nx = x + dir[0]
|
||||
var ny = y + dir[1]
|
||||
|
||||
# Check if the new position is valid and unvisited
|
||||
if nx > 0 and nx < width-1 and ny > 0 and ny < height-1 and maze[ny][nx] == "*":
|
||||
# Carve a path between the current cell and the new cell
|
||||
maze[y + dir[1]/2][x + dir[0]/2] = " "
|
||||
|
||||
# Recursively carve from the new cell
|
||||
_carve_maze(maze, nx, ny, width, height, rng)
|
||||
|
|
|
|||
|
|
@ -304,6 +304,15 @@ func _on_map_node_selected(node_data):
|
|||
mapScreen.visible = false
|
||||
back_to_map = true
|
||||
_on_start_game_pressed(node_data)
|
||||
elif node_data.type == Utils.RoomType.EVENT:
|
||||
if gameMenuScreen:
|
||||
gameMenuScreen.visible = false
|
||||
if deckManagerScreen:
|
||||
deckManagerScreen.visible = false
|
||||
if mapScreen:
|
||||
mapScreen.visible = false
|
||||
back_to_map = true
|
||||
_on_start_game_pressed(node_data)
|
||||
|
||||
func _on_node_completed(options):
|
||||
var node_data = options.node
|
||||
|
|
|
|||
|
|
@ -31,9 +31,11 @@ func _init(game: ChessGame):
|
|||
chess_game.connect("game_initialized", Callable(self, "_on_game_initialized"))
|
||||
|
||||
func _on_game_initialized():
|
||||
reset_conditions()
|
||||
# reset_conditions()
|
||||
print("_on_game_initialized")
|
||||
|
||||
func reset_conditions():
|
||||
print("reset_conditions")
|
||||
captured_pieces.clear()
|
||||
turn_count = 0
|
||||
target_tiles.clear()
|
||||
|
|
@ -81,12 +83,11 @@ func highlight_target_tiles():
|
|||
func set_win_condition(type: Utils.WinConditionType, data: Dictionary = {}):
|
||||
win_condition = type
|
||||
win_condition_data = data
|
||||
reset_conditions()
|
||||
|
||||
func set_loss_condition(type: Utils.LossConditionType, data: Dictionary = {}):
|
||||
loss_condition = type
|
||||
loss_condition_data = data
|
||||
reset_conditions()
|
||||
# reset_conditions()
|
||||
|
||||
func _on_turn_changed():
|
||||
turn_count += 1
|
||||
|
|
@ -112,7 +113,7 @@ func _on_turn_changed():
|
|||
check_conditions()
|
||||
|
||||
func on_piece_captured(piece):
|
||||
print("on_piece_captured ISEnemy ", piece)
|
||||
# print("on_piece_captured ISEnemy ", piece)
|
||||
var is_enemy_piece = piece.Item_Color == (1 if chess_game.Turn == 1 else 0)
|
||||
print("on_piece_captured ISEnemy ", is_enemy_piece)
|
||||
if is_enemy_piece:
|
||||
|
|
@ -220,14 +221,17 @@ func count_enemy_pieces() -> int:
|
|||
# Helper methods for game integration
|
||||
|
||||
func load_condition_from_metadata(metadata: Dictionary):
|
||||
# print("load_condition_from_metadata ", metadata)
|
||||
if metadata.has("win_condition"):
|
||||
match metadata["win_condition"]:
|
||||
Utils.WinConditionType.CAPTURE_UNIT:
|
||||
set_win_condition(Utils.WinConditionType.CAPTURE_UNIT, {"unit": "King"})
|
||||
Utils.WinConditionType.TILE_REACHED:
|
||||
# Get target tiles from metadata if available
|
||||
var target_tiles = metadata.get("target_tiles", [])
|
||||
set_win_condition(Utils.WinConditionType.TILE_REACHED, {"target_tiles": target_tiles, "unit": metadata.get("target_unit", "")})
|
||||
|
||||
target_tiles = metadata.get("win_target", [])
|
||||
# print("load_condition_from_metadata ", " target_tiles ", target_tiles)
|
||||
set_win_condition(Utils.WinConditionType.TILE_REACHED, {"target_tiles": target_tiles, "unit": metadata.get("win_target_unit", "")})
|
||||
Utils.WinConditionType.BOARD_CLEARED:
|
||||
set_win_condition(Utils.WinConditionType.BOARD_CLEARED)
|
||||
Utils.WinConditionType.TURN_NUMBER:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ func enter(_previous: String, data := {}) -> void:
|
|||
|
||||
if "endCondition" in data:
|
||||
finished.emit(Constants.ROUND_END)
|
||||
elif game.currentPlayer == game.WHITE:
|
||||
elif game.currentPlayer == game.WHITE and game.has_opponent:
|
||||
finished.emit(Constants.BLACK_TURN)
|
||||
else:
|
||||
finished.emit(Constants.WHITE_TURN)
|
||||
|
|
@ -20,6 +20,7 @@ func enter(_previous: String, _data := {}) -> void:
|
|||
func check_win_conditions() -> bool:
|
||||
match game.winConditionManager.win_condition:
|
||||
Utils.WinConditionType.CAPTURE_UNIT:
|
||||
print("check_win_conditions ", "Utils.WinConditionType.CAPTURE_UNIT")
|
||||
# Directly check if king/target unit was captured
|
||||
var target_unit = game.winConditionManager.win_condition_data.get("unit", "King")
|
||||
|
||||
|
|
@ -35,6 +36,7 @@ func check_win_conditions() -> bool:
|
|||
return true
|
||||
game.captured_pieces_this_turn = []
|
||||
Utils.WinConditionType.BOARD_CLEARED:
|
||||
print("check_win_conditions ", "Utils.WinConditionType.BOARD_CLEARED")
|
||||
var remaining_enemy_pieces = game.winConditionManager.count_enemy_pieces()
|
||||
if remaining_enemy_pieces <= 0:
|
||||
var condition_data = {
|
||||
|
|
@ -46,6 +48,7 @@ func check_win_conditions() -> bool:
|
|||
return true
|
||||
|
||||
Utils.WinConditionType.TURN_NUMBER:
|
||||
print("check_win_conditions ", "Utils.WinConditionType.TURN_NUMBER")
|
||||
var target_turn = game.winConditionManager.win_condition_data.get("target_turn", 0)
|
||||
if game.winConditionManager.turn_count >= target_turn:
|
||||
var condition_data = {
|
||||
|
|
@ -57,15 +60,18 @@ func check_win_conditions() -> bool:
|
|||
return true
|
||||
|
||||
Utils.WinConditionType.TILE_REACHED:
|
||||
var target_tiles = game.winConditionManager.target_tiles
|
||||
var required_unit = game.winConditionManager.win_condition_data.get("unit", "")
|
||||
print("check_win_conditions ", "Utils.WinConditionType.TILE_REACHED", game.winConditionManager.win_condition_data)
|
||||
var target_tiles = game.winConditionManager.win_condition_data.get("target_tiles", [])
|
||||
var required_unit = game.winConditionManager.win_condition_data.get("unit", "King")
|
||||
var all_targets_reached = true
|
||||
# print("check_win_conditions ", required_unit, " ", target_tiles)
|
||||
|
||||
for tile_loc in target_tiles:
|
||||
if !game.is_tile_reached(tile_loc, required_unit):
|
||||
all_targets_reached = false
|
||||
break
|
||||
|
||||
# print("all_targets_reached ", all_targets_reached,)
|
||||
if all_targets_reached and target_tiles.size() > 0:
|
||||
var condition_data = {
|
||||
"type": Utils.WinConditionType.TILE_REACHED,
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ func check_kingside_castle(board_flow, x: int, y: int) -> bool:
|
|||
if !is_valid_cell(board_flow, rook_pos):
|
||||
return false
|
||||
var rook_container = board_flow.get_node(rook_pos) as PieceContainer
|
||||
if !rook_container.has_piece():
|
||||
return false
|
||||
var rook = rook_container.get_piece()
|
||||
return rook.name == "Rook" && rook.Castling && rook.Item_Color == self.Item_Color
|
||||
|
||||
|
|
@ -88,5 +90,7 @@ func check_queenside_castle(board_flow, x: int, y: int) -> bool:
|
|||
return false
|
||||
|
||||
var rook_container = board_flow.get_node(rook_pos) as PieceContainer
|
||||
if !rook_container.has_piece():
|
||||
return false
|
||||
var rook = rook_container.get_piece()
|
||||
return rook.name == "Rook" && rook.Castling && rook.Item_Color == self.Item_Color
|
||||
|
|
|
|||
Loading…
Reference in a new issue