記憶を残すために

2026-09-29 - 作者 EVE Online Team

「EVE Evolved」構想の取り組みの一環として、EVE OnlineのクライアントおよびサーバーをPython 2からPython 3へアップグレードする作業が継続中です。この作業は、より強固な基盤の上に構築を進め、今後長年にわたる開発に備えるために重要なものです。

「記録保管局」

今回の「EVE Evolved」では、NPCエージェントの記憶について考察しています。毎日約10万件のミッションを管理するという複雑な処理をどのようにこなしているのか、また、将来的にプレイヤーにどんな影響を及ぼす可能性があるのか、その興味深い課題についても触れています。

このブログで言う「エージェント」とは、EVEに登場するNPCエージェントのことを指します。報酬と引き換えに、ゴミを別のステーションまで運んだり、新たな海賊の脅威を排除したり、あるいはまたしてもあのかわいそうな乙女を救い出したりするよう(時には無礼な口調で)依頼してくる、あの愛すべきキャラクターたちのことです。

「簡単なことから」

技術的な詳細解説がお好きな皆さんに向けて、かなり細かな内容までお伝えします。ただし、要点だけ知りたいという方のために、ここですぐに把握できる重要なポイントをまとめました。

  • Python 3へのアップグレードによるEVE Online刷新の一環として、NPCエージェントのデータ保存方法に変化が必要となっています。ミッションやエージェントとのインタラクションの追跡方法については、バックエンドでのアップグレードが行われます。これに伴って、一部の古いデータを削除するとともに、残りのデータを将来性のある形式に変換する必要があります。

    • この処理は、おおむね目に見えない形で実行されます。唯一目に見える影響は、2026年9月29日より前に保存された過去のミッションの進捗にどのような変化が生じるかという点に限られるはずです。

  • NPCスタンディングは維持されます。また、すでにアンロックしたエージェントは、あなたが現在ログインしていなくても、または現在オメガのスタンディングでなくても、引き続き利用可能で、進行状況が失われることはありません。

  • 本日以降、新たなエージェントミッションをリクエストした場合(または既存のミッションを完了/失敗した場合)、そのミッションの進捗は自動的に新しい記憶に継承されるようになりました。

  • 本日以前に、あるエージェントとやり取りをしたことがあり、かつ本日以降、進捗更新のためにそのエージェントとやり取りをしなかった場合、Python 3への移行が完全に完了した時点で、そのエージェントからのジョブはすべて削除されます。

    • 本件はPython 3への大規模な移行の一環に過ぎないため、データ削除がいつ行われるかについて、現時点では明確なスケジュールは決まっていません。このプロセスには数日ではなく数ヶ月を要する見込みです。実施時期が近づきましたら、記憶を削除する前にお知らせいたします。

    • 本日より前にオファーされた、または受諾済みのミッションがあり、本日以降、そのミッションを完了するためにエージェントとやり取りを行わなかった場合、将来的にはそのミッションの進捗がリセットされることになります。

    • 本日の時点で、研究ポイントの獲得を目的としてリサーチエージェントと契約している場合は、そのエージェントを有効な状態に保つために、本日以降にそのエージェントとのミッションを少なくとも1つ完了させる必要があります(これは、キャラクター1人につき、エージェント1人に対して1回だけ行えば十分です)。なお、本日以降一度もアクセスされなかった古い研究ジョブは、順次すべて削除される予定です。

要するに、あなたが現在エージェントミッションを積極的にこなしているなら、そのまま通常通りプレイを続けても問題はなく、何も変わりません。もし大切にしているエージェント(特にリサーチエージェント)がいるなら、そのエージェントを訪ねてミッションを1つこなしてあげましょう。そうすれば、相手から忘れられることはありません。

基礎を押さえたところで、エージェントの買いだめ癖や、過去の秘話についてさらに詳しく知りたいという方は、引き続きお読みください…

「衝突する対立勢力」

「エージェントの記憶」が何を指すのかを理解するには、まずは背景説明が不可欠です。Python 3プロジェクト全体を分類すると、以下の大きな分野に分かれます。

  • ランタイム - ゲームを動作させるクライアントおよびサーバーの実行ファイル。

  • データ - EVE Onlineならではの体験を構成する情報の断片。下のようにさらに細分化することも可能です。

    • コンテンツデータ - アーティスト、デザイナー、ライターが制作するモデル、テクスチャ、テキスト、ステータスなど、あらゆるコンテンツ。クライアントの提供データとしてユーザーに配信されるものもあれば、当社のサーバー内にのみ保存されているものもあります。

    • ネットワークデータ - インターネットを介して、お使いのクライアントと弊社のサーバーの間でやり取りされる情報パケット、およびデータセンター内の弊社サーバークラスタに属する200以上のノード間で行き交う情報パケットのことです。

  • 永続化済みデータ - ゲーム内での20年以上にわたる進捗を記録した、延々と増え続ける「セーブファイル」。主にこれが、EVEの中核をなす巨大なSQLデータベースです。ここにエージェントの記憶が保存されています。

  • 開発者エコシステム - 我々開発者が、皆さんにゲームをお届けするために日々の業務で活用しているツールやプロセス。

「エージェントへの聞き取り」

エージェントの記憶がどこにあるかがわかったので、次はその実体についてご説明しましょう。キャラクターがNPCエージェントとやり取りを行うたびに、データベースにその事実が記録されます。そのやり取りとは、新しいミッションの依頼、以前にオファーされたミッションの完了(または失敗)、リサーチタスクやロケータージョブの開始、あるいは特別なストーリーラインのエージェントへの紹介といった行為を指します。

各エージェントは、これまですべてのキャラクターと交わした最後のやり取りの内容を把握しています。もし20年ぶりにそのエージェントを訪ね、怪しげなホロリールを取り戻すというミッションを始めたとしても、そのエージェントはあなたのことを覚えており、あなたが妥当な期限内にミッションを遂行できなかったといまだに文句を言おうとしています!

エージェントがあなたのキャラクターについて保持する可能性がある記憶には、次のようなものがあります。

  • そのエージェントがあなたにどのミッションをオファーしたか、およびそのミッションの進捗状況(例:ターゲットとなるNPCはすでに倒されたか?)

  • エージェントがリサーチタスクを行っている場合は、その進捗状況

  • あなたから別のキャラクターを探し出すよう依頼されたかどうか

  • 連続したストーリーラインの進行度合い

  • あなたがどのエピックアークやキャリアミッションをクリアしたか

なお、NPCキャラクターやコーポレーションとあなたのキャラクターとの間のスタンディングや関係性は、このエージェントの記憶には含まれていません。スタンディングは分離した独自の仕組みとして扱われ、その状態のトラッキング方法も個別に定められています。

「データ取得」

とうとう、データの保存や取得の方法、そしてこのブログを書いた理由について触れます。

さかのぼること2000年代の初頭、EVE Onlineがサービス開始に向けて最終段階に入っていた頃、エージェント記憶データベースの構想が生まれました。 その要件は、エージェントとキャラクターペア間の相互作用を表現する複雑な状態を保存することでした。通常、データベース設計では、こうしたデータに対してテーブルとリレーションシップの非常に厳密なモデルを構築しようとします。しかしながら、エージェント記憶の要件は複雑で動的でした。やり取りごとに変数のセットが大きく異なっていたのです(例えば、輸送ミッションとストーリーラインでの紹介の説明について比べてみてください)。さらに、ゲームの進化に伴い、設計も急速に変化していました。

この時点では、現代的なNoSQL運動はまだ始まっていませんでした。EVEは、永続化層としてMSSQLを断固として使い続けていました。ある賢いプログラマーは、エージェントの記憶を格納しているPythonオブジェクトをバイナリブロブにシリアライズして、そのブロブをテキストとしてデータベースのテーブルに格納できることに気づきました。

そして、そのエージェントがキャラクターとのインタラクションによって次に起動された際、逆の手順が行われます。そのエージェントのバイナリブロブがデータベースから取得され、デシリアライズしてPythonオブジェクトに戻され、それが実行中のエージェントに注入されることにより、記憶が復元されます(Pythonでは、このプロセスはpickle化およびunpickle化とも呼ばれます)。

これによって当面の問題は解決しましたが、それにより将来的に2つの問題が生じることになりました。

  • 記憶ブロブの検索は容易ではない。データベースの真価は検索機能にあります。つまり、あるパラメータが特定の値を持つすべてのエントリを発見できることです。しかし、各記憶がPythonのエンベロープで包まれていたため、その内部を効率的にクエリすることは不可能でした。例えば、前述の「乙女」に関連するすべての記憶を見つけるには、確認のためにすべての記憶を1つずつPythonに読み込む必要がありました。これは理想的とは言えません。

  • データ形式は、使用中のPythonのバージョンに強く関連付けられている。Python言語が進化するにつれ、新機能が追加されたり、既存の機能が使われなくなり、最終的には廃止されたりしました。すなわち、いつの日か、これらの記憶は読み取れなくなり、まるで雨に溶ける涙のように失われてしまうというわけです。Python 2から3への移行に伴い、その日がもうすぐ訪れようとしています。

「秘密の隠し場所」

この問題を技術用語を使わずに例えで説明すると、引っ越しの際に荷物を倉庫に預けないといけなくなったと想像してみてください。やり方の1つとして、すべての荷物を1つの巨大な密封コンテナに詰め込み、それを倉庫へ送るという方法があります(これがデータの「シリアライズ」です)。この方法は融通が利き(コンテナを運ぶトラックは、中に入っている音楽コレクションがレコードかCDかなど気にしません)、作業効率が良く、コンテナ輸送はすでに定型化されたプロセスとなりました。

