예제 #1
0
def findhubs(wadname):
    wad = omg.WAD(wadname)

    mapexits = {}

    for mapname, mapinfo in wad.maps.items():
        mapexits[mapname] = find_exits(
            mapinfo["LINEDEFS"].data, mapinfo["BEHAVIOR"].data
        )

    mapenters = defaultdict(set)

    print("Map  : Exits to")
    for mapname, exits in sorted(mapexits.items()):
        for exit in exits:
            mapenters[exit].add(mapname)
        s = ", ".join(str(i) for i in exits)
        print(f"{mapname}: {s}")

    mapenters = {k: sorted(v) for k, v in mapenters.items()}

    print("Map  : Comes from")
    for mapname, entries in sorted(mapenters.items()):
        s = ", ".join(str(i) for i in entries)
        print(f"{mapname}: {s}")

    # TODO: Convert mapexits into hub/spoke graph
    with open(f"{wadname}.pickle", "wb") as f:
        pickle.dump((mapexits, mapenters), f)

    return 0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--input', help='input wad file to process')
    parser.add_argument(
        '--mode',
        choices=['train', 'test'],
        help='what those maps are going to be used for: train or test?')
    parser.add_argument('--num_maps',
                        type=int,
                        default=10,
                        help='Number of the mazes to generate.')

    args = parser.parse_args()
    in_file = args.input
    out_file = in_file[:-4]
    wad = omg.WAD(in_file)

    if args.mode == 'test':
        textures = get_textures(TEST_TEXTURES_PATH)
    else:
        global FLOOR_TEXTURE, CEILING_TEXTURE
        FLOOR_TEXTURE, CEILING_TEXTURE = ['MFLR8_1'], ['MFLR8_1']
        textures = get_textures(TRAIN_TEXTURES_PATH)

    for index in range(args.num_maps):
        print(index)
        wad.maps['MAP01'] = change_textures(wad.maps['MAP01'], textures)
        wad.to_file(out_file + '_{}_{}.wad'.format(args.mode, index))
예제 #3
0
def copy_resources():
    for src_file in RES_FILES:
        # don't copy texture lumps for files that aren't present
        if src_file.startswith('textures.doom1') and not get_wad_filename('doom'):
            continue
        elif src_file == 'textures.doom2' and not get_wad_filename('doom2'):
            # DO copy if final doom exists and doom2 doesn't
            if not get_wad_filename('tnt'):
                continue
        elif src_file == 'textures.tnt' and not get_wad_filename('tnt'):
            continue
        elif src_file == 'textures.plut' and not get_wad_filename('plutonia'):
            continue
        logg('Copying %s' % src_file)
        copyfile(RES_DIR + src_file, DEST_DIR + src_file)
    # doom2 vs doom2bfg map31/32 names differ, different mapinfos with same name
    d2wad = omg.WAD()
    d2_wad_filename = get_wad_filename('doom2')
    # neither doom2: mapinfo still wants a file for the secret levels
    if not d2_wad_filename:
        copyfile(RES_DIR + 'mapinfo/doom2_nonbfg_levels.txt',
                 DEST_DIR + 'mapinfo/doom2_secret_levels.txt')
        return
    d2wad.from_file(d2_wad_filename)
    # bfg version?
    if d2wad.graphics.get(BFG_ONLY_LUMP, None):
        copyfile(RES_DIR + 'mapinfo/doom2_bfg_levels.txt',
                 DEST_DIR + 'mapinfo/doom2_secret_levels.txt')
    else:
        copyfile(RES_DIR + 'mapinfo/doom2_nonbfg_levels.txt',
                 DEST_DIR + 'mapinfo/doom2_secret_levels.txt')
