public static List <MarioPuState> GetSuccessiveStates(MarioPuState state) { List <double> hSpeeds = GetSuccessiveHSpeeds(state.HSpeed); return(hSpeeds.ConvertAll( hSpeed => new MarioPuState(state.X, state.Y, state.Z, hSpeed, state.Angle, state, state.Index))); }
public MarioPuState(double x, double y, double z, double hSpeed, double angle, MarioPuState predecessor, int index) { X = x; Y = y; Z = z; HSpeed = hSpeed; Angle = angle; Predecessor = predecessor; Index = index; }
public static MarioPuState TestOverflowJump(MarioPuState state, int angle) { double hSpeed = state.HSpeed * 0.8; double hDist = hSpeed / 4; double vSpeed = 42 + state.HSpeed / 4; double vDist = vSpeed / 4; (double x, double z) = MoreMath.AddVectorToPoint(hDist, angle, state.X, state.Z); double y = state.Y + vDist; double modX = MoreMath.MaybeNegativeModulus(x, 65536); double modY = MoreMath.MaybeNegativeModulus(y, 65536); double modZ = MoreMath.MaybeNegativeModulus(z, 65536); if (modX < -8192 || modX > 8192) { return(null); } if (modZ < -8192 || modZ > 8192) { return(null); } if (modY < -8192) { return(null); } double?bestFloorY = null; foreach (TriangleDataModel tri in flatFloorTris) { if (tri.IsPointInsideAndAboveTriangle(modX, modY, modZ)) { double floorY = tri.GetHeightOnTriangle(modX, modZ); if (bestFloorY == null || floorY > bestFloorY) { bestFloorY = floorY; } } } if (bestFloorY.HasValue && bestFloorY.Value > state.Y - 3000) { return(new MarioPuState(x, bestFloorY.Value, z, hSpeed, angle, state, state.Index + 1)); } return(null); }
public static void Test() { double startX = -2838; double startY = 1610.8349609375; double startZ = -42.8171844482422; List <double> initialHSpeeds = new List <double>() { -427922.90625, -641883.5, -962824.375, -1444235.625, -2166352.75, -3249528.25, }; double goalX = 2806.789063; double goalY = 1033; double goalZ = -130.9819946; flatFloorTris = TriangleUtilities.GetLevelTriangles() .FindAll(tri => tri.IsFloor() && tri.NormY == 1 && tri.SurfaceType != 0x0A); possibleAngles = Enumerable.Range(0, 4096).ToList().ConvertAll(i => 16 * i); List <double> moreHSpeeds = initialHSpeeds.ConvertAll( hSpeed => GetSuccessiveHSpeeds(hSpeed)).SelectMany(list => list).ToList(); initialHSpeeds.AddRange(moreHSpeeds); initialHSpeeds = ControlUtilities.Randomize(initialHSpeeds); Queue <MarioPuState> queue = new Queue <MarioPuState>(); initialHSpeeds.ForEach(hSpeed => queue.Enqueue( new MarioPuState(startX, startY, startZ, hSpeed, 0, null, 0))); Config.Print("START"); int lastIndex = -1; while (queue.Count > 0) { MarioPuState dequeue = queue.Dequeue(); if (dequeue.Index > lastIndex) { lastIndex = dequeue.Index; Config.Print("Now on index " + lastIndex); } List <int> anglesToUse; if (dequeue.Index < 2) { anglesToUse = possibleAngles; } else { int angle = MoreMath.NormalizeAngleTruncated(MoreMath.AngleTo_AngleUnits(goalX, goalZ, dequeue.X, dequeue.Z)); anglesToUse = new List <int>() { angle - 16, angle, angle + 16 }; } foreach (int angle in anglesToUse) { MarioPuState state = TestOverflowJump(dequeue, angle); if (state == null) { continue; } double dist = MoreMath.GetDistanceBetween(state.X, state.Z, goalX, goalZ); if (state.Index >= 2 && dist > Math.Abs(state.HSpeed)) { continue; } if (dist < 1000 && state.Y == goalY) { Config.Print(dist); Config.Print(state.GetLineage()); } if (state.Index >= 3) { continue; } List <MarioPuState> nextStates = GetSuccessiveStates(state); nextStates.Insert(0, state); nextStates = ControlUtilities.Randomize(nextStates); nextStates.ForEach(s => queue.Enqueue(s)); } } Config.Print("END"); }