224 lines
5.7 KiB
C++
224 lines
5.7 KiB
C++
enum signalStates { PREPARE, INERT, GO, RESOLVE, CHECK, END };
|
|
byte signalState = PREPARE;
|
|
enum player {PLAYER1, PLAYER2, PLAYER3, PLAYER4, PLAYER5, PLAYER6};//these modes will simply be different colors
|
|
byte player = PLAYER1;//the default mode when the game begins
|
|
byte player_num = 0;
|
|
byte chosen_player = 6;
|
|
Timer warn_timer;
|
|
Timer check_timer;
|
|
void loop() {
|
|
switch (signalState) {
|
|
case PREPARE:
|
|
prepareLoop();
|
|
break;
|
|
case INERT:
|
|
case GO:
|
|
case RESOLVE:
|
|
playLoop();
|
|
break;
|
|
case CHECK:
|
|
checkLoop();
|
|
break;
|
|
case END:
|
|
endLoop();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void prepareLoop() {
|
|
FOREACH_FACE(f) {
|
|
if (getSignalState(getLastValueReceivedOnFace(f)) == INERT) {
|
|
signalState = INERT;
|
|
player = getPlayer(getLastValueReceivedOnFace(f));
|
|
player_num = player + 1;
|
|
byte sendData = (signalState << 3) + (player);
|
|
setValueSentOnAllFaces(sendData);
|
|
}
|
|
else {
|
|
if (player_num == 0) {
|
|
setColor(OFF);
|
|
}
|
|
else {
|
|
for ( byte i = 0; i < player_num; i ++) {
|
|
setColorOnFace(getColor(i+1), i);
|
|
}
|
|
}
|
|
if (buttonSingleClicked()) {
|
|
player_num = (player_num + 1) % 7;
|
|
}
|
|
if (buttonDoubleClicked() && player_num != 0) {
|
|
player = player_num - 1;
|
|
signalState = INERT;
|
|
byte sendData = (signalState << 3) + (player);
|
|
setValueSentOnAllFaces(sendData);
|
|
}
|
|
else {
|
|
setValueSentOnAllFaces(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void playLoop() {
|
|
switch (signalState) {
|
|
case INERT:
|
|
inertLoop();
|
|
break;
|
|
case GO:
|
|
goLoop();
|
|
break;
|
|
case RESOLVE:
|
|
resolveLoop();
|
|
break;
|
|
}
|
|
displaySignalState();
|
|
byte sendData = (signalState << 3) + (player);
|
|
setValueSentOnAllFaces(sendData);
|
|
}
|
|
|
|
void inertLoop() {
|
|
//set myself to GO
|
|
if (buttonSingleClicked()) {
|
|
if (chosen_player == 6) {
|
|
chosen_player = player;
|
|
}
|
|
else {
|
|
warn_timer.set(1000);
|
|
}
|
|
signalState = GO;
|
|
player = (player + 1) % (player_num);//adds one to game mode, but 3+1 becomes 0
|
|
}
|
|
//listen for neighbors in GO
|
|
FOREACH_FACE(f) {
|
|
if (!isValueReceivedOnFaceExpired(f)) { //a neighbor!
|
|
if (getSignalState(getLastValueReceivedOnFace(f)) == GO) { //a neighbor saying GO!
|
|
signalState = GO;
|
|
player = getPlayer(getLastValueReceivedOnFace(f));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void goLoop() {
|
|
signalState = RESOLVE; //I default to this at the start of the loop. Only if I see a problem does this not happen
|
|
//look for neighbors who have not heard the GO news
|
|
FOREACH_FACE(f) {
|
|
if (!isValueReceivedOnFaceExpired(f)) { //a neighbor!
|
|
if (getSignalState(getLastValueReceivedOnFace(f)) == INERT) {//This neighbor doesn't know it's GO time. Stay in GO
|
|
signalState = GO;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void resolveLoop() {
|
|
if (chosen_player == 6) {
|
|
signalState = INERT; //I default to this at the start of the loop. Only if I see a problem does this not happen
|
|
}
|
|
else {
|
|
check_timer.set(2000);
|
|
signalState = CHECK;
|
|
}
|
|
//look for neighbors who have not moved to RESOLVE
|
|
FOREACH_FACE(f) {
|
|
if (!isValueReceivedOnFaceExpired(f)) { //a neighbor!
|
|
if (getSignalState(getLastValueReceivedOnFace(f)) == GO) {//This neighbor isn't in RESOLVE. Stay in RESOLVE
|
|
signalState = RESOLVE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void checkLoop() {
|
|
if (check_timer.isExpired()) {
|
|
setColor(OFF);
|
|
signalState = END;
|
|
}
|
|
else {
|
|
setColor(WHITE);
|
|
FOREACH_FACE(f) {
|
|
if (!isValueReceivedOnFaceExpired(f)) { //a neighbor!
|
|
if (getSignalState(getLastValueReceivedOnFace(f)) == INERT) {//This neighbor isn't in RESOLVE. Stay in RESOLVE
|
|
signalState = INERT;
|
|
}
|
|
}
|
|
}
|
|
setValueSentOnAllFaces(6 << 3);
|
|
}
|
|
}
|
|
|
|
void endLoop() {
|
|
setColor(getColor(getRealPlayer(chosen_player)))
|
|
FOREACH_FACE(f) {
|
|
if (!isValueReceivedOnFaceExpired(f)) { //a neighbor!
|
|
if (getSignalState(getLastValueReceivedOnFace(f)) == PREPARE) {//This neighbor isn't in RESOLVE. Stay in RESOLVE
|
|
signalState = PREPARE;
|
|
player = PLAYER1;
|
|
player_num = 0;
|
|
chosen_player = 6;
|
|
setColor(OFF);
|
|
}
|
|
}
|
|
}
|
|
if (buttonDoubleClicked()) {
|
|
signalState = PREPARE;
|
|
player = PLAYER1;
|
|
player_num = 0;
|
|
chosen_player = 6;
|
|
setValueSentOnAllFaces(0);
|
|
}
|
|
}
|
|
|
|
void displaySignalState() {
|
|
if (warn_timer.isExpired()) {
|
|
switch (signalState) {
|
|
case INERT:
|
|
setColor(getColor(getRealPlayer(player)));
|
|
break;
|
|
case GO:
|
|
case RESOLVE:
|
|
setColor(WHITE);
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
setColor(WHITE);
|
|
}
|
|
}
|
|
|
|
Color getColor(data) {
|
|
switch (data) {
|
|
case 0:
|
|
return (makeColorRGB(0,0,0));
|
|
break;
|
|
case 1:
|
|
return (makeColorRGB(255,0,0));
|
|
break;
|
|
case 2:
|
|
return (makeColorRGB(0,255,0));
|
|
break;
|
|
case 3:
|
|
return (makeColorRGB(0,0,255));
|
|
break;
|
|
case 4:
|
|
return (makeColorRGB(255,0,255));
|
|
break;
|
|
case 5:
|
|
return (makeColorRGB(255,255,0));
|
|
break;
|
|
case 6:
|
|
return (makeColorRGB(0,255,255));
|
|
break;
|
|
}
|
|
}
|
|
|
|
byte getRealPlayer(byte data) {
|
|
return (data + 1) % player_num + 1;
|
|
}
|
|
|
|
byte getPlayer(byte data) {
|
|
return (data & 7);//returns bits E and F
|
|
}
|
|
|
|
byte getSignalState(byte data) {
|
|
return ((data >> 3) & 7);//returns bits C and D
|
|
} |