예제 #4
0
def main():
  parser = argparse.ArgumentParser()
  parser.add_argument('--input', help='input wad file to process')
  parser.add_argument('--texture-sparsity', choices=['sparse', 'dense'], help='texture randomization mode - sparse or dense')
  parser.add_argument('--mode', choices=['train', 'test'], help='what those maps are going to be used for: train or test?')
  args = parser.parse_args()
  in_file = args.input
  out_file = in_file + SUFFIX
  wad = omg.WAD(in_file)
  if args.texture_sparsity == 'sparse':
    generator_class = DmTextureGeneratorWrapper
  else:
    generator_class = RandomTextureGenerator
  if args.mode == 'test':
    textures = get_textures(TEST_TEXTURES_PATH, [])
    number_of_maps = NUMBER_OF_IDENTICAL_TEST_MAPS
    generator_arguments = (textures, GOAL_TEXTURES, LANDMARK_TEXTURES)
  else:
    textures = get_textures(TEST_TEXTURES_PATH, GOAL_TEXTURES)
    number_of_maps = NUMBER_OF_TRAIN_MAPS
    generator_arguments = (textures, [], [])
  texture_generator = generator_class(*generator_arguments)
  for index in xrange(number_of_maps):
    print(index)
    set_seed(args.mode)
    add_map_to_wad(wad, change_textures(wad.maps['MAP01'], texture_generator), index)
  wad.to_file(out_file)
예제 #5
0
def extract_iwad_maps(wad_name, map_prefix):
    in_wad = omg.WAD()
    wad_filename = get_wad_filename(wad_name)
    in_wad.from_file(wad_filename)
    for map_name in in_wad.maps.find('*'):
        logg('  Extracting map %s...' % map_name)
        out_wad_filename = DEST_DIR + 'maps/' + map_prefix + map_name + '.wad'
        extract_map(in_wad, map_name, out_wad_filename)
예제 #6
0
def add_secret_exit(map_name, line_id):
    # sets given line # in given map as a secret exit switch
    wad = omg.WAD()
    wad_filename = DEST_DIR + 'maps/%s.wad' % map_name
    wad.from_file(wad_filename)
    ed = omg.MapEditor(wad.maps[map_name])
    ed.linedefs[line_id].__dict__['action'] = 51
    wad.maps[map_name] = ed.to_lumps()
    wad.to_file(wad_filename)
예제 #7
0
def toudmf(input, output, namespace):
    """Convert all maps in INPUT.wad to UDMF and write to OUTPUT.wad"""

    source = omg.WAD(input)
    dest = omg.WAD(output if os.path.exists(output) else None)

    try:
        with tqdm(source.maps.items(), unit="map") as t:
            for mapname, mapinfo in t:
                t.write(mapname)
                dest.udmfmaps[mapname] = omg.UMapEditor(mapinfo,
                                                        namespace).to_lumps()
        dest.to_file(output)
    except AttributeError:
        click.echo("Incorrect Namespace (-ns) for map format?")
        return 1

    return 0
예제 #8
0
def extract_lumps(wad_name):
    if not wad_name in WAD_LUMP_LISTS:
        return
    wad = omg.WAD()
    wad_filename = get_wad_filename(wad_name)
    wad.from_file(wad_filename)
    for lump_list in WAD_LUMP_LISTS[wad_name]:
        # derive subdir from name of lump list
        try:
            lump_type = lump_list[:lump_list.index('_')]
        except ValueError:
            logg("ERROR: Couldn't identify type of lump list %s" % lump_list, error=True)
            continue
        # sigil sky lump isn't in patch namespace
        if lump_list == 'patches_sigil':
            lump_type = 'data'
        lump_table = getattr(wad, lump_type, None)
        if not lump_table:
            logg('  ERROR: Lump type %s not found' % lump_type, error=True)
            continue
        logg('  extracting %s...' % lump_list)
        # sigil sky is in data namespace but we want it in patches dir
        if wad_name == 'sigil' and lump_list == 'patches_sigil':
            lump_subdir = DEST_DIR + 'patches/'
        # sigil screens aren't in graphics namespace but belong in that dir
        elif wad_name == 'sigil' and lump_type == 'data':
            lump_subdir = DEST_DIR + 'graphics/'
        # write PLAYPAL, TEXTURE1 etc to pk3 root
        elif lump_type in ['data', 'txdefs']:
            lump_subdir = DEST_DIR
        else:
            lump_subdir = DEST_DIR + lump_type + '/'
        # process each item in lump list
        for line in open(DATA_DIR + lump_list).readlines():
            line = line.strip()
            # ignore comments
            if line.startswith('//'):
                continue
            # no colon: extracted lump uses name from list
            if line.find(':') == -1:
                out_filename = line
                lump_name = line
            # colon: use filename to right of colon
            else:
                # split then strip
                lump_name, out_filename = line.split(':')
                lump_name = lump_name.strip()
                out_filename = out_filename.strip()
            if not lump_name in lump_table:
                logg("  ERROR: Couldn't find lump with name %s" % lump_name, error=True)
                continue
            lump = lump_table[lump_name]
            out_filename += '.lmp' if lump_type != 'music' else '.mus'
            logg('    Extracting %s' % lump_subdir + out_filename)
            lump.to_file(lump_subdir + out_filename)
