Trying to add a bit of functionality to someone else's code

So I decided to create a Secret Maze (Technoblogy - Secret Maze) for my stepmother, who loves games.

In a moment of both stupidity and audacity, I decided that I'd not only build it, I'd expand it -- I want the code to choose one of four mazes to put the player through. I figured I could read code well enough to bumble my way through, and that is rapidly proving not to be the case.

Instead of getting a working program, I've got an error --

exit status 1
expected unqualified-id before 'if'

I originally wanted to use a switch-case structure, as it seemed less clumsy, but it threw the same error, except with 'switch' instead of 'if'. Oh well.

I'm told, based on searching around via google, that I need something called a 'function' that the if-else stuff goes in... I have little idea what that means, let alone how to incorporate it. Forgive me -- the last time I did any programming, it was in Microsoft QuickBASIC (which is entirely different) and both line numbers and 486s were still in vogue!

Here is my code... can someone help me out here? I've got to have this done by Wednesday morning and I do believe I'm about to have kittens just thinking about it! (Yes, I know that's my fault.)

/* Secret Maze v2 - see http://www.technoblogy.com/show?20IY

   David Johnson-Davies - www.technoblogy.com - 14th March 2018
   ATtiny85 @ 1 MHz (internal oscillator; BOD disabled)

   Expanded by Christopher Havel aka Starhawk - 17th June 2018
   Added three new mazes and the code to randomly select one at start.
   
   CC BY 4.0
   Licensed under a Creative Commons Attribution 4.0 International license: 
   http://creativecommons.org/licenses/by/4.0/
*/

volatile int Lights, Buttons = 0;
volatile int Row = 0;

// The Maze **********************************************

// Maze definition
int MazeChoice = random(1, 5);
if (MazeChoice = 1)
  {
    const int Startx = 7, Starty = 8;
    const int Goalx = 15, Goaly = 15;
    unsigned int Maze[16] = { 0xFFFF, 0x8000, 0xFFFD, 0x4005, 0x5FF5, 0x5011, 0x5555, 0x5555,
                              0x5445, 0x57D5, 0x5015, 0x5FF5, 0x4005, 0xFFFD, 0x0001, 0xFFFF };
  }
else if (MazeChoice = 2)
  {
    const int Startx = 8, Starty = 7;
    const int Goalx = 2, Goaly = 7;
    unsigned int Maze[16] = { 0xFFFF, 0x8811, 0xAEF5, 0x8011, 0xF7C7, 0x9435, 0xA5A5, 0xA8A9,
                              0x8B85, 0xA83D, 0xAFE1, 0xE06F, 0x8B01, 0xAAF5, 0x8811, 0xFFFF };
  }
else if (MazeChoice = 3)
  {
    const int Startx = 14, Starty = 7;
    const int Goalx = 1, Goaly = 7;
    unsigned int Maze[16] = { 0xFFFF, 0x8111, 0xADB5, 0x8001, 0xB7ED, 0x8181, 0xF42F, 0xB67D,
                              0x8181, 0x566F, 0x8182, 0xB8ED, 0x8BD1, 0xEA57, 0x8001, 0xFFFF };
  }
else if (MazeChoice = 4)
  {
    const int Startx = 14, Starty = 2;
    const int Goalx = 1, Goaly = 15;
    unsigned int Maze[16] = { 0xFFFF, 0xBCEC, 0x8001, 0xD555, 0x8001, 0xBFFD, 0x8001, 0xFDFF,
                              0x8001, 0xBFFD, 0x8001, 0xAAAB, 0x8001, 0xF7FF, 0x8001, 0xFFFF };
  }
    
// Get one bit in the maze: 0,0 is top right
int Bit (int x, int y) {
  return Maze[y]>>x & 1;
}

// Returns the walls around x,y
int Look (int x, int y) {
  return Bit(x, y+1)<<3 | Bit(x+1, y)<<2 | Bit(x-1, y)<<1 | Bit(x, y-1);
}

// Tiny Tone **********************************************

const int Output = 4; 
const int Clock = 0;                               // 1 MHz
const uint8_t scale[] PROGMEM = {239,226,213,201,190,179,169,160,151,142,134,127};

void note (int n, int octave) {
  int prescaler = 8 + Clock - (octave + n/12);
  if (prescaler<1 || prescaler>15 || octave==0) prescaler = 0;
  DDRB = (DDRB & ~(1<<Output)) | (prescaler != 0)<<Output;
  OCR1C = pgm_read_byte(&scale[n % 12]) - 1;
  GTCCR = (Output == 4)<<COM1B0;
  TCCR1 = 1<<CTC1 | (Output == 1)<<COM1A0 | prescaler<<CS10;
}

void Mydelay (unsigned long millis) {
  for (volatile unsigned long i = 23*millis; i!=0; i--);
}

void Beep () {
  note(0, 4);
  Mydelay(100);
  note(0, 0);
}

// Multiplexing **********************************************

// Interrupt multiplexes display and buttons
ISR(TIMER0_COMPA_vect) {
  // Check button
  int button = ((Row<<1) + 1) % 5;
  if (PINB & 1<<button) {
    Buttons = Buttons & ~(1<<Row);
  } else {
    Buttons = Buttons | 1<<Row;
  }
  Row = (Row + 1) & 0x03;                  // Next row
  // Light LED
  button = ((Row<<1) + 1) % 5;             // Button
  int light = Row ^ 0x03;                  // LED
  if (Lights & 1<<Row) {
    DDRB = (DDRB & (1<<Output)) | 1<<Row | 1<<light;
    PORTB = 1<<light | 1<<button;
  } else {
    DDRB = (DDRB & (1<<Output)) | 1<<Row;
    PORTB = 1<<button;
  } 
}

// Setup **********************************************
  
void setup() {
  // Set up Timer/Counter0 to generate 625Hz interrupt
  TCCR0A = 2<<WGM00;                     // CTC mode
  TCCR0B = 2<<CS00;                      // /8 prescaler
  OCR0A = 249;                           // 500 Hz interrupt
  TIMSK = TIMSK | 1<<OCIE0A;             // Enable interrupt
}

// Position of player in the maze
int X = Startx, Y = Starty;

void loop () {
  Lights = Look(X, Y);                   // Display new position
  while (Buttons != 0);                  // Wait for key release
  // Have we reached goal?
  if ((X == Goalx) && (Y == Goaly)) {
    for (int n=0; n<=7; n++) {           // Success tune!
      note(n, 4);
      if (n!=4 && n!=11) n++;
      Mydelay(200);
    }
    note(0, 0);
    while (1);                           // Wait for reset
  }
  while (Buttons == 0);                  // Wait for keypress
  // Wait until keys are stable
  int keys, count = 0, lastkeys = 0;
  do {
    keys = Buttons;
    count++;
    if (lastkeys != keys) count = 0;
    lastkeys = keys;
  } while (count < 7);
  // Respond to keypress
  int dx = 0, dy = 0;                    // Movement
  if (keys & 0b1000) dy = 1; else if (keys & 0b100) dx = 1;
  else if (keys & 0b10) dx = -1; else if (keys & 0b1) dy = -1;
  // Can we go this way?
  if (Bit(X+dx, Y+dy)) Beep();           // Hit a wall
  else {
    X = X + dx; Y = Y + dy;              // Move
  }
}

This, and the rest that you seem to have added are outside a function.

int MazeChoice = random(1, 5);
if (MazeChoice = 1)
...
...

Also, = is an assignment, == is used to rest equality.

OK, I can easily correct the = to ==, but what's a function, and how do I incorporate that into the existing code so that it will work properly?

Forgive me -- as I said, my (very limited) programming background is in a different language that's procedural, and I haven't touched it in about two decades.

In your code, e.g. setup(), Beep(), MyDelay() and loop() are functions.

What you probably need is to put what you added inside loop().

I'm on a cell phone at the moment so can't have a deeper look at the code.

By the way, C/C++ is a procedural language.

Well, when you get the chance :slight_smile:

...I thought that C++ was object-oriented...?

Start, goal and maze are global variables. They should only be defined once outside any function

You can update the values in those variables at any time. For this example, perhaps setup() should do that.

The tricky part is the notation used to put the values into Maze[] only works in a definition. It doesn't work in an assignment (single =). So the easiest way to do this would be to have multiple mazes and then just point Maze to the one you want.

    int Startx, Starty;
    int Goalx, Goaly ;
    unsigned int Maze1[16] = { 0xFFFF, 0x8000, 0xFFFD, 0x4005, 0x5FF5, 0x5011, 0x5555, 0x5555,
                              0x5445, 0x57D5, 0x5015, 0x5FF5, 0x4005, 0xFFFD, 0x0001, 0xFFFF };
    unsigned int Maze[]; //note this assigns no size or storage so when it starts, this variable points to nothing

void setup() {
// Maze definition
int MazeChoice = random(1, 5);
if (MazeChoice == 1)
  {
    Startx = 7;
    Starty = 8;
    Goalx = 15;
    Goaly = 15;
    Maze[] = Maze1;
  }
else if (MazeChoice == 2)
  {

THANK YOU MorganS! It compiles now :slight_smile: although I had to tinker a little with it, I was able to determine from the errors I got, what was necessary.

The next challenge is to get the IDE working with my TL866A chip programmer, so that I can upload the bootloader and sketch to the chip. Should I start a new thread with that?

Here is the working code...

/* Secret Maze v2 - see http://www.technoblogy.com/show?20IY

   David Johnson-Davies - www.technoblogy.com - 14th March 2018
   ATtiny85 @ 1 MHz (internal oscillator; BOD disabled)

   Expanded by Christopher Havel aka Starhawk - 17th June 2018
   Added three new mazes and the code to randomly select one at start.
   Thank you to 'sterretje' and 'MorganS' on the Arduino Forums for your
   kindly assistance with this task.
   
   CC BY 4.0
   Licensed under a Creative Commons Attribution 4.0 International license: 
   http://creativecommons.org/licenses/by/4.0/
*/

volatile int Lights, Buttons = 0;
volatile int Row = 0;

// The Maze **********************************************

int Startx, Starty;
int Goalx, Goaly ;
unsigned int Maze1[16] = { 0xFFFF, 0x8000, 0xFFFD, 0x4005, 0x5FF5, 0x5011, 0x5555, 0x5555,
                              0x5445, 0x57D5, 0x5015, 0x5FF5, 0x4005, 0xFFFD, 0x0001, 0xFFFF };
unsigned int Maze2[16] = { 0xFFFF, 0x8811, 0xAEF5, 0x8011, 0xF7C7, 0x9435, 0xA5A5, 0xA8A9,
                              0x8B85, 0xA83D, 0xAFE1, 0xE06F, 0x8B01, 0xAAF5, 0x8811, 0xFFFF };
unsigned int Maze3[16] = { 0xFFFF, 0x8111, 0xADB5, 0x8001, 0xB7ED, 0x8181, 0xF42F, 0xB67D,
                              0x8181, 0x566F, 0x8182, 0xB8ED, 0x8BD1, 0xEA57, 0x8001, 0xFFFF };
unsigned int Maze4[16] = { 0xFFFF, 0xBCEC, 0x8001, 0xD555, 0x8001, 0xBFFD, 0x8001, 0xFDFF,
                              0x8001, 0xBFFD, 0x8001, 0xAAAB, 0x8001, 0xF7FF, 0x8001, 0xFFFF };
unsigned int Maze[16]; //note this assigns no storage so when it starts, this variable points to nothing

void mazechoice() {
// Maze definition
int MazeChoice = random(1, 5);
if (MazeChoice == 1)
  {
    Startx = 7;
    Starty = 8;
    Goalx = 15;
    Goaly = 15;
    Maze[16] = Maze1;
  }
else if (MazeChoice == 2)
  {
    Startx = 8;
    Starty = 7;
    Goalx = 2;
    Goaly = 7;
    Maze[16] = Maze2; 
  }
else if (MazeChoice == 3)
  {
    Startx = 14;
    Starty = 7;
    Goalx = 1;
    Goaly = 7;
    Maze[16] = Maze3; 
  }
else if (MazeChoice == 4)
  {
    Startx = 15;
    Starty = 2;
    Goalx = 1;
    Goaly = 15;
    Maze[16] = Maze4; 
  }
}
    
// Get one bit in the maze: 0,0 is top right
int Bit (int x, int y) {
  return Maze[y]>>x & 1;
}

// Returns the walls around x,y
int Look (int x, int y) {
  return Bit(x, y+1)<<3 | Bit(x+1, y)<<2 | Bit(x-1, y)<<1 | Bit(x, y-1);
}

// Tiny Tone **********************************************

const int Output = 4; 
const int Clock = 0;                               // 1 MHz
const uint8_t scale[] PROGMEM = {239,226,213,201,190,179,169,160,151,142,134,127};

void note (int n, int octave) {
  int prescaler = 8 + Clock - (octave + n/12);
  if (prescaler<1 || prescaler>15 || octave==0) prescaler = 0;
  DDRB = (DDRB & ~(1<<Output)) | (prescaler != 0)<<Output;
  OCR1C = pgm_read_byte(&scale[n % 12]) - 1;
  GTCCR = (Output == 4)<<COM1B0;
  TCCR1 = 1<<CTC1 | (Output == 1)<<COM1A0 | prescaler<<CS10;
}

void Mydelay (unsigned long millis) {
  for (volatile unsigned long i = 23*millis; i!=0; i--);
}

void Beep () {
  note(0, 4);
  Mydelay(100);
  note(0, 0);
}

// Multiplexing **********************************************

// Interrupt multiplexes display and buttons
ISR(TIMER0_COMPA_vect) {
  // Check button
  int button = ((Row<<1) + 1) % 5;
  if (PINB & 1<<button) {
    Buttons = Buttons & ~(1<<Row);
  } else {
    Buttons = Buttons | 1<<Row;
  }
  Row = (Row + 1) & 0x03;                  // Next row
  // Light LED
  button = ((Row<<1) + 1) % 5;             // Button
  int light = Row ^ 0x03;                  // LED
  if (Lights & 1<<Row) {
    DDRB = (DDRB & (1<<Output)) | 1<<Row | 1<<light;
    PORTB = 1<<light | 1<<button;
  } else {
    DDRB = (DDRB & (1<<Output)) | 1<<Row;
    PORTB = 1<<button;
  } 
}

// Setup **********************************************
  
void setup() {
  // Set up Timer/Counter0 to generate 625Hz interrupt
  TCCR0A = 2<<WGM00;                     // CTC mode
  TCCR0B = 2<<CS00;                      // /8 prescaler
  OCR0A = 249;                           // 500 Hz interrupt
  TIMSK = TIMSK | 1<<OCIE0A;             // Enable interrupt
}

// Position of player in the maze
int X = Startx, Y = Starty;

void loop () {
  Lights = Look(X, Y);                   // Display new position
  while (Buttons != 0);                  // Wait for key release
  // Have we reached goal?
  if ((X == Goalx) && (Y == Goaly)) {
    for (int n=0; n<=7; n++) {           // Success tune!
      note(n, 4);
      if (n!=4 && n!=11) n++;
      Mydelay(200);
    }
    note(0, 0);
    while (1);                           // Wait for reset
  }
  while (Buttons == 0);                  // Wait for keypress
  // Wait until keys are stable
  int keys, count = 0, lastkeys = 0;
  do {
    keys = Buttons;
    count++;
    if (lastkeys != keys) count = 0;
    lastkeys = keys;
  } while (count < 7);
  // Respond to keypress
  int dx = 0, dy = 0;                    // Movement
  if (keys & 0b1000) dy = 1; else if (keys & 0b100) dx = 1;
  else if (keys & 0b10) dx = -1; else if (keys & 0b1) dy = -1;
  // Can we go this way?
  if (Bit(X+dx, Y+dy)) Beep();           // Hit a wall
  else {
    X = X + dx; Y = Y + dy;              // Move
  }
}

Thank you, Delta_G -- I appreciate that. Bookmarked for later, when I have time to study.

Well thanks a lot star hawk, now I have to add making my own Secret Maze to my endless list of projects…

I haven't looked closely, but it seems that the buttons move the character in fixed directions, an interesting change would be to make the left and right buttons rotate the character in place whilst up would become forward and you wouldn't even need down but it could be backward.

Also it looks like it eats up much of the chips resources, I love this! Nothing is more satisfying that making full use of a chip. Most of my Arduino hacks use like 1/10 or less, space or speed or however you wanna measure it, of an UNO.

a7

You could make the sketch load the maze, start and goal points through serial monitor.

It will use less RAM (allow bigger mazes?) and you won't have to edit the sketch to run new mazes.

I, er, can't seem to upload the sketch. I'm trying to use my TL866A programmer to do it -- I have an Arduino Uno and breadboard and jumpers SOMEWHERE but trying to find it all would take... more time than I care to spend, anyhow.

I've followed the instructions at Minipro TL866CS Universal Programmer working with Arduino IDE - Installation & Troubleshooting - Arduino Forum -- he has the -CS version of the programmer; the only difference AFAICT appears to be that the -CS lacks the -A's port on one side for an ICSP cable. I have Linux, specifically Mint 18.2, and am using that set of instructions. I've installed all dependencies.

Alas, the programmer for some reason is not showing at all in the Arduino IDE, after I did updates. Before that it was showing, but would complain of a missing "program.param.quiet" somethingorother.

...should I start a new thread for this? I asked earlier, but apparently that was not seen.

EDIT: started new thread here --> Issues uploading with TL866A Programmer - Avrdude, stk500, Bootloader issues - Arduino Forum
Let me know if that was the wrong thing to do and I'll report it.

If you have an Uno, why don't you upload via USB directly to the board?

Can't find it without prolonged digging?