pub use crate::card::Card;
pub use crate::cardinal::Point;
pub use crate::grid::Grid;
pub use crate::misc::{LayeredEffect, Phase, Zone};
pub use crate::player::Player;
pub use crate::usize_wrapper::{CardID, DeckID, GridID, IDCounter, PlayerID};
use rand::seq::SliceRandom;
use rand::Rng;
use std::collections::{BTreeMap, VecDeque};
use std::fmt::Debug;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)]
pub struct Deck<DeckType> {
id: DeckID,
deck_type: DeckType,
cards: Vec<CardID>,
owner: Option<PlayerID>,
}
impl<DeckType> Deck<DeckType>
where
DeckType: Clone + Eq,
{
pub fn id(&self) -> DeckID {
self.id
}
pub fn size(&self) -> usize {
self.cards.len()
}
pub fn top(&self) -> Option<CardID> {
self.cards.last().cloned()
}
pub fn deck_type(&self) -> DeckType {
self.deck_type.clone()
}
pub fn owner(&self) -> Option<PlayerID> {
self.owner
}
pub fn all(&self) -> &[CardID] {
&self.cards
}
pub(super) fn new(id: DeckID, deck_type: DeckType, owner: Option<PlayerID>) -> Deck<DeckType> {
Deck {
id,
owner,
deck_type,
cards: Vec::new(),
}
}
pub fn draw(&mut self) -> Option<CardID> {
self.cards.pop()
}
pub fn remove_card_from_deck(&mut self, card: CardID) {
self.cards.retain(|a| *a != card);
}
pub fn put_card_on_top(&mut self, card: CardID) {
self.cards.push(card);
}
pub fn put_card_on_bottom(&mut self, card: CardID) {
self.cards.insert(0, card);
}
pub fn shuffle<R: SliceRandom + Rng>(&mut self, rng: &mut R) {
self.cards.shuffle(rng);
}
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Default)]
pub struct TBG<Msg, Event, Trigger, Effect, EffectLayer, AttName, DeckType, CardType, PhaseType>
where
AttName: Ord,
Effect: Eq,
EffectLayer: Ord,
Event: Eq,
DeckType: Eq,
PhaseType: Default + Eq,
{
messages: VecDeque<Msg>,
events: VecDeque<Event>,
triggers: VecDeque<Trigger>,
effects: Vec<LayeredEffect<Effect, EffectLayer>>,
phase: Phase<PhaseType>,
decks: BTreeMap<DeckID, Deck<DeckType>>,
cards: BTreeMap<CardID, Card<CardType, AttName>>,
players: BTreeMap<PlayerID, Player<AttName>>,
grids: BTreeMap<GridID, Grid<Option<CardID>>>,
deck_ids: IDCounter<DeckID>,
grid_ids: IDCounter<GridID>,
card_ids: IDCounter<CardID>,
player_ids: IDCounter<PlayerID>,
}
pub trait TurnBasedGame<Trigger, Event, Effect, EffectLayer, Msg> {
fn handle_trigger(&mut self, event: &Event, trigger: &Trigger) -> bool;
fn handle_effect(&mut self, effect: &LayeredEffect<Effect, EffectLayer>);
fn handle_msg(&mut self, msg: &Msg);
}
impl<Msg, Event, Trigger, Effect, EffectLayer, AttName, DeckType, CardType, PhaseType>
TBG<Msg, Event, Trigger, Effect, EffectLayer, AttName, DeckType, CardType, PhaseType>
where
AttName: Ord + Default,
Effect: Eq + Clone,
EffectLayer: Ord + Clone,
Event: Eq,
DeckType: Eq + Copy + Clone + Debug,
PhaseType: Default + Eq,
Trigger: Clone,
Self: TurnBasedGame<Trigger, Event, Effect, EffectLayer, Msg>,
{
pub fn add_trigger(&mut self, trigger: Trigger) {
self.triggers.push_back(trigger);
}
pub fn add_event(&mut self, event: Event) {
self.events.push_back(event);
}
pub fn add_effect(&mut self, effect: LayeredEffect<Effect, EffectLayer>) {
self.effects.push(effect);
self.effects.sort_by(|a, b| a.layer.cmp(&b.layer));
}
pub fn create_player(&mut self, name: String) -> &mut Player<AttName> {
let id = self.player_ids.increment();
self.players.insert(id, Player::new(id, name));
self.players.get_mut(&id).unwrap()
}
pub fn create_card(
&mut self,
card_type: CardType,
owner: Option<PlayerID>,
) -> &mut Card<CardType, AttName> {
let id = self.card_ids.increment();
let card = Card::new(id, card_type, owner);
self.cards.insert(id, card);
self.cards.get_mut(&id).unwrap()
}
pub fn create_deck(
&mut self,
deck_type: DeckType,
owner: Option<PlayerID>,
) -> &mut Deck<DeckType> {
let id = self.deck_ids.increment();
self.decks.insert(id, Deck::new(id, deck_type, owner));
self.decks.get_mut(&id).unwrap()
}
pub fn create_grid(
&mut self,
w: usize,
h: usize,
init: Option<CardID>,
) -> &mut Grid<Option<CardID>> {
let id = self.grid_ids.increment();
self.grids.insert(id, Grid::new(w, h, init));
self.grids.get_mut(&id).unwrap()
}
pub fn get_player_deck(
&self,
player: PlayerID,
deck_type: DeckType,
) -> Option<&Deck<DeckType>> {
self.decks
.iter()
.find(|(_, deck)| deck.deck_type() == deck_type && deck.owner() == Some(player))
.map(|(_, deck)| deck)
}
pub fn move_card(&mut self, card_id: CardID, zone: Zone) {
if let Some(card) = self.cards.get_mut(&card_id) {
if card.zone == zone {
return;
}
match card.zone {
Zone::Deck(deck_id) => {
if let Some(deck) = self.decks.get_mut(&deck_id) {
deck.remove_card_from_deck(card.id());
}
}
Zone::Grid(grid_id, a, b) => {
self.grids.get_mut(&grid_id).map(|g| g.set_area(a, b, None));
}
Zone::Nowhere => (),
}
match zone {
Zone::Deck(deck_id) => {
if let Some(deck) = self.decks.get_mut(&deck_id) {
deck.put_card_on_bottom(card.id());
}
}
Zone::Grid(grid_id, a, b) => {
self.grids
.get_mut(&grid_id)
.map(|g| g.set_area(a, b, Some(card_id)));
}
Zone::Nowhere => (),
}
card.zone = zone.clone();
}
}
pub fn move_card_to_player_deck(
&mut self,
card_id: CardID,
player_id: PlayerID,
deck_type: DeckType,
) {
if let Some(deck) = self.get_player_deck(player_id, deck_type).map(|a| a.id()) {
self.move_card(card_id, Zone::Deck(deck));
} else {
panic!(
"DeckType {:?} did not exist for player {:?}",
deck_type, player_id
);
}
}
pub fn move_card_to_grid(&mut self, card_id: CardID, grid_id: GridID, a: Point, b: Point) {
self.move_card(card_id, Zone::Grid(grid_id, a, b));
}
pub fn get_card_deck(&self, card_id: CardID) -> Option<&Deck<DeckType>> {
self.cards.get(&card_id).and_then(|card| {
if let Zone::Deck(deck_id) = card.zone {
self.decks.get(&deck_id)
} else {
None
}
})
}
pub fn get_card_deck_mut(&mut self, card_id: CardID) -> Option<&mut Deck<DeckType>> {
if let Some(card) = self.cards.get(&card_id) {
if let Zone::Deck(deck_id) = card.zone {
self.decks.get_mut(&deck_id)
} else {
None
}
} else {
None
}
}
pub fn get_card_owner(&self, card_id: CardID) -> Option<PlayerID> {
self.cards.get(&card_id).map(|card| card.owner()).flatten()
}
pub fn get_card_controller(&self, card_id: CardID) -> Option<PlayerID> {
self.get_card_deck(card_id)
.map(|deck| deck.owner())
.flatten()
}
pub fn get_player_deck_mut(
&mut self,
player: PlayerID,
deck_type: DeckType,
) -> Option<&mut Deck<DeckType>> {
self.decks
.values_mut()
.find(|deck| deck.deck_type() == deck_type && deck.owner() == Some(player))
}
pub fn set_phase(&mut self, phase_type: PhaseType, time_limit: usize, player: PlayerID) {
self.phase = Phase::new(phase_type, time_limit, player);
}
pub fn step(&mut self) {
while let Some(msg) = self.messages.pop_front() {
self.handle_msg(&msg);
}
while let Some(event) = self.events.pop_front() {
let mut deletes = Vec::new();
let triggers = self.triggers.clone();
triggers.iter().enumerate().for_each(|(ix, trigger)| {
if self.handle_trigger(&event, &trigger) {
deletes.push(ix);
}
self.effects.clone().iter().for_each(|effect| {
self.handle_effect(&effect);
});
});
self.triggers = triggers
.iter()
.enumerate()
.filter_map(|(ix, a)| {
if deletes.contains(&ix) {
None
} else {
Some(a.clone())
}
})
.collect();
}
}
}