UNPKG

@nichathan-gaming/map-generator

Version:

Creates and generates a 2 dimensional array with various path generation functions.

135 lines (114 loc) 4.76 kB
import assertIndex from "../helpers/assertIndex.js"; import countNeighbors from "../helpers/countNeighbors.js"; import mapGenerator from "../mapGenerator.js"; import getNextMoves from './getNextMoves.js'; import getWilsonsConnectedIndexes from './getWilsonsConnectedIndexes.js'; import { assertType, basicTypes, assertInstanceOf } from "@nichathan-gaming/assertions"; /** * Walks through the map searching for a possible path at the startIndex then saves the path if it is valid * @param {mapGenerator} map The current game map element * @param {number} maxPathSize The maximum size for the path * @param {[number, number]} startIndex The index that the path begins at * @param {T} possiblePathValue A temporary value that denotes a part of the map that may be the next path * @returns {[number, number][]} indexes that cannot be connected to the main path */ const walk = (map, maxPathSize, startIndex, possiblePathValue) => { assertInstanceOf(map, mapGenerator); assertType(maxPathSize, basicTypes.number); assertIndex(startIndex); map.assertBasicType(possiblePathValue); //get the next moves for the walk let nextMoves = getNextMoves(map, maxPathSize, startIndex, possiblePathValue); //track the paths walked const walkedPath = []; const currentPath = [startIndex]; const badPath = []; let validPath = false; //get connected paths in case the startIndex is also complete const conn = getWilsonsConnectedIndexes( map, startIndex, currentPath, maxPathSize ); //we are connected, finish here if(conn.length > 0){ currentPath.push(conn[0]); validPath = true; } //we don't have any moves here it is a dead path else if (nextMoves.length === 0){ return [startIndex]; }; //we have moves to make, search for a path let nextMove = nextMoves.splice(0, 1)[0]; //add the rest of the moves in case our current move is invalid walkedPath.push(nextMoves); //set the value at this index so it will affect the next move map.setValueAtIndex(startIndex, possiblePathValue); //continue along the path looking for a valid path while(!validPath){ //see if this new move is connected to the main path const conn = getWilsonsConnectedIndexes( map, nextMove, currentPath, maxPathSize ); //path has connected, set the path if( conn.length > 0 && countNeighbors(map, 1, nextMove, map.getWalkableValue(), false) <= maxPathSize ){ currentPath.push(nextMove); currentPath.push(conn[0]); validPath = true; break; }; //path is not connected yet, keep looking for a connection //set this as a path so we count it in getNextMoves map.setValueAtIndex(nextMove, possiblePathValue); //get next moves nextMoves = getNextMoves(map, maxPathSize, nextMove, possiblePathValue); //determine if we can move forward or if we should move back if(nextMoves.length > 0){ //we still have moves that we can make, move forward currentPath.push(nextMove); nextMove = nextMoves.splice(0, 1)[0]; walkedPath.push(nextMoves); } else { //We cannot make any more moves on this path, add to badPath and move back map.setUnwalkableValueAtIndex(nextMove); badPath.push(nextMove); let foundNewPath = false; while(!foundNewPath){ const walkPop = walkedPath.pop(); //we need to do this again if walkPop is not greater than 0 if(walkPop){ if(walkPop.length > 0){ //found next move nextMove = walkPop.splice(0, 1)[0]; walkedPath.push(walkPop); foundNewPath = true; }else{ const poppedCurrentPath = currentPath.pop(); if(poppedCurrentPath) badPath.push(poppedCurrentPath); }; }else{ break; }; }; if(!foundNewPath){ break; }; }; }; if(validPath){ map.setWalkableValueAtIndexes(...currentPath); } else{ map.setUnwalkableValueAtIndexes(...currentPath, ...badPath); }; return badPath; }; export default walk;