#include <stdio.h>
#include <iostream>

#include "Sand-3.h"
#include <wx/wx.h>
#include <wx/dcscreen.h>
#include <wx/dcbuffer.h>
#include <wx/datetime.h>

#ifndef wxCLOSE_BOX
#define wxCLOSE_BOX 0
#endif

#define TIMERINTERVAL 50
#define WIDTH   800
#define HEIGHT  600

#define NUMBEROFELEMENTS 13

#define EMPTY 0
#define WALL 1
#define FIRE 2
#define WATER 3
#define PLANT 4
#define SAND 5
#define SPOUT 6
#define CERA 7
#define Q 8
#define OIL 9
#define SALT 10
#define EMBER 11
#define FCERA 12


double deathrate[NUMBEROFELEMENTS]= {0, 0, 0.05, 0, 0, 0, 0, 0, 0, 0, 0, 0.02, 0};
double gravity[NUMBEROFELEMENTS] =  {0, 0,-0.6, 0.6, 0, 0.6, 0, 0, 0, 0.6, 0.6, 0, 0.6};
double friction[NUMBEROFELEMENTS] = {0, 1,   0,   0, 1, 0,   1, 1, 0, 0,   0,   1, 0};
double density[NUMBEROFELEMENTS] =  {0, 1,   1,   1, 1, 1,   1, 1, 1, 1,   1,   1, 1};
const wxString names[NUMBEROFELEMENTS] =    {"Eraser", "Wall",   "Fire",   "Water", "Plant", 
					     "Sand",  "Spout", "Cera", "???", "Oil", "Salt", "Ember", "Molten Cera"};
wxColor colors[NUMBEROFELEMENTS] = {wxColor(0,0,0),     wxColor(100,100,100), wxColor(200,50,50),
				    wxColor(10,10,200), wxColor(10,200,10), wxColor(238,204,128),
				    wxColor(10,100,10), wxColor(255,220,200), wxColor(100,0,100),
				    wxColor(100,70,40), wxColor(255,255,255), wxColor(200,50,50), wxColor(255,220,200)};

double trans_death[NUMBEROFELEMENTS]= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
double trans_prob[NUMBEROFELEMENTS][NUMBEROFELEMENTS];
char trans_to[NUMBEROFELEMENTS][NUMBEROFELEMENTS];
char trans_from[NUMBEROFELEMENTS][NUMBEROFELEMENTS];


BEGIN_EVENT_TABLE(Canvas, wxWindow)
  //EVT_PAINT(Canvas::OnPaint)
  EVT_ERASE_BACKGROUND(Canvas::OnEraseBG)
  EVT_LEFT_DOWN(Canvas::OnMouseLeftDown)
  EVT_LEFT_UP(Canvas::OnMouseLeftUp)
  EVT_MOTION(Canvas::OnMouseMove)
  EVT_TIMER(1000, Canvas::OnTimer)
END_EVENT_TABLE()


BEGIN_EVENT_TABLE(MainFrame, wxFrame)
  EVT_SET_FOCUS(MainFrame::OnMove)
  EVT_SIZE(MainFrame::OnSize)
  EVT_LISTBOX(1000, MainFrame::OnChoice)
  EVT_LISTBOX(1001, MainFrame::OnChoice)
END_EVENT_TABLE()


IMPLEMENT_APP(Sand)

MainFrame* g_mainFrame;
Canvas* g_canvas;
char data[WIDTH*HEIGHT];
bool draw[WIDTH*HEIGHT];
wxTimer* g_timer;
bool mouseIsDown = false;
int mousex, mousey;
char sand_type;
int pen_width;
int draw_counter = 0;
wxStatusBar* statusbar;
double previous_now;

