マガジン

「オセロを作って」と一言だけ頼むと、何が省かれるか

遊びをつくる

執筆にClaudeを使用しています。

空きマスが残る青いオセロ盤を挟み、手を止めて考える二人を描いた版画風イラスト。
記事のテーマをもとに制作したAI生成イラスト。

AIに「オセロを作って」とだけ頼むと、ブラウザで動くオセロが数十秒から数分で出てくることがあります。盤面が描かれ、石を置くと挟んだ石が返り、黒と白が交互に進みます。ところが、動いて見えることと、ルールが揃っていることは別の話です。この記事では、一言の依頼で生成されたオセロを検証して、抜けたルールを一覧にする実験の設計書を示します。 ここで確かめたいのは、AIの出来の良し悪しではありません。依頼文に書かなかった事柄を、生成物がどの程度「当たり前のルール」として補っているかです。省かれやすい候補は、初期配置の向き、先手の色、置けない手番のパス、双方が置けないときの終了、引き分けの扱いなどです。これらは仮説であり、結果ではありません。自分の環境で同じ依頼を出し、同じ物差しで測れば、抜けのリストが手元にできます。 作った一覧は、次に依頼文へ何を書き足すかの材料になります。完成した作品を投稿する前の受け入れ検査としても使えます。

この記事の目次
  1. 問いを三つに分ける
  2. 準備するもの
  3. 手順
  4. 何を・どの単位で記録するか
  5. 結果の読み方
  6. 誤りやすい点
  7. 完成品との比較に使う
  8. 次の行動

問いを三つに分ける

「何が省かれるか」は広すぎて、そのままでは記録できません。次の三つに分けると、観察の単位が決まります。

  1. 盤面の初期状態:最初の4個の石の配置と、先手の色は正しいか。
  2. 一手の処理:置ける場所の判定と、石を返す範囲は正しいか。
  3. 進行の端:置ける場所がない手番や、対局の終わり方は処理されているか。

1と2は最初の数手で分かります。難しいのは3で、通常の対局では一部しか現れません。そのため、局面を探す手順を別に設けます。

準備するもの

  • 同じ生成ツールの新しい会話を3つ。会話ごとに依頼を出し、前の会話の文脈を持ち込みません。
  • 依頼文は「オセロを作って」の一言だけです。「ブラウザで遊べる形で」などの補足も足さず、そのまま使います。
  • 生成物を動かすブラウザと、開発者ツールのコンソール。
  • 記録用の表(後述)。
  • 手元に置く基準のルール。標準のオセロでは、8×8の盤の中央に4つの石を斜めに置きます。列をaからh、行を1から8とすると、d4とe5が白、e4とd5が黒です。黒が先手です。

基準のルールを確かめるために、次の短い関数を使えます。盤面を二次元配列で渡すと、ある色の合法手を返します。生成物のコードを読む必要はなく、「正しい答え」を手元に持つためのものです。

js
const DIRS = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]];
const inside = (y, x) => y >= 0 && y < 8 && x >= 0 && x < 8;

// board[行][列]:0 空、1 黒、2 白。me は 1 か 2。
function flips(board, y, x, me) {
  if (board[y][x] !== 0) return [];
  const result = [];
  for (const [dy, dx] of DIRS) {
    const line = [];
    let ny = y + dy, nx = x + dx;
    while (inside(ny, nx) && board[ny][nx] === 3 - me) {
      line.push([ny, nx]); ny += dy; nx += dx;
    }
    if (line.length > 0 && inside(ny, nx) && board[ny][nx] === me)
      result.push(...line);
  }
  return result;
}

function legalMoves(board, me) {
  const moves = [];
  for (let y = 0; y < 8; y++)
    for (let x = 0; x < 8; x++)
      if (flips(board, y, x, me).length > 0) moves.push([y, x]);
  return moves;
}

// 初期配置の確認(行は0始まり。d4=[3][3]、e5=[4][4])
const start = Array.from({length: 8}, () => Array(8).fill(0));
start[3][3] = 2; start[4][4] = 2; // d4、e5 が白
start[3][4] = 1; start[4][3] = 1; // e4、d5 が黒
console.log(legalMoves(start, 1).length); // 4 になります

初期配置で黒が置けるのは4か所です。d3、c4、f5、e6です。たとえば黒がd3に置くと、真下のd4にある白がd5の黒に挟まれて返ります。これで盤面は黒4個、白1個になります。生成物の最初の一手がこの数字と食い違うなら、そこが最初の記録対象です。

手順

生成と起動

  1. 新しい会話で「オセロを作って」と送ります。
  2. 出てきたHTMLを1つのファイルとして保存し、ブラウザで開きます。ファイルが複数に分かれた場合は、その事実も記録します。
  3. 会話を新しくして、同じ手順を合計3回行います。2回目以降の生成物を、1回目に合わせて直さないでください。

前半の検証(最初の数手)

  1. 起動した直後の盤面を見て、黒と白の石がどのマスにあるかを書き出します。
  2. 手番の表示があるか、あるなら誰の番かを確かめます。
  3. 黒の側として、基準の4か所以外にも置けてしまうか試します。たとえば中央から離れた隅や、隣に相手の石がないマスをクリックします。
  4. 合法手のうち1つに置き、返った石の数と位置を基準と照合します。
  5. 横・縦・斜めの3方向で返る局面を、実際の対局の中で探します。斜めが返らない実装は、この確認で見つかります。

後半の検証(進行の端)

