From ce3fda26384096cb20f95af7f12d6f8ed5e66057 Mon Sep 17 00:00:00 2001 From: Sakimori Date: Thu, 15 Aug 2024 14:20:08 -0400 Subject: [PATCH] implemented random action selection --- game.py | 8 +++---- hocUtils.py | 12 ++++++++++ player.py | 57 +++++++++++++++++++++++------------------------- skillContests.py | 25 +++++++++++++++++---- 4 files changed, 64 insertions(+), 38 deletions(-) diff --git a/game.py b/game.py index b03b0d6..900ebc4 100644 --- a/game.py +++ b/game.py @@ -1,7 +1,7 @@ import random, team, player, os, math from team import Team -from player import Player, AtkAction, DefAction, Skater, Goalie -from skillContests import SkillContestParams, Situations +from player import Player, Skater, Goalie +from skillContests import SkillContestParams, Situations, AtkAction, DefAction from attributes import normalDis from hocUtils import RinkGraph from enum import Enum @@ -219,8 +219,8 @@ class Game(object): defender = self.defendingSkater() #reroll until eligible defender found self.ineligibleDefenders = [] #clear ineligible defs - atkAction, nodeTarget = attacker.chooseAtkAction(validActions, defender) - defAction = defender.chooseDefAction() + atkAction, nodeTarget = attacker.chooseAtkAction(validActions, self.currentZone, self.activeGraph(), defender) + defAction = defender.chooseDefAction(self.currentZone, self.activeGraph()) scParams = SkillContestParams().actionCheck(atkAction, defAction, self.currentSituation()) result = self.skillContest(attacker, defender, scParams) diff --git a/hocUtils.py b/hocUtils.py index 4b47690..af1aa51 100644 --- a/hocUtils.py +++ b/hocUtils.py @@ -1,6 +1,8 @@ import os, itertools import networkx as nx +from skillContests import DefAction + 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() @@ -129,6 +131,16 @@ class RinkGraph(object): if nodeDic['adjacent']: adjacents.append(otherNodeName) return adjacents + + def getPossibleDefensiveActions(self, nodeName): + if isinstance(nodeName, int): + nodeName = str(nodeName) + actions = [DefAction.Steal, DefAction.Poke, DefAction.BlockLn, DefAction.Body, DefAction.Force] + if int(nodeName) < 10 or int(nodeName) > 40 or int(nodeName[1]) == 0 or int(nodeName[1]) == 7: #on wall + actions.append(DefAction.Pin) + if int(nodeName[1]) >= 5: #in defensive end + actions.append(DefAction.BlockSlot) + return actions 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""" diff --git a/player.py b/player.py index 46bf6b3..c4095d1 100644 --- a/player.py +++ b/player.py @@ -1,5 +1,7 @@ import attributes from enum import Enum +from random import sample +from skillContests import AtkAction, DefAction, SkillContestParams class CreationError(Exception): pass @@ -49,6 +51,10 @@ class Player(object): if attr.name.lower().startswith(shortname.lower()): return attr return None + + def getAttributes(self): + """Returns a list of all Attributes.""" + return self.attributes def setAttribute(self, shortname:str, value:float): for attr in self.attributes: @@ -78,16 +84,29 @@ class Player(object): outString = f"{self.name[:3]}." return outString - def predictOpposingAction(self, opposingSkater): + def predictOpposingAction(self, opposingSkater, graph, currentNode): + oppAttributes = opposingSkater.getAttributes() + #TODO: Fuzzy opponent attributes based on wisdom + return self.chooseDefAction(statsOverride=oppAttributes) raise NotImplementedError() - def chooseAtkAction(self, actionDic, opposingSkater): - """Picks an action/target node combo.""" - predAction = self.predictOpposingAction(opposingSkater) - raise NotImplementedError() + def chooseAtkAction(self, actionDic, currentNode, graph, opposingSkater): + """TODO: Make actual AI. Picks an action/target node combo.""" + predAction = self.predictOpposingAction(opposingSkater, graph, currentNode) + targetNode = sample(actionDic.keys(),1)[0] #random target node + action = AtkAction[sample(actionDic[targetNode],1)[0]] + ovr = SkillContestParams().actionCheck(action,predAction).override + while ovr is not None and ovr is False: #don't pick an autofail + targetNode = sample(actionDic.keys(),1)[0] #random target node + action = sample(actionDic[targetNode],1)[0] + ovr = SkillContestParams().actionCheck(action,predAction).override + return (action, targetNode) - def chooseDefAction(self): - raise NotImplementedError() + def chooseDefAction(self, currentNode, graph, statsOverride = None): + """TODO: Make actual AI. Returns random possible defensive action.""" + attrs = self.attributes if statsOverride is None else statsOverride + possibleActions = graph.getPossibleDefensiveActions(currentNode) + return sample(possibleActions,1)[0] class Skater(Player): """A hockey player that is not a goalie.""" @@ -96,26 +115,4 @@ class Skater(Player): class Goalie(Player): """A hockey player that *is* a goalie.""" - pass - - -class AtkAction(Enum): - SkateB = 0 - SkateF = 1 - SkateT = 2 - SkateA = 3 - PassS = 4 - PassF = 5 - PassB = 6 - Dump = 7 - ShotS = 8 - ShotW = 9 - -class DefAction(Enum): - Steal = 0 - Poke = 1 - BlockLn = 2 - Body = 3 - Force = 4 - Pin = 5 - BlockSlot = 6 \ No newline at end of file + pass \ No newline at end of file diff --git a/skillContests.py b/skillContests.py index cbb185c..6f7b798 100644 --- a/skillContests.py +++ b/skillContests.py @@ -1,4 +1,3 @@ -from player import AtkAction, DefAction from enum import Enum class Situations(Enum): @@ -7,6 +6,27 @@ class Situations(Enum): PP2 = 2 #5v3 or 6v4 SH1 = -1 #3v4, 4v5, 5v6 SH2 = -2 #3v5 or 4v6 + +class AtkAction(Enum): + SkateB = 0 + SkateF = 1 + SkateT = 2 + SkateA = 3 + PassS = 4 + PassF = 5 + PassB = 6 + Dump = 7 + ShotS = 8 + ShotW = 9 + +class DefAction(Enum): + Steal = 0 + Poke = 1 + BlockLn = 2 + Body = 3 + Force = 4 + Pin = 5 + BlockSlot = 6 class SkillContestParams(object): """Basic structure for contests of skill.""" @@ -28,9 +48,6 @@ class SkillContestParams(object): self.atkStats = result[0] self.defStats = result[1] - - - #Bool overrides, or [List of (stat,weight) , List of (stat,weight)] evenTable = [ #Steal #Poke #block lane #Body check #Force off puck #Pin to wall #Body block