Updated references from old to new module names.
[cellular-automata.git] / 001 / src / life_cell.erl
CommitLineData
982ec720 1-module(life_cell).
d2a0e2f9
SK
2-behaviour(gen_server).
3
4
5%% API
6-export([start_link/1]).
7
8%% Callbacks
9-export([init/1
10 ,handle_call/3
11 ,handle_cast/2
12 ,handle_info/2
13 ,terminate/2
14 ,code_change/3
15 ]).
16
17
18-record(state, {id :: integer()
19 ,name :: string()
20 ,cell_state :: 0 | 1
21 ,neighbors :: list(atom())
22 ,live_neighbors :: integer()
23 ,num_neighbors :: integer()
24 ,replies_pending :: integer()
25 }).
26
27
28%% ============================================================================
29%% API
30%% ============================================================================
31
32start_link({_ID, Name, _NeighborNames}=Datum) ->
33 ServerName = {local, Name},
34 Args = [Datum],
35 Opts = [],
36 gen_server:start_link(ServerName, ?MODULE, Args, Opts).
37
38
39%% ============================================================================
40%% Callbacks
41%% ============================================================================
42
43init([{ID, Name, NeighborNames}]) ->
44 State = #state{id=ID
45 ,name=Name
46 ,cell_state=crypto:rand_uniform(0, 2)
47 ,neighbors=NeighborNames
48 ,num_neighbors=length(NeighborNames)
49 ,live_neighbors=0
50 ,replies_pending=0
51 },
52 {ok, State}.
53
54
55terminate(_Reason, State) ->
56 {ok, State}.
57
58
59code_change(_Old, State, _Other) ->
60 {ok, State}.
61
62
63handle_call(_Msg, _From, State) ->
64 {reply, ok, State}.
65
66
172421cb 67handle_cast(tick,
d2a0e2f9
SK
68 #state{name=Name
69 ,neighbors=Neighbors
70 ,num_neighbors=NumNeighbors
71 }=State) ->
172421cb 72 ok = cast_all(Neighbors, {request_state, Name}),
d2a0e2f9
SK
73 {noreply, State#state{replies_pending=NumNeighbors}};
74
75
172421cb
SK
76handle_cast({request_state, Requester}, State) ->
77 ok = gen_server:cast(Requester, {response_state, State#state.cell_state}),
d2a0e2f9
SK
78 {noreply, State};
79
80
172421cb 81handle_cast({response_state, NeighborState},
d2a0e2f9
SK
82 #state{id=ID
83 ,replies_pending=Pending
84 ,cell_state=CellState
85 ,live_neighbors=LiveNeighbors
86 }=State) ->
87
88 NewPending = Pending - 1,
89 NewLiveNeighbors = LiveNeighbors + NeighborState,
90
91 NewState = State#state{replies_pending=NewPending
92 ,live_neighbors=NewLiveNeighbors
93 },
94
95 case NewPending of
96 0 ->
97 NewCellState = new_state(CellState, NewLiveNeighbors),
982ec720 98 ok = life_time:tock(ID, NewCellState),
d2a0e2f9
SK
99
100 {noreply, NewState#state{live_neighbors=0
101 ,cell_state=NewCellState
172421cb
SK
102 }
103 };
d2a0e2f9
SK
104
105 _N ->
106 {noreply, NewState}
107 end;
108
172421cb
SK
109
110handle_cast(_Msg, State) ->
111 {noreply, State}.
d2a0e2f9
SK
112
113
114handle_info(_Msg, State) ->
115 {noreply, State}.
116
117
118%% ============================================================================
119%% Internal
120%% ============================================================================
121
172421cb
SK
122cast_all([], _) -> ok;
123cast_all([Server | Servers], Msg) ->
124 ok = gen_server:cast(Server, Msg),
125 cast_all(Servers, Msg).
d2a0e2f9
SK
126
127
128new_state(1, LiveNeighbors) when LiveNeighbors < 2 -> 0;
129new_state(1, LiveNeighbors) when LiveNeighbors < 4 -> 1;
130new_state(1, LiveNeighbors) when LiveNeighbors > 3 -> 0;
131new_state(0, LiveNeighbors) when LiveNeighbors =:= 3 -> 1;
132new_state(State, _LiveNeighbors) -> State.
This page took 0.03691 seconds and 4 git commands to generate.