public double[] updateByEnemyMove(Move m) { double[] ret = new double[] { -1, 0 }; //処理の都合上idx1に0を入れておく ulong target = Mask(m.pos); ulong toBit = Mask(m.toPos()); mEnemyGhostBit &= ~target; mEnemyGhostBit |= toBit; if ((mMyEvilGhostBit & toBit) != 0) { //Evilゴーストが取られた mMyEvilGhostBit &= ~toBit; if (mMyEvilGhostBit == 0) { ret[0] = mMyPlayerId; ret[1] = 1.0; return(ret); } } else if ((mMyGoodGhostBit & toBit) != 0) { mMyGoodGhostBit &= ~toBit; if (mMyGoodGhostBit == 0) { ret[0] = 1 - mMyPlayerId; ret[1] = 1.0; return(ret); } } //この時点で自分のゴーストがのゴールマスになにかいるなら、決着がついた if ((mMyGoodGhostBit & cGoal[mMyPlayerId]) != 0) { ret[0] = mMyPlayerId; ret[1] = 1.0; return(ret); } mNextPlayerId = 1 - mNextPlayerId; mTurn++; if (mTurn <= IField.cTotalTurn) { //まだ決着がついてない return(ret); } //全ターン終了、判定勝負 int myGhostScore = Bit.bitCount(mMyGoodGhostBit) - Bit.bitCount(mMyEvilGhostBit); int enemyGhostScore = mEnemyGoodNum - mEnemyEvilNum; if (myGhostScore > enemyGhostScore) { ret[0] = ret[0] * ret[1] + (1.0 - ret[1]) * mMyPlayerId; ret[1] = 1.0; return(ret); } if (myGhostScore < enemyGhostScore) { ret[0] = ret[0] * ret[1] + (1.0 - ret[1]) * (1 - mMyPlayerId); ret[1] = 1.0; return(ret); } //距離勝負、こればかりはコストが掛かる...? int myManScore = myGoodManhattanScore(); double enemyManScore = enemyManhattanScore(); //enemyManScoreとの単純な比較ではないはず...だが、よくわからないのでとりあえずこれで if (myManScore < enemyManScore) { ret[0] = ret[0] * ret[1] + (1.0 - ret[1]) * mMyPlayerId; ret[1] = 1.0; return(ret); } if (myManScore > enemyManScore) { ret[0] = ret[0] * ret[1] + (1.0 - ret[1]) * (1 - mMyPlayerId); ret[1] = 1.0; return(ret); } ret[0] = ret[0] * ret[1] + (1.0 - ret[1]) * (0.5); ret[1] = 1.0; return(ret); }
//idx0に勝者を意味する0~1の値を //idx1にその確率0~1.0を入れる //更新結果は決着がつかなかった場合を入れる(決着がつかないときの遷移先はたかだか1パターンのはず) //idx1が1.0のときは決着がつかない未来がないので更新内容は不定 public double[] updateByMyMove(Move m) { double[] ret = new double[] { -1, 0 }; //処理の都合上idx1に0を入れておく ulong target = Mask(m.pos); ulong toBit = Mask(m.toPos()); if ((mMyEvilGhostBit & target) != 0) { //操作対象はEvilゴーストだった mMyEvilGhostBit &= ~target; mMyEvilGhostBit |= toBit; } else { mMyGoodGhostBit &= ~target; mMyGoodGhostBit |= toBit; } if ((mEnemyGhostBit & toBit) != 0) { //正体不明だけど何か取った if (mEnemyEvilNum == 1 && mEnemyGoodNum == 1) { //決着は絶対につく。結果は半々。 ret[0] = 0.5; ret[1] = 1.0; return(ret); } else if (mEnemyEvilNum == 1) { //それが最後のEvilなら負ける可能性がある ret[0] = 1 - mMyPlayerId; ret[1] = mEnemyEvilNum / (double)(mEnemyEvilNum + mEnemyGoodNum); //更新内容は決着がつかなかった未来なので、今とったのはGoodだったということにする mEnemyGoodNum--; } else if (mEnemyGoodNum == 1) { //それが最後のGoodなら勝つ可能性がある ret[0] = mMyPlayerId; ret[1] = mEnemyGoodNum / (double)(mEnemyEvilNum + mEnemyGoodNum); //更新内容は決着がつかなかった未来なので、今とったのはEvilだったということにする mEnemyEvilNum--; } mEnemyGhostBit &= ~toBit; } //この時点で相手のゴールマスになにかいるなら、決着がついた可能性がある if ((mEnemyGhostBit & cGoal[1 - mMyPlayerId]) != 0) { //Evilが脱出マスに入る作戦が考えにくいなら確定負けにしてもいい気がするが... //新しい決着がつく確率は、(すでに決着がついている確率) + (1-すでに決着がついている確率) * 新たに決着がついた確率 //その時の勝敗期待値は... double goodProb = mEnemyGoodNum / (double)(mEnemyEvilNum + mEnemyGoodNum); double v = ret[0] * ret[1] + ((1.0 - ret[1]) * goodProb) * (1 - mMyPlayerId); double prob = ret[1] + (1.0 - ret[1]) * goodProb; ret[0] = v; ret[1] = prob; //決着がつかなかった未来として、今ゴールマスにいるGhostはEvilに確定することになるが //それを保持する方法がない...のでその処理は一旦省略 } mNextPlayerId = 1 - mNextPlayerId; mTurn++; if (mTurn <= IField.cTotalTurn) { //まだ決着がついてない return(ret); } //前ターン終了、判定勝負 int myGhostScore = Bit.bitCount(mMyGoodGhostBit) - Bit.bitCount(mMyEvilGhostBit); int enemyGhostScore = mEnemyGoodNum - mEnemyEvilNum; if (myGhostScore > enemyGhostScore) { ret[0] = ret[0] * ret[1] + (1.0 - ret[1]) * mMyPlayerId; ret[1] = 1.0; return(ret); } if (myGhostScore < enemyGhostScore) { ret[0] = ret[0] * ret[1] + (1.0 - ret[1]) * (1 - mMyPlayerId); ret[1] = 1.0; return(ret); } //距離勝負、こればかりはコストが掛かる...? int myManScore = myGoodManhattanScore(); double enemyManScore = enemyManhattanScore(); //enemyManScoreとの単純な比較ではないはず...だが、よくわからないのでとりあえずこれで if (myManScore < enemyManScore) { ret[0] = ret[0] * ret[1] + (1.0 - ret[1]) * mMyPlayerId; ret[1] = 1.0; return(ret); } if (myManScore > enemyManScore) { ret[0] = ret[0] * ret[1] + (1.0 - ret[1]) * (1 - mMyPlayerId); ret[1] = 1.0; return(ret); } ret[0] = ret[0] * ret[1] + (1.0 - ret[1]) * (0.5); ret[1] = 1.0; return(ret); }