public static Limb DirectCopy (Limb src) { Limb result = new Limb(); for (int i = 0; i < result.m_Parts.Length; ++i) { result[i] = Part.DirectCopy(src.m_Parts[i]); } return result; }
public static Vector Calculate (Limb[] limbs, Vector default_facing) { if (default_facing == null) { throw new ArgumentException(); } float dx = 0.0f; float dy = 0.0f; int count = 0; for (int a = 0; a < Limb.PART_COUNT; ++a) { Part part_a = limbs[0][a]; if (part_a.IsUnknown()) { continue; } for (int b = 0; b < Limb.PART_COUNT; ++b) { Part part_b = limbs[1][b]; if (part_b.IsUnknown()) { continue; } Vector f = Panel.GetFacing( part_a.panel.index, part_b.panel.index ); dx += f.dx; dy += f.dy; ++count; } } if (count == 0) { return default_facing; } else { return new Vector(dx/count, dy/count); } }
private static bool IsValidOrNot3Bracket (Limb[] limbs) { foreach (Limb limb in limbs) { if (!IsValidOrNot3Bracket(limb == limbs[0], limb)) { return false; } } return true; }
public static void Calculate (State from, Node to, List<Limb[]> output) { if (!IsArcValid(from, to)) { return; } int hoverable_count = 0; Limb[] original = new Limb[from.limbs.Length]; for (int i = 0; i < from.limbs.Length; ++i) { Limb from_limb = from.limbs[i]; Analyzer.Node.Limb to_limb = to.limbs[i]; if (to_limb == null) { original[i] = Limb.ToPassiveDown(from_limb, to.second); } else { original[i] = LimbHelper.TransitionToV3(from_limb, to_limb, to.second); } if (IsHoverable(original[i].main.movement)) { ++hoverable_count; } if (IsHoverable(original[i].sub.movement)) { ++hoverable_count; } else if (IsHoverable(original[i].extra.movement)) { ++hoverable_count; } original[i].sanityCheck(); } if (!IsOverlapping(original) && IsValidOrNot3Bracket(original)) { output.Add(original); } if (hoverable_count >= 2) { for (int limb_index = 0; limb_index < from.limbs.Length; ++limb_index) { Limb limb = original[limb_index]; if (IsHoverable(limb.main.movement)) { Limb[] with_unknown = CloneWithHover(original, limb_index, to.second, 0); if (!IsOverlapping(with_unknown) && IsValidOrNot3Bracket(with_unknown)) { output.Add(with_unknown); } } if (IsHoverable(limb.sub.movement)) { if (IsHoverable(limb.extra.movement)) { Limb[] with_unknown = CloneWithHover(original, limb_index, to.second, 1, 2); if (!IsOverlapping(with_unknown) && IsValidOrNot3Bracket(with_unknown)) { output.Add(with_unknown); } } else { Limb[] with_unknown = CloneWithHover(original, limb_index, to.second, 1); if (!IsOverlapping(with_unknown) && IsValidOrNot3Bracket(with_unknown)) { output.Add(with_unknown); } } } else if (IsHoverable(limb.extra.movement)) { Limb[] with_unknown = CloneWithHover(original, limb_index, to.second, 2); if (!IsOverlapping(with_unknown) && IsValidOrNot3Bracket(with_unknown)) { output.Add(with_unknown); } } } } }
public static bool IsArcValid (Limb from, Analyzer.Node.Limb to) { if (to == null) { return true; } for (int i = 0; i < Limb.PART_COUNT; ++i) { if (!PartHelper.IsArcValid(from[i], to[i])) { return false; } } return true; }
public static Limb ToPassiveDown (Limb src, float cur_second) { Limb result = new Limb(); for (int i = 0; i < result.m_Parts.Length; ++i) { if (src.m_Parts[i].IsUnknown()) { result[i] = Part.ToUnknown(src.m_Parts[i], cur_second); } else { result[i] = Part.ToPassiveDown(src.m_Parts[i], cur_second); } } return result; }
private static bool IsValidOrNot3Bracket (bool is_left_leg, Limb limb) { return ( limb.main.IsUnknown() || limb.sub.IsUnknown() || limb.extra.IsUnknown() ) || Panel.IsValidOrNot3Bracket( is_left_leg, limb.main.panel.index, limb.sub.panel.index, limb.extra.panel.index ); }
private static bool IsOverlapping (Limb[] limbs) { for (int a = 0; a < Limb.PART_COUNT; ++a) { Part part_a = limbs[0][a]; if (part_a.IsUnknown()) { continue; } for (int b = 0; b < Limb.PART_COUNT; ++b) { Part part_b = limbs[1][b]; if (part_b.IsUnknown()) { continue; } if (part_a.panel == part_b.panel) { return true; } } } return false; }
public Fail (Limb limb) { main_sub = !Panel.IsBracketable( limb.main.panel.index, limb.sub.panel.index ); main_extra = !Panel.IsBracketable( limb.main.panel.index, limb.extra.panel.index ); sub_extra = (limb.sub.panel == limb.extra.panel) ? false : !Panel.IsSubBracketable( limb.sub.panel.index, limb.extra.panel.index ); }
public static Limb[] CloneWithHover (Limb[] src, int limb_index, float cur_second, params int[] part_index) { Limb[] dst = new Limb[src.Length]; for (int i = 0; i < src.Length; ++i) { dst[i] = Limb.DirectCopy(src[i]); if (i == limb_index) { foreach (int p in part_index) { dst[i][p] = new Part( Movement.Unknown, null, dst[i][p].cur_second, dst[i][p].cur_moved_second, dst[i][p].prv_moved_second ); } } dst[i].sanityCheck(); } return dst; }
public static State TransitionTo (State from, Limb[] to, float second, int distance_from_start, Beat beat, ICostFactory cost_factory) { State nxt = null; Vector facing = FacingCalculator.Calculate(to, from.facing); Vector facing_desired = FacingCalculator.CalculateDesiredFacing(facing, from.facing_desired); if (IsArcValidWithoutCrossing(to, facing_desired)) { nxt = new State(from, second, distance_from_start, false); } else if (IsArcValidWithCrossing(to, facing_desired)) { //nxt = new State(from, second, distance_from_start, true); return null; } else { return null; } //Transition for (int i = 0; i < from.limbs.Length; ++i) { nxt.limbs[i] = to[i]; } nxt.beat = beat; nxt.facing = facing; nxt.facing_desired = facing_desired; nxt.sanityCheck(); nxt.cost = cost_factory.Calculate(nxt); return nxt; }
public static bool IsArcValidWithCrossing (Limb[] to, Vector facing) { float facing_rad = facing.toRadian(); foreach (Limb limb in to) { if ( !limb.main.IsUnknown() && !limb.sub.IsUnknown() && !Panel.IsBracketableDirection( facing_rad, limb == to[1], limb.main.panel.index, limb.sub.panel.index ) ) { return false; } if ( !limb.main.IsUnknown() && !limb.extra.IsUnknown() && !Panel.IsBracketableDirection( facing_rad, limb == to[1], limb.main.panel.index, limb.extra.panel.index ) ) { return false; } } return true; }
public static Limb TransitionToV3 (Limb from, Analyzer.Node.Limb to, float cur_second) { if (!IsArcValid(from, to)) { throw new ArgumentException(); } if (to == null) { throw new ArgumentException(); } else { Limb nxt = new Limb(); for (int i = 0; i < Limb.PART_COUNT; ++i) { Part from_part = from[i]; Analyzer.Node.Part to_part = to[i]; Part part; if (to_part == null) { if (from_part.IsUnknown()) { part = Part.ToUnknown(from_part, cur_second); } else { part = Part.ToPassiveDown(from_part, cur_second); } } else { if (PartHelper.IsArcValid(from_part, to_part)) { part = PartHelper.TransitionTo(from_part, to_part, cur_second); } else { throw new ArgumentException(); } } nxt[i] = part; } FixInvalidBracket(nxt); nxt.sanityCheck(); return nxt; } }
private static void FixInvalidBracket (Limb limb) { if ( !limb.main.IsUnknown() && !limb.sub.IsUnknown() && ( limb.main.panel == limb.sub.panel || !Panel.IsBracketable( limb.main.panel.index, limb.sub.panel.index ) ) ) { if (limb.main.IsPassiveDown()) { limb.main = Part.ToUnknown(limb.main); } else { limb.sub = Part.ToUnknown(limb.sub); } } if ( !limb.main.IsUnknown() && !limb.extra.IsUnknown() && ( limb.main.panel == limb.extra.panel || !Panel.IsBracketable( limb.main.panel.index, limb.extra.panel.index ) ) ) { if (limb.main.IsPassiveDown()) { limb.main = Part.ToUnknown(limb.main); } else { limb.extra = Part.ToUnknown(limb.extra); } } if ( !limb.sub.IsUnknown() && !limb.extra.IsUnknown() && ( limb.sub.panel == limb.extra.panel || !Panel.IsSubBracketable( limb.sub.panel.index, limb.extra.panel.index ) ) ) { if (limb.sub.IsPassiveDown()) { limb.sub = Part.ToUnknown(limb.sub); } else { limb.extra = Part.ToUnknown(limb.extra); } } }
public static Limb TransitionTo (Limb from, Analyzer.Node.Limb to, float cur_second) { if (!IsArcValid(from, to)) { throw new ArgumentException(); } if (to == null) { throw new ArgumentException(); /*Limb nxt = new Limb(); for (int i = 0; i < Limb.PART_COUNT; ++i) { Part part = PartHelper.TransitionTo(from[i], null, cur_second); nxt[i] = part; } nxt.sanityCheck(); return nxt;*/ } else { Limb nxt = new Limb(); for (int i = 0; i < Limb.PART_COUNT; ++i) { Part part = PartHelper.TransitionTo(from[i], to[i], cur_second); nxt[i] = part; } if (to[Analyzer.Node.Limb.INDEX_EXTRA] == null) { nxt.extra = nxt.sub; } bool has_main = to.main != null; bool has_sub = to.sub != null; bool has_extra = to.extra != null; Fail fail = new Fail(nxt); if (has_main) { if (has_sub) { if (has_extra) { //main+sub+extra if (fail.main_sub) { throw new ArgumentException(); } if (fail.main_extra) { throw new ArgumentException(); } if (fail.sub_extra) { throw new ArgumentException(); } } else { //main+sub if (fail.main_sub) { throw new ArgumentException(); } if (fail.main_extra) { nxt.extra = nxt.sub; fail = new Fail(nxt); } if (fail.sub_extra) { nxt.extra = nxt.sub; fail = new Fail(nxt); } } } else if (has_extra) { //main+extra if (fail.main_sub) { nxt.sub = nxt.extra; fail = new Fail(nxt); } if (fail.main_extra) { throw new ArgumentException(); } if (fail.sub_extra) { nxt.sub = nxt.extra; fail = new Fail(nxt); } } else { //main if (fail.main_sub) { Panel n = Panel.CalculateBestBracketable(nxt.main.panel, nxt.sub.panel); Part src = nxt.sub; nxt.sub = new Part( Movement.Unknown, n, src.cur_second, cur_second, src.cur_moved_second == cur_second ? src.prv_moved_second : src.cur_moved_second ); fail = new Fail(nxt); } if (fail.main_extra) { nxt.extra = nxt.sub; fail = new Fail(nxt); } if (fail.sub_extra) { throw new ArgumentException(); } } } else if (has_sub) { if (has_extra) { //sub+extra if (fail.main_sub) { Panel n = Panel.CalculateBestBracketable(nxt.sub.panel, nxt.main.panel); Part src = nxt.main; nxt.main = new Part( Movement.Unknown, n, src.cur_second, cur_second, src.cur_moved_second == cur_second ? src.prv_moved_second : src.cur_moved_second ); fail = new Fail(nxt); } if (fail.main_extra) { Panel n = Panel.CalculateBestBracketable(nxt.extra.panel, nxt.main.panel); Part src = nxt.main; nxt.main = new Part( Movement.Unknown, n, src.cur_second, cur_second, src.cur_moved_second == cur_second ? src.prv_moved_second : src.cur_moved_second ); fail = new Fail(nxt); } if (fail.sub_extra) { throw new ArgumentException(); } } else { //sub if (fail.main_sub) { Panel n = Panel.CalculateBestBracketable(nxt.sub.panel, nxt.main.panel); Part src = nxt.main; nxt.main = new Part( Movement.Unknown, n, src.cur_second, cur_second, src.cur_moved_second == cur_second ? src.prv_moved_second : src.cur_moved_second ); fail = new Fail(nxt); } if (fail.main_extra) { throw new ArgumentException(); } if (fail.sub_extra) { nxt.extra = nxt.sub; fail = new Fail(nxt); } } } else if (has_extra) { //extra if (fail.main_sub) { throw new ArgumentException(); } if (fail.main_extra) { Panel n = Panel.CalculateBestBracketable(nxt.extra.panel, nxt.main.panel); Part src = nxt.main; nxt.main = new Part( Movement.Unknown, n, src.cur_second, cur_second, src.cur_moved_second == cur_second ? src.prv_moved_second : src.cur_moved_second ); fail = new Fail(nxt); } if (fail.sub_extra) { nxt.sub = nxt.extra; fail = new Fail(nxt); } } else { //NOTHING if (fail.main_sub) { throw new ArgumentException(); } if (fail.main_extra) { throw new ArgumentException(); } if (fail.sub_extra) { throw new ArgumentException(); } } if (fail.main_sub || fail.main_extra || fail.sub_extra) { throw new ArgumentException(); } nxt.sanityCheck(); return nxt; } }
public static List<Limb> TransitionToV2 (Limb from, Analyzer.Node.Limb to, float cur_second) { if (!IsArcValid(from, to)) { throw new ArgumentException(); } if (to == null) { throw new ArgumentException(); } List<Limb> result = new List<Limb>(); Limb nxt = new Limb(); for (int i = 0; i < Limb.PART_COUNT; ++i) { Part part = PartHelper.TransitionTo(from[i], to[i], cur_second); nxt[i] = part; } if (to[Analyzer.Node.Limb.INDEX_EXTRA] == null) { nxt.extra = nxt.sub; } bool has_main = to.main != null; bool has_sub = to.sub != null; bool has_extra = to.extra != null; Fail fail = new Fail(nxt); if (has_main) { if (has_sub) { if (has_extra) { //main+sub+extra if (fail.main_sub) { //throw new ArgumentException(); } if (fail.main_extra) { //throw new ArgumentException(); } if (fail.sub_extra) { //throw new ArgumentException(); } } else { //main+sub if (fail.main_sub) { //throw new ArgumentException(); } if (fail.main_extra) { nxt.extra = nxt.sub; fail = new Fail(nxt); } if (fail.sub_extra) { nxt.extra = nxt.sub; fail = new Fail(nxt); } } } else if (has_extra) { //main+extra if (fail.main_sub) { nxt.sub = nxt.extra; fail = new Fail(nxt); } if (fail.main_extra) { //throw new ArgumentException(); } if (fail.sub_extra) { nxt.sub = nxt.extra; fail = new Fail(nxt); } } else { //main if (fail.main_sub) { List<Panel> neighbours = Panel.Neighbours_1D[nxt.main.panel.index]; foreach (Panel n in neighbours) { Limb copy = Limb.DirectCopy(nxt); Part src = copy.sub; copy.sub = new Part( Movement.Unknown, n, src.cur_second, cur_second, src.cur_moved_second == cur_second ? src.prv_moved_second : src.cur_moved_second ); Fail copy_fail = new Fail(copy); if (copy_fail.main_extra) { copy.extra = copy.sub; } AddIfValid(result, copy); } } if (fail.main_extra) { nxt.extra = nxt.sub; fail = new Fail(nxt); } if (fail.sub_extra) { //throw new ArgumentException(); } } } else if (has_sub) { if (has_extra) { //sub+extra if (fail.main_sub) { List<Panel> neighbours = Panel.Neighbours_1D[nxt.sub.panel.index]; foreach (Panel n in neighbours) { Limb copy = Limb.DirectCopy(nxt); Part src = copy.main; copy.main = new Part( Movement.Unknown, n, src.cur_second, cur_second, src.cur_moved_second == cur_second ? src.prv_moved_second : src.cur_moved_second ); Fail copy_fail = new Fail(copy); if (copy_fail.main_extra) { List<Panel> neighbours_2 = Panel.Neighbours_1D[nxt.extra.panel.index]; foreach (Panel n_2 in neighbours_2) { Limb copy_2 = Limb.DirectCopy(copy); Part src_2 = copy_2.main; copy_2.main = new Part( Movement.Unknown, n_2, src_2.cur_second, cur_second, src_2.cur_moved_second == cur_second ? src_2.prv_moved_second : src_2.cur_moved_second ); AddIfValid(result, copy_2); } } AddIfValid(result, copy); } } if (fail.main_extra) { List<Panel> neighbours_2 = Panel.Neighbours_1D[nxt.extra.panel.index]; foreach (Panel n_2 in neighbours_2) { Limb copy_2 = Limb.DirectCopy(nxt); Part src_2 = copy_2.main; copy_2.main = new Part( Movement.Unknown, n_2, src_2.cur_second, cur_second, src_2.cur_moved_second == cur_second ? src_2.prv_moved_second : src_2.cur_moved_second ); AddIfValid(result, copy_2); } } if (fail.sub_extra) { //throw new ArgumentException(); } } else { //sub if (fail.main_sub) { List<Panel> neighbours = Panel.Neighbours_1D[nxt.sub.panel.index]; foreach (Panel n in neighbours) { Limb copy = Limb.DirectCopy(nxt); Part src = copy.main; copy.main = new Part( Movement.Unknown, n, src.cur_second, cur_second, src.cur_moved_second == cur_second ? src.prv_moved_second : src.cur_moved_second ); Fail copy_fail = new Fail(copy); if (copy_fail.main_extra) { //do nothing } if (copy_fail.sub_extra) { copy.extra = copy.sub; } AddIfValid(result, copy); } } if (fail.main_extra) { //throw new ArgumentException(); } if (fail.sub_extra) { nxt.extra = nxt.sub; } } } else if (has_extra) { //extra if (fail.main_sub) { //throw new ArgumentException(); } if (fail.main_extra) { List<Panel> neighbours = Panel.Neighbours_1D[nxt.extra.panel.index]; foreach (Panel n in neighbours) { Limb copy = Limb.DirectCopy(nxt); Part src = copy.main; copy.main = new Part( Movement.Unknown, n, src.cur_second, cur_second, src.cur_moved_second == cur_second ? src.prv_moved_second : src.cur_moved_second ); Fail copy_fail = new Fail(copy); if (copy_fail.sub_extra) { copy.sub = copy.extra; } AddIfValid(result, copy); } } if (fail.sub_extra) { nxt.sub = nxt.extra; } } else { //NOTHING if (fail.main_sub) { //throw new ArgumentException(); } if (fail.main_extra) { //throw new ArgumentException(); } if (fail.sub_extra) { //throw new ArgumentException(); } } AddIfValid(result, nxt); return result; }
private static void AddIfValid (List<Limb> list, Limb item) { Fail fail = new Fail(item); if (fail.main_sub || fail.main_extra || fail.sub_extra) { return; } item.sanityCheck(); list.Add(item); }