Walk through of Rummy Demo

DhruvCShepHertz edited this page Jan 9, 2014 · 5 revisions

Rummy Demo is a sample game, developed for Android with backend build over AppWarpS2. Complete code is provided as part of the download.

Rummy is a traditional card game. This Game has following Rules.

  1. Cards will be distributed by server for two or three user game.
  2. In case of two-user game each user will get 9 cards.
  3. In case of three-user game each user will get 6 cards.
  4. User can select a new card or can pick top card only once in his turn.
  5. After arranging the cards user has to do send move.
  6. User has to build combinations of 3 cards.
  7. A valid combination is one in which the cards are of the same suit and in a sequence or all the three cards or of the same number.

Example combinations

same face value combination: {1,1,1} {K,K,K} {7,7,7}

same color sequence combination: {1,2,3} {J,Q,K} {Q,K,1}

Note You will first need to create an application zone first through the admin dashboard. This is described in in our getting started page.

Client Side

login

Android client has three screen(Activity).

  1. MainActivity: User enter his name connect to AppWarpS2 or he can also logic with facebook.
  2. RoomSelectionActivity: User has option to join two or three user game. When user click any button this frist try to join existing room if not found it create a new room and wait for other user to join the game.
  3. GameActivity: This activity contain complete game play logic.
  4. The rooms created from the client are turn based rooms.

How to play:

play

Please refer this video link

gameover

Server Work

To run this server side application, please first go through Running your first application. You need to follow the same steps for this sample as well. Following are details specific to this sample.

  1. Start the Game: The game is started when the number of joined users is equal to the desired number (2 or 3).
  2. Deal Cards: Server deals the cards and sends to every user only his cards.
  3. Draw New Card: Server provide new card when client request a new card from the deck.
  4. Validate Move: When client sends any move, the server will validate the cards in the move.
  5. Finish Game: After receiving submit cards request, the server will validate the combinations and broadcast the result.

Implementation

On server side we have defined extensions to override default server side functionality.

BaseServerAdapter: RummyServerExtension.java

BaseZoneAdapter: RummyZoneExtension.java

BaseTurnRoomAdaptor: RummyRoomExtension2User.java and RummyRoomExtension3User.java

Setting Adapter

Setting adapter is necessary task to override default server side functionality. First we set BaseServerAdapter at the time of starting AppWarpS2.

String appconfigPath = System.getProperty("user.dir")+System.getProperty("file.separator")+"AppConfig.json";
	boolean started = AppWarpServer.start(new RummyServerExtension(), appconfigPath);
        if(!started){
            throw new Exception("AppWarpServer did not start. See logs for details.");
        }

we set zone adapter in RummyServerExtension.java as we receive notification onZoneCreated.

@Override
    public void onZoneCreated(IZone zone)
    {             
        zone.setAdaptor(new RummyZoneExtension(zone));
    }

and we set BaseTurnRoomAdaptor as we receive notification of creating room in RummyZoneExtension.

@Override
    public void handleCreateRoomRequest(IUser user, IRoom room, HandlingResult result)
    {
        if(room.isTurnBased() && room.getMaxUsers()==2){
            room.setAdaptor(new RummyRoomExtension2User(izone, (ITurnBasedRoom)room));
        }else if(room.isTurnBased() && room.getMaxUsers()==3){
            room.setAdaptor(new RummyRoomExtension3User(izone, (ITurnBasedRoom)room));
        }
        else{
            result.code = WarpResponseResultCode.BAD_REQUEST;
        }
    }

Custom server side authentication

To check custom-auth we have logic in BaseZoneAdapter handleAddUserRequest i.e. if user select login with facebook we check on server with facebook graph api if user has same user id from client facebook oauth token.

@Override
    public void handleAddUserRequest(final IUser user, final String authData, final HandlingResult result){
        if(authData!=null && authData.length()>0){
            result.code = WarpResponseResultCode.AUTH_PENDING;// indicates that response will be sent asynchronously
            new Thread(new Runnable() {
                @Override
                public void run() {
                    checkForAuth(user, authData, result);
                }
            }).start();
        }
    }

In checkForAuth we check using facebook graph API is user has same fb_id as sent in auth_data.

