File size: 2,412 Bytes
9fca766
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
"""Animation kit: deterministic pieces, and the bell theater resolving."""

from __future__ import annotations

import random

from scrypt.ui import fx


def test_reduced_motion_reads_env(monkeypatch):
    monkeypatch.setenv("SCRYPT_REDUCED_MOTION", "1")
    assert fx.reduced_motion()
    monkeypatch.setenv("SCRYPT_REDUCED_MOTION", "0")
    assert not fx.reduced_motion()
    monkeypatch.delenv("SCRYPT_REDUCED_MOTION")
    assert not fx.reduced_motion()


def test_noise_and_corrupt_keep_shape():
    line = fx.noise_line(40, random.Random(1))
    assert len(line) == 40
    text = "the scale is honest"
    glitched = fx.corrupt(text, fraction=0.5, rng=random.Random(2))
    assert len(glitched) == len(text)
    assert glitched != text


def test_eye_tracks_blinks_and_widens():
    assert fx.eye(0, 5) == fx.EYE_FRAMES[0]
    assert fx.eye(4, 5) == fx.EYE_FRAMES[-1]
    assert fx.eye(2, 5, blink=True) == fx.EYE_BLINK
    assert fx.eye(0, 1, wide=True) == fx.EYE_WIDE
    assert fx.eye(0, 1) == fx.EYE_FRAMES[2]  # singleton hand: centered


def test_boardfx_empty():
    assert fx.BoardFX().empty
    assert not fx.BoardFX(flash={("foe", 1)}).empty
    assert not fx.BoardFX(scale=2).empty


async def test_bell_theater_resolves_combat(monkeypatch):
    """With frames collapsed to zero delay, the theater path must reach the
    same end state as the instant path: bell rung, fx cleared, input back."""
    from scrypt.app import ScryptApp
    from scrypt.ui.board import BoardScreen

    async def instant_frame(self, dt):
        self.refresh_all()

    async def no_glitch(self):
        pass

    monkeypatch.setenv("SCRYPT_REDUCED_MOTION", "0")
    monkeypatch.setattr(BoardScreen, "_frame", instant_frame)
    monkeypatch.setattr(BoardScreen, "_glitch", no_glitch)

    app = ScryptApp(seed=11, skip_menu=True)
    async with app.run_test() as pilot:
        await pilot.pause()
        screen = app.screen
        assert isinstance(screen, BoardScreen)
        state = screen.state
        await pilot.press("s")        # draw a bit
        turn_before = state.turn
        await pilot.press("b")        # ring the bell -> theater worker
        for _ in range(40):
            await pilot.pause()
            if not screen._animating and state.turn > turn_before:
                break
        assert state.turn > turn_before
        assert screen._fx.empty
        assert not screen._animating