From b0454ab1dcda7a2cf1f69f9fcb9b03b3f11eca9f Mon Sep 17 00:00:00 2001 From: Lennard Sprong Date: Mon, 12 Aug 2024 16:48:03 +0200 Subject: [PATCH] Add Snake Egg --- src-ui/changes.html | 2 +- src-ui/img/snakeegg.png | Bin 0 -> 143 bytes src-ui/js/ui/KeyPopup.js | 3 +- src-ui/js/ui/Misc.js | 1 + src-ui/list.html | 1 + src-ui/res/p.en.json | 1 + src/puzzle/Bank.js | 5 +- src/puzzle/Graphic.js | 1 + src/puzzle/KeyInput.js | 5 +- src/pzpr/variety.js | 1 + src/res/failcode.en.json | 5 +- src/variety-common/Answer.js | 2 +- src/variety-common/Encode.js | 10 +- src/variety-common/Graphic.js | 4 +- src/variety/bosnianroad.js | 2 +- src/variety/snakeegg.js | 516 ++++++++++++++++++++++++++++++++++ test/puzzle/input_test.js | 9 +- test/script/snakeegg.js | 131 +++++++++ 18 files changed, 684 insertions(+), 15 deletions(-) create mode 100644 src-ui/img/snakeegg.png create mode 100644 src/variety/snakeegg.js create mode 100644 test/script/snakeegg.js diff --git a/src-ui/changes.html b/src-ui/changes.html index abcf063e4..6e29f205c 100644 --- a/src-ui/changes.html +++ b/src-ui/changes.html @@ -33,13 +33,13 @@
Latest types (all types)
diff --git a/src-ui/img/snakeegg.png b/src-ui/img/snakeegg.png new file mode 100644 index 0000000000000000000000000000000000000000..5d9c06e299321e32fe73944553358c75478bff2a GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~wg8_H*Xd_! zp8vny*0A*;P{iER#W6%;YI1@LGmk^d(&Y literal 0 HcmV?d00001 diff --git a/src-ui/js/ui/KeyPopup.js b/src-ui/js/ui/KeyPopup.js index d99f6dcf6..0aa14601a 100644 --- a/src-ui/js/ui/KeyPopup.js +++ b/src-ui/js/ui/KeyPopup.js @@ -204,7 +204,8 @@ ui.keypopup = { sananko: [10, 113], zabajaba: [80, 0], batten: [10, 0], - firewalk: [10, 0] + firewalk: [10, 0], + snakeegg: [10, 0] }, //--------------------------------------------------------------------------- diff --git a/src-ui/js/ui/Misc.js b/src-ui/js/ui/Misc.js index 2e2a831c7..a4bfd4b04 100755 --- a/src-ui/js/ui/Misc.js +++ b/src-ui/js/ui/Misc.js @@ -190,6 +190,7 @@ function toBGimage(pid) { "simpleloop", "slashpack", "snake", + "snakeegg", "squarejam", "starbattle", "statuepark", diff --git a/src-ui/list.html b/src-ui/list.html index 62b2e01a1..be750a4a4 100644 --- a/src-ui/list.html +++ b/src-ui/list.html @@ -62,6 +62,7 @@

パズルの種類のリスト
  • +
  • diff --git a/src-ui/res/p.en.json b/src-ui/res/p.en.json index 176dae622..4ec58a388 100644 --- a/src-ui/res/p.en.json +++ b/src-ui/res/p.en.json @@ -76,6 +76,7 @@ "preset.fleet3": "Battleships (size 3)", "preset.fleet4": "Battleships (size 4)", "preset.fleet5": "Battleships (size 5)", + "preset.nine": "1~9", "inputmode": "Input Mode", "inputmode.auto": "Auto", "inputmode.slide": "Slide", diff --git a/src/puzzle/Bank.js b/src/puzzle/Bank.js index 153642f26..b4c23290f 100644 --- a/src/puzzle/Bank.js +++ b/src/puzzle/Bank.js @@ -220,7 +220,7 @@ pzpr.classmgr.makeCommon({ } this.old = index < len ? this.board.bank.pieces[index].serialize() : null; - this.num = value || null; + this.num = value; this.index = index; }, @@ -268,6 +268,9 @@ pzpr.classmgr.makeCommon({ }, isNoop: function() { + if (this.num === null) { + return false; + } return this.old === this.num; }, diff --git a/src/puzzle/Graphic.js b/src/puzzle/Graphic.js index 3e3e6cf94..2456cf333 100644 --- a/src/puzzle/Graphic.js +++ b/src/puzzle/Graphic.js @@ -138,6 +138,7 @@ // 枠外の一辺のmargin(セル数換算) margin: 0.15, bankratio: 0.5, + bankVerticalOffset: 0.5, // canvasの大きさを保持する canvasWidth: null, diff --git a/src/puzzle/KeyInput.js b/src/puzzle/KeyInput.js index 86df4da74..a9aa6f704 100644 --- a/src/puzzle/KeyInput.js +++ b/src/puzzle/KeyInput.js @@ -515,6 +515,9 @@ pzpr.classmgr.makeCommon({ else if (this.modesnum) { this.targetdir = this.puzzle.playmode && this.disableAnum ? 5 : 0; } + if (this.puzzle.playmode) { + this.bankpiece = null; + } }, adjust_cell_to_excell: function() { var bd = this.board; @@ -569,8 +572,6 @@ pzpr.classmgr.makeCommon({ //--------------------------------------------------------------------------- movedir: function(dir, mv) { if (this.bankpiece !== null) { - // TODO implement moving from board to bank - // TODO implement moving between bankpieces return this; } diff --git a/src/pzpr/variety.js b/src/pzpr/variety.js index 7bbdd135b..42733270c 100755 --- a/src/pzpr/variety.js +++ b/src/pzpr/variety.js @@ -377,6 +377,7 @@ { kanpen: "slitherlink" } ], snake: [0, 0, "Snake", "Snake"], + snakeegg: [0, 0, "Snake Egg", "Snake Egg"], snakepit: [0, 0, "Snake Pit", "Snake Pit", "fillomino"], starbattle: [0, 0, "スターバトル", "Star Battle"], squarejam: [0, 0, "Square Jam", "Square Jam"], diff --git a/src/res/failcode.en.json b/src/res/failcode.en.json index 4d9fc63ad..fda76ba78 100644 --- a/src/res/failcode.en.json +++ b/src/res/failcode.en.json @@ -38,10 +38,13 @@ "asShadeNe.tilepaint": "The number of shaded cells underward or rightward is not correct.", "baDir.lollipops": "A stick has the wrong orientation.", "bankGt.battleship": "A ship appears too many times on the board.", + "bankGt.snakeegg": "A given size appears too many times on the board.", "bankGt": "A piece appears too many times on the board.", - "bankInvalid": "The board contains an invalid piece.", "bankInvalid.battleship": "The board contains an invalid ship.", + "bankInvalid.snakeegg": "The board contains an unshaded block of invalid size.", + "bankInvalid": "The board contains an invalid piece.", "bankLt.battleship": "Some ships are not used on the board.", + "bankLt.snakeegg": "Some given sizes are not used on the board.", "bankLt": "Some pieces are not used on the board.", "bankNe.tachibk": "The left and right grids contain different pieces.", "baParaGe3.juosan": "There are at least three vertical or horizontal bars in parallel.", diff --git a/src/variety-common/Answer.js b/src/variety-common/Answer.js index 58e644da2..debcd48e1 100644 --- a/src/variety-common/Answer.js +++ b/src/variety-common/Answer.js @@ -1309,7 +1309,7 @@ pzpr.classmgr.makeCommon({ for (var key in pieces) { var found = false; - for (var b = 0; b < this.board.bank.pieces.length; b++ && !found) { + for (var b = 0; b < this.board.bank.pieces.length && !found; b++) { if (key === this.board.bank.pieces[b].canonize()) { found = true; } diff --git a/src/variety-common/Encode.js b/src/variety-common/Encode.js index 56224c0e1..22aed3847 100644 --- a/src/variety-common/Encode.js +++ b/src/variety-common/Encode.js @@ -1008,9 +1008,13 @@ pzpr.classmgr.makeCommon({ this.outbstr += "/"; var bank = this.board.bank; - var pieces = bank.pieces.map(function(p) { - return p.serialize(); - }); + var pieces = bank.pieces + .map(function(p) { + return p.serialize(); + }) + .filter(function(p) { + return p; + }); for (var i = 0; i < bank.presets.length; i++) { if (!bank.presets[i].constant) { diff --git a/src/variety-common/Graphic.js b/src/variety-common/Graphic.js index a9c698b1b..57290e31b 100644 --- a/src/variety-common/Graphic.js +++ b/src/variety-common/Graphic.js @@ -2085,7 +2085,7 @@ pzpr.classmgr.makeCommon({ px = (piece.x + 0.25 + piece.w / 2) * this.cw * r; py = (piece.y + 0.25 + piece.h / 2) * this.ch * r; - py += (this.board.rows + 0.5) * this.ch; + py += (this.board.rows + this.bankVerticalOffset) * this.ch; w = (piece.w + 0.25) * this.cw * r * 0.5; h = (piece.h + 0.25) * this.ch * r * 0.5; } else { @@ -2712,7 +2712,7 @@ pzpr.classmgr.makeCommon({ var r = this.bankratio; var px = this.cw * r * (addButton.x + 0.25) + 1; var py = this.ch * r * (addButton.y + 0.25) + 1; - py += (this.board.rows + 0.5) * this.ch; + py += (this.board.rows + this.bankVerticalOffset) * this.ch; var px2 = px + this.cw * r * addButton.w - 1; var py2 = py + this.ch * r * addButton.h - 1; for (var i = 0; i < 4; i++) { diff --git a/src/variety/bosnianroad.js b/src/variety/bosnianroad.js index 3f4f329d6..0698311bc 100644 --- a/src/variety/bosnianroad.js +++ b/src/variety/bosnianroad.js @@ -1,4 +1,4 @@ -// +// // bosnianroad.js // (function(pidlist, classbase) { diff --git a/src/variety/snakeegg.js b/src/variety/snakeegg.js new file mode 100644 index 000000000..d76ef18a5 --- /dev/null +++ b/src/variety/snakeegg.js @@ -0,0 +1,516 @@ +// +// snakeegg.js +// +(function(pidlist, classbase) { + if (typeof module === "object" && module.exports) { + module.exports = [pidlist, classbase]; + } else { + pzpr.classmgr.makeCustom(pidlist, classbase); + } +})(["snakeegg"], { + MouseEvent: { + use: true, + inputModes: { + edit: ["number", "circle-shade", "info-blk"], + play: ["shade", "unshade", "number", "info-blk"] + }, + mouseinput: function() { + if (this.inputMode === "circle-shade") { + this.inputFixedNumber(0); + } else { + this.common.mouseinput.call(this); + } + }, + mouseinput_auto: function() { + if (this.puzzle.playmode) { + if (this.mousestart || this.mousemove) { + this.inputcell(); + } + if (this.notInputted() && this.mousestart) { + this.inputqcmp(); + } + } else if (this.puzzle.editmode) { + if (this.mousestart) { + this.inputqnum(); + } + if (this.mousestart && this.getbank()) { + if (this.btn === "left") { + this.inputpiece(); + } else { + this.inputqcmp(); + } + } + } + }, + inputpiece: function() { + var piece = this.getbank(); + if (!piece || piece.index === null) { + return; + } + + var pos0 = this.cursor.getaddr(); + this.cursor.bankpiece = piece.index; + pos0.draw(); + }, + + inputqcmp: function() { + var piece = this.getbank(); + if (piece) { + piece.setQcmp(piece.qcmp ? 0 : 1); + piece.draw(); + } + } + }, + + KeyEvent: { + enablemake: true, + enableplay: true, + moveTarget: function(ca) { + if (this.puzzle.playmode) { + return this.moveTCell(ca); + } + + var cursor = this.cursor; + if (cursor.bankpiece !== null) { + var pos0 = this.cursor.getaddr(); + var act = false; + + var piece = + this.board.bank.pieces[cursor.bankpiece] || this.board.bank.addButton; + + switch (ca) { + case "left": + if (cursor.bankpiece > 0) { + cursor.bankpiece--; + act = true; + } + break; + case "right": + if (cursor.bankpiece < this.board.bank.pieces.length) { + cursor.bankpiece++; + act = true; + } + break; + case "up": + if (piece.y === 0) { + cursor.bankpiece = null; + + var estx = (piece.x + piece.w / 2) / (this.board.bank.width || 1); + var bx = (estx * this.board.cols * 2) | 1; + + cursor.bx = Math.max(cursor.minx, Math.min(bx, cursor.maxx)); + cursor.by = cursor.maxy; + act = true; + } else { + act = this.moveBankVertical(-1); + } + break; + case "down": + act = this.moveBankVertical(+1); + break; + default: + break; + } + + pos0.draw(); + return act; + } + + if (ca === "down" && cursor.by === cursor.maxy) { + var pos0 = this.cursor.getaddr(); + if (cursor.bx === cursor.minx) { + cursor.bankpiece = 0; + } else { + var center = cursor.bx / this.puzzle.painter.bankratio; + var i = 0; + while (true) { + var piece = this.board.bank.pieces[i]; + if (!piece) { + cursor.bankpiece = this.board.bank.pieces.length; + break; + } + if (piece.x <= center && piece.x + piece.w >= center) { + cursor.bankpiece = i; + break; + } + if (piece.y > 0) { + cursor.bankpiece = i - 1; + break; + } + i++; + } + } + pos0.draw(); + return true; + } + return this.moveTCell(ca); + }, + moveBankVertical: function(dir) { + var cursor = this.cursor; + var piece = + this.board.bank.pieces[cursor.bankpiece] || this.board.bank.addButton; + + var center = piece.x + piece.w / 2; + + for ( + var i = cursor.bankpiece + dir; + i >= 0 && i <= this.board.bank.pieces.length; + i += dir + ) { + piece = this.board.bank.pieces[i] || this.board.bank.addButton; + if (piece.x <= center && piece.x + piece.w >= center) { + cursor.bankpiece = i; + return true; + } + } + return false; + }, + keyinput: function(ca) { + if (this.cursor.bankpiece !== null && this.puzzle.editmode) { + var piece = + this.board.bank.pieces[this.cursor.bankpiece] || + this.board.bank.addButton; + + if (ca === "BS" && piece.getNum() === -1) { + if (piece !== this.board.bank.addButton) { + this.board.bank.setPiece(null, this.cursor.bankpiece); + } + if (this.cursor.bankpiece > 0) { + this.cursor.bankpiece--; + } + piece.draw(); + return; + } + + var val = this.getNewNumber(piece, ca, piece.getNum()); + if (val === null) { + return; + } + piece.setNum(val); + piece = this.board.bank.pieces[this.cursor.bankpiece]; + + piece.draw(); + this.prev = piece; + this.cancelDefault = true; + } else { + this.key_inputqnum(ca); + } + } + }, + + Cell: { + disableAnum: true, + minnum: function() { + return this.puzzle.playmode ? 1 : 0; + }, + enableSubNumberArray: true, + allowShade: function() { + return this.qnum === 0 || this.qnum === -1; + }, + allowUnshade: function() { + return this.qnum !== 0; + } + }, + + Board: { + getBankPiecesInGrid: function() { + var ret = []; + var shapes = this.board.ublkmgr.components; + for (var r = 0; r < shapes.length; r++) { + var clist = shapes[r].clist; + ret.push([clist.length + "", clist]); + } + return ret; + } + }, + Bank: { + enabled: true, + allowAdd: true, + defaultPreset: function() { + return this.presets[0].constant; + }, + presets: [ + { + name: "preset.nine", + shortkey: "i", + constant: ["1", "2", "3", "4", "5", "6", "7", "8", "9"] + }, + { + name: "preset.copy_answer", + func: "copyAnswer" + }, + { + name: "preset.zero", + shortkey: "z", + constant: [] + } + ], + copyAnswer: function() { + var sizes = this.board.ublkmgr.components.map(function(u) { + return u.clist.length + ""; + }); + sizes.sort(function(a, b) { + return a - b; + }); + return sizes; + } + }, + BankPiece: { + num: null, + deserialize: function(str) { + if (+str) { + this.num = +str; + } else if (!str) { + this.num = -1; + } else { + throw new Error("Invalid piece"); + } + }, + serialize: function() { + if (this.num > 0) { + return this.num + ""; + } + return null; + }, + getmaxnum: function() { + return 999; + }, + getminnum: function() { + return 1; + }, + getNum: function() { + return this.num; + }, + setNum: function(num) { + this.board.bank.setPiece(num, this.index); + }, + + disInputHatena: true, + + /* Gaps between numbers are 1/10 */ + w: 10, + h: 10 + }, + BankEditOperation: { + isBankEdit: true, + disInputHatena: true, + + isModify: function(lastope) { + if ( + lastope.isBankEdit && + lastope.index === this.index && + lastope.num === this.old + ) { + lastope.num = this.num; + return true; + } + return false; + } + }, + BankAddButton: { + w: 10, + h: 10, + getmaxnum: function() { + return 999; + }, + getminnum: function() { + return 1; + }, + getNum: function() { + return -1; + }, + setNum: function(num) { + if (num < 0) { + return; + } + this.board.bank.setPiece(num, this.index); + } + }, + + AreaShadeGraph: { + enabled: true, + coloring: true + }, + AreaUnshadeGraph: { + enabled: true + }, + + Graphic: { + irowakeblk: true, + shadecolor: "rgb(80, 80, 80)", + bgcellcolor_func: "qsub1", + bankratio: 0.1, + bankVerticalOffset: 0.25, + circlestrokecolor_func: "null", + + paint: function() { + this.drawBGCells(); + + this.drawShadedCells(); + this.drawGrid(); + this.drawTargetSubNumber(true); + this.drawBorders(); + + this.drawSubNumbers(); + this.drawQuesNumbers(); + + this.drawCircles(); + + this.drawPekes(); + + this.drawChassis(); + + this.drawBank(); + this.drawTarget(); + }, + + getCircleFillColor: function(cell) { + return cell.qnum === 0 ? this.quescolor : null; + }, + getNumberTextCore: function(num) { + return num > 0 ? "" + num : num === -2 ? "?" : ""; + }, + + drawBankPiece: function(g, piece, idx) { + if (!piece) { + g.vid = "pb_c" + idx; + g.vhide(); + g.vid = "pb_n" + idx; + g.vhide(); + return; + } + + var x = this.cw * 0.1 * (piece.x + 5); + var y = this.ch * 0.1 * piece.y; + y += (this.board.rows + 0.75) * this.ch; + + g.vid = "pb_c" + idx; + g.strokeStyle = this.getBankPieceColor(piece); + g.fillStyle = null; + g.shapeCircle(x, y, this.cw * 0.4); + + g.vid = "pb_n" + idx; + g.strokeStyle = null; + g.fillStyle = this.getBankPieceColor(piece); + var str = piece.num >= 0 ? "" + piece.num : ""; + this.disptext(str, x, y, { ratio: 0.65 }); + }, + + drawTarget: function() { + this.drawCursor( + true, + this.puzzle.editmode || + this.puzzle.mouse.inputMode.indexOf("number") >= 0 + ); + } + }, + + Encode: { + decodePzpr: function(type) { + if (this.outbstr[0] !== "/") { + this.decodeNumber10(); + } + this.decodePieceBank(); + }, + encodePzpr: function(type) { + this.encodeNumber10(); + this.encodePieceBank(); + } + }, + + FileIO: { + decodeData: function() { + this.decodeCellQnum(); + this.decodeCellAns(); + this.decodePieceBank(); + this.decodePieceBankQcmp(); + this.decodeCellSnum(); + }, + encodeData: function() { + this.encodeCellQnum(); + this.encodeCellAns(); + this.encodePieceBank(); + this.encodePieceBankQcmp(); + this.encodeCellSnum(); + } + }, + + AnsCheck: { + checklist: [ + "checkShadeCellExist+", + "check2x2ShadeSection", + "checkShadeLoop", + "checkShadeBranch", + + "checkShadeOnCircle", + "checkNumberSize", + "checkCircleEndpoint", + "checkBankPiecesAvailable", + "checkBankPiecesInvalid", + + "checkConnectShade", + "checkBankPiecesUsed", + "doneShadingDecided" + ], + + check2x2ShadeSection: function() { + this.check2x2Block(function(cell) { + return cell.isShade() && cell.sblk.clist.length !== 4; + }, "cs2x2"); + }, + + checkShadeBranch: function() { + this.checkAllCell(function(cell) { + return ( + cell.isShade() && + cell.countDir4Cell(function(adj) { + return adj.isShade(); + }) > 2 + ); + }, "shBranch"); + }, + checkNumberSize: function() { + this.checkAllCell(function(cell) { + return ( + cell.qnum > 0 && (!cell.ublk || cell.ublk.clist.length !== cell.qnum) + ); + }, "bkSizeNe"); + }, + checkShadeOnCircle: function() { + this.checkAllCell(function(cell) { + return cell.qnum === 0 && !cell.isShade(); + }, "circleUnshade"); + }, + checkCircleEndpoint: function() { + this.checkAllCell(function(cell) { + if (!cell.isShade()) { + return false; + } + return ( + cell.qnum === 0 && + cell.countDir4Cell(function(adj) { + return adj.isShade(); + }) !== 1 + ); + }, "shEndpoint"); + }, + checkShadeLoop: function() { + var blocks = this.board.sblkmgr.components; + if (blocks.length !== 1) { + return; + } + var loop = blocks[0]; + if (loop.circuits > 0) { + this.failcode.add("shLoop"); + if (!this.checkOnly) { + loop.clist.seterr(1); + } + } + } + }, + FailCode: { + shBranch: "shBranch.snake", + shEndpoint: "shEndpoint.snake", + shLoop: "shLoop.snake" + } +}); diff --git a/test/puzzle/input_test.js b/test/puzzle/input_test.js index 272d7a9e1..831468934 100644 --- a/test/puzzle/input_test.js +++ b/test/puzzle/input_test.js @@ -24,8 +24,9 @@ function execmouse(puzzle, strs) { var idx = +strs[++i]; var piece = puzzle.board.bank.pieces[idx]; var r = puzzle.painter.bankratio; + var off = puzzle.painter.bankVerticalOffset; args.push((piece.x + piece.w / 2) * r * 2); - args.push((piece.y + piece.h / 2 + puzzle.board.maxby + 0.5) * r * 2); + args.push((piece.y + piece.h / 2) * r * 2 + puzzle.board.maxby + off); } else { args.push(+strs[i]); } @@ -85,7 +86,11 @@ function execinput(puzzle, str) { puzzle.key.inputKeys.apply(puzzle.key, strs); break; case "cursor": - puzzle.cursor.init(+strs[1], +strs[2]); + if (strs[1] === "bank") { + puzzle.cursor.bankpiece = strs[2] === "null" ? null : +strs[2]; + } else { + puzzle.cursor.init(+strs[1], +strs[2]); + } break; case "mouse": execmouse(puzzle, strs); diff --git a/test/script/snakeegg.js b/test/script/snakeegg.js new file mode 100644 index 000000000..5ae7621c3 --- /dev/null +++ b/test/script/snakeegg.js @@ -0,0 +1,131 @@ +/* snakeegg.js */ + +ui.debug.addDebugData("snakeegg", { + url: "5/5/a0a0l4a2f/4/1/2/3/4", + failcheck: [ + [ + "brNoShade", + "pzprv3/snakeegg/5/5/. 0 . 0 . /. . . . . /. . . . . /. 4 . 2 . /. . . . . /. . . . . /. . . . . /. . . . . /. . . . . /. . . . . /4/1/2/3/4/0 0 0 0 /" + ], + [ + "cs2x2", + "pzprv3/snakeegg/5/5/. 0 . 0 . /. . . . . /. . . . . /. 4 . 2 . /. . . . . /# # . # # /# . . # # /# . # # . /# . # . . /# # # . . /4/1/2/3/4/0 0 0 0 /" + ], + [ + "shLoop", + "pzprv3/snakeegg/5/5/. 0 . 0 . /. . . . . /. . . . . /. 4 . 2 . /. . . . . /# # # # # /# . . . # /# . # # # /# . # . . /# # # . . /4/1/2/3/4/0 0 0 0 /" + ], + [ + "shBranch", + "pzprv3/snakeegg/5/5/. 0 . 0 . /. . . . . /. . . . . /. 4 . 2 . /. . . . . /# # . # # /# . . . # /# # # # # /. . # . . /. . # # # /4/1/2/3/4/0 0 0 0 /" + ], + [ + "circleUnshade", + "pzprv3/snakeegg/5/5/. 0 . 0 . /. . . . . /. . . . . /. 4 . 2 . /. . . . . /. . . . # /# # # . # /# . # . # /# . # . # /. . # # # /4/1/2/3/4/0 0 0 0 /" + ], + [ + "bkSizeNe", + "pzprv3/snakeegg/5/5/. 0 . 0 . /. . . . . /. . . . . /. 4 . 2 . /. . . . . /. # . # # /# # . . # /# . # # # /# . # . . /# # # . . /4/1/2/3/4/0 0 0 0 /" + ], + [ + "shEndpoint", + "pzprv3/snakeegg/5/5/. 0 . 0 . /. . . . . /. . . . . /. 4 . 2 . /. . . . . /. # # # # /# # . . # /# . # # # /# . # . . /. . # # # /4/1/2/3/4/0 0 0 0 /" + ], + [ + "bankGt", + "pzprv3/snakeegg/5/5/. 0 . 0 . /. . . . . /. . . . . /. . . . . /. . . . . /. # . # . /. # . # # /# # . . # /# . # # # /# # # . . /4/1/2/3/4/0 0 0 0 /" + ], + [ + "bankLt", + "pzprv3/snakeegg/5/5/0 . . . . /. . . . . /. . 0 . . /. . . . . /. . . . . /# # # # . /. . . # # /# # # . # /# . . . # /# # # # # /4/1/2/3/4/0 0 0 0 /" + ], + [ + "bankInvalid", + "pzprv3/snakeegg/5/5/. 0 . 0 . /. . . . . /. . . . . /. . . . . /. . . . . /# # . # . /# . . # # /# # . . # /. # # . # /. . # # # /4/1/2/3/4/0 0 0 0 /" + ], + [ + "csDivide", + "pzprv3/snakeegg/5/5/. . 0 . . /. . . . . /. 0 . . . /. . . . . /. . . . . /# . # . . /. . # # # /# # . . # /# . . # # /# # # # . /4/1/2/3/4/0 0 0 0 /" + ], + [ + null, + "pzprv3/snakeegg/5/5/. 0 . 0 . /. . . . . /. . . . . /. 4 . 2 . /. . . . . /# # + # + /# + + # # /# # # + # /+ + # + # /+ + # # # /4/1/2/3/4/0 0 0 0 /" + ] + ], + inputs: [ + { + label: "Can type bank numbers", + input: ["newboard,3,3", "editmode", "mouse,left,bank,2", "key,9"], + result: + "pzprv3/snakeegg/3/3/. . . /. . . /. . . /. . . /. . . /. . . /9/1/2/9/4/5/6/7/8/9/0 0 0 0 0 0 0 0 0 /" + }, + { + label: "Can backspace", + input: ["cursor,bank,4", "key,BS"], + result: + "pzprv3/snakeegg/3/3/. . . /. . . /. . . /. . . /. . . /. . . /9/1/2/9/4//6/7/8/9/0 0 0 0 0 0 0 0 0 /" + }, + { + label: "Can erase", + input: ["key,BS"], + result: + "pzprv3/snakeegg/3/3/. . . /. . . /. . . /. . . /. . . /. . . /8/1/2/9/4/6/7/8/9/0 0 0 0 0 0 0 0 /" + }, + { + label: "Has moved cursor when erased", + result: function(puzzle, assert) { + assert.equal(puzzle.cursor.bankpiece, 3); + } + }, + { + label: "Move horizontally with arrow keys", + input: ["key,left,left,left"], + result: function(puzzle, assert) { + assert.equal(puzzle.cursor.bankpiece, 0); + } + }, + { + label: "Move up to grid from bank", + input: ["key,right,up"], + result: function(puzzle, assert) { + assert.equal(puzzle.cursor.bankpiece, null); + assert.equal(puzzle.cursor.bx, 3); + assert.equal(puzzle.cursor.by, 5); + } + }, + { + label: "Move down to bank from grid", + input: ["key,left,down"], + result: function(puzzle, assert) { + assert.equal(puzzle.cursor.bankpiece, 0); + } + }, + { + label: "Move down to specific bank column from grid", + input: ["cursor,5,5", "key,down"], + result: function(puzzle, assert) { + assert.equal(puzzle.cursor.bankpiece, 1); + } + }, + { + label: "Move down between bank rows", + input: ["key,left,down,down"], + result: function(puzzle, assert) { + assert.equal(puzzle.cursor.bankpiece, 4); + } + }, + { + label: "Move up between bank rows", + input: ["key,right,up"], + result: function(puzzle, assert) { + assert.equal(puzzle.cursor.bankpiece, 3); + } + }, + { + label: "Add new number", + input: ["cursor,bank,8", "key,1,down,2"], + result: + "pzprv3/snakeegg/3/3/. . . /. . . /. . . /. . . /. . . /. . . /9/1/2/9/4/6/7/8/9/12/0 0 0 0 0 0 0 0 0 /" + } + ] +});