Copy to Clipboard Test

Ball/Gem Color Sort Puzzle Code

const int SFX_COLORSORT_PICK = 4;//Sound to play when picking ball from jar

const int SFX_COLORSORT_MOVE = 16;//Sound to play when putting a ball into jar

const int SFX_COLORSORT_SPECIAL_TRIGGER = 47;//Sound to play on special trigger



const int TILE_COLORSORT_TOP = 36169; //Tile used for jar top

const int TILE_COLORSORT_MIDDLE = 36170;//Tile used for jar middle

const int TILE_COLORSORT_BOTTOM = 36171;//Tile used for jar bottom

const int TILE_COLORSORT_BALL = 36147;//Tiles used to render balls. Must be ID of leftmost ball tile.

const int TILE_COLORSORT_GOAL = 36172;//Tile used to mark completed jars

const int TILE_COLORSORT_COLOR_HINT = 36189;//Tiles used to render color clues at jar bases. Must be ID of leftmost tile. This row and TILE_COLORSORT_BALL tile row must have the same color order.

const int TILE_COLORSORT_EMPTY_HINT = 36188;//Tile used to indicate that jar must be empty to solve the puzzle.



const int LINK_MISC_BALL_IN_HAND = 0;//Link Misc variable to track which ball Link has in hand.

const int LINK_MISC_PREV_JAR = 1;//Link Misc variable to track which jar Link was drawn from.



const int CSET_COLORSORT = 7; //CSet used to render jars.

const int CSET_COLORSORT_BALLS = 2;//CSet used to render balls.

const int CSET_COLORSORT_GOAL = 8;//CSet used to mark completed jars

const int CSET_COLORSORT_SPECIAL_GOAL = 5;//CSet used to mark special-triggered jars



const int COLORSORT_SIZE_PER_UNIT = 8;//Unit to pixel conversion rate. Used for rendering script draws.



const int SCREEN_D_COLORSORT_SPECIAL_TRIGGER = 0;//Screen D register used to track special-triggered jars



//Color/gem sorting puzzle.

//You have a number of jars. Some of them have colored gems stacked one on top of another. 

//You can grab top gem from jap and drop it into another jar, adding it on top of the stack.

//If all jars are either empty, or full of same-colored gems, puzzle is solved. 

//Some jars have colored base and can be completed oly if filled with gems of specific color.

//

//1. Set up tiles to render jars, balls and goal marks. Tiles must be as tall as COLORSORT_SIZE_PER_UNIT constant, rest should be transparent.

//   Balls must be consecutive. 

//2. Also for color targeted jars set up a sequence of tiles with the same color order as balls needed to render color clues on jar bases

//   And one tile for clue that jar must be empty.

//3. Set up constants inside script file. For instance, TILE_COLORSORT_BALL to ID of leftmost ball tile.

//4. Set up combo for bottom part of the jar what looks like, if jar was empty.

//5. Place jar FFC`s with combo from step 4 as Data and assigned script. Make sure there is a solid combo underneath FFC and free spot 1 space south.

// D0 to D2.  IDs of ball colors (0-6), starting from bottom. Color are read in pairs.

//      #####.____  - lower ball

//      _____.####  - higher ball

// D3 - #####.____ - jar capacity, in units.

//      _____.#### - add together: 1 - It`s prohibited to place a ball onto different-colored one, unless placed back where it was taken from. 2 - ban placing colored balls into jar that had special trigger already activated (D5 != 0).

// D4 - Target color. The jar must be filled with gems of this color ID to count as complete. -1 - jar must be empty for puzzle to be solved. 0 - any color.

// D5 - Special trigger option in completing jar. >0 - ID of Item awarded, <0 - Instant secret trigger. Balls will disappear on special trigger.

// D6 - Screen D bit ID to track special triggers. Musi be unique for each jar in the screen.





ffc script ColorSortPipe{

	void run(int ball1, int ball2, int ball3, int set, int targcolor, int specialtrigger, int dbit){

		int balls[6]={GetHighFloat(ball1), GetLowFloat(ball1),GetHighFloat(ball2), GetLowFloat(ball2), GetHighFloat(ball3), GetLowFloat(ball3)};

		BallGravity(balls);

		Link->Misc[LINK_MISC_BALL_IN_HAND]=0;

		Link->Misc[LINK_MISC_PREV_JAR]=0;

		int cap = GetHighFloat(set);

		int flags = GetLowFloat(set);

		int drawy = this->Y;

		if (JarCompleted(balls,cap,targcolor) && specialtrigger==0) this->InitD[7]=1;

		else  this->InitD[7]=0;

		while(true){

			if ((Link->Y == this->Y + 8 && (Link->X < this->X + 8 && Link->X > this->X - 8) && Link->Dir == DIR_UP)){

				if (Link->PressEx1){

					if (Link->Misc[LINK_MISC_BALL_IN_HAND] == 0){

						if ( GetLastNonZero(balls)>0){

							Game->PlaySound(SFX_COLORSORT_PICK);

							Link->Misc[LINK_MISC_BALL_IN_HAND] = RemoveFromArray (balls);

							Link->Misc[LINK_MISC_PREV_JAR] = FFCNum(this);

							if (specialtrigger>0){

								if (!GetScreenDBit(SCREEN_D_COLORSORT_SPECIAL_TRIGGER, dbit) && JarCompleted(balls,cap,targcolor)){

									if (specialtrigger>0) item it = CreateItemAt(specialtrigger,Link->X,Link->Y);

									else if (!Screen->State[ST_SECRET]) {

										Game->PlaySound(SFX_SECRET);

										Screen->TriggerSecrets();

										Screen->State[ST_SECRET] = true;

									}

									SetScreenDBit(SCREEN_D_COLORSORT_SPECIAL_TRIGGER, dbit, true);

									Game->PlaySound(SFX_COLORSORT_SPECIAL_TRIGGER);

									for (int i=0;i<6;i++){

										balls[i]=0;

									}

								}

							}

							if (!GetScreenDBit(SCREEN_D_COLORSORT_SPECIAL_TRIGGER, dbit))this->InitD[7]=0;

							if (JarCompleted(balls, cap, targcolor)) this->InitD[7]=1;

						}

					}

					else{

						if (BallFitInJar(flags, this, balls)){

							if (balls[cap-1]==0){

								AppendToArray(balls, Link->Misc[LINK_MISC_BALL_IN_HAND]);

								Link->Misc[LINK_MISC_BALL_IN_HAND]=0;

								Link->Misc[LINK_MISC_PREV_JAR]=0;

								Game->PlaySound(SFX_COLORSORT_MOVE);

								if (specialtrigger==0){

									this->InitD[7]=0;

									if (JarCompleted(balls,cap,targcolor)) this->InitD[7]=1;

									for (int i=1; i<=33; i++){

										if (i==33){

											Game->PlaySound(SFX_SECRET);

											Screen->TriggerSecrets();

											Screen->State[ST_SECRET] = true;

											break;

										}

										ffc s = Screen->LoadFFC(i);

										if (s->Script!=this->Script) continue;

										if (s->InitD[7]==0) break;

									}

								}

								else if (!GetScreenDBit(SCREEN_D_COLORSORT_SPECIAL_TRIGGER, dbit) && JarCompleted(balls,cap,targcolor)){

									if (specialtrigger>0){

										item it = CreateItemAt(specialtrigger,Link->X,Link->Y);

										it->Pickup +=IP_HOLDUP;

									}

									else if (!Screen->State[ST_SECRET]) {

										Game->PlaySound(SFX_SECRET);

										Screen->TriggerSecrets();

										Screen->State[ST_SECRET] = true;

									}

									SetScreenDBit(SCREEN_D_COLORSORT_SPECIAL_TRIGGER, dbit, true);

									Game->PlaySound(SFX_COLORSORT_SPECIAL_TRIGGER);

									for (int i=0;i<6;i++){

										balls[i]=0;

									}

									Waitframe();

									this->InitD[7]=1;

									for (int i=1; i<=33; i++){

										if (i==33){

											Game->PlaySound(SFX_SECRET);

											Screen->TriggerSecrets();

											Screen->State[ST_SECRET] = true;

											break;

										}

										ffc s = Screen->LoadFFC(i);

										if (s->Script!=this->Script) continue;

										if (s->InitD[7]==0) break;

									}

								}

							}

						}

					}

				}

			}

			//render jars and colored balls in them

			drawy = this->Y;

			for (int i = 0; i<SizeOfArray(balls); i++){

				if (balls[i]>0)Screen->FastTile(Cond(i==0, 1, 4), this->X, drawy, TILE_COLORSORT_BALL+balls[i]-1,CSET_COLORSORT_BALLS , OP_OPAQUE);

				drawy-=COLORSORT_SIZE_PER_UNIT;

			}

			drawy = this->Y;

			for (int t=1; t<=cap+1; t++){

				int tile = TILE_COLORSORT_MIDDLE;

				if (t==1) tile = TILE_COLORSORT_BOTTOM;

				if (t ==cap+1) tile = TILE_COLORSORT_TOP;

				Screen->FastTile(Cond(t==1, 0, 4), this->X, drawy, tile, CSET_COLORSORT, OP_OPAQUE);

				//Screen->DrawTile(Cond(t==1, 2, 4), this->X, drawy, tile, 1, 1, CSET_WATERJAR, -1, -1, 0, 0, 0, 0, true, OP_OPAQUE);

				drawy-=COLORSORT_SIZE_PER_UNIT;

			}

			drawy+=COLORSORT_SIZE_PER_UNIT;

			if (this->InitD[7]>0)Screen->FastTile(4, this->X, drawy, TILE_COLORSORT_GOAL,Cond(GetScreenDBit(SCREEN_D_COLORSORT_SPECIAL_TRIGGER, dbit),CSET_COLORSORT_SPECIAL_GOAL,CSET_COLORSORT_GOAL),OP_OPAQUE);

			if (Link->Misc[LINK_MISC_BALL_IN_HAND]>0)Screen->FastTile(3, Link->X, Link->Y-8, TILE_COLORSORT_BALL+Link->Misc[LINK_MISC_BALL_IN_HAND]-1, CSET_COLORSORT_BALLS, OP_OPAQUE);

			if (targcolor>0)Screen->FastTile(3,this->X, this->Y, TILE_COLORSORT_COLOR_HINT+targcolor-1,CSET_COLORSORT_BALLS,OP_OPAQUE);

			if (targcolor<0)Screen->FastTile(3,this->X, this->Y, TILE_COLORSORT_EMPTY_HINT,CSET_COLORSORT_BALLS,OP_OPAQUE);

			Waitframe();

		}		

	}

}



