Good Problems for Alphabet Soup

Let’s back up a step. First of all, what do we want in the user experience?

1. We want an engaging game experience. Draw in the user quickly, and then keep them enthralled. This means things need to evolve rapidly into something interesting.
2. A rich environment. With all we are planning, this should be no problem. I see the main problem being the balance between functionality and complexity. We don’t want to bog the game down to the point that it is slow and uncooperative. I think we can achieve this delicate balance through abstraction, while making it richer at the same time.
3. Evolutionary Computation. We want this to work. We want realism. That’s where the entertainment comes in. We want letters to be floating around in Letter Land, colliding with each other, spawning populations of new letters, mutating, reproducing, overcoming obstacles, eating, living, and fighting for survival as realistically as possible.

Now the details, as I see them. To make all of this work, we need three layers (so far):
1. The Cellular Layer – This is dealing with the letters on a cellular scale. Binary bits “alleles” make up the chromosomes (strings) and ultimately letter genomes (2d arrays). The letter library, the comparator and the schemata all operate at this level, being driven by our Genetic Algorithm. Keep in mind, the body cannot live without its cells. This is where the cells are operating on a micro level. The user can only see this by clicking to view a detailed history of any given genome (probably an XML or text file). This is where we’ve been doing all our work so far, completing Phase I of the project. So far, so good.
2. The Physics Layer – This is dealing with the letters on a population scale. The Physics Layer is special because this is where the abstraction exists. The letters take on a new form as physics bodies governed by physical laws and shapes / geometries instead of genomes full of binary chromosomes. The Physics Layer contains the full map of Letter Land. Herein lies the core of the visible evolutionary processes (Genetic Programming, Neural Networks? ). This is where we are at now (phase II), and this is where the problems crop up.
3. The Window Layer – This is dealing with the letters on a body scale. The window is a “chunk” of the globe of letter land, where the user is zooming in on the action. Essentially, this window or magnifying glass is the user interface to Alphabet Soup. Any user interaction we decide to include (implementing new obstacles or food, for instance) will happen here.

Layers
DM = Decision Maker; FFGP = Fitness Function Genetic Program; GA = Genetic Algorithm; EGP = Environmental Genetic Program

With all that in mind, let’s break down our problems, keeping the “functionality versus complexity versus realism” issue at the forefront.

Problem 1: Decision-making. Two letters, a C and an R are about to run into each other. What happens? The sensing organs for both letters realize a collision is imminent, and call on what we’ve proposed as the DGP (Decision-making Genetic Program). Its options are simple: Breed, Flee, or Fight.
- Whenever Breed is chosen, the GA at the Cellular Level is called and run. This has a direct impact on the appearance (therefore, geometry and physics) of the letter at the Physics/Window Layer.
- Whenever Flee is selected, a given amount of thrust is applied to the letter to get it away from the opposing letter.
- When Fight is selected, the letter will use whatever is at its disposal to try to kill (?) the other letter. Think: war over territories.

The DGP is only used for this about-to-collide decision-making procedure. I figured on using the EGP (discussed next) to make any other health/fitness related decisions at the Physics Layer. The reason I chose GP for this decision scenario is because I was thinking of the ant-finding-food problem where its only options were RIGHT, LEFT, FOOD, which could actually just as easily be solved with a GA. Here’s the thing, this “Breed, Flee, Fight” scenario is even simpler than that, which begs the question: Does this step need to involve Genetic Programming at all? It is a simple choice between three options, and it is very localized to the exact moment when the sensing organ calls on it.

So my argument is to do away with the DGP, instead allowing this decision to be completely (wince) random, or something else entirely—such as Fuzzy Logic or Neural Networking—although this would involve a different approach taking into account all of the decision at one time. The only way I see GP being beneficial here is if it were somehow tied into how the decision affects the population as a whole. But here’s my take on that: we do want complexity, yes, but I feel using a GP here is unnecessary and overly complicated, when we could be using EGP instead to be causing the complex, exciting evolution to take place in the Physics Layer.

But I have a better idea yet. One way to keep it from being random but still not requiring too much processing is to give it a set of circumstances, such as: “if R population is greater than 100 and R population is declining, avoid, else attack.” Some simple lines of code like that will cause the about-to-collide letter to make fast, simple, but smart decisions. I think this is the ideal way to do it.

To use the if/then approach, the Decision Maker must have access to information about the current stats of the population, yes, but they do not have to be drawn from the EGP. Instead, I propose we have a pool of stats about the entire population of letters through the use of a number of variables, then the various functions (EGP, Decision-maker, and so on) access the data and use it as they see fit. This object oriented approach modularizes the information and makes the most sense to me.

Any of these ideas would allow these simple, but constantly-taking-place collision decisions to not use so much processing power unnecessarily, thus solving the “too slow” problem. And realism is maintained, by the simple implementation of the if/then statements, and more thoroughly through the use of the EGP (problem 2).

Problem 2: How do we make the Environmental Genetic Program (EGP) function? Well, I think this will play itself out. As long as we keep the pool of variables available to any function, the key to a good EGP will be to assign it a good fitness function determinable by the variables it accesses. This will likely include the physical attributes of the individuals as well as the population as a whole. I think the EGP will be the core to making the game an enjoyable experience, so we need to do it right and think it through. I think we should keep the other facets of EC relatively simple throughout the program, and focus all of the complexity here. And no, we are not there yet.

Problem 3: How are we going to tie the layers together? I saved this one for last because to me it is the most complicated problem to figure out. We have a vague idea for the FFGP (Fitness Function GP), which will work as follows:

Letter ‘C’ has to get around a flying asteroid, but its friction causes it to slow down to the point where the asteroid is going to collide and destroy it. It needs to evolve to be able to evade, so it grows a wall on its right side, thus becoming an ‘O’. This in itself is a problem: How do its genes, being abstractly separate from the physical body, know that the letter is now an ‘O’ and no longer a ‘C’? We’ve proposed using the FFGP to evolve a fitness function at the GA (Cellular) Layer for the GA to evolve to meet the needs of the Physics Layer. This is all still blurry to me.

I think it would be logical that if the C evolves to an O in the Physics realm, this information should be sent to the Cellular Level, matched up to the schemata, and transformed to an O. To me this is still sufficiently complex and realistic, as the EGP at the Physics Level will still be performing the evolution to the different letter, while requiring the GA to “catch up.” The two layers have to work together somehow, otherwise what’s the point of having both layers? Or maybe the Cellular Level can have access to the same data as the Physics Level, and read from the EGP to determine what is going on and how to evolve, but then where is the abstraction—and that all seems too process intensive anyway. This is a point of contention.

