Title: Extraterrestrial
Description: A randomly generated planetary system, some more odd than others.
ZIP file: https://drive.google.com/file/d/1yUczalct7xfK-ImtEHVy2psxaDYRlB W0/view?usp=sharing
Sample Chapter: https://drive.google.com/file/d/1Fiws_jW0sUUF4xBt384MC7pvyvD-mh4f/view?usp=sharing
For the generative text project, I knew that I wanted to create something related to sci-fi, as I've been taking a sci-fi literature class and was inspired by the idea of using generated text and image to explore "the unknown".
As someone who doesn't find writing natural, I began with the image generator. To make the images of the planets, I randomly generated two colors. I then used p5.js' "lerpColor" function to create a gradient between these two that would determine the color palette for each planet. I then used perlin noise to decide the ranges for 3 colors along that gradient. Each planet was also given a random number of moons, and a random radius size. Later on, this became attached to the random moons and radii that the text itself was generating.
Generating the text itself proved to be a bit frustrating. I first started by generating the name of the planets themselves. The text corpora had a list of planets, and I used wikipedia to find an additional list of minor planets and moons. From these, I randomly generated names for the planets by randomly choosing two names, and splicing random amounts of their characters together. For the name of each system, I simply chose a name from the list.
For the generated text, I used context-free grammar through Rita.js. For each planet, the name, number of moons, moon names, and radius of the planet would be randomly chosen. Then a type of planet (exoplanet, ice planet, terrestrial, etc) would be chosen, and a corresponding climate would be selected. Based on the climate, the habitability and the types of flora and fauna would be selected. Finally, a the generator would choose from a list of possible "other interests" of the planet, such as it being a location that is good for mining, choosing a material from a list from the text corpora of metals.
I would love to revisit this project in the future to dive deeper into the complexity of the generative text. While the results are different from one to the next, they clearly all follow the same structure, which isn't that interesting. I'd be interested to try using Wikipedia's API to potentially use Markov chaining and Rita.js to filter through descriptions of planets from sci-fi novels. I think this project has the potential for something interesting, but it's definitely not there yet.
Code:
Images:
// noprotect
var radius;
var color1;
var color2;
var doRefresh;
var moons;
var axis;
var rings;
var moonNums;
var radii;
var count;
function setup() {
createCanvas(800, 800);
doRefresh = true;
rings = false;
moonNums =[
3,
2,
1,
2,
3,
0,
2,
2,
3,
0,
1
]
radii =[
66083,
48507,
44055,
44710,
68424,
4328,
46568,
40628,
67003,
23938,
55680
]
count = -1;
}
function draw() {
if (doRefresh) {
color1 = color(random(0,255), random(0,255), random(0,255));
color2 = color(random(0,255), random(0,255), random(0,255));
moons = moonNums[count];
noiseSeed(random(0, 9999999));
radius = map(radii[count], 3000, 70000, 40, 300);
axis = random(0, PI/3);
rings = random(0, 1);
if (rings > 0.9) rings = true;
background(0);
noStroke();
for (var r = 0; r < height; r ++) {
for (var c = 0; c < width; c ++) {
if((sqrt(sq(r-height/2)+sq(c-width/2)) < radius))
{
var noiseVal = noise(0.02 * r, 0.02 * c);
if(noiseVal < 0.25)
fill(lerpColor(color1, color2, 0.25));
if(noiseVal < 0.5 && noiseVal > 0.25)
fill(lerpColor(color1, color2, 0.5));
if(noiseVal < 1.0 && noiseVal > 0.5)
fill(lerpColor(color1, color2, 0.75));
ellipse(r,c,2,2);
}
else
{
var star = random(0,1);
if(star < 0.00005)
{
fill(255);
ellipse(r,c,3,3);
}
}
}
}
for(var m = 0; m < moons; m++)
{
fill(lerpColor(color1, color(255), 1/m));
var rad = random(radius*0.15, radius*0.4);
var x = random(10, rad*2);
var y = random(height/2-50, height/2+50);
if(m % 2 == 0)
{
ellipse(width/2-radius-x+20, y, rad, rad);
}
else
{
ellipse(width/2+radius+x-20, y, rad, rad);
}
}
}
doRefresh = false;
}
function keyPressed() {
saveCanvas('planet' + count, 'png');
}
function mousePressed() {
count++;
doRefresh = true;
} |
// noprotect
var radius;
var color1;
var color2;
var doRefresh;
var moons;
var axis;
var rings;
var moonNums;
var radii;
var count;
function setup() {
createCanvas(800, 800);
doRefresh = true;
rings = false;
moonNums =[
3,
2,
1,
2,
3,
0,
2,
2,
3,
0,
1
]
radii =[
66083,
48507,
44055,
44710,
68424,
4328,
46568,
40628,
67003,
23938,
55680
]
count = -1;
}
function draw() {
if (doRefresh) {
color1 = color(random(0,255), random(0,255), random(0,255));
color2 = color(random(0,255), random(0,255), random(0,255));
moons = moonNums[count];
noiseSeed(random(0, 9999999));
radius = map(radii[count], 3000, 70000, 40, 300);
axis = random(0, PI/3);
rings = random(0, 1);
if (rings > 0.9) rings = true;
background(0);
noStroke();
for (var r = 0; r < height; r ++) {
for (var c = 0; c < width; c ++) {
if((sqrt(sq(r-height/2)+sq(c-width/2)) < radius))
{
var noiseVal = noise(0.02 * r, 0.02 * c);
if(noiseVal < 0.25)
fill(lerpColor(color1, color2, 0.25));
if(noiseVal < 0.5 && noiseVal > 0.25)
fill(lerpColor(color1, color2, 0.5));
if(noiseVal < 1.0 && noiseVal > 0.5)
fill(lerpColor(color1, color2, 0.75));
ellipse(r,c,2,2);
}
else
{
var star = random(0,1);
if(star < 0.00005)
{
fill(255);
ellipse(r,c,3,3);
}
}
}
}
for(var m = 0; m < moons; m++)
{
fill(lerpColor(color1, color(255), 1/m));
var rad = random(radius*0.15, radius*0.4);
var x = random(10, rad*2);
var y = random(height/2-50, height/2+50);
if(m % 2 == 0)
{
ellipse(width/2-radius-x+20, y, rad, rad);
}
else
{
ellipse(width/2+radius+x-20, y, rad, rad);
}
}
}
doRefresh = false;
}
function keyPressed() {
saveCanvas('planet' + count, 'png');
}
function mousePressed() {
count++;
doRefresh = true;
}
Text Generator:
var rg;
var button;
var result;
var x, y;
var moons;
var names;
var Planets = [];
var system;
var size;
var sizes = [];
var moonNums = [];
class Planet {
constructor(name, moonNum, size, description) {
this.name = name;
this.moonNum = moonNum;
this.size = size;
this.description = description;
}
}
function setup() {
result = "click to generate"
createCanvas(400, 400);
background(250);
x = 100;
y = 100;
text(result, x, y, 400, 400);
names = (insert very long list of names here)
];
system = names[floor(random() * names.length)];
rg = new RiGrammar();
rg.loadFrom('grammar_yay.json', grammarReady);
function grammarReady() {
console.log('ready');
// console.log(result);
}
var myJsonObject = {};
myJsonObject.system = system;
myJsonObject.planetarySystem = Planets;
myJsonObject.sizes = sizes;
myJsonObject.moonNums = moonNums;
// Make a button. When you press it, it will save the JSON.
createButton('SAVE POEMS BUTTON')
.position(10, 10)
.mousePressed(function() {
saveJSON(myJsonObject, 'planetDescriptions.json');
});
}
function mousePressed() {
var numPlanets = 11;
for (var i = 0; i < numPlanets; i++) {
var n1 = names[floor(random() * names.length)];
var n2 = names[floor(random() * names.length)];
var n3 = names[floor(random() * names.length)];
var l1 = floor(random(2, n1.length-1));
var l2 = floor(random(2, n2.length-1));
var l3 = floor(random(2, n2.length-1));
var aName = n1.substring(0,l1) + n2.substring(1, l2) + n3.substring(1, l3);
var m = random(0, 1);
var aMoonNum;
if (m < 0.3) { aMoonNum = 0; } else if (m >= 0.3 && m < 0.6) { aMoonNum = 1; } else if (m >= 0.6 && m < 0.8) {
aMoonNum = 2;
} else {
aMoonNum = 3;
}
var aMoons = [];
for (var a = 0; a < aMoonNum; a++) {
aMoons[a] = names[floor(random() * names.length)];
}
var diameter = floor(random(2000, 70000));
var aDescription = "";
newPlanet();
if(i == 0)
{
aDescription = aName + " is the 1st planet in the " + system + " System. It has ";
}
else if(i == 1)
{
aDescription = aName + " is the 2nd planet in the " + system + " System. It has ";
}
else if(i == 2)
{
aDescription = aName + " is the 3rd planet in the " + system + " System. It has ";
}
else
{
aDescription = aName + " is the " + (i+1) + "th planet in the " + system + " System. It has ";
}
if(aMoonNum == 0)
{
aDescription = aDescription + "no moons. ";
}
else if(aMoonNum == 1)
{
aDescription = aDescription + aMoonNum + " moon, which is called " + aMoons[0] + ". ";
}
else if(aMoonNum == 2)
{
aDescription = aDescription + aMoonNum + " moons, which are named " + aMoons[0] + " and " + aMoons[1] + ". ";
}
else if(aMoonNum == 3)
{
aDescription = aDescription + aMoonNum + " moons, which are named " + aMoons[0] + ", " + aMoons[1] + ", and " + aMoons[2] + ". ";
}
size = floor(random(3000, 70000));
aDescription = aDescription + "It has a radius of " + size + " kilometers. ";
aDescription = aDescription + aName + " is " + result;
var aPlanet = new Planet(aName, aMoonNum, size, aDescription);
Planets[i] = aPlanet;
sizes[i] = size;
moonNums[i] = aMoonNum;
}
}
function newPlanet() {
result = rg.expand();
result = result.replace(/% /g, '\n');
console.log("\n" + result);
drawPlanet();
}
function drawPlanet() {
background(250);
text(result, x, y, 200, 200);
} |
var rg;
var button;
var result;
var x, y;
var moons;
var names;
var Planets = [];
var system;
var size;
var sizes = [];
var moonNums = [];
class Planet {
constructor(name, moonNum, size, description) {
this.name = name;
this.moonNum = moonNum;
this.size = size;
this.description = description;
}
}
function setup() {
result = "click to generate"
createCanvas(400, 400);
background(250);
x = 100;
y = 100;
text(result, x, y, 400, 400);
names = (insert very long list of names here)
];
system = names[floor(random() * names.length)];
rg = new RiGrammar();
rg.loadFrom('grammar_yay.json', grammarReady);
function grammarReady() {
console.log('ready');
// console.log(result);
}
var myJsonObject = {};
myJsonObject.system = system;
myJsonObject.planetarySystem = Planets;
myJsonObject.sizes = sizes;
myJsonObject.moonNums = moonNums;
// Make a button. When you press it, it will save the JSON.
createButton('SAVE POEMS BUTTON')
.position(10, 10)
.mousePressed(function() {
saveJSON(myJsonObject, 'planetDescriptions.json');
});
}
function mousePressed() {
var numPlanets = 11;
for (var i = 0; i < numPlanets; i++) {
var n1 = names[floor(random() * names.length)];
var n2 = names[floor(random() * names.length)];
var n3 = names[floor(random() * names.length)];
var l1 = floor(random(2, n1.length-1));
var l2 = floor(random(2, n2.length-1));
var l3 = floor(random(2, n2.length-1));
var aName = n1.substring(0,l1) + n2.substring(1, l2) + n3.substring(1, l3);
var m = random(0, 1);
var aMoonNum;
if (m < 0.3) { aMoonNum = 0; } else if (m >= 0.3 && m < 0.6) { aMoonNum = 1; } else if (m >= 0.6 && m < 0.8) {
aMoonNum = 2;
} else {
aMoonNum = 3;
}
var aMoons = [];
for (var a = 0; a < aMoonNum; a++) {
aMoons[a] = names[floor(random() * names.length)];
}
var diameter = floor(random(2000, 70000));
var aDescription = "";
newPlanet();
if(i == 0)
{
aDescription = aName + " is the 1st planet in the " + system + " System. It has ";
}
else if(i == 1)
{
aDescription = aName + " is the 2nd planet in the " + system + " System. It has ";
}
else if(i == 2)
{
aDescription = aName + " is the 3rd planet in the " + system + " System. It has ";
}
else
{
aDescription = aName + " is the " + (i+1) + "th planet in the " + system + " System. It has ";
}
if(aMoonNum == 0)
{
aDescription = aDescription + "no moons. ";
}
else if(aMoonNum == 1)
{
aDescription = aDescription + aMoonNum + " moon, which is called " + aMoons[0] + ". ";
}
else if(aMoonNum == 2)
{
aDescription = aDescription + aMoonNum + " moons, which are named " + aMoons[0] + " and " + aMoons[1] + ". ";
}
else if(aMoonNum == 3)
{
aDescription = aDescription + aMoonNum + " moons, which are named " + aMoons[0] + ", " + aMoons[1] + ", and " + aMoons[2] + ". ";
}
size = floor(random(3000, 70000));
aDescription = aDescription + "It has a radius of " + size + " kilometers. ";
aDescription = aDescription + aName + " is " + result;
var aPlanet = new Planet(aName, aMoonNum, size, aDescription);
Planets[i] = aPlanet;
sizes[i] = size;
moonNums[i] = aMoonNum;
}
}
function newPlanet() {
result = rg.expand();
result = result.replace(/% /g, '\n');
console.log("\n" + result);
drawPlanet();
}
function drawPlanet() {
background(250);
text(result, x, y, 200, 200);
}
Grammar.js file:
{
"": [
""
],
"": [
""
],
"" : [
"",
"The planet's deposits make it the location of a valuable mining colony.",
"",
"The planet is a popular tourist desination in the solar system.",
"",
"Attempts have been made to begin terraforming here.",
"It has the potential for colonization in the future.",
"",
"It is unlikely humans will ever visit."
],
"" : [
"",
"",
"",
""
],
"" : [
"Due to the high amount of in the atmosphere, nothing can survive. ",
"Although beautiful, is incapable of sustaining life. ",
"It is incapable of sustaining life. ",
"No life has been found. ",
"There is little chance of life. ",
"There is no chance of life. "
],
"" : [
"frigid temperatures",
"freezing temperatures",
"constant snowstorms",
"constant blizzards",
"constant hail"
],
"" : [
"Its proximity to the sun and thin atmosphere cause the heat to be almost unbearable. ",
"The planet is known for its constant violent sandstorms. "
],
"" : [
"The surface is covered with boiling lava. "
],
"" : [
"There is very little life here. The climate mainly consists of <1>, and as such only small shrubs and trees are able to grow. ",
"There is very little life here. The climate is entirely <1H>, and as such life here consists mainly of shrubs and small mammals. "
],
"": [
"There is some life here. The planet is mainly covered with <2>, with a variety of , , and . "
],
"" : [
"There is an abundance of life here. It is known for its <3>, which are home to many types of and . "
],
"" : [
"birds",
"bats",
"small animals",
"butterflies",
"mammals",
"reptiles",
"insects",
"arachnids"
],
"" : [
"trees",
"flowers",
"mosses",
"plants"
],
"" : [
],
"" : [
" It is also home to -like aliens who , and are known for being , creatures. ",
" It is also home to -like aliens who , and are known for being , creatures. ",
" It is also home to -like aliens who , and are known for being , creatures. "
],
"" : [
"are highly intelligent and advanced",
"are pretty stupid",
"have only begun to develop tools"
],
"<1>" : [
"tundras",
"dry deserts",
"hot deserts",
"semiarid deserts"
],
"<1H>" : [
"dry deserts",
"deserts",
"semiarid deserts"
],
"<2>" : [
"savannas",
"forests"
],
"<3>" : [
"tropical forests",
"deciduous forests",
"tropical regions",
"forests",
"swamps"
],
"" : [
"The waters here house numerous species of plants and animals, both large and small. ",
"Here, the fauna include many species of fish and some mammals, such as whales and dolphins. Much of the sea life here feeds on the abundant plankton. ",
"Flora are represented primarily by seaweed while the fauna, since it is very nutrient-rich, include all sorts of bacteria, fungi, sponges, sea anemones, worms, sea stars, and fishes. ",
"Chemosynthetic bacteria thrive near these vents because of the large amounts of hydrogen sulfide and other minerals they emit. These bacteria are thus the start of the food web as they are eaten by invertebrates and fishes. "
],
"" : [
"a chthonian planet. ",
"a carbon planet. ",
"a coreless planet. ",
"a gas dwarf. ",
"a helium planet. ",
"an ice giant. The make it uninhabitable.",
"an ice planet. The climate is exlusively tundra, and it is known for its . ",
"an iron planet. ",
"a puffy planet. ",
"a silicate planet. ",
"a terrestrial planet. ",
"a gas giant. ",
"a giant. ",
"an exoplanet. ",
"a lava planet. ",
"a mesoplanet. ",
"a telluric planet. ",
"a rocky planet. ",
"a protoplanet.",
"an ocean planet. ",
"a desert planet. The climate is mostly <1H>, with little life other than the which call it home."
],
"" : [
"cacti",
"shrubs",
"spiders",
"scorpions",
"moths",
"herbs",
"small trees",
"bushes"
],
"" (insert list of poisons here)
"" (insert long list of animals here) |
{
"": [
""
],
"": [
""
],
"" : [
"",
"The planet's deposits make it the location of a valuable mining colony.",
"",
"The planet is a popular tourist desination in the solar system.",
"",
"Attempts have been made to begin terraforming here.",
"It has the potential for colonization in the future.",
"",
"It is unlikely humans will ever visit."
],
"" : [
"",
"",
"",
""
],
"" : [
"Due to the high amount of in the atmosphere, nothing can survive. ",
"Although beautiful, is incapable of sustaining life. ",
"It is incapable of sustaining life. ",
"No life has been found. ",
"There is little chance of life. ",
"There is no chance of life. "
],
"" : [
"frigid temperatures",
"freezing temperatures",
"constant snowstorms",
"constant blizzards",
"constant hail"
],
"" : [
"Its proximity to the sun and thin atmosphere cause the heat to be almost unbearable. ",
"The planet is known for its constant violent sandstorms. "
],
"" : [
"The surface is covered with boiling lava. "
],
"" : [
"There is very little life here. The climate mainly consists of <1>, and as such only small shrubs and trees are able to grow. ",
"There is very little life here. The climate is entirely <1H>, and as such life here consists mainly of shrubs and small mammals. "
],
"": [
"There is some life here. The planet is mainly covered with <2>, with a variety of , , and . "
],
"" : [
"There is an abundance of life here. It is known for its <3>, which are home to many types of and . "
],
"" : [
"birds",
"bats",
"small animals",
"butterflies",
"mammals",
"reptiles",
"insects",
"arachnids"
],
"" : [
"trees",
"flowers",
"mosses",
"plants"
],
"" : [
],
"" : [
" It is also home to -like aliens who , and are known for being , creatures. ",
" It is also home to -like aliens who , and are known for being , creatures. ",
" It is also home to -like aliens who , and are known for being , creatures. "
],
"" : [
"are highly intelligent and advanced",
"are pretty stupid",
"have only begun to develop tools"
],
"<1>" : [
"tundras",
"dry deserts",
"hot deserts",
"semiarid deserts"
],
"<1H>" : [
"dry deserts",
"deserts",
"semiarid deserts"
],
"<2>" : [
"savannas",
"forests"
],
"<3>" : [
"tropical forests",
"deciduous forests",
"tropical regions",
"forests",
"swamps"
],
"" : [
"The waters here house numerous species of plants and animals, both large and small. ",
"Here, the fauna include many species of fish and some mammals, such as whales and dolphins. Much of the sea life here feeds on the abundant plankton. ",
"Flora are represented primarily by seaweed while the fauna, since it is very nutrient-rich, include all sorts of bacteria, fungi, sponges, sea anemones, worms, sea stars, and fishes. ",
"Chemosynthetic bacteria thrive near these vents because of the large amounts of hydrogen sulfide and other minerals they emit. These bacteria are thus the start of the food web as they are eaten by invertebrates and fishes. "
],
"" : [
"a chthonian planet. ",
"a carbon planet. ",
"a coreless planet. ",
"a gas dwarf. ",
"a helium planet. ",
"an ice giant. The make it uninhabitable.",
"an ice planet. The climate is exlusively tundra, and it is known for its . ",
"an iron planet. ",
"a puffy planet. ",
"a silicate planet. ",
"a terrestrial planet. ",
"a gas giant. ",
"a giant. ",
"an exoplanet. ",
"a lava planet. ",
"a mesoplanet. ",
"a telluric planet. ",
"a rocky planet. ",
"a protoplanet.",
"an ocean planet. ",
"a desert planet. The climate is mostly <1H>, with little life other than the which call it home."
],
"" : [
"cacti",
"shrubs",
"spiders",
"scorpions",
"moths",
"herbs",
"small trees",
"bushes"
],
"" (insert list of poisons here)
"" (insert long list of animals here)