Mindful Webworks / The Second Life of Radd Dadd Upshaw / Chick 'n' Egg

Chick'n'Egg v006.002.040 Script Dissected
The script for a Second Life-form by RaddDadd Upshaw
[Full copy of code here]
Updated 2008-Jun-28

Object & Inventory

Chick'n'Egg is an eight-prim object. The eight prims represent (in sequence from root) the root-wheel, the body-egg, the tail, the neck, the head, two eyes, and the beak. The object's inventory contains:

  1. The latest Chick'n'Egg script, running
  2. The eight-prim chicken-as-egg which
    1. has in its inventory the latest Chick'n'Egg script, running, and
    2. at rez is given a copy of itself.

Lists

Prim_Positions

PRIM POSITIONS AT EACH STAGE OF GROWTH
Child positions are relative to root. Root positions are not used. (Might try to eliminate this set of vectors later.)

Egg Chick Hen Rest
Root < 0.000, 0.000, 0.000 > < 0.000, 0.000, 0.000 > < 0.000, 0.000, 0.000 > < 0.000, 0.000, 0.000 >
Body < 0.000, 0.000, 0.020 > < 0.000, 0.000, 0.049 > < 0.000, 0.000, 0.243 > < 0.000, 0.000, 0.056 >
Tail < 0.000, -0.010, 0.020 > < 0.000, -0.056, 0.089 > < 0.000, -0.280, 0.444 > < 0.000, -0.339, 0.075 >
Neck < 0.000, -0.015, 0.031 > < 0.000, 0.040, 0.082 > < 0.000, 0.200, 0.408 > < 0.000, 0.143, 0.150 >
Head < 0.000, 0.003, 0.041 > < 0.000, 0.057, 0.092 > < 0.000, 0.287, 0.460 > < 0.000, 0.256, 0.154 >
R Eye < 0.018, 0.014, 0.044 > < 0.018, 0.068, 0.095 > < 0.035, 0.338, 0.475 > < 0.036, 0.292, 0.145 >
L Eye <-0.019, 0.009, 0.046 > <-0.019, 0.064, 0.097 > <-0.029, 0.318, 0.484 > <-0.032, 0.284, 0.159 >
Beak < 0.000, 0.028, 0.026 > < 0.000, 0.083, 0.077 > < 0.000, 0.413, 0.384 > < 0.000, 0.320, 0.024 >

Prim_Sizes

PRIM SIZES AT CHICK & HEN STAGES

Chick Hen
Root < 0.010, 0.060, 0.060 > < 0.050, 0.300, 0.300 >
Body < 0.100, 0.100, 0.100 > < 0.300, 0.500, 0.400 >
Tail < 0.010, 0.060, 0.060 > < 0.010, 0.300, 0.300 >
Neck < 0.020, 0.020, 0.028 > < 0.050, 0.050, 0.141 >
Head < 0.050, 0.050, 0.050 > < 0.154, 0.100, 0.227 >
R Eye < 0.020, 0.020, 0.020 > < 0.050, 0.050, 0.050 >
L Eye < 0.020, 0.020, 0.020 > < 0.050, 0.050, 0.050 >
Beak < 0.040, 0.040, 0.040 > < 0.100, 0.050, 0.200 >

Prim_Rots

PRIM ROATATIONS (in degrees) AT STANDING & REST STAGES

Standing Rest
Root < 0.00, 0.00, 0.00 > < 0.00, 0.00, 0.00 >
Body < 0.00, 0.00, 0.00 > < 0.00, 0.00, 0.00 >
Tail < 33.55, 0.00, 90.00 > < 112.50, 0.00, 90.00 >
Neck < 310.00, 0.00, 90.00 > < 280.00, 0.00, 90.00 >
Head < 257.00, 0.00, 90.00 > < 228.00, 0.00, 90.00 >
R Eye < 0.00, 0.00, 0.00 > < 0.00, 0.00, 0.00 >
L Eye < 0.00, 0.00, 0.00 > < 0.00, 0.00, 0.00 >
Beak < 242.65, 0.00, 90.00 > < 217.00, 0.00, 90.00 >

Stage_Age & Stage_Name

Stage_Age = DURATION OF EACH GROWTH STAGE
Works best if stages when morphing are exact multiple of total prims times heartbeat.
Durations listed here are HIGHLY subject to change.
Stage_Name = NAME OF EACH GROWTH STAGE
"Peck" includes wander, peck-unpeck, and pivot. "Re-Pos" is repositioning of prims relative to one another. Resizing occurs only in the maturing stage. Recoloring occurs during the maturing and fading stages.

Age_Stage Stage_Age Stage_Name State Peck Re-Pos
0 32.0 embryonic EggTimer No No
1 64.0 hatching Birdbrain Yes Yes
2 32.0 young Yes No
3 64.0 maturing Yes Yes
4 64.0 adult Yes No
5 32.0 settling No Yes
6 32.0 laying Laying No No
7 32.0 rising Birdbrain Yes Yes
8 128.0 old Yes No
9 32.0 expiring No Yes
10 64.0 fading FadeOut No No
NB: to avoid Malthusian problems, the parent hen's time from laying to expiration should be same or less than the pre-laying time (here, both equal 288s).

Patterns

Texture UIDs.

Index Patterns Design
0 b1b96368-ce26-8eda-aac6-5efad53aa51b Floor Tile 3 (beige)
1 b00fd16f-1b5a-8667-bf61-90d960b8112a Denim
2 0444bf21-f77e-7f63-89e9-b839ec66bc15 Blue Plasma
3 61255acc-b70a-51b5-a2eb-3eb96e327dd1 Burlap
4 c6c1ee60-72b5-4cf9-a75f-aaad4192ddf9 Light Moss
5 2d56afdf-9541-70b1-0342-820cd826d635 Leopard
6 c7f1beb3-4c5f-f70e-6d96-7668ff8aea0a Granite
7 18cfbfd6-ad39-11d5-9d21-00d0b7c730a8 American Flag
8 a9a32bf2-7085-98f2-ab25-ac5c6854bd19 Zebra Skin
9 e98661c3-8c05-30c5-06ad-897e933b4c45 Tie-Dye
10 47ecfbee-2a28-92a8-4359-1c767040657d Pinktoile
11 75c0ae9b-bd5a-12f7-bfce-311271475122 Bricks
12 530c88fe-647c-e127-b716-0c6001479cdf Peeling Paint
13 f39ca3bf-0058-9cd6-2a56-dd198a992fc0 Blue-White Gingham
14 953a7e95-8cdb-c0f7-d251-996564a7dc67 Plaid 1
15 1a661817-070d-5f9c-2f00-4d6f0c3e7573 Plaid 2
16 47204770-1b0a-192f-9d46-48bd8afe0a42 Wallpaper - Black and Green floral
17 b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d Smoke
18 e00b6ea4-7a3b-b6fc-e8b7-107e2be6e301 Plywood
19 8dcd4a48-2d37-4909-9f78-f7a9eb4ef903 Default Transparent

Common Variables

Timing and Stages of Growth

Type Name Use Value Purpose
float Heartbeat const 0.5 Minimum timer in active stages
integer AgeDuration var diff each stage Current stage duration
string AgeName var diff each stage Current stage name
integer AgeStage var -1 to fading Counts through growth stages
float countBeats var counting Counts down stage duration
integer TotalPrims const llGetNumberOfPrims() Number of prims in object
integer countPrims var 0 to TotalPrims-1 Counts through prims

Peck, Pivot, & Wander

Type Name Use Value Peck
integer Tilted var -1 || +1 -1 if tilted, +1 if not
integer Pecking var boolean True if pecking during this stage
float henPeck var -45 || 45 Rotation in the X plane to peck & unpeck
integer countPecks var 1 to 2 Pause after peck or unpeck
Type Name Use Value Pivot
float MaxPivot const 30 Maximum turn in the Z plane
Type Name Use Value Wander
vector posOrigin const set at rez Tether point, either nest if found or point of origin
float tooClose const 0.2 Minimum distance from owner
float tooFarAway const 10.0 Distance beyond which owner position is ignored
float maxMove const 0.25 Maximum distance of a move
float maxMove2Owner const 0.1 Maximum distance of move toward owner
float Corral const 4.0 Maximum radius from tether point
vector posCurr var llGetPos(); Used in calculating move targets

