Sorting scenes

Hi all,

I am trying to iterate over all scenes in my game in an order based upon a numeric property (sc-chapter). Can Inform do this or should I create such a list myself (entry 1 with sc-chapter 1, etc)?
The following fails to compile because apparently I cannot sort a list of scenes based on a property (sorting a list of scenes works, even in reverse order, but that ignores the proerty I want to sort in).

Laboratory is a room.

A scene has a number called sc-chapter. [ Entire Game will be chapter 0 ]

scene-two is a recurring scene. The sc-chapter of scene-two is 2.
scene-one is a recurring scene. The sc-chapter of scene-one is 1.

Definition: a scene is active if its sc-chapter is greater than 0. [ Excludes Entire Game ]

When play begins:
	let L be the list of active scenes;
	sort L in sc-chapter order; [ this line fails ]
	repeat with S running through L:
		say "[sc-chapter of S]: [S].";

In WI 21.8 the phrase definitions quietly shift from list of values to list of objects for the sort in property order phrases. So sorting non-objects is unimplemented. You’ll have to write your own sort. (You could create a kind of object that had a scene property and an sc-chapter property, but it’s probably simpler to write your own sort.)

3 Likes

I think the sorting only works with numeric properties of things, not properties of scenes. (Edit: or what Zed said.)

One way would be to use a relation:

Lab is a room.

A scene has a number called sc-chapter. The sc-chapter of a scene is usually -1.

Occurrence relates a scene (called S) to a number (called N) when the sc-chapter of S is N. The verb to occur at means the occurrence relation.

ScA is a scene.
The sc-chapter of ScA is 1.

ScB is a scene.
The sc-chapter of ScB is 3.

ScC is a scene.
The sc-chapter of ScC is 2.

Sc-totalchapters is a number that varies. Sc-totalchapters is 3.

After jumping:
	repeat with X running from 1 to sc-totalchapters:
		let S be a random scene which occurs at X;
		say "Chapter [X]: [S].";

Output:

>jump
Chapter 1: ScA.
Chapter 2: ScC.
Chapter 3: ScB.

4 Likes

I wonder how useful a general-purpose sort that takes a list of K and a phrase K => number would be.

Probably not very useful without lambdas.

1 Like

I dunno. Let’s find out.

use the serial comma.

lab is a room.

A scene has a number called sc-chapter.

scene-two is a recurring scene. The sc-chapter of scene-two is 2.
scene-four is a recurring scene. The sc-chapter of scene-four is 4.
scene-one is a recurring scene. The sc-chapter of scene-one is 1.
scene-three is a recurring scene. The sc-chapter of scene-three is 3.

to decide what number is (s1 - scene) vs (s2 - scene) (this is scene-cmp):
    decide on the sc-chapter of s1 <=> the sc-chapter of s2;

when play begins:
    let l be the list of scenes;
    sort l by scene-cmp;
    puts l;

Include (-
[ partition_fn arr p start end fn pivot l h tmp index;
  l = start;
  h = end - 2;
  pivot = LIST_OF_TY_GetItem(arr, p+1);
  ListSwapEntries(arr, end, p+1);
  while (l < h) {
        if ((fn)(LIST_OF_TY_GetItem(arr, l+1),pivot) < 0) {
            l++;
        } else if ((fn)(LIST_OF_TY_GetItem(arr, h+1),pivot) >= 0)  {
            h--;
        } else {
          ListSwapEntries(arr,l+1,h+1);
        }
    }
    index = h;
    if ((fn)(LIST_OF_TY_GetItem(arr, h+1), pivot) < 0) index++;
    ListSwapEntries(arr,end,index+1);
    return index;
];

[ phrase_sort_fn arr start end fn p;
  if ((end - start) < 2) return;
  p = start + ((end-start)/2);
  p = partition_fn(arr, p, start, end, fn);
    phrase_sort_fn(arr, start, p, fn);
    phrase_sort_fn(arr, p+1, end, fn);
];

[ spaceship v1 v2 k cmp_fn;
  if KOVComparisonFunction(k) cmp_fn = (KOVComparisonFunction(k))(v1,v2);
  if ((~~cmp_fn) || (cmp_fn == UnsignedCompare)) return v1 - v2;
  return cmp_fn(v1,v2);
];
-)

To sort (L - a list of values of kind K) by (ph - phrase (K, K) -> number):
    (- phrase_sort_fn({-by-reference:L},0,BlkValueRead({L}, LIST_LENGTH_F), {ph}-->1); -)

to puts (sv - sayable value): say sv; say line break;

To decide what number is (v1 - a value of kind K) <=> (v2 - a K):
    (- spaceship({v1},{v2},{-strong-kind:K}) -)

I suppose I’ll extension-ize this later.

Edited: @drpeterbatesuk alerted me to a problem with my spaceship phrase: as written, it only worked with block kinds of value (e.g., texts) and the one non-block type I’d special-cased, number. It should now work in the general case, where “work” means “make the same comparison Inform would when sorting a list of this kind”. Plus I noticed there’s an existing ListSwapEntries function that was basically the same thing as my swap_list_entries so now my code uses it.

7 Likes