diff --git a/src-ui/changes.html b/src-ui/changes.html index 65e182ba7..36ff2dd2a 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/seiza.png b/src-ui/img/seiza.png new file mode 100644 index 000000000..5e7a77931 Binary files /dev/null and b/src-ui/img/seiza.png differ diff --git a/src-ui/js/ui/KeyPopup.js b/src-ui/js/ui/KeyPopup.js index 7403eff68..4fa6d299e 100644 --- a/src-ui/js/ui/KeyPopup.js +++ b/src-ui/js/ui/KeyPopup.js @@ -265,7 +265,8 @@ ui.keypopup = { landmeasure: [10, 0], elasticlink: [10, 0], slovak: [136, 10], - gravel: [120, 0] + gravel: [120, 0], + seiza: [4, 0] }, //--------------------------------------------------------------------------- diff --git a/src-ui/js/ui/Misc.js b/src-ui/js/ui/Misc.js index 3a2d700b1..58db7f5dd 100755 --- a/src-ui/js/ui/Misc.js +++ b/src-ui/js/ui/Misc.js @@ -220,6 +220,7 @@ function toBGimage(pid) { "sashikazune", "satogaeri", "scrin", + "seiza", "sendai", "simplegako", "simpleloop", diff --git a/src-ui/list.html b/src-ui/list.html index 359d23a9c..04ff9d81f 100644 --- a/src-ui/list.html +++ b/src-ui/list.html @@ -263,6 +263,7 @@

