1
by fossilet
Initial import |
1 |
#!/usr/bin/env python
|
12
by fossilet
Better pygtk import method. |
2 |
# -*- coding: utf-8 -*-
|
24
by Fossilet
l10n support towards next release; hint table improvement. |
3 |
# pylint: disable-msg=r0201
|
12
by fossilet
Better pygtk import method. |
4 |
"""
|
5 |
4digits - A guess-the-number game, aka Bulls and Cows
|
|
40
by fossilet
1.0 release. |
6 |
Copyright (c) 2004-2011 Yongzhi Pan <http://fourdigits.sourceforge.net>
|
12
by fossilet
Better pygtk import method. |
7 |
|
8 |
4digits is a guess-the-number puzzle game. You are given eight times
|
|
9 |
to guess a four-digit number. One digit is marked A if its value and
|
|
10 |
position are both correct, and marked B if only its value is correct.
|
|
11 |
You win the game when you get 4A0B. Good luck!
|
|
12 |
||
13 |
4digits is free software; you can redistribute it and/or
|
|
14 |
modify it under the terms of the GNU General Public License as
|
|
15 |
published by the Free Software Foundation; either version 2 of
|
|
16 |
the License, or (at your option) any later version.
|
|
17 |
||
18 |
4digits is distributed in the hope that it will be useful,
|
|
19 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
22
by Fossilet
0.8 release. |
20 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
by fossilet
Better pygtk import method. |
21 |
GNU General Public License for more details.
|
22 |
||
23 |
You should have received a copy of the GNU General Public License
|
|
24 |
along with 4digits; if not, write to the Free Software Foundation,
|
|
22
by Fossilet
0.8 release. |
25 |
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
12
by fossilet
Better pygtk import method. |
26 |
"""
|
13
by fossilet
Updated doc. Improved glade file checking. (Kraus) |
27 |
|
24
by Fossilet
l10n support towards next release; hint table improvement. |
28 |
import os |
26
by Fossilet
Version 0.9 release. |
29 |
import cPickle |
25
by Fossilet
Removed i18n stuff since I do not know how to make it work. |
30 |
import random |
37
by fossilet
Version 1.0 pre-release. |
31 |
import pango |
12
by fossilet
Better pygtk import method. |
32 |
import sys |
25
by Fossilet
Removed i18n stuff since I do not know how to make it work. |
33 |
import time |
34 |
import webbrowser |
|
29
by usmarshal
Internationalization, MultiLanguage Support, ie. English and Chinese(Simple). |
35 |
|
36 |
try: |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
37 |
import pygtk |
38 |
pygtk.require('2.0') |
|
39 |
import gtk |
|
40 |
import gtk.glade |
|
29
by usmarshal
Internationalization, MultiLanguage Support, ie. English and Chinese(Simple). |
41 |
except ImportError: |
36
by fossilet
Changed logo; remove other game modes. Start over. |
42 |
print _('python-gtk2 is required to run 4digits.') |
43 |
print _('No python-gtk2 was found on your system.') |
|
22
by Fossilet
0.8 release. |
44 |
sys.exit(1) |
45 |
||
36
by fossilet
Changed logo; remove other game modes. Start over. |
46 |
__version__ = '1.0' |
37
by fossilet
Version 1.0 pre-release. |
47 |
__appdata_dir__ = os.path.join(os.path.expanduser('~'), '.4digits') |
26
by Fossilet
Version 0.9 release. |
48 |
__config_path__ = os.path.join(__appdata_dir__, 'prefs.pickle') |
36
by fossilet
Changed logo; remove other game modes. Start over. |
49 |
__prefs__ = { |
26
by Fossilet
Version 0.9 release. |
50 |
'show toolbar': True, |
51 |
'show hint table': False, |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
52 |
'auto fill hints': False |
26
by Fossilet
Version 0.9 release. |
53 |
}
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
54 |
|
55 |
# The first is the current directory, so you do not have to install
|
|
22
by Fossilet
0.8 release. |
56 |
# 4digits to play it. The second is the installation directory.
|
26
by Fossilet
Version 0.9 release. |
57 |
__gladefiles__ = [os.path.join(os.path.dirname(__file__), '4digits.glade'), |
19
by Fossilet
Doc, script and code cleanup. |
58 |
os.path.normpath(os.path.join( |
13
by fossilet
Updated doc. Improved glade file checking. (Kraus) |
59 |
os.path.dirname(__file__), '../share/4digits/4digits.glade'))] |
37
by fossilet
Version 1.0 pre-release. |
60 |
__helpfiles__ = [os.path.join(os.path.dirname(__file__), 'doc', 'index.html'), |
17
by Fossilet
Updated doc, and improved auto filling. |
61 |
os.path.normpath(os.path.join( |
62 |
os.path.dirname(__file__), '../share/doc/4digits/index.html'))] |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
63 |
__score_filename__ = os.path.join(__appdata_dir__, '4digits.4digits.scores') |
64 |
||
26
by Fossilet
Version 0.9 release. |
65 |
# For future gettext support. I cannot figure out i18n now.
|
66 |
# I wish someone could help me with it.
|
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
67 |
try: |
68 |
_() |
|
69 |
except NameError: |
|
70 |
def _(arg): |
|
71 |
"""Mark translatable strings."""
|
|
72 |
return arg |
|
73 |
||
74 |
def load_glade(dialog = None): |
|
75 |
"""Try to load dialog from the different possible glade files."""
|
|
26
by Fossilet
Version 0.9 release. |
76 |
for gladefile in __gladefiles__: |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
77 |
try: |
36
by fossilet
Changed logo; remove other game modes. Start over. |
78 |
return gtk.glade.XML(gladefile, dialog) |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
79 |
except RuntimeError: |
21
by Fossilet
Added gnome stock icon for scores, and an XPM logo. |
80 |
continue # Just ignore the error, the next file will be tested |
81 |
# Still here
|
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
82 |
print "Gladefile not found! Checked paths were:" |
26
by Fossilet
Version 0.9 release. |
83 |
print __gladefiles__ |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
84 |
sys.exit(2) |
36
by fossilet
Changed logo; remove other game modes. Start over. |
85 |
|
26
by Fossilet
Version 0.9 release. |
86 |
|
87 |
class MainWindow(object): |
|
88 |
"""The main game window."""
|
|
1
by fossilet
Initial import |
89 |
def __init__(self): |
26
by Fossilet
Version 0.9 release. |
90 |
"""GUI initialization."""
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
91 |
self.widget_tree = load_glade() |
92 |
self.toolbar = self.widget_tree.get_widget('toolbar') |
|
93 |
self.view_toolbar = self.widget_tree.get_widget('view_toolbar') |
|
26
by Fossilet
Version 0.9 release. |
94 |
self.hint_table = self.widget_tree.get_widget('hint_table') |
95 |
self.hint_hseparator = self.widget_tree.get_widget( |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
96 |
'hint_hseparator') |
26
by Fossilet
Version 0.9 release. |
97 |
self.view_hint_table = self.widget_tree.get_widget( |
36
by fossilet
Changed logo; remove other game modes. Start over. |
98 |
'view_hint_table') |
26
by Fossilet
Version 0.9 release. |
99 |
self.auto_fill_hints = self.widget_tree.get_widget( |
36
by fossilet
Changed logo; remove other game modes. Start over. |
100 |
'view_auto_fill_hints') |
37
by fossilet
Version 1.0 pre-release. |
101 |
|
102 |
# Input box
|
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
103 |
self.entry = self.widget_tree.get_widget('entry') |
1
by fossilet
Initial import |
104 |
self.entry.grab_focus() |
37
by fossilet
Version 1.0 pre-release. |
105 |
fontsize = self.entry.get_pango_context().\ |
106 |
get_font_description().get_size()/pango.SCALE |
|
107 |
self.entry.modify_font(pango.FontDescription(str(int(fontsize*3)))) |
|
108 |
||
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
109 |
self.ok_button = self.widget_tree.get_widget('ok_button') |
1
by fossilet
Initial import |
110 |
for widget in ('g0', 'g1', 'g2', 'g3', 'g4', 'g5', 'g6', 'g7', |
36
by fossilet
Changed logo; remove other game modes. Start over. |
111 |
'r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7'): |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
112 |
setattr(self, widget, self.widget_tree.get_widget(widget)) |
113 |
self.info_label = self.widget_tree.get_widget('info_label') |
|
114 |
self.time_label = self.widget_tree.get_widget('time_label') |
|
115 |
self.score_view = self.widget_tree.get_widget('score_view') |
|
26
by Fossilet
Version 0.9 release. |
116 |
|
117 |
self.cb_hint = [] # container for check boxes in the hint table |
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
118 |
self.label_hint = [] |
15
by Fossilet
Improved hint table. |
119 |
self.build_hint_table() |
26
by Fossilet
Version 0.9 release. |
120 |
|
121 |
# parse preferences
|
|
122 |
self.read_preferences_file() |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
123 |
if __prefs__['show toolbar']: |
26
by Fossilet
Version 0.9 release. |
124 |
self.toolbar.show() |
125 |
self.view_toolbar.set_active(True) |
|
126 |
else: |
|
127 |
self.toolbar.hide() |
|
128 |
self.view_toolbar.set_active(False) |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
129 |
if __prefs__['show hint table']: |
26
by Fossilet
Version 0.9 release. |
130 |
self.hint_table.show_all() |
131 |
self.hint_hseparator.show() |
|
132 |
self.view_hint_table.set_active(True) |
|
133 |
else: |
|
134 |
self.hint_table.hide_all() |
|
135 |
self.hint_hseparator.hide() |
|
136 |
self.view_hint_table.set_active(False) |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
137 |
if __prefs__['auto fill hints']: |
26
by Fossilet
Version 0.9 release. |
138 |
self.auto_fill_hints.set_active(True) |
139 |
else: |
|
140 |
self.auto_fill_hints.set_active(False) |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
141 |
|
26
by Fossilet
Version 0.9 release. |
142 |
# connect signals and callbacks
|
143 |
dic = {'on_main_window_destroy': self.terminate_program, |
|
144 |
'on_quit_activate': self.terminate_program, |
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
145 |
'on_ok_clicked': self.on_entry_activate, |
146 |
'on_new_game_activate': self.on_new_game_activate, |
|
1
by fossilet
Initial import |
147 |
'on_view_toolbar_toggled': self.on_view_toolbar_toggled, |
26
by Fossilet
Version 0.9 release. |
148 |
'on_view_hint_table_toggled'
|
149 |
: self.on_view_hint_table_toggled, |
|
150 |
'on_view_auto_fill_hints_toggled'
|
|
151 |
: self.on_view_auto_fill_hints_toggled, |
|
1
by fossilet
Initial import |
152 |
'on_entry_activate': self.on_entry_activate, |
153 |
'on_entry_changed': self.on_entry_changed, |
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
154 |
'on_help_activate' : self.on_help_activate, |
155 |
'on_about_activate' : self.on_about_activate, |
|
156 |
'on_score_activate': self.on_score_activate} |
|
157 |
self.widget_tree.signal_autoconnect(dic) |
|
1
by fossilet
Initial import |
158 |
# new game initialization
|
19
by Fossilet
Doc, script and code cleanup. |
159 |
self.game = NewRound() |
1
by fossilet
Initial import |
160 |
|
26
by Fossilet
Version 0.9 release. |
161 |
def read_preferences_file(self): |
162 |
"""Read preferences data from disk.
|
|
163 |
Copied from Comix.
|
|
164 |
"""
|
|
165 |
if os.path.isfile(__config_path__): |
|
166 |
try: |
|
167 |
config = open(__config_path__) |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
168 |
old___prefs__ = cPickle.load(config) |
26
by Fossilet
Version 0.9 release. |
169 |
config.close() |
170 |
except Exception: |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
171 |
print 'Corrupted preferences file \ |
172 |
"%s", deleting...' % __config_path__ |
|
26
by Fossilet
Version 0.9 release. |
173 |
os.remove(__config_path__) |
174 |
else: |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
175 |
for key in old___prefs__: |
176 |
if key in __prefs__: |
|
177 |
__prefs__[key] = old___prefs__[key] |
|
26
by Fossilet
Version 0.9 release. |
178 |
|
179 |
def write_preferences_file(self): |
|
180 |
"""Write preference data to disk.
|
|
181 |
Copied from Comix.
|
|
182 |
"""
|
|
183 |
config = open(__config_path__, 'w') |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
184 |
cPickle.dump(__prefs__, config, cPickle.HIGHEST_PROTOCOL) |
26
by Fossilet
Version 0.9 release. |
185 |
config.close() |
186 |
||
15
by Fossilet
Improved hint table. |
187 |
def build_hint_table(self): |
26
by Fossilet
Version 0.9 release. |
188 |
"""Create the controls for the hint table."""
|
189 |
hint_table = self.widget_tree.get_widget('hint_table') |
|
2
by fossilet
Added high score and hint table |
190 |
for name in (0, 40): |
15
by Fossilet
Improved hint table. |
191 |
table = gtk.Table(rows=11, columns=6) |
26
by Fossilet
Version 0.9 release. |
192 |
hint_table.pack_start(table) |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
193 |
|
21
by Fossilet
Added gnome stock icon for scores, and an XPM logo. |
194 |
# Create row labels
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
195 |
for row in range(0, 10): |
196 |
label = gtk.CheckButton(str(row)) |
|
197 |
table.attach(label, 0, 1, row+1, row+2) |
|
198 |
label.connect('toggled', self.change_row, row+name) |
|
15
by Fossilet
Improved hint table. |
199 |
self.label_hint.append(label) |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
200 |
|
201 |
for col in range(1, 5): |
|
21
by Fossilet
Added gnome stock icon for scores, and an XPM logo. |
202 |
# Create column labels
|
37
by fossilet
Version 1.0 pre-release. |
203 |
#label = gtk.Label(str(col))
|
204 |
#table.attach(label, col, col+1, 0, 1)
|
|
21
by Fossilet
Added gnome stock icon for scores, and an XPM logo. |
205 |
# Create Checkboxes
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
206 |
for row in range(0, 10): |
15
by Fossilet
Improved hint table. |
207 |
checkbutton = gtk.CheckButton() |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
208 |
table.attach(checkbutton, col, col+1, row+1, row+2) |
15
by Fossilet
Improved hint table. |
209 |
self.cb_hint.append(checkbutton) |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
210 |
|
21
by Fossilet
Added gnome stock icon for scores, and an XPM logo. |
211 |
if name == 0: # First table |
26
by Fossilet
Version 0.9 release. |
212 |
hint_table.pack_start(gtk.VSeparator()) |
15
by Fossilet
Improved hint table. |
213 |
self.init_hint_table() |
2
by fossilet
Added high score and hint table |
214 |
|
215 |
def change_row(self, widget, row): |
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
216 |
"""Toggle a rows state."""
|
15
by Fossilet
Improved hint table. |
217 |
enable = widget.get_active() |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
218 |
for col in range(0, 4): |
219 |
self.cb_hint[10 * col + row].set_sensitive(enable) |
|
15
by Fossilet
Improved hint table. |
220 |
|
221 |
def init_hint_table(self): |
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
222 |
"""Reset all controls in the hinttable to their default state."""
|
15
by Fossilet
Improved hint table. |
223 |
for i in range(0, 40): |
224 |
self.cb_hint[i].set_active(True) |
|
225 |
self.cb_hint[i+40].set_active(False) |
|
226 |
self.cb_hint[i+40].set_sensitive(False) |
|
227 |
self.cb_hint[0].set_active(False) |
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
228 |
for row in range(0, 10): |
229 |
self.label_hint[row].set_active(True) |
|
230 |
self.label_hint[row+10].set_active(False) |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
231 |
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
232 |
# 1 2 3 4 1 2 3 4
|
233 |
# 0/0 00 10 20 30 0/10 40 50 60 70
|
|
234 |
# 1/1 01 11 21 31 1/11 41 51 61 71
|
|
235 |
# 2/2 02 12 22 32 2/12 42 52 62 72
|
|
236 |
# ...
|
|
22
by Fossilet
0.8 release. |
237 |
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
238 |
def get_checkbox(self, row, col, tablenr=0): |
26
by Fossilet
Version 0.9 release. |
239 |
"""Get the checkbox at the specified position."""
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
240 |
return self.cb_hint[tablenr * 40 + col * 10 + row] |
2
by fossilet
Added high score and hint table |
241 |
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
242 |
def get_label(self, row, tablenr=0): |
26
by Fossilet
Version 0.9 release. |
243 |
"""Get the label at the specified position."""
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
244 |
return self.label_hint[tablenr*10 + row] |
24
by Fossilet
l10n support towards next release; hint table improvement. |
245 |
|
1
by fossilet
Initial import |
246 |
def on_entry_activate(self, widget): |
26
by Fossilet
Version 0.9 release. |
247 |
"""when input is accepted."""
|
248 |
bulls, cows = 0, 0 |
|
1
by fossilet
Initial import |
249 |
number = '' |
250 |
# check input
|
|
251 |
if self.game.guess < 8: |
|
252 |
number = self.entry.get_text() |
|
253 |
if number == '': |
|
26
by Fossilet
Version 0.9 release. |
254 |
self.process_error(_('Must input something.')) |
1
by fossilet
Initial import |
255 |
return False |
256 |
elif number[0] == '0': |
|
26
by Fossilet
Version 0.9 release. |
257 |
self.process_error(_('First digit cannot be zero.')) |
1
by fossilet
Initial import |
258 |
return False |
259 |
try: |
|
260 |
number = repr(int(number)) |
|
261 |
except ValueError: |
|
26
by Fossilet
Version 0.9 release. |
262 |
self.process_error(_('Must input a number.')) |
1
by fossilet
Initial import |
263 |
return False |
36
by fossilet
Changed logo; remove other game modes. Start over. |
264 |
if len(number) < 4: |
265 |
self.process_error(_('Must input four digits.')) |
|
1
by fossilet
Initial import |
266 |
return False |
36
by fossilet
Changed logo; remove other game modes. Start over. |
267 |
elif len(set(number)) < 4: |
268 |
self.process_error(_('Four digits must be unique.')) |
|
1
by fossilet
Initial import |
269 |
return False |
270 |
elif number in self.game.guesses: |
|
26
by Fossilet
Version 0.9 release. |
271 |
self.process_error(_("You've already guessed it.")) |
1
by fossilet
Initial import |
272 |
return False |
273 |
self.game.guesses.append(number) |
|
274 |
# process input
|
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
275 |
for i in xrange(4): |
276 |
for j in xrange(4): |
|
1
by fossilet
Initial import |
277 |
if self.game.answer[i] == int(number[j]): |
278 |
if i == j: |
|
26
by Fossilet
Version 0.9 release. |
279 |
bulls += 1 |
1
by fossilet
Initial import |
280 |
else: |
26
by Fossilet
Version 0.9 release. |
281 |
cows += 1 |
1
by fossilet
Initial import |
282 |
guess_label = getattr(self, 'g' + repr(self.game.guess)) |
283 |
result_label = getattr(self, 'r' + repr(self.game.guess)) |
|
284 |
guess_label.set_text(number) |
|
26
by Fossilet
Version 0.9 release. |
285 |
result_label.set_text('%dA%dB' % (bulls, cows)) |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
286 |
|
26
by Fossilet
Version 0.9 release. |
287 |
if self.auto_fill_hints.get_active(): |
288 |
self.fill_hints(number, bulls, cows) |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
289 |
|
1
by fossilet
Initial import |
290 |
# win
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
291 |
if bulls == 4: |
1
by fossilet
Initial import |
292 |
self.info_label.set_text(_('You win! :)')) |
293 |
self.get_time_taken_till_now() |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
294 |
self.time_label.set_text(_('Used %.1f s.') % |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
295 |
self.game.time_taken) |
296 |
self.ok_button.set_sensitive(False) |
|
1
by fossilet
Initial import |
297 |
self.entry.set_sensitive(False) |
298 |
if self.is_high_score(self.game.time_taken): |
|
3
by fossilet
Minor tweaking at GUI |
299 |
new_score_rank = self.write_score(self.game.time_taken) |
300 |
self.show_score(new_score_rank) |
|
1
by fossilet
Initial import |
301 |
# lose
|
302 |
elif self.game.guess == 7: |
|
303 |
answer = '' |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
304 |
for i in xrange(4): |
1
by fossilet
Initial import |
305 |
answer += repr(self.game.answer[i]) |
36
by fossilet
Changed logo; remove other game modes. Start over. |
306 |
self.info_label.set_text(_('Haha, you lose. It is %s.') % |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
307 |
answer) |
1
by fossilet
Initial import |
308 |
self.get_time_taken_till_now() |
36
by fossilet
Changed logo; remove other game modes. Start over. |
309 |
self.time_label.set_text(_('Wasted %.1f s.') % |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
310 |
self.game.time_taken) |
311 |
self.ok_button.set_sensitive(False) |
|
1
by fossilet
Initial import |
312 |
self.entry.set_sensitive(False) |
313 |
self.game.guess += 1 |
|
314 |
self.entry.grab_focus() |
|
315 |
||
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
316 |
def clear_row(self, row): |
26
by Fossilet
Version 0.9 release. |
317 |
"""Clear a complete row."""
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
318 |
self.get_label(row, 0).set_active(False) |
319 |
for col in range(0, 4): |
|
320 |
self.get_checkbox(row, col, 0).set_active(False) |
|
321 |
self.get_checkbox(row, col, 1).set_active(False) |
|
322 |
||
26
by Fossilet
Version 0.9 release. |
323 |
def fill_hints(self, number, bulls, cows): |
324 |
"""Auto filling some obvious cases in the hint table."""
|
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
325 |
number = [int(x) for x in number] |
26
by Fossilet
Version 0.9 release. |
326 |
if bulls == 0 and cows == 0: |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
327 |
for digit in number: |
328 |
self.clear_row(digit) |
|
329 |
return
|
|
330 |
||
26
by Fossilet
Version 0.9 release. |
331 |
if bulls+cows == 4: |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
332 |
for digit in range(0, 10): |
333 |
if digit in number: |
|
334 |
self.get_label(digit, 0).set_active(True) |
|
335 |
self.get_label(digit, 1).set_active(True) |
|
336 |
else: |
|
337 |
self.clear_row(digit) |
|
338 |
||
26
by Fossilet
Version 0.9 release. |
339 |
if bulls == 0: # Only cows |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
340 |
for digit_pos in range(0, 4): |
36
by fossilet
Changed logo; remove other game modes. Start over. |
341 |
self.get_checkbox(number[digit_pos], digit_pos, |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
342 |
0).set_active(False) |
36
by fossilet
Changed logo; remove other game modes. Start over. |
343 |
self.get_checkbox(number[digit_pos], digit_pos, |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
344 |
1).set_active(False) |
345 |
||
26
by Fossilet
Version 0.9 release. |
346 |
if cows == 0: # Only bulls |
24
by Fossilet
l10n support towards next release; hint table improvement. |
347 |
# Only digits which are either in the right place or completely wrong
|
23
by Fossilet
Final 0.8 release. |
348 |
for digit_pos in range(0, 4): |
349 |
for pos2 in range(0, 4): |
|
350 |
if pos2 == digit_pos: |
|
351 |
continue
|
|
24
by Fossilet
l10n support towards next release; hint table improvement. |
352 |
# uncheck impossible boxes in first column
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
353 |
self.get_checkbox(number[digit_pos], pos2, |
23
by Fossilet
Final 0.8 release. |
354 |
0).set_active(False) |
355 |
||
1
by fossilet
Initial import |
356 |
def on_entry_changed(self, widget): |
26
by Fossilet
Version 0.9 release. |
357 |
"""Start timer as soon as the user enters the first digit."""
|
1
by fossilet
Initial import |
358 |
self.info_label.set_text('') |
26
by Fossilet
Version 0.9 release. |
359 |
if self.game.on_entry_cb_first_called == True: |
1
by fossilet
Initial import |
360 |
self.time_label.set_text(_('Timer started...')) |
361 |
self.game.time_start = time.time() |
|
26
by Fossilet
Version 0.9 release. |
362 |
self.game.on_entry_cb_first_called = False |
36
by fossilet
Changed logo; remove other game modes. Start over. |
363 |
|
1
by fossilet
Initial import |
364 |
def on_view_toolbar_toggled(self, widget): |
26
by Fossilet
Version 0.9 release. |
365 |
"""Toggle toolbar visibility."""
|
366 |
if self.toolbar.get_property('visible'): |
|
367 |
self.toolbar.hide() |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
368 |
__prefs__['show toolbar'] = False |
26
by Fossilet
Version 0.9 release. |
369 |
else: |
1
by fossilet
Initial import |
370 |
self.toolbar.show() |
36
by fossilet
Changed logo; remove other game modes. Start over. |
371 |
__prefs__['show toolbar'] = True |
1
by fossilet
Initial import |
372 |
|
2
by fossilet
Added high score and hint table |
373 |
def on_view_hint_table_toggled(self, widget): |
26
by Fossilet
Version 0.9 release. |
374 |
"""Toggle hint table visibility."""
|
375 |
if self.hint_table.get_property('visible'): |
|
376 |
self.hint_table.hide_all() |
|
377 |
self.hint_hseparator.hide() |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
378 |
__prefs__['show hint table'] = False |
26
by Fossilet
Version 0.9 release. |
379 |
else: |
2
by fossilet
Added high score and hint table |
380 |
self.hint_table.show_all() |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
381 |
self.hint_hseparator.show() |
36
by fossilet
Changed logo; remove other game modes. Start over. |
382 |
__prefs__['show hint table'] = True |
383 |
||
26
by Fossilet
Version 0.9 release. |
384 |
def on_view_auto_fill_hints_toggled(self, widget): |
385 |
"""Toggle auto filling of hint table."""
|
|
386 |
if self.auto_fill_hints.get_active(): |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
387 |
__prefs__['auto fill hints'] = True |
26
by Fossilet
Version 0.9 release. |
388 |
else: |
36
by fossilet
Changed logo; remove other game modes. Start over. |
389 |
__prefs__['auto fill hints'] = False |
26
by Fossilet
Version 0.9 release. |
390 |
|
25
by Fossilet
Removed i18n stuff since I do not know how to make it work. |
391 |
@classmethod
|
392 |
def on_help_activate(cls, widget): |
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
393 |
"""Show help."""
|
26
by Fossilet
Version 0.9 release. |
394 |
for helpfile in __helpfiles__: |
17
by Fossilet
Updated doc, and improved auto filling. |
395 |
try: |
396 |
file(helpfile) |
|
397 |
except IOError: |
|
398 |
continue
|
|
22
by Fossilet
0.8 release. |
399 |
webbrowser.open(helpfile) |
1
by fossilet
Initial import |
400 |
|
25
by Fossilet
Removed i18n stuff since I do not know how to make it work. |
401 |
@classmethod
|
402 |
def on_about_activate(cls, widget): |
|
26
by Fossilet
Version 0.9 release. |
403 |
"""Show about dialog."""
|
19
by Fossilet
Doc, script and code cleanup. |
404 |
about = AboutDialog().about_dialog |
1
by fossilet
Initial import |
405 |
about.run() |
406 |
about.destroy() |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
407 |
|
25
by Fossilet
Removed i18n stuff since I do not know how to make it work. |
408 |
@classmethod
|
409 |
def on_score_activate(cls, new_score_rank): |
|
26
by Fossilet
Version 0.9 release. |
410 |
"""Show high scores."""
|
21
by Fossilet
Added gnome stock icon for scores, and an XPM logo. |
411 |
score_dialog = ScoreDialog() |
412 |
dlg = score_dialog.score_dialog |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
413 |
score_view = score_dialog.score_view |
414 |
sv_selection = score_view.get_selection() |
|
415 |
sv_selection.set_mode(gtk.SELECTION_NONE) |
|
416 |
column = gtk.TreeViewColumn( |
|
417 |
_('Name'), gtk.CellRendererText(), text = 0) |
|
418 |
score_view.append_column(column) |
|
419 |
column = gtk.TreeViewColumn( |
|
420 |
_('Score'), gtk.CellRendererText(), text = 1) |
|
421 |
score_view.append_column(column) |
|
422 |
column = gtk.TreeViewColumn( |
|
423 |
_('Date'), gtk.CellRendererText(), text = 2) |
|
424 |
score_view.append_column(column) |
|
425 |
dlg.scoreList = gtk.ListStore(str, str, str) |
|
426 |
score_view.set_model(dlg.scoreList) |
|
427 |
||
428 |
try: |
|
429 |
scores = [line.split(' ', 6) |
|
430 |
for line in file(__score_filename__, 'r')] |
|
431 |
except IOError: |
|
432 |
scores = [] |
|
433 |
||
434 |
for line in scores: |
|
435 |
score_tup = line[0], line[1], ' '.join(line[2:]).rstrip('\n') |
|
436 |
dlg.scoreList.append(score_tup) |
|
437 |
# high light the current high score entry
|
|
438 |
try: |
|
439 |
sv_selection.set_mode(gtk.SELECTION_SINGLE) |
|
440 |
sv_selection.select_path(new_score_rank) |
|
441 |
except TypeError: |
|
442 |
sv_selection.set_mode(gtk.SELECTION_NONE) |
|
443 |
||
1
by fossilet
Initial import |
444 |
dlg.run() |
445 |
dlg.destroy() |
|
446 |
||
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
447 |
def on_new_game_activate(self, widget): |
26
by Fossilet
Version 0.9 release. |
448 |
"""New game initialization."""
|
19
by Fossilet
Doc, script and code cleanup. |
449 |
self.game = NewRound() |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
450 |
self.ok_button.set_sensitive(True) |
1
by fossilet
Initial import |
451 |
self.entry.set_sensitive(True) |
452 |
self.entry.grab_focus() |
|
453 |
# won't start the timer when you just start a new game
|
|
26
by Fossilet
Version 0.9 release. |
454 |
self.game.on_entry_cb_first_called = False |
1
by fossilet
Initial import |
455 |
self.entry.set_text('') |
26
by Fossilet
Version 0.9 release. |
456 |
self.game.on_entry_cb_first_called = True |
1
by fossilet
Initial import |
457 |
self.info_label.set_text(_('Ready')) |
458 |
self.time_label.set_text('') |
|
459 |
||
460 |
for i in xrange(8): |
|
461 |
getattr(self, 'g' + repr(i)).set_text('') |
|
462 |
getattr(self, 'r' + repr(i)).set_text('') |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
463 |
|
15
by Fossilet
Improved hint table. |
464 |
self.init_hint_table() |
2
by fossilet
Added high score and hint table |
465 |
|
26
by Fossilet
Version 0.9 release. |
466 |
def process_error(self, msg): |
467 |
"""Show error message in statusbar."""
|
|
1
by fossilet
Initial import |
468 |
self.info_label.set_text(msg) |
469 |
self.entry.grab_focus() |
|
470 |
||
471 |
def get_time_taken_till_now(self): |
|
26
by Fossilet
Version 0.9 release. |
472 |
"""Get time since start of the game."""
|
1
by fossilet
Initial import |
473 |
self.game.time_end = time.time() |
474 |
self.game.time_taken = self.game.time_end - self.game.time_start |
|
475 |
self.game.time_taken = round(self.game.time_taken, 1) |
|
476 |
||
25
by Fossilet
Removed i18n stuff since I do not know how to make it work. |
477 |
@classmethod
|
478 |
def is_high_score(cls, time_taken): |
|
26
by Fossilet
Version 0.9 release. |
479 |
"""Is this time a highscore."""
|
15
by Fossilet
Improved hint table. |
480 |
try: |
36
by fossilet
Changed logo; remove other game modes. Start over. |
481 |
scores = [line.split(' ', 6) |
482 |
for line in file(__score_filename__, 'r')] |
|
15
by Fossilet
Improved hint table. |
483 |
except IOError: |
21
by Fossilet
Added gnome stock icon for scores, and an XPM logo. |
484 |
return True # List does not exist yet |
2
by fossilet
Added high score and hint table |
485 |
if len(scores) < 10: |
486 |
return True |
|
487 |
scores = sorted(scores, key = lambda x: float(x[1][:-1])) |
|
488 |
if time_taken < float(scores[-1][1][:-1]): |
|
1
by fossilet
Initial import |
489 |
return True |
490 |
else: |
|
491 |
return False |
|
492 |
||
25
by Fossilet
Removed i18n stuff since I do not know how to make it work. |
493 |
@classmethod
|
494 |
def write_score(cls, time_taken): |
|
26
by Fossilet
Version 0.9 release. |
495 |
"""Write highscore file."""
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
496 |
date = time.strftime("%a %b %d %H:%M:%S %Y") |
12
by fossilet
Better pygtk import method. |
497 |
new_score = "%s %ss %s\n" % ( |
19
by Fossilet
Doc, script and code cleanup. |
498 |
os.getenv('USERNAME'), time_taken, date) |
15
by Fossilet
Improved hint table. |
499 |
try: |
36
by fossilet
Changed logo; remove other game modes. Start over. |
500 |
saved_scores = open(__score_filename__, 'r').readlines() |
15
by Fossilet
Improved hint table. |
501 |
except IOError: |
36
by fossilet
Changed logo; remove other game modes. Start over. |
502 |
saved_scores = [] |
2
by fossilet
Added high score and hint table |
503 |
saved_scores.append(new_score) |
504 |
scores = [line.split(' ', 6) for line in saved_scores] |
|
505 |
scores = sorted(scores, key = lambda x: float(x[1][:-1])) |
|
506 |
scores = scores[:10] |
|
3
by fossilet
Minor tweaking at GUI |
507 |
|
508 |
# find the index of the new score
|
|
509 |
new_score = new_score.split(' ', 6) |
|
510 |
new_score_rank = scores.index(new_score) |
|
15
by Fossilet
Improved hint table. |
511 |
try: |
36
by fossilet
Changed logo; remove other game modes. Start over. |
512 |
scorefile = open(__score_filename__, 'w') |
15
by Fossilet
Improved hint table. |
513 |
except IOError: |
514 |
# Most likely the directory does not exist
|
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
515 |
new_dir = os.path.dirname(__score_filename__) |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
516 |
os.mkdir(new_dir) |
36
by fossilet
Changed logo; remove other game modes. Start over. |
517 |
scorefile = open(__score_filename__, 'w') # Try again |
2
by fossilet
Added high score and hint table |
518 |
for score in scores: |
26
by Fossilet
Version 0.9 release. |
519 |
scorefile.write(' '.join(score)) |
520 |
scorefile.close() |
|
3
by fossilet
Minor tweaking at GUI |
521 |
return new_score_rank |
1
by fossilet
Initial import |
522 |
|
3
by fossilet
Minor tweaking at GUI |
523 |
def show_score(self, new_score_rank): |
26
by Fossilet
Version 0.9 release. |
524 |
"""Show highscore dialog."""
|
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
525 |
self.on_score_activate(new_score_rank) |
36
by fossilet
Changed logo; remove other game modes. Start over. |
526 |
|
26
by Fossilet
Version 0.9 release. |
527 |
def terminate_program(self, widget): |
528 |
"""Run clean-up tasks and exit.
|
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
529 |
Copied from comix.
|
26
by Fossilet
Version 0.9 release. |
530 |
"""
|
531 |
self.write_preferences_file() |
|
532 |
gtk.main_quit() |
|
533 |
||
36
by fossilet
Changed logo; remove other game modes. Start over. |
534 |
|
25
by Fossilet
Removed i18n stuff since I do not know how to make it work. |
535 |
class AboutDialog(object): |
26
by Fossilet
Version 0.9 release. |
536 |
"""The about dialog."""
|
1
by fossilet
Initial import |
537 |
def __init__(self): |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
538 |
self.widget_tree = load_glade('about_dialog') |
539 |
self.about_dialog = self.widget_tree.get_widget("about_dialog") |
|
12
by fossilet
Better pygtk import method. |
540 |
gtk.about_dialog_set_url_hook( |
541 |
lambda about_dialog, url: webbrowser.open(url)) |
|
22
by Fossilet
0.8 release. |
542 |
self.about_dialog.set_website( |
543 |
'http://fourdigits.sourceforge.net') |
|
544 |
self.about_dialog.set_website_label( |
|
545 |
'http://fourdigits.sourceforge.net') |
|
1
by fossilet
Initial import |
546 |
|
26
by Fossilet
Version 0.9 release. |
547 |
|
25
by Fossilet
Removed i18n stuff since I do not know how to make it work. |
548 |
class ScoreDialog(object): |
26
by Fossilet
Version 0.9 release. |
549 |
"""The score dialog."""
|
1
by fossilet
Initial import |
550 |
def __init__(self): |
16
by Fossilet
Auto filling of hint table and code cleanup by Hermann. |
551 |
self.widget_tree = load_glade('score_dialog') |
552 |
self.score_dialog = self.widget_tree.get_widget('score_dialog') |
|
553 |
self.score_view = self.widget_tree.get_widget('score_view') |
|
1
by fossilet
Initial import |
554 |
|
26
by Fossilet
Version 0.9 release. |
555 |
|
25
by Fossilet
Removed i18n stuff since I do not know how to make it work. |
556 |
class NewRound(object): |
26
by Fossilet
Version 0.9 release. |
557 |
"""Contains data in one round of the game."""
|
1
by fossilet
Initial import |
558 |
def __init__(self): |
559 |
while True: |
|
36
by fossilet
Changed logo; remove other game modes. Start over. |
560 |
self.answer = random.sample(range(10), 4) |
26
by Fossilet
Version 0.9 release. |
561 |
if self.answer[0] != 0: # first digit cannot be zero |
1
by fossilet
Initial import |
562 |
break
|
40
by fossilet
1.0 release. |
563 |
#print self.answer
|
17
by Fossilet
Updated doc, and improved auto filling. |
564 |
if self.answer == [4, 6, 1, 9]: |
26
by Fossilet
Version 0.9 release. |
565 |
gtk.MessageDialog(message_format |
566 |
='4619: You are the luckiest guy on the planet!').show() |
|
1
by fossilet
Initial import |
567 |
self.guess = 0 |
568 |
self.guesses = [] |
|
569 |
self.time_start = 0 |
|
570 |
self.time_end = 0 |
|
571 |
self.time_taken = 0 |
|
26
by Fossilet
Version 0.9 release. |
572 |
self.on_entry_cb_first_called = True |
1
by fossilet
Initial import |
573 |
|
574 |
if __name__ == "__main__": |
|
26
by Fossilet
Version 0.9 release. |
575 |
MainWindow() |
1
by fossilet
Initial import |
576 |
gtk.main() |