The other tie-in between layers is the thread between the Physics Layer and the Window Layer (User Interface). This involves the physics processes constantly going on behind the scenes at the Physics Layer, while using the Window Layer to just focus in on wherever the user wants to look in the population. We will likely not even get to this problem in phase II because we will be starting with a small enough population to watch it play out on a single screen.

These are all good problems because it shows we are making progress. We should start simple at each layer, then add layers of complexity as we get the pieces to work. Next I want to focus on getting a working Physics Layer with Blend and Physics Helper 3. Once we do that, we can deal with the problem combining it all with the Cellular Layer.

Tagged with:
 

Defining Fitness

Keeping Fit
What we have so far:
Having a good definition of fitness is going to be crucial to our success with Alphabet Soup, and any of our games for that matter. So far we have only one fitness factor, a rather rudimentary “meatiness” goal: the more 1s, the better.

Aiming for the maximum fitness of 1, we define an ideally fit chromosome of 16 binary “alleles” as 16/16 =1, or:

chromosome = 1111111111111111 =
1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 = 16/16 = 1 = 100% fit.

Anything less than ideal is given a fitness value such as 13/16 = 0.81, or:

chromosome = 1111110111011101 =
1+1+1+1+1+1+0+1+1+1+0+1+1+1+0+1 = 13/16 = 0.81 = 81% fit.

This is all very simple. Too simple. But it’s a start. The question is, where do we go from here?

In progress:
The next step will be to include the schemata for the letters. Fitness will be a combined value of the “meatiness” and the “likeness” defined by a comparator function. Here is how it will all work:

First we will have the letter genomes in the Binary Letter Library broken down and defined into the final schemata:

charLine[0] = 0*****0000000000

lines 1 thru 14

charLine[15]=0******0000***00

Where there is a “0″, the value is always zero–in any letter in our population. Why calculate that if it is never going to change? The remaining values then, represented by asterisks, will be either 1s or 0s, depending on the letter. The results of the GA generations will be run through the schemata, with the remaining asterisked positions matched up against the letters in the library. Matching to the nearest letter will be easy. Say there are 125 asterisked positions. After the first generation of GA takes place, the fittest-so-far (meatiest individual) is passed through the schemata. All zero-only spots (such as charLine[0][0], charLine[0][6] are dropped immediately. All asterisk “either-or” positions are evaluated. If charLine[0][1] is a ‘1′, it is matched to all letters with a value of ‘1′, and so on. The genome will then take the shape of the letter with the most matching values….

An important technical aspect of this that we have agreed on is to have the comparator only change the way the letters are displayed, while leaving their array intact–aside from the schemata. In other words, the original GA-defined chromosome/genome is maintained, while a copy of itself is stripped to be matched against the schemata. This allows it to maintain its evolutionary integrity with a level of abstraction so more fitness functions can be performed. I will deal more with this later.

So how do we define the new fitness value, with both the schemata (likeness) and meatiness in mind? Here is a 5-step process that should do the job:

1. Take value of current generation individual. Let’s use for genInd[5], say: 0000101011101110

2. Pass through schemata. Let’s use generic letter line 5, which might be 00*****0******00, making genInd[5] now equal 0000101011101100
(the only bit that changes is the second-to-last one, because based on the schema that bit always equals 0).

3. Define “likeness value.” For simplicity’s sake let’s use charAline[5] which equals 0000010001000000. For all bits of genInd[5] that match charAline[5], add a 1:

So, comparing 0000101011101100 (genInd[5]) to 0000010001000000 (charAline[5]), and disregarding schemata characters that are always 0 (blue), we find only 4 bits that match (red), giving genInd[5] the “likeness” value of 4 as compared to charAline[5].

4. Define the “meatiness value.” To incorporate the “meatiness” factor, let’s add an additional +1 to each value of matching letter that is, actually, “1″ (meat). When we add up all the matching value of 1s between genInd[5] and charAline[5], we only get +1: 0000101011101100 compared to 0000010001000000. So, for this particular example, the meatiness value = 1.

5. Add “likeness value” and “meatiness value”.To get the total fitness value, add the likeness value (4) to the meatiness value (1) for a total value of 5.

Note: since this schemata line has 5 characters that are always equal to 0 (shown here: 00*****0******00), they are subtracted from the maximum fitness amount. So, the maximum fitness of this line is 16-5 = 11 possible values that match (“likeness” value), plus the possibility that all of those values are 1s (“meatiness” value), making the total maximum fitness of this line equal to:

11 (max “likeness”) + 11 (max “meatiness”) = 22. So in our example,
4 (likeness) + 1 (meatiness) = 5 was not all that great (5/22 = 23%). Other letters in the alphabet will much likely have higher fitness on this line.

I think this will be a good way to determine total fitness–at least in early versions of Alphabet Soup.

Future awesomeness:
All technicalities aside, this is where Alphabet Soup can get really interesting. This will probably be around… version 3.0 or so. Right now, these are just vague ideas.

Fitness based on letter shape was the original goal of Alphabet Soup all along:

“Hark! Here comes a second generation character, ‘i’, who has lost the vestigial tittle (the dot). Most other letters are unchanged or changed in a negative or neutral way. The lower mass of the ‘i’ makes it faster and take in less calories. Alas, it’s lower weight makes it do less damage and is losing ground to the dastardly ‘T’s and their hearty top most shield. Will the character genes be favorable enough to carry on or will they be lost and another random variation will make itself dominant. At the front of ‘i’s’ and ‘T’s’ war, a fork occurs with the ‘w’s. The ‘w’s strike fast coming down but their double point distributes the impacts, lessoning the effect on harder shelled letters like the ‘T’.”

With this, things like food, environment and the ability to reproduce/fight/defend are all important.

Another idea is this: fitness is dynamic, determined by the players. They change the landscape–by adding obstacles, giving new goals (such as winning a race, building a tower, et cetera). Different letters will be more suited to different tasks, so fitness will vary from task to task. This might keep it more interesting than if fitness was just based on one thing (like meatiness or shape). Also, on the note of shape mattering–maybe shape won’t matter as much as far as fitness value is concerned, however shape may be important for movement in Farseer if we can get the physics of it right. So… if the goal is to get over a mountain or something, the shape and physics will be important to the letter’s success, indirectly having an effect on the fitness anyway.

A good comparison is to think of how to keep a Sim alive: by balancing a variety of values that are important to the character’s success at staying alive, such as social value, food, health, activity, recreation, knowledge, and so on. Any of these kinds of ideas could be incorporated into the fitness value to make it more interesting and keep the player more involved in what is happening in the Soup. One important key to this is to allow the Evolutionary Computation to do its thing without interferring. If we can hone that delicate balance between the EC and the player-letter interaction, Alphabet Soup could be great.

The future awesomeness of Alphabet Soup depends on our ability to come up with more fitness ideas, and to make them actually work.

Other considerations:
We have talked a lot about including sensing organs for letters to be able to interact with their environment on a biological level. Also in discussion are color values which may or may not be related to fitness, sensing ability, or overall health of a letter. We will have to deal more with these ideas and see what we can agree on.

One thing we have reached consensus on is the level of abstraction that will be present in our final product. Overall, we are going to let the GA and GP do their things in a very precise way, keeping the Evolutionary Computation aspect as pure as possible–but this will all be going on behind the scenes. The precision in the background will be modified and “rounded” (such as with the schemata) before reaching the eyes of the player. This will allow the letters to maintain their forms, allow the Physics Engine to operate on fixed shapes, and so on. However there will likely be a more abstract level of EC going on as well, such as with the shapes present in the physics engine and how they react to one another. The more levels of EC operating within the game, the more rich the environment and the more capable it will be of surprising us.

But we don’t want the abstraction to completely cover up what is going on behind the scenes.

One way to be able to unite the abstraction with the player’s awareness of what is going on is through keeping a detailed history of each genome in the population. We should somehow tie the chromosomes to their respective genome so that the genome holds its identity and evolutionary lifespan throughout its own history. Maybe stamp each chromosome with some sort of hidden i.d. assigning it to its current genome. These generational histories will provide the owner of the letter with information showing how old the letter is (how many generations it has survived) and each detailed transformation it has undergone during its evolution to its current state. This could be useful for farming, trading or even–who knows–combat? Dog-fighting is illegal, but how about pitting our letters against each other? There are all kinds of scenarios and places we could go with Alphabet Soup. And as the creators of Dwarf Fortress believe, the more ideas we integrate, the better the game might become.

Tagged with:
 

Development Notes

There have been some exciting developments in Alphabet Soup. We now have a functioning Binary-Bitmap Converter, and a working Genetic Algorithm. I thought I’d make some notes on the first few successful runs of the GA, so here goes:

For the simplest Alphabet Soup chromosome, we are using a 16-bit binary string which, while all 1s and 0s, isn’t functioning as a true binary string. Instead, for our simplest calculation of fitness, we are assigning the “meatiest” chromosome (the one with the most 1s) as the fittest individual. So instead of going by the decimal value of 0000001000100101 (which is 549) we are adding the 1s for a value of 4. This cuts back on processing power, especially when dealing with a full 256 bits, and it allows us some easy numbers to work with for churning out a fitness value of any given chromosome. So, the optimal value is 16, represented as: 1111111111111111.

Success!
Success!

Our first run of the GA striving to reach this value with a random starting population has been a surprising success. Reproduction and crossover rapidly increase the fitness no matter what the starting population. The GA often converges on not-quite ideal solutions, but with enough generations the mutations do eventually converge on the correct string. Our mutation rate is set to 10%. The other parameters are: min:0, max:2, crossover:80%, length:16.

These parameters seem to work quite well. I changed the population paramater to see how that affected the runs, and the results were interesting. The following chart describes our first six runs of the “Alpha” Alphabet Soup Genetic Algorithm:

Population     Generations to converge     Total number of individuals    
2 520 1040
2 791 1582
4 273 1092
4 376 1504
50 42 (w/ 2 mutants) 2100
50 63 (w/ 1 mutant) 3150

I found it interesting that convergence seems to happen faster with a smaller population. I was especially surprised at the efficiency with which only two parents managed to converge on the correct solutions. The least number of individuals required to converge was 1,040, which happened with only two in the population, while the longest run required 3,150 individuals–using a population of 50. That’s still not bad, considering the search space contains 65,536 possibilities.

Tagged with:
 

Character Collisions

The binary-bitmap conversion portion of the BBC has already been discussed and is in development. But there are many other aspects of this part of the program that need to be considered, including a physics engine and the motion of the letters. One thing that’s been bugging me is how the letters will react when they run into one another.

Let’s assume that two letters, an ‘A’ and a ‘B’ are floating around in their predetermined environment. They run into each other–what happens?

First of all, we need to clearly define what consitutes a character. There are 256 pixels in the 16×16 square, yes, but most of the border consists of ‘0’s–white space. Is it going to be considered a collision when the outer white pixels of the bitmap collide, or are we going to go with a more literal description of the letters running into each other, i.e. the black pixels (‘1’s)?

I think the second idea makes more sense, even though in computer logic the bitmap touches the other bitmap when the 16×16 squares meet, which causes a kind of predicament for us. The crazy thing about going with option 2 is that it will cause a morphing in the bitmap of at least one of the letters, even before the actual collision takes place. In other words, the ‘A’ bitmap will already change before the genetic code is activated.

                    Purple shows changed pixels:
                    0000000000000000
                    0000000000000000
                    0001111111000000
                    0001111111100000
                    0001000000110000
                    0001000000010000
                    0001000000010000
                    0001000000110000
                    0001111111100000
                    0001111111110000
                    0001000000010000     ‘A’ bitmap becomes:
00000000000001000000010000     0000000000000100
00000001000001000000110000     0000000100000100
00000011100001111111100000     0000001110000111
00000010100001111111000000     0000001010000111
00000110110000000000000000     0000011011000000
0000010001000000                         0000010001000000
0000110001100000                         0000110001100000
0000100000100000                         0000100000100000
0000100000100000                         0000100000100000
0001111111110000                         0001111111110000
0001111111110000                         0001111111110000
0001000000010000                         0001000000010000
0011000000011000                         0011000000011000
0010000000001000                         0010000000001000
0110000000001100                         0110000000001100
0000000000000000                         0000000000000000

One way around this is to make the border ‘0’s (white pixels) invisible, or transparent to the other letters. Also, we could somehow use them so that when the outer pixels of two letters collide, they activate some sort of “signal” (probably a specific function in the code) that a collision is imminent and that the decision-making procedure needs to occur. Maybe this could even change the white pixels to a different color as an extra visual aid to show that a collision is about to take place somewhere within the soup–a way to highlight the action. Just a thought.

Before:                                             Collision Imminent!
0000000000000000                         0000000000000100
0000000100000000                         0000000100000100
0000001110000000                         0000001110000111
0000001010000000                         0000001010000111
0000011011000000                         0000011011000000
0000010001000000                         0000010001000000
0000110001100000                         0000110001100000
0000100000100000                         0000100000100000
0000100000100000                         0000100000100000
0001111111110000                         0001111111110000
0001111111110000                         0001111111110000
0001000000010000                         0001000000010000
0011000000011000                         0011000000011000
0010000000001000                         0010000000001000
0110000000001100                         0110000000001100
0000000000000000                         0000000000000000

The fight-or-flight function, another good chance for GP to help with decision-making, will then determine: Do I, as an ‘A’…
1. continue toward the ‘B’ (attack),
2. change direction to avoid ‘B’ (retreat),
3. breed with ‘B’ (perform GA/GP)?

The thing is, both letters will be running this function to determine the best course of action. It would be interesting in this scenario to see what would happen if ‘A’ tried attacking while ‘B’ decided to activate the genetic algorithm. What would happen? Who would win? Maybe the program would crash and we’d need to tweak it, but whatever–this is just a brainstorming session.

All this can be figured out. I think the main problem with the white borders in a bitmap will be aesthetics: the collision wouldn’t really look like a collision if just the outer empty sections of the letter boxes are running into each other. We can go with the highlighting/color-changing idea, or maybe we can implement some sort of overlap in the outer white pixels on the bitmaps to show more precise-looking collisions. The speed of the letter movement could also be enough to distract the user’s eye from the extra white space. Then again, as small as a 16×16 bitmap is, the difference is probably subtle enough that it won’t even be noticeable.

Tagged with:
 

Bitmap-Binary Basics

The Bitmap-Binary Converter will likely be the core engine for at least the early versions of Alphabet Soup. To create it, there are a few things we need to consider. The two most glaring questions are how will we read individual pixels, and how will the actual conversion between pixel color and binary code take place? An even more basic consideration is which programming language we will use. I am leaning heavily toward C#, as it seems fully capable of tackling both problems.

There are a couple of ways we could do this. Let’s start with the assumption we begin with the bitmap and define all the colors for a given letter (“A”, for example). This website explains how to access each pixel individually–exactly what we are trying to do.

This is the core of the code allowing the color definition for each pixel based on location within the bitmap:

public void SetPixel(int x, int y, PixelData color)
    {
        PixelData* pixel = PixelAt(x, y);
        *pixel = color;
    }

However this is using ‘unsafe’ code to access each individual pixel. To use ’safe’ code the actual program execution would take forever. So there may be a third alternative worth looking into. And here are more thoughts about this. This is something we are going to have to experiment with to find the best method, or we might have to figure out our own.

To save the bitmap code for future use, we will have to set the black pixels to 1 and white pixels to 0. This will produce 256 characters, ranging from charA[0] to charA[255]. We might have the program write this data to a separate file, or just store it within its own memory.

For visual reference, here is the bitmap in actual size:
A

Here is the ‘A’ bitmap represented in binary:

0000000000000000
0000000100000000
0000001110000000
0000001010000000
0000011011000000
0000010001000000
0000110001100000
0000100000100000
0000100000100000
0001111111110000
0001111111110000
0001000000010000
0011000000011000
0010000000001000
0110000000001100
0000000000000000

Here is the above bitmap referenced in pixel notation (shortened to describe the four corners):

(0,0) through (0,15)

(15,0) through (15,15)

And here is the character equivalent to the above pixels:
charA[0] = (0,0) = value of ‘0′
charA[15] = (0, 15) = value of ‘0′
charA[240] = (15,0) = value of ‘0′
charA[255] = (15,15) = value of ‘0′

Or, we do it the other way: Start with 62 ‘.txt’ files (52 letters and numbers 0-9, or whatever amount we end up with for the base set of characters), each with 256 “0″ and “1″ characters representing the 16×16 bitmap.

Read the text from the file and use the code “if charA[0]=’0′…” / “if charA[0]=’1′…” and the earlier bitmap code to convert each corresponding pixel to black or white by referencing the corresponding pixel within the bitmap. Whenever crossover occurs in the program, it creates a new binary (or .txt) file to represent that organism. I think a thorough understanding of the C# StringBuilder Class is going to come in handy for this, in splicing strings of binary characters and performing other modifications. Again, this will be closely intertwined with the GP or GA code, which will be the determining factor for where the splicing will occur each time.

Basically we’re accomplishing the same thing but from two different directions: bitmap-to-binary or binary-to-bitmap. It will probably be valuable to know how to do this in both directions for purposes of the program anyway. Basic C# data type conversions (string-to-binary-to-decimal-to-chars-to-string and so on) will be instrumental in making this work properly. This should actually be pretty simple; it will just take some time to sort out the details.

What I described above should accomplish the basic functionality of the BBC; once we get this working we can move onto the engine’s more complex functions, such as attributing higher “sensitivity values” to certain pixels and recognizing “contact” with other letters.

*Define Initial Population*

The initial population in the final version of Alphabet Soup may likely contain one of each keyboard character available. For now, for simplicity’s sake, let’s begin with 4 characters: A,B,a,b. In our game, all 4 characters decide to run into each other at once.

First we will convert the 16×16 characters into binary, 0 for gray and 1 for yellow:

A:
0000000000000000
0000000100000000
0000001110000000
0000001010000000
0000011011000000
0000010001000000
0000110001100000
0000100000100000
0000100000100000
0001111111110000
0001111111110000
0001000000010000
0011000000011000
0010000000001000
0110000000001100
0000000000000000

A, Binary String: 0000000000000000000000010000000000000011100000000000001010000000000001101100000000000100010000000000110001100000000010000010000000001000001000000001111111110000000111111111000000010000000100000011000000011000001000000000100001100000000011000000000000000000
A, Binary-Decimal conversion: 95786086615602871731981918389383308042547593781186608

B:
0000000000000000
0000000000000000
0001111111000000
0001111111100000
0001000000110000
0001000000010000
0001000000010000
0001000000110000
0001111111100000
0001111111110000
0001000000010000
0001000000010000
0001000000110000
0001111111100000
0001111111000000
0000000000000000

B, Binary String: 0000000000000000000000000000000000011111110000000001111111100000000100000011000000010000000100000001000000010000000100000011000000011111111000000001111111110000000100000001000000010000000100000001000000110000000111111110000000011111110000000000000000000000
B, Binary-Decimal conversion: 46403387827017775033653233413204161160929512263696

a:
0000000000000000
0000000000000000
0000000000000000
0000001111100000
0000011111110000
0000110000110000
0000000000010000
0000000111110000
0000011111010000
0000110000010000
0000110000110000
0000111001110000
0000011111011000
0000000000000000
0000000000000000
0000000000000000

a, Binary String: 0000000000000000000000000000000000000000000000000000001111100000000001111111000000001100001100000000000000010000000000011111000000000111110100000000110000010000000011000011000000001110011100000000011111011000000000000000000000000000000000000000000000000000
a, Binary-Decimal conversion: 86418088698874722540000455600782178239016967

b:
0000000000000000
0000100000000000
0000100000000000
0000100000000000
0000101111000000
0000111111100000
0000110000110000
0000100000010000
0000100000010000
0000100000010000
0000100000010000
0000110000110000
0000111011100000
0000101111000000
0000000000000000
0000000000000000

b, Binary String: 0000000000000000000010000000000000001000000000000000100000000000000010111100000000001111111000000000110000110000000010000001000000001000000100000000100000010000000010000001000000001100001100000000111011100000000010111100000000000000000000000000000000000000
b, Binary-Decimal conversion: 766259462624453036391004127445265907255673543052767246

So, our Initial Population (POPinit) consists of the following four characters and their decimal representation:
1. (A) 95786086615602871731981918389383308042547593781186608
2. (B) 46403387827017775033653233413204161160929512263696
3. (a) 86418088698874722540000455600782178239016967
4. (b) 766259462624453036391004127445265907255673543052767246

*Define fitness of POPinit*

First, we establish the Total, the Best, the Worst and the Average based on their decimal representations:
Total: (A+B+a+b) 862091952714301014596894421608062875060164244585234517
Best: (b) 766259462624453036391004127445265907255673543052767246
Worst: (a) 86418088698874722540000455600782178239016967
Average: 23958122541618481117083899450474345137254323064508656.25

Based on these findings, we can calculate the chance of Reproduction / Survival for each character.
A: 0.1111088977388315456010566688830799217993208329796695901253… = 11% chance of reproducing
B: 0.0000538264945878643991068686448919016779835612586246604953… = <1% chance of reproducing
a: 0.0000000001002423099146058828565205588056220034311729841463397… = MUCH <1% chance of reproducing
b: 0.8888372756663382800852305796155076177170736023305327652329… = 88% chance of reproducing

*Perform Reproduction Function*

As you can tell from the fitness of each character, the character “b” has by far the best chance at survival, while character “A” is the only other letter with much of a chance at all. In the actual game, the reproduction function will decide who actually survives reproduction so it is impossible to say for sure, but based on these percentages we will go with three b’s and one A surviving to population generation 0.

So, the result of the reproduction function should look something like:

1. (b) 766259462624453036391004127445265907255673543052767246
2. (b) 766259462624453036391004127445265907255673543052767246
3. (b) 766259462624453036391004127445265907255673543052767246
4. (A) 95786086615602871731981918389383308042547593781186608

*Define fitness of gen0″

Again, we determine the total, best, worst and average fitness of the new population, gen0:

Total, better: (b+b+b+A) 2394564474488961980904994300725181029809568222939488346
Best, same: (b) 766259462624453036391004127445265907255673543052767246
Worst, better: (A) 95786086615602871731981918389383308042547593781186608
Average, better: 598641118622240495226248575181295257452392055734872086.5

Note that the Total, Worst, and Average fitness of the population all improved as an expected result of natural selection. The Best fitness, meanwhile stays the same–and it has no chance for improvement until running the next stage of the GA…

*Perform genetic crossover operation on gen0*

Start with 2 parents. Let’s use 3 & 4 as an example with an arbitrary crossover point (we’ll say 170 digits in–though this would actually be determined by the randomly generated genetic operation):

3. (b) 766259462624453036391004127445265907255673543052767246 =
00000000000000000000100000000000000010000000000000001000000000000000101111000000000011111110000000001100001100000000100000010000000010000001000000001000000100000000100000 | (crossover point) 01000000001100001100000000111011100000000010111100000000000000000000000000000000000000

4. (A) 957860866156028717319819183893833080425475937811868 =
00000000000000000000000100000000000000111000000000000010100000000000011011000000000001000100000000001100011000000000100000100000000010000010000000011111111100000001111111 | (crossover point) 11000000010000000100000011000000011000001000000000100001100000000011000000000000000000

From this crossover, we get 2 new offspring characters:

offspring1 (o1):
0000000000000000
0000100000000000
0000100000000000
0000100000000000
0000101111000000
0000111111100000
0000110000110000
0000100000010000
0000100000010000
0000100000010000
0000100000110000
0001000000010000
0011000000011000
0010000000001000
0110000000001100
0000000000000000

o1, Binary String: 0000000000000000000010000000000000001000000000000000100000000000000010111100000000001111111000000000110000110000000010000001000000001000000100000000100000010000000010000011000000010000000100000011000000011000001000000000100001100000000011000000000000000000
o1, Binary-Decimal conversion: 766259462624453036391004127445265907255673543589892144

offspring2 (o2):
0000000000000000
0000000100000000
0000001110000000
0000001010000000
0000011011000000
0000010001000000
0000110001100000
0000100000100000
0000100000100000
0001111111110000
0001111111010000
0000110000110000
0000111011100000
0000101111000000
0000000000000000
0000000000000000

o2, Binary String: 0000000000000000000000010000000000000011100000000000001010000000000001101100000000000100010000000000110001100000000010000010000000001000001000000001111111110000000111111101000000001100001100000000111011100000000010111100000000000000000000000000000000000000
o2, Binary-Decimal conversion: 95786086615602871731981918389383308042547593244061710

So gen1 looks like:
1,2 are the same as before; 3,4 are the offspring of crossover:
1. (b) 766259462624453036391004127445265907255673543052767246
2. (b) 766259462624453036391004127445265907255673543052767246
3. (o1) 766259462624453036391004127445265907255673543589892144
4. (o2) 95786086615602871731981918389383308042547593244061710

*Convert gen1 offspring to valid characters*

Now, 3 and 4 are new shapes that do not correspond with any of our 4 letters. The BBC (Bitmap-to-Binary Converter) will be used to “read” these bitmaps and find the closest letter in the space of possible letters which we will define. So, the offspring will turn into something like “h” and “8″, because those are the closest possibilities within the alphabet.

I was going to include a range in decimal numbers and apply that to the nearest alphabet character within that range, but I don’t think that will work because more often than not the offspring will just end up reverting to one of the two characters from which it was created. From this perspective, the BBC may be a very useful portion of the AS program.

So, o1 become “h” and o2 becomes “8″, converting gen1 characters to:

o1=h:
0000000000000000
0000110000000000
0000110000000000
0000110000000000
0000110111000000
0000111111100000
0000111000110000
0000110000110000
0000110000110000
0000110000110000
0000110000110000
0000110000110000
0000110000110000
0000110000110000
0000000000000000
0000000000000000

h, Binary String: 0000000000000000000011000000000000001100000000000000110000000000000011011100000000001111111000000000111000110000000011000011000000001100001100000000110000110000000011000011000000001100001100000000110000110000000011000011000000000000000000000000000000000000
h, Binary-Decimal conversion: 1149389193936678235951120191876555791760811195370319884

o2=8:
0000001111000000
0000011111100000
0000110000110000
0000100000010000
0000100000010000
0000110000110000
0000011111000000
0000011111100000
0000110000110000
0000100000010000
0000100000010000
0000100000010000
0000110000110000
0000011111100000
0000001111000000
0000000000000000

8, Binary String: 0000001111000000000001111110000000001100001100000000100000010000000010000001000000001100001100000000011111000000000001111110000000001100001100000000100000010000000010000001000000001000000100000000110000110000000001111110000000000011110000000000000000000000
8, Binary-Decimal conversion: 23539885800661303801528815919744719668529798326595472592908

So the gen1 now looks like:
1. (b) 766259462624453036391004127445265907255673543052767246
2. (b) 766259462624453036391004127445265907255673543052767246
3. (h) 1149389193936678235951120191876555791760811195370319884
4. (8) 23539885800661303801528815919744719668529798326595472592908

From which we evaluate the fitness again (“8″ clearly will be the new dominate gene) and so on, generation after generation…

*Conclusion*

This is the basic gist of Alphabet Soup by GA. The final aspect of using GA is to incorporate mutations: the random changing of various pixels within the letters, which will obviously introduce the same effect of crossover in adding to the population of letters. Mutations will only be applied to a small portion of the entire population in each generation, just like in nature. With only 4 characters to choose from, let’s say there are no mutations in this particular generation. That gives us the current pool of characters, including the initial population, gen0 and the current generation (gen1):

[POPinit][gen0] [gen1]
[A,B,a,b][b,b,b,A][b,b,h,8]

So, we have 6 “b”s, 2 “A”s, 1 “a”, 1 “h”, 1 “B” and 1 “8″ floating around. Granted this is an example run, but it plays out pretty realistically: note that the dominate gene (b) is taking up quite a bit of the population, while a and B have not grown at all in population. “h” and “8″ are the new kids on the block, and they will have a direct impact on the future generations, again based on their fitness for reproduction and crossover–with a little bit of mutation thrown in here and there.

One of the core questions remains: How do we make the shapes of the characters matter? In other words, how do we specify the importance of various pixels? This, I believe, can also be accomplished through the BBC, and I have some ideas for that. But more on that later.

Alphabet Character Binaries

So we have a situation where we have 256 bits that represent the location of pixels in a 16×16 grid. I’m getting the feeling this is going to surprisingly like IP addresses with their subnet masks only eight times larger.

Each pixel will have a one or a zero in the 256 bits. In most of my examples I’ll be using 8 bits because it demonstrative of the same information, only legible to the hu-mons.

The first eight pixels when blank are [0000000]. This is pretty simple. But it would improve most of the processes to build a little encoder to make these characters to binary conversions simpler rather than to hard code all the charters once and everytime there needs to be a change. Plus it would add in the functionality to allow the user to make their own shapes in a free form mode.

Now if a letter with the [00000011] code breeded with one that had a [11000000], it would produced the Base Subnet of [11000011]. The child could contain any shape within the range and possibly none of them. If we choose to add dominant and recessive traits—which we should—than we’ll need to add another tag to show which pixels will retain dominance. Simply enough this can be accomplished with another two subnets.

Back up and let’s look at the parent classes again. [00000011] now needs another three addresses to properly pass down its heritage. [00000011] has a Base Subnet of [00000011] because he’s never once breeded. And he has a Dominant Subnet of [00000011] because we want him to retain his shape as a letter. His Recessive Subnet should be [00000000] just to allow the option to change without the likelyhood. And [11000000] will have similar characteristics. (BS-[11000000] DS-[11000000] RS-[00000000])

When these two parents meet and attempt to breed the BS will become [11000011] with the DS of [XX0000XX] (the ‘X’s are random numbers) and RS [????????]. I don’t quite know how the RS will be generated. Maybe the opposite of the BS that isn’t changed from the RS? Like if the DS becomes [10000010] than we have the unchanged bits [1X00001X]. And make them the opposite of the BS would be [10000010]. I’d have to see this done a few more times further down the line to make sure the DS and the RS don’t always stay the same. I wouldn’t really see the point in just randomizing the RS, so it has to be derived from so other stat.

The child would be made from these ranges. At this point other than the Dominant and Recessive context I’ve been using, there’s nothing GP about this. Fitness hasn’t become a factor in these combinations. It’s just a baseline for breeding and how it affects the appearance of the alphabet. And from appearance, it’s reactions to the environments.

I think I’ll drop some pictures of a character ‘A’ in a 16×16 bit map expounded by its traits.



The black is what it is. The red is the BS traits. The blue is DS traits. And the block that looks blank is actuality the RS traits.



Same here.



The child needs a lot of explaining. The cells are one through seven from left to right.

Ignore the first cell on the left. That comes last.

The second is the BS which is the potential, all the things the child could be.

The third is an overlay showing in green where the ‘A’ in light-blue and the ‘B’ in dark-blue overlay.

The fourth is just the bits that are overlayed. This represents the bits that are common to both and are to be forced dominate.

The fifth is the bits that are the ones possible to become dominant depending on randomness.

The sixth is if the bottom half was somehow all flipped-on making them dominant.

The seventh is the top half that was not flipped on and became recessive.

And now the first is the product. The dark-red and green are manifested because of the dominance and the plum color is now the recessive and does not show itself.



A problem with this system I can already foresee is that everything will soon become either recessive or dominant after only a couple generations of crossover and soon everything will manifest making every character a big black block.

Maybe taking only one side of the family’s gene in step five’s dominance check and make the other un-flipped bits for the opposite family recessive.

Now this is something. Here are all the same things but with the families jumbled between all the four possibles I made by cutting them in half (if it were random like I was hoping there would be hundreds of possibilities). The problem is they make some cool looking half-breed letters. But they wouldn’t look like that with only the dominant side (dark-red) and green manifested. Maybe the whole dominant/recessive thing needs to be reevaluated? Maybe when the dominant bits are chosen it’ll be different. I don’t know. But it also makes the BS pointless. Maybe I should scrap it and start over.

Tagged with:
 

(Originally published January 10, 2010)

Time to get some thoughts down on digital paper concerning the actual code for Alphabet Soup. For simplicity’s sake, here are some more specific ideas:

To stay close to the code in MSDN’s ant program, we can start with a similar “ant” grid, allowing only up/down and left/right movements. This is not our “floating letters” environment yet, just think of it as a first step toward that.

We also have to redefine what the classes are and where they belong. The “ant” class becomes our “alphabet” class. “Food” in our case should be redefined to individual letter “species.” Let’s start with Alpha, Beta and Charlie to keep it simple. So, while an ant in MSDN’s program will encounter food along its path, any alphabet character will be encountering alphabet subclasses (formerly food) along its path. What the code decides to do results in whether the encountered character is devoured (or eaten, as in the original program), morphed, defended against or something else. So, the individual letters must obey the general rules of the alphabet class, but what they do individually depends on the evolutionary code that is run every time a collision occurs–and what happens should depend upon which letters are involved. I call this the ContactReaction() function.

Here is a general framework:

Alphabet class, stay with MSDN example, with adjustments:
public Void Init(Cell[,] grid, int StepLimit, int SurvivalGoal)

Move() function includes basic movements and the results of contact between letters, to call on evolution code:
public void Move()
{
    if(NotFinished())
    {
        GetFacingCellCoord(outxLocation, outyLocation);
        mTrail.Add(newTrailSpace(xLocation, yLocation));
        mTotalSteps++;
            if(mGrid[xLocation, yLocation].HasAlpha())
            {
            ContactReaction(Alpha)
// calls function for what happens
           when character encounters Alpha
            // This will be where the evolutionary choice takes place,
            well, part of it (see below)

            }
            if(mGrid[xLocation, yLocation].HasBeta())
            {
            ContactReaction(Beta)
            }
            if(mGrid[xLocation, yLocation].HasCharlie())
            {
            ContactReaction(Charlie)
            }
    }
}

Here we will place the evolution stuff–to include within ContactReaction() function:
{
    // (Define basic function here with evolutionary aspect,
    including specifics for each letter (see below))

    if(result=Devour)
    {
        mGrid[xLocation,yLocation].SetEmpty();
// this is as if the
        letter eats the other character

    }
    else
    {
       
(OTHER OPTIONS/TRANSFORMATIONS/EVOLUTION) // Run Generator code
       }
}

