def __init__(self, cr): NodePath.__init__(self, 'DistributedChineseCheckers') DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel('phase_6/models/golf/checker_game.bam') self.boardNode.reparentTo(self) self.board = ChineseCheckersBoard() self.playerTags = render.attachNewNode('playerTags') self.playerTagList = [] self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.playersTurnBlinker = Sequence() self.yourTurnBlinker = Sequence() self.moveList = [] self.mySquares = [] self.playerSeats = None self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(ToontownGlobals.WallBitmask) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find('**/InventoryButtonRollover') self.clockNode = ToontownTimer() self.clockNode.setPos(1.1599999999999999, 0, -0.82999999999999996) self.clockNode.setScale(0.29999999999999999) self.clockNode.hide() self.playerColors = [ Vec4(0, 0.90000000000000002, 0, 1), Vec4(0.90000000000000002, 0.90000000000000002, 0, 1), Vec4(0.45000000000000001, 0, 0.45000000000000001, 1), Vec4(0.20000000000000001, 0.40000000000000002, 0.80000000000000004, 1), Vec4(1, 0.45000000000000001, 1, 1), Vec4(0.80000000000000004, 0, 0, 1)] self.tintConstant = Vec4(0.25, 0.25, 0.25, 0) self.ghostConstant = Vec4(0, 0, 0, 0.5) self.startingPositions = [ [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [ 10, 11, 12, 13, 23, 24, 25, 35, 36, 46], [ 65, 75, 76, 86, 87, 88, 98, 99, 100, 101], [ 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], [ 74, 84, 85, 95, 96, 97, 107, 108, 109, 110], [ 19, 20, 21, 22, 32, 33, 34, 44, 45, 55]] self.nonOpposingPositions = [] self.knockSound = base.loadSfx('phase_5/audio/sfx/GUI_knock_1.mp3') self.clickSound = base.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.mp3') self.moveSound = base.loadSfx('phase_6/audio/sfx/CC_move.mp3') self.accept('stoppedAsleep', self.handleSleep) ClassicFSM = ClassicFSM State = State import direct.fsm self.fsm = ClassicFSM.ClassicFSM('ChineseCheckers', [ State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, [ 'playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, [ 'gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, [ 'waitingToBegin'])], 'waitingToBegin', 'waitingToBegin') x = self.boardNode.find('**/locators') self.locatorList = x.getChildren() tempList = [] for x in range(0, 121): self.locatorList[x].setTag('GamePeiceLocator', '%d' % x) tempList.append(self.locatorList[x].attachNewNode(CollisionNode('picker%d' % x))) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, 0.115)) for z in self.locatorList: y = loader.loadModel('phase_6/models/golf/checker_marble.bam') z.setColor(0, 0, 0, 0) y.reparentTo(z)
class DistributedChineseCheckers(DistributedNode.DistributedNode): def __init__(self, cr): NodePath.__init__(self, 'DistributedChineseCheckers') DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel('phase_6/models/golf/checker_game.bam') self.boardNode.reparentTo(self) self.board = ChineseCheckersBoard() self.playerTags = render.attachNewNode('playerTags') self.playerTagList = [] self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.playersTurnBlinker = Sequence() self.yourTurnBlinker = Sequence() self.moveList = [] self.mySquares = [] self.playerSeats = None self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(ToontownGlobals.WallBitmask) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find('**/InventoryButtonRollover') self.clockNode = ToontownTimer() self.clockNode.setPos(1.1599999999999999, 0, -0.82999999999999996) self.clockNode.setScale(0.29999999999999999) self.clockNode.hide() self.playerColors = [ Vec4(0, 0.90000000000000002, 0, 1), Vec4(0.90000000000000002, 0.90000000000000002, 0, 1), Vec4(0.45000000000000001, 0, 0.45000000000000001, 1), Vec4(0.20000000000000001, 0.40000000000000002, 0.80000000000000004, 1), Vec4(1, 0.45000000000000001, 1, 1), Vec4(0.80000000000000004, 0, 0, 1)] self.tintConstant = Vec4(0.25, 0.25, 0.25, 0) self.ghostConstant = Vec4(0, 0, 0, 0.5) self.startingPositions = [ [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [ 10, 11, 12, 13, 23, 24, 25, 35, 36, 46], [ 65, 75, 76, 86, 87, 88, 98, 99, 100, 101], [ 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], [ 74, 84, 85, 95, 96, 97, 107, 108, 109, 110], [ 19, 20, 21, 22, 32, 33, 34, 44, 45, 55]] self.nonOpposingPositions = [] self.knockSound = base.loadSfx('phase_5/audio/sfx/GUI_knock_1.mp3') self.clickSound = base.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.mp3') self.moveSound = base.loadSfx('phase_6/audio/sfx/CC_move.mp3') self.accept('stoppedAsleep', self.handleSleep) ClassicFSM = ClassicFSM State = State import direct.fsm self.fsm = ClassicFSM.ClassicFSM('ChineseCheckers', [ State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, [ 'playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, [ 'gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, [ 'waitingToBegin'])], 'waitingToBegin', 'waitingToBegin') x = self.boardNode.find('**/locators') self.locatorList = x.getChildren() tempList = [] for x in range(0, 121): self.locatorList[x].setTag('GamePeiceLocator', '%d' % x) tempList.append(self.locatorList[x].attachNewNode(CollisionNode('picker%d' % x))) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, 0.115)) for z in self.locatorList: y = loader.loadModel('phase_6/models/golf/checker_marble.bam') z.setColor(0, 0, 0, 0) y.reparentTo(z) def setName(self, name): self.name = name def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) if self.table.fsm.getCurrentState().getName() != 'observing': if base.localAvatar.doId in self.table.tableState: self.seatPos = self.table.tableState.index(base.localAvatar.doId) self.playerTags.setPos(self.getPos()) def handleSleep(self, task = None): if self.fsm.getCurrentState().getName() == 'waitingToBegin': self.exitButtonPushed() if task != None: pass 1 def setTableDoId(self, doId): self.tableDoId = doId self.table = self.cr.doId2do[doId] self.table.setTimerFunc(self.startButtonPushed) self.fsm.enterInitialState() self.table.setGameDoId(self.doId) def disable(self): DistributedNode.DistributedNode.disable(self) if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.cleanPlayerTags() def delete(self): DistributedNode.DistributedNode.delete(self) self.table.gameDoId = None self.table.game = None if self.exitButton: self.exitButton.destroy() if self.startButton: self.startButton.destroy() self.clockNode.stop() self.clockNode.hide() self.table.startButtonPushed = None self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.table = None self.cleanPlayerTags() del self.playerTags del self.playerTagList self.playerSeats = None self.yourTurnBlinker.finish() def getTimer(self): self.sendUpdate('requestTimer', []) def setTimer(self, timerEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'waitingToBegin' and not (self.table.fsm.getCurrentState().getName() == 'observing'): self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0 and timerEnd != 0: if timeLeft > 60: timeLeft = 60 self.clockNode.setPos(1.1599999999999999, 0, -0.82999999999999996) self.clockNode.countdown(timeLeft, self.startButtonPushed) self.clockNode.show() else: self.clockNode.stop() self.clockNode.hide() def setTurnTimer(self, turnEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'playing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(turnEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0: self.clockNode.setPos(-0.73999999999999999, 0, -0.20000000000000001) if self.isMyTurn: self.clockNode.countdown(timeLeft, self.doRandomMove) else: self.clockNode.countdown(timeLeft, self.doNothing) self.clockNode.show() def gameStart(self, playerNum): if playerNum != 255: self.playerNum = playerNum self.playerColor = self.playerColors[playerNum - 1] self.moveCameraForGame() playerPos = playerNum - 1 import copy as copy self.nonOpposingPositions = copy.deepcopy(self.startingPositions) if playerPos == 0: self.nonOpposingPositions.pop(0) self.opposingPositions = self.nonOpposingPositions.pop(2) elif playerPos == 1: self.nonOpposingPositions.pop(1) self.opposingPositions = self.nonOpposingPositions.pop(3) elif playerPos == 2: self.nonOpposingPositions.pop(2) self.opposingPositions = self.nonOpposingPositions.pop(4) elif playerPos == 3: self.nonOpposingPositions.pop(3) self.opposingPositions = self.nonOpposingPositions.pop(0) elif playerPos == 4: self.nonOpposingPositions.pop(4) self.opposingPositions = self.nonOpposingPositions.pop(1) elif playerPos == 5: self.nonOpposingPositions.pop(5) self.opposingPositions = self.nonOpposingPositions.pop(2) self.fsm.request('playing') def sendTurn(self, playersTurn): self.playersTurnBlinker.finish() if self.fsm.getCurrentState().getName() == 'playing': if self.playerSeats == None: self.sendUpdate('requestSeatPositions', []) elif playersTurn == self.playerNum: self.isMyTurn = True self.enableTurnScreenText(playersTurn) self.playersTurnBlinker = Sequence() origColor = self.playerColors[playersTurn - 1] self.playersTurnBlinker.append(LerpColorInterval(self.playerTagList[self.playerSeats.index(playersTurn)], 0.40000000000000002, origColor - self.tintConstant - self.ghostConstant, origColor)) self.playersTurnBlinker.append(LerpColorInterval(self.playerTagList[self.playerSeats.index(playersTurn)], 0.40000000000000002, origColor, origColor - self.tintConstant - self.ghostConstant)) self.playersTurnBlinker.loop() def announceSeatPositions(self, playerPos): self.playerSeats = playerPos for x in range(6): pos = self.table.seats[x].getPos(render) renderedPeice = loader.loadModel('phase_6/models/golf/checker_marble.bam') renderedPeice.reparentTo(self.playerTags) renderedPeice.setPos(pos) renderedPeice.setScale(1.5) if x == 1: renderedPeice.setZ(renderedPeice.getZ() + 3.2999999999999998) renderedPeice.setScale(1.3) elif x == 4: renderedPeice.setZ(renderedPeice.getZ() + 3.2999999999999998) renderedPeice.setScale(1.45) else: renderedPeice.setZ(renderedPeice.getZ() + 3.2999999999999998) renderedPeice.hide() self.playerTagList = self.playerTags.getChildren() for x in playerPos: if x != 0: self.playerTagList[playerPos.index(x)].setColor(self.playerColors[x - 1]) self.playerTagList[playerPos.index(x)].show() continue def cleanPlayerTags(self): for x in self.playerTagList: x.removeNode() self.playerTagList = [] self.playerTags.removeNode() def moveCameraForGame(self): if self.table.cameraBoardTrack.isPlaying(): self.table.cameraBoardTrack.finish() rotation = 0 if self.seatPos > 2: if self.playerNum == 1: rotation = 180 elif self.playerNum == 2: rotation = -120 elif self.playerNum == 3: rotation = -60 elif self.playerNum == 4: rotation = 0 elif self.playerNum == 5: rotation = 60 elif self.playerNum == 6: rotation = 120 elif self.playerNum == 1: rotation = 0 elif self.playerNum == 2: rotation = 60 elif self.playerNum == 3: rotation = 120 elif self.playerNum == 4: rotation = 180 elif self.playerNum == 5: rotation = -120 elif self.playerNum == 6: rotation = -60 if rotation == 60 or rotation == -60: int = LerpHprInterval(self.boardNode, 2.5, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) elif rotation == 120 or rotation == -120: int = LerpHprInterval(self.boardNode, 3.5, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) else: int = LerpHprInterval(self.boardNode, 4.2000000000000002, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) int.start() def enterWaitingToBegin(self): if self.table.fsm.getCurrentState().getName() != 'observing': self.enableExitButton() self.enableStartButton() def exitWaitingToBegin(self): if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.startButton: self.startButton.destroy() self.exitButton = None self.clockNode.stop() self.clockNode.hide() def enterPlaying(self): self.inGame = True self.enableScreenText() if self.table.fsm.getCurrentState().getName() != 'observing': self.enableLeaveButton() def exitPlaying(self): self.inGame = False if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None self.playerNum = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.cleanPlayerTags() def enterGameOver(self): pass def exitGameOver(self): pass def exitWaitCountdown(self): self._DistributedChineseCheckers__disableCollisions() self.ignore('trolleyExitButton') self.clockNode.reset() def enableExitButton(self): self.exitButton = DirectButton(relief = None, text = TTLocalizer.ChineseCheckersGetUpButton, text_fg = (1, 1, 0.65000000000000002, 1), text_pos = (0, -0.23000000000000001), text_scale = 0.80000000000000004, image = (self.upButton, self.downButton, self.rolloverButton), image_color = (1, 0, 0, 1), image_scale = (20, 1, 11), pos = (0.92000000000000004, 0, 0.40000000000000002), scale = 0.14999999999999999, command = lambda self = self: self.exitButtonPushed()) def enableScreenText(self): defaultPos = (-0.80000000000000004, -0.40000000000000002) if self.playerNum == 1: message = TTLocalizer.ChineseCheckersColorG color = self.playerColors[0] elif self.playerNum == 2: message = TTLocalizer.ChineseCheckersColorY color = self.playerColors[1] elif self.playerNum == 3: message = TTLocalizer.ChineseCheckersColorP color = self.playerColors[2] elif self.playerNum == 4: message = TTLocalizer.ChineseCheckersColorB color = self.playerColors[3] elif self.playerNum == 5: message = TTLocalizer.ChineseCheckersColorPink color = self.playerColors[4] elif self.playerNum == 6: message = TTLocalizer.ChineseCheckersColorR color = self.playerColors[5] else: message = TTLocalizer.ChineseCheckersColorO color = Vec4(0.0, 0.0, 0.0, 1.0) defaultPos = (-0.80000000000000004, -0.40000000000000002) self.screenText = OnscreenText(text = message, pos = defaultPos, scale = 0.10000000000000001, fg = color, align = TextNode.ACenter, mayChange = 1) def enableStartButton(self): self.startButton = DirectButton(relief = None, text = TTLocalizer.ChineseCheckersStartButton, text_fg = (1, 1, 0.65000000000000002, 1), text_pos = (0, -0.23000000000000001), text_scale = 0.59999999999999998, image = (self.upButton, self.downButton, self.rolloverButton), image_color = (1, 0, 0, 1), image_scale = (20, 1, 11), pos = (0.92000000000000004, 0, 0.10000000000000001), scale = 0.14999999999999999, command = lambda self = self: self.startButtonPushed()) def enableLeaveButton(self): self.leaveButton = DirectButton(relief = None, text = TTLocalizer.ChineseCheckersQuitButton, text_fg = (1, 1, 0.65000000000000002, 1), text_pos = (0, -0.13), text_scale = 0.5, image = (self.upButton, self.downButton, self.rolloverButton), image_color = (1, 0, 0, 1), image_scale = (20, 1, 11), pos = (0.92000000000000004, 0, 0.40000000000000002), scale = 0.14999999999999999, command = lambda self = self: self.exitButtonPushed()) def enableTurnScreenText(self, player): self.yourTurnBlinker.finish() playerOrder = [ 1, 4, 2, 5, 3, 6] message1 = TTLocalizer.ChineseCheckersIts if self.turnText != None: self.turnText.destroy() if player == self.playerNum: message2 = TTLocalizer.ChineseCheckersYourTurn color = (0, 0, 0, 1) elif player == 1: message2 = TTLocalizer.ChineseCheckersGreenTurn color = self.playerColors[0] elif player == 2: message2 = TTLocalizer.ChineseCheckersYellowTurn color = self.playerColors[1] elif player == 3: message2 = TTLocalizer.ChineseCheckersPurpleTurn color = self.playerColors[2] elif player == 4: message2 = TTLocalizer.ChineseCheckersBlueTurn color = self.playerColors[3] elif player == 5: message2 = TTLocalizer.ChineseCheckersPinkTurn color = self.playerColors[4] elif player == 6: message2 = TTLocalizer.ChineseCheckersRedTurn color = self.playerColors[5] self.turnText = OnscreenText(text = message1 + message2, pos = (-0.80000000000000004, -0.5), scale = 0.091999999999999998, fg = color, align = TextNode.ACenter, mayChange = 1) if player == self.playerNum: self.yourTurnBlinker = Sequence() self.yourTurnBlinker.append(LerpScaleInterval(self.turnText, 0.59999999999999998, 1.0449999999999999, 1)) self.yourTurnBlinker.append(LerpScaleInterval(self.turnText, 0.59999999999999998, 1, 1.0449999999999999)) self.yourTurnBlinker.loop() def startButtonPushed(self): self.sendUpdate('requestBegin') self.startButton.hide() self.clockNode.stop() self.clockNode.hide() def exitButtonPushed(self): self.fsm.request('gameOver') self.table.fsm.request('off') self.clockNode.stop() self.clockNode.hide() self.table.sendUpdate('requestExit') def mouseClick(self): messenger.send('wakeup') if self.isMyTurn == True and self.inGame == True: mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(render) if self.myHandler.getNumEntries() > 0: self.myHandler.sortEntries() pickedObj = self.myHandler.getEntry(0).getIntoNodePath() pickedObj = pickedObj.getNetTag('GamePeiceLocator') if pickedObj: self.handleClicked(int(pickedObj)) def handleClicked(self, index): self.sound = Sequence(SoundInterval(self.clickSound)) if self.moveList == []: if index not in self.mySquares: return None self.moveList.append(index) if index in self.opposingPositions: self.isOpposing = True else: self.isOpposing = False self.blinker = Sequence() self.blinker.append(LerpColorInterval(self.locatorList[index], 0.69999999999999996, self.playerColor - self.tintConstant, self.playerColor)) self.blinker.append(LerpColorInterval(self.locatorList[index], 0.69999999999999996, self.playerColor, self.playerColor - self.tintConstant)) self.blinker.loop() self.sound.start() elif self.board.squareList[index].getState() == self.playerNum: for x in self.moveList: self.locatorList[x].setColor(1, 1, 1, 1) self.locatorList[x].hide() self.blinker.finish() self.blinker = Sequence() self.blinker.append(LerpColorInterval(self.locatorList[index], 0.69999999999999996, self.playerColor - self.tintConstant, self.playerColor)) self.blinker.append(LerpColorInterval(self.locatorList[index], 0.69999999999999996, self.playerColor, self.playerColor - self.tintConstant)) self.blinker.loop() self.sound.start() self.locatorList[self.moveList[0]].setColor(self.playerColor) self.locatorList[self.moveList[0]].show() self.moveList = [] self.moveList.append(index) if index in self.opposingPositions: self.isOpposing = True else: self.isOpposing = False elif self.board.squareList[index].getState() != 0: return None elif len(self.moveList) == 1 and self.board.squareList[index].getState() == 0: if index in self.board.squareList[self.moveList[0]].getAdjacent(): for x in self.nonOpposingPositions: if index in x: return None continue self.moveList.append(index) self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.sound.start() if len(self.moveList) >= 1: if index == self.moveList[len(self.moveList) - 1]: for x in self.nonOpposingPositions: if index in x: return None continue if self.existsLegalJumpsFrom(index) == True: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.sound.start() elif self.checkLegalMove(self.board.getSquare(self.moveList[len(self.moveList) - 1]), self.board.getSquare(index)) == True: if index not in self.board.squareList[self.moveList[len(self.moveList) - 1]].getAdjacent(): for x in self.nonOpposingPositions: if self.existsLegalJumpsFrom(index) == False: if index in x: return None index in x self.moveList.append(index) self.locatorList[index].setColor(self.playerColor - self.tintConstant - self.ghostConstant) self.locatorList[index].show() self.sound.start() if self.existsLegalJumpsFrom(index) == False: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False def existsLegalJumpsFrom(self, index): for x in self.board.squareList[index].getAdjacent(): if x == None: continue if x in self.moveList: continue if self.board.getState(x) == 0: continue if self.board.squareList[x].getAdjacent()[self.board.squareList[index].getAdjacent().index(x)] == None: continue if self.board.getState(self.board.squareList[x].getAdjacent()[self.board.squareList[index].getAdjacent().index(x)]) == 0 and self.board.squareList[x].getAdjacent()[self.board.squareList[index].getAdjacent().index(x)] not in self.moveList: return True continue return False def checkLegalMove(self, firstSquare, secondSquare): if secondSquare.getNum() in firstSquare.getAdjacent(): return True else: for x in firstSquare.getAdjacent(): if x == None: continue if self.board.squareList[x].getState() == 0: continue if self.board.squareList[x].getAdjacent()[firstSquare.getAdjacent().index(x)] == secondSquare.getNum(): return True continue return False def d_requestMove(self, moveList): self.sendUpdate('requestMove', [ moveList]) def setGameState(self, tableState, moveList): if moveList != []: self.animatePeice(tableState, moveList) else: self.updateGameState(tableState) def updateGameState(self, squares): self.board.setStates(squares) self.mySquares = [] messenger.send('wakeup') for x in range(121): self.locatorList[x].clearColor() owner = self.board.squareList[x].getState() if owner == self.playerNum: self.mySquares.append(x) if owner == 0: self.locatorList[x].hide() else: self.locatorList[x].show() if owner == 1: self.locatorList[x].setColor(self.playerColors[0]) continue if owner == 2: self.locatorList[x].setColor(self.playerColors[1]) continue if owner == 3: self.locatorList[x].setColor(self.playerColors[2]) continue if owner == 4: self.locatorList[x].setColor(self.playerColors[3]) continue if owner == 5: self.locatorList[x].setColor(self.playerColors[4]) continue if owner == 6: self.locatorList[x].setColor(self.playerColors[5]) continue self.mySquares.sort() self.checkForWin() def animatePeice(self, tableState, moveList): messenger.send('wakeup') gamePeiceForAnimation = loader.loadModel('phase_6/models/golf/checker_marble.bam') gamePeiceForAnimation.setColor(self.locatorList[moveList[0]].getColor()) gamePeiceForAnimation.reparentTo(self.boardNode) gamePeiceForAnimation.setPos(self.locatorList[moveList[0]].getPos()) self.locatorList[moveList[0]].hide() checkersPeiceTrack = Sequence() length = len(moveList) for x in range(length - 1): checkersPeiceTrack.append(Parallel(SoundInterval(self.moveSound), ProjectileInterval(gamePeiceForAnimation, endPos = self.locatorList[moveList[x + 1]].getPos(), duration = 0.5))) checkersPeiceTrack.append(Func(gamePeiceForAnimation.removeNode)) checkersPeiceTrack.append(Func(self.updateGameState, tableState)) checkersPeiceTrack.start() def checkForWin(self): if self.playerNum == 1: if self.mySquares == self.startingPositions[3]: self.sendUpdate('requestWin', []) elif self.playerNum == 2: if self.mySquares == self.startingPositions[4]: self.sendUpdate('requestWin', []) elif self.playerNum == 3: if self.mySquares == self.startingPositions[5]: self.sendUpdate('requestWin', []) elif self.playerNum == 4: if self.mySquares == self.startingPositions[0]: self.sendUpdate('requestWin', []) elif self.playerNum == 5: if self.mySquares == self.startingPositions[1]: self.sendUpdate('requestWin', []) elif self.playerNum == 6: if self.mySquares == self.startingPositions[2]: self.sendUpdate('requestWin', []) def announceWin(self, avId): self.fsm.request('gameOver') def doRandomMove(self): if len(self.moveList) >= 2: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.playSound = Sequence(SoundInterval(self.knockSound)) self.playSound.start() else: import random as random move = [] foundLegal = False self.blinker.pause() self.numRandomMoves += 1 while not foundLegal: x = random.randint(0, 9) for y in self.board.getAdjacent(self.mySquares[x]): if y != None and self.board.getState(y) == 0: for zz in self.nonOpposingPositions: if y not in zz: move.append(self.mySquares[x]) move.append(y) foundLegal = True break continue break continue if move == []: pass 1 playSound = Sequence(SoundInterval(self.knockSound)) playSound.start() self.d_requestMove(move) self.moveList = [] self.isMyTurn = False if self.numRandomMoves >= 5: self.exitButtonPushed() def doNothing(self): pass
def __init__(self, cr): NodePath.__init__(self, 'DistributedChineseCheckers') DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel('phase_6/models/golf/checker_game.bam') self.boardNode.reparentTo(self) self.board = ChineseCheckersBoard() self.playerTags = render.attachNewNode('playerTags') self.playerTagList = [] self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.playersTurnBlinker = Sequence() self.yourTurnBlinker = Sequence() self.moveList = [] self.mySquares = [] self.playerSeats = None self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(ToontownGlobals.WallBitmask) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find('**/InventoryButtonRollover') self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() self.playerColors = [Vec4(0, 0.9, 0, 1), Vec4(0.9, 0.9, 0, 1), Vec4(0.45, 0, 0.45, 1), Vec4(0.2, 0.4, 0.8, 1), Vec4(1, 0.45, 1, 1), Vec4(0.8, 0, 0, 1)] self.tintConstant = Vec4(0.25, 0.25, 0.25, 0) self.ghostConstant = Vec4(0, 0, 0, 0.5) self.startingPositions = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 23, 24, 25, 35, 36, 46], [65, 75, 76, 86, 87, 88, 98, 99, 100, 101], [111, 112, 113, 114, 115, 116, 117, 118, 119, 120], [74, 84, 85, 95, 96, 97, 107, 108, 109, 110], [19, 20, 21, 22, 32, 33, 34, 44, 45, 55]] self.nonOpposingPositions = [] self.knockSound = base.loadSfx('phase_5/audio/sfx/GUI_knock_1.ogg') self.clickSound = base.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.ogg') self.moveSound = base.loadSfx('phase_6/audio/sfx/CC_move.ogg') self.accept('stoppedAsleep', self.handleSleep) from direct.fsm import ClassicFSM, State self.fsm = ClassicFSM.ClassicFSM('ChineseCheckers', [State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, ['playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, ['gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, ['waitingToBegin'])], 'waitingToBegin', 'waitingToBegin') x = self.boardNode.find('**/locators') self.locatorList = x.getChildren() tempList = [] for x in xrange(0, 121): self.locatorList[x].setTag('GamePeiceLocator', '%d' % x) tempList.append(self.locatorList[x].attachNewNode(CollisionNode('picker%d' % x))) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, 0.115)) for z in self.locatorList: y = loader.loadModel('phase_6/models/golf/checker_marble.bam') z.setColor(0, 0, 0, 0) y.reparentTo(z) return
class DistributedChineseCheckers(DistributedNode.DistributedNode): def __init__(self, cr): NodePath.__init__(self, 'DistributedChineseCheckers') DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel('phase_6/models/golf/checker_game.bam') self.boardNode.reparentTo(self) self.board = ChineseCheckersBoard() self.playerTags = render.attachNewNode('playerTags') self.playerTagList = [] self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.playersTurnBlinker = Sequence() self.yourTurnBlinker = Sequence() self.moveList = [] self.mySquares = [] self.playerSeats = None self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(ToontownGlobals.WallBitmask) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') self.upButton = self.buttonModels.find('**//InventoryButtonUp') self.downButton = self.buttonModels.find('**/InventoryButtonDown') self.rolloverButton = self.buttonModels.find('**/InventoryButtonRollover') self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() self.playerColors = [Vec4(0, 0.9, 0, 1), Vec4(0.9, 0.9, 0, 1), Vec4(0.45, 0, 0.45, 1), Vec4(0.2, 0.4, 0.8, 1), Vec4(1, 0.45, 1, 1), Vec4(0.8, 0, 0, 1)] self.tintConstant = Vec4(0.25, 0.25, 0.25, 0) self.ghostConstant = Vec4(0, 0, 0, 0.5) self.startingPositions = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 23, 24, 25, 35, 36, 46], [65, 75, 76, 86, 87, 88, 98, 99, 100, 101], [111, 112, 113, 114, 115, 116, 117, 118, 119, 120], [74, 84, 85, 95, 96, 97, 107, 108, 109, 110], [19, 20, 21, 22, 32, 33, 34, 44, 45, 55]] self.nonOpposingPositions = [] self.knockSound = base.loadSfx('phase_5/audio/sfx/GUI_knock_1.ogg') self.clickSound = base.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.ogg') self.moveSound = base.loadSfx('phase_6/audio/sfx/CC_move.ogg') self.accept('stoppedAsleep', self.handleSleep) from direct.fsm import ClassicFSM, State self.fsm = ClassicFSM.ClassicFSM('ChineseCheckers', [State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, ['playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, ['gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, ['waitingToBegin'])], 'waitingToBegin', 'waitingToBegin') x = self.boardNode.find('**/locators') self.locatorList = x.getChildren() tempList = [] for x in xrange(0, 121): self.locatorList[x].setTag('GamePeiceLocator', '%d' % x) tempList.append(self.locatorList[x].attachNewNode(CollisionNode('picker%d' % x))) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, 0.115)) for z in self.locatorList: y = loader.loadModel('phase_6/models/golf/checker_marble.bam') z.setColor(0, 0, 0, 0) y.reparentTo(z) return def setName(self, name): self.name = name def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) if self.table.fsm.getCurrentState().getName() != 'observing': if base.localAvatar.doId in self.table.tableState: self.seatPos = self.table.tableState.index(base.localAvatar.doId) self.playerTags.setPos(self.getPos()) def handleSleep(self, task = None): if self.fsm.getCurrentState().getName() == 'waitingToBegin': self.exitButtonPushed() if task != None: task.done return def setTableDoId(self, doId): self.tableDoId = doId self.table = self.cr.doId2do[doId] self.table.setTimerFunc(self.startButtonPushed) self.fsm.enterInitialState() self.table.setGameDoId(self.doId) def disable(self): DistributedNode.DistributedNode.disable(self) if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.cleanPlayerTags() return def delete(self): DistributedNode.DistributedNode.delete(self) self.table.gameDoId = None self.table.game = None if self.exitButton: self.exitButton.destroy() if self.startButton: self.startButton.destroy() self.clockNode.stop() self.clockNode.hide() self.table.startButtonPushed = None self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.table = None self.cleanPlayerTags() del self.playerTags del self.playerTagList self.playerSeats = None self.yourTurnBlinker.finish() return def getTimer(self): self.sendUpdate('requestTimer', []) def setTimer(self, timerEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'waitingToBegin' and not self.table.fsm.getCurrentState().getName() == 'observing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0 and timerEnd != 0: if timeLeft > 60: timeLeft = 60 self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.countdown(timeLeft, self.startButtonPushed) self.clockNode.show() else: self.clockNode.stop() self.clockNode.hide() return def setTurnTimer(self, turnEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState().getName() == 'playing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(turnEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0: self.clockNode.setPos(-.74, 0, -0.2) if self.isMyTurn: self.clockNode.countdown(timeLeft, self.doRandomMove) else: self.clockNode.countdown(timeLeft, self.doNothing) self.clockNode.show() return def gameStart(self, playerNum): if playerNum != 255: self.playerNum = playerNum self.playerColor = self.playerColors[playerNum - 1] self.moveCameraForGame() playerPos = playerNum - 1 import copy self.nonOpposingPositions = copy.deepcopy(self.startingPositions) if playerPos == 0: self.nonOpposingPositions.pop(0) self.opposingPositions = self.nonOpposingPositions.pop(2) elif playerPos == 1: self.nonOpposingPositions.pop(1) self.opposingPositions = self.nonOpposingPositions.pop(3) elif playerPos == 2: self.nonOpposingPositions.pop(2) self.opposingPositions = self.nonOpposingPositions.pop(4) elif playerPos == 3: self.nonOpposingPositions.pop(3) self.opposingPositions = self.nonOpposingPositions.pop(0) elif playerPos == 4: self.nonOpposingPositions.pop(4) self.opposingPositions = self.nonOpposingPositions.pop(1) elif playerPos == 5: self.nonOpposingPositions.pop(5) self.opposingPositions = self.nonOpposingPositions.pop(2) self.fsm.request('playing') def sendTurn(self, playersTurn): self.playersTurnBlinker.finish() if self.fsm.getCurrentState().getName() == 'playing': if self.playerSeats == None: self.sendUpdate('requestSeatPositions', []) else: if playersTurn == self.playerNum: self.isMyTurn = True self.enableTurnScreenText(playersTurn) self.playersTurnBlinker = Sequence() origColor = self.playerColors[playersTurn - 1] self.playersTurnBlinker.append(LerpColorInterval(self.playerTagList[self.playerSeats.index(playersTurn)], 0.4, origColor - self.tintConstant - self.ghostConstant, origColor)) self.playersTurnBlinker.append(LerpColorInterval(self.playerTagList[self.playerSeats.index(playersTurn)], 0.4, origColor, origColor - self.tintConstant - self.ghostConstant)) self.playersTurnBlinker.loop() return def announceSeatPositions(self, playerPos): self.playerSeats = playerPos for x in xrange(6): pos = self.table.seats[x].getPos(render) renderedPeice = loader.loadModel('phase_6/models/golf/checker_marble.bam') renderedPeice.reparentTo(self.playerTags) renderedPeice.setPos(pos) renderedPeice.setScale(1.5) if x == 1: renderedPeice.setZ(renderedPeice.getZ() + 3.3) renderedPeice.setScale(1.3) elif x == 4: renderedPeice.setZ(renderedPeice.getZ() + 3.3) renderedPeice.setScale(1.45) else: renderedPeice.setZ(renderedPeice.getZ() + 3.3) renderedPeice.hide() self.playerTagList = self.playerTags.getChildren() for x in playerPos: if x != 0: self.playerTagList[playerPos.index(x)].setColor(self.playerColors[x - 1]) self.playerTagList[playerPos.index(x)].show() def cleanPlayerTags(self): for x in self.playerTagList: x.removeNode() self.playerTagList = [] self.playerTags.removeNode() def moveCameraForGame(self): if self.table.cameraBoardTrack.isPlaying(): self.table.cameraBoardTrack.finish() rotation = 0 if self.seatPos > 2: if self.playerNum == 1: rotation = 180 elif self.playerNum == 2: rotation = -120 elif self.playerNum == 3: rotation = -60 elif self.playerNum == 4: rotation = 0 elif self.playerNum == 5: rotation = 60 elif self.playerNum == 6: rotation = 120 elif self.playerNum == 1: rotation = 0 elif self.playerNum == 2: rotation = 60 elif self.playerNum == 3: rotation = 120 elif self.playerNum == 4: rotation = 180 elif self.playerNum == 5: rotation = -120 elif self.playerNum == 6: rotation = -60 if rotation == 60 or rotation == -60: int = LerpHprInterval(self.boardNode, 2.5, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) elif rotation == 120 or rotation == -120: int = LerpHprInterval(self.boardNode, 3.5, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) else: int = LerpHprInterval(self.boardNode, 4.2, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) int.start() def enterWaitingToBegin(self): if self.table.fsm.getCurrentState().getName() != 'observing': self.enableExitButton() self.enableStartButton() def exitWaitingToBegin(self): if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.startButton: self.startButton.destroy() self.exitButton = None self.clockNode.stop() self.clockNode.hide() return def enterPlaying(self): self.inGame = True self.enableScreenText() if self.table.fsm.getCurrentState().getName() != 'observing': self.enableLeaveButton() def exitPlaying(self): self.inGame = False if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None self.playerNum = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.cleanPlayerTags() return def enterGameOver(self): pass def exitGameOver(self): pass def exitWaitCountdown(self): self.__disableCollisions() self.ignore('trolleyExitButton') self.clockNode.reset() def enableExitButton(self): self.exitButton = DirectButton(relief=None, text=TTLocalizer.ChineseCheckersGetUpButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.4), scale=0.15, command=lambda self = self: self.exitButtonPushed()) return def enableScreenText(self): defaultPos = (-.8, -0.4) if self.playerNum == 1: message = TTLocalizer.ChineseCheckersColorG color = self.playerColors[0] elif self.playerNum == 2: message = TTLocalizer.ChineseCheckersColorY color = self.playerColors[1] elif self.playerNum == 3: message = TTLocalizer.ChineseCheckersColorP color = self.playerColors[2] elif self.playerNum == 4: message = TTLocalizer.ChineseCheckersColorB color = self.playerColors[3] elif self.playerNum == 5: message = TTLocalizer.ChineseCheckersColorPink color = self.playerColors[4] elif self.playerNum == 6: message = TTLocalizer.ChineseCheckersColorR color = self.playerColors[5] else: message = TTLocalizer.ChineseCheckersColorO color = Vec4(0.0, 0.0, 0.0, 1.0) defaultPos = (-.8, -0.4) self.screenText = OnscreenText(text=message, pos=defaultPos, scale=0.1, fg=color, align=TextNode.ACenter, mayChange=1) def enableStartButton(self): self.startButton = DirectButton(relief=None, text=TTLocalizer.ChineseCheckersStartButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.6, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.1), scale=0.15, command=lambda self = self: self.startButtonPushed()) return def enableLeaveButton(self): self.leaveButton = DirectButton(relief=None, text=TTLocalizer.ChineseCheckersQuitButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.13), text_scale=0.5, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(0.92, 0, 0.4), scale=0.15, command=lambda self = self: self.exitButtonPushed()) return def enableTurnScreenText(self, player): self.yourTurnBlinker.finish() playerOrder = [1, 4, 2, 5, 3, 6] message1 = TTLocalizer.ChineseCheckersIts if self.turnText != None: self.turnText.destroy() if player == self.playerNum: message2 = TTLocalizer.ChineseCheckersYourTurn color = (0, 0, 0, 1) elif player == 1: message2 = TTLocalizer.ChineseCheckersGreenTurn color = self.playerColors[0] elif player == 2: message2 = TTLocalizer.ChineseCheckersYellowTurn color = self.playerColors[1] elif player == 3: message2 = TTLocalizer.ChineseCheckersPurpleTurn color = self.playerColors[2] elif player == 4: message2 = TTLocalizer.ChineseCheckersBlueTurn color = self.playerColors[3] elif player == 5: message2 = TTLocalizer.ChineseCheckersPinkTurn color = self.playerColors[4] elif player == 6: message2 = TTLocalizer.ChineseCheckersRedTurn color = self.playerColors[5] self.turnText = OnscreenText(text=message1 + message2, pos=(-0.8, -0.5), scale=0.092, fg=color, align=TextNode.ACenter, mayChange=1) if player == self.playerNum: self.yourTurnBlinker = Sequence() self.yourTurnBlinker.append(LerpScaleInterval(self.turnText, 0.6, 1.045, 1)) self.yourTurnBlinker.append(LerpScaleInterval(self.turnText, 0.6, 1, 1.045)) self.yourTurnBlinker.loop() return def startButtonPushed(self): self.sendUpdate('requestBegin') self.startButton.hide() self.clockNode.stop() self.clockNode.hide() def exitButtonPushed(self): self.fsm.request('gameOver') self.table.fsm.request('off') self.clockNode.stop() self.clockNode.hide() self.table.sendUpdate('requestExit') def mouseClick(self): messenger.send('wakeup') if self.isMyTurn == True and self.inGame == True: mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(render) if self.myHandler.getNumEntries() > 0: self.myHandler.sortEntries() pickedObj = self.myHandler.getEntry(0).getIntoNodePath() pickedObj = pickedObj.getNetTag('GamePeiceLocator') if pickedObj: self.handleClicked(int(pickedObj)) def handleClicked(self, index): self.sound = Sequence(SoundInterval(self.clickSound)) if self.moveList == []: if index not in self.mySquares: return self.moveList.append(index) if index in self.opposingPositions: self.isOpposing = True else: self.isOpposing = False self.blinker = Sequence() self.blinker.append(LerpColorInterval(self.locatorList[index], 0.7, self.playerColor - self.tintConstant, self.playerColor)) self.blinker.append(LerpColorInterval(self.locatorList[index], 0.7, self.playerColor, self.playerColor - self.tintConstant)) self.blinker.loop() self.sound.start() elif self.board.squareList[index].getState() == self.playerNum: for x in self.moveList: self.locatorList[x].setColor(1, 1, 1, 1) self.locatorList[x].hide() self.blinker.finish() self.blinker = Sequence() self.blinker.append(LerpColorInterval(self.locatorList[index], 0.7, self.playerColor - self.tintConstant, self.playerColor)) self.blinker.append(LerpColorInterval(self.locatorList[index], 0.7, self.playerColor, self.playerColor - self.tintConstant)) self.blinker.loop() self.sound.start() self.locatorList[self.moveList[0]].setColor(self.playerColor) self.locatorList[self.moveList[0]].show() self.moveList = [] self.moveList.append(index) if index in self.opposingPositions: self.isOpposing = True else: self.isOpposing = False elif self.board.squareList[index].getState() != 0: return else: if len(self.moveList) == 1 and self.board.squareList[index].getState() == 0: if index in self.board.squareList[self.moveList[0]].getAdjacent(): for x in self.nonOpposingPositions: if index in x: return self.moveList.append(index) self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.sound.start() if len(self.moveList) >= 1: if index == self.moveList[len(self.moveList) - 1]: for x in self.nonOpposingPositions: if index in x: return if self.existsLegalJumpsFrom(index) == True: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.sound.start() elif self.checkLegalMove(self.board.getSquare(self.moveList[len(self.moveList) - 1]), self.board.getSquare(index)) == True: if index not in self.board.squareList[self.moveList[len(self.moveList) - 1]].getAdjacent(): for x in self.nonOpposingPositions: if self.existsLegalJumpsFrom(index) == False: if index in x: return self.moveList.append(index) self.locatorList[index].setColor(self.playerColor - self.tintConstant - self.ghostConstant) self.locatorList[index].show() self.sound.start() if self.existsLegalJumpsFrom(index) == False: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False def existsLegalJumpsFrom(self, index): for x in self.board.squareList[index].getAdjacent(): if x == None: pass elif x in self.moveList: pass elif self.board.getState(x) == 0: pass elif self.board.squareList[x].getAdjacent()[self.board.squareList[index].getAdjacent().index(x)] == None: pass elif self.board.getState(self.board.squareList[x].getAdjacent()[self.board.squareList[index].getAdjacent().index(x)]) == 0 and self.board.squareList[x].getAdjacent()[self.board.squareList[index].getAdjacent().index(x)] not in self.moveList: return True return False def checkLegalMove(self, firstSquare, secondSquare): if secondSquare.getNum() in firstSquare.getAdjacent(): return True else: for x in firstSquare.getAdjacent(): if x == None: pass elif self.board.squareList[x].getState() == 0: pass elif self.board.squareList[x].getAdjacent()[firstSquare.getAdjacent().index(x)] == secondSquare.getNum(): return True return False return def d_requestMove(self, moveList): self.sendUpdate('requestMove', [moveList]) def setGameState(self, tableState, moveList): if moveList != []: self.animatePeice(tableState, moveList) else: self.updateGameState(tableState) def updateGameState(self, squares): self.board.setStates(squares) self.mySquares = [] messenger.send('wakeup') for x in xrange(121): self.locatorList[x].clearColor() owner = self.board.squareList[x].getState() if owner == self.playerNum: self.mySquares.append(x) if owner == 0: self.locatorList[x].hide() else: self.locatorList[x].show() if owner == 1: self.locatorList[x].setColor(self.playerColors[0]) elif owner == 2: self.locatorList[x].setColor(self.playerColors[1]) elif owner == 3: self.locatorList[x].setColor(self.playerColors[2]) elif owner == 4: self.locatorList[x].setColor(self.playerColors[3]) elif owner == 5: self.locatorList[x].setColor(self.playerColors[4]) elif owner == 6: self.locatorList[x].setColor(self.playerColors[5]) self.mySquares.sort() self.checkForWin() def animatePeice(self, tableState, moveList): messenger.send('wakeup') gamePeiceForAnimation = loader.loadModel('phase_6/models/golf/checker_marble.bam') gamePeiceForAnimation.setColor(self.locatorList[moveList[0]].getColor()) gamePeiceForAnimation.reparentTo(self.boardNode) gamePeiceForAnimation.setPos(self.locatorList[moveList[0]].getPos()) self.locatorList[moveList[0]].hide() checkersPeiceTrack = Sequence() length = len(moveList) for x in xrange(length - 1): checkersPeiceTrack.append(Parallel(SoundInterval(self.moveSound), ProjectileInterval(gamePeiceForAnimation, endPos=self.locatorList[moveList[x + 1]].getPos(), duration=0.5))) checkersPeiceTrack.append(Func(gamePeiceForAnimation.removeNode)) checkersPeiceTrack.append(Func(self.updateGameState, tableState)) checkersPeiceTrack.start() def checkForWin(self): if self.playerNum == 1: if self.mySquares == self.startingPositions[3]: self.sendUpdate('requestWin', []) elif self.playerNum == 2: if self.mySquares == self.startingPositions[4]: self.sendUpdate('requestWin', []) elif self.playerNum == 3: if self.mySquares == self.startingPositions[5]: self.sendUpdate('requestWin', []) elif self.playerNum == 4: if self.mySquares == self.startingPositions[0]: self.sendUpdate('requestWin', []) elif self.playerNum == 5: if self.mySquares == self.startingPositions[1]: self.sendUpdate('requestWin', []) elif self.playerNum == 6: if self.mySquares == self.startingPositions[2]: self.sendUpdate('requestWin', []) def announceWin(self, avId): self.fsm.request('gameOver') def doRandomMove(self): if len(self.moveList) >= 2: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.playSound = Sequence(SoundInterval(self.knockSound)) self.playSound.start() else: import random move = [] foundLegal = False self.blinker.pause() self.numRandomMoves += 1 while not foundLegal: x = random.randint(0, 9) for y in self.board.getAdjacent(self.mySquares[x]): if y != None and self.board.getState(y) == 0: for zz in self.nonOpposingPositions: if y not in zz: move.append(self.mySquares[x]) move.append(y) foundLegal = True break break if move == []: pass playSound = Sequence(SoundInterval(self.knockSound)) playSound.start() self.d_requestMove(move) self.moveList = [] self.isMyTurn = False if self.numRandomMoves >= 5: self.exitButtonPushed() return def doNothing(self): pass
def __init__(self, cr): NodePath.__init__(self, "DistributedChineseCheckers") DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel( "phase_6/models/golf/checker_game.bam") self.boardNode.reparentTo(self) #self.boardNode.setZ(2.85) #self.boardNode.setZ(3.5) #self.boardNode.setZ(0.3) #self.boardNode.setZ(self.getZ()) self.board = ChineseCheckersBoard() self.playerTags = render.attachNewNode("playerTags") self.playerTagList = [] #game variables self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.playersTurnBlinker = Sequence() self.yourTurnBlinker = Sequence() self.moveList = [] self.mySquares = [] self.playerSeats = None ###self.playerTags = [None, None, None, None, None, None #Mouse picking required stuff self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(ToontownGlobals.WallBitmask) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel( "phase_3.5/models/gui/inventory_gui") self.upButton = self.buttonModels.find("**//InventoryButtonUp") self.downButton = self.buttonModels.find("**/InventoryButtonDown") self.rolloverButton = self.buttonModels.find( "**/InventoryButtonRollover") self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() #[0] GREEN [1] YELLOW [2] PURPLE [3] BLUE [4] PINK [5] RED self.playerColors = [ Vec4(0, .90, 0, 1), Vec4(.9, .9, 0, 1), Vec4(.45, 0, .45, 1), Vec4(.2, .4, .8, 1), Vec4(1, .45, 1, 1), Vec4(.8, 0, 0, 1) ] self.tintConstant = Vec4(.25, .25, .25, 0) self.ghostConstant = Vec4(0, 0, 0, .5) #starting positions are used to check and see if a player has gone into #his opposing players starting position, thus to tell if he won. self.startingPositions = [ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 23, 24, 25, 35, 36, 46], [65, 75, 76, 86, 87, 88, 98, 99, 100, 101], [111, 112, 113, 114, 115, 116, 117, 118, 119, 120], [74, 84, 85, 95, 96, 97, 107, 108, 109, 110], [19, 20, 21, 22, 32, 33, 34, 44, 45, 55] ] self.nonOpposingPositions = [] self.knockSound = base.loadSfx("phase_5/audio/sfx/GUI_knock_1.mp3") self.clickSound = base.loadSfx( "phase_3/audio/sfx/GUI_balloon_popup.mp3") self.moveSound = base.loadSfx("phase_6/audio/sfx/CC_move.mp3") self.accept('stoppedAsleep', self.handleSleep) #base.setCellsAvailable(base.leftCells + #[base.bottomCells[0]], 0) #base.setCellsAvailable(base.bottomCells,0) ####################### #Fsm and State Data from direct.fsm import ClassicFSM, State self.fsm = ClassicFSM.ClassicFSM( 'ChineseCheckers', [ State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, ['playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, ['gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, ['waitingToBegin']) ], # Initial State 'waitingToBegin', # Final State 'waitingToBegin', ) ######################### #Set up the Board Locators ## x = self.boardNode.find("**/locators") #set up the locator list so we can mess with it self.locatorList = x.getChildren() #tag the locators for "picking" ingame #also add colision spheres for movement tempList = [] for x in range(0, 121): self.locatorList[x].setTag("GamePeiceLocator", "%d" % x) tempList.append(self.locatorList[x].attachNewNode( CollisionNode("picker%d" % x))) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, .115)) for z in self.locatorList: y = loader.loadModel("phase_6/models/golf/checker_marble.bam") z.setColor(0, 0, 0, 0) y.reparentTo(z)
class DistributedChineseCheckers(DistributedNode.DistributedNode): def __init__(self, cr): NodePath.__init__(self, "DistributedChineseCheckers") DistributedNode.DistributedNode.__init__(self, cr) self.cr = cr self.reparentTo(render) self.boardNode = loader.loadModel( "phase_6/models/golf/checker_game.bam") self.boardNode.reparentTo(self) #self.boardNode.setZ(2.85) #self.boardNode.setZ(3.5) #self.boardNode.setZ(0.3) #self.boardNode.setZ(self.getZ()) self.board = ChineseCheckersBoard() self.playerTags = render.attachNewNode("playerTags") self.playerTagList = [] #game variables self.exitButton = None self.inGame = False self.waiting = True self.startButton = None self.playerNum = None self.turnText = None self.isMyTurn = False self.wantTimer = True self.leaveButton = None self.screenText = None self.turnText = None self.exitButton = None self.numRandomMoves = 0 self.blinker = Sequence() self.playersTurnBlinker = Sequence() self.yourTurnBlinker = Sequence() self.moveList = [] self.mySquares = [] self.playerSeats = None ###self.playerTags = [None, None, None, None, None, None #Mouse picking required stuff self.accept('mouse1', self.mouseClick) self.traverser = base.cTrav self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(ToontownGlobals.WallBitmask) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.myHandler = CollisionHandlerQueue() self.traverser.addCollider(self.pickerNP, self.myHandler) self.buttonModels = loader.loadModel( "phase_3.5/models/gui/inventory_gui") self.upButton = self.buttonModels.find("**//InventoryButtonUp") self.downButton = self.buttonModels.find("**/InventoryButtonDown") self.rolloverButton = self.buttonModels.find( "**/InventoryButtonRollover") self.clockNode = ToontownTimer() self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.setScale(0.3) self.clockNode.hide() #[0] GREEN [1] YELLOW [2] PURPLE [3] BLUE [4] PINK [5] RED self.playerColors = [ Vec4(0, .90, 0, 1), Vec4(.9, .9, 0, 1), Vec4(.45, 0, .45, 1), Vec4(.2, .4, .8, 1), Vec4(1, .45, 1, 1), Vec4(.8, 0, 0, 1) ] self.tintConstant = Vec4(.25, .25, .25, 0) self.ghostConstant = Vec4(0, 0, 0, .5) #starting positions are used to check and see if a player has gone into #his opposing players starting position, thus to tell if he won. self.startingPositions = [ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 23, 24, 25, 35, 36, 46], [65, 75, 76, 86, 87, 88, 98, 99, 100, 101], [111, 112, 113, 114, 115, 116, 117, 118, 119, 120], [74, 84, 85, 95, 96, 97, 107, 108, 109, 110], [19, 20, 21, 22, 32, 33, 34, 44, 45, 55] ] self.nonOpposingPositions = [] self.knockSound = base.loadSfx("phase_5/audio/sfx/GUI_knock_1.mp3") self.clickSound = base.loadSfx( "phase_3/audio/sfx/GUI_balloon_popup.mp3") self.moveSound = base.loadSfx("phase_6/audio/sfx/CC_move.mp3") self.accept('stoppedAsleep', self.handleSleep) #base.setCellsAvailable(base.leftCells + #[base.bottomCells[0]], 0) #base.setCellsAvailable(base.bottomCells,0) ####################### #Fsm and State Data from direct.fsm import ClassicFSM, State self.fsm = ClassicFSM.ClassicFSM( 'ChineseCheckers', [ State.State('waitingToBegin', self.enterWaitingToBegin, self.exitWaitingToBegin, ['playing', 'gameOver']), State.State('playing', self.enterPlaying, self.exitPlaying, ['gameOver']), State.State('gameOver', self.enterGameOver, self.exitGameOver, ['waitingToBegin']) ], # Initial State 'waitingToBegin', # Final State 'waitingToBegin', ) ######################### #Set up the Board Locators ## x = self.boardNode.find("**/locators") #set up the locator list so we can mess with it self.locatorList = x.getChildren() #tag the locators for "picking" ingame #also add colision spheres for movement tempList = [] for x in range(0, 121): self.locatorList[x].setTag("GamePeiceLocator", "%d" % x) tempList.append(self.locatorList[x].attachNewNode( CollisionNode("picker%d" % x))) tempList[x].node().addSolid(CollisionSphere(0, 0, 0, .115)) for z in self.locatorList: y = loader.loadModel("phase_6/models/golf/checker_marble.bam") z.setColor(0, 0, 0, 0) y.reparentTo(z) #y.show() #y.hide() def setName(self, name): self.name = name def announceGenerate(self): DistributedNode.DistributedNode.announceGenerate(self) if self.table.fsm.getCurrentState().getName() != 'observing': if base.localAvatar.doId in self.table.tableState: # Fix for strange state #TEMP until i find the cause self.seatPos = self.table.tableState.index( base.localAvatar.doId) self.playerTags.setPos(self.getPos()) def handleSleep(self, task=None): if self.fsm.getCurrentState().getName() == "waitingToBegin": self.exitButtonPushed() if task != None: task.done #task.done ########## ##setTableDoId (required broadcast ram) # #Upon construction, sets local pointer to the table, as well as #sets the pointer on the table to itself. #This is necessary to handle events that occur on the table, not #particularly inside of any one game. ### def setTableDoId(self, doId): self.tableDoId = doId self.table = self.cr.doId2do[doId] self.table.setTimerFunc(self.startButtonPushed) self.fsm.enterInitialState() self.table.setGameDoId(self.doId) #self.table.tempCheckers.hide() #self.boardNode.setP(self.table.getP()) ######### ##Disable/Delete #Must be sure to remove/delete any buttons, screen text #that may be on the screen in the event of a chosen ( or asynchrinous ) #disable or deletion - Code redundance here is necessary #being that "disable" is called upon server crash, and delete is #called upon zone exit ### def disable(self): DistributedNode.DistributedNode.disable(self) if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.cleanPlayerTags() ###self.table = None def delete(self): DistributedNode.DistributedNode.delete(self) self.table.gameDoId = None self.table.game = None if self.exitButton: self.exitButton.destroy() if self.startButton: self.startButton.destroy() self.clockNode.stop() self.clockNode.hide() self.table.startButtonPushed = None self.ignore('mouse1') self.ignore('stoppedAsleep') self.fsm = None self.table = None self.cleanPlayerTags() del self.playerTags del self.playerTagList self.playerSeats = None self.yourTurnBlinker.finish() ########## ##Timer Functions #setTimer (broadcast ram required) #setTurnTimer(broadcast ram required) # #setTimer() controlls the timer for game begin, which upon its timout #calls the startButton. # #turnTimer() does just that # #Important to note that both timers run on the same clockNode. ########## def getTimer(self): self.sendUpdate('requestTimer', []) def setTimer(self, timerEnd): #print "TIMEREND! ", timerEnd if self.fsm.getCurrentState() != None and self.fsm.getCurrentState( ).getName() == 'waitingToBegin' and not self.table.fsm.getCurrentState( ).getName() == 'observing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(timerEnd) timeLeft = int(time - globalClock.getRealTime()) if (timeLeft > 0 and timerEnd != 0): if timeLeft > 60: timeLeft = 60 self.clockNode.setPos(1.16, 0, -0.83) self.clockNode.countdown(timeLeft, self.startButtonPushed) self.clockNode.show() else: self.clockNode.stop() self.clockNode.hide() def setTurnTimer(self, turnEnd): if self.fsm.getCurrentState() != None and self.fsm.getCurrentState( ).getName() == 'playing': self.clockNode.stop() time = globalClockDelta.networkToLocalTime(turnEnd) timeLeft = int(time - globalClock.getRealTime()) if timeLeft > 0: self.clockNode.setPos(-.74, 0, -0.20) if self.isMyTurn: self.clockNode.countdown(timeLeft, self.doRandomMove) else: self.clockNode.countdown(timeLeft, self.doNothing) self.clockNode.show() ########### ##Game start(broadcast) and Send Turn (broadcast ram) # #IMPORTANT - 255 is the Uint8 sent to the player when a game starts #to dictate to him that a game is beginning and he is labeled as an observer #for that game - this affects the visual queues for his player color ect. ########## def gameStart(self, playerNum): if playerNum != 255: #observer value self.playerNum = playerNum self.playerColor = self.playerColors[playerNum - 1] self.moveCameraForGame() playerPos = playerNum - 1 import copy self.nonOpposingPositions = copy.deepcopy(self.startingPositions) if playerPos == 0: self.nonOpposingPositions.pop(0) self.opposingPositions = self.nonOpposingPositions.pop(2) elif playerPos == 1: self.nonOpposingPositions.pop(1) self.opposingPositions = self.nonOpposingPositions.pop(3) elif playerPos == 2: self.nonOpposingPositions.pop(2) self.opposingPositions = self.nonOpposingPositions.pop(4) elif playerPos == 3: self.nonOpposingPositions.pop(3) self.opposingPositions = self.nonOpposingPositions.pop(0) elif playerPos == 4: self.nonOpposingPositions.pop(4) self.opposingPositions = self.nonOpposingPositions.pop(1) elif playerPos == 5: self.nonOpposingPositions.pop(5) self.opposingPositions = self.nonOpposingPositions.pop(2) self.fsm.request('playing') def sendTurn(self, playersTurn): self.playersTurnBlinker.finish() if self.fsm.getCurrentState().getName() == 'playing': #print "GETTING HERE!", playersTurn - 1, " LENGTH!!!" , self.playerTagList #self.playerTagList if self.playerSeats == None: self.sendUpdate("requestSeatPositions", []) else: if playersTurn == self.playerNum: self.isMyTurn = True self.enableTurnScreenText(playersTurn) self.playersTurnBlinker = Sequence() origColor = self.playerColors[playersTurn - 1] self.playersTurnBlinker.append( LerpColorInterval( self.playerTagList[self.playerSeats.index( playersTurn)], .4, origColor - self.tintConstant - self.ghostConstant, origColor)) self.playersTurnBlinker.append( LerpColorInterval( self.playerTagList[self.playerSeats.index( playersTurn)], .4, origColor, origColor - self.tintConstant - self.ghostConstant)) self.playersTurnBlinker.loop() def announceSeatPositions(self, playerPos): #print "ANNOUNCESEATPOSITIONS!", playerPos self.playerSeats = playerPos for x in range(6): pos = self.table.seats[x].getPos(render) renderedPeice = loader.loadModel( "phase_6/models/golf/checker_marble.bam") #renderedPeice.setColor(self.playerColors[x-1]) renderedPeice.reparentTo(self.playerTags) renderedPeice.setPos(pos) renderedPeice.setScale(1.5) if x == 1: renderedPeice.setZ(renderedPeice.getZ() + 3.3) renderedPeice.setScale(1.3) elif x == 4: renderedPeice.setZ(renderedPeice.getZ() + 3.3) renderedPeice.setScale(1.45) else: renderedPeice.setZ(renderedPeice.getZ() + 3.3) renderedPeice.hide() self.playerTagList = self.playerTags.getChildren() for x in playerPos: if x != 0: self.playerTagList[playerPos.index(x)].setColor( self.playerColors[x - 1]) self.playerTagList[playerPos.index(x)].show() #if game is already going #if self.fsm.getCurrentState().getName() == 'playing': # if not self.playersTurnBlinker.isPlaying(): # self.playersTurnBlinker = Sequence() # origColor = self.playerColors[playersTurn-1] # self.playersTurnBlinker.append(LerpColorInterval(self.playerTagList[self.playerSeats.index(playersTurn)], .4, origColor - self.tintConstant - self.ghostConstant, origColor)) # self.playersTurnBlinker.append(LerpColorInterval(self.playerTagList[self.playerSeats.index(playersTurn)], .4,origColor, origColor - self.tintConstant - self.ghostConstant)) # self.playersTurnBlinker.loop() def cleanPlayerTags(self): for x in self.playerTagList: x.removeNode() self.playerTagList = [] self.playerTags.removeNode() ########## ##Move camera # #To make camera movement not seem weird (turning 270 degrees example) #Must check the clients orientation between the seatPos and his current H # so that he turns the least possible amount for the camera orientation # # ########## def moveCameraForGame(self): if self.table.cameraBoardTrack.isPlaying(): self.table.cameraBoardTrack.finish() rotation = 0 if self.seatPos > 2: if self.playerNum == 1: rotation = 180 elif self.playerNum == 2: rotation = -120 elif self.playerNum == 3: rotation = -60 elif self.playerNum == 4: rotation = 0 elif self.playerNum == 5: rotation = 60 elif self.playerNum == 6: rotation = 120 else: if self.playerNum == 1: rotation = 0 elif self.playerNum == 2: rotation = 60 elif self.playerNum == 3: rotation = 120 elif self.playerNum == 4: rotation = 180 elif self.playerNum == 5: rotation = -120 elif self.playerNum == 6: rotation = -60 #print self.boardNode.getHpr() # int = LerpHprInterval(camera, 3,Vec3(camera.getH(),camera.getP(),rotation), camera.getHpr()) #self.table.tempCheckers.hide() if rotation == 60 or rotation == -60: int = LerpHprInterval( self.boardNode, 2.5, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) elif rotation == 120 or rotation == -120: int = LerpHprInterval( self.boardNode, 3.5, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) else: int = LerpHprInterval( self.boardNode, 4.2, Vec3(rotation, self.boardNode.getP(), self.boardNode.getR()), self.boardNode.getHpr()) #self.table.tempCheckers.setHpr( Vec3(rotation, self.table.tempCheckers.getP(), self.table.tempCheckers.getR())) int.start() ##################### #FSM Stuff ### def enterWaitingToBegin(self): if self.table.fsm.getCurrentState().getName() != 'observing': self.enableExitButton() self.enableStartButton() def exitWaitingToBegin(self): if self.exitButton: self.exitButton.destroy() self.exitButton = None if self.startButton: self.startButton.destroy() self.exitButton = None self.clockNode.stop() self.clockNode.hide() def enterPlaying(self): self.inGame = True self.enableScreenText() if self.table.fsm.getCurrentState().getName() != 'observing': self.enableLeaveButton() def exitPlaying(self): self.inGame = False if self.leaveButton: self.leaveButton.destroy() self.leavebutton = None self.playerNum = None if self.screenText: self.screenText.destroy() self.screenText = None if self.turnText: self.turnText.destroy() self.turnText = None self.clockNode.stop() self.clockNode.hide() self.cleanPlayerTags() def enterGameOver(self): pass def exitGameOver(self): pass ################################################## # Button Functions and Text ### def exitWaitCountdown(self): self.__disableCollisions() self.ignore("trolleyExitButton") self.clockNode.reset() def enableExitButton(self): self.exitButton = DirectButton( relief=None, text=TTLocalizer.ChineseCheckersGetUpButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.8, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(.92, 0, 0.4), scale=0.15, command=lambda self=self: self.exitButtonPushed(), ) return def enableScreenText(self): defaultPos = (-.80, -0.40) if self.playerNum == 1: message = TTLocalizer.ChineseCheckersColorG color = self.playerColors[0] elif self.playerNum == 2: message = TTLocalizer.ChineseCheckersColorY color = self.playerColors[1] elif self.playerNum == 3: message = TTLocalizer.ChineseCheckersColorP color = self.playerColors[2] elif self.playerNum == 4: message = TTLocalizer.ChineseCheckersColorB color = self.playerColors[3] elif self.playerNum == 5: message = TTLocalizer.ChineseCheckersColorPink color = self.playerColors[4] elif self.playerNum == 6: message = TTLocalizer.ChineseCheckersColorR color = self.playerColors[5] else: message = TTLocalizer.ChineseCheckersColorO color = Vec4(0.0, 0.0, 0.0, 1.0) defaultPos = (-.80, -0.40) self.screenText = OnscreenText(text=message, pos=defaultPos, scale=0.10, fg=color, align=TextNode.ACenter, mayChange=1) def enableStartButton(self): self.startButton = DirectButton( relief=None, text=TTLocalizer.ChineseCheckersStartButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.23), text_scale=0.6, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(.92, 0, 0.1), scale=0.15, command=lambda self=self: self.startButtonPushed(), ) return def enableLeaveButton(self): self.leaveButton = DirectButton( relief=None, text=TTLocalizer.ChineseCheckersQuitButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -.13), text_scale=0.5, image=(self.upButton, self.downButton, self.rolloverButton), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(.92, 0, 0.4), scale=0.15, command=lambda self=self: self.exitButtonPushed(), ) return def enableTurnScreenText(self, player): self.yourTurnBlinker.finish() playerOrder = [1, 4, 2, 5, 3, 6] message1 = TTLocalizer.ChineseCheckersIts if (self.turnText != None): self.turnText.destroy() #print "player ---",player #print "playerNum --" ,self.playerNum if player == self.playerNum: message2 = TTLocalizer.ChineseCheckersYourTurn color = (0, 0, 0, 1) else: if player == 1: message2 = TTLocalizer.ChineseCheckersGreenTurn color = self.playerColors[0] elif player == 2: message2 = TTLocalizer.ChineseCheckersYellowTurn color = self.playerColors[1] elif player == 3: message2 = TTLocalizer.ChineseCheckersPurpleTurn color = self.playerColors[2] elif player == 4: message2 = TTLocalizer.ChineseCheckersBlueTurn color = self.playerColors[3] elif player == 5: message2 = TTLocalizer.ChineseCheckersPinkTurn color = self.playerColors[4] elif player == 6: message2 = TTLocalizer.ChineseCheckersRedTurn color = self.playerColors[5] self.turnText = OnscreenText(text=message1 + message2, pos=(-0.80, -0.50), scale=0.092, fg=color, align=TextNode.ACenter, mayChange=1) if player == self.playerNum: self.yourTurnBlinker = Sequence() self.yourTurnBlinker.append( LerpScaleInterval(self.turnText, .6, 1.045, 1)) self.yourTurnBlinker.append( LerpScaleInterval(self.turnText, .6, 1, 1.045)) self.yourTurnBlinker.loop() #This function is called either if the player clicks on it (to begin a game) #or if the game begin timer runs out. (timer is in sync with server so results should be # + or - ~ 1 second def startButtonPushed(self): self.sendUpdate("requestBegin") self.startButton.hide() self.clockNode.stop() self.clockNode.hide() def exitButtonPushed(self): self.fsm.request('gameOver') self.table.fsm.request('off') self.clockNode.stop() self.clockNode.hide() self.table.sendUpdate("requestExit") ########## #Mouse Picking/clicking operations # # #These functions handle all of the mous clicking functions #Its best to look through the code for comments for it to make #the most sense. # #The self.blinker that is referenced in these functions, is a cosmetic #colorLerp that gives the player a visual feedback as to what checkers peice #he has (currently) selected. ########## def mouseClick(self): messenger.send('wakeup') if self.isMyTurn == True and self.inGame == True: #cant pick stuff if its not your turn mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(render) if self.myHandler.getNumEntries() > 0: self.myHandler.sortEntries() #get the closest Object pickedObj = self.myHandler.getEntry(0).getIntoNodePath() #will return the INT for the locator node closest parent pickedObj = pickedObj.getNetTag("GamePeiceLocator") if pickedObj: #make sure something actually was "picked" self.handleClicked(int(pickedObj)) def handleClicked(self, index): #self.inOpposing = False self.sound = Sequence(SoundInterval( self.clickSound)) #You clicked something play the click sound #First Moved Square if self.moveList == []: #check if owned if not index in self.mySquares: return self.moveList.append(index) #put this on the movelist if index in self.opposingPositions: self.isOpposing = True else: self.isOpposing = False #Start blinking the new "active" peice self.blinker = Sequence() self.blinker.append( LerpColorInterval(self.locatorList[index], .7, self.playerColor - self.tintConstant, self.playerColor)) self.blinker.append( LerpColorInterval(self.locatorList[index], .7, self.playerColor, self.playerColor - self.tintConstant)) self.blinker.loop() self.sound.start() else: #Check if the square clicked is not open, if so break out not legal #If the Player Clicks on one of his peices after an array of clicking new peices #will reset his "move" and start a new movelist if self.board.squareList[index].getState() == self.playerNum: for x in self.moveList: #clear the already selected Nodes back to white self.locatorList[x].setColor(1, 1, 1, 1) self.locatorList[x].hide() #Blinker is the color lerp for the peice "flashing" - need to stop the flashing of the old one self.blinker.finish() self.blinker = Sequence() self.blinker.append( LerpColorInterval(self.locatorList[index], .7, self.playerColor - self.tintConstant, self.playerColor)) self.blinker.append( LerpColorInterval(self.locatorList[index], .7, self.playerColor, self.playerColor - self.tintConstant)) self.blinker.loop() self.sound.start() #Swap back to the original peice #set the original node back to playercolor self.locatorList[self.moveList[0]].setColor(self.playerColor) self.locatorList[self.moveList[0]].show() self.moveList = [] self.moveList.append(index) if index in self.opposingPositions: self.isOpposing = True else: self.isOpposing = False elif self.board.squareList[index].getState() != 0: return #do nothing because he clicked someone elses peice else: #Check for Explicit adjacent move if len(self.moveList ) == 1 and self.board.squareList[index].getState() == 0: #print "I AM OUTSIDE" if index in self.board.squareList[ self.moveList[0]].getAdjacent(): #print "I AM INSIDE" for x in self.nonOpposingPositions: if index in x: return #You cannot end a move in a non opposing players square self.moveList.append(index) self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.sound.start() #Check for mid series jumps stoppage #print len(self.moveList), len(self.moveList)-1 if len(self.moveList) >= 1: if index == self.moveList[ len(self.moveList) - 1]: #you clicked the same thing TWICE for x in self.nonOpposingPositions: if index in x: return #Will force you to jump out ... if self.existsLegalJumpsFrom(index) == True: self.blinker.finish() #self.locatorList[index].setColor(self.playerColor - self.tintConstant) #self.locatorList[index].show() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.sound.start() #Check for Normal jump #Also check if its a 'finishing jump' #Therefore no jumps possible after it ###print "CHECK LEGAL JUMP!", self.checkLegalMove(self.board.getSquare(self.moveList[len(self.moveList)-1]), self.board.getSquare(index)) == True elif self.checkLegalMove( self.board.getSquare( self.moveList[len(self.moveList) - 1]), self.board.getSquare(index)) == True: #this is the part that adds moves to a series of jumps ## #This if statement is an Explicit check to make sure that #the clicked peice, after a series of jumps #is not in the middle jump adjacent, This results in a #bug due to the way ive detected "legal moves" #but this explicit check should fix that. if not index in self.board.squareList[self.moveList[ len(self.moveList) - 1]].getAdjacent(): for x in self.nonOpposingPositions: #print " LEGAL JUMPS FROM! ", self.existsLegalJumpsFrom(index) if self.existsLegalJumpsFrom(index) == False: if index in x: return #He tried to JUMP into non opposing players startPos => Illegal self.moveList.append(index) #ghostConstant here is a small alpha offset to give it a transparent look #tintConstant makes the peice a bit darker (necessary when ghosting) self.locatorList[index].setColor( self.playerColor - self.tintConstant - self.ghostConstant) self.locatorList[index].show() self.sound.start() if self.existsLegalJumpsFrom(index) == False: self.blinker.finish() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False ################################################################## # Legal Move Request/Checker # (COPY PASTED FROM AI) # (Logic here reflects the (NEXT) move not a series of moves, but still #Checks the validity of two different move peices # #This is probably the most complicated as well as most important part #of the chinese checkers code. To completely understand the CheckLegalMoves, #get out a peice of paper and try to DRAW out what the logic is doing, ill do #my best to explain it. # # #Players request moves as a list of Uint8s (already should be verified on the client side) #but since players are cheating bastards, we check on the server. Basically, how the logic works #is it takes pairs one at a time and checks for a legal move between the two, ect and traverses the #list. # #A move is Legal if (it is adjacent to its last move) - in a checkerboard adjacent is stored in a list #of 6 integers representing the other squares (see ChineseCheckerBoard.py) # #board.squareList[x].getAdjacent() visually looks like this # 1 2 # 0 x 3 where those values [ ] are integers to adjacent squares. # 5 4 # # If a adjacent square does not exist on the board, say the first square only has two adjacent, # the squares in the adjacent list are set to None # #A move is also legal if there exists a legal Jump from A to B. the logic here is difficult to #express without a picture, but for instance, say A is jumping to B # # 1 2 1 2 # 0 A 3 B 3 # 5 4 5 6 # # You check all of A's adjacents, and check the index of that \ # particular one (of A's adjacents) that it sits in A, #if that is equal to B, there is a legal jump, if no one is found the move is illegal. # # EX. board.squareList[A].adjacent[3] == (some number to the left of b) # board.squareList[that number].getAdjacent[self.board.squareList[A].index(some number) # # in this case it equals B (draw it out, Trust me it helps) #### def existsLegalJumpsFrom(self, index): for x in self.board.squareList[index].getAdjacent(): if x == None: pass elif x in self.moveList: pass elif self.board.getState(x) == 0: pass elif self.board.squareList[x].getAdjacent( )[self.board.squareList[index].getAdjacent().index(x)] == None: pass elif self.board.getState(self.board.squareList[x].getAdjacent( )[self.board.squareList[index].getAdjacent().index( x)]) == 0 and not (self.board.squareList[x].getAdjacent()[ self.board.squareList[index].getAdjacent().index(x)] ) in self.moveList: return True return False def checkLegalMove(self, firstSquare, secondSquare): if secondSquare.getNum() in firstSquare.getAdjacent(): return True else: for x in firstSquare.getAdjacent(): if x == None: pass elif self.board.squareList[x].getState() == 0: pass else: #print " FIRSTSQUARE ADJACENT AND X -- " , firstSquare.getAdjacent(), " X == " , x #print "Xs Adjacent and its Index", self.board.squareList[x].getAdjacent(), " INDEX == " , firstSquare.getAdjacent().index(x) if (self.board.squareList[x].getAdjacent()[ firstSquare.getAdjacent().index(x)] ) == secondSquare.getNum(): return True return False def d_requestMove(self, moveList): self.sendUpdate('requestMove', [moveList]) ########## ##setGameState (required broadcast ram) # #This is the function that handles the moves made after a move is parsed by the AI #and deemed to be valid # #If moveList is the empty List, then the player is asynchronously joining the game, (OBSERVING) #and just wants the board state. # #otherwise there is a series of jumps (or jump) that needs to be parsed and animated, then #consequently setting the board state # #after every setGameState, the client checks to see the current #Status of his peices (checkForWin), if he belives he won, he requests it to the server ######### def setGameState(self, tableState, moveList): if moveList != []: self.animatePeice(tableState, moveList) else: self.updateGameState(tableState) def updateGameState(self, squares): self.board.setStates(squares) self.mySquares = [] messenger.send('wakeup') for x in range(121): self.locatorList[x].clearColor() owner = self.board.squareList[x].getState() if owner == self.playerNum: self.mySquares.append(x) if owner == 0: self.locatorList[x].hide() else: self.locatorList[x].show() if owner == 1: self.locatorList[x].setColor(self.playerColors[0]) elif owner == 2: self.locatorList[x].setColor(self.playerColors[1]) elif owner == 3: self.locatorList[x].setColor(self.playerColors[2]) elif owner == 4: self.locatorList[x].setColor(self.playerColors[3]) elif owner == 5: self.locatorList[x].setColor(self.playerColors[4]) elif owner == 6: self.locatorList[x].setColor(self.playerColors[5]) self.mySquares.sort() self.checkForWin() def animatePeice(self, tableState, moveList): messenger.send('wakeup') gamePeiceForAnimation = loader.loadModel( "phase_6/models/golf/checker_marble.bam") gamePeiceForAnimation.setColor( self.locatorList[moveList[0]].getColor()) gamePeiceForAnimation.reparentTo(self.boardNode) gamePeiceForAnimation.setPos(self.locatorList[moveList[0]].getPos()) self.locatorList[moveList[0]].hide() checkersPeiceTrack = Sequence() length = len(moveList) for x in range(length - 1): checkersPeiceTrack.append( Parallel( SoundInterval(self.moveSound), ProjectileInterval( gamePeiceForAnimation, endPos=self.locatorList[moveList[x + 1]].getPos(), duration=.5))) checkersPeiceTrack.append(Func(gamePeiceForAnimation.removeNode)) checkersPeiceTrack.append(Func(self.updateGameState, tableState)) checkersPeiceTrack.start() def checkForWin(self): if self.playerNum == 1: if (self.mySquares == self.startingPositions[3]): self.sendUpdate('requestWin', []) elif self.playerNum == 2: if (self.mySquares == self.startingPositions[4]): self.sendUpdate('requestWin', []) elif self.playerNum == 3: if (self.mySquares == self.startingPositions[5]): self.sendUpdate('requestWin', []) elif self.playerNum == 4: if (self.mySquares == self.startingPositions[0]): self.sendUpdate('requestWin', []) elif self.playerNum == 5: if (self.mySquares == self.startingPositions[1]): self.sendUpdate('requestWin', []) elif self.playerNum == 6: if (self.mySquares == self.startingPositions[2]): self.sendUpdate('requestWin', []) def announceWin(self, avId): self.fsm.request('gameOver') ########### ##doRandomMove # #If a clients move Timer runs out, it will calculate a random move for him #after 3 random moves, it kicks the client out of the game by pushing the #"get up" button for him. ########### def doRandomMove(self): if len(self.moveList) >= 2: self.blinker.finish() #self.locatorList[index].setColor(self.playerColor - self.tintConstant) #self.locatorList[index].show() self.d_requestMove(self.moveList) self.moveList = [] self.isMyTurn = False self.playSound = Sequence(SoundInterval(self.knockSound)) self.playSound.start() else: import random move = [] foundLegal = False self.blinker.pause() self.numRandomMoves += 1 ###self.blinker.finish() while not foundLegal: x = random.randint(0, 9) for y in self.board.getAdjacent(self.mySquares[x]): if y != None and self.board.getState(y) == 0: for zz in self.nonOpposingPositions: if not y in zz: move.append(self.mySquares[x]) move.append(y) foundLegal = True break break if move == []: pass #current flaw in the logic, but shouldnt really ever happen #though on live it might #print "random move is empty" playSound = Sequence(SoundInterval(self.knockSound)) playSound.start() self.d_requestMove(move) self.moveList = [] self.isMyTurn = False if (self.numRandomMoves >= 5): self.exitButtonPushed() def doNothing(self): pass