]>
Commit | Line | Data |
---|---|---|
35c1ca4b HH |
1 | import random |
2 | from wxPython.wx import * | |
3 | ||
4 | class WordFetcher: | |
5 | def __init__(self, filename): | |
6 | try: | |
7 | f = open(filename, "r") | |
8 | except: | |
9 | print "Couldn't open dictionary file %s, using build-ins" % (filename,) | |
10 | self.words = self.builtin_words | |
11 | return | |
12 | self.words = [] | |
13 | while f and len(self.words)<100: | |
14 | line = f.readline() | |
15 | self.words.append(line[0:-1]) | |
16 | print self.words | |
17 | def Get(self): | |
18 | return self.words[int(random.random()*len(self.words))] | |
19 | builtin_words = [ 'albatros', 'banana', 'electrometer', 'eggshell' ] | |
20 | ||
0d236c34 HH |
21 | class HangmanWnd(wxWindow): |
22 | def __init__(self, parent, id): | |
23 | wxWindow.__init__(self, parent, id) | |
24 | self.SetBackgroundColour(wxNamedColour('white')) | |
25 | self.SetFocus() | |
26 | self.frame = parent # ugly | |
27 | def StartGame(self, word): | |
28 | self.word = word | |
29 | self.guess = [] | |
30 | self.tries = 0 | |
31 | self.misses = 0 | |
32 | self.Draw() | |
33 | def EndGame(self): | |
34 | self.misses = 7; | |
35 | self.guess = map(chr, range(ord('a'),ord('z')+1)) | |
36 | self.Draw() | |
37 | def HandleKey(self, key): | |
38 | if self.guess.count(key): | |
39 | self.frame.SetStatusText('Already guessed %s' % (key,),0) | |
40 | return 0 | |
41 | self.guess.append(key) | |
42 | self.guess.sort() | |
43 | self.tries = self.tries+1 | |
44 | if not key in self.word: | |
45 | self.misses = self.misses+1 | |
46 | if self.misses == 7: | |
47 | self.EndGame() | |
48 | return 1 | |
49 | has_won = 1 | |
50 | for letter in self.word: | |
51 | if not self.guess.count(letter): | |
52 | has_won = 0 | |
53 | break | |
54 | if has_won: | |
55 | self.Draw() | |
56 | return 2 | |
57 | self.Draw() | |
58 | return 0 | |
35c1ca4b HH |
59 | def Draw(self, dc = None): |
60 | if not dc: | |
0d236c34 | 61 | dc = wxClientDC(self) |
35c1ca4b | 62 | dc.Clear() |
0d236c34 HH |
63 | (x,y) = self.GetSizeTuple() |
64 | x1 = x-200; y1 = 20 | |
35c1ca4b HH |
65 | for letter in self.word: |
66 | if self.guess.count(letter): | |
67 | dc.DrawText(letter, x1, y1) | |
68 | else: | |
69 | dc.DrawText('.', x1, y1) | |
70 | x1 = x1 + 10 | |
0d236c34 HH |
71 | x1 = x-200 |
72 | dc.DrawText("tries %d misses %d" % (self.tries,self.misses),x1,50) | |
73 | guesses = "" | |
74 | for letter in self.guess: | |
75 | guesses = guesses + letter | |
76 | dc.DrawText("guessed:", x1, 70) | |
77 | dc.DrawText(guesses[:13], x1+70, 70) | |
78 | dc.DrawText(guesses[13:], x1+70, 90) | |
35c1ca4b HH |
79 | dc.SetUserScale(x/1000., y/1000.) |
80 | self.DrawVictim(dc) | |
81 | def DrawVictim(self, dc): | |
82 | dc.SetPen(wxPen(wxNamedColour('black'), 20)) | |
83 | dc.DrawLines([(10, 980), (10,900), (700,900), (700,940), (720,940), | |
84 | (720,980), (900,980)]) | |
85 | dc.DrawLines([(100,900), (100, 100), (300,100)]) | |
86 | dc.DrawLine(100,200,200,100) | |
87 | if ( self.misses == 0 ): return | |
88 | dc.SetPen(wxPen(wxNamedColour('blue'), 10)) | |
89 | dc.DrawLine(300,100,300,200) | |
90 | if ( self.misses == 1 ): return | |
91 | dc.DrawEllipse(250,200,100,100) | |
92 | if ( self.misses == 2 ): return | |
93 | dc.DrawLine(300,300,300,600) | |
94 | if ( self.misses == 3) : return | |
95 | dc.DrawLine(300,300,250,550) | |
96 | if ( self.misses == 4) : return | |
97 | dc.DrawLine(300,300,350,550) | |
98 | if ( self.misses == 5) : return | |
99 | dc.DrawLine(300,600,350,850) | |
100 | if ( self.misses == 6) : return | |
101 | dc.DrawLine(300,600,250,850) | |
102 | def OnPaint(self, event): | |
0d236c34 | 103 | dc = wxPaintDC(self) |
35c1ca4b | 104 | self.Draw(dc) |
0d236c34 HH |
105 | |
106 | class MyFrame(wxFrame): | |
107 | def __init__(self, wf): | |
108 | self.wf = wf | |
109 | wxFrame.__init__(self, NULL, -1, "hangman", wxDefaultPosition, wxSize(400,300)) | |
110 | self.wnd = HangmanWnd(self, -1) | |
111 | menu = wxMenu() | |
112 | menu.Append(1001, "New") | |
113 | menu.Append(1002, "End") | |
114 | menu.AppendSeparator() | |
115 | menu.Append(1003, "Reset") | |
116 | menu.AppendSeparator() | |
117 | menu.Append(1004, "Exit") | |
118 | menubar = wxMenuBar() | |
119 | menubar.Append(menu, "Game") | |
120 | menu = wxMenu() | |
121 | menu.Append(1010, "Internal", "Use internal dictionary", TRUE) | |
122 | menu.Append(1011, "ASCII File...") | |
123 | menubar.Append(menu, "Dictionary") | |
124 | self.SetMenuBar(menubar) | |
125 | self.CreateStatusBar(2) | |
126 | EVT_MENU(self, 1001, self.OnGameNew) | |
127 | EVT_MENU(self, 1002, self.OnGameEnd) | |
128 | EVT_MENU(self, 1003, self.OnGameReset) | |
129 | EVT_MENU(self, 1004, self.OnWindowClose) | |
130 | EVT_MENU(self, 1011, self.OnDictFile) | |
131 | EVT_CHAR(self.wnd, self.OnChar) | |
132 | self.OnGameReset() | |
35c1ca4b | 133 | def OnGameNew(self, event): |
0d236c34 | 134 | word = self.wf.Get() |
35c1ca4b | 135 | self.in_progress = 1 |
0d236c34 HH |
136 | self.SetStatusText("",0) |
137 | self.wnd.StartGame(word) | |
35c1ca4b HH |
138 | def OnGameEnd(self, event): |
139 | self.UpdateAverages(0) | |
35c1ca4b | 140 | self.in_progress = 0 |
0d236c34 HH |
141 | self.SetStatusText("",0) |
142 | self.wnd.EndGame() | |
143 | def OnGameReset(self, event=None): | |
144 | self.played = 0 | |
145 | self.won = 0 | |
146 | self.history = [] | |
147 | self.average = 0.0 | |
148 | self.OnGameNew(None) | |
149 | def OnDictFile(self, event): | |
150 | pass | |
35c1ca4b HH |
151 | def UpdateAverages(self, has_won): |
152 | if has_won: | |
153 | self.won = self.won + 1 | |
154 | self.played = self.played+1 | |
0d236c34 | 155 | self.history.append(self.wnd.misses) # ugly |
35c1ca4b HH |
156 | total = 0.0 |
157 | for m in self.history: | |
158 | total = total + m | |
159 | self.average = float(total/len(self.history)) | |
160 | def OnChar(self, event): | |
161 | if not self.in_progress: | |
162 | self.OnGameNew(None) | |
163 | return | |
164 | key = event.KeyCode(); | |
165 | if key >= ord('A') and key <= ord('Z'): | |
166 | key = key + ord('a') - ord('A') | |
167 | key = chr(key) | |
168 | if key < 'a' or key > 'z': | |
0d236c34 | 169 | event.Skip() |
35c1ca4b | 170 | return |
0d236c34 HH |
171 | res = self.wnd.HandleKey(key) |
172 | if res == 1: | |
173 | self.UpdateAverages(0) | |
35c1ca4b | 174 | self.SetStatusText("Too bad, you're dead!",0) |
35c1ca4b | 175 | self.in_progress = 0 |
0d236c34 HH |
176 | elif res == 2: |
177 | self.in_progress = 0 | |
178 | self.UpdateAverages(1) | |
35c1ca4b | 179 | self.SetStatusText("Congratulations!",0) |
0d236c34 HH |
180 | if self.played: |
181 | percent = (100.*self.won)/self.played | |
182 | else: | |
183 | percent = 0.0 | |
184 | self.SetStatusText("p %d, w %d (%g %%), av %g" % (self.played,self.won, percent, self.average),1) | |
185 | ||
35c1ca4b HH |
186 | def OnWindowClose(self, event): |
187 | self.Destroy() | |
188 | ||
189 | class MyApp(wxApp): | |
190 | def OnInit(self): | |
191 | print "Reading word list" | |
192 | wf = WordFetcher("/usr/share/games/hangman-words") | |
193 | frame = MyFrame(wf) | |
194 | self.SetTopWindow(frame) | |
195 | frame.Show(TRUE) | |
196 | return TRUE | |
197 | ||
198 | if __name__ == '__main__': | |
199 | app = MyApp(0) | |
200 | app.MainLoop() |