Refactoring: use Match to handle interactions.
[kaya.git] / lib / interaction / match.rb
blob1a0bf157be4ef0ecfb980ce7f2afe2b709a61b7a
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 :index
14   attr_reader :kind
15   
16   def initialize(game, kind = :local)
17     @game = game
18     @players = { } # player => ready
19     @history = nil
20     @kind = kind
21   end
22   
23   def register(player)
24     return false if @history
25     return false if @players.has_key?(player)
26     return false if complete?
27     return false unless @game.players.include?(player.color)
28     
29     @players[player] = false
30     fire :complete if complete?
31     true
32   end
33   
34   def start(player)
35     return false if @history
36     return false unless complete?
37     return false unless @players[player] == false
38     
39     @players[player] = true
40     if @players.values.all?
41       state = @game.state.new
42       state.setup
43       @history = History.new(state)
44       @index = 0
45       fire :started
46     end
48     true
49   end
50   
51   def move(player, move, state = nil)
52     return false unless @history
53     # if player is nil, assume the current player is moving
54     if player == nil
55       player = current_player
56     else
57       return false unless @players.has_key?(player)
58       return false unless player.color == @history.state.turn
59     end
61     validate = @game.validator.new(@history.state)
62     valid = validate[move]
63     return false unless valid
65     old_state = @history.state
66     state = old_state.dup
67     state.perform! move
68     @history.add_move(state, move)
69     @index += 1
70     
71     broadcast player, :move => {
72       :player => player,
73       :move => move,
74       :state => state,
75       :old_state => old_state }
76     true
77   end
78   
79   def complete?
80     @game.players.all? do |c| 
81       @players.keys.find {|p| p.color == c }
82     end
83   end
84   
85   def started?
86     ! ! @history
87   end
88   
89   def state
90     @history.state
91   end
92   
93   private
94   
95   def broadcast(player, event)
96     fire event
97     @players.each_key do |p|
98       p.update any_to_event(event) unless p == player
99     end
100   end
101   
102   def current_player
103     @players.keys.find {|p| p.color == state.turn }
104   end