Python
C++
game
自動化
人工知能

ソリティアの自動プレイでスコアを稼いでみた

はじめに

ソリティアの累積ベガスルールを自動プレイするプログラムを作成し、スコアを稼いでみました。

背景

数年前からWindowsソリティアの特に累積ベガスルールに興味を持ち、攻略法がないか調べたのですが、有名なゲームにもかかわらず攻略法の文献は少なく累積ベガスについては皆無という状況です。
しばらく自己流で頑張っていましたが限界を感じたので思考エンジンを開発して自動プレイを行ってみました。
ゲームの名称は正式にはKlonedikeですが、「ソリティア」のほうが知名度が高いと思うので、この投稿では「ソリティア」と呼ぶことにします。

ソースコードは https://github.com/dsanno/Klondike-Solver で公開しています。

各種設定

ゲームの設定は以下のようにしました。

設定名 設定値 備考
OS Windows 10
アプリケーション Microsoft Solitaire Collection
ゲームの種類 KlonDike
一回に引く枚数 3引く
スコアタイプ 累積型ベガス
タイマー オフ オンにするとクリア時に大量のスコアが加わってしますのでオフにしてあります
常にランダムな山札でプレイ オン
元に戻す 「元に戻す」禁止 カードの先読みができてしまうので禁止にしています
思考時の入力 視覚情報のみ利用 メモリの内部を調べて伏せてあるカードの状態を特定するのは禁止です

得点について

累積ベガスルールでは、ゲーム開始時に52点引かれます。
そして組札(右上のスペースにあるカード)1枚につき5点加算されます。
52枚すべてを組札にすると260点加算され、開始時の減点と合わせると208点が加わります。
得点は次のゲームに持ち越され、累積スコアをできるだけ高くするのが目的です。

思考アルゴリズム

思考アルゴリズムはKondike-Solver をベースに実装しました。
Klondike-Solverでは、カードの初期状態を入力すると、クリアまでの最短手順を計算します。
ただし、カードは伏せてあるものも含めてすべて既知であることを想定しています。

これを以下のように改造しました。
あまり深くまで探索すると時間がかかるので、探索空間を抑えてあります。

  • 初期状態だけでなく、任意の状態を入力できるようにした
  • 未知のカードを指定できるようにした
  • 未知のカードがある場合には以下の手順で思考するようにした
    • 未知カードをランダムに設定
    • 設定した状態から探索を行い、初手に対するスコア(組札の枚数)を計算する
    • 未知カードの設定と探索を複数回繰り返す
    • 各初手に対するスコアの平均を計算し、平均スコアが最も高い手を選ぶ

探索について

探索効率を良くするために Kondike-Solver ではいくつかの工夫をしています。

  • 山札(左上のカード)を1回以上めくる手と山札を移動する手をセットにしている
  • 場札(中央の7列のカード)を場札に移動するのは、その次に場札をめくれるときか場札から組札に移動できる時に限定している
  • 場札から組札に移動した場合には、その直後に同じカードを場札に戻す手を探索しない

自動化スクリプト

自動化スクリプトは以下の機能をもっています。
Pythonで実装しました。

  • 画像のパターンマッチングを行ってカードの状態を調べる
  • カードの状態を思考エンジンに入力し、次の手を得る
  • マウス操作を行い次の手をソリティアアプリケーションに入力
  • ゲームが終了したら一定時間待って次のゲームを開始する

結果

97ゲームで1856点獲得することができました。
ゲーム数と得点が中途半端なのはソリティアが強制終了してしまったためです。
累積スコアの推移は以下のようになりました。

累積スコア推移

自動プレイ動画を公開しました。
2時間半もあり長いですが興味ある方はご覧ください。
https://www.youtube.com/watch?v=yw9oBs4mbd8&t=23s

感想

思考アルゴリズムは単純なものでしたが、思ったよりもよい結果を出すことができました。
累積ベガスルールで安定してスコアを稼ぐことができるのかずっと疑問に思っていたのですが、今回の結果からするとうまくやれば可能なようです(人間にとって相当困難だとは思いますが)。
今回のプログラムの手を研究して、今後もソリティアを楽しみたいです。