public List <ICommand> MakeTrace(TModel src, TModel model) { if (src.NumFilled != 0) { return(null); } EHarmonics curHarmonics = EHarmonics.Low; List <ICommand> result = new List <ICommand>(); TCoord current = new TCoord(); TBetterCubeTraverse betterCureTraverse = new TBetterCubeTraverse(model); int iteration = 0; while (iteration == 0 || !current.IsAtStart()) { TCoord next = betterCureTraverse.Next(model); StraightMove move = new StraightMove(); move.Diff = betterCureTraverse.GetDirection(); result.Add(move); if (next.Y > 0 && model[next.X, next.Y - 1, next.Z] > 0) { if (curHarmonics == EHarmonics.Low) { result.Add(new Flip()); curHarmonics = EHarmonics.High; } Fill fill = new Fill(); fill.Diff.Dy = -1; result.Add(fill); } else if (curHarmonics == EHarmonics.High) { result.Add(new Flip()); curHarmonics = EHarmonics.Low; } current = next; ++iteration; } if (curHarmonics == EHarmonics.High) { result.Add(new Flip()); } result.Add(new Halt()); return(result); }
public void Update(TCoord coord, TBot bot) { if (Coords == null) { return; } if (Coords.Contains(coord)) { throw new InvalidStateException($"bot {bot.Bid} interferes with other bots at {coord}"); } Coords.Add(coord); }
private static void TraceMove(TCoord botCoord, StraightMove m, Action <TCoord> action) { var cur = botCoord; var dst = cur; dst.Apply(m.Diff); var step = new CoordDiff(Math.Sign(m.Diff.Dx), Math.Sign(m.Diff.Dy), Math.Sign(m.Diff.Dz)); do { cur.Apply(step); action(cur); }while (!cur.Equals(dst)); }
private bool IsGrounded(TCoord coord, HashSet <TCoord> visited) { if (visited.Contains(coord) || !coord.IsValid(Model.R) || !this[coord]) { return(false); } visited.Add(coord); if (coord.Y == 0) { return(true); } return(coord.ManhattenNeighbours().Any(x => IsGrounded(x, visited))); }
List <Tuple <TCoord, CoordDiff> > GenerateCuts(int lineIndex, List <int> segmentsMap, int layerIndex) { List <Tuple <TCoord, CoordDiff> > res = new List <Tuple <TCoord, CoordDiff> >(); for (int j = 1; j < segmentsMap.Count; j += 2) { var start = segmentsMap[j - 1]; var end = segmentsMap[j]; var pos = new TCoord(lineIndex, start, layerIndex); var direction = new CoordDiff(0, end, 0); res.Add(Tuple.Create <TCoord, CoordDiff>(pos, direction)); } return(res); }
public static TCoord RectangleTraverse(List <ICommand> commands, int minX, int minZ, int maxX, int maxZ, int y, TModel model) { TCoord current; current.X = minX; current.Y = y; current.Z = minZ; while (current.X < maxX || current.Z < maxZ) { if (current.X < maxX) { TCoord next = current; next.X = maxX; AddTransition(commands, current, next, model, true); current = next; } if (current.Z < maxZ) { TCoord next1 = current; next1.Z += 1; TCoord next2 = next1; next2.X = minX; AddTransition(commands, current, next1, model, true); AddTransition(commands, next1, next2, model, true); current = next2; } if (current.Z < maxZ) { TCoord next = current; next.Z += 1; AddTransition(commands, current, next, model, true); current = next; } } return(current); }
public List <ICommand> RecreatePath(TCoord src) { var path = new List <ICommand>(); var cur = Coord; while (!cur.Equals(src)) { var from = cells[cur.X, cur.Y, cur.Z].From; path.Add( new StraightMove { Diff = cur.Diff(from) }); cur = from; } path.Reverse(); return(path); }
List <ICommand> FillLine(TBot bot, CoordDiff direction, CoordDiff botOffset) { TCoord x = bot.Coord; List <ICommand> res = new List <ICommand>(); CoordDiff fillOffset = new CoordDiff(-botOffset.Dx, -botOffset.Dy, -botOffset.Dz); if (direction.Dx != 0) { int dif = direction.Dx < 0 ? -1 : 1; while (true) { Fill fc = new Fill(); fc.Diff = fillOffset; res.Add(fc); if (bot.Coord.X == x.X + direction.Dx + botOffset.Dx) { break; } StraightMove move = new StraightMove(); move.Diff = new CoordDiff(dif, 0, 0); res.Add(move); } } if (direction.Dy != 0) { int dif = direction.Dy < 0 ? -1 : 1; while (true) { Fill fc = new Fill(); fc.Diff = fillOffset; res.Add(fc); if (bot.Coord.Y == x.Y + direction.Dy + botOffset.Dy) { break; } StraightMove move = new StraightMove(); move.Diff = new CoordDiff(0, dif, 0); res.Add(move); } } if (direction.Dz != 0) { int dif = direction.Dz < 0 ? -1 : 1; while (true) { Fill fc = new Fill(); fc.Diff = fillOffset; res.Add(fc); if (bot.Coord.Z == x.Z + direction.Dz + botOffset.Dz) { break; } StraightMove move = new StraightMove(); move.Diff = new CoordDiff(0, 0, dif); res.Add(move); } } return(res); }
public List <ICommand> MakeTrace(TModel src, TModel model) { if (src.NumFilled != 0) { return(null); } ICommand modifyCommand = new Fill(); ((Fill)modifyCommand).Diff.Dy = -1; if (model.Name.Contains("FD")) { modifyCommand = new Void(); ((Void)modifyCommand).Diff.Dy = -1; } // TState state = new TState(model); var result = new List <ICommand>(); result.Add(new Flip()); var current = new TCoord(); var dumpCureTraverse = new TDumpCubeTraverse(model); var iteration = 0; while ((iteration == 0) || !current.IsAtStart()) { if (iteration == 295) { int a = 0; } var next = model.Name.Contains("FA") ? dumpCureTraverse.Next() : dumpCureTraverse.NextDestroy(); var move = new StraightMove(); move.Diff = dumpCureTraverse.GetDirection(); result.Add(move); // { // List<ICommand> ss = new List<ICommand>(); // ss.Add(move); // TCommandsReader cr = new TCommandsReader(ss); // state.Step(cr); // } if ((next.Y > 0) && (model[next.X, next.Y - 1, next.Z] > 0)) { result.Add(modifyCommand); // { // List<ICommand> ss = new List<ICommand>(); // ss.Add(move); // TCommandsReader cr = new TCommandsReader(ss); // state.Step(cr); // } } current = next; ++iteration; } result.Add(new Flip()); result.Add(new Halt()); return(result); }
int Depth(TCoord c) => depth_[c.X, c.Y, c.Z];
private bool IsFree(TCoord coord) => (state.M(coord) == 0) && !interferedCells.Contains(coord);
public List <ICommand> MakeTrace(TModel src, TModel model) { if (src.NumFilled != 0) { return(null); } List <ICommand> result = new List <ICommand>(); int maxY = 0; for (var x = 0; x < model.R; ++x) { for (var y = 0; y < model.R; ++y) { for (var z = 0; z < model.R; ++z) { if (model[x, y, z] > 0) { maxY = Math.Max(maxY, y); } } } } TCoord current; current.X = 0; current.Y = 0; current.Z = 0; for (int y = 0; y <= maxY; ++y) { int minX = model.R; int minZ = model.R; int maxX = 0; int maxZ = 0; for (var x = 0; x < model.R; ++x) { for (var z = 0; z < model.R; ++z) { if (model[x, y, z] > 0) { minX = Math.Min(minX, x); minZ = Math.Min(minZ, z); maxX = Math.Max(maxX, x); maxZ = Math.Max(maxZ, z); } } } TCoord startPoint; startPoint.X = minX; startPoint.Y = y; startPoint.Z = minZ; AddTransition(result, current, startPoint, model, false); current = RectangleTraverse(result, minX, minZ, maxX, maxZ, y, model); TCoord next = current; ++next.Y; AddTransition(result, current, next, model, false); } { TCoord next1 = current; next1.X = 0; next1.Z = 0; AddTransition(result, current, next1, model, false); TCoord next2 = next1; next2.Y = 0; AddTransition(result, next1, next2, model, false); } result.Add(new Halt()); return(result); }
List <ICommand> MoveToPosition(TBot bot, TCoord to) { return(MoveToPosition(bot, to.X, to.Y, to.Z)); }
public int M(TCoord c) => Matrix[c.X, c.Y, c.Z];
private bool this[TCoord c] => c.IsValid(Model.R) && Matrix[c.X, c.Y, c.Z] > 0;
public IEnumerable <CoordWithPath> EnumerateReachablePaths(TCoord src, int maxDepth, int maxSteps) { ++curGeneration; // THIS IS VERY DUMB ALGO. BECAUSE I'M TOO STUPID TO DO BETTER // TODO: support LMoves queue.Clear(); queue.Enqueue(src); cells[src.X, src.Y, src.Z] = new CellData() { Cost = 0, Generation = curGeneration }; yield return(new CoordWithPath(src, cells)); int steps = 0; while (queue.Count != 0) { var cur = queue.Dequeue(); // TODO: smarter precompute? var(minDx, maxDx) = FindRange(1, 0, 0); var(minDy, maxDy) = FindRange(0, 1, 0); var(minDz, maxDz) = FindRange(0, 0, 1); var c = default(CoordWithPath); // we visit (and yield) closes nodes first for (var dx = minDx; dx <= maxDx; ++dx) { if (TryVisit(Math.Abs(dx), dx, 0, 0)) { yield return(c); if (++steps >= maxSteps) { yield break; } queue.Enqueue(c.Coord); } } for (var dy = minDy; dy <= maxDy; ++dy) { if (TryVisit(Math.Abs(dy), 0, dy, 0)) { yield return(c); if (++steps >= maxSteps) { yield break; } queue.Enqueue(c.Coord); } } for (var dz = minDz; dz <= maxDz; ++dz) { if (TryVisit(Math.Abs(dz), 0, 0, dz)) { yield return(c); if (++steps >= maxSteps) { yield break; } queue.Enqueue(c.Coord); } } (int, int) FindRange(int dx, int dy, int dz) { var min = 0; var minCoord = cur; do { minCoord.Apply(new CoordDiff(-1 * dx, -1 * dy, -1 * dz)); --min; }while ((min >= -Constants.StraightMoveCorrection) && minCoord.IsValid(model.R) && IsFree(minCoord, maxDepth)); var max = 0; var maxCoord = cur; do { maxCoord.Apply(new CoordDiff(dx, dy, dz)); ++max; }while ((max <= Constants.StraightMoveCorrection) && maxCoord.IsValid(model.R) && IsFree(maxCoord, maxDepth)); return(min + 1, max - 1); } bool TryVisit(int dist, int dx, int dy, int dz) { var next = new TCoord(cur.X + dx, cur.Y + dy, cur.Z + dz); var curCost = cells[cur.X, cur.Y, cur.Z].Cost; if (next.IsValid(model.R) && !cells[next.X, next.Y, next.Z].Visited(curGeneration)) { // TODO: add energy maintainance into cost cells[next.X, next.Y, next.Z] = new CellData() { From = cur, Cost = curCost + (2 * dist), Generation = curGeneration, }; c = new CoordWithPath(next, cells); return(true); // if (!IsFree(next)) throw new Exception("WTF"); } return(false); } } }
public List <ICommand> MakeReassemblyTrace(TModel srcModel, TModel tgtModel) { Fill doFill = new Fill(); doFill.Diff.Dy = -1; Void doVoid = new Void(); doVoid.Diff.Dy = -1; var result = new List <ICommand>(); result.Add(new Flip()); var current = new TCoord(); var dumpCureTraverse = new TDumpCubeTraverse(srcModel, tgtModel); TState state = new TState(srcModel); List <ICommand> ss = new List <ICommand>(); var iteration = 0; while ((iteration == 0) || !current.IsAtStart()) { var next = dumpCureTraverse.Next(); if (srcModel[next] > 0) { Void curVoid = new Void(); curVoid.Diff = dumpCureTraverse.GetDirection(); result.Add(curVoid); { if (ss.Count == 0) { ss.Add(curVoid); } else { ss[0] = curVoid; } ss.Add(curVoid); TCommandsReader cr = new TCommandsReader(ss); state.Step(cr); } } var move = new StraightMove(); move.Diff = dumpCureTraverse.GetDirection(); result.Add(move); { if (ss.Count == 0) { ss.Add(move); } else { ss[0] = move; } TCommandsReader cr = new TCommandsReader(ss); state.Step(cr); } if ((next.Y > 0) && (tgtModel[next.X, next.Y - 1, next.Z] > 0) && state.Matrix[next.X, next.Y - 1, next.Z] == 0) { result.Add(doFill); { if (ss.Count == 0) { ss.Add(doFill); } else { ss[0] = doFill; } TCommandsReader cr = new TCommandsReader(ss); state.Step(cr); } } if ((next.Y > 0) && (tgtModel[next.X, next.Y - 1, next.Z] == 0) && state.Matrix[next.X, next.Y - 1, next.Z] > 0) { result.Add(doVoid); { if (ss.Count == 0) { ss.Add(doVoid); } else { ss[0] = doVoid; } TCommandsReader cr = new TCommandsReader(ss); state.Step(cr); } } current = next; ++iteration; } result.Add(new Flip()); result.Add(new Halt()); return(result); }
public CoordWithPath(TCoord coord, CellData[,,] cells) { Coord = coord; this.cells = cells; }
private bool IsFree(TCoord coord, int maxDepth) => (state.M(coord) == 0) && // depth[coord.X, coord.Y, coord.Z] < maxDepth && !interferedCells.Contains(coord);
public static void AddTransition(List <ICommand> commands, TCoord current, TCoord target, TModel model, bool doFill) { Fill fill = new Fill(); fill.Diff.Dx = 0; fill.Diff.Dy = 0; fill.Diff.Dz = 0; if (model[current.X, current.Y, current.Z] > 0 && doFill) { commands.Add(fill); } int xDiff = target.X > current.X ? 1 : -1; int yDiff = target.Y > current.Y ? 1 : -1; int zDiff = target.Z > current.Z ? 1 : -1; while (Math.Abs(current.X - target.X) > 1 || Math.Abs(current.Y - target.Y) > 1 || Math.Abs(current.Z - target.Z) > 1) { LMove lMove = new LMove(); lMove.Diff1.Dx = Math.Abs(current.X - target.X) > 1 ? xDiff : 0; lMove.Diff1.Dy = Math.Abs(current.Y - target.Y) > 1 ? yDiff : 0; lMove.Diff1.Dz = Math.Abs(current.Z - target.Z) > 1 ? zDiff : 0; lMove.Diff2.Dx = Math.Abs(current.X - target.X) > 0 ? xDiff : 0; lMove.Diff2.Dy = Math.Abs(current.Y - target.Y) > 0 ? yDiff : 0; lMove.Diff2.Dz = Math.Abs(current.Z - target.Z) > 0 ? zDiff : 0; commands.Add(lMove); current.X += lMove.Diff1.Dx + lMove.Diff2.Dx; current.Y += lMove.Diff1.Dy + lMove.Diff2.Dy; current.Z += lMove.Diff1.Dz + lMove.Diff2.Dz; if (model[current.X, current.Y, current.Z] > 0 && doFill) { commands.Add(fill); } } while (Math.Abs(current.X - target.X) > 0 || Math.Abs(current.Y - target.Y) > 0 || Math.Abs(current.Z - target.Z) > 0) { StraightMove sMove = new StraightMove(); sMove.Diff.Dx = Math.Abs(current.X - target.X) > 0 ? xDiff : 0; sMove.Diff.Dy = Math.Abs(current.Y - target.Y) > 0 ? yDiff : 0; sMove.Diff.Dz = Math.Abs(current.Z - target.Z) > 0 ? zDiff : 0; commands.Add(sMove); current.X += sMove.Diff.Dx; current.Y += sMove.Diff.Dy; current.Z += sMove.Diff.Dz; if (model[current.X, current.Y, current.Z] > 0 && doFill) { commands.Add(fill); } } }