private List <RefillFlowRecord.Path> CollectFromPos(Container2D_Rectangular container, FillInfo[,] fillInfos, int fromX, int fromY) { if (!container.IsLegalPosition(fromX, fromY) || null != container.GetSlot(fromX, fromY)) { return(null); } var fi = fillInfos[fromY, fromX]; var ret = new List <RefillFlowRecord.Path>(); var selfPos = new Pos2D(fromX, fromY); var self = new RefillFlowRecord.Path(); self.dst = selfPos; ret.Add(self); foreach (var child in fi.childrenPos) { var sub = CollectFromPos(container, fillInfos, child.x, child.y); if (null == sub) { continue; } ret.AddRange(sub); } foreach (var r in ret) { r.src = selfPos; r.movements.Add(selfPos); } return(ret); }
private List <RefillFlowRecord.Path> CollectFillPathList(Container2D_Rectangular container, FillInfo[,] fillInfos) { var ret = new List <RefillFlowRecord.Path>(); for (int x = 0; x < container.Width; x++) { var sub = CollectFromPos(container, fillInfos, x, container.Height - 1); if (null == sub) { continue; } sub.Sort((lhr, rhr) => { return((lhr.movements.Count > rhr.movements.Count) ? -1 : 1); }); var len = sub.Count; for (int i = 0; i < len; i++) { var index = i + 1; var s = sub[i]; s.src = new Pos2D(x, container.Height - 1 + index); for (int j = 1; j <= index; j++) { s.movements.Add(new Pos2D(x, container.Height - 1 + j)); } s.movements.Reverse(); } ret.AddRange(sub); } return(ret); }
public override RefillFlowRecord Apply (Container2D_Rectangular container) { var key = GetType().Name + "-" + "RefillInfoMap"; FillInfo[,] fillInfoMap = null; if (!container.UserData.ContainsKey(key)) { List<Pos2D> pores = new List<Pos2D>(); container.ForeachSlot((x, y, slot)=>{ if (null == slot){ pores.Add(new Pos2D(x, y)); container.WrapperRect[y, x] = new SlotWrapper2D(); container.WrapperRect[y, x].pos = new Pos2D(x, y); } }); fillInfoMap = GenerateRefillTrendMap(container); container.UserData.Add(key, fillInfoMap); GlobalDebug.refillInfoMap = fillInfoMap; foreach (var p in pores) { container.ClearSlot(p.x, p.y); } } else { fillInfoMap = container.UserData[key] as FillInfo[,]; } return DoApply(container, fillInfoMap); }
private List <Pos2D> CollectRefillEnds(Container2D_Rectangular container, FillInfo[,] fillInfoMap) { var slots = container.WrapperRect; var ret = new List <Pos2D>(); container.ForeachSlot((x, y, slot) => { if (null != slot) { return; } if (fillInfoMap[y, x].IsOnSpot) { return; } foreach (var t in surroundingOffsets) { if (!container.IsLegalPosition(x + t.item1, y + t.item2)) { continue; } if (null != slots[y + t.item2, x + t.item1]) { continue; } var fi = fillInfoMap[y + t.item2, x + t.item1]; if (!fi.IsOnSpot && fi.ancestorPos.x == x && fi.ancestorPos.y == y) { return; } } ret.Add(new Pos2D(x, y)); }); return(ret); }
public override RefillFlowRecord Apply(Container2D_Rectangular container) { var key = GetType().Name + "-" + "RefillInfoMap"; FillInfo[,] fillInfoMap = null; if (!container.UserData.ContainsKey(key)) { List <Pos2D> pores = new List <Pos2D>(); container.ForeachSlot((x, y, slot) => { if (null == slot) { pores.Add(new Pos2D(x, y)); container.WrapperRect[y, x] = new SlotWrapper2D(); container.WrapperRect[y, x].pos = new Pos2D(x, y); } }); fillInfoMap = GenerateRefillTrendMap(container); container.UserData.Add(key, fillInfoMap); GlobalDebug.refillInfoMap = fillInfoMap; foreach (var p in pores) { container.ClearSlot(p.x, p.y); } } else { fillInfoMap = container.UserData[key] as FillInfo[, ]; } return(DoApply(container, fillInfoMap)); }
private List <LMRecord2D_Retangular> SeekContainerLM(Container2D_Rectangular container) { var ret = new List <LMRecord2D_Retangular>(); var seekCtx = new LMSeeker2D_Retangular.SeekContext(); seekCtx.container = container; seekCtx.matchRules = matchRules; seekCtx.result = ret; LMSeeker2D_Retangular.Seek(seekCtx); return(ret); }
private bool[,] CollectContainerEliminate(Container2D_Rectangular container, List <LMRecord2D_Retangular> lmRecords) { var eliminationCtx = new EliminationCollector2D_Rectangular.EliminateContext(); eliminationCtx.container = container; eliminationCtx.extensionRules = extensionRules; eliminationCtx.sandbox = new bool[container.Height, container.Width]; eliminationCtx.records = lmRecords; EliminationCollector2D_Rectangular.CollectElimination(eliminationCtx); return(eliminationCtx.sandbox); }
public void Init(Container2D_Rectangular container, ViewLayout2DR layout) { this.layout = layout; cells = new ViewCell[container.Height, container.Width]; container.ForeachSlot((x, y, s) => { InsertCell(s.slotAttribute, new Pos2D(x, y)); }); if (drawCoordinate) { DrawCoordinates(container); } }
public void Init(Container2D_Rectangular container, ViewLayout2DR layout) { this.layout = layout; cells = new ViewCell[container.Height,container.Width]; container.ForeachSlot((x, y, s)=>{ InsertCell(s.slotAttribute, new Pos2D(x, y)); }); if (drawCoordinate) { DrawCoordinates(container); } }
private List <PLMRecord2D_Retangular> SeekContainerPLM(Container2D_Rectangular container) { var seekCtx = new PLMSeeker2D_Retangular.SeekContext(); seekCtx.container = container; seekCtx.matchRules = matchRules; seekCtx.operationRules = operationRules; seekCtx.result = new List <PLMRecord2D_Retangular>(); PLMSeeker2D_Retangular.Seek(seekCtx); var ret = seekCtx.result; return(ret); }
void DrawCoordinates(Container2D_Rectangular container) { for (int y = 0; y < container.Height; y++) { for (int x = 0; x < container.Width; x++) { var tm = GameObject.Instantiate<TextMesh>(pfbText); tm.gameObject.SetActive(true); tm.text = "[" + x + "," + y + "]"; var pos = layout.Logic2View(new Pos2D(x, y)); tm.transform.SetParent(textRoot.transform, new Vector3(pos.x, pos.y, -1f), Vector3.one); } } }
void DrawCoordinates(Container2D_Rectangular container) { for (int y = 0; y < container.Height; y++) { for (int x = 0; x < container.Width; x++) { var tm = GameObject.Instantiate <TextMesh>(pfbText); tm.gameObject.SetActive(true); tm.text = "[" + x + "," + y + "]"; var pos = layout.Logic2View(new Pos2D(x, y)); tm.transform.SetParent(textRoot.transform, new Vector3(pos.x, pos.y, -1f), Vector3.one); } } }
private List <PLMRecord2D_Retangular> MakeContainerPlayable(Container2D_Rectangular container) { var records = SeekContainerPLM(container); if (records.Count >= minimalPlayablePLM) { return(records); } else { container.RecreateSubjects(true); MakeContainerStable(container); return(MakeContainerPlayable(container)); } }
private void MakeContainerStable(Container2D_Rectangular container) { var lmRecords = SeekContainerLM(container); if (lmRecords.Count <= 0) { return; } var sandbox = CollectContainerEliminate(container, lmRecords); container.ForeachSlot((x, y, slot) => { if (sandbox[y, x]) { container.ClearSlot(x, y); container.FillSlot(x, y); } }); MakeContainerStable(container); }
private static bool JudgeOperable(SlotTrait matchingTrait, Container2D_Rectangular container, int xMask, int yMask, int xInMask, int yInMask, RuleMatchBasic2D_Rectangular match, RuleOperation2D_Rectangular operation, bool inverse) { int xRelative = inverse ? -operation.xRelative : operation.xRelative; int yRelative = inverse ? -operation.yRelative : operation.yRelative; int xTouch = xInMask + xRelative; int yTouch = yInMask + yRelative; if (yTouch >= 0 && yTouch < match.maskHeight && xTouch >= 0 && xTouch < match.maskWidth && match.PeekMask(xTouch, yTouch)) { return(false); } var sniffX = xMask + xInMask + xRelative; var sniffY = yMask + yInMask + yRelative; if (!container.IsLegalPosition(sniffX, sniffY)) { return(false); } var sniff = container.GetSlot(sniffX, sniffY); if (!sniff.IsTarget) { return(false); } return(matchingTrait.AbsoluteEqual(sniff.slotAttribute.trait)); }
public abstract RefillFlowRecord Apply(Container2D_Rectangular container);
private List<Pos2D> CollectRefillEnds(Container2D_Rectangular container, FillInfo[,] fillInfoMap) { var slots = container.WrapperRect; var ret = new List<Pos2D>(); container.ForeachSlot((x, y, slot)=>{ if (null != slot) return; if (fillInfoMap[y, x].IsOnSpot) return; foreach (var t in surroundingOffsets){ if (!container.IsLegalPosition(x + t.item1, y + t.item2)) continue; if (null != slots[y + t.item2, x + t.item1]) continue; var fi = fillInfoMap[y + t.item2, x + t.item1]; if (!fi.IsOnSpot && fi.ancestorPos.x == x && fi.ancestorPos.y == y) { return; } } ret.Add(new Pos2D(x, y)); }); return ret; }
// Do nothing public override RefillFlowRecord Apply(Container2D_Rectangular container) { throw new NotImplementedException(); }
public abstract bool Apply(Container2D_Rectangular container, LMRecord2D_Retangular matchRecord, List<Pos2D> results);
// Do nothing public override RefillFlowRecord Apply (Container2D_Rectangular container) { throw new NotImplementedException(); }
private static bool DryRun(PlayableScheme scheme, out string reason) { reason = ""; if (scheme.canvasConfig is CanvasConfig2DR) { var container = new Container2D_Rectangular(scheme.canvasConfig as CanvasConfig2DR, scheme.slotConfig); container.InitBlocks(); var count1 = 0; var count2 = 0; for (int i = 0; i < 20; i++) { container.RecreateSubjects(true); var ctx1 = new LMSeeker2D_Retangular.SeekContext(); ctx1.container = container; ctx1.matchRules = scheme.matchRules.SchemeStyleMap<RuleMatchBasic, RuleMatchBasic2D_Rectangular>((r)=>{ var raw = r as RuleMatchBasic2D_Rectangular; var ret = new RuleMatchBasic2D_Rectangular(); ret.mask = raw.mask; ret.maskWidth = raw.maskWidth; ret.maskHeight = raw.maskHeight; ret.Compile(); return ret; }).ToArray(); ctx1.result = new List<LMRecord2D_Retangular>(); LMSeeker2D_Retangular.Seek(ctx1); if (ctx1.result.Count > 0) { count1++; } var ctx2 = new PLMSeeker2D_Retangular.SeekContext(); ctx2.container = container; ctx2.matchRules = scheme.matchRules.SchemeStyleMap<RuleMatchBasic, RuleMatchBasic2D_Rectangular>((r)=>{ var raw = r as RuleMatchBasic2D_Rectangular; var ret = new RuleMatchBasic2D_Rectangular(); ret.mask = raw.mask; ret.maskWidth = raw.maskWidth; ret.maskHeight = raw.maskHeight; ret.Compile(); return ret; }).ToArray(); ctx2.operationRules = scheme.operationRules.SchemeStyleMap<RuleOperation, RuleOperation2D_Rectangular>((r)=>{ return r as RuleOperation2D_Rectangular; }).ToArray(); ctx2.result = new List<PLMRecord2D_Retangular>(); PLMSeeker2D_Retangular.Seek(ctx2); if (ctx2.result.Count >= scheme.minimalPlayablePLM) { count2++; } } if (count1 < 2 || count2 < 2) { reason = "Scheme is NOT playable!"; return false; } return true; } throw new NotImplementedException(); }
private static bool DryRun(PlayableScheme scheme, out string reason) { reason = ""; if (scheme.canvasConfig is CanvasConfig2DR) { var container = new Container2D_Rectangular(scheme.canvasConfig as CanvasConfig2DR, scheme.slotConfig); container.InitBlocks(); var count1 = 0; var count2 = 0; for (int i = 0; i < 20; i++) { container.RecreateSubjects(true); var ctx1 = new LMSeeker2D_Retangular.SeekContext(); ctx1.container = container; ctx1.matchRules = scheme.matchRules.SchemeStyleMap <RuleMatchBasic, RuleMatchBasic2D_Rectangular>((r) => { var raw = r as RuleMatchBasic2D_Rectangular; var ret = new RuleMatchBasic2D_Rectangular(); ret.mask = raw.mask; ret.maskWidth = raw.maskWidth; ret.maskHeight = raw.maskHeight; ret.Compile(); return(ret); }).ToArray(); ctx1.result = new List <LMRecord2D_Retangular>(); LMSeeker2D_Retangular.Seek(ctx1); if (ctx1.result.Count > 0) { count1++; } var ctx2 = new PLMSeeker2D_Retangular.SeekContext(); ctx2.container = container; ctx2.matchRules = scheme.matchRules.SchemeStyleMap <RuleMatchBasic, RuleMatchBasic2D_Rectangular>((r) => { var raw = r as RuleMatchBasic2D_Rectangular; var ret = new RuleMatchBasic2D_Rectangular(); ret.mask = raw.mask; ret.maskWidth = raw.maskWidth; ret.maskHeight = raw.maskHeight; ret.Compile(); return(ret); }).ToArray(); ctx2.operationRules = scheme.operationRules.SchemeStyleMap <RuleOperation, RuleOperation2D_Rectangular>((r) => { return(r as RuleOperation2D_Rectangular); }).ToArray(); ctx2.result = new List <PLMRecord2D_Retangular>(); PLMSeeker2D_Retangular.Seek(ctx2); if (ctx2.result.Count >= scheme.minimalPlayablePLM) { count2++; } } if (count1 < 2 || count2 < 2) { reason = "Scheme is NOT playable!"; return(false); } return(true); } throw new NotImplementedException(); }
private List<RefillFlowRecord.Path> CollectFillPathList(Container2D_Rectangular container, FillInfo[,] fillInfos) { var ret = new List<RefillFlowRecord.Path>(); for (int x = 0; x < container.Width; x++) { var sub = CollectFromPos(container, fillInfos, x, container.Height - 1); if (null == sub) continue; sub.Sort((lhr, rhr)=>{ return (lhr.movements.Count > rhr.movements.Count) ? -1 : 1; }); var len = sub.Count; for (int i = 0; i < len; i++) { var index = i + 1; var s = sub[i]; s.src = new Pos2D(x, container.Height - 1 + index); for (int j = 1; j <= index; j++) { s.movements.Add(new Pos2D(x, container.Height - 1 + j)); } s.movements.Reverse(); } ret.AddRange(sub); } return ret; }
public abstract bool Apply(Container2D_Rectangular container, LMRecord2D_Retangular matchRecord, List <Pos2D> results);
private RefillFlowRecord DoApply(Container2D_Rectangular container, FillInfo[,] fillInfoMap) { var ret = new RefillFlowRecord(); var slots = container.WrapperRect; container.ForeachSlot((x, y, slot)=>{ if (null != slot) return; var fi = fillInfoMap[y, x]; if (fi.IsOnSpot){ ret.OnSpotList.Add(new Pos2D(x, y)); } }); var ends = CollectRefillEnds(container, fillInfoMap); var dir = new Dictionary<int, Tuple<SlotWrapper2D, int>>(); foreach (var e in ends) { var pos = fillInfoMap[e.y, e.x].ancestorPos; int inverseDepth = 0; while (container.IsLegalPosition(pos.x, pos.y)) { var s = slots[pos.y, pos.x]; if (null != s) { inverseDepth++; if (!dir.ContainsKey(s.Trait)) { dir.Add(s.Trait, new Tuple<SlotWrapper2D, int>(s, inverseDepth)); } else if (dir[s.Trait].item2 < inverseDepth) { dir[s.Trait].item2 = inverseDepth; } } pos = fillInfoMap[pos.y, pos.x].ancestorPos; } } var list = new List<Tuple<SlotWrapper2D, int>>(); foreach (var kvp in dir) { list.Add(kvp.Value); } list.Sort((lhr, rhr)=>{ return (lhr.item2 < rhr.item2) ? -1 : 1; }); foreach (var t in list) { var src = t.item1.pos; var moveTo = DepthFirstSearch(slots, fillInfoMap, src.x, src.y); var dst = moveTo.item1; var path = new RefillFlowRecord.Path(); path.src = src.Clone(); path.dst = dst.Clone(); container.SwapSlot(src.x, src.y, dst.x, dst.y); var cur = path.dst; do { path.movements.Add(cur); cur = fillInfoMap[cur.y, cur.x].ancestorPos; } while (cur != path.src); path.movements.Add(path.src); path.movements.Reverse(); ret.NonFillMovements.Add(path); } ret.FillMovements = CollectFillPathList(container, fillInfoMap); return ret; }
private List<RefillFlowRecord.Path> CollectFromPos(Container2D_Rectangular container, FillInfo[,] fillInfos, int fromX, int fromY) { if (!container.IsLegalPosition(fromX, fromY) || null != container.GetSlot(fromX, fromY)) return null; var fi = fillInfos[fromY, fromX]; var ret = new List<RefillFlowRecord.Path>(); var selfPos = new Pos2D(fromX, fromY); var self = new RefillFlowRecord.Path(); self.dst = selfPos; ret.Add(self); foreach (var child in fi.childrenPos) { var sub = CollectFromPos(container, fillInfos, child.x, child.y); if (null == sub) continue; ret.AddRange(sub); } foreach (var r in ret) { r.src = selfPos; r.movements.Add(selfPos); } return ret; }
private FillInfo[,] GenerateRefillTrendMap(Container2D_Rectangular container) { var ret = new FillInfo[container.Height, container.Width]; var slots = container.WrapperRect; Action<int, int, List<SlotWrapper2D>> picker = (x, y, list)=>{ if (x < 0 || x >= container.Width) return; if (y < 0 || y >= container.Height) return; if (null != slots[y, x].slotAttribute && slots[y, x].slotAttribute.category == SlotAttribute.Category.INSULATOR) { return; } list.Add(slots[y, x]); }; Action<int, int> exitMarker = (x, y)=>{ if (null == ret[y, x]) { ret[y, x] = new FillInfo(); ret[y, x].ancestorPos = new Pos2D(x, y + 1); } }; container.ForeachSlot((x, y, slot)=>{ if (null != ret[y, x]) return; if (null != slot.slotAttribute && slot.slotAttribute.category == SlotAttribute.Category.INSULATOR) return; var ctx = new AStar.Context<SlotWrapper2D>(); ctx.start = slots[y, x]; ctx.procTrait = (s)=>{ return s.Trait; }; ctx.procWeight = (SlotWrapper2D from, SlotWrapper2D to)=>{ foreach (var t in surroundingOffsets){ if (to.pos.x == from.pos.x + t.item1 && to.pos.y == from.pos.y + t.item2){ return t.item3; } } throw new NotImplementedException(); }; ctx.procTermination = (SlotWrapper2D s)=>{ return s.pos.y == container.Height - 1; }; ctx.procDistanceEstimator = (SlotWrapper2D s)=>{ return (container.Height - 1 - s.pos.y) * 1.0001f; }; ctx.procAdjacencies = (SlotWrapper2D s)=>{ var list = new List<SlotWrapper2D>(); foreach (var t in surroundingOffsets){ picker.Invoke(s.pos.x + t.item1, s.pos.y + t.item2, list); } return list; }; if (AStar.Evaluate(ctx)) { var result = ctx.path; if (result.Count <= 0) { exitMarker.Invoke(x, y); } else { result.Reverse(); for (int i = 0, len = result.Count - 1; i < len; i++) { if (null != ret[result[i].pos.y, result[i].pos.x]) continue; var t = new FillInfo(); t.ancestorPos = new Pos2D(result[i + 1].pos.x, result[i + 1].pos.y); ret[result[i].pos.y, result[i].pos.x] = t; } exitMarker(result[result.Count - 1].pos.x, result[result.Count - 1].pos.y); } } else { ret[y, x] = new FillInfo(); } }); for (int y = 0; y < container.Height; y++) { for (int x = 0; x < container.Width; x++) { var fi = ret[y, x]; if (null == fi) continue; if (fi.IsOnSpot) continue; fi.childrenPos = new List<Pos2D>(); foreach (var t in surroundingOffsets) { var sx = x + t.item1; var sy = y + t.item2; if (!container.IsLegalPosition(sx, sy)) { continue; } var slot = container.GetSlot(sx, sy); if (null != slot && null != slot.slotAttribute && slot.slotAttribute.category == SlotAttribute.Category.INSULATOR) { continue; } var touch = ret[sy, sx]; if (null != touch.ancestorPos && touch.ancestorPos.x == x && touch.ancestorPos.y == y) { fi.childrenPos.Add(new Pos2D(sx, sy)); } } } } return ret; }
private RefillFlowRecord DoApply(Container2D_Rectangular container, FillInfo[,] fillInfoMap) { var ret = new RefillFlowRecord(); var slots = container.WrapperRect; container.ForeachSlot((x, y, slot) => { if (null != slot) { return; } var fi = fillInfoMap[y, x]; if (fi.IsOnSpot) { ret.OnSpotList.Add(new Pos2D(x, y)); } }); var ends = CollectRefillEnds(container, fillInfoMap); var dir = new Dictionary <int, Tuple <SlotWrapper2D, int> >(); foreach (var e in ends) { var pos = fillInfoMap[e.y, e.x].ancestorPos; int inverseDepth = 0; while (container.IsLegalPosition(pos.x, pos.y)) { var s = slots[pos.y, pos.x]; if (null != s) { inverseDepth++; if (!dir.ContainsKey(s.Trait)) { dir.Add(s.Trait, new Tuple <SlotWrapper2D, int>(s, inverseDepth)); } else if (dir[s.Trait].item2 < inverseDepth) { dir[s.Trait].item2 = inverseDepth; } } pos = fillInfoMap[pos.y, pos.x].ancestorPos; } } var list = new List <Tuple <SlotWrapper2D, int> >(); foreach (var kvp in dir) { list.Add(kvp.Value); } list.Sort((lhr, rhr) => { return((lhr.item2 < rhr.item2) ? -1 : 1); }); foreach (var t in list) { var src = t.item1.pos; var moveTo = DepthFirstSearch(slots, fillInfoMap, src.x, src.y); var dst = moveTo.item1; var path = new RefillFlowRecord.Path(); path.src = src.Clone(); path.dst = dst.Clone(); container.SwapSlot(src.x, src.y, dst.x, dst.y); var cur = path.dst; do { path.movements.Add(cur); cur = fillInfoMap[cur.y, cur.x].ancestorPos; } while (cur != path.src); path.movements.Add(path.src); path.movements.Reverse(); ret.NonFillMovements.Add(path); } ret.FillMovements = CollectFillPathList(container, fillInfoMap); return(ret); }
private FillInfo[,] GenerateRefillTrendMap(Container2D_Rectangular container) { var ret = new FillInfo[container.Height, container.Width]; var slots = container.WrapperRect; Action <int, int, List <SlotWrapper2D> > picker = (x, y, list) => { if (x < 0 || x >= container.Width) { return; } if (y < 0 || y >= container.Height) { return; } if (null != slots[y, x].slotAttribute && slots[y, x].slotAttribute.category == SlotAttribute.Category.INSULATOR) { return; } list.Add(slots[y, x]); }; Action <int, int> exitMarker = (x, y) => { if (null == ret[y, x]) { ret[y, x] = new FillInfo(); ret[y, x].ancestorPos = new Pos2D(x, y + 1); } }; container.ForeachSlot((x, y, slot) => { if (null != ret[y, x]) { return; } if (null != slot.slotAttribute && slot.slotAttribute.category == SlotAttribute.Category.INSULATOR) { return; } var ctx = new AStar.Context <SlotWrapper2D>(); ctx.start = slots[y, x]; ctx.procTrait = (s) => { return(s.Trait); }; ctx.procWeight = (SlotWrapper2D from, SlotWrapper2D to) => { foreach (var t in surroundingOffsets) { if (to.pos.x == from.pos.x + t.item1 && to.pos.y == from.pos.y + t.item2) { return(t.item3); } } throw new NotImplementedException(); }; ctx.procTermination = (SlotWrapper2D s) => { return(s.pos.y == container.Height - 1); }; ctx.procDistanceEstimator = (SlotWrapper2D s) => { return((container.Height - 1 - s.pos.y) * 1.0001f); }; ctx.procAdjacencies = (SlotWrapper2D s) => { var list = new List <SlotWrapper2D>(); foreach (var t in surroundingOffsets) { picker.Invoke(s.pos.x + t.item1, s.pos.y + t.item2, list); } return(list); }; if (AStar.Evaluate(ctx)) { var result = ctx.path; if (result.Count <= 0) { exitMarker.Invoke(x, y); } else { result.Reverse(); for (int i = 0, len = result.Count - 1; i < len; i++) { if (null != ret[result[i].pos.y, result[i].pos.x]) { continue; } var t = new FillInfo(); t.ancestorPos = new Pos2D(result[i + 1].pos.x, result[i + 1].pos.y); ret[result[i].pos.y, result[i].pos.x] = t; } exitMarker(result[result.Count - 1].pos.x, result[result.Count - 1].pos.y); } } else { ret[y, x] = new FillInfo(); } }); for (int y = 0; y < container.Height; y++) { for (int x = 0; x < container.Width; x++) { var fi = ret[y, x]; if (null == fi) { continue; } if (fi.IsOnSpot) { continue; } fi.childrenPos = new List <Pos2D>(); foreach (var t in surroundingOffsets) { var sx = x + t.item1; var sy = y + t.item2; if (!container.IsLegalPosition(sx, sy)) { continue; } var slot = container.GetSlot(sx, sy); if (null != slot && null != slot.slotAttribute && slot.slotAttribute.category == SlotAttribute.Category.INSULATOR) { continue; } var touch = ret[sy, sx]; if (null != touch.ancestorPos && touch.ancestorPos.x == x && touch.ancestorPos.y == y) { fi.childrenPos.Add(new Pos2D(sx, sy)); } } } } return(ret); }