Brush.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. // $Id: foo.cpp 2979 2006-01-10 00:00:04Z sommer $
  2. //
  3. // Cobble - A simple SuperTux level editor
  4. // Copyright (C) 2006 Christoph Sommer <supertux@2006.expires.deltadevelopment.de>
  5. //
  6. // This program is free software; you can redistribute it and/or
  7. // modify it under the terms of the GNU General Public License
  8. // as published by the Free Software Foundation; either version 2
  9. // of the License, or (at your option) any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program; if not, write to the Free Software
  18. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  19. // 02111-1307, USA.
  20. using System;
  21. using System.Collections.Generic;
  22. using System.Text;
  23. using System.IO;
  24. namespace Cobble {
  25. class Brush {
  26. protected TileRepository tileRepository;
  27. protected List<int[,]> id_matrices = new List<int[,]>();
  28. protected List<bool[,]> solid_matrices = new List<bool[,]>();
  29. //protected int[,] getIdMatrix(int tx, int ty) {
  30. // return new int[3, 3] {
  31. // { getTileAt(tx-1,ty-1), getTileAt(tx+0,ty-1), getTileAt(tx+1,ty-1) },
  32. // { getTileAt(tx-1,ty+0), getTileAt(tx+0,ty+0), getTileAt(tx+1,ty+0) },
  33. // { getTileAt(tx-1,ty+1), getTileAt(tx+0,ty+1), getTileAt(tx+1,ty+1) }
  34. // };
  35. //}
  36. public Brush(TileRepository tileRepository) {
  37. this.tileRepository = tileRepository;
  38. }
  39. public int Length {
  40. get {
  41. return id_matrices.Count;
  42. }
  43. }
  44. public void saveToFile(string fname) {
  45. FileStream fs = new FileStream(fname, FileMode.Create);
  46. TextWriter tw = new StreamWriter(fs);
  47. foreach (int[,] m1 in id_matrices) {
  48. tw.WriteLine("" + m1[0, 0] + "," + m1[0, 1] + "," + m1[0, 2] + "," + m1[1, 0] + "," + m1[1, 1] + "," + m1[1, 2] + "," + m1[2, 0] + "," + m1[2, 1] + "," + m1[2, 2] + "");
  49. }
  50. tw.Close();
  51. fs.Close();
  52. }
  53. public static Brush loadFromFile(TileRepository tileRepository, string fname) {
  54. TileRepository tr = tileRepository;
  55. Brush brush = new Brush(tileRepository);
  56. FileStream fs = new FileStream(fname, FileMode.Open);
  57. TextReader trd = new StreamReader(fs);
  58. try {
  59. string s;
  60. while ((s = trd.ReadLine()) != null) {
  61. string[] v = s.Split(',');
  62. if (v.Length < 9) continue;
  63. int[,] ids = new int[3, 3] {
  64. {int.Parse(v[0]), int.Parse(v[1]), int.Parse(v[2])},
  65. {int.Parse(v[3]), int.Parse(v[4]), int.Parse(v[5])},
  66. {int.Parse(v[6]), int.Parse(v[7]), int.Parse(v[8])}
  67. };
  68. bool[,] sols = new bool[3, 3] {
  69. {tr.isSolid[int.Parse(v[0])], tr.isSolid[int.Parse(v[1])], tr.isSolid[int.Parse(v[2])]},
  70. {tr.isSolid[int.Parse(v[3])], tr.isSolid[int.Parse(v[4])], tr.isSolid[int.Parse(v[5])]},
  71. {tr.isSolid[int.Parse(v[6])], tr.isSolid[int.Parse(v[7])], tr.isSolid[int.Parse(v[8])]}
  72. };
  73. brush.id_matrices.Add(ids);
  74. brush.solid_matrices.Add(sols);
  75. }
  76. }
  77. catch (IOException) {
  78. }
  79. trd.Close();
  80. fs.Close();
  81. return brush;
  82. }
  83. protected bool equal(int[,] m1, int[,] m2) {
  84. for (int px = 0; px < 3; px++) {
  85. for (int py = 0; py < 3; py++) {
  86. if (m1[px, py] != m2[px, py]) return false;
  87. }
  88. }
  89. return true;
  90. }
  91. protected bool matrixExists(int[,] m1) {
  92. foreach (int[,] m2 in id_matrices) {
  93. if (equal(m1, m2)) return true;
  94. }
  95. return false;
  96. }
  97. //if (!careful) {
  98. // if (!matrixExists(new int[3, 3] {
  99. // { tm.getTileAt(tx-2,ty-1), m1[0, 0], m1[0, 1] },
  100. // { getTileAt(tx-2,ty+0), m1[1, 0], m1[1, 1] },
  101. // { getTileAt(tx-2,ty+1), m1[2, 0], m1[2, 1] }
  102. // })) thisSimilarity -= 100;
  103. // if (!matrixExists(new int[3, 3] {
  104. // { m1[0, 1], m1[0, 1], getTileAt(tx+2,ty-1)},
  105. // { m1[1, 1], m1[1, 2], getTileAt(tx+2,ty+0)},
  106. // { m1[2, 1], m1[2, 2], getTileAt(tx+2,ty+1)}
  107. // })) thisSimilarity -= 100;
  108. //}
  109. public void learn(Tilemap tilemap, int tx, int ty) {
  110. Tilemap tm = tilemap;
  111. TileRepository tr = tileRepository;
  112. int[,] m1 = new int[3, 3] {
  113. { tm.getTileAt(tx-1,ty-1), tm.getTileAt(tx+0,ty-1), tm.getTileAt(tx+1,ty-1) },
  114. { tm.getTileAt(tx-1,ty+0), tm.getTileAt(tx+0,ty+0), tm.getTileAt(tx+1,ty+0) },
  115. { tm.getTileAt(tx-1,ty+1), tm.getTileAt(tx+0,ty+1), tm.getTileAt(tx+1,ty+1) }
  116. };
  117. bool[,] m2 = new bool[3, 3] {
  118. { tr.isSolid[tm.getTileAt(tx-1,ty-1)], tr.isSolid[tm.getTileAt(tx+0,ty-1)], tr.isSolid[tm.getTileAt(tx+1,ty-1)] },
  119. { tr.isSolid[tm.getTileAt(tx-1,ty+0)], tr.isSolid[tm.getTileAt(tx+0,ty+0)], tr.isSolid[tm.getTileAt(tx+1,ty+0)] },
  120. { tr.isSolid[tm.getTileAt(tx-1,ty+1)], tr.isSolid[tm.getTileAt(tx+0,ty+1)], tr.isSolid[tm.getTileAt(tx+1,ty+1)] }
  121. };
  122. if (!matrixExists(m1)) {
  123. id_matrices.Add(m1);
  124. solid_matrices.Add(m2);
  125. }
  126. }
  127. public void learn(Tilemap tilemap) {
  128. for (int tx = 0; tx < tilemap.width; tx++) {
  129. for (int ty = 0; ty < tilemap.height; ty++) {
  130. learn(tilemap, tx, ty);
  131. }
  132. }
  133. }
  134. public void forget(Tilemap tilemap, int tx, int ty) {
  135. Tilemap tm = tilemap;
  136. TileRepository tr = tileRepository;
  137. int[,] m1 = new int[3, 3] {
  138. { tm.getTileAt(tx-1,ty-1), tm.getTileAt(tx+0,ty-1), tm.getTileAt(tx+1,ty-1) },
  139. { tm.getTileAt(tx-1,ty+0), tm.getTileAt(tx+0,ty+0), tm.getTileAt(tx+1,ty+0) },
  140. { tm.getTileAt(tx-1,ty+1), tm.getTileAt(tx+0,ty+1), tm.getTileAt(tx+1,ty+1) }
  141. };
  142. bool[,] m2 = new bool[3, 3] {
  143. { tr.isSolid[tm.getTileAt(tx-1,ty-1)], tr.isSolid[tm.getTileAt(tx+0,ty-1)], tr.isSolid[tm.getTileAt(tx+1,ty-1)] },
  144. { tr.isSolid[tm.getTileAt(tx-1,ty+0)], tr.isSolid[tm.getTileAt(tx+0,ty+0)], tr.isSolid[tm.getTileAt(tx+1,ty+0)] },
  145. { tr.isSolid[tm.getTileAt(tx-1,ty+1)], tr.isSolid[tm.getTileAt(tx+0,ty+1)], tr.isSolid[tm.getTileAt(tx+1,ty+1)] }
  146. };
  147. for (int i = 0; i < id_matrices.Count; i++) {
  148. if (equal(m1, id_matrices[i])) {
  149. id_matrices.RemoveAt(i);
  150. solid_matrices.RemoveAt(i);
  151. }
  152. }
  153. }
  154. protected void draw(Tilemap tilemap, int tx, int ty, bool erase) {
  155. Tilemap tm = tilemap;
  156. TileRepository tr = tileRepository;
  157. int[,] desiredIdPattern = new int[3, 3] {
  158. { tm.getTileAt(tx-1,ty-1), tm.getTileAt(tx+0,ty-1), tm.getTileAt(tx+1,ty-1) },
  159. { tm.getTileAt(tx-1,ty+0), tm.getTileAt(tx+0,ty+0), tm.getTileAt(tx+1,ty+0) },
  160. { tm.getTileAt(tx-1,ty+1), tm.getTileAt(tx+0,ty+1), tm.getTileAt(tx+1,ty+1) }
  161. };
  162. bool[,] desiredSolPattern = new bool[3, 3] {
  163. { tr.isSolid[tm.getTileAt(tx-1,ty-1)], tr.isSolid[tm.getTileAt(tx+0,ty-1)], tr.isSolid[tm.getTileAt(tx+1,ty-1)] },
  164. { tr.isSolid[tm.getTileAt(tx-1,ty+0)], !erase , tr.isSolid[tm.getTileAt(tx+1,ty+0)] },
  165. { tr.isSolid[tm.getTileAt(tx-1,ty+1)], tr.isSolid[tm.getTileAt(tx+0,ty+1)], tr.isSolid[tm.getTileAt(tx+1,ty+1)] }
  166. };
  167. float bestSimilarity = 0;
  168. int[,] bestPattern = new int[3, 3] {
  169. { tm.getTileAt(tx-1,ty-1), tm.getTileAt(tx+0,ty-1), tm.getTileAt(tx+1,ty-1) },
  170. { tm.getTileAt(tx-1,ty+0), tm.getTileAt(tx+0,ty+0), tm.getTileAt(tx+1,ty+0) },
  171. { tm.getTileAt(tx-1,ty+1), tm.getTileAt(tx+0,ty+1), tm.getTileAt(tx+1,ty+1) }
  172. };
  173. for (int i = 0; i < id_matrices.Count; i++) {
  174. int[,] m1 = id_matrices[i];
  175. int[,] m2 = desiredIdPattern;
  176. bool[,] m3 = solid_matrices[i];
  177. bool[,] m4 = desiredSolPattern;
  178. float thisSimilarity = 0;
  179. for (int px = 0; px < 3; px++) {
  180. for (int py = 0; py < 3; py++) {
  181. if ((px == 1) && (py == 1)) {
  182. if (tr.isSolid[m1[px, py]] == (!erase)) thisSimilarity += 1000;
  183. continue;
  184. }
  185. if (m1[px, py] == m2[px, py]) thisSimilarity += 1;
  186. if (m3[px, py] == m4[px, py]) thisSimilarity += 100;
  187. }
  188. }
  189. if (thisSimilarity > bestSimilarity) { bestSimilarity = thisSimilarity; bestPattern = m1; }
  190. }
  191. if (bestSimilarity > 0) {
  192. int[,] m1 = bestPattern;
  193. tm.setTileAt(tx - 1, ty - 1, m1[0, 0]);
  194. tm.setTileAt(tx + 0, ty - 1, m1[0, 1]);
  195. tm.setTileAt(tx + 1, ty - 1, m1[0, 2]);
  196. tm.setTileAt(tx - 1, ty + 0, m1[1, 0]);
  197. tm.setTileAt(tx + 0, ty + 0, m1[1, 1]);
  198. tm.setTileAt(tx + 1, ty + 0, m1[1, 2]);
  199. tm.setTileAt(tx - 1, ty + 1, m1[2, 0]);
  200. tm.setTileAt(tx + 0, ty + 1, m1[2, 1]);
  201. tm.setTileAt(tx + 1, ty + 1, m1[2, 2]);
  202. }
  203. }
  204. public void draw(Tilemap tilemap, int tx, int ty) {
  205. draw(tilemap, tx, ty, false);
  206. }
  207. public void erase(Tilemap tilemap, int tx, int ty) {
  208. draw(tilemap, tx, ty, true);
  209. }
  210. }
  211. }