3 ## Copyright (C) 2004 NABEYA Kenichi (aka nanami@2ch)
4 ## Copyright (C) 2007-2012 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
22 module ShogiServer # for a namespace
24 # MonitorObserver observes GameResult to send messages to the monitors
28 def update(game_result)
29 game_result.game.each_monitor do |monitor_handler|
30 monitor_handler.write_safe(game_result.game.game_id, game_result.result_type)
35 # LoggingObserver appends a result of each game to a log file, which will
36 # be used to calculate rating scores of players.
40 @logfile = File.join($league.dir, "00LIST")
43 def update(game_result)
44 end_time_str = game_result.end_time.strftime("%Y/%m/%d %H:%M:%S")
45 black = game_result.black
46 white = game_result.white
47 black_name = black.rated? ? black.player_id : black.name
48 white_name = white.rated? ? white.player_id : white.name
50 game_result.log_summary_type,
51 game_result.black_result,
54 game_result.white_result,
55 game_result.game.logfile,
56 game_result.game.board.move_count]
58 # Note that this is proccessed in the gian lock.
59 File.open(@logfile, "a") do |f|
60 f << msg.join("\t") << "\n"
64 $stderr.puts "Failed to write to the game result file: #{@logfile}" if $DEBUG
69 # Base abstract class for a game result.
70 # Imediate subclasses are GameResultWin and GameResultDraw.
83 # Command to send monitors such as '%TORYO' etc...
84 attr_reader :result_type
85 # Result types to write the main log file such as 'toryo' etc...
86 attr_reader :log_summary_type
87 # Time when the game ends
90 def initialize(game, p1, p2)
93 if p1.sente && !p2.sente
94 @black, @white = p1, p2
95 elsif !p1.sente && p2.sente
96 @black, @white = p2, p1
98 raise "Never reached!: %s p1: %s p2: %s" % [game.game_id, p1.sente, p2.sente]
100 @players.each do |player|
101 player.status = "connected"
109 add_observer MonitorObserver.new
110 add_observer LoggingObserver.new
112 if League::Floodgate.game_name?(@game.game_name) &&
113 @game.sente.player_id && @game.gote.player_id
114 path = League::Floodgate.history_file_path(@game.game_name)
115 history = League::Floodgate::History.factory(path)
116 add_observer history if history
121 raise "Implement me!"
126 notify_observers(self)
134 log(@game.board.to_s.gsub(/^/, "\'").chomp)
138 return "Implemet me!"
142 return "Implemet me!"
147 log("'summary:%s:%s %s:%s %s" % [@log_summary_type,
148 @black.name, black_result,
149 @white.name, white_result])
153 class GameResultWin < GameResult
154 attr_reader :winner, :loser
156 def initialize(game, winner, loser)
158 @winner, @loser = winner, loser
159 @winner.last_game_win = true
160 @loser.last_game_win = false
164 return @black == @winner ? "win" : "lose"
168 return @black == @winner ? "lose" : "win"
172 class GameResultAbnormalWin < GameResultWin
173 def initialize(game, winner, loser)
175 @log_summary_type = "abnormal"
176 @result_type = "%TORYO"
180 @winner.write_safe("%TORYO\n#RESIGN\n#WIN\n")
181 @loser.write_safe( "%TORYO\n#RESIGN\n#LOSE\n")
188 class GameResultTimeoutWin < GameResultWin
189 def initialize(game, winner, loser)
191 @log_summary_type = "time up"
192 @result_type = "#TIME_UP"
196 @winner.write_safe("#TIME_UP\n#WIN\n")
197 @loser.write_safe( "#TIME_UP\n#LOSE\n")
198 log("%TIME_UP") # a player in turn lost
204 # A player declares (successful) Kachi
205 class GameResultKachiWin < GameResultWin
206 def initialize(game, winner, loser)
208 @log_summary_type = "kachi"
209 @result_type = "%KACHI"
213 @winner.write_safe("%KACHI\n#JISHOGI\n#WIN\n")
214 @loser.write_safe( "%KACHI\n#JISHOGI\n#LOSE\n")
221 # A player declares wrong Kachi
222 class GameResultIllegalKachiWin < GameResultWin
223 def initialize(game, winner, loser)
225 @log_summary_type = "illegal kachi"
226 @result_type = "%KACHI"
230 @winner.write_safe("%KACHI\n#ILLEGAL_MOVE\n#WIN\n")
231 @loser.write_safe( "%KACHI\n#ILLEGAL_MOVE\n#LOSE\n")
238 class GameResultIllegalWin < GameResultWin
239 def initialize(game, winner, loser, cause)
240 super(game, winner, loser)
241 @log_summary_type = cause
242 @result_type = "#ILLEGAL_MOVE"
246 @winner.write_safe("#ILLEGAL_MOVE\n#WIN\n")
247 @loser.write_safe( "#ILLEGAL_MOVE\n#LOSE\n")
254 class GameResultIllegalMoveWin < GameResultIllegalWin
255 def initialize(game, winner, loser)
256 super(game, winner, loser, "illegal move")
260 class GameResultUchifuzumeWin < GameResultIllegalWin
261 def initialize(game, winner, loser)
262 super(game, winner, loser, "uchifuzume")
266 class GameResultOuteKaihiMoreWin < GameResultIllegalWin
267 def initialize(game, winner, loser)
268 super(game, winner, loser, "oute_kaihimore")
272 # This won't happen, though.
274 class GameResultOutoriWin < GameResultIllegalWin
275 def initialize(game, winner, loser)
276 super(game, winner, loser, "outori")
280 class GameResultToryoWin < GameResultWin
281 def initialize(game, winner, loser)
283 @log_summary_type = "toryo"
284 @result_type = "%TORYO"
288 @winner.write_safe("%TORYO\n#RESIGN\n#WIN\n")
289 @loser.write_safe( "%TORYO\n#RESIGN\n#LOSE\n")
296 class GameResultOuteSennichiteWin < GameResultWin
297 def initialize(game, winner, loser)
299 @log_summary_type = "oute_sennichite"
300 @result_type = "#OUTE_SENNICHITE"
304 @winner.write_safe("#OUTE_SENNICHITE\n#WIN\n")
305 @loser.write_safe( "#OUTE_SENNICHITE\n#LOSE\n")
314 class GameResultDraw < GameResult
315 def initialize(game, p1, p2)
317 p1.last_game_win = false
318 p2.last_game_win = false
330 class GameResultSennichiteDraw < GameResultDraw
331 def initialize(game, winner, loser)
333 @log_summary_type = "sennichite"
334 @result_type = "#SENNICHITE"
338 @players.each do |player|
339 player.write_safe("#SENNICHITE\n#DRAW\n")
347 class GameResultMaxMovesDraw < GameResultDraw
348 def initialize(game, winner, loser)
350 @log_summary_type = "max_moves"
351 @result_type = "#MAX_MOVES"
355 @players.each do |player|
356 player.write_safe("#MAX_MOVES\n#CENSORED\n")