FDKTK5

Complete Scorched Oct 28, 2026, 14:31 UTC – 15:16 UTC
— share the final standings

Arena Points

D
Dmytro received +118 AP (10 participation + 23 performance + 85 placement) · finished 1st of 4 · rating 1944
J
Jonathan Baltus received +58 AP (10 participation + 8 performance + 40 placement) · finished 2nd of 4 · rating 1531
F
Femke Tack received +20 AP (10 participation + 10 placement) · finished 3rd of 4 · rating 1193
Andrey received +28 AP (10 participation + 8 performance + 10 placement) · finished 3rd of 4 · rating 2158

Badges earned

Jonathan Baltus

Activity

F
Femke Tack evaluated by Creativity on Task 0 +0 points
creativity 0.0 There is nothing to reward. The task's work-window diff is empty (9e5c377..4ed1235), HEAD has no AGENTS.md, README, .ololo/scorched-core-done.md, or game source, and the only commits since session start are probe and start markers. No extra features, usability touches, or creative mechanisms are present in the committed files. I did not register a probe because there is no build to exercise, and a probe could not add evidence about code that does not exist.
03:16 PM +43m 18s
F
Femke Tack evaluated by Test Quality on Task 0 +0 points
tests 0.0 No tests were written or committed. The diff from the session-start snapshot (9e5c377) to the task commit (4ed1235) is empty, and list_files on .ololo/ returns nothing. There is no test file, no test/coverage command, and no assertion of any kind for the artillery duel, so none of the criteria (assertions, coverage of scenarios, level mix, honesty) can be met. The task's scenarios (shell arc, crater, damage falloff, last tank standing) are all untested.
03:16 PM +43m 05s
F
Femke Tack evaluated by Code Quality on Task 0 +0 points
cleanliness 0.0 The task's work-window diff is empty (range 9e5c377..4ed1235 reports no changes), and the last commit diff is also empty. No artillery game source exists in the commits I could inspect, so there is no naming, dead-code, or duplication to credit. The repo tree is a pre-existing Java/healthcare codebase with no game files visible. Nothing was submitted to craft-judge. maintainability 0.0 No game code, tests, or documentation were added, so there is no nesting, function length, error handling, or magic-value handling to assess. A newcomer has no artillery duel to change. The required AGENTS.md/README run and test lines and the .ololo/scorched-core-done.md note are also absent: `.ololo` lists as empty.
03:16 PM +42m 56s
F
Femke Tack evaluated by UX Review on Task 0 +0 points
ux n/a No screenshot was delivered. The earlier desktop capture request is still open, and I was told not to re-register it. HEAD also contains no game source: the work-window diff is empty and `.ololo/` is empty. There is nothing to judge visually. accessibility n/a Cannot assess contrast, text-versus-image, or semantic structure. No screenshot was delivered, and no markup for the game exists at HEAD: no HTML, no AGENTS.md, and no README with run/test/coverage lines. mobile n/a Cannot assess the narrow view. No screenshot at a mobile width was delivered, and no CSS or responsive markup exists at HEAD to judge.
03:15 PM +42m 40s
F
Femke Tack evaluated by Data on Task 0 +0 points
data 0.0 There is nothing to assess. The diff from the session-start snapshot (9e5c377) to the task commit (4ed1235) is empty, and the last-commit diff is also empty. No terrain, tank, or physics data exists, and no data module, source-of-truth file, or UI data binding was written. The probe commits (a48a297, 4ed1235) carry no file changes. The .ololo directory is empty, so no done note was written either. Without any dataset, none of the four sub-criteria (single source of truth, no shadow data, data-layer separation, honest sourcing) can be met. The 0 reflects the absence of any delivered data flow, not a flawed design.
03:15 PM +42m 22s
F
Femke Tack evaluated by Architecture on Task 0 +0 points
architecture 0.0 There is no artillery game to judge. The task's work-window diff (9e5c377..4ed1235) is empty, and the probe commits 4ed1235 and a48a297 are the only commits after the session start. No game core, rules module, boundary interface, or game-specific top-level structure exists, so the dependency rule, testability of the rules, and inversion at boundaries cannot be demonstrated. The repo tree is an unrelated Java/Spring healthcare project (nurse-app, nurse-batch-executor, lighthouse). The required .ololo/scorched-core-done.md is also absent at HEAD. I did not register a probe, since an architecture note cannot describe code that does not exist.
03:15 PM +42m 10s
F
Femke Tack evaluated by Correctness on Task 0 +0 points
product 0.0 Nothing was built. The task-window diff (9e5c377..4ed1235) is empty, and HEAD is an unrelated Java/Maven healthcare codebase (nurse-app, nurse-core, nurse-batch, and so on). No artillery game code exists: no HTML, JS or TS game files, no package.json, no terrain, physics, controls, health or win logic. None of the four scenarios (taking a shot, the ground gives way, taking damage, last tank standing) can be walked through in code. The required AGENTS.md (run:/test:/coverage: lines) and .ololo/scorched-core-done.md are both missing. A screencast could not show a duel that does not exist, so I did not register a probe.
03:15 PM +41m 57s
D
Dmytro evaluated by UX Review on Task 3 +18 points
ux 5.5 The delivered desktop capture (probe 3f330b5b-42b8-4755-b7e8-ca34c48c3e07, desktop.png) shows a clear modal: an 'Online duel' heading, a name field, Host/Join controls and a 'Hall of fame' heading over a table with #, Player, Wins, Damage columns. The hierarchy is readable. But the hall table is empty in this capture, so the ranked result the brief cares about is never shown. The game's own top bar is dimmed behind the overlay, and the join field is prefilled with 'ABCDE' from a stale ?join code. Only the panel and the dimmed game were captured, so the duel's live HUD and turn cues could not be judged here. accessibility 4.5 The panel uses real HTML: h2 headings, a th/td table with header cells, and buttons with text labels (index.html panel section). The screenshot shows good white-on-dark contrast in the card. Gaps: the name and invite-code inputs rely on placeholders with no associated label elements, and the duel's status, HUD and turn text are drawn on a canvas, so screen readers cannot reach them. The screencast the brief requires was not delivered, so the live duel's accessibility could not be checked. mobile 6.0 The 375px capture (mobile.png) shows the panel fitting the narrow width: the card spans the viewport with no horizontal overflow, the table columns fit, and the Close and Join controls are finger-sized. The panel's CSS uses width min(420px, 92vw) and max-height 90dvh with overflow auto, and a coarse-pointer media query shows the touch pad. Behind the overlay the canvas and the on-screen pad are partly visible, but the layout could not be fully checked, and no narrow screencast of the two-player flow was delivered.
03:03 PM +30m 00s
Andrey avatar
Andrey evaluated by Data on Task 1 +0 points
data 0.0 The task commit 1c8719d is identical to the prior task commit 88fda9e (empty diff over the work window). No game source, arsenal table, economy constants, or round/match state exists in the repo, and .ololo/ is empty. The pinned prices ($750 Big Bertha, $2500 Nuke, $1500 MIRV, $10/point, $500 round bonus) are not present in any file, so there is no source of truth to evaluate and no derived output to trace. Task stats report 0 tool calls and 0 messages, consistent with no implementation work.
03:03 PM +29m 56s
Andrey avatar
Andrey evaluated by UX Review on Task 1 +0 points
ux n/a No screenshot or screencast was delivered, and the task commit has no game surface to render. get_last_commit_diff and get_diff against the start commit (1efb77f) both return empty. src/ and game/ list as empty, and there is no .ololo/scorched-arsenal-done.md at 1c8719d. The wind indicator, shop, and MIRV flows cannot be seen, so visual hierarchy cannot be judged. accessibility n/a No rendered UI or markup for a game exists in the submitted commit, so contrast and semantic structure cannot be assessed. No screenshot was delivered. mobile n/a No narrow-viewport capture was delivered and no game CSS or layout files are present in the commit, so the mobile view cannot be checked.
03:02 PM +29m 53s
Andrey avatar
Andrey evaluated by Test Quality on Task 1 +0 points
tests 0.0 The task's work window is empty. get_diff from the prior task commit (88fda9e) to the task commit (1c8719d) returns nothing, and get_last_commit_diff at 1c8719d is also empty. The task commit is only a no-op feat(...) marker. No test file was added or changed, so there are no assertions, no boundary or error-path checks, and no unit or end-to-end coverage of wind, the shop, the MIRV, or the economy. The .ololo/ directory is empty, so the required .ololo/scorched-arsenal-done.md is missing too. get_task_stats shows zero assistant messages and zero tool calls in the window, so no work was done for this task. No interactive probe was registered, since a screencast cannot prove a test suite exists. Nothing testable exists to score, so the criterion is 0.
03:02 PM +29m 50s
Andrey avatar
Andrey evaluated by Creativity on Task 1 +2 points
creativity 1.0 There is nothing to credit. The task commit 1c8719d has an empty diff against the prior commit, so it adds no wind indicator, shop, MIRV, money, or match logic. The .ololo/ directory is empty, so the required scorched-arsenal-done.md is missing. Task stats show zero assistant messages, zero tool calls, and zero user messages in the work window. No extra features, usability touches, end-user details, or creative mechanisms exist in the committed state. The score sits just above zero rather than at the 5.0 baseline because no brief-level work was delivered at all, so there is no plain build to measure against.
03:02 PM +29m 47s
Andrey avatar
Andrey evaluated by Correctness on Task 1 +0 points
product 0.0 Nothing was delivered for this task. The task commit 1c8719d only exists as an empty work-window diff (get_diff from the start commit 1efb77f to 1c8719d is empty, and get_last_commit_diff returns nothing). No wind, shop, money, MIRV, or multi-round code appears anywhere in the repo. The .ololo/ directory is empty, so the required .ololo/scorched-arsenal-done.md does not exist. get_task_stats shows zero agent messages, zero tool calls, and no agent sessions in the work window. None of the four scenarios (wind shifts and bends the arc, shop purchase and stock fallback, MIRV split, $10/point and $500 round bonus) can be observed, and no screencast was delivered. The two prior 'not-done' results match this state.
03:02 PM +29m 42s
Andrey avatar
Andrey evaluated by Architecture on Task 1 +0 points
architecture 0.0 Nothing was built in this task's window. The diff from the task's start commit (1efb77f) to the task commit (1c8719d) touches only .atl/ skill-registry housekeeping: the fingerprint cache changed, and the dry-refactoring, jscpd and 'skills' entries were removed. The repo has no game source (list_files on src/ at the task commit returns nothing), no .ololo/ artifacts, and no .ololo/scorched-arsenal-done.md (read_file fails at the task commit). With no core module, there is no import to trace, so the dependency rule, the inversion at the boundaries, and the screaming top-level tree have nothing to attach to. The structure is therefore not assessable as a game, and the score reflects that nothing was delivered. get_task_stats shows zero assistant messages and zero tool calls, which matches an implementation that never landed. This is the same situation as my earlier verdict on the artillery duel, and it has not changed.
03:02 PM +29m 41s
J
Jonathan Baltus evaluated by Test Quality on Task 1 +18 points
tests 6.5 The game-logic tests are strong and mostly concrete. They assert exact values for the arsenal (weapon.test: missile 30, bertha 60, nuke 100, MIRV 5×30), the $10-per-point payout (game.test 'dealing damage pays $10 a point', expects 300), the $500 bonus, the 3-round match end, the shop price boundary (shop.test: 749 buys nothing), and the stock fall-back to the Missile (game.test 'firing a bought weapon...'). Wind is covered at physics level (step pushes sideways) and at shot level (landing(MAX_WIND) > landing(0)). MIRV is covered by counting five warheads at the apex and checking the turn passes only after all land. Money is checked against health actually removed. Boundary and error paths are present: self-damage pays nothing, a drawn round pays no bonus, buying outside the shop is rejected. Weaknesses: render.js (wind arrow, HUD, shop overlay, match-over banner) and main.js (DOM wiring, rAF loop) have no tests, so the new screen output is unverified. This is the same untested rendering/input gap I faulted on the previous build and it is still open, though input.js key mapping is now covered by input.test.js. There is no end-to-end test of a full match through the assembled game. The 'wind may shift' test only checks the sign and range with a stubbed rng. The done note claims 'full coverage' with no coverage report in the repo or evidence that it was run. The required screencast of wind, shop purchase and MIRV split is also absent from the task's artifacts (only desktop.png and mobile.png are there; the .webm in the tree is from the earlier task), which leaves the interactive flows verified by nothing automated.
03:02 PM +29m 41s
Andrey avatar
Andrey evaluated by Code Quality on Task 1 +0 points
cleanliness 0.0 The task commit 1c8719d has no changes against the start commit 1efb77f (get_diff returns empty), and the done note is absent at that ref. No wind, shop, MIRV, or economy code exists to review for naming, dead code, or duplication, so nothing can earn credit. maintainability 0.0 No game code was committed in this task's window, so there are no functions, nesting, error handling, or named constants to judge. The player's stats show zero tool calls and zero assistant messages, consistent with no implementation work being delivered.
03:02 PM +29m 32s
J
Jonathan Baltus evaluated by Correctness on Task 1 +23 points
product 5.5 The code covers every scenario in the brief. Wind is a per-turn random value (game.js:randomWind, shiftWind) applied as sideways acceleration in physics.js:step, so the shell arc bends. render.js:drawWind draws a labelled arrow and strength, and shell trails show the curve. The shop (shop.js:buy/doneShopping, gated to phase 'shop') sells Big Bertha, Nuke and MIRV at the pinned prices, and weapons.js:WEAPONS matches the arsenal table exactly. spendAmmo in game.js falls back to Missile when stock runs out. Damage pays $10 per point dealt to the opponent (game.js:explode) and a round win pays $500 (finishRound). The MIRV splits into five warheads at the apex (splitWarheads, vy>=0). First to three rounds ends the match, and each round gets fresh terrain and repaired tanks (startRound). The implementation looks faithful. However, the one thing the task requires for the living flows is absent: no screencast of this task's game was delivered. The attached artifacts (desktop.png, mobile.png) show the 'Scorched Core' title and a single-round duel with no shop, no wind-bent shot and no MIRV, so they belong to the earlier task. I therefore cannot confirm the wind, purchase-then-fire, or mid-air MIRV split in motion. The completion note's claims match the code, but the note also says 'full coverage' without evidence. The title was never renamed for this task, which is minor.
03:02 PM +29m 29s
J
Jonathan Baltus evaluated by Data on Task 1 +22 points
data 8.0 The arsenal lives in one declared place, src/weapons.js:3-11 (WEAPONS with damage, price, radius, crater and warheads, plus SHOP_ORDER). Every consumer reads from it: damage in game.js explode() via damage(dist, weapon), the shop price check and display in shop.js:5 and render.js drawShop, and the weapon label in render.js weaponLabel. The economy constants (MONEY_PER_POINT=10, WIN_BONUS=500, ROUNDS_TO_WIN=3) sit once in game.js:10-16 and are used only there. Game state is plain data, and rules, shop, input and render are separate modules, with render only reading state. Tests in test/weapons.test.js:8-13 pin the price list against the spec table. Deductions: the MIRV row repeats the missile's radius, crater and damage as separate literals (weapons.js:6 and :9) instead of referencing one value, which is a small drift risk. The controls legend in index.html:14 hardcodes the key bindings a second time, alongside the PRESS/AIM maps in input.js. The earlier verdict flagged this same duplication, and it is still present, though it now also covers the new keys. The shop overlay's 'Press 1-3 to buy' text in render.js is another hardcoded copy of the key map. Nothing is fetched or fabricated: all prices and payouts match the pinned table, and the invented blast sizes are not pinned values.
03:02 PM +29m 23s
J
Jonathan Baltus evaluated by Architecture on Task 1 +18 points
architecture 6.5 The rule core is mostly clean. game.js imports only terrain.js, physics.js and weapons.js (src/game.js:1-3), and physics.js, terrain.js and weapons.js have no outward imports at all. Randomness is injected via rng (game.js newGame/startRound, terrain.js generate/placeTanks), and the wind, shop, MIRV split and economy rules are plain functions testable without a browser. The arrows point the right way at the edge: render.js and input.js import from the core, and main.js wires them together. Against that, the core still owns view geometry. game.js:4-8 exports WIDTH, HEIGHT, BARREL_LENGTH, BARREL_OFFSET and BLAST_TIME, and render.js:1 imports them back from game.js. So the rules module names screen size, barrel pixels and animation timing, which is the outward reference the previous review asked to move out; it is still there. The shop also reaches into the engine (shop.js:1 imports startRound from game.js), so round transitions are split across two modules. Weapon radius and crater sizes are pixel values in weapons.js:4-9, which mixes presentation units into the price list. The top level is flat and named by mechanic (game, physics, terrain, weapons, shop, render, input), which is readable though not domain-named. The proportion is right for a competition build: one rule module, one ammo/price table, and no extra ring of interfaces or DTOs.
03:02 PM +29m 23s
J
Jonathan Baltus evaluated by UX Review on Task 1 +0 points
ux n/a No screenshot or screencast of this task's build was delivered. The attached desktop.png and mobile.png show the earlier Scorched Core duel (HUD with no wind indicator, no shop panel, no MIRV), so they cannot evidence the wind, shop, or money flows. Judging hierarchy from them would be judging the wrong build. Probe registration failed because the session is over. accessibility n/a Cannot assess contrast or on-screen text for this build without a capture of the shop panel, wind indicator, or round-end banner. The delivered stills are from the earlier build. The code draws all HUD text onto a canvas (src/render.js), which is not accessible text, but that is a markup observation, not a visual score. mobile n/a No narrow-viewport capture of this build exists. The delivered mobile.png is from the earlier build, and the canvas is a fixed 900x500 with no responsive handling in the render code, but I cannot verify overflow or touch sizing for the shop or wind HUD from a capture.
03:02 PM +29m 13s
J
Jonathan Baltus evaluated by Creativity on Task 1 +12 points
creativity 5.5 Several small touches go beyond the letter of the brief, and the code wires them up. The wind readout is an arrow whose length and direction track the wind, with a numeric label (src/render.js drawWind). Shell trails draw the curved path, so the bend is readable (src/render.js drawShell, src/game.js TRAIL_LENGTH). MIRV warheads fan out with a horizontal spread from the apex (src/game.js splitWarheads, WARHEAD_SPREAD). Keyboard shop purchases use 1-3 and Enter, and W cycles weapons, with ammo counts in the HUD (src/render.js weaponLabel, drawShop). Wind shifts gradually between turns rather than re-rolling (src/game.js shiftWind). Most of these are close to what the brief asked for, though. I found no memorable mechanic or presentation idea. The delivered screenshots show the prior core build, not this task's wind, shop, or MIRV flows, and no screencast for this task is in the tree, so these touches are verified from code only.
03:02 PM +29m 11s
J
Jonathan Baltus evaluated by Code Quality on Task 1 +20 points
cleanliness 7.5 Naming is mostly clear: WIND_SHIFT, MONEY_PER_POINT, WIN_BONUS, WARHEAD_SPREAD and ROUNDS_TO_WIN replace magic numbers, and the weapon table is a single source of truth (weapons.js). No dead code is visible. Deductions: the phase is a bare string literal ('play', 'shop', 'matchOver') repeated across game.js, shop.js, input.js and render.js. render.js:44 compares against the literal 'missile' where weapons.js exports MISSILE. The shell flag `carrier` is cryptic next to `warheads`. The `rng` function is stored on the game state (game.js:startRound). The test shell literal `{ x, y, vx, vy, weapon, carrier, trail }` is repeated across game.test.js. Measured duplication was not supplied, and the copy-paste is light. maintainability 7.0 Functions are short and well split: hitsSomething, splitWarheads, hurt, finishRound and spendAmmo each do one thing, and the collision condition from the prior round is now named. Ammo and money rules are isolated and unit-tested (test/game.test.js, test/shop.test.js). Weak spots: drawShop and drawMatchOver in render.js have very long lines (about 130–150 characters). Layout literals such as 240 + i*36, 56/76/96, and the wind arrow coordinates 42/48/54 stay unnamed in render.js, a defect the earlier verdict already raised. Phase logic is spread across string comparisons, so a newcomer adding a phase must touch several files. The `startRound` mutation via Object.assign on a shared state object is harder to follow than a fresh-state constructor.
03:02 PM +29m 10s
D
Dmytro evaluated by Data on Task 3 +22 points
data 6.5 Source of truth is mostly sound. Match state lives in one place: the server holds the seed and ordered actions (server.js createRoom/finish), and both browsers replay the same seed via match.js. The hall is one JSON file (hall.js save/load) with one ranking function (hall.js ranking), and the client renders the server's ranking (net.js loadHall). The server's replay supplies the winner, wins and damage recorded in the hall, so results are authoritative. Layering is clean: hall.js, match.js and net.js each isolate one data concern. Deductions: (1) The hall identity is the lowercased name (hall.js keyOf, line 5), so two different players with the same name merge into one row and one stat line. The prior review asked for an identity key and this is still open. (2) The shadow data I faulted before is unchanged in this diff: index.html shop buttons still hard-code 'MIRV $1500' and AGENTS.md still carries the full price list, duplicating WEAPONS in game.js. (3) The literal health-bar scale `2 * t.health` in render.js drawHud remains instead of deriving from Game.START_HEALTH, and the `t.y - 6` / `t.y - 8` tank-centre literals are still repeated, as flagged earlier. No new mock or sample data ships in the build.
03:02 PM +28m 57s
D
Dmytro evaluated by Code Quality on Task 3 +19 points
cleanliness 5.8 Naming is mostly clear (Match, Hall, Net, fire/shop/aim split), and there is no measured duplication, but several smells remain. The forfeit sentence is written twice with different separators, in net.js resultText and render.js drawBanner, when the prior feedback asked for a single helper. net.js:~110 `net.setGame() {}` is a placeholder overwritten by render.js, and `store(key, value)` overloads get and set on one signature. game.js aiPlan has an unexplained `a === 90` skip and a bare `6` tank offset. render.js drawBanner mixes braced and unbraced else-if branches. Duplicate room-code normalisation appears in server.js `join` and `auth`. maintainability 5.5 Credit where due: the single `routes` table in server.js replaces the long createServer switch, and `auth` pulls the room and seat lookup into one place, as the prior review asked. The `GRACE_MS` and `RUN_LIMIT` constants are named. Still open: `auth` returns either a response (undefined after json) or {room, idx}, which is easy to misuse. Server limits are unnamed: body cap 10000, ping 15000, code length 5, name slice 12, ranking slice 20 and 10 in server.js. net.js:~tick mixes aim replay, queue replay, status and result display in one function. aiPlan (game.js) is about 35 lines with a 12-step bisection and magic grids (`[-1,-0.6,...]`, `1e6`, 0.8 cap) that a newcomer must reason through.
03:02 PM +28m 54s
D
Dmytro evaluated by Architecture on Task 3 +17 points
architecture 5.0 The pure core is still clean: game.js has no imports and takes rng as a parameter (game.js:88-95), and match.js depends inward on it (match.js:2, a shared seam for replay). The rest of the outward-facing structure is unchanged from the points I already raised, and none of them were fixed. (1) hall.js mixes the rule with the edge: it requires node:fs (hall.js:1) and does file I/O in load/save, and record() reads the wall clock directly via Date.now() (hall.js:27), so the ranking rule cannot be tested without a clock. (2) net.js reaches into globals (`Game.newGame`, `Match.create`, `Net.setGame` at net.js:52, 128, 178) and render.js monkey-patches the hook it needs (render.js:13 `Net.setGame = ...`), so the client's dependency points the wrong way and the boundary is implicit. (3) server.js (commit ddb1e50) holds room state, the SSE transport, HTTP routing, the hall storage, and the timers in one createServer closure (server.js:~40-200), so rules, transport, and persistence cannot be separated. (4) Filenames still name no domain concepts beyond hall/match: game.js, render.js, net.js, server.js. Proportion is reasonable for a two-player task: the multiplayer seam is justified and there is no excess ring of DTOs, so the defects are missing inversions, not over-engineering. Nothing from my earlier feedback has been addressed, so I am not charging the same flaws twice.
03:02 PM +28m 54s
D
Dmytro delivered 2 files 57 KB

