implemented default rink graph
This commit is contained in:
parent
cc0487469a
commit
1c6a5400a5
1260
Rinks/Graphs/defaultedges.nx
Normal file
1260
Rinks/Graphs/defaultedges.nx
Normal file
File diff suppressed because it is too large
Load diff
36
Rinks/Graphs/defaultnodesnamed.nx
Normal file
36
Rinks/Graphs/defaultnodesnamed.nx
Normal file
|
@ -0,0 +1,36 @@
|
|||
LDLW
|
||||
LDHW
|
||||
LDNW
|
||||
LONW
|
||||
LOHW
|
||||
LOLW
|
||||
LDC
|
||||
LDL
|
||||
LDH
|
||||
LDN
|
||||
LON
|
||||
LOH
|
||||
LOL
|
||||
LOC
|
||||
DT
|
||||
DLS
|
||||
DHS
|
||||
CD
|
||||
CO
|
||||
OHS
|
||||
OLS
|
||||
OT
|
||||
RDC
|
||||
RDL
|
||||
RDH
|
||||
RDN
|
||||
RON
|
||||
ROH
|
||||
ROL
|
||||
ROC
|
||||
RDLW
|
||||
RDHW
|
||||
RDNW
|
||||
RONW
|
||||
ROHW
|
||||
ROLW
|
36
Rinks/Graphs/defaultnodesnumbered.nx
Normal file
36
Rinks/Graphs/defaultnodesnumbered.nx
Normal file
|
@ -0,0 +1,36 @@
|
|||
01
|
||||
02
|
||||
03
|
||||
04
|
||||
05
|
||||
06
|
||||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
20
|
||||
21
|
||||
22
|
||||
23
|
||||
24
|
||||
25
|
||||
26
|
||||
27
|
||||
30
|
||||
31
|
||||
32
|
||||
33
|
||||
34
|
||||
35
|
||||
36
|
||||
37
|
||||
41
|
||||
42
|
||||
43
|
||||
44
|
||||
45
|
||||
46
|
11
SimHoc.py
11
SimHoc.py
|
@ -1,6 +1,10 @@
|
|||
import os, player, tweepy, twitHandler, time, skillContests, random
|
||||
import os, player, tweepy, twitHandler, time, skillContests, random, itertools
|
||||
from attributes import normalDis
|
||||
from hocTests import AttributeTest
|
||||
from hocUtils import RinkGraph
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
#for name in ["Vivi", "Artemis", "Laika", "Sharks", "Dragons", "Melua", "Sabriina", "Jorts (Buttered)", "Jorts (Unbuttered)"]:
|
||||
|
@ -10,8 +14,9 @@ if __name__ == "__main__":
|
|||
# print(atr)
|
||||
# print("----------")
|
||||
|
||||
test = AttributeTest()
|
||||
test.allTests()
|
||||
g = RinkGraph(edgeFilename="defaultedges.nx")
|
||||
g.getNodeDebug('25')
|
||||
|
||||
|
||||
#twitter = twitHandler.TwitHandler()
|
||||
#if os.path.exists(os.path.join("Data", "lastID.twt")):
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
<Compile Include="hocTests.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="hocUtils.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="skillContests.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
@ -59,6 +62,9 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Data\" />
|
||||
<Folder Include="Rinks\" />
|
||||
<Folder Include="Rinks\Backgrounds\" />
|
||||
<Folder Include="Rinks\Graphs\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Data\s options.txt" />
|
||||
|
|
43
game.py
43
game.py
|
@ -1,8 +1,14 @@
|
|||
import random, team, player
|
||||
import random, team, player, os
|
||||
from team import Team
|
||||
from player import Player, AtkAction, DefAction
|
||||
from skillContests import SkillContestParams, Situations
|
||||
from attributes import normalDis
|
||||
from hocUtils import RinkGraph
|
||||
from enum import Enum
|
||||
import networkx as nx
|
||||
|
||||
RINKDIRPATH = os.path.join("Rinks","Graphs")
|
||||
DEFAULTRINKFILENAME = "defaultedges.nx"
|
||||
|
||||
class Game(object):
|
||||
"""A game of hockey!"""
|
||||
|
@ -12,6 +18,11 @@ class Game(object):
|
|||
self.away = awayTeam
|
||||
self.home = homeTeam
|
||||
|
||||
self.awayZones = RinkGraph(edgeFilename=DEFAULTRINKFILENAME)
|
||||
self.homeZones = RinkGraph(edgeFilename=DEFAULTRINKFILENAME)
|
||||
self.currentZone = None
|
||||
self.faceoff = FaceoffDot.Center
|
||||
|
||||
self.lineSize = 5
|
||||
if len(awayTeam.roster) != 10 or len(homeTeam.roster) != 10 or threes:
|
||||
self.lineSize = 3
|
||||
|
@ -19,10 +30,10 @@ class Game(object):
|
|||
self.goalieHome = self.home.chooseGoalie()
|
||||
self.goalieAway = self.away.chooseGoalie()
|
||||
|
||||
self.playerInPossession = None
|
||||
self.positionInPossession = None
|
||||
self.teamInPossession = None
|
||||
|
||||
self.skatersHome = [] #LW LD C RD RW
|
||||
self.skatersHome = [] #LW LD C RD RW, use the SkaterPosition enum for indexing.
|
||||
self.skatersAway = []
|
||||
|
||||
self.penaltyBoxAway = []
|
||||
|
@ -41,6 +52,10 @@ class Game(object):
|
|||
else:
|
||||
return self.home
|
||||
|
||||
def attackingTeam(self):
|
||||
"""Alias for teamInPossession, to match defendingTeam()"""
|
||||
return teamInPossession
|
||||
|
||||
def homeAttacking(self):
|
||||
return teamInPossession == self.home
|
||||
|
||||
|
@ -66,4 +81,24 @@ class Game(object):
|
|||
|
||||
atkRoll = normalDis(atkValue, atkValue/2, 0)
|
||||
defRoll = normalDis(defValue, defValue/2, 0)
|
||||
return atkRoll-defRoll > 0
|
||||
return atkRoll-defRoll > 0
|
||||
|
||||
class FaceoffDot(Enum):
|
||||
"""All orientations are given from the perspective of the defending team."""
|
||||
AwayZoneLeft = -4
|
||||
AwayZoneRight = -3
|
||||
AwayNeutralLeft = -2
|
||||
AwayNeutralRight = -1
|
||||
Center = 0
|
||||
HomeNeutralRight = 1
|
||||
HomeNeutralLeft = 2
|
||||
HomeZoneRight = 3
|
||||
HomeZoneLeft = 4
|
||||
|
||||
class SkaterPosition(Enum):
|
||||
"""Allows easy indexing to the active skaters lists for each team."""
|
||||
LW = 0
|
||||
LD = 1
|
||||
C = 2
|
||||
RD = 3
|
||||
RW = 4
|
|
@ -1,4 +1,5 @@
|
|||
import skillContests, player, team, game, attributes
|
||||
import skillContests, player, team, game, attributes, os
|
||||
|
||||
|
||||
class AttributeTest(object):
|
||||
def __init__(self):
|
||||
|
|
131
hocUtils.py
Normal file
131
hocUtils.py
Normal file
|
@ -0,0 +1,131 @@
|
|||
import os, itertools
|
||||
import networkx as nx
|
||||
|
||||
class RinkGraph(object):
|
||||
"""Base class for a graph of nodes representing a hockey rink. Description of nodes found in design documents."""
|
||||
G = nx.empty_graph()
|
||||
|
||||
def __init__(self, nodeFilename:str=None, edgeFilename:str=None):
|
||||
if nodeFilename is not None:
|
||||
with open(os.path.join("Rinks","Graphs",nodeFilename)) as nodeFile:
|
||||
nodeListS = [node.strip() for node in nodeFile.readlines()]
|
||||
self.G = nx.empty_graph(create_using=nx.DiGraph)
|
||||
edges = itertools.permutations(nodeListS,2)
|
||||
self.G.add_edges_from(edges)
|
||||
elif edgeFilename is not None:
|
||||
self.G = nx.readwrite.edgelist.read_edgelist(os.path.join("Rinks","Graphs", edgeFilename), create_using=nx.DiGraph)
|
||||
|
||||
def writeGraph(self, writeFilename:str):
|
||||
nx.readwrite.edgelist.write_edgelist(self.G, os.path.join("Rinks","Graphs",writeFilename))
|
||||
|
||||
def nameToZones(self, name:str):
|
||||
column = int(name[1])
|
||||
row = int(name[0])
|
||||
|
||||
def adjacencyRule(self):
|
||||
for node1, node2 in list(self.G.edges):
|
||||
self.G.edges[node1, node2]['actions'] = []
|
||||
if (abs(int(node1[0]) - int(node2[0])) <= 1 and abs(int(node1[1]) - int(node2[1])) <= 0) or (abs(int(node1[0]) - int(node2[0])) <= 0 and abs(int(node1[1]) - int(node2[1])) <= 1):
|
||||
self.G.edges[node1, node2]['adjacent'] = 1
|
||||
elif node1 == "01" and node2 == "10" or node1 == "10" and node2 == "01" or node1 == "06" and node2 == "17" or node1 == "17" and node2 == "06":
|
||||
self.G.edges[node1, node2]['adjacent'] = 1
|
||||
elif node1 == "41" and node2 == "30" or node1 == "30" and node2 == "41" or node1 == "46" and node2 == "37" or node1 == "37" and node2 == "46":
|
||||
self.G.edges[node1, node2]['adjacent'] = 1
|
||||
else:
|
||||
self.G.edges[node1, node2]['adjacent'] = 0
|
||||
|
||||
def backSkateRule(self):
|
||||
for node1, node2 in list(self.G.edges):
|
||||
if node1[1] in ['1','2','3','4','6']:
|
||||
if abs(int(node1[0]) - int(node2[0])) <= 1 and int(node2[1]) == int(node1[1])-1:
|
||||
self.G.edges[node1, node2]['actions'].append('SkateB')
|
||||
|
||||
def forwardSkateRule(self):
|
||||
for node1, node2 in list(self.G.edges):
|
||||
access = False
|
||||
if node1[1] in ['0','1','2']:
|
||||
access = True
|
||||
distance = 2
|
||||
elif node1[1] in ['3','4']:
|
||||
access = True
|
||||
distance = 1
|
||||
|
||||
if access and node2[1] >= node1[1]:
|
||||
atkDistance = int(node2[1]) - int(node1[1])
|
||||
horzDistance = abs(int(node2[0]) - int(node1[0]))
|
||||
if (atkDistance+horzDistance) <= distance:
|
||||
self.G.edges[node1, node2]['actions'].append('SkateF')
|
||||
|
||||
def throughSkateRule(self):
|
||||
for node1, node2 in list(self.G.edges):
|
||||
if node1[1] in ['5','6','7']:
|
||||
if node1[0] not in ['0','4']:
|
||||
if node2 == '26':
|
||||
self.G.edges[node1, node2]['actions'].append('SkateT')
|
||||
else:
|
||||
if node1[0] == '0' and node2 == '16' or node1[0] == '4' and node2 == '36':
|
||||
self.G.edges[node1, node2]['actions'].append('SkateT')
|
||||
|
||||
def aroundSkateRule(self):
|
||||
for node1, node2 in list(self.G.edges):
|
||||
if node1[1] in ['5','6'] and node1[0] != '2' and node2 == '27':
|
||||
self.appendAction(node1, node2, 'SkateA')
|
||||
|
||||
def stretchPassRule(self):
|
||||
for node1, node2 in list(self.G.edges):
|
||||
if node1[1] in ['1','2'] and node2[1] == '5':
|
||||
self.appendAction(node1, node2, "PassS")
|
||||
|
||||
def forwardPassRule(self):
|
||||
for node1, node2 in list(self.G.edges):
|
||||
if node1[1] in ['1','2', '3', '5', '6']:
|
||||
if int(node2[1]) >= int(node1[1]) and int(node2[1]) - int(node1[1]) <= 2:
|
||||
self.appendAction(node1, node2, 'PassF')
|
||||
elif node1[1] == '4' and node2[1] in ['4','5']:
|
||||
self.appendAction(node1, node2, 'PassF')
|
||||
elif node1[1] == '7' and node2[1] in ['5','6']:
|
||||
self.appendAction(node1, node2, 'PassF')
|
||||
|
||||
def backwardPassRule(self):
|
||||
for node1, node2 in list(self.G.edges):
|
||||
if node1[1] not in ['0','5','7']: #back pass from column 7 is treated as forward pass for difficulty
|
||||
if int(node1[1]) - int(node2[1]) == 1 and node1[0] == node2[0]:
|
||||
self.appendAction(node1, node2, 'PassB')
|
||||
|
||||
|
||||
def appendAction(self, node1, node2, actionString):
|
||||
self.G.edges[node1, node2]['actions'].append(actionString)
|
||||
|
||||
|
||||
def allRules(self):
|
||||
self.adjacencyRule()
|
||||
self.backSkateRule()
|
||||
self.forwardSkateRule()
|
||||
self.throughSkateRule()
|
||||
self.aroundSkateRule()
|
||||
self.stretchPassRule()
|
||||
self.forwardPassRule()
|
||||
self.backwardPassRule()
|
||||
self.writeGraph("defaultedges.nx")
|
||||
|
||||
def getAllReachableFrom(self, nodeName):
|
||||
"""Returns a dictionary where the keys are all reachable nodes, and the values are the list of actions that can reach the key node."""
|
||||
if isinstance(nodeName, int):
|
||||
nodeName = str(nodeName)
|
||||
allConnected = dict(self.G[nodeName])
|
||||
possibleReachable = {}
|
||||
for otherNode in allConnected:
|
||||
if allConnected[otherNode]['actions'] != []:
|
||||
possibleReachable[otherNode] = allConnected[otherNode]['actions']
|
||||
return possibleReachable
|
||||
|
||||
def getAdjacentNodes(self, nodeName):
|
||||
"""Returns a list of all nodes marked as adjacent by the current map."""
|
||||
if isinstance(nodeName, int):
|
||||
nodeName = str(nodeName)
|
||||
allConnected = dict(self.G[nodeName])
|
||||
adjacents = []
|
||||
for otherNodeName, nodeDic in allConnected.items():
|
||||
if nodeDic['adjacent']:
|
||||
adjacents.append(otherNodeName)
|
||||
return adjacents
|
Loading…
Reference in a new issue