Ejemplo n.º 1
0
    /// @copydoc IThinker.Think
    /// <seealso cref="IThinker.Think"/>
    public FutureMove Think(Board board, CancellationToken ct)
    {
        // Check how many pieces current player has
        int roundPieces  = board.PieceCount(board.Turn, PShape.Round);
        int squarePieces = board.PieceCount(board.Turn, PShape.Square);

        // Chose a random piece
        int    pieceRand = random.Next(roundPieces + squarePieces);
        PShape shape     = pieceRand < roundPieces ? PShape.Round : PShape.Square;

        // Chose a random free position
        int col;

        do
        {
            // Get a random position
            col = random.Next(board.cols);
            // Is this task to be cancelled?
            if (ct.IsCancellationRequested)
            {
                return(FutureMove.NoMove);
            }
        }while (board.IsColumnFull(col));

        // Return the random move
        return(new FutureMove(col, shape));
    }
Ejemplo n.º 2
0
		public PSolver(PShape shape1, PShape shape2, PContact[] contacts, int num) {
			s1 = shape1;
			s2 = shape2;
			b1 = s1._parent;
			b2 = s2._parent;
			fric = (float) System.Math.Sqrt(s1._fric * s2._fric);
			rest = (float) System.Math.Sqrt(s1._rest * s2._rest);
			cs = contacts;
			numContacts = num;
			for (int i = 0; i < numContacts; i++) {
				PContact c = cs[i];
				c.rel1 = c.pos.Sub(b1.pos);
				c.rel2 = c.pos.Sub(b2.pos);
				c.massN = PTransformer.CalcEffectiveMass(b1, b2, c.rel1, c.rel2,
						c.normal);
				c.massT = PTransformer.CalcEffectiveMass(b1, b2, c.rel1, c.rel2,
						c.tangent);
				c.relVel = PTransformer
						.CalcRelativeVelocity(b1, b2, c.rel1, c.rel2);
				float rvn = c.relVel.Dot(c.normal);
				if (rvn < -0.5F)
					c.targetVelocity = System.Math.Max(rest * -rvn,0.0F);
				else
					c.targetVelocity = 0.0F;
				c.tangent.Set(c.normal.y, -c.normal.x);
				c.localRel1.Set(c.rel1.x, c.rel1.y);
				c.localRel2.Set(c.rel2.x, c.rel2.y);
				b1.mAng.Transpose().MulEqual(c.localRel1);
				b2.mAng.Transpose().MulEqual(c.localRel2);
			}
	
		}
Ejemplo n.º 3
0
    private void NewPlay(
        Pos pos,
        Piece piece,
        Player player,
        PColor color,
        PShape shape)
    {
        if (piece.color == color ||
            piece.shape == shape)
        {
            if (player == Player.me)
            {
                myWinCorridors.Add(
                    new Play(
                        pos.col,
                        pos.row,
                        oneGood));
            }

            else
            {
                myWinCorridors.Add(
                    new Play(
                        pos.col,
                        pos.row,
                        blockedCorridor));
            }
        }
    }
Ejemplo n.º 4
0
    protected override void setup()
    {
        size(512 * displayAspectW, 512, P2D);

        square = createShape(RECT, 0, 0, width / 2 - 25 * 2, height - 25 * 2);
        square.disableStyle();

        circle = createShape(ELLIPSE, 0, 0, 100, 100);
        circle.setFill(color(0, 255, 0));

        star = createShape();
        star.beginShape(TRIANGLE_FAN);
        star.vertex(0, 0);
        star.vertex(0, -50);
        star.vertex(14, -20);
        star.vertex(47, -15);
        star.vertex(23, 7);
        star.vertex(29, 40);
        star.vertex(0, 25);
        star.vertex(-29, 40);
        star.vertex(-23, 7);
        star.vertex(-47, -15);
        star.vertex(-14, -20);
        star.vertex(0, -50);
        star.endShape();

        recycle();
    }
 // Make shape selection visible in the UI
 private void SelectShape(PColor player, PShape shape)
 {
     // Keep the currently selected shape
     selectedShapes[(int)player] = shape;
     // Update UI widgets which depend on the shape selection
     ShapeSelected.Invoke(player, shape);
 }
Ejemplo n.º 6
0
 /// @copydoc ColorShapeLinks.Common.AI.AbstractThinker.Setup
 /// <seealso cref="ColorShapeLinks.Common.AI.AbstractThinker.Setup"/>
 public override void Setup(string str)
 {
     selectedCol   = Cols / 2;
     selectedShape = PShape.Round;
     Console.Clear();
     Console.WriteLine("\n\n\n");
 }
Ejemplo n.º 7
0
 private void triangleToolStripMenuItem_Click(object sender, EventArgs e)
 {
     pointShape = PShape.T;
     circleToolStripMenuItem.Checked   = false;
     squareToolStripMenuItem.Checked   = false;
     triangleToolStripMenuItem.Checked = true;
 }
Ejemplo n.º 8
0
		public PSortableObject(PShape s, PSortableAABB a, float v,
				bool b) {
			this.parent = s;
			this.aabb = a;
			this.value_ren = v;
			this.begin = b;
		}