Morphing

Type Name Use Value Interpolation
integer Morphing var boolean True if morphing during this stage
float frameMorph var diff each stage Unit of morph: 1/(AgeDuration/Heartbeat/TotalPrims)
float stepMorph var calculated Percentage of morph per frame
Type Name Use Value Size Interpolation
integer orig_size_offset const 0 Origin offset for sizes list
integer dest_size_offset const TotalPrims Destination offset for sizes list
vector orig_size var diff each prim/stage Origin size for morph
vector dest_size var diff each prim/stage Destination size for morph
vector new_size var calculated New size for morph
Type Name Use Value Rotation Interpolation
vector orig_rot var diff each prim/stage Origin rotation for morph
vector dest_rot var diff each prim/stage Destination rotation for morph
vector new_rot var calculated New rotation for morph
Type Name Use Value Position Interpolation
integer orig_pos_offset var (0 to 3) * TotalPrims Origin offset for positions list
integer dest_pos_offset var (0 to 3) * TotalPrims Destination offset for positions list
vector orig_pos var diff each prim/stage Origin position for morph
vector dest_pos var diff each prim/stage Destination position for morph
vector new_pos var calculated New position vector for morph
Type Name Use Value Color & Transparency Interpolation
vector orig_Leather const < 0.0, 0.0, 0.0 > Chick color for root, eyes, & beak
vector orig_Feather const < 0.5, 0.5, 0.0 > Chick color for body, tail, neck, & head
vector orig_Color var diff each stage Origin color vector for morph
vector dest_Leather var xyz=random 0.25 to 1.00 Hen color for root, eyes, & beak
vector dest_Feather var xyz=random 0.00 to 0.75 Hen color for body, tail, neck, & head
vector dest_Color var diff each stage Destination color vector for morph
vector new_Color var calculated New color vector for morph
float viz var calculated New transparency vector for morph
Type Name Use Value Texture choice and appearance
string tex_Leather var random Texture for root, eyes, & beak
string tex_Feather var random Texture for body, tail, neck, & head
vector tex_repeat var random Texture repeat pattern
vector tex_offset var random Texture offset distance
float tex_rot var random Texture rotation

Interactive

Type Name Use Value Purpose
string BirthTime const llGetTimestamp() at rez Moment of origin
string BirthPlace const llGetRegionName() at rez Place of origin
integer textViz var Boolean Status of text display
vector textColor const < 1.0, 1.0, 0.0 > (yellow) Color of text display
float textAlpha const 1.0 Transparency of text display
integer OwnerEar var listen handle Hears commands via chat

Functions

Sign

Returns the sign of a floating variable as an integer of value -1 to 1.
integer Sign( float inp ){
	if( inp < 0 ){
		return - 1;
	} else if ( inp > 0 ){
		return 1;
	} else return 0;
}

Initialize

