Class: Upwords::Move

Inherits:
Object
  • Object
show all
Defined in:
lib/upwords/move.rb

Instance Method Summary collapse

Constructor Details

#initialize(tiles = []) ⇒ Move

Initialized with a list of 2D arrays, each containing a position (row, col) and a letter



7
8
9
10
# File 'lib/upwords/move.rb', line 7

def initialize(tiles = [])
  @shape = Shape.new(tiles.map {|(row, col), letter| [row, col]})
  @move = tiles.to_h
end

Instance Method Details

#[](row, col) ⇒ Object

Return the letter in position (row, col) of the move



62
63
64
# File 'lib/upwords/move.rb', line 62

def [](row, col)
  @move[[row, col]]
end

#can_play_letters?(board, raise_exception = false) ⇒ Boolean

Check if entire move can be played on a board violating any board constraints, such as being out of bounds or exceeding the maximum stack height

Returns:

  • (Boolean)


50
51
52
53
54
# File 'lib/upwords/move.rb', line 50

def can_play_letters?(board, raise_exception = false)
  @move.all? do |(row, col), letter|
    board.can_play_letter?(letter, row, col, raise_exception)
  end
end

#legal?(board, dict, raise_exception = false) ⇒ Boolean

Check if a move is legal

Returns:

  • (Boolean)


22
23
24
# File 'lib/upwords/move.rb', line 22

def legal?(board, dict, raise_exception = false)
  legal_shape?(board, raise_exception) && legal_words?(board, dict, raise_exception)
end

Check if a move has a legal shape

Returns:

  • (Boolean)


27
28
29
# File 'lib/upwords/move.rb', line 27

def legal_shape?(board, raise_exception = false)
  @shape.legal?(board, raise_exception)
end

Check if all words that result from move are legal TODO: Add the following legal move checks: TODO: - Move is not a simple pluralization? (e.g. Cat -> Cats is NOT a legal move)

Returns:

  • (Boolean)


34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/upwords/move.rb', line 34

def legal_words?(board, dict, raise_exception = false)

  if can_play_letters?(board, raise_exception)    
    bad_words = self.new_illegal_words(board, dict)
    if bad_words.empty?
      return true
    elsif raise_exception
      raise IllegalMove, "#{bad_words.join(', ')} #{bad_words.size==1 ? 'is not a legal word' : 'are not legal words'}!" 
    end
  end

  return false
end

#new_illegal_words(board, dict) ⇒ Object

Return a list of new words that are not legal that would result from playing this move on the board



108
109
110
# File 'lib/upwords/move.rb', line 108

def new_illegal_words(board, dict)
  new_words(board).reject {|word| dict.legal_word?(word.to_s)}
end

#new_words(board, raise_exception = false) ⇒ Object

Return a list of new words that would result from playing this move on the board



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/upwords/move.rb', line 90

def new_words(board, raise_exception = false)
  if can_play_letters?(board, raise_exception) 
    # HACK: update board with new move
    words = (board.play_move(self).word_positions).select do |word_posns|
      word_posns.any? {|row, col| position?(row, col)}
      
    end.map do |word_posns|
      Word.new(word_posns, board)
    end
  
    # HACK: remove move from board
    remove_from(board)
  
    return words
  end
end

#play(board) ⇒ Object

Play move on board and return the board NOTE: this method mutates the boards! TODO: consider adding the ‘can_play_letters?’ check?



69
70
71
72
73
74
# File 'lib/upwords/move.rb', line 69

def play(board)
  @move.reduce(board) do |b, (posn, letter)| 
    b.play_letter(letter, *posn)
    b
  end
end

#position?(row, col) ⇒ Boolean

Check if a particular position (row, col) is covered by the move

Returns:

  • (Boolean)


57
58
59
# File 'lib/upwords/move.rb', line 57

def position?(row, col)
  @move.key?([row, col])
end

#remove_from(board) ⇒ Object

Remove a previous move from the board and return the board (throws an exception if the move does not exist on the board) NOTE: this method mutates the boards!



78
79
80
81
82
83
84
85
86
87
# File 'lib/upwords/move.rb', line 78

def remove_from(board)
  if @move.any? {|(row, col), letter| board.top_letter(row, col) != letter}
    raise IllegalMove, "Move does not exist on board and therefore cannot be removed!"
  else
    (@move.each_key).reduce(board) do |b, posn| 
      b.remove_top_letter(*posn)
      b
    end
  end
end

#score(board, player) ⇒ Object

Calculate value of move Most of the word score calculate logic is in the Word class. However, this method will also add 20 points if the player uses all of their letters in the move



15
16
17
18
19
# File 'lib/upwords/move.rb', line 15

def score(board, player)
  new_words(board).reduce(player.rack_capacity == @move.size ? 20 : 0) do |total, word|
    total += word.score
  end
end