Commit Graph

1292 Commits

Author SHA1 Message Date
FloPinguin 1eee8b4ddb New Map! "Surrounded" 🏝️ (#2770)
## Description:

A new map where you basically have to hop from island to island :) 
We don't have such a map at the moment.
There is a special center island which isn't necessary to get 80% of the
map.
This map could be very interesting in team games. One hydro will destroy
an entire island.
Size: 1976 x 1976
Nations: 8

<img width="949" height="951" alt="Screenshot 2026-01-02 214219"
src="https://github.com/user-attachments/assets/7139bcc9-6a05-414d-90c1-33cc36dd94fb"
/>

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2026-01-02 13:09:59 -08:00
Arkadiusz Sygulski 4877e202f6 Update MIRV target selection algorithm (#2765)
## Description:

`MIRVExecution.separate` is consuming more resources than it needs to.
This PR introduces a series of minor performance changes which do not
alter the behavior of the selection algorithm. Assessing the code
initially, I was convinced there are multiple easy wins - starting with
the proximity check. However, after many hours of mostly math, no
alternative solution came close to the speed of current implementation.
Therefore this PR consists of only a few minor tweaks:

#### Removed `console.log`
This is by far the worst offender, in my test removing the three lines
of console log improved execution time from ~30ms down to ~10ms. The
logs are not very useful. I do not see a clear pattern in the logs
produced by the application therefore they were completely removed for
now. If there is a need for the log in production build, I suggest
adding single line with the number of destinations selected.

```diff
- console.log(`dsts: ${dsts.length}`);
- console.log(`got ${dsts.length} dsts!!`);
- console.log("couldn't find place, giving up");
```

#### Replaced multiple calls to `random.nextInt` with single call to
`random.next`
The flamechart shows calling pseudo random number generator is
expensive. Therefore instead of calling it twice, the code now generates
a single random number and derives further calculations from it. It
remains 100% deterministic and there should not be any noticeable change
to the enthrophy. This saves about ~1.5ms in my tests.

```diff
- const x = this.random.nextInt(
-   this.mg.x(ref) - this.mirvRange,
-   this.mg.x(ref) + this.mirvRange,
- );

- const y = this.random.nextInt(
-   this.mg.y(ref) - this.mirvRange,
-   this.mg.y(ref) + this.mirvRange,
- );

+ const r1 = this.random.next();
+ const r2 = (r1 * 15485863) % 1;

+ const x = Math.round(r1 * this.range * 2 - this.range + this.baseX);
+ const y = Math.round(r2 * this.range * 2 - this.range + this.baseY);
```

#### Caching of destination coordinates
Since the target tile coordinates are used a lot, instead of retrieving
them every time with `this.mg.x` and `this.mg.y`, they get cached as
`baseX` and `baseY`. To reduce usage further, I also exposed `x` and `y`
to `isOverlapping` / `proximityCheck` directly instead of passing the
tile. Since available methods operate on `TileRef`, this change requires
the calculations - manhattan and euclidean distance - to be inlined. I
do not think this is a big issue, considering this code is responsible
for very specific task. This saves another ~1.5ms in my tests.

```diff
- if (this.mg.euclideanDistSquared(tile, ref) > mirvRange2) {
+ if ((x - this.baseX) ** 2 + (y - this.baseY) ** 2 > this.rangeSquared) {
```

## Benchmark:
**Before**
```
=== MIRV Performance Benchmark Results ===
MIRV target selection - sparse territory x 53.53 ops/sec ±0.48% (71 runs sampled)
MIRV target selection - dense territory x 53.39 ops/sec ±0.57% (70 runs sampled)
MIRV target selection - giant world map (350 targets) x 1,129 ops/sec ±0.98% (90 runs sampled)
```
**After**
```
=== MIRV Performance Benchmark Results ===
MIRV target selection - sparse territory x 198 ops/sec ±0.39% (85 runs sampled)
MIRV target selection - dense territory x 200 ops/sec ±0.28% (86 runs sampled)
MIRV target selection - giant world map (350 targets) x 1,409 ops/sec ±0.89% (92 runs sampled)
```

## Please complete the following:

- [ ] I have added screenshots for all UI updates
- [ ] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory*
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

\* Tests in separate PR, implemented against master:
https://github.com/openfrontio/OpenFrontIO/pull/2767

## Please put your Discord username so you can be contacted if a bug or
regression is found:

moleole
2026-01-02 12:48:08 -08:00
evanpelle 2f7c9eb930 Merge branch 'v28' 2026-01-01 19:20:38 -08:00
Vahant Sharma b990fe6ae5 Use WebSocket intent for lobby game configuration updates (#2761)
Fixes #2758

## Description:
This PR migrates lobby configuration updates from the HTTP PUT
`/game/:id` endpoint to a WebSocket-based intent flow.

The lobby creator is already authenticated via the game WebSocket, so
updating configuration through intents removes redundant authentication
and aligns with existing real-time lobby actions such as `kick_player`
and `toggle_pause`.

## Changes Made
- Added `update_game_config` WebSocket intent schema
- Wired client → transport → server intent handling
- Refactored `putGameConfig()` to emit WebSocket intent instead of HTTP
fetch
- Preserved all existing validation, partial-update semantics, and
client-side debouncing
- Left the REST endpoint untouched for backward compatibility

## Testing
- All existing automated tests pass
- Manual verification completed:
  - Lobby creator can update all lobby settings
  - Non-creators are rejected
  - Updates are rejected after game start
  - Bots slider debounce (300ms) remains intact
  - No `PUT /api/game/:id` requests are made from the lobby UI

## Checklist:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
2026-01-01 16:46:53 -08:00
evanpelle 793efe4dd1 Revert "Special bot names (#2552)"
This reverts commit 8f32746bb2.
2026-01-01 16:32:57 -08:00
evanpelle e4a6e3bd20 Revert "Special bot names 2 (#2609)"
This reverts commit 099337d83e.
2026-01-01 16:30:41 -08:00
evanpelle e319de99ec Revert "Add Christmas emojis (#2634)"
This reverts commit 507f391aa1.
2026-01-01 16:14:33 -08:00
FloPinguin ad7c30e44c Fix nation warship edge-case issue ⛴️ (#2760)
## Description:

On the world map, if two teams of nations are fighting each other (left
side vs. right side), there is a possibility that an extreme warship
battle involving nearly 200 warships could occur. This PR helps resolve
that edge-case issue a bit.

<img width="623" height="647" alt="Screenshot 2025-12-31 155924"
src="https://github.com/user-attachments/assets/993c0b08-eccc-491f-aae9-7ea4fd8943f3"
/>

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2026-01-01 13:31:54 -08:00
FloPinguin fb6bbf1730 Reduce nation cheating even more 📊 (#2757)
## Description:

WIth my other new PR "Nations send much better nukes now (Part 1)"
nations got smarter.

Because of that, and based on player feedback, my own tests and youtube
videos (pros like enzo can't beat impossible difficulty nations without
warship infestations) we need to turn down the cheating.

With this PR, I reduced the cheating by 50% (again).

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2026-01-01 13:30:30 -08:00
FloPinguin 23e4bf6725 ☢️ Nations send much better nukes now (Part 1) ☢️ (#2756)
This is a very important PR for HumansVsNations (But also for
singleplayer).
Humans will throw lots of nukes onto nations, but nations didn't do
that. Until now :)

## Refactor

- Moved all the nuking logic to the new file `NationNukeBehavior.ts`
- Moved `randTerritoryTileArray()` and `randTerritoryTile()` to the new
file `NationUtils.ts` because we need that method in multiple places now
- Because we already have an `NationUtils.ts` (It contains the method
`createNationsForGame` for HumansVsNations) I renamed the old one to
`NationCreation.ts` to avoid confusion

## Bug fixed

- `allRelationsSorted()` in `PlayerImpl` returned dead players all the
time... Which caused nations to not attack / send nukes in some cases...

## Nuke-sending features / improvements

- On hard and impossible difficulty, nations no longer make sure that
nukes will only hit inside of their targets border. This logic very
often stopped nations from throwing nukes. Now their nukes are allowed
to hit TerraNullius (=> ocean!). And in team games, it's even allowed
that their nukes hit other non-friendly players as well! This is very
important for HumansVsNations.
- The basic check for SAMs now gets skipped if we are on easy difficulty
(easy nations are not smart enough to do that)
- I improved the basic check for SAMs (medium difficulty) a bit (nations
send less nukes into SAMs)
- On hard and impossible difficulty, we now use the new method
`isTrajectoryInterceptableBySam()` to avoid SAMs completely. It's
mirroring `NukeTrajectoryPreviewLayer.ts` logic a bit.
- I added "perceived cost" to simulate nations saving up for a MIRV
(Otherwise most hard/impossible nations will spend all their gold on
nukes). But if we are in a team game (MIRVs are not relevant) or if we
already saved up for a MIRV, the "perceived cost" gets ignored.
- Updated the "most hated player" selection in `findBestNukeTarget()` to
ignore very weak players. We don't need to throw nukes at players which
we can easily steamroll by land.
- Added `findFFACrownTarget()` to nuke the crown (based on difficulty).
- Added `findStrongestTeamTarget()` to nuke the strongest team.
- Updated `randTerritoryTile()` so that it has a higher chance of
returning the tiles of a
"leftover-nuked-to-death-player-with-some-tiles-left": `if
(p.numTilesOwned() <= 100) {return
random.randElement(Array.from(p.tiles()));}`.
- Changed `const range = nukeType === UnitType.HydrogenBomb ? 60 : 15`
to `config().nukeMagnitudes(nukeType).inner`. Should make more sense.
- Adjusted `nukeTileScore()` to search for units in
`this.mg.config().nukeMagnitudes(nukeType).inner` instead of fixed 25
- Adjusted `nukeTileScore()` to account for unit levels (levels got
ignored previously). Also increased score for ports from 10_000 to
15_000.
- I made sure that nations can nuke EVERY SINGLE TILE from an enemy,
even if the enemy has no structures ("Prefer tiles that are closer to a
silo" can no longer make the `nukeTileScore()` drop too much,
`bestValue` in `maybeSendNuke()` starts at -1 now)
- In the entire nuking logic, factories were missing. Now they are
added.

## Media

Nation team vs. nation team: They are nuking the very last pixels of
red, just like humans would do it 😀

<img width="915" height="683" alt="image"
src="https://github.com/user-attachments/assets/109c7921-b959-4aa9-a971-0d7742971686"
/>

Hard difficulty FFA game: Nations throwing much more nukes. And they are
nuking the crown.


https://github.com/user-attachments/assets/a6e43924-a6ca-4b1a-a578-4e4f8252e383

Lots of nukes flying:


https://github.com/user-attachments/assets/8fc4edad-a6e6-4476-8a86-08cdef58169e

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin

---------

Co-authored-by: iamlewis <lewismmmm@gmail.com>
2026-01-01 13:29:46 -08:00
bijx 9d5f167446 Feat: Strait of Hormuz map (#2747)
## Description:
Introduces the Strait of Hormuz section in the Persian Gulf as a map!
This map is actually crazy fun to play on because of how the water
narrows to a small strait where control is necessary otherwise enemies
can transport boat to you easily. I figured a strategic map based on
modern-ish day conflicts would fit the theme, but man it's a great map
to play on.

### Full Map
<img width="2739" height="1822" alt="image"
src="https://github.com/user-attachments/assets/f35bdefa-723a-4bb2-9dc9-fb42898528ce"
/>

### In game with nations
<img width="2218" height="1502" alt="image"
src="https://github.com/user-attachments/assets/00e350cf-8654-4638-8654-178accdf6a48"
/>



## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

bijx
2025-12-31 15:55:43 -08:00
Duwibi 11b2591fa6 Add Two Lakes (#2743)
## Description:
This PR adds the Two Lakes map, based on the irl area around lake Ohrid
and lake Prespa

Describe the PR.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

DISCORD_USERNAME
Nikola123
2025-12-30 19:34:51 +00:00
Abdallah Bahrawi 09a1cf885f Add red warning circle when nuke would break alliance (#2728)
## Description:

When placing a nuke (Atom Bomb or Hydrogen Bomb), the range circle now
turns red to warn players when the attack would break an alliance.

<img width="456" height="333" alt="Screenshot 2025-12-28 211927"
src="https://github.com/user-attachments/assets/dfe6f874-3f8b-4662-8877-0af30aa20139"
/>


## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

abodcraft1

---------

Co-authored-by: iamlewis <lewismmmm@gmail.com>
2025-12-30 17:55:15 +00:00
Evan 4f3d9df46a vite: fix docker build (#2738)
## Description:

The sync-assets wasn't executing on docker-build. so instead just import
it from resources/ directory, vite logs a warning but I think that's
okay for now.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2025-12-29 18:37:51 -08:00
FloPinguin d321c08d92 Nations now gang up on players and prioritize traitors/AFK players 🤖 (+ other improvements) (#2730)
## Description:

- **Nations now specifically target AFK players, traitors, and players
who are already being attacked (they gang up on them).** Depends on the
difficulty.
- Added ally assistance directly to the attack order (instead of calling
it separately beforehand).
- Added ally assistance to `findBestNukeTarget`.
- Removed some checks from `findBestNukeTarget` (not necessary; better
checks will follow in a dedicated nuking PR).
- Relation updates on attack now depend on difficulty (makes Easy &
Medium nations a bit easier).
- On betrayal, every nation in the game previously received a –40
relation penalty toward the betrayer. That was too extreme, so now this
only applies only to neighbors.
- Nations send fewer alliance requests now; it felt like too many
before.
- In team games, nations may now reject alliance requests more often
(depending on difficulty).
- To ensure there are enough non-friendly players to stop the crown with
nukes, nations may now reject alliance requests if the other player has
too many alliances (on Hard and Impossible difficulty).
- Rebalanced nation emoji usage a bit.
- Nations may now send an emoji when they get MIRVed.

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin

---------

Co-authored-by: iamlewis <lewismmmm@gmail.com>
2025-12-29 10:16:26 -08:00
Ryan f1561df470 Bomb Direction (#2435)
Resolves #2434 

## Description:

Allows bomb direction to be inverted by pressing a hotkey - currently
"U".

**Check the issue for screenshots / videos.**

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

w.o.n

---------

Co-authored-by: Evan <evanpelle@gmail.com>
Co-authored-by: iamlewis <lewismmmm@gmail.com>
2025-12-29 09:03:46 -08:00
Wraith 26f5d40819 build: migrate build system to Vite and test runner to Vitest & Remove depracated husky usage (#2703)
- Replace Webpack with Vite for faster client bundling and HMR.
- Migrate tests from Jest to Vitest and update configuration.
- Update Web Worker instantiation to standard ESM syntax.
- Implement Env utility in `src/core` for safe, hybrid environment
variable access (Vite vs Node).
- Refactor configuration loaders to remove direct `process.env`
dependencies in shared code.
- Update TypeScript environment definitions and project scripts for the
new toolchain.
- Remove the [depracated usage of the
husky](https://github.com/typicode/husky/releases/tag/v9.0.1).

## Description:

migrate build system to Vite and test runner to Vitest & Remove
depracated husky usage

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [ ] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

wraith4081

---------

Co-authored-by: evanpelle <evanpelle@gmail.com>
2025-12-28 22:10:26 -08:00
FloPinguin f6412a5979 Re-Enable HumansVsNations 🎉 (#2689)
## Description:

**HumansVsNations is back!**

The original PR had an issue: only the nations listed in the map’s
`manifest.json` were being spawned, which resulted in completely
unbalanced games.

What did I change with this PR?

- The number of humans and nations is now always the same.
- If a map contains too many nations, we take a random subset.
- If a map doesn’t contain enough nations, we dynamically add additional
ones. These get random spawn locations, and their names are taken from
the new name generator `NationNames.ts`. The name generator was taken
from the closed PR #2245 (idea from @VariableVince).

These changes apply to private lobbies and singleplayer as well. In
singleplayer, you now simply play a 1-vs-1 against a nation.

For public lobbies, we use 50% of the regular team-game player count.
The remaining 50% are nations.

We are also using the Hard difficulty for HumansVsNations.
At the moment, it’s important that nations cheat a little because humans
can donate troops, whereas nations cannot, at least not yet. In the
future, we may make that work.

We might need to adjust the difficulty or do fine-tuning depending on
the humans’ win rate in production. Ideally, we want a ~50% win rate;
otherwise, the mode may become boring. Over time, humans will likely
develop strategies that nations can’t counter, in which case we’ll need
to improve the nation AI.

Here is a screenshot showing that the number of nations now matches the
number of humans in the private lobby UI:

<img width="806" height="304" alt="Screenshot 2025-12-25 004023"
src="https://github.com/user-attachments/assets/cb4ac6f6-13cc-452c-8cc5-7a500670d7f2"
/>

The `PuplicLobby` display was a bit bugged for HumansVsNations:

<img width="532" height="191" alt="Screenshot 2025-12-23 221832"
src="https://github.com/user-attachments/assets/3950bcd9-0072-4c28-b1a0-83c0a24e9b8e"
/>

So I fixed it to look like this;

<img width="532" height="195" alt="Screenshot 2025-12-23 224127"
src="https://github.com/user-attachments/assets/690fc554-b607-4c8a-8b22-0c2912ee671a"
/>

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin

---------

Co-authored-by: iamlewis <lewismmmm@gmail.com>
2025-12-28 21:01:32 -08:00
Achim Marius 5a065d71c5 Fix alliance renewal popup not being removed when alliance is broken (#2722)
Resolves #2464

## Description

This PR fixes a bug where the alliance renewal popup remained visible
after an alliance was broken or betrayed.
The issue occurred because renewal UI events were tied to player
identifiers instead of the unique allianceId.
When a player had multiple alliances, breaking one alliance did not
correctly remove the associated renewal popup.
This change ensures that renewal popups are correctly removed only for
the specific alliance that was broken.


### What was wrong
Alliance renewal UI events were previously associated implicitly with
players.
This caused incorrect behavior when a player had **multiple alliances**,
because **players are not unique identifiers of an alliance**.

As a result, breaking one alliance could leave stale renewal popups
visible.

### What was changed
- Alliance break logic now relies on **allianceId**, not player IDs
- Renewal popups are removed **only for the specific broken alliance**
- Alliances involving the same player but different allianceIds are
unaffected
- Added tests to ensure this bug cannot reappear

### Result
- Renewal popup disappears immediately when an alliance is
betrayed/broken
- No unintended removal of other alliance renewal popups
- Correct behavior even when a player is involved in multiple alliances

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

assessin.
2025-12-28 13:35:05 -08:00
FloPinguin 5d52f73278 The clown is gone! 🤡 Nations send much better emojis now (#2696)
## Description:

Previously, nations just spammed these two rather toxic emojis: 🤡😡

They now send fewer emojis while attacking, and the clown emoji is
reserved for special cases.

They got the ability to send emojis in much more cases:
- Human didn't donate enough for relation update
- Human did donate an ok amount
- Human did donate a lot
- Responding to emojis that they get sent from a human
- Nuke sent
- MIRV sent
- Retaliation warship sent
- Traitor tries to ally
- Threat asks for / accepts an alliance request
- Disliked human tries to ally
- Friendly human tries to ally
- They are getting attacked by very much troops
- They are getting attacked by very little troops
- Congratulating the winner
- Bragging with their crown
- Charming their allies
- Clown-Emoting traitors
- Easteregg: Sending a rat emoji to very small humans

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin

---------

Co-authored-by: iamlewis <lewismmmm@gmail.com>
2025-12-26 13:07:31 -08:00
bibizu 664d66613b fix: Check alliance breakage once at launch, and is deterministic now (#2554)
## Description:

Removes the check to break alliance after nuke is launched, and alliance
breaking is now determined before tiles are randomly chosen for
destruction. (It is now slightly stricter, I believe, as a weighted
average calculation is a little tricky)

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:
bibizu
2025-12-26 12:32:16 -08:00
bijx 677a17d05a Feat: Lemnos Map (#2683)
## Description:

Introduces the Greek island, Lemnos, as a map. The island is both fun
and challenging to play (because of the terrain and elevation) and this
addition was inspired by Altis from the game [Arma
3](https://armedassault.fandom.com/wiki/Altis). The nation names are set
based on the real landmarks, towns, and regions.

<img width="2190" height="1791" alt="image"
src="https://github.com/user-attachments/assets/a7a6de54-f376-43ac-87da-f20aecfebbe0"
/>

<img width="1994" height="1608" alt="image"
src="https://github.com/user-attachments/assets/bc280780-298f-4342-8313-db6cc27ac188"
/>



## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

bijx
2025-12-26 12:15:54 -08:00
YoussfeCantCode 1c52d20e83 Added pause functionality for private multiplayer games (#2657)
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #2491

## Description:
Adds pause/unpause functionality for private multiplayer games. Only the
lobby creator can pause the game, and all players see a pause overlay
when the game is paused.

  **Key features:**
- Lobby creator sees pause/play button in control panel (alongside
existing singleplayer/replay controls)
  - Server validates that only lobby creator can toggle pause
  - All players see "Game paused by Lobby Creator" overlay when paused
  - Game state freezes (no turn execution) while paused
  - Unpause resumes normal gameplay

  **Implementation details:**
- Server-side pause state (`isPaused`) prevents turn execution during
pause
- Each client receives `isLobbyCreator` flag in `GameStartInfo` to
show/hide pause button
- Added `TogglePauseIntent` that broadcasts to all clients via
`NoOpExecution`
  - New `PauseOverlay` component (shows in single player also)

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

furo18

<img width="1459" height="861" alt="Screenshot 2025-12-20 at 15 16 33"
src="https://github.com/user-attachments/assets/f5a3222f-f54b-473c-b0f6-104ce4c1e7a8"
/>
2025-12-26 10:21:18 -08:00
Evan 02a6ac58ea Cleanup unused deployment secrets & args (#2698)
## Description:

* Remove unused otel creds
* Remove unused R2 creds
* remove left-over BASIC_AUTH
* Generate an admin token on startup
* Removed kick_player since lobby creators already have ability to kick
player

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2025-12-25 19:38:17 -08:00
Evan 77908f7a1a Cleanup unused deployment secrets & args (#2698)
## Description:

* Remove unused otel creds
* Remove unused R2 creds
* remove left-over BASIC_AUTH
* Generate an admin token on startup
* Removed kick_player since lobby creators already have ability to kick
player

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2025-12-25 19:34:36 -08:00
FloPinguin e1d0773672 Fix bots no longer attacking humans 🤖 For v28 (#2697)
## Description:

A small number of people are complaining that bots no longer attack them
and that "This has broken the factory farming strat".
In the old #2550 I somehow added that bots on easy difficulty don't
attack humans and nations anymore.
And public games are on easy difficulty now.
But I think the difficulty should actually only change nation behavior,
not bot behavior. Their attacks are harmless anyways.
So lets remove that little check.
Also let `shouldAttack()` return true for bots.

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2025-12-25 16:16:13 -08:00
evanpelle 3a01e15c49 Merge branch 'v28' 2025-12-25 16:03:17 -08:00
FloPinguin 6d2ac30526 Fix bots no longer attacking humans 🤖 (#2690)
## Description:

A small number of people are complaining that bots no longer attack them
and that "This has broken the factory farming strat".
In the old #2550 I somehow added that bots on easy difficulty don't
attack humans and nations anymore.
And public games are on easy difficulty now.
But I think the difficulty should actually only change nation behavior,
not bot behavior. Their attacks are harmless anyways.
So lets remove that little check.
Also let `shouldAttack()` return true for bots.

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2025-12-25 16:01:35 -08:00
Evan a9012a6613 Move cloudflare tunnel creation back into startup.sh (#2694)
## Description:
Reverts #49b01d8

Move cloudflare tunnel creation back into startup.sh. This keeps the
infra outside of the main app.
## Please complete the following:

- [ ] I have added screenshots for all UI updates
- [ ] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [ ] I have added relevant tests to the test directory
- [ ] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2025-12-25 13:24:23 -08:00
FloPinguin 86d1ac6c62 Nations now counter warship infestations 🚢 (#2658)
## Description:

Relevant for singleplayer and HumansVsNations: 
Humans sometimes try to flood the entire ocean with warships. The goal
is to dominate the trade and to block transport ships.

The already existing `trackTransportShipsAndRetaliate` and
`trackTradeShipsAndRetaliate` methods can't stop these large scale
infestations, the nations are completely helpless.

The new `counterWarshipInfestation` method checks if a nation is one of
the top 3 richest players (Enough money for warships) and if any enemy
(or enemy team) has accumulated more than 10 (for teams total 15)
warships, then builds a counter-warship targeting that threat.

This feature only activates on Hard or Impossible difficulty.

Thats how it can look, nations send out a warship every couple of
seconds, until the infestation threat is gone:

<img width="779" height="670" alt="Screenshot 2025-12-20 160600"
src="https://github.com/user-attachments/assets/25040077-e7db-4720-aea4-7c230afe05ea"
/>

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2025-12-24 10:07:44 -08:00
FloPinguin 6afaf932a5 Make easy and medium nations less aggressive 📊 (#2671)
## Description:

1. Players complained that they have problems allying with nations in
the earlygame. So I added an `isEarlygame()` check to
`AllianceBehavior`. This should make the easier difficulties much easier
:)

2. The attack order of nations now depends on the difficulty. Easy and
medium nations got dumbed down, they now take nuked territory before
retaliating against attacks again.

3. The attack rate now depends on the difficulty. Easy nations are
reacting slower than impossible nations (to make sure the number of sent
alliance requests stays the same I removed the difficulty check in
`maybeSendAllianceRequests()`).

4. On easy and medium difficulty nations will sometimes just skip an
attack if the enemy is a human (`shouldAttack()`). But this did not
apply for the nuking logic. Now it does, which makes the easier
difficulties a bit easier.

5. I tuned the `getBotAttackMaxParallelism()` method a bit. The nations
are doing a bit less parallel bot attacks now, which makes the easier
difficulties a bit easier.

6. The settings in MIRVBehavior now depend on the difficulty. On easy
difficulty, nations will only send MIRVs very rarely.

7. Unrelated MIRVBehavior Cleanup: There was a 2 second cooldown and
cache logic. But it was completely useless because `considerMIRV()` is
only called every 4-8 seconds by NationExecution. So I removed it.

8. Unrelated little cleanup: I made a couple of methods `private`

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2025-12-24 03:10:39 +00:00
Mykola 56e497145e Fix nations spawn (#2672)
## Description:

Returned code that spawns nations around predefined coordinates from the
map manifest.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

nikolaj_mykola
2025-12-24 03:07:51 +00:00
Danny 88c6e40399 Remove RNG from SAM launchers (#2665)
## Description:
SAMs will now always hit their target instead of missing sometimes.

Describe the PR.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

Lavodan
2025-12-23 08:08:02 -08:00
scamiv 0e3200d647 Tint territory borders based on player relationships. (#2439)
## Description:

Add visual indicators to territory borders that reflect diplomatic
relationships between players, making it easier to identify relations at
a glance.

### Problem Statement

Currently, players must check diplomatic status through other UI
elements. There's no immediate visual feedback on the map showing which
borders represent embargo or friendly relationships.

### Benefits

1. **Improved Gameplay Clarity**: Quickly identify diplomatic
relationships without opening menus
2. **Strategic Awareness**: Visual feedback helps make tactical
decisions about border defense

### Proposed Solution

Tint territory borders based on neighbor relationships: embargo red,
friendly green


### Implementation Details
- Border variants are based on this._borderColor (theme/style handling
unchanged) computed in the constructor and stored in userSettings
UnitView
- Apply tinting to checkerboard for defended borders
- borderColor() checks all neighbors to determine the worst relationship
status
- Embargos take priority.


<img width="1193" height="601" alt="image"
src="https://github.com/user-attachments/assets/cb516402-4f4b-473c-a31b-02397fee9203"
/>
<img width="959" height="682" alt="image"
src="https://github.com/user-attachments/assets/de01a4b9-0fd4-44b2-895d-96705b6cf30b"
/>

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
2025-12-21 14:57:42 -08:00
Danny 7db8d51bf7 Remove RNG from SAM launchers (#2665)
## Description:
SAMs will now always hit their target instead of missing sometimes.

Describe the PR.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

Lavodan
2025-12-21 22:49:10 +00:00
Aaron Tidwell 9ab1319126 Map Generator Go Code Documentation (#2656)
Resolves #2602

## Description:
tldr: `npm run docs:map-generator`

Adds documentation to the `map-generator` go code.

This has no functional changes, other than the renaming of the package.
I used the github url, though this can be set to anything as long as it
contains a `.` so that the docs parse it correctly. Go doc best
practices seem a little verbose and terse, but attempted to comply

Future Facing (to get these docs viewable without running locally):
- Wait until the -http issue is sorted, then these are easy to
statically host alongside builds
- Could use the legacy `godoc`
- Could do formatting after outputting the `txt` output


## Change List:

- Add documentation to all types/fns in map-generator go code
- Ensure this outputs correctly with `go doc`
- Add `docs:map-generator` command to package.json. This runs `go doc`
in `map-generator` w/ appropriate flags to generate full documentation.
(see notes in readme)
- rename `map-generator` module to work around pkgsite assuming all
packages without a . are stdlib (this makes `-http` work at all)
- Add new sections to README and update existing sections
- Add additional references to locations in the primary code base where
things can be found
- Update documentation in the ts theme files to add output color
mappings - this ensures that everything needed to trace the input file
-> in game rendered asset is fully documented.


## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

tidwell
2025-12-21 14:00:54 -08:00
FloPinguin 183b0ae4cf Fix: Optimize nation random boat targeting by skipping unreachable players 🚢 (#2660)
## Description:

Saw lots of `"cannot send ship to Player"` warnings in the console.
It was caused by `randomBoatTarget` not checking if the target is
reachable by boat.
It also caused the for loop in `randomBoatTarget` to exit too early (=>
no boat sent).
So I added a `canBuildTransportShip` check. Because this runs expensive
(?) pathfinding I added a `unreachablePlayers` Set to optimize
performance.

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2025-12-21 13:17:52 -08:00
Mykola 6112547273 Improve random spawn (#2503)
## Description:

This is a previously approved PR with an additional commit that fixes
case when nations change spawn & jump around, their previous territory
wasn't getting deleted.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

nikolaj_mykola

---------

Co-authored-by: Evan <evanpelle@gmail.com>
2025-12-20 13:35:30 -08:00
bijx 4ee3319397 Feat: Added cursor price option to user and basic settings (#2655)
## Description:

Following the hotkey cursor price textbox addition of #2650, this
feature adds the option to enable and disable the visual feature via the
User Settings menu or the Basic Settings modal in game. Also added a
[new icon](https://thenounproject.com/icon/pay-per-click-2586454/) for
the Basic Settings modal from the Noun Project and added credit for it
to the `CREDITS.md` file.

### Video Demo


https://github.com/user-attachments/assets/1667081e-45e3-4b11-9bda-3f00c341e03c

### User Settings Menu
<img width="1029" height="1436" alt="image"
src="https://github.com/user-attachments/assets/e4e6bf6d-db59-463a-81fb-f622ef6e3931"
/>

### Basic Settings Menu
<img width="964" height="1545" alt="image"
src="https://github.com/user-attachments/assets/6b083655-b96e-4937-95d6-f3458858f03d"
/>



## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

bijx
2025-12-20 11:09:44 -08:00
FloPinguin e554ffb1b0 Cleanup nations (Part 3) 🧹 Remove nation strength (#2649)
## Description:

This PR removes the nation strength. Reasoning:

- It is currently unused. The backstory can be found in #2498
- It forces map-makers to do balancing work, which is probably not a
good idea
- It increases map-making work
- It increases nation balancing complexity by a lot (we need to have all
the json files in mind)
- It makes humans avoid map areas completely because there is always
that one, same, strong nation
- The map lead Nikola123 wants to "not deal with the stupid nations and
their balancing"

If the goal of nation strength was to make them feel different I would
suggest a nation personality system. Nations that love to boat, love to
ally, love to nuke, love to fullsend, etc.

Link to a discord discussion about nation strength:


https://discord.com/channels/1359946986937258015/1360078040222142564/1450973197251117218

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2025-12-19 19:10:01 -08:00
FloPinguin af1e05961c Cleanup nations (Part 2) 🧹 (#2647)
## Description:

1. Moved the currently very small betrayal logic from `AiAttackBehavior`
to `NationAllianceBehavior` because it makes more sense to have it
there.

3. Very small bugfix in `AiAttackBehavior::shouldAttack()`: the numbers
in the two `random.chance` calls were the wrong way round.

4. `NationExecution` was quite big and a lot of it was about MIRVs. So I
moved all the MIRV logic to the new `NationMIRVBehavior`.

5. `emoji()` and `maybeSendEmoji()` did not really fit in
`AiAttackBehavior`. So I moved it to the new `NationEmojiBehavior` (and
did some renaming for clarity). I'm planning to extend that class in a
future PR.

2. Reordered methods in `AiAttackBehavior` to easily find related
methods.
6. Reordered methods in `NationExecution` to easily find related
methods.

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2025-12-19 19:08:37 -08:00
FloPinguin 4d5bb7a835 Cleanup nations (Part 1) 🧹 (#2637)
## Description:

1. Using the wording `"Nation"`, `"FakeHuman"` and `"NPC"` at the same
time is confusing.
So I renamed every mention of `"FakeHuman"` and `"NPC"` in the entire
project to `"Nation"`. Just like they are called ingame.

2. `BotBehavior.ts` was originally intended for sharing the logic
between nations and bots.
But at the moment, the logic there isn't really shared and it's
basically just about attacking.
So I renamed `BotBehavior.ts` to `AiAttackBehavior.ts`. I use "Ai" to
indicate that this file is used by bots AND nations.

3. Moved `execuction/utils/AllianceBehavior.ts` to
`execuction/nation/NationAllianceBehavior.ts` to make sure everybody
understands that this file is not about alliances in general. It's just
about nations and how they handle alliances.

4. Removed `difficultyModifier` from `DefaultConfig`. It's unused and I
think we usually want to finetune the difficulty instead of using that
method.

5. Added `assertNever` in all `switch (difficulty)` default cases.

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
2025-12-18 16:20:23 -08:00
DevelopingTom 507f391aa1 Add Christmas emojis (#2634)
## Description:

Add some christmas spirit in the emoji list
🎁🌟🎅🎄

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

IngloriousTom
2025-12-17 14:18:39 -08:00
evanpelle 5f5176bd39 meta: reduce train gold from allies from 50k => 35k 2025-12-17 12:28:37 -08:00
evanpelle 9edf0349cb bugfix: bomb launch was recorded before the MIRV was constructed, causing it to increase in price before it could be built 2025-12-16 12:31:00 -08:00
FloPinguin 058bb44273 Fix nation relation exploit 🔧 (#2523)
## Description:

Saw this in an Enzo video about beating impossible nations:

You can just donate 1% gold / 1% troops to a nation to get a friendly
relation with them.

This PR adds randomized minimum donation requirements based on the
difficulty.
Randomized in a way that there is a minimum someone has to donate to
surely get the relation improvement, but you can also gamble and send
less.

For troop donations, the minimum is calculated based on what percentage
of their troops the sender donated.

For gold donations, it's fixed values. We cannot use percentages here
because “having nearly no gold” is a usual case. Donating 100% of your
gold wouldn’t hurt if you just spent all your gold on buildings.

I tried to add tests for this but it's really horrible. Because the test
would have to wait until the relation update from the alliance accepting
is gone (we need to have an alliance to send stuff), has returned to
Neutral, and then changes back to Friendly after the donation.

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin

---------

Co-authored-by: Evan <evanpelle@gmail.com>
2025-12-16 09:01:18 -08:00
Danny 58c7cdd46f Task: Unify username validation and remove username sanitation (#2622)
## Description:

This PR centralizes all username validation using UsernameSchema with a
set maximum, minimum, and a regex pattern,

It also removes sanitization, as all places where the username would be
sanitized on the server have been gatekept, so no unvalidated usernames
can get onto the server past the ClientMessageSchema safeParse in
GameServer's on message func.

Here is how the errors look if that happens, Note that if the client is
funtioning correctly and the user doesn't manually send a WS message,
they should never see this. The screenshots are from a debug build where
client uname validation was disabled.
<img height="300" alt="error message too short"
src="https://github.com/user-attachments/assets/1b7ac32c-2f03-40fb-8ce9-1f4ab66100bd"
/>
<img height="300" alt="error message bad regex"
src="https://github.com/user-attachments/assets/c78b4114-7e4b-4d39-a135-4cab3ad52c0b"
/>

Profanity sanitization was not changed.

Additionally, the censor tests were updated to reflect the new
expectations.
Jose was added to the jest config as an allowed transform pattern, as it
didn't make sense to me to mock a zod schema.

The UsernameSchema pattern was set to `^[a-zA-Z0-9_ \[\]üÜ]+$`, I
personally think either we should allow all latin characters (regex has
a pattern for this, `\p{L}` or `\p{sc=Latin}`) and then we'd use some
kind of library to normalize all latin characters into regular ascii for
name filtering, or we should only keep ascii letters.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

Lavodan


(I just realized sanitization isn't a word, it's supposed to be
sanitation, sorry.)
2025-12-15 10:07:15 -08:00
jachisc 690b7e1155 Add Manicouagan Map and Credit OpenTopography (#2620)
## Description:

Adds a map based on the Manicouagan Reservoir in Quebec and credits
OpenTopography

## Checklist:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
<img width="1017" height="1017" alt="Screenshot 2025-12-14 214706"
src="https://github.com/user-attachments/assets/030c4bbd-0325-4da4-bef5-71053dc8f183"
/>

## Discord username:

sehentsin
2025-12-15 09:44:15 -08:00
scamiv aae9c43fa4 perf Optimize removeClusters by replacing sort with linear scan (#2614)
## Description:

PlayerExecution.ts removeClusters:
Replace O(k log k) sorting with O(k) linear scan to find the largest
cluster
2025-12-15 09:43:10 -08:00
Evan 71cf309252 increase mirv price with total number of merged launched (#2621)
## Description:

To prevent MAD stalemates, have the price of MIRVs increase after each
launch. This will encourage players to launch a MIRV once they have
enough money for it. Also reduce the price of the first MIRV to 25
million to reduce snowballing, each subsequent MIRV cost an extra 15
million:

1. 25 million
2. 40 million
3. 60 million
4. etc



## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2025-12-14 19:52:54 -08:00