politburo/src/cards.rs

198 lines
5.4 KiB
Rust
Raw Normal View History

2024-04-09 08:04:10 -04:00
use std::{borrow::Cow, fmt::Display};
2024-03-10 20:27:00 -04:00
2024-03-13 08:30:41 -04:00
use serde::Deserialize;
2024-03-10 20:27:00 -04:00
use yoke::Yokeable;
use super::player::Position;
2024-03-10 20:52:44 -04:00
/// A card in a players deck which can apply an effect
/// to the game or advance a solution
2024-04-09 08:04:10 -04:00
#[derive(Default, Deserialize, Yokeable)]
#[serde(default)]
2024-03-10 20:27:00 -04:00
pub struct ActionCard<'a> {
/// How much influence the card will cost to play
influence: i32,
2024-04-09 08:04:10 -04:00
/// The effects the card will have on the game once it's played
effects: Vec<Effect>,
2024-03-10 20:27:00 -04:00
/// The image on the card
image: Cow<'a, str>,
/// A description of what the card does
description: Cow<'a, str>,
2024-04-09 08:04:10 -04:00
/// The name of the card
name: Cow<'a, str>,
/// The position that this card can exclusively be used by
position: Option<Position>,
/// The maximum number of times this card can be drawn
draw_limit: u32,
}
impl<'a> Display for ActionCard<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for effect in &self.effects {
write!(f, "{} ", effect)?;
}
if self.draw_limit > 0 {
write!(
f,
"This card can only ever be drawn {} times.",
self.draw_limit
)?;
}
Ok(())
}
2024-03-10 20:27:00 -04:00
}
/// A card which must be solved by someone on the politburo
2024-04-09 08:04:10 -04:00
#[derive(Default, Deserialize)]
#[serde(default)]
2024-03-10 20:27:00 -04:00
pub struct SituationCard<'a> {
/// Points associated with the card
points: i32,
/// Solving this card benefits the player in this position
2024-04-09 08:04:10 -04:00
benefactor: Vec<Position>,
2024-03-10 20:27:00 -04:00
/// The image on the card
image: Cow<'a, str>,
/// The name of the card
name: Cow<'a, str>,
/// A description of the situation the card entails
description: Cow<'a, str>,
}
2024-04-09 08:04:10 -04:00
#[derive(Deserialize)]
2024-03-10 20:27:00 -04:00
pub enum CardType {
/// A card which can be used by anyone
General,
/// A card which can only be used by the given
/// poisition
Position(Position),
}
2024-04-09 08:04:10 -04:00
#[derive(Deserialize, Default)]
pub enum Effect {
PublicOpinion {
/// How much public opinion changes
magnitude: i32,
/// If the affector of this card is chosen by it's player
position_choosable: bool,
},
SolutionTrack {
magnitude: i32,
yours: bool,
},
DrawCard {
number: i32,
position_specific: bool,
},
OpposingCards {
number: i32,
position: Option<Position>,
},
InfluenceGain {
magnitude: i32,
},
#[default]
Custom,
}
impl Display for Effect {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Effect::PublicOpinion {
magnitude,
position_choosable,
} => {
if *magnitude < 0 {
write!(f, "Decrease ")?;
} else {
write!(f, "Increase ")?;
}
if *position_choosable {
write!(f, "the public opinion of a player you chose ")?;
} else {
write!(f, "your public opinion ")?;
}
write!(f, "by {}.", magnitude.abs())?;
if *position_choosable {
write!(
f,
" This player is chosen after it is determined that this card passes."
)
} else {
Ok(())
}
}
Effect::SolutionTrack { magnitude, yours } => {
write!(f, "Move ")?;
if *magnitude < 0 {
write!(f, "down ")?;
} else {
write!(f, "up ")?;
}
if *yours {
write!(f, "your solution track ")?;
} else {
write!(f, "a solution track of your choice ")?;
}
write!(f, "by {}.", magnitude.abs())
}
Effect::DrawCard {
number,
position_specific,
} => {
if *number < 0 {
write!(f, "Discard ")?;
} else {
write!(f, "Draw ")?;
}
write!(f, "{} ", number.abs())?;
if *position_specific {
write!(f, "position specific ")?;
}
if number.abs() <= 1 {
write!(f, "card.")
} else {
write!(f, "cards.")
}
}
Effect::InfluenceGain { magnitude } => {
if *magnitude < 0 {
write!(f, "Decrease ")?;
} else {
write!(f, "Increase ")?;
}
write!(f, "your influence gain by {}.", magnitude.abs())
}
Effect::OpposingCards { number, position } => {
if let Some(pos) = position {
write!(f, "The {} ", pos)?;
} else {
write!(f, "A player of your choice ")?;
}
write!(f, "must ")?;
if *number < 0 {
write!(f, "discard ")?;
} else {
write!(f, "draw ")?;
}
write!(f, "{} cards.", number.abs())
}
Effect::Custom => Ok(()),
}
}
2024-03-13 08:30:41 -04:00
}