I called out a challenge, each participant should code not more than somewhat around one hour (max 75 minutes), language of your choice, OOP prefered (best in one file only).

There no right or wrong, just the time to beat. It sure won’t be the best code you had ever written - but that’s fine. It’s all about excercising, having fun and laughing about your final result when the time is over.

Specifications

  • build a chess board (a1 to h8)
  • add figurines, one black, one white
  • both figurines can walk 1 step (up, down, left, right)
  • white starts at g1
  • black starts at a8
  • only white moves and wipes black off the board with exactly 15 steps

optional:

  • validate no one steps off the board
  • log steps
  • track wipes

here is what i came up with

what I like:

  • the board as hash
  • board has most of the game logic

what I dislike:

  • how I solved moving, I would use an abstraction of the board next time
class Board
  attr_reader :types, :grid, :alphabet, :draws, :kill_stack
  def initialize
    @figures = {}
    @draws = {}
    @types = %i[peasant king queen tower horse bishop1]
    @kill_stack = []
    @alphabet = ('a'..'h').to_a
    @grid =
      {
        h1: nil, g1: nil, f1: nil, e1: nil, d1: nil, c1: nil, b1: nil, a1: nil,
        h2: nil, g2: nil, f2: nil, e2: nil, d2: nil, c2: nil, b2: nil, a2: nil,
        h3: nil, g3: nil, f3: nil, e3: nil, d3: nil, c3: nil, b3: nil, a3: nil,
        h4: nil, g4: nil, f4: nil, e4: nil, d4: nil, c4: nil, b4: nil, a4: nil,
        h5: nil, g5: nil, f5: nil, e5: nil, d5: nil, c5: nil, b5: nil, a5: nil,
        h6: nil, g6: nil, f6: nil, e6: nil, d6: nil, c6: nil, b6: nil, a6: nil,
        h7: nil, g7: nil, f7: nil, e7: nil, d7: nil, c7: nil, b7: nil, a7: nil,
        h8: nil, g8: nil, f8: nil, e8: nil, d8: nil, c8: nil, b8: nil, a8: nil
      }
  end

  def place_figure(figure)
    raise ArgumentError unless figure.color == :white || figure.color == :black

    @figures[figure.color] ||= {}
    @figures[figure.color][figure.type] = figure
    @grid[figure.position] = figure
  end

  def move_figurine(figure, new_position)
    puts "moving figure #{figure.type} #{figure.color} from #{figure.position} to #{new_position}"

    check_grid?(new_position)

    @grid[figure.position] = nil
    @draws[figure.color] || @draws[figure.color] = 0
    figure.position = new_position
    @draws[figure.color] = @draws[figure.color] + 1
    @grid[new_position] = figure
  end

  def check_grid(new_position)
    figure = @grid[new_position]
    puts 'you captured the king' if figure && figure.type == :king
    @kill_stack.push(figure) if figure
    figure
  end

  def check_grid?(new_position)
    !!check_grid(new_position)
  end

  def show_grid
    temp_grid = {}
    @grid.each do |field_id, figure|
      temp_grid[field_id] = (figure.name if figure)
    end
    puts temp_grid
  end
end

class Figurine
  attr_reader :board, :color, :type
  attr_accessor :position
  def initialize(board, starting_position, color, type)
    @board = board
    @position = starting_position
    @color = color
    @type = type
    validate_initialize
  end

  def name
    "#{color} #{type}"
  end

  private

  def validate_initialize
    raise ArgumentError unless @color == :black || @color == :white
    raise ArgumentError unless @board.is_a?(Board)
    raise ArgumentError unless @position.is_a?(Symbol) && @board.grid.keys.any? { |grid_elem| grid_elem == @position }
    raise ArgumentError unless @board.types.include? @type
  end
end

class Peasant < Figurine
  def move(position)
    @position = position
    @board.grid[:position]
  end

  def extract_row_column_from_position
    column = @position.to_s.split('').first # :a8
    row = @position.to_s.split('').last.to_i # :a8
    { column: column, row: row }
  end

  def move_forward
    row, column = extract_row_column_from_position.values_at(:row, :column)

    if @color == :black
      raise ArgumentError if row - 1 < 1

      @board.move_figurine(self, "#{column}#{row - 1}".to_sym)
    elsif @color == :white
      raise ArgumentError if row + 1 > 8

      @board.move_figurine(self, "#{column}#{row + 1}".to_sym)
    end
  end

  def move_backward
    row, column = extract_row_column_from_position.values_at(:row, :column)

    if @color == :black
      raise ArgumentError if row + 1 > 8

      @board.move_figurine(self, "#{column}#{row + 1}").to_sym
    elsif @color == :white
      raise ArgumentError if row - 1 < 1

      @board.move_figurine(self, "#{column}#{row - 1}".to_sym)
    end
  end

  def move_left
    row, column = extract_row_column_from_position.values_at(:row, :column)

    alphabet = @board.alphabet
    if @color == :black
      next_step = alphabet.index(column) + 1
      raise ArgumentError if next_step > 7

      @board.move_figurine(self, "#{alphabet[next_step]}#{row}").to_sym
    elsif @color == :white
      next_step = alphabet.index(column) - 1
      raise ArgumentError if next_step < 0

      @board.move_figurine(self, "#{alphabet[next_step]}#{row}".to_sym)
    end
  end

  def move_right
    row, column = extract_row_column_from_position.values_at(:row, :column)

    alphabet = @board.alphabet
    if @color == :black
      next_step = alphabet.index(column) - 1
      raise ArgumentError if next_step < 0

      @board.move_figurine(self, "#{alphabet[next_step]}#{row}").to_sym
    elsif @color == :white
      next_step = alphabet.index(column) + 1
      raise ArgumentError if next_step > 7

      @board.move_figurine(self, "#{alphabet[next_step]}#{row}".to_sym)
    end
  end
end

current_board = Board.new
peasant_white = Peasant.new(current_board, :g1, :white, :peasant)
peasant_black = Peasant.new(current_board, :a8, :black, :peasant)

current_board.place_figure(peasant_white)
current_board.place_figure(peasant_black)

puts current_board.show_grid
puts current_board.grid[:a8].name
puts current_board.grid[:g1].name

peasant_white.move_forward
peasant_white.move_forward
peasant_white.move_forward
peasant_white.move_forward
peasant_white.move_forward
peasant_white.move_forward
peasant_white.move_forward

peasant_white.move_left
peasant_white.move_right
peasant_white.move_left
peasant_white.move_left
peasant_white.move_left
peasant_white.move_left
peasant_white.move_left
peasant_white.move_left

puts current_board.draws

puts current_board.show_grid
puts 'wiped: ' << current_board.kill_stack.map(&:name).join(', ')
``