Search code examples
javascriptdiscordbotsdice

Dice roll. DND, add numbers from an array together


So i created a basic dice rolling dicord bot for Dungeons & Dragons.

the code i have so far works to roll any type of dice, (ex. "roll xdy" "roll 1d20", "roll 100d100")

when someone sends a message that matches, it will output the resulting dice rolls.

my issue is that i would like to add these numbers together and show the resulting total aswell but im unsure how to get there.

// Run dotenv
require('dotenv').config();

const { any } = require('async');
const Discord = require('discord.js');
const client = new Discord.Client({ intents: ["GUILDS", "GUILD_MESSAGES"] });


client.on('messageCreate', msg => {
        z = msg.content;
        matches = z.match(/\d+/g);
        x = matches[0];
        y = matches[1];

    if (msg.content === 'ping') {
        msg.reply('pong');
    }
    if (msg.content == 'roll ' + x + 'd' + y) {
        
        function rollDie(sides) {
            if (!sides) sides = 6;
            return 1 + Math.floor(Math.random() * sides);
        }

        function rollDice(number, sides) {
            var total = [];
            var number = x;
            var sides = y;
            while (number-- > 0) total.push(rollDie(sides));
            return total;
        }
        msg.reply("result: " + rollDice());
        console.log(rollDice())
    }
});

client.login(process.env.DISCORD_TOKEN);

Solution

  • Seemed like you were declaring variables without using let or var (z, matches, x, and y). No reason to use var anymore. You had parameters for the rollDice function but then were just pulling from the variables you created and not using the parameters, so I modified that. I used the reduce method to sum the array. I changed some variable names to be more descriptive (such as z to msgContent) and used them in more available places.

    In your rollDie function you give a default die side number of 6, but because of the if statement wrapping it, the only way the function will be called is if a side number is specifically chosen. So I modified this so that someone can type "Roll 3" if they just want to roll 3 6-sided dice. When reporting the dice roll I used the join method so they would display in a comma and space separated list instead of as an array.


    I have modified this solution after seeing your edits. msgContent is now created at the top with a new regular expression I made that is robust enough to get rid of the toLowerCase and trim method input scrubbing as well as the other string checks previously necessary in the code. The msg will pass the regular expression test method if msg is either 'roll #' or 'roll #d#' (where '#' is any numbers besides 0 of any digit length). The regular expression will automatically ignore character case and any whitespace on the ends of the string. I converted the rollDie function into a more succinct arrow function and put it inside the rollDice function scope because that is the only place it needs to be called. You don't need to write if (!sides) sides = 6; because you can just use the expression (sides || 6) because sides is only used once and if is falsy that expression will just evaluate as 6. I also stopped declaring diceResults as a blank array, as it can be defined later when the output of rollDice() is saved to it.

    require('dotenv').config();
    const { any } = require("async");
    const Discord = require("discord.js");
    const client = new Discord.Client({ intents: ["GUILDS", "GUILD_MESSAGES"] });
    
    client.on("messageCreate", (msg) => {
      const msgContent = msg.content,
            msgRegEx = /\s*roll\s[1-9]\d*(d[1-9]\d*)?\s*/i;
    
      if (msgRegEx.test(msgContent)) {
        let matches = msgContent.match(/\d+/g),
            numDice = matches[0],
            numSides = matches[1],
            diceResults;
    
        function rollDice(number, sides) {
          const rollDie = sides => Math.floor(Math.random() * (sides || 6)) + 1;
    
          let diceArray = [];
    
          while (number-- > 0) diceArray.push(rollDie(sides));
    
          return diceArray;
        }
    
        function calcDiceTotal(diceArray) {
          return diceArray.reduce(
            (previousValue, currentValue) => previousValue + currentValue,
            0
          );
        }
    
        diceResults = rollDice(numDice, numSides);
    
        msg.reply(
          "ROLLING... " + diceResults.join(", ") +
          " || TOTAL: " + calcDiceTotal(diceResults)
        );
      }
    });
    
    client.login(process.env.DISCORD_TOKEN);
    

    Output should look like this: "ROLLING... 3, 1, 6, 3, 5 || TOTAL: 18"