Skip to content

Proof of concept ‐ Using AI, Self‐Evolving Game

Andreas AFENTAKIS edited this page Nov 27, 2025 · 4 revisions

Proof of concept - Using AI, a Self-Evolving Game of Life.

Credits: Thanks to George P. Afentakis for this inspired program.

AI-Driven Self-Modifying Code

The concept of a Self-Evolving Program using Artificial Intelligence focuses on systems where the AI component actively modifies the application's underlying source code or configuration rules. Unlike traditional AI that merely optimizes parameters or generates outputs, this approach grants the AI the meta-ability to act as its own programmer. . The AI, often based on techniques like Genetic Algorithms or advanced Large Language Models (LLMs), monitors the program's performance and identifies bottlenecks or opportunities for new functionality. It then generates or alters specific code segments, typically within a safe, modular, and controlled environment, and automatically integrates the change after rigorous testing. This capability transforms the program from a fixed piece of software into an autopoietic system—one that can iteratively refine its own structure to maximize efficiency and adapt to unforeseen challenges in real-time, ushering in a new era of truly autonomous software development.

That's a great idea! Focusing on the Game of Life grounds the abstract concept of "self-evolving" code in a tangible, recognizable simulation.

Here is the paragraph specifically focused on Conway's Game of Life:


Conway's Game of Life as an Evolving System

Conway's Game of Life is an ideal platform for demonstrating self-evolving programs because it is a Turing-complete cellular automaton defined by only four simple, static rules (survival, death by loneliness, death by overcrowding, and birth). The self-evolving concept introduces an external AI layer that monitors the Game of Life's ongoing state, identifying persistent, stable patterns (like gliders or still life forms) or emergent, complex phenomena. Instead of merely observing, the AI system can use its analysis to modify the fundamental rule set of the Game of Life itself, or strategically inject new cell configurations into the grid. This meta-level control allows the program to guide the evolution of the simulation, perhaps to maximize population density, ensure pattern longevity, or intentionally crash the simulation, showcasing AI's capability to rewrite the governing logic of its own environment.


Diagram The Self-Evolving Game of Life Workflow

This diagram illustrates the workflow of the Proof of Concept program, detailing how the simulation uses Artificial Intelligence (AI) to dynamically generate its own rules. The process is broken down into three main phases: AI Rule Generation, Initialization, and the continuous Simulation Loop.


1. AI Rule Generation

The program begins by gathering user input for the number of generations and a Rule Suggestion. This suggestion is passed to the AI component . The AI is prompted with the base sample rules and the user's idea, and in response, it generates new FBASIC Rule Code (RuleProgram). Crucially, the AI also provides an Explanation of Changes (RuleChange). Both the executable code and the human-readable explanation are saved for persistence.


2. Initialization and Loop Entry

Before the simulation starts, the program Initializes a Random $16 \times 16$ Grid with live and dead cells and sets the generation counter to zero.


3. The Simulation Loop

The core of the system is the Simulation Loop, which runs for the specified number of generations ($M$). In each generation:

  1. The current Grid State is Displayed.
  2. The grid data is prepared and Stored in a Memory Stream.
  3. The program executes the AI-generated code using the command eval RuleProgram. This is the self-evolving action, where the program runs the dynamic rules created by the AI to calculate the next state.
  4. The Next Grid State is Retrieved and used to Update the Grid.
  5. The generation counter is incremented, and the loop repeats.

Once the generations are complete, the program exits, printing the AI's Final Rule Summary to show the user exactly how the rules were changed during the PoC run.

4. The Diagram

