Fix race conditions, add look feature
This commit is contained in:
		
							parent
							
								
									138a981c3f
								
							
						
					
					
						commit
						bd56dd38a4
					
				
							
								
								
									
										132
									
								
								botany.py
									
									
									
									
									
								
							
							
						
						
									
										132
									
								
								botany.py
									
									
									
									
									
								
							| @ -3,7 +3,8 @@ import time | ||||
| import pickle | ||||
| import json | ||||
| import math | ||||
| import os.path | ||||
| import sys | ||||
| import os | ||||
| import random | ||||
| import getpass | ||||
| import threading | ||||
| @ -15,16 +16,11 @@ from menu_screen import * | ||||
| # development plan | ||||
| 
 | ||||
| # build plant lifecycle just stepping through | ||||
| #   - What else should it do during life? growth alone is not all that | ||||
| #   interesting. | ||||
| #   - how long should each stage last ? thinking realistic lmao | ||||
| #   seed -> seedling -> sprout -> young plant -> mature plant -> flower -> | ||||
| #   pollination -> fruit -> seeds | ||||
| #   - TODO: pollination and end of life | ||||
| # | ||||
| # interaction | ||||
| #   - look at plant, how do you feel? (also gets rid of pests) | ||||
| # | ||||
| # events | ||||
| # - heatwave | ||||
| # - rain | ||||
| @ -39,11 +35,11 @@ from menu_screen import * | ||||
| #   - create rarer species by diff gens | ||||
| # - if neighbor plant dies, node will be removed from list | ||||
| # | ||||
| # garden system | ||||
| # - can plant your plant in the garden to start a new plant | ||||
| 
 | ||||
| # build ascii trees | ||||
| 
 | ||||
| # Make it fun to keep growing after seed level (what is reward for continuing | ||||
| # instead of starting over? | ||||
| # Reward for bringing plant to full life - second gen plant w/ more variety | ||||
| 
 | ||||
| class Plant(object): | ||||
|     # This is your plant! | ||||
| @ -140,6 +136,9 @@ class Plant(object): | ||||
|     def __init__(self, this_filename): | ||||
|         # Constructor | ||||
|         self.plant_id = str(uuid.uuid4()) | ||||
|         # TODO: change from debug | ||||
|         self.life_stages = (10, 20, 30, 40, 50) | ||||
|         # self.life_stages = (3600, (3600*24)*3, (3600*24)*10, (3600*24)*20, (3600*24)*30) | ||||
|         self.stage = 0 | ||||
|         self.mutation = 0 | ||||
|         self.species = random.randint(0,len(self.species_dict)-1) | ||||
| @ -148,6 +147,7 @@ class Plant(object): | ||||
|         self.ticks = 0 | ||||
|         self.age_formatted = "0" | ||||
|         self.dead = False | ||||
|         self.write_lock = False | ||||
|         self.owner = getpass.getuser() | ||||
|         self.file_name = this_filename | ||||
|         self.start_time = int(time.time()) | ||||
| @ -157,9 +157,20 @@ class Plant(object): | ||||
|         # self.watered_timestamp = int(time.time()) # debug | ||||
|         self.watered_24h = False | ||||
| 
 | ||||
|     def new_seed(self,this_filename): | ||||
|         # Creates life after death | ||||
|         self.__init__(this_filename) | ||||
|     def parse_plant(self): | ||||
|         # reads plant info (maybe want to reorg this into a different class | ||||
|         # with the reader dicts...) | ||||
|         output = "" | ||||
|         if self.stage >= 3: | ||||
|             output += self.rarity_dict[self.rarity] + " " | ||||
|         if self.mutation != 0: | ||||
|             output += self.mutation_dict[self.mutation] + " " | ||||
|         if self.stage >= 4: | ||||
|             output += self.color_dict[self.color] + " " | ||||
|         output += self.stage_dict[self.stage] + " " | ||||
|         if self.stage >= 2: | ||||
|             output += self.species_dict[self.species] + " " | ||||
|         return output.strip() | ||||
| 
 | ||||
