Tower Before Dusk: 인간과 AI를 위한 퍼즐 게임 제작기
요약
June Solstice Game Jam을 위해 제작된 'Tower Before Dusk'는 인간과 AI가 동일한 규칙으로 플레이하는 퍼즐 게임입니다. Google의 WebMCP를 활용하여 Gemini 3.1 Flash-Lite 모델이 게임 도구를 사용해 퍼즐을 해결하도록 시도하는 과정을 담고 있습니다.
핵심 포인트
- 인간과 AI가 공통의 규칙으로 경쟁하는 퍼즐 게임 설계
- Google WebMCP를 활용한 AI 에이전트의 게임 플레이 시연
- 경량 모델(Gemini 3.1 Flash-Lite)의 추론 능력 한계 확인
- TypeScript와 Vite를 사용한 웹 기반 게임 개발
이 글은 June Solstice Game Jam 제출물입니다.
가장 흥미로운 아이디어는 항상 작업할 시간이 거의 없을 때 찾아온다는 점이 흥미롭습니다.
몇 주 전, 저는 오래된 WinForms 게임을 다시 살려내며 GitHub 챌린지 제출을 마쳤습니다. 그 프로젝트는 매우 즐거운 작업이었습니다. 그러던 중 Sylwia Laskowska가 Google의 WebMCP에 관한 훌륭한 기사를 게시했습니다. 그 아이디어는 저를 매료시켰지만, 실제로 어디에 사용할 수 있을지는 확신이 서지 않았습니다. 그때 June Solstice Game Jam이 발표되었습니다. 아이디어가 번개처럼 스쳤습니다: 인간과 AI가 모두 플레이할 수 있는 게임을 만든다면 어떨까?
한번 해봅시다.
내가 만든 것
저는 Tower Before Dusk라는 이름의 하지(solstice) 테마 퍼즐 게임을 만들었습니다. 목표는 간단합니다: 해가 지기 전에 자신의 집 탑에 도착하는 것입니다. 모든 행동에는 시간이 소요됩니다. 모든 발걸음은 일몰을 조금씩 더 가깝게 만듭니다. 강은 길을 가로막고, 바위는 우회하게 만들며, 물을 건너는 유일한 방법은 충분한 나무를 모아 다리를 건설하는 것입니다. 너무 많이 움직이거나, 불필요한 자원을 수집하거나, 잘못된 경로를 선택하면 집에 도착하기도 전에 밤이 찾아올 것입니다.
도전 과제는 단순히 퍼즐을 푸는 것이 아닙니다. 효율적으로 푸는 것입니다.
그리고 분명히, 그것은 인간과 AI 모두에게 어려운 일입니다.
비디오 데모
이 데모에서는 Gemini 3.1 Flash-Lite가 공개된 게임 도구(tools)를 사용하여 레벨을 해결하려고 시도합니다. 모델은 실패하고, 그 후 제가 레벨을 재시작하여 수동으로 해결합니다. 그 실패 자체가 핵심입니다. 도구는 작동했지만, 경량 모델(lightweight model)에게 퍼즐을 통해 추론(reasoning)하는 것은 여전히 어려웠습니다.
tower-before-dusk.gramli.workers.dev
코드
Gramli / tower-before-dusk
인간과 AI가 동일한 규칙 아래에서 같은 과제를 해결하는 WebMCP 시연용 TypeScript 퍼즐 게임.
Tower Before Dusk
Tower Before Dusk는 일몰 전까지 탑에 도달하는 것을 목표로 하는 타일 기반 (tile-based) 퍼즐 게임입니다. 각 경로를 신중하게 계획하세요. 모든 이동은 일조량을 소모하며, 나무는 목재를 제공하고, 물은 다리를 건설해야만 건널 수 있습니다.
이 게임은 TypeScript, HTML canvas, 그리고 Vite를 사용하여 현대적인 브라우저 앱으로 구축되었습니다. 또한 어시스턴트(assistant)가 현재 맵을 읽고 UI에서 재생할 수 있는 완전한 행동 계획을 제출할 수 있도록 작은 모델 컨텍스트 인터페이스 (model-context interface)를 노출합니다.
특징 (Features)
- 서로 다른 탑 배치와 이동 제한이 있는 세 가지 수제 퍼즐 레벨
- 아침부터 일몰까지 이동 예산을 추적하는 일조량 시스템
- 진입 시 목재를 위해 자동으로 수집되는 나무
- 물 타일당 목재 2개를 소모하여 물 위에 다리 건설
- 바위, 물, 다리, 탑, 그리고 스프라이트 기반 (sprite-based) 지형 렌더링
- 다양한 브라우저 크기에 대응하는 반응형 캔버스 스케일링 (Responsive canvas scaling)
- 재시작 및 도움말 단축키를 포함한 키보드 기반 플레이
- 레벨 이름, 목재 수량, 사용된 이동 횟수 등을 표시하는 HUD
제작 과정 (How I Built It)
WebMCP가 저에게는 완전히 새로운 것이었기 때문에, 작동 방식을 먼저 이해하지 않은 채 바로 게임 제작에 뛰어들고 싶지 않았습니다.
그래서 간단한 Vite 애플리케이션을 생성하고 아주 작은 카운터 도구 (counter tool)로 실험을 진행했습니다:
const incrementCounterTool = {
name: "incrementCounter",
description: "Increments the counter by a specified value.",
...
AI가 성공적으로 카운터를 증가시키고 브라우저에서 값이 변하는 것을 확인했을 때, 저는 계속 진행할 수 있다는 확신을 얻었습니다.
물론, 제 게임은 카운터보다는 조금 더 복잡할 것이었습니다. 처음에는 매 수(move)마다 AI가 게임 상태 (game state)를 검사하도록 하는 방안을 고려했지만, 그렇게 하면 토큰 (tokens)을 엄청나게 빠르게 소모할 것이라는 사실을 깨달았습니다. 그래서 다른 접근 방식을 생각해냈습니다.
한 수씩 플레이하는 대신, AI가 전체 게임 상태를 전달받아 규칙을 이해하고 목표에 도달하기 위한 하나의 완전한 계획 (plan)을 생성하도록 하는 것이었습니다. 하지만 곧 또 다른 생각이 떠올랐습니다.
"어떻게 하면 AI가 실제로 플레이하는 것처럼 보이게 만들 수 있을까?"
답은 놀라울 정도로 간단했습니다. AI가 일련의 행동 (sequence of actions)을 반환하면, 제 게임 루프 (game loop)가 각 행동 사이에 짧은 지연 시간을 두어 이를 재현하는 것이었습니다. 플레이어의 관점에서는 AI가 실시간으로 생각하고 플레이하는 것처럼 보일 것입니다.
심지어 이는 게임의 아키텍처 (architecture)와도 완벽하게 맞아떨어졌는데, 인간 플레이어들이 이미 게임 상태를 수정하는 키보드 동작을 통해 상호작용하고 있었기 때문입니다.
이 아이디어를 염두에 두고, 저는 MVP (Minimum Viable Product)를 구축했습니다.
저는 "구식" 방식으로 진행했습니다. 즉, 플레이어 우선 방식이었습니다. (유행하는 컨퍼런스 강연은 적지만, 거의 모바일 퍼스트 (mobile-first) 방식과 비슷합니다.)
또한 제 이전 EasterGame 프로젝트에서 몇 가지 핵심 아이디어를 가져왔다는 점도 인정해야겠습니다. 이쯤 되니 제가 실수로 아주 작은 퍼즐 게임 엔진의 기초를 만들고 있는 게 아닌가 하는 의심이 들기 시작합니다.
첫 번째 플레이 가능한 레벨은 다음과 같았습니다:
게임은 작동했습니다. 타워에 도달하여 승리할 수 있었습니다. 이제 드디어 AI를 투입할 차례였습니다.
원래의 아이디어를 바탕으로, 저는 두 가지 MCP 도구 (tools)를 만들었습니다:
getGameStatesubmitPlan
getGameState는 목표, 규칙, 가능한 행동, 그리고 보이는 맵을 포함하여 현재 레벨의 전체 상태를 제공합니다:
export const gameState: GameState = {
objective: "최대한 적은 이동 횟수를 사용하여 일몰 전까지 G에 도달하세요. 불필요한 나무를 수집하지 마세요.",
...
두 번째 도구인 submitPlan은 AI가 제안한 해결책을 수락합니다:
inputSchema: {
type: "object",
properties: {
...
AI는 다음과 같은 행동(actions) 배열을 반환합니다:
["MOVE_UP","MOVE_DOWN","MOVE_LEFT","MOVE_RIGHT"]
그 다음 submitPlan은 해당 행동들을 게임 루프(game loop)에 전달하며, 게임 루프는 플레이어가 AI의 퍼즐 해결 시도를 지켜볼 수 있도록 짧은 지연 시간(delay)을 두고 이를 재현합니다.
꽤 멋지지 않나요?
음... 작동은 했습니다. AI는 두 도구를 모두 성공적으로 호출했지만, 곧바로 또 다른 문제를 드러냈습니다. 바로 제 레벨 디자인이 너무 어려웠다는 점입니다. 심지어 레벨 1조차 제가 테스트한 모델들에게는 놀라울 정도로 도전적인 과제였습니다.
개발 및 테스트를 위해, 저는 무료 API 계층을 통해 사용할 수 있는 Gemini 모델들과 함께 WebMCP Inspector를 사용했습니다:
- Gemini 3 Flash Preview
- Gemini 3.1 Flash-Lite
- Gemini 3.5 Flash
세 모델 모두 두 도구를 정확하게 호출했지만, 그중 어떤 모델도 레벨 1에 대해서만 유효한 해결책을 생성해내지는 못했습니다. 그 순간, 저는 제가 퍼즐 디자인에 대해 다소 낙관적이었다는 것을 깨달았고, 난이도를 낮추었습니다. 결국, AI는 마침내 탑에 도달하여 첫 번째 레벨을 완료할 수 있었습니다.
승리... 음... 작은 승리였습니다. 더 강력한 모델이라면 더 어려운 레벨에서도 더 나은 성능을 보일 것이라고 확신하지만, 퍼즐 해결을 위한 호기심이 API 토큰 비용으로 얼마나 많이 청구될지는 확인하고 싶지 않았습니다.
직접 시도해보고 싶다면, 제가 사용한 프롬프트(prompt)는 다음과 같습니다:
You are playing Tower Before Dusk.
First call getGameState. Study the objective, legend, rules, remainingMoves, wood, and visibleMap.
...
흥미로운 생각들
이 프로젝트를 시작할 때, 저는 WebMCP를 게임에 통합하는 것이 가장 어려운 부분일 것이라고 가정했지만, 그렇지 않았습니다.
진정한 놀라움은 아주 단순한 퍼즐 레벨조차 AI 모델들에게는 결코 사소하지 않다는 사실을 발견한 것이었습니다. 도구들은 거의 즉각적으로 작동했지만, 인간에게는 직관적으로 느껴지면서도 AI는 고전하게 만드는 레벨을 설계하는 것은 흥미로운 도전이 되었습니다.
이를 통해 우리가 "쉽다"고 생각하는 퍼즐들이, 제가 예상했던 것만큼 언어 모델 (Language Models)에게 명확하게 드러나지 않는 직관과 추론 패턴에 의존하는 경우가 많다는 것을 깨달았습니다.
해가 저물다
그렇게 Tower Before Dusk가 탄생했습니다. 저는 June Solstice Game Jam을 위해 게임을 제작하고 실험적인 기술을 탐구하려 시작했지만, 겉보기에 단순해 보이는 퍼즐 게임이 AI에게 반드시 단순한 것은 아니라는 점을 발견하게 되었고, 인간과 언어 모델 (Language Models) 모두가 공략하기 어려워할 만한 무언가를 만들어내게 되었습니다.
솔직히 말해서, 지는 해를 향해 달리는 게임이라는 주제에 꽤나 어울리는 결과라고 생각합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기