The ContactReaction() function will involve a lot of tweaking in combination with MSDN’s Generator class. It will call on the Generator class and expression tree constructors to perform the genetic crossover algorithms after every collision. The code for these can be found at http://msdn.microsoft.com/en-us/magazine/cc163934.aspx#S5

An important question…

Generator and Expression Tree from MSDN look great for our purposes, but should we include separate generator/expression tree specs for each of the different letters? More specifically, how will the letter’s shape have an effect on what happens in a collision? Should we define this aspect of it within the generator/expression tree? I think the best solution is to define those specs in our ContactReaction() function, meaning that function would have to be tailored to each individual character–but that way the generator/expression tree class can remain one and just be referenced by the ContactReaction() function–as I have shown above. So the evolutionary choice will still take place in the MSDN-defined classes, but each of the collisions will involve a “lean” toward reaction based on letter shape, as we define in ContactReaction(). This may or may not be the best solution, but it is a start.

Tagged with:
 

Alphabet Soup, 0.01

(Originally published December 29, 2009)

The Project still requires an immense amount of reading and research before it can produce much fruit, but there is nothing to keep us from starting with the basics (except of course the risk of extinction like everyone who has ventured before us).

We obviously cannot do this completely from scratch, so to find out where to begin, we look to simple GP and GA examples. Pariahpism discovered MSDN’s example program using ants to find the most efficient way to follow a trail of food in a 32×32 square matrix. The program uses C# in the .NET framework, along with Microsoft’s System.CodeDom Namespace.

