
//-----------------------------------------------------------------------------
// BomberRun by George Allan
//-----------------------------------------------------------------------------

global score = 0;
global height = 23;
global gframe = 0;
global detec = table();
global killStars = 0;
global playerx = 0;
global playery = 0;
global fireCnt = 0;
global fireMax = 3;
global clearExplo = 0;

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

global sync = function() {
  time = TICK();
  wait = (1./30.) - time;
  if(wait > 0) {
    sleep(wait);
  }
  TICK();
  global gframe = gframe + 1;
};

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

global star = function() {

     global detec;
     global killStars;

     frame = 0;
     while (1) {

           x = randint(1,79);
           y = randint(2,height);
           
           // On top of a building ?
           if (y < detec[x]-1) {

             // Print Star for a while
             t = randint(50,100);
             for (i=0;i<t;i=i+1) {
                 // Choose a twinkle color
                 if (randint(0,2) == 0) {
                   CATTRIB(CA.F_RED|CA.F_BLUE|CA.F_GREEN | CA.B_BLUE);
                 }
                 else {
                   CATTRIB(CA.F_RED|CA.F_GREEN | CA.B_BLUE);
                 }

                 // Pop !
                 if (i>t-2) {
                   XYTEXT(x,y,",");
                 }
                 else {
                   XYTEXT(x,y,".");
                 }

                 // Sync to the master frame
                 while (frame == gframe) {
                      yield();
                      if (killStars) {
                        exit();
                      }
                 }
                 frame = gframe;
             }
  
             // Clear Star
             CATTRIB(CA.F_BLUE | CA.B_BLUE);
             XYTEXT(x,y," ");
           }
           yield();
           if (killStars) {
             exit();
           }
     }
};

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

global particle = function(x, y) {

    global detec;
    global clearExplo;

    pcoltab = table(CA.F_RED|CA.F_INTENSITY,  CA.F_RED|CA.F_GREEN|CA.F_INTENSITY,  CA.F_RED|CA.F_GREEN|CA.F_BLUE|CA.F_INTENSITY);
    pfrtab = table(".", "+", "*");

    xmom = randfloat(-1.0,1.0);
//    ymom = randfloat(-0.2,-2.0);
    ymom = randfloat(-2.0,-0.2);

    xpos = x.Float();
    ypos = y.Float();

    frame = -1;

    time = randint(10,40);
    from = time;
    
    frint = randint(0,3);

    while (1) {

      if (y < detec[x]) {
         CATTRIB(CA.F_BLUE | CA.B_BLUE);
         XYTEXT(x,y," ");
      }
      xpos = xpos + xmom;
      ypos = ypos + ymom;
      ymom = ymom + 0.15f;
      x = xpos.Int();
      y = ypos.Int();

      // On Screen
      if ( y >= height || y < 0 || x < 0 || x > 79) {
         exit();
      }

      // Out of Time ?
      time = time - 1;
      if (time < 0 || clearExplo) {
            exit();
      }

      if (y < detec[x]) {
        fr = (time*3) / from;
        CATTRIB(pcoltab[fr] | CA.B_BLUE);
        XYTEXT(x,y,pfrtab[frint]);
      }

      // Sync to the master frame
      while (frame == gframe) {
           yield();
      }
      frame = gframe;
    }
};

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

global explode = function(x, y) {

    global particle;

    for (i=0;i<10;i=i+1) {
        thread(particle, x, y);
    }
};

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

global bullet = function() {

    global detec;
    global playerx;
    global playery;
    global score;
    global gframe;
    global fireCnt;
    global score;
    global explode;

    firex = playerx;
    firey = playery+1;
    fireHTG = 4;
    frame = gframe;
    
    score = score - 10;

    while (1) {

      // Detection
      if (firey > height-1 || fireHTG <= 0) {
        fireCnt = fireCnt - 1;
        exit();
      }
      else {
        // If okay - display
        CATTRIB(CA.F_RED|CA.F_GREEN|CA.F_BLUE|CA.F_INTENSITY | CA.B_BLUE);
        XYTEXT(firex,firey,"\31");
      }

      // Sync to the master frame
      while (frame == gframe) {
           yield();
      }
      frame = gframe;

      // Clear Bullet
      CATTRIB(CA.F_BLUE | CA.B_BLUE);
      XYTEXT(firex,firey," ");

      firey = firey + 1;
      first = 0;

      // Detection
      if (detec[firex] < firey) {
         score = score + 10;
         detec[firex] = firey;
         fireHTG = fireHTG - 1;
         // Boom !
         explode(firex,firey);
      }
    }
};

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

