Simplified dealing logic so we always have one set

main
Elijah Voigt 1 year ago
parent e1d438a189
commit 83c15f7c64

1
Cargo.lock generated

@ -3564,6 +3564,7 @@ name = "set"
version = "0.1.0"
dependencies = [
"bevy",
"rand",
"wasm-bindgen",
]

@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
wasm-bindgen = { version = "= 0.2.95" }
bevy = "0.15"
rand = "0.8.5"
[profile.dev]
opt-level = 1

@ -52,16 +52,16 @@ impl Deck {
}
pub(crate) fn shuffled() -> Vec<Card> {
let rs = RandomState::new();
let mut base = Self::cards();
let len = base.len();
(1..len).into_iter().for_each(|i| {
let a = rs.hash_one(base[i]) % (len as u64);
let b = rs.hash_one(base[i - 1]) % (len as u64);
if a > b {
base.swap(a as usize, b as usize);
{
use rand::seq::SliceRandom;
use rand::thread_rng;
let mut rng = thread_rng();
base.as_mut_slice().shuffle(&mut rng);
}
});
base
}

@ -6,9 +6,11 @@ pub struct PlayPlugin;
impl Plugin for PlayPlugin {
fn build(&self, app: &mut App) {
app.add_observer(serve_new_cards)
.add_systems(OnEnter(GameState::Main), serve_cards)
.add_systems(Update, rotate_cards);
app.add_event::<ServeCards>()
.add_observer(serve_cards)
.add_observer(fill_cards)
.add_systems(OnEnter(GameState::Main), deal_table)
.add_systems(Update, spin_cards);
}
}
@ -32,7 +34,7 @@ pub(crate) struct PlayLocation {
pub(crate) struct SetNumber(pub u8);
/// Debug system rotating selected cards for visual flare
fn rotate_cards(mut query: Query<&mut Transform, (With<Card>, With<Selected>)>, time: Res<Time>) {
fn spin_cards(mut query: Query<&mut Transform, (With<Card>, With<Selected>)>, time: Res<Time>) {
let dt = time.delta().as_secs_f32();
query.iter_mut().for_each(|mut t| {
t.rotate_z(dt * 0.5);
@ -116,12 +118,17 @@ fn is_set((a, b, c): (&Card, &Card, &Card)) -> bool {
color && number && pattern && shape
}
#[derive(Event, Clone)]
struct ServeCards;
/// When requested, fill in empty spots on the board with cards
fn serve_cards(
_trigger: Trigger<ServeCards>,
cards: Query<(Entity, &DeckOrder)>,
spots: Query<&PlayLocation>,
mut commands: Commands,
) {
info!("Serving cards");
let mut target = (cards.iter().len() - 1) as u8;
// Iterate over every x, y play location
for this_x in 0..=3 {
@ -148,36 +155,16 @@ fn serve_cards(
}
}
fn serve_new_cards(
_trigger: Trigger<OnAdd, SetNumber>,
cards: Query<(Entity, &DeckOrder)>,
spots: Query<&PlayLocation>,
mut commands: Commands,
) {
let mut target = (cards.iter().len() - 1) as u8;
// Iterate over every x, y play location
for this_x in 0..=3 {
for this_y in 0..=3 {
// If this spot does not have a card
if spots
.iter()
.find(|PlayLocation { x, y }| *x == (this_x as u8) && *y == (this_y as u8))
.is_none()
{
if let Some((e, _)) = cards.iter().find(|(_, deck_order)| deck_order.0 == target) {
// Set the selected card to this play location and remove from the deck
commands
.entity(e)
.remove::<DeckOrder>()
.insert(PlayLocation {
x: this_x,
y: this_y,
});
target = target - 1;
}
}
}
/// Trigger dealing cards when the game starts
fn deal_table(mut commands: Commands) {
info!("Dealing table");
commands.trigger(ServeCards);
}
/// Trigger serving cards when a new set is created
fn fill_cards(_trigger: Trigger<OnAdd, SetNumber>, mut commands: Commands) {
info!("Filling cards");
commands.trigger(ServeCards);
}
/// When a card is added to the board, place it on the screen
@ -207,7 +194,7 @@ pub(crate) fn check_for_sets(
selected: Query<Entity, With<Selected>>,
mut commands: Commands,
) {
cards
let candidate = cards
// Iterate over all combinations of cards on the board
.iter_combinations()
// Only find combinations including currently selected cards
@ -237,17 +224,19 @@ pub(crate) fn check_for_sets(
} else {
None
}
})
.iter()
.for_each(|(a, b, c)| {
if !selected.contains(*a) {
commands.entity(*a).insert(Selected);
} else if !selected.contains(*b) {
commands.entity(*b).insert(Selected);
} else if !selected.contains(*c) {
commands.entity(*c).insert(Selected);
});
if let Some((a, b, c)) = candidate {
if !selected.contains(a) {
commands.entity(a).insert(Selected);
} else if !selected.contains(b) {
commands.entity(b).insert(Selected);
} else if !selected.contains(c) {
commands.entity(c).insert(Selected);
} else {
info!("I cannot hold your hand further...");
}
});
} else {
info!("No sets!");
}
}

@ -1,20 +1,10 @@
TODO:
* Reset game (click new game button)
* Track score (number of sets)
* Make button(s) look pretty
* Make buttons react to hover/click!
* Music!
* Background!
* Print "no set"/"too many cards" messages
* Add "quit game" button
* View all cards with some indication of in-set
* Menu
* About/Credits
* How To Play
Exclude for now:
* deck
* sets
* "New Game" button
* Print "no set"/"too many cards" alert
* Guarentee there is always a set
* Better shuffling
Exclude in wasm:
* quit
Later:
* View all cards with some indication of in-set
* Music!
* Make button(s) look pretty

Loading…
Cancel
Save