Got refactor to compile⚙️
This commit is contained in:
242
src/game.rs
242
src/game.rs
@ -47,7 +47,7 @@ enum Event {
|
||||
Shuffle(Player),
|
||||
Draw(Player, usize),
|
||||
Pass(Player, Player),
|
||||
ChangeLifeTotal(Player, i32, i32),
|
||||
ChangeLifeTotal(Player, isize, isize),
|
||||
FadeFromHand(Player),
|
||||
PlayFromHand(Player),
|
||||
Bounce(Player),
|
||||
@ -69,6 +69,15 @@ struct CountedEvent {
|
||||
event: Event,
|
||||
}
|
||||
|
||||
macro_rules! gen_event {
|
||||
($list:expr,$event:expr) => {
|
||||
$list.push(CountedEvent {
|
||||
id: $list.len(),
|
||||
event: $event,
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct GameState {
|
||||
deck: VecDeque<Uuid>,
|
||||
@ -76,7 +85,7 @@ pub struct GameState {
|
||||
shadow_realm: Vec<Uuid>,
|
||||
play: HashMap<Uuid, InPlay>,
|
||||
hands: Vec<Hand>,
|
||||
life_totals: Vec<i32>,
|
||||
life_totals: Vec<isize>,
|
||||
turn_player: Player,
|
||||
events: Vec<CountedEvent>,
|
||||
}
|
||||
@ -87,7 +96,7 @@ pub struct OnePlayerGameState {
|
||||
shadow_realm: Vec<Uuid>,
|
||||
play: Vec<InPlay>,
|
||||
hand: Vec<Uuid>,
|
||||
life_totals: Vec<i32>,
|
||||
life_totals: Vec<isize>,
|
||||
turn_player: Player,
|
||||
opponent_cards_in_hand: usize,
|
||||
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 {
|
||||
Player::A => &mut game_state.hands[0],
|
||||
Player::B => &mut game_state.hands[1],
|
||||
};
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::Draw(player.clone(), count.clone()),
|
||||
});
|
||||
player_hand.cards.extend_from_slice(
|
||||
game_state
|
||||
.deck
|
||||
.split_off(game_state.deck.len() - count)
|
||||
.make_contiguous(),
|
||||
let remaining_cards =
|
||||
std::cmp::max(0, game_state.deck.len() as isize - count as isize) as usize;
|
||||
gen_event!(
|
||||
game_state.events,
|
||||
Event::Draw(player.clone(), count.clone())
|
||||
);
|
||||
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> {
|
||||
@ -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::B => &mut game_state.hands[1],
|
||||
};
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::Yoink(player.clone()),
|
||||
});
|
||||
gen_event!(game_state.events, Event::Yoink(player.clone()));
|
||||
match game_state.deck.remove(deck_index) {
|
||||
Some(card) => Ok(player_hand.cards.push(card)),
|
||||
None => Err(format!("Yoink index out of bounds: {}", deck_index)),
|
||||
@ -196,10 +202,7 @@ pub fn yoink_mill(
|
||||
))
|
||||
}
|
||||
};
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::YoinkMill(card.clone()),
|
||||
});
|
||||
gen_event!(game_state.events, Event::YoinkMill(card.clone()));
|
||||
if shadow {
|
||||
game_state.shadow_realm.push(card);
|
||||
} else {
|
||||
@ -209,10 +212,7 @@ pub fn yoink_mill(
|
||||
}
|
||||
|
||||
pub fn shuffle(game_state: &mut GameState, player: Player) {
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::Shuffle(player),
|
||||
});
|
||||
gen_event!(game_state.events, Event::Shuffle(player));
|
||||
game_state.deck.make_contiguous().shuffle(&mut rng());
|
||||
}
|
||||
|
||||
@ -230,22 +230,22 @@ pub fn pass(game_state: &mut GameState) {
|
||||
Player::A => Player::B,
|
||||
Player::B => Player::A,
|
||||
};
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::Pass(*current_player, new_player.clone()),
|
||||
});
|
||||
gen_event!(
|
||||
game_state.events,
|
||||
Event::Pass(*current_player, new_player.clone())
|
||||
);
|
||||
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 {
|
||||
Player::A => game_state.life_totals[0].clone(),
|
||||
Player::B => game_state.life_totals[1].clone(),
|
||||
};
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::ChangeLifeTotal(player, player_life.clone(), player_life.clone() + diff),
|
||||
});
|
||||
gen_event!(
|
||||
game_state.events,
|
||||
Event::ChangeLifeTotal(player, player_life.clone(), player_life.clone() + diff)
|
||||
);
|
||||
player_life += diff;
|
||||
match player {
|
||||
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 {
|
||||
Player::A => &mut game_state.hands[0],
|
||||
Player::B => &mut game_state.hands[1],
|
||||
};
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::FadeFromHand(player.clone()),
|
||||
});
|
||||
gen_event!(game_state.events, 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);
|
||||
if bottom {
|
||||
game_state.deck.push_front(card);
|
||||
} else {
|
||||
game_state.deck.push_back(card);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn play_from_hand(
|
||||
@ -279,12 +286,9 @@ pub fn play_from_hand(
|
||||
Player::A => &mut game_state.hands[0],
|
||||
Player::B => &mut game_state.hands[1],
|
||||
};
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::PlayFromHand(player.clone()),
|
||||
});
|
||||
gen_event!(game_state.events, Event::PlayFromHand(player.clone()));
|
||||
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 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::B => &mut game_state.hands[1],
|
||||
};
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::Bounce(played_card.owner),
|
||||
});
|
||||
gen_event!(game_state.events, Event::Bounce(played_card.owner));
|
||||
Ok(player_hand.cards.push(played_card.id))
|
||||
}
|
||||
|
||||
pub fn tap(game_state: &mut GameState, play_id: Uuid) -> Result<(), String> {
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::Tap(play_id.clone()),
|
||||
});
|
||||
gen_event!(game_state.events, Event::Tap(play_id.clone()));
|
||||
match game_state.play.get_mut(&play_id) {
|
||||
Some(played_card) => {
|
||||
played_card.tapped = !played_card.tapped;
|
||||
@ -338,6 +336,7 @@ pub fn move_played_card(
|
||||
position_x: u8,
|
||||
position_y: u8,
|
||||
) -> Result<(), String> {
|
||||
// no event made, intentionally
|
||||
match game_state.play.get_mut(&play_id) {
|
||||
Some(played_card) => {
|
||||
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 {
|
||||
Player::A => &mut game_state.hands[0],
|
||||
Player::B => &mut game_state.hands[1],
|
||||
};
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::Discard(player.clone()),
|
||||
});
|
||||
gen_event!(game_state.events, Event::Discard(player.clone()));
|
||||
if None == player_hand.cards.get(hand_index) {
|
||||
return Err(format!("Discard index out of bounds: {}", hand_index));
|
||||
}
|
||||
let card = player_hand.cards.remove(hand_index);
|
||||
if shadow {
|
||||
game_state.shadow_realm.push(card);
|
||||
} else {
|
||||
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 {
|
||||
Player::A => &mut game_state.hands[0],
|
||||
Player::B => &mut game_state.hands[1],
|
||||
};
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::Undiscard(player.clone()),
|
||||
});
|
||||
let card = if shadow {
|
||||
game_state.shadow_realm.remove(pile_index)
|
||||
let pile = if shadow {
|
||||
&mut game_state.shadow_realm
|
||||
} 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) {
|
||||
let played_card = game_state.play.remove(&play_id).unwrap();
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::Kill(played_card.id.clone(), shadow),
|
||||
});
|
||||
pub fn kill(game_state: &mut GameState, play_id: Uuid, shadow: bool) -> Result<(), String> {
|
||||
let played_card = match game_state.play.remove(&play_id) {
|
||||
Some(played_card) => played_card,
|
||||
None => return Err(format!("Nonexistant play id: {}", play_id)),
|
||||
};
|
||||
gen_event!(
|
||||
game_state.events,
|
||||
Event::Kill(played_card.id.clone(), shadow)
|
||||
);
|
||||
if shadow {
|
||||
game_state.shadow_realm.push(played_card.id);
|
||||
} else {
|
||||
game_state.discard_pile.push(played_card.id);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unkill(game_state: &mut GameState, player: Player, pile_index: usize, shadow: bool) {
|
||||
let card = if shadow {
|
||||
game_state.shadow_realm.remove(pile_index)
|
||||
pub fn unkill(
|
||||
game_state: &mut GameState,
|
||||
player: Player,
|
||||
pile_index: usize,
|
||||
shadow: bool,
|
||||
) -> Result<(), String> {
|
||||
let pile = if shadow {
|
||||
&mut game_state.shadow_realm
|
||||
} 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();
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::Unkill(card, shadow),
|
||||
});
|
||||
game_state.play.insert(
|
||||
play_uuid,
|
||||
InPlay {
|
||||
@ -417,31 +446,43 @@ pub fn unkill(game_state: &mut GameState, player: Player, pile_index: usize, sha
|
||||
play_id: play_uuid,
|
||||
},
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn transfer_dead_card(game_state: &mut GameState, pile_index: usize, shadow_to_discard: bool) {
|
||||
let card_id = if shadow_to_discard {
|
||||
let card = game_state.shadow_realm.remove(pile_index);
|
||||
let ret = card.clone();
|
||||
game_state.discard_pile.push(card);
|
||||
ret
|
||||
pub fn transfer_dead_card(
|
||||
game_state: &mut GameState,
|
||||
pile_index: usize,
|
||||
shadow_to_discard: bool,
|
||||
) -> Result<(), String> {
|
||||
let (source, target) = if shadow_to_discard {
|
||||
(&mut game_state.shadow_realm, &mut game_state.discard_pile)
|
||||
} else {
|
||||
let card = game_state.discard_pile.remove(pile_index);
|
||||
let ret = card.clone();
|
||||
game_state.shadow_realm.push(card);
|
||||
ret
|
||||
(&mut game_state.discard_pile, &mut game_state.shadow_realm)
|
||||
};
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::TransferDeadCard(card_id, shadow_to_discard),
|
||||
});
|
||||
|
||||
if pile_index >= source.len() {
|
||||
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) {
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::UntapAll(player),
|
||||
});
|
||||
gen_event!(game_state.events, Event::UntapAll(player));
|
||||
for (_, card) in game_state.play.iter_mut() {
|
||||
if card.owner == player {
|
||||
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 {
|
||||
game_state.events.push(CountedEvent {
|
||||
id: game_state.events.len(),
|
||||
event: Event::ViewDeck(player),
|
||||
});
|
||||
gen_event!(game_state.events, Event::ViewDeck(player));
|
||||
let deck_copy = game_state.deck.clone();
|
||||
serde_json::to_string(&deck_copy).unwrap()
|
||||
}
|
||||
|
||||
55
src/main.rs
55
src/main.rs
@ -39,10 +39,16 @@ macro_rules! get_player {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! respond_ok {
|
||||
() => {
|
||||
(Status::Ok, (ContentType::Plain, "Ok!".to_string()))
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! respond {
|
||||
($state:expr) => {
|
||||
match $state {
|
||||
Ok(()) => (Status::Ok, (ContentType::Plain, "Ok!".to_string())),
|
||||
Ok(()) => respond_ok!(),
|
||||
Err(err_string) => (Status::BadRequest, (ContentType::Plain, err_string)),
|
||||
}
|
||||
};
|
||||
@ -84,7 +90,8 @@ fn shuffle(
|
||||
) -> (Status, (ContentType, String)) {
|
||||
let player = get_player!(player_uuids, uuid);
|
||||
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")]
|
||||
@ -95,7 +102,8 @@ fn pass(
|
||||
) -> (Status, (ContentType, String)) {
|
||||
assert_player!(player_uuids, uuid);
|
||||
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>")]
|
||||
@ -322,10 +330,13 @@ fn get_state(
|
||||
) -> (Status, (ContentType, String)) {
|
||||
let player = get_player!(player_uuids, uuid);
|
||||
unlock_state!(game_state_arc, mutex, game_state);
|
||||
(Status::Ok, (ContentType::JSON, format!(
|
||||
"{}",
|
||||
game::get_game_one_player(&game_state, player.clone())
|
||||
)))
|
||||
(
|
||||
Status::Ok,
|
||||
(
|
||||
ContentType::JSON,
|
||||
format!("{}", game::get_game_one_player(&game_state, player.clone())),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[post("/<uuid>/get_deck")]
|
||||
@ -336,10 +347,13 @@ fn get_deck(
|
||||
) -> (Status, (ContentType, String)) {
|
||||
let player = get_player!(player_uuids, uuid);
|
||||
unlock_state_mut!(game_state_arc, mutex, game_state);
|
||||
(Status::Ok, (ContentType::JSON, format!(
|
||||
"{}",
|
||||
game::get_deck(&mut game_state, player.clone())
|
||||
)))
|
||||
(
|
||||
Status::Ok,
|
||||
(
|
||||
ContentType::JSON,
|
||||
format!("{}", game::get_deck(&mut game_state, player.clone())),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[post("/<uuid>/untap_all")]
|
||||
@ -350,7 +364,8 @@ fn untap_all(
|
||||
) -> (Status, (ContentType, String)) {
|
||||
let player = get_player!(player_uuids, uuid);
|
||||
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>")]
|
||||
@ -402,13 +417,14 @@ fn fade_bottom(
|
||||
#[post("/<uuid>/life/<count>")]
|
||||
fn life(
|
||||
uuid: Uuid,
|
||||
count: i32,
|
||||
count: isize,
|
||||
game_state_arc: &State<ArcMutexGameState>,
|
||||
player_uuids: &State<PlayerUuids>,
|
||||
) -> (Status, (ContentType, String)) {
|
||||
let player = get_player!(player_uuids, uuid);
|
||||
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 {
|
||||
@ -427,13 +443,12 @@ fn rocket() -> _ {
|
||||
let game_state_arc = Arc::new(Mutex::new(game_state));
|
||||
|
||||
#[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))]
|
||||
let a_uuid: Uuid = 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 (a_uuid, b_uuid) = (Uuid::new_v4(), Uuid::new_v4());
|
||||
|
||||
let uuid_map = HashMap::from([(a_uuid, Player::A), (b_uuid, Player::B)]);
|
||||
println!("A: {}", a_uuid);
|
||||
|
||||
Reference in New Issue
Block a user