Skip to content

Instantly share code, notes, and snippets.

@mkremins
Created June 25, 2026 21:19
Show Gist options
  • Select an option

  • Save mkremins/f81eff65ba56e887c40dd9c44c1ade93 to your computer and use it in GitHub Desktop.

Select an option

Save mkremins/f81eff65ba56e887c40dd9c44c1ade93 to your computer and use it in GitHub Desktop.
Fairmath: softly saturating arithmetic for storygames
// Generalized implementation of ChoiceScript's "fairmath":
// a variant of additive arithmetic that bounds the outputs to a specific range
// and reduces the impact of additions proportional to the starting value's closeness
// to the edge of the range you're moving toward. ChoiceScript's fairmath implementation
// uses 0-100 as the hardcoded range for values; this implementation allows you to
// specify your own range, but will default to 0-100 if none is provided.
//
// Example usage:
// `fairmath({to: 10, add: 20, min: 0, max: 100}) // => 28`
//
// For more information:
// - https://choicescriptdev.fandom.com/wiki/Arithmetic_operators#Fairmath
// - https://videlais.com/2018/08/24/learning-choicescript-part-6-fairmath/
// - https://github.com/ChapelR/fairmath
function fairmath(params) {
const min = params.min || 0;
const max = params.max || 100;
const range = max - min;
const initVal = params.to;
const baseDelta = params.add;
const goingUp = baseDelta >= 0;
const distanceFromEdge = goingUp ? max - initVal : initVal - min;
const realDelta = (baseDelta / range) * distanceFromEdge;
const uncappedResult = initVal + realDelta;
return Math.max(min, Math.min(max, uncappedResult));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment