Geminiの画像認識でポケモンの選出画面をスマホから自動解析する方法

AI・Python



スマホをいじっていて、ふと気づく。

「あら、いつの間にかスマホ版のポケモンチャンピオンズがリリースされてるじゃん!」

にPC環境で「画像認識AIに相手のパーティを自動解析させるシステム」を作りましたが、せっかくゲームがスマホにきたなら、解析もスマホで完結させたいところ。

そこで今回は、AIを使用した画像解析をiPhoneでも動作するように改造してみました。





フローにするとこんな感じになります。

スマホ(スクショ撮影)
 ↓
Safari(index.htmlを開く)
 ↓
画像を選択 → FileReaderがbase64に変換
 ↓
fetch()でGemini APIにPOST送信
  ・base64画像
  ・解析プロンプト
  ・APIキー
 ↓
Gemini(画像を解析してテキスト生成)
 ↓
JSONでレスポンスが返ってくる
 ↓
Safari(結果をページに表示)



実際にやることは「サーバー」に「index.html」を置いて画像の読み込みを行うだけ。



スクショの撮影方法


スマフォのスクリーンショットの作成方法については事前に確認しておきましょう。

ここはググればいくらでも出てきます。

iPhoneならこんな感じ。


iPhone: 「電源ボタン」と「音量を上げるボタン」を同時にカチッと押す



スクリプトの作成



以下のコードをコピーして『ファイル名.html』で保存します。

コードはこちら(お好きにコピーしてください。)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>ポケサポ</title>
<style>
  :root {
    --bg: #f0f2f5;
    --surface: #ffffff;
    --surface2: #e8eaed;
    --border: #d1d5db;
    --accent: #4f7ef7;
    --accent2: #2563eb;
    --gold: #d97706;
    --text: #1f2937;
    --muted: #6b7280;
    --success: #059669;
    --danger: #dc2626;
    --radius: 12px;
  }

  * { box-sizing: border-box; margin: 0; padding: 0; }

  body {
    background: var(--bg);
    color: var(--text);
    font-family: 'Hiragino Sans', 'Yu Gothic', sans-serif;
    min-height: 100vh;
    padding-bottom: 40px;
  }

  header {
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    padding: 14px 16px;
    display: flex;
    align-items: center;
    gap: 10px;
    position: sticky;
    top: 0;
    z-index: 10;
  }

  .header-icon {
    width: 36px;
    height: 36px;
    background: linear-gradient(135deg, #4f7ef7, #60a5fa);
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    flex-shrink: 0;
  }

  header h1 {
    font-size: 16px;
    font-weight: 700;
    color: var(--accent2);
    letter-spacing: 0.05em;
  }

  header p {
    font-size: 11px;
    color: var(--muted);
  }

  .apikey-section {
    margin: 16px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px;
  }

  .apikey-section label {
    font-size: 11px;
    color: var(--muted);
    display: block;
    margin-bottom: 6px;
    letter-spacing: 0.05em;
  }

  .apikey-row {
    display: flex;
    gap: 8px;
    align-items: center;
  }

  .apikey-row input {
    flex: 1;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 9px 12px;
    color: var(--text);
    font-size: 13px;
    font-family: monospace;
    min-width: 0;
  }

  .apikey-row input:focus {
    outline: none;
    border-color: var(--accent);
  }

  .btn-save {
    background: var(--accent);
    color: white;
    border: none;
    border-radius: 8px;
    padding: 9px 14px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    flex-shrink: 0;
  }

  .key-status {
    margin-top: 6px;
    font-size: 11px;
    color: var(--muted);
  }

  .key-status.ok { color: var(--success); }
  .key-status.ng { color: var(--danger); }

  .upload-section {
    margin: 0 16px 16px;
  }

  .upload-label {
    font-size: 11px;
    color: var(--muted);
    letter-spacing: 0.05em;
    display: block;
    margin-bottom: 8px;
  }

  .upload-box {
    background: var(--surface);
    border: 2px dashed var(--border);
    border-radius: var(--radius);
    padding: 24px 16px;
    text-align: center;
    cursor: pointer;
    transition: border-color 0.2s;
    position: relative;
  }

  .upload-box:active {
    border-color: var(--accent);
    background: var(--surface2);
  }

  .upload-box.dragover {
    border-color: var(--accent);
    background: var(--surface2);
  }

  .upload-box input[type="file"] {
    position: absolute;
    inset: 0;
    opacity: 0;
    cursor: pointer;
    width: 100%;
    height: 100%;
  }

  .upload-icon { font-size: 32px; margin-bottom: 8px; }

  .upload-text {
    font-size: 14px;
    font-weight: 600;
    color: var(--accent2);
    margin-bottom: 4px;
  }

  .upload-sub {
    font-size: 12px;
    color: var(--muted);
  }

  .preview-section {
    margin: 0 16px 16px;
    display: none;
  }

  .preview-section.show { display: block; }

  .preview-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
  }

  .preview-header span {
    font-size: 11px;
    color: var(--muted);
    letter-spacing: 0.05em;
  }

  .btn-clear {
    font-size: 12px;
    color: var(--danger);
    background: none;
    border: none;
    cursor: pointer;
    padding: 2px 6px;
  }

  #preview-img {
    width: 100%;
    border-radius: 10px;
    border: 1px solid var(--border);
    display: block;
    max-height: 260px;
    object-fit: contain;
    background: #e5e7eb;
  }

  .analyze-section {
    margin: 0 16px 16px;
  }

  .btn-analyze {
    width: 100%;
    background: linear-gradient(135deg, #4f7ef7, #60a5fa);
    color: white;
    border: none;
    border-radius: var(--radius);
    padding: 16px;
    font-size: 16px;
    font-weight: 700;
    cursor: pointer;
    letter-spacing: 0.05em;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    transition: opacity 0.2s, transform 0.1s;
  }

  .btn-analyze:active {
    opacity: 0.85;
    transform: scale(0.98);
  }

  .btn-analyze:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    transform: none;
  }

  .result-section {
    margin: 0 16px;
    display: none;
  }

  .result-section.show { display: block; }

  .result-label {
    font-size: 11px;
    color: var(--muted);
    letter-spacing: 0.05em;
    margin-bottom: 8px;
  }

  .result-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
  }

  .result-header {
    background: var(--surface2);
    border-bottom: 1px solid var(--border);
    padding: 10px 14px;
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .result-header span {
    font-size: 13px;
    font-weight: 600;
    color: var(--gold);
  }

  .result-body {
    padding: 14px;
    font-size: 14px;
    line-height: 1.75;
    color: var(--text);
    white-space: pre-wrap;
    word-break: break-word;
  }

  .loading-bar {
    margin: 0 16px 16px;
    display: none;
  }

  .loading-bar.show { display: block; }

  .loading-inner {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 20px 16px;
    text-align: center;
  }

  .spinner {
    width: 36px;
    height: 36px;
    border: 3px solid var(--border);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
    margin: 0 auto 12px;
  }

  @keyframes spin { to { transform: rotate(360deg); } }

  .loading-text {
    font-size: 13px;
    color: var(--muted);
  }

  .loading-dots::after {
    content: '';
    animation: dots 1.5s steps(4) infinite;
  }

  @keyframes dots {
    0%   { content: ''; }
    25%  { content: '.'; }
    50%  { content: '..'; }
    75%  { content: '...'; }
    100% { content: ''; }
  }

  .divider {
    height: 1px;
    background: var(--border);
    margin: 0 16px 16px;
  }

  .tip-box {
    margin: 0 16px 16px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 3px solid var(--gold);
    border-radius: var(--radius);
    padding: 12px 14px;
  }

  .tip-title {
    font-size: 11px;
    color: var(--gold);
    font-weight: 600;
    letter-spacing: 0.05em;
    margin-bottom: 6px;
  }

  .tip-text {
    font-size: 12px;
    color: var(--muted);
    line-height: 1.6;
  }

  .section-gap { height: 16px; }
</style>
</head>
<body>

<header>
  <div class="header-icon">⚔️</div>
  <div>
    <h1>ポケサポ</h1>
    <p>ポケモンチャンピオンズ バトルサポート</p>
  </div>
</header>

<div class="section-gap"></div>

<div class="apikey-section">
  <label>GEMINI API KEY</label>
  <div class="apikey-row">
    <input type="password" id="apikey-input" placeholder="APIキーを入力..." autocomplete="off" spellcheck="false">
    <button class="btn-save" onclick="saveKey()">保存</button>
  </div>
  <div class="key-status" id="key-status">未設定</div>
</div>

<div class="section-gap"></div>

<div class="upload-section">
  <span class="upload-label">スクリーンショット</span>
  <div class="upload-box" id="upload-box">
    <input type="file" id="file-input" accept="image/*" onchange="handleFile(event)">
    <div class="upload-icon">📸</div>
    <div class="upload-text">タップして画像を選択</div>
    <div class="upload-sub">カメラロール・ファイルから選択可能</div>
  </div>
</div>

<div class="preview-section" id="preview-section">
  <div class="preview-header">
    <span>プレビュー</span>
    <button class="btn-clear" onclick="clearImage()">✕ クリア</button>
  </div>
  <img id="preview-img" alt="preview">
</div>

<div class="analyze-section">
  <button class="btn-analyze" id="analyze-btn" onclick="analyze()" disabled>
    🔍 解析する
  </button>
</div>

<div class="loading-bar" id="loading-bar">
  <div class="loading-inner">
    <div class="spinner"></div>
    <div class="loading-text">ポケサポが解析中<span class="loading-dots"></span></div>
  </div>
</div>

<div class="result-section" id="result-section">
  <div class="result-label">解析結果</div>
  <div class="result-card">
    <div class="result-header">
      <span>🎮 ポケサポのアドバイス</span>
    </div>
    <div class="result-body" id="result-body"></div>
  </div>
</div>

<div class="section-gap"></div>

<div class="tip-box">
  <div class="tip-title">💡 使い方のヒント</div>
  <div class="tip-text">
    ① ポケモンチャンピオンズでスクショを撮影<br>
    ② このページで画像を選択<br>
    ③「戦況を解析する」をタップ<br><br>
    APIキーはこの端末のみに保存されます。
  </div>
</div>

<script>
let imageBase64 = null;
let imageType = null;

const STORAGE_KEY = 'gemini_api_key';
const MODEL = 'gemini-2.5-flash';

const PROMPT = `あなたはポケモンチャンピオンズ(M-Bレギュレーション、シングルバトル)の戦略アドバイザーです。

このスクリーンショットを分析して、以下の情報を提供してください:

【パーティ確認】
- 自分のパーティ(見えているポケモン)
- 相手のパーティ(見えているポケモン)

【現在の状況】
- 場に出ているポケモン
- HP状況、状態異常など
- ターン数・試合の局面

【戦略アドバイス】
- 今すぐ取るべき最善の行動
- 次のターン以降の方針
- 注意すべき相手の技・ポケモン

【勝率予測】
- 現在の有利不利の判断とその理由

画像から読み取れる情報のみで分析してください。`;

window.onload = function() {
  const saved = localStorage.getItem(STORAGE_KEY);
  if (saved) {
    document.getElementById('apikey-input').value = saved;
    updateKeyStatus(saved);
  }
};

function saveKey() {
  const key = document.getElementById('apikey-input').value.trim();
  if (!key) {
    setStatus('APIキーを入力してください', 'ng');
    return;
  }
  localStorage.setItem(STORAGE_KEY, key);
  updateKeyStatus(key);
}

function updateKeyStatus(key) {
  if (key) {
    setStatus('✓ 保存済み', 'ok');
  } else {
    setStatus('未設定', '');
  }
}

function setStatus(msg, cls) {
  const el = document.getElementById('key-status');
  el.textContent = msg;
  el.className = 'key-status ' + cls;
}

function handleFile(e) {
  const file = e.target.files[0];
  if (!file) return;
  const reader = new FileReader();
  reader.onload = function(ev) {
    const data = ev.target.result;
    imageBase64 = data.split(',')[1];
    imageType = file.type || 'image/jpeg';
    document.getElementById('preview-img').src = data;
    document.getElementById('preview-section').classList.add('show');
    document.getElementById('analyze-btn').disabled = false;
    document.getElementById('result-section').classList.remove('show');
  };
  reader.readAsDataURL(file);
}

function clearImage() {
  imageBase64 = null;
  imageType = null;
  document.getElementById('file-input').value = '';
  document.getElementById('preview-section').classList.remove('show');
  document.getElementById('analyze-btn').disabled = true;
  document.getElementById('result-section').classList.remove('show');
}

async function analyze() {
  const key = localStorage.getItem(STORAGE_KEY) || document.getElementById('apikey-input').value.trim();
  if (!key) { alert('APIキーを設定してください'); return; }
  if (!imageBase64) { alert('画像を選択してください'); return; }

  document.getElementById('loading-bar').classList.add('show');
  document.getElementById('result-section').classList.remove('show');
  document.getElementById('analyze-btn').disabled = true;

  const url = `https://generativelanguage.googleapis.com/v1beta/models/${MODEL}:generateContent?key=${key}`;

  const body = {
    contents: [{
      parts: [
        {
          inline_data: {
            mime_type: imageType,
            data: imageBase64
          }
        },
        {
          text: PROMPT
        }
      ]
    }]
  };

  try {
    const res = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(body)
    });

    const data = await res.json();

    if (!res.ok) {
      const msg = data?.error?.message || `エラー: ${res.status}`;
      throw new Error(msg);
    }

    const text = data?.candidates?.[0]?.content?.parts?.[0]?.text || '解析結果を取得できませんでした';
    document.getElementById('result-body').textContent = text;
    document.getElementById('result-section').classList.add('show');

  } catch (err) {
    document.getElementById('result-body').textContent = '⚠ エラー: ' + err.message;
    document.getElementById('result-section').classList.add('show');
  } finally {
    document.getElementById('loading-bar').classList.remove('show');
    document.getElementById('analyze-btn').disabled = false;
  }
}
</script>
</body>
</html>



