~ml-launchpad/ubuntu/natty/gcompris/fix-for-777349

« back to all changes in this revision

Viewing changes to src/boards/python/connect4.py

  • Committer: Bazaar Package Importer
  • Author(s): Marc Gariepy, Marc Gariepy, Stephane Graber
  • Date: 2010-01-04 17:42:49 UTC
  • mfrom: (1.1.14 upstream)
  • Revision ID: james.westby@ubuntu.com-20100104174249-7bupatd9dtxyhvs4
Tags: 9.0-0ubuntu1
[Marc Gariepy]
* New upstream release (9.0).
* Remove cache.c from POTFILES to avoid FTBFS
* Remove unneeded rm in debian/rules (file no longer exists upstream)

[Stephane Graber]
* Bump Debian standards to 3.8.3
* Add patch system (dpatch)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#  gcompris - connect4
2
 
#
3
 
# Copyright (C) 2005 Laurent Lacheny
4
 
#
5
 
#   This program is free software; you can redistribute it and/or modify
6
 
#   it under the terms of the GNU General Public License as published by
7
 
#   the Free Software Foundation; either version 3 of the License, or
8
 
#   (at your option) any later version.
9
 
#
10
 
#   This program is distributed in the hope that it will be useful,
11
 
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
#   GNU General Public License for more details.
14
 
#
15
 
#   You should have received a copy of the GNU General Public License
16
 
#   along with this program; if not, see <http://www.gnu.org/licenses/>.
17
 
 
18
 
#
19
 
# The IA code comes from the project 4stattack by Jeroen Vloothuis
20
 
# http://forcedattack.sourceforge.net/
21
 
#
22
 
 
23
 
import gobject
24
 
import gnomecanvas
25
 
import gcompris
26
 
import gcompris.utils
27
 
import gcompris.skin
28
 
import gcompris.bonus
29
 
import gcompris.anim
30
 
import gtk
31
 
import gtk.gdk
32
 
from gcompris import gcompris_gettext as _
33
 
 
34
 
from  connect4p import rules
35
 
from  connect4p import human
36
 
from  connect4p import minmax
37
 
from  connect4p import board
38
 
# ----------------------------------------
39
 
#
40
 
 
41
 
class Gcompris_connect4:
42
 
    """Connect 4 stones"""
43
 
 
44
 
 
45
 
    def __init__(self, gcomprisBoard):
46
 
        self.gcomprisBoard = gcomprisBoard
47
 
 
48
 
    def start(self):
49
 
        self.boardSize = 490.0
50
 
        self.nbColumns = 7
51
 
        self.nbLines = 6
52
 
        self.stoneSize = 70.0
53
 
        self.maxVictory = 3
54
 
        self.maxLevel = 4
55
 
        self.boardItem = None
56
 
        self.timerAnim = 0
57
 
        self.humanVictory = 0
58
 
        self.endAnimCallback = None
59
 
        self.gcomprisBoard.level=1
60
 
        self.gcomprisBoard.maxlevel=9
61
 
        self.gcomprisBoard.sublevel=1
62
 
        self.gcomprisBoard.number_of_sublevel=1
63
 
        self.mode = (self.gcomprisBoard.mode == "2players") and 2 or 1
64
 
        if self.mode == 1:
65
 
            board_bar = gcompris.BAR_LEVEL
66
 
            gcompris.bar_set_level(self.gcomprisBoard)
67
 
        else:
68
 
            board_bar = 0
69
 
        # Create our rootitem. We put each canvas item in it so at the end we
70
 
        # only have to kill it. The canvas deletes all the items it contains automaticaly.
71
 
        self.rootitem = self.gcomprisBoard.canvas.root().add(
72
 
            gnomecanvas.CanvasGroup,
73
 
            x=0.0,
74
 
            y=0.0
75
 
            )
76
 
 
77
 
        pixmap = gcompris.utils.load_pixmap(gcompris.skin.image_to_skin("button_reload.png"))
78
 
        if(pixmap):
79
 
            gcompris.bar_set_repeat_icon(pixmap)
80
 
            board_bar = board_bar | gcompris.BAR_REPEAT_ICON
81
 
        else:
