Update readme and code cleanup

pull/1/head
Jake Funke 2017-03-15 20:56:00 +00:00
parent 0ca4683a1e
commit c30ff07551
3 changed files with 24 additions and 22 deletions

View File

@ -1,5 +1,5 @@
# botany # botany
![Screencap](http://tilde.town/~curiouser/botany.png)
by Jake Funke - jifunks@gmail.com - tilde.town/~curiouser - http://jakefunke.online/ by Jake Funke - jifunks@gmail.com - tilde.town/~curiouser - http://jakefunke.online/
A command line, realtime, community plant buddy. A command line, realtime, community plant buddy.
@ -11,7 +11,8 @@ Check in and water your plant every 24h to keep it growing. 5 days without water
## getting started ## getting started
botany is designed for unix-based systems. Clone into a local directory using `git clone https://github.com/jifunks/botany.git`. Run with `python botany.py`. Water your seed to get started. You can come and go as you please and your plant continues to grow. Make sure to come back and water every 24 hours or your plant won't grow. If your plant goes 5 days without water, it will die! botany is designed for unix-based systems. Clone into a local directory using `git clone https://github.com/jifunks/botany.git`. Run with `python botany.py`. Water your seed to get started. You can come and go as you please and your plant continues to grow. Make sure to come back and water every 24 hours or your plant won't grow. If your plant goes 5 days without water, it will die!
*Note - botany.py must initially be run by the user who cloned/unzipped it
this initalizes the shared data file permissions.*
## features ## features
* Curses-based menu system * Curses-based menu system
* Persistent aging system that allows your plant to grow even when app is closed * Persistent aging system that allows your plant to grow even when app is closed

View File

@ -222,7 +222,7 @@ class Plant(object):
# 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
# even maybe) # even maybe)
CONST_MUTATION_RARITY = 1000 # 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) mutation_seed = random.randint(1,CONST_MUTATION_RARITY)
if mutation_seed == CONST_MUTATION_RARITY: if mutation_seed == CONST_MUTATION_RARITY:
# mutation gained! # mutation gained!
@ -307,6 +307,7 @@ class DataManager(object):
savefile_name = this_user + '_plant.dat' savefile_name = this_user + '_plant.dat'
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')
def __init__(self): def __init__(self):
self.this_user = getpass.getuser() self.this_user = getpass.getuser()
@ -391,9 +392,6 @@ class DataManager(object):
def garden_update(self, this_plant): def garden_update(self, this_plant):
# garden is a dict of dicts # garden is a dict of dicts
# garden contains one entry for each plant id # garden contains one entry for each plant id
# TODO: this should calculate age based on time since start, not just
# when they saved it
# IE someone logged out, still gaining age, just not gaining ticks
age_formatted = self.plant_age_convert(this_plant) age_formatted = self.plant_age_convert(this_plant)
this_plant_id = this_plant.plant_id this_plant_id = this_plant.plant_id
plant_info = { plant_info = {
@ -409,16 +407,19 @@ class DataManager(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)
new_file_check = False new_file_check = False
# TODO: it would be smart to lock this file down somehow, write to
# it only through the software (to prevent tampering)
# TODO: this is not the right way to do this, other users who run
# it can't chmod that file
# TODO: json file also needs to be writeable by all
# os.chmod(self.garden_file_path, 0666)
else: else:
# create empty garden list # create empty garden list and initalize file permissions
this_garden = {} this_garden = {}
new_file_check = True new_file_check = True
open(self.garden_file_path, 'a').close()
open(self.garden_json_path, 'a').close()
# If user has access, modify permissions to allow others to write
# This means the first run has to be by the file owner.
if os.stat(self.garden_file_path).st_uid == os.getuid():
os.chmod(self.garden_file_path, 0666)
if os.stat(self.garden_json_path).st_uid == os.getuid():
os.chmod(self.garden_json_path, 0666)
# if current plant ID isn't in garden list # if current plant ID isn't in garden list
if this_plant.plant_id not in this_garden: if this_plant.plant_id not in this_garden:
this_garden[this_plant_id] = plant_info this_garden[this_plant_id] = plant_info
@ -427,12 +428,12 @@ class DataManager(object):
current_plant_ticks = this_garden[this_plant_id]["score"] 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 this_garden[this_plant_id] = plant_info
# dump garden file
with open(self.garden_file_path, 'wb') as f: with open(self.garden_file_path, 'wb') as f:
pickle.dump(this_garden, f, protocol=2) pickle.dump(this_garden, f, protocol=2)
# dump json file
# create json file from plant_info with open(self.garden_json_path, 'w') as outfile:
garden_json_path = os.path.join(self.game_dir,'garden_file.json')
with open(garden_json_path, 'w') as outfile:
json.dump(this_garden, outfile) json.dump(this_garden, outfile)
return new_file_check return new_file_check

View File

@ -71,7 +71,6 @@ class CursedMenu(object):
self.screen.refresh() self.screen.refresh()
try: try:
self.draw_default() self.draw_default()
self.screen.border(0)
self.screen.refresh() self.screen.refresh()
except Exception as exception: except Exception as exception:
# Makes sure data is saved in event of a crash due to window resizing # Makes sure data is saved in event of a crash due to window resizing
@ -100,6 +99,7 @@ class CursedMenu(object):
#traceback.print_exc() #traceback.print_exc()
def ascii_render(self, filename, ypos, xpos): def ascii_render(self, filename, ypos, xpos):
# Prints ASCII art from file at given coordinates
this_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)),"art") this_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)),"art")
this_filename = os.path.join(this_dir,filename) this_filename = os.path.join(this_dir,filename)
this_file = open(this_filename,"r") this_file = open(this_filename,"r")
@ -111,7 +111,6 @@ class CursedMenu(object):
def draw_default(self): def draw_default(self):
# draws default menu # draws default menu
# TODO: draw bee
clear_bar = " " * (int(self.maxx*2/3)) clear_bar = " " * (int(self.maxx*2/3))
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
@ -142,7 +141,9 @@ class CursedMenu(object):
else: else:
self.screen.addstr(5,13, clear_bar, curses.A_NORMAL) 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) self.screen.addstr(5,13, " - you can't water a dead plant :(", curses.A_NORMAL)
self.ascii_render("bee.txt",-1,self.maxx-27)
# This draws cute ascii from files
self.ascii_render("bee.txt",-1,self.maxx-23)
def update_plant_live(self): def update_plant_live(self):
# updates plant data on menu screen, live! # updates plant data on menu screen, live!
@ -193,13 +194,12 @@ class CursedMenu(object):
this_plant = this_garden[plant_id] this_plant = this_garden[plant_id]
plant_table += this_plant["owner"] + " - " plant_table += this_plant["owner"] + " - "
plant_table += this_plant["age"] + " - " plant_table += this_plant["age"] + " - "
plant_table += str(this_plant["score"]) + " points - " plant_table += str(this_plant["score"]) + "p - "
plant_table += this_plant["description"] + "\n" plant_table += this_plant["description"] + "\n"
return plant_table return plant_table
def draw_garden(self): def draw_garden(self):
# draws neighborhood # draws neighborhood
# TODO: use age from start date to now, not ticks or static
clear_bar = " " * (self.maxx-2) + "\n" clear_bar = " " * (self.maxx-2) + "\n"
clear_block = clear_bar * 5 clear_block = clear_bar * 5
control_keys = [curses.KEY_UP, curses.KEY_DOWN, curses.KEY_LEFT, curses.KEY_RIGHT] control_keys = [curses.KEY_UP, curses.KEY_DOWN, curses.KEY_LEFT, curses.KEY_RIGHT]