|     def rarity_check(self): | ||||
|         # Generate plant rarity | ||||
| @ -189,23 +200,6 @@ class Plant(object): | ||||
|             rarity = 4 | ||||
|         return rarity | ||||
| 
 | ||||
|     def growth(self): | ||||
|         # Increase plant growth stage | ||||
|         if self.stage < (len(self.stage_dict)-1): | ||||
|             self.stage += 1 | ||||
|             # do stage growth stuff | ||||
|         else: | ||||
|             # do stage 5 stuff (after fruiting) | ||||
|             1==1 | ||||
| 
 | ||||
|     def water(self): | ||||
|         # Increase plant growth stage | ||||
|         # TODO: overwatering? if more than once a day it dies? | ||||
|         if not self.dead: | ||||
|             self.watered_timestamp = int(time.time()) | ||||
|             self.watered_24h = True | ||||
| 
 | ||||
| 
 | ||||
|     def dead_check(self): | ||||
|         time_delta_watered = int(time.time()) - self.watered_timestamp | ||||
|         # if it has been >5 days since watering, sorry plant is dead :( | ||||
| @ -213,9 +207,6 @@ class Plant(object): | ||||
|             self.dead = True | ||||
|         return self.dead | ||||
| 
 | ||||
|     def kill_plant(self): | ||||
|         self.dead = True | ||||
| 
 | ||||
|     def water_check(self): | ||||
|         # if plant has been watered in 24h then it keeps growing | ||||
|         # time_delta_watered is difference from now to last watered | ||||
| @ -230,7 +221,7 @@ class Plant(object): | ||||
|         # Create plant mutation | ||||
|         # TODO: when out of debug this needs to be set to high number (1000 | ||||
|         # even maybe) | ||||
|         CONST_MUTATION_RARITY = 10 # Increase this # to make mutation rarer (chance 1 out of x) | ||||
|         CONST_MUTATION_RARITY = 2000 # Increase this # to make mutation rarer (chance 1 out of x) | ||||
|         mutation_seed = random.randint(1,CONST_MUTATION_RARITY) | ||||
|         if mutation_seed == CONST_MUTATION_RARITY: | ||||
|             # mutation gained! | ||||
| @ -241,20 +232,39 @@ class Plant(object): | ||||
|         else: | ||||
|             return False | ||||
| 
 | ||||
|     def parse_plant(self): | ||||
|         # reads plant info (maybe want to reorg this into a different class | ||||
|         # with the reader dicts...) | ||||
|         output = "" | ||||
|         if self.stage >= 3: | ||||
|             output += self.rarity_dict[self.rarity] + " " | ||||
|         if self.mutation != 0: | ||||
|             output += self.mutation_dict[self.mutation] + " " | ||||
|         if self.stage >= 4: | ||||
|             output += self.color_dict[self.color] + " " | ||||
|         output += self.stage_dict[self.stage] + " " | ||||
|         if self.stage >= 2: | ||||
|             output += self.species_dict[self.species] + " " | ||||
|         return output.strip() | ||||
|     def new_seed(self,this_filename): | ||||
|         # Creates life after death | ||||
|         self.__init__(this_filename) | ||||
| 
 | ||||
|     def growth(self): | ||||
|         # Increase plant growth stage | ||||
|         if self.stage < (len(self.stage_dict)-1): | ||||
|             self.stage += 1 | ||||
|             # do stage growth stuff | ||||
|         else: | ||||
|             # do stage 5 stuff (after fruiting) | ||||
|             1==1 | ||||
| 
 | ||||
|     def water(self): | ||||
|         # Increase plant growth stage | ||||
|         if not self.dead: | ||||
|             self.watered_timestamp = int(time.time()) | ||||
|             self.watered_24h = True | ||||
| 
 | ||||
|     def start_over(self): | ||||
|         self.write_lock = True | ||||
|         self.kill_plant() | ||||
|         while self.write_lock: | ||||
|             # Wait for garden writer to unlock | ||||
|             1==1 | ||||
|         if not self.write_lock: | ||||
|             self.new_seed(self.file_name) | ||||
| 
 | ||||
|     def kill_plant(self): | ||||
|         self.dead = True | ||||
| 
 | ||||
|     def unlock_new_creation(self): | ||||
|         self.write_lock = False | ||||
| 
 | ||||
|     def start_life(self): | ||||
|        # runs life on a thread | ||||
| @ -265,7 +275,7 @@ class Plant(object): | ||||
|     def life(self): | ||||
|         # I've created life :) | ||||
|         # TODO: change out of debug | ||||
|         life_stages = (5, 15, 30, 45, 60) | ||||
|         # TODO: variable stages of life | ||||
|         # day = 3600*24 | ||||
|         # life_stages = (1*day, 2*day, 3*day, 4*day, 5*day) | ||||
|         # leave this untouched bc it works for now | ||||
| @ -275,7 +285,7 @@ class Plant(object): | ||||
|                 if self.watered_24h: | ||||
|                     self.ticks += 1 | ||||
|                     if self.stage < len(self.stage_dict)-1: | ||||
|                         if self.ticks >= life_stages[self.stage]: | ||||
|                         if self.ticks >= self.life_stages[self.stage]: | ||||
|                             self.growth() | ||||
|                     if self.mutate_check(): | ||||
|                         1==1 | ||||
| @ -299,6 +309,8 @@ class DataManager(object): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.this_user = getpass.getuser() | ||||
|         # check if instance is already running | ||||
|         self.lock_file() | ||||
|         # check for .botany dir in home | ||||
|         try: | ||||
|             os.makedirs(self.botany_dir) | ||||
| @ -307,6 +319,19 @@ class DataManager(object): | ||||
|                 raise | ||||
|         self.savefile_name = self.this_user + '_plant.dat' | ||||
| 
 | ||||
|     def lock_file(self): | ||||
|         # Only allow one instance of game | ||||
|         pid = str(os.getpid()) | ||||
|         this_filename = "instance.lock" | ||||
|         self.pid_file_path = os.path.join(self.botany_dir,this_filename) | ||||
|         if os.path.isfile(self.pid_file_path): | ||||
|             print "botany already running, exiting. (pid %s)" % pid | ||||
|             sys.exit() | ||||
|         file(self.pid_file_path, 'w').write(pid) | ||||
| 
 | ||||
|     def clear_lock(self): | ||||
|         os.unlink(self.pid_file_path) | ||||
| 
 | ||||
|     def check_plant(self): | ||||
|         # check for existing save file | ||||
|         if os.path.isfile(self.savefile_path): | ||||
| @ -333,6 +358,7 @@ class DataManager(object): | ||||
|                 self.save_plant(this_plant) | ||||
|                 self.data_write_json(this_plant) | ||||
|                 self.garden_update(this_plant) | ||||
|                 this_plant.unlock_new_creation() | ||||
|             time.sleep(.1) | ||||
| 
 | ||||
|     def autosave(self, this_plant): | ||||
| @ -379,7 +405,6 @@ class DataManager(object): | ||||
|     def garden_update(self, this_plant): | ||||
|         # garden is a dict of dicts | ||||
|         # garden contains one entry for each plant id | ||||
| 
 | ||||
|         age_formatted = self.plant_age_convert(this_plant) | ||||
|         this_plant_id = this_plant.plant_id | ||||
|         plant_info = { | ||||
| @ -408,7 +433,7 @@ class DataManager(object): | ||||
|         # if plant ticks for id is greater than current ticks of plant id | ||||
|         else: | ||||
|             current_plant_ticks = this_garden[this_plant_id]["score"] | ||||
|             if this_plant.ticks > current_plant_ticks: | ||||
|             if this_plant.ticks >= current_plant_ticks: | ||||
|                 this_garden[this_plant_id] = plant_info | ||||
|         with open(self.garden_file_path, 'wb') as f: | ||||
|             pickle.dump(this_garden, f, protocol=2) | ||||
| @ -444,9 +469,6 @@ class DataManager(object): | ||||
|         with open(json_file, 'w') as outfile: | ||||
|             json.dump(plant_info, outfile) | ||||
| 
 | ||||
|         # update leaderboard 'garden' for display in game | ||||
|         # also should be a pickle file bc... let's be honest ppl want to cheat | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     my_data = DataManager() | ||||
|     # if plant save file exists | ||||
| @ -454,7 +476,6 @@ if __name__ == '__main__': | ||||
|         my_plant = my_data.load_plant() | ||||
|     # otherwise create new plant | ||||
|     else: | ||||
|         #TODO: onboarding, select seed, select whatever else | ||||
|         my_plant = Plant(my_data.savefile_path) | ||||
|         my_data.data_write_json(my_plant) | ||||
|     my_plant.start_life() | ||||
| @ -464,3 +485,4 @@ 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) | ||||
|     my_data.clear_lock() | ||||
|  | ||||
							
								
								
									
										274
									
								
								menu_screen.py
									
									
									
									
									
								
							
							
						
						
									
										274
									
								
								menu_screen.py
									
									
									
									
									
								
							| @ -1,7 +1,8 @@ | ||||
| import curses, os, traceback, threading, time, datetime, pickle | ||||
| import curses, os, traceback, threading, time, datetime, pickle, operator, random | ||||
| 
 | ||||
| class CursedMenu(object): | ||||
|     #TODO: create a side panel with log of events..? | ||||
|     #TODO: name your plant | ||||
|     '''A class which abstracts the horrors of building a curses-based menu system''' | ||||
|     def __init__(self, this_plant, this_garden_file_path): | ||||
|         '''Initialization''' | ||||
| @ -18,14 +19,14 @@ class CursedMenu(object): | ||||
|         self.plant_ticks = str(self.plant.ticks) | ||||
|         self.exit = False | ||||
|         self.instructiontoggle = False | ||||
|         #TODO: debugging | ||||
|         # self.gardenmenutoggle = True | ||||
|         self.gardenmenutoggle = False | ||||
|         self.looktoggle = False | ||||
|         self.maxy, self.maxx = self.screen.getmaxyx() | ||||
|         # Highlighted and Normal line definitions | ||||
|         curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE) | ||||
|         self.highlighted = curses.color_pair(1) | ||||
|         self.normal = curses.A_NORMAL | ||||
|         # Threaded screen update for live changes | ||||
|         screen_thread = threading.Thread(target=self.update_plant_live, args=()) | ||||
|         screen_thread.daemon = True | ||||
|         screen_thread.start() | ||||
| @ -44,16 +45,18 @@ class CursedMenu(object): | ||||
|     def update_options(self): | ||||
|         # Makes sure you can get a new plant if it dies | ||||
|         if self.plant.dead: | ||||
|             if "kill" in self.options: | ||||
|                 self.options.remove("kill") | ||||
|             if "new" not in self.options: | ||||
|                 self.options.insert(-1,"new") | ||||
|             # if "start over" in self.options: | ||||
|             #     self.options.remove("start over") | ||||
|             if "start over" not in self.options: | ||||
|                 self.options.insert(-1,"start over") | ||||
|         else: | ||||
|             # TODO: remove after debug or bury in settings | ||||
|             if "new" in self.options: | ||||
|                 self.options.remove("new") | ||||
|             if "kill" not in self.options: | ||||
|                 self.options.insert(-1,"kill") | ||||
|             if self.plant.stage == 5: | ||||
|                 if "start over" not in self.options: | ||||
|                     self.options.insert(-1,"start over") | ||||
|             else: | ||||
|                 if "start over" in self.options: | ||||
|                     self.options.remove("start over") | ||||
| 
 | ||||
