OSDN Git Service

39a9c62bf75d49e02e75a3827b7c37804dce8959
[shogi-server/shogi-server.git] / shogi_server / game_result.rb
1 ## $Id$
2
3 ## Copyright (C) 2004 NABEYA Kenichi (aka nanami@2ch)
4 ## Copyright (C) 2007-2008 Daigo Moriwaki (daigo at debian dot org)
5 ##
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.
10 ##
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.
15 ##
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
19
20 require 'observer'
21
22 module ShogiServer # for a namespace
23  
24 # MonitorObserver observes GameResult to send messages to the monitors
25 # watching the game
26 #
27 class MonitorObserver
28   def update(game_result)
29     game_result.game.each_monitor do |monitor|
30       monitor.write_safe("##[MONITOR][%s] %s\n" % [game_result.game.game_id, game_result.result_type])
31     end
32   end
33 end
34
35 # Base class for a game result
36 #
37 class GameResult
38   include Observable
39
40   # Game object
41   attr_reader :game
42   # Array of players
43   attr_reader :players
44   # Black player object
45   attr_reader :black
46   # White plyer object
47   attr_reader :white
48   # Command to send monitors such as '%TORYO' etc...
49   attr_reader :result_type
50
51   def initialize(game, p1, p2)
52     @game = game
53     @players = [p1, p2]
54     if p1.sente && !p2.sente
55       @black, @white = p1, p2
56     elsif !p1.sente && p2.sente
57       @black, @white = p2, p1
58     else
59       raise "Never reached!"
60     end
61     @players.each do |player|
62       player.status = "connected"
63     end
64     @result_type = ""
65
66     regist_observers
67   end
68
69   def regist_observers
70     add_observer MonitorObserver.new
71
72     if League::Floodgate.game_name?(@game.game_name) &&
73        @game.sente.player_id &&
74        @game.gote.player_id &&
75        $options["floodgate-history"]
76       add_observer League::Floodgate::History.factory
77     end
78
79   end
80
81   def process
82     raise "Implement me!"
83   end
84
85   def notify
86     changed
87     notify_observers(self)
88   end
89
90   def log(str)
91     @game.log_game(str)
92   end
93
94   def log_board
95     log(@game.board.to_s.gsub(/^/, "\'").chomp)
96   end
97
98 end
99
100 class GameResultWin < GameResult
101   attr_reader :winner, :loser
102
103   def initialize(game, winner, loser)
104     super
105     @winner, @loser = winner, loser
106     @winner.last_game_win = true
107     @loser.last_game_win  = false
108   end
109
110   def log_summary(type)
111     log_board
112
113     black_result = white_result = ""
114     if @black == @winner
115       black_result = "win"
116       white_result = "lose"
117     else
118       black_result = "lose"
119       white_result = "win"
120     end
121     log("'summary:%s:%s %s:%s %s" % [type, 
122                                      @black.name, black_result,
123                                      @white.name, white_result])
124
125   end
126 end
127
128 class GameResultAbnormalWin < GameResultWin
129   def process
130     @winner.write_safe("%TORYO\n#RESIGN\n#WIN\n")
131     @loser.write_safe( "%TORYO\n#RESIGN\n#LOSE\n")
132     log("%TORYO")
133     log_summary("abnormal")
134     @result_type = "%TORYO"
135     notify
136   end
137 end
138
139 class GameResultTimeoutWin < GameResultWin
140   def process
141     @winner.write_safe("#TIME_UP\n#WIN\n")
142     @loser.write_safe( "#TIME_UP\n#LOSE\n")
143     log_summary("time up")
144     @result_type = "#TIME_UP"
145     notify
146   end
147 end
148
149 # A player declares (successful) Kachi
150 class GameResultKachiWin < GameResultWin
151   def process
152     @winner.write_safe("%KACHI\n#JISHOGI\n#WIN\n")
153     @loser.write_safe( "%KACHI\n#JISHOGI\n#LOSE\n")
154     log("%KACHI")
155     log_summary("kachi")
156     @result_type = "%KACHI"
157     notify
158   end
159 end
160
161 # A player declares wrong Kachi
162 class GameResultIllegalKachiWin < GameResultWin
163   def process
164     @winner.write_safe("%KACHI\n#ILLEGAL_MOVE\n#WIN\n")
165     @loser.write_safe( "%KACHI\n#ILLEGAL_MOVE\n#LOSE\n")
166     log("%KACHI")
167     log_summary("illegal kachi")
168     @result_type = "%KACHI"
169     notify
170   end
171 end
172
173 class GameResultIllegalWin < GameResultWin
174   def initialize(game, winner, loser, cause)
175     super(game, winner, loser)
176     @cause = cause
177   end
178
179   def process
180     @winner.write_safe("#ILLEGAL_MOVE\n#WIN\n")
181     @loser.write_safe( "#ILLEGAL_MOVE\n#LOSE\n")
182     log_summary(@cause)
183     @result_type = "#ILLEGAL_MOVE"
184     notify
185   end
186 end
187
188 class GameResultIllegalMoveWin < GameResultIllegalWin
189   def initialize(game, winner, loser)
190     super(game, winner, loser, "illegal move")
191   end
192 end
193
194 class GameResultUchifuzumeWin < GameResultIllegalWin
195   def initialize(game, winner, loser)
196     super(game, winner, loser, "uchifuzume")
197   end
198 end
199
200 class GameResultOuteKaihiMoreWin < GameResultIllegalWin
201   def initialize(game, winner, loser)
202     super(game, winner, loser, "oute_kaihimore")
203   end
204 end
205
206 class GameResultOutoriWin < GameResultWin
207   def initialize(game, winner, loser)
208     super(game, winner, loser)
209   end
210 end
211
212 class GameResultToryoWin < GameResultWin
213   def process
214     @winner.write_safe("%TORYO\n#RESIGN\n#WIN\n")
215     @loser.write_safe( "%TORYO\n#RESIGN\n#LOSE\n")
216     log("%TORYO")
217     log_summary("toryo")
218     @result_type = "%TORYO"
219     notify
220   end
221 end
222
223 class GameResultOuteSennichiteWin < GameResultWin
224   def process
225     @winner.write_safe("#OUTE_SENNICHITE\n#WIN\n")
226     @loser.write_safe( "#OUTE_SENNICHITE\n#LOSE\n")
227     log_summary("oute_sennichite")
228     @result_type = "#OUTE_SENNICHITE"
229     notify
230   end
231 end
232
233 class GameResultDraw < GameResult
234   def initialize(game, p1, p2)
235     super
236     p1.last_game_win = false
237     p2.last_game_win = false
238   end
239   
240   def log_summary(type)
241     log_board
242     log("'summary:%s:%s draw:%s draw" % [type, @black.name, @white.name])
243   end
244 end
245
246 class GameResultSennichiteDraw < GameResultDraw
247   def process
248     @players.each do |player|
249       player.write_safe("#SENNICHITE\n#DRAW\n")
250     end
251     log_summary("sennichite")
252     @result_type = "#SENNICHITE"
253     notify
254   end
255 end
256
257 end # ShogiServer
258