-
Notifications
You must be signed in to change notification settings - Fork 1
/
Doorscape.ino
160 lines (137 loc) · 3.81 KB
/
Doorscape.ino
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
bool amDoor = false;
byte doorCombo[6] = {8, 8, 8, 8, 8, 8};
Color cardColors[9] = {RED, YELLOW, GREEN, BLUE, RED, YELLOW, GREEN, BLUE, dim(WHITE, 50)};
enum cardTypes {REDCARD, YELCARD, GRECARD, BLUCARD, REDTRAP, YELTRAP, GRETRAP, BLUTRAP, EMPTY};
byte deckContents[13] = {REDCARD, YELCARD, GRECARD, BLUCARD, REDCARD, YELCARD, GRECARD, BLUCARD, REDTRAP, YELTRAP, GRETRAP, BLUTRAP, EMPTY};
byte deckPosition = 0;
Timer doorTimer;
#define DOOR_CODE_TIME 20000
Timer drawAnimTimer;
#define DRAW_ANIM_TIME 400
bool isSolved = false;
void setup() {
// put your setup code here, to run once:
randomize();
shuffleDeck();
}
void loop() {
if (amDoor) {
doorLoop();
} else {
cardLoop();
cardDisplay();
}
}
void doorLoop() {
if (buttonMultiClicked()) {
if (buttonClickCount() == 3 ) {
amDoor = false;
}
}
if (doorTimer.isExpired()) {
//reset doorTimer
doorTimer.set(DOOR_CODE_TIME);
//randomize door code
FOREACH_FACE(f) {
doorCombo[f] = random(4);
if (doorCombo[f] == 4) {
doorCombo[f] = 8;
}
}
//reset isSolved
isSolved = false;
}
//look at neighbors, determine if the combo has been made
byte correctNeighbors = 0;
FOREACH_FACE(f) {
if (!isValueReceivedOnFaceExpired(f)) {//neighbor!
if (doorCombo[f] < 4) {//this face WANTS a neighbor
byte neighborColor = getCardColor(getLastValueReceivedOnFace(f));
if (neighborColor == doorCombo[f]) {
correctNeighbors++;
}
}
} else {//no neighbor!
if (doorCombo[f] == 8) {//this face wants NO NEIGHBOR
correctNeighbors++;
}
}
}//end of neighborhood check loop
if (correctNeighbors == 6) {
isSolved = true;
}
if (isSolved) {
setColor(WHITE);
setColorOnFace(RED, random(5));
setColorOnFace(YELLOW, random(5));
setColorOnFace(GREEN, random(5));
setColorOnFace(BLUE, random(5));
} else {
FOREACH_FACE(f) {
setColorOnFace(cardColors[doorCombo[f]], f);
}
}
}
void cardLoop() {
if (buttonSingleClicked()) {
if (deckPosition < 12) {
deckPosition++;
drawAnimTimer.set(DRAW_ANIM_TIME);
} else {
//BAD TIMES YO
}
}
if (buttonDoubleClicked()) {
deckPosition = 0;
shuffleDeck();
}
if (buttonMultiClicked()) {
if (buttonClickCount() == 3 ) {
amDoor = true;
}
}
byte sendData = (amDoor << 4) | (deckContents[deckPosition]);
setValueSentOnAllFaces(sendData);
}
void cardDisplay() {
//am I idle, or am I drawing?
if (drawAnimTimer.isExpired()) {//just sitting idly showing cards
setColor(cardColors[deckContents[deckPosition]]);
if (deckPosition < 12) {
setColorOnFace(cardColors[deckContents[deckPosition + 1]], 0);
}
} else {//doing draw animation
byte currentFrame = map(DRAW_ANIM_TIME - drawAnimTimer.getRemaining(), 0, DRAW_ANIM_TIME, 1, 3);
switch (currentFrame) {
case 1:
setColor(cardColors[deckContents[deckPosition - 1]]);
setColorOnFace(cardColors[deckContents[deckPosition]], 0);
break;
case 2:
setColor(cardColors[deckContents[deckPosition - 1]]);
setColorOnFace(cardColors[deckContents[deckPosition]], 0);
setColorOnFace(cardColors[deckContents[deckPosition]], 1);
setColorOnFace(cardColors[deckContents[deckPosition]], 5);
break;
case 3:
setColor(cardColors[deckContents[deckPosition]]);
setColorOnFace(cardColors[deckContents[deckPosition - 1]], 3);
break;
}
}
}
void shuffleDeck() {
for (byte i = 0; i < 30; i++) {
byte swapA = random(11);
byte swapB = random(11);
byte temp = deckContents[swapA];
deckContents[swapA] = deckContents[swapB];
deckContents[swapB] = temp;
}
}
byte getAmDoor(byte data) {
return (data >> 4);
}
byte getCardColor(byte data) {
return (data & 15);
}