Full game instructions
Play the game
For every piece that is dropped into the pit, the survival fitness (s-fitness) is incremented 1 point. That way, the longer the player survived, the higher the s-fitness, and therefore, the higher the chance that this player's GP function knows how to keep it alive.The question then arose as to how the two would work together in creating the AI player. There needed to be some sort of balance between the two fitnesses. Horn et al. (1994) says, "Historically, multiple objective have been combined ad hoc to form a scalar objective function, usually through a linear combination (weighted sum) of the multiple attributes..."[1] Though Horn goes beyond this linear combination in his work, the linear combination approach would suffice for this project. To find the Pareto optimal front in this project was relatively simple, and actually unnecessary as was found out later. But it was decided that populations would be created at five different points along the front. The five points are represented by the following fitness equations:
The second fitness measure, the position fitness (p-fitness), is measured directly by how many rocks would be sent over from a group or groups disappearing had the player been playing with an opponent. This translates to:
So, if the player were to make one group of 4 and one group of 6 disappear, then he would send over 8 rocks since it would be a chain sequence of 2 groups plus an extra 2 balls (6 + 2 rocks). Therefore, his p-fitness would be incremented by 8 points.1 group 1 rock 1 group + n balls 1 + n rocks 2 groups 1 row (6 rocks) 2 groups + n balls 1 row + n balls (6 + n rocks) 3 groups 2 rows (12 rocks) 4 groups 3 rows (18 rocks) 5 groups 4 rows (24 rocks) 6 groups 5 rows (30 rocks)
At the extreme edges of this front was the percentages of 5% and 95%. At first, I had tried 0% and 100% but this would cause too many ties in best fitness, especially when s-fitness was set to 100% since many of the AI players were able to survive indefinitely and would max out the s-fitness score to 144.p05: s-fitness * 0.05 + p-fitness * 0.95 p25: s-fitness * 0.25 + p-fitness * 0.75 p50: s-fitness * 0.50 + p-fitness * 0.50 p75: s-fitness * 0.75 + p-fitness * 0.25 p95: s-fitness * 0.95 + p-fitness * 0.05
Primitive | Arguments | Factor | Description |
+ | 2 | N/A | Sums the two arguments |
- | 2 | N/A | Subtracts the two arguments |
* | 2 | N/A | Multiplies the two arguments |
/ | 2 | N/A | Safe divides the two arguments |
height | 0 | 1.5 |
height is a measure of how tall a column is. But this primitive is special
in that it doesn't return the straight height but maps the height to an exponential function so the higher columns give extremely low numbers to prevent pieces from being placed there for survival's sake. Here is the mapping: height of 0 -> 10 height of 1 -> 9 height of 2 -> 9 height of 3 -> 9 height of 4 -> 9 height of 5 -> 8 height of 6 -> 8 height of 7 -> 8 height of 8 -> 7 height of 9 -> 7 height of 10 -> 6 height of 11 -> 5 height of 12 -> 4 height of 13 -> 2 height of 14 -> 0 |
sides | 0 | 3 x 2.0 | Counts the same-colored pieces to its left, right, and bottom. This terminal, above all, is probably the most important since it will be responsible for causing the same-colored balls to group together. |
diagonals | 0 | 5 x 1.2 | Counts the same-colored pieces to its upper-left, upper-right, lower-left, lower-right, and two pieces below. This terminal will hopefully facilitate chain reactions by causing same-colored groups to form when its own column or a neighboring column that has a same-colored ball it is diagonal to shifts down one. |
diagonals2 | 0 | 4 x 1.5 | Counts the same-colored pieces two rows up and to the left and right, and two rows down to the left and right. This terminal has the same idea as the diagonals terminal except now the chain reactions would come when its column or a neightboring column shifts down two. |
column | 0 | 9 x 0.67 | Counts all the same colored balls in the same column. |
adjcolumn | 0 | 18 x 0.33 | Counts all the same colored balls in the neighboring column(s). |
4 | 0 | 1 |
AI #1 ----- Function: ( + ( / diagonals2 ( * sides column )) ( + ( / sides ( * 4 ( * sides height ))) ( + sides diagonals ))) s-fitness: 1382 out of 1440 p-fitness: 1127 pareto: p05 delay: 400 ms AI #2 ----- Function: ( + ( + ( + height sides ) sides ) adjcolumn ) s-fitness: 1440 out of 1440 p-fitness: 1152 pareto: p95 delay: 300 ms AI #3 ----- Function: ( / ( + diagonals2 ( + sides ( + sides ( / sides diagonals2 )))) diagonals ) s-fitness: 1418 out of 1440 p-fitness: 1158 pareto: p75 delay: 250 ms AI #4 ----- Function: ( + sides ( + height adjcolumn )) s-fitness: 1440 out of 1440 p-fitness: 1166 pareto: p50 delay: 225 ms AI #5 ----- Function: ( + ( + diagonals2 ( / ( + ( + sides ( - 4 sides )) ( * ( / ( / sides sides ) column ) sides )) column )) ( * ( + sides sides ) sides )) s-fitness: 1440 out of 1440 p-fitness: 1226 pareto: p25 delay: 200 msTo see all the output, click here.