---
# System prepended metadata

title: 'CAR-1: Quests'

---

# CAR-1: Quests

This specification defines a method to manage on-chain quest status for video games.

## Motivation

As the on-chain gaming space grows it is important to define a standard for handling quests that allows for easy indexing. This enables external platforms to display a game's quest progress, their completion criteria, and allowing them to then mint rewards on the completion of these quests in a permissionless manner.

## Implementation

A quest is defined when the `quest_progress` event is emitted with a unique ID field and a [metadata URI](#metadata-uri). Its status is updated via events that are emitted as a result of a player's in-game actions.

Quests can have a one-to-many relationship to other quests. Child quests need to be completed by the player first before the parent can be completed. A quest's completion criteria is defined in the [metadata](#metadata-uri).

### Interface

#### Contract

```cairo
@event
func quest_progress(
  id: felt,
  player: felt,
  metadata_len: felt,
  metadataURI: felt*
) -> ()
```

#### Metadata URI

The value of `metadataURI` should be a data URI (`data:application/json,...`) or an IPFS Content ID (`ipfs://...`) that resolves to a JSON object.

The following metadata fields are required:

```json
{
  "title": "string",
  "description": "string"
}
```

Supported optional fields:

```json
{
  "completion": {
    "all": [
      {
        "id": "number",
        "count": "number"
      }
    ],
    "any": [
      {
        "id": "number",
        "count": "number"
      },
      {
        "id": "number",
        "count": "number"
      }
    ]
  },
  "imageURI": "string"
}
```

The `completion` object can contain arrays with the following keys:

- `all` - Contains references to quests that **all** need to be completed
- `any` - Contains references to quests where **any** one needs to be completed

The objects in the arrays have the fields:

- `id` - The `id` of the child quest we are referencing
- `count` - The number of times the child quest needs be completed per player


### Creating a quest

If a quest does not have completion criteria then `completion` can be omitted from its metadata. These are completed for the player as soon as the event is emitted.

---
**Use the zero address as the player when defining the quest**

---

1. Emit the `quest_progress` event to create a quest for any tasks that will be part of the completion criteria
1. Emit the `quest_progress` event to create the quest for the parent, including the child quests if it has any in its metadata

### Completing a quest

Any time the `quest_progress` event is emitted and it either does not have completion criteria, or the completion criteria is met, the quest is completed. quests can be completed multiple times.

quests without `completion` in its metadata will be completed for the player as soon as the event is emitted.

If it does have completion criteria:

1. Complete any child quests in the completion criteria first by emitting the `quest_progress` events for at least as many times as the criteria requires
1. Emit `quest_progress` for the parent quest when all completion criteria is satisfied to complete it

## Example

Consider the following quest:

In Hyrule, destroy
- 3 Stalchildren
- 1 Stalfo OR 5 Deku Babas

First create the quest for each task:

**Note: json() is used for brevity**

```cairo
// Note that we do not include completion 
// criteria for these tasks
quest_progress.emit(
  id=1,
  player=0,
  metadata_len=4,
  metadataURI=json('{
    "title": "Destroy a Stalchild",
    "description": "They come out at night in Hyrule Field"
  }'),
);
quest_progress.emit(
  id=2,
  player=0,
  metadata_len=4,
  metadataURI=json('{
    "title": "Destroy a Stalfo",
    "description": "They come out at night in Hyrule Field"
  }'),
);
quest_progress.emit(
  id=3,
  player=0,
  metadata_len=4,
  metadataURI=json('{
    "title": "Destroy a Deku Baba",
    "description": "They can be found throughout Hyrule"
  }'),
);
```

Now we can use those quests as completion criteria:

```cairo
quest_progress.emit(
  id=4,
  player=0,
  metadata_len=7,
  metadataURI=json('{
    "title": "Monster Hunting",
    "description": "
      - Destroy 3 Stalchildren 
      - Destroy 1 Stalfo OR 5 Deku Babas
    ",
    "completion": {
      "all": [
        {
          "id": 1,
          "count": 3
        }
      ],
      "any": [
        {
          "id": 2,
          "count": 1
        },
        {
          "id": 3,
          "count": 5
        }
      ]
    }
  }')
);
```

Now we have a small progress tree defined for this quest. It can easily be extended by including completion criteria that in turn has its own completion criteria.

```mermaid
flowchart TD

q4["Monster Hunting"]
q3["Destroy a Stalchild"]

subgraph ANY
  q2["Destroy a Stalfo"]
  q1["Destroy a Deku Baba"]
end

q4 --3--> q3
q4 --1--> q2
q4 --5--> q1
```


Before the parent quest can be completed, the player (0x123) should perform actions that will result in the following events emitted:

```cairo
// Stalchildren
quest_progress(id=1, player=0x123, ...)
quest_progress(id=1, player=0x123, ...)
quest_progress(id=1, player=0x123, ...)

// Stalfos
quest_progress(id=2, player=0x123, ...)
quest_progress(id=2, player=0x123, ...)

// OR Deku Babas
quest_progress(id=3, player=0x123, ...)
quest_progress(id=3, player=0x123, ...)
quest_progress(id=3, player=0x123, ...)
quest_progress(id=3, player=0x123, ...)
quest_progress(id=3, player=0x123, ...)
```

At this point we can emit the event with the parent quest and it will be considered completed:

```cairo
quest_progress(id=4, player=0x123, ...)
```
