# frozen_string_literal: true RSpec.describe GameOfLife::Universe do describe ".new" do it "creates a @current 2D array (Plane) of height * width" do universe = described_class.new(width: 10, height: 1) current_generation = universe.instance_variable_get(:@current) expect(current_generation).to be_a GameOfLife::Plane expect(current_generation[0]).to be_a GameOfLife::Plane expect(current_generation.size).to eq 1 expect(current_generation[0].size).to eq 10 end it "creates a @future 2D array (Plane) of height * width" do universe = described_class.new(width: 10, height: 1) future_generation = universe.instance_variable_get(:@future) expect(future_generation).to be_a GameOfLife::Plane expect(future_generation[0]).to be_a GameOfLife::Plane expect(future_generation.size).to eq 1 expect(future_generation[0].size).to eq 10 end end describe "#to_s" do subject(:universe) { described_class.new(width: 3, height: 3) } before do universe[0] = [1, 2, 3] universe[1] = [4, 5, 6] universe[2] = [7, 8, 9] end it "prints out the universe 2D @current array" do expect(universe.to_s).to eq "123\n456\n789" end end describe "#evolve!" do subject(:universe) { described_class.new(width: 3, height: 3) } before do # quick way to initialize the whole universe with living cells 9.times { |i| universe[i / 3][i % 3] = GameOfLife::Cell.new(y: i / 3, x: i % 3, alive: true) } end it "calls Cell#evolve! on every cell" do 9.times { |i| expect(universe[i / 3][i % 3]).to receive(:evolve!) } universe.evolve! end it "updates the universe current state" do 9.times { |i| expect(universe[i / 3][i % 3]).to be_alive } universe.evolve! 9.times { |i| expect(universe[i / 3][i % 3]).to be_dead } end end describe "#neighbors" do subject(:universe) { described_class.new(width: 5, height: 5) } it "returns surronding neighbors" do current = GameOfLife::Plane.new( [ GameOfLife::Plane.new(%w[. . . . .]), GameOfLife::Plane.new(%w[. x x x .]), GameOfLife::Plane.new(%w[. x C x .]), GameOfLife::Plane.new(%w[. x x x .]), GameOfLife::Plane.new(%w[. . . . .]), ], ) universe.instance_variable_set(:@current, current) cell = GameOfLife::Cell.new(y: 2, x: 2, alive: "C") expect(universe.send(:neighbors, cell)).to eq %w[x x x x x x x x] end it "returns surronding neighbors (beyond top edge)" do current = GameOfLife::Plane.new( [ GameOfLife::Plane.new(%w[. x C x .]), GameOfLife::Plane.new(%w[. x x x .]), GameOfLife::Plane.new(%w[. . . . .]), GameOfLife::Plane.new(%w[. . . . .]), GameOfLife::Plane.new(%w[. x x x .]), ], ) universe.instance_variable_set(:@current, current) cell = GameOfLife::Cell.new(y: 0, x: 2, alive: "C") expect(universe.send(:neighbors, cell)).to eq %w[x x x x x x x x] end it "returns surronding neighbors (beyond left edge)" do current = GameOfLife::Plane.new( [ GameOfLife::Plane.new(%w[. . . . .]), GameOfLife::Plane.new(%w[. . . . .]), GameOfLife::Plane.new(%w[x x . . x]), GameOfLife::Plane.new(%w[C x . . x]), GameOfLife::Plane.new(%w[x x . . x]), ], ) universe.instance_variable_set(:@current, current) cell = GameOfLife::Cell.new(y: 3, x: 0, alive: "C") expect(universe.send(:neighbors, cell)).to eq %w[x x x x x x x x] end it "returns surronding neighbors (beyond diagonal edges)" do current = GameOfLife::Plane.new( [ GameOfLife::Plane.new(%w[C x . . x]), GameOfLife::Plane.new(%w[x x . . x]), GameOfLife::Plane.new(%w[. . . . .]), GameOfLife::Plane.new(%w[. . . . .]), GameOfLife::Plane.new(%w[x x . . x]), ], ) universe.instance_variable_set(:@current, current) cell = GameOfLife::Cell.new(y: 0, x: 0, alive: "C") expect(universe.send(:neighbors, cell)).to eq %w[x x x x x x x x] end it "returns surronding neighbors (beyond reversed diagonal edges)" do current = GameOfLife::Plane.new( [ GameOfLife::Plane.new(%w[x . . x x]), GameOfLife::Plane.new(%w[. . . . .]), GameOfLife::Plane.new(%w[. . . . .]), GameOfLife::Plane.new(%w[x . . x x]), GameOfLife::Plane.new(%w[x . . x C]), ], ) universe.instance_variable_set(:@current, current) cell = GameOfLife::Cell.new(y: 4, x: 4, alive: "C") expect(universe.send(:neighbors, cell)).to eq %w[x x x x x x x x] end end end