Use helper when creating matches.
[kaya.git] / lib / plugins / ics / lib / match_helper.rb
blob7f6da80adff038edcd7b60ad771ce99fedfe54ae
1 # Copyright (c) 2010 Paolo Capriotti <p.capriotti@gmail.com>
2
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 require_bundle 'ics', 'style12'
9 require 'singleton'
11 module ICS
13
14 # Helper mixin to create and start ICS matches.
15
16 module MatchHelper
17   #
18   # Create an appropriate MatchHelper instance for the given style12
19   # 
20   def self.from_style12(style12)
21     @@helpers ||= {}.tap do |h|
22       h[Style12::Relation::EXAMINING] = ExaminingMatchHelper.instance
23       h[Style12::Relation::NOT_MY_MOVE] = DefaultMatchHelper.instance
24       h[Style12::Relation::MY_MOVE] = h[Style12::Relation::NOT_MY_MOVE]
25     end
26     
27     @@helpers[style12.relation]
28   end
29   
30   # 
31   # Get the helper instance for this type.
32   # 
33   # Currently supported types: :default, :examining, :observing.
34   # 
35   def self.get(type)
36     ICS.const_get(type.to_s.capitalize + "MatchHelper").instance
37   end
38   
39   # 
40   # Create the opponent player. By default, create an ICSPlayer that
41   # will respond to future style12 events.
42   # 
43   def create_opponent(protocol, color, match_info)
44     send = lambda {|msg| protocol.connection.send_text(msg) }
45     opponent = ICSPlayer.new(send, color, match_info[:match], match_info)
46     match_info[:icsplayer] = opponent
47     opponent
48   end
49   
50   # 
51   # Create a player for this match.
52   # 
53   def create_player(user, color, match_info)
54     raise "not implemented"
55   end
56   
57   # 
58   # Create a new match instance.
59   # 
60   def create_match(match_info)
61     raise "not implemented"
62   end
63   
64   # 
65   # Perform post-creation initialization for players.
66   # 
67   def setup_players(user, players)
68   end
69   
70   # 
71   # Return or create a match. Called on an existing match when a new style12 
72   # event is received.
73   # If no match for that style12 event is found, the match argument
74   # will be nil.
75   # 
76   def get_match(protocol, match_info, style12)
77     match_info
78   end
79   
80   # 
81   # Return an array of colors to be assigned to the players.
82   # 
83   def colors(state, rel)
84     turns = [state.turn, state.opposite_turn(state.turn)]
85     if rel == Style12::Relation::NOT_MY_MOVE
86       turns.reverse
87     else
88       turns
89     end
90   end
91   
92   # 
93   # Start an existing match. Called when the first style12
94   # for the given match is received.
95   # 
96   def start(protocol, user, match_info, style12)
97     rel = style12.relation
98     state = style12.state
99     turns = [state.turn, state.opposite_turn(state.turn)]
100     
101     user_color, opponent_color = colors(state, rel)
102         
103     # create players
104     opponent = create_opponent(protocol, opponent_color, match_info)
105     player = create_player(user, user_color, match_info)
106     setup_players(user, [player, opponent])
107     
108     # start match
109     match = match_info[:match]
110     match.register(player)
111     match.register(opponent)
112     match.start(player)
113     match.start(opponent)
114     raise "couldn't start match" unless match.started?
115     
116     # set initial state and time
117     unless match_info[:icsapi].same_state(match.state, style12.state)
118       match.history.state = style12.state
119     end
120     match.update_time(style12.time)
121     
122     # reset controller
123     user.reset(match)
124   end
128 # Helper class to setup normal ICS games.
130 class DefaultMatchHelper
131   include MatchHelper
132   include Singleton
134   def create_player(user, color, match_info)
135     # do not create a new player, just return user
136     user.color = color
137     user.premove = true
138     user.name = match_info[color][:name]
139     user
140   end
141   
142   def create_match(match_info)
143     match = Match.new(match_info[:game], 
144         :kind => :ics,
145         :editable => false,
146         :time_running => true)
147     match_info.merge(:match => match)
148   end
152 # Helper class to setup matches in examination mode
154 class ExaminingMatchHelper
155   include MatchHelper
156   include Singleton
157   
158   def create_player(user, color, match_info)
159     user.color = nil
160     
161     # create a controlled player
162     player = DummyPlayer.new(color)
163     player.name = match_info[color][:name]
164     user.premove = false
165     player
166   end
167   
168   def setup_players(user, players)
169     players.each do |player|
170       user.add_controlled_player(player)
171     end
172   end
174   def get_match(protocol, match_info, style12)
175     if match_info.nil?
176       # Examined games on ics have no header, so we have to be prepared to
177       # create a new match on the fly at this point.
178       # Create an editable Game.dummy match for the moment.
179       match_info = create_match(style12.match_info)
180       
181       # We want to change the game type at some point, so request the game
182       # movelist to the server.
183       protocol.connection.send_text('moves')
184     end
185     
186     match_info
187   end
188   
189   def create_match(match_info)
190     match = Match.new(Game.dummy, 
191       :kind => :ics,
192       :editable => true,
193       :navigable => true)
194     match_info.merge(:match => match)
195   end
199 # Helper class to setup matches in observation mode
201 class ObservingMatchHelper
202   include MatchHelper
203   include Singleton