def test_map_selection():
    """verify the functionality of selectMap()"""
    for i in range(100): # without any params, a single map should always selected
        assert isinstance(selectMap(), MapRecord)
    casesInclusion = [
        # INPUT TEST CASE   EXPECTED RESULT
        ("zerg",            ["DefeatZerglingsAndBanelings", "FindAndDefeatZerglings"]),
        ("AndBane",         ["DefeatZerglingsAndBanelings"]),
        ("e[ar].*r$",       ["Dreamcatcher", "Interloper"]), #accepts regular expression
        ("^b.*a.*k$",       ["BattleOnTheBoardwalk", "Blackpink", "Blackpink"]),
        ("q",               ["Sequencer", "NeonVioletSquare", "NeonVioletSquare"]), # identifies multiple results for their unique paths
        ("^x",              Exception), # none of the maps start with an 'x'
        ("^abi",            ["Abiogenesis"]),
        ("[ui][rt]e$",      ["Fracture", "Parasite"]),
        (".{1}[^o]nt",      ["AcidPlant", "AcidPlant", "AcidPlant", "LastRemnant", "LastRemnant"]),
    ]
    casesExclusion = [
        # INPUT TEST CASE   EXPECTED RESULT
        ("[\w]",            Exception), # if ignoring all valid chars, error!
        ("[aeiou]",         Exception), # all maps have a vowel
        ("[diyt]",          ["Sequencer", "CeruleanFall"]), # all maps without an a, i or y
        ("[qtyhdjm1649]",   ["Abiogenesis", "Blackpink", "Blackpink", "CeruleanFall"]),
        ("^[^u]",           ["Ujari", "Ujari"]),
        ("[acdeghjklmny]",  ["Frost", "16Bit"]),
    ]
    def iterCases(cases, exclusion):
        for thisInput, thisExpect in cases:
            try:    mapResults = selectMap(name=thisInput, excludeName=exclusion, closestMatch=False)
            except:
                display_test(thisInput, Exception, thisExpect)
                continue
            print(">>", mapResults)
            for m in mapResults:
                display_test("%s in %s"%(m.name, thisExpect), m.name in thisExpect, True)
            display_test(thisInput, len(mapResults), len(thisExpect))
    iterCases(casesInclusion, False)
    iterCases(casesExclusion, True)
    newMap = selectMap(year=2018, season=1) # get exactly one map
    assert not isinstance(newMap, list)
    try:    assert selectMap(year=1970) and False
    except: assert True # bad attrs causes an exception
    try:    assert selectMap("z", mode="1v1", year=2018, season=2) and False
    except: assert True # force attribute selection AND bad name filtering resuling in no matches
    try:    assert selectMap("[\w]", excludeName="ujari", closestMatch=True, ladder=True) and False
    except: assert True
def test_match_attrs():
    boardwalk = selectMap("boardwalk")
    assert False == f.matchRecordAttrs(boardwalk, {"asdjfd":True})
    assert True  == f.matchRecordAttrs(boardwalk, {"asdjfd":None})
    assert True  == f.matchRecordAttrs(boardwalk, {"asdjfd":""})
    assert True  == f.matchRecordAttrs(boardwalk, {"asdjfd":0})
    assert True  == f.matchRecordAttrs(boardwalk, {"asdjfd":False})
    assert False == f.matchRecordAttrs(boardwalk, {"year":2016})
    assert True  == f.matchRecordAttrs(boardwalk, {"year":2017})
    assert True  == f.matchRecordAttrs(boardwalk, {})
 def iterCases(cases, exclusion):
     for thisInput, thisExpect in cases:
         try:    mapResults = selectMap(name=thisInput, excludeName=exclusion, closestMatch=False)
         except:
             display_test(thisInput, Exception, thisExpect)
             continue
         print(">>", mapResults)
         for m in mapResults:
             display_test("%s in %s"%(m.name, thisExpect), m.name in thisExpect, True)
         display_test(thisInput, len(mapResults), len(thisExpect))
def test_simple():
    for m in selectMap(name="oi", season=1, excludeName=True, closestMatch=False):
        assert isinstance(m, MapRecord)
        assert isinstance(m.rawData, bytes) # requires real paths
