1
0
Fork 0

Implement basic board intelligent strategy

This commit is contained in:
Andrew Tomaka 2022-01-28 21:52:46 -05:00
parent 202f0ce06c
commit 6b591eaa35
Signed by: atomaka
GPG key ID: 61209BF70A5B18BE
6 changed files with 119 additions and 3 deletions

View file

@ -3,6 +3,8 @@ require "selenium-webdriver"
require "webdrivers" require "webdrivers"
require_relative "../nonexistant_guess_error" require_relative "../nonexistant_guess_error"
require_relative "../played_board"
require_relative "../played_letter"
module Board module Board
class WordleUnlimited class WordleUnlimited
@ -80,6 +82,29 @@ module Board
end end
end end
def state
PlayedBoard.new(
locked_in.map do |row|
letters = row
.find_all('div.RowL-letter', wait: 0)
.map do |letter|
state = if letter.[]("class").split.include?("letter-correct")
:correct
elsif letter.[]("class").split.include?("letter-elsewhere")
:elsewhere
elsif letter.[]("class").split.include?("letter-absent")
:absent
end
PlayedLetter.new(
letter: letter.text.downcase,
state: state
)
end
end
)
end
private private
def exact_letters def exact_letters

View file

@ -1,13 +1,17 @@
require "debug" require "debug"
require "logger"
require_relative "outcome"
require_relative "nonexistant_guess_error" require_relative "nonexistant_guess_error"
require_relative "outcome"
require_relative "played_board"
require_relative "played_letter"
require_relative "board/wordle_unlimited" require_relative "board/wordle_unlimited"
require_relative "dictionary/dictionary" require_relative "dictionary/dictionary"
require_relative "dictionary/live_dictionary" require_relative "dictionary/live_dictionary"
require_relative "strategy/basic_board"
require_relative "strategy/most_common" require_relative "strategy/most_common"
require_relative "strategy/naive" require_relative "strategy/naive"
require_relative "strategy/template" require_relative "strategy/template"
@ -16,11 +20,13 @@ require_relative "strategy/wheel_of_fortune"
class Game class Game
attr_reader :board, :dictionary, :start_strategy, :strategy, :outcomes attr_reader :board, :dictionary, :start_strategy, :strategy, :outcomes
attr :logger
def initialize( def initialize(
board: Board::WordleUnlimited, board: Board::WordleUnlimited,
dictionary: Dictionary::LiveDictionary, dictionary: Dictionary::LiveDictionary,
start_strategy: Strategy::MostCommon, start_strategy: Strategy::Vowels,
strategy: Strategy::Template strategy: Strategy::BasicBoard
) )
@board = board.new @board = board.new
@dictionary = dictionary.new @dictionary = dictionary.new
@ -28,6 +34,8 @@ class Game
@strategy = strategy.new(dictionary: @dictionary) @strategy = strategy.new(dictionary: @dictionary)
@outcomes = [] @outcomes = []
@logger = Logger.new("loss-logger.log")
end end
def play def play
@ -42,6 +50,7 @@ class Game
bad_letters: board.bad_letters, bad_letters: board.bad_letters,
guesses: board.guesses, guesses: board.guesses,
template: board.template, template: board.template,
board: board.state,
) )
begin begin
@ -64,6 +73,8 @@ class Game
guesses: board.guesses, guesses: board.guesses,
) )
board.reset! board.reset!
logger.info(outcomes.last.to_s)
end end
end end
end end

View file

@ -14,4 +14,12 @@ class Outcome
def loss? def loss?
state == :loss state == :loss
end end
def to_s
"#{state}: #{correct} guessing #{guesses_to_s}"
end
def guesses_to_s
guesses.join(", ")
end
end end

21
lib/played_board.rb Normal file
View file

@ -0,0 +1,21 @@
class PlayedBoard < Array
def good_letters
(correct_letters + elsewhere_letters).uniq
end
def bad_letters
absent_letters - good_letters
end
def correct_letters
flatten.select(&:correct?).uniq.map(&:letter)
end
def elsewhere_letters
flatten.select(&:elsewhere?).uniq.map(&:letter)
end
def absent_letters
flatten.select(&:absent?).uniq.map(&:letter)
end
end

20
lib/played_letter.rb Normal file
View file

@ -0,0 +1,20 @@
class PlayedLetter
attr :letter, :state
def initialize(letter:, state:)
@letter = letter
@state = state
end
def correct?
state == :correct
end
def elsewhere?
state == :elsewhere
end
def absent?
state == :absent
end
end

View file

@ -0,0 +1,31 @@
module Strategy
class BasicBoard
attr :dictionary, :word_size
def initialize(dictionary:, word_size: 5)
@dictionary = dictionary
@word_size = word_size
end
def guess(board:, **args)
transposed_board = board.transpose
dictionary.words
.select { |word| word.length == word_size }
.reject { |word| (word.chars & board.bad_letters).any? }
.select { |word| (board.good_letters - word.chars).length == 0 }
.reject do |word| # any word has character where board has letter absent
transposed_board.each_with_index.any? do |letters, index|
letters.reject(&:correct?).map(&:letter).include?(word[index])
end
end
.select do |word| # make sure correct letters used in right spot
transposed_board.each_with_index.all? do |letters, index|
correct_letter = letters.select(&:correct?).first
!correct_letter || word[index] == correct_letter.letter
end
end
.sample
end
end
end