82
 
            board_bar = board_bar | gcompris.BAR_REPEAT
83
 
        gcompris.bar_set(board_bar)
84
 
 
85
 
        selector = self.rootitem.add(
86
 
            gnomecanvas.CanvasPixbuf,
87
 
            pixbuf = gcompris.utils.load_pixmap("connect4/back.png"),
88
 
            x=0.0,
89
 
            y=0.0
90
 
            )
91
 
        selector.connect("event", self.columnItemEvent, 0)
92
 
 
93
 
        if self.mode == 1:
94
 
            self.prof = self.rootitem.add(
95
 
                gnomecanvas.CanvasPixbuf,
96
 
                pixbuf = gcompris.utils.load_pixmap("connect4/tux-teacher.png"),
97
 
                x=10,
98
 
                y=350.0
99
 
                )
100
 
            self.prof.connect("event", self.profItemEvent, 0)
101
 
            self.prof.connect("event", gcompris.utils.item_event_focus)
102
 
 
103
 
        self.timericon = gcompris.anim.CanvasItem( gcompris.anim.Animation("connect4/sablier.txt"),
104
 
            self.rootitem )
105
 
        self.timericon.gnomecanvas.hide()
106
 
 
107
 
        self.player_stone = None
108
 
 
109
 
        for i in range(2):
110
 
            self.rootitem.add(gnomecanvas.CanvasPixbuf,
111
 
                pixbuf = gcompris.utils.load_pixmap("connect4/stone_%d.png" % (i+1)),
112
 
                x= 25,
113
 
                y=175 + i * 73 )
114
 
        self.score_item = self.rootitem.add(
115
 
            gnomecanvas.CanvasText,
116
 
            font=gcompris.skin.get_font("gcompris/board/huge bold"),
117
 
            x=60,
118
 
            y=250,
119
 
            justification=gtk.JUSTIFY_CENTER,
120
 
            fill_color_rgba=0xFF0000FFL)
121
 
 
122
 
        self.update_scores((0, 0))
123
 
 
124
 
        self.newGame()
125
 
 
126
 
    def end(self):
127
 
        if self.timerAnim:
128
 
            gtk.timeout_remove(self.timerAnim)
129
 
 
130
 
        del self.timericon
131
 
 
132
 
        # Remove the root item removes all the others inside it
133
 
        self.rootitem.destroy()
134
 
        self.boardItem.destroy()
135
 
 
136
 
    def ok(self):
137
 
        pass
138
 
 
139
 
    def repeat(self):
140
 
        if max(self.scores) >= self.maxVictory:
141
 
            if self.scores[0] >= self.maxVictory and self.mode == 1:
142
 
                if self.gcomprisBoard.level < self.maxLevel:
143
 
                    self.set_level(self.gcomprisBoard.level+1)
144
 
                else:
145
 
                    self.end()
146
 
                    gcompris.end_board()
147
 
            else:
148
 
                self.update_scores([0, 0])
149
 
                self.newGame()
150
 
        else:
151
 
            self.newGame()
152
 
 
153
 
    def config(self):
154
 
        pass
155
 
    def update_scores(self, scores=None):
156
 
        if scores: self.scores = list(scores)
157
 
        txt = str(self.scores[0]) + "\n\n" + str(self.scores[1])
158
 
        self.score_item.set(text=txt)
159
 
 
160
 
    def stone_init(self):
161
 
        if self.player_stone:
162
 
            self.player_stone.destroy()
163
 
        self.player_stone = self.rootitem.add(
164
 
            gnomecanvas.CanvasPixbuf,
165
 
            pixbuf = gcompris.utils.load_pixmap("connect4/stone_%d.png" % self.cur_player),
166
 
            x=0,
167
 
            y=-20 )
168
 
        self.update_stone2()
169
 
    def update_stone2(self):
170
 
        self.player_stone.set_property("x", (gcompris.BOARD_WIDTH - self.boardSize) /2 +
171
 
            self.keyb_column * self.boardSize / self.nbColumns)
172
 
 
173
 
    def key_press(self, keyval, commit_str, preedit_str):
174
 
        if self.mode == 1 and self.cur_player == 2: # AI playing
