The goal of each team is to implement a client to ace the Dead-Man's-Draw card game using their language and tools of choice.
During the competition period there will be several practice tournaments, while the competition will close with a grand tournament where teams' solutions will compete against each other and the most victorious teams will ace the SLCEE-PC-2023.
- Teams register themselves to the organizers
- Organizers enter the team with a generated passwordhash
- Organizers send the Player id and the passwordhash to the Team
e.g{id: '636438380ee778617e6e5be8', password: 'playerpass'}
- Organizers send the Player id and the passwordhash to the Team
- Players implement a test client using the specification and the example clients
- Organizers publish example clients to a public repo beforehands
- Players test themselves on practice Matches and develop a good strategy
- Organizers announce Practice Tournaments, where Players are challenged to compete. Organizers create appropriate Matches between the Players - e.g. around at the end of each day 3pm-4pm
- Teams are expectd to keep their solution up and running during the tournament and react to ongoing matches with their involvement with the logic below
Teams host their solution either on any internet enabled local machine - e.g. dev laptop or may choose to publish their client in the cloud
NOTE: This is an awesome opportunity to test Kyma, or any hyperscaler - Once all Matches are finished, Organizers announce ranking and winners
- Teams are expected to react on matches within a short amount of time (e.g. 30 seconds - tbd) time otherwise a central watchdog may terminate the match forcefully and announce the other team as winner.
- Teams are expectd to keep their solution up and running during the tournament and react to ongoing matches with their involvement with the logic below
Teams host their solution either on any internet enabled local machine - e.g. dev laptop or may choose to publish their client in the cloud
During the tournaments we will use double elimination. This means that teams are eliminated from the tournament when they lose against two opponents, i.e. every team has a second chance. When facing an opponent, the teams will play five matches against each other in a row and the winner will be the team winning more times. In case of a draw, subsequents matches will be played until a winner can be determined. The status of the current tournament can be tracked on the Tournament Status page. On the top of the page you can see the tournament's results, while on the bottom of the page the status of the currently running matches are displayed.
Game is available through a public server, the Arena as a collection of REST api's.
- REST API with OpenAPI specification is available at /api, documented under /docs endpoint.
- Web Frontend Frontent UI available under /matches.
Eye fancy only, use this to enable easy comprehension for practice matches, do not use it for your programmatic / automated / competition scene.
No uptime guarantee.
A Match is a game between two players. Can be created by the Organizers between any two Players or as a practice Match.
- Team listens to the /matches?active=true&wait=true&tags=GAMETAG endpoint.
- Arena server returns any matches - if found
- In absence - it will use "HTTP Long Polling" to wait and keep the connection for a longer period (e.g. 30 seconds), and then returns with an empty array
[]
- Teams are advised to retry the polling to get informed on any new match announced
- As a match is started the API endpoint returns with a list of matching Match Ids so user gets notified about a match start.
NOTE: Organizers will start a one active match at a time for each team, so no teams should deal with simultaneous matches.
-
Player checks the state of the match and eventually waits for his/her turn via.
GET /api/matches/{matchid}?waitactive=true
- Similary to the waiting for a match step, the arena server keeps the connection open to a longer period "HTTP Long Polling" (e.g. 30 sec) and returns with a
409 - Authenticated user is not the current player
code if the player is not the active. Players should retry this wait step. - If the match ended by the last action of the other player arena server returns
410 - No action possible on finished matches
with the list of closing events, so scores and winner can is known also by this player.
- Similary to the waiting for a match step, the arena server keeps the connection open to a longer period "HTTP Long Polling" (e.g. 30 sec) and returns with a
-
Player issues a
Draw
action via the API and waits for result viaPOST /api/matches/{matchid} { "etype": "Draw" }
- Player receives information on events resulted by the action in the response
- Upon turn start all changes of the playarea is delivered as a delta structure.
- If the card triggers an effect that requires user response (e.g.
Map
) and the effect is not nullified the user is expected to call the action API with the appropriate response viaResponseToEffect
POST /api/matches/{matchid} - { "etype": "ResponseToEffect", "effect": { "effectType": "Hook", "card": { "suit": "Kraken", "value": 4 } } }
- As any action can bust the turn, Players should check if the returned response contains a
TurnEnded
or evenMatchEnded
event. (Though Arena server will prevent any invalid actions, such as drawing a card when already the other player is on turn.)
-
After a number of cards player issues
EndTurn
action viaPOST /api/matches/{matchid} { "etype": "EndTurn" }
- Arena server returns the list of state change events similarly to
Draw
including a turn ended aggregate state delta
- Arena server returns the list of state change events similarly to
-
If busted or draw pile is exhaused turn ends automatically -- server adds a
TurnEnded
event in response. -
If draw pile is exhaused and all effects are responded to match ends automatically and winner or a tie is announced -- server adds
MatchEnded
event in response.
Teams are not expected to ace the game at the first day, therefore a number of tools are at your disposal during the development journey to gradually excel with the result.
- Teams can onboard on
/api/helloworld
and then/api/whoami
endpoints - REST API is easier than you would think - use web browser for testing, curl, PostMan or even Excel macros, Excel grid, using e.g. restapiexample.
- Teams receive a number of example clients te ease development in most popular languages
- Teams can start and conduct any amount of Practice Matches to test game logic with the same user
- Teams can start and conduct any amount of Practice Matches to test game logic between the own user + dummy user to test dialogue handling
- Teams can set initial state of the game to test out different situations in Practice Matches, and set randomization or even turn out randomization completely
- Teams can recreate and replay any match in Practice Matches
- Teams can use the autopick mechanism to neglect any abligation for Card Effect responses
- Teams can check relevant match results via a web browser, rendering all moves and match state
A practice Match is a Match that is created by the Player itself, and contains twice the PlayerId or the PlayerId and the DummyId so that it can act as both sides of the table.
For a practice Match extended amounts of information is optionally delivered via the API for easier debugging.
DummyPlayer is identified with "000000000000000000000000":"dummypass"
accepting any match as an opponent.
Be aware that you need to play with the dummyuser as well if you start a match with it.
Be aware that dummyuser will receive many matches from other players as well - react only on matches you have started yourself, consider using a tag for such maches.
Practice match can be started with specifying any initial starting state with regards to draw, discard pile or banks. See the OpenAPI documentation for the parameters - check out MatchCreationParams
.
Practice match can be started with specifying the random seed so that a previous match can re replayed and any programming errors can be understood better.
Each game creation returns the random seed used or generated - check out MatchCreateResponse
.
Special random seed parameter is norandom
when areana server picks first available choice - useful for selection of initial player from players array or discard pile drawing on "Map" effect.
If the card triggers an effect that requires user response (e.g. Map) and the effect is not nullified the user is expected to call the action API with the appropriate response. with ResponseToEffect
.
To ease the initial learning curve teams can use the autopick mechanism that provides an automatic answer for any card effects, though not the most strategically smart one - check out IUserAction.
{
"etype": "ResponseToEffect",
"autopick": "true"
}
{
"etype": "Draw",
"autopick": "true"
}
{
"etype": "EndTurn",
"autopick": "true"
}
The next few steps describes the steps necessary to set up a test match and connect two clients to play against each other. The text refers to the java client, but it can be replaced with your favorite one.
- As a preparation please download the precompiled binary version of the java client "SpcJavaClient-1.0-SNAPSHOT-jar-with-dependencies.jar" from /example_clients/SPCJavaClient/taget.
- Please make sure that SapMachine 17 or any other Java 17 compatible JDK or JRE is installed on your system. Check that entering java --version in a comand prompt reports a java version 17 or higher.
- You also need a REST client to interactively create a match. We recommend Postman, but anything will do.
- Using Postman create a POST request to the endpoint https://slhpc2023.appspot.com/api/matches.
In the body use the following text:
{
"playerids": ["<your user id>", "<dummy user id>"],
"tags": ["<something unique>"]
}
The user id is the one we gave your team, the dummy user id is 000000000000000000000000.
- Set up basic authentication with your user id and password.
- Send the request.
The response returned from the arena server should look like this:
{
"id": "<match id>",
"randomSeed": "<random seed>"
}
Both <match id> and <random seed> are unique strings. We will not use the random seed in this guide, but the match id is essential, as it identifies the match that you want to connect your clients to.
There are multiple ways to continue from here. Choose one that you like.
-
running two separate instances of the java client; one for each player.
Run the following commands in separate terminal windows:
java -jar SpcJavaClient-1.0-SNAPSHOT-jar-with-dependencies.jar -g <match id> -p <user id> -pw <your password> -s https://slhpc2023.appspot.com
java -jar SpcJavaClient-1.0-SNAPSHOT-jar-with-dependencies.jar -g <match id> -p 000000000000000000000000 -pw dummypass -s https://slhpc2023.appspot.com
- running one instance, playing the role of both players.
java -jar SpcJavaClient-1.0-SNAPSHOT-jar-with-dependencies.jar -g <match id> -p <user id> -pw <your password> -p2 000000000000000000000000 -pw2 dummypass -s https://slhpc2023.appspot.com
- waiting for a tag instead of connecting to the specific match. This is the recommended setup for competitions. We also add the -l parameter that forces the client to run in a loop, i.e. it will wait for a new match with the same tag after completing the previous one. The order in which you start the client and create the match is not important in this case, the connection will be established in both cases.
java -jar SpcJavaClient-1.0-SNAPSHOT-jar-with-dependencies.jar -w -l -t <your unique tag> -p <user id> -pw <your password> -p2 000000000000000000000000 -pw2 dummypass -s https://slhpc2023.appspot.com
Obviously, during a real competition you must not add the credentials of the dummy user as you want to run a single instance of the client on behalf of your own user.
You will also find an example client written in Javascript using Node.js.
It will draw and on a random basis either draw a next card or end the turn.
- install nodejs from https://nodejs.org/en
- navigate a console to the
example_clients\javascript
directory - install all dependencies by
npm install
You can start the node client, wait for an active match for the user and play it through.
node.exe _example_client_nodejs.js --u=<userid> --p=<password>
Additionally it is also possible to start a specific match.
node.exe _example_client_nodejs.js --u=<userid> --p=<password> --m=<matchid>
There is an extensive OpenAPI documentation under /docs path of the server. The REST API works on JSON format.
Match request and Action execution endpoints works with a timeout with wait=true
parameter specified to avoid constant polling. As there is a timeout of cc 30 sec, eventually the request needs to be restarted.
GET /api/matches
- get matchesPOST /api/matches
- create a matchGET /api/matches/{id}
- get match statusPOST /api/matches/{id}
- execute action
Digest or Basic authentication is used in the header with the username and passwordhash provided.
NOTE: For the scope of the programming competition this is sufficient, sorry for not adding APIKey or JWT authentication. Rationale: we wanted to keep an entry level learning curve.
The Areana server is a development artifact not thourougly tested for security flaws or performance bottlenecks. There were tests performed withstanding 100+ parallel users every second easily, yet that was not the main focus of the current implementation.
To keep chances fair, we expect all teams to respect arena integrity, report and not exploit any flaws to and solely the organizers right away. To keep chances fair, we expect that each team polls server with the timeout frequency implemented (~30 sec) to avoid potential overload and denial of service.
The organizers will start the tournament matches with a timeout setting, where any player is obligued to respond to the their turn within the given timeframe (e.g. 10 sec). This will keep a fair and clean tournament and ensures that all players have a chance to ace even if an opponent experiences technical difficulties.
To ease comprehension teams can check relevant match results via a web browser, rendering all moves and match state.
The frontent is accessible via /matches. An example gameplay of a match including user turns and moves look like this.
This is how the a gameplay looks like from the frontend perspective.
example_match.mp4
The game is a slightly simplified version of the popular card game.
Two players play against each other, their goal is to collect the highest number of cards and secure them in their own treasure chest.
One player starts the game. The players take turns and in each turn only one of the players is active. The active player draws cards one by one. After each draw he/she can finish the turn or draw another card. If the player stops drawing, all the cards drawn in the round can be moved to the player's chest. However, if a player keeps drawing and the type of a new card matches one already drawn in the same round, all the cards drawn in the round must be discarded and the round is completed without gaining anything. Every new card a player draws increases the potential value he/she can gain in the round but at the same time the chance of drawing a duplicate and completing the round with 0 points is increased as well.
There are 9 type of cards, all of them having 6 identical cards (54 in total). All of the 9 types affect the player's turn in a different way. When a duplicate is drawn it is discarded instantly together with the other cards without its ability affecting the round.
Anchor - the cards drawn before the anchor are placed into the treasure chest even if the round ends with a duplicate.
Cannon - the player can choose a card from the other player's chest to discard (if the other player has at least one card in the chest).
Sword - the next card must be choosen from the opponent's chest (if there is any). If a player chooses a card that matches one already drawn before (e.g. because there is only one card in the chest), the turn ends just as a duplicate was drawn and the cards must be discarded (except those protected by the anchor).
Hook - the player must choose a card from his/her own chest (if there is any) and move it back to the play field. The card must be treated as it was drawn, i.e. the action based on its type must be executed. If a player chooses a card that matches one already drawn before (e.g. because there is only one card in the chest), the turn ends just as a duplicate was drawn and the cards must be discarded (except those protected by the anchor).
Oracle - player can look at the next card before deciding to stop the round or draw the card.
Map - the player must choose the next card from three cards randomly selected from the discarded ones. One must be choosen even if it completes the turn by being a duplicate. If there is no three cards in the discarded set, then the player must choose from less options. If there is no discarded card, then the next card must be drawn the standard way.
Kraken - the player has two draw two additional cards before stopping. If the first drawn card is a sword, map or hook, the next card counts towards the two regardless where it was drawn from.
Chest & Key - these cards have no special ability, but when both of these cards are drawn in a round and the player decides to stop (i.e. the turn does not end by drawing a duplicate) the player can move twice as many card to his chest that he/she would normally do. The additional cards are selected randomly from the discarded pack. If there are less cards discarded than the number of cards drawn, then all the discarded cards are moved to the player's chest.
The game ends when there are no more cards to draw. The player having the highest sum of the topmost cards in his/her treasure chest wins the game.
- How Kraken card behaves with any subsequent effects?
- Kraken must draw two cards - if drawpile allows
- Kraken practically ignores the first card's Oracle effect, as you will need draw a second card anyhow
- if first card successfully triggers effect (Hook, Map, Sword) that places a second card to the playarea, no forced second draw is triggered
- if card effect for first Kraken-pulled-card cannot be fulfilled, thus is nullified, the second card needs to be drawn (e.g. Kraken->Map(empty discardpile)->[draw second], Kraken->Hook(with empty bank)->[draw second], Kraken->Sword(with empty or all existing suit stacks)->[draw second] ))
- as stated in the rules, you must perform Kraken if you can, even if it busts your turn.
- Sword effect is not allmighty
- Sword effect cannot pick enemy Suit from which own Player already has someting in its Bank, yet not taking anything on the PlayArea in account
- Bonus cards on short or empty drawpile
- Chest & Key draws from the DiscardPile randomly, bad luck if there are no or not enough cards for you in the pile
- DiscardPile initial state
- DiscardPile is initially filled with the smallest of each suit