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
6fn 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
29pub 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
45pub 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
61pub 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
78pub 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
94pub 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
111pub 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
128pub 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}