game = function() {

  global detec;
  global killStars;
  global star;
  global bullet;
  global playerx;
  global playery;
  global fireCnt;
  global fireMax;
  global score;
  global explode;

  killStars = 0;
  allgone = 0;

  for (i=0;i<30;i=i+1) {
    thread(star);
  }

  CATTRIB(CA.F_BLUE | CA.B_BLUE);
  CLS();

  coltab = table(CA.B_GREEN|CA.B_RED,  CA.B_BLUE|CA.B_RED,  CA.B_BLUE|CA.B_GREEN,  CA.B_GREEN);
  coltabfore = table(CA.F_GREEN|CA.F_RED,  CA.F_BLUE|CA.F_RED,  CA.F_BLUE|CA.F_GREEN,  CA.F_GREEN);
  btypes = table("\254", "\58", "\124");
  ttypes = table("\191", "\194", "\218");

  // Clear Collision
  for (i=0;i<=150;i=i+1) {
      detec[i] = height;
  }

  // Buildings
  for (x=0;x<80;x=x+1) {

    // Calc Height
    rand = 10;
    if (x < 30) {
       rand = x / 3;
    }
    if (x > 50) {
      rand = (80-x) / 3;
    }
    if (x < 10) {
      rand = 0;
    }
    if (x > 70) {
      rand = 0;
    }
    rand = randint(0,rand);
    if (rand > 1) {

      // Detection
      detec[x] = height-rand;

      // Random Building Color
      col = randint(0,4);

      // Random Top
      if (randint(0,10) < 2) {
        CATTRIB(coltabfore[col] | CA.B_BLUE);
        ttype = randint(0,3);
        XYTEXT(x,height-rand-1,ttypes[ttype]);
      }

      // The Main Building
      btype = randint(0,3);
      CATTRIB(coltab[col] | CA.F_BLACK);
      for (y=height-rand;y<height;y=y+1) {
        if (randint(0,5) < 2) {
           CATTRIB(coltab[col] | CA.F_RED | CA.F_GREEN | CA.F_INTENSITY);
           XYTEXT(x,y,btypes[btype]);
           CATTRIB(coltab[col] | CA.F_BLACK);
        }
        else {
          XYTEXT(x,y,btypes[btype]);
        }
      }
    }
  }

  CATTRIB(CA.F_GREEN | CA.B_BLACK);
  for (x=0;x<80;x=x+1) {
    XYTEXT(x,height,"\178");
  }

  playerx = 2;
  playery = 3;
  anim = 0;
  playermove = 0;
  fireOkay = 0;
  landingtimer = 0;

  while(!ISPRESSED('Q')) {

      // Flattened already ?
      allgone = 1;
      for (i=0;i<80;i=i+1) {
          if (detec[i] != height) {
              allgone = 0;
          }
      }

      // Add Loads of stars
      if (ISPRESSED('S')) {
          for (i=0;i<30;i=i+1) {
            thread(star);
          }
      }

      // Score
      CATTRIB(CA.F_BLUE | CA.F_GREEN | CA.F_INTENSITY | CA.B_BLUE);
      XY(35,1);
      print("Score ", score);

      // Show Memeory Usage
      if (ISPRESSED('M')) {
        XY(1,2);
        print("Memory ", sysGetMemoryUsage());
      }

      if (ISPRESSED(' ')) {
            if (fireCnt < fireMax && (fireOkay || fireMax == 50)) {
                 thread(bullet);
                 fireCnt = fireCnt + 1;
            }
            fireOkay = 0;
      }
      else {
           fireOkay = 1;
      }

      // Clear Player
      CATTRIB(CA.F_BLUE | CA.B_BLUE);
      XYTEXT(playerx-2,playery,"    ");

        // Auto Pilot landing
      if (allgone && playery < height-1) {
         landingtimer = landingtimer + 1;
         if (landingtimer > 10) {
           landingtimer = 0;
           playery = playery + 1;
         }
      }

      // Move and reposition if reach the side of the screen
      playerx = playerx+1;
      if (playerx > 79) {
        playerx = 2;
        playery = playery + 1;
      }
      
      // Not too low
      if (playery > height-1) {
         playery = height-1;
      }      

      // Print at new position
      CATTRIB(CA.F_RED|CA.F_GREEN|CA.F_BLUE|CA.F_INTENSITY | CA.B_BLUE);
      XYTEXT(playerx-2,playery,"\200");
      XYTEXT(playerx-1,playery,"\205");
      XYTEXT(playerx,playery,"\254");

      // Landed !!!
      if (playerx == 60 && playery == height-1) {
         for (i=0;i<60;i=i+1) {
             sync();
         }
         // Completion bonus - based on fireMax
         if (score != 50) {
            score = score + (6-fireMax) * 1000;
         }
         niceone();
         return;
      }

      // Hit a building (ignores arieals)
      if (detec[playerx+1] <= playery) {
         sync();

         y0 = playery;
         y1 = playery;
         y2 = playery;
         x = playerx;
         
         // Dramatic Pause !
         for (i=0;i<20;i=i+1) {
             XYTEXT(x-2,y0,"\200");
             XYTEXT(x-1,y1,"\205");
             XYTEXT(x-0,y2,"\254");
             sync();
         }

         done = 0;
         while (!done) {
               done = 1;

               // Clear
               CATTRIB(CA.F_BLUE | CA.B_BLUE);
               XYTEXT(x-2,y0," ");
               XYTEXT(x-1,y1," ");
               XYTEXT(x-0,y2," ");

               // Move
               if (y0 < detec[x-2]-1) {
                  y0 = y0 + 1;
                  done = 0;
               }
               if (y1 < detec[x-1]-1) {
                  y1 = y1 + 1;
                  done = 0;
               }
               if (y2 < detec[x-0]-1) {
                  y2 = y2 + 1;
                  done = 0;
               }

               // Print
               CATTRIB(CA.F_RED|CA.F_GREEN|CA.F_BLUE|CA.F_INTENSITY | CA.B_BLUE);
               XYTEXT(x-2,y0,"\200");
               XYTEXT(x-1,y1,"\205");
               XYTEXT(x-0,y2,"\254");
               sync();
          }
          
          for (i=0;i<60;i=i+1) {
              XYTEXT(x-2,y0,"\200");
              XYTEXT(x-1,y1,"\205");
              XYTEXT(x-0,y2,"\254");
              sync();
          }
          gameover();
          return;
      }
      else {
        if (anim == 1) {
          XYTEXT(playerx+1,playery,"\217");
          anim = 0;
        }
        else {
          XYTEXT(playerx+1,playery,"\191");
          anim = 1;
        }
      }
      
      // Next Frame
      sync();
  }
};

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

