Advertisement
Guest User

Float Aligner Thingie

a guest
Sep 26th, 2023
241
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 16.41 KB | None | 0 0
  1. import java.util.*;
  2.  
  3. public class floot {
  4.    
  5.     public static HashMap<Integer, Movement> movementMap = new HashMap<>();
  6.     public static HashMap<Long, Movement> startMap = new HashMap<>();
  7.  
  8.  
  9.     //finds large starting movements to get "close to the target" and smaller movements to cover that distance later
  10.     //most times there's too many floats between raw start->target, so the starting movements cuts down that distance
  11.     //this way there's less distance to search through, and the distance is easily covered with a few smaller movements
  12.     //startLimit is how many floats the starting movements have to be within the target, and offsetLimit is how many floats the offsets can be
  13.     //fwiw 256.9999999-257.0(my usual goal) is about 2 million floats. And the closer to 0 the more it'll be(5.9999999-6.0 is ~100 million)
  14.     //the whole simulation is jankily crammed in here because I'm impatient and its like 5x faster to do stupidly than think critically
  15.     public static void createMovements(Set<Long> starts, Set<Integer> offsets, long startLimit, long offsetLimit, double start, double target){
  16.         //could be adjusted to do more or be rta friendly i just think this is fine generally
  17.         System.out.println("creating movements...");
  18.         long startTime = System.currentTimeMillis();
  19.         long targetLong = Double.doubleToLongBits(target);
  20.         long startLong = Double.doubleToLongBits(start);
  21.         boolean[] truefalse = {true,false};
  22.         boolean ground = false;
  23.         for(boolean sneak : truefalse) {
  24.             for(int strafe = 0; strafe < 2; strafe++) {
  25.                 double inputForward = 1 * (sneak ? 0.2940000295639038 : 0.9800000190734863);
  26.                 double inputSideways = strafe * (sneak ? 0.2940000295639038 : 0.9800000190734863);
  27.                 float speed = ground ? 0.1f : 0.02f;
  28.                 float friction = ground ? 0.54600006f : 0.91f;
  29.                 for (int yawIndex = 0; yawIndex < 65536; yawIndex += 1) {
  30.                     double pos = start;
  31.                     double vel = 0;
  32.                     double inputMag = inputForward * inputForward + inputSideways * inputSideways; //1 tick holding forward
  33.                     if(inputMag > 1){
  34.                         inputMag = (float)Math.sqrt(inputMag);
  35.                         inputForward/= inputMag;
  36.                         inputSideways/= inputMag;
  37.                     }
  38.                     vel += ((inputForward * (double)speed) * (double)MathHelp.MCsins[(yawIndex + 16384) & 0xFFFF]) +
  39.                             ((inputSideways * (double)speed) * (double)MathHelp.MCsins[(yawIndex) & 0xFFFF]);
  40.                     if (Math.abs(vel) < 1e-7) vel = 0; //:3
  41.                     pos+= vel;
  42.                     vel*= friction;
  43.                     if (Math.abs(vel) < 0.003) vel = 0; //1 tick holding back
  44.                     inputMag = inputForward * inputForward + inputSideways * inputSideways;
  45.                     if(inputMag > 1){
  46.                         inputMag = (float)Math.sqrt(inputMag);
  47.                         inputForward/= inputMag;
  48.                         inputSideways/= inputMag;
  49.                     }
  50.                     vel += ((-inputForward * (double)speed) * (double)MathHelp.MCsins[(yawIndex + 16384) & 0xFFFF]) +
  51.                             ((-inputSideways * (double)speed) * (double)MathHelp.MCsins[(yawIndex) & 0xFFFF]);
  52.                     if (Math.abs(vel) < 1e-7) vel = 0; //:3
  53.                     pos+= vel;
  54.                     vel*= friction;
  55.                     while(vel != 0) { //tick until stopped just in case
  56.                         if (Math.abs(vel) < 0.003) vel = 0;
  57.                         pos+= vel;
  58.                         vel*= friction;
  59.                     }
  60.                     for (int yawIndex1 = 0; yawIndex1 < 65536; yawIndex1 += 1) {
  61.                         double pos1 = pos;
  62.                         double vel1 = 0;
  63.                         inputMag = inputForward * inputForward + inputSideways * inputSideways; //1 tick holding forward
  64.                         if(inputMag > 1){
  65.                             inputMag = (float)Math.sqrt(inputMag);
  66.                             inputForward/= inputMag;
  67.                             inputSideways/= inputMag;
  68.                         }
  69.                         vel1 += ((inputForward * (double)speed) * (double)MathHelp.MCsins[(yawIndex1 + 16384) & 0xFFFF]) +
  70.                                 ((inputSideways * (double)speed) * (double)MathHelp.MCsins[(yawIndex1) & 0xFFFF]);
  71.                         if (Math.abs(vel1) < 1e-7) vel1 = 0; //:3
  72.                         pos1+= vel1;
  73.                         vel1*= friction;
  74.                         if (Math.abs(vel1) < 0.003) vel1 = 0; //1 tick holding back
  75.                         inputMag = inputForward * inputForward + inputSideways * inputSideways;
  76.                         if(inputMag > 1){
  77.                             inputMag = (float)Math.sqrt(inputMag);
  78.                             inputForward/= inputMag;
  79.                             inputSideways/= inputMag;
  80.                         }
  81.                         vel1 += ((-inputForward * (double)speed) * (double)MathHelp.MCsins[(yawIndex1 + 16384) & 0xFFFF]) +
  82.                                 ((-inputSideways * (double)speed) * (double)MathHelp.MCsins[(yawIndex1) & 0xFFFF]);
  83.                         if (Math.abs(vel1) < 1e-7) vel1 = 0; //:3
  84.                         pos1+= vel1;
  85.                         vel1*= friction;
  86.                         while(vel1 != 0) { //tick until stopped just in case
  87.                             if (Math.abs(vel1) < 0.003) vel1 = 0;
  88.                             pos1+= vel1;
  89.                             vel1*= friction;
  90.                         }
  91.                         long posLong = Double.doubleToLongBits(pos1);
  92.                         long startDiff = (posLong - startLong); //surely
  93.                         if(startDiff == 0) continue;
  94.                         if((Math.abs(posLong - targetLong) < startLimit) && starts.add(posLong)) { //is this a good lorge starting movement?
  95.                             startMap.put(startDiff, new Movement(new int[]{yawIndex, yawIndex, yawIndex1, yawIndex1}, new int[]{1,-1,1,-1}, new int[]{strafe, -strafe, strafe, -strafe}, false, sneak));
  96.                         }if((Math.abs(startDiff) < offsetLimit) && offsets.add((int)(posLong - startLong))) { //is this a good small offset?
  97.                             movementMap.put((int)startDiff, new Movement(new int[]{yawIndex, yawIndex, yawIndex1, yawIndex1}, new int[]{1,-1,1,-1}, new int[]{strafe, -strafe, strafe, -strafe}, false, sneak));
  98.                         }
  99.                     }
  100.                     if((yawIndex & 16383) == 0) System.out.println(".." + yawIndex);
  101.                 }
  102.             }
  103.         }
  104.         System.out.println(String.format("created %d starts within %d floats and %d < %d float offsets within in %.3f seconds.", starts.size(), startLimit, offsets.size(), offsetLimit, (double)(System.currentTimeMillis() - startTime) / 1000.0));
  105.  
  106.     }
  107.  
  108.  
  109.     //given a relatively close starting and target position on an axis
  110.     //find a set of inputs that moves that postion into that exact float target position
  111.     //this assumes no powers of two are passed during this, since it measures in numbers of float values passed per movement
  112.     //there's definitely better ways to do this that aren't jank or slow but I am not that smart
  113.     public static void main(String args[])
  114.     {
  115.         //starting position(aka hitbox position...)
  116.         double startPos = 1050;
  117.         //position to target
  118.         double targetPos = 1049.9999999;
  119.         //max number of acceptable movements before giving up and crying
  120.         int maxPath = 50;
  121.  
  122.         Set<Integer> offsets = new HashSet<>();
  123.         Set<Long> startOffsets = new HashSet<>();
  124.  
  125.         //sim heavy stuff to get movements that'll be used
  126.         createMovements(startOffsets, offsets, 2_000_000L, 2_000_000L, startPos, targetPos);
  127.  
  128.         //setup start/end indexes for actual search
  129.         long targetLong = Double.doubleToLongBits(targetPos);
  130.         long longOffset = Math.min(Collections.min(startOffsets), targetLong);
  131.         Set<Integer> starts = new HashSet<>();
  132.         for(Long a : startOffsets){
  133.             starts.add((int)(a - longOffset));
  134.         }
  135.         startOffsets.clear();
  136.         int targetIndex = (int)(targetLong - longOffset);
  137.        
  138.  
  139.  
  140.         //I'm not actually sure how large this should be mathematically but ig this works?
  141.         int searchRange = 1 + Math.max(Collections.max(starts), targetIndex) + Collections.max(offsets);
  142.         System.out.println("finding path...");
  143.         long searchTime = System.currentTimeMillis();
  144.         LinkedList<Integer> path = findPath(starts, targetIndex, offsets, searchRange, maxPath);
  145.         if(path != null){
  146.             System.out.println(String.format("%d movement solution from %.16f(%d) found in %f seconds \nPath: ", path.size(), startPos, Double.doubleToLongBits(startPos), (double)(System.currentTimeMillis() - searchTime) / 1000.0));
  147.             StringBuilder movementsString = new StringBuilder(Double.longBitsToDouble(path.get(path.size() - 1) + longOffset) + String.format("(%d) ", path.get(path.size() - 1) + longOffset) + startMap.get((path.get(path.size() - 1) + longOffset) - Double.doubleToLongBits(startPos)).toString());
  148.             for (int i = path.size() - 1; i >= 0; i--) {
  149.                 long currentfloat = path.get(i) + longOffset;
  150.                 if(i != path.size() -1) movementsString.append(Double.longBitsToDouble(currentfloat) + String.format("(%d) ", currentfloat) + movementMap.get((int)(currentfloat - (path.get(i + 1) + longOffset))).toString());
  151.             }
  152.             System.out.println(movementsString);
  153.         }else{
  154.             System.out.println(String.format("no solution found within %d movements in %f seconds", maxPath, (double)(System.currentTimeMillis() - searchTime) / 1000.0));
  155.         }
  156.     }
  157.  
  158.     //try and get from specified starting points to the destination w/ only increments of the provided offsets
  159.     //each index represents one float value. kinda looks like the dragon ai
  160.     public static LinkedList<Integer> findPath(Set<Integer> starts, int target, Set<Integer> offsets, int range, int maxMovements){
  161.         int[] prevFloat = new int[range]; //tracks our path through the floats by linking each index to its previous
  162.         short[] movements = new short[range]; //number of movements to get here
  163.         boolean[] visited = new boolean[range]; //number of movements to get here
  164.         Queue<Integer> queue = new LinkedList<>();
  165.  
  166.         for(int i = 0; i < range; i++){
  167.             movements[i] = -1;
  168.             prevFloat[i] = -1;
  169.         }
  170.         for(int start : starts){ //start branching from all of these at once
  171.             visited[start] = true;
  172.             movements[start] = 0;
  173.             queue.add(start);
  174.         }
  175.         int c = 0;
  176.         search: {
  177.             while (!queue.isEmpty()) { // search as long as there's stuff to search from
  178.                 int index = queue.remove();
  179.                 if (movements[index] > maxMovements) continue;
  180.                 for (int offset : offsets) { //branch out to all our possible offsets
  181.                     int offIndex = offset + index;
  182.                     if (offIndex > -1 && offIndex < range && !visited[offIndex]) { //have we been here/is it in bounds/is it worth
  183.                         visited[offIndex] = true;
  184.                         movements[offIndex] = (short) (movements[index] + 1);
  185.                         prevFloat[offIndex] = index;
  186.                         queue.add(offIndex); //link up and advance this offset
  187.                         c++;
  188.                         if (offIndex == target) { //wow we made it this is so epic sauce
  189.                             break search;
  190.                         }
  191.                     }
  192.                 }
  193.                 if((c & 32767) == 0) System.out.println(String.format("%.3f",(double)c/range));
  194.             }
  195.             return null; //we couldn't get anywhere reasonably rest in peace
  196.         }
  197.         //your royal success... you should be out changing your life for the better!
  198.         //but instead you just sit, hoping that today will be the day, all while praying that each tomorrow will be the same as before.
  199.         //is there something i just can't see? what more can you be waiting for? surely you can't run in circles forever?
  200.         int traverse = target;
  201.         LinkedList<Integer> path = new LinkedList<>(List.of(traverse));
  202.         while(prevFloat[traverse] != -1){
  203.             traverse = prevFloat[traverse];
  204.             path.add(traverse);
  205.         }
  206.         return path;
  207.     }
  208. }
  209.  
  210. class MathHelp { //does silly math stuff to mimic how minecraft handles it
  211.  
  212.     //lookup table used by minecraft trigonometry functions
  213.     public static final float[] MCsins = constructSines();
  214.  
  215.     //radian value thingy to make my life easier
  216.     //or smthn ig idk what a math is
  217.     private static final float RAD = ((float)Math.PI / 180);
  218.  
  219.     //builds the sin table from minecraft
  220.     public static float[] constructSines(){
  221.         float[] MCsins = new float[65536];
  222.         for (int i = 0; i < 65536; ++i) {
  223.             MCsins[i] = (float)Math.sin((double)i * Math.PI * 2.0 / 65536.0);
  224.         }
  225.         return MCsins;
  226.     }
  227.  
  228.     //returns whether the two doubles are almost the same(within .00001)
  229.     public static boolean isNear(double a, double b){
  230.         return Math.abs(b - a) < 1.0E-5f;
  231.     }
  232.     //ceiling function
  233.     public static int ceil(float f) {
  234.         int i = (int)f;
  235.         return f > (float)i ? i + 1 : i;
  236.     }
  237.     //flooring functions
  238.     public static int floor(double d) {
  239.         int i = (int)d;
  240.         return d < (double)i ? i - 1 : i;
  241.     }
  242.     public static long lfloor(double d) {
  243.         long l = (long)d;
  244.         return d < (double)l ? l - 1L : l;
  245.     }
  246.  
  247.     //returns the stuff after the period.
  248.     public static double fractionalPart(double value) {
  249.         return value - (double) MathHelp.lfloor(value);
  250.     }
  251.  
  252.     //returns the sign of a double
  253.     public static int sign(double d) {
  254.         if (d == 0.0) {
  255.             return 0;
  256.         }
  257.         return d > 0.0 ? 1 : -1;
  258.     }
  259.  
  260.     //returns the sin value of a given radian
  261.     //but using minecraft's quirky table
  262.     public static float MCsin(float f) {
  263.         return MCsins[(int)(f * 10430.378f) & 0xFFFF];
  264.     }
  265.  
  266.     //returns the cos value of a given radian
  267.     //but also using minecraft's quirky table
  268.     public static float MCcos(float f) {
  269.         return MCsins[(int)(f * 10430.378f + 16384.0f) & 0xFFFF];
  270.     }
  271.  
  272.     //returns the funky radian value to make my life easier
  273.     public static float RAD(){
  274.         return RAD;
  275.     }
  276.  
  277. }
  278.  
  279. //jank info about a specific movement
  280. class Movement{
  281.  
  282.     boolean ground;
  283.     boolean sneak;
  284.     int[] forwards;
  285.     int[] strafes;
  286.     int[] yaws;
  287.  
  288.     public Movement(int[] yaws, int[] forwards, int[] strafes, boolean ground, boolean sneak){
  289.         this.yaws = yaws;
  290.         this.forwards = forwards;
  291.         this.strafes = strafes;
  292.         this.ground = ground;
  293.         this.sneak = sneak;
  294.     }
  295.  
  296.     //tries to recreate a in-game angle from a specific index into the sin table
  297.     public static float estimateAngle(int angleIndex){
  298.         float guess = ((float)angleIndex / 10430.378f) / MathHelp.RAD();
  299.         if(angleIndex == ((int)((guess * MathHelp.RAD()) * 10430.378f) & 0xFFFF) && angleIndex + 16384 == ((int)((guess * MathHelp.RAD()) * 10430.378f + 16384.0f) & 0xFFFF)){
  300.             return guess;
  301.         }else{
  302.             for(float guess1 = guess - 0.01f; guess1 < guess + 0.01; guess1+= 0.001f){
  303.                 if(angleIndex == ((int)((guess1 * MathHelp.RAD()) * 10430.378f) & 0xFFFF) && angleIndex + 16384 == ((int)((guess1 * MathHelp.RAD()) * 10430.378f + 16384.0f) & 0xFFFF)){
  304.                     return guess1;
  305.                 }
  306.             }
  307.             return -1f;
  308.         }
  309.     }
  310.  
  311.     // ?
  312.     public String toString() {
  313.         StringBuilder string = new StringBuilder((ground ? "ground " : "air ") + (sneak ? "sneak " : "walk ") + "w/ inputs: ");
  314.         for(int i = 0; i < yaws.length; i++){
  315.             string.append(String.format("%d: (yaw: %d[%.10f], " + (forwards[i] == 1 ? "forward, " : (forwards[i] == -1 ? "back, " : " ")) + (strafes[i] == 1 ? "left" : (strafes[i] == -1 ? "right" : "")) + ") ", i, yaws[i], estimateAngle(yaws[i])));
  316.         }
  317.         string.append("\n");
  318.         return string.toString();
  319.     }
  320.  
  321. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement