Refactor frontend system.
@@ -11,6 +11,11 @@
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
if (context.Request.Path.ToString().StartsWith("/games/img"))
|
||||
{
|
||||
context.Request.Path = context.Request.Path.ToString().Substring("/games".Length);
|
||||
}
|
||||
|
||||
var origin = context.Request.Headers["Origin"].ToString();
|
||||
if (string.IsNullOrEmpty(origin))
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@model int
|
||||
|
||||
@section Styles {
|
||||
<link href="~/chessboardjs/css/chessboard-1.0.0.min.css" rel="stylesheet"/>
|
||||
<link href="~/node_modules/@@chrisoakman/chessboardjs/dist/chessboard-1.0.0.min.css" rel="stylesheet" />
|
||||
<style>
|
||||
.hidden {
|
||||
display: none;
|
||||
@@ -9,9 +9,6 @@
|
||||
</style>
|
||||
}
|
||||
|
||||
@* Make a responsible board based on bootstrap: (Avoid width with hardcode or overflow) *@
|
||||
@* <div id="board"></div> *@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div id="board" style="width: 100%"></div>
|
||||
@@ -25,8 +22,7 @@
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<script type="module" src="~/chess.js/dist/esm/chess.js"></script>
|
||||
<script src="~/chessboardjs/js/chessboard-1.0.0.js"></script>
|
||||
<script type="module" src="~/node_modules/@@chrisoakman/chessboardjs/dist/chessboard-1.0.0.min.js"></script>
|
||||
<script type="module" src="~/site.js"></script>
|
||||
<script type="module">
|
||||
// Ask the user to enter w or b:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Aiursoft Chess Server</title>
|
||||
<link rel="stylesheet" href="~/bootstrap/dist/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="~/node_modules/bootstrap/dist/css/bootstrap.min.css" />
|
||||
@await RenderSectionAsync("Styles", required: false)
|
||||
</head>
|
||||
<body>
|
||||
@@ -37,8 +37,8 @@
|
||||
© @DateTime.UtcNow.Year - Aiursoft.ChessServer
|
||||
</div>
|
||||
</footer>
|
||||
<script src="~/jquery/dist/jquery.min.js"></script>
|
||||
<script src="~/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="~/node_modules/jquery/dist/jquery.min.js"></script>
|
||||
<script src="~/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
@await RenderSectionAsync("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2021 Twitter, Inc.
|
||||
Copyright (c) 2011-2021 The Bootstrap Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -1,427 +0,0 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
background-color: currentColor;
|
||||
border: 0;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
hr:not([size]) {
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title],
|
||||
abbr[data-bs-original-title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.2em;
|
||||
background-color: #fcf8e3;
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0d6efd;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
color: #0a58ca;
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 1em;
|
||||
direction: ltr /* rtl:ignore */;
|
||||
unicode-bidi: bidi-override;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: #d63384;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
a > code {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.2rem 0.4rem;
|
||||
font-size: 0.875em;
|
||||
color: #fff;
|
||||
background-color: #212529;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: #6c757d;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
tbody,
|
||||
tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]::-webkit-calendar-picker-indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: left;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
legend + * {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
::-webkit-datetime-edit-text,
|
||||
::-webkit-datetime-edit-minute,
|
||||
::-webkit-datetime-edit-hour-field,
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
outline-offset: -2px;
|
||||
-webkit-appearance: textfield;
|
||||
}
|
||||
|
||||
/* rtl:raw:
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
}
|
||||
*/
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
||||
@@ -1,8 +0,0 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
|
||||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
||||
@@ -1,424 +0,0 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
background-color: currentColor;
|
||||
border: 0;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
hr:not([size]) {
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title],
|
||||
abbr[data-bs-original-title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.2em;
|
||||
background-color: #fcf8e3;
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0d6efd;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
color: #0a58ca;
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 1em;
|
||||
direction: ltr ;
|
||||
unicode-bidi: bidi-override;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: #d63384;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
a > code {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.2rem 0.4rem;
|
||||
font-size: 0.875em;
|
||||
color: #fff;
|
||||
background-color: #212529;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: #6c757d;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
tbody,
|
||||
tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]::-webkit-calendar-picker-indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: right;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
legend + * {
|
||||
clear: right;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
::-webkit-datetime-edit-text,
|
||||
::-webkit-datetime-edit-minute,
|
||||
::-webkit-datetime-edit-hour-field,
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
outline-offset: -2px;
|
||||
-webkit-appearance: textfield;
|
||||
}
|
||||
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
}
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
|
||||
@@ -1,8 +0,0 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-right:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-right:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:right}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:right;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:right}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=email],[type=number],[type=tel],[type=url]{direction:ltr}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
|
||||
/*# sourceMappingURL=bootstrap-reboot.rtl.min.css.map */
|
||||
@@ -1,32 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint'],
|
||||
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
|
||||
|
||||
rules: {
|
||||
// allow while(true) loops
|
||||
'no-constant-condition': ['error', { checkLoops: false }],
|
||||
'@typescript-eslint/naming-convention': [
|
||||
'error',
|
||||
{
|
||||
selector: ['default'],
|
||||
format: ['strictCamelCase'],
|
||||
leadingUnderscore: 'allow',
|
||||
},
|
||||
{
|
||||
selector: ['variable'],
|
||||
format: ['strictCamelCase', 'UPPER_CASE'],
|
||||
},
|
||||
{
|
||||
selector: ['objectLiteralProperty'],
|
||||
format: ['strictCamelCase', 'UPPER_CASE'],
|
||||
},
|
||||
{
|
||||
selector: ['typeLike'],
|
||||
format: ['PascalCase'],
|
||||
},
|
||||
],
|
||||
'multiline-comment-style': ['error', 'starred-block']
|
||||
},
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
coverage/
|
||||
package-lock.json
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"overrides": [
|
||||
{
|
||||
"files": "**/*.md",
|
||||
"options": {
|
||||
"parser": "markdown",
|
||||
"printWidth": 80,
|
||||
"proseWrap": "always"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": "**/*.json",
|
||||
"options": {
|
||||
"parser": "json",
|
||||
"tabWidth": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
Copyright (c) 2023, Jeff Hlywa (jhlywa@gmail.com)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,901 +0,0 @@
|
||||
# chess.js
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
chess.js is a TypeScript chess library used for chess move
|
||||
generation/validation, piece placement/movement, and check/checkmate/stalemate
|
||||
detection - basically everything but the AI.
|
||||
|
||||
chess.js has been extensively tested in node.js and most modern browsers.
|
||||
|
||||
## Installation
|
||||
|
||||
Run the following command to install the most recent version of chess.js from
|
||||
NPM:
|
||||
|
||||
```sh
|
||||
npm install chess.js
|
||||
```
|
||||
|
||||
## Import into your project
|
||||
|
||||
### Modern way (ESM)
|
||||
|
||||
```js
|
||||
import { Chess } from 'chess.js'
|
||||
```
|
||||
|
||||
If you want to use it in a browser you can import as module like this:
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import { Chess } from 'chess.js'
|
||||
</script>
|
||||
```
|
||||
|
||||
### Old way (CommonJS)
|
||||
|
||||
```js
|
||||
const { Chess } = require('chess.js')
|
||||
```
|
||||
|
||||
## Example Code
|
||||
|
||||
The code below plays a random game of chess:
|
||||
|
||||
```js
|
||||
const chess = new Chess()
|
||||
|
||||
while (!chess.isGameOver()) {
|
||||
const moves = chess.moves()
|
||||
const move = moves[Math.floor(Math.random() * moves.length)]
|
||||
chess.move(move)
|
||||
}
|
||||
console.log(chess.pgn())
|
||||
```
|
||||
|
||||
## User Interface
|
||||
|
||||
By design chess.js is a headless library and does not include user interface
|
||||
elements. Many developers have successfully integrated chess.js with the
|
||||
[chessboard.js](http://chessboardjs.com) library. See
|
||||
[chessboard.js - Random vs Random](http://chessboardjs.com/examples#5002) for an
|
||||
example.
|
||||
|
||||
## Move & PGN Parsers
|
||||
|
||||
This library includes two parsers (`permissive` and `strict`) which are used to
|
||||
parse different forms of chess move notation. The `permissive` parser (the
|
||||
default) is able to handle many derivates of algebraic notation (e.g. `Nf3`,
|
||||
`g1f3`, `g1-f3`, `Ng1f3`, `Ng1-f3`, `Ng1xf3`). The `strict` parser only accepts
|
||||
moves in Standard Algebraic Notation and requires that they strictly adhere to
|
||||
the specification. The `strict` parser runs slightly faster but is much less
|
||||
forgiving of non-standard notation.
|
||||
|
||||
## API
|
||||
|
||||
### Constructor: Chess([ fen ])
|
||||
|
||||
The Chess() constructor takes an optional parameter which specifies the board
|
||||
configuration in
|
||||
[Forsyth-Edwards Notation (FEN)](http://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation).
|
||||
Throws an exception if an invalid FEN string is provided.
|
||||
|
||||
```ts
|
||||
// board defaults to the starting position when called with no parameters
|
||||
const chess = new Chess()
|
||||
|
||||
// pass in a FEN string to load a particular position
|
||||
const chess = new Chess(
|
||||
'r1k4r/p2nb1p1/2b4p/1p1n1p2/2PP4/3Q1NB1/1P3PPP/R5K1 b - - 0 19'
|
||||
)
|
||||
```
|
||||
|
||||
### .ascii()
|
||||
|
||||
Returns a string containing an ASCII diagram of the current position.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
// make some moves
|
||||
chess.move('e4')
|
||||
chess.move('e5')
|
||||
chess.move('f4')
|
||||
|
||||
chess.ascii()
|
||||
// -> ' +------------------------+
|
||||
// 8 | r n b q k b n r |
|
||||
// 7 | p p p p . p p p |
|
||||
// 6 | . . . . . . . . |
|
||||
// 5 | . . . . p . . . |
|
||||
// 4 | . . . . P P . . |
|
||||
// 3 | . . . . . . . . |
|
||||
// 2 | P P P P . . P P |
|
||||
// 1 | R N B Q K B N R |
|
||||
// +------------------------+
|
||||
// a b c d e f g h'
|
||||
```
|
||||
|
||||
### .board()
|
||||
|
||||
Returns an 2D array representation of the current position. Empty squares are
|
||||
represented by `null`.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
chess.board()
|
||||
// -> [[{square: 'a8', type: 'r', color: 'b'},
|
||||
{square: 'b8', type: 'n', color: 'b'},
|
||||
{square: 'c8', type: 'b', color: 'b'},
|
||||
{square: 'd8', type: 'q', color: 'b'},
|
||||
{square: 'e8', type: 'k', color: 'b'},
|
||||
{square: 'f8', type: 'b', color: 'b'},
|
||||
{square: 'g8', type: 'n', color: 'b'},
|
||||
{square: 'h8', type: 'r', color: 'b'}],
|
||||
[...],
|
||||
[...],
|
||||
[...],
|
||||
[...],
|
||||
[...],
|
||||
[{square: 'a1', type: 'r', color: 'w'},
|
||||
{square: 'b1', type: 'n', color: 'w'},
|
||||
{square: 'c1', type: 'b', color: 'w'},
|
||||
{square: 'd1', type: 'q', color: 'w'},
|
||||
{square: 'e1', type: 'k', color: 'w'},
|
||||
{square: 'f1', type: 'b', color: 'w'},
|
||||
{square: 'g1', type: 'n', color: 'w'},
|
||||
{square: 'h1', type: 'r', color: 'w'}]]
|
||||
```
|
||||
|
||||
### .clear()
|
||||
|
||||
Clears the board.
|
||||
|
||||
```ts
|
||||
chess.clear()
|
||||
chess.fen()
|
||||
// -> '8/8/8/8/8/8/8/8 w - - 0 1' <- empty board
|
||||
```
|
||||
|
||||
### .deleteComment()
|
||||
|
||||
Delete and return the comment for the current position, if it exists.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
chess.loadPgn('1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 {giuoco piano} *')
|
||||
|
||||
chess.getComment()
|
||||
// -> "giuoco piano"
|
||||
|
||||
chess.deleteComment()
|
||||
// -> "giuoco piano"
|
||||
|
||||
chess.getComment()
|
||||
// -> undefined
|
||||
```
|
||||
|
||||
### .deleteComments()
|
||||
|
||||
Delete and return comments for all positions.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
chess.loadPgn(
|
||||
"1. e4 e5 {king's pawn opening} 2. Nf3 Nc6 3. Bc4 Bc5 {giuoco piano} *"
|
||||
)
|
||||
|
||||
chess.deleteComments()
|
||||
// -> [
|
||||
// {
|
||||
// fen: "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2",
|
||||
// comment: "king's pawn opening"
|
||||
// },
|
||||
// {
|
||||
// fen: "r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3",
|
||||
// comment: "giuoco piano"
|
||||
// }
|
||||
// ]
|
||||
|
||||
chess.getComments()
|
||||
// -> []
|
||||
```
|
||||
|
||||
### .fen()
|
||||
|
||||
Returns the FEN string for the current position. Note, the en passant square is
|
||||
only included if the side-to-move can legally capture en passant.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
// make some moves
|
||||
chess.move('e4')
|
||||
chess.move('e5')
|
||||
chess.move('f4')
|
||||
|
||||
chess.fen()
|
||||
// -> 'rnbqkbnr/pppp1ppp/8/4p3/4PP2/8/PPPP2PP/RNBQKBNR b KQkq - 0 2'
|
||||
```
|
||||
|
||||
### .get(square)
|
||||
|
||||
Returns the piece on the square:
|
||||
|
||||
```ts
|
||||
chess.clear()
|
||||
chess.put({ type: chess.PAWN, color: chess.BLACK }, 'a5') // put a black pawn on a5
|
||||
|
||||
chess.get('a5')
|
||||
// -> { type: 'p', color: 'b' },
|
||||
chess.get('a6')
|
||||
// -> null
|
||||
```
|
||||
|
||||
### .getCastlingRights(color)
|
||||
|
||||
Gets the castling rights for the given color. An object is returned which
|
||||
indicates whether the right is available or not for both kingside and queenside.
|
||||
Note this does not indicate if such a move is legal or not in the current
|
||||
position as checks etc. also need to be considered.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
chess.getCastlingRights(BLACK) // black can castle queenside only
|
||||
// -> { 'k': false, 'q': true }
|
||||
```
|
||||
|
||||
### .getComment()
|
||||
|
||||
Retrieve the comment for the current position, if it exists.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
chess.loadPgn('1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 {giuoco piano} *')
|
||||
|
||||
chess.getComment()
|
||||
// -> "giuoco piano"
|
||||
```
|
||||
|
||||
### .getComments()
|
||||
|
||||
Retrieve comments for all positions.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
chess.loadPgn(
|
||||
"1. e4 e5 {king's pawn opening} 2. Nf3 Nc6 3. Bc4 Bc5 {giuoco piano} *"
|
||||
)
|
||||
|
||||
chess.getComments()
|
||||
// -> [
|
||||
// {
|
||||
// fen: "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2",
|
||||
// comment: "king's pawn opening"
|
||||
// },
|
||||
// {
|
||||
// fen: "r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3",
|
||||
// comment: "giuoco piano"
|
||||
// }
|
||||
// ]
|
||||
```
|
||||
|
||||
### .header()
|
||||
|
||||
Allows header information to be added to PGN output. Any number of key/value
|
||||
pairs can be passed to .header().
|
||||
|
||||
```ts
|
||||
chess.header('White', 'Robert James Fischer')
|
||||
chess.header('Black', 'Mikhail Tal')
|
||||
|
||||
// or
|
||||
|
||||
chess.header('White', 'Morphy', 'Black', 'Anderssen', 'Date', '1858-??-??')
|
||||
```
|
||||
|
||||
Calling .header() without any arguments returns the header information as an
|
||||
object.
|
||||
|
||||
```ts
|
||||
chess.header()
|
||||
// -> { White: 'Morphy', Black: 'Anderssen', Date: '1858-??-??' }
|
||||
```
|
||||
|
||||
### .history([ options ])
|
||||
|
||||
Returns a list containing the moves of the current game. Options is an optional
|
||||
parameter which may contain a 'verbose' flag. See .moves() for a description of
|
||||
the verbose move fields. A FEN string of the position _prior_ to the move being
|
||||
made is added to the verbose history output.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
chess.move('e4')
|
||||
chess.move('e5')
|
||||
chess.move('f4')
|
||||
chess.move('exf4')
|
||||
|
||||
chess.history()
|
||||
// -> ['e4', 'e5', 'f4', 'exf4']
|
||||
|
||||
chess.history({ verbose: true })
|
||||
// -->
|
||||
// [
|
||||
// {
|
||||
// before: 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',
|
||||
// after: 'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1',
|
||||
// color: 'w',
|
||||
// piece: 'p',
|
||||
// from: 'e2',
|
||||
// to: 'e4',
|
||||
// san: 'e4',
|
||||
// lan: 'e2e4',
|
||||
// flags: 'b'
|
||||
// },
|
||||
// {
|
||||
// before: 'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1',
|
||||
// after: 'rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2',
|
||||
// color: 'b',
|
||||
// piece: 'p',
|
||||
// from: 'e7',
|
||||
// to: 'e5',
|
||||
// san: 'e5',
|
||||
// lan: 'e7e5',
|
||||
// flags: 'b'
|
||||
// },
|
||||
// {
|
||||
// before: 'rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2',
|
||||
// after: 'rnbqkbnr/pppp1ppp/8/4p3/4PP2/8/PPPP2PP/RNBQKBNR b KQkq - 0 2',
|
||||
// color: 'w',
|
||||
// piece: 'p',
|
||||
// from: 'f2',
|
||||
// to: 'f4',
|
||||
// san: 'f4',
|
||||
// lan: 'f2f4',
|
||||
// flags: 'b'
|
||||
// },
|
||||
// {
|
||||
// before: 'rnbqkbnr/pppp1ppp/8/4p3/4PP2/8/PPPP2PP/RNBQKBNR b KQkq - 0 2',
|
||||
// after: 'rnbqkbnr/pppp1ppp/8/8/4Pp2/8/PPPP2PP/RNBQKBNR w KQkq - 0 3',
|
||||
// color: 'b',
|
||||
// piece: 'p',
|
||||
// from: 'e5',
|
||||
// to: 'f4',
|
||||
// san: 'exf4',
|
||||
// lan: 'e5f4',
|
||||
// flags: 'c',
|
||||
// captured: 'p'
|
||||
// }
|
||||
// ]
|
||||
```
|
||||
|
||||
### .inCheck()
|
||||
|
||||
Returns true or false if the side to move is in check.
|
||||
|
||||
```ts
|
||||
const chess = new Chess(
|
||||
'rnb1kbnr/pppp1ppp/8/4p3/5PPq/8/PPPPP2P/RNBQKBNR w KQkq - 1 3'
|
||||
)
|
||||
chess.inCheck()
|
||||
// -> true
|
||||
```
|
||||
|
||||
### .isAttacked(square, color)
|
||||
|
||||
Returns true if the square is attacked by any piece of the given color.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
chess.isAttacked('f3', Chess.WHITE)
|
||||
// -> true (we can attack empty squares)
|
||||
|
||||
chess.isAttacked('f6', Chess.BLACK)
|
||||
// -> true (side to move (e.g. the value returned by .turn) is ignored)
|
||||
|
||||
chess.load(Chess.DEFAULT_POSITION)
|
||||
chess.isAttacked('e2', Chess.WHITE)
|
||||
// -> true (we can attack our own pieces)
|
||||
|
||||
chess.load('4k3/4n3/8/8/8/8/4R3/4K3 w - - 0 1')
|
||||
chess.isAttacked('c6', Chess.BLACK)
|
||||
// -> true (pieces still attack a square if even they are pinned)
|
||||
```
|
||||
|
||||
### .isCheckmate()
|
||||
|
||||
Returns true or false if the side to move has been checkmated.
|
||||
|
||||
```ts
|
||||
const chess = new Chess(
|
||||
'rnb1kbnr/pppp1ppp/8/4p3/5PPq/8/PPPPP2P/RNBQKBNR w KQkq - 1 3'
|
||||
)
|
||||
chess.isCheckmate()
|
||||
// -> true
|
||||
```
|
||||
|
||||
### .isDraw()
|
||||
|
||||
Returns true or false if the game is drawn (50-move rule or insufficient
|
||||
material).
|
||||
|
||||
```ts
|
||||
const chess = new Chess('4k3/4P3/4K3/8/8/8/8/8 b - - 0 78')
|
||||
chess.isDraw()
|
||||
// -> true
|
||||
```
|
||||
|
||||
### .isInsufficientMaterial()
|
||||
|
||||
Returns true if the game is drawn due to insufficient material (K vs. K, K vs.
|
||||
KB, or K vs. KN) otherwise false.
|
||||
|
||||
```ts
|
||||
const chess = new Chess('k7/8/n7/8/8/8/8/7K b - - 0 1')
|
||||
chess.isInsufficientMaterial()
|
||||
// -> true
|
||||
```
|
||||
|
||||
### .isGameOver()
|
||||
|
||||
Returns true if the game has ended via checkmate, stalemate, draw, threefold
|
||||
repetition, or insufficient material. Otherwise, returns false.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
chess.isGameOver()
|
||||
// -> false
|
||||
|
||||
// stalemate
|
||||
chess.load('4k3/4P3/4K3/8/8/8/8/8 b - - 0 78')
|
||||
chess.isGameOver()
|
||||
// -> true
|
||||
|
||||
// checkmate
|
||||
chess.load('rnb1kbnr/pppp1ppp/8/4p3/5PPq/8/PPPPP2P/RNBQKBNR w KQkq - 1 3')
|
||||
chess.isGameOver()
|
||||
// -> true
|
||||
```
|
||||
|
||||
### .isStalemate()
|
||||
|
||||
Returns true or false if the side to move has been stalemated.
|
||||
|
||||
```ts
|
||||
const chess = new Chess('4k3/4P3/4K3/8/8/8/8/8 b - - 0 78')
|
||||
chess.isStalemate()
|
||||
// -> true
|
||||
```
|
||||
|
||||
### .isThreefoldRepetition()
|
||||
|
||||
Returns true or false if the current board position has occurred three or more
|
||||
times.
|
||||
|
||||
```ts
|
||||
const chess = new Chess('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1')
|
||||
// -> true
|
||||
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq occurs 1st time
|
||||
chess.isThreefoldRepetition()
|
||||
// -> false
|
||||
|
||||
chess.move('Nf3') chess.move('Nf6') chess.move('Ng1') chess.move('Ng8')
|
||||
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq occurs 2nd time
|
||||
chess.isThreefoldRepetition()
|
||||
// -> false
|
||||
|
||||
chess.move('Nf3') chess.move('Nf6') chess.move('Ng1') chess.move('Ng8')
|
||||
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq occurs 3rd time
|
||||
chess.isThreefoldRepetition()
|
||||
// -> true
|
||||
```
|
||||
|
||||
### .load(fen)
|
||||
|
||||
Clears the board and loads the provided FEN string. The castling rights, en
|
||||
passant square and move numbers are defaulted to `- - 0 1` if ommitted. Throws
|
||||
an exception if the FEN is invalid.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
chess.load('4r3/8/2p2PPk/1p6/pP2p1R1/P1B5/2P2K2/3r4 w - - 1 45')
|
||||
|
||||
try {
|
||||
chess.load('4r3/8/X12XPk/1p6/pP2p1R1/P1B5/2P2K2/3r4 w - - 1 45')
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
// -> Error: Invalid FEN: piece data is invalid (invalid piece)
|
||||
```
|
||||
|
||||
### .loadPgn(pgn, [ options ])
|
||||
|
||||
Load the moves of a game stored in
|
||||
[Portable Game Notation](http://en.wikipedia.org/wiki/Portable_Game_Notation).
|
||||
`pgn` should be a string. Options is an optional object which may contain a
|
||||
string `newlineChar` and a boolean `strict`.
|
||||
|
||||
The `newlineChar` is a string representation of a valid RegExp fragment and is
|
||||
used to process the PGN. It defaults to `\r?\n`. Special characters should not
|
||||
be pre-escaped, but any literal special characters should be escaped as is
|
||||
normal for a RegExp. Keep in mind that backslashes in JavaScript strings must
|
||||
themselves be escaped (see `sloppyPgn` example below). Avoid using a
|
||||
`newlineChar` that may occur elsewhere in a PGN, such as `.` or `x`, as this
|
||||
will result in unexpected behavior.
|
||||
|
||||
The `strict` flag is a boolean (default: `false`) that instructs chess.js to
|
||||
only parse moves in Standard Algebraic Notation form. See `.move` documentation
|
||||
for more information about non-SAN notations.
|
||||
|
||||
The method will throw and exception if the PGN fails to parse.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
const pgn = [
|
||||
'[Event "Casual Game"]',
|
||||
'[Site "Berlin GER"]',
|
||||
'[Date "1852.??.??"]',
|
||||
'[EventDate "?"]',
|
||||
'[Round "?"]',
|
||||
'[Result "1-0"]',
|
||||
'[White "Adolf Anderssen"]',
|
||||
'[Black "Jean Dufresne"]',
|
||||
'[ECO "C52"]',
|
||||
'[WhiteElo "?"]',
|
||||
'[BlackElo "?"]',
|
||||
'[PlyCount "47"]',
|
||||
'',
|
||||
'1.e4 e5 2.Nf3 Nc6 3.Bc4 Bc5 4.b4 Bxb4 5.c3 Ba5 6.d4 exd4 7.O-O',
|
||||
'd3 8.Qb3 Qf6 9.e5 Qg6 10.Re1 Nge7 11.Ba3 b5 12.Qxb5 Rb8 13.Qa4',
|
||||
'Bb6 14.Nbd2 Bb7 15.Ne4 Qf5 16.Bxd3 Qh5 17.Nf6+ gxf6 18.exf6',
|
||||
'Rg8 19.Rad1 Qxf3 20.Rxe7+ Nxe7 21.Qxd7+ Kxd7 22.Bf5+ Ke8',
|
||||
'23.Bd7+ Kf8 24.Bxe7# 1-0',
|
||||
]
|
||||
|
||||
chess.loadPgn(pgn.join('\n'))
|
||||
|
||||
chess.ascii()
|
||||
// -> ' +------------------------+
|
||||
// 8 | . r . . . k r . |
|
||||
// 7 | p b p B B p . p |
|
||||
// 6 | . b . . . P . . |
|
||||
// 5 | . . . . . . . . |
|
||||
// 4 | . . . . . . . . |
|
||||
// 3 | . . P . . q . . |
|
||||
// 2 | P . . . . P P P |
|
||||
// 1 | . . . R . . K . |
|
||||
// +------------------------+
|
||||
// a b c d e f g h'
|
||||
|
||||
// Parse non-standard move formats and unusual line separators
|
||||
const sloppyPgn = [
|
||||
'[Event "Wijk aan Zee (Netherlands)"]',
|
||||
'[Date "1971.01.26"]',
|
||||
'[Result "1-0"]',
|
||||
'[White "Tigran Vartanovich Petrosian"]',
|
||||
'[Black "Hans Ree"]',
|
||||
'[ECO "A29"]',
|
||||
'',
|
||||
'1. Pc2c4 Pe7e5', // non-standard
|
||||
'2. Nc3 Nf6',
|
||||
'3. Nf3 Nc6',
|
||||
'4. g2g3 Bb4', // non-standard
|
||||
'5. Nd5 Nxd5',
|
||||
'6. c4xd5 e5-e4', // non-standard
|
||||
'7. dxc6 exf3',
|
||||
'8. Qb3 1-0',
|
||||
].join(':')
|
||||
|
||||
chess.loadPgn(sloppyPgn, { newlineChar: ':' })
|
||||
// works by default
|
||||
|
||||
chess.loadPgn(sloppyPgn, { newlineChar: ':', strict: true })
|
||||
// Error: Invalid move in PGN: Pc2c4
|
||||
```
|
||||
|
||||
### .move(move, [ options ])
|
||||
|
||||
Makes a move on the board and returns a move object if the move was legal. The
|
||||
move argument can be either a string in Standard Algebraic Notation (SAN) or a
|
||||
move object. Throws an 'Illegal move' exception if the move was illegal.
|
||||
|
||||
#### .move() - Standard Algebraic Notation (SAN)
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
chess.move('e4')
|
||||
// -> { color: 'w', from: 'e2', to: 'e4', flags: 'b', piece: 'p', san: 'e4' }
|
||||
|
||||
chess.move('nf6') // SAN is case sensitive!!
|
||||
// Error: Invalid move: nf6
|
||||
|
||||
chess.move('Nf6')
|
||||
// -> { color: 'b', from: 'g8', to: 'f6', flags: 'n', piece: 'n', san: 'Nf6' }
|
||||
```
|
||||
|
||||
#### .move() - Object Notation
|
||||
|
||||
A move object contains `to`, `from` and, `promotion` (only when necessary)
|
||||
fields.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
chess.move({ from: 'g2', to: 'g3' })
|
||||
// -> { color: 'w', from: 'g2', to: 'g3', flags: 'n', piece: 'p', san: 'g3' }
|
||||
```
|
||||
|
||||
#### .move() - Permissive Parser
|
||||
|
||||
The permissive (default) move parser can be used to parse a variety of
|
||||
non-standard move notations. Users may specify an `{ strict: true }` flag to
|
||||
verify that all supplied moves adhere to the Standard Algebraic Notation
|
||||
specification.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
// permissive parser accepts various forms of algebraic notation
|
||||
chess.move('e2e4')
|
||||
chess.move('e7-e5')
|
||||
chess.move('Pf2-f4')
|
||||
chess.move('ef4') // missing 'x' in capture
|
||||
chess.move('Ng1-f3')
|
||||
chess.move('d7xd6') // ignore 'x' when not a capture
|
||||
chess.move('d4')
|
||||
|
||||
// correctly parses incorrectly disambiguated moves
|
||||
chess.load('r2qkbnr/ppp2ppp/2n5/1B2pQ2/4P3/8/PPP2PPP/RNB1K2R b KQkq - 3 7')
|
||||
|
||||
chess.move('Nge7') // Ne7 is unambiguous because the knight on c6 is pinned
|
||||
chess.undo()
|
||||
chess.move('Nge7', { strict: true }) // strict SAN requires Ne7
|
||||
// Error: Invalid move: Nge7
|
||||
```
|
||||
|
||||
### .moveNumber()
|
||||
|
||||
Returns the current move number.
|
||||
|
||||
```ts
|
||||
chess.load('4r1k1/p1prnpb1/Pp1pq1pp/3Np2P/2P1P3/R4N2/1PP2PP1/3QR1K1 w - - 2 20')
|
||||
chess.moveNumber()
|
||||
// -> 20
|
||||
```
|
||||
|
||||
### .moves({ piece?: Piece, square?: Square, verbose?: Boolean }?)
|
||||
|
||||
Returns a list of legal moves from the current position. This function takes an
|
||||
optional object which can be used to generate detailed move objects or to
|
||||
restrict the move generator to specific squares or pieces.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
chess.moves()
|
||||
// -> ['a3', 'a4', 'b3', 'b4', 'c3', 'c4', 'd3', 'd4', 'e3', 'e4',
|
||||
// 'f3', 'f4', 'g3', 'g4', 'h3', 'h4', 'Na3', 'Nc3', 'Nf3', 'Nh3']
|
||||
|
||||
chess.moves({ square: 'e2' }) // single square move generation
|
||||
// -> ['e3', 'e4']
|
||||
|
||||
chess.moves({ piece: 'n' }) // generate moves for piece type
|
||||
// ['Na3', 'Nc3', 'Nf3', 'Nh3']
|
||||
|
||||
chess.moves({ verbose: true }) // return verbose moves
|
||||
// -> [{ color: 'w', from: 'a2', to: 'a3',
|
||||
// flags: 'n', piece: 'p',
|
||||
// san 'a3', 'lan', 'a2a3',
|
||||
// before: 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
|
||||
// after: 'rnbqkbnr/pppppppp/8/8/8/P7/1PPPPPPP/RNBQKBNR b KQkq - 0 1'
|
||||
// # a `captured` field is included when the move is a capture
|
||||
// # a `promotion` field is included when the move is a promotion
|
||||
// },
|
||||
// ...
|
||||
// ]
|
||||
```
|
||||
|
||||
#### Move Objects (e.g. when { verbose: true })
|
||||
|
||||
The `color` field indicates the color of the moving piece (`w` or `b`).
|
||||
|
||||
The `from` and `to` fields are from and to squares in algebraic notation.
|
||||
|
||||
The `piece`, `captured`, and `promotion` fields contain the lowercase
|
||||
representation of the applicable piece (`pnbrqk`). The `captured` and
|
||||
`promotion` fields are only present when the move is a valid capture or
|
||||
promotion.
|
||||
|
||||
The `san` field is the move in Standard Algebraic Notation (SAN). The `lan`
|
||||
field is the move in Long Algebraic Notation (LAN).
|
||||
|
||||
The `before` and `after` keys contain the FEN of the position before and after
|
||||
the move.
|
||||
|
||||
The `flags` field contains one or more of the string values:
|
||||
|
||||
- `n` - a non-capture
|
||||
- `b` - a pawn push of two squares
|
||||
- `e` - an en passant capture
|
||||
- `c` - a standard capture
|
||||
- `p` - a promotion
|
||||
- `k` - kingside castling
|
||||
- `q` - queenside castling
|
||||
|
||||
A `flags` value of `pc` would mean that a pawn captured a piece on the 8th rank
|
||||
and promoted.
|
||||
|
||||
### .pgn([ options ])
|
||||
|
||||
Returns the game in PGN format. Options is an optional parameter which may
|
||||
include max width and/or a newline character settings.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
chess.header('White', 'Plunky', 'Black', 'Plinkie')
|
||||
chess.move('e4')
|
||||
chess.move('e5')
|
||||
chess.move('Nc3')
|
||||
chess.move('Nc6')
|
||||
|
||||
chess.pgn({ maxWidth: 5, newline: '<br />' })
|
||||
// -> '[White "Plunky"]<br />[Black "Plinkie"]<br /><br />1. e4 e5<br />2. Nc3 Nc6'
|
||||
```
|
||||
|
||||
### .put(piece, square)
|
||||
|
||||
Place a piece on the square where piece is an object with the form { type: ...,
|
||||
color: ... }. Returns true if the piece was successfully placed, otherwise, the
|
||||
board remains unchanged and false is returned. `put()` will fail when passed an
|
||||
invalid piece or square, or when two or more kings of the same color are placed.
|
||||
|
||||
```ts
|
||||
chess.clear()
|
||||
|
||||
chess.put({ type: chess.PAWN, color: chess.BLACK }, 'a5') // put a black pawn on a5
|
||||
// -> true
|
||||
chess.put({ type: 'k', color: 'w' }, 'h1') // shorthand
|
||||
// -> true
|
||||
|
||||
chess.fen()
|
||||
// -> '8/8/8/p7/8/8/8/7K w - - 0 0'
|
||||
|
||||
chess.put({ type: 'z', color: 'w' }, 'a1') // invalid piece
|
||||
// -> false
|
||||
|
||||
chess.clear()
|
||||
|
||||
chess.put({ type: 'k', color: 'w' }, 'a1')
|
||||
// -> true
|
||||
|
||||
chess.put({ type: 'k', color: 'w' }, 'h1') // fail - two kings
|
||||
// -> false
|
||||
```
|
||||
|
||||
### .remove(square)
|
||||
|
||||
Remove and return the piece on _square_.
|
||||
|
||||
```ts
|
||||
chess.clear()
|
||||
chess.put({ type: chess.PAWN, color: chess.BLACK }, 'a5') // put a black pawn on a5
|
||||
chess.put({ type: chess.KING, color: chess.WHITE }, 'h1') // put a white king on h1
|
||||
|
||||
chess.remove('a5')
|
||||
// -> { type: 'p', color: 'b' },
|
||||
chess.remove('h1')
|
||||
// -> { type: 'k', color: 'w' },
|
||||
chess.remove('e1')
|
||||
// -> null
|
||||
```
|
||||
|
||||
### .reset()
|
||||
|
||||
Reset the board to the initial starting position.
|
||||
|
||||
### .setCastlingRights(color, rights)
|
||||
|
||||
Sets the castling rights for the given color. Returns true if the change was
|
||||
successfully made. False will be returned when the position doesn't allow the
|
||||
requested change i.e. if the corresponding king or rook is not on it's starting
|
||||
square.
|
||||
|
||||
```ts
|
||||
// white can't castle kingside but can castle queenside
|
||||
chess.setCastlingRights(WHITE, { [chess.KING]: false, [chess.QUEEN]: true })
|
||||
```
|
||||
|
||||
### .setComment(comment)
|
||||
|
||||
Comment on the current position.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
chess.move('e4')
|
||||
chess.setComment("king's pawn opening")
|
||||
|
||||
chess.pgn()
|
||||
// -> "1. e4 {king's pawn opening}"
|
||||
```
|
||||
|
||||
### .squareColor(square)
|
||||
|
||||
Returns the color of the square ('light' or 'dark').
|
||||
|
||||
```ts
|
||||
const chess = Chess()
|
||||
chess.squareColor('h1')
|
||||
// -> 'light'
|
||||
chess.squareColor('a7')
|
||||
// -> 'dark'
|
||||
chess.squareColor('bogus square')
|
||||
// -> null
|
||||
```
|
||||
|
||||
### .turn()
|
||||
|
||||
Returns the current side to move.
|
||||
|
||||
```ts
|
||||
chess.load('rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1')
|
||||
chess.turn()
|
||||
// -> 'b'
|
||||
```
|
||||
|
||||
### .undo()
|
||||
|
||||
Takeback the last half-move, returning a move object if successful, otherwise
|
||||
null.
|
||||
|
||||
```ts
|
||||
const chess = new Chess()
|
||||
|
||||
chess.fen()
|
||||
// -> 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
|
||||
chess.move('e4')
|
||||
chess.fen()
|
||||
// -> 'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1'
|
||||
|
||||
chess.undo()
|
||||
// {
|
||||
// color: 'w',
|
||||
// piece: 'p',
|
||||
// from: 'e2',
|
||||
// to: 'e4',
|
||||
// san: 'e4',
|
||||
// flags: 'b',
|
||||
// lan: 'e2e4',
|
||||
// before: 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',
|
||||
// after: 'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1'
|
||||
// }
|
||||
|
||||
chess.fen()
|
||||
// -> 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
|
||||
chess.undo()
|
||||
// -> null
|
||||
```
|
||||
|
||||
### .validateFen(fen):
|
||||
|
||||
Returns a validation object specifying validity or the errors found within the
|
||||
FEN string.
|
||||
|
||||
```ts
|
||||
chess.validateFen('2n1r3/p1k2pp1/B1p3b1/P7/5bP1/2N1B3/1P2KP2/2R5 b - - 4 25')
|
||||
// -> { ok: true }
|
||||
|
||||
chess.validateFen('4r3/8/X12XPk/1p6/pP2p1R1/P1B5/2P2K2/3r4 w - - 1 45')
|
||||
// -> { ok: false,
|
||||
// error: '1st field (piece positions) is invalid [invalid piece].' }
|
||||
```
|
||||
@@ -1,230 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright (c) 2023, Jeff Hlywa (jhlywa@gmail.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
export declare const WHITE = "w";
|
||||
export declare const BLACK = "b";
|
||||
export declare const PAWN = "p";
|
||||
export declare const KNIGHT = "n";
|
||||
export declare const BISHOP = "b";
|
||||
export declare const ROOK = "r";
|
||||
export declare const QUEEN = "q";
|
||||
export declare const KING = "k";
|
||||
export declare type Color = 'w' | 'b';
|
||||
export declare type PieceSymbol = 'p' | 'n' | 'b' | 'r' | 'q' | 'k';
|
||||
export declare type Square = 'a8' | 'b8' | 'c8' | 'd8' | 'e8' | 'f8' | 'g8' | 'h8' | 'a7' | 'b7' | 'c7' | 'd7' | 'e7' | 'f7' | 'g7' | 'h7' | 'a6' | 'b6' | 'c6' | 'd6' | 'e6' | 'f6' | 'g6' | 'h6' | 'a5' | 'b5' | 'c5' | 'd5' | 'e5' | 'f5' | 'g5' | 'h5' | 'a4' | 'b4' | 'c4' | 'd4' | 'e4' | 'f4' | 'g4' | 'h4' | 'a3' | 'b3' | 'c3' | 'd3' | 'e3' | 'f3' | 'g3' | 'h3' | 'a2' | 'b2' | 'c2' | 'd2' | 'e2' | 'f2' | 'g2' | 'h2' | 'a1' | 'b1' | 'c1' | 'd1' | 'e1' | 'f1' | 'g1' | 'h1';
|
||||
export declare const DEFAULT_POSITION = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
||||
export declare type Piece = {
|
||||
color: Color;
|
||||
type: PieceSymbol;
|
||||
};
|
||||
declare type InternalMove = {
|
||||
color: Color;
|
||||
from: number;
|
||||
to: number;
|
||||
piece: PieceSymbol;
|
||||
captured?: PieceSymbol;
|
||||
promotion?: PieceSymbol;
|
||||
flags: number;
|
||||
};
|
||||
export declare type Move = {
|
||||
color: Color;
|
||||
from: Square;
|
||||
to: Square;
|
||||
piece: PieceSymbol;
|
||||
captured?: PieceSymbol;
|
||||
promotion?: PieceSymbol;
|
||||
flags: string;
|
||||
san: string;
|
||||
lan: string;
|
||||
before: string;
|
||||
after: string;
|
||||
};
|
||||
export declare const SQUARES: Square[];
|
||||
export declare function validateFen(fen: string): {
|
||||
ok: boolean;
|
||||
error: string;
|
||||
} | {
|
||||
ok: boolean;
|
||||
error?: undefined;
|
||||
};
|
||||
export declare class Chess {
|
||||
private _board;
|
||||
private _turn;
|
||||
private _header;
|
||||
private _kings;
|
||||
private _epSquare;
|
||||
private _halfMoves;
|
||||
private _moveNumber;
|
||||
private _history;
|
||||
private _comments;
|
||||
private _castling;
|
||||
constructor(fen?: string);
|
||||
clear(keepHeaders?: boolean): void;
|
||||
removeHeader(key: string): void;
|
||||
load(fen: string, keepHeaders?: boolean): void;
|
||||
fen(): string;
|
||||
private _updateSetup;
|
||||
reset(): void;
|
||||
get(square: Square): Piece;
|
||||
put({ type, color }: {
|
||||
type: PieceSymbol;
|
||||
color: Color;
|
||||
}, square: Square): boolean;
|
||||
remove(square: Square): Piece;
|
||||
_updateCastlingRights(): void;
|
||||
_updateEnPassantSquare(): void;
|
||||
_attacked(color: Color, square: number): boolean;
|
||||
private _isKingAttacked;
|
||||
isAttacked(square: Square, attackedBy: Color): boolean;
|
||||
isCheck(): boolean;
|
||||
inCheck(): boolean;
|
||||
isCheckmate(): boolean;
|
||||
isStalemate(): boolean;
|
||||
isInsufficientMaterial(): boolean;
|
||||
isThreefoldRepetition(): boolean;
|
||||
isDraw(): boolean;
|
||||
isGameOver(): boolean;
|
||||
moves(): string[];
|
||||
moves({ square }: {
|
||||
square: Square;
|
||||
}): string[];
|
||||
moves({ piece }: {
|
||||
piece: PieceSymbol;
|
||||
}): string[];
|
||||
moves({ square, piece }: {
|
||||
square: Square;
|
||||
piece: PieceSymbol;
|
||||
}): string[];
|
||||
moves({ verbose, square }: {
|
||||
verbose: true;
|
||||
square?: Square;
|
||||
}): Move[];
|
||||
moves({ verbose, square }: {
|
||||
verbose: false;
|
||||
square?: Square;
|
||||
}): string[];
|
||||
moves({ verbose, square, }: {
|
||||
verbose?: boolean;
|
||||
square?: Square;
|
||||
}): string[] | Move[];
|
||||
moves({ verbose, piece }: {
|
||||
verbose: true;
|
||||
piece?: PieceSymbol;
|
||||
}): Move[];
|
||||
moves({ verbose, piece }: {
|
||||
verbose: false;
|
||||
piece?: PieceSymbol;
|
||||
}): string[];
|
||||
moves({ verbose, piece, }: {
|
||||
verbose?: boolean;
|
||||
piece?: PieceSymbol;
|
||||
}): string[] | Move[];
|
||||
moves({ verbose, square, piece, }: {
|
||||
verbose: true;
|
||||
square?: Square;
|
||||
piece?: PieceSymbol;
|
||||
}): Move[];
|
||||
moves({ verbose, square, piece, }: {
|
||||
verbose: false;
|
||||
square?: Square;
|
||||
piece?: PieceSymbol;
|
||||
}): string[];
|
||||
moves({ verbose, square, piece, }: {
|
||||
verbose?: boolean;
|
||||
square?: Square;
|
||||
piece?: PieceSymbol;
|
||||
}): string[] | Move[];
|
||||
moves({ square, piece }: {
|
||||
square?: Square;
|
||||
piece?: PieceSymbol;
|
||||
}): Move[];
|
||||
_moves({ legal, piece, square, }?: {
|
||||
legal?: boolean;
|
||||
piece?: PieceSymbol;
|
||||
square?: Square;
|
||||
}): InternalMove[];
|
||||
move(move: string | {
|
||||
from: string;
|
||||
to: string;
|
||||
promotion?: string;
|
||||
}, { strict }?: {
|
||||
strict?: boolean;
|
||||
}): Move;
|
||||
_push(move: InternalMove): void;
|
||||
private _makeMove;
|
||||
undo(): Move | null;
|
||||
private _undoMove;
|
||||
pgn({ newline, maxWidth, }?: {
|
||||
newline?: string;
|
||||
maxWidth?: number;
|
||||
}): string;
|
||||
header(...args: string[]): Record<string, string>;
|
||||
loadPgn(pgn: string, { strict, newlineChar, }?: {
|
||||
strict?: boolean;
|
||||
newlineChar?: string;
|
||||
}): void;
|
||||
private _moveToSan;
|
||||
private _moveFromSan;
|
||||
ascii(): string;
|
||||
perft(depth: number): number;
|
||||
private _makePretty;
|
||||
turn(): Color;
|
||||
board(): ({
|
||||
square: Square;
|
||||
type: PieceSymbol;
|
||||
color: Color;
|
||||
} | null)[][];
|
||||
squareColor(square: Square): "light" | "dark" | null;
|
||||
history(): string[];
|
||||
history({ verbose }: {
|
||||
verbose: true;
|
||||
}): Move[];
|
||||
history({ verbose }: {
|
||||
verbose: false;
|
||||
}): string[];
|
||||
history({ verbose }: {
|
||||
verbose: boolean;
|
||||
}): string[] | Move[];
|
||||
private _pruneComments;
|
||||
getComment(): string;
|
||||
setComment(comment: string): void;
|
||||
deleteComment(): string;
|
||||
getComments(): {
|
||||
fen: string;
|
||||
comment: string;
|
||||
}[];
|
||||
deleteComments(): {
|
||||
fen: string;
|
||||
comment: string;
|
||||
}[];
|
||||
setCastlingRights(color: Color, rights: Partial<Record<typeof KING | typeof QUEEN, boolean>>): boolean;
|
||||
getCastlingRights(color: Color): {
|
||||
k: boolean;
|
||||
q: boolean;
|
||||
};
|
||||
moveNumber(): number;
|
||||
}
|
||||
export {};
|
||||
@@ -1,7 +0,0 @@
|
||||
/** @type {import('@ts-jest/dist/types').InitialOptionsTsJest} */
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
setupFilesAfterEnv: ['jest-extended/all'],
|
||||
testRegex: '/__tests__/.*(\\.|/)(test|spec)\\.[jt]sx?$',
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"name": "chess.js",
|
||||
"version": "1.0.0-beta.6",
|
||||
"license": "BSD-2-Clause",
|
||||
"main": "dist/cjs/chess.js",
|
||||
"module": "dist/esm/chess.js",
|
||||
"types": "dist/types/chess.d.ts",
|
||||
"homepage": "https://github.com/jhlywa/chess.js",
|
||||
"author": "Jeff Hlywa <jhlywa@gmail.com>",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"lint": "eslint src/ --ext .ts",
|
||||
"build": "tsc -b ./tsconfig.cjs.json ./tsconfig.esm.json ./tsconfig.types.json",
|
||||
"clean": "rm -rf ./dist"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jhlywa/chess.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.4.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.17.0",
|
||||
"@typescript-eslint/parser": "^5.17.0",
|
||||
"eslint": "^8.12.0",
|
||||
"jest": "^27.0.6",
|
||||
"jest-extended": "^2.0.0",
|
||||
"ts-jest": "^27.0.4",
|
||||
"typescript": "^4.6.3"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/cjs",
|
||||
"module": "commonjs"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/esm",
|
||||
"module": "esnext"
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node",
|
||||
"removeComments": false,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"target": "ESNext"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/types",
|
||||
"declaration": true,
|
||||
"emitDeclarationOnly": true
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
# chessboard.js Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [1.0.0] - 2019-06-11
|
||||
- Orientation methods now return current orientation. [Issue #64]
|
||||
- Drop support for IE8
|
||||
- Do not check for `window.JSON` (Error #1004)
|
||||
- Rename `ChessBoard` to `Chessboard` (`ChessBoard` is still supported, however)
|
||||
- id query selectors are now supported as the first argument to `Chessboard()`
|
||||
- Remove Error #1002
|
||||
- Format code according to [StandardJS]
|
||||
- Bump minimum jQuery version to 1.8.3
|
||||
- Throttle piece drag functions
|
||||
|
||||
## [0.3.0] - 2013-08-10
|
||||
- Added `appearSpeed` animation config property
|
||||
- Added `onSnapbackEnd` event
|
||||
- Added `onMoveEnd` event
|
||||
|
||||
## [0.2.0] - 2013-08-05
|
||||
- Added `onMouseoverSquare` and `onMouseoutSquare` events
|
||||
- Added `onSnapEnd` event
|
||||
- Added square code as CSS class on the squares
|
||||
- Added [chess.js] integration examples
|
||||
|
||||
## [0.1.0] - 2013-05-21
|
||||
- Initial release
|
||||
|
||||
[chess.js]:https://github.com/jhlywa/chess.js
|
||||
[Issue #64]:https://github.com/oakmac/chessboardjs/issues/64
|
||||
[StandardJS]:https://standardjs.com/
|
||||
@@ -1,20 +0,0 @@
|
||||
Copyright 2019 Chris Oakman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,82 +0,0 @@
|
||||
# chessboard.js
|
||||
|
||||
chessboard.js is a JavaScript chessboard component. It depends on [jQuery].
|
||||
|
||||
Please see [chessboardjs.com] for documentation and examples.
|
||||
|
||||
## What is chessboard.js?
|
||||
|
||||
chessboard.js is a JavaScript chessboard component with a flexible "just a
|
||||
board" API that
|
||||
|
||||
chessboard.js is a standalone JavaScript Chess Board. It is designed to be "just
|
||||
a board" and expose a powerful API so that it can be used in different ways.
|
||||
Here's a non-exhaustive list of things you can do with chessboard.js:
|
||||
|
||||
- Use chessboard.js to show game positions alongside your expert commentary.
|
||||
- Use chessboard.js to have a tactics website where users have to guess the best
|
||||
move.
|
||||
- Integrate chessboard.js and [chess.js] with a PGN database and allow people to
|
||||
search and playback games (see [Example 5000])
|
||||
- Build a chess server and have users play their games out using the
|
||||
chessboard.js board.
|
||||
|
||||
chessboard.js is flexible enough to handle any of these situations with relative
|
||||
ease.
|
||||
|
||||
## What can chessboard.js **not** do?
|
||||
|
||||
The scope of chessboard.js is limited to "just a board." This is intentional and
|
||||
makes chessboard.js flexible for handling a multitude of chess-related problems.
|
||||
|
||||
This is a common source of confusion for new users. [remove?]
|
||||
|
||||
Specifically, chessboard.js does not understand anything about how the game of
|
||||
chess is played: how a knight moves, who's turn is it, is White in check?, etc.
|
||||
|
||||
Fortunately, the powerful [chess.js] library deals with exactly this sort of
|
||||
problem domain and plays nicely with chessboard.js's flexible API. Some examples
|
||||
of chessboard.js combined with chess.js: 5000, 5001, 5002
|
||||
|
||||
Please see the powerful [chess.js] library for an API to deal with these sorts
|
||||
of questions.
|
||||
|
||||
|
||||
This logic is distinct from the logic of the board. Please see the powerful
|
||||
[chess.js] library for this aspect of your application.
|
||||
|
||||
|
||||
|
||||
Here is a list of things that chessboard.js is **not**:
|
||||
|
||||
- A chess engine
|
||||
- A legal move validator
|
||||
- A PGN parser
|
||||
|
||||
chessboard.js is designed to work well with any of those things, but the idea
|
||||
behind chessboard.js is that the logic that controls the board should be
|
||||
independent of those other problems.
|
||||
|
||||
## Docs and Examples
|
||||
|
||||
- Docs - <http://chessboardjs.com/docs>
|
||||
- Examples - <http://chessboardjs.com/examples>
|
||||
|
||||
## Developer Tools
|
||||
|
||||
```sh
|
||||
# create a build in the build/ directory
|
||||
npm run build
|
||||
|
||||
# re-build the website
|
||||
npm run website
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](LICENSE.md)
|
||||
|
||||
[jQuery]:https://jquery.com/
|
||||
[chessboardjs.com]:http://chessboardjs.com
|
||||
[chess.js]:https://github.com/jhlywa/chess.js
|
||||
[Example 5000]:http://chessboardjs.com/examples#5000
|
||||
@@ -1,54 +0,0 @@
|
||||
/*! chessboard.js v1.0.0 | (c) 2019 Chris Oakman | MIT License chessboardjs.com/license */
|
||||
|
||||
.clearfix-7da63 {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.board-b72b1 {
|
||||
border: 2px solid #404040;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.square-55d63 {
|
||||
float: left;
|
||||
position: relative;
|
||||
|
||||
/* disable any native browser highlighting */
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.white-1e1d7 {
|
||||
background-color: #f0d9b5;
|
||||
color: #b58863;
|
||||
}
|
||||
|
||||
.black-3c85d {
|
||||
background-color: #b58863;
|
||||
color: #f0d9b5;
|
||||
}
|
||||
|
||||
.highlight1-32417, .highlight2-9c5d2 {
|
||||
box-shadow: inset 0 0 3px 3px yellow;
|
||||
}
|
||||
|
||||
.notation-322f9 {
|
||||
cursor: default;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.alpha-d2270 {
|
||||
bottom: 1px;
|
||||
right: 3px;
|
||||
}
|
||||
|
||||
.numeric-fc462 {
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
/*! chessboard.js v1.0.0 | (c) 2019 Chris Oakman | MIT License chessboardjs.com/license */
|
||||
.clearfix-7da63{clear:both}.board-b72b1{border:2px solid #404040;box-sizing:content-box}.square-55d63{float:left;position:relative;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.white-1e1d7{background-color:#f0d9b5;color:#b58863}.black-3c85d{background-color:#b58863;color:#f0d9b5}.highlight1-32417,.highlight2-9c5d2{box-shadow:inset 0 0 3px 3px #ff0}.notation-322f9{cursor:default;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;position:absolute}.alpha-d2270{bottom:1px;right:3px}.numeric-fc462{top:2px;left:2px}
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"author": "Chris Oakman <chris@oakmac.com> (http://chrisoakman.com/)",
|
||||
"name": "@chrisoakman/chessboardjs",
|
||||
"description": "JavaScript chessboard widget",
|
||||
"homepage": "https://chessboardjs.com",
|
||||
"license": "MIT",
|
||||
"version": "1.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/oakmac/chessboardjs.git"
|
||||
},
|
||||
"files": ["dist/"],
|
||||
"dependencies": {
|
||||
"jquery": ">=3.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"csso": "3.5.1",
|
||||
"fs-plus": "3.1.1",
|
||||
"kidif": "1.1.0",
|
||||
"mustache": "2.3.0",
|
||||
"standard": "10.0.2",
|
||||
"uglify-js": "3.6.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "standard lib/chessboard.js && node scripts/build.js",
|
||||
"standard": "standard --fix lib/*.js website/js/*.js",
|
||||
"website": "node scripts/website.js"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 777 B After Width: | Height: | Size: 777 B |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 748 B After Width: | Height: | Size: 748 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -1,21 +0,0 @@
|
||||
|
||||
Copyright OpenJS Foundation and other contributors, https://openjsf.org/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "wwwroot",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "chess.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@chrisoakman/chessboardjs": "^1.0.0",
|
||||
"bootstrap": "^5.3.2",
|
||||
"chess.js": "^1.0.0-beta.6",
|
||||
"jquery": "^3.7.1"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Chess} from "/chess.js/dist/esm/chess.js";
|
||||
import { Chess } from "/node_modules/chess.js/dist/esm/chess.js";
|
||||
|
||||
const statusControl = $('#status');
|
||||
const fenControl = $('#fen');
|
||||
|
||||