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_REFILL7 = 2, // 14-bag randomizer that refills 7 pieces when 7 pieces are left in the bag
- RAND_BAG14 = 3, // 14-bag randomizer AKA double-bag randomizer
- RAND_REFILL1 = 4, // 8-bag randomizer that refills 7 pieces when 1 piece is left in the bag
- RAND_BAG = 5, // 7-bag randomizer
- RAND_BAG8 = 6, // all 7 pieces plus one random piece
- RAND_BAG6 = 7, // all 7 pieces minus one random piece
- RAND_GB = 8,
- RAND_NES = 9,
- RAND_TGM = 10,
- RAND_TGM2 = 11,
- RAND_LENGTH = 12;
- 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
- int[] drought2; // when did you get the second last of a certain piece kind
- int[] drought3; // when did you get the third last of a certain piece kind
- 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;
- bag = new int[100];
- for ( int j = 0; j < bag.length; j++ )
- {
- bag[j] = -1;
- }
- left = 0;
- history = new int[7];
- 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;
- }
- drought2 = new int[numpieces];
- drought3 = new int[numpieces];
- for ( int i = 0; i < numpieces; i++ )
- {
- drought2[i] = drought[i] + numpieces;
- drought3[i] = drought[i] + 2*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_BAG )
- piece = nextbag();
- else if ( type == RAND_BAG8 )
- piece = nextbag8();
- else if ( type == RAND_BAG6 )
- piece = nextbag6();
- else if ( type == RAND_BAG14 )
- piece = nextbag14();
- else if ( type == RAND_REFILL7 )
- piece = nextrefill7();
- else if ( type == RAND_REFILL1 )
- piece = nextrefill1();
- else if ( type == RAND_GB )
- piece = nextgb();
- else if ( type == RAND_NES )
- piece = nextnes();
- else if ( type == RAND_TGM )
- piece = nexttgm();
- else if ( type == RAND_TGM2 )
- piece = nexttgm2();
- else System.out.println("Randomizer.next: unknown Tetromino-Randomizer");
- // update history, 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;
- drought2[i] += 1;
- drought3[i] += 1;
- }
- drought3[piece] = drought2[piece];
- drought2[piece] = drought[piece];
- drought[piece] = 0;
- return piece;
- }
- // pretty close to memoyless randomizer, uses weights to reduce chances of droughts and floods
- public int nextolaf()
- {
- final int base = 160;
- final int[] reduction = {70,30,14,6}; // ensure that the sum is smaller than base
- final int[] threshold = {11,14,18,22, 26, 30, 35, 40, 45, 50}; // if a drought lasts longer than ...
- final int[] increase = {10,20,45,80,115,160,225,320,450,640}; // then increase chances by ...
- final int threshadd2 = 10; // add this number to threshold for 2-pieces drought
- final int threshadd3 = 20; // add this number to threshold for 3-pieces drought
- int total = numpieces * base;
- for ( int j = 0; j < reduction.length; j++ )
- total -= reduction[j]; // total = 1000
- int[] addme = new int[numpieces];
- for ( int i = 0; i < numpieces; i++ )
- {
- for ( int j = threshold.length - 1; j >= 0 ; j-- )
- {
- if ( drought[i] >= threshold[j] )
- {
- addme[i] += increase[j];
- break;
- }
- }
- for ( int j = threshold.length - 1; j >= 0 ; j-- )
- {
- if ( drought2[i] >= threshold[j] + threshadd2 )
- {
- addme[i] += increase[j];
- break;
- }
- }
- for ( int j = threshold.length - 1; j >= 0 ; j-- )
- {
- if ( drought3[i] >= threshold[j] + threshadd3 )
- {
- addme[i] += increase[j];
- break;
- }
- }
- total += addme[i];
- }
- int rand = r.nextInt( total );
- for ( int i = 0; i < numpieces; i++ )
- {
- int ival = base + addme[i];
- for ( int j = 0; j < reduction.length; j++ )
- {
- if ( i == history[j] )
- ival -= reduction[j];
- }
- if ( rand < ival )
- return i; // choose i as next piece, chance = ival/total
- else
- rand -= ival;
- }
- return -1; // this code is never executed
- }
- public void insertbag()
- {
- for ( int i = 0; i < numpieces ; i++ )
- {
- bag[left] = i;
- left += 1;
- }
- }
- public void insertbag8()
- {
- for ( int i = 0; i < numpieces ; i++ )
- {
- bag[left] = i;
- left += 1;
- }
- bag[left] = r.nextInt(numpieces);
- left += 1;
- }
- public void insertbag6()
- {
- int ignore = r.nextInt(numpieces);
- for ( int i = 0; i < numpieces ; i++ )
- {
- if ( i == ignore )
- continue;
- 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();
- }
- public int nextbag8()
- {
- if ( left == 0 )
- insertbag8(); // fill in 8 pieces
- return takefrombag();
- }
- public int nextbag6()
- {
- if ( left == 0 )
- insertbag6(); // fill in 6 pieces
- return takefrombag();
- }
- public int nextrefill()
- {
- if ( left == 0 )
- {
- insertbag(); insertbag(); // fill in 14 pieces
- }
- else if ( left == 7 )
- insertbag(); // fill in 7 pieces
- return takefrombag();
- }
- public int nextrefill7()
- {
- if ( left == 0 )
- {
- insertbag(); insertbag(); // fill in 14 pieces
- }
- else if ( left == numpieces )
- insertbag(); // fill in 7 pieces
- return takefrombag();
- }
- public int nextrefill1()
- {
- if ( left == 0 )
- {
- insertbag(); // fill in 7 pieces
- }
- else if ( left == 1 )
- insertbag(); // fill in 7 pieces
- return takefrombag();
- }
- // this code assumes the following piece IDs: L = 0, J = 1, I = 2, O = 3, Z = 4, S = 5, T = 6
- public int nextgb()
- {
- int numrolls = 3;
- int id = -1;
- for (int i = 0; i < numrolls; i++)
- {
- id = r.nextInt(numpieces);
- if ( (id | history[0] | history[1]) != history[1] )
- break;
- }
- return id;
- }
- public int nextnes()
- {
- int id = r.nextInt(numpieces+1);
- if ( id == history[0] || id == numpieces )
- id = r.nextInt(numpieces);
- return id;
- }
- public int nexttgm()
- {
- return history4(4);
- }
- public int nexttgm2()
- {
- return history4(6);
- }
- public int history4(int numrolls)
- {
- int id = -1;
- for (int i = 0; i < numrolls; i++)
- {
- id = r.nextInt(numpieces);
- if ( id != history[0] && id != history[1] && id != history[2] && id != history[3] )
- break;
- }
- return id;
- }
- // 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: variance = 41,902 derivation = 6,47
- // Dementia weights: variance = 28,498 derivation = 5,34
- // Refill bag if 7 left: variance = 25,023 derivation = 5,00
- // Double bag: variance = 19,064 derivation = 4,37
- // Refill bag if 1 left: variance = 12,939 derivation = 3,60
- // 7-piece Bag: variance = 7,994 derivation = 2,83
- // Bag plus one: variance = 11,776 derivation = 3,43
- // Bag minus one: variance = 12,799 derivation = 3,58
- // Original GameBoy: variance = 37,861 derivation = 6,15
- // Nintendo NES: variance = 32,614 derivation = 5,71
- // Tetris Grand Master 1: variance = 10,156 derivation = 3,19
- // Tetris Grand Master 2: variance = 7,334 derivation = 2,71
- public static void variance()
- {
- Randomizer randomizer = new Randomizer();
- String str = "Unknown";
- int[] queue = new int[100];
- int tries = 1000000;
- for ( int type = 0; type < RAND_LENGTH; type++ )
- {
- if ( type == RAND_DORY )
- str = "Memoryless";
- else if ( type == RAND_OLAF )
- str = "Dementia weights";
- else if ( type == RAND_REFILL7 )
- str = "Refill bag if 7 left";
- else if ( type == RAND_BAG14 )
- str = "Double bag";
- else if ( type == RAND_REFILL1 )
- str = "Refill bag if 1 left";
- else if ( type == RAND_BAG )
- str = "7-piece Bag";
- else if ( type == RAND_BAG8 )
- str = "Bag plus one";
- else if ( type == RAND_BAG6 )
- str = "Bag minus one";
- else if ( type == RAND_GB )
- str = "Original GameBoy";
- else if ( type == RAND_NES )
- str = "Nintendo NES";
- else if ( type == RAND_TGM )
- str = "Tetris Grand Master 1";
- else if ( type == RAND_TGM2 )
- str = "Tetris Grand Master 2";
- 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;
- 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);
- }
- float variance = sum*1f/tries;
- System.out.println(str + ": variance = " + String.format("%6.3f", variance) + " derivation = " + String.format("%4.2f", Math.sqrt(variance)) );
- }
- }
- public static void main(String[] args)
- {
- variance();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement