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
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.")
def test_simple(): for m in selectMap(name="flat", melee=True, excludeName=True, closestMatch=False): assert isinstance(m, MapRecord)
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