Ejemplo n.º 9
0
 public PSortableObject(PShape s, PSortableAABB a, float v,
                        bool b)
 {
     this.parent    = s;
     this.aabb      = a;
     this.value_ren = v;
     this.begin     = b;
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Updates a hashed key with one extra position;
        /// </summary>
        /// <param name="column"> column position of the move</param>
        /// <param name="row"> row position of the move</param>
        /// <param name="color"> color of the piece</param>
        /// <param name="shape"> shape of the piece</param>
        /// <param name="oldKey"> old key to add the move to</param>
        /// <returns>
        /// New key with the desired move incorporated in.
        /// </returns>
        public ulong UpdateHash(int column, int row, PColor color, PShape shape, ulong oldKey)
        {
            ulong newKey = 0;

            // Xor occupied locations in turn
            newKey = oldKey ^ zobristKey[column * row][(int)shape][(int)color];

            return(newKey);
        }
Ejemplo n.º 11
0
    private void CheckWinCorridors(
        Player player,
        PColor color,
        PShape shape,
        Board board)
    {
        Piece piece;

        foreach (IEnumerable <Pos> enumerable in board.winCorridors)
        {
            foreach (Pos pos in enumerable)
            {
                positions.Add(pos);
            }
        }

        foreach (Pos pos in positions)
        {
            if (board[pos.row, pos.col] == null)
            {
                if (pos.col == 0)
                {
                    if (board[pos.row, pos.col + 1] != null)
                    {
                        piece = (Piece)board[pos.row, pos.col + 1];

                        NewPlay(pos, piece, player, color, shape);
                    }
                }
                else if (pos.col == board.cols - 1)
                {
                    if (board[pos.row, pos.col - 1] != null)
                    {
                        piece = (Piece)board[pos.row, pos.col - 1];

                        NewPlay(pos, piece, player, color, shape);
                    }
                }
                else
                {
                    if (board[pos.row, pos.col + 1] != null)
                    {
                        piece = (Piece)board[pos.row, pos.col + 1];

                        NewPlay(pos, piece, player, color, shape);
                    }

                    if (board[pos.row, pos.col - 1] != null)
                    {
                        piece = (Piece)board[pos.row, pos.col - 1];

                        NewPlay(pos, piece, player, color, shape);
                    }
                }
            }
        }
    }
Ejemplo n.º 12
0
 /// @copydoc ColorShapeLinks.Common.AI.AbstractThinker.Setup
 /// <seealso cref="ColorShapeLinks.Common.AI.AbstractThinker.Setup"/>
 public override void Setup(string str)
 {
     selectedCol   = Cols / 2;
     selectedShape = PShape.Round;
     if (str != null && str.Trim().Length > 0)
     {
         Console.WriteLine(
             $"Human player ignored these parameters: \"{str}\"");
     }
 }
Ejemplo n.º 13
0
        /// <summary>
        ///     Get greyscale level.
        /// </summary>
        /// <param name="x">X.</param>
        /// <param name="y">Y.</param>
        /// <returns>Value.</returns>
        protected byte GetGreyscaleLevel(int x, int y)
        {
            // Is this position is stored in cache ?
            if (!Cache.IsCached(x, y))
            {
                Cache.Update(x, y, PShape.GetValue(x, y).Red);
            }

            return(Cache.Level);
        }
Ejemplo n.º 14
0
		public virtual int Collide(PShape s1, PShape s2, PContact[] cs) {
			PCollider collider = null;
			bool flip = false;
			switch (s1._type) {
			case Physics.PShapeType.BOX_SHAPE:
			case Physics.PShapeType.CONVEX_SHAPE:
				switch (s2._type) {
				case Physics.PShapeType.BOX_SHAPE:
				case Physics.PShapeType.CONVEX_SHAPE:
					collider = new PPolygonPolygonCollider();
					break;
				case Physics.PShapeType.CIRCLE_SHAPE:
					collider = new PCirclePolygonCollider();
					flip = true;
					break;
				case Physics.PShapeType.CONCAVE_SHAPE:
				default:
					break;
				}
				break;
			case Physics.PShapeType.CIRCLE_SHAPE:
				switch (s2._type) {
				case Physics.PShapeType.BOX_SHAPE:
				case Physics.PShapeType.CONVEX_SHAPE:
					collider = new PCirclePolygonCollider();
					break;
				case Physics.PShapeType.CIRCLE_SHAPE:
					collider = new PCircleCirlceCollider();
					break;
				case Physics.PShapeType.CONCAVE_SHAPE:
				default:
					break;
				}
				break;
			case Physics.PShapeType.CONCAVE_SHAPE:
			default:
				break;
			}
			if (collider == null) {
				return 0;
			}
			if (flip) {
				int res = collider.Collide(s2, s1, cs);
				if (res > 0) {
					for (int i = 0; i < res; i++) {
						cs[i].normal.NegateLocal();
					}
				}
				return res;
			}
			return collider.Collide(s1, s2, cs);
		}
Ejemplo n.º 15
0
        public override FutureMove Think(Board board, CancellationToken ct)
        {
            Winner winner;
            PColor colorOfOurAI = board.Turn;

            possibleMoves.Clear();
            nonLosingMoves.Clear();

            for (int col = 0; col < Cols; col++)
            {
                if (board.IsColumnFull(col))
                {
                    continue;
                }

                for (int shp = 0; shp < 2; shp++)
                {
                    PShape shape = (PShape)shp;

                    if (board.PieceCount(colorOfOurAI, shape) == 0)
                    {
                        continue;
                    }

                    possibleMoves.Add(new FutureMove(col, shape));

                    board.DoMove(shape, col);

                    winner = board.CheckWinner();

                    // immediately
                    board.UndoMove();

                    if (winner.ToPColor() == colorOfOurAI)
                    {
                        return(new FutureMove(col, shape));
                    }
                    else if (winner.ToPColor() != colorOfOurAI.Other())
                    {
                        nonLosingMoves.Add(new FutureMove(col, shape));
                    }
                }
            }

            if (nonLosingMoves.Count > 0)
            {
                return(nonLosingMoves[random.Next(nonLosingMoves.Count)]);
            }

            return(possibleMoves[random.Next(possibleMoves.Count)]);
        }
Ejemplo n.º 16
0
 void changeShape(PShape newShape)
 {
     shape = newShape;
     if (newShape == PShape.circle)
     {
         sprite.sprite = gm.circleSprite;
     }
     else if (newShape == PShape.hexagon)
     {
         sprite.sprite = gm.hexagonSprite;
     }
     else if (newShape == PShape.diamond)
     {
         sprite.sprite = gm.diamondSprite;
     }
 }
Ejemplo n.º 17
0
    /// <summary>
    /// Check enemy colums for a winning move according to shapes.
    /// </summary>
    /// <param name="board"></param>
    /// <param name="col"></param>
    /// <returns>A move that blocks enemy win.</returns>
    private FutureMove?CheckEnemyColsShape(Board board, int col)
    {
        FutureMove? move;
        List <bool> threeInLine = new List <bool>();
        Piece       piece;
        PShape      enemyShape =
            color == PColor.White ? PShape.Square : PShape.Round;

        for (int i = 0; i < board.rows; i++)
        {
            if (board[i, col] == null)
            {
                return(null);
            }
            piece = (Piece)board[i, col];
            if (piece.shape == enemyShape)
            {
                threeInLine.Add(true);
            }
            else
            {
                threeInLine.RemoveRange(0, threeInLine.Count);
            }
            if (threeInLine.Count == 3)
            {
                if (board[i + 1, col].HasValue || i == board.rows)
                {
                    piece = (Piece)board[i + 1, col];
                    if (piece.shape == shape)
                    {
                        threeInLine.RemoveRange(0, threeInLine.Count);
                    }
                }
                else
                {
                    if (!board.IsColumnFull(col))
                    {
                        return(move = new FutureMove(col, shape));
                    }
                }
            }
        }

        return(move = null);
    }
Ejemplo n.º 18
0
 public PSolver(PShape shape1, PShape shape2, PContact[] contacts, int num)
 {
     s1          = shape1;
     s2          = shape2;
     b1          = s1._parent;
     b2          = s2._parent;
     fric        = (float)System.Math.Sqrt(s1._fric * s2._fric);
     rest        = (float)System.Math.Sqrt(s1._rest * s2._rest);
     cs          = contacts;
     numContacts = num;
     for (int i = 0; i < numContacts; i++)
     {
         PContact c = cs[i];
         c.rel1  = c.pos.Sub(b1.pos);
         c.rel2  = c.pos.Sub(b2.pos);
         c.massN = PTransformer.CalcEffectiveMass(b1, b2, c.rel1, c.rel2,
                                                  c.normal);
         c.massT = PTransformer.CalcEffectiveMass(b1, b2, c.rel1, c.rel2,
                                                  c.tangent);
         c.relVel = PTransformer
                    .CalcRelativeVelocity(b1, b2, c.rel1, c.rel2);
         float rvn = c.relVel.Dot(c.normal);
         if (rvn < -0.5F)
         {
             c.targetVelocity = System.Math.Max(rest * -rvn, 0.0F);
         }
         else
         {
             c.targetVelocity = 0.0F;
         }
         c.tangent.Set(c.normal.y, -c.normal.x);
         c.localRel1.Set(c.rel1.x, c.rel1.y);
         c.localRel2.Set(c.rel2.x, c.rel2.y);
         b1.mAng.Transpose().MulEqual(c.localRel1);
         b2.mAng.Transpose().MulEqual(c.localRel2);
     }
 }
Ejemplo n.º 19
0
        public virtual int Collide(PShape s1, PShape s2, PContact[] cs)
        {
            PCollider collider = null;
            bool      flip     = false;

            switch (s1._type)
            {
            case Physics.PShapeType.BOX_SHAPE:
            case Physics.PShapeType.CONVEX_SHAPE:
                switch (s2._type)
                {
                case Physics.PShapeType.BOX_SHAPE:
                case Physics.PShapeType.CONVEX_SHAPE:
                    collider = new PPolygonPolygonCollider();
                    break;

                case Physics.PShapeType.CIRCLE_SHAPE:
                    collider = new PCirclePolygonCollider();
                    flip     = true;
                    break;

                case Physics.PShapeType.CONCAVE_SHAPE:
                default:
                    break;
                }
                break;

            case Physics.PShapeType.CIRCLE_SHAPE:
                switch (s2._type)
                {
                case Physics.PShapeType.BOX_SHAPE:
                case Physics.PShapeType.CONVEX_SHAPE:
                    collider = new PCirclePolygonCollider();
                    break;

                case Physics.PShapeType.CIRCLE_SHAPE:
                    collider = new PCircleCirlceCollider();
                    break;

                case Physics.PShapeType.CONCAVE_SHAPE:
                default:
                    break;
                }
                break;

            case Physics.PShapeType.CONCAVE_SHAPE:
            default:
                break;
            }
            if (collider == null)
            {
                return(0);
            }
            if (flip)
            {
                int res = collider.Collide(s2, s1, cs);
                if (res > 0)
                {
                    for (int i = 0; i < res; i++)
                    {
                        cs[i].normal.NegateLocal();
                    }
                }
                return(res);
            }
            return(collider.Collide(s1, s2, cs));
        }
Ejemplo n.º 20
0
 /// <summary>
 /// Get number of remaining pieces with the given color and shape.
 /// </summary>
 /// <param name="color">Pieces color.</param>
 /// <param name="shape">Pieces shape.</param>
 /// <returns>
 /// Number of remaining pieces with the given color and shape.
 /// </returns>
 public int PieceCount(PColor color, PShape shape) =>
 numberOfPieces[new Piece(color, shape)];
Ejemplo n.º 21
0
    /// <summary>
    /// Make a move, return row
    /// </summary>
    /// <param name="shape">
    /// Shape of piece used in move (color is obtained from
    /// <see cref="Board.Turn"/>).
    /// </param>
    /// <param name="col">Column where to drop piece.</param>
    /// <returns>Row where piece was placed or -1 if move is invalid.</returns>
    public int DoMove(PShape shape, int col)
    {
        // The row were to place the piece, initially assumed to be the top row
        int row = rows - 1;

        // The color of the piece to place, depends on who's playing
        PColor color = Turn;

        // The piece to place
        Piece piece = new Piece(color, shape);

        // If the column is not a valid column, there is a client code bug,
        // so let's throw an exception
        if (col < 0 || col >= cols)
        {
            throw new InvalidOperationException($"Invalid board column: {col}");
        }

        // If we already found a winner, there is a client code bug, so let's
        // throw an exception
        if (CheckWinner() != Winner.None)
        {
            throw new InvalidOperationException(
                      "Game is over, unable to make further moves.");
        }

        // If there are no more pieces of the specified kind, there is a client
        // bug, so let's throw an exception
        if (numberOfPieces[piece] == 0)
        {
            throw new InvalidOperationException(
                      $"No more {piece} pieces available");
        }

        // If column is already full, return negative value, indicating the
        // move is invalid
        if (board[col, row].HasValue)
        {
            return(-1);
        }

        //
        // If we get here, move is valid, so let's do it
        //

        // Find row where to place the piece
        for (int r = row - 1; r >= 0 && !board[col, r].HasValue; r--)
        {
            row = r;
        }

        // Place the piece
        board[col, row] = piece;

        // Decrease the piece count
        numberOfPieces[piece]--;

        // Remember the move
        moveSequence.Push(new Pos(row, col));

        // Increment number of moves
        numMoves++;

        // Update turn
        Turn = Turn == PColor.White ? PColor.Red : PColor.White;

        // Return true, indicating the move was successful
        return(row);
    }
Ejemplo n.º 22
0
    /// <summary>
    /// Method used to play a move.
    /// </summary>
    /// <param name="board"></param>
    /// <param name="ct"></param>
    /// <returns>Move</returns>
    public FutureMove Think(Board board, CancellationToken ct)
    {
        FutureMove?test;
        Play       play;

        random = new System.Random();

        color = board.Turn;

        if (color == PColor.White)
        {
            shape = PShape.Round;
        }
        else
        {
            shape = PShape.Square;
        }

        if (shape == PShape.Round && board.PieceCount(color, PShape.Round) == 0)
        {
            shape = PShape.Square;
        }
        else if (shape == PShape.Square && board.PieceCount(color, PShape.Square) == 0)
        {
            shape = PShape.Round;
        }

        Check(board);

        test = PlayPiece(board);
        if (test != null)
        {
            return((FutureMove)test);
        }

        test = CheckEnemy(board);
        if (test != null)
        {
            return((FutureMove)test);
        }

        play = Negamax(board, board.Turn, maxDepth, ct);

        if (test != null)
        {
            if (play.pos == null)
            {
                return(FutureMove.NoMove);
            }
            else
            {
                return(new FutureMove((int)play.pos, PShape.Round));
            }
        }

        if (allPiece.Count % 2 == 0)
        {
            test = CheckWinCorridors(board);
        }
        else
        {
            test = CheckEnemyWinCorridors(board);
        }



        if (test != null)
        {
            return((FutureMove)test);
        }

        /*int roundPieces = board.PieceCount(board.Turn, PShape.Round);
         * int squarePieces = board.PieceCount(board.Turn, PShape.Square);
         * shape = squarePieces < roundPieces ? PShape.Round : PShape.Square;*/

        return(new FutureMove(random.Next(0, board.cols), shape));
    }
Ejemplo n.º 23
0
    public FutureMove Think(Board board, CancellationToken ct)
    {
        FutureMove?test;
        Play       play;

        random = new Random();

        color = board.Turn;

        if (color == PColor.White)
        {
            shape = PShape.Round;
        }

        else
        {
            shape = PShape.Square;
        }

        if (shape == PShape.Round &&
            board.PieceCount(color, PShape.Round) == 0)
        {
            shape = PShape.Square;
        }

        else if (shape == PShape.Square &&
                 board.PieceCount(color, PShape.Square) == 0)
        {
            shape = PShape.Round;
        }

        Check(board);

        test = CheckPlayer(board, Player.me);
        if (test != null)
        {
            return((FutureMove)test);
        }

        test = CheckPlayer(board, Player.enemy);
        if (test != null)
        {
            return((FutureMove)test);
        }

        PColor myColor = board.Turn;
        PShape myShape = shape;

        CheckWinCorridors(Player.me, myColor, myShape, board);

        PColor enemyColor =
            color == PColor.White ? PColor.Red : PColor.White;
        PShape enemyShape =
            shape == PShape.Round ? PShape.Square : PShape.Round;

        CheckWinCorridors(Player.enemy, enemyColor, enemyShape, board);

        play = Negamax(board, board.Turn, maxDepth, ct);

        if (test != null)
        {
            if (play.posCol == null)
            {
                return(FutureMove.NoMove);
            }

            else
            {
                return(new FutureMove((int)play.posCol, PShape.Round));
            }
        }

        return(new FutureMove(random.Next(0, board.cols), shape));
    }
Ejemplo n.º 24
0
        /// @copydoc ColorShapeLinks.Common.AI.IThinker.Think
        /// <remarks>
        /// This method asks the human to play.
        /// </remarks>
        /// <seealso cref="ColorShapeLinks.Common.AI.IThinker.Think"/>
        public override FutureMove Think(Board board, CancellationToken ct)
        {
            // By default, no move is performed in case of timeout
            FutureMove move = FutureMove.NoMove;

            // No thinking notification has taken place
            DateTime lastNotificationTime = DateTime.MinValue;

            // Set thinking notification interval between frames to 20ms
            TimeSpan notificationInterval = TimeSpan.FromMilliseconds(20);

            // Calculate the time limit for the human to play
            DateTime timeLimit =
                DateTime.Now + TimeSpan.FromMilliseconds(TimeLimitMillis);

            // Show some info on what keys are used for input
            OnThinkingInfo("T to toggle piece, < > to change selected column");

            // If a certain type of piece is not available, make the other
            // type the selected one
            if (board.PieceCount(board.Turn, PShape.Round) == 0)
            {
                selectedShape = PShape.Square;
            }
            if (board.PieceCount(board.Turn, PShape.Square) == 0)
            {
                selectedShape = PShape.Round;
            }

            // If the current column is full, iterate column selection until
            // one is not
            while (board.IsColumnFull(selectedCol))
            {
                selectedCol++;
                if (selectedCol >= Cols)
                {
                    selectedCol = 0;
                }
            }

            // Wait for human input at most until the cancellation token is
            // activated
            while (true)
            {
                // Was a key pressed?
                if (Console.KeyAvailable)
                {
                    // Retrieve key
                    ConsoleKey key = Console.ReadKey().Key;

                    // Check if it was a column increment key
                    if (key == ConsoleKey.RightArrow ||
                        key == ConsoleKey.D ||
                        key == ConsoleKey.NumPad6 ||
                        key == ConsoleKey.D6)
                    {
                        // Increment column...
                        do
                        {
                            // ...making sure a full column is not selectable,
                            // and wraping around
                            selectedCol++;
                            if (selectedCol >= Cols)
                            {
                                selectedCol = 0;
                            }
                        } while (board.IsColumnFull(selectedCol));
                    }
                    // Check if it was a column decrement key
                    else if (key == ConsoleKey.LeftArrow ||
                             key == ConsoleKey.A ||
                             key == ConsoleKey.NumPad4 ||
                             key == ConsoleKey.D4)
                    {
                        // Decrement column...
                        do
                        {
                            // ...making sure a full column is not selectable,
                            // and wraping around
                            selectedCol--;
                            if (selectedCol < 0)
                            {
                                selectedCol = Cols - 1;
                            }
                        } while (board.IsColumnFull(selectedCol));
                    }
                    // Check if it was a piece toggle key
                    else if (key == ConsoleKey.T)
                    {
                        // Toggle piece if the other type of piece is available
                        if (selectedShape == PShape.Round &&
                            board.PieceCount(board.Turn, PShape.Square) > 0)
                        {
                            selectedShape = PShape.Square;
                        }
                        else if (selectedShape == PShape.Square &&
                                 board.PieceCount(board.Turn, PShape.Round) > 0)
                        {
                            selectedShape = PShape.Round;
                        }
                    }
                    // Check if it was a piece drop key
                    else if (key == ConsoleKey.Enter)
                    {
                        // Drop piece and get out of the input loop
                        move = new FutureMove(selectedCol, selectedShape);
                        break;
                    }
                }

                // If cancellation token is activated, terminate input loop
                if (ct.IsCancellationRequested)
                {
                    break;
                }

                // Is it time for another thinking notification?
                if (DateTime.Now > lastNotificationTime + notificationInterval)
                {
                    // Show dialog
                    Console.CursorLeft = 0;
                    Console.Write(String.Format(
                                      "Col [{0,4}] | Shape [{1,7}] | Time [{2,14}]",
                                      selectedCol,
                                      selectedShape,
                                      timeLimit - DateTime.Now));
                    Console.CursorLeft = 0;

                    // Update last notification time
                    lastNotificationTime = DateTime.Now;
                }
            }

            // Return chosen move
            return(move);
        }
Ejemplo n.º 25
0
    /// <summary>
    /// Method used to check enemy WinCorridors and play according to it,
    /// in order to block is line
    /// </summary>
    /// <param name="board"></param>
    /// <returns>A play for the AI to use.</returns>
    private FutureMove?CheckEnemyWinCorridors(Board board)
    {
        Piece  piece;
        PColor enemyColor =
            color == PColor.White ? PColor.Red : PColor.White;
        PShape enemyShape =
            shape == PShape.Round ? PShape.Square : PShape.Round;

        foreach (IEnumerable <Pos> enumerable in board.winCorridors)
        {
            foreach (Pos pos in enumerable)
            {
                positions.Add(pos);
            }
        }

        foreach (Pos pos in positions)
        {
            if (board[pos.row, pos.col] == null)
            {
                if (pos.col == 0)
                {
                    if (board[pos.row, pos.col + 1] != null)
                    {
                        piece = (Piece)board[pos.row, pos.col + 1];

                        if (piece.color == enemyColor || piece.shape == enemyShape)
                        {
                            return(new FutureMove(pos.col, shape));
                        }
                    }
                }
                else if (pos.col == board.cols - 1)
                {
                    if (board[pos.row, pos.col - 1] != null)
                    {
                        piece = (Piece)board[pos.row, pos.col - 1];

                        if (piece.color == enemyColor || piece.shape == enemyShape)
                        {
                            return(new FutureMove(pos.col, shape));
                        }
                    }
                }
                else
                {
                    if (board[pos.row, pos.col + 1] != null)
                    {
                        piece = (Piece)board[pos.row, pos.col + 1];

                        if (piece.color == enemyColor || piece.shape == enemyShape)
                        {
                            return(new FutureMove(pos.col, shape));
                        }
                    }

                    if (board[pos.row, pos.col - 1] != null)
                    {
                        piece = (Piece)board[pos.row, pos.col - 1];
                        if (piece.color == enemyColor || piece.shape == enemyShape)
                        {
                            return(new FutureMove(pos.col, shape));
                        }
                    }
                }
            }
        }

        return(null);
    }
Ejemplo n.º 26
0
    /// <summary>
    /// Negamax.
    /// </summary>
    /// <param name="board"></param>
    /// <param name="turn"></param>
    /// <param name="maxDepth"></param>
    /// <param name="ct"></param>
    /// <returns>A play for the AI to use.</returns>
    private Play Negamax(Board board, PColor turn, int maxDepth, CancellationToken ct)
    {
        Play bestMove = new Play(null, int.MinValue);

        PColor proxTurn =
            turn == PColor.Red ? PColor.White : PColor.Red;

        bool stup = false;

        if (ct.IsCancellationRequested)
        {
            return(new Play(null, 0));
        }
        else
        {
            if (maxDepth <= 0)
            {
                return(bestMove);
            }

            foreach (Play play in myWinCorridors)
            {
                for (int j = 0; j < board.cols; j++)
                {
                    int pos = j;

                    if (board[(int)play.pos, j] == null)
                    {
                        int roundPieces  = board.PieceCount(board.Turn, PShape.Round);
                        int squarePieces = board.PieceCount(board.Turn, PShape.Square);
                        if (shape == PShape.Round)
                        {
                            if (roundPieces == 0)
                            {
                                shape = PShape.Square;
                            }
                        }
                        else
                        {
                            if (squarePieces == 0)
                            {
                                shape = PShape.Round;
                            }
                        }

                        Play move = default;

                        board.DoMove(shape, j);

                        maxDepth--;

                        if (board.CheckWinner() != Winner.None)
                        {
                            stup = true;
                        }

                        if (!stup)
                        {
                            move = Negamax(board, proxTurn, maxDepth, ct);
                        }

                        board.UndoMove();

                        move.score = -move.score;

                        if (move.score > bestMove.score)
                        {
                            bestMove.score = move.score;
                            bestMove.pos   = pos;
                        }
                    }
                }
            }

            /*for (int i = 0; i < board.rows; i++)
             * {
             *  for (int j = 0; j < board.cols; j++)
             *  {
             *      int pos = j;
             *      if (board[i, j] == null)
             *      {
             *          int roundPieces = board.PieceCount(board.Turn, PShape.Round);
             *          int squarePieces = board.PieceCount(board.Turn, PShape.Square);
             *          if (shape == PShape.Round)
             *          {
             *              if (roundPieces == 0)
             *              {
             *                  shape = PShape.Square;
             *              }
             *          }
             *          else
             *          {
             *              if (squarePieces == 0)
             *              {
             *                  shape = PShape.Round;
             *              }
             *          }
             *          Play move = default;
             *          board.DoMove(shape, j);
             *          maxDepth--;
             *          if (board.CheckWinner() != Winner.None)
             *          {
             *              stup = true;
             *          }
             *          if (!stup)
             *          {
             *              move = Negamax(board, proxTurn, maxDepth, ct);
             *          }
             *          board.UndoMove();
             *          move.score = -move.score;
             *          if (move.score > bestMove.score)
             *          {
             *              bestMove.score = move.score;
             *              bestMove.pos = pos;
             *          }
             *      }
             *  }
             * }*/

            return(bestMove);
        }
    }
Ejemplo n.º 27
0
        private Play Negamax(int depth, Board board, PColor turn, CancellationToken cancellationToken, int alpha = int.MinValue, int beta = int.MaxValue)
        {
            Play   selectedMove = new Play(null, int.MinValue);
            PColor nextTurn     = (turn == PColor.Red) ? PColor.White : PColor.Red;

            if (cancellationToken.IsCancellationRequested)
            {
                return(new Play(null, 0));
            }

            if (depth <= 0)
            {
                int tempScore = _random.Next(0, 100);

                if (board.CheckWinner() != Winner.None)
                {
                    tempScore = 300;
                }
                tempScore += board.winCorridors.Count() * 10;

                if (tempScore % 2 != 0)
                {
                    tempScore *= -1;
                }
                selectedMove.Score = tempScore;


                return(selectedMove);
            }
            for (int j = 0; j < board.cols; j++)
            {
                int column = j;
                for (int i = 0; i < board.rows; i++)
                {
                    if (board[i, j] == null)
                    {
                        int  roundPieces  = board.PieceCount(board.Turn, PShape.Round);
                        int  squarePieces = board.PieceCount(board.Turn, PShape.Square);
                        Play move         = default;

                        if (roundPieces > 0)
                        {
                            shape = PShape.Round;
                            board.DoMove(shape, j);
                            if ((board.CheckWinner() == Winner.None))
                            {
                                move = Negamax(depth - 1, board, nextTurn, cancellationToken, -beta, -alpha);
                            }
                            board.UndoMove();
                            move.Score = -move.Score;
                            if (move.Score > bestMove.Score)
                            {
                                bestMove = move;
                            }

                            if (bestMove.Score > alpha)
                            {
                                alpha = bestMove.Score;
                            }

                            if (bestMove.Score >= beta)
                            {
                                bestMove.Score    = alpha;
                                bestMove.Position = column;
                                return(bestMove);
                            }
                        }

                        if (squarePieces > 0)
                        {
                            shape = PShape.Square;
                            board.DoMove(shape, j);
                            if ((board.CheckWinner() == Winner.None))
                            {
                                move = Negamax(depth - 1, board, nextTurn, cancellationToken, -beta, -alpha);
                            }
                            board.UndoMove();
                            if (move.Score > bestMove.Score)
                            {
                                bestMove = move;
                            }

                            if (bestMove.Score > alpha)
                            {
                                alpha = bestMove.Score;
                            }

                            if (bestMove.Score >= beta)
                            {
                                bestMove.Score    = alpha;
                                bestMove.Position = column;
                                return(bestMove);
                            }
                        }
                    }
                }
            }
            return(bestMove);
        }
Ejemplo n.º 28
0
 /// <summary>Create a new piece.</summary>
 /// <param name="color">The piece color.</param>
 /// <param name="shape">The piece shape.</param>
 public Piece(PColor color, PShape shape)
 {
     this.color = color;
     this.shape = shape;
 }
Ejemplo n.º 29
0
 /// <summary>Is the piece of the specified color and shape?</summary>
 /// <param name="color">The piece color.</param>
 /// <param name="shape">The piece shape.</param>
 /// <returns>
 /// `true` if the piece has the specified color and shape, `false`
 /// otherwise.
 /// </returns>
 public bool Is(PColor color, PShape shape) =>
 this.color == color && this.shape == shape;
Ejemplo n.º 30
0
    private Play Negamax(
        Board board,
        PColor turn,
        int maxDepth,
        CancellationToken ct)
    {
        Play bestMove = new Play(null, null, int.MinValue);

        PColor proxTurn =
            turn == PColor.Red ? PColor.White : PColor.Red;

        if (ct.IsCancellationRequested)
        {
            return(new Play(null, null, 0));
        }
        else
        {
            if (cDepth == maxDepth)
            {
                return(bestMove);
            }

            cDepth++;

            foreach (Play play in myWinCorridors)
            {
                for (int j = 0; j < board.cols; j++)
                {
                    int pos = j;

                    if (board[(int)play.posCol, (int)play.posRow] == null)
                    {
                        int roundPieces =
                            board.PieceCount(board.Turn, PShape.Round);

                        int squarePieces =
                            board.PieceCount(board.Turn, PShape.Square);

                        if (shape == PShape.Round)
                        {
                            if (roundPieces == 0)
                            {
                                shape = PShape.Square;
                            }
                            else
                            if (squarePieces == 0)
                            {
                                shape = PShape.Round;
                            }
                        }

                        Play move = default;

                        board.DoMove(shape, j);

                        if (board.CheckWinner() == Winner.None)
                        {
                            move = Negamax(board, proxTurn, maxDepth, ct);
                        }

                        board.UndoMove();

                        move.score = -move.score;

                        if (move.score > bestMove.score)
                        {
                            bestMove.score  = move.score;
                            bestMove.posCol = pos;
                        }
                    }
                }
            }

            return(bestMove);
        }
    }
Ejemplo n.º 31
0
        public override void Alter(LTimerContext timer)
        {
            for (int i = 0; i < keySize; i++)
            {
                ActionKey act = (ActionKey)keyActions.Get(i);
                if (act.IsPressed())
                {
                    act.Act(elapsedTime);
                    if (act.isReturn)
                    {
                        return;
                    }
                }
            }
            if (content.IsVisible())
            {
                ProcessEvents();
                content.UpdateNode(timer.GetMilliseconds());
            }
            if (usePhysics)
            {
                if (_dt < 0)
                {
                    _manager.Step(timer.GetMilliseconds());
                }
                else
                {
                    _manager.Step(_dt);
                }
            }
            if (follow != null)
            {
                if (usePhysics)
                {
                    _manager.Offset(follow.GetX(), follow.GetY());
                }
                foreach (TileMap tile in tiles)
                {
                    float offsetX = GetHalfWidth() - follow.GetX();
                    offsetX = MathUtils.Min(offsetX, 0);
                    offsetX = MathUtils.Max(offsetX, GetWidth() - tile.GetWidth());

                    float offsetY = GetHalfHeight() - follow.GetY();
                    offsetY = MathUtils.Min(offsetY, 0);
                    offsetY = MathUtils
                              .Max(offsetY, GetHeight() - tile.GetHeight());

                    SetOffset(tile, offsetX, offsetY);
                    tile.Update(elapsedTime);
                }
            }
            foreach (SpriteBatchObject o in objects)
            {
                if (usePhysics)
                {
                    PBody body = (PBody)CollectionUtils.Get(_Bodys, o);
                    if (body != null)
                    {
                        PShape shape    = body.Inner_shapes()[0];
                        float  rotation = (shape.GetAngle() * MathUtils.RAD_TO_DEG) % 360;
                        AABB   aabb     = shape.GetAABB();
                        o.SetLocation(_manager.GetScreenX(aabb.minX),
                                      _manager.GetScreenY(aabb.minY));
                        o.SetRotation(rotation);
                    }
                }
                o.Update(elapsedTime);
                if (updateListener != null)
                {
                    updateListener.Act(o, elapsedTime);
                }
            }
            Update(elapsedTime);
            Commits();
        }
        // Awake is called when the script instance is being loaded
        private void Awake()
        {
            // Top and bottom pole padding
            const float polePadding = 0.1f;

            // Ground instance
            GameObject groundInst, messageBox;

            // Top-left of ground sprite renderer
            Vector3 gTopLeft;

            // Bounds of different sprite renderers
            Bounds gBounds, plBounds, aBounds, pcBounds;

            // Get reference to the camera
            Camera camera =
                GameObject.Find("Main Camera").GetComponent <Camera>();

            // Get reference to the match view configuration
            IMatchViewConfig viewConfig =
                GetComponentInParent <IMatchViewConfig>();

            // Get value of last move animation length in seconds
            lastMoveAnimLength = viewConfig.LastMoveAnimLength;

            // /////////////////////////////////// //
            // Get references to essential prefabs //
            // /////////////////////////////////// //

            whiteRoundPiece =
                Resources.Load <GameObject>("Prefabs/PieceWhiteRound");
            whiteSquarePiece =
                Resources.Load <GameObject>("Prefabs/PieceWhiteSquare");
            redRoundPiece =
                Resources.Load <GameObject>("Prefabs/PieceRedRound");
            redSquarePiece =
                Resources.Load <GameObject>("Prefabs/PieceRedSquare");
            pole        = Resources.Load <GameObject>("Prefabs/Pole");
            ground      = Resources.Load <GameObject>("Prefabs/Ground");
            arrowButton = Resources.Load <GameObject>("Prefabs/ArrowButton");
            playerPanel = Resources.Load <GameObject>("Prefabs/PlayerPanel");

            // //////////////////////////////////////////// //
            // Initialize required variables and coroutines //
            // //////////////////////////////////////////// //

            // Instantiate a string builder, used for keeping messages
            messages = new StringBuilder();

            // We just started, so game is not finished yet
            finished = false;

            // Get reference to the match configuration
            matchConfig = GetComponentInParent <IMatchConfig>();

            // Get reference to the session data and the game board
            matchData = GetComponentInParent <IMatchDataProvider>();
            board     = matchData.Board;

            // Both players have the round shapes initially selected by default
            selectedShapes = new PShape[] { PShape.Round, PShape.Round };

            // Instantiate Unity events for shape selection and board updating
            ShapeSelected = new ColorShapeEvent();
            BoardUpdated  = new UnityEvent();

            // Create matrix for placing game objects representing pieces
            pieces = new GameObject[board.rows, board.cols];

            // Create array for UI arrow script objects
            uiArrows = new HumanMoveButton[board.cols];

            // Instantiate the message queue
            messageQueue = new Queue <string>();

            // Get reference to the "Message Box" canvas game object, set the
            // reference to the main camera, and get a reference to the UI text
            // to display the messages
            messageBox = GameObject.Find("MessageBox").gameObject;
            messageBox.GetComponent <Canvas>().worldCamera = camera;
            messageBoxText = messageBox.GetComponentInChildren <Text>();

            // Initialize message box coroutine
            StartCoroutine(UpdateMessageBox());

            // /////////////////////////////////////// //
            // Initialize and place game board objects //
            // /////////////////////////////////////// //

            // Instantiate ground
            groundInst = Instantiate(ground, transform);

            // Determine where ground starts, since everything will be placed
            // with respect to the ground
            gBounds  = groundInst.GetComponent <SpriteRenderer>().bounds;
            gTopLeft = new Vector3(gBounds.min.x, gBounds.max.y, 0);

            // Get pole bounds
            plBounds = pole.GetComponent <SpriteRenderer>().bounds;

            // Get arrow bounds
            aBounds = arrowButton.GetComponent <SpriteRenderer>().bounds;

            // Get piece bounds (any will do)
            pcBounds = redRoundPiece.GetComponent <SpriteRenderer>().bounds;

            // Instantiate poles and arrows
            for (int c = 0; c < board.cols; c++)
            {
                GameObject currPole, currArrow;

                // Instantiate current pole
                currPole = Instantiate(
                    pole,
                    new Vector3(
                        gTopLeft.x
                        + (c + 1) * (gBounds.size.x / (board.cols + 1)),
                        gTopLeft.y + plBounds.extents.y - polePadding,
                        1),
                    Quaternion.identity,
                    transform);
                currPole.name = $"Pole{c}";

                // Instantiate current arrow
                currArrow = Instantiate(
                    arrowButton,
                    new Vector3(
                        gTopLeft.x
                        + (c + 1) * (gBounds.size.x / (board.cols + 1)),
                        gTopLeft.y
                        + plBounds.size.y + polePadding + aBounds.extents.y,
                        4),
                    Quaternion.identity,
                    transform);
                currArrow.name = $"Arrow{c}";

                // Keep reference to the UI arrow script
                uiArrows[c] = currArrow.GetComponent <HumanMoveButton>();

                // Set the arrow's column
                uiArrows[c].Column = c;

                // Listen to arrow clicks in order to perform move selection
                uiArrows[c].Click.AddListener(OnMoveSelected);

                // Enable or disable arrow depending on who's playing
                currArrow.SetActive(matchData.CurrentThinker is HumanThinker);
            }

            // These will be necessary for calculating the positions of the
            // pieces
            leftPoleBase = new Vector2(
                gTopLeft.x + gBounds.size.x / (board.cols + 1),
                gTopLeft.y);
            distBtwPoles         = gBounds.size.x / (board.cols + 1);
            totalHeightForPieces = plBounds.size.y - 2 * polePadding;

            // The scale of the pieces will the minimum between...
            piecesScale = Mathf.Min(
                // ...half of distance between the poles divided by the original
                // width of the prefabs...
                (distBtwPoles / 2) / pcBounds.size.x,
                // ...and the available space for each piece in a pole, divided
                // by the original height of the prefabs
                (totalHeightForPieces / board.rows) / pcBounds.size.y);

            // Keep the length of the pieces (equal in x and y directions)
            piecesLength = piecesScale * pcBounds.size.y;

            // /////////////////// //
            // Setup player panels //
            // /////////////////// //

            // Instantiate player panels
            GameObject[] playerPanels =
            {
                Instantiate(playerPanel, transform),
                Instantiate(playerPanel, transform)
            };

            // Initialize an array of piece sprites, which will simplify
            // passing the correct sprite for each shape in each player panel
            Sprite[,] pieceSprites =
            {
                {
                    whiteRoundPiece.GetComponent <SpriteRenderer>().sprite,
                    whiteSquarePiece.GetComponent <SpriteRenderer>().sprite,
                },
                {
                    redRoundPiece.GetComponent <SpriteRenderer>().sprite,
                    redSquarePiece.GetComponent <SpriteRenderer>().sprite,
                }
            };

            // Initialize panels for each player
            for (int i = 0; i < 2; i++)
            {
                // Current player
                PColor player = (PColor)i;
                // Get current panel
                GameObject panel = playerPanels[i];
                // Get current panel's rect transform
                RectTransform rtPanel = panel.GetComponent <RectTransform>();
                // Get current panel toggles for selecting shape
                Toggle[] toggles = panel.GetComponentsInChildren <Toggle>();
                // Setup event camera in panel
                panel.GetComponent <Canvas>().worldCamera = camera;
                // Position panel
                rtPanel.position = new Vector3(
                    i == 0
                    // First panel to the right
                        ? gBounds.center.x - gBounds.extents.x / 2
                    // Second panel to the left
                        : gBounds.center.x + gBounds.extents.x / 2,
                    gBounds.min.y
                    - rtPanel.rect.height / 2 * rtPanel.localScale.y,
                    rtPanel.position.z
                    );
                // Set player name in panel
                panel.GetComponentInChildren <Text>().text =
                    matchData.GetThinker(player).ToString();

                // Configure toggles for selecting shape
                for (int j = 0; j < 2; j++)
                {
                    // Current shape
                    PShape shape = (PShape)j;

                    // Setup correct sprite for the toggle
                    toggles[j]
                    .transform
                    .GetChild(1)
                    .GetComponent <Image>()
                    .sprite = pieceSprites[i, j];

                    // Delegate to be called at start and after each move,
                    // which:
                    // 1. Updates piece count in current player's toggle UI
                    //    widget
                    // 2. Enables/disables toggle interaction depending on
                    //    who's playing
                    UnityAction setToggles = () =>
                    {
                        // 1.
                        // Count for current player and shape
                        int count = board.PieceCount(player, shape);
                        // Update label to update with shape count
                        toggles[(int)shape].GetComponentInChildren <Text>()
                        .text = count.ToString();
                        // If count reached zero, swap shape selection
                        if (count == 0)
                        {
                            SelectShape(
                                player,
                                shape == PShape.Round
                                    ? PShape.Square
                                    : PShape.Round);
                            toggles[(int)shape].interactable = false;
                        }
                        // 2.
                        else
                        {
                            // Player is human, is its turn and game not over,
                            // enable toggle
                            if (matchData.GetThinker(player) is HumanThinker &&
                                player == board.Turn && !finished)
                            {
                                toggles[(int)shape].interactable = true;
                            }
                            // Otherwise disable toggle
                            else
                            {
                                toggles[(int)shape].interactable = false;
                            }
                        }
                    };

                    // Invoke delegate to initialize toggles
                    setToggles.Invoke();

                    // Make this delegate be called after each move
                    BoardUpdated.AddListener(setToggles);

                    // Wire up method for listening to piece swap events
                    toggles[j].onValueChanged.AddListener(
                        b => { if (b)
                               {
                                   SelectShape(player, shape);
                               }
                        });
                }

                // Wire up listener for programatically changing selected shape
                // in current player's toggle
                ShapeSelected.AddListener((PColor p, PShape s) =>
                                          { if (p == player)
                                            {
                                                toggles[(int)s].isOn = true;
                                            }
                                          });
            }
        }
Ejemplo n.º 33
0
    private FutureMove?CheckCols(
        Board board,
        int col,
        Player player,
        CheckType checkType)
    {
        List <bool> threeInLine = new List <bool>(3);
        Piece       piece;

        PColor enemyColor =
            color == PColor.White ? PColor.Red : PColor.White;

        PShape enemyShape =
            color == PColor.White ? PShape.Square : PShape.Round;

        for (int i = 0; i < board.rows; i++)
        {
            if (board[i, col] == null)
            {
                return(null);
            }

            piece = (Piece)board[i, col];

            if (checkType == CheckType.color)
            {
                if (piece.color == board.Turn)
                {
                    threeInLine.Add(true);
                }
                else
                {
                    threeInLine.RemoveRange(0, threeInLine.Count);
                }
            }
            else
            {
                if (piece.shape == shape)
                {
                    threeInLine.Add(true);
                }
                else
                {
                    threeInLine.RemoveRange(0, threeInLine.Count);
                }
            }

            if (threeInLine.Count == 3)
            {
                if (!board.IsColumnFull(col))
                {
                    if (board[i + 1, col].HasValue ||
                        i == board.rows)
                    {
                        piece = (Piece)board[i + 1, col];

                        if (checkType == CheckType.color)
                        {
                            if (piece.color == enemyColor)
                            {
                                threeInLine.RemoveRange(
                                    0,
                                    threeInLine.Count);
                            }
                            else
                            if (piece.shape == enemyShape)
                            {
                                threeInLine.RemoveRange(
                                    0,
                                    threeInLine.Count);
                            }
                        }
                    }
                    else
                    {
                        if (player == Player.me)
                        {
                            myWinCorridors.Add(new Play(col, i, win));
                        }
                        else
                        {
                            myWinCorridors.Add(new Play(col, i, block));
                        }

                        return(new FutureMove(col, shape));
                    }
                }
            }
        }

        return(null);
    }