惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
WordPress大学
WordPress大学
小众软件
小众软件
P
Proofpoint News Feed
IT之家
IT之家
Apple Machine Learning Research
Apple Machine Learning Research
T
The Exploit Database - CXSecurity.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Threat Research - Cisco Blogs
K
Kaspersky official blog
V
V2EX
博客园 - Franky
Cisco Talos Blog
Cisco Talos Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Scott Helme
Scott Helme
量子位
SecWiki News
SecWiki News
博客园 - 叶小钗
S
SegmentFault 最新的问题
L
LINUX DO - 最新话题
Attack and Defense Labs
Attack and Defense Labs
T
Tailwind CSS Blog
Google DeepMind News
Google DeepMind News
T
Tor Project blog
N
News and Events Feed by Topic
The Cloudflare Blog
Help Net Security
Help Net Security
Forbes - Security
Forbes - Security
罗磊的独立博客
Stack Overflow Blog
Stack Overflow Blog
P
Privacy & Cybersecurity Law Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
A
Arctic Wolf
L
LangChain Blog
Latest news
Latest news
S
Schneier on Security
C
CERT Recently Published Vulnerability Notes
D
Darknet – Hacking Tools, Hacker News & Cyber Security
博客园_首页
T
The Blog of Author Tim Ferriss
Schneier on Security
Schneier on Security
S
Security @ Cisco Blogs
Hugging Face - Blog
Hugging Face - Blog
MyScale Blog
MyScale Blog
Blog — PlanetScale
Blog — PlanetScale
O
OpenAI News

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Tower Before Dusk: I Built a Puzzle Game for Humans and AI
Daniel Balcarek · 2026-06-18 · via DEV Community

This is a submission for the June Solstice Game Jam

It's interesting how the most exciting ideas always arrive when I have basically no time to work on them.

A few weeks earlier, I had finished my submission for the GitHub challenge by bringing an old WinForms game back to life. That project turned out to be a lot of fun. Then Sylwia Laskowska published a great article about Google's WebMCP. The idea fascinated me, but I wasn't sure where I could actually use it. Then the June Solstice Game Jam was announced. The idea hit me like a lightning bolt: What if I made a game that both humans and AI could play?

Let's do it.

What I Built

I created a puzzle game with a solstice theme called Tower Before Dusk. The goal is simple: reach your home tower before sundown. Every action costs time. Every step brings sunset a little closer. Rivers block your path, rocks force detours and the only way across water is to collect enough wood and build bridges. Move too much, collect unnecessary resources, or choose the wrong path, and night will arrive before you make it home.

The challenge isn't just solving the puzzle. It's solving it efficiently.

And apparently, that's difficult for both humans and AI.

Video Demo

In this demo, Gemini 3.1 Flash-Lite tries to solve the level using the exposed game tools. It fails, then I restart the level and solve it manually. That failure is part of the point: the tools worked, but reasoning through the puzzle was still hard for the lightweight model.

Code

GitHub logo Gramli / tower-before-dusk

A TypeScript puzzle game demonstrating WebMCP, where humans and AI solve the same challenges under the same rules.

Tower Before Dusk

TypeScript Vite Canvas

Tower Before Dusk is a tile-based puzzle game about reaching the tower before sunset. Plan each route carefully: every move spends daylight, trees provide wood, and water can only be crossed by building bridges.

The game is built as a modern browser app with TypeScript, HTML canvas, and Vite. It also exposes a small model-context interface so an assistant can read the current map and submit a complete action plan for replay in the UI.

Features

  • Three handcrafted puzzle levels with different tower layouts and move limits
  • Daylight system that tracks the move budget from morning through sunset
  • Trees that are collected automatically for wood when entered
  • Bridge building over water, consuming two wood per water tile
  • Rocks, water, bridges, towers, and sprite-based terrain rendering
  • Responsive canvas scaling for different browser sizes
  • Keyboard-driven play with restart and help shortcuts
  • HUD for level name, wood count, moves used…

How I Built It

Since WebMCP was completely new to me, I didn't want to jump straight into building a game without understanding how it worked first.

So I generated a simple Vite application and experimented with a tiny counter tool:

const incrementCounterTool = {
  name: "incrementCounter",
  description: "Increments the counter by a specified value.",
  inputSchema: {
    type: "object",
    properties: { value: { type: "number" } },
  },
  execute: async ({ value }: { value: number }) => {
    const counter  = document.getElementById('counter') as HTMLElement;
    if (counter) {
      const currentValue = parseInt(counter.innerText, 10) || 0;
      counter.innerText = (currentValue + value).toString();
    }
  },
  annotations: {
    readOnlyHint: false,
    untrustedContentHint: true
  },
};

When the AI successfully incremented the counter and I saw the value changing in the browser, I knew I could continue.

Of course, my game would be a little more complicated than a counter. At first, I considered letting the AI inspect the game state after every move, but then I realized I would burn through tokens incredibly fast. So I came up with another approach.

Instead of playing move by move, the AI would receive the entire game state, understand the rules, and generate one complete plan to reach the goal, but then another thought appeared:

"How do I make it look like the AI is actually playing?"

The answer was surprisingly simple. The AI would return a sequence of actions and my game loop would replay them with a short delay between moves. From the player's perspective, it would look like the AI was thinking and playing in real time.

Even better, it fit perfectly with the game's architecture, because human players already interact through keyboard actions that modify the game state.