Canvas::Canvas(wxWindow* parent, wxWindowID id = -1, wxPoint pos = wxDefaultPosition, wxSize size = wxDefaultSize) : wxWindow( parent, id, pos, size, wxSUNKEN_BORDER | wxCLIP_CHILDREN ){
  g_canvas = this;
  this->SetSizeHints(WIDTH,HEIGHT);
  //this->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
  this->SetBackgroundColour(wxColor("BLACK"));
  //this->SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
  g_timer = new wxTimer(this, 1000);
  sand_type = 1;
  pen_width = 2;

  for(int y=0;y<HEIGHT;++y){
    for(int x=0;x<WIDTH;++x){
      data[(WIDTH*y)+x] = 0;
      draw[(WIDTH*y)+x] = true;
    }
  }

  //this->ClearBackground();

  for(int i=0;i<NUMBEROFELEMENTS;++i){
    for(int j=0;j<NUMBEROFELEMENTS;++j){
      trans_prob[i][j] = 0;
      trans_to[i][j] = 0;
      trans_from[i][j] = 0;
    }
  }

  //embers
  trans_prob[EMBER][EMPTY] = 0.2;
  trans_to[EMBER][EMPTY] = EMBER;
  trans_from[EMBER][EMPTY] = FIRE;

  trans_prob[EMBER][WATER] = 0.9;
  trans_to[EMBER][WATER] = EMPTY;
  trans_from[EMBER][WATER] = EMPTY;

  trans_prob[EMBER][OIL] = 0.75;
  trans_to[EMBER][OIL] = EMBER;
  trans_from[EMBER][OIL] = FIRE;

  trans_prob[EMBER][PLANT] = 1;
  trans_to[EMBER][PLANT] = EMBER;
  trans_from[EMBER][PLANT] = FIRE;

  trans_prob[EMBER][CERA] = 0.1;
  trans_to[EMBER][CERA] = FCERA;
  trans_from[EMBER][CERA] = EMBER;

  //fire
  trans_prob[FIRE][FIRE] = 0.0005;
  trans_to[FIRE][FIRE] = EMPTY;
  trans_from[FIRE][FIRE] = EMPTY;

  trans_prob[FIRE][WATER] = 0.9;
  trans_to[FIRE][WATER] = EMPTY;
  trans_from[FIRE][WATER] = EMPTY;

  trans_prob[FIRE][OIL] = 0.75;
  trans_to[FIRE][OIL] = FIRE;
  trans_from[FIRE][OIL] = FIRE;

  trans_prob[FIRE][PLANT] = 1;
  trans_to[FIRE][PLANT] = FIRE;
  trans_from[FIRE][PLANT] = FIRE;

  trans_prob[FIRE][CERA] = 0.1;
  trans_to[FIRE][CERA] = FCERA;
  trans_from[FIRE][CERA] = EMBER;

  //fcera turns back into cera.
  trans_prob[FCERA][CERA] = 0.01;
  trans_to[FCERA][CERA] = CERA;
  trans_from[FCERA][CERA] = CERA;

  trans_prob[FCERA][WALL] = 0.001;
  trans_to[FCERA][WALL] = CERA;
  trans_from[FCERA][WALL] = WALL;

  trans_prob[FCERA][WATER] = 0.001;
  trans_to[FCERA][WATER] = CERA;
  trans_from[FCERA][WATER] = WATER;

  trans_prob[FCERA][PLANT] = 0.001;
  trans_to[FCERA][PLANT] = CERA;
  trans_from[FCERA][PLANT] = PLANT;

  trans_prob[FCERA][SAND] = 0.001;
  trans_to[FCERA][SAND] = CERA;
  trans_from[FCERA][SAND] = SAND;

  trans_prob[FCERA][OIL] = 0.001;
  trans_to[FCERA][OIL] = CERA;
  trans_from[FCERA][OIL] = OIL;

  trans_prob[FCERA][SPOUT] = 0.001;
  trans_to[FCERA][SPOUT] = CERA;
  trans_from[FCERA][SPOUT] = SPOUT;

  //plant
  trans_prob[PLANT][WATER] = 0.2;
  trans_to[PLANT][WATER] = PLANT;
  trans_from[PLANT][WATER] = PLANT;

  //spout
  trans_prob[SPOUT][EMPTY] = 0.75;
  trans_to[SPOUT][EMPTY] = SPOUT;
  trans_from[SPOUT][EMPTY] = WATER;

  trans_prob[SPOUT][SAND] = 0.5;
  trans_to[SPOUT][SAND] = EMPTY;
  trans_from[SPOUT][SAND] = EMPTY;

  //???
  trans_prob[Q][SPOUT] = 0.2;
  trans_to[Q][SPOUT] = EMPTY;
  trans_from[Q][SPOUT] = Q;
  
  trans_prob[Q][SALT] = 0.2;
  trans_to[Q][SALT] = EMPTY;
  trans_from[Q][SALT] = Q;
  
  trans_prob[Q][EMPTY] = 0.2;
  trans_to[Q][EMPTY] = Q;
  trans_from[Q][EMPTY] = Q;
  
  trans_prob[Q][WATER] = 0.2;
  trans_to[Q][WATER] = EMPTY;
  trans_from[Q][WATER] = Q;
  
  trans_prob[Q][OIL] = 0.2;
  trans_to[Q][OIL] = EMPTY;
  trans_from[Q][OIL] = Q;
  
  trans_prob[Q][FCERA] = 0.2;
  trans_to[Q][FCERA] = EMPTY;
  trans_from[Q][FCERA] = Q;
  
  trans_prob[Q][CERA] = 0.2;
  trans_to[Q][CERA] = EMPTY;
  trans_from[Q][CERA] = Q;
  
  trans_prob[Q][WALL] = 0.2;
  trans_to[Q][WALL] = EMPTY;
  trans_from[Q][WALL] = Q;
  
  trans_prob[Q][SAND] = 0.2;
  trans_to[Q][SAND] = EMPTY;
  trans_from[Q][SAND] = Q;
  

  /*
  trans_prob[][] = 0;
  trans_to[][] = ;
  trans_from[][] = ;

  */

  g_timer->Start(TIMERINTERVAL);    // 1/10 second interval
}


