Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.util.Random;
- public class Randomizer
- {
- public static final int RAND_DORY = 0, // memoryless randomizer
- RAND_OLAF = 1, // dementia randomizer, reduces chances of floods and droughts
- RAND_RECURSIVE = 2, // recursive update of probabilities
- RAND_BAG14 = 3, // 14-bag randomizer AKA double-bag randomizer
- RAND_BAG = 4, // 7-bag randomizer
- RAND_LENGTH = 5;
- public int numpieces; // how many pieces exist, should be 7 for Tetris pieces
- public Random r; // random number generator
- public int type; // randomizer-type ,e.g. memoryless, bag randomizer
- int[] bag; // pieces that will be handed out in near future
- int left; // how many pieces are currently left in the bag
- int[] history; // pieces you got in recent past; history[0] is most recent piece
- int[] drought; // how long you didn't get a certain piece kind
- double[] chance; // weights resp. probabilities for recursively updated randomizer
- public Randomizer()
- {
- type = RAND_BAG;
- reset();
- }
- public Randomizer( long seed )
- {
- type = RAND_BAG;
- reset( seed );
- }
- public void reset()
- {
- r = new Random();
- initme();
- }
- public void reset( long seed )
- {
- r = new Random( seed );
- initme();
- }
- public void initme()
- {
- numpieces = 7;
- // needed for 7-bag and 14-bag randomizer
- bag = new int[14];
- for ( int j = 0; j < bag.length; j++ )
- bag[j] = -1;
- left = 0;
- // needed for dementia/olaf randomizer
- history = new int[4];
- for ( int j = 0; j < history.length; j++ )
- history[j] = r.nextInt( numpieces );
- drought = new int[numpieces];
- for ( int i = 0; i < numpieces; i++ )
- drought[i] = history.length;
- for ( int j = history.length - 1; j >= 0; j-- )
- drought[history[j]] = j;
- // needed for recursively updated randomizer
- chance = new double[numpieces];
- for ( int i = 0; i < numpieces; i++ )
- chance[i] = 1f / numpieces;
- }
- // hands out the next piece, returns a number between 0 and numpieces-1
- public int next()
- {
- int piece = -1;
- if ( type == RAND_DORY )
- piece = r.nextInt( numpieces );
- else if ( type == RAND_OLAF )
- piece = nextolaf();
- else if ( type == RAND_RECURSIVE )
- piece = nextrecursive();
- else if ( type == RAND_BAG )
- piece = nextbag();
- else if ( type == RAND_BAG14 )
- piece = nextbag14();
- else
- System.out.println( "unknown Randomizer" );
- return piece;
- }
- // pretty close to memoyless randomizer, uses weights to reduce chances of droughts and floods
- public int nextolaf()
- {
- // uses global arrays history[] and drought[]
- // history tells which piece kinds you got most recently, history[0] is the most recent piece
- // drought tells you when you got each piece kind for the last time,
- // drought[0] is how long you have to wait for the piece shape with the ID 0
- // flood reduction constants
- final int base = 160; // the weight for each piece kind before floods and droughts are considered
- final int[] reduction = { 70, 30, 14, 6 }; // subtracted from base for the 4 most recent pieces
- // drought reduction constants
- final int threshold = 7; // increase probability of a shape if drought is at least this long
- final float factor = 1.4f;
- final float potence = 1.5f;
- int[] weight = new int[numpieces];
- for ( int i = 0; i < numpieces; i++ )
- weight[i] = base;
- // flood reduction
- for ( int j = 0; j < reduction.length; j++ )
- weight[history[j]] -= reduction[j];
- // drought reduction
- for ( int i = 0; i < numpieces; i++ )
- if ( drought[i] > threshold )
- weight[i] += (int) ( factor * Math.pow( drought[i] - threshold, potence ) );
- // dealing a piece shape
- int total = 0;
- for ( int i = 0; i < numpieces; i++ )
- total += weight[i];
- int rand = r.nextInt( total );
- int piece; // piece shape IDs are numerated from 0 to numpieces-1
- for ( piece = 0; piece < numpieces; piece++ )
- if ( rand < weight[piece] )
- break; // choose the current shape as next piece
- else
- rand -= weight[piece];
- // update history and drought
- for ( int j = history.length - 1; j > 0; j-- )
- history[j] = history[j - 1];
- history[0] = piece;
- for ( int i = 0; i < numpieces; i++ )
- drought[i] += 1;
- drought[piece] = 0;
- return piece;
- }
- // recursively updated randomizer, sum of chances are 1
- public int nextrecursive()
- {
- final double multiplier = 0.5f; // must be between 0 and 1, memoryless = 1
- // dealing a piece shape
- double rand = r.nextDouble();
- int piece; // piece shape IDs are numerated from 0 to numpieces-1
- for ( piece = 0; piece < numpieces; piece++ )
- if ( rand < chance[piece] )
- break; // choose the current shape as next piece
- else
- rand -= chance[piece];
- // recursively update piece chances
- double increasement = chance[piece] * ( 1 - multiplier ) / ( numpieces - 1 );
- for ( int i = 0; i < numpieces; i++ )
- if ( i == piece )
- chance[i] *= multiplier;
- else
- chance[i] += increasement;
- return piece;
- }
- public void insertbag()
- {
- for ( int i = 0; i < numpieces; i++ )
- {
- bag[left] = i;
- left += 1;
- }
- }
- public int takefrombag()
- {
- int rand = r.nextInt( left );
- int piece = bag[rand];
- for ( int j = rand; j < left - 1; j++ )
- {
- bag[j] = bag[j + 1];
- }
- left -= 1;
- bag[left] = -1;
- return piece;
- }
- public int nextbag14()
- {
- if ( left == 0 )
- {
- insertbag();
- insertbag(); // fill in 14 pieces
- }
- return takefrombag();
- }
- public int nextbag()
- {
- if ( left == 0 )
- insertbag(); // fill in 7 pieces
- return takefrombag();
- }
- // just to make sure that all piece kinds are handed out equally
- public static void amountpershape()
- {
- Randomizer randomizer = new Randomizer();
- int tries = 1000000;
- int numpieces = randomizer.numpieces;
- for ( int type = 0; type < RAND_LENGTH; type++ )
- {
- int[] sum = new int[numpieces];
- randomizer.type = type;
- randomizer.reset();
- int piece;
- for ( int j = 0; j < tries; j++ )
- {
- piece = randomizer.next();
- sum[piece] += 1;
- // if ( type == RAND_RECURSIVE && j <= 100 )
- // {
- // String str = "";
- // for ( int i = 0; i < numpieces; i++ )
- // str += String.format( "%5.2f", 100 * randomizer.chance[i] ) + " ";
- // System.out.println( str );
- // }
- }
- String str = "Randomizer Nr. " + type + ":";
- for ( int i = 0; i < numpieces; i++ )
- str += " " + sum[i];
- System.out.println( str );
- }
- }
- // The following function takes a look at the following scenario:
- // A certain piece shape is handed out. How long do you have to wait
- // until the next piece of that same shape shows up?
- // More explicitely the function calculates the variance and the
- // standard derivation of that probability distribution.
- // In average, a piece shape is handed out every 7 pieces. But what's
- // the deviations from this mean?
- // The output looks as follows (numbers can vary a little):
- //
- // Memoryless: derivation = 6,48 , variance = 41,994 , flood = 11,065 , drought = 30,930
- // Dementia weights: derivation = 5,43 , variance = 29,438 , flood = 8,990 , drought = 20,448
- // Recursive chances: derivation = 4,62 , variance = 21,335 , flood = 7,958 , drought = 13,376
- // Double bag: derivation = 4,36 , variance = 19,004 , flood = 7,647 , drought = 11,357
- // 7-piece Bag: derivation = 2,83 , variance = 8,001 , flood = 4,000 , drought = 4,000
- //
- // dist Memoryl Dementi Recursi Double 7-piece
- // 1 14,28% 8,23% 8,38% 8,17% 2,04%
- // 2 12,25% 11,39% 8,90% 8,49% 4,09%
- // 3 10,48% 11,31% 9,12% 8,63% 6,12%
- // 4 9,00% 10,30% 9,12% 8,67% 8,17%
- // 5 7,71% 9,14% 8,84% 8,52% 10,20%
- // 6 6,62% 7,72% 8,37% 8,28% 12,24%
- // 7 5,66% 6,52% 7,71% 7,91% 14,28%
- // 8 4,86% 5,51% 6,98% 7,40% 12,24%
- // 9 4,17% 4,69% 6,16% 6,78% 10,22%
- // 10 3,58% 4,00% 5,32% 6,08% 8,16%
- // 11 3,06% 3,42% 4,51% 5,23% 6,12%
- // 12 2,61% 2,95% 3,75% 4,31% 4,08%
- // 13 2,24% 2,50% 3,05% 3,30% 2,05%
- // 14 1,93% 2,14% 2,44% 2,19% 0,00%
- // 15 1,65% 1,80% 1,92% 1,73% 0,00%
- // 16 1,42% 1,53% 1,48% 1,33% 0,00%
- // 17 1,22% 1,28% 1,12% 1,00% 0,00%
- // 18 1,04% 1,07% 0,84% 0,72% 0,00%
- // 19 0,89% 0,89% 0,61% 0,51% 0,00%
- // 20 0,76% 0,73% 0,44% 0,34% 0,00%
- // 21 0,66% 0,60% 0,31% 0,21% 0,00%
- // 22 0,56% 0,49% 0,21% 0,12% 0,00%
- // 23 0,48% 0,39% 0,15% 0,06% 0,00%
- // 24 0,41% 0,31% 0,10% 0,02% 0,00%
- // 25 0,35% 0,25% 0,06% 0,01% 0,00%
- // 26 0,31% 0,20% 0,04% 0,00% 0,00%
- // 27 0,26% 0,15% 0,03% 0,00% 0,00%
- // 28 0,22% 0,12% 0,02% 0,00% 0,00%
- // 29 0,19% 0,09% 0,01% 0,00% 0,00%
- // 30+ 1,14% 0,27% 0,02% 0,00% 0,00%
- public static void variance()
- {
- Randomizer randomizer = new Randomizer();
- String str = "Unknown";
- String str2 = "dist";
- float[][] percentages = new float[30][RAND_LENGTH];
- int tries = 1000000;
- for ( int type = 0; type < RAND_LENGTH; type++ )
- {
- int[] queue = new int[100];
- int[] distances = new int[30];
- if ( type == RAND_DORY )
- str = "Memoryless";
- else if ( type == RAND_OLAF )
- str = "Dementia weights";
- else if ( type == RAND_RECURSIVE )
- str = "Recursive chances";
- else if ( type == RAND_BAG14 )
- str = "Double bag";
- else if ( type == RAND_BAG )
- str = "7-piece Bag";
- str2 += " " + String.format( "%7s", str ).substring( 0, 7 );
- str = String.format( "%21s", str );
- randomizer.type = type;
- randomizer.reset();
- // initialize queue
- for ( int i = queue.length - 1; i >= 0; i-- )
- queue[i] = randomizer.next();
- // now log a very long sequence and sum up the local variances
- long sum = 0, sum2 = 0, sum3 = 0;
- for ( int j = 0; j < tries; j++ )
- {
- // deal out new piece, update queue
- for ( int i = queue.length - 2; i >= 0; i-- )
- {
- queue[i + 1] = queue[i];
- }
- queue[0] = randomizer.next();
- // did the new piece shape appear recently?
- int dist;
- for ( dist = 1; dist < queue.length; dist++ )
- {
- if ( queue[dist] == queue[0] )
- break;
- }
- sum += ( dist - 7 ) * ( dist - 7 );
- if ( dist < 7 )
- sum2 += ( dist - 7 ) * ( dist - 7 );
- if ( dist > 7 )
- sum3 += ( dist - 7 ) * ( dist - 7 );
- distances[Math.min( dist - 1, distances.length - 1 )] += 1;
- }
- float variance = sum * 1f / tries;
- float flood = sum2 * 1f / tries;
- float drought = sum3 * 1f / tries;
- System.out.println( str + ": derivation = " + String.format( "%4.2f", Math.sqrt( variance ) )
- + " , variance = " + String.format( "%6.3f", variance ) + " , flood = "
- + String.format( "%6.3f", flood ) + " , drought = " + String.format( "%6.3f", drought ) );
- for ( int i = 0; i < percentages.length; i++ )
- {
- percentages[i][type] = distances[i] * 100f / tries;
- }
- }
- // log distance probabilities
- System.out.println();
- System.out.println( str2 );
- for ( int i = 0; i < percentages.length; i++ )
- {
- str = String.format( "%4s", i + 1 );
- if ( i == percentages.length - 1 )
- str = String.format( "%3s", i + 1 ) + "+";
- for ( int j = 0; j < RAND_LENGTH; j++ )
- {
- str += " " + String.format( "%5.2f", percentages[i][j] ) + "%";
- }
- System.out.println( str );
- }
- }
- public static void main( String[] args )
- {
- variance();
- // amountpershape();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement