Support including initial configuration in ALPACA description.
catseye
12 years ago
|
0 |
/*
|
|
1 |
John Conway's Game of Life, plus an initial configuration.
|
|
2 |
*/
|
|
3 |
|
|
4 |
state Dead " " to Alive when 3 Alive and 5 Dead;
|
|
5 |
state Alive "*" to Dead when 4 Alive or 7 Dead
|
|
6 |
begin
|
|
7 |
**
|
|
8 |
* *
|
|
9 |
*
|
0 | 0 |
"""
|
1 | 1 |
Direct evaluator of ALPACA AST nodes.
|
|
2 |
|
|
3 |
XXX move some of these out into alpaca.analysis
|
2 | 4 |
|
3 | 5 |
"""
|
4 | 6 |
|
5 | 7 |
from alpaca.ast import AST
|
|
8 |
from alpaca.playfield import Playfield
|
6 | 9 |
|
7 | 10 |
|
8 | 11 |
def eval_state_ref(playfield, x, y, ast):
|
|
99 | 102 |
|
100 | 103 |
|
101 | 104 |
def get_default_state(ast):
|
102 | |
map = {}
|
103 | 105 |
assert ast.type == 'Alpaca'
|
104 | 106 |
defns = ast.children[0]
|
105 | 107 |
assert defns.type == 'Definitions'
|
|
108 | 110 |
return defn.value
|
109 | 111 |
|
110 | 112 |
|
|
113 |
def get_defined_playfield(ast):
|
|
114 |
assert ast.type == 'Alpaca'
|
|
115 |
playast = ast.children[1]
|
|
116 |
assert playast.type == 'Playfield'
|
|
117 |
repr_map = construct_representation_map(ast)
|
|
118 |
pf = Playfield(get_default_state(ast), repr_map)
|
|
119 |
for (x, y, ch) in playast.value:
|
|
120 |
pf.set(x, y, repr_map[ch])
|
|
121 |
pf.recalculate_limits()
|
|
122 |
return pf
|
|
123 |
|
|
124 |
|
111 | 125 |
def evolve_playfield(playfield, new_pf, ast):
|
112 | 126 |
# XXX TODO + 1, - 1's in here should reflect the maximum
|
113 | 127 |
# neighbourhood used by any rule
|
|
128 |
if playfield.min_y is None:
|
|
129 |
return
|
114 | 130 |
y = playfield.min_y - 1
|
115 | 131 |
while y <= playfield.max_y + 1:
|
116 | 132 |
x = playfield.min_x - 1
|
11 | 11 |
from alpaca.eval import (
|
12 | 12 |
evolve_playfield,
|
13 | 13 |
construct_representation_map,
|
14 | |
get_default_state
|
|
14 |
get_default_state,
|
|
15 |
get_defined_playfield,
|
15 | 16 |
)
|
16 | 17 |
from alpaca.parser import Parser
|
17 | 18 |
from alpaca.playfield import Playfield
|
|
51 | 52 |
default_state = get_default_state(ast)
|
52 | 53 |
repr_map = construct_representation_map(ast)
|
53 | 54 |
|
54 | |
# XXX if has_own_defined_playfield(ast): pf = get_playfield_from(ast): else...
|
55 | |
file = open(args[1])
|
56 | |
pf = Playfield(default_state, repr_map)
|
57 | |
pf.load(file)
|
58 | |
file.close()
|
|
55 |
pf = get_defined_playfield(ast)
|
|
56 |
if pf is None:
|
|
57 |
file = open(args[1])
|
|
58 |
pf = Playfield(default_state, repr_map)
|
|
59 |
pf.load(file)
|
|
60 |
file.close()
|
59 | 61 |
|
60 | 62 |
count = 0
|
61 | 63 |
print str(pf)
|
70 | 70 |
|
71 | 71 |
def alpaca(self):
|
72 | 72 |
defns = []
|
73 | |
playfield = AST('Playfield', value=None)
|
74 | 73 |
defns.append(self.defn())
|
|
74 |
pf = None
|
75 | 75 |
while self.scanner.consume(';'):
|
76 | 76 |
defns.append(self.defn())
|
77 | |
if self.scanner.consume('begin'):
|
78 | |
playfield = self.scanner.read_playfield()
|
|
77 |
# we shan't consume() this token, lest the scanner jump
|
|
78 |
# ahead assuming that the next token is normal. If the
|
|
79 |
# scanner is already on this token, the rest of the scanner
|
|
80 |
# text is the playfield; so we just check on() here.
|
|
81 |
if self.scanner.on('begin'):
|
|
82 |
pf = self.scanner.scan_playfield()
|
79 | 83 |
else:
|
80 | 84 |
self.scanner.expect('.')
|
|
85 |
playfield = AST('Playfield', value=pf)
|
81 | 86 |
return AST('Alpaca', [AST('Definitions', defns), playfield])
|
82 | 87 |
|
83 | 88 |
def defn(self):
|
4 | 4 |
self.recalculate_limits()
|
5 | 5 |
self.map = map
|
6 | 6 |
self._inverted_map = dict([(v, k) for (k, v) in map.iteritems()])
|
|
7 |
|
|
8 |
def copy(self, pf):
|
|
9 |
y = pf.min_y
|
|
10 |
while y <= pf.max_y:
|
|
11 |
x = pf.min_x
|
|
12 |
while x <= pf.max_x:
|
|
13 |
self.set(x, y, pf.get(x, y))
|
|
14 |
x += 1
|
|
15 |
y += 1
|
|
16 |
self.recalculate_limits()
|
7 | 17 |
|
8 | 18 |
def load(self, f):
|
9 | 19 |
y = 0
|
|
52 | 62 |
def __str__(self):
|
53 | 63 |
s = ''
|
54 | 64 |
y = self.min_y
|
|
65 |
if y is None:
|
|
66 |
return ''
|
55 | 67 |
while y <= self.max_y:
|
56 | 68 |
x = self.min_x
|
57 | 69 |
while x <= self.max_x:
|
51 | 51 |
raise ValueError("this should never happen, "
|
52 | 52 |
"self.text=(%s)" % self.text)
|
53 | 53 |
|
|
54 |
def scan_playfield(self):
|
|
55 |
"""Called when the token which introduces the playfield has
|
|
56 |
already just been scanned.
|
|
57 |
|
|
58 |
"""
|
|
59 |
self.scan_pattern(r'[ \t]*', 'whitespace')
|
|
60 |
self.scan_pattern(r'[\n\r]', 'eol')
|
|
61 |
elems = []
|
|
62 |
y = 0
|
|
63 |
while self.text:
|
|
64 |
x = 0
|
|
65 |
while self.scan_pattern(r'[^\n\r]', 'arbitrary character'):
|
|
66 |
#print repr((x, y, self.token))
|
|
67 |
elems.append((x, y, self.token))
|
|
68 |
x += 1
|
|
69 |
self.scan_pattern(r'[\n\r]', 'eol')
|
|
70 |
y += 1
|
|
71 |
return elems
|
|
72 |
|
54 | 73 |
def expect(self, token):
|
55 | 74 |
if self.token == token:
|
56 | 75 |
self.scan()
|