inline bool checkForTransformation(int center, int other){
  char t1 = data[center];
  char t2 = data[other];
  if (trans_prob[t1][t2] == 0) return false;
  if (rand() < trans_prob[t1][t2]*RAND_MAX){
    data[center] = trans_to[t1][t2];
    data[other] = trans_from[t1][t2];
    draw[center] = true;
    draw[other] = true;
    return true;
  }
  return false;
}



void Canvas::OnTimer(wxTimerEvent& event){
  int now = wxDateTime::UNow().GetMinute()*60*1000 + wxDateTime::UNow().GetSecond()*1000 + wxDateTime::UNow().GetMillisecond();
  int span = now - previous_now;
  if (span == 0)
    span = 1;
  wxString str = "";
  str.Printf("%4.1f fps", 0.1*round(10*1000.0/double(span)));
  statusbar->SetStatusText(str);
  previous_now = now;

  g_timer->Stop();

  int offset = WIDTH*50;
  for(int i=WIDTH/8;i<(WIDTH/8)+10;++i)
    if (rand() < RAND_MAX/4){
      data[offset+i] = SAND;
      draw[offset+i] = true;
    }
  for(int i=2*WIDTH/8;i<(2*WIDTH/8)+10;++i)
    if (rand() < RAND_MAX/4){
      data[offset+i] = WATER;
      draw[offset+i] = true;
    }
  for(int i=3*WIDTH/8;i<(3*WIDTH/8)+10;++i)
    if (rand() < RAND_MAX/4){
      data[offset+i] = SALT;
      draw[offset+i] = true;
    }
  for(int i=4*WIDTH/8;i<(4*WIDTH/8)+10;++i)
    if (rand() < RAND_MAX/4){
      data[offset+i] = OIL;
      draw[offset+i] = true;
    }

  for(int y=HEIGHT-3;y>1;--y){
    //Randomly calculate left or right.
    int startx = 2;
    int endx = WIDTH-2;
    int move = 1;
    if (rand() < 0.5*RAND_MAX){
      startx = WIDTH-2;
      endx = 1;
      move = -1;
    }

    for(int x = startx; x != endx-move; x += move){
      int center = (WIDTH*y)+x;
      if (data[center] == 0)
	continue;

      if (y == HEIGHT-1){
	data[center] = 0;
	draw[center] = true;
	continue;
      }

      int left = (WIDTH*y)+x-1;
      int right = (WIDTH*y)+x+1;
      int up = (WIDTH*(y-1))+x;
      int down = (WIDTH*(y+1))+x;
      int downleft = (WIDTH*(y+1))+x-1;
      int downright = (WIDTH*(y+1))+x+1;

      if (deathrate[data[center]] > 0){
	if (rand() < deathrate[data[center]] * RAND_MAX){
	  data[center] = trans_death[data[center]];
	  draw[center] = true;
	  continue;
	}
      }

      if (rand() > 0.5*RAND_MAX){
	//Check for specific transformations.
	//if(checkForTransformation(x,y,x-1,y-1)) continue;
	if(checkForTransformation(center, left)) continue;
	//if(checkForTransformation(x,y,x-1,y+1)) continue;
	if(checkForTransformation(center, down)) continue;
	//if(checkForTransformation(x,y,x+1,y+1)) continue;
	if(checkForTransformation(center, right)) continue;
	//if(checkForTransformation(x,y,x+1,y-1)) continue;
	if(checkForTransformation(center, up)) continue;
      }
      else{
	//Check for specific transformations.
	if(checkForTransformation(center, up)) continue;
	if(checkForTransformation(center, right)) continue;
	if(checkForTransformation(center, down)) continue;
	if(checkForTransformation(center, left)) continue;
      }


      if (gravity[data[center]] == 0 && friction[data[center]] == 1)
	continue;

      //Check for falling through the air.
      if (gravity[data[center]] > 0){
	if (data[down] == 0){
	  if (rand() < gravity[data[center]]*RAND_MAX){
	    data[down] = data[center];
	    data[center] = 0;
	    draw[center] = true;
	    draw[down] = true;
	    continue;
	  }
	}
      }
      else{
	double g = -gravity[data[center]];
	if (data[up] == 0){
	  if (rand() < g*RAND_MAX){
	    data[up] = data[center];
	    data[center] = 0;
	    draw[center] = true;
	    draw[up] = true;
	    continue;
	  }
	}
	if (rand() < 0.5*RAND_MAX){
	  int upleft = (WIDTH*(y-1))+x-1;
	  if (data[upleft] == 0){
	    if (rand() < g*RAND_MAX){
	      data[upleft] = data[center];
	      data[center] = 0;
	      draw[center] = true;
	      draw[upleft] = true;
	      continue;
	    }
	  }
	}
	else{
	  int upright = (WIDTH*(y-1))+x+1;
	  if (data[upright] == 0){
	    if (rand() < g*RAND_MAX){
	      data[upright] = data[center];
	      data[center] = 0;
	      draw[center] = true;
	      draw[upright] = true;
	      continue;
	    }
	  }
	}
      }


      //Randomly move side-to-side.
      if ((data[down] != 0) && (data[left] == 0 || data[right] == 0 )){
	if ((data[downright] != 0) || (data[downleft] != 0)){
	  if (rand() < 0.5*RAND_MAX)
	    continue;
	}
	if (data[left] == 0){
	  if (rand() > 0.5){
	    data[left] = data[center];
	    data[center] = 0;
	    draw[center] = true;
	    draw[left] = true;
	    continue;
	  }
	}
	if (data[right] == 0){
	  if (rand() > 0.5){
	    data[right] = data[center];
	    data[center] = 0;
	    draw[center] = true;
	    draw[right] = true;
	    continue;
	  }
	}

      }

      
      //Check for being pushed to the side.
      //Randomize which direction to check first.
      if (data[left] == 0 || data[right] == 0 ){
	if (rand() < 0.5*RAND_MAX){
	  if (data[left] == 0 && data[right] > 0){
	    if (rand() < friction[data[center]]*RAND_MAX){
	      data[left] = data[center];
	      data[center] = 0;
	      draw[center] = true;
	      draw[left] = true;
	      continue;
	    }
	    continue;
	  }
	  else if (data[right] == 0 && data[left] > 0){
	    if (rand() < friction[data[center]]*RAND_MAX){
	      data[right] = data[center];
	      data[center] = 0;
	      draw[center] = true;
	      draw[right] = true;
	      continue;
	    }
	    continue;
	  }
	}
	else{
	  if (data[right] == 0 && data[left] > 0){
	    if (rand() < friction[data[center]]*RAND_MAX){
	      data[right] = data[center];
	      data[center] = 0;
	      draw[center] = true;
	      draw[right] = true;
	      continue;
	    }
	    continue;
	  }
	  else if (data[left] == 0 && data[right] > 0){
	    if (rand() < friction[data[center]]*RAND_MAX){
	      data[left] = data[center];
	      data[center] = 0;
	      draw[center] = true;
	      draw[left] = true;
	      continue;
	    }
	    continue;
	  }
	}
      }
      

      //Check for falling downhill
      if (data[downleft] == 0 || data[downright] == 0 ){
	if (rand() < 0.5*RAND_MAX){
	  if (data[downright] == 0){
	    if (rand() < friction[data[center]]*RAND_MAX){
	      data[downright] = data[center];
	      data[center] = 0;
	      draw[center] = true;
	      draw[downright] = true;
	      continue;
	    }
	    continue;
	  }
	}
	else{
	  if (data[downleft] == 0){
	    if (rand() < friction[data[center]]*RAND_MAX){
	      data[downleft] = data[center];
	      data[center] = 0;
	      draw[center] = true;
	      draw[downleft] = true;
	      continue;
	    }
	    continue;
	  }
	}
      }

      
      //Check for falling through another material.
      if (density[data[center]] != 1.0){
	if (density[data[center]] > density[data[down]]){
	  if ( rand() < ((density[data[center]] - density[data[down]]))*RAND_MAX ){
	    char t = data[center];
	    data[center] = data[down];
	    data[down] = t;
	    draw[center] = true;
	    draw[down] = true;
	    continue;
	  }
	}
	if (rand() < 0.5*RAND_MAX){
	  if (density[data[center]] > density[data[downleft]]){
	    if ( rand() < ((density[data[center]] - density[data[downleft]]))*RAND_MAX ){
	      char t = data[center];
	      data[center] = data[downleft];
	      data[downleft] = t;
	      draw[center] = true;
	      draw[downleft] = true;
	      continue;
	    }
	  }
	}
	else{
	  if (density[data[center]] > density[data[downright]]){
	    if ( rand() < ((density[data[center]] - density[data[downright]]))*RAND_MAX ){
	      char t = data[center];
	      data[center] = data[downright];
	      data[downright] = t;
	      draw[center] = true;
	      draw[downright] = true;
	      continue;
	    }
	  }
	}
	//Pushing left and right.
	//Randomly choose which side goes first.
	if (rand() < 0.5*RAND_MAX){
	  if (density[data[center]] > density[data[left]]){
	    if ( rand() < ((density[data[center]] - density[data[left]]))*RAND_MAX ){
	      char t = data[center];
	      data[center] = data[left];
	      data[left] = t;
	      draw[center] = true;
	      draw[left] = true;
	      continue;
	    }
	  }
	  if (density[data[center]] > density[data[right]]){
	    if ( rand() < ((density[data[center]] - density[data[right]]))*RAND_MAX ){
	      char t = data[center];
	      data[center] = data[right];
	      data[right] = t;
	      draw[center] = true;
	      draw[right] = true;
	      continue;
	    }
	  }
	}
	else{
	  if (density[data[center]] > density[data[right]]){
	    if ( rand() < ((density[data[center]] - density[data[right]]))*RAND_MAX ){
	      char t = data[center];
	      data[center] = data[right];
	      data[right] = t;
	      draw[center] = true;
	      draw[right] = true;
	      continue;
	    }
	  }
	  if (density[data[center]] > density[data[left]]){
	    if ( rand() < ((density[data[center]] - density[data[left]]))*RAND_MAX ){
	      char t = data[center];
	      data[center] = data[left];
	      data[left] = t;
	      draw[center] = true;
	      draw[left] = true;
	      continue;
	    }
	  }
	}
      }

      
      

    }
  }
  if (mouseIsDown){
    for(int i=mousex-pen_width/2;i<mousex+pen_width/2;++i){
      for(int j=mousey-pen_width/2;j<mousey+pen_width/2;++j){
	if (i > 0 && i < WIDTH && j > 0 && j < HEIGHT){
	  data[(WIDTH*j)+i] = sand_type;
	  draw[(WIDTH*j)+i] = true;
	}
      }
    }
  }

  this->Refresh();
}


void Canvas::Refresh(){
  g_timer->Stop();

  wxClientDC dc(g_canvas);

  int cx,cy,cw,ch;
  dc.GetClippingBox(&cx,&cy,&cw,&ch);
  for(int y = cy;y<cy+ch; ++y)
    for(int x = cx;x<cx+cw; ++x)
      draw[(WIDTH*y)+x] = true;

  for(int y=0;y<HEIGHT;++y){
    for(int x=0;x<WIDTH;++x){
      int center = (WIDTH*y)+x;
      if (draw[center] == false)
	continue;

      dc.SetPen(wxPen(colors[data[center]], 1, wxSOLID));
      dc.DrawPoint(x, y);
      dc.SetPen(wxNullPen);
      draw[center] = false;
      continue;
    }
  }
  g_timer->Start(TIMERINTERVAL);
}

void Canvas::OnEraseBG(wxEraseEvent& e){
  //Do absolutely nothing, thereby halting this event.
  
  for(int y=0;y<HEIGHT;++y){
    for(int x=0;x<WIDTH;++x){
      draw[(WIDTH*y)+x] = true;
    }
  }
   
  this->Refresh();
}

void Canvas::OnMouseLeftDown(wxMouseEvent& event){
  mouseIsDown = true;
  mousex = event.GetX();
  mousey = event.GetY();

  for(int i=mousex-pen_width/2;i<mousex+pen_width/2;++i){
    for(int j=mousey-pen_width/2;j<mousey+pen_width/2;++j){
      if (i > 0 && i < WIDTH && j > 0 && j < HEIGHT){
	data[(WIDTH*j)+i] = sand_type;
	draw[(WIDTH*j)+i] = true;
      }
    }
  }

  //g_canvas->Refresh();
}