パズルの種類のリスト
  • +
  • diff --git a/src/pzpr/variety.js b/src/pzpr/variety.js index a0ae91d5e..a4270942e 100755 --- a/src/pzpr/variety.js +++ b/src/pzpr/variety.js @@ -419,6 +419,7 @@ ], scrabble: [0, 0, "Scrabble", "Scrabble"], scrin: [0, 0, "スクリン", "Scrin"], + seiza: [0, 0, "星座になれたら", "Seiza"], sendai: [0, 0, "宮城県仙台市", "Sendai-Miyagi"], shakashaka: [0, 1, "シャカシャカ", "Shakashaka"], shikaku: [0, 1, "四角に切れ", "Shikaku", "shikaku"], diff --git a/src/res/failcode.en.json b/src/res/failcode.en.json index 6ad1e0b5e..f78f90fe9 100644 --- a/src/res/failcode.en.json +++ b/src/res/failcode.en.json @@ -338,6 +338,8 @@ "bkSizeNe": "The size of the block is not equal to the number.", "bkSizeNe5.hebi": "The size of a snake is not five.", "bkSmallOnBig.ripple": "There is a smaller number on top of a bigger number in a room.", + "bkStarGt.seiza": "A region has more than one star.", + "bkStarLt.seiza": "A region does not have a star.", "bkStarGt.starbattle": "The number of stars in an area is too large.", "bkStarLt.starbattle": "The number of stars in an area is too small.", "bkSubdivided.oneroom": "A room is divided internally by shaded cells.", @@ -566,6 +568,7 @@ "kitamakura.shugaku": "There is a futon that faces down.", "laCurve.herugolf": "A ball curves halfway.", "laCurve.kaidan": "Two rectangles overlap.", + "laCurve.seiza": "A line turns outside of a star.", "laCurve": "A line has curve.", "laIsolate.bonsan": "A line doesn't connect any circle.", "laIsolate.herugolf": "A line doesn't connect any ball.", @@ -609,6 +612,7 @@ "lcCurveNe0.bwloop": "Two equal pearls aren't connected by a straight line.", "lcCurveNe1.bwloop": "Two different pearls don't have exactly one turn between them.", "lcDeadEnd": "There is a dead-end line.", + "lcDivided.seiza": "Not all stars are connected.", "lcDivided.tjunction": "Not all T-junctions are connected.", "lcDivided": "All lines and numbers are not connected to each other.", "lcGrayGt.coffeemilk": "A group has more than one gray circle.", @@ -645,6 +649,7 @@ "lnAdjacent.tontti": "Identical line shapes are connected.", "lnBranch.energywalk": "There is a branch line outside of an energy cell.", "lnBranch.forestwalk": "There is a branch line outside of a forest cell.", + "lnBranch.seiza": "There is a branch line outside of a star.", "lnBranch": "There is a branch line.", "lnConsecutive.kaidan": "Two adjacent rectangles don't have a size difference of 1.", "lnCross": "There is a crossing line.", @@ -837,6 +842,7 @@ "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.", + "nmLineNe.seiza": "A number is not equal to the amount of lines connected to its star.", "nmLineNe.slither": "The number is not equal to the number of lines around it.", "nmLoop.snakepit": "A snake has no head or tail.", "nmLt1.lapaz": "A number is not contained in a 1x2 region.", @@ -856,6 +862,7 @@ "nmNoLine.firefly": "There is a lonely firefly.", "nmNoLine.ichimaga": "A circle doesn't start any line.", "nmNoLine.kusabi": "A circle is not connected to another object.", + "nmNoLine.seiza": "A star is not connected to another star.", "nmNoLine.wblink": "A circle doesn't start any line.", "nmNoLine": "A number is not connected to another number.", "nmNoMove.bonsan": "A circle doesn't move.", @@ -1000,7 +1007,7 @@ "slLoopGiri.gokigen": "There is a loop that consists '切'.", "slNotLoopWa.gokigen": "There is not a loop that consists '輪'.", "snakeAttack.hebi": "A snake can see another snake.", - "starAround.starbattle": "Some stars touch.", + "starAround": "Some stars touch.", "stInvalid.icebarn": "System can't detect start position.", "stLineNe2.slalom": "Start/goal circle doesn't have two lines.", "stNoLine.icebarn": "The line doesn't go through the 'IN' arrow.", diff --git a/src/res/failcode.ja.json b/src/res/failcode.ja.json index c01be284f..360f39088 100644 --- a/src/res/failcode.ja.json +++ b/src/res/failcode.ja.json @@ -624,7 +624,7 @@ "slLoopGiri.gokigen": "'切'が含まれた線が輪っかになっています。", "slNotLoopWa.gokigen": "'輪'が含まれた線が輪っかになっていません。", "snakeAttack.hebi": "蛇の視線の先に別の蛇がいます。", - "starAround.starbattle": "星がタテヨコナナメに隣接しています。", + "starAround": "星がタテヨコナナメに隣接しています。", "stInvalid.icebarn": "スタート位置を特定できませんでした。", "stLineNe2.slalom": "○から線が2本出ていません。", "stNoLine.icebarn": "INに線が通っていません。", diff --git a/src/variety/seiza.js b/src/variety/seiza.js new file mode 100644 index 000000000..80b12cafe --- /dev/null +++ b/src/variety/seiza.js @@ -0,0 +1,296 @@ +(function(pidlist, classbase) { + if (typeof module === "object" && module.exports) { + module.exports = [pidlist, classbase]; + } else { + pzpr.classmgr.makeCustom(pidlist, classbase); + } +})(["seiza"], { + MouseEvent: { + inputModes: { + edit: ["empty", "border", "number"], + play: ["star", "unshade", "peke", "line"] + }, + mouseinputAutoPlay: function() { + if (this.mousestart || this.mousemove) { + if (this.btn === "left") { + this.inputLine(); + } else if (this.btn === "right") { + if (this.mousestart && this.inputpeke_ifborder()) { + return; + } + if (!this.firstCell.isnull || this.notInputted()) { + this.inputcell(); + } + } + } else if (this.mouseend && this.notInputted()) { + var cell = this.getcell(); + if (!this.firstCell.isnull && cell !== this.firstCell) { + return; + } + this.inputcell(); + } + }, + mouseinputAutoEdit: function() { + if (this.mousestart || this.mousemove) { + this.inputborder(); + } else if (this.mouseend && this.notInputted()) { + this.inputqnum(); + } + } + }, + KeyEvent: { + enablemake: true, + keyinput: function(ca) { + if (ca === "q") { + var cell = this.cursor.getc(); + if (!cell.isnull) { + cell.setValid(cell.ques !== 7 ? 7 : 0); + cell.draw(); + } + } else { + this.key_inputqnum(ca); + } + } + }, + + Cell: { + maxnum: 4, + isLineShapeEndpoint: function() { + return this.qans === 1; + }, + noLP: function(dir) { + return this.isEmpty(); + }, + prehook: { + qans: function(num) { + return num && this.isEmpty(); + }, + qsub: function(num) { + return num && this.isEmpty(); + } + }, + posthook: { + ques: function() { + if (!this.ques) { + return; + } + this.setQans(0); + this.setQsub(0); + for (var dir in this.adjborder) { + this.adjborder[dir].removeLine(); + } + } + } + }, + Border: { + enableLineNG: true, + isBorder: function() { + return ( + this.isnull || + this.ques || + this.sidecell[0].isEmpty() || + this.sidecell[1].isEmpty() + ); + } + }, + Board: { + hasborder: 1 + }, + LineGraph: { + enabled: true, + makeClist: true + }, + AreaRoomGraph: { + enabled: true, + hastop: true + }, + + //--------------------------------------------------------- + // 画像表示系 + Graphic: { + irowake: true, + gridcolor_type: "LIGHT", + textoption: { ratio: 0.45, position: 5 } /* TOPLEFT */, + numbercolor_func: "fixed", + + paint: function() { + this.drawBGCells(); + this.drawGrid(); + this.drawQuesCells(); + this.drawQuesNumbers(); + + this.drawDotCells(); + this.drawLines(); + this.drawStars(); + this.drawPekes(); + + this.drawBorders(); + + this.drawChassis(); + this.drawTarget(); + }, + getQuesCellColor: function(cell) { + return cell.isEmpty() ? "black" : null; + }, + + drawStars: function() { + var g = this.vinc("cell_star", "auto", true); + var clist = this.range.cells; + for (var i = 0; i < clist.length; i++) { + var cell = clist[i]; + g.vid = "c_star_" + cell.id; + if (cell.qans === 1) { + g.fillStyle = !cell.trial ? this.qanscolor : this.trialcolor; + this.fillStar( + g, + cell.bx * this.bw, + cell.by * this.bh, + this.bw * 0.8, + this.bh * 0.8 + ); + } else { + g.vhide(); + } + } + } + }, + + //--------------------------------------------------------- + // URLエンコード/デコード処理 + Encode: { + decodePzpr: function(type) { + this.decodeBorder(); + this.decodeEmpty(); + this.decodeRoomNumber16(); + }, + encodePzpr: function(type) { + this.encodeBorder(); + this.encodeEmpty(); + this.encodeRoomNumber16(); + }, + encodeBorder_makaro: function() { + /* 同じ見た目のパズルにおけるURLを同じにするため、 */ + /* 一時的にborder.ques=1にしてURLを出力してから元に戻します */ + var bd = this.board, + sv_ques = []; + for (var id = 0; id < bd.border.length; id++) { + sv_ques[id] = bd.border[id].ques; + bd.border[id].ques = bd.border[id].isBorder() ? 1 : 0; + } + + this.encodeBorder(); + + for (var id = 0; id < bd.border.length; id++) { + bd.border[id].ques = sv_ques[id]; + } + } + }, + FileIO: { + decodeData: function() { + this.decodeCell(function(cell, ca) { + if (ca === "*") { + cell.ques = 7; + } else if (ca === "-") { + cell.qnum = -2; + } else if (ca !== ".") { + cell.qnum = +ca; + } + }); + this.decodeBorderQues(); + this.decodeBorderLine(); + this.decodeCellAns(); + }, + encodeData: function() { + this.encodeCell(function(cell) { + if (cell.ques) { + return "* "; + } else if (cell.qnum === -2) { + return "- "; + } else if (cell.qnum > 0) { + return cell.qnum + " "; + } else { + return ". "; + } + }); + this.encodeBorderQues(); + this.encodeBorderLine(); + this.encodeCellAns(); + } + }, + AnsCheck: { + checklist: [ + "checkAroundStars", + "checkCrossLine", + "checkCurveLine", + "checkOverSaturatedStars", + "checkOutgoingLine", + "checkLineShapeDeadend", + "checkNoLineObject", + "checkInsufficientStars", + "checkConnectAllNumber" + ], + checkLineShapeDeadend: function() { + this.checkAllCell(function(cell) { + return !cell.qans && cell.lcnt === 1; + }, "lcDeadEnd"); + }, + checkCrossLine: function() { + this.checkAllCell(function(cell) { + return !cell.qans && cell.lcnt > 2; + }, "lnBranch"); + }, + checkCurveLine: function() { + this.checkAllCell(function(cell) { + return !cell.qans && cell.isLineCurve(); + }, "laCurve"); + }, + checkAroundStars: function() { + this.checkAroundCell(function(cell1, cell2) { + return cell1.qans === 1 && cell2.qans === 1; + }, "starAround"); + }, + checkOverSaturatedStars: function() { + var bd = this.board; + this.checkAllBlock( + bd.roommgr, + function(cell) { + return cell.qans === 1; + }, + function(w, h, a, n) { + return a <= 1; + }, + "bkStarGt" + ); + }, + checkInsufficientStars: function() { + var bd = this.board; + this.checkAllBlock( + bd.roommgr, + function(cell) { + return cell.qans === 1; + }, + function(w, h, a, n) { + return a >= 1; + }, + "bkStarLt" + ); + }, + checkNoLineObject: function() { + this.checkAllCell(function(cell) { + return cell.lcnt === 0 && cell.qans; + }, "nmNoLine"); + }, + checkOutgoingLine: function() { + this.checkAllCell(function(cell) { + if (!cell.qans || !cell.room) { + return false; + } + if (cell.room.top.isValidNum() && cell.room.top.qnum !== cell.lcnt) { + cell.room.clist.seterr(1); + return true; + } + return false; + }, "nmLineNe"); + } + } +}); diff --git a/test/script/seiza.js b/test/script/seiza.js new file mode 100644 index 000000000..30cbdfd12 --- /dev/null +++ b/test/script/seiza.js @@ -0,0 +1,47 @@ +/* seiza.js */ + +ui.debug.addDebugData("seiza", { + url: "5/5/o1ag8f0v08000i3h", + failcheck: [ + [ + "starAround", + "pzprv3/seiza/5/5/. . . . . /. * . . . /. . 3 . . /. . . . . /. . . . . /1 1 0 0 /0 0 0 0 /0 1 0 1 /0 1 0 1 /0 0 0 0 /0 1 0 0 0 /0 1 1 1 1 /0 0 0 0 0 /1 1 1 1 1 /0 1 1 1 /0 0 0 0 /0 0 0 0 /1 1 1 1 /0 0 0 0 /0 0 0 0 1 /0 0 0 0 1 /0 0 0 0 1 /0 0 1 0 0 /. # . . # /. . . . . /. . . . . /# . # . # /. . # . . /" + ], + [ + "lnBranch", + "pzprv3/seiza/5/5/. . . . . /. * . . . /. . 3 . . /. . . . . /. . . . . /1 1 0 0 /0 0 0 0 /0 1 0 1 /0 1 0 1 /0 0 0 0 /0 1 0 0 0 /0 1 1 1 1 /0 0 0 0 0 /1 1 1 1 1 /0 1 1 1 /0 0 0 0 /1 1 1 1 /0 0 0 0 /0 0 0 0 /0 0 1 0 0 /0 0 1 0 0 /1 0 0 0 0 /1 0 0 0 0 /. # . . # /. . . . . /# . # . # /. . . . . /# . . . . /" + ], + [ + "laCurve", + "pzprv3/seiza/5/5/. . . . . /. * . . . /. . 3 . . /. . . . . /. . . . . /1 1 0 0 /0 0 0 0 /0 1 0 1 /0 1 0 1 /0 0 0 0 /0 1 0 0 0 /0 1 1 1 1 /0 0 0 0 0 /1 1 1 1 1 /0 1 1 1 /0 0 0 0 /1 1 1 1 /0 0 0 0 /0 0 1 0 /0 0 0 0 1 /0 0 0 0 1 /0 0 1 0 0 /0 0 1 0 0 /. # . . # /. . . . . /# . # . # /. . . . . /. . . # . /" + ], + [ + "bkStarGt", + "pzprv3/seiza/5/5/. . . . . /. * . . . /. . 3 . . /. . . . . /. . . . . /1 1 0 0 /0 0 0 0 /0 1 0 1 /0 1 0 1 /0 0 0 0 /0 1 0 0 0 /0 1 1 1 1 /0 0 0 0 0 /1 1 1 1 1 /0 1 1 1 /0 0 0 0 /1 1 1 1 /0 0 0 0 /0 0 1 1 /0 0 0 0 1 /0 0 0 0 1 /0 0 1 0 0 /0 0 1 0 0 /. # . . # /. . . . . /# . # . # /. . . . . /. . # . # /" + ], + [ + "nmLineNe", + "pzprv3/seiza/5/5/. . . . . /. * . . . /. . 3 . . /. . . . . /. . . . . /1 1 0 0 /0 0 0 0 /0 1 0 1 /0 1 0 1 /0 0 0 0 /0 1 0 0 0 /0 1 1 1 1 /0 0 0 0 0 /1 1 1 1 1 /0 1 1 1 /0 0 0 0 /1 1 1 1 /0 0 0 0 /0 0 0 0 /0 0 0 0 1 /0 0 0 0 1 /1 0 0 0 0 /1 0 0 0 0 /. # . . # /. . . . . /# . # . # /. . . . . /# . . . . /" + ], + [ + "lcDeadEnd", + "pzprv3/seiza/5/5/. . . . . /. * . . . /. . 3 . . /. . . . . /. . . . . /1 1 0 0 /0 0 0 0 /0 1 0 1 /0 1 0 1 /0 0 0 0 /0 1 0 0 0 /0 1 1 1 1 /0 0 0 0 0 /1 1 1 1 1 /0 1 1 1 /0 0 0 0 /1 1 1 1 /0 0 0 0 /0 0 0 0 /0 0 0 0 1 /0 0 0 0 1 /0 0 1 0 1 /0 0 0 0 1 /. # . . # /. . . . . /# . # . # /. . . . . /. . . . # /" + ], + [ + "nmNoLine", + "pzprv3/seiza/5/5/. . . . . /. * . . . /. . 3 . . /. . . . . /. . . . . /1 1 0 0 /0 0 0 0 /0 1 0 1 /0 1 0 1 /0 0 0 0 /0 1 0 0 0 /0 1 1 1 1 /0 0 0 0 0 /1 1 1 1 1 /0 0 0 0 /0 0 0 0 /1 1 1 1 /0 0 0 0 /0 0 0 0 /0 0 0 0 1 /0 0 0 0 1 /0 0 1 0 0 /0 0 1 0 0 /. # . . # /. . . . . /# . # . # /. . . . . /. . # . . /" + ], + [ + "bkStarLt", + "pzprv3/seiza/5/5/. . . . . /. * . . . /. . 3 . . /. . . . . /. . . . . /1 1 0 0 /0 0 0 0 /0 1 0 1 /0 1 0 1 /0 0 0 0 /0 1 0 0 0 /0 1 1 1 1 /0 0 0 0 0 /1 1 1 1 1 /0 0 0 0 /0 0 0 0 /0 0 0 0 /1 1 1 1 /0 0 0 0 /0 0 1 0 0 /0 0 1 0 0 /0 0 1 0 0 /0 0 0 0 0 /. . # . . /. . . . . /. . . . . /# . # . # /. . . . . /" + ], + [ + "lcDivided", + "pzprv3/seiza/5/5/. . . . . /. * . . . /. . 3 . . /. . . . . /. . . . . /1 1 0 0 /0 0 0 0 /0 1 0 1 /0 1 0 1 /0 0 0 0 /0 1 0 0 0 /0 1 1 1 1 /0 0 0 0 0 /1 1 1 1 1 /0 1 1 1 /0 0 0 0 /1 1 1 1 /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 1 0 0 /. # . . # /. . . . . /# . # . # /. . . . . /. . # . . /" + ], + [ + null, + "pzprv3/seiza/5/5/. . . . . /. * . . . /. . 3 . . /. . . . . /. . . . . /1 1 0 0 /0 0 0 0 /0 1 0 1 /0 1 0 1 /0 0 0 0 /0 1 0 0 0 /0 1 1 1 1 /0 0 0 0 0 /1 1 1 1 1 /0 1 1 1 /0 0 0 0 /1 1 1 1 /0 0 0 0 /0 0 0 0 /0 0 0 0 1 /0 0 0 0 1 /0 0 1 0 0 /0 0 1 0 0 /. # . . # /. . . . . /# . # . # /. . . . . /. . # . . /" + ] + ] +});