371 lines
11 KiB
Plaintext
371 lines
11 KiB
Plaintext
|
|
|
|
/** 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;
|
|
}
|
|
}
|