kewb/cube/
generators.rs

1use crate::constants::{CO_COUNT, CP_COUNT, EO_COUNT, EP_COUNT};
2
3use super::{cubie::CubieCube, index::*};
4use rand::{rngs::ThreadRng, seq::SliceRandom, thread_rng, Rng};
5
6/// Randomly swaps corner or edges to fix parity.
7fn fix_parity(state: &mut CubieCube, rng: &mut ThreadRng, corners: Vec<usize>, edges: Vec<usize>) {
8    if rng.gen_bool(0.5) {
9        swap_edges(state, rng, edges)
10    } else {
11        swap_corners(state, rng, corners)
12    }
13}
14
15fn swap_edges(state: &mut CubieCube, rng: &mut ThreadRng, edges: Vec<usize>) {
16    let pos: Vec<&usize> = edges.choose_multiple(rng, 2).collect();
17    let a = *pos[0];
18    let b = *pos[1];
19    state.ep.swap(a, b)
20}
21
22fn swap_corners(state: &mut CubieCube, rng: &mut ThreadRng, corners: Vec<usize>) {
23    let pos: Vec<&usize> = corners.choose_multiple(rng, 2).collect();
24    let a = *pos[0];
25    let b = *pos[1];
26    state.cp.swap(a, b)
27}
28
29/// Generates a random state with corners solved.
30pub fn generate_state_corners_solved() -> CubieCube {
31    let mut rng = thread_rng();
32    let mut state = CubieCube {
33        ep: index_to_ep(rng.gen_range(0..EP_COUNT)),
34        eo: index_to_eo(rng.gen_range(0..EO_COUNT)),
35        ..Default::default()
36    };
37
38    if !state.is_solvable() {
39        swap_edges(&mut state, &mut rng, (0..12).collect());
40    }
41
42    state
43}
44
45/// Generates a random state with edges solved.
46pub fn generate_state_edges_solved() -> CubieCube {
47    let mut rng = thread_rng();
48    let mut state = CubieCube {
49        cp: index_to_cp(rng.gen_range(0..CP_COUNT)),
50        co: index_to_co(rng.gen_range(0..CO_COUNT)),
51        ..Default::default()
52    };
53
54    if !state.is_solvable() {
55        swap_corners(&mut state, &mut rng, (0..8).collect());
56    }
57
58    state
59}
60
61/// Generates a random state with oriented solved last layer cross.
62pub fn generate_state_oll_cross_solved() -> CubieCube {
63    let mut rng = thread_rng();
64    let mut state = CubieCube {
65        cp: index_to_cp_f2l(rng.gen_range(0..4)),
66        co: index_to_co_f2l(rng.gen_range(0..27)),
67        ep: index_to_ep_f2l(rng.gen_range(0..24)),
68        ..Default::default()
69    };
70
71    if !state.is_solvable() {
72        fix_parity(&mut state, &mut rng, (0..4).collect(), (4..8).collect())
73    }
74
75    state
76}
77
78/// Generates a random state with oriented last layer corners and edges.
79pub fn generate_state_oll_solved() -> CubieCube {
80    let mut rng = thread_rng();
81    let mut state = CubieCube {
82        cp: index_to_cp_f2l(rng.gen_range(0..4)),
83        ep: index_to_ep_f2l(rng.gen_range(0..24)),
84        ..Default::default()
85    };
86
87    if !state.is_solvable() {
88        fix_parity(&mut state, &mut rng, (0..4).collect(), (4..8).collect())
89    }
90
91    state
92}
93
94/// Generates a random state with solved First two layer.
95pub fn generate_state_f2l_solved() -> CubieCube {
96    let mut rng = thread_rng();
97    let mut state = CubieCube {
98        cp: index_to_cp_f2l(rng.gen_range(0..4)),
99        co: index_to_co_f2l(rng.gen_range(0..27)),
100        ep: index_to_ep_f2l(rng.gen_range(0..24)),
101        eo: index_to_eo_f2l(rng.gen_range(0..8)),
102    };
103
104    if !state.is_solvable() {
105        fix_parity(&mut state, &mut rng, (0..4).collect(), (4..8).collect())
106    }
107
108    state
109}
110
111/// Generates a random state with solved cross.
112pub fn generate_state_cross_solved() -> CubieCube {
113    let mut rng = thread_rng();
114    let mut state = CubieCube {
115        cp: index_to_cp(rng.gen_range(0..CP_COUNT)),
116        co: index_to_co(rng.gen_range(0..CO_COUNT)),
117        ep: index_to_ep_cross(rng.gen_range(0..40320)),
118        eo: index_to_eo_cross(rng.gen_range(0..128)),
119    };
120
121    if !state.is_solvable() {
122        fix_parity(&mut state, &mut rng, (0..8).collect(), (0..8).collect())
123    }
124
125    state
126}
127
128/// Generates a random state on the cubie level.
129pub fn generate_random_state() -> CubieCube {
130    let mut rng = thread_rng();
131    let mut state = CubieCube {
132        cp: index_to_cp(rng.gen_range(0..CP_COUNT)),
133        co: index_to_co(rng.gen_range(0..CO_COUNT)),
134        ep: index_to_ep(rng.gen_range(0..EP_COUNT)),
135        eo: index_to_eo(rng.gen_range(0..EO_COUNT)),
136    };
137
138    if !state.is_solvable() {
139        fix_parity(&mut state, &mut rng, (0..8).collect(), (0..12).collect())
140    }
141
142    state
143}