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")
41 @logfile_floodgate = File.join($league.dir, "00LIST.floodgate")
42 @logfile_others = File.join($league.dir, "00LIST.others")
45 def update(game_result)
46 end_time_str = game_result.end_time.strftime("%Y/%m/%d %H:%M:%S")
47 black = game_result.black
48 white = game_result.white
49 black_name = black.rated? ? black.player_id : black.name
50 white_name = white.rated? ? white.player_id : white.name
52 game_result.log_summary_type,
53 game_result.black_result,
56 game_result.white_result,
57 game_result.game.logfile,
58 game_result.game.board.move_count]
61 if League::Floodgate.game_name?(game_result.game.game_name)
62 files << @logfile_floodgate
64 files << @logfile_others
66 # Note that this is proccessed in the gian lock.
69 File.open(file, "a") do |f|
75 $stderr.puts "Failed to write to the game result file: #{@logfile}" if $DEBUG
80 # Base abstract class for a game result.
81 # Imediate subclasses are GameResultWin and GameResultDraw.
94 # Command to send monitors such as '%TORYO' etc...
95 attr_reader :result_type
96 # Result types to write the main log file such as 'toryo' etc...
97 attr_reader :log_summary_type
98 # Time when the game ends
101 def initialize(game, p1, p2)
104 if p1.sente && !p2.sente
105 @black, @white = p1, p2
106 elsif !p1.sente && p2.sente
107 @black, @white = p2, p1
109 raise "Never reached!: %s p1: %s p2: %s" % [game.game_id, p1.sente, p2.sente]
111 @players.each do |player|
112 player.status = "connected"
120 add_observer MonitorObserver.new
121 add_observer LoggingObserver.new
123 if League::Floodgate.game_name?(@game.game_name) &&
124 @game.sente.player_id && @game.gote.player_id
125 path = League::Floodgate.history_file_path(@game.game_name)
126 history = League::Floodgate::History.factory(path)
127 add_observer history if history
132 raise "Implement me!"
137 notify_observers(self)
145 log(@game.board.to_s.gsub(/^/, "\'").chomp)
149 return "Implemet me!"
153 return "Implemet me!"
158 log("'summary:%s:%s %s:%s %s" % [@log_summary_type,
159 @black.name, black_result,
160 @white.name, white_result])
164 class GameResultWin < GameResult
165 attr_reader :winner, :loser
167 def initialize(game, winner, loser)
169 @winner, @loser = winner, loser
170 @winner.last_game_win = true
171 @loser.last_game_win = false
175 return @black == @winner ? "win" : "lose"
179 return @black == @winner ? "lose" : "win"
183 class GameResultAbnormalWin < GameResultWin
184 def initialize(game, winner, loser)
186 @log_summary_type = "abnormal"
187 @result_type = "%TORYO"
191 @winner.write_safe("%TORYO\n#RESIGN\n#WIN\n")
192 @loser.write_safe( "%TORYO\n#RESIGN\n#LOSE\n")
199 class GameResultTimeoutWin < GameResultWin
200 def initialize(game, winner, loser)
202 @log_summary_type = "time up"
203 @result_type = "#TIME_UP"
207 @winner.write_safe("#TIME_UP\n#WIN\n")
208 @loser.write_safe( "#TIME_UP\n#LOSE\n")
209 log("%TIME_UP") # a player in turn lost
215 # A player declares (successful) Kachi
216 class GameResultKachiWin < GameResultWin
217 def initialize(game, winner, loser)
219 @log_summary_type = "kachi"
220 @result_type = "%KACHI"
224 @winner.write_safe("%KACHI\n#JISHOGI\n#WIN\n")
225 @loser.write_safe( "%KACHI\n#JISHOGI\n#LOSE\n")
232 # A player declares wrong Kachi
233 class GameResultIllegalKachiWin < GameResultWin
234 def initialize(game, winner, loser)
236 @log_summary_type = "illegal kachi"
237 @result_type = "%KACHI"
241 @winner.write_safe("%KACHI\n#ILLEGAL_MOVE\n#WIN\n")
242 @loser.write_safe( "%KACHI\n#ILLEGAL_MOVE\n#LOSE\n")
249 class GameResultIllegalWin < GameResultWin
250 def initialize(game, winner, loser, cause)
251 super(game, winner, loser)
252 @log_summary_type = cause
253 @result_type = "#ILLEGAL_MOVE"
257 @winner.write_safe("#ILLEGAL_MOVE\n#WIN\n")
258 @loser.write_safe( "#ILLEGAL_MOVE\n#LOSE\n")
265 class GameResultIllegalMoveWin < GameResultIllegalWin
266 def initialize(game, winner, loser)
267 super(game, winner, loser, "illegal move")
271 class GameResultUchifuzumeWin < GameResultIllegalWin
272 def initialize(game, winner, loser)
273 super(game, winner, loser, "uchifuzume")
277 class GameResultOuteKaihiMoreWin < GameResultIllegalWin
278 def initialize(game, winner, loser)
279 super(game, winner, loser, "oute_kaihimore")
283 # This won't happen, though.
285 class GameResultOutoriWin < GameResultIllegalWin
286 def initialize(game, winner, loser)
287 super(game, winner, loser, "outori")
291 class GameResultToryoWin < GameResultWin
292 def initialize(game, winner, loser)
294 @log_summary_type = "toryo"
295 @result_type = "%TORYO"
299 @winner.write_safe("%TORYO\n#RESIGN\n#WIN\n")
300 @loser.write_safe( "%TORYO\n#RESIGN\n#LOSE\n")
307 class GameResultOuteSennichiteWin < GameResultWin
308 def initialize(game, winner, loser)
310 @log_summary_type = "oute_sennichite"
311 @result_type = "#OUTE_SENNICHITE"
315 @winner.write_safe("#OUTE_SENNICHITE\n#WIN\n")
316 @loser.write_safe( "#OUTE_SENNICHITE\n#LOSE\n")
325 class GameResultDraw < GameResult
326 def initialize(game, p1, p2)
328 p1.last_game_win = false
329 p2.last_game_win = false
341 class GameResultSennichiteDraw < GameResultDraw
342 def initialize(game, winner, loser)
344 @log_summary_type = "sennichite"
345 @result_type = "#SENNICHITE"
349 @players.each do |player|
350 player.write_safe("#SENNICHITE\n#DRAW\n")
358 class GameResultMaxMovesDraw < GameResultDraw
359 def initialize(game, winner, loser)
361 @log_summary_type = "max_moves"
362 @result_type = "#MAX_MOVES"
366 @players.each do |player|
367 player.write_safe("#MAX_MOVES\n#CENSORED\n")