Allelia
Allelia is a lightweight genetics library for games and simulations.
It allows you to define genes and alleles, create parent genomes, and generate child genetics using direct inheritance, blending, and mutation.
Allelia is designed to be flexible rather than biologically accurate. The library handles the inheritance system while your game or simulation determines what the genetic information represents.
Features
- Continuous genes
- Discrete genes
- Direct inheritance
- Blended inheritance
- Mutation
- Genotypes and phenotypes
- Custom inheritance functions
- Custom expression functions
- Custom mutation functions
- One or more parents
- Numeric, tuple, list, and dictionary blending
Basic Concepts
Gene
A Gene defines how a particular genetic trait behaves.
from allelia import Gene
eye_color = Gene(
"eye_color",
"continuous"
)
Allelia currently supports two gene types:
"continuous"
"discrete"
Continuous genes can blend their alleles together.
Discrete genes select individual alleles without blending them.
Genome
A Genome stores the alleles belonging to an individual.
from allelia import Genome
parent = Genome()
parent.set(
"eye_color",
[
(110, 70, 40),
(70, 130, 180)
]
)
You can retrieve the genotype with:
parent.get(
"eye_color"
)
You can also check whether a genome contains a gene:
parent.has(
"eye_color"
)
Creating an Allelia System
Create an Allelia instance and register the genes used by your system.
from allelia import Allelia, Gene
allelia = Allelia()
allelia.add_gene(
Gene(
"eye_color",
"continuous"
)
)
By default, inheritance probabilities are:
Direct Inheritance: 80%
Blending: 18%
Mutation: 2%
You can change these when creating the system:
allelia = Allelia(
direct_inheritance=0.80,
blending=0.18,
mutation=0.02
)
The values are treated as relative weights, so they do not have to add up to exactly 1.0.
Creating Parents
Each parent is represented by a Genome.
parent_1 = Genome()
parent_1.set(
"eye_color",
[
(110, 70, 40),
(70, 130, 180)
]
)
parent_2 = Genome()
parent_2.set(
"eye_color",
[
(80, 130, 75),
(130, 145, 150)
]
)
In this example, each parent has two eye color alleles.
Creating a Child
Pass the parent genomes to:
allelia.create_child()
For example:
child = allelia.create_child(
parent_1,
parent_2
)
Each parent contributes one allele for every gene that parent contains.
The resulting child stores those contributions as its genotype.
print(
child.get("eye_color")
)
Phenotypes
A genotype contains an individual's alleles.
A phenotype is the allele that is expressed.
Use:
allelia.express()
to generate a phenotype from a genome.
child_phenotype = allelia.express(
child
)
print(
child_phenotype["eye_color"]
)
By default, Allelia randomly selects an allele from the genotype for expression.
Custom expression rules can also be supplied to a gene.
Continuous Genes
Continuous genes allow values to be blended.
For example:
Gene(
"height",
"continuous"
)
Allelia can blend numerical alleles:
170
190
into an intermediate value.
Continuous genes can also contain more complicated numerical structures.
For example, RGB colors:
[
(110, 70, 40),
(70, 130, 180)
]
can produce intermediate colors.
Discrete Genes
Discrete genes represent traits that should remain separate rather than being mathematically blended.
For example:
allelia.add_gene(
Gene(
"ear_type",
"discrete"
)
)
A genome might contain:
parent.set(
"ear_type",
[
"round",
"pointed"
]
)
Allelia selects one of the available alleles when that parent contributes the gene.
Blending
Allelia includes a recursive blend() function.
It can blend:
- Numbers
- Tuples
- Lists
- Dictionaries
For example:
from allelia.allelia import blend
result = blend(
100,
200,
0.5
)
print(result)
Result:
150.0
The ratio determines how much each value contributes.
blend(
100,
200,
0.25
)
uses:
75% of the first value
25% of the second value
The same system works recursively with tuples:
blend(
(100, 50),
(200, 100),
0.5
)
and dictionaries:
blend(
{
"x": 100,
"y": 50
},
{
"x": 200,
"y": 100
},
0.5
)
This makes continuous genes useful for more than simple numbers.
Mutation
Mutation behavior can be defined separately for each gene.
Create a function that accepts:
allele
gene
For example:
import random
def mutate_color(
allele,
gene
):
return tuple(
max(
0,
min(
255,
value + random.randint(-20, 20)
)
)
for value in allele
)
Then assign it to the gene:
allelia.add_gene(
Gene(
"eye_color",
"continuous",
mutate=mutate_color
)
)
When mutation is selected during inheritance, Allelia generates the inherited allele and passes it to your mutation function.
If no mutation function is supplied, the allele is returned unchanged.
This allows the application using Allelia to determine what mutation means for its particular data.
Custom Expression
You can override the default phenotype behavior.
An expression function receives:
genotype
gene
Example:
def express_first(
genotype,
gene
):
return genotype[0]
Then:
Gene(
"eye_color",
"continuous",
express=express_first
)
Allelia will use your function instead of randomly selecting an allele.
Custom Inheritance
Genes can also provide their own inheritance behavior.
An inheritance function receives:
genotype
gene
For example:
def inherit_first(
genotype,
gene
):
return genotype[0]
Then:
Gene(
"special_gene",
"continuous",
inherit=inherit_first
)
This allows individual genes to override Allelia's default contribution behavior.
More Than Two Parents
Allelia does not require exactly two parents.
create_child() accepts one or more parent genomes.
For example:
child = allelia.create_child(
parent_1,
parent_2,
parent_3
)
Each parent that contains a particular gene contributes one allele to the child's genotype for that gene.
This allows Allelia to support fictional reproductive systems without requiring special handling inside the library.
Complete Example
from allelia import Allelia, Gene, Genome
allelia = Allelia()
allelia.add_gene(
Gene(
"eye_color",
"continuous"
)
)
parent_1 = Genome()
parent_1.set(
"eye_color",
[
(110, 70, 40),
(70, 130, 180)
]
)
parent_2 = Genome()
parent_2.set(
"eye_color",
[
(80, 130, 75),
(130, 145, 150)
]
)
child = allelia.create_child(
parent_1,
parent_2
)
phenotype = allelia.express(
child
)
print(
"Parent 1:",
parent_1.get("eye_color")
)
print(
"Parent 2:",
parent_2.get("eye_color")
)
print(
"Child:",
child.get("eye_color")
)
print(
"Expressed Color:",
phenotype["eye_color"]
)
Running the example multiple times can produce different results because inheritance, blending ratios, mutation, and phenotype expression can use randomness.
Design Philosophy
Allelia separates genetic rules from the meaning of the data.
The library does not need to know that:
(70, 130, 180)
represents an eye color or that:
(120, 80)
represents a point in a procedural character model.
To Allelia, they are simply alleles.
This allows the same inheritance system to be used for character appearance, creature generation, fictional species, procedural traits, or other game and simulation systems.
Applications remain responsible for deciding what their genes represent and how their resulting phenotypes are used.
Version
Current version:
0.1.0
Allelia is currently an early-stage library. The API may change as the library is expanded and tested in additional projects.
Release files for allelia 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| allelia-0.1.0.tar.gz | 9.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| allelia-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.2 kB
Release files / allelia-0.1.0.tar.gz
| Download URL | allelia-0.1.0.tar.gz |
|---|---|
| Size | 9.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b7b148370e154aa56ad0b1c7b3a930ab39b56dec903a07eaf1a27fbd6bc4f5d6
|
|
BLAKE2b-256 checksum How to use checksums |
6432765507a8e7331516250369d3de672ca0dbe590c7589b1bdfc1481d22df3b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.7
|
Release files / allelia-0.1.0-py3-none-any.whl
| Download URL | allelia-0.1.0-py3-none-any.whl |
|---|---|
| Size | 7.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4976435c8b24c594c9f5124ceb87f8ed644d6d39af0648601c9ec712af22bcfb
|
|
BLAKE2b-256 checksum How to use checksums |
3f31acb27103fed5a596e9ff55c68de2c7f233367580d546af35a40e96b935d4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.7
|