faceoffs and functioning test game

This commit is contained in:
Sakimori 2022-01-11 13:50:01 -05:00
parent 1c6a5400a5
commit a317e079d6
3 changed files with 101 additions and 14 deletions

53
game.py
View file

@ -1,6 +1,6 @@
import random, team, player, os import random, team, player, os, math
from team import Team from team import Team
from player import Player, AtkAction, DefAction from player import Player, AtkAction, DefAction, Skater, Goalie
from skillContests import SkillContestParams, Situations from skillContests import SkillContestParams, Situations
from attributes import normalDis from attributes import normalDis
from hocUtils import RinkGraph from hocUtils import RinkGraph
@ -21,7 +21,8 @@ class Game(object):
self.awayZones = RinkGraph(edgeFilename=DEFAULTRINKFILENAME) self.awayZones = RinkGraph(edgeFilename=DEFAULTRINKFILENAME)
self.homeZones = RinkGraph(edgeFilename=DEFAULTRINKFILENAME) self.homeZones = RinkGraph(edgeFilename=DEFAULTRINKFILENAME)
self.currentZone = None self.currentZone = None
self.faceoff = FaceoffDot.Center self.faceoffSpot = FaceoffDot.Center
self.playStopped = True
self.lineSize = 5 self.lineSize = 5
if len(awayTeam.roster) != 10 or len(homeTeam.roster) != 10 or threes: 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.goalieHome = self.home.chooseGoalie()
self.goalieAway = self.away.chooseGoalie() self.goalieAway = self.away.chooseGoalie()
self.positionInPossession = None self.positionInPossession = None #use SkaterPosition enum
self.teamInPossession = None self.teamInPossession = None
self.skatersHome = [] #LW LD C RD RW, use the SkaterPosition enum for indexing. 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.skatersAway = self.away.roster[:5]
self.penaltyBoxAway = [] self.penaltyBoxAway = []
self.penaltyBoxHome = [] self.penaltyBoxHome = []
@ -42,22 +43,35 @@ class Game(object):
self.pulledGoalieHome = False self.pulledGoalieHome = False
self.period = 1 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 = [] self.eventLog = []
def defendingTeam(self): def defendingTeam(self):
if teamInPossession == self.home: if self.teamInPossession == self.home:
return self.away return self.away
else: else:
return self.home return self.home
def attackingTeam(self): def attackingTeam(self):
"""Alias for teamInPossession, to match defendingTeam()""" """Alias for teamInPossession, to match defendingTeam()"""
return teamInPossession return self.teamInPossession
def homeAttacking(self): 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): def currentSituation(self):
skatersH = self.lineSize + self.pulledGoalieHome - len(self.penaltyBoxHome) skatersH = self.lineSize + self.pulledGoalieHome - len(self.penaltyBoxHome)
@ -83,6 +97,22 @@ class Game(object):
defRoll = normalDis(defValue, defValue/2, 0) defRoll = normalDis(defValue, defValue/2, 0)
return atkRoll-defRoll > 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): class FaceoffDot(Enum):
"""All orientations are given from the perspective of the defending team.""" """All orientations are given from the perspective of the defending team."""
AwayZoneLeft = -4 AwayZoneLeft = -4
@ -101,4 +131,5 @@ class SkaterPosition(Enum):
LD = 1 LD = 1
C = 2 C = 2
RD = 3 RD = 3
RW = 4 RW = 4
EA = 5

View file

@ -11,7 +11,7 @@ class AttributeTest(object):
self.fakeGame = game.Game(None, None) 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): def lowStats(self):
"""Tests attacker and defender with minimum stats.""" """Tests attacker and defender with minimum stats."""
@ -86,4 +86,44 @@ class AttributeTest(object):
for attr, w in self.params.defStats: for attr, w in self.params.defStats:
print(self.defPlayer.getAttribute(attr)) print(self.defPlayer.getAttribute(attr))
print(f"Success rate: {str(round(success/total*100,2))}%") print(f"Success rate: {str(round(success/total*100,2))}%")
print("-------") 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

View file

@ -128,4 +128,20 @@ class RinkGraph(object):
for otherNodeName, nodeDic in allConnected.items(): for otherNodeName, nodeDic in allConnected.items():
if nodeDic['adjacent']: if nodeDic['adjacent']:
adjacents.append(otherNodeName) adjacents.append(otherNodeName)
return adjacents 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