public void makeAiMove() { // System.out.println("Presenter makeAiMove"); if (state.isGameOver()) { return; } AlphaBetaPruning ai = new AlphaBetaPruning(new Heuristic()); Integer aiMove = ai.findBestMove(state, 5, new DateTimer(3000)); System.out.println("P MAIM state: " + state); System.out.println("P MAIM move: " + aiMove); State oldState = state.copyState(); stateToSetAfterAnimation = state.copyState(); stateToSetAfterAnimation.makeMove(aiMove); makeAnimatedMove(aiMove, oldState); // state.makeMove(aiMove); System.out.println("State after Move: " + state); // setState(state); // graphics.sendMoveToServerAI(aiMove, state); // this will be made in the graphics after the move was saved // if (state.getWhoseTurn().equals(usersSide.getOpposite())) // makeAiMove(); }
/** It enables only the pits from the player whose turn it is */ void enableActiveSide() { boolean enableNorth; boolean enableSouth; if (usersSide == null) { // sideTheUserIs is not yet initialized enableNorth = false; enableSouth = false; } else if (state.getWhoseTurn().isNorth() && usersSide.isNorth()) { enableNorth = true; enableSouth = false; } else if (state.getWhoseTurn().isNorth() && usersSide.isSouth()) { enableNorth = false; enableSouth = false; } else if (state.getWhoseTurn().isSouth() && usersSide.isSouth()) { enableNorth = false; enableSouth = true; } else { enableNorth = false; enableSouth = false; } for (int i = 0; i < state.getNorthPits().length - 1; i++) { graphics.setPitEnabled(PlayerColor.N, i, enableNorth); graphics.setPitEnabled(PlayerColor.S, i, enableSouth); } }
public void afterAnimation() { if (stateToSetAfterAnimation.getLastMoveWasOppositeCapture()) graphics.oppositeCaptureSound(); state = stateToSetAfterAnimation.copyState(); updateBoard(); if (aiMatch) sendMoveToServerAI(lastMove, state); }
/** When there are zero seeds in a pit it can't be chosen either so disable them */ void disableZeroSeedPits() { int[] activePits = new int[7]; if (state.getWhoseTurn().isNorth()) activePits = state.getNorthPits(); else activePits = state.getSouthPits(); // state.getNorthPits().length-1 because the last array field is the // treasure chest for (int i = 0; i < state.getNorthPits().length - 1; i++) { if (activePits[i] == 0) graphics.setPitEnabled(state.getWhoseTurn(), i, false); } }
/** Set a message in the case of game over */ void message() { if (state.isGameOver()) { graphics.gameOverSound(); String msg = ""; if (state.winner() == null) { msg = messages.tie(); } else { String winner = state.winner().isNorth() ? "North" : "South"; msg = messages.winnerIs(winner, state.score() + ""); } graphics.setMessage(msg); publish(msg); } }
/** * After the user clicked on a pit the seeds should be distributed in an animated fashion * * @param chosenPitIndex the index the user chose to distribute the seeds from * @param oldState the state before the user chose his pit */ void makeAnimatedMove(int chosenPitIndex, State oldState) { // disable board until the animation is over disableBoard(); state.makeMove(chosenPitIndex); PlayerColor whoseTurn = oldState.getWhoseTurn(); PlayerColor sideToPlaceSeedOn = whoseTurn; int seedAmount = oldState.getPitsOfWhoseTurn()[chosenPitIndex]; boolean lastAnimation = false; int indexToPlaceSeedIn = chosenPitIndex; int maxIndex = 6; for (int i = 1; i <= seedAmount; i++) { indexToPlaceSeedIn++; maxIndex = whoseTurn.equals(sideToPlaceSeedOn) ? 6 : 5; if ((indexToPlaceSeedIn) > maxIndex) { sideToPlaceSeedOn = sideToPlaceSeedOn.getOpposite(); indexToPlaceSeedIn = 0; } if (i == seedAmount) lastAnimation = true; graphics.animateFromPitToPit( whoseTurn, chosenPitIndex, sideToPlaceSeedOn, indexToPlaceSeedIn, 400 * (i - 1), lastAnimation); } if (this.state.getLastMoveWasOppositeCapture()) { // graphics.oppositeCaptureSound(); // TODO: give this it's own animation // //int[] opposingPits = whoseTurn.isNorth() ? // this.state.getSouthPits() : state.getNorthPits(); // int seedAmountInOpposingPit = this.state.getOppositeSeeds(); // // graphics.animateFromPitToPit(whoseTurn, indexToPlaceSeedIn, // whoseTurn, 6, seedAmount * 400 + 1400); // for(int i = 0; i < seedAmountInOpposingPit; i++) // graphics.animateFromPitToPit(whoseTurn.getOpposite(), // State.getMirrorIndex(indexToPlaceSeedIn, 5), whoseTurn, 6, // seedAmount * 400 + 1000 + 400 * i); } }
/** makes a move on the model, adds the new state to the history and updates the board */ void makeMove(int index) { try { lastMove = index; if (aiMatch) { stateToSetAfterAnimation = state.copyState(); stateToSetAfterAnimation.makeMove(index); makeAnimatedMove(index, state.copyState()); } else { State stateCopy = state.copyState(); stateCopy.makeMove(index); sendMoveToServer(index, State.serialize(stateCopy)); } // State oldState = state.copyState(); // // stateToSetAfterAnimation = state.copyState(); // stateToSetAfterAnimation.makeMove(index); // state.makeMove(index); // sendMoveToServer() is called by the graphics class after the animation is done // makeAnimatedMove(index, oldState); } catch (IllegalMoveException e) { graphics.setMessage(messages.newGameBecauseError() + e); setState(new State()); } catch (GameOverException e) { graphics.setMessage(messages.newGameBecauseError() + e); setState(new State()); } }
public void clearBoard() { // update pits for (int i = 0; i < state.getNorthPits().length; i++) { graphics.setSeeds(PlayerColor.N, i, 0); graphics.setSeeds(PlayerColor.S, i, 0); } // disable pits disableBoard(); }
/** * Updates all elements that are necessary after the state changed 1. Update all the seedAmounts * in the pits after a move was made 2. It enables only the pits from the player whose turn it is * 3. When there are zero seeds in a pit it can't be chosen either so disable them 4. Set a * message in the case of game over */ void updateBoard() { if (usersSide == null) graphics.setTurnLabelText(messages.startNewGame()); else { graphics.setTurnLabelText( state.getWhoseTurn().equals(usersSide) ? messages.itsYourTurn() : messages.opponentsTurn()); } updatePits(); enableActiveSide(); disableZeroSeedPits(); message(); }
/** * A player can only select certain pits for their move. That's why some have to be enabled and * some have to be disabled before a player's turn. */ @Override public void setPitEnabled(PlayerColor side, int col, boolean enabled) { AbsolutePanel pnl; if (col < 6) { if (side.isNorth()) { pnl = (AbsolutePanel) gameGrid.getWidget(0, State.getMirrorIndex(col, 5)); } else if (side.isSouth()) { pnl = (AbsolutePanel) gameGrid.getWidget(1, col); } else throw new IllegalMoveException(); final int colB = col; int row = side.isNorth() ? 0 : 1; if (enabled) { // the handerRegs keeps track of all click handlers of the pits // by removing it from this array the handler is removed from // the pit (absolutePanel) as well handlerRegs[row][col].removeHandler(); handlerRegs[row][col] = pnl.addDomHandler( new ClickHandler() { @Override public void onClick(ClickEvent event) { presenter.makeMove(colB); } }, ClickEvent.getType()); } else { handlerRegs[row][col].removeHandler(); handlerRegs[row][col] = pnl.addDomHandler( new ClickHandler() { @Override public void onClick(ClickEvent event) { setWarnLabelText(messages.warnMessage()); } }, ClickEvent.getType()); } } }
/** The seedAmount will be placed on the right side at the correct index */ @Override public void setSeeds(PlayerColor side, int col, int seedAmount) { if (col < 6) { AbsolutePanel pnl; if (side.isNorth()) { pnl = (AbsolutePanel) gameGrid.getWidget(0, State.getMirrorIndex(col, 5)); } else if (side.isSouth()) { pnl = (AbsolutePanel) gameGrid.getWidget(1, col); } else throw new IllegalMoveException(); addSeeds(pnl, seedAmount); } else if (col == 6) { AbsolutePanel pnl; if (side.isNorth()) { pnl = (AbsolutePanel) treasureGridN.getWidget(0, 0); } else if (side.isSouth()) { pnl = (AbsolutePanel) treasureGridS.getWidget(0, 0); } else throw new IllegalMoveException(); addSeedsToTreasureChest(pnl, seedAmount); } else throw new IllegalMoveException(); }
public void sendMoveToServer(Integer chosenIndex, String stateString) { final Integer fChosenIndex = chosenIndex; final String fStateString = stateString; if (aiMatch) { sendMoveToServerAI(chosenIndex, State.deserialize(stateString)); return; } // secured against xsrf attacks // see http://www.gwtproject.org/doc/latest/DevGuideSecurityRpcXsrf.html XsrfTokenServiceAsync xsrf = (XsrfTokenServiceAsync) GWT.create(XsrfTokenService.class); ((ServiceDefTarget) xsrf).setServiceEntryPoint(GWT.getModuleBaseURL() + "gwt/xsrf"); xsrf.getNewXsrfToken( new AsyncCallback<XsrfToken>() { public void onSuccess(XsrfToken token) { ((HasRpcToken) mancalaService).setRpcToken(token); mancalaService.makeMove( userId, matchId, fChosenIndex, fStateString, new AsyncCallback<Void>() { @Override public void onFailure(Throwable caught) { Window.alert("Server error!"); } @Override public void onSuccess(Void result) { // updateMatchList(); } }); } public void onFailure(Throwable caught) { Window.alert("Error retrieving xsrf token! Please try again later."); } }); }
/** Update all the seedAmounts in the pits after a move was made */ private void updatePits() { for (int i = 0; i < state.getNorthPits().length; i++) { graphics.setSeeds(PlayerColor.N, i, state.getNorthPits()[i]); graphics.setSeeds(PlayerColor.S, i, state.getSouthPits()[i]); } }
public void disableBoard() { for (int i = 0; i < state.getNorthPits().length - 1; i++) { graphics.setPitEnabled(PlayerColor.N, i, false); graphics.setPitEnabled(PlayerColor.S, i, false); } }