Write code instead of a cover letter!

Click for API docs or debugger

V1 API docs

Write an API client that plays instead of you

1) Start a game in Story mode
2) Beat as many levels as you can by writing code in your favorite IDE
3) Win a job interview at ICF Tech Hungary without boring HR questions

Your code shall call the endpoints of this API to play the game

Beating a Map (The Game)

You play a turn-based game - You set what you want to do on the next tick (turn) of the Map, and then trigger a tick.

To beat a Map, collect all the treasures on it by controlling your Hero. A Hero is basically your Player's "presence" on a Map. You can control your Hero by calling endpoints described below:

info

The game uses an XY coordinate system of integers. (0;0) is the bottom-left corner of the map.

Right after your Map was generated (we'll talk about how this happens later), call the GET play/mapResource endpoint - it returns immutable resources that you should store until you finish the Map. I.e. you should only call this endpoint once for a Map.

After you got your Map's resources from GET play/mapResource, the turn-based game can start. There are two endpoints that you'll probably regularly call in your implementation:

  1. GET play/mapState - returns the current state of all the moving parts on the Map
  2. POST play/approveHeroTurn - sets the next move of a Hero

Combining the prefetched data from the GET play/mapResource endpoint with data from the GET play/mapState endpoint gives you the full state of the Map you're playing on - thus your API client implementation can decide what the next action of the Hero should be.

info

There is a debugger accessible on /freeRoam. It visualizes the current state of all the entities on a map. Use it to make developing your API client easier and more convenient.

After your implementation calculated the action, it can call the POST play/approveHeroTurn endpoint to submit it. The submitted action will be executed on the next tick. POST play/approveHeroTurn also ticks the Map if all the Heroes on the Map approved their turn.

info

In Story mode, there is only one Hero on the map, so calling POST play/approveHeroTurn ticks the map instantly.

Game elements:

  • Obstacle: You can't go through obstacles
  • Treasure: You can collect them by stepping on them. Collect them all and win the map!
  • Enemy: Tries to kill you before collecting the treasures
  • Bullet: Enemies can shoot bullets at you, which then move on the map slowly, in a straight line
  • Hero: Your (or in multiplayer, someone else's) presence on the map. A character you control

Enemies are moving towards the closest Hero. If they manage to step on the same field as a Hero, they deal Touch Damage. Enemies also shoot Bullets at you. A Bullet has a direction and advances one field on every tick (in a straight line).

To attack an Enemy, submit the "KICK_*" actions . These actions damage the Enemies standing on the Hero's field, on its neighboring field, and on its second neighboring field.

info

Hero and Enemy health ranges from 0 to 1. A "KICK_*" deals 0.6 damage to all Enemies in range. You can't "kick" "through" obstacles.

To protect against a Bullet, submit the USE_SHIELD action - it reduces the Bullet Damage to zero. You should apply "USE_SHIELD" exactly on the tick when the Bullet arrives on the field of your Hero.

note

A Bullet vanishes if it 1) hits an obstacle 2) goes out of map bounds or 3) hits a Hero with or without using a shield.

You can tell that a Map is finished if "$.map.status" in the response of GET play/mapState is "WON".

note

One Player can place and control multiple Heroes on the same Map thus you can even race your different algorithms against each other on the same Map using the same Player.

Order of execution in a tick:

  1. Bullets move
  2. Enemies move
  3. Heroes move
  4. Heroes set defense up (USE_SHIELD)
  5. Enemies attack (touch damage, shoot bullets)
  6. Bullets deal damage
  7. Heroes attack

Game Modes

Progressing through a Story (Story mode)

A Story is a predefined list of Map specifications, i.e., levels. It starts when you start the game on ponypanic.io or call the POST story/begin endpoint.

Playing in Story mode means that there is a StoryPlaythrough entity that tracks your progress across Story levels (Maps). A StoryPlaythrough always provides a Map that you have to beat to get to the next level.

When you play a StoryPlaythrough, we auto-generate Maps for you based on the Story's Map specification belonging to your current level.

info

When playing in Story mode, both the Map and Player are provided by the StoryPlaythrough entity. You can check out the Authentication chapter on how to authenticate a StoryPlaythrough.

After you beat a Map, you can proceed to the next level by calling the POST story/nextLevel endpoint. This endpoint generates you a whole new Map that you shall beat. After you finished the last Map, you won the StoryPlaythrough - Yaay, congrats!

note

The levels (Maps) continuously get harder so you may need to make small tweaks in your API client implementation as you level up. Some of the starting maps are handcrafted to address particular scenarios and ease you in when you start developing your API client.

If you hit a deadlock, just call POST story/resetLevel to generate a new Map for your current level.

To win a StoryPlaythrough, you have to beat all the generated Maps in a consecutive order.

note

If you are curious about the current state of your StoryPlaythrough (e.g. which level are you on) call GET story/playthroughState.

Creating and playing standalone maps (Freestyle mode)

You can generate Maps by custom generation parameters (size, difficulty, etc). To do this, call POST freestyle/createMap and provide the parameters.

POST freestyle/createMap returns a Map-Token that you can use to interact with the Map.

To put a Hero on a Map (i.e., to be able to play the Map), call the POST freestyle/joinMap endpoint.

info

You can share the Map-Token with other Players so they will also be able to join and you can all play multiplayer on the same Map

note

One Player can place and control multiple Heroes on the same map thus you can even race your different algorithms against each other on the same Map using the same Player. If your Player has multiple heroes on the same Map, you have to specify which Hero are you setting the desired action for when calling POST play/approveHeroTurn - to do so, set the heroId request param to the value returned by POST freestyle/joinMap

Authentication

There are three entities that you can authenticate to:

  • Player entity: Your identity that is generated when you start the game on ponypanic.io. You should stick to one Player (instead of generating multiple ones) so we can count your score
  • Map entity: A map that you can beat. Multiple Players can play on the same map if they can authenticate the Map (and the map itself allows for multiple players)
  • StoryPlaythrough entity: Your progress during a playing through a story. It also authenticates your Player and the current level's Map so you don't have to authenticate neither Player nor Map if you authenticated the StoryPlaythrough

To authenticate an entity, add its token to your HTTP requests as the value of the appropriate header:

  • For Player, add the Player-Token as the "player-token" header
  • For Map, add the Map-Token as the "map-token" header
  • For StoryPlaythrough, add the Story-Playthrough-Token as the "story-playthrough-token" header
info

If you're playing in Story mode, you only have to provide Story-Playthrough-Token. StoryPlaythrough refers to both Player and Map. If you provide Story-Playthrough-Token, you don't have to provide Player-Token or Map-Token.

Obtaining the tokens:

  • Player-Token: 1) Click the "Show Tokens" button on the right side of the game interface on ponypanic.io. or 2) If you already registered with an email, click the login button on ponypanic.io and follow the instructions to claim your token
  • Map-Token: Call POST freestyle/createMap (this creates a new Map so you can't obtain an existing Map's token this way)
  • Story-Playthrough-Token: Click the "Show Tokens" button on the right side of the game interface on ponypanic.io

Endpoints

All these endpoints are HTTP, use JSON in their request & response bodies, and require partial auth described in the Authentication section above. Their base URL is https://ponypanic.io/playGameApi/v1/.

POST play/tickMap

Ticks the map regardless if belonging heroes approved their round or not

GET play/mapState

Returns the current state of mutable elements on a map
Response:
1{
2    "map": {
3        "id": 99642,
4        "width": 5,
5        "height": 5,
6        "elapsedTickCount": 0,
7        "status": "PLAYING", // V1MapStatus
8        "isGameOver": false,
9        "treasures": [], // V1TreasureResponse array
10        "enemies": [], // V1EnemyResponse array
11        "bullets": [] // V1BulletResponse array
12    },
13    "heroes": [] // V1HeroResponse array
14}

$.status: V1MapStatus

$.map.treasures: The heroes present on the map. Schema: V1HeroResponse
$.map.treasures: The treasures present on the map. Schema: V1TreasureResponse
$.map.enemies: The enemies present on the map. Schema: V1EnemyResponse
$.map.bullets: The bullets present on the map. Schema: V1BulletResponse

GET play/mapResource

Returns immutable resources belonging to a map. Only call this endpoint once for a map!
Response:
1{
2    "compressedObstacles": {
3        "coordinateMap": {
4            "1": [ 2, 6, 8 ],
5            "2": [ 4, 5 ],
6            "4": [ 4, 8 ]
7        }
8    }
9}

The $.compressedObstacles.coordinateMap object contains the coordinates of obstacles on the map. The keys are the X coordinates and the arrays of each key are the Y coordinates belonging to the X coordinate in the key.

note

E.g. the { "x1": [y1, y2], "x2": [y3, y4] } coordinateMap means the following four obstacles: (x1;y1), (x1;y2), (x2;y3), (x2;y4)

POST play/approveHeroTurn

Sets the action that a Hero will do on the next tick of the Map and signs that the Hero is done with their turn. If all Heroes on the Map are done with their turns, this endpoint also triggers a Map tick
Request:
1{
2    "heroId": 17, // Ignore this if you're playing Story mode
3    "action": "NOTHING" // :HeroAction
4}

$.action is the action that the Hero will execute on the next tick of the Map. Schema: V1HeroAction

