1
0
peddlers-of-ketran/server/ai/longest-road.ts

175 lines
5.2 KiB
TypeScript

// @ts-nocheck
import { layout } from '../util/layout';
const processCorner = (game: any, color: string, cornerIndex: number, placedCorner: any): number => {
/* If this corner is allocated and isn't assigned to the walking color, skip it */
if (placedCorner.color && placedCorner.color !== color) {
return 0;
}
/* If this corner is already being walked, skip it */
if (placedCorner.walking) {
return 0;
}
placedCorner.walking = true;
/* Calculate the longest road branching from both corners */
let longest = 0;
layout.corners[cornerIndex].roads.forEach((roadIndex: number) => {
const placedRoad = game.placements.roads[roadIndex];
if (!placedRoad) {
return;
}
if (placedRoad.walking) {
return;
}
const tmp = processRoad(game, color, roadIndex, placedRoad);
longest = Math.max(tmp, longest);
/*if (tmp > longest) {
longest = tmp;
placedCorner.longestRoad = roadIndex;
placedCorner.longest
}
longest = Math.max(
*/
});
return longest;
};
const buildCornerGraph = (game: any, color: string, cornerIndex: number, placedCorner: any, set: any) => {
/* If this corner is allocated and isn't assigned to the walking color, skip it */
if (placedCorner.color && placedCorner.color !== color) {
return;
}
/* If this corner is already being walked, skip it */
if (placedCorner.walking) {
return;
}
placedCorner.walking = true;
/* Calculate the longest road branching from both corners */
layout.corners[cornerIndex].roads.forEach((roadIndex: number) => {
const placedRoad = game.placements.roads[roadIndex];
if (!placedRoad) return;
buildRoadGraph(game, color, roadIndex, placedRoad, set);
});
};
const processRoad = (game: any, color: string, roadIndex: number, placedRoad: any): number => {
/* If this road isn't assigned to the walking color, skip it */
if (placedRoad.color !== color) {
return 0;
}
/* If this road is already being walked, skip it */
if (placedRoad.walking) {
return 0;
}
placedRoad.walking = true;
/* Calculate the longest road branching from both corners */
let roadLength = 1;
layout.roads[roadIndex].corners.forEach((cornerIndex) => {
const placedCorner = game.placements.corners[cornerIndex];
if (!placedCorner) return;
if (placedCorner.walking) {
return;
}
roadLength += processCorner(game, color, cornerIndex, placedCorner);
});
return roadLength;
};
const buildRoadGraph = (game: any, color: string, roadIndex: number, placedRoad: any, set: any) => {
/* If this road isn't assigned to the walking color, skip it */
if (placedRoad.color !== color) {
return;
}
/* If this road is already being walked, skip it */
if (placedRoad.walking) {
return;
}
placedRoad.walking = true;
set.push(roadIndex);
/* Calculate the longest road branching from both corners */
layout.roads[roadIndex].corners.forEach((cornerIndex) => {
const placedCorner = game.placements.corners[cornerIndex];
if (!placedCorner) return;
buildCornerGraph(game, color, cornerIndex, placedCorner, set);
});
};
const clearRoadWalking = (game: any) => {
/* Clear out walk markers on roads */
layout.roads.forEach((item, itemIndex) => {
if (game.placements && game.placements.roads && game.placements.roads[itemIndex]) {
delete game.placements.roads[itemIndex].walking;
}
});
/* Clear out walk markers on corners */
layout.corners.forEach((item, itemIndex) => {
if (game.placements && game.placements.corners && game.placements.corners[itemIndex]) {
delete game.placements.corners[itemIndex].walking;
}
});
}
const calculateRoadLengths = (game: any) => {
const color = game.color;
clearRoadWalking(game);
/* Build a set of connected road graphs. Once all graphs are
* constructed, walk through each graph, starting from each
* location in the graph. If the length ever equals the
* number of items in the graph, short circuit--longest path.
* Otherwise, check all paths from each segment. This is
* needed to catch loops where starting from an outside end
* point may result in not counting the length of the loop
*/
let graphs = [];
layout.roads.forEach((_, roadIndex) => {
const placedRoad = game.placements.roads[roadIndex];
if (!placedRoad) return;
if (placedRoad.color === color) {
let set = [];
buildRoadGraph(game, color, roadIndex, placedRoad, set);
if (set.length) {
graphs.push({ color, set });
}
}
});
let final = {
segments: 0,
index: -1,
};
clearRoadWalking(game);
graphs.forEach((graph) => {
graph.longestRoad = 0;
graph.set.forEach((roadIndex) => {
const placedRoad = game.placements.roads[roadIndex];
clearRoadWalking(game);
const length = processRoad(game, color, roadIndex, placedRoad);
if (length >= graph.longestRoad) {
graph.longestStartSegment = roadIndex;
graph.longestRoad = length;
if (length > final.segments) {
final.segments = length;
final.index = roadIndex;
}
}
});
});
game.placements.roads.forEach((road: any) => {
if (road) delete road.walking;
});
return final;
};
export default calculateRoadLengths;