1use std::{error::Error, fmt::Display};
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
4pub enum PlayError {
5 OutOfBounds,
6 AlreadyOccupied,
7 NoCapstone,
8 NoStones,
9 OpeningNonFlat,
10 EmptySquare,
11 StackNotOwned,
12 StackError(StackError),
13 TakeError(TakeError),
14 SpreadOutOfBounds,
15 GameOver,
16}
17
18impl Display for PlayError {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 if let Self::StackError(stack_error) = self {
21 stack_error.fmt(f)
22 } else if let Self::TakeError(take_error) = self {
23 take_error.fmt(f)
24 } else {
25 match self {
26 Self::OutOfBounds => "given square is not on the board",
27 Self::AlreadyOccupied => {
28 "cannot place a piece in that position because it is already occupied"
29 }
30 Self::NoCapstone => "there is not a capstone left to play",
31 Self::NoStones => "there are no more stones left to play",
32 Self::OpeningNonFlat => "cannot play a wall or capstone on the first two plies",
33 Self::EmptySquare => "cannot move from an empty square",
34 Self::StackNotOwned => "cannot move a stack that you do not own",
35 Self::SpreadOutOfBounds => "spread would leave the board",
36 Self::GameOver => "cannot play a move after the game is over",
37 Self::StackError(_) | Self::TakeError(_) => unreachable!(),
38 }
39 .fmt(f)
40 }
41 }
42}
43
44impl Error for PlayError {}
45
46impl From<TakeError> for PlayError {
47 fn from(e: TakeError) -> Self {
48 Self::TakeError(e)
49 }
50}
51
52impl From<StackError> for PlayError {
53 fn from(e: StackError) -> Self {
54 Self::StackError(e)
55 }
56}
57
58#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
59pub enum StackError {
60 Wall,
61 Cap,
62}
63
64impl Display for StackError {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 match self {
67 Self::Cap => "cannot stack on top of a capstone",
68 Self::Wall => "can only flatten a wall with a capstone",
69 }
70 .fmt(f)
71 }
72}
73
74impl Error for StackError {}
75
76#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
77pub enum TakeError {
78 Zero,
79 CarryLimit,
80 StackSize,
81}
82
83impl Display for TakeError {
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 match self {
86 Self::Zero => "cannot take 0 from a stack",
87 Self::CarryLimit => "cannot take more than the carry limit",
88 Self::StackSize => "cannot take more pieces than there are on the stack",
89 }
90 .fmt(f)
91 }
92}
93
94impl Error for TakeError {}