Advertisement
Guest User

Tetris Randomizer

a guest
May 14th, 2015
405
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.31 KB | None | 0 0
  1. import java.util.Random;
  2.  
  3. public class Randomizer
  4. {
  5.    
  6.     public static final int RAND_DORY = 0, // memoryless randomizer
  7.                             RAND_OLAF = 1, // dementia randomizer, reduces chances of floods and droughts
  8.                             RAND_REFILL7 = 2, // 14-bag randomizer that refills 7 pieces when 7 pieces are left in the bag
  9.                             RAND_BAG14 = 3, // 14-bag randomizer AKA double-bag randomizer
  10.                             RAND_REFILL1 = 4, // 8-bag randomizer that refills 7 pieces when 1 piece is left in the bag
  11.                             RAND_BAG = 5, // 7-bag randomizer
  12.                             RAND_BAG8 = 6, // all 7 pieces plus one random piece
  13.                             RAND_BAG6 = 7, // all 7 pieces minus one random piece
  14.                             RAND_GB = 8,
  15.                             RAND_NES = 9,
  16.                             RAND_TGM = 10,
  17.                             RAND_TGM2 = 11,
  18.                             RAND_LENGTH = 12;
  19.    
  20.     public int numpieces; // how many pieces exist, should be 7 for Tetris pieces
  21.    
  22.     public Random r; // random number generator
  23.     public int type; // randomizer-type ,e.g. memoryless, bag randomizer
  24.     int[] bag; // pieces that will be handed out in  near future
  25.     int left; // how many pieces are currently left in the bag
  26.     int[] history; // pieces you got in recent past; history[0] is most recent piece
  27.     int[] drought; // how long you didn't get a certain piece kind
  28.     int[] drought2; // when did you get the second last of a certain piece kind
  29.     int[] drought3; // when did you get the third last of a certain piece kind
  30.    
  31.     public Randomizer()
  32.     {
  33.         type = RAND_BAG;
  34.         reset();
  35.     }  
  36.    
  37.     public Randomizer(long seed)
  38.     {
  39.         type = RAND_BAG;
  40.         reset(seed);
  41.     }
  42.    
  43.     public void reset()
  44.     {
  45.         r = new Random();
  46.         initme();
  47.     }
  48.    
  49.     public void reset(long seed)
  50.     {
  51.         r = new Random(seed);
  52.         initme();
  53.     }
  54.    
  55.     public void initme()
  56.     {
  57.         numpieces = 7;
  58.         bag = new int[100];
  59.         for ( int j = 0; j < bag.length; j++ )
  60.         {
  61.             bag[j] = -1;
  62.         }      
  63.         left = 0;
  64.         history = new int[7];
  65.         for ( int j = 0; j < history.length; j++ )
  66.         {
  67.             history[j] = r.nextInt(numpieces);
  68.         }
  69.         drought = new int[numpieces];
  70.         for ( int i = 0; i < numpieces; i++ )
  71.         {
  72.             drought[i] = history.length;
  73.         }
  74.         for ( int j = history.length - 1 ; j >= 0; j-- )
  75.         {
  76.             drought[history[j]] = j;
  77.         }
  78.         drought2 = new int[numpieces];
  79.         drought3 = new int[numpieces];
  80.         for ( int i = 0; i < numpieces; i++ )
  81.         {
  82.             drought2[i] = drought[i] + numpieces;
  83.             drought3[i] = drought[i] + 2*numpieces;
  84.         }
  85.     }
  86.  
  87.     // hands out the next piece, returns a number between 0 and numpieces-1
  88.     public int next()
  89.     {
  90.         int piece = -1;
  91.         if ( type == RAND_DORY )
  92.             piece = r.nextInt(numpieces);
  93.         else if ( type == RAND_OLAF )
  94.             piece = nextolaf();
  95.         else if ( type == RAND_BAG )
  96.             piece = nextbag();
  97.         else if ( type == RAND_BAG8 )
  98.             piece = nextbag8();
  99.         else if ( type == RAND_BAG6 )
  100.             piece = nextbag6();    
  101.         else if ( type == RAND_BAG14 )
  102.             piece = nextbag14();
  103.         else if ( type == RAND_REFILL7 )
  104.             piece = nextrefill7();
  105.         else if ( type == RAND_REFILL1 )
  106.             piece = nextrefill1();
  107.         else if ( type == RAND_GB )
  108.             piece = nextgb();
  109.         else if ( type == RAND_NES )
  110.             piece = nextnes();
  111.         else if ( type == RAND_TGM )
  112.             piece = nexttgm();
  113.         else if ( type == RAND_TGM2 )
  114.             piece = nexttgm2();
  115.         else System.out.println("Randomizer.next: unknown Tetromino-Randomizer");
  116.         // update history, drought
  117.         for ( int j = history.length - 1; j > 0; j-- )
  118.         {
  119.             history[j] = history[j-1];
  120.         }
  121.         history[0] = piece;
  122.         for ( int i = 0; i < numpieces; i++ )
  123.         {
  124.             drought[i] += 1;
  125.             drought2[i] += 1;
  126.             drought3[i] += 1;
  127.         }
  128.         drought3[piece] = drought2[piece];
  129.         drought2[piece] = drought[piece];
  130.         drought[piece] = 0;    
  131.         return piece;
  132.     }
  133.    
  134.     // pretty close to memoyless randomizer, uses weights to reduce chances of droughts and floods
  135.     public int nextolaf()
  136.     {
  137.         final int base = 160;
  138.         final int[] reduction = {70,30,14,6}; // ensure that the sum is smaller than base
  139.         final int[] threshold = {11,14,18,22, 26, 30, 35, 40, 45, 50}; // if a drought lasts longer than ...
  140.         final int[] increase  = {10,20,45,80,115,160,225,320,450,640}; // then increase chances by ...     
  141.         final int threshadd2 = 10; // add this number to threshold for 2-pieces drought
  142.         final int threshadd3 = 20; // add this number to threshold for 3-pieces drought
  143.        
  144.         int total = numpieces * base;
  145.         for ( int j = 0; j < reduction.length; j++ )
  146.             total -= reduction[j]; // total = 1000
  147.         int[] addme = new int[numpieces];
  148.         for ( int i = 0; i < numpieces; i++ )
  149.         {
  150.             for ( int j = threshold.length - 1; j >= 0 ; j-- )
  151.             {
  152.                 if ( drought[i] >= threshold[j] )
  153.                 {
  154.                     addme[i] += increase[j];
  155.                     break;
  156.                 }
  157.             }
  158.             for ( int j = threshold.length - 1; j >= 0 ; j-- )
  159.             {
  160.                 if ( drought2[i] >= threshold[j] + threshadd2 )
  161.                 {
  162.                     addme[i] += increase[j];
  163.                     break;
  164.                 }
  165.             }
  166.             for ( int j = threshold.length - 1; j >= 0 ; j-- )
  167.             {
  168.                 if ( drought3[i] >= threshold[j] + threshadd3 )
  169.                 {
  170.                     addme[i] += increase[j];
  171.                     break;
  172.                 }
  173.             }
  174.             total += addme[i];
  175.         }
  176.        
  177.         int rand = r.nextInt( total );
  178.         for ( int i = 0; i < numpieces; i++ )
  179.         {
  180.             int ival = base + addme[i];
  181.             for ( int j = 0; j < reduction.length; j++ )
  182.             {
  183.                 if ( i == history[j] )
  184.                     ival -= reduction[j];
  185.             }
  186.             if ( rand < ival )
  187.                 return i; // choose i as next piece, chance = ival/total
  188.             else
  189.                 rand -= ival;
  190.         }
  191.         return -1; // this code is never executed
  192.     }
  193.  
  194.     public void insertbag()
  195.     {
  196.         for ( int i = 0; i < numpieces ; i++ )
  197.         {
  198.             bag[left] = i;
  199.             left += 1;
  200.         }
  201.     }
  202.    
  203.     public void insertbag8()
  204.     {
  205.         for ( int i = 0; i < numpieces ; i++ )
  206.         {
  207.             bag[left] = i;
  208.             left += 1;
  209.         }
  210.         bag[left] = r.nextInt(numpieces);
  211.         left += 1;
  212.     }
  213.    
  214.     public void insertbag6()
  215.     {
  216.         int ignore = r.nextInt(numpieces);
  217.         for ( int i = 0; i < numpieces ; i++ )
  218.         {
  219.             if ( i == ignore )
  220.                 continue;
  221.             bag[left] = i;
  222.             left += 1;
  223.         }
  224.     }
  225.    
  226.     public int takefrombag()
  227.     {
  228.         int rand = r.nextInt( left );
  229.         int piece = bag[rand];
  230.         for ( int j = rand; j < left-1; j++ )
  231.         {
  232.             bag[j] = bag[j+1];
  233.         }
  234.         left -= 1;
  235.         bag[left] = -1;
  236.         return piece;
  237.     }
  238.    
  239.     public int nextbag14()
  240.     {
  241.         if ( left == 0 )
  242.         {
  243.             insertbag(); insertbag(); // fill in 14 pieces
  244.         }
  245.         return takefrombag();
  246.     }
  247.    
  248.     public int nextbag()
  249.     {
  250.         if ( left == 0 )
  251.             insertbag(); // fill in 7 pieces
  252.         return takefrombag();
  253.     }
  254.    
  255.     public int nextbag8()
  256.     {
  257.         if ( left == 0 )
  258.             insertbag8(); // fill in 8 pieces
  259.         return takefrombag();
  260.     }
  261.    
  262.     public int nextbag6()
  263.     {
  264.         if ( left == 0 )
  265.             insertbag6(); // fill in 6 pieces
  266.         return takefrombag();
  267.     }
  268.  
  269.     public int nextrefill()
  270.     {
  271.         if ( left == 0 )
  272.         {
  273.             insertbag(); insertbag(); // fill in 14 pieces
  274.         }
  275.         else if ( left == 7 )
  276.             insertbag(); // fill in 7 pieces
  277.         return takefrombag();
  278.     }
  279.    
  280.     public int nextrefill7()
  281.     {
  282.         if ( left == 0 )
  283.         {
  284.             insertbag(); insertbag(); // fill in 14 pieces
  285.         }
  286.         else if ( left == numpieces )
  287.             insertbag(); // fill in 7 pieces
  288.         return takefrombag();
  289.     }
  290.    
  291.     public int nextrefill1()
  292.     {
  293.         if ( left == 0 )
  294.         {
  295.             insertbag(); // fill in 7 pieces
  296.         }
  297.         else if ( left == 1 )
  298.             insertbag(); // fill in 7 pieces
  299.         return takefrombag();
  300.     }
  301.    
  302.     // this code assumes the following piece IDs: L = 0, J = 1, I = 2, O = 3, Z = 4, S = 5, T = 6
  303.     public int nextgb()
  304.     {
  305.         int numrolls = 3;
  306.         int id = -1;
  307.         for (int i = 0; i < numrolls; i++)
  308.         {
  309.             id = r.nextInt(numpieces);
  310.             if ( (id | history[0] | history[1]) != history[1] )
  311.                 break;
  312.         }
  313.         return id;
  314.     }
  315.    
  316.     public int nextnes()
  317.     {
  318.         int id = r.nextInt(numpieces+1);
  319.         if ( id == history[0] || id == numpieces )
  320.             id = r.nextInt(numpieces);
  321.         return id;
  322.     }
  323.    
  324.     public int nexttgm()
  325.     {
  326.         return history4(4);
  327.     }
  328.    
  329.     public int nexttgm2()
  330.     {
  331.         return history4(6);
  332.     }  
  333.    
  334.     public int history4(int numrolls)
  335.     {
  336.         int id = -1;
  337.         for (int i = 0; i < numrolls; i++)
  338.         {
  339.             id = r.nextInt(numpieces);
  340.             if ( id != history[0] && id != history[1] && id != history[2] && id != history[3] )
  341.                 break;
  342.         }
  343.         return id;
  344.     }
  345.    
  346.     // The following function takes a look at the following scenario:
  347.     // A certain piece shape is handed out. How long do you have to wait
  348.     // until the next piece of that same shape shows up?
  349.     // More explicitely the function calculates the variance and the
  350.     // standard derivation of that probability distribution.
  351.     // In average, a piece shape is handed out every 7 pieces. But what's
  352.     // the deviations from this mean?
  353.     // The output looks as follows (numbers can vary a little):
  354.     //            Memoryless: variance = 41,902 derivation = 6,47
  355.     //      Dementia weights: variance = 28,498 derivation = 5,34
  356.     //  Refill bag if 7 left: variance = 25,023 derivation = 5,00
  357.     //            Double bag: variance = 19,064 derivation = 4,37
  358.     //  Refill bag if 1 left: variance = 12,939 derivation = 3,60
  359.     //           7-piece Bag: variance =  7,994 derivation = 2,83
  360.     //          Bag plus one: variance = 11,776 derivation = 3,43
  361.     //         Bag minus one: variance = 12,799 derivation = 3,58
  362.     //      Original GameBoy: variance = 37,861 derivation = 6,15
  363.     //          Nintendo NES: variance = 32,614 derivation = 5,71
  364.     // Tetris Grand Master 1: variance = 10,156 derivation = 3,19
  365.     // Tetris Grand Master 2: variance =  7,334 derivation = 2,71
  366.     public static void variance()
  367.     {
  368.         Randomizer randomizer = new Randomizer();
  369.         String str = "Unknown";
  370.         int[] queue = new int[100];
  371.         int tries = 1000000;
  372.        
  373.         for ( int type = 0; type < RAND_LENGTH; type++ )
  374.         {
  375.             if ( type == RAND_DORY )
  376.                 str = "Memoryless";
  377.             else if ( type == RAND_OLAF )
  378.                 str = "Dementia weights";
  379.             else if ( type == RAND_REFILL7 )
  380.                 str = "Refill bag if 7 left";          
  381.             else if ( type == RAND_BAG14 )
  382.                 str = "Double bag";
  383.             else if ( type == RAND_REFILL1 )
  384.                 str = "Refill bag if 1 left";
  385.             else if ( type == RAND_BAG )
  386.                 str = "7-piece Bag";
  387.             else if ( type == RAND_BAG8 )
  388.                 str = "Bag plus one";
  389.             else if ( type == RAND_BAG6 )
  390.                 str = "Bag minus one";         
  391.             else if ( type == RAND_GB )
  392.                 str = "Original GameBoy";
  393.             else if ( type == RAND_NES )
  394.                 str = "Nintendo NES";          
  395.             else if ( type == RAND_TGM )
  396.                 str = "Tetris Grand Master 1";
  397.             else if ( type == RAND_TGM2 )
  398.                 str = "Tetris Grand Master 2";
  399.            
  400.             str = String.format("%21s", str);
  401.             randomizer.type = type;
  402.             randomizer.reset();
  403.  
  404.             // initialize queue
  405.             for ( int i = queue.length-1; i >= 0; i-- )
  406.             {
  407.                 queue[i] = randomizer.next();
  408.             }
  409.             // now log a very long sequence and sum up the local variances
  410.             long sum = 0;
  411.             for ( int j = 0; j < tries; j++ )
  412.             {
  413.                 // deal out new piece, update queue
  414.                 for ( int i = queue.length-2; i >= 0; i-- )
  415.                 {
  416.                     queue[i+1] = queue[i];
  417.                 }
  418.                 queue[0] = randomizer.next();
  419.                 // did the new piece shape appear recently?
  420.                 int dist;
  421.                 for ( dist = 1; dist < queue.length; dist++ )
  422.                 {
  423.                     if ( queue[dist] == queue[0] )
  424.                         break;
  425.                 }
  426.                 sum += (dist-7)*(dist-7);
  427.             }
  428.             float variance = sum*1f/tries;
  429.             System.out.println(str + ": variance = " + String.format("%6.3f", variance) + " derivation = " + String.format("%4.2f", Math.sqrt(variance)) );
  430.         }
  431.     }
  432.    
  433.     public static void main(String[] args)
  434.     {
  435.         variance();
  436.     }
  437. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement