/**
* @module counter
*/
let next_free = 1;
/**
* Represents a counter, which is a wrapper around item IDs
* @typedef {object} counter
* @property {item} item Item ID of a counter
* @property {item_type} type Type of a counter
* @property {add} add Adds a specific amount (or another counter) to the current counter
* @property {subtract} subtract Subtracts a specific amount (or another counter) from the current counter
* @property {multiply} multiply Multiplies the current counter by a specific amount (or another counter)
* @property {divide} divide Divides the current counter by a specific amount (or another counter)
* @property {set} set Sets the current counter to a specific amount or another counter
* @property {reset} reset Resets the current counter to 0
* @property {if_is} if_is Checks if a comparison is true, and if so calls a group (SMALLER_THAN/EQUAL_TO_LARGER_THAN)
* @property {to_const} to_const Converts the current counter to a plain number by taking in a range of possible values and a function
* @property {copy_to} copy_to Copies the current counter to another counter
* @property {display} display Displays the current counter at a specific position
* @property {to_obj} to_obj Returns item display for current counter as an object
* @property {add_to} add_to Adds the current counter to another and resets the current counter
* @property {subtract_from} subtract_from Subtracts the current counter from another and resets the current counter
* @property {function} abs Gets absolute value from counter
* @property {function} neg Converts value to negative value
*/
/**
* Adds a specific amount (or another counter) to the current counter
* @callback add
* @param {number|counter} amount Counter or number to add to the current counter
*/
/**
* Subtracts a specific amount (or another counter) from the current counter
* @callback subtract
* @param {number|counter} amount Counter or number to subtract from the current counter
*/
/**
* Multiplies the current counter by a specific amount (or another counter)
* @callback multiply
* @param {number|counter} amount Counter or number to multiply the current counter by
*/
/**
* Divides the current counter by a specific amount (or another counter)
* @callback divide
* @param {number|counter} amount Counter or number to divide the current counter by
*/
/**
* Sets the current counter to a specific amount (or another counter)
* @callback set
* @param {number|counter} amount Counter or number to set the current counter to
*/
/**
* Resets the current counter to 0
* @callback reset
*/
/**
* Returns item display for current counter as an object
* @callback to_obj
* @returns {object} Resulting item display
*/
/**
* Checks if a comparison is true, and if so calls a group (SMALLER_THAN/EQUAL_TO_LARGER_THAN)
* @callback if_is
* @param {comparison} comparison Condition to check for between the counter and number
* @param {number} other Number to compare the current counter to
* @param {group} trig_func Trigger function or group to run if the comparison is true
*/
/**
* Converts the current counter to a plain number by taking in a range of possible values and a function
* @callback to_const
* @param {array} range Possible range of values that the current counter is equal to
* @param {function} func Callback function to run that takes the plain numerical value as input
*/
/**
* Displays the current counter at a specific position
* @callback display
* @param {number} x X position of item display
* @param {number} y Y position of item display
*/
/**
* Copies the current counter to another counter
* @callback copy_to
* @param {counter} counter Counter to copy the current counter to
*/
/**
* Adds the current counter to another and resets the current counter
* @callback add_to
* @param {counter} counter Counter to add the current counter to
*/
/**
* Subtracts the current counter from another and resets the current counter
* @callback subtract_from
* @param {counter} counter Counter to be subtracted from
*/
/**
* Creates a counter, which has methods for editing items
* @function
* @param {number|boolean} [num=0] Number or boolean to be represented by counter
* @param {boolean} [use_id=false] Whether to use an existing item ID as a counter instead of creating a new item
* @param {boolean} [persistent=false] Whether to make the counter persistent between attempts
* @param {boolean} [timer=false] Whether to make the counter a timer
* @returns {counter} Resulting counter
*/
let counter = (num = 0, use_id = false, persistent = false, timer = false) => {
let id = use_id ? num : next_free++;
if (num !== 0 && !use_id) {
if (!persistent) {
$.add(object({
OBJ_ID: 1817,
COUNT: num,
ITEM: id,
}));
}
}
if (persistent) {
$.add(object({
OBJ_ID: 3641,
PERSISTENT: true,
ITEM: id,
494: +(persistent && timer)
}));
};
let exports = {
item: id,
type: timer ? TIMER : ITEM,
add: (amount) => {
if (typeof amount == 'number') {
$.add(object({
OBJ_ID: 1817,
COUNT: amount,
ITEM: id,
}));
} else if (typeof amount == 'object') {
$.add(item_edit(amount.item, undefined, id, amount.type, NONE, exports.type, ADD));
}
return exports;
},
set: (amount) => {
if (typeof amount == 'number') {
$.add(object({
OBJ_ID: 1817,
COUNT: amount,
OVERRIDE_COUNT: true,
ITEM: id,
}));
} else if (typeof amount == 'object') {
$.add(item_edit(undefined, amount.item, id, NONE, amount.type, exports.type, EQ));
}
return exports;
},
subtract: (amount) => {
if (typeof amount == 'number') {
$.add(object({
OBJ_ID: 1817,
COUNT: -amount,
ITEM: id,
}));
} else if (typeof amount == 'object') {
$.add(item_edit(amount.item, undefined, id, amount.type, NONE, exports.type, SUB));
}
return exports;
},
multiply: (amount) => {
if (typeof amount == 'number') {
$.add(object({
OBJ_ID: 1817,
MODIFIER: amount,
MULT_DIV: 1,
ITEM: id,
}));
} else if (typeof amount == 'object') {
$.add(item_edit(amount.item, undefined, id, amount.type, NONE, exports.type, MUL));
}
return exports;
},
divide: (amount) => {
if (typeof amount == 'number') {
$.add(object({
OBJ_ID: 1817,
MODIFIER: amount,
MULT_DIV: 2,
ITEM: id,
}));
} else if (typeof amount == 'object') {
$.add(item_edit(amount.item, undefined, id, amount.type, NONE, exports.type, DIV));
}
return exports;
},
display: (x, y) =>
$.add(object({
OBJ_ID: 1615,
X: x,
Y: y,
ITEM: id,
COLOR: color(1),
})),
to_obj: () => {
let or = object({
OBJ_ID: 1615,
ITEM: id,
COLOR: color(1)
});
return or;
},
if_is: (comparison, other, trig_func) => {
$.add(object({
OBJ_ID: 1811,
TARGET: trig_func,
COUNT: other,
ACTIVATE_GROUP: true,
COMPARISON: comparison,
ITEM: id,
}));
},
to_const: (range, cb) => {
let old_ctx = Context.current;
for (let i in range) {
i = range[i];
let id = crypto.randomUUID();
let context = new Context(id, true);
cb(i);
Context.set(old_ctx);
exports.if_is(EQUAL_TO, i, context.group);
}
},
add_to: (item) => {
item.add(exports);
exports.reset();
return exports;
},
copy_to: (item) => {
$.add(item_edit(undefined, id, item.item, NONE, item.type, exports.type, EQ));
return exports;
},
clone: () => {
let n_counter = counter(0);
exports.copy_to(n_counter);
return n_counter;
return exports;
},
subtract_from: (b) => {
// basically (a - b) then reset b to zero
$.add(item_edit(id, b.item, id, exports.type, b.type, exports.type, EQ, SUB));
b.reset();
return exports;
},
reset: () => {
exports.set(0);
return exports;
},
abs: () => {
$.add(item_edit(undefined, exports.item, exports.item, NONE, exports.type, exports.type, EQ, undefined, undefined, 1, ABS));
return exports;
},
neg: () => {
$.add(item_edit(undefined, exports.item, exports.item, NONE, exports.type, exports.type, EQ, undefined, undefined, 1, NEG));
return exports;
}
};
if (persistent) {
let tfr = trigger_function(() => {
$.add(object({
OBJ_ID: 1817,
COUNT: num,
OVERRIDE_COUNT: true,
ITEM: id,
}));
});
exports.if_is(EQUAL_TO, 0, tfr);
}
return exports;
};
/**
* Version of counter that supports floating point values
* @typedef {object} float_counter
* @property {item} item Item ID of a counter
* @property {item_type} type Type of a counter
* @property {add} add Adds a specific amount (or another counter) to the current counter
* @property {subtract} subtract Subtracts a specific amount (or another counter) from the current counter
* @property {multiply} multiply Multiplies the current counter by a specific amount (or another counter)
* @property {divide} divide Divides the current counter by a specific amount (or another counter)
* @property {set} set Sets the current counter to a specific amount or another counter
* @property {reset} reset Resets the current counter to 0
* @property {copy_to} copy_to Copies the current counter to another counter
* @property {display} display Displays the current counter at a specific position
* @property {to_obj} to_obj Returns item display for current counter as an object
* @property {add_to} add_to Adds the current counter to another and resets the current counter
* @property {subtract_from} subtract_from Subtracts the current counter from another and resets the current counter
* @property {function} abs Gets absolute value from counter
* @property {function} neg Converts value to negative value
* @property {function} round Rounds the floating point value into an integer
*/
/**
* Creates a floating-point counter
* @function
* @param {number|boolean} [num=0] Number or boolean to be represented by counter
* @returns {counter} Resulting counter
*/
let float_counter = (val = 0, use_id = false, persistent = false) => {
let c_item = counter(use_id ? val : 0, use_id, persistent, true);
if (val !== 0 && !use_id) $.add(item_edit(undefined, undefined, c_item.item, NONE, NONE, TIMER, EQ, undefined, undefined, val));
c_item.display = (x, y, seconds_only = false) => $.add(object({
OBJ_ID: 1615,
X: x,
Y: y,
ITEM: c_item.item,
TIME_COUNTER: true,
SECONDS_ONLY: seconds_only,
COLOR: color(2),
}));
c_item.to_obj = () => object({
OBJ_ID: 1615,
ITEM: c_item.item,
TIME_COUNTER: true,
COLOR: color(2),
});
c_item.add = (amount) => {
if (typeof amount == 'number') {
$.add(item_edit(undefined, undefined, c_item.item, NONE, NONE, TIMER, ADD, undefined, undefined, amount));
} else if (typeof amount == 'object') {
$.add(item_edit(amount.item, undefined, c_item.item, amount.type, NONE, TIMER, ADD));
}
return c_item;
}
c_item.if_is = (comparison, other, trig_func) => {
$.add(item_comp(c_item.item, 0, TIMER, NONE, comparison == 2 ? 3 : comparison, trig_func, undefined, undefined, other));
};
c_item.subtract = (amount) => {
if (typeof amount == 'number') {
$.add(item_edit(undefined, undefined, c_item.item, TIMER, NONE, TIMER, SUB, undefined, undefined, amount));
} else if (typeof amount == 'object') {
$.add(item_edit(amount.item, undefined, c_item.item, amount.type, NONE, TIMER, SUB));
}
return c_item;
}
c_item.divide = (amount) => {
if (typeof amount == 'number') {
$.add(item_edit(undefined, undefined, c_item.item, TIMER, NONE, TIMER, DIV, undefined, undefined, amount));
} else if (typeof amount == 'object') {
$.add(item_edit(amount.item, undefined, c_item.item, amount.type, NONE, TIMER, DIV));
}
return c_item;
}
c_item.multiply = (amount) => {
if (typeof amount == 'number') {
$.add(item_edit(undefined, undefined, c_item.item, TIMER, NONE, TIMER, MUL, undefined, undefined, amount));
} else if (typeof amount == 'object') {
$.add(item_edit(amount.item, undefined, c_item.item, amount.type, NONE, TIMER, MUL));
}
return c_item;
}
c_item.set = (amount) => {
if (typeof amount == 'number') {
console.log(c_item)
$.add(item_edit(undefined, undefined, c_item.item, NONE, NONE, TIMER, EQ, undefined, undefined, amount));
} else if (typeof amount == 'object') {
$.add(item_edit(amount.item, undefined, c_item.item, amount.type, NONE, TIMER, EQ));
}
return c_item;
};
c_item.reset = () => {
c_item.set(0);
return c_item;
}
c_item.abs = () => {
$.add(item_edit(undefined, c_item.item, c_item.item, NONE, TIMER, TIMER, EQ, undefined, undefined, 1, ABS));
return c_item;
};
c_item.neg = () => {
$.add(item_edit(undefined, c_item.item, c_item.item, NONE, TIMER, TIMER, EQ, undefined, undefined, 1, NEG));
return c_item;
};
c_item.round = () => {
$.add(item_edit(undefined, c_item.item, c_item.item, NONE, TIMER, TIMER, EQ, undefined, undefined, 1, undefined, undefined, RND));
return c_item;
};
return c_item;
}
module.exports = { counter, float_counter };