3 ## Copyright (C) 2004 NABEYA Kenichi (aka nanami@2ch)
4 ## Copyright (C) 2007-2008 Daigo Moriwaki (daigo at debian dot org)
6 ## This program is free software; you can redistribute it and/or modify
7 ## it under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 2 of the License, or
9 ## (at your option) any later version.
11 ## This program is distributed in the hope that it will be useful,
12 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ## GNU General Public License for more details.
16 ## You should have received a copy of the GNU General Public License
17 ## along with this program; if not, write to the Free Software
18 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 module ShogiServer # for a namespace
22 # Abstract class to caclulate thinking time.
26 def TimeClock.factory(least_time_per_move, game_name)
27 time_map = Game.parse_time game_name
29 if time_map[:stop_watch]
30 @time_clock = StopWatchClock.new(least_time_per_move, time_map[:total_time], time_map[:byoyomi])
32 if least_time_per_move == 0
33 @time_clock = ChessClockWithLeastZero.new(least_time_per_move,
34 time_map[:total_time],
38 @time_clock = ChessClock.new(least_time_per_move,
39 time_map[:total_time],
48 def initialize(least_time_per_move, total_time, byoyomi, fischer=0)
49 @least_time_per_move = least_time_per_move
50 @total_time = total_time
55 # Returns thinking time duration
57 def time_duration(mytime, start_time, end_time)
62 # Returns what "Time_Unit:" in CSA protocol should provide.
68 # If thinking time runs out, returns true; false otherwise.
70 def timeout?(player, start_time, end_time)
75 # Updates a player's remaining time and returns thinking time.
77 def process_time(player, start_time, end_time)
78 t = time_duration(player.mytime, start_time, end_time)
80 player.mytime += @fischer
82 if (player.mytime < 0)
90 # Calculates thinking time with chess clock.
92 class ChessClock < TimeClock
93 def initialize(least_time_per_move, total_time, byoyomi, fischer=0)
97 def time_duration(mytime, start_time, end_time)
98 return [(end_time - start_time).floor, @least_time_per_move].max
101 def timeout?(player, start_time, end_time)
102 t = time_duration(player.mytime, start_time, end_time)
104 if ((player.mytime - t + @byoyomi + @fischer <= 0) &&
105 ((@total_time > 0) || (@byoyomi > 0) || (@fischer > 0)))
113 return "ChessClock: LeastTimePerMove %d; TotalTime %d; Byoyomi %d; Fischer" %
114 [@least_time_per_move, @total_time, @byoyomi, @fischer]
118 # Calculates thinking time with chess clock, truncating decimal seconds for
119 # thinking time. This is a new rule that CSA introduced in November 2014.
121 # least_time_per_move should be 0.
122 # byoyomi should be more than 0.
124 class ChessClockWithLeastZero < ChessClock
125 def initialize(least_time_per_move, total_time, byoyomi, fischer=0)
126 if least_time_per_move != 0
127 raise ArgumentError, "least_time_per_move #{least_time_per_move} should be 0."
133 return "ChessClockWithLeastZero: LeastTimePerMove %d; TotalTime %d; Byoyomi %d; Fischer %d" %
134 [@least_time_per_move, @total_time, @byoyomi, @fischer]
138 # StopWatchClock does not support Fischer time.
140 class StopWatchClock < TimeClock
141 def initialize(least_time_per_move, total_time, byoyomi)
142 super least_time_per_move, total_time, byoyomi, 0
149 def time_duration(mytime, start_time, end_time)
150 t = [(end_time - start_time).floor, @least_time_per_move].max
151 return (t / @byoyomi) * @byoyomi
154 def timeout?(player, start_time, end_time)
155 t = time_duration(player.mytime, start_time, end_time)
157 if (player.mytime <= t)
165 return "StopWatchClock: LeastTimePerMove %d; TotalTime %d; Byoyomi %d" % [@least_time_per_move, @total_time, @byoyomi]