/**
improvments:
- do in place transposition
- add a static string boardBar = "+----+"
- change printString("|") to printChar
- change the grid to static variable?
*/
class Board {
field Array grid;
field int nTurn, seed, status; // status: 0: begin game; 1: in game; 2: lose; 3: win;
static String boardBar, strLost, strCont, strGameOver, strWon;
constructor Board new() {
var int i;
let grid = Array.new(4);
let i = 0;
while (i < 4) {
let grid[i] = Array.new(4);
let i = i + 1;
}
do initBoard();
let seed = 0;
return this;
}
function void init() {
let boardBar = "+----+";
let strLost = "You lost!";
let strWon = "You won!";
let strCont = "Press any key to continue";
let strGameOver = "Game over!";
return;
}
method void initBoard() {
var int i, j;
var Array t;
let i = 0;
while (i < 4) {
let j = 0;
let t = grid[i];
while (j < 4) {
let t[j] = 32;
let j = j + 1;
}
let i = i + 1;
}
let t = grid[0];
let t[0] = 65;
let nTurn = 0;
let status = 0;
return;
}
method void transpose() {
do exch(0, 1);
do exch(0, 2);
do exch(0, 3);
do exch(1, 2);
do exch(1, 3);
do exch(2, 3);
return;
}
method void exch(int i, int j){
var int t;
var Array s1, s2;
let s1 = grid[i];
let s2 = grid[j];
let t = s1[j];
let s1[j] = s2[i];
let s2[i] = t;
return;
}
method void align(Array xs, boolean left){
var int i, j;
let i = 0;
let j = 0;
if (left) {
while (i < 4) {
if (xs[i] > 64) {
let xs[j] = xs[i];
let j = j + 1;
}
let i = i + 1;
}
while (j < 4) {
let xs[j] = 32;
let j = j + 1;
}
} else {
while (i < 4) {
if (xs[3 - i] > 64) {
let xs[3 - j] = xs[3 - i];
let j = j + 1;
}
let i = i + 1;
}
while (j < 4) {
let xs[3 - j] = 32;
let j = j + 1;
}
}
return;
}
method void reduce(Array xs, boolean left){
if ((xs[0] = xs[1]) & (xs[2] = xs[3]) & (xs[0] > 64) & (xs[2] > 64)) {
if (left) {
let xs[0] = xs[0] + 1;
let xs[1] = xs[2] + 1;
let xs[2] = 32;
let xs[3] = 32;
} else {
let xs[3] = xs[3] + 1;
let xs[2] = xs[1] + 1;
let xs[1] = 32;
let xs[0] = 32;
}
return;
}
if ((xs[0] = xs[1]) & (xs[0] > 64)) {
if (left) {
let xs[0] = xs[0] + 1;
let xs[1] = xs[2];
let xs[2] = xs[3];
let xs[3] = 32;
} else {
let xs[1] = xs[1] + 1;
let xs[0] = 32;
}
return;
}
if ((xs[2] = xs[3]) & (xs[2] > 64)) {
if (left) {
let xs[2] = xs[2] + 1;
let xs[3] = 32;
} else {
let xs[3] = xs[3] + 1;
let xs[2] = xs[1];
let xs[1] = xs[0];
let xs[0] = 32;
}
return;
}
if ((xs[1] = xs[2]) & (xs[1] > 64)) {
if (left) {
let xs[1] = xs[1] + 1;
let xs[2] = xs[3];
let xs[3] = 32;
} else {
let xs[2] = xs[2] + 1;
let xs[1] = xs[0];
let xs[0] = 32;
}
return;
}
return;
}
method void addTile(){
var Array t;
var int r, c, parity, newTile;
/*
let t = grid[1];
if (t[1] = 32) {
let t[1] = 65;
}
*/
if (~(status = 1)) {
return;
}
let seed = seed * 25173 + 13849;
if (seed < 0) {
let seed = - seed;
}
if (seed - (seed / 2 * 2) = 0) {
let parity = 1;
} else {
let parity = -1;
}
let seed = seed - (seed / 16 * 16);
let r = seed / 4;
let c = seed - (4 * r);
let t = grid[r];
let newTile = 65;
while (t[c] > 64){
let seed = seed + parity;
if (seed < 0) {
let seed = 15;
}
let seed = seed - (seed / 16 * 16);
let r = seed / 4;
let c = seed - (4 * r);
let t = grid[r];
let newTile = 131 - newTile;
}
let t[c] = newTile;
return;
}
method void transform(char dir){
var boolean isVertical, left;
var int i;
if ((dir = 0) | (dir = 1)) {
let left = true;
} else {
let left = false;
}
if ((dir = 0) | (dir = 2)) {
let isVertical = false;
} else {
let isVertical = true;
}
if (isVertical) {
do transpose();
}
let i = 0;
while (i < 4) {
do align(grid[i], left);
do reduce(grid[i], left);
let i = i + 1;
}
if (isVertical) {
do transpose();
}
return;
}
method void next(int dir){
let nTurn = nTurn + 1;
do transform(dir);
do updateStatus();
return;
}
method int getStatus(){
return status;
}
method void setStatus(int x){
let status = x;
return;
}
method void updateStatus(){
var int i, j;
var Array r;
let i = 0;
while (i < 4) {
let r = grid[i];
let j = 0;
while (j < 4) {
if (r[j] = 75) {
let status = 3;
return;
}
if (r[j] = 32) {
let status = 1;
return;
}
let j = j + 1;
}
let i = i + 1;
}
let status = 2;
return;
}
method void draw(){
var int r, c, i, j;
var Array t;
let r = 9;
let c = 30;
if (status = 0) {
do Output.moveCursor(r - 1, c - 1);
do Output.printChar(75);
do Output.moveCursor(r + 1, c - 1);
do Output.printString(strCont);
} else { if (status = 2) {
do Output.moveCursor(r - 1, c - 1);
do Output.printString(strGameOver);
do Output.moveCursor(r + 1, c - 1);
do Output.printString(strLost);
do Output.moveCursor(r + 3, c - 1);
do Output.printString(strCont);
} else { if (status = 3) {
do Output.moveCursor(r - 1, c - 1);
do Output.printString(strGameOver);
do Output.moveCursor(r + 1, c - 1);
do Output.printString(strWon);
do Output.moveCursor(r + 3, c - 1);
do Output.printString(strCont);
} else {
do Output.moveCursor(r - 1, c - 1);
do Output.printString(boardBar);
do Output.moveCursor(r + 4, c - 1);
do Output.printString(boardBar);
let i = 0;
while (i < 4) {
let j = 0;
do Output.moveCursor(r + i, c - 1);
do Output.printChar(124); // 124 is |
let t = grid[i];
while (j < 4) {
do Output.printChar(t[j]);
let j = j + 1;
}
do Output.printChar(124);
let i = i + 1;
}
do Output.moveCursor(r + 6, c - 2);
do Output.printString("Turn: ");
do Output.printInt(nTurn);
}}}
return;
}
method void dispose() {
do Memory.deAlloc(this);
return;
}
}