if(response.get("id").equals(user.getName())){
                    // "Auth success on server"
                    izone.sendAddUserResponse(user, WarpResponseResultCode.SUCCESS, "Auth success on server");
                }else{
                    // "Auth Failed on server"
                    izone.sendAddUserResponse(user, WarpResponseResultCode.AUTH_ERROR, "Auth failed on server");
                }

Starting the game

Game is started by server if joined user in room and max users in room are same. This is done using the startGame operation API of ITurnBasedRoom.

@Override
    public void handleTimerTick(long time){
         if(GAME_STATUS==CardsConstants.STOPPED && gameRoom.getJoinedUsers().size()==gameRoom.getMaxUsers()){
                GAME_STATUS=CardsConstants.RUNNING;
                dealNewCards();
                gameRoom.startGame(CardsConstants.SERVER_NAME);
         }
    }

Handling move

When clients send a move, the server will validate it. To validate the move server checks the top card sent by client is actually held by the sender or not.

@Override
    public void handleMoveRequest(IUser sender, String moveData, HandlingResult result){
            int top_card =-1;
            JSONObject data = new JSONObject(moveData);
            top_card = data.getInt("top");
            validateAndHandleMove(sender, top_card, result);
            ....
    }


_validateAndHandleMove_

if(USER_1_HAND.indexOf(topCard)!=-1){
...
}

Check For Win

When client submit his cards then server checks if client has won the game or not on the basis of rules(defined above). If client has won the game server declare client as winning user and broadcast the result. If client cards are not winning cards then server will send back a notification to the client.

boolean status = Utils.checkForWin(cardList);
            if(status){// for winning condition
                if(sender.getName().equals(user1_name)){
                    handleFinishGame(user1_name, cardList);
                }else if(sender.getName().equals(user2_name)){
                    handleFinishGame(user2_name, cardList);
                }
            }else{
                String desc = CardsConstants.SUBMIT_CARD+"#"+"You don't have winning cards";
                sender.SendChatNotification(CardsConstants.SERVER_NAME, desc, gameRoom);
            }

miscellaneous

TurnBasedRoom

RummyDemo use AppWarpS2 TurnBasedRoom API. In this room turn time is 180 seconds user has to complete his turn in turn time other wise his turn will be expired. By default AppWarpS2 gives turn to next user if you want to edit this functionality you can define logic in onTurnExpired of BaseTrunRoomAdapter

public void onTurnExpired(IUser turn, HandlingResult result)
    {
        
    }

Handling leaving user

If game is started by server and any user leaves the game then in case of two user game server declare other user as winning user and in case of three user game server continue the game and put leaving user cards in deck.

@Override
    public void onUserLeavingTurnRoom(IUser user, HandlingResult result){
        String leaveingUser = null;
        if(user.getName().equals(user1_name)){
            leaveingUser = user1_name;
        }else if(user.getName().equals(user2_name)){
            leaveingUser = user2_name;
        }
        String message = "You Win! Enemy "+leaveingUser+" left the room";
        gameRoom.BroadcastChat(CardsConstants.SERVER_NAME, CardsConstants.RESULT_USER_LEFT+"#"+message);
        ...
    }

Handling connection resiliency

Rummy Demo client has AppWarp Connection Resiliency feature. When server receive onUserPause then it stop the game.

@Override
    public void onUserPaused(IUser user){
        if(user.getLocation().getMaxUsers()==2){
            RummyRoomExtension2User extension = (RummyRoomExtension2User)user.getLocation().getAdaptor();
            extension.onUserPaused(user);
        }
        ....
    }

_onUserPaused_
if(gameRoom.getJoinedUsers().contains(user)){
            pausedUserList.add(user);
            GAME_STATUS = CardsConstants.PAUSED;
            gameRoom.stopGame(CardsConstants.SERVER_NAME);
        }

server resume the game as it receive handleResumeUserRequest

@Override
    public void handleResumeUserRequest(IUser user, String authData, HandlingResult result){
        if(user.getLocation().getMaxUsers()==2){
            RummyRoomExtension2User extension = (RummyRoomExtension2User)user.getLocation().getAdaptor();
            extension.onUserResume(user);
        }
        ....
    }

_onUserResume_
if(pausedUserList.indexOf(user)!=-1){
            pausedUserList.remove(user);
        }
        if(pausedUserList.isEmpty()){
            GAME_STATUS = CardsConstants.RESUMED;
        }
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.