サーバーにファイルの配置



作成したファイルをサーバーに配置します。

自分は『Conoha WING』を使用します。



※以下はAIがまとめてくれた無料でhtmlファイルを置ける場所になります。
 静的Webページ一枚を置くなら十分とのこと。

サービス無料枠特徴
GitHub Pages無制限GitHubリポジトリから自動公開
Netlify無制限ドラッグ&ドロップでアップ可能
Vercel無制限Netlifyと似た感じ
Cloudflare Pages無制限高速CDN付




※CONOHAを使用したファイルの配置例です。

① 『Conoha WING』のサーバーログインします。



② 『サイト管理』 → 『ファイルマネージャー』の順でクリックします。




③ ファイルマネージャーが起動します。




④ 『public_html』 → 『ドメイン名』の配下に作成したファイルを配置します。




⑤ 置いたファイルを『右クリック』 → 『情報』 を選択するとアドレスが表示されます。

  コピーしてGmailとかでスマフォに連携しちゃいましょう。



アプリの起動確認



前項で置いたファイルをiPhone(safari)のアドレスバーに張り付けます。

※黒塗りの部分ですね。



こんな画面が表示されればアプリの準備は完了です。


Google AI StudioからAPIキーを取得する


以前にやったようにGoogle AI StudioからAPIキーを取得します。


