summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--HexBoard.gd41
-rw-r--r--Map.gd16
-rw-r--r--Piece.gd20
-rw-r--r--README.md4
-rw-r--r--Tile.gd13
-rw-r--r--Unit.gd14
-rw-r--r--godot/Piece.pngbin0 -> 1209 bytes
-rw-r--r--project.godot14
8 files changed, 112 insertions, 10 deletions
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
--- /dev/null
+++ b/godot/Piece.png
Binary files 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]