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);
                }
            }
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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);
        }