weiss_core/state/target.rs
1use serde::{Deserialize, Serialize};
2
3use crate::db::CardId;
4use crate::effects::EffectPayload;
5
6use super::CardInstanceId;
7
8/// Zones that can be targeted by effects.
9#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
10pub enum TargetZone {
11 /// Stage (front/back row slots).
12 Stage,
13 /// Hand.
14 Hand,
15 /// Top of deck.
16 DeckTop,
17 /// Clock.
18 Clock,
19 /// Level zone.
20 Level,
21 /// Stock.
22 Stock,
23 /// Memory.
24 Memory,
25 /// Waiting room.
26 WaitingRoom,
27 /// Climax zone.
28 Climax,
29 /// Resolution zone (temporary).
30 Resolution,
31}
32
33/// Side selection for targeting.
34#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
35pub enum TargetSide {
36 /// Current player / controller side.
37 SelfSide,
38 /// Opponent side.
39 Opponent,
40}
41
42/// Slot filter for targeting.
43#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
44pub enum TargetSlotFilter {
45 /// Any slot (no restriction).
46 Any,
47 /// Front-row slots only.
48 FrontRow,
49 /// Back-row slots only.
50 BackRow,
51 /// A specific slot index.
52 SpecificSlot(
53 /// Slot index in `[0, 4]`.
54 u8,
55 ),
56}
57
58/// Targeting specification for effects.
59#[derive(Clone, Debug, Hash, Serialize, Deserialize)]
60pub struct TargetSpec {
61 /// Target zone to search/select from.
62 pub zone: TargetZone,
63 /// Which side to target.
64 pub side: TargetSide,
65 /// Optional slot filter (primarily for stage targeting).
66 pub slot_filter: TargetSlotFilter,
67 /// Optional card type restriction.
68 pub card_type: Option<crate::db::CardType>,
69 /// Optional trait restriction (packed trait id).
70 #[serde(default)]
71 pub card_trait: Option<u16>,
72 /// Optional inclusive maximum level restriction.
73 pub level_max: Option<u8>,
74 /// Optional inclusive maximum cost restriction.
75 #[serde(default)]
76 pub cost_max: Option<u8>,
77 /// Optional card id whitelist restriction.
78 #[serde(default)]
79 pub card_ids: Vec<CardId>,
80 /// Number of cards/targets to select.
81 pub count: u8,
82 /// Optional hard limit for search-like effects.
83 #[serde(default)]
84 pub limit: Option<u8>,
85 /// If true, only the source card is eligible.
86 #[serde(default)]
87 pub source_only: bool,
88 /// If true, reveal selected cards to the controller.
89 #[serde(default)]
90 pub reveal_to_controller: bool,
91}
92
93/// Concrete target reference.
94#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
95pub struct TargetRef {
96 /// Owning/located player seat (0 or 1).
97 pub player: u8,
98 /// Zone containing the card.
99 pub zone: TargetZone,
100 /// Index within the zone (slot or list position).
101 pub index: u8,
102 /// Static card id.
103 pub card_id: CardId,
104 /// Stable per-game card instance id.
105 pub instance_id: CardInstanceId,
106}
107
108/// Pending target effect awaiting resolution.
109#[derive(Clone, Debug, Hash, Serialize, Deserialize)]
110pub enum PendingTargetEffect {
111 /// Resolve an effect payload once targeting is complete.
112 EffectPending {
113 /// Effect instance id to associate with the payload.
114 instance_id: u32,
115 /// Effect payload to execute.
116 payload: EffectPayload,
117 },
118}
119
120/// State for a target-selection prompt.
121#[derive(Clone, Debug, Hash, Serialize, Deserialize)]
122pub struct TargetSelectionState {
123 /// Controlling player making selections.
124 pub controller: u8,
125 /// Source card id producing the prompt.
126 pub source_id: CardId,
127 /// Targeting specification to satisfy.
128 pub spec: TargetSpec,
129 /// Remaining selections required.
130 pub remaining: u8,
131 /// Selected targets so far.
132 pub selected: Vec<TargetRef>,
133 /// Optional precomputed candidate list (for pagination/debugging).
134 #[serde(default)]
135 pub candidates: Vec<TargetRef>,
136 /// Effect to apply once selection completes.
137 pub effect: PendingTargetEffect,
138 /// Whether the controller may skip instead of selecting.
139 pub allow_skip: bool,
140}