Copy to Clipboard Test

Railroad Rotating/Moving colored circle puzzle Code

const int CF_MOVING_CIRCLES_PATH = 8;//Dombo flag used for defining paths

const int CMB_MOVING_ROTCIRCLE = 956;//Combo used to render rotating circle
const int CSET_MOVING_ROTCIRCLE = 2;//CSet used to render rotating circle

const int SFX_MOVING_CIRCLES_MOVE = 50;//Sound to play, when circle starts moving
const int SFX_MOVING_CIRCLES_CANTMOVE = 16;//Sound to play, when circle tries to move off rails or onto occupied rails.
const int SFX_MOVING_CIRCLES_STOP = 16;//Sound to play, when circle stops moving

//Railroad Rotating/Moving colored circle 2*2.
//Stand on FFC, face desired direction and press EX1, to cause colored circle on rails to start it moving along it until next node (32 pixels per move).
//As circle moves, it turns 90 degrees every 32 pixels moved. Bring all circles to target positions while having them facing target directions
// to solve the puzzle.

//Build rail paths using CF_MOVING_CIRCLES_PATH flags and referring top-left corner as standpoint.

//Place FFC at operator spot.
//D0 - Combo position for starting location of colored circle.
//D1 - Starting direction facing the circle. 0 - 3
//D2 - Target position for colored circle.
//D3 - Target direction for colored circle.
//D4 - 1 - anti-clockwise rotation, 0 for clockwise rotation.
//D5 - Does not stop moving unless obstructed.


ffc script MovingEdgeMatcher{
	void run (int pos, int dir, int targetpos, int tatgetdir, int rotdir, int ice){
		int xpos = ComboX(this->InitD[0]);
		int ypos = ComboY(this->InitD[0]);
		int str[] = "MovingEdgeMatcher";
		int scr = Game->GetFFCScript(str);
		int movecounter = 0;
		int movedir=-1;
		int angle = 0;
		bool Connect = false;
		if (dir== DIR_DOWN)angle=180;
		if (dir==DIR_LEFT)angle=270;
		if (dir==DIR_RIGHT)angle=90;
		while (true){
			if (movecounter==0){
				if (RectCollision(Link->X+7, Link->Y+7, Link->X+8, Link->Y+8, this->X, this->Y, this->X+this->EffectWidth-1, this->Y+this->EffectHeight-1)){
					Screen->Rectangle(2, xpos, ypos, xpos+31, ypos+31, 1, -1, 0, 0, 0, false, OP_OPAQUE);
					if (Link->PressEx1){
						if (EdgeMatchMoverCanBeMoved(this, Link->Dir)){
							Game->PlaySound(SFX_MOVING_CIRCLES_MOVE);
							movedir=Link->Dir;
							movecounter = 16;
						}
					}
				}
			}
			else{
				NoAction();
				movecounter--;
				float consta = 5.625;
				if (movedir==DIR_UP)ypos-=2;
				if (movedir== DIR_DOWN)ypos+=2;
				if (movedir==DIR_LEFT)xpos-=2;
				if (movedir==DIR_RIGHT)xpos+=2;
				if (rotdir==1) angle -= consta;
				else angle += consta;
				if (movecounter==0){
					pos = ComboAt (xpos+1, ypos+1);
					this->InitD[0]=pos;
					if (rotdir==1)dir = RotDir(dir, -2);
					else dir = RotDir(dir, 2);
					this->InitD[1] = dir;
					if (angle>360) angle-=360;
					if (angle<0) angle+=360;
					if ((ice>0)&&(EdgeMatchMoverCanBeMoved(this, movedir))) movecounter=16;
					else{
						Game->PlaySound(SFX_MOVING_CIRCLES_STOP);
						bool secret = true;
						for (int j=1;j<=33;j++){
							if (!secret) break;
							if (j==33){
								Game->PlaySound(SFX_SECRET);
								Screen->TriggerSecrets();
								Screen->State[ST_SECRET]=true;
								break;
							}
							ffc n = Screen->LoadFFC(j);
							if (n->Script != scr) continue;
							if(n->InitD[2]!=n->InitD[0]) break;
							if(n->InitD[3]!=n->InitD[1]) break; 
						}
					}
				}
			}
			Screen->DrawCombo(2, xpos, ypos,CMB_MOVING_ROTCIRCLE, 2, 2, CSET_MOVING_ROTCIRCLE, -1, -1, xpos, ypos, angle, 0, 0,true, OP_OPAQUE);
			Waitframe();
		}
	}
}

bool EdgeMatchMoverCanBeMoved(ffc f, int dir){
	int str[] = "MovingEdgeMatcher";
	int scr = Game->GetFFCScript(str);
	int pos = f->InitD[0];
	int adj = AdjacentComboFix(pos, dir);
	if (!ComboFI(adj,CF_MOVING_CIRCLES_PATH)){
		Game->PlaySound(SFX_MOVING_CIRCLES_CANTMOVE);
		return false;
	}
	adj = AdjacentComboFix(adj, dir);
	for (int i=1;i<=33;i++){
		if (i==33) return true;
		ffc n = Screen->LoadFFC(i);
		if (n->Script!=scr) continue;
		if (n->InitD[0]==adj){
			Game->PlaySound(SFX_MOVING_CIRCLES_CANTMOVE);
			return false;
		}
	}
}

//Fixed variant of AdjacentCombo function from std_extension.zh
int AdjacentComboFix(int cmb, int dir)
{
	int combooffsets[13]={-0x10, 0x10, -1, 1, -0x11, -0x0F, 0x0F, 0x11};
	if ( cmb % 16 == 0 ) combooffsets[9] = -1;//if it's the left edge
	if ( (cmb % 16) == 15 ) combooffsets[10] = -1; //if it's the right edge
	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]==-1 && ( dir == DIR_LEFT || dir == DIR_LEFTUP || dir == DIR_LEFTDOWN ) ) return -1; //if the left columb
	if ( combooffsets[10]==-1 && ( dir == DIR_RIGHT || dir == DIR_RIGHTUP || dir == DIR_RIGHTDOWN ) ) return -1; //if the right column
	if ( combooffsets[11]==-1 && ( dir == DIR_UP || dir == DIR_RIGHTUP || dir == DIR_LEFTUP ) ) return -1; //if the top row
	if ( combooffsets[12]==-1 && ( dir == DIR_DOWN || dir == DIR_RIGHTDOWN || dir == DIR_LEFTDOWN ) ) return -1; //if the bottom row
	if ( cmb >= 0 && cmb < 176 ) return cmb + combooffsets[dir];
	else return -1;
}

int RotDir(int dir, int num){
	int dirs[8] = {DIR_UP, DIR_RIGHTUP, DIR_RIGHT, DIR_RIGHTDOWN, DIR_DOWN, DIR_LEFTDOWN, DIR_LEFT, DIR_LEFTUP};
	int idx=-1;
	for (int i=0; i<8; i++){
		//Trace(dirs[i]);
		if (dirs[i] == dir){
			idx=i;
			break;
		}
	}
	if (idx<0) return -1;
	idx+=num;
	while (idx<0) idx+=8;
	while (idx>=8) idx-=8;
	return dirs[idx];
}