titlescreen = function() {

  global killStars = 1;
  global fireMax = 0;
  global score = 0;
  global detec;
  global clearExplo = 0;
  
  for (i=0;i<81;i=i+1) {
     detec[i] = height;
  }

  CATTRIB(0);
  CLS();

  CATTRIB(CA.F_RED);
  CURSOR(0,0);

  maxtab = 12;
  tabindex = 0;
  tctab = table(  CA.F_RED|CA.F_BLUE|CA.F_GREEN | CA.F_INTENSITY,
                  CA.F_GREEN | CA.F_INTENSITY | CA.F_INTENSITY,
                  CA.F_BLUE,
                  CA.F_GREEN | CA.F_INTENSITY,
                  CA.F_RED|CA.F_GREEN | CA.F_INTENSITY,
                  CA.F_RED|CA.F_BLUE|CA.F_GREEN | CA.F_INTENSITY,
                  CA.F_BLUE | CA.F_INTENSITY,
                  CA.F_BLUE | CA.F_INTENSITY,
                  CA.F_RED|CA.F_BLUE|CA.F_GREEN,
                  CA.F_BLUE,
                  CA.F_BLUE | CA.F_INTENSITY,
                  CA.F_RED|CA.F_GREEN | CA.F_INTENSITY  );

  maxtab2 = 8;
  tabindex2 = 0;
  tctab2 = table( CA.F_RED|CA.F_BLUE|CA.F_GREEN | CA.F_INTENSITY,
                  CA.F_RED|CA.F_BLUE|CA.F_GREEN | CA.F_INTENSITY,
                  CA.F_RED|CA.F_BLUE|CA.F_GREEN | CA.F_INTENSITY,
                  CA.F_RED|CA.F_GREEN | CA.F_INTENSITY,
                  CA.F_RED | CA.F_INTENSITY,
                  CA.F_RED,
                  CA.F_RED | CA.F_INTENSITY,
                  CA.F_RED|CA.F_GREEN | CA.F_INTENSITY  );


  // Flush Keyboard !?
  ISPRESSED(' ');
  ISPRESSED(' ');
  ISPRESSED(' ');

  while(!fireMax) {

    // Start in which mode
    if (ISPRESSED('1')) { fireMax = 1; }
    if (ISPRESSED('2')) { fireMax = 2; }
    if (ISPRESSED('3')) { fireMax = 3; }
    if (ISPRESSED('4')) { fireMax = 4; }
    if (ISPRESSED('5')) { fireMax = 5; }
    if (ISPRESSED(' ')) { fireMax = 3; }
    if (ISPRESSED('C')) { fireMax = 50; }
    if (ISPRESSED(27))  { threadKillAll(true); } // Kill all threads when ESC is pressed

    // Title Color
    tabindex = tabindex + 1;
    if (tabindex >= maxtab) {
      tabindex = 0;
    }
    CATTRIB(tctab[tabindex]);

    CLS();
    XYTEXT(4,2,`   ________                 ______             ________      `);
    XYTEXT(4,3,`   ___  __ )____________ ______  /________________  __ \___  ________ `);
    XYTEXT(4,4,`   __  __  |  __ \_  __ ``__ \_  __ \  _ \_  ___/_  /_/ /  / / /_  __ \ `);
    XYTEXT(4,5,`   _  /_/ // /_/ /  / / / / /  /_/ /  __/  /   _  _, _// /_/ /_  / / / `);
    XYTEXT(4,6,`   /_____/ \____//_/ /_/ /_//_.___/\___//_/    /_/ |_| \__,_/ /_/ /_/ `);

    // Text Color
    tabindex2 = tabindex2 + 1;
    if (tabindex2 >= maxtab2) {
      tabindex2 = 0;
    }
    CATTRIB(tctab2[tabindex2]);

    XYTEXT(12,8, "            Written in GameMonkey by Happy ");

    XYTEXT(12,11, "     Flatten the city by dropping bombs (spacebar)");
    XYTEXT(12,12, "        Destory all buildings to land saftley");
    XYTEXT(12,13, "   Score 10 points for each builing piece destoryed");
    XYTEXT(12,14, "        Loose 10 points for each bomb dropped");
    XYTEXT(12,15, "     Landing bonus is based on difficulty setting");

    XYTEXT(12,18, "        Press 'Space' to play at standard level");
    XYTEXT(12,19, "    Press 1-5 to choose difficulty (number of bombs)");
    XYTEXT(12,20, "Press 'C' to play the cheat version (hold the spacebar!)");
    XYTEXT(12,21, "           Press 'Q' to to quit during play");    
    XYTEXT(12,22, "             Press ESC to exit game now");    

    x = randint(2,78);
    y = randint(2,height-2);
    explode(x,y);

    sync();
  }
  
  clearExplo = 1;
     sync();
     sync();
     clearExplo = 0;
};

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

