プログラマーは Recycleされました()

ブラウザで動くコード構築型ローグライクです。ノード(コード断片)を並べて「RUN」し、敵と戦闘しながらショップや報酬でビルドを強化します。Next.js 16 をベースに、Nanostores でクライアント状態管理、Drizzle + Postgres で永続化、NextAuth (GitHub) で認証を行っています。

2025.12
使用技術
ReactNext.jsTailwind CSSTypeScriptSupabasedrizzle ORMNanostores
プログラマーは Recycleされました()

ゲーム概要

  • 元ネタ: 「農家はReplaceされました()」
  • コードで農業を自動化するゲーム
  • 本作はローグライク要素を追加して戦闘ゲーム化
  • ジャンル: コード構築型ローグライク
  • ノード(コード片)を並べて「RUN」し、敵と戦闘
  • 戦闘→ショップ→報酬を繰り返して3周回ってボス戦後クリア

ゲームの流れ

  1. マップ選択: 左回り/右回りを選択
  2. コード構築: ノードを並べてプログラムを作成
  3. 戦闘実行: RUNボタンで実行、敵にダメージ
  4. 報酬獲得: 勝利後、ランダムアイテムを獲得
  5. ショップ: アイテムの交換・強化
  6. ボス戦: 3周回後に最終ボスと対決

なぜRubyを選んだのか?

1. カッコを使わない文法

n = 3
n.times do
  atk()
end

→ 一行一行をアイテムとして分割しやすい

2. 実在する言語の方が親しみやすい

  • 完全な疑似言語よりも学習コストが低い
  • プログラミング経験者にとって理解しやすい

技術スタック

フロントエンド

  • Next.js 16 / React 19
  • TypeScript (型安全性)
  • Tailwind CSS 4 (スタイリング)
  • Nanostores (状態管理)

バックエンド

  • Drizzle ORM + Postgres (データ永続化)
  • NextAuth (GitHub認証)
  • Hono (APIルーティング)

トランスパイラの実装

Ruby風コード → JavaScript変換

export const itemDefinitions: Record<string, ItemDefinition> = {
  'atk_call': {
    label: 'atk()',
    generateCode: () => 'await atk();',
    executeAction: async (context) => {
      const damage = context.player.atk;
      context.updateEnemy({ hp: context.enemy.hp - damage });
      await context.sleep(500);
    },
  },
  // ...
};

トランスパイラを自作した理由

処理ごとに演出を挟むため

  • 演出制御: await sleep(500) でアニメーションを挟める
  • ゲームロジック: ダメージ計算やログ出力を細かく制御
  • バリデーション: 文法エラーを検出

実装: src/lib/transpiler.ts

Reactでゲームを作る難しさ

状態管理がひたすら増える...

  • プレイヤーのHP、攻撃力、BP
  • 敵のステータス
  • アイテムリスト、コードノード
  • マップ進行状況、周回数
  • ショップの状態、ログ
  • モーダルの表示/非表示

useRef、useState、useContext... 管理が大変!

Nanostoreについて

軽量なバンドルサイズのライブラリ

  • バンドルサイズ: わずか 334 bytes (gzip)
  • フレームワーク非依存: React, Vue, Svelte, Vanilla JS
  • TypeScript完全対応
  • シンプルなAPI: atom, map, computed
© 2026 SoraPort All Rights Reserved.