These commits are when the Protocol Buffers files have changed: (only the last 100 relevant commits are shown)
| Commit: | a790ea0 | |
|---|---|---|
| Author: | snailbrainx | |
jobs: an on-chain job board carrying the generic escrow deal Adds a player-driven contracts system: a job is an escrowed reward plus a worker collateral plus a deadline, optionally exclusive to one designated worker. It is settled by a completion percentage that a bound arbiter dials on a dispute, or by the end-date sweep when nobody rules. The obvious shape for this is a catalogue of verified types -- transport this cargo, escort that vehicle, rent me a slot -- each with a consensus rule that watches the world and decides whether the term was met. That was built and abandoned: most of what players want to contract about is not observable to consensus, and every type that pretends otherwise is an approximation with an exploit surface behind it. So the chain does the one thing it can do perfectly -- hold value and release it by a rule the parties agreed to in advance -- and the job "category" survives only as a cosmetic integer tag that consensus never reads. database/jobs.* the board table: rows, queries, admission counts and the reserved-coin sums; terminal transitions delete the row, so the table stays bounded src/jobs.* everything above the table: the move-op lifecycle (post/assign/accept/cancel + the deal ops), the settlement math, and the superblock expiry sweep proto/jobs.proto the non-column payload docs/escrow-deals.md the design notes It is the first consumer of the runtime-tunable parameters table added in the preceding commit: the admission caps and the reward floors read through it, so they can be retuned -- or posting frozen with a 0 override -- without a redeploy. Settlement properties, all test-pinned: each party bears the protocol tax and the arbiter fee on its own transacted share, so fee incidence tracks payout share; escrow is conserved exactly (every path either pays out or refunds the full pot, with division dust burned, never redistributed); tax_bps, fee_bps and the reaction window are snapshot at post, so a governance retune can never change an in-flight deal. A late confirm or an arbiter-bound dispute inside the reaction window pushes the deadline to now + W, at most twice, so the successor move always keeps a full window to answer. Admission control rather than a sweep bound: caps are enforced at the door (global, per poster) so settlement semantics never change for rows already on the board, and posting can be frozen outright with a 0 override. Reputation counters are display-only -- no consensus rule reads them back. They are raw tallies, not trust scores: a colluding ring can wash-trade its own deals for the price of the burn, which is why the value-weighted counters exist alongside the counts. Ghosting an arbiter is deliberately NOT counted: a post binds an arbiter unilaterally, with no consent step, so a permanent per-account mark would be inflictable on a non-consenting third party. A settled deal is not retained on chain: the row is deleted and only the aggregate account counters remain. Per-deal retention belongs to a general archival mechanism rather than a table bespoke to this feature; what such a record needs to carry is written down in docs/escrow-deals.md so it can be added without re-deriving it. Tests: 65 unit cases over the deal lifecycle and the settlement algebra, the database table layer, and four gametest suites (jobs_deals, jobs_caps, jobs_rpc, jobs_reorg) covering the end-to-end move wiring, the admin-tunable caps, the RPC surface and reorg unwinding.
| Commit: | d856d8b | |
|---|---|---|
| Author: | snailbrainx | |
Retire the two-call height idiom, and stop overselling valueruled Two findings from the re-review of 779029a, both real, neither consensus. The dual-clock footgun had one site left that the last pass missed, and it was the harmful shape rather than the merely fragile one: a 200-iteration loop in logic_tests did SetHeight(Height()+1) then SetBlockHeight(BlockHeight()+1), so the second call incremented a value the first had already clobbered -- chain height 44 on the first pass, not 101. Since this idiom has now produced findings in two consecutive rounds, every remaining SetHeight-then- SetBlockHeight pair becomes one SetHeights call instead of just the broken one, and a same-value pair in combat_tests collapses to the single call that already set both. No pairs remain. PXLogicTests' own fixture stays two calls and now says why: its local SetHeight helper also pins the regions table. And a claim of mine that did not survive checking: the proto comment said arbiter_value_ruled carried "the same proportionality caveat" as deals_posted_value. It does not. Crediting the whole pot means collateral returned at a high p -- which bears no tax -- rides in free, so a sock-puppet trio buys value here at ~1.3% of the credited figure against ~4% for the reward-based counters (R=1000 with the maximum 2x collateral, self-ruled p=100: 40 burned, 3000 credited). The pot is still the right measure of what a ruling governed, since a p=0 ruling decides the fate of all of it, so the measure stays and the comment now states the real rate and warns against comparing the two counters as one currency.
| Commit: | 7465674 | |
|---|---|---|
| Author: | snailbrainx | |
jobs: no consensus ghost mark for an arbiter nobody asked A deal post binds its arbiter unilaterally -- it names any initialised account, and there is no consent move, no acceptance and no way to refuse or revoke. Pairing that with a permanent `arbiter_ghosted` counter made a defamation primitive: two colluding accounts post a throwaway deal naming any third account as arbiter, accept, dispute, and let it lapse. The sweep's GHOST_SPLIT then branded a bystander who never signed anything, for the cost of the burn on one minimum deal (40 vCHI at the current params), with no rate limit, no defence -- the poster picks the window, and `d` has no floor -- and nothing anywhere that decrements the counter. Drop the counter rather than invent a consent mechanism this round, because nothing is actually lost: the settled history row already carries `arbiter`, `settle_mode` (GHOST_SPLIT), `fee_paid` and `dispute_time` -- the last added precisely so a Phase-2 layer could attribute a ghost. Derived there, ghosting stays scoped, decayable and rebuttable instead of branded into consensus state for good, and consensus still punishes it where it bites: the forfeited fee. Settlement no longer even OPENS a non-consenting arbiter's row: it joins the credit map only when there is a fee to pay or a ruling to record, which also spares an account read on the pro-bono happy path. `arbiter_rulings` stays -- it moves only on the arbiter's own signed ruling, the same footing as the poster and worker counters -- and gains `arbiter_value_ruled`, the pot each ruling directed. A raw count is farmable by a sock-puppet trio for the burn alone; the value weight is what makes a big claimed record cost proportionally, and it makes all three role records count+value. The proto comments that oversold these numbers as vetting material now say plainly what each one can and cannot be trusted for. Tests: the poisoning sequence is pinned as a regression over both fee shapes (the victim signs nothing and ends with an untouched record and balance), the ghost-split cases assert the arbiter is left alone, and the previously untested successful p=100 ruling is covered.
| Commit: | c64333e | |
|---|---|---|
| Author: | snailbrainx | |
jobs: consensus trust counters for the poster and arbiter roles Only the worker side of a deal settlement left a consensus record, so a poster's payout history and an arbiter's rulings existed nowhere in game state -- clients could derive them from settled history, but the GSP prunes that after jobs-history-retention. Adds five account counters, all bumped inside SettleDeal's existing per-name credit loop (no extra account reads): the poster's mirror of the worker completion pair under the same tax anchor, a disputed count for both parties, and the arbiter's rulings against ghosted disputes. GHOST_SPLIT doubles as the no-arbiter dispute fallback, so the arbiter counters ride inside the credit-map branch that only exists when an arbiter was actually bound.
| Commit: | 229288e | |
|---|---|---|
| Author: | snailbrainx | |
jobs: compaction pass 1 -- dead declarations + duplicated rationale First of three behaviour-preserving compaction commits, from a verified deletion audit of the whole branch. Net -48 lines, no object-code change beyond two dead test-library helpers. DEAD CODE (added by this branch, never reachable): - gametest/pxtest.py: onlyJob () -- its only consumers lived in jobs_transport.py, deleted with the delivery types; nothing in gametest/ references it and Makefile.am lists no file that could. - gametest/pxtest.py: the vestigial `mine=True` parameter of setCharactersHP. All 20 call sites in the tree pass a single positional argument; the only callers that ever passed mine=False were jobs_stress.py and jobs_assassination.py, both removed in the pivot. Dropping it restores the upstream signature verbatim, which also reduces merge friction. - src/logic_tests.cpp: an unused #include <map>. DUPLICATED RATIONALE (kept at ONE canonical site, cross-referenced from the others -- the convention already used elsewhere in these files): - The reputation-counter threat model was stated at four sites; the canonical site is BumpJobStats / BumpDealStats in jobs_predicates.cpp, so proto/account.proto and the JSON exporter now point at it. Two sentences deliberately KEPT in the proto because that file is their canonical home: the field-width wrap acceptance (it sits with the field declarations) and the Phase-2 directive to read "completed" as "settled with the worker earning something", which is an instruction to a future consumer rather than a restatement. - The admission-cap and prune-batch rationale was restated in proto/config.proto over src/jobs.hpp and ExpireJobs. Kept in the proto: "A POST past a cap is rejected" (enforcement semantics, without which the surviving 0-freezes-posting half is unintelligible), the 0 sentinel meaning on both proto sites, and "ordered by settled_time then id" (determinism). - The reaction-window extension rule was stated three times; the canonical site is ExtendForReactionWindow, which alone carries the strict-< non-shortening proof, the one-shot 2W bound and the W=0 inertness proof. Both proto sites keep the 0-sentinel meaning. - The bounty memoisation cost note in jobs.cpp was a strict subset of the class doc in jobs.hpp. The chain-halt warning ("this must NOT be a CHECK") and the probe-is-the-membership-check statement stay. - WantedPredicate::OnTargetKill restated PayKillShares' aggregation for the fourth time, and restated its own burn rule twice. FALSE CLAIMS CORRECTED (worth taking at zero line saving, because each was a live contradiction): - Both src/jobs.hpp and the JSON exporter claimed the linked-entity kind derives from the predicate registry. It does not: LinkedEntityKind has exactly one consumer, the ValidateJobs switch, and JobCommonJson hardcodes the "building" key. Fixed at BOTH sites -- fixing one alone would just relocate the inconsistency. - The JobOperation doc listed four ops; there are five (DealOperation is parsed from the `dl` discriminator), contradicting its own Parse doc. - The AudienceFaction default is currently unreachable (all three live types override to INVALID); documented as the contract for a future faction-scoped type rather than as live behaviour. The overrides are deliberately NOT collapsed into the base: that would delete the wanted override's eligibility rationale. Validation: src 719/723 with the four known map-artifact failures; jobs_bounty and jobs_caps green (they exercise setCharactersHP).
| Commit: | 400a7ff | |
|---|---|---|
| Author: | snailbrainx | |
jobs: escrow v1.2 -- close the 5af4495 review Lows (no consensus change) Closes all six Low findings of the corrected three-model review of escrow-clean @ 5af4495 (source verdict: MERGE). Nothing here changes consensus behaviour: comments, tests, and one provably-equivalent expression, so no wipe/resync is required. L1 -- invite_only wire/state contract PINNED (pre-launch decision). JobData.invite_only is the BORN-PRIVATE discriminator, not a general "is exclusive" bit: it is set only at POST by a "w" term, and ASSIGN designates a worker WITHOUT setting it, so a publicly posted deal that is later assigned is exclusive while still reporting invite_only=false. Exclusivity is therefore the pair the accept gate enforces, never the bit alone: exclusive = invite_only || designated_worker != "" Documented at all three sites that previously conflated "assigned" with "invite-only" (proto/jobs.proto, AssignOperation::IsValid, GameStateJson job export) and pinned by assertion in AssignRestrictsAcceptToDesignatedWorker, which now checks the ASSIGNed row carries "designated" and NOT "inviteonly". The rejected alternative -- setting the bit on ASSIGN -- would store state already derivable from designated_worker and retroactively mislabel a public deal as born-private. Pinned now because invite_only is serialized consensus state: changing it post-activation is fork-visible. L2 -- the poster != arbiter ban guarantees a distinct ACCOUNT, not a distinct person. One operator can arbitrate their own deal under a second Xaya name; a named-arbiter model has no Sybil-resistant identity to check. The comment now says so, and names the real protection: the arbiter is bound at POST, so the worker sees who will judge before staking collateral. L3 -- the DealPredicate header still promised "a fixed posted end-date", which the v1.1 reaction window made false. It now states the live rule: the end date moves FORWARD ONLY (a late single confirm, or an arbiter-bound dispute, pushes it to now + W, at most twice), so the posted date is a floor, never a promise. L4 -- documented the retention foot-gun: because the floor is 0 and 0 means keep-forever, a NEGATIVE jobs-history-retention override silently disables pruning instead of being rejected. Consensus-safe (every node clamps identically) and never silent to a reader -- getjobsparams reports the post-clamp 0, which is how an operator sees pruning is off. L5 -- getjobsparams gained end-to-end coverage in gametest/jobs_rpc.py: roconfig defaults project through; over-ceiling caps saturate; a negative window floors to 0; a stored-0 prune batch floors to 1; the self-bounding economics params pass through unclamped. It then proves RPC == consensus rather than a parallel formula -- an over-ceiling window override is reported as the clamped 2592000 AND is exactly what a subsequent POST snapshots onto the row. L6 -- AssignOperation::IsValid now uses the file's established type discriminator (GetType () == Job::Type::DEAL) instead of has_deal (); dropped a no-op second params.Set of an already-zero deal-reaction-window in ReactionWindowSnapshotImmuneToRetune. Also corrects the review's §9 evidence-provenance point: the ~0.105s settling-block anchor cited beside the admission-cap ceilings was measured on the superseded jobs-superblocks branch, whose job-type set differs from this one, and no in-tree harness reproduces it here (the largest ordinary sweep test is 200 rows). The comment now states the ceilings are headroom bounds, NOT benched limits, and that max-live-jobs should stay at its conservative 10k default until an ExpireJobs benchmark runs at CAP_MAX_LIVE_JOBS through full block wiring under a stated block-time budget. Validation: DealTests 63/63; full src suite 719/723 with failures being exactly the four known map-artifact tests (CanPlaceBuildingTests.Ok, FinishProspectingTests.Resources, PendingStateUpdaterTests.Mining and .Prospecting); database 171/171; all six jobs gametests green (jobs_rpc, jobs_deals, jobs_reorg, jobs_ad, jobs_bounty, jobs_caps).
| Commit: | 5af4495 | |
|---|---|---|
| Author: | snailbrainx | |
jobs: escrow v1.1 — deal reaction window, private deals at post, param ceilings The deal reaction window (design escrow-v1.1, taurionui docs/escrow-v11-reaction-window-plan.md): a CONFIRM that leaves the counterparty a live answer, or an ARBITER-BOUND dispute, landing strictly within the deal's window of its deadline extends the deadline to now + window — one-shot per set-once flag, never shortening, <= 2W total. The window is a per-row snapshot taken at POST, min(the clamped deal-reaction-window param, the posted duration d), stored in DealPayload.reaction_window (tag 14) like the tax/fee snapshots, so a runtime retune reaches only future posts. Mainnet default 86400 (24h), regtest 30. A no-arbiter dispute never extends (its only successor is the sweep's Option-B 50/50); dispute_time (tag 13) is stamped on every dispute, so an arbiter-bound ghost-split becomes attributable arbiter fault. Private deals become real at the post door: the optional deal term "w" designates a worker at birth (only the designee can ever accept) and w:"" posts invite-only-unassigned (JobData.invite_only — acceptable by NOBODY until ASSIGN names a designee), closing the POST->ASSIGN public window (three-model review F1). w != poster != arbiter; poster == arbiter is now rejected outright (under the window it would arm a late-dispute -> rule-p=0 total seizure); assigning the bound arbiter as worker is rejected (F7). Runtime-param hardening (F3/F5): every liveness-bounding param read routes through one CappedParam clamp helper with compile-time ceilings (max-live-jobs 100000, per-poster 2000, per-linked-entity 1000, bounty-pools-per-target 100, reaction window 30d); the settled-history retention + prune batch now honour the runtime overlay, with the prune-batch floor of 1 applied at the ExpireJobs read (an admin-stored 0 would otherwise CHECK-halt the sweep). New read-only getjobsparams RPC reports the post-clamp effective values through the same helper (F4), and the deal JSON gains reactionwindow / disputetime / inviteonly. The six terminal-action race pins flip to the v1.1 outcomes (a late confirm/dispute now extends; the at-deadline miss and the no-arbiter 50/50 are unchanged), with new coverage for the trigger boundaries, the 2W worst chain, snapshot retune-immunity, W=0 v1-equivalence, late accepts, the private-deal grammar and the param clamps. DealTests 63, src suite green outside the four known map-config artifacts, database 171/171, all six jobs gametests green; concentrated-cohort settle timings at the new ceilings: 1000 linked jobs ~28ms, 100 bounty pools ~3ms.
| Commit: | 772ed31 | |
|---|---|---|
| Author: | snailbrainx | |
jobs: pin the free no-arbiter terminal dispute + settlement-metadata semantics Resolution of the c19a0c9 re-review's H1: the free no-arbiter terminal p=50 dispute is ADOPTED as the intended v1 behaviour (the review's Option B) -- no code change. Rejecting no-arbiter disputes (Option A) would let a worker self-confirm a no-arbiter deal and take p=100 at the sweep with the poster stripped of any answer; the dispute-to-50/50 IS the unconfirmed counterparty's defence against a false one-sided confirm, and it is symmetric (the disputer forfeits half its own side too). The design doc (taurionui) is amended to state this consistently and clients must disclose the split before acceptance and before the dispute action. Tests and comments only -- zero consensus-behaviour change: - H1 regression matrix: no-arbiter counterparty disputes after a worker confirm, after a poster confirm and straight from the accepted state all settle the exact p=50 ghost split (worker 4925 / poster 4850 / treasury 225 on the 5000/5000 deal); the arbiter-bound counterparty-dispute shape with a ghosting arbiter forfeits the fee; a new jobs_deals.py phase drives a genuinely no-arbiter deal end-to-end and asserts the history metadata (mode ghost-split, settledp 50, no feepaid key). - deals_completed / deals_value_completed semantics pinned (comments in account.proto and BumpDealStats, plus a DealStats assertion on the ghost split): the counter includes ghost splits and partial rulings -- any tax-bearing settlement with p>0 -- with the value scaling by the earned share, so Phase-2 reputation must not read it as full completions. - fee_paid semantics pinned (comment in jobs.proto plus a pro-bono-arbiter test): the flag records that the agreed fee SCHEDULE was honoured, true even for a zero-fee arbiter where no coins move; false only on forfeit. - Coverage gaps closed: an OPEN never-accepted deal expires void with none of the settlement keys; jobs_reorg.py now asserts the settle_mode / settled_p / fee_paid history metadata is dropped by the undo and rebuilt bit-identically by an identical re-settle on the redo branch.
| Commit: | c19a0c9 | |
|---|---|---|
| Author: | snailbrainx | |
jobs: review fixes — confirmation finality, param bounds, history settlement metadata Fixes for the final adversarial review of this branch at 0ef401f (one High plus five lower findings; each verified against source before changing code): - H1 (High, merge blocker): a party could confirm and later dispute the same deal, revoking the documented-as-binding confirmation. Worst case a disclosed poster-as-arbiter confirms, disputes and rules p=0 to seize the escrow; without an arbiter the same flaw downgrades the one-confirm p=100 timeout into the disputed 50/50 fallback. DISPUTE now rejects an actor whose own confirmation flag is set (design §6.2: a confirm waives only the confirmer's OWN dispute right); the counterparty's right is unchanged. Pinned by a seven-case regression matrix in the unit tests and by the atomic [confirm, dispute, rule:0] single-move form end-to-end in jobs_deals.py -- TryJobOperations validates each op of a j array against the evolving state, so the array form cannot bypass the guard. - L1: the deal post door evaluated tax + fee on raw int64 runtime params before bounding either operand, so an extreme admin pair (2^62 + 6000 for both) overflows the signed sum past the guard and then narrows to small uint32s whose persisted sum halts settlement on the CHECK precondition. Tax and fee are now each independently bounded to [0, 9999] before the sum; regression-tested at 2^62 + 6000 and INT64_MAX. - M2/L2: settled deals left no record of HOW they settled -- every positive ruling produced an identical history row, which the arbiter-reputation layer cannot live with. DealPayload gains settled_p, settle_mode (both-confirm / ruling / single-confirm / ghost-split / refund) and fee_paid, stamped onto the history snapshot at the settle sites (never on a live row -- pinned by a test) and exposed through getjobshistory. A p=0 ruling keeps the coarse "failed" outcome for history compatibility; clients render deal history neutrally from the metadata instead. - M1: the design doc claimed the neither-acted timeout refund is taxed and that arbiter deals never refund both, while the code refunds both stakes in full and untaxed. Decision: the code behaviour is adopted -- the burned post fee plus zero reputation accrual on a void already close the recycling loop, and a genuine deliverer self-protects by confirming (which routes to the taxed single-confirm p=100 settlement). Now pinned by exact-balance tests for the arbiter and no-arbiter variants; the design doc (taurionui) is amended to match. - L3: the deal-only ASSIGN operation is kept as a supported feature -- private / invite-only deals (the poster designates a worker pre-accept and only the designee can accept). The stale reference to the superseded design in its comment is rewritten and the positive path is now regression-tested (assign, other worker rejected, designee accepts). - Latent harness defect (not in the review): jobs_bounty.py, jobs_caps.py and jobs_reorg.py were committed without the executable bit, so the automake test driver could never run them as committed. Modes fixed. Verified: src and database unit suites green (the only failures are the four pre-existing map-config tests, identical at the 0ef401f baseline), all six jobs gametests green including the reorg sweep over the new history stamps, and a fork full replay (genesis hash exact) with live probes of the H1 rejections, the atomic form and the history metadata, bit-exact against the §6.3 settlement math.
| Commit: | 0ef401f | |
|---|---|---|
| Author: | snailbrainx | |
| Committer: | snailbrainx | |
jobs: on-chain job board — wanted bounties, ad-slot rentals, escrow deals A minimal jobs subsystem on the superblock core: one coin-escrow spine (post/accept/cancel + superblock expiry sweep + settled-jobs history + paged getjobspage/getjobshistory reads + runtime params table) carrying three job types: * wanted — a standing bounty pool on a name, settled per qualifying kill at the combat hook (split across the damage list); * ad — an ad-slot rental on a building with slot exclusivity and future-window booking, settled at the calendar window end; * deal — the generic escrow: reward + worker collateral, an arbiter %-dial dispute settlement, reputation counters, that subsumes every verify-and-pay job as a cosmetic type tag. Runs behind the superblock expiry sweep; deploys via wipe+resync.
| Commit: | 74454ff | |
|---|---|---|
| Author: | snailbrainx | |
jobs: add the assassination contract (designated per-kill hit) A designated-hit counterpart to the open-claim wanted board. The poster names an assassin (assign -> accept), who alone earns the reward: it splits into N equal tranches and each qualifying kill of one of the target's characters -- the assassin on the victim's damage list, while ACCEPTED -- pays one whole slice to the assassin. The Nth kill completes the contract; at the deadline any earned slice is a pass (COMPLETED, unearned slices refund the poster) and zero kills is a plain FAILED (no collateral, so no forfeit-as-poster mark). The assassin must be an enemy faction of the target (no friendly fire), enforced at accept. Rides the existing kill hook: wanted and assassination share a new TargetKillPredicate base (POST grammar, the min-bounty-reward floor, the per-target stacked-listing cap now gated by SettlesOnTargetKill()), and OnTargetKill's return widens from bool to JobOutcome so the tracker records the predicate-supplied outcome (wanted -> DRAINED, assassination -> COMPLETED). Cost is unchanged: one account write per kill, no per-owner fan-out. Job::Type::ASSASSINATION = 11 + an AssassinationPayload proto. Full unit matrix (post/hire/enemy-only accept/per-kill/completion/expiry pass+fail/ open-void/shared cap/stacked-with-wanted) and gametest/jobs_assassination.py.
| Commit: | 5355efc | |
|---|---|---|
| Author: | snailbrainx | |
jobs: wire the prune batch, gate haul relinks and price the board slots The v16 audit round. Two of its findings were real defects in the caps commit, both fixed here; the round also adds the minimum-reward floors and closes the review's test-coverage asks. * History prune (H1): ExpireJobs never passed the configured batch, so production still ran the old unbounded delete -- the bounded SQL was dead code. The batch argument is now non-defaulted, CHECKed positive and wired through; a unit test drives batch + 1 expired rows through the real sweep, and the stress prune cohort asserts the deterministic oldest-first drain (three superblocks at the 10k scale). * Haul destinations (H2): an OPEN haul links its source, so the POST-time per-entity count never saw the destination and open hauls could pile past its cap, relinking unchecked at accept. Accept now re-applies the same admission gate to the entity the row relinks to (JobPredicate::AcceptRelinkId; the shared EntityAtLinkedCap helper is the single cap predicate). A full destination keeps the job OPEN. * Admin params (M2): an entry of size two whose value key was typo'd (e.g. "value") read entry["v"] as null and REMOVED the override -- an emergency freeze failing in the dangerous direction. The parser now requires exactly the members n and v. * Minimum rewards: every post must escrow at least min_job_reward (100 vCHI) and a wanted pool at least min_bounty_reward (1,000 vCHI), both runtime-tunable like the caps ("min-job-reward" / "min-bounty-reward", via JobPredicate::MinReward). Occupying the capped board slots -- above all a target's 25 pool slots -- now locks real value instead of pocket change. * Tests: the four cap defaults are exercised at their REAL roconfig boundaries (10,000 / 200 / 100 / 25); the floors at theirs (99/100, 999/1000); the stress suite gains the DEFAULT max-legal 10k-board scale (the whole global cap settles in 0.405s), a materially scaling mega-battle (up to 42 distinct-owner deaths in one superblock) and scale-proof funding; the god teleport/sethp test helpers chunk under the move-size ceiling like every other bulk phase. * Comments: the phantom "jobscfg"/jobs_config names are corrected to the real "param" command and parameters table, the stress docstring counts all seven cohorts, CountAll's plan is described accurately and PostLinkedIdKeys returns a static reference like PostTermKeys. Deliberately NOT built, decided with Andy: no immutable cap maxima (the params stay free int64s exactly like the soccerverse GSP's), and slot monopolisation stays a documented, watched vector -- the floors price it, and the caps are admin-adjustable live if it ever bites.
| Commit: | 5c45c55 | |
|---|---|---|
| Author: | snailbrainx | |
jobs: admission caps behind runtime-tunable parameters + honest kill timings Bounds every atomic settlement path at the DOOR (the focused-re-review round; caps approved by Andy): - Admission caps enforced in POST validation: max live jobs in total (10,000 -- the hard ceiling on any one expiry sweep), per poster (200), per linked entity (100; haul counts both its buildings), and wanted pools per target (25). Rows already admitted keep their settlement semantics untouched; a deterministic sweep cap stays rejected since it would reopen the mutable-inputs-after-deadline window JobIsDue closes. - The caps read through a new ParamsTable (parameters table), mirroring the soccerverse GSP's runtime parameters exactly: the "param" admin command takes [{"n": name, "v": value}], null removes the override (falling back to the roconfig default -- taurion's twist, since our defaults live in roconfig), 0 freezes the respective admission. The same mechanism carries soccerverse-style fork-* activation flags for post-launch consensus changes. - History pruning is batched (jobs_history_prune_batch, 5,000): oldest-first in deterministic (settled_time, id) order, the remainder drains on later sweeps. - Stress cohorts 5/6 now mine the killing block INSIDE the timed call (the previous shape mined it in setCharactersHP first -- the recorded figures measured the following block); new mega-battle cohort 7 kills many distinct owners (bountied and bounty-free mixed) in ONE superblock against the dormant board and replays it across a reorg; timings re-recorded at 1x/5x/11x, flat at ~0.105s per settling block. - Comment corrections from the same review: per-death probe wording (bountied owners re-probe while pools remain), covering-index rather than O(1), the drained-pool re-probe test comment, the ad-window acceptance-time clamp in the proto prose; PostTermKeys returns static vectors (no per-parse allocation). - New jobs_caps.py drives cap boundary + admin raise + freeze + reset end-to-end; unit tests cover every cap dimension, the param admin command and batched pruning. NOTE: consensus change (caps + parameters table) -- deployments replay from the fresh-state premise (wipe + resync).
| Commit: | f4cd15d | |
|---|---|---|
| Author: | snailbrainx | |
jobs: bound the death path to the deaths + strict POST grammar Full-branch review round (v14). No correctness defect was found; these close the performance-bound and grammar findings: - Bounty attribution no longer scales with the dormant board: one O(1) any-bounty probe per death superblock plus at most one indexed linked-name probe per distinct dead owner (negative results memoised within the superblock -- safe because moves precede hooks, so pools can only shrink during the kill pass). Replaces the constructor preload of every name under bounty, whose cost grew with the (protocol-unbounded) number of dormant bounty targets. - POST moves are exactly as strict as the lifecycle ops: beyond the generic t/d/wd/r/co keys, only the type's own term keys are accepted (PostTermKeys per predicate); an unknown member rejects the move instead of being silently ignored. NOTE: this narrows the consensus move grammar -- deployments replay from the fresh-state premise (wipe + resync). - Rental count negation goes through an explicit signed cast instead of unsigned negation plus implementation-defined conversion. - Ad-window proto prose now states the implemented half-open [start, deadline) semantics; the unpaged full-state jobs export is documented as trusted/bootstrap-only; the expiry-sweep notes pin admission caps as the designated mechanism if a bound is ever needed. - The stress recipe grows the two missing fan-out shapes: a dormant distinct-target bounty board against an unrelated kill (flat at 0.109s against 550 dormant pools, 11x scale) and a pools x distinct killers drain (275 pools x 34 killers in 0.144s), each timed under the one-superblock deadline; parsing tests cover every type's full key set and one unknown-key rejection per predicate family.
| Commit: | b16a53c | |
|---|---|---|
| Author: | snailbrainx | |
jobs: harden the stress evidence — settle inside the timed block, chunk every bulk phase, reorg-replay the sweeps jobs_stress.py: the kill now lands inside the bounded, GSP-synced timed block (target acquired on the teleport superblock, god HP drop submitted unmined, alive before / dead after); assignments and acceptances ride the same sub-ceiling chunks as posts, so JOBS_STRESS_N scales construct the same shapes; the aligned sweep and the retention prune both replay across a reorg (undo + re-settle on the outbuilt branch); recorded 1x/5x/11x runs live in the module docstring, with the 11x board walking the paged reader past its 2000-row page cap. pxtest.py: getJobs clamps pageSize exactly like the server clamps the RPC limit (JobsTable::MAX_PAGE), so over-cap or non-positive requests walk the whole board instead of truncating or looping onto an empty page; jobs_rpc.py covers the clamp edges. jobs_rentals.py: real-path rental grace-gap leg on the transport gating recipe — a legal player transfer redeposits the goods in the overdue gap on an ordinary block, the explicit fulfil there is rejected, and the next sweep settles as a clean return. Comments: the value counter is described as the fee-backed face-value signal (~1% posting-fee burn per credited value) rather than "honest"; ad rent pays at the first sweep after the deadline (plus sale-void) in the AdPredicate overview; kill attribution and the retention prune are superblock-only in the DB docs; the ExpireJobs rationale now cites the recorded in-repo runs and labels the forked-chain evidence external.
| Commit: | 5bb6bd4 | |
|---|---|---|
| Author: | snailbrainx | |
jobs: close the review round — drop getjobs, fix counter widths, pin boundary policies with tests Remove the whole-board getjobs RPC outright: the paged getjobspage is the only per-table jobs read on the public connector, and the full board remains reachable only through the whole-state export like every other table. The four jobs gametests now share one paged getJobs/history helper set in pxtest.py (deduplicating three copies), and the new gametest/jobs_rpc.py covers the surface over the real generated stub: page walk, limit clamp edges, strict-cursor RPC errors, and the method's absence. Correct the BumpJobStats overflow rationale to the actual proto widths (uint32 counts, uint64 value growing by at most MAX_COIN_AMOUNT = 1e11 per settlement) and unify the counters' contract everywhere they are described: consensus-stored, client-read vetting signals that no consensus rule consumes; deterministic wrap at those widths is explicitly accepted over saturating (which would add consensus-visible code for an unreachable boundary). Pin the two decided move-before-sweep policies with real UpdateState boundary tests: rental goods landing in the deadline-to-sweep gap settle COMPLETED from the sweep's view of the handover inventory (while an explicit fulfil in the same gap stays rejected, and goods that never land still default), and a b.send building sale in that gap voids a due accepted ad with a full refund and a clean handover. The rental overview and ad payload prose now state the sweep observation point instead of contradicting it. Add gametest/jobs_stress.py as reproducible in-repo evidence behind the deliberately uncapped settlement sweeps: aligned expiry (200 jobs, one sweep), a standing bounty stack plus a linked bodyguard stack settled by one kill (25 + 25), and a full retention prune (225 rows), all through the real chain path with logged wall times (all at ~1-2ms of block processing); the ExpireJobs rationale now cites it.
| Commit: | 4f2dd2b | |
|---|---|---|
| Author: | snailbrainx | |
jobs: work windows -- the job clock starts at accept A deadlined job now carries two windows (design 3.2, approved 2026-07-16): "d" is the listing window (an OPEN job voids at the sweep if nobody accepts) and "wd" is the work window -- accepting rewrites the deadline to the accept timestamp plus wd, so the worker always gets the full window no matter how late in the listing they commit. One deadline column serves both phases; the expiry sweep is unchanged. The accept-runway guard is deleted (field 27 reserved): it existed to kill the accept-at-the-deadline collateral trap, which the rewrite removes structurally, and it made minimum-duration jobs unacceptable after their posting block (confirmed live). min/max_job_duration become min/max_listing_window (floor raised to 1 day) and min/max_work_window (1 hour .. 30 days) bound the new window. The work window is required for every deadlined type except ad-slots, which rent a CALENDAR window ([post+start, post+d], no wd, deadline untouched by accept) and are exempt from the listing floor since their own window-length check (now min_work_window) subsumes it. A patrol's check-in schedule must fit wd, not d. The board JSON exposes "wd" as a visible term of the deal. Replay note: the historical test posts on the deployment chain lack wd and replay as rejected -- expected pre-launch divergence (design 3.10), verified at the wipe+resync.
| Commit: | 3c9072f | |
|---|---|---|
| Author: | John | |
jobs: fix stale comments
| Commit: | bc01edb | |
|---|---|---|
| Author: | snailbrainx | |
jobs: ad-slot scheduling, slot exclusivity and sale-void An ad may now book a future window: AdPayload gains an absolute start timestamp (post time + the optional relative "start" seconds of the post move; absent = the window opens at post), and the rented window [start, deadline) must itself satisfy the min-duration floor. Accepting an ad is the booking, so the accept is rejected while another ACCEPTED ad on the same (building, slot) overlaps the window (half-open intervals: back-to-back bookings may share an endpoint; the candidate's window is clamped to now, which also ignores competitors already due for this block's expiry sweep). OPEN ads never block each other -- the owner's accept picks the winner among competing offers. Selling a building settles its ads like destroying it does: the new OnLinkedBuildingTransferred hook (called from the move processor's building transfer) voids every ad linked to the building and refunds the advertiser -- the new owner never approved the content and the old owner is no longer the payee. Other building-linked job types are unaffected by a sale. The state JSON exposes the start timestamp on scheduled ads.
| Commit: | 88e62ae | |
|---|---|---|
| Author: | snailbrainx | |
| Committer: | snailbrainx | |
jobs: poster-side forfeit counter (jobs_failed_as_poster) A poster can force a worker forfeit at will -- suicide the protected asset, strand the escort target -- pocketing the bond while only the victim worker's record shows the failure. Mark the poster too: - account proto field 8 jobs_failed_as_poster, bumped in SettleFailureAtHook (the single funnel for every worker-forfeit settlement: delivery/escort/patrol expiry + bodyguard/protect linked-death). One increment on the already-loaded poster handle; no extra lookups. Rental non-return stays a plain failure on the renter (nobody forfeited a bond under that post), void/cancel unchanged. - getaccounts jobstats emits it as "posterfailed". - tests: JobStats helper extended to the 4-tuple so every existing assertion also pins the counter at zero on non-forfeit paths; poster-side asserts on the expiry and linked-death forfeit cases; jobs_protection gametest asserts the mark after the bodyguard forfeit. Also folds in the previously uncommitted HistoryRecordsOutcomes src test.
| Commit: | f44308e | |
|---|---|---|
| Author: | snailbrainx | |
| Committer: | snailbrainx | |
jobs: consensus settled-jobs history (job_history table + getjobshistory RPC) The chain deletes settled jobs from the live board, so until now the only record of WHAT settled and WHY lived off-chain in whatever indexer happened to be watching -- which misses every block it did not witness. The history now lives in consensus state like everything else: the same block processing that DELETEs a live row first writes a job_history row with the TRUE outcome, so any resync rebuilds the record identically and reorgs unwind it cleanly. - database: job_history table (jobs columns + outcome/settled_height/ settled_time), JobOutcome enum (completed / failed / cancelled / void / drained; consensus values), JobHistoryEntry reader, WriteHistory / QueryHistory(fromtime) / PruneHistory on JobsTable. - jobs core: OnExpire and OnLinkedEntityDestroyed now RETURN the outcome (compiler-enforced across every predicate); all five terminal sites write history before deleting (cancel, fulfil-complete, expiry sweep, linked- entity death, pool drain). The expiry sweep also runs the deterministic retention prune (params.jobs_history_retention, 180d; unset = keep forever). - RPC: getjobshistory(fromtime) -- incremental, ordered by settle time; the JSON rows carry the same per-type fields as getjobs (shared serializer) plus outcome/settledheight/settledtime. - tests: 4 db-layer round-trip/prune tests, a src settle-path outcome test, and gametest assertions (deliver -> completed, cancel -> cancelled). db 164/164, src suite green (3 pre-existing overlay failures only), 4/4 jobs gametests.
| Commit: | 5a7c8f5 | |
|---|---|---|
| Author: | snailbrainx | |
jobs: complete the contract-type catalogue (haul, wanted, protection, rentals) Adds every remaining job type from the approved design onto the generic core, each as one predicate object: - haul: poster-supplied delivery -- goods reserved out of the poster's inventory at post, handed to the worker on accept (link swaps source -> destination), dropped as ground loot if the source dies while open. - wanted: the standing open-claim bounty board on account names. Pool of r/N tranches paid per qualifying kill, split across the distinct damage-list owners (attribution runs in the pre-removal pass alongside fame, gated by an in-memory bounty-name set); notice-based cancel via the normal deadline sweep; division dust burns. - protect / destroy / bodyguard: approval-required contracts on a linked entity's fate (shared base; destroy is the mirrored outcome and open to all factions), settled by the entity hook or success-on-expiry. - escort: single-moment fulfil once the protectee is docked alive at the destination. - patrol: K spaced check-ins inside an area, the one Progress-state type. - rental: payer/payee swapped -- accept hands the items lessor -> renter, the renter's fulfil (or the expiry check) returns them and splits the escrow into rent + deposit; non-return defaults everything to the lessor. - ad-slot / toll: poster-paid, success-on-expiry rentals where the entity hook refunds the payer (content-hash committed ads; kill-the-payer voids the toll). Core additions carried by the catalogue: the standing duration class and notice-cancel, per-type accept validation/side effects, poster-submitted fulfils, an OnCancel hook, audience-faction overrides, the character entity hook in the kill processor, per-account completion counters (jobs_completed / jobs_failed / jobs_value_completed, surfaced in the account JSON), jobs invariants in ValidateStateSlow, and delivery reworked to progressive cargo dumps so foundations (and any destination) can be supplied bit-by-bit by convoys or repeat trips while the reward still settles all-or-nothing. Tests: 74 unit tests (src) + 8 (database) green; four gametests (jobs_transport incl. haul + bit-by-bit, jobs_bounty with real combat kills, jobs_protection, jobs_rentals) green.
| Commit: | 7b93a4e | |
|---|---|---|
| Author: | snailbrainx | |
jobs board: generic on-chain contracts core + transport A single generic jobs/contracts subsystem: one table + a t/s/a/c/f move family + a per-type completion-predicate object, with transport (courier-sourced delivery) as the first type. Isolated in a new jobs module; changes to existing files are minimal. - database/jobs.*: jobs table + accessor (worker, nullable seconds deadline, linked_id, linked_name; reserved-coins SUM). - src/jobs.*: JobPredicate interface + TransportPredicate, five generic move ops mirroring DexOperation, coin escrow, per-block expiry + kill hooks. - proto/jobs.proto, roconfig job params, jobs table in schema. - read layer: getjobs RPC + jobs escrow in balance.reserved. - moveprocessor dispatches j after c/b; combat + logic call the hooks. Tests: 29 unit tests (database/jobs_tests.cpp + src/jobs_tests.cpp) + gametest/jobs_transport.py.
| Commit: | 2a43af5 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Introduce the concept of superblocks in game. Superblocks are virtual blocks. We track the "superblock height" as a virtual block height increasing by one roughly every 5 seconds, rather than with the underlying blockchain. Superblocks and the superblock height are used in most aspects of the game that need stable durations, from movement and combat to building construction and service durations. This ensures the game pace is well-defined, and the game balance is correct, independent of the speed of the underlying blockchain. Real block heights are still used for some things that are not related to game tuning, in particular for historical records of DEX trades and for the "last modified" value of regions (which we use to retrieve recently modified regions only in the frontend). There the actual block height makes sense as a raw, underlying identifier.
The documentation is generated from this commit.
| Commit: | 89ffa20 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
WIP: introduce superblocks
The documentation is generated from this commit.
| Commit: | 973c1b5 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
WIP: introduce superblocks
The documentation is generated from this commit.
| Commit: | 3edf5be | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Enable burns on Polygon. Enable burns on Polygon (for minting credits). Burning is not directly supported by the EVM Xaya framework (especially on Polygon), as we do not want the "burnt" coins to remain sitting in the Polygon bridge forever. Instead, "burning" for the purpose of the game is done by sending to another special address. This burn address is also controlled by the Xaya team, but with the understanding that coins received there will be bridged back to Ethereum and burnt there from time to time.
| Commit: | fb35e9e | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Proto and config data for skills. For the upcoming feature of skills, XP and character progression, this adds some basic protocol buffer config data. In particular, we define an enum for skill types, and for each type, a config proto that can be looked up through RoConfig. For now, the config data only contains the skill's name, to be used with game-state JSON as field names. In the future, we might have skill-specific constants, e.g. defining how that skill maps raw XP count to "level".
| Commit: | 2cb3b9b | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Move-processor updates for building config. Update the move processor for delayed update of building configuration: Instead of updating the building data directly for moves, create the corresponding ongoing operation with delay (120 blocks / one hour on mainnet, 10 blocks on regtest).
| Commit: | a36a10b | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Ongoing operation for building config updates. This defines a new ongoing operation for delayed updates to building configuration. When it "expires" (gets processed at its set block height), the owner-configurable data in the associated building is updated from some value set inside the operation. In the future, when a building owner issues a move to update the building configuration, we will schedule such an update rather than change the config immediately. This protects users in the building from frontrunning.
| Commit: | 70bd0d4 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Sub-message for building owner config. Move the owner-configurable values of a building into a new and dedicated sub-message (service fee and DEX trading fee). The new sub-message is also reflected in the building game-state JSON. Instead of having "dexfee" and "servicefee" directly in the building JSON, they are now moved into a "config" object. This will allow us to implement a general mechanism for building updates (and delays for it with an ongoing-operation), independent of the particular config fields updated / supported.
| Commit: | fc720a4 | |
|---|---|---|
| Author: | Daniel Kraft | |
Only use test safe zones on regtest. In regtest mode, only use the testing safe zones (rather than adding them on top of the normal ones). This makes the setup even more predictable, especially if we are doing more changes with safe zones in the future (like disallowing to build buildings in them).
| Commit: | b6c0bc4 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Enable arena support in protocol buffers. Turn on arena support (with option cc_enable_arenas) in all our .proto files, so we can use arenas for more efficient proto usage in the future.
| Commit: | b8a22fb | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Define factions for fitments/vehicles. Add a new field to the ItemData roconfig proto, which can specify the faction for faction-specific fitments and vehicles. For fitments, it is explicitly set in the roconfig data as appropriate. For vehicles, the faction will be deduced at runtime from the name prefix, e.g. "rv st". In the future, these factions will be used to apply certain restrictions (e.g. Jodon fitments can only be placed on Jodon vehicles).
| Commit: | db9c7ee | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Restrict building construction by faction. This associates a faction to some building types, based on the name prefix of the type (i.e. "r vb" is red, while "huesli" has no faction). This is done through RoConfig magic, similar to how bpo or prize items are constructed. Further, if a building has such a faction, it can only be constructed (founded) by a character of the same faction. In other words, a Reubo can no longer found a Jodon vehicle bay, for instance.
| Commit: | 096141f | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Configuration of DEX fees. Each trade on the DEX will cost a certain fee paid by the seller from the Cubits they receive. There will be a 3% base fee that is configured in the ro params and just burned (to protect against spam and wash trading). In addition to that, the owner of each building can configure a building DEX fee in basis points up to 30% max, which is paid to the building owner by the seller of each successful trade inside the building. The building DEX fee is returned as a new field "dexfee" in the building state JSON, and can be set with a new building-update move (similar to setting the service fee): {"b": {"id": 42, "xf": 350}} This would set the dex fee in building 42 to 350 bps, i.e. 3.5%.
| Commit: | c7718ec | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Sort TargetKey same as targets/fighters. Explicitly make the sorting order of TargetKey instances match the order in which some database queries (TargetFinder::ProcessL1Targets and FighterTable::ProcessWithAttacks) return targets, namely first buildings and then characters (and within each group by ID). For now, the sorting order of TargetKey is irrelevant, as it is just used for direct lookups. But in the future, we can then use it to sort targets for processing, matching the direct DB queries (e.g. for parallelisation of some things in combat).
| Commit: | 8690edb | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Age data for buildings. In the building proto data, store the block heights when a building was founded and when it was finished. This is useful for the competition prizes, but may also be useful in general for some other things in the future game.
| Commit: | ab4bcd5 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Age data for buildings. In the building proto data, store the block heights when a building was founded and when it was finished. This is useful for the competition prizes, but may also be useful in general for some other things in the future game.
| Commit: | 992a80a | |
|---|---|---|
| Author: | Daniel Kraft | |
Construct items from bpo one by one. When constructing items (fitments or vehicles) from an original blueprint, produce them one by one as they get finished rather than all at once at the end of construction. We still take away the entire cost immediately (to make sure it is reserved) and give back the bpo at the very end, but the constructed items will become available as they are finished.
| Commit: | a7fac2d | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Spawn characters in starter cities. Spawn new characters inside their starter-city buildings, rather than directly on the map. This is simpler and more straight-forward. They can then immediately exit the building if they want anyway, which leads to the same result as before (placing them on the map somewhere around the starter building). In particular, this prevents cluttering of the spawn area with characters that may not be used at all, e.g. from free-to-play claims.
| Commit: | 503fbdb | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Spawn in starter city after fork. Update the game rules after the "unblock spawns" fork so that new characters will spawn in the starter-city building of their faction, rather than directly on the map. This helps to reduce the amount of idle characters in the starter zones that were created with the f2p "faucet" and never touched; they will now be inside the building, where they are not as annoying.
| Commit: | 5cee824 | |
|---|---|---|
| Author: | Daniel Kraft | |
Track minted balance for each account. Add a new field with the coins minted in the burnsale to the Account proto and state data. This allows to track the vCHI sale progress during the game, independently of what happens with the vCHI inside the beta competition.
| Commit: | a5a84f3 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Implement burnsale schedule logic. Define and implement the schedule and stages of the burnsale (i.e. add the stats to roconfig and implement the logic that computes how many vCHI can be bought for a given amount of burnt CHI). It is not used anywhere yet.
| Commit: | 15fddca | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Add hit-chance modifier as effect. Also add a combat effect that reduces the hit chance, and define a matching AoE weapon fitment that has this effect (the "hitred"). As usual, we define the light variant, and the others will be added in with a future, general data update.
| Commit: | c17f921 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Implement fitment to boost one's hit chance. This defines a new fitment, "lf hitext", which boosts the hit chance for one's own attacks. (The other variants will be added in with a future general fitment update from the data sheets.) Also implements general combat logic to apply a modifier to the hit chance, which for now is just based on that self boost (but in the future will also include negative combat effects).
| Commit: | 092b840 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Implement hit/miss chance for attacks. Support a hit/miss chance for attacks (applying damage, not effects). The chance is based on both a "target" and "weapon" size. Small weapons hit large targets with 100% chance; if the weapon size is larger than the target size, the hit chance is proportional to that. Both weapons and targets support also a special property, which just means "hits always" (unless e.g. modified in the future with a tracking disruptor).
| Commit: | 9dcc320 | |
|---|---|---|
| Author: | Daniel Kraft | |
Define "mentecon" effect and fitment. This defines a new combat effect, namely a flag (codenamed mentecon) that disrupts a fighter's enemy/friendly detection. There is also a new fitment, "vhf mentecon", which has this effect on the unit's current target (not AoE). For now, we just apply the effect, but do not take it into account in the actual combat system. That will be done in the next step.
| Commit: | e3062bb | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Add allyreplenish fitment. This defines a new fitment "lf allyreplenish", which increases the shield regeneration rate of friendlies in an AoE. For this, we define a new combat effect for modifying the shield regeneration rate, and a flag for attacks to mark them as "affects friendlies" (which is for simplicity only supported with plain AoE). Neither the shield regeneration modifier nor the actual friendly attacks are implemented yet in the combat logic.
| Commit: | 41ab04c | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Define mobile refinery. This extends the protocol buffers to support stats for a mobile refinery. A fitment can have those, and then they will be propagated onto a character that equips it (and returned in the character's JSON state). So far, this does not do anything, but actually using it will be the next step. This also defines the "vhf" variant of the mobile refinery as actual fitment, with the real stats. That's the only one that will exist (no lighter ones are possible).
| Commit: | 4f02da3 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Implement range reduction combat effect. This adds a new combat effect, which modifies (e.g. reduces) the range of a targeted fighter. This ability is given by a new fitment, rangered, which reduces ranges with AoE style by 15%. For now, we've defined the light variant of the new fitment. Others will be added later with a general data update.
| Commit: | c3497ed | |
|---|---|---|
| Author: | Daniel Kraft | |
Add armour regeneration fitment. This adds a new fitment, armourregen, which enables an (absolute) armour regeneration rate when equipped. It is the only way in the game to actually get armour regeneration. For now this defines the light variant; others will be added with a general fitment data update before the competition.
| Commit: | 895f2be | |
|---|---|---|
| Author: | Daniel Kraft | |
Support absolute changes in StatModifier. Extend the StatModifier (implementation class and proto) to support also absolute changes in addition to relative (percent) changes. This will be used for armour regeneration, which is an absolute change in the respective fitment.
| Commit: | 2d9823f | |
|---|---|---|
| Author: | Daniel Kraft | |
Update protos for regeneratable armour. Update the protocol buffer definitions and roconfig data to allow also armour to regenerate (i.e. the accumulated mhp field is now a general HP message, as is the regeneration_mhp field). The code is not yet updated accordingly (and hence even breaks), nor is there anything that actually *has* regenerating armour for now.
| Commit: | 16f55f9 | |
|---|---|---|
| Author: | Daniel Kraft | |
Fitment attribute for damage reduction. This adds a new fitment attribute, which defines a modifier that is applied to received damage. This attribute gets passed through to a character's CombatData, but there it is not yet taken into account when actually processing the combat logic. With this, we define the new "dmgred" fitment type (armour hardening) in the "lf" variant for now.
| Commit: | b234def | |
|---|---|---|
| Author: | Daniel Kraft | |
Define gain_hp function for fitments in roconfig. This adds a new proto field for attacks, gain_hp. When set, it means that HP from damage of this attack will be added back to the attacker's own HP set. This will be used by the syphon and AoE syphon fitments (with shield-only damage). The change also defines the "lf" variants of the syphon fitments for testing (the other variants will be added in later with a general update of the fitment data). For now the new field has no effect, but it will be implemented in the combat logic in a follow-up.
| Commit: | 7545ad2 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Update number of ore found on regions. Instead of specifying a base amount of ore found on a prospected region per type, we just specify a minimum and maximum value to be found (for all types of ore) in the roconfig params. Rare materials will be rare through fewer regions and less output of refinement rather than through less ores on any region. (Although the random span of outcomes is now much larger than before with the [X, 2X] system.) This also updates the numbers to match the new units measured in cm^3, namely to much higher values than before (2M to 100M for now and the upcoming competition).
| Commit: | 671d704 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Movement along principal directions. This revamps how the consensus-layer movement logic works in the GSP: Instead of doing path finding in a local range, we expect the waypoints to be set in principal directions from each other (but with arbitrary distance). Then we simply try to step along that path. This implements the idea described in https://github.com/xaya/taurion_gsp/issues/135 and will make movement processing (which has been the main bottleneck in the past two competitions) much faster in the consensus code. (Path-finding still needs to be done, but only client side to come up with the waypoints to send in a move.)
| Commit: | 9c94307 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Define data for artefact finds when prospecting. Add data about the artefact chances when prospecting (which is based itself on what type of ore is found in the region) to the configuration protocol buffers.
| Commit: | ad20851 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Add armour/shield damage factors to config. Allow the configuration of an attack to contain factors for how damage affects armour and shield differently. Two new fitments (laser beam and rail gun) use this, which are specifically effective against shield and armour, respectively. (So far only the light variants of the new fitments are included; we will update the data file completely in a follow-up.) The new fields are not yet taken into account when dealing damage, which will be the next step.
| Commit: | 10c3885 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Define safe zones in roconfig. Add fields to the roconfig proto for defining safe zones (neutral no-combat as well as faction-specific starter areas). They are not yet interpreted in the game in any way.
| Commit: | b28388d | |
|---|---|---|
| Author: | Daniel Kraft | |
Implement fitment restrictions by vehicle size. Allow to define fitments that can only be placed on a vehicle of a given (exact) size. E.g. we do not want light shield boosters on a very heavy vehicle.
| Commit: | e2c71c7 | |
|---|---|---|
| Author: | Daniel Kraft | |
Define size of vehicles. This adds a new field to the vehicle configuration, which defines the "size" of the vehicle (starter, light, medium, heavy or very heavy). It has to be set on each vehicle item type. In a follow-up, we will use this to restrict placing of certain fitments.
| Commit: | f8f0964 | |
|---|---|---|
| Author: | Daniel Kraft | |
Define initial buildings in roconfig. Instead of hardcoding the initial buildings in C++ code, define them in the roconfig proto and place them in code from there.
| Commit: | 8f248f3 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Fitments to boost prospecting and mining. This gives fitments the ability to modify the prospecting blocks and mining rate. It also defines two fitments (plus one test one) that do this, a "pick" and a "scanner" (boosting mining and prospecting by 20%, respectively).
| Commit: | e637eab | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Store prospecting blocks in character data. Instead of defining the number of blocks prospecting needs in the general game params, make it into a property stored for each character and vehicle type. With this, we can have vehicle types that do not support prospecting at all, and we can also have different rates between different types of vehicles. Later on, we can even define fitments that alter the prospecting rate.
| Commit: | 9a58d30 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Define self-destruct fitment. This adds in a definition of a new fitment item with the "self-destruct" ability. When added to a vehicle, it will add this ability to the fighter's combat data. The ability is not yet used in the actual combat code, though.
| Commit: | 88abc85 | |
|---|---|---|
| Author: | Daniel Kraft | |
Auto-generate prize items. Instead of defining the items for prizes in the roconfig, auto-generate them based on the prize data in roconfig (similar to how the blueprint items are defined).
| Commit: | 6bff57b | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Migrate prizes to roconfig. Move the prospecting prize data from Params to roconfig. This will make it easier to maintain the data, provide it also to the frontend if needed, and will allow us to auto-generate the items for them.
| Commit: | 0407108 | |
|---|---|---|
| Author: | Daniel Kraft | |
Move dev address to roconfig. Migrate the developer address for character payments from Params to roconfig. This allows us to get rid of the duplicated definition in the Python tests and instead use it directly from the protocol buffer. Since the address differs on testnet from mainnet, we have to add new support for a testnet-specific merge proto.
| Commit: | 9bce933 | |
|---|---|---|
| Author: | Daniel Kraft | |
Move god-mode flag to roconfig. Use the flag for whether god-mode is enabled to roconfig from Params. It is set to false in the main config and overridden to true on the regtest merge.
| Commit: | d56f1b8 | |
|---|---|---|
| Author: | Daniel Kraft | |
Define spawn areas in roconfig. Define the spawn areas (centre and radius) in roconfig rather than in the Params class.
| Commit: | b4f2b48 | |
|---|---|---|
| Author: | Daniel Kraft | |
Migrate service parameters. Move the service-related parameters (armour repair, blueprint copy and construction cost and duration) from Params to roconfig.
| Commit: | 75c5b95 | |
|---|---|---|
| Author: | Daniel Kraft | |
Migrate prospection expiry. Move the prospection_expiry_blocks from Params to roconfig. Since this value is actually different on regtest, we have to introduce the corresponding file with regtest merge overrides.
| Commit: | d8077df | |
|---|---|---|
| Author: | Daniel Kraft | |
Migrate some block counts. Move over the damage_list_blocks and prospecting_blocks values from Params to the roconfig.
| Commit: | 88ae414 | |
|---|---|---|
| Author: | Daniel Kraft | |
Migrate movement parameters. Migrate the movement parameters (max_waypoint_l1_dist and blocked_step_retries) from Params to roconfig.
| Commit: | 612d2a0 | |
|---|---|---|
| Author: | Daniel Kraft | |
Move character limit to roconfig. Migrate the character limit (per account) from Params to the roconfig proto data.
| Commit: | b8809db | |
|---|---|---|
| Author: | Daniel Kraft | |
Expose roconfig to Python tests. This exposes the roconfig proto to the Python tests, and makes use of the character cost parameter from there (rather than duplicating the value in the Python code). Also required some refactoring to how the protocol buffers are built and used to make it work properly with Python modules.
| Commit: | 589c1b2 | |
|---|---|---|
| Author: | Daniel Kraft | |
Put character cost into roconfig. Define a new field in the roconfig, which will hold basic game parameters. As a first step, we migrate over the character cost from Params to the roconfig proto.
| Commit: | d1056c6 | |
|---|---|---|
| Author: | Daniel Kraft | |
Separate roconfig for regtest. Move the test items and buildings into a separate roconfig instance for testing, which is only added to the main configuration when running on the regtest chain.
| Commit: | 26ce3ed | |
|---|---|---|
| Author: | Daniel Kraft | |
Record start height for ongoings. Store the start height whenever an ongoing operation is created, and return both start_height and end_height with the RPC interface. This is useful to show progress in the frontend.
| Commit: | 773bf05 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Define low-HP boosts in combat data and fitments. This adds a new concept of "low-HP boosts" to the fitments and also the combat data of a character that has such a fitment equiped. We also define a fitment item already for it. For now, it does not have any actual effect; in the future, these boosts will increase damage and range of a character when it is low on armour HP.
| Commit: | 3a94b92 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Apply effects during combat. When processing combat attacks, also apply effects in addition to applying damage (and reset the effects at the end of processing a block). In addition to the general framework, this also defines two new fitment attacks: A retarder, which slows enemies in AoE, and a longretard, which slows enemies in AoE around a selected target.
| Commit: | bebac4f | |
|---|---|---|
| Author: | Daniel Kraft | |
Database storage for combat effects. This introduces a new CombatEffects proto, which will store temporary effects onto a character from combat (e.g. slowing or increased range due to friendlies). The character table has a new column to store those effects, with a quick way to clear all effects (at the end of each turn). The effect data is not yet filled in anywhere or used.
| Commit: | b90fa4f | |
|---|---|---|
| Author: | Daniel Kraft | |
Move StatModifier to separate file. Split out the StatModifier proto into its own .proto file, and also the source code for it out of fitments. It will be used in the future also for stat modifications due to combat effects.
| Commit: | ffd5c8e | |
|---|---|---|
| Author: | Daniel Kraft | |
Restructure damage field in Attack proto. Move the min/max damage fields in the Attack proto into a separate submessage for "damage". This way, we can later on more easily have attacks without damage at all, and with e.g. effects instead.
| Commit: | 7fafd8e | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Allow AoE around target. This restructures the way attack ranges and AoE ranges are defined in the proto configuration. Instead of having a single range and a boolean "is AoE" field, we now have two ranges. This allows for three main types of attacks: range set to N, area unset: Simple attack with range N. range unset, area set to N: AoE around attacker with range N. range set to R, area set to A: Target within range up to R, and then do AoE around that target up to A tiles away. The third option was not possible before, and is now implemented properly in the core code and also used for some fitment items.
| Commit: | ae5b3b0 | |
|---|---|---|
| Author: | Daniel Kraft | |
Link to ongoing construction from building. When a building has an ongoing construction operation, link to the ongoing ID from the building state proto. The ID is also returned in game-state JSON, and "slow validation" verifies those links.
| Commit: | f38c3bc | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Ongoing operation for building construction. Define the ongoing operation for constructing a building (i.e. taking it from foundation to full building).
| Commit: | 3140778 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Rename "construction" to "item construction". Change the name of the ongoing operation type from "construction" to "item construction". There will be a "building construction" ongoing as well, namely when a building is updated from foundation to full building.
| Commit: | 91864f1 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Add construction inventory for foundations. For building foundations, we do not have actual account inventories but just a single (per-building) "construction inventory". Any items dropped in the foundation go towards that, which will later be used to handle upgrading the foundation to the full building.
| Commit: | 6eae9c2 | |
|---|---|---|
| Author: | Daniel Kraft | |
| Committer: | Daniel Kraft | |
Foundation concept in protos. Extend the building protos (configuration and actual game-state data) to include a concept of building foundations. Buildings on the map can now be only foundations, which will be reflected in the game state and returned in JSON. This also defines building roconfig data for how HPs look like in the foundation vs full building, and what the stats (resources and time required) are for building some type of building.
| Commit: | 8da87cc | |
|---|---|---|
| Author: | Daniel Kraft | |
Restructure ItemData proto with oneof. The ItemData proto has a couple of fields specific to item types (e.g. stats for vehicle items or data about refining the material). These are conceptually already a oneof, but were not in the actual code. This change makes them a oneof. This structures the proto more clearly, and also gives an easier-to-see separation between some fields that are general for items and some that define specific types of items.
| Commit: | 2e7fcea | |
|---|---|---|
| Author: | Daniel Kraft | |
Move ItemData proto messages to global scope. Instead of defining the messages for vehicle data or fitment data inside the ItemData proto message, move them to the global scope. This makes the definition easier to read; and the name "VehicleData" (and others) is clear enough even on the global scope.
| Commit: | 52b5ff7 | |
|---|---|---|
| Author: | Daniel Kraft | |
Check for fitment suitability. Implement the logic that checks if a list of fitments is suitable for a given vehicle. This verifies the complexity levels and also the equipment slots. Also adds a new fitment that increases vehicle complexity and thus allows placing "bigger" (or more) fitments.
| Commit: | 091ca77 | |
|---|---|---|
| Author: | Daniel Kraft | |
Define some basic fitments. This defines some of the basic fitments / fitment types (additional attacks, boosts to speed/cargo/max hp/regeneration/attack range/attack damage) and implements the logic to adjust character stats for fitments. It does not yet include code to actually place those fitments or to validate which ones can be placed.
| Commit: | 17f6c40 | |
|---|---|---|
| Author: | Daniel Kraft | |
Define starter vehicles as items. Instead of defining and initialising the starting vehicle stats in a custom Params function, define them as actual item types in the roconfig data. We also created a function to "derive" the character stats from the character's vehicle item, which we use to initialise them now. At the moment, this just copies some proto fields. In the future, this function will also take fitments into account to modify derived stats accordingly.
| Commit: | a6d3133 | |
|---|---|---|
| Author: | Daniel Kraft | |
Define construction service operation. This defines a new service operation, which can be used to construct either items or vehicles from blueprints. (These two types of construction are different building services, construction facility vs vehicle bay.) Items can be constructed from a blueprint original or blueprint copy. In either case, they cost a certain amount of resources (defined by the base item type) per constructed item, and a certain amount of vCHI defined by the base item's complexity. Blueprint copies are used up, originals will just be temporarily taken away (and then given back again). When items are constructed from an original, they are done "in series", i.e. it takes Nx the base number of blocks to construct N items (and the base duration depends on the item complexity). When constructed from blueprint copies, the user needs to have N copies available anyway, but then construction is done "in parallel" so it only takes the base number of blocks to do it. The new service can be requested with this move: {"s": [{"b": 42, "t": "bld", "i": "item bpo", "n": 5}]} The "i" field is passed the blueprint that should be used (not the base item). Based on that, the GSP figures out whether or not this is a construction from original, and whether it is a vehicle or fitment (normal item).
| Commit: | 137946e | |
|---|---|---|
| Author: | Daniel Kraft | |
Ongoing operation for construction. Define the ongoing operation (proto data and handling of it finishing) for construction, of either vehicles or fitments. If construction is done from a blueprint original (rather than copy), the original may drop if the building is destroyed while the operation is in progress (same as with blueprint copy).
| Commit: | 666d81f | |
|---|---|---|
| Author: | Daniel Kraft | |
Building service for blueprint copy. Define the building service for copying blueprints. This takes one original blueprint and produces one or more copies, using up a certain amount of vCHI and taking a certain amount of blocks. The cost and duration are proportional to the blueprint's base item's "complexity" measure. To request this service, the move format is: {"s": [{"b": 42, "t": "cp", "i": "item bpo", "n": 10}]}