Sign In Register

How can we help you today?

Start a new topic

Assistance creating Async turn-based flow

Hi all,

First, I am following this link to create the async turn based game:

Now, what I want to create is a flow like Trivia Crack:

1) Player 1 clicks on Random (to play with any random player)

2) If system finds a pending match (some other player already created a challenge and is waiting for someone to play with, asynchronously) then Player 1 joins that match

3) If system cannot find a pending match, it will create one (I still don't understand the difference between match and challenge)

4) Player 1 plays his turn and set his play data using LogChallengeChallengeEvent

5) Player 1 takes the turn

6) Player 2 plays his turn and so on

So this is basically my flow. How can I achieve this? I am envisioning the following API calls:

1) "FindPendingMatchesRequest"

2) if the response of above has one pendingMatch then call "JoinPendingMatchRequest" and start the game

3) if the response is empty, then call "CreateChallengeRequest"

4) Get the challengeInstanceId from the response and then call "createLogEventRequest" to set the game data that both players will be playing 

5) Player 1 plays turn 1 of the game and then calls "createLogChallengeEventRequest" to set his turn 1 data and take the turn

6) It's player 2 turn and etc...

I feel that this flow is broken because of my lack of understanding between matches and challenges...

Another thing is that my game has 5 turns... So I suppose that I must not enabled the "turn based" button in my challenge and set a script to control each turn and then on turn 5 decide the victor

Any help appreciated


Ok, this is the flow diagram I created after a lot of trial and error...

Am I going in the right direction?



Hi Felipe,

Yes, you're definitely on the right track here. The only issue with this flow is in the 'Join Challenge' branch - after joining the challenge, there shouldn't be any need to invoke a GetChallengeRequest - once joined you should receive all challenge-related messages, so once the challenge begins (either through reaching the startTime or maxPlayers (if autoStartOnMaxPlayers is set to true)), you should receive a 'ChallengeStartedMessage' with all of the challenge info you should need.

You can set the challenge to be turn-based, and use the ChallengeTurnTakenMessage to get the PlayerTurnCount, which you can use to determine when to end your challenge.

I understand the difference between Matches and Challenges can be slightly confusing at first. Essentially, if you're looking for another player that suits a given set of criteria, you'd use a Match, once a matching player has been found you could use the other players details to, for example, set up a private challenge between the players that have been matched. Challenges, on the other hand, represent some kind of specific interaction or 'game' between a set of players, with a startTime, endTime, winner, loser, etc. Our Hearthstone tutorial gives a great illustration of how you can use matchmaking to set up your challenge. I hope this helps to clear things up a bit.



1 person likes this

Hi Vinnie,

Thanks for your help so far. If you don't mind, I will keep bugging you until this setup is up and running! :)

Ok, so I followed your advice and reviewd the GetChallegeRequest. I am running the FindChallegeRequest and when I find one PUBLIC available challenge, I run the JoinChallengeRequest. But, in the response of the Join, I get "joined=false". Have a look at the logs:

I/System.out: onTextMessage. websocket: text: {"@class":".FindChallengeResponse","challengeInstances":[{"accepted":[{"externalIds":{ },"id":"57f1f5fde62c9073b9235abc"},{"externalIds":{ },"id":"580495b7e879cb9abad36ead"}],"challengeId":"580334084d6a8d056d01c8ae","challengeName":"Turn-based Challenge","challenged":[{"externalIds":{ },"id":"580495b7e879cb9abad36ead"}],"challenger":{"externalIds":{ },"id":"57f1f5fde62c9073b9235abc"},"endDate":"2016-10-19T08:02Z","scriptData":{},"shortCode":"CHALL","state":"ISSUED","turnCount":{"57f1f5fde62c9073b9235abc":0,"580495b7e879cb9abad36ead":0}}],"requestId":"1476740625178_6"}

I/System.out: {"challengeInstanceId":"580334084d6a8d056d01c8ae","@class":".JoinChallengeRequest","requestId":"1476740625498_7"}

I/System.out: onTextMessage. websocket: text: {"@class":".JoinChallengeResponse","joined":false,"requestId":"1476740625498_7"}

In order to invoke the JoinChallengeRequest, I set the challengeInstanceId I took from the result of FindChallengeRequest:

What makes a join challenge return false?

Thank you

I removed the GetChallengeRequest (not reviewed)

Knock Knock, anyone there to help ? :)

Hi Felipe,

Have you tried this request in the Test Harness? Do you get the same results?

Kind regards,

 - Steve

Thanks Steve.

I am now using the Test Harness and I do the following steps:

Player 1


LogEvent (saves game data in the challenge that both players willl be playing)

Player 2


Then, in the "ChallengeJoinedMessage" I've done the following:

var chal = Spark.getChallenge(Spark.getData().challengeInstanceId);

Spark.setScriptData("game_data", chal.getScriptData("game_data"));

With that I am trying to send the Player2 the game data that was set by the Player 1.

This function is failing: 

invalid hexadecimal representation of an ObjectId: [undefined] (userMessage/ChallengeJoinedMessage.js#7)

That's right on the first line... any clue why?

Thank you

Ok, I now know that  Spark.getData().challengeInstanceId is undefined. I need to send the "game_data" set by Player1 to Player2 when he joins the match (in the response).
How do I do that?

Thank you

I now tried this line: var challengeId2 =;

but also no luck

Ok, here am I again...
I tried the very same code from above in the "JoinChallengeResponse" but P2 is not receiving the game_data still...  

What I did notice was that P1 received the "@class": ".ChallengeJoinedMessage",

But, it's not exactly that what I want. I want P1 to create the challenge, set the game data to the challenge, allow P1 to play his first round and then take the turn.

Then, P2 will Search for an open challenge, find the one P1 created, Join it and receive in the response the game_data so he can play it. And then take the turn.

So, I tried exactly this what I described in test harness. P1 created the challenged, saved the data with a LogEvent, and took the turn with a LogChallengeEvent. But it fails because the challenge is still in ISSUED status, although I set the min players to 1... so was expecting it to be RUNNING.

 "@class": ".CreateChallengeRequest",
 "accessType": "PUBLIC",
 "autoStartJoinedChallengeOnMaxPlayers": true,
 "challengeMessage": "",
 "challengeShortCode": "CHALL",
 "eligibilityCriteria": {},
 "endTime": "2016-10-23T15:01Z",
 "maxPlayers": 2,
 "minPlayers": 1,
 "silent": false

 "@class": ".LogEventRequest",
 "eventKey": "SAVE_GAME_DATA",
 "game_data": {"a":"b"},
 "challengeInstanceId": "580b114af43e600560f80a80"

 "@class": ".LogChallengeEventResponse",
 "error": {
  "challengeInstanceId": "ISSUED"

Hi Felipe,

To get the challengeId from theChallengeJoinedMessage you would need to use the following.





1 person likes this

Liam, thank you very much. That worked.

Is there anywhere I can find which objects and their functions are available in each User/Global message? That would be very helpful.

And, another question: I want the challenge to start automatically when P1 creates it (status RUNNING). I don't want to wait till P2 joins it. How do I do that?

Hello again guys, how can I get the challenge to start (status RUNNING) right when P1 creates it?

Thank you

Hi Felipe,

After P1 creates the challenge in cloud code you can do something like this. Spark.getChallenge(challengeId).startChallenge(); I've linked the relevant documentation here.

Kind regards,

 - Steve

1 person likes this
Login to post a comment