diff --git a/src-ui/changes.html b/src-ui/changes.html index 56f7ebc6b..1c2836c86 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/cityspace.png b/src-ui/img/cityspace.png new file mode 100644 index 000000000..d30b0ea59 Binary files /dev/null and b/src-ui/img/cityspace.png differ diff --git a/src-ui/js/ui/KeyPopup.js b/src-ui/js/ui/KeyPopup.js index e7871de63..389c0d0fd 100644 --- a/src-ui/js/ui/KeyPopup.js +++ b/src-ui/js/ui/KeyPopup.js @@ -234,7 +234,8 @@ ui.keypopup = { isowatari: [10, 0], uturns: [133, 0], distopia: [10, 0], - numcity: [10, 10] + numcity: [10, 10], + cityspace: [10, 0] }, //--------------------------------------------------------------------------- diff --git a/src-ui/js/ui/Misc.js b/src-ui/js/ui/Misc.js index d11277473..4d16c62cb 100755 --- a/src-ui/js/ui/Misc.js +++ b/src-ui/js/ui/Misc.js @@ -123,6 +123,7 @@ function toBGimage(pid) { "cbanana", "chainedb", "circlesquare", + "cityspace", "cocktail", "coffeemilk", "compass", diff --git a/src-ui/list.html b/src-ui/list.html index 1ca665008..030da8f71 100644 --- a/src-ui/list.html +++ b/src-ui/list.html @@ -67,6 +67,7 @@

