# Wyvern&Castle

## Sujet et tache
Ceci est un projet de **modèle MCP** ([Model Context Protocol](https://modelcontextprotocol.io/docs/getting-started/intro)) pour le cours de **Natural Language Programming** de l'année 2025-2026.

L'objectif du projet a été de concevoir une **version simplifié du jeu Donjon & Dragon** avec un LLM capable de générer des parties et des scénarios qui n'ont de limite que votre imagination (et celles du LLM aussi!).
Le projet contient un serveur (`server.py`) qui intéragit avec notre API de jeu (`game.py`) via un système d'outils (MCP tooling) asynchrone afin de pouvoir enchainer les outils sans trop de délais d'interruption pour les appels long.

## Installation des dépendances
Pour lancer une partie de notre jeu, il faudra installer **l'utilitaire python `UV`** qui est similaire à `pip` ainsi qu'une **application qui contient un LLM** de bureau.

Nous vous conseillons d'installer **[Claude Desktop](https://claude.com/fr-fr/download)** (disponible sur Windows
et Mac) qui va servir de LLM de base. Nous n'avons pas essayé pour ce projet mais il serait aussi possible d'utiliser la **version Desktop de ChatGPT**.

**1. Installation de UV :**
```bash
# Mac/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows, l'ajouter au Path
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```

**2. Initialiser le dossier pour l'installation**
Creer un dossier et cloner le projet :
```bash
mkdir wyvern_castle
cd wyvern_castle
git clone "https://gitea.galaxynoliro.fr/KuMiShi/Wyvern-Castle.git"
```
**3. Creation de l'environnement virtuel**
```bash
# Cela est nécessaire afin de pouvoir télécharger les librairies du projet
uv venv
```
Mac/Linux
```bash
# Activation du venv
source .venv/bin/activate
```
Windows
```Powershell
# Activation du venv
.\.venv\Scripts\activate
```

**4. Installation des dependances/requirements python**
```bash
# Synchronise l'environnement virtuel du dossier avec les dependances du projet
uv pip sync pyproject.toml

# Si cela ne fonctionne pas correctement, vous pouvez le générer un fichier de dependances avec la commande suivante à partir du .toml:
uv pip compile --upgrade pyproject.toml -o uv.lock
# Puis synchroniser à nouveau (avec le nouveau fichier cette fois)
uv pip sync uv.lock
```

**5. Configuration de Claude Desktop**
Il faut d'abord se rendre dans les **Paramètres > Développeur** en cliquant sur l'icône du profil en bas à gauche de la fenêtre.
<div align="center">
  <img src="images/parameter_claude.PNG"/>
</div>

Une fois dans la partie dev, il faut rajouter la configuration suivante en modifier le fichier `claude_desktop_config.json` par le json ci-dessous:
```json
{
  "mcpServers": {
        "wyvern_castle": {
            "command": "uv",
            "args": [
            "--directory",
            "C:\\ABSOLUTE\\PATH\\TO\\PARENT\\FOLDER\\wyvern_castle",
            "run",
            "server.py"
            ]
        }
    }
}
```
Si la configuration a bien été effectuée, vous devriez voir le tag `running` à côté du modèle. Autrement, il faudra sûrement **redémarrer l'application**. Si jamais ca ne fonctionne toujours pas, vous pouvez
aller **regarder les logs** ("journaux") pour diagnostiquer l'erreur.

## Utilisation
<div align="center">
  <img src="images/create_player.gif"/>
</div>

Une fois les configurations terminées et que notre modèle tourne bien en local, vous pouvez vous rendre dans **Discussion** et verifier dans l'icône **(+) -> Connecteurs** que votre modèle wyvern_castle est bien coché:

<div align="center">
  <img src="images/connector.png"/>
</div>

Si cela est bien coché, alors il ne vous reste plus qu'à écrire votre prompt et laisser l'IA utilise nos outils MCP:
<div align="center">
  <img src="images/game_party_state.gif"/>
</div>

## Documentation
### Tools / Outils
Outils liés à la gestion de la partie :

```python
# Charge une sauvegarde
async def load_game(slot:int)
# Sauvegarde une partie
async def save_game(slot:int)
# Récupère le contexte de la partie pour se remettre à jour
async def get_game_state()
```

Routines de création de contenu :
```python
# Crée un joueur
async def create_npc(name: str, strength: int, dexterity: int, intelligence: int, wisdom: int, charisma: int, hp: int, armor: int, speed: int, item_id:str)
# Crée un personnage non-joueur
async def create_player(name: str, strength: int, dexterity: int, intelligence: int, wisdom: int, charisma: int, hp: int, armor: int, speed: int, item_id:str)
# Crée un objet
async def create_item(name: str, description: str, stat_modifier: dict[str,int])
# Crée un événement (fonctionne comme un contexte de combat, d'exploration, etc.)
async def start_event(location:str, initial_description:str, entity_list:list[str])
```

Routines d'actions du joueur et du système
```python
# Lance une attaque
async def perform_attack(src_entity_id:str, target_entity_id:str, attack_type:Stat)
# Lance un test (ex: crocheter une serrure, soulever un poids)
async def perform_simple_action(entity_id:str, stat:Stat, difficulty:int, roll:int, description:str)
# Modifie une statistique (se faire maudire, boire une potion)
async def perform_stat_modification(entity_id:str, stat:Stat, value:int=0)
# Donne un objet à une entité
async def equip_item_to_entity(entity_id: str, item_id: str)
```

Routines utilitaires :
```python
# Récupère les propriétés d'un objet
async def get_item_properties(item_id: str) -> Dict[str, Any]
# Récupère les propriétés d'une entité
async def get_entity_status(entity_id: str) -> Dict[str, Any]
# Récupère l'événement en cours
async def get_current_event() -> Dict[str, Any]
# Récupère la liste de toutes les entités actives
async def get_all_entities_status()
# Lance un dé
async def throw_a_dice(n_faces: int) -> Any
# Lance une pièce
async def toss_coin()
```