後日新居に引っ越す際、コンテナを配送してもらい、大切な荷物を開梱できます。ただし、これには欠点もあります。もし倉庫が、違法な資源が保管されていないことを確認するために安全監査を義務付けられている場合、すべてのコンテナを開けて手作業で検査するしかありません。あまり効率的なプロセスとは言えません。

「機器の輸送」

この手法は、長期的な欠点があったにもかかわらず、結果は成功でした。EVE Onlineは無事にサービスを開始し、その後も継続しました。エージェントの記憶に関する解決策は、諸般の事情を考慮すれば、驚くほど良好に機能し続けました。しかし、永遠に続くものなどありません。

「記録消去」

Python 3への移行は、過去の手落ちを是正する絶好の(文字通り、見逃すことができない)機会となっています。SQLデータベースへPythonのブロブを格納することによる柔軟性の欠如や、本質的な陳腐化から脱却する必要があります。同時に、この機会を利用して整理整頓を行い、蓄積された大量のデータを一掃する予定でもあります(エージェントの記憶テーブルは、弊社データベース内で最大規模のテーブルの一つであり、唯一増え続けるだけで決して縮小することのない数少ないテーブルの一つでもあります)。

「死の二人組」

本作業はすでに水面下で始まっています。最近、エージェントの記憶の読み込みおよび保存方法を更新しました。新しい記憶を保存する必要がある場合は、今後は以下の2つの形式で平行して処理を遂行します。

  • 従来通りの、不透明なPythonブロブ形式。

  • 特定のPython形式に依存せず、より良い検索性と将来への適応性を確保した、将来を視野に入れた新しい透明な形式。

新規または更新された記憶は、当面の間、両方の形式で存在することになります。今日、エージェントにミッションを依頼した場合、その記憶は両方の形式で保存されます。これにより、エージェントの記憶を読み込む際に、どちらの形式を優先するかを私たちが選択できるようになります。また、古い方式を廃止する前に、両方の形式が同じ内容であることを確認できるため、リスクを軽減にもなります。

エージェントの記憶をデータベースから読み込む必要がある場合、優先に扱うソースを指定するためのオプションが複数できました。これを3つの段階で使い分けていきます。

  • 第1段階:当面は、新形式が正しく動作していることが確認できるまで、従来のストレージからのみ読み込みを継続します。

  • 第2段階:次に優先順位を切り替え、まず新形式の記憶を検索し、それでも見つからない場合は、旧形式から読み込むようにします。

  • 第3段階:最終的には(あらゆる要素をPython 3へ完全に移行した時点で)、旧形式からの読み込みを完全停止します。エージェントが利用できるのは、新形式で保存された記憶のみとなります。そうすれば、一度も更新されなかった古いレガシー記憶をデータベースから削除することができ、データベース管理者の負担を軽減できます。

Python 3への移行に伴い、本日より、新規の記憶はすべて引き継がれることになります。この移行作業は長期にわたるため、エージェントとやり取りしたり、新しいミッションを請け負ったり、既存のミッションを完了させたりする時間は十分に確保されています。移行期間については、数ヶ月単位の話であり、数日単位ではありません。第3段階がより近づくにつれ、その旨を必ずお知らせします。

「戦争準備のための資源」

古い記憶であっても、また、関連キャラクターがログインしなかったり、エージェントごとに新しい記憶が生成されなかったりする場合であっても、必ず継承すべき記憶がいくつかあります。例えば、特定のチュートリアルやエピックアークのミッションは一度きりのものなので、その記録を追跡する必要があります。こうした限られたケースにおいては、バックグラウンドでデータが自動的に新しい形式へ移行されます。

キャラクターとエージェントの関係性を構成する重要な要素の一つが「スタンディング」です。これは、レベル1のエージェントからレベル4、さらにはレベル5へとランクを上げていく過程で築き上げていくものです。キャラクターとNPCエージェント、コーポレーション、勢力との間のすべてのスタンディングは維持され、今回の変更による影響は受けません。これらのスタンディングがリセットされたり、失われたりすることはありません。

「建築材の輸送」

Python 3 への移行作業は続いています。クライアント/サーバー側のコードを変換するという「簡単な」作業に加え、コードを取り巻くあらゆる要素を更新する作業も、それと同程度、あるいはそれ以上の労力を要します。 開発者が日々利用しているツールは数多くあります。例えば、Pythonプロセスがネットワークを介して他のコンポーネントと通信する、数多くの境界があります。また、ボタンを押すだけで拡張機能を本番環境に公開できるデプロイプロセスもあります。

また、これまで見てきたように、データベース内に保存されているデータでさえ、時折更新が必要になることがあります。

安全な良き航海を。また近いうちに別のブログでお会いしましょう o7