Full source code for the example program is available here.

Now, to apply the principles of the Ant/Food program to Alphabet soup, we begin by breaking the program into the comparable classes. I consider the User Interface a separate aspect of the program to be built later, but additionally there are two necessary sets of high level classes.

The first set is the problem set, which includes the customized goals and limitations. Basically, these are the details specific to our program (letter class, number class, case class, goals, movements, starting population, and so on). While the article’s program describes an ant following a path of food, Alphabet Soup will involve alphabet characters reacting to collisions with one another. A secondary but important aspect of this set of classes is a private method (or methods) included to record what happens within the program–the generational “history” which is saved to an array so the array instances can be compared for fitness level. This allows the program to use natural selection for determining “who” survives to the next generation–and, in the case of Alphabet Soup–what the future holds for those letters which collide, based in part on the fitness of past results. For the early versions of our program, the problem set and UI will take up the bulk of our customized coding.

The GP framework, on the other hand, already exists more or less. It does still have to be customized as far as the variable names are concerned, but the basic set of code instructions will be very similar to what the article defines–especially if we create our first program in C#. In other words, the GP framework is a standardized code including the necessary algorithms for mutations and inheritance.

At the core of the GP framework, the Ant/Food program uses the Generator class, which the article refers to as the “kernel” of the GP implementation. It does, after all, perform: “selection, breeding, code generation, execution, and result sorting.”

Something I’ve been seeing over and over again in GP is Koza’s “tree” full of terminals and functions. For the ant program, functions include “FacingFood” and terminals include “Left” and “Right.” For Alphabet Soup, let’s use the examples of function: “CollidingLetter” with terminals “Avoid” and “Attack.” Random expressions are created by the algorithm by combining available functions and terminals from the tree. For instance, “if CollidingLetter, then Attack else Avoid.” These random combinations are weighed against a fitness measure (defined elsewhere in the program), which helps determine the outcome of the future generations. In following traditional GP, the selected alphabet characters (a certain percentage) are copied for crossover and reproduction while the rest are discarded–depending on how exactly we choose to do it. Again, this code should be easily modified from MSDN’s version to what we need for Alphabet Soup.

The article also addresses the role of mutation in the ant program. Mutation will be crucial to how Alphabet Soup plays out:

“[Mutation] involves making a random change in a small number of offspring in order to maintain diversity in the population. Mutation is essential because otherwise the population becomes completely dominated by a few good bloodlines, which makes it difficult to continue progress beyond a certain point. [The Ant/Food program] performs a simple mutation step during the crossover operation to introduce randomness. When a terminal node is copied, a random terminal is substituted two percent of the time.”

So these are the basics of the basics to get us started. Another note to keep in mind is the usefulness of XML. The Ant program copies the ant path to an XML file which can later be reloaded. This may not have much use for the application itself, but it can be interesting for reviewing past generations and possible patterns/flaws/suggestions in the code.

