require 'mkmf' module Chess # Use Gnuchess to I.A. _(Only a draft)_. # # To use this module, extend a game object with {Chess::Gnuchess}. # @note Gnuchess binary have to be installed. # @example # g = Chess::Game.new # g.extend Chess::Gnuchess # g.gnuchess_move! # puts g module Gnuchess # Returns the next move calculated by Gnuchess. # @return [String] Returns the short algebraic chess notation of the move. def gnuchess_move pipe = IO.popen('gnuchess -x', 'r+') begin pipe.puts('depth 1') pipe.puts('manual') self.coord_moves.each do |m| pipe.puts(m) end pipe.puts('go') while (line = pipe.gets) raise IllegalMoveError if line.include?('Invalid move') match = line.match(/My move is : ([a-h][1-8][a-h][1-8][rkbq]?)/) return match[1] if match end ensure pipe.puts('quit') pipe.close end return moves end # Make a move using Gnuchess engine. # @note This add a new {Board} in the {Game}. # @return [String] Returns the short algebraic chess notation of the move. def gnuchess_move! next_move = self.gnuchess_move self.move(next_move) if next_move end class << self private def included(_mod) raise_if_gnuchess_is_not_installed end def extended(_mod) raise_if_gnuchess_is_not_installed end # Raise an exception if Gnuchess is not installed def raise_if_gnuchess_is_not_installed raise 'You must install Gnuchess to use the module Chess::Gnuchess!' unless find_executable0('gnuchess') end end private def gen_pgn(file_to_save, moves = []) done = false pipe = IO.popen('gnuchess', 'r+') begin pipe.write("depth 1\n") pipe.write("force\n") pipe.write("name chess.rb\n") moves.each do |move| pipe.write("#{move}\n") end until done pipe.write("go\n") while (line = pipe.gets) break if line.include?('My move is : ') break if line.include?(' : resign') if / : 1-0 {White mates}/.match?(line) done = :white_won break elsif / : 0-1 {Black mates}/.match?(line) done = :black_won break elsif (m = line.match(/1\/2-1\/2 {(.*?)}/)) case m[1] when 'Stalemate' done = :stalemate when 'Draw by repetition' done = :repetition when 'Draw by fifty-move rule' done = :fifty_move_rule when 'Draw by insufficient material' done = :insufficient_material end break end end end dir = File.dirname(file_to_save) name = File.basename(file_to_save) pipe.write("pgnsave #{File.join(dir, done.to_s, name)}\n") ensure pipe.write("quit\n") pipe.close end end end end