go wild on KlondikeInstruction
This commit is contained in:
+179
-200
@@ -9,9 +9,8 @@ impl Default for KlondikeConfig {
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum KlondikePileId {
|
||||
pub enum Tableau {
|
||||
Tableau1,
|
||||
Tableau2,
|
||||
Tableau3,
|
||||
@@ -19,15 +18,11 @@ pub enum KlondikePileId {
|
||||
Tableau5,
|
||||
Tableau6,
|
||||
Tableau7,
|
||||
Foundation1,
|
||||
Foundation2,
|
||||
Foundation3,
|
||||
Foundation4,
|
||||
Stock,
|
||||
}
|
||||
impl KlondikePileId {
|
||||
impl Tableau {
|
||||
const ITER_BEGIN: Self = Self::Tableau1;
|
||||
const fn next(self) -> Option<Self> {
|
||||
use KlondikePileId::*;
|
||||
use Tableau::*;
|
||||
Some(match self {
|
||||
Tableau1 => Tableau2,
|
||||
Tableau2 => Tableau3,
|
||||
@@ -35,229 +30,213 @@ impl KlondikePileId {
|
||||
Tableau4 => Tableau5,
|
||||
Tableau5 => Tableau6,
|
||||
Tableau6 => Tableau7,
|
||||
Tableau7 => Foundation1,
|
||||
Foundation1 => Foundation2,
|
||||
Foundation2 => Foundation3,
|
||||
Foundation3 => Foundation4,
|
||||
Foundation4 => Stock,
|
||||
Stock => return None,
|
||||
Tableau7 => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// high four bits for stack depth, low four bits for Pile Id
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct InstructionSrc(u8);
|
||||
impl InstructionSrc {
|
||||
const STOCK: Self = InstructionSrc::new(KlondikePileStack::Stock);
|
||||
pub const fn new(src: KlondikePileStack) -> Self {
|
||||
match src {
|
||||
KlondikePileStack::Tableau1(skip_cards) => {
|
||||
Self(KlondikePileId::Tableau1 as u8 + ((skip_cards as u8) << 4))
|
||||
}
|
||||
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,
|
||||
}
|
||||
}
|
||||
pub enum Foundation {
|
||||
Foundation1,
|
||||
Foundation2,
|
||||
Foundation3,
|
||||
Foundation4,
|
||||
}
|
||||
impl Foundation {
|
||||
const ITER_BEGIN: Self = Self::Foundation1;
|
||||
const fn next(self) -> Option<Self> {
|
||||
match self.into_spec().next() {
|
||||
Some(s) => Some(Self::new(s)),
|
||||
None => None,
|
||||
}
|
||||
use Foundation::*;
|
||||
Some(match self {
|
||||
Foundation1 => Foundation2,
|
||||
Foundation2 => Foundation3,
|
||||
Foundation3 => Foundation4,
|
||||
Foundation4 => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl From<InstructionSrc> for KlondikePileId {
|
||||
fn from(value: InstructionSrc) -> Self {
|
||||
match value.into_spec() {
|
||||
KlondikePileStack::Tableau1(_) => KlondikePileId::Tableau1,
|
||||
KlondikePileStack::Tableau2(_) => KlondikePileId::Tableau2,
|
||||
KlondikePileStack::Tableau3(_) => KlondikePileId::Tableau3,
|
||||
KlondikePileStack::Tableau4(_) => KlondikePileId::Tableau4,
|
||||
KlondikePileStack::Tableau5(_) => KlondikePileId::Tableau5,
|
||||
KlondikePileStack::Tableau6(_) => KlondikePileId::Tableau6,
|
||||
KlondikePileStack::Tableau7(_) => KlondikePileId::Tableau7,
|
||||
KlondikePileStack::Foundation1 => KlondikePileId::Foundation1,
|
||||
KlondikePileStack::Foundation2 => KlondikePileId::Foundation2,
|
||||
KlondikePileStack::Foundation3 => KlondikePileId::Foundation3,
|
||||
KlondikePileStack::Foundation4 => KlondikePileId::Foundation4,
|
||||
KlondikePileStack::Stock => KlondikePileId::Stock,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum KlondikePile {
|
||||
Tableau(Tableau),
|
||||
Stock,
|
||||
Foundation(Foundation),
|
||||
}
|
||||
impl KlondikePile {
|
||||
const ITER_BEGIN: Self = Self::Tableau(Tableau::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,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum SkipCards {
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
Five,
|
||||
Six,
|
||||
Seven,
|
||||
Eight,
|
||||
Nine,
|
||||
Ten,
|
||||
Eleven,
|
||||
Twelve,
|
||||
Skip0,
|
||||
Skip1,
|
||||
Skip2,
|
||||
Skip3,
|
||||
Skip4,
|
||||
Skip5,
|
||||
Skip6,
|
||||
Skip7,
|
||||
Skip8,
|
||||
Skip9,
|
||||
Skip10,
|
||||
Skip11,
|
||||
Skip12,
|
||||
}
|
||||
impl SkipCards {
|
||||
const ITER_BEGIN: Self = Self::Skip0;
|
||||
const fn next(self) -> Option<Self> {
|
||||
use SkipCards::*;
|
||||
Some(match self {
|
||||
Zero => One,
|
||||
One => Two,
|
||||
Two => Three,
|
||||
Three => Four,
|
||||
Four => Five,
|
||||
Five => Six,
|
||||
Six => Seven,
|
||||
Seven => Eight,
|
||||
Eight => Nine,
|
||||
Nine => Ten,
|
||||
Ten => Eleven,
|
||||
Eleven => Twelve,
|
||||
Twelve => 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,
|
||||
Skip0 => Skip1,
|
||||
Skip1 => Skip2,
|
||||
Skip2 => Skip3,
|
||||
Skip3 => Skip4,
|
||||
Skip4 => Skip5,
|
||||
Skip5 => Skip6,
|
||||
Skip6 => Skip7,
|
||||
Skip7 => Skip8,
|
||||
Skip8 => Skip9,
|
||||
Skip9 => Skip10,
|
||||
Skip10 => Skip11,
|
||||
Skip11 => Skip12,
|
||||
Skip12 => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct KlondikeInstruction {
|
||||
pub src: InstructionSrc,
|
||||
pub dst: KlondikePileId,
|
||||
pub struct TableauStack {
|
||||
tableau: Tableau,
|
||||
skip_cards: SkipCards,
|
||||
}
|
||||
impl KlondikeInstruction {
|
||||
pub const fn stock() -> Self {
|
||||
Self {
|
||||
src: InstructionSrc::STOCK,
|
||||
dst: KlondikePileId::Stock,
|
||||
}
|
||||
}
|
||||
|
||||
impl TableauStack {
|
||||
const ITER_BEGIN: Self = Self {
|
||||
tableau: Tableau::ITER_BEGIN,
|
||||
skip_cards: SkipCards::ITER_BEGIN,
|
||||
};
|
||||
const fn next(self) -> Option<Self> {
|
||||
let KlondikeInstruction { src, dst } = self;
|
||||
if let Some(next_dst) = dst.next() {
|
||||
return Some(Self { src, dst: next_dst });
|
||||
}
|
||||
if let Some(next_src) = src.next() {
|
||||
let TableauStack {
|
||||
tableau,
|
||||
skip_cards,
|
||||
} = self;
|
||||
if let Some(skip_cards) = skip_cards.next() {
|
||||
return Some(Self {
|
||||
src: next_src,
|
||||
dst: KlondikePileId::Tableau1,
|
||||
tableau,
|
||||
skip_cards,
|
||||
});
|
||||
}
|
||||
if let Some(tableau) = tableau.next() {
|
||||
let skip_cards = SkipCards::Skip0;
|
||||
return Some(Self {
|
||||
tableau,
|
||||
skip_cards,
|
||||
});
|
||||
}
|
||||
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 {
|
||||
src: KlondikePile,
|
||||
foundation: Foundation,
|
||||
}
|
||||
impl DstFoundation {
|
||||
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 {
|
||||
src: KlondikePileStack,
|
||||
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 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 fn sum(n: usize) -> usize {
|
||||
n * (n + 1) / 2
|
||||
@@ -479,7 +458,7 @@ impl KlondikeIter {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
instruction: Some(KlondikeInstruction {
|
||||
src: InstructionSrc::new(KlondikePileStack::Tableau1(SkipCards::Zero)),
|
||||
src: InstructionSrc::new(KlondikePileStack::Tableau1(SkipCards::Skip0)),
|
||||
dst: KlondikePileId::Tableau2,
|
||||
}),
|
||||
}
|
||||
|
||||
+13
-13
@@ -152,19 +152,19 @@ fn find_valid_instruction(
|
||||
naive_instruction: NaiveInstruction,
|
||||
) -> Option<KlondikeInstruction> {
|
||||
const SKIP_LIST: [SkipCards; 13] = [
|
||||
SkipCards::Zero,
|
||||
SkipCards::One,
|
||||
SkipCards::Two,
|
||||
SkipCards::Three,
|
||||
SkipCards::Four,
|
||||
SkipCards::Five,
|
||||
SkipCards::Six,
|
||||
SkipCards::Seven,
|
||||
SkipCards::Eight,
|
||||
SkipCards::Nine,
|
||||
SkipCards::Ten,
|
||||
SkipCards::Eleven,
|
||||
SkipCards::Twelve,
|
||||
SkipCards::Skip0,
|
||||
SkipCards::Skip1,
|
||||
SkipCards::Skip2,
|
||||
SkipCards::Skip3,
|
||||
SkipCards::Skip4,
|
||||
SkipCards::Skip5,
|
||||
SkipCards::Skip6,
|
||||
SkipCards::Skip7,
|
||||
SkipCards::Skip8,
|
||||
SkipCards::Skip9,
|
||||
SkipCards::Skip10,
|
||||
SkipCards::Skip11,
|
||||
SkipCards::Skip12,
|
||||
];
|
||||
let dst = naive_instruction.dst;
|
||||
let src = match naive_instruction.src {
|
||||
|
||||
Reference in New Issue
Block a user