Back to index

gcompris  8.2.2
bargame.py
Go to the documentation of this file.
00001 #  gcompris - BarGame
00002 #
00003 #
00004 #
00005 # Copyright (C) 2004  Yves Combe
00006 #
00007 #   This program is free software; you can redistribute it and/or modify
00008 #   it under the terms of the GNU General Public License as published by
00009 #   the Free Software Foundation; either version 2 of the License, or
00010 #   (at your option) any later version.
00011 #
00012 #   This program is distributed in the hope that it will be useful,
00013 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 #   GNU General Public License for more details.
00016 #
00017 #   You should have received a copy of the GNU General Public License
00018 #   along with this program; if not, write to the Free Software
00019 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 #
00021 import gnomecanvas
00022 import gcompris
00023 import gcompris.utils
00024 import gcompris.bonus
00025 import gcompris.skin
00026 import pygtk
00027 import gtk
00028 import gtk.gdk
00029 import random
00030 import math
00031 
00032 backgrounds = [ 'images/school_bg1.jpg',
00033                 'images/school_bg2.jpg',
00034                 'images/school_bg3.jpg',
00035                 'images/school_bg4.jpg'
00036                 ]
00037 
00038 profs = [ 'images/tux.png',
00039           'images/tux_teen.png',
00040           'images/tux_graduate.png',
00041           'images/tux_albert.png'
00042           ]
00043 
00044 class Gcompris_bargame:
00045   """The Bar Game"""
00046 
00047   def __init__(self, gcomprisBoard):
00048     random.seed()
00049     self.gcomprisBoard = gcomprisBoard
00050     self.rootitem = None
00051 
00052     # To display the bonus, we need to pause the board.
00053     self.board_paused  = 0
00054     self.number_balls = [[1,4],[2,6],[3,6]]
00055     self.board_size = [15,19,29]
00056     self.gcomprisBoard.level=1
00057     self.gcomprisBoard.maxlevel=4
00058     self.gcomprisBoard.sublevel=1
00059     self.gcomprisBoard.number_of_sublevel=3
00060 
00061     # global scale depending on the level
00062     self.scales = [0.208, 0.164, 0.107]
00063 
00064     self.holes = []
00065     self.balls = []
00066     self.list_win = []
00067     self.profbutton = []
00068     self.answer = []
00069 
00070     self.pixmap_blue_ball  = gcompris.utils.load_pixmap("bargame/blue_ball.png")
00071     self.pixmap_green_ball = gcompris.utils.load_pixmap("bargame/green_ball.png")
00072     self.pixmap_case       = gcompris.utils.load_pixmap("bargame/case.png")
00073     self.pixmap_case_last  = gcompris.utils.load_pixmap("bargame/case_last.png")
00074     self.pixmap_ombre      = gcompris.utils.load_pixmap("bargame/ombre.png")
00075     self.pixmap_mask       = gcompris.utils.load_pixmap("bargame/mask.png")
00076     self.pixmap_mask_last  = gcompris.utils.load_pixmap("bargame/mask_last.png")
00077 
00078   def start(self):
00079     # load pixmaps for the ui.
00080     #
00081     pixmap = gcompris.utils.load_pixmap(gcompris.skin.image_to_skin("button_reload.png"))
00082     if(pixmap):
00083       gcompris.bar_set_repeat_icon(pixmap)
00084       gcompris.bar_set(gcompris.BAR_LEVEL|gcompris.BAR_OK|gcompris.BAR_REPEAT_ICON)
00085     else:
00086       gcompris.bar_set(gcompris.BAR_LEVEL|gcompris.BAR_OK|gcompris.BAR_REPEAT)
00087     gcompris.bar_set_level(self.gcomprisBoard)
00088 
00089     # Create persistent over levels root item canvas for the board
00090     self.rootitem_p = self.gcomprisBoard.canvas.root().add(
00091       gnomecanvas.CanvasGroup,
00092       x=0,
00093       y=0
00094       )
00095 
00096     self.profbutton = self.prof_button(self,
00097                                        self.rootitem_p,
00098                                        profs[self.gcomprisBoard.level - 1])
00099 
00100     self.answer = self.answer_button(self.rootitem_p,
00101                                      self.scales[self.gcomprisBoard.sublevel-1],
00102                                      self.pixmap_green_ball,
00103                                      self.number_balls[self.gcomprisBoard.sublevel-1])
00104 
00105     #
00106     self.newGame()
00107 
00108   def end(self):
00109     self.cleanup()
00110 
00111     del self.profbutton
00112     self.profbutton = []
00113 
00114     del self.answer
00115     self.answer = []
00116 
00117     if self.rootitem_p:
00118       self.rootitem_p.destroy()
00119 
00120 
00121   def set_level(self,level):
00122     self.gcomprisBoard.level = level
00123     self.gcomprisBoard.sublevel = 1
00124     gcompris.bar_set_level(self.gcomprisBoard)
00125 
00126     self.newGame()
00127     pass
00128 
00129   def ok(self):
00130     self.answer.has_focus()
00131     self.play(self.answer.value,True)
00132     pass
00133 
00134   def key_press(self, keyval, commit_str, preedit_str):
00135     return False
00136 
00137   def repeat(self):
00138     self.newGame()
00139 
00140   def pause(self, pause):
00141     self.board_paused = pause
00142 
00143     # When the bonus is displayed, it call us first with pause(1) and then with pause(0)
00144     # the game is won
00145     if ((pause == 0) and self.finished_sublevel):
00146       self.set_sublevel(self.gcomprisBoard.sublevel+1)
00147       return 0
00148 
00149 
00150   #-------------------------------------------------
00151   #-------------------------------------------------
00152   #-------------------------------------------------
00153 
00154   def set_sublevel(self, sublevel):
00155     #sublevel change only in game_won
00156     if sublevel > self.gcomprisBoard.number_of_sublevel:
00157       if self.game_won:
00158         if self.gcomprisBoard.level == self.gcomprisBoard.maxlevel:
00159           gcompris.bonus.board_finished(gcompris.bonus.FINISHED_RANDOM)
00160           return 0
00161         else:
00162           self.set_level(self.gcomprisBoard.level+1)
00163       else:
00164         self.gcomprisBoard.sublevel = 1
00165         self.newGame()
00166     else:
00167       self.gcomprisBoard.sublevel = sublevel
00168       self.newGame()
00169 
00170 
00171   def calculate_win_places(self):
00172     winners = []
00173 
00174     min = self.number_balls[self.gcomprisBoard.sublevel-1][0]
00175     max = self.number_balls[self.gcomprisBoard.sublevel-1][1]
00176     period = (min + max)
00177 
00178     winners_list = [(self.board_size[self.gcomprisBoard.sublevel-1] -1 -x)% period for x in range(min)]
00179     for i in range(self.board_size[self.gcomprisBoard.sublevel-1]):
00180       if ((i+1) % period) in  winners_list:
00181         winners.append(i)
00182 
00183     level_win = (self.gcomprisBoard.level -1) * min
00184 
00185     if level_win == 0:
00186       winners = []
00187     else:
00188       winners = winners[-level_win:]
00189 
00190     return winners
00191 
00192   # Remove uneeded objects
00193   def cleanup(self):
00194     if self.rootitem:
00195       self.rootitem.destroy()
00196 
00197     # Holes reinit
00198     for h in self.holes:
00199       del h
00200 
00201     del self.holes
00202     self.holes = []
00203 
00204     # Balls reinit
00205     for h in self.balls:
00206       del h
00207 
00208     del self.balls
00209     self.balls = []
00210 
00211 
00212     # Other variable cleanup
00213     del self.list_win
00214     self.list_win = []
00215 
00216   def newGame(self):
00217     self.cleanup()
00218 
00219     width_ref = 256
00220 
00221     scale = self.scales[self.gcomprisBoard.sublevel-1]
00222 
00223     self.last_played = -1
00224     self.finished_sublevel = False
00225     self.game_won = False
00226     self.list_win = self.calculate_win_places()
00227 
00228 
00229     # Create root item canvas for the board
00230     self.rootitem = self.gcomprisBoard.canvas.root().add(
00231       gnomecanvas.CanvasGroup,
00232       x=0,
00233       y=0
00234       )
00235 
00236     # background
00237     gcompris.set_background(self.gcomprisBoard.canvas.root(),
00238                             backgrounds[self.gcomprisBoard.level - 1])
00239 
00240     self.profbutton.set_prof(profs[self.gcomprisBoard.level - 1])
00241 
00242     for i in range(self.board_size[self.gcomprisBoard.sublevel-1]):
00243       self.holes.append(self.hole(self,
00244                                   self.rootitem,
00245                                   i * width_ref * scale,
00246                                   gcompris.BOARD_HEIGHT - 120, i,
00247                                   self.board_size[self.gcomprisBoard.sublevel-1],
00248                                   scale))
00249 
00250     for i in range(self.number_balls[self.gcomprisBoard.sublevel-1][1]):
00251       self.balls.append(self.ball(self.rootitem,
00252                                   i * width_ref * scale + 150,
00253                                   gcompris.BOARD_HEIGHT - 160,
00254                                   scale,
00255                                   self.pixmap_blue_ball))
00256       self.balls.append(self.ball(self.rootitem,
00257                                   i * width_ref * scale +150,
00258                                   gcompris.BOARD_HEIGHT-70,
00259                                   scale,
00260                                   self.pixmap_green_ball))
00261 
00262     self.answer.set_number_of_balls(self.number_balls[self.gcomprisBoard.sublevel-1])
00263 
00264 
00265   def play(self, value, human):
00266     for i in range(1,value+1):
00267       self.last_played += 1
00268       if human:
00269         self.holes[self.last_played].isGreen()
00270       else:
00271         self.holes[self.last_played].isBlue()
00272 
00273       if self.last_played == self.board_size[self.gcomprisBoard.sublevel-1] - 1 :
00274         self.gamelost(human)
00275         return
00276 
00277     if human:
00278       self.machine_play()
00279 
00280 
00281   def machine_play(self):
00282 
00283     def accessible(x):
00284       if ((x + self.last_played) in self.list_win):
00285         return True
00286       return False
00287 
00288     playable = filter(accessible,
00289                       range(self.number_balls[self.gcomprisBoard.sublevel-1][0],
00290                             self.number_balls[self.gcomprisBoard.sublevel-1][1]+1))
00291 
00292     if playable != []:
00293       self.play(random.choice(playable),False)
00294     else:
00295       self.play(random.choice(range(self.number_balls[self.gcomprisBoard.sublevel-1][0],
00296                                     self.number_balls[self.gcomprisBoard.sublevel-1][1]+1)),
00297                 False)
00298 
00299     self.answer.new_value(self.number_balls[self.gcomprisBoard.sublevel-1][0])
00300 
00301   def gamelost(self,human):
00302     self.finished_sublevel = True
00303     if human:
00304       gcompris.bonus.display(gcompris.bonus.LOOSE, gcompris.bonus.GNU)
00305     else:
00306       self.game_won = True
00307       gcompris.bonus.display(gcompris.bonus.WIN, gcompris.bonus.GNU)
00308 
00309 
00310   class hole:
00311     def __init__(self, board, root, x, y, index,
00312                  board_size,
00313                  scale):
00314       self.board = board
00315 
00316       self.itemgroup = root.add(
00317         gnomecanvas.CanvasGroup,
00318         x=x,
00319         y=y)
00320 
00321       self.scale = scale
00322 
00323       if (index == (board_size-1)):
00324         pixbuf_case = self.board.pixmap_case_last
00325         pixbuf_mask = self.board.pixmap_mask_last
00326       else:
00327         pixbuf_case = self.board.pixmap_case
00328         pixbuf_mask = self.board.pixmap_mask
00329 
00330 
00331       item = self.itemgroup.add(
00332         gnomecanvas.CanvasPixbuf,
00333         pixbuf = pixbuf_case,
00334         x=0,
00335         y=0)
00336       bounds = item.get_bounds()
00337       item.set(width  = (bounds[2]-bounds[0])*scale,
00338                height = (bounds[3]-bounds[1])*scale,
00339                width_set  = True,
00340                height_set = True)
00341 
00342       self.ombre = self.itemgroup.add(
00343         gnomecanvas.CanvasPixbuf,
00344         pixbuf = self.board.pixmap_ombre,
00345         x=0,
00346         y=0)
00347       self.ombre.hide()
00348       bounds = self.ombre.get_bounds()
00349       self.ombre.set(width  = (bounds[2]-bounds[0])*scale,
00350                      height = (bounds[3]-bounds[1])*scale,
00351                      width_set  = True,
00352                      height_set = True)
00353 
00354       self.ball = self.itemgroup.add(
00355         gnomecanvas.CanvasPixbuf,
00356         x=0,
00357         y=0)
00358       self.ball.hide()
00359 
00360       item = self.itemgroup.add(
00361         gnomecanvas.CanvasPixbuf,
00362         pixbuf = pixbuf_mask,
00363         x=0,
00364         y=0)
00365       bounds = item.get_bounds()
00366       item.set(width  = (bounds[2]-bounds[0])*scale,
00367                height = (bounds[3]-bounds[1])*scale,
00368                width_set  = True,
00369                height_set = True)
00370 
00371       if ((index+1)%5 == 0):
00372         self.itemgroup.add(
00373           gnomecanvas.CanvasText,
00374           x=(bounds[2]-bounds[0])/2,
00375           y=-10,
00376           fill_color_rgba=0x000000ffL,
00377           font=gcompris.skin.get_font("gcompris/board/small bold"),
00378           anchor=gtk.ANCHOR_CENTER,
00379           text = index + 1)
00380 
00381 
00382     def isBlue(self):
00383       self.ball.set(pixbuf = self.board.pixmap_blue_ball)
00384       bounds = self.ball.get_bounds()
00385       self.ball.set(width  = (bounds[2]-bounds[0])*self.scale,
00386                     height = (bounds[3]-bounds[1])*self.scale,
00387                     width_set  = True,
00388                     height_set = True)
00389       self.ball.show()
00390       self.ombre.show()
00391 
00392     def isGreen(self):
00393       self.ball.set(pixbuf = self.board.pixmap_green_ball)
00394       bounds = self.ball.get_bounds()
00395       self.ball.set(width  = (bounds[2]-bounds[0])*self.scale,
00396                     height = (bounds[3]-bounds[1])*self.scale,
00397                     width_set  = True,
00398                     height_set = True)
00399       self.ball.show()
00400       self.ombre.show()
00401 
00402 
00403   class ball:
00404     def __init__(self, root, x, y, scale, image):
00405 
00406       self.ball = root.add(
00407         gnomecanvas.CanvasPixbuf,
00408         pixbuf = image,
00409         x=x,
00410         y=y)
00411       bounds = self.ball.get_bounds()
00412       self.ball.set(width  = (bounds[2]-bounds[0])*scale,
00413                     height = (bounds[3]-bounds[1])*scale,
00414                     width_set  = True,
00415                     height_set = True)
00416 
00417   class answer_button:
00418     def __init__(self, root, scale, image, number_balls):
00419       self.focus = False
00420 
00421       self.number_balls = number_balls
00422 
00423       self.itemgroup = root.add(
00424         gnomecanvas.CanvasGroup,
00425         x = gcompris.BOARD_WIDTH - 200,
00426         )
00427 
00428       self.background = self.itemgroup.add(
00429         gnomecanvas.CanvasPixbuf,
00430         pixbuf = gcompris.utils.load_pixmap("images/enumerate_answer.png"),
00431         x=0,
00432         y=0
00433         )
00434       answer_bounds = self.background.get_bounds()
00435 
00436       self.itemgroup.set( y = gcompris.BOARD_HEIGHT - answer_bounds[3]-answer_bounds[1] - 5)
00437 
00438       self.background_focused = self.itemgroup.add(
00439         gnomecanvas.CanvasPixbuf,
00440         pixbuf = gcompris.utils.load_pixmap("images/enumerate_answer_focus.png"),
00441         x=0,
00442         y=0
00443         )
00444       self.background_focused.hide()
00445 
00446       self.icone = self.itemgroup.add(
00447         gnomecanvas.CanvasPixbuf,
00448         pixbuf = image,
00449         x=10,
00450         y=20
00451         )
00452       bounds = self.icone.get_bounds()
00453       self.icone.set(width  = (bounds[2]-bounds[0])*scale,
00454                      height = (bounds[3]-bounds[1])*scale,
00455                      width_set  = True,
00456                      height_set = True)
00457 
00458       self.value = number_balls[0]
00459 
00460       self.text = self.itemgroup.add(
00461         gnomecanvas.CanvasText,
00462         x = answer_bounds[2]-answer_bounds[0] - 50,
00463         y = 40,
00464         fill_color_rgba=0xff0000ffL,
00465         font=gcompris.skin.get_font("gcompris/board/huge bold"),
00466         anchor=gtk.ANCHOR_CENTER,
00467         text = self.value
00468         )
00469 
00470       self.background.connect("event",self.answer_event)
00471       self.background_focused.connect("event",self.answer_event)
00472       self.icone.connect("event",self.answer_event)
00473       self.text.connect("event",self.answer_event)
00474 
00475 
00476     def new_value(self, value):
00477       self.value = value
00478       self.text.set_property('text',value)
00479 
00480     def has_focus(self):
00481       self.background_focused.show()
00482       self.focus = True
00483 
00484     def set_number_of_balls(self, number_balls):
00485       self.number_balls = number_balls
00486       self.new_value(1)
00487 
00488     def answer_event(self, item, event):
00489       if ((event.type != gtk.gdk.BUTTON_PRESS) or
00490           (event.button != 1)):
00491         return False
00492 
00493       self.has_focus()
00494 
00495       value = ( (self.value
00496                  + 1
00497                  - self.number_balls[0])
00498                 % (self.number_balls[1]
00499                    + 1
00500                    - self.number_balls[0])
00501                 + self.number_balls[0]
00502                 )
00503       self.new_value(value)
00504 
00505       return True
00506 
00507   class prof_button:
00508     def __init__(self, board, root, prof_image):
00509       self.board = board
00510 
00511       self.prof_item = root.add(
00512         gnomecanvas.CanvasPixbuf,
00513         y = 230
00514         )
00515       bounds = self.prof_item.get_bounds()
00516       self.prof_item.set(x  = ((gcompris.BOARD_WIDTH - bounds[2]-bounds[0])/2 - 90))
00517 
00518       self.prof_item.connect("event",self.event_play)
00519       # This item is clickeable and it must be seen
00520       self.prof_item.connect("event", gcompris.utils.item_event_focus)
00521 
00522     def set_prof(self, prof_image):
00523       self.prof_item.set(pixbuf = gcompris.utils.load_pixmap(prof_image))
00524 
00525     def event_play(self, item, event):
00526       if ((event.type != gtk.gdk.BUTTON_PRESS) or
00527           (event.button != 1)):
00528         return False
00529 
00530       # if answer button has been clicked, that play the human turn
00531       if self.board.last_played == -1 :
00532         self.board.machine_play()
00533         return True
00534 
00535       return False
00536