Metadata-Version: 2.4
Name: RampantTrackGeneration
Version: 0.0.2.0.1
Summary: Rampant on the Tracks's Track generation logic, leveraging Voronout and optimized for a web service.
Project-URL: Homepage, https://github.com/jpshankar/RampantTrackGeneration
Project-URL: Issues, https://github.com/jpshankar/RampantTrackGeneration/issues
Author-email: Javas Shankar <javasshankar@gmail.com>
License-Expression: MIT
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.13
Requires-Dist: aggdraw
Requires-Dist: flask
Requires-Dist: numpy
Requires-Dist: pillow
Requires-Dist: rustworkx
Requires-Dist: shapely
Requires-Dist: voronout
Description-Content-Type: text/markdown

# RampantTrackGeneration is..

.. the Track generation logic for [Rampant on the Tracks](https://jpshh.com/rott/pitch).

The logic is invoked by calling 

```Python
@staticmethod
    def generate_track(
        diagram_width: int,
        diagram_height: int,
        num_diagram_regions: int,
        angle_min_quantile: float,
        length_min_quantile: float,
        num_path_nodes_min_quantile: float,
        max_fuel_cost: float, 
        min_cycle_period: int,
        max_cycle_period: int,
        max_length_travel_duration_seconds: int,
        stop_radius: int
    ) -> Track:
```

in `TrackGenerator`.

`Track`

```Python
@dataclass(frozen=True)
class Track:
    nodes: dict[uuid4, Point]
    edges: dict[uuid4, EdgeVertexInfo]

    start_node_id: uuid4
    destination_node_id: uuid4

    start_destination_path_edges: tuple[uuid4]
    
    node_info: dict[uuid4, NodeInfo]
    edge_info: dict[uuid4, EdgeInfo]
```

describes a set of `edges`, each a connection between two `Point`s. `nodes` are the `Point`s.

`generate_track` derives the `Track` from a randomly generated Voronoi diagram. 

It preserves the organic appeal of the diagram's shape - unevenly spaced points connected by edges of varying length - and goes on to enhance that by 

* removing all edges shorter than `diagram_edge_min_acceptable_length` and/or contributing to an angle less than `diagram_edge_min_acceptable_angle`
* examining the set of subgraphs `S` with length `i` created by edge removal and connecting them sequentially and looping over them, connecting `S[i]` to `S[i + 1]`
* for each edge `A` and `B` that intersects at a point `j`, splitting both edges on `j` so that there are four edges
* calculating edge fuel costs, number of stops, and " junction block cycle " period
* determining `start_node_id` and `destination_node_id`
* constructing and returning a `Track` from the information so far

The diagram is generated with [Voronout](https://pypi.org/project/Voronout/) and modeled with [rustworkX](https://www.rustworkx.org/).

`node_info` contains further information about nodes

```Python
@dataclass(frozen=True)
class NodeInfo:
    num_steps_to_destination: int
    num_seconds_block_cycle: int
```

for game logic - `num_steps_to_destination` tells you how many edges away it is from `destination_node_id`'s node, while `num_seconds_block_cycle` is used in the " junction block cycle " mechanic.

`edge_info` is likewise for edges

```Python
@dataclass(frozen=True)
class EdgeInfo:
    edge_traversal_fuel_cost: float
    edge_traversal_duration: float

    edge_stop_info: tuple[StopInfo]

    edge_image_default_b64: str
    edge_image_focused_b64: str
```

`edge_traversal_fuel_cost` is the fuel spent in-game by a `Walker` traversing the edge - `edge_traversal_duration` is the time it takes to do so in seconds, used for animation purposes.

`edge_image_*_b64` are the edge's graphical representations in its default/focused states, stored in `base64`. The game converts them into sprites to show on-screen.

```
@dataclass(frozen=True)
class StopInfo:
    stop_point: Point
    stop_id: uuid4

    stop_fuel: float
```

`stop_fuel` is how much fuel a Walker can draw from the stop.
