@@ 40,6 40,8 @@ pub enum Command {
Draw { amount: usize },
/// discard card from hand in slot N
Discard { index: usize },
+ /// end the targets turn
+ EndTurn { },
/// change player state to another
ChangePlayerState { state: PlayerState },
}
@@ 7,12 7,32 @@
*/
use std::collections::HashMap;
+
use fastrand::Rng;
use crate::{api::game::{Action, Command, Game}, game_status::SupplyPile};
use super::{GameStatus, PlayerState, PlayerStatus, Card};
+/// funny unsafe wrapper
+fn get_invoker_target<'a, K, V>(
+ players: &'a mut HashMap<K, V>,
+ invoker: &K,
+ target: &K
+) -> (&'a mut V, Option<&'a mut V>)
+where
+ K: Eq + std::hash::Hash,
+{
+ if invoker == target {
+ return (players.get_mut(invoker).unwrap(), None);
+ }
+ unsafe {
+ let invoker_ref = players.get_mut(invoker).unwrap() as *mut _;
+ let target_ref = players.get_mut(target).unwrap() as *mut _;
+ (&mut *invoker_ref, Some(&mut *target_ref))
+ }
+}
+
pub fn parse(game: &Game) -> Result<GameStatus, ()> {
let mut game_status = GameStatus {
actions: game.actions.as_ref().unwrap().to_vec(),
@@ 41,13 61,9 @@ pub fn parse(game: &Game) -> Result<GameStatus, ()> {
// TODO: a system for reparsing if needed, e.g. after something
// modifies the actions Vector.
for action in &game_status.actions {
- // the one who invoked the action
- let invoker = game_status.players.get_mut(&action.invoker)
- .unwrap_or_else(|| unreachable!());
-
- // the one who the action affects, may also be the invoker, e.g. draw
- let target = game_status.players.get_mut(&action.target)
- .unwrap_or_else(|| unreachable!());
+ // invoker: the one who invoked the action
+ // target: the one who the action affects, may also be the invoker, e.g. draw
+ let (invoker, target) = get_invoker_target(&mut game_status.players, &action.invoker, &action.target);
match &action.command {
Command::InitSupplyPile { card, amount } => {
@@ 85,6 101,20 @@ pub fn parse(game: &Game) -> Result<GameStatus, ()> {
assert!(*index <= target.hand.len());
target.discard.push(target.hand.remove(*index));
}
+ Command::EndTurn { } => {
+ // NOTE: target will be the next player
+
+ // set player to idle
+ invoker.state = PlayerState::Idle;
+
+ // set the target to action phase
+ target.state = PlayerState::ActionPhase;
+
+ // clear currency
+ invoker.currency = 0;
+
+ // other?
+ }
Command::ChangePlayerState { state } => {
target.state = *state;
}