This repository defines a deterministic C simulation for identical humanoid cage-fighting robots. Each robot has the same hard-metal body, mass model, armor, actuator availability, processor placement, component health, and failure thresholds. The only competitive difference is the command program loaded into the head-resident control processor.
The current simulator is a physical arena model. Robots have positions, velocities, rigid circular footprints, wall contact, body contact, momentum transfer, knockback, downed states, standing recovery, and component damage. The bodies are not allowed to overlap.
The default build is the generic Linux x86_64 command-line simulator:
makeThis writes build/linux-x86_64/cagefight. On x86_64 Linux it uses cc.
On other hosts it auto-detects x86_64-linux-gnu-gcc,
x86_64-linux-musl-gcc, or zig cc -target x86_64-linux-musl.
You can select the same target explicitly:
make linux-x86
make TARGET=linux-x86Build a runnable binary for the current host:
make native
make TARGET=nativeThis writes build/native/cagefight.
Query the CFA core source/API version:
make native
build/native/cagefight --versionThe value comes from CFA_CORE_VERSION in src/cagefight.h. C and Swift
callers can query the same value with cfa_core_version().
Build an Apple Silicon macOS command-line executable:
make apple-silicon
make TARGET=apple-siliconThis writes build/apple-silicon/cagefight.
Override the Linux compiler and flags when your toolchain uses a different command:
make linux-x86 LINUX_X86_CC="zig cc -target x86_64-linux-gnu"
make linux-x86 LINUX_X86_CC="clang --target=x86_64-linux-gnu"On macOS with Homebrew, install the default cross-build fallback:
make setup-linux-x86Run the automated build availability matrix:
make testThe test target checks every configured build that is available on the current
machine: Linux x86_64, native host, Apple Silicon CLI, and the Swift/Xcode app
build. Missing cross-compilers are reported as skips. Binaries that can run on
the current host are smoke-tested with --list-moves. The native test also
runs a short C logger smoke test and verifies that turn frames and finish
actions were written.
Skip the Swift/Xcode app build during a pure C check:
make test TEST_SWIFT=0CFA owns the run log and crash breadcrumb path. Logs default to:
/tmp/CageFightingAIRuns
Set CFA_LOG_DIR to write logs somewhere else:
CFA_LOG_DIR=build/test-logs build/native/cagefight --smoke-log command_sets/headhunter.cfos command_sets/limb_breaker.cfos 42 3Normal command-line bouts create a detailed per-run log automatically. Each log
includes seed, command set paths, per-turn arena state, robot telemetry, crowd
state, collision capsules, events, finish reason, and a flushed final frame.
Crash signal handlers append a CRASH_SIGNAL line to the active log before the
process terminates.
The Swift/Metal app uses the same C logger and sets the log directory to its
app temporary CageFightingAIRuns directory. The exact path is exposed through
the app's run-log path and printed with NSLog. Swift can add app-specific
actions such as pause, restart, audio toggles, and playback speed changes, but
file creation, frame serialization, flushing, and crash breadcrumbs are handled
by the CFA C layer.
Open CageFightingAI.xcodeproj in Xcode and select the CageFightingAI scheme. The scheme builds the simulator as a macOS command-line executable and runs from $(PROJECT_DIR) so command-set paths resolve correctly.
The Swift/Metal app in ../CageFightMetal does not use the command-line
binary from this Makefile. Xcode compiles src/cagefight.c directly with
CFA_NO_CLI_MAIN=1, so macOS and iOS architecture selection comes from the
chosen Swift/Xcode destination. From this directory, the Swift macOS app can be
built with:
make swift-mac
make TARGET=swift-macDefault run arguments:
command_sets/headhunter.cfos command_sets/limb_breaker.cfos 42
Run a single bout:
build/native/cagefight command_sets/headhunter.cfos command_sets/limb_breaker.cfos 42Bouts continue until a clear stoppage or the one-hour bout horizon is reached.
At the standard 0.48 s turn duration this is 7500 turns, so a
time limit expired without knockout draw is reserved for true endurance
failures rather than short demo runs.
Run the sample tournament:
make tournamentExpected sample output for seed 42:
program wins loss draw stop avg_t
Headhunter 17 1 0 17 30
Limb Breaker 2 16 0 1 72
Clinch Driver 9 9 0 9 60
Counter Guard 8 10 0 8 31
Print the movement command table:
make movesThe simulated platform is the CFM-1 humanoid cage-fighting test article.
| Subsystem | Specification |
|---|---|
| Architecture | Bipedal humanoid, bilateral upper and lower limbs, single armored head module |
| Physical model | Hard circular body footprint in a circular cage |
| Arena radius | 3.00 m |
| Robot hard radius | 0.34 m |
| Robot mass reference | 118 kg |
| Body contact | Rigid separation solver; robots cannot overlap |
| Cage contact | Position clamp with reflected velocity and wall-impact shock |
| Command processing | All tactical command processing, sequencing, and state evaluation run in the head module |
| Distributed electronics | Limbs contain only low-level motor control, encoders, thermal sensors, and current-limit boards |
| Processor failure behavior | Loss of head processor terminates command execution immediately |
| Torso role | Battery pack, power bus, inertial reference, and structural spine |
| Limb role | Striking, guarding, clinch attachment, movement, posture recovery, and balance |
Initial structural values:
| Body part | Initial integrity | Armor | Simulation function |
|---|---|---|---|
| Head | 100 | 12 | Processor, sensors, tactical control |
| Torso | 160 | 18 | Power bus, trunk frame, balance reference |
| Left arm | 90 | 9 | Guarding, jabs, hooks, clinch control |
| Right arm | 90 | 9 | Crosses, hooks, clinch control |
| Left leg | 110 | 11 | Mobility, low kicks, knees, stomps |
| Right leg | 110 | 11 | Mobility, high kicks, knees, stomps |
The hardware is intentionally symmetric. A command set cannot change actuator power, mass, armor, footprint radius, sensor range, or processor location. Tactical performance comes from movement, spacing, target selection, heat management, and conditional behavior.
Each turn resolves in this order:
- Clear transient movement and guard flags.
- Recover a small amount of heat, shock, and stability.
- Evaluate
.cfospriority conditions. - Select the next unconditional command if no condition fires.
- Apply movement impulses.
- Step physical state and separate hard-body contacts.
- Resolve attacks in timing order.
- Apply damage, guard transfer, knockback, fall checks, and detachment events.
- Step physical state again after impact.
- Check stoppage conditions.
Distances are continuous meters:
| Telemetry | Meaning |
|---|---|
center |
Center-to-center distance between robot bodies |
gap |
Surface gap between hard body footprints |
wall |
Distance from robot footprint to cage wall |
pos(x,y) |
Robot center in the cage plane |
v(x,y) |
Current body velocity |
DOWN |
Robot is on the floor and must execute STAND before normal movement |
No-overlap behavior is enforced by the contact solver. When center distance falls below 2 * ROBOT_RADIUS_M, the bodies are separated along the collision normal and their velocities are adjusted. High relative contact velocity adds shock and stability loss.
Persistent clinch or contact-lock is also timed. If the robots remain stuck together for FORCED_MOVE_APART seconds, currently 2.0, the simulation clears clinch pressure and forces both bodies to step and impulse apart.
Command programs use .cfos files. The format supports unconditional cyclic commands and priority conditional rules.
Unconditional command:
COMMAND
COMMAND TARGET
Conditional command:
IF METRIC OP VALUE THEN COMMAND
IF METRIC OP VALUE THEN COMMAND TARGET
Conditionals are checked from the top of the file every turn. The first true condition runs immediately. If no condition is true, the simulator runs the next unconditional command in cyclic order.
Example:
name: Physical Pressure
IF SELF DOWN == 1 THEN STAND
IF SELF HEAT > 120 THEN GUARD
IF DISTANCE > 0.85 THEN ADVANCE
IF DISTANCE < 0.05 THEN RETREAT
IF OPP HEAD < 35 THEN R_CROSS HEAD
IF OPP DOWN == 1 THEN STOMP TORSO
ADVANCE
L_JAB HEAD
R_CROSS HEAD
CIRCLE_L
LOW_KICK R_LEG
GUARD
Supported comparison operators:
< <= > >= == != =
Supported conditional metrics:
| Metric | Value |
|---|---|
SELF HEAD / OPP HEAD |
Component integrity |
SELF TORSO / OPP TORSO |
Component integrity |
SELF L_ARM / OPP L_ARM |
Component integrity |
SELF R_ARM / OPP R_ARM |
Component integrity |
SELF L_LEG / OPP L_LEG |
Component integrity |
SELF R_LEG / OPP R_LEG |
Component integrity |
SELF PROCESSOR / OPP PROCESSOR |
Head processor health |
SELF HEAT / OPP HEAT |
Thermal load |
SELF SHOCK / OPP SHOCK |
Shock accumulator |
SELF STABILITY / OPP STABILITY |
Balance and posture reserve |
SELF DOWN / OPP DOWN |
1 when down, otherwise 0 |
DISTANCE, GAP, or RANGE |
Surface gap in meters |
CENTER_DISTANCE |
Center-to-center distance in meters |
WALL or CAGE |
Own footprint distance to cage wall in meters |
Supported targets:
HEAD
TORSO
L_ARM
R_ARM
L_LEG
R_LEG
Supported movement commands:
| Command | Function |
|---|---|
GUARD |
Brace frame and raise arms around head and torso |
ADVANCE |
Apply body impulse toward opponent |
RETREAT |
Apply body impulse away from opponent |
STRAFE_L |
Move laterally left while facing opponent |
STRAFE_R |
Move laterally right while facing opponent |
CIRCLE_L |
Circle left with slight inward pressure |
CIRCLE_R |
Circle right with slight inward pressure |
RESET |
Break clinch and back out |
STAND |
Recover from downed state if lower frame can carry load |
Hands stay in a raised guard posture by default. Incoming head and torso
strikes can trigger dynamic block attempts when an arm actuator is available.
GUARD increases block tracking, reduces strike accuracy, and can shunt part
of the impact into the shielding arm. Body shots can be deflected in some
close and mid-range exchanges, though head protection remains the strongest
guard behavior.
Supported attack commands:
| Command | Function |
|---|---|
L_JAB |
Fast left-arm linear strike |
R_CROSS |
Rear straight punch with stronger momentum transfer |
L_HOOK |
Short left arc strike |
R_HOOK |
Short right arc strike |
UPPERCUT |
Close vertical head strike |
LOW_KICK |
Low-line leg attack |
HIGH_KICK |
High-energy head kick |
KNEE |
Contact-range piston strike |
ELBOW |
Compact close strike using arm hardpoint |
CLINCH |
Attach both arms and constrain separation |
THROW |
Clinch-only rotational takedown |
STOMP |
Downward strike against close or downed opponent |
| Method | Condition |
|---|---|
| Processor kill | Head integrity or head processor reaches zero |
| Technical knockout | Torso power bus reaches zero |
| Knockout | Cranial shock reaches watchdog reset threshold |
| Mobility kill | Both legs detach |
| Decision | Maximum turn count reached; higher remaining structural and posture score wins |
| File | Doctrine |
|---|---|
command_sets/headhunter.cfos |
Maintain striking distance, attack head processor, stomp if opponent falls |
command_sets/joint_reaper.cfos |
Guarded leg destruction that opens a head finish after Headhunter loses balance |
command_sets/shock_clinch.cfos |
Short-range clinch pressure, throws, stomps, and torso/head shock accumulation |
command_sets/cross_guard.cfos |
Guarded head-counter plan with hooks, uppercuts, resets, and heat control |
command_sets/limb_breaker.cfos |
Damage legs and arms, adapt to damaged lower frame, finish upstairs |
command_sets/clinch_driver.cfos |
Enter body contact, clinch, knee, elbow, and throw |
command_sets/counter_guard.cfos |
Guard, retreat, strafe, and counter when opponent overcommits |
Before contact solve:
R1 radius 0.34m R2 radius 0.34m
( overlap )
[###][###]
After contact solve:
[###] [###]
gap = 0.00m
Result:
bodies are separated along the collision normal
velocities are adjusted
high relative velocity adds shock and stability loss
R1 R_CROSS HEAD
R1 center ----------------------> R2 center
impact vector
Effects:
head armor reduces raw damage
net damage reduces HEAD integrity
part of net head damage reduces PROCESSOR health
strike impulse adds velocity to R2 away from R1
high pressure may set R2 DOWN
circular cage wall
/ \
| R2 knocked back |
| ---> [###] |
\__________________/
If the robot footprint crosses the arena boundary:
position is clamped inside the cage
outward velocity is reflected
wall impact may add shock and reduce stability
IF SELF L_LEG < 35 THEN RETREAT
IF OPP DOWN == 1 THEN STOMP TORSO
IF DISTANCE > 0.85 THEN ADVANCE
The command processor evaluates these rules every turn before the cyclic plan.
This allows component health and physical position to cause behavior changes.
Create a new .cfos file under command_sets/ and run it against the existing programs:
build/native/cagefight command_sets/my_program.cfos command_sets/headhunter.cfos 1001For tournament comparison:
build/native/cagefight --tournament 1001 command_sets/*.cfosUse fixed seeds for regression testing. Change the seed when exploring whether a command set is robust to timing and impact variation.
The simulator is contained in src/cagefight.c. It uses only the C standard library, math.h, and a deterministic local linear congruential generator. No external runtime is required.
The movement table is data driven in move_specs. To add a new command, add an enum value, define its MoveSpec, and add any special physical handling if it is not a normal movement or strike command.