diff --git a/src-ui/changes.html b/src-ui/changes.html index 12bafc355..6b8be4e15 100644 --- a/src-ui/changes.html +++ b/src-ui/changes.html @@ -33,6 +33,7 @@
Latest types (all types)
diff --git a/src-ui/img/patchwork.png b/src-ui/img/patchwork.png new file mode 100644 index 000000000..352a821cf Binary files /dev/null and b/src-ui/img/patchwork.png differ diff --git a/src-ui/js/ui/KeyPopup.js b/src-ui/js/ui/KeyPopup.js index d623ca4a4..9cf0fed8a 100644 --- a/src-ui/js/ui/KeyPopup.js +++ b/src-ui/js/ui/KeyPopup.js @@ -180,7 +180,8 @@ ui.keypopup = { maxi: [10, 0], tetrochain: [10, 0], brownies: [127, 0], - sashikazune: [10, 0] + sashikazune: [10, 0], + patchwork: [10, 0] }, //--------------------------------------------------------------------------- @@ -397,6 +398,11 @@ ui.keypopup = { cap = "□"; } else if (pid === "rectslider") { cap = "■"; + } else if (pid === "patchwork") { + cap = { + text: "■", + color: "rgb(204,204,204)" + }; } else if ( pid === "kurotto" || pid === "bonsan" || diff --git a/src-ui/js/ui/Misc.js b/src-ui/js/ui/Misc.js index 1efe9ed4a..55a6f7eb2 100755 --- a/src-ui/js/ui/Misc.js +++ b/src-ui/js/ui/Misc.js @@ -157,6 +157,7 @@ function toBGimage(pid) { "oneroom", "ovotovata", "oyakodori", + "patchwork", "pencils", "pentopia", "ququ", diff --git a/src-ui/list.html b/src-ui/list.html index 0716d98c7..67a7fe447 100644 --- a/src-ui/list.html +++ b/src-ui/list.html @@ -75,6 +75,7 @@