void Canvas::OnMouseLeftUp(wxMouseEvent& event){
  mouseIsDown = false;
}

void Canvas::OnMouseMove(wxMouseEvent& event){
  if (event.LeftIsDown()){
    mousex = event.GetX();
    mousey = event.GetY();
    mouseIsDown = true;

    for(int i=mousex-pen_width/2;i<mousex+pen_width/2;++i){
      for(int j=mousey-pen_width/2;j<mousey+pen_width/2;++j){
	if (i > 0 && i < WIDTH && j > 0 && j < HEIGHT){
	  data[(WIDTH*j)+i] = sand_type;
	  draw[(WIDTH*j)+i] = true;
	}
      }
    }

    //g_canvas->Refresh();
  }
  else
    mouseIsDown = false;
}

void Canvas::OnPaint(wxPaintEvent& event){
  wxPaintDC dc;
  for(int y=0;y<HEIGHT;++y){
    for(int x=0;x<WIDTH;++x){
      draw[(WIDTH*y)+x] = true;
    }
  }
  this->Refresh();
}




MainFrame::MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, 
		     long style) : wxFrame(NULL, -1, title, pos, size, style){
  statusbar = this->CreateStatusBar();
  statusbar->Show(true);
  g_mainFrame = this;

  //this->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
  g_canvas = new Canvas(this, -1, wxDefaultPosition, wxDefaultSize);
  wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
  sizer->Add(g_canvas, 1, wxEXPAND);
  sizer->Add(new wxListBox(this, 1000, wxDefaultPosition, wxDefaultSize, NUMBEROFELEMENTS, names, wxLB_SINGLE), 0, wxEXPAND);
  const wxString labels2[10] = {"2", "4", "6", "8", "10", "12", "14", "16", "18", "20"};
  sizer->Add(new wxListBox(this, 1001, wxDefaultPosition, wxDefaultSize, 10, labels2, wxLB_SINGLE), 0, wxEXPAND);

  this->SetSizer(sizer);
  this->Layout();
  sizer->Fit(this);
  //this->SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
}

void MainFrame::OnChoice(wxCommandEvent& event){
  if (event.GetId() == 1000){
    sand_type = (char)event.GetSelection();
  }
  else{
    pen_width = (event.GetSelection()+1)*2;
  }

}


void MainFrame::OnSize(wxSizeEvent& event){
  for(int y=0;y<HEIGHT;++y){
    for(int x=0;x<WIDTH;++x){
      draw[(WIDTH*y)+x] = true;
    }
  }
  g_mainFrame->Layout();
}

void MainFrame::OnMove(wxFocusEvent& event){
  for(int y=0;y<HEIGHT;++y){
    for(int x=0;x<WIDTH;++x){
      draw[(WIDTH*y)+x] = true;
    }
  }
  if (g_canvas)
    g_canvas->Refresh();
}


/* this is executed upon startup, like 'main()' in non-wxWidgets programs */
bool Sand::OnInit()
{
  wxString str = "Owen's Reality v";
  str << VERSION;
  wxFrame *frame = new MainFrame(str, wxDefaultPosition, wxSize(WIDTH,HEIGHT), wxCLOSE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN);
  frame->Show(TRUE);
  SetTopWindow(frame);
  return true;
}

