# Obsidian: a living field A small artificial ecosystem written in C89 for the IBM RS/6000 named `obsidian`. The simulation runs natively on AIX 4.3.3 with IBM XL C 5.0.2 or GCC 2.95.3. No graphics server or external libraries are required. ## Build and run Unpack the source bundle and run these commands from its directory on AIX. ```sh sh build.sh xlc ./bin/ecosystem-xl --seed 604 --ticks 4000 --snapshot-every 40 --output my-run ``` Use a new output directory for each run; existing directories are refused. `sh build.sh gcc` builds `bin/ecosystem-gcc`. On a modern Unix machine, `sh build.sh host` builds `bin/ecosystem-host`. Output consists of raw P6 PPM images, `population.csv`, and `journal.txt`. The program exits after the requested ticks; it installs no background service. The default run produces 101 images (about 28.5 MiB) at 384 × 256 pixels. ## The experiment 160 organisms begin in a 96 × 64 world with wrapping edges. Each cell can hold one organism and 0–255 food units. Two circular patches are especially fertile. The left and right halves have opposite triangular seasons, which repeat every 800 ticks. Food regrows before organisms act each tick. Four inherited byte-valued traits affect behavior: | Trait | Benefit | Cost or constraint | | --- | --- | --- | | Movement | Higher chance of attempting a move | Successful moves consume energy; random movement can leave fertile ground | | Feeding | Harvests more food each tick | Higher ongoing metabolism | | Longevity | Raises maximum age from 600 to 1,620 ticks | Raises the energy threshold for reproduction | | Food sensing | More often chooses the richest vacant neighboring cell | Higher ongoing metabolism | Organisms gain energy from food, die from starvation or age, and reproduce when they have enough energy and an adjacent vacancy. A child receives 40% of the parent's energy; reproduction also costs the parent 12 energy units. Each child trait independently has a 12% chance of a mutation attempt, adding −16 to +16, clamped to 0–255. The mutation counter counts actual changes, rather than attempts. There are no predators or programmed species. Each tick visits the fixed organism-slot array from a random starting point; actions are sequential and can affect later actions. This is not a uniform random shuffle. Newborns wait until the following tick. A dead original participant's slot cannot be reused until that tick ends. These scheduling choices are part of the model and may influence its outcomes. Green background intensity shows food. Organism color encodes movement (red), food sensing (green), and longevity (blue). Colors represent traits, not species or ancestry. `max_generation` is the greatest ancestry depth among current survivors, not the number of generations experienced by the whole population. CSV trait columns are sums; divide by population for means. ## Reproducibility and checks The simulation uses a masked 32-bit xorshift generator and integer arithmetic. The same seed and arguments should produce identical frames and logs across the supported compilers. It checks population counts, occupancy mappings, food bounds, and living organisms' energy bounds every tick. This is an exploratory toy model. Trait changes are selection within these explicit rules, rather than evidence about biological evolution. A single seed cannot establish a general result. Seasonal contrasts, fixed starting traits, mutation-free controls, and many seeds would make useful next studies. ### First native run: seed 604 The 4,000-tick XL C run took 79.55 seconds elapsed (70.83 user CPU seconds). It ended with 6,139 survivors, 32,160 births, 26,181 deaths, and 14,580 actual trait mutations. The population initially overshot its food supply, declined, and eventually occupied nearly every cell. | Mean trait | Initial | Final | | --- | ---: | ---: | | Movement | 124.33 | 100.88 | | Feeding | 129.47 | 76.64 | | Longevity | 139.93 | 147.56 | | Food sensing | 132.04 | 78.13 | Lower feeding and sensing means are consistent with selection for lower metabolic costs in a crowded world, but this interpretation needs controls and multiple seeds. Mean changes also reflect which initial lineages survive. Nearly complete occupancy suppresses movement and sensing opportunities; a next experiment could adjust food regrowth or add disturbances to preserve spatial diversity. Validation completed: all images and logs from the 400-tick seed-604 run matched byte for byte across native XL C, native GCC, and the Linux compiler. All 101 full-run images decoded correctly, and every recorded population matched `160 + births - deaths`. A separate 200-tick seed-777 Linux run passed Valgrind with zero errors and zero leaked bytes. Seven invalid-input and existing-output checks passed. Linux sanitizer compilation was unavailable because its installed runtime libraries were missing; Valgrind was used instead. ## Export on Linux Copy the run directory back using SFTP/SCP and install Pillow and Matplotlib: ```sh python3 export.py run-604 samples ``` The exporter makes an annotated GIF, still images, and a population/trait plot. Simulation pixels and measurements come from the native run; captions, charts, and GIF encoding are produced afterward on Linux. The animation's playback speed is independent of the simulation's execution speed.