X-Git-Url: http://git.sourceforge.jp/view?p=shogi-server%2Fshogi-server.git;a=blobdiff_plain;f=shogi_server%2Fboard.rb;h=bcf888781dba52cbca32d830065d07bb2bc465ac;hp=be22ef19f03d9ca745beff162dfe29eb6f6fed34;hb=66e7c4522f3597aef4f23eabedd718734459a1e7;hpb=3ab213167ab29caa43f8040592ad172a7da3b000 diff --git a/shogi_server/board.rb b/shogi_server/board.rb index be22ef1..bcf8887 100644 --- a/shogi_server/board.rb +++ b/shogi_server/board.rb @@ -1,7 +1,7 @@ ## $Id$ ## Copyright (C) 2004 NABEYA Kenichi (aka nanami@2ch) -## Copyright (C) 2007-2008 Daigo Moriwaki (daigo at debian dot org) +## Copyright (C) 2007-2012 Daigo Moriwaki (daigo at debian dot org) ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ class Board # Initial board setup. # The string ends with '+', not a line break. # - INITIAL_POSITION = (<<-EOF).chomp + INITIAL_HIRATE_POSITION = (<<-EOF).chomp P1-KY-KE-GI-KI-OU-KI-GI-KE-KY P2 * -HI * * * * * -KA * P3-FU-FU-FU-FU-FU-FU-FU-FU-FU @@ -43,17 +43,42 @@ EOF # Split a moves line into an array of a move string. # If it fails to parse the moves, it raises WrongMoves. - # @param moves a moves line. Ex. "+776FU-3334Fu" - # @return an array of a move string. Ex. ["+7776FU", "-3334FU"] + # @param moves a moves line. Ex. "+776FU-3334FU" or + # moves with times. Ex "+776FU,T2-3334FU,T5" + # @return an array of a move string. Ex. ["+7776FU", "-3334FU"] or + # an array of arrays. Ex. [["+7776FU","T2"], ["-3334FU", "T5"]] # def Board.split_moves(moves) ret = [] - rs = moves.gsub %r{[\+\-]\d{4}\w{2}} do |s| - ret << s - "" - end - raise WrongMoves, rs unless rs.empty? + i=0 + tmp = "" + while i true, white => false @initial_moves = [] + @move = nil + @ous = [nil, nil] # keep OU pieces of Sente and Gote end attr_accessor :array, :sente_hands, :gote_hands, :history, :sente_history, :gote_history, :teban attr_reader :move_count @@ -78,6 +105,11 @@ EOF # moves. attr_reader :initial_moves + # A move parsed by handle_one_move. If the move is not :normal, the board + # position may or may not be rolled back. + # + attr_reader :move + # See if self equals rhs, including a logical board position (i.e. # not see object IDs) and sennichite stuff. # @@ -128,6 +160,17 @@ EOF @teban = true end + # Cache OU piece. + # Piece#new will call back this method. + # + def add_ou(ou) + if ou.sente + @ous[0] = ou + else + @ous[1] = ou + end + end + # Set up a board with the strs. # Failing to parse the moves raises an StandardError. # @param strs a board text @@ -230,14 +273,21 @@ EOF # Set up a board starting with a position after the moves. # Failing to parse the moves raises an ArgumentError. - # @param moves an array of moves. ex. ["+7776FU", "-3334FU"] + # @param moves an array of moves. ex. ["+7776FU", "-3334FU"] or + # an array of arrays. ex. [["+7776FU","T2"], ["-3334FU","T5"]] # def set_from_moves(moves) initial() return :normal if moves.empty? rt = nil moves.each do |move| - rt = handle_one_move(move, @teban) + rt = nil + case move + when Array + rt = handle_one_move(move[0], @teban) + when String + rt = handle_one_move(move, @teban) + end raise ArgumentError, "bad moves: #{moves}" unless rt == :normal end @initial_moves = moves.dup @@ -324,22 +374,13 @@ EOF end # def each_reserved_square - + def look_for_ou(sente) - x = 1 - while (x <= 9) - y = 1 - while (y <= 9) - if (@array[x][y] && - (@array[x][y].name == "OU") && - (@array[x][y].sente == sente)) - return @array[x][y] - end - y = y + 1 - end - x = x + 1 + if sente + return @ous[0] + else + return @ous[1] end - raise "can't find ou" end # See if sente is checked (i.e. loosing) or not. @@ -585,6 +626,7 @@ EOF # - :uchifuzume # - :oute_kaihimore # - (:outori will not be returned) + # - :max_moves # def handle_one_move(str, sente=nil) if (str =~ /^([\+\-])(\d)(\d)(\d)(\d)([A-Z]{2})/) @@ -643,18 +685,18 @@ EOF return :illegal # can't put on existing piece end - move = Move.new(x0, y0, x1, y1, name, sente) - result = move_to(move) + @move = Move.new(x0, y0, x1, y1, name, sente) + result = move_to(@move) if (result == :illegal) # self is unchanged return :illegal end if (checkmated?(sente)) - move_back(move) + move_back(@move) return :oute_kaihimore end if ((x0 == 0) && (y0 == 0) && (name == "FU") && uchifuzume?(sente)) - move_back(move) + move_back(@move) return :uchifuzume end @@ -662,19 +704,29 @@ EOF update_sennichite(sente) os_result = oute_sennichite?(sente) if os_result # :oute_sennichite_sente_lose or :oute_sennichite_gote_lose - move_back(move) + move_back(@move) restore_sennichite_stuff(*sennichite_stuff) return os_result end if sennichite? - move_back(move) + move_back(@move) restore_sennichite_stuff(*sennichite_stuff) return :sennichite end + # New rule that CSA introduced in November 2014. + # If a game with 256 plies does not end, make the game a draw. + # When running test cases $options might be nil. + if $options && $options["max-moves"] && + $options["max-moves"] > 0 && @move_count >= $options["max-moves"] + return :max_moves + end + return :normal end + # Return a CSA-styled string notation of the current position. + # def to_s a = Array::new y = 1 @@ -711,6 +763,14 @@ EOF a.push("%s\n" % [@teban ? "+" : "-"]) return a.join end + + # Return a CSA-styled string notation of the initial position. + # + def initial_string + tmp_board = self.class.new + tmp_board.initial + return tmp_board.to_s + end end end # ShogiServer