Dev blog 2026-10-22 · Keel 0.5.2.1

Three factions, one loop

A loop of three factions, and a standing you earn.

We built three alien factions that beat each other in a loop, gave each an Enclave to visit, and made your standing with them something you earn and spend. This post covers who they are, how they fight, what standing changes, and what you fly while you earn it.

The factions and their Enclaves have been live since 0.5.0, and the live build is 0.5.2.1. A Titan for each faction is coming in 0.5.3 and is a story for another post. Here we stay with what runs today.

The Keel game screen on Layer 1. The contacts list on the right shows two hostile Breaker Patrols, each tagged PLS for Plasma, with shield and hull bars. Six Carriers are listed on the left, and the log says a Breaker jammed a Carrier.
Layer 1 on a 0.5.2 build. Two Breaker Patrols sit in the contacts list, each tagged PLS for Plasma, and the log shows a Breaker jamming a Carrier. The six Carriers and the Marks come from a dev-filled capture account.
The problem

A faction used to be a label.

Before 0.5.0, Raiders, Sentries, and Breakers were only what an enemy happened to be.

A faction told you the damage type, the colour, and which Remnant a wreck might hold. It was not a reputation bar. There was no place to visit and nobody to deal with.

Alien blueprints came from the Haven shop, from incursions, from wrecks, and from research. Nothing sent a pilot looking for a faction. Nothing a pilot did to one faction cost them with another.

We wanted the factions to be somewhere you go and something you earn, not only something you shoot. That is decision D79, and it shipped in 0.5.0.

What we wanted instead

Three rules for a faction you can earn.

The design started as a short list of answers. These three shaped everything after them.

Kills stay out of it

Ordinary kills never move standing. You fight all three factions all day, and a score that moved with every kill would push every pilot toward kill on sight with everyone.

Standing is a currency

You earn it from quests and spend it on copies at the merchant. A spend never takes you below zero, so buying a hull cannot turn the guards on you.

Helping one costs you with another

A Hunt for one faction costs half its gain with the faction it targets. The three are a loop, so what you do for one pulls against another.

What we built

Three factions that share one brain and differ in gear.

A Raider squad, a Sentry squad, and a Breaker squad fly the same AI. They differ in what they carry. Every NPC flies a real fit built from its own faction's modules, out of the same tables a player's crafted gear uses.

2 to 10Ships in a squad from Layer 1 to Layer 6, as flown. The squad sizes are stand-ins and the sector caps limit them.
14 sA lead waits this long, then jumps one sector, and its squad follows.
3Sectors a squad chases you for. It focuses one ship, usually the weakest.
120 sUntil a lost squad is replaced. On Layer 1 it is 30 seconds.
A Raider Patrol hull in rust and orange, seen from above. Raiders Impact. They hit hard and fire slowly. Gun volley 25 percent up, cycle 15 percent longer. Shield, Clamp, Jam, and Brace restore 25 percent up. Armor, drive, hold, and mender 15 percent down. Hull: 5 percent more shield. Favoured lines: Lance and Screen. Gear resists Impact by 15 percent and the other two types by 5.
A Sentry Patrol hull in pale cyan, seen from above. Sentries Phase. They lock fast and track small hulls best. Gun lock 25 percent shorter, volley 15 percent down. Tracking removes half of a big gun's penalty against a small hull. Mender 25 percent up, Brace cooldown 25 percent shorter. Shield, Clamp, armor, and hold 15 percent down. Hull: 5 percent shorter lock. Favoured lines: Lance and Tender. Gear resists Phase by 15 percent and the other two types by 5.
A Breaker Patrol hull in violet, seen from above. Breakers Plasma. They take hits, haul, and keep firing. Gun volley 15 percent down, shots 25 percent cheaper in battery. Armor, drive, and hold 25 percent up. Shield, Clamp, and Jam 15 percent down. Hull: 5 percent more hull. Favoured lines: Anchor and Mule. Gear resists Plasma by 15 percent and the other two types by 5.

Percentages are the faction lines in rules.FACTION_WEAPON, FACTION_MODULE, FACTION_BRACE, and HULL_FACTION. The hull shifts, resists, and tracking are marked as stand-ins in balance/tuning.csv. The sprites are Patrol hulls, class 1.

Reading them on the map

Colour first, shape second.

Hulls, modules, and incursion blocks wear the faction colour: rust and orange for Raiders, pale cyan for Sentries, violet and magenta for Breakers, gunmetal for Humans.

Module icons add a shape: a star for Raiders, a ring for Sentries, a hexagon for Breakers, a square for Humans. The colours come from one palette file and nothing else is allowed to invent a faction hue.

Layer 2 with an orange block of hexes marked incursion near the centre and a violet block at the upper right. A fleet of six Carriers is listed on the left.
Layer 2 on a 0.5.2 build, from the same dev-filled capture account. An incursion wears its faction's colour, so the orange block is a Raider incursion and the violet block is a Breaker one.
The loop

Impact beats Phase beats Plasma beats Impact.

Each faction deals one damage type, and its gear leans to the same type. A hit that beats the type of the module it strikes does 15 percent more. A hit that the struck type beats does 15 percent less.

beats beats beats Raiders Impact Sentries Phase Breakers Plasma
Schematic drawn for this post, not a capture. An arrow points at the faction whose pools the other faction's damage type beats.
Raiders DamageImpact Hits harder againstSentries Hit harder byBreakers
Sentries DamagePhase Hits harder againstBreakers Hit harder byRaiders
Breakers DamagePlasma Hits harder againstRaiders Hit harder bySentries

The merchants follow the arrows.

A Raider merchant sends you to hunt Sentries. A Sentry merchant sends you after Breakers. A Breaker merchant sends you after Raiders. The target is always the faction your faction beats.

The edge reads the module that is struck, not the gun. The faction of the shield decides it while the shield is up, and the faction of the armor decides it for what gets through. A fit may mix factions freely, and there is no set bonus.

What the code pins
  • A Raider Impact hit on a Sentry pool counts 1.15 times, and a Phase hit on a Raider pool counts 0.85 times.
  • The same type against itself is even.
  • The edge sizes are EDGE_ADVANTAGE and EDGE_DISADVANTAGE in rules.py.
The fourth faction

You start as a Human, and Humans take no edge.

Every account starts with Human hulls and gear. Humans are not an NPC faction: no squad flies Human, and no Enclave stands for them.

  • Human gear is 10 percent under the alien baseline on every slot, with no penalty line. A Human hull is the baseline, with no shift.
  • A Human weapon splits every shot, a third each of Plasma, Impact, and Phase, each third against its own resist.
  • Human armor and shields resist all three types by 8 percent. An alien piece resists its own type by 15 and the other two by 5.
  • A Human pool takes no edge in either direction.
  • Haven sells Human copies. Incursions, wrecks, and research make Human blueprints only. Alien modules still drop as loot, and you can fly them without standing.
A Human Patrol hull in gunmetal with pewter glass, seen from above.
A Human Patrol, class 1, in gunmetal with pewter glass.
As a pilot lives it

Find a door, dock, take a quest, come back.

Each faction keeps an Enclave, a small map of its own that you reach through a wormhole. The server owns the door, the dock, and every quest count.

  1. Find the doorEach faction keeps one wormhole open on Layer 2 to Layer 6. It is hidden like any wormhole and personal to you: your charter mates find their own. The Journal remembers a found door until it collapses.
  2. Jump inThe Enclave is a 7 by 7 box with the station at 8, 8. It borrows the tables of the layer its door opens from, so a door on Layer 6 leads somewhere as dangerous as Layer 6.
  3. DockThe station docks you at Neutral or better: berth, repair, refit, and Deposit. No industry, no blueprint shop, no Spools, no insurance, and no layer travel.
  4. Take a questThe merchant offers three quests, and you hold one at a time per merchant. Hunt, Haul, Salvage, Survey, or help clear a rival incursion.
  5. Hand in and spendA hand-in pays standing and XP. Standing and Marks buy copies at the same counter.
