Rem Console Number Slide
Rem With RFO Basic!
Rem November 2015
Rem Version 1.00
Rem By Roy Shepherd

di_height = 1152 % set to my Device
di_width = 672

gr.open
gr.orientation 1
pause 1000
WakeLock 3

gr.screen screenWidth,screenHeight
scale_x=screenWidth/di_width
scale_y=screenHeight/di_height
gr.scale scale_x,scale_y

!-------------------------------------------------
! Setup screen for drawing.
!-------------------------------------------------
gr.bitmap.create screen, di_width, di_height
gr.bitmap.draw    nn, screen, 0, 0
gr.bitmap.drawinto.start screen

!-------------------------------------------------
! include ConLib.bas after opening graphics 
! and setting up the bitmap screen and before creating any bundles 
!-------------------------------------------------
include ConLib.bas % include 'ConLib.bas' here

!-------------------------------------------------
! Put bundle's here, after the included ConLib.bas
! 'global' bundle pointer = 2.
!-------------------------------------------------
bundle.create global % bundle pointer = 2.
bundle.put global, "Trys", 0 
bundle.put global, "Best", 0
bundle.put global, "Sound", 1
bundle.put global, "Buzz", 1
bundle.put global, "Help", ""

dim numbers[16]

gosub Functions % Let basic see the functions before they are called.

call SetUp(numbers[]) 
call DrawBoard(numbers[])
call PlayGame(numbers[])
call GoodBye()
end

onBackKey:
	call Menu(numbers[]) 
	back.resume
end

!!----------------------------------------------------------------------
 0 = Black, 1 = Grey, 2 = Silver, 3 = White, 4 = Maroon, 5 = Red, 6 = Olive, 7 = Yellow,
 8 = Green, 9 = Lime, 10 = Teal, 11 = Aqua, 12 = Navy, 13 = Blue, 14 = Purple, 
 15 = Fuchsia, 16 = Brown, 17 = Gold.
!!----------------------------------------------------------------------
Functions:
!-------------------------------------------------
! Setup the screen and load array numbers[] 
!-------------------------------------------------
fn.def SetUp(numbers[])
	call ReadHelp()
	call LoadBest()
	for x = 1 to 15
		numbers[x] = x + 9311 % UniCode Characters (1) to (15)
	next
	numbers[16] = 32 % space
fn.end

!-------------------------------------------------
! Mix array numbers[] and draw board
!-------------------------------------------------
fn.def DrawBoard(numbers[])
	Con_BackGroundName("Navy") : Con_Scroll(0)
	Con_Cls() : c = 1
	Con_ChrPerLine(20) : Con_RenderOff()
	Con_PrintAt(3,5, "Scrambling Tiles") : Con_Render()
	call box(1, 2, Con_GetMaxX(), 11, "Number Slide", "Green", "Grey")
	Con_ColourName("Yellow") : Con_ChrPerLine(10)
	call MixNumbers(numbers[])
	for y = 1 to 4 
		for x = 1 to 4 
			Con_PrintAt(x * 2,y + 1, chr$(numbers[c])) : c++
		next
	next
	bundle.put 2, "Trys", 0
	call DoTrys(0) : call DoBest(1)
	Con_RenderOn()
fn.end

!-------------------------------------------------
! Mix array numbers[] so that the puzzle can be done.
! It's no good just mixing the numbers at random.
!-------------------------------------------------
fn.def MixNumbers(numbers[])
	do
		flag = 0 : wellShuffeld = 0
		for s = 1 to 16 
			if numbers[s] = 32 then spc = s
		next
		! Look to see if legal move
		x = floor(rnd() * 4) + 1
		y = floor(rnd() * 4) + 1
		num = x 
		if y = 2 : num += 4
			elseif y = 3 : num += 8 
			elseif y = 4 : num += 12
		endif
		if x < 4 & num + 1 = spc then flag = 1
		if x > 1 & num - 1 = spc then flag = 1
		if num + 4 = spc then flag = 1
		if num - 4 = spc then flag = 1
		if flag then swap numbers[num], numbers[spc]
		for x = 1 to 15 
			if numbers[x] = x + 9311 then wellShuffeld++
		next 
	until wellShuffeld < 2 % numbers[1] <> 32 & numbers[1] <> 9312 & numbers[2] <> 9313 & numbers[3] <> 9314 & numbers[4] <> 9315 % number 1
fn.end

!-------------------------------------------------
! Swop the number with the space until there read 1 to 15
!-------------------------------------------------
fn.def PlayGame(numbers[])
	do
		do
			do
				do : x = Con_GetTouchX() : until x
				do : y = Con_GetTouchY() : until y
				x /= 2 : x = int(x) : y -= 1 
			until x > 0 & x < 5 & y > 0 & y < 5
			call DoBuzz()
			do : gr.touch t, tx, ty : until ! t
			num = x 
			if y = 2 : num += 4
				elseif y = 3 : num += 8 
				elseif y = 4 : num += 12
			endif
			
			if numbers[num] <> 32 then call DoSwop(numbers[], num, x) else : call Bell()
			
		until GameIsDone(numbers[])
		
		newBest = DoBest(0)
		
		if newBest then 
			do : dialog.message "Game over","A New Low Best\nAnother Game",yn,"Yes","No" : until yn > 0
		else 
			do : dialog.message "Game over","Another Game",yn,"Yes","No" : until yn > 0
		endif
		if yn = 1 then call DrawBoard(numbers[])
	until yn = 2
fn.end

!-------------------------------------------------
! If a legal move then swop number tapped with the space
!-------------------------------------------------
fn.def DoSwop(numbers[], num, x)
	flag = 0
	for s = 1 to 16 
		if numbers[s] = 32 then spc = s
	next
	! Look to see if legal move
	if x < 4 & num + 1 = spc then flag = 1
	if x > 1 & num - 1 = spc then flag = 1
	if num + 4 = spc then flag = 1
	if num - 4 = spc then flag = 1
	if ! flag then call Bell()
	
	if flag then 
		swap numbers[num], numbers[spc] 
		 c = 1
		gr.color 255,128,128,128,1
		!gr.rect null, 50,170,620,720
		gr.rect null, 50,170,620,700
		Con_RenderOff()
		for y = 1 to 4 
			for x = 1 to 4 
				Con_PrintAt(x * 2,y + 1, chr$(numbers[c])) : c++
			next
		next
		Con_RenderOn()
		call DoTrys(1)
	endif 
fn.end

!-------------------------------------------------
! Test to see if game is over
!-------------------------------------------------
fn.def GameIsDone(numbers[])
	flag = 1 : testChr = 9312
	for x = 1 to 15
		if numbers[x] <> testChr then flag = 0 % UniCode Characters (1) to (15)
		testChr++
	next
	fn.rtn flag
fn.end

!-------------------------------------------------
! Print the number of trys so for
!-------------------------------------------------
fn.def DoTrys(t)
	bundle.get 2, "Trys", trys 
	trys += t
	Con_BackGroundName("Navy") : Con_ChrPerLine(20)
	Con_PrintAt(1, 12, "Trys:" + int$(trys))
	Con_BackGroundName("Grey") : Con_ChrPerLine(10)
	bundle.put 2, "Trys", trys 
fn.end 

!-------------------------------------------------
! Print the lest trys to complete the game
!-------------------------------------------------
fn.def DoBest(display)
	flag = 0
	bundle.get 2, "Best", best
	if ! display then
		bundle.get 2, "Trys", trys
		if best = 0 then 
			best = trys : flag = 1 
			bundle.put 2, "Best", best
		elseif trys < best then 
			best = trys : flag = 1 
			bundle.put 2, "Best", best
		endif
	endif
	b$ ="   Best:" + int$(best) 
	Con_BackGroundName("Navy") : Con_ChrPerLine(20)
	bestLen = len(b$)
	Con_PrintAt(Con_GetMaxX() - bestLen, 12, b$)
	Con_BackGroundName("Grey") : Con_ChrPerLine(10)
	if flag then call SaveBest()
	fn.rtn flag
fn.end

!-------------------------------------------------
! Save best score
!-------------------------------------------------
fn.def SaveBest()
	! saves lowest trys, sound and vibration
	dataPath$="../../NumbersSlide/data/"
	bundle.get 2, "Best", best
	bundle.get 2, "Sound", sound
	bundle.get 2, "Buzz", vibration
	file.exists BestPresent,dataPath$+"NumberBest.txt"
	if BestPresent then
		text.open w,hs,dataPath$+"NumberBest.txt"
			text.writeln hs,int$(best)
			text.writeln hs,int$(sound)
			text.writeln hs,int$(vibration)
		text.close hs
	else
		file.mkdir dataPath$
		text.open w,hs,dataPath$+"NumberBest.txt"
			text.writeln hs,int$(best)
			text.writeln hs,int$(sound)
			text.writeln hs,int$(vibration)
		text.close hs
	endif
fn.end

!-------------------------------------------------
! Load best score
!-------------------------------------------------
fn.def LoadBest()
	! loads lowest trys, sound and vibration
	dataPath$="../../NumbersSlide/data/"
	file.exists BestPresent,dataPath$+"NumberBest.txt"
	if BestPresent then
		text.open r,hs,dataPath$+"NumberBest.txt"
			text.readln hs,best$
			best = val(best$)
			
			text.readln hs,best$
			sound = val(best$)
			
			text.readln hs,best$
			vibration = val(best$)
			
			bundle.put 2, "Best", best
			bundle.put 2, "Sound", sound
			bundle.put 2, "Buzz", vibration
		text.close hs
	endif
fn.end

!-------------------------------------------------
! Read the help from read.data and put in a bundle
!-------------------------------------------------
fn.def ReadHelp()
	read.from 1
	while h$ <> "STOP"
		read.next h$ 
		if h$ <> "STOP" then help$ = help$ + h$ + chr$(10)
	repeat
	bundle.put 2, "Help", help$
fn.end

!-------------------------------------------------
! Back key tapped. Call the menu
!-------------------------------------------------
fn.def Menu(numbers[])
	bundle.get 2, "Sound", sound
	bundle.get 2, "Buzz", vibration
	if sound then sound$="Sound On" else sound$="Sound Off"
	if vibration then vibration$="Vibration On" else vibration$="Vibration Off"
	
	array.load menu$[],	sound$,~
						vibration$,~
						"Reset Best Score",~
						"About",~
						"Help",~
						"New Game",~
						"Back to Game",~
						"Exit"
	dialog.select menuSelected, menu$[], "Main"
	
	sw.begin menuSelected
		sw.case 1
			if sound then sound = 0 else sound = 1	
			bundle.put 2, "Sound", sound
		sw.break
			
		sw.case 2
			if vibration then vibration = 0 else vibration = 1
			bundle.put 2, "Buzz", vibration
		Sw.break
		
		sw.case 3
			do : dialog.Message"Reset Best Score to zero?",,yn,"Yes","No" : until yn > 0
			if yn = 1 then 
				bundle.put 2, "Best", 0
				call SaveBest()
				call DoBest(1)
			endif
		sw.break
		
		sw.case 4
			Dialog.Message " About:\n\n",~
			"   Number Slide for Android\n\n" + ~
			"   With: RFO BASIC!\n\n" + ~
			"   Using ConLib.bas include file\n\n" + ~
			"   November 2015\n\n" +~
			"   Version: 1.00\n\n" + ~ 
			"   Author: Roy Shepherd\n\n", ~
			ok, "OK"
		sw.break
		
		sw.case 5
			bundle.get 2, "Help", help$
			dialog.Message " Number Slide Blocks Help:",help$,ok,"OK"
		sw.break
		
		sw.case 6
			call DrawBoard(numbers[])
			! Start new game
		sw.break
		
		sw.case 7
			! Back to game
		sw.break
			
		sw.case 8
			do : dialog.Message"Exit Game?",,yn,"Yes","No" : until yn > 0
			if yn=1 then call GoodBye()
		sw.break
	sw.end
fn.end

!-------------------------------------------------
! Leave game
!-------------------------------------------------
fn.def GoodBye()
	call SaveBest() % saves lowest trys, sound and vibration
	Con_ChrPerLine(40) : Con_BackgroundName("Navy") 
	Con_Cls() : Con_RenderOff()
	x = Con_GetMaxX() + 1 : y = Con_GetMaxY()
	Con_ColourName("Yellow") : Con_Bold(1)
	Con_PrintString(x, chr$(9574))
	Con_Locate(1,2)
	Con_PrintString(x, chr$(9577))
	
	Con_PrintString(x, chr$(9618))
	Con_PrintString(x, chr$(9618))
	
	Con_PrintString(x, chr$(9574))
	Con_PrintString(x, chr$(9577))
	
	Con_Locate(1, y - 5) 
	Con_PrintString(x, chr$(9574))
	Con_Locate(1, y - 4) 
	Con_PrintString(x, chr$(9577))
	
	Con_PrintString(x, chr$(9618))
	Con_PrintString(x, chr$(9618))
	
	Con_PrintString(x, chr$(9574))
	Con_PrintString(x, chr$(9577))
	Con_RenderOn()
	Con_ChrPerLine(6) : Con_ColourName("Red")
	
	Con_PrintAt(1,2, " Good ")
	Con_PrintAt(1,3, " Bye")
	
	pause 5000
	exit  
fn.end

!-------------------------------------------------
! Print box with heading, background and foreground colours.
!-------------------------------------------------
fn.def Box(boxUperLeft, top, boxBottomRight, bottom, heading$, colour$, BGcolour$)
	
	topLeft$ = chr$(9556): topRight$ = chr$(9559) : bottomLeft$ = chr$(9562) : bottomRight$ = chr$(9565)
	LeftRightBar$ = chr$(9553) : topBottomBar$ = chr$(9552) : headingLeftBar$ = chr$(9569) : headingRightBar$ = chr$(9566)
	!restoreColour = Con_GetColour() : restoreBGcolour = Con_GetBackground()
	Con_ColourName(colour$) : Con_BackGroundName(BGcolour$)
	
	! if BGcolour$ <> "" then print background
	for x = boxUperLeft + 1 to boxBottomRight - 1
		for y = top + 1 to bottom - 1 
			Con_PrintAt(x, y, " ")
		next
	next
	
	! Print each corner 
	Con_PrintAt(boxUperLeft, top, topLeft$) : Con_PrintAt(boxBottomRight, bottom, bottomRight$)
	Con_PrintAt(boxUperLeft, bottom, bottomLeft$) : Con_PrintAt(boxBottomRight, top, topRight$)
	
	! Print left and right bars
	for y = top + 1 to bottom - 1
		Con_PrintAt(boxUperLeft, y, LeftRightBar$)
		Con_PrintAt(boxBottomRight, y, LeftRightBar$)
	next
	! Print top and bottom bars
	for x = boxUperLeft + 1 to boxBottomRight - 1
		Con_PrintAt(x, top, topBottomBar$)
		Con_PrintAt(x, bottom, topBottomBar$)
	next
	
	! Print the heading, if heading$ is not ""
	if heading$ <> "" then 
		s$ = headingLeftBar$ + heading$ + headingRightBar$ 
		headingLenth = len(s$) / 2
		x = (boxBottomRight + boxUperLeft) / 2
		x = x - headingLenth
		Con_PrintAt(x, top, s$)
	endif
fn.end

!-------------------------------------------------
! Sound if user make an error
!-------------------------------------------------
fn.def Bell()
	bundle.get 2, "Sound", sound
	if sound then tone 500,100,0
fn.end

!-------------------------------------------------
! Vibrate when user taps screen
!-------------------------------------------------
fn.def DoBuzz()
	bundle.get 2, "Buzz", vibration
	if vibration then 
		array.load buzzGame[], 1, 100
		vibrate buzzGame[], -1
		array.delete buzzGame[]
	endif
fn.end

return

!------------------------------------------------
! Help data for the game.
!------------------------------------------------
read.data ""
read.data "Playing Number Slide:"
read.data "     Number Slide is a sliding puzzle game."
read.data "There are 15 numbered tiles in random order with one tile missing."
read.data "The object of this game is to place the tiles in order by tapping tiles next to the empty space to swap them over."
read.data "Try solving it in the less number of trys."
read.data ""
read.data "Menu:"
read.data "     Tap the Back Key to access the Menu"
read.data "     From the menu, you can:"
read.data "     Turn Sound On and Off"
read.data "     Turn Vibration On and Off"
read.data "     Reset the Best Score to zero."
read.data "     Read About and Help."
read.data "     Start a New game"
read.data "     Go back to the game."
read.data "     Exit the game."
read.data ""
read.data "	------------------------------------------------------------"
read.data "STOP"