diff --git a/game.py b/game.py index 1e4673f..9474f9f 100644 --- a/game.py +++ b/game.py @@ -1,6 +1,6 @@ -import random, team, player, os +import random, team, player, os, math from team import Team -from player import Player, AtkAction, DefAction +from player import Player, AtkAction, DefAction, Skater, Goalie from skillContests import SkillContestParams, Situations from attributes import normalDis from hocUtils import RinkGraph @@ -21,7 +21,8 @@ class Game(object): self.awayZones = RinkGraph(edgeFilename=DEFAULTRINKFILENAME) self.homeZones = RinkGraph(edgeFilename=DEFAULTRINKFILENAME) self.currentZone = None - self.faceoff = FaceoffDot.Center + self.faceoffSpot = FaceoffDot.Center + self.playStopped = True self.lineSize = 5 if len(awayTeam.roster) != 10 or len(homeTeam.roster) != 10 or threes: @@ -30,11 +31,11 @@ class Game(object): self.goalieHome = self.home.chooseGoalie() self.goalieAway = self.away.chooseGoalie() - self.positionInPossession = None + self.positionInPossession = None #use SkaterPosition enum self.teamInPossession = None - self.skatersHome = [] #LW LD C RD RW, use the SkaterPosition enum for indexing. - self.skatersAway = [] + self.skatersHome = self.home.roster[:5] #LW LD C RD RW, EA; use the SkaterPosition enum for indexing. Threes uses left winger, left defenseman, center. + self.skatersAway = self.away.roster[:5] self.penaltyBoxAway = [] self.penaltyBoxHome = [] @@ -42,22 +43,35 @@ class Game(object): self.pulledGoalieHome = False self.period = 1 - self.clock = 60*20 #clock will be given in seconds + self.clock = 60*20 #Time remaining in period, given in seconds self.eventLog = [] def defendingTeam(self): - if teamInPossession == self.home: + if self.teamInPossession == self.home: return self.away else: return self.home def attackingTeam(self): """Alias for teamInPossession, to match defendingTeam()""" - return teamInPossession + return self.teamInPossession def homeAttacking(self): - return teamInPossession == self.home + return self.teamInPossession == self.home + + def skatersInPossession(self): + return self.skatersHome if self.homeAttacking() else self.skatersAway + + def clockToMinutesSeconds(self): + """Returns a string MM:SS elapsed in period.""" + elapsedSeconds = 60*20 - self.clock if self.clock >= 0 else 60*20 + minutes = str(int(math.modf(elapsedSeconds/60)[1])) + seconds = str(elapsedSeconds % 60) + if len(seconds) == 1: + seconds = f"0{seconds}" + return f"{minutes}:{seconds}" + def currentSituation(self): skatersH = self.lineSize + self.pulledGoalieHome - len(self.penaltyBoxHome) @@ -83,6 +97,22 @@ class Game(object): defRoll = normalDis(defValue, defValue/2, 0) return atkRoll-defRoll > 0 + def faceoff(self, awayPlayer:Skater, homePlayer:Skater): + """Hold a faceoff! True indicates home win, False is away win.""" + faceoffSkills = [('Dex',50),('Sti',50),('Pas', 10)] + params = SkillContestParams(faceoffSkills, faceoffSkills) + return self.skillContest(homePlayer, awayPlayer, params) if random.random() > 0.4 else random.sample([True, False], 1)[0] + + def event(self): + """Meat and potatoes. Everything that happens is a direct result of this being called.""" + if self.playStopped: #need a faceoff + self.teamInPossession = self.home if self.faceoff(self.skatersAway[SkaterPosition.C.value], self.skatersHome[SkaterPosition.C.value]) else self.away + self.positionInPossession = SkaterPosition(random.sample([0, 1, 1, 3, 3, 4],1)[0]) #wingers are less likely to recieve the faceoff than defensemen + self.playStopped = False + winningPlayer = self.skatersInPossession()[SkaterPosition.C.value] + self.eventLog.append(f"{self.clockToMinutesSeconds()} - {self.teamInPossession.shortname} {str(winningPlayer)} wins faceoff.") + self.clock -= random.randint(2,5) + class FaceoffDot(Enum): """All orientations are given from the perspective of the defending team.""" AwayZoneLeft = -4 @@ -101,4 +131,5 @@ class SkaterPosition(Enum): LD = 1 C = 2 RD = 3 - RW = 4 \ No newline at end of file + RW = 4 + EA = 5 \ No newline at end of file diff --git a/hocTests.py b/hocTests.py index a3005c4..4167a47 100644 --- a/hocTests.py +++ b/hocTests.py @@ -11,7 +11,7 @@ class AttributeTest(object): self.fakeGame = game.Game(None, None) - self.params = skillContests.SkillContestParams(self.atkAction, self.defAction) + self.params = skillContests.SkillContestParams().actionCheck(self.atkAction, self.defAction) def lowStats(self): """Tests attacker and defender with minimum stats.""" @@ -86,4 +86,44 @@ class AttributeTest(object): for attr, w in self.params.defStats: print(self.defPlayer.getAttribute(attr)) print(f"Success rate: {str(round(success/total*100,2))}%") - print("-------") \ No newline at end of file + print("-------") + + +class TestGame(object): + + def __init__(self): + awayRoster = [ + player.Player("Laika", 93), + player.Player("Vivi", 16), + player.Player("Jorts", 75), + player.Player("Yuki", 23), + player.Player("Konecny", 96), + player.Player("Laika", 93), + player.Player("Vivi", 16), + player.Player("Jorts", 75), + player.Player("Yuki", 23), + player.Player("Konecny", 96) + ] + homeRoster = [ + player.Player("Landeskog", 92), + player.Player("Byram", 4), + player.Player("MacKinnon", 29), + player.Player("Makar", 8), + player.Player("Rantanen", 96), + player.Player("Landeskog", 92), + player.Player("Byram", 4), + player.Player("MacKinnon", 29), + player.Player("Makar", 8), + player.Player("Rantanen", 96) + ] + + + aTeam = team.Team(awayRoster, [player.Player('Artemis', 17)], "Jorts Butter", "BTR") + hTeam = team.Team(homeRoster, [player.Player('Kuemper', 35)], "Colorado Avalanche", "COL") + self.Game = game.Game(aTeam, hTeam) + + def faceoffTest(self): + for i in range(0,8): + self.Game.playStopped = True + foResult = self.Game.event() + pass \ No newline at end of file diff --git a/hocUtils.py b/hocUtils.py index 9b929bb..4b47690 100644 --- a/hocUtils.py +++ b/hocUtils.py @@ -128,4 +128,20 @@ class RinkGraph(object): for otherNodeName, nodeDic in allConnected.items(): if nodeDic['adjacent']: adjacents.append(otherNodeName) - return adjacents \ No newline at end of file + return adjacents + + def shotDanger(self, nodeName): + """Returns an int indicating the danger of a shot from that zone. 0 is no danger, 100 is 26-Offensive Low Slot""" + if isinstance(nodeName, int): + nodeName = str(nodeName) + + if int(nodeName[1]) < 5: + return 0 + elif nodeName == '26': + return 100 + elif nodeName == '25': + return 70 + elif nodeName[0] in ['1','3'] or nodeName == '27': #27 is included for tuck/michigan + return 40 + else: + return 20 \ No newline at end of file