// code from goatstore // api: https://store.agi.bd module.exports = { config: { name: "connect", aliases: ["game", "c4"], version: "2.2", author: "MR_FARHAN", countDown: 30, role: 0, category: "š—™š—Øš—” & š—šš—”š— š—˜", shortDescription: { en: "šŸŸ”šŸ”“ 4-in-a-Row with PvE/PvP modes" }, longDescription: { en: "Classic connection game with visual board and smart AI" }, guide: { en: "PvE: connect4 [bet]\nPvP: connect4 [bet] @player" } }, onStart: async function ({ api, event, args, usersData, message }) { const minBet = 100; const betAmount = parseInt(args[0]); const mentioned = Object.keys(event.mentions); // Validate input if (!betAmount || isNaN(betAmount)) { return message.reply(`šŸŒ€ š—œš—»š˜ƒš—®š—¹š—¶š—± š—•š—²š˜\n━━━━━━━━━━━━\nāŒ Please specify bet amount\nšŸ’ø Minimum: ${minBet} coins\n\nšŸ”¹ Usage: connect4 [bet] @player`); } if (betAmount < minBet) { return message.reply(`āš ļø š— š—¶š—»š—¶š—ŗš˜‚š—ŗ š—•š—²š˜\n━━━━━━━━━━━━\nšŸ’° You need to bet at least ${minBet} coins!`); } const player1 = event.senderID; let gameType, player2; if (mentioned.length === 0) { // PvE Mode gameType = "pve"; player2 = "bot"; } else if (mentioned.length === 1) { // PvP Mode gameType = "pvp"; player2 = mentioned[0]; if (player1 === player2) { return message.reply("āŒ š—œš—»š˜ƒš—®š—¹š—¶š—± š—¢š—½š—½š—¼š—»š—²š—»š˜\n━━━━━━━━━━━━\nYou can't play against yourself!"); } } else { return message.reply("āš ļø š—œš—»š˜ƒš—®š—¹š—¶š—± š—œš—»š—½š˜‚š˜\n━━━━━━━━━━━━\nšŸ”¹ PvE: connect4 [bet]\nšŸ”¹ PvP: connect4 [bet] @player"); } // Check balances const [player1Data, player2Data] = await Promise.all([ usersData.get(player1), gameType === "pvp" ? usersData.get(player2) : Promise.resolve({ money: Infinity }) ]); if (player1Data.money < betAmount) { return message.reply(`šŸ’ø š—œš—»š˜€š˜‚š—³š—³š—¶š—°š—¶š—²š—»š˜ š—™š˜‚š—»š—±š˜€\n━━━━━━━━━━━━\nāŒ You only have ${player1Data.money} coins\nšŸ’° Needed: ${betAmount} coins`); } if (gameType === "pvp" && player2Data.money < betAmount) { return message.reply(`šŸ’ø š—¢š—½š—½š—¼š—»š—²š—»š˜'š˜€ š—™š˜‚š—»š—±š˜€\n━━━━━━━━━━━━\nāŒ Opponent needs ${betAmount} coins to play`); } // Deduct coins await usersData.set(player1, { money: player1Data.money - betAmount }); if (gameType === "pvp") { await usersData.set(player2, { money: player2Data.money - betAmount }); } // Initialize game const board = Array(6).fill().map(() => Array(6).fill(0)); // 6x6 grid const gameState = { players: [player1, player2], currentPlayer: 0, board, betAmount, gameType, messageID: null }; const displayText = gameType === "pve" ? `šŸ¤– š—£š—¹š—®š˜†š—²š—æ š˜ƒš˜€ š—•š—¼š˜\nšŸ’° Bet: ${betAmount} coins` : `šŸ‘„ š—£š—¹š—®š˜†š—²š—æ š˜ƒš˜€ š—£š—¹š—®š˜†š—²š—æ\nšŸ’° Pot: ${betAmount * 2} coins`; const msg = await message.reply( `šŸŽ® š—–š—¢š—”š—”š—˜š—–š—§ šŸ° šŸŽ®\n━━━━━━━━━━━━\n${displayText}\n\n${this.getBoardDisplay(board)}\n\n` + `šŸ”¹ Current Turn: ${await this.getPlayerName(api, player1)}\n` + "šŸ’¬ Reply with column (1-6) to play!" ); gameState.messageID = msg.messageID; global.connect4Games = global.connect4Games || {}; global.connect4Games[msg.messageID] = gameState; }, onChat: async function ({ api, event, message, usersData }) { if (!global.connect4Games) return; const gameEntry = Object.entries(global.connect4Games).find(([_, game]) => game.players[game.currentPlayer] === event.senderID && /^[1-6]$/.test(event.body) ); if (!gameEntry) return; const [messageID, game] = gameEntry; const column = parseInt(event.body) - 1; // Convert to 0-5 index // Human player move const row = this.makeMove(game.board, column, game.currentPlayer + 1); if (row === -1) { return message.reply("āš ļø š—œš—»š˜ƒš—®š—¹š—¶š—± š— š—¼š˜ƒš—²\n━━━━━━━━━━━━\nāŒ Column is full!\nšŸ”¹ Choose another (1-6)"); } // Check for win if (this.checkWin(game.board, row, column)) { const winner = game.players[game.currentPlayer]; const winnings = game.betAmount * (game.gameType === "pvp" ? 2 : 1.5); await usersData.set(winner, { money: (await usersData.get(winner)).money + winnings }); const resultText = winner === "bot" ? "šŸ¤– š—•š—¼š˜ š—Ŗš—¶š—»š˜€!\n━━━━━━━━━━━━\nāŒ Better luck next time!" : `šŸŽ‰ š—©š—¶š—°š˜š—¼š—æš˜†!\n━━━━━━━━━━━━\nšŸ’° ${await this.getPlayerName(api, winner)} wins ${winnings} coins!`; message.reply( `šŸŽÆ š—šš—®š—ŗš—² š—¢š˜ƒš—²š—æ šŸŽÆ\n━━━━━━━━━━━━\n${resultText}\n\n${this.getBoardDisplay(game.board)}` ); delete global.connect4Games[messageID]; return; } // Check for draw if (this.isBoardFull(game.board)) { const refund = game.betAmount; await usersData.set(game.players[0], { money: (await usersData.get(game.players[0])).money + refund }); if (game.gameType === "pvp") { await usersData.set(game.players[1], { money: (await usersData.get(game.players[1])).money + refund }); } message.reply( "šŸ¤ š——š—æš—®š˜„!\n━━━━━━━━━━━━\nšŸ’° Both players get their coins back\n\n" + this.getBoardDisplay(game.board) ); delete global.connect4Games[messageID]; return; } // Switch turns game.currentPlayer = 1 - game.currentPlayer; // Bot move in PvE if (game.gameType === "pve" && game.currentPlayer === 1) { const botColumn = this.getBotMove(game.board); const botRow = this.makeMove(game.board, botColumn, 2); if (this.checkWin(game.board, botRow, botColumn)) { message.reply( `šŸŽÆ š—šš—®š—ŗš—² š—¢š˜ƒš—²š—æ šŸŽÆ\n━━━━━━━━━━━━\nšŸ¤– š—•š—¼š˜ š—Ŗš—¶š—»š˜€!\n\n${this.getBoardDisplay(game.board)}` ); delete global.connect4Games[messageID]; return; } game.currentPlayer = 0; // Switch back to player } // Update game board await message.reply( `šŸŽ® š—–š—¢š—”š—”š—˜š—–š—§ šŸ° šŸŽ®\n━━━━━━━━━━━━\n` + `${game.gameType === "pve" ? "šŸ¤– PvE" : "šŸ‘„ PvP"} | šŸ’° Pot: ${game.betAmount * 2} coins\n\n` + `${this.getBoardDisplay(game.board)}\n\n` + `šŸ”¹ Current Turn: ${await this.getPlayerName(api, game.players[game.currentPlayer])}\n` + "šŸ’¬ Reply with column (1-6)" ); api.unsendMessage(messageID); }, // Helper Methods makeMove: function(board, col, player) { if (col < 0 || col > 5 || board[0][col] !== 0) return -1; for (let row = 5; row >= 0; row--) { if (board[row][col] === 0) { board[row][col] = player; return row; } } return -1; }, getBotMove: function(board) { // Try to win for (let col = 0; col < 6; col++) { const testBoard = JSON.parse(JSON.stringify(board)); const row = this.makeMove(testBoard, col, 2); if (row !== -1 && this.checkWin(testBoard, row, col)) { return col; } } // Block player for (let col = 0; col < 6; col++) { const testBoard = JSON.parse(JSON.stringify(board)); const row = this.makeMove(testBoard, col, 1); if (row !== -1 && this.checkWin(testBoard, row, col)) { return col; } } // Center preference if (board[5][3] === 0) return 3; // Random valid move const validColumns = []; for (let col = 0; col < 6; col++) { if (board[0][col] === 0) validColumns.push(col); } return validColumns[Math.floor(Math.random() * validColumns.length)]; }, checkWin: function(board, row, col) { const player = board[row][col]; const directions = [ [0, 1], [1, 0], [1, 1], [1, -1] ]; return directions.some(([dx, dy]) => { let count = 1; // Check in positive direction for (let i = 1; i < 4; i++) { const r = row + i * dx; const c = col + i * dy; if (r < 0 || r >= 6 || c < 0 || c >= 6 || board[r][c] !== player) break; count++; } // Check in negative direction for (let i = 1; i < 4; i++) { const r = row - i * dx; const c = col - i * dy; if (r < 0 || r >= 6 || c < 0 || c >= 6 || board[r][c] !== player) break; count++; } return count >= 4; }); }, isBoardFull: function(board) { return board[0].every(cell => cell !== 0); }, getBoardDisplay: function(board) { const symbols = ['⬜', 'šŸ”“', '🟔']; // Empty, Player1, Player2/Bot let display = '1ļøāƒ£ 2ļøāƒ£ 3ļøāƒ£ 4ļøāƒ£ 5ļøāƒ£ 6ļøāƒ£\n'; // Column indicators for (const row of board) { display += row.map(cell => symbols[cell]).join('') + '\n'; } return display; }, getPlayerName: async function(api, userID) { try { if (userID === "bot") return "šŸ¤– Bot"; const userInfo = await api.getUserInfo(userID); return userInfo[userID].name || `Player ${userID}`; } catch { return `Player ${userID}`; } } };