forked from mvr/barrister
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLifeUnknownState.hpp
167 lines (130 loc) · 6.18 KB
/
LifeUnknownState.hpp
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#pragma once
#include "LifeAPI.h"
#include "Bits.hpp"
#include "LifeStableState.hpp"
class LifeUnknownState {
public:
LifeState state;
LifeState unknown;
LifeState unknownStable;
LifeState glanceableUnknown;
LifeUnknownState UncertainStepMaintaining(const LifeStableState &stable) const;
LifeState ActiveComparedTo(const LifeStableState &stable) const;
bool CompatibleWith(const LifeStableState &stable) const;
std::tuple<uint64_t, uint64_t, uint64_t> UncertainStepColumn(const LifeStableState &stable, int column) const;
std::tuple<bool, bool, bool> NextForCell(const LifeStableState &stable, std::pair<int, int> cell) const;
bool KnownNext(const LifeStableState &stable, std::pair<int, int> cell) const;
bool StillGlancingFor(std::pair<int, int> cell, const LifeStableState &stable) const;
};
LifeUnknownState LifeUnknownState::UncertainStepMaintaining(const LifeStableState &stable) const {
LifeUnknownState result;
LifeState state3(false), state2(false), state1(false), state0(false);
LifeState unknown3(false), unknown2(false), unknown1(false), unknown0(false);
CountNeighbourhood(state, state3, state2, state1, state0);
CountNeighbourhood(unknown, unknown3, unknown2, unknown1, unknown0);
LifeState unequal_stable = (state ^ stable.state) | (unknownStable ^ stable.unknownStable) |
state3 | (state2 ^ stable.state2) |
(state1 ^ stable.state1) | (state0 ^ stable.state0) |
(unknown3 ^ stable.unknown3) | (unknown2 ^ stable.unknown2) |
(unknown1 ^ stable.unknown1) | (unknown0 ^ stable.unknown0);
#pragma clang loop unroll(full)
for (int i = 0; i < N; i++) {
uint64_t on3 = state3[i];
uint64_t on2 = state2[i];
uint64_t on1 = state1[i];
uint64_t on0 = state0[i];
uint64_t unk3 = unknown3[i];
uint64_t unk2 = unknown2[i];
uint64_t unk1 = unknown1[i];
uint64_t unk0 = unknown0[i];
on2 |= on3;
on1 |= on3;
on0 |= on3;
unk1 |= unk2 | unk3;
unk0 |= unk2 | unk3;
uint64_t stateon = state[i];
uint64_t stateunk = unknown[i];
uint64_t next_on = 0;
uint64_t unknown = 0;
// ALWAYS CHECK THE PHASE that espresso outputs or you will get confused
// Begin Autogenerated
unknown |= stateon & (~on1) & (~on0) & (unk1 | unk0);
unknown |= (~on2) & unk1 & (on1 | on0 | unk0);
unknown |= (~on2) & on1 & unk0 & ~((stateunk | stateon) & on0);
next_on |= (stateunk | stateon | ~unk0) & (~on2) & on1 & on0 & (~unk1);
next_on |= stateon & (~on1) & (~on0) & (~unk1) & (~unk0);
// End Autogenerated
result.state[i] = next_on;
result.unknown[i] = unknown;
uint64_t common_part = unknown &
// & ~any_unstable_unknown
~(stateon | stateunk | stable.state2[i] | stable.state1[i] | on2);
uint64_t glanceable =
common_part
& (~stable.state0[i])
& (~on1) & on0
& (unk1 | unk0);
result.glanceableUnknown[i] = glanceable;
// Remove unknown cells that we have decided were glancing
uint64_t glanceSafe = common_part & ~stable.state0[i] & ~on1;
result.unknown[i] &= ~(glanceSafe & stable.glanced[i]);
uint64_t toRestore = ~unequal_stable[i] & result.unknown[i];
result.state[i] = (result.state[i] & ~toRestore) | (stable.state[i] & toRestore);
result.unknown[i] = (result.unknown[i] & ~toRestore) | (stable.unknownStable[i] & toRestore);
result.unknownStable[i] = stable.unknownStable[i] & toRestore;
}
return result;
}
std::tuple<uint64_t, uint64_t, uint64_t> LifeUnknownState::UncertainStepColumn(const LifeStableState &stable, int column) const {
auto [on3, on2, on1, on0] = CountNeighbourhoodColumn(state, column);
auto [unk3, unk2, unk1, unk0] = CountNeighbourhoodColumn(unknown, column);
uint64_t stateon = state[column];
uint64_t stateunk = unknown[column];
uint64_t stateunkstable = unknownStable[column];
uint64_t unequal_stable =
(stateon ^ stable.state[column]) | (stateunkstable ^ stable.unknownStable[column]) |
on3 | (on2 ^ stable.state2[column]) |
(on1 ^ stable.state1[column]) | (on0 ^ stable.state0[column]) |
(unk3 ^ stable.unknown3[column]) | (unk2 ^ stable.unknown2[column]) |
(unk1 ^ stable.unknown1[column]) | (unk0 ^ stable.unknown0[column]);
on2 |= on3;
on1 |= on3;
on0 |= on3;
unk1 |= unk2 | unk3;
unk0 |= unk2 | unk3;
uint64_t next_on = 0;
uint64_t unknown = 0;
// ALWAYS CHECK THE PHASE that espresso outputs or you will get confused
// Begin Autogenerated
unknown |= (~on2) & unk1 & (on1 | on0 | unk0);
unknown |= stateon & (~on1) & (~on0) & (unk1 | unk0) ;
unknown |= (~stateunk) & (~stateon) & (~on2) & on1 & unk0 ;
unknown |= (~on2) & on1 & (~on0) & unk0 ;
next_on |= (stateunk | stateon | ~unk0) & (~on2) & on1 & on0 & (~unk1) ;
next_on |= stateon & (~on1) & (~on0) & (~unk1) & (~unk0) ;
// End Autogenerated
uint64_t unknownStable = ~unequal_stable & unknown;
return {next_on, unknown, unknownStable};
}
std::tuple<bool, bool, bool> LifeUnknownState::NextForCell(const LifeStableState &stable, std::pair<int, int> cell) const {
auto [nextColumn, nextUnknownColumn, nextUnknownStableColumn] = UncertainStepColumn(stable, cell.first);
int y = cell.second;
bool cellNext = (nextColumn & (1ULL << y)) >> y;
bool cellUnknown = (nextUnknownColumn & (1ULL << y)) >> y;
bool cellUnknownStable = (nextUnknownStableColumn & (1ULL << y)) >> y;
return {cellNext, cellUnknown, cellUnknownStable};
}
bool LifeUnknownState::KnownNext(const LifeStableState &stable, std::pair<int, int> cell) const {
auto [cellNext, cellUnknown, cellUnknownStable] = NextForCell(stable, cell);
return !cellUnknown || cellUnknownStable;
}
LifeState LifeUnknownState::ActiveComparedTo(const LifeStableState &stable) const {
return ~unknown & ~stable.unknownStable & stable.stateZOI & (stable.state ^ state);
}
bool LifeUnknownState::CompatibleWith(const LifeStableState &stable) const {
return ActiveComparedTo(stable).IsEmpty();
}
bool LifeUnknownState::StillGlancingFor(std::pair<int, int> cell, const LifeStableState &stable) const {
return !stable.state2.Get(cell) && !stable.state1.Get(cell) &&
(stable.unknown3.Get(cell) || stable.unknown2.Get(cell) || stable.unknown1.Get(cell) || stable.unknown0.Get(cell));
}