const layout = require('./layout.js'); const isRuleEnabled = (game, rule) => { return rule in game.rules && game.rules[rule].enabled; }; const getValidRoads = (game, color) => { const limits = []; /* For each road, if the road is set, skip it. * If no color is set, check the two corners. If the corner * has a matching color, add this to the set. Otherwise skip. */ layout.roads.forEach((road, roadIndex) => { if (game.placements.roads[roadIndex].color) { return; } let valid = false; for (let c = 0; !valid && c < road.corners.length; c++) { const corner = layout.corners[road.corners[c]], cornerColor = game.placements.corners[road.corners[c]].color; /* Roads do not pass through other player's settlements */ if (cornerColor && cornerColor !== color) { continue; } for (let r = 0; !valid && r < corner.roads.length; r++) { /* This side of the corner is pointing to the road being validated. Skip it. */ if (corner.roads[r] === roadIndex) { continue; } if (game.placements.roads[corner.roads[r]].color === color) { valid = true; } } } if (valid) { limits.push(roadIndex); } }); return limits; } const getValidCorners = (game, color, type) => { const limits = []; /* For each corner, if the corner already has a color set, skip it if type * isn't set. If type is set, if it is a match, and the color is a match, * add it to the list. * * If we are limiting based on active player, a corner is only valid * if it connects to a road that is owned by that player. * * If no color is set, walk each road that leaves that corner and * check to see if there is a settlement placed at the end of that road * * If so, this location cannot have a settlement. * * If still valid, and we are in initial settlement placement, and if * Volcano is enabled, verify the tile is not the Volcano. */ layout.corners.forEach((corner, cornerIndex) => { const placement = game.placements.corners[cornerIndex]; if (type) { if (placement.color === color && placement.type === type) { limits.push(cornerIndex); } return; } if (placement.color) { return; } let valid; if (!color) { valid = true; /* Not filtering based on current player */ } else { valid = false; for (let r = 0; !valid && r < corner.roads.length; r++) { valid = game.placements.roads[corner.roads[r]].color === color; } } for (let r = 0; valid && r < corner.roads.length; r++) { const road = layout.roads[corner.roads[r]]; for (let c = 0; valid && c < road.corners.length; c++) { /* This side of the road is pointing to the corner being validated. * Skip it. */ if (road.corners[c] === cornerIndex) { continue; } /* There is a settlement within one segment from this * corner, so it is invalid for settlement placement */ if (game.placements.corners[road.corners[c]].color) { valid = false; } } } if (valid) { /* During initial placement, if volcano is enabled, do not allow * placement on a corner connected to the volcano (robber starts * on the volcano) */ if (!(game.state === 'initial-placement' && isRuleEnabled(game, 'volcano') && layout.tiles[game.robber].corners.indexOf(cornerIndex) !== -1 )) { limits.push(cornerIndex); } } }); return limits; } module.exports = { getValidCorners, getValidRoads, isRuleEnabled };