Dice Lite

name

Dice Lite

icon

casino

description

Roll simple, basic, advanced formulas, or specialized dice directly within your notes.

instructions

- Run the Dice Lite:from App Options by / command.
- At first, it give you blank boxes to fill up. (Next time it remember your previous inputs).
- You can play around with the options listed to get an extensive range of a result.
Note: More options are on its way. Comment in the Installation page for any feedback or suggestion.
GitHub Link: https://github.com/krishnakanthb13/anp-21-dice-lite
YouTube: https://youtu.be/I-DrMKXhXUM

setting

Previous_Roll_Simple

setting

Previous_Roll

setting

Previous_Roll_Spc

setting

Dice_Usage_Stats


(() => {
// anp-21-dice-lite/lib/utils.js
function rollDice({
numDice = null,
faces = null,
min = null,
max = null,
keep = null,
drop = null,
explode = null,
sort = null,
unique = false
} = {}) {
const rollSingleDie = () => Math.floor(Math.random() * faces) + 1;
let rolls = Array.from({ length: numDice }, rollSingleDie);
if (min !== null) rolls = rolls.map((roll) => Math.max(roll, min));
if (max !== null) rolls = rolls.map((roll) => Math.min(roll, max));
if (explode) {
const { target, reroll } = explode;
const newRolls = [];
rolls.forEach((roll) => {
newRolls.push(roll);
let explodeCount = 0;
let currentRoll = roll;
while (currentRoll === target && explodeCount < 100) {
const extraRoll = rollSingleDie();
newRolls.push(extraRoll);
currentRoll = extraRoll;
explodeCount++;
if (!reroll) break;
}
});
rolls = newRolls;
}
if (unique) rolls = [...new Set(rolls)];
if (keep || drop) {
rolls.sort((a, b) => a - b);
if (keep) {
const { highest, count } = keep;
rolls = highest ? rolls.slice(-count) : rolls.slice(0, count);
}
if (drop) {
const { highest, count } = drop;
rolls = highest ? rolls.slice(0, rolls.length - count) : rolls.slice(count);
}
}
if (sort === "asc") rolls.sort((a, b) => a - b);
if (sort === "desc") rolls.sort((a, b) => b - a);
return {
rolls,
total: rolls.reduce((sum, roll) => sum + roll, 0)
};
}
 
// anp-21-dice-lite/lib/simple.js
async function simple(app) {
const existingSetting = await app.settings["Previous_Roll_Simple"];
let defaultDice = "1";
let defaultFaces = "6";
if (existingSetting) {
const parts = existingSetting.split(",");
if (parts.length === 2) {
defaultDice = parts[0];
defaultFaces = parts[1];
}
}
const result = await app.prompt("Simple Dice Roll", {
inputs: [
{ label: "Number of Dice", type: "string", value: defaultDice },
{ label: "Number of Faces", type: "string", value: defaultFaces }
]
});
if (!result) return "";
const [numDiceStr, facesStr] = result;
const numDice = parseInt(numDiceStr, 10);
const faces = parseInt(facesStr, 10);
if (isNaN(numDice) || isNaN(faces) || numDice < 1 || faces < 1) {
await app.alert("Number of dice and faces must be at least 1.");
return "";
}
await app.setSetting("Previous_Roll_Simple", `${numDice},${faces}`);
const rollResult = rollDice({ numDice, faces });
return `\u{1F3B2} **Simple Roll** (${numDice}d${faces}): [${rollResult.rolls.join(", ")}] **Total:** ${rollResult.total}`;
}
 
// anp-21-dice-lite/lib/basic.js
async function basic(app) {
const existingSetting = await app.settings["Previous_Roll"];
let result;
if (existingSetting) {
let parsed = (existingSetting || "").split(",").map((value) => value === "" || value === "null" ? null : value);
const [
numDicez,
facesz,
minz,
maxz,
keepHighestz,
keepCountz,
dropHighestz,
dropCountz,
explodez,
explodeTargetz,
sortOptionz,
uniquez
] = parsed.map((value, index) => {
const defaults = [1, 6, null, null, false, 0, false, 0, false, 0, 1, false];
if (value === void 0 || value === null) {
return defaults[index];
}
if ([0, 1, 2, 3, 5, 7, 9, 10].includes(index)) return Number(value) || defaults[index];
if ([4, 6, 8, 11].includes(index)) return String(value).toLowerCase() === "true";
return value;
});
result = await app.prompt("Configure Your Dice Roll (Recall settings)", {
inputs: [
{ label: "Number of Dice", type: "string", value: numDicez },
{ label: "Number of Faces", type: "string", value: facesz },
{ label: "Minimum Roll Limit", type: "string", value: minz },
{ label: "Maximum Roll Limit", type: "string", value: maxz },
{ label: "Keep Highest Rolls (Discard the rest)", type: "checkbox", value: keepHighestz },
{ label: "Count of Highest Rolls to Keep", type: "string", value: keepCountz },
{ label: "Drop Highest Rolls (Keep the rest)", type: "checkbox", value: dropHighestz },
{ label: "Count of Highest Rolls to Drop", type: "string", value: dropCountz },
{ label: "Exploding Dice (Roll again on max value)", type: "checkbox", value: explodez },
{ label: "Explode Target Value", type: "string", value: explodeTargetz },
{ label: "Sort Results", type: "select", options: [{ label: "None", value: 1 }, { label: "Ascending", value: 2 }, { label: "Descending", value: 3 }], value: sortOptionz || 1 },
{ label: "Unique Results Only (No duplicates)", type: "checkbox", value: uniquez }
]
});
} else {
result = await app.prompt("Configure Your Dice Roll", {
inputs: [
{ label: "Number of Dice", type: "string", value: "1" },
{ label: "Number of Faces", type: "string", value: "6" },
{ label: "Minimum Roll Limit", type: "string" },
{ label: "Maximum Roll Limit", type: "string" },
{ label: "Keep Highest Rolls (Discard the rest)", type: "checkbox", value: false },
{ label: "Count of Highest Rolls to Keep", type: "string", value: "0" },
{ label: "Drop Highest Rolls (Keep the rest)", type: "checkbox", value: false },
{ label: "Count of Highest Rolls to Drop", type: "string", value: "0" },
{ label: "Exploding Dice (Roll again on max value)", type: "checkbox", value: false },
{ label: "Explode Target Value", type: "string", value: "0" },
{ label: "Sort Results", type: "select", options: [{ label: "None", value: 1 }, { label: "Ascending", value: 2 }, { label: "Descending", value: 3 }], value: 1 },
{ label: "Unique Results Only (No duplicates)", type: "checkbox", value: false }
]
});
}
if (!result) return "";
const [
numDice,
faces,
min,
max,
keepHighest,
keepCount,
dropHighest,
dropCount,
explode,
explodeTarget,
sortOption,
unique
] = result;
const numDiceNum = Number(numDice);
const facesNum = Number(faces);
if (isNaN(numDiceNum) || isNaN(facesNum) || numDiceNum < 1 || facesNum < 1) {
await app.alert("Number of dice and faces must be at least 1");
return "";
}
await app.setSetting("Previous_Roll", result.join(","));
const sortMap = { 1: null, 2: "asc", 3: "desc" };
const diceResult = rollDice({
numDice: numDiceNum || 1,
faces: facesNum || 6,
min: min ? Number(min) : null,
max: max ? Number(max) : null,
keep: keepHighest ? { highest: true, count: Number(keepCount) || 1 } : null,
drop: dropHighest ? { highest: true, count: Number(dropCount) || 1 } : null,
explode: explode ? { target: Number(explodeTarget) || 6, reroll: true } : null,
sort: sortMap[sortOption],
unique: !!unique
});
const modifiers = [];
if (min) modifiers.push(`min limit: ${min}`);
if (max) modifiers.push(`max limit: ${max}`);
if (keepHighest) modifiers.push(`keep highest ${keepCount || 1}`);
if (dropHighest) modifiers.push(`drop highest ${dropCount || 1}`);
if (explode) modifiers.push(`explode on ${explodeTarget || 6}`);
if (unique) modifiers.push("unique");
if (sortOption == 2) modifiers.push("sorted asc");
if (sortOption == 3) modifiers.push("sorted desc");
const modifierStr = modifiers.length > 0 ? `, ${modifiers.join(", ")}` : "";
return `\u{1F3B2} **Basic Roll** (${numDice}d${faces}${modifierStr}): [${diceResult.rolls.join(", ")}] **Total:** ${diceResult.total}`;
}
 
// anp-21-dice-lite/lib/advanced.js
async function advanced(app) {
class DiceParser {
constructor() {
this.pos = 0;
this.input = "";
}
/**
* Rolls a single die with a given number of sides.
* @param {number} sides - Number of sides.
* @returns {number} - Rolled value.
*/
rollDie(sides) {
return Math.floor(Math.random() * sides) + 1;
}
/**
* Rolls multiple dice and sums their values.
* @param {number} count - Number of dice to roll.
* @param {number} sides - Number of sides on each die.
* @returns {number} - Sum of all rolls.
*/
rollDice(count, sides) {
let sum = 0;
for (let i = 0; i < count; i++) {
sum += this.rollDie(sides);
}
return sum;
}
/**
* Skips whitespace characters in the input formula.
*/
skipWhitespace() {
while (this.pos < this.input.length && /\s/.test(this.input[this.pos])) {
this.pos++;
}
}
/**
* Parses a plain number or a dice roll formula (e.g. 2d6).
* @returns {number} - The parsed and evaluated value.
*/
parseNumber() {
this.skipWhitespace();
if (/\d/.test(this.input[this.pos])) {
let start = this.pos;
while (this.pos < this.input.length && /\d/.test(this.input[this.pos])) {
this.pos++;
}
if (this.pos < this.input.length && this.input[this.pos] === "d") {
const count = parseInt(this.input.slice(start, this.pos), 10);
this.pos++;
start = this.pos;
while (this.pos < this.input.length && /\d/.test(this.input[this.pos])) {
this.pos++;
}
const sides = parseInt(this.input.slice(start, this.pos), 10);
return this.rollDice(count, sides);
} else {
return parseInt(this.input.slice(start, this.pos), 10);
}
}
throw new Error("Invalid number or dice expression");
}
/**
* Parses parenthesized sub-expressions.
* @returns {number} - The evaluated value.
*/
parseParentheses() {
this.skipWhitespace();
if (this.input[this.pos] === "(") {
this.pos++;
const result2 = this.parseExpression();
this.skipWhitespace();
if (this.input[this.pos] !== ")") {
throw new Error("Missing closing parenthesis");
}
this.pos++;
return result2;
}
return this.parseNumber();
}
/**
* Parses exponents (^).
* @returns {number} - The evaluated value.
*/
parseExponent() {
let left = this.parseParentheses();
this.skipWhitespace();
while (this.pos < this.input.length && this.input[this.pos] === "^") {
this.pos++;
const right = this.parseParentheses();
left = Math.pow(left, right);
this.skipWhitespace();
}
return left;
}
/**
* Parses multiplication (*) and division (/).
* @returns {number} - The evaluated value.
*/
parseMultiplyDivide() {
let left = this.parseExponent();
this.skipWhitespace();
while (this.pos < this.input.length && (this.input[this.pos] === "*" || this.input[this.pos] === "/")) {
const operator = this.input[this.pos];
this.pos++;
const right = this.parseExponent();
if (operator === "*") {
left *= right;
} else {
left /= right;
}
this.skipWhitespace();
}
return left;
}
/**
* Parses addition (+) and subtraction (-).
* @returns {number} - The evaluated value.
*/
parseExpression() {
let left = this.parseMultiplyDivide();
this.skipWhitespace();
while (this.pos < this.input.length && (this.input[this.pos] === "+" || this.input[this.pos] === "-")) {
const operator = this.input[this.pos];
this.pos++;
const right = this.parseMultiplyDivide();
if (operator === "+") {
left += right;
} else {
left -= right;
}
this.skipWhitespace();
}
return left;
}
/**
* Parses and evaluates a complete input formula.
* @param {string} input - The raw mathematical formula.
* @returns {number} - The final evaluated result.
*/
parse(input) {
this.input = input.replace(/\s+/g, "").toLowerCase();
this.pos = 0;
const result2 = this.parseExpression();
if (this.pos < this.input.length) {
throw new Error("Invalid expression");
}
return result2;
}
}
function evaluateDiceExpression(expression) {
const parser = new DiceParser();
try {
return parser.parse(expression);
} catch (error) {
return `Error: ${error.message}`;
}
}
const examplez = `1d2,
3d4 + 3,
1d12 + 1d10 + 5,
3d4+3d4-(3d4 * 1d4) - 2^1d7`;
const result = await app.prompt("Evaluate Custom Dice Formulas", {
inputs: [
{ label: "Single Roll Formula (e.g., 2d6 + 5)", type: "string", value: `1d2` },
{ label: "Batch Roll Formulas (One per line or comma-separated)", type: "text", value: `${examplez}` }
]
});
if (!result) return "";
const [singleDice, multipleDice] = result;
let outputParts = [];
if (singleDice) {
outputParts.push(`**Formula:** \`${singleDice}\` = **${evaluateDiceExpression(singleDice)}**`);
}
if (multipleDice) {
const multipleDicez = multipleDice.split(/[\n,]/).map((dice) => dice.trim()).filter((dice) => dice !== "");
const batchResults = multipleDicez.map((dice) => `\`${dice}\` = **${evaluateDiceExpression(dice)}**`);
outputParts.push(`**Batch:** [${batchResults.join(", ")}]`);
}
return `\u{1F3B2} **Advanced Roll** | ` + outputParts.join(" | ");
}
 
// anp-21-dice-lite/lib/specialized.js
async function specialized(app) {
const existingSetting = await app.settings["Previous_Roll_Spc"];
let numDicez = "5";
let specializedDicez = "poker";
let pokerVariz = "standard";
let addProbz = false;
if (existingSetting) {
const parts = (existingSetting || "").split(",");
if (parts.length === 4) {
numDicez = parts[0];
specializedDicez = parts[1];
pokerVariz = parts[2];
addProbz = parts[3].toLowerCase() === "true";
}
}
const result = await app.prompt("Configure Specialized Dice Roll", {
inputs: [
{ label: "Number of Dice", type: "string", value: numDicez },
{ label: "Specialized Dice Type", type: "select", options: [{ label: "Sicherman Dice", value: "sicherman" }, { label: "Intransitive Dice", value: "intransitive" }, { label: "Poker Dice", value: "poker" }], value: specializedDicez },
{ label: "Poker Variation (If Poker selected)", type: "select", options: [{ label: "Standard", value: "standard" }, { label: "Numeric", value: "numeric" }, { label: "Crown", value: "crown" }], value: pokerVariz },
{ label: "Calculate & Show Probabilities", type: "checkbox", value: addProbz }
]
});
if (!result) return "";
const [
numDice,
specializedDice,
pokerVari,
addProb
] = result;
await app.setSetting("Previous_Roll_Spc", `${numDice},${specializedDice},${pokerVari},${addProb}`);
const DICE_VARIATIONS = {
sicherman: {
die1: [1, 3, 4, 5, 6, 8],
die2: [1, 2, 2, 3, 3, 4]
},
intransitive: {
dieA: [2, 2, 4, 4, 9, 9],
dieB: [1, 1, 6, 6, 8, 8],
dieC: [3, 3, 5, 5, 7, 7]
},
poker: {
standard: ["A", "K", "Q", "J", "10", "9"],
numeric: [1, 2, 3, 4, 5, 6],
crown: ["Crown", "Queen", "Jack", "Ten", "Nine", "Eight"]
}
};
class DiceSimulator {
constructor() {
this.results = [];
this.diceConfig = DICE_VARIATIONS;
}
/**
* Rolls a single die from a list of faces.
* @param {Array<number|string>} faces - Available face values on the die.
* @returns {number|string} - The rolled face value.
*/
rollDie(faces) {
return faces[Math.floor(Math.random() * faces.length)];
}
/**
* Calculates probability distribution for Sicherman dice sum outcomes.
* @returns {Array<{sum: number, probability: string}>} - Sorted sum probabilities.
*/
calculateSichermanProbabilities() {
const probabilities = /* @__PURE__ */ new Map();
const die1 = this.diceConfig.sicherman.die1;
const die2 = this.diceConfig.sicherman.die2;
for (let v1 of die1) {
for (let v2 of die2) {
const sum = v1 + v2;
probabilities.set(sum, (probabilities.get(sum) || 0) + 1);
}
}
const totalOutcomes = die1.length * die2.length;
return Array.from(probabilities.entries()).map(([sum, count]) => ({
sum,
probability: (count / totalOutcomes * 100).toFixed(2) + "%"
})).sort((a, b) => a.sum - b.sum);
}
/**
* Calculates win probabilities matchups between intransitive dice.
* @returns {Object} - Win percentage mappings.
*/
calculateIntransitiveProbabilities() {
const dieA = this.diceConfig.intransitive.dieA;
const dieB = this.diceConfig.intransitive.dieB;
const dieC = this.diceConfig.intransitive.dieC;
const calculateWinProbability = (die1, die2) => {
let wins = 0;
let total = 0;
for (let v1 of die1) {
for (let v2 of die2) {
if (v1 > v2) wins++;
total++;
}
}
return (wins / total * 100).toFixed(2) + "%";
};
return {
"A vs B": calculateWinProbability(dieA, dieB),
"B vs C": calculateWinProbability(dieB, dieC),
"C vs A": calculateWinProbability(dieC, dieA)
};
}
/**
* Classifies a 5-card poker hand.
* @param {Array<string|number>} hand - Drawn cards.
* @returns {string} - Classification of the poker hand (e.g. Full house).
*/
analyzePokerHand(hand) {
const valueMap = { "A": 14, "K": 13, "Q": 12, "J": 11 };
const numericHand = hand.map(
(card) => valueMap[card] || parseInt(card, 10)
).sort((a, b) => b - a);
const frequencies = /* @__PURE__ */ new Map();
numericHand.forEach(
(value) => frequencies.set(value, (frequencies.get(value) || 0) + 1)
);
const counts = Array.from(frequencies.values()).sort((a, b) => b - a);
if (counts[0] === 5) return "Five of a kind";
if (counts[0] === 4) return "Four of a kind";
if (counts[0] === 3 && counts[1] === 2) return "Full house";
if (counts[0] === 3) return "Three of a kind";
if (counts[0] === 2 && counts[1] === 2) return "Two pair";
if (counts[0] === 2) return "One pair";
let isStrait = true;
for (let i = 1; i < numericHand.length; i++) {
if (numericHand[i] !== numericHand[i - 1] - 1) {
isStrait = false;
break;
}
}
if (isStrait) return "Straight";
return "High card";
}
/**
* Simulates Sicherman dice rolls.
* @param {number} rolls - Number of simulations.
* @returns {Object} - Formatted roll text and probabilities.
*/
simulateSicherman(rolls = 1) {
this.results = [];
const probabilities = this.calculateSichermanProbabilities();
for (let i = 0; i < rolls; i++) {
const die1 = this.rollDie(this.diceConfig.sicherman.die1);
const die2 = this.rollDie(this.diceConfig.sicherman.die2);
this.results.push({ die1, die2, sum: die1 + die2 });
}
return {
rolls: this.results.map((r, idx) => `[Roll ${idx + 1}: Die 1 = ${r.die1}, Die 2 = ${r.die2}, Sum = ${r.sum}]`).join(", "),
probabilities
};
}
/**
* Simulates Intransitive dice rolls.
* @param {number} rolls - Number of simulations.
* @returns {Object} - Formatted roll text and probabilities.
*/
simulateIntransitive(rolls = 1) {
this.results = [];
const probabilities = this.calculateIntransitiveProbabilities();
for (let i = 0; i < rolls; i++) {
const dieA = this.rollDie(this.diceConfig.intransitive.dieA);
const dieB = this.rollDie(this.diceConfig.intransitive.dieB);
const dieC = this.rollDie(this.diceConfig.intransitive.dieC);
this.results.push({ dieA, dieB, dieC });
}
return {
rolls: this.results.map((r, idx) => `[Roll ${idx + 1}: Die A = ${r.dieA}, Die B = ${r.dieB}, Die C = ${r.dieC}]`).join(", "),
probabilities
};
}
/**
* Simulates a Poker hand roll.
* @param {number} rolls - Number of cards/dice (usually 5).
* @param {string} diceVariation - Poker variation (standard, numeric, crown).
* @returns {Object} - Drawn hand, classification, and statistical probabilities.
*/
simulatePoker(rolls = 5, diceVariation = "standard") {
this.results = [];
for (let i = 0; i < rolls; i++) {
this.results.push(this.rollDie(this.diceConfig.poker[diceVariation]));
}
const hand = this.results;
const handType = this.analyzePokerHand(hand);
return {
hand: hand.join(" "),
analysis: handType,
probabilities: {
"Five of a kind": "0.08%",
"Four of a kind": "1.93%",
"Full house": "3.86%",
"Three of a kind": "15.43%",
"Two pair": "23.15%",
"One pair": "46.30%",
"Straight": "1.54%",
"High card": "7.71%"
}
};
}
}
const simulator = new DiceSimulator();
let output = "";
const diceCount = parseInt(numDice, 10) || 5;
if (specializedDice === "sicherman") {
const res = simulator.simulateSicherman(diceCount);
output = `\u{1F3B2} **Specialized Sicherman Roll** (${diceCount} rolls):
**Rolls:** ${res.rolls}`;
if (addProb) {
const probStr = res.probabilities.map((p) => `Sum ${p.sum}: ${p.probability}`).join(", ");
output += `
**Probabilities:** [${probStr}]`;
}
} else if (specializedDice === "intransitive") {
const res = simulator.simulateIntransitive(diceCount);
output = `\u{1F3B2} **Specialized Intransitive Roll** (${diceCount} rolls):
**Rolls:** ${res.rolls}`;
if (addProb) {
output += `
**Win Matchups:** [A vs B: ${res.probabilities["A vs B"]}, B vs C: ${res.probabilities["B vs C"]}, C vs A: ${res.probabilities["C vs A"]}]`;
}
} else if (specializedDice === "poker") {
const res = simulator.simulatePoker(diceCount, pokerVari);
output = `\u{1F3B2} **Specialized Poker Roll** (Variation: ${pokerVari}):
**Hand:** [${res.hand}]
**Analysis:** ${res.analysis}`;
if (addProb) {
output += `
**Hand Chance:** ${res.probabilities[res.analysis] || "N/A"}`;
}
}
return output;
}
 
// anp-21-dice-lite/dice-lite.js
function wrapFeature(featureName, moduleFunc) {
return async function(app, ...args) {
try {
const statsStr = await app.settings["Dice_Usage_Stats"];
let stats = {};
try {
stats = statsStr ? JSON.parse(statsStr) : {};
} catch (e) {
console.warn("Could not parse Dice_Usage_Stats setting:", e);
}
stats[featureName] = (stats[featureName] || 0) + 1;
await app.setSetting("Dice_Usage_Stats", JSON.stringify(stats));
const result = await moduleFunc(app, ...args);
if (result && app.context && typeof app.context.replaceSelection === "function") {
try {
const success = await app.context.replaceSelection(result);
if (success) {
return null;
}
} catch (e) {
console.warn("replaceSelection failed, falling back to direct string return:", e);
}
}
return result;
} catch (error) {
console.error(`Plugin Error in [${featureName}]:`, error);
await app.alert(`An error occurred in ${featureName}:
${error.message}`);
return "";
}
};
}
var dice_lite_default = {
insertText: {
"Simple Roll": wrapFeature("Simple Roll", simple),
"Basic Roll": wrapFeature("Basic Roll", basic),
"Advanced Roll": wrapFeature("Advanced Roll", advanced),
"Specialized Roll": wrapFeature("Specialized Roll", specialized)
}
};
var dice_lite_default2 = dice_lite_default;
 
 
return dice_lite_default2;
})()