This function is called after an egg is rezzed with the script running in the default state, or after the script is reset and the object is touched by the owner. Birth data is logged. The point of origin is set as the Center of the corral. The adult colors, textures, and texture patterns are chosen. Various values are initialized.
Initialize(){
	BirthTime = llGetTimestamp();
	BirthPlace = llGetRegionName();
	//TotalPrims = 8; //for testing
	TotalPrims = llGetNumberOfPrims();
	AgeStage = -1;
	Tilted = 1;
	Pecking = FALSE;
	henPeck = -45;
	orig_size_offset = 0;
	dest_size_offset = TotalPrims;
	posOrigin = llGetPos();
	orig_size = < 0, 0, 0 >;
	orig_pos = < 0, 0, 0 >;
	dest_size = < 0, 0, 0 >;
	dest_pos = < 0, 0, 0 >;
	dest_Leather = < llFrand( 0.75 ), llFrand( 0.75 ), llFrand( 0.75 ) >;
	dest_Feather = < llFrand( 0.75 ) + 0.25, llFrand( 0.75 ) + 0.25, llFrand( 0.75 ) + 0.25 >;
	integer tex1 = (integer) llFrand( llGetListLength( Patterns ) - .001 );
	tex_Feather = llList2String( Patterns, tex1 );
	integer tex2;
	do
		tex2 = (integer) llFrand( llGetListLength( Patterns ) - 1 );
	while ( tex2 == tex1 );
	tex_Leather = llList2String( Patterns, tex2 );
	float TexRepX = llFrand( llFrand( llFrand( 100 )));
	float TexRepY;
	if( llFrand( 2 ) > 1 ){
		// 1/2 the time, x & y repeats are equal
		TexRepY = TexRepX;
	} else {
		TexRepY = llFrand( llFrand( llFrand( 100 )));
	}
	tex_repeat = < TexRepX, TexRepY, 0 >;
	tex_offset = < llFrand( 2 ) - 1, llFrand( 2 ) - 1, 0 >;
	tex_rot = DEG_TO_RAD * llFrand( 360 );
}

NewStage

Increments the life stage, resets the stage timer, and derives the name and duration of the new stage of life.
NewStage(){
	if( textViz ) SelfReport();
	AgeStage ++;
	countBeats = 0;
	AgeName = llList2String( Stage_Name, AgeStage );
	AgeDuration = llList2Integer( Stage_Age, AgeStage );
}

SelfReport

The text display, reporting the hen's time and place of origin and current stage. is toggled on and off by anyone touching the object.
SelfReport() {
	string msg;
	textViz = !textViz;
	if( textViz ){
		msg = "Gen #" + (string) ( llGetStartParameter() + 1 )
			+ ", currently " + AgeName
			+ "\nLaid "
			+ llGetSubString( BirthTime, 0, 9 )
			+ " " + llGetSubString( BirthTime, 11, 15 )
			+ " at " + BirthPlace
			+ "\n \nmindfulwebworks.com/\nsecond-life/\nchick'n'egg.html\n\n\n\n\n\n\n\n\n\n\n ";
	} else {
		msg = "";
	}
	llSetText( msg, textColor, textAlpha );
}

Peck, Pivot, & Wander

Peck

Rotates in the X (bilateral) plane, plus or minus the pecking-tilt amount
Peck(){
	rotation rotPeck = llEuler2Rot( < henPeck * Tilted, 0.0, 0.0 > );
	llSetRot( rotPeck * llGetRot() );
	Tilted = -Tilted;
}

Pivot

Rotates randomly in the horizontal plane from -MaxPivot/2 to +MaxPivot/2
Pivot(){
	llSetRot( llEuler2Rot(
		< 0.0, 0.0,
		llFrand( MaxPivot ) - MaxPivot/2 > )
		* llGetRot() );
}

Wander

Keeping it simple, all movement is in the horizontal plane, for a limited random distance, and in a mostly random direction with a gradual veering toward the owner, if detected in the area, but not too close. Never moves outside its corral,

Planned: veer toward nearest other chicken in area ("flock together" behavior), and keeping outside the bounding box of all nearby objects.

Wander(){
	posCurr = llGetPos();
	vector targCorral;
	//get distance to Center
	float farAway = llVecDist( posOrigin, posCurr );
	//if outside the corral
	if( farAway > Corral ){
		targCorral = posOrigin - posCurr;
		if( llFabs( targCorral.x ) > maxMove )
			targCorral.x = maxMove * Sign( targCorral.x);
		if( llFabs( targCorral.y ) > maxMove )
			targCorral.y = maxMove * Sign( targCorral.y);
		if( llFabs( targCorral.z ) > maxMove )
			targCorral.z = maxMove * Sign( targCorral.z);
	}

	vector targOwner;
	list detailOwner = llGetObjectDetails( llGetOwner(), [ OBJECT_POS ]);
	//only if owner is in sim
	integer detOwnLen = llGetListLength( detailOwner );
	if( detOwnLen == 0 ){
		//get owner's position
		vector posOwner = llList2Vector( detailOwner, 0 );
		//get distance between
		farAway = llVecDist( posOwner, posCurr );
		//don't bother about owner if too far away
		if( farAway < tooFarAway ){
			//target owner
			targOwner = posOwner - posCurr;
			//veer toward owner
			integer whichway = 1;
			if( farAway < tooClose ) whichway = -1;
			targOwner.x = maxMove2Owner * Sign( targOwner.x ) * whichway;
			targOwner.y = maxMove2Owner * Sign( targOwner.y ) * whichway;
			targOwner.z = 0;
		}
	}
	//combine corral seek & owner veer + random
	vector vecMove = targCorral + targOwner + <
		llFrand( maxMove * 2 ) - maxMove,
		llFrand( maxMove * 2 ) - maxMove,
		0 >;
	//govern move
	if( llFabs( vecMove.x ) > maxMove )
		vecMove.x = maxMove * Sign( vecMove.x );
	if( llFabs( vecMove.y ) > maxMove )
		vecMove.y = maxMove * Sign( vecMove.y) ;
	Pivot();
	llSetPos( posCurr + vecMove );
	Pivot();
}

Morphing

SetMorphOffsets

Set up list offsets for repositioning for each stage
SetMorphOffsets(){
	if( AgeName == "hatching" ){		// Egg to Chick
		orig_pos_offset = 0;				//orig pos is egg
		dest_pos_offset = TotalPrims;		//dest pos is chick
	} else if ( AgeName == "maturing" ){// Chick to Hen (sizes change)
		orig_pos_offset = TotalPrims;		//orig pos is chick
		dest_pos_offset = 2 * TotalPrims;	//dest pos is hen
	} else if ( ( AgeName == "settling"	//	Settle to Nest
		|| AgeName == "expiring" ) ){			//  OR  Settle at last
		orig_pos_offset = 2 * TotalPrims;	//orig pos is hen in stage 6 or 10
		dest_pos_offset = 3 * TotalPrims;	//dest pos is rest in stage 6 or 10
	} else if ( AgeName == "rising" ){	//  Rise from Nest
		orig_pos_offset = 3 * TotalPrims;	//orig pos is rest
		dest_pos_offset = 2 * TotalPrims;	//dest pos is hen
	}
	frameMorph = 1/(AgeDuration/Heartbeat/TotalPrims);
}

Morph

Progress from origin parameters to target parameters during morphing stages.
Morph(){
	list MorphList = [];
	if( countPrims == 0 ){
		stepMorph = 1-(( countBeats / AgeDuration ) + frameMorph);
	}
	if( AgeName == "maturing" ){
		string txtur;
		if(( countPrims > 0 ) && ( countPrims < 5 )){
			// FEATHER:	#2 Body, #3-5, Tail, Neck, & Head
			dest_Color = dest_Feather;
			orig_Color = orig_Feather;
			txtur = tex_Feather;
		} else {
			// LEATHER:	#1 Root, #6 & #7 Eyes, & #8 Beak
			dest_Color = dest_Leather;
			orig_Color = orig_Leather;
			txtur = tex_Leather;
		}
		new_Color = ( dest_Color - orig_Color ) * stepMorph;
		new_Color = dest_Color - new_Color;
		vector incr_tex_repeat = < (
			  100 - tex_repeat.x ) *stepMorph + tex_repeat.x,
			( 100 - tex_repeat.y ) *stepMorph + tex_repeat.y, 0 >;
		//		tex_offset = < llFrand( 2 ) - 1, llFrand( 2 ) - 1, 0 >;
		//		tex_rot = DEG_TO_RAD * llFrand( 360 );
		MorphList = [
			PRIM_COLOR, ALL_SIDES, new_Color, 1.0,
			PRIM_TEXTURE, ALL_SIDES, txtur, incr_tex_repeat, tex_offset, tex_rot
			];
		dest_size = llList2Vector( Prim_Sizes, countPrims + dest_size_offset );
		orig_size = llList2Vector( Prim_Sizes, countPrims + orig_size_offset );
		new_size = ( dest_size - orig_size ) * stepMorph;
		new_size = dest_size - new_size;

		//adjust root position relative to current position with size change
		if ( countPrims == 0 ){
			new_pos = llGetPos();
			new_pos.z += ( dest_size.z - orig_size.z ) * frameMorph / 2;
			MorphList = llListInsertList( MorphList,
				[ PRIM_SIZE, new_size,
				PRIM_COLOR, ALL_SIDES, new_Color, 1.0,
				PRIM_POSITION, new_pos ],
				llGetListLength( MorphList ) );
		}
	}
	if( countPrims > 0 ){
		//child positions relative to root
		dest_pos = llList2Vector( Prim_Positions, countPrims + dest_pos_offset );
		orig_pos = llList2Vector( Prim_Positions, countPrims + orig_pos_offset );
		new_pos = ( dest_pos - orig_pos ) * stepMorph;
		new_pos = dest_pos - new_pos;
		MorphList = llListInsertList( MorphList,
			[ PRIM_POSITION, new_pos ],
			llGetListLength( MorphList ) );
		//sizes
		if( AgeName == "maturing" ){
			MorphList = llListInsertList( MorphList,
				[ PRIM_SIZE, new_size],
				llGetListLength( MorphList ) );
		}
		//rotations
		if(( AgeName == "settling" )
			|| ( AgeName == "expiring" )
			|| ( AgeName == "rising" ) ){
			dest_rot = llList2Vector( Prim_Rots,
				countPrims + TotalPrims * ( AgeName != "rising" ));
			if( dest_rot != < 0, 0, 0 > ){
				orig_rot = llList2Vector( Prim_Rots,
					countPrims + TotalPrims * ( AgeName == "rising" ));
				new_rot = ( dest_rot - orig_rot ) * stepMorph;
				new_rot = dest_rot - new_rot;
				vector new_radians = ( new_rot * DEG_TO_RAD );
				rotation modrot = llEuler2Rot( new_radians ) / llGetRot();
				MorphList = llListInsertList( MorphList,
					[ PRIM_ROTATION, modrot ],
					llGetListLength( MorphList ) );
			}
		}
	}
	if( ( AgeName == "maturing" ) || ( countPrims > 0 ) ){
		llSetLinkPrimitiveParams( countPrims + 1, MorphList );
	}
	countPrims++;
	if( countPrims == TotalPrims ) countPrims = 0;
}

States

default

Upon script reset, nothing happens. Life begins either when the object is rezzed with the script running in the default state, or after the script is reset and the object is touched by the owner. The Initialization function is run. If the bird senses a nearby henyard, the henyard becomes the Center of the bird's corral. The script then progresses to the EggTimer state.
default{
	touch_start( integer HowMany ){
		integer i = 0;
		for(; i < HowMany; i++ ){
			if( llDetectedKey( i ) == llGetOwner() ){
				Initialize();
				llSensor( "Henyard", NULL_KEY, PASSIVE, tooFarAway, PI );
			}
		}
	}
	on_rez(integer Gen){
		Initialize();
		llSensor( "Henyard", NULL_KEY, PASSIVE, tooFarAway, PI );
	}
	sensor(integer total_number){
		posOrigin = llDetectedPos( 0 );
		vector primsize = llGetScale();
		posOrigin.z += primsize.z;
		state EggTimer;
	}
	no_sensor(){
		state EggTimer;
	}
}

EggTimer

The bird is inactive during this embryonic time, except for the self-report response to touch.
state EggTimer{
	state_entry(){
		NewStage();
		llSetTimerEvent(AgeDuration);
	}
	on_rez(integer start_param){
		llResetScript();
	}
	timer()
	{
		state Birdbrain;
	}
	touch_start(integer HowMany)
    {
		SelfReport();
    }
}

Birdbrain

The active state for all stages of life except embryonic, laying, and fading out. Listens for and executes owner commands. Chooses pecking, pivoting, and wandering behaviors. Executes morphing during growth, settling, and rising.
state Birdbrain{
	state_entry()
	{
		NewStage();
		//stage will be hatching or rising
		Morphing = TRUE;
		SetMorphOffsets();
		countPecks = 0;
		Pecking = TRUE;
		llSetTimerEvent( Heartbeat );
		OwnerEar = llListen( 42, "", llGetOwner(), "" );
	}
	listen( integer channel, string name, key id, string message ){
		message = llStringTrim( message, STRING_TRIM );
		list msgs = llParseString2List( message, [" "], [] );
		string msg = llList2String( msgs, 0 );
		if( msg == "hen" ){
			llSetTimerEvent( 0.0 );
			integer msg_ndx = 1;
			for (; msg_ndx < llGetListLength( msgs ); msg_ndx++ ){
				msg = llList2String( msgs, msg_ndx );
				integer spins = 6;
				integer doSpin = TRUE;
				integer spinLR = 60;
				if(( msg == "cw" ) || ( msg == "fw" )) spinLR = -spinLR;
				vector vec_spin = < 0.0, 0.0, 0.0 >;
				float rad_spin = spinLR * DEG_TO_RAD;
				if(( msg == "cw" ) || ( msg == "ccw" )){
					vec_spin.z = rad_spin;
				} else if(( msg == "fw" ) || ( msg == "bw" )){
					vec_spin.x = rad_spin;
				} else doSpin = FALSE;
				if( doSpin ){
					if( Tilted < 0 ) Peck();
					for (; spins > 0; spins-- )
						llSetRot( llEuler2Rot( vec_spin ) * llGetRot() );
				}
			}
			llSetTimerEvent( Heartbeat );
		}
	}
	timer()
	{
		if( Pecking )
		{
			if ( countPecks > 0 ){
				countPecks -= 1;
			} else {
				// If pose is not normal, stand up (sometimes poop?), wait 1.0s
				// If pose is normal, randomly pivot, peck, or wander, wait 0.5s
				if( Tilted < 0 ){
					Peck();
					countPecks = 2;
				} else {
					float rndBehavior = llFrand( 4.0 );
					if( rndBehavior <= 1.0 ){
						Pivot();
					} else if ( rndBehavior <= 2.0 ){
						Peck();
					} else Wander();
					countPecks = 1;
				}
			}
		}

		if( Morphing ) Morph();
		countBeats += Heartbeat;
		if( countBeats == AgeDuration ){
			NewStage();
			if( AgeName == "fading" ){
				state FadeOut;
			} else if( AgeName == "laying" ){
				if( Tilted < 0 ) Peck();
				state Laying;
			} else if( ( AgeName == "settling" )
				|| ( AgeName == "expiring" )){
				if ( Tilted < 0 ) Peck();
				Pecking = FALSE;
				Morphing = TRUE;
			} else {
				Pecking = TRUE;
				if ( AgeName == "maturing" ){
					Morphing = TRUE;
				} else {
					Morphing = FALSE;
				}
			}
			if( Morphing )SetMorphOffsets();
		}
	}
	touch_start(integer HowMany)
    {
		SelfReport();
    }
}

Laying

It's alive! Reproduction! An egg is rezzed at the mother hen's feet... wheel... whatever. Egg is given copy of egg by mother hen so the generations can continue.
state Laying {
	state_entry()
	{
		vector EggDiff = (
			llList2Vector( Prim_Sizes, TotalPrims )
			- llList2Vector( Prim_Sizes, 0 ) );
		vector EggPos = llGetPos();
		EggPos = EggPos - < 0, 0, EggDiff.z / 2.0 >;
		llRezAtRoot(
			llGetObjectName(), // Egg presumed to have same name as object
			EggPos, // Rezzed near hen's base
			< 0, 0, 0 >, // with no velocity
			llGetRot(), // rotation same as mother hen
			llGetStartParameter() + 1 ); // incremented generation count
		llSetTimerEvent( AgeDuration ); // wait for a while
	}
	object_rez(key id)
	{
		llGiveInventory( id, llGetObjectName());  //give egg to egg
	}
	timer() {
		state Birdbrain;
	}
	touch_start(integer HowMany)
	{
		SelfReport();
	}
}

FadeOut

Having first settled to its final resting position, the old bird fades away and dies.
state FadeOut {
	state_entry()
	{
		countPrims = 0;
		countBeats = Heartbeat * TotalPrims;
		llSetTimerEvent( Heartbeat );
	}
	timer() {
		if( countPrims == 0 )
			viz = 1 - ( countBeats / AgeDuration );
		if(( countPrims > 0 ) && ( countPrims < 5 )){
			dest_Color = dest_Feather;
		} else {
			dest_Color = dest_Leather;
		}
		new_Color = viz * dest_Color;
		llSetLinkPrimitiveParams( countPrims + 1, [
			PRIM_COLOR, ALL_SIDES, new_Color, viz ]);
		countPrims++;
		if( countPrims == TotalPrims ){
			countPrims = 0;
			countBeats += Heartbeat * TotalPrims;
			if( countBeats >= AgeDuration ) llDie();
		}
	}
	touch_start(integer HowMany)
		{
			SelfReport();
		}
}

Change Log

Changes in v006

2008 Jun 28: Changed texture selection to be fixed at the beginning of the maturing stage. Added more textures. Tweaked the texture appearance calculations. Added to the default state: besides rezzing, a touch by the owner also now begins life; required the creation of the Initialization function. Created the Sign(float) function. Modified the Wander function to adjust for the object being outside of, and above or below, the corral (still testing). Added chat-response on channel 42 during the Birdbrain state; the bird's aging timer is turned off during chat-induced performances.Added response to commands cw, ccw, fw, and bw, respectively to spin clockwise or counter-clockwise, or to flip forward or backward (but not a true flip yet because it spins around the root prim instead of around the object center).

2008 Jun 19: Added textures. At the beginning of each round of prim growth during maturity stage, a "Leather" texture and a "Feather" texture are randomly selected from a list of several UUIDs from the default library, and texture offset, rotation, and repetition are also randomly set, with repetition weighted toward the lower end of 0-to-100. Leather and Feather never have the same texture. Final textures are whatever were chosen for the last round of growth for Leather and Feather.

2008 Jun 18: Added rotation interpolation between standing & resting positions for beak, head, neck, and tail.

2008 Jun 13: Default entry state does nothing. Life now begins after rez, when all variables are initialized. Eliminates the script reset on rez, so the start parameter now continuously conveys generation number.
Added self-report when user touches object.
Tweaked fadeout slightly for better timing.

2008 May 30: Consistent egg-laying life cycle achieved!

As of 2008 May 21:
Egg-to-Expiration script timing & state sequences
Wandering, Pecking, and Pivoting behaviors
Repositioning of prims through egg, chick, hen, rest, rise, rest morphs
Resizing of prims from chick to hen, with according repositioning of root prim; also adoption of adult colors.
Fading out & dying

2007 Nov 09 - Rotation to direction of movement

2007 Nov 08 - Worked on rotation, e.g. toward owner as prelude to getting chicken to turn to the direction of movement.

2007 Nov 07 - Worked on movement toward but not too close to owner. Began working on nesting pose. Began working on expiration pattern.

2007 Nov 06 - Standardized chicken models & fixed a few buglets. Chickens recognize center of corral as point of origin unless a nest is sensed nearby, which takes priority.

2007 Nov 05 - Created chick-to-hen growth pattern

2007 Nov 04 - Created chick

2007 Nov 03 - Created pivoting behavior. Created random movement. Created a corral ( limited distance from point of origin ). Created move toward owner. Created pooping (not perfected). Created fourth floor-tile chicken.

2007 Nov 02 - Created blue denim, red burlap, and leopard print chickens Created pecking behavior.