I made a python script that simulates how many generations it would take to get a 99th (you can edit this) percentile horse. It impossibly tries to optimize for all 3 of the stats. But it’s pretty cool you can simulate breeding progress. Make sure to edit the parent values to match your 2 top horses. 👍
This assumes that the psudeocode from this post is correct. I’m not 100% certain on how the game sets these values since 1.19.4.
Statistics and Psuedocode for the new Horse Breeding Mechanics byu/pink_cow_moo inMinecraft
Note: The weighting/next gen selection algorithm may not be perfect ` import random import matplotlib.pyplot as plt
# Constants MAX_SPEED = 0.3375 MIN_SPEED = 0.1125 MAX_JUMP = 1.0 MIN_JUMP = 0.4 MAX_HEALTH = 30 MIN_HEALTH = 15
#Inputs (conversion from internal units line 77) parent1 = {‘speed’: 0.3287, ‘jump’: 0.88, ‘health’: 22} parent2 = {‘speed’: 0.3132, ‘jump’: 0.7648, ‘health’: 23}
PERCENTILE_TARGET = 0.99 #Calculate target values, comment out the logic and put a fixed number in front to customize priorites TARGET_SPEED = MIN_SPEED + PERCENTILE_TARGET * (MAX_SPEED – MIN_SPEED) TARGET_JUMP = MIN_JUMP + PERCENTILE_TARGET * (MAX_JUMP – MIN_JUMP) TARGET_HEALTH = 22#MIN_HEALTH + PERCENTILE_TARGET * (MAX_HEALTH – MIN_HEALTH)
def breed_stat(x, y, MIN, MAX): base_value = (abs(x – y) + (MAX – MIN) * 0.3) * ((random.random() + random.random() + random.random()) / 3 – 0.5) + (x + y) / 2 if base_value > MAX: return 2 * MAX – base_value if base_value < MIN: return 2 * MIN – base_value return base_value def calculate_weights(parent1, parent2): speed_diff = abs(parent1[‘speed’] – parent2[‘speed’]) jump_diff = abs(parent1[‘jump’] – parent2[‘jump’]) health_diff = abs(parent1[‘health’] – parent2[‘health’]) total_diff = speed_diff + jump_diff + health_diff weights = { ‘speed’: speed_diff / total_diff * 100, ‘jump’: jump_diff / total_diff * 100, ‘health’: health_diff / total_diff * 100 } return weights weights = calculate_weights(parent1, parent2) def breed(parent1, parent2, weights): offspring = {} speed = breed_stat(parent1[‘speed’]parent2[‘speed’]MIN_SPEED, MAX_SPEED) jump = breed_stat(parent1[‘jump’]parent2[‘jump’]MIN_JUMP, MAX_JUMP) health = breed_stat(parent1[‘health’]parent2[‘health’]MIN_HEALTH, MAX_HEALTH) if weights[‘speed’] * speed + weights[‘jump’] * jump + weights[‘health’] * health > weights[‘speed’] * parent1[‘speed’] + weights[‘jump’] * parent1[‘jump’] + weights[‘health’] * parent1[‘health’]: offspring = {‘speed’: speed, ‘jump’: jump, ‘health’: health} else: offspring = parent1.copy()
return offspring
generations = 250 speeds, jumps, healths = [], [], []
for _ in range(generations): offspring = breed(parent1, parent2, weights) speeds.append(offspring[‘speed’]) jumps.append(offspring[‘jump’]) healths.append(offspring[‘health’])
if (offspring[‘speed’] >= TARGET_SPEED) or (offspring[‘jump’] >= TARGET_JUMP) or (offspring[‘health’] >= TARGET_HEALTH): weights = calculate_weights(parent1, parent2)
if offspring[‘speed’] >= TARGET_SPEED and offspring[‘jump’] >= TARGET_JUMP and offspring[‘health’] >= TARGET_HEALTH: print(f”Reached “+ PERCENTILE_TARGET*100 + “th percentile in all categories after {_ + 1} generations!”) break
parent1 = offspring
# Conversion functions for plotting def speed_to_blocks(speed_value): return speed_value * 42.16
def jump_to_blocks(jump_value): return jump_value * (5.29997 – 1.1093) + 1.1093
def health_to_hearts(health_value): return health_value / 2
converted_speeds = [speed_to_blocks(s) for s in speeds] converted_jumps = [jump_to_blocks(j) for j in jumps] converted_healths = [health_to_hearts(h) for h in healths]
# Plotting fig, host = plt.subplots()
par1 = host.twinx() par2 = host.twinx()
par2.spines[‘right’].set_position((‘outward’, 60)) fig.subplots_adjust(right=0.75)
host.plot(converted_speeds, color=’blue’, label=’Speed’) par1.plot(converted_jumps, color=’green’, label=’Jump’) par2.plot(converted_healths, color=’red’, label=’Health’)
host.set_xlabel(“Generations”) host.set_ylabel(“Speed (blocks/s)”) par1.set_ylabel(“Jump (blocks)”) par2.set_ylabel(“Health (hearts)”)
host.set_ylim(speed_to_blocks(MIN_SPEED), speed_to_blocks(MAX_SPEED)) par1.set_ylim(jump_to_blocks(MIN_JUMP), jump_to_blocks(MAX_JUMP)) par2.set_ylim(health_to_hearts(MIN_HEALTH), health_to_hearts(MAX_HEALTH))
host.legend(loc=’upper left’) par1.legend(loc=’upper center’) par2.legend(loc=’upper right’)
plt.show()`