1
0

189 lines
5.3 KiB
TypeScript

import type { Game, Session, Player } from "./types";
import { newPlayer } from "./playerFactory";
export const addActivity = (game: Game, session: Session | null, message: string): void => {
let date = Date.now();
if (!game.activities) game.activities = [] as any[];
if (game.activities.length && game.activities[game.activities.length - 1].date === date) {
date++;
}
game.activities.push({ color: session ? session.color : "", message, date });
if (game.activities.length > 30) {
game.activities.splice(0, game.activities.length - 30);
}
};
export const addChatMessage = (game: Game, session: Session | null, message: string, isNormalChat?: boolean) => {
let now = Date.now();
let lastTime = 0;
if (!game.chat) game.chat = [] as any[];
if (game.chat.length) {
lastTime = game.chat[game.chat.length - 1].date;
}
if (now <= lastTime) {
now = lastTime + 1;
}
const entry: any = {
date: now,
message: message,
};
if (isNormalChat) {
entry.normalChat = true;
}
if (session && session.name) {
entry.from = session.name;
}
if (session && session.color) {
entry.color = session.color;
}
game.chat.push(entry);
if (game.chat.length > 50) {
game.chat.splice(0, game.chat.length - 50);
}
};
export const getColorFromName = (game: Game, name: string): string => {
for (let id in game.sessions) {
const s = game.sessions[id];
if (s && s.name === name) {
return s.color || "";
}
}
return "";
};
export const getLastPlayerName = (game: Game): string => {
const index = (game.playerOrder || []).length - 1;
const color = (game.playerOrder || [])[index];
if (!color) return "";
for (let id in game.sessions) {
const s = game.sessions[id];
if (s && s.color === color) {
return s.name || "";
}
}
return "";
};
export const getFirstPlayerName = (game: Game): string => {
const color = (game.playerOrder || [])[0];
if (!color) return "";
for (let id in game.sessions) {
const s = game.sessions[id];
if (s && s.color === color) {
return s.name || "";
}
}
return "";
};
export const getNextPlayerSession = (game: Game, name: string): Session | undefined => {
let color: string | undefined;
for (let id in game.sessions) {
const s = game.sessions[id];
if (s && s.name === name) {
color = s.color;
break;
}
}
if (!color) return undefined;
const order = game.playerOrder || [];
let index = order.indexOf(color);
if (index === -1) return undefined;
index = (index + 1) % order.length;
const nextColor = order[index];
for (let id in game.sessions) {
const s = game.sessions[id];
if (s && s.color === nextColor) {
return s;
}
}
console.error(`getNextPlayerSession -- no player found!`);
console.log(game.players);
return undefined;
};
export const getPrevPlayerSession = (game: Game, name: string): Session | undefined => {
let color: string | undefined;
for (let id in game.sessions) {
const s = game.sessions[id];
if (s && s.name === name) {
color = s.color;
break;
}
}
if (!color) return undefined;
const order = game.playerOrder || [];
let index = order.indexOf(color);
if (index === -1) return undefined;
index = (index - 1 + order.length) % order.length;
const prevColor = order[index];
for (let id in game.sessions) {
const s = game.sessions[id];
if (s && s.color === prevColor) {
return s;
}
}
console.error(`getPrevPlayerSession -- no player found!`);
console.log(game.players);
return undefined;
};
export const clearPlayer = (player: Player) => {
const color = player.color;
for (let key in player) {
// delete all runtime fields
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete (player as any)[key];
}
// Use shared factory to ensure a single source of defaults
Object.assign(player, newPlayer(color || ""));
};
export const canGiveBuilding = (game: Game): string | undefined => {
if (!game.turn.roll) {
return `Admin cannot give a building until the dice have been rolled.`;
}
if (game.turn.actions && game.turn.actions.length !== 0) {
return `Admin cannot give a building while other actions in play: ${game.turn.actions.join(", ")}.`;
}
return undefined;
};
export const setForRoadPlacement = (game: Game, limits: any): void => {
game.turn.actions = ["place-road"];
game.turn.limits = { roads: limits };
};
export const setForCityPlacement = (game: Game, limits: any): void => {
game.turn.actions = ["place-city"];
game.turn.limits = { corners: limits };
};
export const setForSettlementPlacement = (game: Game, limits: number[] | undefined, _extra?: any): void => {
game.turn.actions = ["place-settlement"];
game.turn.limits = { corners: limits };
};
// Adjust a player's resource counts by a deltas map. Deltas may be negative.
export const adjustResources = (player: Player, deltas: Partial<Record<string, number>>): void => {
if (!player) return;
let total = player.resources || 0;
const keys = Object.keys(deltas || {});
keys.forEach((k) => {
const v = deltas[k] || 0;
// update named resource slot if present
try {
const current = (player as any)[k] || 0;
(player as any)[k] = current + v;
total += v;
} catch (e) {
// ignore unexpected keys
}
});
player.resources = total;
};