Class: Advance

Inherits:
Action show all
Defined in:
lib/software_challenge_client/action.rb

Overview

Go forward in the current direction by #distance. When on a sandbank, a value of -1 to go backwards is also legal.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Action

#invalid

Constructor Details

#initialize(distance) ⇒ Advance

Returns a new instance of Advance.



128
129
130
# File 'lib/software_challenge_client/action.rb', line 128

def initialize(distance)
  @distance = distance
end

Instance Attribute Details

#distanceObject (readonly)

Returns the value of attribute distance.



126
127
128
# File 'lib/software_challenge_client/action.rb', line 126

def distance
  @distance
end

Instance Method Details

#==(other) ⇒ Object



219
220
221
# File 'lib/software_challenge_client/action.rb', line 219

def ==(other)
  other.type == type && other.distance == distance
end

#perform!(gamestate, current_player) ⇒ Object

Perform the action.

Parameters:

  • gamestate (GameState)

    The game state on which the action will be performed. Performing may change the game state.

  • current_player (Player)

    The player for which the action will be performed.



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
# File 'lib/software_challenge_client/action.rb', line 133

def perform!(gamestate, current_player)
  invalid 'Bewegung um 0 ist unzulässig.' if distance.zero?
  if distance < 0 && gamestate.board.field(current_player.x, current_player.y).type != FieldType::SANDBANK
    invalid 'Negative Bewegung ist nur auf Sandbank erlaubt.'
  end
  begin
    fields = gamestate.board.get_all_in_direction(
      current_player.x, current_player.y, current_player.direction, distance
    )
  rescue FieldUnavailableException => e
    invalid "Feld (#{e.x}, #{e.y}) ist nicht vorhanden"
  end
  # test if all fields are passable
  if fields.any?(&:blocked?)
    invalid 'Der Weg ist blockiert.'
  end
  # Test if movement is enough.
  req_movement = required_movement(gamestate, current_player)
  if req_movement > current_player.movement
    invalid 'Nicht genug Bewegungspunkte.'
  end
  # test if opponent is not on fields over which is moved
  if fields[0...-1].any? { |f| gamestate.occupied_by_other_player? f }
    invalid 'Man darf nicht über den Gegner fahren.'
  end
  # test if moving over sandbank
  if fields[0...-1].any? { |f| f.type == FieldType::SANDBANK }
    invalid 'Die Bewegung darf nur auf einer Sandbank enden, '\
            'nicht über sie hinaus gehen.'
  end
  target_field = fields.last
  current_player.x = target_field.x
  current_player.y = target_field.y

  if target_field.type == FieldType::SANDBANK
    current_player.movement = 0
    current_player.velocity = 1
  else
    current_player.movement -= req_movement
  end

  # test for passenger
  if current_player.velocity == 1
    required_field_for_direction = {
      Direction::RIGHT.key=> FieldType::PASSENGER3.key,
      Direction::UP_RIGHT.key=> FieldType::PASSENGER4.key,
      Direction::UP_LEFT.key=> FieldType::PASSENGER5.key,
      Direction::LEFT.key=> FieldType::PASSENGER0.key,
      Direction::DOWN_LEFT.key=> FieldType::PASSENGER2.key,
      Direction::DOWN_RIGHT.key=> FieldType::PASSENGER1.key
    }
    Direction.each do |direction|
      begin
        neighbor = gamestate.board.get_in_direction(current_player.x, current_player.y, direction)
        if neighbor.type.key == required_field_for_direction[direction.key]
          if current_player.passengers < 2
            current_player.passengers += 1
            neighbor.type = FieldType::BLOCKED
          end
        end
      rescue FieldUnavailableException
        # neighbor did not exist, that is okay
      end
    end
  end

end

#required_movement(gamestate, current_player) ⇒ Object

returns the required movement points to perform this action



202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/software_challenge_client/action.rb', line 202

def required_movement(gamestate, current_player)
  gamestate.board.get_all_in_direction(current_player.x, current_player.y, current_player.direction, distance).map do |field|
    # pushing costs one more movement
    on_opponent = field.x == gamestate.other_player.x && field.y == gamestate.other_player.y
    case field.type
    when FieldType::WATER, FieldType::GOAL, FieldType::SANDBANK
      on_opponent ? 2 : 1
    when FieldType::LOG
      on_opponent ? 3 : 2
    end
  end.reduce(:+)
end

#typeObject



215
216
217
# File 'lib/software_challenge_client/action.rb', line 215

def type
  :advance
end