Back to index

gcompris  8.2.2
guessnumber.py
Go to the documentation of this file.
00001 #  gcompris - guessnumber
00002 #
00003 # Copyright (C) 2005 Bruno Coudoin / Clement Coudoin
00004 #
00005 #   This program is free software; you can redistribute it and/or modify
00006 #   it under the terms of the GNU General Public License as published by
00007 #   the Free Software Foundation; either version 2 of the License, or
00008 #   (at your option) any later version.
00009 #
00010 #   This program is distributed in the hope that it will be useful,
00011 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 #   GNU General Public License for more details.
00014 #
00015 #   You should have received a copy of the GNU General Public License
00016 #   along with this program; if not, write to the Free Software
00017 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 #
00019 
00020 import gnomecanvas
00021 import gcompris
00022 import gcompris.utils
00023 import gcompris.skin
00024 import gcompris.admin
00025 import gcompris.bonus
00026 import gtk
00027 import gtk.gdk
00028 import random
00029 import pango
00030 
00031 from gcompris import gcompris_gettext as _
00032 
00033 class Gcompris_guessnumber:
00034   """Tux hide a number, you must guess it"""
00035 
00036 
00037   def __init__(self, gcomprisBoard):
00038 
00039     self.gcomprisBoard = gcomprisBoard
00040 
00041     self.gcomprisBoard.disable_im_context = True
00042 
00043     # A text canvas item use to indicate it's over or lower
00044     self.indicator = None
00045     self.indicator_s = None
00046 
00047     # The text entry for the number
00048     self.entry = None
00049 
00050     # The min and max value that must be found
00051     self.min = -1
00052     self.max = -1
00053 
00054     # These are used to let us restart only after the bonus is displayed.
00055     # When the bonus is displayed, it call us first with pause(1) and then with pause(0)
00056     self.board_paused  = 0
00057     self.gamewon       = 0
00058 
00059     # Manage the helico move
00060     self.move_stepnum = 0
00061     self.x = self.y = self.x_old = self.y_old = -1
00062     self.moving = False
00063     self.action_start = 0
00064     self.anim = None
00065     self.velocity = []
00066     self.sw = self.sh = 1
00067     self.move_tick = 30
00068     self.num_moveticks = 20
00069     self.rotation = 0
00070     self.movestep_timer = 0
00071 
00072     self.orig_x = 0
00073     self.orig_y = gcompris.BOARD_HEIGHT/2
00074     self.target_x = 700
00075     self.target_y = self.orig_y
00076 
00077     self.helico_width = -1
00078     self.helico_height = -1
00079 
00080   def start(self):
00081 
00082     self.gcomprisBoard.level=1
00083     self.gcomprisBoard.maxlevel=4
00084     self.gcomprisBoard.sublevel=1
00085     self.gcomprisBoard.number_of_sublevel=1
00086 
00087     gcompris.bar_set(gcompris.BAR_OK|gcompris.BAR_LEVEL)
00088 
00089     gcompris.bar_set_level(self.gcomprisBoard)
00090 
00091     gcompris.set_background(self.gcomprisBoard.canvas.root(), "images/cave.png")
00092 
00093     self.display_game()
00094 
00095 
00096   def end(self):
00097 
00098     gcompris.reset_locale()
00099 
00100     # Remove the root item removes all the others inside it
00101     self.cleanup_game()
00102 
00103   def ok(self):
00104     print("Gcompris_guessnumber ok.")
00105 
00106 
00107   def repeat(self):
00108     print("Gcompris_guessnumber repeat.")
00109 
00110 
00111   def key_press(self, keyval, commit_str, preedit_str):
00112     # Return  True  if you did process a key
00113     # Return  False if you did not processed a key
00114     #         (gtk need to send it to next widget)
00115     return False
00116 
00117   def pause(self, pause):
00118     self.board_paused = pause
00119 
00120     # Hack for widget that can't be covered by bonus and/or help
00121     if pause:
00122        self.entry.hide()
00123     else:
00124       self.entry.show()
00125 
00126     # When the bonus is displayed, it call us first with pause(1) and then with pause(0)
00127     # the game is won
00128     if(pause == 0 and self.gamewon):
00129       self.increment_level()
00130       self.gamewon = 0
00131 
00132       self.cleanup_game()
00133       self.display_game()
00134 
00135     return
00136 
00137 
00138   def set_level(self, level):
00139     self.gcomprisBoard.level=level;
00140     self.gcomprisBoard.sublevel=1;
00141 
00142     # Set the level in the control bar
00143     gcompris.bar_set_level(self.gcomprisBoard);
00144 
00145     self.cleanup_game()
00146     self.display_game()
00147 
00148   #
00149   # End of Initialisation
00150   # ---------------------
00151   #
00152 
00153   # Code that increments the sublevel and level
00154   # And bail out if no more levels are available
00155   # return 1 if continue, 0 if bail out
00156   def increment_level(self):
00157     self.gcomprisBoard.sublevel += 1
00158 
00159     if(self.gcomprisBoard.sublevel>self.gcomprisBoard.number_of_sublevel):
00160       # Try the next level
00161       self.gcomprisBoard.sublevel=1
00162       self.gcomprisBoard.level += 1
00163       gcompris.bar_set_level(self.gcomprisBoard)
00164 
00165       if(self.gcomprisBoard.level>self.gcomprisBoard.maxlevel):
00166         # the current board is finished : bail out
00167         gcompris.bonus.board_finished(gcompris.bonus.FINISHED_RANDOM)
00168         return 0
00169 
00170     return 1
00171 
00172   # Display the board game
00173   def cleanup_game(self):
00174     self.gamewon = False
00175     if self.movestep_timer != 0:
00176       gtk.timeout_remove(self.movestep_timer)
00177       self.movestep_timer = 0
00178 
00179     # Remove the root item removes all the others inside it
00180     self.rootitem.destroy()
00181 
00182   # Display the board game
00183   def display_game(self):
00184 
00185       # Create our rootitem. We put each canvas item in it so at the end we
00186       # only have to kill it. The canvas deletes all the items it contains automaticaly.
00187       self.rootitem = self.gcomprisBoard.canvas.root().add(
00188           gnomecanvas.CanvasGroup,
00189           x=0.0,
00190           y=0.0
00191           )
00192 
00193       self.min = 1
00194       self.max = 10
00195       if(self.gcomprisBoard.level == 2):
00196           self.max = 100
00197       elif(self.gcomprisBoard.level == 3):
00198           self.max = 500
00199       elif(self.gcomprisBoard.level == 4):
00200           self.max = 1000
00201 
00202       # Select the number to find
00203       self.solution = random.randint(self.min, self.max)
00204 
00205       text = _("Guess a number between %d and %d") %(self.min, self.max)
00206 
00207       self.rootitem.add(
00208           gnomecanvas.CanvasText,
00209           x=340.0 + 1.0,
00210           y=30.0 + 1.0,
00211           font=gcompris.skin.get_font("gcompris/title"),
00212           text=(text),
00213           fill_color="white",
00214           justification=gtk.JUSTIFY_CENTER
00215           )
00216 
00217       self.rootitem.add(
00218           gnomecanvas.CanvasText,
00219           x=340.0,
00220           y=30.0,
00221           font=gcompris.skin.get_font("gcompris/title"),
00222           text=(text),
00223           fill_color_rgba=0x1514c4ffL,
00224           justification=gtk.JUSTIFY_CENTER
00225           )
00226 
00227       self.indicator_s = self.rootitem.add(
00228           gnomecanvas.CanvasText,
00229           x=300.0 + 1.0,
00230           y=70.0 + 1.0,
00231           font=gcompris.skin.get_font("gcompris/subtitle"),
00232           text=(""),
00233           fill_color="white",
00234           justification=gtk.JUSTIFY_CENTER
00235           )
00236 
00237       self.indicator = self.rootitem.add(
00238           gnomecanvas.CanvasText,
00239           x=300.0,
00240           y=70.0,
00241           font=gcompris.skin.get_font("gcompris/subtitle"),
00242           text=(""),
00243           fill_color_rgba=0xff0006ffL,
00244           justification=gtk.JUSTIFY_CENTER
00245           )
00246 
00247       self.entry_text()
00248 
00249       #
00250       # Display the helico
00251       #
00252       pixmap = gcompris.utils.load_pixmap("gcompris/misc/tuxhelico.png")
00253       self.helico_width = pixmap.get_width()
00254       self.helico_height = pixmap.get_height()
00255       self.orig_x = self.x_old = self.x = pixmap.get_width()/2 + 10
00256       self.y_old = self.y = self.orig_y
00257 
00258       self.anim = self.rootitem.add(
00259         gnomecanvas.CanvasPixbuf,
00260         pixbuf = pixmap,
00261         x=self.x,
00262         y=self.y,
00263         anchor=gtk.ANCHOR_CENTER,
00264         )
00265 
00266   def entry_text(self):
00267     self.entry = gtk.Entry()
00268 
00269     self.entry.modify_font(pango.FontDescription("sans bold 24"))
00270     text_color = gtk.gdk.color_parse("blue")
00271     text_color_selected = gtk.gdk.color_parse("green")
00272 
00273     self.entry.modify_text(gtk.STATE_NORMAL, text_color)
00274     self.entry.modify_text(gtk.STATE_SELECTED, text_color_selected)
00275 
00276     self.entry.set_max_length(4)
00277     self.entry.connect("activate", self.enter_callback)
00278     self.entry.connect("changed", self.enter_char_callback)
00279 
00280     self.entry.show()
00281 
00282     self.widget = self.rootitem.add(
00283       gnomecanvas.CanvasWidget,
00284       widget=self.entry,
00285       x=730,
00286       y=30,
00287       width=100,
00288       height=46,
00289       anchor=gtk.ANCHOR_CENTER,
00290       size_pixels=False
00291       )
00292 
00293     self.widget.raise_to_top()
00294 
00295     # does not work. Why ?
00296     #self.gcomprisBoard.canvas.grab_focus()
00297     self.widget.grab_focus()
00298     self.entry.grab_focus()
00299 
00300   def enter_char_callback(self, widget):
00301       text = widget.get_text()
00302       widget.set_text(text.decode('utf8').upper().encode('utf8'))
00303 
00304   def enter_callback(self, widget):
00305     text = widget.get_text()
00306 
00307     # Find a number game
00308     if str(self.solution) == text:
00309       self.indicator.set(text="")
00310       self.indicator_s.set(text="")
00311       self.gamewon = True
00312       gcompris.bonus.display(gcompris.bonus.WIN, gcompris.bonus.TUX)
00313     else:
00314       try:
00315         # can have been destroyed before by a delete action. No matter
00316         number = int(text)
00317       except:
00318         self.indicator.set(text=_("Please enter a number between %d and %d") %(self.min, self.max))
00319         self.indicator_s.set(text=_("Please enter a number between %d and %d") %(self.min, self.max))
00320         widget.set_text('')
00321         return
00322 
00323       if number > self.max or number <= 0:
00324         self.indicator.set(text=_("Out of range"))
00325         self.indicator_s.set(text=_("Out of range"))
00326       else:
00327         max_distance = max(self.max - self.solution, self.solution)
00328         distance_x = self.target_x - abs(self.solution - number) * float(self.target_x - self.orig_x) / max_distance
00329         distance_y = self.orig_y + float(((self.solution - number) * 170) / max_distance)
00330         if(number > self.solution):
00331           self.indicator.set(text=_("Too high"))
00332           self.indicator_s.set(text=_("Too high"))
00333         else:
00334           self.indicator.set(text=_("Too low"))
00335           self.indicator_s.set(text=_("Too low"))
00336 
00337         self.move(self.x_old, self.y_old,
00338                   distance_x,
00339                   distance_y)
00340 
00341     widget.set_text('')
00342 
00343 
00344   def move_step(self):
00345     if self.move_stepnum < self.num_moveticks-1:
00346       self.move_stepnum += 1
00347       x_old = self.anim.get_property("x")
00348       y_old = self.anim.get_property("y")
00349       x = self.anim.get_property("x") + self.velocity[0]/self.num_moveticks
00350       y = self.anim.get_property("y") + self.velocity[1]/self.num_moveticks
00351       ret = True
00352       self.anim.set(x=x, y=y)
00353       return True
00354     else:
00355       x = self.anim.get_property("x") + self.velocity[0]/self.num_moveticks
00356       y = self.anim.get_property("y") + self.velocity[1]/self.num_moveticks
00357       self.move_stepnum = 0
00358       self.moving = False
00359       self.movestep_timer = 0
00360       self.anim.set(x=(self.x_old),
00361                     y=(self.y_old))
00362       gcompris.utils.item_rotate(self.anim, 0)
00363       self.entry.set_editable(True)
00364       return False
00365 
00366 
00367   def move(self, x_old, y_old, x, y):
00368     if x == x_old and y == y_old:
00369       return
00370 
00371     self.entry.set_editable(False)
00372     self.x_old = x
00373     self.y_old = y
00374     self.x = x
00375     self.y = y
00376     self.velocity = [float(x-x_old), float(y-y_old)]
00377 
00378     if(x>x_old):
00379       self.rotation = 2
00380     elif (x<x_old):
00381       self.rotation = -2
00382     else:
00383       self.rotation = 0
00384     gcompris.utils.item_rotate(self.anim, self.rotation)
00385 
00386     self.moving = True
00387     self.move_stepnum = 0
00388 
00389     # it takes self.num_moveticks iterations of duration self.move_tick to move squares
00390     self.movestep_timer = gtk.timeout_add(self.move_tick, self.move_step)