Example #5
0
def main(options=None):
    if options == None:  # if not provided, assume options are provided via command line
        parser = optionsParser()
        options = parser.parse_args()
        sys.argv = sys.argv[:
                            1]  # remove all arguments to avoid problems with absl FLAGS :(
    try:
        specifiedMap = selectMap(
            options.mapname,
            excludeName=options.exclude,
            closestMatch=True,  # force selection of at most one map
            **getSelectionParams(options))
    except Exception as e:
        print(e)
        return
    outTempName = specifiedMap.name + "_%d_%d." + c.SC2_REPLAY_EXT
    outTemplate = os.path.join(options.replaydir, outTempName)
    if options.editor:
        bankFile = getBankFilepath(specifiedMap.name)
        if os.path.isfile(bankFile):  # this map has saved previous scenarios
            bankName = re.sub("\..*?$", "", os.path.basename(bankFile))
            bankDir = os.path.dirname(bankFile)
            dirTime = re.sub("\.", "_", str(time.time()))
            tmpDir = os.path.join(bankDir, "%s_%s" % (bankName, dirTime))
            tmpXml = os.path.join(tmpDir, c.FILE_BANKLIST)
            tmpName = "%s.%s" % (bankName, c.SC2_MAP_EXT)
            tmpMapPath = os.path.join(tmpDir, tmpName)
            cfg = Config()
            dstMapDir = cfg.installedApp.mapsDir
            dstMapPath = os.path.join(dstMapDir, tmpName)
            if os.path.isdir(tmpDir):
                shutil.rmtree(tmpDir)
            try:
                os.makedirs(tmpDir)
                shutil.copyfile(
                    specifiedMap.path,
                    tmpMapPath)  # copy the original map file for modification
                with open(tmpXml, "w") as f:  # generate temporary xml data
                    f.write(c.BANK_DATA % bankName)
                if cfg.is64bit: mpqApp = c.PATH_MPQ_EDITOR_64BIT
                else: mpqApp = c.PATH_MPQ_EDITOR_32BIT
                cmd = c.MPQ_CMD % (mpqApp, tmpMapPath, tmpXml, c.FILE_BANKLIST)
                x = subprocess.call(
                    cmd)  # modify a temporary mapfile using the mpq editor
                print("Loaded previously defined %s scenarios." % (bankName))
                if os.path.isfile(
                        dstMapPath
                ):  # always ensure the destination mapfile is the modified version
                    os.remove(dstMapPath)
                shutil.copyfile(
                    tmpMapPath, dstMapPath
                )  # relocate the temporary map file into the maps folder
                tmpRecord = MapRecord(specifiedMap.name, dstMapPath, {})
                launchEditor(
                    tmpRecord
                )  # launch the editor using a temporary, modified map that includes the previously defined SC2Bank scenario data
            finally:
                time.sleep(
                    options.cleandelay
                )  # wait for the editor to launch before removing temporary files
                if os.path.isdir(
                        tmpDir
                ):  # always remove the temporary map and XML files
                    shutil.rmtree(tmpDir)
                while True:
                    try:
                        os.remove(dstMapPath
                                  )  # always remove the temporary map mpq file
                        break
                    except:
                        time.sleep(
                            2
                        )  # continue trying until the editor closes and the deletion is successful
        else:
            launchEditor(
                specifiedMap)  # run the editor using the game modification
    elif options.regression:
        batteries = options.test.split(",")
        raise NotImplementedError("TODO -- run each test battery")
    elif options.custom:
        playerNames = re.split("[,\s]+", options.players)
        if len(playerNames) != 2:  # must specify two players for 1v1
            if not options.players:
                playerNames = ""
            raise ValueError("must specify two players, but given %d: '%s'" %
                             (len(playerNames), playerNames))
        try:
            thisPlayer = getPlayer(
                playerNames[0]
            )  # player name stated first is expected to be this player
        except Exception:
            print("ERROR: player '%s' is not known" % playerNames[0])
            return
        if options.race == c.RANDOM:
            options.race = thisPlayer.raceDefault  # defer to a player's specified default race
        cfg = Config(
            themap=specifiedMap,
            ladder=getLadder("versentiedge"),
            players=[
                PlayerPreGame(thisPlayer,
                              selectedRace=c.types.SelectRaces(options.race))
            ],
            mode=c.types.GameModes(c.MODE_1V1),
            opponents=playerNames[1:],
            whichPlayer=thisPlayer.name,
            fogDisabled=
            True,  # disable fog to be able to see, set and remove enemy units
            **
            thisPlayer.initOptions,  # ensure desired data is sent in callback
        )
        cfg.raw = True  # required to be able to set up units using debug commands
        #cfg.display()
        scenarios = getSetup(specifiedMap, options, cfg)
        for scenario in scenarios:
            epoch = int(time.time(
            ))  # used for replay differentiation between each scenario
            failure = False
            for curLoop in range(
                    1, options.repeat + 1
            ):  # each loop of each scenario gets its own unique replay (count starting at one)
                outFile = outTemplate % (epoch, curLoop)
                launchOpts = defineLaunchOptions(scenario, outFile)
                failure = launcher.run(launchOpts, cfg=cfg)
                if failure: break
            if failure: break
    elif options.join:
        raise NotImplementedError("TODO -- implement remote play")
    else:
        parser.print_help()
        print("ERROR: must select a main option.")
