1 require 'observer_utils'
3 require 'board/pool_animator'
5 require 'interaction/match'
12 attr_reader :controlled
21 @field = AnimationField.new(20)
25 yield @board if @board
26 @pools.each {|c, pool| yield pool }
27 @clocks.each {|c, clock| yield clock }
33 move = @match.game.policy.new_move(state, @board.selection, p)
34 validate = @match.game.validator.new(state)
39 @board.selection = nil
40 elsif @match.game.policy.movable?(state, p) and movable?(p)
47 @table.reset(match.game)
48 @board = @table.elements[:board]
49 @pools = @table.elements[:pools]
50 @clocks = @table.elements[:clocks]
52 @animator = @match.game.animator.new(@board)
53 @board.reset(match.state.board)
56 @clocks.each do |col, clock|
61 @board.observe(:click) {|p| c.on_board_click(p) }
62 @board.observe(:drag) {|data| c.on_board_drag(data) }
63 @board.observe(:drop) {|data| c.on_board_drop(data) }
64 @pools.each do |col, pool|
65 pool.observe(:drag) {|data| c.on_pool_drag(col, data) }
66 pool.observe(:drop) {|data| c.on_pool_drop(col, data) }
68 @clocks.each do |col, clock|
69 clock.clock = Clock.new(300, 0, nil)
70 clock.data = { :color => col }
73 @clocks[@match.game.players.first].active = true
76 def perform!(move, opts = {})
77 col = @match.state.turn
78 if @controlled[col] and @match.move(@controlled[col], move)
79 animate(:forward, @match.state, move, opts)
80 @board.highlight(move)
83 @clocks[@match.state.turn].start
88 # state, move = @history.back
89 # animate(:back, state, move)
90 # @board.highlight(@history.move)
91 # rescue History::OutOfBound
92 # puts "error: first move"
96 # state, move = @history.forward
97 # animate(:forward, state, move)
98 # @board.highlight(move)
99 # rescue History::OutOfBound
100 # puts "error: last move"
103 def animate(direction, state, move, opts = {})
104 anim = @animator.send(direction, state, move, opts)
111 @pools.each do |col, pool|
112 anim = pool.animator.warp(@match.state.pool(col))
117 def on_board_drop(data)
121 if data[:src] == data[:dst]
122 @board.selection = data[:src]
125 move = @match.game.policy.new_move(
126 @match.state, data[:src], data[:dst])
127 validate = @match.game.validator.new(@match.state)
131 if move and move.valid?
132 @board.add_to_group data[:item]
133 @board.lower data[:item]
134 perform! move, :adjust => true
138 elsif data[:index] and data[:dst]
140 move = @match.game.policy.new_move(
141 @match.state, nil, data[:dst],
142 :dropped => data[:item].name)
143 validate = @match.game.validator.new(@match.state)
145 @board.add_to_group data[:item]
146 @board.lower data[:item]
147 perform! move, :dropped => data[:item]
154 def on_board_drag(data)
155 if @match.game.policy.movable?(@match.state, data[:src]) and
157 @board.raise data[:item]
158 @board.remove_from_group data[:item]
159 @board.selection = nil
164 def on_pool_drag(c, data)
165 if @match.game.policy.droppable?(@match.state, c, data[:index]) and
166 droppable?(c, data[:index])
169 # replace item with a correctly sized one
170 item = @board.create_piece(data[:item].name)
172 @board.remove_from_group item
173 anim = @pools[c].animator.remove_piece(data[:index])
175 data[:size] = @board.unit
176 data[:pool_color] = c
184 def on_pool_drop(color, data)
188 def cancel_drop(data)
189 anim = if data[:index]
190 # remove dragged item
192 # make original item reappear in its place
193 @pools[data[:pool_color]].animator.insert_piece(
197 @board.add_to_group data[:item]
198 @board.lower data[:item]
199 @animator.movement(data[:item], nil, data[:src], Path::Linear)
202 @field.run(anim) if anim
205 def add_controlled_player(player)
206 @controlled[player.color] = player
211 @controlled = { @color => self }
215 ! ! @controlled[@match.state.turn]
218 def droppable?(color, index)
219 ! ! @controlled[@match.state.turn]