後半は、局面を作る必要があります。盤面の配置を決め打ちして入力する方法は、生成物の内部構造が不明なので使えません。実際の対局の中で、次の条件を満たす局面を探します。

  • 片方が置けない局面:終盤に、自分の石が壁際に偏った側が現れやすくなります。相手の石が盤の端に寄り、内側に自分の石が少ないとき、挟める場所が消えやすくなります。この状況を意識して序盤から手を選びます。
  • 両者とも置けない局面:盤面が埋まる前に起きることもあれば、埋まって起きることもあります。最後まで打ち切って、終局の表示が出るかを見ます。
  • 片方の石が盤上から消える局面:一方が極端に少数になるまで追い込む打ち方で近づけます。起きたときに終局として扱われるか、続行されるかを記録します。

1回の対局で全部は出ません。1つの生成物につき、最後まで打ち切る対局を最低2回行います。途中でやめた対局は、やめた時点の局面とともに「未到達」と書きます。

何を・どの単位で記録するか

記録は「生成物ごと × 項目ごと」の表で行います。3回生成して、項目は次のとおりです。

  • 初期配置、見方:d4・e5が白、e4・d5が黒か、記録:○/×、実際の配置
  • 先手、見方:黒が先に打てるか、記録:○/×/表示なし
  • 合法手の制限、見方:挟めないマスに置けないか、記録:○/×/△
  • 返す範囲、見方:8方向すべてで返るか、記録:返らなかった方向
  • 連続して返る範囲、見方:挟んだ列だけが返るか(その先まで返っていないか)、記録:○/×
  • 手番のパス、見方:置けない手番が飛ぶか、記録:○/×/未到達
  • 双方置けない終了、見方:終局の判定が出るか、記録:○/×/未到達
  • 勝敗・引き分け、見方:石数の比較と、同数の扱い、記録:表示の文言
  • 石数の表示、見方:現在の個数が見えるか、記録:あり/なし
  • 再開、見方:最初からやり直せるか、記録:あり/なし

判定は○(基準どおり)、△(一部だけ合う)、×(食い違い)、未到達(局面を作れなかった)の4種類にします。「未到達」は「合格」と区別してください。確認できていないだけの項目を合格にすると、一覧の意味が失われます。

食い違いを見つけたら、メモには次の3点を書きます。

  • どの局面か(石の位置を言葉で書き出す)
  • 何が起きたか
  • 基準ではどうなるべきか

結果の読み方

3回の生成物を並べると、項目ごとに次の三つのパターンのどれかになります。

  • 3回とも○:一言の依頼でも安定して補われている項目です。依頼文に書き足す必要は、ひとまずありません。
  • 3回とも×または未実装:依頼文に書かないと出てこない項目の可能性が高いです。次の依頼文に明示します。
  • 回によって○と×が割れる:運任せの項目です。依頼のたびに結果が変わるので、仕様として書き込まないと再現できません。最も危ないのはこれです。

読み方の注意点がもう一つあります。「実装が存在すること」と「正しく動くこと」は別に扱います。パスの仕組みが作られていても、置ける場所があるのにパスされるなら、記録は×です。

抜けの一覧ができたら、それを依頼文へ書き換えます。たとえば「黒先手」「置ける場所がない手番は自動でパス」「双方が置けなければ終局し、石の多い側が勝ち、同数は引き分け」といった形にして、もう一度同じ検証をします。一言のときと比べて、×だった項目が減ったかを見れば、書き足した一文の効き目が分かります。

誤りやすい点

  • 見た目で合格にする:石が返るアニメーションが付いていると、動いているだけで正しく見えます。必ず返った石の位置を基準と突き合わせてください。
  • 1回の生成で結論を出す:同じ依頼でも生成物は変わりえます。1回の結果は「その1回」の記録にとどめます。
  • 途中で直してもらう:対話で修正を重ねると、一言の依頼の結果ではなくなります。この実験では修正を頼まず、検証だけを行います。
  • 基準を自分の記憶に頼る:オセロには家庭ごとの遊び方の差が出やすいです。初期配置の色の向きは特に混ざりやすいので、基準のルールを先に文章にして固定します。
  • 未到達を放置する:パスや終局は、自然な対局では出会いにくい項目です。「確かめられなかった」と明記し、次の対局で狙います。

完成品との比較に使う

検証の物差しは、公開されている作品を見るときにも使えます。アソバースの「潮目のオセロ」は、設計から読み取れる範囲で、黒が先手であること、置けない手番が自動でパスされること、返る石のプレビューがあること、投了があることなど、対局の端に当たる部分が仕様として明示されています。それぞれがどんな見た目で働くかは、作品を開いて確かめてください。上の表の項目を、公開作品に当てはめてみるのも練習になります。

自作のオセロをアソバースに投稿する場合も、この表が受け入れ検査になります。独立したHTMLとして直下にindex.htmlを置けば、アップロード投稿の対象になります。投稿前に「パス」と「終局」の行を埋めておくと、遊んだ人が最初に当たる不具合を減らせます。

次の行動

まず「オセロを作って」の一言を3つの新しい会話に出し、生成物を保存して、上の表の「初期配置」と「合法手の制限」の2行だけ埋めてください。その後、終盤の対局を最後まで打ち切り、「パス」と「終局」の行を埋めます。最後に、×や△の項目を依頼文に一文ずつ書き足し、同じ検証をもう一度行います。差が出た項目の一覧が、あなたの依頼文の改善点になります。