パズルの種類のリスト
  • +
  • diff --git a/src/pzpr/variety.js b/src/pzpr/variety.js index e43d6855a..0c7379452 100755 --- a/src/pzpr/variety.js +++ b/src/pzpr/variety.js @@ -285,6 +285,7 @@ oyakodori: [0, 0, "おやこどり", "Oyakodori", "kaero"], paintarea: [1, 0, "ペイントエリア", "Paintarea"], parquet: [0, 0, "Parquet", "Parquet"], + patchwork: [0, 0, "パッチワーク", "Patchwork"], pencils: [0, 0, "ペンシルズ", "Pencils"], pentominous: [0, 0, "Pentominous", "Pentominous", "fillomino"], pentopia: [0, 0, "Pentopia", "Pentopia", "statuepark"], diff --git a/src/res/failcode.en.json b/src/res/failcode.en.json index fc3ac1661..0ee022e1f 100644 --- a/src/res/failcode.en.json +++ b/src/res/failcode.en.json @@ -168,7 +168,7 @@ "bkNotRect": "There is a room whose shape is not a rectangle.", "bkNotRect3.shikaku": "An area whose size is not a multiple of three is not a rectangle.", "bkNotSeqNum.renban": "The numbers in the room are not consecutive.", - "bkNotSquare.squarejam": "An area is not a square.", + "bkNotSquare": "An area is not a square.", "bkNotSquare.tatamibari": "A tatami is not a square.", "bkNotSymmRoom.fillomino": "An area is not point symmetric.", "bkNotSymRoom.ayeheya": "The room is not point symmetric.", @@ -316,6 +316,7 @@ "cbSameNum.nanro": "Adjacent blocks have the same number.", "cbShade.shimaguni": "Countries in different marine areas are adjacent.", "cbShade": "Shaded cells are adjacent over a border.", + "cbUnshade": "Unshaded cells are adjacent over a border.", "ceAddLine": "A cell with given lines has extra lines.", "ceDark.lightup": "A cell is not shined.", "ceDirection.compass": "The number of cells in the direction is wrong.", diff --git a/src/res/failcode.ja.json b/src/res/failcode.ja.json index 1adcc2025..035cc3855 100644 --- a/src/res/failcode.ja.json +++ b/src/res/failcode.ja.json @@ -657,7 +657,7 @@ "nmLoop.snakepit": "スネークに端がありません。", "nmMidpoint.snakepit": "灰色のマスがスネークの端になっています。", "nmSame2x2.snakepit": "スネークが自分自身とタテヨコに接しています。", - "bkNotSquare.squarejam": "領域が正方形ではありません。", + "bkNotSquare": "領域が正方形ではありません。", "anShadeNe.yajisoko": "箱の数が正しくありません。", "bkSideNe.squarejam": "数字と領域の大きさが異なります。", "laOnNum.yajisoko": "線が箱を通り過ぎています。", diff --git a/src/variety-common/Graphic.js b/src/variety-common/Graphic.js index ab7cbafea..9d9821b71 100644 --- a/src/variety-common/Graphic.js +++ b/src/variety-common/Graphic.js @@ -1116,31 +1116,31 @@ pzpr.classmgr.makeCommon({ var LTin = cell.bx > 2, RTin = cell.bx < 2 * this.board.cols - 2; - var isUP = !UPin || adb.top.ques === 1; - var isDN = !DNin || adb.bottom.ques === 1; - var isLT = !LTin || adb.left.ques === 1; - var isRT = !RTin || adb.right.ques === 1; + var isUP = !UPin || adb.top.isBorder(); + var isDN = !DNin || adb.bottom.isBorder(); + var isLT = !LTin || adb.left.isBorder(); + var isRT = !RTin || adb.right.isBorder(); var isUL = - !UPin || - !LTin || - cell.relbd(-2, -1).ques === 1 || - cell.relbd(-1, -2).ques === 1; + isUP || + isLT || + cell.relbd(-2, -1).isBorder() || + cell.relbd(-1, -2).isBorder(); var isUR = - !UPin || - !RTin || - cell.relbd(2, -1).ques === 1 || - cell.relbd(1, -2).ques === 1; + isUP || + isRT || + cell.relbd(2, -1).isBorder() || + cell.relbd(1, -2).isBorder(); var isDL = - !DNin || - !LTin || - cell.relbd(-2, 1).ques === 1 || - cell.relbd(-1, 2).ques === 1; + isDN || + isLT || + cell.relbd(-2, 1).isBorder() || + cell.relbd(-1, 2).isBorder(); var isDR = - !DNin || - !RTin || - cell.relbd(2, 1).ques === 1 || - cell.relbd(1, 2).ques === 1; + isDN || + isRT || + cell.relbd(2, 1).isBorder() || + cell.relbd(1, 2).isBorder(); g.beginPath(); diff --git a/src/variety-common/MouseInput.js b/src/variety-common/MouseInput.js index 46a558c9e..76c95a405 100644 --- a/src/variety-common/MouseInput.js +++ b/src/variety-common/MouseInput.js @@ -64,13 +64,16 @@ pzpr.classmgr.makeCommon({ this.inputData = cell.qans !== 1 ? 1 : 0; } else if (this.inputMode === "unshade") { this.inputData = cell.qsub !== 1 ? 2 : 0; - } else if (this.puzzle.getConfig("use") === 1) { + } else if ( + this.puzzle.getConfig("use") === 1 && + this.pid !== "patchwork" + ) { if (this.btn === "left") { this.inputData = cell.qans !== 1 ? 1 : 0; } else if (this.btn === "right") { this.inputData = cell.qsub !== 1 ? 2 : 0; } - } else if (this.puzzle.getConfig("use") === 2) { + } else { if (!cell.allowShade()) { this.inputData = cell.qsub !== 1 ? 2 : 0; } else if (!cell.allowUnshade()) { diff --git a/src/variety/patchwork.js b/src/variety/patchwork.js new file mode 100644 index 000000000..866850314 --- /dev/null +++ b/src/variety/patchwork.js @@ -0,0 +1,213 @@ +// +// patchwork.js +// +(function(pidlist, classbase) { + if (typeof module === "object" && module.exports) { + module.exports = [pidlist, classbase]; + } else { + pzpr.classmgr.makeCustom(pidlist, classbase); + } +})(["patchwork"], { + //--------------------------------------------------------- + // マウス入力系 + MouseEvent: { + inputModes: { + edit: ["number", "undef", "clear"], + play: ["border", "shade", "unshade", "subline"] + }, + mouseinput_auto: function() { + if (this.puzzle.playmode) { + if (this.mousestart || this.mousemove) { + if (this.btn === "right") { + this.inputQsubLine(); + } else if (this.isBorderMode()) { + this.inputborder(); + } else { + this.inputShade(); + } + } else if (this.notInputted()) { + if (this.isBorderMode()) { + var border = this.getborder(); + if (!border.isnull) { + border.setQsub(border.qsub === 1 ? 0 : 1); + border.draw(); + } + } else if (this.btn === "right") { + this.inputShade(); + } + } + } else if (this.puzzle.editmode) { + this.inputqnum(); + } + } + }, + + //--------------------------------------------------------- + // キーボード入力系 + KeyEvent: { + enablemake: true + }, + + Cell: { + numberRemainsUnshaded: true, + minnum: 0, + maxnum: function() { + return this.board.cols * this.board.rows - 1; + } + }, + + Board: { + hasborder: 1 + }, + + AreaRoomGraph: { + enabled: true + }, + + //--------------------------------------------------------- + // 画像表示系 + + Graphic: { + hideHatena: true, + icecolor: "rgb(204,204,204)", + shadecolor: "#222222", + bordercolor_func: "qans", + + paint: function() { + this.drawBGCells(); + this.drawShadedCells(); + this.drawDashedGrid(); + + this.drawQuesNumbers(); + + this.drawBorders(); + this.drawBorderQsubs(); + + this.drawBoxBorders(false); + this.drawChassis(); + this.drawTarget(); + }, + + getBGCellColor: function(cell) { + if (cell.error === 1 || cell.qinfo === 1) { + if (cell.isNum()) { + return this.erricecolor; + } else { + return this.errbcolor1; + } + } else if (cell.isNum()) { + return this.icecolor; + } else if (cell.qsub === 1) { + return this.bcolor; + } + return null; + } + }, + + //--------------------------------------------------------- + // URLエンコード/デコード処理 + Encode: { + decodePzpr: function(type) { + this.decodeNumber16(); + }, + encodePzpr: function(type) { + this.encodeNumber16(); + } + }, + + //--------------------------------------------------------- + FileIO: { + decodeData: function() { + this.decodeCellQnumAns(); + this.decodeBorderAns(); + }, + encodeData: function() { + this.encodeCellQnumAns(); + this.encodeBorderAns(); + } + }, + + //--------------------------------------------------------- + // 正解判定処理実行部 + AnsCheck: { + checklist: [ + "checkSideAreaShadeCell", + "checkShadeCellCount", + "checkSideAreaUnshadeCell", + "checkRoomSquare", + "checkBorderDeadend+", + "doneShadingDecided" + ], + + checkShadeCellCount: function() { + var rooms = this.board.roommgr.components; + for (var r = 0; r < rooms.length; r++) { + var clist = rooms[r].clist, + d = clist.getRectSize(); + + if (d.rows !== d.cols || d.rows * d.cols !== d.cnt) { + continue; + } + + var count = clist.filter(function(cell) { + return cell.isShade(); + }).length; + + for (var i = 0; i < clist.length; i++) { + var cell = clist[i]; + var qnum = cell.qnum; + if (qnum < 0) { + continue; + } + if (qnum !== count) { + this.failcode.add("bkShadeNe"); + if (this.checkOnly) { + return; + } + clist.seterr(1); + } + } + } + }, + + checkRoomSquare: function() { + this.checkAllArea( + this.board.roommgr, + function(w, h, a, n) { + return w === h && w * h === a; + }, + "bkNotSquare" + ); + }, + + checkSideAreaShadeCell: function() { + this.checkSideAreaCell( + function(cell1, cell2) { + return ( + !cell1.isNum() && + !cell2.isNum() && + cell1.isShade() && + cell2.isShade() + ); + }, + false, + "cbShade" + ); + }, + + checkSideAreaUnshadeCell: function() { + this.checkSideAreaCell( + function(cell1, cell2) { + return ( + !cell1.isNum() && + !cell2.isNum() && + !cell1.isShade() && + !cell2.isShade() + ); + }, + false, + "cbUnshade" + ); + } + } +}); diff --git a/test/script/patchwork.js b/test/script/patchwork.js new file mode 100644 index 000000000..7a4df563c --- /dev/null +++ b/test/script/patchwork.js @@ -0,0 +1,53 @@ +/* patchwork.js */ + +ui.debug.addDebugData("patchwork", { + url: "6/6/8j3i0m.i1h.i1.h0.g1", + failcheck: [ + [ + "cbShade", + "pzprv3/patchwork/6/6/8 # # . . 3 /# # # 0 . . /# # # . . - /. . # 1 . . /- . . . 1 - /. . 0 - . 1 /0 0 1 0 0 /0 0 1 0 0 /0 0 1 0 0 /0 1 0 1 0 /0 1 0 1 0 /0 0 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /1 1 1 1 0 0 /0 0 0 0 0 0 /0 0 1 1 0 0 /" + ], + [ + "cbUnshade", + "pzprv3/patchwork/6/6/8 # # . # 3 /# # # 0 # # /# # # . . - /. . . 1 # . /- . . . 1 - /. . 0 - # 1 /0 0 1 1 0 /0 0 1 1 0 /0 0 1 0 1 /0 0 1 0 1 /0 0 1 1 0 /0 0 1 1 0 /0 0 0 1 0 0 /0 0 0 1 1 1 /1 1 1 0 0 0 /0 0 0 1 1 1 /0 0 0 1 0 0 /" + ], + [ + "bkShadeNe", + "pzprv3/patchwork/6/6/8 # # + # 3 /# # # 0 # # /# # # + + - /+ + + 1 # + /- # + # 1 - /# # 0 - # 1 /0 0 1 1 0 /0 0 1 1 0 /0 0 1 0 1 /0 0 1 0 1 /0 0 1 1 0 /0 0 1 1 0 /0 0 0 1 0 0 /0 0 0 1 1 1 /1 1 1 0 0 1 /0 0 0 1 1 1 /0 0 0 1 0 0 /" + ], + [ + "bkNotSquare", + "pzprv3/patchwork/6/6/8 # # . . 3 /# # # 0 . . /# # # . . - /. . . 1 . . /- . . . 1 - /. . 0 - . 1 /0 0 1 0 0 /0 0 1 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 /1 1 1 0 0 0 /0 0 0 0 0 0 /0 0 0 0 0 0 /" + ], + [ + "bdDeadEnd", + "pzprv3/patchwork/6/6/8 # # + # 3 /# # # 0 # # /# # # + + - /+ + + 1 # + /- + + # 1 - /+ + 0 - # 1 /0 0 1 1 0 /0 0 1 1 0 /0 0 1 0 1 /0 0 1 0 1 /0 0 1 1 0 /0 0 1 1 0 /0 0 0 1 0 0 /0 0 0 1 1 1 /1 1 1 0 1 1 /0 0 0 1 1 1 /0 0 0 1 1 0 /" + ], + [ + null, + "pzprv3/patchwork/6/6/8 # # + # 3 /# # # 0 # # /# # # + + - /+ + + 1 # + /- + + # 1 - /+ + 0 - # 1 /0 0 1 1 0 /0 0 1 1 0 /0 0 1 0 1 /0 0 1 0 1 /0 0 1 1 0 /0 0 1 1 0 /0 0 0 1 0 0 /0 0 0 1 1 1 /1 1 1 0 0 1 /0 0 0 1 1 1 /0 0 0 1 0 0 /" + ] + ], + inputs: [ + { + input: ["newboard,3,2", "editmode", "mouse,rightx2,3,1"], + result: "pzprv3/patchwork/2/3/. 5 . /. . . /0 0 /0 0 /0 0 0 /" + }, + { + input: ["playmode", "mouse,left,1,1,1,3"], + result: "pzprv3/patchwork/2/3/# 5 . /# . . /0 0 /0 0 /0 0 0 /" + }, + { + input: ["mouse,left,1.9,0,2.1,4", "mouse,right,5,2,5,1,5,3"], + result: "pzprv3/patchwork/2/3/# 5 . /# . . /1 0 /1 0 /0 0 -1 /" + }, + { + input: ["mouse,leftx2,3,3", "mouse,left,4,3"], + result: "pzprv3/patchwork/2/3/# 5 . /# + . /1 0 /1 -1 /0 0 -1 /" + }, + { + input: ["mouse,right,5,1", "mouse,left,5,2"], + result: "pzprv3/patchwork/2/3/# 5 + /# + . /1 0 /1 -1 /0 0 0 /" + } + ] +});