Copy to Clipboard Test

MasterMind puzzle Code

const int CSET_MASTERMIND_SOLVED = 5;//CSet used to paint combination on success
const int CSET_MASTERMIND_FAIL = 10;//CSet used to render combination on failure
const int CSET_MASTERMIND_INPUT = 11;//CSet used to render guesses

const int CMB_MASTERMIND_CURSOR = 2991;//Combo used to render cursor
const int CSET_MASTERMIND_CURSOR = 7;//CSet used to render cursor

const int TILE_MASTERMIND_FRAME = 17057;//Tile used to render prompt frame with instructions, along with combo underneath Link. 0 for no prompt drawing.
const int CSET_MASTERMIND_FRAME = 7;//Cset used to render frame.

const int STR_MASTERMIND_INVALID_GUESS = 15;//String to display when attempting to input guess with forbidden duplicate symbols.
const int SFX_MASTERMIND_INVALID_GUESS = 10;//Sound to play when attempting to input guess with forbidden duplicate symbols.

const int SFX_MASTERMIND_FAIL = 3;//Sound to play on game loss
const int SFX_MASTERMIND_INPUT = 16;////Sound to play on making guess

const int FONT_MASTERMIND = 0;//Font used to render hint outputs ("bulls and cows")

//Mastermind - Bulls and Cows logic guessing game.

//You are given a set of rows with cursor at bottom left corner. A password is needed to be cracked open by making guesses. On each guess, one "bull" is rendered for each digit that is in correct place and one "cow" is rendered for each digit that exists in password, but not in correct position. After each guess cursor moves upwards. If it runs out of room (input area is solid or flagged with CF_NOBLOCKS), you lose the game.
//Stand on numbers to right of cursor, then press Ex1 and Ex3 to change input, then press Ex2 to confirm guess. You get 2 numbers, left one is Bulls, right one is Cows.


//1. Set up sequence of consecutive combos for "alphabet", like numbers 0-9;
//2. Build puzzle area. It`s rectangle full of non-solid floor with width equal to number of digits plus 2 positions to render output, and height equal to number of attempts allowed. Put solid combos above puzzle area.
//3.Place invisible FFC with sript and combo of 1st combo from step 1 at bottom left corner of puzzle area.
// D0 - number of digits/elements in password
// D1 - number of different elements/digits that can be in password.
// D2 - >0 - allow duplicates in guesses and password.

ffc script MasterMind{
	void run (int numsymbols, int alphabetsize, int allowdupes){
		int arr_target[16];
		int arr_input[16];
		int arr_guess[16];
		int bullhistory[16];
		int cowhistory[16];
		
		for (int i=0;i<16;i++){
			arr_target[i]=-1;
			arr_input[i]=-1;
			arr_guess[i]=i;
			bullhistory[i]=-1;
			cowhistory[i]=-1;
		}
		
		int attempt = 0;
		int origx = this->X;
		int origy = this->Y;
		int cmb=-1;
		int pos = ComboAt (CenterX(this)+1, CenterY(this)+1);
		int indexarr = 0;
		MastermindShuffleArray(arr_guess);
		
		for (int i=0;i<numsymbols;i++){
			arr_input[i]=0;
			Screen->ComboD[pos+i]=this->Data;
			if (allowdupes) arr_target[i]=Rand(alphabetsize);
			else{
				while(arr_guess[indexarr]>=alphabetsize)indexarr++;
				arr_target[i]=arr_guess[indexarr];
				indexarr++;
			}
		}
		
		while(true){
			cmb = ComboAt (CenterLinkX(), CenterLinkY());
			indexarr = cmb-pos;
			if (indexarr>=0 && indexarr<numsymbols){
				if (TILE_MASTERMIND_FRAME>0){
					MASTERMINDDrawFrame(5, TILE_MASTERMIND_FRAME, Link->X-16, Link->Y-48, 3, 3, CSET_MASTERMIND_FRAME, OP_OPAQUE);
					Screen->FastCombo(5, Link->X, Link->Y-32, Screen->ComboD[cmb], Screen->ComboC[cmb], OP_OPAQUE);
				}
				if (Link->PressEx1){
					Game->PlaySound(SFX_MASTERMIND_INPUT);
					Screen->ComboD[cmb]++;
					arr_input[indexarr]++;
					if (arr_input[indexarr]>=alphabetsize){
						Screen->ComboD[cmb]=this->Data;
						arr_input[indexarr]=0;
					}
				}
				if (Link->PressEx3){
					Game->PlaySound(SFX_MASTERMIND_INPUT);
					Screen->ComboD[cmb]--;
					arr_input[indexarr]--;
					if (arr_input[indexarr]<0){
						Screen->ComboD[cmb]=this->Data+alphabetsize-1;
						arr_input[indexarr]=alphabetsize-1;
					}
				}
				if (Link->PressEx2){
					if (Mastermind_IsValidInput(arr_input,numsymbols, allowdupes>0)){
						Game->PlaySound(SFX_MASTERMIND_INPUT);
						bullhistory[attempt]=0;
						cowhistory[attempt]=0;
						for (int i=0;i<numsymbols;i++){
							arr_guess[i]=arr_target[i];
						}
						for (int i=0;i<numsymbols;i++){
							indexarr = MastermindArrayMatch(arr_input, arr_guess[i]);
							if (indexarr<0)continue;
							if (arr_guess[i]==arr_input[i]){
								bullhistory[attempt]++;
								arr_input[i]=-1;
							}
							else{
								cowhistory[attempt]++;
								arr_input[indexarr]=-1;
							}
						}
						if (bullhistory[attempt]>=numsymbols){
							for (int i=0;i<numsymbols;i++){
								Screen->ComboC[pos+i] = CSET_MASTERMIND_SOLVED;
							}
							Game->PlaySound(SFX_SECRET);
							Screen->TriggerSecrets();
							Screen->State[ST_SECRET]=true;
							Quit();
						}
						else{
							for (int i=0;i<numsymbols;i++){
								Screen->ComboC[pos+i] = CSET_MASTERMIND_INPUT;
							}							
							this->Y-=16;
							pos = ComboAt (CenterX(this)+1, CenterY(this)+1);
							if (Screen->ComboS[pos]>0||ComboFI(pos,CF_NOBLOCKS)){
								Game->PlaySound(SFX_MASTERMIND_FAIL);
								for (int i=0;i<numsymbols;i++){
									Screen->ComboC[pos+i] = CSET_MASTERMIND_FAIL;
									Screen->ComboD[pos+i] = this->Data+arr_target[i];
								}
								Quit();
							}
							attempt++;
							for (int i=0;i<numsymbols;i++){
								arr_input[i]=0;
								Screen->ComboD[pos+i]=this->Data;
							}
						}
					}
					else{
						Game->PlaySound(SFX_MASTERMIND_INVALID_GUESS);
						if (STR_MASTERMIND_INVALID_GUESS>0) Screen->Message(STR_MASTERMIND_INVALID_GUESS);
					}
				}
			}
			for (int i=0;i<16;i++){
				if (bullhistory[i]<0)continue;
				Screen->DrawInteger(2, this->X+16*numsymbols, origy-16*i,FONT_MASTERMIND, 1,0 , -1, -1, bullhistory[i], 0, OP_OPAQUE);
				Screen->DrawInteger(2, this->X+16*numsymbols+16, origy-16*i,FONT_MASTERMIND, 1,0 , -1, -1, cowhistory[i], 0, OP_OPAQUE);
			}
			if (UsingItem(I_LENS)){
				for (int i=0;i<numsymbols;i++){
					Screen->FastCombo(2, this->X+16*i, this->Y, this->Data+arr_target[i], this->CSet, OP_OPAQUE);
				}
			}
			Screen->FastCombo(2, this->X-16, this->Y, CMB_MASTERMIND_CURSOR, CSET_MASTERMIND_CURSOR, OP_OPAQUE);
			Waitframe();
		}
	}
}

bool Mastermind_IsValidInput(int arr_input, int numsymbols, bool allowdupes){
	if (allowdupes) return true;
	int f = -1;
	for (int i=0;i<numsymbols;i++){
		f = MastermindArrayMatch(arr_input, arr_input[i]);
		if (f>=0 && f!=i) return false;
	}
	return true;
}

//Returns index of the given element that exists in the given array or -1, if it does not exist.
int MastermindArrayMatch(int arr, int value){
	for (int i=0; i<SizeOfArray(arr); i++){
		if (arr[i] == value) return i;
	}
	return -1;
}

//Swaps two elements in the given array
void MastermindSwapArray(int arr, int pos1, int pos2){
	int r = arr[pos1];
	arr[pos1]=arr[pos2];
	arr[pos2]=r;
}

//Shuffles the given array like deck of playing cards
void MastermindShuffleArray(int arr){
	int size = SizeOfArray(arr)-1;
	for (int i=0; i<=size*size; i++){
		int r1 = Rand(size);
		int r2 = Rand(size);
		MastermindSwapArray(arr, r1, r2);
	}
}

void MASTERMINDDrawFrame(int layer, int tile, int posx, int posy, int sizex, int sizey, int CSet, int opacity){
	int drawx = posx;
	int drawy = posy;
	int xoffset=0;
	int yoffset=0;
	for (int w=0; w<sizex; w++){
		drawx = posx+16*w;
		xoffset=0;
		if (w>0)xoffset=1;
		if (w==sizex-1) xoffset=2;
		for (int h=0; h<sizey; h++){
			drawy = posy+16*h;
			yoffset=0;
			if (h>0)yoffset=1;
			if (h==sizey-1) yoffset=2;
			Screen->FastTile(layer, drawx, drawy, tile +xoffset+20*yoffset, CSet, opacity);
		}
	}
}