~ubuntu-branches/ubuntu/trusty/gcompris/trusty

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Yann Dirson
  • Date: 2006-12-15 23:08:17 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20061215230817-exr5ks1hd73s3tlk
Tags: 8.2.2-1
* New upstream bugfix release, fixes among other things the support for
  the version of gnucap shipped in etch.
* Add missing dependency on python-gtk2 (Closes: #396523).
* Removed reference to non-existent sound file from memory.c (upstream
  fix - impacts 8.2 as well).  
* Now suggests gnuchess, gnucap, and tuxpaint.
* Updated extended description for the main package.

Show diffs side-by-side

added added

removed removed

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