Added Force Quit to intcode processor

This commit is contained in:
Brian Buller 2019-12-16 17:31:11 -06:00
parent 11019fa77e
commit 0e315631dd
4 changed files with 238 additions and 21 deletions

View File

@ -8,10 +8,13 @@ import (
"time"
intcode "git.bullercodeworks.com/brian/adventofcode/2019/intcode-processor"
helpers "git.bullercodeworks.com/brian/adventofcode/helpers"
)
var auto bool
var maze *Maze
func main() {
progFileName := "input"
@ -19,20 +22,49 @@ func main() {
auto = true
}
prog := intcode.ReadIntCodeFile(progFileName)
maze = NewMaze()
play(prog)
}
func play(prog []int) {
p := intcode.NewProgram(prog)
go func() {
var roadTaken []helpers.Coordinate
for {
time.Sleep(500)
fmt.Println(helpers.CLEAR_SCREEN)
maze.Print()
for !p.NeedsInput() {
time.Sleep(1)
}
var movingDir int
var moveToCoord *helpers.Coordinate
if auto {
var picked bool
directions := []int{DIR_N, DIR_E, DIR_S, DIR_W}
// If we have an unexplored location, try it
for _, tryDir := range directions {
v := maze.GetCoord(maze.GetDirFromBot(tryDir))
if v == MAZE_UNKNOWN {
movingDir = tryDir
picked = true
break
}
}
if !picked {
movingDir = maze.GetDirectionToLast()
if movingDir == -1 {
fmt.Println("Maze Created")
p.ForceQuit()
return
}
picked = true
}
moveToCoord = maze.GetDirFromBot(movingDir)
} else {
var gotInput bool
for !gotInput {
for movingDir == 0 {
fmt.Print("Input (vimlike): ")
reader := bufio.NewReader(os.Stdin)
inp, err := reader.ReadString('\n')
@ -41,38 +73,40 @@ func play(prog []int) {
}
inp = strings.TrimSpace(inp)
switch inp {
case "h":
p.Input(3)
gotInput = true
case "j":
p.Input(2)
gotInput = true
case "k":
p.Input(1)
gotInput = true
case "l":
p.Input(4)
gotInput = true
case "h": // West
movingDir = DIR_W
moveToCoord = maze.bot.GetWestCoord()
case "j": // South
movingDir = DIR_S
moveToCoord = maze.bot.GetSouthCoord()
case "k": // North
movingDir = DIR_N
moveToCoord = maze.bot.GetNorthCoord()
case "l": // East
movingDir = DIR_E
moveToCoord = maze.bot.GetEastCoord()
}
}
}
p.Input(movingDir)
for !p.NeedsOutput() {
time.Sleep(1)
}
moveRes := p.Output()
maze.SetCoord(moveToCoord, moveRes)
switch moveRes {
case 0: // Hit a wall
fmt.Println("WALL")
case 1: // Moved
fmt.Println("OK")
case 2: // Moved and done
fmt.Println("DONE")
case 1, 2: // Moved
roadTaken = append(roadTaken, *maze.bot)
maze.MoveBot(movingDir)
}
if p.State() == intcode.RET_DONE || p.State() == intcode.RET_ERR {
break
}
}
}()
ret := p.Run()
if ret == intcode.RET_DONE {
maze.Print()
} else if ret == intcode.RET_ERR {
fmt.Println("ERROR")
fmt.Println(p.Error())

139
2019/day15/maze.go Normal file
View File

@ -0,0 +1,139 @@
package main
import (
"fmt"
helpers "git.bullercodeworks.com/brian/adventofcode/helpers"
)
const (
MAZE_UNKNOWN = -1
MAZE_WALL = 0
MAZE_EMPTY = 1
MAZE_O2SYS = 2
)
const (
DIR_N = 1
DIR_S = 2
DIR_W = 3
DIR_E = 4
)
type Maze struct {
maze map[string]int
maxX, minX int
maxY, minY int
bot *helpers.Coordinate
path []*helpers.Coordinate
dirHistory []int
dnt bool
}
func NewMaze() *Maze {
m := &Maze{
maze: make(map[string]int),
maxX: helpers.MIN_INT,
minX: helpers.MAX_INT,
maxY: helpers.MIN_INT,
minY: helpers.MAX_INT,
bot: helpers.NewCoordinate(0, 0),
}
m.path = append(m.path, helpers.NewCoordinate(0, 0))
return m
}
func (m *Maze) SetCoord(c *helpers.Coordinate, val int) {
m.maze[c.String()] = val
if m.maxX < c.X {
m.maxX = c.X
}
if m.minX > c.X {
m.minX = c.X
}
if m.maxY < c.Y {
m.maxY = c.Y
}
if m.minY > c.Y {
m.minY = c.Y
}
}
func (m *Maze) GetCoord(c *helpers.Coordinate) int {
v, ok := m.maze[c.String()]
if !ok {
return MAZE_UNKNOWN
}
return v
}
func (m *Maze) GetDirFromBot(dir int) *helpers.Coordinate {
switch dir {
case DIR_N:
return m.bot.GetNorthCoord()
case DIR_E:
return m.bot.GetEastCoord()
case DIR_S:
return m.bot.GetSouthCoord()
case DIR_W:
return m.bot.GetWestCoord()
}
return nil
}
func (m *Maze) MoveBot(dir int) bool {
dest := m.GetDirFromBot(dir)
if m.GetCoord(dest) == MAZE_UNKNOWN || m.GetCoord(dest) == MAZE_WALL {
return false
}
m.bot.X, m.bot.Y = dest.X, dest.Y
if !m.dnt {
m.path = append(m.path, helpers.NewCoordinate(m.bot.X, m.bot.Y))
m.dirHistory = append(m.dirHistory, dir)
}
m.dnt = false
return true
}
func (m *Maze) GetDirectionToLast() int {
if len(m.dirHistory) == 0 {
return -1
}
m.dnt = true
var dir int
dir, m.dirHistory = m.dirHistory[len(m.dirHistory)-1], m.dirHistory[:len(m.dirHistory)-1]
switch dir {
case DIR_N:
return DIR_S
case DIR_S:
return DIR_N
case DIR_W:
return DIR_E
case DIR_E:
return DIR_W
}
return -1
}
func (m *Maze) Print() {
for y := m.minY; y <= m.maxY; y++ {
for x := m.minX; x <= m.maxX; x++ {
c := helpers.NewCoordinate(x, y)
if m.bot.Equals(*c) {
fmt.Print("%")
} else {
switch m.GetCoord(c) {
case MAZE_UNKNOWN:
fmt.Print("~")
case MAZE_WALL:
fmt.Print("#")
case MAZE_EMPTY:
fmt.Print(" ")
case MAZE_O2SYS:
fmt.Print("O")
}
}
}
fmt.Println()
}
}

View File

@ -44,6 +44,7 @@ type Program struct {
state int
error error
bail bool
waitingForInput bool
input chan int
waitingForOutput bool
@ -113,6 +114,12 @@ func (p *Program) Error() error {
return p.error
}
func (p *Program) ForceQuit() {
p.bail = true
close(p.input)
close(p.output)
}
func (p *Program) Run() int {
for {
p.state = p.Step()
@ -123,6 +130,10 @@ func (p *Program) Run() int {
}
func (p *Program) Step() int {
if p.bail {
p.error = errors.New("Force Quit")
return RET_ERR
}
if len(p.code) < p.ptr {
p.error = errors.New("Pointer Exception")
return RET_ERR

View File

@ -10,6 +10,35 @@ type Coordinate struct {
X, Y int
}
func NewCoordinate(x, y int) *Coordinate {
return &Coordinate{x, y}
}
func (c *Coordinate) GetNorthCoord() *Coordinate {
return &Coordinate{
X: c.X,
Y: c.Y - 1,
}
}
func (c *Coordinate) GetEastCoord() *Coordinate {
return &Coordinate{
X: c.X + 1,
Y: c.Y,
}
}
func (c *Coordinate) GetSouthCoord() *Coordinate {
return &Coordinate{
X: c.X,
Y: c.Y + 1,
}
}
func (c *Coordinate) GetWestCoord() *Coordinate {
return &Coordinate{
X: c.X - 1,
Y: c.Y,
}
}
func CoordinateFromString(str string) *Coordinate {
c := Coordinate{}
r := strings.NewReader(str)
@ -35,3 +64,7 @@ func (c Coordinate) String() string {
func (c Coordinate) Distance(t Coordinate) int {
return AbsInt(c.X-t.X) + AbsInt(c.Y-t.Y)
}
func (c Coordinate) Equals(c2 Coordinate) bool {
return c.X == c2.X && c.Y == c2.Y
}