# Nekoban Map Generator 역탐색 기반으로 소코반 맵을 생성하는 .NET 7 콘솔 툴입니다. 마스크(외곽 형태)를 지정하고, 목표에 박스를 놓은 상태에서 박스를 “pull”하여 시작 상태를 만들기 때문에 항상 풀 수 있는 맵만 출력합니다. 외벽은 `#`, 바깥은 `0`, 바닥은 `.`, 목표/박스/플레이어는 `G/$/@`로 표시합니다. ## 요구사항 - .NET 7 SDK ## 사용 방법 ```bash dotnet build dotnet run -- [startId] [endId] > output.json # 개별/범위 검증: 생성된 JSON이 풀리는지 확인 dotnet run -- --verify [endId] dotnet run -- --verify-all # 외곽 트림: JSON의 외부 void(0) 행/열 제거 dotnet run -- --trim <입력 json> [출력 json] [startId] [endId] ``` - 예: `dotnet run -- 12345 3 20 > stage.json` - 예: `dotnet run -- --verify stage.json 210 220` - 예: `dotnet run -- --trim stage.json trimmed.json 200 260` - `seed`가 없으면 기본값(12345)을 사용합니다. - `startId/endId`가 없으면 `levelbalance.json`에 정의된 밴드 범위를 사용합니다. - 검증 모드에서는 지정한 JSON의 레벨을 솔버로 풀어보고, 성공/실패와 함께 `moves/ pushes/ turns`를 리포트합니다. - 트림 모드는 지정한 범위(id)만 외곽의 '0' 패딩을 걷어내서 저장합니다(기본 출력 경로: `trimmed_output.json`). - 생성 중 매 레벨 단위로 누적 체크포인트 JSON을 `stage_checkpoint.json`에 기록하며, 경로는 `NEKOBAN_CHECKPOINT` 환경변수로 바꿀 수 있습니다. - 진행 상태는 stderr에 한 줄로 갱신되며 점(.) 애니메이션과 현재 레벨/전체 경과 시간이 함께 표시됩니다. ## 설정 - `levelbalance.json`: 레벨 밴드 설정(레벨 범위, 박스 수, 최소 푸시/턴/브랜칭, 마스크 세트/확장 범위, 역탐색 깊이/폭 스케일, 목표/박스 간 최소 거리, 주머니(포켓) 리라이팅). `maskSets`(micro/medium/large), `maskPadMin/max`, `reverseDepthScale/breadthScale`, `minAllowedBranching`, `minGoal/Box/WallDistance`, `pocketCarveMin/Max/Radius`를 밴드별로 조정해 난이도·길이감을 설계합니다. - `mask_library.cs`: Microban/Novoban 스타일의 외곽 마스크 모음 + 중형/대형 마스크. 회전/반전/스케일 변형과 소규모 벽 지터가 자동 적용됩니다. 마스크를 추가해 형태 다양성을 늘릴 수 있습니다. - `Program.cs`: 생성 튜닝(`GenerationTuning`)에 시도 횟수, 시간 한도, 릴랙스 단계 수, 역탐색 기본 깊이/폭, 외벽 정규화, 코너 데드락 필터 옵션 등이 정의되어 있습니다. ## 출력 형식 `output.json`은 다음 형태의 배열입니다. ```json [ { "id": 3, "grid": [ "000000000", "00#####00", "00#...#00", "0##.$.##0", "0#@$.G.#0", "0##...##0", "00#.G.#00", "00#####00", "000000000" ], "lowestPush": 5, "pushLimit": 7, "moveCount": 9 } ] ``` - `grid`: 문자열 배열(행). `0`은 외부 void, `#`는 벽, `.`은 바닥, `G/$/@`는 목표/박스/플레이어. - `lowestPush`: 솔버가 계산한 최소 푸시 수. - `pushLimit`: 최소 푸시에 여유 패딩을 더한 제한 값. - `moveCount`: 솔버가 계산한 최소 이동 수(걷기 + 푸시 포함). ## 메모 - 외벽은 항상 `#`로 둘러지며, `0`은 외부에서만 사용됩니다. - 중복 레이아웃은 제거됩니다. - 해법 패턴(푸시/턴/방향 런 요약) 해시를 이용해 유사 해법 레벨도 추가로 걸러냅니다. - 더 느리게 돌려야 하면 `GenerationTuning`의 시도/시간 한도를 조정하세요. - 밴드 강등/시드 재시도는 성공할 때까지 반복되므로, 오래 걸릴 때는 진행 메시지의 경과 시간을 참고해 중단 여부를 판단하세요.