software_challenge_client 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/.rubocop.yml +6 -0
- data/AUTHORS +6 -0
- data/Guardfile +44 -0
- data/README.md +45 -0
- data/RELEASES.md +4 -0
- data/develop.sh +3 -0
- data/example/client.rb +45 -17
- data/example/main.rb +1 -1
- data/generate-authors.sh +19 -0
- data/lib/software_challenge_client.rb +18 -15
- data/lib/software_challenge_client/action.rb +278 -0
- data/lib/software_challenge_client/board.rb +74 -289
- data/lib/software_challenge_client/client_interface.rb +8 -3
- data/lib/software_challenge_client/condition.rb +2 -4
- data/lib/software_challenge_client/debug_hint.rb +3 -25
- data/lib/software_challenge_client/direction.rb +39 -0
- data/lib/software_challenge_client/field.rb +34 -12
- data/lib/software_challenge_client/field_type.rb +29 -8
- data/lib/software_challenge_client/field_unavailable_exception.rb +17 -0
- data/lib/software_challenge_client/game_state.rb +88 -255
- data/lib/software_challenge_client/invalid_move_exception.rb +16 -0
- data/lib/software_challenge_client/logging.rb +24 -0
- data/lib/software_challenge_client/move.rb +36 -35
- data/lib/software_challenge_client/network.rb +16 -19
- data/lib/software_challenge_client/player.rb +47 -10
- data/lib/software_challenge_client/player_color.rb +8 -7
- data/lib/software_challenge_client/protocol.rb +131 -83
- data/lib/software_challenge_client/runner.rb +9 -7
- data/lib/software_challenge_client/version.rb +1 -1
- data/release.sh +9 -0
- data/software_challenge_client.gemspec +20 -8
- metadata +175 -7
- data/lib/software_challenge_client/connection.rb +0 -56
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'typesafe_enum'
|
4
|
+
# A direction on the hexagonal board of the game. Possible directions are:
|
5
|
+
# * RIGHT
|
6
|
+
# * UP_RIGHT
|
7
|
+
# * UP_LEFT
|
8
|
+
# * LEFT
|
9
|
+
# * DOWN_LEFT
|
10
|
+
# * DOWN_RIGHT
|
11
|
+
# Access them as Direction::RIGHT for example.
|
12
|
+
class Direction < TypesafeEnum::Base
|
13
|
+
new :RIGHT
|
14
|
+
new :UP_RIGHT
|
15
|
+
new :UP_LEFT
|
16
|
+
new :LEFT
|
17
|
+
new :DOWN_LEFT
|
18
|
+
new :DOWN_RIGHT
|
19
|
+
|
20
|
+
# @param direction [Direction] starting direction
|
21
|
+
# @param turns [Integer] number of turns (positive means turning
|
22
|
+
# counterclockwise).
|
23
|
+
# @return [Direction] The direction when turning the given number of steps
|
24
|
+
# from the given direction.
|
25
|
+
def self.get_turn_direction(direction, turns)
|
26
|
+
# order of directions is equal to counterclockwise turning
|
27
|
+
Direction.find_by_ord((direction.ord + turns) % 6)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Turn] The Turn action to get from from_direction to to_direction.
|
31
|
+
def self.from_to(from_direction, to_direction)
|
32
|
+
distance = (to_direction.ord - from_direction.ord + 6) % 6
|
33
|
+
if distance > 3
|
34
|
+
distance = distance - 6
|
35
|
+
end
|
36
|
+
Turn.new(distance)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -1,13 +1,8 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
require_relative 'player_color'
|
3
2
|
require_relative 'field_type'
|
4
3
|
|
5
|
-
#
|
6
|
-
# A field on the game board
|
4
|
+
# A field on the game board.
|
7
5
|
class Field
|
8
|
-
# @!attribute [rw] ownerColor
|
9
|
-
# @return [PlayerColor] the field's owner's color
|
10
|
-
attr_accessor :ownerColor
|
11
6
|
# @!attribute [rw] type
|
12
7
|
# @return [PlayerColor] the field's type
|
13
8
|
attr_accessor :type
|
@@ -18,26 +13,53 @@ class Field
|
|
18
13
|
# @return [Integer] the field's y-coordinate
|
19
14
|
attr_reader :y
|
20
15
|
|
16
|
+
# @!attribute [r] direction
|
17
|
+
# @return [Integer] the direction of the tile which the field belongs to
|
18
|
+
attr_reader :direction
|
19
|
+
|
20
|
+
# @!attribute [r] index
|
21
|
+
# @return [Integer] the index of the tile which the field belongs to
|
22
|
+
attr_reader :index
|
23
|
+
|
24
|
+
# @!attribute [r] points
|
25
|
+
# @return [Integer] the points awarded to a player placed on this field additionally to points for current tile and passengers
|
26
|
+
attr_reader :points
|
27
|
+
|
21
28
|
# Initializer
|
22
29
|
#
|
23
30
|
# @param type [FieldType] field type
|
24
31
|
# @param x [Integer] x-coordinate
|
25
32
|
# @param y [Integer] y-coordinate
|
26
|
-
|
27
|
-
|
33
|
+
# @param index [Integer] index of tile
|
34
|
+
# @param direction [Integer] direction of tile
|
35
|
+
# @param points [Integer] points
|
36
|
+
def initialize(type, x, y, index, direction, points)
|
28
37
|
self.type = type
|
29
38
|
@x = x
|
30
39
|
@y = y
|
40
|
+
@index = index
|
41
|
+
@direction = direction
|
42
|
+
@points = points
|
31
43
|
end
|
32
44
|
|
33
45
|
def ==(another_field)
|
34
|
-
return self.
|
35
|
-
self.type == another_field.type &&
|
46
|
+
return self.type == another_field.type &&
|
36
47
|
self.x == another_field.x &&
|
37
48
|
self.y == another_field.y
|
38
49
|
end
|
39
50
|
|
51
|
+
# @return [Boolean] true if the field may never be moved onto.
|
52
|
+
def blocked?
|
53
|
+
[FieldType::BLOCKED,
|
54
|
+
FieldType::PASSENGER0,
|
55
|
+
FieldType::PASSENGER1,
|
56
|
+
FieldType::PASSENGER2,
|
57
|
+
FieldType::PASSENGER3,
|
58
|
+
FieldType::PASSENGER4,
|
59
|
+
FieldType::PASSENGER5].include? type
|
60
|
+
end
|
61
|
+
|
40
62
|
def to_s
|
41
|
-
return "Field: x = #{self.x}, y = #{self.y},
|
63
|
+
return "Field: x = #{self.x}, y = #{self.y}, type = #{self.type}"
|
42
64
|
end
|
43
|
-
end
|
65
|
+
end
|
@@ -1,9 +1,30 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
|
3
|
+
require 'typesafe_enum'
|
4
|
+
# All possible field types:
|
5
|
+
# * WATER
|
6
|
+
# * BLOCKED
|
7
|
+
# * PASSENGER0
|
8
|
+
# * PASSENGER1
|
9
|
+
# * PASSENGER2
|
10
|
+
# * PASSENGER3
|
11
|
+
# * PASSENGER4
|
12
|
+
# * PASSENGER5
|
13
|
+
# * SANDBANK
|
14
|
+
# * LOG
|
15
|
+
# * GOAL
|
16
|
+
# Access them with FieldType::WATER.
|
17
|
+
class FieldType < TypesafeEnum::Base
|
18
|
+
new :WATER
|
19
|
+
new :BLOCKED
|
20
|
+
new :PASSENGER0
|
21
|
+
new :PASSENGER1
|
22
|
+
new :PASSENGER2
|
23
|
+
new :PASSENGER3
|
24
|
+
new :PASSENGER4
|
25
|
+
new :PASSENGER5
|
26
|
+
new :SANDBANK
|
27
|
+
new :LOG
|
28
|
+
new :GOAL
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Exception indicating that a requested field does not exist.
|
3
|
+
class FieldUnavailableException < StandardError
|
4
|
+
# @!attribute [r] x
|
5
|
+
# @return [Integer] the X-coordinate of the requested field.
|
6
|
+
attr_reader :x
|
7
|
+
|
8
|
+
# @!attribute [r] y
|
9
|
+
# @return [Integer] the Y-coordinate of the requested field.
|
10
|
+
attr_reader :y
|
11
|
+
|
12
|
+
def initialize(x, y)
|
13
|
+
super("Field with coordinates (#{x},#{y}) is not available.")
|
14
|
+
@x = x
|
15
|
+
@y = y
|
16
|
+
end
|
17
|
+
end
|
@@ -1,25 +1,22 @@
|
|
1
|
-
# encoding:
|
1
|
+
# encoding: utf-8
|
2
2
|
require_relative './util/constants'
|
3
3
|
require_relative 'player'
|
4
4
|
require_relative 'board'
|
5
5
|
require_relative 'move'
|
6
6
|
require_relative 'condition'
|
7
|
-
require_relative 'player_color'
|
8
7
|
require_relative 'field_type'
|
9
8
|
|
10
|
-
#
|
11
|
-
# The state of a game
|
9
|
+
# The state of a game, as received from the server.
|
12
10
|
class GameState
|
13
|
-
|
14
11
|
# @!attribute [rw] turn
|
15
12
|
# @return [Integer] turn number
|
16
13
|
attr_accessor :turn
|
17
|
-
# @!attribute [rw]
|
14
|
+
# @!attribute [rw] start_player_color
|
18
15
|
# @return [PlayerColor] the start-player's color
|
19
|
-
attr_accessor :
|
20
|
-
# @!attribute [rw]
|
16
|
+
attr_accessor :start_player_color
|
17
|
+
# @!attribute [rw] current_player_color
|
21
18
|
# @return [PlayerColor] the current player's color
|
22
|
-
attr_accessor :
|
19
|
+
attr_accessor :current_player_color
|
23
20
|
# @!attribute [r] red
|
24
21
|
# @return [Player] the red player
|
25
22
|
attr_reader :red
|
@@ -35,310 +32,146 @@ class GameState
|
|
35
32
|
# @!attribute [rw] condition
|
36
33
|
# @return [Condition] the winner and winning reason
|
37
34
|
attr_accessor :condition
|
35
|
+
# @!attribute [rw] free_acceleration
|
36
|
+
# @return [Boolean] true if the free acceleration for this turn is still
|
37
|
+
# available.
|
38
|
+
attr_accessor :free_acceleration
|
39
|
+
alias free_acceleration? free_acceleration
|
40
|
+
|
41
|
+
# @!attribute [rw] free_turn
|
42
|
+
# @return [Boolean] True if the free turning for this turn is still
|
43
|
+
# available.
|
44
|
+
attr_accessor :free_turn
|
45
|
+
alias free_turn? free_turn
|
46
|
+
|
47
|
+
# @!attribute [rw] additional_free_turn_after_push
|
48
|
+
# @return [Boolean] True if the free turning for this turn is still
|
49
|
+
# available.
|
50
|
+
attr_accessor :additional_free_turn_after_push
|
51
|
+
alias additional_free_turn_after_push? additional_free_turn_after_push
|
52
|
+
|
53
|
+
POINTS_PER_TILE = 5
|
54
|
+
POINTS_PER_PASSENGER = 5
|
38
55
|
|
39
56
|
def initialize
|
40
|
-
|
41
|
-
|
42
|
-
|
57
|
+
@current_player_color = PlayerColor::RED
|
58
|
+
@start_player_color = PlayerColor::RED
|
59
|
+
@board = Board.new
|
60
|
+
@free_acceleration = true
|
61
|
+
@free_turn = true
|
62
|
+
@additional_free_turn_after_push = false
|
43
63
|
end
|
44
64
|
|
45
65
|
# adds a player to the gamestate
|
46
66
|
#
|
47
67
|
# @param player [Player] the player, that will be added
|
48
|
-
def
|
68
|
+
def add_player(player)
|
49
69
|
if player.color == PlayerColor::RED
|
50
70
|
@red = player
|
51
|
-
|
52
|
-
|
53
|
-
end
|
71
|
+
elsif player.color == PlayerColor::BLUE
|
72
|
+
@blue = player
|
54
73
|
end
|
55
74
|
end
|
56
75
|
|
57
76
|
# gets the current player
|
58
77
|
#
|
59
78
|
# @return [Player] the current player
|
60
|
-
def
|
61
|
-
if
|
62
|
-
|
63
|
-
else
|
64
|
-
return self.blue
|
79
|
+
def current_player
|
80
|
+
if current_player_color == PlayerColor::RED
|
81
|
+
then red
|
82
|
+
else blue
|
65
83
|
end
|
66
84
|
end
|
67
85
|
|
68
86
|
# gets the other (not the current) player
|
69
87
|
#
|
70
88
|
# @return [Player] the other (not the current) player
|
71
|
-
def
|
72
|
-
if
|
73
|
-
return
|
89
|
+
def other_player
|
90
|
+
if current_player_color == PlayerColor::RED
|
91
|
+
return blue
|
74
92
|
else
|
75
|
-
return
|
93
|
+
return red
|
76
94
|
end
|
77
95
|
end
|
78
96
|
|
79
97
|
# gets the other (not the current) player's color
|
80
98
|
#
|
81
99
|
# @return [PlayerColor] the other (not the current) player's color
|
82
|
-
def
|
83
|
-
|
84
|
-
end
|
85
|
-
|
86
|
-
# gets the start player
|
87
|
-
#
|
88
|
-
# @return [Player] the startPlayer
|
89
|
-
def startPlayer
|
90
|
-
if self.startPlayer == PlayerColor::RED
|
91
|
-
return self.red
|
92
|
-
else
|
93
|
-
return self.blue
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
# switches current player
|
98
|
-
def switchCurrentPlayer
|
99
|
-
if currentPlayer.color == PlayerColor::RED
|
100
|
-
@currentPlayer = self.blue
|
101
|
-
else
|
102
|
-
@currentPlayer = self.red
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# prepares next turn and sets the last move
|
107
|
-
#
|
108
|
-
# @param [Move] the last move
|
109
|
-
def prepareNextTurn(lastMove)
|
110
|
-
@turn++
|
111
|
-
@lastMove = lastMove;
|
112
|
-
self.switchCurrentPlayer()
|
100
|
+
def other_player_color
|
101
|
+
PlayerColor.opponent_color(current_player_color)
|
113
102
|
end
|
114
103
|
|
115
104
|
# gets the current round
|
116
105
|
#
|
117
106
|
# @return [Integer] the current round
|
118
107
|
def round
|
119
|
-
|
120
|
-
end
|
121
|
-
|
122
|
-
# gets all possible moves
|
123
|
-
#
|
124
|
-
# @return [Array<Move>] a list of all possible moves
|
125
|
-
def getPossibleMoves
|
126
|
-
enemyFieldType = currentPlayer.color == PlayerColor::RED ? FieldType::BLUE : FieldType::RED
|
127
|
-
moves = Array.new
|
128
|
-
for x in 0..(Constants::SIZE-1)
|
129
|
-
for y in 0..(Constants::SIZE-1)
|
130
|
-
if (self.board.fields[x][y].ownerColor == PlayerColor::NONE &&
|
131
|
-
self.board.fields[x][y].type != FieldType::SWAMP &&
|
132
|
-
self.board.fields[x][y].type != enemyFieldType)
|
133
|
-
moves.push(Move.new(x, y))
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
return moves
|
108
|
+
turn / 2
|
138
109
|
end
|
139
110
|
|
140
111
|
# performs a move on the gamestate
|
141
112
|
#
|
142
113
|
# @param move [Move] the move, that will be performed
|
143
114
|
# @param player [Player] the player, who makes the move
|
144
|
-
def perform(move, player)
|
145
|
-
|
146
|
-
|
147
|
-
move.x >= 0 && move.y >= 0
|
148
|
-
if self.getPossibleMoves.include?(move)
|
149
|
-
self.board.put(move.x, move.y, player)
|
150
|
-
player.points = self.pointsForPlayer(player)
|
151
|
-
else
|
152
|
-
raise "Der Zug ist nicht möglich, denn der Platz ist bereits besetzt oder nicht besetzbar."
|
153
|
-
end
|
154
|
-
else
|
155
|
-
raise "Startkoordinaten sind nicht innerhalb des Spielfeldes."
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
# gets a player's points
|
161
|
-
#
|
162
|
-
# @param player [Player] the player, whos statistics will be returned
|
163
|
-
# @return [Integer] the points of the player
|
164
|
-
def playerStats(player)
|
165
|
-
return self.playerStats(player.color)
|
166
|
-
end
|
167
|
-
|
168
|
-
# gets a player's points by the player's color
|
169
|
-
#
|
170
|
-
# @param playerColor [PlayerColor] the player's color, whos statistics will be returned
|
171
|
-
# @return [Integer] the points of the player
|
172
|
-
def playerStats(playerColor)
|
173
|
-
if playerColor == PlayerColor::RED
|
174
|
-
return self.gameStats[0];
|
175
|
-
else
|
176
|
-
return self.gameStats[1]
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
# gets the players' statistics
|
181
|
-
#
|
182
|
-
# @return [Array<Integer>] the points for both players
|
183
|
-
def gameStats
|
184
|
-
stats = Array.new(2, Array.new(1))
|
185
|
-
|
186
|
-
stats[0][0] = self.red.points
|
187
|
-
stats[1][0] = self.blue.points
|
188
|
-
|
189
|
-
return stats
|
190
|
-
end
|
191
|
-
|
192
|
-
# get the players' names
|
193
|
-
#
|
194
|
-
# @return [Array<String>] the names for both players
|
195
|
-
def playerNames
|
196
|
-
return [red.displayName, blue.displayName]
|
197
|
-
end
|
198
|
-
|
199
|
-
# sets the game-ended condition
|
200
|
-
#
|
201
|
-
# @param winner [Player] the winner of the game
|
202
|
-
# @param reason [String] the winning reason
|
203
|
-
def endGame(winner, reason)
|
204
|
-
if condition.nil?
|
205
|
-
@condition = Condition.new(winner, reason)
|
115
|
+
def perform!(move, player)
|
116
|
+
move.actions.each do |action|
|
117
|
+
action.perform!(self, player)
|
206
118
|
end
|
207
119
|
end
|
208
120
|
|
209
121
|
# has the game ended?
|
210
122
|
#
|
211
123
|
# @return [Boolean] true, if the game has allready ended
|
212
|
-
def
|
213
|
-
|
124
|
+
def game_ended?
|
125
|
+
!condition.nil?
|
214
126
|
end
|
215
127
|
|
216
128
|
# gets the game's winner
|
217
129
|
#
|
218
130
|
# @return [Player] the game's winner
|
219
131
|
def winner
|
220
|
-
|
132
|
+
condition.nil? ? nil : condition.winner
|
221
133
|
end
|
222
134
|
|
223
135
|
# gets the winning reason
|
224
136
|
#
|
225
137
|
# @return [String] the winning reason
|
226
|
-
def
|
227
|
-
|
138
|
+
def winning_reason
|
139
|
+
condition.nil? ? nil : condition.reason
|
228
140
|
end
|
229
141
|
|
230
|
-
# calculates a player's points
|
142
|
+
# calculates a player's points based on the current gamestate
|
231
143
|
#
|
232
|
-
#
|
144
|
+
# @param player [Player] the player, whos point will be calculated
|
233
145
|
# @return [Integer] the points of the player
|
234
|
-
def
|
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
|
-
for fields in outermostFieldsInCircuit
|
267
|
-
if (playerColor == PlayerColor::RED && fields[1].y - fields[0].y > longestPath)
|
268
|
-
longestPath = fields[1].y - fields[0].y
|
269
|
-
end
|
270
|
-
if (playerColor == PlayerColor::BLUE && fields[1].x - fields[0].x > longestPath)
|
271
|
-
longestPath = fields[1].x - fields[0].x
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
return longestPath # return longestPath
|
276
|
-
end
|
277
|
-
|
278
|
-
# the following functions are helpers for the points calculation
|
279
|
-
def bottomMostFieldInCircuit(circuit)
|
280
|
-
bottomMostField = circuit[0]
|
281
|
-
for f in circuit
|
282
|
-
if f.y < bottomMostField.y
|
283
|
-
bottomMostField = f
|
284
|
-
end
|
285
|
-
end
|
286
|
-
return bottomMostField
|
287
|
-
end
|
288
|
-
|
289
|
-
def topMostFieldInCircuit(circuit)
|
290
|
-
topMostField = circuit[0]
|
291
|
-
for f in circuit
|
292
|
-
if f.y > topMostField.y
|
293
|
-
topMostField = f
|
294
|
-
end
|
295
|
-
end
|
296
|
-
return topMostField
|
297
|
-
end
|
298
|
-
|
299
|
-
def leftMostFieldInCircuit(circuit)
|
300
|
-
leftMostField = circuit[0]
|
301
|
-
for f in circuit
|
302
|
-
if f.x < leftMostField.x
|
303
|
-
leftMostField = f
|
304
|
-
end
|
305
|
-
end
|
306
|
-
return leftMostField
|
307
|
-
end
|
308
|
-
|
309
|
-
def rightMostFieldInCircuit(circuit)
|
310
|
-
rightMostField = circuit[0]
|
311
|
-
for f in circuit
|
312
|
-
if f.x > rightMostField.x
|
313
|
-
rightMostField = f
|
314
|
-
end
|
315
|
-
end
|
316
|
-
return rightMostField
|
317
|
-
end
|
318
|
-
|
319
|
-
def circuit(circuit, visited)
|
320
|
-
changed = false;
|
321
|
-
toBeAddedFields = Array.new
|
322
|
-
for f in circuit
|
323
|
-
if !visited.include?(f)
|
324
|
-
changed = true
|
325
|
-
visited.push(f)
|
326
|
-
for c in self.board.getConnections(f.x,f.y)
|
327
|
-
if !circuit.include?(self.board.fields[c.x2][c.y2])
|
328
|
-
toBeAddedFields.push(self.board.fields[c.x2][c.y2])
|
329
|
-
end
|
330
|
-
if !circuit.include?(self.board.fields[c.x1][c.y1])
|
331
|
-
toBeAddedFields.push(self.board.fields[c.x1][c.y1])
|
332
|
-
end
|
333
|
-
end
|
334
|
-
end
|
335
|
-
end
|
336
|
-
circuit.push(*toBeAddedFields)
|
337
|
-
if changed
|
338
|
-
return self.circuit(circuit, visited)
|
339
|
-
else
|
340
|
-
return circuit
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
end
|
146
|
+
def points_for_player(player)
|
147
|
+
player_field = board.field(player.x, player.y)
|
148
|
+
POINTS_PER_TILE * player_field.index +
|
149
|
+
POINTS_PER_PASSENGER * player.passengers +
|
150
|
+
player_field.points
|
151
|
+
end
|
152
|
+
|
153
|
+
# @return [Boolean] true if the given field is occupied by the other (not
|
154
|
+
# current) player.
|
155
|
+
def occupied_by_other_player?(field)
|
156
|
+
field.x == other_player.x && field.y == other_player.y
|
157
|
+
end
|
158
|
+
|
159
|
+
# Compared with other state.
|
160
|
+
def ==(other)
|
161
|
+
turn == other.turn &&
|
162
|
+
start_player_color == other.start_player_color &&
|
163
|
+
current_player_color == other.current_player_color &&
|
164
|
+
red == other.red &&
|
165
|
+
blue == other.blue &&
|
166
|
+
board == other.board &&
|
167
|
+
lastMove == other.lastMove &&
|
168
|
+
free_acceleration == other.free_acceleration &&
|
169
|
+
condition == other.condition
|
170
|
+
end
|
171
|
+
|
172
|
+
# Create a deep copy of the gamestate. Can be used to perform moves on without
|
173
|
+
# changing the original gamestate.
|
174
|
+
def deep_clone
|
175
|
+
Marshal.load(Marshal.dump(self))
|
176
|
+
end
|
177
|
+
end
|