Paginate garden

pull/1/head
Jake Funke 2017-03-21 19:55:11 +00:00
parent 2fcdb01577
commit 8f99063b5b
3 changed files with 92 additions and 31 deletions

View File

@ -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! * ASCII art only shows first stage of growth - more coming soon!
### to-dos ### to-dos
* Add day/night ASCII art * Finish garden feature
* Finish garden display ('garden' function) * Switch to database instead of .dat file
* Allows you to water neighbor's plants * 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 * Plant pollination - cross-breed with neighbor plants to unlock second-gen plants
* Share seeds with other users
* Global events * Global events
* Server API to have rain storms, heat waves, insects * Server API to have rain storms, heat waves, insects
* Name your plant * Name your plant

View File

@ -224,7 +224,7 @@ class Plant(object):
# Create plant mutation # Create plant mutation
# TODO: when out of debug this needs to be set to high number # 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) # 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) mutation_seed = random.randint(1,CONST_MUTATION_RARITY)
if mutation_seed == CONST_MUTATION_RARITY: if mutation_seed == CONST_MUTATION_RARITY:
# mutation gained! # mutation gained!
@ -281,7 +281,6 @@ class Plant(object):
def life(self): def life(self):
# I've created life :) # I've created life :)
while True: while True:
time.sleep(1)
if not self.dead: if not self.dead:
if self.watered_24h: if self.watered_24h:
self.ticks += 1 self.ticks += 1
@ -297,8 +296,11 @@ class Plant(object):
# Do something else # Do something else
pass pass
# TODO: event check # TODO: event check
time.sleep(1)
class DataManager(object): 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) # handles user data, puts a .botany dir in user's home dir (OSX/Linux)
user_dir = os.path.expanduser("~") user_dir = os.path.expanduser("~")
botany_dir = os.path.join(user_dir,'.botany') botany_dir = os.path.join(user_dir,'.botany')
@ -309,6 +311,8 @@ class DataManager(object):
savefile_path = os.path.join(botany_dir, savefile_name) savefile_path = os.path.join(botany_dir, savefile_name)
garden_file_path = os.path.join(game_dir, 'garden_file.dat') garden_file_path = os.path.join(game_dir, 'garden_file.dat')
garden_json_path = os.path.join(game_dir, 'garden_file.json') 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): def __init__(self):
self.this_user = getpass.getuser() self.this_user = getpass.getuser()
@ -346,17 +350,16 @@ class DataManager(object):
self.save_plant(this_plant) self.save_plant(this_plant)
self.data_write_json(this_plant) self.data_write_json(this_plant)
self.garden_update(this_plant) self.garden_update(this_plant)
self.harvest_plant(this_plant)
this_plant.unlock_new_creation() this_plant.unlock_new_creation()
time.sleep(.1) time.sleep(.1)
def autosave(self, this_plant): def autosave(self, this_plant):
# running on thread # running on thread, saves plant every 5s
while True: while True:
self.save_plant(this_plant) self.save_plant(this_plant)
self.data_write_json(this_plant) self.data_write_json(this_plant)
self.garden_update(this_plant) self.garden_update(this_plant)
# TODO: change after debug
#time.sleep(60)
time.sleep(5) time.sleep(5)
def load_plant(self): def load_plant(self):
@ -377,7 +380,6 @@ class DataManager(object):
else: else:
ticks_to_add = 0 ticks_to_add = 0
this_plant.ticks += ticks_to_add this_plant.ticks += ticks_to_add
return this_plant return this_plant
def plant_age_convert(self,this_plant): def plant_age_convert(self,this_plant):
@ -462,6 +464,35 @@ class DataManager(object):
with open(json_file, 'w') as outfile: with open(json_file, 'w') as outfile:
json.dump(plant_info, 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__': if __name__ == '__main__':
my_data = DataManager() my_data = DataManager()
# if plant save file exists # if plant save file exists
@ -474,6 +505,7 @@ if __name__ == '__main__':
my_plant.start_life() my_plant.start_life()
my_data.start_threads(my_plant) my_data.start_threads(my_plant)
botany_menu = CursedMenu(my_plant,my_data.garden_file_path) botany_menu = CursedMenu(my_plant,my_data.garden_file_path)
my_data.save_plant(my_plant) my_data.save_plant(my_plant)
my_data.data_write_json(my_plant) my_data.data_write_json(my_plant)
my_data.garden_update(my_plant) my_data.garden_update(my_plant)

View File

@ -45,16 +45,15 @@ class CursedMenu(object):
def update_options(self): def update_options(self):
# Makes sure you can get a new plant if it dies # Makes sure you can get a new plant if it dies
if self.plant.dead: if self.plant.dead:
if "start over" not in self.options: if "harvest" not in self.options:
self.options.insert(-1,"start over") self.options.insert(-1,"harvest")
else: else:
# TODO: remove after debug or bury in settings
if self.plant.stage == 5: if self.plant.stage == 5:
if "start over" not in self.options: if "harvest" not in self.options:
self.options.insert(-1,"start over") self.options.insert(-1,"harvest")
else: else:
if "start over" in self.options: if "harvest" in self.options:
self.options.remove("start over") self.options.remove("harvest")
def set_options(self, options): def set_options(self, options):
# Validates that the last option is "exit" # Validates that the last option is "exit"
@ -228,7 +227,7 @@ class CursedMenu(object):
return return
def format_garden_data(self,this_garden): def format_garden_data(self,this_garden):
# Returns list of lists (pages) of garden entries
plant_table = "" plant_table = ""
for plant_id in this_garden: for plant_id in this_garden:
if this_garden[plant_id]: if this_garden[plant_id]:
@ -238,7 +237,11 @@ class CursedMenu(object):
plant_table += this_plant["age"] + " - " plant_table += this_plant["age"] + " - "
plant_table += str(this_plant["score"]) + "p - " plant_table += str(this_plant["score"]) + "p - "
plant_table += this_plant["description"] + "\n" 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): def draw_garden(self):
# draws neighborhood # draws neighborhood
@ -249,22 +252,47 @@ class CursedMenu(object):
with open(self.garden_file_path, 'rb') as f: with open(self.garden_file_path, 'rb') as f:
this_garden = pickle.load(f) this_garden = pickle.load(f)
# format data # format data
plant_table_pages = []
if self.infotoggle != 2: 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): for y, line in enumerate(clear_block.splitlines(), 2):
self.screen.addstr(y+12, 2, line) self.screen.addstr(y+12, 2, line)
self.screen.refresh() self.screen.refresh()
plant_table_formatted = self.format_garden_data(this_garden) plant_table_pages = self.format_garden_data(this_garden)
self.infotoggle = 2 self.infotoggle = 2
else: else:
plant_table_formatted = clear_bar # the screen IS currently showing the garden (1 page), make the
for plant in this_garden: # text a bunch of blanks to clear it out
if not this_garden[plant]["dead"]: big_clear_block = clear_bar * (self.maxy - 14)
plant_table_formatted += clear_bar plant_table_pages.append(big_clear_block.splitlines())
self.infotoggle = 0 self.infotoggle = 0
for y, line in enumerate(plant_table_formatted.splitlines(), 2): # print garden information OR clear it
self.screen.addstr(y+12, 2, line) for page_num, page in enumerate(plant_table_pages, 1):
self.screen.refresh() # 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): def get_plant_description(self, this_plant):
output_text = "" output_text = ""
@ -281,6 +309,8 @@ class CursedMenu(object):
"You wish your seed could tell you what it needs.", "You wish your seed could tell you what it needs.",
"You can feel the spirit inside your seed.", "You can feel the spirit inside your seed.",
"These pretzels are making you thirsty.", "These pretzels are making you thirsty.",
"Way to plant, Ann!",
"'To see things in the seed, that is genius' - Lao Tzu",
], ],
1:[ 1:[
"The seedling fills you with hope.", "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 + ".", "You're proud of the dedication it took to grow your " + this_species + ".",
"The " + this_species + " looks good.", "The " + this_species + " looks good.",
"You think about how good this " + this_species + " will look.", "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 + ".", "You play your favorite song for your " + this_species + ".",
], ],
4:[ 4:[
@ -386,9 +416,6 @@ class CursedMenu(object):
# load data # load data
# format data # format data
if self.infotoggle != 1: 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) output_string = clear_bar * (self.maxy - 15)
for y, line in enumerate(output_string.splitlines(), 2): for y, line in enumerate(output_string.splitlines(), 2):
self.screen.addstr(y+12, 2, line) self.screen.addstr(y+12, 2, line)
@ -431,7 +458,7 @@ available in the readme :)
def handle_request(self, request): def handle_request(self, request):
'''this is where you do things with the request''' '''this is where you do things with the request'''
if request == None: return if request == None: return
if request == "start over": if request == "harvest":
self.plant.start_over() self.plant.start_over()
if request == "water": if request == "water":
self.plant.water() self.plant.water()