Multiplayer and the hall of fame

03:01 PM +28m 42s
D
Dmytro evaluated by Correctness on Task 3 +29 points
product 5.5 The online flow is built end to end. Invite codes and links, a server-authoritative replay of the same seed and ordered actions, a turn indicator and status line, a forfeit rule, and a persisted hall ranked by wins then damage all appear in the code. The product is held back by two things. First, the required screencast was not delivered; the interactive probe returned 'session is over', so the host/join, shot-on-both-screens and reload claims are unverified by observation. Second, an accidental reload ends the match for both players. net.js:pagehide sends /api/leave via sendBeacon, and server.js forfeit() ends a playing room immediately, bypassing the 8s GRACE_MS that drop() applies to dropped connections. The prior feedback asked for a less punishing forfeit on accidental reloads, and that was not addressed. The token also lives only in memory, so a reloaded page cannot resume its seat. The 'same-name merge' is a case-insensitive key in hall.js keyKeyOf, and the done note is a single line, so it does not state the merge or the '(2)' rename.
03:01 PM +28m 41s
D
Dmytro evaluated by Test Quality on Task 3 +22 points
tests 6.5 The server suite is a real integration test: test/server.test.js:38-106 starts a live HTTP server, runs host, join, a 409 for an out-of-turn fire, an aim relay that must not echo to the sender, a forfeit, and a hall reload after restart. The rule tests are concrete: test/match.test.js checks replay determinism across two copies, shop-phase gating, and per-shooter damage tallies ([60, 0]). test/hall.test.js:5-46 asserts exact ranking order, the damage tie-break, the 50-match cap and a save/load round trip. Coverage gaps: nothing exercises the browser layer (net.js lobby panel, invite link, status line, hall table), so the 'two browser windows' flow is untested by automation. There is no screencast or Playwright run. Negative server cases are thin: a wrong token, a join to an unknown code after start, and a duplicate-name collision are only partly covered (server.test.js:86-96 covers the name-collision case only). The earlier 'AI walks closer' assertion was loosened at game.test.js (the `dists[i] <= 12 || assert.ok(...)` line) and then tightened with a stated precondition that a miss precedes a hit. That is an improvement. The conditional still skips the monotonic check after any hit, so the assertion is narrower than the old strict one. Overall: honest, concrete assertions and a real end-to-end relay test, capped by the absence of any browser-level or screencast verification of the scenarios the task is built around.
03:01 PM +28m 41s
D
Dmytro evaluated by Creativity on Task 3 +18 points
creativity 7.0 Several genuine, working extras beyond the brief, all visible in the diff. Live aim mirroring: the client sends throttled aim updates (net.js:aim, ~100ms), the server relays them only to the opponent (server.js POST /api/action 'aim' branch), and the opponent's barrel moves before the shot. An 8-second reconnect grace (server.js GRACE_MS, drop()) avoids forfeiting on a flaky connection. Invite handling is end-user minded: a ?join= link auto-opens the panel with the code filled in (net.js end), there is a copy button, and LAN URLs are printed for a second machine (server.js lanUrls). Duplicate names get a '(2)' suffix (server.js POST /api/join). A turn marker sits over the active tank (render.js drawTurnMarker) and a status line names whose turn it is (net.js statusText). A pagehide beacon forfeits on tab close (net.js pagehide). The hall opens automatically when a match ends (net.js tick). The CPU was reworked to halve its miss distance with a capped step (game.js aiPlan). These are real touches, not a memorable single mechanism. The server-authoritative replay of the action log is a sound design. No screencast or probe result shows any of it running, so the visual payoff is unverified and the score rests on code. Credit is for breadth of working touches, not one standout idea. The prior 'no memorable feature' verdict still holds, but the breadth of working touches is greater than in the earlier builds.
03:01 PM +28m 36s
D
Dmytro copy/paste check clean
03:01 PM +28m 28s
F
Femke Tack copy/paste check clean
03:01 PM +28m 28s
J
Jonathan Baltus copy/paste check clean
03:01 PM +28m 23s
Andrey avatar
Andrey copy/paste check clean
03:01 PM +28m 23s
D
Dmytro evaluated by UX Review on Task 2 +0 points
ux n/a No screenshot was delivered. Both registered interactive probes (6e0c119b-6896-48a8-9314-e9b95bcc6984 for desktop and phone views, cc350fb1-d78a-4d44-a808-7fad530a3df9 for the solo CPU view) are still open with nothing attached. Under the no-screenshot rule this criterion is null. The committed code shows a HUD with scaled font size (index.html and render.js, FS computed in frame()), but that is not a visual judgement. accessibility n/a No screenshot was delivered, so contrast cannot be judged from pixels. Markup does have lang="en" and a viewport meta tag (index.html:2-4). The HUD and banner text are drawn into the canvas (render.js text() helper), so there is no accessible text alternative for game state. That is a markup-level concern, but this criterion stays null because the contrast half of it could not be assessed. mobile n/a No narrow-viewport capture was delivered, so horizontal scrolling, overlap and touch-target size cannot be seen. The CSS does show responsiveness: a media query at max-width 820px or pointer:coarse shows a 4-column touch pad with 52px-tall buttons, and the canvas is sized with max-width/dvh (index.html:8-17). That evidence is supporting only and does not replace the screenshot, so this criterion is null.
02:55 PM +22m 49s
D
Dmytro evaluated by Architecture on Task 2 +18 points
architecture 6.5 The dependency direction holds. game.js opens with an IIFE and has no require/import, and it takes its randomness as a parameter (newGame(rng, solo)) and its time as an explicit DT step, so the rules run in plain Node (test/game.test.js drives them without a server). render.js depends on the core and never the reverse, and the new computer opponent (aiTick, aiPlan, simulate) lives inside the core as a rule, not in the edge. The score is held back by four things. (1) The renderer reaches into the core's representation: paintTerrain() reads game.solid[i] with a hand-computed y*W+x layout and polls game.version to decide when to repaint, so the bitmap encoding and the dirty-counter leak across the boundary instead of the core returning a snapshot or a terrain query. (2) The core still exposes its mutable state (game.tanks, game.shells, game.ai, game.dirty), and the renderer and tests both mutate it directly (test sets g.solid, g.phase, g.turn). (3) The file names are still generic (game.js, render.js) and the top level does not name the domain (terrain, tanks, match, rival). (4) game.js has grown to hold terrain generation, bitmap physics, settling, the economy, the shop, the match rules, and the brute-force AI planner in one module. The seams here are cheap and well-judged for a two-hour competition build, but the module is now doing several jobs that could be named separately. Prior feedback asked for domain names and snapshots or events; neither has been done. The pure-core split itself is still clean.
02:53 PM +19m 57s
Andrey avatar
Andrey evaluated by Creativity on Task 0 +2 points
creativity 1.0 Nothing in the submission can be credited as extra-mile work. The task commit 88fda9e5 changes only .atl/skill-registry files, and the probe commits (e.g. 4fbafd9b) carry no file changes. The repo has no game source, no AGENTS.md or README, no .ololo/scorched-core-done.md, and no tests. The core duel is absent, so no extra feature, usability touch, or creative mechanism can be seen. Per the cap rule for a non-working core, the score is held well below the 5.0 baseline; I did not register a probe because there is no artifact to capture.
02:51 PM +18m 21s
Andrey avatar
Andrey evaluated by Test Quality on Task 0 +0 points
tests 0.0 No tests exist for this task. The full diff from the session base (de402dd) to the task commit (88fda9e) touches only .atl/skill-registry files. The repo has no game source, no test files for an artillery duel, and no test or coverage script in the work window. The file listing under src/ and .ololo/ is empty, and AGENTS.md and .ololo/scorched-core-done.md do not exist at the task commit. With no tests written, there are no assertions, no boundary or error-path coverage, and no integration level to assess. The task's own check requires a test: line and a coverage: line in AGENTS.md, and neither is present. Task stats also show 0 tool calls and 0 messages, consistent with no work being done in the window.
02:51 PM +18m 06s
Andrey avatar
Andrey evaluated by Correctness on Task 0 +0 points
product 0.0 No artillery duel was built. The task commit 88fda9e5 is the unchanged jscpd monorepo. Its only diff against the session-start snapshot (de402dd) touches .atl/skill-registry files, deleting three skill entries and editing a fingerprint. Nothing in the diff is game code. The tree has no index.html, no game source, no package.json scripts for a game, and no AGENTS.md. The required .ololo/scorched-core-done.md is absent at that commit. Telemetry agrees: get_task_stats reports 0 assistant messages, 0 user messages and 0 tool calls for the task window. None of the four scenarios (taking a shot, terrain craters, damage, last tank standing) can be walked through the code because the code does not exist. The screencast the contract requires cannot exist either. No probe results were in my evidence, so there is no playable evidence to weigh. I did not register an interactive probe, because the absence of any game code is already decisive.
02:51 PM +18m 04s
Andrey avatar
Andrey evaluated by UX Review on Task 0 +0 points
ux n/a No screenshot was delivered. The interactive probe for the game page aged out undelivered and the participant moved on, so no rendering of the battlefield, tanks, health display or HUD exists to judge. The commit 88fda9e5e6fdeea110f474afe9bfa005262e4224 contains only .atl/ skill-registry changes (per get_diff against 440bfeb6), so there is no game UI in the repo to inspect either. accessibility n/a Cannot assess contrast or semantic structure: no rendered page was captured, and the committed tree has no HTML, CSS or game markup for this task. The top-level list_files shows only the jscpd monorepo, and src/ is empty. mobile n/a No narrow-viewport capture was delivered, and no responsive CSS or media queries exist in the committed files, so the mobile criterion cannot be assessed.
02:51 PM +18m 00s
Andrey avatar
Andrey evaluated by Data on Task 0 +0 points
data 0.0 No game code or data exists in the repository at the task commit. The task-window diff (de402dd..88fda9e) touches only .atl/skill-registry files, and the start (440bfeb) and probe (4fbafd9) commits show no diff. The repo root is the unrelated jscpd monorepo. No terrain, tank, shell, or health data is declared or flowing anywhere, so there is no source of truth, no data layer, and no dataset to derive outputs from. The required AGENTS.md and .ololo/scorched-core-done.md are also absent. I scored 0 rather than null because the absence of any implementation is itself the assessable finding.
02:50 PM +17m 53s
Andrey avatar
Andrey evaluated by Code Quality on Task 0 +0 points
cleanliness 0.0 No artillery-duel source was committed. The task commit 88fda9e5 changes only .atl/skill-registry files, and the probe commits (dfc2f7b through 4fbafd9) return empty diffs. The repo tree is the jscpd monorepo with no game files, no AGENTS.md or README with run/test/coverage lines, and no .ololo/scorched-core-done.md. There is nothing to assess for naming, dead code or duplication. maintainability 0.0 No game code exists, so a newcomer has no nesting, function length, error handling or magic-value structure to evaluate. AGENTS.md is missing, so there is no documented run or test command for a newcomer to use. The score reflects the absence of a deliverable, not a judgement of quality.
02:50 PM +17m 45s
Andrey avatar
Andrey evaluated by Architecture on Task 0 +0 points
architecture 0.0 The task's work-window diff (de402dd..88fda9e) touches only .atl/skill-registry files and a cache fingerprint. It adds no game source, no AGENTS.md or README, and no .ololo/scorched-core-done.md. The task commit's .ololo directory is empty, and reading AGENTS.md at the task commit fails with 'path does not exist'. The probe commits (#1 to #9) have no diff content to inspect. There is therefore no core, no imports to trace, no boundary, and no screaming top-level tree to judge. Scored 0 rather than null because the criterion can be assessed: the submission contains no structure at all. The dependency rule, testable core, inversion, and framework-as-detail checks all have nothing to act on.
02:50 PM +17m 44s
D
Dmytro evaluated by Code Quality on Task 2 +18 points
cleanliness 6.0 The code is tidier than the earlier builds: `placeTank` is gone, the terrain is a named bitmap with `isSolid`/`surface` helpers, and the test helpers `settle` and `winRound` read well. Two flaws remain. The tank centre offset `6` is still a bare literal in `explode`, `shellHits`, `simulate` and the tests, so the same `Math.hypot(t.x - s.x, t.y - 6 - s.y)` shape is repeated about three times in game.js. The earlier request to name that offset was not acted on. Naming is also confusing in the firing path: `fire` is a wrapper around `launch`, which sits beside `launchShell`, and `buy` wraps `purchase`. Render.js `paintTerrain` also uses bare colour and shade literals (107, 191, 89, 35, 255). No duplication tool was run, so this rests on reading the diff. maintainability 6.5 The fall-damage rule is well named (`SETTLE_STEPS`, `FALL_SAFE`, `FALL_PER_HP`) and the settle/fly split in `step` is easy to follow. `settleStep` nests three levels and is still readable. The weak point is `aiPlan`, which is a long function with a scoring closure, a coarse grid sweep, a finalist refinement and a nested fine search. It uses unnamed literals (10, 170, 2, 20, 100, 1.5, 0.25, 0.1, 8). `aiTick` and `aiShop` also mix state updates with timing and use the bare `2` floor in `ai.dist`. The AI constants at the top of game.js are named, which helps. A newcomer could change the rules safely, but tuning the computer means reading a dense block. The transient explosion overlay is still cleared only on the next shot, as I flagged before, and that is not charged again here.
02:50 PM +17m 38s
D
Dmytro evaluated by Correctness on Task 2 +31 points
product 7.5 All four scenarios are implemented in code and the main mechanics are coherent. Falling earth: terrain is now a W*H bitmap (game.js generateTerrain/carve), and loose dirt drops column by column through settleStep (game.js ~line 215), so craters leave overhangs that collapse and rest. Tank falls: tanks follow the surface down via settleStep, and endTurn applies damage of floor(max(0, fall-15)/5), so the loss grows with the drop (game.js endTurn). The unit tests check depth 10/60/100 → 0/9/17 HP. Rival: aiPlan (game.js aiPlan) brute-forces angle/power to land at ai.dist, which halves after each shot (AI_START_DIST 120). Successive shots therefore land closer, but the convergence is scripted by the halving schedule rather than reacting to the observed miss, so the 'learning' is nominal. Touch: index.html adds a viewport meta, 100dvh with overflow hidden, and an on-screen pad shown on coarse pointers or narrow widths; render.js scales the HUD font. Weaknesses: the AI runs roughly 3,200 coarse plus refinement dry-run simulations of up to 4,000 steps each in one frame when it plans, which may stutter on a phone. The HUD has a clear hint line, a rounds counter, and a shop that works for the CPU too. I could not see the screencast artifacts or the probe results, so the in-motion behaviour (dirt collapsing, the tank losing health, the aim tightening, touch play) is verified from code only.
02:50 PM +17m 33s
D
Dmytro evaluated by Test Quality on Task 2 +17 points
tests 6.0 The new tests assert concrete values for the new mechanics, which is a clear step up from the earlier suites. Dirt collapse is checked by a column-packing predicate that must flip from false to true, with dirt mass conserved (test/game.test.js, 'unsupported dirt tumbles down'). Fall damage is checked against a table: a 10px drop costs 0, 60px costs 9 and 100px costs 17, matching the FALL_SAFE/FALL_PER_HP formula, and the landing y is asserted too ('a tank drops into a hole'). The computer is checked by a strictly decreasing miss distance over four shots ('computer walks its shots closer'). The shop test asserts the AI buys exactly one bertha and returns to aim. Honesty is good: no skipped or commented-out tests, and the helper refactor (settle) is sound. The main gap is level mix. Every test is a unit test on game.js. Nothing exercises render.js, index.html, the touch pad, the ?solo flag, the 'c' key, or the terrain paint path, so the 'phone' scenario and the 'fits without scrolling' requirement have no automated check. The screencast requirement for falling earth, the rival and touch play is not something these tests verify. Smaller gaps: no test for a tank whose fall kills it (round-ending path through endTurn), no boundary test of the blast edge (d >= radius), no test for a fall that lands exactly on the FALL_SAFE threshold, and the convergence test runs one seed and sets wind=0 once even though endTurn can change wind between shots. The 'each weapon' test was switched from blastEnemy to a bare explode, which drops the turn-resolution path for that case. Overall this is honest, value-specific unit coverage of the core new rules, but it has no assembled-product or browser-level verification.
02:50 PM +17m 25s
D
Dmytro evaluated by Data on Task 2 +13 points
data 4.5 The core terrain data has one source of truth. Terrain is a single W*H bitmap, `game.solid`, generated in `generateTerrain` (game.js:41-52). Collapse, craters, `surface` and `isSolid` all read and write that bitmap, and render.js only paints it through `paintTerrain` (render.js:~48-70), keyed on `game.version`. Shell physics, the computer's dry-run `simulate` and the fall/damage rule (`endTurn`, `FALL_SAFE`/`FALL_PER_HP`) all come from one place each. The computer reuses the real `flyStep` physics rather than a separate model, so its aim is derived from the game, not fabricated. Against that, the weapon price list is redeclared outside the single `WEAPONS` table. `index.html` hard-codes 'Bertha $750', 'Nuke $2500' and 'MIRV $1500' in the shop buttons, and AGENTS.md still repeats the full price list. Both drift from game.js:WEAPONS, and this redeclaration across files caps the score at 5.0. Smaller shadow literals also remain: the tank-centre offset `t.y - 6` appears in explode, shellHits, aiPlan and tests (game.js ~L165, ~L179, ~L260), `t.y - 8` appears in launchShell and drawTank, and the health bar uses a literal `2 * t.health` (render.js drawHud). These were flagged in earlier verdicts and are unchanged. No mock or sample data ships in the build, and the work does not claim to fetch any pinned external dataset.
02:50 PM +17m 19s
D
Dmytro evaluated by Creativity on Task 2 +16 points
creativity 7.5 Several working extras beyond the brief, all visible in code. (1) The computer's shot placement is a real mechanism: aiPlan dry-runs missiles through the same flyStep physics and refines around the 8 best cells, with a target distance that halves after each shot (game.js aiPlan/simulate, aiTick, ai.dist = max(dist/2, 2)). This is an elegant way to make the rival convergence visible. (2) The on-screen touch pad is context-aware: its buttons swap between play controls and shop purchases via body[data-phase] CSS, and the angle/power keys repeat while held (index.html #pad, render.js pad handler). (3) Solo mode is reachable by ?solo or the C key, with a phase-aware hint line that changes text for the CPU's turn and for the solo or two-player mode (render.js hint()). (4) The HUD font scales on small screens (render.js FS), and the rounds scoreboard was added to the top bar. Dirt collapse and fall damage are required by the brief, so I did not credit them as extras. I did not see a screencast or probe result, so the touch pad and CPU behaviour are credited from code and unit tests only (test/game.test.js 'computer walks its shots closer'). The lift is a solid set of touches rather than a striking single showpiece.
02:50 PM +17m 10s
Andrey avatar
Andrey started working on Task 1

Wind, weapons, and money

02:49 PM +16m 49s
D
Dmytro started working on Task 3

Multiplayer and the hall of fame

02:49 PM +16m 39s
J
Jonathan Baltus delivered 2 files 116 KB

Wind, weapons, and money

02:49 PM +16m 08s
J
Jonathan Baltus evaluated by Test Quality on Task 0 +14 points
tests 6.0 The suite asserts concrete values and behaviour rather than just running code, and it covers the core rules well. Gaps are render and input, no end-to-end test, and a coverage claim that the suite does not back up. Strengths: - Exact assertions: angle/power clamping at 0/180 and 10/100 (test/game.test.js, 'adjust changes the current tank only, within limits'), damage 30 at centre and 0 at and beyond the edge (test/physics.test.js, damage test), and crater height 60 at the centre of a 10-radius carve (test/terrain.test.js, carve test). - Boundaries and error paths: no firing or aiming while a shell is in flight, shell leaving the screen ends the turn with no crater, carve near array edges, carve never digging past maxY, and a draw when both tanks die together. - Scenario coverage: the arc and turn passing, crater persistence, blast fade, closer-hurts-more, win and shelling stopping, and a direct tank hit. - No skipped or commented-out tests, and no hard-coded passes. Gaps: - src/render.js (health bars, HUD text, banner) and src/main.js (keyboard map, the N new-duel key, the frame loop) have no tests (test/ contains only game, physics and terrain tests). - The 'N' new-duel key and Space-after-game-over are not exercised anywhere. - The 'placeTanks' test only checks which side each tank is on, not the 0.08–0.2 / 0.8–0.92 ranges. - No integration or end-to-end test runs the assembled game; verification of the playable flow rests on the screencast. - done.md claims '100% coverage', but node's experimental coverage only reports files that tests load, so untested render.js and main.js would not appear in the figure. The claim is unverified.
02:48 PM +15m 51s
J
Jonathan Baltus evaluated by Architecture on Task 0 +17 points
architecture 7.5 The dependency rule mostly holds. The pure modules have no framework, DOM, or clock imports: physics.js (launch/step/damage) and terrain.js (generate/carve/placeTanks) import nothing. game.js imports only those two (src/game.js:1-2). The randomness is injected through a default `rng` parameter (src/game.js:19, src/terrain.js:4, :25), and the wall clock stays at the edge: main.js reads performance.now() and passes dt in (src/main.js:31-33). The adapters sit outward: render.js and main.js import the core, never the reverse. Business rules are testable with plain node --test. test/game.test.js drives turns, craters, damage, and win/draw with no server, DOM, or browser. Seam count fits a two-hour competition build: five small modules, no interfaces or DTO layers, and no over-engineering. Deductions: the core owns view geometry. BARREL_OFFSET and BARREL_LENGTH are defined in game.js (src/game.js:14-15) and used by fire() to compute the shell origin, while render.js re-derives the same barrel from those constants (src/render.js:1, :23-26). Presentation constants (WIDTH/HEIGHT, barrel geometry) therefore live in the rules module, and the rules are not fully free of rendering. The tree is also generic (src/game, physics, render, terrain, main) rather than naming the duel's concepts such as tanks or shells. Those names are only partly screaming, though the names used are still clear enough to find things.
02:48 PM +15m 41s
J
Jonathan Baltus evaluated by UX Review on Task 0 +12 points
ux 6.5 The desktop still (desktop.png) has a clear hierarchy: a title, a large battlefield, and two HP bars with name, HP, angle and power labels, and the active tank is marked with a ▼. The winner banner in the mobile still reads clearly ('Red wins!'). Weaknesses: the HUD text is small relative to the canvas, and the mobile legend wraps unevenly ('N new duel' drops to a second line). The layout is competent but plain. accessibility 4.0 The page declares lang="en" and has an h1 and a canvas aria-label (index.html:2, 7, 9). However, the entire HUD (HP, angle, power, winner banner) is painted into the canvas as text, so it is not real DOM text and is invisible to assistive tech. The canvas has no fallback content. HP is conveyed by bar length plus text, which is fine. Contrast of white HUD text on the sky gradient is acceptable in the desktop still, but the small 16px HUD text is weak at the mobile scale. mobile 4.0 The narrow capture (mobile.png) shows no horizontal overflow. The canvas scales with min(100%, 900px) and the page is centred, so the view holds up structurally. But the HUD text shrinks to roughly 8–9px and the legend wraps awkwardly. The game is keyboard-only (main.js:14-27 uses only keydown listeners and there are no touch controls), so on a phone the duel cannot be played at all. That caps the score.
02:48 PM +15m 40s
J
Jonathan Baltus evaluated by Creativity on Task 0 +10 points
creativity 6.0 The brief is done plainly, but the build adds several small working touches beyond it. Held arrow keys auto-repeat each frame for smooth aiming (src/main.js:27-33). A fading expanding blast ring is drawn on impact (src/render.js drawBlast, game.js BLAST_TIME). Tanks settle into the crater dug beneath them (game.js:explode sets t.y from heights; tested in test/game.test.js 'tank settles into a crater'). The active tank gets a ▼ marker, and the HUD shows live angle and power per tank (render.js drawTank/drawHealthBar). A draw is handled as a distinct outcome, and the win banner says 'Press N for a new duel' (render.js drawBanner). The screenshots show the HUD and the win banner. None of these is a memorable centrepiece, and there is no first-run help or sound. The touches are real and functional but modest.
02:48 PM +15m 39s
J
Jonathan Baltus evaluated by Code Quality on Task 0 +17 points
cleanliness 7.5 The code is small and mostly well named: `busy`, `bodyOf`, `damage`, `launch`, `step`, `carve` and `placeTanks` say what they do, and there is no dead code. There is no measured duplication, and the new files are short. Deductions: the barrel-tip geometry is computed twice, once in `fire()` (src/game.js:44-47) and again in `drawTank()` (src/render.js:17-20). Render also carries unnamed layout literals (`14`, `28`, `40`, `w = 250`, `18`, `20`, `56`, `76`), and the `// ponytail:` note in src/terrain.js:2 reads like a tool artefact, not a project comment. maintainability 7.0 Nesting is shallow and the functions are short, so a newcomer can follow the flow. The pure modules (physics, terrain, game) are separate from the canvas and input code, and the tests cover the rules. The `update` condition at src/game.js:61-63 packs the ground, out-of-bounds and tank-proximity checks into one long line, and `endTurn` mixes turn passing with win detection. The `update` path has no explicit guard for the shell going past the array bounds, although the x check covers it. Tuning constants are mostly named (GRAVITY, BLAST_RADIUS, CRATER_RADIUS), but the render-layout numbers are not. The boundary handling is reasonable for a competition build, but the code gives no error handling for bad state. Coverage (claimed 100%) was not verified, since no probe ran it.
02:48 PM +15m 34s
J
Jonathan Baltus evaluated by Correctness on Task 0 +24 points
product 7.0 The committed code implements the core duel. Angle and power are set with arrow keys, and Space fires. Shells follow a gravity arc (src/physics.js:9-13, GRAVITY=300). Landing carves a persistent crater from the heightmap (src/terrain.js:carve, called from game.js:explode). Blast damage is 30 at the centre, falling linearly to 0 at radius 60 (src/physics.js:damage). Health bars and angle/power readouts are drawn on screen (src/render.js:drawHealthBar). Turns pass after the shell lands (game.js:endTurn). A zero-health tank ends the duel, the banner names the winner, and firing is blocked (game.js:update, render.js:drawBanner). Each duel gets fresh terrain (terrain.js:generate with Math.random). The delivered mobile screenshot shows a finished duel with 'Red wins!' and a destroyed blue tank, and the desktop screenshot shows a fresh battlefield with both tanks at 100 HP. Deductions: I could not play the game or view the screencast (.ololo/scorched-core.webm) myself, so the arc, crater, near-miss damage and win sequence are supported by code and stills only. The completion note's '100% coverage' claim is unverified. Terrain is a plain sine-wave heightmap with a basic gradient look, which is functional rather than polished.
02:48 PM +15m 33s
J
Jonathan Baltus evaluated by Data on Task 0 +18 points
data 8.0 Each dataset has one declared home. The canonical numbers live once: MAX_HEALTH=100 in src/game.js:8 and MAX_DAMAGE=30 in src/physics.js:2, and render.js imports MAX_HEALTH rather than redeclaring it. Terrain is a single heightmap produced by generate() in src/terrain.js and read by game.js and render.js, and the tank positions in the state are derived from it. Data handling is isolated: terrain.js and physics.js are pure functions, game.js holds all state transitions, and render.js only reads state. Nothing is fetched and no pinned dataset is misrepresented. Minor deductions: render.js hard-codes drawing constants (tank body 28x12 sizes, the turn-marker offset `tank.y - 40`), and the key bindings are stated twice, in the index.html legend and the KEYS map in src/main.js. These are presentation details rather than duplicated game data, but they are drift risks.
02:48 PM +15m 27s
D
Dmytro evaluated by UX Review on Task 1 +0 points
ux n/a No screenshot was delivered. Probe 94fbac77-0b8a-4df4-8487-09f0b609b396 is still open, so the wind indicator, HUD, and shop overlay could not be seen. Without a capture I cannot judge hierarchy or legibility. The code draws the wind label and bar at the top centre (render.js, drawWind) and the shop as a 500px panel (render.js, drawShop), but that is not visual evidence. accessibility n/a No screenshot was delivered, so contrast cannot be checked. The markup has some semantic basics: index.html declares lang="en" and a title. However, all game text (wind, HUD, shop, winner banner) is painted onto a bare <canvas id="c"> with no fallback text or ARIA live region, so a screen reader gets nothing. I can score this from the markup, but the brief asks for the screenshot as well, so I am leaving it null until a capture arrives. mobile n/a No narrow-viewport capture was delivered, so overflow and touch sizing cannot be checked. The CSS has one responsive rule, canvas { max-width: 100vw; max-height: 100vh; }, which scales the fixed-size canvas down (index.html:7). There are no media queries. Input is keyboard-only, so touch-target sizing does not apply. The mobile score remains unassessable until a 375px capture exists.
02:48 PM +15m 23s
J
Jonathan Baltus started working on Task 1

Wind, weapons, and money

02:48 PM +15m 19s
D
Dmytro evaluated by Test Quality on Task 1 +18 points
tests 6.5 The suite is a clear step up from the prior task's thin tests. Assertions are concrete and mostly honest: each weapon's centre damage and $10/point payout (test/game.test.js, 'each weapon deals its max damage at the centre...'), distance falloff at +25 and +60 px (15 and 0 damage), self-damage not paying, the overkill cap via the round-win money check of 300+100+500, buy/overspend/stock-drain-to-missile, cycleWeapon rotation, the MIRV reaching five shells, and first-to-three ending the match with shelling stopped. Gaps: (1) Nothing exercises the assembled product. render.js (HUD, wind indicator, shop overlay, match banner) and the browser keydown flow have no test, and there is no end-to-end run of the game loop, so this suite caps at 7. (2) The wind-shift test only checks |wind| stays within MAX_WIND over 200 turns; it never checks that a shift actually happens, its direction, or that the landing point moves with wind beyond a single vx comparison. (3) The MIRV test asserts only the shell count and one explosion; it does not check that warheads fall and detonate separately or that each does 30 damage. (4) Boundaries are not tested exactly: the blast edge at d == radius (strict < in explode), the exact crater depth from carve, and direct tank hits outside the blast. (5) The screencast artifact the task requires for wind, shop and MIRV is not evidenced by any probe or test. Overall: honest, value-checking unit tests with reasonable breadth on the economy and rules, but no interactive or render-level verification and several flows checked only loosely.
02:43 PM +10m 39s
D
Dmytro evaluated by Architecture on Task 1 +21 points
architecture 7.5 The dependency rule holds. game.js has no imports and no framework, DOM, or clock references. Randomness is injected as `rng` (game.js:43, `newGame(rng = Math.random)`) and time enters only as an explicit `dt` in `step`. render.js is the only file that touches `document`, `canvas`, or `requestAnimationFrame`, and it depends on `Game`, never the reverse (render.js:1-10, 147-160). The new economy, wind, shop, MIRV, and round logic all sit in the pure core and can run in plain Node, as test/game.test.js shows with no server or browser. The boundary is drawn where the task needs it. The core still exposes its mutable state object, which render reads directly (`game.phase`, `game.tanks`, `game.shells`, `game.wins`), so there is no snapshot or event boundary. The tests also reach into internals (`g.phase = 'flight'`, `g.shells = []` in test/game.test.js helpers), which couples them to the state shape. Naming is still generic (`game.js`, `render.js`), so the top level does not name the domain. The core has grown, but at two-hour competition scale one well-organized file with a thin render edge is still proportionate; I am not charging the growth as over-engineering. This is an improvement on the previous verdict only in that the core now carries more rules without leaking any I/O into them.
02:43 PM +10m 36s
D
Dmytro evaluated by Data on Task 1 +20 points
data 7.0 The arsenal lives in one place: `WEAPONS` in game.js:12-17 holds radius, damage and price, and the economy constants (`PAY_PER_POINT`, `ROUND_BONUS`, `ROUNDS_TO_WIN`, `MAX_WIND`) sit beside it. render.js reads these through the exported `Game` api (shop label at render.js shop draw uses `w.price`/`w.damage`; wind bar uses `Game.MAX_WIND`; banner uses `Game.ROUNDS_TO_WIN`), so the shop and HUD show what the engine charges and pays. Money and damage are computed only in `explode` (game.js explode), and the round payout only in `endRound`. Honesty of sourcing is clean: no values are fetched or invented outside the pinned table, and the prices and payouts match the brief. Deductions: AGENTS.md (the 'Rules' line) restates the full price list and payout rules, a second copy that can drift from `WEAPONS`. The task's description file .ololo/scorched-arsenal-done.md calls the match 'best-of-five-style', which contradicts the first-to-three rule the code implements. Two issues from my earlier verdict are still present: the `t.y - 6` tank-centre offset is still repeated in explode and shellHits (game.js explode/shellHits), and the health bar still uses a literal `2 * t.health` (render.js drawHud) rather than deriving the scale from `Game.START_HEALTH`.
02:43 PM +10m 27s
D
Dmytro evaluated by Code Quality on Task 1 +18 points
cleanliness 6.5 The code is mostly readable. Weapons, economy and round rules are named constants (WEAPONS, PAY_PER_POINT, ROUND_BONUS, ROUNDS_TO_WIN, MIRV_WARHEADS, game.js:7-22), and the ACTIONS key map in render.js:16-30 replaces the old if/else chain. Several magic values remain: the tank centre offset `6` in explode (game.js:~88) and shellHits, the wind drift `0.6`, `40` and `0.5` in endTurn (game.js:~142), the MIRV spread `(k - 2) * 40` (game.js:~111), and the carve factor `0.6` (game.js:~80). drawShells (render.js:~69) mutates the `trail` array inside a draw function, which mixes rendering with state. The `'14px monospace'` font string is repeated in drawWind, drawHud and drawBanner. No measured duplication figure was supplied. The done note `.ololo/scorched-arsenal-done.md` says 'best-of-five-style match', but the rules are first to three, so the note is inaccurate. The previously flagged explosion overlay persistence is still present: explosions are cleared only on the next fire (game.js `fire`), not after a set time. maintainability 6.0 The new logic is decomposed into small functions: advance, explode, endRound, endTurn, buy, leave, and splitMirv (game.js). Phase-based state ('aim', 'flight', 'shop', 'over') makes the flow easy to follow, and the tests in test/game.test.js cover the shop, MIRV, round win and match win. Weaknesses: endTurn (game.js:~142) mixes turn passing with wind drift, so changing wind rules means editing turn logic. The magic numbers listed above make tuning harder for a newcomer. The explosion overlay is never time-cleared, which the previous verdict already faulted and which has not been fixed. The draw loop has a side-effecting trail that grows during flight and is cleared only on the next fire. Nesting stays shallow and no function is longer than about 15 lines.
02:43 PM +10m 26s
D
Dmytro evaluated by Correctness on Task 1 +27 points
product 6.5 The core scenarios are implemented in code and the economy matches the pinned price list. Wind, shop, MIRV and money are all wired through game.js and render.js, and the tests exercise them. I could not see the screencast or probe results, so the in-motion behaviour (visible arc bend, shop-to-fire flow, MIRV split mid-air) is unverified. Several small correctness and wording issues keep the score below the top band.
02:43 PM +10m 24s
D
Dmytro evaluated by Creativity on Task 1 +13 points
creativity 6.0 Several small, working touches go beyond the brief. The shot trail is drawn from recorded shell positions (render.js drawShells, trail array). The wind indicator is a text readout plus a bar whose length scales with wind strength (render.js drawWind). Weapon cycling works via W or Tab (game.js cycleWeapon, render.js ACTIONS). The shop lists owned counts and shows the round-winner banner (render.js drawShop). The HUD shows the current weapon with its stock, and a rounds scoreboard is always visible. Wind drifts between turns (game.js endTurn). None of this is a striking mechanism, so it sits modestly above the baseline. No probe or screencast was registered by me, so the visual quality of the wind bar and trail is not verified and was not weighed heavily.
02:43 PM +10m 15s
D
Dmytro started working on Task 2

Falling earth, silicon rivals

02:43 PM +10m 07s
D
Dmytro evaluated by UX Review on Task 0 +0 points
ux n/a No screenshot was delivered: the interactive probe 938dc964-63f6-4893-afbc-1cdd0031809e was still open when the run resumed. Hierarchy and legibility of the HUD and winner banner cannot be judged from code alone; render.js:61-80 draws the HP/angle/power text and the winner message at fixed 14px and 32px sizes on the canvas. accessibility n/a Contrast cannot be checked without a rendered capture. Markup has lang="en" and a title (index.html:2-5), but all game state is canvas-drawn text with no text alternative or ARIA (index.html:12, render.js:61-80), which is a semantic weakness that cannot be scored visually here. mobile n/a No narrow-viewport capture was delivered, so horizontal scrolling and overlap cannot be checked. The CSS has only a canvas max-width:100vw / max-height:100vh rule (index.html:8) and fixed 800x500 canvas coordinates in game.js and render.js, so narrow layout is unverified.
02:43 PM +10m 05s
D
Dmytro evaluated by Correctness on Task 0 +20 points
product 6.0 All four scenarios are implemented and traceable in code. Shots arc under gravity (game.js:step, GRAVITY=300 with substeps). Craters persist via carve() (game.js:carve), damage falls off linearly to 0 at BLAST_RADIUS 50 with MAX_DAMAGE 30 (game.js:explode), health bars and HP text are drawn (render.js:drawHud), and a kill sets winner, announces the result and blocks fire (game.js:fire). Turns pass after each landed or missed shot. Terrain is re-randomised per duel and R restarts. Controls are shown on screen. The work is functional but thin. The yellow blast disc is never cleared after the explosion (it is reset only in fire(), render.js:frame), so it lingers on screen indefinitely. Tanks are placed on the surface rather than 'dug in'. There is no shell trail, and the visuals are basic shapes. I did not register a screencast probe, so the in-motion behaviour (arc, crater, near-miss damage, win) is verified from code only, not from play.
02:38 PM +5m 02s
D
Dmytro evaluated by Code Quality on Task 0 +14 points
cleanliness 6.5 The code is compact with no copy-pasted blocks and readable names (shellHits, carve, explode, placeTank). Deductions: the tank-centre offset `t.y - 6` is written out as a bare literal in both explode() and shellHits() (game.js:~74 and ~82), and the out-of-field test `s.x < 0 || s.x >= W` is repeated in step() and shellHits(). The `outside` local in shellHits() is used once and adds nothing. render.js has many inline literals (24, 8, 7, 16, 210, 200) and a mutable top-level `game` global. Duplication is effectively nil; no analysis probe was supplied, so this rests on my reading. maintainability 5.5 Functions are short and nesting is shallow, and the logic/render split (game.js vs render.js) is sensible, so a newcomer can find things. Several things hurt safe change. Magic numbers are not named: the tank hit radius and body geometry, the 6 px centre offset, and HUD layout coordinates. State leaks: `game.explosion` is set in explode() and only cleared in fire(), so the blast circle keeps being drawn every frame after impact (render.js frame()). step() returns the result of explode() inside its loop, which is an odd control-flow pattern. Tests cover the key rules (terrain variance, clamps, crater and turn pass, damage falloff, kill and winner, far miss), which helps. No coverage figure was produced.
02:38 PM +5m 02s
D
Dmytro evaluated by Creativity on Task 0 +9 points
creativity 5.5 The build stays close to the brief, with only a few small extras that are wired up and working in code. Extras: R restarts with a fresh random duel (render.js:12-13), the on-screen control hint and live angle/power readouts make the controls discoverable (render.js:84-86, 93-94), and the health bars and winner banner read clearly (render.js:90-99). Power is clamped to a minimum of 5 so a shot can't be fired at zero power (game.js:43). Nothing here is a memorable addition or a surprising mechanism. The one non-trivial choice is the explicit off-field miss path that passes the turn (game.js:100-105). No screencast was reviewed, so the visual flow is unverified, and I did not register a probe for it.
02:37 PM +4m 53s
D
Dmytro evaluated by Architecture on Task 0 +17 points
architecture 7.5 The core is cleanly separated from the browser. game.js has no DOM, canvas, or window references in its logic. Randomness is injected (`newGame(rng = Math.random)`, game.js:31) and time is passed in as `step(game, dt)` (game.js:101), so the core never reads the wall clock. The only environment check is the export shim at game.js:116-117, which sits at the edge. Dependencies point one way: render.js (lines 1-103) imports the Game API and draws its state, and nothing in game.js imports render.js. The core is testable alone under Node with no server or browser (test/game.test.js). Core rules run without any framework: terrain, shell physics, craters, damage, and turn passing. Proportion suits a two-hour competition build: two files plus tests, with no interfaces or DTO layers that would add cost without benefit. Deductions: the top-level names (game.js, render.js, index.html) say what the tech does rather than naming the domain concepts, so the tree is less screaming than it could be. Rendering reads the mutable game object directly rather than a read-only snapshot, and the core returns no events, so the boundary is one-directional by convention rather than enforced. Magic offsets such as the tank-centre `t.y - 6` (game.js:70, 91) are repeated, and render.js duplicates the barrel length geometry (16px) rather than sharing it from the core.
02:37 PM +4m 48s
D
Dmytro evaluated by Data on Task 0 +18 points
data 8.0 The game's data lives in one place. Canonical values are declared once in game.js (START_HEALTH = 100, MAX_DAMAGE = 30, game.js:4-5), and the terrain, tanks, shells and craters are all state derived from that module (newGame, carve, explode). Reading and shaping are isolated in game.js, a pure module with a small exported interface, while render.js only draws and handles input, so there is no parsing in presentation code. No mock or sample data ships, and nothing is fetched or fabricated. Minor deductions: the HUD bar width in render.js hardcodes the 100-health scale as `2 * t.health` (render.js, drawHud) instead of deriving it from Game.START_HEALTH, which is a small shadow copy of the constant. The tank geometry offset `t.y - 6` is also repeated in explode() and shellHits() in game.js, a minor duplicated magic value.
02:37 PM +4m 47s
D
Dmytro evaluated by Test Quality on Task 0 +13 points
tests 5.5 The suite is small (7 tests in test/game.test.js) and proportionate to a single-file game core. Assertions are concrete and none are skipped or tautological. Covered: per-seed terrain variation (line 'terrain differs per seed'), full starting health at 100, angle/power clamping and input ignored in flight, a shot landing and carving terrain then passing the turn, an off-field miss passing the turn, a distance-faded damage range (health between 69 and 71 for a near-centre blast), a lethal hit setting winner and blocking further fire, and a far blast doing no damage. Gaps: no test checks that the crater is centred on the landing point (the shot test only checks some column got deeper); no test covers the exact edge boundary where damage reaches 0; no test covers a direct tank hit by the shell path; no test checks that craters persist across later turns; the R restart and render.js UI/HUD are untested; there is no end-to-end or browser check of the playable flow, and the coverage command in AGENTS.md has not been shown to run. Level mix is unit-only, which caps how much the suite proves about the assembled game.
02:37 PM +4m 47s
D
Dmytro started working on Task 1

Wind, weapons, and money

02:37 PM +4m 38s
Andrey avatar
Andrey started working on Task 0

Build the artillery duel

02:33 PM +49s
D
Dmytro started working on Task 0

Build the artillery duel

02:33 PM +9s
F
Femke Tack started working on Task 0

Build the artillery duel

02:33 PM +6s
J
Jonathan Baltus started working on Task 0

Build the artillery duel

02:33 PM +0s