-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrule.gleam
86 lines (78 loc) · 2.13 KB
/
rule.gleam
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//// src/rule.gleam
////
//// Module: rule
////
//// In this module, the Rule type and its functions are defined.
////
//// API:
//// - Rule
//// - new() -> Rule
//// - add_case(Rule, Neighbourhood, Cell) -> Rule
//// - apply(Rule, Neighbourhood) -> Cell
//// Internal:
//// * None
// Local imports:
import cell as cel
import neighbourhood as nei
// IMPORTANT NOTE: In the traditional game of life, the next state is only determined by its current state and it's alive neighbour count. We instead determine the next state based on the current state and it's neighbourhood (exact equality so multiple versions of the neighbourhood can be differentiated even if they share the alive count).
// Public:
/// Rule type definition.
/// A rule is a function that takes a cell with it's neighbourhood and returns the next state of the cell after a tick.
pub type Rule =
fn(nei.Neighbourhood) -> cel.Cell
/// Rule constructor.
pub fn new() -> Rule {
fn(neighbourhood: nei.Neighbourhood) -> cel.Cell {
case neighbourhood {
#(_cell1, _cell2, _cell3, _cell4, cell5, _cell6, _cell7, _cell8, _cell9) ->
cell5
}
}
}
/// Add case to rule.
pub fn add_case(
rule: Rule,
neighbourhood_outer: nei.Neighbourhood,
next_state: cel.Cell,
) -> Rule {
fn(neighbourhood_inner: nei.Neighbourhood) -> cel.Cell {
case neighbourhood_inner {
any if any == neighbourhood_outer -> next_state
any -> rule(any)
}
}
}
/// Add logic to rule.
pub fn add_logic(rule: Rule, logic: fn(nei.Neighbourhood) -> cel.Cell) -> Rule {
fn(neighbourhood: nei.Neighbourhood) -> cel.Cell {
case neighbourhood {
#(
cell1,
cell2,
cell3,
cell4,
cel.Alive(location),
cell6,
cell7,
cell8,
cell9,
) ->
logic(#(
cell1,
cell2,
cell3,
cell4,
cel.new(location, True),
cell6,
cell7,
cell8,
cell9,
))
any -> rule(any)
}
}
}
// Apply rule to cell and it's neighbourhood.
pub fn apply(rule: Rule, neighbourhood: nei.Neighbourhood) -> cel.Cell {
rule(neighbourhood)
}