Example #6
0
def test_simple():
    for m in selectMap(name="flat",
                       melee=True,
                       excludeName=True,
                       closestMatch=False):
        assert isinstance(m, MapRecord)
Example #7
0
def run(debug=False):
    """PURPOSE: start a starcraft2 process using the defined the config parameters"""
    FLAGS(sys.argv)
    config = gameConfig.Config(
        version=
        None,  # vers is None... unless a specific game version is desired
        themap=selectMap(ladder=True),  # pick a random ladder map
        players=["defaulthuman", "blizzbot2_easy"],
    )
    createReq = sc_pb.RequestCreateGame(  # used to advance to "Init Game" state, when hosting
        realtime=config.realtime,
        disable_fog=config.fogDisabled,
        random_seed=int(now(
        )),  # a game is created using the current second timestamp as the seed
        local_map=sc_pb.LocalMap(map_path=config.mapLocalPath,
                                 map_data=config.mapData))
    joinRace = None
    for player in config.players:
        reqPlayer = createReq.player_setup.add(
        )  # add new player; get link to settings
        playerObj = PlayerPreGame(player)
        if playerObj.isComputer:
            reqPlayer.difficulty = playerObj.difficulty.gameValue()
            pType = playerObj.type.type
        else:
            pType = c.PARTICIPANT
        reqPlayer.type = t.PlayerControls(pType).gameValue()
        reqPlayer.race = playerObj.selectedRace.gameValue()
        if not playerObj.isComputer:
            joinRace = reqPlayer.race
    interface = sc_pb.InterfaceOptions()
    raw, score, feature, rendered = config.interfaces
    interface.raw = raw  # whether raw data is reported in observations
    interface.score = score  # whether score data is reported in observations
    interface.feature_layer.width = 24
    joinReq = sc_pb.RequestJoinGame(
        options=interface)  # SC2APIProtocol.RequestJoinGame
    joinReq.race = joinRace  # update joinGame request as necessary
    if debug: print("Starcraft2 game process is launching.")
    controller = None
    with config.launchApp() as controller:
        try:
            if debug:
                print("Starcraft2 application is live. (%s)" %
                      (controller.status))  # status: launched
            controller.create_game(createReq)
            if debug:
                print(
                    "Starcraft2 is waiting for %d player(s) to join. (%s)" %
                    (config.numAgents, controller.status))  # status: init_game
            playerID = controller.join_game(
                joinReq).player_id  # SC2APIProtocol.RequestJoinGame
            print("[GET IN-GAME DATA] player#%d %s" % (playerID, config))
            return (controller.ping(), controller.data())
        except (protocol.ConnectionError, protocol.ProtocolError,
                remote_controller.RequestError) as e:
            if debug:
                print("%s Connection to game closed (NOT a bug)%s%s" %
                      (type(e), os.linesep, e))
            else:
                print("Connection to game closed.")
        except KeyboardInterrupt:
            print(
                "caught command to forcibly shutdown Starcraft2 host server.")
        finally:
            config.disable(
            )  # if the saved cfg file still exists, always remove it
            controller.quit()  # force the sc2 application to close