online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code   
Language
# frozen_string_literal: true require_relative 'game' class GameInterface def initialize @color_choices = %w[black white] @directory = './saved-games' end def start loop do display_menu process_choice(gets.chomp.to_i) end end private def display_menu puts 'Pick one:' puts '' puts '(1) Human vs. computer' puts '(2) Human vs. human' puts '(3) Load saved game' end def process_choice(choice) case choice when 1 setup_and_start_computer_game when 2 start_human_game when 3 load_game end end def setup_and_start_computer_game color = get_color_choice game = setup_game(color, true) game.play_game end def start_human_game game = Game.new game.play_game end def get_color_choice puts 'Do you want to play as Black or White?' color = nil until @color_choices.include?(color) color = gets.chomp.downcase puts 'Invalid choice.' unless @color_choices.include?(color) end color end def setup_game(color, play_with_computer) game = Game.new game.play_with_computer = play_with_computer if color == 'black' game.print_color = 'black' game.computer_has_turn = game.computer_has_turn.reverse end game end def load_game if Dir.entries(@directory).length == 2 system 'clear' puts "\e[38;5;196mNo games have been saved.\e[0m" puts '' else game = get_saved_game game&.play_from_saved end end def get_saved_game puts 'Pick a saved game:' Dir.entries(@directory).each do |filename| puts filename unless ['.', '..'].include? filename end filename = nil until Dir.entries(@directory).include?(filename) filename = gets.chomp.downcase return Game.load_game("#{@directory}/#{filename}") if Dir.entries(@directory).include?(filename) puts 'Invalid filename. Please re-type.' end end end system 'clear' GameInterface.new.start
# frozen_string_literal: true require_relative 'piece' class Bishop < Piece def legal_move?(board, check_king_safety = true) find_distances condition = @distance_y == @distance_x && no_friendly_at_dest?(board) && diagonal_clear?(board) check_king_safety ? condition && results_in_king_safety?(board) : condition end end
# frozen_string_literal: true require_relative 'display' require_relative 'fen_manager' require_relative 'draw_manager' require_relative 'piece' require_relative 'knight' require_relative 'bishop' require_relative 'rook' require_relative 'queen' require_relative 'king' require_relative 'pawn' class Board include Display include FenManager include DrawManager attr_reader :pieces, :board, :white_has_castled, :black_has_castled attr_accessor :legal_pieces, :state def initialize @state = 8.times.map { 8.times.map { nil } } @pieces = %w[Rook Knight Bishop Queen King Bishop Knight Rook] @legal_pieces = [] @positions = [] @white_has_castled = false @black_has_castled = false end def add_piece(piece, y, x) @state[y][x] = piece @state[y][x].set_origin(@state) end def create_piece(name, color) label = color == 'black' ? name.downcase : name Object.const_get(name).new(label.slice(0, 3), color) end def add_home_rank(rank, color) @state[rank].each_index do |i| add_piece(create_piece(@pieces[i], color), rank, i) end end def add_pawn_rank(rank, color) @state[rank].each_index do |i| add_piece(create_piece('Pawn', color), rank, i) end end def setup_board add_home_rank(0, 'black') add_pawn_rank(1, 'black') add_pawn_rank(6, 'white') add_home_rank(7, 'white') end def reset_piece_state(piece) piece.set_origin(@state) piece.unmoved = false @state.each do |row| row.each do |el| el.unset_moved if el.instance_of?(Pawn) end end end def set_piece_state(piece, dest_y, dest_x) piece.set_destination(dest_y, dest_x) piece.set_origin(@state) end def set_nil(piece, origin_y, origin_x, dest_x) @state[origin_y][dest_x] = nil if piece.instance_of?(Pawn) && piece.en_passant_possible?(self) @state[origin_y][origin_x] = nil end def move_piece_if_legal(piece, origin_y, origin_x, dest_y, dest_x) return unless piece.legal_move?(self) @state[dest_y][dest_x] = piece set_nil(piece, origin_y, origin_x, dest_x) end def make_move(origin_y, origin_x, dest_y, dest_x, computer_has_turn, print_color) piece = @state[origin_y][origin_x] set_piece_state(piece, dest_y, dest_x) move_piece_if_legal(piece, origin_y, origin_x, dest_y, dest_x) reset_piece_state(piece) piece.set_moved_two if piece.instance_of?(Pawn) && (origin_y - dest_y).abs == 2 piece.promote(self, computer_has_turn, print_color) if piece.instance_of?(Pawn) end def piece_at?(color, dest_y, dest_x, side) dest_piece = @state[dest_y][dest_x] !dest_piece.nil? && (side == 'friendly' ? color == dest_piece.color : color != dest_piece.color) end def direction_clear?(origin, destination, y_inc, x_inc, y = origin[0], x = origin[1]) path = [] loop do y += y_inc x += x_inc break if destination == [y, x] || !y.between?(0, 7) || !x.between?(0, 7) path << @state[y][x].nil? end path.all? end def diagonal_clear?(origin, destination) inc_y = destination[0] > origin[0] ? 1 : -1 inc_x = destination[1] > origin[1] ? 1 : -1 direction_clear?(origin, destination, inc_y, inc_x) end def horizontal_clear?(origin, destination) if destination[0] != origin[0] inc_x = 0 inc_y = destination[0] > origin[0] ? 1 : -1 else inc_y = 0 inc_x = destination[1] > origin[1] ? 1 : -1 end direction_clear?(origin, destination, inc_y, inc_x) end def square_safe?(king, dest_y, dest_x) opponent_pieces = @state.flatten.select { |el| el.is_a?(Piece) && el.color != king.color } opponent_pieces.each do |piece| piece.set_origin(@state) piece.set_destination(dest_y, dest_x) end @state[king.origin[0]][king.origin[1]] = nil boolean = opponent_pieces.none? do |piece| piece.instance_of?(Pawn) ? piece.square_attackable? : piece.legal_move?(self, check_king_safety = false) end @state[king.origin[0]][king.origin[1]] = king boolean end def find_king(color) @state.each do |row| row.each do |piece| return piece if piece.instance_of?(King) && piece.color == color end end end def king_is_safe?(color) king = find_king(color) dest_y = king.origin[0] dest_x = king.origin[1] square_safe?(king, dest_y, dest_x) end def each_square_safe?(king, dir, y = king.origin[0], x = king.origin[1]) coords = [[y, x], [y, x + dir], [y, x + dir * 2]] booleans = [] coords.each do |sub_arr| booleans << square_safe?(king, sub_arr[0], sub_arr[1]) end booleans.all? end def castle(king, rook, dir, y = king.origin[0], king_x = king.origin[1], rook_x = rook.origin[1]) king_dest_x = king_x + dir * 2 rook_dest_x = king_x + dir if horizontal_clear?([y, king_x], [y, rook_x]) && each_square_safe?(king, dir) && king.unmoved && rook.unmoved @state[y][king_x], @state[y][rook_x] = nil, nil add_piece(king, y, king_dest_x) add_piece(rook, y, rook_dest_x) king.color == 'white' ? @white_has_castled = true : @black_has_castled = true king.unmoved, rook.unmoved = false, false else false end end def find_legal_pieces(turn_color, piece_name, dest_y, dest_x) @state.each do |row| row.each do |piece| next unless !piece.nil? && piece.color == turn_color && piece.piece_name.downcase == piece_name piece.set_destination(dest_y, dest_x) @legal_pieces << piece if piece.legal_move?(self) piece.destination = [] end end end def find_pawn_origin(turn_color, dest_y, dest_x) @state.each do |row| piece = row[dest_x] next unless !piece.nil? && piece.color == turn_color && piece.instance_of?(Pawn) piece.set_destination(dest_y, dest_x) @legal_pieces << piece if piece.legal_move?(self) piece.destination = [] end end def check_if_legal(turn_color, origin_y, origin_x, dest_y, dest_x) piece = @state[origin_y][origin_x] return unless !piece.nil? && piece.color == turn_color piece.set_destination(dest_y, dest_x) @legal_pieces << piece if piece.legal_move?(self) end def print_for_rspec @state.each do |row| row.each do |piece| if piece.nil? print '--- ' else print "#{piece.piece_name} " end end puts end end def player_mated?(color) @state.each do |row| row.each do |piece| next unless piece && piece.color == color @state.each_with_index do |row, y| row.each_index do |x| piece.set_destination(y, x) return false if piece.legal_move?(self) piece.destination = [] end end end end true end def player_checkmated?(color) king = find_king(color) !square_safe?(king, king.origin[0], king.origin[1]) && player_mated?(color) end def player_stalemated?(color) king = find_king(color) square_safe?(king, king.origin[0], king.origin[1]) && player_mated?(color) end end
# frozen_string_literal: true module ComputerPlayer def legal_moves(color) legal_moves = [] @board.state.each do |row| row.each do |piece| next unless piece && piece.color == color @board.state.each_with_index do |row, y| row.each_index do |x| piece.set_destination(y, x) legal_moves << [piece.origin, piece.destination] if piece.legal_move?(@board) piece.destination = [] end end end end legal_moves end def sample_legal_moves(color) legal_moves(color).sample end end
# frozen_string_literal: true module Display def init_escape_sequences @dark_bg = "\e[48;5;253m" @light_bg = "\e[48;5;231m" @black_fg = "\e[30m" @red_fg = "\e[38;5;196m" @reset = "\e[0m" end def init_pieces @blank = ' ' @red = { kin: 'K', que: 'Q', roo: 'R', bis: 'B', kni: 'N', paw: 'P' }.transform_values { |value| @red_fg + value } @black = @red.transform_values { |value| @black_fg + value[11..] } end def init_display init_escape_sequences init_pieces end def build_empty_board @board = Array.new(8) do |row_i| Array.new(8) do |el_i| (row_i.even? == el_i.even? ? @light_bg : @dark_bg) + @blank + @reset end end end def fill_board build_empty_board @state.each_with_index do |row, y| row.each_with_index do |square, x| if square piece = square.piece_name.downcase.to_sym @board[y][x][-6] = square.color == 'white' ? @red[piece] : @black[piece] end end end end def board_as_black @board.reverse.map(&:reverse) end def print_board(side, board = @board, rank = 9, i = -1, letters = (' a'..' h')) if side == 'black' (board = board_as_black rank = 0 i = 1 letters = letters.to_a.reverse) end print ' ', *letters, "\n" board.each do |row| print rank += i, ' ' row.each { |square| print square } print ' ', rank, "\n" end print ' ', *letters, "\n" end def full_print_sequence(side) init_display fill_board print_board(side) end end
# frozen_string_literal: true module DrawManager def pieces_for_draw_check pieces = [] @state.each do |row| row.each do |piece| pieces << piece if piece end end pieces end def only_two_kings? pieces_for_draw_check.length == 2 end def lone_bishop_or_knight? pieces_for_draw_check.length == 3 && pieces_for_draw_check.any? do |piece| piece.piece_name.downcase =~ /^(kni|bis)$/ end end def bishops pieces_for_draw_check.filter { |piece| piece.piece_name.downcase == 'bis' } end def same_color_bishops? bishops.all? { |bishop| bishop.origin.sum.even? } || bishops.all? { |bishop| bishop.origin.sum.odd? } end def only_same_color_bishops? pieces_for_draw_check.length == 4 && bishops.length == 2 && same_color_bishops? end def insufficient_material? only_two_kings? || lone_bishop_or_knight? || only_same_color_bishops? end def count_pawns_by_row fen_split = output_fen.split '/' pawn_count_array = [] fen_split.each do |row| pawn_count_array << row.count('p') + row.count('P') end pawn_count_array end def count_pieces i = 0 @state.each do |row| row.each do |piece| i += 1 if piece end end i end def pawn_and_piece_counts array = count_pawns_by_row array << count_pieces array end end
# frozen_string_literal: true module FenManager def output_fen @state.map do |row| row.map do |piece| case piece when nil then 1 when Rook then piece.color == 'white' ? 'R' : 'r' when Knight then piece.color == 'white' ? 'N' : 'n' when Bishop then piece.color == 'white' ? 'B' : 'b' when Queen then piece.color == 'white' ? 'Q' : 'q' when King then piece.color == 'white' ? 'K' : 'k' when Pawn then piece.color == 'white' ? 'P' : 'p' end end.join end.join('/').gsub(/1+/) { |ones| ones.length.to_s } end def push_position @positions << output_fen end def get_positions @positions end def count_repeated_positions fen_counts = Hash.new(0) @positions.each do |fen| fen_counts[fen] += 1 end fen_counts.values.max end end
# frozen_string_literal: true require_relative 'input_handler' require_relative 'computer_player' require_relative 'board' require_relative 'input' class Game include InputHandler include ComputerPlayer attr_reader :board attr_accessor :play_with_computer, :computer_has_turn, :print_color def initialize @board = Board.new @turn_color = %w[white black] @game_status = 'ongoing' @input = '' @fifty_move_increment = 0 @letters = { 'n' => 'kni', 'b' => 'bis', 'r' => 'roo', 'q' => 'que', 'k' => 'kin' } @play_with_computer = false @computer_has_turn = [false, true] @print_color = 'white' end def get_input_until_valid loop do puts "#{@turn_color[0].capitalize}, enter move or 'help'." @input = Input.instance.get_input break if input_valid? puts 'Invalid input. Try again.' end end def continue_sequence system 'clear' @board.full_print_sequence(@print_color) @turn_color.reverse! recursive_sequence end def set_game_status @game_status = if @board.player_stalemated?(@turn_color[0]) 'stalemate' elsif @board.player_checkmated?(@turn_color[0]) 'mate' elsif @board.insufficient_material? 'insufficient material' elsif @input == 'resign' 'resignation' elsif agreement_valid? 'draw by agreement' elsif @board.count_repeated_positions == 3 'threefold' elsif @fifty_move_increment == 50 'fifty' end end def puts_ending case @game_status when 'mate' puts "Checkmate. #{@turn_color[1].capitalize} wins." when 'stalemate' puts 'Stalemate. Teehee!' when 'insufficient material' puts 'Draw by insufficient material.' when 'resignation' puts "#{@turn_color[1].capitalize} resigns. #{@turn_color[0].capitalize} wins!" when 'draw by agreement' puts 'Draw by agreement.' when 'threefold' puts 'Draw by threefold repetition.' when 'fifty' puts 'Draw by fifty-move rule.' end end def end_condition? ['mate', 'stalemate', 'insufficient material', 'resignation', 'draw by agreement', 'threefold', 'fifty'].include?(@game_status) end def get_draw_response if @computer_has_turn[1] && @play_with_computer puts 'Computer takes pity on you and accepts the draw.' sleep(2.5) @draw_response = 'accept' else loop do @draw_response = gets.chomp.downcase break if @draw_response == 'accept' || @draw_response == 'decline' puts "'Please enter 'accept' or 'decline'." end end end def handle_draw_agreement return unless draw_offered? @draw_offered = true unless @computer_has_turn[1] && @play_with_computer puts "#{@turn_color[0].capitalize} offers draw. #{@turn_color[1].capitalize}, please accept or decline." end get_draw_response unless agreement_valid? @draw_offered = false @turn_color.reverse! end continue_sequence end def set_computer_move random_move = sample_legal_moves(@turn_color[0]) sleep 0.5 @origin_y = random_move[0][0] @origin_x = random_move[0][1] @dest_y = random_move[1][0] @dest_x = random_move[1][1] end def make_computer_move pre_castle_state = [@board.white_has_castled, @board.black_has_castled] castle_as_computer(1) castle_as_computer(-1) post_castle_state = [@board.white_has_castled, @board.black_has_castled] return unless pre_castle_state == post_castle_state @board.make_move(@origin_y, @origin_x, @dest_y, @dest_x, @computer_has_turn[0], @print_color) end def print_instructions puts '' File.open('instructions.txt', 'r') do |file| file.each_line do |line| puts line end end puts '' end def handle_help return unless @input == 'help'.downcase print_instructions get_input_until_valid end def handle_input get_input_until_valid handle_draw_agreement handle_help retrieve_dest branch end def recursive_sequence set_game_status if end_condition? puts_ending return end if @computer_has_turn[0] set_computer_move else handle_input save_sequence end return if end_condition? make_computer_move if @computer_has_turn[0] before_move_state = @board.pawn_and_piece_counts unless @input == 'resign' || @computer_has_turn[0] @board.make_move(@origin_y, @origin_x, @dest_y, @dest_x, false, @print_color) end after_move_state = @board.pawn_and_piece_counts @fifty_move_increment += before_move_state != after_move_state ? -@fifty_move_increment : 0.5 @board.push_position @computer_has_turn.reverse! if @play_with_computer continue_sequence end def abort puts 'Illegal move.' recursive_sequence end def get_origin_from_piece_letter @board.find_legal_pieces(@turn_color[0], lookup_piece, @dest_y, @dest_x) legal_count = @board.legal_pieces.length if legal_count.zero? abort elsif legal_count > 1 puts "More than one such piece can move there. State origin square and destination square, e.g. 'a1a4'." recursive_sequence else retrieve_origin_from_piece @board.legal_pieces = [] end end def get_origin_for_pawn_push @board.find_pawn_origin(@turn_color[0], @dest_y, @dest_x) legal_count = @board.legal_pieces.length if legal_count.zero? abort else retrieve_origin_from_piece @board.legal_pieces = [] end end def check_legality retrieve_unambiguous_origin @board.check_if_legal(@turn_color[0], @origin_y, @origin_x, @dest_y, @dest_x) legal_count = @board.legal_pieces.length if legal_count.zero? abort else @board.legal_pieces = [] end end def try_castle(dir) has_castled = @turn_color[0] == 'white' ? @board.white_has_castled : @board.black_has_castled abort if has_castled || @board.find_king(@turn_color[0]).unmoved == false king = @board.find_king(@turn_color[0]) rook = if dir == 1 @turn_color[0] == 'white' ? @board.state[7][7] : @board.state[0][7] else @turn_color[0] == 'white' ? @board.state[7][0] : @board.state[0][0] end abort if rook.nil? || @board.castle(king, rook, dir) == false end def castle_as_computer(dir) return if @board.find_king(@turn_color[0]).unmoved == false king = @board.find_king(@turn_color[0]) rook = if dir == 1 @turn_color[0] == 'white' ? @board.state[7][7] : @board.state[0][7] else @turn_color[0] == 'white' ? @board.state[7][0] : @board.state[0][0] end @board.castle(king, rook, dir) unless rook.nil? end def branch if pawn_push? get_origin_for_pawn_push elsif unambiguous? check_legality elsif non_pawn? get_origin_from_piece_letter elsif short_c? try_castle(1) @computer_has_turn.reverse! if @play_with_computer continue_sequence elsif long_c? try_castle(-1) @computer_has_turn.reverse! if @play_with_computer continue_sequence end end def save_game(filename) File.open("./saved-games/#{filename}", 'w') do |file| file.puts Marshal.dump(self) end end def self.load_game(filename) File.open(filename, 'r') do |file| Marshal.load(file) end end def play_game @board.setup_board system 'clear' @board.full_print_sequence(@print_color) @board.push_position recursive_sequence end def play_from_saved system 'clear' @board.full_print_sequence(@print_color) @board.push_position recursive_sequence end def play_saved_game(filename) game = load_game(filename) game.play_game end end
# frozen_string_literal: true require 'singleton' class Input include Singleton def get_input @value = gets.chomp.downcase end end
# frozen_string_literal: true module InputHandler def draw_offered? @input == 'offer draw' end def agreement_valid? @draw_response == 'accept' && @draw_offered end def claim_draw? @input == 'claim draw' end def long_c? @input == 'o-o-o' end def short_c? @input == 'o-o' end def resign? @input == 'resign' end def algebraic?(index_1, index_2) @input[index_1].between?('a', 'h') && @input[index_2].between?('1', '8') end def pawn_push? @input.length == 2 && algebraic?(-2, -1) end def non_pawn? @input.length == 3 && @letters.key?(@input[0]) && algebraic?(-2, -1) end def unambiguous? @input.length == 4 && algebraic?(0, 1) && algebraic?(-2, -1) end def save_game? @input == 'save game' || @input == 'save' end def help? @input == 'h' || @input == 'help' end def input_valid? non_pawn? || pawn_push? || short_c? || long_c? || draw_offered? || agreement_valid? || claim_draw? || resign? || unambiguous? || save_game? || help? end def save_sequence return unless save_game? puts 'Please enter filename.' filename = gets.chomp save_game(filename) recursive_sequence end def retrieve_dest @dest_y = 8 - @input[-1].to_i @dest_x = ('a'..'h').to_a.index @input[-2] end def retrieve_unambiguous_origin @origin_y = 8 - @input[1].to_i @origin_x = ('a'..'h').to_a.index @input[0] end def retrieve_origin_from_piece @origin_y = @board.legal_pieces[0].origin[0] @origin_x = @board.legal_pieces[0].origin[1] end def lookup_piece @letters[@input[0]] end end
# frozen_string_literal: true require_relative 'piece' class King < Piece def empty_square_safe?(board) board.square_safe?(self, @destination[0], @destination[1]) end def capture_safe?(board, y = @destination[0], x = @destination[1]) if board.state[y][x] && board.state[y][x].color != color dummy_board = Board.new dummy_board.state = Marshal.load(Marshal.dump(board.state)) dummy_board.state[y][x] = nil dummy_board.state[@origin[0]][@origin[1]] = nil empty_square_safe?(dummy_board) else true end end def legal_move?(board, check_king_safety = true) find_distances condition = no_friendly_at_dest?(board) && @distance_y.between?(0, 1) && @distance_x.between?(0, 1) check_king_safety ? condition && empty_square_safe?(board) && capture_safe?(board) : condition end end
# frozen_string_literal: true require_relative 'piece' class Knight < Piece def legal_move?(board, check_king_safety = true) find_distances condition = [@distance_y, @distance_x].sort == [1, 2] && no_friendly_at_dest?(board) check_king_safety ? condition && results_in_king_safety?(board) : condition end end
# frozen_string_literal: true require_relative 'piece' class Pawn < Piece attr_reader :moved_two def at_starting_square? @origin[0] == (@color == 'white' ? 6 : 1) end def set_direction(c = @color == 'white') @one_step = c ? -1 : 1 @two_step = c ? -2 : 2 end def set_moved_two @moved_two = true end def unset_moved @moved_two = false end def square_attackable? find_distances dir = @color == 'black' ? 1 : -1 @destination[0] == @origin[0] + dir && @distance_x == 1 end def en_passant_possible?(board) board.piece_at?(@color, @origin[0], @destination[1], 'opponent') && board.state[@origin[0]][@destination[1]].instance_of?(Pawn) && board.state[@origin[0]][@destination[1]].moved_two end def enemy_at_attackable?(board) square_attackable? && (board.piece_at?(@color, @destination[0], @destination[1], 'opponent') || en_passant_possible?(board)) end def x_in_bounds?(_board) @destination[1] == @origin[1] end def one_or_two_steps?(board) @destination[0] == @origin[0] + @one_step || (at_starting_square? && @destination[0] == @origin[0] + @two_step && horizontal_clear?(board)) end def no_opponent_in_front?(board) !board.piece_at?(@color, @destination[0], @destination[1], 'opponent') end def legal_move?(board, check_king_safety = true) set_direction condition = (no_opponent_in_front?(board) && no_friendly_at_dest?(board) && one_or_two_steps?(board) && x_in_bounds?(board) || enemy_at_attackable?(board)) check_king_safety ? condition && results_in_king_safety?(board) : condition end def prompt_loop(board, computer_has_turn, print_color, piece_name = nil) until board.pieces.reject { |el| el == 'King' }.include?(piece_name) system 'clear' board.full_print_sequence(print_color) puts 'Enter name of new piece for pawn promotion.' piece_name = computer_has_turn ? 'Queen' : Input.instance.get_input.capitalize end piece_name end def promote(board, computer_has_turn, print_color) return unless (@origin[0]).zero? || @origin[0] == 7 color = (@origin[0]).zero? ? 'white' : 'black' piece_name = prompt_loop(board, computer_has_turn, print_color) new_piece = board.create_piece(piece_name, color) board.add_piece(new_piece, @origin[0], @origin[1]) end end
# frozen_string_literal: true class Piece attr_reader :origin, :piece_name, :color attr_accessor :unmoved, :destination def initialize(piece_name, color) @piece_name = piece_name @color = color @destination = [] @origin = [] @moved_two = false @unmoved = true end def set_origin(state) state.each do |row| @origin = state.index(row), row.index(self) if row.include? self end end def set_destination(y, x) @destination = [y, x] end def find_distances @distance_y = (@origin[0] - @destination[0]).abs @distance_x = (@origin[1] - @destination[1]).abs end def no_friendly_at_dest?(board) !board.piece_at?(@color, @destination[0], @destination[1], 'friendly') end def diagonal_clear?(board) board.diagonal_clear?(@origin, @destination) end def horizontal_clear?(board) board.horizontal_clear?(@origin, @destination) end def results_in_king_safety?(board) dest_y = @destination[0] dest_x = @destination[1] check_test_board = Board.new check_test_board.state = Marshal.load(Marshal.dump(board.state)) check_test_board.state[@origin[0]][@origin[1]] = nil check_test_board.state[dest_y][dest_x] = dup check_test_board.king_is_safe?(@color) end end
# frozen_string_literal: true require_relative 'piece' class Queen < Piece def queen_path_clear?(board) @destination[0] == @origin[0] || @destination[1] == @origin[1] ? horizontal_clear?(board) : diagonal_clear?(board) end def legal_move?(board, check_king_safety = true) find_distances condition = no_friendly_at_dest?(board) && queen_path_clear?(board) && (@distance_y == @distance_x || (@distance_y.zero? || @distance_x.zero?)) check_king_safety ? condition && results_in_king_safety?(board) : condition end end
# frozen_string_literal: true require_relative 'piece' class Rook < Piece def legal_move?(board, check_king_safety = true) find_distances condition = (@distance_y.zero? || @distance_x.zero?) && no_friendly_at_dest?(board) && horizontal_clear?(board) check_king_safety ? condition && results_in_king_safety?(board) : condition end end
Piece Moves: Enter a piece's letter followed by its destination square (e.g. 'nf3') -- n is the piece letter, and f3 is the destination square coordinate. Alternatively, use unambiguous notation (e.g. 'e4f3'), which is simply origin square (e4) immediately followed by destination square (f3), with no space between. Pawn captures require the latter. You can use both notations so that you can enter the moves a bit more quickly, or rely entirely on the unambiguous notation -- it's not possible to play without relying on the unambiguous notation for certain moves. If you want to use the first option, a piece's piece letter is simply the first letter of its piece name -- except for the knight, whose piece letter is "n" (since "k" is for the king). Pawn Moves: Just use file and rank (e.g., 'e4') -- that is, the destination square of the pawn. For pawn captures, you must use unambiguous notation (e.g., 'e4d5'). Castling: Use 'o-o' for kingside castling, and 'o-o-o' for queenside castling. Saving games: Type 'save'.

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text
×

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue