def test_failed_stupid_prevents_block(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) player.skills.append(Skills.REALLY_STUPID) board.set_position(Position(7, 7), player) opponent = away_team.get_player(0) board.set_position(Position(8, 7), opponent) board.setup_complete() cmds = iter_([ TargetPlayerCommand( 1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.AWAY.value, 0, 8, 7]), TargetSpaceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 8, 7]), DeclineRerollCommand(1, 1, TeamType.HOME, 1, []), DiceChoiceCommand(1, 1, TeamType.HOME.value, 1, [0, 0, 0]) ]) log_entries = iter_([ StupidEntry(player.team.team_type, player.number, "2+", "1", ActionResult.FAILURE) ]) events = replay._process_block(player, opponent, cmds, log_entries, board) event = next(events) assert isinstance(event, Action) assert event.action == ActionType.REALLY_STUPID assert event.result == ActionResult.FAILURE assert not board.is_prone(player) assert not board.is_prone(opponent) assert not next(events, None) assert not next(cmds, None) assert not next(log_entries, None)
def test_stupid_player_pass_with_failure(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player_1 = home_team.get_player(0) player_1.skills.append(Skills.REALLY_STUPID) board.set_position(Position(5, 7), player_1) player_2 = home_team.get_player(1) board.set_position(Position(7, 7), player_2) board.set_ball_carrier(player_1) cmds = [ TargetPlayerCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.HOME.value, 1, 3, 3]), DiceChoiceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0]) ] log_entries = [ StupidEntry(TeamType.HOME, 1, "4+", "3", ActionResult.FAILURE.name) ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_throw(player_1, player_2, cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, Action) assert event.player == player_1 assert event.action == ActionType.REALLY_STUPID assert event.result == ActionResult.FAILURE assert board.get_ball_carrier() == player_1 assert board.get_ball_position() == Position(5, 7) assert not next(events, None) assert not next(cmds_iter, None) assert not next(log_entries_iter, None)
def test_apothecary_not_used_for_stunned(board): board.apothecaries[TeamType.HOME.value] = 1 home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) board.set_position(Position(6, 7), player) cmds = iter_([]) log_entries = iter_([ InjuryRollEntry(player.team.team_type, player.number, "1", InjuryRollResult.STUNNED.name) ]) events = replay._process_injury_roll(player, cmds, log_entries, board) event = next(events) assert isinstance(event, InjuryRoll) assert event.player == player assert event.result == InjuryRollResult.STUNNED assert not board.is_injured(player) assert player.position == Position(6, 7) assert board.get_position(Position(6, 7)) == player assert not next(events, None) assert not next(cmds, None) assert not next(log_entries, None)
def test_no_hits_with_spell(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) board.set_position(Position(7, 7), player) board.set_ball_carrier(player) cmds = [ SpellCommand(1, 1, TeamType.AWAY.value, 0, [TeamType.AWAY.value, 0, 255, 7, 7]) ] log_entries = [ FireballEntry(TeamType.HOME, 1, "4+", "3", ActionResult.FAILURE.name) ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_spell(cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, Spell) assert event.target == Position(7, 7) assert event.spell == "Fireball" event = next(events) assert isinstance(event, Action) assert event.player == player assert event.action == ActionType.SPELL_HIT assert event.result == ActionResult.FAILURE assert board.get_ball_carrier() == player assert not next(events, None) assert not next(log_entries_iter, None)
def test_spell_does_not_consume_following_events(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) board.set_position(Position(7, 7), player) board.set_ball_carrier(player) cmds = [ SpellCommand(1, 1, TeamType.AWAY.value, 0, [TeamType.AWAY.value, 0, 255, 7, 7]) ] log_entries = [ FireballEntry(TeamType.HOME, 1, "4+", "4", ActionResult.SUCCESS.name), ArmourValueRollEntry(TeamType.HOME, 1, "8+", "9", ActionResult.SUCCESS.name), InjuryRollEntry(TeamType.HOME, 1, "6", InjuryRollResult.STUNNED.name), BounceLogEntry(ScatterDirection.NW.value), BlockLogEntry(TeamType.HOME, 2) ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_spell(cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, Spell) assert event.target == Position(7, 7) assert event.spell == "Fireball" event = next(events) assert isinstance(event, Action) assert event.player == player assert event.action == ActionType.SPELL_HIT assert event.result == ActionResult.SUCCESS event = next(events) assert isinstance(event, PlayerDown) assert event.player == player event = next(events) assert isinstance(event, ArmourRoll) assert event.player == player assert event.result == ActionResult.SUCCESS event = next(events) assert isinstance(event, InjuryRoll) assert event.player == player assert event.result == InjuryRollResult.STUNNED event = next(events) assert isinstance(event, Bounce) assert event.start_space == Position(7, 7) assert event.end_space == Position(6, 8) assert event.scatter_direction == ScatterDirection.NW assert board.get_ball_carrier() is None assert board.get_ball_position() == Position(6, 8) assert not next(events, None) assert isinstance(next(log_entries_iter), BlockLogEntry)
def test_failed_catch_on_kick(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) cmds = iter_([ SetupCompleteCommand(1, 0, TeamType.AWAY.value, 0, []), SetupCommand(1, 0, TeamType.HOME.value, 0, [TeamType.HOME.value, 0, 8, 14]), SetupCompleteCommand(1, 0, TeamType.HOME.value, 0, []), KickoffCommand(1, 0, TeamType.AWAY.value, 0, [8, 15]), PreKickoffCompleteCommand(1, 0, TeamType.HOME.value, 0, [TeamType.HOME.value]) ]) log_entries = iter_([ KickDirectionLogEntry(TeamType.AWAY, "1", ScatterDirection.S.value), KickDistanceLogEntry(TeamType.AWAY, "1", 1), KickoffEventLogEntry(KickoffEvent.CHEERING_FANS.value), CatchEntry(TeamType.HOME, "1", "2+", "1", ActionResult.FAILURE), BounceLogEntry(ScatterDirection.N.value) ]) events = replay._process_kickoff(cmds, log_entries, board) event = next(events) assert isinstance(event, TeamSetupComplete) assert event.team == TeamType.AWAY event = next(events) assert isinstance(event, TeamSetupComplete) assert event.team == TeamType.HOME event = next(events) assert isinstance(event, SetupComplete) event = next(events) assert isinstance(event, Kickoff) assert event.target == Position(8, 15) assert event.scatter_direction == ScatterDirection.S assert event.scatter_distance == 1 assert board.get_ball_position() == Position(8, 14) event = next(events) assert isinstance(event, KickoffEventTuple) assert event.result == KickoffEvent.CHEERING_FANS event = next(events) assert isinstance(event, Action) assert event.action == ActionType.CATCH assert event.result == ActionResult.FAILURE event = next(events) assert isinstance(event, Bounce) assert event.scatter_direction == ScatterDirection.N assert event.start_space == Position(8, 14) assert event.end_space == Position(8, 15) assert board.get_ball_carrier() is None assert not next(events, None) assert not next(cmds, None) assert not next(log_entries, None)
def test_pass_forward_success_after_pass_skill_reroll(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player_1 = home_team.get_player(0) player_1.skills.append(Skills.PASS) board.set_position(Position(5, 7), player_1) player_2 = home_team.get_player(1) board.set_position(Position(7, 7), player_2) board.set_ball_carrier(player_1) cmds = [ TargetPlayerCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.HOME.value, 1, 7, 7]), TargetSpaceCommand(1, 1, TeamType.HOME.value, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 7, 7]), InterceptCommand(1, 1, TeamType.AWAY.value, 13, [TeamType.AWAY.value]) ] log_entries = [ ThrowEntry(TeamType.HOME, 1, "3+", "1", ThrowResult.FUMBLE.name), SkillEntry(TeamType.HOME, 1, Skills.PASS.name), ThrowEntry(TeamType.HOME, 1, "3+", "6", ThrowResult.ACCURATE_PASS.name), CatchEntry(TeamType.HOME, 2, "3+", "3", ActionResult.SUCCESS.name) ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_throw(player_1, player_2, cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, Pass) assert event.player == player_1 assert event.target == Position(7, 7) assert event.result == ThrowResult.FUMBLE event = next(events) assert isinstance(event, Reroll) assert event.team == TeamType.HOME assert event.type == "Pass" event = next(events) assert isinstance(event, Pass) assert event.player == player_1 assert event.target == Position(7, 7) assert event.result == ThrowResult.ACCURATE_PASS event = next(events) assert isinstance(event, Action) assert event.player == player_2 assert event.action == ActionType.CATCH assert event.result == ActionResult.SUCCESS assert board.get_ball_carrier() == player_2 assert board.get_ball_position() == Position(7, 7) assert not next(events, None) assert not next(cmds_iter, None) assert not next(log_entries_iter, None)
def test_touchback_for_off_pitch_bounce(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) cmds = iter_([ SetupCompleteCommand(1, 0, TeamType.AWAY.value, 0, []), SetupCompleteCommand(1, 0, TeamType.HOME.value, 0, []), KickoffCommand(1, 0, TeamType.AWAY.value, 0, [1, 1]), # Kick right into the corner, PreKickoffCompleteCommand(1, 0, TeamType.HOME.value, 0, [TeamType.HOME.value]), TouchbackCommand(1, 0, TeamType.HOME.value, 0, [TeamType.HOME.value, 0]) ]) log_entries = iter_([ KickDirectionLogEntry(TeamType.AWAY, "1", ScatterDirection.SW.value), KickDistanceLogEntry(TeamType.AWAY, "1", 1), KickoffEventLogEntry(KickoffEvent.CHEERING_FANS.value), BounceLogEntry(ScatterDirection.S.value) ]) events = replay._process_kickoff(cmds, log_entries, board) event = next(events) assert isinstance(event, TeamSetupComplete) assert event.team == TeamType.AWAY event = next(events) assert isinstance(event, TeamSetupComplete) assert event.team == TeamType.HOME event = next(events) assert isinstance(event, SetupComplete) event = next(events) assert isinstance(event, Kickoff) assert event.target == Position(1, 1) assert event.scatter_direction == ScatterDirection.SW assert event.scatter_distance == 1 assert board.get_ball_position() == Position(0, 0) event = next(events) assert isinstance(event, KickoffEventTuple) assert event.result == KickoffEvent.CHEERING_FANS event = next(events) assert isinstance(event, Bounce) assert event.scatter_direction == ScatterDirection.S assert event.start_space == Position(0, 0) assert event.end_space.is_offpitch() event = next(events) assert isinstance(event, Touchback) assert event.player == player assert not next(cmds, None) assert not next(log_entries, None)
def test_throwing_teammate_fumble_pickup_failed_landing(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player_1 = home_team.get_player(0) player_1.skills.append(Skills.THROW_TEAMMATE) board.set_position(Position(7, 12), player_1) player_2 = home_team.get_player(1) player_2.skills.append(Skills.RIGHT_STUFF) board.set_position(Position(7, 11), player_2) cmds = [ TargetPlayerCommand(1, 1, TeamType.HOME.value, 1, [0, 0, 0, 1, 9, 18]), TargetSpaceCommand(1, 1, TeamType.HOME.value, 1, [0, 0, 0, 1, 26, 0, 0, 0, 7, 11, 0, 0]), DiceChoiceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0]) ] log_entries = [ ThrowTeammateEntry(TeamType.HOME, 1, "6+", 6, ThrowResult.FUMBLE.name), LandingEntry(TeamType.HOME, 2, "4+", 3, ActionResult.FAILURE.name), ArmourValueRollEntry(player_2.team.team_type, player_2.number, "9+", "8", ActionResult.FAILURE) ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_throw_teammate(player_1, player_2, cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, ThrowTeammate) assert event.player == player_1 assert event.thrown_player == player_2 assert event.target == Position(9, 18) assert event.result == ThrowResult.FUMBLE event = next(events) assert isinstance(event, Action) assert event.player == player_2 assert event.action == ActionType.LANDING assert event.result == ActionResult.FAILURE event = next(events) assert isinstance(event, PlayerDown) assert event.player == player_2 event = next(events) assert isinstance(event, ArmourRoll) assert event.player == player_2 assert event.result == ActionResult.FAILURE assert player_2.position == Position(7, 11) assert board.is_prone(player_2) assert not next(events, None) assert not next(cmds_iter, None) assert not next(log_entries_iter, None)
def test_handoff_failure_bounces(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player_1 = home_team.get_player(0) board.set_position(Position(7, 6), player_1) player_2 = home_team.get_player(1) board.set_position(Position(7, 7), player_2) board.set_ball_carrier(player_1) cmds = [ TargetPlayerCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.HOME.value, 1, 7, 7]), TargetSpaceCommand(1, 1, TeamType.HOME.value, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 7, 7]) ] log_entries = [ CatchEntry(TeamType.HOME, 2, "3+", "6", ActionResult.FAILURE.name), BounceLogEntry(ScatterDirection.W.value), TurnOverEntry(TeamType.HOME, "Lost the ball") ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_throw(player_1, player_2, cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, Handoff) assert event.player == player_1 assert event.target == player_2 event = next(events) assert isinstance(event, Action) assert event.player == player_2 assert event.action == ActionType.CATCH assert event.result == ActionResult.FAILURE event = next(events) assert isinstance(event, Bounce) assert event.scatter_direction == ScatterDirection.W assert event.start_space == Position(7, 7) assert event.end_space == Position(6, 7) event = next(events) assert isinstance(event, EndTurn) assert event.reason == "Lost the ball" assert not board.get_ball_carrier() assert board.get_ball_position() == Position(6, 7) assert not next(events, None) assert not next(cmds_iter, None) assert not next(log_entries_iter, None)
def test_apothecary_reduces_KO(board): board.apothecaries[TeamType.HOME.value] = 1 home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) board.set_position(Position(6, 7), player) cmds = iter_([ApothecaryCommand(1, 1, TeamType.HOME, 1, [0, 0, 1])]) log_entries = iter_( [ApothecaryLogEntry(player.team.team_type, player.number)]) events = replay._process_apothecary(player, InjuryRollResult.KO, CasualtyResult.NONE, cmds, log_entries, board) event = next(events) assert isinstance(event, Apothecary) assert event.player == player assert event.new_injury == InjuryRollResult.STUNNED assert event.casualty == CasualtyResult.NONE event = next(events) assert isinstance(event, InjuryRoll) assert event.player == player assert event.result == InjuryRollResult.STUNNED assert not board.is_injured(player) assert not next(events, None) assert not next(cmds, None) assert not next(log_entries, None)
def test_pass_diagonal_failed_intercept(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player_1 = home_team.get_player(0) board.set_position(Position(5, 5), player_1) player_2 = home_team.get_player(1) board.set_position(Position(3, 3), player_2) board.set_ball_carrier(player_1) opponent = away_team.get_player(0) board.set_position(Position(4, 4), opponent) cmds = [ TargetPlayerCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.HOME.value, 1, 3, 3]), TargetSpaceCommand(1, 1, TeamType.HOME.value, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 3, 3]), InterceptCommand(1, 1, TeamType.AWAY.value, 13, [1]) ] log_entries = [ CatchEntry(TeamType.AWAY, 1, "3+", "2", ActionResult.FAILURE.name), ThrowEntry(TeamType.HOME, 1, "3+", "6", ThrowResult.ACCURATE_PASS.name), CatchEntry(TeamType.HOME, 2, "3+", "6", ActionResult.SUCCESS.name) ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_throw(player_1, player_2, cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, Interception) assert event.player == opponent assert event.result == ActionResult.FAILURE event = next(events) assert isinstance(event, Pass) assert event.player == player_1 assert event.target == Position(3, 3) assert event.result == ThrowResult.ACCURATE_PASS event = next(events) assert isinstance(event, Action) assert event.player == player_2 assert event.action == ActionType.CATCH assert event.result == ActionResult.SUCCESS assert board.get_ball_carrier() == player_2 assert board.get_ball_position() == Position(3, 3) assert not next(events, None) assert not next(cmds_iter, None) assert not next(log_entries_iter, None)
def test_touchback_for_own_half_kick_other_direction(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) cmds = iter_([ SetupCompleteCommand(1, 0, TeamType.AWAY.value, 0, []), SetupCompleteCommand(1, 0, TeamType.HOME.value, 0, []), KickoffCommand(1, 0, TeamType.AWAY.value, 0, [8, 12]), PreKickoffCompleteCommand(1, 0, TeamType.HOME.value, 0, [TeamType.HOME.value]), TouchbackCommand(1, 0, TeamType.HOME.value, 0, [TeamType.HOME.value, 0]) ]) log_entries = iter_([ KickDirectionLogEntry(TeamType.AWAY, "1", ScatterDirection.N.value), KickDistanceLogEntry(TeamType.AWAY, "1", 1), KickoffEventLogEntry(KickoffEvent.CHEERING_FANS.value), BounceLogEntry(ScatterDirection.W.value) ]) events = replay._process_kickoff(cmds, log_entries, board) event = next(events) assert isinstance(event, TeamSetupComplete) assert event.team == TeamType.AWAY event = next(events) assert isinstance(event, TeamSetupComplete) assert event.team == TeamType.HOME event = next(events) assert isinstance(event, SetupComplete) event = next(events) assert isinstance(event, Kickoff) assert event.target == Position(8, 12) assert event.scatter_direction == ScatterDirection.N assert event.scatter_distance == 1 assert board.get_ball_position() == Position(8, 13) event = next(events) assert isinstance(event, KickoffEventTuple) assert event.result == KickoffEvent.CHEERING_FANS event = next(events) assert isinstance(event, Touchback) assert event.player == player assert not next(cmds, None) assert not next(log_entries, None)
def test_pushback_against_fend(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) board.set_position(Position(7, 7), player) opponent = away_team.get_player(0) opponent.skills.append(Skills.FEND) board.set_position(Position(8, 7), opponent) cmds = iter_([ TargetPlayerCommand( 1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.AWAY.value, 0, 8, 7]), TargetSpaceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 8, 7]), DiceChoiceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0]), PushbackCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 9, 8]) ]) log_entries = iter_([ BlockLogEntry(player.team.team_type, player.number).complete([BlockResult.PUSHED]), SkillEntry(opponent.team.team_type, opponent.number, "Fend") ]) events = replay._process_block(player, opponent, cmds, log_entries, board) event = next(events) assert isinstance(event, Block) assert event.blocking_player == player assert event.blocked_player == opponent assert event.dice == [BlockResult.PUSHED] assert event.result == BlockResult.PUSHED event = next(events) assert isinstance(event, Pushback) assert event.pushing_player == player assert event.pushed_player == opponent assert event.source_space == Position(8, 7) assert event.taget_space == Position(9, 8) event = next(events) assert isinstance(event, Skill) assert event.player == opponent assert event.skill == Skills.FEND assert not next(events, None) assert not next(cmds, None) assert not next(log_entries, None)
def test_dumpoff_does_not_allow_reroll(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) board.set_position(Position(5, 7), player) board.set_ball_carrier(player) player_2 = home_team.get_player(1) board.set_position(Position(7, 7), player_2) # Dump-offs are out of sequence board.turn_team = away_team cmds = iter_([ # Dumpoff is consumed in the block rolling function # DumpOffCommand(1, 1, TeamType.AWAY, 0, []), ThrowCommand(1, 1, TeamType.HOME.value, 0, [TeamType.HOME.value, 0, 7, 7]), InterceptCommand(1, 1, TeamType.AWAY.value, 0, [TeamType.HOME.value, 0, 0]) ]) log_entries = iter_([ ThrowEntry(player.team.team_type, player.number, "3+", "3", ThrowResult.ACCURATE_PASS.name), CatchEntry(player_2.team.team_type, player_2.number, "4+", "3", ActionResult.FAILURE.name), BounceLogEntry(ScatterDirection.N.value) ]) events = replay._process_pass(player, cmds, log_entries, board) event = next(events) assert isinstance(event, Pass) assert event.player == player assert event.target == Position(7, 7) event = next(events) assert isinstance(event, Action) assert event.action == ActionType.CATCH assert event.result == ActionResult.FAILURE event = next(events) assert isinstance(event, Bounce) assert event.scatter_direction == ScatterDirection.N assert event.start_space == Position(7, 7) assert event.end_space == Position(7, 8) assert not next(events, None) assert not next(cmds, None) assert not next(log_entries, None)
def test_fumble_then_prone_bounce(board): home_team, away_team = board.teams player = home_team.get_player(0) board.set_position(Position(13, 11), player) opponent = away_team.get_player(0) board.set_position(Position(14, 10), opponent) board.set_prone(opponent) replay = Replay(home_team, away_team, [], []) board.set_ball_position(Position(13, 12)) board.setup_complete() cmds = iter_([ DeclineRerollCommand(1, 1, TeamType.HOME, 1, []) ]) log_entries = [ BounceLogEntry(ScatterDirection.S.value), CatchEntry(TeamType.HOME, 1, "3+", "1", ActionResult.FAILURE.name), BounceLogEntry(ScatterDirection.SE.value), BounceLogEntry(ScatterDirection.W.value) ] log_entries_iter = iter_(log_entries) events = replay._process_ball_movement(cmds, log_entries_iter, board) event = next(events) assert isinstance(event, Bounce) assert event.start_space == Position(13, 12) assert event.end_space == Position(13, 11) event = next(events) assert isinstance(event, Action) assert event.player == player assert event.action == ActionType.CATCH assert event.result == ActionResult.FAILURE event = next(events) assert isinstance(event, Bounce) assert event.start_space == Position(13, 11) assert event.end_space == Position(14, 10) event = next(events) assert isinstance(event, Bounce) assert event.start_space == Position(14, 10) assert event.end_space == Position(13, 10) assert not next(cmds, None) assert not next(log_entries_iter, None) assert not next(events, None)
def test_team_reroll_on_block_dice(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) board.set_position(Position(7, 7), player) opponent = away_team.get_player(0) board.set_position(Position(8, 7), opponent) board.setup_complete() cmds = iter_([ TargetPlayerCommand( 1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.AWAY.value, 0, 8, 7]), TargetSpaceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 8, 7]), RerollCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0]), DiceChoiceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0]), PushbackCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 9, 8]), FollowUpChoiceCommand(1, 1, TeamType.HOME, 0, [1]) ]) log_entries = iter_([ BlockLogEntry(player.team.team_type, player.number).complete([BlockResult.BOTH_DOWN]), RerollEntry(TeamType.HOME), BlockLogEntry(player.team.team_type, player.number).complete([BlockResult.PUSHED]), ]) events = replay._process_block(player, opponent, cmds, log_entries, board) event = next(events) assert isinstance(event, Reroll) assert event.team == TeamType.HOME event = next(events) assert isinstance(event, Block) assert event.blocking_player == player assert event.blocked_player == opponent assert event.dice == [BlockResult.PUSHED] assert event.result == BlockResult.PUSHED event = next(events) assert isinstance(event, Pushback) assert event.pushing_player == player assert event.pushed_player == opponent assert event.source_space == Position(8, 7) assert event.taget_space == Position(9, 8) event = next(events) assert isinstance(event, FollowUp) assert event.following_player == player assert event.followed_player == opponent assert event.source_space == Position(7, 7) assert event.target_space == Position(8, 7) assert not board.is_prone(player) assert not board.is_prone(opponent) assert not next(events, None) assert not next(cmds, None) assert not next(log_entries, None)
def test_normal_kick_very_sunny(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) cmds = iter_([ SetupCompleteCommand(1, 0, TeamType.AWAY.value, 0, []), SetupCompleteCommand(1, 0, TeamType.HOME.value, 0, []), KickoffCommand(1, 0, TeamType.AWAY.value, 0, [8, 15]), PreKickoffCompleteCommand(1, 0, TeamType.HOME.value, 0, [TeamType.HOME.value]) ]) log_entries = iter_([ KickDirectionLogEntry(TeamType.AWAY, "1", ScatterDirection.S.value), KickDistanceLogEntry(TeamType.AWAY, "1", 1), KickoffEventLogEntry(KickoffEvent.CHANGING_WEATHER.value), WeatherLogEntry(Weather.VERY_SUNNY.name), BounceLogEntry(ScatterDirection.N.value), BounceLogEntry(ScatterDirection.E.value) ]) events = replay._process_kickoff(cmds, log_entries, board) event = next(events) assert isinstance(event, TeamSetupComplete) assert event.team == TeamType.AWAY event = next(events) assert isinstance(event, TeamSetupComplete) assert event.team == TeamType.HOME event = next(events) assert isinstance(event, SetupComplete) event = next(events) assert isinstance(event, Kickoff) assert event.target == Position(8, 15) assert event.scatter_direction == ScatterDirection.S assert event.scatter_distance == 1 assert board.get_ball_position() == Position(8, 14) event = next(events) assert isinstance(event, KickoffEventTuple) assert event.result == KickoffEvent.CHANGING_WEATHER event = next(events) assert isinstance(event, WeatherTuple) assert event.result == Weather.VERY_SUNNY event = next(events) assert isinstance(event, Bounce) assert event.scatter_direction == ScatterDirection.N assert event.start_space == Position(8, 14) assert event.end_space == Position(8, 15) event = next(events) assert isinstance(event, Bounce) assert event.scatter_direction == ScatterDirection.E assert event.start_space == Position(8, 15) assert event.end_space == Position(9, 15) assert not next(cmds, None) assert not next(log_entries, None)
def test_ghost_bounce_due_to_no_catch(board): # Based on turn 6 of Replay_2021-04-04_09-49-09.db when Kardel the Putrefier is knocked into the ball home_team, away_team = board.teams player = home_team.get_player(0) board.set_position(Position(13, 11), player) replay = Replay(home_team, away_team, [], []) board.set_ball_position(Position(13, 12)) board.setup_complete() cmds = iter_([]) log_entries = [ BounceLogEntry(ScatterDirection.S.value), BounceLogEntry(ScatterDirection.SE.value) ] log_entries_iter = iter_(log_entries) events = replay._process_ball_movement(cmds, log_entries_iter, board) event = next(events) assert isinstance(event, Bounce) assert event.start_space == Position(13, 12) assert event.end_space == Position(14, 11) assert not next(events, None)
def test_pickup_failure(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) board.set_position(Position(6, 7), player) board.set_ball_position(Position(7, 7)) cmds = [ EndMovementCommand(1, 1, TeamType.HOME.value, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 7, 7]), DiceChoiceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0]), ] log_entries = [ PickupEntry(TeamType.HOME, player.number, "2+", "1", ActionResult.FAILURE.name), BounceLogEntry(ScatterDirection.NW.value), TurnOverEntry(TeamType.HOME, "Pick-up failed!") ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_movement(player, cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, Movement) assert event.source_space == Position(6, 7) assert event.target_space == Position(7, 7) event = next(events) assert isinstance(event, Pickup) assert event.player == player assert event.position == Position(7, 7) assert event.result == ActionResult.FAILURE event = next(events) assert isinstance(event, Bounce) assert event.start_space == Position(7, 7) assert event.end_space == Position(6, 8) assert event.scatter_direction == ScatterDirection.NW event = next(events) assert isinstance(event, EndTurn) assert event.reason == "Pick-up failed!" assert board.get_ball_carrier() is None assert board.get_ball_position() == Position(6, 8) assert not next(cmds_iter, None) assert not next(log_entries_iter, None)
def test_pass_diagonal_successful_intercept(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player_1 = home_team.get_player(0) board.set_position(Position(5, 5), player_1) player_2 = home_team.get_player(1) board.set_position(Position(3, 3), player_2) board.set_ball_carrier(player_1) opponent = away_team.get_player(0) board.set_position(Position(4, 4), opponent) cmds = [ TargetPlayerCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.HOME.value, 1, 3, 3]), TargetSpaceCommand(1, 1, TeamType.HOME.value, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 3, 3]), InterceptCommand(1, 1, TeamType.AWAY.value, 13, [1]) ] log_entries = [ CatchEntry(TeamType.AWAY, 1, "3+", "3", ActionResult.SUCCESS.name), TurnOverEntry(TeamType.HOME, "Lost the ball!") ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_throw(player_1, player_2, cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, Interception) assert event.player == opponent assert event.result == ActionResult.SUCCESS event = next(events) assert isinstance(event, EndTurn) assert event.reason == "Lost the ball!" assert board.get_ball_carrier() == opponent assert board.get_ball_position() == Position(4, 4) assert not next(events, None) assert not next(cmds_iter, None) assert not next(log_entries_iter, None)
def test_frenzy_with_first_block_down(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) player.skills.append(Skills.FRENZY) board.set_position(Position(7, 7), player) opponent = away_team.get_player(0) board.set_position(Position(8, 7), opponent) cmds = iter_([ TargetPlayerCommand( 1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.AWAY.value, 0, 8, 7]), TargetSpaceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 8, 7]), DiceChoiceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0]), PushbackCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 9, 8]) ]) log_entries = iter_([ BlockLogEntry(player.team.team_type, player.number).complete([BlockResult.DEFENDER_DOWN]), ArmourValueRollEntry(opponent.team.team_type, opponent.number, "9+", "8", ActionResult.FAILURE) ]) events = replay._process_block(player, opponent, cmds, log_entries, board) event = next(events) assert isinstance(event, Block) assert event.blocking_player == player assert event.blocked_player == opponent assert event.dice == [BlockResult.DEFENDER_DOWN] assert event.result == BlockResult.DEFENDER_DOWN event = next(events) assert isinstance(event, Pushback) assert event.pushing_player == player assert event.pushed_player == opponent assert event.source_space == Position(8, 7) assert event.taget_space == Position(9, 8) event = next(events) assert isinstance(event, FollowUp) assert event.following_player == player assert event.followed_player == opponent assert event.source_space == Position(7, 7) assert event.target_space == Position(8, 7) event = next(events) assert isinstance(event, PlayerDown) assert event.player == opponent event = next(events) assert isinstance(event, ArmourRoll) assert event.player == opponent assert event.result == ActionResult.FAILURE assert not next(events, None) assert not next(cmds, None) assert not next(log_entries, None)
def test_pushback_off_field(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) board.set_position(Position(1, 0), player) opponent = away_team.get_player(0) board.set_position(Position(0, 0), opponent) cmds = iter_([ TargetPlayerCommand( 1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.AWAY.value, 0, 8, 7]), TargetSpaceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 0, 0]), DiceChoiceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0]), FollowUpChoiceCommand(1, 1, TeamType.HOME, 0, [1]) ]) log_entries = iter_([ BlockLogEntry(player.team.team_type, player.number).complete([BlockResult.PUSHED]), InjuryRollEntry(opponent.team.team_type, opponent.number, "4", InjuryRollResult.STUNNED.name) ]) events = replay._process_block(player, opponent, cmds, log_entries, board) event = next(events) assert isinstance(event, Block) assert event.blocking_player == player assert event.blocked_player == opponent assert event.dice == [BlockResult.PUSHED] assert event.result == BlockResult.PUSHED event = next(events) assert isinstance(event, Pushback) assert event.pushing_player == player assert event.pushed_player == opponent assert event.source_space == Position(0, 0) assert event.taget_space == Position(-1, -1) event = next(events) assert isinstance(event, FollowUp) assert event.following_player == player assert event.followed_player == opponent assert event.source_space == Position(1, 0) assert event.target_space == Position(0, 0) event = next(events) assert isinstance(event, InjuryRoll) assert event.player == opponent assert event.result == InjuryRollResult.STUNNED assert not board.is_prone(player) # They were stunned, not injured assert not board.is_injured(opponent) assert not next(events, None) assert not next(cmds, None) assert not next(log_entries, None)
def test_pickup_success_with_sure_hands(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) player.skills.append(Skills.SURE_HANDS) board.set_position(Position(6, 7), player) board.set_ball_position(Position(7, 7)) cmds = [ EndMovementCommand(1, 1, TeamType.HOME.value, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 7, 7]) ] log_entries = [ PickupEntry(TeamType.HOME, player.number, "2+", "1", ActionResult.FAILURE.name), SkillEntry(TeamType.HOME, player.number, Skills.SURE_HANDS.name), PickupEntry(TeamType.HOME, player.number, "2+", "2", ActionResult.SUCCESS.name) ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_movement(player, cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, Movement) assert event.source_space == Position(6, 7) assert event.target_space == Position(7, 7) event = next(events) assert isinstance(event, Pickup) assert event.player == player assert event.position == Position(7, 7) assert event.result == ActionResult.FAILURE event = next(events) assert isinstance(event, Reroll) assert event.team == TeamType.HOME assert event.type == Skills.SURE_HANDS.name.title() event = next(events) assert isinstance(event, Pickup) assert event.player == player assert event.position == Position(7, 7) assert event.result == ActionResult.SUCCESS assert board.get_ball_carrier() == player assert board.get_ball_position() == Position(7, 7) assert not next(events, None) assert not next(cmds_iter, None) assert not next(log_entries_iter, None)
def test_throwing_teammate_successful_always_hungry(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player_1 = home_team.get_player(0) player_1.skills.append(Skills.THROW_TEAMMATE) player_1.skills.append(Skills.ALWAYS_HUNGRY) board.set_position(Position(7, 12), player_1) player_2 = home_team.get_player(1) player_2.skills.append(Skills.RIGHT_STUFF) board.set_position(Position(7, 11), player_2) cmds = [ TargetPlayerCommand(1, 1, TeamType.HOME.value, 1, [0, 0, 0, 1, 9, 18]), TargetSpaceCommand(1, 1, TeamType.HOME.value, 1, [0, 0, 0, 1, 26, 0, 0, 0, 7, 11, 0, 0]) ] log_entries = [ AlwaysHungryEntry(TeamType.HOME, 1, "2+", 2, ActionResult.SUCCESS.name), ThrowTeammateEntry(TeamType.HOME, 1, "6+", 6, ThrowResult.INACCURATE_PASS.name), ScatterLaunchEntry(ScatterDirection.NW.value), ScatterLaunchEntry(ScatterDirection.SE.value), ScatterLaunchEntry(ScatterDirection.E.value), LandingEntry(TeamType.HOME, 2, "4+", 4, ActionResult.SUCCESS.name) ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_throw_teammate(player_1, player_2, cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, Action) assert event.player == player_1 assert event.action == ActionType.ALWAYS_HUNGRY assert event.result == ActionResult.SUCCESS event = next(events) assert isinstance(event, ThrowTeammate) assert event.player == player_1 assert event.thrown_player == player_2 assert event.target == Position(9, 18) assert event.result == ThrowResult.INACCURATE_PASS event = next(events) assert isinstance(event, Scatter) assert event.start_space == Position(9, 18) assert event.end_space == Position(10, 18) event = next(events) assert isinstance(event, Action) assert event.player == player_2 assert event.action == ActionType.LANDING assert event.result == ActionResult.SUCCESS assert player_2.position == Position(10, 18) assert not board.is_prone(player_2) assert not next(events, None) assert not next(cmds_iter, None) assert not next(log_entries_iter, None)
def test_handoff_diagonal_success(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player_1 = home_team.get_player(0) board.set_position(Position(6, 6), player_1) player_2 = home_team.get_player(1) board.set_position(Position(7, 7), player_2) board.set_ball_carrier(player_1) cmds = [ TargetPlayerCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.HOME.value, 1, 7, 7]), TargetSpaceCommand(1, 1, TeamType.HOME.value, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 7, 7]) ] log_entries = [ CatchEntry(TeamType.HOME, 2, "3+", "6", ActionResult.SUCCESS.name) ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_throw(player_1, player_2, cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, Handoff) assert event.player == player_1 assert event.target == player_2 event = next(events) assert isinstance(event, Action) assert event.player == player_2 assert event.action == ActionType.CATCH assert event.result == ActionResult.SUCCESS assert board.get_ball_carrier() == player_2 assert board.get_ball_position() == Position(7, 7) assert not next(events, None) assert not next(cmds_iter, None) assert not next(log_entries_iter, None)
def test_dodge_on_defender_stumbles(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) board.set_position(Position(7, 7), player) opponent = away_team.get_player(0) opponent.skills.append(Skills.DODGE) board.set_position(Position(8, 7), opponent) cmds = iter_([ TargetPlayerCommand( 1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.AWAY.value, 0, 8, 7]), TargetSpaceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 8, 7]), DiceChoiceCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 0]), PushbackCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, 9, 8]), FollowUpChoiceCommand(1, 1, TeamType.HOME, 0, [1]) ]) log_entries = iter_([ BlockLogEntry(player.team.team_type, player.number).complete([BlockResult.DEFENDER_STUMBLES]), SkillEntry(opponent.team.team_type, opponent.number, "Dodge") ]) events = replay._process_block(player, opponent, cmds, log_entries, board) event = next(events) assert isinstance(event, Block) assert event.blocking_player == player assert event.blocked_player == opponent assert event.dice == [BlockResult.DEFENDER_STUMBLES] assert event.result == BlockResult.DEFENDER_STUMBLES event = next(events) assert isinstance(event, Pushback) assert event.pushing_player == player assert event.pushed_player == opponent assert event.source_space == Position(8, 7) assert event.taget_space == Position(9, 8) event = next(events) assert isinstance(event, FollowUp) assert event.following_player == player assert event.followed_player == opponent assert event.source_space == Position(7, 7) assert event.target_space == Position(8, 7) event = next(events) assert isinstance(event, DodgeBlock) assert event.blocking_player == player assert event.blocked_player == opponent assert not next(events, None) assert not next(cmds, None) assert not next(log_entries, None)
def draw_map(board, pretty): # TODO: String builder map = "" has_ball_carrier = board.get_ball_carrier() is not None ball_position = board.get_ball_position() for row in range(PITCH_LENGTH - 1, -1, -1): row_data = board[row] if row == NEAR_ENDZONE_IDX: map += draw_filler_row(ENDZONE, pretty) elif row == BEFORE_HALFWAY_IDX: map += draw_filler_row(HALFWAY_LINE, pretty) elif row == FAR_ENDZONE_IDX: map += draw_filler_row(TOPLINE, pretty) elif row == FAR_ENDZONE_IDX - 1: map += draw_filler_row(ENDZONE, pretty) else: map += draw_filler_row(ROW_AFTER, pretty) map += f"{row:^3}" if pretty: map += BOARD_COLOUR map += ROW[0] for col in range(PITCH_WIDTH): player = row_data[col] if player: map += player_to_text(player, pretty, board) elif not has_ball_carrier and ball_position == Position(col, row): ball = ROW[1] + "●" + ROW[1] # "🏈" is too wide to align properly☹ map += ball if not pretty else BALL_COLOUR + ball + PIECE_RESET else: map += ROW[1] * 3 if col == LEFT_WIDEZONE_IDX or col == RIGHT_WIDEZONE_IDX - 1: map += ROW[3] elif col == LAST_COLUMN_IDX: map += ROW[4] else: map += ROW[2] if pretty: map += ROW_RESET map += "\n" if row == 0: map += draw_filler_row(BOTTOMLINE, pretty) map += " " # Three spaces for numbering, plus one for the border for col in range(PITCH_WIDTH): map += f"{col:^4}" map += "\n" return map
def test_pass_fumble_scatters_to_teammate(board): home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player_1 = home_team.get_player(0) board.set_position(Position(5, 7), player_1) player_2 = home_team.get_player(1) board.set_position(Position(7, 7), player_2) player_3 = home_team.get_player(2) board.set_position(Position(4, 8), player_3) board.set_ball_carrier(player_1) cmds = [ TargetPlayerCommand(1, 1, TeamType.HOME, 0, [TeamType.HOME.value, 0, TeamType.HOME.value, 1, 7, 7]), TargetSpaceCommand(1, 1, TeamType.HOME.value, 0, [TeamType.HOME.value, 0, 0, 0, 0, 0, 0, 0, 7, 7]), InterceptCommand(1, 1, TeamType.AWAY.value, 13, [TeamType.AWAY.value]), DeclineRerollCommand(1, 1, TeamType.HOME.value, 0, []) ] log_entries = [ ThrowEntry(TeamType.HOME, 1, "3+", "1", ThrowResult.FUMBLE.name), BounceLogEntry(ScatterDirection.NW.value), CatchEntry(TeamType.HOME, 3, "2+", "2", ActionResult.SUCCESS.name) ] cmds_iter = iter_(cmds) log_entries_iter = iter_(log_entries) events = replay._process_throw(player_1, player_2, cmds_iter, log_entries_iter, board) event = next(events) assert isinstance(event, Pass) assert event.player == player_1 assert event.target == Position(7, 7) assert event.result == ThrowResult.FUMBLE event = next(events) assert isinstance(event, Bounce) assert event.scatter_direction == ScatterDirection.NW assert event.start_space == Position(5, 7) assert event.end_space == Position(4, 8) event = next(events) assert isinstance(event, Action) assert event.action == ActionType.CATCH assert event.player == player_3 assert event.result == ActionResult.SUCCESS assert board.get_ball_carrier() == player_3 assert board.get_ball_position() == Position(4, 8) assert not next(events, None) assert not next(cmds_iter, None) assert not next(log_entries_iter, None)
def test_apothecary_declined(board): board.apothecaries[TeamType.HOME.value] = 1 home_team, away_team = board.teams replay = Replay(home_team, away_team, [], []) player = home_team.get_player(0) board.set_position(Position(6, 7), player) board.set_injured(player) cmds = iter_([ApothecaryCommand(1, 1, TeamType.HOME, 1, [0, 0, 0])]) log_entries = iter_([]) events = replay._process_apothecary(player, InjuryRollResult.INJURED, CasualtyResult.DEAD, cmds, log_entries, board) assert board.is_injured(player) assert not next(events, None) assert not next(cmds, None) assert not next(log_entries, None)