Advertisement
Shisui_Daniel

Untitled

Jul 16th, 2025
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 22.05 KB | Source Code | 0 0
  1. const fs = require('fs');
  2. const fetch = require('node-fetch');
  3.  
  4. // Chemins de sauvegarde
  5. const SAVE_PATH = './damier_games.json';
  6. const STATS_PATH = './damier_stats.json';
  7.  
  8. // Chargement & sauvegarde des parties
  9. const damierGames = {};
  10. const playerStats = {};
  11. function saveGames() { fs.writeFileSync(SAVE_PATH, JSON.stringify(damierGames, null, 2)); }
  12. function loadGames() { if (fs.existsSync(SAVE_PATH)) Object.assign(damierGames, JSON.parse(fs.readFileSync(SAVE_PATH))); }
  13. function saveStats() { fs.writeFileSync(STATS_PATH, JSON.stringify(playerStats, null, 2)); }
  14. function loadStats() { if (fs.existsSync(STATS_PATH)) Object.assign(playerStats, JSON.parse(fs.readFileSync(STATS_PATH))); }
  15. loadGames();
  16. loadStats();
  17.  
  18. // Emojis par dΓ©faut
  19. let DEFAULTS = {
  20.   EMPTY: "🟩",
  21.   PION_B: "βšͺ",
  22.   PION_N: "⚫",
  23.   DAME_B: "πŸ”΅",
  24.   DAME_N: "πŸ”΄"
  25. };
  26.  
  27. // GΓ©nΓ©rer un damier de base
  28. function createDamierBoard() {
  29.   const { EMPTY, PION_B, PION_N } = DEFAULTS;
  30.   const board = Array.from({ length: 8 }, () => Array(8).fill(EMPTY));
  31.   for (let i = 0; i < 3; i++)
  32.     for (let j = 0; j < 8; j++)
  33.       if ((i + j) % 2 === 1) board[i][j] = PION_N;
  34.   for (let i = 5; i < 8; i++)
  35.     for (let j = 0; j < 8; j++)
  36.       if ((i + j) % 2 === 1) board[i][j] = PION_B;
  37.   return board;
  38. }
  39.  
  40. // Affichage du damier
  41. function displayDamier(board) {
  42.   let s = "  a b c d e f g h\n";
  43.   for (let i = 0; i < 8; i++) {
  44.     s += (8 - i) + " ";
  45.     for (let j = 0; j < 8; j++)
  46.       s += board[i][j] + " ";
  47.     s += "\n";
  48.   }
  49.   return s;
  50. }
  51.  
  52. // Historique
  53. function displayHistory(history) {
  54.   if (!history || !history.length) return '';
  55.   return "πŸ“| Historique :\n" + history.map(
  56.     (h, i) => `${i+1}. ${h.player}: ${h.move}`
  57.   ).join('\n') + '\n';
  58. }
  59.  
  60. // DΓ©tection de move
  61. function parseDamierMove(move) {
  62.   const regex = /^([a-h][1-8])\s+([a-h][1-8])$/i;
  63.   const match = move.match(regex);
  64.   if (!match) return null;
  65.   const pos = (p) => [8 - Number(p[1]), p.charCodeAt(0) - 97];
  66.   return [pos(match[1].toLowerCase()), pos(match[2].toLowerCase())];
  67. }
  68.  
  69. // Utilitaires
  70. function isInside(x, y) { return x >= 0 && x < 8 && y >= 0 && y < 8; }
  71. function hasPieces(board, pion, dame) {
  72.   return board.flat().some(cell => cell === pion || cell === dame);
  73. }
  74. function updateStats(winnerID, loserID) {
  75.   if (!playerStats[winnerID]) playerStats[winnerID] = { win: 0, lose: 0 };
  76.   if (!playerStats[loserID]) playerStats[loserID] = { win: 0, lose: 0 };
  77.   playerStats[winnerID].win++;
  78.   playerStats[loserID].lose++;
  79.   saveStats();
  80. }
  81.  
  82. // Mouvement lΓ©gal (inclut prise pour dames et pions)
  83. function isValidMoveDamier(board, from, to, player) {
  84.   const { EMPTY, PION_B, PION_N, DAME_B, DAME_N } = DEFAULTS;
  85.   const [fx, fy] = from, [tx, ty] = to;
  86.   if (!isInside(fx, fy) || !isInside(tx, ty)) return false;
  87.   const piece = board[fx][fy];
  88.   if (board[tx][ty] !== EMPTY) return false;
  89.   // Pion blanc
  90.   if (piece === PION_B) {
  91.     if (fx - tx === 1 && Math.abs(ty - fy) === 1) return true; // avance simple
  92.     if (fx - tx === 2 && Math.abs(ty - fy) === 2) {
  93.       const midX = fx - 1, midY = fy + (ty - fy) / 2;
  94.       if ([PION_N, DAME_N].includes(board[midX][midY])) return "prise";
  95.     }
  96.   }
  97.   // Pion noir
  98.   if (piece === PION_N) {
  99.     if (tx - fx === 1 && Math.abs(ty - fy) === 1) return true;
  100.     if (tx - fx === 2 && Math.abs(ty - fy) === 2) {
  101.       const midX = fx + 1, midY = fy + (ty - fy) / 2;
  102.       if ([PION_B, DAME_B].includes(board[midX][midY])) return "prise";
  103.     }
  104.   }
  105.   // Dame blanche
  106.   if (piece === DAME_B) {
  107.     if (Math.abs(fx - tx) === Math.abs(fy - ty)) {
  108.       const dx = tx > fx ? 1 : -1, dy = ty > fy ? 1 : -1;
  109.       let x = fx + dx, y = fy + dy, found = false;
  110.       while (x !== tx && y !== ty) {
  111.         if ([PION_N, DAME_N].includes(board[x][y])) {
  112.           if (found) return false;
  113.           found = true;
  114.         } else if (board[x][y] !== EMPTY) return false;
  115.         x += dx; y += dy;
  116.       }
  117.       return found ? "prise" : true;
  118.     }
  119.   }
  120.   // Dame noire
  121.   if (piece === DAME_N) {
  122.     if (Math.abs(fx - tx) === Math.abs(fy - ty)) {
  123.       const dx = tx > fx ? 1 : -1, dy = ty > fy ? 1 : -1;
  124.       let x = fx + dx, y = fy + dy, found = false;
  125.       while (x !== tx && y !== ty) {
  126.         if ([PION_B, DAME_B].includes(board[x][y])) {
  127.           if (found) return false;
  128.           found = true;
  129.         } else if (board[x][y] !== EMPTY) return false;
  130.         x += dx; y += dy;
  131.       }
  132.       return found ? "prise" : true;
  133.     }
  134.   }
  135.   return false;
  136. }
  137.  
  138. // Promotion
  139. function checkPromotion(board) {
  140.   const { PION_B, PION_N, DAME_B, DAME_N } = DEFAULTS;
  141.   for (let j = 0; j < 8; j++) {
  142.     if (board[0][j] === PION_B) board[0][j] = DAME_B;
  143.     if (board[7][j] === PION_N) board[7][j] = DAME_N;
  144.   }
  145. }
  146.  
  147. // Liste des coups lΓ©gaux
  148. function getAllLegalMoves(board, player) {
  149.   const { PION_B, DAME_B, PION_N, DAME_N } = DEFAULTS;
  150.   const moves = [];
  151.   const myPion = player === 0 ? PION_B : PION_N;
  152.   const myDame = player === 0 ? DAME_B : DAME_N;
  153.   for (let fx = 0; fx < 8; fx++)
  154.     for (let fy = 0; fy < 8; fy++)
  155.       if ([myPion, myDame].includes(board[fx][fy]))
  156.         for (let tx = 0; tx < 8; tx++)
  157.           for (let ty = 0; ty < 8; ty++)
  158.             if ((fx !== tx || fy !== ty) && isValidMoveDamier(board, [fx, fy], [tx, ty], player === 0 ? "blanc" : "noir"))
  159.               moves.push([[fx, fy], [tx, ty]]);
  160.   return moves;
  161. }
  162.  
  163. // Prise multiple obligatoire
  164. function canContinueTaking(board, pos, player) {
  165.   const { EMPTY, PION_B, PION_N, DAME_B, DAME_N } = DEFAULTS;
  166.   const [fx, fy] = pos;
  167.   const piece = board[fx][fy];
  168.   const directions = [[-2, -2], [-2, 2], [2, -2], [2, 2]];
  169.   for (const [dx, dy] of directions) {
  170.     const tx = fx + dx, ty = fy + dy;
  171.     if (!isInside(tx, ty)) continue;
  172.     if (isValidMoveDamier(board, [fx, fy], [tx, ty], player) === "prise")
  173.       return [tx, ty];
  174.   }
  175.   return null;
  176. }
  177.  
  178. // Bot choix
  179. function botChooseMove(moves, board, level) {
  180.   if (level === 0) return moves[Math.floor(Math.random() * moves.length)];
  181.   if (level === 1) {
  182.     return moves.find(([from, to]) => isValidMoveDamier(board, from, to, "noir") === "prise") || moves[0];
  183.   }
  184.   // Pour niveau difficile, ici on fait pareil (Γ  amΓ©liorer)
  185.   return moves.find(([from, to]) => isValidMoveDamier(board, from, to, "noir") === "prise") || moves[0];
  186. }
  187.  
  188. // Tour bot
  189. async function botPlay(game, api, threadID) {
  190.   const board = game.board;
  191.   const moves = getAllLegalMoves(board, 1);
  192.   if (moves.length === 0) {
  193.     game.inProgress = false;
  194.     const winner = game.players[0];
  195.     await api.sendMessage(
  196.       `${displayDamier(board)}\n${displayHistory(game.history)}\n\nπŸŽ‰| ${winner.name} πš›πšŽπš–πš™πš˜πš›πšπšŽ πš•πšŠ πš™πšŠπš›πšπš’πšŽ !`,
  197.       threadID
  198.     );
  199.     return;
  200.   }
  201.   let botMove = botChooseMove(moves, board, game.botLevel || 0);
  202.   let [[fx, fy], [tx, ty]] = botMove;
  203.   let piece = board[fx][fy];
  204.  
  205.   // Undo stack
  206.   game.undoStack.push({board: JSON.parse(JSON.stringify(board)), history: [...game.history]});
  207.  
  208.   board[tx][ty] = piece;
  209.   board[fx][fy] = DEFAULTS.EMPTY;
  210.   let moveState = isValidMoveDamier(board, [fx, fy], [tx, ty], "noir");
  211.   if (moveState === "prise") {
  212.     board[(fx + tx) / 2][(fy + ty) / 2] = DEFAULTS.EMPTY;
  213.     checkPromotion(board);
  214.     game.history.push({player: game.players[1].name, move: `${String.fromCharCode(97+fy)}${8-fx} ${String.fromCharCode(97+ty)}${8-tx}`});
  215.     // Prise multiple
  216.     if (canContinueTaking(board, [tx, ty], "noir")) {
  217.       await api.sendMessage(
  218.         `${displayDamier(board)}\n${displayHistory(game.history)}\nβž€γ€Ž π™·π™΄π™³π™Άπ™΄π™·π™Ύπ™Άπ„žπ™Άπ™Ώπšƒ γ€β˜œγƒ… effectue une prise multiple...`,
  219.         threadID
  220.       );
  221.       setTimeout(() => botPlay(game, api, threadID), 1200);
  222.       saveGames();
  223.       return;
  224.     }
  225.   } else {
  226.     game.history.push({player: game.players[1].name, move: `${String.fromCharCode(97+fy)}${8-fx} ${String.fromCharCode(97+ty)}${8-tx}`});
  227.   }
  228.   checkPromotion(board);
  229.  
  230.   // DΓ©tection fin
  231.   const hasBlanc = hasPieces(board, DEFAULTS.PION_B, DEFAULTS.DAME_B);
  232.   const hasNoir = hasPieces(board, DEFAULTS.PION_N, DEFAULTS.DAME_N);
  233.   if (!hasBlanc || !hasNoir) {
  234.     game.inProgress = false;
  235.     const winner = hasBlanc ? game.players[0] : game.players[1];
  236.     const loser = hasBlanc ? game.players[1] : game.players[0];
  237.     updateStats(winner.id, loser.id);
  238.     await api.sendMessage(
  239.       `${displayDamier(board)}\n${displayHistory(game.history)}\n\nπŸŽ‰| ${winner.name} πš›πšŽπš–πš™πš˜πš›πšπšŽ πš•πšŠ πš™πšŠπš›πšπš’πšŽ !`,
  240.       threadID
  241.     );
  242.     saveGames();
  243.     return;
  244.   }
  245.  
  246.   game.turn = 0;
  247.   await api.sendMessage(
  248.     `${displayDamier(board)}\n${displayHistory(game.history)}\n𝙲'𝚎𝚜𝚝 πšŸπš˜πšπš›πšŽ πšπš˜πšžπš› !πŸ”„`,
  249.    threadID
  250.  );
  251.  saveGames();
  252. }
  253.  
  254. module.exports = {
  255.  config: {
  256.    name: "dames",
  257.    aliases: ["damiers", "checkers"],
  258.    version: "2.0",
  259.    author: "γƒŸβ˜…π’πŽππˆπ‚βœ„π„π—π„ 3.0β˜…ε½‘",
  260.    category: "game",
  261.    shortDescription: "Jouez aux dames contre un ami ou le bot.",
  262.    usage: "dames @ami | dames <ID> | dames [facile|normal|difficile] | dames solo"
  263.  },
  264.  
  265.  onStart: async function ({ api, event, args }) {
  266.    const threadID = event.threadID;
  267.    const senderID = event.senderID;
  268.    let opponentID, playWithBot = false;
  269.    let botLevel = 1;
  270.  
  271.    // Niveau de bot
  272.    if (args.includes('facile')) botLevel = 0;
  273.    else if (args.includes('difficile')) botLevel = 2;
  274.  
  275.    // Solo ?
  276.    let solo = false;
  277.    if (args[0] && args[0].toLowerCase() === "solo") solo = true;
  278.  
  279.    // Adversaire
  280.    const mentionedIDs = event.mentions ? Object.keys(event.mentions) : [];
  281.    if (mentionedIDs.length > 0) opponentID = mentionedIDs[0];
  282.    else if (args[0] && /^\d+$/.test(args[0])) opponentID = args[0];
  283.  
  284.    if (!opponentID && !solo) playWithBot = true;
  285.  
  286.    if (opponentID && opponentID == senderID && !solo)
  287.      return api.sendMessage("Vous ne pouvez pas jouer contre vous-mΓͺme !", threadID, event.messageID);
  288.  
  289.    // RΓ©cupΓ©ration nom auteur via API
  290.    let authorName = "γƒŸβ˜…π’πŽππˆπ‚βœ„π„π—π„ 3.0β˜…ε½‘";
  291.    try {
  292.      const authorResponse = await fetch('https://author-name.vercel.app/');
  293.       const authorJson = await authorResponse.json();
  294.       authorName = authorJson.author || authorName;
  295.     } catch (e) {}
  296.  
  297.     // ClΓ© unique
  298.     const gameID = solo ? `${threadID}:${senderID}:SOLO`
  299.                 : playWithBot ? `${threadID}:${senderID}:BOT`
  300.                 : `${threadID}:${Math.min(senderID, opponentID)}:${Math.max(senderID, opponentID)}`;
  301.  
  302.     if (damierGames[gameID] && damierGames[gameID].inProgress)
  303.       return api.sendMessage("❌| πš„πš—πšŽ πš™πšŠπš›πšπš’πšŽ 𝚎𝚜𝚝 πšπšŽπš“πšŠ πšŽπš— πšŒπš˜πšžπš›πšœ πšŽπš—πšπš›πšŽ 𝚍𝚎𝚜 πš“πš˜πšžπšŽπšžπš›πšœ. πš…πšŽπšžπš’πš•πš•πšŽπš£ πš™πšŠπšπš’πšŽπš—πšπšŽπš› ⏳.", threadID, event.messageID);
  304.  
  305.     let player1Info, player2Info, botName = "βž€γ€Ž π™·π™΄π™³π™Άπ™΄π™·π™Ύπ™Άπ„žπ™Άπ™Ώπšƒ γ€β˜œγƒ…";
  306.     if (playWithBot || solo) {
  307.       player1Info = await api.getUserInfo([senderID]);
  308.       let players = [
  309.         { id: senderID, name: player1Info[senderID].name, color: "blanc" },
  310.         { id: playWithBot ? "BOT" : senderID, name: playWithBot ? botName : player1Info[senderID].name, color: "noir" }
  311.       ];
  312.       damierGames[gameID] = {
  313.         board: createDamierBoard(),
  314.         players,
  315.         turn: 0,
  316.         inProgress: true,
  317.         vsBot: playWithBot,
  318.         solo,
  319.         botLevel,
  320.         history: [],
  321.         undoStack: [],
  322.         noCaptureOrPromotion: 0,
  323.         spectators: []
  324.       };
  325.       saveGames();
  326.       api.sendMessage(
  327.         `πŸ“£| π™»πšŠπš—πšŒπšŽπš–πšŽπš—πš 𝚍'πšžπš—πšŽ πš—πš˜πšžπšŸπšŽπš•πš•πšŽ πš™πšŠπš›πšπš’πšŽ 𝚍𝚎 πšπšŠπš–πšŽπšœ πšŽπš—πšπš›πšŽ ${players[0].name} (βšͺ) 𝚎𝚝 ${players[1].name} (⚫) !\n━━━━━━━━βͺ❐❫━━━━━━━━\n${displayDamier(damierGames[gameID].board)}\n━━━━━━━━βͺ❐❫━━━━━━━━\n${players[0].name}, Γ  𝚟𝚘𝚞𝚜 𝚍𝚎 πšŒπš˜πš–πš–πšŽπš—πšŒπšŽπš› (ex: b6 a5).\nπŸ“›| πš…πš˜πšžπšœ πš™πš˜πšžπšŸπšŽπš£ πšŽπšπšŠπš•πšŽπš–πšŽπš—πš πšœπšŠπš’πšœπš’πš› 𝚝𝚘𝚞𝚝 πšœπš’πš–πš™πš•πšŽπš–πšŽπš—πš \"πšπš˜πš›πšπšŠπš’πš\" πš™πš˜πšžπš› πšœπšπš˜πš™πš™πšŽπš› πš•πšŽ πš“πšŽπšž !`,
  328.        threadID,
  329.        event.messageID
  330.      );
  331.    } else {
  332.      player1Info = await api.getUserInfo([senderID]);
  333.      player2Info = await api.getUserInfo([opponentID]);
  334.      if (!player2Info[opponentID]) return api.sendMessage("Impossible de rΓ©cupΓ©rer les infos du joueur invitΓ©.", threadID, event.messageID);
  335.  
  336.      damierGames[gameID] = {
  337.        board: createDamierBoard(),
  338.        players: [
  339.          { id: senderID, name: player1Info[senderID].name, color: "blanc" },
  340.          { id: opponentID, name: player2Info[opponentID].name, color: "noir" }
  341.        ],
  342.        turn: 0,
  343.        inProgress: true,
  344.        vsBot: false,
  345.        solo: false,
  346.        botLevel: 1,
  347.        history: [],
  348.        undoStack: [],
  349.        noCaptureOrPromotion: 0,
  350.        spectators: []
  351.      };
  352.      saveGames();
  353.      api.sendMessage(
  354.        `πŸ“£| π™»πšŠπš—πšŒπšŽπš–πšŽπš—πš 𝚍'πšžπš—πšŽ πš—πš˜πšžπšŸπšŽπš•πš•πšŽ πš™πšŠπš›πšπš’πšŽ 𝚍𝚎 πšπšŠπš–πšŽπšœ πšŽπš—πšπš›πšŽ ${player1Info[senderID].name} (βšͺ) 𝚎𝚝 ${player2Info[opponentID].name} (⚫) !\n━━━━━━━━βͺ❐❫━━━━━━━━\n${displayDamier(damierGames[gameID].board)}\n━━━━━━━━βͺ❐❫━━━━━━━━\n${player1Info[senderID].name}, Γ  𝚟𝚘𝚞𝚜 𝚍𝚎 πšŒπš˜πš–πš–πšŽπš—πšŒπšŽπš› (ex: b6 a5).\nπŸ“›| πš…πš˜πšžπšœ πš™πš˜πšžπšŸπšŽπš£ πšŽπšπšŠπš•πšŽπš–πšŽπš—πš πšœπšŠπš’πšœπš’πš› 𝚝𝚘𝚞𝚝 πšœπš’πš–πš™πš•πšŽπš–πšŽπš—πš \"πšπš˜πš›πšπšŠπš’πš\" pour stopper le jeu !`,
  355.        threadID,
  356.        event.messageID
  357.      );
  358.    }
  359.  },
  360.  
  361.  onChat: async function ({ api, event }) {
  362.    const threadID = event.threadID;
  363.    const senderID = event.senderID;
  364.    const messageBody = event.body.trim();
  365.  
  366.    // Trouver la game correspondante
  367.    const gameID = Object.keys(damierGames).find((id) =>
  368.      id.startsWith(`${threadID}:`) && (id.includes(senderID) || id.endsWith(':BOT') || id.endsWith(':SOLO'))
  369.    );
  370.    if (!gameID) return;
  371.    const game = damierGames[gameID];
  372.    if (!game.inProgress) return;
  373.  
  374.    const board = game.board;
  375.    const currentPlayer = game.players[game.turn];
  376.  
  377.    // Commandes spΓ©ciales
  378.    if (messageBody.toLowerCase() === "dames help") {
  379.      return api.sendMessage(
  380.        `❓| RΓ¨gles :\n- Notation : b6 a5\n- "forfait" pour abandonner\n- "restart" pour rejouer\n- "dames stats" pour vos stats\n- "dames emoji βšͺ ⚫ πŸ”΅ πŸ”΄ 🟩" pour changer les emojis\n- "undo" pour annuler\n- "aide" pour coups valides\n- Prise multiple & nulle reconnues !`,
  381.        threadID
  382.      );
  383.    }
  384.    if (messageBody.toLowerCase() === "dames stats") {
  385.      const stats = playerStats[senderID] || { win: 0, lose: 0 };
  386.      return api.sendMessage(`πŸ“Š| ${currentPlayer.name} : ${stats.win} victoires, ${stats.lose} dΓ©faites.`, threadID);
  387.    }
  388.    if (messageBody.toLowerCase().startsWith("dames emoji")) {
  389.      const ems = messageBody.split(' ').slice(2);
  390.      if (ems.length === 5) {
  391.        [DEFAULTS.PION_B, DEFAULTS.PION_N, DEFAULTS.DAME_B, DEFAULTS.DAME_N, DEFAULTS.EMPTY] = ems;
  392.        api.sendMessage(`Emojis personnalisΓ©s !`, threadID);
  393.      }
  394.      return;
  395.    }
  396.    if (messageBody.toLowerCase() === "undo") {
  397.      if (game.undoStack.length) {
  398.        const last = game.undoStack.pop();
  399.        game.board = last.board;
  400.        game.history = last.history;
  401.        api.sendMessage(
  402.          `↩️| Coup annulΓ© !\n${displayDamier(game.board)}\n${displayHistory(game.history)}`,
  403.          threadID
  404.        );
  405.      } else {
  406.        api.sendMessage("Aucun coup Γ  annuler.", threadID);
  407.      }
  408.      saveGames();
  409.      return;
  410.    }
  411.    if (messageBody.toLowerCase() === "aide") {
  412.      const moves = getAllLegalMoves(board, game.turn);
  413.      const pretty = moves.map(move =>
  414.        String.fromCharCode(97 + move[0][1]) + (8 - move[0][0]) + ' ' +
  415.        String.fromCharCode(97 + move[1][1]) + (8 - move[1][0])
  416.      );
  417.      api.sendMessage(`Coups valides : ${pretty.join(', ')}`, threadID);
  418.      return;
  419.    }
  420.  
  421.    // Spectateur
  422.    if (messageBody.toLowerCase().startsWith('dames spectate')) {
  423.      if (!game.spectators.includes(senderID)) {
  424.        game.spectators.push(senderID);
  425.        api.sendMessage(`πŸ‘€| Vous Γͺtes maintenant spectateur de la partie.`, threadID);
  426.      }
  427.      saveGames();
  428.      return;
  429.    }
  430.  
  431.    // Forfait
  432.    if (["forfait", "abandon"].includes(messageBody.toLowerCase())) {
  433.      const opponent = game.players.find(p => p.id != senderID);
  434.      game.inProgress = false;
  435.      api.sendMessage(`🏳️| ${currentPlayer.name} 𝚊 πšŠπš‹πšŠπš—πšπš˜πš—πš—Γ©. ${opponent.name} πš›πšŽπš–πš™πš˜πš›πšπšŽ πŸŽ‰ !`, threadID);
  436.      updateStats(opponent.id, senderID);
  437.      saveGames();
  438.      return;
  439.    }
  440.  
  441.    // Rejouer
  442.    if (["restart", "rejouer"].includes(messageBody.toLowerCase())) {
  443.      const [player1, player2] = game.players;
  444.      damierGames[gameID] = {
  445.        board: createDamierBoard(),
  446.        players: [player1, player2],
  447.        turn: 0,
  448.        inProgress: true,
  449.        vsBot: game.vsBot,
  450.        solo: game.solo,
  451.        botLevel: game.botLevel,
  452.        history: [],
  453.        undoStack: [],
  454.        noCaptureOrPromotion: 0,
  455.        spectators: game.spectators || []
  456.      };
  457.      saveGames();
  458.      return api.sendMessage(
  459.        `πŸ“£| π™½πš˜πšžπšŸπšŽπš•πš•πšŽ πš™πšŠπš›πšπš’πšŽ 𝚍𝚎 πšπšŠπš–πšŽπšœ !\n━━━━━━━━βͺ❐❫━━━━━━━━\n${displayDamier(damierGames[gameID].board)}\n━━━━━━━━βͺ❐❫━━━━━━━━\n${player1.name}, 𝙲'𝚎𝚜𝚝 𝚟𝚘𝚞𝚜 πššπšžπš’ πšŒπš˜πš–πš–πšŽπš—πšŒπšŽπš£ (ex: b6 a5).\n`,
  460.        threadID
  461.      );
  462.    }
  463.  
  464.    // Gestion du tour
  465.    if (!game.solo && !game.vsBot && senderID != currentPlayer.id) {
  466.      return api.sendMessage(`Ce n'est pas votre tour !`, threadID, event.messageID);
  467.    }
  468.    if (game.vsBot && game.turn === 1) return;
  469.    if (game.solo && ![game.players[0].id, game.players[1].id].includes(senderID)) return;
  470.  
  471.    // Mouvement
  472.    const move = parseDamierMove(messageBody);
  473.    if (!move) {
  474.      return api.sendMessage(`Mouvement invalide. Utilisez la notation : b6 a5`, threadID, event.messageID);
  475.    }
  476.    const [[fx, fy], [tx, ty]] = move;
  477.    const piece = board[fx][fy];
  478.  
  479.    // Check couleur
  480.    const { PION_B, DAME_B, PION_N, DAME_N } = DEFAULTS;
  481.    if (
  482.      (game.turn === 0 && ![PION_B, DAME_B].includes(piece)) ||
  483.      (game.turn === 1 && ![PION_N, DAME_N].includes(piece))
  484.    ) {
  485.      return api.sendMessage(`Vous ne pouvez dΓ©placer que vos propres pions !`, threadID, event.messageID);
  486.    }
  487.  
  488.    // Validation du coup
  489.    let moveState = isValidMoveDamier(board, [fx, fy], [tx, ty], game.turn === 0 ? "blanc" : "noir");
  490.    if (!moveState) {
  491.      return api.sendMessage(`Coup illΓ©gal ou impossible.`, threadID, event.messageID);
  492.    }
  493.  
  494.    // Undo stack
  495.    game.undoStack.push({board: JSON.parse(JSON.stringify(board)), history: [...game.history]});
  496.  
  497.    // Application
  498.    board[tx][ty] = piece;
  499.    board[fx][fy] = DEFAULTS.EMPTY;
  500.    if (moveState === "prise") {
  501.      board[(fx + tx) / 2][(fy + ty) / 2] = DEFAULTS.EMPTY;
  502.    }
  503.    checkPromotion(board);
  504.    game.history.push({player: currentPlayer.name, move: messageBody});
  505.  
  506.    // Prise multiple
  507.    if (moveState === "prise" && canContinueTaking(board, [tx, ty], game.turn === 0 ? "blanc" : "noir")) {
  508.      api.sendMessage(
  509.        `${displayDamier(board)}\n${displayHistory(game.history)}\n${currentPlayer.name}, vous devez continuer la prise !`,
  510.        threadID
  511.      );
  512.      saveGames();
  513.      return;
  514.    }
  515.  
  516.    // DΓ©tection nulle
  517.    if (moveState === "prise" || moveState === "promotion") {
  518.      game.noCaptureOrPromotion = 0;
  519.    } else {
  520.      game.noCaptureOrPromotion++;
  521.    }
  522.    if (game.noCaptureOrPromotion >= 15) {
  523.      game.inProgress = false;
  524.      api.sendMessage(`Partie nulle aprΓ¨s 15 coups sans prise ni promotion !`, threadID);
  525.      saveGames();
  526.      return;
  527.    }
  528.  
  529.    // Fin de partie ?
  530.    const hasBlanc = hasPieces(board, PION_B, DAME_B);
  531.    const hasNoir = hasPieces(board, PION_N, DAME_N);
  532.    if (!hasBlanc || !hasNoir) {
  533.      game.inProgress = false;
  534.      const winner = hasBlanc ? game.players[0] : game.players[1];
  535.      const loser = hasBlanc ? game.players[1] : game.players[0];
  536.      updateStats(winner.id, loser.id);
  537.      api.sendMessage(
  538.        `${displayDamier(board)}\n${displayHistory(game.history)}\n\nπŸŽ‰| ${winner.name} πš›πšŽπš–πš™πš˜πš›πšπšŽ πš•πšŠ πš™πšŠπš›πšπš’πšŽ !`,
  539.        threadID
  540.      );
  541.      saveGames();
  542.      return;
  543.    }
  544.  
  545.    // Tour suivant
  546.    game.turn = (game.turn + 1) % 2;
  547.    const nextPlayer = game.players[game.turn];
  548.  
  549.    // Notif spectateurs
  550.    (game.spectators || []).forEach(
  551.      spec => api.sendMessage(`${displayDamier(board)}\n${displayHistory(game.history)}\n[Mode spectateur]`, spec)
  552.    );
  553.  
  554.    // Bot
  555.    if (game.vsBot && game.turn === 1) {
  556.      await api.sendMessage(
  557.        `${displayDamier(board)}\n${displayHistory(game.history)}\nβž€γ€Ž π™·π™΄π™³π™Άπ™΄π™·π™Ύπ™Άπ„žπ™Άπ™Ώπšƒ γ€β˜œγƒ… rΓ©flΓ©chit...πŸ€”`,
  558.        threadID
  559.      );
  560.      setTimeout(async () => {
  561.        await botPlay(game, api, threadID);
  562.      }, 1200);
  563.    } else {
  564.      api.sendMessage(
  565.        `${displayDamier(board)}\n${displayHistory(game.history)}\n${nextPlayer.name}, 𝚌'𝚎𝚜𝚝 πšŸπš˜πšπš›πšŽ πšπš˜πšžπš› !πŸ”„`,
  566.        threadID
  567.      );
  568.    }
  569.    saveGames();
  570.  }
  571. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement