Introduction
This all started with a discord bot I was building for friends. I was thinking of neat features to add when I found someone post a “star field” in another discord server. I thought it would be fun to have a algorithm that could generate random star fields on demand. Achieving this was fairly simple but got me thinking, is it possible to force the algorithm to generate a star field from a seed value?
I need my space
First off what does one of these star fields look like?
I had to take a picture because mark down does not play nice with empty spaces. As you can see they are fairly simple with a bunch of small stars then a few emojis for planets and space ships. The trick here is to make sure the background stars spawn more often than the planets. We can achieve this with a dictionary and applying “weights” to each element we want to spawn. Then loop over the list and compare the weight to a random integer selected 1 to 100. If the weight is greater than the integer we print a star!
stars = {':sunny:':1, ':rocket:':1, ':full_moon:':1, ':earth_americas:':1, '✦':20, ' ゚':25, '*':30, ',': 35, '.':35, ' ':80} #Elements with a higher weight will spawn more often.
field = ''
for y in range(6):
for x in range(6):
for z, q in stars.items(): #Iterate over our list of stars and space
if q >= random.randint(0, 100): #Check if our star has spawned or not
field += str(z)
else:
field += str(' ') #If the star did not spawn just print empty space
field += str('\n\n\n\n\n')
Seeds And “Predictability”
Now suppose we want to create the same star field from a given seed. How do we achieve this? This is the same concept behind how minecraft world generation works. Achieving this in python is actually frustratingly simple. All we need to add to our code is the following:
random.seed(seed)
See? Told you it was easy. Here’s how it looks all put together:
import random
def space(arg=None): #Function to generate a star field
if arg == None: #If no seed is passed to the function we will create a random one
seed = random.randint(0, 99999999999999)
random.seed(seed)
else: #If a seed is passed we will use it to generate our random numbers (Which will be the same every time if this seed is used. Even across linux and windows!)
seed = arg
random.seed(seed)
stars = {':sunny:':1, ':rocket:':1, ':full_moon:':1, ':earth_americas:':1, '✦':20, ' ゚':25, '*':30, ',': 35, '.':35, ' ':80}
field = ''
for y in range(6): #Build a 6 x 6 grid of stars. Discord has a 2000 char limit on messages D:
for x in range(6):
for z, q in stars.items():
if q >= random.randint(0, 100): #All calls to random will inherit the seed we selected
field += str(z)
else:
field += str(' ')
field += str('\n\n\n\n\n')
field += '\nSeed: ' + str(seed)
print(field)
space(1220035984966)
Now every time we pass 1220035984966 to our algorithm we will get the same “random” starfield!
Thanks to https://twitter.com/tiny_star_field for the inspiration!
Full Code can be found here: https://github.com/BuckarewBanzai/Random-Star-Field
comments powered by Disqus