Files
2023-03-17 11:59:21 +00:00

176 lines
4.5 KiB
C++

#include <SPI.h>
#include <Gamebuino.h>
Gamebuino gb;
#include <EEPROM.h>
#include <avr/pgmspace.h>
//world size
//use power of 2 for better perfomance
#define SX 64
#define SY 32
byte buffer[SX*SY/8];
unsigned int pop = 0;
unsigned int prevPop = 0;
byte resetCounter = 0;
unsigned int gen = 0;
byte graphCursor = 0;
void setup() {
gb.begin();
gb.titleScreen(F("Conway's game of life"));
gb.pickRandomSeed();
reset();
}
void loop(){
if(gb.update()){
if(gb.buttons.pressed(BTN_C)){
gb.titleScreen(F("Conway's game of life"));
reset();
}
//compute next gen
gen++;
for (byte x = 0; x < SX; x++) {
for (byte y = 0; y < SY; y++) {
byte count = 0;
if(getCell(x-1, (y-1+SY)%SY)) count++;
if(getCell(x, (y-1+SY)%SY)) count++;
if(getCell((x+1)%SX, (y-1+SY)%SY)) count++;
if(getCell((x+1)%SX, y)) count++;
if(getCell((x+1)%SX, (y+1)%SY)) count++;
if(getCell(x, (y+1)%SY)) count++;
if(getCell((x-1+SX)%SX, (y+1)%SY)) count++;
if(getCell((x-1+SX)%SX, y)) count++;
byte cell = getCell(x,y);
if ( cell ) { //if there is a cell
if ( (count < 2) || (count > 3) ) { //and more than 3 neighbors or less than 2
gb.display.setColor(WHITE);
gb.display.drawPixel(x+1,y+1);
gb.display.setColor(BLACK,WHITE);
pop--;
}
}
else { //if there is no cell
if (count == 3) { //and 3 neighbors
gb.display.drawPixel(x+1,y+1);
pop++;
}
else { //randomly add new cells if there is enough light
if ((count==2) && (gb.backlight.ambientLight > 950) && !(random()%64)){
gb.display.drawPixel(x+1,y+1);
pop++;
}
else{
if ((count==2) && (gb.backlight.ambientLight > 900) && !(random()%128)){
gb.display.drawPixel(x+1,y+1);
pop++;
}
}
}
}
}
}
for (byte x = 0; x < SX; x++) {
for (byte y = 0; y < SY; y++) {
setCell(x, y, gb.display.getPixel(x+1, y+1));
}
}
if(gb.frameCount%6){
if(prevPop == pop){
resetCounter++;
if (resetCounter > 4){
gb.display.setColor(BLACK,WHITE);
gb.display.cursorX = 38;
gb.display.cursorY = 36;
gb.display.print("Gimme");
gb.display.cursorX = 38;
gb.display.cursorY = 36+gb.display.fontHeight;
gb.display.print("light!");
}
}
else{
resetCounter = 0;
}
prevPop = pop;
}
gb.display.textWrap = false;
gb.display.cursorX = LCDWIDTH-4*gb.display.fontWidth;
gb.display.cursorY = 2;
gb.display.println(F("Pop"));
gb.display.cursorX = LCDWIDTH-4*gb.display.fontWidth;
gb.display.print(pop);
gb.display.println(" ");
gb.display.cursorX = LCDWIDTH-4*gb.display.fontWidth;
gb.display.cursorY += 2;
gb.display.println(F("Gen"));
gb.display.cursorX = LCDWIDTH-4*gb.display.fontWidth;
gb.display.println(gen);
gb.display.cursorX = LCDWIDTH-4*gb.display.fontWidth;
gb.display.cursorY += 2;
gb.display.println(F("Sun"));
gb.display.cursorX = LCDWIDTH-4*gb.display.fontWidth;
gb.display.print(F("\17")); //sun logo
if(gb.backlight.ambientLight > 900)
gb.display.print(F("\17"));
else
gb.display.print(F(" "));
if(gb.backlight.ambientLight > 950)
gb.display.print(F("\17"));
else
gb.display.print(F(" "));
gb.display.setColor(WHITE);
gb.display.drawFastVLine(graphCursor,34,14);
gb.display.setColor(BLACK, WHITE);
gb.display.drawFastVLine(graphCursor+1,34,14);
gb.display.drawPixel(graphCursor, LCDHEIGHT-(pop/32)%16);
graphCursor++;
if(graphCursor > SX) graphCursor = 0;
}
}
void setCell(byte x, byte y, boolean state){
if (state)
buffer[x + (y / 8) * SX] |= _BV(y % 8);
else
buffer[x + (y / 8) * SX] &= ~_BV(y % 8);
}
byte getCell(byte x, byte y){
return (buffer[x + (y / 8) * SX] >> (y % 8)) & 0x1;
}
void reset(){
gb.battery.show = false;
gb.display.persistence = true;
pop = 0;
gen = 0;
graphCursor = 0;
gb.display.clear();
gb.display.drawRect(0,0,SX+2,SY+2);
for (byte x = 0; x < SX; x++) {
for (byte y = 0; y < SY; y++) {
if(!(random()%4)){
setCell(x, y, true);
gb.display.drawPixel(x+1,y+1);
pop++;
}
}
gb.display.update();
}
}