def return_team(ret_d=45.0, gw=20.0):
"""A return team: six men on the line, two vices on each gunner, one returner deep."""
pl_ = [D(f"F{i}", "DL", 1.0, w) for i, w in enumerate([-5.5, -3.0, -1.0, 1.0, 3.0, 5.5])]
pl_ += [D("VL1", "CB", 1.0, -gw + 1.8, "V"), D("VL2", "CB", 1.0, -gw - 1.8, "V"),
D("VR1", "CB", 1.0, gw - 1.8, "V"), D("VR2", "CB", 1.0, gw + 1.8, "V"),
D("PR", "DB", ret_d, 0.0, "PR")]
return pl_
sp = Play(spread_punt(gw=20.0), return_team(ret_d=45.0, gw=20.0), los=40, to_go=None)
KICK_T, CATCH_T = 2.0, 6.4
RET = (45.0, 1.5)
KICK_SPOT = (-12.9, 0.0)
# gunners: fight through the vices at the line, then bend in toward the returner
sp.route("GL", [(4.0, -19.4), (20.0, -15.5), (42.5, -2.0)], absolute=True, speed=7.3)
sp.route("GR", [(4.0, 19.4), (20.0, 15.5), (42.5, 5.0)], absolute=True, speed=7.3)
# vices ride their gunner: the outside vice on his outside hip, the inside vice on his inside hip
for k, side, out in (("VL1", -1, False), ("VL2", -1, True), ("VR1", 1, False), ("VR2", 1, True)):
dw = 1.5 if out else -1.5
sp.path(k, [(3.5, side * (19.4 + dw)), (19.0, side * (15.5 + dw)), (40.0, side * (4.5 + dw) + 1.5)],
absolute=True, speed=6.6)
# linemen and wings: hold up the rush until the kick, then release into lanes about five yards apart
LANES = {"LW": -14.0, "LT": -9.0, "LG": -4.5, "LS": 0.0, "RG": 4.5, "RT": 9.0, "RW": 14.0}
for k, lane in LANES.items():
sp.block(k, pts=[(-0.4, 0.0)], speed=1.0) # 0.4 s set, then hold
sp.path(k, [(6.0, lane * 0.9), (33.0, lane * 0.75 + 0.4)], absolute=True, speed=7.0,
delay=KICK_T - 0.4 - 0.1)
sp.block("PP", pts=[(0.0, -0.3)], speed=1.0)
sp.path("PP", [(3.0, 1.0), (17.0, 3.5)], absolute=True, speed=5.5, delay=KICK_T - 0.3 + 0.2)
# punter: catches the snap, takes his steps to the spot of the kick, then trails the coverage
sp.path("P", [KICK_SPOT], absolute=True, speed=1.2, delay=0.75) # arrives about 2.1 s
sp.path("P", [(4.0, -3.0)], absolute=True, speed=5.0, delay=0.4)
# front six: a token rush, then turn and retreat toward the returner
for i, k in enumerate(["F0", "F1", "F2", "F3", "F4", "F5"]):
q = sp.players[k]
sp.rush(k, pts=[(-0.9, 0.0)], speed=1.2)
sp.path(k, [(18.0 + 1.5 * (i % 2), q.w * 1.6), (26.0 + 1.5 * (i % 2), q.w * 1.3)], absolute=True,
speed=5.8, delay=0.1)
sp.path("PR", [RET], absolute=True, speed=1.5, delay=4.6)
def punt_ball(t):
if t <= 0:
return (0.0, 0.0)
if t < 0.75:
return lerp((0.0, 0.0), (-14.2, 0.0), t / 0.75)
if t < KICK_T:
return lerp((-14.2, 0.0), KICK_SPOT, (t - 0.75) / (KICK_T - 0.75))
if t < CATCH_T:
return lerp(KICK_SPOT, RET, (t - KICK_T) / (CATCH_T - KICK_T))
return RET
sp_df = with_ball(sp, punt_ball, t_after=0.4)
def sp_notes(axes):
strip_text(axes[0], sp, 20.0, 0.0, "returner 45 yds\npast the line,\n~60 from punter", color=DC, fs=6.4)
strip_text(axes[0], sp, -3.6, -18.0, "G + 2 V", color=OC, fs=6.4)
strip_text(axes[0], sp, -3.6, 18.0, "G + 2 V", color=OC, fs=6.4)
strip_text(axes[0], sp, -9.5, -7.5, "shield:\nwings + PP", color=OC, fs=6.4)
strip_text(axes[0], sp, -14.5, 7.0, "punter", color=OC, fs=6.4)
strip_text(axes[1], sp, 18.0, 0.0, "kick: linemen\nrelease now", color=OC, fs=6.4)
ax = axes[2]
for lane in LANES.values():
(x0, y0), (x1, y1) = sxy(sp, 12.0, lane * 0.87), sxy(sp, 30.0, lane * 0.77)
ax.plot([x0, x1], [y0, y1], color=OC, lw=0.8, ls=(0, (1, 2)), alpha=0.8, zorder=2)
strip_text(ax, sp, 36.0, -14.0, "coverage\nlanes", color=OC, fs=6.4)
strip_text(axes[3], sp, 20.0, 12.5, "ball arrives:\na gunner on\neach side of PR", color=OC, fs=6.4)
show_strip(sp_df, times=[0.0, KICK_T, 4.2, CATCH_T], annotate=sp_notes)