forest_fire_oo.sf 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #!/usr/bin/ruby
  2. define RED = "\e[1;31m";
  3. define YELLOW = "\e[1;33m";
  4. define GREEN = "\e[1;32m";
  5. define DIRS = [
  6. [-1, -1], [0, -1], [1, -1],
  7. [-1, 0], [1, 0],
  8. [-1, 1], [0, 1], [1, 1],
  9. ]
  10. enum (Empty, Tree, Heating, Burning);
  11. define pix = [' ', GREEN + "*", YELLOW + "*", RED + "*"];
  12. class Forest(p=0.01, f=0.001, height, width) {
  13. has coords = [];
  14. has spot = [];
  15. has neighbors = [];
  16. method init {
  17. coords = (0..height ~X 0..width)
  18. spot = height.of { width.of { [true, false].pick ? Tree : Empty } }
  19. self.init_neighbors
  20. }
  21. method init_neighbors {
  22. for i,j in coords {
  23. neighbors[i][j] = gather {
  24. for dir in DIRS {
  25. take(\(spot[i + dir[0]][j + dir[1]] \\ next));
  26. }
  27. }
  28. }
  29. }
  30. method step {
  31. var heat = [];
  32. for i,j in coords {
  33. given (spot[i][j]) {
  34. when Empty { spot[i][j] = Tree if (1.rand < p) }
  35. when Tree { spot[i][j] = Heating if (1.rand < f) }
  36. when Heating { spot[i][j] = Burning; heat << [i, j] }
  37. when Burning { spot[i][j] = Empty }
  38. }
  39. }
  40. for i,j in heat {
  41. neighbors[i][j].each { |ref|
  42. *ref = Heating if (*ref == Tree);
  43. }
  44. }
  45. }
  46. method show {
  47. for i in ^height {
  48. say pix[@spot[i]];
  49. }
  50. }
  51. }
  52. STDOUT.autoflush(true)
  53. var width = Num(`tput cols`)-1
  54. var height = Num(`tput lines`)-1
  55. var forest = Forest(height: height, width: width)
  56. print "\e[2J";
  57. loop {
  58. print "\e[H";
  59. forest.show;
  60. forest.step;
  61. }