Android Open Source - it.alcacoop.fourinaline F S M






From Project

Back to project page it.alcacoop.fourinaline.

License

The source code is released under:

GNU General Public License

If you think the Android project it.alcacoop.fourinaline listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 ##################################################################
 #                     FOUR IN A LINE MOBILE                      #
 ##################################################################
 #                                                                #
 #  Authors: Domenico Martella - Francesco Valente                #
 #  E-mail: info@alcacoop.it                                      #
 #  Date:   18/10/2013                                            #
 #                                                                #
 ##################################################################
 #                                                                #
 #  Copyright (C) 2013   Alca Societa' Cooperativa                #
 #                                                                #
 #  This file is part of FOUR IN A LINE MOBILE.                   #
 #  FOUR IN A LINE MOBILE is free software: you can redistribute  # 
 #  it and/or modify it under the terms of the GNU General        #
 #  Public License as published by the Free Software Foundation,  #
 #  either version 3 of the License, or (at your option)          #
 #  any later version.                                            #
 #                                                                #
 #  FOUR IN A LINE MOBILE is distributed in the hope that it      #
 #  will be useful, but WITHOUT ANY WARRANTY; without even the    #
 #  implied warranty of MERCHANTABILITY or FITNESS FOR A          #
 #  PARTICULAR PURPOSE.  See the GNU General Public License       #
 #  for more details.                                             #
 #                                                                #
 #  You should have received a copy of the GNU General            #
 #  Public License v3 along with this program.                    #
 #  If not, see <http://http://www.gnu.org/licenses/>             #
 #                                                                #
 ##################################################################
 **///from ww  w . j a  v  a  2s.co m

/**
 @startuml
 null --> MAIN_MENU
 MAIN_MENU --> MAIN_MENU : BUTTON_CLICKED
 MAIN_MENU --> MATCH_OPTIONS
 MATCH_OPTIONS --> MATCH_OPTIONS : BUTTON_CLICKED
 MATCH_OPTIONS --> INIT_GAME
 INIT_GAME --> INIT_GAME : START_GAME
 INIT_GAME --> LOCAL_TURN
 LOCAL_TURN --> LOCAL_TURN : CLICKED_COL
 LOCAL_TURN --> LOCAL_TURN : MOVE_END
 LOCAL_TURN --> AI_TURN
 AI_TURN --> AI_TURN : AI_EVALUETED
 AI_TURN --> AI_TURN : MOVE_END
 AI_TURN --> LOCAL_TURN
 LOCAL_TURN --> CHECK_END_MATCH
 CHECK_END_MATCH --> CHECK_END_MATCH : GAME_TERMINATED
 CHECK_END_MATCH --> CHECK_END_MATCH : BOARD_RESETTED
 CHECK_END_MATCH --> MAIN_MENU
 @enduml
 *
 * Result of:
 * $> grep -i "PLANTUML" fsm_single | sed 's/PLANTUML://'
 * on the output
 */

// SIMULATED GAME STATE MACHINE
// From: http://vanillajava.blogspot.com/2011/06/java-secret-using-enum-as-state-machine.html

package it.alcacoop.fourinaline.fsm;

import it.alcacoop.fourinaline.FourInALine;
import it.alcacoop.fourinaline.actors.UIDialog;
import it.alcacoop.fourinaline.fsm.FSM.Events;
import it.alcacoop.fourinaline.gservice.GServiceClient;
import it.alcacoop.fourinaline.gservice.GServiceMessages;
import it.alcacoop.fourinaline.layers.GameScreen;
import it.alcacoop.fourinaline.logic.MatchState;
import it.alcacoop.fourinaline.utils.AchievementsManager;
import it.alcacoop.fourinaline.utils.ELORatingManager;

import java.util.Random;

import org.gojul.fourinaline.model.AlphaBeta;

import com.badlogic.gdx.Gdx;


interface Context {
  State state();

  void state(State state);
}

interface State {
  boolean processEvent(Context ctx, Events evt, Object params);

  void enterState(Context ctx);

  void exitState(Context ctx);
}


// MAIN FSM
public class FSM implements Context {

  private static long waitTime;

