Files
flippr-game/PlayerState.py
Jonas Zeunert 0ef881bb91 bubb
2022-08-31 15:07:44 +02:00

374 lines
11 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.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
self.replayBall = True
self.replayBallTimer = Timer(interval=1, function=self.updateReplayBall)
def updateReplayBall(self):
self.bonusTime -= 1
self.printSpecial()
if self.bonusTime == 0:
self.stopReplayBall()
return
self.replayBallTimer = Timer(interval=1, function=self.updateReplayBall)
def stopReplayBall(self):
if not self.isActive:
return
self.replayBall = False
self.replayBallTimer = None
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