]> Untitled Git - axy/ft/pacman.git/commitdiff
Cleanup and run conditions
authorAxy <gilliardmarthey.axel@gmail.com>
Sun, 27 Sep 2026 21:36:45 +0000 (23:36 +0200)
committerAxy <gilliardmarthey.axel@gmail.com>
Sun, 27 Sep 2026 21:36:45 +0000 (23:36 +0200)
src/pacman/ecs/schedule.py
src/pacman/ecs/world.py

index d9742f46a57eb4162406b1a8017743d30a102031..58fe9b5c163723d1c032d1d2f624d9ba4910d355 100644 (file)
@@ -72,6 +72,7 @@ class Schedule[T]:
     def __init__(self) -> None:
         self._dag: DAG[T | DAGLabel | None] = DAG()
         self._group_appartenance: dict[T | SystemSet, set[SystemSet]] = {}
+        self._run_predicates: dict[T | SystemSet, Callable[[], bool]] = {}
 
     def add_ordering(
         self,
@@ -79,6 +80,7 @@ class Schedule[T]:
         pre: Iterable[T | SystemSet],
         post: Iterable[T | SystemSet],
         group: Iterable[SystemSet],
+        cond: Callable[[], bool] | None,
     ) -> None:
         def get_pre(e: T | SystemSet) -> T | DAGLabel:
             if isinstance(e, SystemSet):
@@ -102,19 +104,25 @@ class Schedule[T]:
                 self._dag.add_edge(get_pre(e), get_pre(item))
                 self._dag.add_edge(get_post(item), get_post(e))
                 self._group_appartenance[item].add(e)
+            if cond is not None:
+                if (prev := self._run_predicates.get(item)) is not None:
+                    self._run_predicates[item] = lambda: prev() and cond()
+                else:
+                    self._run_predicates[item] = cond
 
-    def traverse(
-        self, run_cond: Callable[[T | SystemSet], bool]
-    ) -> Generator[T]:
+    def traverse(self) -> Generator[T]:
         cond_cache: dict[T | SystemSet, bool] = {}
 
         def should_run(val: T | SystemSet) -> bool:
             if val in cond_cache:
                 return cond_cache[val]
-            res = all(
-                should_run(parent)
-                for parent in self._group_appartenance.get(val, set())
-            ) and run_cond(val)
+            res = (
+                all(
+                    should_run(parent)
+                    for parent in self._group_appartenance.get(val, set())
+                )
+                and self._run_predicates.get(val, lambda: True)()
+            )
             cond_cache[val] = res
             return res
 
index b173484df4ee0b0b946eb8afbf7ce4695373c2ba..f81f7680a45aa3e2642b237b1f0e5eefc4bdbea4 100644 (file)
@@ -823,7 +823,7 @@ class World(FromWorld):
 
     def add_raw_system[T](
         self,
-        system: Callable[..., T],
+        system: System[T],
         default: Callable[[], T] = _system_failed,
     ) -> RawSystem[T]:
         extractors = self._sys_extractors(system)
@@ -853,7 +853,7 @@ class World(FromWorld):
     def tick(self, schedule: ScheduleLabel) -> None:
         if schedule not in self._schedules:
             return
-        for system in self._schedules[schedule].traverse(lambda _: True):
+        for system in self._schedules[schedule].traverse():
             system()
 
     def run(
@@ -868,13 +868,10 @@ class World(FromWorld):
         self,
         schedule: ScheduleLabel,
         *systems: "System | Systems",
-        sets: set[SystemSet] | None = None,
-    ) -> "World":
-        if sets is None:
-            sets = set()
+    ) -> Self:
         if schedule not in self._schedules:
             self._schedules[schedule] = Schedule()
-        Systems(*systems).in_set(*sets)._apply(self, self._schedules[schedule])
+        Systems(*systems)._apply(self, self._schedules[schedule])
         return self
 
     def with_hook[T: Component](
@@ -882,7 +879,7 @@ class World(FromWorld):
         cycle: Literal["insert", "remove"],
         ty: type[T],
         hook: ComponentHook[T],
-    ) -> "World":
+    ) -> Self:
         comp_id = self.component_id(resolve_type_aliases(ty))
         hooks = cast(ComponentHooks[T], self._components_cache[comp_id][1])
         sys = self.add_system(hook, default=lambda _: None)
@@ -893,7 +890,7 @@ class World(FromWorld):
                 hooks.add_remove(sys)
         return self
 
-    def with_plugins(self, *plugins: Plugin) -> "World":
+    def with_plugins(self, *plugins: Plugin) -> Self:
         for plugin in plugins:
             if isinstance(plugin, tuple):
                 self.with_plugins(plugin)
@@ -915,23 +912,28 @@ class Systems:
         self._pre: list[System | SystemSet] = []
         self._post: list[System | SystemSet] = []
         self._in_set: list[SystemSet] = []
+        self._conds: list[System[bool]] = []
 
-    def chain(self) -> "Systems":
+    def chain(self) -> Self:
         self._chain = True
         return self
 
-    def after(self, *systems: System | SystemSet) -> "Systems":
+    def after(self, *systems: System | SystemSet) -> Self:
         self._pre.extend(systems)
         return self
 
-    def before(self, *systems: System | SystemSet) -> "Systems":
+    def before(self, *systems: System | SystemSet) -> Self:
         self._post.extend(systems)
         return self
 
-    def in_set(self, *sets: SystemSet) -> "Systems":
+    def in_set(self, *sets: SystemSet) -> Self:
         self._in_set.extend(sets)
         return self
 
+    def run_if(self, *conds: System[bool]) -> Self:
+        self._conds.extend(conds)
+        return self
+
     def _apply(self, world: World, sched: Schedule[RawSystem]) -> SystemSet:
         global _order_groups
         _order_groups += 1
@@ -946,14 +948,18 @@ class Systems:
             )
             for e in self._systems
         )
-        sched.add_ordering((label,), self._pre, self._post, self._in_set)
+        for cond in self._conds:
+            sched.add_ordering(
+                (label,), (), (), (), world.add_raw_system(cond, lambda: False)
+            )
+        sched.add_ordering((label,), self._pre, self._post, self._in_set, None)
         if self._chain:
             prev: tuple[SystemSet | RawSystem] | tuple[()] = ()
             for system in systems:
-                sched.add_ordering((system,), prev, (), (label,))
+                sched.add_ordering((system,), prev, (), (label,), None)
                 prev = (system,)
         else:
-            sched.add_ordering(systems, (), (), (label,))
+            sched.add_ordering(systems, (), (), (label,), None)
         return label