  public enum Events {
    NOOP, RESIGN_GAME, BUTTON_CLICKED, GAME_TERMINATED, BOARD_RESETTED, MOVE_END, CLICKED_COL, AI_EVALUETED, START_GAME, LEAVE_GAME, LEAVE_MATCH, GSERVICE_READY, GSERVICE_INIT_RATING, GSERVICE_HANDSHAKE, GSERVICE_BYE, GSERVICE_MOVES, PERFORMED_MOVE, GSERVICE_ABANDON, OPPONENT_LEAVE_OR_RESIGN, GSERVICE_ERROR, GSERVICE_CHATMSG
  }

  public enum States implements State {

    MAIN_MENU {
      @Override
      public void enterState(Context ctx) {
        FourInALine.Instance.setScreen(FourInALine.Instance.menuScreen);
        String invitationId = FourInALine.Instance.nativeFunctions.gservicePendingNotificationAreaInvitation();
        if (!invitationId.equals("")) {
          FourInALine.Instance.nativeFunctions.gserviceAcceptInvitation(invitationId);
        }
      }

      @Override
      public boolean processEvent(Context ctx, Events evt, Object params) {
        switch (evt) {
          case LEAVE_GAME:
            if ((Boolean)params)
              Gdx.app.exit();
            break;
          case BUTTON_CLICKED:
            String btn = ((String)params);

            FourInALine.Instance.snd.playButton();
            FourInALine.Instance.vibrate(80);

            if (btn.equals("SINGLE PLAYER")) {
              MatchState.matchType = 0;
              FourInALine.Instance.fsm.state(States.MATCH_OPTIONS);
            } else if (btn.equals("TWO PLAYERS")) {
              MatchState.matchType = 1;
              FourInALine.Instance.fsm.state(States.MATCH_OPTIONS);
            } else if (btn.equals("ONLINE MULTIPLAYER")) {
              if (FourInALine.Instance.nativeFunctions.isNetworkUp()) {
                MatchState.matchType = 2;
                FourInALine.Instance.nativeFunctions.gserviceStartRoom();
              } else {
                UIDialog.getFlashDialog(Events.NOOP, "Network is down - Multiplayer not available");
              }
            } else if (btn.equals("OPTIONS")) {
              FourInALine.Instance.fsm.state(States.GAME_OPTIONS);
            } else if (btn.equals("ABOUT..")) {
              UIDialog.getAboutDialog();
            } else if (btn.equals("REMOVE ADS")) {
              FourInALine.Instance.nativeFunctions.inAppBilling();
            } else if (btn.equals("RATE IT!")) {
              FourInALine.Instance.nativeFunctions.openURL("https://play.google.com/store/apps/details?id=it.alcacoop.fourinaline");
            }

            break;
          default:
            return false;
        }
        return true;
      }
    },


    GAME_OPTIONS {
      @Override
      public void enterState(Context ctx) {
        FourInALine.Instance.setScreen(FourInALine.Instance.optionsScreen);
      }

      @Override
      public boolean processEvent(Context ctx, Events evt, Object params) {
        switch (evt) {
          case BUTTON_CLICKED:
            String btn = ((String)params);
            if (btn.equals("BACK")) {
              FourInALine.Instance.fsm.back();
            }
            break;
          default:
            return false;
        }
        return true;
      }
    },


    MATCH_OPTIONS {
      @Override
      public void enterState(Context ctx) {
        FourInALine.Instance.setScreen(FourInALine.Instance.matchOptionsScreen);
      }

      @Override
      public boolean processEvent(Context ctx, Events evt, Object params) {
        switch (evt) {
          case BUTTON_CLICKED:
            String btn = ((String)params);
            if (btn.equals("BACK")) {
              FourInALine.Instance.fsm.back();
            } else if (btn.equals("PLAY")) {
              MatchState.firstGame = true;
              FourInALine.Instance.fsm.state(States.INIT_GAME);
            }
            break;
          default:
            return false;
        }
        return true;
      }
    },