|     def set_options(self, options): | ||||
|         # Validates that the last option is "exit" | ||||
| @ -61,6 +64,22 @@ class CursedMenu(object): | ||||
|             options.append('exit') | ||||
|         self.options = options | ||||
| 
 | ||||
|     def draw(self): | ||||
|         # Draw the menu and lines | ||||
|         # TODO: this needs to either display the default menu screen or the | ||||
|         # garden/leaderboard thing  based on self.gardenmenutoggle | ||||
|         # TODO: display refresh is hacky. Could be more precise | ||||
|         self.screen.refresh() | ||||
|         self.screen.border(0) | ||||
|         try: | ||||
|             self.draw_default() | ||||
|             self.screen.refresh() | ||||
|         except Exception as exception: | ||||
|             # Makes sure data is saved in event of a crash due to window resizing | ||||
|             self.screen.addstr(0,0,"Enlarge terminal!") | ||||
|             self.__exit__() | ||||
|             traceback.print_exc() | ||||
| 
 | ||||
|     def draw_menu(self): | ||||
|         # Actually draws the menu and handles branching | ||||
|         request = "" | ||||
| @ -81,6 +100,9 @@ class CursedMenu(object): | ||||
|         clear_bar = " " * (int(self.maxx*2/3)) | ||||
|         self.screen.addstr(2,2, self.title, curses.A_STANDOUT) # Title for this menu | ||||
|         self.screen.addstr(4,2, self.subtitle, curses.A_BOLD) #Subtitle for this menu | ||||
|         # Clear menu on screen | ||||
|         for index in range(len(self.options)+1): | ||||
|             self.screen.addstr(5+index,4, clear_bar, curses.A_NORMAL) | ||||
|         # Display all the menu items, showing the 'pos' item highlighted | ||||
|         for index in range(len(self.options)): | ||||
|             textstyle = self.normal | ||||
| @ -104,62 +126,6 @@ class CursedMenu(object): | ||||
|             self.screen.addstr(5,13, clear_bar, curses.A_NORMAL) | ||||
|             self.screen.addstr(5,13, " - you can't water a dead plant :(", curses.A_NORMAL) | ||||
| 
 | ||||
|     def format_garden_data(self,this_garden): | ||||
|         plant_table = "" | ||||
|         # TODO: include only live plants maybe | ||||
|         for plant_id in this_garden: | ||||
|             if this_garden[plant_id]: | ||||
|                 if not this_garden[plant_id]["dead"]: | ||||
|                     this_plant = this_garden[plant_id] | ||||
|                     plant_table += this_plant["owner"] + " - " | ||||
|                     plant_table += this_plant["age"] + " - " | ||||
|                     plant_table += this_plant["description"] + " - " | ||||
|                     plant_table += str(this_plant["score"]) + "\n" | ||||
|         return plant_table | ||||
| 
 | ||||
|     def draw_garden(self): | ||||
|         # Draws neighborhood | ||||
|         clear_bar = " " * (self.maxx-2) + "\n" | ||||
|         control_keys = [curses.KEY_UP, curses.KEY_DOWN, curses.KEY_LEFT, curses.KEY_RIGHT] | ||||
|         # load data | ||||
|         with open(self.garden_file_path, 'rb') as f: | ||||
|             this_garden = pickle.load(f) | ||||
|         # format data | ||||
|         if not self.gardenmenutoggle: | ||||
|             plant_table_formatted = self.format_garden_data(this_garden) | ||||
|             self.gardenmenutoggle = not self.gardenmenutoggle | ||||
|         else: | ||||
|             plant_table_formatted = "" | ||||
|             for plant in this_garden: | ||||
|                 if not this_garden[plant]["dead"]: | ||||
|                     plant_table_formatted += clear_bar | ||||
|             self.gardenmenutoggle = not self.gardenmenutoggle | ||||
| 
 | ||||
