diff --git a/src-ui/changes.html b/src-ui/changes.html index e627e92e4..f2d147e4f 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/wittgen.png b/src-ui/img/wittgen.png new file mode 100644 index 000000000..2cd0ed39d Binary files /dev/null and b/src-ui/img/wittgen.png differ diff --git a/src-ui/js/ui/KeyPopup.js b/src-ui/js/ui/KeyPopup.js index d324c38c9..0c0cdfd62 100644 --- a/src-ui/js/ui/KeyPopup.js +++ b/src-ui/js/ui/KeyPopup.js @@ -183,7 +183,8 @@ ui.keypopup = { sashikazune: [10, 0], patchwork: [10, 0], waterwalk: [10, 0], - haisu: [10, 0] + haisu: [10, 0], + wittgen: [4, 0] }, //--------------------------------------------------------------------------- diff --git a/src-ui/js/ui/Misc.js b/src-ui/js/ui/Misc.js index 88790da45..540a48914 100755 --- a/src-ui/js/ui/Misc.js +++ b/src-ui/js/ui/Misc.js @@ -190,6 +190,7 @@ function toBGimage(pid) { "vslither", "walllogic", "waterwalk", + "wittgen", "yinyang" ]; if (imgs.indexOf(pid) >= 0) { diff --git a/src-ui/list.html b/src-ui/list.html index 8671a254a..b8d787265 100644 --- a/src-ui/list.html +++ b/src-ui/list.html @@ -334,6 +334,7 @@

パズルの種類のリスト
  • +
  • diff --git a/src/pzpr/variety.js b/src/pzpr/variety.js index abe510fab..ecfc953d2 100755 --- a/src/pzpr/variety.js +++ b/src/pzpr/variety.js @@ -387,6 +387,7 @@ walllogic: [0, 0, "ウォールロジック", "Wall Logic"], waterwalk: [0, 0, "ウォーターウォーク", "Water Walk", "icewalk"], wblink: [0, 0, "シロクロリンク", "Shirokuro-link"], + wittgen: [0, 0, "Wittgenstein Briquet", "Wittgenstein Briquet", "kaidan"], yajikazu: [1, 0, "やじさんかずさん", "Yajisan-Kazusan"], yajilin: [ 0, diff --git a/src/res/failcode.en.json b/src/res/failcode.en.json index 8d6bd7fae..5857a8293 100644 --- a/src/res/failcode.en.json +++ b/src/res/failcode.en.json @@ -397,6 +397,7 @@ "cu3.aqre": "There are more than three unshaded cells in a row.", "cuConnOut": "Some unshaded cells are not connected to the outside.", "cuDivide.kaidan": "The rectangles are divided.", + "cuDivide.wittgen": "The cells not used by rectangles are divided.", "cuDivide": "The unshaded cells are divided.", "cuDivideRB": "The unshaded cells are divided.", "cuEndpoint.takoyaki": "An endpoint does not have a circle.", @@ -525,6 +526,7 @@ "lnLenGt.reflect": "The lines passing a triangle are too long.", "lnLengthGt.pencils": "A line is longer than the connected pencil.", "lnLengthLt.pencils": "A line is shorter than the connected pencil.", + "lnLengthNe3.wittgen": "A block does not cover exactly 3 cells.", "lnLenLt.anglers": "A line is shorter than the number.", "lnLenLt.reflect": "The lines passing a triangle are too short.", "lnMultipleTips.pencils": "A line connects to more than one pencil tip.", @@ -636,8 +638,10 @@ "nmIgnored.herugolf": "There is a Hole without a ball.", "nmIneqNe.minarism": "A inequality sign is not correct.", "nmLineGt.hashikake": "The number of connecting bridges to a number is not correct.", + "nmLineGt.wittgen": "The number of blocks adjacent to a number is not correct.", "nmLineGt1.amibo": "Multiple lines connect to a white circle.", "nmLineLt.hashikake": "The number of connecting bridges to a number is not correct.", + "nmLineLt.wittgen": "The number of blocks adjacent to a number is not correct.", "nmLineLt2.kouchoku": "A clue doesn't have two segments.", "nmLineNe.ichimaga": "The number is not equal to the number of lines out of the circle.", "nmLineNe.lither": "The number is not equal to the number of lines around it.", diff --git a/src/variety/kaidan.js b/src/variety/kaidan.js index 3fd9c9447..f3f44efed 100644 --- a/src/variety/kaidan.js +++ b/src/variety/kaidan.js @@ -4,7 +4,7 @@ } else { pzpr.classmgr.makeCustom(pidlist, classbase); } -})(["kaidan", "takoyaki"], { +})(["kaidan", "takoyaki", "wittgen"], { MouseEvent: { use: true, RBShadeCell: true, @@ -53,13 +53,19 @@ return; } - if (this.pid === "kaidan" && cell.lcnt === 1 && this.btn === "left") { + if ( + (this.pid === "kaidan" || this.pid === "wittgen") && + cell.lcnt === 1 && + this.btn === "left" + ) { cell.setLineVal(+!cell.line); cell.draw(); } else if (cell.isNum()) { this.inputqcmp(); } else if (this.btn === "right" && this.inputpeke_ifborder()) { return; + } else if (this.pid === "wittgen") { + this.inputShade(); } else { this.inputcell(); } @@ -99,7 +105,7 @@ this.common.mousereset.call(this); } }, - "MouseEvent@kaidan": { + "MouseEvent@kaidan,wittgen": { inputLine: function() { var cell = this.getcell(); var addcmp = false; @@ -172,6 +178,22 @@ } } }, + "MouseEvent@wittgen#2": { + inputModes: { + edit: ["number", "undef", "clear"], + play: ["line", "peke", "subcircle", "objblank", "completion"] + }, + inputShade: function() { + if (this.puzzle.getConfig("use") === 2) { + this.inputBGcolor(); + } else { + this.inputFixedQsub(this.btn === "left" ? 1 : 2); + } + }, + inputDot: function() { + this.inputFixedQsub(2); + } + }, KeyEvent: { enablemake: true @@ -197,6 +219,81 @@ "Border@takoyaki": { enableLineNG: true }, + "Border@wittgen": { + prehook: { + line: function(num) { + if (!num) { + return false; + } + + if (this.isLineNG() || this.checkFormCurve(num)) { + return true; + } + + var length = 0; + + if (this.isVert() && this.relbd(-2, 0).path) { + length += this.relbd(-2, 0).path.clist.length; + } + if (this.isVert() && this.relbd(2, 0).path) { + length += this.relbd(2, 0).path.clist.length; + } + if (!this.isVert() && this.relbd(0, -2).path) { + length += this.relbd(0, -2).path.clist.length; + } + if (!this.isVert() && this.relbd(0, 2).path) { + length += this.relbd(0, 2).path.clist.length; + } + return length >= 3; + } + }, + posthook: { + line: function() { + for (var i in this.sidecell) { + var cell = this.sidecell[i]; + if (cell.line && cell.lcnt !== 1) { + cell.setLineVal(0); + } + if (this.line && cell.qsub) { + cell.setQsub(0); + } + cell.draw(); + } + if (this.path && this.path.clist.length === 3) { + for (var c = 0; c < 3; c++) { + var cell = this.path.clist[c]; + if (cell.lcnt === 1) { + cell.setLineVal(1); + cell.draw(); + } + } + } + if (!this.line && this.isVert()) { + if (this.relbd(-2, 0).line) { + var cell = this.relcell(-3, 0); + cell.setLineVal(0); + cell.draw(); + } + if (this.relbd(2, 0).line) { + var cell = this.relcell(3, 0); + cell.setLineVal(0); + cell.draw(); + } + } else if (!this.line && this.isHorz()) { + if (this.relbd(0, -2).line) { + var cell = this.relcell(0, -3); + cell.setLineVal(0); + cell.draw(); + } + if (this.relbd(0, 2).line) { + var cell = this.relcell(0, 3); + cell.setLineVal(0); + cell.draw(); + } + } + } + } + }, Cell: { maxnum: 4, @@ -228,6 +325,16 @@ return this.qnum === -1; } }, + "Cell@wittgen": { + isDot: function() { + return this.qsub === 2 && this.lcnt === 0; + }, + prehook: { + qsub: function(num) { + return num && (this.isNum() || this.lcnt > 0); + } + } + }, Board: { cols: 8, @@ -247,29 +354,43 @@ return !cell.noLP(); } }, + "AreaUnshadeGraph@wittgen": { + enabled: true, + relation: { "border.line": "block" }, + isnodevalid: function(cell) { + return cell.lcnt === 0; + }, + modifyOtherInfo: function(border, relation) { + this.setEdgeByNodeObj(border.sidecell[0]); + this.setEdgeByNodeObj(border.sidecell[1]); + } + }, Graphic: { - hideHatena: true, - gridcolor_type: "LIGHT", - fontShadecolor: "white", fgcellcolor_func: "qnum", qcmpcolor: "rgb(127,127,127)", - mbcolor: "rgb(127,127,255)", paint: function() { this.drawBGCells(); this.drawGrid(); - this.drawQuesCells(); + if (this.pid !== "wittgen") { + this.drawQuesCells(); + } this.drawQuesNumbers(); - this.drawCircles(); - this.drawCrosses(); + if (this.pid !== "wittgen") { + this.drawCircles(); + this.drawCrosses(); + } else { + this.drawDotCells(); + this.drawMBs(); + } this.drawLines(); - if (this.pid === "kaidan") { + if (this.pid === "kaidan" || this.pid === "wittgen") { this.drawLineEnds(); } this.drawPekes(); @@ -277,6 +398,30 @@ this.drawChassis(); this.drawTarget(); + } + }, + "Graphic@kaidan,takoyaki#2": { + hideHatena: true, + mbcolor: "rgb(127,127,255)", + fontShadecolor: "white", + getQuesNumberColor: function(cell) { + return cell.qcmp === 1 ? this.qcmpcolor : this.fontShadecolor; + }, + + getCircleStrokeColor: function(cell) { + if (cell.qans === 1) { + if (cell.error === 1) { + return this.errcolor1; + } else if (cell.trial) { + return this.trialcolor; + } else { + return this.quescolor; + } + } + return null; + }, + getCircleFillColor: function(cell) { + return null; }, drawCrosses: function() { var g = this.vinc("cell_mb", "auto"); @@ -300,28 +445,9 @@ g.vhide(); } } - }, - - getQuesNumberColor: function(cell) { - return cell.qcmp === 1 ? this.qcmpcolor : this.fontShadecolor; - }, - getCircleStrokeColor: function(cell) { - if (cell.qans === 1) { - if (cell.error === 1) { - return this.errcolor1; - } else if (cell.trial) { - return this.trialcolor; - } else { - return this.quescolor; - } - } - return null; - }, - getCircleFillColor: function(cell) { - return null; } }, - "Graphic@kaidan": { + "Graphic@kaidan,wittgen": { drawLines: function() { var g = this.vinc("line", "crispEdges"); var mx = this.bw / 2; @@ -378,8 +504,10 @@ px = cell.bx * this.bw; py = cell.by * this.bh; - g.fillStyle = cell.trial ? this.trialcolor : this.linecolor; var lm = this.lm + this.addlw / 2; + g.fillStyle = cell.trial + ? this.trialcolor + : this.getLineColor(dir[1]); if (dir[1].isVert()) { g.fillRectCenter( px + (mx + 1) * (dir[2] === cell.RT ? -1 : +1), @@ -404,6 +532,36 @@ "Graphic@takoyaki": { irowake: true }, + "Graphic@wittgen#2": { + getQuesNumberColor: function(cell) { + if ((cell.error || cell.qinfo) === 1) { + return this.errcolor1; + } + return cell.qcmp ? this.qcmpcolor : this.quescolor; + }, + drawMBs: function() { + var g = this.vinc("cell_mb", "auto", true); + g.lineWidth = 1; + + var rsize = this.cw * 0.35; + var clist = this.range.cells; + for (var i = 0; i < clist.length; i++) { + var cell = clist[i], + px, + py; + + g.vid = "c_MB1_" + cell.id; + if (cell.qsub === 1) { + px = cell.bx * this.bw; + py = cell.by * this.bh; + g.strokeStyle = !cell.trial ? this.mbcolor : "rgb(192, 192, 192)"; + g.strokeCircle(px, py, rsize); + } else { + g.vhide(); + } + } + } + }, Encode: { decodePzpr: function(type) { @@ -419,7 +577,11 @@ this.decodeCell(function(cell, ca) { var val = +ca; if (val & 1) { - cell.qans = 1; + if (this.pid === "wittgen") { + cell.qsub = 2; + } else { + cell.qans = 1; + } } if (val & 2) { cell.line = 1; @@ -436,10 +598,10 @@ encodeData: function() { this.encodeCellQnum(); this.encodeCell(function(cell) { - return ( - (cell.qans | (cell.line << 1) | (cell.qsub << 2) | (cell.qcmp << 3)) + - " " - ); + var ans = this.pid === "wittgen" ? cell.qsub === 2 : cell.qans === 1; + var sub = cell.qsub === 1; + + return (+ans | (cell.line << 1) | (+sub << 2) | (cell.qcmp << 3)) + " "; }); this.encodeBorderLine(); } @@ -463,6 +625,16 @@ 1, "nmShadeLt" ); + }, + checkLineOverlap: function() { + this.checkAllCell(function(cell) { + return cell.lcnt > 2 || cell.isLineCurve(); + }, "laCurve"); + }, + checkMissingEnd: function() { + this.checkAllCell(function(cell) { + return cell.lcnt === 1 && !cell.line; + }, "ceNoEnd"); } }, @@ -514,17 +686,6 @@ return b1.line && b2.line; }, "lnEnds"); }, - - checkLineOverlap: function() { - this.checkAllCell(function(cell) { - return cell.lcnt > 2 || cell.isLineCurve(); - }, "laCurve"); - }, - checkMissingEnd: function() { - this.checkAllCell(function(cell) { - return cell.lcnt === 1 && !cell.line; - }, "ceNoEnd"); - }, checkEmptyCell_kaidan: function() { this.checkAllCell(function(cell) { return cell.lcnt === 0 && !cell.isShade() && cell.noNum(); @@ -632,6 +793,56 @@ }, "cuEndpoint"); } }, + "AnsCheck@wittgen#1": { + checklist: [ + "checkDir4BlockOver", + "checkConnectUnshade", + "checkLineOverlap", + "checkLineLength", + "checkDir4BlockLess", + "checkMissingEnd" + ], + checkLineLength: function() { + var paths = this.board.linegraph.components; + for (var r = 0; r < paths.length; r++) { + var path = paths[r]; + if (path.clist.length === 3) { + continue; + } + if ( + path.clist.length === 2 && + (!path.clist[0].line || !path.clist[1].line) + ) { + continue; + } + + this.failcode.add("lnLengthNe3"); + if (this.checkOnly) { + break; + } + this.board.border.setnoerr(); + path.setedgeerr(1); + } + }, + checkDir4BlockOver: function() { + this.checkDir4Cell( + function(cell) { + return cell.lcnt; + }, + 2, + "nmLineGt" + ); + }, + checkDir4BlockLess: function() { + this.checkDir4Cell( + function(cell) { + return cell.lcnt; + }, + 1, + "nmLineLt" + ); + } + }, "FailCode@takoyaki": { lnOnShade: "lnOnShade" } diff --git a/test/script/wittgen.js b/test/script/wittgen.js new file mode 100644 index 000000000..1b0c7d4d2 --- /dev/null +++ b/test/script/wittgen.js @@ -0,0 +1,101 @@ +/* wittgen.js */ + +ui.debug.addDebugData("wittgen", { + url: "6/6/n0drchbj", + failcheck: [ + [ + "nmLineGt", + "pzprv3/wittgen/6/6/. . . . . . /. . 0 3 . . /. . . . . . /. . . . . . /2 . . . . 1 /. . . . . . /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /2 0 2 0 0 0 /0 2 0 2 0 0 /2 0 2 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /1 1 0 0 0 /0 1 1 0 0 /1 1 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /" + ], + [ + "nmLineLt", + "pzprv3/wittgen/6/6/. . . . . . /. . 0 3 . . /. . . . . . /. . . . . . /2 . . . . 1 /. . . . . . /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 2 0 2 0 0 /2 0 2 2 0 2 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 1 1 0 0 /1 1 0 1 1 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /" + ], + [ + "lnLengthNe3", + "pzprv3/wittgen/6/6/. . . . . . /. . 0 3 . . /. . . . . . /. . . . . . /2 . . . . 1 /. . . . . . /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /2 0 0 2 0 0 /0 0 0 0 0 0 /0 0 0 0 2 2 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /1 1 1 0 0 /0 0 0 0 0 /0 0 0 0 1 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /" + ], + [ + "laCurve", + "pzprv3/wittgen/6/6/. . . . . . /. . 0 3 . . /. . . . . . /. . . . . . /2 . . . . 1 /. . . . . . /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 2 0 0 0 /0 0 0 0 0 0 /2 0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /1 1 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /0 0 1 0 0 0 /0 0 1 0 0 0 /" + ], + [ + "cuDivide", + "pzprv3/wittgen/6/6/. . . . . . /. . 0 3 . . /. . . . . . /. . . . . . /2 . . . . 1 /. . . . . . /0 0 0 2 0 2 /2 0 0 0 2 0 /0 0 0 2 0 0 /2 0 0 0 2 0 /0 0 0 2 0 0 /2 0 2 2 0 2 /0 0 0 1 1 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /1 1 0 1 1 /0 0 0 0 0 0 /1 0 0 0 1 0 /1 0 0 1 1 0 /0 0 0 1 0 0 /0 0 0 0 0 0 /" + ], + [ + "ceNoEnd", + "pzprv3/wittgen/6/6/. . . . . . /. . 0 3 . . /. . . . . . /. . . . . . /2 . . . . 1 /. . . . . . /0 0 0 2 0 2 /0 0 0 0 2 2 /0 0 0 2 0 0 /2 0 0 0 0 2 /0 2 0 0 0 0 /0 0 0 0 0 0 /0 0 0 1 1 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 1 1 /1 0 0 1 1 1 /0 1 0 1 0 0 /0 0 0 0 0 0 /" + ], + [ + null, + "pzprv3/wittgen/6/6/. . . . . . /. . 0 3 . . /. . . . . . /. . . . . . /2 . . . . 1 /. . . . . . /0 0 0 2 0 2 /2 0 0 0 2 2 /0 2 0 2 0 0 /2 0 0 0 2 2 /0 2 0 2 0 0 /0 0 0 0 0 0 /0 0 0 1 1 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 0 /1 0 0 0 1 1 /1 1 0 1 1 1 /0 1 0 1 0 0 /0 0 0 0 0 0 /" + ] + ], + inputs: [ + { + label: "Test UnshadeGraph updates", + input: [ + "newboard,4,2", + "playmode", + "mouse,left,1,1,5,1", + "mouse,left,3,3,7,3" + ], + result: function(puzzle, assert) { + assert.notEqual( + puzzle.board.getc(7, 1).ublk, + puzzle.board.getc(1, 3).ublk + ); + } + }, + { + label: "Input aux marks", + input: [ + "newboard,3,3", + "mouse,left,1,3", + "mouse,right,3,3", + "mouse,right,5,1,5,3" + ], + result: + "pzprv3/wittgen/3/3/. . . /. . . /. . . /0 0 1 /4 1 1 /0 0 0 /0 0 /0 0 /0 0 /0 0 0 /0 0 0 /" + }, + { + label: "Remove aux marks", + input: ["mouse,left,1,3,3,3", "mouse,left,1,3"], + result: + "pzprv3/wittgen/3/3/. . . /. . . /. . . /0 0 1 /2 0 1 /0 0 0 /0 0 /1 0 /0 0 /0 0 0 /0 0 0 /" + }, + { + label: "Stop corners", + input: ["mouse,left,3,5,5,5,5,1"], + result: + "pzprv3/wittgen/3/3/. . . /. . . /. . . /0 0 0 /2 0 0 /0 0 0 /0 0 /1 0 /0 1 /0 0 1 /0 0 0 /" + }, + { + label: "Auto-close on 3", + input: ["newboard,6,1", "mouse,left,1,1,11,1"], + result: "pzprv3/wittgen/1/6/. . . . . . /2 0 2 2 0 2 /1 1 0 1 1 /" + }, + { + label: "Erase lines", + input: ["mouse,left,3,1,9,1", "playmode,objblank", "mouse,left,5,1,7,1"], + result: "pzprv3/wittgen/1/6/. . . . . . /0 0 1 1 0 0 /1 0 0 0 1 /" + }, + { + label: "Cycle aux mark", + input: ["playmode,auto", "setconfig,use,2", "mouse,right,5,1"], + result: "pzprv3/wittgen/1/6/. . . . . . /0 0 4 1 0 0 /1 0 0 0 1 /" + }, + { + label: "Erase lines vertical", + input: [ + "newboard,1,6", + "mouse,left,1,1,1,11", + "mouse,left,1,1,1,3", + "mouse,left,1,9,1,11" + ], + result: + "pzprv3/wittgen/6/1/. /. /. /. /. /. /0 /0 /0 /0 /0 /0 ///////0 /1 /0 /1 /0 /" + } + ] +});