175 lines
5.2 KiB
TypeScript
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; |