graph TD
    id1[Start Program Execution] --> id2{Input: Generations and AI Rule Prompt};

    subgraph AI_RULE_GENERATION
        direction TB
        id2 -- Rule Suggestion --> id3[AI Prompted with Sample Rules];
        id3 --> id4[AI Generates New FBASIC Rule Code];
        id4 --> id5[AI Writes Rule Change Explanation];
        id4 --> id6[Save Generated Rule Code lifeGame.rule];
        id5 --> id7[Save Rule Change Text lifeGame.txt];
    end

    id8[Initialize Random 16x16 Grid] --> id9(Initialize Generation Counter: gen=0);

    subgraph SIMULATION_LOOP
        direction TB
        id9 --> id10{Current Generation < M?};
        id10 -- No --> id11[Simulation Finished];
        id10 -- Yes --> id12[Display Grid State];
        id12 --> id13[Store Current Grid in Memory Stream];
        id13 --> id14[Execute AI Code eval RuleProgram];
        id14 --> id15[Retrieve Next Grid State];
        id15 --> id16[Update GameScreen];
        id16 --> id17[Increment Generation];
        id17 --> id10;
    end

    id11 --> id18[Print AI's Final Rule Summary];
    id18 --> id19[End Program];

Loading

Implementation

The scope of this program is to implement a self-evolving version of Conway's Game of Life on a fixed $16 \times 16$ grid, where the core rules for cell survival and birth are not static but are dynamically generated and modified by an Artificial Intelligence (AI) model.

The program encompasses three main areas: initialization, simulation, and AI rule generation.

1. Game of Life Simulation

  • Grid Size: Fixed at $N \times N$, where $N=16$ (a $16 \times 16$ grid).
  • Initialization: The grid is initialized with a random distribution of live cells (@) and dead cells (.), with live cells having approximately a $27%$ probability of appearance.
  • Execution: The program runs for a user-specified number of generations ($M$), printing the grid state to the console for each generation.
  • Mechanics: The simulation logic reads the current grid from a MEMSTREAM (GridStream), applies the rules defined in the RuleProgram (which is code generated by the AI), and writes the new grid state back to the stream, thus completing one generation cycle.

2. AI Rule Generation and Modification

  • Self-Evolving Core: The primary function is to replace the standard Game of Life rules with rules generated by an AI model (Claude).
  • User Input: The user is prompted for a suggestionRule (e.g., "Add 5 new rules," or "Be Very Creative") to influence the AI's code generation.
  • Code Generation: An AI session (RuleSession) is used to prompt the AI to rewrite a samplecode template—which contains the classic Game of Life rules—into a new set of rules in the FBASIC low code language. The AI is specifically instructed to output only the executable code (RuleProgram).
  • Documentation: The AI is also prompted to explain what changes it made (RuleChange), providing documentation for the new rules.

3. Rule Management

  • Dynamic Execution: The AI-generated code (RuleProgram) is executed using the eval command, allowing the program's core logic to be changed on the fly.
  • Persistence: The generated rule code (RuleProgram) and the AI's explanation of the change (RuleChange) are saved to local files (lifeGame.rule and lifeGame.txt).
  • Loading: The user has the option (L) to skip AI generation and load the last saved rule set from these files, which is useful for testing or re-running a specific generated rule.

In essence, the program's scope is not just to run a simulation, but to demonstrate a Proof of Concept (PoC) for AI-driven self-modification by using the simple, rule-based Game of Life as a testbed.

PoC-1: Output (Prompt: Be realistic)

The Conway's Game of Life.
How many Generations should I'll simulate: 10 Should the Game rule include anything special? (E.g. How many New rules should I add? Or just write "Be Very Creative")
Left empty line, to use the sample code or enter L and the last rule will be used: Be Realistic
Waiting AI to make a new rule code.
Generated program saved.


Generation 0
. . . @ @ . @ . . . . . . . . .
. . . . . @ . @ @ . . @ . . . .
@ . @ @ @ . @ @ . @ . . . . . @
. @ . . @ . . . @ . . @ @ . . .
. . @ . . @ . @ . . @ . . @ @ @
. . . @ @ . . . . . . . . . . .
. . . . . . . . . . @ @ . . @ @
. . . . . . . . . @ . . . . . @
@ . . . @ . . . . @ @ . @ @ . .
. @ @ . . . . . . @ . . . @ . .
@ @ @ . . . @ . . . . . . . @ .
. . . . . . . . . . @ . @ . . .
@ . @ . . . . . @ @ . . @ @ . .
. @ . @ . . . . . @ . @ . @ . .
@ @ . . @ . . . . . . . . . @ .
. @ . . @ . . . . . . @ . . . @

...
...
...

Generation 9
. @ . @ . @ . . . @ . @ @ . . .
. @ . @ @ . @ @ @ . . . @ . @ .
. @ . @ @ . @ @ @ . . @ @ . @ @
. @ . . . . . @ @ . . @ @ @ @ @
. @ . . . @ . @ @ . . . . . . .
@ . @ . . . . @ . @ . . . . @ @
. . . . . . @ @ @ . . @ @ @ . .
@ @ @ @ @ . @ . @ . . @ @ @ . .
@ @ . . . . @ . . . . . . @ . @
@ @ @ . . @ @ . . . . . . . @ .
. . @ @ @ . @ . . . . . . . @ @
. . @ @ @ . . . @ @ . . @ . . @
. . . . @ @ . . @ @ @ @ @ . @ @
@ @ . . . @ . @ . . . . . . . @
. @ . . . @ @ @ . @ @ @ . . @ .
. . . . @ @ @ . . @ @ @ @ @ . .

User Prompt: Be realistic

Change on the rules: I introduced three major changes:

  1. Toroidal wrapping: The grid now wraps around at the edges (like a torus), so cells at the boundary interact with cells on the opposite side instead of treating out-of-bounds as dead cells.
  2. Entropy-based randomness: I added a deterministic but varying "entropy" factor based on position and generation number that creates probabilistic behavior in certain neighbor count scenarios.
  3. Modified survival/birth rules: Living cells now survive with 1, 2, or 3 neighbors (instead of just 2 or 3), and can sometimes survive with 4 neighbors based on entropy. Dead cells can be born with 2 or 4 neighbors (with entropy conditions) in addition to the standard 3 neighbors, creating more chaotic and unpredictable patterns that resist stabilization.

PoC-2: Output (Prompt: Only 2 cells)

The Conway's Game of Life. How many Generations should I'll simulate: 10 Should the Game rule include anything special? (E.g. How many New rules should I add? Or just write "Be Very Creative" ) Left empty line, to use the sample code or enter L and the last rule will be used: Each cell can have only two other cells in side areas. If more will die. Choose a clear notation Waiting AI to make a new rule code. Generated program saved.

Generation 0
. . . . . . @ . . . @ . . . . .
. . . . . @ . @ . . @ . . . . .
. @ . . . . . . . . . . . @ . @
. @ . . . . . . . . . . @ . . .
. . . . . . . @ . . . . . . @ .
@ @ . @ @ . . @ @ @ . . @ . . .
@ . @ . . @ . . @ @ . . . . @ .
@ . @ . . . . . . @ . . . . . .
. @ . . . . @ . @ . . . . . . .
. . . . . . . @ . . @ . . . . @
@ . @ . @ . @ . . . . @ @ . . .
. . @ . @ . . . @ . . . . @ @ @
@ . . . . . . @ . . . . . @ . @
. @ @ . . . @ . . @ . @ @ . . .
. . . @ . @ . @ @ @ . @ . @ . .
@ @ . . . @ . . . . . . @ . . .

...
...
...

Generation 9
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
@ @ @ @ @ . . @ @ @ . . . . . .
. . . . . . . . @ @ . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . @ @ . . .
. . . . . . . . . . . . . @ @ @
. . . . . . . . . . . . . . . .
. @ @ . . . . . . . @ @ @ . . .
. . . . . @ @ @ @ @ @ @ . . . .
@ @ . . . . . . . . . . . . . .

User Prompt: Each cell can have only two other cells in side areas. If more will die. Choose a clear notation

Change on the rules: I changed the Game of Life to only count the two side neighbors (left and right) instead of all 8 surrounding cells. The new rules are: a live cell stays alive if it has exactly 1 or 2 live side neighbors, otherwise it dies (from isolation with 0 neighbors or overcrowding with more than 2). A dead cell becomes alive if it has exactly 2 live side neighbors. This creates a one-dimensional-like behavior where patterns propagate horizontally across rows, with each row evolving independently based only on left-right relationships. Cells can no longer be influenced by diagonal or vertical neighbors, fundamentally changing the dynamics from Conway's complex 2D patterns to simpler horizontal wave-like behaviors.

Generated Code

let N = 16
SREWIND GridStream
STOS GridStream TO GridText
let row = 0
let col = 0
let qRow = 0
let qCol = 0
let idx = 0
let cellChar = "."
let curCell = "."
let sideNeighbors = 0
let newChar = "."
let NextText = ""

For row = 1 To N
For col = 1 To N

qRow = row
qCol = col
GOSUB GetCell
curCell = cellChar

sideNeighbors = 0

qRow = row
qCol = col - 1
GOSUB GetCell
if cellChar = "@" Then
   sideNeighbors = sideNeighbors + 1
EndIf

qRow = row
qCol = col + 1
GOSUB GetCell
if cellChar = "@" Then
   sideNeighbors = sideNeighbors + 1
EndIf

newChar = "."
if curCell = "@" Then
   if sideNeighbors = 1 Then
      newChar = "@"
   EndIf
   
   if sideNeighbors = 2 Then
      newChar = "@"
   EndIf
 Else
   if sideNeighbors = 2 Then
      newChar = "@"
   EndIf
EndIf

NextText = NextText + newChar
Next col
Next row

SREWIND GridStream
STOS GridStream FROM NextText
RESULT 0
END

GetCell:
if qRow < 1 Then
   cellChar = "."
   RETURN    
EndIf    
if qRow > N Then
   cellChar = "."
   RETURN
EndIf    

if qCol < 1 Then
   cellChar = "."
   RETURN    
EndIf

if qCol > N Then
   cellChar = "."
   RETURN
EndIf

idx = (qRow - 1) * N + qCol
cellChar = mid(GridText, idx, 1)
RETURN

The full code

Find the latest revision of this program in Interactive Testing Console as LifeAI.bas

rem  ============================================
rem The Game of Life. 
rem Uses AI to evolve the grid
rem (c) George P. Afentakis
rem ============================================

print "\n\n\nThe Conway's Game of Life."
print "How many Generations should I'll simulate: ";
input M

gosub MakeAIRules

let SEED=rnd()*34214*M  'SEED is a random 5 digit number or more
let i = 0
let N = 16


MEMSTREAM GridStream

REM Init random grid
For i = 1 To N * N
    let gameChar = "."
    SEED = mod(SEED * 16807, 2147483647)
    let rng = mod(SEED * 11, 100)
    if rng < 27 Then
        gameChar = "@"
    EndIf
    SDATA GameScreen gameChar
Next i

let gen = 0

For gen = 0 To M - 1

    print "Generation " + str(gen)

    RESET GameScreen
    let GameOutput = ""
    let cnt = 0

    FOREACH GameScreen
        GameOutput = GameOutput + [GameScreen.Item] + " "
        cnt = cnt + 1
        if mod(cnt, N) = 0 Then
            GameOutput = GameOutput + "\n"
        EndIf
    ENDFOREACH GameScreen

    print GameOutput
    print ""

    if gen = M - 1 Then
        GOTO DoneAll
    EndIf

    REM write grid to GridStream
    RESET GameScreen
    let GridText = ""
    FOREACH GameScreen
        GridText = GridText + [GameScreen.Item]
    ENDFOREACH GameScreen

    SREWIND GridStream
    STOS GridStream FROM GridText

    REM run the AI generated code
    eval RuleProgram

    REM read new grid back
    SREWIND GridStream
    STOS GridStream TO GridTextNext

    let totalCells = len(GridTextNext)
    let idx = 0
    For idx = 1 To totalCells
        let ch = mid(GridTextNext, idx, 1)
        SSET GameScreen idx ch
    Next idx

Next gen

DoneAll:

print "\nChange on the rules:\n"
print RuleChange
print "\n\n"

HALT


REM ============================================
REM GenerateRule
REM Ask AI to generate code based on a template
REM ============================================

REM --- Configure AI provider & session ---
MakeAIRules:

AIPROVIDER MyProvider, CLAUDE, * 
AISESSION RuleSession, MyProvider, "Generate code in a tiny BASIC-like language called FBASIC. You must output ONLY FBASIC code, no explanations, no markdown, do no use ``` fences."
print "Should the Game rule include anything special?"
print "(E.g. How many New rules should I add? Or just write \"Be Very Creative\" )"
print "Left empty line, to use the sample code or enter `L` and the last rule will be used: ";
input suggestionRule

gosub loadSampleCode
if suggestionRule = "" then
   let RuleProgram = samplecode
   return
endif
if ucase(suggestionRule) = "L" Then 
   gosub LoadLastRule
   return
endif

let RuleProgram = ""
let prompt = "Here is a complete novel programming language for a Game of Life rule:" + "\n" + samplecode
let prompt = "\nRewrite this so it follows different rules the rules can be as usual Or as diffrent New And creative as you want.
Output ONLY the final FBASIC program code without markdown code. No explanations. No code block in the begging Or the end. 
The point here Is playing Conways Game of life. But utilize whatever New rules you want."+ suggestionRule

PRINT "Waiting AI to make a new rule code."
AIPROMPT RuleSession, RuleProgram, prompt
AIPROMPT RuleSession, RuleChange, "What exactly did you change? What New rules did you introduce Or what old ones did you delete? Explain in 1 to 10 sentences"


gosub SaveGeneratedRule

RETURN

rem
rem Save the Generated rule
rem
SaveGeneratedRule:
FILESTREAM RuleFile, out, "","Output", "lifeGame.rule"
STOS RuleFile FROM RuleProgram

FILESTREAM ChangeFile, out, "","Output", "lifeGame.txt"
let txt=suggestionRule+"\n\n"+RuleChange
STOS ChangeFile FROM txt
sclose ChangeFile 
sclose RuleFile
PRINT "Generated program saved."
return


rem
rem Load last Generated rule
rem
LoadLastRule:
FILESTREAM oldRuleFile, in, "","Output", "lifeGame.rule"
STOS oldRuleFile TO RuleProgram
FILESTREAM oldRuleText, in, "","Output", "lifeGame.txt"
STOS oldRuleText TO RuleChange
sclose oldRuleText 
sclose oldRuleFile
PRINT "Last generated program loaded."
return

rem
rem Sample Code
rem 
loadSampleCode:

let samplecode = "let N = 16
SREWIND GridStream
STOS GridStream TO GridText
let row = 0
let col = 0
let qRow = 0
let qCol = 0
let idx = 0
let cellChar = \".\"
let curCell = \".\"
let liveNeighbors = 0
let newChar = \".\"
let NextText = \"\"

For row = 1 To N
For col = 1 To N

qRow = row
qCol = col
GOSUB GetCell
curCell = cellChar

liveNeighbors = 0

qRow = row - 1
qCol = col - 1
GOSUB GetCell
if cellChar = \"@\" Then
   liveNeighbors = liveNeighbors + 1
EndIf

qRow = row - 1
qCol = col
GOSUB GetCell
if cellChar = \"@\" Then
   liveNeighbors = liveNeighbors + 1
EndIf

qRow = row - 1
qCol = col + 1
GOSUB GetCell
if cellChar = \"@\" Then
   liveNeighbors = liveNeighbors + 1
EndIf

qRow = row
qCol = col - 1
GOSUB GetCell

if cellChar = \"@\" Then
   liveNeighbors = liveNeighbors + 1
EndIf

qRow = row
qCol = col + 1
GOSUB GetCell

if cellChar = \"@\" Then
   liveNeighbors = liveNeighbors + 1
EndIf

qRow = row + 1
qCol = col - 1
GOSUB GetCell

if cellChar = \"@\" Then
   liveNeighbors = liveNeighbors + 1
EndIf

qRow = row + 1
qCol = col
GOSUB GetCell

if cellChar = \"@\" Then
   liveNeighbors = liveNeighbors + 1
EndIf

qRow = row + 1
qCol = col + 1
GOSUB GetCell

if cellChar = \"@\" Then
   liveNeighbors = liveNeighbors + 1
EndIf

newChar = \".\"
if curCell = \"@\" Then
   if liveNeighbors = 2 Then
      newChar = \"@\"
   EndIf
   
   if liveNeighbors = 3 Then
      newChar = \"@\"
   EndIf
 Else
   if liveNeighbors = 3 Then
      newChar = \"@\"
   EndIf
EndIf

NextText = NextText + newChar
Next col
Next row

SREWIND GridStream
STOS GridStream FROM NextText
RESULT 0
END

GetCell:
if qRow < 1 Then
   cellChar = \".\"
   RETURN    
EndIf    
if qRow > N Then
   cellChar = \".\"
   RETURN
EndIf    

if qCol < 1 Then
   cellChar = \".\"
   RETURN    
EndIf

if qCol > N Then
   cellChar = \".\"
   RETURN
EndIf

idx = (qRow - 1) * N + qCol
cellChar = mid(GridText, idx, 1)
RETURN
"
return 


Clone this wiki locally