text: from direct.distributed.DistributedNodeAI import DistributedNodeAI
  from direct.distributed.ClockDelta import *
  from direct.fsm import ClassicFSM, State
  from direct.fsm import State
  from direct.fsm import StateData
  from toontown.safezone import DistributedChineseCheckersAI
  from toontown.safezone import DistributedCheckersAI
  from toontown.safezone import DistributedFindFourAI
  
  class DistributedPicnicTableAI(DistributedNodeAI):
  
      def __init__(self, air, zone, name, x, y, z, h, p, r):
          DistributedNodeAI.__init__(self, air)
          self.name = name
          self.air = air
          self.seats = [None,
           None,
           None,
           None,
           None,
           None]
          self.setPos(x, y, z)
          self.setHpr(h, p, r)
          self.playersSitting = 0
          self.myPos = (x, y, z)
          self.myHpr = (h, p, r)
          self.playerIdList = []
          self.checkersZoneId = None
          self.generateOtpObject(air.districtId, zone, optionalFields=['setX',
           'setY',
           'setZ',
           'setH',
           'setP',
           'setR'])
          self.observers = []
          self.allowPickers = []
          self.hasPicked = False
          self.game = None
          self.gameDoId = None
          self.isAccepting = True
          return
  
      def announceGenerate(self):
          pass
  
      def delete(self):
          DistributedNodeAI.delete(self)
          self.game = None
          self.gameDoId = None
          return
  
      def setGameDoId(self, doId):
          self.gameDoId = doId
          self.game = self.air.doId2do.get(doId)
  
      def requestTableState(self):
          avId = self.air.getAvatarIdFromSender()
          self.getTableState()
  
      def getTableState(self):
          tableStateList = []
          for x in self.seats:
              if x == None:
                  tableStateList.append(0)
              else:
                  tableStateList.append(x)
  
          if self.game and self.game.fsm.getCurrentState().getName() == 'playing':
              self.sendUpdate('setTableState', [tableStateList, 1])
          else:
              self.sendUpdate('setTableState', [tableStateList, 0])
          return
  
      def sendIsPlaying(self):
          if self.game.fsm.getCurrentState().getName() == 'playing':
              self.sendUpdate('setIsPlaying', [1])
          else:
              self.sendUpdate('setIsPlaying', [0])
  
      def announceWinner(self, gameName, avId):
          self.sendUpdate('announceWinner', [gameName, avId])
          self.gameDoId = None
          self.game = None
          return
  
      def requestJoin(self, si, x, y, z, h, p, r):
          avId = self.air.getAvatarIdFromSender()
          if self.findAvatar(avId) != None:
              self.notify.warning('Ignoring multiple requests from %s to board.' % avId)
              return
          else:
              av = self.air.doId2do.get(avId)
              if av:
                  if av.hp > 0 and self.isAccepting and self.seats[si] == None:
                      self.notify.debug('accepting boarder %d' % avId)
                      self.acceptBoarder(avId, si, x, y, z, h, p, r)
                  else:
                      self.notify.debug('rejecting boarder %d' % avId)
                      self.sendUpdateToAvatarId(avId, 'rejectJoin', [])
              else:
                  self.notify.warning('avid: %s does not exist, but tried to board a picnicTable' % avId)
              return
  
      def acceptBoarder(self, avId, seatIndex, x, y, z, h, p, r):
          self.notify.debug('acceptBoarder %d' % avId)
          if self.findAvatar(avId) != None:
              return
          isEmpty = True
          for xx in self.seats:
              if xx != None:
                  isEmpty = False
                  break
  
          if isEmpty == True or self.hasPicked == False:
              self.sendUpdateToAvatarId(avId, 'allowPick', [])
              self.allowPickers.append(avId)
          if self.hasPicked == True:
              self.sendUpdateToAvatarId(avId, 'setZone', [self.game.zoneId])
          self.seats[seatIndex] = avId
          self.acceptOnce(self.air.getAvatarExitEvent(avId), self.__handleUnexpectedExit, extraArgs=[avId])
          self.timeOfBoarding = globalClock.getRealTime()
          if self.game:
              self.game.informGameOfPlayer()
          self.sendUpdate('fillSlot', [avId,
           seatIndex,
           x,
           y,
           z,
           h,
           p,
           r,
           globalClockDelta.localToNetworkTime(self.timeOfBoarding),
           self.doId])
          self.getTableState()
          return
  
      def requestPickedGame(self, gameNum):
          avId = self.air.getAvatarIdFromSender()
          if self.hasPicked == False and avId in self.allowPickers:
              self.hasPicked = True
              numPickers = len(self.allowPickers)
              self.allowPickers = []
              self.pickGame(gameNum)
              if self.game:
                  for x in xrange(numPickers):
                      self.game.informGameOfPlayer()
  
      def pickGame(self, gameNum):
          x = 0
          for x in self.seats:
              if x != None:
                  x += 1
  
          if gameNum == 1:
              if simbase.config.GetBool('want-chinese', 0):
                  self.game = DistributedChineseCheckersAI.DistributedChineseCheckersAI(self.air, self.doId, 'chinese', self.getX(), self.getY(), self.getZ() + 2.83, self.getH(), self.getP(), self.getR())
                  self.sendUpdate('setZone', [self.game.zoneId])
          elif gameNum == 2:
              if x <= 2:
                  if simbase.config.GetBool('want-checkers', 0):
                      self.game = DistributedCheckersAI.DistributedCheckersAI(self.air, self.doId, 'checkers', self.getX(), self.getY(), self.getZ() + 2.83, self.getH(), self.getP(), self.getR())
                      self.sendUpdate('setZone', [self.game.zoneId])
          elif x <= 2:
              if simbase.config.GetBool('want-findfour', 0):
                  self.game = DistributedFindFourAI.DistributedFindFourAI(self.air, self.doId, 'findFour', self.getX(), self.getY(), self.getZ() + 2.83, self.getH(), self.getP(), self.getR())
                  self.sendUpdate('setZone', [self.game.zoneId])
          return
  
      def requestZone(self):
          avId = self.air.getAvatarIdFromSender()
          self.sendUpdateToAvatarId(avId, 'setZone', [self.game.zoneId])
  
      def requestGameZone(self):
          if self.hasPicked == True:
              avId = self.air.getAvatarIdFromSender()
              if self.game:
                  self.game.playersObserving.append(avId)
              self.observers.append(avId)
              self.acceptOnce(self.air.getAvatarExitEvent(avId), self.handleObserverExit, extraArgs=[avId])
              if self.game:
                  if self.game.fsm.getCurrentState().getName() == 'playing':
                      self.sendUpdateToAvatarId(avId, 'setGameZone', [self.checkersZoneId, 1])
                  else:
                      self.sendUpdateToAvatarId(avId, 'setGameZone', [self.checkersZoneId, 0])
  
      def leaveObserve(self):
          avId = self.air.getAvatarIdFromSender()
          if self.game:
              if avId in self.game.playersObserving:
                  self.game.playersObserving.remove(avId)
  
      def handleObserverExit(self, avId):
          if self.game and avId in self.game.playersObserving:
              if self.game:
                  self.game.playersObserving.remove(avId)
                  self.ignore(self.air.getAvatarExitEvent(avId))
  
      def requestExit(self):
          self.notify.debug('requestExit')
          avId = self.air.getAvatarIdFromSender()
          av = self.air.doId2do.get(avId)
          if av:
              if self.countFullSeats() > 0:
                  self.acceptExiter(avId)
              else:
                  self.notify.debug('Player tried to exit after AI already kicked everyone out')
          else:
              self.notify.warning('avId: %s does not exist, but tried to exit picnicTable' % avId)
  
      def acceptExiter(self, avId):
          seatIndex = self.findAvatar(avId)
          if seatIndex == None:
              if avId in self.observers:
                  self.sendUpdateToAvatarId(avId, 'emptySlot', [avId, 255, globalClockDelta.getRealNetworkTime()])
          else:
              self.seats[seatIndex] = None
              self.ignore(self.air.getAvatarExitEvent(avId))
              self.sendUpdate('emptySlot', [avId, seatIndex, globalClockDelta.getRealNetworkTime()])
              self.getTableState()
              numActive = 0
              for x in self.seats:
                  if x != None:
                      numActive = numActive + 1
  
          if self.game:
              self.game.informGameOfPlayerLeave()
              self.game.handlePlayerExit(avId)
          if numActive == 0:
              self.isAccepting = True
              if self.game:
                  self.game.handleEmptyGame()
                  self.game.requestDelete()
                  self.game = None
                  self.hasPicked = False
          return
  
      def __handleUnexpectedExit(self, avId):
          self.notify.warning('Avatar: ' + str(avId) + ' has exited unexpectedly')
          seatIndex = self.findAvatar(avId)
          if seatIndex == None:
              pass
          else:
              self.seats[seatIndex] = None
              self.ignore(self.air.getAvatarExitEvent(avId))
              if self.game:
                  self.game.informGameOfPlayerLeave()
                  self.game.handlePlayerExit(avId)
                  self.hasPicked = False
              self.getTableState()
              numActive = 0
              for x in self.seats:
                  if x != None:
                      numActive = numActive + 1
  
          if numActive == 0 and self.game:
              simbase.air.deallocateZone(self.game.zoneId)
              self.game.requestDelete()
              self.game = None
              self.gameDoId = None
          return
  
      def informGameOfPlayerExit(self, avId):
          self.game.handlePlayerExit(avId)
  
      def handleGameOver(self):
          for x in self.observers:
              self.acceptExiter(x)
              self.observers.remove(x)
  
          if self.game:
              self.game.playersObserving = []
          for x in self.seats:
              if x != None:
                  self.acceptExiter(x)
  
          self.game = None
          self.gameDoId = None
          self.hasPicked = False
          return
  
      def findAvatar(self, avId):
          for i in xrange(len(self.seats)):
              if self.seats[i] == avId:
                  return i
  
          return
  
      def countFullSeats(self):
          avCounter = 0
          for i in self.seats:
              if i:
                  avCounter += 1
  
          return avCounter
  
      def findAvailableSeat(self):
          for i in xrange(len(self.seats)):
              if self.seats[i] == None:
                  return i
  
          return
  
      def setCheckersZoneId(self, zoneId):
          self.checkersZoneId = zoneId