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(''.join(WORDS
))
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 return [l
for l
in self
.ordered_letters
if l
not in discovered
+ missed
][0]
84 class PlayerAlphabetical(PlayerFixedOrder
):
86 super().__init
__(string
.ascii_lowercase
)
88 class PlayerAlphabeticalReversed(PlayerFixedOrder
):
90 super().__init
__(list(reversed(string
.ascii_lowercase
)))
92 class PlayerFreqOrdered(PlayerFixedOrder
):
94 super().__init
__(LETTERS_IN_ORDER
)
96 class PlayerDictFreqOrdered(PlayerFixedOrder
):
98 super().__init
__(DICT_LETTERS_IN_ORDER
)
101 class PlayerAdaptive
:
102 def __init__(self
, words
):
103 self
.candidate_words
= words
105 def guess(self
, discovered
, missed
, lives
):
106 self
.filter_candidate_words(discovered
, missed
)
107 self
.set_ordered_letters()
108 return [l
for l
in self
.ordered_letters
if l
not in discovered
+ missed
][0]
110 def filter_candidate_words(self
, discovered
, missed
):
113 def set_ordered_letters(self
):
114 counts
= collections
.Counter(l
.lower()
115 for l
in ''.join(self
.candidate_words
) + string
.ascii_lowercase
116 if l
in string
.ascii_letters
)
117 self
.ordered_letters
= [p
[0] for p
in counts
.most_common()]
119 def match(self
, pattern
, target
, excluded
=None):
122 if len(pattern
) != len(target
):
124 for m
, c
in zip(pattern
, target
):
125 if m
== '_' and c
not in excluded
:
128 elif m
!= '_' and m
== c
:
135 class PlayerAdaptiveLength(PlayerAdaptive
):
136 def __init__(self
, words
):
137 super().__init
__(words
)
139 self
.ordered_letters
= None
141 def filter_candidate_words(self
, discovered
, missed
):
142 if not self
.word_len
:
143 self
.word_len
= len(discovered
)
144 self
.candidate_words
= [w
for w
in self
.candidate_words
if len(w
) == self
.word_len
]
146 def set_ordered_letters(self
):
147 if not self
.ordered_letters
:
148 super().set_ordered_letters()
151 class PlayerAdaptiveIncludedLetters(PlayerAdaptive
):
152 def filter_candidate_words(self
, discovered
, missed
):
153 self
.candidate_words
= [w
for w
in self
.candidate_words
if self
.match(discovered
, w
)]
156 class PlayerAdaptiveExcludedLetters(PlayerAdaptive
):
157 def filter_candidate_words(self
, discovered
, missed
):
159 empty_target
= '_' * len(discovered
)
160 self
.candidate_words
= [w
for w
in self
.candidate_words
if self
.match(empty_target
, w
, missed
)]
163 class PlayerAdaptivePattern(PlayerAdaptive
):
164 def filter_candidate_words(self
, discovered
, missed
):
165 attempted_letters
= [l
for l
in discovered
if l
!= '_'] + missed
166 self
.candidate_words
= [w
for w
in self
.candidate_words
if self
.match(discovered
, w
, attempted_letters
)]
169 class PlayerAdaptiveSplit(PlayerAdaptivePattern
):
170 def set_ordered_letters(self
):
172 return abs(sum(1 if l
in w
else -1 for w
in self
.candidate_words
))
173 possible_letters
= set(''.join(self
.candidate_words
))
174 letter_diffs
= [(l
, letter_diff(l
)) for l
in possible_letters
]
175 self
.ordered_letters
= [p
[0] for p
in sorted(letter_diffs
, key
=lambda p
: p
[1])]