From: Benjamin Auder Date: Wed, 29 Jun 2022 21:32:22 +0000 (+0200) Subject: First version of complete Chakart rules (unfinished). Draft diagramer (missing marks... X-Git-Url: https://git.auder.net/images/assets/doc/html/current/R.css?a=commitdiff_plain;h=5abaabb3061f9c2927e2204a33a58c309f3a0082;p=xogo.git First version of complete Chakart rules (unfinished). Draft diagramer (missing marks for now) --- diff --git a/TODO b/TODO index 1e4eda3..0bbf333 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,5 @@ +allow markers on board for diagrams (add d_pieces to base_rules.js --> all the same purple circle) + add variants : Dark Racing Kings ? Checkered-Teleport ? diff --git a/base_rules.js b/base_rules.js index ea34a3d..ad30c0a 100644 --- a/base_rules.js +++ b/base_rules.js @@ -415,6 +415,7 @@ export default class ChessRules { // Graphical (can use variables defined above) this.containerId = o.element; + this.isDiagram = o.diagram; this.graphicalInit(); } @@ -561,7 +562,8 @@ export default class ChessRules { window.onresize = () => this.re_drawBoardElements(); const g_init = () => { this.re_drawBoardElements(); - this.initMouseEvents(); + if (!this.isDiagram) + this.initMouseEvents(); }; let container = document.getElementById(this.containerId); if (container.getBoundingClientRect().width == 0) { @@ -655,6 +657,7 @@ export default class ChessRules { } setupPieces(r) { + // TODO: d_pieces : only markers (for diagrams) / also in rescale() if (this.g_pieces) { // Refreshing: delete old pieces first for (let i=0; i { document.removeEventListener(ml.type, ml.listener); diff --git a/common.css b/common.css index e9bf31c..aed01ae 100644 --- a/common.css +++ b/common.css @@ -14,7 +14,6 @@ html { height: 100%; } - body { height: 100%; margin: 0; @@ -23,7 +22,6 @@ body { /* https://stackoverflow.com/a/24392249/12660887 */ position: relative; } - main { display: flex; flex-direction: column; @@ -32,62 +30,101 @@ main { flex-wrap: nowrap; font-size: 1.25rem; } +h1 { + font-size: 2rem; + font-weight: bold; + text-align: center; + display: block; + margin: 10px 0; +} +h4 { + font-size: 1.5rem; + font-weight: bold; + text-align: center; + display: block; + margin: 10px 0; + color: darkgreen; +} +a { + text-decoration: none; +} +.bold { + font-weight: bold; +} +button { + background-color: #757575; + border: none; + color: white; + padding: 10px 15px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 1em; + cursor: pointer; + border-radius: 20%; + margin: 15px 0; +} +button:hover, button.block-btn:hover { + background-color: #b11adc; +} +button.block-btn { + display: block; + background-color: #01786F; + margin: 0 auto 30px auto; /*TODO: margin-bottom 20px ? */ + font-size: 2rem; + padding: 15px 32px; +} +button.cancel-something { + background-color: darkred; + display: block; + margin-left: auto; + margin-right: auto; +} + +/* "Sticky footer" */ +#footer { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 50px; + text-align: center; +} +@media(max-height: 399px) { + #footer { + display: none; + } +} +a.left-link { + margin-right: 25px; +} +a.right-link { + margin-left: 25px; +} +#footer a > img { + height: 1.2em; + display: inline-block; + transform: translateY(3px); +} main > div { margin-top: 25vh; min-height: 500px; min-width: 320px; } - #gameInfos { max-width: 800px; } - @media(max-height: 800px) { #newGameForm, #gameInfos { margin-top: 30px; } } - @media(max-width: 767px) { main > div { padding: 0 10px; } } - -.author { - color: darkblue; - font-style: italic; -} - -#boardContainer { - position: fixed; - width: 100%; - height: 100%; - left: 0; - top: 0; - margin: 0; - padding: 0; - border: none; -} - -h1 { - font-size: 2rem; - font-weight: bold; - text-align: center; - display: block; - margin: 10px 0; -} - -h4 { - font-size: 1.5rem; - font-weight: bold; - text-align: center; - display: block; - margin: 10px 0; - color: darkgreen; -} - #gameInfos, #boardContainer, #gameStopped, @@ -96,147 +133,132 @@ h4 { #newGameForm { display: none; } - -.bold { - font-weight: bold; +#gameStopped > h1 { + margin-bottom: 10px; } #gameInfos > .players-info { text-align: center; } - #gameInfos > .options-info { text-align: center; color: #757575; margin-bottom: 15px; } - #gameInfos > div { margin: 10px 0; } - #gameInfos > .rules { color: #732E6C; } - -#gameInfos > .rules > p, -#gameInfos > .rules > ul, -#gameInfos > .rules > ol { +#gameInfos > .rules p, +#gameInfos > .rules ul, +#gameInfos > .rules ol { margin: 10px 0; } - -#gameInfos > .rules > ul { +#gameInfos > .rules ul { list-style-type: square; padding-left: 30px; } -#gameInfos > .rules > ol { +#gameInfos > .rules ol { list-style-type: numeric; padding-left: 30px; } - -#gameInfos > .rules > a { +#gameInfos > .rules a { padding-bottom: 1px; border-bottom: 1px dotted black; } - -#gameStopped > h1 { - margin-bottom: 10px; -} - -/* "Sticky footer" */ -#footer { - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 50px; - text-align: center; +#gameInfos > .rules .author { + color: darkblue; + font-style: italic; } -@media(max-height: 399px) { - #footer { - display: none; - } +/* Complete rules (separate page) */ +.full-rules { + max-width: 800px; + margin: 20px auto; + padding: 0 10px; } - -a.left-link { - margin-right: 25px; +.full-rules h2, .full-rules h3, .full-rules h4 { + font-weight: bold; + display: block; } -a.right-link { - margin-left: 25px; +.full-rules h2 { + color: darkred; + font-size: 2.5em; + margin: 10px 0; } - -#footer a > img { - height: 1.2em; - display: inline-block; - transform: translateY(3px); +.full-rules h3 { + color: darkviolet; + font-size: 2em; + margin: 10px 0; } - -button { - background-color: #757575; - border: none; - color: white; - padding: 10px 15px; +.full-rules h4 { + color: darkgreen; + font-size: 1.5em; + margin: 5px 0; text-align: center; - text-decoration: none; - display: inline-block; - font-size: 1em; - cursor: pointer; - border-radius: 20%; - margin: 15px 0; -} - -button:hover, button.block-btn:hover { - background-color: #b11adc; } - -button.block-btn { - display: block; - background-color: #01786F; - margin: 0 auto 30px auto; /*TODO: margin-bottom 20px ? */ - font-size: 2rem; - padding: 15px 32px; +.full-rules .diag { + position: relative; + margin: -30px auto 0 auto; } - -button.cancel-something { - background-color: darkred; +.full-rules figcaption { display: block; - margin-left: auto; - margin-right: auto; -} - -#upLeftInfos { - position: absolute; - left: 0; - top: 0; + text-align: center; + margin-top: -50px; + margin-bottom: 30px; } - -#upRightStop { - position: absolute; - left: calc(100% - 25px); - top: 0; +/* TODO: use same CSS for rules and full-rules? */ +.full-rules p, .full-rules ul, .full-rules ol { + margin: 10px 0; } -#upLeftInfos > svg, #upRightStop > svg { - width: 25px; - cursor: pointer; +.full-rules ul { + list-style-type: square; + padding-left: 30px; } - -@media(max-width: 767px) { - #upRightStop { - left: calc(100% - 35px); - } - #upLeftInfos > svg, #upRightStop > svg { - width: 35px; - } - #upLeftInfos > svg path, #upRightStop > svg path { - fill: #999; - } +.full-rules ol { + list-style-type: numeric; + padding-left: 30px; } +/* From vchess to adapt: */ +/* +figure.diagram-container + margin: 15px 0 15px 0 + text-align: center + width: 100% + display: block + .diagram + display: block + width: 50% + margin-left: auto + margin-right: auto + @media screen and (max-width: 630px) + width: 75% + .diag12 + float: left + width: 42% + margin: 0 2% 0 6% + @media screen and (max-width: 630px) + width: 49% + margin: 0 1% 0 0 + .diag22 + float: left + width: 42% + margin: 0 6% 0 2% + @media screen and (max-width: 630px) + width: 49% + margin: 0 0 0 1% + figcaption + display: block + clear: both + padding-top: 5px + font-size: 0.8em +*/ #ng-select { margin-bottom: 20px; } - /* Options when starting custom game */ .words { line-height: 0.9em; @@ -254,24 +276,19 @@ button.cancel-something { .highlight-word { background-color: lightblue; } - #gameOptions { text-align: center; } - .option-select, .option-input { margin: 15px 0 0 0; } - .option-input { display: inline-block; margin-right: 10px; } - .option-input input[type=number] { width: 64px; } - .btn-wrap { text-align: center; } @@ -280,35 +297,63 @@ button.cancel-something { width: inherit; text-align: center; } - -a { - text-decoration: none; -} - /* Game link div + custom game "button" */ #gameLink span, #gameLink a, #footer a { padding-bottom: 1px; border-bottom: 1px dotted darkgrey; color: darkred; } - #gameLink span { display: inline-box; cursor: pointer; } - #gameLink > p { margin: 10px 0; } -/* Board container (without reserves) */ +/* Board container (with reserves) */ +#boardContainer { + position: fixed; + width: 100%; + height: 100%; + left: 0; + top: 0; + margin: 0; + padding: 0; + border: none; +} +#upLeftInfos { + position: absolute; + left: 0; + top: 0; +} +#upRightStop { + position: absolute; + left: calc(100% - 25px); + top: 0; +} +#upLeftInfos > svg, #upRightStop > svg { + width: 25px; + cursor: pointer; +} +@media(max-width: 767px) { + #upRightStop { + left: calc(100% - 35px); + } + #upLeftInfos > svg, #upRightStop > svg { + width: 35px; + } + #upLeftInfos > svg path, #upRightStop > svg path { + fill: #999; + } +} +/* Playing board (without reserves) */ .chessboard { position: absolute; cursor: pointer; min-width: 200px; min-height: 200px; } - piece { position: absolute; top: 0; @@ -318,17 +363,14 @@ piece { will-change: transform; pointer-events: none; } - piece.hidden { display: none; } - /* Drawing of the board */ .chessboard_SVG { width: 100%; height: 100%; } - /* Default squares colors (can be overriden or unused) */ .dark-square { fill: #b58863; @@ -336,46 +378,38 @@ piece.hidden { .light-square { fill: #f0d9b5; } - .in-shadow { filter: brightness(50%); } - .reserves { position: absolute; display: block; cursor: pointer; } - .reserve-cell { position: relative; display: block; float: left; } - /* Pieces' counter for reserves */ .reserve-num { color: red; position: absolute; display: block; font-weight: bold; - /*z-index: 10;*/ } - -/* Choices div after a promotion (TODO: do not hide board) */ +/* Choices div after a promotion */ #choices, .choice { position: absolute; cursor: pointer; } - /* https://moderncss.dev/custom-select-styles-with-pure-css/ */ :root { --select-border: #777; --select-focus: #b11adc; --select-arrow: var(--select-border); } - select { appearance: none; background-color: transparent; @@ -390,7 +424,6 @@ select { z-index: 1; outline: none; } - .select { display: grid; grid-template-areas: "select"; @@ -409,11 +442,9 @@ select { width: 100%; margin: auto; } - select, .select::after { grid-area: select; } - .select::after { content: ""; justify-self: end; @@ -422,7 +453,6 @@ select, .select::after { background-color: var(--select-arrow); clip-path: polygon(100% 0%, 0 0%, 50% 100%); } - select:focus + .focus { position: absolute; top: -1px; @@ -433,7 +463,6 @@ select:focus + .focus { border-radius: inherit; } - /* https://auralinna.blog/post/2018/how-to-create-material-design-like-form-text-fields/ */ .form-field { display: block; @@ -498,7 +527,6 @@ select:focus + .focus { width: 100%; } - /* https://dev.to/kallmanation/styling-a-checkbox-with-only-css-3o3p */ label.checkbox > input[type="checkbox"] { display: none; @@ -515,7 +543,6 @@ label.checkbox > input[type="checkbox"] + *::before { border-width: 0.1rem; border-color: gray; } - label.checkbox > input[type="checkbox"]:checked + *::before { content: "✓"; font-size: 1.1rem; @@ -528,16 +555,11 @@ label.checkbox > input[type="checkbox"]:checked + *::before { label.checkbox > input[type="checkbox"]:checked + * { color: teal; } - -/*label.checkbox { - color: teal; -}*/ label.checkbox > span.spacer { width: 10px; content: " "; } - /* https://theanam.github.io/css-only-loaders/ ("hour-glass") */ :root{ --loader-width: 70px; @@ -553,7 +575,6 @@ label.checkbox > span.spacer { flex-grow: 0; flex-shrink: 0; } - @keyframes slide { 0% { transform: translateY(0%); @@ -571,7 +592,6 @@ label.checkbox > span.spacer { transform: translateY(0%); } } - @keyframes spin { 0% { transform: rotate(0deg); @@ -589,7 +609,6 @@ label.checkbox > span.spacer { transform: rotate(360deg); } } - .loader.hour-glass { position: relative; width: var(--loader-width, 100px); @@ -601,7 +620,6 @@ label.checkbox > span.spacer { animation: spin var(--animation-duration, 4s) infinite ease-in-out; margin: 20px auto; } - .hour-glass:before { content: ""; position: absolute; diff --git a/utils/drawDiagrams.js b/utils/drawDiagrams.js new file mode 100644 index 0000000..4672643 --- /dev/null +++ b/utils/drawDiagrams.js @@ -0,0 +1,37 @@ +function fenToDiag(vname) { + import(`/variants/${vname}/class.js`).then(module => { + window.V = module.default; + for (const [k, v] of Object.entries(V.Aliases)) + window[k] = v; + drawDiagrams(); + }); +} + +// TODO: heuristic to improve for ratio != 1 (how?) +function getDiagSize() { + if (window.innerWidth > 1000) + return 500; + if (window.innerWidth < 800) + return window.innerWidth; + return window.innerWidth / 2; +} + +function drawDiagrams() { + const diagrams = document.getElementsByClassName("diag"); + for (let i=0; iTODO

+ + + Chakart Rules + + + + + +
+ +

Chakart Rules

+ +
+

+ Pieces move as usual, but they all hide a special "power" inspired by + Mario Kart: +

+
    +
  • + The pawn (Toad) leaves a "turbo" mushroom on its initial square, or on + the intermediate one in case of a two squares move. +
  • +
  • + The knight (Yoshi) let a surprise egg on its initial square. See about + egg effect below. +
  • +
  • + The rook (Donkey) put a banana on a square diagonally adjacent to the + arrival one, at random, if possible. +
  • +
  • + The bishop (Wario) put a bomb on a square orthogonally adjacent to the + arrival one, at random, if possible. +
  • +
  • + The queen (Mario) can play a stealth move once in the game: the opponent + will only know that a queen moved - to an empty square. + A promoted queen also has this power if not already used. +
  • +
  • + The king (Peach) can "throw a shell" on an enemy reachable by a queen, + once in the game. A promoted king also has this power, if not already + used. The capture is done remotely without moving. +
  • +
+

The king cannot castle, and pawns don't capture en passant.

+
+
+
+
After 1.d4 Nf6 2.Bb4 (put a bomb on c4).
+
+
+ +
+

+ So the goal is to capture Peach :) If pawns promoted into king, then all + of them must be captured. Since it still looked too easy, the 4 mentioned + objects alter the move played, generally at random: +

+
    +
  • + A king or a pawn arriving on a mushroom advance one square further, + while a knight jump another time in the same direction, if possible. + Pawns can "eat" objects diagonally too. +
  • +
  • + A piece arriving on a banana (resp. bomb) is redirected at random by one + square in an orthogonal (resp. diagonal) direction. If a piece (of any + color!) stands on that square, then it is captured. +
  • +
  • + The effects can cumulate, as illustrated on the diagram: the bishop + "captures" the banana on e4, and is then redirected twoard e5: mushroom, + it jumps over the black pawn to ends on the bomb on e7, which sends it + on d6 (f6 and f8 were possible too). A bomb is finally put on c6 which + is the only eligible square. A piece may ends on its initial square, + move back, and so on. That being said, a given object can only be used + once on the path. +
  • +
+ +
+
+
+
+
+
Left: before 1.Bxe4. Right: after the move, ending on d6.
+
+
+ +
+

+ The egg case is more complex: a move ending on an egg triggers an effect + chosen at random, positive or negative. There are four bonus and four + penalties. They are introduced in a dual form: first the positive, then + the negative. +

+
    +
  • + King Boo (*B) let you exchange the position of any pair of pieces on the + board. +
  • +
  • Koopa (*K) drives the piece back onto its initial square.
  • +
  • + Toadette (*T) allows to place a new — random — piece on the + board. If the piece is dropped on an egg, banana or bomb, its effects + are applied. +
  • +
  • + Chomp (*C) eats the piece, which is thus captured. If it's Peach, then + bad luck, game over :) +
  • +
  • Daisy (*D) allows to play again with any of your pieces.
  • +
  • + Bowser (*M) immobilizes the piece (which is surrounded by a light green + halo). It won't be allowed to move on the next turn. +
  • +
  • Luigi (*L) changes the color of a random enemy piece.
  • +
  • Waluigi (*W) changes the color of one of your pieces (at random).
  • +
+
+
+
+
+
+
+ 1...Rxf6*W: Waluigi turns the g8 queen into white. + This last can then capture the king. Bad luck :( +
+
+
+ +
+ + + + + diff --git a/variants/Hex/class.js b/variants/Hex/class.js index 507b42d..80d4501 100644 --- a/variants/Hex/class.js +++ b/variants/Hex/class.js @@ -165,7 +165,9 @@ export default class HexRules extends ChessRules { get size() { const baseRatio = 1.6191907514450865; //2801.2 / 1730, "widescreen" - const rotate = window.innerWidth < window.innerHeight; //"vertical screen" + const rc = + document.getElementById(this.containerid).getBoundingClientRect(); + const rotate = rc.width < rc.height; //"vertical screen" return { x: this.options["bsize"], y: this.options["bsize"],