예제 #9
0
def hexenhubmerge(input, output, merged_map_name, hub, maps, udmf):
    """Merge HUB and MAPS from INPUT.wad into a single map in OUTPUT.wad as NAME"""

    source = omg.WAD(input)

    hubname = to_mapname(hub)
    if hubname not in source.maps:
        click.echo(f"Error: Hub {hubname} not found in source wad.")
        return 1

    spokes = [to_mapname(s) for s in maps]
    missing = [mapname for mapname in spokes if mapname not in source.maps]

    if missing:
        mstr = ", ".join(missing)
        click.echo(f"Error: Could not find {mstr}")
        return 1

    click.echo(f"Converting {hubname} to UDMF to use as the starting hub")
    merger = MapMerger(source.maps[hubname])

    for spoke in spokes:
        click.echo(f"Converting and merging {spoke}")
        merger.merge(source.maps[spoke])

    merged_map_name = to_mapname(merged_map_name)
    source_hubnum = to_mapnum(hubname)
    dest_hubnum = to_mapnum(merged_map_name) + 1
    spoke_nums = [to_mapnum(s) for s in maps]
    click.echo(
        f"Merged map will be {merged_map_name} in {click.format_filename(output)}, will exit into MAP{dest_hubnum:02}."
    )
    merger.fix_teleports(source_hubnum, dest_hubnum, spoke_nums)
    if udmf is not None:
        click.echo(f"Dumped UDMF to {click.format_filename(udmf.name)}")
        udmf.write(merger.to_textmap())

    result = omg.WAD(output if os.path.exists(output) else None)
    result.udmfmaps[merged_map_name] = merger.to_lumps()
    result.to_file(output)

    return 0
예제 #10
0
def add_secret_level(map_src_filename, map_src_name, map_dest_name):
    global num_maps
    # copies given map file into dest dir and sets its map lump name
    src_filename = get_wad_filename(map_src_filename)
    dest_filename = DEST_DIR + 'maps/%s.wad' % map_dest_name
    copyfile(src_filename, dest_filename)
    wad = omg.WAD()
    wad.from_file(dest_filename)
    wad.maps.rename(map_src_name, map_dest_name)
    wad.to_file(dest_filename)
    num_maps += 1
예제 #11
0
def load_map_editors(wad_or_wad_file):
    ''' Function to load map editors from wad (or filename)
    '''
    if isinstance(wad_or_wad_file, str):
        wad = omg.WAD(wad_or_wad_file)
    elif isinstance(wad_or_wad_file, omg.WAD):
        wad = wad_or_wad_file
    else:
        raise TypeError(
            "argument {} is of type {} but expected str or omg.WAD".format(
                'wad_or_wad_file', type(wad_or_wad_file)))
    return {k: MapEditorPreprocessor(wad, v) for k, v in wad.maps.items()}
예제 #12
0
def dumpacs(wad_filename):
    """Extract and decompile all BEHAVIOR lumps from a wad"""

    source = omg.WAD(wad_filename)

    with tqdm(source.maps.items(), unit="map") as t:
        for mapname, mapinfo in t:
            try:
                dump(mapname, mapinfo["BEHAVIOR"].data)
            except KeyError:
                pass

    return 0
예제 #13
0
 def setUp(self):
     testwad = omg.WAD('test.wad')
     self.testcol = testwad.data['COLORMAP']
     self.col = omg.colormap.Colormap()
예제 #14
0
 def setUp(self):
     testwad = omg.WAD('test.wad')
     self.testmap = omg.mapedit.MapEditor(testwad.maps['MAP01'])
예제 #15
0
 def setUp(self):
     testwad = omg.WAD('test.wad')
     self.testgfx = testwad.graphics['HELP1']
