From 8e84be1656b836d4fc93b12d325556c9076317d4 Mon Sep 17 00:00:00 2001 From: "Ean Milligan (Bastion)" Date: Mon, 4 Jul 2022 20:37:38 -0400 Subject: [PATCH] Started work on OVA dice, adjusted parser to fall back to the roller --- src/solver/parser.ts | 10 +++--- src/solver/roller.ts | 73 +++++++++++++++++++++++++------------------- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/src/solver/parser.ts b/src/solver/parser.ts index 6043072..54f1abd 100644 --- a/src/solver/parser.ts +++ b/src/solver/parser.ts @@ -82,11 +82,6 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll } else if (mathConf[i] == parseFloat(mathConf[i].toString())) { // If its a number, parse the number out mathConf[i] = parseFloat(mathConf[i].toString()); - } else if (/([0123456789])/g.test(mathConf[i].toString())) { - // If there is a number somewhere in mathconf[i] but there are also other characters preventing it from parsing correctly as a number, it should be a dice roll, parse it as such (if it for some reason is not a dice roll, formatRoll/roll will handle it) - const formattedRoll = formatRoll(mathConf[i].toString(), modifiers.maxRoll, modifiers.nominalRoll); - mathConf[i] = formattedRoll.solvedStep; - tempCountDetails.push(formattedRoll.countDetails); } else if (mathConf[i].toString().toLowerCase() === 'e') { // If the operand is the constant e, create a SolvedStep for it mathConf[i] = { @@ -132,6 +127,11 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll containsCrit: false, containsFail: false, }]); + } else { + // If nothing else has handled it by now, try it as a roll + const formattedRoll = formatRoll(mathConf[i].toString(), modifiers.maxRoll, modifiers.nominalRoll); + mathConf[i] = formattedRoll.solvedStep; + tempCountDetails.push(formattedRoll.countDetails); } if (mathConf[i - 1] === '-' && (!mathConf[i - 2] || mathConf[i - 2] === '(')) { diff --git a/src/solver/roller.ts b/src/solver/roller.ts index c6a7730..373133b 100644 --- a/src/solver/roller.ts +++ b/src/solver/roller.ts @@ -72,23 +72,8 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Fill out the die count, first item will either be an int or empty string, short circuit execution will take care of replacing the empty string with a 1 const rawDC = dpts.shift() || '1'; const tempDC = rawDC.replace(/\D/g, ''); - rollConf.dieCount = parseInt(tempDC); - - // Finds the end of the die size/beginnning of the additional options - let afterDieIdx = dpts[0].search(/\D/); - if (afterDieIdx === -1) { - afterDieIdx = dpts[0].length; - } - // Rejoin all remaining parts let remains = dpts.join('d'); - // Get the die size out of the remains and into the rollConf - rollConf.dieSize = parseInt(remains.slice(0, afterDieIdx)); - remains = remains.slice(afterDieIdx); - - if (!rollConf.dieCount || !rollConf.dieSize) { - throw new Error('YouNeedAD'); - } // Manual Parsing for custom roll types let manualParse = false; @@ -109,10 +94,36 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea loggingEnabled && log(LT.LOG, `handling cwod ${rollStr} | Parsing difficulty ${i}`); rollConf.critScore.range.push(i); } + } else if (rawDC.endsWith('ova')) { + // OVA dice parsing + rollType = 'ova'; + manualParse = true; + + // Get CWOD parts, setting count and getting difficulty + const ovaParts = rollStr.split('ovad'); + rollConf.dieCount = parseInt(ovaParts[0] || '1'); + rollConf.dieSize = parseInt(ovaParts[1] || '6'); + } else { + // roll20 dice setup + rollConf.dieCount = parseInt(tempDC); + + // Finds the end of the die size/beginnning of the additional options + let afterDieIdx = dpts[0].search(/\D/); + if (afterDieIdx === -1) { + afterDieIdx = dpts[0].length; + } + + // Get the die size out of the remains and into the rollConf + rollConf.dieSize = parseInt(remains.slice(0, afterDieIdx)); + remains = remains.slice(afterDieIdx); } - loggingEnabled && log(LT.LOG, `Handling roll20 ${rollStr} | Parsed Die Count: ${rollConf.dieCount}`); - loggingEnabled && log(LT.LOG, `Handling roll20 ${rollStr} | Parsed Die Size: ${rollConf.dieSize}`); + if (!rollConf.dieCount || !rollConf.dieSize) { + throw new Error('YouNeedAD'); + } + + loggingEnabled && log(LT.LOG, `Handling ${rollType} ${rollStr} | Parsed Die Count: ${rollConf.dieCount}`); + loggingEnabled && log(LT.LOG, `Handling ${rollType} ${rollStr} | Parsed Die Size: ${rollConf.dieSize}`); // Finish parsing the roll if (!manualParse && remains.length > 0) { @@ -123,7 +134,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Loop until all remaining args are parsed while (remains.length > 0) { - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Parsing remains ${remains}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Parsing remains ${remains}`); // Find the next number in the remains to be able to cut out the rule name let afterSepIdx = remains.search(/\d/); if (afterSepIdx < 0) { @@ -181,7 +192,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Configure reroll for all numbers greater than or equal to tNum (this could happen multiple times, but why) rollConf.reroll.on = true; for (let i = tNum; i <= rollConf.dieSize; i++) { - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Parsing r> ${i}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Parsing r> ${i}`); rollConf.reroll.nums.push(i); } break; @@ -192,7 +203,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Configure reroll for all numbers less than or equal to tNum (this could happen multiple times, but why) rollConf.reroll.on = true; for (let i = 1; i <= tNum; i++) { - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Parsing r< ${i}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Parsing r< ${i}`); rollConf.reroll.nums.push(i); } break; @@ -206,7 +217,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Configure CritScore for all numbers greater than or equal to tNum (this could happen multiple times, but why) rollConf.critScore.on = true; for (let i = tNum; i <= rollConf.dieSize; i++) { - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Parsing cs> ${i}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Parsing cs> ${i}`); rollConf.critScore.range.push(i); } break; @@ -214,7 +225,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Configure CritScore for all numbers less than or equal to tNum (this could happen multiple times, but why) rollConf.critScore.on = true; for (let i = 0; i <= tNum; i++) { - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Parsing cs< ${i}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Parsing cs< ${i}`); rollConf.critScore.range.push(i); } break; @@ -228,7 +239,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Configure CritFail for all numbers greater than or equal to tNum (this could happen multiple times, but why) rollConf.critFail.on = true; for (let i = tNum; i <= rollConf.dieSize; i++) { - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Parsing cf> ${i}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Parsing cf> ${i}`); rollConf.critFail.range.push(i); } break; @@ -236,7 +247,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Configure CritFail for all numbers less than or equal to tNum (this could happen multiple times, but why) rollConf.critFail.on = true; for (let i = 0; i <= tNum; i++) { - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Parsing cf< ${i}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Parsing cf< ${i}`); rollConf.critFail.range.push(i); } break; @@ -269,7 +280,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Configure Exploding for all numbers greater than or equal to tNum (this could happen multiple times, but why) rollConf.exploding.on = true; for (let i = tNum; i <= rollConf.dieSize; i++) { - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Parsing !> ${i}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Parsing !> ${i}`); rollConf.exploding.nums.push(i); } break; @@ -280,7 +291,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Configure Exploding for all numbers less than or equal to tNum (this could happen multiple times, but why) rollConf.exploding.on = true; for (let i = 1; i <= tNum; i++) { - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Parsing !< ${i}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Parsing !< ${i}`); rollConf.exploding.nums.push(i); } break; @@ -303,7 +314,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Since only one drop or keep option can be active, count how many are active to throw the right error let dkdkCnt = 0; [rollConf.drop.on, rollConf.keep.on, rollConf.dropHigh.on, rollConf.keepLow.on].forEach((e) => { - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Checking if drop/keep is on ${e}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Checking if drop/keep is on ${e}`); if (e) { dkdkCnt++; } @@ -369,7 +380,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // Initial rolling, not handling reroll or exploding here for (let i = 0; i < rollConf.dieCount; i++) { - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Initial rolling ${i} of ${JSON.stringify(rollConf)}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Initial rolling ${i} of ${JSON.stringify(rollConf)}`); // If loopCount gets too high, stop trying to calculate infinity if (loopCount > config.limits.maxLoops) { throw new Error('MaxLoopsExceeded'); @@ -403,7 +414,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea // If needed, handle rerolling and exploding dice now if (rollConf.reroll.on || rollConf.exploding.on) { for (let i = 0; i < rollSet.length; i++) { - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Handling rerolling and exploding ${JSON.stringify(rollSet[i])}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Handling rerolling and exploding ${JSON.stringify(rollSet[i])}`); // If loopCount gets too high, stop trying to calculate infinity if (loopCount > config.limits.maxLoops) { throw new Error('MaxLoopsExceeded'); @@ -480,7 +491,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea throw new Error('MaxLoopsExceeded'); } - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Setting originalIdx on ${JSON.stringify(rollSet[j])}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Setting originalIdx on ${JSON.stringify(rollSet[j])}`); rollSet[j].origidx = j; if (rollSet[j].rerolled) { @@ -534,7 +545,7 @@ export const roll = (rollStr: string, maximiseRoll: boolean, nominalRoll: boolea throw new Error('MaxLoopsExceeded'); } - loggingEnabled && log(LT.LOG, `handling roll20 ${rollStr} | Dropping dice ${dropCount} ${JSON.stringify(rollSet[i])}`); + loggingEnabled && log(LT.LOG, `handling ${rollType} ${rollStr} | Dropping dice ${dropCount} ${JSON.stringify(rollSet[i])}`); // Skip all rolls that were rerolled if (!rollSet[i].rerolled) { rollSet[i].dropped = true;