SHARE
TWEET

Untitled

a guest Sep 17th, 2019 112 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top