Mixed-Up Mother Goose is a Sierra adventure game,
in the lineage of classics like
King's Quest and
Space Quest.
It is designed for small children, with simplified mechanics and no reading requirement.
The game was remade multiple times;
this TAS is of the original
AGI version from 1987.
The run features computer-optimized routing,
careful micro optimization,
and a few fun movement glitches.
The most significant aspect is exhaustive enumeration
of random seeds to find
an item assignment that can be solved quickly.
These submission comments highlight the most interesting parts;
for chronological development notes
see
thread #23454.
Suggested screenshot: frame 19277
Emulation
Mixed-Up Mother Goose (1987) 1.00D, AGI version 2.915
goodolddays.net ID: 168
SHA-256 checksum:
e33dea30ceb5692d4111f3a92037cbd15b9c62f2dd2ea2a251ee1ce3e5e354fc 000168_mixed-up_mother_goose/disk1.img
PCem 17+st-1
libTAS 1.4.3
Debian bullseye amd64, Linux 5.10.0-13-amd64
Music is an important part of this game,
which is why I chose to play it on an emulated
Tandy 1000
rather than one of the
premade PC configurations.
Mixed-Up Mother Goose uses the Tandy's multi-channel sound hardware for
better music
than is possible with the PC speaker.
PCem
Machine: [8086] Tandy 1000 SL/2
CPU: 8086/8
Memory: 512 KB
HDD: None
FDD1: 3.5" 720k
FDD2: None
PCem ROMs and SHA-256 checksums:
37527f661580e5a09710051cec67422abfadf31c61b841537a91e7f27be19304 mda.rom
2143765cebd59c2ef024f56284e17259b2dfaa8fca6cf419f48d533c5f3c55af wy700.rom
f17b4f9c063f88a096b02681b203178705796f0abcdffc696f2a1d605e3af84d 8x12.bin
7fe228566de37a2f06ca6703a9f1280fd75db2f2d0e0e635b7c3b1e214680866 tandy1000sl2/8079047.hu1
160116f3ad6788af7faa7a5f12de636de58ea18e2021ddba242ac1e801a927af tandy1000sl2/8079048.hu2
Game mechanics
The object of the game is to complete nursery rhymes
by finding 20 items
that have been randomly scattered over the game map
and delivering each to its proper place.
After completing a rhyme, you are rewarded with a musical cutscene.
The 20 items are internally numbered from 11 to 30.
They are divided into two types:
"walking" items and "pocket" items.
The walking items have an animated sprite
that follows you around the screen.
The pocket items, when collected,
simply disappear from the screen
and are understood to be carried by the player.
The map consists of 44
rooms.
Rooms 1–35 are "overworld" rooms arranged in a 7×5 grid.
Rooms 36–44 are "interior" rooms, accessed via doors in the overworld.
There are barriers (shown as black lines in the graphic below) that prevent you from walking
between or within certain rooms.
Gold squares show where where items may be placed;
blue circles are the rooms they must be delivered to.
For example: item 12, Miss Muffet,
wherever she may be placed initially,
must be delivered to her tuffet in room 9 (blue circle marked 12).
There are 22 rooms eligible for item placement
and only 20 items to place,
so 2 of the gold squares will be unused in any item assignment.
Item 27, the Watering Can, is the only item whose location is
not randomized.
It always starts in room 34.
The map shown is roughly the one used for
computer-assisted routing
and
random seed optimization.
It simplifies and omits some details that are important
for small-scale optimization and
point-to-point movement between route waypoints.
For example, at 19:08 we will comment on a wall-hugging strategy
that gives faster vertical movement between rooms.
The one-way passage from room 24 to room 17 is a movement glitch
we will see exploited at 11:08.
The player's inventory can hold only one item at a time.
When holding an item,
there are only two ways to remove it from the inventory:
deliver it to its destination,
or
swap it with a different item.
This is where the distinction between walking items and pocket items comes into play.
The rule is: walking items cannot remain in an interior room.
If you try to swap a walking item in an interior room,
the walking item will not stay in the room,
but will instead
"warp" to some other overworld room.
The route used in this TAS uses one swap,
but the warp mechanic turns out not to save time.
There are 20 items, but only 18 nursery rhymes.
That is because Old King Cole demands not one, but three items:
Pipe, Bowl, and Fiddlers Three,
which must be delivered in exactly that order.
Apart from that restriction, any item may be delivered at any time.
The open-world nature of the game,
and the possibility of item swaps and warps,
makes optimizing a specific random item assignment nontrivial.
Time-based random seed manipulation
The single most important optimization
is setting the system clock immediately after boot.
This is to control the RNG seed and get a favorable item assignment.
The Tandy 1000
does not have a hardware real-time clock,
so setting the time in libTAS has no effect.
Instead, we run the
TIME
command at the DOS prompt.
The item assignment algorithm is based on a
random number generator
that is seeded by the time of day,
specifically a
16-bit counter that increments at 18.2 Hz.
There are 65,536 possible random seeds,
but only 24,110 distinct item assignments:
many seeds result in the same effective assignment.
(I ignored 131 seeds that cause the RNG to re-seed itself from the current time again
before item assignment is finished, and that therefore
produce different assignments depending on the CPU speed.)
I wrote
an optimizer to test every one
of the 24,110 possible item assignments
and find the one with the fastest route.
The optimizer knows about distances and inter-room connectivity,
but it ignores some fixed costs, like delivery cutscenes,
and makes a few approximations.
The game's state space is too large to search exhaustively,
so the optimizer is an approximate one,
based on
simulated annealing.
Running the optimizer on all item assignments took about 1,800 CPU-hours.
One assignment emerged as the best by a wide margin.
There are three seeds that result in it:
34871, 44046, and 52929.
The difference in estimated time between the worst and best item assignments
is large, over 5 minutes.
Because the 16-bit 18.2 Hz counter wraps about once per hour,
and there are three usable seeds,
there are
72 moments in each 24-hour day
that we might use.
The time specification "3:40:5.3" was chosen because
it fits in the BIOS keyboard buffer.
The timestamp we're actually aiming for
is 3:40:18.02,
which is when we start a new game and
item assignment happens.
The item assignment we get is shown below.
The arrows are just a visual guide to help associate items' locations
with their delivery rooms,
and do not necessarily reflect movement in the run.
The route optimizer outputs the plan below.
(Actually, the optimizer outputs 24 routes that it thinks are equivalent,
because of its connectivity and movement approximations.
I arrived at this one, out of the 24,
after analyzing
small differences between the different options.)
Room | Actions | Timestamp in this run |
---|
start in room 32 (Mother Goose's house exterior) | | 02:00 |
go to room 30 | get Little Dog | 02:20 |
go to room 27 | deliver Little Dog to boy | 03:02 |
go to room 28 | get Broth | 03:41 |
go to room 21 (shoe house exterior) | deliver Broth to old woman | 03:50 |
go to room 44 (shoe house interior) | get Candlestick | 04:44 |
go to room 33 | deliver Candlestick to Jack | 05:20 |
go to room 34 | get Watering Can | 05:51 |
go to room 31 | deliver Watering Can to Mary Quite Contrary | 06:24 |
go to room 29 | get Bowl | 07:27 |
go to room 37 (castle interior) | swap Bowl for Ladder | 08:24 |
go to room 5 (castle courtyard east) | deliver Ladder to Humpty Dumpty | 08:42 |
go to room 11 | get Pipe | 09:13 |
go to room 37 (castle interior) | deliver Pipe to Old King Cole, get Bowl, deliver Bowl | 09:30 |
go to room 19 (Horner house side yard) | get Mouse | 10:36 |
go to room 41 (clock house interior) | deliver Mouse, get Steak | 11:06 |
go to room 36 (Sprat house interior) | deliver Steak to Sprats, get Pie | 12:03 |
go to room 43 (Horner house interior) | deliver Pie to Jack Horner, get Sixpence | 13:09 |
go to room 15 (crooked house exterior) | deliver Sixpence to Crooked Man | 14:26 |
go to room 40 (crooked house interior) | get Horse | 15:09 |
go to room 18 (Banbury Cross) | deliver Horse | 15:44 |
go to room 16 | get Sheep | 16:38 |
go to room 23 | deliver Sheep to Little Bo-Peep | 16:44 |
go to room 22 | get Pail | 17:20 |
go to room 1 (well) | deliver Pail to Jack and Jill | 17:47 |
go to room 8 | get Miss Muffet | 18:19 |
go to room 9 | deliver Miss Muffet | 18:33 |
go to room 2 | get Knife | 19:13 |
go to room 3 (castle courtyard west) | deliver Knife to Tommy Tucker | 19:53 |
go to room 20 | get Little Lamb | 21:01 |
go to room 13 (school exterior) | deliver Little Lamb to Mary | 21:10 |
go to room 39 | get Fiddle | 21:58 |
go to room 7 | deliver Fiddle to cat | 22:16 |
go to room 14 | get Wife | 22:58 |
go to room 12 (pumpkin house exterior) | deliver Wife to Peter Pumpkin Eater | 23:33 |
go to room 6 | get Fiddlers Three | 24:18 |
go to room 37 (castle interior) | deliver Fiddlers Three to Old King Cole | 25:17 |
Floppy drive delay
The game runs directly from the A: floppy drive.
A hard disk drive was an
optional upgrade
for the Tandy SL/2,
and even on other PC-compatibles,
directly from floppy is how
many would have played back in the day.
The floppy drive adds another dimension to optimization,
namely
the time needed to read data.
When you enter a new room, deliver an item,
or collect certain items,
there is a delay while the game reads data from the drive.
It's obviously a good idea to minimize the number of floppy drive accesses,
but it's even a little more complicated than that.
The disk drive motor needs to spin up before you can read data,
which takes about 1.2 seconds.
The OS keeps the motor spinning ("hot")
for about 1.5 seconds after the drive is used.
If you do another access while the drive is still hot,
you avoid the cost of spinning it up.
But if too much time passes,
you must pay the spin-up cost again
at the next disk access.
So, while you want to access the drive
as little as possible,
when you do need to access it,
you want to batch as many consecutive accesses together as possible,
in order to amortize the drive motor delay.
In most cases, the most accesses we can string together is 1 or 2,
but sometimes we manage 3 or 4.
00:15 Name entry
A one-character name is quickest to enter.
The traditional TAS name "A" doesn't work,
because the AGI
text parser
treats the word "a" specially.
For the same reason, the name "I" doesn't work
(and actually softlocks).
I used the name "@"
in honor of the
classic roguelike protagonist.
02:00 Game speed
For this TAS,
I decided to break with tradition
and play the game on "Fast" speed rather than "Fastest".
On Fastest, the game's speed depends on the speed
of the emulated CPU.
On Fast, the game runs at a fixed rate of 20 cycles per second.
The player character can move 1 pixel per game cycle
(horizontally or vertically or both).
It may look like the player moves 2 pixels per cycle horizontally,
but that is because the game's graphics are
stretched 2× horizontally—internally, the
x-coordinate
only changes by 1 unit.
Therefore it takes 1 second to move 20 pixels.
If you need to move both horizontally and vertically,
the time needed
is proportional to the
maximum of the
horizontal and vertical distances
(
Chebyshev distance);
i.e., diagonal movement is free.
The walkable area of rooms is usually
160 pixels wide and 80 pixels tall,
but there are many exceptions.
02:00 Shortcut behind Mother Goose's house
We start in room 32, at the bottom center of the map.
The route calls for
moving left, into room 31.
Instead of walking immediately left,
we first walk up, to the back of the house,
then left.
AGI adventure games are programmed in a bytecode called
logic.
The connections between rooms are not represented in any
systematic or structured way,
but as snippets of logic code in each room.
This is one of many places
where custom, room-specific logic
alters room connectivity in a way that is not visually apparent.
This is the relevant logic in room 32:
get.posn(O_EGO, v212, v213);
if (v212 < 62 && v213 < 95) {
new.room(31);
}
It says: if the player's y-coordinate
is less than (closer to the top of the screen than) 95,
and their x-coordinate is less than 62,
then immediately move into room 31.
It means that the threshold for entering room 31,
when you're behind the house,
is x-coordinate 62,
which is faster to get to than
walking to x-coordinate 0
from the front of the house.
Visually, it looks like this:
(The game internally locates the player
by the bottom left pixel of their sprite,
but in connectivity graphics like this one
I have adjusted the visual zones to be relative
to the bottom center of the sprite.
The player sprite is 7 pixels wide.)
Nearly every room has custom logic like this
that controls movement to neighboring rooms.
There is no way to infer the rules from the graphics;
in every room you have to read the logic and check for exceptions.
We will use this shortcut behind the house again, in the reverse direction,
when we return with the Little Dog—only then,
it will be defined in the logic of room 31.
A shortcut in one direction does not automatically imply
a shortcut in the opposite direction.
02:42 Little Dog delivery
The first item we collect and deliver is the Little Dog.
We must take the dog from room 30 to room 27,
which means moving 4 rooms east and 1 room north.
Here is one of the places where we
batch floppy drive accesses.
We go north from room 32 to room 25 near the right edge of the screen,
so that we can then go east from room 25 to room 26
while the floppy drive is still hot.
This "corner cutting" technique will be used repeatedly.
I tested every corners on the path between room 30 and room 27,
and this one was the fastest.
04:39 Out-of-bounds Candlestick
We collect the Broth from room 28 and deliver it to
the old woman who lives in a shoe,
one room to the north.
Inside the shoe is the next item, the Candlestick.
Although it's not visually obvious, the player
takes a shortcut out of bounds in the shoe house.
The trick takes advantage of an oversight in this room's
priority screen,
the hidden layer of graphics that defines where
the player is allowed to walk, among other things.
This is what the room's priority screen looks like,
with the relevant part magnified:
The blue and black lines define the walkable area:
the player may not cross these lines.
The area by the door is marked with a green line
(a
signal line)
as if it were a door,
but the logic of the room does not actually treat it as a door.
Instead, the green pixels are inert,
walkable pixels, which form a 1-pixel gap
at the bottom of the screen that
leads outside the intended walkable area.
Though out of bounds,
we can still get close enough to be within the Candlestick's collection radius.
Being out of bounds saves time
in exiting the room,
because we can walk straight down
rather than having to walk all the way back to the door.
05:19 Candlestick delivery
We enter room 33, to deliver the Candlestick, from the north,
because entering from the north provides us with about 43 pixels of free horizontal movement.
To avoid the player being hidden by foreground objects,
like trees,
room logic sometimes forces the player's position to
certain values.
On entering room 33 from the north,
if the player's x-coordinate is greater than 130
(i.e., behind the tree),
it gets set to 110 instead.
(Something similar would happen near the left edge of the screen.)
get.posn(O_EGO, v212, v213);
if (prev_room_no == 26) {
if (v212 > 130) {
position(O_EGO, 110, 86);
} else {
if (v212 > 80) {
position(O_EGO, 80, 86);
}
}
}
The delivery of the Candlestick,
like most deliveries in this game,
is based on distance from a point.
Delivery is triggered when the player is within
19 pixels of Jack.
Distance in AGI
is defined as the sum of horizontal distance and vertical displacement
(
Manhattan distance).
Therefore the delivery radius defines a diamond-shaped area:
But the goal is not simply to get inside the delivery area as fast as possible.
The player is usually scripted to move
to fixed waypoints after initiating the delivery,
and during cutscenes,
the player moves at half speed.
It is usually best to move the player to the point in
the delivery area that is closest to the first waypoint.
In the graphic above,
the first waypoint is marked by a black dot.
In this room, the player walks down and right,
in order to get close to the waypoint
before starting the delivery.
The delivery cutscene must be loaded from disk.
Here, we were able to start the delivery
with the floppy drive still hot
from entering the room.
07:27 Bowl, Ladder, and Pipe
After collecting and delivering the Watering Can,
the route has us collect the Bowl in room 29
and move it to Old King Cole's castle (room 37).
We cannot actually deliver the Bowl yet, because Old King Cole
will demand his Pipe first.
What we can do is take the Bowl to the castle now
and swap it with the Ladder there.
The Ladder needs to go to Humpty Dumpty,
who is two rooms away in room 5.
Exiting room 5 to the south causes diagonal movement to room 11,
where the Pipe is.
We take the Pipe to the castle and deliver it to Old King Cole,
then immediately deliver the Bowl that we stashed there earlier.
The king now asks for his Fiddlers Three,
which will be our last delivery.
11:36 Clock house shortcut
After visiting the castle, we begin
a circuit through the houses in town.
The first stop is room 19,
Jack Horner's side yard,
where we collect the Mouse.
We take the Mouse across the street
and deliver it at the clock house, room 41.
In the clock house we collect the Steak,
whose destination is room 36, to the north.
Because there is a hedge dividing room 17 horizontally,
if we were to obey the intended map connectivity,
we would have to go east to the main road (room 25),
then northwest to room 17, then north to rooms 10 and 36.
Instead, we use a connectivity glitch to shortcut directly to
the other side of the hedge in room 17.
It is intended that the player be able to walk around the back of the house
to arrive at the side yard, inside the hedge in room 17.
The logic of room 24
defines a special connectivity zone that juts down from the horizon,
behind the house,
to make this transition easier.
The logic in room 17 decides where to place the player
based on their x-coordinate:
if the player is sufficiently far to the left,
it assumes the player must have come from outside
the town wall;
otherwise it places the player inside the yard.
But the logic in room 17 is slightly out of sync
with the dimensions of the special connectivity zone in room 24.
There is a 1-pixel-wide strip inside the wall in room 24
that is far enough to the left to be considered outside the wall in room 17.
This shortcut not only avoids having to enter room 25,
it also puts the player closer to the gate in room 17.
17:36 Miss Muffet dodge
The next few deliveries are straightforward.
We deliver the Steak to the Sprats
and the Pie to Jack Horner,
then make a round trip to the Crooked Man's house
to deliver the Sixpence and bring back the Horse.
Then we go to room 22 to collect the Pail.
In taking the Pail north,
we benefit from having already delivered the Sixpence.
If we had not,
a short cutscene would play as we passed by
the Crooked Man outside his house.
In room 8 we narrowly avoid getting too close
to Miss Muffet, which would trigger an undesired item swap
and a cutscene.
The dodge is just barely possible.
The zigzag movement
to avoid Miss Muffet and the tree
does not lose any time,
because in this room and the next
we are bottlenecked on vertical movement,
not horizontal.
19:08 Knife delivery
After delivering the Pail to Jack and Jill,
we return to Miss Muffet
and take her to her tuffet, one room away.
The next step in the route is to get the Knife
from room 2 and take it to Tommy Tucker in room 3.
Although the rooms are adjacent,
there is a wall between them.
It looks like a long walk around the wall and into town,
and it is,
but we speed it up by batching four consecutive floppy drive accesses
and taking advantage of some unintuitive room connectivity.
After delivering Miss Muffet in room 9,
we walk north to room 2 to collect the Knife,
then return south to room 9.
While we have to spin up the floppy drive
to cross from room 9 to room 2,
the Knife is close enough to the bottom of room 2
that we can dip in and out while the drive is still hot.
If we were to follow the game map graphic,
from room 9 we would next
walk one room south to room 16,
then one room east to room 17.
That would require traversing the whole of room 9 vertically,
which is not only slow in itself (about 4 seconds),
but would let the floppy drive spin down.
Instead, we go east to room 10,
where there is a little triangle of walkable area
outside the wall.
The connectivity from this little region of the map is not intuitive.
If the player's y-coordinate is higher on the screen than row 113,
touching the left edge of the screen takes you west, as you might expect.
But if you are lower than that threshold,
touching the left edge of the screen takes you south, to room 17:
if (ego_edge_code == 4) { // left edge of screen
get.posn(O_EGO, v212, v213);
if (v213 > 112) {
new.room(17);
} else {
new.room(9);
}
}
Besides batching floppy drive accesses,
this technique saves vertical movement.
The player is hardcoded to enter room 10
at y-coordinate 105.
Going south from room 10 therefore only requires
walking down 8 pixels,
rather than all the way to the bottom edge
as would be required in room 9.
When we finally deliver the Knife to Tommy Tucker
in room 3,
see how we walk to the left side before entering
the delivery area.
This is for the same reason that we delayed delivering the Candlestick to Jack:
the delivery cutscene
automatically moves the player to a waypoint
towards the left,
and the player moves at half speed during cutscenes.
23:29 Pumpkin house shortcut
The last four items are in the northeast part of the map.
Mary's lost Little Lamb is one room south of where it needs to be;
and then inside the schoolhouse is the Fiddle
that needs to be delivered to the cat in room 7.
In taking Peter Pumpkin Eater's Wife
back to her house,
we take advantage of a connectivity glitch
similar to the one we used at the clock house.
The intended way of entering the yard of room 12
is to walk through the front gate from room 19.
But in another instance of room logic not
exactly agreeing with the walkable area of rooms,
we can "jump the wall" from the right side of room 19.
We walk south from room 12 to room 19
along the east wall,
then immediately return to room 12 by walking north,
far enough to the left that the logic of room 12 places the player inside the yard.
The shortcut is not symmetric:
there is no reciprocal direct connection from inside the yard
in room 12
to outside the wall in room 19.
25:17 Final delivery
We return to the northeast portion of the map to collect the Fiddlers Three,
again hugging the wall
for faster vertical movement.
After the delivery cutscene plays,
we have to press a key to dismiss the text.
After that, the ending cutscene plays out by itself.
Frame counts by category
Like Ocarina of Time,
the speedrun of this game consists more of cutscenes
than gameplay.
Category | Frames | Minutes | Percentage |
---|
Boot and DOS prompt | 175 | 0:02 | 0.1% |
Menuing | 87 | 0:01 | 0.0% |
Gameplay | 42558 | 7:06 | 27.4% |
Cutscenes | 65479 | 10:55 | 42.2% |
Floppy drive motor delay | 10230 | 1:42 | 6.6% |
Floppy drive data access | 18109 | 3:01 | 11.7% |
Room loading | 18086 | 3:01 | 11.7% |
Doors opening/closing | 458 | 0:05 | 0.3% |
Utilities
git clone https://www.bamsoftware.com/git/mumg.git
The tools and notes I made
in the course of creating this TAS
are available in the Git repository above.
They include:
- A reimplementation of the game's random assignment algorithm
- Extracted picture and priority graphics
- Decompiled and lightly annotated logic resources
- The simulated annealing–based route optimizer
- A watch file with useful RAM addresses
Thanks
- agikit by Nat Budin, which was indispensable for its ability to decompile AGI logic resources.
- AGI Programmers' Wiki, with references for logic commands and file formats.
- ScummVM, from which I ripped the AGI picture resource renderer to make the game map and visualize obstacles in rooms. I tried some other renderers but ScummVM's was the only one accurate enough to draw all the rooms correctly.
- agi-upscale and its associated video, which is what got me interested in AGI.
slamo: Replaced movie file to fix the platform, and judging!
slamo: Tremendously well-researched and planned as always. Great work.
This run uses a configuration besides our three pre-made setups, which we allow as long as there are instructions on how to reproduce it. In this case, the Tandy is very easy to set up, having DOS built into the ROM, so only a .cfg file is required. The justification for this config is that the built-in sound is much better, which I think is a perfectly valid reason to use it. We were also able to sync the run, so all the information here is adequate.
The only other thing to talk about is the game speed. There are faster runs out there, but they 1) use DOSBox, which is not exactly the paragon of accuracy, and 2) rely on a high cycle count and the Fastest speed setting, which is only limited by the CPU speed, and we explicitly disallow using unintended environments to make the gameplay faster. Fastest speed actually would have been fine in this case, since you're playing the game on intended hardware, but I'm not going to sweat the game speed too much, especially if you have ambitions to console-verify this. As long as the gameplay is optimized (which it is), then we're copacetic.
Accepting!