예제 #16
0
 def setUp(self):
     testwad = omg.WAD('test.wad')
     self.tex = omg.txdef.Textures(testwad.txdefs)
예제 #17
0
 def setUp(self):
     testwad = omg.WAD('test.wad')
     self.testpal = testwad.data['PLAYPAL']
     self.pal = omg.playpal.Playpal()
예제 #18
0
import omg
from os import listdir
from os.path import isfile, join
import sys
from PIL import Image

wadfilespath = "enginewad/"
wad = omg.WAD()
files = [f for f in listdir(wadfilespath) if isfile(join(wadfilespath, f))]
for f in files:
    ext = f.find('.meta')
    if ext != -1:
        continue
    ext = f[f.find('.') + 1:]
    if ext == "png":
        graphic = omg.Graphic()
        graphic.from_Image(Image.open(wadfilespath + f))
        lump = graphic
    else:
        with open(wadfilespath + f, "rb") as file:
            lump = omg.Lump(file.read())

    wad.data[f[:f.find('.')]] = lump

wad.to_file("../../../nasty.wad")
예제 #19
0
in_file = '/home/adosovit/work/future_pred/my_scenarios/paper/%s.wad' % map_name
out_file = '/home/adosovit/work/future_pred/my_scenarios/paper/%s_manymaps_%s.wad' % (map_name, mode)


if mode == 'all':
    texture_files = ['all_textures.txt'] * 98
elif mode == 'train':
    texture_files = ['train_textures.txt'] * 98
elif mode == 'test':
    texture_files = ['test_textures.txt'] * 98
elif mode == 'mix':
    texture_files = ['train_textures.txt'] * 88 + ['test_textures.txt'] * 10
else:
    raise Exception('Unknown mode', mode)

wad = omg.WAD(in_file) 

for (nm,texturef) in enumerate(texture_files):
    wad.maps['MAP%.2d' % (nm+2)] = change_textures(wad.maps['MAP01'], texturef)

wad.to_file(out_file)

#for a in sys.argv[1:]:
    #if a == "-o":
        #break
    #print "Adding %s..." % a
    #w += omg.WAD(a)
#outpath = "merged.wad"
#if "-o" in sys.argv: outpath = sys.argv[-1]
#w.to_file(outpath)
예제 #20
0
for word in words.strip().split("\n"):
    word = " " + word + " "
    v = add_vertex(x=0, y=y + 32)
    add_linedef(vx_a=last_v, vx_b=v, flags=1, front=sd1)
    last_v = v
    y += 32

    start_v = last_v
    backpin_v = add_vertex(x=-1, y=y)

    for offset, npixels in make_phrase(word, letters):
        sd = add_sidedef(sector=sec1, tx_low="SHAWN1", off_x=offset)
        v = add_vertex(x=0, y=y + npixels)
        add_linedef(vx_a=last_v, vx_b=v, front=sd, back=sd2,
                    flags=1 + 4 + 16)  # impassible, two-sided, lower-unpeg
        last_v = v
        y += npixels

    add_linedef(vx_a=start_v, vx_b=backpin_v, front=sd2, flags=1)
    add_linedef(vx_a=backpin_v, vx_b=last_v, front=sd2, flags=1)

# Tailing end to join back with first linedef
add_linedef(vx_a=last_v, vx_b=v4, front=sd1, flags=1)

# Player 1 start
add_thing(x=128, y=128, type=1, angle=180)

