Pathfinding initial implementation [2 errors]
This commit is contained in:
15
src/common/utils.odin
Normal file
15
src/common/utils.odin
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
// Generic contains function for an (dynamic) array
|
||||||
|
list_contains :: proc(list: []$T, element: T) -> bool {
|
||||||
|
for el in list do if el == element do return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inserts element into the list after asserting that element is not already within
|
||||||
|
insert_if_not_exists :: proc(list: ^[]$T, element: T) {
|
||||||
|
if list_contains(list, element) do return
|
||||||
|
|
||||||
|
append(list, element)
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
|
import "core:math/rand"
|
||||||
|
|
||||||
import "common"
|
import "common"
|
||||||
import inf "infrastructure"
|
import inf "infrastructure"
|
||||||
@@ -99,5 +100,19 @@ delete_entity :: proc(self: ^Simulator, entity_index: u32, type: common.Entity)
|
|||||||
|
|
||||||
// Returns a random node that has no cars on it
|
// Returns a random node that has no cars on it
|
||||||
get_free_node :: proc(self: ^Simulator) -> u32 {
|
get_free_node :: proc(self: ^Simulator) -> u32 {
|
||||||
|
car_occupied_nodes: [dynamic]u32
|
||||||
|
|
||||||
|
for car in self.cars {
|
||||||
|
node, ok := car.node_pos.?
|
||||||
|
if !ok do continue
|
||||||
|
|
||||||
|
if common.list_contains(car_occupied_nodes[:], node) do continue
|
||||||
|
append(&car_occupied_nodes, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
node := rand.uint32_max(u32(len(self.nodes)))
|
||||||
|
|
||||||
|
if !common.list_contains(car_occupied_nodes[:], node) do return node
|
||||||
|
}
|
||||||
}
|
}
|
||||||
43
src/pathfinding.odin
Normal file
43
src/pathfinding.odin
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "common"
|
||||||
|
import inf "infrastructure"
|
||||||
|
|
||||||
|
// Returns path to destination node => road => node
|
||||||
|
get_path_to_destination :: proc(self: ^Simulator, source: u32, destination: u32) -> []u32 {
|
||||||
|
source_node := self.nodes[source]
|
||||||
|
destination_node := self.nodes[destination]
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns if path is reachable from node => destination
|
||||||
|
get_destination_reachable :: proc(self: ^Simulator, node_to_search: u32, destination: u32, nodes_to_ignore: ^[]u32) -> bool {
|
||||||
|
if !self.nodes[node_to_search].enabled || common.list_contains(nodes_to_ignore[:], node_to_search) do return false
|
||||||
|
append(nodes_to_ignore, node_to_search)
|
||||||
|
|
||||||
|
if node_to_search == destination do return true
|
||||||
|
for node in get_neighbouring_nodes(self, node_to_search) {
|
||||||
|
if get_destination_reachable(self, node, destination, nodes_to_ignore) do return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private="file")
|
||||||
|
get_neighbouring_nodes :: proc(self: ^Simulator, node_index: u32) -> []u32 {
|
||||||
|
node := self.nodes[node_index]
|
||||||
|
neighbour_nodes := make([dynamic]u32, 0, len(node.roads))
|
||||||
|
|
||||||
|
for road_index in node.roads {
|
||||||
|
road := self.roads[road_index]
|
||||||
|
|
||||||
|
// We pick the node that is not the original node with which we reached the node
|
||||||
|
// But rather the other node, on the end
|
||||||
|
next_node := road.nodes[0] == node_index ? road.nodes[1] : road.nodes[0]
|
||||||
|
|
||||||
|
if !common.list_contains(neighbour_nodes[:], next_node) do append(&neighbour_nodes, next_node)
|
||||||
|
}
|
||||||
|
|
||||||
|
return neighbour_nodes[:]
|
||||||
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
import inf "../infrastructure"
|
|
||||||
|
|
||||||
get_path_to_destination :: proc(source: u32, destination: u32, nodes: []inf.Node) {
|
|
||||||
source_node := nodes[source]
|
|
||||||
destination_node := nodes[destination]
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -19,32 +19,31 @@ Car :: struct {
|
|||||||
// Car's destination node
|
// Car's destination node
|
||||||
destination: Maybe(u32),
|
destination: Maybe(u32),
|
||||||
// Tracks on which node car has been last
|
// Tracks on which node car has been last
|
||||||
node_pos: u32,
|
//
|
||||||
|
// if null car is not on node
|
||||||
|
node_pos: Maybe(u32),
|
||||||
|
// if null car is not on road
|
||||||
road_pos: Maybe(u32),
|
road_pos: Maybe(u32),
|
||||||
|
// tracks absolute pos
|
||||||
actual_pos: rl.Vector2,
|
actual_pos: rl.Vector2,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
car_init :: proc(nodes: []inf.Node) -> Car {
|
car_init :: proc(node: u32, nodes: []inf.Node) -> Car {
|
||||||
rand_origin := rand.uint32_max(nodes_len)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fuel_level = common.FUEL_MAX,
|
fuel_level = common.FUEL_MAX,
|
||||||
max_speed = common.CAR_MAX_SPEED,
|
max_speed = common.CAR_MAX_SPEED,
|
||||||
origin = rand_origin,
|
origin = node,
|
||||||
node_pos = rand_origin,
|
node_pos = node,
|
||||||
actual_pos =
|
actual_pos = nodes[node].pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets a (valid) route for the car
|
// Sets a (valid) route for the car
|
||||||
//
|
//
|
||||||
// Does NOT guarantee the route is reachable (TODO?)
|
// Does NOT guarantee the route is reachable (TODO!)
|
||||||
car_set_route :: proc(self: ^Car, nodes_len: u32) {
|
car_set_route :: proc(self: ^Car, nodes_len: u32) {
|
||||||
for self.origin == self.destination {
|
for self.origin == self.destination do self.destination = rand.uint32_max(nodes_len)
|
||||||
self.destination = rand.uint32_max(nodes_len)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates (origin and destination) node reference
|
// Updates (origin and destination) node reference
|
||||||
|
|||||||
Reference in New Issue
Block a user