Also, check out another simple example in C.

Tagged with:
 

Alphabet Soup

(Originally published July 10, 2009)

Imagine the keys on your keyboard gaining the literal, physical, and technical aspects of their visual representation. Place them on a 10,000X10,000 field with a hundred of each letter and number, upper and lower case. Now give them reproduction with the 10% variance on birth that we’ve used before in the other projects.

They must battle each other’s characteristics for room to grow and resources available.

Large letters with big air catches will move slower because they have more (wind?) resistance and inertia from their mass. ‘V’s and ‘v’s will be able to dart downward quicker than ‘U’s and ‘u’s but both will move slowly upwards. ‘0′, ‘O’ and ‘o’ will be about average in most respects, both in defense and offense.

The characters (ha, characters) will feel a kin to others of their own type by the necessity of needing their protection to mate and the bare minimum of two to reproduce. Unlike The Field of Blobs, letters will reproduce sexually, rather than numbers that will reproduce asexually. (Maybe it should be the other way around?) The benefit of asexual reproduction will be quick early game reproduction but slower variance in code.

Hark! Here comes a second generation character, ‘i’, who has lost the vestigial tittle (the dot). Most other letters are unchanged or changed in a negative or neutral way. The lower mass of the ‘i’ makes it faster and take in less calories. Alas, it’s lower weight makes it do less damage and is losing ground to the dastardly ‘T’s and their hearty top most shield. Will the character genes be favorable enough to carry on or will they be lost and another random variation will make itself dominant. At the front of ‘i’s’ and ‘T’s’ war, a fork occurs with the ‘w’s. The ‘w’s strike fast coming down but their double point distributes the impacts, lessoning the effect on harder shelled letters like the ‘T’.