|         for y, line in enumerate(plant_table_formatted.splitlines(), 2): | ||||
|             self.screen.addstr(y+12, 2, line) | ||||
|         self.screen.refresh() | ||||
| 
 | ||||
|     def draw(self): | ||||
|         # Draw the menu and lines | ||||
|         # TODO: this needs to either display the default menu screen or the | ||||
|         # garden/leaderboard thing  based on self.gardenmenutoggle | ||||
|         # TODO: display refresh is hacky. Could be more precise | ||||
|         self.screen.refresh() | ||||
|         self.screen.border(0) | ||||
|         # TODO: separate screen for garden menu, interactive | ||||
|         # if self.gardenmenutoggle: | ||||
|         #     self.draw_garden() | ||||
|         # else: | ||||
|         #     self.draw_default() | ||||
|         try: | ||||
|             self.draw_default() | ||||
|             self.screen.refresh() | ||||
|         except Exception as exception: | ||||
|             # Makes sure data is saved in event of a crash due to window resizing | ||||
|             self.screen.addstr(0,0,"Enlarge terminal!") | ||||
|             self.__exit__() | ||||
|             traceback.print_exc() | ||||
| 
 | ||||
|     def update_plant_live(self): | ||||
|         # Updates plant data on menu screen, live! | ||||
|         # Will eventually use this to display ascii art... | ||||
| @ -194,6 +160,167 @@ class CursedMenu(object): | ||||
|         self.selected = self.selected % len(self.options) | ||||
|         return | ||||
| 
 | ||||
|     def format_garden_data(self,this_garden): | ||||
| 
 | ||||
|         plant_table = "" | ||||
|         for plant_id in this_garden: | ||||
|             if this_garden[plant_id]: | ||||
|                 if not this_garden[plant_id]["dead"]: | ||||
|                     this_plant = this_garden[plant_id] | ||||
|                     plant_table += this_plant["owner"] + " - " | ||||
|                     plant_table += this_plant["age"] + " - " | ||||
|                     plant_table += str(this_plant["score"]) + " points - " | ||||
|                     plant_table += this_plant["description"] + "\n" | ||||
|         return plant_table | ||||
| 
 | ||||
|     def draw_garden(self): | ||||
|         # Draws neighborhood | ||||
|         clear_bar = " " * (self.maxx-2) + "\n" | ||||
|         control_keys = [curses.KEY_UP, curses.KEY_DOWN, curses.KEY_LEFT, curses.KEY_RIGHT] | ||||
|         # load data | ||||
|         with open(self.garden_file_path, 'rb') as f: | ||||
|             this_garden = pickle.load(f) | ||||
|         # format data | ||||
|         if not self.gardenmenutoggle: | ||||
|             plant_table_formatted = self.format_garden_data(this_garden) | ||||
|             self.gardenmenutoggle = not self.gardenmenutoggle | ||||
|         else: | ||||
|             plant_table_formatted = clear_bar | ||||
|             for plant in this_garden: | ||||
|                 if not this_garden[plant]["dead"]: | ||||
|                     plant_table_formatted += clear_bar | ||||
|             self.gardenmenutoggle = not self.gardenmenutoggle | ||||
| 
 | ||||
|         for y, line in enumerate(plant_table_formatted.splitlines(), 2): | ||||
|             self.screen.addstr(y+17, 2, line) | ||||
|         self.screen.refresh() | ||||
| 
 | ||||
|     def get_plant_description(self, this_plant): | ||||
|         1==1 | ||||
|         output_text = "" | ||||
|         this_species = this_plant.species_dict[this_plant.species] | ||||
|         this_color = this_plant.color_dict[this_plant.color] | ||||
|         this_stage = this_plant.stage | ||||
| 
 | ||||
|         stage_descriptions = { | ||||
|                 0:[ | ||||
|             "You're excited about your new seed.", | ||||
|             "You wonder what kind of plant your seed will grow into.", | ||||
|             "You're ready for a new start with this plant.", | ||||
|             "You're tired of waiting for your seed to grow.", | ||||
|             "You wish your seed could tell you what it needs.", | ||||
|             ], | ||||
|                 1:[ | ||||
|             "The seedling fills you with hope.", | ||||
|             "You can make out a tiny leaf - or is that a thorn?", | ||||
|             "You can feel the seedling looking back at you.", | ||||
|             "You kiss your seedling good night.", | ||||
|             "You think about all the seedlings who came before it.", | ||||
|             "You and your seedling make a great team.", | ||||
|             ], | ||||
|                 2:[ | ||||
|             "The " + this_species + " makes you feel relaxed.", | ||||
|             "You sing a song to your " + this_species + ".", | ||||
|             "You quietly sit with your " + this_species + " for a few minutes.", | ||||
|             "Your " + this_species + " looks pretty good.", | ||||
|             "You play loud techno to your " + this_species + ".", | ||||
|             ], | ||||
|                 3:[ | ||||
|             "Your " + this_species + " is growing nicely!", | ||||
|             "You're proud of the dedication it took to grow your " + this_species + ".", | ||||
|             "The " + this_species + " looks good.", | ||||
|             "You think how good this " + this_species + " would look on steroids.", | ||||
|             "The buds of your " + this_species + " are about to bloom.", | ||||
|             ], | ||||
|                 4:[ | ||||
|             "The " + this_color + " flowers look nice on your " + this_species +"!", | ||||
|             "The " + this_color + " flowers have bloomed and fill you with desire.", | ||||
|             "The " + this_color + " flowers of your " + this_species + " remind you of your childhood.", | ||||
|             "The " + this_species + " has grown beautiful " + this_color + " flowers.", | ||||
|             "The " + this_color + " petals remind you of your favorite shirt.", | ||||
|             ], | ||||
|                 5:[ | ||||
|             "You fondly remember all of the time you spent caring for your " + this_species + ".", | ||||
|             "Your " + this_species + " looks old and wise.", | ||||
|             "Seed pods have grown on your " + this_species + ".", | ||||
|             "The " + this_species + " fills you with love.", | ||||
|             "The " + this_species + " reminds you of your first crush.", | ||||
|             ], | ||||
|                 99:[ | ||||
|             "You wish you had taken better care of your plant.", | ||||
|             "If only you had watered your plant more often..", | ||||
|             "Your plant is dead, there's always next time.", | ||||
|             "You cry over the withered leaves of your plant.", | ||||
|             "Your plant died. Maybe you need a fresh start.", | ||||
|             ], | ||||
|         } | ||||
|         # self.life_stages is tuple containing length of each stage | ||||
|         # (seed, seedling, young, mature, flowering) | ||||
|         # if stage == 0 == seed | ||||
|         if this_plant.dead: | ||||
|             this_stage = 99 | ||||
| 
 | ||||
|         this_stage_descriptions = stage_descriptions[this_stage] | ||||
|         description_num = random.randint(0,len(this_stage_descriptions) - 1) | ||||
|         if this_stage <= 4: | ||||
|             # Growth hint | ||||
|             if this_stage >= 1: | ||||
|                 last_growth_at = this_plant.life_stages[this_stage - 1] | ||||
|             else: | ||||
|                 last_growth_at = 0 | ||||
|             ticks_since_last = this_plant.ticks - last_growth_at | ||||
|             ticks_between_stage = this_plant.life_stages[this_stage] - last_growth_at | ||||
|             if ticks_since_last >= ticks_between_stage * 0.8: | ||||
|                 output_text += "You notice your plant looks different.\n" | ||||
| 
 | ||||
