diff --git a/README.md b/README.md index 5828fef..775d0f1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,11 @@ definitely not a shameless untap clone # todo + Add drag-and-drop from hand and piles -+ Add hotkeys for every zone ++ Add hotkeys for every zone (Almost done!) + Add untap all hotkey + Add viewing top of deck ++ Add score values (usable for life counters) + +# maybe todo ++ Make deck information, piles, and score info json-configurable + Use cookies instead of hardcoded url uuid diff --git a/src/game.rs b/src/game.rs index bebcc48..f994b27 100644 --- a/src/game.rs +++ b/src/game.rs @@ -53,8 +53,10 @@ enum Event { Bounce(Player), Tap(Uuid), Discard(Player), + Undiscard(Player), Kill(Uuid, bool), Unkill(Uuid, bool), + TransferDeadCard(Uuid, bool) } #[derive(Serialize, Clone, Debug)] @@ -298,6 +300,23 @@ pub fn discard(game_state: &mut GameState, hand_index: usize, player: Player, sh } } +pub fn undiscard(game_state: &mut GameState, pile_index: usize, player: Player, shadow: bool) { + 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) + } else { + game_state.discard_pile.remove(pile_index) + }; + player_hand.cards.push(card); +} + 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 { @@ -334,3 +353,21 @@ pub fn unkill(game_state: &mut GameState, player: Player, pile_index: usize, sha }, ); } + +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 + } else { + let card = game_state.discard_pile.remove(pile_index); + let ret = card.clone(); + game_state.shadow_realm.push(card); + ret + }; + game_state.events.push(CountedEvent { + id: game_state.events.len(), + event: Event::TransferDeadCard(card_id, shadow_to_discard), + }); +} diff --git a/src/main.rs b/src/main.rs index b52eea0..53eccda 100644 --- a/src/main.rs +++ b/src/main.rs @@ -230,6 +230,74 @@ fn banish( Ok(format!("{}", game::get_events(&game_state))) } +#[get("//unshadow/")] +fn unshadow( + uuid: Uuid, + index: usize, + game_state_arc: &State, + player_uuids: &State, +) -> Result> { + match player_uuids.map.get(&uuid) { + Some(_) => (), + None => return Err(BadRequest(format!("Invalid player {}.", uuid))), + }; + let game_state_mutex = Arc::clone(&game_state_arc.state); + let mut game_state = game_state_mutex.lock().unwrap(); + game::transfer_dead_card(&mut game_state, index, true); + Ok(format!("{}", game::get_events(&game_state))) +} + +#[get("//undiscard/")] +fn undiscard( + uuid: Uuid, + index: usize, + game_state_arc: &State, + player_uuids: &State, +) -> Result> { + let player = match player_uuids.map.get(&uuid) { + Some(player) => player, + None => return Err(BadRequest(format!("Invalid player {}.", uuid))), + }; + let game_state_mutex = Arc::clone(&game_state_arc.state); + let mut game_state = game_state_mutex.lock().unwrap(); + game::undiscard(&mut game_state, index, player.clone(), false); + Ok(format!("{}", game::get_events(&game_state))) +} + +#[get("//remember/")] +fn remember( + uuid: Uuid, + index: usize, + game_state_arc: &State, + player_uuids: &State, +) -> Result> { + let player = match player_uuids.map.get(&uuid) { + Some(player) => player, + None => return Err(BadRequest(format!("Invalid player {}.", uuid))), + }; + let game_state_mutex = Arc::clone(&game_state_arc.state); + let mut game_state = game_state_mutex.lock().unwrap(); + game::undiscard(&mut game_state, index, player.clone(), true); + Ok(format!("{}", game::get_events(&game_state))) +} + +#[get("//shadow/")] +fn shadow( + uuid: Uuid, + index: usize, + game_state_arc: &State, + player_uuids: &State, +) -> Result> { + match player_uuids.map.get(&uuid) { + Some(_) => (), + None => return Err(BadRequest(format!("Invalid player {}.", uuid))), + }; + let game_state_mutex = Arc::clone(&game_state_arc.state); + let mut game_state = game_state_mutex.lock().unwrap(); + game::transfer_dead_card(&mut game_state, index, false); + Ok(format!("{}", game::get_events(&game_state))) +} + #[get("//get_state")] fn get_state( uuid: Uuid, @@ -389,7 +457,11 @@ fn rocket() -> _ { forget, banish, unkill, - unbanish + unbanish, + shadow, + unshadow, + undiscard, + remember, ], ) .manage(ArcMutexGameState { diff --git a/web/src/script.ls b/web/src/script.ls index 038d7a9..358bd7a 100644 --- a/web/src/script.ls +++ b/web/src/script.ls @@ -264,18 +264,53 @@ | \r => if $current-mouse-node?.has-attribute \data-play-id fetch-log "./bounce/#{$current-mouse-node.get-attribute \data-play-id}" + else if $current-mouse-node?.has-attribute \data-list-type + switch $current-mouse-node.get-attribute \data-list-type + | \discard + fetch-log "./undiscard/#{$current-mouse-node.get-attribute \data-index}" + | \deck + void #fetch-log "./unshadow/#{$current-mouse-node.get-attribute \data-index}" + | \shadow + fetch-log "./remember/#{$current-mouse-node.get-attribute \data-index}" + $current-mouse-node.parent-element.remove-child $current-mouse-node + if !$extra.child-element-count + $extra.class-list.add \hidden + $extra.remove-attribute \data-pile-type | \d => if $current-mouse-node?.has-attribute \data-hand-index fetch-log "./discard/#{$current-mouse-node.get-attribute \data-hand-index}" else if $current-mouse-node?.has-attribute \data-play-id fetch-log "./kill/#{$current-mouse-node.get-attribute \data-play-id}" + else if $current-mouse-node?.has-attribute \data-list-type + switch $current-mouse-node.get-attribute \data-list-type + | \discard + return #fetch-log "./unkill/#{$current-mouse-node.get-attribute \data-index}" + | \deck + void #fetch-log "./unkill/#{$current-mouse-node.get-attribute \data-index}" + | \shadow + fetch-log "./unshadow/#{$current-mouse-node.get-attribute \data-index}" + $current-mouse-node.parent-element.remove-child $current-mouse-node + if !$extra.child-element-count + $extra.class-list.add \hidden + $extra.remove-attribute \data-pile-type | \s => if $current-mouse-node?.has-attribute \data-hand-index fetch-log "./forget/#{$current-mouse-node.get-attribute \data-hand-index}" else if $current-mouse-node?.has-attribute \data-play-id fetch-log "./banish/#{$current-mouse-node.get-attribute \data-play-id}" + else if $current-mouse-node?.has-attribute \data-list-type + switch $current-mouse-node.get-attribute \data-list-type + | \discard + fetch-log "./shadow/#{$current-mouse-node.get-attribute \data-index}" + | \deck + void #fetch-log "./unbanish/#{$current-mouse-node.get-attribute \data-index}" + | \shadow + return #fetch-log "./unshadow/#{$current-mouse-node.get-attribute \data-index}" + $current-mouse-node.parent-element.remove-child $current-mouse-node + if !$extra.child-element-count + $extra.class-list.add \hidden + $extra.remove-attribute \data-pile-type | \q => $extra.class-list.add \hidden $extra.remove-attribute \data-pile-type - )! diff --git a/web/src/style.scss b/web/src/style.scss index 8b9914a..aa34275 100644 --- a/web/src/style.scss +++ b/web/src/style.scss @@ -49,7 +49,7 @@ main { #extra { transition: height 0.5s; - overflow: hidden; + overflow: auto; background-color: #222d; }