private static bool TryApplyInstruction(ref SimpleBoard board, Piece piece, Instruction inst, out Piece result, NativeArray <int4x4> pieceShapes) { switch (inst) { case Left: result = piece.WithOffset(-1, 0); return(!board.CollidesFast(result, pieceShapes)); case Right: result = piece.WithOffset(1, 0); return(!board.CollidesFast(result, pieceShapes)); case Cw: var t = SRSNoAlloc.TryRotate(piece, ref board, true, pieceShapes, out var r1, out var r1Result); result = piece.kind == T?r1Result.WithTSpinStatus(board.CheckTSpin(r1Result, r1)) : r1Result; return(t); case Ccw: var s = SRSNoAlloc.TryRotate(piece, ref board, false, pieceShapes, out var r2, out var r2Result); result = piece.kind == T?r2Result.WithTSpinStatus(board.CheckTSpin(r2Result, r2)) : r2Result; return(s); case SonicDrop: var originY = piece.y; result = board.SonicDropFast(piece, pieceShapes); return(originY != result.y); default: throw new ArgumentOutOfRangeException(nameof(inst), inst, null); } }
private static void Confirm(ref SimpleBoard board, ref NativeHashMap <Piece, Move> lookup, Move mv, NativeArray <int4x4> pieceShapes) { if (!IsAboveStacking(mv.piece, 20) && !board.CollidesFast(mv.piece, pieceShapes)) { lookup.TryAdd(mv.piece, mv); } }
private static void Attempt(ref SimpleBoard board, Move move, ref NativeHashMap <Piece, bool> alreadyPassed, ref NativePriorityQueue <Move> checkQueue, Instruction instruction, int maxBoardHeight, NativeArray <int4x4> pieceShapes, bool repeat = false) { if (repeat && !(instruction == Left || instruction == Right)) { throw new ArgumentException(); } var piece = move.piece; if (!TryApplyInstruction(ref board, piece, instruction, out var result, pieceShapes)) { return; } piece = result; var t = 0; if (instruction == SonicDrop) { t += 2 * move.piece.y - result.y; } else { t = 1; } if (move.length != 0 && move.GetInstructionAt(move.length - 1) == instruction) { t += 1; } move.Append(instruction, t, result); while (repeat && !move.IsFull && TryApplyInstruction(ref board, piece, instruction, out result, pieceShapes)) { piece = result; move.Append(instruction, 2, result); } if (result.tSpin != TSpinStatus.None || !IsAboveStacking(result, maxBoardHeight)) { // We should do further checks if (alreadyPassed.TryAdd(result, true) && !move.IsFull) { var dropped = board.SonicDropFast(piece, pieceShapes); if (piece.y != dropped.y) { move.Append(SonicDrop, (piece.y - dropped.y) * 2, dropped); } checkQueue.Enqueue(move); } } }
public static NativeHashMap <Piece, Move> Generate(ref SimpleBoard board, Piece spawned, NativeArray <int4x4> pieceShapes) { var results = new NativeHashMap <Piece, Move>(200, Allocator.Temp); var passed = new NativeHashMap <Piece, bool>(100, Allocator.Temp); var checkQueue = new NativeList <Move>(100, Allocator.Temp); //todo passed.Dispose(); checkQueue.Dispose(); return(results); }
public static Move?FindPath(ref SimpleBoard board, Node node, NativeArray <int4x4> pieceShapes) { var job = new PathFindJob { board = board, holdUsed = node.holdUsed, dest = node.piece, pieceShapes = pieceShapes, success = new NativeArray <bool>(1, Allocator.TempJob), move = new NativeArray <Move>(1, Allocator.TempJob) }; job.Run(); var success = job.success[0]; var mv = job.move[0]; job.success.Dispose(); job.move.Dispose(); return(success ? mv : (Move?)null); }
public static bool TryRotate(Piece piece, ref SimpleBoard board, bool cw, NativeArray <int4x4> pieceShapes, out int rotation, out Piece rotated) { if (piece.kind == PieceKind.O) { rotation = 0; rotated = piece; return(true); } var rotatedDirection = GetRotatedDirection(piece.spin, cw); var newPiece = new Piece(piece.kind, piece.x, piece.y, rotatedDirection); if (!board.CollidesFast(newPiece, pieceShapes)) { rotation = 0; rotated = newPiece; return(true); } var key = piece.spin * 10 + rotatedDirection; var offsetTable = piece.kind == PieceKind.I ? RotationTableI[KeyToIndex(key)] : RotationTable[KeyToIndex(key)]; for (var i = 0; i < 4; i++) { newPiece = piece.WithOffset(offsetTable[i]).WithSpin(rotatedDirection); if (!board.CollidesFast(newPiece, pieceShapes)) { rotation = i + 1; rotated = newPiece; return(true); } } rotation = default; rotated = default; return(false); }
public static NativeHashMap <Piece, Move> Generate(ref SimpleBoard board, Piece spawned, NativeArray <int4x4> pieceShapes, bool holdUse) { var columns = stackalloc int[10]; var maxHeights = stackalloc byte[10]; board.GetColumns(columns, maxHeights); var lookup = new NativeHashMap <Piece, Move>(200, Allocator.Temp); var passed = new NativeHashMap <Piece, bool>(200, Allocator.Temp); var checkQueue = new NativePriorityQueue <Move>(false, 100, Allocator.Temp); var maxHeight = 0; for (var i = 0; i < 10; i++) { if (maxHeights[i] > maxHeight) { maxHeight = maxHeights[i]; } } if (maxHeight < 16) { var starts = GenerateStarts(spawned.kind, holdUse); for (var i = 0; i < starts.Length; i++) { var start = starts[i]; var originY = start.piece.y; var piece = board.SonicDropFast(start.piece, pieceShapes); start.piece = piece; Confirm(ref board, ref lookup, start, pieceShapes); var m2 = start; var dY = originY - piece.y; m2.instructions[m2.length++] = (byte)SonicDrop; m2.time += dY * 2; checkQueue.Enqueue(m2); } starts.Dispose(); } else { var p = new Piece(spawned.kind); var d = board.SonicDropFast(p, pieceShapes); var m = new Move(); m.hold = holdUse; m.piece = d; m.instructions[0] = (byte)SonicDrop; m.length = 1; m.time = 2 * (p.y - d.y); checkQueue.Enqueue(m); } while (checkQueue.TryDequeue(out var mv)) { if (!mv.IsFull) { Attempt(ref board, mv, ref passed, ref checkQueue, Left, maxHeight, pieceShapes); Attempt(ref board, mv, ref passed, ref checkQueue, Right, maxHeight, pieceShapes); if (mv.piece.kind != O) { Attempt(ref board, mv, ref passed, ref checkQueue, Cw, maxHeight, pieceShapes); Attempt(ref board, mv, ref passed, ref checkQueue, Ccw, maxHeight, pieceShapes); } Attempt(ref board, mv, ref passed, ref checkQueue, Left, maxHeight, pieceShapes, true); Attempt(ref board, mv, ref passed, ref checkQueue, Right, maxHeight, pieceShapes, true); Attempt(ref board, mv, ref passed, ref checkQueue, SonicDrop, maxHeight, pieceShapes); } //Finally add this placement(harddropped) to return array var pl = board.SonicDropFast(mv.piece, pieceShapes); var mHard = mv; mHard.piece = pl; Confirm(ref board, ref lookup, mHard, pieceShapes); } passed.Dispose(); checkQueue.Dispose(); return(lookup); }