diff --git a/src-ui/img/tetroctb.png b/src-ui/img/tetroctb.png new file mode 100644 index 000000000..88e54a6cd Binary files /dev/null and b/src-ui/img/tetroctb.png differ diff --git a/src-ui/js/ui/KeyPopup.js b/src-ui/js/ui/KeyPopup.js index 9ff23d200..2ac20c677 100644 --- a/src-ui/js/ui/KeyPopup.js +++ b/src-ui/js/ui/KeyPopup.js @@ -247,7 +247,8 @@ ui.keypopup = { oasis: [10, 0], bhaibahan: [10, 0], heavydots: [10, 0], - marutaring: [10, 0] + marutaring: [10, 0], + tetroctb: [10, 0] }, //--------------------------------------------------------------------------- diff --git a/src-ui/js/ui/Misc.js b/src-ui/js/ui/Misc.js index c6b2c3341..d56794790 100755 --- a/src-ui/js/ui/Misc.js +++ b/src-ui/js/ui/Misc.js @@ -233,6 +233,7 @@ function toBGimage(pid) { "teri", "tetrochain", "tetrochaink", + "tetroctb", "tetrominous", "tilecity", "timebomb", diff --git a/src-ui/list.html b/src-ui/list.html index 8b454e16b..45fcbca76 100644 --- a/src-ui/list.html +++ b/src-ui/list.html @@ -100,6 +100,7 @@

パズルの種類のリスト
  • +
  • diff --git a/src/pzpr/variety.js b/src/pzpr/variety.js index c2e0cad79..21dda3d54 100755 --- a/src/pzpr/variety.js +++ b/src/pzpr/variety.js @@ -456,6 +456,7 @@ teri: [0, 0, "テリトリー", "Territory", "kurodoko"], tetrochain: [0, 0, "テトロチェーンY", "Tetro Chain-Y"], tetrochaink: [0, 0, "テトロチェーンK", "Tetro Chain-K", "kurarin"], + tetroctb: [0, 0, "テトロチェーンCTB", "Tetro Chain-CTB", "shimaguni"], tetrominous: [0, 0, "Tetrominous", "Tetrominous", "fillomino"], tilecity: [0, 0, "タイルシティー", "Tile City"], tilepaint: [1, 0, "タイルペイント", "Tilepaint"], diff --git a/src/res/failcode.en.json b/src/res/failcode.en.json index c1dfb8f99..6af69dff8 100644 --- a/src/res/failcode.en.json +++ b/src/res/failcode.en.json @@ -151,6 +151,7 @@ "bkMSGe2.nondango": "An area has two or more shaded circles.", "bkMSPassedGt2.moonsun": "A line passes the marks of the moon for two rooms in a row.", "bkMUPassedGt2.moonsun": "A line passes the marks of the sun for two rooms in a row.", + "bkNoBorder.tetroctb": "A block does not cross a region border.", "bkNoChain.chainedb": "A block is not diagonally adjacent to another block.", "bkNoChain.mrtile": "A block is not diagonally adjacent to another identical block.", "bkNoChain.sendai": "A city is not adjacent to another city with the same shape and orientation.", diff --git a/src/variety/shimaguni.js b/src/variety/shimaguni.js index 3835fb2d6..0d5ba71e4 100644 --- a/src/variety/shimaguni.js +++ b/src/variety/shimaguni.js @@ -17,7 +17,8 @@ "cocktail", "martini", "nuritwin", - "marutaring" + "marutaring", + "tetroctb" ], { //--------------------------------------------------------- @@ -37,13 +38,13 @@ play: ["shade", "unshade", "number"] } }, - "MouseEvent@cocktail,nuritwin,marutaring": { + "MouseEvent@cocktail,nuritwin,marutaring,tetroctb": { inputModes: { edit: ["border", "number", "clear", "info-blk"], play: ["shade", "unshade", "info-blk"] } }, - "MouseEvent@cocktail,martini#2": { + "MouseEvent@cocktail,martini,tetroctb#2": { dispInfoBlk: function() { var cell = this.getcell(); this.mousereset(); @@ -123,7 +124,7 @@ enableSubNumberArray: true, disableAnum: true }, - "Cell@chocona,hinge,heyablock,cocktail": { + "Cell@chocona,hinge,heyablock,cocktail,tetroctb": { minnum: 0 }, "Cell@martini": { @@ -182,7 +183,7 @@ Board: { hasborder: 1 }, - "Board@shimaguni,stostone,heyablock,cocktail,martini,nuritwin,marutaring": { + "Board@shimaguni,stostone,heyablock,cocktail,martini,nuritwin,marutaring,tetroctb": { addExtraInfo: function() { this.stonegraph = this.addInfoList(this.klass.AreaStoneGraph); } @@ -301,7 +302,7 @@ } }, - "AreaShadeGraph@chocona": { + "AreaShadeGraph@chocona,tetroctb": { enabled: true }, "AreaShadeGraph@nuritwin,marutaring": { @@ -316,7 +317,7 @@ component.hinge = null; } }, - "AreaStoneGraph:AreaShadeGraph@shimaguni,stostone,heyablock,cocktail,martini,nuritwin,marutaring": { + "AreaStoneGraph:AreaShadeGraph@shimaguni,stostone,heyablock,cocktail,martini,nuritwin,marutaring,tetroctb": { // Same as LITS AreaTetrominoGraph enabled: true, relation: { "cell.qans": "node", "border.ques": "separator" }, @@ -356,7 +357,7 @@ "AreaRoomGraph@martini": { hastop: false }, - "AreaShade8Graph@cocktail,martini": { + "AreaShade8Graph@cocktail,martini,tetroctb": { enabled: true }, @@ -647,6 +648,19 @@ "checkShadeDeadEnd" ] }, + "AnsCheck@tetroctb#1": { + checklist: [ + "checkShadeCellExist+", + "checkOverShadeCell", + "checkAdjacentShapes", + "checkUnderShadeCell", + + "checkShadeCellCount", + "checkBlockHasBorder", + "checkConnect8Shade", + "doneShadingDecided" + ] + }, "AnsCheck@shimaguni,stostone,heyablock,cocktail,martini": { checkSideAreaShadeCell: function() { this.checkSideAreaCell( @@ -1055,6 +1069,89 @@ ); } }, + "AnsCheck@tetroctb": { + checkOverShadeCell: function() { + this.checkAllArea( + this.board.sblkmgr, + function(w, h, a, n) { + return a <= 4; + }, + "csGt4" + ); + }, + checkUnderShadeCell: function() { + this.checkAllArea( + this.board.sblkmgr, + function(w, h, a, n) { + return a >= 4; + }, + "csLt4" + ); + }, + checkAdjacentShapes: function() { + var bd = this.board; + for (var c = 0; c < bd.cell.length; c++) { + var cell = bd.cell[c]; + if (cell.bx === bd.maxbx - 1 || cell.by === bd.maxby - 1) { + continue; + } + + var i, + adc = cell.adjacent; + var cells = [ + [cell, adc.right.adjacent.bottom], + [adc.right, adc.bottom] + ]; + for (i = 0; i < 2; i++) { + if (cells[i][0].isShade() && cells[i][1].isShade()) { + break; + } + } + if (i === 2) { + continue; + } + + var block1 = cells[i][0].sblk, + block2 = cells[i][1].sblk; + if ( + block1 === block2 || + block1.clist.length !== 4 || + this.isDifferentShapeBlock(block1, block2) + ) { + continue; + } + + this.failcode.add("bsSameShape"); + if (this.checkOnly) { + break; + } + block1.clist.seterr(1); + block2.clist.seterr(1); + } + }, + checkBlockHasBorder: function() { + var areas = this.board.sblkmgr.components; + for (var id = 0; id < areas.length; id++) { + var area = areas[id], + clist = area.clist; + if ( + clist.length < 4 || + clist.length !== clist[0].stone.clist.length + ) { + continue; + } + + this.failcode.add("bkNoBorder"); + if (this.checkOnly) { + break; + } + clist.seterr(1); + } + }, + checkConnect8Shade: function() { + this.checkOneArea(this.board.sblk8mgr, "csDivide"); + } + }, FailCode: { bkShadeDivide: "bkShadeDivide", diff --git a/test/script/tetroctb.js b/test/script/tetroctb.js new file mode 100644 index 000000000..f7e05122f --- /dev/null +++ b/test/script/tetroctb.js @@ -0,0 +1,40 @@ +/* tetroctb.js */ + +ui.debug.addDebugData("tetroctb", { + url: "6/6/va3orecsuf6l31h2i101h11", + failcheck: [ + [ + "brNoShade", + "pzprv3/tetroctb/6/6/15/0 1 2 3 4 5 /0 0 3 3 4 4 /3 3 3 3 6 7 /8 9 3 3 3 3 /10 11 3 3 12 13 /10 10 3 14 12 12 /3 1 . . 2 . /. . . . . . /. . . . . . /1 0 . . . . /1 . . . . 1 /. . . 1 . . /. . . . . . /. . . . . . /. . . . . . /. . . . . . /. . . . . . /. . . . . . /" + ], + [ + "csGt4", + "pzprv3/tetroctb/6/6/15/0 1 2 3 4 5 /0 0 3 3 4 4 /3 3 3 3 6 7 /8 9 3 3 3 3 /10 11 3 3 12 13 /10 10 3 14 12 12 /3 1 . . 2 . /. . . . . . /. . . . . . /1 0 . . . . /1 . . . . 1 /. . . 1 . . /. . . . . . /. . . . . . /. . . . . . /# . . . . . /# # # # . . /. . . . . . /" + ], + [ + "csLt4", + "pzprv3/tetroctb/6/6/15/0 1 2 3 4 5 /0 0 3 3 4 4 /3 3 3 3 6 7 /8 9 3 3 3 3 /10 11 3 3 12 13 /10 10 3 14 12 12 /3 1 . . 2 . /. . . . . . /. . . . . . /1 0 . . . . /1 . . . . 1 /. . . 1 . . /# # . . . . /# # . . . . /. . . . . . /# . . . . . /# # . . . . /. . . . . . /" + ], + [ + "bsSameShape", + "pzprv3/tetroctb/6/6/15/0 1 2 3 4 5 /0 0 3 3 4 4 /3 3 3 3 6 7 /8 9 3 3 3 3 /10 11 3 3 12 13 /10 10 3 14 12 12 /3 1 . . 2 . /. . . . . . /. . . . . . /1 0 . . . . /1 . . . . 1 /. . . 1 . . /# # . # # # /# # . . . # /. . # # # . /# . . # . . /# # # . . # /. . . # # # /" + ], + [ + "bkNoBorder", + "pzprv3/tetroctb/6/6/15/0 1 2 3 4 5 /0 0 3 3 4 4 /3 3 3 3 6 7 /8 9 3 3 3 3 /10 11 3 3 12 13 /10 10 3 14 12 12 /3 1 . . 2 . /. . . . . . /. . . . . . /1 0 . . . . /1 . . . . 1 /. . . 1 . . /# # . . # # /# # . # . # /. . # # . # /# . . # . . /# # # . # # /. . . # # . /" + ], + [ + "csDivide", + "pzprv3/tetroctb/6/6/15/0 1 2 3 4 5 /0 0 3 3 4 4 /3 3 3 3 6 7 /8 9 3 3 3 3 /10 11 3 3 12 13 /10 10 3 14 12 12 /3 1 . . 2 . /. . . . . . /. . . . . . /1 0 . . . . /1 . . . . 1 /. . . 1 . . /# # . # # . /# # . . # . /. . . . # . /# . . . . . /# # # . # # /. . . # # . /" + ], + [ + "bkShadeNe", + "pzprv3/tetroctb/6/6/15/0 1 2 3 4 5 /0 0 3 3 4 4 /3 3 3 3 6 7 /8 9 3 3 3 3 /10 11 3 3 12 13 /10 10 3 14 12 12 /3 1 . . 2 . /. . . . . . /. . . . . . /1 0 . . . . /1 . . . . 1 /. . . 1 . . /# # . . . . /# # . . . . /. . # # # . /# . . # . . /# # # . # # /. . . # # . /" + ], + [ + null, + "pzprv3/tetroctb/6/6/15/0 1 2 3 4 5 /0 0 3 3 4 4 /3 3 3 3 6 7 /8 9 3 3 3 3 /10 11 3 3 12 13 /10 10 3 14 12 12 /3 1 . . 2 . /. . . . . . /. . . . . . /1 0 . . . . /1 . . . . 1 /. . . 1 . . /# # + # # # /# # + + + # /+ + # # # + /# + + # + + /# # # + # # /+ + + # # + /" + ] + ], + inputs: [] +});