Copy to Clipboard Test

Edge Matching Puzzle Code

const int SFX_EDGEMATCH_MOVE=16; //Sounв to play on rotating tile.

//3*3 rotating tiles. Match connecting pixels to open secrets.
//Place 3*3 FFCs spaced so their centers are speced apart by 2 combos. Check demo quest to see how combos are set up
//Import and compile the script. Nothing beyond default stuff is need.
//D0-D3 edge IDs, up, right, down and left. For puzzle to be solved, all IDs on adjacent FFCs must match. 
//For instance One FFC has D0 to 1 and same number on another FFCs D2.
//D4 - Set to 1 for FFC to be able to be rotated.
//D5 - Set to 1 to prevent initial rotation randomization of this FFC.
//Must set "Run Script at Screen Init" and "Only Visible to Lens of Truth" flags. 

ffc script EdgeMatcher{
	void run (int rotup, int rotright, int rotdown, int rotleft, int rot, int norando){
		int rotate[4] = {rotup, rotright, rotdown, rotleft};
		int cmb = ComboAt(CenterX(this), CenterY(this));
		this->X = ComboX(cmb);
		this->Y = ComboY(cmb);
		this->TileWidth=1;
		this->TileHeight=1;
		int origdata = this->Data;
		this->Data = FFCS_INVISIBLE_COMBO;
		int rottimer=0;
		int rotcount=0;
		int randrotate[4];
		for (int i=0;i<4;i++) randrotate[i]=rotate[i];
		if ((rot>0)&&(norando==0)){
			this->InitD[7]=1;
			while(this->InitD[7]>0){
				for (int i=0;i<4;i++) randrotate[i]=rotate[i];
				int Rnd=Rand(3);
				rotcount=Rnd;
				for (int i=0;i<Rnd;i++){
					ArrayShiftRight(randrotate);
					for (int i=0; i<4; i++){
						this->InitD[i] = randrotate[i];
					}
				}			
				for (int i=0;i<=3;i++){
					int adjcmb=-1;
					if ( i==0) adjcmb = AdjacentComboFix(cmb, DIR_UP, 2);
					if ( i==1) adjcmb = AdjacentComboFix(cmb, DIR_RIGHT, 2);
					if ( i==2) adjcmb = AdjacentComboFix(cmb, DIR_DOWN, 2);
					if ( i==3) adjcmb = AdjacentComboFix(cmb, DIR_LEFT, 2);
					//Screen->Rectangle(3, ComboX(adjcmb), ComboY(adjcmb), ComboX(adjcmb)+15, ComboY(adjcmb)+15, 1, -1, 0, 0, 0, false, OP_OPAQUE);
					if (adjcmb<0) continue;
					for (int j=1;j<=32;j++){
						ffc f = Screen->LoadFFC(j);
						if (f->Script!=this->Script) continue;
						if (f->X!= ComboX(adjcmb)) continue;
						if (f->Y!= ComboY(adjcmb)) continue;
						int checkdir = i+2;
						if (checkdir>3) checkdir-=4;
						if (f->InitD[checkdir]!=this->InitD[i]){
							this->InitD[7]=0;
							break;
						}
					}
				}
				Waitframe();
			}
		} 
		else if(rot==0) this->InitD[7]=1;
		for (int i=0; i<4; i++){
			rotate[i]=randrotate[i];
			this->InitD[i] = randrotate[i];
		}
		while(true){
			if (rottimer==0){
				if(LinkCollision(this)&&(Link->PressEx1)&&(rot>0)){
					Game->PlaySound(16);
					rottimer = 30;
					this->InitD[7]=0;
					rotcount++;
					if (rotcount>=4) rotcount=0;
				}
			}
			else {
				if (rottimer>0)rottimer--;
				if (rottimer==0){
					ArrayShiftRight(rotate);
					for (int i=0; i<4; i++){
						this->InitD[i] = rotate[i];
					}
					for (int i=0;i<=3;i++){
						int adjcmb=-1;
						if ( i==0) adjcmb = AdjacentComboFix(cmb, DIR_UP, 2);
						if ( i==1) adjcmb = AdjacentComboFix(cmb, DIR_RIGHT, 2);
						if ( i==2) adjcmb = AdjacentComboFix(cmb, DIR_DOWN, 2);
						if ( i==3) adjcmb = AdjacentComboFix(cmb, DIR_LEFT, 2);
						//Screen->Rectangle(3, ComboX(adjcmb), ComboY(adjcmb), ComboX(adjcmb)+15, ComboY(adjcmb)+15, 1, -1, 0, 0, 0, false, OP_OPAQUE);
						if (adjcmb<0) continue;
						for (int j=1;j<=32;j++){
							ffc f = Screen->LoadFFC(j);
							if (f->Script!=this->Script) continue;
							if (f->X!= ComboX(adjcmb)) continue;
							if (f->Y!= ComboY(adjcmb)) continue;
							int checkdir = i+2;
							if (checkdir>3) checkdir-=4;
							if (f->InitD[checkdir]!=this->InitD[i]){
								this->InitD[7]=0;
								break;
							}
							this->InitD[7]=1;
						}
					}
					for (int j=1;j<=33;j++){
						if (Screen->State[ST_SECRET]) break;
						else if (j==33){
							Game->PlaySound(SFX_SECRET);
							Screen->TriggerSecrets();
							Screen->State[ST_SECRET]=true;
							break;
						}
						ffc f = Screen->LoadFFC(j);
						if (f->Script!=this->Script) continue;
						if (f->InitD[7]==0)	break;
					}
				}					
			}
			if (this->InitD[7]>0)Screen->Rectangle(5, this->X, this->Y, this->X+15, this->Y+15, 0x81, -1, 0,0, 0, false, OP_OPAQUE);
			Screen->DrawCombo(2-rot, this->X-16, this->Y-16, origdata, 3, 3, this->CSet, -1, -1, this->X-16, this->Y-16, rotcount*90-rottimer*3, 0, 0,true, OP_OPAQUE);
			Waitframe();
		}
	}
}