bool BallFitInJar(int flags, ffc f, int balls){

	if ((flags&2)>0 && GetScreenDBit(SCREEN_D_COLORSORT_SPECIAL_TRIGGER, f->InitD[6])) return false;

	if (GetLastNonZero(balls)==0) return true;

	if ((flags&1)>0 && Link->Misc[LINK_MISC_BALL_IN_HAND]!=GetLastNonZero(balls) && Link->Misc[LINK_MISC_PREV_JAR]!=FFCNum(f))return false;

	return true;

}



bool JarCompleted(int arr, int cap, int targcolor){

	if(GetLastNonZero(arr)==0 && targcolor==0)return true;

	if(GetLastNonZero(arr)>0 && targcolor<0)return false;

	int check = arr[0];

	if (targcolor>0 && check!=targcolor) return false; 

	for(int i=0; i<cap; i++){

		if (arr[i]!=check)return false;

	}

	return true;

}



void BallGravity(int arr){

	for( int i=1; i<6; i++){

		if (arr[i]==0)continue;

		int p=i;

		while(arr[p-1]==0){

			SwapArray(arr, p, p-1);

			p--;

		}

	}

}



void AppendToArray(int arr, int a){

	for (int i =0; i<SizeOfArray(arr);i++){

		if (arr[i]>0) continue;

		arr[i]=a;

		return;

	}

}



int GetLastNonZero(int arr){

	for (int i=SizeOfArray(arr)-1; i>=0;i--){

		if (arr[i]==0) continue;

		return  arr[i];

	}

	return 0;

}



int RemoveFromArray (int arr){

	for (int i=SizeOfArray(arr)-1; i>=0;i--){

		if (arr[i]==0) continue;

		int ret = arr[i];

		arr[i]=0;

		return ret;

	}

}



//Swaps two elements in the given array

void SwapArray(int arr, int pos1, int pos2){

	int r = arr[pos1];

	arr[pos1]=arr[pos2];

	arr[pos2]=r;

}