Got refactor to compile⚙️

This commit is contained in:
2025-03-02 04:57:58 -06:00
parent e329b1f223
commit 159126e7ca
2 changed files with 176 additions and 123 deletions

View File

@ -47,7 +47,7 @@ enum Event {
Shuffle(Player), Shuffle(Player),
Draw(Player, usize), Draw(Player, usize),
Pass(Player, Player), Pass(Player, Player),
ChangeLifeTotal(Player, i32, i32), ChangeLifeTotal(Player, isize, isize),
FadeFromHand(Player), FadeFromHand(Player),
PlayFromHand(Player), PlayFromHand(Player),
Bounce(Player), Bounce(Player),
@ -69,6 +69,15 @@ struct CountedEvent {
event: Event, event: Event,
} }
macro_rules! gen_event {
($list:expr,$event:expr) => {
$list.push(CountedEvent {
id: $list.len(),
event: $event,
})
};
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct GameState { pub struct GameState {
deck: VecDeque<Uuid>, deck: VecDeque<Uuid>,
@ -76,7 +85,7 @@ pub struct GameState {
shadow_realm: Vec<Uuid>, shadow_realm: Vec<Uuid>,
play: HashMap<Uuid, InPlay>, play: HashMap<Uuid, InPlay>,
hands: Vec<Hand>, hands: Vec<Hand>,
life_totals: Vec<i32>, life_totals: Vec<isize>,
turn_player: Player, turn_player: Player,
events: Vec<CountedEvent>, events: Vec<CountedEvent>,
} }
@ -87,7 +96,7 @@ pub struct OnePlayerGameState {
shadow_realm: Vec<Uuid>, shadow_realm: Vec<Uuid>,
play: Vec<InPlay>, play: Vec<InPlay>,
hand: Vec<Uuid>, hand: Vec<Uuid>,
life_totals: Vec<i32>, life_totals: Vec<isize>,
turn_player: Player, turn_player: Player,
opponent_cards_in_hand: usize, opponent_cards_in_hand: usize,
you: Player, you: Player,
@ -150,21 +159,21 @@ pub fn new() -> GameState {
} }
} }
pub fn draw(game_state: &mut GameState, count: usize, player: Player) { pub fn draw(game_state: &mut GameState, count: usize, player: Player) -> Result<(), String> {
let player_hand = match player { let player_hand = match player {
Player::A => &mut game_state.hands[0], Player::A => &mut game_state.hands[0],
Player::B => &mut game_state.hands[1], Player::B => &mut game_state.hands[1],
}; };
game_state.events.push(CountedEvent { let remaining_cards =
id: game_state.events.len(), std::cmp::max(0, game_state.deck.len() as isize - count as isize) as usize;
event: Event::Draw(player.clone(), count.clone()), gen_event!(
}); game_state.events,
player_hand.cards.extend_from_slice( Event::Draw(player.clone(), count.clone())
game_state
.deck
.split_off(game_state.deck.len() - count)
.make_contiguous(),
); );
player_hand
.cards
.extend_from_slice(game_state.deck.split_off(remaining_cards).make_contiguous());
Ok(())
} }
pub fn yoink(game_state: &mut GameState, deck_index: usize, player: Player) -> Result<(), String> { pub fn yoink(game_state: &mut GameState, deck_index: usize, player: Player) -> Result<(), String> {
@ -172,10 +181,7 @@ pub fn yoink(game_state: &mut GameState, deck_index: usize, player: Player) -> R
Player::A => &mut game_state.hands[0], Player::A => &mut game_state.hands[0],
Player::B => &mut game_state.hands[1], Player::B => &mut game_state.hands[1],
}; };
game_state.events.push(CountedEvent { gen_event!(game_state.events, Event::Yoink(player.clone()));
id: game_state.events.len(),
event: Event::Yoink(player.clone()),
});
match game_state.deck.remove(deck_index) { match game_state.deck.remove(deck_index) {
Some(card) => Ok(player_hand.cards.push(card)), Some(card) => Ok(player_hand.cards.push(card)),
None => Err(format!("Yoink index out of bounds: {}", deck_index)), None => Err(format!("Yoink index out of bounds: {}", deck_index)),
@ -196,10 +202,7 @@ pub fn yoink_mill(
)) ))
} }
}; };
game_state.events.push(CountedEvent { gen_event!(game_state.events, Event::YoinkMill(card.clone()));
id: game_state.events.len(),
event: Event::YoinkMill(card.clone()),
});
if shadow { if shadow {
game_state.shadow_realm.push(card); game_state.shadow_realm.push(card);
} else { } else {
@ -209,10 +212,7 @@ pub fn yoink_mill(
} }
pub fn shuffle(game_state: &mut GameState, player: Player) { pub fn shuffle(game_state: &mut GameState, player: Player) {
game_state.events.push(CountedEvent { gen_event!(game_state.events, Event::Shuffle(player));
id: game_state.events.len(),
event: Event::Shuffle(player),
});
game_state.deck.make_contiguous().shuffle(&mut rng()); game_state.deck.make_contiguous().shuffle(&mut rng());
} }
@ -230,22 +230,22 @@ pub fn pass(game_state: &mut GameState) {
Player::A => Player::B, Player::A => Player::B,
Player::B => Player::A, Player::B => Player::A,
}; };
game_state.events.push(CountedEvent { gen_event!(
id: game_state.events.len(), game_state.events,
event: Event::Pass(*current_player, new_player.clone()), Event::Pass(*current_player, new_player.clone())
}); );
game_state.turn_player = new_player; game_state.turn_player = new_player;
} }
pub fn change_life(game_state: &mut GameState, diff: i32, player: Player) { pub fn change_life(game_state: &mut GameState, diff: isize, player: Player) {
let mut player_life = match player { let mut player_life = match player {
Player::A => game_state.life_totals[0].clone(), Player::A => game_state.life_totals[0].clone(),
Player::B => game_state.life_totals[1].clone(), Player::B => game_state.life_totals[1].clone(),
}; };
game_state.events.push(CountedEvent { gen_event!(
id: game_state.events.len(), game_state.events,
event: Event::ChangeLifeTotal(player, player_life.clone(), player_life.clone() + diff), Event::ChangeLifeTotal(player, player_life.clone(), player_life.clone() + diff)
}); );
player_life += diff; player_life += diff;
match player { match player {
Player::A => game_state.life_totals[0] = player_life, Player::A => game_state.life_totals[0] = player_life,
@ -253,21 +253,28 @@ pub fn change_life(game_state: &mut GameState, diff: i32, player: Player) {
}; };
} }
pub fn fade_from_hand(game_state: &mut GameState, hand_index: usize, player: Player, bottom: bool) { pub fn fade_from_hand(
game_state: &mut GameState,
hand_index: usize,
player: Player,
bottom: bool,
) -> Result<(), String> {
let player_hand = match player { let player_hand = match player {
Player::A => &mut game_state.hands[0], Player::A => &mut game_state.hands[0],
Player::B => &mut game_state.hands[1], Player::B => &mut game_state.hands[1],
}; };
game_state.events.push(CountedEvent { gen_event!(game_state.events, Event::FadeFromHand(player.clone()));
id: game_state.events.len(),
event: Event::FadeFromHand(player.clone()), if None == player_hand.cards.get(hand_index) {
}); return Err(format!("Fade index out of bounds: {}", hand_index));
}
let card = player_hand.cards.remove(hand_index); let card = player_hand.cards.remove(hand_index);
if bottom { if bottom {
game_state.deck.push_front(card); game_state.deck.push_front(card);
} else { } else {
game_state.deck.push_back(card); game_state.deck.push_back(card);
} }
Ok(())
} }
pub fn play_from_hand( pub fn play_from_hand(
@ -279,12 +286,9 @@ pub fn play_from_hand(
Player::A => &mut game_state.hands[0], Player::A => &mut game_state.hands[0],
Player::B => &mut game_state.hands[1], Player::B => &mut game_state.hands[1],
}; };
game_state.events.push(CountedEvent { gen_event!(game_state.events, Event::PlayFromHand(player.clone()));
id: game_state.events.len(),
event: Event::PlayFromHand(player.clone()),
});
if None == player_hand.cards.get(hand_index) { if None == player_hand.cards.get(hand_index) {
return Err(format!("Yoink index out of bounds: {}", hand_index)); return Err(format!("Play index out of bounds: {}", hand_index));
} }
let card = player_hand.cards.remove(hand_index); let card = player_hand.cards.remove(hand_index);
let play_uuid = Uuid::new_v4(); let play_uuid = Uuid::new_v4();
@ -311,18 +315,12 @@ pub fn bounce(game_state: &mut GameState, play_id: Uuid) -> Result<(), String> {
Player::A => &mut game_state.hands[0], Player::A => &mut game_state.hands[0],
Player::B => &mut game_state.hands[1], Player::B => &mut game_state.hands[1],
}; };
game_state.events.push(CountedEvent { gen_event!(game_state.events, Event::Bounce(played_card.owner));
id: game_state.events.len(),
event: Event::Bounce(played_card.owner),
});
Ok(player_hand.cards.push(played_card.id)) Ok(player_hand.cards.push(played_card.id))
} }
pub fn tap(game_state: &mut GameState, play_id: Uuid) -> Result<(), String> { pub fn tap(game_state: &mut GameState, play_id: Uuid) -> Result<(), String> {
game_state.events.push(CountedEvent { gen_event!(game_state.events, Event::Tap(play_id.clone()));
id: game_state.events.len(),
event: Event::Tap(play_id.clone()),
});
match game_state.play.get_mut(&play_id) { match game_state.play.get_mut(&play_id) {
Some(played_card) => { Some(played_card) => {
played_card.tapped = !played_card.tapped; played_card.tapped = !played_card.tapped;
@ -338,6 +336,7 @@ pub fn move_played_card(
position_x: u8, position_x: u8,
position_y: u8, position_y: u8,
) -> Result<(), String> { ) -> Result<(), String> {
// no event made, intentionally
match game_state.play.get_mut(&play_id) { match game_state.play.get_mut(&play_id) {
Some(played_card) => { Some(played_card) => {
played_card.position_x = position_x; played_card.position_x = position_x;
@ -348,64 +347,94 @@ pub fn move_played_card(
} }
} }
pub fn discard(game_state: &mut GameState, hand_index: usize, player: Player, shadow: bool) { pub fn discard(
game_state: &mut GameState,
hand_index: usize,
player: Player,
shadow: bool,
) -> Result<(), String> {
let player_hand = match player { let player_hand = match player {
Player::A => &mut game_state.hands[0], Player::A => &mut game_state.hands[0],
Player::B => &mut game_state.hands[1], Player::B => &mut game_state.hands[1],
}; };
game_state.events.push(CountedEvent { gen_event!(game_state.events, Event::Discard(player.clone()));
id: game_state.events.len(), if None == player_hand.cards.get(hand_index) {
event: Event::Discard(player.clone()), return Err(format!("Discard index out of bounds: {}", hand_index));
}); }
let card = player_hand.cards.remove(hand_index); let card = player_hand.cards.remove(hand_index);
if shadow { if shadow {
game_state.shadow_realm.push(card); game_state.shadow_realm.push(card);
} else { } else {
game_state.discard_pile.push(card); game_state.discard_pile.push(card);
} }
Ok(())
} }
pub fn undiscard(game_state: &mut GameState, pile_index: usize, player: Player, shadow: bool) { pub fn undiscard(
game_state: &mut GameState,
pile_index: usize,
player: Player,
shadow: bool,
) -> Result<(), String> {
let player_hand = match player { let player_hand = match player {
Player::A => &mut game_state.hands[0], Player::A => &mut game_state.hands[0],
Player::B => &mut game_state.hands[1], Player::B => &mut game_state.hands[1],
}; };
game_state.events.push(CountedEvent { let pile = if shadow {
id: game_state.events.len(), &mut game_state.shadow_realm
event: Event::Undiscard(player.clone()),
});
let card = if shadow {
game_state.shadow_realm.remove(pile_index)
} else { } else {
game_state.discard_pile.remove(pile_index) &mut game_state.discard_pile
}; };
player_hand.cards.push(card); if None == pile.get(pile_index) {
return Err(format!("Discard index out of bounds: {}", pile_index));
}
gen_event!(game_state.events, Event::Undiscard(player.clone()));
player_hand.cards.push(pile.remove(pile_index));
Ok(())
} }
pub fn kill(game_state: &mut GameState, play_id: Uuid, shadow: bool) { pub fn kill(game_state: &mut GameState, play_id: Uuid, shadow: bool) -> Result<(), String> {
let played_card = game_state.play.remove(&play_id).unwrap(); let played_card = match game_state.play.remove(&play_id) {
game_state.events.push(CountedEvent { Some(played_card) => played_card,
id: game_state.events.len(), None => return Err(format!("Nonexistant play id: {}", play_id)),
event: Event::Kill(played_card.id.clone(), shadow), };
}); gen_event!(
game_state.events,
Event::Kill(played_card.id.clone(), shadow)
);
if shadow { if shadow {
game_state.shadow_realm.push(played_card.id); game_state.shadow_realm.push(played_card.id);
} else { } else {
game_state.discard_pile.push(played_card.id); game_state.discard_pile.push(played_card.id);
} }
Ok(())
} }
pub fn unkill(game_state: &mut GameState, player: Player, pile_index: usize, shadow: bool) { pub fn unkill(
let card = if shadow { game_state: &mut GameState,
game_state.shadow_realm.remove(pile_index) player: Player,
pile_index: usize,
shadow: bool,
) -> Result<(), String> {
let pile = if shadow {
&mut game_state.shadow_realm
} else { } else {
game_state.discard_pile.remove(pile_index) &mut game_state.discard_pile
}; };
if None == pile.get(pile_index) {
let pile_name = if shadow {
"shadow realm"
} else {
"discard pile"
};
return Err(format!(
"Transfer index out of bounds: {} ({})",
pile_index, pile_name
));
}
let card = pile.remove(pile_index);
gen_event!(game_state.events, Event::Unkill(card, shadow));
let play_uuid = Uuid::new_v4(); let play_uuid = Uuid::new_v4();
game_state.events.push(CountedEvent {
id: game_state.events.len(),
event: Event::Unkill(card, shadow),
});
game_state.play.insert( game_state.play.insert(
play_uuid, play_uuid,
InPlay { InPlay {
@ -417,31 +446,43 @@ pub fn unkill(game_state: &mut GameState, player: Player, pile_index: usize, sha
play_id: play_uuid, play_id: play_uuid,
}, },
); );
Ok(())
} }
pub fn transfer_dead_card(game_state: &mut GameState, pile_index: usize, shadow_to_discard: bool) { pub fn transfer_dead_card(
let card_id = if shadow_to_discard { game_state: &mut GameState,
let card = game_state.shadow_realm.remove(pile_index); pile_index: usize,
let ret = card.clone(); shadow_to_discard: bool,
game_state.discard_pile.push(card); ) -> Result<(), String> {
ret let (source, target) = if shadow_to_discard {
(&mut game_state.shadow_realm, &mut game_state.discard_pile)
} else { } else {
let card = game_state.discard_pile.remove(pile_index); (&mut game_state.discard_pile, &mut game_state.shadow_realm)
let ret = card.clone();
game_state.shadow_realm.push(card);
ret
}; };
game_state.events.push(CountedEvent {
id: game_state.events.len(), if pile_index >= source.len() {
event: Event::TransferDeadCard(card_id, shadow_to_discard), let direction = if shadow_to_discard {
}); "shadow realm -> discard pile"
} else {
"discard pile -> shadow realm"
};
return Err(format!(
"Transfer index out of bounds: {} ({})",
pile_index, direction
));
}
let card = source.remove(pile_index);
let card_id = card.clone();
gen_event!(
game_state.events,
Event::TransferDeadCard(card_id, shadow_to_discard)
);
target.push(card);
Ok(())
} }
pub fn untap_all(game_state: &mut GameState, player: Player) { pub fn untap_all(game_state: &mut GameState, player: Player) {
game_state.events.push(CountedEvent { gen_event!(game_state.events, Event::UntapAll(player));
id: game_state.events.len(),
event: Event::UntapAll(player),
});
for (_, card) in game_state.play.iter_mut() { for (_, card) in game_state.play.iter_mut() {
if card.owner == player { if card.owner == player {
card.tapped = false; card.tapped = false;
@ -450,10 +491,7 @@ pub fn untap_all(game_state: &mut GameState, player: Player) {
} }
pub fn get_deck(game_state: &mut GameState, player: Player) -> String { pub fn get_deck(game_state: &mut GameState, player: Player) -> String {
game_state.events.push(CountedEvent { gen_event!(game_state.events, Event::ViewDeck(player));
id: game_state.events.len(),
event: Event::ViewDeck(player),
});
let deck_copy = game_state.deck.clone(); let deck_copy = game_state.deck.clone();
serde_json::to_string(&deck_copy).unwrap() serde_json::to_string(&deck_copy).unwrap()
} }

View File

@ -39,10 +39,16 @@ macro_rules! get_player {
}; };
} }
macro_rules! respond_ok {
() => {
(Status::Ok, (ContentType::Plain, "Ok!".to_string()))
};
}
macro_rules! respond { macro_rules! respond {
($state:expr) => { ($state:expr) => {
match $state { match $state {
Ok(()) => (Status::Ok, (ContentType::Plain, "Ok!".to_string())), Ok(()) => respond_ok!(),
Err(err_string) => (Status::BadRequest, (ContentType::Plain, err_string)), Err(err_string) => (Status::BadRequest, (ContentType::Plain, err_string)),
} }
}; };
@ -67,7 +73,7 @@ fn index(player_uuids: &State<PlayerUuids>) -> content::RawHtml<String> {
content::RawHtml(format!( content::RawHtml(format!(
"<a href=\"/{}/\">/{}</a><br /><a href=\"/{}/\">/{}</a>", "<a href=\"/{}/\">/{}</a><br /><a href=\"/{}/\">/{}</a>",
player_uuids.a, player_uuids.a, player_uuids.b, player_uuids.b player_uuids.a, player_uuids.a, player_uuids.b, player_uuids.b
)) ))
} }
#[get("/get_events")] #[get("/get_events")]
@ -84,7 +90,8 @@ fn shuffle(
) -> (Status, (ContentType, String)) { ) -> (Status, (ContentType, String)) {
let player = get_player!(player_uuids, uuid); let player = get_player!(player_uuids, uuid);
unlock_state_mut!(game_state_arc, mutex, game_state); unlock_state_mut!(game_state_arc, mutex, game_state);
respond!(game::shuffle(&mut game_state, player.clone())) game::shuffle(&mut game_state, player.clone());
respond_ok!()
} }
#[post("/<uuid>/pass")] #[post("/<uuid>/pass")]
@ -95,7 +102,8 @@ fn pass(
) -> (Status, (ContentType, String)) { ) -> (Status, (ContentType, String)) {
assert_player!(player_uuids, uuid); assert_player!(player_uuids, uuid);
unlock_state_mut!(game_state_arc, mutex, game_state); unlock_state_mut!(game_state_arc, mutex, game_state);
respond!(game::pass(&mut game_state)) game::pass(&mut game_state);
respond_ok!()
} }
#[post("/<uuid>/bounce/<play_id>")] #[post("/<uuid>/bounce/<play_id>")]
@ -322,10 +330,13 @@ fn get_state(
) -> (Status, (ContentType, String)) { ) -> (Status, (ContentType, String)) {
let player = get_player!(player_uuids, uuid); let player = get_player!(player_uuids, uuid);
unlock_state!(game_state_arc, mutex, game_state); unlock_state!(game_state_arc, mutex, game_state);
(Status::Ok, (ContentType::JSON, format!( (
"{}", Status::Ok,
game::get_game_one_player(&game_state, player.clone()) (
))) ContentType::JSON,
format!("{}", game::get_game_one_player(&game_state, player.clone())),
),
)
} }
#[post("/<uuid>/get_deck")] #[post("/<uuid>/get_deck")]
@ -336,10 +347,13 @@ fn get_deck(
) -> (Status, (ContentType, String)) { ) -> (Status, (ContentType, String)) {
let player = get_player!(player_uuids, uuid); let player = get_player!(player_uuids, uuid);
unlock_state_mut!(game_state_arc, mutex, game_state); unlock_state_mut!(game_state_arc, mutex, game_state);
(Status::Ok, (ContentType::JSON, format!( (
"{}", Status::Ok,
game::get_deck(&mut game_state, player.clone()) (
))) ContentType::JSON,
format!("{}", game::get_deck(&mut game_state, player.clone())),
),
)
} }
#[post("/<uuid>/untap_all")] #[post("/<uuid>/untap_all")]
@ -350,7 +364,8 @@ fn untap_all(
) -> (Status, (ContentType, String)) { ) -> (Status, (ContentType, String)) {
let player = get_player!(player_uuids, uuid); let player = get_player!(player_uuids, uuid);
unlock_state_mut!(game_state_arc, mutex, game_state); unlock_state_mut!(game_state_arc, mutex, game_state);
respond!(game::untap_all(&mut game_state, player.clone())) game::untap_all(&mut game_state, player.clone());
respond_ok!()
} }
#[post("/<uuid>/draw/<count>")] #[post("/<uuid>/draw/<count>")]
@ -402,13 +417,14 @@ fn fade_bottom(
#[post("/<uuid>/life/<count>")] #[post("/<uuid>/life/<count>")]
fn life( fn life(
uuid: Uuid, uuid: Uuid,
count: i32, count: isize,
game_state_arc: &State<ArcMutexGameState>, game_state_arc: &State<ArcMutexGameState>,
player_uuids: &State<PlayerUuids>, player_uuids: &State<PlayerUuids>,
) -> (Status, (ContentType, String)) { ) -> (Status, (ContentType, String)) {
let player = get_player!(player_uuids, uuid); let player = get_player!(player_uuids, uuid);
unlock_state_mut!(game_state_arc, mutex, game_state); unlock_state_mut!(game_state_arc, mutex, game_state);
respond!(game::change_life(&mut game_state, count, player.clone())) game::change_life(&mut game_state, count, player.clone());
respond_ok!()
} }
struct ArcMutexGameState { struct ArcMutexGameState {
@ -427,13 +443,12 @@ fn rocket() -> _ {
let game_state_arc = Arc::new(Mutex::new(game_state)); let game_state_arc = Arc::new(Mutex::new(game_state));
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
let a_uuid: Uuid = uuid!("9b0a2a95-72a9-4e03-930e-a9583d2a2a5a"); let (a_uuid, b_uuid) = (
uuid!("9b0a2a95-72a9-4e03-930e-a9583d2a2a5a"),
uuid!("2efc0332-975d-4f71-9dd0-ffc9213098a5"),
);
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
let a_uuid: Uuid = Uuid::new_v4(); let (a_uuid, b_uuid) = (Uuid::new_v4(), Uuid::new_v4());
#[cfg(debug_assertions)]
let b_uuid: Uuid = uuid!("2efc0332-975d-4f71-9dd0-ffc9213098a5");
#[cfg(not(debug_assertions))]
let b_uuid: Uuid = Uuid::new_v4();
let uuid_map = HashMap::from([(a_uuid, Player::A), (b_uuid, Player::B)]); let uuid_map = HashMap::from([(a_uuid, Player::A), (b_uuid, Player::B)]);
println!("A: {}", a_uuid); println!("A: {}", a_uuid);