feat(slay-the-spire-like): add map navigation logic
Implement `canMoveTo` and `moveToNode` for navigating the point crawl map, and add `PointCrawlMapNavigator` type. Also reformat map module files to use double quotes.
This commit is contained in:
parent
88d31430a6
commit
423cc7c841
|
|
@ -1,5 +1,18 @@
|
||||||
export { MapNodeType, MapLayerType } from './types';
|
export { MapNodeType, MapLayerType } from "./types";
|
||||||
export type { MapNode, MapLayer, PointCrawlMap, MapGenerationConfig } from './types';
|
export type {
|
||||||
|
MapNode,
|
||||||
|
MapLayer,
|
||||||
|
PointCrawlMap,
|
||||||
|
MapGenerationConfig,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
export { generatePointCrawlMap } from './generator';
|
export { generatePointCrawlMap } from "./generator";
|
||||||
export { getNode, getChildren, getParents, hasPath, findAllPaths } from './generator';
|
export {
|
||||||
|
getNode,
|
||||||
|
getChildren,
|
||||||
|
getParents,
|
||||||
|
hasPath,
|
||||||
|
findAllPaths,
|
||||||
|
} from "./generator";
|
||||||
|
|
||||||
|
export { canMoveTo, moveToNode } from "./navigation";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { getNode } from "./generator";
|
||||||
|
import { PointCrawlMap, PointCrawlMapNavigator } from "./types";
|
||||||
|
|
||||||
|
export function canMoveTo(
|
||||||
|
navigator: PointCrawlMapNavigator,
|
||||||
|
map: PointCrawlMap,
|
||||||
|
targetNodeId: string,
|
||||||
|
): boolean {
|
||||||
|
const currentNode = getNode(map, navigator.currentNodeId);
|
||||||
|
if (!currentNode) return false;
|
||||||
|
|
||||||
|
return currentNode.childIds.includes(targetNodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function moveToNode(
|
||||||
|
navigator: PointCrawlMapNavigator,
|
||||||
|
map: PointCrawlMap,
|
||||||
|
targetNodeId: string,
|
||||||
|
): boolean {
|
||||||
|
if (!canMoveTo(navigator, map, targetNodeId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetNode = getNode(map, targetNodeId);
|
||||||
|
if (!targetNode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update current position
|
||||||
|
navigator.currentNodeId = targetNodeId;
|
||||||
|
navigator.visitedNodes.add(targetNodeId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -1,83 +1,88 @@
|
||||||
import {EncounterData} from "@/samples/slay-the-spire-like/system/types";
|
import { EncounterData } from "@/samples/slay-the-spire-like/system/types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Types of nodes that can appear on the point crawl map.
|
* Types of nodes that can appear on the point crawl map.
|
||||||
*/
|
*/
|
||||||
export enum MapNodeType {
|
export enum MapNodeType {
|
||||||
Start = 'start',
|
Start = "start",
|
||||||
End = 'end',
|
End = "end",
|
||||||
Minion = 'minion',
|
Minion = "minion",
|
||||||
Elite = 'elite',
|
Elite = "elite",
|
||||||
Event = 'event',
|
Event = "event",
|
||||||
Camp = 'camp',
|
Camp = "camp",
|
||||||
Shop = 'shop',
|
Shop = "shop",
|
||||||
Curio = 'curio',
|
Curio = "curio",
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Semantic type of a layer.
|
* Semantic type of a layer.
|
||||||
*/
|
*/
|
||||||
export enum MapLayerType {
|
export enum MapLayerType {
|
||||||
Wild = 'wild',
|
Wild = "wild",
|
||||||
Settlement = 'settlement',
|
Settlement = "settlement",
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single node on the map.
|
* A single node on the map.
|
||||||
*/
|
*/
|
||||||
export interface MapNode {
|
export interface MapNode {
|
||||||
/** Unique identifier */
|
/** Unique identifier */
|
||||||
id: string;
|
id: string;
|
||||||
/** Which layer this node belongs to */
|
/** Which layer this node belongs to */
|
||||||
layerIndex: number;
|
layerIndex: number;
|
||||||
/** Semantic type of the node */
|
/** Semantic type of the node */
|
||||||
type: MapNodeType;
|
type: MapNodeType;
|
||||||
/** IDs of nodes in the next layer this node connects to */
|
/** IDs of nodes in the next layer this node connects to */
|
||||||
childIds: string[];
|
childIds: string[];
|
||||||
/** Encounter data assigned to this node (from encounter CSV) */
|
/** Encounter data assigned to this node (from encounter CSV) */
|
||||||
encounter?: EncounterData;
|
encounter?: EncounterData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A horizontal layer of nodes at the same progression stage.
|
* A horizontal layer of nodes at the same progression stage.
|
||||||
*/
|
*/
|
||||||
export interface MapLayer {
|
export interface MapLayer {
|
||||||
/** Layer index (0 = start, last = end) */
|
/** Layer index (0 = start, last = end) */
|
||||||
index: number;
|
index: number;
|
||||||
/** Ordered IDs of nodes in this layer */
|
/** Ordered IDs of nodes in this layer */
|
||||||
nodeIds: string[];
|
nodeIds: string[];
|
||||||
/** Semantic type of the layer */
|
/** Semantic type of the layer */
|
||||||
layerType: MapLayerType | 'start' | 'end';
|
layerType: MapLayerType | "start" | "end";
|
||||||
/** Direct references to nodes in this layer (for performance) */
|
/** Direct references to nodes in this layer (for performance) */
|
||||||
nodes: MapNode[];
|
nodes: MapNode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fully generated point crawl map.
|
* A fully generated point crawl map.
|
||||||
*/
|
*/
|
||||||
export interface PointCrawlMap {
|
export interface PointCrawlMap {
|
||||||
/** Layers from start to end */
|
/** Layers from start to end */
|
||||||
layers: MapLayer[];
|
layers: MapLayer[];
|
||||||
/** All nodes keyed by ID */
|
/** All nodes keyed by ID */
|
||||||
nodes: Map<string, MapNode>;
|
nodes: Map<string, MapNode>;
|
||||||
/** Reverse index: nodeId → parent node IDs (for fast getParent lookup) */
|
/** Reverse index: nodeId → parent node IDs (for fast getParent lookup) */
|
||||||
parentIndex?: Map<string, string[]>;
|
parentIndex?: Map<string, string[]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PointCrawlMapNavigator {
|
||||||
|
currentNodeId: string;
|
||||||
|
visitedNodes: Set<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration for map generation.
|
* Configuration for map generation.
|
||||||
*/
|
*/
|
||||||
export interface MapGenerationConfig {
|
export interface MapGenerationConfig {
|
||||||
/** Total number of layers (including start and end) */
|
/** Total number of layers (including start and end) */
|
||||||
totalLayers: number;
|
totalLayers: number;
|
||||||
/** Number of nodes in each wild layer */
|
/** Number of nodes in each wild layer */
|
||||||
wildLayerNodeCount: number;
|
wildLayerNodeCount: number;
|
||||||
/** Number of nodes in each settlement layer */
|
/** Number of nodes in each settlement layer */
|
||||||
settlementLayerNodeCount: number;
|
settlementLayerNodeCount: number;
|
||||||
/** Probability weights for wild node types (should sum to 100) */
|
/** Probability weights for wild node types (should sum to 100) */
|
||||||
wildNodeTypeWeights: {
|
wildNodeTypeWeights: {
|
||||||
[MapNodeType.Minion]: number;
|
[MapNodeType.Minion]: number;
|
||||||
[MapNodeType.Elite]: number;
|
[MapNodeType.Elite]: number;
|
||||||
[MapNodeType.Event]: number;
|
[MapNodeType.Event]: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue