harness.pyΒΆ

Part of Q1K3.

 1"""Smoke harness for Q1K3: starts the game from the menu and drives the player.
 2
 3Runs headless through ``SceneRunner``, and clicks / types through
 4``InputSimulator`` rather than poking node state, so the real input path is the
 5thing under test.
 6"""
 7
 8from __future__ import annotations
 9
10import sys
11from pathlib import Path
12
13_PORT_DIR = Path(__file__).parent
14if str(_PORT_DIR) not in sys.path:
15    sys.path.insert(0, str(_PORT_DIR))
16
17from nodes.root import Q1K3Root  # noqa: E402
18
19from simvx.core import Button, Key  # noqa: E402
20from simvx.core.testing import InputSimulator, SceneRunner  # noqa: E402
21
22
23def _first_button(node) -> Button | None:
24    if isinstance(node, Button):
25        return node
26    for child in node.children:
27        found = _first_button(child)
28        if found is not None:
29            return found
30    return None
31
32
33def main() -> int:
34    runner = SceneRunner(screen_size=(1280, 720))
35    runner.load(Q1K3Root())
36    sim = InputSimulator(runner.tree)
37    runner.advance_frames(2)
38
39    root = runner.root
40    assert isinstance(root, Q1K3Root)
41    if not runner.tree.paused or not root.menu.visible:
42        print("FAIL: the title screen should be up and the tree paused at boot")
43        return 1
44
45    play = _first_button(root.menu)
46    if play is None:
47        print("FAIL: no start button on the title screen")
48        return 1
49    x, y, w, h = play.get_global_rect()
50    sim.click((x + w / 2, y + h / 2))
51    runner.advance_frames(2)
52
53    if runner.tree.paused or root.player is None:
54        print("FAIL: the start button did not start the game")
55        return 1
56
57    start = root.player.p
58    sim.press_key(Key.W)
59    runner.advance_frames(30)
60    sim.release_key(Key.W)
61    if (root.player.p - start).length() < 1.0:
62        print("FAIL: holding forward did not move the player")
63        return 1
64
65    sim.tap_key(Key.ESCAPE)
66    runner.advance_frames(2)
67    if not runner.tree.paused or not root.menu.visible:
68        print("FAIL: Escape did not return to the title screen")
69        return 1
70
71    print(f"OK: started from the menu; player at {root.player.p}; entities={len(root._entities)}")
72    return 0
73
74
75if __name__ == "__main__":
76    sys.exit(main())