# gcompris - BarGame # # Copyright (C) 2004, 2008 Yves Combe # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # import goocanvas import gcompris import gcompris.utils import gcompris.bonus import gcompris.skin import pygtk import gtk import gtk.gdk import random import math backgrounds = [ 'bargame/school_bg1.jpg', 'bargame/school_bg2.jpg', 'bargame/school_bg3.jpg', 'bargame/school_bg4.jpg' ] profs = [ 'bargame/tux.png', 'bargame/tux_teen.png', 'bargame/tux_graduate.png', 'bargame/tux_albert.png' ] class Gcompris_bargame: """The Bar Game""" def __init__(self, gcomprisBoard): random.seed() self.gcomprisBoard = gcomprisBoard self.rootitem = None # To display the bonus, we need to pause the board. self.board_paused = 0 self.number_balls = [[1,4],[2,6],[3,6]] self.board_size = [15,19,29] self.gcomprisBoard.level=1 self.gcomprisBoard.maxlevel=4 self.gcomprisBoard.sublevel=1 self.gcomprisBoard.number_of_sublevel=3 # global scale depending on the level self.scales = [0.208, 0.164, 0.107] self.holes = [] self.balls = [] self.list_win = [] self.profbutton = [] self.answer = [] self.pixmap_blue_ball = gcompris.utils.load_pixmap("bargame/blue_ball.png") self.pixmap_green_ball = gcompris.utils.load_pixmap("bargame/green_ball.png") self.pixmap_case = gcompris.utils.load_pixmap("bargame/case.png") self.pixmap_case_last = gcompris.utils.load_pixmap("bargame/case_last.png") self.pixmap_ombre = gcompris.utils.load_pixmap("bargame/ombre.png") self.pixmap_mask = gcompris.utils.load_pixmap("bargame/mask.png") self.pixmap_mask_last = gcompris.utils.load_pixmap("bargame/mask_last.png") def start(self): # load pixmaps for the ui. # gcompris.bar_set(gcompris.BAR_LEVEL|gcompris.BAR_REPEAT) gcompris.bar_set_level(self.gcomprisBoard) gcompris.bar_location(10, -1, 0.7) # Create persistent over levels root item canvas for the board self.rootitem_p = goocanvas.Group( parent = self.gcomprisBoard.canvas.get_root_item() ) self.profbutton = self.prof_button(self, self.rootitem_p, profs[self.gcomprisBoard.level - 1]) self.answer = self.answer_button(self.rootitem_p, self.scales[self.gcomprisBoard.sublevel-1], self.pixmap_green_ball, self.number_balls[self.gcomprisBoard.sublevel-1]) # self.newGame() def end(self): self.cleanup() del self.profbutton self.profbutton = [] del self.answer self.answer = [] if self.rootitem_p: self.rootitem_p.remove() def set_level(self,level): self.gcomprisBoard.level = level self.gcomprisBoard.sublevel = 1 gcompris.bar_set_level(self.gcomprisBoard) self.newGame() pass def ok(self): self.answer.has_focus() self.play(self.answer.value,True) def key_press(self, keyval, commit_str, preedit_str): return False def repeat(self): self.newGame() def pause(self, pause): self.board_paused = pause # When the bonus is displayed, it call us first with pause(1) and then with pause(0) # the game is won if ((pause == 0) and self.finished_sublevel): self.set_sublevel(self.gcomprisBoard.sublevel+1) return 0 #------------------------------------------------- #------------------------------------------------- #------------------------------------------------- def set_sublevel(self, sublevel): #sublevel change only in game_won if sublevel > self.gcomprisBoard.number_of_sublevel: if self.game_won: if self.gcomprisBoard.level == self.gcomprisBoard.maxlevel: self.set_level(self.gcomprisBoard.level) else: self.set_level(self.gcomprisBoard.level+1) else: self.gcomprisBoard.sublevel = 1 self.newGame() else: self.gcomprisBoard.sublevel = sublevel self.newGame() def calculate_win_places(self): winners = [] min = self.number_balls[self.gcomprisBoard.sublevel-1][0] max = self.number_balls[self.gcomprisBoard.sublevel-1][1] period = (min + max) winners_list = [(self.board_size[self.gcomprisBoard.sublevel-1] -1 -x)% period for x in range(min)] for i in range(self.board_size[self.gcomprisBoard.sublevel-1]): if ((i+1) % period) in winners_list: winners.append(i) level_win = (self.gcomprisBoard.level -1) * min if level_win == 0: winners = [] else: winners = winners[-level_win:] return winners # Remove uneeded objects def cleanup(self): if self.rootitem: self.rootitem.remove() # Holes reinit for h in self.holes: del h del self.holes self.holes = [] # Balls reinit for h in self.balls: del h del self.balls self.balls = [] # Other variable cleanup del self.list_win self.list_win = [] def newGame(self): self.cleanup() width_ref = 256 scale = self.scales[self.gcomprisBoard.sublevel-1] self.last_played = -1 self.finished_sublevel = False self.game_won = False self.list_win = self.calculate_win_places() # Create root item canvas for the board self.rootitem = goocanvas.Group(parent = self.gcomprisBoard.canvas.get_root_item()) # background gcompris.set_background(self.gcomprisBoard.canvas.get_root_item(), backgrounds[self.gcomprisBoard.level - 1]) self.profbutton.set_prof(profs[self.gcomprisBoard.level - 1]) for i in range(self.board_size[self.gcomprisBoard.sublevel-1]): self.holes.append(self.hole(self, self.rootitem, i * width_ref * scale, gcompris.BOARD_HEIGHT - 140, i, self.board_size[self.gcomprisBoard.sublevel-1], scale)) for i in range(self.number_balls[self.gcomprisBoard.sublevel-1][1]): self.balls.append(self.ball(self.rootitem, i * width_ref * scale + 150, gcompris.BOARD_HEIGHT - 200, scale, self.pixmap_blue_ball)) self.balls.append(self.ball(self.rootitem, i * width_ref * scale +150, gcompris.BOARD_HEIGHT-90, scale, self.pixmap_green_ball)) self.answer.set_number_of_balls(self.number_balls[self.gcomprisBoard.sublevel-1]) # The OK Button item = goocanvas.Svg(parent = self.rootitem, svg_handle = gcompris.skin.svg_get(), svg_id = "#OK" ) item.translate(item.get_bounds().x1 * -1 + gcompris.BOARD_WIDTH - (item.get_bounds().x2 - item.get_bounds().x1) - 10, item.get_bounds().y1 * -1 + gcompris.BOARD_HEIGHT - 230) item.connect("button_press_event", self.ok_event) gcompris.utils.item_focus_init(item, None) def play(self, value, human): for i in range(1,value+1): self.last_played += 1 if human: self.holes[self.last_played].isGreen() else: self.holes[self.last_played].isBlue() if self.last_played == self.board_size[self.gcomprisBoard.sublevel-1] - 1 : self.gamelost(human) return if human: self.machine_play() def machine_play(self): def accessible(x): if ((x + self.last_played) in self.list_win): return True return False playable = filter(accessible, range(self.number_balls[self.gcomprisBoard.sublevel-1][0], self.number_balls[self.gcomprisBoard.sublevel-1][1]+1)) if playable != []: self.play(random.choice(playable),False) else: self.play(random.choice(range(self.number_balls[self.gcomprisBoard.sublevel-1][0], self.number_balls[self.gcomprisBoard.sublevel-1][1]+1)), False) self.answer.new_value(self.number_balls[self.gcomprisBoard.sublevel-1][0]) self.profbutton.no_more_active() def gamelost(self,human): self.finished_sublevel = True if human: gcompris.bonus.display(gcompris.bonus.LOOSE, gcompris.bonus.GNU) else: self.game_won = True gcompris.bonus.display(gcompris.bonus.WIN, gcompris.bonus.GNU) class hole: def __init__(self, board, root, x, y, index, board_size, scale): self.board = board self.itemgroup = goocanvas.Group(parent = root) self.itemgroup.translate(x, y) self.scale = scale if (index == (board_size-1)): pixbuf_case = self.board.pixmap_case_last pixbuf_mask = self.board.pixmap_mask_last else: pixbuf_case = self.board.pixmap_case pixbuf_mask = self.board.pixmap_mask item = goocanvas.Image( parent = self.itemgroup, pixbuf = pixbuf_case, x=0, y=0) bounds = item.get_bounds() # Add a little zoom offset to make sure items stick well item.scale(scale + 0.01, scale) self.ombre = goocanvas.Image( parent = self.itemgroup, pixbuf = self.board.pixmap_ombre, x=0, y=0) self.ombre.props.visibility = goocanvas.ITEM_INVISIBLE bounds = self.ombre.get_bounds() self.ombre.scale(scale, scale) self.ball = goocanvas.Image( parent = self.itemgroup, x=0, y=0) self.ball.props.visibility = goocanvas.ITEM_INVISIBLE item = goocanvas.Image( parent = self.itemgroup, pixbuf = pixbuf_mask, x=0, y=0) bounds = item.get_bounds() item.scale(scale, scale) if ((index+1)%5 == 0): goocanvas.Text( parent = self.itemgroup, x = (bounds.x2-bounds.x1)/2, y = -10, fill_color_rgba = 0x000000ffL, font=gcompris.skin.get_font("gcompris/board/small bold"), anchor = gtk.ANCHOR_CENTER, text = index + 1) def isBlue(self): self.ball.props.pixbuf = self.board.pixmap_blue_ball bounds = self.ball.get_bounds() self.ball.scale(self.scale, self.scale) self.ball.props.visibility = goocanvas.ITEM_VISIBLE self.ombre.props.visibility = goocanvas.ITEM_VISIBLE def isGreen(self): self.ball.props.pixbuf = self.board.pixmap_green_ball bounds = self.ball.get_bounds() self.ball.scale(self.scale, self.scale) self.ball.props.visibility = goocanvas.ITEM_VISIBLE self.ombre.props.visibility = goocanvas.ITEM_VISIBLE class ball: def __init__(self, root, x, y, scale, image): self.ball = goocanvas.Image( parent = root, pixbuf = image) bounds = self.ball.get_bounds() self.ball.scale(scale, scale) (x, y) = root.get_canvas().convert_to_item_space(self.ball, x, y) self.ball.translate(x, y) class answer_button: def __init__(self, root, scale, image, number_balls): self.focus = False self.number_balls = number_balls self.itemgroup = goocanvas.Group(parent = root) self.background = goocanvas.Image( parent = self.itemgroup, pixbuf = gcompris.utils.load_pixmap("bargame/enumerate_answer.png"), ) answer_bounds = self.background.get_bounds() gcompris.utils.item_focus_init(self.background, None) self.itemgroup.translate(gcompris.BOARD_WIDTH - 180, gcompris.BOARD_HEIGHT - answer_bounds.y2 \ - answer_bounds.y1 - 10) self.background_focused = goocanvas.Image( parent = self.itemgroup, pixbuf = gcompris.utils.load_pixmap("bargame/enumerate_answer_focus.png"), ) gcompris.utils.item_focus_init(self.background_focused, self.background) self.background_focused.props.visibility = goocanvas.ITEM_INVISIBLE self.icone = goocanvas.Image( parent = self.itemgroup, pixbuf = image) bounds = self.icone.get_bounds() self.icone.scale(scale, scale) (x, y) = root.get_canvas().convert_from_item_space(self.itemgroup, 10, 20) (x, y) = root.get_canvas().convert_to_item_space(self.icone, x, y) self.icone.translate(x, y) gcompris.utils.item_focus_init(self.icone, self.background) self.value = number_balls[0] self.text = goocanvas.Text( parent = self.itemgroup, x = answer_bounds.x2-answer_bounds.x1 - 50, y = 40, fill_color_rgba=0xff0000ffL, font=gcompris.skin.get_font("gcompris/board/huge bold"), anchor=gtk.ANCHOR_CENTER, text = self.value ) gcompris.utils.item_focus_init(self.text, self.background) self.background.connect("button_press_event",self.answer_event) self.background_focused.connect("button_press_event",self.answer_event) self.icone.connect("button_press_event",self.answer_event) self.text.connect("button_press_event",self.answer_event) def new_value(self, value): self.value = value self.text.set_property('text',value) def has_focus(self): self.background_focused.props.visibility = goocanvas.ITEM_VISIBLE self.focus = True def set_number_of_balls(self, number_balls): self.number_balls = number_balls self.new_value(1) def answer_event(self, item, target, event): if ((event.type != gtk.gdk.BUTTON_PRESS) or (event.button != 1)): return False self.has_focus() value = ( (self.value + 1 - self.number_balls[0]) % (self.number_balls[1] + 1 - self.number_balls[0]) + self.number_balls[0] ) self.new_value(value) return True class prof_button: def __init__(self, board, root, prof_image): self.board = board self.prof_item = goocanvas.Image( parent = root, y = 210 ) def set_prof(self, prof_image): self.prof_item.props.pixbuf = gcompris.utils.load_pixmap(prof_image) bounds = self.prof_item.get_bounds() self.prof_item.props.x = \ (gcompris.BOARD_WIDTH - bounds.x2-bounds.x1)/2 - 90 self.prof_item.connect("button_press_event", self.event_play) self.prof_image = prof_image # This item is clickeable and it must be seen gcompris.utils.item_focus_init(self.prof_item, None) def no_more_active(self): gcompris.utils.item_focus_remove(self.prof_item, None) def event_play(self, item, target, event): if ((event.type != gtk.gdk.BUTTON_PRESS) or (event.button != 1)): return False # if answer button has been clicked, that play the human turn if self.board.last_played == -1 : self.board.machine_play() return True return False def ok_event(self, widget, target, event=None): self.ok()