Skip to content

Ellipsis #218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 18 additions & 24 deletions js/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -1387,23 +1387,24 @@ function rulesToMask(state) {
var anyObjectsPresent = [];
var movementsPresent = new BitVec(STRIDE_MOV);
var movementsMissing = new BitVec(STRIDE_MOV);
var hasEllipsis = false;

var objectlayers_l = new BitVec(STRIDE_MOV);
for (var l = 0; l < cell_l.length; l += 2) {
var object_dir = cell_l[l];
if (object_dir==='...') {
objectsPresent = ellipsisPattern;
if (cell_l.length!==2) {
logError("You can't have anything in with an ellipsis. Sorry.",rule.lineNumber);
hasEllipsis = true;
if (l != cell_l.length - 2) {
logError("Ellipsis must be last in a cell.", rule.lineNumber);
} else if ((k===0)||(k===cellrow_l.length-1)) {
logError("There's no point in putting an ellipsis at the very start or the end of a rule",rule.lineNumber);
} else if (rule.rhs.length>0) {
var rhscell=cellrow_r[k];
if (rhscell.length!==2 || rhscell[0]!=='...') {
if (rhscell.length < 2 || rhscell[rhscell.length - 2] !== '...') {
logError("An ellipsis on the left must be matched by one in the corresponding place on the right.",rule.lineNumber);
}
}
break;
continue;
} else if (object_dir==='random') {
logError("'random' cannot be matched on the left-hand side, it can only appear on the right",rule.lineNumber);
continue;
Expand Down Expand Up @@ -1443,28 +1444,21 @@ function rulesToMask(state) {
}
}

if (rule.rhs.length>0) {
if (rule.rhs.length > 0) {
var rhscell = cellrow_r[k];
var lhscell = cellrow_l[k];
if (rhscell[0]==='...' && lhscell[0]!=='...' ) {
logError("An ellipsis on the right must be matched by one in the corresponding place on the left.",rule.lineNumber);
}
for (var l=0;l<rhscell.length;l+=2) {
for (var l=0; l<rhscell.length; l+=2) {
var content=rhscell[l];
if (content==='...') {
if (rhscell.length!==2) {
logError("You can't have anything in with an ellipsis. Sorry.",rule.lineNumber);
}
if (content==='...' && l != rhscell.length - 2) {
logError("Ellipsis must be last in a cell.", rule.lineNumber);
}
}
if (rhscell[rhscell.length - 2] === '...' && lhscell[lhscell.length - 2] !== '...') {
logError("An ellipsis on the right must be matched by one in the corresponding place on the left.",rule.lineNumber);
}
}

if (objectsPresent === ellipsisPattern) {
cellrow_l[k] = ellipsisPattern;
continue;
} else {
cellrow_l[k] = new CellPattern([objectsPresent, objectsMissing, anyObjectsPresent, movementsPresent, movementsMissing, null]);
}
cellrow_l[k] = new CellPattern([objectsPresent, objectsMissing, anyObjectsPresent, movementsPresent, movementsMissing, null, hasEllipsis]);

if (rule.rhs.length===0) {
continue;
Expand All @@ -1487,7 +1481,7 @@ function rulesToMask(state) {
var object_name = cell_r[l + 1];

if (object_dir==='...') {
logError("spooky ellipsis found! (should never hit this)");
//logError("spooky ellipsis found! (should never hit this)");
break;
} else if (object_dir==='random') {
if (object_name in state.objectMasks) {
Expand Down Expand Up @@ -1575,7 +1569,7 @@ function cellRowMasks(rule) {
var cellRow = lhs[i];
var rowMask=new BitVec(STRIDE_OBJ);
for (var j=0;j<cellRow.length;j++) {
if (cellRow[j] === ellipsisPattern)
if (cellRow[j].hasEllipsis)
continue;
rowMask.ior(cellRow[j].objectsPresent);
}
Expand All @@ -1599,7 +1593,7 @@ function collapseRules(groups) {
for (var j = 0; j < oldrule.lhs.length; j++) {
var cellrow_l = oldrule.lhs[j];
for (var k = 0; k < cellrow_l.length; k++) {
if (cellrow_l[k] === ellipsisPattern) {
if (cellrow_l[k].hasEllipsis) {
if (ellipses[j]) {
logError("You can't use two ellipses in a single cell match pattern. If you really want to, please implement it yourself and send me a patch :) ", oldrule.lineNumber);
}
Expand Down Expand Up @@ -1682,7 +1676,7 @@ function checkNoLateRulesHaveMoves(state){
var cellRow_l = rule.patterns[cellRowIndex];
for (var cellIndex=0;cellIndex<cellRow_l.length;cellIndex++) {
var cellPattern = cellRow_l[cellIndex];
if (cellPattern === ellipsisPattern) {
if (cellPattern.hasEllipsis) {
continue;
}
var moveMissing = cellPattern.movementsMissing;
Expand Down
27 changes: 14 additions & 13 deletions js/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -980,8 +980,6 @@ Level.prototype.setMovements = function(index, vec) {
}
}

var ellipsisPattern = ['ellipsis'];

function BitVec(init) {
this.data = new Int32Array(init);
return this;
Expand Down Expand Up @@ -1107,15 +1105,15 @@ function Rule(rule) {
this.patterns = rule[1]; /* lists of CellPatterns to match */
this.hasReplacements = rule[2];
this.lineNumber = rule[3]; /* rule source for debugging */
this.isEllipsis = rule[4]; /* true if pattern has ellipsis */
this.hasEllipsis = rule[4]; /* true if pattern has ellipsis */
this.groupNumber = rule[5]; /* execution group number of rule */
this.isRigid = rule[6];
this.commands = rule[7]; /* cancel, restart, sfx, etc */
this.isRandom = rule[8];
this.cellRowMasks = rule[9];
this.cellRowMatches = [];
for (var i=0;i<this.patterns.length;i++) {
this.cellRowMatches.push(this.generateCellRowMatchesFunction(this.patterns[i],this.isEllipsis[i]));
this.cellRowMatches.push(this.generateCellRowMatchesFunction(this.patterns[i],this.hasEllipsis[i]));
}
/* TODO: eliminate isRigid, groupNumber, isRandom
from this class by moving them up into a RuleGroup class */
Expand Down Expand Up @@ -1163,12 +1161,14 @@ Rule.prototype.generateCellRowMatchesFunction = function(cellRow,hasEllipsis) {
fn += "var result = [];\n"
fn += "if(cellRow[0].matches(i)";
var cellIndex=1;
for (;cellRow[cellIndex]!==ellipsisPattern;cellIndex++) {
for (;!cellRow[cellIndex].hasEllipsis;cellIndex++) {
fn+="&&cellRow["+cellIndex+"].matches((i+"+cellIndex+"*d)%level.n_tiles)";
}
cellIndex++;
fn+=") {\n";
fn+="\tfor (var k=kmin;k<kmax;k++) {\n"
fn+="\t\tif(k>kmin && !cellRow["+cellIndex+"].matches((i+d*(k+"+(cellIndex-1)+"))%level.n_tiles))";
fn+="\t\t\tbreak;";
cellIndex++;
fn+="\t\tif(cellRow["+cellIndex+"].matches((i+d*(k+"+(cellIndex-1)+"))%level.n_tiles)";
cellIndex++;
for (;cellIndex<cr_l;cellIndex++) {
Expand Down Expand Up @@ -1212,7 +1212,7 @@ function cellRowMatchesWildcardFunctionGenerate(direction,cellRow,i, maxk, mink)
Rule.prototype.toJSON = function() {
/* match construction order for easy deserialization */
return [
this.direction, this.patterns, this.hasReplacements, this.lineNumber, this.isEllipsis,
this.direction, this.patterns, this.hasReplacements, this.lineNumber, this.hasEllipsis,
this.groupNumber, this.isRigid, this.commands, this.isRandom, this.cellRowMasks
];
};
Expand All @@ -1228,6 +1228,7 @@ function CellPattern(row) {
this.movementsMissing = row[4];
this.matches = this.generateMatchFunction();
this.replacement = row[5];
this.hasEllipsis = row[6];
};

function CellReplacement(row) {
Expand Down Expand Up @@ -1456,7 +1457,7 @@ function DoesCellRowMatchWildCard(direction,cellRow,i,maxk,mink) {
targetIndex = (targetIndex+d1+d0)%level.n_tiles;

var cellPattern = cellRow[j]
if (cellPattern === ellipsisPattern) {
if (cellPattern.hasEllipsis) {
//BAM inner loop time
for (var k=mink;k<maxk;k++) {
var targetIndex2=targetIndex;
Expand Down Expand Up @@ -1506,7 +1507,7 @@ function DoesCellRowMatch(direction,cellRow,i,k) {
for (var j=1;j<cr_l;j++) {
targetIndex = (targetIndex+d1+d0)%level.n_tiles;
cellPattern = cellRow[j];
if (cellPattern === ellipsisPattern) {
if (cellPattern.hasEllipsis) {
//only for once off verifications
targetIndex = (targetIndex+(d1+d0)*k)%level.n_tiles;
}
Expand Down Expand Up @@ -1739,7 +1740,7 @@ Rule.prototype.findMatches = function() {
for (var cellRowIndex=0;cellRowIndex<this.patterns.length;cellRowIndex++) {
var cellRow = this.patterns[cellRowIndex];
var matchFunction = this.cellRowMatches[cellRowIndex];
if (this.isEllipsis[cellRowIndex]) {//if ellipsis
if (this.hasEllipsis[cellRowIndex]) {//if ellipsis
var match = matchCellRowWildCard(this.direction,matchFunction,cellRow,cellRowMasks[cellRowIndex]);
} else {
var match = matchCellRow(this.direction,matchFunction,cellRow,cellRowMasks[cellRowIndex]);
Expand All @@ -1760,7 +1761,7 @@ Rule.prototype.applyAt = function(delta,tuple,check) {
if (check) {
var ruleMatches=true;
for (var cellRowIndex=0;cellRowIndex<rule.patterns.length;cellRowIndex++) {
if (rule.isEllipsis[cellRowIndex]) {//if ellipsis
if (rule.hasEllipsis[cellRowIndex]) {//if ellipsis
if (DoesCellRowMatchWildCard(rule.direction,rule.patterns[cellRowIndex],tuple[cellRowIndex][0],
tuple[cellRowIndex][1]+1, tuple[cellRowIndex][1])===false) { /* pass mink to specify */
ruleMatches=false;
Expand All @@ -1785,11 +1786,11 @@ Rule.prototype.applyAt = function(delta,tuple,check) {
for (var cellRowIndex=0;cellRowIndex<rule.patterns.length;cellRowIndex++) {
var preRow = rule.patterns[cellRowIndex];

var currentIndex = rule.isEllipsis[cellRowIndex] ? tuple[cellRowIndex][0] : tuple[cellRowIndex];
var currentIndex = rule.hasEllipsis[cellRowIndex] ? tuple[cellRowIndex][0] : tuple[cellRowIndex];
for (var cellIndex=0;cellIndex<preRow.length;cellIndex++) {
var preCell = preRow[cellIndex];

if (preCell === ellipsisPattern) {
if (preCell.hasEllipsis) {
var k = tuple[cellRowIndex][1];
currentIndex = (currentIndex+(d1+d0)*k)%level.n_tiles;
continue;
Expand Down