Quick answer: Augment each element with its original index. Sort by primary key, then by index as a tiebreaker. Stable sort even on old browsers.

A high score table sorts by score descending. Players with identical scores swap positions every refresh — sort isn’t stable. The display feels random.

Augmented Array

Maintain a parallel index in the array data:

[
  { score: 100, name: "A", idx: 0 },
  { score: 200, name: "B", idx: 1 },
  { score: 100, name: "C", idx: 2 }
]

Sort comparator: score desc, then idx asc:

function(a, b) {
    if (a.score != b.score) return b.score - a.score;
    return a.idx - b.idx;
}

In Construct Events

Construct’s Sort action calls a JS expression or uses a custom event. For complex sorts, use the JavaScript module:

scoreArray.sort((a, b) => {
    const s = b.score - a.score;
    return s !== 0 ? s : a.idx - b.idx;
});

Run via Browser → Execute JavaScript or in a JS file imported via the script project property.

Why Indices Help

Without tiebreaker, the sort algorithm freely swaps equal elements. With idx tiebreaker, ordering is deterministic: equal-score players always show in the same relative order.

Stable Sort Helper Function

Reuse across the project:

function stableSort(arr, cmp) {
    return arr
        .map((v, i) => [v, i])
        .sort(([a, i], [b, j]) => cmp(a, b) || i - j)
        .map(([v]) => v);
}

Decorates with index, sorts, undecorates. Stable on any JS runtime.

Verifying

Sort score table repeatedly. Equal-score entries always in the same order. Add a new tied entry; it slots after existing same-score entries (matching insertion order).

“Stable sort = predictable display. Pair sort key with index, problem solved everywhere.”

For leaderboards specifically, also add timestamp tiebreaker — earlier scorers rank ahead, motivating early competition.