grammar.rs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. use std::ops;
  2. use std::collections::{HashMap, HashSet};
  3. use std::hash::Hash;
  4. use rand::{Rng, thread_rng};
  5. /// Our indices here are two 32-bit signed values.
  6. type Index = (i32, i32);
  7. /// A `SparseBoard` here is a board that may or may not have every
  8. /// tile filled in, which we represent as a hashmap from indices to
  9. /// cells. When we use a `SparseBoard` as the LHS of a rule, we try to
  10. /// match every cell provided, but don't bother matching the cells
  11. /// which aren't provided; when we use one as the RHS of a rule, we
  12. /// instead overwrite only those cells provided in the board.
  13. ///
  14. /// A `SparseBoard` has a conceptual center, which is the cell at
  15. /// index `(0, 0)`. Indices in a `SparseBoard` can be negative.
  16. type SparseBoard<Cell> = HashMap<Index, Cell>;
  17. /// The most important parts of a `Rule` are its LHS and its
  18. /// RHS. These correspond respectively to the patterns which are
  19. /// matched, and the cells that are used to replace those
  20. /// patterns. Note that both of these are sparse boards: a pattern may
  21. /// be an arbitrary shape, and its replacement may replace all, some,
  22. /// or none of the cells matched by the LHS.
  23. pub struct Rule<Cell> {
  24. pub rule_name: Option<String>,
  25. pub requires: HashSet<Cell>,
  26. pub lhs: SparseBoard<Cell>,
  27. pub rhs: SparseBoard<Cell>,
  28. }
  29. pub struct Board<Cell> {
  30. pub width: u32,
  31. pub height: u32,
  32. pub cells: Vec<Cell>,
  33. pub contents: HashSet<Cell>,
  34. }
  35. impl<Cell: Clone + Hash + Eq> Board<Cell> {
  36. pub fn new(width: u32, height: u32, default: Cell) -> Board<Cell> {
  37. let cells = (0..width*height).map(|_| default.clone()).collect();
  38. let contents = vec![default].into_iter().collect();
  39. Board { width, height, cells, contents }
  40. }
  41. pub fn get<'a>(&'a self, (w, h): Index) -> Option<&'a Cell> {
  42. if w > 0 && w < self.width as i32 && h > 0 && h < self.height as i32 {
  43. Some(&self[(w, h)])
  44. } else {
  45. None
  46. }
  47. }
  48. pub fn indices(&self) -> Vec<Index> {
  49. let mut v = Vec::new();
  50. for x in 0..self.width {
  51. for y in 0..self.height {
  52. v.push((x as i32, y as i32))
  53. }
  54. }
  55. v
  56. }
  57. pub fn random_indices(&self) -> Vec<Index> {
  58. let mut v = self.indices();
  59. {
  60. let slice = v.as_mut_slice();
  61. thread_rng().shuffle(slice);
  62. }
  63. v
  64. }
  65. }
  66. impl Board<char> {
  67. pub fn print(&self) {
  68. for x in 0..self.width {
  69. for y in 0..self.height {
  70. print!("{} ", self[(x as i32, y as i32)]);
  71. }
  72. println!("");
  73. }
  74. }
  75. }
  76. impl<Cell> ops::Index<Index> for Board<Cell> {
  77. type Output = Cell;
  78. fn index(&self, (w, h): Index) -> &Cell {
  79. let n: usize = (w + (h * self.width as i32)) as usize;
  80. &self.cells[n as usize]
  81. }
  82. }
  83. impl<Cell> ops::IndexMut<Index> for Board<Cell> {
  84. fn index_mut(&mut self, (w, h): Index) -> &mut Cell {
  85. let n: usize = (w + (h * self.width as i32)) as usize;
  86. &mut self.cells[n as usize]
  87. }
  88. }
  89. impl<Cell: Clone + Hash + Eq> Rule<Cell> {
  90. /// Create a new `Rule` from two sparse grids of cells,
  91. /// corresponding respectively to the LHS and the RHS
  92. pub fn new(
  93. lhs: SparseBoard<Cell>,
  94. rhs: SparseBoard<Cell>,
  95. ) -> Rule<Cell> {
  96. let rule_name = None;
  97. let requires = lhs.values().cloned().collect();
  98. Rule { rule_name, requires, lhs, rhs }
  99. }
  100. /// Get mutable access to the LHS of the `Rule`, for modification
  101. /// later
  102. pub fn lhs_mut(&mut self) -> &mut SparseBoard<Cell> {
  103. &mut self.lhs
  104. }
  105. /// Get mutable access to the RHS of the `Rule`, for modification
  106. /// later
  107. pub fn rhs_mut(&mut self) -> &mut SparseBoard<Cell> {
  108. &mut self.lhs
  109. }
  110. /// Attempt to apply this rule to the provided board at random
  111. /// (i.e. if there are multiple possible applications of this
  112. /// rule, then it should choose one of them entirely at random
  113. pub fn apply_to_board(&self, b: &mut Board<Cell>) -> bool {
  114. // for each random location in the board
  115. 'outer: for (x, y) in b.random_indices() {
  116. // find out whether each of our tiles matche
  117. for (&(i, j), v) in self.lhs.iter() {
  118. // if a given tile doesn't, then skip ahead
  119. match b.get((x + i, y + j)) {
  120. Some(r) if v == r => (),
  121. _ => continue 'outer,
  122. }
  123. }
  124. // if all of them match, then do the rewrites!
  125. for (&(i, j), r) in self.rhs.iter() {
  126. b[(x + i, y + j)] = r.clone();
  127. }
  128. // and because the rule applied, we can quit now
  129. return true;
  130. }
  131. // if we've tried them all and none of them worked, then we've
  132. // failed
  133. false
  134. }
  135. }
  136. #[cfg(test)]
  137. #[test]
  138. pub fn grammar_test() {
  139. let rule1: Rule<char> = Rule::new(
  140. vec![ ((0, 0), 'x') ].into_iter().collect(),
  141. vec![ ((0, 0), 'y'), ((1, 0), 'y') ].into_iter().collect(),
  142. );
  143. let rule2: Rule<char> = Rule::new(
  144. vec![ ((0, 0), 'y') ].into_iter().collect(),
  145. vec![ ((0, 0), 'z') ].into_iter().collect(),
  146. );
  147. let mut board = Board::new(8, 8, '.');
  148. board[(2, 2)] = 'x';
  149. assert!(true, rule1.apply_to_board(&mut board));
  150. assert!(true, rule2.apply_to_board(&mut board));
  151. board.print();
  152. }