Files
zhichun-project/CTF
ydy0615 5e76bb2452 feat(ai): add Map class for pathfinding and speed up world updates
- Remove unused `random` import and introduce `collections` for BFS queue.
- Decrease `GameMap` update interval from 1000 ms to 1 ms and lower `update_threshold` from 100 to 1 for near‑real‑time world state.
- Add thread‑safe lock, timestamp tracking, and rename `player_to_flag_assignments` to `player_to_flag_assign`.
- Introduce `my_side_is_left` flag to differentiate safe‑zone logic.
- Implement new `Map` class:
  * Stores grid, edges, and safe‑zone status.
  * Updates grid with walls, allies, enemies, and safe‑zone handling.
  * Computes adjacency edges respecting obstacles.
  * Provides `guideance` (BFS) to obtain the first movement direction towards a target.
- Overall refactor improves AI flag‑picking speed and decision accuracy.
2025-12-28 11:38:50 +08:00
..
2025-12-27 15:59:21 +08:00
2025-12-27 15:59:21 +08:00
2025-12-27 15:59:21 +08:00
2025-12-27 15:59:21 +08:00

Capture the Flag

Your job is to implement your own algorithm (see backend/server.cpp) to control a team to compete in "Capture the Flag" Game.

Game Rules

Capture the Flag is a popular outdoor game where two teams compete in an open field. Each team has a territory and a set of flags located within the territory. Each team's goal is to collect flags of the opponent team and bring them back to the target area.

A player can tag the opponent team's player within his territory. When tagged, the opponent team's player will be put into the prison. The player will stay in the prison for a period of time, unless he is saved by his teammate earlier. The initial positions of flags, the target area and the prison are within the team's territory. A player can only pick the flags of the opponent team. That is, he cannot pick up his team's flag and put it in a different place.

Our game has two teams: "L" and "R" team. The field is a rectangle area, where the left half is "L" team's territory and the other is "R" team's. There are obstacles and walls within the map.

Capture The Flag Map

Play

The game consists of 2 parts:

  • frontend/: starts the game web server, written in Javascript. It optionally connects to 2 backend servers to move the players. You should NOT change the code, but you may read the code to understand how it generates the map and communicates with the backend.
  • backend/: is the backend server which sends back instructions to frontend to move players. This is where you implement your algorithms. Note that in real competition, your server controls one team and the other is your opponent team's implementation.

To play it manually, you can use w a s d keys to control L team and ↑ ← ↓ → keys to control R team. The keys override backend server's decisions. Note that the pressed keys move all players in one direction while your code can move each player independently.

Press SPACE KEY to start, pause or continue the game.

  1. Install dependency
brew update;
brew install boost nlohmann-json
  1. Compile server.cpp
cd backend/;
g++ -std=c++17 server.cpp -I/opt/homebrew/include -L/opt/homebrew/lib -lpthread -o server
  1. Run server on port 8081 (can run on other ports)
./server 8081
  1. Update assets/remote_config.json to the local port. Update ws_url with your port.
{
  "teams": [
    { "name": "L", "ws_url": "ws://localhost:8080" },
    { "name": "R", "ws_url": "ws://localhost:8081" }
  ]
}
  1. Start frontend website
cd frontend/;
python3 -m http.server 8000
  1. In your browser, open "http://localhost:8000/index.html" to play.
    • Press (Cmd + Option + I on macOS) to open DevTools
    • Go to the Network tab
    • Check “Disable cache” (upper-left toolbar) to ensure all your updated remote_config.json is loaded properly.

Your Job

In backend/server.cpp, your need to implement startGame(req) and planNextActions(req, ws) functions.

  • startGame(req) is called once when the game starts. req contains the game information, such as map (e.g., height, width, obstacle positions) and team (e.g., name, number of players and number of flags).
  • planNextActions(req, ws) is called periodically to update you all the player and flags' information. You should use ws to send back the actions taken for your team player. The current implementation returns random actions for every team player.
  • gameOver(req) is called once the game finishes and a winner is determined. You may clean up the state for the next startGame.

Write up (Important!)

You must submit a markdown writeup consisting of the following:

  1. The top 3-5 "strategic" decisions to compete against the opponents? Explain the intuition, the core idea and the technical details (such as the data structure & algorithms).
  2. Some interesting and funny moments when you are testing your implementations, or competing with your friends. What changes did you make after the test?

Sample Team (in Python)

We provide a "not-so-dummy" python backend as a competitive opponent for you to develop your own algorithm. DO NOT translate the python algorithm into C++ as your own implementation. To run the python example,

python3 pick_closest_flag.py 8081

You'll need to pip3 install dependency, such as asyncio.