global niceone = function() {

  global killStars = 0;
  global detec;
  global score;
  global clearExplo = 0;
  global fireMax;

  for (i=0;i<500;i=i+1) {
    thread(star);
  }

  for (i=0;i<200;i=i+1) {

    CATTRIB(CA.F_RED|CA.F_GREEN|CA.F_BLUE|CA.F_INTENSITY|CA.B_BLUE);
    CLS();

    XYTEXT(1,7,`   .__   __. __   ______ _______    ______  .__   __. _______   __  __  __   `);
    XYTEXT(1,8,`   |  \ |  ||  | /      |   ____|  /  __  \ |  \ |  ||   ____| |  ||  ||  | `);
    XYTEXT(1,9,`   |   \|  ||  ||  ,----'  |__    |  |  |  ||   \|  ||  |__    |  ||  ||  | `);
    XYTEXT(1,10,`   |  . ``  ||  ||  |    |   __|   |  |  |  ||  . ``  ||   __|   |  ||  ||  | `);
    XYTEXT(1,11,`   |  |\   ||  ||  ``----.  |____  |  ``--'  ||  |\   ||  |____  |__||__||__| `);
    XYTEXT(1,12,`   |__| \__||__| \______|_______|  \______/ |__| \__||_______| (__)(__)(__) `);
    XY(1,15);
    if (score < 0) {
         print("                    You score is to crap too mention !");
    }
    else if (score < 1500) {
        print("                       Your score is a average", score);
    }
    else if (score < 3000) {
        print("                     Your score is a respectable", score);
    }
    else {
        print("                      Your score is an awesome", score);
    }
    if (fireMax == 50) {
         XY(1,17);
         print("                ---  Now try again without cheating ;)  ---");
    }

    x = randint(2,78);
    y = randint(2,height-2);
    explode(x,y);

    sync();
  }


};

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