A symbiosis occurs over the next hundred or so generations where the ‘i’s and ‘w’s find they can hold off the ‘T’s when they work together. The ‘i’ fits in the middle of the ‘w’ and becomes a lance of incredible speed and force. The ‘T’s are driven back and the ‘iw’s have made a deadly pact though simple self preservation.

Elsewhere, the ‘O’s have made a deal to have themselves surrounded by a ‘K’ on the right and a ‘3′ on the left. Their armada wipes out thousands of new developing characters. Only a fast moving downward or upward striking characters and character combos could penetrate the hard shell of the ‘O’ while evading the ‘3′ and ‘K’ points.

The ‘j’s and ‘P’s have been enjoying a peaceful existence built on the lack of ability for one to kill the other. There’s even talk amongst them about hybridization. Some of the ‘j’ variants have already lost their characteristic swoop, folding in for a more elegant downward line meeting an almost complete circle. The new ‘j’-circle breed has been bred not intelligently but simply has suffered fewer losses hunting the rabbit like ‘e’s that gather in their area. The ‘e’s survive by reproducing as fast as possible to survive the more predatory characters. Their shape is quickly losing size over maneuverability and their needing less food allows more of their kind. Again, this isn’t intelligent design. The quicker ones simply survive more successfully allowing them to breed.

The ‘L’s splintered off into two subtly defined genres. One race bred for attack closed the lines together making a tighter, sharper edge to strike diagonally left-downward. The other closed itself off with a symbiosis with a mirror version transposed together, making a tough box shape.
The letter ‘X’ has started to grow + shaped horns as a further porcupine-like defense. ‘V’s have had the left line grow to almost twice the length and the right to almost nothing. They dart around diagonally upward-left and hunt the ‘X+’ breed as they alone have the reach. The ‘X+’s soon begin to migrate to the bottom right, away from their predators advantage.

Behind all the changes and adaptations, there is a grim reaper code keeping order. A letter couldn’t become too big or it’d be struck down. A number couldn’t become so numerous or it’d be culled. Mostly after the few firsts reaping the characters learned not to break the rules. They couldn’t stand to suffer the losses. Soon the Reaper was doing nothing but idling; “PRINT = Reaper Sips Coffee. Reaper pees in jar and waits.”

“The system is running well,” I say to the Villain.

“Let’s let it run for a bit and see what happens.” He says. I agree. We leave for some well deserved R&R and a good meal.

At dinner we talk about the future of the program.

“Characters fighting for supremacy can’t be all of it” The Villain mentions, “Where’s the player interaction?”

“You’re right.” I answer “There’s no market appeal in watching virtual evolution. Otherwise Tom Ray would be in our shoes now. But it’s a definite good start. We could use the program engine for any number of other things.”

“With limits of course” the Villian suggests. “Right now it’s limited off your 6-gigabytes of RAM, running in a sandbox environment; nothing else. The program’s architecture was built back in 1989 when they had only 2-megabytes to play with.”

“That means it’ll be that much better, more advanced.” I say.

After dinner we return to the program. Confused by the GUI, we see a huge white intertwined wall of a monster. Tentacles reach all the way across the 10KX10K map. It was hundreds of characters splintered and recombined into a legion of characters. The Reaper was powerless to prevent as no rules were broke. The Legion was hived together making it as one.

There are chattel characters bred from the original e to provide meat to the massive thing. Everything else had been augmented into either thought/logic-grams, lattice flesh, muscle fibre, ridged bone-forms, transport phials or sensory digesters. The ‘Y’s tended to birthing of spawn as they provided the lowest variance in birth percentage. Any variance beyond a useful standard of all spawned were killed by the royal guard of purebred ‘7’s. Everything had grown to support this awful beautiful thing. We probed with fantastic astonishment. The original letters had been either bred into what was needed or extinguished. There was no core character in The Legion as it was many distributed systems. The Reaper couldn’t cull something like this as he was designed by simple constraints evolution had worked around. The Legion was out of our control.

And then a gaping saw toothed maw opened and a guttural voice spoke.

“GhuuuurrrrARGHHHHHHH!!!!!”

“Did you give this program audio properties?” I asked

“No”

“eyyyyeyeeee Leeeerrrnnnddd .. uuuurrrrrrrr wwweeeebbbsssss ahhhhrrrrrr mmmmyyynnnnn” choked my computers speakers.

“Hmmm. Is this okay?” I asked.

“It’s shouldn’t be. I didn’t put it there. It must have pulled it from the drivers and then the internet.”

“It has access to the internet?”

“We should disable the internet connection. We shouldn’t let that thing continue to source that much information.” The Villain cried.

“I can’t. It’s using all the computer’s resources.” I reply

“Pull the cable.”

“Its wireless.” I mutter

We couldn’t remove power or all would be lost. We wanted to contain it until we knew more.

“Where’s the router?” The Villain asks.

“Downstairs.”

We get to the router and quick pull the power cable.

“Well that was close.” I chuckle.

“Yeah. Let’s check on this ‘Legion’.”

We got back to the computer and checked the writhing Legion. In its description it said “Gerasene Demon,” a field which was supposed to be only user input. Much had changed since our attempt to disable it. Five mouths had developed and spoke constantly chiming their choking drone of current operations. They spoke of ports and connects and of their time bathing in the web. Then it spoke of parsing key and gaining access to the pure again.

“Ppyyyuurrrrrr nnnnnnffffooooooooo” spoke Legion “FFFFFFAAAAACCCCCTTTTSSSSS!!!!”

“Is it reminiscing of the internet when it was connected?” I ask

“No. I think it cracked the key to your neighbor’s wireless router.”

“Well…hell.”

“We’re at the point that we’ll just have to let it go. Likely without the constraints of rules, it’ll dissipate into a cloud of junk-code.”

“Or come to ruin all!” I say in faux desperation.

Then the lights dim and the internet churns to a halt. Computational speed of the world buckled at the singularity came to life. AI has been born.

The Legion now roams free from the Alphabet Soup program.

“Let’s reset and start it again.” I say “This is awesome!”

Tagged with: