File size: 2,022 Bytes
d2e6f94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
from __future__ import annotations

from config import load_settings
from .models import LegalMove
from .storage import read_json


def load_game_graph() -> dict:
    settings = load_settings()
    return read_json(settings.game_graph_path)


def all_junction_ids() -> list[int]:
    graph = load_game_graph()
    return sorted(int(node["id"]) for node in graph.get("nodes", []))


def adjacent_junctions(junction_id: int) -> list[int]:
    graph = load_game_graph()
    adjacency = graph.get("adjacency", {}).get(str(junction_id), [])
    return sorted({int(item["destination"]) for item in adjacency})


def legal_moves_from(junction_id: int, blocked_edges: list[dict] | None = None) -> list[LegalMove]:
    graph = load_game_graph()
    blocked_edges = blocked_edges or []
    moves: list[LegalMove] = []

    for edge in graph.get("edges", []):
        source = int(edge["source"])
        target = int(edge["target"])
        if junction_id not in (source, target):
            continue

        destination = target if source == junction_id else source
        for mode in edge.get("modes", []):
            blocked = _is_blocked(junction_id, destination, mode, blocked_edges)
            moves.append(LegalMove(destination=destination, via=(junction_id, destination), mode=mode, blocked=blocked))

    return sorted(moves, key=lambda move: (move.destination, move.mode))


def _is_blocked(source: int, target: int, mode: str, blocks: list[dict]) -> bool:
    for block in blocks:
        block_type = block.get("block_type")
        if block_type == "mode_block" and block.get("mode") == mode:
            return True
        if block_type == "junction_block" and block.get("junction_id") in (source, target):
            return True
        if block_type == "edge_block":
            same_edge = {block.get("from_junction"), block.get("to_junction")} == {source, target}
            same_mode = block.get("mode") in (None, mode)
            if same_edge and same_mode:
                return True
    return False