27 return {-1, 0, 0, -1};
35 for (
size_t i = 0; i < tile.
playerIds.size(); i++) {
36 if (!s.empty()) s +=
" ";
42 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
43 for (
int c = 0; c < tile.
resources[type]; c++) {
44 if (!s.empty()) s +=
" ";
57 [
this, connectionId, playerId] {
58 if (!_world.getPlayers().count(playerId)) {
59 _executeNext(connectionId);
65 switch (p.orientation) {
92 [
this, connectionId, playerId] {
93 if (!_world.getPlayers().count(playerId)) {
94 _executeNext(connectionId);
111 [
this, connectionId, playerId] {
112 if (!_world.getPlayers().count(playerId)) {
113 _executeNext(connectionId);
129 [
this, connectionId, playerId] {
130 if (!_world.getPlayers().count(playerId)) {
131 _executeNext(connectionId);
136 int tileCount = (p.level + 1) * (p.level + 1);
139 for (
int i = 0; i < tileCount; i++) {
141 while ((d + 1) * (d + 1) <= i) d++;
142 int xRel = i - d * d - d;
144 int dx = d * look.fx + xRel * look.rx;
145 int dy = d * look.fy + xRel * look.ry;
147 if (i > 0) r +=
", ";
163 std::chrono::milliseconds(delayMs /
_clock.
freq()), [
this, connectionId, playerId] {
164 if (!_world.getPlayers().count(playerId)) {
165 _executeNext(connectionId);
170 std::string r =
"[ food " + std::to_string(p.inventory.food) +
", linemate " +
171 std::to_string(p.inventory.linemate) +
", deraumere " +
172 std::to_string(p.inventory.deraumere) +
", sibur " +
173 std::to_string(p.inventory.sibur) +
", mendiane " +
174 std::to_string(p.inventory.mendiane) +
", phiras " +
175 std::to_string(p.inventory.phiras) +
", thystame " +
176 std::to_string(p.inventory.thystame) +
" ]\n";
190 if (!_world.getPlayers().count(playerId)) {
191 _executeNext(connectionId);
196 if (pid == playerId)
continue;
199 _clients.
send(dst.connectionId,
"message " + std::to_string(dir) +
"," + msg +
"\n");
213 [
this, connectionId, playerId] {
214 if (!_world.getPlayers().count(playerId)) {
215 _executeNext(connectionId);
230 std::chrono::milliseconds(delayMs /
_clock.
freq()), [
this, connectionId, playerId] {
231 if (!_world.getPlayers().count(playerId)) {
232 _executeNext(connectionId);
237 if (result.ejectedPlayerIds.empty()) {
243 for (
int eid : result.ejectedPlayerIds) {
247 ejected.orientation);
248 _clients.
send(ejected.connectionId,
"eject: " + std::to_string(dir) +
"\n");
262 [
this, connectionId, playerId, resource] {
263 if (!_world.getPlayers().count(playerId)) {
264 _executeNext(connectionId);
281 [
this, connectionId, playerId, resource] {
282 if (!_world.getPlayers().count(playerId)) {
283 _executeNext(connectionId);
298 int delayMs = 300000;
311 for (
int pid : *participants)
315 std::chrono::milliseconds(delayMs /
_clock.
freq()),
316 [
this, connectionId, participants = *participants, x, y] {
320 for (
int pid : participants) {
321 auto it = players.find(pid);
322 if (it == players.end())
continue;
326 "Current level: " + std::to_string(it->second.level) +
"\n");
static LookVectors _lookForwardRight(Orientation o)
static std::string _tileContent(const Tile &tile)
Orientation turnRight(Orientation o)
Orientation turnLeft(Orientation o)
ResourceType
Enumerate the different types of resources in the game.
static std::string res(const Resources &r)
int broadcastDirection(int srcX, int srcY, int dstX, int dstY, int mapW, int mapH, Orientation dstFacing)
void send(int connectionId, const std::string &msg)
Queue msg to be sent to a client (flushed during poll()).
Connection & getConnection(int connectionId)
Access the underlying Connection (e.g. to set its type/playerId).
void _handleFork(int connectionId)
void _handleIncantation(int connectionId)
void _handleTake(int connectionId, ResourceType resource)
void _handleLeft(int connectionId)
void _handleLook(int connectionId)
void _executeNext(int connectionId)
Run the next queued AI command (or go idle if none left).
void _handleForward(int connectionId)
void _handleInventory(int connectionId)
void _handleBroadcast(int connectionId, const std::string &msg)
void _handleRight(int connectionId)
void _handleSet(int connectionId, ResourceType resource)
void _handleEject(int connectionId)
int playerId() const
Player this connection drives (-1 for GUI / not yet assigned).
static std::string get_name(int index)
static constexpr int TYPE_COUNT
void schedule(std::chrono::milliseconds delay, std::function< void()> cb)
bool takeResource(int playerId, ResourceType type)
void movePlayer(int id, int x, int y)
bool finalizeIncantation(int x, int y, const std::vector< int > &participantIds)
Finalize an incantation after the 300/f second delay. Re-checks prerequisites. On success,...
const std::unordered_map< int, Player > & getPlayers() const
void turnPlayer(int id, Orientation orientation)
Tile & at(int x, int y)
Access a tile by position. Map is toroidal, coordinates wrap.
EjectResult ejectPlayers(int ejectorId)
void playerBroadcast(int playerId, const std::string &message)
Fire onBroadcast to observers (GUI animation, logging). No state change.
bool setResource(int playerId, ResourceType type)
std::optional< std::vector< int > > startIncantation(int playerId)
Validate and start an incantation for playerId. Returns the list of participant IDs on success,...
Player & getPlayer(int id)
Represents a tile on the game map, containing resources, player IDs, and egg IDs.
std::vector< int > playerIds