New game dialog allows selecting engines.
[kaya.git] / lib / interaction / match.rb
blob4bf00bab4cde3c65b37c9ed01717334ea0352566
1 require 'observer_utils'
2 require 'history'
4 module Player
5   def name
6   end
7 end
9 class Match
10   include Observable
11   
12   attr_reader :game
13   attr_reader :history
14   attr_reader :kind
15   attr_reader :index
16   attr_accessor :url
17   
18   def initialize(game, opts = {})
19     @game = game
20     @players = { } # player => ready
21     @history = nil
22     @kind = opts[:kind] || :local
23     @editable = opts.fetch(:editable, true)
24     @info = { }
25   end
26   
27   def register(player)
28     return false if @history
29     return false if @players.has_key?(player)
30     return false if complete?
31     return false unless @game.players.include?(player.color)
32     
33     @players[player] = false
34     fire :complete if complete?
35     true
36   end
37   
38   def start(player)
39     return false if @history
40     return false unless complete?
41     return false unless @players[player] == false
42     
43     @players[player] = true
44     if @players.values.all?
45       state = @game.state.new
46       state.setup
47       @history = History.new(state)
48       @index = 0
49       fire :started
50     end
52     true
53   end
54   
55   def move(player, move, state = nil)
56     return false unless @history
57     # if player is nil, assume the current player is moving
58     if player == nil
59       player = current_player
60     else
61       return false unless @players.has_key?(player)
62       return false unless player.color == @history.state.turn
63     end
65     validate = @game.validator.new(@history.state)
66     valid = validate[move]
67     return false unless valid
69     old_state = @history.state
70     state = old_state.dup
71     state.perform! move
72     @history.add_move(state, move)
73     @index += 1
74     
75     broadcast player, :move => {
76       :player => player,
77       :move => move,
78       :state => state,
79       :old_state => old_state }
80     true
81   end
82   
83   def update_time(time)
84     broadcast nil, :time => time
85   end
86   
87   def complete?
88     @game.players.all? do |c| 
89       @players.keys.find {|p| p.color == c }
90     end
91   end
92   
93   def started?
94     ! ! @history
95   end
96   
97   def state
98     @history.state
99   end
100   
101   def editable?
102     @editable
103   end
104     
105   def player(color)
106     @players.keys.find{|p| p.color == color }
107   end
108   
109   def close(result = nil, message = nil)
110     @info[:result] = result if result
111     broadcast nil, :close => { 
112       :result => result,
113       :message => message }
114   end
115   
116   def info
117     @info.merge(:players => @players.keys)
118   end
119   
120   def add_info(infos)
121     @info = @info.merge(infos)
122     infos[:players].each do |col, name|
123       p = player(col)
124       if p
125         p.name = name
126       end
127     end
128   end
129   
130   def history=(history)
131     @history = history
132     @index = history.size - 1
133   end
134     
135   private
136   
137   def broadcast(player, event)
138     fire event
139     @players.each_key do |p|
140       p.update any_to_event(event) unless p == player
141     end
142   end
143   
144   def current_player
145     @players.keys.find {|p| p.color == state.turn }
146   end