here2share

# tk_basic_evolution.py

Aug 16th, 2025
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.36 KB | None | 0 0
  1. # tk_basic_evolution.py
  2. import random
  3. import tkinter as tk
  4.  
  5. LETTER_SUCCESSORS = {
  6.     'a': list('bcdfghjklmnprstvwxz'),
  7.     'b': list('aeiloruy'),
  8.     'c': list('acehlortu'),
  9.     'd': list('aeioruyl'),
  10.     'e': list('abcdefgilmnoprstuvwxz'),
  11.     'f': list('aeiloruy'),
  12.     'g': list('abeiloruy'),
  13.     'i': list('abcdefgilmnoprstuvwxz'),
  14.     'l': list('aeioruyl'),
  15.     'm': list('aeiloruy'),
  16.     'n': list('aeioruy'),
  17.     'o': list('abcdefgilmnoprstuvwxz'),
  18.     'p': list('aehloruy'),
  19.     'r': list('aeioruy'),
  20.     's': list('aeioruyhpt'),
  21.     't': list('aeiohrsy'),
  22.     'u': list('abcdefgilmnoprstuvwxz'),
  23.     'w': list('aeiloruy'),
  24.     'y': list('abcdefgilmnoprstuvwxz'),
  25. }
  26. DOUBLED_LETTERS = set('eltsonrdpfgmbc')
  27. ALPHABET = list(LETTER_SUCCESSORS)
  28. MAX_LENGTH = 120
  29. MAX_SPECIES = 1000
  30. VOWELS = set('aeiouy')
  31. CONSONANTS = set(ALPHABET) - VOWELS
  32.  
  33. species = set(['e'])
  34. extinct_species = {}
  35. all_species_ordered = ['e']
  36. ancestry = {'e': '-'}
  37. fossilization_status = {}
  38. canvas_items = {}
  39.  
  40. root = tk.Tk()
  41. root.title('Brevity Words Evolution')
  42. root.geometry('1080x640+0+0')
  43.  
  44. frame = tk.Frame(root)
  45. frame.pack(fill='both', expand=True)
  46.  
  47. canvas = tk.Canvas(frame, bg='white', width=1000, height=640)
  48. canvas.pack(side='left', fill='both', expand=True)
  49.  
  50. vscrollbar = tk.Scrollbar(frame, orient='vertical', command=canvas.yview)
  51. vscrollbar.pack(side='right', fill='y')
  52. canvas.configure(yscrollcommand=vscrollbar.set)
  53.  
  54. def update_species_on_canvas(specie, index=-1):
  55.     ancestor = ancestry.get(specie, 'Unknown')
  56.     display_text = f"Ancestor: '{ancestor}' >>> Species: '{specie}'"
  57.     if specie in species or len(specie) < 3:
  58.         fill_color = 'black'
  59.     else:
  60.         fill_color = 'red'
  61.         fossil_status = fossilization_status.get(specie, 'not fossilized')
  62.         display_text += f" went extinct{fossil_status}"
  63.        
  64.     if index != -1:
  65.         y_pos = 10 + index * 24
  66.         x_start = 10
  67.    
  68.         text_id = canvas.create_text(x_start, y_pos, anchor='nw', text=display_text, font=('Consolas', 12), fill=fill_color)
  69.         canvas_items[specie] = text_id
  70.        
  71.         canvas.configure(scrollregion=(0, 0, 0, y_pos + 40))
  72.     else:
  73.         canvas.itemconfig(canvas_items[specie], text=display_text, fill=fill_color)
  74.  
  75. def show_species_on_canvas():
  76.     canvas.delete('all')
  77.     canvas_items.clear()
  78.    
  79.     for i, specie in enumerate(all_species_ordered):
  80.         update_species_on_canvas(specie, i)
  81.  
  82. def count_consec_letter_types(word, pos):
  83.     letter = word[pos]
  84.     is_vowel = letter in VOWELS
  85.     count = 1
  86.     i = pos - 1
  87.     while i >= 0:
  88.         if (word[i] in VOWELS) == is_vowel:
  89.             count += 1
  90.             i -= 1
  91.         else:
  92.             break
  93.     i = pos + 1
  94.     while i < len(word):
  95.         if (word[i] in VOWELS) == is_vowel:
  96.             count += 1
  97.             i += 1
  98.         else:
  99.             break
  100.     return count
  101.  
  102. def can_insert_letter(word, index, letter):
  103.     if len(word) + 1 > MAX_LENGTH:
  104.         return False
  105.     new_word = word[:index] + letter + word[index:]
  106.    
  107.     if len(new_word) >= 2 and new_word[0] == new_word[1]:
  108.         return False
  109.    
  110.     start = max(0, index - 2)
  111.     end = min(len(new_word), index + 3)
  112.     for i in range(start, end - 2):
  113.         if new_word[i] == new_word[i + 1] == new_word[i + 2]:
  114.             return False
  115.     if index > 0:
  116.         prev_letter = new_word[index - 1]
  117.         if letter not in LETTER_SUCCESSORS.get(prev_letter, ALPHABET):
  118.             return False
  119.     if index < len(new_word) - 1:
  120.         next_letter = new_word[index + 1]
  121.         if next_letter not in LETTER_SUCCESSORS.get(letter, ALPHABET):
  122.             return False
  123.     consec_count = count_consec_letter_types(new_word, index)
  124.     if consec_count > 2:
  125.         return False
  126.     return True
  127.  
  128. def is_valid_double(parent, insert_index, letter):
  129.     if insert_index != 0:
  130.         candidate = parent[:insert_index] + letter * 2 + parent[insert_index:]
  131.        
  132.         if len(candidate) >= 2 and candidate[0] == candidate[1]:
  133.             return False, None
  134.            
  135.         triple_repeats = any(candidate[i] == candidate[i+1] == candidate[i+2] for i in range(len(candidate) - 2))
  136.         valid_double = True
  137.        
  138.         if insert_index > 0:
  139.             if letter not in LETTER_SUCCESSORS.get(parent[insert_index - 1], ALPHABET):
  140.                 valid_double = False
  141.         if insert_index < len(parent):
  142.             if parent[insert_index] not in LETTER_SUCCESSORS.get(letter, ALPHABET):
  143.                 valid_double = False
  144.         if letter not in LETTER_SUCCESSORS.get(letter, ALPHABET):
  145.             valid_double = False
  146.         if triple_repeats:
  147.             valid_double = False
  148.         if valid_double and (count_consec_letter_types(candidate, insert_index) > 2 or count_consec_letter_types(candidate, insert_index + 1) > 2):
  149.             valid_double = False
  150.            
  151.         return valid_double, candidate
  152.     return False, None
  153.  
  154. def evolve():
  155.     global species, all_species_ordered, ancestry
  156.     new_species = set(species)
  157.     living = [word for word in species if len(word) < MAX_LENGTH]
  158.     attempts = 0
  159.     added = 0
  160.     new_additions = []
  161.    
  162.     while added < 1000 and attempts < 5000:
  163.         attempts += 1
  164.         parent = random.choice(living)
  165.         if len(parent) == 0:
  166.             continue
  167.         letter = random.choice(ALPHABET)
  168.         insert_index = random.randint(0, len(parent))
  169.         if not can_insert_letter(parent, insert_index, letter):
  170.             continue
  171.         if letter in DOUBLED_LETTERS and random.random() < 0.3:
  172.             valid_double, candidate = is_valid_double(parent, insert_index, letter)
  173.             if valid_double:
  174.                 offspring = candidate
  175.             else:
  176.                 offspring = parent[:insert_index] + letter + parent[insert_index:]
  177.         else:
  178.             offspring = parent[:insert_index] + letter + parent[insert_index:]
  179.         if offspring not in species and offspring not in new_species:
  180.             new_species.add(offspring)
  181.             all_species_ordered.append(offspring)
  182.             ancestry[offspring] = parent
  183.             new_additions.append(offspring)
  184.             added += 1
  185.    
  186.     species = new_species
  187.    
  188.     for i, specie in enumerate(new_additions):
  189.         update_species_on_canvas(specie, len(all_species_ordered) - len(new_additions) + i)
  190.  
  191. def extinction():
  192.     global species, extinct_species, fossilization_status
  193.     if len(species) > MAX_SPECIES:
  194.         extinct_amount = random.randint(200, 500)
  195.         to_extinct = random.sample(list(species), extinct_amount)
  196.         for death in to_extinct:
  197.             fossil_status = '' if random.randint(0, 7) else ' and fossilized'
  198.             species.remove(death)
  199.             extinct_species[death] = True
  200.             fossilization_status[death] = fossil_status
  201.             if death not in canvas_items:
  202.                 return
  203.             update_species_on_canvas(death)
  204.  
  205. def run_simulation():
  206.     evolve()
  207.     extinction()
  208.     root.after(1000, run_simulation)
  209.  
  210. def on_mousewheel(event):
  211.     canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
  212.  
  213. canvas.bind_all("<MouseWheel>", on_mousewheel)
  214.  
  215. show_species_on_canvas()
  216. root.after(0, run_simulation)
  217. root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment