Skip to main content

jja/
ctg.rs

1//
2// jja: swiss army knife for chess file formats
3// src/ctg.rs: CTG constants and utilities
4//
5// Copyright (c) 2023 Ali Polatel <alip@chesswob.org>
6// Based in part upon remoteglot which is:
7//     Copyright 2007 Steinar H. Gunderson <steinar+remoteglot@gunderson.no>
8//     Licensed under the GNU General Public License, version 2.
9//
10// SPDX-License-Identifier: GPL-3.0-or-later
11
12use std::{
13    fmt::{self, Display, Formatter},
14    io::{Error, ErrorKind},
15};
16
17use console::style;
18use shakmaty::{uci::Uci, Board, Color, Role, Square};
19
20/// A structure representing page boundaries.
21#[derive(Debug)]
22pub struct PageBounds {
23    /// Padding
24    pub pad: i32,
25    /// Low page bound
26    pub low: i32,
27    /// High page bound
28    pub high: i32,
29}
30
31/// A structure representing a chess board.
32#[derive(Debug, Clone, Eq, PartialEq)]
33pub struct ByteBoard {
34    /// Chess board represented as a set of bytes.
35    pub bytes: [u8; 64],
36}
37
38/// An enumeration representing Numeric Annotation Glyphs (NAGs)
39///
40/// # NAG Groupings
41///
42/// - `$0`: provided for the convenience of software designers as a placeholder value; should not
43/// appear in PGN files and has no typographic representation.
44/// - `$1-$9`: Move assessments (used by jja for weight/priority calculation during CTG->{BIN,ABK}
45/// conversion)
46/// - `$10-$135`: Positional assessments
47/// - `$136-$139`: Time Pressure Commentaries
48/// - `$140+`: not defined (some non-standard NAGs defined in this range)
49#[derive(Debug, Eq, PartialEq, Copy, Clone, PartialOrd, Ord)]
50#[repr(u8)]
51pub enum Nag {
52    /// Null annotation
53    Null,
54    /// A good move, commonly known as "!"
55    Good,
56    /// A mistake, commonly known as "?"
57    Mistake,
58    /// A hard move, commonly known as "!!"
59    Hard,
60    /// A blunder, commonly known as "??"
61    Blunder,
62    /// An interesting move, commonly known as "!?"
63    Interesting,
64    /// A dubious move, commonly known as "?!"
65    Dubious,
66    /// A forced move, also known as "□"
67    Forced,
68    /// A singular move (no reasonable alternatives)
69    Only,
70    /// Worst move
71    Worst,
72    /// Drawish position or even
73    Drawish,
74    /// Equal chances, quiet position
75    EqualQuiet,
76    /// Equal chances, active position
77    EqualActive,
78    /// Unclear position
79    Unclear,
80    /// White has a slight advantage
81    SlightEdgeWhite,
82    /// Black has a slight advantage
83    SlightEdgeBlack,
84    /// White has a moderate advantage
85    ModerateAdvantageWhite,
86    /// Black has a moderate advantage
87    ModerateAdvantageBlack,
88    /// White has a decisive advantage
89    DecisiveAdvantageWhite,
90    /// Black has a decisive advantage
91    DecisiveAdvantageBlack,
92    /// White has a crushing advantage (Black should resign)
93    CrushingAdvantageWhite,
94    /// Black has a crushing advantage (White should resign)
95    CrushingAdvantageBlack,
96    /// White is in zugzwang, also known as "⊙"
97    ZugzwangWhite,
98    /// Black is in zugzwang, also known as "⊙"
99    ZugzwangBlack,
100    /// White has a slight space advantage
101    SlightSpaceAdvantageWhite,
102    /// Black has a slight space advantage
103    SlightSpaceAdvantageBlack,
104    /// White has a moderate space advantage, also known as "○"
105    ModerateSpaceAdvantageWhite,
106    /// Black has a moderate space advantage, also known as "○"
107    ModerateSpaceAdvantageBlack,
108    /// White has a decisive space advantage
109    DecisiveSpaceAdvantageWhite,
110    /// Black has a decisive space advantage
111    DecisiveSpaceAdvantageBlack,
112    /// White has a slight time (development) advantage
113    SlightDevelopmentAdvantageWhite,
114    /// Black has a slight time (development) advantage
115    SlightDevelopmentAdvantageBlack,
116    /// White has a moderate time (development) advantage, also known as "⟳"
117    ModerateDevelopmentAdvantageWhite,
118    /// Black has a moderate time (development) advantage, also known as "⟳"
119    ModerateDevelopmentAdvantageBlack,
120    /// White has a decisive time (development) advantage
121    DecisiveDevelopmentAdvantageWhite,
122    /// Black has a decisive time (development) advantage
123    DecisiveDevelopmentAdvantageBlack,
124    /// White has the initiative, also known as "↑"
125    InitiativeWhite,
126    /// Black has the initiative, also known as "↑"
127    InitiativeBlack,
128    /// White has a lasting initiative
129    LastingInitiativeWhite,
130    /// Black has a lasting initiative
131    LastingInitiativeBlack,
132    /// White has the attack, also known as "→"
133    AttackWhite,
134    /// Black has the attack, also known as "→"
135    AttackBlack,
136    /// White has insufficient compensation for material deficit
137    InsufficientCompensationWhite,
138    /// Black has insufficient compensation for material deficit
139    InsufficientCompensationBlack,
140    /// White has sufficient compensation for material deficit, also known as "⯹"
141    SufficientCompensationWhite,
142    /// Black has sufficient compensation for material deficit, also known as "⯹"
143    SufficientCompensationBlack,
144    /// White has more than adequate compensation for material deficit
145    MoreThanAdequateCompensationWhite,
146    /// Black has more than adequate compensation for material deficit
147    MoreThanAdequateCompensationBlack,
148    /// White has a slight center control advantage
149    SlightCenterControlAdvantageWhite,
150    /// Black has a slight center control advantage
151    SlightCenterControlAdvantageBlack,
152    /// White has a moderate center control advantage
153    ModerateCenterControlAdvantageWhite,
154    /// Black has a moderate center control advantage
155    ModerateCenterControlAdvantageBlack,
156    /// White has a decisive center control advantage
157    DecisiveCenterControlAdvantageWhite,
158    /// Black has a decisive center control advantage
159    DecisiveCenterControlAdvantageBlack,
160    /// White has a slight kingside control advantage
161    SlightKingSideControlAdvantageWhite,
162    /// Black has a slight kingside control advantage
163    SlightKingSideControlAdvantageBlack,
164    /// White has a moderate kingside control advantage
165    ModerateKingSideControlAdvantageWhite,
166    /// Black has a moderate kingside control advantage
167    ModerateKingSideControlAdvantageBlack,
168    /// White has a decisive kingside control advantage
169    DecisiveKingSideControlAdvantageWhite,
170    /// Black has a decisive kingside control advantage
171    DecisiveKingSideControlAdvantageBlack,
172    /// White has a slight queenside control advantage
173    SlightQueenSideControlAdvantageWhite,
174    /// Black has a slight queenside control advantage
175    SlightQueenSideControlAdvantageBlack,
176    /// White has a moderate queenside control advantage
177    ModerateQueenSideControlAdvantageWhite,
178    /// Black has a moderate queenside control advantage
179    ModerateQueenSideControlAdvantageBlack,
180    /// White has a decisive queenside control advantage
181    DecisiveQueenSideControlAdvantageWhite,
182    /// Black has a decisive queenside control advantage
183    DecisiveQueenSideControlAdvantageBlack,
184    /// White has a vulnerable first rank
185    VulnerableFirstRankWhite,
186    /// Black has a vulnerable first rank
187    VulnerableFirstRankBlack,
188    /// White has a well protected first rank
189    WellProtectedFirstRankWhite,
190    /// Black has a well protected first rank
191    WellProtectedFirstRankBlack,
192    /// White has a poorly protected king
193    PoorlyProtectedKingWhite,
194    /// Black has a poorly protected king
195    PoorlyProtectedKingBlack,
196    /// White has a well protected king
197    WellProtectedKingWhite,
198    /// Black has a well protected king
199    WellProtectedKingBlack,
200    /// White has a poorly placed king
201    PoorlyPlacedKingWhite,
202    /// Black has a poorly placed king
203    PoorlyPlacedKingBlack,
204    /// White has a well placed king
205    WellPlacedKingWhite,
206    /// Black has a well placed king
207    WellPlacedKingBlack,
208    /// White has a very weak pawn structure
209    VeryWeakPawnStructureWhite,
210    /// Black has a very weak pawn structure
211    VeryWeakPawnStructureBlack,
212    /// White has a moderately weak pawn structure
213    ModeratelyWeakPawnStructureWhite,
214    /// Black has a moderately weak pawn structure
215    ModeratelyWeakPawnStructureBlack,
216    /// White has a moderately strong pawn structure
217    ModeratelyStrongPawnStructureWhite,
218    /// Black has a moderately strong pawn structure
219    ModeratelyStrongPawnStructureBlack,
220    /// White has a very strong pawn structure
221    VeryStrongPawnStructureWhite,
222    /// Black has a very strong pawn structure
223    VeryStrongPawnStructureBlack,
224    /// White has poor knight placement
225    PoorKnightPlacementWhite,
226    /// Black has poor knight placement
227    PoorKnightPlacementBlack,
228    /// White has good knight placement
229    GoodKnightPlacementWhite,
230    /// Black has good knight placement
231    GoodKnightPlacementBlack,
232    /// White has poor bishop placement
233    PoorBishopPlacementWhite,
234    /// Black has poor bishop placement
235    PoorBishopPlacementBlack,
236    /// White has good bishop placement
237    GoodBishopPlacementWhite,
238    /// Black has good bishop placement
239    GoodBishopPlacementBlack,
240    /// White has poor rook placement
241    PoorRookPlacementWhite,
242    /// Black has poor rook placement
243    PoorRookPlacementBlack,
244    /// White has good rook placement
245    GoodRookPlacementWhite,
246    /// Black has good rook placement
247    GoodRookPlacementBlack,
248    /// White has poor queen placement
249    PoorQueenPlacementWhite,
250    /// Black has poor queen placement
251    PoorQueenPlacementBlack,
252    /// White has good queen placement
253    GoodQueenPlacementWhite,
254    /// Black has good queen placement
255    GoodQueenPlacementBlack,
256    /// White has poor piece coordination
257    PoorPieceCoordinationWhite,
258    /// Black has poor piece coordination
259    PoorPieceCoordinationBlack,
260    /// White has good piece coordination
261    GoodPieceCoordinationWhite,
262    /// Black has good piece coordination
263    GoodPieceCoordinationBlack,
264    /// White has played the opening very poorly
265    VeryPoorOpeningPlayWhite,
266    /// Black has played the opening very poorly
267    VeryPoorOpeningPlayBlack,
268    /// White has played the opening poorly
269    PoorOpeningPlayWhite,
270    /// Black has played the opening poorly
271    PoorOpeningPlayBlack,
272    /// White has played the opening well
273    WellOpeningPlayWhite,
274    /// Black has played the opening well
275    WellOpeningPlayBlack,
276    /// White has played the opening very well
277    VeryWellOpeningPlayWhite,
278    /// Black has played the opening very well
279    VeryWellOpeningPlayBlack,
280    /// White has played the middlegame very poorly
281    VeryPoorMiddleGamePlayWhite,
282    /// Black has played the middlegame very poorly
283    VeryPoorMiddleGamePlayBlack,
284    /// White has played the middlegame poorly
285    PoorMiddleGamePlayWhite,
286    /// Black has played the middlegame poorly
287    PoorMiddleGamePlayBlack,
288    /// White has played the middlegame well
289    WellMiddleGamePlayWhite,
290    /// Black has played the middlegame well
291    WellMiddleGamePlayBlack,
292    /// White has played the middlegame very well
293    VeryWellMiddleGamePlayWhite,
294    /// Black has played the middlegame very well
295    VeryWellMiddleGamePlayBlack,
296    /// White has played the ending very poorly
297    VeryPoorEndingPlayWhite,
298    /// Black has played the ending very poorly
299    VeryPoorEndingPlayBlack,
300    /// White has played the ending poorly
301    PoorEndingPlayWhite,
302    /// Black has played the ending poorly
303    PoorEndingPlayBlack,
304    /// White has played the ending well
305    WellEndingPlayWhite,
306    /// Black has played the ending well
307    WellEndingPlayBlack,
308    /// White has played the ending very well
309    VeryWellEndingPlayWhite,
310    /// Black has played the ending very well
311    VeryWellEndingPlayBlack,
312    /// White has slight counterplay
313    SlightCounterPlayWhite,
314    /// Black has slight counterplay
315    SlightCounterPlayBlack,
316    /// White has moderate counterplay, also known as "⇆"
317    ModerateCounterPlayWhite,
318    /// Black has moderate counterplay, also known as "⇆"
319    ModerateCounterPlayBlack,
320    /// White has decisive counterplay, also known as "⇆"
321    DecisiveCounterPlayWhite,
322    /// Black has decisive counterplay, also known as "⇆"
323    DecisiveCounterPlayBlack,
324    /// White has moderate time control pressure
325    ModerateTimeControlPressureWhite,
326    /// Black has moderate time control pressure
327    ModerateTimeControlPressureBlack,
328    /// White has severe time control pressure, also known as zeitnot or "⨁"
329    SevereTimeControlPressureWhite,
330    /// Black has severe time control pressure, also known as zeitnot or "⨁"
331    SevereTimeControlPressureBlack,
332    /// With the idea..., also known as "∆"
333    WithTheIdea,
334    /// Aimed against..., also known as "∇"
335    AimedAgainst,
336    /// Better is..., also known as "⌓"
337    BetterIs,
338    /// Worse is..., also known as "<="
339    WorseIs,
340    /// Equivalent is..., also known as "=="
341    EquivalentIs,
342    /// Editorial Comment, also known as "RR"
343    EditorialComment,
344    /// Novelty, also known as "N"
345    Novelty,
346    /// Undefined
347    Nag147,
348    /// Undefined
349    Nag148,
350    /// Undefined
351    Nag149,
352    /// Undefined
353    Nag150,
354    /// Undefined
355    Nag151,
356    /// Undefined
357    Nag152,
358    /// Undefined
359    Nag153,
360    /// Undefined
361    Nag154,
362    /// Undefined
363    Nag155,
364    /// Undefined
365    Nag156,
366    /// Undefined
367    Nag157,
368    /// Undefined
369    Nag158,
370    /// Undefined
371    Nag159,
372    /// Undefined
373    Nag160,
374    /// Undefined
375    Nag161,
376    /// Undefined
377    Nag162,
378    /// Undefined
379    Nag163,
380    /// Undefined
381    Nag164,
382    /// Undefined
383    Nag165,
384    /// Undefined
385    Nag166,
386    /// Undefined
387    Nag167,
388    /// Undefined
389    Nag168,
390    /// Undefined
391    Nag169,
392    /// Undefined
393    Nag170,
394    /// Undefined
395    Nag171,
396    /// Undefined
397    Nag172,
398    /// Undefined
399    Nag173,
400    /// Undefined
401    Nag174,
402    /// Undefined
403    Nag175,
404    /// Undefined
405    Nag176,
406    /// Undefined
407    Nag177,
408    /// Undefined
409    Nag178,
410    /// Undefined
411    Nag179,
412    /// Undefined
413    Nag180,
414    /// Undefined
415    Nag181,
416    /// Undefined
417    Nag182,
418    /// Undefined
419    Nag183,
420    /// Undefined
421    Nag184,
422    /// Undefined
423    Nag185,
424    /// Undefined
425    Nag186,
426    /// Undefined
427    Nag187,
428    /// Undefined
429    Nag188,
430    /// Undefined
431    Nag189,
432    /// Undefined
433    Nag190,
434    /// Undefined
435    Nag191,
436    /// Undefined
437    Nag192,
438    /// Undefined
439    Nag193,
440    /// Undefined
441    Nag194,
442    /// Undefined
443    Nag195,
444    /// Undefined
445    Nag196,
446    /// Undefined
447    Nag197,
448    /// Undefined
449    Nag198,
450    /// Undefined
451    Nag199,
452    /// Undefined
453    Nag200,
454    /// Undefined
455    Nag201,
456    /// Undefined
457    Nag202,
458    /// Undefined
459    Nag203,
460    /// Undefined
461    Nag204,
462    /// Undefined
463    Nag205,
464    /// Undefined
465    Nag206,
466    /// Undefined
467    Nag207,
468    /// Undefined
469    Nag208,
470    /// Undefined
471    Nag209,
472    /// Undefined
473    Nag210,
474    /// Undefined
475    Nag211,
476    /// Undefined
477    Nag212,
478    /// Undefined
479    Nag213,
480    /// Undefined
481    Nag214,
482    /// Undefined
483    Nag215,
484    /// Undefined
485    Nag216,
486    /// Undefined
487    Nag217,
488    /// Undefined
489    Nag218,
490    /// Undefined
491    Nag219,
492    /// Diagram, also known as "⬒"
493    Diagram,
494    /// Diagram (from Black), also known as "⬓"
495    DiagramFromBlack,
496    /// Undefined
497    Nag222,
498    /// Undefined
499    Nag223,
500    /// Undefined
501    Nag224,
502    /// Undefined
503    Nag225,
504    /// Undefined
505    Nag226,
506    /// Undefined
507    Nag227,
508    /// Undefined
509    Nag228,
510    /// Undefined
511    Nag229,
512    /// Undefined
513    Nag230,
514    /// Undefined
515    Nag231,
516    /// Undefined
517    Nag232,
518    /// Undefined
519    Nag233,
520    /// Undefined
521    Nag234,
522    /// Undefined
523    Nag235,
524    /// Undefined
525    Nag236,
526    /// Undefined
527    Nag237,
528    /// Space advantage, also known as "○"
529    SpaceAdvantage,
530    /// File (columns on the chessboard labeled a-h), also known as "⇔"
531    File,
532    /// Diagonal, also known as "⇗"
533    Diagonal,
534    /// Centre, also known as "⊞"
535    Centre,
536    /// King-side, also known as "⟫"
537    KingSide,
538    /// Queen-side, also known as "⟪"
539    QueenSide,
540    /// Weak point, also known as "✕"
541    WeakPoint,
542    /// Ending, also known as "⊥"
543    Ending,
544    /// Bishop pair
545    BishopPair,
546    /// Opposite bishops
547    OppositeBishops,
548    /// Same bishops
549    SameBishops,
550    /// Connected pawns, also known as "⯺"
551    ConnectedPawns,
552    /// Isolated pawns, also known as "⯻"
553    IsolatedPawns,
554    /// Doubled pawns, also known as "⯼"
555    DoubledPawns,
556    /// Passed pawn, also known as "⯽"
557    PassedPawn,
558    /// Pawn majority
559    PawnMajority,
560    /// With, also known as "∟"
561    With,
562    /// Without, also known as "⯾"
563    Without,
564}
565
566impl Display for Nag {
567    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
568        match self {
569            Nag::Null => write!(f, " "),
570            Nag::Hard => write!(f, "!!"),
571            Nag::Good => write!(f, "!"),
572            Nag::Mistake => write!(f, "?"),
573            Nag::Blunder => write!(f, "??"),
574            Nag::Interesting => write!(f, "!?"),
575            Nag::Dubious => write!(f, "?!"),
576            Nag::Forced | Nag::Only => write!(f, "□"),
577            Nag::ZugzwangWhite | Nag::ZugzwangBlack => write!(f, "⊙"),
578            Nag::ModerateSpaceAdvantageWhite | Nag::ModerateSpaceAdvantageBlack => write!(f, "○"),
579            Nag::ModerateDevelopmentAdvantageWhite | Nag::ModerateDevelopmentAdvantageBlack => {
580                write!(f, "⟳")
581            }
582            Nag::InitiativeWhite | Nag::InitiativeBlack => write!(f, "↑"),
583            Nag::AttackWhite | Nag::AttackBlack => write!(f, "→"),
584            Nag::SufficientCompensationWhite | Nag::SufficientCompensationBlack => write!(f, "⯹"),
585            Nag::ModerateCounterPlayWhite
586            | Nag::DecisiveCounterPlayWhite
587            | Nag::ModerateCounterPlayBlack
588            | Nag::DecisiveCounterPlayBlack => write!(f, "⇆"),
589            Nag::SevereTimeControlPressureWhite | Nag::SevereTimeControlPressureBlack => {
590                write!(f, "⨁")
591            }
592            Nag::WithTheIdea => write!(f, "∆"),
593            Nag::AimedAgainst => write!(f, "∇"),
594            Nag::BetterIs => write!(f, "⌓"),
595            Nag::WorseIs => write!(f, "<="),
596            Nag::EquivalentIs => write!(f, "=="),
597            Nag::EditorialComment => write!(f, "RR"),
598            Nag::Novelty => write!(f, "N"),
599            Nag::Diagram => write!(f, "⬒"),
600            Nag::DiagramFromBlack => write!(f, "⬓"),
601            Nag::SpaceAdvantage => write!(f, "○"),
602            Nag::File => write!(f, "⇔"),
603            Nag::Diagonal => write!(f, "⇗"),
604            Nag::Centre => write!(f, "⊞"),
605            Nag::KingSide => write!(f, "⟫"),
606            Nag::QueenSide => write!(f, "⟪"),
607            Nag::WeakPoint => write!(f, "✕"),
608            Nag::Ending => write!(f, "⊥"),
609            Nag::ConnectedPawns => write!(f, "⯺"),
610            Nag::IsolatedPawns => write!(f, "⯻"),
611            Nag::DoubledPawns => write!(f, "⯼"),
612            Nag::PassedPawn => write!(f, "⯽"),
613            Nag::With => write!(f, "∟"),
614            Nag::Without => write!(f, "⯾"),
615            n => write!(f, "${}", n),
616        }
617    }
618}
619
620impl From<u8> for Nag {
621    fn from(num: u8) -> Self {
622        match num {
623            0 => Nag::Null,
624            1 => Nag::Good,
625            2 => Nag::Mistake,
626            3 => Nag::Hard,
627            4 => Nag::Blunder,
628            5 => Nag::Interesting,
629            6 => Nag::Dubious,
630            7 => Nag::Forced,
631            8 => Nag::Only,
632            9 => Nag::Worst,
633            10 => Nag::Drawish,
634            11 => Nag::EqualQuiet,
635            12 => Nag::EqualActive,
636            13 => Nag::Unclear,
637            14 => Nag::SlightEdgeWhite,
638            15 => Nag::SlightEdgeBlack,
639            16 => Nag::ModerateAdvantageWhite,
640            17 => Nag::ModerateAdvantageBlack,
641            18 => Nag::DecisiveAdvantageWhite,
642            19 => Nag::DecisiveAdvantageBlack,
643            20 => Nag::CrushingAdvantageWhite,
644            21 => Nag::CrushingAdvantageBlack,
645            22 => Nag::ZugzwangWhite,
646            23 => Nag::ZugzwangBlack,
647            24 => Nag::SlightSpaceAdvantageWhite,
648            25 => Nag::SlightSpaceAdvantageBlack,
649            26 => Nag::ModerateSpaceAdvantageWhite,
650            27 => Nag::ModerateSpaceAdvantageBlack,
651            28 => Nag::DecisiveSpaceAdvantageWhite,
652            29 => Nag::DecisiveSpaceAdvantageBlack,
653            30 => Nag::SlightDevelopmentAdvantageWhite,
654            31 => Nag::SlightDevelopmentAdvantageBlack,
655            32 => Nag::ModerateDevelopmentAdvantageWhite,
656            33 => Nag::ModerateDevelopmentAdvantageBlack,
657            34 => Nag::DecisiveDevelopmentAdvantageWhite,
658            35 => Nag::DecisiveDevelopmentAdvantageBlack,
659            36 => Nag::InitiativeWhite,
660            37 => Nag::InitiativeBlack,
661            38 => Nag::LastingInitiativeWhite,
662            39 => Nag::LastingInitiativeBlack,
663            40 => Nag::AttackWhite,
664            41 => Nag::AttackBlack,
665            42 => Nag::InsufficientCompensationWhite,
666            43 => Nag::InsufficientCompensationBlack,
667            44 => Nag::SufficientCompensationWhite,
668            45 => Nag::SufficientCompensationBlack,
669            46 => Nag::MoreThanAdequateCompensationWhite,
670            47 => Nag::MoreThanAdequateCompensationBlack,
671            48 => Nag::SlightCenterControlAdvantageWhite,
672            49 => Nag::SlightCenterControlAdvantageBlack,
673            50 => Nag::ModerateCenterControlAdvantageWhite,
674            51 => Nag::ModerateCenterControlAdvantageBlack,
675            52 => Nag::DecisiveCenterControlAdvantageWhite,
676            53 => Nag::DecisiveCenterControlAdvantageBlack,
677            54 => Nag::SlightKingSideControlAdvantageWhite,
678            55 => Nag::SlightKingSideControlAdvantageBlack,
679            56 => Nag::ModerateKingSideControlAdvantageWhite,
680            57 => Nag::ModerateKingSideControlAdvantageBlack,
681            58 => Nag::DecisiveKingSideControlAdvantageWhite,
682            59 => Nag::DecisiveKingSideControlAdvantageBlack,
683            60 => Nag::SlightQueenSideControlAdvantageWhite,
684            61 => Nag::SlightQueenSideControlAdvantageBlack,
685            62 => Nag::ModerateQueenSideControlAdvantageWhite,
686            63 => Nag::ModerateQueenSideControlAdvantageBlack,
687            64 => Nag::DecisiveQueenSideControlAdvantageWhite,
688            65 => Nag::DecisiveQueenSideControlAdvantageBlack,
689            66 => Nag::VulnerableFirstRankWhite,
690            67 => Nag::VulnerableFirstRankBlack,
691            68 => Nag::WellProtectedFirstRankWhite,
692            69 => Nag::WellProtectedFirstRankBlack,
693            70 => Nag::PoorlyProtectedKingWhite,
694            71 => Nag::PoorlyProtectedKingBlack,
695            72 => Nag::WellProtectedKingWhite,
696            73 => Nag::WellProtectedKingBlack,
697            74 => Nag::PoorlyPlacedKingWhite,
698            75 => Nag::PoorlyPlacedKingBlack,
699            76 => Nag::WellPlacedKingWhite,
700            77 => Nag::WellPlacedKingBlack,
701            78 => Nag::VeryWeakPawnStructureWhite,
702            79 => Nag::VeryWeakPawnStructureBlack,
703            80 => Nag::ModeratelyWeakPawnStructureWhite,
704            81 => Nag::ModeratelyWeakPawnStructureBlack,
705            82 => Nag::ModeratelyStrongPawnStructureWhite,
706            83 => Nag::ModeratelyStrongPawnStructureBlack,
707            84 => Nag::VeryStrongPawnStructureWhite,
708            85 => Nag::VeryStrongPawnStructureBlack,
709            86 => Nag::PoorKnightPlacementWhite,
710            87 => Nag::PoorKnightPlacementBlack,
711            88 => Nag::GoodKnightPlacementWhite,
712            89 => Nag::GoodKnightPlacementBlack,
713            90 => Nag::PoorBishopPlacementWhite,
714            91 => Nag::PoorBishopPlacementBlack,
715            92 => Nag::GoodBishopPlacementWhite,
716            93 => Nag::GoodBishopPlacementBlack,
717            94 => Nag::PoorRookPlacementWhite,
718            95 => Nag::PoorRookPlacementBlack,
719            96 => Nag::GoodRookPlacementWhite,
720            97 => Nag::GoodRookPlacementBlack,
721            98 => Nag::PoorQueenPlacementWhite,
722            99 => Nag::PoorQueenPlacementBlack,
723            100 => Nag::GoodQueenPlacementWhite,
724            101 => Nag::GoodQueenPlacementBlack,
725            102 => Nag::PoorPieceCoordinationWhite,
726            103 => Nag::PoorPieceCoordinationBlack,
727            104 => Nag::GoodPieceCoordinationWhite,
728            105 => Nag::GoodPieceCoordinationBlack,
729            106 => Nag::VeryPoorOpeningPlayWhite,
730            107 => Nag::VeryPoorOpeningPlayBlack,
731            108 => Nag::PoorOpeningPlayWhite,
732            109 => Nag::PoorOpeningPlayBlack,
733            110 => Nag::WellOpeningPlayWhite,
734            111 => Nag::WellOpeningPlayBlack,
735            112 => Nag::VeryWellOpeningPlayWhite,
736            113 => Nag::VeryWellOpeningPlayBlack,
737            114 => Nag::VeryPoorMiddleGamePlayWhite,
738            115 => Nag::VeryPoorMiddleGamePlayBlack,
739            116 => Nag::PoorMiddleGamePlayWhite,
740            117 => Nag::PoorMiddleGamePlayBlack,
741            118 => Nag::WellMiddleGamePlayWhite,
742            119 => Nag::WellMiddleGamePlayBlack,
743            120 => Nag::VeryWellMiddleGamePlayWhite,
744            121 => Nag::VeryWellMiddleGamePlayBlack,
745            122 => Nag::VeryPoorEndingPlayWhite,
746            123 => Nag::VeryPoorEndingPlayBlack,
747            124 => Nag::PoorEndingPlayWhite,
748            125 => Nag::PoorEndingPlayBlack,
749            126 => Nag::WellEndingPlayWhite,
750            127 => Nag::WellEndingPlayBlack,
751            128 => Nag::VeryWellEndingPlayWhite,
752            129 => Nag::VeryWellEndingPlayBlack,
753            130 => Nag::SlightCounterPlayWhite,
754            131 => Nag::SlightCounterPlayBlack,
755            132 => Nag::ModerateCounterPlayWhite,
756            133 => Nag::ModerateCounterPlayBlack,
757            134 => Nag::DecisiveCounterPlayWhite,
758            135 => Nag::DecisiveCounterPlayBlack,
759            136 => Nag::ModerateTimeControlPressureWhite,
760            137 => Nag::ModerateTimeControlPressureBlack,
761            138 => Nag::SevereTimeControlPressureWhite,
762            139 => Nag::SevereTimeControlPressureBlack,
763            140 => Nag::WithTheIdea,
764            141 => Nag::AimedAgainst,
765            142 => Nag::BetterIs,
766            143 => Nag::WorseIs,
767            144 => Nag::EquivalentIs,
768            145 => Nag::EditorialComment,
769            146 => Nag::Novelty,
770            147 => Nag::Nag147,
771            148 => Nag::Nag148,
772            149 => Nag::Nag149,
773            150 => Nag::Nag150,
774            151 => Nag::Nag151,
775            152 => Nag::Nag152,
776            153 => Nag::Nag153,
777            154 => Nag::Nag154,
778            155 => Nag::Nag155,
779            156 => Nag::Nag156,
780            157 => Nag::Nag157,
781            158 => Nag::Nag158,
782            159 => Nag::Nag159,
783            160 => Nag::Nag160,
784            161 => Nag::Nag161,
785            162 => Nag::Nag162,
786            163 => Nag::Nag163,
787            164 => Nag::Nag164,
788            165 => Nag::Nag165,
789            166 => Nag::Nag166,
790            167 => Nag::Nag167,
791            168 => Nag::Nag168,
792            169 => Nag::Nag169,
793            170 => Nag::Nag170,
794            171 => Nag::Nag171,
795            172 => Nag::Nag172,
796            173 => Nag::Nag173,
797            174 => Nag::Nag174,
798            175 => Nag::Nag175,
799            176 => Nag::Nag176,
800            177 => Nag::Nag177,
801            178 => Nag::Nag178,
802            179 => Nag::Nag179,
803            180 => Nag::Nag180,
804            181 => Nag::Nag181,
805            182 => Nag::Nag182,
806            183 => Nag::Nag183,
807            184 => Nag::Nag184,
808            185 => Nag::Nag185,
809            186 => Nag::Nag186,
810            187 => Nag::Nag187,
811            188 => Nag::Nag188,
812            189 => Nag::Nag189,
813            190 => Nag::Nag190,
814            191 => Nag::Nag191,
815            192 => Nag::Nag192,
816            193 => Nag::Nag193,
817            194 => Nag::Nag194,
818            195 => Nag::Nag195,
819            196 => Nag::Nag196,
820            197 => Nag::Nag197,
821            198 => Nag::Nag198,
822            199 => Nag::Nag199,
823            200 => Nag::Nag200,
824            201 => Nag::Nag201,
825            202 => Nag::Nag202,
826            203 => Nag::Nag203,
827            204 => Nag::Nag204,
828            205 => Nag::Nag205,
829            206 => Nag::Nag206,
830            207 => Nag::Nag207,
831            208 => Nag::Nag208,
832            209 => Nag::Nag209,
833            210 => Nag::Nag210,
834            211 => Nag::Nag211,
835            212 => Nag::Nag212,
836            213 => Nag::Nag213,
837            214 => Nag::Nag214,
838            215 => Nag::Nag215,
839            216 => Nag::Nag216,
840            217 => Nag::Nag217,
841            218 => Nag::Nag218,
842            219 => Nag::Nag219,
843            220 => Nag::Diagram,
844            221 => Nag::DiagramFromBlack,
845            222 => Nag::Nag222,
846            223 => Nag::Nag223,
847            224 => Nag::Nag224,
848            225 => Nag::Nag225,
849            226 => Nag::Nag226,
850            227 => Nag::Nag227,
851            228 => Nag::Nag228,
852            229 => Nag::Nag229,
853            230 => Nag::Nag230,
854            231 => Nag::Nag231,
855            232 => Nag::Nag232,
856            233 => Nag::Nag233,
857            234 => Nag::Nag234,
858            235 => Nag::Nag235,
859            236 => Nag::Nag236,
860            237 => Nag::Nag237,
861            238 => Nag::SpaceAdvantage,
862            239 => Nag::File,
863            240 => Nag::Diagonal,
864            241 => Nag::Centre,
865            242 => Nag::KingSide,
866            243 => Nag::QueenSide,
867            244 => Nag::WeakPoint,
868            245 => Nag::Ending,
869            246 => Nag::BishopPair,
870            247 => Nag::OppositeBishops,
871            248 => Nag::SameBishops,
872            249 => Nag::ConnectedPawns,
873            250 => Nag::IsolatedPawns,
874            251 => Nag::DoubledPawns,
875            252 => Nag::PassedPawn,
876            253 => Nag::PawnMajority,
877            254 => Nag::With,
878            255 => Nag::Without,
879        }
880    }
881}
882
883impl Nag {
884    /// Returns `true` if the Nag is `Interesting`, `Dubious`, `Mistake`, or `Blunder`, `false`
885    /// otherwise.
886    pub fn is_question_mark(&self) -> bool {
887        matches!(
888            self,
889            Nag::Interesting | Nag::Dubious | Nag::Mistake | Nag::Blunder | Nag::Worst
890        )
891    }
892}
893
894impl ByteBoard {
895    /// Creates a new empty chessboard.
896    ///
897    /// This method creates a new `ByteBoard` object representing an empty
898    /// chessboard, with all squares set to the space character (`' '`).
899    ///
900    /// # Returns
901    ///
902    /// * `ByteBoard` - A new `ByteBoard` object representing an empty chessboard.
903    pub fn new(board_str: &str) -> Self {
904        let bytes: [u8; 64] = board_str.as_bytes().try_into().unwrap();
905        Self { bytes }
906    }
907
908    /// Creates a new `ByteBoard` from the given byte slice.
909    ///
910    /// This method creates a new `ByteBoard` object using the given byte
911    /// slice. The slice should have exactly 64 elements representing
912    /// the pieces on the chessboard.
913    ///
914    /// # Arguments
915    ///
916    /// * `slice: &[u8; 64]` - A byte slice containing the board
917    /// representation.
918    ///
919    /// # Returns
920    ///
921    /// * `ByteBoard` - A new `ByteBoard`
922    pub fn from_bytes(slice: &[u8; 64]) -> Self {
923        Self { bytes: *slice }
924    }
925
926    /// Creates a new `ByteBoard` from a `shakmaty` `Board` object.
927    ///
928    /// This method creates a new `ByteBoard` object from a given `shakmaty` `Board` object,
929    /// where each byte in the internal array represents a piece or an empty square (with the space
930    /// character, `' '`, for empty squares).
931    ///
932    /// # Arguments
933    ///
934    /// * `board` - A `shakmaty` `Board` object representing the chess board.
935    ///
936    /// # Returns
937    ///
938    /// * `ByteBoard` - A new `ByteBoard` object representing the chess board.
939    pub fn from_board(board: &Board) -> Self {
940        let mut bytes: [u8; 64] = [b' '; 64];
941
942        let mut set_piece_byte = |role, color, byte: u8| {
943            for square in board.by_role(role) & board.by_color(color) {
944                let (file, rank) = square.coords();
945                let index = (7 - rank as usize) * 8 + file as usize;
946                bytes[index] = byte;
947            }
948        };
949
950        // Order optimized for cache efficiency.
951        set_piece_byte(Role::Pawn, Color::Black, b'p');
952        set_piece_byte(Role::Pawn, Color::White, b'P');
953        set_piece_byte(Role::Knight, Color::Black, b'n');
954        set_piece_byte(Role::Knight, Color::White, b'N');
955        set_piece_byte(Role::Bishop, Color::Black, b'b');
956        set_piece_byte(Role::Bishop, Color::White, b'B');
957        set_piece_byte(Role::Rook, Color::Black, b'r');
958        set_piece_byte(Role::Rook, Color::White, b'R');
959        set_piece_byte(Role::Queen, Color::Black, b'q');
960        set_piece_byte(Role::Queen, Color::White, b'Q');
961        set_piece_byte(Role::King, Color::Black, b'k');
962        set_piece_byte(Role::King, Color::White, b'K');
963
964        Self { bytes }
965    }
966
967    /// Gets a byte slice representation of the chessboard.
968    ///
969    /// This method returns a reference to the internal byte array
970    /// representing the chessboard. Each byte in the array corresponds to a
971    /// piece or an empty square, where the space character (`' '`) represents
972    /// an empty square.
973    ///
974    /// # Returns
975    ///
976    /// * `&[u8]` - A byte slice representing the chessboard.
977    pub fn as_bytes(&self) -> &[u8] {
978        &self.bytes
979    }
980
981    /// Decodes a FEN (Forsyth-Edwards Notation) string into a `ByteBoard` object.
982    ///
983    /// This method converts a FEN string representing a chessboard position
984    /// into a `ByteBoard` object, where each byte in the internal array represents
985    /// a piece or an empty square (with the space character, `' '`, for empty squares).
986    ///
987    /// # Arguments
988    ///
989    /// * `fen` - A FEN string representing the chessboard position.
990    ///
991    /// # Returns
992    ///
993    /// * `Result<ByteBoard, Error>` - A `ByteBoard` object representing the chessboard if
994    ///   the input FEN string is valid, or an `Error` if the input FEN string is invalid.
995    pub fn from_fen(fen: &[u8]) -> Result<Self, Error> {
996        // Create a new board array, initially filled with spaces
997        let mut bytes = [b' '; 64];
998        // Keep track of the current index on the board
999        let mut i = 0;
1000
1001        // Iterate over each character in the input FEN string
1002        for &ch in fen {
1003            match ch {
1004                // If we encounter a valid piece character, place it at the current index on the board
1005                b'r' | b'n' | b'b' | b'q' | b'k' | b'p' | b'R' | b'N' | b'B' | b'Q' | b'K'
1006                | b'P' => {
1007                    // Ensure we're not out of bounds on the array (which should never happen if the input is a valid FEN string)
1008                    if i < 64 {
1009                        bytes[i] = ch;
1010                        i += 1;
1011                    } else {
1012                        return Err(Error::from(ErrorKind::InvalidInput));
1013                    }
1014                }
1015                // If we encounter a digit, skip the appropriate number of spaces on the board
1016                b'1'..=b'8' => {
1017                    let spaces = ch - b'0'; // Convert the character to a number
1018                    i = (i + spaces as usize).min(64); // Increment the index by that number, but ensure we don't go out of bounds
1019                }
1020                // If we encounter a '/', we're moving to the next row
1021                b'/' => {
1022                    // Adjust index to next line start considering the empty spots at the end of the rank.
1023                    // We calculate the remainder when current index is divided by 8 (which is the board width)
1024                    // If remainder is not zero, it means that we haven't finished current row yet (we have empty spots at the end)
1025                    // So, we add (8 - remainder) to the index to move it to the start of the next row
1026                    let remainder = i % 8;
1027                    if remainder != 0 {
1028                        i += 8 - remainder;
1029                    }
1030                }
1031                // A space indicates the end of the board section of the FEN string
1032                b' ' => {
1033                    break;
1034                }
1035                // If we encounter an unexpected character, it's an error
1036                _ => {
1037                    return Err(Error::from(ErrorKind::InvalidInput));
1038                }
1039            }
1040        }
1041
1042        // If we made it through the entire loop without returning an error, our board is good to go!
1043        Ok(Self { bytes })
1044    }
1045
1046    /// Searches for a specific chess piece on the board and returns its position.
1047    ///
1048    /// This method searches for the given `piece` character in the `ByteBoard` object
1049    /// and returns the position of the `num`-th occurrence of the piece.
1050    /// Board positions are represented as i32 values (0 to 63).
1051    ///
1052    /// # Arguments
1053    ///
1054    /// * `piece` - The character representing the chess piece to search for.
1055    /// * `num` - The occurrence number of the piece to search for.
1056    ///
1057    /// # Returns
1058    ///
1059    /// * `Option<i32>` - The position of the `num`-th occurrence of `piece` on the board, or an
1060    /// `None` if the piece is not found.
1061    pub fn find_piece(&self, piece: char, num: i32) -> Option<i32> {
1062        let piece_byte = piece as u8;
1063        let mut occurrence = num;
1064
1065        for x in 0..8 {
1066            // SAFETY: Loop bounds guarantee safe conversion in range.
1067            let ux: usize = unsafe { x.try_into().unwrap_unchecked() };
1068
1069            for y in 0..8 {
1070                // SAFETY: Loop bounds guarantee safe conversion in range.
1071                let uy: usize = unsafe { y.try_into().unwrap_unchecked() };
1072
1073                let index = (7 - uy) * 8 + ux;
1074                if self.bytes[index] != piece_byte {
1075                    continue;
1076                }
1077                if occurrence == 1 {
1078                    return Some(y * 8 + x);
1079                }
1080                occurrence -= 1;
1081            }
1082        }
1083
1084        None
1085    }
1086
1087    /// Inverts the colors of the pieces on the chessboard and flips the board vertically.
1088    ///
1089    /// This method inverts the colors of the pieces on the `ByteBoard` object by changing
1090    /// the case of each character, and flips the board vertically. The resulting board
1091    /// is stored in a new `ByteBoard` object.
1092    ///
1093    /// # Returns
1094    ///
1095    /// * `ByteBoard` - A new `ByteBoard` object representing the inverted and flipped chessboard.
1096    pub fn invert(&mut self) {
1097        for y in 0..4 {
1098            for x in 0..8 {
1099                let index1 = y * 8 + x;
1100                let index2 = (7 - y) * 8 + x;
1101
1102                self.bytes.swap(index1, index2);
1103                self.bytes[index1] = invert_color(self.bytes[index1]);
1104                self.bytes[index2] = invert_color(self.bytes[index2]);
1105            }
1106        }
1107    }
1108
1109    /// Determines if a chessboard should be flipped.
1110    ///
1111    /// This method checks if the given chessboard should be flipped. A board is flipped when
1112    /// neither side can castle, and the white king is on the lower half of the board. This
1113    /// function must not be called if either side can castle.
1114    ///
1115    /// # Returns
1116    ///
1117    /// * `bool` - `true` if the board should be flipped, `false` otherwise.
1118    pub fn needs_flipping(&self) -> bool {
1119        self.bytes[0..32].contains(&b'K')
1120    }
1121
1122    /// Flips a chessboard horizontally and returns the flipped en passant square.
1123    ///
1124    /// This method takes a mutable reference to a `ByteBoard` object and an en passant square option,
1125    /// flips the board horizontally, and returns the flipped en passant square as an option.
1126    ///
1127    /// # Arguments
1128    ///
1129    /// * `eps` - An optional `shakmaty::Square` representing the en passant square.
1130    ///
1131    /// # Returns
1132    ///
1133    /// * `Option<Square>` - An optional `shakmaty::Square` containing the flipped en passant
1134    /// square.
1135    pub fn flip(&mut self, eps: Option<Square>) -> Option<Square> {
1136        // Flip the board horizontally
1137        self.bytes.reverse();
1138
1139        eps.map(|square| square.flip_horizontal())
1140    }
1141}
1142
1143impl std::fmt::Display for ByteBoard {
1144    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1145        write!(f, "{}", String::from_utf8_lossy(&self.bytes))
1146    }
1147}
1148
1149/// Inverts the color of a chess piece character by switching its case.
1150///
1151/// This function takes a character representing a chess piece and returns the
1152/// corresponding character for the piece with the opposite color. If the input
1153/// character is not a valid chess piece character, it returns the input character
1154/// unchanged.
1155///
1156/// # Arguments
1157///
1158/// * `c` - A character representing a chess piece ("PNBRQK" or lowercase).
1159///
1160/// # Returns
1161///
1162/// * `char` - The character representing the chess piece with the opposite color.
1163#[inline(always)]
1164fn invert_color(c: u8) -> u8 {
1165    match c {
1166        b'p' => b'P',
1167        b'P' => b'p',
1168        b'n' => b'N',
1169        b'N' => b'n',
1170        b'b' => b'B',
1171        b'B' => b'b',
1172        b'r' => b'R',
1173        b'R' => b'r',
1174        b'q' => b'Q',
1175        b'Q' => b'q',
1176        b'k' => b'K',
1177        b'K' => b'k',
1178        _ => c,
1179    }
1180}
1181
1182// A constant table of 64-bit values used in the `gen_hash` function.
1183const TBL2: [u32; 64] = [
1184    0x3100d2bf, 0x3118e3de, 0x34ab1372, 0x2807a847, 0x1633f566, 0x2143b359, 0x26d56488, 0x3b9e6f59,
1185    0x37755656, 0x3089ca7b, 0x18e92d85, 0x0cd0e9d8, 0x1a9e3b54, 0x3eaa902f, 0x0d9bfaae, 0x2f32b45b,
1186    0x31ed6102, 0x3d3c8398, 0x146660e3, 0x0f8d4b76, 0x02c77a5f, 0x146c8799, 0x1c47f51f, 0x249f8f36,
1187    0x24772043, 0x1fbc1e4d, 0x1e86b3fa, 0x37df36a6, 0x16ed30e4, 0x02c3148e, 0x216e5929, 0x0636b34e,
1188    0x317f9f56, 0x15f09d70, 0x131026fb, 0x38c784b1, 0x29ac3305, 0x2b485dc5, 0x3c049ddc, 0x35a9fbcd,
1189    0x31d5373b, 0x2b246799, 0x0a2923d3, 0x08a96e9d, 0x30031a9f, 0x08f525b5, 0x33611c06, 0x2409db98,
1190    0x0ca4feb2, 0x1000b71e, 0x30566e32, 0x39447d31, 0x194e3752, 0x08233a95, 0x0f38fe36, 0x29c7cd57,
1191    0x0f7b3a39, 0x328e8a16, 0x1e7d1388, 0x0fba78f5, 0x274c7e7c, 0x1e8be65c, 0x2fa0b0bb, 0x1eb6c371,
1192];
1193
1194/// Returns a colored string representation of a UCI move according to the recommendation and NAGs.
1195///
1196/// This function takes a recommendation value, NAGs, and a UCI move as input.
1197/// If the recommendation ix 0xa4, the move will be colored green.
1198/// If the recommendation is 0x80, the move will be colored green, unless the NAGs
1199/// include the '?' character, in which case the move will be colored blue.
1200/// If the recommendation is 0x40, the move will be colored red.
1201/// For any other recommendation, the UCI move will not be colored.
1202///
1203/// # Arguments
1204///
1205/// * `uci` - A `shakmaty::uci::Uci` representing the UCI move.
1206/// * `nag` - An `Option<Nag>` containing the NAG for the move.
1207/// * `recommendation` - An unsigned 8-bit integer representing the recommendation value.
1208pub fn colored_uci(uci: &Uci, nag: &Option<Nag>, recommendation: u8) -> String {
1209    let is_question_mark = nag.map(|n| n.is_question_mark()).unwrap_or(false);
1210
1211    match recommendation {
1212        0xa4 => style(uci.to_string()).green().to_string(),
1213        0x80 => {
1214            if is_question_mark {
1215                style(uci.to_string()).blue().to_string()
1216            } else {
1217                style(uci.to_string()).green().to_string()
1218            }
1219        }
1220        0x40 => style(uci.to_string()).red().to_string(),
1221        _ => uci.to_string(),
1222    }
1223}
1224
1225/// Generates a hash value for the input slice of i8 integers.
1226///
1227/// This function takes a slice of i8 integers and generates a hash value
1228/// using a custom algorithm that incorporates the values in the `TBL2` constant.
1229///
1230/// # Arguments
1231///
1232/// * `ptr` - A slice of i8 integers to generate the hash value for.
1233/// * `len` - The length of the input slice.
1234///
1235/// # Returns
1236///
1237/// * `i32` - The generated hash value.
1238#[inline(always)]
1239pub fn gen_hash(ptr: &[i8], len: usize) -> i32 {
1240    let mut hash: i32 = 0;
1241    let mut tmp: i16 = 0;
1242
1243    for ch in ptr.iter().take(len) {
1244        let ch = i16::from(*ch);
1245        tmp += ((0x0f - (ch & 0x0f)) << 2) + 1;
1246        hash = hash.wrapping_add(TBL2[(tmp & 0x3f) as usize] as i32);
1247        tmp += ((0xf0 - (ch & 0xf0)) >> 2) + 1;
1248        hash = hash.wrapping_add(TBL2[(tmp & 0x3f) as usize] as i32);
1249    }
1250
1251    hash
1252}
1253
1254/// A struct representing an encoded chess move.
1255///
1256/// This struct is used to store information about a chess move, including the
1257/// move encoding, the piece involved, the number of moves, and the directions
1258/// of the move (forward and right).
1259pub struct MoveEnc {
1260    /// An `u8` representing the move encoding.
1261    pub encoding: u8,
1262    /// A `char` representing the chess piece involved in the move.
1263    pub piece: char,
1264    /// An `i32` representing the number of moves.
1265    pub num: i32,
1266    /// An `i32` representing the forward direction of the move.
1267    pub forward: i32,
1268    /// An `i32` representing the right direction of the move.
1269    pub right: i32,
1270}
1271
1272/// A constant representing the maximum number of elements in the `MOVETABLE`.
1273pub const MOVETABLE_MAX: usize = 166;
1274
1275/// A static array of `MoveEnc` structs representing a table of encoded chess moves.
1276///
1277/// This table is used to store information about encoded chess moves for use
1278/// in move generation and validation.
1279pub static MOVETABLE: [MoveEnc; MOVETABLE_MAX] = [
1280    MoveEnc {
1281        encoding: 0x00,
1282        piece: 'P',
1283        num: 5,
1284        forward: 1,
1285        right: 1,
1286    },
1287    MoveEnc {
1288        encoding: 0x01,
1289        piece: 'N',
1290        num: 2,
1291        forward: -1,
1292        right: -2,
1293    },
1294    MoveEnc {
1295        encoding: 0x03,
1296        piece: 'Q',
1297        num: 2,
1298        forward: 0,
1299        right: 2,
1300    },
1301    MoveEnc {
1302        encoding: 0x04,
1303        piece: 'P',
1304        num: 2,
1305        forward: 1,
1306        right: 0,
1307    },
1308    MoveEnc {
1309        encoding: 0x05,
1310        piece: 'Q',
1311        num: 1,
1312        forward: 1,
1313        right: 0,
1314    },
1315    MoveEnc {
1316        encoding: 0x06,
1317        piece: 'P',
1318        num: 4,
1319        forward: 1,
1320        right: -1,
1321    },
1322    MoveEnc {
1323        encoding: 0x08,
1324        piece: 'Q',
1325        num: 2,
1326        forward: 0,
1327        right: 4,
1328    },
1329    MoveEnc {
1330        encoding: 0x09,
1331        piece: 'B',
1332        num: 2,
1333        forward: 6,
1334        right: 6,
1335    },
1336    MoveEnc {
1337        encoding: 0x0a,
1338        piece: 'K',
1339        num: 1,
1340        forward: -1,
1341        right: 0,
1342    },
1343    MoveEnc {
1344        encoding: 0x0c,
1345        piece: 'P',
1346        num: 1,
1347        forward: 1,
1348        right: -1,
1349    },
1350    MoveEnc {
1351        encoding: 0x0d,
1352        piece: 'B',
1353        num: 1,
1354        forward: 3,
1355        right: 3,
1356    },
1357    MoveEnc {
1358        encoding: 0x0e,
1359        piece: 'R',
1360        num: 2,
1361        forward: 0,
1362        right: 3,
1363    },
1364    MoveEnc {
1365        encoding: 0x0f,
1366        piece: 'N',
1367        num: 1,
1368        forward: -1,
1369        right: -2,
1370    },
1371    MoveEnc {
1372        encoding: 0x12,
1373        piece: 'B',
1374        num: 1,
1375        forward: 7,
1376        right: 7,
1377    },
1378    MoveEnc {
1379        encoding: 0x13,
1380        piece: 'K',
1381        num: 1,
1382        forward: 1,
1383        right: 0,
1384    },
1385    MoveEnc {
1386        encoding: 0x14,
1387        piece: 'P',
1388        num: 8,
1389        forward: 1,
1390        right: 1,
1391    },
1392    MoveEnc {
1393        encoding: 0x15,
1394        piece: 'B',
1395        num: 1,
1396        forward: 5,
1397        right: 5,
1398    },
1399    MoveEnc {
1400        encoding: 0x18,
1401        piece: 'P',
1402        num: 7,
1403        forward: 1,
1404        right: 0,
1405    },
1406    MoveEnc {
1407        encoding: 0x1a,
1408        piece: 'Q',
1409        num: 2,
1410        forward: 6,
1411        right: 0,
1412    },
1413    MoveEnc {
1414        encoding: 0x1b,
1415        piece: 'B',
1416        num: 1,
1417        forward: 1,
1418        right: -1,
1419    },
1420    MoveEnc {
1421        encoding: 0x1d,
1422        piece: 'B',
1423        num: 2,
1424        forward: 7,
1425        right: 7,
1426    },
1427    MoveEnc {
1428        encoding: 0x21,
1429        piece: 'R',
1430        num: 2,
1431        forward: 0,
1432        right: 7,
1433    },
1434    MoveEnc {
1435        encoding: 0x22,
1436        piece: 'B',
1437        num: 2,
1438        forward: 2,
1439        right: -2,
1440    },
1441    MoveEnc {
1442        encoding: 0x23,
1443        piece: 'Q',
1444        num: 2,
1445        forward: 6,
1446        right: 6,
1447    },
1448    MoveEnc {
1449        encoding: 0x24,
1450        piece: 'P',
1451        num: 8,
1452        forward: 1,
1453        right: -1,
1454    },
1455    MoveEnc {
1456        encoding: 0x26,
1457        piece: 'B',
1458        num: 1,
1459        forward: 7,
1460        right: -7,
1461    },
1462    MoveEnc {
1463        encoding: 0x27,
1464        piece: 'P',
1465        num: 3,
1466        forward: 1,
1467        right: -1,
1468    },
1469    MoveEnc {
1470        encoding: 0x28,
1471        piece: 'Q',
1472        num: 1,
1473        forward: 5,
1474        right: 5,
1475    },
1476    MoveEnc {
1477        encoding: 0x29,
1478        piece: 'Q',
1479        num: 1,
1480        forward: 0,
1481        right: 6,
1482    },
1483    MoveEnc {
1484        encoding: 0x2a,
1485        piece: 'N',
1486        num: 2,
1487        forward: -2,
1488        right: 1,
1489    },
1490    MoveEnc {
1491        encoding: 0x2d,
1492        piece: 'P',
1493        num: 6,
1494        forward: 1,
1495        right: 1,
1496    },
1497    MoveEnc {
1498        encoding: 0x2e,
1499        piece: 'B',
1500        num: 1,
1501        forward: 1,
1502        right: 1,
1503    },
1504    MoveEnc {
1505        encoding: 0x2f,
1506        piece: 'Q',
1507        num: 1,
1508        forward: 0,
1509        right: 1,
1510    },
1511    MoveEnc {
1512        encoding: 0x30,
1513        piece: 'N',
1514        num: 2,
1515        forward: -2,
1516        right: -1,
1517    },
1518    MoveEnc {
1519        encoding: 0x31,
1520        piece: 'Q',
1521        num: 1,
1522        forward: 0,
1523        right: 3,
1524    },
1525    MoveEnc {
1526        encoding: 0x32,
1527        piece: 'B',
1528        num: 2,
1529        forward: 5,
1530        right: 5,
1531    },
1532    MoveEnc {
1533        encoding: 0x34,
1534        piece: 'N',
1535        num: 1,
1536        forward: 2,
1537        right: 1,
1538    },
1539    MoveEnc {
1540        encoding: 0x36,
1541        piece: 'N',
1542        num: 1,
1543        forward: 1,
1544        right: 2,
1545    },
1546    MoveEnc {
1547        encoding: 0x37,
1548        piece: 'Q',
1549        num: 1,
1550        forward: 4,
1551        right: 0,
1552    },
1553    MoveEnc {
1554        encoding: 0x38,
1555        piece: 'Q',
1556        num: 2,
1557        forward: 4,
1558        right: -4,
1559    },
1560    MoveEnc {
1561        encoding: 0x39,
1562        piece: 'Q',
1563        num: 1,
1564        forward: 0,
1565        right: 5,
1566    },
1567    MoveEnc {
1568        encoding: 0x3a,
1569        piece: 'B',
1570        num: 1,
1571        forward: 6,
1572        right: 6,
1573    },
1574    MoveEnc {
1575        encoding: 0x3b,
1576        piece: 'Q',
1577        num: 2,
1578        forward: 5,
1579        right: -5,
1580    },
1581    MoveEnc {
1582        encoding: 0x3c,
1583        piece: 'B',
1584        num: 1,
1585        forward: 5,
1586        right: -5,
1587    },
1588    MoveEnc {
1589        encoding: 0x41,
1590        piece: 'Q',
1591        num: 2,
1592        forward: 5,
1593        right: 5,
1594    },
1595    MoveEnc {
1596        encoding: 0x42,
1597        piece: 'Q',
1598        num: 1,
1599        forward: 7,
1600        right: -7,
1601    },
1602    MoveEnc {
1603        encoding: 0x44,
1604        piece: 'K',
1605        num: 1,
1606        forward: -1,
1607        right: 1,
1608    },
1609    MoveEnc {
1610        encoding: 0x45,
1611        piece: 'Q',
1612        num: 1,
1613        forward: 3,
1614        right: 3,
1615    },
1616    MoveEnc {
1617        encoding: 0x4a,
1618        piece: 'P',
1619        num: 8,
1620        forward: 2,
1621        right: 0,
1622    },
1623    MoveEnc {
1624        encoding: 0x4b,
1625        piece: 'Q',
1626        num: 1,
1627        forward: 5,
1628        right: -5,
1629    },
1630    MoveEnc {
1631        encoding: 0x4c,
1632        piece: 'N',
1633        num: 2,
1634        forward: 2,
1635        right: 1,
1636    },
1637    MoveEnc {
1638        encoding: 0x4d,
1639        piece: 'Q',
1640        num: 2,
1641        forward: 1,
1642        right: 0,
1643    },
1644    MoveEnc {
1645        encoding: 0x50,
1646        piece: 'R',
1647        num: 1,
1648        forward: 6,
1649        right: 0,
1650    },
1651    MoveEnc {
1652        encoding: 0x52,
1653        piece: 'R',
1654        num: 1,
1655        forward: 0,
1656        right: 6,
1657    },
1658    MoveEnc {
1659        encoding: 0x54,
1660        piece: 'B',
1661        num: 2,
1662        forward: 1,
1663        right: -1,
1664    },
1665    MoveEnc {
1666        encoding: 0x55,
1667        piece: 'P',
1668        num: 3,
1669        forward: 1,
1670        right: 0,
1671    },
1672    MoveEnc {
1673        encoding: 0x5c,
1674        piece: 'P',
1675        num: 7,
1676        forward: 1,
1677        right: 1,
1678    },
1679    MoveEnc {
1680        encoding: 0x5f,
1681        piece: 'P',
1682        num: 5,
1683        forward: 2,
1684        right: 0,
1685    },
1686    MoveEnc {
1687        encoding: 0x61,
1688        piece: 'Q',
1689        num: 1,
1690        forward: 6,
1691        right: 6,
1692    },
1693    MoveEnc {
1694        encoding: 0x62,
1695        piece: 'P',
1696        num: 2,
1697        forward: 2,
1698        right: 0,
1699    },
1700    MoveEnc {
1701        encoding: 0x63,
1702        piece: 'Q',
1703        num: 2,
1704        forward: 7,
1705        right: -7,
1706    },
1707    MoveEnc {
1708        encoding: 0x66,
1709        piece: 'B',
1710        num: 1,
1711        forward: 3,
1712        right: -3,
1713    },
1714    MoveEnc {
1715        encoding: 0x67,
1716        piece: 'K',
1717        num: 1,
1718        forward: 1,
1719        right: 1,
1720    },
1721    MoveEnc {
1722        encoding: 0x69,
1723        piece: 'R',
1724        num: 2,
1725        forward: 7,
1726        right: 0,
1727    },
1728    MoveEnc {
1729        encoding: 0x6a,
1730        piece: 'B',
1731        num: 1,
1732        forward: 4,
1733        right: 4,
1734    },
1735    MoveEnc {
1736        /* short castling */
1737        encoding: 0x6b,
1738        piece: 'K',
1739        num: 1,
1740        forward: 0,
1741        right: 2,
1742    },
1743    MoveEnc {
1744        encoding: 0x6e,
1745        piece: 'R',
1746        num: 1,
1747        forward: 0,
1748        right: 5,
1749    },
1750    MoveEnc {
1751        encoding: 0x6f,
1752        piece: 'Q',
1753        num: 2,
1754        forward: 7,
1755        right: 7,
1756    },
1757    MoveEnc {
1758        encoding: 0x72,
1759        piece: 'B',
1760        num: 2,
1761        forward: 7,
1762        right: -7,
1763    },
1764    MoveEnc {
1765        encoding: 0x74,
1766        piece: 'Q',
1767        num: 1,
1768        forward: 0,
1769        right: 2,
1770    },
1771    MoveEnc {
1772        encoding: 0x79,
1773        piece: 'B',
1774        num: 2,
1775        forward: 6,
1776        right: -6,
1777    },
1778    MoveEnc {
1779        encoding: 0x7a,
1780        piece: 'R',
1781        num: 1,
1782        forward: 3,
1783        right: 0,
1784    },
1785    MoveEnc {
1786        encoding: 0x7b,
1787        piece: 'R',
1788        num: 2,
1789        forward: 6,
1790        right: 0,
1791    },
1792    MoveEnc {
1793        encoding: 0x7c,
1794        piece: 'P',
1795        num: 3,
1796        forward: 1,
1797        right: 1,
1798    },
1799    MoveEnc {
1800        encoding: 0x7d,
1801        piece: 'R',
1802        num: 2,
1803        forward: 1,
1804        right: 0,
1805    },
1806    MoveEnc {
1807        encoding: 0x7e,
1808        piece: 'Q',
1809        num: 1,
1810        forward: 3,
1811        right: -3,
1812    },
1813    MoveEnc {
1814        encoding: 0x7f,
1815        piece: 'R',
1816        num: 1,
1817        forward: 0,
1818        right: 1,
1819    },
1820    MoveEnc {
1821        encoding: 0x80,
1822        piece: 'Q',
1823        num: 1,
1824        forward: 6,
1825        right: -6,
1826    },
1827    MoveEnc {
1828        encoding: 0x81,
1829        piece: 'R',
1830        num: 1,
1831        forward: 1,
1832        right: 0,
1833    },
1834    MoveEnc {
1835        encoding: 0x82,
1836        piece: 'P',
1837        num: 6,
1838        forward: 1,
1839        right: -1,
1840    },
1841    MoveEnc {
1842        encoding: 0x85,
1843        piece: 'N',
1844        num: 1,
1845        forward: 2,
1846        right: -1,
1847    },
1848    MoveEnc {
1849        encoding: 0x86,
1850        piece: 'R',
1851        num: 1,
1852        forward: 0,
1853        right: 7,
1854    },
1855    MoveEnc {
1856        encoding: 0x87,
1857        piece: 'R',
1858        num: 1,
1859        forward: 5,
1860        right: 0,
1861    },
1862    MoveEnc {
1863        encoding: 0x8a,
1864        piece: 'N',
1865        num: 1,
1866        forward: -2,
1867        right: 1,
1868    },
1869    MoveEnc {
1870        encoding: 0x8b,
1871        piece: 'P',
1872        num: 1,
1873        forward: 1,
1874        right: 1,
1875    },
1876    MoveEnc {
1877        encoding: 0x8c,
1878        piece: 'K',
1879        num: 1,
1880        forward: -1,
1881        right: -1,
1882    },
1883    MoveEnc {
1884        encoding: 0x8e,
1885        piece: 'Q',
1886        num: 2,
1887        forward: 2,
1888        right: -2,
1889    },
1890    MoveEnc {
1891        encoding: 0x8f,
1892        piece: 'Q',
1893        num: 1,
1894        forward: 0,
1895        right: 7,
1896    },
1897    MoveEnc {
1898        encoding: 0x92,
1899        piece: 'Q',
1900        num: 2,
1901        forward: 1,
1902        right: 1,
1903    },
1904    MoveEnc {
1905        encoding: 0x94,
1906        piece: 'Q',
1907        num: 1,
1908        forward: 3,
1909        right: 0,
1910    },
1911    MoveEnc {
1912        encoding: 0x96,
1913        piece: 'P',
1914        num: 2,
1915        forward: 1,
1916        right: 1,
1917    },
1918    MoveEnc {
1919        encoding: 0x97,
1920        piece: 'K',
1921        num: 1,
1922        forward: 0,
1923        right: -1,
1924    },
1925    MoveEnc {
1926        encoding: 0x98,
1927        piece: 'R',
1928        num: 1,
1929        forward: 0,
1930        right: 3,
1931    },
1932    MoveEnc {
1933        encoding: 0x99,
1934        piece: 'R',
1935        num: 1,
1936        forward: 4,
1937        right: 0,
1938    },
1939    MoveEnc {
1940        encoding: 0x9a,
1941        piece: 'Q',
1942        num: 1,
1943        forward: 6,
1944        right: 0,
1945    },
1946    MoveEnc {
1947        encoding: 0x9b,
1948        piece: 'P',
1949        num: 3,
1950        forward: 2,
1951        right: 0,
1952    },
1953    MoveEnc {
1954        encoding: 0x9d,
1955        piece: 'Q',
1956        num: 1,
1957        forward: 2,
1958        right: 0,
1959    },
1960    MoveEnc {
1961        encoding: 0x9f,
1962        piece: 'B',
1963        num: 2,
1964        forward: 4,
1965        right: -4,
1966    },
1967    MoveEnc {
1968        encoding: 0xa0,
1969        piece: 'Q',
1970        num: 2,
1971        forward: 3,
1972        right: 0,
1973    },
1974    MoveEnc {
1975        encoding: 0xa2,
1976        piece: 'Q',
1977        num: 1,
1978        forward: 2,
1979        right: 2,
1980    },
1981    MoveEnc {
1982        encoding: 0xa3,
1983        piece: 'P',
1984        num: 8,
1985        forward: 1,
1986        right: 0,
1987    },
1988    MoveEnc {
1989        encoding: 0xa5,
1990        piece: 'R',
1991        num: 2,
1992        forward: 5,
1993        right: 0,
1994    },
1995    MoveEnc {
1996        encoding: 0xa9,
1997        piece: 'R',
1998        num: 2,
1999        forward: 0,
2000        right: 2,
2001    },
2002    MoveEnc {
2003        encoding: 0xab,
2004        piece: 'Q',
2005        num: 2,
2006        forward: 6,
2007        right: -6,
2008    },
2009    MoveEnc {
2010        encoding: 0xad,
2011        piece: 'R',
2012        num: 2,
2013        forward: 0,
2014        right: 4,
2015    },
2016    MoveEnc {
2017        encoding: 0xae,
2018        piece: 'Q',
2019        num: 2,
2020        forward: 3,
2021        right: 3,
2022    },
2023    MoveEnc {
2024        encoding: 0xb0,
2025        piece: 'Q',
2026        num: 2,
2027        forward: 4,
2028        right: 0,
2029    },
2030    MoveEnc {
2031        encoding: 0xb1,
2032        piece: 'P',
2033        num: 6,
2034        forward: 2,
2035        right: 0,
2036    },
2037    MoveEnc {
2038        encoding: 0xb2,
2039        piece: 'B',
2040        num: 1,
2041        forward: 6,
2042        right: -6,
2043    },
2044    MoveEnc {
2045        encoding: 0xb5,
2046        piece: 'R',
2047        num: 2,
2048        forward: 0,
2049        right: 5,
2050    },
2051    MoveEnc {
2052        encoding: 0xb7,
2053        piece: 'Q',
2054        num: 1,
2055        forward: 5,
2056        right: 0,
2057    },
2058    MoveEnc {
2059        encoding: 0xb9,
2060        piece: 'B',
2061        num: 2,
2062        forward: 3,
2063        right: 3,
2064    },
2065    MoveEnc {
2066        encoding: 0xbb,
2067        piece: 'P',
2068        num: 5,
2069        forward: 1,
2070        right: 0,
2071    },
2072    MoveEnc {
2073        encoding: 0xbc,
2074        piece: 'Q',
2075        num: 2,
2076        forward: 0,
2077        right: 5,
2078    },
2079    MoveEnc {
2080        encoding: 0xbd,
2081        piece: 'Q',
2082        num: 2,
2083        forward: 2,
2084        right: 0,
2085    },
2086    MoveEnc {
2087        encoding: 0xbe,
2088        piece: 'K',
2089        num: 1,
2090        forward: 0,
2091        right: 1,
2092    },
2093    MoveEnc {
2094        encoding: 0xc1,
2095        piece: 'B',
2096        num: 1,
2097        forward: 2,
2098        right: 2,
2099    },
2100    MoveEnc {
2101        encoding: 0xc2,
2102        piece: 'B',
2103        num: 2,
2104        forward: 2,
2105        right: 2,
2106    },
2107    MoveEnc {
2108        encoding: 0xc3,
2109        piece: 'B',
2110        num: 1,
2111        forward: 2,
2112        right: -2,
2113    },
2114    MoveEnc {
2115        encoding: 0xc4,
2116        piece: 'R',
2117        num: 2,
2118        forward: 0,
2119        right: 1,
2120    },
2121    MoveEnc {
2122        encoding: 0xc5,
2123        piece: 'R',
2124        num: 2,
2125        forward: 4,
2126        right: 0,
2127    },
2128    MoveEnc {
2129        encoding: 0xc6,
2130        piece: 'Q',
2131        num: 2,
2132        forward: 5,
2133        right: 0,
2134    },
2135    MoveEnc {
2136        encoding: 0xc7,
2137        piece: 'P',
2138        num: 7,
2139        forward: 1,
2140        right: -1,
2141    },
2142    MoveEnc {
2143        encoding: 0xc8,
2144        piece: 'P',
2145        num: 7,
2146        forward: 2,
2147        right: 0,
2148    },
2149    MoveEnc {
2150        encoding: 0xc9,
2151        piece: 'Q',
2152        num: 2,
2153        forward: 7,
2154        right: 0,
2155    },
2156    MoveEnc {
2157        encoding: 0xca,
2158        piece: 'B',
2159        num: 2,
2160        forward: 3,
2161        right: -3,
2162    },
2163    MoveEnc {
2164        encoding: 0xcb,
2165        piece: 'P',
2166        num: 6,
2167        forward: 1,
2168        right: 0,
2169    },
2170    MoveEnc {
2171        encoding: 0xcc,
2172        piece: 'B',
2173        num: 2,
2174        forward: 5,
2175        right: -5,
2176    },
2177    MoveEnc {
2178        encoding: 0xcd,
2179        piece: 'R',
2180        num: 1,
2181        forward: 0,
2182        right: 2,
2183    },
2184    MoveEnc {
2185        encoding: 0xcf,
2186        piece: 'P',
2187        num: 4,
2188        forward: 1,
2189        right: 0,
2190    },
2191    MoveEnc {
2192        encoding: 0xd1,
2193        piece: 'P',
2194        num: 2,
2195        forward: 1,
2196        right: -1,
2197    },
2198    MoveEnc {
2199        encoding: 0xd2,
2200        piece: 'N',
2201        num: 2,
2202        forward: 1,
2203        right: 2,
2204    },
2205    MoveEnc {
2206        encoding: 0xd3,
2207        piece: 'N',
2208        num: 2,
2209        forward: 1,
2210        right: -2,
2211    },
2212    MoveEnc {
2213        encoding: 0xd7,
2214        piece: 'Q',
2215        num: 1,
2216        forward: 1,
2217        right: -1,
2218    },
2219    MoveEnc {
2220        encoding: 0xd8,
2221        piece: 'R',
2222        num: 2,
2223        forward: 0,
2224        right: 6,
2225    },
2226    MoveEnc {
2227        encoding: 0xd9,
2228        piece: 'Q',
2229        num: 1,
2230        forward: 2,
2231        right: -2,
2232    },
2233    MoveEnc {
2234        encoding: 0xda,
2235        piece: 'N',
2236        num: 1,
2237        forward: -2,
2238        right: -1,
2239    },
2240    MoveEnc {
2241        encoding: 0xdb,
2242        piece: 'P',
2243        num: 1,
2244        forward: 2,
2245        right: 0,
2246    },
2247    MoveEnc {
2248        encoding: 0xde,
2249        piece: 'P',
2250        num: 5,
2251        forward: 1,
2252        right: -1,
2253    },
2254    MoveEnc {
2255        encoding: 0xdf,
2256        piece: 'K',
2257        num: 1,
2258        forward: 1,
2259        right: -1,
2260    },
2261    MoveEnc {
2262        encoding: 0xe0,
2263        piece: 'N',
2264        num: 2,
2265        forward: -1,
2266        right: 2,
2267    },
2268    MoveEnc {
2269        encoding: 0xe1,
2270        piece: 'R',
2271        num: 1,
2272        forward: 7,
2273        right: 0,
2274    },
2275    MoveEnc {
2276        encoding: 0xe3,
2277        piece: 'R',
2278        num: 2,
2279        forward: 3,
2280        right: 0,
2281    },
2282    MoveEnc {
2283        encoding: 0xe5,
2284        piece: 'Q',
2285        num: 1,
2286        forward: 0,
2287        right: 4,
2288    },
2289    MoveEnc {
2290        encoding: 0xe6,
2291        piece: 'P',
2292        num: 4,
2293        forward: 2,
2294        right: 0,
2295    },
2296    MoveEnc {
2297        encoding: 0xe7,
2298        piece: 'Q',
2299        num: 1,
2300        forward: 4,
2301        right: 4,
2302    },
2303    MoveEnc {
2304        encoding: 0xe8,
2305        piece: 'R',
2306        num: 1,
2307        forward: 2,
2308        right: 0,
2309    },
2310    MoveEnc {
2311        encoding: 0xe9,
2312        piece: 'N',
2313        num: 1,
2314        forward: -1,
2315        right: 2,
2316    },
2317    MoveEnc {
2318        encoding: 0xeb,
2319        piece: 'P',
2320        num: 4,
2321        forward: 1,
2322        right: 1,
2323    },
2324    MoveEnc {
2325        encoding: 0xec,
2326        piece: 'P',
2327        num: 1,
2328        forward: 1,
2329        right: 0,
2330    },
2331    MoveEnc {
2332        encoding: 0xed,
2333        piece: 'Q',
2334        num: 1,
2335        forward: 7,
2336        right: 7,
2337    },
2338    MoveEnc {
2339        encoding: 0xee,
2340        piece: 'Q',
2341        num: 2,
2342        forward: 1,
2343        right: -1,
2344    },
2345    MoveEnc {
2346        encoding: 0xef,
2347        piece: 'R',
2348        num: 1,
2349        forward: 0,
2350        right: 4,
2351    },
2352    MoveEnc {
2353        encoding: 0xf0,
2354        piece: 'Q',
2355        num: 2,
2356        forward: 0,
2357        right: 7,
2358    },
2359    MoveEnc {
2360        encoding: 0xf1,
2361        piece: 'Q',
2362        num: 1,
2363        forward: 1,
2364        right: 1,
2365    },
2366    MoveEnc {
2367        encoding: 0xf3,
2368        piece: 'N',
2369        num: 2,
2370        forward: 2,
2371        right: -1,
2372    },
2373    MoveEnc {
2374        encoding: 0xf4,
2375        piece: 'R',
2376        num: 2,
2377        forward: 2,
2378        right: 0,
2379    },
2380    MoveEnc {
2381        encoding: 0xf5,
2382        piece: 'B',
2383        num: 2,
2384        forward: 1,
2385        right: 1,
2386    },
2387    MoveEnc {
2388        /* long castling */
2389        encoding: 0xf6,
2390        piece: 'K',
2391        num: 1,
2392        forward: 0,
2393        right: -2,
2394    },
2395    MoveEnc {
2396        encoding: 0xf7,
2397        piece: 'N',
2398        num: 1,
2399        forward: 1,
2400        right: -2,
2401    },
2402    MoveEnc {
2403        encoding: 0xf8,
2404        piece: 'Q',
2405        num: 2,
2406        forward: 0,
2407        right: 1,
2408    },
2409    MoveEnc {
2410        encoding: 0xf9,
2411        piece: 'Q',
2412        num: 2,
2413        forward: 6,
2414        right: 0,
2415    },
2416    MoveEnc {
2417        encoding: 0xfa,
2418        piece: 'Q',
2419        num: 2,
2420        forward: 0,
2421        right: 3,
2422    },
2423    MoveEnc {
2424        encoding: 0xfb,
2425        piece: 'Q',
2426        num: 2,
2427        forward: 2,
2428        right: 2,
2429    },
2430    MoveEnc {
2431        encoding: 0xfd,
2432        piece: 'Q',
2433        num: 1,
2434        forward: 7,
2435        right: 0,
2436    },
2437    MoveEnc {
2438        encoding: 0xfe,
2439        piece: 'Q',
2440        num: 2,
2441        forward: 3,
2442        right: -3,
2443    },
2444];
2445
2446#[cfg(test)]
2447mod tests {
2448    use shakmaty::*;
2449
2450    use super::*;
2451
2452    #[test]
2453    fn test_byteboard_from_board() {
2454        let pos = Chess::default();
2455        let epd = format!(
2456            "{}",
2457            shakmaty::fen::Epd::from_position(pos.clone(), EnPassantMode::PseudoLegal)
2458        );
2459        let bb0 = ByteBoard::from_fen(epd.as_bytes()).expect("invalid fen");
2460        let bb1 = ByteBoard::from_board(&pos.board());
2461
2462        assert_eq!(bb0, bb1);
2463    }
2464}