Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion PCG/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Run this command to get a PCG (Procedural Content Generation) generated map:

```bash
cd PCG
python pcg.py --width 16 --height 16
python pcg.py --width 16 --height 16 --num-maps 200
```

Such a command would generate a map at `maps/filename.xml`. You may use microrts's GUI editor at `gym_microrts/microrts/src/gui/frontend/FrontEnd.java` to visualize the map.
Expand Down
15 changes: 0 additions & 15 deletions PCG/maps/wall-1

This file was deleted.

76 changes: 61 additions & 15 deletions PCG/pcg.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import argparse
import os
import random
import time
import xml.etree.cElementTree as ET


Expand All @@ -8,34 +10,53 @@ def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument('--width', type=int, default=16,help='the width of the map')
parser.add_argument('--height', type=int, default=16,help='the height of the map')

parser.add_argument('--num-maps', type=int, default=200, help='the number of the maps to generate')
parser.add_argument('--seed', type=int, default=1,
help='seed of the experiment')
parser.add_argument('--wall-rings-vary', type=bool, default=False, help='the switch to turn on varying wall rings')
args = parser.parse_args()
# fmt: on

if not args.seed:
args.seed = int(time.time())
return args


class PCG:
def __init__(
self, width=16, height=16, key=15, unit_location_records=[], sections_choices=[0, 1, 2, 3], base_location_records=[]
self,
width=16,
height=16,
key=15,
unit_location_records=[],
sections_choices=[0, 1, 2, 3],
base_location_records=[],
num_maps=200,
wall_rings_vary=False,
):
self.height = height
self.width = width
self.wall_rings_vary = wall_rings_vary
self.wallRingsLimit = min(height, width) // 2 - 3
if self.wallRingsLimit < 0:
self.wallRingsLimit = 0
self.wallRings = random.randint(0, self.wallRingsLimit)
if self.wall_rings_vary:
self.wall_rings = random.randint(0, self.wallRingsLimit)
else:
self.wall_rings = 0
self.key = key
self.sections = [
((self.wallRings, (width - 1) // 2), (self.wallRings, (height - 1) // 2)),
((width // 2, (width - 1) - self.wallRings), (self.wallRings, (height - 1) // 2)),
((self.wallRings, (width - 1) // 2), (height // 2, (height - 1) - self.wallRings)),
((width // 2, (width - 1) - self.wallRings), (height // 2, (height - 1) - self.wallRings)),
((self.wall_rings, (width - 1) // 2), (self.wall_rings, (height - 1) // 2)),
((width // 2, (width - 1) - self.wall_rings), (self.wall_rings, (height - 1) // 2)),
((self.wall_rings, (width - 1) // 2), (height // 2, (height - 1) - self.wall_rings)),
((width // 2, (width - 1) - self.wall_rings), (height // 2, (height - 1) - self.wall_rings)),
]
self.unit_location_records = unit_location_records
self.sections_choices = sections_choices
self.base_location_records = base_location_records
self.num_maps = num_maps

def initiate_terrain(self, root, tag, wallRings):
def initiate_terrain(self, root, tag, wall_rings):
terrain = ET.SubElement(root, tag)
eText = ""

Expand All @@ -48,10 +69,10 @@ def get_obstacle():

for y in range(self.height):
for x in range(self.width):
if y in range(0, wallRings) or y in range(self.height - wallRings, self.height):
if y in range(0, wall_rings) or y in range(self.height - wall_rings, self.height):
eText += "1"
self.unit_location_records.append((x, y))
elif x in range(0, wallRings) or x in range(self.height - wallRings, self.height):
elif x in range(0, wall_rings) or x in range(self.height - wall_rings, self.height):
eText += "1"
self.unit_location_records.append((x, y))
else:
Expand Down Expand Up @@ -144,17 +165,42 @@ def get_xy(self, index):
self.unit_location_records.append((x, y))
return x, y

def get_map(self):
def get_map(self, mapKey):
root = ET.Element("rts.PhysicalGameState", width=str(self.width), height=str(self.height))
self.initiate_terrain(root, "terrain", self.wallRings)
self.initiate_terrain(root, "terrain", self.wall_rings)
self.initiate_players(root, "players")
self.initiate_units(root, "units")
tree = ET.ElementTree(root)
tree.write("./maps/filename.xml")
tree.write(os.path.join("PCG/maps/", "pcg_map" + "_" + str(mapKey) + ".xml"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the output directory should be configurable (not hard coded like this).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what kind of configurable output directory you are expecting?

self.reset()

return tree

def reset(self):
self.unit_location_records = []
self.base_location_records = []
self.reset_wall_rings()

def reset_wall_rings(self):
if not self.wall_rings_vary:
return
self.wall_rings = random.randint(0, self.wallRingsLimit)
self.sections = [
((self.wall_rings, (self.width - 1) // 2), (self.wall_rings, (self.height - 1) // 2)),
((self.width // 2, (self.width - 1) - self.wall_rings), (self.wall_rings, (self.height - 1) // 2)),
((self.wall_rings, (self.width - 1) // 2), (self.height // 2, (self.height - 1) - self.wall_rings)),
((self.width // 2, (self.width - 1) - self.wall_rings), (self.height // 2, (self.height - 1) - self.wall_rings)),
]

def get_maps(self):
for i in range(self.num_maps):
self.get_map(i)


if __name__ == "__main__":
if not os.path.exists("PCG/maps"):
os.makedirs("PCG/maps")
args = parse_args()
pcg = PCG(width=args.width, height=args.height)
pcg.get_map()
random.seed(args.seed)
pcg = PCG(width=args.width, height=args.height, num_maps=args.num_maps, wall_rings_vary=args.wall_rings_vary)
pcg.get_maps()
4 changes: 3 additions & 1 deletion gym_microrts/envs/vec_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from PIL import Image

import gym_microrts
import PCG


class MicroRTSGridModeVecEnv:
Expand Down Expand Up @@ -59,7 +60,8 @@ def __init__(
self.microrts_path = os.path.join(gym_microrts.__path__[0], "microrts")

# prepare training maps
self.cycle_maps = list(map(lambda i: os.path.join(self.microrts_path, i), cycle_maps))
self.pcg_map_path = os.path.join(PCG.__path__[0], "maps")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This input PCG map path should be configurable.

self.cycle_maps = list(map(lambda i: os.path.join(self.pcg_map_path, i), cycle_maps))
self.next_map = cycle(self.cycle_maps)

# read map
Expand Down