今回はiPhone(safari)で取得を行います。


① Google AI Studio を開き左上の【🉁】をタップします。
※ハンバーガーメニューっていうそうな。。



② 『Dashboard』をタップします。



③ 『APIキー』をタップします。



④ 『APIキーを作成』をタップします。



⑤ 『キーを作成』をタップします。



⑥ 赤枠の部分をタップしてAPIキーをコピーします。



※余談ですが、以下の部分でクレジットカード情報の登録がなければ

 基本的に無料枠での利用となります。



 これでAPIキーの準備も完了しました。


画像解析を実行する


あとは画像の解析を行うだけです。

① Gemini API KEY に 取得した『APIキー』を貼り付けて『保存』をタップします。



② 『保存済み』の表示が出ればOK



③ アプリを起動した状態でスクリーンショットを撮影します。

  ※以下は読み込みテストの為に用意したファイルです。




④ 『タップして画像を選択』をタップします。



⑤ 『写真ライブラリ』 から画像ファイルを選択します。

  画像が読み込まれると『プレビュー』が下部に表示されます。



⑥ 『解析する』をタップします。



⑦ 以下に解析結果が表示されます。


以外にちゃんと解析されてる?



<以下解析結果>

全文見たい方はこちらをクリック

### 【パーティ確認】
**自分のパーティ(選出可能ポケモン):** 1. **フシギバナ (Venusaur)** ♂ – メガフシギバナイト (Mega Venusaurite) – *メガシンカ可能*
2. **ミミロップ (Lopunny)** ♀ – メガミミロップナイト (Mega Lopunnite) – *メガシンカ可能*
3. **ワルビアル (Krookodile)** ♀ – こだわりスカーフ (Choice Scarf)
4. **ハラバリー (Bellibolt)** ♀ – たべのこし (Leftovers)
5. **マリルリ (Azumarill)** ♂ – オボンのみ (Sitrus Berry)
6. **ラウドボーン (Skeledirge)** ♂ – きあいのタスキ (Focus Sash)

**相手のパーティ(見えているポケモン):** 1. **リザードン (Charizard)** ♂ – ほのお/ひこう (Fire/Flying)
2. **カプ・テテフ (Tapu Lele)** ♀ – エスパー/フェアリー (Psychic/Fairy)
3. **テツノカイナ (Iron Hands)** ♀ – かくとう/でんき (Fighting/Electric)
4. **カバルドン (Hippowdon)** ♂ – じめん (Ground)
5. **マスカーニャ (Meowscarada)** ♂ – くさ/あく (Grass/Dark)
6. **ドラパルト (Dragapult)** ♂ – ドラゴン/ゴースト (Dragon/Ghost)


### 【現在の状況】
* **場に出ているポケモン:** なし。チーム選出段階です。
* **HP状況、状態異常など:** チーム選出段階のため、不明。
* **ターン数・試合の局面:** チーム選出の制限時間(残り1分24秒)内で、戦うポケモンを3匹選ぶ局面です。現在0/3匹選出済みです。


### 【戦略アドバイス】
相手のパーティは、起点作成役のカバルドン、スイープ役のリザードン(恐らくメガシンカか珠)、高速アタッカーのマスカーニャ・ドラパルト、高火力アタッカーのカプ・テテフ・テツノカイナと、非常にバランスが良く強力です。
特にカバルドン+リザードン(Yなら砂嵐で削られるが晴れで強化、Xなら砂嵐で削られるが物理技強化)の組み合わせ、カプ・テテフのサイコフィールド展開、高速のマスカーニャ・ドラパルトをどう対処するかが重要になります。

**今すぐ取るべき最善の行動(推奨選出):**
1. **フシギバナ (Venusaur) @ メガフシギバナイト:** * **選出理由:** 相手のカバルドンに強く、テツノカイナの格闘技を受けられ、マスカーニャの草技にも耐性があります。カプ・テテフのサイコフィールド下のサイコキネシスにも草タイプとしてそこそこの耐性があり、宿り木の種やヘドロ爆弾で削りや状態異常を狙えます。メガシンカすることで高い耐久力を誇ります。

2. **マリルリ (Azumarill) @ オボンのみ:** * **選出理由:** 相手のリザードン(特にY)に強い水タイプであり、フェアリータイプとしてドラパルトやマスカーニャに圧力をかけられます。カバルドンにも有効打があり、アクアジェットでリザードンのタスキや弱ったポケモンを縛ることができます。オボンのみで耐久も確保。

3. **ラウドボーン (Skeledirge) @ きあいのタスキ:** * **選出理由:** マスカーニャの弱点をつける炎タイプであり、ドラパルトのゴースト技を半減で受けられます。きあいのタスキで行動保証があり、おにびやトーチソングで相手の物理アタッカーや流し際に負荷をかけられます。テツノカイナにも炎技でダメージを与えられます。カプ・テテフのサイコフィールド下でも、ゴーストタイプは先制技を受けないため有利に動けます。

**選出の狙い:** * **初手読み:** 相手が初手カバルドンでステルスロック・砂嵐展開をしてくる可能性が高いです。その場合、フシギバナで悠然と対処し、眠り粉などで行動を制限できます。

* **リザードン対策:** マリルリで水技による弱点をつき、アクアジェットで縛ることを狙います。 * メガリザードンYならマリルリで対処可能。 * メガリザードンXの場合、物理攻撃はフシギバナで受け、ラウドボーンのおにびで弱体化を狙います。
* **高速アタッカー対策:** マスカーニャとドラパルトに対して、ラウドボーンが炎・ゴースト技で弱点を突き、マリルリがフェアリー技で処理を狙います。ラウドボーンのきあいのタスキで確実に1発耐え、反撃をすることができます。

* **テツノカイナ対策:** フシギバナの草技で弱点をつき、ラウドボーンの炎技も有効です。

* **カプ・テテフ対策:** フシギバナの毒技で削りつつ、ラウドボーンのゴースト技で弱点を突きます。マリルリはフェアリー技がテテフの弱点ですが、サイコフィールド下でのエスパー技が危険なので注意が必要です。
**次のターン以降の方針:**
* 相手のメガシンカ(リザードン)の形態を早めに見極め、対応するポケモン(リザYならマリルリ、リザXならフシギバナ/ラウドボーン)を繰り出します。
* カバルドンが出た場合は、フシギバナを繰り出して宿り木の種などで有利に展開し、裏のポケモンを削っていきます。
* カプ・テテフのサイコフィールド展開後も、フシギバナやラウドボーンで様子を見つつ、マリルリのフェアリー技で撃破を狙います。
**注意すべき相手の技・ポケモン:**

