view code/dotScanner.lm @ 79:dcfa97976071

Better handling of target selection
author Michael Pavone <pavone@retrodev.com>
date Mon, 28 Jul 2014 03:24:21 -0700
parents 3b8a277decfa
children 4251797af36b
line wrap: on
line source

#{
	import: [
		length
		reverse
		split:at
		map
		fold:with
		filter
		flatten
	] from: (module: "ll.lm")
		
	import: [
		makeTree:size
		makeTree
		get:fromTree:size
		get:fromTree
		treeMap:size
		treeMap
		tree:size:update:with
		tree:update:with
		tree:set:to
	] from: (module: "tree.lm")

	import: [
		grid:get	
		grid:update:with
		grid:set:to
		gridMaxX
		gridMaxY
		gridArea
		grid:inBounds?
		calcPos
	] from: (module: "grid.lm")

	visited <- 0
	badGhostCount <- 0
	edibleGhosts <- 0
	totalGhosts <- 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
	}
	
	target0 <- 2
	target1 <- 3
	target2 <- 4
	target3 <- 7

	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 = target0) + (atpos = target1) + (atpos = target2) + (atpos = target3) {
						//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
		myVitality <- lmState 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 
		})
		badGhostCount <- 0
		edibleGhosts <- 0
		totalGhosts <- 0
		grid <- fold: ghostState grid with: :acc ghost {
			totalGhosts <- totalGhosts + 1
			vitality <- ghost value
			loc <- (ghost tail) value
			dir <- (ghost tail) tail
			nextloc <- 0
			move <- 0
			manHatDist <- 0
			if: vitality = 1 {
				
				if: (myLoc value) > (loc value) {
					manHatDist <- (myLoc value) - (loc value)
				} else: {
					manHatDist <- (loc value) - (myLoc value)
				}
				if: (myLoc tail) > (loc tail) {
					manHatDist <- manHatDist + (myLoc tail) - (loc tail)
				} else: {
					manHatDist <- manHatDist + (loc tail) - (myLoc tail)
				}
				if: myVitality > (manHatDist * 254) {
					edibleGhosts <- edibleGhosts + 1	
				} else: {}
				//mark fright mode ghosts
				acc <- grid: acc set: loc to: 7
			} else: {
				if: vitality = 0 {
					badGhostCount <- badGhostCount + 1
					//treat normal mode ghosts as a wall for now
					acc <- grid: acc set: loc to: 0
					while: { move < 4 } do: {
						nextloc <- calcPos: move loc
						if: (grid: acc inBounds?: nextloc) {
							acc <- grid: acc update: nextloc with: :oldval {
								if: oldval = 3 {
								} else: {
									oldval <- 0
								}
								oldval
							}
						} else: {}
						move <- move + 1
					}
				} else: {}
			}
			acc
		}
		//default behavior, target all yummy things
		target0 <- 2
		target1 <- 3
		target2 <- 4
		target3 <- 7
		if: badGhostCount > 0 {
		} else: {
			if: totalGhosts > 0 {
				//ignore power pellets when there are no ghosts in normal mode
				target1 <- 2
				if: edibleGhosts > 0 {
					//ignore anything except edible ghosts when some are in range
					target0 <- 7
					target1 <- 7
					target2 <- 7
				} else: {}
			} else: {}
		}
		//make sure my location is marked clear even if there is a ghost nearby
		grid <- grid: grid set: myLoc to: 1
		visited <- treeMap: grid :row {
			treeMap: row :el { 0 }
		}
		path <- advancer: [(makeContClos: grid myLoc [])]
		if: (path isInteger?) {
			print: 42
			path <- [0]
		} else: {}
		#[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]
	}
}