This commit is contained in:
Jonas Zeunert
2021-03-07 15:47:45 +01:00
parent c54ab2e311
commit 6450ee22dc
10 changed files with 277 additions and 29 deletions

View File

@@ -1,42 +1,139 @@
from threading import Timer from threading import Timer
from utils.RepeatTimer import RepeatTimer
import time import time
import random
import config 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 BONUS_MULTIPLIER_LAMPS
from lamps.LampGroup import BONUS_LAMPS
from events.LeaveUpperPlayfieldEvent import LeaveUpperPlayfieldEvent
class PlayerState: class PlayerState:
def __init__(self, display, specialDisplay, id, ballsToPlay, upperPlayfieldTime = 5, bonusTime = 0): display = None
specialDisplay = None
id = 0
points = 0
bonus = 0
bonusMultiplier = 1
ballsLeft = 0
replayBall = False
redSpecial = 0
redSpecialLit = False
orangeSpecialLeft = False
orangeSpecialRight = False
orangeSpecialLit = False
advanceTimeLeft = False
advanceTimeRight = False
timeAdvanceLeftTimer = None
timeAdvanceRightTimer = None
upperPlayfieldTimer = None
upperPlayfieldTime = 0
def __init__(self, display, specialDisplay, id, ballsToPlay):
self.display = display self.display = display
self.specialDisplay = specialDisplay self.specialDisplay = specialDisplay
self.id = id self.id = id
self.points = 0 self.points = 0
self.ballsLeft = ballsToPlay self.ballsLeft = ballsToPlay
self.enableTiming()
self.bonusTime = config.BEGINNING_BONUS_TIME self.bonusTime = config.BEGINNING_BONUS_TIME
self.reset() self.reset()
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] * config.BONUS_TIME_ACTIVATION_PROBABILITY * 100 \
+ [False] * (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 = time.Timer(activationTime, self.timeAdvanceLeft)
def timeAdvanceLeft(self):
choiceList = [True] * config.BONUS_TIME_ACTIVATION_PROBABILITY * 100 \
+ [False] * (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 = time.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): def reset(self):
self.bonus = 0 self.upperPlayfieldTimer = None
self.bonusMultiplier = 1
self.timer = None
self.timerStartTime = None
self.replayBall = False self.replayBall = False
self.upperPlayfieldTime = config.BEGINNING_UPPER_PLAYFIELD_TIME self.upperPlayfieldTime = config.BEGINNING_UPPER_PLAYFIELD_TIME
self.resetBonus()
self.resetTargets() self.resetTargets()
def resetBonus(self):
self.bonus = 0
self.bonusMultiplier = 1
BONUS_LAMPS.deactivate()
BONUS_MULTIPLIER_LAMPS.deactivate()
def resetTargets(self): def resetTargets(self):
self.resetRedSpecial() self.resetRedSpecial()
self.resetOrangeSpecial() self.resetOrangeSpecial()
self.tunnelLit = 0 self.resetTunnel()
def resetRedSpecial(self): def resetRedSpecial(self):
self.redSpecial = 0 self.redSpecial = 0
self.redSpecialLit = False self.redSpecialLit = False
Lamp("Special Red").deactivate()
CHAMP_LAMPS.deactivate()
def resetOrangeSpecial(self): def resetOrangeSpecial(self):
self.orangeSpecialLeft = False self.orangeSpecialLeft = False
self.orangeSpecialRight = False self.orangeSpecialRight = False
self.orangeSpecialLit = False self.orangeSpecialLit = False
Lamp("Special Orange").deactivate()
def resetTunnel(self):
self.tunnelLit = 0
def advanceRightOrangeSpecial(self): def advanceRightOrangeSpecial(self):
self.orangeSpecialRight = True self.orangeSpecialRight = True
@@ -52,22 +149,41 @@ class PlayerState:
elif config.ORANGE_SPECIAL_BANK == config.ORANGE_SPECIAL_BANK_OPTIONS.BOTH: elif config.ORANGE_SPECIAL_BANK == config.ORANGE_SPECIAL_BANK_OPTIONS.BOTH:
self.orangeSpecialLit = self.orangeSpecialRight and self.orangeSpecialLeft self.orangeSpecialLit = self.orangeSpecialRight and self.orangeSpecialLeft
if self.orangeSpecialLit:
Lamp("Special Orange").activate()
def advanceRedSpecial(self): def advanceRedSpecial(self):
self.redSpecial += 1 self.redSpecial += 1
CHAMP_LAMPS.activateNext()
if(self.redSpecial == config.RED_SPECIAL_TIMES): if(self.redSpecial == config.RED_SPECIAL_TIMES):
self.redSpecialLit = True self.redSpecialLit = True
Lamp("Special Red").activate()
def advanceTunnel(self):
if self.tunnelLit <= 5:
self.tunnelLit += 1
def advanceBonus(self):
if self.bonus >= 20:
return
self.bonus += 1
BONUS_LAMPS.activateNext()
def advanceBonusMultiplier(self): def advanceBonusMultiplier(self):
if self.bonusMultiplier >= 15: if self.bonusMultiplier >= 15:
return return
if self.bonusMultiplier == 1: if self.bonusMultiplier == 1:
self.bonusMultiplier = 5 self.bonusMultiplier = 10
return elif self.bonusMultiplier == 10:
self.bonusMultiplier = 20
elif self.bonusMultiplier == 20:
self.bonusMultiplier == 50
self.bonusMultiplier *= 2 BONUS_MULTIPLIER_LAMPS.activateNext()
def setReplayBall(self): def setReplayBall(self):
self.replayBall = True self.replayBall = True
@@ -87,25 +203,31 @@ class PlayerState:
self.ballsLeft -= 1 self.ballsLeft -= 1
self.specialDisplay.printBallsToPlay(self.ballsLeft) self.specialDisplay.printBallsToPlay(self.ballsLeft)
def addUpperPlayfieldTime(self, time): def advanceUpperPlayfieldTime(self):
self.upperPlayfieldTime += time if self.upperPlayfieldTime == 0:
self.upperPlayfieldTime = 5
elif self.upperPlayfieldTime == 5:
self.upperPlayfieldTime = 10
elif self.upperPlayfieldTime == 10:
self.upperPlayfieldTime = 20
elif self.upperPlayfieldTime == 20:
self.upperPlayfieldTime = 30
def __setUpperPlayfieldTime(self, time): UPPER_PLAYFIELD_TIME_LAMPS.activateNext()
self.upperPlayfieldTime = time
def startUpperPlayfieldTimer(self): def startUpperPlayfieldTimer(self):
self.timerStartTime = time.time() self.upperPlayfieldTimer = Timer(1, self.updatePlayfieldTime)
self.timer = Timer(self.upperPlayfieldTime, self.stopUpperPlayfieldTimer)
def stopUpperPlayfieldTimer(self): def updatePlayfieldTime(self):
if not self.timer: if self.upperPlayfieldTime == 0:
self.upperPlayfieldTimer = None
return return
self.timer.cancel() if self.upperPlayfieldTime in [0, 5, 10, 20]:
UPPER_PLAYFIELD_TIME_LAMPS.deactivateCurrent()
elapsedTime = time.time() - self.timerStartTime self.upperPlayfieldTime -= 1
timeLeft = self.upperPlayfieldTime - elapsedTime self.upperPlayfieldTimer = Timer(1, self.updatePlayfieldTime)
self.__setUpperPlayfieldTime(timeLeft)
def addBonusTimeSecond(self): def addBonusTimeSecond(self):
self.bonusTime += 1 self.bonusTime += 1

View File

@@ -2,7 +2,8 @@ import os
from events.SpecialEvent import SpecialEvent from events.SpecialEvent import SpecialEvent
from enum import Enum from enum import Enum
ORANGE_SPECIAL_BANK_OPTIONS = Enum("BOTH", "ONE") ORANGE_SPECIAL_BANK_OPTIONS = Enum("ORANGE_SPECIAL_BANK_OPTIONS", ["BOTH", "ONE"])
BONUS_TIME_ALGORITHM_OPTIONS = Enum("BONUS_TIME_ALGORITHM_OPTIONS", ["ALWAYS", "RANDOM"])
# Game Config # Game Config
## Network Config ## Network Config
@@ -13,8 +14,13 @@ OUTPUT_SOCKET_NAME = "/S.flippR_driver.out"
BALLS_PER_GAME = 3 BALLS_PER_GAME = 3
BEGINNING_UPPER_PLAYFIELD_TIME = 5 BEGINNING_UPPER_PLAYFIELD_TIME = 5
BEGINNING_BONUS_TIME = 0 BEGINNING_BONUS_TIME = 0
## Bonus Time Algorithm
BONUS_TIME_ALGORITHM = BONUS_TIME_ALGORITHM_OPTIONS["RANDOM"]
BONUS_TIME_MIN_RANDOM_TIME = 5
BONUS_TIME_MAX_RANDOM_TIME = 15
BONUS_TIME_ACTIVATION_PROBABILITY = 0.1
## Special config ## Special config
RED_SPECIAL = SpecialEvent.replay RED_SPECIAL = SpecialEvent.replay
RED_SPECIAL_TIMES = 1 RED_SPECIAL_TIMES = 1
ORANGE_SPECIAL = SpecialEvent.points ORANGE_SPECIAL = SpecialEvent.points
ORANGE_SPECIAL_BANK = ORANGE_SPECIAL_BANK_OPTIONS.BOTH ORANGE_SPECIAL_BANK = ORANGE_SPECIAL_BANK_OPTIONS["BOTH"]

View File

@@ -10,3 +10,7 @@ class BankEvent(Event):
def trigger(self, target): def trigger(self, target):
super().trigger(target) super().trigger(target)
self.bankSolenoid.trigger() self.bankSolenoid.trigger()
self.advanceBonus()
def advanceBonus(self):
self.playerState().advanceBonus()

View File

@@ -10,5 +10,4 @@ class BottomLeftBankEvent(BankEvent):
super().trigger(target) super().trigger(target)
playerState = self.playerState() playerState = self.playerState()
playerState.advanceLeftOrangeSpecial() playerState.advanceLeftOrangeSpecial()
if playerState.upperPlayfieldTime < 30: playerState.advanceUpperPlayfieldTime()
playerState.addUpperPlayfieldTime(5)

View File

@@ -0,0 +1,11 @@
from Event import Event
class FixedTargetEvent(Event):
def __init__(self, playerState):
super().__init__("Fixed Target Event")
self.playerState = playerState
def trigger(self, target):
super().trigger(target)
self.playerState().advanceTunnel()

View File

@@ -1,13 +1,13 @@
from Event import Event from Event import Event
from solenoids.TopFlipper import TopFlipper
class LeaveUpperPlayfieldEvent(Event): class LeaveUpperPlayfieldEvent(Event):
def __init__(self, playerState, flipper): def __init__(self, playerState, flipper):
self.playerState = playerState self.playerState = playerState
self.flipper = flipper self.flipper = TopFlipper()
super().__init__("Leave Upper Playfield Event") super().__init__("Leave Upper Playfield Event")
def trigger(self, target): def trigger(self, target):
super().trigger(target) super().trigger(target)
self.flipper.deactivate() self.flipper.deactivate()
self.playerState().stopUpperPlayfieldTimer()

View File

@@ -17,6 +17,7 @@ from events.TunnelEvent import TunnelEvent
from events.RedSpecialEvent import RedSpecialEvent from events.RedSpecialEvent import RedSpecialEvent
from events.OrangeSpecialEvent import OrangeSpecialEvent from events.OrangeSpecialEvent import OrangeSpecialEvent
from events.SpinnerEvent import SpinnerEvent from events.SpinnerEvent import SpinnerEvent
from events.FixedTargetEvent import FixedTargetEvent
class EventFactory: class EventFactory:
def __init__(self, targets, currentPlayer): def __init__(self, targets, currentPlayer):
@@ -113,5 +114,14 @@ class EventFactory:
self.__registerEventToTarget(event, self.targets["Spinner"]) self.__registerEventToTarget(event, self.targets["Spinner"])
return event return event
def createFixedTargetEvent(self):
event = FixedTargetEvent(self.currentPlayer)
self.__registerEventToTarget(event, self.targets["Fixed Target 1"])
self.__registerEventToTarget(event, self.targets["Fixed Target 2"])
self.__registerEventToTarget(event, self.targets["Fixed Target 3"])
self.__registerEventToTarget(event, self.targets["Fixed Target 4"])
self.__registerEventToTarget(event, self.targets["Fixed Target 5"])
return event
def __registerEventToTarget(self, event, target): def __registerEventToTarget(self, event, target):
target.on(target.hit_key, event.trigger) target.on(target.hit_key, event.trigger)

View File

@@ -0,0 +1,15 @@
from networking.Networking import Networking
class Lamp:
def __init__(self, name):
self.name = name
def activate(self):
Networking().activateLamp(self)
def deactivate(self):
Networking().deactivateLamp()
def isActivated(self):
Networking().getLamps(self)

View File

@@ -0,0 +1,74 @@
from lamps.Lamp import Lamp
class LampGroup:
def __init__(self, lamps):
self.lamps = lamps
self.currentLamp = 0
self.deactivate()
def activate(self):
for lamp in self.lamps:
lamp.activate()
def deactivate(self):
for lamp in self.lamps:
lamp.deactivate()
def activateNext(self):
self.lamps[self.currentLamp].activate()
if self.currentLamp == len(self.lamps):
return
self.currentLamp += 1
def deactivateCurrent(self):
self.lamps[self.currentLamp].deactivate()
if self.currentLamp == 0:
return
self.currentLamp -= 1
CHAMP_LAMPS = LampGroup([
Lamp("C Of Champ"),
Lamp("H Of Champ"),
Lamp("A Of Champ"),
Lamp("M Of Champ"),
Lamp("P Of Champ")
])
UPPER_PLAYFIELD_TIME_LAMPS = LampGroup([
Lamp("Lamp 5 Sec"),
Lamp("Lamp 10 Sec"),
Lamp("Lamp 20 Sec"),
Lamp("Lamp 30 Sec")
])
BONUS_MULTIPLIER_LAMPS = LampGroup([
Lamp("Bonus Multiplier x10"),
Lamp("Bonus Multiplier x20"),
Lamp("Bonus Multiplier x50")
])
BONUS_LAMPS = LampGroup([
Lamp("Bonus 1000"),
Lamp("Bonus 2000"),
Lamp("Bonus 3000"),
Lamp("Bonus 4000"),
Lamp("Bonus 5000"),
Lamp("Bonus 6000"),
Lamp("Bonus 7000"),
Lamp("Bonus 8000"),
Lamp("Bonus 9000"),
Lamp("Bonus 10000"),
Lamp("Bonus 11000"),
Lamp("Bonus 12000"),
Lamp("Bonus 13000"),
Lamp("Bonus 14000"),
Lamp("Bonus 15000"),
Lamp("Bonus 16000"),
Lamp("Bonus 17000"),
Lamp("Bonus 18000"),
Lamp("Bonus 19000"),
Lamp("Bonus 20000")
])

7
utils/RepeatTimer.py Normal file
View File

@@ -0,0 +1,7 @@
from threading import Timer
class RepeatTimer(Timer):
def run(self):
while not self.finished.wait(self.interval):
self.function(*self.args, **self.kwargs)