$.heroId is the ID of the Hero you set the action for. Ignore this parameter if you only have one Hero on the Map. Otherwise use the heroId you got back from POST freestyle/joinMap

POST story/begin

Creates a new StoryPlaythrough
Response:
1{
2    "storyPlaythroughId": 17,
3    "storyPlaythroughToken": "17_topsecret",
4    "playthroughState": V1PlaythroughStateResponse
5}

$.playthroughState: V1PlaythroughStateResponse

POST story/nextLevel

In story mode, increments the level stored in the StoryPlaythrough entity and generates a new map for the new level. If the map of the current level is not yet finished, an error is returned
Response:
1{
2    "playthroughState": V1PlaythroughStateResponse
3}

$.playthroughState: V1PlaythroughStateResponse

POST story/resetLevel

In story mode, generates a new map instead of the current one but does not increment the level stored in the StoryPlaythrough entity
Response:
1{
2    "playthroughState": V1PlaythroughStateResponse
3}

$.playthroughState: V1PlaythroughStateResponse

GET story/playthroughState

Gets the current state of a StoryPlaythrough entity

Response: V1PlaythroughStateResponse

POST freestyle/createMap

Creates a new map with custom parameters
Request:
1{
2    "width": 5, // nullable
3    "height": 5, // nullable
4    "treasureCount": 2, // nullable
5    "obstaclesPresent": true, // nullable
6    "enemyConfig": V1EnemyConfigRequest, // nullable
7}

$.enemyConfig: V1EnemyConfigRequest

POST freestyle/joinMap

Puts a new Hero onto the map
Response:
1{
2    "heroId": 17 // ID of the new Hero
3}

Schemas

V1PlaythroughStateResponse

State managed by a StoryPlaythrough entity
1{
2    "currentLevel": 1, // number - nth level
3    "isCurrentLevelFinished": false, // boolean
4    "currentMapStatus": "PLAYING", // V1MapStatus
5    "storyLine": "hi there" // string
6}

$.currentMapStatus: V1MapStatus

V1HeroResponse

Describes a "Hero" game element
1{
2    "id":1, // unique ID of the Hero
3    "position": {
4        "x": 4,
5        "y": 2
6    },
7    "health": 1.0, // dies when reaches 0
8}

V1TreasureResponse

Describes a "Treasure" game element
1{
2    "id":1, // unique ID of the Treasure
3    "position": {
4        "x": 4,
5        "y": 2
6    },
7    "name": "Some treasure",
8    "collectedByHeroId": null // null or number
9}

$.collectedByHeroId:

  • If null: the treasure is still free to collect
  • If a number: the treasure was already collected by the Hero of this ID

V1EnemyResponse

Describes an "Enemy" game element
1{
2    "id":1, // unique ID of the Enemy
3    "position": {
4        "x": 4,
5        "y": 2
6    },
7    "moveProbability": 0.2, // chance to step to a neighbouring field in a tick
8    "shootProbability": 0.3, // chance to release a bullet in a tick
9    "onTouchDamage": 0.4, // deals this much damage in every tick when located on the same field as a Hero
10    "bulletDamage": 0.5, // shoots bullets that has this much damage
11    "health": 0.6, // dies when reaches 0
12}

V1BulletResponse

Describes a "Bullet" game element
1{
2    "id":1, // unique ID of the Bullet
3    "position": {
4        "x": 4,
5        "y": 2
6    },
7    "damage": 0.3,
8    "direction": "RIGHT", // V1Direction
9    "shotByEnemyId": 23
10}

$.direction: The Bullet steps one field in this direction on every tick of the Map. Schema: V1Direction
$.damage: When the Bullet hits a Hero who does not use a shield, it deals this much damage

V1HeroAction

An enum representing actions executable by Heroes on map ticks

Possible values: "NOTHING", "USE_SHIELD", "MOVE_LEFT", "MOVE_RIGHT", "MOVE_UP", "MOVE_DOWN", "KICK_LEFT", "KICK_RIGHT","KICK_UP", "KICK_DOWN".

V1MapStatus

An enum indicating the current status of the map

Possible values: "CREATED", "PLAYING", "WON", "LOST".
If a Map's status is "WON" or "LOST", no more Heroes can join or play on it.

V1Direction

An enum representing a direction on the map

Possible values: "NONE", "LEFT", "RIGHT", "UP" (north), "DOWN" (south)

V1EnemyConfigRequest

Configures how enemies should be generated when generating a new map
1{
2    "count": number, // count of enemies to put on the map 
3    "canMove": boolean, // sets if enemies can move
4    "canShoot": boolean, // sets if enemies can shoot
5    "canDamageOnTouch": boolean, // sets if enemies can deal damage when they touch a Hero 
6}

Powered by

Privacy Policy|Feedback & Report a bug