More documentation for the MatchHandler class.
[kaya.git] / lib / plugins / ics / lib / match_handler.rb
blob3fb7c69cb5026977ac16b875fae80b30a922050a
1 # Copyright (c) 2009 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 'interaction/match'
9 require_bundle 'ics', 'icsplayer'
11 module ICS
14 # Handler for ICS games.
15
16 # Responds to ICS protocol events creating and updating matches.
17 # Matches are stored in the @matches instance variable. It is possible to
18 # have more than one match running on FICS because of the observe feature.
19
20 class MatchHandler
21   include Observer
22   
23   attr_reader :matches
24   
25   def initialize(user, protocol)
26     @protocol = protocol
27     @matches = { }
28     @user = user
29     
30     protocol.add_observer(self)
31   end
32   
33   def on_creating_game(data)
34     match = Match.new(data[:game], 
35         :kind => :ics, 
36         :editable => false,
37         :time_running => true)
38     @matches[data[:number]] = [match, data.merge(:type => :played)]
39   end
40   
41   def on_end_game(data)
42     entry = @matches.delete(data[:game_number])
43     if entry
44       match, info = entry
45       match.close(data[:result], data[:message])
46     end
47   end
48   
49   def on_end_examination(number)
50     on_end_game(:game_number => number,
51                 :result => '',
52                 :message => '')
53   end
54   
55   def on_examination_revert(data)
56     match, match_info = @matches[data[:game_number]]
57     if match_info
58       match_info[:about_to_revert_to] = data[:index]
59     end
60   end
61   
62   def on_style12(style12)
63     match, match_info = @matches[style12.game_number]
64     if match.nil? && style12.relation == Style12::Relation::EXAMINING
65       # if it is an examined game, start a new match
66       match = Match.new(Game.dummy, :kind => :ics, :editable => true, :navigable => true)
67       match_info = style12.match_info.merge(:type => :examined)
68       @matches[style12.game_number] = [match, match_info]
69       
70       # request more info from the server
71       @protocol.connection.send_text('moves')
72       @protocol.observe_limited(:movelist) do |movelist|
73         puts "movelist = #{movelist.inspect}"
74         true
75       end
76     end
77     
78     if match.started?
79       match_info[:icsplayer].on_style12(style12)
80     else
81       rel = style12.relation
82       state = style12.state
83       turns = [state.turn, state.opposite_turn(state.turn)]
84       @user.color, opponent_color =
85         if rel == Style12::Relation::MY_MOVE
86           turns
87         elsif rel == Style12::Relation::NOT_MY_MOVE
88           turns.reverse
89         else
90           [nil, turns[1]]
91         end
92       opponent = ICSPlayer.new(
93         lambda {|msg| @protocol.connection.send_text(msg) },
94         opponent_color,
95         match,
96         match_info)
97       match_info[:icsplayer] = opponent
98       
99       player = @user
100       
101       # in examined games, playing moves for the opponent is allowed
102       if @user.color.nil?
103         player = DummyPlayer.new(state.turn)
104         @user.add_controlled_player(player)
105         @user.add_controlled_player(opponent)
106         @user.premove = false
107       else
108         @user.premove = true
109       end
110       
111       player.name = match_info[player.color][:name]
112       
113       match.register(player)
114       match.register(opponent)
115       
116       match.start(player)
117       match.start(opponent)
118       
119       raise "couldn't start match" unless match.started?
120       unless match_info[:icsapi].same_state(match.state, style12.state)
121         match.history.state = style12.state
122       end
123       
124       @user.reset(match)
125       
126       match.update_time(style12.time)
127     end
128     
129     
130   end