from DistributedMinigameAI import * from direct.distributed.ClockDelta import * from direct.interval.IntervalGlobal import * from direct.fsm import ClassicFSM from direct.fsm import State from direct.actor import Actor import DivingGameGlobals import random import random import types class DistributedDivingGameAI(DistributedMinigameAI): fishProportions = [] for i in xrange(6): fishProportions.append([]) n = 100 fishProportions[0] fishProportions[0].append(([0, 0.8], [0.8, 0.9], [0.9, 1], [n, n], [n, n], [n, n])) fishProportions[0].append(([0, 0.8], [0.8, 1], [n, n], [n, n], [n, n], [n, n])) fishProportions[0].append(([0, 0.7], [0.7, 1], [n, n], [n, n], [n, n], [n, n])) fishProportions[0].append(([0, 0.7], [0.7, 0.9], [0.9, 1], [n, n], [n, n], [n, n])) fishProportions[0].append(([0, 0.5], [0.5, 1], [n, n], [n, n], [n, n], [n, n])) fishProportions[0].append(([n, 0.5], [0.5, 1], [n, n], [n, n], [n, n], [n, n])) fishProportions[1] fishProportions[1].append(([0, 0.8], [0.8, 0.9], [0.9, 1], [n, n], [n, n], [n, n])) fishProportions[1].append(([0, 0.8], [0.8, 1], [n, n], [n, n], [n, n], [n, n])) fishProportions[1].append(([0, 0.7], [0.7, 1], [n, n], [n, n], [n, n], [n, n])) fishProportions[1].append(([0, 0.7], [0.7, 0.9], [n, n], [n, n], [n, n], [0.9, 1])) fishProportions[1].append(([0, 0.4], [0.4, 0.8], [n, n], [n, n], [n, n], [0.8, 1])) fishProportions[1].append(([n, 0.3], [0.3, 0.6], [n, n], [n, n], [n, n], [0.6, 1])) fishProportions[2] fishProportions[2].append(([0, 0.7], [0.7, 0.9], [0.9, 1], [n, n], [n, n], [n, n])) fishProportions[2].append(([0, 0.6], [0.6, 1], [n, n], [n, n], [n, n], [n, n])) fishProportions[2].append(([0, 0.6], [0.6, 0.8], [n, n], [0.8, 1], [n, n], [n, n])) fishProportions[2].append(([0, 0.5], [0.5, 0.7], [n, n], [0.7, 0.9], [n, n], [0.9, 1])) fishProportions[2].append(([0, 0.2], [0.2, 0.4], [n, n], [0.4, 0.75], [n, n], [0.75, 1])) fishProportions[2].append(([n, 0.2], [0.2, 0.6], [n, n], [0.6, 0.8], [n, n], [0.8, 1])) fishProportions[3] fishProportions[3].append(([0, 0.7], [0.7, 0.9], [0.9, 1], [n, n], [n, n], [n, n])) fishProportions[3].append(([0, 0.6], [0.6, 1], [n, n], [n, n], [n, n], [n, n])) fishProportions[3].append(([0, 0.6], [0.6, 0.8], [n, n], [0.95, 1], [n, n], [n, n])) fishProportions[3].append(([0, 0.5], [0.5, 0.7], [n, n], [0.7, 0.85], [0.9, 0.95], [0.95, 1])) fishProportions[3].append(([0, 0.2], [0.2, 0.4], [n, n], [0.4, 0.75], [0.75, 0.85], [0.85, 1])) fishProportions[3].append(([n, 0.2], [0.2, 0.6], [n, n], [0.6, 0.8], [n, n], [0.8, 1])) fishProportions[4] fishProportions[4].append(([0, 0.7], [0.7, 0.9], [0.9, 1], [n, n], [n, n], [n, n])) fishProportions[4].append(([0, 0.45], [0.45, 0.9], [n, n], [0.9, 1], [n, n], [n, n])) fishProportions[4].append(([0, 0.2], [0.2, 0.5], [n, n], [0.5, 0.95], [0.95, 1], [n, n])) fishProportions[4].append(([0, 0.1], [0.1, 0.3], [n, n], [0.3, 0.75], [0.75, 0.8], [0.8, 1])) fishProportions[4].append(([n, n], [0, 0.15], [n, n], [0.15, 0.4], [n, n], [0.4, 1])) fishProportions[4].append(([n, n], [n, n], [n, n], [0, 0.4], [n, n], [0.6, 1])) fishProportions[5] fishProportions[5].append(([0, 0.7], [0.7, 0.9], [0.9, 1], [n, n], [n, n], [n, n])) fishProportions[5].append(([0, 0.45], [0.45, 0.9], [n, n], [0.9, 1], [n, n], [n, n])) fishProportions[5].append(([0, 0.2], [0.2, 0.5], [n, n], [0.5, 0.95], [0.95, 1], [n, n])) fishProportions[5].append(([0, 0.1], [0.1, 0.3], [n, n], [0.3, 0.75], [0.75, 0.8], [0.8, 1])) fishProportions[5].append(([n, n], [0, 0.15], [n, n], [0.15, 0.4], [n, n], [0.4, 1])) fishProportions[5].append(([n, n], [n, n], [n, n], [0, 0.4], [n, n], [0.6, 1])) difficultyPatternsAI = {ToontownGlobals.ToontownCentral: [3.5, fishProportions[0], 1.5], ToontownGlobals.DonaldsDock: [3.0, fishProportions[1], 1.8], ToontownGlobals.DaisyGardens: [2.5, fishProportions[2], 2.1], ToontownGlobals.MinniesMelodyland: [2.0, fishProportions[3], 2.4], ToontownGlobals.TheBrrrgh: [2.0, fishProportions[4], 2.7], ToontownGlobals.DonaldsDreamland: [1.5, fishProportions[5], 3.0]} def __init__(self, air, minigameId): try: self.DistributedDivingGameAI_initialized except: self.DistributedDivingGameAI_initialized = 1 DistributedMinigameAI.__init__(self, air, minigameId) self.gameFSM = ClassicFSM.ClassicFSM('DistributedDivingGameAI', [State.State('inactive', self.enterInactive, self.exitInactive, ['swimming']), State.State('swimming', self.enterSwimming, self.exitSwimming, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, ['inactive'])], 'inactive', 'inactive') self.addChildGameFSM(self.gameFSM) self.__timeBase = globalClockDelta.localToNetworkTime(globalClock.getRealTime()) def delete(self): self.notify.debug('delete') del self.gameFSM DistributedMinigameAI.delete(self) def setGameReady(self): self.notify.debug('setGameReady') self.sendUpdate('setTrolleyZone', [self.trolleyZone]) for avId in self.scoreDict.keys(): self.scoreDict[avId] = 0 self.treasureHolders = [0] * self.numPlayers self.SPAWNTIME = self.difficultyPatternsAI[self.getSafezoneId()][0] self.proportion = self.difficultyPatternsAI[self.getSafezoneId()][1] self.REWARDMOD = self.difficultyPatternsAI[self.getSafezoneId()][2] DistributedMinigameAI.setGameReady(self) self.spawnings = [] for i in xrange(DivingGameGlobals.NUM_SPAWNERS): self.spawnings.append(Sequence(Func(self.spawnFish, i), Wait(self.SPAWNTIME + random.random()), Func(self.spawnFish, i), Wait(self.SPAWNTIME - 0.5 + random.random()))) self.spawnings[i].loop() def setGameStart(self, timestamp): self.notify.debug('setGameStart') DistributedMinigameAI.setGameStart(self, timestamp) self.gameFSM.request('swimming') self.scoreTracking = {} for avId in self.scoreDict.keys(): self.scoreTracking[avId] = [0, 0, 0, 0, 0] def getCrabMoving(self, crabId, crabX, dir): timestamp = globalClockDelta.getFrameNetworkTime() rand1 = int(random.random() * 10) rand2 = int(random.random() * 10) self.sendUpdate('setCrabMoving', [crabId, timestamp, rand1, rand2, crabX, dir]) def treasureRecovered(self): if not hasattr(self, 'scoreTracking'): return avId = self.air.getAvatarIdFromSender() if avId not in self.avIdList: self.air.writeServerEvent('suspicious', avId, 'DivingGameAI.treasureRecovered: invalid avId') return if avId not in self.treasureHolders: self.air.writeServerEvent('suspicious', avId, 'DivingGameAI.treasureRecovered: tried to recover without holding treasure') return self.treasureHolders[self.treasureHolders.index(avId)] = 0 timestamp = globalClockDelta.getFrameNetworkTime() newSpot = int(random.random() * 30) self.scoreTracking[avId][4] += 1 for someAvId in self.scoreDict.keys(): if someAvId == avId: self.scoreDict[avId] += 10 * (self.REWARDMOD * 0.25) self.scoreDict[someAvId] += 10 * (self.REWARDMOD * 0.75 / float(len(self.scoreDict.keys()))) self.sendUpdate('incrementScore', [avId, newSpot, timestamp]) def hasScoreMult(self): return 0 def setGameAbort(self): self.notify.debug('setGameAbort') taskMgr.remove(self.taskName('gameTimer')) 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) trackingString = 'MiniGame Stats : Diving Game' trackingString += '\nDistrict:%s' % self.getSafezoneId() for avId in self.scoreTracking.keys(): trackingString = trackingString + '\navId:%s fishHits:%s crabHits:%s treasureCatches:%s treasureDrops:%s treasureRecoveries:%s Score: %s' % (avId, self.scoreTracking[avId][0], self.scoreTracking[avId][1], self.scoreTracking[avId][2], self.scoreTracking[avId][3], self.scoreTracking[avId][4], self.scoreDict[avId]) self.air.writeServerEvent('MiniGame Stats', None, trackingString) return def enterInactive(self): self.notify.debug('enterInactive') def exitInactive(self): pass def getTimeBase(self): return self.__timeBase def enterSwimming(self): self.notify.debug('enterSwimming') duration = 65.0 taskMgr.doMethodLater(duration, self.timerExpired, self.taskName('gameTimer')) def timerExpired(self, task): self.notify.debug('timer expired') for avId in self.scoreDict.keys(): if self.scoreDict[avId] < 5: self.scoreDict[avId] = 5 self.gameOver() return Task.done def exitSwimming(self): for i in xrange(DivingGameGlobals.NUM_SPAWNERS): self.spawnings[i].pause() def enterCleanup(self): self.notify.debug('enterCleanup') for i in xrange(DivingGameGlobals.NUM_SPAWNERS): self.spawnings[i].finish() del self.spawnings self.gameFSM.request('inactive') def exitCleanup(self): pass def pickupTreasure(self, chestId): if not hasattr(self, 'scoreTracking'): return timestamp = globalClockDelta.getFrameNetworkTime() avId = self.air.getAvatarIdFromSender() if avId not in self.avIdList: self.air.writeServerEvent('suspicious', avId, 'DivingGameAI.pickupTreasure: invalid avId') return if avId in self.treasureHolders: self.air.writeServerEvent('suspicious', avId, 'DivingGameAI.pickupTreasure: already holding treasure') return if not (0 <= chestId < len(self.treasureHolders)): self.air.writeServerEvent('suspicious', avId, 'DivingGameAI.pickupTreasure: invalid chest requested (#%d)' % chestId) return if self.treasureHolders[chestId]: # This chest is already held by someone else. Because this can happen # during normal play (race conditions if two Toons swim into the treasure # simultaneously) we do not log a suspicious event and silently ignore it. return self.scoreTracking[avId][2] += 1 self.treasureHolders[chestId] = avId self.sendUpdate('setTreasureGrabbed', [avId, chestId]) def spawnFish(self, spawnerId): timestamp = globalClockDelta.getFrameNetworkTime() props = self.proportion[spawnerId] num = random.random() for i in xrange(len(props)): prop = props[i] low = prop[0] high = prop[1] if num > low and num <= high: offset = int(10 * random.random()) self.sendUpdate('fishSpawn', [timestamp, i, spawnerId, offset]) return def handleCrabCollision(self, avId, status): if avId not in self.avIdList: self.air.writeServerEvent('suspicious', avId, 'DivingGameAI.handleCrabCollision: invalid avId') return timestamp = globalClockDelta.getFrameNetworkTime() self.sendUpdate('setTreasureDropped', [avId, timestamp]) self.scoreTracking[avId][1] += 1 if status == 'normal' or status == 'treasure': timestamp = globalClockDelta.getFrameNetworkTime() self.sendUpdate('performCrabCollision', [avId, timestamp]) if status == 'treasure': if avId in self.treasureHolders: self.treasureHolders[self.treasureHolders.index(avId)] = 0 self.scoreTracking[avId][3] += 1 else: self.air.writeServerEvent('suspicious', avId, 'DivingGameAI.handleCrabCollision: reported "treasure drop" without holding treasure') def handleFishCollision(self, avId, spawnId, spawnerId, status): if avId not in self.avIdList: self.air.writeServerEvent('suspicious', avId, 'DivingGameAI.handleFishCollision: invalid avId') return timestamp = globalClockDelta.getFrameNetworkTime() self.sendUpdate('setTreasureDropped', [avId, timestamp]) timestamp = globalClockDelta.getFrameNetworkTime() self.scoreTracking[avId][0] += 1 if status == 'treasure': if avId in self.treasureHolders: self.treasureHolders[self.treasureHolders.index(avId)] = 0 self.scoreTracking[avId][3] += 1 else: self.air.writeServerEvent('suspicious', avId, 'DivingGameAI.handleFishCollision: reported "treasure drop" without holding treasure') self.sendUpdate('performFishCollision', [avId, spawnId, spawnerId, timestamp])