With that idea in mind, I built the MVP.

I did it the "old-fashioned" way: player first. (Almost like mobile-first, except with fewer trendy conference talks.)

I also have to admit that I stole some core ideas from my previous EasterGame project. At this point, I'm starting to suspect I accidentally built the beginnings of a tiny puzzle game engine.

The first playable level looked like this:

Level MVP

The game worked, You could reach the tower and win. It was finally time to bring AI into the picture.

Based on the original idea, I created two MCP tools:

  • getGameState
  • submitPlan

getGameState provides the complete state of the current level, including objectives, rules, available actions, and the visible map:

export const gameState: GameState = {
  objective:  "Reach G before sunset using as few moves as possible. Do not collect unnecessary wood.",

  legend: {
    P: "player start position",
    ".": "land / walkable tile",
    W: "wood / walkable tile, can be collected",
    "~": "water / blocked unless player has enough wood",
    R: "rock / blocked tile",
    B: "bridge / walkable tile created after entering water",
    G: "goal / walkable tile",
  },

  rules: {
    map:
      "visibleMap is an array of map rows from top to bottom. The first symbol in each row is x=0, and rows start at y=0. Symbols are separated by spaces for readability.",

    movement:
      "The player can move one tile up, down, left, or right. Each movement costs 1 move.",

    rock:
      "Rock tiles marked R are blocked and cannot be entered.",

    wood:
      "Tree tiles marked W are walkable, but entering W automatically collects the tree. This costs 1 extra move, adds 1 wood, and removes W from the map. Because collecting wood costs an extra move, avoid W unless the wood is needed to cross water.",

    water:
      "Water cannot be entered unless the player has at least 2 wood.",

    bridge:
      "When the player moves into a water tile with at least 2 wood, a bridge is built automatically on that single water tile. This costs 1 extra move, consumes 2 wood, and changes only that one water tile to B. Other connected water tiles remain water.",

    bridgeLimit:
      "Each bridge covers only one water tile. If there are multiple water tiles in a row, the player needs enough wood to build one bridge per water tile.",

    strategy:
      "Use the minimum number of actions needed to reach G. Do not collect wood unless it is required to build enough bridges. Avoid stepping on W unless that wood is necessary. Extra wood has no value at the end.",

    goal:
      "The player wins immediately when reaching G using no more than the maximum allowed moves.",

    lose:
      "The player loses if the move budget is exhausted before reaching G, or if no valid action can reach G.",
  },

  actions: [
    "MOVE_UP",
    "MOVE_DOWN",
    "MOVE_LEFT",
    "MOVE_RIGHT",
  ],

  remainingMoves: 30,
  wood: 0,

  visibleMap: [
    "P . W W W W ~ ~ G",
  ],
};

The second tool, submitPlan, accepts the AI's proposed solution:

    inputSchema: {
      type: "object",
      properties: {
        actions: {
          type: "array",
          items: {
            type: "string",
            enum: [
              "MOVE_UP",
              "MOVE_DOWN",
              "MOVE_LEFT",
              "MOVE_RIGHT",
            ],
          },
        },
        summary: { type: "string" },
      },
      required: ["actions"],
      additionalProperties: false,
    },

The AI returns an array of actions such as:

["MOVE_UP","MOVE_DOWN","MOVE_LEFT","MOVE_RIGHT"]

Then submitPlan feeds those actions into the game loop, which replays them with a short delay so players can watch the AI attempt to solve the puzzle.

Pretty neat, right?

Well... It worked. The AI successfully called both tools and then it immediately exposed another problem: my level design was too difficult. Even Level 1 turned out to be surprisingly challenging for the models I tested.

For development and testing, I used the WebMCP Inspector with the Gemini models available through the free API tier:

  • Gemini 3 Flash Preview
  • Gemini 3.1 Flash-Lite
  • Gemini 3.5 Flash

All three models correctly called both tools, but none of them managed to generate a valid solution for just Level 1. At that moment, I realized that perhaps I had been a little too optimistic about my puzzle design, so I lowered the difficulty. Eventually, AI finally managed to reach the tower and complete the first level.

Victory ...Well... a small victory. I'm fairly sure stronger models would perform better on the harder levels, but I also didn't want to discover how much puzzle-solving curiosity could cost in API tokens.

If you'd like to try it yourself, this is the prompt I used:

You are playing Tower Before Dusk.

First call getGameState. Study the objective, legend, rules, remainingMoves, wood, and visibleMap.

Create one complete plan to reach G before sunset. Use only the listed actions. Account for move costs, automatic bridge building, wood collection, rocks, water, and remainingMoves.

Then call submitPlan exactly once with the full action list. Do not submit partial plans.

Interesting Thoughts

Going into this project, I assumed the hardest part would be integrating WebMCP into the game, but it wasn't.

The real surprise was discovering that even simple puzzle levels weren't trivial for AI models. The tools worked almost immediately, but designing levels that felt straightforward to humans while making AI struggle turned out to be an interesting challenge.

It made me realize that puzzles we consider "easy" often rely on intuition and reasoning patterns that aren't as obvious to language models as I had expected.

The Sunset Arrives

And that's how Tower Before Dusk came to life. I set out to build a game for the June Solstice Game Jam and explore an experimental technology, discovering that simple-looking puzzle games aren't necessarily simple for AI and creating something that humans and language models can both struggle to beat.

Honestly, I think that's a pretty fitting result for a game about racing against the setting sun.