Copy to Clipboard Test

smartcombos.zh Code

//Places combo and replaces adjacent combos to avoid cutoff
void SmartComboPlace(int pos, int origcmb){
	if((Screen->ComboD[pos]>=origcmb)&&(Screen->ComboD[pos]<(origcmb+16)))return;
	int dircs=0;
	for (int i=0;i<4;i++){
		int adjcmb = AdjacentComboSmart(pos, i);
		if (Screen->ComboD[adjcmb]<origcmb)continue;
		if (Screen->ComboD[adjcmb]>(origcmb+15))continue;
		int adjdirs = Screen->ComboD[adjcmb] - origcmb;
		adjdirs += (1<<(OppositeDir(i)));
		Screen->ComboD[adjcmb]=origcmb+adjdirs;
		dircs+= (1<<i);
	}
	Screen->ComboD[pos]=origcmb+dircs;
}

//Erase combo and replaces adjacent combos to avoid cutoff
void SmartComboErase(int pos, int origcmb, int ucmb){
	if (Screen->ComboD[pos]==ucmb) return;
	int dircs=0;
	for (int i=0;i<4;i++){
		int adjcmb = AdjacentComboSmart(pos, i);
		if (Screen->ComboD[adjcmb]<origcmb)continue;
		if (Screen->ComboD[adjcmb]>(origcmb+15))continue;
		int adjdirs = Screen->ComboD[adjcmb] - origcmb;
		adjdirs -= (1<<(OppositeDir(i)));
		Screen->ComboD[adjcmb]=origcmb+adjdirs;
	}
	Screen->ComboD[pos]=ucmb;
}


//Fixed variant of AdjacentCombo function from std_extension.zh
int AdjacentComboSmart(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;
}

//Ex1-Place, Ex2-Erase
ffc script SmartComboTest{
	void run(){
		int origcmb=this->Data;
		int net[176];
		int node = ComboAt(CenterX(this),CenterY(this));
		while(true){
			int cmb = ComboAt (CenterLinkX(), CenterLinkY());
			if (!ComboFI(cmb,CF_NOBLOCKS)){
				if (Link->PressEx1)SmartComboPlace(cmb, origcmb);
				if (Link->PressEx2)SmartComboErase(cmb, origcmb, Screen->UnderCombo);
			}
			SmartCombos_LoadNetwork(net, node, origcmb);
			for (int i=0;i<176;i++){
				if (net[i]>0)Screen->ComboC[i]=5;
				else Screen->ComboC[i]=2;
			}
			Waitframe();
		}
	}
}

//Loads/updates connected network of combos, starting from given position into buffer (176 minimum)
void SmartCombos_LoadNetwork(int net, int node, int origcmb){
	for (int i=0;i<176;i++){
		net[i]=0;
	}
	net[node]=1;
	int dirstate[176];	
	for (int i=0;i<176;i++){
		if (Screen->ComboD[i]<origcmb)dirstate[i]=-1;
		else if (Screen->ComboD[i]>(origcmb+15))dirstate[i]=-1;
		else dirstate[i]=Screen->ComboD[i] - origcmb;
		//Screen->DrawInteger(2, ComboX(i), ComboY(i), 0,1,0, -1, -1, dirstate[i],0 , OP_OPAQUE);
	}
	SmartCombos_RunNetwork(net, node, dirstate);
}

//Credit goes to Moosh for path checking procedure.
void SmartCombos_RunNetwork(int net, int node, int dirstate){
	int dir = -1;
	int pos = -1;	
	for (int i=0;i<4;i++){
		if ((dirstate[node]&(1<<i))>0){
			pos = AdjacentComboSmart(node, i);
			//if (net[pos]>0)continue;
			if (dirstate[pos]<0)continue;
			dir=i;
			while(true){
				if (net[pos]>0)break;
				if ((dirstate[pos]&(1<<OppositeDir(dir)))<=0) break;
				net[pos] = 1;
				//Trace(pos);
				if(dirstate[pos]==1111b||dirstate[pos]==0111b||dirstate[pos]==1011b||dirstate[pos]==1101b||dirstate[pos]==1110b){
					//You play a dangerous game there, Moosh...
					//Working with powers beyond your understanding...
					//Will ZScript break under the strain of the recursive functions?
					//Only time will tell...
					SmartCombos_RunNetwork(net, pos, dirstate);
					break;
				}
				if (dirstate[pos]==(1<<OppositeDir(dir))) break;// Capped dead end reached.
				dir = SmFindNextDir(pos, dirstate, dir);
				//if (dir<0) break;
				pos = AdjacentComboSmart(pos, dir);
				if (pos<0)break;
			}
		}
	}
}


//Finds the next direction in a node with two or less directions
int SmFindNextDir(int node, int dirState, int lastDir){
	for(int i=0; i<4; i++){
		if(i!=OppositeDir(lastDir)){
			if(dirState[node]&(1<<i)){
				return i;
			}
		}
	}
	return lastDir;
}

//Returns true, if all nodes in the given array are all connected
bool SmartCombos_NodesConnected(int nodes, int origcmb){
	int net[176];
	SmartCombos_LoadNetwork(net, nodes[0], origcmb);
	for (int i=0; i<SizeOfArray(nodes);i++){
		int n = nodes[i];
		if (net[n]==0) return false;
	}
	return true;
}

//Connects all smart combos, thus fixing cutoff. Has option for separate CSets
void ConnectDirectionalCombos(int origcmb, bool color){
	int dirstate[176];
	for (int i=1; i<176; i++){
		if (Screen->ComboD[i]<origcmb)dirstate[i]=-1;
		else if (Screen->ComboD[i]>(origcmb+15))dirstate[i]=-1;
		else{
			dirstate[i]=0;
			for (int d=0;d<4;d++){
				int adjcmb = AdjacentComboSmart(i, d);
				if (Screen->ComboD[adjcmb]<origcmb)continue;
				if (Screen->ComboD[i]>(origcmb+15))continue;
				if (color){
					if (Screen->ComboC[adjcmb]!= Screen->ComboC[i]) continue;
				}
				dirstate[i]+=(1<<d);
			}
		}
	}
	for (int i=1; i<176; i++){
		if (dirstate[i]>=0) Screen->ComboD[i]=origcmb+dirstate[i];
	}
}

//Debug function that renders connections between combos.
void SmartCombos_Debug_DrawDirstate(int dirstate, int origcmb, int minuscmb, int cset){
	for (int i=1; i<176; i++){
		int state = dirstate[i];
		if (state<0) Screen->FastCombo(7, ComboX(state), ComboY(state), minuscmb, cset, OP_TRANS);
		else Screen->FastCombo(7, ComboX(state), ComboY(state), origcmb+dirstate[i], cset, OP_TRANS);
	}
}