w = omg.WAD()
w.maps["MAP01"] = ed.to_lumps()
w.to_file("letters.wad")
예제 #21
0
    def get_random_map_shot(self):
        # search any WAD files for maps using omgifol
        self.all_wad_maps = []
        # remember which file a map lives in (for multi-wad zips)
        map_wad_mapping = {}
        for f in self.files_to_load:
            if f.lower().endswith('wad'):
                maps = omg.WAD(f).maps.keys()
                if not maps:
                    continue
                for m in maps:
                    # don't add MAPINFO lumps
                    if m != 'MAPINFO':
                        self.all_wad_maps.append(m)
                        map_wad_mapping[m] = f
        if len(self.all_wad_maps) > 0:
            print('Maps found: %s' % ', '.join(self.all_wad_maps))
        else:
            print("Couldn't find any maps")
            return
        # pick a map
        map_name = random.choice(self.all_wad_maps)
        self.map_wad = os.path.basename(map_wad_mapping[map_name])
        # get correct number(s) to feed -warp CLI switch: map# for doom2,
        # E# M# for doom1
        if map_name.startswith('E'):
            self.level = '%s %s' % (map_name[1], map_name[3:])
        elif map_name.startswith('MAP'):
            self.level = map_name[3:]
        else:
            # something else, gzdoom hopefully opens these by lump name
            self.level = map_name
        # determine IWAD to launch with
        # two numbers = doom1 eXmY map, one number = doom2 mapXX format
        # if already set, we got it from a url, eg heretic or hexen
        if self.file_link and self.file_link.startswith(DOWNLOAD_URL_PATTERN +
                                                        'levels/heretic/'):
            self.iwad = 'heretic.wad'
        elif self.file_link and self.file_link.startswith(
                DOWNLOAD_URL_PATTERN + 'levels/hexen/'):
            self.iwad = 'hexen.wad'
        elif self.map_wad.lower() in ['heretic.wad', 'hexen.wad', 'hexdd.wad']:
            self.iwad = self.map_wad
        elif ' ' in self.level:
            self.iwad = 'doom.wad'
        else:
            self.iwad = 'doom2.wad'
        print('Will try to load map %s' % self.level)
        # enclose pwad file names in quotes
        file_list = []
        for f in ALWAYS_INCLUDE_PWADS + self.files_to_load:
            file_list.append('"%s"' % f)
        # generate a shell script to run gzdoom with all the correct settings
        cmd = ['python2', 'dmvis.py', ' '.join(self.files_to_load), map_name]
        SCREENSHOT_FILENAMES[0] = ("%s_%s.gif" %
                                   (self.files_to_load[0], map_name))
        SCREENSHOT_OUTPUT_FILENAMES[0] = SCREENSHOT_FILENAMES[0]
        print(' '.join(cmd))
        subprocess.call(cmd)

        self.shot_valid = os.path.exists(
            SCREENSHOT_FILENAMES[0])  # and os.path.exists(LOG_PATH)
        if self.shot_valid:
            self.post()
예제 #22
0
    res = spack("2H2h", *imr.size, 0, 0)
    cols = []

    for x in range(imr.size[0]):
        res += spack("I", 8 + imr.size[0] * 4 + (3 + imr.size[1]) * len(cols))
        col = spack("3B", 0, image.size[1], 0)
        i = image.crop((x, 0, x + 1, imr.size[1]))
        col += i.tobytes()
        cols.append(col)

    return res + b''.join(cols)


if __name__ == "__main__":
    texnames = sys.argv[3:]
    outwad = omg.WAD()
    pal = ImagePalette.ImagePalette(
        "RGB",
        bytearray(omg.WAD(from_file=sys.argv[1]).data["PLAYPAL"].data[:768]))
    texture1 = []
    pnames = []
    i = 0

    print(":: ImagoLux :: Limit-Removing Colored Lighting ::")
    print("(c)2018 Gustavo R. Rehermann. Code: MIT License. Media:")
    print("CC0 if owned by Gustavo, respective owners otherwise.")
    print()

    if ZDOOM:
        print("Exporting ZDoom-style textures.")
예제 #23
0
def extract_map(in_wad, map_name, out_filename):
    global num_maps
    out_wad = omg.WAD()
    out_wad.maps[map_name] = in_wad.maps[map_name]
    out_wad.to_file(out_filename)
    num_maps += 1
예제 #24
0
def main(argv):
    w = omg.WAD(from_file=omg.WadIO(argv[1], mode='rb'))
    map_editor = omg.MapEditor(w.maps[argv[2]])
    return globals()[argv[3]](map_editor, *argv[4:])
