Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e065007
seems like the socket connection from the frontend simulator to backe…
MahdMalik Feb 14, 2026
2bab495
took forever, but fixed the issue of simulator not updating when the …
MahdMalik Feb 15, 2026
c40271a
gonna merge having piece type attributes into this for my next ingeni…
MahdMalik Feb 15, 2026
5d6256f
Piece type attribute (#269)
MahdMalik Feb 15, 2026
b847ac9
got the FEIN algorithm done for dynamically determinign robot default…
MahdMalik Feb 15, 2026
4e9d530
fixed issue with board not being updated when default position was tu…
MahdMalik Feb 15, 2026
1e41d47
alright checked everything, this should be good to push now
MahdMalik Feb 16, 2026
4a0c992
added comments and ran the format + link checker
MahdMalik Feb 16, 2026
1449c69
finished making changes
MahdMalik Feb 21, 2026
17c3867
Merge branch 'main' of https://github.com/Comet-Robotics/chessbots-se…
MahdMalik Feb 21, 2026
47c8e72
Merge branch 'main' of https://github.com/Comet-Robotics/chessbots-se…
MahdMalik Feb 21, 2026
2a43ff6
Merge branch 'main' of https://github.com/Comet-Robotics/chessbots-se…
MahdMalik Feb 21, 2026
e384217
Merge branch 'main' of https://github.com/Comet-Robotics/chessbots-se…
MahdMalik Feb 21, 2026
2da6c0e
fixed two issues
MahdMalik Feb 21, 2026
bf13bd4
queue works!
MahdMalik Feb 21, 2026
3ea21fc
fixed lint and format error
MahdMalik Feb 21, 2026
e114312
ok now fixed
MahdMalik Feb 21, 2026
7075c51
found an error with black side queen castling lol. Fixed now. I reall…
MahdMalik Feb 23, 2026
0d39d95
a couple qualms about the shimmying algo, but it's not blatantly obvi…
MahdMalik Feb 23, 2026
078db32
add formatting
MahdMalik Feb 23, 2026
c12d8ff
goo goo ga ga
MahdMalik Feb 23, 2026
4763e68
goo goo ga ga
MahdMalik Feb 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/client/editor/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ export function Editor() {
startIdx,
endIdx + 1,
);
console.log(selectedEvents);
// console.log(selectedEvents);

await navigator.clipboard.writeText(
JSON.stringify(selectedEvents),
Expand Down
13 changes: 5 additions & 8 deletions src/client/puzzle/setup-puzzle.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useState } from "react";
import { SetupBase } from "../setup/setup-base";
import { SelectPuzzle } from "./select-puzzle";
import { NonIdealState, Spinner } from "@blueprintjs/core";
import { get, useEffectQuery } from "../api";
Expand Down Expand Up @@ -29,12 +28,10 @@ export function SetupPuzzle() {
}

return (
<SetupBase>
<SelectPuzzle
puzzles={data}
selectedPuzzle={selectedPuzzle}
onPuzzleSelected={setSelectedPuzzle}
/>
</SetupBase>
<SelectPuzzle
puzzles={data}
selectedPuzzle={selectedPuzzle}
onPuzzleSelected={setSelectedPuzzle}
/>
);
}
24 changes: 11 additions & 13 deletions src/server/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ let canReloadQueue = true;
export const websocketHandler: WebsocketRequestHandler = (ws, req) => {
// on close, delete the cookie id
ws.on("close", () => {
console.log("We closed the connection");
socketManager.handleSocketClosed(req.cookies.id);
console.log(`We closed the connection of ${req.cookies.id}`);
socketManager.handleSocketClosed(req.cookies.id, ws);

//if you reload and the game is over
if (gameManager?.isGameEnded() && canReloadQueue) {
Expand Down Expand Up @@ -172,7 +172,7 @@ export const websocketHandler: WebsocketRequestHandler = (ws, req) => {

//wait in case the client is just reloading or disconnected instead of leaving
setTimeout(() => {
if (socketManager.getSocket(req.cookies.id) === undefined) {
if (socketManager.getSockets(req.cookies.id) === undefined) {
//remove the person from the queue to free up space
queue.popInd(queue.find(req.cookies.id));
names.delete(req.cookies.id);
Expand Down Expand Up @@ -228,16 +228,14 @@ export const websocketHandler: WebsocketRequestHandler = (ws, req) => {
const message = parseMessage(data.toString());
console.log("Received message: " + message.toJson());

// take out that page value, add a delimeter
// // add current page to the cookie id
// const finalSocketId = pageValue.concat(req.cookies.id);

if (message instanceof RegisterWebsocketMessage) {
console.log(`Register a new socket with request ${req.url}`);
//find in the url where we specify the page
const cutoffIndex = req.url.indexOf("page=") + 5;
// take out that page value, add a delimeter
const pageValue = req.url.substring(cutoffIndex) + "|o|o|";
// add current page to the cookie id
const finalSocketId = pageValue.concat(req.cookies.id);

socketManager.registerSocket(finalSocketId, ws);
console.log(`Register a new socket with request ${req.cookies.id}`);

socketManager.registerSocket(req.cookies.id, ws);
} else if (
message instanceof GameInterruptedMessage ||
message instanceof MoveMessage ||
Expand All @@ -246,7 +244,6 @@ export const websocketHandler: WebsocketRequestHandler = (ws, req) => {
message instanceof GameFinishedMessage ||
message instanceof GameEndMessage
) {
// TODO: Handle game manager not existing
await gameManager?.handleMessage(message, req.cookies.id);
} else if (message instanceof DriveRobotMessage) {
await doDriveRobot(message);
Expand Down Expand Up @@ -373,6 +370,7 @@ apiRouter.get("/game-state", (req, res) => {
* returns a success message
*/
apiRouter.post("/start-computer-game", async (req, res) => {
console.log("start comp game");
canReloadQueue = true;
const side = req.query.side as Side;
const difficulty = parseInt(req.query.difficulty as string) as Difficulty;
Expand Down
32 changes: 18 additions & 14 deletions src/server/api/client-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ export class ClientManager {
* get the host's socket
* @returns the host socket
*/
public getHostSocket(): WebSocket | undefined {
public getHostSocket(): Set<WebSocket> | undefined {
if (this.hostId !== undefined) {
return this.socketManager.getSocket(this.hostId);
return this.socketManager.getSockets(this.hostId);
}
return undefined;
}
Expand All @@ -33,11 +33,11 @@ export class ClientManager {
* @returns if the socket was found
*/
public sendToHost(message: Message): boolean {
const socket = this.getHostSocket();
if (socket !== undefined) {
socket.send(message.toJson());
const sockets = this.getHostSocket();
if (sockets !== undefined) {
for (const socket of sockets) socket.send(message.toJson());
}
return socket !== undefined;
return sockets !== undefined;
}

/**
Expand All @@ -46,11 +46,11 @@ export class ClientManager {
* @returns if the socket was found
*/
public sendToClient(message: Message): boolean {
const socket = this.getClientSocket();
if (socket !== undefined) {
socket.send(message.toJson());
const sockets = this.getClientSocket();
if (sockets !== undefined) {
for (const socket of sockets) socket.send(message.toJson());
}
return socket !== undefined;
return sockets !== undefined;
}

/**
Expand All @@ -61,8 +61,12 @@ export class ClientManager {
public sendToSpectators(message: Message): boolean {
if (this.spectatorIds.size !== 0) {
for (const item of this.spectatorIds) {
if (this.socketManager.getSocket(item))
this.socketManager.getSocket(item).send(message.toJson());
const potentialSocket = this.socketManager.getSockets(item);
if (potentialSocket !== null && potentialSocket !== undefined) {
for (const socket of potentialSocket) {
socket.send(message.toJson());
}
}
}
return true;
}
Expand All @@ -73,9 +77,9 @@ export class ClientManager {
* get the client socket
* @returns the socket of the client
*/
public getClientSocket(): WebSocket | undefined {
public getClientSocket(): Set<WebSocket> | undefined {
if (this.clientId !== undefined) {
return this.socketManager.getSocket(this.clientId);
return this.socketManager.getSockets(this.clientId);
}
return undefined;
}
Expand Down
5 changes: 4 additions & 1 deletion src/server/api/game-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ export class HumanGameManager extends GameManager {
* @param id - id of the sender
*/
public async handleMessage(message: Message, id: string): Promise<void> {
// console.log("handling message");

// check which type the id is
const clientType = this.clientManager.getClientType(id);
let sendToPlayer: SendMessage;
Expand Down Expand Up @@ -148,14 +150,15 @@ export class HumanGameManager extends GameManager {
const ids = this.clientManager.getIds();
const currentSave = SaveManager.loadGame(id);
// update the internal chess object if it is a move massage and game not paused
console.log("up to here");
if (message instanceof MoveMessage && !gamePaused) {
// Call path materializer and send to bots
const command = materializePath(message.move);

this.chess.makeMove(message.move);

console.log("running executor");
console.dir(command, { depth: null });
// console.dir(command, { depth: null });
await executor.execute(command).catch((reason) => {
setPaused(true);
console.log(reason);
Expand Down
35 changes: 23 additions & 12 deletions src/server/api/socket-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,46 @@ import type { Message } from "../../common/message/message";
* A class which maps player client ids to their corresponding websocket (if any).
*/
export class SocketManager {
constructor(private sockets: Record<string, WebSocket>) {}
constructor(private sockets: Record<string, Set<WebSocket>>) {}

public registerSocket(id: string, socket: WebSocket): void {
if (this.sockets[id] === null || this.sockets[id] === undefined) {
this.sockets[id] = new Set<WebSocket>();
}
console.log(`Id is: ${id}`);
this.sockets[id] = socket;
this.sockets[id].add(socket);
}

/**
* deletes the socket at the provided id
* @param id - id to be deleted
*/
public handleSocketClosed(id: string): void {
delete this.sockets[id];
public handleSocketClosed(id: string, socket: WebSocket): void {
// find if the socket exists and is in the set for that user
if (this.sockets[id] && this.sockets[id].has(socket)) {
// if so, KILL IT!
this.sockets[id].delete(socket);
return;
}
}

/**
* gets the socket at the provided id
* gets the socket at the provided id, which may be multiple if they have multiple tabs open
* @param id - id of the desired socket
*/
public getSocket(id: string): WebSocket {
return this.sockets[id];
public getSockets(id: string): Set<WebSocket> | undefined {
if (this.sockets[id]) return this.sockets[id];
return undefined;
}

/**
* Sends a message to a socket with the specified id.
* Returns true if the message was sent successfully, and false otherwise.
*/
public sendToSocket(id: string, message: Message): boolean {
const socket = this.getSocket(id);
if (socket !== undefined) {
socket.send(message.toJson());
const sockets = this.getSockets(id);
if (sockets !== undefined) {
for (const socket of sockets) socket.send(message.toJson());
return true;
}
return false;
Expand All @@ -49,8 +58,10 @@ export class SocketManager {
public sendToAll(message: Message): boolean {
const sockets = Object.values(this.sockets);
console.log(`Current list of connections are: ${sockets.length}`);
for (const socket of sockets) {
socket.send(message.toJson());
for (const socketSet of sockets) {
for (const socket of socketSet) {
socket.send(message.toJson());
}
}
return true;
}
Expand Down
12 changes: 8 additions & 4 deletions src/server/robot/path-materializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ function findShimmyLocation(
collisionType: CollisionType,
): Position {
const shimmyPos: Position = robotManager.getRobot(pieceId).position;
const axisShimmyAmount: number = 1 / 3;
const axisShimmyAmount: number = 1 / 2;
switch (collisionType) {
// Horizontal
case CollisionType.HORIZONTAL: {
Expand Down Expand Up @@ -490,6 +490,8 @@ function moveToDeadZone(origin: GridIndices): GridMove {
];

collisionTuple.sort((a, b) => a[1].length - b[1].length);
console.log("Collision decision:");
console.log(collisionTuple[0]);
return collisionTuple[0][0];
}

Expand Down Expand Up @@ -522,7 +524,7 @@ function returnToHome(from: GridIndices, id: string): SequentialCommandGroup {
//const capturedPiece: GridIndices = GridIndices.squareToGrid(from);
const home: GridIndices = robotManager.getRobot(id).homeIndices;
const fastestMoveToDeadzone = moveToDeadZone(from);
const toDeadzone = moveMainPiece(fastestMoveToDeadzone, true);
const toDeadzone = moveMainPiece(fastestMoveToDeadzone);

const startInDeadzone = fastestMoveToDeadzone.to;
let finalDestination: GridIndices | undefined;
Expand Down Expand Up @@ -1168,11 +1170,13 @@ export function materializePath(move: Move): Command {
rookPiece.id,
Position.fromGridIndices(new GridIndices(7, 2)),
);
} else {
}
// black side castling
else {
rookPiece = robotManager.getRobotAtIndices(new GridIndices(9, 9));
kingMove = new AbsoluteMoveCommand(
robotManager.getRobotAtIndices(moveToGridMove(move).from).id,
Position.fromGridIndices(new GridIndices(9, 8)),
Position.fromGridIndices(new GridIndices(8, 9)),
);
rookMove1 = new AbsoluteMoveCommand(
rookPiece.id,
Expand Down