Okay - after some discussion with CfB and checking out another such simulation I think I can get mine a lot closer to what is "really" going on underneath the hood (of course it is "only a simulation" so it can only be of so much benefit).
So this version is 100 years worth of blocks *without log(balance)* but instead with a "random divisor" of your balance to take the place of "time to forge" and now the figures look like this:
blocks = 52560000
a: 10
b: 10
c: 10
d: 10
e: 10
f: 50
wins( a ) = 4453471
wins( b ) = 4447734
wins( c ) = 4448973
wins( d ) = 4443112
wins( e ) = 4437624
wins( f ) = 30329086
best_streak( a ) = 7
best_streak( b ) = 6
best_streak( c ) = 7
best_streak( d ) = 7
best_streak( e ) = 8
best_streak( f ) = 31
best_combined_streak = 22
and when run with the 90/10 we now get the following:
blocks = 52560000
a: 10
b: 90
wins( a ) = 5361825
wins( b ) = 47198175
best_streak( a ) = 7
best_streak( b ) = 136
Whether this is a good enough approximation to statistically what is going on I am not sure but at least the simulator is no longer using floating point nor "log" (and is giving less skewed results).
#include <ctime>
#include <cmath>
#include <cstdlib>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#define NUM_DAYS 1
#define NUM_YEARS 100
//#define PREVENT_IMMEDIATE_REPEAT
//#define SHOW_WINNERS
//#define SHOW_WINNERS_WEIGHT
using namespace std;
#ifndef NUM_YEARS
const size_t c_num_blocks = 1440 * NUM_DAYS;
#else
const size_t c_num_blocks = 1440 * 365 * NUM_YEARS;
#endif
int main( )
{
#ifdef SHOW_WINNERS
string winners;
#endif
vector< int > wins;
vector< int > streaks;
vector< int > balances;
vector< int > best_streak;
vector< int > combined;
vector< long > weights;
int combined_streak = 0;
int best_combined_streak = 0;
balances.push_back( 10 );
balances.push_back( 10 );
balances.push_back( 10 );
balances.push_back( 10 );
balances.push_back( 10 );
balances.push_back( 50 );
srand( ( unsigned int )time( 0 ) );
for( size_t i = 0; i < balances.size( ); i++ )
{
wins.push_back( 0 );
weights.push_back( 0 );
streaks.push_back( 0 );
combined.push_back( 0 );
best_streak.push_back( 0 );
}
size_t last_winner = 0;
for( size_t blocks = 0; blocks < c_num_blocks; blocks++ )
{
long total_weight = 0;
for( size_t i = 0; i < weights.size( ); i++ )
{
int divisor = rand( ) % 10;
if( divisor == 0 )
++divisor;
weights[ i ] = ( rand( ) % 10000 ) * ( balances[ i ] / divisor );
total_weight += weights[ i ];
}
size_t winner = 0;
size_t runner_up = 0;
long best_target = 0;
#ifdef PREVENT_IMMEDIATE_REPEAT
long second_best_target = 0;
#endif
for( size_t i = 0; i < balances.size( ); i++ )
{
long adjusted_weight = weights[ i ] * 1000 / total_weight;
if( adjusted_weight > best_target )
{
winner = i;
best_target = adjusted_weight;
}
#ifdef PREVENT_IMMEDIATE_REPEAT
else if( adjusted_weight > second_best_target )
{
runner_up = i;
second_best_target = adjusted_weight;
}
#endif
}
#ifdef PREVENT_IMMEDIATE_REPEAT
if( winner == last_winner )
winner = runner_up;
#endif
#ifdef SHOW_WINNERS
winners += ( char )( 'a' + winner );
# ifdef SHOW_WINNERS_WEIGHT
ostringstream osstr;
osstr << best_target;
winners += "(" + osstr.str( ) + ")";
# endif
#endif
++wins[ winner ];
if( winner != balances.size( ) - 1 )
{
++combined_streak;
if( combined_streak > best_combined_streak )
best_combined_streak = combined_streak;
}
else
combined_streak = 0;
if( winner == last_winner )
{
++streaks[ winner ];
if( streaks[ winner ] > best_streak[ winner ] )
best_streak[ winner ] = streaks[ winner ];
}
else
streaks[ winner ] = 0;
last_winner = winner;
}
cout << "blocks = " << c_num_blocks << endl;
for( size_t i = 0; i < balances.size( ); i++ )
cout << ( char )( 'a' + i ) << ": " << balances[ i ] << endl;
#ifdef SHOW_WINNERS
cout << winners << endl;
#endif
for( size_t i = 0; i < wins.size( ); i++ )
cout << "wins( " << ( char )( 'a' + i ) << " ) = " << wins[ i ] << endl;
for( size_t i = 0; i < best_streak.size( ); i++ )
cout << "best_streak( " << ( char )( 'a' + i ) << " ) = " << ( best_streak[ i ] + 1 ) << endl;
cout << "best_combined_streak = " << best_combined_streak << endl;
}