    INIT_GAME {
      @Override
      public void enterState(Context ctx) {
        if (MatchState.matchType == 2) {
          FourInALine.Instance.setScreen(FourInALine.Instance.gameScreen);
          FourInALine.Instance.board.initMatch(MatchState.whoStart);
        } else {
          int[] a = { 1, 2 };
          if (MatchState.firstGame) {
            FourInALine.Instance.setScreen(FourInALine.Instance.gameScreen);
            MatchState.whoStart = new Random().nextInt(2) + 1;
          } else {
            MatchState.whoStart = ((MatchState.whoStart - 1) == 0) ? a[1] : a[0];
          }
          FourInALine.Instance.board.initMatch(MatchState.whoStart);
        }
        super.enterState(ctx);
      }

      @Override
      public boolean processEvent(Context ctx, Events evt, Object params) {
        if (evt == Events.START_GAME) {
          System.out.println("WHO: " + MatchState.whoStart);
          switch (MatchState.matchType) {
            case -1: // SIMULATION
              FourInALine.Instance.fsm.state(AI_TURN);
              break;
            case 0: // SINGLE PLAYER
              ELORatingManager.getInstance().setRatings(AlphaBeta.ratings[MatchState.AILevel - 1]);
              if (MatchState.whoStart == 1)
                FourInALine.Instance.fsm.state(LOCAL_TURN);
              else
                FourInALine.Instance.fsm.state(AI_TURN);
              break;
            case 1: // TWO PLAYER
              FourInALine.Instance.fsm.state(LOCAL_TURN);
              break;
            case 2: // MULTIPLAYER
              if (MatchState.whoStart == 1)
                FourInALine.Instance.fsm.state(LOCAL_TURN);
              else
                FourInALine.Instance.fsm.state(REMOTE_TURN);
              break;
            default:
              break;
          }
          return true;
        }
        return false;
      }
    },


    LOCAL_TURN {
      @Override
      public void enterState(Context ctx) {
        if (MatchState.winner == -1) {
          FourInALine.Instance.gameScreen.highlightPlayer(MatchState.currentPlayer);
        }
        FourInALine.Instance.gameScreen.showThinking(false);
      }

      @Override
      public boolean processEvent(Context ctx, Events evt, Object params) {
        switch (evt) {
          case CLICKED_COL:
            FourInALine.Instance.board.play((Integer)params);
            break;

          case MOVE_END:
            if (MatchState.matchType == 0)
              FourInALine.Instance.fsm.state(AI_TURN);
            else if (MatchState.matchType == 1)
              FourInALine.Instance.fsm.state(LOCAL_TURN);
            else if (MatchState.matchType == 2) {
              int col = (Integer)params;
              FourInALine.Instance.fsm.state(REMOTE_TURN);
              GServiceClient.getInstance().sendMessage("6 " + col);
            }
            break;

          case LEAVE_MATCH:
            // LEAVE MATCH
            if ((Boolean)params) {
              MatchState.nMatchTo = 0; // DIRTY HACK
              FourInALine.Instance.fsm.state(CHECK_END_MATCH);

              if (MatchState.matchType == 2) {
                GServiceClient.getInstance().sendMessage(GServiceMessages.GSERVICE_ABANDON + " 1");
                FourInALine.Instance.fsm.processEvent(Events.GAME_TERMINATED, null);
              } else {
                FourInALine.Instance.fsm.processEvent(Events.GAME_TERMINATED, null);
              }
            }
            break;
          case RESIGN_GAME:
            // RESIGN MATCH
            if ((Boolean)params) {
              MatchState.nMatchTo = 0; // DIRTY HACK
              FourInALine.Instance.fsm.state(CHECK_END_MATCH);

              if (MatchState.matchType == 2) {
                GServiceClient.getInstance().sendMessage(GServiceMessages.GSERVICE_ABANDON + " 2");
                FourInALine.Instance.fsm.processEvent(Events.GAME_TERMINATED, null);
              } else {
                FourInALine.Instance.fsm.processEvent(Events.GAME_TERMINATED, null);
              }
            }
            break;
          case OPPONENT_LEAVE_OR_RESIGN:
            int abandonOrResign = (Integer)params;
            MatchState.nMatchTo = 0; // DIRTY HACK
            FourInALine.Instance.gameScreen.highlightPlayer(0);
            FourInALine.Instance.fsm.state(CHECK_END_MATCH);
            if (abandonOrResign == 1) {
              UIDialog.getFlashDialog(Events.GAME_TERMINATED, "Opponent abandoned match");
            } else {
              UIDialog.getFlashDialog(Events.GAME_TERMINATED, "Opponent resigned a game");
            }
            FourInALine.Instance.nativeFunctions.gserviceResetRoom();
            break;

          default:
            return false;
        }
        return true;
      }

    },

