changeset 37:e613d243d2bc

Merge
author Michael Pavone <pavone@retrodev.com>
date Sat, 26 Jul 2014 03:18:17 -0700
parents c0b3922646d8 (diff) c68c03a0e072 (current diff)
children 6b9b21456cf4
files
diffstat 2 files changed, 170 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/code/README	Sat Jul 26 02:32:59 2014 -0700
+++ b/code/README	Sat Jul 26 03:18:17 2014 -0700
@@ -0,0 +1,119 @@
+Team: Rhope Burn
+Language: Quiche
+Members: Michael Pavone, William Morgan
+
+HOW TO BUILD:
+
+To build our Lambda-man AI, you first need to build the lmc compiler. lmc is
+written in a WIP language called Quiche. The steps to get a Quiche toolchain
+setup are as follows:
+
+1) Make a local clone of hg repo: http://rhope.retrodev.com/repos/tabletprog
+2) Make sure the d8 Javascript shell (built from Chrome's v8) is in your path
+   -- see this page for instructions on how to build d8: 
+		https://developers.google.com/v8/build
+3) Install the Boehm GC development package (libgc-dev on Debian derivatives)
+3) Install gcc if it is not already present
+
+Once you have the toolchain in place, navigate to the Quiche repo clone in a
+terminal and execute the following command.
+
+./compile PATH/TO/lmc.tp
+
+If all goes well an executable named lmc will be produced at PATH/TO/lmc. This
+program takes a .lm file as an argument and produces "GCC" assembly code on
+stdout.
+
+ABOUTE QUICHE:
+
+Quiche (previously called TP) is a language I (Michael Pavone) work on in my
+spare time. It draws rather heavily from Smalltalk with a smattering of
+influence from other languages. In theory, it's reason for existence is to be
+a good target for a structured editor on mobile devices. In practice, I'd
+probably be better served targeting an existing language, but that's not nearly
+as much fun.
+
+The current implementation is a quick and dirty bootstrap compiler written in
+Javascript that produces C code. A self-hosted compiler is in progress.
+
+A Quiche program is made up of one or more modules. At runtime, a module is
+just a plain object. Only one module is allowed per source file. The top level
+of a Quiche source file is required to either be an object literal or a lambda
+that returns an object. After all modules used are initialized, execution
+starts in the main method of the main module. Currently, the names of all
+available modules occupy the top level of the symbol table; however, this will
+change in the self-hosted compiler.
+
+QUICHE SYNTAX:
+
+To make reading lmc's code a bit easier, here is a quick primer on Quiche's
+syntax.
+
+line comment: //
+block comment: /* */
+assignment: foo <- bar
+list literal: [1 2 3 4]
+array literal: #[1 2 3 4]
+string literal "foo bar"
+lambda: :arg {
+	arg + 1
+}
+object literal: #{
+	foo <- "blah blah"
+	bar <- :val {
+		foo <- val . " blah"
+	}
+}
+method invokation/function application:
+	someval someFunOrMeth
+	someFunOrMeth: someval
+	some: val1 Fun: val2 OrMeth: val3
+	some:Fun:OrMeth: val1 val2 val3
+operators:
+	+,-,/,* -- basic arithmetic
+	=,!=,>=,<= -- comparison 
+	and,or,xor -- bitwise
+	% -- modulus
+	. -- concatenation
+	| -- cons
+	
+ABOUT LMC:
+
+lmc implements a subset of Quiche for the LamCo General Compute Coprocessor. It
+uses the parser, ast and symbols modules from the work in progress self-hosted
+compiler. Object literals are not supported apart from the top-level object
+that represents the module. That object is used to populate the global
+environment. Closures are properly supported; however, some elements that are
+implemented using closures in the normal Quiche compiler (namely if:else and 
+while:do) are instead implemented as special forms that do not introduce a new
+scope. Array literals are used for producing tuples as the GCC does not really
+support the former and Quiche does not currently support the latter.
+
+Tail call optimization is notcurrently implemented; however, while:do is
+implemented using TSEL so we were able to do without.
+
+LIGHTNING ROUND SOLUTION:
+
+Our lightning round solution is relatively simple. Each step, we do a breadth
+first search for something desirable (pellet, power pellet, fruit or fright
+mode ghost). Cells occupied by normal mode ghosts and their immediate neighbors
+are marked as walls to provide simple avoidance behavior.
+
+We translate the grid to a tree format to provide more efficient lookup. An
+identically dimensioned tree is used for keeping track of visited nodes for our
+search.
+
+This seems to work surprisingly well given how simple it is. I'm a bit
+concerned about our cycle usage when the nearest "good" thing is far away,
+hopefully that will not be an issue.
+
+We noticed that the "undefined" input to main appears to be the ghost code, but
+we did not have time to take advantage of it for the lightning round.
+
+The code for this AI is located in dotScanner.lm
+
+OTHER FILES:
+
+test.lm - random collection of syntax for exercising parts of the compiler
+simple.lm - picks each direction in order every 4 turns
+mike00.lm - test program for developing library functions
--- a/code/dotScanner.lm	Sat Jul 26 02:32:59 2014 -0700
+++ b/code/dotScanner.lm	Sat Jul 26 03:18:17 2014 -0700
@@ -260,10 +260,12 @@
 				} 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
@@ -280,28 +282,76 @@
 	}
 
 	step <- :myState world {
-		grid <- makeTree: (map: (world value) :row { makeTree: row })
 		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
+			dir <- (ghost tail) tail
+			nextloc <- 0
+			move <- 0
+			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
+					while: { move < 4 } do: {
+						nextloc <- calcPos: move loc
+						if: (grid: acc inBounds?: nextloc) {
+							acc <- grid: acc set: nextloc to: 0
+						} else: {}
+						move <- move + 1
+					}
+				} else: {}
+			}
+			acc
+		}
+		//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]