from threading import Timer from utils.RepeatTimer import RepeatTimer import time import random import logging import config from lamps.Lamp import Lamp from lamps.LampGroup import CHAMP_LAMPS from lamps.LampGroup import UPPER_PLAYFIELD_TIME_LAMPS from lamps.LampGroup import TUNNEL_NUMBER_LAMPS from lamps.LampGroup import TUNNEL_LAMPS from lamps.LampGroup import TUNNEL_SCORE_LAMPS from lamps.LampGroup import BONUS_MULTIPLIER_LAMPS from lamps.LampGroup import BONUS_LAMPS from events.LeaveUpperPlayfieldEvent import LeaveUpperPlayfieldEvent from solenoids.BottomLeftBankSolenoid import BottomLeftBankSolenoid from solenoids.BottomRightBankSolenoid import BottomRightBankSolenoid from solenoids.TopCentralBankSolenoid import TopCentralBankSolenoid TUNNEL_SCORES = [20000, 30000, 50000] BONUS_MULTIPLIER = [1, 10, 20, 50] UPPER_PLAYFIELD_TIME = [5, 10, 20, 30] class PlayerState: display = None specialDisplay = None id = 0 _points = 0 @property def points(self): return self._points @points.setter def points(self, points): self._points = points self.display.printScore(self.points) bonus = 0 bonusMultiplierIter = iter(BONUS_MULTIPLIER) bonusMultiplier = 1 tunnelScoreIter = iter(TUNNEL_SCORES) tunnelScore = 0 tunnelLit = 0 ballsLeft = 0 replayBall = False hasBallScored = False isActive = False redSpecial = 0 redSpecialLit = False orangeSpecialLeft = False orangeSpecialRight = False orangeSpecialLit = False advanceTimeLeft = False advanceTimeRight = False timeAdvanceLeftTimer = None timeAdvanceRightTimer = None upperPlayfieldTimer = None upperPlayfieldTimeIter = iter(UPPER_PLAYFIELD_TIME) upperPlayfieldTime = 0 def __init__(self, display, specialDisplay, id, ballsToPlay, banks): self.banks = banks self.display = display self.specialDisplay = specialDisplay self.id = id self.points = 0 self.ballsLeft = ballsToPlay self.enableTiming() self.bonusTime = config.BEGINNING_BONUS_TIME self.specialDisplay.printScore() def activate(self): self.resetBall() self.isActive = True def deactivate(self): self.isActive = False def enableTiming(self): if config.BONUS_TIME_ALGORITHM == config.BONUS_TIME_ALGORITHM_OPTIONS.RANDOM: self.disableAdvanceTimeLeft() self.disableAdvanceTimeRight() self.timeAdvanceLeft() self.timeAdvanceRight() elif config.BONUS_TIME_ALGORITHM == config.BONUS_TIME_ALGORITHM_OPTIONS.ALWAYS: self.enableAdvanceTimeLeft() self.enableAdvanceTimeRight() def timeAdvanceLeft(self): choiceList = [True] * int(config.BONUS_TIME_ACTIVATION_PROBABILITY * 100) \ + [False] * int((1 - config.BONUS_TIME_ACTIVATION_PROBABILITY) * 100) if random.choice(choiceList): self.enableAdvanceTimeLeft() else: self.disableAdvanceTimeLeft() activationTime = random.randrange(config.BONUS_TIME_MIN_RANDOM_TIME, config.BONUS_TIME_MAX_RANDOM_TIME) self.timeAdvanceLeftTimer = Timer(activationTime, self.timeAdvanceLeft) def timeAdvanceRight(self): choiceList = [True] * int(config.BONUS_TIME_ACTIVATION_PROBABILITY * 100) \ + [False] * int((1 - config.BONUS_TIME_ACTIVATION_PROBABILITY) * 100) if random.choice(choiceList): self.enableAdvanceTimeRight() else: self.disableAdvanceTimeRight() activationTime = random.randrange(config.BONUS_TIME_MIN_RANDOM_TIME, config.BONUS_TIME_MAX_RANDOM_TIME) self.timeAdvanceLeftTimer = Timer(activationTime, self.timeAdvanceRight) def enableAdvanceTimeLeft(self): self.advanceTimeLeft = True Lamp("Left Advance Time").activate() def disableAdvanceTimeLeft(self): self.advanceTimeLeft = False Lamp("Left Advance Time").deactivate() def enableAdvanceTimeRight(self): self.advanceTimeRight = True Lamp("Right Advance Time").activate() def disableAdvanceTimeRight(self): self.advanceTimeRight = False Lamp("Right Advance Time").deactivate() def reset(self): self.resetBall() self.upperPlayfieldTime = next(self.upperPlayfieldTimeIter) self.replayBall = False self.hasBallScored = False def resetBall(self): self.resetBanks() self.resetTargets() self.printSpecial() self.upperPlayfieldTimer = None self.upperPlayfieldTimeIter = iter(UPPER_PLAYFIELD_TIME) self.resetBonus() def resetBonus(self): self.bonus = 0 self.bonusMultiplierIter = iter(BONUS_MULTIPLIER) self.bonusMultiplier = next(self.bonusMultiplierIter) BONUS_LAMPS.deactivate() BONUS_MULTIPLIER_LAMPS.deactivate() def resetTargets(self): self.resetBanks() self.resetRedSpecial() self.resetOrangeSpecial() self.resetTunnel() def resetRedSpecial(self): self.redSpecial = 0 self.redSpecialLit = False Lamp("Special Red").deactivate() CHAMP_LAMPS.deactivate() def resetOrangeSpecial(self): self.orangeSpecialLeft = False self.orangeSpecialRight = False self.orangeSpecialLit = False Lamp("Special Orange").deactivate() def resetTunnel(self): self.tunnelScoreIter = iter(TUNNEL_SCORES) self.tunnelScore = next(self.tunnelScoreIter) self.tunnelLit = 0 TUNNEL_SCORE_LAMPS.deactivate() TUNNEL_SCORE_LAMPS.activateNext() TUNNEL_LAMPS.deactivate() def resetBanks(self): for bank in self.banks: bank.reset() BottomRightBankSolenoid().trigger() BottomLeftBankSolenoid().trigger() TopCentralBankSolenoid().trigger() def printSpecial(self): self.specialDisplay.printBallsToPlay(self.ballsLeft) self.specialDisplay.printGameTimeBonus(self.bonusTime) def advanceRightOrangeSpecial(self): if not self.isActive: return self.orangeSpecialRight = True self.setOrangeSpecialLit() def advanceLeftOrangeSpecial(self): if not self.isActive: return self.orangeSpecialLeft = True self.setOrangeSpecialLit() def setOrangeSpecialLit(self): if config.ORANGE_SPECIAL_BANK_OPTIONS == config.ORANGE_SPECIAL_BANK_OPTIONS.ONE: self.orangeSpecialLit = self.orangeSpecialRight or self.orangeSpecialLeft elif config.ORANGE_SPECIAL_BANK == config.ORANGE_SPECIAL_BANK_OPTIONS.BOTH: self.orangeSpecialLit = self.orangeSpecialRight and self.orangeSpecialLeft if self.orangeSpecialLit: Lamp("Special Orange").activate() def advanceRedSpecial(self): if not self.isActive: return self.redSpecial += 1 CHAMP_LAMPS.activateNext() if self.redSpecial == config.RED_SPECIAL_TIMES: self.redSpecialLit = True Lamp("Special Red").activate() def advanceTunnelScore(self): if not self.isActive: return try: self.tunnelScore = next(self.tunnelScoreIter) TUNNEL_SCORE_LAMPS.deactivateCurrent() TUNNEL_SCORE_LAMPS.currentLamp += 1 # dirty TUNNEL_SCORE_LAMPS.activateNext() except StopIteration: pass def advanceTunnel(self): if not self.isActive: return if self.tunnelLit == 5: self.advanceTunnelScore() TUNNEL_LAMPS.deactivate() TUNNEL_NUMBER_LAMPS.deactivate() return self.tunnelLit += 1 TUNNEL_LAMPS.activateNext() TUNNEL_NUMBER_LAMPS.activateNext() def advanceBonus(self): if not self.isActive: return if self.bonus >= 20: return self.bonus += 1 BONUS_LAMPS.activateNext() def advanceBonusMultiplier(self): if not self.isActive: return try: self.bonusMultiplier = next(self.bonusMultiplierIter) BONUS_MULTIPLIER_LAMPS.activateNext() except StopIteration: pass def setReplayBall(self): if not self.isActive: return self.replayBall = True def addPoints(self, points): if not self.isActive: return if not self.hasBallScored: self.hasBallScored = True self.points += points def addBall(self): if not self.isActive: return self.ballsLeft += 1 self.specialDisplay.printBallsToPlay(self.ballsLeft) def removeBall(self): if self.ballsLeft == 0: return self.ballsLeft -= 1 self.specialDisplay.printBallsToPlay(self.ballsLeft) def advanceUpperPlayfieldTime(self): if not self.isActive: return try: self.upperPlayfieldTime = next(self.upperPlayfieldTimeIter) UPPER_PLAYFIELD_TIME_LAMPS.activateNext() except StopIteration: pass def startUpperPlayfieldTimer(self): logging.info("Started Upper Playfield Timer") self.upperPlayfieldTimer = Timer(1, self.updatePlayfieldTime) self.upperPlayfieldTimer.start() def updatePlayfieldTime(self): if self.upperPlayfieldTime == 0: self.upperPlayfieldTimer = None LeaveUpperPlayfieldEvent(self) logging.info("Stopped Upper Playfield Timer") return if self.upperPlayfieldTime in [0, 5, 10, 20]: UPPER_PLAYFIELD_TIME_LAMPS.deactivateCurrent() self.upperPlayfieldTime -= 1 self.upperPlayfieldTimer = Timer(1, self.updatePlayfieldTime) def addBonusTimeSecond(self): if not self.isActive: return self.bonusTime += 1