global gameover = function() {

  global killStars = 1;
  global detec;
  global score;
  global clearExplo = 1;
 
  CATTRIB(CA.F_RED|CA.F_INTENSITY);
  for (i=height+15;i>-15;i=i-1) {
       CLS();
       y = i;
       if (y >= 0 && y <= height) {       XYTEXT(8,y,`              _______     ___     .___  ___. _______ `); }
       y = y + 1;
       if (y >= 0 && y <= height) {       XYTEXT(8,y,`             /  _____|   /   \    |   \/   ||   ____| `);   }
       y = y + 1;
       if (y >= 0 && y <= height) {       XYTEXT(8,y,`            |  |  __    /  ^  \   |  \  /  ||  |__ `);    }
       y = y + 1;
       if (y >= 0 && y <= height) {       XYTEXT(8,y,`            |  | |_ |  /  /_\  \  |  |\/|  ||   __| `);    }
       y = y + 1;
       if (y >= 0 && y <= height) {       XYTEXT(8,y,`            |  |__| | /  _____  \ |  |  |  ||  |____ `);   }
       y = y + 1;
       if (y >= 0 && y <= height) {       XYTEXT(8,y,`             \______|/__/    _\__\|__|__|__||_______| `);  }
       y = y + 1;
       if (y >= 0 && y <= height) {       XYTEXT(8,y,`            /  __  \ \   \  /   /|   ____|   _  \ `);   }
       y = y + 1;
       if (y >= 0 && y <= height) {       XYTEXT(8,y,`           |  |  |  | \   \/   / |  |__  |  |_)  | `);   }
       y = y + 1;
       if (y >= 0 && y <= height) {       XYTEXT(8,y,`           |  |  |  |  \      /  |   __| |      / `);  }
       y = y + 1;
       if (y >= 0 && y <= height) {       XYTEXT(8,y,`           |  ``--'  |   \    /   |  |____|  |\  \----. `);  }
       y = y + 1;
       if (y >= 0 && y <= height) {       XYTEXT(8,y,`            \______/     \__/    |_______| _| ``._____| `);  }
       y = y + 1;
       sync();
   }
};

//-----------------------------------------------------------------------------
// and finaly - the main loop !
//-----------------------------------------------------------------------------

  while (1) {
    titlescreen();
    game();
  }

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