175
 
            return False
176
 
        if self.cur_player == 0 or self.timerAnim:  # Game over or Timer animate
177
 
            return False
178
 
        key = gtk.gdk.keyval_name(keyval)
179
 
        if key == "Left":
180
 
            self.keyb_column = max(self.keyb_column-1, 0)
181
 
            self.update_stone2()
182
 
        elif key == "Right":
183
 
            self.keyb_column = min(self.keyb_column+1, self.nbColumns-1)
184
 
            self.update_stone2()
185
 
        elif key =="Down" or commit_str == " ":
186
 
            if self.play(self.player1, self.cur_player, self.keyb_column):
187
 
                self.player_stone.hide()
188
 
        return False
189
 
 
190
 
    def pause(self, pause):
191
 
        pass
192
 
 
193
 
  # Called by gcompris when the user click on the level icon
194
 
    def set_level(self, level):
195
 
        if level > self.maxLevel: level = 1
196
 
        self.gcomprisBoard.level=level
197
 
        self.gcomprisBoard.sublevel=1
198
 
        gcompris.bar_set_level(self.gcomprisBoard)
199
 
        self.player1.setDifficulty(level)
200
 
        self.player2.setDifficulty(level)
201
 
        self.update_scores([0, 0])
202
 
        self.newGame()
203
 
 
204
 
  # End of Initialisation
205
 
  # ---------------------
206
 
 
207
 
    def newGame(self):
208
 
        if self.timerAnim:
209
 
            gtk.timeout_remove(self.timerAnim)
210
 
            self.timerAnim = None
211
 
        if self.boardItem:
212
 
            self.boardItem.destroy()
213
 
        self.boardItem = self.gcomprisBoard.canvas.root().add(
214
 
            gnomecanvas.CanvasGroup,
215
 
            x=(gcompris.BOARD_WIDTH-self.boardSize)/2.0,
216
 
            y=50.0
217
 
            )
218
 
        self.player1 = human.Human(self.gcomprisBoard.level)
219
 
        if self.mode == 1:
220
 
            self.player2 = minmax.MinMax(self.gcomprisBoard.level, self.refreshScreen)
221
 
        self.board = board.Board()
222
 
        self.gamewon = False
223
 
        self.winLine = None
224
 
        try:
225
 
            del self.redLine
226
 
        except:
227
 
            pass
228
 
        self.keyb_column = 0
229
 
        self.cur_player = 1
230
 
        self.stone_init()
231
 
        self.update_stone2()
232
 
 
233
 
        self.timericon.gnomecanvas.hide()
234
 
        if self.mode == 1:
235
 
            self.prof.show()
236
 
 
237
 
    def columnItemEvent(self, widget, event, columns):
238
 
        if self.mode == 1 and self.cur_player == 2: # AI playing
239
 
            return False
240
 
        if self.cur_player == 0 or self.timerAnim:  # Game over or Timer animate
241
 
            return False
