Mercurial > repos > icfp2012
view src/sim.tp @ 43:1f583d85c8ed
rocks slide correctly now. rock movement is complete.
author | William Morgan <bill@mrgn.org> |
---|---|
date | Sun, 15 Jul 2012 16:45:42 -0700 |
parents | 21b14768ea00 |
children | 5d2e59cbbc7c ccaecf1d6425 |
line wrap: on
line source
{ null <- #{} eachbyte <- :string action { strLen <- string byte_length: index <- 0 while: {index < strLen} do: { element <- (string byte: index) action: index element index <- index + 1 } } debugLog <- :str { os write: 2 str } abs <- :val { if: val < 0 { 0 - val } else: { val } } makeCellTypes <- { typedict <- dict linear new <- :idStr { cannav <- if: idStr = " " {true} else: { if: idStr = "." {true} else: { if: idStr = "\\" {true} else: { if: idStr = "O" {true} else: { false }}}} ret <- #{ id <- (idStr byte: 0) string <- idStr isrobot <- { false } eq <- :other { id = (other id) } navigable <- { cannav } } typedict set: (ret id) ret ret } #{ find <- :id { if: id = ("R" byte: 0) { robot: } else: { typedict get: id withDefault: empty } } wall <- new: "#" empty <- new: " " earth <- new: "." rock <- new: "*" lambda <- new: "\\" closedLift <- new: "L" openLift <- new: "O" newline <- new: "\n" robot <- { commands <- dict linear ret <- #{ id <- ("R" byte: 0) string <- "R" x <- 0 y <- 0 isrobot <- { true } eq <- :other { id = (other id) } collected <- 0 heldBreath <- 0 razors <- 0 busted <- false mine <- null doCmd <- :cmd { action <- commands get: cmd withDefault: { null } action: } move <- :xDelta yDelta { xPrime <- x + xDelta yPrime <- y + yDelta writeMove <- { mine setCell: xPrime yPrime self mine setCell: x y empty x <- xPrime y <- yPrime } consequenceOf <- :cur { if: (cur eq: lambda) {collected <- collected + 1} if: (cur eq: openLift) {mine succeeded!: true} } destination <- mine getCell: xPrime yPrime if: (destination navigable: ) { consequenceOf: destination writeMove: } else: { if: (destination eq: rock) { xPrimePrime <- xDelta * 2 + x rockDestination <- mine getCell: xPrimePrime y if: (rockDestination eq: empty) { mine setCell: xPrimePrime y rock writeMove: } } } } } commands set: "L" {ret move: (-1) 0 } commands set: "R" {ret move: 1 0 } commands set: "U" {ret move: 0 1 } commands set: "D" {ret move: 0 (-1) } //commands set: "A" {mine ended!: true} ret } } } #{ cellTypes <- makeCellTypes: state <- #{ new <- :in_grid in_width in_height { nextGrid <- #[] _robot <- null endreached <- false _lambdaCount <- 0 _succeeded <- false ret <- #{ grid <- in_grid width <- in_width height <- in_height calcIndex <- :x y { x + y * width } calcX <- :index {index % width} calcY <- :index {index / width} setCell <- :x y val { grid set: (calcIndex: x y) val } getCell <- :x y { grid get: (calcIndex: x y) } validDest?:from <- :index :fromIndex { cell <- (grid get: index) if: (cell navigable) {true} else: { if: (cell eq: (cellTypes rock)) { diff <- index - fromIndex //make sure movement was horizontal if: (abs: diff) = 1 { rockdest <- index + diff if: ((grid get: rockdest) eq: (cellTypes empty)) { //make sure rock destination doesn't wrap (calcY: rockdest) = (calcY: index) } } } } } validMoves <- :x y { amove <- :idx name {#{ index <- idx cmd <- name string <- { name . "(" . idx . ")" } }} here <- calcIndex: x y //TODO: Add wait move when rocks are in motion //(amove: here "W") cur <- #[(amove: here "A")] up <- amove: (calcIndex: x y + 1) "U" down <- amove: (calcIndex: x y - 1) "D" left <- amove: (calcIndex: x - 1 y) "L" right <- amove: (calcIndex: x + 1 y) "R" foreach: #[up down left right] :idx el { if: (validDest?: (el index) from: here) { cur append: el } } cur } getRobot <- { _robot } updatePos <- :obj Index { obj x!: (calcX: Index) obj y!: (calcY: Index) } lambdaCount <- {_lambdaCount} water <- 0 flooding <- 0 waterproof <- 10 moves <- 0 ended <- {endreached} succeeded <- {_succeeded} succeeded! <- :newval { endreached <- newval _succeeded <- newval } doUpdate <- { foreach: grid :index value { if: (value eq: (cellTypes rock)) { x <- calcX: index y <- calcY: index below <- getCell: x (y - 1) fallToSide <- :delta { side <- getCell: (x + delta) y belowSide <- getCell: (x + delta) (y - 1) if: (side eq: (cellTypes empty)) { if: (belowSide eq: (cellTypes empty)) { setCell: (x + delta) (y - 1) value setCell: x y (cellTypes empty) true } else: { false } } else: { false } } if: (below eq: (cellTypes empty)) { setCell: x y (cellTypes empty) setCell: x (y - 1) value } else: { if: (below eq: (cellTypes rock)) { if: (not: (fallToSide: 1)) {fallToSide: -1} } else: { if: (below eq: (cellTypes lambda)) { fallToSide: 1 }}} // end if } else: { if: (value eq: (cellTypes closedLift)) { if: (_robot collected) = _lambdaCount { grid set: index (cellTypes openLift) } } } } } advance <- :roboCmd { endreached <- roboCmd = "A" if: (not: endreached) { _robot doCmd: roboCmd moves <- moves + 1 doUpdate: } self } printGrid <- { cur <- (grid length) - width col <- 0 while: {cur >= 0} do: { os write: 2 ((grid get: cur) string) cur <- cur + 1 col <- col + 1 if: col = width { col <- 0 cur <- cur - (width + width) os write: 2 "\n" } } } clone <- { cgrid <- #[] foreach: grid :idx el { if: (el isrobot) { cgrid append: (cellTypes robot) } else: { cgrid append: el } } myclone <- state new: cgrid width height myclone water!: water myclone flooding!: flooding myclone waterproof!: waterproof myclone moves!: moves myclone } } foreach: in_grid :index el{ nextGrid append: el if: (el isrobot) { _robot <- el _robot mine!: ret ret updatePos: _robot index } else: { if: (el eq: (cellTypes lambda)) { _lambdaCount <- _lambdaCount + 1 } } } ret } fromStr <- :str { strLen <- str byte_length: maxCol <- 0 nl <- (cellTypes newline) id blank <- cellTypes empty lines <- #[] curline <- #[] eachbyte: str :index element { if: element = nl { col <- curline length maxCol <- if: col > maxCol {col} else: {maxCol} lines append: curline curline <- #[] } else: { curline append: (cellTypes find: element) } } grid <- #[] cur <- (lines length) - 1 while: { cur >= 0 } do: { curline <- (lines get: cur) foreach: curline :idx el { grid append: el } extra <- maxCol - (curline length) while: { extra > 0 } do: { grid append: blank extra <- extra - 1 } cur <- cur - 1 } new: grid maxCol (lines length) } } readFd <- :fd { if: fd < 0 { "" } else: { cur <- "" part <- "" while: { part <- os read: fd 128 part != "" } do: { cur <- cur . part } cur } } readFile <- :path { fd <- os open: path (os O_RDONLY) out <- readFd: fd os close: fd out } getMove <- { ret <- os read: 0 1 while: {ret = "\n"} do: { ret <- os read: 0 1 } ret } main <- :args { if: (args length) < 2 { print: "usage: sim filename\n" } else: { verbose <- true text <- readFile: (args get: 1) print: text //os close: 1 simState <- state fromStr: text while: { not: (simState ended: ) } do: { simState advance: (getMove: ) if: verbose { simState printGrid } } } } } }