all repos — groupgardenbot @ 78adc3594b992c35bf1041cd9123a20d7bea306b

An extension of the game "botany", originally designed for unix-based systems, to the Telegram Bot API.

Gardening.py (view raw)

  1import random, time, math, datetime, os
  2from Constants import *
  3
  4water_duration = 3600 * 24
  5death_duration = 6 * water_duration
  6stage_factors = (1, 3, 10, 20, 30)
  7indicator_squares = 6
  8mutation_rarity = 20000 # Increase this # to make mutation rarer (chance 1 out of x each second)
  9max_plant_rarity = 256.0
 10
 11class Plant(object):
 12    # This is your plant!
 13    def __init__(self, owner, generation=1):
 14        # Constructor
 15        self.points = 0 # one point per second
 16        self.life_stages = tuple(st * water_duration for st in stage_factors)
 17        self.stage = 0
 18        self.mutation = 0
 19        self.species = random.randint(0, len(species_list) - 1)
 20        self.color = random.randint(0, len(color_list) - 1)
 21        self.name = plant_names[random.randint(0, len(plant_names) - 1)]
 22        self.rarity = self.rarity_check()
 23        self.ticks = 0
 24        self.generation = generation
 25        self.generation_bonus = 1 + (0.2 * (generation - 1))
 26        self.dead = False
 27        self.owner = owner
 28        self.start_time = int(time.time())
 29        self.last_update = self.start_time
 30        self.last_water = self.start_time - water_duration
 31
 32    def update(self):
 33        now = int(time.time())
 34        water_delta = now - self.last_water
 35        if water_delta > death_duration:
 36            self.dead = True
 37            return
 38    
 39        increase = min(water_delta, water_duration) - min(self.last_update - self.last_water, water_duration)
 40
 41        if increase != 0:
 42            self.points += increase
 43            self.mutate_check(increase)
 44
 45        stages = tuple(th / self.generation_bonus for th in self.life_stages) # bonus is applied to stage thresholds
 46        count = 0
 47        closest = None
 48        delta = self.points
 49
 50        for n in stages:
 51            if (n <= delta and (closest is None or (delta - n) < (delta - closest))):
 52                closest = n
 53                count += 1
 54
 55        self.stage = count
 56        self.last_update = now
 57        
 58    def parse_plant(self):
 59        # Converts plant data to human-readable format
 60        output = ""
 61        if self.stage >= 3:
 62            output += rarity_list[self.rarity] + " "
 63        if self.mutation != 0:
 64            output += mutation_list[self.mutation] + " "
 65        if self.stage >= 4:
 66            output += color_list[self.color] + " "
 67        output += stage_list[self.stage] + " "
 68        if self.stage >= 2:
 69            output += species_list[self.species] + " "
 70        return output.strip()
 71
 72    def rarity_check(self):
 73        # Generate plant rarity
 74        rare_seed = random.randint(1,max_plant_rarity)
 75        common_range =    round((2.0 / 3) * max_plant_rarity)
 76        uncommon_range =  round((2.0 / 3) * (max_plant_rarity - common_range))
 77        rare_range =      round((2.0 / 3) * (max_plant_rarity - common_range - uncommon_range))
 78        legendary_range = round((2.0 / 3) * (max_plant_rarity - common_range - uncommon_range - rare_range))
 79
 80        common_max = common_range
 81        uncommon_max = common_max + uncommon_range
 82        rare_max = uncommon_max + rare_range
 83        legendary_max = rare_max + legendary_range
 84        godly_max = max_plant_rarity
 85
 86        if 0 <= rare_seed <= common_max:
 87            return 0
 88        elif common_max < rare_seed <= uncommon_max:
 89            return 1
 90        elif uncommon_max < rare_seed <= rare_max:
 91            return 2
 92        elif rare_max < rare_seed <= legendary_max:
 93            return 3
 94        elif legendary_max < rare_seed <= godly_max:
 95            return 4
 96
 97    def mutate_check(self, increase):
 98        # Create plant mutation
 99        mutation_seed = random.randint(increase, mutation_rarity)
