Exemple #1
0
// print a legend of the Surface output
func PrintInfo() {
	log.Lock <- 1
	log.A("Surface Field association:\n")
	log.A("EMPTY\t\t' '\n")
	log.A("BOX\t\t'$'\n")
	log.A("FIGURE\t\t'x'\n")
	log.A("EMPTY POINT\t'*'\n")
	log.A("BOX POINT\t'%'\n")
	log.A("FIGURE POINT\t'+'\n")
	log.A("WALL\t\t'#'\n")
	log.A("DEAD FIELD\t'☠'\n")
	<-log.Lock
}
Exemple #2
0
// run the algo, print some output and catch if won.
// straightAhead: true: new direction are initialized with current dir, false: init with 0
func Run(e engine.Engine, single bool, outputFreq int32, printSurface bool, straightAhead bool, threads int) {
	steps, solutions, solSteps = 0, 0, []int32{}
	numWorkers = 0
	running = true
	cDone = make(chan int8, threads) // queue for threads
	cHistory = make(chan bool, 1)    // mutex on global history object

	// preprocessing
	MarkDeadFields(&e.Surface)
	e.Print()

	// init time counter
	syscall.Gettimeofday(&starttime)

	// ???
	//	runtime.GOMAXPROCS(runtime.NumCPU())

	// init path
	path := Path{}
	path.Push(engine.NO_DIRECTION)

	// create history store and save initial constellation
	history = newHistoryTree(-1, -1)
	newHist := e.GetBoxesAndX()
	addHistory(&history, newHist)

	// prepare for starting workers
	wg.Add(1)
	cDone <- 1
	go runWorker(e, path, threads, single, outputFreq, printSurface, straightAhead)

	// wait for all workers to finish
	wg.Wait()
	//	time.Sleep(1 * time.Second)

	// print result
	min, sec, µsec := getTimePassed(starttime)
	log.A("Run finished with %d steps after %dm %ds %dµs.\n%d solutions found at following steps:\n%d\n", steps, min, sec, µsec, solutions, solSteps)
}
Exemple #3
0
// print the current Surface
func (e *Engine) Print() {
	log.Lock <- 1
	var x, y int8
	for y = 0; y < int8(len(e.Surface)); y++ {
		log.A("%3d ", e.Id)
		for x = 0; x < int8(len(e.Surface[y])); x++ {
			switch field := e.Surface[y][x]; {
			case field.Wall:
				log.A("#")
			case e.figPos.X == x && e.figPos.Y == y:
				if field.Point {
					log.A("+")
				} else {
					log.A("x")
				}
			case field.Box == EMPTY:
				if field.Point {
					log.A("*")
				} else if field.Dead {
					log.A("☠")
				} else {
					log.A(" ")
				}
			default: // field has box
				if field.Point {
					log.A("%%")
				} else {
					log.A("$")
				}
			}
			log.A(" ")
		}
		log.A("\n")
	}
	fieldnr, deadnr := e.Surface.AmountOfFields()
	log.A("Boxes: %d\n", len(e.Boxes()))
	log.A("Points: %d\n", len(e.Points()))
	log.A("Fields: %d\n", fieldnr)
	log.A("DeadFields: %d\n", deadnr)
	<-log.Lock
}
Exemple #4
0
func main() {
	log.DebugLevel = 4
	runmode := false
	single := true
	level := "alevel"
	straightAhead := false
	outputFreq := int32(50000)
	printSurface := false
	threads := 1

	e := engine.NewEngine()

	if len(os.Args) > 1 {
		for i, _ := range os.Args {
			switch os.Args[i] {
			case "-r":
				runmode = true
			case "-l":
				if len(os.Args) > i+1 {
					level = os.Args[i+1]
				}
			case "-i":
				engine.PrintInfo()
			case "-m":
				single = false
			case "-d":
				if len(os.Args) > i+1 {
					debuglevel, err := strconv.Atoi(os.Args[i+1])
					if err == nil {
						log.DebugLevel = debuglevel
					}
				}
			case "-s":
				straightAhead = true
			case "-f":
				if len(os.Args) > i+1 {
					of, err := strconv.Atoi(os.Args[i+1])
					if err == nil {
						outputFreq = int32(of)
					}
				}
			case "-p":
				printSurface = true
			case "-t":
				if len(os.Args) > i+1 {
					t, err := strconv.Atoi(os.Args[i+1])
					if err != nil {
						panic(err)
					} else {
						threads = t
					}
				}
			}
		}
	}

	e.LoadLevel(level)
	log.I(e.Id, "Level: "+level)

	if runmode {
		ai.Run(e, single, outputFreq, printSurface, straightAhead, threads)
		return
	}

	// surface
	e.Print()

	var choice string
	for {
		choice = ""
		log.A("Press m for manual or r for run: ")
		fmt.Scanf("%s", &choice)
		if choice == "r" {
			ai.Run(e, single, outputFreq, printSurface, straightAhead, threads)
			break
		} else if choice == "m" {
			log.A("Manual mode\n")
			var input int
			for {
				fmt.Scanf("%d", &input)
				if input >= 0 && input <= 3 {
					e.Move(engine.Direction(input))
					e.Print()
				} else {
					e.UndoStep()
					e.Print()
				}
			}
			break
		}
	}
}
Exemple #5
0
func runWorker(e engine.Engine, basePath Path, threads int, single bool, outputFreq int32, printSurface bool, straightAhead bool) {
	// make sure, process will wait for this worker
	defer wg.Done()
	gorNo := numWorkers
	numWorkers++
	log.I(gorNo, "runWorker %d created, %d running", gorNo, runtime.NumGoroutine())
	e.Id = gorNo
	//	path := Path{basePath[len(basePath)-1].Clone()}
	path := basePath[len(basePath)-1:]

	basePath = basePath[:len(basePath)-1]
	//	basePath = basePath.Clone()

	//	log.I(gorNo, "path: %d, basePath: %d", path, basePath)

	for {
		var ignoredDir = false
		ignoredDir = false
		// ### 1. check if finished
		if path.Empty() || !running {
			log.D(e.Id, "Empty path / stopped executition. Hopefully all possibilities tried ;)")
			break
		}
		// ### 2. increase the current direction to try the next possibility
		path.IncCurrentDir()
		// ### 3. check if rotation is finished. Then backtrack
		if path.CurrentCounter() > 3 {
			var dir = path.Current().PopIgnored()
			if dir == -1 {
				log.D(e.Id, "Rotation finished. Deadlock. Backtrack.")
				e.UndoStep()
				path.Pop()
				continue
			} else {
				path.SetCurrentDir(dir)
				ignoredDir = true
			}
		}
		// ### 4a. check if there is a box in direction dir and if this box is on a point
		cf := e.FigPos()                        // current figureposition
		nf := cf.Add(path.CurrentDir().Point()) // potential new figureposition
		if e.Surface[nf.Y][nf.X].Point && e.Surface[nf.Y][nf.X].Box != 0 && !ignoredDir {
			log.D(e.Id, "Do not moving a box from a point")
			path.Current().PushIgnored(path.CurrentDir())
			continue
		}
		// ### 4b. Try moving
		log.D(e.Id, "Try moving in dir=%d", path.CurrentDir())
		moved, boxMoved := e.Move(path.CurrentDir())
		if !moved {
			log.D(e.Id, "Could not move.")
			continue
		}
		// ### 5. If moved, first check if not in a loop
		newHist := e.GetBoxesAndX()
		if everBeenHere(&history, newHist) {
			log.D(e.Id, "I'v been here already. Backtrack: %d", newHist)
			e.UndoStep()
			continue
		}
		// ### 6. If not in a loop, append history and go on
		addHistory(&history, newHist)
		if straightAhead {
			path.Push(path.CurrentDir() - 1)
		} else {
			path.Push(-1)
		}
		log.D(e.Id, "Moved. Path added.")
		// ### 7. Do some statistics
		incSteps()
		if printSurface {
			e.Print()
		}
		if steps%outputFreq == 0 {
			min, sec, µsec := getTimePassed(starttime)
			log.I(gorNo, "Steps: %9d; %4dm %2ds %6dµs", steps, min, sec, µsec)
		}
		// ### 8. Do we already won? :)
		if boxMoved != 0 && e.Won() {
			incSolutions()
			min, sec, µsec := getTimePassed(starttime)
			stepsCpy := steps
			log.Lock <- 1
			log.A("%d. solution found after %d steps, %4dm %2ds %6dµs.\nPath: %d%d\n", solutions, stepsCpy, min, sec, µsec, basePath.Directions(), path.Directions())
			<-log.Lock
			e.Print()
			solSteps = append(solSteps, stepsCpy)
			if single {
				running = false
				break
			}
			e.UndoStep()
			path.Pop()
		}
		// ### 9. Decide if we just go on or if we start a new thread
		if len(cDone) < threads {
			wg.Add(1)
			cDone <- 1
			ne := e.Clone()
			log.I(gorNo, "Creating new worker")
			go runWorker(ne, path.Clone(), threads, single, outputFreq, printSurface, straightAhead)
			// go back, as we deligated current dir go worker
			//			time.Sleep(3 * time.Second)
			e.UndoStep()
			path.Pop()
		}

	}
	<-cDone
	log.I(gorNo, "runWorker %d finished", gorNo)
}
Exemple #6
0
func printTree(history HistoryTree) {
	log.A("%d\n", history)
}