Add curses menu and watering feature
parent
180a4fe80f
commit
ca4f48105b
50
botany.py
50
botany.py
|
@ -1,7 +1,6 @@
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
import time
|
import time
|
||||||
import pickle
|
import pickle
|
||||||
import curses
|
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
import os.path
|
import os.path
|
||||||
|
@ -145,7 +144,10 @@ class Plant(object):
|
||||||
self.rarity = self.rarity_check()
|
self.rarity = self.rarity_check()
|
||||||
self.ticks = 0
|
self.ticks = 0
|
||||||
self.dead = False
|
self.dead = False
|
||||||
self.filename = this_filename
|
self.file_name = this_filename
|
||||||
|
self.start_time = int(time.time())
|
||||||
|
self.last_time = int(time.time())
|
||||||
|
self.watered_date = 0
|
||||||
|
|
||||||
def rarity_check(self):
|
def rarity_check(self):
|
||||||
# Generate plant rarity
|
# Generate plant rarity
|
||||||
|
@ -155,7 +157,7 @@ class Plant(object):
|
||||||
uncommon_range = round((2/3)*(CONST_RARITY_MAX-common_range))
|
uncommon_range = round((2/3)*(CONST_RARITY_MAX-common_range))
|
||||||
rare_range = round((2/3)*(CONST_RARITY_MAX-common_range-uncommon_range))
|
rare_range = round((2/3)*(CONST_RARITY_MAX-common_range-uncommon_range))
|
||||||
legendary_range = round((2/3)*(CONST_RARITY_MAX-common_range-uncommon_range-rare_range))
|
legendary_range = round((2/3)*(CONST_RARITY_MAX-common_range-uncommon_range-rare_range))
|
||||||
godly_range = round((2/3)*(CONST_RARITY_MAX-common_range-uncommon_range-rare_range-legendary_range))
|
# godly_range = round((2/3)*(CONST_RARITY_MAX-common_range-uncommon_range-rare_range-legendary_range))
|
||||||
|
|
||||||
# print common_range, uncommon_range, rare_range, legendary_range, godly_range
|
# print common_range, uncommon_range, rare_range, legendary_range, godly_range
|
||||||
|
|
||||||
|
@ -163,7 +165,7 @@ class Plant(object):
|
||||||
uncommon_max = common_max + uncommon_range
|
uncommon_max = common_max + uncommon_range
|
||||||
rare_max = uncommon_max + rare_range
|
rare_max = uncommon_max + rare_range
|
||||||
legendary_max = rare_max + legendary_range
|
legendary_max = rare_max + legendary_range
|
||||||
godly_max = legendary_max + godly_range
|
godly_max = CONST_RARITY_MAX
|
||||||
|
|
||||||
# print common_max, uncommon_max, rare_max, legendary_max, godly_max
|
# print common_max, uncommon_max, rare_max, legendary_max, godly_max
|
||||||
if 0 <= rare_seed <= common_max:
|
if 0 <= rare_seed <= common_max:
|
||||||
|
@ -174,7 +176,7 @@ class Plant(object):
|
||||||
rarity = 2
|
rarity = 2
|
||||||
elif rare_max < rare_seed <= legendary_max:
|
elif rare_max < rare_seed <= legendary_max:
|
||||||
rarity = 3
|
rarity = 3
|
||||||
elif legendary_max < rare_seed <= CONST_RARITY_MAX:
|
elif legendary_max < rare_seed <= godly_max:
|
||||||
rarity = 4
|
rarity = 4
|
||||||
return rarity
|
return rarity
|
||||||
|
|
||||||
|
@ -187,6 +189,10 @@ class Plant(object):
|
||||||
# do stage 5 stuff (after fruiting)
|
# do stage 5 stuff (after fruiting)
|
||||||
1==1
|
1==1
|
||||||
|
|
||||||
|
def water(self):
|
||||||
|
# Increase plant growth stage
|
||||||
|
self.watered_date = datetime.datetime.now().date()
|
||||||
|
|
||||||
def mutate_check(self):
|
def mutate_check(self):
|
||||||
# Create plant mutation
|
# Create plant mutation
|
||||||
# TODO: when out of debug this needs to be set to high number (1000
|
# TODO: when out of debug this needs to be set to high number (1000
|
||||||
|
@ -198,7 +204,7 @@ class Plant(object):
|
||||||
mutation = random.randint(0,len(self.mutation_dict)-1)
|
mutation = random.randint(0,len(self.mutation_dict)-1)
|
||||||
if self.mutation == 0:
|
if self.mutation == 0:
|
||||||
self.mutation = mutation
|
self.mutation = mutation
|
||||||
print "mutation!"
|
#print "mutation!"
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
@ -237,9 +243,10 @@ class Plant(object):
|
||||||
if self.stage < len(self.stage_dict)-1:
|
if self.stage < len(self.stage_dict)-1:
|
||||||
if self.ticks == life_stages[self.stage]:
|
if self.ticks == life_stages[self.stage]:
|
||||||
self.growth()
|
self.growth()
|
||||||
print self.parse_plant()
|
#print self.parse_plant()
|
||||||
if self.mutate_check():
|
if self.mutate_check():
|
||||||
print self.parse_plant()
|
1==1
|
||||||
|
#print self.parse_plant()
|
||||||
|
|
||||||
# what kills the plant?
|
# what kills the plant?
|
||||||
|
|
||||||
|
@ -278,6 +285,7 @@ class DataManager(object):
|
||||||
|
|
||||||
def save_plant(self, this_plant):
|
def save_plant(self, this_plant):
|
||||||
# create savefile
|
# create savefile
|
||||||
|
this_plant.last_time = int(time.time())
|
||||||
with open(self.savefile_path, 'wb') as f:
|
with open(self.savefile_path, 'wb') as f:
|
||||||
pickle.dump(this_plant, f, protocol=2)
|
pickle.dump(this_plant, f, protocol=2)
|
||||||
|
|
||||||
|
@ -289,28 +297,42 @@ class DataManager(object):
|
||||||
|
|
||||||
def data_write_json(self, this_plant):
|
def data_write_json(self, this_plant):
|
||||||
# create json file for user to use outside of the game (website?)
|
# create json file for user to use outside of the game (website?)
|
||||||
|
this_plant.watered_date = this_plant.watered_date.strftime("%Y-%m-%d")
|
||||||
json_file = os.path.join(self.botany_dir,self.this_user + '_plant_data.json')
|
json_file = os.path.join(self.botany_dir,self.this_user + '_plant_data.json')
|
||||||
with open(json_file, 'w') as outfile:
|
with open(json_file, 'w') as outfile:
|
||||||
json.dump(this_plant.__dict__, outfile)
|
json.dump(this_plant.__dict__, outfile)
|
||||||
|
|
||||||
|
def whats_happened(self,this_plant):
|
||||||
|
# need to calculate lifetime ticks to determine stage of life
|
||||||
|
# need to calculate if it's been too long since it's watered
|
||||||
|
current_timestamp = int(time.time())
|
||||||
|
current_date = datetime.datetime.now().date()
|
||||||
|
|
||||||
|
time_delta_overall = current_timestamp - this_plant.start_time
|
||||||
|
time_delta_last = current_timestamp - this_plant.last_time
|
||||||
|
time_delta_watered = (current_date - this_plant.watered_date).days
|
||||||
|
# compare timestamp of signout to timestamp now
|
||||||
|
# need to create timestamps to begin with..
|
||||||
|
# create plant birthday = unix datetime
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
my_data = DataManager()
|
my_data = DataManager()
|
||||||
# if plant save file exists
|
# if plant save file exists
|
||||||
if my_data.check_plant():
|
if my_data.check_plant():
|
||||||
print "Welcome back, " + getpass.getuser()
|
#print "Welcome back, " + getpass.getuser()
|
||||||
my_plant = my_data.load_plant()
|
my_plant = my_data.load_plant()
|
||||||
print my_plant.parse_plant()
|
#print my_plant.parse_plant()
|
||||||
# otherwise create new plant
|
# otherwise create new plant
|
||||||
else:
|
else:
|
||||||
print "Welcome, " + getpass.getuser()
|
#print "Welcome, " + getpass.getuser()
|
||||||
#TODO: onboarding, select seed, select whatever else
|
#TODO: onboarding, select seed, select whatever else
|
||||||
my_plant = Plant(my_data.savefile_path)
|
my_plant = Plant(my_data.savefile_path)
|
||||||
my_plant.start_life()
|
my_plant.start_life()
|
||||||
print "Your plant is living :)"
|
#print "Your plant is living :)"
|
||||||
botany_menu = CursedMenu(my_plant)
|
botany_menu = CursedMenu(my_plant)
|
||||||
botany_menu.show([1,2,3], title=' botany ', subtitle='Options')
|
botany_menu.show([1,"water",3], title=' botany ', subtitle='Options')
|
||||||
#raw_input('Press return to save and exit...\n')
|
#raw_input('Press return to save and exit...\n')
|
||||||
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)
|
||||||
print "end"
|
#print "end"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import curses, os, traceback, threading, time
|
import curses, os, traceback, threading, time, datetime
|
||||||
|
|
||||||
class CursedMenu(object):
|
class CursedMenu(object):
|
||||||
|
#TODO: create a side panel with log of events..?
|
||||||
'''A class which abstracts the horrors of building a curses-based menu system'''
|
'''A class which abstracts the horrors of building a curses-based menu system'''
|
||||||
def __init__(self, this_plant):
|
def __init__(self, this_plant):
|
||||||
'''Initialization'''
|
'''Initialization'''
|
||||||
|
@ -17,10 +18,11 @@ class CursedMenu(object):
|
||||||
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
|
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
|
||||||
self.highlighted = curses.color_pair(1)
|
self.highlighted = curses.color_pair(1)
|
||||||
self.normal = curses.A_NORMAL
|
self.normal = curses.A_NORMAL
|
||||||
thread = threading.Thread(target=self.update_plant_live, args=())
|
screen_thread = threading.Thread(target=self.update_plant_live, args=())
|
||||||
thread.daemon = True
|
screen_thread.daemon = True
|
||||||
thread.start()
|
screen_thread.start()
|
||||||
|
# TODO: tweaking this to try to get rid of garble bug
|
||||||
|
self.screen.clear()
|
||||||
|
|
||||||
def show(self, options, title="Title", subtitle="Subtitle"):
|
def show(self, options, title="Title", subtitle="Subtitle"):
|
||||||
'''Draws a menu with the given parameters'''
|
'''Draws a menu with the given parameters'''
|
||||||
|
@ -56,6 +58,7 @@ class CursedMenu(object):
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
'''Draw the menu and lines'''
|
'''Draw the menu and lines'''
|
||||||
|
self.screen.refresh()
|
||||||
self.screen.border(0)
|
self.screen.border(0)
|
||||||
self.screen.addstr(2,2, self.title, curses.A_STANDOUT) # Title for this menu
|
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
|
self.screen.addstr(4,2, self.subtitle, curses.A_BOLD) #Subtitle for this menu
|
||||||
|
@ -66,18 +69,27 @@ class CursedMenu(object):
|
||||||
textstyle = self.highlighted
|
textstyle = self.highlighted
|
||||||
self.screen.addstr(5+index,4, "%d - %s" % (index+1, self.options[index]), textstyle)
|
self.screen.addstr(5+index,4, "%d - %s" % (index+1, self.options[index]), textstyle)
|
||||||
|
|
||||||
|
try:
|
||||||
self.screen.refresh()
|
self.screen.refresh()
|
||||||
|
except Exception as exception:
|
||||||
|
# Makes sure data is saved in event of a crash due to window resizing
|
||||||
|
self.__exit__()
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
def update_plant_live(self):
|
def update_plant_live(self):
|
||||||
|
# TODO: fix thread synchronization issue.. text garbling
|
||||||
|
# Updates plant data on menu screen, live!
|
||||||
|
# Will eventually use this to display ascii art...
|
||||||
while self.exit is not True:
|
while self.exit is not True:
|
||||||
plant_string = self.plant.parse_plant()
|
plant_string = self.plant.parse_plant()
|
||||||
plant_ticks = str(self.plant.ticks)
|
plant_ticks = str(self.plant.ticks)
|
||||||
self.screen.addstr(10,2, plant_string, curses.A_NORMAL)
|
self.screen.addstr(10,2, plant_string, curses.A_NORMAL)
|
||||||
self.screen.addstr(11,2, plant_ticks, curses.A_NORMAL)
|
self.screen.addstr(11,2, plant_ticks, curses.A_NORMAL)
|
||||||
|
if self.plant.watered_date == datetime.datetime.now().date():
|
||||||
|
self.screen.addstr(6,13, " - plant watered already!", curses.A_NORMAL)
|
||||||
|
|
||||||
self.screen.refresh()
|
self.screen.refresh()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
#curses.endwin()
|
|
||||||
#os.system('clear')
|
|
||||||
|
|
||||||
def get_user_input(self):
|
def get_user_input(self):
|
||||||
'''Gets the user's input and acts appropriately'''
|
'''Gets the user's input and acts appropriately'''
|
||||||
|
@ -109,6 +121,9 @@ class CursedMenu(object):
|
||||||
if request == 1:
|
if request == 1:
|
||||||
self.screen.addstr(8,15,str(self.plant.ticks), curses.A_STANDOUT) # Title for this menu
|
self.screen.addstr(8,15,str(self.plant.ticks), curses.A_STANDOUT) # Title for this menu
|
||||||
self.screen.refresh()
|
self.screen.refresh()
|
||||||
|
if request == "water":
|
||||||
|
self.plant.water()
|
||||||
|
|
||||||
|
|
||||||
def __exit__(self):
|
def __exit__(self):
|
||||||
self.exit = True
|
self.exit = True
|
||||||
|
@ -119,4 +134,5 @@ class CursedMenu(object):
|
||||||
|
|
||||||
'''demo'''
|
'''demo'''
|
||||||
# cm = CursedMenu()
|
# cm = CursedMenu()
|
||||||
# cm.show([1,2,3], title=' botany ', subtitle='Options')
|
# cm.show([1,"water",3], title=' botany ', subtitle='Options')
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue