Rem Symbols Shift
Rem November 2014
Rem With RFO Basic!
Rem Version 1.02
Rem By Roy
Rem

console.title"Symbol Shift"
Rem Open Graphics
di_width = 1280 % set to my tablet
di_height = 800

gr.open 255,0,0,0 % Black
gr.orientation 0
pause 1000
gr.screen screenWidth,screenHeight
scale_x=screenWidth/di_width
scale_y=screenHeight/di_height
gr.scale scale_x,scale_y
gr.text.size 30
wakelock 3

Rem Globel Vars
score=0
movesLeft=50
soundOnOff=1
dim info[4]
info[1]=score 
!info[2] will whole the best score
info[3]=movesLeft
info[4]=soundOnOff
dim symbols[9]
dim symbolShift[1]
dim blown[6]
dim arrows[4]
dim board[8,8]
dim toModify[8,8]
dim upDate[3]
dim sound[3]

Rem Start of Functions

fn.def LoadSounds(sound[])
	Soundpool.open 1
	Soundpool.load sound[1],"falling.wav"
	Soundpool.load sound[2],"slider.wav"
	Soundpool.load sound[3],"blowup.wav"
fn.end

fn.def SaveBestScore(info[])
	BestScorePath$="../../SymbolShift/data/"
	file.exists BestPresent,BestScorePath$+"BestScore.tst"
	if BestPresent then
		text.open w,hs,BestScorePath$+"BestScore.tst"
			text.writeln hs,int$(info[2])
		text.close hs
	else
		file.mkdir BestScorePath$
		text.open w,hs,BestScorePath$+"BestScore.tst"
			text.writeln hs,int$(info[2])
		text.close hs
	endif
fn.end

fn.def LoadBestScore(info[])
	BestScorePath$="../../SymbolShift/data/"
	file.exists BestPresent,BestScorePath$+"BestScore.tst"
	if BestPresent then
		text.open r,hs,BestScorePath$+"BestScore.tst"
			text.readln hs,bs$
			info[2]=val(bs$)
		text.close hs
	else
		info[2]=0
	endif
fn.end

fn.def LoadImages(symbols[],blown[],arrows[],symbolShift[])
	for x=1 to 9
		gr.bitmap.load symbols[x], "symbol0"+int$(x)+".jpg"
		gr.bitmap.scale symbols[x], symbols[x], 75,75
	next
	for x=1 to 6 
		gr.bitmap.load blown[x],"blow0"+int$(x)+".png"
		gr.bitmap.scale blown[x],blown[x],75,75
	next
	for x=1 to 4 
		gr.bitmap.load arrows[x],"arrow0"+int$(x)+".gif" 
		gr.bitmap.scale arrows[x],arrows[x],50,50 
	next
	gr.bitmap.load symbolShift[1],"ss.jpg" 
	gr.bitmap.scale symbolShift[1],symbolShift[1],100,150
fn.end

fn.def CurvyWindow(x,y,l,h,c)
	call Gcol(c,1)
	gr.rect r,x,y+25,l,h-25 
	gr.rect r,x+25,y,l-25,h 
	gr.circle c, x+25,y+25,25 
	gr.circle c,l-25,y+25,25 
	gr.circle c,x+25,h-25,25
	gr.circle c,l-25,h-25,25
	gr.render
fn.end

fn.def LoadBoard(board[])
	Rem do until there is not three in a row. Left to right or Top to bottom
	do
	for y=1 to 8 
		for x=1 to 8
			s=int(8 * rnd()+1)
			board[x,y]=s
		next
	next
	until LessThenThree(board[])
	
fn.end

fn.def LessThenThree(board[])
	flag=1
	Rem Look left to right
	for y=1 to 8 
		for x=1 to 6 
			if board[x,y]=board[x+1,y] & board[x,y]=board[x+2,y] then flag=0
		next
	next
	Rem Look top to bottom
	for x=1 to 8 
		for y=1 to 6 
			if board[x,y]=board[x,y+1] & board[x,y]=board[x,y+2] then flag=0
		next
	next
	
	fn.rtn flag

fn.end

fn.def DrawBoard(board[],symbols[],arrows[],symbolShift[],toModify[])
	gr.cls
	call CurvyWindow(1,1,1280,800,8)
	call CurvyWindow(3,3,1277,797,2)
	gr.set.stroke 2
	call Gcol(7,1)
	gr.rect r,80,80,720,720
	
	call Gcol(8,1)
	gr.line l,80,80,720,720
	gr.line l, 720,80,80,720
	
	call Gcol(8,1)
	gr.rect r,100,100,700,700
	
	call Gcol(0,0)
	gr.rect r,100,100,700,700
	
	call DrawMenu()	
	
	Rem Show Arrows
	call Gcol(0,1)
	for arrow=100 to 550 step 150
		gr.bitmap.draw d,arrows[3],arrow+15,30 %Top Arrows
		gr.bitmap.draw d,arrows[4],arrow+90,720 %Botom Arrows
		
		gr.bitmap.draw d,arrows[2],30,arrow+85 %Left Arrows
		gr.bitmap.draw d,arrows[1],720,arrow+15 %Right Arrows
	next
	gr.bitmap.draw d,symbolShift[1],975,280
	gr.render
	Rem Show Symbols
	call DisplaySymbolsFirstTime(board[],symbols[],toModify[])
fn.end

fn.def DrawMenu()
	call Gcol(7,1)
	gr.rect r, 880,80,1170,720 
	call Gcol(8,1)
	gr.line l,880,80,900,100 
	gr.line l,880,720,900,700 
	gr.line l,1170,80,1150,100 
	gr.line l,1170,720,1150,700 
	call Gcol(8,1)
	gr.rect r,900,100,1150,700 
	call Gcol(0,0)
	gr.rect r,900,100,1150,700 
	
	Rem Menu Buttons
	array.load menu$[],"Sound","New Game","Help","Exit"
	m=1
	gr.text.align 2
	for y=450 to 660 step 60
		call CurvyWindow(908,y-2,1142,y+52,0)
		call CurvyWindow(910,y,1140,y+50,4)
		call Gcol(0,1)
		gr.text.draw d,1025,y+35,menu$[m]
		m++
	next
	array.delete menu$[]
	call Gcol(2,1)
	gr.circle c, 1100,475,15 % sound on Green off Red
	gr.text.align 1
	gr.render
fn.end

fn.def DisplaySymbolsFirstTime(board[],symbols[],toModify[])
	bx=1 
	by=1
	for y=100 to 675 step 75
		for x=100 to 675 step 75 
			gr.bitmap.draw toModify[bx,by],symbols[board[bx,by]],x,y % Show symbols
			bx++
		next
		bx=1 
		by++
	next
	gr.render
fn.end

fn.def DisplaySymbols(board[],symbols[],toModify[])
	for y=1 to 8
		for x=1 to 8
			gr.modify toModify[x,y],"bitmap",symbols[board[x,y]]
		next
	next
	gr.render
fn.end

fn.def BlownSymbolsHorizontal(blown[],xx,yy,c,b,toModify[])
	bx=1 
	by=1
	for y=100 to 675 step 75
		flag=0
		for x=100 to 675 step 75 
			if by<>yy then f_n.break
			if bx>=xx & bx <= xx+c then
				gr.modify toModify[bx,by],"bitmap",blown[b]
				flag=1
			endif
			bx++
		next
		if flag then gr.render
		bx=1 
		by++
	next
fn.end

fn.def BlownSymbolsVertical(blown[],board[],xx,yy,c,b,toModify[])
	bx=1 
	by=1
	for x=100 to 675 step 75
		flag=0
		for y=100 to 675 step 75 
			if bx<>xx then f_n.break
			if by>=yy & by <= yy+c then
				gr.modify toModify[bx,by],"bitmap",blown[b]
				if b=5 then board[bx,by]=9
				flag=1
			endif
			by++
		next
		if flag then gr.render
		by=1 
		bx++
	next
fn.end

fn.def DisplayInfo(upDate[],info[])
	gr.text.align 2
	call Gcol(0,1)
	x=1025
	gr.text.draw upDate[1],x,150,"Score:"+int$(info[1])
	gr.text.draw upDate[2],x,200,"Best:"+int$(info[2])
	gr.text.draw upDate[3],x,250,"Moves Left:"+int$(info[3])
	gr.text.align 1
	gr.render
fn.end

fn.def UpDateInfo(upDate[],info[])
	gr.modify upDate[1],"text","Score:"+int$(info[1])
	gr.modify upDate[2],"text","Best:"+int$(info[2])
	gr.modify upDate[3],"text","Moves Left:"+int$(info[3])
	gr.render % Do not Forget
fn.end

fn.def Gcol(c,g)
	Rem g=0 Outline and g=1 Fill
	if c=0 then gr.color 255,0,0,0,g % black
	if c=1 then gr.color 255,255,0,0,g % Red
	if c=2 then gr.color 255,0,255,0,g % green
	if c=3 then gr.color 255,0,0,255,g % blue
	if c=4 then gr.color 255,255,255,0,g % yellow
	if c=5 then gr.color 255,0,255,255,g % cyan
	if c=6 then gr.color 255,255,0,255,g % magenta
	if c=7 then gr.color 255,192,192,192,g % gray
	if c=8 then gr.color 255,255,255,255,g % white
fn.end

fn.def GetTouch(tx,ty)
	do
		gr.touch touched,tx,ty 
	until touched
	do
		gr.touch touched,tx,ty 
	until !touched
fn.end

fn.def ToddleSound(info[])
	if info[4]=1 then 
		info[4]=0 
		call Gcol(1,1)
		gr.circle c, 1100,475,15 % sound off Red
	else 
		info[4]=1 
		call Gcol(2,1)
		gr.circle c, 1100,475,15 % sound on Green
	endif
	gr.render
fn.end

fn.def NewGame(upDate[],info[],board[],symbols[],dis,toModify[])
	do
		if info[3]=0 then
			Dialog.Message "New Game:", "No Moves Left. Start a New Game", yn, "Yes","No"
		else
			Dialog.Message "New Game:", "Start a New Game", yn, "Yes","No"
		endif
		if yn=0 then tone 300,300
	until yn=1 | yn=2
		
		if info[1]>info[2] & yn = 1 | info[1]>info[2] & dis then 
			info[2]=info[1]
			b$=int$(info[2])
			call UpDateInfo(upDate[],info[])
			call SaveBestScore(info[])
			Dialog.Message "New Best:", b$  + " Is a new Best Score. Well Done!!", ok, "OK"
		endif
	if yn=1 then 
		info[1]=0 
		info[3]=50 % Reset moves left
		call LoadBoard(board[])
		call DisplaySymbols(board[],symbols[],toModify[])
		call UpDateInfo(upDate[],info[])
	endif
	fn.rtn yn
fn.end

fn.def Help()
	p$=chr$(10)+chr$(10) % Do a paragraph brake
	do
		Dialog.Message "Help:",~
		"Use the arrows to shift the symbols" + ~
		" left, right, up or down, so that" + ~
		" you line up three or more of the" + ~ 
		" same symbol in a row or column." + p$ + ~
		"Lining three symbols up scores 9, four" + ~
        " scores 16 and five scores 25." + p$ + ~
		"Somtimes you can start off a chain" + ~
		" reaction and blow up many symbols." + p$ + ~
		"Get the highest score you can in 50 moves" + p$ + ~
		"Matching symbols diagonally does not count.", ~
		ok, "OK"
		if ok=0 then tone 300,300
	until ok=1
fn.end

fn.def GameExit(upDate[],info[])
	do
		Dialog.Message "Exit:", "Are you sure you want to leave Symbol Shift", yn, "Yes","No"
		if yn=0 then tone 300,300
	until yn=1 | yn=2
	if yn=1 then 
		if info[1]>info[2] & yn = 1 | info[1]>info[2] & dis then 
			info[2]=info[1]
			b$=int$(info[2])
			call UpDateInfo(upDate[],info[])
			call SaveBestScore(info[])
			Dialog.Message "New Best:", b$  + " Is a new Best Score. Well Done!!", ok, "OK"
		endif
		wakelock 5
		soundpool.release
		call Goodbye()
		gr.close
		exit
	endif
fn.end

fn.def Goodbye()
	gr.text.size 70
	call CurvyWindow(200,200,1080,600,0)
	call CurvyWindow(220,220,1060,580,4)
	call ThreeDtext(0,1,350,300,"Thanks for playing")
	call ThreeDtext(0,1,420,400,"Symbol Shift")
	call ThreeDtext(0,1,480,500,"Goodbye")
	gr.render
	pause 5000
fn.end

fn.def ThreeDtext(c1,c2,x,y,t$)
	gr.text.bold 1
	call Gcol(c1,1)
	gr.text.draw d,x,y,t$
	call Gcol(c2,1)
	gr.text.draw d,x+2,y-2,t$
	gr.text.bold 0
	gr.render
fn.end

fn.def Beep(p,d)
	tone p,d 
fn.end

fn.def ThreeOrMore(upDate[],info[],blown[],symbols[],board[],sound[],toModify[])
	do
		Rem Look Horizontal
		flag=0
		for y=1 to 8
			for x=1 to 6 
				c=1
				temp=board[x,y]
				for f=x+1 to 8
					if board[f,y]=temp then
						c++
					else
						f_n.break
					endif
				next
				if c>2 then
					flag=1
					if info[4]=1 then Soundpool.play s,sound[3],0.99,0.99,1,0,1
					call DropHorizontal(blown[],symbols[],board[],x,y,c-1,sound[],info[],toModify[])
					info[1]+=c*c
					call UpDateInfo(upDate[],info[])
				endif
				if flag then f_n.break
			next
			if flag then f_n.break
		next

		Rem Look Vertical
		for x=1 to 8
			for y=1 to 6 
				c=1
				temp=board[x,y]
				for f=y+1 to 8
					if board[x,f]=temp then
						c++
					else
						f_n.break
					endif
				next
				if c>2 then
					flag=1
					if info[4]=1 then Soundpool.play s,sound[3],0.99,0.99,1,0,1
					call DropVertical(blown[],symbols[],board[],x,y,c-1,sound[],info[],toModify[])
					info[1]+=c*c
					call UpDateInfo(upDate[],info[])
				endif
				if flag then f_n.break
			next
			if flag then f_n.break
		next

	until !flag
fn.end

fn.def DropVertical(blown[],symbols[],board[],x,y,c,sound[],info[],toModify[])
	for b=1 to 6 step 2
		call BlownSymbolsVertical(blown[],board[],x,y,c,b,toModify[])
	next
	if info[4]=1 then Soundpool.play s,sound[1],0.99,0.99,1,0,1
	Rem Drop down from above
	s=y+c 
	for d=y to s 
		for yy=d to 2 step - 1 
			board[x,yy]=board[x,yy-1] 
			board[x,yy-1]=9 % blank
		next
		call DisplaySymbols(board[],symbols[],toModify[])
	next

	Rem fill from top
	for yy=1+c to 1 step - 1
		s=int(8 * rnd()+1)
		board[x,yy]=s
		call DisplaySymbols(board[],symbols[],toModify[])
	next
	
fn.end

fn.def DropHorizontal(blown[],symbols[],board[],x,y,c,sound[],info[],toModify[])
	for b=1 to 6 step 2
		call BlownSymbolsHorizontal(blown[],x,y,c,b,toModify[])
	next
	if info[4]=1 then Soundpool.play s,sound[1],0.99,0.99,1,0,1
	Rem Drop down
	for yy=y to 2 step - 1
		for xx=x to x+c 
			board[xx,yy]=board[xx,yy-1]
		next
		call DisplaySymbols(board[],symbols[],toModify[])
		!pause 10
	next
	Rem Fill to row
	for xx=x to x+c 
		s=int(8 * rnd()+1)
		board[xx,1]=s
	next
	call DisplaySymbols(board[],symbols[],toModify[])
	
fn.end

fn.def TopArrows(top,symbols[],board[])
	top=val(mid$("1357",top,1))
	temp=board[top,8]
	for y=8 to 2 step - 1 
		board[top,y]=board[top,y-1]
	next
	board[top,1]=temp
	fn.rtn 1
fn.end

fn.def BottomArrows(bottom,symbols[],board[])
	bottom*=2
	temp=board[bottom,1]
	for y=1 to 7
		board[bottom,y]=board[bottom,y+1]
	next
	board[bottom,8]=temp
	fn.rtn 1
fn.end

fn.def LeftArrows(left,symbols[],board[])
	left*=2
	temp=board[8,left]
	for x=8 to 2 step - 1 
		board[x,left]=board[x-1,left]
	next
	board[1,left]=temp
	fn.rtn 1
fn.end

fn.def RightArrows(right,symbols[],board[])
	right=val(mid$("1357",right,1))
	temp=board[1,right]
	for x=1 to 7
		board[x,right]=board[x+1,right]
	next
	board[8,right]=temp
	fn.rtn 1
fn.end

fn.def MenuLook(tx,ty,scale_x,scale_y,upDate[],info[],board[],symbols[],toModify[])
	flag=0 
	if tx>900*scale_x & ty>450*scale_y & tx<1150*scale_x & ty<680*scale_y then flag=1 % Menu has been tapped
	if tx>900*scale_x & ty>450*scale_y & tx<1150*scale_x & ty<500 * scale_y then call ToddleSound(info[])
	if tx>900*scale_x & ty>510*scale_y & tx<1150*scale_x & ty<560 * scale_y then call NewGame(upDate[],info[],board[],symbols[],0,toModify[])
	if tx>900*scale_x & ty>570*scale_y & tx<1150*scale_x & ty<620 * scale_y then call Help()
	if tx>900*scale_x & ty>630*scale_y & tx<1150*scale_x & ty<680 * scale_y then call GameExit(upDate[],info[])
	fn.rtn flag
fn.end

fn.def ProcessTouch(tx,ty,upDate[],info[],scale_x,scale_y,symbols[],board[],sound[],toModify[])
	flag = 0
	flag = MenuLook(tx,ty,scale_x,scale_y,upDate[],info[],board[],symbols[],toModify[])

	if !flag then
		touchedArrow=1
		for arrow=100 to 550 step 150
			if tx>arrow * scale_x & ty>0 * scale_y & tx<(arrow+100)*scale_x & ty<80*scale_y then flag = TopArrows(touchedArrow,symbols[],board[])
			if tx>(arrow+80) * scale_x & ty>700 * scale_y & tx<(arrow+180)*scale_x & ty<800*scale_y then flag = BottomArrows(touchedArrow,symbols[],board[])
			
			if tx>0 * scale_x & ty>(arrow+50) * scale_y & tx<100*scale_x & ty<(arrow+150)*scale_y then flag = LeftArrows(touchedArrow,symbols[],board[])
			if tx>700 * scale_x & ty>(arrow-20) * scale_y & tx<800*scale_x & ty<(arrow+80)*scale_y then flag = RightArrows(touchedArrow,symbols[],board[])
			if flag then f_n.break
			touchedArrow++
		next
		if flag = 1 then
			
			call DisplaySymbols(board[],symbols[],toModify[])
			if info[4] then Soundpool.play s,sound[2],0.99,0.99,1,0,1 % call Beep(500,100)
			info[3]--
			call UpDateInfo(upDate[],info[])
		endif
	endif

	fn.rtn flag
fn.end

fn.def PlayGame(upDate[],info[],scale_x,scale_y,blown[],symbols[],board[],sound[],toModify[])
	do
		flag=0
		tx=0 
		ty=0	
		call GetTouch(&tx,&ty)
		flag = ProcessTouch(tx,ty,upDate[],info[],scale_x,scale_y,symbols[],board[],sound[],toModify[])
		if flag then ThreeOrMore(upDate[],info[],blown[],symbols[],board[],sound[],toModify[])
	until info[3]=0 % no moves left
fn.end

fn.def CatchBackKey(upDate[],info[])
	do
	Dialog.Message "Exit:", "Are you sure you want to leave Symbol Shift", yn, "Yes","No"
		if yn=0 then tone 400,400
	until yn=1 | yn=2

	if yn=1 then
		if info[1]>info[2] then 
			info[2]=info[1]
			b$=int$(info[2])
			call UpDateInfo(upDate[],info[])
			call SaveBestScore(info[])
			Dialog.Message "New Best:", b$  + " Is a new Best Score. Well Done!!", ok, "OK"
		endif
		call Goodbye()
	endif
	fn.rtn yn
fn.end

Rem End of Functions

Rem Main
call LoadSounds(sound[])
call LoadImages(symbols[],blown[],arrows[],symbolShift[])
call LoadBoard(board[])
call DrawBoard(board[],symbols[],arrows[],symbolShift[],toModify[])
call LoadBestScore(info[])
call DisplayInfo(upDate[],info[])

do
	call PlayGame(upDate[],info[],scale_x,scale_y,blown[],symbols[],board[],sound[],toModify[])
until NewGame(upDate[],info[],board[],symbols[],1,toModify[])=2 % 2 = No button

call Goodbye()
wakelock 5
soundpool.release
exit

onBackKey:
yesNo = CatchBackKey(upDate[],info[])
if yesNo = 2 then back.resume % No button

wakelock 5
soundpool.release

exit
