Advertisement
Guest User

Untitled

a guest
Sep 17th, 2019
166
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.64 KB | None | 0 0
  1. class Cell
  2.  
  3. attr_reader :type
  4. attr_reader :value
  5. attr_reader :glpyh
  6.  
  7. attr_accessor :position
  8.  
  9. def initialize(type, value, glpyh, position)
  10. @type = type
  11. @value = value
  12. @glpyh = glpyh
  13. @position = position
  14. end
  15.  
  16. def empty?
  17. return self.type == :empty
  18. end
  19.  
  20. def self.empty(x, y)
  21. return Cell.new(:empty, nil, " ", [x, y])
  22. end
  23.  
  24. def self.parse_tile(char, x, y)
  25. case char
  26. when "?"
  27. return Tile.new(:input, nil, char, [x, y])
  28. when "*"
  29. return Tile.new(:scanner, nil, char, [x, y])
  30. when "F"
  31. return Tile.new(:furnace, nil, char, [x, y])
  32. when ">"
  33. return Tile.new(:belt_right, nil, char, [x, y])
  34. when "<"
  35. return Tile.new(:belt_left, nil, char, [x, y])
  36. when "i"
  37. return Tile.new(:copy_up, nil, char, [x, y])
  38. when "!"
  39. return Tile.new(:copy_down, nil, char, [x, y])
  40. when "r"
  41. return Tile.new(:random, nil, char, [x, y])
  42. when "T"
  43. return Tile.new(:turning_point, nil, char, [x, y])
  44. when "["
  45. return Tile.new(:bulldozer_right, nil, char, [x, y])
  46. when "]"
  47. return Tile.new(:bulldozer_left, nil, char, [x, y])
  48. when "\\"
  49. return Tile.new(:ramp_right, nil, char, [x, y])
  50. when "/"
  51. return Tile.new(:ramp_left, nil, char, [x, y])
  52.  
  53. when /\d/
  54. return Value.new(:data, char.to_i, char, [x, y])
  55. when " "
  56. return empty(x, y)
  57. else
  58. return Tile::WALL
  59. end
  60. end
  61.  
  62. end
  63.  
  64. class Tile < Cell
  65. WALL = Tile.new(:wall, nil, "=", [0, 0])
  66. end
  67.  
  68. class Value < Cell
  69. end
  70.  
  71. class VocalRunner
  72.  
  73. def initialize(initial_world, world_name, args)
  74. @world = initial_world.strip.split("\n").map.with_index do |row, j|
  75. row.split("").map.with_index do |char, i|
  76. Cell.parse_tile(char, i, j)
  77. end
  78. end
  79. @name = world_name
  80. @input = [*args]
  81. @output = []
  82. @debug = []
  83. validate_world
  84. end
  85.  
  86. def validate_world
  87. all_cells = @world.flatten
  88. if all_cells.count { |cell| cell.type == :input } > 1
  89. raise "InvalidWorldException: More than one input found."
  90. end
  91. end
  92.  
  93. def add_value(x, y, value)
  94. if value.is_a?(Numeric)
  95. if (0..9).include?(value)
  96. glpyh = value.to_s
  97. else
  98. glpyh = "#"
  99. end
  100. elsif value.is_a?(String)
  101. glpyh = "\""
  102. else
  103. glpyh = "#"
  104. end
  105. cell = Value.new(:data, value, glpyh, [x, y])
  106. set_cell(x, y, cell)
  107. end
  108.  
  109. def get_cell(x, y)
  110. return Tile::WALL if y < 0 or y >= @world.size
  111. return Tile::WALL if x < 0 or x >= @world[y].size
  112. return @world[y][x]
  113. end
  114.  
  115. def set_cell(x, y, cell)
  116. return if y < 0 or y >= @world.size
  117. return if x < 0 or x >= @world[y].size
  118. @world[y][x] = cell
  119. cell.position = [x, y]
  120. end
  121.  
  122. def clear_cell(x, y)
  123. set_cell(x, y, Cell.empty(x, y))
  124. end
  125.  
  126. def move_cell_horizontal(x, y, dx)
  127. value = get_cell(x, y)
  128. target = [x + dx, y]
  129. if get_cell(*target).empty?
  130. set_cell(*target, value)
  131. clear_cell(x, y)
  132. return true
  133. # elsif ramp
  134. # TODO: handle ramps
  135. end
  136. return false
  137. end
  138.  
  139. def get_input
  140. return @input.shift
  141. end
  142.  
  143. def add_output(value)
  144. @output.push(value)
  145. end
  146.  
  147. def log(message)
  148. @debug.push(message)
  149. end
  150.  
  151. def run
  152. display
  153. while tick
  154. begin
  155. puts
  156. display
  157. sleep(0.1)
  158. rescue Exception
  159. break
  160. end
  161. end
  162. unless @output.empty?
  163. puts
  164. puts @output.join("\n")
  165. end
  166. unless @debug.empty?
  167. puts
  168. puts @debug.join("\n")
  169. end
  170. end
  171.  
  172. def display
  173. @world.each do |row|
  174. puts row.map { |cell| cell.glpyh }.join("")
  175. end
  176. end
  177.  
  178. def tick
  179. any_changes = false
  180.  
  181. all_cells = @world.flatten
  182.  
  183.  
  184. #---
  185. # Input
  186. #---
  187. all_cells.select { |cell| cell.type == :input }
  188. .each do |input|
  189. x, y = *input.position
  190. target = [x, y + 1]
  191. if get_cell(*target).empty?
  192. value = get_input
  193. unless value.nil?
  194. add_value(*target, value)
  195. any_changes = true
  196. end
  197. end
  198. end
  199.  
  200. #---
  201. # Random
  202. #---
  203. all_cells.select { |cell| cell.type == :random }
  204. .each do |input|
  205. x, y = *input.position
  206. target = [x, y + 1]
  207. if get_cell(*target).empty?
  208. value = rand(10)
  209. unless value.nil?
  210. add_value(*target, value)
  211. any_changes = true
  212. end
  213. end
  214. end
  215.  
  216. #---
  217. # Scanner
  218. #---
  219. all_cells.select { |cell| cell.type == :scanner }
  220. .each do |scanner|
  221. x, y = *scanner.position
  222. target = [x, y + 1]
  223. value = get_cell(*target)
  224. if value.is_a?(Value)
  225. add_output(value.value)
  226. end
  227. end
  228.  
  229. #---
  230. # Furnace
  231. #---
  232. all_cells.select { |cell| cell.type == :furnace }
  233. .each do |furnace|
  234. x, y = *furnace.position
  235. (-1..1).map { |j| j + y }.each do |j|
  236. (-1..1).map { |i| i + x }.each do |i|
  237. next if j == y and i == x
  238. cell = get_cell(i, j)
  239. if cell.is_a?(Value)
  240. clear_cell(i, j)
  241. any_changes = true
  242. end
  243. end
  244. end
  245. end
  246.  
  247. #---
  248. # Copiers
  249. #---
  250. all_cells.select { |cell| cell.type == :copy_up }
  251. .sort_by { |cell| cell.position[1] }
  252. .each do |copier|
  253. x, y = *copier.position
  254. origin = [x, y + 1]
  255. target = [x, y - 1]
  256. value = get_cell(*origin)
  257. if value.is_a?(Value) and get_cell(*target).empty?
  258. set_cell(*target, value)
  259. any_changes = true
  260. end
  261. end
  262.  
  263. #---
  264. # Bulldozers
  265. #---
  266. all_cells.select { |cell| cell.type == :bulldozer_left }
  267. .sort_by { |cell| cell.position[0] }
  268. .each do |dozer|
  269. x, y = *dozer.position
  270. if get_cell(x - 1, y).is_a?(Value)
  271. if move_cell_horizontal(x - 1, y, -1)
  272. any_changes = true
  273. end
  274. end
  275. if move_cell_horizontal(x, y, -1)
  276. any_changes = true
  277. if get_cell(x - 1, y - 1).type == :turning_point
  278. flipped = Tile.new(:bulldozer_right, nil, "[", [x - 1, y])
  279. set_cell(x - 1, y, flipped)
  280. end
  281. end
  282. end
  283. all_cells.select { |cell| cell.type == :bulldozer_right }
  284. .sort_by { |cell| cell.position[0] }
  285. .each do |dozer|
  286. x, y = *dozer.position
  287. if get_cell(x + 1, y).is_a?(Value)
  288. if move_cell_horizontal(x + 1, y, 1)
  289. any_changes = true
  290. end
  291. end
  292. if move_cell_horizontal(x, y, 1)
  293. any_changes = true
  294. if get_cell(x + 1, y - 1).type == :turning_point
  295. flipped = Tile.new(:bulldozer_left, nil, "]", [x + 1, y])
  296. set_cell(x + 1, y, flipped)
  297. end
  298. end
  299. end
  300.  
  301. #---
  302. # Belts
  303. #---
  304. all_cells.select { |cell| cell.type == :belt_left }
  305. .sort_by { |cell| cell.position[0] }
  306. .each do |belt|
  307. x, y = *belt.position
  308. if get_cell(x, y - 1).is_a?(Value)
  309. if move_cell_horizontal(x, y - 1, -1)
  310. any_changes = true
  311. end
  312. end
  313. end
  314. all_cells.select { |cell| cell.type == :belt_right }
  315. .sort_by { |cell| -cell.position[0] }
  316. .each do |belt|
  317. x, y = *belt.position
  318. if get_cell(x, y - 1).is_a?(Value)
  319. if move_cell_horizontal(x, y - 1, 1)
  320. any_changes = true
  321. end
  322. end
  323. end
  324.  
  325. #---
  326. # Adders
  327. #---
  328. all_cells.select { |cell| cell.type == :adder }
  329. .each do |adder|
  330. x, y = *adder.position
  331. input_1 = get_cell(x, y - 1)
  332. input_2 = get_cell(x, y - 1)
  333. if input_1.is_a?(Value) and input_2.is_a?(Value)
  334. sum = input_1.value + input_2.value
  335. # TODO: decide where inputs go, and where outputs go
  336. any_changes = true
  337. end
  338. end
  339.  
  340. # TODO: subtracters
  341.  
  342. # TODO: doors that close their sides when there's anything above them
  343. # TODO: doors that close their sides when there's a value above them,
  344. # and they also decrease that value by one every time, and remove
  345. # it when it gets to 0
  346.  
  347. return any_changes
  348. end
  349.  
  350. end
  351.  
  352.  
  353. code = <<-END
  354.  
  355. .T?.*.T.T.T
  356. F[ F 2]
  357. ....o......
  358. ...........
  359.  
  360. END
  361.  
  362. # code = <<-END
  363.  
  364. # ..?..*..
  365. # . F
  366. # ..>>>>>.
  367.  
  368. # END
  369.  
  370. runner = VocalRunner.new(code, "test", [1, 0, 3, 2, 5, 4])
  371. runner.run
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement