Add solutions for part 1
This commit is contained in:
370
projects/09/CellAutomaton1D/CellularAutomatonController.jack
Normal file
370
projects/09/CellAutomaton1D/CellularAutomatonController.jack
Normal file
@@ -0,0 +1,370 @@
|
||||
|
||||
|
||||
/** Manages the cellular automaton and interacts with the user. */
|
||||
class CellularAutomatonController {
|
||||
field CellularAutomaton automaton;
|
||||
field Array config;
|
||||
field Array rules;
|
||||
field int numRules;
|
||||
|
||||
constructor CellularAutomatonController new() {
|
||||
// Turned out it is easiest to manage the Automaton itself from here.
|
||||
let automaton = CellularAutomaton.new();
|
||||
// We need the cell state array to write the initial configuration
|
||||
// by the user into it.
|
||||
let config = automaton.getCurrentConfig();
|
||||
|
||||
// Array to switch between rules.
|
||||
let numRules = 4;
|
||||
let rules = Array.new(numRules);
|
||||
let rules[0] = 57;
|
||||
let rules[1] = 90;
|
||||
let rules[2] = 101;
|
||||
let rules[3] = 110;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
method void dispose() {
|
||||
// config gets deAllocated by CellularAutomaton!
|
||||
do automaton.dispose();
|
||||
do rules.dispose();
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Greets the user and guides through the initial configuration. */
|
||||
method void initialConfiguration() {
|
||||
do Screen.clearScreen();
|
||||
do Screen.setColor(true);
|
||||
do sayHello();
|
||||
do printHelpInitialConfiguration();
|
||||
do createInitialConfiguration();
|
||||
do selectRule();
|
||||
do finishConfiguration();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Prints some dots on the screen to simulate loading, because why not? */
|
||||
method void makeWaitDots() {
|
||||
do Sys.wait(30);
|
||||
do Output.printString(".");
|
||||
do Sys.wait(30);
|
||||
do Output.printString(".");
|
||||
do Sys.wait(30);
|
||||
do Output.printString(".");
|
||||
do Sys.wait(30);
|
||||
do Output.printString(" ");
|
||||
return;
|
||||
}
|
||||
|
||||
method void waitForEnter() {
|
||||
var int key;
|
||||
var boolean exit;
|
||||
|
||||
let key = 0;
|
||||
let exit = false;
|
||||
|
||||
do Output.printString("<Enter> to continue. ");
|
||||
|
||||
while (~exit) {
|
||||
while (key = 0) {
|
||||
let key = Keyboard.keyPressed();
|
||||
}
|
||||
if (key = 128) { let exit = true; } // enter key
|
||||
while (~(key = 0)) {
|
||||
let key = Keyboard.keyPressed();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
method void sayHello() {
|
||||
do Output.moveCursor(0, 0);
|
||||
do Output.printString("> Welcome to cellular automaton 1D! ");
|
||||
do makeWaitDots();
|
||||
do Output.moveCursor(1, 0);
|
||||
do Output.printString("> Let's configure the automaton");
|
||||
do makeWaitDots();
|
||||
return;
|
||||
}
|
||||
|
||||
method void printHelpInitialConfiguration() {
|
||||
do Output.moveCursor(3, 0);
|
||||
do Output.printString("> Toggle the cells that should be alive with <space>");
|
||||
do makeWaitDots();
|
||||
do Output.moveCursor(4, 0);
|
||||
do Output.printString("> Move with <h>/<l> and use <u>/<i> to change the step size");
|
||||
do makeWaitDots();
|
||||
do Output.moveCursor(6, 0);
|
||||
do Output.printString("> stepSize = 1 - position = - activeCells = ");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
method void printStepSize(int n) {
|
||||
do Output.moveCursor(6, 15);
|
||||
do Output.printString(" ");
|
||||
do Output.moveCursor(6, 15);
|
||||
do Output.printInt(n);
|
||||
return;
|
||||
}
|
||||
|
||||
method void printCursorPosition(int n) {
|
||||
do Output.moveCursor(6, 32);
|
||||
do Output.printString(" ");
|
||||
do Output.moveCursor(6, 32);
|
||||
do Output.printInt(n);
|
||||
return;
|
||||
}
|
||||
|
||||
method void printActiveCellsj(int n) {
|
||||
do Output.moveCursor(6, 52);
|
||||
do Output.printString(" ");
|
||||
do Output.moveCursor(6, 52);
|
||||
do Output.printInt(n);
|
||||
return;
|
||||
}
|
||||
|
||||
method void createInitialConfiguration() {
|
||||
var int key;
|
||||
var boolean exit;
|
||||
var int cursorPosition;
|
||||
var int stepSize;
|
||||
var int activeCells;
|
||||
|
||||
// Variables for printing the cell selction UI.
|
||||
var int cursorY1, cursorY2, cellY1, cellY2;
|
||||
|
||||
let key = 0;
|
||||
|
||||
let cursorY1 = 90;
|
||||
let cursorY2 = 95;
|
||||
let cellY1 = 85;
|
||||
let cellY2 = 88;
|
||||
|
||||
let stepSize = 1;
|
||||
let cursorPosition = 0;
|
||||
let activeCells = 0;
|
||||
|
||||
do printStepSize(stepSize);
|
||||
do printCursorPosition(cursorPosition);
|
||||
do printActiveCellsj(activeCells);
|
||||
do Screen.drawLine(cursorPosition, cursorY1, cursorPosition, cursorY2);
|
||||
|
||||
let exit = false;
|
||||
while (~exit) {
|
||||
while (key = 0) {
|
||||
let key = Keyboard.keyPressed();
|
||||
}
|
||||
if (key = 128) { // enter key
|
||||
if (activeCells > 0) {
|
||||
let exit = true;
|
||||
} else {
|
||||
do Output.moveCursor(9, 0);
|
||||
do Output.printString("> Toggle at least one cell!");
|
||||
}
|
||||
} // enter key
|
||||
if (key = 72) { // h key
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawLine(cursorPosition, cursorY1, cursorPosition, cursorY2);
|
||||
if ((cursorPosition - stepSize) > 0) {
|
||||
let cursorPosition = cursorPosition - stepSize;
|
||||
} else {
|
||||
let cursorPosition = 0;
|
||||
}
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawLine(cursorPosition, cursorY1, cursorPosition, cursorY2);
|
||||
do printCursorPosition(cursorPosition);
|
||||
}
|
||||
if (key = 76) { // l key
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawLine(cursorPosition, cursorY1, cursorPosition, cursorY2);
|
||||
if ((cursorPosition + stepSize) < 511) {
|
||||
let cursorPosition = cursorPosition + stepSize;
|
||||
} else {
|
||||
let cursorPosition = 511;
|
||||
}
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawLine(cursorPosition, cursorY1, cursorPosition, cursorY2);
|
||||
do printCursorPosition(cursorPosition);
|
||||
}
|
||||
if (key = 73) { // i key
|
||||
if (stepSize < 512) {
|
||||
let stepSize = stepSize * 2;
|
||||
do printStepSize(stepSize);
|
||||
}
|
||||
}
|
||||
if (key = 85) { // u key
|
||||
if (stepSize > 1) {
|
||||
let stepSize = stepSize / 2;
|
||||
do printStepSize(stepSize);
|
||||
}
|
||||
}
|
||||
if (key = 32) { // space key
|
||||
if (config[cursorPosition]) { // cell is alive -> make dead
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawLine(cursorPosition, cellY1, cursorPosition, cellY2);
|
||||
let config[cursorPosition] = 0;
|
||||
let activeCells = activeCells - 1;
|
||||
} else { // cell is dead -> make alive
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawLine(cursorPosition, cellY1, cursorPosition, cellY2);
|
||||
let config[cursorPosition] = 1;
|
||||
let activeCells = activeCells + 1;
|
||||
}
|
||||
do Screen.setColor(true);
|
||||
do printActiveCellsj(activeCells);
|
||||
}
|
||||
|
||||
while (~(key = 0)) {
|
||||
let key = Keyboard.keyPressed();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
method void printRule(int n) {
|
||||
do Output.moveCursor(12, 8);
|
||||
do Output.printString(" ");
|
||||
do Output.moveCursor(12, 8);
|
||||
do Output.printInt(n);
|
||||
return;
|
||||
}
|
||||
|
||||
method void selectRule() {
|
||||
var int i;
|
||||
var int rule;
|
||||
var int key;
|
||||
var boolean exit;
|
||||
|
||||
let i = 1;
|
||||
let rule = rules[i];
|
||||
let exit = false;
|
||||
|
||||
do Output.moveCursor(10, 0);
|
||||
do Output.printString("> Good. Let's select which rule you want to simulate");
|
||||
do makeWaitDots();
|
||||
do Output.moveCursor(11, 0);
|
||||
do Output.printString("> Use <h>/<l> to switch between rules");
|
||||
do makeWaitDots();
|
||||
|
||||
do Output.moveCursor(12, 0);
|
||||
do Output.printString("> Rule selected. Confirm with <enter>.");
|
||||
do printRule(rule);
|
||||
|
||||
while (~exit) {
|
||||
while (key = 0) {
|
||||
let key = Keyboard.keyPressed();
|
||||
}
|
||||
if (key = 128) { // enter key
|
||||
let exit = true;
|
||||
}
|
||||
|
||||
if (key = 72) { // h key -> prev rule
|
||||
if (i > 0) {
|
||||
let i = i - 1;
|
||||
}
|
||||
}
|
||||
if (key = 76) {
|
||||
if (i < (numRules - 1)) {
|
||||
let i = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
let rule = rules[i];
|
||||
do printRule(rule);
|
||||
do automaton.setRule(rule);
|
||||
|
||||
while (~(key = 0)) {
|
||||
let key = Keyboard.keyPressed();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
method void finishConfiguration() {
|
||||
do Output.moveCursor(15, 0);
|
||||
do Output.printString("> Okay, nice. We are ready to go");
|
||||
do makeWaitDots();
|
||||
do Output.moveCursor(16, 0);
|
||||
do Output.printString("> Once you press enter you will no longer see the menu");
|
||||
do makeWaitDots();
|
||||
do Output.moveCursor(17, 0);
|
||||
do Output.printString("> So remember the following keys (or at least <q> for quit)");
|
||||
do makeWaitDots();
|
||||
do Output.moveCursor(19, 0);
|
||||
do Output.printString("> Controls: ");
|
||||
do makeWaitDots();
|
||||
do Output.moveCursor(20, 0);
|
||||
do Output.printString("> <p>ause, <c>ontinue, <s>tep, <r>restart, <q>quit! ");
|
||||
|
||||
do Output.moveCursor(22, 0);
|
||||
do Output.printString(" ");
|
||||
do waitForEnter();
|
||||
do Screen.clearScreen();
|
||||
return;
|
||||
}
|
||||
|
||||
method void run() {
|
||||
var int key;
|
||||
var boolean quit;
|
||||
var boolean running;
|
||||
var boolean restart;
|
||||
var boolean step;
|
||||
|
||||
let quit = false;
|
||||
let restart = false;
|
||||
let running = true;
|
||||
let step = false;
|
||||
|
||||
while (~quit) {
|
||||
if (restart) {
|
||||
do automaton.dispose();
|
||||
let automaton = CellularAutomaton.new();
|
||||
do initialConfiguration();
|
||||
let quit = false;
|
||||
let restart = false;
|
||||
let running = true;
|
||||
let step = false;
|
||||
}
|
||||
|
||||
if (running) {
|
||||
do automaton.draw();
|
||||
do automaton.step();
|
||||
}
|
||||
|
||||
if (step) {
|
||||
do automaton.draw();
|
||||
do automaton.step();
|
||||
let step = false;
|
||||
}
|
||||
|
||||
let key = Keyboard.keyPressed();
|
||||
if (key = 82) { // r key
|
||||
let restart = true;
|
||||
}
|
||||
if (key = 80) { // p key
|
||||
let running = false;
|
||||
}
|
||||
if (key = 67) { // c key
|
||||
let running = true;
|
||||
}
|
||||
if (key = 83) { // s key
|
||||
if (~running) {
|
||||
let step = true;
|
||||
}
|
||||
}
|
||||
if (key = 81) { // q key
|
||||
let quit = true;
|
||||
}
|
||||
|
||||
while (~(key = 0)) {
|
||||
let key = Keyboard.keyPressed();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user