242
 
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1:
243
 
            column = int((event.x - (gcompris.BOARD_WIDTH-self.boardSize)/2.0) // self.stoneSize)
244
 
            if 0 <= column < self.nbColumns:
245
 
                if self.play(self.player1, self.cur_player, column):
246
 
                    self.timericon.gnomecanvas.show()
247
 
                    self.player_stone.hide()
248
 
        elif event.type == gtk.gdk.MOTION_NOTIFY:
249
 
            column = int((event.x - (gcompris.BOARD_WIDTH-self.boardSize)/2.0) // self.stoneSize)
250
 
            if 0 <= column < self.nbColumns:
251
 
                self.keyb_column = column
252
 
                self.update_stone2()
253
 
        return False
254
 
 
255
 
    def profItemEvent(self, widget, event, column):
256
 
        if event.type == gtk.gdk.BUTTON_PRESS:
257
 
            self.cur_player=1
258
 
            self.prof.hide()
259
 
            self.player_stone.hide()
260
 
            self.play_next()
261
 
 
262
 
    def play_next(self):
263
 
        if self.cur_player == 1:
264
 
            self.cur_player = 2
265
 
            if self.mode == 1:
266
 
                # IA play
267
 
                self.timericon.gnomecanvas.show()
268
 
                self.play(self.player2, 2, 0)
269
 
            else:
270
 
                # player 2
271
 
                self.stone_init()
272
 
        else:
273
 
            # player 1
274
 
            self.cur_player = 1
275
 
            self.stone_init()
276
 
 
277
 
    def refreshScreen(self):
278
 
        gtk.main_iteration(block=False)
279
 
        pass
280
 
 
281
 
    def play(self, player, numPlayer, column):
282
 
        if self.mode == 1:
283
 
            self.prof.hide()
284
 
        move = player.doMove(self.board, numPlayer, column)
285
 
 
286
 
        if isinstance(move, int) and rules.isMoveLegal(self.board, move):
287
 
            self.board.move(move, numPlayer)
288
 
            self.drawBoard(self.board)
289
 
            return True
290
 
        return False
291
 
 
292
 
    def drawBoard(self, board):
293
 
        stone = self.board.state[self.board.last_move][-1]
294
 
        x = self.board.last_move
295
 
        y = len(self.board.state[self.board.last_move])-1
296
 
        file = "connect4/stone_%d.png" % stone
297
 
 
298
 
        self.stone = self.boardItem.add(
299
 
            gnomecanvas.CanvasPixbuf,
300
 
            pixbuf = gcompris.utils.load_pixmap(file),
301
 
            x=x*(self.boardSize/self.nbColumns),
302
 
            y=0
303
 
            )
304
 
        self.stone.connect("event", self.columnItemEvent, 0)
305
 
        self.countAnim = self.nbLines-y
306
 
        self.timerAnim = gtk.timeout_add(200, self.animTimer)
307
 
        self.timericon.gnomecanvas.show()
308
 
 
309
 
    def animTimer(self):
310
 
        self.countAnim -= 1
311
 
        if self.countAnim > 0:
312
 
            y= self.stone.get_property('y')
313
 
            self.stone.set_property('y', y + (self.boardSize/self.nbColumns))
314
 
            self.timerAnim = gtk.timeout_add(200, self.animTimer)
315
 
        else:
316
 
            self.timerAnim = None
317
 
            self.timericon.gnomecanvas.hide()
318
 
            self.winLine = rules.isWinner(self.board, self.cur_player)
319
 
            if self.winLine:
320
 
                self.winner(self.cur_player)
321
 
            elif rules.isBoardFull(self.board):
322
 
                self.winner(0)
323
 
            else:
324
 
                self.play_next()
325
 
 
326
 
    def winner(self, player):
327
 
        self.gamewon = True
328
 
        self.cur_player = 0
329
 
 
330
 
        # It's a draw, no line to draw
331
 
        if player == 0:
332
 
            gcompris.bonus.display(gcompris.bonus.DRAW, gcompris.bonus.FLOWER)
333
 
            return
334
 
 
335
 
        # Display the winner line
336
 
        self.scores[player-1] += 1
337
 
        self.update_scores()
338
 
 
339
 
        points = ( self.winLine[0][0]*(self.boardSize/self.nbColumns)+self.stoneSize/2,
340
 
                (self.boardSize/self.nbColumns)*(self.nbLines-1-self.winLine[0][1])+self.stoneSize/2,
341
 
                self.winLine[1][0]*(self.boardSize/self.nbColumns)+self.stoneSize/2,
342
 
                (self.boardSize/self.nbColumns)*(self.nbLines-1-self.winLine[1][1])+self.stoneSize/2
343
 
                )
344
 
 
345
 
        self.redLine = self.boardItem.add(
346
 
            gnomecanvas.CanvasLine,
347
 
            fill_color_rgba=0xFF0000FFL,
348
 
            points=points,
349
 
            width_pixels = 8
350
 
            )
351
 
        self.redLine.set_property("cap-style", gtk.gdk.CAP_ROUND)
352
 
        if player == 1 or self.mode == 2:
353
 
            gcompris.bonus.display(gcompris.bonus.WIN, gcompris.bonus.FLOWER)
354
 
        elif player == 2:
355
 
            gcompris.bonus.display(gcompris.bonus.LOOSE, gcompris.bonus.FLOWER)
356