* **リザードンのメガシンカ形態:** Yであれば特殊火力、Xであれば物理火力と型が大きく変わるため、どちらの型か初手で確認することが最重要。

* **カプ・テテフのサイコフィールド:** こちらの先制技(マリルリのアクアジェットなど)が使えなくなるため、その間に高火力のサイコキネシスなどで突破されないよう注意が必要です。

* **カバルドンのステルスロック・あくび:** こちらのタスキを潰したり、行動を制限してくるため、フシギバナやマリルリで早めに処理したいところです。

* **マスカーニャのへんげんじざい(もしあれば)とトリックフラワー:** 高火力な先制技のない草タイプとして非常に危険。ラウドボーンやマリルリで対処します。

* **ドラパルトのりゅうせいぐん、ゴーストダイブ、とんぼがえり:** 高速からの高火力技やサイクル回しに注意が必要です。マリルリのフェアリー技で一貫を切りたい。

* **テツノカイナのパンチグローブ持ちのパンチ技、電気技:** 非常に火力が高いので、フシギバナの草タイプで対処し、弱点を突くことが重要です。


### 【勝率予測】
* **現在の有利不利の判断:** やや有利~五分
* **理由:**

* 相手のパーティは非常に強力で隙がありませんが、こちらの選出は相手の主要な脅威に対して明確な対策を準備できています。

* フシギバナがカバルドンやテツノカイナに強く、耐久面で安定感をもたらします。

* マリルリがリザードンY、ドラパルト、マスカーニャといったアタッカーに対して有効です。

* ラウドボーンがきあいのタスキでマスカーニャやドラパルト、カプ・テテフに確実に一撃を入れることができ、おにびによる物理アタッカーの機能停止も狙えます。

* メガシンカ枠をフシギバナにすることで、高い耐久で相手の攻撃を受け切りつつ、確実に負荷をかけていくことができます。

適切な選出と立ち回り次第で十分勝利を狙える状況と言えるでしょう。相手の選出を見極め、冷静に立ち回ることが重要です。




そんなことはなかったね。

まぁ、プロンプトを改修しているわけではないのでトンデモネー解析結果になっていますね。

ドラパもテテフもカイナも含めて、おりませぬ。

実際に運用してみる


テストファイルで動くのが確認できたので、実際に戦ってみましょう。

いい結果になるとは思えませんが…


<以下対戦画面>




<以下解析結果>

長いので見たい方はクリックしてください

### 【パーティ確認】
**自分のパーティ(左側):**
1. **キラフロル (Glimmora)**: ♂ / 毒・岩タイプ / 持ち物: キラフロルナイト
2. **アシレーヌ (Primarina)**: ♂ / 水・フェアリータイプ / 持ち物: たつじんのおび (Expert Belt)
3. **サザンドラ (Hydreigon)**: ♂ / 悪・ドラゴンタイプ / 持ち物: こだわりスカーフ (Choice Scarf)
4. **ヤバソチャ (Sinistcha)**: ♂ / 草・ゴーストタイプ / 持ち物: たべのこし (Leftovers)
5. **ズルズキン (Scrafty)**: ♂ / 悪・格闘タイプ / 持ち物: ズルズキナイト
6. **ソウブレイズ (Ceruledge)**: ♀ / 炎・ゴーストタイプ / 持ち物: きあいのタスキ (Focus Sash)
**相手のパーティ(右側):**
1. **マリル (Marill)**: ♂ / 水・フェアリータイプ / 持ち物: 不明
2. **メタグロス (Metagross)**: ♂ / 鋼・エスパー タイプ / 持ち物: 不明
3. **カバルドン (Hippowdon)**: ♂ / 地面タイプ / 持ち物: 不明
4. **ハギギシリ (Bruxish)**: ♂ / 水・エスパータイプ / 持ち物: 不明
5. **カイリュー (Dragonite)**: ♂ / ドラゴン・飛行タイプ / 持ち物: 不明
6. **リザードン (Charizard)**: ♂ / 炎・飛行タイプ / 持ち物: 不明

### 【現在の状況】
* **場に出ているポケモン:** なし(選出画面)
* **HP状況、状態異常など:** 該当なし
* **ターン数・試合の局面:** 選出フェーズ(残り時間 01:29)。まだ試合は始まっていません。
* **選出状況:** 0/3匹

