// jumpsaround.go - jumper game
// (c) 2020 Alexander Kulbartsch
// 
// use type inference and int types when neccessary
// (slightly performace optimized version: valid jumpes checked bevore iteration.)

package main

import (
	"fmt"
)

const SIZEX = 6
const SIZEY = 5

type boardt [SIZEX][SIZEY]int

var board boardt
var jump = [8][2]int{{-1, -2}, {1, -2}, {-2, -1}, {2, -1}, {-2, 1}, {2, 1}, {-1, 2}, {1, 2}}
var solutions = 0
var roundtrips = 0

func main() {
	fmt.Println("Hello, Jumper!")

	jumpto(0, 0, 1)

	fmt.Println("I am done.")
}

func jumpto(x, y, iter int) {

	// ok - store position
	board[x][y] = iter

	// finished?
	if iter >= SIZEX*SIZEY {

		// check for jumper roundtrips
		round := false
		for _, d := range jump {
			nx := x + d[0]
			ny := y + d[1]
			// check if position is on the board
			if nx < 0 || nx > (SIZEX-1) || ny < 0 || ny > (SIZEY-1) {
				continue
			}
			// detect roundtrip
			if board[nx][ny] == 1 {
				round = true
				roundtrips++
				break
			} // True
		}

		solutions++
		if round == true {
			printboard(round)
		}
		board[x][y] = 0
		return
	}

	// try next jump
	for _, d := range jump {
		nx := x + d[0]
		ny := y + d[1]

		// check if position is on the board
		if nx < 0 || nx > (SIZEX-1) || ny < 0 || ny > (SIZEY-1) {
			continue
		}

		//  check if new field position is still empty
		if board[nx][ny] != 0 {
			continue
		} // True

		jumpto(nx, ny, iter+1)
	}

	// this iteration is done
	board[x][y] = 0

}

func printboard(round bool) {
	fmt.Println("===== Solution #", solutions, " - Roundtripps:", roundtrips, " ====== ")
	if round == true {
		fmt.Println(" *** Roundtrip *** ")
	}
	fmt.Println("")
	for i := 0; i < SIZEY; i++ {
		for j := 0; j < SIZEX; j++ {
			fmt.Printf("%2d:", board[j][i])
		}
		fmt.Println("")
	}
	fmt.Println("")
}

// EOF
