From 1fed584f3a7a37a7b7631cc4709477580971ad88 Mon Sep 17 00:00:00 2001 From: Blake Wingard Date: Mon, 4 Nov 2024 12:13:25 -0600 Subject: [PATCH 1/3] Restores console state to original colors --- clip_lin.py | 3 ++- clip_win.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/clip_lin.py b/clip_lin.py index 935ff24..e09b0ca 100644 --- a/clip_lin.py +++ b/clip_lin.py @@ -117,6 +117,7 @@ PLACEHOLDER_CHAR = '.' PLACEHOLDER_COLOR = F"{COLORS['F_BLK']}{COLORS['B_BLK']}" PLACEHOLDER = F'{PLACEHOLDER_COLOR}{PLACEHOLDER_CHAR}' +RESTORE_STATE = '\033[0m' # CURSOR ANSI ESCAPE PATTERNS CURSOR_UP = '\033[1A' # moves cursor up one line @@ -364,7 +365,7 @@ def run(self): self.play_clip() self.loop_clip() sys.stdout.write(CURSOR_ON) - sys.stdout.write(COLORS['F_WHT'] + COLORS['B_BLK']) + sys.stdout.write(RESTORE_STATE) def clippy(path, speed, cycles, color): diff --git a/clip_win.py b/clip_win.py index 5b8b02c..b7490ac 100644 --- a/clip_win.py +++ b/clip_win.py @@ -117,6 +117,7 @@ PLACEHOLDER_CHAR = '.' PLACEHOLDER_COLOR = F"{COLORS['F_BLK']}{COLORS['B_BLK']}" PLACEHOLDER = F'{PLACEHOLDER_COLOR}{PLACEHOLDER_CHAR}' +RESTORE_STATE = '\033[0m' # CURSOR ANSI ESCAPE PATTERNS CURSOR_UP = '\033[1A' # moves cursor up one line @@ -362,7 +363,7 @@ def run(self): self.play_clip() self.loop_clip() sys.stdout.write(CURSOR_ON) - sys.stdout.write(COLORS['F_WHT'] + COLORS['B_BLK']) + sys.stdout.write(RESTORE_STATE) def clippy(path, speed, cycles, color): From 0c12be42fe52782f04dd359d2755538c3cf22164 Mon Sep 17 00:00:00 2001 From: Blake Wingard Date: Tue, 5 Nov 2024 15:08:00 -0600 Subject: [PATCH 2/3] Changed the code to be operating system agnostic. The reason the code was split was due to difference in paths and system commands. The pathing issue was solved by using the os.path module. The system commands only occur once, and can be differentiated by checking the os.name. --- clip_win.py => clip.py | 761 +++++++++++++++++++++-------------------- clip_lin.py | 379 -------------------- 2 files changed, 382 insertions(+), 758 deletions(-) rename clip_win.py => clip.py (90%) delete mode 100644 clip_lin.py diff --git a/clip_win.py b/clip.py similarity index 90% rename from clip_win.py rename to clip.py index b7490ac..adb4b21 100644 --- a/clip_win.py +++ b/clip.py @@ -1,379 +1,382 @@ -""" -DO NOT DELETE THE AUTHOR COPYRIGHT -©Connor Talbot 2021 - https://github.com/con-dog/clippy - -clip.py - Animate and color a given directory of .txt files. - -The text files in the directory provided should be 'frames' in a sequence -to give the impression of animation. For steps to make your own, visit the -GitHub link ReadMe. Its very easy! - -Example: -In the directory: "clip/art/sea/boats/small_boat_1" there are a few text files -under a subfolder called "ascii": -small_boat_1a, small_boat_1b, small_boat_1c, ... small_boat_1f etc - - clip - ├───art - ├───animals - ... - ... - └───sea - └───boats - └───small_boat_1 - ├───ascii - | └───small_boat_1a.txt - | └───small_boat_1b.txt - | ... - | ... - | └───small_boat_1h.txt - └───color - -Stepping through these clearly shows a boat (and a bird) moving frame by frame - -small_boat_1a.txt ------------------ -................. -........~...v.... -.........../|.... -.....v..../_|__.. -.........\-----/. -~~~~~~~~~`~~~~~~' - -small_boat_1b.txt ------------------ -................. -.......~...v..... -........../|...\, -....v..../_|__... -........\-----/.. -~~~~~~~~`~~~~~~'~ - -..... -..... - -small_boat_1h.txt ------------------ -... /`\.......... -...v............. -../|............. -./_|__........... -\-----/.......... -`~~~~~~'~~~~~~~~~ - - -Any art samples you create should be of a frame-by-frame nature as above ordered -alphabetically with lowercase lettering. Frame play order is dictated by -this alphabetical order. - -All files shall be saved to a relevant directory under the "art" directory in -the repo. - -Note that you can also color in your art, but you have to create another txt -file in another subfolder called "color" that holds the color mappings to -accompany the art file for each frame eg: -small_boat_1a.txt, small_boat_1a_color.txt, .... etc -'' - -For ASCII art ideas visit https://www.asciiart.eu/ and credit the original -author if copying -""" - -import argparse -from collections import Counter -from contextlib import ExitStack -import glob -import os -import re -import sys -import time - -# COLORS: FOREGROUND = F, BACKGROUND = B, Value = ANSI value -COLORS = { - 'F_BLK': '\033[30m', 'B_BLK': '\033[40m', # BLACK - 'F_RED': '\033[31m', 'B_RED': '\033[41m', # RED - 'F_GRN': '\033[32m', 'B_GRN': '\033[42m', # GREEN - 'F_YLW': '\033[33m', 'B_YLW': '\033[43m', # YELLOW - 'F_BLU': '\033[34m', 'B_BLU': '\033[44m', # BLUE - 'F_MGT': '\033[35m', 'B_MGT': '\033[45m', # MAGENTA - 'F_CYA': '\033[36m', 'B_CYA': '\033[46m', # CYAN - 'F_WHT': '\033[37m', 'B_WHT': '\033[47m', # WHITE - 'F_CLP': '\033[38;5;68m', 'B_CLP': '\033[48;5;68m', # CLIPPY - 'F_PYT': '\033[38;5;33m', 'B_PYT': '\033[48;5;33m', - 'F_BWN': '\033[38;5;130m', 'B_BWN': '\033[48;5;130m', # BROWN - 'F_GRY': '\033[38;5;153m', 'B_GRY': '\033[48;5;153m', # GRAY - 'F_TRQ': '\033[38;5;50m', 'B_TRQ': '\033[48;5;50m', # TURQUOISE - 'F_NVY': '\033[38;5;33m', 'B_NVY': '\033[48;5;33m', # NAVY - 'F_STN': '\033[38;5;153m', 'B_STN': '\033[48;5;153m', # STONE - 'F_MRN': '\033[38;5;160m', 'B_MRN': '\033[48;5;160m', # MORNING - 'F_ONG': '\033[38;5;202m', 'B_ONG': '\033[48;5;202m', # ORANGE - 'F_DSK': '\033[38;5;203m', 'B_DSK': '\033[48;5;203m', # DUSK - 'F_SND': '\033[38;5;229m', 'B_SND': '\033[48;5;229m', # SAND -} - -# DEFAULT COLORS AND PLACEHOLDER CHARACTER -DEFAULT_FG = COLORS['F_WHT'] -DEFAULT_BG = COLORS['B_BLK'] -PLACEHOLDER_CHAR = '.' -PLACEHOLDER_COLOR = F"{COLORS['F_BLK']}{COLORS['B_BLK']}" -PLACEHOLDER = F'{PLACEHOLDER_COLOR}{PLACEHOLDER_CHAR}' -RESTORE_STATE = '\033[0m' - -# CURSOR ANSI ESCAPE PATTERNS -CURSOR_UP = '\033[1A' # moves cursor up one line -CURSOR_DOWN = '\033[1B' # moves cursor up one line -CURSOR_RESET = '\033[u' # resets the cursor -CURSOR_OFF = '\033[?25l' # makes cursor invisible -CURSOR_ON = '\033[?25h' # makes cursor visible -CURSOR_SAVE_POS = '\033[s' # saves cursor position -CURSOR_RESTORE_POS = '\033[u' # returns cursor to last saved position - - -def make_cli_parser(): - """Make the modules default argparser""" - parser = argparse.ArgumentParser( - description='Animate and color ASCII art in the cli', - usage='use "%(prog)s --help" for more information', - formatter_class=argparse.RawTextHelpFormatter - ) - - parser.add_argument( - 'path', metavar='path', type=str, - help="""If your folder is 'small_boat_1', then you would pass: - -art/sea/boats/small_boat_1 - -eg: Directory structure of clippy is like so: - - C:. - └───art - ├───animals - ├───buildings - │ ├───castles - │ │ └───castle_1 - │ └───houses - │ └───small_home_1 - ... - ... - ... - └───sea - └───boats - └───small_boat_1 - ├───ascii - └───color - -""" - ) - - parser.add_argument( - 'speed', metavar='speed', type=int, help='the play speed from 1-100' - ) - - parser.add_argument( - 'cycles', metavar='cycles', type=int, help='the number of times to ' - 'cycle the animation from 1-1000' - ) - - parser.add_argument( - '-c', '--color', dest='color', action='store_true', - help='pass this flag to color the ASCII art' - ) - - parser.set_defaults(color=False) - args = parser.parse_args() - return args - - -class ClipException(Exception): - """Raise Exception if Clip class methods are misused""" - pass - - -class Clip: - """A class to manage all aspects of a clip.""" - def __init__(self, source_folder, play_speed, play_cycles, color=False): - """Initialize instance of Tile""" - os.system('color') # Required to work, enables ANSI codes - os.system('cls') # Clear cli - sys.stdout.write(CURSOR_OFF) - self._source_folder = source_folder - self.play_speed = 5.1 - (play_speed/20) - self.play_cycles = play_cycles - self._color = color - ascii_sub = f'{self.source_folder}\\ascii' - color_sub = f'{self.source_folder}\color' - if not os.path.isdir(ascii_sub): - raise ClipException(""" - Your folder specified by path, must contain a subfolder - called 'ascii'. This ascii subfolder must contain at least - 1 txt file. Your folder hierarchy should look similar to: - - C:. - └───art - ├───animals - ├───buildings - │ └───castles - ... └───my_folder - └───ascii - └───my_art_1.txt - └───my_art_2.txt - ... - ... - └───my_art_n.txt - - """) - if not isinstance(self.play_cycles, int): - raise ClipException('play cycles must be an integer') - if (self.play_cycles < 1) or (self.play_cycles > 1000): - raise ClipException('play cycles must be an integer from 1-1000') - if not isinstance(play_speed, int): - raise ClipException('Speed must be an integer from 1-100') - if (play_speed < 1) or (play_speed > 100): - raise ClipException('Speed must be an integer from 1-100') - if (not isinstance(self._color, bool)): - raise ClipException('colorless by default - pass "True" for color') - if color: - if not os.path.isdir(color_sub): - raise ClipException(""" - When passing color flag, folder specified by path, must - contain a subfolder called 'color'. - """) - if len(os.listdir(ascii_sub)) != len(os.listdir(color_sub)): - raise ClipException(""" - When passing color flag, the subfolders 'ascii' and - 'color' must contain an equal number of txt files to - ensure color mappings are correct. - """) - - @property - def source_folder(self): - """Instance read only property""" - return self._source_folder - - @property - def color(self): - """Instance read only property""" - return self._color - - def get_frames(self): - """Get all the frame art from the ascii sub-directory in alphabetical - order.""" - # get all /ascii/*.txt files in dir. These are the ascii frames - filenames = glob.glob(f"{self.source_folder}{'./ascii./*.txt'}") - with ExitStack() as stack: # dynamically handle multi file opens/closes - self.ascii_files = [stack.enter_context(open(f)) for f in filenames] - if self.ascii_files: - self.frames = [] - for f in self.ascii_files: # iterate over the frame files list - frame = [] - lines = f.read().splitlines() - for line in lines: - row = list(line) # becomes a [row][column] structure - frame.append(row) - self.frames.append(frame) - - def set_char_base_color(self): - """Loop over each frames characters, and set them to defaults""" - for f, frame in enumerate(self.frames): - for r, row in enumerate(frame): - for c, char in enumerate(self.frames[f][r]): - if char != PLACEHOLDER_CHAR: - self.frames[f][r][c] = f'{DEFAULT_FG}{DEFAULT_BG}{char}' - else: - self.frames[f][r][c] = PLACEHOLDER - - def get_frame_color_maps(self): - """Get all the color mappings from the color sub-directory in - alphabetical order.""" - # get all /color/*.txt files in dir. These are the color mappings - filenames = glob.glob(f"{self.source_folder}{'./color./*.txt'}") - with ExitStack() as stack: # dynamically handle multi file opens/closes - self.color_files = [stack.enter_context(open(f)) for f in filenames] - if self.color_files: - self.frame_color_maps = [] - for f in self.color_files: # iterate over the frame files list - lines = f.read().splitlines() - # Remove any empty lines. Required for regex - frame_color_map = list(line for line in lines if line) - self.frame_color_maps.append(frame_color_map) - else: - raise ClipException('Path must include txt files!') - - def color_cells(self): - """Color the cells by mapping the frames color map to that frames - characters""" - map_regex = re.compile(r''' - \[(\d*)\] # group 1: Match [digit/s] for row - \[(\d*)\] # group 2: Match [digit/s] for column - [\s=\s]* # get everything around equals sign - (\w*[^,]) # group 3: match the 1st color (not optional) - (,[\s]*(\w*))? # group 5: match an optional second color - ''', re.VERBOSE - ) - # need the index of the frame_color_map to map to the corresponding - # frame in self.frames - for frame_index, frame_color_map in enumerate(self.frame_color_maps): - char_update_operations = [] - rows = [] - for char_color_map in frame_color_map: - mo = map_regex.search(char_color_map) - row = int(mo.group(1)) - column = int(mo.group(2)) - color_1_text = mo.group(3) - color_2_text = mo.group(5) - # just get the ASCII character, not its color! - char = self.frames[frame_index][row][column][-1] - - # map colors string to COLORS variables constants values - color_1 = COLORS.get(color_1_text, '') - color_2 = COLORS.get(color_2_text, '') - - updated_char = f"{color_1}{color_2}{char}" - self.frames[frame_index][row][column] = updated_char - - def play_clip(self): - """Loop through a clips frames to display it to screen at the given - speed""" - sys.stdout.flush() - for frame in self.frames: - for row in frame: # Iterate over each frames rows - for char in row: - sys.stdout.write(char) - sys.stdout.write('\n') # newline after all cells in row shown - sys.stdout.write(CURSOR_SAVE_POS) # save cursor position - # Move cursor back to top of display and draw next frame - sys.stdout.write(CURSOR_UP*len(frame)) - time.sleep(self.play_speed) - - def loop_clip(self): - """Loop through the clip the given number of cycles""" - while self.play_cycles > 1: - self.play_clip() - self.play_cycles -= 1 - sys.stdout.write(CURSOR_RESTORE_POS) # restore cursor to saved position - - def run(self): - """Call instance functions to animate the frames to the screen and cycle - the animation""" - self.get_frames() - self.set_char_base_color() - if self.color: - self.get_frame_color_maps() - self.color_cells() - self.play_clip() - self.loop_clip() - sys.stdout.write(CURSOR_ON) - sys.stdout.write(RESTORE_STATE) - - -def clippy(path, speed, cycles, color): - """main function for module""" - clip = Clip(path, speed, cycles, color) - clip.run() - - -if __name__ == '__main__': - args = make_cli_parser() - clippy(args.path, args.speed, args.cycles, args.color) - - +r""" +DO NOT DELETE THE AUTHOR COPYRIGHT +©Connor Talbot 2021 - https://github.com/con-dog/clippy + +clip.py - Animate and color a given directory of .txt files. + +The text files in the directory provided should be 'frames' in a sequence +to give the impression of animation. For steps to make your own, visit the +GitHub link ReadMe. Its very easy! + +Example: +In the directory: "clip/art/sea/boats/small_boat_1" there are a few text files +under a subfolder called "ascii": +small_boat_1a, small_boat_1b, small_boat_1c, ... small_boat_1f etc + + clip + ├───art + ├───animals + ... + ... + └───sea + └───boats + └───small_boat_1 + ├───ascii + | └───small_boat_1a.txt + | └───small_boat_1b.txt + | ... + | ... + | └───small_boat_1h.txt + └───color + +Stepping through these clearly shows a boat (and a bird) moving frame by frame + +small_boat_1a.txt +----------------- +................. +........~...v.... +.........../|.... +.....v..../_|__.. +.........\-----/. +~~~~~~~~~`~~~~~~' + +small_boat_1b.txt +----------------- +................. +.......~...v..... +........../|...\, +....v..../_|__... +........\-----/.. +~~~~~~~~`~~~~~~'~ + +..... +..... + +small_boat_1h.txt +----------------- +... /`\.......... +...v............. +../|............. +./_|__........... +\-----/.......... +`~~~~~~'~~~~~~~~~ + + +Any art samples you create should be of a frame-by-frame nature as above ordered +alphabetically with lowercase lettering. Frame play order is dictated by +this alphabetical order. + +All files shall be saved to a relevant directory under the "art" directory in +the repo. + +Note that you can also color in your art, but you have to create another txt +file in another subfolder called "color" that holds the color mappings to +accompany the art file for each frame eg: +small_boat_1a.txt, small_boat_1a_color.txt, .... etc +'' + +For ASCII art ideas visit https://www.asciiart.eu/ and credit the original +author if copying +""" + +import argparse +from contextlib import ExitStack +import glob +import os +import re +import sys +import time + +# COLORS: FOREGROUND = F, BACKGROUND = B, Value = ANSI value +COLORS = { + 'F_BLK': '\033[30m', 'B_BLK': '\033[40m', # BLACK + 'F_RED': '\033[31m', 'B_RED': '\033[41m', # RED + 'F_GRN': '\033[32m', 'B_GRN': '\033[42m', # GREEN + 'F_YLW': '\033[33m', 'B_YLW': '\033[43m', # YELLOW + 'F_BLU': '\033[34m', 'B_BLU': '\033[44m', # BLUE + 'F_MGT': '\033[35m', 'B_MGT': '\033[45m', # MAGENTA + 'F_CYA': '\033[36m', 'B_CYA': '\033[46m', # CYAN + 'F_WHT': '\033[37m', 'B_WHT': '\033[47m', # WHITE + 'F_CLP': '\033[38;5;68m', 'B_CLP': '\033[48;5;68m', # CLIPPY + 'F_PYT': '\033[38;5;33m', 'B_PYT': '\033[48;5;33m', + 'F_BWN': '\033[38;5;130m', 'B_BWN': '\033[48;5;130m', # BROWN + 'F_GRY': '\033[38;5;153m', 'B_GRY': '\033[48;5;153m', # GRAY + 'F_TRQ': '\033[38;5;50m', 'B_TRQ': '\033[48;5;50m', # TURQUOISE + 'F_NVY': '\033[38;5;33m', 'B_NVY': '\033[48;5;33m', # NAVY + 'F_STN': '\033[38;5;153m', 'B_STN': '\033[48;5;153m', # STONE + 'F_MRN': '\033[38;5;160m', 'B_MRN': '\033[48;5;160m', # MORNING + 'F_ONG': '\033[38;5;202m', 'B_ONG': '\033[48;5;202m', # ORANGE + 'F_DSK': '\033[38;5;203m', 'B_DSK': '\033[48;5;203m', # DUSK + 'F_SND': '\033[38;5;229m', 'B_SND': '\033[48;5;229m', # SAND +} + +# DEFAULT COLORS AND PLACEHOLDER CHARACTER +DEFAULT_FG = COLORS['F_WHT'] +DEFAULT_BG = COLORS['B_BLK'] +PLACEHOLDER_CHAR = '.' +PLACEHOLDER_COLOR = F"{COLORS['F_BLK']}{COLORS['B_BLK']}" +PLACEHOLDER = F'{PLACEHOLDER_COLOR}{PLACEHOLDER_CHAR}' +RESTORE_STATE = '\033[0m' + +# CURSOR ANSI ESCAPE PATTERNS +CURSOR_UP = '\033[1A' # moves cursor up one line +CURSOR_DOWN = '\033[1B' # moves cursor up one line +CURSOR_RESET = '\033[u' # resets the cursor +CURSOR_OFF = '\033[?25l' # makes cursor invisible +CURSOR_ON = '\033[?25h' # makes cursor visible +CURSOR_SAVE_POS = '\033[s' # saves cursor position +CURSOR_RESTORE_POS = '\033[u' # returns cursor to last saved position + + +def make_cli_parser(): + """Make the modules default argparser""" + parser = argparse.ArgumentParser( + description='Animate and color ASCII art in the cli', + usage='use "%(prog)s --help" for more information', + formatter_class=argparse.RawTextHelpFormatter + ) + + parser.add_argument( + 'path', metavar='path', type=str, + help="""If your folder is 'small_boat_1', then you would pass: + +art/sea/boats/small_boat_1 + +eg: Directory structure of clippy is like so: + + C:. + └───art + ├───animals + ├───buildings + │ ├───castles + │ │ └───castle_1 + │ └───houses + │ └───small_home_1 + ... + ... + ... + └───sea + └───boats + └───small_boat_1 + ├───ascii + └───color + +""" + ) + + parser.add_argument( + 'speed', metavar='speed', type=int, help='the play speed from 1-100' + ) + + parser.add_argument( + 'cycles', metavar='cycles', type=int, help='the number of times to ' + 'cycle the animation from 1-1000' + ) + + parser.add_argument( + '-c', '--color', dest='color', action='store_true', + help='pass this flag to color the ASCII art' + ) + + parser.set_defaults(color=False) + args = parser.parse_args() + return args + + +class ClipException(Exception): + """Raise Exception if Clip class methods are misused""" + pass + + +class Clip: + """A class to manage all aspects of a clip.""" + + def __init__(self, source_folder, play_speed, play_cycles, color=False): + """Initialize instance of Tile""" + if os.name == 'nt': + os.system('color') # Required to work, enables ANSI codes + os.system('cls') # Clear cli + else: + os.system('clear') + sys.stdout.write(CURSOR_OFF) + self.ascii_files = None + self.frames = [] + self.color_files = None + self.frame_color_maps = [] + self._source_folder = source_folder + self.play_speed = 5.1 - (play_speed / 20) + self.play_cycles = play_cycles + self._color = color + self.ascii_sub = os.path.join(self.source_folder, 'ascii') + self.color_sub = os.path.join(self.source_folder, 'color') + if not os.path.isdir(self.ascii_sub): + raise ClipException(""" + Your folder specified by path, must contain a subfolder + called 'ascii'. This ascii subfolder must contain at least + 1 txt file. Your folder hierarchy should look similar to: + + C:. + └───art + ├───animals + ├───buildings + │ └───castles + ... └───my_folder + └───ascii + └───my_art_1.txt + └───my_art_2.txt + ... + ... + └───my_art_n.txt + + """) + if not isinstance(self.play_cycles, int): + raise ClipException('play cycles must be an integer') + if (self.play_cycles < 1) or (self.play_cycles > 1000): + raise ClipException('play cycles must be an integer from 1-1000') + if not isinstance(play_speed, int): + raise ClipException('Speed must be an integer from 1-100') + if (play_speed < 1) or (play_speed > 100): + raise ClipException('Speed must be an integer from 1-100') + if (not isinstance(self._color, bool)): + raise ClipException('colorless by default - pass "True" for color') + if color: + if not os.path.isdir(self.color_sub): + raise ClipException(""" + When passing color flag, folder specified by path, must + contain a subfolder called 'color'. + """) + if len(os.listdir(self.ascii_sub)) != len(os.listdir(self.color_sub)): + raise ClipException(""" + When passing color flag, the subfolders 'ascii' and + 'color' must contain an equal number of txt files to + ensure color mappings are correct. + """) + + @property + def source_folder(self): + """Instance read only property""" + return self._source_folder + + @property + def color(self): + """Instance read only property""" + return self._color + + def get_frames(self): + """Get all the frame art from the ascii sub-directory in alphabetical + order.""" + # get all /ascii/*.txt files in dir. These are the ascii frames + filenames = glob.glob(os.path.join(self.ascii_sub, '*.txt')) + with ExitStack() as stack: # dynamically handle multi file opens/closes + self.ascii_files = [stack.enter_context(open(f)) for f in filenames] + if self.ascii_files: + self.frames = [] + for f in self.ascii_files: # iterate over the frame files list + frame = [] + lines = f.read().splitlines() + for line in lines: + row = list(line) # becomes a [row][column] structure + frame.append(row) + self.frames.append(frame) + + def set_char_base_color(self): + """Loop over each frames characters, and set them to defaults""" + for f, frame in enumerate(self.frames): + for r, row in enumerate(frame): + for c, char in enumerate(self.frames[f][r]): + if char != PLACEHOLDER_CHAR: + self.frames[f][r][c] = f'{DEFAULT_FG}{DEFAULT_BG}{char}' + else: + self.frames[f][r][c] = PLACEHOLDER + + def get_frame_color_maps(self): + """Get all the color mappings from the color sub-directory in + alphabetical order.""" + # get all /color/*.txt files in dir. These are the color mappings + filenames = glob.glob(os.path.join(self.color_sub, '*.txt')) + with ExitStack() as stack: # dynamically handle multi file opens/closes + self.color_files = [stack.enter_context(open(f)) for f in filenames] + if self.color_files: + self.frame_color_maps = [] + for f in self.color_files: # iterate over the frame files list + lines = f.read().splitlines() + # Remove any empty lines. Required for regex + frame_color_map = list(line for line in lines if line) + self.frame_color_maps.append(frame_color_map) + else: + raise ClipException('Path must include txt files!') + + def color_cells(self): + """Color the cells by mapping the frames color map to that frames + characters""" + map_regex = re.compile(r''' + \[(\d*)\] # group 1: Match [digit/s] for row + \[(\d*)\] # group 2: Match [digit/s] for column + [\s=\s]* # get everything around equals sign + (\w*[^,]) # group 3: match the 1st color (not optional) + (,[\s]*(\w*))? # group 5: match an optional second color + ''', re.VERBOSE + ) + # need the index of the frame_color_map to map to the corresponding + # frame in self.frames + for frame_index, frame_color_map in enumerate(self.frame_color_maps): + for char_color_map in frame_color_map: + mo = map_regex.search(char_color_map) + row = int(mo.group(1)) + column = int(mo.group(2)) + color_1_text = mo.group(3) + color_2_text = mo.group(5) + # just get the ASCII character, not its color! + char = self.frames[frame_index][row][column][-1] + + # map colors string to COLORS variables constants values + color_1 = COLORS.get(color_1_text, '') + color_2 = COLORS.get(color_2_text, '') + + updated_char = f"{color_1}{color_2}{char}" + self.frames[frame_index][row][column] = updated_char + + def play_clip(self): + """Loop through a clips frames to display it to screen at the given + speed""" + sys.stdout.flush() + for frame in self.frames: + for row in frame: # Iterate over each frames rows + for char in row: + sys.stdout.write(char) + sys.stdout.write('\n') # newline after all cells in row shown + sys.stdout.write(CURSOR_SAVE_POS) # save cursor position + # Move cursor back to top of display and draw next frame + sys.stdout.write(CURSOR_UP * len(frame)) + time.sleep(self.play_speed) + + def loop_clip(self): + """Loop through the clip the given number of cycles""" + while self.play_cycles > 1: + self.play_clip() + self.play_cycles -= 1 + sys.stdout.write(CURSOR_RESTORE_POS) # restore cursor to saved position + + def run(self): + """Call instance functions to animate the frames to the screen and cycle + the animation""" + self.get_frames() + self.set_char_base_color() + if self.color: + self.get_frame_color_maps() + self.color_cells() + self.play_clip() + self.loop_clip() + sys.stdout.write(CURSOR_ON) + sys.stdout.write(RESTORE_STATE) + + +def clippy(path, speed, cycles, color): + """main function for module""" + clip = Clip(path, speed, cycles, color) + clip.run() + + +if __name__ == '__main__': + args = make_cli_parser() + clippy(args.path, args.speed, args.cycles, args.color) diff --git a/clip_lin.py b/clip_lin.py deleted file mode 100644 index e09b0ca..0000000 --- a/clip_lin.py +++ /dev/null @@ -1,379 +0,0 @@ -""" -DO NOT DELETE THE AUTHOR COPYRIGHT -©Connor Talbot 2021 - https://github.com/con-dog/clippy - -clip.py - Animate and color a given directory of .txt files. - -The text files in the directory provided should be 'frames' in a sequence -to give the impression of animation. For steps to make your own, visit the -GitHub link ReadMe. Its very easy! - -Example: -In the directory: "clip/art/sea/boats/small_boat_1" there are a few text files -under a subfolder called "ascii": -small_boat_1a, small_boat_1b, small_boat_1c, ... small_boat_1f etc - - clip - ├───art - ├───animals - ... - ... - └───sea - └───boats - └───small_boat_1 - ├───ascii - | └───small_boat_1a.txt - | └───small_boat_1b.txt - | ... - | ... - | └───small_boat_1h.txt - └───color - -Stepping through these clearly shows a boat (and a bird) moving frame by frame - -small_boat_1a.txt ------------------ -................. -........~...v.... -.........../|.... -.....v..../_|__.. -.........\-----/. -~~~~~~~~~`~~~~~~' - -small_boat_1b.txt ------------------ -................. -.......~...v..... -........../|...\, -....v..../_|__... -........\-----/.. -~~~~~~~~`~~~~~~'~ - -..... -..... - -small_boat_1h.txt ------------------ -... /`\.......... -...v............. -../|............. -./_|__........... -\-----/.......... -`~~~~~~'~~~~~~~~~ - - -Any art samples you create should be of a frame-by-frame nature as above ordered -alphabetically with lowercase lettering. Frame play order is dictated by -this alphabetical order. - -All files shall be saved to a relevant directory under the "art" directory in -the repo. - -Note that you can also color in your art, but you have to create another txt -file in another subfolder called "color" that holds the color mappings to -accompany the art file for each frame eg: -small_boat_1a.txt, small_boat_1a_color.txt, .... etc -'' - -For ASCII art ideas visit https://www.asciiart.eu/ and credit the original -author if copying -""" - -import argparse -from collections import Counter -from contextlib import ExitStack -import glob -import os -import re -import sys -import time - -# COLORS: FOREGROUND = F, BACKGROUND = B, Value = ANSI value -COLORS = { - 'F_BLK': '\033[30m', 'B_BLK': '\033[40m', # BLACK - 'F_RED': '\033[31m', 'B_RED': '\033[41m', # RED - 'F_GRN': '\033[32m', 'B_GRN': '\033[42m', # GREEN - 'F_YLW': '\033[33m', 'B_YLW': '\033[43m', # YELLOW - 'F_BLU': '\033[34m', 'B_BLU': '\033[44m', # BLUE - 'F_MGT': '\033[35m', 'B_MGT': '\033[45m', # MAGENTA - 'F_CYA': '\033[36m', 'B_CYA': '\033[46m', # CYAN - 'F_WHT': '\033[37m', 'B_WHT': '\033[47m', # WHITE - 'F_CLP': '\033[38;5;68m', 'B_CLP': '\033[48;5;68m', # CLIPPY - 'F_PYT': '\033[38;5;33m', 'B_PYT': '\033[48;5;33m', - 'F_BWN': '\033[38;5;130m', 'B_BWN': '\033[48;5;130m', # BROWN - 'F_GRY': '\033[38;5;153m', 'B_GRY': '\033[48;5;153m', # GRAY - 'F_TRQ': '\033[38;5;50m', 'B_TRQ': '\033[48;5;50m', # TURQUOISE - 'F_NVY': '\033[38;5;33m', 'B_NVY': '\033[48;5;33m', # NAVY - 'F_STN': '\033[38;5;153m', 'B_STN': '\033[48;5;153m', # STONE - 'F_MRN': '\033[38;5;160m', 'B_MRN': '\033[48;5;160m', # MORNING - 'F_ONG': '\033[38;5;202m', 'B_ONG': '\033[48;5;202m', # ORANGE - 'F_DSK': '\033[38;5;203m', 'B_DSK': '\033[48;5;203m', # DUSK - 'F_SND': '\033[38;5;229m', 'B_SND': '\033[48;5;229m', # SAND -} - -# DEFAULT COLORS AND PLACEHOLDER CHARACTER -DEFAULT_FG = COLORS['F_WHT'] -DEFAULT_BG = COLORS['B_BLK'] -PLACEHOLDER_CHAR = '.' -PLACEHOLDER_COLOR = F"{COLORS['F_BLK']}{COLORS['B_BLK']}" -PLACEHOLDER = F'{PLACEHOLDER_COLOR}{PLACEHOLDER_CHAR}' -RESTORE_STATE = '\033[0m' - -# CURSOR ANSI ESCAPE PATTERNS -CURSOR_UP = '\033[1A' # moves cursor up one line -CURSOR_DOWN = '\033[1B' # moves cursor up one line -CURSOR_RESET = '\033[u' # resets the cursor -CURSOR_OFF = '\033[?25l' # makes cursor invisible -CURSOR_ON = '\033[?25h'# makes cursor visible -CURSOR_SAVE_POS = '\033[s' # saves cursor position -CURSOR_RESTORE_POS = '\033[u'# returns cursor to last saved position - -def make_cli_parser(): - """Make the modules default argparser""" - parser = argparse.ArgumentParser( - description='Animate and color ASCII art in the cli', - usage='use "%(prog)s --help" for more information', - formatter_class=argparse.RawTextHelpFormatter - ) - - parser.add_argument( - 'path', metavar='path', type=str, - help="""If your folder is 'small_boat_1', then you would pass: - -art/sea/boats/small_boat_1 - -eg: Directory structure of clippy is like so: - - C:. - └───art - ├───animals - ├───buildings - │ ├───castles - │ │ └───castle_1 - │ └───houses - │ └───small_home_1 - ... - ... - ... - └───sea - └───boats - └───small_boat_1 - ├───ascii - └───color - -""" - ) - - parser.add_argument( - 'speed', metavar='speed', type=int, help='the play speed from 1-100' - ) - - parser.add_argument( - 'cycles', metavar='cycles', type=int, help='the number of times to ' - 'cycle the animation from 1-1000' - ) - - parser.add_argument( - '-c', '--color', dest='color', action='store_true', - help='pass this flag to color the ASCII art' - ) - - parser.set_defaults(color=False) - args = parser.parse_args() - return args - - -class ClipException(Exception): - """Raise Exception if Clip class methods are misused""" - pass - - -class Clip: - """A class to manage all aspects of a clip.""" - def __init__(self, source_folder, play_speed, play_cycles, color=False): - """Initialize instance of Tile""" - # os.system('color')# DOES NOT WORK IN LINUX/UNIX BASED SYSTEMS - os.system('clear')# Clear cli - sys.stdout.write(CURSOR_OFF) - self.ascii_files = None - self.frames = [] - self.color_files = None - self.frame_color_maps = [] - self._source_folder = source_folder - self.play_speed = 5.1 - (play_speed/20) - self.play_cycles = play_cycles - self._color = color - ascii_sub = f'{self.source_folder}/ascii' - color_sub = f'{self.source_folder}/color' - if not os.path.isdir(ascii_sub): - raise ClipException(""" - Your folder specified by path, must contain a subfolder - called 'ascii'. This ascii subfolder must contain at least - 1 txt file. Your folder hierarchy should look similar to: - - C:. - └───art - ├───animals - ├───buildings - │ └───castles - ... └───my_folder - └───ascii - └───my_art_1.txt - └───my_art_2.txt - ... - ... - └───my_art_n.txt - - """) - if not isinstance(self.play_cycles, int): - raise ClipException('play cycles must be an integer') - if (self.play_cycles < 1) or (self.play_cycles > 1000): - raise ClipException('play cycles must be an integer from 1-1000') - if not isinstance(play_speed, int): - raise ClipException('Speed must be an integer from 1-100') - if (play_speed < 1) or (play_speed > 100): - raise ClipException('Speed must be an integer from 1-100') - if (not isinstance(self._color, bool)): - raise ClipException('colorless by default - pass "True" for color') - if color: - if not os.path.isdir(color_sub): - raise ClipException(""" - When passing color flag, folder specified by path, must - contain a subfolder called 'color'. - """) - if len(os.listdir(ascii_sub)) != len(os.listdir(color_sub)): - raise ClipException(""" - When passing color flag, the subfolders 'ascii' and - 'color' must contain an equal number of txt files to - ensure color mappings are correct. - """) - - @property - def source_folder(self): - """Instance read only property""" - return self._source_folder - - @property - def color(self): - """Instance read only property""" - return self._color - - def get_frames(self): - """Get all the frame art from the ascii sub-directory in alphabetical - order.""" - # get all /ascii/*.txt files in dir. These are the ascii frames - filenames = glob.glob(f"{self.source_folder}{'/ascii/*.txt'}") - with ExitStack() as stack: # dynamically handle multi file opens/closes - self.ascii_files = [stack.enter_context(open(f)) for f in filenames] - if self.ascii_files: - self.frames = [] - for f in self.ascii_files: # iterate over the frame files list - frame = [] - lines = f.read().splitlines() - for line in lines: - row = list(line) # becomes a [row][column] structure - frame.append(row) - self.frames.append(frame) - - def set_char_base_color(self): - """Loop over each frames characters, and set them to defaults""" - for f, frame in enumerate(self.frames): - for r, row in enumerate(frame): - for c, char in enumerate(self.frames[f][r]): - if char != PLACEHOLDER_CHAR: - self.frames[f][r][c] = f'{DEFAULT_FG}{DEFAULT_BG}{char}' - else: - self.frames[f][r][c] = PLACEHOLDER - - def get_frame_color_maps(self): - """Get all the color mappings from the color sub-directory in - alphabetical order.""" - # get all /color/*.txt files in dir. These are the color mappings - filenames = glob.glob(f"{self.source_folder}{'/color/*.txt'}") - with ExitStack() as stack: # dynamically handle multi file opens/closes - self.color_files = [stack.enter_context(open(f)) for f in filenames] - if self.color_files: - self.frame_color_maps = [] - for f in self.color_files: # iterate over the frame files list - lines = f.read().splitlines() - # Remove any empty lines. Required for regex - frame_color_map = list(line for line in lines if line) - self.frame_color_maps.append(frame_color_map) - else: - raise ClipException('Path must include txt files!') - - def color_cells(self): - """Color the cells by mapping the frames color map to that frames - characters""" - map_regex = re.compile(r''' - \[(\d*)\] # group 1: Match [digit/s] for row - \[(\d*)\] # group 2: Match [digit/s] for column - [\s=\s]* # get everything around equals sign - (\w*[^,]) # group 3: match the 1st color (not optional) - (,[\s]*(\w*))? # group 5: match an optional second color - ''', re.VERBOSE - ) - # need the index of the frame_color_map to map to the corresponding - # frame in self.frames - for frame_index, frame_color_map in enumerate(self.frame_color_maps): - char_update_operations = [] - rows = [] - for char_color_map in frame_color_map: - mo = map_regex.search(char_color_map) - row = int(mo.group(1)) - column = int(mo.group(2)) - color_1_text = mo.group(3) - color_2_text = mo.group(5) - # just get the ASCII character, not its color! - char = self.frames[frame_index][row][column][-1] - - # map colors string to COLORS variables constants values - color_1 = COLORS.get(color_1_text, '') - color_2 = COLORS.get(color_2_text, '') - updated_char = f"{color_1}{color_2}{char}" - self.frames[frame_index][row][column] = updated_char - - def play_clip(self): - """Loop through a clips frames to display it to screen at the given - speed""" - sys.stdout.flush() - for frame in self.frames: - for row in frame: # Iterate over each frames rows - for char in row: - sys.stdout.write(char) - sys.stdout.write('\n') # newline after all cells in row shown - sys.stdout.write(CURSOR_SAVE_POS) # save cursor position - # Move cursor back to top of display and draw next frame - sys.stdout.write(CURSOR_UP*len(frame)) - time.sleep(self.play_speed) - - def loop_clip(self): - """Loop through the clip the given number of cycles""" - while self.play_cycles > 1: - self.play_clip() - self.play_cycles -= 1 - sys.stdout.write(CURSOR_RESTORE_POS)# restore cursor to saved position - - def run(self): - """Call instance functions to animate the frames to the screen and cycle - the animation""" - self.get_frames() - self.set_char_base_color() - if self.color: - self.get_frame_color_maps() - self.color_cells() - self.play_clip() - self.loop_clip() - sys.stdout.write(CURSOR_ON) - sys.stdout.write(RESTORE_STATE) - - -def clippy(path, speed, cycles, color): - """main function for module""" - clip = Clip(path, speed, cycles, color) - clip.run() - - -if __name__ == '__main__': - args = make_cli_parser() - clippy(args.path, args.speed, args.cycles, args.color) From 8b7db8840ce30fa7155bd8b115c73e155b7eaa10 Mon Sep 17 00:00:00 2001 From: Blake Wingard Date: Tue, 5 Nov 2024 15:09:18 -0600 Subject: [PATCH 3/3] Fixed animations The format specified that animation frames should be a folder called ascii. This commit moves the files not in an ascii folder to an ascii folder. --- .../castles/castle_1/{ => ascii}/castle_1a.txt | 12 ++++++------ .../castles/castle_1/{ => ascii}/castle_1b.txt | 12 ++++++------ .../castles/castle_1/ascii}/castle_1c.txt | 12 ++++++------ .../castles/castle_1/ascii}/castle_1d.txt | 12 ++++++------ .../castles/castle_1/{ => ascii}/castle_1e.txt | 12 ++++++------ .../castles/castle_1/{ => ascii}/castle_1f.txt | 12 ++++++------ .../houses/small_home_1/{ => ascii}/house_1a.txt | 12 ++++++------ .../houses/small_home_1/ascii}/house_1b.txt | 12 ++++++------ .../houses/small_home_1/ascii}/house_1c.txt | 12 ++++++------ .../houses/small_home_1/ascii}/house_1d.txt | 12 ++++++------ .../houses/small_home_1/{ => ascii}/house_1e.txt | 12 ++++++------ art/castles/{ => castle_1/ascii}/castle_1a.txt | 12 ++++++------ art/castles/{ => castle_1/ascii}/castle_1b.txt | 12 ++++++------ .../castle_1/ascii}/castle_1c.txt | 12 ++++++------ .../castle_1/ascii}/castle_1d.txt | 12 ++++++------ art/castles/{ => castle_1/ascii}/castle_1e.txt | 12 ++++++------ art/castles/{ => castle_1/ascii}/castle_1f.txt | 12 ++++++------ art/dance/{ => man_1/ascii}/man_1a.txt | 12 ++++++------ art/dance/{ => man_1/ascii}/man_1b.txt | 12 ++++++------ art/dance/{ => man_1/ascii}/man_1c.txt | 12 ++++++------ art/dance/{ => man_1/ascii}/man_1d.txt | 12 ++++++------ art/dance/{ => man_1/ascii}/man_1e.txt | 12 ++++++------ art/dance/{ => man_1/ascii}/man_1f.txt | 12 ++++++------ art/dance/{ => man_1/ascii}/man_1g.txt | 12 ++++++------ art/houses/{ => house_1/ascii}/house_1a.txt | 12 ++++++------ .../house_1/ascii}/house_1b.txt | 12 ++++++------ .../house_1/ascii}/house_1c.txt | 12 ++++++------ .../house_1/ascii}/house_1d.txt | 12 ++++++------ art/houses/{ => house_1/ascii}/house_1e.txt | 12 ++++++------ art/sea/{ => sea_1/ascii}/sea_1a.txt | 10 +++++----- art/sea/{ => sea_1/ascii}/sea_1b.txt | 10 +++++----- art/sea/{ => sea_1/ascii}/sea_1c.txt | 10 +++++----- art/sea/{ => sea_1/ascii}/sea_1d.txt | 10 +++++----- art/sea/{ => sea_1/ascii}/sea_1e.txt | 10 +++++----- art/sea/{ => sea_1/ascii}/sea_1f.txt | 10 +++++----- art/sea/{ => sea_1/ascii}/sea_1g.txt | 10 +++++----- art/sea/{ => sea_1/ascii}/sea_1h.txt | 10 +++++----- 37 files changed, 214 insertions(+), 214 deletions(-) rename art/buildings/castles/castle_1/{ => ascii}/castle_1a.txt (94%) rename art/buildings/castles/castle_1/{ => ascii}/castle_1b.txt (94%) rename art/{castles => buildings/castles/castle_1/ascii}/castle_1c.txt (94%) rename art/{castles => buildings/castles/castle_1/ascii}/castle_1d.txt (94%) rename art/buildings/castles/castle_1/{ => ascii}/castle_1e.txt (94%) rename art/buildings/castles/castle_1/{ => ascii}/castle_1f.txt (94%) rename art/buildings/houses/small_home_1/{ => ascii}/house_1a.txt (95%) rename art/{houses => buildings/houses/small_home_1/ascii}/house_1b.txt (95%) rename art/{houses => buildings/houses/small_home_1/ascii}/house_1c.txt (95%) rename art/{houses => buildings/houses/small_home_1/ascii}/house_1d.txt (95%) rename art/buildings/houses/small_home_1/{ => ascii}/house_1e.txt (95%) rename art/castles/{ => castle_1/ascii}/castle_1a.txt (94%) rename art/castles/{ => castle_1/ascii}/castle_1b.txt (94%) rename art/{buildings/castles/castle_1 => castles/castle_1/ascii}/castle_1c.txt (94%) rename art/{buildings/castles/castle_1 => castles/castle_1/ascii}/castle_1d.txt (94%) rename art/castles/{ => castle_1/ascii}/castle_1e.txt (94%) rename art/castles/{ => castle_1/ascii}/castle_1f.txt (94%) rename art/dance/{ => man_1/ascii}/man_1a.txt (96%) rename art/dance/{ => man_1/ascii}/man_1b.txt (96%) rename art/dance/{ => man_1/ascii}/man_1c.txt (96%) rename art/dance/{ => man_1/ascii}/man_1d.txt (96%) rename art/dance/{ => man_1/ascii}/man_1e.txt (96%) rename art/dance/{ => man_1/ascii}/man_1f.txt (95%) rename art/dance/{ => man_1/ascii}/man_1g.txt (95%) rename art/houses/{ => house_1/ascii}/house_1a.txt (95%) rename art/{buildings/houses/small_home_1 => houses/house_1/ascii}/house_1b.txt (95%) rename art/{buildings/houses/small_home_1 => houses/house_1/ascii}/house_1c.txt (95%) rename art/{buildings/houses/small_home_1 => houses/house_1/ascii}/house_1d.txt (95%) rename art/houses/{ => house_1/ascii}/house_1e.txt (95%) rename art/sea/{ => sea_1/ascii}/sea_1a.txt (95%) rename art/sea/{ => sea_1/ascii}/sea_1b.txt (95%) rename art/sea/{ => sea_1/ascii}/sea_1c.txt (95%) rename art/sea/{ => sea_1/ascii}/sea_1d.txt (95%) rename art/sea/{ => sea_1/ascii}/sea_1e.txt (95%) rename art/sea/{ => sea_1/ascii}/sea_1f.txt (95%) rename art/sea/{ => sea_1/ascii}/sea_1g.txt (95%) rename art/sea/{ => sea_1/ascii}/sea_1h.txt (95%) diff --git a/art/buildings/castles/castle_1/castle_1a.txt b/art/buildings/castles/castle_1/ascii/castle_1a.txt similarity index 94% rename from art/buildings/castles/castle_1/castle_1a.txt rename to art/buildings/castles/castle_1/ascii/castle_1a.txt index 73d9368..dba75ba 100644 --- a/art/buildings/castles/castle_1/castle_1a.txt +++ b/art/buildings/castles/castle_1/ascii/castle_1a.txt @@ -1,6 +1,6 @@ -.......|~...... -....../.\...... -)..|~/___\.|~.. -../_\|::.|/_\.. -..|$||/^\||$|.. -..|nnn|I|nnn|.. +.......|~...... +....../.\...... +)..|~/___\.|~.. +../_\|::.|/_\.. +..|$||/^\||$|.. +..|nnn|I|nnn|.. diff --git a/art/buildings/castles/castle_1/castle_1b.txt b/art/buildings/castles/castle_1/ascii/castle_1b.txt similarity index 94% rename from art/buildings/castles/castle_1/castle_1b.txt rename to art/buildings/castles/castle_1/ascii/castle_1b.txt index 84fed99..299e7bd 100644 --- a/art/buildings/castles/castle_1/castle_1b.txt +++ b/art/buildings/castles/castle_1/ascii/castle_1b.txt @@ -1,6 +1,6 @@ -......~|....... -(x).../.\...... -..~|./___\.|~.. -../_\|::.|/_\.. -..|$||/^\||$|.. -..|nnn|I|nnn|.. +......~|....... +(x).../.\...... +..~|./___\.|~.. +../_\|::.|/_\.. +..|$||/^\||$|.. +..|nnn|I|nnn|.. diff --git a/art/castles/castle_1c.txt b/art/buildings/castles/castle_1/ascii/castle_1c.txt similarity index 94% rename from art/castles/castle_1c.txt rename to art/buildings/castles/castle_1/ascii/castle_1c.txt index c7adfef..9af72eb 100644 --- a/art/castles/castle_1c.txt +++ b/art/buildings/castles/castle_1/ascii/castle_1c.txt @@ -1,6 +1,6 @@ -...(X).|~...... -....../.\...... -..~|./___\~|... -../_\|::.|/_\.. -..|$||/^\||$|.. -..|nnn|I|nnn|.. +...(X).|~...... +....../.\...... +..~|./___\~|... +../_\|::.|/_\.. +..|$||/^\||$|.. +..|nnn|I|nnn|.. diff --git a/art/castles/castle_1d.txt b/art/buildings/castles/castle_1/ascii/castle_1d.txt similarity index 94% rename from art/castles/castle_1d.txt rename to art/buildings/castles/castle_1/ascii/castle_1d.txt index 1d99fb8..cecaa54 100644 --- a/art/castles/castle_1d.txt +++ b/art/buildings/castles/castle_1/ascii/castle_1d.txt @@ -1,6 +1,6 @@ -......~|.(X)... -....../.\...... -...|~/___\.|~.. -../_\|::.|/_\.. -..|$||/^\||$|.. -..|nnn|I|nnn|.. +......~|.(X)... +....../.\...... +...|~/___\.|~.. +../_\|::.|/_\.. +..|$||/^\||$|.. +..|nnn|I|nnn|.. diff --git a/art/buildings/castles/castle_1/castle_1e.txt b/art/buildings/castles/castle_1/ascii/castle_1e.txt similarity index 94% rename from art/buildings/castles/castle_1/castle_1e.txt rename to art/buildings/castles/castle_1/ascii/castle_1e.txt index 9c663c1..2c372f4 100644 --- a/art/buildings/castles/castle_1/castle_1e.txt +++ b/art/buildings/castles/castle_1/ascii/castle_1e.txt @@ -1,6 +1,6 @@ -.*....~|..*.... -...*../.\....(o -..~|./___\.|~.. -../_\|::.|/_\.. -..|$||/^\||$|.. -..|nnn|I|nnn|.. +.*....~|..*.... +...*../.\....(o +..~|./___\.|~.. +../_\|::.|/_\.. +..|$||/^\||$|.. +..|nnn|I|nnn|.. diff --git a/art/buildings/castles/castle_1/castle_1f.txt b/art/buildings/castles/castle_1/ascii/castle_1f.txt similarity index 94% rename from art/buildings/castles/castle_1/castle_1f.txt rename to art/buildings/castles/castle_1/ascii/castle_1f.txt index 164b103..a0883ca 100644 --- a/art/buildings/castles/castle_1/castle_1f.txt +++ b/art/buildings/castles/castle_1/ascii/castle_1f.txt @@ -1,6 +1,6 @@ -...*...|~....*. -.*..*./.\.*...* -...|~/___\~|..( -../_\|::.|/_\.. -..|$||/^\||$|.. -..|nnn|I|nnn|.. +...*...|~....*. +.*..*./.\.*...* +...|~/___\~|..( +../_\|::.|/_\.. +..|$||/^\||$|.. +..|nnn|I|nnn|.. diff --git a/art/buildings/houses/small_home_1/house_1a.txt b/art/buildings/houses/small_home_1/ascii/house_1a.txt similarity index 95% rename from art/buildings/houses/small_home_1/house_1a.txt rename to art/buildings/houses/small_home_1/ascii/house_1a.txt index 3b78919..7773ad5 100644 --- a/art/buildings/houses/small_home_1/house_1a.txt +++ b/art/buildings/houses/small_home_1/ascii/house_1a.txt @@ -1,7 +1,7 @@ -................ -................ -...... ___H_.... -....../_)_)_\... -......|#[]# |... -"""""""""""""""" +................ +................ +...... ___H_.... +....../_)_)_\... +......|#[]# |... +"""""""""""""""" ................ \ No newline at end of file diff --git a/art/houses/house_1b.txt b/art/buildings/houses/small_home_1/ascii/house_1b.txt similarity index 95% rename from art/houses/house_1b.txt rename to art/buildings/houses/small_home_1/ascii/house_1b.txt index f5f9176..831ab53 100644 --- a/art/houses/house_1b.txt +++ b/art/buildings/houses/small_home_1/ascii/house_1b.txt @@ -1,7 +1,7 @@ -................ -..........,..... -...... ___H_.... -....../_)_)_\... -......|#[]# |... -"""""""""""""""" +................ +..........,..... +...... ___H_.... +....../_)_)_\... +......|#[]# |... +"""""""""""""""" ................ \ No newline at end of file diff --git a/art/houses/house_1c.txt b/art/buildings/houses/small_home_1/ascii/house_1c.txt similarity index 95% rename from art/houses/house_1c.txt rename to art/buildings/houses/small_home_1/ascii/house_1c.txt index 6d55827..8765f8c 100644 --- a/art/houses/house_1c.txt +++ b/art/buildings/houses/small_home_1/ascii/house_1c.txt @@ -1,7 +1,7 @@ -................ -..........,`.... -...... ___H_.... -....../_)_)_\... -......|#[]# |... -"""""""""""""""" +................ +..........,`.... +...... ___H_.... +....../_)_)_\... +......|#[]# |... +"""""""""""""""" ................ \ No newline at end of file diff --git a/art/houses/house_1d.txt b/art/buildings/houses/small_home_1/ascii/house_1d.txt similarity index 95% rename from art/houses/house_1d.txt rename to art/buildings/houses/small_home_1/ascii/house_1d.txt index f4575e9..a94729f 100644 --- a/art/houses/house_1d.txt +++ b/art/buildings/houses/small_home_1/ascii/house_1d.txt @@ -1,7 +1,7 @@ -................ -..........,`'... -...... ___H_.... -....../_)_)_\... -......|#[]# |... -"""""""""""""""" +................ +..........,`'... +...... ___H_.... +....../_)_)_\... +......|#[]# |... +"""""""""""""""" ................ \ No newline at end of file diff --git a/art/buildings/houses/small_home_1/house_1e.txt b/art/buildings/houses/small_home_1/ascii/house_1e.txt similarity index 95% rename from art/buildings/houses/small_home_1/house_1e.txt rename to art/buildings/houses/small_home_1/ascii/house_1e.txt index 62f3e3e..f679e49 100644 --- a/art/buildings/houses/small_home_1/house_1e.txt +++ b/art/buildings/houses/small_home_1/ascii/house_1e.txt @@ -1,7 +1,7 @@ -................ -..........,`'~.. -...... ___H_.... -....../_)_)_\... -......|#[]# |... -"""""""""""""""" +................ +..........,`'~.. +...... ___H_.... +....../_)_)_\... +......|#[]# |... +"""""""""""""""" ................ \ No newline at end of file diff --git a/art/castles/castle_1a.txt b/art/castles/castle_1/ascii/castle_1a.txt similarity index 94% rename from art/castles/castle_1a.txt rename to art/castles/castle_1/ascii/castle_1a.txt index 73d9368..dba75ba 100644 --- a/art/castles/castle_1a.txt +++ b/art/castles/castle_1/ascii/castle_1a.txt @@ -1,6 +1,6 @@ -.......|~...... -....../.\...... -)..|~/___\.|~.. -../_\|::.|/_\.. -..|$||/^\||$|.. -..|nnn|I|nnn|.. +.......|~...... +....../.\...... +)..|~/___\.|~.. +../_\|::.|/_\.. +..|$||/^\||$|.. +..|nnn|I|nnn|.. diff --git a/art/castles/castle_1b.txt b/art/castles/castle_1/ascii/castle_1b.txt similarity index 94% rename from art/castles/castle_1b.txt rename to art/castles/castle_1/ascii/castle_1b.txt index 84fed99..299e7bd 100644 --- a/art/castles/castle_1b.txt +++ b/art/castles/castle_1/ascii/castle_1b.txt @@ -1,6 +1,6 @@ -......~|....... -(x).../.\...... -..~|./___\.|~.. -../_\|::.|/_\.. -..|$||/^\||$|.. -..|nnn|I|nnn|.. +......~|....... +(x).../.\...... +..~|./___\.|~.. +../_\|::.|/_\.. +..|$||/^\||$|.. +..|nnn|I|nnn|.. diff --git a/art/buildings/castles/castle_1/castle_1c.txt b/art/castles/castle_1/ascii/castle_1c.txt similarity index 94% rename from art/buildings/castles/castle_1/castle_1c.txt rename to art/castles/castle_1/ascii/castle_1c.txt index c7adfef..9af72eb 100644 --- a/art/buildings/castles/castle_1/castle_1c.txt +++ b/art/castles/castle_1/ascii/castle_1c.txt @@ -1,6 +1,6 @@ -...(X).|~...... -....../.\...... -..~|./___\~|... -../_\|::.|/_\.. -..|$||/^\||$|.. -..|nnn|I|nnn|.. +...(X).|~...... +....../.\...... +..~|./___\~|... +../_\|::.|/_\.. +..|$||/^\||$|.. +..|nnn|I|nnn|.. diff --git a/art/buildings/castles/castle_1/castle_1d.txt b/art/castles/castle_1/ascii/castle_1d.txt similarity index 94% rename from art/buildings/castles/castle_1/castle_1d.txt rename to art/castles/castle_1/ascii/castle_1d.txt index 1d99fb8..cecaa54 100644 --- a/art/buildings/castles/castle_1/castle_1d.txt +++ b/art/castles/castle_1/ascii/castle_1d.txt @@ -1,6 +1,6 @@ -......~|.(X)... -....../.\...... -...|~/___\.|~.. -../_\|::.|/_\.. -..|$||/^\||$|.. -..|nnn|I|nnn|.. +......~|.(X)... +....../.\...... +...|~/___\.|~.. +../_\|::.|/_\.. +..|$||/^\||$|.. +..|nnn|I|nnn|.. diff --git a/art/castles/castle_1e.txt b/art/castles/castle_1/ascii/castle_1e.txt similarity index 94% rename from art/castles/castle_1e.txt rename to art/castles/castle_1/ascii/castle_1e.txt index 9c663c1..2c372f4 100644 --- a/art/castles/castle_1e.txt +++ b/art/castles/castle_1/ascii/castle_1e.txt @@ -1,6 +1,6 @@ -.*....~|..*.... -...*../.\....(o -..~|./___\.|~.. -../_\|::.|/_\.. -..|$||/^\||$|.. -..|nnn|I|nnn|.. +.*....~|..*.... +...*../.\....(o +..~|./___\.|~.. +../_\|::.|/_\.. +..|$||/^\||$|.. +..|nnn|I|nnn|.. diff --git a/art/castles/castle_1f.txt b/art/castles/castle_1/ascii/castle_1f.txt similarity index 94% rename from art/castles/castle_1f.txt rename to art/castles/castle_1/ascii/castle_1f.txt index 164b103..a0883ca 100644 --- a/art/castles/castle_1f.txt +++ b/art/castles/castle_1/ascii/castle_1f.txt @@ -1,6 +1,6 @@ -...*...|~....*. -.*..*./.\.*...* -...|~/___\~|..( -../_\|::.|/_\.. -..|$||/^\||$|.. -..|nnn|I|nnn|.. +...*...|~....*. +.*..*./.\.*...* +...|~/___\~|..( +../_\|::.|/_\.. +..|$||/^\||$|.. +..|nnn|I|nnn|.. diff --git a/art/dance/man_1a.txt b/art/dance/man_1/ascii/man_1a.txt similarity index 96% rename from art/dance/man_1a.txt rename to art/dance/man_1/ascii/man_1a.txt index cee078c..71c2c8f 100644 --- a/art/dance/man_1a.txt +++ b/art/dance/man_1/ascii/man_1a.txt @@ -1,7 +1,7 @@ -.................... -.................... -.........O.......... -........<|>......... -......../.\......... -.................... +.................... +.................... +.........O.......... +........<|>......... +......../.\......... +.................... .................... \ No newline at end of file diff --git a/art/dance/man_1b.txt b/art/dance/man_1/ascii/man_1b.txt similarity index 96% rename from art/dance/man_1b.txt rename to art/dance/man_1/ascii/man_1b.txt index f706cea..413a93d 100644 --- a/art/dance/man_1b.txt +++ b/art/dance/man_1/ascii/man_1b.txt @@ -1,7 +1,7 @@ -.................... -.................... -.........O/......... -........<|.......... -........<.\......... -.................... +.................... +.................... +.........O/......... +........<|.......... +........<.\......... +.................... .................... \ No newline at end of file diff --git a/art/dance/man_1c.txt b/art/dance/man_1/ascii/man_1c.txt similarity index 96% rename from art/dance/man_1c.txt rename to art/dance/man_1/ascii/man_1c.txt index 220c3db..d7e2a5a 100644 --- a/art/dance/man_1c.txt +++ b/art/dance/man_1/ascii/man_1c.txt @@ -1,7 +1,7 @@ -.................... -.................... -........\O.......... -.........|>......... -......../.>......... -.................... +.................... +.................... +........\O.......... +.........|>......... +......../.>......... +.................... .................... \ No newline at end of file diff --git a/art/dance/man_1d.txt b/art/dance/man_1/ascii/man_1d.txt similarity index 96% rename from art/dance/man_1d.txt rename to art/dance/man_1/ascii/man_1d.txt index b3ccaa1..dc99b9b 100644 --- a/art/dance/man_1d.txt +++ b/art/dance/man_1/ascii/man_1d.txt @@ -1,7 +1,7 @@ -.................... -.................... -........\O/......... -.........|......... -........<.>......... -.................... +.................... +.................... +........\O/......... +.........|......... +........<.>......... +.................... .................... \ No newline at end of file diff --git a/art/dance/man_1e.txt b/art/dance/man_1/ascii/man_1e.txt similarity index 96% rename from art/dance/man_1e.txt rename to art/dance/man_1/ascii/man_1e.txt index 36d737f..2c1bc49 100644 --- a/art/dance/man_1e.txt +++ b/art/dance/man_1/ascii/man_1e.txt @@ -1,7 +1,7 @@ -.................... -.................... -........\O>......... -.........|......... -........<.\......... -.................... +.................... +.................... +........\O>......... +.........|......... +........<.\......... +.................... .................... \ No newline at end of file diff --git a/art/dance/man_1f.txt b/art/dance/man_1/ascii/man_1f.txt similarity index 95% rename from art/dance/man_1f.txt rename to art/dance/man_1/ascii/man_1f.txt index f2a9bc5..5f29cfd 100644 --- a/art/dance/man_1f.txt +++ b/art/dance/man_1/ascii/man_1f.txt @@ -1,7 +1,7 @@ -.................... -.................... -................ -........ |........ -........<.>......... -.................... +.................... +.................... +................ +........ |........ +........<.>......... +.................... .................... \ No newline at end of file diff --git a/art/dance/man_1g.txt b/art/dance/man_1/ascii/man_1g.txt similarity index 95% rename from art/dance/man_1g.txt rename to art/dance/man_1/ascii/man_1g.txt index 1ed3274..dbcb133 100644 --- a/art/dance/man_1g.txt +++ b/art/dance/man_1/ascii/man_1g.txt @@ -1,7 +1,7 @@ -.................... -.................... -.........O>........ -........<|........ -......../.>......... -.................... +.................... +.................... +.........O>........ +........<|........ +......../.>......... +.................... .................... \ No newline at end of file diff --git a/art/houses/house_1a.txt b/art/houses/house_1/ascii/house_1a.txt similarity index 95% rename from art/houses/house_1a.txt rename to art/houses/house_1/ascii/house_1a.txt index 3b78919..7773ad5 100644 --- a/art/houses/house_1a.txt +++ b/art/houses/house_1/ascii/house_1a.txt @@ -1,7 +1,7 @@ -................ -................ -...... ___H_.... -....../_)_)_\... -......|#[]# |... -"""""""""""""""" +................ +................ +...... ___H_.... +....../_)_)_\... +......|#[]# |... +"""""""""""""""" ................ \ No newline at end of file diff --git a/art/buildings/houses/small_home_1/house_1b.txt b/art/houses/house_1/ascii/house_1b.txt similarity index 95% rename from art/buildings/houses/small_home_1/house_1b.txt rename to art/houses/house_1/ascii/house_1b.txt index f5f9176..831ab53 100644 --- a/art/buildings/houses/small_home_1/house_1b.txt +++ b/art/houses/house_1/ascii/house_1b.txt @@ -1,7 +1,7 @@ -................ -..........,..... -...... ___H_.... -....../_)_)_\... -......|#[]# |... -"""""""""""""""" +................ +..........,..... +...... ___H_.... +....../_)_)_\... +......|#[]# |... +"""""""""""""""" ................ \ No newline at end of file diff --git a/art/buildings/houses/small_home_1/house_1c.txt b/art/houses/house_1/ascii/house_1c.txt similarity index 95% rename from art/buildings/houses/small_home_1/house_1c.txt rename to art/houses/house_1/ascii/house_1c.txt index 6d55827..8765f8c 100644 --- a/art/buildings/houses/small_home_1/house_1c.txt +++ b/art/houses/house_1/ascii/house_1c.txt @@ -1,7 +1,7 @@ -................ -..........,`.... -...... ___H_.... -....../_)_)_\... -......|#[]# |... -"""""""""""""""" +................ +..........,`.... +...... ___H_.... +....../_)_)_\... +......|#[]# |... +"""""""""""""""" ................ \ No newline at end of file diff --git a/art/buildings/houses/small_home_1/house_1d.txt b/art/houses/house_1/ascii/house_1d.txt similarity index 95% rename from art/buildings/houses/small_home_1/house_1d.txt rename to art/houses/house_1/ascii/house_1d.txt index f4575e9..a94729f 100644 --- a/art/buildings/houses/small_home_1/house_1d.txt +++ b/art/houses/house_1/ascii/house_1d.txt @@ -1,7 +1,7 @@ -................ -..........,`'... -...... ___H_.... -....../_)_)_\... -......|#[]# |... -"""""""""""""""" +................ +..........,`'... +...... ___H_.... +....../_)_)_\... +......|#[]# |... +"""""""""""""""" ................ \ No newline at end of file diff --git a/art/houses/house_1e.txt b/art/houses/house_1/ascii/house_1e.txt similarity index 95% rename from art/houses/house_1e.txt rename to art/houses/house_1/ascii/house_1e.txt index 62f3e3e..f679e49 100644 --- a/art/houses/house_1e.txt +++ b/art/houses/house_1/ascii/house_1e.txt @@ -1,7 +1,7 @@ -................ -..........,`'~.. -...... ___H_.... -....../_)_)_\... -......|#[]# |... -"""""""""""""""" +................ +..........,`'~.. +...... ___H_.... +....../_)_)_\... +......|#[]# |... +"""""""""""""""" ................ \ No newline at end of file diff --git a/art/sea/sea_1a.txt b/art/sea/sea_1/ascii/sea_1a.txt similarity index 95% rename from art/sea/sea_1a.txt rename to art/sea/sea_1/ascii/sea_1a.txt index 0d127f7..cb160fa 100644 --- a/art/sea/sea_1a.txt +++ b/art/sea/sea_1/ascii/sea_1a.txt @@ -1,6 +1,6 @@ -................. -........~...v.... -.........../|.... -.....v..../_|__.. -.........\-----/. +................. +........~...v.... +.........../|.... +.....v..../_|__.. +.........\-----/. ~~~~~~~~~`~~~~~~' \ No newline at end of file diff --git a/art/sea/sea_1b.txt b/art/sea/sea_1/ascii/sea_1b.txt similarity index 95% rename from art/sea/sea_1b.txt rename to art/sea/sea_1/ascii/sea_1b.txt index 3b51f8f..8227a4b 100644 --- a/art/sea/sea_1b.txt +++ b/art/sea/sea_1/ascii/sea_1b.txt @@ -1,6 +1,6 @@ -................. -.......~...v..... -........../|...\, -....v..../_|__... -........\-----/.. +................. +.......~...v..... +........../|...\, +....v..../_|__... +........\-----/.. ~~~~~~~~`~~~~~~'~ \ No newline at end of file diff --git a/art/sea/sea_1c.txt b/art/sea/sea_1/ascii/sea_1c.txt similarity index 95% rename from art/sea/sea_1c.txt rename to art/sea/sea_1/ascii/sea_1c.txt index 3aec562..053fce0 100644 --- a/art/sea/sea_1c.txt +++ b/art/sea/sea_1/ascii/sea_1c.txt @@ -1,6 +1,6 @@ -................. -.....~...v....... -......../|.../`\. -..v..../_|__..... -......\-----/.... +................. +.....~...v....... +......../|.../`\. +..v..../_|__..... +......\-----/.... .~~~~~`~~~~~~'~~~ \ No newline at end of file diff --git a/art/sea/sea_1d.txt b/art/sea/sea_1/ascii/sea_1d.txt similarity index 95% rename from art/sea/sea_1d.txt rename to art/sea/sea_1/ascii/sea_1d.txt index 145ca10..54cda89 100644 --- a/art/sea/sea_1d.txt +++ b/art/sea/sea_1/ascii/sea_1d.txt @@ -1,6 +1,6 @@ -................. -....~...v../`\... -......./|........ -.v..../_|__...... -.....\-----/..... +................. +....~...v../`\... +......./|........ +.v..../_|__...... +.....\-----/..... ~~~~~`~~~~~~'~~~~ \ No newline at end of file diff --git a/art/sea/sea_1e.txt b/art/sea/sea_1/ascii/sea_1e.txt similarity index 95% rename from art/sea/sea_1e.txt rename to art/sea/sea_1/ascii/sea_1e.txt index e554808..458993b 100644 --- a/art/sea/sea_1e.txt +++ b/art/sea/sea_1/ascii/sea_1e.txt @@ -1,6 +1,6 @@ -.........\,/..... -.....~.v......... -....../|......... -.. ../_|__....... -..v.\-----/...... +.........\,/..... +.....~.v......... +....../|......... +.. ../_|__....... +..v.\-----/...... ~~~~`~~~~~~'~~~~~ \ No newline at end of file diff --git a/art/sea/sea_1f.txt b/art/sea/sea_1/ascii/sea_1f.txt similarity index 95% rename from art/sea/sea_1f.txt rename to art/sea/sea_1/ascii/sea_1f.txt index f47484c..2b46ba3 100644 --- a/art/sea/sea_1f.txt +++ b/art/sea/sea_1/ascii/sea_1f.txt @@ -1,6 +1,6 @@ -....../`\........ -.~...v........... -..../|........... -.../_|__......... -..\-----/........ +....../`\........ +.~...v........... +..../|........... +.../_|__......... +..\-----/........ ~~`~~~~~~'~~~~~~~ \ No newline at end of file diff --git a/art/sea/sea_1g.txt b/art/sea/sea_1/ascii/sea_1g.txt similarity index 95% rename from art/sea/sea_1g.txt rename to art/sea/sea_1/ascii/sea_1g.txt index b8282af..cdc825e 100644 --- a/art/sea/sea_1g.txt +++ b/art/sea/sea_1/ascii/sea_1g.txt @@ -1,6 +1,6 @@ -.....\,/......... -~...v............ -.../|............ -../_|__.......... -.\-----/......... +.....\,/......... +~...v............ +.../|............ +../_|__.......... +.\-----/......... ~`~~~~~~'~~~~~~~~ \ No newline at end of file diff --git a/art/sea/sea_1h.txt b/art/sea/sea_1/ascii/sea_1h.txt similarity index 95% rename from art/sea/sea_1h.txt rename to art/sea/sea_1/ascii/sea_1h.txt index e677aae..4be0efe 100644 --- a/art/sea/sea_1h.txt +++ b/art/sea/sea_1/ascii/sea_1h.txt @@ -1,6 +1,6 @@ -... /`\........ -...v........... -../|........... -./_|__......... -\-----/........ +... /`\........ +...v........... +../|........... +./_|__......... +\-----/........ `~~~~~~'~~~~~~~ \ No newline at end of file