パズルの種類のリスト
  • +
  • diff --git a/src-ui/res/rules.en.yaml b/src-ui/res/rules.en.yaml index 838c0cb94..1059f03cc 100644 --- a/src-ui/res/rules.en.yaml +++ b/src-ui/res/rules.en.yaml @@ -122,6 +122,7 @@ skyscrapers: "Place a number in each cell.\n1. Numbers must be between 1 and N, castle: "Draw lines through orthogonally adjacent cells to form a loop.\n1. Lines cannot go through bold borders.\n2. White cells must be inside the loop, and black cells must be outside the loop.\n3. A number with an arrow indicates the number of line segments in that direction. Vertical arrows only count vertical lines, and horizontal arrows count horizontal lines." cbblock: "Draw lines over the dotted lines to divide the board into blocks.\n1. Each block must contain exactly two outlined regions.\n2. Two adjacent blocks cannot have the same shape, counting rotations and reflections as the same.\n3. Blocks cannot be rectangle- or square-shaped." chocona: "Shade some cells on the board.\n1. A group of orthogonally connected shaded cells is called a block. Each block must be a filled rectangle or square.\n2. Numbered regions must contain the indicated amount of shaded cells." +cityspace: "Shade some cells on the board.\n1. Groups of orthogonally connected shaded cells must be 1xN rectangles, where N is at least 2.\n2. All unshaded cells on the board form an orthogonally connected area.\n3. Unshaded cells cannot form a loop. This includes 2x2 squares.\n4. Numbers cannot be shaded.\n5. Clues represent the total number of unshaded cells that can be seen in a straight line vertically or horizontally, including itself." cojun: "Place a number in each cell. Some numbers are given.\n1. Numbers must be between 1 and N, where N is the size of the region.\n2. Each region contains exactly one of each number.\n3. Two equal numbers cannot be orthogonally adjacent.\n4. Where two numbers within a region are stacked vertically, the number on top must always be larger." compass: "Draw lines over the dotted lines to divide the board into several blocks.\n 1. Each block contains exactly one cell with a compass.\n2. A number in a compass indicates how many cells belong to its region that are further in the indicated direction than the compass itself." country: "Draw lines through orthogonally adjacent cells to form a loop.\n1. The loop cannot branch off or cross itself.\n2. Every country must be visited exactly once.\n3. A number indicates how many cells inside the country are visited by the loop.\n4. Two adjacent cells separated by a border cannot both be unused by the loop." diff --git a/src/pzpr/variety.js b/src/pzpr/variety.js index 811efe272..b7120f392 100755 --- a/src/pzpr/variety.js +++ b/src/pzpr/variety.js @@ -130,6 +130,7 @@ cbblock: [0, 0, "コンビブロック", "Combi Block"], chainedb: [0, 0, "チェンブロ", "Chained Block"], chocona: [0, 0, "チョコナ", "Chocona", "shimaguni"], + cityspace: [1, 0, "City Space", "City Space", "kurodoko"], cocktail: [0, 0, "カクテルランプ", "Cocktail Lamp", "shimaguni"], coffeemilk: [0, 0, "コーヒー牛乳", "Coffee Milk", "wblink"], cojun: [0, 0, "コージュン", "Cojun", "ripple"], diff --git a/src/res/failcode.en.json b/src/res/failcode.en.json index 893f89a57..8317cb387 100644 --- a/src/res/failcode.en.json +++ b/src/res/failcode.en.json @@ -415,6 +415,7 @@ "crNoSegment.tajmahal": "A clue is not inside a square.", "crShadeGt.creek": "The number of shaded cells overlapping a number is too high.", "crShadeLt.creek": "The number of shaded cells overlapping a number is too low.", + "cs1x1.cityspace": "There is an isolated shaded cell.", "cs2x2.bosnianroad": "The loop goes back on itself.", "cs2x2.snake": "The snake loops back on itself.", "cs2x2": "There is a 2x2 block of shaded cells.", @@ -463,6 +464,7 @@ "csSameJunction": "A shaded cell touches multiple T-junctions with the same orientation.", "csUpper.stostone": "Shaded cells remain in the upper half of the board after the blocks have fallen.", "csWidthGt1.nuribou": "There is a mass of shaded cells whose width is more than one.", + "csWidthGt1.cityspace": "There is a mass of shaded cells that is not a 1xN rectangle.", "cu2x2": "There is a 2x2 block of unshaded cells.", "cu3.aqre": "There are 4 or more unshaded cells in a row.", "cuConnOut": "Some unshaded cells are not connected to the outside.", diff --git a/src/variety/kurodoko.js b/src/variety/kurodoko.js index 7731b39a0..f72408290 100644 --- a/src/variety/kurodoko.js +++ b/src/variety/kurodoko.js @@ -7,7 +7,7 @@ } else { pzpr.classmgr.makeCustom(pidlist, classbase); } -})(["kurodoko", "nurimisaki", "cave", "teri"], { +})(["kurodoko", "nurimisaki", "cave", "teri", "cityspace"], { //--------------------------------------------------------- // マウス入力系 MouseEvent: { @@ -60,7 +60,7 @@ }, autoplay_func: "cell" }, - "MouseEvent@cave": { + "MouseEvent@cave,cityspace": { inputModes: { edit: ["number", "clear", "info-ublk"], play: ["shade", "unshade", "peke", "info-ublk"] @@ -222,7 +222,7 @@ enabled: true }, - "AreaShadeGraph@cave": { + "AreaShadeGraph@cave,cityspace": { enabled: true }, @@ -266,7 +266,7 @@ } }, - "Graphic@cave": { + "Graphic@cave,cityspace": { hideHatena: false, gridcolor_type: "DLIGHT", @@ -396,11 +396,14 @@ "check2x2ShadeCell@nurimisaki", "checkAdjacentShadeCell@kurodoko,teri", "checkConnectUnshadeRB@kurodoko,teri", - "checkConnectUnshade@nurimisaki,cave", + "checkConnectUnshade@nurimisaki,cave,cityspace", "checkConnectShadeOutside@cave", "checkViewOfNumber", "check2x2UnshadeCell@nurimisaki", "checkCirclePromontory@nurimisaki", + "checkUnshadeLoop@cityspace", + "checkShadeRect@cityspace", + "check1x1ShadeCell@cityspace", "checkNonCircleNotPromontory@nurimisaki", "doneShadingDecided" ], @@ -428,6 +431,44 @@ } }, + "AnsCheck@cityspace": { + checkUnshadeLoop: function() { + var bd = this.board, + ublks = bd.ublkmgr.components; + for (var r = 0; r < ublks.length; r++) { + if (ublks[r].circuits === 0) { + continue; + } + + this.failcode.add("cuLoop"); + if (this.checkOnly) { + return; + } + this.searchloop(ublks[r], bd.ublkmgr).seterr(1); + } + }, + + checkShadeRect: function() { + this.checkAllArea( + this.board.sblkmgr, + function(w, h, a, n) { + return w === 1 || h === 1; + }, + "csWidthGt1" + ); + }, + + check1x1ShadeCell: function() { + this.checkAllArea( + this.board.sblkmgr, + function(w, h, a, n) { + return a >= 2; + }, + "cs1x1" + ); + } + }, + "AnsCheck@nurimisaki": { check2x2UnshadeCell: function() { this.check2x2Block(function(cell) { diff --git a/test/script/cityspace.js b/test/script/cityspace.js new file mode 100644 index 000000000..e6538b0a3 --- /dev/null +++ b/test/script/cityspace.js @@ -0,0 +1,84 @@ +/* cityspace.js */ + +ui.debug.addDebugData("cityspace", { + url: "6/6/8i3t2i3r", + failcheck: [ + [ + "cuDivide", + "pzprv3/cityspace/6/6/8 . . . 3 . /. . . . . . /. . . . . . /. 2 . . . 3 /. . . . . . /. . . . . . /+ + + # + # /+ # + # + # /+ # + + + # /+ + # # # + /+ # + + + + /+ # + # # + /" + ], + [ + "cuLoop", + "pzprv3/cityspace/6/6/8 . . . 3 . /. . . . . . /. . . . . . /. 2 . . . 3 /. . . . . . /. . . . . . /+ + + # + # /+ # + # + # /+ # + + + + /+ + # # # + /+ # + + + + /+ + + # # # /" + ], + [ + "cuLoop", + "pzprv3/cityspace/6/6/8 . . . 3 . /. . . . . . /. . . . . . /. 2 . . . 3 /. . . . . . /. . . . . . /+ + + # + # /+ # + # + # /+ # + + + + /+ + # # # + /+ # + + + + /+ # + + # # /" + ], + [ + "csWidthGt1", + "pzprv3/cityspace/6/6/8 . . . 3 . /. . . . . . /. . . . . . /. 2 . . . 3 /. . . . . . /. . . . . . /+ + + # + # /+ # + # + # /+ # + + + + /+ + # # # + /+ # # + + + /+ + + # # # /" + ], + [ + "cs1x1", + "pzprv3/cityspace/6/6/8 . . . 3 . /. . . . . . /. . . . . . /. 2 . . . 3 /. . . . . . /. . . . . . /+ + + # + # /+ # + # + # /+ # + + + + /+ + # # # + /+ # + + + + /+ + # # # # /" + ], + [ + "nmSumViewNe", + "pzprv3/cityspace/6/6/8 . . . 3 . /. . . . . . /. . . . . . /. 2 . . . 3 /. . . . . . /. . . . . . /+ + + # + # /+ # + # + # /+ # + + + + /+ + # # # + /# # + + + + /+ + + # # # /" + ], + + [ + null, + "pzprv3/cityspace/6/6/8 . . . 3 . /. . . . . . /. . . . . . /. 2 . . . 3 /. . . . . . /. . . . . . /+ + + # + # /+ # + # + # /+ # + + + + /+ + # # # + /+ # + + + + /+ # + # # # /" + ] + ], + inputs: [ + { input: ["newboard,5,1", "editmode"] }, + { + input: [ + "cursor,1,1", + "key,-", + "key,right", + "key,0", + "key,right", + "key,1", + "key,right", + "key,2", + "key,right", + "key,1,0" + ], + result: "pzprv3/cityspace/1/5/- . 1 2 1 /. . . . . /" + }, + { + input: [ + "cursor,1,1", + "key,-", + "key,right", + "key,-", + "key,right", + "key,-", + "key,-" + ], + result: "pzprv3/cityspace/1/5/. - . 2 1 /. . . . . /" + }, + { input: ["newboard,5,2", "editmode"] }, + { + input: [ + "cursor,0,0", + "mouse,leftx2, 1,1", + "mouse,leftx3, 3,1", + "mouse,leftx4, 5,1", + "mouse,leftx5, 7,1", + "mouse,leftx6, 9,1", + "mouse,leftx7, 1,3", + "mouse,leftx8, 3,3", + "mouse,rightx2, 5,3", + "mouse,rightx3, 7,3", + "mouse,rightx4, 9,3" + ], + result: + "pzprv3/cityspace/2/5/- 2 3 4 5 /6 . 6 5 4 /. . . . . /. . . . . /" + } + ] +});