Survival LLM
인터넷 없이도 동작하는 무료 AI 어시스턴트와 150만 건 오프라인 자료를 제공, 답변 출처 표시, Mac·Windows 지원
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
메이플스토리 미니게임 「한글 모아모아」(10×16 보드)의 화면을 인식해 보유 조각 3개의 배치 순서, 방향(회전/반전), 위치를 추천하는 정적 웹 페이지입니다. 빌드나 의존성이 없습니다. getDisplayMedia(화면 공유)는 보안 컨텍스트가 필요하므로 로컬 서버로 여는 것을 권장합니다. 그다음 브라우저에서 http://127.0.0.1:8765/을 엽니다. 업데이트 후 화면이 이상하면 Ctrl+F5로 새로고침합니다. 스크린샷만 사용할 때는 index.html을 직접 열어도 됩니다.README 전문 보기 ↗
메이플스토리 미니게임 「한글 모아모아」(10×16 보드)의 화면을 인식해 보유 조각 3개의 배치 순서, 방향(회전/반전), 위치를 추천하는 정적 웹 페이지입니다. 빌드나 의존성이 없습니다.
바로 쓰기: https://runedia.github.io/
getDisplayMedia(화면 공유)는 보안 컨텍스트가 필요하므로 로컬 서버로 여는 것을 권장합니다.
python.exe -m http.server 8765 --bind 127.0.0.1
그다음 브라우저에서 http://127.0.0.1:8765/을 엽니다. 업데이트 후 화면이 이상하면 Ctrl+F5로 새로고침합니다. 스크린샷만 사용할 때는 index.html을 직접 열어도 됩니다.
게임 창 공유 시작 → MapleStory 창을 선택. 자동 분석이 기본으로 켜집니다. R 키(또는 지금 분석)는 현재 화면으로 이번 턴 계획을 새로 계산합니다(입력란에 입력 중일 때는 무시).인식 결과에 보드와 슬롯이 표시됩니다. 캡처 원본과 인식 영역(빨간 보드 격자, 노란 슬롯 영역)은 접이식 캡처 화면 · 보드 영역 지정에서 볼 수 있으며, 보드를 찾지 못하면 자동으로 펼쳐집니다.
회전/반전으로 맞춥니다.캡처 화면 안의 보드 영역 직접 지정 → 10×16 보드 바깥 경계를 드래그합니다. 같은 해상도에서는 저장된 값을 재사용합니다.자동 분석은 1초마다 프레임을 읽습니다. 같은 결과가 연속 2회 나오고 직전 적용분과 다를 때만 반영하므로, 조각을 끄는 동안의 프레임은 무시됩니다. 조각을 선택해 배치 중인 화면과 툴팁(능력 버튼 등의 설명 상자)이 보드·능력 칸을 덮은 화면은 건너뜁니다.
턴 계획 고정: 계산한 계획은 그 턴 동안 고정합니다. 새 화면이 "계획을 k단계까지 둔 판 + 남은 슬롯"과 같으면 다시 계산하지 않고 놓은 단계만 흐리게(✓) 표시합니다. 같지 않으면 다음처럼 처리합니다.
dev로 남긴 뒤 지금 판에서 다시 계산합니다.설정 화면은 없습니다. 줄 제거 후 위 블록은 그대로(화면으로 확인), 탐색 가중치는 기본값(아이템 80, 동시 제거 비중 100%)을 씁니다. 점 찍기·바꿔 뽑기 보유 수는 도구 막대에서 고칠 수 있고, 화면에서 읽기가 켜져 있으면 버튼 옆 숫자를 자동으로 읽어 채웁니다(읽지 못하면 입력값 유지).
초반 능력 제한은 꺼 두었습니다: "제거한 줄 수가 200 미만이면 능력을 비상시에만"(abilityFrom: 200)을 한 판 써 봤지만 끈 상태(abilityFrom: 0)가 기본입니다. 제한이 있으면 초반에 7/7로 오래 머물러 아이템 생성이 멈췄습니다(로그 0003에서 200줄 전 기록의 70%가 7/7). 가득 참 규칙을 바로잡은 능력 시뮬레이션(빈 판 시작 250턴, 128판)에서 제한이 없으면 점수 +10.9%(±3.3%), 생존 턴 +16±7, 250턴 안 사망률 −10.9±4.5%p였습니다. "가득 차면 제한 해제"(earlyFull)는 그 중간(제한 없음 대비 −4.8%)입니다. 다시 켜려면 js/solver.js의 abilityFrom을 200으로 둡니다(켜면 결과 요약에 200줄 전에는 능력을 비상시에만 사용이 표시됩니다).
한칸은 다시 뽑지 않음: 슬롯의 한칸 조각은 바꿔 뽑기를 권하지 않습니다(조각을 다 놓을 수 없을 때는 예외). 빈 판에서도 한칸 다시 뽑기가 +0.24줄 이득으로 계산되는 등 큰 조각일수록 칸이 차서 평가가 오르는 효과로 보였고, 시뮬레이션에서 점수 차이는 없고(+1.0±0.9%, −0.3±2.3%) 사망률은 조금 낮았습니다(−5.5±2.8%p, −3.9±3.7%p).
점 찍기: 원하는 칸 1개를 채우는 수로 탐색에 포함합니다. 1회당 기회비용을 빼고도 이득일 때만 씁니다. 2개는 항상 비상용으로 남기며, 남긴 것은 조각을 다 놓을 수 없을 때만 씁니다. 1개만 남기던 판(270,088점)에서 7/7 가득 참이 잦았고, 마지막에 비상용까지 다 쓴 뒤 끝나 2개로 늘렸습니다. 능력 시뮬레이션(로그 시작 120턴, 128판)에서 1개·2개·3개는 표준오차 안에서 차이가 없어 2개를 유지합니다.
이번만 사용 안 함: 추천에 점 찍기가 들어가면 결과 요약에 점 찍기 이번만 사용 안 함 버튼이 나옵니다. 누르면 이번 턴은 점 찍기 없이(비상용 포함) 다시 계산하고, 점 찍기 다시 허용으로 되돌릴 수 있습니다. 새 조각 3개가 들어오면(슬롯 조각 수가 늘면) 자동으로 풀리며, 바꿔 뽑기로 한 조각만 바뀐 경우는 같은 턴으로 봅니다. 보유량은 그대로 가득 참 판단에 씁니다. 로그의 rec.noDots에 기록됩니다.
바꿔 뽑기: 슬롯마다 "다시 뽑으면 평균적으로 얼마나 좋아지는가"를 계산합니다. 새 조각은 실측 등장 빈도(200줄부터 후반 빈도)로 나온다고 보고, 각 경우의 최선 계획 점수를 평균해 현재 계획과 비교합니다(놓지 못한 조각은 크게 감점). 기대 이득이 권장 기준을 넘으면 그 슬롯을 권장하며, 권장하지 않을 때도 슬롯별 기대 이득을 결과 맨 위에 표시합니다.
보유 한도: 두 능력 합계는 최대 7입니다. 가득 찬 상태에서 아이템 줄을 지우면 아이템을 얻지 못하고 아이콘(회색)이 그 칸에 남고, "다음 능력" 계수는 0에서 멈춰 가득 참을 벗어난 뒤 첫 배치에서야 아이템이 생깁니다. 탐색은 "더 얻을 수 있는 수(7 − 보유)"를 따라가며 넘는 아이템은 판에 남는 것으로 계산하고, 점 찍기를 쓰면 그 순간 한도가 1 늘어납니다. 기준은 보유량에 따라 조정합니다.
점 찍기 먼저: 같은 결과(최종 판·점수)라면 아이템을 더 얻는 순서를, 그것도 같으면 점 찍기를 앞에 두는 순서를 안내합니다. 가득 찬 상태에서 점 찍기를 먼저 쓰면 그 턴의 아이템을 얻고 멈춘 아이템 생성이 바로 이어집니다.
| 보유 합계 | 점 찍기 비용 | 한 턴 점 찍기 (비상용 2개 제외) | 바꿔 뽑기 권장 기준 (기대 이득) |
|---|---|---|---|
| 0~5 | 65 (줄을 완성할 때만 사용) | 최대 2 | +0.75줄 초과 |
| 6 | 30 | 최대 2 | +0.33줄 초과 |
| 7 (가득) | 20, 단 첫 사용에 낭비 방지 가치 +40 | 최대 3 | 아래 "가득 찼을 때" 참고 |
가득 찼을 때(7/7): 가득 찬 동안은 아이템을 얻지 못하고 새 아이템 생성도 멈추므로, 하나라도 써서 자리를 비우는 가치로 첫 사용에 낭비 방지 가치(40, 줄 1/3개)를 더해 다음 셋 중 가장 나은 것을 고릅니다. 결과 맨 위에 선택과 이유를 표시합니다.
조각을 선택하면 슬롯 카드가 노랗게 바뀌고 보드에 미리보기 칸이 그려집니다. 자동 분석은 이 상태에서 갱신을 보류하고, 조각을 놓은 뒤 화면이 안정되면 다시 갱신합니다.
| 파일 | 역할 |
|---|---|
js/pieces.js | 조각 19종 정의, 회전·반전 방향 생성, 버튼 조작 계산 |
js/solver.js | 3조각 순서·방향·위치 빔 서치(폭 500)와 보드 평가 |
js/solver-wasm.js | 빔 서치(앞보기 포함)의 WebAssembly판. wasm/src/lib.rs에서 node tools/build-wasm.js로 생성하며 직접 고치지 않습니다. 결과는 JS와 같고 약 2배 빠릅니다. 없거나 준비 전이면 JS 탐색을 씁니다 |
js/vision.js | 보드 자동 감지(빈 칸 색 + 격자선 주기), 칸·아이템 판정, 슬롯 조각 인식 |
js/app.js | UI, 화면 공유, 수동 보정, 결과 표시 |
test/solver.test.js | 조각·탐색 단위 테스트 (node --test test/solver.test.js) |
test/vision.html | 샘플 이미지 배율별 인식 회귀 테스트 (서버 실행 후 /test/vision.html) |
test/sim.js | 자가 대전 시뮬레이터: node test/sim.js --sigma 1 --games 16 --seed 7 [--set well=0] |
test/sim-pool.js | 설정 비교용 작업 큐: node test/sim-pool.js --cfg base= --cfg cand=hole1=9 --start log --minScore 20000 --turns 30 (로그의 실제 판에서 30턴, 약 30초). --abilities 1이면 점 찍기·바꿔 뽑기·아이템 등장까지 시뮬레이션(규칙은 로그에서 추정, AGENTS.md 참고) |
test/analyze-log.js | 내보낸 로그의 턴별 추천 점수와 최대 가능 점수 비교 (--why: 원인 분류) |
tools/dump_raw.py, tools/bar-ocr-eval.js | 상단 바 숫자 읽기 대량 평가 (Python으로 픽셀 덤프 → Node로 평가) |
tools/bench-solver.js | 탐색기 속도와 출력 지문: --save로 기준을 남기고 --check로 같은지 확인, --js 1은 JS 탐색만 사용 |
tools/build-wasm.js, wasm/ | Rust 탐색기 빌드 → js/solver-wasm.js 생성 (rustup target add wasm32-unknown-unknown 필요) |
AGENTS.md | 유지보수·로그 분석 절차, 게임 규칙 사실/가정, 실험 기록 (에이전트용) |
인식 회귀 테스트·tools/가 쓰는 스크린샷(samples/)과 로그 분석·시뮬레이터 로그 시작(--start log)이 쓰는 플레이 로그(log/)는 저장소에 포함하지 않습니다. 단위 테스트와 빈 판 시뮬레이션은 이 파일 없이 동작합니다.
한 번에 지운 줄 수 n에 대해 300 × n²점: 1줄 300, 2줄 1,200, 3줄 2,700, 4줄 4,800, 5줄 7,500. 추천 카드와 요약에 예상 점수를 표시합니다.
탐색은 한 수의 줄 제거 가치를 n × 120 + 점수 비중 × 120 × (n² − n)으로 평가합니다. 점수 비중은 100%로 고정이고, 동시 제거 가산은 여유와 관계없이 적용합니다(comboDamp: 0).
계획이 정해지면 같은 위치들에 놓는 순서를 모두 바꿔 보고, 동시 제거 점수가 가장 큰 순서를 고릅니다(최종 판은 같음). 빔 서치가 "줄을 아직 안 지운 중간 상태"를 낮게 보아 동시 제거 순서를 놓치는 경우를 보완합니다.
빔 서치는 마지막 단계 전까지 "동시 제거 잠재력"(지금까지의 게임 점수 + 9칸 찬 줄 × 250 + 8칸 찬 줄 × 80) 상위 후보도 빔 폭만큼 함께 남깁니다(diverse: 1). 점수 하나로만 고르면 1줄을 바로 지우는 상태가 여러 줄을 한 번에 지울 준비 상태를 밀어내기 때문입니다. 로그에서 놓친 동시 제거 10건 중 7건을 찾고, 128판 시뮬레이션에서는 +6%(표준오차 범위 안)였습니다.
조각 등장 빈도는 로그 두 판(603개)의 실측값을 씁니다(js/pieces.js의 OBSERVED). ㅌ형 12.8%가 가장 많고 ㅅ형 1.8%가 가장 적습니다. 바꿔 뽑기 기대값, "놓을 자리 없는 조각" 감점, 시뮬레이터(--dist log)에 반영합니다.
배치는 1턴 앞보기로 고릅니다. 빔 서치의 상위 후보 16개마다 다음 턴 조각 3개를 실측 빈도로 32묶음 뽑아 실제로 이어 두어 보고, 이번 턴 가치 + 0.9 × 다음 턴 최선 가치의 평균이 가장 큰 후보를 고릅니다. 정적 평가만으로는 "지금은 좋아 보이지만 다음 조각이 안 들어가는 판"을 구분하지 못했습니다. 실제로 정적 평가는 종료 직전 판일수록 점수가 높았습니다. 시뮬레이션 128판(빔 500, 당시 8개·16묶음)에서 점수 +118%, 생존 턴 +46이었고, 아래 판 조각화 대응에서 16개·32묶음으로 넓혔습니다. 점 찍기 횟수·가득 참·바꿔 뽑기 판단은 기존처럼 정적 평가로 하고, 앞보기는 그 안에서 배치만 고릅니다.
바꿔 뽑기 판단은 탐색이 57번 필요해 가장 오래 걸리므로, 배치 추천을 먼저 표시하고 그 뒤에 계산해 덧붙입니다. 탐색 평가를 바뀐 행만 다시 세는 차분 계산으로 바꿔 5~7배 빨라졌고, 앞보기를 포함해도 배치 추천 평균 약 0.2초, 판단까지 약 0.4초입니다(능력 보유 기록 40건, Node).
시뮬레이션(node test/sim.js, 조각 19종 균등·능력 미사용 가정, 같은 조각 순서로 16판 비교, 시드 7):
| 설정 | 평균 생존 | 평균 점수 |
|---|---|---|
| 동시 제거 가산 없음 | 38턴 | 18,938 |
| 동시 제거 가산, 판이 차면 줄임 | 47턴 | 26,119 |
| 동시 제거 가산, 줄이지 않음 | 54턴 | 30,544 |
| + 놓는 순서 최적화 (현재) | 54턴 | 33,281 |
"우물"(한 열을 비워 여러 줄을 한 번에 지우기) 준비 가산도 시험했지만 생존·점수가 모두 나빠져 꺼 두었습니다(well: 0). 3×3 빈 공간 가산(open)도 128판에서 효과가 없어 꺼 두었습니다. 놓을 자리 수(이동성) 가산과 좁은 틈 감점도 효과가 없거나 해로워 제거했습니다.
이후 비교(node test/sim-pool.js, 실측 분포, 시드 8개 × 16판 = 128판, 같은 판끼리 짝지은 차이 ± 표준오차):
| 설정 | 빔 | 평균 생존 | 평균 점수 | 기준 대비 점수 |
|---|---|---|---|---|
| 앞보기 없음 | 100 | 51턴 | 32,276 | — |
| 1턴 앞보기 (현재) | 100 | 112턴 | 81,623 | +153% (±16%) |
| 앞보기 없음 | 500 | 51턴 | 33,129 | — |
| 1턴 앞보기 (현재) | 500 | 97턴 | 72,089 | +118% (±13%) |
로그 시작 비교(--start log --minScore 20000 --turns 30, 실제 중후반 판 233개에서 30턴): 앞보기를 끄면 30턴 안 사망률이 32%에서 61%로 오릅니다.
"여유가 있으면 줄을 바로 지우지 않고 쌓아 두기(빌드업)"와 "빈 행 확보"도 시험했지만 둘 다 나빠져 코드를 제거했습니다(128판, 기준 대비 짝차 ± 표준오차).
| 설정 | 로그 시작 30턴 | 빈 판 시작 400턴 |
|---|---|---|
빌드업 0.3 (buildUp) | — | 점수 −13.9% (±8.1%), 턴 −16±8 |
| 빌드업 0.5 | 점수 −3.7% (±3.7%), 사망률 +13.3±4.5%p | 점수 −27.2% (±8.2%), 턴 −35±8 |
| 빌드업 1 | 점수 −22.7% (±4.4%), 사망률 +32±4.8%p | — |
빈 행 가산 5 (emptyRow) | 점수 −0.6% (±2.5%) | 점수 −8.3% (±8.0%) |
| 빈 행 가산 15 | 점수 −4.8% (±3.3%) | — |
판 조각화 대응 (2026-10-04, 채택). 실제 로그에서 200줄 이후 3칸 이하 조각이 21.7%에서 15.3%로 줄어, 틈을 메울 조각이 부족해 판이 쪼개지며 끝났습니다(로그 0440, 477,268점의 종료 판). 시뮬레이터에 후반 분포(--dist late, 200줄 전후로 바뀌는 --dist stage)를 넣고 다시 비교했습니다(능력 모드, 128판, 기준 대비 짝차 ± 표준오차).
| 설정 | 후반 판에서 120턴 (--dist late) | 빈 판에서 300턴 (--dist stage) |
|---|---|---|
| 기준 (이전 기본값) | 점수 82,390, 사망률 25.8% | 점수 207,213, 사망률 36.7% |
덮기 어려운 칸 감점 hard 10 | +11.7% (±3.5%), 사망률 −11.7±4.5%p | +9.3% (±2.9%), 사망률 −18.8±5.2%p |
hard 10 + 후반 빈도 lateFrom 200 + 앞보기 look 16·lookN 32 (현재) | +17.4% (±3.6%), 사망률 −14.8±4.6%p | +18.0% (±2.6%), 사망률 −26.6±4.8%p |
hard는 빈 칸마다 "무작위 조각 하나가 그 칸을 덮을 수 있는 확률"을 실측 빈도로 구해, 덮기 어려운 칸(한칸·점 찍기로만 메울 수 있는 틈)을 감점합니다. 같은 판끼리의 비교라 절대 점수는 실제 게임과 다릅니다.
로그 분석: node test/analyze-log.js log/<파일>.json — 턴마다 당시 추천, 현재 코드의 추천, 같은 조각으로 가능한 최대 점수(근사), 실제 얻은 점수를 비교합니다.
로그 접이식에서 켜고 끕니다(기본 켜짐). 새 계획을 계산할 때마다 보드·아이템·슬롯·능력 수·다음 능력·점수/제거한 줄 수/최고 점수·추천 단계와 예상 점수·바꿔 뽑기 판단·설정을 한 건씩 브라우저(localStorage)에 저장합니다. 계획대로 진행 중인 중간 상태는 다시 계산하지 않으므로 기록하지 않습니다. 같은 상태 반복과 직접 편집은 기록하지 않고, 점수나 줄 수가 줄면 새 게임 번호를 붙입니다. 최대 5,000건이며 JSON 내보내기로 파일을 받습니다.
계획과 다르게 둔 수는 다음 항목의 dev에 남습니다: step(계획의 몇 번째 단계부터 달라졌는지), plan(남은 계획 단계), actual(실제로 둔 수, [슬롯, 조각, 방향, 행, 열] 또는 [점, 행, 열]), 설명되지 않는 인식을 받아들인 경우 unexplained: true.
점수·제거한 줄 수·최고 점수는 상단 바에서 읽습니다. 확신이 없으면 null로 기록합니다(1,155건 평가에서 오독 0, 읽기 실패 약 5%).
정적 점수 = 제거한 줄×120 + 아이템×(우선도) + 행 채움² 보너스 − 행·열 경계 수 − 고립 구멍 − 작은 빈 영역 − 놓을 자리가 없는 조각 종류×40 − 덮기 어려운 칸(hard)
최종 선택 = 이번 턴의 줄·아이템 가치 + 0.9 × (다음 턴 조각 표본 32묶음에서 정적 점수 기준 최선 계획 가치의 평균). 다음 턴에 조각을 다 못 놓는 표본은 1개당 400점을 뺍니다.
stay). 탐색 코드는 shift도 지원하지만 화면에서 고를 수는 없습니다.숫자 읽기: 점 찍기·바꿔 뽑기 버튼 옆 숫자와 "다음 능력 획득까지 n번"을 화면에서 읽습니다. 확신이 없으면 읽지 않고(입력값 유지), 셀이 22px 미만인 아주 작은 창에서는 읽지 않습니다.
samples/0번.png·회색.png, 6은 바꿔뽑기6.png), 7은 같은 글꼴을 본뜬 템플릿이라 실물 검증 전입니다. 6은 0·5와 한 획만 달라, 짝인 숫자가 상위 후보에 있으면 그 획 영역의 밝기로 가릅니다.samples/0번.png). 7/7이면 게임이 숫자 대신 "가득 찼습니다"를 표시하므로 읽지 않습니다.칸 인식: 점 찍기로 채운 칸은 보라 블록으로 그려져 바꿔 뽑기 아이콘과 색이 같으므로, 칸의 대부분이 보라이면 블록으로 봅니다. 가득 참일 때 회색이 된 아이콘(빈 칸 위)도 아이템으로 인식합니다(블록 위 회색 아이콘은 샘플이 없어 미확인).
다음 능력 반영: 6/7일 때 다음 능력이 이번 턴이나 다음 턴(이번 턴 배치 수 + 3번 이내)에 들어오면 "곧 가득 참"으로 보고 조금 더 적극적으로 씁니다. 더 멀면 평소처럼 아낍니다.
보드 위 아이템 아이콘은 그 줄을 지우면 획득하므로 아이템 우선도만큼 가산합니다. 블록 위에 남은 아이콘도 포함합니다.