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 <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); }
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)); }
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 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<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; }
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); }
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); }