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|
60 @board.observe(:click) {|p| on_board_click(p) }
61 @board.observe(:drag) {|data| on_board_drag(data) }
62 @board.observe(:drop) {|data| on_board_drop(data) }
63 @pools.each do |col, pool|
64 pool.observe(:drag) {|data| on_pool_drag(col, data) }
65 pool.observe(:drop) {|data| on_pool_drop(col, data) }
67 @clocks.each do |col, clock|
68 clock.clock = Clock.new(300, 0, nil)
69 clock.data = { :color => col }
72 @clocks[@match.game.players.first].active = true
75 def perform!(move, opts = {})
76 col = @match.state.turn
77 if @controlled[col] and @match.move(@controlled[col], move)
78 animate(:forward, @match.state, move, opts)
79 @board.highlight(move)
82 @clocks[@match.state.turn].start
87 # state, move = @history.back
88 # animate(:back, state, move)
89 # @board.highlight(@history.move)
90 # rescue History::OutOfBound
91 # puts "error: first move"
95 # state, move = @history.forward
96 # animate(:forward, state, move)
97 # @board.highlight(move)
98 # rescue History::OutOfBound
99 # puts "error: last move"
102 def animate(direction, state, move, opts = {})
103 anim = @animator.send(direction, state, move, opts)
110 @pools.each do |col, pool|
111 anim = pool.animator.warp(@match.state.pool(col))
116 def on_board_drop(data)
120 if data[:src] == data[:dst]
121 @board.selection = data[:src]
124 move = @match.game.policy.new_move(
125 @match.state, data[:src], data[:dst])
126 validate = @match.game.validator.new(@match.state)
130 if move and move.valid?
131 @board.add_to_group data[:item]
132 @board.lower data[:item]
133 perform! move, :adjust => true
137 elsif data[:index] and data[:dst]
139 move = @match.game.policy.new_move(
140 @match.state, nil, data[:dst],
141 :dropped => data[:item].name)
142 validate = @match.game.validator.new(@match.state)
144 @board.add_to_group data[:item]
145 @board.lower data[:item]
146 perform! move, :dropped => data[:item]
153 def on_board_drag(data)
154 if @match.game.policy.movable?(@match.state, data[:src]) and
156 @board.raise data[:item]
157 @board.remove_from_group data[:item]
158 @board.selection = nil
163 def on_pool_drag(c, data)
164 if @match.game.policy.droppable?(@match.state, c, data[:index]) and
165 droppable?(c, data[:index])
168 # replace item with a correctly sized one
169 item = @board.create_piece(data[:item].name)
171 @board.remove_from_group item
172 anim = @pools[c].animator.remove_piece(data[:index])
174 data[:size] = @board.unit
175 data[:pool_color] = c
183 def on_pool_drop(color, data)
187 def cancel_drop(data)
188 anim = if data[:index]
189 # remove dragged item
191 # make original item reappear in its place
192 @pools[data[:pool_color]].animator.insert_piece(
196 @board.add_to_group data[:item]
197 @board.lower data[:item]
198 @animator.movement(data[:item], nil, data[:src], Path::Linear)
201 @field.run(anim) if anim
204 def add_controlled_player(player)
205 @controlled[player.color] = player
210 @controlled = { @color => self }
214 ! ! @controlled[@match.state.turn]
217 def droppable?(color, index)
218 ! ! @controlled[@match.state.turn]