From 228a1e4afbc849be20cf0cf48d1913d7301c91ec Mon Sep 17 00:00:00 2001 From: homer Date: Mon, 19 Oct 2026 11:31:47 +0200 Subject: [PATCH] Ajoute les extensions et Harmonies : Crescendo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Format expansions/-/ (expansion.json, rules.fr.json), schémas expansion et expansion-rules, guide de contribution - Harmonies : choix de la face des plateaux personnels (A/B), module Esprits de la nature renommé - Crescendo (472690) : modules Sanctuaires et Murmures, faces C et D, fiche de règles résumée Co-Authored-By: Claude Opus 5.5 --- CONTRIBUTING.md | 52 +++ README.md | 4 + .../472690-crescendo/expansion.json | 38 ++ .../expansions/472690-crescendo/rules.fr.json | 10 + games/414317-harmonies/scoring.json | 18 +- schemas/expansion-rules.schema.json | 60 +++ schemas/expansion.schema.json | 412 ++++++++++++++++++ 7 files changed, 593 insertions(+), 1 deletion(-) create mode 100644 games/414317-harmonies/expansions/472690-crescendo/expansion.json create mode 100644 games/414317-harmonies/expansions/472690-crescendo/rules.fr.json create mode 100644 schemas/expansion-rules.schema.json create mode 100644 schemas/expansion.schema.json diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cbbeb23..6cbc30f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,6 +47,58 @@ relue avant publication. Le CI vérifie automatiquement les fichiers. ligne autorisés. **Rédigez avec vos propres mots** : pas de copier-coller du livret de l'éditeur. +## Ajouter une extension + +Une **variante incluse dans la boîte** du jeu (mode alternatif, règle +optionnelle) est une **option** dans `scoring.json`. Un **produit vendu à +part, avec sa propre fiche BoardGameGeek**, est une **extension** : + +``` +games/414317-harmonies/ + expansions/ + 472690-crescendo/ # - + expansion.json # obligatoire + rules.fr.json # facultatif : seulement ce qui change +``` + +`expansion.json` décrit uniquement ce que l'extension **ajoute** au modèle du +jeu de base : + +```json +{ + "$schema": "../../../../schemas/expansion.schema.json", + "schemaVersion": 1, + "bggId": 472690, + "name": "Crescendo", + "adds": { + "options": [ + { "type": "boolean", "id": "murmures", "label": "Module Murmures", "default": true } + ], + "choices": [ + { "optionId": "plateau", "values": [{ "value": "C", "label": "Face C" }] } + ], + "categories": [ + { "id": "murmures", "label": "Murmures", "requiresOption": "murmures", "after": "animaux" } + ] + } +} +``` + +- `options` : chaque **module** de l'extension devient une option, que les + joueurs cochent au lancement de la partie. +- `choices` : nouvelles valeurs pour un choix existant du jeu de base. +- `categories` : nouvelles catégories de score, placées après `after` (sinon + à la fin) ; `requiresOption` les lie au module correspondant. +- `players` / `end` : remplacent le nombre de joueurs ou la fin de partie. + +Le CI vérifie que l'extension s'applique au jeu de base, et que toutes les +extensions d'un jeu peuvent être jouées ensemble (pas deux fois le même +identifiant, pas deux extensions qui changent la même règle). + +La fiche de règles d'une extension (`rules.fr.json`, schéma +`expansion-rules.schema.json`) n'exige que `summary` : décrivez ce qui change +(mise en place, déroulement, décompte), pas tout le jeu. + ## Vérifier avant d'envoyer Avec un éditeur qui comprend les schémas JSON (VS Code…), la clé `$schema` diff --git a/README.md b/README.md index b4e7275..59d61ed 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,10 @@ games/ scoring.json # modèle de score (comment compter les points) rules.fr.json # fiche de règles en français README.md # notes libres (facultatif) + expansions/ # extensions vendues à part (une par dossier) + -/ + expansion.json # ce que l'extension ajoute au jeu de base + rules.fr.json # ce qui change dans les règles schemas/ # schémas JSON (autocomplétion dans l'éditeur) ``` diff --git a/games/414317-harmonies/expansions/472690-crescendo/expansion.json b/games/414317-harmonies/expansions/472690-crescendo/expansion.json new file mode 100644 index 0000000..1bef88c --- /dev/null +++ b/games/414317-harmonies/expansions/472690-crescendo/expansion.json @@ -0,0 +1,38 @@ +{ + "$schema": "../../../../schemas/expansion.schema.json", + "schemaVersion": 1, + "bggId": 472690, + "name": "Crescendo", + "adds": { + "options": [ + { "type": "boolean", "id": "sanctuaires", "label": "Module Sanctuaires", "default": true }, + { "type": "boolean", "id": "murmures", "label": "Module Murmures", "default": true } + ], + "choices": [ + { + "optionId": "plateau", + "values": [ + { "value": "C", "label": "Face C (Crescendo)" }, + { "value": "D", "label": "Face D (Crescendo)" } + ] + } + ], + "categories": [ + { + "id": "sanctuaires", + "label": "Sanctuaires", + "icon": "Castle", + "color": "#0e7490", + "requiresOption": "sanctuaires", + "after": "animaux" + }, + { + "id": "murmures", + "label": "Murmures", + "icon": "Gem", + "color": "#a855f7", + "requiresOption": "murmures" + } + ] + } +} diff --git a/games/414317-harmonies/expansions/472690-crescendo/rules.fr.json b/games/414317-harmonies/expansions/472690-crescendo/rules.fr.json new file mode 100644 index 0000000..b3cdd96 --- /dev/null +++ b/games/414317-harmonies/expansions/472690-crescendo/rules.fr.json @@ -0,0 +1,10 @@ +{ + "$schema": "../../../../schemas/expansion-rules.schema.json", + "schemaVersion": 1, + "locale": "fr", + "summary": "Trois modules indépendants, à combiner entre eux et avec les modules du jeu de base : les Sanctuaires, de nouveaux plateaux personnels (faces C et D) et les Murmures.", + "setup": "Choisissez ensemble les modules utilisés avant de commencer.\nSanctuaires : mélangez les tuiles en pioche, face « en cours » visible, et révélez-en 2 à côté (3 tuiles visibles avec celle de la pioche).\nNouveaux plateaux : tous les joueurs jouent la même face, C ou D, avec la carte d'aide correspondante.\nMurmures : ajoutez les cartes Murmure au paquet Animaux avant de le mélanger, et gardez les cubes violets à portée de main.", + "turn": "Sanctuaires : en plus de vos actions, vous pouvez prendre une tuile Sanctuaire visible. Elle compte comme une carte (4 au maximum au-dessus du plateau) et autorise une pile de jetons normalement interdite, selon le motif indiqué. Une fois le motif terminé, retournez la tuile : le dernier cube d'une carte Animal de l'une de ses deux couleurs peut alors être posé sur ce Sanctuaire.\nFace C : la case centrale n'existe pas.\nFace D : certaines cases sont sèches au départ ; une case sèche devient ordinaire dès qu'elle touche de l'eau.\nMurmures : une carte Murmure se prend à la place d'une carte Animal. On pose ses 2 cubes violets sur le motif réalisé ; un cube Murmure peut partager une case avec un cube Animal ou Esprit.", + "scoring": "Sanctuaires : chaque Sanctuaire terminé rapporte 3 points par case voisine dont le jeton du dessus est de l'une de ses deux couleurs. Un Sanctuaire ne compte pour aucun paysage (rivière, montagne, champ).\nFace C : un Bâtiment rapporte 8 points s'il est entouré d'au moins 4 couleurs différentes, sinon rien.\nFace D : Arbres et Champs rapportent davantage sur les cases ordinaires, et rien sur une case restée sèche à la fin. Un Champ d'au moins 2 jetons jaunes rapporte 6 points si l'un d'eux est sur une case ordinaire.\nMurmures : 2 points par case avec un cube Murmure seul, 5 points si la case contient aussi un cube Animal ou Esprit.", + "tips": "Pour découvrir l'extension progressivement : Sanctuaires seuls (face A), puis Murmures (face D), puis les deux (face C), et enfin tout avec les Esprits de la nature (face B)." +} diff --git a/games/414317-harmonies/scoring.json b/games/414317-harmonies/scoring.json index 1be6813..80986f3 100644 --- a/games/414317-harmonies/scoring.json +++ b/games/414317-harmonies/scoring.json @@ -21,8 +21,24 @@ { "type": "boolean", "id": "esprits_nature", - "label": "Extension : Esprits de la nature", + "label": "Module Esprits de la nature", "default": false + }, + { + "type": "select", + "id": "plateau", + "label": "Face des plateaux personnels", + "default": "A", + "choices": [ + { + "value": "A", + "label": "Face A" + }, + { + "value": "B", + "label": "Face B" + } + ] } ], "categories": [ diff --git a/schemas/expansion-rules.schema.json b/schemas/expansion-rules.schema.json new file mode 100644 index 0000000..e17f0e5 --- /dev/null +++ b/schemas/expansion-rules.schema.json @@ -0,0 +1,60 @@ +{ + "type": "object", + "properties": { + "$schema": { + "type": "string" + }, + "schemaVersion": { + "type": "number", + "const": 1 + }, + "locale": { + "type": "string", + "enum": [ + "fr" + ], + "default": "fr" + }, + "summary": { + "type": "string", + "maxLength": 300, + "minLength": 1 + }, + "goal": { + "type": "string", + "maxLength": 1000 + }, + "setup": { + "type": "string", + "maxLength": 3000 + }, + "turn": { + "type": "string", + "maxLength": 5000 + }, + "end": { + "type": "string", + "maxLength": 2000 + }, + "scoring": { + "type": "string", + "maxLength": 3000 + }, + "tips": { + "type": "string", + "maxLength": 2000 + }, + "officialRulesUrl": { + "type": "string", + "format": "uri", + "pattern": "^https\\:\\/\\/" + } + }, + "required": [ + "schemaVersion", + "summary" + ], + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Fiche de règles d'une extension (rules.fr.json)" +} diff --git a/schemas/expansion.schema.json b/schemas/expansion.schema.json new file mode 100644 index 0000000..f4f2b5a --- /dev/null +++ b/schemas/expansion.schema.json @@ -0,0 +1,412 @@ +{ + "type": "object", + "properties": { + "$schema": { + "type": "string" + }, + "schemaVersion": { + "type": "number", + "const": 1 + }, + "bggId": { + "type": "integer", + "exclusiveMinimum": 0 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 60 + }, + "officialRulesUrl": { + "type": "string", + "format": "uri", + "pattern": "^https\\:\\/\\/" + }, + "adds": { + "type": "object", + "properties": { + "options": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "boolean" + }, + "id": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "pattern": "^[a-z0-9][a-z0-9_-]*$" + }, + "label": { + "type": "string", + "minLength": 1, + "maxLength": 80 + }, + "default": { + "type": "boolean" + }, + "visibleWhen": { + "type": "object", + "properties": { + "optionId": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "pattern": "^[a-z0-9][a-z0-9_-]*$" + }, + "equals": { + "type": [ + "boolean", + "number", + "string" + ] + } + }, + "required": [ + "optionId", + "equals" + ], + "additionalProperties": false + } + }, + "required": [ + "type", + "id", + "label", + "default" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "number" + }, + "id": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "pattern": "^[a-z0-9][a-z0-9_-]*$" + }, + "label": { + "type": "string", + "minLength": 1, + "maxLength": 80 + }, + "default": { + "type": "number" + }, + "min": { + "type": "number" + }, + "max": { + "type": "number" + }, + "visibleWhen": { + "type": "object", + "properties": { + "optionId": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "pattern": "^[a-z0-9][a-z0-9_-]*$" + }, + "equals": { + "type": [ + "boolean", + "number", + "string" + ] + } + }, + "required": [ + "optionId", + "equals" + ], + "additionalProperties": false + } + }, + "required": [ + "type", + "id", + "label", + "default" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "select" + }, + "id": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "pattern": "^[a-z0-9][a-z0-9_-]*$" + }, + "label": { + "type": "string", + "minLength": 1, + "maxLength": 80 + }, + "default": { + "type": "string" + }, + "choices": { + "type": "array", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string" + }, + "label": { + "type": "string", + "minLength": 1, + "maxLength": 80 + } + }, + "required": [ + "value", + "label" + ], + "additionalProperties": false + }, + "minItems": 1 + }, + "visibleWhen": { + "type": "object", + "properties": { + "optionId": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "pattern": "^[a-z0-9][a-z0-9_-]*$" + }, + "equals": { + "type": [ + "boolean", + "number", + "string" + ] + } + }, + "required": [ + "optionId", + "equals" + ], + "additionalProperties": false + } + }, + "required": [ + "type", + "id", + "label", + "default", + "choices" + ], + "additionalProperties": false + } + ] + }, + "default": [] + }, + "choices": { + "type": "array", + "items": { + "type": "object", + "properties": { + "optionId": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "pattern": "^[a-z0-9][a-z0-9_-]*$" + }, + "values": { + "type": "array", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string" + }, + "label": { + "type": "string", + "minLength": 1, + "maxLength": 80 + } + }, + "required": [ + "value", + "label" + ], + "additionalProperties": false + }, + "minItems": 1 + } + }, + "required": [ + "optionId", + "values" + ], + "additionalProperties": false + }, + "default": [] + }, + "categories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "pattern": "^[a-z0-9][a-z0-9_-]*$" + }, + "label": { + "type": "string", + "minLength": 1, + "maxLength": 80 + }, + "icon": { + "type": "string", + "maxLength": 40 + }, + "color": { + "type": "string", + "pattern": "^#[0-9a-fA-F]{6}$" + }, + "requiresOption": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "pattern": "^[a-z0-9][a-z0-9_-]*$" + }, + "after": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "pattern": "^[a-z0-9][a-z0-9_-]*$" + } + }, + "required": [ + "id", + "label" + ], + "additionalProperties": false + }, + "default": [] + }, + "players": { + "type": "object", + "properties": { + "min": { + "type": "integer", + "minimum": 1, + "maximum": 30 + }, + "max": { + "type": "integer", + "minimum": 1, + "maximum": 30 + } + }, + "required": [ + "min", + "max" + ], + "additionalProperties": false + }, + "end": { + "type": "object", + "properties": { + "target": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "fixed" + }, + "value": { + "type": "number" + } + }, + "required": [ + "type", + "value" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "option" + }, + "optionId": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "pattern": "^[a-z0-9][a-z0-9_-]*$" + }, + "customValue": { + "type": "string" + }, + "customOptionId": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "pattern": "^[a-z0-9][a-z0-9_-]*$" + } + }, + "required": [ + "type", + "optionId" + ], + "additionalProperties": false + } + ] + }, + "targetCondition": { + "type": "string", + "enum": [ + "reaches", + "exceeds" + ], + "default": "reaches" + }, + "rounds": { + "type": "integer", + "exclusiveMinimum": 0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false, + "default": {} + } + }, + "required": [ + "schemaVersion", + "bggId", + "name" + ], + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Extension Skori (expansion.json)" +}