use crate::messages::message_protocol::ActionMessage;
use crate::{Money, Value};
use crate::{animals::Animal, player::base_player::PlayerId};
use pyo3::prelude::*;
use serde::{Deserialize, Serialize};
use tracing::error;
pub trait FromActionMessage: Sized {
fn extract(action: ActionMessage) -> Option<Self>;
}
#[pyclass()]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum NoAction {
Ok(),
}
impl FromActionMessage for NoAction {
fn extract(action: ActionMessage) -> Option<Self> {
match action {
ActionMessage::NoAction { decision } => Some(decision),
_ => {
error!("Expected ActionMessage::NoAction");
None
}
}
}
}
#[pyclass()]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub enum PlayerTurnDecision {
Draw(),
Trade(InitialTrade),
}
impl FromActionMessage for PlayerTurnDecision {
fn extract(action: ActionMessage) -> Option<Self> {
match action {
ActionMessage::PlayerTurnDecision { decision } => Some(decision),
_ => {
error!("Expected ActionMessage::PlayerTurnDecision");
None
}
}
}
}
#[pymethods]
impl PlayerTurnDecision {
#[getter]
fn initial_trade(&self) -> PyResult<Option<InitialTrade>> {
match self {
PlayerTurnDecision::Trade(it) => Ok(Some(it.clone())),
_ => Ok(None),
}
}
}
#[pyclass()]
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct InitialTrade {
#[pyo3(get)]
pub opponent: PlayerId,
#[pyo3(get)]
pub animal: Animal,
#[pyo3(get)]
pub animal_count: usize,
#[pyo3(get)]
pub amount: Vec<Money>,
}
impl PartialEq for InitialTrade {
fn eq(&self, other: &Self) -> bool {
let same_player = self.opponent == other.opponent;
let same_animal = self.animal == other.animal;
let same_count = self.animal_count == other.animal_count;
let same_amount;
let other_has_zero = other.amount.len() == 0 || other.amount.iter().all(|&x| x == 0);
let self_has_zero = self.amount.len() == 0 || self.amount.iter().all(|&x| x == 0);
if self_has_zero {
same_amount = other_has_zero;
} else {
same_amount = self.amount == other.amount
}
return same_player && same_animal && same_count && same_amount;
}
}
#[pymethods]
impl InitialTrade {
#[new]
fn new(opponent: PlayerId, animal: Animal, animal_count: usize, amount: Vec<Money>) -> Self {
InitialTrade {
opponent,
animal,
animal_count,
amount,
}
}
}
impl FromActionMessage for InitialTrade {
fn extract(action: ActionMessage) -> Option<Self> {
match action {
ActionMessage::InitialTrade { decision } => Some(decision),
_ => {
error!("Expected ActionMessage::InitialTrade");
None
}
}
}
}
#[pyclass()]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum AuctionDecision {
Buy(),
Sell(),
}
impl FromActionMessage for AuctionDecision {
fn extract(action: ActionMessage) -> Option<Self> {
match action {
ActionMessage::AuctionDecision { decision } => Some(decision),
_ => {
error!("Expected ActionMessage::AuctionDecision");
None
}
}
}
}
#[pyclass()]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum TradeOpponentDecision {
Accept(),
CounterOffer(Vec<Money>),
}
impl FromActionMessage for TradeOpponentDecision {
fn extract(action: ActionMessage) -> Option<Self> {
match action {
ActionMessage::TradeOpponentDecision { decision } => Some(decision),
_ => {
error!("Expected ActionMessage::TradeOpponentDecision");
None
}
}
}
}
#[pymethods]
impl TradeOpponentDecision {
#[getter]
fn money_list(&self) -> PyResult<Option<Vec<Money>>> {
match self {
TradeOpponentDecision::CounterOffer(m) => Ok(Some(m.clone())),
_ => Ok(None),
}
}
}
#[pyclass()]
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum SendMoney {
WasBluff(),
Amount(Vec<Money>),
}
impl PartialEq for SendMoney {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(SendMoney::WasBluff(), SendMoney::WasBluff()) => true,
(SendMoney::WasBluff(), SendMoney::Amount(a)) => a.iter().sum::<usize>() == 0,
(SendMoney::Amount(a), SendMoney::WasBluff()) => a.iter().sum::<usize>() == 0,
(SendMoney::Amount(a), SendMoney::Amount(b)) => a == b,
}
}
}
#[pymethods]
impl SendMoney {
#[getter]
fn money_list(&self) -> PyResult<Option<Vec<Money>>> {
match self {
SendMoney::Amount(money_list) => Ok(Some(money_list.clone())),
_ => Ok(None),
}
}
}
impl FromActionMessage for SendMoney {
fn extract(action: ActionMessage) -> Option<Self> {
match action {
ActionMessage::SendMoney { decision } => Some(decision),
_ => {
error!("Expected ActionMessage::SendMoney");
None
}
}
}
}
#[pyclass()]
#[derive(Serialize, Deserialize, Debug, Clone, Eq)]
pub enum Bidding {
Pass(),
Bid(Value),
}
#[pymethods]
impl Bidding {
#[getter]
fn money_list(&self) -> PyResult<Option<Value>> {
match self {
Bidding::Bid(val) => Ok(Some(val.clone())),
_ => Ok(None),
}
}
}
impl PartialEq for Bidding {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Bidding::Pass(), Bidding::Pass()) => true,
(Bidding::Pass(), _) => false,
(_, Bidding::Pass()) => false,
(Bidding::Bid(a), Bidding::Bid(b)) => a == b,
}
}
}
impl Ord for Bidding {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match (self, other) {
(Bidding::Pass(), Bidding::Pass()) => std::cmp::Ordering::Equal,
(Bidding::Pass(), _) => std::cmp::Ordering::Less,
(_, Bidding::Pass()) => std::cmp::Ordering::Greater,
(Bidding::Bid(a), Bidding::Bid(b)) => a.cmp(b),
}
}
}
impl PartialOrd for Bidding {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl FromActionMessage for Bidding {
fn extract(action: ActionMessage) -> Option<Self> {
match action {
ActionMessage::Bidding { decision } => Some(decision),
_ => {
error!("Expected ActionMessage::Bidding");
None
}
}
}
}