import stanford.karel.*;
public class GameOfLife extends SuperKarel {
public void run() {
initialSweep();
turnRight();
while(true) {
exploreWorld();
fixGeneration();
}
}
public void initialSweep() {
while(notFacingNorth()) {
if(frontIsClear()) {
move();
} else {
moveBack();
moveUpRow();
}
if(beepersPresent()) {
paintCorner(WHITE);
} else {
paintCorner(BLACK);
}
}
}
public void exploreWorld() {
while(notFacingNorth()) {
if(frontIsClear()) {
move();
} else {
moveBack();
moveUpRow();
}
checkSquare();
}
}
public void fixGeneration() {
turnRight();
while(notFacingNorth()) {
if(frontIsClear()) {
move();
} else {
moveBack();
moveUpRow();
}
if(beepersPresent()) {
pickBeeper();
if(beepersPresent()) {
pickBeeper();
if(beepersPresent()) {
// Dead cell
clearSquare();
paintCorner(BLACK);
} else {
// New cell
putBeeper();
paintCorner(WHITE);
}
} else {
// surviving cell
putBeeper();
paintCorner(WHITE);
}
}
}
turnRight();
}
/*
* Rules:
*
* 1. Any live cell with fewer than two live neighbors dies
* 2. Any live cell with more than three neighbors dies
* 3. Any live cell with two or three live neighbors lives on to the next generation
* 4. Any dead cell with exactly three live neighbors becomes a live cell
*/
public void checkSquare() {
if(beepersPresent()) {
pickBeeper();
if(noBeepersPresent()) { // Make sure we don't have a new cell
countNeighbors();
if(beepersPresent()) { // One neighbor
pickBeeper();
if(noBeepersPresent()) {
// Die because of rule 1
markDead();
} else { // Two neighbors
pickBeeper();
if(beepersPresent()) { // Three neighbors
pickBeeper();
if(beepersPresent()) { // Four neighbors
// Die because of rule 2
markDead();
} else {
// Cell is alive
putBeeper();
}
} else {
// Cell is alive
putBeeper();
}
}
} else {
// Die because of rule 1
markDead();
}
} else {
// this is a new live cell
putBeeper();
}
} else {
countNeighbors();
if(beepersPresent()) { // One neighbor
pickBeeper();
if(beepersPresent()) { // Two neighbors
pickBeeper();
if(beepersPresent()) { // Three neighbors
pickBeeper();
if(noBeepersPresent()) { // Exactly three neighbors
// Cell comes to life because of rule 4
markNew();
} else {
clearSquare();
}
}
}
}
}
}
public void markDead() {
clearSquare();
for(int i = 0; i < 3; i++)
putBeeper();
}
public void markNew() {
markDead();
pickBeeper();
}
public void clearSquare() {
while(beepersPresent()) {
pickBeeper();
}
}
public void countNeighbors() {
checkNorth();
checkSouth();
checkEast();
checkWest();
checkNorthEast();
checkSouthWest();
checkNorthWest();
checkSouthEast();
}
// ----------------- N, S, E, W ---------------- //
public void checkNorth() {
turnLeft();
checkAhead();
}
public void checkSouth() {
checkAhead();
}
public void checkEast() {
turnRight();
checkAhead();
}
public void checkWest() {
checkAhead();
}
public void checkAhead() {
if(frontIsClear()) {
move();
turnAround();
if(beepersPresent()) {
pickBeeper();
if(beepersPresent()) {
pickBeeper();
if(beepersPresent()) {
// This is a dead cell, still count it
markDead();
move();
putBeeper();
} else {
// This is a new cell, don't count it
markNew();
move();
}
} else {
// This is an surviving cell
putBeeper();
move();
putBeeper();
}
} else {
move();
}
} else {
turnAround();
}
}
// ---------- NE, NW, SW, SE ------------ //
public void checkNorthEast() {
checkDiagonal();
}
public void checkSouthWest() {
checkDiagonal();
}
public void checkNorthWest() {
turnLeft();
checkDiagonal();
}
public void checkSouthEast() {
checkDiagonal();
turnRight();
}
public void checkDiagonal() {
if(frontIsClear()) {
move();
turnLeft();
if(frontIsClear()) {
move();
turnAround();
if(beepersPresent()) {
pickBeeper();
if(beepersPresent()) {
pickBeeper();
if(beepersPresent()) {
// This is a dead cell, still count it
markDead();
moveDiagonal();
putBeeper();
} else {
// This is a new cell, don't count it
markNew();
moveDiagonal();
}
} else {
// This is a surviving cell, count it
putBeeper();
moveDiagonal();
putBeeper();
}
} else {
moveDiagonal();
}
} else {
turnLeft();
move();
}
} else {
turnAround();
}
}
public void moveDiagonal() {
move();
turnRight();
move();
}
// ---------- Basic Movement Methods --------- //
public void moveBack() {
turnAround();
while(frontIsClear())
move();
turnAround();
}
public void moveUpRow() {
turnLeft();
if(frontIsClear()) {
move();
turnRight();
} else {
moveBack();
}
}
// Note: This is an unfortunate hack to correct a
// shortfall in our new Eclipse plugin. Don't worry
// about (you won't be tested on it and aren't expected
// to understand what's going on). However, don't
// delete it, or you won't be able to run your Karel
// program.
public static void main(String[] args) {
String[] newArgs = new String[args.length + 1];
System.arraycopy(args, 0, newArgs, 0, args.length);
newArgs[args.length] = "code=" + new SecurityManager(){
public String className() {
return this.getClassContext()[1].getCanonicalName();
}
}.className();
SuperKarel.main(newArgs);
}
}