1 # Copyright (c) 2009 Paolo Capriotti <p.capriotti@gmail.com>
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'
14 # Handler for ICS games.
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.
25 def initialize(user, protocol)
30 protocol.add_observer(self)
33 def on_creating_game(data)
34 match = Match.new(data[:game],
37 :time_running => true)
38 @matches[data[:number]] = [match, data.merge(:type => :played)]
42 entry = @matches.delete(data[:game_number])
45 match.close(data[:result], data[:message])
49 def on_end_examination(number)
50 on_end_game(:game_number => number,
55 def on_examination_revert(data)
56 match, match_info = @matches[data[:game_number]]
58 match_info[:about_to_revert_to] = data[:index]
62 def on_style12(style12)
63 match, match_info = @matches[style12.game_number]
65 if style12.relation == Style12::Relation::EXAMINING
66 # Examined games on ics have no header, so we have to be prepared to
67 # create a new match on the fly at this point.
68 # Create an editable Game.dummy match for the moment.
69 match = Match.new(Game.dummy, :kind => :ics, :editable => true, :navigable => true)
70 match_info = style12.match_info.merge(:type => :examined)
71 @matches[style12.game_number] = [match, match_info]
73 # We want to change the game type at some point, so request the game
74 # movelist to the server.
75 @protocol.connection.send_text('moves')
76 @protocol.observe_limited(:movelist) do |movelist|
77 puts "movelist = #{movelist.inspect}"
81 # ignore spurious style12 events
87 match_info[:icsplayer].on_style12(style12)
89 rel = style12.relation
91 turns = [state.turn, state.opposite_turn(state.turn)]
92 @user.color, opponent_color =
93 if rel == Style12::Relation::MY_MOVE
95 elsif rel == Style12::Relation::NOT_MY_MOVE
100 opponent = ICSPlayer.new(
101 lambda {|msg| @protocol.connection.send_text(msg) },
105 match_info[:icsplayer] = opponent
109 # in examined games, playing moves for the opponent is allowed
111 player = DummyPlayer.new(state.turn)
112 @user.add_controlled_player(player)
113 @user.add_controlled_player(opponent)
114 @user.premove = false
119 player.name = match_info[player.color][:name]
121 match.register(player)
122 match.register(opponent)
125 match.start(opponent)
127 raise "couldn't start match" unless match.started?
128 unless match_info[:icsapi].same_state(match.state, style12.state)
129 match.history.state = style12.state
134 match.update_time(style12.time)