예제 #1
0
파일: game.go 프로젝트: g3force/Go_Sokoban
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
		}
	}
}
예제 #2
0
파일: bot.go 프로젝트: g3force/Go_Sokoban
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)
}