Here I will discuss the parts of a-life code other than the 82 behaviors outlined in List of a-life actions. While actions explain what an a-life is doing at the current moment, it's the rest of the code that dictates how long it will perform that action and what it will do next, as well as evaluating more low-level information like updating the a-life's position and counting down its lifespan value. For each function I'll list its location in the final and E3 version, an overview of that function's purpose, and any differences between the two versions. I'm using Bo Bayles' names for these functions.
Location:
Final: 0x06035A74
E3: 0x06038A24
Description (Final):
This function iterates through the linked list of a-life, performing different operations on each depending on the value of a 16-bit timer stored in memory at 0x060D3192.
The timer counts up from 0, being incremented each time this function is called.
If the timer >= 6000, each a-life's lifespan is decremented unless it is an egg or a decorative background pian, then the timer is reset to 0.
If the timer is < 6000, the function nightopian_ref_02 is called on each a-life that is not currently loaded on-screen.
If the timer is a multiple of 8, each off-screen a-life is checked to see if it has moved within a certain range of the player. If true, a new object instance is generated to load the a-life on-screen. nightopian_ref_04 is assigned as that object's handler. However, currently on-screen a-life are not checked to see if they have moved out of range and should be unloaded. That is handled by nightopian_ref_11, which is eventually called from nightopian_ref_04.
Regardless of the timer's value, this function also calls nightopian_ref_08 on each a-life if the value at 0x060FFC6E is 1. This happens about half of the time, since another function constantly toggles 0x060FFC6E between 0 and 1.
E3 Differences:
The only difference from the final is that the timer is reset once it reaches 3600, rather than 6000. This means a-life's lifespan decreases at a faster rate in E3.
Location:
Final: 0x06035B5C
E3: 0x06038B0C
Description (Final):
Serves as the starting point for several routines that need to be called on off-screen a-life. This function only proceeds if the a-life meets certain criteria. Specifically, it must not be an egg or decorative pian, and not a badpian or king pian. If this condition is met, nightopian_ref_03 is called next. Then, the value of the a-life's current action (at byte 0x40) is transferred to its previous action (0x41), and the following are called in order:
nightopian_ref_14
nightopian_ref_15
nightopian_ref_24
Finally, two more functions are called to move the a-life along NiGHTS' flight paths according to its current direction and speed.
E3 Differences:
The only difference in the E3 version is the initial condition, which is less strict and only requires that the a-life is not decorative.
Location:
Final: 0x06035BA0
E3: 0x06038B48
Description (Final):
Handles main behavior logic for off-screen a-life.
First, if the a-life's "ignoring" bit is set, it continues its previous behavior.
Otherwise, the code checks a variety of conditions to determine what behavior each a-life should perform next. This logic differs depending on whether the a-life is a nightopian or a mepian (king pians and badpians cannot reach this point in the code).
For nightopians:
If the nightopian is touching another entity:
If the other entity is a nightmaren or a badpian, the nightopian dies (behavior 0x15), unless it was a nightmaren that was thrown by the player, in which case it creates an egg with the nightmaren before dying immediately (0x16).
If the other entity is a mepian and the mepian is ready to breed (the nightopian's value is not checked), it creates an egg with the mepian (0x16). Otherwise, normal behavior starts (0x0).
If the other entity is a nightopian and both nightopians are ready to breed, they create an egg (0x20). Otherwise, normal behavior starts (0x0).
If the other entity is a king pian, resume normal behavior (0x0).
Else if the nightopian is near another entity:
If the other entity is a mepian, badpian, or nightmaren, the nightopian flees (0x1A).
If the other entity is a nightopian, and both are ready to breed, they start the mating dance (0x21). Otherwise, they resume normal behavior (0x0).
If the other entity is a king pian, resume normal behavior (0x0).
Else (nightopian is not touching or near another entity)
Resume normal behavior (0x0)
For mepians:
If the mepian is touching another entity:
If the other entity is a nightmaren or a badpian, if the mepian is ready to breed, it will create an egg with the nightmaren/badpian (behavior 0x44) and survive (unless it had less than 10 lifespan left). If it was not ready to breed, normal behavior starts (0x0).
If the other entity is a mepian and boths mepians are ready to breed, they create an egg (0x20). Otherwise, they resume normal behavior (0x0).
If the other entity is a nightopian and the mepian is ready to breed, they create an egg (0x44). Otherwise, normal behavior starts (0x0).
If the other entity is a king pian, resume normal behavior (0x0).
Else if the mepian is near another entity:
If the other entity is a nightopian, badpian, or nightmaren, and the mepian is ready to breed, it starts its mating dance (0x1C). Otherwise, normal behavior starts (0x0).
If the other entity is a mepian, and both are ready to breed, they start the mating dance (0x21). Otherwise, they resume normal behavior (0x0).
If the other entity is a king pian, resume normal behavior (0x0).
Else (mepian is not touching or near another entity)
Resume normal behavior (0x0)
E3 Differences:
This version contains several differences from the final.
Badpians and king pians can reach this part of the code, and they are treated as mepians and nightopians, respectively.
When a mepian/badpian and nightopian touch, the logic for whether an egg should appear is contradictory on the mepian's and nightopian's side. For nightopians touching mepians, they create an egg unconditionally. However, for mepians touching nightopians, the logic states that both need to be ready to breed for an egg to appear. This causes inconsistent results in whether they manage to breed depending on the two a-lifes' positions, since the code that creates the egg is only called on the partner facing left.
For mepians/badpians touching nightmarens/badpians, there are different conditions on whether they will manage to reproduce or get eaten. They will be able to breed normally if the nightmaren has been thrown by the player or is not hungry. The mepian does not have to be ready to breed for the egg to appear, unlike the final version. If the nightmaren was hungry, the mepian dies. With badpians involved, this logic becomes more muddled, since badpians have lifespan instead of hunger and cannot regain it, meaning if the badpian has lifespan < max the approaching mepian/badpian will always be eaten.
Mepians/badpians will start their mating dance towards nightopians, nightmarens, or badpians regardless of whether either of them are ready to breed. This allows them to produce eggs with nightmarens or badpians in quick succession, skipping the usual wait time to be ready to breed again.
Unreachable Code:
In both the final and E3 version, some unreachable lines of code exist that seem to be leftovers from an earlier build, nightopian_ref_13 which is similar, or both.
These include code to start behaviors 0x22 and 0x23, which are used in nightopian_ref_13 to handle the case when two nightopians or two mepians are near each other or touching and are not ready to breed.
The final version contains logic that specifically allows mepians to create an egg with thrown nightmarens without dying, which is a leftover from the E3 version (the final code allows them to survive whether the nightmaren was thrown or not).
Location:
Final: 0x060360A4
E3: 0x06038F9C
Description (Final):
Serves as the starting point for several routines that need to be called on on-screen a-life. It is only called at the first moment when an a-life comes on-screen, since it replaces itself with a different handler in the a-life's object data afterwards.
First, a pointer to the current stage's table of a-life animation frames is stored in the long at offset 0x2C in the a-life's object reference. Then, nightopian_ref_24 is called to transfer position and velocity data from the a-life's data to the object reference. Then, nightopian_ref_5 is called.
What happens next depends on the a-life's type, as follows:
If the a-life is an egg:
The egg's current behavior is set to 0x18, its X speed is set to 0, and the a-life's object handler is replaced with nightopian_ref_06.
Else, if the a-life is a background decoration:
Its object handler is replaced with nightopian_ref_10.
Else, if the a-life is a king pian:
If the king pian's flight modifier (last 2 bits of byte 0xF, gets incremented on every playthrough) is 2 or above, the highest bit on that king pian's byte 0x74 is set. This indicates that it is ready to work on the castle. If a castle does not already exist in the level (byte at 0x060CFFA0 is negative), one is created, with a position chosen randomly from a few (2-5) candidates that differ depending on each stage.
If the castle was created, the king pian teleports to its location. If not, it teleports to the first of the candidate locations. Finally, its object handler is replaced with nightopian_ref_09.
Else:
The a-life's object handler is replaced with nightopian_ref_11. If the a-life is a nightopian, and the player has already paralooped 3 or more nightopians in the same playthrough, that nightopian's mood is set to 0.
E3 Differences:
It uses a negligibly different version of nightopian_ref_24 to transfer coordinates from the a-life data to the object reference.
The a-life's object handler is replaced without performing any additional operations.
Location:
Final: 0x0603725C
E3: 0x0603A030
Description (Final):
This function gets the a-life's torso type (at byte 0x60 in its data) and uses that number to retrieve an address which points to a positioning scheme for the a-life's limbs. Since different mepian torso parts have different shapes, this allows arms and legs to be attached in different places as required. The pointer to the positioning scheme is stored at offset 0x7C in the a-life's data.
E3 Differences:
No differences.
Location:
Final: 0x06036140
E3: 0x06039028
Description (Final):
Object handler for a-life eggs.
First, if the egg is a certain distance away from the player, its object reference is deallocated.
Otherwise, if the egg has the "adult ai" bit set as well as the egg bit, the handler replaces itself with nightopian _ref_09 if a king pian, and nightopian_ref_11 otherwise. It then starts behavior 0x19 to hatch the egg. If the bit is not set, the egg starts behavior 0x18 to remain unhatched, and if NiGHTS is currently on the same lap segment as the egg, some attributes are set on the egg object which will allow NiGHTS to touch dash the egg without being flung backwards as with other touch dashable objects.
Either way, nightopian_ref_15, nightopian_ref_24 and another function are called to snap the a-life to one of NiGHTS' flight paths. Next, some logic chooses the a-life's next animation frame and renders it on-screen.
E3 Differences:
The only difference is the code doesn't check that NiGHTS is on the same lap segment before assigning attributes to the egg object, and it doesn't set the bit flag that prevents NiGHTS from bouncing off the egg when touch dashing it.
Location:
Final: 0x06035CB8
E3: 0x06038C40
Description (Final):
Evaluates which a-life are nearby or touching.
The main logic of this function takes the form of a nested while loop which iterates through the linked list of a-life.
a = alifeList.begin()
while (a.hasNext()) {
b = a.next()
while (b != null) {
// evaluate distance between a-life A and B
b = b.next();
}
a = a.next();
}
In plain english, this function goes through every pair of unique a-life to check how close together they are. I'll designate the first a-life in the pair as A and the second one as B.
I'll use the following programming terms to explain:
Continue : Skip the rest of the code in the current loop and start the current loop again from the beginning, using the next a-life A (in the outer loop) or a-life B (inner loop).
Break : Exit the current loop (inner or outer).
Exit : Exit both loops. the code is finished executing.
The following conditions are evaluated for each a-life A (outer loop):
If a-life A is null, exit. If a-life A is not null and has the "should be ignored" bit set on its data, continue.
The following are evaluated for each a-life B (inner loop):
If a-life B is null, break.
If a-life B has the "should be ignored" bit set, or is on a different lap segment than a-life A, continue.
If the X or Y distance between the two a-life is > 16, evaluate if the first a-life can see the second (note that the second a-life's vision is not checked).
If the second a-life's X position is within the first a-life's vision distance, then set the "near" bit on both a-life's data, and record the type (nightopian, king pian, mepian, or badpian/nightmaren) and pointer of each a-life on the opposite a-life's data. Also record which of the two is on the left and right.
If the X distance is < 8, and Y distance is < 16:
Regardless of either a-life's vision, set the "touching" bit on both a-life's data, and record the type (nightopian, king pian, mepian, or badpian/nightmaren) and pointer of each a-life on the opposite a-life's data. Also record which of the two is on the left and right and move the second a-life backwards by 1 in the X direction.
If the X and Y distance does not meet the above criteria, continue.
Once the above have been evaluated for every a-life B, A = A.next().
Once the above have been evaluated for every a-life A, exit.
The fact that only one a-life's vision distance (the one that's closer to the beginning of the list) is used to check for nearness causes some unexpected behavior.
Example a-life list:
a-life 1 -> a-life 2-> a-life 3 -> a-life 4 -> a-life 5
Say in the above list that a-life 5 is a nightopian with maximum vision, and a-life 1 is a nightmaren with minimum vision -- effectively blind. You would expect that when the nightopian comes near the nightmaren, it will see it and start to run away. However, they actually pass by each other without interacting, because the nightmaren, with its 0 vision value, was first in the a-life list and only its vision value is checked.
E3 Differences:
The only difference is that the E3 version is missing a few instructions that account for the case where the distance between a-life B and A is negative (due to B being to the left of A) and instead always checks that the distance is less than a positive version of a-life A's vision distance. This causes a-life to notice another a-life to the left of them at the maximum possible distance (16) about half of the time, depending on whether the a-life to the right comes first in the a-life list.
Location:
Final: 0x06036140
E3: 0x06039608
Description (Final):
Object handler for king pians.
First, if the king pian is a certain distance away from the player, its object reference is deallocated, unless the king pian's lifespan reached 0, in which case its a-life data is deallocated, and the number of king pians in the stage is decremented.
Otherwise, if the king pian has the "adult ai" bit set as well as the egg bit, it starts behavior 0x19 to hatch the egg. If the king pian was paralooped, its behavior is set to 6 and the nightopian scream sound is played. If it was near another a-life while being paralooped, the 0x10 bit on the near a-life's byte 0x42 is unset. The meaning of this is unclear as the bit does not appear to be used anywhere, though other bits in the value are known to be used as the a-life's mood.
If the highest bit of the king pian's byte 0x74 is set, this function calls nightopian_ref_22. Otherwise, it calls nightopian_ref_23. In either case, nightopian_ref_14 is called next.
Afterwards, nightopian_ref_15, nightopian_ref_24 and another function are called to snap the a-life to one of NiGHTS' flight paths. Finally, some logic chooses the a-life's next animation frame and renders it on-screen.
E3 Differences:
The E3 version of this function has 2 major differences from the final.
The logic for the king pian being paralooped is missing. It actually cannot be paralooped at all.
At this point, ref_23 hasn't been implemented so ref_22 is called regardless of the value of byte 0x74 on the king pian's data.
Location:
Final: 0x0603625C
E3: 0x06039134
Description (Final):
Object handler for decorative a-life.
If the decorative a-life is a certain distance away from the player, its object reference is deallocated.
Otherwise, the decorative a-life's animation is chosen based on its behavior and rendered to the screen.
E3 Differences:
No differences.
Location:
Final: 0x060362EC
E3: 0x060391C4
Description (Final):
Object handler for normal a-life, including nightopians, mepians, and badpians.
If the a-life is a certain distance away from the player, its object reference is deallocated, unless the a-life's lifespan reached 0, in which case its a-life data is deallocated and the number of its a-life type in the stage is decremented.
Otherwise, if the a-life has the "adult ai" bit set as well as the egg bit, it starts behavior 0x19 to hatch the egg. If the a-life was paralooped, its behavior is set to 6 and the nightopian scream sound is played if a nightopian, or the mepian scream sound if a mepian or badpian. If it was near another a-life while being paralooped, the 0x10 bit on the near a-life's byte 0x42 is unset. The meaning of this is unclear as the bit does not appear to be used anywhere, though other bits in the value are known to be used as the a-life's mood. If the paralooped a-life was a nightopian, the count of paralooped nightopians is incremented in memory.
Next, this function calls nightopian_ref_13 and nightopian_ref_14.
Afterwards, nightopian_ref_15, nightopian_ref_24 and another function are called to snap the a-life to one of NiGHTS' flight paths. The a-life's next animation frame is chosen based on its current behavior, and it may also generate a sprite of a thrown object when switching between behaviors.
E3 Differences:
There are 2 differences from the final.
The count of paralooped nightopians is not updated when paralooping a nightopian.
Instead of unsetting bit 0x10 of byte 0x42, the mood of an a-life near a paralooped a-life is decremented by 1, capped at 0.
Location:
Final: 0x060364E8
E3: 0x06039408
Description (Final):
Handles main behavior logic for on-screen a-life.
First, if NiGHTS is touching or touch dashing the a-life (both of which are impossible), it starts behavior 2 showing a panicked expression. Otherwise, if its lifespan has reached 0, the dying behavior 0x11 starts. Else, if its "ignoring" bit is set, it continues its previous behavior.
Otherwise, the code checks a variety of conditions to determine what behavior each a-life should perform next. This logic differs depending on whether the a-life is a nightopian or a mepian/badpian (king pians cannot reach this part of the code).
For nightopians:
If the nightopian is touching another entity:
If the other entity is a nightmaren or a badpian, the nightopian is eaten (behavior 0x15), unless it was a nightmaren that was thrown by the player, in which case it creates an egg with the nightmaren before dying immediately (0x16). If the nightopian is eaten, the nightopian scream sound is played and its object handler is replaced with nightopian_ref_17. Its object reference is deallocated once the nightopian disappears.
If the other entity is a mepian and the mepian is ready to breed (the nightopian's value is not checked), it creates an egg with the mepian (0x16). Otherwise, the nightopian reacts to the player.
If the other entity is a nightopian and both nightopians are ready to breed, they create an egg (0x20). Otherwise, if only one partner is ready to breed, they start behavior 0x23 which triggers genetic behaviors that are activated by touching another a-life. If neither are ready, they react to the player.
If the other entity is a king pian, react to the player.
Else if the nightopian is near another entity:
If the other entity is a mepian, badpian, or nightmaren, the nightopian flees (0x1A).
If the other entity is a nightopian, and both are ready to breed, they start the mating dance (0x21). Otherwise, if only one is ready, they start behavior 0x22 which triggers genetic behaviors that are activated by moving near another a-life. If both are not ready, they react to the player.
If the other entity is a king pian, react to the player.
Else (nightopian is not touching or near another entity)
React to the player.
For mepians/badpians:
If the mepian is touching another entity:
If the other entity is a nightmaren or a badpian, the mepian is eaten (behavior 0x15), unless it was a nightmaren that was thrown by the player, in which case it creates an egg with the nightmaren before losing 50 lifespan (0x16) almost always enough to kill. If the mepian is eaten, the mepian scream sound is played and its object handler is replaced with nightopian_ref_17. Its object reference is deallocated once the mepian disappears.
If the other entity is a mepian and both mepians are ready to breed, they create an egg (0x20). Otherwise, if only one partner is ready to breed, they start behavior 0x23 . If neither are ready, they react to the player.
If the other entity is a nightopian and the mepian is ready to breed, they create an egg (0x44). Otherwise, the mepian reacts to the player.
If the other entity is a king pian, react to the player.
Else if the mepian is near another entity:
If the other entity is a nightopian, badpian, or nightmaren, and the mepian is ready to breed, it starts its mating dance (0x1C). Otherwise, it reacts to the player.
If the other entity is a mepian, and both are ready to breed, they start the mating dance (0x21). Otherwise, if only one is ready, they start behavior 0x22. If both are not ready, they react to the player.
If the other entity is a king pian, react to the player.
Else (mepian is not touching or near another entity)
React to the player.
Reacting to the player
This important piece of logic is used in several places in the function. It tests whether the player is within vision distance of the a-life. If true, the a-life's next behavior is chosen as follows:
If the a-life's opinion is positive (3): Start behavior 4.
If the a-life's opinion is neutral (2): Start behavior 0.
If the a-life's opinion is negative (0 or 1): Start behavior 0xF.
E3 Differences:
This version contains several differences from the final.
NiGHTS touching or touch dashing an a-life has an additional effect of adding 450 points to the player's score. The code that does this is an early version of the star chip bonus pian's code. In the final version, the star chip pian appears above the Ideya Palace on the 3rd mare and can be touched on the 4th mare, which adds scare calculated as 10 time the number of star chips the player has collected up to that point. In the E3 version, the code instead works similarly to the link score, where the first chip gives 10 points, the second gives 20, and so on until the 10th chip where every subsequent chip only gives 100 points. However the code contains a flaw which causes it to grant a fixed number of points instead of counting the number of star chips properly.
As with nightopian_ref_03, the code is contradictory on whether an egg should be created when a nightopian and mepian touch. For nightopians touching mepians, they create an egg unconditionally. However, for mepians touching nightopians, the logic states that both need to be ready to breed for an egg to appear. This causes inconsistent results in whether they manage to breed depending on the two a-lifes' positions, since the code that creates the egg is only called on the partner facing left.
When a mepian/badpian touches a nightmaren/badpian, some code checks that the nightmaren's hunger value / badpian's lifespan value is full. It true, the mepian will survive touching the nightmaren/badpian and will create an egg regardless of whether either were ready to breed.
A mepian/badpian will always start its mating dance when near a nightmaren/badpian, regardless of whether either are ready to breed. This means mepians can breed with nightmarens or badpians in quick succession, skipping the usual wait time before creating an egg.
A mepian/badpian will only start its mating dance toward a nightopian if both are ready to breed. If only one is ready, it will start behavior 0x22. In the final version, behavior 0x22 can only be activated between two mepians or two nightopians.
Near the end of the function is some extra code that sets a bit on a-life that prevents NiGHTS from touch dashing them. This activates whenever the player's star chip count is > 0. Other parts of the code prevent NiGHTS from touch dashing a-life while not having star chips, which makes touch dashing adult a-life impossible. In the final game this code is absent (touch dashing is still impossible).
Location:
Final: 0x06035DFC
E3: 0x06038D80
Description (Final):
If a timer stored at word 0x12 of an a-life's data is positive, it is decremented. If that value equals 0, 0x40 is added to that a-life's Y speed until it's >= 0x100, causing it to descend. If the timer's value is negative, nothing happens.
E3 Differences:
No differences.
Location:
Final: 0x06035E28
E3: 0x06038DAC
Description (Final):
If the a-life is not decorative, this function increments a timer stored at long 0x78 in the a-life's data. This value is used to determine whether that a-life is ready to breed.
Next, if the a-life is loaded on-screen or is not loaded and the timer is a multiple of 8, the following occurs:
nightopian_ref_16 is called and the a-life's position is updated according to its current velocity. Next, if the a-life is touching the ground, the "touching ground" bit is set on byte 0xE of its data. The timer on word 0x12, which is also used in nightopian_ref_14, is reset to a value that differs based on the first 2 bits of its "flight modifier" gene:
0: 0x258 (600, 1 minute)
1: 0x4B0 (1200, 2 minutes)
2: 0x708 (1800, 3 minutes)
3: 0xFFFF (-1 -- this means the a-life will never descend to the ground while flying, though it might for another action)
If the a-life is not touching the ground, the "touching ground" bit on its data is unset.
E3 Differences:
Decorative a-life are treated the same as normal a-life in this version.
Location:
Final: 0x06035EBC
E3: 0x06038E38
Description (Final):
This function mainly serves to keep a-life out of certain areas of the stage. It is called on both on-screen and off-screen a-life.
It retrieves a list of barrier locations based on the current stage. These always include the Ideya Palace's location and for certain stages also includes unusual areas like the museum in Soft Museum or the water cave in Splash Garden. For each one, it checks if the a-life's X and Z position are within a threshold of 90 distance (which is about half the width of the Ideya Palace). If so, the a-life's virtual X direction reverses, and the following occurs.
If the a-life's byte 0x12 was == 0, then the value at 0x14 is set to 0x258 (600). I'm not sure what the effect of this is.
Else, if the value at 0x14 was < 0xF0 (240), then the a-life bounces up slightly in the Y direction.
Either way, the word at 0x16 in the a-life's data is set to -1, causing it to show the turning around animation.
E3 Differences:
The final uses a simple calculation to figure out how far to move the a-life away from the barrier so it doesn't trigger the collision a second time. The E3 version has a mistake in this calculation. Specifically, when the distance between the a-life and the barrier is positive (a-life is to the left of the barrier), it calculates the difference between the a-life's distance and the barrier's width with the wrong sign. This ultimately causes it to zip through the barrier and end up on the other side.
The two checks on the values at 0x12 and 0x14 in the a-life's data do not occur.
Location:
Final: 0x0603689C
E3: 0x060397D8
Description (Final):
This object handler is used for a-life that have been paralooped or eaten. Basically, if the paralooped or eaten a-life goes far enough off-screen to unload, or if the first 4 bytes of its a-life data == -1, its object reference is deallocated. Otherwise, its behavior is set to 15 and its current animation frame is rendered on screen.
E3 Differences:
No differences.
Location:
Final: 0x06036CF6
E3: 0x06039C0C
Description (Final):
This code handles drawing the a-life sprites on screen.
E3 Differences:
Location:
Final: 0x0603686C
E3: 0x06039720
Description (Final):
This handles the behavior of a king pian once it has started to build the castle. First, if it has the 0x40 bit set on byte 0xE, it will continue its previous behavior. If the king pian is touching a nightmaren or a badpian, but not a mepian, it will start behavior 0x50 to start throwing rocks (king pians cannot be eaten). If it is touching any other type of a-life, it will start behavior 0x41, signaling to the other a-life to help build the castle. This interaction is not fully implemented in the game and the nearby a-life will not react to the king pian's action.
If the king pian is near a nightmaren, badpian, or mepian, it will start throwing rocks. If it is near a nightopian or king pian, it will signal for it to help build the castle. Once again, this interaction is unfinished. If the king pian is not near anything, it will start behavior 0x42, flying up and down near the castle's location.
E3 Differences:
In the E3 version this function is much more complex, and activates regardless of whether the king pian is ready to build the castle.
It includes code to handle NiGHTS touching or touch dashing a king pian, which activates the same behavior (0x2) as touching a normal pian would, but does not activate the star chip bonus code. It also sets a "touch event" on the king pian as long as it is not already being touched and is still alive. This differs from the code for normal a-life in ref_13 which only sets the touch event if the player has at least one star chip. In both cases though, a bit is set on the touch event which prevents NiGHTS from actually touching them.
If the king pian's lifespan has reached 0, it will start behavior 0x11, showing the same dying animation as a normal pian (including the normal pian's head sprite). This doesn't happen in the final, where the king pian will continue as normal until it goes off screen, at which point it will be deleted.
As in the final version, the king pian will start throwing rocks if near a nightmaren, badpian, or mepian or touching a nightmaren or badpian. If the king pian is touching or near another king, it will always start behavior 0x42. If the king pian is near a nightopian, or touching a nightopian or mepian, it can start behavior 0x41, but strangely this will only happen if one of the two is ready to breed. If both or neither are, the king pian will start behavior 0x42.
Location:
Final: 0x06036818
E3: N/A
Description (Final):
This handles the behavior of a king pian before it has started to build the castle. First, if it has the 0x40 bit set on byte 0xE, it will continue its previous behavior. If the king pian is touching a nightmaren or a badpian, but not a mepian, it will start behavior 0x50 to start throwing rocks (king pians cannot be eaten). If it is touching any other type of a-life, it will start behavior 0x4F, flying normally.
If the king pian is near a nightmaren, badpian, or mepian, it will start throwing rocks. If it is near a nightopian or king pian, it will fly normally.
E3 Differences:
This function is not implemented in the E3 version.
Location:
Final: 0x06036940
E3: 0x0603987C
Description (Final):
This tests whether one a-life and another one near or touching it are ready to breed. It checks whether the first a-life's "desire to mate" value has reached a threshold of 0x4650 (18000), which takes about 5 minutes. If so, the 0x10 bit is set on its byte 0xE. If both a-life now have this bit set, the funciton returns 2. If only one of them does, it returns 1, and if neither do, it returns 0.
E3 Differences:
The time threshold for a-life to breed is lower, at 0x2A30 (10800) which amounts to 3 minutes.
Location:
Final: 0x0603697C
E3: 0x060398B8
Description (Final):
Generates a new a-life object from two parents. The parents' data is not used 100% equally, so I will refer to one as the first parent and the other as the second parent. Which is which depends on which one was facing left and right when they collided.
First, this function checks if the number of a-life in the level has reached its limit, 42 in the final. If so, the new a-life will not be generated.
Assuming there is enough space for the new a-life, the following occurs:
The new egg's Y velocity is set to a small negative value, causing it to bounce up slightly when generated. The value 0x40 is set in its data at byte 0x1A (the meaning of this is unclear). Position data, including X, Y, Z, virtual X, and lap segment, are transferred from the first parent to the offspring. Behavior 0x18 is set as both the current and previous behavior of the new a-life.
Next, the rng is rolled, and the function recombine_gene determines whether the new a-life inherits its torso part from the first or second parent. It also inherits its lifespan value from the same parent.
Rng is rolled again, and the a-life inherits its head part using the same method, along with the vision gene from the same parent.
Rng is rolled and the a-life inherits its arm part and flight stamina from one of its parents.
Rng is rolled one last time and the a-life inherits its leg part along with speed from one parent.
Next, the a-life's mood is inherited from the first parent, this won't matter though because hatching an egg automatically sets its mood to 3.
The new a-life inherits its first flight pattern from its first parent, and the second flight pattern from its second parent.
The new a-life randomly inherits one of the two genetic behaviors from its first parent, and one of the two behaviors from its second parent. If both are the same, one or the other is randomly incremented by 5.
The egg bit is set on the new a-life's data and its byte 0xE is set to 0xC0, causing it to repeat its current behavior and to be ignored by other a-life.
The flight modifier values of both parents are added together. If the sum is 5 or more, the new a-life's flight modifier is set to 1, otherwise it is 0.
Next, the new a-life's type is determined. If both parents were mepians, and the offspring has no nightmaren parts, its type is set to 0 for king pian. Otherwise, if the offspring has no nightmaren parts its type is set to 1 for normal pian. If the offspring inherited at least 1, but less than 4 nightmaren parts, its type is set to 3 for normal mepian, and its "desire to mate" value is set to 0x12C0 (4800 or 80 seconds), giving it a head start on being able to reproduce once it hatches. If the offspring has 4 nightmaren parts, its type becomes 2 for badpian.
Finally, the count of the new a-life's type is incremented in memory.
E3 Differences:
The max number of a-life is 63 instead of 42.
Mepians' desire to mate value is set to 0xE10 (3600 or 60 seconds).