Maint Street / Tank Dominoes -- New problem

I’ve fixed the code below to cross off colors as they are matched. Yet, colors the player has already done, are somehow reviving / turning back on.

Load the following.

Double Click one blink once. Green “building”.
Double Click a second blink, two times. Red “Building”

Triple click a third blink. “Car”.

Match the color face on the car, to the corresponding building.
Single Click.
Matching color face on car goes off. Good. Expected.

take that same car to the next building. Attempt to repeat the process, … matching the car face to that building’s color.

Click

That matching light goes off. Good. Expected.

Previous light comes back on.

WHY.

Related

  1. Single Clicking a blink, unattached, brings up the entire car, on it’s own. This is unexpected. Why?

  2. Single Clicking a blink that is attached and clustered also brings up a garbled result that is not “Standard” car, four faces on one of each color, Face 2 and 5 off.

  3. Thankfully I can’t reproduce it now, but I had a curly brace out of place in one load, and the entire string of blinks connected to the dev blink (and the dev blink itself) all loaded to “car” immediately after “teaching” was over. Why?


byte BuildingSend = 0;
byte BuildingColor = 0;
byte CarColor = 0;
Color CarColorList[4] = {CYAN, WHITE, ORANGE, MAGENTA};
Color BuildingColorList[4] = {GREEN, RED, YELLOW, BLUE};

byte GreenCrossed = 0;
byte RedCrossed = 0;
byte BlueCrossed = 0; 
byte YellowCrossed = 0; 

void setup() {
  // put your setup code here, to run once:
//Main Street Pre-Alpha Feel-Around 06/23/21
//4 blinks in one row, connected. One blink for die. 4 blinks as cars. Each car has to go down "Main Street" to run errands on this very busy Saturday. 
//Green Grocers, A Doctor's Appointment, The Post Office, and The Library. Roll Die. ROTATE blink over the top of Main Street, and over other cars (Traffic Jam) 
// in effort to have your blink's face with the corresponding color match the given location's face, at the time they are there. First to unload all faces wins. 
// Both directions of travel allowed, but turn is skipped if another blink is over-taking you. 

  //setColorOnFace(dim (WHITE, 50), 2);
  //setColorOnFace(dim (WHITE, 50), 5); 
  //White to set up the double stripe lined road.
  //Green Grocers, Doctor/Red, Post Office/Blue, Library / Yellow

  setColor(OFF);

}

void loop() {
// ID Paint Color for "The Car"
  if (buttonLongPressed()){
    setColorOnFace(CarColorList[CarColor], 2);
    setColorOnFace(OFF, 5);
    CarColor = (CarColor + 1) % 4;
    
  }
//Swap " List " between first and second "Building Color"
//Building Colors / Attractions 
  if (buttonDoubleClicked()){
    setColorOnFace(BuildingColorList[BuildingColor], 0);
    setColorOnFace(BuildingColorList[BuildingColor], 1);
    setColorOnFace(BuildingColorList[BuildingColor], 3);
    setColorOnFace(BuildingColorList[BuildingColor], 4);
    setValueSentOnAllFaces(BuildingSend);
    BuildingSend = (BuildingSend + 1) % 4;
    BuildingColor = (BuildingColor + 1) % 4;
  }
  // The "Car"
  
  if (buttonMultiClicked()){
    
    if (GreenCrossed == 0);
      {
        setColorOnFace(GREEN, 0);
      }
      
    
    if (RedCrossed == 0);
      {
        setColorOnFace(RED, 1);
      }

    if (YellowCrossed == 0);
      {
        setColorOnFace(YELLOW, 3);
      }

    if (BlueCrossed == 0);
      {
        setColorOnFace(BLUE, 4);
      }
      
}

//The Logistics


  if (buttonSingleClicked())
  {
    if (getLastValueReceivedOnFace(0) == 0)
    {
        setColorOnFace (OFF, 0);
        GreenCrossed = 1;
    }

    if (getLastValueReceivedOnFace(1) == 1)
    {
       setColorOnFace (OFF, 1);
       RedCrossed = 1;
    }

    if (getLastValueReceivedOnFace(3) == 2)
    {
       setColorOnFace (OFF, 3);
       YellowCrossed = 1; 
    }

   if (getLastValueReceivedOnFace(4) == 3)
   {
      setColorOnFace (OFF, 4);
      BlueCrossed = 1;
    }


/// Added June 26 
if (isValueReceivedOnFaceExpired(0))
{
  if (GreenCrossed = 0);
    {
        setColorOnFace(GREEN, 0);
    }
}

if (isValueReceivedOnFaceExpired(1))
{
    if (RedCrossed = 0); 
      {
        setColorOnFace(RED, 1);
      }
}

if (isValueReceivedOnFaceExpired(3))
{
    if (YellowCrossed = 0);
      {
        setColorOnFace(YELLOW, 3);
      }
}

if (isValueReceivedOnFaceExpired(4))
{
    if (BlueCrossed = 0);
      {
        setColorOnFace(BLUE, 4);
      }
}

//// Remove entire block here if needed

//&& BuildingSend == 0
//&& BuildingSend == 1
//&& BuildingSend == 2
//&& BuildingSend == 3



}

}

