From ed517bbfd0e10abd9bc571131188061a7221d103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= Date: Fri, 10 Jul 2020 14:01:43 +0200 Subject: implement possible_moves() --- HexBoard.gd | 41 +++++++++++++++++++++++++++++++++++++++++ Map.gd | 16 +++++++++++----- Piece.gd | 20 ++++++++++++++++++++ README.md | 4 ++-- Tile.gd | 13 +++++++++++-- Unit.gd | 14 ++++++++++++++ godot/Piece.png | Bin 0 -> 1209 bytes project.godot | 14 +++++++++++++- 8 files changed, 112 insertions(+), 10 deletions(-) create mode 100644 Piece.gd create mode 100644 Unit.gd create mode 100644 godot/Piece.png diff --git a/HexBoard.gd b/HexBoard.gd index aa5d8e9..c44ff7f 100644 --- a/HexBoard.gd +++ b/HexBoard.gd @@ -22,6 +22,8 @@ var tl : int # num of hexes in 2 consecutives rows var tile_factory_fct : FuncRef var angles : Dictionary var adjacents : Array +var search_count : int +var stack : Array func configure(cols : int, rows : int, side : float, v0 : Vector2, vertical : bool) -> void: v = vertical @@ -39,6 +41,7 @@ func configure(cols : int, rows : int, side : float, v0 : Vector2, vertical : bo bt = v0 cr = Vector2(rows, cols) tl = (2 * int(cr.x) - 1) + search_count = 0 angles = {} if v: angles[Orientation.E] = 0 @@ -360,3 +363,41 @@ func compute_contact(from : Vector2, to : Vector2, o : int, t : Vector2, line : var x : float = t.x + (dh if (o == Orientation.NW || o == Orientation.SW) else -dh) var y : float = t.y + (dw if (o == Orientation.SE || o == Orientation.SW) else -dw) return Vector2(x, y) + +func possible_moves(piece : Piece, from : Tile, tiles : Array) -> int: + tiles.clear() + search_count += 1 + from.acc = piece.get_mp() + from.parent = null + from.search_count = search_count + if from.acc <= 0 or not is_on_map(from.coords): return 0 + var road_march_bonus : int = piece.road_march_bonus() + from.road_march = road_march_bonus > 0 + stack.push_back(from) + while(not stack.empty()): + var src : Tile = stack.pop_back() + if (src.acc + (road_march_bonus if src.road_march else 0)) <= 0: continue + # warning-ignore:return_value_discarded + build_adjacents(src.coords) + for dst in adjacents: + if not dst.on_board: continue + var a : int = angle(src, dst) + var cost : int = piece.move_cost(src, dst, a) + if (cost == -1): continue # impracticable + var r : int = src.acc - cost + var rm : bool = src.road_march and src.has_road(a) + # not enough MP even with RM, maybe first move allowed + if ((r + (road_march_bonus if rm else 0)) < 0 and not (src == from and piece.at_least_one_tile())): continue + if dst.search_count != search_count: + dst.search_count = search_count + dst.acc = r + dst.parent = src + dst.road_march = rm + stack.push_back(dst) + tiles.append(dst) + elif (r > dst.acc or (rm and (r + road_march_bonus > dst.acc + (road_march_bonus if dst.roadMarch else 0)))): + dst.acc = r + dst.parent = src + dst.road_march = rm + stack.push_back(dst) + return tiles.size() diff --git a/Map.gd b/Map.gd index 76edb86..157aaca 100644 --- a/Map.gd +++ b/Map.gd @@ -7,6 +7,7 @@ const MAPH : String = "res://assets/map-h.png" const MAPV : String = "res://assets/map-v.png" const BLOCK : String = "res://assets/block.png" const BLACK : String = "res://assets/black.png" +const MOVE : String = "res://assets/move.png" const GREEN : String = "res://assets/green.png" const TREE : String = "res://assets/tree.png" const CITY : String = "res://assets/city.png" @@ -21,6 +22,8 @@ var hex_rotation : int var p0 : Vector2 var p1 : Vector2 var los : Array +var move : Array +var unit : Unit func _ready(): board = HexBoard.new() @@ -29,6 +32,7 @@ func _ready(): drag = null hexes = {} los = [] + unit = Unit.new() func reset() -> void: hexes.clear() @@ -38,7 +42,7 @@ func get_tile(coords : Vector2, k : int) -> Tile: if hexes.has(k): return hexes[k] var hex : Hex = Hex.new() hex.rotation_degrees = hex_rotation - hex.configure(board.center_of(coords), coords, [GREEN, BLACK, CITY, TREE, MOUNT]) + hex.configure(board.center_of(coords), coords, [GREEN, BLACK, CITY, TREE, MOUNT, MOVE]) hexes[k] = hex $Hexes.add_child(hex) return hex @@ -112,9 +116,11 @@ func notify(hex : Hex, pos : Vector2, coords : Vector2) -> void: else: emit_signal("hex_touched", pos, hex, -1) func update_los() -> void: - for hex in los: - hex.show_los(false) + for hex in los: hex.show_los(false) var ct : Vector2 = board.line_of_sight(p0, p1, los) $Los.setup($Tank.position, $Target.position, ct) - for hex in los: - hex.show_los(true) + for hex in los: hex.show_los(true) + for hex in move: hex.show_move(false) + # warning-ignore:return_value_discarded + board.possible_moves(unit, board.get_tile(p0), move) + for hex in move: hex.show_move(true) diff --git a/Piece.gd b/Piece.gd new file mode 100644 index 0000000..7564d0f --- /dev/null +++ b/Piece.gd @@ -0,0 +1,20 @@ +#warning-ignore-all:unused_argument +extends Node2D + +class_name Piece, "res://godot/Piece.png" + +func get_mp() -> int: + print("Piece#get_mp() must be overriden in a subclass") + return 0 + +func road_march_bonus() -> int: + print("Piece#road_march_bonus() must be overriden in a subclass") + return 0 + +func move_cost(src : Tile, dst : Tile, a : int) -> int: + print("Piece#move_cost() must be overriden in a subclass") + return 1 + +func at_least_one_tile() -> bool: + print("Piece#at_least_one_tile() must be overriden in a subclass") + return true diff --git a/README.md b/README.md index da97ecd..129bdc6 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ base map made with [gimp](https://www.gimp.org) and my plugin [hexmap](https://g - [x] Distance - [x] Adjacents - - [x] Line Of Sight - - [ ] Reachable Tiles ::: BFS + - [x] 3D Line Of Sight + - [x] Reachable Tiles ::: BFS - [ ] Shortest Path ::: A* - [ ] Range Of Influence (LOS - Fire Power) - [ ] Battle lines (Kruskal + farthest apart units are the flank units) diff --git a/Tile.gd b/Tile.gd index ec9b52c..03f10be 100644 --- a/Tile.gd +++ b/Tile.gd @@ -7,6 +7,11 @@ var coords : Vector2 var blocked : bool var on_board : bool = false +var acc : int +var parent : Tile +var road_march : bool +var search_count : int + func configure(p : Vector2, c: Vector2, o :Array) -> void: position = p coords = c @@ -18,13 +23,17 @@ func configure(p : Vector2, c: Vector2, o :Array) -> void: add_child(s) visible = false +func has_road(a) -> bool: + # FIXME + return false + func block_los(from : Tile, to : Tile, d : float, dt : float) -> bool: + print("Tile#block_los() must be overriden in a subclass") return false func enable_overlay(i :int, v : bool) -> void: get_child(i).visible = v - if v: - visible = true + if v: visible = true else : visible = false for o in get_children(): diff --git a/Unit.gd b/Unit.gd new file mode 100644 index 0000000..2de5ed6 --- /dev/null +++ b/Unit.gd @@ -0,0 +1,14 @@ +#warning-ignore-all:unused_argument +extends Piece + +class_name Unit, "res://godot/Piece.png" + +func get_mp() -> int: + return 3 + +func road_march_bonus() -> int: + return 3 + +func move_cost(src : Tile, dst : Tile, a : int) -> int: + print("from %d %d -> %d %d : %d" % [src.coords.x,src.coords.y,dst.coords.x,dst.coords.y,a]) + return dst.cost() diff --git a/godot/Piece.png b/godot/Piece.png new file mode 100644 index 0000000..add6a52 Binary files /dev/null and b/godot/Piece.png differ diff --git a/project.godot b/project.godot index f00effb..03a9823 100644 --- a/project.godot +++ b/project.godot @@ -20,14 +20,26 @@ _global_script_classes=[ { "path": "res://HexBoard.gd" }, { "base": "Node2D", +"class": "Piece", +"language": "GDScript", +"path": "res://Piece.gd" +}, { +"base": "Node2D", "class": "Tile", "language": "GDScript", "path": "res://Tile.gd" +}, { +"base": "Piece", +"class": "Unit", +"language": "GDScript", +"path": "res://Unit.gd" } ] _global_script_class_icons={ "Hex": "res://godot/Tile.png", "HexBoard": "res://godot/HexBoard.png", -"Tile": "res://godot/Tile.png" +"Piece": "res://godot/Piece.png", +"Tile": "res://godot/Tile.png", +"Unit": "res://godot/Piece.png" } [application] -- cgit v1.1-2-g2b99