-
Notifications
You must be signed in to change notification settings - Fork 0
/
piece.rb
405 lines (328 loc) · 8.08 KB
/
piece.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
# Possible actions:
# try_flip
# die
# attempt_capture
# successful_capture
# successful_move
require 'effect'
require 'affectable'
class Piece
attr_accessor :effects, :myeffect, :space, :attribs
attr_reader :player, :name, :num, :game, :movement_grid, :cost
include Affectable
MOVEMENT_GRID_WIDTH = 5
MOVEMENT_GRID_HEIGHT = 5
MAX_COL_MOVE = (MOVEMENT_GRID_WIDTH - 1) / 2 # => 2
MAX_ROW_MOVE = (MOVEMENT_GRID_HEIGHT - 1) / 2 # => 2
MOVEMENT_GRID_CENTER = MOVEMENT_GRID_WIDTH * MAX_ROW_MOVE + MAX_COL_MOVE # => 12
@@SIDE1 = nil
@@SIDE2 = nil
def initialize(player, space, owner = player)
@owner = owner
@player = player
player.pieces << self
@space = space
space.piece = self
@effects = []
@attribs = {}
@game = game
end
def pay_for_flip
if attribs[:flipped] || attribs[:unflippable] || @player.pool < @cost
nil
elsif run_effects(:action => :try_flip)
@player.pool -= @cost
end
end
def flip
if pay_for_flip
@movement_grid = @@SIDE2
attribs[:flipped] = true
end
end
def flipback
if attribs[:flipped] && !attribs[:unflippable]
@movement_grid = @@SIDE1
attribs[:flipped] = false
end
end
# Move this piece to the graveyard and trigger any effects that happen when the piece is captured
def die(params = {:source => self})
self.space.piece = nil
self.space = nil
self.flipback
self.player.graveyard << self
self.run_effects({:action => :die}.merge(params))
end
#def space=(new_space)
# @space = new_space
#end
=begin
def attribs
@attribs
end
def attribs=(attrib)
@attribs = attrib
end
=end
# = can_reach?(space)
#
# Does the piece's movement grid allow it to move to the Space?
def can_reach?(to_space)
#Flip the movement grid around for player1 (i.e. second player)
mg = self.player.num == 0 ? self.movement_grid : self.movement_grid.reverse
#calculate the number of columns and rows the space is from current position
col_move = to_space.col - self.space.col # Left: <0 Right: >0
row_move = to_space.row - self.space.row # Up: >0 Down: <0
#check if the piece's movement grid allows it to move DIRECTLY (i.e. 'jump') to the specified space
if col_move.abs <= MAX_COL_MOVE &&
row_move.abs <= MAX_ROW_MOVE &&
mg[MOVEMENT_GRID_CENTER - (MOVEMENT_GRID_WIDTH * row_move) + col_move] != 0
return true
else #if the piece can't jump to the specified space, see if it can 'slide' there
#HANDLE ADVANCED MOVEMENT
# The piece's grid doesn't allow it to move there
false
end
end
def can_enter?(to_space)
to_space.can_be_entered_by?(self)
end
def enter(to_space)
self.space.exited_by(self)
self.space = to_space
to_space.entered_by(self)
self.run_effects(:action => :successful_move)
end
def can_capture?(piece)
piece.can_be_captured_by?(self)
end
def can_be_captured_by?(piece)
# Test effects
result = run_effects(:piece => piece, :action => :attempt_capture)
return false if result == false
# This piece can be captured
true
end
def capture(opponent_piece)
opponent_piece.die(:player => :opponent)
# Discarding the return value. Any side effects should be handled by the effects themselves.
self.run_effects(:action => :successful_capture)
# Adding the value of the captured piece to the pool last for now.
# It's possible we may need to revisit this.
self.player.pool_add(opponent_piece.cost)
end
# = move(move_to)
#
# Handles piece movement.
# move_to: a Space object representing the space the piece is attempting to move to
#
def move(move_to)
unless self.can_reach?(move_to)
return {:result => false, :message => "#{self.name} at #{self.space.col}, #{self.space.row} cannot reach #{move_to.col}, #{move_to.row}"}
end
unless self.can_enter?(move_to)
return {:result => false, :message => "#{self.name} at #{self.space.col}, #{self.space.row} not allowed to enter space at #{move_to.col}, #{move_to.row}"}
end
# We are able to move (and capture)
self.capture(move_to.piece) if move_to.piece
# check for win here?
self.enter(move_to)
#simple_move(move_to)
# default movement
# if move_to.piece == nil
# simple_move(move_to)
# elsif move_to.piece.player == @player
# nil
# else
# #TRY TO CAPTURE AN OPPONENT'S PIECE
# #IF MOVE IS SUCCESSFUL, TRY TO CAPTURE
# #IF CAPTURE IS SUCCESSFUL, THE OPPONENT'S PIECE SHOULD BE SENT :die
# nil
# end
{:result => true, :message => "Move successful"}
end
private
# def simple_move(move_to)
# # Need to have Space run through effects for Space and Occupying piece, if applicable
# self.space.piece = nil
# self.space = move_to
# self.space.piece = self
# end
#Some common movement grids
KING = [ 0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 1, 0, 1, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0 ]
GOLD = [ 0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 1, 0, 1, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0 ]
SILVER = [ 0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0 ]
BLACK = [ 0, 0, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0 ]
RED = [ 0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0 ]
ROOKLIKE = [ 0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
1, 1, 0, 1, 1,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0 ]
BISHOPLIKE = [ 1, 0, 0, 0, 1,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0,
0, 1, 0, 1, 0,
1, 0, 0, 0, 1 ]
SQUARE = [ 0, 0, 0, 0, 0,
0, 0, 1, 0, 0,
0, 1, 0, 1, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0 ]
DIAGONAL = [ 0, 0, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0 ]
end
# -------------
# = BlackStone
# -------------
class BlackStone < Piece
def initialize(player, space)
super(player, space)
@name = "Black Stone"
@num = -1
@cost = 1
@movement_grid = BLACK
@attribs[:unflippable] = true
end
def move(move_to)
result = super(move_to)
return result if result[:result] == false
if @player.pool < Player::MAX_POOL
@player.pool += 1
end
end
def flip
nil
end
end
# ------------
# = RedStone
# ------------
class RedStone < Piece
def initialize(player, space)
super(player, space)
@name = "Red Stone"
@num = -2
@cost = 3
@movement_grid = RED
@attribs[:unflippable] = true
end
def move(move_to)
if super(move_to)[:result] && @player.pool < Player::MAX_POOL
@player.pool += 3
end
end
def flip
nil
end
end
# ------------
# = Nav
# ------------
class Nav < Piece
def initialize(player, space)
super(player, space)
@cost = 60
@movement_grid = KING
@attribs[:nav] = true
end
def flip
:win
end
end
# ------------
# = NavEst
# ------------
class NavEst < Nav
def initialize(player, space)
super(player, space)
@name = "Nav Est"
@num = 1
end
end
# ------------
# = NavDeb
# ------------
class NavDeb < Nav
def initialize(player, space)
super(player, space)
@name = "Nav Deb"
@num = 2
end
end
# ------------
# = NavI
# ------------
class NavI < Nav
def initialize(player, space)
super(player, space)
@name = "Nav I"
@num = 3
end
end
# ------------
# = NavKr
# ------------
class NavKr < Nav
def initialize(player, space)
super(player, space)
@name = "Nav Kr"
@num = 4
end
end
# ------------
# = NavCha
# ------------
class NavCha < Nav
def initialize(player, space)
super(player, space)
@name = "Nav Cha"
@num = 5
end
end
# ------------
# = NavHil
# ------------
class NavHil < Nav
def initialize(player, space)
super(player, space)
@name = "Nav Hil"
@num = 6
end
end
# ------------
# = NavPer
# ------------
class NavPer < Nav
def initialize(player, space)
super(player, space)
@name = "Nav Per"
@num = 7
end
end
require 'tro'
require 'ham'