LogQuest accepted: Destroy 15 Sentry ships on Layer 2 or deeper.
LogRaider quest: 7 of 15.
LogRaider quest done. Return to the Raider Enclave to hand in.
LogQuest handed in: +0.4 Raider, -0.2 Sentry, 8 XP.
LogYou need 3.0 Sentry standing; you have 1.0.

Wording is copied from the server's strings in factions.py. The numbers are the ones a Layer 2 Hunt produces: 15 kills, 0.4 standing, 0.2 off the rival, 8 XP. The last line shows what a Sentry merchant says to a pilot with 1.0 standing who asks for a 3.0 copy.

FriendlyGood to see you, friend. The best of the yard is open to you.
NeutralYou may dock. Earn our trust and the shop opens further.
HostileYou are not welcome here. Prove yourself or keep away.
KOSOur guards fire on sight. Leave.

The merchant's greeting for each level, from GREETING in factions.py. A pilot at Hostile or worse cannot dock, so they read these lines while browsing the merchant from afar.

What standing changes

Docked or refused. Guards calm or guards firing.

Standing runs from -10 to +10 in steps of 0.1, starts at 0, and never decays. Four words sit on top of that number. In the live build, only two things read those words.

Friendly5.0 and up StationDocks you The faction's guardsLeave you alone until you fire on one MerchantQuests and buying
Neutral-2.4 to 4.9, and everyone starts at 0 StationDocks you The faction's guardsLeave you alone until you fire on one MerchantQuests and buying
Hostile-4.9 to -2.5 StationRefuses you The faction's guardsAttack like any other NPC MerchantRead-only, from the Journal
KOS-5.0 and below StationRefuses you The faction's guardsAttack like any other NPC MerchantRead-only, from the Journal
Prices do not moveA copy costs the same standing and the same Marks for every pilot at every level. The level decides whether you can stand at the counter, and the number decides what you can afford there.
Only Enclaves changeOutside an Enclave nothing changes. Every faction's roamers still fight everyone, whatever your standing. Inside, the other two factions' ships are ordinary hostiles too.
Words that matchFriendly and Neutral behave the same today, and so do Hostile and KOS. The first thing that will check the Friendly level itself is coming in 0.5.3, and it belongs to another post.
How standing moves

Quests raise it. Hunts and purchases lower it. Kills do nothing.

Each merchant keeps three offers and you hold one quest per merchant. Offers are posted for Layer 2 and deeper, up to the deepest layer you have reached. The size and the reward follow the layer.

LayerGainHuntHaulSalvageSurvey
20.415150215
30.520200220
40.730300330
50.940400440
61.250500550

Gain is standing paid at hand-in. Hunt is rival ships to destroy on that layer or deeper, Haul is units of ore or gas, Salvage is the faction's own Remnants, and Survey is sectors you had not visited. Every size is a stand-in marked in balance/tuning.csv. XP at hand-in is 8, 11, 17, 25, and 38.

Five kinds of quest, one number.

  • Hunt: destroy the rival's ships. It also costs half the gain with that rival, and unlike a spend it can take that standing below zero.
  • Haul: deliver ore or gas to the station. The hold is taken first, then the stash.
  • Salvage: deliver the faction's own Remnants.
  • Survey: chart sectors you had not visited on that layer.
  • Incursion: contribute over 5 percent to clearing a rival faction's incursion on that layer or deeper. Clearing one with no quest held moves nothing.
The rest of the moves
  • Abandoning a quest costs a tenth of its gain, rounded up to the next 0.1. It never takes you below zero.
  • Buying a copy spends its standing price. It never takes you below zero either.
  • At 0.4 a quest, the 5.0 Friendly line is 13 quests away. At 1.2 it is 5. That is arithmetic, not a measured evening.
  • Quests are closed in the tutorial and while Infinite is on.
What the merchant sells

The only door for alien blueprints.

The faction merchant is the one place an alien blueprint enters the game. Every faction sells 50 module copies and 22 hull copies.

50Module copies: weapon, drive, shield, armor, hold, Jam, Clamp, Brace, Sensor, and mender, in classes 1 to 5.
22Hull copies: every class from Patrol to Carrier in each of its role lines.
0.2 to 1.5Standing for one module copy, class 1 to 5: 0.2, 0.4, 0.6, 1.0, and 1.5.
0.5 to 8Standing for one hull copy, class 1 to 5: 0.5, 1.5, 3, 5, and 8.
Standing and MarksEvery copy also costs a Marks fee equal to the Haven shop price of its materials. A Sentry Lance Destroyer copy is 3.0 standing and 312,000 Marks, as the code on our main branch prices it today.
One run, then tradeA copy is one manufacturing run. A merchant never sells an original. Bought copies sell and trade like any copy.
Role lines live hereThe Lance, Anchor, Screen, Tender, and Mule hulls are sold by faction merchants. Each faction favours two of them: Raiders Lance and Screen, Sentries Lance and Tender, Breakers Anchor and Mule.

Buying needs you docked at the station. The Factions tab of the Journal opens every merchant read-only from anywhere, so you can plan a purchase, and you can pin a copy as a goal. The log tells you when its standing price is in reach. It does not count Marks.

Under the hood

One mixin, a few tables, and a lot of checks that read one number.

The mechanic lives in server/factions.py, 599 lines, mixed into the world. The faction tables sit in server/rules.py, and server/npc_gear.py, 243 lines, builds every NPC's fit. One function writes standing, and the rest only read it.

The stateserver/factions.py keeps each account's faction_standing table, its quest boards, the Enclave doors, and the merchant rows. A short faction_log keeps the last 20 moves.
The tablesserver/rules.py holds FACTION_WEAPON, FACTION_MODULE, FACTION_BRACE, HULL_FACTION, FACTION_RESIST, and FACTION_DAMAGE. Each value is a row in balance/tuning.csv.
The squadsserver/world.py spawns the squads and server/npc_gear.py builds each hull's fit, with grade, rank, and quality set by layer. The AI is shared, so a faction's behaviour is its gear.

One Hunt, as a call chain

  1. AcceptThe client sends quest_accept. The server checks that you are docked at that Enclave and that you hold no quest there, then moves the offer onto the board as your active quest._quest_accept, _quest_board
  2. KillA rival ship dies in the combat code. A Hunt counts it if the ship was on the quest's layer or deeper._hurt_npc, _quest_on_kill
  3. CountProgress is capped at the need and logged at a quarter, a half, and three quarters. At the need the quest is marked done._quest_progress
  4. Hand inDocked at the station, the server pays the gain, takes the rival's cost, and adds the XP._quest_hand_in
  5. WriteOne function clamps standing to -10 and +10, logs the move, and says so when the level word changes._shift_standing, level
  6. SpendA purchase checks standing, Marks, and the dock, spends both, and writes a one-run copy into your blueprints._merchant_buy

The main functions

_shift_standingfactions.py

The one writer of standing. Every quest, abandon, and purchase goes through it. It clamps to -10 and +10, keeps the log, and lets a spend stop at zero.

_tick_enclavesfactions.py

Keeps exactly one door per faction open on Layer 2 to Layer 6. A door lives 30 to 90 minutes. When it collapses a new one opens, and the Enclave takes a new shape.

_guard_calmfactions.py

Says whether an Enclave's own ships leave a pilot alone: Neutral or better, and not provoked. Targeting and escorts both ask it.

_enclave_dock_refusalfactions.py

The other check that reads standing. It refuses the dock at Hostile or worse and tells you the level and the number.

_spawn_squadworld.py

Picks a squad's faction, builds its ships, and in an Enclave turns two squads in three into the faction's own guards.

build_fitnpc_gear.py

Crafts a real module for every open slot, rolls its grade, and spends the class power grid the way a player would.

_merchant_rows_builtfactions.py

Builds the shop rows for one faction. They are the same for every pilot, so one memo serves everyone and a balance apply clears it.

Choices we are happy with

One writerThe clamp, the log, and the level message live in one function. A new way to move standing gets all three for free.
Danger follows the doorAn Enclave has no table of its own. It borrows its door layer's through rules.tier, so squads, gear, and mining rates follow the door without a new number.
Shared tablesPlayers and NPCs read the same faction lines, so a balance change touches both at once.
The shop is dataRows are built from the bills and one price table, not hand-written, so a new slot or class appears in every faction's shop.
The client side

The server decides. The client draws and asks.

  • The server owns standing, the dock refusal, who is calm, quest progress, and every price. The client may not decide any of them.
  • merchant_panel.gd draws the rows the server sent and sends an order. The server checks standing, Marks, and the dock again.
  • sector_card.gd draws the station card: the faction, your standing, and one button to the merchant. journal_panel.gd holds the Factions tab.
What the code looks like in numbers
599Lines in factions.py.
243Lines in npc_gear.py.
676Lines in merchant_panel.gd.
7Tests in FactionsTest.
What the tests prove

What is pinned, and what is not.

The unit tests live in server/test_alpha.py and run on every commit. playtest_check.py walks the Enclave loop with a real pilot over the network.

Pinned

  • test_levels_and_spends_never_go_below_zero: the four levels at 5.0, 4.9, -2.4, -2.5, -4.9, and -5.0, standing clamped at 10, and a spend that stops at zero.
  • test_each_faction_keeps_one_door_and_the_enclave_follows_it: one door per faction on Layer 2 to 6, an Enclave inside a 7 by 7 box, danger that follows the door, and a collapsed door replaced.
  • test_station_docks_at_neutral_and_guards_follow_standing: the refusal at -3.0, a calm guard at 0.0, a guard that fights back once fired on, and another faction's ship never calm.
  • test_hunt_quest_accept_progress_and_hand_in: rival kills count, other kills do not, and a hand-in pays +0.4 and takes 0.2 from the rival.
  • test_merchant_sells_for_standing_and_marks: 50 module rows, a 3.0 price for a class 3 Lance, both spends, the copy written, and Infinite refused.
  • test_counter_loop_uses_the_defense_not_the_weapon: the 15 percent edge both ways, read from the struck module.
  • The Faction Enclaves area of playtest_check.py: find a door, jump in, dock, take a quest, hand it in, buy a copy, and find industry closed at the station.

Not pinned, or thin

  • Survey, Salvage, and Incursion quest progress. Only Hunt and Haul have tests.
  • Who a guard shoots in a running fight. The tests cover _guard_calm alone, not a whole tick.
  • The Enclave squad mix. No test and no count.
  • The way back from Hostile. The 0.5.3 Restitution hunt has unit tests, but how long the climb from KOS feels is untested.
  • Faction against faction. farm_sim.py tunes squads by layer and rotates the faction each fight, so it cannot say whether one faction is stronger. Every number here is a stand-in.
What we learned and what is next

Reading the code for this post showed us two gaps.

Kills stay out of standingEvery pilot fights all three factions all day, so we kept kills out of the number. The cost is that standing moves only at a station, through quests.
A word has to be trueThe Neutral greeting says the shop opens further as you earn trust. In the code the shop is the same rows at every level, and standing is the thing you spend. We should change the line or make it true.
The gapsA pilot at Hostile or worse cannot dock, quests and the merchant need a dock, and standing never decays. 0.5.3 adds a Restitution hunt: a hunt against the faction's rival, taken and handed in without docking, that earns standing back until Neutral. Also, by our reading of the code, an Enclave sends two squads in three as its own guards, and the third falls through to the open rotation, which gives Raiders at that slot. Neither has a test.

Where we would push next

  • Watching how the 0.5.3 Restitution hunt plays as the way back from Hostile, and tuning it if the climb is too long or too short.
  • Tests for Survey, Salvage, and Incursion quests, and for the Enclave guard mix.
  • A fresh capture of an Enclave station and its merchant. The captures folder holds none today.
  • A greeting for each level that says what the level really does.
Join the open alpha

Pick a faction and see who docks you.

Keel is free to play on PC, and the open alpha is where the factions live. Find us in the Keel Discord, tell us what the factions did to your evening, and file a report from inside the game when something looks wrong.

Players whose reports become fixes are credited in game. Try this first: find one Enclave door on Layer 2, dock, take a single quest, and tell us whether the standing felt worth the trip.