//Returns the combo ID of a combo based on a location, in a givem direction, N combos away.
int AdjacentComboFix(int cmb, int dir, int dist)
{
	int combooffsets[13]={-0x10, 0x10, -1, 1, -0x11, -0x0F, 0x0F, 0x11};
	if ( cmb % 16 == 0 ) combooffsets[9] = -1;
	if ( (cmb % 16) == 15 ) combooffsets[10] = -1; 
	if ( cmb < 0x10 ) combooffsets[11] = -1; //if it's the top row
	if ( cmb > 0x9F ) combooffsets[12] = -1; //if it's on the bottom row
	if ( combooffsets[9] && ( dir == DIR_LEFT || dir == DIR_LEFTUP || dir == DIR_LEFTDOWN || dir == DIR_LEFTUP ) ) return -1; //if the left columb
	if ( combooffsets[10] && ( dir == DIR_RIGHT || dir == DIR_RIGHTUP || dir == DIR_RIGHTDOWN ) ) return -1; //if the right column
	if ( combooffsets[11] && ( dir == DIR_UP || dir == DIR_RIGHTUP || dir == DIR_LEFTUP || dir == DIR_LEFTUP ) ) return -1; //if the top row
	if ( combooffsets[12] && ( dir == DIR_DOWN || dir == DIR_RIGHTDOWN || dir == DIR_LEFTDOWN ) ) return -1; //if the bottom row
	else if ( cmb >= 0 && cmb < 176 ) 
	{
		int cmbs[2];//needs a for loop to ensure that t returns the most valid combo
	    
		for ( cmbs[1] = 0; cmbs[1] < dist; cmbs[1]++ ) 
		{
			cmbs[0] = cmb;
			cmb += (combooffsets[dir]);
			if ( cmb < 0 || cmb > 175 ) return -1;
			if ( cmb % 16 == 0 ) combooffsets[9] = -1;
			if ( (cmb % 16) == 15 ) combooffsets[10] = -1;  
			if ( cmb < 0x10 ) combooffsets[11] = -1; //if it's the top row
			if ( cmb > 0x9F ) combooffsets[12] = -1; //if it's on the bottom row
			if ( combooffsets[9] && ( dir == DIR_LEFT || dir == DIR_LEFTUP || dir == DIR_LEFTDOWN || dir == DIR_LEFTUP ) ) return -1; //if the left columb
			if ( combooffsets[10] && ( dir == DIR_RIGHT || dir == DIR_RIGHTUP || dir == DIR_RIGHTDOWN ) ) return -1; //if the right column
			if ( combooffsets[11] && ( dir == DIR_UP || dir == DIR_RIGHTUP || dir == DIR_LEFTUP || dir == DIR_LEFTUP ) ) return -1; //if the top row
			if ( combooffsets[12] && ( dir == DIR_DOWN || dir == DIR_RIGHTDOWN || dir == DIR_LEFTDOWN ) ) return -1; //if the bottom row
			
		}
		return cmb;
	}
	else return -1;
} 

void ArrayShiftRight(int arr){
	int lasti = SizeOfArray(arr)-1;
	int res = arr[lasti];
	for(int i = lasti; i>0; i--){
		arr[i] = arr[i-1];
	}
	arr[0]=res;
}

void ArrayShiftLeft(int arr){
	int lasti = SizeOfArray(arr)-1;
	int res = arr[0];
	for(int i = 0; i<lasti; i++){
		arr[i] = arr[i+1];
	}
	arr[lasti]=res;
}