# Problem Description
This is a turn-based battle game simulation between a player and a dragon. The game has two distinct status phases with different attack patterns. The goal is to calculate the remaining life points of whoever wins the battle (either dragon or player). The battle follows specific rules for attack power modifications and status transitions.

# Visual Facts
Status 1:
- Dragon attacks the player with 100% attack point.
- Check player's life:
    - If life > 0, continue.
    - If life ≤ 0, game over.
- If player's life < 60, shift to Status 2.
- Otherwise, Player attacks the dragon with 100% attack point.
- Check dragon's life:
    - If life > 0, continue.
    - If life ≤ 0, game over.


Status 2:
- Player attacks the dragon with 80% attack point.
- Check dragon's life:
    - If life > 0, continue.
    - If life ≤ 0, game over.
- Dragon attacks the player with 120% attack point.
- Check player's life:
    - If life > 0, continue.
    - If life ≤ 0, game over.

# Visual Patterns
Critical Thresholds:
   - In Status 1, each time the player is attacked by the dragon, we need to check if the player's life is below 60. If it is, the game will directly switch to Status 2, and the player will attack the dragon with 80% of their attack points.
   - Player life < 60 triggers status change from Status 1 to Status 2
   - Life points ≤ 0 triggers game over
   - When the dragon's life is ≤ 0, return the player's life.
   - When the player's life is ≤ 0, return the dragon's life.

# Solution
def solution(dragon_life: float, player_life: float, dragon_attack_point: float, player_attack_point: float) -> int:
    """
    Build the dragon slaying game as shown in the diagram, and calculate how many life points the winner has left.

    Parameters:
        dragon_life (float): The life points of the dragon.
        player_life (float): The life points of the player.
        dragon_attack_point (float): The base attack points of the dragon.
        player_attack_point (float): The base attack points of the player.

    Returns:
        int: The life points of the winner (rounded down).
    """
    status = 1
    while True:
        player_life -= dragon_attack_point

        if player_life <= 0:
            return int(dragon_life)
        
        if player_life < 60 and status == 1:
            status = 2
            dragon_attack_point *= 1.2
            player_attack_point *= 0.8

        dragon_life -= player_attack_point

        if dragon_life <= 0:
            return int(player_life)


# Test Script
def test():
    test_cases = [
        (90, 100, 5, 10, 49),
        (78, 59.9, 26.6, 60, 1),
        (100.79, 1000.1, 50.3, 8.54, 396),
        (100, 63, 1, 100, 62),
        (10, 1000.34, 1001, 11, 10),
        (176.24, 150.33, 26.8, 23.5, 68),
        (11.1, 92.3, 32.3, 1, 9),
        (13323.9, 12384.4, 11.1, 10.1, 2080),
        (11847382.68, 11111111.223, 4.4, 3.3, 3514065),
        (837272819.23, 1321137281.11, 666, 55.9, 726384604),
    ]

    for i, (dragon_life, player_life, dragon_attack_point, player_attack_point, expected_output) in enumerate(test_cases):
        try:
            output = solution(dragon_life, player_life, dragon_attack_point, player_attack_point)
        except Exception as e:
            error_message = (
                f"An exception occurred while running the test case:\n"
                f"`dragon_life`: {dragon_life}\n"
                f"`player_life`: {player_life}\n"
                f"`dragon_attack_point`: {dragon_attack_point}\n"
                f"`player_attack_point`: {player_attack_point}\n\n"
                f"Exception: '{str(e)}'"
            )
            assert False, error_message

        if output != expected_output:
            error_message = (
                f"The following Test Case failed:\n"
                f"`dragon_life`: {dragon_life}\n"
                f"`player_life`: {player_life}\n"
                f"`dragon_attack_point`: {dragon_attack_point}\n"
                f"`player_attack_point`: {player_attack_point}\n\n"
                f"Actual Output: {output}\n"
                f"Expected Output: {expected_output}"
            )
            assert False, error_message

test()