    REMOTE_TURN {
      @Override
      public void enterState(Context ctx) {
        FourInALine.Instance.gameScreen.showThinking(true);
        if (MatchState.winner == -1) {
          FourInALine.Instance.gameScreen.highlightPlayer(MatchState.currentPlayer);
          GServiceClient.getInstance().queue.pull(Events.GSERVICE_MOVES);
        }
      }

      @Override
      public boolean processEvent(Context ctx, Events evt, Object params) {
        switch (evt) {
          case GSERVICE_MOVES:
            int col = (Integer)params;
            FourInALine.Instance.board.play((Integer)col);
            break;

          case PERFORMED_MOVE:
            // ctx.board().updatePInfo();
            // ctx.board().performNextMove();
            break;

          case MOVE_END:
            FourInALine.Instance.fsm.state(LOCAL_TURN);
            break;

          case LEAVE_MATCH:
            // LEAVE MATCH
            if ((Boolean)params) {
              MatchState.nMatchTo = 0; // DIRTY HACK
              FourInALine.Instance.fsm.state(CHECK_END_MATCH);
              GServiceClient.getInstance().sendMessage(GServiceMessages.GSERVICE_ABANDON + " 1");
              FourInALine.Instance.fsm.processEvent(Events.GAME_TERMINATED, null);
            }
            break;
          case RESIGN_GAME:
            // RESIGN MATCH
            if ((Boolean)params) {
              MatchState.nMatchTo = 0; // DIRTY HACK
              FourInALine.Instance.fsm.state(CHECK_END_MATCH);
              GServiceClient.getInstance().sendMessage(GServiceMessages.GSERVICE_ABANDON + " 2");
              FourInALine.Instance.fsm.processEvent(Events.GAME_TERMINATED, null);
            }
            break;

          default:
            return false;
        }

        return true;
      }
    },

    AI_TURN {
      @Override
      public void enterState(Context ctx) {
        FourInALine.Instance.gameScreen.showThinking(true);
        if (MatchState.winner == -1) {
          FourInALine.Instance.gameScreen.highlightPlayer(MatchState.currentPlayer);
          FourInALine.Instance.board.playAI();
        }
      }

      @Override
      public boolean processEvent(Context ctx, Events evt, Object params) {
        switch (evt) {
          case AI_EVALUETED:
            FourInALine.Instance.board.play((Integer)params);
            break;

          case MOVE_END:
            if (MatchState.matchType == -1)
              FourInALine.Instance.fsm.state(AI_TURN);
            else
              FourInALine.Instance.fsm.state(LOCAL_TURN);
            break;

          case LEAVE_MATCH:
            // LEAVE MATCH
            if ((Boolean)params) {
              MatchState.nMatchTo = 0; // DIRTY HACK
              FourInALine.Instance.fsm.state(CHECK_END_MATCH);
              FourInALine.Instance.fsm.processEvent(Events.GAME_TERMINATED, null);
            }
            break;
          case RESIGN_GAME:
            // RESIGN MATCH
            if ((Boolean)params) {
              MatchState.nMatchTo = 0; // DIRTY HACK
              FourInALine.Instance.fsm.state(CHECK_END_MATCH);
              FourInALine.Instance.fsm.processEvent(Events.GAME_TERMINATED, null);
            }
            break;

          default:
            return false;
        }

        return true;
      }
    },

