Refactor KlondikeInstruction (#4)
Fixes #2 Reviewed-on: #4 Co-authored-by: Rhys Lloyd <krakow20@gmail.com> Co-committed-by: Rhys Lloyd <krakow20@gmail.com>
This commit was merged in pull request #4.
This commit is contained in:
+281
-311
@@ -9,9 +9,8 @@ impl Default for KlondikeConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
pub enum KlondikePileId {
|
pub enum Tableau {
|
||||||
Tableau1,
|
Tableau1,
|
||||||
Tableau2,
|
Tableau2,
|
||||||
Tableau3,
|
Tableau3,
|
||||||
@@ -19,15 +18,11 @@ pub enum KlondikePileId {
|
|||||||
Tableau5,
|
Tableau5,
|
||||||
Tableau6,
|
Tableau6,
|
||||||
Tableau7,
|
Tableau7,
|
||||||
Foundation1,
|
|
||||||
Foundation2,
|
|
||||||
Foundation3,
|
|
||||||
Foundation4,
|
|
||||||
Stock,
|
|
||||||
}
|
}
|
||||||
impl KlondikePileId {
|
impl Tableau {
|
||||||
|
const ITER_BEGIN: Self = Self::Tableau1;
|
||||||
const fn next(self) -> Option<Self> {
|
const fn next(self) -> Option<Self> {
|
||||||
use KlondikePileId::*;
|
use Tableau::*;
|
||||||
Some(match self {
|
Some(match self {
|
||||||
Tableau1 => Tableau2,
|
Tableau1 => Tableau2,
|
||||||
Tableau2 => Tableau3,
|
Tableau2 => Tableau3,
|
||||||
@@ -35,229 +30,228 @@ impl KlondikePileId {
|
|||||||
Tableau4 => Tableau5,
|
Tableau4 => Tableau5,
|
||||||
Tableau5 => Tableau6,
|
Tableau5 => Tableau6,
|
||||||
Tableau6 => Tableau7,
|
Tableau6 => Tableau7,
|
||||||
Tableau7 => Foundation1,
|
Tableau7 => return None,
|
||||||
Foundation1 => Foundation2,
|
|
||||||
Foundation2 => Foundation3,
|
|
||||||
Foundation3 => Foundation4,
|
|
||||||
Foundation4 => Stock,
|
|
||||||
Stock => return None,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// high four bits for stack depth, low four bits for Pile Id
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
pub struct InstructionSrc(u8);
|
pub enum Foundation {
|
||||||
impl InstructionSrc {
|
Foundation1,
|
||||||
const STOCK: Self = InstructionSrc::new(KlondikePileStack::Stock);
|
Foundation2,
|
||||||
pub const fn new(src: KlondikePileStack) -> Self {
|
Foundation3,
|
||||||
match src {
|
Foundation4,
|
||||||
KlondikePileStack::Tableau1(skip_cards) => {
|
}
|
||||||
Self(KlondikePileId::Tableau1 as u8 + ((skip_cards as u8) << 4))
|
impl Foundation {
|
||||||
}
|
const ITER_BEGIN: Self = Self::Foundation1;
|
||||||
KlondikePileStack::Tableau2(skip_cards) => {
|
|
||||||
Self(KlondikePileId::Tableau2 as u8 + ((skip_cards as u8) << 4))
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau3(skip_cards) => {
|
|
||||||
Self(KlondikePileId::Tableau3 as u8 + ((skip_cards as u8) << 4))
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau4(skip_cards) => {
|
|
||||||
Self(KlondikePileId::Tableau4 as u8 + ((skip_cards as u8) << 4))
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau5(skip_cards) => {
|
|
||||||
Self(KlondikePileId::Tableau5 as u8 + ((skip_cards as u8) << 4))
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau6(skip_cards) => {
|
|
||||||
Self(KlondikePileId::Tableau6 as u8 + ((skip_cards as u8) << 4))
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau7(skip_cards) => {
|
|
||||||
Self(KlondikePileId::Tableau7 as u8 + ((skip_cards as u8) << 4))
|
|
||||||
}
|
|
||||||
KlondikePileStack::Foundation1 => Self(KlondikePileId::Foundation1 as u8),
|
|
||||||
KlondikePileStack::Foundation2 => Self(KlondikePileId::Foundation2 as u8),
|
|
||||||
KlondikePileStack::Foundation3 => Self(KlondikePileId::Foundation3 as u8),
|
|
||||||
KlondikePileStack::Foundation4 => Self(KlondikePileId::Foundation4 as u8),
|
|
||||||
KlondikePileStack::Stock => Self(KlondikePileId::Stock as u8),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const fn into_spec(self) -> KlondikePileStack {
|
|
||||||
// SAFETY: there is no way to construct an invalid InstructionSrc
|
|
||||||
let pile = unsafe { core::mem::transmute(self.0 & 0b1111) };
|
|
||||||
match pile {
|
|
||||||
KlondikePileId::Tableau1 => {
|
|
||||||
KlondikePileStack::Tableau1(unsafe { core::mem::transmute(self.0 >> 4) })
|
|
||||||
}
|
|
||||||
KlondikePileId::Tableau2 => {
|
|
||||||
KlondikePileStack::Tableau2(unsafe { core::mem::transmute(self.0 >> 4) })
|
|
||||||
}
|
|
||||||
KlondikePileId::Tableau3 => {
|
|
||||||
KlondikePileStack::Tableau3(unsafe { core::mem::transmute(self.0 >> 4) })
|
|
||||||
}
|
|
||||||
KlondikePileId::Tableau4 => {
|
|
||||||
KlondikePileStack::Tableau4(unsafe { core::mem::transmute(self.0 >> 4) })
|
|
||||||
}
|
|
||||||
KlondikePileId::Tableau5 => {
|
|
||||||
KlondikePileStack::Tableau5(unsafe { core::mem::transmute(self.0 >> 4) })
|
|
||||||
}
|
|
||||||
KlondikePileId::Tableau6 => {
|
|
||||||
KlondikePileStack::Tableau6(unsafe { core::mem::transmute(self.0 >> 4) })
|
|
||||||
}
|
|
||||||
KlondikePileId::Tableau7 => {
|
|
||||||
KlondikePileStack::Tableau7(unsafe { core::mem::transmute(self.0 >> 4) })
|
|
||||||
}
|
|
||||||
KlondikePileId::Foundation1 => KlondikePileStack::Foundation1,
|
|
||||||
KlondikePileId::Foundation2 => KlondikePileStack::Foundation2,
|
|
||||||
KlondikePileId::Foundation3 => KlondikePileStack::Foundation3,
|
|
||||||
KlondikePileId::Foundation4 => KlondikePileStack::Foundation4,
|
|
||||||
KlondikePileId::Stock => KlondikePileStack::Stock,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const fn next(self) -> Option<Self> {
|
const fn next(self) -> Option<Self> {
|
||||||
match self.into_spec().next() {
|
use Foundation::*;
|
||||||
Some(s) => Some(Self::new(s)),
|
Some(match self {
|
||||||
None => None,
|
Foundation1 => Foundation2,
|
||||||
}
|
Foundation2 => Foundation3,
|
||||||
|
Foundation3 => Foundation4,
|
||||||
|
Foundation4 => return None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<InstructionSrc> for KlondikePileId {
|
|
||||||
fn from(value: InstructionSrc) -> Self {
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
match value.into_spec() {
|
pub enum KlondikePile {
|
||||||
KlondikePileStack::Tableau1(_) => KlondikePileId::Tableau1,
|
Tableau(Tableau),
|
||||||
KlondikePileStack::Tableau2(_) => KlondikePileId::Tableau2,
|
Stock,
|
||||||
KlondikePileStack::Tableau3(_) => KlondikePileId::Tableau3,
|
Foundation(Foundation),
|
||||||
KlondikePileStack::Tableau4(_) => KlondikePileId::Tableau4,
|
}
|
||||||
KlondikePileStack::Tableau5(_) => KlondikePileId::Tableau5,
|
impl KlondikePile {
|
||||||
KlondikePileStack::Tableau6(_) => KlondikePileId::Tableau6,
|
const ITER_BEGIN: Self = Self::Tableau(Tableau::ITER_BEGIN);
|
||||||
KlondikePileStack::Tableau7(_) => KlondikePileId::Tableau7,
|
const fn next(self) -> Option<Self> {
|
||||||
KlondikePileStack::Foundation1 => KlondikePileId::Foundation1,
|
Some(match self {
|
||||||
KlondikePileStack::Foundation2 => KlondikePileId::Foundation2,
|
Self::Tableau(tableau_stack) => match tableau_stack.next() {
|
||||||
KlondikePileStack::Foundation3 => KlondikePileId::Foundation3,
|
Some(tableau_stack) => Self::Tableau(tableau_stack),
|
||||||
KlondikePileStack::Foundation4 => KlondikePileId::Foundation4,
|
None => Self::Stock,
|
||||||
KlondikePileStack::Stock => KlondikePileId::Stock,
|
},
|
||||||
|
Self::Stock => Self::Foundation(Foundation::ITER_BEGIN),
|
||||||
|
Self::Foundation(foundation) => match foundation.next() {
|
||||||
|
Some(foundation) => Self::Foundation(foundation),
|
||||||
|
None => return None,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
impl From<Tableau> for KlondikePile {
|
||||||
|
fn from(value: Tableau) -> Self {
|
||||||
|
KlondikePile::Tableau(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<Foundation> for KlondikePile {
|
||||||
|
fn from(value: Foundation) -> Self {
|
||||||
|
KlondikePile::Foundation(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
pub enum SkipCards {
|
pub enum SkipCards {
|
||||||
Zero,
|
Skip0,
|
||||||
One,
|
Skip1,
|
||||||
Two,
|
Skip2,
|
||||||
Three,
|
Skip3,
|
||||||
Four,
|
Skip4,
|
||||||
Five,
|
Skip5,
|
||||||
Six,
|
Skip6,
|
||||||
Seven,
|
Skip7,
|
||||||
Eight,
|
Skip8,
|
||||||
Nine,
|
Skip9,
|
||||||
Ten,
|
Skip10,
|
||||||
Eleven,
|
Skip11,
|
||||||
Twelve,
|
Skip12,
|
||||||
}
|
}
|
||||||
impl SkipCards {
|
impl SkipCards {
|
||||||
|
const ITER_BEGIN: Self = Self::Skip0;
|
||||||
const fn next(self) -> Option<Self> {
|
const fn next(self) -> Option<Self> {
|
||||||
use SkipCards::*;
|
use SkipCards::*;
|
||||||
Some(match self {
|
Some(match self {
|
||||||
Zero => One,
|
Skip0 => Skip1,
|
||||||
One => Two,
|
Skip1 => Skip2,
|
||||||
Two => Three,
|
Skip2 => Skip3,
|
||||||
Three => Four,
|
Skip3 => Skip4,
|
||||||
Four => Five,
|
Skip4 => Skip5,
|
||||||
Five => Six,
|
Skip5 => Skip6,
|
||||||
Six => Seven,
|
Skip6 => Skip7,
|
||||||
Seven => Eight,
|
Skip7 => Skip8,
|
||||||
Eight => Nine,
|
Skip8 => Skip9,
|
||||||
Nine => Ten,
|
Skip9 => Skip10,
|
||||||
Ten => Eleven,
|
Skip10 => Skip11,
|
||||||
Eleven => Twelve,
|
Skip11 => Skip12,
|
||||||
Twelve => return None,
|
Skip12 => return None,
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
|
||||||
pub enum KlondikePileStack {
|
|
||||||
Tableau1(SkipCards),
|
|
||||||
Tableau2(SkipCards),
|
|
||||||
Tableau3(SkipCards),
|
|
||||||
Tableau4(SkipCards),
|
|
||||||
Tableau5(SkipCards),
|
|
||||||
Tableau6(SkipCards),
|
|
||||||
Tableau7(SkipCards),
|
|
||||||
Foundation1,
|
|
||||||
Foundation2,
|
|
||||||
Foundation3,
|
|
||||||
Foundation4,
|
|
||||||
Stock,
|
|
||||||
}
|
|
||||||
impl KlondikePileStack {
|
|
||||||
const fn next(self) -> Option<Self> {
|
|
||||||
use KlondikePileStack::*;
|
|
||||||
Some(match self {
|
|
||||||
Tableau1(skip) => match skip.next() {
|
|
||||||
Some(next) => Tableau1(next),
|
|
||||||
None => Tableau2(SkipCards::Zero),
|
|
||||||
},
|
|
||||||
Tableau2(skip) => match skip.next() {
|
|
||||||
Some(next) => Tableau2(next),
|
|
||||||
None => Tableau3(SkipCards::Zero),
|
|
||||||
},
|
|
||||||
Tableau3(skip) => match skip.next() {
|
|
||||||
Some(next) => Tableau3(next),
|
|
||||||
None => Tableau4(SkipCards::Zero),
|
|
||||||
},
|
|
||||||
Tableau4(skip) => match skip.next() {
|
|
||||||
Some(next) => Tableau4(next),
|
|
||||||
None => Tableau5(SkipCards::Zero),
|
|
||||||
},
|
|
||||||
Tableau5(skip) => match skip.next() {
|
|
||||||
Some(next) => Tableau5(next),
|
|
||||||
None => Tableau6(SkipCards::Zero),
|
|
||||||
},
|
|
||||||
Tableau6(skip) => match skip.next() {
|
|
||||||
Some(next) => Tableau6(next),
|
|
||||||
None => Tableau7(SkipCards::Zero),
|
|
||||||
},
|
|
||||||
Tableau7(skip) => match skip.next() {
|
|
||||||
Some(next) => Tableau7(next),
|
|
||||||
None => Foundation1,
|
|
||||||
},
|
|
||||||
Foundation1 => Foundation2,
|
|
||||||
Foundation2 => Foundation3,
|
|
||||||
Foundation3 => Foundation4,
|
|
||||||
Foundation4 => Stock,
|
|
||||||
Stock => return None,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
pub struct KlondikeInstruction {
|
pub struct TableauStack {
|
||||||
pub src: InstructionSrc,
|
pub tableau: Tableau,
|
||||||
pub dst: KlondikePileId,
|
pub skip_cards: SkipCards,
|
||||||
}
|
}
|
||||||
impl KlondikeInstruction {
|
|
||||||
pub const fn stock() -> Self {
|
impl TableauStack {
|
||||||
Self {
|
const ITER_BEGIN: Self = Self {
|
||||||
src: InstructionSrc::STOCK,
|
tableau: Tableau::ITER_BEGIN,
|
||||||
dst: KlondikePileId::Stock,
|
skip_cards: SkipCards::ITER_BEGIN,
|
||||||
}
|
};
|
||||||
}
|
|
||||||
const fn next(self) -> Option<Self> {
|
const fn next(self) -> Option<Self> {
|
||||||
let KlondikeInstruction { src, dst } = self;
|
let TableauStack {
|
||||||
if let Some(next_dst) = dst.next() {
|
tableau,
|
||||||
return Some(Self { src, dst: next_dst });
|
skip_cards,
|
||||||
}
|
} = self;
|
||||||
if let Some(next_src) = src.next() {
|
if let Some(skip_cards) = skip_cards.next() {
|
||||||
return Some(Self {
|
return Some(Self {
|
||||||
src: next_src,
|
tableau,
|
||||||
dst: KlondikePileId::Tableau1,
|
skip_cards,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(tableau) = tableau.next() {
|
||||||
|
let skip_cards = SkipCards::Skip0;
|
||||||
|
return Some(Self {
|
||||||
|
tableau,
|
||||||
|
skip_cards,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
|
pub enum KlondikePileStack {
|
||||||
|
Tableau(TableauStack),
|
||||||
|
Stock,
|
||||||
|
Foundation(Foundation),
|
||||||
|
}
|
||||||
|
impl KlondikePileStack {
|
||||||
|
const ITER_BEGIN: Self = Self::Tableau(TableauStack::ITER_BEGIN);
|
||||||
|
const fn next(self) -> Option<Self> {
|
||||||
|
Some(match self {
|
||||||
|
Self::Tableau(tableau_stack) => match tableau_stack.next() {
|
||||||
|
Some(tableau_stack) => Self::Tableau(tableau_stack),
|
||||||
|
None => Self::Stock,
|
||||||
|
},
|
||||||
|
Self::Stock => Self::Foundation(Foundation::ITER_BEGIN),
|
||||||
|
Self::Foundation(foundation) => match foundation.next() {
|
||||||
|
Some(foundation) => Self::Foundation(foundation),
|
||||||
|
None => return None,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
|
pub struct DstFoundation {
|
||||||
|
pub src: KlondikePile,
|
||||||
|
pub foundation: Foundation,
|
||||||
|
}
|
||||||
|
impl DstFoundation {
|
||||||
|
const ITER_BEGIN: Self = Self {
|
||||||
|
src: KlondikePile::ITER_BEGIN,
|
||||||
|
foundation: Foundation::ITER_BEGIN,
|
||||||
|
};
|
||||||
|
const fn next(self) -> Option<Self> {
|
||||||
|
let DstFoundation { src, foundation } = self;
|
||||||
|
if let Some(src) = src.next() {
|
||||||
|
return Some(Self { src, foundation });
|
||||||
|
}
|
||||||
|
if let Some(foundation) = foundation.next() {
|
||||||
|
let src = KlondikePile::ITER_BEGIN;
|
||||||
|
return Some(Self { src, foundation });
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
|
pub struct DstTableau {
|
||||||
|
pub src: KlondikePileStack,
|
||||||
|
pub tableau: Tableau,
|
||||||
|
}
|
||||||
|
impl DstTableau {
|
||||||
|
const ITER_BEGIN: Self = Self {
|
||||||
|
src: KlondikePileStack::ITER_BEGIN,
|
||||||
|
tableau: Tableau::ITER_BEGIN,
|
||||||
|
};
|
||||||
|
const fn next(self) -> Option<Self> {
|
||||||
|
let DstTableau { src, tableau } = self;
|
||||||
|
if let Some(src) = src.next() {
|
||||||
|
return Some(Self { src, tableau });
|
||||||
|
}
|
||||||
|
if let Some(tableau) = tableau.next() {
|
||||||
|
let src = KlondikePileStack::ITER_BEGIN;
|
||||||
|
return Some(Self { src, tableau });
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
|
pub enum KlondikeInstruction {
|
||||||
|
DstFoundation(DstFoundation),
|
||||||
|
DstTableau(DstTableau),
|
||||||
|
RotateStock,
|
||||||
|
}
|
||||||
|
impl KlondikeInstruction {
|
||||||
|
const ITER_BEGIN: Self = Self::DstFoundation(DstFoundation::ITER_BEGIN);
|
||||||
|
const fn next(self) -> Option<Self> {
|
||||||
|
Some(match self {
|
||||||
|
Self::DstFoundation(dst_foundation) => match dst_foundation.next() {
|
||||||
|
Some(dst_foundation) => Self::DstFoundation(dst_foundation),
|
||||||
|
None => Self::DstTableau(DstTableau::ITER_BEGIN),
|
||||||
|
},
|
||||||
|
Self::DstTableau(tableau) => match tableau.next() {
|
||||||
|
Some(tableau) => Self::DstTableau(tableau),
|
||||||
|
None => Self::RotateStock,
|
||||||
|
},
|
||||||
|
Self::RotateStock => return None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const TABLEAUS: usize = 7;
|
const TABLEAUS: usize = 7;
|
||||||
const fn sum(n: usize) -> usize {
|
const fn sum(n: usize) -> usize {
|
||||||
n * (n + 1) / 2
|
n * (n + 1) / 2
|
||||||
@@ -313,128 +307,106 @@ impl KlondikeState {
|
|||||||
pub const fn tableau7(&self) -> &Pile<6, 13> {
|
pub const fn tableau7(&self) -> &Pile<6, 13> {
|
||||||
&self.tableau7
|
&self.tableau7
|
||||||
}
|
}
|
||||||
fn src_card(&self, src: InstructionSrc) -> Option<&Card> {
|
fn card(&self, src: KlondikePileStack) -> Option<&Card> {
|
||||||
match src.into_spec() {
|
match src {
|
||||||
KlondikePileStack::Tableau1(skip_cards) => {
|
KlondikePileStack::Tableau(TableauStack {
|
||||||
self.tableau1.face_up().get(skip_cards as usize)
|
tableau,
|
||||||
|
skip_cards,
|
||||||
|
}) => match tableau {
|
||||||
|
Tableau::Tableau1 => self.tableau1.face_up().get(skip_cards as usize),
|
||||||
|
Tableau::Tableau2 => self.tableau2.face_up().get(skip_cards as usize),
|
||||||
|
Tableau::Tableau3 => self.tableau3.face_up().get(skip_cards as usize),
|
||||||
|
Tableau::Tableau4 => self.tableau4.face_up().get(skip_cards as usize),
|
||||||
|
Tableau::Tableau5 => self.tableau5.face_up().get(skip_cards as usize),
|
||||||
|
Tableau::Tableau6 => self.tableau6.face_up().get(skip_cards as usize),
|
||||||
|
Tableau::Tableau7 => self.tableau7.face_up().get(skip_cards as usize),
|
||||||
|
},
|
||||||
|
KlondikePileStack::Foundation(foundation) => {
|
||||||
|
self.foundations[foundation as usize].last()
|
||||||
}
|
}
|
||||||
KlondikePileStack::Tableau2(skip_cards) => {
|
|
||||||
self.tableau2.face_up().get(skip_cards as usize)
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau3(skip_cards) => {
|
|
||||||
self.tableau3.face_up().get(skip_cards as usize)
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau4(skip_cards) => {
|
|
||||||
self.tableau4.face_up().get(skip_cards as usize)
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau5(skip_cards) => {
|
|
||||||
self.tableau5.face_up().get(skip_cards as usize)
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau6(skip_cards) => {
|
|
||||||
self.tableau6.face_up().get(skip_cards as usize)
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau7(skip_cards) => {
|
|
||||||
self.tableau7.face_up().get(skip_cards as usize)
|
|
||||||
}
|
|
||||||
KlondikePileStack::Foundation1 => self.foundations[1 - 1].last(),
|
|
||||||
KlondikePileStack::Foundation2 => self.foundations[2 - 1].last(),
|
|
||||||
KlondikePileStack::Foundation3 => self.foundations[3 - 1].last(),
|
|
||||||
KlondikePileStack::Foundation4 => self.foundations[4 - 1].last(),
|
|
||||||
KlondikePileStack::Stock => self.stock.face_up().last(),
|
KlondikePileStack::Stock => self.stock.face_up().last(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn take_src_cards(&mut self, src: InstructionSrc) -> Stack<13> {
|
fn top_card(&self, src: KlondikePile) -> Option<&Card> {
|
||||||
match src.into_spec() {
|
match src {
|
||||||
KlondikePileStack::Tableau1(skip_cards) => {
|
KlondikePile::Tableau(tableau) => match tableau {
|
||||||
self.tableau1.take_range_flip_up(skip_cards as usize..)
|
Tableau::Tableau1 => self.tableau1.face_up().last(),
|
||||||
|
Tableau::Tableau2 => self.tableau2.face_up().last(),
|
||||||
|
Tableau::Tableau3 => self.tableau3.face_up().last(),
|
||||||
|
Tableau::Tableau4 => self.tableau4.face_up().last(),
|
||||||
|
Tableau::Tableau5 => self.tableau5.face_up().last(),
|
||||||
|
Tableau::Tableau6 => self.tableau6.face_up().last(),
|
||||||
|
Tableau::Tableau7 => self.tableau7.face_up().last(),
|
||||||
|
},
|
||||||
|
KlondikePile::Foundation(foundation) => self.foundations[foundation as usize].last(),
|
||||||
|
KlondikePile::Stock => self.stock.face_up().last(),
|
||||||
}
|
}
|
||||||
KlondikePileStack::Tableau2(skip_cards) => {
|
|
||||||
self.tableau2.take_range_flip_up(skip_cards as usize..)
|
|
||||||
}
|
}
|
||||||
KlondikePileStack::Tableau3(skip_cards) => {
|
fn take_cards(&mut self, src: KlondikePileStack) -> Stack<13> {
|
||||||
self.tableau3.take_range_flip_up(skip_cards as usize..)
|
match src {
|
||||||
|
KlondikePileStack::Tableau(TableauStack {
|
||||||
|
tableau,
|
||||||
|
skip_cards,
|
||||||
|
}) => match tableau {
|
||||||
|
Tableau::Tableau1 => self.tableau1.take_range_flip_up(skip_cards as usize..),
|
||||||
|
Tableau::Tableau2 => self.tableau2.take_range_flip_up(skip_cards as usize..),
|
||||||
|
Tableau::Tableau3 => self.tableau3.take_range_flip_up(skip_cards as usize..),
|
||||||
|
Tableau::Tableau4 => self.tableau4.take_range_flip_up(skip_cards as usize..),
|
||||||
|
Tableau::Tableau5 => self.tableau5.take_range_flip_up(skip_cards as usize..),
|
||||||
|
Tableau::Tableau6 => self.tableau6.take_range_flip_up(skip_cards as usize..),
|
||||||
|
Tableau::Tableau7 => self.tableau7.take_range_flip_up(skip_cards as usize..),
|
||||||
|
},
|
||||||
|
KlondikePileStack::Foundation(foundation) => {
|
||||||
|
Stack::from_iter(self.foundations[foundation as usize].pop())
|
||||||
}
|
}
|
||||||
KlondikePileStack::Tableau4(skip_cards) => {
|
|
||||||
self.tableau4.take_range_flip_up(skip_cards as usize..)
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau5(skip_cards) => {
|
|
||||||
self.tableau5.take_range_flip_up(skip_cards as usize..)
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau6(skip_cards) => {
|
|
||||||
self.tableau6.take_range_flip_up(skip_cards as usize..)
|
|
||||||
}
|
|
||||||
KlondikePileStack::Tableau7(skip_cards) => {
|
|
||||||
self.tableau7.take_range_flip_up(skip_cards as usize..)
|
|
||||||
}
|
|
||||||
KlondikePileStack::Foundation1 => Stack::from_iter(self.foundations[1 - 1].pop()),
|
|
||||||
KlondikePileStack::Foundation2 => Stack::from_iter(self.foundations[2 - 1].pop()),
|
|
||||||
KlondikePileStack::Foundation3 => Stack::from_iter(self.foundations[3 - 1].pop()),
|
|
||||||
KlondikePileStack::Foundation4 => Stack::from_iter(self.foundations[4 - 1].pop()),
|
|
||||||
KlondikePileStack::Stock => Stack::from_iter(self.stock.pop()),
|
KlondikePileStack::Stock => Stack::from_iter(self.stock.pop()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn dst_card(&self, dst: KlondikePileId) -> Option<&Card> {
|
fn take_top_card(&mut self, src: KlondikePile) -> Option<Card> {
|
||||||
match dst {
|
match src {
|
||||||
KlondikePileId::Tableau1 => self.tableau1.face_up().last(),
|
KlondikePile::Tableau(tableau) => match tableau {
|
||||||
KlondikePileId::Tableau2 => self.tableau2.face_up().last(),
|
Tableau::Tableau1 => self.tableau1.pop(),
|
||||||
KlondikePileId::Tableau3 => self.tableau3.face_up().last(),
|
Tableau::Tableau2 => self.tableau2.pop(),
|
||||||
KlondikePileId::Tableau4 => self.tableau4.face_up().last(),
|
Tableau::Tableau3 => self.tableau3.pop(),
|
||||||
KlondikePileId::Tableau5 => self.tableau5.face_up().last(),
|
Tableau::Tableau4 => self.tableau4.pop(),
|
||||||
KlondikePileId::Tableau6 => self.tableau6.face_up().last(),
|
Tableau::Tableau5 => self.tableau5.pop(),
|
||||||
KlondikePileId::Tableau7 => self.tableau7.face_up().last(),
|
Tableau::Tableau6 => self.tableau6.pop(),
|
||||||
KlondikePileId::Foundation1 => self.foundations[1 - 1].last(),
|
Tableau::Tableau7 => self.tableau7.pop(),
|
||||||
KlondikePileId::Foundation2 => self.foundations[2 - 1].last(),
|
},
|
||||||
KlondikePileId::Foundation3 => self.foundations[3 - 1].last(),
|
KlondikePile::Foundation(foundation) => self.foundations[foundation as usize].pop(),
|
||||||
KlondikePileId::Foundation4 => self.foundations[4 - 1].last(),
|
KlondikePile::Stock => self.stock.pop(),
|
||||||
KlondikePileId::Stock => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn extend_dst_pile(&mut self, dst: KlondikePileId, cards: Stack<13>) {
|
fn extend<I: IntoIterator<Item = Card>>(&mut self, dst: KlondikePile, cards: I) {
|
||||||
match dst {
|
match dst {
|
||||||
KlondikePileId::Tableau1 => self.tableau1.extend(cards),
|
KlondikePile::Tableau(tableau) => match tableau {
|
||||||
KlondikePileId::Tableau2 => self.tableau2.extend(cards),
|
Tableau::Tableau1 => self.tableau1.extend(cards),
|
||||||
KlondikePileId::Tableau3 => self.tableau3.extend(cards),
|
Tableau::Tableau2 => self.tableau2.extend(cards),
|
||||||
KlondikePileId::Tableau4 => self.tableau4.extend(cards),
|
Tableau::Tableau3 => self.tableau3.extend(cards),
|
||||||
KlondikePileId::Tableau5 => self.tableau5.extend(cards),
|
Tableau::Tableau4 => self.tableau4.extend(cards),
|
||||||
KlondikePileId::Tableau6 => self.tableau6.extend(cards),
|
Tableau::Tableau5 => self.tableau5.extend(cards),
|
||||||
KlondikePileId::Tableau7 => self.tableau7.extend(cards),
|
Tableau::Tableau6 => self.tableau6.extend(cards),
|
||||||
KlondikePileId::Foundation1 => self.foundations[1 - 1].extend(cards),
|
Tableau::Tableau7 => self.tableau7.extend(cards),
|
||||||
KlondikePileId::Foundation2 => self.foundations[2 - 1].extend(cards),
|
},
|
||||||
KlondikePileId::Foundation3 => self.foundations[3 - 1].extend(cards),
|
KlondikePile::Foundation(foundation) => {
|
||||||
KlondikePileId::Foundation4 => self.foundations[4 - 1].extend(cards),
|
self.foundations[foundation as usize].extend(cards)
|
||||||
KlondikePileId::Stock => (),
|
}
|
||||||
|
KlondikePile::Stock => self.stock.extend(cards),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn is_instruction_valid(&self, instruction: KlondikeInstruction) -> bool {
|
fn is_instruction_valid(&self, instruction: KlondikeInstruction) -> bool {
|
||||||
match instruction {
|
match instruction {
|
||||||
// Stock -> Stock draws a card or resets the stock
|
// Stock -> Stock draws a card or resets the stock
|
||||||
KlondikeInstruction {
|
KlondikeInstruction::RotateStock => {
|
||||||
src: InstructionSrc::STOCK,
|
|
||||||
dst: KlondikePileId::Stock,
|
|
||||||
} => {
|
|
||||||
// cannot move stock when stock is empty
|
// cannot move stock when stock is empty
|
||||||
!self.stock.is_empty()
|
!self.stock.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
// cannot move cards to stock
|
|
||||||
KlondikeInstruction {
|
|
||||||
src: _,
|
|
||||||
dst: KlondikePileId::Stock,
|
|
||||||
} => false,
|
|
||||||
|
|
||||||
// moving to foundation has special rules
|
// moving to foundation has special rules
|
||||||
KlondikeInstruction { src, dst }
|
KlondikeInstruction::DstFoundation(dst_foundation) => {
|
||||||
if matches!(
|
|
||||||
dst,
|
|
||||||
KlondikePileId::Foundation1
|
|
||||||
| KlondikePileId::Foundation2
|
|
||||||
| KlondikePileId::Foundation3
|
|
||||||
| KlondikePileId::Foundation4
|
|
||||||
) =>
|
|
||||||
{
|
|
||||||
// get the top cards
|
// get the top cards
|
||||||
if let Some(src_card) = self.src_card(src) {
|
if let Some(src_card) = self.top_card(dst_foundation.src) {
|
||||||
match self.dst_card(dst) {
|
match self.top_card(dst_foundation.foundation.into()) {
|
||||||
// destination card exists
|
// destination card exists
|
||||||
Some(dst_card) => {
|
Some(dst_card) => {
|
||||||
// suit matches?
|
// suit matches?
|
||||||
@@ -450,10 +422,10 @@ impl KlondikeState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// other = move to tableau
|
// other = move to tableau
|
||||||
KlondikeInstruction { src, dst } => {
|
KlondikeInstruction::DstTableau(dst_tableau) => {
|
||||||
// get the top cards
|
// get the cards
|
||||||
if let Some(src_card) = self.src_card(src) {
|
if let Some(src_card) = self.card(dst_tableau.src) {
|
||||||
match self.dst_card(dst) {
|
match self.top_card(dst_tableau.tableau.into()) {
|
||||||
// destination card exists
|
// destination card exists
|
||||||
Some(dst_card) => {
|
Some(dst_card) => {
|
||||||
// red-ness is opposite?
|
// red-ness is opposite?
|
||||||
@@ -478,10 +450,7 @@ pub struct KlondikeIter {
|
|||||||
impl KlondikeIter {
|
impl KlondikeIter {
|
||||||
const fn new() -> Self {
|
const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
instruction: Some(KlondikeInstruction {
|
instruction: Some(KlondikeInstruction::ITER_BEGIN),
|
||||||
src: InstructionSrc::new(KlondikePileStack::Tableau1(SkipCards::Zero)),
|
|
||||||
dst: KlondikePileId::Tableau2,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -558,19 +527,20 @@ impl Game for Klondike {
|
|||||||
fn process_instruction(&mut self, instruction: Self::Instruction) {
|
fn process_instruction(&mut self, instruction: Self::Instruction) {
|
||||||
match instruction {
|
match instruction {
|
||||||
// Reset the stock if it's empty
|
// Reset the stock if it's empty
|
||||||
KlondikeInstruction {
|
KlondikeInstruction::RotateStock => {
|
||||||
src: InstructionSrc::STOCK,
|
|
||||||
dst: KlondikePileId::Stock,
|
|
||||||
} => {
|
|
||||||
if self.state.stock.face_down().is_empty() {
|
if self.state.stock.face_down().is_empty() {
|
||||||
self.state.stock.flip_it_and_reverse_it();
|
self.state.stock.flip_it_and_reverse_it();
|
||||||
} else {
|
} else {
|
||||||
self.state.stock.flip_up();
|
self.state.stock.flip_up();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KlondikeInstruction { src, dst } => {
|
KlondikeInstruction::DstFoundation(DstFoundation { src, foundation }) => {
|
||||||
let cards = self.state.take_src_cards(src);
|
let cards = self.state.take_top_card(src);
|
||||||
self.state.extend_dst_pile(dst, cards);
|
self.state.extend(foundation.into(), cards);
|
||||||
|
}
|
||||||
|
KlondikeInstruction::DstTableau(DstTableau { src, tableau }) => {
|
||||||
|
let cards = self.state.take_cards(src);
|
||||||
|
self.state.extend(tableau.into(), cards);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-103
@@ -5,8 +5,8 @@ pub type Rng = rand::rngs::ThreadRng;
|
|||||||
|
|
||||||
use card_game::{Card, Game, Pile, Session, Suit};
|
use card_game::{Card, Game, Pile, Session, Suit};
|
||||||
use klondike::{
|
use klondike::{
|
||||||
InstructionSrc, Klondike, KlondikeInstruction, KlondikePileId, KlondikePileStack,
|
DstFoundation, DstTableau, Foundation, Klondike, KlondikeInstruction, KlondikePile,
|
||||||
KlondikeState, SkipCards,
|
KlondikePileStack, SkipCards, Tableau, TableauStack,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
@@ -91,8 +91,8 @@ impl Display for Klondike {
|
|||||||
struct Invalid;
|
struct Invalid;
|
||||||
struct Parsed<T>(T);
|
struct Parsed<T>(T);
|
||||||
struct NaiveInstruction {
|
struct NaiveInstruction {
|
||||||
src: KlondikePileId,
|
src: KlondikePile,
|
||||||
dst: KlondikePileId,
|
dst: KlondikePile,
|
||||||
}
|
}
|
||||||
impl core::str::FromStr for NaiveInstruction {
|
impl core::str::FromStr for NaiveInstruction {
|
||||||
type Err = Invalid;
|
type Err = Invalid;
|
||||||
@@ -102,22 +102,22 @@ impl core::str::FromStr for NaiveInstruction {
|
|||||||
Ok(NaiveInstruction { src, dst })
|
Ok(NaiveInstruction { src, dst })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl core::str::FromStr for Parsed<KlondikePileId> {
|
impl core::str::FromStr for Parsed<KlondikePile> {
|
||||||
type Err = Invalid;
|
type Err = Invalid;
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
Ok(Parsed(match s {
|
Ok(Parsed(match s {
|
||||||
"st" => KlondikePileId::Stock,
|
"st" => KlondikePile::Stock,
|
||||||
"t1" => KlondikePileId::Tableau1,
|
"t1" => KlondikePile::Tableau(Tableau::Tableau1),
|
||||||
"t2" => KlondikePileId::Tableau2,
|
"t2" => KlondikePile::Tableau(Tableau::Tableau2),
|
||||||
"t3" => KlondikePileId::Tableau3,
|
"t3" => KlondikePile::Tableau(Tableau::Tableau3),
|
||||||
"t4" => KlondikePileId::Tableau4,
|
"t4" => KlondikePile::Tableau(Tableau::Tableau4),
|
||||||
"t5" => KlondikePileId::Tableau5,
|
"t5" => KlondikePile::Tableau(Tableau::Tableau5),
|
||||||
"t6" => KlondikePileId::Tableau6,
|
"t6" => KlondikePile::Tableau(Tableau::Tableau6),
|
||||||
"t7" => KlondikePileId::Tableau7,
|
"t7" => KlondikePile::Tableau(Tableau::Tableau7),
|
||||||
"f1" => KlondikePileId::Foundation1,
|
"f1" => KlondikePile::Foundation(Foundation::Foundation1),
|
||||||
"f2" => KlondikePileId::Foundation2,
|
"f2" => KlondikePile::Foundation(Foundation::Foundation2),
|
||||||
"f3" => KlondikePileId::Foundation3,
|
"f3" => KlondikePile::Foundation(Foundation::Foundation3),
|
||||||
"f4" => KlondikePileId::Foundation4,
|
"f4" => KlondikePile::Foundation(Foundation::Foundation4),
|
||||||
_ => return Err(Invalid),
|
_ => return Err(Invalid),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -152,99 +152,48 @@ fn find_valid_instruction(
|
|||||||
naive_instruction: NaiveInstruction,
|
naive_instruction: NaiveInstruction,
|
||||||
) -> Option<KlondikeInstruction> {
|
) -> Option<KlondikeInstruction> {
|
||||||
const SKIP_LIST: [SkipCards; 13] = [
|
const SKIP_LIST: [SkipCards; 13] = [
|
||||||
SkipCards::Zero,
|
SkipCards::Skip0,
|
||||||
SkipCards::One,
|
SkipCards::Skip1,
|
||||||
SkipCards::Two,
|
SkipCards::Skip2,
|
||||||
SkipCards::Three,
|
SkipCards::Skip3,
|
||||||
SkipCards::Four,
|
SkipCards::Skip4,
|
||||||
SkipCards::Five,
|
SkipCards::Skip5,
|
||||||
SkipCards::Six,
|
SkipCards::Skip6,
|
||||||
SkipCards::Seven,
|
SkipCards::Skip7,
|
||||||
SkipCards::Eight,
|
SkipCards::Skip8,
|
||||||
SkipCards::Nine,
|
SkipCards::Skip9,
|
||||||
SkipCards::Ten,
|
SkipCards::Skip10,
|
||||||
SkipCards::Eleven,
|
SkipCards::Skip11,
|
||||||
SkipCards::Twelve,
|
SkipCards::Skip12,
|
||||||
];
|
];
|
||||||
let dst = naive_instruction.dst;
|
let instruction = match (naive_instruction.dst, naive_instruction.src) {
|
||||||
let src = match naive_instruction.src {
|
(KlondikePile::Tableau(tableau), src) => {
|
||||||
KlondikePileId::Tableau1 => {
|
let src = match src {
|
||||||
for skip in SKIP_LIST {
|
KlondikePile::Tableau(src_tableau) => {
|
||||||
let src = InstructionSrc::new(KlondikePileStack::Tableau1(skip));
|
for skip_cards in SKIP_LIST {
|
||||||
let instruction = KlondikeInstruction { src, dst };
|
let src = KlondikePileStack::Tableau(TableauStack {
|
||||||
|
tableau: src_tableau,
|
||||||
|
skip_cards,
|
||||||
|
});
|
||||||
|
let instruction =
|
||||||
|
KlondikeInstruction::DstTableau(DstTableau { tableau, src });
|
||||||
if state.is_instruction_valid(instruction) {
|
if state.is_instruction_valid(instruction) {
|
||||||
return Some(instruction);
|
return Some(instruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
KlondikePileId::Tableau2 => {
|
KlondikePile::Stock => KlondikePileStack::Stock,
|
||||||
for skip in SKIP_LIST {
|
KlondikePile::Foundation(foundation) => KlondikePileStack::Foundation(foundation),
|
||||||
let src = InstructionSrc::new(KlondikePileStack::Tableau2(skip));
|
};
|
||||||
let instruction = KlondikeInstruction { src, dst };
|
KlondikeInstruction::DstTableau(DstTableau { tableau, src })
|
||||||
if state.is_instruction_valid(instruction) {
|
}
|
||||||
return Some(instruction);
|
(KlondikePile::Stock, KlondikePile::Stock) => KlondikeInstruction::RotateStock,
|
||||||
}
|
(KlondikePile::Foundation(foundation), src) => {
|
||||||
}
|
KlondikeInstruction::DstFoundation(DstFoundation { foundation, src })
|
||||||
return None;
|
}
|
||||||
}
|
_ => return None,
|
||||||
KlondikePileId::Tableau3 => {
|
|
||||||
for skip in SKIP_LIST {
|
|
||||||
let src = InstructionSrc::new(KlondikePileStack::Tableau3(skip));
|
|
||||||
let instruction = KlondikeInstruction { src, dst };
|
|
||||||
if state.is_instruction_valid(instruction) {
|
|
||||||
return Some(instruction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
KlondikePileId::Tableau4 => {
|
|
||||||
for skip in SKIP_LIST {
|
|
||||||
let src = InstructionSrc::new(KlondikePileStack::Tableau4(skip));
|
|
||||||
let instruction = KlondikeInstruction { src, dst };
|
|
||||||
if state.is_instruction_valid(instruction) {
|
|
||||||
return Some(instruction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
KlondikePileId::Tableau5 => {
|
|
||||||
for skip in SKIP_LIST {
|
|
||||||
let src = InstructionSrc::new(KlondikePileStack::Tableau5(skip));
|
|
||||||
let instruction = KlondikeInstruction { src, dst };
|
|
||||||
if state.is_instruction_valid(instruction) {
|
|
||||||
return Some(instruction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
KlondikePileId::Tableau6 => {
|
|
||||||
for skip in SKIP_LIST {
|
|
||||||
let src = InstructionSrc::new(KlondikePileStack::Tableau6(skip));
|
|
||||||
let instruction = KlondikeInstruction { src, dst };
|
|
||||||
if state.is_instruction_valid(instruction) {
|
|
||||||
return Some(instruction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
KlondikePileId::Tableau7 => {
|
|
||||||
for skip in SKIP_LIST {
|
|
||||||
let src = InstructionSrc::new(KlondikePileStack::Tableau7(skip));
|
|
||||||
let instruction = KlondikeInstruction { src, dst };
|
|
||||||
if state.is_instruction_valid(instruction) {
|
|
||||||
return Some(instruction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
KlondikePileId::Foundation1 => InstructionSrc::new(KlondikePileStack::Foundation1),
|
|
||||||
KlondikePileId::Foundation2 => InstructionSrc::new(KlondikePileStack::Foundation2),
|
|
||||||
KlondikePileId::Foundation3 => InstructionSrc::new(KlondikePileStack::Foundation3),
|
|
||||||
KlondikePileId::Foundation4 => InstructionSrc::new(KlondikePileStack::Foundation4),
|
|
||||||
KlondikePileId::Stock => InstructionSrc::new(KlondikePileStack::Stock),
|
|
||||||
};
|
};
|
||||||
let instruction = KlondikeInstruction { src, dst };
|
|
||||||
state
|
state
|
||||||
.is_instruction_valid(instruction)
|
.is_instruction_valid(instruction)
|
||||||
.then_some(instruction)
|
.then_some(instruction)
|
||||||
@@ -281,7 +230,9 @@ fn main() -> Result<(), std::io::Error> {
|
|||||||
println!("No valid moves!");
|
println!("No valid moves!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SessionInstruction::Stock => session.process_instruction(KlondikeInstruction::stock()),
|
SessionInstruction::Stock => {
|
||||||
|
session.process_instruction(KlondikeInstruction::RotateStock)
|
||||||
|
}
|
||||||
SessionInstruction::Klondike(naive_instruction) => {
|
SessionInstruction::Klondike(naive_instruction) => {
|
||||||
if let Some(instruction) =
|
if let Some(instruction) =
|
||||||
find_valid_instruction(session.state(), naive_instruction)
|
find_valid_instruction(session.state(), naive_instruction)
|
||||||
|
|||||||
Reference in New Issue
Block a user