Class: GameRuleLogic

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/software_challenge_client/game_rule_logic.rb

Overview

Methoden, welche die Spielregeln von Ostseeschach abbilden.

Es gibt hier viele Helfermethoden, die von den beiden Hauptmethoden GameRuleLogic.valid_move? und GameRuleLogic.possible_moves benutzt werden.

Constant Summary collapse

SUM_MAX_SQUARES =
89

Constants included from Constants

Constants::BOARD_SIZE, Constants::GAME_IDENTIFIER, Constants::ROUND_LIMIT

Class Method Summary collapse

Class Method Details

.moves_for_piece(gamestate, piece) ⇒ Array<Move>

Hilfsmethode um Legezüge für einen [Piece] zu berechnen.

Parameters:

  • gamestate (GameState)

    Der zu untersuchende Spielstand.

  • piece (Piece)

    Der Typ des Spielsteines

Returns:

  • (Array<Move>)

    Die möglichen Moves



75
76
77
78
79
80
81
# File 'lib/software_challenge_client/game_rule_logic.rb', line 75

def self.moves_for_piece(gamestate, piece)
  moves = Set[]
  self.target_coords(gamestate, piece).each do |c| 
    moves << Move.new(piece.coords, c)
  end
  moves.select { |m| valid_move?(gamestate, m) }.to_a
end

.perform_move(gamestate, move) ⇒ GameState

Führe den gegebenen [Move] im gebenenen [GameState] aus.

Parameters:

  • gamestate (GameState)

    der aktuelle Spielstand

  • move

    der auszuführende Zug

Returns:



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

def self.perform_move(gamestate, move)
  raise 'Invalid move!' unless valid_move?(gamestate, move)

  target_field = gamestate.board.field_at(move.to)

  gamestate.current_player.fishes += target_field.fishes

  if gamestate.turn < 8 
    target_field.piece = Piece.new(gamestate.current_player.team, move.to)
  else
    start_field = gamestate.board.field_at(move.from)

    start_field.fishes = 0

    target_field.piece = start_field.piece
    start_field.piece = nil?
  end

  other_player = gamestate.not_player(gamestate.current_player)
  if gamestate.can_move?(other_player)
    gamestate.current_player = other_player
  end

  gamestate.turn += 1
end

.possible_move(gamestate) ⇒ Move

Gibt einen zufälligen möglichen Zug zurück

Parameters:

  • gamestate (GameState)

    Der zu untersuchende Spielstand.

Returns:

  • (Move)

    Ein möglicher Move



66
67
68
# File 'lib/software_challenge_client/game_rule_logic.rb', line 66

def self.possible_move(gamestate)
  self.possible_moves(gamestate).sample
end

.possible_moves(gamestate) ⇒ Array<Move>

Gibt alle möglichen Züge für den Spieler zurück, der in der gamestate dran ist. Diese ist die wichtigste Methode dieser Klasse für Schüler.

Parameters:

  • gamestate (GameState)

    Der zu untersuchende Spielstand.

Returns:

  • (Array<Move>)

    Die möglichen Moves



25
26
27
28
29
30
31
# File 'lib/software_challenge_client/game_rule_logic.rb', line 25

def self.possible_moves(gamestate)
  if gamestate.turn < 8
    self.possible_setmoves(gamestate)
  else
    self.possible_normalmoves(gamestate)
  end
end

.possible_normalmoves(gamestate) ⇒ Object



51
52
53
54
55
56
57
58
59
60
# File 'lib/software_challenge_client/game_rule_logic.rb', line 51

def self.possible_normalmoves(gamestate)
  moves = []
  fields = gamestate.board.fields_of_team(gamestate.current_player.team)

  fields.each do |f|
    moves.push(*moves_for_piece(gamestate, f.piece))
  end

  moves.select { |m| valid_move?(gamestate, m) }.to_a
end

.possible_setmoves(gamestate) ⇒ Array<Move>

Gibt alle möglichen Lege-Züge für den Spieler zurück, der in der gamestate dran ist.

Parameters:

  • gamestate (GameState)

    Der zu untersuchende Spielstand.

Returns:

  • (Array<Move>)

    Die möglichen Moves



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/software_challenge_client/game_rule_logic.rb', line 37

def self.possible_setmoves(gamestate)
  moves = []

  (0...BOARD_SIZE).to_a.map do |x|
    (0...BOARD_SIZE).to_a.map do |y|
      if gamestate.board.field(x, y).fishes == 1
        moves.push(Move.new(nil, Coordinates.new(x, y)))
      end
    end
  end

  moves
end

.target_coords(gamestate, piece) ⇒ Array<Coordinates>

Berechnet die Koordinaten zu denen sich dieser Spielstein bewegen könnte.

Returns:



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

def self.target_coords(gamestate, piece)
  coords = []
  c = Coordinates.oddr_to_doubled(piece.coords)

  Direction.each { |d|
    x = c.x
    y = c.y
    disp = d.to_vec()

    # doubled taversal
    for i in 0..8 do
      x += disp.x
      y += disp.y
      
      oddr_coords = Coordinates.doubled_to_oddr_int(x, y)
      if !gamestate.board.in_bounds?(oddr_coords) || !gamestate.board.field_at(oddr_coords).free?
        break
      end

      coords.push(oddr_coords)
    end
  }

  coords
end

.valid_move?(gamestate, move) ⇒ Boolean

Prüft, ob der gegebene [Move] zulässig ist.

Parameters:

  • gamestate (GameState)

    Der zu untersuchende Spielstand.

  • move (Move)

    Der zu überprüfende Zug

Returns:

  • (Boolean)

    ob der Zug zulässig ist



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

def self.valid_move?(gamestate, move)
  if gamestate.turn < 8
    # Setmove

    # Must be setmove
    return false unless move.from == nil
    
    # Must have 1 fish to set on
    return false unless gamestate.board.field_at(move.to).fishes == 1 

    # Must have no piece on it
    return false unless gamestate.board.field_at(move.to).piece == nil
  else
    # Normal move

    # Must be normal move
    return false unless !move.from.nil?

    # Team must be correct
    return false unless gamestate.current_player.team == gamestate.board.field_at(move.from).piece.team

    # Move must stay in bounds
    return false unless gamestate.board.in_bounds?(move.to)

    # Move must go onto free field
    return false unless gamestate.board.field_at(move.to).free?

    # Move must go onto valid coords
    return false unless self.target_coords(gamestate, gamestate.board.field_at(move.from).piece).include?(move.to)
  end

  # TODO 2023: Forgot checks?

  true
end

.winning_condition(gamestate) ⇒ Condition

Prueft, ob ein Spieler im gegebenen GameState gewonnen hat.

Parameters:

  • gamestate (GameState)

    Der zu untersuchende GameState.

Returns:

  • (Condition)

    nil, if the game is not won or a Condition indicating the winning player



194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/software_challenge_client/game_rule_logic.rb', line 194

def self.winning_condition(gamestate)
  
  if GameRuleLogic.possible_moves(gamestate).count == 0
    if gamestate.player_one.fishes > gamestate.player_two.fishes
      Condition.new(gamestate.player_one, "Spieler 1 hat mehr Fische erreicht und gewonnen!")
    else
      Condition.new(gamestate.player_one, "Spieler 2 hat mehr Fische erreicht und gewonnen!")
    end
  end

  nil
end