public override int getMove(Flower[] board) { const int INFINITY = 10000; int result = -INFINITY; Flower.FlowerType[] types = LogicUtils.getFlowerTypes(board); // figure out if this is our first move bool firstMove = true; for (int i = 0; i < types.Length; i++) { if (types[i] != Flower.FlowerType.None) { firstMove = false; break; } } if (firstMove) { result = base.generateMove(board); } else { int move; int bestMove = -INFINITY; int alpha = -INFINITY; int beta = INFINITY; Flower.FlowerType[] cloned; Winner winner; for (int i = 0; i < types.Length; i++) { if (types[i] == Flower.FlowerType.None) // only process empty nodes { cloned = LogicUtils.cloneFlowerTypes(types); // clone our board cloned[i] = LogicUtils.COMPUTERS_TYPE; // change this piece to the computers piece if (LogicUtils.isGameOver(cloned, out winner)) // check if this move puts the game into game over state { if (winner.winningType == LogicUtils.COMPUTERS_TYPE) // check if the computer wins { result = i; break; // we found a win so no need to continue looping } } move = miniMax(cloned, LogicUtils.PLAYERS_TYPE, alpha, beta); //run the algorithm if (move > bestMove) // interpret the results { result = i; bestMove = move; } } } } return(result); }
//Alpha: a score the computer knows with certanty it can achieve //Beta: a score the human knows with certanty it can achieve //If beta becomes <= alpha, further investigation is useless private int miniMax(Flower.FlowerType[] types, Flower.FlowerType turn, int alpha, int beta) { int bestMove; int move; Winner winner; if (LogicUtils.isGameOver(types, out winner)) { if (winner.winningType == LogicUtils.COMPUTERS_TYPE) { return(1); } else if (winner.winningType == LogicUtils.PLAYERS_TYPE) { return(-1); } else { return(0); } } else { if (LogicUtils.COMPUTERS_TYPE.Equals(turn)) { bestMove = alpha; } else { bestMove = beta; } Flower.FlowerType[] cloned = null; Flower.FlowerType inversedTurn = EnumUtils.inverseValue <Flower.FlowerType>(turn); for (int i = 0; i < types.Length; i++) { if (types[i] == Flower.FlowerType.None) // get valid moves { cloned = LogicUtils.cloneFlowerTypes(types); // get our result cloned[i] = turn; move = miniMax(cloned, inversedTurn, alpha, beta); // interpret our result if (LogicUtils.COMPUTERS_TYPE == turn) { if (move > alpha) { alpha = move; } if (alpha >= beta) { return(alpha); } } else { if (move < beta) { beta = move; } if (alpha >= beta) { return(beta); } } } } } if (turn == LogicUtils.COMPUTERS_TYPE) { return(alpha); } else { return(beta); } }
public override void update(float elapsed) { if (this.flowers != null) { foreach (Flower flower in this.flowers) { flower.update(elapsed); flower.updateColour(base.currentTransitionTime); } if (StateManager.getInstance().CurrentState == StateManager.GameState.InitGameOver) { StateManager.getInstance().CurrentState = StateManager.GameState.GameOver; } } if (this.computer != null) { this.computer.update(elapsed); this.computer.updateColour(base.currentTransitionTime); } if (this.player != null) { this.player.update(elapsed); this.player.updateColour(base.currentTransitionTime); } MouseState currentState = Mouse.GetState(); // accept input to the tiles if the game is running if (StateManager.getInstance().CurrentState == StateManager.GameState.Active) { if (StateManager.getInstance().WhosTurnIsIt == StateManager.TurnType.Players) { if (currentState.LeftButton == ButtonState.Pressed && base.previousMouseState.LeftButton == ButtonState.Released) // first press // find the tile we clicked { Vector2 mousePos = new Vector2(currentState.X, currentState.Y); Flower flower = null; for (int i = 0; i < this.flowers.Length; i++) { flower = this.flowers[i]; if (flower.Type == Flower.FlowerType.None) { if (PickingUtils.pickRectangle(mousePos, FlowerBuilder.SpritePositioner.getInstance().getPositionsRectangle(flower.Index))) { if (StateManager.getInstance().WhosTurnIsIt == StateManager.TurnType.Players) { SoundManager.getInstance().SFXEngine.playSoundEffect(this.diggingSFX); flower.initSprites(this.player); StateManager.getInstance().WhosTurnIsIt = StateManager.TurnType.Computers; this.currentDelay = 0f; } /*else {// player two if we implement it * flower.initSprites(Flower.FlowerType.Daisy, this.computersAliveTexture, this.computersDyingTexture); * StateManager.getInstance().WhosTurnIsIt = StateManager.TurnType.Players; * }*/ break; } } } } } else if (StateManager.getInstance().WhosTurnIsIt == StateManager.TurnType.Computers) { if (this.currentDelay >= DELAY) { int move = StateManager.getInstance().ActiveDifficulty.getMove(this.flowers); SoundManager.getInstance().SFXEngine.playSoundEffect(this.diggingSFX); this.flowers[move].initSprites(this.computer); StateManager.getInstance().WhosTurnIsIt = StateManager.TurnType.Players; } } Winner winner; if (LogicUtils.isGameOver(this.flowers, out winner)) { StateManager.getInstance().CurrentState = StateManager.GameState.InitGameOver; StateManager.getInstance().Winner = winner; if (winner.winningType == LogicUtils.COMPUTERS_TYPE) { this.computer.Score++; } else if (winner.winningType == LogicUtils.PLAYERS_TYPE) { this.player.Score++; } } } else if (StateManager.getInstance().CurrentState == StateManager.GameState.GameOver) { Vector2 mousePos = new Vector2(Mouse.GetState().X, Mouse.GetState().Y); this.replayButton.processActorsMovement(mousePos); if (this.replayButton.isActorOver(mousePos)) { if (currentState.LeftButton == ButtonState.Pressed && base.previousMouseState.LeftButton == ButtonState.Released) // first press { reset(false); } } } if (StateManager.getInstance().CurrentTransitionState != StateManager.TransitionState.None) { Vector2 mousePos = new Vector2(Mouse.GetState().X, Mouse.GetState().Y); if (StateManager.getInstance().CurrentTransitionState == StateManager.TransitionState.TransitionIn) { if (this.replayButton.isActorOver(mousePos)) { ((ColouredButton)this.replayButton).updateColours(base.fadeIn(ResourceManager.getInstance().ButtonsMouseOverColour)); } else { ((ColouredButton)this.replayButton).updateColours(base.fadeIn(ResourceManager.getInstance().TextColour)); } } else if (StateManager.getInstance().CurrentTransitionState == StateManager.TransitionState.TransitionOut) { if (this.replayButton.isActorOver(mousePos)) { ((ColouredButton)this.replayButton).updateColours(base.fadeOut(ResourceManager.getInstance().ButtonsMouseOverColour)); } else { ((ColouredButton)this.replayButton).updateColours(base.fadeOut(ResourceManager.getInstance().TextColour)); } } // if the fade ins/outs are complete we change the state if (base.transitionTimeElapsed()) { if (StateManager.getInstance().CurrentTransitionState == StateManager.TransitionState.TransitionIn) { StateManager.getInstance().CurrentTransitionState = StateManager.TransitionState.None; } else if (StateManager.getInstance().CurrentTransitionState == StateManager.TransitionState.TransitionOut) { // we need to transition in our in game menu screen StateManager.getInstance().CurrentTransitionState = StateManager.TransitionState.TransitionIn; } } } // At any time if we press escape we need to go to the in game menu if (Keyboard.GetState().IsKeyDown(Keys.Escape) && base.previousKeyboardState.IsKeyUp(Keys.Escape)) { StateManager.getInstance().CurrentState = StateManager.GameState.InGameMenu; StateManager.getInstance().CurrentTransitionState = StateManager.TransitionState.TransitionOut; } if (StateManager.getInstance().CurrentState == StateManager.GameState.Active) { this.currentDelay += elapsed; } base.update(elapsed); }