File size: 2,089 Bytes
bb3fbf9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
"""

Numba Utils for Love Live Card Game

JIT-compiled functions for high-performance game logic.

"""

try:
    from numba import njit

    JIT_AVAILABLE = True
except ImportError:
    # Fallback to python decorator if numba is missing (for safety)
    JIT_AVAILABLE = False

    def njit(func):
        return func


import numpy as np


@njit
def calc_main_phase_masks(

    hand: np.ndarray,

    stage: np.ndarray,

    available_energy: int,

    total_reduction: int,

    baton_touch_allowed: bool,

    members_played_this_turn: np.ndarray,

    member_costs: np.ndarray,  # Direct lookup array: cost = member_costs[card_id]

    mask: np.ndarray,

) -> None:
    """

    JIT-compiled Main Phase legal action calculation.

    """
    # Iterate through hand to find playable members
    hand_len = len(hand)
    for i in range(hand_len):
        card_id = hand[i]

        # Check if valid card ID for array lookup
        if card_id < 0 or card_id >= len(member_costs):
            continue

        base_cost = member_costs[card_id]
        if base_cost == -1:  # Not a member
            continue

        # Check each of the 3 stage areas
        for area in range(3):
            if members_played_this_turn[area]:
                continue

            active_cost = base_cost - total_reduction
            if active_cost < 0:
                active_cost = 0

            # Baton Touch Rule
            stage_card_id = stage[area]
            if baton_touch_allowed and stage_card_id != -1:
                if stage_card_id < len(member_costs):
                    existing_cost = member_costs[stage_card_id]
                    if existing_cost != -1:
                        active_cost = active_cost - existing_cost
                        if active_cost < 0:
                            active_cost = 0

            # Check affordability
            if active_cost <= available_energy:
                action_idx = 1 + (i * 3) + area
                if action_idx < 1000:
                    mask[action_idx] = 1