Advertisement
Earthcomputer

Untitled

Mar 27th, 2019
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 14.25 KB | None | 0 0
  1. import javax.imageio.ImageIO;
  2. import java.awt.*;
  3. import java.awt.image.BufferedImage;
  4. import java.io.File;
  5. import java.io.IOException;
  6. import java.io.UncheckedIOException;
  7. import java.lang.reflect.Field;
  8. import java.math.BigInteger;
  9. import java.util.*;
  10. import java.util.List;
  11. import java.util.concurrent.atomic.AtomicLong;
  12.  
  13. public class Main {
  14.  
  15.     private static final double FLOOR_HEIGHT = 0.875 - 1;
  16.     private static double initialHeight;
  17.     private static int launchTntCount;
  18.  
  19.     private static List<Detector> detectors;
  20.  
  21.     public static void main(String[] args) {
  22.         /*
  23.         Scanner scan = new Scanner(System.in);
  24.         System.out.println("Initial height (integer). The height of the TNT above the ender chests.");
  25.         System.out.println("If the dispenser is on the same level as the ender chests, enter 0.");
  26.         System.out.print("> ");
  27.         initialHeight = Double.parseDouble(scan.nextLine());
  28.         System.out.println("Launch TNT count (integer). The number of TNT used to launch the TNT.");
  29.         System.out.print("> ");
  30.         launchTntCount = Integer.parseInt(scan.nextLine());
  31.         scan.close();
  32.  
  33.         generateDetectorCircle();
  34.  
  35.         for (int i = 0; i < 20; i++) {
  36.             Random rand = new Random();
  37.             for (int j = 0; j < 7; j++) {
  38.                 for (int k = 0; k < 2696; k++)
  39.                     rand.nextDouble();
  40.                 System.out.print(getDetectorOutput(rand.nextDouble() * 2 * Math.PI) + " ");
  41.             }
  42.             System.out.println(getSeed(rand));
  43.         }
  44.  
  45.         /*
  46.         long largestDifference = 0;
  47.  
  48.         long lastSeed = 0;
  49.         for (int detectorId = 0; detectorId < detectors.size(); detectorId++) {
  50.             long seed = getUpperSeedBound(detectorId);
  51.             System.out.println(detectorId + ": " + toBinaryString(seed));
  52.             if (seed - lastSeed > largestDifference)
  53.                 largestDifference = seed - lastSeed;
  54.             lastSeed = seed;
  55.         }
  56.         System.out.println("Largest difference: " + largestDifference);
  57.         System.out.println("Log of that: " + Math.log(largestDifference) / Math.log(2));
  58.         System.out.println("Circle radius: " + -detectors.get(0).z);
  59.  
  60.         renderDetectors();
  61.         */
  62.  
  63.  
  64.  
  65.         initialHeight = 26;
  66.         launchTntCount = 7;
  67.         generateDetectorCircle();
  68.         long[] lut = new long[detectors.size()];
  69.         for (int i = 0; i < lut.length; i++)
  70.             lut[i] = getUpperSeedBound(i);
  71.  
  72.         final long a = 0x97be9f880aa9L;
  73.         final long b = 0xeac471130bcaL;
  74.         long[] bvec = {0xc8fbaf16b114L, 0xc2a36898b9feL, 0x13e60619c078L, 0xe7244157cb02L, 0x3771906241cL, 0x47d6c669fa46L, 0L};
  75.         final long[] m6 = {0xff7392795dd6L, 0x1184f9b300L, 0xff79d1d659aeL, 0xff62f08153d5L, 0xfe64fe5e8622L, 0x24beb7ecc11L, 0x30c38f7adcL};
  76.         final long[][] mm1 = {
  77.                 {-26, -81, -16, 50, 14, 22, -76},
  78.                 {-117, 4, -42, -45, -20, -61, -32},
  79.                 {3, 79, 1, 92, 5, 26, 8},
  80.                 {18, 28, 48, 53, -92, -33, -33},
  81.                 {43, 63, -68, -10, 33, 18, -57},
  82.                 {-21, -6, 91, -19, 56, 51, -12},
  83.                 {-44, 25, -6, -1, -44, 65, 34}
  84.         };
  85.         bvec = matmult(bvec, mm1);
  86.         System.out.println(Arrays.toString(bvec));
  87.  
  88.         for (int i = 0; i < 100; i++) {
  89.             Random rand = new Random();
  90.             int[] detectorArray = new int[7];
  91.             for (int j = 0; j < 7; j++) {
  92.                 for (int k = 0; k < 2696; k++)
  93.                     rand.nextDouble();
  94.                 detectorArray[j] = getDetectorOutput(rand.nextDouble() * 2 * Math.PI);
  95.             }
  96.  
  97.             long[] penultimateVector = new long[7];
  98.             for (int j = 0; j < 7; j++) {
  99.                 long[] v = new long[7];
  100.                 for (int k = 0; k < 7; k++) {
  101.                     int detectorId = detectorArray[k];
  102.                     if ((mm1[k][j] & 0x800000000000L) != 0) { // if it's negative mod 2^48
  103.                         detectorId--;
  104.                         if (detectorId < 0)
  105.                             detectorId += detectors.size();
  106.                         v[k] = lut[detectorId] & ~((1L << (48 - 26)) - 1);
  107.                     } else {
  108.                         v[k] = lut[detectorId];
  109.                     }
  110.                 }
  111.                 BigInteger val = dotBig(v, mm1, j);
  112.                 val = val.subtract(toBigInt48(bvec[j]));
  113.                 val = val.shiftRight(48);
  114.                 penultimateVector[j] = val.longValue();
  115.             }
  116.  
  117.             //System.out.println(Arrays.toString(penultimateVector));
  118.             long seed = dot(m6, penultimateVector) & 0xffffffffffffL;
  119.             for (int j = 0; j < 1; j++) {
  120.                 //seed = ((seed - 0xbL) * 0xdfe05bcb1365L) & 0xffffffffffffL;
  121.                 seed = (seed * 0x5deece66dL + 0xbL) & 0xffffffffffffL;
  122.             }
  123.             System.out.println("Expected: " + getSeed(rand) + ", actual: " + seed);
  124.             System.out.println("Diff: " + (getSeed(rand) - seed));
  125.         }
  126.  
  127.     }
  128.  
  129.     private static BigInteger toBigInt48(long n) {
  130.         if ((n & 0x800000000000L) != 0)
  131.             return BigInteger.valueOf(n | 0xffff000000000000L);
  132.         else
  133.             return BigInteger.valueOf(n & 0xffffffffffffL);
  134.     }
  135.  
  136.     private static BigInteger dotBig(long[] v, long[][] mat, int col) {
  137.         BigInteger result = BigInteger.ZERO;
  138.         for (int i = 0; i < v.length; i++) {
  139.             result = result.add(BigInteger.valueOf(v[i] & 0xffffffffffffL).multiply(toBigInt48(mat[i][col])));
  140.         }
  141.         return result;
  142.     }
  143.  
  144.     private static long dot(long[] a, long[] b) {
  145.         long result = 0;
  146.         for (int i = 0; i < a.length; i++)
  147.             result += a[i] * b[i];
  148.         return result;
  149.     }
  150.  
  151.     private static long[] matmult(long[] vec, long[][] mat) {
  152.         long[] result = new long[mat.length];
  153.         for (int i = 0; i < mat.length; i++) {
  154.             for (int j = 0; j < mat.length; j++) {
  155.                 result[i] += vec[j] * mat[j][i];
  156.             }
  157.         }
  158.         return result;
  159.     }
  160.  
  161.     private static long getSeed(Random rand) {
  162.         try {
  163.             Field field = Random.class.getDeclaredField("seed");
  164.             field.setAccessible(true);
  165.             return ((AtomicLong) field.get(rand)).get();
  166.         } catch (ReflectiveOperationException e) {
  167.             e.printStackTrace();
  168.             return 0;
  169.         }
  170.     }
  171.  
  172.     private static void generateDetectorCircle() {
  173.         detectors = new ArrayList<>();
  174.  
  175.         double radius = -simulateTntLaunch(0).z;
  176.         int x = (int) (radius + 0.49 - 0.001);
  177.         int z = 0;
  178.         while (x >= z) {
  179.             double dx = x - 0.99 - 0.001;
  180.             double dz = z + 0.01 + 0.001;
  181.             double dx2 = radius * radius - dz * dz;
  182.             if (dx2 < dx * dx)
  183.                 x--;
  184.             detectors.add(new Detector(x, z));
  185.             detectors.add(new Detector(-z, x));
  186.             detectors.add(new Detector(-x, -z));
  187.             detectors.add(new Detector(z, -x));
  188.             if (z != 0 && z != x) {
  189.                 detectors.add(new Detector(z, x));
  190.                 detectors.add(new Detector(-x, z));
  191.                 detectors.add(new Detector(-z, -x));
  192.                 detectors.add(new Detector(x, -z));
  193.             }
  194.             z++;
  195.         }
  196.  
  197.         detectors.sort(Comparator.comparingDouble(detector -> {
  198.             double angle = Math.atan2(-detector.x, -detector.z);
  199.             if (angle < 0) angle += Math.PI * 2;
  200.             return angle;
  201.         }));
  202.     }
  203.  
  204.     private static void renderDetectors() {
  205.         final int CELL_SIZE = 16;
  206.         int radius = -detectors.get(0).z;
  207.         BufferedImage image = new BufferedImage((2 * radius + 1) * CELL_SIZE, (2 * radius + 1) * CELL_SIZE, BufferedImage.TYPE_INT_ARGB);
  208.         Graphics2D g = image.createGraphics();
  209.         g.setColor(Color.WHITE);
  210.         g.fillRect(0, 0, image.getWidth(), image.getHeight());
  211.  
  212.         g.setColor(Color.GREEN);
  213.         for (Detector detector : detectors) {
  214.             g.fillRect((detector.x + radius) * CELL_SIZE, (detector.z + radius) * CELL_SIZE, CELL_SIZE, CELL_SIZE);
  215.         }
  216.  
  217.         g.setColor(Color.BLUE);
  218.         g.fillRect(radius * CELL_SIZE, radius * CELL_SIZE, CELL_SIZE, CELL_SIZE);
  219.  
  220.         g.setColor(Color.BLACK);
  221.         for (int i = 0; i < 2 * radius; i++) {
  222.             g.drawLine((i + 1) * CELL_SIZE, 0, (i + 1) * CELL_SIZE, image.getHeight());
  223.             g.drawLine(0, (i + 1) * CELL_SIZE, image.getWidth(), (i + 1) * CELL_SIZE);
  224.         }
  225.  
  226.         g.setColor(Color.RED);
  227.         double preciseRadius = -simulateTntLaunch(0).z;
  228.         g.drawOval((int) ((0.01 - preciseRadius + radius) * CELL_SIZE), (int) ((0.01 - preciseRadius + radius) * CELL_SIZE), (int) ((2 * preciseRadius) * CELL_SIZE), (int) ((2 * preciseRadius) * CELL_SIZE));
  229.         g.drawOval((int) ((0.01 - preciseRadius + radius) * CELL_SIZE), (int) ((0.99 - preciseRadius + radius) * CELL_SIZE), (int) ((2 * preciseRadius) * CELL_SIZE), (int) ((2 * preciseRadius) * CELL_SIZE));
  230.         g.drawOval((int) ((0.99 - preciseRadius + radius) * CELL_SIZE), (int) ((0.01 - preciseRadius + radius) * CELL_SIZE), (int) ((2 * preciseRadius) * CELL_SIZE), (int) ((2 * preciseRadius) * CELL_SIZE));
  231.         g.drawOval((int) ((0.99 - preciseRadius + radius) * CELL_SIZE), (int) ((0.99 - preciseRadius + radius) * CELL_SIZE), (int) ((2 * preciseRadius) * CELL_SIZE), (int) ((2 * preciseRadius) * CELL_SIZE));
  232.         g.dispose();
  233.  
  234.         try {
  235.             ImageIO.write(image, "PNG", new File("circle.png"));
  236.         } catch (IOException e) {
  237.             throw new UncheckedIOException(e);
  238.         }
  239.         try {
  240.             Desktop.getDesktop().open(new File("circle.png"));
  241.         } catch (IOException e) {
  242.             e.printStackTrace();
  243.         }
  244.     }
  245.  
  246.     private static long getUpperSeedBound(int detectorId) {
  247.         double upperAngle = getUpperAngleBound(detectorId);
  248.         long upperSeed = (long) (upperAngle / (2 * Math.PI) * 0x1.0p26) << (48 - 26);
  249.         upperSeed |= (1 << (48 - 26)) - 1;
  250.         return upperSeed;
  251.     }
  252.  
  253.     private static double getUpperAngleBound(int detectorId) {
  254.         final double EPSILON = 0x1.0p-28 * Math.PI;
  255.  
  256.         Detector detector = detectors.get(detectorId < 2 ? detectorId - 2 + detectors.size() : detectorId - 2);
  257.         double lower = Math.atan2(-detector.x, -detector.z);
  258.         detector = detectors.get((detectorId + 2) % detectors.size());
  259.         double upper = Math.atan2(-detector.x, -detector.z);
  260.  
  261.         while (upper - lower > EPSILON) {
  262.             double da = (upper - lower) % (Math.PI * 2);
  263.             double diff = 2 * da % (Math.PI * 2) - da;
  264.             double mid = lower + diff * 0.5;
  265.             int actualDetector = getDetectorOutput(mid);
  266.             int dd = (actualDetector - detectorId) % detectors.size();
  267.             int detectorDiff = 2 * dd % detectors.size() - dd;
  268.             if (detectorDiff <= 0)
  269.                 lower = mid;
  270.             else
  271.                 upper = mid;
  272.         }
  273.  
  274.         return upper < 0 ? upper + Math.PI * 2 : upper;
  275.     }
  276.  
  277.     private static int getDetectorOutput(double angle) {
  278.         TntEntity tnt = simulateTntLaunch(angle);
  279.  
  280.         int detectorId = 0;
  281.         boolean foundDetector = false;
  282.         while (true) {
  283.             double minX = tnt.x - 0.49 + 0.001, maxX = tnt.x + 0.49 - 0.001;
  284.             double minZ = tnt.z - 0.49 + 0.001, maxZ = tnt.z + 0.49 - 0.001;
  285.             Detector detector = detectors.get(detectorId);
  286.             boolean intersects = minX < detector.x + 1 && maxX >= detector.x && minZ < detector.z + 1 && maxZ >= detector.z;
  287.             if (intersects)
  288.                 foundDetector = true;
  289.             else if (foundDetector)
  290.                 return detectorId == 0 ? detectors.size() - 1 : detectorId - 1;
  291.             detectorId = (detectorId + 1) % detectors.size();
  292.         }
  293.     }
  294.  
  295.     // Simulates TNT being fired upwards from a dispenser at (0.5, initialHeight, 0.5) and being blasted by launchTntCount TNT
  296.     private static TntEntity simulateTntLaunch(double initialAngle) {
  297.         TntEntity tnt = new TntEntity();
  298.         tnt.x = 0.5;
  299.         tnt.y = initialHeight;
  300.         tnt.z = 0.5;
  301.         tnt.vx = -Math.sin(initialAngle) * 0.02;
  302.         tnt.vy = 0.2;
  303.         tnt.vz = -Math.cos(initialAngle) * 0.02;
  304.  
  305.         for (int i = 0; i < 29; i++)
  306.             tnt.update(initialHeight);
  307.  
  308.         double dx = tnt.x - 0.5;
  309.         double dy = -0.98/16;
  310.         double dz = tnt.z - 0.5;
  311.         double distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
  312.         double multiplier = (1 - (distance / 8)) / distance;
  313.         tnt.vx += dx * multiplier * launchTntCount;
  314.         tnt.vy += dy * multiplier * launchTntCount;
  315.         tnt.vz += dz * multiplier * launchTntCount;
  316.  
  317.         for (int i = 0; i < 80 - 29; i++) {
  318.             double minX = tnt.x - 0.49, maxX = tnt.x + 0.49;
  319.             double minZ = tnt.z - 0.49, maxZ = tnt.z + 0.49;
  320.             boolean offDispenser = maxX < 0 || minX > 1 || maxZ < 0 || minZ > 1;
  321.             tnt.update(offDispenser ? FLOOR_HEIGHT : initialHeight);
  322.         }
  323.  
  324.         return tnt;
  325.     }
  326.  
  327.     private static class TntEntity {
  328.         private double x, y, z, vx, vy, vz;
  329.  
  330.         void update(double floorHeight) {
  331.             vy -= 0.04;
  332.  
  333.             double dx = vx, dy = vy, dz = vz;
  334.             double prevVy = vy;
  335.             if (y + dy < floorHeight)
  336.                 dy = floorHeight - y;
  337.             y += dy;
  338.             x += dx;
  339.             z += dz;
  340.             boolean onGround = dy != prevVy && prevVy < 0;
  341.             if (dy != prevVy)
  342.                 vy = 0;
  343.  
  344.             vx *= 0.98;
  345.             vy *= 0.98;
  346.             vz *= 0.98;
  347.             if (onGround) {
  348.                 vx *= 0.7;
  349.                 vz *= 0.7;
  350.                 vy *= -0.5;
  351.             }
  352.         }
  353.     }
  354.  
  355.     private static class Detector {
  356.         private int x, z;
  357.  
  358.         public Detector(int x, int z) {
  359.             this.x = x;
  360.             this.z = z;
  361.         }
  362.     }
  363.  
  364.     private static String toBinaryString(long l) {
  365.         StringBuilder str = new StringBuilder(Long.toBinaryString(l));
  366.         while (str.length() < 48)
  367.             str.insert(0, "0");
  368.         return str.toString();
  369.     }
  370.  
  371. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement