예제 #1
0
func markDeadWall(surface *engine.Surface, start engine.Point, end engine.Point) {
	if start.X == end.X && start.Y != end.Y {
		if start.Y < end.Y {
			for i := start.Y; i <= end.Y; i++ {
				(*surface)[i][start.X].Dead = true
			}
		} else {
			for i := start.Y; i >= end.Y; i-- {
				(*surface)[i][start.X].Dead = true
			}
		}
	} else if start.Y == end.Y && start.X != end.X {
		if start.X < end.X {
			for i := start.X; i <= end.X; i++ {
				(*surface)[start.Y][i].Dead = true
			}
		} else {
			for i := start.X; i >= end.X; i-- {
				(*surface)[start.Y][i].Dead = true
			}
		}
	} else {
		log.D(-1, "Solo dead end")
	}
	return
}
예제 #2
0
/* try moving figure in specified direction.
 * Returns, if figure was moved and if figure moved a box.
 */
func (e *Engine) Move(dir Direction) (success bool, boxMoved int8) {
	success = false
	boxMoved = EMPTY
	cf := e.FigPos()          // current figureposition
	nf := cf.Add(dir.Point()) // potential new figureposition
	if !e.Surface.In(nf) {
		log.D(e.Id, "Can not move: surface border")
		return
	}
	// check type of field of new figureposition
	switch f := e.Surface[nf.Y][nf.X]; {
	case f.Wall == true:
		log.D(e.Id, "Can not move: wall")
		return
	case f.Box != EMPTY: // if box
		nnf := nf.Add(dir.Point()) // potential new boxposition
		if !e.Surface.In(nnf) {
			log.D(e.Id, "Can not move: blocked box (surface border)")
			return
		}
		if e.Surface[nnf.Y][nnf.X].Dead {
			log.D(e.Id, "Can not move: Dead field")
			return
		}
		if e.Surface[nnf.Y][nnf.X].Wall || e.Surface[nnf.Y][nnf.X].Box != EMPTY {
			log.D(e.Id, "Can not move: blocked box")
			return
		}
		log.D(e.Id, "Move box")
		boxMoved = f.Box
		e.boxes[f.Box].SetPos(nnf) // nnf is position that box should move to, f.Box is current box
		e.reOrderBoxes(f.Box, dir)
		e.Surface[nnf.Y][nnf.X].Box = e.Surface[nf.Y][nf.X].Box
		fallthrough // go to next case statment to also move the figure
	case f.Box >= EMPTY: // actually always...
		var hist HistoryType
		hist.NewPos = nf
		hist.OldPos = cf
		hist.BoxMoved = boxMoved
		e.History = append(e.History, hist)
		e.Surface[nf.Y][nf.X].Box = e.Surface[cf.Y][cf.X].Box
		e.Surface[cf.Y][cf.X].Box = EMPTY
		e.figPos = nf // refresh figureposition
		success = true
	default:
		log.E(e.Id, "Unknown field")
	}
	return
}
예제 #3
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)
}