Fix Musketeer, Joker, Shinobi. Start draft of Cwda
[vchess.git] / client / src / utils / printDiagram.js
1 import { ArrayFun } from "@/utils/array";
2 import { store } from "@/store";
3
4 // Turn (human) marks into coordinates
5 function getMarkArray(marks) {
6 if (!marks || marks == "-") return [];
7 let markArray = ArrayFun.init(V.size.x, V.size.y, false);
8 const squares = marks.split(",");
9 for (let i = 0; i < squares.length; i++) {
10 const coords = V.SquareToCoords(squares[i]);
11 markArray[coords.x][coords.y] = true;
12 }
13 return markArray;
14 }
15
16 // Turn (human) shadow indications into coordinates
17 function getShadowArray(shadow) {
18 if (!shadow || shadow == "-") return [];
19 let shadowArray = ArrayFun.init(V.size.x, V.size.y, false);
20 const squares = shadow.split(",");
21 for (let i = 0; i < squares.length; i++) {
22 const rownum = V.size.x - parseInt(squares[i], 10);
23 if (!isNaN(rownum)) {
24 // Shadow a full row
25 for (let i = 0; i < V.size.y; i++) shadowArray[rownum][i] = true;
26 continue;
27 }
28 if (squares[i].length == 1) {
29 // Shadow a full column
30 const colnum = V.ColumnToCoord(squares[i]);
31 for (let i = 0; i < V.size.x; i++) shadowArray[i][colnum] = true;
32 continue;
33 }
34 if (squares[i].indexOf("-") >= 0) {
35 // Shadow a range of squares, horizontally or vertically
36 const firstLastSq = squares[i].split("-");
37 const range = [
38 V.SquareToCoords(firstLastSq[0]),
39 V.SquareToCoords(firstLastSq[1])
40 ];
41 const step = [
42 range[1].x == range[0].x
43 ? 0
44 : (range[1].x - range[0].x) / Math.abs(range[1].x - range[0].x),
45 range[1].y == range[0].y
46 ? 0
47 : (range[1].y - range[0].y) / Math.abs(range[1].y - range[0].y)
48 ];
49 // Convention: range always from smaller to larger number
50 for (
51 let x = range[0].x, y = range[0].y;
52 x <= range[1].x && y <= range[1].y;
53 x += step[0], y += step[1]
54 ) {
55 shadowArray[x][y] = true;
56 }
57 continue;
58 }
59 // Shadow just one square:
60 const coords = V.SquareToCoords(squares[i]);
61 shadowArray[coords.x][coords.y] = true;
62 }
63 return shadowArray;
64 }
65
66 // args: object with position (mandatory), and
67 // orientation, marks, shadow (optional)
68 // TODO: in time, find a strategy to draw middle lines (weiqi, xianqi...)
69 // and maybe also some diagonals (fanorona...)
70 // https://stackoverflow.com/questions/40697231/horizontal-line-in-the-middle-of-divs
71 // + CSS rotate?
72 export function getDiagram(args) {
73 // Obtain the array of pieces images names:
74 const board = V.GetBoard(args.position);
75 const orientation = args.orientation || "w";
76 const markArray = getMarkArray(args.marks);
77 const shadowArray = getShadowArray(args.shadow);
78 const vr = new V(); //just for pieces images paths
79 let boardDiv = "";
80 const [startX, startY, inc] =
81 orientation == "w" ? [0, 0, 1] : [V.size.x - 1, V.size.y - 1, -1];
82 for (let i = startX; i >= 0 && i < V.size.x; i += inc) {
83 boardDiv += "<div class='row";
84 if (i == startX && V.Monochrome) boardDiv += " border-top";
85 boardDiv += "'>";
86 for (let j = startY; j >= 0 && j < V.size.y; j += inc) {
87 boardDiv += "<div class='board board" + V.size.y + " ";
88 if (V.Monochrome) {
89 boardDiv += "monochrome " +
90 (V.Notoodark ? "middle-square" : "dark-square");
91 if (j == startY) boardDiv += " border-left";
92 }
93 else {
94 const oddity = (i + j) % 2;
95 if (
96 (oddity == 0 && !V.DarkBottomRight) ||
97 (oddity == 1 && V.DarkBottomRight)
98 ) {
99 boardDiv += "light-square";
100 }
101 else boardDiv += "dark-square";
102 }
103 boardDiv += " " + store.state.settings.bcolor;
104 if (shadowArray.length > 0 && shadowArray[i][j])
105 boardDiv += " in-shadow";
106 boardDiv += "'>";
107 if (board[i][j] != V.EMPTY) {
108 boardDiv +=
109 "<img " +
110 "src='/images/pieces/" +
111 vr.getPpath(board[i][j], null, null, orientation) +
112 V.IMAGE_EXTENSION + "' " +
113 "class='piece'/>";
114 }
115 if (markArray.length > 0 && markArray[i][j])
116 boardDiv += "<img src='/images/diag_mark.svg' class='mark-square'/>";
117 boardDiv += "</div>";
118 }
119 boardDiv += "</div>";
120 }
121 return boardDiv;
122 }
123
124 // Method to replace diagrams in loaded HTML
125 export function replaceByDiag(match, p1, p2) {
126 const diagParts = p2.split(" ");
127 return getDiagram({
128 position: diagParts[0],
129 marks: diagParts[1],
130 orientation: diagParts[2],
131 shadow: diagParts[3]
132 });
133 }