### 【戦略アドバイス】
現在の状況は「選出」フェーズです。相手のパーティを見て、自分の6匹の中から3匹を選ぶ必要があります。

**相手パーティの主な特徴と脅威:**
* **物理アタッカーが多い:** メタグロス、カイリュー、カバルドン、マリル(恐らくちからもち)、リザードン(物理型もあり得る)。
* **特殊アタッカーも強力:** マリル(フェアリー)、ハギギシリ(水・エスパー)、リザードン(特殊型)。
* **耐性:**
* **フェアリータイプ(マリル):** ドラゴン・格闘に強い。
* **鋼タイプ(メタグロス):** 毒・フェアリーに強い。
* **地面タイプ(カバルドン):** ステルスロックや砂嵐展開の可能性、物理耐久が高い。
* **飛行タイプ(カイリュー、リザードン):** 地面無効。カイリューはマルチスケイルが強力。リザードンは岩4倍弱点。
* **特性の脅威:**
* **マリル:** 「ちからもち」の場合、非常に高火力。
* **カバルドン:** 「すなおこし」で砂嵐展開。
* **ハギギシリ:** 「ビビッドボディ」で先制技無効。
* **カイリュー:** 「マルチスケイル」により一撃で倒しにくい。

**自分のパーティの強みと相手への解答:**
* **「○○ナイト」持ちポケモン(キラフロル、ズルズキン):** もしこれがメガストーンであるならば、メガシンカにより大幅な能力アップと戦略の軸になる可能性があります。
* **タイプ相性:**
* **キラフロル (毒/岩):** マリルのフェアリー、カイリュー・リザードンの飛行、メタグロスの鋼、カバルドンの地面に弱点を突ける。
* **アシレーヌ (水/フェアリー):** カバルドンの地面、リザードンの炎、カイリューのドラゴンに弱点を突ける。
* **サザンドラ (悪/ドラゴン):** メタグロス・ハギギシリのエスパー、カイリューのドラゴンに弱点を突けるが、マリルのフェアリーが致命傷。
* **ヤバソチャ (草/ゴースト):** カバルドンの地面、マリルの水に弱点を突ける。
* **ズルズキン (悪/格闘):** メタグロスの鋼に弱点を突ける。
* **ソウブレイズ (炎/ゴースト):** メタグロスの鋼、ヤバソチャの草に弱点を突ける。タスキで行動保証。

**今すぐ取るべき最善の行動(選出ポケモン3匹の提案):**
相手のパーティは全体的に攻撃性能が高く、特にカイリューのマルチスケイル、マリル(ちからもち)の高火力、カバルドンの耐久と砂嵐展開など、厄介なポケモンが多いです。こちらはタイプ相性で弱点を突きつつ、相手の攻撃を受けきれるポケモンを選出することが重要です。

以下の3匹を選出することを推奨します。
1. **キラフロル (Glimmora)** * **理由:** 相手のカイリュー、リザードン、メタグロス、カバルドン全員に弱点を突ける「岩」タイプ技が非常に強力です。マリルの「フェアリー」タイプにも「毒」タイプ技で弱点を突けます。「キラフロルナイト」がメガシンカであれば、さらに強力なエースとして活躍が期待できます。初手から相手のサイクルを崩せる可能性があります。
2. **アシレーヌ (Primarina)** * **理由:** 相手のカバルドンに刺さる「水」タイプ技、カイリュー・マリルに刺さる「フェアリー」タイプ技の両方を持っています。リザードンの4倍弱点ではないものの、水技で弱点を突けます。「たつじんのおび」で火力も補強されており、カイリューのマルチスケイルも突破しやすいです。
3. **ソウブレイズ (Ceruledge)** * **理由:** 「きあいのタスキ」持ちなので、確実に1発耐えて行動保証があるのが強みです。相手のメタグロスに「炎・ゴースト」タイプ技で弱点を突け、カバルドンやカイリュー、リザードンにも一貫性のある打点があります。ハギギシリのビビッドボディを考慮すると、先制技を読み違える心配もありません。
**選出候補から外したポケモンとその理由:**
* **サザンドラ (Hydreigon):** こだわりスカーフで高速アタッカーですが、マリルのフェアリータイプが致命的に厳しく、選出リスクが高いと判断しました。 * **ヤバソチャ (Sinistcha):** たべのこしで耐久寄りの型と思われますが、相手の攻撃的なパーティに対しては火力不足になりがちです。