    GSERVICE {
      @Override
      public void enterState(Context ctx) {
        GServiceClient.getInstance().queue.reset();
        MatchState.anScore[0] = 0;
        MatchState.anScore[1] = 0;
        MatchState.nMatchTo = 1;

        GServiceClient.getInstance().sendMessage("2");
        GServiceClient.getInstance().queue.pull(Events.GSERVICE_READY);
      }

      @Override
      public boolean processEvent(Context ctx, Events evt, Object params) {
        switch (evt) {
          case GSERVICE_READY:
            GServiceClient.getInstance().sendMessage("8 " + FourInALine.Instance.gameOptionPrefs.getString("multiboard", "0"));
            GServiceClient.getInstance().queue.pull(Events.GSERVICE_INIT_RATING);
            break;

          case GSERVICE_INIT_RATING:
            double opponentRating = (Double)params;
            ELORatingManager.getInstance().setRatings(opponentRating);

            Random gen = new Random();
            waitTime = gen.nextLong();
            GServiceClient.getInstance().sendMessage("3 " + waitTime + " " + FourInALine.Instance.nativeFunctions.getAppVersionCode());
            GServiceClient.getInstance().queue.pull(Events.GSERVICE_HANDSHAKE);
            break;

          case GSERVICE_HANDSHAKE:
            long remoteWaitTime = (Long)params;
            if (waitTime < remoteWaitTime) {
              // Tocca a Local Turn
              MatchState.whoStart = 1;
              MatchState.currentPlayer = 1;
            } else {
              MatchState.whoStart = 2;
              MatchState.currentPlayer = 2;
            }
            FourInALine.Instance.fsm.state(States.INIT_GAME);
            FourInALine.Instance.fsm.processEvent(Events.START_GAME, null);
            break;

          default:
            return false;
        }
        return true;
      }
    },

    CHECK_END_MATCH {
      @Override
      public void enterState(Context ctx) {
        FourInALine.Instance.gameScreen.showThinking(false);
      }

      @Override
      public boolean processEvent(Context ctx, Events evt, Object params) {
        switch (evt) {
          case GAME_TERMINATED:
            FourInALine.Instance.board.reset();
            break;
          case BOARD_RESETTED:
            if (MatchState.winner == 1) {
              AchievementsManager.getInstance().checkAchievements(true);
              ELORatingManager.getInstance().updateRating(true);
            }

            if (MatchState.matchType == 2) {
              FourInALine.Instance.nativeFunctions.gserviceResetRoom();
              FourInALine.Instance.fsm.state(States.MAIN_MENU);
            } else {
              MatchState.mCount = 0;
              if ((MatchState.anScore[0] < MatchState.nMatchTo) && (MatchState.anScore[1] < MatchState.nMatchTo)) {
                MatchState.firstGame = false;
                FourInALine.Instance.fsm.state(States.INIT_GAME);
                FourInALine.Instance.fsm.processEvent(Events.START_GAME, null);
              } else {
                FourInALine.Instance.fsm.state(States.MAIN_MENU);
              }
            }
            break;
          default:
            return false;
        }
        return true;
      }
    },

    STOPPED {
      @Override
      public void enterState(Context ctx) {
      }
    };

    // DEFAULT IMPLEMENTATION
    public boolean processEvent(Context ctx, FSM.Events evt, Object params) {
      return false;
    }

    public void enterState(Context ctx) {
    }

    public void exitState(Context ctx) {
    }

  };

  public State currentState;
  public State previousState;


  public void start() {
    state(States.MAIN_MENU);
  }

  public void stop() {
    state(States.STOPPED);
  }

  public void restart() {
    stop();
    start();
  }

  public void processEvent(final Events evt, final Object params) {
    final FSM ctx = this;
    // System.out.println("PROCESS " + evt + " ON " + state());
    System.out.println("PLANTUML:" + currentState + " --> " + state() + " : " + evt);
    Gdx.app.postRunnable(new Runnable() {
      @Override
      public void run() {
        switch (evt) {
          case GSERVICE_CHATMSG:
            FourInALine.Instance.snd.playMessage();
            ((GameScreen)FourInALine.Instance.currentScreen).chatBox.appendMessage("Opponent", (String)params, false);
            break;

          case GSERVICE_ERROR:
            // Se la partita in corso
            if (MatchState.winner == -1) {
              int errorCode = (Integer)params;
              String message = "";
              switch (errorCode) {
                case 0:
                  message = "Network error: opponent disconnected!";
                  break;
                case 1:
                  message = "Network Error: you disconnected!";
                  break;
                case 2:
                  message = "Match stopped. You have to reinvite!";
                  break;
              }
              if (FourInALine.Instance.currentScreen instanceof GameScreen) {
                ctx.state(States.CHECK_END_MATCH);
                UIDialog.getFlashDialog(Events.GAME_TERMINATED, message);
              }
            }
            break;
          case GSERVICE_BYE:
            // ctx.state(States.MAIN_MENU);
            break;

          default:
            state().processEvent(ctx, evt, params);
            break;
        }
      }
    });
  }

