def enterWaitPlayback(self): self.notify.debug('enterWaitPlayback') stillPlayingList = self.golfCourse.getStillPlayingAvIds() self.barrierPlayback = ToonBarrier( 'waitClientsPlayback', self.uniqueName('waitClientsPlayback'), stillPlayingList, 120, self.handleWaitPlaybackDone, self.handlePlaybackTimeout)
def enterWaitClientsReady(self): self.notify.debug('enterWaitClientsReady') self.nextRoundBarrier = ToonBarrier( 'nextRoundReady', self.uniqueName('nextRoundReady'), self.avIdList, PatternGameGlobals.ClientsReadyTimeout, self.__allPlayersReady, self.__clientsReadyTimeout) for avId in self.readyClients: self.nextRoundBarrier.clear(avId)
def enterWaitForResults(self): self.notify.debug('enterWaitForResults') self.results = [None] * self.numPlayers self.fastestTime = PatternGameGlobals.InputTime * 2 self.fastestAvId = 0 self.resultsBarrier = ToonBarrier( 'results', self.uniqueName('results'), self.avIdList, PatternGameGlobals.InputTimeout + 1.0 * self.round, self.__gotAllPatterns, self.__resultsTimeout) return
def enterFrameworkWaitClientsReady(self): self.notify.debug("BASE: enterFrameworkWaitClientsReady") def allAvatarsReady(self=self): self.notify.debug("BASE: all avatars ready") self.frameworkFSM.request("frameworkGame") def handleTimeout(avIds, self=self): self.notify.debug("BASE: timed out waiting for clients %s to report 'ready'" % avIds) self.setGameAbort() self.__barrier = ToonBarrier( "waitClientsReady", self.uniqueName("waitClientsReady"), self.avIdList, READY_TIMEOUT, allAvatarsReady, handleTimeout, ) for avId in self.stateDict.keys(): if self.stateDict[avId] == READY: self.__barrier.clear(avId) self.notify.debug(" safezone: %s" % self.getSafezoneId()) self.notify.debug("difficulty: %s" % self.getDifficulty())
def enterWaitForResults(self): self.notify.debug('enterWaitForResults') self.results = [None] * self.numPlayers self.fastestTime = PatternGameGlobals.InputTime * 2 self.fastestAvId = 0 self.resultsBarrier = ToonBarrier('results', self.uniqueName('results'), self.avIdList, PatternGameGlobals.InputTimeout + 1.0 * self.round, self.__gotAllPatterns, self.__resultsTimeout) return
def enterPlay(self): self.notify.debug('enterPlay') self.caughtList = [0] * 100 table = CatchGameGlobals.NumFruits[self.numPlayers - 1] self.numFruits = table[self.getSafezoneId()] self.notify.debug('numFruits: %s' % self.numFruits) self.fruitsCaught = 0 def allToonsDone(self = self): self.notify.debug('allToonsDone') self.sendUpdate('setEveryoneDone') if not CatchGameGlobals.EndlessGame: self.gameOver() def handleTimeout(avIds, self = self): self.notify.debug('handleTimeout: avatars %s did not report "done"' % avIds) self.setGameAbort() self.doneBarrier = ToonBarrier('waitClientsDone', self.uniqueName('waitClientsDone'), self.avIdList, CatchGameGlobals.GameDuration + MinigameGlobals.latencyTolerance, allToonsDone, handleTimeout)
def enterWaitReadyHole(self): self.notify.debug('GOLF COURSE: enterWaitReadyHole') def allAvatarsInHole(self = self): self.notify.debug('GOLF COURSE: all avatars ready hole') if self.safeDemand('PlayHole'): self.d_setPlayHole() def handleTimeout(avIds, self = self): self.notify.debug("GOLF COURSE: Hole timed out waiting for clients %s to report 'ready'" % avIds) if self.haveAllGolfersExited(): self.setCourseAbort() elif self.safeDemand('PlayHole'): self.d_setPlayHole() stillPlaying = self.getStillPlayingAvIds() self.__barrier = ToonBarrier('WaitReadyHole', self.uniqueName('WaitReadyHole'), stillPlaying, READY_TIMEOUT, allAvatarsInHole, handleTimeout) for avId in self.avStateDict.keys(): if self.avStateDict[avId] == ONHOLE: self.__barrier.clear(avId)
def enterPlay(self): self.notify.debug('enterPlay') def allToonsDone(self=self): self.notify.debug('allToonsDone') self.sendUpdate('setEveryoneDone') if not ToonBlitzGlobals.EndlessGame: self.gameOver() def handleTimeout(avIds, self=self): self.notify.debug( 'handleTimeout: avatars %s did not report "done"' % avIds) self.setGameAbort() self.doneBarrier = ToonBarrier( 'waitClientsDone', self.uniqueName('waitClientsDone'), self.avIdList, ToonBlitzGlobals.GameDuration[self.getSafezoneId()] + ToonBlitzGlobals.ShowScoresDuration + MinigameGlobals.latencyTolerance, allToonsDone, handleTimeout)
def enterFrameworkWaitClientsExit(self): self.notify.debug('BASE: enterFrameworkWaitClientsExit') self.b_setGameExit() def allAvatarsExited(self=self): self.notify.debug('BASE: all avatars exited') self.frameworkFSM.request('frameworkCleanup') def handleTimeout(avIds, self=self): self.notify.debug( 'BASE: timed out waiting for clients %s to exit' % avIds) self.frameworkFSM.request('frameworkCleanup') self.__barrier = ToonBarrier('waitClientsExit', self.uniqueName('waitClientsExit'), self.avIdList, EXIT_TIMEOUT, allAvatarsExited, handleTimeout) for avId in self.stateDict.keys(): if self.stateDict[avId] == EXITED: self.__barrier.clear(avId)
def enterWaitJoin(self): self.notify.debug('GOLF COURSE: enterWaitJoin') for avId in self.avIdList: self.avStateDict[avId] = EXPECTED self.acceptOnce(self.air.getAvatarExitEvent(avId), self.handleExitedAvatar, extraArgs=[avId]) def allAvatarsJoined(self = self): self.notify.debug('GOLF COURSE: all avatars joined') self.load() def handleTimeout(avIds, self = self): self.notify.debug('GOLF COURSE: timed out waiting for clients %s to join' % avIds) for avId in self.avStateDict: if not self.avStateDict[avId] == JOINED: self.handleExitedAvatar(avId) if self.haveAllGolfersExited(): self.setCourseAbort() else: self.load() self.__barrier = ToonBarrier('waitClientsJoin', self.uniqueName('waitClientsJoin'), self.avIdList, JOIN_TIMEOUT, allAvatarsJoined, handleTimeout)
def enterPlay(self): self.notify.debug('enterPlay') def allToonsDone(self = self): self.notify.debug('allToonsDone') self.sendUpdate('setEveryoneDone') if not ToonBlitzGlobals.EndlessGame: self.gameOver() def handleTimeout(avIds, self = self): self.notify.debug('handleTimeout: avatars %s did not report "done"' % avIds) self.setGameAbort() self.doneBarrier = ToonBarrier('waitClientsDone', self.uniqueName('waitClientsDone'), self.avIdList, ToonBlitzGlobals.GameDuration[self.getSafezoneId()] + ToonBlitzGlobals.ShowScoresDuration + MinigameGlobals.latencyTolerance, allToonsDone, handleTimeout)
def enterFrameworkWaitClientsReady(self): self.notify.debug('BASE: enterFrameworkWaitClientsReady') def allAvatarsReady(self=self): self.notify.debug('BASE: all avatars ready') self.frameworkFSM.request('frameworkGame') def handleTimeout(avIds, self=self): self.notify.debug( "BASE: timed out waiting for clients %s to report 'ready'" % avIds) self.setGameAbort() self.__barrier = ToonBarrier('waitClientsReady', self.uniqueName('waitClientsReady'), self.avIdList, READY_TIMEOUT, allAvatarsReady, handleTimeout) for avId in self.stateDict.keys(): if self.stateDict[avId] == READY: self.__barrier.clear(avId) self.notify.debug(' safezone: %s' % self.getSafezoneId()) self.notify.debug('difficulty: %s' % self.getDifficulty())
def enterFrameworkWaitClientsJoin(self): self.notify.debug('BASE: enterFrameworkWaitClientsJoin') for avId in self.avIdList: self.stateDict[avId] = EXPECTED self.scoreDict[avId] = DEFAULT_POINTS self.acceptOnce(self.air.getAvatarExitEvent(avId), self.handleExitedAvatar, extraArgs=[avId]) def allAvatarsJoined(self=self): self.notify.debug('BASE: all avatars joined') self.b_setGameReady() self.frameworkFSM.request('frameworkWaitClientsReady') def handleTimeout(avIds, self=self): self.notify.debug( 'BASE: timed out waiting for clients %s to join' % avIds) self.setGameAbort() self.__barrier = ToonBarrier('waitClientsJoin', self.uniqueName('waitClientsJoin'), self.avIdList, JOIN_TIMEOUT, allAvatarsJoined, handleTimeout)
def enterWaitReadyCourse(self): self.notify.debug('GOLF COURSE: enterWaitReadyCourse') def allAvatarsInCourse(self = self): self.notify.debug('GOLF COURSE: all avatars ready course') for avId in self.avIdList: blankScoreList = [0] * self.numHoles self.scores[avId] = blankScoreList self.aimTimes[avId] = 0 self.notify.debug('self.scores = %s' % self.scores) self.startNextHole() def handleTimeout(avIds, self = self): self.notify.debug("GOLF COURSE: Course timed out waiting for clients %s to report 'ready'" % avIds) if self.haveAllGolfersExited(): self.setCourseAbort() else: allAvatarsInCourse() self.__barrier = ToonBarrier('WaitReadyCourse', self.uniqueName('WaitReadyCourse'), self.avIdList, READY_TIMEOUT, allAvatarsInCourse, handleTimeout) for avId in self.avStateDict.keys(): if self.avStateDict[avId] == READY: self.__barrier.clear(avId)
def enterFrameworkWaitClientsExit(self): self.notify.debug("BASE: enterFrameworkWaitClientsExit") self.b_setGameExit() def allAvatarsExited(self=self): self.notify.debug("BASE: all avatars exited") self.frameworkFSM.request("frameworkCleanup") def handleTimeout(avIds, self=self): self.notify.debug("BASE: timed out waiting for clients %s to exit" % avIds) self.frameworkFSM.request("frameworkCleanup") self.__barrier = ToonBarrier( "waitClientsExit", self.uniqueName("waitClientsExit"), self.avIdList, EXIT_TIMEOUT, allAvatarsExited, handleTimeout, ) for avId in self.stateDict.keys(): if self.stateDict[avId] == EXITED: self.__barrier.clear(avId)
def enterFrameworkWaitClientsJoin(self): self.notify.debug("BASE: enterFrameworkWaitClientsJoin") for avId in self.avIdList: self.stateDict[avId] = EXPECTED self.scoreDict[avId] = DEFAULT_POINTS self.acceptOnce(self.air.getAvatarExitEvent(avId), self.handleExitedAvatar, extraArgs=[avId]) def allAvatarsJoined(self=self): self.notify.debug("BASE: all avatars joined") self.b_setGameReady() self.frameworkFSM.request("frameworkWaitClientsReady") def handleTimeout(avIds, self=self): self.notify.debug("BASE: timed out waiting for clients %s to join" % avIds) self.setGameAbort() self.__barrier = ToonBarrier( "waitClientsJoin", self.uniqueName("waitClientsJoin"), self.avIdList, JOIN_TIMEOUT, allAvatarsJoined, handleTimeout, )
class DistributedMinigameAI(DistributedObjectAI.DistributedObjectAI): notify = directNotify.newCategory("DistributedMinigameAI") def __init__(self, air, minigameId): try: self.DistributedMinigameAI_initialized except: self.DistributedMinigameAI_initialized = 1 DistributedObjectAI.DistributedObjectAI.__init__(self, air) self.minigameId = minigameId self.frameworkFSM = ClassicFSM.ClassicFSM( "DistributedMinigameAI", [ State.State( "frameworkOff", self.enterFrameworkOff, self.exitFrameworkOff, ["frameworkWaitClientsJoin"] ), State.State( "frameworkWaitClientsJoin", self.enterFrameworkWaitClientsJoin, self.exitFrameworkWaitClientsJoin, ["frameworkWaitClientsReady", "frameworkWaitClientsExit", "frameworkCleanup"], ), State.State( "frameworkWaitClientsReady", self.enterFrameworkWaitClientsReady, self.exitFrameworkWaitClientsReady, ["frameworkGame", "frameworkWaitClientsExit", "frameworkCleanup"], ), State.State( "frameworkGame", self.enterFrameworkGame, self.exitFrameworkGame, ["frameworkWaitClientsExit", "frameworkCleanup"], ), State.State( "frameworkWaitClientsExit", self.enterFrameworkWaitClientsExit, self.exitFrameworkWaitClientsExit, ["frameworkCleanup"], ), State.State( "frameworkCleanup", self.enterFrameworkCleanup, self.exitFrameworkCleanup, ["frameworkOff"] ), ], "frameworkOff", "frameworkOff", ) self.frameworkFSM.enterInitialState() self.avIdList = [] self.stateDict = {} self.scoreDict = {} self.difficultyOverride = None self.trolleyZoneOverride = None self.skippable = True self.skipAvIds = [] def addChildGameFSM(self, gameFSM): self.frameworkFSM.getStateNamed("frameworkGame").addChild(gameFSM) def removeChildGameFSM(self, gameFSM): self.frameworkFSM.getStateNamed("frameworkGame").removeChild(gameFSM) def setExpectedAvatars(self, avIds): self.avIdList = avIds self.numPlayers = len(self.avIdList) self.notify.debug("BASE: setExpectedAvatars: expecting avatars: " + str(self.avIdList)) def setNewbieIds(self, newbieIds): self.newbieIdList = newbieIds if len(self.newbieIdList) > 0: self.notify.debug("BASE: setNewbieIds: %s" % self.newbieIdList) def setTrolleyZone(self, trolleyZone): self.trolleyZone = trolleyZone def setDifficultyOverrides(self, difficultyOverride, trolleyZoneOverride): self.difficultyOverride = difficultyOverride if self.difficultyOverride is not None: self.difficultyOverride = MinigameGlobals.QuantizeDifficultyOverride(difficultyOverride) self.trolleyZoneOverride = trolleyZoneOverride return def _playing(self): if not hasattr(self, "gameFSM"): return False if self.gameFSM.getCurrentState() == None: return False return self.gameFSM.getCurrentState().getName() == "play" def _inState(self, states): if not hasattr(self, "gameFSM"): return False if self.gameFSM.getCurrentState() == None: return False return self.gameFSM.getCurrentState().getName() in makeList(states) def generate(self): DistributedObjectAI.DistributedObjectAI.generate(self) self.frameworkFSM.request("frameworkWaitClientsJoin") def delete(self): self.notify.debug("BASE: delete: deleting AI minigame object") del self.frameworkFSM self.ignoreAll() DistributedObjectAI.DistributedObjectAI.delete(self) def isSinglePlayer(self): if self.numPlayers == 1: return 1 else: return 0 def getParticipants(self): return self.avIdList def getTrolleyZone(self): return self.trolleyZone def getDifficultyOverrides(self): response = [self.difficultyOverride, self.trolleyZoneOverride] if response[0] is None: response[0] = MinigameGlobals.NoDifficultyOverride else: response[0] *= MinigameGlobals.DifficultyOverrideMult response[0] = int(response[0]) if response[1] is None: response[1] = MinigameGlobals.NoTrolleyZoneOverride return response def b_setGameReady(self): self.setGameReady() self.d_setGameReady() def d_setGameReady(self): self.notify.debug("BASE: Sending setGameReady") self.sendUpdate("setGameReady", []) def setGameReady(self): self.notify.debug("BASE: setGameReady: game ready with avatars: %s" % self.avIdList) self.normalExit = 1 def b_setGameStart(self, timestamp): self.d_setGameStart(timestamp) self.setGameStart(timestamp) def d_setGameStart(self, timestamp): self.notify.debug("BASE: Sending setGameStart") self.sendUpdate("setGameStart", [timestamp]) def setGameStart(self, timestamp): self.notify.debug("BASE: setGameStart") def b_setGameExit(self): self.d_setGameExit() self.setGameExit() def d_setGameExit(self): self.notify.debug("BASE: Sending setGameExit") self.sendUpdate("setGameExit", []) def setGameExit(self): self.notify.debug("BASE: setGameExit") def setGameAbort(self): self.notify.debug("BASE: setGameAbort") self.normalExit = 0 self.sendUpdate("setGameAbort", []) self.frameworkFSM.request("frameworkCleanup") def handleExitedAvatar(self, avId): self.notify.warning("BASE: handleExitedAvatar: avatar id exited: " + str(avId)) self.stateDict[avId] = EXITED self.setGameAbort() def gameOver(self): self.frameworkFSM.request("frameworkWaitClientsExit") def enterFrameworkOff(self): self.notify.debug("BASE: enterFrameworkOff") def exitFrameworkOff(self): pass def enterFrameworkWaitClientsJoin(self): self.notify.debug("BASE: enterFrameworkWaitClientsJoin") for avId in self.avIdList: self.stateDict[avId] = EXPECTED self.scoreDict[avId] = DEFAULT_POINTS self.acceptOnce(self.air.getAvatarExitEvent(avId), self.handleExitedAvatar, extraArgs=[avId]) def allAvatarsJoined(self=self): self.notify.debug("BASE: all avatars joined") self.b_setGameReady() self.frameworkFSM.request("frameworkWaitClientsReady") def handleTimeout(avIds, self=self): self.notify.debug("BASE: timed out waiting for clients %s to join" % avIds) self.setGameAbort() self.__barrier = ToonBarrier( "waitClientsJoin", self.uniqueName("waitClientsJoin"), self.avIdList, JOIN_TIMEOUT, allAvatarsJoined, handleTimeout, ) def setAvatarJoined(self): if self.frameworkFSM.getCurrentState().getName() != "frameworkWaitClientsJoin": self.notify.debug("BASE: Ignoring setAvatarJoined message") return avId = self.air.getAvatarIdFromSender() self.notify.debug("BASE: setAvatarJoined: avatar id joined: " + str(avId)) self.air.writeServerEvent("minigame_joined", avId, "%s|%s" % (self.minigameId, self.trolleyZone)) self.stateDict[avId] = JOINED self.notify.debug("BASE: setAvatarJoined: new states: " + str(self.stateDict)) self.__barrier.clear(avId) def exitFrameworkWaitClientsJoin(self): self.__barrier.cleanup() del self.__barrier def enterFrameworkWaitClientsReady(self): self.notify.debug("BASE: enterFrameworkWaitClientsReady") def allAvatarsReady(self=self): self.notify.debug("BASE: all avatars ready") self.frameworkFSM.request("frameworkGame") def handleTimeout(avIds, self=self): self.notify.debug("BASE: timed out waiting for clients %s to report 'ready'" % avIds) self.setGameAbort() self.__barrier = ToonBarrier( "waitClientsReady", self.uniqueName("waitClientsReady"), self.avIdList, READY_TIMEOUT, allAvatarsReady, handleTimeout, ) for avId in self.stateDict.keys(): if self.stateDict[avId] == READY: self.__barrier.clear(avId) self.notify.debug(" safezone: %s" % self.getSafezoneId()) self.notify.debug("difficulty: %s" % self.getDifficulty()) def setAvatarReady(self): if self.frameworkFSM.getCurrentState().getName() not in [ "frameworkWaitClientsReady", "frameworkWaitClientsJoin", ]: self.notify.debug("BASE: Ignoring setAvatarReady message") return avId = self.air.getAvatarIdFromSender() self.notify.debug("BASE: setAvatarReady: avatar id ready: " + str(avId)) self.stateDict[avId] = READY self.notify.debug("BASE: setAvatarReady: new avId states: " + str(self.stateDict)) if self.frameworkFSM.getCurrentState().getName() == "frameworkWaitClientsReady": self.__barrier.clear(avId) self.skippable = False def exitFrameworkWaitClientsReady(self): self.__barrier.cleanup() del self.__barrier def enterFrameworkGame(self): self.notify.debug("BASE: enterFrameworkGame") self.gameStartTime = globalClock.getRealTime() self.b_setGameStart(globalClockDelta.localToNetworkTime(self.gameStartTime)) def exitFrameworkGame(self): pass def enterFrameworkWaitClientsExit(self): self.notify.debug("BASE: enterFrameworkWaitClientsExit") self.b_setGameExit() def allAvatarsExited(self=self): self.notify.debug("BASE: all avatars exited") self.frameworkFSM.request("frameworkCleanup") def handleTimeout(avIds, self=self): self.notify.debug("BASE: timed out waiting for clients %s to exit" % avIds) self.frameworkFSM.request("frameworkCleanup") self.__barrier = ToonBarrier( "waitClientsExit", self.uniqueName("waitClientsExit"), self.avIdList, EXIT_TIMEOUT, allAvatarsExited, handleTimeout, ) for avId in self.stateDict.keys(): if self.stateDict[avId] == EXITED: self.__barrier.clear(avId) def setAvatarExited(self): if self.frameworkFSM.getCurrentState().getName() != "frameworkWaitClientsExit": self.notify.debug("BASE: Ignoring setAvatarExit message") return avId = self.air.getAvatarIdFromSender() self.notify.debug("BASE: setAvatarExited: avatar id exited: " + str(avId)) self.stateDict[avId] = EXITED self.notify.debug("BASE: setAvatarExited: new avId states: " + str(self.stateDict)) self.__barrier.clear(avId) self.checkForSkip() def exitFrameworkWaitClientsExit(self): self.__barrier.cleanup() del self.__barrier def hasScoreMult(self): return 1 def enterFrameworkCleanup(self): self.notify.debug("BASE: enterFrameworkCleanup: normalExit=%s" % self.normalExit) scoreMult = MinigameGlobals.getScoreMult(self.getSafezoneId()) if not self.hasScoreMult(): scoreMult = 1.0 self.notify.debug("score multiplier: %s" % scoreMult) for avId in self.avIdList: self.scoreDict[avId] *= scoreMult scoreList = [] for avId in self.avIdList: if self.normalExit: score = int(self.scoreDict[avId] + 0.5) else: score = 0 if simbase.air.newsManager.isHolidayRunning( ToontownGlobals.JELLYBEAN_TROLLEY_HOLIDAY ) or simbase.air.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_TROLLEY_HOLIDAY_MONTH): score *= MinigameGlobals.JellybeanTrolleyHolidayScoreMultiplier logEvent = False if score > 255: score = 255 logEvent = True elif score < 0: score = 0 logEvent = True if logEvent: self.air.writeServerEvent( "suspicious", avId, "got %s jellybeans playing minigame %s in zone %s" % (score, self.minigameId, self.getSafezoneId()), ) scoreList.append(score) self.requestDelete() self.handleRegularPurchaseManager(scoreList) self.frameworkFSM.request("frameworkOff") def handleRegularPurchaseManager(self, scoreList): for id in self.newbieIdList: pm = NewbiePurchaseManagerAI.NewbiePurchaseManagerAI( self.air, id, self.avIdList, scoreList, self.minigameId, self.trolleyZone ) MinigameCreatorAI.acquireMinigameZone(self.zoneId) pm.generateWithRequired(self.zoneId) if len(self.avIdList) > len(self.newbieIdList): pm = PurchaseManagerAI.PurchaseManagerAI( self.air, self.avIdList, scoreList, self.minigameId, self.trolleyZone, self.newbieIdList ) pm.generateWithRequired(self.zoneId) def exitFrameworkCleanup(self): pass def requestExit(self): self.notify.debug("BASE: requestExit: client has requested the game to end") self.setGameAbort() def local2GameTime(self, timestamp): return timestamp - self.gameStartTime def game2LocalTime(self, timestamp): return timestamp + self.gameStartTime def getCurrentGameTime(self): return self.local2GameTime(globalClock.getFrameTime()) def getDifficulty(self): if self.difficultyOverride is not None: return self.difficultyOverride if hasattr(self.air, "minigameDifficulty"): return float(self.air.minigameDifficulty) return MinigameGlobals.getDifficulty(self.getSafezoneId()) def getSafezoneId(self): if self.trolleyZoneOverride is not None: return self.trolleyZoneOverride if hasattr(self.air, "minigameSafezoneId"): return MinigameGlobals.getSafezoneId(self.air.minigameSafezoneId) return MinigameGlobals.getSafezoneId(self.trolleyZone) def logPerfectGame(self, avId): self.air.writeServerEvent( "perfectMinigame", avId, "%s|%s|%s" % (self.minigameId, self.trolleyZone, self.avIdList) ) def logAllPerfect(self): for avId in self.avIdList: self.logPerfectGame(avId) def requestSkip(self): avId = self.air.getAvatarIdFromSender() if (not self.skippable) or (avId not in self.avIdList) or (avId in self.skipAvIds): return self.skipAvIds.append(avId) self.checkForSkip() def checkForSkip(self): if len(self.skipAvIds) >= len(self.avIdList): self.skippable = False self.setGameAbort() else: self.sendUpdate("setSkipCount", [len(self.skipAvIds)])
class DistributedGolfHoleAI( DistributedPhysicsWorldAI.DistributedPhysicsWorldAI, FSM, GolfHoleBase.GolfHoleBase): defaultTransitions = { 'Off': ['Cleanup', 'WaitTee'], 'WaitTee': ['WaitSwing', 'Cleanup', 'WaitTee', 'WaitPlayback'], 'WaitSwing': ['WaitPlayback', 'Cleanup', 'WaitSwing', 'WaitTee'], 'WaitPlayback': ['WaitSwing', 'Cleanup', 'WaitTee', 'WaitPlayback'], 'Cleanup': ['Off'] } id = 0 notify = directNotify.newCategory('DistributedGolfHoleAI') def __init__(self, zoneId, golfCourse, holeId): FSM.__init__(self, 'Golf_%s_FSM' % self.id) DistributedPhysicsWorldAI.DistributedPhysicsWorldAI.__init__( self, simbase.air) GolfHoleBase.GolfHoleBase.__init__(self) self.zoneId = zoneId self.golfCourse = golfCourse self.holeId = holeId self.avIdList = golfCourse.avIdList[:] self.watched = [0, 0, 0, 0] self.barrierPlayback = None self.trustedAvId = None self.activeGolferIndex = None self.activeGolferId = None self.holeInfo = GolfGlobals.HoleInfo[self.holeId] self.teeChosen = {} for avId in self.avIdList: self.teeChosen[avId] = -1 self.ballPos = {} for avId in self.avIdList: self.ballPos[avId] = Vec3(0, 0, 0) self.playStarted = False return def curGolfBall(self): return self.ball def generate(self): DistributedPhysicsWorldAI.DistributedPhysicsWorldAI.generate(self) self.ball = self.createBall() self.createRays() if len(self.teePositions) > 1: startPos = self.teePositions[1] else: startPos = self.teePositions[0] startPos += Vec3(0, 0, GolfGlobals.GOLF_BALL_RADIUS) self.ball.setPosition(startPos) def delete(self): self.notify.debug('__delete__') DistributedPhysicsWorldAI.DistributedPhysicsWorldAI.delete(self) self.notify.debug('calling self.terrainModel.removeNode') self.terrainModel.removeNode() self.notify.debug('self.barrierPlayback is %s' % self.barrierPlayback) if self.barrierPlayback: self.notify.debug('calling self.barrierPlayback.cleanup') self.barrierPlayback.cleanup() self.notify.debug('calling self.barrierPlayback = None') self.barrierPlayback = None self.activeGolferId = None return def setZoneId(self, zoneId): self.zoneId = zoneId def setAvatarReadyHole(self): self.notify.debugStateCall(self) avId = self.air.getAvatarIdFromSender() self.golfCourse.avatarReadyHole(avId) def startPlay(self): self.notify.debug('startPlay') self.playStarted = True self.numGolfers = len(self.golfCourse.getGolferIds()) self.selectNextGolfer() def selectNextGolfer(self): self.notify.debug( 'selectNextGolfer, old golferIndex=%s old golferId=%s' % (self.activeGolferIndex, self.activeGolferId)) if self.golfCourse.isCurHoleDone(): return if self.activeGolferIndex == None: self.activeGolferIndex = 0 self.activeGolferId = self.golfCourse.getGolferIds()[ self.activeGolferIndex] else: self.activeGolferIndex += 1 if self.activeGolferIndex >= len(self.golfCourse.getGolferIds()): self.activeGolferIndex = 0 self.activeGolferId = self.golfCourse.getGolferIds()[ self.activeGolferIndex] safety = 0 while safety < 50 and not self.golfCourse.checkGolferPlaying( self.golfCourse.getGolferIds()[self.activeGolferIndex]): self.activeGolferIndex += 1 self.notify.debug('Index %s' % self.activeGolferIndex) if self.activeGolferIndex >= len(self.golfCourse.getGolferIds()): self.activeGolferIndex = 0 self.activeGolferId = self.golfCourse.getGolferIds()[ self.activeGolferIndex] safety += 1 if safety != 50: golferId = self.golfCourse.getGolferIds()[self.activeGolferIndex] if self.teeChosen[golferId] == -1: self.sendUpdate('golferChooseTee', [golferId]) self.request('WaitTee') else: self.sendUpdate('golfersTurn', [golferId]) self.request('WaitSwing') else: self.notify.debug('safety') self.notify.debug( 'selectNextGolfer, new golferIndex=%s new golferId=%s' % (self.activeGolferIndex, self.activeGolferId)) return def clearWatched(self): self.watched = [1, 1, 1, 1] for index in xrange(len(self.golfCourse.getGolferIds())): self.watched[index] = 0 def setWatched(self, avId): for index in xrange(len(self.golfCourse.getGolferIds())): if self.golfCourse.getGolferIds()[index] == avId: self.watched[index] = 1 def checkWatched(self): if 0 not in self.watched: return True else: return False def turnDone(self): self.notify.debug('Turn Done') avId = self.air.getAvatarIdFromSender() if self.barrierPlayback: self.barrierPlayback.clear(avId) def ballInHole(self, golferId=None): self.notify.debug('ballInHole') if golferId: avId = golferId else: avId = self.air.getAvatarIdFromSender() self.golfCourse.setBallIn(avId) if self.golfCourse.isCurHoleDone(): self.notify.debug('ballInHole doing nothing') else: self.notify.debug('ballInHole calling self.selectNextGolfer') self.selectNextGolfer() def getHoleId(self): return self.holeId def finishHole(self): self.notify.debug('finishHole') self.golfCourse.holeOver() def getGolferIds(self): return self.avIdList def loadLevel(self): GolfHoleBase.GolfHoleBase.loadLevel(self) optionalObjects = self.terrainModel.findAllMatches('**/optional*') requiredObjects = self.terrainModel.findAllMatches('**/required*') self.parseLocators(optionalObjects, 1) self.parseLocators(requiredObjects, 0) self.teeNodePath = self.terrainModel.find('**/tee0') if self.teeNodePath.isEmpty(): teePos = Vec3(0, 0, 10) else: teePos = self.teeNodePath.getPos() teePos.setZ(teePos.getZ() + GolfGlobals.GOLF_BALL_RADIUS) self.notify.debug('teeNodePath heading = %s' % self.teeNodePath.getH()) self.teePositions = [teePos] teeIndex = 1 teeNode = self.terrainModel.find('**/tee%d' % teeIndex) while not teeNode.isEmpty(): teePos = teeNode.getPos() teePos.setZ(teePos.getZ() + GolfGlobals.GOLF_BALL_RADIUS) self.teePositions.append(teePos) self.notify.debug('teeNodeP heading = %s' % teeNode.getH()) teeIndex += 1 teeNode = self.terrainModel.find('**/tee%d' % teeIndex) def createLocatorDict(self): self.locDict = {} locatorNum = 1 curNodePath = self.hardSurfaceNodePath.find('**/locator%d' % locatorNum) while not curNodePath.isEmpty(): self.locDict[locatorNum] = curNodePath locatorNum += 1 curNodePath = self.hardSurfaceNodePath.find('**/locator%d' % locatorNum) def loadBlockers(self): loadAll = simbase.config.GetBool('golf-all-blockers', 0) self.createLocatorDict() self.blockerNums = self.holeInfo['blockers'] for locatorNum in self.locDict: if locatorNum in self.blockerNums or loadAll: locator = self.locDict[locatorNum] locatorParent = locator.getParent() locator.getChildren().wrtReparentTo(locatorParent) else: self.locDict[locatorNum].removeNode() self.hardSurfaceNodePath.flattenStrong() def createBall(self): golfBallGeom = self.createSphere(self.world, self.space, GolfGlobals.GOLF_BALL_DENSITY, GolfGlobals.GOLF_BALL_RADIUS, 1)[1] return golfBallGeom def preStep(self): GolfHoleBase.GolfHoleBase.preStep(self) def postStep(self): GolfHoleBase.GolfHoleBase.postStep(self) def postSwing(self, cycleTime, power, x, y, z, dirX, dirY): avId = self.air.getAvatarIdFromSender() self.storeAction = [avId, cycleTime, power, x, y, z, dirX, dirY] if self.commonHoldData: self.doAction() def postSwingState(self, cycleTime, power, x, y, z, dirX, dirY, curAimTime, commonObjectData): self.notify.debug('postSwingState') if not self.golfCourse.getStillPlayingAvIds(): return avId = self.air.getAvatarIdFromSender() self.storeAction = [avId, cycleTime, power, x, y, z, dirX, dirY] self.commonHoldData = commonObjectData self.trustedAvId = self.chooseAvatarToSimulate() self.sendUpdateToAvatarId( self.trustedAvId, 'assignRecordSwing', [avId, cycleTime, power, x, y, z, dirX, dirY, commonObjectData]) self.golfCourse.addAimTime(avId, curAimTime) def chooseAvatarToSimulate(self): stillPlaying = self.golfCourse.getStillPlayingAvIds() return stillPlaying[0] if stillPlaying else 0 def ballMovie2AI(self, cycleTime, avId, movie, spinMovie, ballInFrame, ballTouchedHoleFrame, ballFirstTouchedHoleFrame, commonObjectData): sentFromId = self.air.getAvatarIdFromSender() if sentFromId == self.trustedAvId: lastFrameNum = len(movie) - 2 if lastFrameNum < 0: lastFrameNum = 0 lastFrame = movie[lastFrameNum] lastPos = Vec3(lastFrame[1], lastFrame[2], lastFrame[3]) self.ballPos[avId] = lastPos self.golfCourse.incrementScore(avId) for id in self.golfCourse.getStillPlayingAvIds(): if not id == sentFromId: self.sendUpdateToAvatarId(id, 'ballMovie2Client', [ cycleTime, avId, movie, spinMovie, ballInFrame, ballTouchedHoleFrame, ballFirstTouchedHoleFrame, commonObjectData ]) if self.state == 'WaitPlayback' or self.state == 'WaitTee': self.notify.warning( 'ballMovie2AI requesting from %s to WaitPlayback' % self.state) self.request('WaitPlayback') elif self.trustedAvId == None: return else: self.doAction() self.trustedAvId = None return def performReadyAction(self): avId = self.storeAction[0] if self.state == 'WaitPlayback': self.notify.debugStateCall(self) self.notify.debug( 'ignoring the postSwing for avId=%d since we are in WaitPlayback' % avId) return if avId == self.activeGolferId: self.golfCourse.incrementScore(self.activeGolferId) else: self.notify.warning( 'activGolferId %d not equal to sender avId %d' % (self.activeGolferId, avId)) if avId not in self.golfCourse.drivingToons: position = self.ballPos[avId] else: position = Vec3(self.storeAction[3], self.storeAction[4], self.storeAction[5]) self.useCommonObjectData(self.commonHoldData) newPos = self.trackRecordBodyFlight(self.ball, self.storeAction[1], self.storeAction[2], position, self.storeAction[6], self.storeAction[7]) if self.state == 'WaitPlayback' or self.state == 'WaitTee': self.notify.warning( 'performReadyAction requesting from %s to WaitPlayback' % self.state) self.request('WaitPlayback') self.sendUpdate('ballMovie2Client', [ self.storeAction[1], avId, self.recording, self.aVRecording, self.ballInHoleFrame, self.ballTouchedHoleFrame, self.ballFirstTouchedHoleFrame, self.commonHoldData ]) self.ballPos[avId] = newPos self.trustedAvId = None return def postResult(self, cycleTime, avId, recording, aVRecording, ballInHoleFrame, ballTouchedHoleFrame, ballFirstTouchedHoleFrame): pass def enterWaitSwing(self): pass def exitWaitSwing(self): pass def enterWaitTee(self): pass def exitWaitTee(self): pass def enterWaitPlayback(self): self.notify.debug('enterWaitPlayback') stillPlayingList = self.golfCourse.getStillPlayingAvIds() self.barrierPlayback = ToonBarrier( 'waitClientsPlayback', self.uniqueName('waitClientsPlayback'), stillPlayingList, 120, self.handleWaitPlaybackDone, self.handlePlaybackTimeout) def hasCurGolferReachedMaxSwing(self): strokes = self.golfCourse.getCurHoleScore(self.activeGolferId) maxSwing = self.holeInfo['maxSwing'] retval = strokes >= maxSwing if retval: av = simbase.air.doId2do.get(self.activeGolferId) if av: if av.getUnlimitedSwing(): retval = False return retval def handleWaitPlaybackDone(self): if self.isCurBallInHole( self.activeGolferId) or self.hasCurGolferReachedMaxSwing(): if self.activeGolferId: self.ballInHole(self.activeGolferId) else: self.selectNextGolfer() def isCurBallInHole(self, golferId): retval = False for holePos in self.holePositions: displacement = self.ballPos[golferId] - holePos length = displacement.length() self.notify.debug('hole %s length=%s' % (holePos, length)) if length <= GolfGlobals.DistanceToBeInHole: retval = True break return retval def exitWaitPlayback(self): self.notify.debug('exitWaitPlayback') if hasattr(self, 'barrierPlayback') and self.barrierPlayback: self.barrierPlayback.cleanup() self.barrierPlayback = None return def enterCleanup(self): pass def exitCleanup(self): pass def handlePlaybackTimeout(self, task=None): self.notify.debug('handlePlaybackTimeout') self.handleWaitPlaybackDone() def getGolfCourseDoId(self): return self.golfCourse.doId def avatarDropped(self, avId): self.notify.warning('avId %d dropped, self.state=%s' % (avId, self.state)) if self.barrierPlayback: self.barrierPlayback.clear(avId) else: if avId == self.trustedAvId: self.doAction() if avId == self.activeGolferId and not self.golfCourse.haveAllGolfersExited( ): self.selectNextGolfer() def setAvatarTee(self, chosenTee): golferId = self.air.getAvatarIdFromSender() self.teeChosen[golferId] = chosenTee self.ballPos[golferId] = self.teePositions[chosenTee] self.sendUpdate('setAvatarFinalTee', [golferId, chosenTee]) self.sendUpdate('golfersTurn', [golferId]) self.request('WaitSwing') def setBox(self, pos0, pos1, pos2, quat0, quat1, quat2, quat3, anV0, anV1, anV2, lnV0, lnV1, lnV2): self.sendUpdate('sendBox', [ pos0, pos1, pos2, quat0, quat1, quat2, quat3, anV0, anV1, anV2, lnV0, lnV1, lnV2 ]) def parseLocators(self, objectCollection, optional=0): if optional and objectCollection.getNumPaths(): if 'optionalMovers' in self.holeInfo: for optionalMoverId in self.holeInfo['optionalMovers']: searchStr = 'optional_mover_' + str(optionalMoverId) for objIndex in xrange(objectCollection.getNumPaths()): object = objectCollection.getPath(objIndex) if searchStr in object.getName(): self.fillLocator(objectCollection, objIndex) break else: for index in xrange(objectCollection.getNumPaths()): self.fillLocator(objectCollection, index) def fillLocator(self, objectCollection, index): path = objectCollection[index] pathName = path.getName() pathArray = pathName.split('_') sizeX = None sizeY = None move = None type = None for subString in pathArray: if subString[:1] == 'X': dataString = subString[1:] dataString = dataString.replace('p', '.') sizeX = float(dataString) elif subString[:1] == 'Y': dataString = subString[1:] dataString = dataString.replace('p', '.') sizeY = float(dataString) elif subString[:1] == 'd': dataString = subString[1:] dataString = dataString.replace('p', '.') move = float(dataString) elif subString == 'mover': type = 4 elif subString == 'windmillLocator': type = 3 if type == 4 and move and sizeX and sizeY: self.createCommonObject(4, path.getPos(), path.getHpr(), sizeX, sizeY, move) elif type == 3: self.createCommonObject(3, path.getPos(), path.getHpr()) return
class DistributedMinigameAI(DistributedObjectAI.DistributedObjectAI): notify = directNotify.newCategory('DistributedMinigameAI') def __init__(self, air, minigameId): try: self.DistributedMinigameAI_initialized except: self.DistributedMinigameAI_initialized = 1 DistributedObjectAI.DistributedObjectAI.__init__(self, air) self.minigameId = minigameId self.frameworkFSM = ClassicFSM.ClassicFSM( 'DistributedMinigameAI', [ State.State('frameworkOff', self.enterFrameworkOff, self.exitFrameworkOff, ['frameworkWaitClientsJoin']), State.State( 'frameworkWaitClientsJoin', self.enterFrameworkWaitClientsJoin, self.exitFrameworkWaitClientsJoin, [ 'frameworkWaitClientsReady', 'frameworkWaitClientsExit', 'frameworkCleanup' ]), State.State( 'frameworkWaitClientsReady', self.enterFrameworkWaitClientsReady, self.exitFrameworkWaitClientsReady, [ 'frameworkGame', 'frameworkWaitClientsExit', 'frameworkCleanup' ]), State.State( 'frameworkGame', self.enterFrameworkGame, self.exitFrameworkGame, ['frameworkWaitClientsExit', 'frameworkCleanup']), State.State('frameworkWaitClientsExit', self.enterFrameworkWaitClientsExit, self.exitFrameworkWaitClientsExit, ['frameworkCleanup']), State.State('frameworkCleanup', self.enterFrameworkCleanup, self.exitFrameworkCleanup, ['frameworkOff']) ], 'frameworkOff', 'frameworkOff') self.frameworkFSM.enterInitialState() self.avIdList = [] self.stateDict = {} self.scoreDict = {} self.difficultyOverride = None self.trolleyZoneOverride = None self.skippable = True self.skipAvIds = [] def addChildGameFSM(self, gameFSM): self.frameworkFSM.getStateNamed('frameworkGame').addChild(gameFSM) def removeChildGameFSM(self, gameFSM): self.frameworkFSM.getStateNamed('frameworkGame').removeChild(gameFSM) def setExpectedAvatars(self, avIds): self.avIdList = avIds self.numPlayers = len(self.avIdList) self.notify.debug('BASE: setExpectedAvatars: expecting avatars: ' + str(self.avIdList)) def setNewbieIds(self, newbieIds): self.newbieIdList = newbieIds if len(self.newbieIdList) > 0: self.notify.debug('BASE: setNewbieIds: %s' % self.newbieIdList) def setTrolleyZone(self, trolleyZone): self.trolleyZone = trolleyZone def setDifficultyOverrides(self, difficultyOverride, trolleyZoneOverride): self.difficultyOverride = difficultyOverride if self.difficultyOverride is not None: self.difficultyOverride = MinigameGlobals.QuantizeDifficultyOverride( difficultyOverride) self.trolleyZoneOverride = trolleyZoneOverride return def _playing(self): if not hasattr(self, 'gameFSM'): return False if self.gameFSM.getCurrentState() == None: return False return self.gameFSM.getCurrentState().getName() == 'play' def _inState(self, states): if not hasattr(self, 'gameFSM'): return False if self.gameFSM.getCurrentState() == None: return False return self.gameFSM.getCurrentState().getName() in makeList(states) def generate(self): DistributedObjectAI.DistributedObjectAI.generate(self) self.frameworkFSM.request('frameworkWaitClientsJoin') def delete(self): self.notify.debug('BASE: delete: deleting AI minigame object') del self.frameworkFSM self.ignoreAll() DistributedObjectAI.DistributedObjectAI.delete(self) def isSinglePlayer(self): if self.numPlayers == 1: return 1 else: return 0 def getParticipants(self): return self.avIdList def getTrolleyZone(self): return self.trolleyZone def getDifficultyOverrides(self): response = [self.difficultyOverride, self.trolleyZoneOverride] if response[0] is None: response[0] = MinigameGlobals.NoDifficultyOverride else: response[0] *= MinigameGlobals.DifficultyOverrideMult response[0] = int(response[0]) if response[1] is None: response[1] = MinigameGlobals.NoTrolleyZoneOverride return response def b_setGameReady(self): self.setGameReady() self.d_setGameReady() def d_setGameReady(self): self.notify.debug('BASE: Sending setGameReady') self.sendUpdate('setGameReady', []) def setGameReady(self): self.notify.debug('BASE: setGameReady: game ready with avatars: %s' % self.avIdList) self.normalExit = 1 def b_setGameStart(self, timestamp): self.d_setGameStart(timestamp) self.setGameStart(timestamp) def d_setGameStart(self, timestamp): self.notify.debug('BASE: Sending setGameStart') self.sendUpdate('setGameStart', [timestamp]) def setGameStart(self, timestamp): self.notify.debug('BASE: setGameStart') def b_setGameExit(self): self.d_setGameExit() self.setGameExit() def d_setGameExit(self): self.notify.debug('BASE: Sending setGameExit') self.sendUpdate('setGameExit', []) def setGameExit(self): self.notify.debug('BASE: setGameExit') def setGameAbort(self): self.notify.debug('BASE: setGameAbort') self.normalExit = 0 self.sendUpdate('setGameAbort', []) self.frameworkFSM.request('frameworkCleanup') def handleExitedAvatar(self, avId): self.notify.warning('BASE: handleExitedAvatar: avatar id exited: ' + str(avId)) self.stateDict[avId] = EXITED self.setGameAbort() def gameOver(self): self.frameworkFSM.request('frameworkWaitClientsExit') def enterFrameworkOff(self): self.notify.debug('BASE: enterFrameworkOff') def exitFrameworkOff(self): pass def enterFrameworkWaitClientsJoin(self): self.notify.debug('BASE: enterFrameworkWaitClientsJoin') for avId in self.avIdList: self.stateDict[avId] = EXPECTED self.scoreDict[avId] = DEFAULT_POINTS self.acceptOnce(self.air.getAvatarExitEvent(avId), self.handleExitedAvatar, extraArgs=[avId]) def allAvatarsJoined(self=self): self.notify.debug('BASE: all avatars joined') self.b_setGameReady() self.frameworkFSM.request('frameworkWaitClientsReady') def handleTimeout(avIds, self=self): self.notify.debug( 'BASE: timed out waiting for clients %s to join' % avIds) self.setGameAbort() self.__barrier = ToonBarrier('waitClientsJoin', self.uniqueName('waitClientsJoin'), self.avIdList, JOIN_TIMEOUT, allAvatarsJoined, handleTimeout) def setAvatarJoined(self): if self.frameworkFSM.getCurrentState().getName( ) != 'frameworkWaitClientsJoin': self.notify.debug('BASE: Ignoring setAvatarJoined message') return avId = self.air.getAvatarIdFromSender() self.notify.debug('BASE: setAvatarJoined: avatar id joined: ' + str(avId)) self.air.writeServerEvent( 'minigame_joined', avId, '%s|%s' % (self.minigameId, self.trolleyZone)) self.stateDict[avId] = JOINED self.notify.debug('BASE: setAvatarJoined: new states: ' + str(self.stateDict)) self.__barrier.clear(avId) def exitFrameworkWaitClientsJoin(self): self.__barrier.cleanup() del self.__barrier def enterFrameworkWaitClientsReady(self): self.notify.debug('BASE: enterFrameworkWaitClientsReady') def allAvatarsReady(self=self): self.notify.debug('BASE: all avatars ready') self.frameworkFSM.request('frameworkGame') def handleTimeout(avIds, self=self): self.notify.debug( "BASE: timed out waiting for clients %s to report 'ready'" % avIds) self.setGameAbort() self.__barrier = ToonBarrier('waitClientsReady', self.uniqueName('waitClientsReady'), self.avIdList, READY_TIMEOUT, allAvatarsReady, handleTimeout) for avId in self.stateDict.keys(): if self.stateDict[avId] == READY: self.__barrier.clear(avId) self.notify.debug(' safezone: %s' % self.getSafezoneId()) self.notify.debug('difficulty: %s' % self.getDifficulty()) def setAvatarReady(self): if self.frameworkFSM.getCurrentState().getName() not in [ 'frameworkWaitClientsReady', 'frameworkWaitClientsJoin' ]: self.notify.debug('BASE: Ignoring setAvatarReady message') return avId = self.air.getAvatarIdFromSender() self.notify.debug('BASE: setAvatarReady: avatar id ready: ' + str(avId)) self.stateDict[avId] = READY self.notify.debug('BASE: setAvatarReady: new avId states: ' + str(self.stateDict)) if self.frameworkFSM.getCurrentState().getName( ) == 'frameworkWaitClientsReady': self.__barrier.clear(avId) self.skippable = False def exitFrameworkWaitClientsReady(self): self.__barrier.cleanup() del self.__barrier def enterFrameworkGame(self): self.notify.debug('BASE: enterFrameworkGame') self.gameStartTime = globalClock.getRealTime() self.b_setGameStart( globalClockDelta.localToNetworkTime(self.gameStartTime)) def exitFrameworkGame(self): pass def enterFrameworkWaitClientsExit(self): self.notify.debug('BASE: enterFrameworkWaitClientsExit') self.b_setGameExit() def allAvatarsExited(self=self): self.notify.debug('BASE: all avatars exited') self.frameworkFSM.request('frameworkCleanup') def handleTimeout(avIds, self=self): self.notify.debug( 'BASE: timed out waiting for clients %s to exit' % avIds) self.frameworkFSM.request('frameworkCleanup') self.__barrier = ToonBarrier('waitClientsExit', self.uniqueName('waitClientsExit'), self.avIdList, EXIT_TIMEOUT, allAvatarsExited, handleTimeout) for avId in self.stateDict.keys(): if self.stateDict[avId] == EXITED: self.__barrier.clear(avId) def setAvatarExited(self): if self.frameworkFSM.getCurrentState().getName( ) != 'frameworkWaitClientsExit': self.notify.debug('BASE: Ignoring setAvatarExit message') return avId = self.air.getAvatarIdFromSender() self.notify.debug('BASE: setAvatarExited: avatar id exited: ' + str(avId)) self.stateDict[avId] = EXITED self.notify.debug('BASE: setAvatarExited: new avId states: ' + str(self.stateDict)) self.__barrier.clear(avId) self.checkForSkip() def exitFrameworkWaitClientsExit(self): self.__barrier.cleanup() del self.__barrier def hasScoreMult(self): return 1 def enterFrameworkCleanup(self): self.notify.debug('BASE: enterFrameworkCleanup: normalExit=%s' % self.normalExit) scoreMult = MinigameGlobals.getScoreMult(self.getSafezoneId()) if not self.hasScoreMult(): scoreMult = 1.0 self.notify.debug('score multiplier: %s' % scoreMult) for avId in self.avIdList: self.scoreDict[avId] *= scoreMult scoreList = [] for avId in self.avIdList: if self.normalExit: score = int(self.scoreDict[avId] + 0.5) else: score = 0 if simbase.air.newsManager.isHolidayRunning( ToontownGlobals.JELLYBEAN_TROLLEY_HOLIDAY ) or simbase.air.newsManager.isHolidayRunning( ToontownGlobals.JELLYBEAN_TROLLEY_HOLIDAY_MONTH): score *= MinigameGlobals.JellybeanTrolleyHolidayScoreMultiplier logEvent = False if score > 255: score = 255 logEvent = True elif score < 0: score = 0 logEvent = True if logEvent: self.air.writeServerEvent( 'suspicious', avId, 'got %s jellybeans playing minigame %s in zone %s' % (score, self.minigameId, self.getSafezoneId())) scoreList.append(score) self.requestDelete() self.handleRegularPurchaseManager(scoreList) self.frameworkFSM.request('frameworkOff') def handleRegularPurchaseManager(self, scoreList): for id in self.newbieIdList: pm = NewbiePurchaseManagerAI.NewbiePurchaseManagerAI( self.air, id, self.avIdList, scoreList, self.minigameId, self.trolleyZone) MinigameCreatorAI.acquireMinigameZone(self.zoneId) pm.generateWithRequired(self.zoneId) if len(self.avIdList) > len(self.newbieIdList): pm = PurchaseManagerAI.PurchaseManagerAI(self.air, self.avIdList, scoreList, self.minigameId, self.trolleyZone, self.newbieIdList) pm.generateWithRequired(self.zoneId) def exitFrameworkCleanup(self): pass def requestExit(self): self.notify.debug( 'BASE: requestExit: client has requested the game to end') self.setGameAbort() def local2GameTime(self, timestamp): return timestamp - self.gameStartTime def game2LocalTime(self, timestamp): return timestamp + self.gameStartTime def getCurrentGameTime(self): return self.local2GameTime(globalClock.getFrameTime()) def getDifficulty(self): if self.difficultyOverride is not None: return self.difficultyOverride if hasattr(self.air, 'minigameDifficulty'): return float(self.air.minigameDifficulty) return MinigameGlobals.getDifficulty(self.getSafezoneId()) def getSafezoneId(self): if self.trolleyZoneOverride is not None: return self.trolleyZoneOverride if hasattr(self.air, 'minigameSafezoneId'): return MinigameGlobals.getSafezoneId(self.air.minigameSafezoneId) return MinigameGlobals.getSafezoneId(self.trolleyZone) def logPerfectGame(self, avId): self.air.writeServerEvent( 'perfectMinigame', avId, '%s|%s|%s' % (self.minigameId, self.trolleyZone, self.avIdList)) def logAllPerfect(self): for avId in self.avIdList: self.logPerfectGame(avId) def requestSkip(self): avId = self.air.getAvatarIdFromSender() if (not self.skippable) or (avId not in self.avIdList) or ( avId in self.skipAvIds): return self.skipAvIds.append(avId) self.checkForSkip() def checkForSkip(self): if len(self.skipAvIds) >= len(self.avIdList): self.skippable = False self.setGameAbort() else: self.sendUpdate('setSkipCount', [len(self.skipAvIds)])
def enterWaitPlayback(self): self.notify.debug('enterWaitPlayback') stillPlayingList = self.golfCourse.getStillPlayingAvIds() self.barrierPlayback = ToonBarrier('waitClientsPlayback', self.uniqueName('waitClientsPlayback'), stillPlayingList, 120, self.handleWaitPlaybackDone, self.handlePlaybackTimeout)
class DistributedGolfHoleAI(DistributedPhysicsWorldAI.DistributedPhysicsWorldAI, FSM, GolfHoleBase.GolfHoleBase): defaultTransitions = {'Off': ['Cleanup', 'WaitTee'], 'WaitTee': ['WaitSwing', 'Cleanup', 'WaitTee', 'WaitPlayback'], 'WaitSwing': ['WaitPlayback', 'Cleanup', 'WaitSwing', 'WaitTee'], 'WaitPlayback': ['WaitSwing', 'Cleanup', 'WaitTee', 'WaitPlayback'], 'Cleanup': ['Off']} id = 0 notify = directNotify.newCategory('DistributedGolfHoleAI') def __init__(self, zoneId, golfCourse, holeId): FSM.__init__(self, 'Golf_%s_FSM' % self.id) DistributedPhysicsWorldAI.DistributedPhysicsWorldAI.__init__(self, simbase.air) GolfHoleBase.GolfHoleBase.__init__(self) self.zoneId = zoneId self.golfCourse = golfCourse self.holeId = holeId self.avIdList = golfCourse.avIdList[:] self.watched = [0, 0, 0, 0] self.barrierPlayback = None self.trustedAvId = None self.activeGolferIndex = None self.activeGolferId = None self.holeInfo = GolfGlobals.HoleInfo[self.holeId] self.teeChosen = {} for avId in self.avIdList: self.teeChosen[avId] = -1 self.ballPos = {} for avId in self.avIdList: self.ballPos[avId] = Vec3(0, 0, 0) self.playStarted = False return def curGolfBall(self): return self.ball def generate(self): DistributedPhysicsWorldAI.DistributedPhysicsWorldAI.generate(self) self.ball = self.createBall() self.createRays() if len(self.teePositions) > 1: startPos = self.teePositions[1] else: startPos = self.teePositions[0] startPos += Vec3(0, 0, GolfGlobals.GOLF_BALL_RADIUS) self.ball.setPosition(startPos) def delete(self): self.notify.debug('__delete__') DistributedPhysicsWorldAI.DistributedPhysicsWorldAI.delete(self) self.notify.debug('calling self.terrainModel.removeNode') self.terrainModel.removeNode() self.notify.debug('self.barrierPlayback is %s' % self.barrierPlayback) if self.barrierPlayback: self.notify.debug('calling self.barrierPlayback.cleanup') self.barrierPlayback.cleanup() self.notify.debug('calling self.barrierPlayback = None') self.barrierPlayback = None self.activeGolferId = None return def setZoneId(self, zoneId): self.zoneId = zoneId def setAvatarReadyHole(self): self.notify.debugStateCall(self) avId = self.air.getAvatarIdFromSender() self.golfCourse.avatarReadyHole(avId) def startPlay(self): self.notify.debug('startPlay') self.playStarted = True self.numGolfers = len(self.golfCourse.getGolferIds()) self.selectNextGolfer() def selectNextGolfer(self): self.notify.debug('selectNextGolfer, old golferIndex=%s old golferId=%s' % (self.activeGolferIndex, self.activeGolferId)) if self.golfCourse.isCurHoleDone(): return if self.activeGolferIndex == None: self.activeGolferIndex = 0 self.activeGolferId = self.golfCourse.getGolferIds()[self.activeGolferIndex] else: self.activeGolferIndex += 1 if self.activeGolferIndex >= len(self.golfCourse.getGolferIds()): self.activeGolferIndex = 0 self.activeGolferId = self.golfCourse.getGolferIds()[self.activeGolferIndex] safety = 0 while safety < 50 and not self.golfCourse.checkGolferPlaying(self.golfCourse.getGolferIds()[self.activeGolferIndex]): self.activeGolferIndex += 1 self.notify.debug('Index %s' % self.activeGolferIndex) if self.activeGolferIndex >= len(self.golfCourse.getGolferIds()): self.activeGolferIndex = 0 self.activeGolferId = self.golfCourse.getGolferIds()[self.activeGolferIndex] safety += 1 if safety != 50: golferId = self.golfCourse.getGolferIds()[self.activeGolferIndex] if self.teeChosen[golferId] == -1: self.sendUpdate('golferChooseTee', [golferId]) self.request('WaitTee') else: self.sendUpdate('golfersTurn', [golferId]) self.request('WaitSwing') else: self.notify.debug('safety') self.notify.debug('selectNextGolfer, new golferIndex=%s new golferId=%s' % (self.activeGolferIndex, self.activeGolferId)) return def clearWatched(self): self.watched = [1, 1, 1, 1] for index in xrange(len(self.golfCourse.getGolferIds())): self.watched[index] = 0 def setWatched(self, avId): for index in xrange(len(self.golfCourse.getGolferIds())): if self.golfCourse.getGolferIds()[index] == avId: self.watched[index] = 1 def checkWatched(self): if 0 not in self.watched: return True else: return False def turnDone(self): self.notify.debug('Turn Done') avId = self.air.getAvatarIdFromSender() if self.barrierPlayback: self.barrierPlayback.clear(avId) def ballInHole(self, golferId = None): self.notify.debug('ballInHole') if golferId: avId = golferId else: avId = self.air.getAvatarIdFromSender() self.golfCourse.setBallIn(avId) if self.golfCourse.isCurHoleDone(): self.notify.debug('ballInHole doing nothing') else: self.notify.debug('ballInHole calling self.selectNextGolfer') self.selectNextGolfer() def getHoleId(self): return self.holeId def finishHole(self): self.notify.debug('finishHole') self.golfCourse.holeOver() def getGolferIds(self): return self.avIdList def loadLevel(self): GolfHoleBase.GolfHoleBase.loadLevel(self) optionalObjects = self.terrainModel.findAllMatches('**/optional*') requiredObjects = self.terrainModel.findAllMatches('**/required*') self.parseLocators(optionalObjects, 1) self.parseLocators(requiredObjects, 0) self.teeNodePath = self.terrainModel.find('**/tee0') if self.teeNodePath.isEmpty(): teePos = Vec3(0, 0, 10) else: teePos = self.teeNodePath.getPos() teePos.setZ(teePos.getZ() + GolfGlobals.GOLF_BALL_RADIUS) self.notify.debug('teeNodePath heading = %s' % self.teeNodePath.getH()) self.teePositions = [teePos] teeIndex = 1 teeNode = self.terrainModel.find('**/tee%d' % teeIndex) while not teeNode.isEmpty(): teePos = teeNode.getPos() teePos.setZ(teePos.getZ() + GolfGlobals.GOLF_BALL_RADIUS) self.teePositions.append(teePos) self.notify.debug('teeNodeP heading = %s' % teeNode.getH()) teeIndex += 1 teeNode = self.terrainModel.find('**/tee%d' % teeIndex) def createLocatorDict(self): self.locDict = {} locatorNum = 1 curNodePath = self.hardSurfaceNodePath.find('**/locator%d' % locatorNum) while not curNodePath.isEmpty(): self.locDict[locatorNum] = curNodePath locatorNum += 1 curNodePath = self.hardSurfaceNodePath.find('**/locator%d' % locatorNum) def loadBlockers(self): loadAll = simbase.config.GetBool('golf-all-blockers', 0) self.createLocatorDict() self.blockerNums = self.holeInfo['blockers'] for locatorNum in self.locDict: if locatorNum in self.blockerNums or loadAll: locator = self.locDict[locatorNum] locatorParent = locator.getParent() locator.getChildren().wrtReparentTo(locatorParent) else: self.locDict[locatorNum].removeNode() self.hardSurfaceNodePath.flattenStrong() def createBall(self): golfBallGeom = self.createSphere(self.world, self.space, GolfGlobals.GOLF_BALL_DENSITY, GolfGlobals.GOLF_BALL_RADIUS, 1)[1] return golfBallGeom def preStep(self): GolfHoleBase.GolfHoleBase.preStep(self) def postStep(self): GolfHoleBase.GolfHoleBase.postStep(self) def postSwing(self, cycleTime, power, x, y, z, dirX, dirY): avId = self.air.getAvatarIdFromSender() self.storeAction = [avId, cycleTime, power, x, y, z, dirX, dirY] if self.commonHoldData: self.doAction() def postSwingState(self, cycleTime, power, x, y, z, dirX, dirY, curAimTime, commonObjectData): self.notify.debug('postSwingState') if not self.golfCourse.getStillPlayingAvIds(): return avId = self.air.getAvatarIdFromSender() self.storeAction = [avId, cycleTime, power, x, y, z, dirX, dirY] self.commonHoldData = commonObjectData self.trustedAvId = self.chooseAvatarToSimulate() self.sendUpdateToAvatarId(self.trustedAvId, 'assignRecordSwing', [avId, cycleTime, power, x, y, z, dirX, dirY, commonObjectData]) self.golfCourse.addAimTime(avId, curAimTime) def chooseAvatarToSimulate(self): stillPlaying = self.golfCourse.getStillPlayingAvIds() return stillPlaying[0] if stillPlaying else 0 def ballMovie2AI(self, cycleTime, avId, movie, spinMovie, ballInFrame, ballTouchedHoleFrame, ballFirstTouchedHoleFrame, commonObjectData): sentFromId = self.air.getAvatarIdFromSender() if sentFromId == self.trustedAvId: lastFrameNum = len(movie) - 2 if lastFrameNum < 0: lastFrameNum = 0 lastFrame = movie[lastFrameNum] lastPos = Vec3(lastFrame[1], lastFrame[2], lastFrame[3]) self.ballPos[avId] = lastPos self.golfCourse.incrementScore(avId) for id in self.golfCourse.getStillPlayingAvIds(): if not id == sentFromId: self.sendUpdateToAvatarId(id, 'ballMovie2Client', [cycleTime, avId, movie, spinMovie, ballInFrame, ballTouchedHoleFrame, ballFirstTouchedHoleFrame, commonObjectData]) if self.state == 'WaitPlayback' or self.state == 'WaitTee': self.notify.warning('ballMovie2AI requesting from %s to WaitPlayback' % self.state) self.request('WaitPlayback') elif self.trustedAvId == None: return else: self.doAction() self.trustedAvId = None return def performReadyAction(self): avId = self.storeAction[0] if self.state == 'WaitPlayback': self.notify.debugStateCall(self) self.notify.debug('ignoring the postSwing for avId=%d since we are in WaitPlayback' % avId) return if avId == self.activeGolferId: self.golfCourse.incrementScore(self.activeGolferId) else: self.notify.warning('activGolferId %d not equal to sender avId %d' % (self.activeGolferId, avId)) if avId not in self.golfCourse.drivingToons: position = self.ballPos[avId] else: position = Vec3(self.storeAction[3], self.storeAction[4], self.storeAction[5]) self.useCommonObjectData(self.commonHoldData) newPos = self.trackRecordBodyFlight(self.ball, self.storeAction[1], self.storeAction[2], position, self.storeAction[6], self.storeAction[7]) if self.state == 'WaitPlayback' or self.state == 'WaitTee': self.notify.warning('performReadyAction requesting from %s to WaitPlayback' % self.state) self.request('WaitPlayback') self.sendUpdate('ballMovie2Client', [self.storeAction[1], avId, self.recording, self.aVRecording, self.ballInHoleFrame, self.ballTouchedHoleFrame, self.ballFirstTouchedHoleFrame, self.commonHoldData]) self.ballPos[avId] = newPos self.trustedAvId = None return def postResult(self, cycleTime, avId, recording, aVRecording, ballInHoleFrame, ballTouchedHoleFrame, ballFirstTouchedHoleFrame): pass def enterWaitSwing(self): pass def exitWaitSwing(self): pass def enterWaitTee(self): pass def exitWaitTee(self): pass def enterWaitPlayback(self): self.notify.debug('enterWaitPlayback') stillPlayingList = self.golfCourse.getStillPlayingAvIds() self.barrierPlayback = ToonBarrier('waitClientsPlayback', self.uniqueName('waitClientsPlayback'), stillPlayingList, 120, self.handleWaitPlaybackDone, self.handlePlaybackTimeout) def hasCurGolferReachedMaxSwing(self): strokes = self.golfCourse.getCurHoleScore(self.activeGolferId) maxSwing = self.holeInfo['maxSwing'] retval = strokes >= maxSwing if retval: av = simbase.air.doId2do.get(self.activeGolferId) if av: if av.getUnlimitedSwing(): retval = False return retval def handleWaitPlaybackDone(self): if self.isCurBallInHole(self.activeGolferId) or self.hasCurGolferReachedMaxSwing(): if self.activeGolferId: self.ballInHole(self.activeGolferId) else: self.selectNextGolfer() def isCurBallInHole(self, golferId): retval = False for holePos in self.holePositions: displacement = self.ballPos[golferId] - holePos length = displacement.length() self.notify.debug('hole %s length=%s' % (holePos, length)) if length <= GolfGlobals.DistanceToBeInHole: retval = True break return retval def exitWaitPlayback(self): self.notify.debug('exitWaitPlayback') if hasattr(self, 'barrierPlayback') and self.barrierPlayback: self.barrierPlayback.cleanup() self.barrierPlayback = None return def enterCleanup(self): pass def exitCleanup(self): pass def handlePlaybackTimeout(self, task = None): self.notify.debug('handlePlaybackTimeout') self.handleWaitPlaybackDone() def getGolfCourseDoId(self): return self.golfCourse.doId def avatarDropped(self, avId): self.notify.warning('avId %d dropped, self.state=%s' % (avId, self.state)) if self.barrierPlayback: self.barrierPlayback.clear(avId) else: if avId == self.trustedAvId: self.doAction() if avId == self.activeGolferId and not self.golfCourse.haveAllGolfersExited(): self.selectNextGolfer() def setAvatarTee(self, chosenTee): golferId = self.air.getAvatarIdFromSender() self.teeChosen[golferId] = chosenTee self.ballPos[golferId] = self.teePositions[chosenTee] self.sendUpdate('setAvatarFinalTee', [golferId, chosenTee]) self.sendUpdate('golfersTurn', [golferId]) self.request('WaitSwing') def setBox(self, pos0, pos1, pos2, quat0, quat1, quat2, quat3, anV0, anV1, anV2, lnV0, lnV1, lnV2): self.sendUpdate('sendBox', [pos0, pos1, pos2, quat0, quat1, quat2, quat3, anV0, anV1, anV2, lnV0, lnV1, lnV2]) def parseLocators(self, objectCollection, optional = 0): if optional and objectCollection.getNumPaths(): if 'optionalMovers' in self.holeInfo: for optionalMoverId in self.holeInfo['optionalMovers']: searchStr = 'optional_mover_' + str(optionalMoverId) for objIndex in xrange(objectCollection.getNumPaths()): object = objectCollection.getPath(objIndex) if searchStr in object.getName(): self.fillLocator(objectCollection, objIndex) break else: for index in xrange(objectCollection.getNumPaths()): self.fillLocator(objectCollection, index) def fillLocator(self, objectCollection, index): path = objectCollection[index] pathName = path.getName() pathArray = pathName.split('_') sizeX = None sizeY = None move = None type = None for subString in pathArray: if subString[:1] == 'X': dataString = subString[1:] dataString = dataString.replace('p', '.') sizeX = float(dataString) elif subString[:1] == 'Y': dataString = subString[1:] dataString = dataString.replace('p', '.') sizeY = float(dataString) elif subString[:1] == 'd': dataString = subString[1:] dataString = dataString.replace('p', '.') move = float(dataString) elif subString == 'mover': type = 4 elif subString == 'windmillLocator': type = 3 if type == 4 and move and sizeX and sizeY: self.createCommonObject(4, path.getPos(), path.getHpr(), sizeX, sizeY, move) elif type == 3: self.createCommonObject(3, path.getPos(), path.getHpr()) return
class DistributedTwoDGameAI(DistributedMinigameAI): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedTwoDGameAI') def __init__(self, air, minigameId): try: self.DistributedTwoDGameAI_initialized except: self.DistributedTwoDGame_initialized = 1 DistributedMinigameAI.__init__(self, air, minigameId) self.gameFSM = ClassicFSM.ClassicFSM('DistributedTwoDGameAI', [ State.State('inactive', self.enterInactive, self.exitInactive, ['play']), State.State('play', self.enterPlay, self.exitPlay, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, ['inactive']) ], 'inactive', 'inactive') self.addChildGameFSM(self.gameFSM) self.finishedBonusDict = {} self.finishedTimeLeftDict = {} self.numFallDownDict = {} self.numHitByEnemyDict = {} self.numSquishDict = {} self.treasuresCollectedDict = {} self.sectionsSelected = [] self.enemyHealthTable = [] self.treasureTakenTable = [] self.sectionIndexList = [] def generate(self): self.notify.debug('generate') DistributedMinigameAI.generate(self) def delete(self): self.notify.debug('delete') del self.gameFSM DistributedMinigameAI.delete(self) def setTrolleyZone(self, trolleyZone): DistributedMinigameAI.setTrolleyZone(self, trolleyZone) self.setupSections() def setGameReady(self): self.notify.debug('setGameReady') DistributedMinigameAI.setGameReady(self) self.numTreasures = ToonBlitzGlobals.NumTreasures self.numEnemies = ToonBlitzGlobals.NumEnemies self.numTreasuresTaken = 0 self.numEnemiesKilled = 0 for avId in self.scoreDict.keys(): self.scoreDict[avId] = 0 self.finishedBonusDict[avId] = 0 self.finishedTimeLeftDict[avId] = -1 self.numFallDownDict[avId] = 0 self.numHitByEnemyDict[avId] = 0 self.numSquishDict[avId] = 0 self.treasuresCollectedDict[avId] = [0, 0, 0, 0] for i in xrange(len(self.sectionsSelected)): sectionIndex = self.sectionsSelected[i][0] attribs = ToonBlitzGlobals.SectionTypes[sectionIndex] enemiesPool = attribs[3] self.enemyHealthTable += [[]] enemyIndicesSelected = self.sectionsSelected[i][1] for j in xrange(len(enemyIndicesSelected)): enemyIndex = enemyIndicesSelected[j] enemyType = enemiesPool[enemyIndex][0] self.enemyHealthTable[i] += [ToonBlitzGlobals.EnemyBaseHealth] self.enemyHealthTable[i][j] *= self.numPlayers if enemyType in ToonBlitzGlobals.EnemyHealthMultiplier: self.enemyHealthTable[i][ j] *= ToonBlitzGlobals.EnemyHealthMultiplier[enemyType] self.treasureTakenTable += [[]] treasureIndicesSelected = self.sectionsSelected[i][2] for j in xrange(len(treasureIndicesSelected)): self.treasureTakenTable[i] += [0] enemyIndicesSelected = self.sectionsSelected[i][1] for j in xrange(len(enemyIndicesSelected)): self.treasureTakenTable[i] += [0] def setGameStart(self, timestamp): self.notify.debug('setGameStart') DistributedMinigameAI.setGameStart(self, timestamp) self.gameFSM.request('play') def setGameAbort(self): self.notify.debug('setGameAbort') if self.gameFSM.getCurrentState(): self.gameFSM.request('cleanup') DistributedMinigameAI.setGameAbort(self) def gameOver(self): self.notify.debug('gameOver') scoreList = [] finishedBonusList = [] timeLeftList = [] treasureCollectedList = [] playerErrorList = [] for avId in self.avIdList: scoreList.append(self.scoreDict[avId]) finishedBonusList.append(self.finishedBonusDict[avId]) timeLeftList.append(self.finishedTimeLeftDict[avId]) treasureCollectedList.append(self.treasuresCollectedDict[avId]) playerError = [ self.numFallDownDict[avId], self.numHitByEnemyDict[avId], self.numSquishDict[avId] ] playerErrorList.append(playerError) self.scoreDict[avId] = max(0, self.scoreDict[avId]) jellybeans = sqrt(self.scoreDict[avId] * ToonBlitzGlobals.ScoreToJellyBeansMultiplier) self.scoreDict[avId] = max(1, int(jellybeans)) self.air.writeServerEvent( 'minigame_twoD', self.doId, '%s|%s|%s|%s|%s|%s|%s|%s|%s' % (ToontownGlobals.TwoDGameId, self.getSafezoneId(), self.avIdList, scoreList, finishedBonusList, timeLeftList, treasureCollectedList, playerErrorList, self.sectionIndexList)) self.notify.debug( 'minigame_twoD%s: %s|%s|%s|%s|%s|%s|%s|%s|%s' % (self.doId, ToontownGlobals.TwoDGameId, self.getSafezoneId(), self.avIdList, scoreList, finishedBonusList, timeLeftList, treasureCollectedList, playerErrorList, self.sectionIndexList)) self.gameFSM.request('cleanup') DistributedMinigameAI.gameOver(self) def enterInactive(self): self.notify.debug('enterInactive') def exitInactive(self): pass def enterPlay(self): self.notify.debug('enterPlay') def allToonsDone(self=self): self.notify.debug('allToonsDone') self.sendUpdate('setEveryoneDone') if not ToonBlitzGlobals.EndlessGame: self.gameOver() def handleTimeout(avIds, self=self): self.notify.debug( 'handleTimeout: avatars %s did not report "done"' % avIds) self.setGameAbort() self.doneBarrier = ToonBarrier( 'waitClientsDone', self.uniqueName('waitClientsDone'), self.avIdList, ToonBlitzGlobals.GameDuration[self.getSafezoneId()] + ToonBlitzGlobals.ShowScoresDuration + MinigameGlobals.latencyTolerance, allToonsDone, handleTimeout) def exitPlay(self): pass def enterCleanup(self): self.notify.debug('enterCleanup') self.doneBarrier.cleanup() del self.doneBarrier self.gameFSM.request('inactive') def exitCleanup(self): pass def claimTreasure(self, sectionIndex, treasureIndex): avId = self.air.getAvatarIdFromSender() self.notify.debug('treasure %s-%s claimed by %s' % (sectionIndex, treasureIndex, avId)) if sectionIndex < 0 or sectionIndex >= len(self.sectionsSelected): self.air.writeServerEvent( 'warning', sectionIndex, 'TwoDGameAI.claimTreasure sectionIndex out of range.') return if treasureIndex < 0 or treasureIndex >= len( self.treasureTakenTable[sectionIndex]): self.notify.warning( 'Treasure %s: TwoDGameAI.claimTreasure treasureIndex out of range.' % treasureIndex) self.air.writeServerEvent( 'warning', treasureIndex, 'TwoDGameAI.claimTreasure treasureIndex out of range.') return if self.treasureTakenTable[sectionIndex][treasureIndex]: return initialTreasureList = self.sectionsSelected[sectionIndex][2] if treasureIndex < len(initialTreasureList): treasureValue = initialTreasureList[treasureIndex][1] else: treasureValue = self.numPlayers self.treasureTakenTable[sectionIndex][treasureIndex] = treasureValue self.treasuresCollectedDict[avId][treasureValue - 1] += 1 self.scoreDict[ avId] += ToonBlitzGlobals.ScoreGainPerTreasure * treasureValue self.numTreasuresTaken += 1 self.sendUpdate('setTreasureGrabbed', [avId, sectionIndex, treasureIndex]) def claimEnemyShot(self, sectionIndex, enemyIndex): avId = self.air.getAvatarIdFromSender() self.notify.debug('enemy %s-%s shot claimed by %s' % (sectionIndex, enemyIndex, avId)) if sectionIndex < 0 or sectionIndex >= len(self.sectionsSelected): self.air.writeServerEvent( 'warning', sectionIndex, 'TwoDGameAI.claimEnemyShot sectionIndex out of range.') return if enemyIndex < 0 or enemyIndex >= len( self.sectionsSelected[sectionIndex][1]): self.air.writeServerEvent( 'warning', enemyIndex, 'TwoDGameAI.claimEnemyShot enemyIndex out of range.') return if self.enemyHealthTable[sectionIndex][enemyIndex] > 0: self.enemyHealthTable[sectionIndex][ enemyIndex] -= ToonBlitzGlobals.DamagePerBullet if self.enemyHealthTable[sectionIndex][enemyIndex] <= 0: self.numEnemiesKilled += 1 self.sendUpdate('setEnemyShot', [ avId, sectionIndex, enemyIndex, self.enemyHealthTable[sectionIndex][enemyIndex] ]) def reportDone(self): if self.gameFSM.getCurrentState( ) == None or self.gameFSM.getCurrentState().getName() != 'play': return avId = self.air.getAvatarIdFromSender() self.notify.debug('reportDone: avatar %s is done' % avId) self.doneBarrier.clear(avId) return def toonVictory(self, avId, timestamp): if self.gameFSM.getCurrentState( ) == None or self.gameFSM.getCurrentState().getName() != 'play': msg = 'TwoDGameAI.toonVictory not in play state!' self.notify.warning('suspicious: ' + str(avId) + ' ' + msg) self.air.writeServerEvent('suspicious: ', avId, msg) return if avId not in self.scoreDict.keys(): self.notify.warning('Avatar %s not in list.' % avId) self.air.writeServerEvent( 'suspicious: ', avId, 'TwoDGameAI.toonVictory toon not in list.') return curTime = self.getCurrentGameTime() timeLeft = ToonBlitzGlobals.GameDuration[ self.getSafezoneId()] - curTime self.notify.debug('curTime =%s timeLeft = %s' % (curTime, timeLeft)) addBonus = int( ToonBlitzGlobals.BaseBonusOnCompletion[self.getSafezoneId()] + ToonBlitzGlobals.BonusPerSecondLeft * timeLeft) self.notify.debug('addBOnus = %d' % addBonus) if addBonus < 0: addBonus = 0 self.finishedBonusDict[avId] = addBonus timeLeftStr = '%.1f' % timeLeft self.finishedTimeLeftDict[avId] = timeLeftStr self.scoreDict[avId] += addBonus self.sendUpdate('addVictoryScore', [avId, addBonus]) self.doneBarrier.clear(avId) return def toonFellDown(self, avId, timestamp): if avId not in self.scoreDict.keys(): self.notify.warning('Avatar %s not in list.' % avId) self.air.writeServerEvent( 'warning', avId, 'TwoDGameAI.toonFellDown toon not in list.') return self.numFallDownDict[avId] += 1 self.scoreDict[avId] += ToonBlitzGlobals.ScoreLossPerFallDown[ self.getSafezoneId()] def toonHitByEnemy(self, avId, timestamp): if avId not in self.scoreDict.keys(): self.notify.warning('Avatar %s not in list.' % avId) self.air.writeServerEvent( 'warning', avId, 'TwoDGameAI.toonHitByEnemy toon not in list.') return self.numHitByEnemyDict[avId] += 1 self.scoreDict[avId] += ToonBlitzGlobals.ScoreLossPerEnemyCollision[ self.getSafezoneId()] def toonSquished(self, avId, timestamp): if avId not in self.scoreDict.keys(): self.notify.warning('Avatar %s not in list.' % avId) self.air.writeServerEvent( 'warning', avId, 'TwoDGameAI.toonSquished toon not in list.') return self.numSquishDict[avId] += 1 self.scoreDict[avId] += ToonBlitzGlobals.ScoreLossPerStomperSquish[ self.getSafezoneId()] def setupSections(self): szId = self.getSafezoneId() sectionWeights = ToonBlitzGlobals.SectionWeights[szId] numSections = ToonBlitzGlobals.NumSections[szId] difficultyPool = [] difficultyList = [] sectionsPool = ToonBlitzGlobals.SectionsPool sectionTypes = ToonBlitzGlobals.SectionTypes sectionsPoolByDifficulty = [[], [], [], [], [], []] sectionsSelectedByDifficulty = [[], [], [], [], [], []] sectionIndicesSelected = [] for weight in sectionWeights: difficulty, probability = weight difficultyPool += [difficulty] * probability for i in xrange(numSections): difficulty = random.choice(difficultyPool) difficultyList.append(difficulty) difficultyList.sort() for sectionIndex in sectionsPool: difficulty = sectionTypes[sectionIndex][0] sectionsPoolByDifficulty[difficulty] += [sectionIndex] for targetDifficulty in difficultyList: whileCount = 0 difficulty = targetDifficulty while not len(sectionsPoolByDifficulty[difficulty]) > 0: difficulty += 1 if difficulty >= 5: difficulty = 0 whileCount += 1 if whileCount > 1: break else: sectionIndexChoice = random.choice( sectionsPoolByDifficulty[difficulty]) sectionsSelectedByDifficulty[difficulty] += [ sectionIndexChoice ] sectionsPoolByDifficulty[difficulty].remove(sectionIndexChoice) if whileCount > 1: self.notify.debug( 'We need more sections than we have choices. We have to now repeat.' ) for i in xrange(len(sectionsSelectedByDifficulty)): for j in xrange(len(sectionsSelectedByDifficulty[i])): sectionIndicesSelected.append( sectionsSelectedByDifficulty[i][j]) for i in xrange(len(sectionIndicesSelected)): sectionIndex = sectionIndicesSelected[i] self.sectionIndexList.append(sectionIndex) attribs = sectionTypes[sectionIndex] difficulty = attribs[0] length = attribs[1] blocksPool = attribs[2] enemiesPool = attribs[3] treasuresPool = attribs[4] spawnPointsPool = attribs[5] stompersPool = attribs[6] enemyIndicesPool = [] enemyIndicesSelected = [] if enemiesPool != None: minEnemies, maxEnemies = attribs[7] for i in xrange(len(enemiesPool)): enemyIndicesPool += [i] numEnemies = maxEnemies * ToonBlitzGlobals.PercentMaxEnemies[ szId] / 100 numEnemies = max(numEnemies, minEnemies) for j in xrange(int(numEnemies)): if len(enemyIndicesPool) == 0: break enemyIndex = random.choice(enemyIndicesPool) enemyIndicesSelected.append(enemyIndex) enemyIndicesPool.remove(enemyIndex) enemyIndicesSelected.sort() treasureIndicesPool = [] treasureValuePool = [] for value in xrange(1, 5): treasureValuePool += [ value ] * ToonBlitzGlobals.TreasureValueProbability[value] treasureIndicesSelected = [] if treasuresPool != None: minTreasures, maxTreasures = attribs[8] for i in xrange(len(treasuresPool)): treasureIndicesPool += [i] numTreasures = maxTreasures * ToonBlitzGlobals.PercentMaxTreasures[ szId] / 100 numTreasures = max(numTreasures, minTreasures) for i in xrange(int(numTreasures)): if len(treasureIndicesPool) == 0: break treasureIndex = random.choice(treasureIndicesPool) treasureValue = random.choice(treasureValuePool) treasure = (treasureIndex, treasureValue) treasureIndicesPool.remove(treasureIndex) treasureIndicesSelected.append(treasure) treasureIndicesSelected.sort() spawnPointIndicesPool = [] spawnPointIndicesSelected = [] if spawnPointsPool != None: minSpawnPoints, maxSpawnPoints = attribs[9] for i in xrange(len(spawnPointsPool)): spawnPointIndicesPool += [i] numSpawnPoints = maxSpawnPoints * ToonBlitzGlobals.PercentMaxSpawnPoints[ szId] / 100 numSpawnPoints = max(numSpawnPoints, minSpawnPoints) for i in xrange(int(numSpawnPoints)): if len(spawnPointIndicesPool) == 0: break spawnPoint = random.choice(spawnPointIndicesPool) spawnPointIndicesSelected.append(spawnPoint) spawnPointIndicesPool.remove(spawnPoint) spawnPointIndicesSelected.sort() stomperIndicesPool = [] stomperIndicesSelected = [] if stompersPool != None: minStompers, maxStompers = attribs[10] for i in xrange(len(stompersPool)): stomperIndicesPool += [i] numStompers = maxStompers * ToonBlitzGlobals.PercentMaxStompers[ szId] / 100 numStompers = max(numStompers, minStompers) for i in xrange(int(numStompers)): if len(stomperIndicesPool) == 0: break stomper = random.choice(stomperIndicesPool) stomperIndicesSelected.append(stomper) stomperIndicesPool.remove(stomper) stomperIndicesSelected.sort() sctionTuple = (sectionIndex, enemyIndicesSelected, treasureIndicesSelected, spawnPointIndicesSelected, stomperIndicesSelected) self.sectionsSelected.append(sctionTuple) return def getSectionsSelected(self): return self.sectionsSelected
def enterWaitReward(self): self.updateHistoryForCourseComplete() self.awardTrophies() self.awardCups() self.awardHoleBest() self.awardCourseBest() self.recordHoleInOne() self.recordCourseUnderPar() trophiesList = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] if avId in self.newTrophies: oneTrophyList = self.newTrophies[avId] trophiesList.append(oneTrophyList) else: trophiesList.append([]) while len(trophiesList) < GolfGlobals.MAX_PLAYERS_PER_HOLE: trophiesList.append([]) holeBestList = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] if avId in self.newHoleBest: oneTrophyList = self.newHoleBest[avId] holeBestList.append(oneTrophyList) else: holeBestList.append([]) while len(holeBestList) < GolfGlobals.MAX_PLAYERS_PER_HOLE: holeBestList.append([]) courseBestList = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] if avId in self.newCourseBest: oneTrophyList = self.newCourseBest[avId] courseBestList.append(oneTrophyList) else: courseBestList.append([]) while len(courseBestList) < GolfGlobals.MAX_PLAYERS_PER_HOLE: courseBestList.append([]) cupList = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] if avId in self.newCups: oneCupList = self.newCups[avId] cupList.append(oneCupList) self.cupListLen = self.cupListLen + 1 else: cupList.append([]) while len(cupList) < GolfGlobals.MAX_PLAYERS_PER_HOLE: cupList.append([]) REWARD_TIMEOUT = (self.trophyListLen + self.holeBestListLen + self.courseBestListLen + self.cupListLen) * 5 + 19 aimTimesList = [0] * 4 aimIndex = 0 stillPlaying = self.getStillPlayingAvIds() for avId in self.avIdList: if avId in stillPlaying: aimTime = 0 if avId in self.aimTimes: aimTime = self.aimTimes[avId] aimTimesList[aimIndex] = aimTime aimIndex += 1 self.sendUpdate('setReward', [trophiesList, self.rankings, holeBestList, courseBestList, cupList, self.winnerByTieBreak, aimTimesList[0], aimTimesList[1], aimTimesList[2], aimTimesList[3]]) def allAvatarsRewarded(self = self): self.notify.debug('GOLF COURSE: all avatars rewarded') self.rewardDone() def handleRewardTimeout(avIds, self = self): self.notify.debug('GOLF COURSE: timed out waiting for clients %s to finish reward' % avIds) self.rewardDone() stillPlaying = self.getStillPlayingAvIds() self.rewardBarrier = ToonBarrier('waitReward', self.uniqueName('waitReward'), stillPlaying, REWARD_TIMEOUT, allAvatarsRewarded, handleRewardTimeout)
class DistributedTwoDGameAI(DistributedMinigameAI): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedTwoDGameAI') def __init__(self, air, minigameId): try: self.DistributedTwoDGameAI_initialized except: self.DistributedTwoDGame_initialized = 1 DistributedMinigameAI.__init__(self, air, minigameId) self.gameFSM = ClassicFSM.ClassicFSM('DistributedTwoDGameAI', [State.State('inactive', self.enterInactive, self.exitInactive, ['play']), State.State('play', self.enterPlay, self.exitPlay, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, ['inactive'])], 'inactive', 'inactive') self.addChildGameFSM(self.gameFSM) self.finishedBonusDict = {} self.finishedTimeLeftDict = {} self.numFallDownDict = {} self.numHitByEnemyDict = {} self.numSquishDict = {} self.treasuresCollectedDict = {} self.sectionsSelected = [] self.enemyHealthTable = [] self.treasureTakenTable = [] self.sectionIndexList = [] def generate(self): self.notify.debug('generate') DistributedMinigameAI.generate(self) def delete(self): self.notify.debug('delete') del self.gameFSM DistributedMinigameAI.delete(self) def setTrolleyZone(self, trolleyZone): DistributedMinigameAI.setTrolleyZone(self, trolleyZone) self.setupSections() def setGameReady(self): self.notify.debug('setGameReady') DistributedMinigameAI.setGameReady(self) self.numTreasures = ToonBlitzGlobals.NumTreasures self.numEnemies = ToonBlitzGlobals.NumEnemies self.numTreasuresTaken = 0 self.numEnemiesKilled = 0 for avId in self.scoreDict.keys(): self.scoreDict[avId] = 0 self.finishedBonusDict[avId] = 0 self.finishedTimeLeftDict[avId] = -1 self.numFallDownDict[avId] = 0 self.numHitByEnemyDict[avId] = 0 self.numSquishDict[avId] = 0 self.treasuresCollectedDict[avId] = [0, 0, 0, 0] for i in xrange(len(self.sectionsSelected)): sectionIndex = self.sectionsSelected[i][0] attribs = ToonBlitzGlobals.SectionTypes[sectionIndex] enemiesPool = attribs[3] self.enemyHealthTable += [[]] enemyIndicesSelected = self.sectionsSelected[i][1] for j in xrange(len(enemyIndicesSelected)): enemyIndex = enemyIndicesSelected[j] enemyType = enemiesPool[enemyIndex][0] self.enemyHealthTable[i] += [ToonBlitzGlobals.EnemyBaseHealth] self.enemyHealthTable[i][j] *= self.numPlayers if enemyType in ToonBlitzGlobals.EnemyHealthMultiplier: self.enemyHealthTable[i][j] *= ToonBlitzGlobals.EnemyHealthMultiplier[enemyType] self.treasureTakenTable += [[]] treasureIndicesSelected = self.sectionsSelected[i][2] for j in xrange(len(treasureIndicesSelected)): self.treasureTakenTable[i] += [0] enemyIndicesSelected = self.sectionsSelected[i][1] for j in xrange(len(enemyIndicesSelected)): self.treasureTakenTable[i] += [0] def setGameStart(self, timestamp): self.notify.debug('setGameStart') DistributedMinigameAI.setGameStart(self, timestamp) self.gameFSM.request('play') def setGameAbort(self): self.notify.debug('setGameAbort') if self.gameFSM.getCurrentState(): self.gameFSM.request('cleanup') DistributedMinigameAI.setGameAbort(self) def gameOver(self): self.notify.debug('gameOver') scoreList = [] finishedBonusList = [] timeLeftList = [] treasureCollectedList = [] playerErrorList = [] for avId in self.avIdList: scoreList.append(self.scoreDict[avId]) finishedBonusList.append(self.finishedBonusDict[avId]) timeLeftList.append(self.finishedTimeLeftDict[avId]) treasureCollectedList.append(self.treasuresCollectedDict[avId]) playerError = [self.numFallDownDict[avId], self.numHitByEnemyDict[avId], self.numSquishDict[avId]] playerErrorList.append(playerError) self.scoreDict[avId] = max(0, self.scoreDict[avId]) jellybeans = sqrt(self.scoreDict[avId] * ToonBlitzGlobals.ScoreToJellyBeansMultiplier) self.scoreDict[avId] = max(1, int(jellybeans)) self.air.writeServerEvent('minigame_twoD', self.doId, '%s|%s|%s|%s|%s|%s|%s|%s|%s' % (ToontownGlobals.TwoDGameId, self.getSafezoneId(), self.avIdList, scoreList, finishedBonusList, timeLeftList, treasureCollectedList, playerErrorList, self.sectionIndexList)) self.notify.debug('minigame_twoD%s: %s|%s|%s|%s|%s|%s|%s|%s|%s' % (self.doId, ToontownGlobals.TwoDGameId, self.getSafezoneId(), self.avIdList, scoreList, finishedBonusList, timeLeftList, treasureCollectedList, playerErrorList, self.sectionIndexList)) self.gameFSM.request('cleanup') DistributedMinigameAI.gameOver(self) def enterInactive(self): self.notify.debug('enterInactive') def exitInactive(self): pass def enterPlay(self): self.notify.debug('enterPlay') def allToonsDone(self = self): self.notify.debug('allToonsDone') self.sendUpdate('setEveryoneDone') if not ToonBlitzGlobals.EndlessGame: self.gameOver() def handleTimeout(avIds, self = self): self.notify.debug('handleTimeout: avatars %s did not report "done"' % avIds) self.setGameAbort() self.doneBarrier = ToonBarrier('waitClientsDone', self.uniqueName('waitClientsDone'), self.avIdList, ToonBlitzGlobals.GameDuration[self.getSafezoneId()] + ToonBlitzGlobals.ShowScoresDuration + MinigameGlobals.latencyTolerance, allToonsDone, handleTimeout) def exitPlay(self): pass def enterCleanup(self): self.notify.debug('enterCleanup') self.doneBarrier.cleanup() del self.doneBarrier self.gameFSM.request('inactive') def exitCleanup(self): pass def claimTreasure(self, sectionIndex, treasureIndex): avId = self.air.getAvatarIdFromSender() self.notify.debug('treasure %s-%s claimed by %s' % (sectionIndex, treasureIndex, avId)) if sectionIndex < 0 or sectionIndex >= len(self.sectionsSelected): self.air.writeServerEvent('warning', sectionIndex, 'TwoDGameAI.claimTreasure sectionIndex out of range.') return if treasureIndex < 0 or treasureIndex >= len(self.treasureTakenTable[sectionIndex]): self.notify.warning('Treasure %s: TwoDGameAI.claimTreasure treasureIndex out of range.' % treasureIndex) self.air.writeServerEvent('warning', treasureIndex, 'TwoDGameAI.claimTreasure treasureIndex out of range.') return if self.treasureTakenTable[sectionIndex][treasureIndex]: return initialTreasureList = self.sectionsSelected[sectionIndex][2] if treasureIndex < len(initialTreasureList): treasureValue = initialTreasureList[treasureIndex][1] else: treasureValue = self.numPlayers self.treasureTakenTable[sectionIndex][treasureIndex] = treasureValue self.treasuresCollectedDict[avId][treasureValue - 1] += 1 self.scoreDict[avId] += ToonBlitzGlobals.ScoreGainPerTreasure * treasureValue self.numTreasuresTaken += 1 self.sendUpdate('setTreasureGrabbed', [avId, sectionIndex, treasureIndex]) def claimEnemyShot(self, sectionIndex, enemyIndex): avId = self.air.getAvatarIdFromSender() self.notify.debug('enemy %s-%s shot claimed by %s' % (sectionIndex, enemyIndex, avId)) if sectionIndex < 0 or sectionIndex >= len(self.sectionsSelected): self.air.writeServerEvent('warning', sectionIndex, 'TwoDGameAI.claimEnemyShot sectionIndex out of range.') return if enemyIndex < 0 or enemyIndex >= len(self.sectionsSelected[sectionIndex][1]): self.air.writeServerEvent('warning', enemyIndex, 'TwoDGameAI.claimEnemyShot enemyIndex out of range.') return if self.enemyHealthTable[sectionIndex][enemyIndex] > 0: self.enemyHealthTable[sectionIndex][enemyIndex] -= ToonBlitzGlobals.DamagePerBullet if self.enemyHealthTable[sectionIndex][enemyIndex] <= 0: self.numEnemiesKilled += 1 self.sendUpdate('setEnemyShot', [avId, sectionIndex, enemyIndex, self.enemyHealthTable[sectionIndex][enemyIndex]]) def reportDone(self): if self.gameFSM.getCurrentState() == None or self.gameFSM.getCurrentState().getName() != 'play': return avId = self.air.getAvatarIdFromSender() self.notify.debug('reportDone: avatar %s is done' % avId) self.doneBarrier.clear(avId) return def toonVictory(self, avId, timestamp): if self.gameFSM.getCurrentState() == None or self.gameFSM.getCurrentState().getName() != 'play': msg = 'TwoDGameAI.toonVictory not in play state!' self.notify.warning('suspicious: ' + str(avId) + ' ' + msg) self.air.writeServerEvent('suspicious: ', avId, msg) return if avId not in self.scoreDict.keys(): self.notify.warning('Avatar %s not in list.' % avId) self.air.writeServerEvent('suspicious: ', avId, 'TwoDGameAI.toonVictory toon not in list.') return curTime = self.getCurrentGameTime() timeLeft = ToonBlitzGlobals.GameDuration[self.getSafezoneId()] - curTime self.notify.debug('curTime =%s timeLeft = %s' % (curTime, timeLeft)) addBonus = int(ToonBlitzGlobals.BaseBonusOnCompletion[self.getSafezoneId()] + ToonBlitzGlobals.BonusPerSecondLeft * timeLeft) self.notify.debug('addBOnus = %d' % addBonus) if addBonus < 0: addBonus = 0 self.finishedBonusDict[avId] = addBonus timeLeftStr = '%.1f' % timeLeft self.finishedTimeLeftDict[avId] = timeLeftStr self.scoreDict[avId] += addBonus self.sendUpdate('addVictoryScore', [avId, addBonus]) self.doneBarrier.clear(avId) return def toonFellDown(self, avId, timestamp): if avId not in self.scoreDict.keys(): self.notify.warning('Avatar %s not in list.' % avId) self.air.writeServerEvent('warning', avId, 'TwoDGameAI.toonFellDown toon not in list.') return self.numFallDownDict[avId] += 1 self.scoreDict[avId] += ToonBlitzGlobals.ScoreLossPerFallDown[self.getSafezoneId()] def toonHitByEnemy(self, avId, timestamp): if avId not in self.scoreDict.keys(): self.notify.warning('Avatar %s not in list.' % avId) self.air.writeServerEvent('warning', avId, 'TwoDGameAI.toonHitByEnemy toon not in list.') return self.numHitByEnemyDict[avId] += 1 self.scoreDict[avId] += ToonBlitzGlobals.ScoreLossPerEnemyCollision[self.getSafezoneId()] def toonSquished(self, avId, timestamp): if avId not in self.scoreDict.keys(): self.notify.warning('Avatar %s not in list.' % avId) self.air.writeServerEvent('warning', avId, 'TwoDGameAI.toonSquished toon not in list.') return self.numSquishDict[avId] += 1 self.scoreDict[avId] += ToonBlitzGlobals.ScoreLossPerStomperSquish[self.getSafezoneId()] def setupSections(self): szId = self.getSafezoneId() sectionWeights = ToonBlitzGlobals.SectionWeights[szId] numSections = ToonBlitzGlobals.NumSections[szId] difficultyPool = [] difficultyList = [] sectionsPool = ToonBlitzGlobals.SectionsPool sectionTypes = ToonBlitzGlobals.SectionTypes sectionsPoolByDifficulty = [[], [], [], [], [], []] sectionsSelectedByDifficulty = [[], [], [], [], [], []] sectionIndicesSelected = [] for weight in sectionWeights: difficulty, probability = weight difficultyPool += [difficulty] * probability for i in xrange(numSections): difficulty = random.choice(difficultyPool) difficultyList.append(difficulty) difficultyList.sort() for sectionIndex in sectionsPool: difficulty = sectionTypes[sectionIndex][0] sectionsPoolByDifficulty[difficulty] += [sectionIndex] for targetDifficulty in difficultyList: whileCount = 0 difficulty = targetDifficulty while not len(sectionsPoolByDifficulty[difficulty]) > 0: difficulty += 1 if difficulty >= 5: difficulty = 0 whileCount += 1 if whileCount > 1: break else: sectionIndexChoice = random.choice(sectionsPoolByDifficulty[difficulty]) sectionsSelectedByDifficulty[difficulty] += [sectionIndexChoice] sectionsPoolByDifficulty[difficulty].remove(sectionIndexChoice) if whileCount > 1: self.notify.debug('We need more sections than we have choices. We have to now repeat.') for i in xrange(len(sectionsSelectedByDifficulty)): for j in xrange(len(sectionsSelectedByDifficulty[i])): sectionIndicesSelected.append(sectionsSelectedByDifficulty[i][j]) for i in xrange(len(sectionIndicesSelected)): sectionIndex = sectionIndicesSelected[i] self.sectionIndexList.append(sectionIndex) attribs = sectionTypes[sectionIndex] difficulty = attribs[0] length = attribs[1] blocksPool = attribs[2] enemiesPool = attribs[3] treasuresPool = attribs[4] spawnPointsPool = attribs[5] stompersPool = attribs[6] enemyIndicesPool = [] enemyIndicesSelected = [] if enemiesPool != None: minEnemies, maxEnemies = attribs[7] for i in xrange(len(enemiesPool)): enemyIndicesPool += [i] numEnemies = maxEnemies * ToonBlitzGlobals.PercentMaxEnemies[szId] / 100 numEnemies = max(numEnemies, minEnemies) for j in xrange(int(numEnemies)): if len(enemyIndicesPool) == 0: break enemyIndex = random.choice(enemyIndicesPool) enemyIndicesSelected.append(enemyIndex) enemyIndicesPool.remove(enemyIndex) enemyIndicesSelected.sort() treasureIndicesPool = [] treasureValuePool = [] for value in xrange(1, 5): treasureValuePool += [value] * ToonBlitzGlobals.TreasureValueProbability[value] treasureIndicesSelected = [] if treasuresPool != None: minTreasures, maxTreasures = attribs[8] for i in xrange(len(treasuresPool)): treasureIndicesPool += [i] numTreasures = maxTreasures * ToonBlitzGlobals.PercentMaxTreasures[szId] / 100 numTreasures = max(numTreasures, minTreasures) for i in xrange(int(numTreasures)): if len(treasureIndicesPool) == 0: break treasureIndex = random.choice(treasureIndicesPool) treasureValue = random.choice(treasureValuePool) treasure = (treasureIndex, treasureValue) treasureIndicesPool.remove(treasureIndex) treasureIndicesSelected.append(treasure) treasureIndicesSelected.sort() spawnPointIndicesPool = [] spawnPointIndicesSelected = [] if spawnPointsPool != None: minSpawnPoints, maxSpawnPoints = attribs[9] for i in xrange(len(spawnPointsPool)): spawnPointIndicesPool += [i] numSpawnPoints = maxSpawnPoints * ToonBlitzGlobals.PercentMaxSpawnPoints[szId] / 100 numSpawnPoints = max(numSpawnPoints, minSpawnPoints) for i in xrange(int(numSpawnPoints)): if len(spawnPointIndicesPool) == 0: break spawnPoint = random.choice(spawnPointIndicesPool) spawnPointIndicesSelected.append(spawnPoint) spawnPointIndicesPool.remove(spawnPoint) spawnPointIndicesSelected.sort() stomperIndicesPool = [] stomperIndicesSelected = [] if stompersPool != None: minStompers, maxStompers = attribs[10] for i in xrange(len(stompersPool)): stomperIndicesPool += [i] numStompers = maxStompers * ToonBlitzGlobals.PercentMaxStompers[szId] / 100 numStompers = max(numStompers, minStompers) for i in xrange(int(numStompers)): if len(stomperIndicesPool) == 0: break stomper = random.choice(stomperIndicesPool) stomperIndicesSelected.append(stomper) stomperIndicesPool.remove(stomper) stomperIndicesSelected.sort() sctionTuple = (sectionIndex, enemyIndicesSelected, treasureIndicesSelected, spawnPointIndicesSelected, stomperIndicesSelected) self.sectionsSelected.append(sctionTuple) return def getSectionsSelected(self): return self.sectionsSelected
class DistributedCatchGameAI(DistributedMinigameAI): def __init__(self, air, minigameId): try: self.DistributedCatchGameAI_initialized except: self.DistributedCatchGameAI_initialized = 1 DistributedMinigameAI.__init__(self, air, minigameId) self.gameFSM = ClassicFSM.ClassicFSM('DistributedCatchGameAI', [State.State('inactive', self.enterInactive, self.exitInactive, ['play']), State.State('play', self.enterPlay, self.exitPlay, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, ['inactive'])], 'inactive', 'inactive') self.addChildGameFSM(self.gameFSM) def generate(self): self.notify.debug('generate') DistributedMinigameAI.generate(self) def delete(self): self.notify.debug('delete') del self.gameFSM DistributedMinigameAI.delete(self) def setGameReady(self): self.notify.debug('setGameReady') DistributedMinigameAI.setGameReady(self) def setGameStart(self, timestamp): self.notify.debug('setGameStart') DistributedMinigameAI.setGameStart(self, timestamp) self.gameFSM.request('play') def setGameAbort(self): self.notify.debug('setGameAbort') if self.gameFSM.getCurrentState(): self.gameFSM.request('cleanup') DistributedMinigameAI.setGameAbort(self) def gameOver(self): self.notify.debug('gameOver') self.notify.debug('fruits: %s, fruits caught: %s' % (self.numFruits, self.fruitsCaught)) perfect = self.fruitsCaught >= self.numFruits for avId in self.avIdList: self.scoreDict[avId] = max(1, int(self.scoreDict[avId] / 2)) if perfect: self.notify.debug('PERFECT GAME!') self.scoreDict[avId] += round(self.numFruits / 4.0) self.logAllPerfect() self.gameFSM.request('cleanup') DistributedMinigameAI.gameOver(self) def enterInactive(self): self.notify.debug('enterInactive') def exitInactive(self): pass def enterPlay(self): self.notify.debug('enterPlay') self.caughtList = [0] * 100 table = CatchGameGlobals.NumFruits[self.numPlayers - 1] self.numFruits = table[self.getSafezoneId()] self.notify.debug('numFruits: %s' % self.numFruits) self.fruitsCaught = 0 def allToonsDone(self = self): self.notify.debug('allToonsDone') self.sendUpdate('setEveryoneDone') if not CatchGameGlobals.EndlessGame: self.gameOver() def handleTimeout(avIds, self = self): self.notify.debug('handleTimeout: avatars %s did not report "done"' % avIds) self.setGameAbort() self.doneBarrier = ToonBarrier('waitClientsDone', self.uniqueName('waitClientsDone'), self.avIdList, CatchGameGlobals.GameDuration + MinigameGlobals.latencyTolerance, allToonsDone, handleTimeout) def exitPlay(self): del self.caughtList self.doneBarrier.cleanup() del self.doneBarrier def claimCatch(self, objNum, DropObjTypeId): if self.gameFSM.getCurrentState().getName() != 'play': return if DropObjTypeId < 0 or DropObjTypeId >= len(CatchGameGlobals.DOTypeId2Name): self.air.writeServerEvent('warning', DropObjTypeId, 'CatchGameAI.claimCatch DropObjTypeId out of range') return if objNum < 0 or objNum > 5000 or objNum >= 2 * len(self.caughtList): self.air.writeServerEvent('warning', objNum, 'CatchGameAI.claimCatch objNum is too high or negative') return if objNum >= len(self.caughtList): self.caughtList += [0] * len(self.caughtList) if not self.caughtList[objNum]: self.caughtList[objNum] = 1 avId = self.air.getAvatarIdFromSender() self.sendUpdate('setObjectCaught', [avId, objNum]) objName = CatchGameGlobals.DOTypeId2Name[DropObjTypeId] self.notify.debug('avatar %s caught object %s: %s' % (avId, objNum, objName)) if CatchGameGlobals.Name2DropObjectType[objName].good: self.scoreDict[avId] += 1 self.fruitsCaught += 1 def reportDone(self): if not self.gameFSM or not self.gameFSM.getCurrentState() or self.gameFSM.getCurrentState().getName() != 'play': return avId = self.air.getAvatarIdFromSender() self.notify.debug('reportDone: avatar %s is done' % avId) self.doneBarrier.clear(avId) def enterCleanup(self): self.notify.debug('enterCleanup') self.gameFSM.request('inactive') def exitCleanup(self): pass
def enterWaitClientsReady(self): self.notify.debug('enterWaitClientsReady') self.nextRoundBarrier = ToonBarrier('nextRoundReady', self.uniqueName('nextRoundReady'), self.avIdList, PatternGameGlobals.ClientsReadyTimeout, self.__allPlayersReady, self.__clientsReadyTimeout) for avId in self.readyClients: self.nextRoundBarrier.clear(avId)
class DistributedPatternGameAI(DistributedMinigameAI): def __init__(self, air, minigameId): try: self.DistributedPatternGameAI_initialized except: self.DistributedPatternGameAI_initialized = 1 DistributedMinigameAI.__init__(self, air, minigameId) self.gameFSM = ClassicFSM.ClassicFSM('DistributedPatternGameAI', [ State.State('off', self.enterInactive, self.exitInactive, ['waitClientsReady', 'cleanup']), State.State('waitClientsReady', self.enterWaitClientsReady, self.exitWaitClientsReady, ['generatePattern', 'cleanup']), State.State('generatePattern', self.enterGeneratePattern, self.exitGeneratePattern, ['waitForResults', 'cleanup']), State.State('waitForResults', self.enterWaitForResults, self.exitWaitForResults, ['waitClientsReady', 'cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, []) ], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) def delete(self): self.notify.debug('delete') del self.gameFSM DistributedMinigameAI.delete(self) def setGameReady(self): self.notify.debug('setGameReady') DistributedMinigameAI.setGameReady(self) self.__initGameVars() def setGameStart(self, timestamp): self.notify.debug('setGameStart') DistributedMinigameAI.setGameStart(self, timestamp) self.gameFSM.request('waitClientsReady') def setGameAbort(self): self.notify.debug('setGameAbort') if self.gameFSM.getCurrentState(): self.gameFSM.request('cleanup') DistributedMinigameAI.setGameAbort(self) def gameOver(self): self.notify.debug('gameOver') self.gameFSM.request('cleanup') DistributedMinigameAI.gameOver(self) def enterInactive(self): self.notify.debug('enterInactive') def exitInactive(self): pass def __initGameVars(self): self.pattern = [] self.round = 0 self.perfectResults = {} for avId in self.avIdList: self.perfectResults[avId] = 1 self.readyClients = [] self.timeoutTaskName = self.uniqueName('PatternGameResultsTimeout') def enterWaitClientsReady(self): self.notify.debug('enterWaitClientsReady') self.nextRoundBarrier = ToonBarrier( 'nextRoundReady', self.uniqueName('nextRoundReady'), self.avIdList, PatternGameGlobals.ClientsReadyTimeout, self.__allPlayersReady, self.__clientsReadyTimeout) for avId in self.readyClients: self.nextRoundBarrier.clear(avId) def reportPlayerReady(self): if not self._inState('waitClientsReady'): return avId = self.air.getAvatarIdFromSender() if avId not in self.avIdList: self.notify.warning( 'Got reportPlayerReady from an avId: %s not in our list: %s' % (avId, self.avIdList)) else: self.readyClients.append(avId) self.nextRoundBarrier.clear(avId) def __allPlayersReady(self): self.readyClients = [] self.gameFSM.request('generatePattern') def __clientsReadyTimeout(self, avIds): self.notify.debug( '__clientsReadyTimeout: clients %s have not responded' % avIds) self.setGameAbort() def exitWaitClientsReady(self): self.nextRoundBarrier.cleanup() del self.nextRoundBarrier def enterGeneratePattern(self): self.notify.debug('enterGeneratePattern') self.round += 1 targetLen = PatternGameGlobals.INITIAL_ROUND_LENGTH + PatternGameGlobals.ROUND_LENGTH_INCREMENT * ( self.round - 1) count = targetLen - len(self.pattern) for i in xrange(0, count): self.pattern.append(random.randint(0, 3)) self.gameFSM.request('waitForResults') self.sendUpdate('setPattern', [self.pattern]) def exitGeneratePattern(self): pass def enterWaitForResults(self): self.notify.debug('enterWaitForResults') self.results = [None] * self.numPlayers self.fastestTime = PatternGameGlobals.InputTime * 2 self.fastestAvId = 0 self.resultsBarrier = ToonBarrier( 'results', self.uniqueName('results'), self.avIdList, PatternGameGlobals.InputTimeout + 1.0 * self.round, self.__gotAllPatterns, self.__resultsTimeout) return def reportButtonPress(self, index, wrong): if not self._inState('waitForResults'): return avId = self.air.getAvatarIdFromSender() if avId not in self.avIdList: self.air.writeServerEvent( 'suspicious', avId, 'PatternGameAI.reportButtonPress avId not on list') return if index < 0 or index > 3: self.air.writeServerEvent( 'warning', index, 'PatternGameAI.reportButtonPress got bad index') return if wrong not in [0, 1]: self.air.writeServerEvent( 'warning', wrong, "PatternGameAI.reportButtonPress got bad 'wrong'") return self.sendUpdate('remoteButtonPressed', [avId, index, wrong]) def __resultsTimeout(self, avIds): self.notify.debug('__resultsTimeout: %s' % avIds) for avId in avIds: index = self.avIdList.index(avId) self.__acceptPlayerPattern(avId, [], PatternGameGlobals.InputTime * 2) self.__gotAllPatterns() def reportPlayerPattern(self, pattern, totalTime): if not self._inState('waitForResults'): return avId = self.air.getAvatarIdFromSender() self.__acceptPlayerPattern(avId, pattern, totalTime) self.resultsBarrier.clear(avId) def __acceptPlayerPattern(self, avId, pattern, totalTime): index = self.avIdList.index(avId) if self.results[index] != None: return self.results[index] = pattern if totalTime < self.fastestTime and pattern == self.pattern: self.fastestTime = totalTime self.fastestAvId = avId if self.numPlayers == 1: self.fastestAvId = 1 else: self.scoreDict[self.fastestAvId] += 2 return def __gotAllPatterns(self): patterns = [[]] * 4 for i in xrange(0, len(self.results)): patterns[i] = self.results[i] if patterns[i] is None: patterns[i] = [] self.sendUpdate('setPlayerPatterns', patterns + [self.fastestAvId]) for i in xrange(0, self.numPlayers): avId = self.avIdList[i] if not self.results[i] == self.pattern: self.perfectResults[avId] = 0 else: self.scoreDict[avId] += self.round if self.round < PatternGameGlobals.NUM_ROUNDS: self.gameFSM.request('waitClientsReady') else: for avId in self.avIdList: if self.perfectResults[avId]: self.scoreDict[avId] += 4 self.logPerfectGame(avId) self.gameOver() self.gameFSM.request('cleanup') return def exitWaitForResults(self): self.resultsBarrier.cleanup() del self.resultsBarrier def enterCleanup(self): self.notify.debug('enterCleanup') def exitCleanup(self): pass
class DistributedPatternGameAI(DistributedMinigameAI): def __init__(self, air, minigameId): try: self.DistributedPatternGameAI_initialized except: self.DistributedPatternGameAI_initialized = 1 DistributedMinigameAI.__init__(self, air, minigameId) self.gameFSM = ClassicFSM.ClassicFSM('DistributedPatternGameAI', [State.State('off', self.enterInactive, self.exitInactive, ['waitClientsReady', 'cleanup']), State.State('waitClientsReady', self.enterWaitClientsReady, self.exitWaitClientsReady, ['generatePattern', 'cleanup']), State.State('generatePattern', self.enterGeneratePattern, self.exitGeneratePattern, ['waitForResults', 'cleanup']), State.State('waitForResults', self.enterWaitForResults, self.exitWaitForResults, ['waitClientsReady', 'cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) def delete(self): self.notify.debug('delete') del self.gameFSM DistributedMinigameAI.delete(self) def setGameReady(self): self.notify.debug('setGameReady') DistributedMinigameAI.setGameReady(self) self.__initGameVars() def setGameStart(self, timestamp): self.notify.debug('setGameStart') DistributedMinigameAI.setGameStart(self, timestamp) self.gameFSM.request('waitClientsReady') def setGameAbort(self): self.notify.debug('setGameAbort') if self.gameFSM.getCurrentState(): self.gameFSM.request('cleanup') DistributedMinigameAI.setGameAbort(self) def gameOver(self): self.notify.debug('gameOver') self.gameFSM.request('cleanup') DistributedMinigameAI.gameOver(self) def enterInactive(self): self.notify.debug('enterInactive') def exitInactive(self): pass def __initGameVars(self): self.pattern = [] self.round = 0 self.perfectResults = {} for avId in self.avIdList: self.perfectResults[avId] = 1 self.readyClients = [] self.timeoutTaskName = self.uniqueName('PatternGameResultsTimeout') def enterWaitClientsReady(self): self.notify.debug('enterWaitClientsReady') self.nextRoundBarrier = ToonBarrier('nextRoundReady', self.uniqueName('nextRoundReady'), self.avIdList, PatternGameGlobals.ClientsReadyTimeout, self.__allPlayersReady, self.__clientsReadyTimeout) for avId in self.readyClients: self.nextRoundBarrier.clear(avId) def reportPlayerReady(self): if not self._inState('waitClientsReady'): return avId = self.air.getAvatarIdFromSender() if avId not in self.avIdList: self.notify.warning('Got reportPlayerReady from an avId: %s not in our list: %s' % (avId, self.avIdList)) else: self.readyClients.append(avId) self.nextRoundBarrier.clear(avId) def __allPlayersReady(self): self.readyClients = [] self.gameFSM.request('generatePattern') def __clientsReadyTimeout(self, avIds): self.notify.debug('__clientsReadyTimeout: clients %s have not responded' % avIds) self.setGameAbort() def exitWaitClientsReady(self): self.nextRoundBarrier.cleanup() del self.nextRoundBarrier def enterGeneratePattern(self): self.notify.debug('enterGeneratePattern') self.round += 1 targetLen = PatternGameGlobals.INITIAL_ROUND_LENGTH + PatternGameGlobals.ROUND_LENGTH_INCREMENT * (self.round - 1) count = targetLen - len(self.pattern) for i in xrange(0, count): self.pattern.append(random.randint(0, 3)) self.gameFSM.request('waitForResults') self.sendUpdate('setPattern', [self.pattern]) def exitGeneratePattern(self): pass def enterWaitForResults(self): self.notify.debug('enterWaitForResults') self.results = [None] * self.numPlayers self.fastestTime = PatternGameGlobals.InputTime * 2 self.fastestAvId = 0 self.resultsBarrier = ToonBarrier('results', self.uniqueName('results'), self.avIdList, PatternGameGlobals.InputTimeout + 1.0 * self.round, self.__gotAllPatterns, self.__resultsTimeout) return def reportButtonPress(self, index, wrong): if not self._inState('waitForResults'): return avId = self.air.getAvatarIdFromSender() if avId not in self.avIdList: self.air.writeServerEvent('suspicious', avId, 'PatternGameAI.reportButtonPress avId not on list') return if index < 0 or index > 3: self.air.writeServerEvent('warning', index, 'PatternGameAI.reportButtonPress got bad index') return if wrong not in [0, 1]: self.air.writeServerEvent('warning', wrong, "PatternGameAI.reportButtonPress got bad 'wrong'") return self.sendUpdate('remoteButtonPressed', [avId, index, wrong]) def __resultsTimeout(self, avIds): self.notify.debug('__resultsTimeout: %s' % avIds) for avId in avIds: index = self.avIdList.index(avId) self.__acceptPlayerPattern(avId, [], PatternGameGlobals.InputTime * 2) self.__gotAllPatterns() def reportPlayerPattern(self, pattern, totalTime): if not self._inState('waitForResults'): return avId = self.air.getAvatarIdFromSender() self.__acceptPlayerPattern(avId, pattern, totalTime) self.resultsBarrier.clear(avId) def __acceptPlayerPattern(self, avId, pattern, totalTime): index = self.avIdList.index(avId) if self.results[index] != None: return self.results[index] = pattern if totalTime < self.fastestTime and pattern == self.pattern: self.fastestTime = totalTime self.fastestAvId = avId if self.numPlayers == 1: self.fastestAvId = 1 else: self.scoreDict[self.fastestAvId] += 2 return def __gotAllPatterns(self): patterns = [[]] * 4 for i in xrange(0, len(self.results)): patterns[i] = self.results[i] if patterns[i] is None: patterns[i] = [] self.sendUpdate('setPlayerPatterns', patterns + [self.fastestAvId]) for i in xrange(0, self.numPlayers): avId = self.avIdList[i] if not self.results[i] == self.pattern: self.perfectResults[avId] = 0 else: self.scoreDict[avId] += self.round if self.round < PatternGameGlobals.NUM_ROUNDS: self.gameFSM.request('waitClientsReady') else: for avId in self.avIdList: if self.perfectResults[avId]: self.scoreDict[avId] += 4 self.logPerfectGame(avId) self.gameOver() self.gameFSM.request('cleanup') return def exitWaitForResults(self): self.resultsBarrier.cleanup() del self.resultsBarrier def enterCleanup(self): self.notify.debug('enterCleanup') def exitCleanup(self): pass
class DistributedGolfCourseAI(DistributedObjectAI.DistributedObjectAI, FSM): notify = directNotify.newCategory('DistributedGolfCourseAI') defaultTransitions = {'Off': ['WaitJoin'], 'WaitJoin': ['WaitReadyCourse', 'Cleanup'], 'WaitReadyCourse': ['WaitReadyHole', 'Cleanup'], 'WaitReadyHole': ['PlayHole', 'Cleanup', 'WaitLeaveHole', 'WaitReward'], 'PlayHole': ['PlayHole', 'WaitLeaveHole', 'Cleanup', 'WaitReward'], 'WaitLeaveHole': ['WaitReadyHole', 'WaitLeaveCourse', 'Cleanup', 'WaitReward'], 'WaitReward': ['WaitLeaveCourse', 'Cleanup', 'WaitLeaveHole'], 'WaitLeaveCourse': ['Cleanup'], 'Cleanup': ['Off']} def __init__(self, zoneId, avIds, courseId, preferredHoleId = None): FSM.__init__(self, 'GolfCourse_%s_FSM' % zoneId) DistributedObjectAI.DistributedObjectAI.__init__(self, simbase.air) self.notify.debug('GOLF COURSE: init') self.zoneId = zoneId self.currentHole = None self.avIdList = [] self.avStateDict = {} self.addExpectedGolfers(avIds) self.courseId = courseId self.preferredHoleId = preferredHoleId self.courseInfo = GolfGlobals.CourseInfo[self.courseId] self.numHoles = self.courseInfo['numHoles'] self.holeIds = self.calcHolesToUse() self.notify.debug('self.holeIds = %s' % self.holeIds) self.numHolesPlayed = 0 self.curHoleIndex = 0 self.trophyListLen = 0 self.courseBestListLen = 0 self.holeBestListLen = 0 self.cupListLen = 0 self.scores = {} self.aimTimes = {} self.startingHistory = {} self.endingHistory = {} self.startingHoleBest = {} self.endingHoleBest = {} self.startingCourseBest = {} self.endingCourseBest = {} self.startingCups = {} self.endingCups = {} self.initHistory() self.newTrophies = {} self.newHoleBest = {} self.newCourseBest = {} self.newCups = {} self.drivingToons = [] self.__barrier = None self.winnerByTieBreak = 0 return def initHistory(self): for avId in self.avIdList: av = simbase.air.doId2do.get(avId) if av: history = av.getGolfHistory() self.startingHistory[avId] = history[:] self.endingHistory[avId] = history[:] holeBest = av.getGolfHoleBest() self.startingHoleBest[avId] = holeBest[:] self.endingHoleBest[avId] = holeBest[:] courseBest = av.getGolfCourseBest() self.startingCourseBest[avId] = courseBest[:] self.endingCourseBest[avId] = courseBest[:] def generate(self): DistributedObjectAI.DistributedObjectAI.generate(self) self.grabGolfers() def delete(self): self.notify.debug('GOLF COURSE: delete: deleting AI GolfCourse object') if hasattr(self, 'rewardBarrier'): self.rewardBarrier.cleanup() del self.rewardBarrier if self.currentHole: self.notify.debug('calling requestDelete on hole %d' % self.currentHole.doId) self.currentHole.requestDelete() self.currentHole = None self.ignoreAll() from src.toontown.golf import GolfManagerAI GolfManagerAI.GolfManagerAI().removeCourse(self) if self.__barrier: self.__barrier.cleanup() self.__barrier = None DistributedObjectAI.DistributedObjectAI.delete(self) return def load(self): self.b_setCourseReady() self.request('WaitReadyCourse') def getZoneId(self): return self.zoneId def addExpectedGolfers(self, avIdList): self.notify.debug('Sending %s to course %s' % (avIdList, self.zoneId)) for avId in avIdList: golfer = simbase.air.doId2do.get(avId) if golfer: if avId not in self.avIdList: self.avIdList.append(avId) self.avStateDict[avId] = INITIAL elif self.avStateDict[avId] == EXITED: if self.isGenerated(): pass else: self.notify.warning('GOLF COURSE: trying to grab golfer %s that is already on the course' % avId) def grabGolfers(self): for avId in self.avIdList: golfer = simbase.air.doId2do.get(avId) if golfer: if self.avStateDict[avId] == INITIAL: self.avStateDict[avId] = EXPECTED self.request('WaitJoin') def getGolferIds(self): return self.avIdList def checkGolferPlaying(self, avId): if self.avStateDict[avId] == ONHOLE: return 1 else: return 0 def b_setCourseReady(self): self.setCourseReady() self.d_setCourseReady() def d_setCourseReady(self): self.notify.debug('GOLF COURSE: Sending setCourseReady') self.sendUpdate('setCourseReady', [self.numHoles, self.holeIds, self.calcCoursePar()]) def setCourseReady(self): self.notify.debug('GOLF COURSE: setCourseReady: golf course ready with avatars: %s' % self.avIdList) self.trophyListLen = 0 self.courseBestListLen = 0 self.holeBestListLen = 0 self.cupListLen = 0 self.normalExit = 1 def d_setPlayHole(self): self.notify.debug('GOLF COURSE: setPlayHole: play on golf hole about to start') self.sendUpdate('setPlayHole', []) def b_setCourseExit(self): self.d_setCourseExit() self.setCourseExit() def d_setCourseExit(self): self.notify.debug('GOLF COURSE: Sending setGameExit') self.sendUpdate('setCourseExit', []) def setCourseExit(self): self.notify.debug('GOLF COURSE: setGameExit') def handleExitedAvatar(self, avId): self.notify.warning('GOLF COURSE: handleExitedAvatar: avatar id exited: ' + str(avId)) self.avStateDict[avId] = EXITED self.sendUpdate('avExited', [avId]) if self.currentHole and not self.haveAllGolfersExited(): self.currentHole.avatarDropped(avId) if self.haveAllGolfersExited(): self.setCourseAbort() elif self.isCurHoleDone(): if self.isPlayingLastHole(): if self.state not in ['WaitReward', 'WaitReadyHole']: self.safeDemand('WaitReward') else: self.notify.debug('allBalls are in holes, calling holeOver') self.holeOver() if hasattr(self, 'rewardBarrier'): if self.rewardBarrier: self.rewardBarrier.clear(avId) if hasattr(self, '__barrier'): if self.__barrier: self.__.clear(avId) def startNextHole(self): self.notify.debugStateCall(self) holeId = self.holeIds[self.numHolesPlayed] self.currentHole = DistributedGolfHoleAI.DistributedGolfHoleAI(self.zoneId, golfCourse=self, holeId=holeId) self.currentHole.generateWithRequired(self.zoneId) self.d_setCurHoleDoId(self.currentHole.doId) self.safeDemand('WaitReadyHole') def holeOver(self): self.notify.debug('GOLF COURSE: holeOver') self.numHolesPlayed += 1 if self.numHolesPlayed < self.numHoles: self.b_setCurHoleIndex(self.numHolesPlayed) self.safeDemand('WaitLeaveHole') def setCourseAbort(self): self.notify.debug('GOLF COURSE: setGameAbort') self.normalExit = 0 self.sendUpdate('setCourseAbort', [0]) self.safeDemand('Cleanup') def enterOff(self): self.notify.debug('GOLF COURSE: enterOff') def exitOff(self): self.notify.debug('GOLF COURSE: exitOff') def enterWaitJoin(self): self.notify.debug('GOLF COURSE: enterWaitJoin') for avId in self.avIdList: self.avStateDict[avId] = EXPECTED self.acceptOnce(self.air.getAvatarExitEvent(avId), self.handleExitedAvatar, extraArgs=[avId]) def allAvatarsJoined(self = self): self.notify.debug('GOLF COURSE: all avatars joined') self.load() def handleTimeout(avIds, self = self): self.notify.debug('GOLF COURSE: timed out waiting for clients %s to join' % avIds) for avId in self.avStateDict: if not self.avStateDict[avId] == JOINED: self.handleExitedAvatar(avId) if self.haveAllGolfersExited(): self.setCourseAbort() else: self.load() self.__barrier = ToonBarrier('waitClientsJoin', self.uniqueName('waitClientsJoin'), self.avIdList, JOIN_TIMEOUT, allAvatarsJoined, handleTimeout) def exitWaitJoin(self): self.notify.debugStateCall(self) self.__barrier.cleanup() self.__barrier = None return def setAvatarJoined(self): avId = self.air.getAvatarIdFromSender() self.notify.debug('GOLF COURSE: setAvatarJoined: avatar id joined: ' + str(avId)) self.avStateDict[avId] = JOINED self.notify.debug('GOLF COURSE: setAvatarJoined: new states: ' + str(self.avStateDict)) if hasattr(self, '_DistributedGolfCourseAI__barrier') and self.__barrier: self.__barrier.clear(avId) else: self.notify.warning('setAvatarJoined avId=%d but barrier is invalid' % avId) def exitFrameworkWaitClientsJoin(self): self.__barrier.cleanup() del self.__barrier def enterWaitReadyCourse(self): self.notify.debug('GOLF COURSE: enterWaitReadyCourse') def allAvatarsInCourse(self = self): self.notify.debug('GOLF COURSE: all avatars ready course') for avId in self.avIdList: blankScoreList = [0] * self.numHoles self.scores[avId] = blankScoreList self.aimTimes[avId] = 0 self.notify.debug('self.scores = %s' % self.scores) self.startNextHole() def handleTimeout(avIds, self = self): self.notify.debug("GOLF COURSE: Course timed out waiting for clients %s to report 'ready'" % avIds) if self.haveAllGolfersExited(): self.setCourseAbort() else: allAvatarsInCourse() self.__barrier = ToonBarrier('WaitReadyCourse', self.uniqueName('WaitReadyCourse'), self.avIdList, READY_TIMEOUT, allAvatarsInCourse, handleTimeout) for avId in self.avStateDict.keys(): if self.avStateDict[avId] == READY: self.__barrier.clear(avId) def setAvatarReadyCourse(self): avId = self.air.getAvatarIdFromSender() self.notify.debug('GOLF COURSE: setAvatarReadyCourse: avatar id ready: ' + str(avId)) self.avStateDict[avId] = READY self.notify.debug('GOLF COURSE: setAvatarReadyCourse: new avId states: ' + str(self.avStateDict)) if self.state == 'WaitReadyCourse': self.__barrier.clear(avId) def exitWaitReadyCourse(self): self.notify.debugStateCall(self) self.__barrier.cleanup() self.__barrier = None return def enterWaitReadyHole(self): self.notify.debug('GOLF COURSE: enterWaitReadyHole') def allAvatarsInHole(self = self): self.notify.debug('GOLF COURSE: all avatars ready hole') if self.safeDemand('PlayHole'): self.d_setPlayHole() def handleTimeout(avIds, self = self): self.notify.debug("GOLF COURSE: Hole timed out waiting for clients %s to report 'ready'" % avIds) if self.haveAllGolfersExited(): self.setCourseAbort() elif self.safeDemand('PlayHole'): self.d_setPlayHole() stillPlaying = self.getStillPlayingAvIds() self.__barrier = ToonBarrier('WaitReadyHole', self.uniqueName('WaitReadyHole'), stillPlaying, READY_TIMEOUT, allAvatarsInHole, handleTimeout) for avId in self.avStateDict.keys(): if self.avStateDict[avId] == ONHOLE: self.__barrier.clear(avId) def exitWaitReadyHole(self): self.notify.debugStateCall(self) if hasattr(self, '__barrier'): self.__barrier.cleanup() self.__barrier = None return def getStillPlayingAvIds(self): retval = [] for avId in self.avIdList: av = simbase.air.doId2do.get(avId) if av: if avId in self.avStateDict and not self.avStateDict[avId] == EXITED: retval.append(avId) return retval def avatarReadyHole(self, avId): if self.state not in ['WaitJoin', 'WaitReadyCourse', 'WaitReadyHole']: self.notify.debug('GOLF COURSE: Ignoring setAvatarReadyHole message') return self.notify.debug('GOLF COURSE: setAvatarReadyHole: avatar id ready: ' + str(avId)) self.avStateDict[avId] = ONHOLE self.notify.debug('GOLF COURSE: setAvatarReadyHole: new avId states: ' + str(self.avStateDict)) if self.state == 'WaitReadyHole': self.__barrier.clear(avId) def enterPlayHole(self): self.notify.debug('GOLF COURSE: enterPlayHole') if self.currentHole and not self.currentHole.playStarted: self.currentHole.startPlay() def exitPlayHole(self): self.notify.debug('GOLF COURSE: exitPlayHole') def enterWaitLeaveHole(self): self.notify.debugStateCall(self) self.notify.debug('calling requestDelete on hole %d' % self.currentHole.doId) self.currentHole.requestDelete() self.currentHole = None if self.numHolesPlayed >= self.numHoles: pass else: self.startNextHole() return def exitWaitLeaveHole(self): pass def enterWaitReward(self): self.updateHistoryForCourseComplete() self.awardTrophies() self.awardCups() self.awardHoleBest() self.awardCourseBest() self.recordHoleInOne() self.recordCourseUnderPar() trophiesList = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] if avId in self.newTrophies: oneTrophyList = self.newTrophies[avId] trophiesList.append(oneTrophyList) else: trophiesList.append([]) while len(trophiesList) < GolfGlobals.MAX_PLAYERS_PER_HOLE: trophiesList.append([]) holeBestList = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] if avId in self.newHoleBest: oneTrophyList = self.newHoleBest[avId] holeBestList.append(oneTrophyList) else: holeBestList.append([]) while len(holeBestList) < GolfGlobals.MAX_PLAYERS_PER_HOLE: holeBestList.append([]) courseBestList = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] if avId in self.newCourseBest: oneTrophyList = self.newCourseBest[avId] courseBestList.append(oneTrophyList) else: courseBestList.append([]) while len(courseBestList) < GolfGlobals.MAX_PLAYERS_PER_HOLE: courseBestList.append([]) cupList = [] for index in xrange(len(self.avIdList)): avId = self.avIdList[index] if avId in self.newCups: oneCupList = self.newCups[avId] cupList.append(oneCupList) self.cupListLen = self.cupListLen + 1 else: cupList.append([]) while len(cupList) < GolfGlobals.MAX_PLAYERS_PER_HOLE: cupList.append([]) REWARD_TIMEOUT = (self.trophyListLen + self.holeBestListLen + self.courseBestListLen + self.cupListLen) * 5 + 19 aimTimesList = [0] * 4 aimIndex = 0 stillPlaying = self.getStillPlayingAvIds() for avId in self.avIdList: if avId in stillPlaying: aimTime = 0 if avId in self.aimTimes: aimTime = self.aimTimes[avId] aimTimesList[aimIndex] = aimTime aimIndex += 1 self.sendUpdate('setReward', [trophiesList, self.rankings, holeBestList, courseBestList, cupList, self.winnerByTieBreak, aimTimesList[0], aimTimesList[1], aimTimesList[2], aimTimesList[3]]) def allAvatarsRewarded(self = self): self.notify.debug('GOLF COURSE: all avatars rewarded') self.rewardDone() def handleRewardTimeout(avIds, self = self): self.notify.debug('GOLF COURSE: timed out waiting for clients %s to finish reward' % avIds) self.rewardDone() stillPlaying = self.getStillPlayingAvIds() self.rewardBarrier = ToonBarrier('waitReward', self.uniqueName('waitReward'), stillPlaying, REWARD_TIMEOUT, allAvatarsRewarded, handleRewardTimeout) def exitWaitReward(self): pass def enterWaitLeaveCourse(self): self.notify.debugStateCall(self) self.setCourseAbort() def exitWaitLeaveCourse(self): pass def enterCleanup(self): self.notify.debug('GOLF COURSE: enterCleanup') self.requestDelete() def exitCleanup(self): self.notify.debug('GOLF COURSE: exitCleanup') def isCurHoleDone(self): retval = False if self.areAllBallsInHole(): retval = True else: retval = True for state in self.avStateDict.values(): if not (state == BALLIN or state == EXITED): retval = False break return retval def areAllBallsInHole(self): self.notify.debug('areAllBallsInHole, self.avStateDict=%s' % self.avStateDict) allBallsInHole = True for state in self.avStateDict.values(): if state != BALLIN: allBallsInHole = False return allBallsInHole def isPlayingLastHole(self): retval = self.numHoles - self.numHolesPlayed == 1 return retval def setBallIn(self, avId): self.notify.debug('setBallIn %d' % avId) if self.avStateDict[avId] == BALLIN: self.notify.debug('setBallIn already in BALLIN state, just returning') return self.avStateDict[avId] = BALLIN self.updateHistoryForBallIn(avId) if self.isCurHoleDone(): if self.isPlayingLastHole(): if self.state != 'WaitReward': self.safeDemand('WaitReward') else: self.notify.debug('allBalls are in holes, calling holeOver') self.holeOver() def updateHistoryForBallIn(self, avId): if self.currentHole == None: return holeId = self.currentHole.holeId holeInfo = GolfGlobals.HoleInfo[holeId] par = holeInfo['par'] holeIndex = self.numHolesPlayed if holeIndex >= self.numHoles: self.notify.warning('updateHistoryForBallIn invalid holeIndex %d' % holeIndex) holeIndex = self.numHoles - 1 elif holeIndex < 0: self.notify.warning('updateHistoryForBallIn invalid holeIndex %d' % holeIndex) holeIndex = 0 strokes = self.scores[avId][holeIndex] self.notify.debug('self.scores = %s' % self.scores) diff = strokes - par if strokes == 1: self.incrementEndingHistory(avId, GolfGlobals.HoleInOneShots) if diff <= -2: self.incrementEndingHistory(avId, GolfGlobals.EagleOrBetterShots) if diff <= -1: self.incrementEndingHistory(avId, GolfGlobals.BirdieOrBetterShots) if diff <= 0: self.endingHistory[avId][GolfGlobals.ParOrBetterShots] += 1 if strokes < self.endingHoleBest[avId][holeId] or self.endingHoleBest[avId][holeId] == 0: self.endingHoleBest[avId][holeId] = strokes return def incrementEndingHistory(self, avId, historyIndex): if avId in self.endingHistory and historyIndex in GolfGlobals.TrophyRequirements: maximumAmount = GolfGlobals.TrophyRequirements[historyIndex][-1] if self.endingHistory[avId][historyIndex] < maximumAmount: self.endingHistory[avId][historyIndex] += 1 def getCourseId(self): return self.courseId def abortCurrentHole(self): holeId = self.currentHole.holeId holeDoId = self.currentHole.doId self.currentHole.finishHole() return (holeId, holeDoId) def calcHolesToUse(self): retval = [] if simbase.air.config.GetBool('golf-course-randomized', 1): retval = self.calcHolesToUseRandomized(self.courseId) self.notify.debug('randomized courses!') for x in xrange(len(retval)): self.notify.debug('Hole is: %s' % retval[x]) else: validHoles = self.calcUniqueHoles(self.courseId) if self.preferredHoleId in validHoles: retval.append(self.preferredHoleId) while len(retval) < self.numHoles: for holeId in GolfGlobals.CourseInfo[self.courseId]['holeIds']: if type(holeId) == type(0): retval.append(holeId) elif type(holeId) == type(()): retval.append(holeId[0]) else: self.notify.warning('cant handle %s' % self.holeId) if len(retval) >= self.numHoles: break return retval def incrementScore(self, avId): self.notify.debug('incrementScore self.scores=%s avId=%s' % (self.scores, avId)) self.scores[avId][self.numHolesPlayed] += 1 self.notify.debug('after increment self.score=%s' % self.scores) self.sendScores() def sendScores(self): self.notify.debug('sendScores self.scores = %s' % self.scores) scorelist = [] for avId in self.avIdList: for score in self.scores[avId]: scorelist.append(score) self.sendUpdate('setScores', [scorelist]) self.notify.debug('sendScores end self.scores = %s' % self.scores) def getCurHoleIndex(self): return self.curHoleIndex def b_setCurHoleIndex(self, holeIndex): self.setCurHoleIndex(holeIndex) self.d_setCurHoleIndex(holeIndex) def d_setCurHoleIndex(self, holeIndex): self.sendUpdate('setCurHoleIndex', [holeIndex]) def setCurHoleIndex(self, holeIndex): self.curHoleIndex = holeIndex def setDoneReward(self): avId = self.air.getAvatarIdFromSender() self.notify.debug('got rewardDone from %d' % avId) if hasattr(self, 'rewardBarrier'): self.rewardBarrier.clear(avId) self.sendUpdate('setCourseAbort', [avId]) def rewardDone(self): self.notify.debug('rewardDone') self.holeOver() self.safeDemand('WaitLeaveCourse') def updateHistoryForCourseComplete(self): self.calcRankings() stillPlaying = self.getStillPlayingAvIds() for avId in stillPlaying: self.incrementEndingHistory(avId, GolfGlobals.CoursesCompleted) coursePar = self.calcCoursePar() totalScore = self.getTotalScore(avId) if totalScore < coursePar: self.incrementEndingHistory(avId, GolfGlobals.CoursesUnderPar) if len(stillPlaying) > 1: self.incrementEndingHistory(avId, GolfGlobals.MultiPlayerCoursesCompleted) if self.rankingsById[avId] == 1: if self.courseId == 0: self.incrementEndingHistory(avId, GolfGlobals.CourseZeroWins) elif self.courseId == 1: self.incrementEndingHistory(avId, GolfGlobals.CourseOneWins) elif self.courseId == 2: self.incrementEndingHistory(avId, GolfGlobals.CourseTwoWins) else: self.notify.warning('unhandled case, self.courseId=%s' % self.courseId) if totalScore < self.endingCourseBest[avId][self.courseId] or self.endingCourseBest[avId][self.courseId] == 0: self.endingCourseBest[avId][self.courseId] = totalScore def calcRankings(self): stillPlaying = self.getStillPlayingAvIds() self.rankings = [] totalScores = [] for avId in self.avIdList: aimTime = 0 if avId in self.aimTimes: aimTime = self.aimTimes[avId] if avId in stillPlaying: totalScores.append((avId, self.getTotalScore(avId), aimTime)) else: totalScores.append((avId, 255, aimTime)) def scoreCompareNoTime(tupleA, tupleB): if tupleA[1] > tupleB[1]: return 1 elif tupleA[1] == tupleB[1]: return 0 else: return -1 def scoreCompareWithTime(tupleA, tupleB): if tupleA[1] > tupleB[1]: return 1 elif tupleA[1] == tupleB[1]: if tupleA[2] > tupleB[2]: return 1 elif tupleA[2] == tupleB[2]: return 0 else: return -1 else: return -1 if GolfGlobals.TIME_TIE_BREAKER: totalScores.sort(scoreCompareWithTime) else: totalScores.sort(scoreCompareNoTime) curRank = 0 oldScore = 0 oldTime = 0 self.rankingsById = {} for scoreTuple in totalScores: time = scoreTuple[2] score = scoreTuple[1] avId = scoreTuple[0] if score > oldScore or GolfGlobals.TIME_TIE_BREAKER and score == oldScore and time > oldTime: curRank += 1 oldScore = score oldTime = time self.rankingsById[avId] = curRank tiedForFirst = [] tempRank = 0 oldScore = 0 oldTime = 0 for scoreTuple in totalScores: time = scoreTuple[2] score = scoreTuple[1] avId = scoreTuple[0] if score > oldScore: tempRank += 1 oldScore = score oldTime = time if tempRank == 1: tiedForFirst.append(avId) for avId in self.avIdList: if avId in stillPlaying: self.rankings.append(self.rankingsById[avId]) else: self.rankings.append(-1) if len(tiedForFirst) >= 2 and not GolfGlobals.TIME_TIE_BREAKER: winnerAvId = random.choice(tiedForFirst) winnerIndex = self.avIdList.index(winnerAvId) self.winnerByTieBreak = winnerAvId for index in xrange(len(self.rankings)): if self.rankings[index] > 0 and index != winnerIndex: self.rankings[index] += 1 for avId in self.rankingsById: if self.rankingsById[avId] > 0 and avId != winnerAvId: self.rankingsById[avId] += 1 elif len(tiedForFirst) >= 2: winnerAvId = totalScores[0][0] self.winnerByTieBreak = winnerAvId def awardTrophies(self): stillPlaying = self.getStillPlayingAvIds() for avId in stillPlaying: av = simbase.air.doId2do.get(avId) if av: oldHistory = self.startingHistory[avId] endingHistory = self.endingHistory[avId] oldTrophies = GolfGlobals.calcTrophyListFromHistory(oldHistory) endingTrophies = GolfGlobals.calcTrophyListFromHistory(endingHistory) av.b_setGolfHistory(endingHistory) newTrophies = [] for index in xrange(len(oldTrophies)): if not oldTrophies[index] and endingTrophies[index]: self.notify.debug('New Trophy %d' % index) self.air.writeServerEvent('golf_trophy', avId, '%s' % index) newTrophies.append(True) self.trophyListLen = self.trophyListLen + 1 else: newTrophies.append(False) self.newTrophies[avId] = newTrophies def awardCups(self): stillPlaying = self.getStillPlayingAvIds() for avId in stillPlaying: av = simbase.air.doId2do.get(avId) if av: oldHistory = self.startingHistory[avId] endingHistory = self.endingHistory[avId] oldCups = GolfGlobals.calcCupListFromHistory(oldHistory) endingCups = GolfGlobals.calcCupListFromHistory(endingHistory) newCups = [] for index in xrange(len(oldCups)): if not oldCups[index] and endingCups[index]: self.notify.debug('New Trophy %d' % index) newCups.append(True) self.air.writeServerEvent('golf_cup', avId, '%s' % index) newMaxHp = av.getMaxHp() + 1 av.b_setMaxHp(newMaxHp) av.toonUp(newMaxHp) else: newCups.append(False) self.newCups[avId] = newCups def awardHoleBest(self): stillPlaying = self.getStillPlayingAvIds() for avId in stillPlaying: av = simbase.air.doId2do.get(avId) if av: oldHoleBest = self.startingHoleBest[avId] endingHoleBest = self.endingHoleBest[avId] av.b_setGolfHoleBest(endingHoleBest) newHoleBest = [] longestHoleBestList = 0 for index in xrange(len(oldHoleBest)): if endingHoleBest[index] < oldHoleBest[index]: self.notify.debug('New HoleBest %d' % index) newHoleBest.append(True) longestHoleBestList = longestHoleBestList + 1 else: newHoleBest.append(False) if longestHoleBestList > self.holeBestListLen: self.holeBestListLen = longestHoleBestList self.newHoleBest[avId] = newHoleBest def awardCourseBest(self): stillPlaying = self.getStillPlayingAvIds() for avId in stillPlaying: av = simbase.air.doId2do.get(avId) if av: oldCourseBest = self.startingCourseBest[avId] endingCourseBest = self.endingCourseBest[avId] av.b_setGolfCourseBest(endingCourseBest) newCourseBest = [] longestCourseBestList = 0 for index in xrange(len(oldCourseBest)): if endingCourseBest[index] < oldCourseBest[index]: self.notify.debug('New CourseBest %d' % index) newCourseBest.append(True) longestCourseBestList = longestCourseBestList + 1 else: newCourseBest.append(False) if longestCourseBestList > self.courseBestListLen: self.courseBestListLen = longestCourseBestList self.newCourseBest[avId] = newCourseBest def haveAllGolfersExited(self): retval = True for avId in self.avStateDict: if not self.avStateDict[avId] == EXITED: retval = False break return retval def getCurHoleDoId(self): retval = 0 if self.currentHole: retval = self.currentHole.doId return retval def d_setCurHoleDoId(self, curHoleDoId): self.sendUpdate('setCurHoleDoId', [curHoleDoId]) def calcCoursePar(self): retval = 0 for holeId in self.holeIds: holeInfo = GolfGlobals.HoleInfo[holeId] retval += holeInfo['par'] return retval def getTotalScore(self, avId): retval = 0 if avId in self.scores: for holeScore in self.scores[avId]: retval += holeScore return retval def getCurHoleScore(self, avId): retval = 0 if avId in self.scores and self.numHolesPlayed < len(self.scores[avId]): retval = self.scores[avId][self.numHolesPlayed] return retval def toggleDrivePermission(self, avId): if avId in self.drivingToons: self.drivingToons.remove(avId) self.sendUpdate('changeDrivePermission', [avId, 0]) retval = False else: self.drivingToons.append(avId) self.sendUpdate('changeDrivePermission', [avId, 1]) retval = True return retval def safeDemand(self, newState): doingDemand = False if self.state == 'Cleanup': pass else: if self.state in self.defaultTransitions: if newState in self.defaultTransitions[self.state]: self.demand(newState) doingDemand = True elif self.state == None: self.demand(newState) doingDemand = True if not doingDemand: self.notify.warning('doId=%d ignoring demand from %s to %s' % (self.doId, self.state, newState)) return doingDemand def setAvatarExited(self): avId = self.air.getAvatarIdFromSender() self.handleExitedAvatar(avId) def createChoicesList(self, courseId, possibleHoles): retval = [] holeIds = GolfGlobals.CourseInfo[courseId]['holeIds'] for holeOrTuple in holeIds: if type(holeOrTuple) == type(()): holeId = holeOrTuple[0] weight = holeOrTuple[1] elif type(holeOrTuple) == type(0): holeId = holeOrTuple weight = 1 else: self.notify.warning('cant handle %s' % holeOrTuple) continue if holeId in possibleHoles: retval += [holeId] * weight return retval def calcUniqueHoles(self, courseId): uniqueHoles = set() for holeOrTuple in GolfGlobals.CourseInfo[courseId]['holeIds']: if type(holeOrTuple) == type(()): uniqueHoles.add(holeOrTuple[0]) elif type(holeOrTuple) == type(0): uniqueHoles.add(holeOrTuple) else: self.notify.warning('cant handle %s' % holeOrTuple) return uniqueHoles def calcHolesToUseRandomized(self, courseId): retval = [] numHoles = GolfGlobals.CourseInfo[courseId]['numHoles'] uniqueHoles = self.calcUniqueHoles(courseId) curHolesChosen = set() while len(retval) < numHoles: if uniqueHoles == curHolesChosen: curHolesChosen = set() possibleHoles = uniqueHoles - curHolesChosen choicesList = self.createChoicesList(courseId, possibleHoles) if not self.preferredHoleId == None and self.preferredHoleId in choicesList and self.preferredHoleId not in curHolesChosen: holeChosen = self.preferredHoleId else: holeChosen = random.choice(choicesList) retval.append(holeChosen) curHolesChosen.add(holeChosen) return retval def recordHoleInOne(self): stillPlaying = self.getStillPlayingAvIds() for avId in stillPlaying: scoreList = self.scores[avId] ns = 0 for holeIndex in xrange(len(scoreList)): strokes = scoreList[holeIndex] if strokes == 1: ns +=1 holeId = self.holeIds[holeIndex] self.air.writeServerEvent('golf_ace', avId, '%d|%d|%s' % (self.courseId, holeId, stillPlaying)) def recordCourseUnderPar(self): coursePar = self.calcCoursePar() stillPlaying = self.getStillPlayingAvIds() for avId in stillPlaying: totalScore = self.getTotalScore(avId) netScore = totalScore - coursePar if netScore < 0: self.air.writeServerEvent('golf_underPar', avId, '%d|%d|%s' % (self.courseId, netScore, stillPlaying)) def addAimTime(self, avId, aimTime): if avId in self.aimTimes: self.aimTimes[avId] += aimTime