You’ll want to update the buildingSend before sending on all faces to make sure internal state and what the Blink is broadcasting to others are in sync

    BuildingSend = (BuildingSend + 1) % 4;
    setValueSentOnAllFaces(BuildingSend);

Careful! :slight_smile:

The = assigns a value to the variable, while the == is a comparator that returns a value of true or false

In this case that statement will always evaluate to false and set GreenCrossed to 0 which is clearly not your intention. Keep the great posts coming, everyone can learn from these, it’s a very common mistake. Next I’ll look to answer your actual 3 questions :slight_smile:

(Edit: Explained below even clearer)

The formatting of the code here can help show scope. Currently, the code labeled “added June 26th” only executes on a single click. Because it is not indented it looks like it is intended to be outside of the single click routine. The Arduino IDE has a convenient feature to auto format your code with control/command + t. This helps me spot any issues I may have with my curly braces and consequently scope.

This should help to explain question 1 & 2

Blinks default to sending 0 on all faces and similarly, Blinks default to having received 0 on all faces. This statement will return true without anything else being set since it is true given the default values of 0. In my programs, I like to only check for the last received value when I have first checked to make sure it isn’t expired (i.e. the neighboring Blink is still present and on).

There are of course reasons that you might want to check the last value received even after a neighbor has departed, but in this case, I think it would be wise to simply store that last value in a variable/array named for its use.

I am aware that = and == are different.

And that’s about it.

I had other logic in this same code wanting to do the opposite. So now I even further confused.

Knowing they are different is a great start. Knowing what each of them are for is the next step.

Use = when you want to assign a value to a variable. i.e. CarColorIndex = 3
This is the same as commanding CarColorIndex to be 3, and now it is 3.

Use == when you want to compare two values (such as bytes or integers). You will use this in if statements I.e if(CarColorIndex == 3)
This is the same as asking the question “are these two values equal?” (Does CarColorIndex equal 3?)

Hope these tips continue to clarify

Wait. Indents actually matter to the compiler?! I ultimately thought it came down to personal preference as an ad hoc aid to help the programer as they were coding.

Any and all blinks sending 0 at default probably explains a lot. … Cant wait to get back home to trying all of these.

1 Like

Indents do not matter to the compiler, just help in human legibility when sharing your code with others or scanning yourself. Of course, not necessary, but a best practice. As for spaces vs tabs, I won’t open that can :slight_smile:

Ok. I think I figured out what threw me here.

What controls? Where is the priority?

That is, I have the If statement that is testing a logic conditional. And then, after that, as you stated, I have (essentially) “Hey, GreenCrossed! Become Zero!”

Does " If " not force the issue of testing a conditional, over = being an assigner ? While I take your point, I don’t automatically follow how " = " gets to simply tell " if " … to not if. That is, even though GreenCrossed = 0 is within the if, … it still becomes zero, regardless?

That is, in so many words, I didn’t know that assignment … apparently can happen “anywhere”, even when you are trying to do very much the opposite, and have all the evidence pointing to the opposite as well.

When you do if (RedCrossed = 0), you are doing 2 things here:

1 - Assigning the value 0 to RedCrossed.
2 - Executing the statement if (RedCrossed). As you just assigned 0 to RedCossed, this results into if (0). In C/C++ 0 is equal to false (and non-zero is equal to true) so you are doing, in the end, if (false) which makes the if block never execute (as the block only executes when the parameters evaluate as true).

1 Like