2018-01-01 18:11:11 +00:00
#!/usr/bin/env python3
2017-07-14 12:34:33 +00:00
import argparse
2019-12-16 11:52:30 +00:00
import copy
2017-07-14 12:34:33 +00:00
import os
import logging
import random
2017-07-14 16:24:23 +00:00
import textwrap
2019-12-16 11:52:30 +00:00
import shlex
2017-11-19 21:00:26 +00:00
import sys
2017-07-14 12:34:33 +00:00
2017-12-17 05:25:46 +00:00
from Main import main
2019-04-18 09:23:24 +00:00
from Utils import is_bundled , close_console , output_path
2017-07-14 12:34:33 +00:00
2017-07-14 16:24:23 +00:00
class ArgumentDefaultsHelpFormatter ( argparse . RawTextHelpFormatter ) :
def _get_help_string ( self , action ) :
return textwrap . dedent ( action . help )
2019-12-15 17:10:01 +00:00
def parse_arguments ( argv , no_defaults = False ) :
def defval ( value ) :
return value if not no_defaults else None
2017-11-04 18:23:57 +00:00
2019-12-16 11:52:30 +00:00
# we need to know how many players we have first
parser = argparse . ArgumentParser ( )
parser . add_argument ( ' --multi ' , default = defval ( 1 ) , type = lambda value : min ( max ( int ( value ) , 1 ) , 255 ) )
multiargs , _ = parser . parse_known_args ( argv )
2017-07-14 16:24:23 +00:00
parser = argparse . ArgumentParser ( formatter_class = ArgumentDefaultsHelpFormatter )
2017-07-14 12:34:33 +00:00
parser . add_argument ( ' --create_spoiler ' , help = ' Output a Spoiler File ' , action = ' store_true ' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --logic ' , default = defval ( ' noglitches ' ) , const = ' noglitches ' , nargs = ' ? ' , choices = [ ' noglitches ' , ' minorglitches ' , ' nologic ' ] ,
2017-07-14 16:24:23 +00:00
help = ''' \
Select Enforcement of Item Requirements . ( default : % ( default ) s )
2017-11-19 01:43:37 +00:00
No Glitches :
2017-07-14 16:24:23 +00:00
Minor Glitches : May require Fake Flippers , Bunny Revival
2017-11-19 01:43:37 +00:00
and Dark Room Navigation .
2018-03-25 22:21:36 +00:00
No Logic : Distribute items without regard for
item requirements .
2017-07-14 16:24:23 +00:00
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --mode ' , default = defval ( ' open ' ) , const = ' open ' , nargs = ' ? ' , choices = [ ' standard ' , ' open ' , ' inverted ' ] ,
2017-07-14 16:24:23 +00:00
help = ''' \
Select game mode . ( default : % ( default ) s )
2017-07-17 20:28:29 +00:00
Open : World starts with Zelda rescued .
2017-07-14 16:24:23 +00:00
Standard : Fixes Hyrule Castle Secret Entrance and Front Door
but may lead to weird rain state issues if you exit
through the Hyrule Castle side exits before rescuing
Zelda in a full shuffle .
2019-07-27 13:13:13 +00:00
Inverted : Starting locations are Dark Sanctuary in West Dark
World or at Link ' s House, which is shuffled freely.
Requires the moon pearl to be Link in the Light World
instead of a bunny .
2017-07-14 16:24:23 +00:00
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --swords ' , default = defval ( ' random ' ) , const = ' random ' , nargs = ' ? ' , choices = [ ' random ' , ' assured ' , ' swordless ' , ' vanilla ' ] ,
2019-08-04 16:32:35 +00:00
help = ''' \
Select sword placement . ( default : % ( default ) s )
Random : All swords placed randomly .
Assured : Start game with a sword already .
Swordless : No swords . Curtains in Skull Woods and Agahnim \' s
Tower are removed , Agahnim \' s Tower barrier can be
destroyed with hammer . Misery Mire and Turtle Rock
can be opened without a sword . Hammer damages Ganon .
Ether and Bombos Tablet can be activated with Hammer
( and Book ) . Bombos pads have been added in Ice
Palace , to allow for an alternative to firerod .
Vanilla : Swords are in vanilla locations .
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --goal ' , default = defval ( ' ganon ' ) , const = ' ganon ' , nargs = ' ? ' , choices = [ ' ganon ' , ' pedestal ' , ' dungeons ' , ' triforcehunt ' , ' crystals ' ] ,
2017-07-14 16:24:23 +00:00
help = ''' \
Select completion goal . ( default : % ( default ) s )
2017-11-19 01:43:37 +00:00
Ganon : Collect all crystals , beat Agahnim 2 then
2017-07-17 20:28:29 +00:00
defeat Ganon .
2017-08-01 17:07:44 +00:00
Crystals : Collect all crystals then defeat Ganon .
2017-07-14 16:24:23 +00:00
Pedestal : Places the Triforce at the Master Sword Pedestal .
2017-07-17 20:28:29 +00:00
All Dungeons : Collect all crystals , pendants , beat both
Agahnim fights and then defeat Ganon .
2017-11-19 01:43:37 +00:00
Triforce Hunt : Places 30 Triforce Pieces in the world , collect
20 of them to beat the game .
2017-07-14 16:24:23 +00:00
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --difficulty ' , default = defval ( ' normal ' ) , const = ' normal ' , nargs = ' ? ' , choices = [ ' normal ' , ' hard ' , ' expert ' ] ,
2017-07-14 16:24:23 +00:00
help = ''' \
Select game difficulty . Affects available itempool . ( default : % ( default ) s )
Normal : Normal difficulty .
2017-11-10 10:18:09 +00:00
Hard : A harder setting with less equipment and reduced health .
Expert : A harder yet setting with minimum equipment and health .
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --item_functionality ' , default = defval ( ' normal ' ) , const = ' normal ' , nargs = ' ? ' , choices = [ ' normal ' , ' hard ' , ' expert ' ] ,
2019-08-10 23:37:26 +00:00
help = ''' \
Select limits on item functionality to increase difficulty . ( default : % ( default ) s )
Normal : Normal functionality .
Hard : Reduced functionality .
Expert : Greatly reduced functionality .
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --timer ' , default = defval ( ' none ' ) , const = ' normal ' , nargs = ' ? ' , choices = [ ' none ' , ' display ' , ' timed ' , ' timed-ohko ' , ' ohko ' , ' timed-countdown ' ] ,
2017-11-10 10:18:09 +00:00
help = ''' \
Select game timer setting . Affects available itempool . ( default : % ( default ) s )
None : No timer .
2017-11-12 00:08:41 +00:00
Display : Displays a timer but does not affect
the itempool .
2017-07-14 16:24:23 +00:00
Timed : Starts with clock at zero . Green Clocks
subtract 4 minutes ( Total : 20 ) , Blue Clocks
subtract 2 minutes ( Total : 10 ) , Red Clocks add
2 minutes ( Total : 10 ) . Winner is player with
lowest time at the end .
Timed OHKO : Starts clock at 10 minutes . Green Clocks add
5 minutes ( Total : 25 ) . As long as clock is at 0 ,
Link will die in one hit .
2017-11-19 01:36:42 +00:00
OHKO : Like Timed OHKO , but no clock items are present
and the clock is permenantly at zero .
2017-07-14 16:24:23 +00:00
Timed Countdown : Starts with clock at 40 minutes . Same clocks as
Timed mode . If time runs out , you lose ( but can
2017-11-19 01:43:37 +00:00
still keep playing ) .
2017-07-14 16:24:23 +00:00
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --progressive ' , default = defval ( ' on ' ) , const = ' normal ' , nargs = ' ? ' , choices = [ ' on ' , ' off ' , ' random ' ] ,
2017-11-10 10:18:09 +00:00
help = ''' \
Select progressive equipment setting . Affects available itempool . ( default : % ( default ) s )
On : Swords , Shields , Armor , and Gloves will
all be progressive equipment . Each subsequent
item of the same type the player finds will
upgrade that piece of equipment by one stage .
Off : Swords , Shields , Armor , and Gloves will not
be progressive equipment . Higher level items may
be found at any time . Downgrades are not possible .
Random : Swords , Shields , Armor , and Gloves will , per
category , be randomly progressive or not .
2017-11-19 01:43:37 +00:00
Link will die in one hit .
2017-11-10 10:18:09 +00:00
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --algorithm ' , default = defval ( ' balanced ' ) , const = ' balanced ' , nargs = ' ? ' , choices = [ ' freshness ' , ' flood ' , ' vt21 ' , ' vt22 ' , ' vt25 ' , ' vt26 ' , ' balanced ' ] ,
2017-07-14 16:24:23 +00:00
help = ''' \
2017-10-15 17:52:42 +00:00
Select item filling algorithm . ( default : % ( default ) s
2017-11-11 21:28:34 +00:00
balanced : vt26 derivitive that aims to strike a balance between
the overworld heavy vt25 and the dungeon heavy vt26
algorithm .
2017-10-15 17:52:42 +00:00
vt26 : Shuffle items and place them in a random location
that it is not impossible to be in . This includes
2017-11-11 21:28:34 +00:00
dungeon keys and items .
2017-08-01 17:07:44 +00:00
vt25 : Shuffle items and place them in a random location
2017-07-14 16:24:23 +00:00
that it is not impossible to be in .
vt21 : Unbiased in its selection , but has tendency to put
Ice Rod in Turtle Rock .
vt22 : Drops off stale locations after 1 / 3 of progress
items were placed to try to circumvent vt21 \' s
shortcomings .
Freshness : Keep track of stale locations ( ones that cannot be
reached yet ) and decrease likeliness of selecting
them the more often they were found unreachable .
Flood : Push out items starting from Link \' s House and
slightly biased to placing progression items with
2017-11-19 01:43:37 +00:00
less restrictions .
2017-07-14 16:24:23 +00:00
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --shuffle ' , default = defval ( ' full ' ) , const = ' full ' , nargs = ' ? ' , choices = [ ' vanilla ' , ' simple ' , ' restricted ' , ' full ' , ' crossed ' , ' insanity ' , ' restricted_legacy ' , ' full_legacy ' , ' madness_legacy ' , ' insanity_legacy ' , ' dungeonsfull ' , ' dungeonssimple ' ] ,
2017-07-14 16:24:23 +00:00
help = ''' \
Select Entrance Shuffling Algorithm . ( default : % ( default ) s )
2018-02-20 20:34:39 +00:00
Full : Mix cave and dungeon entrances freely while limiting
multi - entrance caves to one world .
2017-07-14 16:24:23 +00:00
Simple : Shuffle Dungeon Entrances / Exits between each other
and keep all 4 - entrance dungeons confined to one
location . All caves outside of death mountain are
2018-02-20 20:34:39 +00:00
shuffled in pairs and matched by original type .
2017-07-14 16:24:23 +00:00
Restricted : Use Dungeons shuffling from Simple but freely
connect remaining entrances .
2018-02-20 20:34:39 +00:00
Crossed : Mix cave and dungeon entrances freely while allowing
caves to cross between worlds .
Insanity : Decouple entrances and exits from each other and
shuffle them freely . Caves that used to be single
entrance will still exit to the same location from
which they are entered .
Vanilla : All entrances are in the same locations they were
in the base game .
Legacy shuffles preserve behavior from older versions of the
entrance randomizer including significant technical limitations .
2017-07-14 16:24:23 +00:00
The dungeon variants only mix up dungeons and keep the rest of
2017-11-19 01:43:37 +00:00
the overworld vanilla .
2017-07-14 16:24:23 +00:00
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --crystals_ganon ' , default = defval ( ' 7 ' ) , const = ' 7 ' , nargs = ' ? ' , choices = [ ' random ' , ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' ] ,
2019-08-11 12:55:38 +00:00
help = ''' \
How many crystals are needed to defeat ganon . Any other
requirements for ganon for the selected goal still apply .
This setting does not apply when the all dungeons goal is
selected . ( default : % ( default ) s )
Random : Picks a random value between 0 and 7 ( inclusive ) .
0 - 7 : Number of crystals needed
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --crystals_gt ' , default = defval ( ' 7 ' ) , const = ' 7 ' , nargs = ' ? ' , choices = [ ' random ' , ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' ] ,
2019-08-11 12:55:38 +00:00
help = ''' \
How many crystals are needed to open GT . For inverted mode
this applies to the castle tower door instead . ( default : % ( default ) s )
Random : Picks a random value between 0 and 7 ( inclusive ) .
0 - 7 : Number of crystals needed
''' )
2019-12-12 08:20:32 +00:00
parser . add_argument ( ' --openpyramid ' , help = ''' \
Pre - opens the pyramid hole , this removes the Agahnim 2 requirement for it
''' , action= ' store_true ' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --rom ' , default = defval ( ' Zelda no Densetsu - Kamigami no Triforce (Japan).sfc ' ) , help = ' Path to an ALttP JAP(1.0) rom to use as a base. ' )
parser . add_argument ( ' --loglevel ' , default = defval ( ' info ' ) , const = ' info ' , nargs = ' ? ' , choices = [ ' error ' , ' info ' , ' warning ' , ' debug ' ] , help = ' Select level of logging for output. ' )
2017-07-14 12:34:33 +00:00
parser . add_argument ( ' --seed ' , help = ' Define seed number to generate. ' , type = int )
2017-07-14 16:24:23 +00:00
parser . add_argument ( ' --count ' , help = ''' \
Use to batch generate multiple seeds with same settings .
If - - seed is provided , it will be used for the first seed , then
used to derive the next seed ( i . e . generating 10 seeds with
- - seed given will produce the same 10 ( different ) roms each
2017-11-19 01:43:37 +00:00
time ) .
2017-07-14 16:24:23 +00:00
''' , type=int)
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --fastmenu ' , default = defval ( ' normal ' ) , const = ' normal ' , nargs = ' ? ' , choices = [ ' normal ' , ' instant ' , ' double ' , ' triple ' , ' quadruple ' , ' half ' ] ,
2018-01-05 22:53:29 +00:00
help = ''' \
Select the rate at which the menu opens and closes .
( default : % ( default ) s )
''' )
2017-07-14 12:34:33 +00:00
parser . add_argument ( ' --quickswap ' , help = ' Enable quick item swapping with L and R. ' , action = ' store_true ' )
2017-11-28 10:54:14 +00:00
parser . add_argument ( ' --disablemusic ' , help = ' Disables game music. ' , action = ' store_true ' )
2019-12-13 21:37:52 +00:00
parser . add_argument ( ' --mapshuffle ' , help = ' Maps are no longer restricted to their dungeons, but can be anywhere ' , action = ' store_true ' )
parser . add_argument ( ' --compassshuffle ' , help = ' Compasses are no longer restricted to their dungeons, but can be anywhere ' , action = ' store_true ' )
parser . add_argument ( ' --keyshuffle ' , help = ' Small Keys are no longer restricted to their dungeons, but can be anywhere ' , action = ' store_true ' )
parser . add_argument ( ' --bigkeyshuffle ' , help = ' Big Keys are no longer restricted to their dungeons, but can be anywhere ' , action = ' store_true ' )
2018-03-14 18:31:36 +00:00
parser . add_argument ( ' --retro ' , help = ''' \
Keys are universal , shooting arrows costs rupees ,
and a few other little things make this more like Zelda - 1.
''' , action= ' store_true ' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --custom ' , default = defval ( False ) , help = ' Not supported. ' )
parser . add_argument ( ' --customitemarray ' , default = defval ( False ) , help = ' Not supported. ' )
parser . add_argument ( ' --accessibility ' , default = defval ( ' items ' ) , const = ' items ' , nargs = ' ? ' , choices = [ ' items ' , ' locations ' , ' none ' ] , help = ''' \
2019-08-04 21:40:13 +00:00
Select Item / Location Accessibility . ( default : % ( default ) s )
Items : You can reach all unique inventory items . No guarantees about
reaching all locations or all keys .
Locations : You will be able to reach every location in the game .
None : You will be able to reach enough locations to beat the game .
''' )
2019-01-23 09:04:42 +00:00
parser . add_argument ( ' --hints ' , help = ''' \
Make telepathic tiles and storytellers give helpful hints .
''' , action= ' store_true ' )
2018-01-27 22:11:53 +00:00
# included for backwards compatibility
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --shuffleganon ' , help = argparse . SUPPRESS , action = ' store_true ' , default = defval ( True ) )
2018-01-27 22:11:53 +00:00
parser . add_argument ( ' --no-shuffleganon ' , help = ''' \
If set , the Pyramid Hole and Ganon ' s Tower are not
included entrance shuffle pool .
''' , action= ' store_false ' , dest= ' shuffleganon ' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --heartbeep ' , default = defval ( ' normal ' ) , const = ' normal ' , nargs = ' ? ' , choices = [ ' double ' , ' normal ' , ' half ' , ' quarter ' , ' off ' ] ,
2017-07-14 16:24:23 +00:00
help = ''' \
Select the rate at which the heart beep sound is played at
2017-11-19 01:43:37 +00:00
low health . ( default : % ( default ) s )
2017-07-14 16:24:23 +00:00
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --heartcolor ' , default = defval ( ' red ' ) , const = ' red ' , nargs = ' ? ' , choices = [ ' red ' , ' blue ' , ' green ' , ' yellow ' , ' random ' ] ,
2018-02-28 02:26:33 +00:00
help = ' Select the color of Link \' s heart meter. (default: %(default)s ) ' )
2017-07-14 16:24:23 +00:00
parser . add_argument ( ' --sprite ' , help = ''' \
Path to a sprite sheet to use for Link . Needs to be in
2017-11-19 01:43:37 +00:00
binary format and have a length of 0x7000 ( 28672 ) bytes ,
2017-07-14 16:24:23 +00:00
or 0x7078 ( 28792 ) bytes including palette data .
Alternatively , can be a ALttP Rom patched with a Link
2017-11-19 01:43:37 +00:00
sprite that will be extracted .
2017-07-14 16:24:23 +00:00
''' )
2017-07-14 12:34:33 +00:00
parser . add_argument ( ' --suppress_rom ' , help = ' Do not create an output rom file. ' , action = ' store_true ' )
parser . add_argument ( ' --gui ' , help = ' Launch the GUI ' , action = ' store_true ' )
2017-07-16 21:20:54 +00:00
parser . add_argument ( ' --jsonout ' , action = ' store_true ' , help = ''' \
2017-11-19 01:43:37 +00:00
Output . json patch to stdout instead of a patched rom . Used
2017-07-14 16:24:23 +00:00
for VT site integration , do not use otherwise .
''' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --skip_playthrough ' , action = ' store_true ' , default = defval ( False ) )
parser . add_argument ( ' --enemizercli ' , default = defval ( ' ' ) )
parser . add_argument ( ' --shufflebosses ' , default = defval ( ' none ' ) , choices = [ ' none ' , ' basic ' , ' normal ' , ' chaos ' ] )
2019-12-16 00:35:10 +00:00
parser . add_argument ( ' --shuffleenemies ' , default = defval ( ' none ' ) , choices = [ ' none ' , ' shuffled ' , ' chaos ' ] )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --enemy_health ' , default = defval ( ' default ' ) , choices = [ ' default ' , ' easy ' , ' normal ' , ' hard ' , ' expert ' ] )
parser . add_argument ( ' --enemy_damage ' , default = defval ( ' default ' ) , choices = [ ' default ' , ' shuffled ' , ' chaos ' ] )
parser . add_argument ( ' --shufflepalette ' , default = defval ( False ) , action = ' store_true ' )
parser . add_argument ( ' --shufflepots ' , default = defval ( False ) , action = ' store_true ' )
parser . add_argument ( ' --multi ' , default = defval ( 1 ) , type = lambda value : min ( max ( int ( value ) , 1 ) , 255 ) )
parser . add_argument ( ' --names ' , default = defval ( ' ' ) )
2019-04-18 09:23:24 +00:00
parser . add_argument ( ' --outputpath ' )
2019-12-15 17:10:01 +00:00
parser . add_argument ( ' --race ' , default = defval ( False ) , action = ' store_true ' )
2019-12-15 16:29:17 +00:00
parser . add_argument ( ' --outputname ' )
2019-12-16 11:52:30 +00:00
if multiargs . multi :
for player in range ( 1 , multiargs . multi + 1 ) :
parser . add_argument ( f ' --p { player } ' , default = defval ( ' ' ) , help = argparse . SUPPRESS )
ret = parser . parse_args ( argv )
if multiargs . multi :
defaults = copy . deepcopy ( ret )
for player in range ( 1 , multiargs . multi + 1 ) :
playerargs = parse_arguments ( shlex . split ( getattr ( ret , f " p { player } " ) ) , True )
2019-12-16 16:46:21 +00:00
for name in [ ' logic ' , ' mode ' , ' swords ' , ' goal ' , ' difficulty ' , ' item_functionality ' ] :
2019-12-16 11:52:30 +00:00
value = getattr ( defaults , name ) if getattr ( playerargs , name ) is None else getattr ( playerargs , name )
if player == 1 :
setattr ( ret , name , { 1 : value } )
else :
getattr ( ret , name ) [ player ] = value
return ret
2019-12-15 17:10:01 +00:00
def start ( ) :
args = parse_arguments ( None )
2017-07-14 12:34:33 +00:00
2019-04-18 09:23:24 +00:00
if args . outputpath and os . path . isdir ( args . outputpath ) :
output_path . cached_path = args . outputpath
2017-12-17 05:25:46 +00:00
if is_bundled ( ) and len ( sys . argv ) == 1 :
2017-11-28 14:36:32 +00:00
# for the bundled builds, if we have no arguments, the user
# probably wants the gui. Users of the bundled build who want the command line
2017-11-16 03:06:53 +00:00
# interface shouuld specify at least one option, possibly setting a value to a
# default if they like all the defaults
2019-07-11 21:33:27 +00:00
from Gui import guiMain
2017-12-02 14:21:04 +00:00
close_console ( )
2017-11-16 03:06:53 +00:00
guiMain ( )
sys . exit ( 0 )
2017-07-14 12:34:33 +00:00
# ToDo: Validate files further than mere existance
if not args . jsonout and not os . path . isfile ( args . rom ) :
input ( ' Could not find valid base rom for patching at expected path %s . Please run with -h to see help for further information. \n Press Enter to exit. ' % args . rom )
2017-11-19 21:00:26 +00:00
sys . exit ( 1 )
2017-07-16 21:20:54 +00:00
if args . sprite is not None and not os . path . isfile ( args . sprite ) :
if not args . jsonout :
input ( ' Could not find link sprite sheet at given location. \n Press Enter to exit. ' % args . sprite )
2017-11-19 21:00:26 +00:00
sys . exit ( 1 )
2017-07-16 21:20:54 +00:00
else :
raise IOError ( ' Cannot find sprite file at %s ' % args . sprite )
2017-07-14 12:34:33 +00:00
# set up logger
loglevel = { ' error ' : logging . ERROR , ' info ' : logging . INFO , ' warning ' : logging . WARNING , ' debug ' : logging . DEBUG } [ args . loglevel ]
logging . basicConfig ( format = ' %(message)s ' , level = loglevel )
if args . gui :
2019-07-11 21:33:27 +00:00
from Gui import guiMain
2017-07-14 12:34:33 +00:00
guiMain ( args )
elif args . count is not None :
seed = args . seed
2017-12-17 05:25:46 +00:00
for _ in range ( args . count ) :
2017-07-14 12:34:33 +00:00
main ( seed = seed , args = args )
seed = random . randint ( 0 , 999999999 )
else :
main ( seed = args . seed , args = args )
2017-12-17 05:25:46 +00:00
if __name__ == ' __main__ ' :
start ( )