  public State state() {
    return currentState;
  }

  public void back() {
    if (previousState != null)
      state(previousState);
  }

  public void state(State state) {
    System.out.println("PLANTUML:" + currentState + " --> " + state);
    if (currentState != null)
      currentState.exitState(this);
    previousState = currentState;
    currentState = state;
    if (currentState != null)
      currentState.enterState(this);
  }

  public boolean isStopped() {
    return currentState == States.STOPPED;
  }
}




Java Source Code List

android.UnusedStub.java
it.alcacoop.fourinaline.BaseGServiceApplication.java
it.alcacoop.fourinaline.FourInALineDesktop.java
it.alcacoop.fourinaline.FourInALine.java
it.alcacoop.fourinaline.GServiceApplication.java
it.alcacoop.fourinaline.GServiceInterface.java
it.alcacoop.fourinaline.MainActivity.java
it.alcacoop.fourinaline.NativeFunctions.java
it.alcacoop.fourinaline.PrivateDataManager.java
it.alcacoop.fourinaline.PurchaseActivity.java
it.alcacoop.fourinaline.SoundManager.java
it.alcacoop.fourinaline.actors.BoardImage.java
it.alcacoop.fourinaline.actors.Board.java
it.alcacoop.fourinaline.actors.ChatBox.java
it.alcacoop.fourinaline.actors.Checker.java
it.alcacoop.fourinaline.actors.FixedButtonGroup.java
it.alcacoop.fourinaline.actors.IconButton.java
it.alcacoop.fourinaline.actors.ParticleEffectActor.java
it.alcacoop.fourinaline.actors.PlayerBlock.java
it.alcacoop.fourinaline.actors.UIDialog.java
it.alcacoop.fourinaline.billingutils.Base64DecoderException.java
it.alcacoop.fourinaline.billingutils.Base64.java
it.alcacoop.fourinaline.billingutils.IabException.java
it.alcacoop.fourinaline.billingutils.IabHelper.java
it.alcacoop.fourinaline.billingutils.IabResult.java
it.alcacoop.fourinaline.billingutils.Inventory.java
it.alcacoop.fourinaline.billingutils.Purchase.java
it.alcacoop.fourinaline.billingutils.Security.java
it.alcacoop.fourinaline.billingutils.SkuDetails.java
it.alcacoop.fourinaline.client.GwtLauncher.java
it.alcacoop.fourinaline.fsm.FSM.java
it.alcacoop.fourinaline.gservice.GServiceClient.java
it.alcacoop.fourinaline.gservice.GServiceCookieMonster.java
it.alcacoop.fourinaline.gservice.GServiceMessages.java
it.alcacoop.fourinaline.gservice.GServiceNetHandler.java
it.alcacoop.fourinaline.layers.BaseScreen.java
it.alcacoop.fourinaline.layers.GameScreen.java
it.alcacoop.fourinaline.layers.MatchOptionsScreen.java
it.alcacoop.fourinaline.layers.MenuScreen.java
it.alcacoop.fourinaline.layers.OptionsScreen.java
it.alcacoop.fourinaline.layers.SplashScreen.java
it.alcacoop.fourinaline.logic.AIExecutor.java
it.alcacoop.fourinaline.logic.MatchState.java
it.alcacoop.fourinaline.util.Base64DecoderException.java
it.alcacoop.fourinaline.util.Base64.java
it.alcacoop.fourinaline.util.GServiceGameHelper.java
it.alcacoop.fourinaline.util.GameHelperUtils.java
it.alcacoop.fourinaline.utils.AchievementsManager.java
it.alcacoop.fourinaline.utils.AppDataManager.java
it.alcacoop.fourinaline.utils.ELORatingManager.java
org.gojul.fourinaline.model.AlphaBeta.java
org.gojul.fourinaline.model.DefaultEvalScore.java
org.gojul.fourinaline.model.EvalScore.java
org.gojul.fourinaline.model.GameModel.java