feat: camera moves include static holds on one object; X to Y fires less often

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
digital-garbage
2026-09-30 20:01:04 +03:00
co-authored by Claude Sonnet 5.5
parent 8bbed2b1f8
commit e91fc71150
2 changed files with 25 additions and 1 deletions
+8 -1
View File
@@ -61,7 +61,10 @@ MOVES_THEN = ("Then the camera pans to {y}.", "Then the camera racks focus to {y
MOVES_FINISH = ("Then the camera zooms out.", "Then the camera pulls back.",
"Then the camera pulls back to a wider view.")
COUNT_WEIGHTS = (6, 3, 1) # one move / two / three, in a shot that gets any
TRAVEL_SHARE = 0.5 # of one-move shots with two topics, how many travel X -> Y
TRAVEL_SHARE = 0.25 # of one-move shots with two topics, how many travel X -> Y
HOLD_SHARE = 0.25 # of the other one-move shots, how many stay still on one thing
MOVES_HOLD = ("The camera holds steady on {x}.", "The camera stays still, focused on {x}.",
"The camera stays fixed, focused on {x}.")
DETERMINERS = {"the", "a", "an", "this", "that", "these", "those"}
POSSESSIVE_PRONOUNS = {"his", "her", "their", "its", "my", "your", "our"}
@@ -277,6 +280,10 @@ def _plan(pool, last, rng, prior=None):
x, y = _name(topics[0]), _name(topics[-1])
move = _pick(MOVES_TRAVEL, last, rng)
return move.format(x=x, y=y), f"{x} -> {y}", move
if rng is not None and k == 1 and rng.random() < HOLD_SHARE:
hold = _pick(MOVES_HOLD, last, rng) # some shots want one fixed focus
target = _name(best)
return hold.format(x=target), target, hold
first = topics[0] if (k > 1 and topics) else best
moves = MOVES_DETAIL if (first[2] or first[0] in PARTS) else MOVES_OTHER
opening = _pick(moves, last, rng)
+17
View File
@@ -417,3 +417,20 @@ def test_a_move_never_ends_on_a_dangling_word():
P = HEAD + "[Shot 1] <Subject 1> touches the base, then the skin, while <Subject 2> watches."
_out, rep = sc.add_camera_moves(P, seed=1, chance=1.0)
assert rep[0]["move"] is None
def test_some_shots_hold_still_on_one_object_and_pans_are_the_minority():
"""Not every shot is a move: a static focus is part of the mix, and X -> Y is rarer than it."""
pytest.importorskip("spacy")
kinds = {"hold": 0, "pan": 0, "other": 0}
for seed in range(300):
_o, rep = sc.add_camera_moves(TWO, seed=seed)
m = rep[0]["move"]
if "holds steady" in m or "stays still" in m or "stays fixed" in m:
kinds["hold"] += 1
elif " from " in m and " to " in m and " Then" not in m:
kinds["pan"] += 1
else:
kinds["other"] += 1
assert kinds["hold"] > 20 and 0 < kinds["pan"] < kinds["other"], kinds
assert kinds["pan"] < 0.3 * 300, kinds