Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /***
- *
- * Author: Draco18s
- *
- * call this from Input Modifier
- * var r = MatchDiceAndParse(modifiedText, state);
- * if(r.stop) return r;
- * modifiedText = r.text;
- *
- * /dice or /roll will display the results in a message.
- * Syntax errors will display in a message and leave the input unaltered.
- * /dice help will display the help text, reproduced here because it's unreadable in a message
- * due to AI Dungeon's current CSS.
- *
- * Wrap dice values in [].
- * ndm: rolls n m-sided dice. +-/*% supported. < > compares two values as <= and >= respectively and the ternary
- * operator can evaluate a truthy value to strings, eg [1d6>5?"hit":"miss"].
- * {} creates a collection (eg {1,2,3}), dice rolled inside a collection are concatenated into the collection
- * instead of being summed, eg [{3d6}] will create a collection of 3 random values
- * Wrap in parens to evaluate the sum first, eg [{(3d6),(3d6)}].
- * p and s will pick (without replacement) or select (with replacement) n values from a collection.
- * /dice [...] will place the result in the message and not send to the AI.
- *
- ***/
- function MatchDiceAndParse(modifiedText, state) {
- delete state.message;
- const regex = /\[((?:[dhlps \d?:*+,/(){}<>-]|(?:\?"[^"]*":"[^"]*")){3,})\]/i;
- var didMatch = false;
- while(modifiedText.match(regex) && state.message == undefined) {
- didMatch = true;
- modifiedText = modifiedText.replace(regex, function(v) {
- var m = v.match(regex);
- return ParseAndRollDice(m[1], state);
- });
- }
- const command = /\/dice|\/roll/i;
- if(modifiedText.match(command)) {
- if(modifiedText.match("help")) {
- state.message = "Wrap dice values in [].\nndm: rolls n m-sided dice. +-*/% supported. < > compares two values as <= and >= respectively and the ternary operator can evaluate a truthy value to strings, eg [1d6>5?\"hit\":\"miss\"].\n{} creates a collection (eg {1,2,3}), dice rolled inside a collection are concatenated into the collection instead of being summed, eg [{3d6}] will create a collection of 3 random values\nWrap in parens to evaluate the sum first, eg [{(3d6),(3d6)}].\np and s will pick (without replacement) or select (with replacement) n values from a collection.\n/dice [...] will place the result in the message and not send to the AI.";
- return { text: "", stop: true };
- }
- else if(didMatch) {
- if(state.message == undefined)
- state.message = modifiedText.replace(command,"");
- else
- return { text: modifiedText, stop: true };
- return { text: "", stop: true };
- }
- }
- return { text: modifiedText };
- }
- var OpPrecedence = {
- '(': 999,
- 'd': 50,
- 'p': 40,
- 's': 40,
- '*': 20,
- '/': 20,
- '%': 20,
- 'h': 15,
- 'l': 15,
- '+': 10,
- '-': 10,
- '<': 5,
- '>': 5,
- ',': 5,
- '{': 2,
- '?': 1,
- ':': 1
- }
- function ParseAndRollDice(dice, state) {
- var output = [];
- var trainyard = [];
- var value = -1;
- var stringread = false;
- var tempString = "";
- for(var i=0; i<dice.length;i++) {
- var exp = dice[i];
- if(stringread) {
- if(exp == '"') {
- stringread = false;
- output.push(tempString);
- }
- else {
- tempString += exp;
- }
- continue;
- }
- if(exp == ' ' || exp == ':') continue;
- if(exp>='0' && exp<='9') {
- if(value == -1) value = 0;
- value = value*10+parseInt(exp.toString());
- continue;
- }
- else if(value != -1) {
- output.push(value);
- value = -1;
- }
- switch(exp) {
- case '"':
- tempString = "";
- stringread = true;
- break;
- case '{':
- case '(':
- output.push(exp);
- case '+':
- case '-':
- case '*':
- case '/':
- case '%':
- case 'd':
- case 'p':
- case 's':
- case 'h':
- case 'l':
- case '<':
- case '>':
- case ',':
- case '?':
- while(trainyard.length > 0 && trainyard[trainyard.length-1] != '(' && OpPrecedence[exp] <= OpPrecedence[trainyard[trainyard.length-1]]) {
- var pp = trainyard.pop();
- output.push(pp);
- }
- trainyard.push(exp);
- break;
- case '}':
- while(trainyard.length > 0) {
- var c = trainyard.pop();
- if(c == '{') break;
- if(c == '(') {
- state.message = "Unpaired (!";
- return "["+dice+"]";
- }
- output.push(c);
- }
- output.push(exp);
- break;
- case ')':
- while(trainyard.length > 0) {
- var c = trainyard.pop();
- if(c == '(') break;
- if(c == '{') {
- state.message = "Unpaired {!";
- return "["+dice+"]";
- }
- output.push(c);
- }
- output.push(exp);
- break;
- default:
- if(!(exp>='0' && exp<='9')) {
- state.message = "Unrecognized dice operation: " + exp;
- return "["+dice+"]";
- }
- break;
- }
- }
- if(value > -1) {
- output.push(value);
- }
- while(trainyard.length > 0) {
- output.push(trainyard.pop());
- }
- var ops = [];
- var v1=0;
- var v2=0;
- var collapse = 0;
- var retreat = [];
- while(output.length > 0) {
- exp = output.shift();
- switch(exp) {
- case '+':
- v1 = ParseArray(ops.pop());
- v2 = ParseArray(ops.pop());
- ops.push(v2+v1);
- break;
- case '-':
- v1 = ParseArray(ops.pop());
- v2 = ParseArray(ops.pop());
- ops.push(v2-v1);
- break;
- case '*':
- v1 = ParseArray(ops.pop());
- v2 = ParseArray(ops.pop());
- ops.push(v2*v1);
- break;
- case '/':
- v1 = ParseArray(ops.pop());
- v2 = ParseArray(ops.pop());
- ops.push(Math.floor(v2/v1));
- break;
- case '%':
- v1 = ParseArray(ops.pop());
- v2 = ParseArray(ops.pop());
- ops.push(Math.floor(v2%v1));
- break;
- case 'd':
- v1 = ParseArray(ops.pop());
- v2 = ParseArray(ops.pop());
- var r = [];
- for(var n=0; n < v2; n++) {
- r.push(Math.floor(Math.random()*v1)+1);
- }
- if(collapse == 0) {
- ops.push(ParseArray(r));
- }
- else {
- ops.push(r);
- }
- break;
- case ':':
- break;
- case '?':
- if(ops.length < 3) {
- state.message = "Invalid dice operation: " + exp + "\nInvalid number of operands.";
- return "["+dice+"]";
- }
- v3 = ops.pop();
- v2 = ops.pop();
- var v1 = ops.pop();
- if(v1) {
- ops.push(v2);
- }
- else {
- ops.push(v3);
- }
- break;
- case 'p':
- case 's':
- v1 = ParseArray(ops.pop());
- v2 = ops.pop();
- if(!Array.isArray(v2)) {
- state.message = "Unrecognized dice operation: " + exp + "\nValue " + v2 + " was not a collection.";
- return "["+dice+"]";
- }
- if(v2.length < v1) {
- state.message = "Invalid dice operation: " + exp + "\nValue " + v1 + " was larger than the size of the collection " + v2 + ".";
- return "["+dice+"]";
- }
- var r = [];
- for(var h=0;h<v1;h++) {
- var i = Math.floor(Math.random()*v2.length);
- r.push(v2[i]);
- if(exp == 'p')
- v2.splice(i,1);
- }
- if(collapse == 0) {
- ops.push(ParseArray(r));
- }
- else {
- ops.push(r);
- }
- break;
- case 'h':
- v1 = ParseArray(ops.pop());
- v2 = ops.pop();
- if(!Array.isArray(v2)) {
- state.message = "Unrecognized dice operation: " + exp + "\nValue " + v2 + " was not a collection.";
- return "["+dice+"]";
- }
- v2.sort(function(a, b){return a - b});
- v2.reverse();
- var r = [];
- for(var h=0;h<v1;h++) {
- r.push(v2[h]);
- }
- ops.push(r);
- break;
- case 'l':
- v1 = ParseArray(ops.pop());
- v2 = ops.pop();
- if(!Array.isArray(v2)) {
- state.message = "Unrecognized dice operation: " + exp + "\nValue " + v2 + " was not a collection.";
- return "["+dice+"]";
- }
- v2.sort(function(a, b){return a - b});
- var r = [];
- for(var h=0;h<v1;h++) {
- r.push(v2[h]);
- }
- ops.push(r);
- break;
- case '<':
- v1 = ParseArray(ops.pop());
- v2 = ParseArray(ops.pop());
- ops.push(v2 <= v1);
- break;
- break;
- case '>':
- v1 = ParseArray(ops.pop());
- v2 = ParseArray(ops.pop());
- ops.push(v2 >= v1);
- break;
- case '{':
- collapse++;
- break;
- case '}':
- collapse--;
- break;
- case '(':
- if(collapse > 0) {
- retreat.push(collapse);
- collapse = 0;
- }
- break;
- case ')':
- if(retreat.length > 0) {
- collapse = retreat.pop();
- }
- break;
- case ',':
- v1 = ops.pop();
- v2 = ops.pop();
- var p = [];
- if(collapse > 0 && v1 != null && v2 != null) {
- if(Array.isArray(v2)) {
- p = v2.concat(v1);
- }
- else if(Array.isArray(v1)) {
- var v3 = [];
- v3.push(v2);
- p = v3.concat(v1);
- }
- else {
- p = [v2, v1];
- }
- ops.push(p);
- }
- else if(v1 == null || v2 == null) {
- state.message = "Invalid operation: " + exp + "\nInvalid collection syntax!";
- return "["+dice+"]";
- }
- else {
- state.message = "Invalid operation: " + exp + "\nTo create a collection, use {a,b}.";
- return "["+dice+"]";
- }
- break;
- default:
- if(collapse > 0) {
- ops.push([exp]);
- }
- else {
- ops.push(exp);
- }
- break;
- }
- }
- var ret = ops.pop();
- if(ret === true) {
- return "[Success!]";
- }
- else if(ret === false) {
- return "[Failed!]";
- }
- if(Array.isArray(ret)) {
- return "(" + ret + ")";
- }
- return ParseArray(ret);
- }
- function ParseArray(val) {
- if(Array.isArray(val)) {
- var r = 0;
- for(var i = 0; i < val.length; i++) {
- r+=val[i];
- }
- return r;
- }
- else
- return val;
- }
Add Comment
Please, Sign In to add comment