100        if mutation_seed == mutation_rarity:
101            # mutation gained!
102            mutation = random.randint(0, len(self.mutation_list) - 1)
103            if self.mutation == 0:
104                self.mutation = mutation
105                return True
106        else:
107            return False
108
109    def water(self):
110        if not self.dead:
111            self.last_water = int(time.time())
112
113    def start_over(self):
114        next_generation = self.generation if self.dead else self.generation + 1
115        self.__init__(self.owner, next_generation)
116
117def get_plant_water(plant: Plant):
118    water_delta = int(time.time()) - plant.last_water
119    water_left_pct = max(0, 1 - (water_delta/water_duration))
120    water_left = int(math.ceil(water_left_pct * indicator_squares))
121    return f"{water_left * '🟦'}{'⬛' * (indicator_squares - water_left)} {str(round(water_left_pct * 100))}% "
122
123def get_plant_description(plant: Plant):
124    output_text = ""
125    this_species = species_list[plant.species]
126    this_color = color_list[plant.color]
127    this_stage = plant.stage
128    
129    if plant.dead:
130            this_stage = 99
131    try:
132        description_num = random.randint(0,len(stage_descriptions[this_stage]) - 1)
133    except KeyError as e:
134        print(e)
135        description_num = 0
136    # If not fully grown
137    if this_stage <= 4:
138        # Growth hint
139        if this_stage >= 1:
140            last_growth_at = plant.life_stages[this_stage - 1]
141        else:
142            last_growth_at = 0
143        ticks_since_last = plant.ticks - last_growth_at
144        ticks_between_stage = plant.life_stages[this_stage] - last_growth_at
145        if ticks_since_last >= ticks_between_stage * 0.8:
146            output_text += "You notice your plant looks different.\n"
147
148    output_text += get_stage_description(this_stage, description_num, this_species, this_color) + "\n"
149
150    # if seedling
151    if this_stage == 1:
152        species_options = [species_list[plant.species],
153                species_list[(plant.species+3) % len(species_list)],
154                species_list[(plant.species-3) % len(species_list)]]
155        random.shuffle(species_options)
156        plant_hint = "It could be a(n) " + species_options[0] + ", " + species_options[1] + ", or " + species_options[2]
157        output_text += plant_hint + ".\n"
158
159    # if young plant
160    if this_stage == 2:
161        if plant.rarity >= 2:
162            rarity_hint = "You feel like your plant is special."
163            output_text += rarity_hint + ".\n"
164
165    # if mature plant
166    if this_stage == 3:
167        color_options = [color_list[plant.color],
168                color_list[(plant.color+3) % len(color_list)],
169                color_list[(plant.color-3) % len(color_list)]]
170        random.shuffle(color_options)
171        return "You can see the first hints of " + color_options[0] + ", " + color_options[1] + ", or " + color_options[2]
172
173    return output_text
174
175def get_art_filename(plant: Plant):
176    if plant.dead == True: return 'rip.txt'
177    if datetime.date.today().month == 10 and datetime.date.today().day == 31: return 'jackolantern.txt'
178    if plant.stage == 0: return 'seed.txt'
179    if plant.stage == 1: return 'seedling.txt'
180    if plant.stage == 2: return plant_art_list[plant.species]+'1.txt'
181    if plant.stage == 3 or plant.stage == 5: return plant_art_list[plant.species]+'2.txt'
182    if plant.stage == 4: return plant_art_list[plant.species]+'3.txt'
183    return "template.txt"
184
185def get_plant_art(plant: Plant):
186    filename = get_art_filename(plant)
187    # Prints ASCII art from file at given coordinates
188    this_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "art")
189    this_filename = os.path.join(this_dir, filename)
190    this_file = open(this_filename,"r")
191    this_string = this_file.read()
192    this_file.close()
193    return this_string
194
195def get_plant_info(plant: Plant):
196    return f'''
197{get_plant_description(plant)}
198```{get_plant_art(plant)}```
199[{plant.name}, the {plant.parse_plant()}](tg://user?id={plant.owner})
200
201{get_plant_water(plant)}
202
203Points: {plant.points}
204Bonus: x{plant.generation_bonus - 1}
205'''