catan-board-generator
Version:
A React component for generating Catan board layouts.
202 lines (201 loc) • 7.82 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateExpansionBoard = exports.generateCatanBoard = void 0;
// Mapping of each tile to its neighbors based on their indices
var neighbors = {
// Each key is a tile index, and its value is an array of indices of neighboring tiles
0: [1, 10, 11],
1: [0, 2, 11, 12],
2: [1, 12, 13],
10: [0, 11, 20, 21],
11: [0, 1, 10, 12, 21, 22],
12: [1, 2, 11, 13, 22, 23],
13: [2, 12, 23, 24],
20: [10, 21, 30],
21: [10, 11, 20, 22, 30, 31],
22: [11, 12, 21, 23, 31, 32],
23: [12, 13, 22, 24, 32, 33],
24: [13, 23, 33],
30: [20, 21, 31, 40],
31: [21, 22, 30, 32, 40, 41],
32: [22, 23, 31, 33, 41, 42],
33: [23, 24, 32, 42],
40: [30, 31, 41],
41: [31, 32, 40, 42],
42: [32, 33, 41],
};
var expandedNeighbors = {
0: [1, 10, 11],
1: [0, 2, 11, 12],
2: [1, 12, 13],
10: [0, 11, 20, 21],
11: [0, 1, 10, 12, 21, 22],
12: [1, 2, 11, 13, 22, 23],
13: [2, 12, 23, 24],
20: [10, 21, 30, 31],
21: [10, 11, 20, 22, 31, 32],
22: [11, 12, 21, 23, 32, 33],
23: [12, 13, 22, 24, 33, 34],
24: [13, 23, 34, 35],
30: [20, 31, 40],
31: [20, 21, 30, 32, 40, 41],
32: [21, 22, 31, 33, 41, 42],
33: [22, 23, 32, 34, 42, 43],
34: [23, 24, 33, 35, 43, 44],
35: [24, 34, 44],
40: [30, 31, 41, 50],
41: [31, 32, 40, 42, 50, 51],
42: [32, 33, 41, 43, 51, 52],
43: [33, 34, 42, 44, 52, 53],
44: [34, 35, 43, 53],
50: [40, 41, 51, 60],
51: [41, 42, 50, 52, 60, 61],
52: [42, 43, 51, 53, 61, 62],
53: [43, 44, 52, 62],
60: [50, 51, 61],
61: [51, 52, 60, 62],
62: [52, 53, 61]
};
// Function to shuffle an array in place
function shuffleArray(array) {
var _a;
// Loop backwards through the array
for (var i = array.length - 1; i > 0; i--) {
// Pick a random index before the current one
var j = Math.floor(Math.random() * (i + 1));
// Swap elements at indices i and j
_a = [array[j], array[i]], array[i] = _a[0], array[j] = _a[1];
}
}
// Function to determine the next index, with special cases
function incrementCounter(num, expansion) {
// Map of special cases where the next index jumps ahead
var nextIndexMap;
if (expansion) {
nextIndexMap = { 2: 10, 13: 20, 24: 30, 35: 40, 44: 50, 53: 60 };
}
else {
nextIndexMap = { 2: 10, 13: 20, 24: 30, 33: 40 };
}
// Return the mapped value if it exists, otherwise increment by 1
return nextIndexMap[num] !== undefined ? nextIndexMap[num] : num + 1;
}
// Function to fill the board with resources
function fillResources(board, expansion) {
// Array of tiles to be distributed on the board
var tiles = ['Wood', 'Wood', 'Wood', 'Wood', 'Brick', 'Brick', 'Brick', 'Wheat', 'Wheat', 'Wheat', 'Wheat', 'Sheep', 'Sheep', 'Sheep', 'Sheep', 'Ore', 'Ore', 'Ore', 'Desert'];
if (expansion) {
tiles = ['Wood', 'Wood', 'Wood', 'Wood', 'Wood', 'Wood', 'Brick', 'Brick', 'Brick', 'Brick', 'Brick', 'Wheat', 'Wheat', 'Wheat', 'Wheat', 'Wheat', 'Wheat', 'Sheep', 'Sheep', 'Sheep', 'Sheep', 'Sheep', 'Sheep', 'Ore', 'Ore', 'Ore', 'Ore', 'Ore', 'Desert', 'Desert'];
}
// Shuffle the tiles to randomize their distribution
shuffleArray(tiles);
// Iterator for placing tiles on the board
var itr = 0;
// Loop until all tiles are placed
while (tiles.length > 0) {
// Place the tile on the board and set its number to 0 initially
board[Math.floor(itr / 10)][itr % 10] = { resource: tiles.pop() || 'Desert', number: 0 };
// Move to the next index, with special cases handled by incrementCounter
itr = incrementCounter(itr, expansion);
}
}
// Helper function for fillNumbers to check if the board's number distribution follows the game's rules
function checkNeighbors(board, expansion) {
var neighborMap = expansion ? expandedNeighbors : neighbors;
var limit = expansion ? 62 : 42;
var itr = 0;
// Iterator for checking each tile
// Loop through all possible tile positions
while (itr <= limit) {
// Get the current tile
var tile = board[Math.floor(itr / 10)][itr % 10];
// Check all neighbors for rule violations
for (var _i = 0, _a = neighborMap[itr]; _i < _a.length; _i++) {
var neighborNum = _a[_i];
var neighbor = board[Math.floor(neighborNum / 10)][neighborNum % 10];
// Return false if a rule is violated
if (tile.resource === "Desert" && neighbor.resource === "Desert") {
fillResources(board, true);
return checkNeighbors(board, true);
}
if (neighbor.number === tile.number ||
((tile.number === 6 || tile.number === 8) && (neighbor.number === 6 || neighbor.number === 8)) ||
((tile.number === 2 || (tile.number === 12)) && (neighbor.number === 2 || neighbor.number === 12))) {
return false;
}
}
// Move to the next tile
itr = incrementCounter(itr, expansion);
}
// Return true if all tiles pass the checks
return true;
}
// Function to fill the board with numbers, ensuring no rule violations
function fillNumbers(board, expansion) {
// Flag to indicate a valid configuration has been found
var valid = false;
// Loop until a valid configuration is found
while (!valid) {
// Array of numbers to be distributed on the board
var numbers = [2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10, 11, 11, 12];
if (expansion) {
numbers = [2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12];
}
// Shuffle the numbers to randomize their distribution
shuffleArray(numbers);
// Iterator for placing numbers on the board
var itr = 0;
// Loop until all numbers are placed
while (numbers.length > 0) {
// Calculate row and index within the row for the current number
var row = Math.floor(itr / 10);
var index = itr % 10;
// Skip desert tiles when assigning numbers
if (board[row][index].resource !== "Desert") {
board[row][index].number = numbers.pop() || 0;
}
// Move to the next index
itr = incrementCounter(itr, expansion);
}
// Check if the current configuration is valid
valid = checkNeighbors(board, expansion);
}
}
// Main function to generate a Catan board
function generateCatanBoard() {
// Initialize the board with empty rows of varying lengths
var board = [
new Array(3).fill(null),
new Array(4).fill(null),
new Array(5).fill(null),
new Array(4).fill(null),
new Array(3).fill(null)
];
// Fill the board with resources and then numbers
fillResources(board, false);
fillNumbers(board, false);
// Return the completed board
return board;
}
exports.generateCatanBoard = generateCatanBoard;
// Main function to generate a Catan board
function generateExpansionBoard() {
// Initialize the board with empty rows of varying lengths
var board = [
new Array(3).fill(null),
new Array(4).fill(null),
new Array(5).fill(null),
new Array(6).fill(null),
new Array(5).fill(null),
new Array(4).fill(null),
new Array(3).fill(null)
];
// Fill the board with resources and then numbers
fillResources(board, true);
fillNumbers(board, true);
// Return the completed board
return board;
}
exports.generateExpansionBoard = generateExpansionBoard;
var board = generateExpansionBoard();
console.log(board);
;