* **ズルズキン (Scrafty):** ズルズキナイトが強力であれば候補ですが、相手の飛行タイプ(カイリュー、リザードン)とフェアリータイプ(マリル)に弱く、エスパータイプ(メタグロス、ハギギシリ)の攻撃を受けにくい点がネックです。

**次のターン以降の方針:**
* **初手:** 相手の選出を見て判断します。
* カバルドンが出た場合: アシレーヌの「水」技、キラフロルの「岩」技などで負担をかけられます。
* カイリューが出た場合: キラフロルの「岩」技、アシレーヌの「フェアリー」技で対処できます。
* メタグロスが出た場合: ソウブレイズの「炎」技、キラフロルの「岩」技などで対応。
* マリルが出た場合: キラフロルの「毒」技、アシレーヌの「フェアリー」技で有利に立ち回れます。
* **交代:** 相手の攻撃を受けられるポケモンに躊躇なく交代し、タイプ相性を有利に保ちます。
* **削り:** 一貫性のある技でダメージを蓄積させ、一匹ずつ確実に突破していきます。

**注意すべき相手の技・ポケモン:**
* **マリル(水・フェアリー):** 「ちからもち」からの「アクアジェット」「じゃれつく」の超火力。
* **メタグロス(鋼・エスパー):** 「コメットパンチ」「バレットパンチ」「しねんのずつき」「じしん」など、高い攻撃力と先制技。
* **カバルドン(地面):** 「すなおこし」による定数ダメージと砂嵐下での「とくぼう」上昇。「ステルスロック」「じしん」「なまける」「ふきとばし」などで耐久戦術。
* **ハギギシリ(水・エスパー):** 特性「ビビッドボディ」による先制技無効。読み間違いに注意。「サイコファング」「アクアブレイク」など。
* **カイリュー(ドラゴン・飛行):** 特性「マルチスケイル」による耐久力と、「りゅうのまい」からの「しんそく」「げきりん」「じしん」などの全抜き性能。
* **リザードン(炎・飛行):** 「りゅうのまい」からの物理型、または「ひでり」からの特殊型(ソーラービーム、ぼうふうなど)の可能性。岩4倍弱点だが、もしメガシンカが許されている環境ならメガリザードンX/Yも考慮。


### 【勝率予測】
**現在の有利不利の判断とその理由:**
**勝率:やや有利**
* **理由:**
* **メガシンカの可能性:** こちらのパーティに「キラフロルナイト」「ズルズキナイト」という、ポケモン名+ナイトという表記があるため、もしこれがメガシンカアイテムであれば、個々のポケモンのスペックで相手を上回る可能性があります。特にキラフロルは相手の多くのポケモンに弱点を突けるため、メガシンカで能力が上がれば非常に強力なエースになります。
* **選出の柔軟性:** 今回提案した3匹は、相手のパーティ全体に安定して対応できるタイプ相性と役割を持っています。特にカイリューやマリル、カバルドンといった厄介なポケモンへの対策をしっかり組めています。
* **アイテムの明確さ:** 自分のポケモンの持ち物は全て判明しているため、明確な戦略を立てやすいです。対して相手の持ち物が不明であるため、サプライズ要素はあるものの、こちらが警戒しやすいという側面もあります。
しかし、相手のパーティも非常に強力な面々が揃っており、持ち物や技構成次第では厳しい戦いになることも予想されます。特にカイリューのマルチスケイル+竜の舞、マリルのちからもち+アクアジェット、カバルドンの砂嵐展開などは常に警戒が必要です。

この選出と戦略で、チャンピオンを目指しましょう!  


はい、こんなもんでしょう。



所感


と言うわけで、スマフォで画像解析を行う方法となりました。

今回のスクリプトでは1枚の画像解析に約40~50秒程度かかりました。
※無論、通信環境やスマフォのスペックによると思いますが。

実際に『ポケモンチャンピオンズのスクショの撮影(1~5秒)』 → 『ブラウザ(safari)からファイルの選択(1~5秒)』 → 『解析ボタンをタップ(1~5秒)』 → 『解析時間(40~50秒)』 → 『解析結果の確認(プライスレス)』 

これを選出時間の90秒でやるのは人類の限界を超えるんじゃないかな?


あと老眼のおっさんからするとスマフォの画面は読みづらい…

パソコンはあった方がいいなと思いました。

ブラウジングやら、少しコード書く程度なら整備済みパソコンとか以外に安くて便利ですよ。


以上