view code/dotScanner.lm @ 34:968705fcb4c6

Initial stab at taking fruit and ghost state into account
author Michael Pavone <pavone@retrodev.com>
date Sat, 26 Jul 2014 01:41:24 -0700
parents 934d03d42a7e
children 8c26981aae8c
line wrap: on
line source

#{
	length <- :lst {
		len <- []
		while: { not: (lst isInteger?)} do: {
			lst <- lst tail
			len <- len + 1
		}
		len
	}
	
	reverse <- :lst {
		new <- []
		while: { not: (lst isInteger?)} do: {
			new <- (lst value) | new
			lst <- lst tail
		}
		new
	}

	split:at <- :lst :pos {
		first <- []
		i <- 0
		while: { i < pos } do: {
			first <- (lst value) | first
			lst <- lst tail
			i <- i + 1
		}
		#[(reverse: first) lst]
	}
	
	map <- :lst fun {
		new <- []
		while: { not: (lst isInteger?) } do: {
			new <- (fun: (lst value)) | new
			lst <- lst tail
		}
		reverse: new
	}
	
	fold:with <- :lst acc :fun {
		while: { not: (lst isInteger?) } do: {
			acc <- fun: acc (lst value)
			lst <- lst tail
		}
		acc
	}
	
	filter <- :lst pred {
		new <- []
		while: { not: (lst isInteger?) } do: {
			if: (pred: (lst value)) {
				new <- (lst value) | new
			} else: {}
			lst <- lst tail
		}
		reverse: new
	}

	flatten <- :lst {
		fold: lst [] with: :acc el {
			fold: el acc with: :iacc iel {
				iel | iacc
			}
		}
	}
	
	makeTree:size <- :lst :size {
		ret <- 0
		sub <- 0
		half <- size / 2
		if: size = 2 {
			ret <- #[(lst value) ((lst tail) value)]
		} else: {
			if: size = 1 {
				ret <- lst
			} else: {
				sub <- split: lst at: half
				ret <- #[
					(makeTree: (sub value) size: half)
					(makeTree: (sub tail) size: size-half)
				]
			}
		}
		ret
	}
	
	makeTree <- :lst {
		size <- lst length
		#[size (makeTree: lst size: size)]
	}
	
	get:fromTree:size <- :idx :tree :size {
		ret <- 0
		half <- size / 2
		if: size <= 2 {
			if: idx = 0 {
				ret <- tree value
			} else: {	
				ret <- tree tail
			}
		} else: {
			if: idx < half {
				ret <- get: idx fromTree: (tree value) size: half
			} else: {
				ret <- get: idx-half fromTree: (tree tail) size: size-half
			}
		}
		ret
	}
	
	get:fromTree <- :idx :tree {
		size <- tree value
		get: idx fromTree: (tree tail) size: size
	}
	
	treeMap:size <- :tree fun :size {
		ret <- 0
		half <- size / 2
		if: size = 2 {
			ret <- #[(fun: (tree value)) (fun: (tree tail))]
		} else: {
			if: size = 1 {
				ret <- #[(fun: (tree value)) 0]
			} else: {
				ret <- #[
					(treeMap: (tree value) fun size: half)
					(treeMap: (tree tail) fun size: size-half)
				]
			}
		}
		ret
	}
	
	treeMap <- :tree fun {	
		#[(tree value) (treeMap: (tree tail) fun size: (tree value))]
	}
	
	tree:size:update:with <- :tree :size :idx :fun {
		ret <- 0
		half <- size / 2
		if: size = 2 {
			if: idx = 0 {
				ret <- #[(fun: (tree value)) (tree tail)]
			} else: {
				ret <- #[(tree value) (fun: (tree tail))]
			}
		} else: {
			if: size = 1 {
				ret <- #[(fun: (tree value)) 0]
			} else: {
				if: (idx < half) {
					ret <- #[
						(tree: (tree value) size: half update: idx with: fun)
						(tree tail)
					]
				} else: {
					ret <- #[
						(tree value)
						(tree: (tree tail) size: size-half update: idx-half with: fun)
					]
				}
			}
		}
		ret
	}
	
	tree:update:with <- :tree :idx :fun {
		#[(tree value) (tree: (tree tail) size: (tree value) update: idx with: fun)]
	}
	
	tree:set:to <- :tree :idx :val {
		tree: tree update: idx with: :el { val }
	}

	grid:get <- :grid :pos {
		x <- pos value
		y <- pos tail
		get: x fromTree: (get: y fromTree: grid)
	}
	
	grid:update:with <- :grid :pos :fun {
		x <- pos value
		y <- pos tail
		tree: grid update: y with: :row {
			tree: row update: x with: fun
		}
	}
	
	grid:set:to <- :grid :pos :val {
		grid: grid update: pos with: :el { val }
	}

	grid:inBounds? <- :grid :pos {
		x <- pos value
		y <- pos tail
		maxY <- grid value
		maxX <- (get: 0 fromTree: grid) value
		((x >= 0) + (y >= 0) + (x < maxX) + (y < maxY)) > 0
	}

	visited <- 0

	advancer <- :continuations {
		notdone <- 1
		while: { notdone } do: {
			if: (continuations isInteger?) {
				notdone <- 0
			} else: {
				continuations <- fold: continuations [] with: :acc el{
					ret <- acc
					if: notdone {
						ret <- el:
						if: (ret isInteger?) {
							ret <- acc
						} else: {
							if: (ret value) {
								notdone <- 0
								ret <- (ret tail)
							} else: {
								ret <- (ret tail) | acc
							}
						}
					} else: {}
					ret
				}
				if: notdone {
					continuations <- flatten: continuations
				} else: {}
			}
		}
		continuations
	}

	calcPos <- :move from {
		x <- from value
		y <- from tail
		if: move {
			if: move = 1 {
				x <- x + 1
			} else: {
				if: move = 2 {
					y <- y + 1
				} else: {
					x <- x - 1
				}
			}
		} else: {
			y <- y - 1
		}
		#[x y]
	}

	makeContClos <- :grid myLoc path {
		{
			ret <- []
			move <- 0
			atpos <- 0
			if: (grid: grid inBounds?: myLoc) {
				if: (grid: visited get: myLoc) {
				} else: {
					atpos <- grid: grid get: myLoc
					if: (atpos = 2) + (atpos = 3) + (atpos = 4) {
						//pellet, power pellet, fruit
						ret <- #[1 (reverse: path)]
					} else: {
						visited <- grid: visited set: myLoc to: 1
						if: atpos {
							//empty space
							move <- 0
							while: { move < 4 } do: {
								ret <- (makeContClos: grid (calcPos: move myLoc) move | path) | ret
								move <- move + 1
							}
							ret <- #[0 ret]
						} else: {}
					}
				}
			} else: {
			}
			ret
		}
	}

	step <- :myState world {
		lmState <- (world tail) value
		myLoc <- (lmState tail) value
		ghostState <- ((world tail) tail) value
		fruitState <- ((world tail) tail) tail
		
		grid <- makeTree: (map: (world value) :row { 
			if: fruitState >= 127 {
			} else: {
				row <- map: row :el {
					//remove fruit if it is not enabled
					if: el = 4 {
						el <- 1
					} else: {}
					el
				}
			}
			makeTree: row 
		})
		grid <- fold: ghostState grid with: :acc ghost {
			vitality <- ghost value
			loc <- (ghost tail) value
			if: vitality = 1 {
				//treat fright mode ghosts as a pellet for now
				acc <- grid: acc set: loc to: 2
			} else: {
				if: vitality = 0 {
					//treat normal mode ghosts as a wall for now
					acc <- grid: acc set: loc to: 0
				} else: {}
			}
			acc
		}
		visited <- treeMap: grid :row {
			treeMap: row :el { 0 }
		}
		path <- advancer: [(makeContClos: grid myLoc [])]
		#[0 (path value)]
	}
	
	main <- :initWorld ghostCode {
		/*
		print: (step: 0 #[
			//grid
			[
				[0 0 0 0]
				[0 2 2 0]
				[0 1 0 0]
				[0 0 0 0]
			]
			//lmstate
			#[0 #[1 2] 2 3 0]
			//ghost state
			[]
			//fruit state
			0
		]) */
		#[0 step]
	}
}