예제 #25
0
def extract_master_levels():
    # check if present first
    order_file, ml_map_order = get_master_levels_map_order()
    if len(ml_map_order) == 0:
        return
    first_ml_wad = get_wad_filename(ml_map_order[0])
    if not first_ml_wad:
        logg('ERROR: Master Levels not found.', error=True)
        return
    logg('Processing Master Levels...')
    mapinfo = open(ML_MAPINFO_FILENAME, 'w')
    mapinfo.write(MASTER_LEVELS_MAPINFO_HEADER % order_file)
    for i,wad_name in enumerate(ml_map_order):
        in_wad = omg.WAD()
        wad_filename = get_wad_filename(wad_name)
        if not wad_filename:
            logg("ERROR: Couldn't find %s" % wad_name, error=True)
            continue
        in_wad.from_file(wad_filename)
        out_wad_filename = DEST_DIR + 'maps/' + MASTER_LEVELS_MAP_PREFIX + 'map'
        # extra zero for <10 map numbers, eg map01
        out_wad_filename += str(i + 1).rjust(2, '0') + '.wad'
        logg('  Extracting %s to %s' % (wad_filename, out_wad_filename))
        # grab first map we find in each wad
        map_name = in_wad.maps.find('*')[0]
        extract_map(in_wad, map_name, out_wad_filename)
        # write data to mapinfo based on ordering
        mapinfo.writelines('\n'.join(get_ml_mapinfo(wad_name, i+1)))
        mapinfo.write('\n\n')
    # save teeth map32 to map21
    wad_filename = get_wad_filename('teeth')
    out_wad_filename = DEST_DIR + 'maps/' + MASTER_LEVELS_MAP_PREFIX + 'map21' + '.wad'
    logg('  Extracting %s map32 to %s' % (wad_filename, out_wad_filename))
    in_wad = omg.WAD()
    in_wad.from_file(wad_filename)
    extract_map(in_wad, in_wad.maps.find('*')[1], out_wad_filename)
    # write map21 mapinfo
    if ml_map_order.index('teeth') == 19:
        next_map = 'EndGameC'
    else:
        next_map = '%sMAP%s' % (MASTER_LEVELS_MAP_PREFIX.upper(),
                                ml_map_order.index('teeth') + 2)
    mapinfo.write(MASTER_LEVELS_SECRET_DEF % (next_map, MASTER_LEVELS_MUSIC['teeth2'],
                                              MASTER_LEVELS_AUTHOR_PREFIX, MASTER_LEVELS_AUTHORS['teeth2']))
    # finish mapinfo
    mapinfo.writelines([MASTER_LEVELS_CLUSTER_DEF])
    mapinfo.close()
    # extract sky lumps
    for wad_name,patch_replace in MASTER_LEVELS_PATCHES.items():
        wad = omg.WAD()
        wad_filename = get_wad_filename(wad_name)
        wad.from_file(wad_filename)
        # manor stores sky in patches namespace, combine and virgil don't
        if patch_replace[0] in wad.data:
            lump = wad.data[patch_replace[0]]
        else:
            lump = wad.patches[patch_replace[0]]
        out_filename = DEST_DIR + 'patches/' + patch_replace[1] + '.lmp'
        logg('  Extracting %s lump from %s as %s' % (patch_replace[0],
                                                   wad_filename,
                                                   patch_replace[1]))
        lump.to_file(out_filename)
예제 #26
0
    else:
        n = str(num)
    return "MAP" + n


def print_map_order(sortedlist, wad):
    for m in sortedlist:
        print m.orig_pos


def place_maps_in_wad(sortedlist, wad):
    for i, m in enumerate(sortedlist):
        wad.maps[map_index(i)] = m
    return wad


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print "Usage:"
        print ""
        print "  doomsort.py [wad]"
    else:
        test_wad_path = sys.argv[1]
        test_wad = omg.WAD(test_wad_path)
        # test_map = omg.MapEditor(test_wad.maps["MAP01"])
        rated_list = rate_map_list(test_wad)
        sorted_rated_list = sorted(rated_list, key=lambda wmap: wmap.rating)
        #output_wad = place_maps_in_wad(sorted_rated_list,test_wad)
        #output_wad.to_file(test_output_path)
        print_map_order(sorted_rated_list, test_wad)
예제 #27
0
import omg, sys

if (len(sys.argv) < 3):
    print "\n    Omgifol script: merge WADs\n"
    print "    Usage:"
    print "    merge.py input1.wad input2.wad ... [-o output.wad]\n"
    print "    Default output is merged.wad"
