OSDN Git Service

New feature: Zero least time per move.
[shogi-server/shogi-server.git] / shogi_server / board.rb
index c006176..eb2efaa 100644 (file)
@@ -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
@@ -94,6 +94,8 @@ EOF
     @move_count = move_count
     @teban = nil # black => 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
@@ -103,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.
   #
@@ -153,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
@@ -356,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.
@@ -617,6 +626,7 @@ EOF
   #   - :uchifuzume 
   #   - :oute_kaihimore 
   #   - (:outori will not be returned)
+  #   - :max_moves_draw
   #
   def handle_one_move(str, sente=nil)
     if (str =~ /^([\+\-])(\d)(\d)(\d)(\d)([A-Z]{2})/)
@@ -675,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
 
@@ -694,16 +704,24 @@ 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_draw
+    end
+
     return :normal
   end