// If gameOver is true in state then game is over and display the winning text and appropriate colors void Update() { if (screenShown == false && OthelloGame.gameOver == true) { winnerText.GetComponent <Text>().text = "Winner: " + OthelloGame.GetWinner().ToUpper(); if (OthelloGame.GetWinner() == "white") { winnerText.GetComponent <Text>().color = Color.white; gameOverText.GetComponent <Text>().color = Color.white; backgroundCube.GetComponent <Renderer>().material = blue; } else if (OthelloGame.GetWinner() == "black") { winnerText.GetComponent <Text>().color = Color.black; gameOverText.GetComponent <Text>().color = Color.black; backgroundCube.GetComponent <Renderer>().material = red; } else { winnerText.GetComponent <Text>().color = Color.white; gameOverText.GetComponent <Text>().color = Color.white; backgroundCube.GetComponent <Renderer>().material = squareGreen; } restartScreen.SetActive(true); screenShown = true; } }
private void SetupBoard() { _myGame = new OthelloGame(); _minMaxAgent = new MinMaxAgent(); _boardPanels = new PiecePanel[OthelloGame.BOARD_SIZE, OthelloGame.BOARD_SIZE]; _currentViewedMove = 0; int tileSize = ((Size.Width > Size.Height) ? Size.Height - 45 : Size.Width - 45) / OthelloGame.BOARD_SIZE; for (int i = 0; i < OthelloGame.BOARD_SIZE; i++) { for (int j = 0; j < OthelloGame.BOARD_SIZE; j++) { var newPanel = new PiecePanel(new int[] { i, j }) { Size = new Size(tileSize, tileSize), Location = new Point(tileSize * i, tileSize * j) }; newPanel.MouseClick += new MouseEventHandler(OthelloPeice_Click); Controls.Add(newPanel); _boardPanels[i, j] = newPanel; Color panelcolor = Color.Red; if (BoardColorDictionary.BoardStateColors.TryGetValue(_myGame.GetBoard()[i, j], out panelcolor)) { _boardPanels[i, j].ReColor(panelcolor); } } } }
/// <summary> /// The main entry point for the application. /// </summary> static void Main(string[] args) { using (OthelloGame game = new OthelloGame()) { game.Run(); } }
public override byte[] MakeMove(OthelloGame game, BoardStates player) { byte[] bestMove = new byte[] { byte.MaxValue, byte.MaxValue }; List <byte[]> moves = game.GetPossiblePlayList(); double bestScore = int.MinValue + 1; if (game.GetPieceCount(BoardStates.empty) > 58)//first two moves, don't compute { return(OpeningMove(player, game)); } else if (moves.Count == 1) //don't compute if there is only 1 move { return(moves[0]); } foreach (byte[] move in moves) { OthelloGame testGame = game.DeepCopy(); testGame.MakeMove(move); double thisScore = EvaluateBoard(testGame, player); if (thisScore > bestScore) { bestScore = thisScore; bestMove = move; } } if ((bestMove[0] == byte.MaxValue || bestMove[1] == byte.MaxValue) && moves.Count > 0) {//All moves are valued at -inf, return one of em return(moves[0]); } return(bestMove); }
public override double EvaluateBoard(OthelloGame game, BoardStates player) { ///Based of features of the board that humans have identified. ///Hints of evaluation from any source I could find ///idealy these could me optimized using a genetic algorithm, ///but that is a different project double value = 0; int empty = game.GetPieceCount(BoardStates.empty); if (game.GameComplete) { return(CompleteEval(player, game)); } //plane funct //value += coinDiffSlope * (game.GetPieceCount(player) - game.GetPieceCount(~player)) + (empty * coinTimeSlope) + coinDiffOffset; //value += cornerDiffSlope * (game.GetCornerCount(player) - game.GetCornerCount(~player)) + (empty * cornerTimeSlope) + cornerDiffOffset; //value += nearCornerDiffSlope * (game.GetAdjCornerCount(player) - game.GetAdjCornerCount(~player)) + (empty * nearCornerTimeSlope) + nearCornerDiffOffset; //value += avalibleMoveDiffSlope * (game.GetPossiblePlayList(player).Count() - game.GetPossiblePlayList(~player).Count()) + (empty * avalibleMoveTimeSlope) + avalibleMoveDiffOffset; //value += nonTurnableCoinDiffSlope * (game.GetSafePeiceCountEstimation(player) - game.GetSafePeiceCountEstimation(~player)) + (empty * nonTurnableTimeSlope) + nonTurnableCoinDiffOffset; //value += controlledCornerDiffSlope * (game.GetControlledCorners(player) - game.GetControlledCorners(~player)) + (empty * controlledCornerTimeSlope) + controlledCornerDiffOffset; //power funct value += coinDiffSlope * Math.Pow(game.GetPieceCount(player) - game.GetPieceCount(~player) + empty - coinDiffOffset, coinTimeSlope); value += cornerDiffSlope * Math.Pow(game.GetCornerCount(player) - game.GetCornerCount(~player) + empty - cornerDiffOffset, cornerTimeSlope); value += nearCornerDiffSlope * Math.Pow(game.GetAdjCornerCount(player) - game.GetAdjCornerCount(~player) + empty - nearCornerDiffOffset, nearCornerTimeSlope); value += avalibleMoveDiffSlope * Math.Pow(game.GetPossiblePlayList(player).Count() - game.GetPossiblePlayList(~player).Count() + empty - avalibleMoveDiffOffset, avalibleMoveTimeSlope); value += nonTurnableCoinDiffSlope * Math.Pow(game.GetSafePeiceCountEstimation(player) - game.GetSafePeiceCountEstimation(~player) + empty - nonTurnableCoinDiffOffset, nonTurnableTimeSlope); value += controlledCornerDiffSlope * Math.Pow(game.GetControlledCorners(player) - game.GetControlledCorners(~player) + empty - controlledCornerDiffOffset, controlledCornerTimeSlope); return(value); }
public void CtorThatPiecesSetUp() { var g = new OthelloGame(); g.board[3, 4].Should().Be(GamePiece.Black); g.board[3, 3].Should().Be(GamePiece.White); g.board[3, 2].Should().Be(GamePiece.Blank); }
public double Evaluate(IChromosome chromosome) {//Play n games vs a random (to be Neural Net), % win is Fitness FloatingPointChromosome myChromosome = (FloatingPointChromosome)chromosome; double[] genes = myChromosome.ToFloatingPoints(); double fitness = 0; double wonCount = 0; object wonCountLock = new object(); for (int index = 0; index < TEST_COUNT; index++) { //Parallel.For(0, TEST_COUNT, new ParallelOptions() { MaxDegreeOfParallelism = 2}, // (index) => { BoardStates player = (index % 2 == 0) ? BoardStates.black : BoardStates.white; OthelloGame othelloGame = new OthelloGame(); IEvaluationAgent heurAgent = new HeuristicAgent(genes); while (!othelloGame.GameComplete) { if (othelloGame.WhosTurn == player) { othelloGame.MakeMove(heurAgent.MakeMove(othelloGame, player)); } else { othelloGame.MakeMove(opposingAgent.MakeMove(othelloGame, ~player)); } } if (othelloGame.GameComplete)//just gotta check { if (othelloGame.FinalWinner == player) { lock (wonCountLock) { wonCount++; } } else if (othelloGame.FinalWinner == BoardStates.empty) { lock (wonCountLock) { wonCount += .5; } } } else { throw new Exception("EvaluationFitness didn't complete a game"); } // }); } fitness = (double)wonCount / TEST_COUNT; //System.Diagnostics.Debug.WriteLine("Fitness: " + fitness); return(fitness); }
public async Task ExecuteGroupAsync(CommandContext ctx, [Description("Move time (def. 30s).")] TimeSpan?movetime = null) { if (this.Shared.IsEventRunningInChannel(ctx.Channel.Id)) { throw new CommandFailedException("Another event is already running in the current channel!"); } await this.InformAsync(ctx, StaticDiscordEmoji.Question, $"Who wants to play Othello against {ctx.User.Username}?"); DiscordUser opponent = await ctx.WaitForGameOpponentAsync(); if (opponent == null) { return; } if (movetime?.TotalSeconds < 2 || movetime?.TotalSeconds > 120) { throw new InvalidCommandUsageException("Move time must be in range of [2-120] seconds."); } var game = new OthelloGame(ctx.Client.GetInteractivity(), ctx.Channel, ctx.User, opponent, movetime); this.Shared.RegisterEventInChannel(game, ctx.Channel.Id); try { await game.RunAsync(); if (game.Winner != null) { if (game.IsTimeoutReached) { await this.InformAsync(ctx, StaticDiscordEmoji.Trophy, $"{game.Winner.Mention} won due to no replies from opponent!"); } else { await this.InformAsync(ctx, StaticDiscordEmoji.Trophy, $"The winner is: {game.Winner.Mention}!"); } await this.Database.UpdateUserStatsAsync(game.Winner.Id, GameStatsType.OthellosWon); if (game.Winner.Id == ctx.User.Id) { await this.Database.UpdateUserStatsAsync(opponent.Id, GameStatsType.OthellosLost); } else { await this.Database.UpdateUserStatsAsync(ctx.User.Id, GameStatsType.OthellosLost); } } else { await this.InformAsync(ctx, StaticDiscordEmoji.Joystick, "A draw... Pathetic..."); } } finally { this.Shared.UnregisterEventInChannel(ctx.Channel.Id); } }
public PlayAgentForm() { InitializeComponent(); _myGame = new OthelloGame(); InitializeAgentSelectionComboBox(); InitializePlayerSelectionComboBox(); InitializeMinMaxSelectionComboBox(); SetGameCompleteVisuals(false); }
void Start() { OGD = othelloGameData.GetComponent <OthelloGame>(); for (int r = 0; r < 8; r++) { for (int l = 0; l < 8; l++) { othelloBoardDataBoard[r, l] = 0; } } }
private static byte[] OpeningMove(BoardStates player, OthelloGame game) {//avoid computation for first move - only one symmetric option //randomly select perpendicular or diagonal for second move - parallel //has been shown to be much worse //SPECIFIC TO 8x8 BOARDS byte[][] firstMoves = new byte[4][] { new byte[] { 2, 3 }, new byte[] { 3, 2 }, new byte[] { 4, 5 }, new byte[] { 5, 4 } }; if (game.GetPieceCount(BoardStates.empty) == 60) { Random rndGen = new Random(); int rand = (int)Math.Ceiling(rndGen.NextDouble() * 4); switch (rand) { case 1: return(firstMoves[0]); case 2: return(firstMoves[1]); case 3: return(firstMoves[2]); case 4: return(firstMoves[3]); default: throw new Exception("OpeningMove has faulted with random number generation"); } } if (game.GetPieceCount(BoardStates.empty) == 59) { List <byte[]> moves = game.GetPossiblePlayList(); Random rndGen = new Random(); byte rand = (byte)Math.Ceiling(rndGen.NextDouble() * 2); switch (rand) { case 1: //diagonal return(moves[0]); case 2: //perpendicular return(moves[0]); default: throw new Exception("Opening move has faulted with random number generation"); } } return(new byte[] { byte.MaxValue, byte.MaxValue }); }
private static int CompleteEval(BoardStates player, OthelloGame game) { ///Returns complete worth of board, -inf for loss, +inf for win if (game.FinalWinner == player) { return(int.MaxValue); } else { return(int.MinValue); } }
public override byte[] MakeMove(OthelloGame game, BoardStates player) { List <byte[]> possibleMoves = game.GetPossiblePlayList(player); if (possibleMoves.Count == 0) { return new byte[] { byte.MaxValue, byte.MaxValue } } ; Random rndGenerator = new Random(); int rnd = (int)Math.Floor(rndGenerator.NextDouble() * possibleMoves.Count); return(possibleMoves[rnd]); } }
// When player clicks restart. Resets the game state, hides the restart screen and removes all squares + pieces // to recreate them immediately after void buttonClicked() { Debug.Log("clicked button"); OthelloGame.ResetState(); restartScreen.SetActive(false); screenShown = false; GameObject baseBoard = GameObject.Find("Game_board"); Transform baseboardTransform = baseBoard.GetComponent <Transform>(); var children = new List <GameObject>(); foreach (Transform child in baseboardTransform) { children.Add(child.gameObject); } children.ForEach(child => Destroy(child)); baseBoard.GetComponent <CreateSquares>().InitSquares(); }
public async Task ExecuteGroupAsync(CommandContext ctx, [Description("desc-game-movetime")] TimeSpan?moveTime = null) { if (moveTime?.TotalSeconds is < 2 or > 120) { throw new InvalidCommandUsageException(ctx, "cmd-err-game-movetime", 2, 120); } if (this.Service.IsEventRunningInChannel(ctx.Channel.Id)) { throw new CommandFailedException(ctx, "cmd-err-evt-dup"); } DiscordUser?opponent = await ctx.WaitForGameOpponentAsync(); if (opponent is null) { throw new CommandFailedException(ctx, "cmd-err-game-op-none", ctx.User.Mention); } var game = new OthelloGame(ctx.Client.GetInteractivity(), ctx.Channel, ctx.User, opponent, moveTime); this.Service.RegisterEventInChannel(game, ctx.Channel.Id); try { await game.RunAsync(this.Localization); if (game.Winner is { }) { if (game.IsTimeoutReached) { await ctx.ImpInfoAsync(this.ModuleColor, Emojis.Trophy, "str-game-timeout", game.Winner.Mention); } else { await ctx.ImpInfoAsync(this.ModuleColor, Emojis.Trophy, "fmt-winners", game.Winner.Mention); } GameStatsService gss = ctx.Services.GetRequiredService <GameStatsService>(); await gss.UpdateStatsAsync(game.Winner.Id, s => s.OthelloWon++); await gss.UpdateStatsAsync(game.Winner == ctx.User?opponent.Id : ctx.User.Id, s => s.OthelloLost++); }
public override byte[] MakeMove(OthelloGame game, BoardStates player) { List <byte[]> moves = game.GetPossiblePlayList(player); double bestScore = double.MinValue; byte[] bestMove = new byte[] { byte.MaxValue, byte.MaxValue }; foreach (byte[] move in moves) { OthelloGame testGame = game.DeepCopy(); testGame.MakeMove(move); double thisScore = EvaluateBoard(testGame, player); if (thisScore > bestScore) { bestScore = thisScore; bestMove = move; } } return(bestMove); }
public override double EvaluateBoard(OthelloGame game, BoardStates player) { return(game.GetPieceCount(player)); }
public void MoveWhenOccupiedShouldReturnFalse() { var g = new OthelloGame(); g.Move(3, 3).Should().BeFalse(); }
public void MoveWhenNotOccupiedShouldReturnTrue() { var g = new OthelloGame(); g.Move(3, 5).Should().BeTrue(); }
// Detects touch input and also detects if this square object has been pressed. If yes, then adds the piece to the board // If piece is already on board but needs to change color, it is destroyed then recreated on the opposite side. // (THIS PART NEED TO BE ADJUSTED BOTH FOR ANIMATION AND CROSSHAIR STYLE OF PLAY) void Update() { List <string> validMoves = OthelloGame.validMoves; string[] square_num = gameObject.name.Split('_'); if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) // If touch is detected by user { Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position); RaycastHit rayhit = new RaycastHit(); if (Physics.Raycast(ray, out rayhit)) // If touch by user hit the square object { string hitObjectName = rayhit.transform.name; // Get the name of the square object hit if (placed == false && hitObjectName == gameObject.name && validMoves.Contains(square_num[1])) // If this square, no piece placed there and move on square is valid { GameObject hitObject = GameObject.Find(gameObject.name); // Almost same code below as Start() Transform hitObjectTransform = hitObject.GetComponent <Transform>(); if (OthelloGame.currentTurn == "black") { GameObject piece = Instantiate(pieceObj, hitObjectTransform); piece.transform.localRotation = Quaternion.Euler(0f, 0f, 180f); piece.transform.localPosition = new Vector3(piece.transform.localPosition.x, 4, piece.transform.localPosition.z); piece.name = "piece_" + square_num[1]; placed = true; OthelloGame.PlacePiece(square_num[1]); // Place piece in the board state (backend code) } else { GameObject piece = Instantiate(pieceObj, hitObjectTransform); piece.name = "piece_" + square_num[1]; placed = true; OthelloGame.PlacePiece(square_num[1]); } } } } if (placed == true && OthelloGame.piecesToConvert.Contains(square_num[1])) // If player has won this piece from opponent, convert it { StartCoroutine(sound()); // The sound starts as soon as every piece converts Vibration.Vibrate(OthelloGame.piecesToConvertLength * 50); // the vibrate starts as as soon as every piece converts var children = new List <GameObject>(); foreach (Transform child in transform) { children.Add(child.gameObject); // Add all children of square object to a temporary list } //children.ForEach(child => Destroy(child)); // Destroy piece to create new (if animation later, shouldn't destroy) if (OthelloGame.currentTurn == "white") { children.ForEach(child => child.GetComponent <PieceAnimate>().PieceFlipWtoB()); } if (OthelloGame.currentTurn == "black") { children.ForEach(child => child.GetComponent <PieceAnimate>().PieceFlipBtoW()); } OthelloGame.ApplyConvertOfPiece(square_num[1]); // Remove piece from state so the view only update once with the new one /* * GameObject squareObject = GameObject.Find(gameObject.name); * Transform squareObjectTransform = squareObject.GetComponent<Transform>(); * * if (OthelloGame.currentTurn == "white") * { * GameObject piece = Instantiate(pieceObj, squareObjectTransform); * piece.transform.localRotation = Quaternion.Euler(0f, 0f, 180f); * piece.transform.localPosition = new Vector3(piece.transform.localPosition.x, 4, piece.transform.localPosition.z); * piece.GetComponent<PieceAnimate>().PieceDropWhite(); // init drop piece animation * piece.name = "piece_" + square_num[1]; * placed = true; * * } * else if (OthelloGame.currentTurn == "black") * { * GameObject piece = Instantiate(pieceObj, squareObjectTransform); * * piece.name = "piece_" + square_num[1]; * piece.GetComponent<PieceAnimate>().PieceDropBlack(); // init drop piece animation * } */ } }
void Start() { board = transform.parent.GetComponent <OthelloGame>(); cell = transform.Find("Disk").GetComponent <Image>(); isBlack = false; }
public Computer(OthelloGame.eGameToken i_Token, OthelloGame i_Game) { r_ComputerToken = i_Token; m_TheGame = i_Game; m_MinimaxTree = new Minimax(m_TheGame.GameBoardSize); }
public abstract double EvaluateBoard(OthelloGame game, BoardStates player);