else:
    w = omg.WAD()
    for a in sys.argv[1:]:
        if a == "-o":
            break
        print "Adding %s..." % a
        w += omg.WAD(a)
    outpath = "merged.wad"
    if "-o" in sys.argv: outpath = sys.argv[-1]
    w.to_file(outpath)
def main():
    """Main function"""
    args = parse_args()
    with open(args.wad_config[0]) as wad_config_stream:
        wad_list = yaml.safe_load(wad_config_stream)

    wad_id_list = []
    for wad in wad_list:
        if 'www.doomworld.com' in wad:
            file_id = get_file_id_from_idgames_url(wad)
            wad_id_list.append(file_id)
        else:
            file_search = IdgamesAPI.search(wad)
            if file_search.get('content'):
                files_info = file_search['content']['file']
                if not isinstance(files_info, list):
                    files_info = [files_info]

                if len(files_info) > 1 and not args.download_all:
                    raise RuntimeError(
                        'Found multiple matching wads for wad name {} during search.'.format(wad)
                    )

                wad_id_list.extend([file_info['id'] for file_info in files_info])

    wad_jsons = []
    for wad_id in wad_id_list:
        idgames_response, local_file_path = IdgamesAPI.download_file(file_id=wad_id, overwrite=True)
        file_info = idgames_response['content']

        file_creation_date = None
        tmp_extract_path = 'tmp_extraction'
        with ZipFile(local_file_path, 'r') as zip_file:
            info_list = zip_file.infolist()
            for file_zip_info in info_list:
                for resource_re in RESOURCE_FILE_FORMATS:
                    if resource_re.match(file_zip_info.filename):
                        if not file_creation_date:
                            file_creation_date = parse_zip_info_date_time(file_zip_info.date_time)
                        else:
                            cur_file_creation_date = parse_zip_info_date_time(
                                file_zip_info.date_time
                            )
                            if cur_file_creation_date > file_creation_date:
                                file_creation_date = cur_file_creation_date

            zip_file.extractall('tmp_extraction')

        wads_in_zip = glob.glob('{}/*.wad'.format(tmp_extract_path))
        num_maps = 0
        for wad in wads_in_zip:
            wad_object = omg.WAD(wad)
            num_maps += len(wad_object.maps)

        if num_maps < 1:
            LOGGER.error('No maps found for wad %s.', file_info['filename'])

        # idgames date format: YYYY-MM-DD
        # This expression splits the date by '-', converts each element to int, then passes the
        # values as args to the datetime constructor
        idgames_date = datetime(*map(int, file_info['date'].split('-')))
        idgames_year = idgames_date.year
        file_creation_year = file_creation_date.year
        if idgames_year != file_creation_year:
            LOGGER.error('Mismatched years in idgames date and file creation date for wad %s!',
                         file_info['filename'])
            LOGGER.error('Idgames year: %s, file creation year: %s.', idgames_year,
                         file_creation_year)

        wad_year = file_creation_year
        if file_creation_date < EARLIEST_WAD_TIME:
            wad_year = idgames_year

        wad_json = {
            'author': file_info['author'],
            'single_map': num_maps == 1,
            'iwad': file_info['dir'].split('/')[1],
            'name': file_info['title'],
            'short_name': file_info['filename'].split('.')[0],
            'year': wad_year,
            'file': {
                'name': local_file_path,
                'data': 'placeholder'
            }
        }
        wad_jsons.append(wad_json)

        shutil.rmtree(tmp_extract_path)

    wad_jsons = {'wads': wad_jsons}
    output_json = args.output_json
    if not output_json:
        output_json = '{}_upload.json'.format(datetime.today().strftime('%Y%m%d'))
        if os.path.exists(output_json):
            filename_no_ext = os.path.splitext(output_json)[0]
            alt_file_list = glob.glob('{}_*.json'.format(filename_no_ext))
            if not alt_file_list:
                output_json = '{}_2.json'.format(filename_no_ext)
            else:
                max_idx = max(int(os.path.splitext(filename)[0].split('_')[-1])
                              for filename in alt_file_list)
                output_json = '{}_{}.json'.format(filename_no_ext, max_idx + 1)

    if os.path.exists(output_json):
        raise OSError('Output JSON {} already exists!'.format(output_json))
    with open(output_json, 'w') as output_stream:
        json.dump(wad_jsons, output_stream, sort_keys=True, indent=2)