From 8f99063b5b03858b8fea1c98744cbd5374577b03 Mon Sep 17 00:00:00 2001 From: Jake Funke Date: Tue, 21 Mar 2017 19:55:11 +0000 Subject: [PATCH] Paginate garden --- README.md | 8 +++--- botany.py | 44 ++++++++++++++++++++++++++----- menu_screen.py | 71 ++++++++++++++++++++++++++++++++++---------------- 3 files changed, 92 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index e4cb099..322f612 100644 --- a/README.md +++ b/README.md @@ -48,11 +48,13 @@ If your plant goes 5 days without water, it will die! * ASCII art only shows first stage of growth - more coming soon! ### to-dos -* Add day/night ASCII art -* Finish garden display ('garden' function) +* Finish garden feature + * Switch to database instead of .dat file * Allows you to water neighbor's plants -* Plant end of life (seeding/pollination) +* Harvest plant at end of life (gather seeds) + * Create harvest file with a log of all previous plants * Plant pollination - cross-breed with neighbor plants to unlock second-gen plants + * Share seeds with other users * Global events * Server API to have rain storms, heat waves, insects * Name your plant diff --git a/botany.py b/botany.py index c302648..f339fd0 100644 --- a/botany.py +++ b/botany.py @@ -224,7 +224,7 @@ class Plant(object): # Create plant mutation # TODO: when out of debug this needs to be set to high number # Increase this # to make mutation rarer (chance 1 out of x each second) - CONST_MUTATION_RARITY = 3000 + CONST_MUTATION_RARITY = 5000 mutation_seed = random.randint(1,CONST_MUTATION_RARITY) if mutation_seed == CONST_MUTATION_RARITY: # mutation gained! @@ -281,7 +281,6 @@ class Plant(object): def life(self): # I've created life :) while True: - time.sleep(1) if not self.dead: if self.watered_24h: self.ticks += 1 @@ -297,8 +296,11 @@ class Plant(object): # Do something else pass # TODO: event check + time.sleep(1) class DataManager(object): + # TODO: garden file stuff has a race condition - need to find and + # eliminate it. # handles user data, puts a .botany dir in user's home dir (OSX/Linux) user_dir = os.path.expanduser("~") botany_dir = os.path.join(user_dir,'.botany') @@ -309,6 +311,8 @@ class DataManager(object): savefile_path = os.path.join(botany_dir, savefile_name) garden_file_path = os.path.join(game_dir, 'garden_file.dat') garden_json_path = os.path.join(game_dir, 'garden_file.json') + harvest_file_path = os.path.join(botany_dir, 'harvest_file.dat') + harvest_json_path = os.path.join(botany_dir, 'harvest_file.json') def __init__(self): self.this_user = getpass.getuser() @@ -346,17 +350,16 @@ class DataManager(object): self.save_plant(this_plant) self.data_write_json(this_plant) self.garden_update(this_plant) + self.harvest_plant(this_plant) this_plant.unlock_new_creation() time.sleep(.1) def autosave(self, this_plant): - # running on thread + # running on thread, saves plant every 5s while True: self.save_plant(this_plant) self.data_write_json(this_plant) self.garden_update(this_plant) - # TODO: change after debug - #time.sleep(60) time.sleep(5) def load_plant(self): @@ -377,7 +380,6 @@ class DataManager(object): else: ticks_to_add = 0 this_plant.ticks += ticks_to_add - return this_plant def plant_age_convert(self,this_plant): @@ -462,6 +464,35 @@ class DataManager(object): with open(json_file, 'w') as outfile: json.dump(plant_info, outfile) + def harvest_plant(self, this_plant): + # harvest is a dict of dicts + # harvest contains one entry for each plant id + age_formatted = self.plant_age_convert(this_plant) + this_plant_id = this_plant.plant_id + plant_info = { + "description":this_plant.parse_plant(), + "age":age_formatted, + "score":this_plant.ticks, + } + if os.path.isfile(self.harvest_file_path): + # harvest file exists: load data + with open(self.harvest_file_path, 'rb') as f: + this_harvest = pickle.load(f) + new_file_check = False + else: + this_harvest = {} + new_file_check = True + this_harvest[this_plant_id] = plant_info + + # dump harvest file + with open(self.harvest_file_path, 'wb') as f: + pickle.dump(this_harvest, f, protocol=2) + # dump json file + with open(self.harvest_json_path, 'w') as outfile: + json.dump(this_harvest, outfile) + + return new_file_check + if __name__ == '__main__': my_data = DataManager() # if plant save file exists @@ -474,6 +505,7 @@ if __name__ == '__main__': my_plant.start_life() my_data.start_threads(my_plant) botany_menu = CursedMenu(my_plant,my_data.garden_file_path) + my_data.save_plant(my_plant) my_data.data_write_json(my_plant) my_data.garden_update(my_plant) diff --git a/menu_screen.py b/menu_screen.py index 72307f8..e419370 100644 --- a/menu_screen.py +++ b/menu_screen.py @@ -45,16 +45,15 @@ class CursedMenu(object): def update_options(self): # Makes sure you can get a new plant if it dies if self.plant.dead: - if "start over" not in self.options: - self.options.insert(-1,"start over") + if "harvest" not in self.options: + self.options.insert(-1,"harvest") else: - # TODO: remove after debug or bury in settings if self.plant.stage == 5: - if "start over" not in self.options: - self.options.insert(-1,"start over") + if "harvest" not in self.options: + self.options.insert(-1,"harvest") else: - if "start over" in self.options: - self.options.remove("start over") + if "harvest" in self.options: + self.options.remove("harvest") def set_options(self, options): # Validates that the last option is "exit" @@ -228,7 +227,7 @@ class CursedMenu(object): return def format_garden_data(self,this_garden): - + # Returns list of lists (pages) of garden entries plant_table = "" for plant_id in this_garden: if this_garden[plant_id]: @@ -238,7 +237,11 @@ class CursedMenu(object): plant_table += this_plant["age"] + " - " plant_table += str(this_plant["score"]) + "p - " plant_table += this_plant["description"] + "\n" - return plant_table + # build list of n entries per page + entries_per_page = self.maxy - 16 + garden_list = plant_table.splitlines() + paginated_list = [garden_list[i:i+entries_per_page] for i in range(0,len(garden_list),entries_per_page)] + return paginated_list def draw_garden(self): # draws neighborhood @@ -249,22 +252,47 @@ class CursedMenu(object): with open(self.garden_file_path, 'rb') as f: this_garden = pickle.load(f) # format data + plant_table_pages = [] if self.infotoggle != 2: + # if infotoggle isn't 2, the screen currently displays other stuff + # we want to prep the screen for showing the garden + # Clear text area of other text (look info, etc) first for y, line in enumerate(clear_block.splitlines(), 2): self.screen.addstr(y+12, 2, line) self.screen.refresh() - plant_table_formatted = self.format_garden_data(this_garden) + plant_table_pages = self.format_garden_data(this_garden) self.infotoggle = 2 else: - plant_table_formatted = clear_bar - for plant in this_garden: - if not this_garden[plant]["dead"]: - plant_table_formatted += clear_bar + # the screen IS currently showing the garden (1 page), make the + # text a bunch of blanks to clear it out + big_clear_block = clear_bar * (self.maxy - 14) + plant_table_pages.append(big_clear_block.splitlines()) self.infotoggle = 0 - for y, line in enumerate(plant_table_formatted.splitlines(), 2): - self.screen.addstr(y+12, 2, line) - self.screen.refresh() + # print garden information OR clear it + for page_num, page in enumerate(plant_table_pages, 1): + # Print page text + for y, line in enumerate(page, 2): + self.screen.addstr(y+12, 2, line) + if len(plant_table_pages) > 1: + # Multiple pages, paginate and require keypress + page_text = " --- press any key --- (%d/%d)" % (page_num, len(plant_table_pages)) + self.screen.addstr(self.maxy-2, 2, page_text) + self.screen.getch() + self.screen.refresh() + # Clear page before drawing next + for y, line in enumerate(range(self.maxy-16), 2): + self.screen.addstr(y+12, 2, clear_bar) + self.infotoggle = 0 + self.screen.refresh() + else: + self.screen.refresh() + # self.screen.getch() + # for y, line in enumerate(range(self.maxy-16), 2): + # self.screen.addstr(y+12, 2, clear_bar) + # self.screen.refresh() + + def get_plant_description(self, this_plant): output_text = "" @@ -281,6 +309,8 @@ class CursedMenu(object): "You wish your seed could tell you what it needs.", "You can feel the spirit inside your seed.", "These pretzels are making you thirsty.", + "Way to plant, Ann!", + "'To see things in the seed, that is genius' - Lao Tzu", ], 1:[ "The seedling fills you with hope.", @@ -308,7 +338,7 @@ class CursedMenu(object): "You're proud of the dedication it took to grow your " + this_species + ".", "The " + this_species + " looks good.", "You think about how good this " + this_species + " will look.", - "The buds of your " + this_species + " are about to bloom.", + "The buds of your " + this_species + " might bloom soon.", "You play your favorite song for your " + this_species + ".", ], 4:[ @@ -386,9 +416,6 @@ class CursedMenu(object): # load data # format data if self.infotoggle != 1: - # TODO: when garden grows this won't clear everything. - # for example if there are 9 people in garden it won't clear all - # of them output_string = clear_bar * (self.maxy - 15) for y, line in enumerate(output_string.splitlines(), 2): self.screen.addstr(y+12, 2, line) @@ -431,7 +458,7 @@ available in the readme :) def handle_request(self, request): '''this is where you do things with the request''' if request == None: return - if request == "start over": + if request == "harvest": self.plant.start_over() if request == "water": self.plant.water()