docs(site): edit rules for clarity + cross-links; migrate off rules.txt
Build · Site / build (push) Successful in 8s
Tests · Go / test (push) Successful in 2m27s
Tests · UI / test (push) Waiting to run
Tests · Integration / integration (pull_request) Successful in 1m45s
Build · Site / build (pull_request) Successful in 9s
Tests · Go / test (pull_request) Successful in 3m14s
Tests · UI / test (pull_request) Successful in 3m14s

Editorial pass over site/ru/rules.md (on top of the verbatim port):
- moved the lore intro to the RU home page, rewritten in a modern voice;
- fixed typos, replaced the TODO/WTF cargo-tech note and the abandoned
  (---ссылка---) marker with the verified mechanic and a real cross-link,
  dropped the report TODO row;
- wove organic intra-page cross-links (#combat, #movement, #victory, ...);
- documented engine nuances verified against the code: ore auto-farming
  and the capital / "запасы промышленности" store (industry capped at
  population); cargo lost with ships destroyed in battle; and that a
  losing race's colonists at a neutral planet are NOT lost — they stay
  aboard (this corrects the audit note, verified in route.go).

Migration: delete game/rules.txt (its content now lives, authoritative,
in site/ru/rules.md) and repoint every reference to it (ui/frontend code
comments + tests, ui/docs, tools, ui/PLAN.md links). Record the
RU-authoritative rule in site/README.md and CLAUDE.md. The English
site/rules.md mirror follows in a separate stage.
This commit is contained in:
Ilia Denisov
2026-05-31 15:56:00 +02:00
parent d3770e7f77
commit 140ee8e0ee
18 changed files with 56 additions and 1511 deletions
+2 -2
View File
@@ -268,7 +268,7 @@ export interface ReportLocalFleet {
* table uses.
*
* `relation` reflects the local player's stance TOWARD this race,
* not the other way around (`rules.txt` line 1162). Per the engine
* not the other way around (`site/ru/rules.md` #report). Per the engine
* (`controller/race.go.UpdateRelation`) the relation is stored
* unilaterally — race A can be at war with race B while race B is
* at peace with race A.
@@ -508,7 +508,7 @@ export interface GameReport {
/**
* myVotes is the local player's total vote weight in the current
* report, read from `Report.votes` (the engine assigns one vote
* per 1000 population, see `rules.txt:1060`). Zero when the
* per 1000 population, see `site/ru/rules.md` #victory). Zero when the
* report has not been produced yet.
*/
myVotes: number;
@@ -8,7 +8,7 @@ immediately and the auto-sync pipeline drives the server in the
background.
The alliance graph and the 2/3 victory check are NOT computed
here: `rules.txt` keeps each race's outgoing vote target private
here: `site/ru/rules.md` keeps each race's outgoing vote target private
(only the votes a race RECEIVED in the last tally and the local
player's own pick are observable), and the acceptance criterion
"vote counts match server state byte-for-byte" rules out
@@ -10,7 +10,7 @@
// `OrderCommand` payload always carries the canonical `[0, 1]`
// summing to `1.0` shape the FBS encoder ships on the wire.
//
// Engine rules (from `pkg/calc/validator.go` and `game/rules.txt`):
// Engine rules (from `pkg/calc/validator.go` and `site/ru/rules.md`):
//
// - drive, weapons, shields, cargo: float in `[0, 1]`;
// - the four values sum to `1.0` (the engine accepts a small
@@ -6,7 +6,7 @@
// to gate auto-sync, so the local invariants match the engine's
// (`game/internal/controller/ship_class.go.ShipClassCreate`).
//
// Engine rules (from `pkg/calc/validator.go` and `game/rules.txt`):
// Engine rules (from `pkg/calc/validator.go` and `site/ru/rules.md`):
//
// - drive, weapons, shields, cargo: float, equal to 0 or >= 1;
// - armament: integer, >= 0;
+1 -1
View File
@@ -330,7 +330,7 @@ export class OrderDraftStore {
* tracks a single war/peace stance per opponent, so a newer
* entry supersedes any prior `setDiplomaticStance` for the
* same other race.
* - `setVoteRecipient` collapses singleton: per `rules.txt`
* - `setVoteRecipient` collapses singleton: per `site/ru/rules.md`
* each race controls a single vote slot, so a newer entry
* supersedes any prior `setVoteRecipient` regardless of the
* acceptor.
+1 -1
View File
@@ -463,7 +463,7 @@ export interface SetDiplomaticStanceCommand {
* to a race. Mirrors the engine `CommandRaceVote`
* (`pkg/schema/fbs/order.fbs`,
* `game/internal/controller/command.go.RaceVote`). The engine
* tallies votes at turn cutoff (`rules.txt` "Процесс голосования");
* tallies votes at turn cutoff (`site/ru/rules.md` "Процесс голосования");
* between turns the player can change their pick freely. The
* acceptor may be the local race itself — the engine treats
* self-vote as the neutral default and re-applies it whenever a
+1 -1
View File
@@ -112,7 +112,7 @@ describe("validateScience", () => {
expect(result.reason).toBe("sum_not_hundred");
});
test("accepts the canonical First Step fixture from rules.txt", () => {
test("accepts the canonical First Step fixture from site/ru/rules.md", () => {
// 10 Drive + 5 Weapons + 30 Shields + 0 Cargo, normalised:
// 10/45 ≈ 22.222… %, 5/45 ≈ 11.111… %, 30/45 ≈ 66.666… %,
// 0/45 = 0 %. Snapped to one decimal at input time:
@@ -138,7 +138,7 @@ describe("validateShipClass", () => {
expect(result.reason).toBe("all_zero");
});
test("accepts the canonical Cruiser fixture from rules.txt", () => {
test("accepts the canonical Cruiser fixture from site/ru/rules.md", () => {
const result = validateShipClass(
draft({
name: "Cruiser",