# 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:
- Player attacks the dragon with 100% attack power.
- Check dragon's life:
    - If life > 0, continue.
    - If life ≤ 0, game over.
- If dragon's life < 40, shift to Status 2.
- Otherwise, Dragon attacks the player with 100% attack power.
- Check player's life:
    - If life > 0, return to player's attack.
    - If life ≤ 0, game over.

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

# Visual Patterns
1. Critical Thresholds:
   - Dragon life < 40 triggers status change from Status 1 to Status 2
   - Life points ≤ 0 triggers game over

2. Turn Order Pattern:
   - Status 1: Player attack → check status shifting → Dragon attack → Player attack → ...
   - Status 2: Dragon attack → Player attack → Dragon attack → ...


# 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:
        dragon_life -= player_attack_point

        if dragon_life <= 0:
            return int(player_life)
        
        if dragon_life < 40 and status == 1:
            status = 2
            player_attack_point *= 1.35
            dragon_attack_point *= 0.65

        player_life -= dragon_attack_point

        if player_life <= 0:
            return int(dragon_life)


# Test Script
def test():
    test_cases = [
        (100, 90, 10, 5, 55),
        (59.9, 78, 60, 26.6, 39),
        (1000.1, 100.79, 8.54, 50.3, 396),
        (63, 100, 100, 1, 62),
        (1000.34, 10, 11, 1001, 10),
        (150.33, 176.24, 23.5, 26.8, 66),
        (92.3, 11.1, 1, 32.3, 9),
        (12384.4, 13323.9, 10.1, 11.1, 2073),
        (11111111.223, 11847382.68, 3.3, 4.4, 3514065),
        (1321137281.11, 837272819.23, 55.9, 666, 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()