Files
battery/tests/test_mounting.py
James Campbell d84e4627c3 Initial commit
2026-07-21 19:36:02 -04:00

154 lines
3.8 KiB
Python

"""Mounting traps on other traps."""
from conftest import step, DT
from game.traps import Block, Spike
PLATFORM_WITH_SPIKE = """
name: t
tile_size: 32
map: |
############
#..........#
#..........#
#.........G#
#P.........#
############
traps:
- type: block
at: [3, 2]
path: [[3, 2], [8, 2]]
mode: pingpong
speed: 120
sprite: patrol_block
mounts:
- type: spike
at: [0, -1]
trigger: always
direction: up
"""
def test_spike_mount_follows_platform(make_game):
g = make_game(PLATFORM_WITH_SPIKE)
plat = g.level.traps[0]
sp = plat.mounts[0]
assert isinstance(sp, Spike)
for _ in range(30):
g.level.update(DT, g)
p = plat.current_rect()
hz = sp.hazard_rects()[0]
# spike sits one tile above the platform and moves with it
assert hz.centerx == p.centerx
assert hz.bottom <= p.top + 1
def test_block_mounted_on_block(make_game):
g = make_game("""
name: t
tile_size: 32
map: |
############
#..........#
#..........#
#.........G#
#P.........#
############
traps:
- type: block
at: [3, 2]
path: [[3, 2], [8, 2]]
mode: pingpong
speed: 120
sprite: patrol_block
mounts:
- type: block
at: [-1, 0]
deadly: true
- type: block
at: [1, 0]
deadly: true
""")
plat = g.level.traps[0]
g.level.update(DT, g)
for m in plat.mounts:
assert m._mounted and m.deadly
# each deadly mount tracks the platform at its offset and is lethal
exp = (plat.current_rect().x + m._mount_off[0],
plat.current_rect().y + m._mount_off[1])
assert (m.current_rect().x, m.current_rect().y) == exp
assert m.hazard_rects()
MOBILE_MOUNT = """
name: t
tile_size: 32
map: |
################
#..............#
#..............#
#..............#
#..............#
#P............G#
################
traps:
- type: block
at: [3, 4]
path: [[3, 4], [8, 4]]
mode: pingpong
speed: 120
sprite: patrol_block
mounts:
# Rides the patrol AND runs its own upward stroke when armed.
- type: block
at: [0, -1]
move: [0, -3]
speed: 240
mode: once
trigger: { within: 40 } # player is always in range -> stays extended
mounts:
- type: spike
at: [0, -1]
trigger: always
direction: up
"""
def test_block_mount_runs_own_motion_while_riding(make_game):
g = make_game(MOBILE_MOUNT)
plat = g.level.traps[0]
mnt = plat.mounts[0]
assert isinstance(mnt, Block) and mnt._mounted
tile = g.level.tile
# At rest the mount sits one tile above the patrol, tracking its column.
assert mnt.current_rect().x == plat.current_rect().x
assert mnt.current_rect().top == plat.current_rect().top - tile
for _ in range(120):
g.level.update(DT, g)
pr, mr = plat.current_rect(), mnt.current_rect()
# Still rides along horizontally (same column offset as home)...
assert mr.x == pr.x
# ...but has run its own three-tile upward stroke above the resting spot
# (resting = 1 tile up; extended = 1 + 3 tiles up).
assert mr.top == pr.top - 4 * tile
# It reports as a solid carrier so a rider would be carried.
assert mnt.solid_rects() and mnt.carriers()
# The spike rides the lunging block, one tile above it.
spike = mnt.mounts[0]
hz = spike.hazard_rects()[0]
assert hz.centerx == mr.centerx and hz.bottom <= mr.top + 1
def test_reset_repositions_mounts(make_game):
g = make_game(PLATFORM_WITH_SPIKE)
plat = g.level.traps[0]
sp = plat.mounts[0]
for _ in range(40):
g.level.update(DT, g)
g.level.reset()
# after reset the platform is home and the mount snapped back onto it
assert sp.base_rect.centerx == plat.current_rect().centerx