Gardening.py (view raw)
1import random, time, math, datetime, os
2from Constants import *
3
4water_duration = 3600 # * 24
5stage_factors = (1, 3, 10, 20, 30)
6
7class Plant(object):
8 # This is your plant!
9 def __init__(self, owner, generation=1):
10 # Constructor
11 self.points = 0 # one point per second
12 self.life_stages = tuple(st * water_duration for st in stage_factors)
13 self.stage = 0
14 self.mutation = 0
15 self.species = random.randint(0,len(species_list)-1)
16 self.color = random.randint(0,len(color_list)-1)
17 self.rarity = self.rarity_check()
18 self.ticks = 0
19 self.age_formatted = "0"
20 self.generation = generation
21 self.generation_bonus = 1 + (0.2 * (generation - 1))
22 self.dead = False
23 self.owner = owner
24 self.start_time = int(time.time())
25 self.last_time = int(time.time())
26 self.last_update = int(time.time())
27 # must water plant first day
28 #self.last_water = int(time.time())-(24*3600)-1
29 self.last_water = int(time.time())
30 self.watered_24h = True
31 self.visitors = []
32
33 def update(self):
34
35 # find out stage:
36 self.water_check()
37 if self.dead_check(): # updates self.time_delta_watered
38 return
39
40 self.stage = find_stage(self)
41
42 def parse_plant(self):
43 # Converts plant data to human-readable format
44 output = ""
45 if self.stage >= 3:
46 output += rarity_list[self.rarity] + " "
47 if self.mutation != 0:
48 output += mutation_list[self.mutation] + " "
49 if self.stage >= 4:
50 output += color_list[self.color] + " "
51 output += stage_list[self.stage] + " "
52 if self.stage >= 2:
53 output += species_list[self.species] + " "
54 return output.strip()
55
56 def rarity_check(self):
57 # Generate plant rarity
58 CONST_RARITY_MAX = 256.0
59 rare_seed = random.randint(1,CONST_RARITY_MAX)
60 common_range = round((2.0/3)*CONST_RARITY_MAX)
61 uncommon_range = round((2.0/3)*(CONST_RARITY_MAX-common_range))
62 rare_range = round((2.0/3)*(CONST_RARITY_MAX-common_range-uncommon_range))
63 legendary_range = round((2.0/3)*(CONST_RARITY_MAX-common_range-uncommon_range-rare_range))
64
65 common_max = common_range
66 uncommon_max = common_max + uncommon_range
67 rare_max = uncommon_max + rare_range
68 legendary_max = rare_max + legendary_range
69 godly_max = CONST_RARITY_MAX
70
71 if 0 <= rare_seed <= common_max:
72 return 0
73 elif common_max < rare_seed <= uncommon_max:
74 return 1
75 elif uncommon_max < rare_seed <= rare_max:
76 return 2
77 elif rare_max < rare_seed <= legendary_max:
78 return 3
79 elif legendary_max < rare_seed <= godly_max:
80 return 4
81
82 def dead_check(self):
83 # if it has been >5 days since watering, sorry plant is dead :(
84 self.time_delta_watered = int(time.time()) - self.last_water
85 if self.time_delta_watered > (5 * water_duration):
86 self.dead = True
87 return self.dead
88
89 def water_check(self):
90 self.time_delta_watered = int(time.time()) - self.last_water
91 if self.time_delta_watered <= (water_duration):
92 if not self.watered_24h:
93 self.watered_24h = True
94 return True
95 else:
96 self.watered_24h = False
97 return False
98
99 def mutate_check(self):
100 # Create plant mutation
101 # Increase this # to make mutation rarer (chance 1 out of x each second)
102 CONST_MUTATION_RARITY = 20000
103 mutation_seed = random.randint(1,CONST_MUTATION_RARITY)
104 if mutation_seed == CONST_MUTATION_RARITY:
105 # mutation gained!
106 mutation = random.randint(0,len(self.mutation_list)-1)
107 if self.mutation == 0:
108 self.mutation = mutation
109 return True
110 else:
111 return False
112
113 def growth(self):
114 # Increase plant growth stage
115 if self.stage < (len(stage_list)-1):
116 self.stage += 1
117
118 def water(self):
119 # Increase plant growth stage
120 if not self.dead:
121 self.last_water = int(time.time())
122 self.watered_24h = True
123
124 def start_over(self):
125 # After plant reaches final stage, given option to restart
126 # increment generation only if previous stage is final stage and plant
127 # is alive
128 if not self.dead:
129 next_generation = self.generation + 1
130 else:
131 # Should this reset to 1? Seems unfair.. for now generations will
132 # persist through death.
133 next_generation = self.generation
134 self.kill_plant()
135
136 self.__init__(self.owner, next_generation)
137
138 def kill_plant(self):
139 self.dead = True
140
141def find_stage(plant: Plant):
142 now = int(time.time())
143
144 res1 = min(now - plant.last_water, water_duration)
145 res2 = min(plant.last_update - plant.last_water, water_duration)
146
147 plant.points += max(0, res1 - res2) # max() not necessary but just in case
148
149 #print("generation bonus: ", plant.generation_bonus, ". increase: ", res1 - res2, "max: ", water_duration)
150 plant.last_update = now
151
152 stages = tuple(ti / plant.generation_bonus for ti in plant.life_stages) # bonus is applied to stage thresholds
153 count = 0
154 closest = None
155 delta = plant.points
156
157 for n in stages:
158 if (n <= delta and (closest is None or (delta - n) < (delta - closest))):
159 closest = n
160 count += 1
161
162 #print("plant is in stage", count, "because it passed", closest, "seconds of life")
163 return count
164
165def get_plant_water(plant: Plant):
166 water_delta = time.time() - plant.last_water
167 water_left_pct = max(0, 1 - (water_delta/water_duration)) # 24h
168 water_left = int(math.ceil(water_left_pct * 10))
169 return f"{water_left * '🟦'}{'⬛' * (10 - water_left)} {str(int(water_left_pct * 100))}% "
170
171def get_plant_description(plant: Plant):
172 output_text = ""
173 this_species = species_list[plant.species]
174 this_color = color_list[plant.color]
175 this_stage = plant.stage
176
177 if plant.dead:
178 this_stage = 99
179 try:
180 description_num = random.randint(0,len(stage_descriptions[this_stage]) - 1)
181 except KeyError as e:
182 print(e)
183 description_num = 0
184 # If not fully grown
185 if this_stage <= 4:
186 # Growth hint
187 if this_stage >= 1:
188 last_growth_at = plant.life_stages[this_stage - 1]
189 else:
190 last_growth_at = 0
191 ticks_since_last = plant.ticks - last_growth_at
192 ticks_between_stage = plant.life_stages[this_stage] - last_growth_at
193 if ticks_since_last >= ticks_between_stage * 0.8:
194 output_text += "You notice your plant looks different.\n"
195
196 output_text += get_stage_description(this_stage, description_num, this_species, this_color) + "\n"
197
198 # if seedling
199 if this_stage == 1:
200 species_options = [species_list[plant.species],
201 species_list[(plant.species+3) % len(species_list)],
202 species_list[(plant.species-3) % len(species_list)]]
203 random.shuffle(species_options)
204 plant_hint = "It could be a(n) " + species_options[0] + ", " + species_options[1] + ", or " + species_options[2]
205 output_text += plant_hint + ".\n"
206
207 # if young plant
208 if this_stage == 2:
209 if plant.rarity >= 2:
210 rarity_hint = "You feel like your plant is special."
211 output_text += rarity_hint + ".\n"
212
213 # if mature plant
214 if this_stage == 3:
215 color_options = [color_list[plant.color],
216 color_list[(plant.color+3) % len(color_list)],
217 color_list[(plant.color-3) % len(color_list)]]
218 random.shuffle(color_options)
219 return "You can see the first hints of " + color_options[0] + ", " + color_options[1] + ", or " + color_options[2]
220
221 return output_text
222
223def get_plant_art(plant: Plant):
224
225 if plant.dead == True:
226 filename = 'rip.txt'
227 elif datetime.date.today().month == 10 and datetime.date.today().day == 31:
228 filename = 'jackolantern.txt'
229 elif plant.stage == 0:
230 filename = 'seed.txt'
231 elif plant.stage == 1:
232 filename = 'seedling.txt'
233 elif plant.stage == 2:
234 filename = plant_art_list[plant.species]+'1.txt'
235 elif plant.stage == 3 or plant.stage == 5:
236 filename = plant_art_list[plant.species]+'2.txt'
237 elif plant.stage == 4:
238 filename = plant_art_list[plant.species]+'3.txt'
239
240 # Prints ASCII art from file at given coordinates
241 this_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "art")
242 this_filename = os.path.join(this_dir, filename)
243 this_file = open(this_filename,"r")
244 this_string = this_file.read()
245 this_file.close()
246 return this_string
247
248def get_plant_info(plant: Plant):
249
250 return f'''
251{get_plant_description(plant)}
252```{get_plant_art(plant)}```
253{plant.parse_plant()}
254
255{get_plant_water(plant)}
256
257Points: {plant.points}
258Bonus: x{plant.generation_bonus - 1}
259'''