1 pub use glam::i32::IVec2 as Pos;
2 use rand::seq::IteratorRandom;
3 use std::cell::RefCell;
10 fn swap(self) -> Self {
11 Self::new(self.y, self.x)
15 pub struct Field(RefCell<u32>);
29 pub fn value(&self) -> u32 {
33 fn merge(&self, other: &Self) -> MergeResult {
34 let mut s = self.0.borrow_mut();
35 let mut o = other.0.borrow_mut();
38 return MergeResult::Empty;
45 return MergeResult::Replaced;
52 return MergeResult::Merged(1 << *s);
61 fields: Vec<Vec<Field>>,
72 pub fn new(size: Pos) -> Self {
76 .map(|_| (0..size.y).map(|_| Field::new()).collect())
81 pub fn step(&self, dir: Dir) -> Option<u32> {
89 let step_row = dir.abs().swap();
92 let len_row = (step_row.abs() * self.size).max_element();
93 let len_col = (step_col.abs() * self.size).max_element();
95 let start = (dir + Pos::ONE) / 2 * (self.size - Pos::ONE);
99 for row in 0..len_row {
100 let start_row = start + row * step_row;
102 for col1 in 0..len_col - 1 {
103 let field1 = self.get(start_row + col1 * step_col);
105 for col2 in col1 + 1..len_col {
106 let field2 = self.get(start_row + col2 * step_col);
108 match field1.merge(field2) {
109 MergeResult::Merged(sc) => {
110 score = Some(score.unwrap_or(0) + sc);
113 MergeResult::Replaced => score = Some(score.unwrap_or(0)),
114 MergeResult::Blocked => break,
115 MergeResult::Empty => continue,
124 pub fn get(&self, pos: Pos) -> &Field {
132 pub fn spawn<R>(&self, rng: &mut R)
134 R: rand::Rng + ?core::marker::Sized,
136 if let Some(field) = self
139 .flat_map(|v| v.iter())
140 .filter(|f| f.value() == 0)
143 *field.0.borrow_mut() = 1;