React to opponent moves on ICS.
[kaya.git] / lib / interaction / match.rb
blob23847f9fa40c14f00e232845b2ea9a5c47c10db5
1 require 'observer_utils'
2 require 'history'
4 module Player
5   include Observer
6 end
8 class Match
9   include Observable
10   
11   attr_reader :game
12   attr_reader :history
13   attr_reader :kind
14   
15   def initialize(game, kind = :local)
16     @game = game
17     @players = { } # player => ready
18     @history = nil
19     @kind = kind
20   end
21   
22   def register(player)
23     return false if @history
24     return false if @players.has_key?(player)
25     return false if complete?
26     return false unless @game.players.include?(player.color)
27     
28     @players[player] = false
29     fire :complete if complete?
30     true
31   end
32   
33   def start(player)
34     return false if @history
35     return false unless complete?
36     return false unless @players[player] == false
37     
38     @players[player] = true
39     if @players.values.all?
40       state = @game.state.new
41       state.setup
42       @history = History.new(state)
43       fire :started
44     end
46     true
47   end
48   
49   def move(player, move, state = nil)
50     return false unless @history
51     # if player is nil, assume the current player is moving
52     if player == nil
53       player = current_player
54     else
55       return false unless @players.has_key?(player)
56       return false unless player.color == @history.state.turn
57     end
59     validate = @game.validator.new(@history.state)
60     valid = validate[move]
61     return false unless valid
63     old_state = @history.state
64     state = old_state.dup
65     state.perform! move
66     @history.add_move(state, move)
67     
68     broadcast player, :move => {
69       :player => player,
70       :move => move,
71       :state => state,
72       :old_state => old_state }
73     true
74   end
75   
76   def complete?
77     @game.players.all? do |c| 
78       @players.keys.find {|p| p.color == c }
79     end
80   end
81   
82   def started?
83     ! ! @history
84   end
85   
86   def state
87     @history.state
88   end
89   
90   def index
91     @history.current
92   end
93   
94   private
95   
96   def broadcast(player, event)
97     fire event
98     @players.each_key do |p|
99       p.update any_to_event(event) unless p == player
100     end
101   end
102   
103   def current_player
104     @players.keys.find {|p| p.color == state.turn }
105   end