# -*- coding: utf-8 -*- from random import * import re import os # Program that randomizes position of units # in Battalion Wars "_Level" XML files. # This version only randomizes unit positions, # not objects (except cameras and waypoints). # Each units has 2 attributes that can modify its position: # "spawnMatrix" and "Mat". # They must have exactly the same values. # Objects such as static props, waypoints, etc, only # have the "Mat" attributes. # All this explains some the decisions made in the code. # The values under , itself under the Attribute # (either "spawnMatrix" or "Mat") are most likely: # rot x, rot z (vertical), rot y, unknown_flag, # unknown_flag, unknown_flag, unknown_flag, unknown_flag, # unknown value, unknown value, unknown value, unknown value, # pos x, pos z (vertical), pos y, unknown flag # NOTE AND WARNING: messing up too much with # the rotation values will mess up the game's graphics. # Not 100% sure, but I think rotation values # must be kept between -1 and 0. # Below: function to add zeroes in case numbers are low # (maybe to be deleted later if it causes unforseen issues # in the XML files. def add_zeroes(random_int): if random_int < 100 and random_int > 9: random_int = "0"+str(random_int) return str(random_int) elif random_int < 10 and random_int > 0: random_int = "00"+str(random_int) return str(random_int) else: return str(random_int) # Below: main function randomzing position x and y # of units and objects def randomize(f): print("Working on: ",f) xml_file = open(f,"r", encoding="utf-8") #f_name_xml = re.sub('(.+)\.xml','\g<1>_randomized.xml',f) f_name_xml = re.sub('(.+)\.xml','./randomized/\g<1>.xml',f) randomized_xml_file = open(f_name_xml,"w+", encoding="utf-8") counter_changed = 0 counter_unchanged = 0 prevLine = "" # Above: important to be able to read previous line pos_x_preserved = "" pos_y_preserved = "" pos_z_preserved = "" # Above: to allow "Mat" to get the same values as # "spawnMatrix" both_spawnmatrix_and_mat_present = True is_unit = False is_camera = False is_waypoint = False # Below: max and min random values here # so it's easier to change all the # values at once # Note: since z is vertical, it's best not # to go into negative numbers. Also, it's # best to keep the value relatively small, # or else the game can crash. if f == "C1_OnPatrol_Level.xml": RANDOM_INT_MIN_X = 440 RANDOM_INT_MAX_X = 710 RANDOM_INT_MIN_Y = 0 RANDOM_INT_MAX_Y = 300 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C1_WarThaw_Level.xml": RANDOM_INT_MIN_X = -790 RANDOM_INT_MAX_X = -344 RANDOM_INT_MIN_Y = -1292 RANDOM_INT_MAX_Y = -286 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C1_WindbreakRidge_Level.xml": RANDOM_INT_MIN_X = -198 RANDOM_INT_MAX_X = 250 RANDOM_INT_MIN_Y = -261 RANDOM_INT_MAX_Y = 0 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C1_PlanOfAttack_Level.xml": RANDOM_INT_MIN_X = 350 RANDOM_INT_MAX_X = 700 RANDOM_INT_MIN_Y = 70 RANDOM_INT_MAX_Y = 350 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C1_SOSandMASH_Level.xml": RANDOM_INT_MIN_X = -500 RANDOM_INT_MAX_X = 62 RANDOM_INT_MIN_Y = -300 RANDOM_INT_MAX_Y = 90 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C1_Gauntlet_Level.xml": RANDOM_INT_MIN_X = -315 RANDOM_INT_MAX_X = 250 RANDOM_INT_MIN_Y = -560 RANDOM_INT_MAX_Y = 735 RANDOM_INT_MIN_Z = 150 RANDOM_INT_MAX_Z = 200 elif f == "C1_Tanktics_Level.xml": RANDOM_INT_MIN_X = -200 RANDOM_INT_MAX_X = 230 RANDOM_INT_MIN_Y = -200 RANDOM_INT_MAX_Y = 230 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C1_Bonus_Level.xml": RANDOM_INT_MIN_X = -200 RANDOM_INT_MAX_X = 230 RANDOM_INT_MIN_Y = -200 RANDOM_INT_MAX_Y = 230 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C2_Beachhead_Level.xml": RANDOM_INT_MIN_X = -20 RANDOM_INT_MAX_X = 190 RANDOM_INT_MIN_Y = -46 RANDOM_INT_MAX_Y = 414 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C2_Exodus_Level.xml": RANDOM_INT_MIN_X = -700 RANDOM_INT_MAX_X = 0 RANDOM_INT_MIN_Y = -600 RANDOM_INT_MAX_Y = 100 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C2_BonusInvasion_Level.xml": RANDOM_INT_MIN_X = -700 RANDOM_INT_MAX_X = 0 RANDOM_INT_MIN_Y = -600 RANDOM_INT_MAX_Y = 100 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C2_GunshipsOfTheDesert_Level.xml": RANDOM_INT_MIN_X = -340 RANDOM_INT_MAX_X = 444 RANDOM_INT_MIN_Y = -620 RANDOM_INT_MAX_Y = -150 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C2_BlackGold_Level.xml": RANDOM_INT_MIN_X = -600 RANDOM_INT_MAX_X = 317 RANDOM_INT_MIN_Y = -600 RANDOM_INT_MAX_Y = 730 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C3_XDay_Level.xml": RANDOM_INT_MIN_X = -430 RANDOM_INT_MAX_X = 114 RANDOM_INT_MIN_Y = -830 RANDOM_INT_MAX_Y = -30 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C3_CrackSquad_Level.xml": RANDOM_INT_MIN_X = -228 RANDOM_INT_MAX_X = 400 RANDOM_INT_MIN_Y = -404 RANDOM_INT_MAX_Y = 200 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C3_DomesticBlitz_Level.xml": RANDOM_INT_MIN_X = -350 RANDOM_INT_MAX_X = 324 RANDOM_INT_MIN_Y = 524 RANDOM_INT_MAX_Y = 1226 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C3_HeavyFirepower_Level.xml": RANDOM_INT_MIN_X = -400 RANDOM_INT_MAX_X = 370 RANDOM_INT_MIN_Y = -400 RANDOM_INT_MAX_Y = -370 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C3_PassThePort_Level.xml": RANDOM_INT_MIN_X = -544 RANDOM_INT_MAX_X = 562 RANDOM_INT_MIN_Y = -630 RANDOM_INT_MAX_Y = 400 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C3_Bonus_Level.xml": RANDOM_INT_MIN_X = -400 RANDOM_INT_MAX_X = 370 RANDOM_INT_MIN_Y = -400 RANDOM_INT_MAX_Y = -370 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C4_Bridges_on_the_River_Styx_Level.xml": RANDOM_INT_MIN_X = -160 RANDOM_INT_MAX_X = 246 RANDOM_INT_MIN_Y = -400 RANDOM_INT_MAX_Y = 662 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C4_RoadToXylvania_Level.xml": RANDOM_INT_MIN_X = -933 RANDOM_INT_MAX_X = -190 RANDOM_INT_MIN_Y = -912 RANDOM_INT_MAX_Y = 453 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C4_UnknownSoldiers_Level.xml": RANDOM_INT_MIN_X = -380 RANDOM_INT_MAX_X = 220 RANDOM_INT_MIN_Y = -350 RANDOM_INT_MAX_Y = -220 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C4_Siege_of_the_Vladstag_Level.xml": RANDOM_INT_MIN_X = -280 RANDOM_INT_MAX_X = 224 RANDOM_INT_MIN_Y = -634 RANDOM_INT_MAX_Y = 490 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 elif f == "C4_Bonus_Level.xml": RANDOM_INT_MIN_X = -928 RANDOM_INT_MAX_X = -528 RANDOM_INT_MIN_Y = -869 RANDOM_INT_MAX_Y = 43 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 else: RANDOM_INT_MIN_X = 0 RANDOM_INT_MAX_X = 125 RANDOM_INT_MIN_Y = 0 RANDOM_INT_MAX_Y = 125 RANDOM_INT_MIN_Z = 60 RANDOM_INT_MAX_Z = 90 # Below: name of objects whose position will change: will_change_1 = ' '): # line above: check the previous line both_spawnmatrix_and_mat_present = True # lin above: if spawnMatrix is present, then # both spawnMatrix AND Mat are present, mandatorily pos_x = add_zeroes(randint(RANDOM_INT_MIN_X,RANDOM_INT_MAX_X)) pos_y = add_zeroes(randint(RANDOM_INT_MIN_Y,RANDOM_INT_MAX_Y)) #pos_z = add_zeroes(randint(RANDOM_INT_MIN_Z,RANDOM_INT_MAX_Z)) new_item_line = "\t\t\t1,1,1,1, 1,1,1,1, 1,1,1,1,"+pos_x+",75,"+pos_y+",1" line = new_item_line randomized_xml_file.write(line) counter_changed = counter_changed + 1 pos_x_preserved = pos_x pos_y_preserved = pos_y #pos_z_preserved = pos_z elif (is_unit == True or is_camera == True or is_waypoint == True) and prevLine.startswith(' '): # line above: changes the "Mat" attribute # so it has the same value as the "spawnMatrix" attribute # (hence the "preserved" values below) if both_spawnmatrix_and_mat_present == True: pos_x = pos_x_preserved pos_y = pos_y_preserved pos_z = pos_z_preserved if pos_x == "": pos_x = add_zeroes(randint(RANDOM_INT_MIN_X,RANDOM_INT_MAX_X)) if pos_y == "": pos_y = add_zeroes(randint(RANDOM_INT_MIN_Y,RANDOM_INT_MAX_Y)) if pos_z == "": pos_z = add_zeroes(randint(RANDOM_INT_MIN_Z,RANDOM_INT_MAX_Z)) new_item_line = "\t\t\t1,1,1,1, 1,1,1,1, 1,1,1,1,"+pos_x+",75,"+pos_y+",1" line = new_item_line elif is_camera == True or is_waypoint == True: pos_x = add_zeroes(randint(RANDOM_INT_MIN_X,RANDOM_INT_MAX_X)) pos_y = add_zeroes(randint(RANDOM_INT_MIN_Y,RANDOM_INT_MAX_Y)) pos_z = add_zeroes(randint(RANDOM_INT_MIN_Z,RANDOM_INT_MAX_Z)) new_item_line = "\t\t\t1,1,1,1, 1,1,1,1, 1,1,1,1,"+pos_x+","+pos_z+","+pos_y+",1" line = new_item_line both_spawnmatrix_and_mat_present = False # re-defaults to false is_camera = False is_waypoint = False randomized_xml_file.write(line) counter_changed = counter_changed + 1 else: randomized_xml_file.write(line) counter_unchanged = counter_unchanged + 1 prevLine = line print("Number of lines changed: "+str(counter_changed)) print("Number of lines unchanged: "+str(counter_unchanged)) print("Total: "+str(counter_changed+counter_unchanged)) print("File done, jumping to the next") xml_file.close() randomized_xml_file.close() try: os.mkdir("randomized") except OSError: print ("Creation of the directory %s failed, maybe it already exists?" % "randomized") else: print ("Successfully created the directory %s " % "randomized") for file in os.listdir('.'): if re.match('.+\_Level.xml', file): randomize(file) end = input("done. press enter to quit")