Class: Linotype::Game
- Inherits:
-
Object
- Object
- Linotype::Game
- Defined in:
- lib/linotype/game.rb
Instance Attribute Summary collapse
-
#current_player ⇒ Object
readonly
Returns the value of attribute current_player.
-
#moves ⇒ Object
Returns the value of attribute moves.
-
#players ⇒ Object
readonly
Returns the value of attribute players.
Instance Method Summary collapse
- #all_tiles ⇒ Object
- #best_next_play ⇒ Object
- #board ⇒ Object
- #calc_potential_plays(remaining_letters) ⇒ Object
- #corner_tiles(player) ⇒ Object
- #covered_tiles(player) ⇒ Object
- #create_tile_letter_array(letter_arg) ⇒ Object
- #defended_tiles(player) ⇒ Object
- #dictionary ⇒ Object
- #edge_tiles(player) ⇒ Object
- #every_play_for_word(word) ⇒ Object
-
#initialize(args = {}) ⇒ Game
constructor
A new instance of Game.
- #invalid_moves ⇒ Object
- #letters ⇒ Object
- #other_player ⇒ Object
- #over? ⇒ Boolean
- #play(*tile_coordinates) ⇒ Object
- #player_number(player) ⇒ Object
- #potential_plays(remaining_letters = letters) ⇒ Object
- #previously_played_words ⇒ Object
- #print_board ⇒ Object
- #print_scores ⇒ Object
- #remaining_plays ⇒ Object
- #score(player) ⇒ Object
- #scores ⇒ Object
- #test_potential_plays ⇒ Object
- #tile_rows ⇒ Object
- #toggle_current_player ⇒ Object
- #uncovered_tiles ⇒ Object
- #valid_moves ⇒ Object
- #valid_potential_plays ⇒ Object
- #winner ⇒ Object
- #word_match(letter_group, word) ⇒ Object
Constructor Details
#initialize(args = {}) ⇒ Game
Returns a new instance of Game.
7 8 9 10 11 12 13 |
# File 'lib/linotype/game.rb', line 7 def initialize(args={}) args = { player_one: Player.new, player_two: Player.new }.merge(args) @board = Board.new(self, tiles: create_tile_letter_array(args[:tiles])) @players = [args[:player_one], args[:player_two]] @current_player = @players[0] @moves = [] end |
Instance Attribute Details
#current_player ⇒ Object (readonly)
Returns the value of attribute current_player.
5 6 7 |
# File 'lib/linotype/game.rb', line 5 def current_player @current_player end |
#moves ⇒ Object
Returns the value of attribute moves.
4 5 6 |
# File 'lib/linotype/game.rb', line 4 def moves @moves end |
#players ⇒ Object (readonly)
Returns the value of attribute players.
5 6 7 |
# File 'lib/linotype/game.rb', line 5 def players @players end |
Instance Method Details
#all_tiles ⇒ Object
155 156 157 |
# File 'lib/linotype/game.rb', line 155 def all_tiles tile_rows.flatten end |
#best_next_play ⇒ Object
86 87 88 89 90 |
# File 'lib/linotype/game.rb', line 86 def best_next_play valid_potential_plays.sort do |a, b| current_player.strategy.score(b) <=> current_player.strategy.score(a) end.first end |
#board ⇒ Object
104 105 106 |
# File 'lib/linotype/game.rb', line 104 def board tile_rows.collect { |row| row.collect { |tile| tile.to_hash } } end |
#calc_potential_plays(remaining_letters) ⇒ Object
120 121 122 123 124 125 126 127 128 129 |
# File 'lib/linotype/game.rb', line 120 def calc_potential_plays(remaining_letters) plays = [] letter_group = letters.group_by { |l| l } dictionary.words.each do |word| if word_match(letter_group, word) plays << word end end plays end |
#corner_tiles(player) ⇒ Object
197 198 199 |
# File 'lib/linotype/game.rb', line 197 def corner_tiles(player) tile_rows.flatten.select { |tile| player && tile.corner? && tile.covered_by == player } end |
#covered_tiles(player) ⇒ Object
189 190 191 |
# File 'lib/linotype/game.rb', line 189 def covered_tiles(player) tile_rows.flatten.select { |tile| player && tile.covered_by == player } end |
#create_tile_letter_array(letter_arg) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/linotype/game.rb', line 15 def create_tile_letter_array(letter_arg) case letter_arg when nil Board.new_random_letters when Array letter_arg when String square_size = Math.sqrt(letter_arg.length).ceil letter_array = [[]] letter_arg.each_char do |letter| letter_array << [] if letter_array.last.size == square_size letter_array.last << letter.upcase end letter_array end end |
#defended_tiles(player) ⇒ Object
185 186 187 |
# File 'lib/linotype/game.rb', line 185 def defended_tiles(player) tile_rows.flatten.select { |tile| player && tile.covered_by == player && tile.defended? } end |
#dictionary ⇒ Object
147 148 149 |
# File 'lib/linotype/game.rb', line 147 def dictionary Linotype::Dictionary.loaded end |
#edge_tiles(player) ⇒ Object
193 194 195 |
# File 'lib/linotype/game.rb', line 193 def edge_tiles(player) tile_rows.flatten.select { |tile| player && tile.edge? && tile.covered_by == player } end |
#every_play_for_word(word) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/linotype/game.rb', line 37 def every_play_for_word(word) tiles_per_letter = {} word.chars.to_a.uniq.each do |unique_letter| tiles_per_letter[unique_letter] = [] tile_rows.flatten.select { |tile| tile.letter == unique_letter }.each do |matching_tile| tiles_per_letter[unique_letter] << matching_tile end end variations = tiles_per_letter.values.inject(1) { |vars, tiles| tiles.count * vars } plays = [] v = 0 variations.times { plays << []; v += 1 } word.chars.each do |letter| play_number = 0 repetitions = variations / tiles_per_letter[letter].count tiles_per_letter[letter].each do |tile| repetitions.times do plays[play_number] << tile play_number += 1 end end end plays.select { |play| play.uniq.count == play.count } end |
#invalid_moves ⇒ Object
143 144 145 |
# File 'lib/linotype/game.rb', line 143 def invalid_moves @moves.select(&:invalid?) end |
#letters ⇒ Object
159 160 161 |
# File 'lib/linotype/game.rb', line 159 def letters @board.tiles.flatten.collect(&:letter) end |
#other_player ⇒ Object
163 164 165 |
# File 'lib/linotype/game.rb', line 163 def other_player @players.index(@current_player) == 0 ? @players[1] : @players[0] end |
#over? ⇒ Boolean
92 93 94 |
# File 'lib/linotype/game.rb', line 92 def over? uncovered_tiles.empty? || two_passes_in_a_row? end |
#play(*tile_coordinates) ⇒ Object
32 33 34 35 |
# File 'lib/linotype/game.rb', line 32 def play(*tile_coordinates) tiles = find_tiles(tile_coordinates) Move.new(self, @current_player, tiles).valid? end |
#player_number(player) ⇒ Object
108 109 110 |
# File 'lib/linotype/game.rb', line 108 def player_number(player) @players.index(player) + 1 end |
#potential_plays(remaining_letters = letters) ⇒ Object
116 117 118 |
# File 'lib/linotype/game.rb', line 116 def potential_plays(remaining_letters=letters) @potential_plays ||= calc_potential_plays(remaining_letters) end |
#previously_played_words ⇒ Object
74 75 76 |
# File 'lib/linotype/game.rb', line 74 def previously_played_words moves.collect(&:word) end |
#print_board ⇒ Object
206 207 208 209 210 211 212 213 214 |
# File 'lib/linotype/game.rb', line 206 def print_board tile_rows.each do |row| r = "" row.each do |tile| r << "#{tile.letter}#{tile.covered_by ? player_number(tile.covered_by) : ' '} " end puts r end end |
#print_scores ⇒ Object
216 217 218 |
# File 'lib/linotype/game.rb', line 216 def print_scores players.each { |player| puts "Player #{player_number(player)}: #{covered_tiles(player).count}" } end |
#remaining_plays ⇒ Object
78 79 80 |
# File 'lib/linotype/game.rb', line 78 def remaining_plays potential_plays - previously_played_words end |
#score(player) ⇒ Object
112 113 114 |
# File 'lib/linotype/game.rb', line 112 def score(player) covered_tiles(player).count end |
#scores ⇒ Object
100 101 102 |
# File 'lib/linotype/game.rb', line 100 def scores @players.inject({}) { |scores, player| scores[player_number(player)] = score(player); scores } end |
#test_potential_plays ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/linotype/game.rb', line 62 def test_potential_plays potential_moves = [] remaining_plays.each do |word_to_test| every_play_for_word(word_to_test).each do |tiles| move = Move.new(self, @current_player, tiles) potential_moves << move move.undo! end end potential_moves end |
#tile_rows ⇒ Object
151 152 153 |
# File 'lib/linotype/game.rb', line 151 def tile_rows @board.tiles end |
#toggle_current_player ⇒ Object
177 178 179 |
# File 'lib/linotype/game.rb', line 177 def toggle_current_player @current_player = other_player end |
#uncovered_tiles ⇒ Object
181 182 183 |
# File 'lib/linotype/game.rb', line 181 def uncovered_tiles all_tiles.select { |tile| !tile.covered_by } end |
#valid_moves ⇒ Object
139 140 141 |
# File 'lib/linotype/game.rb', line 139 def valid_moves @moves.select(&:valid?) end |
#valid_potential_plays ⇒ Object
82 83 84 |
# File 'lib/linotype/game.rb', line 82 def valid_potential_plays test_potential_plays.select { |potential_play| potential_play.valid? } end |
#winner ⇒ Object
96 97 98 |
# File 'lib/linotype/game.rb', line 96 def winner scores.inject(nil) { |winner, p| p[1] > winner.to_i ? p[0] : winner } if over? end |
#word_match(letter_group, word) ⇒ Object
131 132 133 134 135 136 137 |
# File 'lib/linotype/game.rb', line 131 def word_match(letter_group, word) word_letter_group = word.chars.to_a.group_by { |c| c } word.each_char do |letter| return false unless (letter_group[letter] && letter_group[letter].count >= word_letter_group[letter].count) end true end |