383 lines
12 KiB
Python
383 lines
12 KiB
Python
from threading import Timer
|
|
from utils.RepeatTimer import RepeatTimer
|
|
import time
|
|
import random
|
|
import logging
|
|
import config
|
|
|
|
from lamps.Lamp import Lamp
|
|
from lamps.Lamp import SHOOT_AGAIN
|
|
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 lamps.LampGroup import PLAYER_LAMPS
|
|
|
|
from events.LeaveUpperPlayfieldEvent import LeaveUpperPlayfieldEvent
|
|
from solenoids.BottomLeftBankSolenoid import BottomLeftBankSolenoid
|
|
from solenoids.BottomRightBankSolenoid import BottomRightBankSolenoid
|
|
from solenoids.TopCentralBankSolenoid import TopCentralBankSolenoid
|
|
|
|
from solenoids.MainFlipper import MainFlipper
|
|
|
|
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
|
|
hasBallScored = False
|
|
isActive = False
|
|
hasHighscore = 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
|
|
|
|
replayBall = False
|
|
bonusTime = config.BEGINNING_BONUS_TIME
|
|
replayBallTimer = None
|
|
|
|
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.printSpecial()
|
|
|
|
def activate(self):
|
|
self.isActive = False
|
|
self.resetBall()
|
|
PLAYER_LAMPS.deactivate()
|
|
PLAYER_LAMPS.activate_one(self.id)
|
|
time.sleep(config.WAIT_TIME_TO_RESET_SECONDS)
|
|
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.points = 0
|
|
|
|
def resetBall(self):
|
|
self.resetBanks()
|
|
self.resetTargets()
|
|
self.printSpecial()
|
|
self.upperPlayfieldTime = next(self.upperPlayfieldTimeIter)
|
|
self.upperPlayfieldTimer = None
|
|
self.upperPlayfieldTimeIter = iter(UPPER_PLAYFIELD_TIME)
|
|
|
|
self.replayBall = False
|
|
self.hasBallScored = False
|
|
SHOOT_AGAIN.activate()
|
|
|
|
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:
|
|
self.advanceBonusMultiplier()
|
|
self.tunnelScore = iter(TUNNEL_SCORES)
|
|
self.tunnelScore = next(self.tunnelScoreIter)
|
|
TUNNEL_SCORE_LAMPS.deactivate()
|
|
TUNNEL_SCORE_LAMPS.activateNext()
|
|
|
|
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
|
|
|
|
if self.ballsLeft == 0 and self.bonusTime != 0:
|
|
self.replayBall = True
|
|
SHOOT_AGAIN.activate()
|
|
if self.replayBallTimer != None:
|
|
self.replayBallTimer.cancel()
|
|
self.replayBallTimer = Timer(interval=1, function=self.updateReplayBall)
|
|
self.replayBallTimer.start()
|
|
|
|
def updateReplayBall(self):
|
|
self.bonusTime -= 1
|
|
self.printSpecial()
|
|
|
|
if self.bonusTime == 0:
|
|
self.stopReplayBall()
|
|
return
|
|
|
|
self.replayBallTimer = Timer(interval=1, function=self.updateReplayBall)
|
|
self.replayBallTimer.start()
|
|
|
|
def stopReplayBall(self):
|
|
if not self.isActive:
|
|
return
|
|
|
|
self.replayBall = False
|
|
self.replayBallTimer = None
|
|
SHOOT_AGAIN.deactivate()
|
|
MainFlipper().deactivate()
|
|
|
|
def addPoints(self, points):
|
|
if points == 0:
|
|
return
|
|
|
|
if not self.isActive:
|
|
return
|
|
|
|
if not self.hasBallScored:
|
|
SHOOT_AGAIN.deactivate()
|
|
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(interval=5, function=self.updatePlayfieldTime)
|
|
self.upperPlayfieldTimer.start()
|
|
|
|
def updatePlayfieldTime(self):
|
|
if self.upperPlayfieldTime in [0, 5, 10, 20]:
|
|
UPPER_PLAYFIELD_TIME_LAMPS.deactivateCurrent()
|
|
|
|
if self.upperPlayfieldTime == 0:
|
|
self.upperPlayfieldTimer = None
|
|
LeaveUpperPlayfieldEvent(self).trigger(None)
|
|
logging.info("Stopped Upper Playfield Timer")
|
|
return
|
|
|
|
self.upperPlayfieldTime -= 5
|
|
logging.info("Playfield time left: " + str(self.upperPlayfieldTime))
|
|
self.upperPlayfieldTimer = Timer(interval=5, function=self.updatePlayfieldTime)
|
|
self.upperPlayfieldTimer.start()
|
|
|
|
def addBonusTimeSecond(self):
|
|
if not self.isActive:
|
|
return
|
|
self.bonusTime += 1
|
|
|