【開発[#2] 38日目】戦略SLG

今回は37日目〜38日目の作業まとめになります。

この2日間は、AIの外交判断、謀略コマンド「引抜」、外交コマンド「破棄」など、勢力間の駆け引きに関わる処理を中心に進めました。また、演出面では季節エフェクトの本体連結も行い、開発運用そのものの見直しにも着手しています。
地味な内部処理が多めですが、戦略SLGとしてはかなり重要な土台部分です。

■ 37日目:AI外交コマンド「同盟/親睦」の本実装

37日目は、AI思考ルーチンに外交コマンド「同盟」と「親睦」の判断・発行ロジックを実装しました。

対象となるのは、AIコマンド入力フェーズの外交処理です。いきなりコードを書くのではなく、まずは仕様をかなり細かく確認しました。その過程で、当初のフローに到達不能な分岐、いわゆるデッドコードのようなものがあることが分かりました。
こういう部分は、後で無理にコードだけ整えようとすると高確率で破綻するので、先に仕様側を整理しています。

■ AI外交判断を四段構造に再設計

最終的に、AIの外交判断は大きく4段階の流れに整理しました。
まず、同盟相手や同盟可能勢力の中に、信頼度40以上の相手がいなければ親睦を優先します。成功率の低い同盟要請を無理に出すのではなく、まずは関係改善を狙う形です。
次に、同盟数を見て同盟行動へ進むかどうかを判断します。同盟数が0なら同盟行動を優先し、すでに1つ同盟がある場合は一定確率で同盟を狙う、という流れです。

親睦を行う場合は、同盟の有無によって対象候補や閾値を切り替えます。
同盟を行う場合は、同盟可能勢力の中から「同盟優先度数」を使って候補を抽選し、相手の信頼度に応じて同盟か親睦かを分岐させます。

文章にすると少しややこしいですが、要するに、

・味方がいないなら同盟を狙う
・信用できる相手がいないなら親睦する
・同盟しすぎて戦争相手がいなくなる状態は避ける
・状況に応じて、外交と戦争の余地を両方残す

という思想です。

■ 同盟可能条件の整理

同盟可能な相手の条件も明確化しました。
今回の実装では、以下の条件をすべて満たす勢力だけを同盟候補にしています。

・相手の同盟数が2未満であること
・同盟しても出陣先、つまり非同盟の隣接勢力が残ること
・同盟しても全生存勢力と同盟関係にならないこと

特に重要なのは、同盟によってAIが動けなくなる状況を防ぐことです。
戦略SLGでは、外交が強すぎると盤面が止まってしまうことがあります。
逆に、外交が弱すぎると同盟や親睦が空気になります。
今回はその中間を取るために、「同盟はするが、戦争できる余地は残す」という制約を入れています。

■ 同盟優先度数の導入

同盟候補の抽選には、単純なランダムではなく「同盟優先度数」を使う形にしました。
同盟優先度数は、友好度をベースにしつつ、非隣接勢力や名声の低い勢力に補正を加えています。隣接勢力だけと同盟し続けると、戦争対象が減ってしまいやすいため、非隣接勢力に少し加点(遠交近攻)しています。また、名声が低い勢力は外交面でやや同盟を求めやすい、という扱いです。

このあたりは、数字としては地味ですが、AIの行動傾向をかなり左右する部分だと思います。

■ AIは信頼度を全参照する仕様に

信頼度については、本来プレイヤー側では諜報力60以上で参照可能になる情報です。
ただし、AIは判断材料として信頼度を全参照する仕様にしました。

いわゆるAI特権です。

プレイヤーに見えない情報をAIが見るのは少しズルく見える部分もありますが、AIが外交判断をするためには、ある程度情報を持っていないと自然な動きになりません。
プレイヤー側はマスク表示、AI側は判断材料として参照、という形で割り切っています。ただAIは諜報力維持行動の優先度が高いので諜報力0とかになることは基本的にないようAI調整してます。大体50~60は最低限維持するようなAI行動パターンです。

■ 37日目の成果

実装としては、ManagerPhase.cs に AssignDiplomacy と関連ヘルパーを追加しました。36日目に整備した拠点所有データも、隣接判定の土台として活用しています。これにより、AIが同盟・親睦コマンドを判断し、発行するところまで動くようになりました。
ただし、現時点では同盟や親睦の「締結処理」や「友好度変動」は、まだ数値変動フェーズ側が未実装です。
つまり、AIが外交コマンドを出すところまではできていますが、その結果を実際に反映する部分は後日実装となります。
中間状態ではありますが、段階的な実装としては予定通りです。

■ 38日目:季節エフェクト、引抜、破棄、開発運用の見直し

38日目は、複数の作業をまとめて進めました。
大きく分けると、

・季節エフェクトの本体連結と是正
・謀略コマンド「引抜」の数値処理
・外交コマンド「破棄」の決済処理
・開発運用の見直し

の4つです。
この日は見た目の演出と、内部の数値処理の両方を触っています。

■ 季節エフェクトの連結是正

まず、季節エフェクトを本体コードへ連結しました。
これは、四季に応じて画面上に舞い落ちるパーティクルと、画面端のグラデーションを出す演出です。
春・夏・秋・冬で画面の雰囲気を変えるためのものです。
今回の季節エフェクトは、独立性の高い演出部分として別AIに作らせ、その後で本体コードへ連結・是正するという流れで進めました。

この開発フローは今回が初回運用です。
切り出せる演出系は別AIで作成し、本体担当側では連結と調整に集中する、という形です。うまく回れば、かなり開発効率が上がりそうです。

■ 季節判定ロジックを GameUtility に集約

連結時に確認したところ、季節算出ロジックが複数箇所に重複していました。
このままだと、後で季節の仕様を変えたときに、どこかだけ修正漏れする危険があります。
そこで、季節算出ロジックは GameUtility に集約しました。
季節が変わっても1箇所を直せばよい構造になったので、保守性はかなり改善されたと思います。
また、グラデーション用マテリアルの破棄処理も追加し、メモリリーク対策も行いました。
文字エンコードの混在チェック、季節列挙型の統合、不要になった独立ファイルの削除も実施しています。
シェーダについても、プロジェクト規約である Built-in RP 準拠、Shader Graph 不使用で問題ないことを確認しました。
最終的に、演出側の季節判定式と本体側のゲーム処理の季節判定が一致していることも確認しています。

これで、「画面演出上は春なのに、ゲーム処理上は夏」みたいな事故は避けられるはずです。

わかりにくいかもしれないが秋には紅葉や枯れ葉がひらひらと舞う


■ 謀略コマンド「引抜」の数値処理を実装

次に、謀略コマンド「引抜」の結果処理を実装しました。
これは他勢力の武将を引き抜くコマンドです。
今回実装したのは、コマンド実行後の結果処理、つまり数値変動フェーズ側の処理です。
ここも、仕様の矛盾や不明点を整理してからコード化しています。

引抜の結果は、

・完全成功
・部分成功
・失敗

の3パターンに分かれます。
1回の乱数でこの3分岐を判定する形です。

■ 引抜の完全成功・部分成功・失敗

完全成功した場合、対象武将は相手勢力から出奔します。
発覚した場合は、相手勢力との友好度が下がります。
引き抜いた武将は一度在野へ放流され、プレイヤー側であれば登用判断へ、AI側であれば空席があれば即登用する形です。部分成功の場合は、対象武将の忠誠が下がります。
さらに、対象以外の配下にも巻き添えで忠誠下落が発生する可能性があります。ただし、配下人数が多いほど巻き込まれにくくなるように、傾斜確率を入れています。
失敗した場合は、相手勢力との友好度が下がり、さらに実行武将の捕縛判定が発生します。このあたりは、謀略コマンドらしくリスクとリターンが出るようにしています。
適用特技としては、明晰・英傑による知力補正、篭絡による完全成功率上昇、潜伏逃亡による捕縛回避などを反映しました。

■ 登用UIは後日実装

完全成功時の登用UIについては、今回はまだ実装していません。
これは満席時の入替UIに依存するためです。
枠だけ残して、後日その周辺のUIとあわせて実装する予定です。
こういう部分は無理に仮実装すると後で作り直しになりやすいので、今回は処理本体を優先しました。

■ 外交コマンド「破棄」の決済処理を実装

続いて、外交コマンド「破棄」の処理を実装しました。
これは同盟を破棄するコマンドです。
処理場所は、数値変動フェーズの外交処理段階になります。
破棄は相手に拒否されず、100%成立する決済として扱います。

実装内容としては、

・双方の同盟状態を解消
・双方の友好度を下落
・破棄した勢力の名声を下落
・関連特技による補正を適用

という形です。
同盟破棄は便利な行動ですが、ノーリスクだと強すぎます。
そのため、友好度と名声の両方にペナルティが入るようにしています。
適用特技としては、明晰・求心・英傑による能力補正、無才によるペナルティ最小化を反映しています。

また、名声の変動処理も1箇所に集約しました。
今後、名声が上がる処理を追加する場合も、同じ処理を通す方針です。
地味ですが、後で効く整理です。

■ 即時破棄ペナルティは将来実装

仕様上、「敵勢力の同盟勝利が迫った際の即時破棄」には大きなペナルティを入れる想定があります。
ただし、この処理は勝敗判定ロジック自体に依存します。現時点では勝敗判定ロジックが未実装のため、今回は将来の実装項目として残しました。
こういう依存関係のある処理は、先に無理やり作るより、土台ができてから入れた方が安全です。

■ 開発運用の見直し

最後に、開発運用そのものも見直しました。
最近はAIを併用しながら開発を進めていますが、長い作業を続けていると、チャットや引き継ぎ情報が肥大化しがちです。

そこで、チャットの区切り方を見直しました。
これまでは日付単位で区切る意識がありましたが、今後は「1タスクが完結し、次の作業が独立するタイミング」を基準にします。議論が続いているなら、日をまたいでも同じ流れで扱います。一方で、ブログや広報用の日次区切りは、チャット内の区切り対話マーカーで担保する形にします。
これにより、開発作業としての区切りと、ブログ記事化の区切りを分けられるようになります。

■ 引き継ぎドキュメントも2層構造へ

引き継ぎドキュメントも見直しました。

今後は、

・常設コア
・作業状態

の2層構造に分けます。
常設コアには、滅多に変わらないルールや仕様を置きます。
作業状態には、今まさに進行中のタスクや一時的な情報を置きます。
完了済みタスクの細かい経緯は基本的に破棄し、そこから派生した恒久ルールだけをコアへ昇格させます。
これにより、引き継ぎ情報の肥大化を抑えられるはずです。
開発そのものだけでなく、開発を続けるための仕組みも整えていく段階に入ってきた感じがあります。

■ 現時点の開発状況

今回の作業で、勢力間の駆け引きに関わる処理がかなり前進しました。
AI思考ルーチンの外交判断、謀略「引抜」、外交「破棄」と、戦略SLGらしい内部処理が増えてきています。
数値変動フェーズについては、残る大きなものがAI外交判断まわりに絞られてきました。
AIコマンド入力フェーズの通常処理も、ほぼ完成に近づいています。
一方で、出陣・援軍系については、戦争解決フェーズに依存する部分が大きいため、今後はそのあたりが大きな山になりそうです。

■ 次回の作業予定

次回以降は、今回残した外交結果の反映や、戦争解決フェーズに関わる処理を進めていく予定です。特に、出陣・援軍系の処理はゲームの中核に関わるため、仕様を整理しながら慎重に進めたいところです。
また、季節エフェクトについては、動画撮影してSNS投稿にも使えそうなので、見た目の調整も少しずつ進めていきます。内部処理と演出の両方が少しずつ揃ってきて、だいぶ戦略SLGらしい形になってきました。

引き続き『王国創世記 -Kingdom Chronicle-』の開発を進めていきます。

※2週間くらいで作るつもりでしたが、もう開発40日目が目前です(笑)