TOM对弈升降段的计算机模拟

为了想知道在现在的TOM升降段制度下,假定一个人水平不变,升降段到底有多难,我写了一个模拟程序来做。
前提:
 ×假定该人水平不变,起始段位为0。
 ×他对同水平棋手的胜率为50%,对高一段胜率为31%,高两段为19%。。。胜率的计算用这个公式来模拟:
double winningChance(int opponentRank, double var)
{
if (opponentRank >= 0)
   return pow(0.5, opponentRank * var +1);
else
   return 1 - pow(0.5, -opponentRank * var + 1);
}

输入var为0.7时能达到高一段约30%的胜率。

×按照TOM的规则,最近20盘中:
  20战18胜2败胜率90%以上升2段
  20战14胜6败胜率70%以上升1段
  20战6胜14败胜率30%以下降1段
  20战2胜18败胜率10%以下降2段
每升降段后清零。

以下是一次模拟运行的结果:

Simulated strength:
Winning chance to opponent of strength -2 : 81%
Winning chance to opponent of strength -1 : 69%
Winning chance to opponent of strength 0 : 50%
Winning chance to opponent of strength 1 : 31%
Winning chance to opponent of strength 2 : 19%
Total simulated games: 10000
Total win: 5007 Loss: 4993
Total rank changes: 242
Average games per rank change: 41.3223
Minimum Rank -1 Maximum Rank 1
Distribution:
At Rank -1 Played 14.08% games.
At Rank 0 Played 69.48% games.
At Rank 1 Played 16.44% games.

这是模拟一个人下了10000盘的结果.从这个结果中可以看出:
* 平均41盘棋有一次升降.
* 最低级别只降了一段,最高时只升了一段。
* 有70%的时间他呆在自己的原有段位里,有30%的时间在高一段或者低一段的组里。

只是一个模拟,没有考虑例外,仅作参考。

#include <math.h>
#include 
<iostream>
#include 
<vector>
#include 
<string>
#include 
<algorithm>
#include 
<numeric>
#include 
<time.h>
#include 
<assert.h>
using namespace std;
typedef vector
<int> intv;
#define min _MIN
#define max _MAX

#define EVALGAMES 20
#define MIN_POSSIBLE_RANK -20

template 
<class T> ostream &operator << (ostream &outconst vector<T> &a)
{
    
out<<"{";
    
for(int i = 0; i < a.size(); i++)
    
{
        
out<<"""<<a[i]<<""";
        
if (i != a.size() - 1)
            
out<<",";
    }

    
out<<"} ";
    
return out;
}


class Sim
{
public:
    intv ranks, games;
    
int totalRankChanges; 
    
int minRank, maxRank;
    intv rankStats;
    
double winningChance(int opponentRank, double var)
    
{
        
if (opponentRank >= 0)
            
return pow(0.5, opponentRank * var +1);
        
else
            
return 1 - pow(0.5-opponentRank * var + 1);
    }

    
void doit(int count, double var)
    
{
        
int i, k;
        
int r = 0;
        
int startFresh = 0;
        totalRankChanges 
= 0;
        minRank 
= maxRank = 0;
        rankStats.clear();
        rankStats.resize(
1000);
        
for(i = 0; i < count; i++)
        
{
            
double favor = winningChance(r, var);
            
bool win = rand() > RAND_MAX * (1 - favor);
            games.push_back(win);
            ranks.push_back(r);
            rankStats[r 
- MIN_POSSIBLE_RANK]++;
            
int countwin = 0;
            
int countall = 0;
            
if (i - startFresh + 1 >= EVALGAMES)
            
{
                
for(k = i; k >= max(startFresh, i - EVALGAMES + 1); k--)
                
{
                    countwin 
+= games[k];
                    countall 
++;
                }

                assert(countall 
== EVALGAMES);
                
int delta = 0;
                
if (countwin >= 18)
                    delta 
= 2;
                
else if (countwin >= 14)
                    delta 
= 1;
                
else if (countwin >= 7)
                    delta 
= 0;
                
else if (countwin >= 3)
                    delta 
= -1;
                
else
                    delta 
= -2;
                r 
+= delta;
                
if (delta) 
                
{
                    startFresh 
= i+1;
                    totalRankChanges 
++;
                    minRank 
= min(minRank, r);
                    maxRank 
= max(maxRank, r);
                    cout 
<< "Rank change " << ((delta > 0? "+" : "-"<< abs(delta);
                    cout 
<< " at game: " << i << " Current Rank: " << r << endl;
                }

            }

        }

        
int totalWin = accumulate(games.begin(), games.end(), 0);
        cout 
<< "==============================================================" << endl;
        cout 
<< "Simulated strength:" << endl;
        
for(i = minRank-1; i <= maxRank+1; i++)
        
{
            cout 
<< "  Winning chance to opponent of strength " << i << " : ";
            cout 
<< int(winningChance(i, var) * 100 + 0.5<< "%" << endl;
        }

        cout 
<< "Total simulated games: " << count << endl;
        cout 
<< "Total win: " << totalWin << " Loss: " << count - totalWin << endl;
        cout 
<< "Total rank changes: " << totalRankChanges << endl;
        cout 
<< "Average games per rank change: " << double(count) / totalRankChanges << endl;
        cout 
<< "Minimum Rank " << minRank << " Maximum Rank " << maxRank << endl;
        cout 
<< "Distribution: " << endl;
        
for(i = 0; i < rankStats.size(); i++)
        
{
            
if (rankStats[i])
                cout 
<< "  At Rank " << i + MIN_POSSIBLE_RANK << " Played " << (rankStats[i] * 100.0/count << "% games." << endl; 
        }

        
//cout << games;
    }

}
;

int main()
{
    srand(time(NULL));
    Sim sim;
    sim.doit(
1000000.7);
    
return 0;
}



posted on 2004-07-23 16:58  阿呆  阅读(1047)  评论(1编辑  收藏  举报

导航