1eac3a55a6db4ae9f9ebfe7ed26d624340aac9f0
6 WORDS
= [w
.strip() for w
in open('/usr/share/dict/british-english').readlines()
7 if re
.match(r
'^[a-z]*$', w
.strip())]
9 LETTER_COUNTS
= collections
.Counter(l
.lower() for l
in open('../sherlock-holmes.txt').read() if l
in string
.ascii_letters
)
10 LETTERS_IN_ORDER
= [p
[0] for p
in LETTER_COUNTS
.most_common()]
12 DICT_COUNTS
= collections
.Counter(l
.lower() for l
in open('/usr/share/dict/british-english').read() if l
in string
.ascii_letters
)
13 DICT_LETTERS_IN_ORDER
= [p
[0] for p
in DICT_COUNTS
.most_common()]
18 def __init__(self
, target
, player
=None, lives
=STARTING_LIVES
):
22 self
.discovered
= list('_' * len(target
))
23 self
.wrong_letters
= []
24 self
.game_finished
= False
26 self
.game_lost
= False
28 def find_all(self
, letter
):
29 return [p
for p
, l
in enumerate(self
.target
) if l
== letter
]
31 def update_discovered_word(self
, guessed_letter
):
32 locations
= self
.find_all(guessed_letter
)
33 for location
in locations
:
34 self
.discovered
[location
] = guessed_letter
35 return self
.discovered
39 guess
= self
.player
.guess(self
.discovered
, self
.wrong_letters
, self
.lives
)
41 guess
= self
.ask_for_guess()
42 if guess
in self
.target
:
43 self
.update_discovered_word(guess
)
46 if guess
not in self
.wrong_letters
:
47 self
.wrong_letters
+= [guess
]
49 self
.game_finished
= True
51 if '_' not in self
.discovered
:
52 self
.game_finished
= True
55 def ask_for_guess(self
):
56 print('Word:', ' '.join(self
.discovered
),
57 ' : Lives =', self
.lives
,
58 ', wrong guesses:', ' '.join(sorted(self
.wrong_letters
)))
59 guess
= input('Enter letter: ').strip().lower()[0]
63 while not self
.game_finished
:
69 def report_on_game(self
):
71 print('You won! The word was', self
.target
)
73 print('You lost. The word was', self
.target
)
77 class PlayerFixedOrder
:
78 def __init__(self
, ordered_letters
):
79 self
.ordered_letters
= ordered_letters
81 def guess(self
, discovered
, missed
, lives
):
82 guessed_letters
= [l
.lower() for l
in discovered
+ missed
if l
in string
.ascii_letters
]
83 return [l
for l
in self
.ordered_letters
if l
not in guessed_letters
][0]
85 class PlayerAlphabetical(PlayerFixedOrder
):
87 super().__init
__(string
.ascii_lowercase
)
89 class PlayerAlphabeticalReversed(PlayerFixedOrder
):
91 super().__init
__(list(reversed(string
.ascii_lowercase
)))
93 class PlayerFreqOrdered(PlayerFixedOrder
):
95 super().__init
__(LETTERS_IN_ORDER
)
97 class PlayerDictFreqOrdered(PlayerFixedOrder
):
99 super().__init
__(DICT_LETTERS_IN_ORDER
)
102 class PlayerAdaptive
:
103 def __init__(self
, words
):
104 self
.candidate_words
= words
106 def guess(self
, discovered
, missed
, lives
):
107 self
.filter_candidate_words(discovered
, missed
)
108 self
.set_ordered_letters()
109 guessed_letters
= [l
.lower() for l
in discovered
+ missed
if l
in string
.ascii_letters
]
110 return [l
for l
in self
.ordered_letters
if l
not in guessed_letters
][0]
112 def filter_candidate_words(self
, discovered
, missed
):
115 def set_ordered_letters(self
):
116 counts
= collections
.Counter(l
.lower()
117 for l
in ''.join(self
.candidate_words
) + string
.ascii_lowercase
118 if l
in string
.ascii_letters
)
119 self
.ordered_letters
= [p
[0] for p
in counts
.most_common()]
121 def match(self
, pattern
, target
, excluded
=None):
124 if len(pattern
) != len(target
):
126 for m
, c
in zip(pattern
, target
):
127 if m
== '_' and c
not in excluded
:
130 elif m
!= '_' and m
== c
:
137 class PlayerAdaptiveLength(PlayerAdaptive
):
138 def __init__(self
, words
):
139 super().__init
__(words
)
141 self
.ordered_letters
= None
143 def filter_candidate_words(self
, discovered
, missed
):
144 if not self
.word_len
:
145 self
.word_len
= len(discovered
)
146 self
.candidate_words
= [w
for w
in self
.candidate_words
if len(w
) == self
.word_len
]
148 def set_ordered_letters(self
):
149 if not self
.ordered_letters
:
150 super().set_ordered_letters()
153 class PlayerAdaptiveIncludedLetters(PlayerAdaptive
):
154 def filter_candidate_words(self
, discovered
, missed
):
155 self
.candidate_words
= [w
for w
in self
.candidate_words
if self
.match(discovered
, w
)]
158 class PlayerAdaptiveExcludedLetters(PlayerAdaptive
):
159 def filter_candidate_words(self
, discovered
, missed
):
161 empty_target
= '_' * len(discovered
)
162 self
.candidate_words
= [w
for w
in self
.candidate_words
if self
.match(empty_target
, w
, missed
)]
165 class PlayerAdaptivePattern(PlayerAdaptive
):
166 def filter_candidate_words(self
, discovered
, missed
):
167 attempted_letters
= [l
for l
in discovered
if l
!= '_'] + missed
168 self
.candidate_words
= [w
for w
in self
.candidate_words
if self
.match(discovered
, w
, attempted_letters
)]
171 class PlayerAdaptiveSplit(PlayerAdaptivePattern
):
172 def set_ordered_letters(self
):
174 return abs(sum(1 if l
in w
else -1 for w
in self
.candidate_words
))
175 possible_letters
= set(''.join(self
.candidate_words
))
176 letter_diffs
= [(l
, letter_diff(l
)) for l
in possible_letters
]
177 self
.ordered_letters
= [p
[0] for p
in sorted(letter_diffs
, key
=lambda p
: p
[1])]