じゃんけんで階段登るゲーム

ご存知、じゃんけんで階段登るゲームありますよね。 階段を登るときにじゃんけんをし、勝ったらその手に応じた歩数だけ階段を登っていき、先に登り切った方が勝ちになるというあれ。 単純なルールながら、パーとチョキは6歩、グーだけ3歩という露骨な不平等により、絶妙な駆け引きを生んでいます。 グーを「グリコのおまけ」とするバージョンもあり、その場合グーは7歩となって差は減ってしまうのですが、これは改悪と言わざるを得ないでしょう。 ちなみにWikipediaではグリコという名前で載っています(今知った)。
そして、そのWikipediaに、衝撃の一文が。
>相手がグー・チョキ・パーをいかなる割合で出してきても引き分けるには、グー・チョキ・パーを2:2:1の割合で出すと良い。
しかも要出典タグもついておらず、見事に断言されています。えっ、マジで?

最強のパターンを追究するつもりで書き始めたのですが、反証を示すべき命題が見つかったので非常に助かりました・・・。

では検証してみましょう。以下ソースコードです。
二人のプレイヤーが予め決められた割合に従ってランダムで手を選択し、定められた回数だけじゃんけんした後の歩数を表示します。
この場合、プレイヤー1はWikipediaの教えに従い2:2:1、プレイヤー2は1:1:1で手を出します。

#include 
#include 
#include 
#define TRY_MAX 100000	//試行回数

enum EnumHand{
	H_G, H_C, H_P, H_MAX
};

struct StrRate{
	int g; int c; int p;
};

//それぞれの手で勝ったときに進める歩数
const int steps[H_MAX] = {
	3, 6, 6
};

//それぞれの手を出す割合
const StrRate r[2] = {
	{
		2, 2, 1
	},{
		1, 1, 1
	}
};

int GetHand(const StrRate* rate);

int main(){
	int step[2] = {0, 0};
	for(int i = 0; i < TRY_MAX; ++i){
		int hand[2];
		for(int t = 0; t < 2; ++t){
			hand[t] = GetHand(&r[t]);
		}
		for(int t = 0; t < 2; ++t){
			if(abs(hand[t] + 3 - hand[(t + 1) % 2]) % 3 == 2){
				step[t] += steps[hand[t]];
			}
		}
	}
	printf("1:%d歩 2:%d歩\n", step[0], step[1]);
	return 0;
}

int GetHand(const StrRate* rate){
	int h = rand() % (rate->g + rate->c + rate->p);
	if(h < rate->g){
		return H_G;
	}
	else if(h < rate->g + rate->c){
		return H_C;
	}
	else if(h < rate->g + + rate->c + rate->p){
		return H_P;
	}
	return -1;
}

結果。160101歩と160152歩。ほぼ互角になりました。

次はチョキの確率を上げてみましょう。勝った場合に6歩進めるのに負けても相手は3歩しか進めないすぐれものです。
プレイヤー2の手の割合を1:10:1にすると、130443歩と130398歩。やはりほぼ互角。

開き直って最弱のグーしか出さないようにすると、120876歩と119811歩。互角。

Wikipedia先生へ。疑ってごめんなさい。

細かい理論が知りたい方は「じゃんけんグリコ」の数学を見るとよいと思います。