//import "chess.zh" //REQUIRED
const int SFX_LIGHTSOUT_PUZZLE_MOVE = 16; //Sound to play when making move.
const int SFX_LIGHTSOUT_PUZZLE_SOLVED = 27; //Sound to play when puzzle is solved.
//ZC adaptation of Lights Out puzzle. Can you turn off those nasty lights?
//Stand on a light combo and press A. This light and all adjacent, depending on type will change state, on, off and different levels of brightness.
// Set up a sequence of combos, for each state of light.
//Place FFC anywhere on the screen.
//D0 - unused.
//D1 - Combo for OFF light state, 1st in sequence.
// All other combos on the screen are ignored. You can build board of any shape and size, as long, as it fits the screen.
//D2 - Puzzle type
/// 0 - Normal Lights Out puzzle. Adjacent combos flick states with targrted one.
/// 1 - Flip Flop. All combos on the same horizontal and vertical lines flick states with targeted one.
/// 2 - Knights Out - All combos within knight move flick states, together with targeted one.
//D3 Number of light states.
//D4 - add together:
// 1 - Flash effect on dolving the puzzle.
// 2 - Allow solving puzzle by turning all lights ON.
// 4 - Disable internal puzzle solution trigger, allowing using external secret triggers, like Matrix Password puzzle.
// 8 - Randomize light states on puzzle startup
//Lights of different groups don`t affect each other, but all lights must either be fully On or fully Off to solve.
ffc script LightsOut{
void run (int cmb_on, int cmb_off, int type, int numstates, int flags){
if (cmb_off==0)cmb_off = this->Data;
if (numstates==0)numstates= 2;
int numlights = 0;
int flashcounter=0;
int numpuzzles = CountFFCsRunning(this->Script);
if ((flags&8)>0){
for (int i = 0; i<176; i++){
int state = Screen->ComboD[i]-cmb_off;
if (state<0)continue;
if (state>=numstates)continue;
Screen->ComboD[i]=cmb_off + Rand(numstates);
}
}
for (int i = 0; i<176; i++){
if (Screen->ComboD[i]==cmb_off+(numstates-1)){
if (Screen->State[ST_SECRET]==true) Screen->ComboD[i]=cmb_off;
numlights++;
}
if ((Screen->ComboD[i]<cmb_off+(numstates-1))&&(Screen->ComboD[i]>=cmb_off))numlights++;
}
if (Screen->State[ST_SECRET]==true) Quit();
while (true){
int cmb = ComboAt(CenterLinkX(), CenterLinkY());
if ((Screen->ComboD[cmb]<=cmb_off+(numstates-1))&&(Screen->ComboD[cmb]>=cmb_off)){
if (Link->PressEx1 && flashcounter==0){
Game->PlaySound(SFX_LIGHTSOUT_PUZZLE_MOVE);
Screen->ComboD[cmb]++;
if (Screen->ComboD[cmb]>=(cmb_off+numstates))Screen->ComboD[cmb]=cmb_off;
for (int i = 0; i<176; i++){
if (type==0){
if (LeaperMoveAdjacent(cmb,i, 0,1 )){
if ((Screen->ComboD[i]<=(cmb_off+numstates-1))&&(Screen->ComboD[i]>=cmb_off)){
Screen->ComboD[i]++;
if (Screen->ComboD[i]>=(cmb_off+numstates))Screen->ComboD[i]=cmb_off;
}
}
}
else if (type==1){
if ((OnSameRank(cmb, i))||(OnSameFile(cmb, i))){
if (cmb!=i){
if ((Screen->ComboD[i]<=(cmb_off+numstates-1))&&(Screen->ComboD[i]>=cmb_off)){
Screen->ComboD[i]++;
if (Screen->ComboD[i]>=(cmb_off+numstates))Screen->ComboD[i]=cmb_off;
}
}
}
}
else if (type==2){
if (LeaperMoveAdjacent(cmb,i, 2,1 )){
if ((Screen->ComboD[i]<=(cmb_off+numstates-1))&&(Screen->ComboD[i]>=cmb_off)){
Screen->ComboD[i]++;
if (Screen->ComboD[i]>=(cmb_off+numstates))Screen->ComboD[i]=cmb_off;
}
}
}
}
int numlightson=0;
int numlightsoff=0;
for (int i = 0; i<176; i++){
if (Screen->ComboD[i]==(cmb_off+numstates-1))numlightson++;
if (Screen->ComboD[i]==(cmb_off))numlightsoff++;
}
if (numlightsoff==numlights) this->InitD[7]=1;
else if ((numlightson==numlights) && ((flags&2)>0)) this->InitD[7]=-1;
else this->InitD[7]=0;
if ((flags&4)>0) this->InitD[7]=0;
// int str[] = "LightsOut";
// int scr = Game->GetFFCScript(str);
int numsol = 0;
for(int i=1;i<=32;i++){
ffc f = Screen->LoadFFC(i);
if (f->Script!=this->Script)continue;
numsol+=f->InitD[7];
}
if (numsol==numpuzzles){
Game->PlaySound(SFX_LIGHTSOUT_PUZZLE_SOLVED);
if ((flags&1) >0) flashcounter = 30;
Screen->TriggerSecrets();
Screen->State[ST_SECRET]=true;
if (flashcounter==0) Quit();
}
if ((numsol==(-numpuzzles)) && ((flags&2)>0)){
Game->PlaySound(SFX_LIGHTSOUT_PUZZLE_SOLVED);
if ((flags&1) >0) flashcounter = -30;
Screen->TriggerSecrets();
Screen->State[ST_SECRET]=true;
if (flashcounter==0) Quit();
}
}
}
if (flashcounter!=0){
if (flashcounter<0){
if (IsEven(flashcounter)) Screen->Rectangle(7, 0, 0, 255, 175, 1, -1, 0, 0, 0, true, OP_TRANS);
flashcounter++;
if (flashcounter>=0)Quit();
}
if (flashcounter>0){
if (IsEven(flashcounter)) Screen->Rectangle(7, 0, 0, 255, 175, 15, -1, 0, 0, 0, true, OP_TRANS);
flashcounter--;
if (flashcounter<=0)Quit();
}
}
Waitframe();
}
}
}