Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Turnaround #544

Merged
merged 30 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
### ????-??-??

* aqre: New puzzle type Aqre
* interbd: New puzzle type International Borders (due to Lennard Sprong)
* tapaloop: New puzzle type Tapa-Like Loop (due to Giuliano Montelucci)
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src-ui/changes.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<main>
<div style="margin-bottom: 5px;"><b>Latest types</b> (<em><a href="/list.html" target="_parent">all types</a></em>)</div>
<ul>
<li><a href="/p?turnaround" target="_parent">Turnaround</a></li>
<li><a href="/p?sananko" target="_parent">San-Anko サンアンコー</a></li>
<li><a href="/p?bosnianroad" target="_parent">Bosnian Road</a></li>
<li><a href="/p?kuromenbun" target="_parent">Kuromenbun クロメンブン</a></li>
Expand Down
Binary file added src-ui/img/turnaround.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src-ui/js/ui/KeyPopup.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ ui.keypopup = {
teri: [10, 0],
portal: [10, 0],
kuromenbun: [10, 0],
turnaround: [3, 0],
bosnianroad: [8, 0],
sananko: [10, 113]
},
Expand Down Expand Up @@ -343,6 +344,8 @@ ui.keypopup = {
this.generate_retroships(mode);
} else if (type === 130) {
this.generate_lix(mode);
} else if (type === 131) {
this.generate_infinity(mode);
}
},
gentable4: function(mode) {
Expand Down
1 change: 1 addition & 0 deletions src-ui/js/ui/Misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ function toBGimage(pid) {
"tontonbeya",
"trainstations",
"tslither",
"turnaround",
"voxas",
"vslither",
"walllogic",
Expand Down
1 change: 1 addition & 0 deletions src-ui/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ <h2 id="title"><span lang="ja">パズルの種類のリスト</span><span lang="
<li data-pid="lixloop"></li>
<li data-pid="portal"></li>
<li data-pid="bosnianroad"></li>
<li data-pid="turnaround"></li>
</ul>
</div>
<div class="lists loops">
Expand Down
1 change: 1 addition & 0 deletions src-ui/res/history.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,4 @@ lineofsight: This genre was invented by Inaba Naoki.
kuromenbun: This genre first appeared in Puzzle Communication Nikoli vol. 138.
teri: This genre was invented by Inaba Naoki.
sananko: This genre was invented by Subaru Saito.
turnaround: This genre was invented by Ivan Adrian Koswara a.k.a. chaotic_iak.
1 change: 1 addition & 0 deletions src-ui/res/history.ja.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,4 @@ lineofsight: 稲葉直貴氏発案
kuromenbun: パズル通信ニコリ vol.138より
teri: 稲葉直貴氏発案
sananko: 齋藤スバル氏発案
turnaround: Ivan Adrian Koswara (chaotic_iak)氏発案
1 change: 1 addition & 0 deletions src-ui/res/rules.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -306,3 +306,4 @@ teri: "Shade some cells on the board.\n1. Shaded cells cannot be horizontally or
lixloop: "Shade some cells on the board, and draw a single loop that goes through all remaining cells.\n1. The loop cannot branch off or cross itself.\n2. Shaded cells cannot be orthogonally adjacent.\n3. Cells with letters or question marks cannot be shaded, and are not part of the loop.\n4. The letters represent cells that contain a turning line (L), straight line (I), or shaded cell (X). The clued cells indicate whichever type is most frequent in that direction. If multiple types are tied for most frequent, all letters will be listed in the clue."
sananko: "Place a number between 1 and 3 in some of the empty cells.\n1. Numbers must appear in groups of 3 orthogonally connected cells with the same number.\n2. Different groups cannot be orthogonally adjacent.\n3. Clues on shaded cells indicate the sum of numbers in the (up to four) orthogonally adjacent cells."
bosnianroad: "Shade some cells to form a loop.\n1. The loop cannot visit a cell that's orthogonally or diagonally adjacent to a cell it has visited before.\n2. Gray cells cannot be shaded.\n3. A number indicates the amount of shaded cells in the orthogonally and diagonally adjacent cells."
turnaround: "Draw a loop traveling orthogonally on cells. \n1. The loop must visit all numbers. \n2. Each number indicates how many turns the loop makes among the three cells: the number itself, and the cells immediately before and after it in the loop."
2 changes: 1 addition & 1 deletion src-ui/res/rules.ja.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,4 @@ sananko: "1. 空いているマスのいくつかに1~3の数字を1つ
bosnianroad: "1. いくつかのマスを黒く塗り、黒マスでひとつのループを作りましょう。\n2. ループの中腹同士が辺や頂点で接してはいけません。\n3. 灰色のマスは塗りつぶすことができません。数字は、その周囲8マスのうち黒く塗られるマスの数を表します。"
subomino: "1. 点線上に線を引き、盤面の白マスをブロックに分割する。\n2. 数字は、そのマスを含むブロックのマス数を表す。ブロックは数字をいくつ含んでも良い。\n3. 辺で接するブロック同士は、一方が他方を包含してはいけない。ただし包含とは、片方のブロックを回転せずに平行移動させたとき、もう片方のブロックの上にマスがはみ出ず重ねられることである。"
trainstations: "1. 盤面の全てのマスにタテヨコに線を引き、全体で1つの輪っかを作ります。\n2. 輪っかを作る線はマスの中央を通り、盤面の外に出たり、枝分かれしたり、行き止まりがあったりしてはいけません。\n3. ┼のマスでは、線は必ず立体交差します。┼以外のマスで線が交差してはいけません。\n4. 数字は駅を表します。駅は、数字の順番通りに通る必要があります。\n5. 線は駅のマスの上で直進します。"
lineofsight: "1. パズル面のいくつかの頂点を線でつないで枝分かれのない一つのループを作る。\n2. 数字と矢印は、その方向を見たときに見える直線の長さを表す。"
lineofsight: "1. パズル面のいくつかの頂点を線でつないで枝分かれのない一つのループを作る。\n2. 数字と矢印は、その方向を見たときに見える直線の長さを表す。"
1 change: 0 additions & 1 deletion src/puzzle/Config.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
"patchwork_leftaux",
true
); /* patchwork: Alternative mouse input */

this.add("squarecell", true); /* セルは正方形にする */

/* 入力方法設定 */
Expand Down
13 changes: 7 additions & 6 deletions src/pzpr/variety.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,6 @@
arukone: [0, 0, "アルコネ", "Arukone", "numlin"],
ayeheya: [0, 1, "∀人∃HEYA", "Ayeheya", "heyawake"],
balance: [0, 0, "Balance Loop", "Balance Loop"],
cave: [1, 0, "バッグ", "Cave", "kurodoko", { alias: "bag" }],
cbanana: [0, 0, "チョコバナナ", "Choco Banana"],
circlesquare: [0, 0, "Circles and Squares", "Circles and Squares"],
context: [0, 0, "Context", "Context"],
crossstitch: [0, 0, "Crossstitch", "Crossstitch"],
cts: [0, 0, "Cross the Streams", "Cross the Streams", "nonogram"],
barns: [1, 0, "バーンズ", "Barns"],
battleship: [0, 0, "Battleship", "Battleship", "statuepark"],
bdblock: [1, 0, "ボーダーブロック", "Border Block"],
Expand All @@ -113,6 +107,12 @@
bosnianroad: [0, 0, "Bosnian Road", "Bosnian Road"],
box: [0, 0, "ボックス", "Box"],
brownies: [0, 0, "ブラウニー", "Brownies", "yosenabe"],
cave: [1, 0, "バッグ", "Cave", "kurodoko", { alias: "bag" }],
cbanana: [0, 0, "チョコバナナ", "Choco Banana"],
circlesquare: [0, 0, "Circles and Squares", "Circles and Squares"],
context: [0, 0, "Context", "Context"],
crossstitch: [0, 0, "Crossstitch", "Crossstitch"],
cts: [0, 0, "Cross the Streams", "Cross the Streams", "nonogram"],
skyscrapers: [
0,
0,
Expand Down Expand Up @@ -408,6 +408,7 @@
tren: [0, 0, "パーキング", "Tren"],
triplace: [0, 0, "トリプレイス", "Tri-place"],
tslither: [0, 0, "Touch Slitherlink", "Touch Slitherlink", "vslither"],
turnaround: [0, 0, "ターンアラウンド", "Turnaround"],
usotatami: [0, 0, "ウソタタミ", "Uso-tatami", "fillmat"],
usoone: [0, 0, "ウソワン", "Uso-one"],
view: [1, 0, "ヴィウ", "View", "sukoro"],
Expand Down
3 changes: 3 additions & 0 deletions src/res/failcode.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"anShadeNe.yajisoko": "The number of boxes is not correct.",
"anShadeNe": "The number of shaded cells is not correct.",
"anTatamiNe.yajitatami": "The number of tatamis are not correct.",
"anTurn.turnaround": "The number of turns is not correct",
"anUnitNe.kuroclone": "The size of the pointed unit is not correct.",
"arAdjPair.toichika": "There are paired arrows in adjacent countries.",
"arAdjPair.toichika2": "There are paired numbers in adjacent countries.",
Expand Down Expand Up @@ -769,6 +770,7 @@
"nqAroundDup.kakuru": "There are same numbers around the pre-numbered cell.",
"nqAroundSumNe.kakuru": "A sum of numbers around the pre-numbered cell is incorrect.",
"numNoLine.geradeweg": "A number has no line.",
"numNoLine.turnaround": "A number has no line.",
"objShaded.nurimaze": "An object is shaded.",
"pairedLetterNe.kinkonkan": "Beam from a light doesn't reach its pair.",
"pairedNumberNe.kinkonkan": "The number of reflections is wrong.",
Expand All @@ -780,6 +782,7 @@
"rmDeadend.scrin": "There is a dead-end rectangle.",
"rmIsolated.scrin": "There is an isolated rectangle.",
"rmRectUnshade.scrin": "A rectangle is not part of the solution.",
"routeLenLoop": "The route does not contain a loop.",
"routeIgnoreCP.nurimaze": "There is a circle out of the shortest route from S to G.",
"routePassDeadEnd.nurimaze": "There is a triangle on the shortest route from S to G.",
"segBlackEq.balance": "Segments through a black circle are equal.",
Expand Down
5 changes: 5 additions & 0 deletions src/res/failcode.ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"anNumberNe.hebi": "矢印の先にある数字が正しくありません。",
"anShadeNe": "矢印の方向にある黒マスの数が正しくありません。",
"anTatamiNe.yajitatami": "矢印の方向にあるタタミの数が正しくありません。",
"anTurn.turnaround": "線の曲がった回数が数字と違っています。",
x-sheep marked this conversation as resolved.
Show resolved Hide resolved
"anUnitNe.kuroclone": "矢印の先にあるユニットの大きさが正しくありません。",
"arAdjPair.toichika": "辺を共有する国にペアとなる矢印が入っています。",
"arAdjPair.toichika2": "ペアとなる数字の入っている領域が隣り合っています。",
Expand Down Expand Up @@ -589,6 +590,7 @@
"nqAroundDup.kakuru": "初めから出ている数字の周りに同じ数字が入っています。",
"nqAroundSumNe.kakuru": "初めから出ている数字の周りに入る数の合計が正しくありません。",
"numNoLine.geradeweg": "線の通っていない数字があります。",
"numNoLine.turnaround": "線の通っていない数字があります。",
"objShaded.nurimaze": "オブジェクトが黒マスになっています。",
"pairedLetterNe.kinkonkan": "光が同じ文字の場所へ到達しません。",
"pairedNumberNe.kinkonkan": "光の反射回数が正しくありません。",
Expand All @@ -600,6 +602,9 @@
"rmDeadend.scrin": "頂点を1つしか共有していない長方形があります。",
"rmIsolated.scrin": "頂点を全く共有していない長方形があります。",
"rmRectUnshade.scrin": "輪の中に長方形が出来ています。",
"routeLenGt": "ブロックの数が数字よりも長いです",
"routeLenLt": "ブロックの数が数字よりも短いです",
"routeLenLoop": "ループではありません.",
x-sheep marked this conversation as resolved.
Show resolved Hide resolved
"routeIgnoreCP.nurimaze": "○がSからGへの経路上にありません。",
"routePassDeadEnd.nurimaze": "△がSからGへの経路上にあります。",
"segBlackEq.balance": "黒丸から線の端までの長さが同じになっています。",
Expand Down
175 changes: 175 additions & 0 deletions src/variety/turnaround.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
(function(pidlist, classbase) {
if (typeof module === "object" && module.exports) {
module.exports = [pidlist, classbase];
} else {
pzpr.classmgr.makeCustom(pidlist, classbase);
}
})(["turnaround"], {
MouseEvent: {
inputModes: {
edit: ["number", "clear", "info-line"],
play: ["line", "peke", "clear", "info-line"]
},
autoedit_func: "qnum",
autoplay_func: "line"
},
KeyEvent: {
enablemake: true
},

Cell: {
minnum: 0,
maxnum: 3,

isCmp: function() {
if (!this.puzzle.execConfig("autocmp")) {
return false;
}
return this.qnum === this.countTurn();
},

countTurn: function() {
if (!this.isNum() || this.lcnt !== 2) {
return -1;
}

var clist = this.getAdjCells();
if (
clist.some(function(cell) {
return cell.lcnt !== 2;
})
) {
return -1;
}

clist.add(this);
var turncount = 0;
clist.each(function(cell) {
turncount += cell.isLineCurve() ? 1 : 0;
});

return turncount;
},

getAdjCells: function() {
var clist = new this.klass.PieceList();
for (var dir in this.adjborder) {
if (this.adjborder[dir].isLine()) {
clist.add(this.adjacent[dir]);
}
}
return clist;
},

posthook: {
qans: function(num) {
x-sheep marked this conversation as resolved.
Show resolved Hide resolved
if (num >= 0) {
this.checkAutoCmp();
}
}
}
},
Board: {
hasborder: 1
},
LineGraph: {
enabled: true
},

Graphic: {
irowake: true,
qcmpcolor: "rgb(127,127,127)",
autocmp: "number",

getQuesNumberColor: function(cell) {
var qnum_color = this.getQuesNumberColor_mixed(cell);
if ((cell.error || cell.qinfo) === 1) {
return qnum_color;
}
return cell.isCmp() ? this.qcmpcolor : qnum_color;
},

setRange: function(x1, y1, x2, y2) {
var puzzle = this.puzzle,
bd = puzzle.board;
if (puzzle.execConfig("autocmp")) {
x1 = bd.minbx - 2;
y1 = bd.minby - 2;
x2 = bd.maxbx + 2;
y2 = bd.maxby + 2;
}
this.common.setRange.call(this, x1, y1, x2, y2);
},

paint: function() {
this.drawBGCells();
this.drawShadedCells();
this.drawDashedGrid();
this.drawLines();
this.drawQuesNumbers();
this.drawPekes();

this.drawChassis();

this.drawTarget();
}
},

Encode: {
decodePzpr: function(type) {
this.decodeNumber16();
},
encodePzpr: function(type) {
this.encodeNumber16();
}
},
FileIO: {
decodeData: function() {
this.decodeCellQnum();
this.decodeBorderLine();
},
encodeData: function() {
this.encodeCellQnum();
this.encodeBorderLine();
}
},

AnsCheck: {
checklist: [
"checkBranchLine",
"checkCrossLine",

"checkTurnCount",
"checkNoLineNumber",

"checkDeadendLine+",
"checkOneLoop"
],

checkTurnCount: function() {
this.checkAllCell(function(cell) {
if (!cell.isValidNum()) {
return false;
}

var turncount = cell.countTurn();
if (turncount === -1) {
return false;
}
if (turncount !== cell.qnum) {
cell.seterr(1);
cell.getAdjCells().seterr(1);
return true;
}

return false;
}, "anTurn");
},

checkNoLineNumber: function() {
this.checkAllCell(function(cell) {
return cell.isNum() && cell.lcnt === 0;
}, "numNoLine");
}
}
});
37 changes: 37 additions & 0 deletions test/script/turnaround.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
ui.debug.addDebugData("turnaround", {
url: "5/5/h0g1l1g2l2g3h",
failcheck: [
[
"numNoLine",
"pzprv3/turnaround/5/5/. . 0 . 1 /. . . . . /. 1 . 2 . /. . . . . /2 . 3 . . /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 /"
],
[
"numNoLine",
"pzprv3/turnaround/5/5/. . 0 . 1 /. . . . . /. 1 . 2 . /. . . . . /2 . 3 . . /0 0 0 0 /1 1 1 1 /1 1 1 0 /0 0 0 1 /0 0 0 0 /0 0 0 0 0 /1 0 0 0 1 /0 0 0 1 1 /0 0 0 0 0 /"
],
[
"anTurn",
"pzprv3/turnaround/5/5/. . 0 . 1 /. . . . . /. 1 . 2 . /. . . . . /2 . 3 . . /0 1 1 1 /0 0 0 0 /0 0 0 1 /0 0 0 1 /1 1 0 0 /0 1 0 0 0 /0 0 0 0 1 /1 0 0 1 0 /1 0 0 0 1 /"
],
[
"lnBranch",
"pzprv3/turnaround/5/5/. . 0 . 1 /. . . . . /. 1 . 2 . /. . . . . /2 . 3 . . /0 0 0 0 /0 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 0 0 0 /0 0 0 0 0 /"
],
[
"lnCross",
"pzprv3/turnaround/5/5/. . 0 . 1 /. . . . . /. 1 . 2 . /. . . . . /2 . 3 . . /0 0 0 0 /0 1 1 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 0 /"
],
[
"lnDeadEnd",
"pzprv3/turnaround/5/5/. . 0 . 1 /. . . . . /. . . . . /. . . . . /2 . 3 . . /1 1 1 1 /0 0 0 0 /1 0 0 0 /0 1 0 0 /1 0 1 0 /0 0 0 0 1 /0 0 0 0 1 /1 0 0 0 0 /1 1 1 1 0 /"
],
[
"lnPlLoop",
"pzprv3/turnaround/5/5/. . 0 . 1 /. . . . . /. . . . . /. . . . . /2 . 3 . . /1 1 1 1 /1 0 1 0 /1 0 1 0 /0 1 0 1 /1 0 1 0 /1 0 0 0 1 /0 1 1 1 1 /1 0 0 0 1 /1 1 1 1 0 /"
],
[
null,
"pzprv3/turnaround/5/5/. . 0 . 1 /. . . . . /. 1 . 2 . /. . . . . /2 . 3 . . /1 1 1 1 /1 1 1 0 /1 1 1 0 /0 1 0 1 /1 0 1 0 /1 0 0 0 1 /0 0 0 1 1 /1 0 0 0 1 /1 1 1 1 0 /"
]
]
});