|         output_text += this_stage_descriptions[description_num] + "\n" | ||||
| 
 | ||||
|         # issue 1 - referencing anything past 4 on life stages breaks | ||||
|         # issue 2 - 80% using plant ticks doesn't really work since it shifts | ||||
|         # each time. need to use the difference between 2 stages, and then | ||||
|         # plant ticks minus last stage | ||||
| 
 | ||||
|         if this_stage == 1: | ||||
|             species_options = [this_plant.species_dict[this_plant.species], | ||||
|                     this_plant.species_dict[(this_plant.species+3) % len(this_plant.species_dict)], | ||||
|                     this_plant.species_dict[(this_plant.species-3) % len(this_plant.species_dict)]] | ||||
|             random.shuffle(species_options) | ||||
|             plant_hint = "It could be a(n) " + species_options[0] + ", " + species_options[1] + ", or " + species_options[2] | ||||
|             output_text += plant_hint + ".\n" | ||||
| 
 | ||||
|         if this_stage == 2: | ||||
|             # TODO: more descriptive rarity | ||||
|             if this_plant.rarity >= 2: | ||||
|                 rarity_hint = "You feel like your plant is special." | ||||
|                 output_text += rarity_hint + ".\n" | ||||
| 
 | ||||
|         if this_stage == 3: | ||||
|             color_options = [this_plant.color_dict[this_plant.color], | ||||
|                     this_plant.color_dict[(this_plant.color+3) % len(this_plant.color_dict)], | ||||
|                     this_plant.color_dict[(this_plant.color-3) % len(this_plant.color_dict)]] | ||||
|             random.shuffle(color_options) | ||||
|             plant_hint = "You can see the first hints of " + color_options[0] + ", " + color_options[1] + ", or " + color_options[2] | ||||
|             output_text += plant_hint + ".\n" | ||||
| 
 | ||||
|         return output_text | ||||
| 
 | ||||
|     def draw_plant_description(self, this_plant): | ||||
|         clear_bar = " " * (self.maxx-2) + "\n" | ||||
|         control_keys = [curses.KEY_UP, curses.KEY_DOWN, curses.KEY_LEFT, curses.KEY_RIGHT] | ||||
|         # load data | ||||
|         # format data | ||||
|         if not self.looktoggle: | ||||
|             output_string = self.get_plant_description(this_plant) | ||||
|             self.looktoggle = not self.looktoggle | ||||
|         else: | ||||
|             output_string = clear_bar | ||||
|             output_string += clear_bar*3 | ||||
|             self.looktoggle = not self.looktoggle | ||||
| 
 | ||||
|         for y, line in enumerate(output_string.splitlines(), 2): | ||||
|             self.screen.addstr(y+12, 2, line) | ||||
|         self.screen.refresh() | ||||
| 
 | ||||
|     def draw_instructions(self): | ||||
|         if not self.instructiontoggle: | ||||
|             instructions_txt = """welcome to botany. you've been given a seed | ||||
| @ -222,12 +349,17 @@ available in the readme :) | ||||
|     def handle_request(self, request): | ||||
|         '''This is where you do things with the request''' | ||||
|         if request == None: return | ||||
|         if request == "kill": | ||||
|             self.plant.kill_plant() | ||||
|         if request == "new": | ||||
|             self.plant.new_seed(self.plant.file_name) | ||||
|         if request == "start over": | ||||
|             self.plant.start_over() | ||||
|         if request == "water": | ||||
|             self.plant.water() | ||||
|         if request == "look": | ||||
|             # try: | ||||
|             self.draw_plant_description(self.plant) | ||||
|            #  except Exception as exception: | ||||
|            #      self.screen.addstr(0,0,"Enlarge terminal!") | ||||
|            #      self.__exit__() | ||||
|            #      traceback.print_exc() | ||||
|         if request == "instructions": | ||||
|             try: | ||||
|                 self.draw_instructions() | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user