Skip to content

Keep friends on the same team in public Duos, Trios and Quads - #6091

Open
iiamlewis wants to merge 2 commits into
mainfrom
claude/new-session-ebfd11
Open

iiamlewis wants to merge 2 commits into
mainfrom
claude/new-session-ebfd11

Conversation

@iiamlewis

Copy link
Copy Markdown
Contributor

What was wrong

A player reported (support ticket #3877) that they and a friend joined the same public Duos lobby before it started, but were put on different teams.

In public team games, players who aren't in a clan were seated one at a time, in the order they joined. Each player went to the team with the most of their friends on it. If no team had any, Duos, Trios and Quads put them on the fullest team that still had room.

That breaks when a friend group is split by strangers in the join order:

  1. A stranger joins first and sits alone on Red.
  2. Friend A is placed. Friend B hasn't been placed yet, so A has no friends on any team, and the "fullest team" rule puts A beside the stranger on Red. Red is now full.
  3. Friend B is placed. B's friend is on Red, but Red is full, so B goes to Blue.

The existing tests didn't catch this because the friends were always the first players in the list.

What this changes

All in packages/engine-lib/src/game/TeamAssignment.ts:

  • Friend groups are seated back to back, largest first. Players linked by friendships (including friend-of-friend chains) are grouped, then each group is placed in one go, so strangers can't take a friend's seat in between. Players without friends are groups of one and keep their join order, so games with no friends in them assign teams exactly as before.
  • The first member of a group goes to a team with room for the whole group. When no team has any of a player's friends yet, it now prefers the team that can seat the most of their group before falling back to the old tie-break. This covers the case where a team is already half-filled by a clan, for example.
  • Groups too big for one team still spill onto another team. Nobody is kicked, same as before.

Clan grouping, matchmade team pins (ranked 2v2/FFA, clan wars) and nation placement aren't changed. The lobby preview uses the same function, so the teams it shows stay in step with the game.

Example (3 Duos teams, 6 players)

Join order Before After
stranger, A, B, 3 strangers s1 Red, A Red, B Blue ❌ A Red, B Red, s1 Blue ✅
A, 2 strangers, B, 2 strangers A Red, s1 Red, s2 Blue, B Blue ❌ A Red, B Red, s1 Blue, s2 Blue ✅

Screenshots

None: this changes team assignment in the simulation, not any UI. The examples above are the real output of assignTeams.

Things to know

  • This only affects public lobby Duos/Trios/Quads. Ranked 2v2 teams come pinned from the matchmaker in the API, and those pins still win over friend lists.
  • Friend grouping needs both players signed in and friends in the game (the friend list from /users/@me).

Tests

Three new regression tests in tests/TeamAssignment.test.ts. All three fail on main and pass with this change:

  • duo friends who joined after one stranger
  • duo friends who joined far apart
  • a group of three friends when a clan member already holds half of one team

npx vitest tests/TeamAssignment.test.ts --run: 34/34 pass. The full suite's only failures (RenderDesktopDescriptor, UpdateRegister) also fail on an unmodified checkout on Windows and aren't related. Lint and typecheck are clean.

🤖 Generated with Claude Code

Players were seated one at a time in join order. In Duos/Trios/Quads the
tie-break packs the fullest open team, so the first friend took the last
seat beside a stranger and the second friend found that team full.

Friend groups are now seated back to back, largest first, and the first
member goes to a team with room for the whole group when there is one.
Groups too big for one team still spill over rather than kicking anyone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 96f06748-97a3-4a1a-ac95-94609f8e0401
📥 Commits

Reviewing files that changed from the base of the PR and between eb152aa and e818e1e.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • No new commits to review - use @coderabbitai full review for a full pass

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3f58699c-2178-47da-8d8f-58273a98d38d
📥 Commits

Reviewing files that changed from the base of the PR and between ad40ac6 and eb152aa.

📒 Files selected for processing: 2
  • packages/engine-lib/src/game/TeamAssignment.ts
  • tests/TeamAssignment.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 5 remain after this review.

Walkthrough

Team assignment now groups connected friends and processes larger groups first. Team selection considers how many remaining group members fit on each team. Tests cover duo and three-person friend groups.

Changes

Friend-group placement

Layer / File(s) Summary
Build and process friend groups
packages/engine-lib/src/game/TeamAssignment.ts
The assignment flow builds connected friend groups, sorts them by size, and passes each member’s remaining group count to placement.
Place friends together
packages/engine-lib/src/game/TeamAssignment.ts, tests/TeamAssignment.test.ts
Team selection uses the number of remaining group members a team can fit as a tie-breaker. Regression tests cover duo and three-person friend groups.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Bug fix

Possibly related PRs

  • openfrontio/OpenFrontIO#6080: This PR records each human player's team through assignTeams, so its recorded team values use the updated placement behavior.

Suggested reviewers: evanpelle

Merge Risk: ⚪ Minimal · up to eb152

No concrete issue remains that would prevent merging after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: keeping friends on the same team in public Duos, Trios, and Quads.
Description check Passed The description is directly related to the changeset. It explains the assignment issue, the friend-group placement changes, scope, tests, and known unrelated failures.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Friends line up, group by group
Larger circles take their turn
Open seats help guide the choice
Duos find a place to stay
Three friends fit where room remains
Teams fill up, the tests confirm

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 Claude Code Review

Verdict: No issues found. 0 findings (0 high, 0 medium, 0 low).

Checked for bugs and CLAUDE.md compliance. Notes from the review:

  • friendGroups only builds groups from otherPlayers, so clan, pinned and nation players never get pulled into a friend group. A non-clan player's friend on a clan team still counts through friendsOnTeam, as it did before.
  • Every non-first member reached by the BFS is a direct friend of a member placed earlier, so the friendsOnTeam preference still decides where they go. groupSeats only matters for the first member, or when a friend's team is full.
  • When no friends are present, each player is a group of one with groupLeft = 1, so groupSeats is 1 for every open team. The stable sort keeps join order, so assignment is unchanged. In non-Duos/Trios/Quads games, the emptiest team always has the most room, so the new tie-break can't override the "emptiest first" balancing.
  • Math.min is exact, so it doesn't fall under the DetMath rule. The new test in tests/TeamAssignment.test.ts (clan + trio, maxTeamSize = 3) traces to Blue for the trio and Red for the clan member, as it asserts.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 Claude Code Review

Reviewed range: eb152aa..e818e1e

Verdict: No issues found. 0 findings (0 high, 0 medium, 0 low).

This range only merges in the base branch. It doesn't touch this PR's own files (packages/engine-lib/src/game/TeamAssignment.ts, tests/TeamAssignment.test.ts), so the earlier review of eb152aa still covers the PR's changes. Checked for bugs and CLAUDE.md compliance.

This branch was successfully deployed

1 active deployment
staging — e818e1ee Deployed Oct 23, 2026 by openfrontio[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Triage

Development

Successfully merging this pull request may close these issues.

2 participants