diff --git a/src-ui/changes.html b/src-ui/changes.html index 1c2836c86..9a1b311d0 100644 --- a/src-ui/changes.html +++ b/src-ui/changes.html @@ -33,13 +33,13 @@
Latest types (all types)
diff --git a/src-ui/js/ui/KeyPopup.js b/src-ui/js/ui/KeyPopup.js index 389c0d0fd..eac9b777d 100644 --- a/src-ui/js/ui/KeyPopup.js +++ b/src-ui/js/ui/KeyPopup.js @@ -231,6 +231,7 @@ ui.keypopup = { wataridori: [10, 0], kurarin: [133, 0], narrow: [134, 0], + blindrush: [10, 0], isowatari: [10, 0], uturns: [133, 0], distopia: [10, 0], @@ -485,29 +486,8 @@ ui.keypopup = { text: "■", color: "rgb(204,204,204)" }; - } else if ( - pid === "kurotto" || - pid === "bonsan" || - pid === "satogaeri" || - pid === "heyabon" || - pid === "yosenabe" || - pid === "herugolf" || - pid === "kazunori" || - pid === "nurimisaki" || - pid === "amibo" || - pid === "firefly" || - pid === "shikaku" || - pid === "aho" || - pid === "bosanowa" || - pid === "portal" || - pid === "minarism" || - pid === "mintonette" || - pid === "onsen" || - pid === "wataridori" - ) { - cap = "○"; - } else if (!ui.puzzle.painter.hideHatena) { - cap = "?"; + } else { + cap = ui.puzzle.painter.hideHatena ? "○" : "?"; } if (cap !== null) { itemlist.push(["-", cap]); diff --git a/src-ui/list.html b/src-ui/list.html index 030da8f71..317d9a2de 100644 --- a/src-ui/list.html +++ b/src-ui/list.html @@ -253,6 +253,7 @@

パズルの種類のリスト
  • +
  • diff --git a/src/pzpr/variety.js b/src/pzpr/variety.js index b7120f392..750f4b606 100755 --- a/src/pzpr/variety.js +++ b/src/pzpr/variety.js @@ -106,6 +106,7 @@ battleship: [0, 0, "Battleship", "Battleship", "statuepark"], bdblock: [1, 0, "ボーダーブロック", "Border Block"], bdwalk: [0, 0, "ビルウォーク", "Building Walk", "haisu"], + blindrush: [0, 0, "猪突猛進", "Blind Rush"], bonsan: [1, 0, "ぼんさん", "Bonsan", "bonsan"], bosanowa: [1, 0, "ボサノワ", "Bosanowa", "", { alias: "bossanova" }], bosnianroad: [0, 0, "Bosnian Road", "Bosnian Road"], diff --git a/src/res/failcode.en.json b/src/res/failcode.en.json index 8317cb387..c1809908c 100644 --- a/src/res/failcode.en.json +++ b/src/res/failcode.en.json @@ -71,6 +71,8 @@ "bdNotChassis.shwolf": "A line doesn't connect to the chassis.", "bdPassStar.nuriuzu": "A star overlaps a shaded cell.", "bdPassStar.tentaisho": "A line goes over a star.", + "bdPierceGt1.blindrush": "A network of walls is pierced more than once.", + "bdPierceLt1.blindrush": "A network of walls is not pierced by a line.", "bdUnequal.antmill": "A cross clue does not overlap exactly 1 shaded cell.", "bdUnused.fillomino": "A given border does not divide two regions.", "bdUnused.kissing": "A bar is not adjacent to two different blocks.", @@ -519,6 +521,7 @@ "laIsolate.rectslider": "A line doesn't connect any shaded cell.", "laIsolate.yosenabe": "A line doesn't connect any filling.", "laIsolate": "A line doesn't connect to any letter.", + "laLenNe.blindrush": "A number doesn't go through the correct amount of walls.", "laLenNe.herugolf": "A ball stops halfway.", "laLenNe": "The length of a line is wrong.", "laLoop": "A line forms a loop.", @@ -536,6 +539,7 @@ "laOnNum": "A line goes through a letter.", "laShadeOnBorder.oyakodori": "A black bird goes over a border.", "laUnshadeNoBorder.oyakodori": "A white bird does not go over a border.", + "laWallStop.blindrush": "A circle does not stop at a wall.", "laWaterHazard.herugolf": "A ball lands into the water.", "lbDivide.amibo": "The bars are not connected.", "lbIsolate.walllogic": "A line doesn't connect to any number.", @@ -774,8 +778,8 @@ "nmNoLine.kusabi": "A circle is not connected to another object.", "nmNoLine.wblink": "A circle doesn't start any line.", "nmNoLine": "A number is not connected to another number.", - "nmNoMove.bonsan": "A circle doesn't start any line.", - "nmNoMove.rectslider": "A shaded cell doesn't start any line.", + "nmNoMove.bonsan": "A circle doesn't move.", + "nmNoMove.rectslider": "A shaded cell doesn't move.", "nmNoOrbit.orbital": "A black circle is not inside a loop.", "nmNoSequence.numcity": "A city does not contain one district of every number from 1 to N.", "nmNoSideShade.tasquare": "No shaded cells are adjacent to square marks.", diff --git a/src/variety/blindrush.js b/src/variety/blindrush.js new file mode 100644 index 000000000..d05db91d0 --- /dev/null +++ b/src/variety/blindrush.js @@ -0,0 +1,371 @@ +// +// パズル固有スクリプト部 ぼんさん・へやぼん・四角スライダー版 bonsan.js +// +(function(pidlist, classbase) { + if (typeof module === "object" && module.exports) { + module.exports = [pidlist, classbase]; + } else { + pzpr.classmgr.makeCustom(pidlist, classbase); + } +})(["blindrush"], { + //--------------------------------------------------------- + MouseEvent: { + inputModes: { + edit: ["number", "clear"], + play: ["line", "peke", "clear", "completion"] + }, + + mouseinput_auto: function() { + if (this.puzzle.playmode) { + this.mouseinputAutoPlay_line(); + if (this.mouseend && this.notInputted()) { + this.inputqcmp(); + } + } else if (this.puzzle.editmode) { + if (this.mousestart || this.mousemove) { + this.inputborder(); + } else if (this.mouseend && this.notInputted()) { + this.inputqnum(); + } + } + }, + + inputqcmp: function() { + var cell = this.getcell(); + if (cell.isnull) { + return false; + } + + var targetcell = !this.puzzle.execConfig("dispmove") ? cell : cell.base; + if (targetcell.isNum()) { + if (this.inputData === null) { + this.inputData = targetcell.qcmp !== 1 ? 21 : 20; + } + + targetcell.setQcmp(this.inputData === 21 ? 1 : 0); + cell.draw(); + this.mouseCell = cell; + return true; + } + this.mouseCell = cell; + return false; + } + }, + //--------------------------------------------------------- + // キーボード入力系 + KeyEvent: { + enablemake: true + }, + + //--------------------------------------------------------- + // 盤面管理系 + Cell: { + isCmp: function() { + return this.isCmp_blindrush( + this.puzzle.execConfig("autocmp"), + this.puzzle.execConfig("dispmove"), + false + ); + }, + + getBurstCount: function() { + if (!this.path) { + return 0; + } + var borders = this.path.getedgeobjs(); + var count = 0; + for (var i = 0; i < borders.length; i++) { + if (i > 0 && borders[i].isvert !== borders[i - 1].isvert) { + return -1; + } + if (borders[i].isBorder()) { + count++; + } + } + return count; + }, + + isStoppedAtWall: function() { + if ( + !this.path || + !this.path.destination || + this.path.destination.isnull + ) { + return false; + } + var borders = this.path.destination.adjborder; + if (borders.left.isLine()) { + return borders.right.isnull || borders.right.isBorder(); + } else if (borders.right.isLine()) { + return borders.left.isnull || borders.left.isBorder(); + } else if (borders.top.isLine()) { + return borders.bottom.isnull || borders.bottom.isBorder(); + } else if (borders.bottom.isLine()) { + return borders.top.isnull || borders.top.isBorder(); + } + return false; + }, + + isCmp_blindrush: function(is_autocmp, is_dispmove) { + var targetcell = !is_dispmove ? this : this.base; + if (targetcell.qcmp === 1) { + return true; + } else if (!is_autocmp) { + return false; + } + + if (!this.isStoppedAtWall()) { + return false; + } + + var burst = this.getBurstCount(); + return burst >= 0 && targetcell.getNum() === burst; + }, + + maxnum: function() { + var bd = this.board, + bx = this.bx, + by = this.by; + var col = (bx < bd.maxbx >> 1 ? bd.maxbx - bx : bx) >> 1; + var row = (by < bd.maxby >> 1 ? bd.maxby - by : by) >> 1; + return Math.max(col, row); + }, + minnum: 0 + }, + Border: { + prehook: { + line: function(num) { + return this.puzzle.execConfig("dispmove") && this.checkFormCurve(num); + } + } + }, + "BorderGraph:AreaGraphBase": { + enabled: true, + pointgroup: "border", + relation: { "border.ques": "node" }, + + setComponentRefs: function(obj, component) { + obj.bdarea = component; + }, + getObjNodeList: function(nodeobj) { + return nodeobj.bdareanodes; + }, + resetObjNodeList: function(nodeobj) { + nodeobj.bdareanodes = []; + }, + + isnodevalid: function(nodeobj) { + return nodeobj.isBorder(); + }, + + getSideObjByNodeObj: function(border) { + var borders = [ + border.relbd(-1, -1), + border.relbd(-1, 1), + border.relbd(1, -1), + border.relbd(1, 1) + ]; + if (border.isvert) { + borders.push(border.relbd(0, -2)); + borders.push(border.relbd(0, 2)); + } else { + borders.push(border.relbd(-2, 0)); + borders.push(border.relbd(2, 0)); + } + + return borders.filter(function(b) { + return !b.isnull; + }); + } + }, + + Board: { + cols: 8, + rows: 8, + + hasborder: 1, + + addExtraInfo: function() { + this.bordergraph = this.addInfoList(this.klass.BorderGraph); + } + }, + + LineGraph: { + enabled: true, + moveline: true + }, + //--------------------------------------------------------- + // 画像表示系 + Graphic: { + autocmp: "number", + hideHatena: true, + + gridcolor_type: "LIGHT", + + numbercolor_func: "move", + + circlefillcolor_func: "qcmp", + + paint: function() { + this.drawBGCells(); + this.drawGrid(); + this.drawBorders(); + + this.drawTip(); + this.drawDepartures(); + this.drawLines(); + + this.drawCircledNumbers(); + + this.drawChassis(); + this.drawPekes(); + + this.drawTarget(); + }, + + getLineColor: function(border) { + if (border.isLine() && border.error === 2) { + return this.noerrcolor; + } + return this.common.getLineColor.call(this, border); + }, + + getBorderColor: function(border) { + if (border.ques) { + return border.error === 2 ? this.errcolor1 : this.quescolor; + } + return null; + } + }, + + //--------------------------------------------------------- + // URLエンコード/デコード処理 + Encode: { + decodePzpr: function(type) { + this.decodeBorder(); + this.decodeNumber16(); + }, + encodePzpr: function(type) { + this.encodeBorder(); + this.encodeNumber16(); + } + }, + //--------------------------------------------------------- + FileIO: { + decodeData: function() { + this.decodeCellQnum(); + this.decodeBorderQues(); + this.decodeCellAnumsub(); + this.decodeBorderLine(); + }, + encodeData: function() { + this.encodeCellQnum(); + this.encodeBorderQues(); + this.encodeCellAnumsub(); + this.encodeBorderLine(); + } + }, + + //--------------------------------------------------------- + // 正解判定処理実行部 + AnsCheck: { + checklist: [ + "checkLineExist+", + "checkBranchLine", + "checkCrossLine", + + "checkConnectObject", + "checkLineOverLetter", + "checkCurveLine", + + "checkBurstCount", + "checkRestingPosition", + + "checkPierceMultiple", + "checkPierceNone", + + "checkNoMoveCircle", + "checkDisconnectLine" + ], + + movementCheck: function(func, code) { + for (var c = 0; c < this.board.cell.length; c++) { + var cell = this.board.cell[c]; + if (!cell.isNum() || !cell.path || cell.path.destination === cell) { + continue; + } + if (!func(cell)) { + continue; + } + + this.failcode.add(code); + if (this.checkOnly) { + break; + } + cell.path.clist.seterr(1); + } + }, + + checkBurstCount: function() { + this.movementCheck(function(cell) { + return cell.isValidNum() && cell.getBurstCount() !== cell.getNum(); + }, "laLenNe"); + }, + + checkRestingPosition: function() { + this.movementCheck(function(cell) { + return !cell.isStoppedAtWall(); + }, "laWallStop"); + }, + + pierceCheck: function(flag, code) { + var walls = this.board.bordergraph.components; + for (var id = 0; id < walls.length; id++) { + var wall = walls[id]; + var count = wall.clist.filter(function(border) { + return border.isLine(); + }).length; + + if ((count > 0 && flag === 0) || (count <= 1 && flag > 0)) { + continue; + } + + this.failcode.add(code); + if (this.checkOnly) { + break; + } + this.board.border.setnoerr(); + wall.clist.seterr(2); + } + }, + + checkPierceNone: function() { + this.pierceCheck(0, "bdPierceLt1"); + }, + + checkPierceMultiple: function() { + this.pierceCheck(1, "bdPierceGt1"); + }, + + checkCurveLine: function() { + this.checkAllArea( + this.board.linegraph, + function(w, h, a, n) { + return w === 1 || h === 1; + }, + "laCurve" + ); + }, + checkNoMoveCircle: function() { + this.checkAllCell(function(cell) { + return cell.isNum() && cell.lcnt === 0; + }, "nmNoMove"); + } + }, + FailCode: { + nmNoMove: "nmNoMove.bonsan", + laIsolate: "laIsolate.bonsan", + nmConnected: "nmConnected.bonsan", + laOnNum: "laOnNum.bonsan" + } +}); diff --git a/src/variety/yosenabe.js b/src/variety/yosenabe.js index 80aa56cea..564bc6708 100644 --- a/src/variety/yosenabe.js +++ b/src/variety/yosenabe.js @@ -1211,6 +1211,8 @@ } }, "FailCode@brownies": { + nmNoMove: "nmNoMove.bonsan", + laIsolate: "laIsolate.bonsan", nmConnected: "nmConnected.bonsan", laOnNum: "laOnNum.bonsan" } diff --git a/test/script/blindrush.js b/test/script/blindrush.js new file mode 100644 index 000000000..bf45c1ef3 --- /dev/null +++ b/test/script/blindrush.js @@ -0,0 +1,80 @@ +/* blindrush.js */ + +ui.debug.addDebugData("blindrush", { + url: "5/5/0h0lo028.r1m2i", + failcheck: [ + [ + "brNoLine", + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . 1 . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 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 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /" + ], + [ + "lnBranch", + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . 1 . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 0 /0 1 0 0 0 /. . . . . /. . . . . /. . . . . /. . . . . /. . . . . /0 0 0 0 /0 0 0 0 /1 1 1 0 /0 0 0 0 /0 0 0 0 /1 0 0 0 0 /1 0 0 0 0 /1 0 0 0 0 /1 0 0 0 0 /" + ], + [ + "lnCross", + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . 1 . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 0 /0 1 0 0 0 /. . . . . /. . . . . /. . . . . /. . . . . /. . . . . /0 0 0 0 /0 0 0 0 /1 1 1 0 /0 0 0 0 /0 0 0 0 /0 1 0 0 0 /0 1 0 0 0 /0 1 0 0 0 /0 1 0 0 0 /" + ], + [ + "nmConnected", + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . 1 . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 0 /0 1 0 0 0 /. . . . . /. . . . . /. . . . . /. . . . . /. . . . . /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 0 0 0 0 /0 0 0 0 0 /" + ], + [ + "laOnNum", + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . 1 . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 0 /0 1 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 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /" + ], + [ + "laCurve", + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . 1 . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 0 /0 1 0 0 0 /. . . . . /. . . . . /. . . . . /. . . . . /. . . . . /0 0 0 0 /0 0 0 0 /0 0 1 0 /0 0 0 0 /0 1 1 1 /1 0 1 0 0 /1 0 1 0 0 /1 0 0 0 0 /1 0 0 0 0 /" + ], + [ + "laIsolate", + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . 1 . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 0 /0 1 0 0 0 /. . . . . /. . . . . /. . . . . /. . . . . /. . . . . /1 1 1 1 /0 0 1 1 /1 1 1 0 /0 0 0 0 /0 1 1 1 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /" + ], + [ + "laLenNe", + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . 1 . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 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 /1 0 0 0 0 /1 1 0 0 0 /1 1 0 1 0 /1 1 0 1 0 /" + ], + [ + "laWallStop", + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . 1 . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 0 /0 1 0 0 0 /. . . . . /. . . . . /. . . . . /. . . . . /. . . . . /0 0 0 0 /0 0 0 0 /0 1 1 0 /0 0 0 0 /0 1 1 1 /1 0 0 0 0 /1 0 0 0 0 /1 0 0 0 0 /1 0 0 0 0 /" + ], + [ + "nmNoMove", + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . 1 . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 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 1 0 0 0 /0 1 0 0 0 /0 1 0 1 0 /0 1 0 1 0 /" + ], + [ + "bdPierceLt1", + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . - . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 0 /0 1 0 0 0 /. . . . . /. . . . . /. . . . . /. . . . . /. . . . . /1 1 1 1 /0 0 0 0 /0 0 0 1 /0 0 0 0 /0 1 1 1 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /" + ], + [ + "bdPierceGt1", + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . 1 . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 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 /1 1 0 0 0 /1 1 0 0 0 /1 1 0 1 0 /1 1 0 1 0 /" + ], + [ + null, + "pzprv3/blindrush/5/5/- . . . . /. . . . . /. . . 1 . /. . . . . /. 2 . . . /0 0 0 0 /0 1 0 0 /0 1 0 0 /0 0 0 1 /0 1 0 1 /1 1 0 0 0 /0 0 0 0 0 /0 0 0 1 0 /0 1 0 0 0 /c . . . . /. . . . . /. . . . . /. . . . . /. . . . . /1 1 1 1 /0 0 0 0 /1 1 1 0 /0 0 0 0 /0 1 1 1 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /0 0 0 0 0 /" + ] + ], + inputs: [ + { + input: [ + "newboard,5,1", + "editmode", + "cursor,1,1", + "mouse,left,1,1", + "mouse,left,2,0,2,2" + ], + result: "pzprv3/blindrush/1/5/- . . . . /1 0 0 0 /. . . . . /0 0 0 0 /" + }, + { + input: [ + "playmode", + "mouse,left,1,1,5,1", + "mouse,left,5,1", + "mouse,left,6,1" + ], + result: "pzprv3/blindrush/1/5/- . . . . /1 0 0 0 /c . . . . /1 1 -1 0 /" + } + ] +});