;+-----------------------------+
;|    This is "Swap Stones",   |
;| a simple single player game |
;|  for STK500 and ATmega8515. |
;|    Connect LEDS to PORTB    |
;|    and Switches to PORTD.   |
;|     Program the device!     |
;|       Enjoy the game!       |
;|                             |
;|     Made by Ivaylo Belev    |
;|     kink_alias@yahoo.com    |
;+-----------------------------+

.include "8515def.inc"
.def l1 = r16 			;layer1 mask
.def l2 = r17 			;layer2 mask
.def cnt = r18 			;countdown to success
.def dlay = r19			;delay variable 1 
.def dlay2 = r20 		;delay variable 2 


;**** Initialization

		ser		cnt
		out		DDRB,cnt		;set PORTB to output

INIT:	
		ldi 	l1,0x88			;load initial values
		ldi 	l2,0x8F
		ldi 	cnt,15
		clr		dlay
		clr		dlay2
	

;**** Main program

MAIN:
		out		PORTB,l1		;update LEDs layer1

		out		PORTB,l2		;update LEDs layer 2

;**** Test input

		sbis	PIND,0			;if button0 pressed
		rjmp 	Check0			;check for possible move
		
		sbis	PIND,1		
		rjmp 	Check1
		
		sbis	PIND,2
		rjmp 	Check2		
		
		sbis	PIND,3
		rjmp 	Check3		
		
		sbis	PIND,4		
		rjmp 	Check4

		sbis	PIND,5		
		rjmp 	Check5

		sbis	PIND,6
		rjmp 	Check6

		sbis	PIND,7			;if button7 pressed
		rjmp	INIT			;game restart

		rjmp	MAIN

Check0:
		sbrc 	l1,0			;check if empty
		rjmp	MAIN
		sbrs	l2,0			;check direction
		rjmp	MAIN	
		sbrs	l1,1			;check if left empty
		rjmp	ifDiff0

		sbr 	l1,1			;move left
		cbr		l1,2
		dec		cnt
		rjmp  	MAIN

	ifDiff0:
		sbrc	l2,1			;if can skip
		rjmp	MAIN	
		sbrs	l1,2			;if left++ empty
		rjmp	MAIN	

		sbr		l1,1			;move left++
		cbr		l1,4
		dec		cnt
		rjmp	MAIN	


Check1:
		sbrc 	l1,1			;check if empty
		rjmp	MAIN
		sbrs	l2,1			;check direction
		rjmp	revDir1	
		sbrs	l1,2			;check if left empty
		rjmp	ifDiff1

		sbr 	l1,2			;move left
		cbr		l1,4
		dec		cnt
		rjmp  	MAIN

	ifDiff1:
		sbrc	l2,2			;if can skip
		rjmp	MAIN	
		sbrs	l1,3			;if left++ empty
		rjmp	MAIN	

		sbr		l1,2			;move left++
		cbr		l1,8
		dec		cnt
		rjmp	MAIN	

	revDir1:
		sbrs	l1,0			;check if right empty
		rjmp	MAIN

		sbr 	l1,2			;move right
		sbr 	l2,2
		cbr		l1,1
		cbr		l2,1
		dec		cnt
		rjmp  	MAIN

	
Check2:
		sbrc 	l1,2			;check if empty
		rjmp	MAIN
		sbrs	l2,2			;check direction
		rjmp	revDir2	
		sbrs	l1,3			;check if left empty
		rjmp	ifDiff2

		sbr 	l1,4			;move left
		cbr		l1,8
		dec		cnt
		rjmp  	MAIN

	ifDiff2:
		sbrc	l2,3			;if can skip
		rjmp	MAIN	
		sbrs	l1,4			;if left++ empty
		rjmp	MAIN	

		sbr		l1,4			;move left++
		cbr		l1,16
		dec		cnt
		rjmp	MAIN	

	revDir2:
		sbrs	l1,1			;check if right empty
		rjmp	ifDiff2r

		sbr 	l1,4			;move right
		sbr 	l2,4
		cbr		l1,2
		cbr		l2,2
		dec		cnt
		rjmp  	MAIN

	ifDiff2r:
		sbrs	l2,1			;if can skip
		rjmp	MAIN	
		sbrs	l1,0			;if right++ empty
		rjmp	MAIN	

		sbr		l1,4			;move right++
		sbr		l2,4
		cbr		l1,1
		cbr		l2,1
		dec		cnt
		rjmp	MAIN


Check3:
		sbrc 	l1,3			;check if empty
		rjmp	MAIN
		sbrs	l2,3			;check direction
		rjmp	revDir3	
		sbrs	l1,4			;check if left empty
		rjmp	ifDiff3

		sbr 	l1,8			;move left
		cbr		l1,16
		dec		cnt

		cpse	cnt,dlay
		rjmp  	MAIN
		rjmp	WELL_DONE

	ifDiff3:
		sbrc	l2,4			;if can skip
		rjmp	MAIN	
		sbrs	l1,5			;if left++ empty
		rjmp	MAIN	

		sbr		l1,8			;move left++
		cbr		l1,32
		dec		cnt
		rjmp	MAIN	

	revDir3:
		sbrs	l1,2			;check if right empty
		rjmp	ifDiff3r

		sbr 	l1,8			;move right
		sbr 	l2,8
		cbr		l1,4
		cbr		l2,4
		dec		cnt
		
		cpse	cnt,dlay
		rjmp  	MAIN
		rjmp	WELL_DONE

	ifDiff3r:
		sbrs	l2,2			;if can skip
		rjmp	MAIN	
		sbrs	l1,1			;if right++ empty
		rjmp	MAIN	

		sbr		l1,8			;move right++
		sbr		l2,8
		cbr		l1,2
		cbr		l2,2
		dec		cnt
		rjmp	MAIN


Check4:
		sbrc 	l1,4			;check if empty
		rjmp	MAIN
		sbrs	l2,4			;check direction
		rjmp	revDir4	
		sbrs	l1,5			;check if left empty
		rjmp	ifDiff4

		sbr 	l1,16			;move left
		cbr		l1,32
		dec		cnt
		rjmp  	MAIN

	ifDiff4:
		sbrc	l2,5			;if can skip
		rjmp	MAIN	
		sbrs	l1,6			;if left++ empty
		rjmp	MAIN	

		sbr		l1,16			;move left++
		cbr		l1,64
		dec		cnt
		rjmp	MAIN	

	revDir4:
		sbrs	l1,3			;check if right empty
		rjmp	ifDiff4r

		sbr 	l1,16			;move right
		sbr 	l2,16
		cbr		l1,8
		cbr		l2,8
		dec		cnt
		rjmp  	MAIN

	ifDiff4r:
		sbrs	l2,3			;if can skip
		rjmp	MAIN	
		sbrs	l1,2			;if right++ empty
		rjmp	MAIN	

		sbr		l1,16			;move right++
		sbr		l2,16
		cbr		l1,4
		cbr		l2,4
		dec		cnt
		rjmp	MAIN


Check5:
		sbrc 	l1,5			;check if empty
		rjmp	MAIN
		sbrs	l2,5			;check direction
		rjmp	revDir5	
		sbrs	l1,6			;check if left empty
		rjmp	MAIN

		sbr 	l1,32			;move left
		cbr		l1,64
		dec		cnt
		rjmp  	MAIN

	revDir5:
		sbrs	l1,4			;check if right empty
		rjmp	ifDiff5r

		sbr 	l1,32			;move right
		sbr 	l2,32
		cbr		l1,16
		cbr		l2,16
		dec		cnt
		rjmp  	MAIN

	ifDiff5r:
		sbrs	l2,4			;if can skip
		rjmp	MAIN	
		sbrs	l1,3			;if right++ empty
		rjmp	MAIN	

		sbr		l1,32			;move right++
		sbr		l2,32
		cbr		l1,8
		cbr		l2,8
		dec		cnt
		rjmp	MAIN

Check6:
		sbrc 	l1,6			;check if empty
		rjmp	MAIN
		sbrc	l2,6			;check direction
		rjmp	MAIN	

		sbrs	l1,5			;check if right empty
		rjmp	ifDiff6r

		sbr 	l1,64			;move right
		sbr 	l2,64
		cbr		l1,32
		cbr		l2,32
		dec		cnt
		rjmp  	MAIN

	ifDiff6r:
		sbrs	l2,5			;if can skip
		rjmp	MAIN	
		sbrs	l1,4			;if right++ empty
		rjmp	MAIN	

		sbr		l1,64			;move right++
		sbr		l2,64
		cbr		l1,16
		cbr		l2,16
		dec		cnt
		rjmp	MAIN


;**** Mission accomplished!

WELL_DONE:
		out		PORTB,cnt		;all LEDs flashing

	delay:
		dec		dlay
		brne 	delay
		dec		dlay2
		brne 	delay

		com		cnt

		sbis 	PIND,7			;if button7 pressed
		rjmp 	INIT			;restart

		rjmp 	WELL_DONE
