2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@sns.it>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
12 #include "xchess/animator.h"
13 #include "xchess/piece.h"
14 #include "xchess/move.h"
15 #include "moveserializer.impl.h"
16 #include "xchess/dropanimator.impl.h"
17 #include "crazyhouse_p.h"
18 #include "interactiontype.h"
19 #include "turnpolicy.h"
20 #include "tagua_wrapped.h"
21 #include "icsapi.impl.h"
41 typedef bool PromotionType
;
48 : m_color(INVALID_COLOR
)
49 , m_type(INVALID_TYPE
)
50 , m_promoted(false) { }
51 ShogiPiece(ShogiPiece::Color color
, ShogiPiece::Type type
, bool promoted
= false);
52 ShogiPiece(const ShogiPiece
& other
);
54 void promote() { m_promoted
= true; }
55 bool promoted() { return m_promoted
; }
57 bool operator<(const ShogiPiece
& p
) const {
58 if (m_promoted
== p
.m_promoted
)
59 if (m_color
== p
.m_color
)
60 return m_type
< p
.m_type
;
62 return m_color
< p
.m_color
;
64 return m_promoted
< p
.m_promoted
;
68 static QString
typeName(ShogiPiece::Type t
);
69 bool valid() const { return m_color
!= INVALID_COLOR
&& m_type
!= INVALID_TYPE
; }
70 operator bool() const { return valid(); }
71 bool operator!() const { return !valid(); }
73 bool equals(const ShogiPiece
* p
) const {
76 return (*this) == (*p
);
84 bool operator==(const ShogiPiece
& p
) const {
85 return m_promoted
== p
.m_promoted
&&
86 m_color
== p
.m_color
&&
90 bool operator!=(const ShogiPiece
& p
) const {
91 return !(operator==(p
));
94 static Type
getType(const QString
& t
);
95 static QString
typeSymbol(ShogiPiece::Type t
);
97 bool canMove(const class ShogiPosition
&, const Point
&, const Point
&) const;
98 Color
color() const { return m_color
; }
99 Type
type() const { return m_type
; }
101 static Color
oppositeColor(Color c
) { return c
== WHITE
? BLACK
: WHITE
; }
102 Point
direction() const { return Point(0, m_color
== WHITE
? 1 : -1); }
105 ShogiPiece::ShogiPiece(ShogiPiece::Color color
, ShogiPiece::Type type
, bool promoted
)
108 , m_promoted(promoted
) { }
110 ShogiPiece::ShogiPiece(const ShogiPiece
& other
)
111 : m_color(other
.m_color
)
112 , m_type(other
.m_type
)
113 , m_promoted(other
.m_promoted
) { }
115 QString
ShogiPiece::name() const {
116 QString res
= m_color
== WHITE
? "white_" : "black_";
119 res
+= typeName(m_type
);
123 QString
ShogiPiece::typeName(ShogiPiece::Type t
) {
146 ShogiPiece::Type
ShogiPiece::getType(const QString
&) {
147 return KING
; // FIXME
150 QString
ShogiPiece::typeSymbol(ShogiPiece::Type t
) {
173 // ------------------------------
182 template<typename T
> friend class MoveSerializer
;
188 ShogiMove(const Point
& from
, const Point
& to
, bool promote
);
189 ShogiMove(int pool
, int pool_index
, const Point
& to
);
191 QString
toString(int, int) const;
193 bool operator==(const ShogiMove
& other
) const;
195 const ShogiPiece
& drop() const { return m_drop
; }
196 void setDrop(const ShogiPiece
& piece
) { m_drop
= piece
; }
197 int pool() const { return m_pool
; }
198 int poolIndex() const { return m_pool_index
; }
200 bool promote() const { return m_promote
; }
201 bool valid() const { return to
.valid(); }
204 ShogiMove::ShogiMove()
208 , from(Point::invalid())
209 , to(Point::invalid()) { }
211 ShogiMove::ShogiMove(const Point
& from
, const Point
& to
, bool promote
)
218 ShogiMove::ShogiMove(int pool
, int pool_index
, const Point
& to
)
220 , m_pool_index(pool_index
)
222 , from(Point::invalid())
225 QString
ShogiMove::toString(int xsize
, int ysize
) const {
226 QString res
= from
.numcol(xsize
) + from
.alpharow()
227 + to
.numcol(xsize
) + to
.alpharow();
228 //if (m_promote) res = res + "+";
233 bool ShogiMove::operator==(const ShogiMove
& other
) const {
235 return m_drop
== other
.m_drop
238 return m_promote
== other
.m_promote
240 && from
== other
.from
;
243 // ------------------------------
245 class ShogiPosition
{
247 typedef ShogiPiece Piece
;
248 typedef ShogiMove Move
;
250 typedef PoolReference
<ShogiPosition
> PoolReference
;
251 typedef PoolConstReference
<ShogiPosition
> PoolConstReference
;
252 typedef PoolReference::Pool Pool
;
253 typedef PoolReference::PlayerPool PlayerPool
;
259 template<typename T
> friend class MoveSerializer
;
261 ShogiPosition(const ShogiPosition
&);
262 ShogiPosition(Piece::Color turn
, bool wk
, bool wq
,
263 bool bk
, bool bq
, const Point
& ep
);
264 ShogiPosition(const QList
<boost::shared_ptr
<BaseOpt
> >& opts
);
265 virtual ShogiPosition
* clone() const { return new ShogiPosition(*this); }
266 virtual ~ShogiPosition() { }
268 virtual void setup();
270 bool testMove(Move
&) const;
271 bool pseudolegal(Move
& m
) const;
273 PoolReference
pool(int);
274 PoolConstReference
pool(int) const;
276 PlayerPool
& rawPool(Piece::Color color
) { return m_pool
[color
]; }
277 const PlayerPool
& rawPool(Piece::Color color
) const { return const_cast<Pool
&>(m_pool
)[color
]; }
279 virtual const Point
first() const { return m_board
.first(); }
280 virtual const Point
last() const { return m_board
.last(); }
281 virtual Point
next(const Point
& p
) const { return m_board
.next(p
); }
282 inline bool valid(const Point
& p
) const { return m_board
.valid(p
); }
284 ShogiPiece
get(const Point
& p
) const;
285 void set(const Point
& p
, const Piece
& piece
);
287 ShogiPiece
operator[](const Point
& p
) const { return m_board
[p
]; }
289 Piece::Color
turn() const { return m_turn
; }
290 void setTurn(Piece::Color turn
) { m_turn
= turn
; }
291 Piece::Color
previousTurn() const { return Piece::oppositeColor(m_turn
); }
292 void switchTurn() { m_turn
= Piece::oppositeColor(m_turn
); }
294 InteractionType
movable(const TurnTest
& test
, const Point
& p
) const {
295 if (!valid(p
) || !m_board
[p
] || !test(m_board
[p
].color()))
297 return m_board
[p
].color() == m_turn
? Moving
: Premoving
;
299 InteractionType
droppable(const TurnTest
& test
, int p
) const {
302 ShogiPiece::Color c
= static_cast<ShogiPiece::Color
>(p
);
303 return c
== m_turn
? Moving
: Premoving
;
305 void move(const ShogiMove
& m
);
307 void fromFEN(const QString
&, bool& ok
) { ok
= false; }
308 QString
fen(int, int) const { return ""; }
309 bool operator==(const ShogiPosition
& p
) const;
311 static Move
getVerboseMove(Piece::Color turn
, const VerboseNotation
& m
);
312 Move
getMove(const AlgebraicNotation
&, bool& ok
) const;
313 boost::shared_ptr
<ShogiPiece
> moveHint(const ShogiMove
& m
) const;
315 Point
size() const { return Point(9,9); }
316 void dump() const { }
318 static bool promotionZone(Piece::Color color
, const Point
& p
);
319 static bool stuckPiece(const Piece
& piece
, const Point
& to
);
320 PathInfo
path(const Point
& from
, const Point
& to
) const { return m_board
.path(from
, to
); }
321 QStringList
borderCoords() const;
324 ShogiPosition::ShogiPosition()
325 : m_turn(ShogiPiece::BLACK
)
328 ShogiPosition::ShogiPosition(const ShogiPosition
& other
)
329 : m_turn(other
.m_turn
)
330 , m_board(other
.m_board
)
331 , m_pool(other
.m_pool
) { }
333 ShogiPosition::ShogiPosition(Piece::Color turn
, bool, bool, bool, bool, const Point
&)
337 ShogiPosition::ShogiPosition(const QList
<boost::shared_ptr
<BaseOpt
> >&)
338 : m_turn(ShogiPiece::BLACK
)
341 QStringList
ShogiPosition::borderCoords() const
344 for(int i
=m_board
.getSize().y
; i
>0; i
--)
345 retv
+= QString::number(i
);
346 retv
<< QChar(0x4e5d) << QChar(0x516b) << QChar(0x4e03) << QChar(0x516d)
347 << QChar(0x4e94) << QChar(0x56db) << QChar(0x4e09) << QChar(0x4e8c) << QChar(0x4e00);
351 bool ShogiPiece::canMove(const ShogiPosition
& pos
,
352 const Point
& from
, const Point
& to
) const {
353 if (!from
.valid()) return false;
354 if (!to
.valid()) return false;
355 if (from
== to
) return false;
356 if (pos
[to
].color() == m_color
) return false;
357 Point delta
= to
- from
;
362 return abs(delta
.x
) <= 1 && abs(delta
.y
) <= 1;
364 return (delta
.x
== 0 && abs(delta
.y
) == 1)
365 || (delta
.y
== 0 && abs(delta
.x
) == 1)
366 || (delta
.y
== direction().y
&& abs(delta
.x
) <= 1);
368 return (abs(delta
.x
) == abs(delta
.y
) && abs(delta
.x
) == 1)
369 || (delta
.y
== direction().y
&& abs(delta
.x
) <= 1);
372 PathInfo path
= pos
.path(from
, to
);
373 return path
.parallel() && path
.clear();
377 PathInfo path
= pos
.path(from
, to
);
378 return path
.diagonal() && path
.clear();
382 return abs(delta
.x
) == 1 && delta
.y
== direction().y
* 2;
386 PathInfo path
= pos
.path(from
, to
);
387 return delta
.x
== 0 && path
.clear() && (delta
.y
* direction().y
> 0);
390 return delta
.x
== 0 && delta
.y
== direction().y
;
401 return (delta
.x
== 0 && abs(delta
.y
) == 1)
402 || (delta
.y
== 0 && abs(delta
.x
) == 1)
403 || (delta
.y
== direction().y
&& abs(delta
.x
) <= 1);
406 if (abs(delta
.x
) <= 1 && abs(delta
.y
) <= 1) return true;
407 PathInfo path
= pos
.path(from
, to
);
408 return path
.parallel() && path
.clear();
412 if (abs(delta
.x
) <= 1 && abs(delta
.y
) <= 1) return true;
413 PathInfo path
= pos
.path(from
, to
);
414 return path
.diagonal() && path
.clear();
423 ShogiPosition::Move
ShogiPosition::getVerboseMove(Piece::Color
, const VerboseNotation
&) {
427 ShogiPosition::Move
ShogiPosition::getMove(const AlgebraicNotation
&, bool& ok
) const {
432 ShogiPiece
ShogiPosition::get(const Point
& p
) const {
433 if (m_board
.valid(p
)) {
441 void ShogiPosition::set(const Point
& p
, const ShogiPiece
& piece
) {
442 if (m_board
.valid(p
)) {
447 ShogiPosition::PoolReference
ShogiPosition::pool(int index
) {
448 ShogiPiece::Color color
= static_cast<ShogiPiece::Color
>(index
);
449 return PoolReference(&m_pool
[color
], color
);
452 ShogiPosition::PoolConstReference
ShogiPosition::pool(int index
) const {
453 ShogiPiece::Color color
= static_cast<ShogiPiece::Color
>(index
);
454 return PoolConstReference(&m_pool
[color
], color
);
457 bool ShogiPosition::operator==(const ShogiPosition
& p
) const {
458 return m_turn
== p
.m_turn
459 && m_board
== p
.m_board
;
462 boost::shared_ptr
<ShogiPiece
> ShogiPosition::moveHint(const ShogiMove
& m
) const {
463 if (m
.drop()) return boost::shared_ptr
<ShogiPiece
>(new ShogiPiece(m
.drop()));
464 else return boost::shared_ptr
<ShogiPiece
>();
467 bool ShogiPosition::promotionZone(Piece::Color color
, const Point
& p
) {
468 return color
== ShogiPiece::WHITE
? p
.y
>= 6 : p
.y
<= 2;
471 #define SET_PIECE(i,j, color, type) m_board[Point(i,j)] = Piece(ShogiPiece::color, ShogiPiece::type)
472 void ShogiPosition::setup() {
473 for (int i
= 0; i
< m_board
.getSize().x
; i
++) {
474 SET_PIECE(i
, 2, WHITE
, PAWN
);
475 SET_PIECE(i
, 6, BLACK
, PAWN
);
478 SET_PIECE(0,0, WHITE
, LANCE
);
479 SET_PIECE(1,0, WHITE
, KNIGHT
);
480 SET_PIECE(2,0, WHITE
, SILVER
);
481 SET_PIECE(3,0, WHITE
, GOLD
);
482 SET_PIECE(4,0, WHITE
, KING
);
483 SET_PIECE(5,0, WHITE
, GOLD
);
484 SET_PIECE(6,0, WHITE
, SILVER
);
485 SET_PIECE(7,0, WHITE
, KNIGHT
);
486 SET_PIECE(8,0, WHITE
, LANCE
);
487 SET_PIECE(1,1, WHITE
, ROOK
);
488 SET_PIECE(7,1, WHITE
, BISHOP
);
490 SET_PIECE(0,8, BLACK
, LANCE
);
491 SET_PIECE(1,8, BLACK
, KNIGHT
);
492 SET_PIECE(2,8, BLACK
, SILVER
);
493 SET_PIECE(3,8, BLACK
, GOLD
);
494 SET_PIECE(4,8, BLACK
, KING
);
495 SET_PIECE(5,8, BLACK
, GOLD
);
496 SET_PIECE(6,8, BLACK
, SILVER
);
497 SET_PIECE(7,8, BLACK
, KNIGHT
);
498 SET_PIECE(8,8, BLACK
, LANCE
);
499 SET_PIECE(1,7, BLACK
, BISHOP
);
500 SET_PIECE(7,7, BLACK
, ROOK
);
503 m_turn
= ShogiPiece::BLACK
;
507 bool ShogiPosition::testMove(Move
& m
) const {
511 ShogiPosition
tmp(*this);
514 // find king position
515 Point king_pos
= Point::invalid();
516 ShogiPiece
king(m_turn
, ShogiPiece::KING
);
517 for (Point i
= tmp
.m_board
.first(); i
<= tmp
.m_board
.last(); i
= tmp
.m_board
.next(i
)) {
518 if (ShogiPiece p
= tmp
[i
])
524 if (!king_pos
.valid()) return false;
526 // check if the king can be captured
527 for (Point i
= tmp
.m_board
.first(); i
<= tmp
.m_board
.last(); i
= tmp
.m_board
.next(i
)) {
528 if (ShogiPiece p
= tmp
[i
])
529 if (p
.color() == tmp
.turn() && p
.canMove(tmp
, i
, king_pos
)) return false;
535 bool ShogiPosition::stuckPiece(const ShogiPiece
& piece
, const Point
& p
) {
536 if (piece
.type() == Piece::PAWN
) {
537 if (p
.y
== (piece
.color() == Piece::WHITE
? 8 : 0))
540 else if (piece
.type() == Piece::KNIGHT
) {
541 if (piece
.color() == Piece::WHITE
) {
553 bool ShogiPosition::pseudolegal(Move
& m
) const {
554 if (!m
.drop() && m
.pool() != -1 && m
.poolIndex() != -1) {
555 m
.setDrop(pool(m
.pool()).get(m
.poolIndex()));
558 if (ShogiPiece dropped
= m
.drop()) {
559 if (m_board
[m
.to
]) return false;
560 if (stuckPiece(dropped
, m
.to
)) return false;
561 if (dropped
.type() == Piece::PAWN
) {
562 for (int i
= 0; i
< m_board
.getSize().y
; i
++)
563 if (ShogiPiece other
= m_board
[Point(m
.to
.x
, i
)])
564 if (other
.color() == m_turn
&& other
.type() == Piece::PAWN
&& !other
.promoted()) return false;
569 const Piece
& p
= m_board
[m
.from
];
570 return p
&& p
.canMove(*this, m
.from
, m
.to
);
574 void ShogiPosition::move(const ShogiMove
& m
) {
575 if (Piece dropped
= m
.drop()) {
576 m_board
[m
.to
] = dropped
;
577 if (!--rawPool(dropped
.color())[dropped
.type()])
578 rawPool(dropped
.color()).erase(dropped
.type());
581 if (Piece captured
= m_board
[m
.to
]) {
582 rawPool(Piece::oppositeColor(captured
.color()))[captured
.type()]++;
585 m_board
[m
.to
] = m_board
[m
.from
];
586 m_board
[m
.from
] = Piece();
589 if (promotionZone(m_turn
, m
.to
) || promotionZone(m_turn
, m
.from
)) {
590 if (m
.promote() || stuckPiece(m_board
[m
.to
], m
.to
)) {
591 Piece::Type type
= m_board
[m
.to
].type();
592 if (type
!= ShogiPiece::KING
&& type
!= ShogiPiece::GOLD
)
593 m_board
[m
.to
].promote();
600 class ShogiAnimatorBase
;
602 class ShogiVariantInfo
{
604 static QStringList
getNumbers() {
605 return QStringList() << QChar(0x4e5d) << QChar(0x516b) << QChar(0x4e03)
606 << QChar(0x516d) << QChar(0x4e94) << QChar(0x56db)
607 << QChar(0x4e09) << QChar(0x4e8c) << QChar(0x4e00);
610 typedef ShogiPosition Position
;
611 typedef Position::Move Move
;
612 typedef Position::Piece Piece
;
613 typedef DropAnimatorMixin
<ShogiAnimatorBase
> Animator
;
616 static const bool hasICS
= false;
617 static const bool m_simple_moves
= false;
618 static void forallPieces(PieceFunction
& f
);
619 static int moveListLayout() { return 0; }
620 static OptList
positionOptions() { return OptList(); }
621 static const char *m_name
;
622 static const char *m_theme_proxy
;
625 const char *ShogiVariantInfo::m_name
= "Shogi_OLD";
626 const char *ShogiVariantInfo::m_theme_proxy
= "Shogi";
629 void ShogiVariantInfo::forallPieces(PieceFunction
& f
) {
630 ChessVariant::forallPieces(f
);
633 VariantInfo
* ShogiVariant::static_shogi_variant
= 0;
635 VariantInfo
* ShogiVariant::info() {
636 if (!static_shogi_variant
)
637 static_shogi_variant
= new WrappedVariantInfo
<ShogiVariantInfo
>;
638 return static_shogi_variant
;
641 class ShogiAnimatorBase
: public BaseAnimator
<ShogiVariantInfo
> {
643 typedef ShogiVariantInfo Variant
;
645 typedef BaseAnimator
<ShogiVariantInfo
> Base
;
646 typedef Base::API API
;
648 ShogiAnimatorBase(API cinterface
)
649 : Base(cinterface
) { }
651 virtual AnimationGroupPtr
forward(const ShogiPosition
& final
, const ShogiMove
& move
) {
652 AnimationFactory
res(m_cinterface
->inner());
654 NamedSprite piece
= m_cinterface
->takeSprite(move
.from
);
655 NamedSprite captured
= m_cinterface
->takeSprite(move
.to
);
656 m_cinterface
->setSprite(move
.to
, piece
);
659 res
.addPreAnimation(Animate::move(piece
, move
.to
));
662 res
.addPostAnimation(Animate::destroy(captured
));
664 if (final
.get(move
.to
) != m_cinterface
->position()->get(move
.from
)) {
665 Piece promoted
= final
.get(move
.to
);
668 QPoint real
= m_cinterface
->converter()->toReal(move
.to
);
669 NamedSprite old_sprite
= m_cinterface
->getSprite(move
.to
);
670 NamedSprite new_sprite
= m_cinterface
->setPiece(move
.to
, promoted
, false);
672 res
.addPostAnimation(Animate::morph(old_sprite
, new_sprite
));
679 virtual AnimationGroupPtr
back(const ShogiPosition
& final
, const ShogiMove
& move
) {
680 AnimationFactory
res(m_cinterface
->inner());
682 NamedSprite piece
= m_cinterface
->takeSprite(move
.to
);
683 NamedSprite captured
;
684 if (Piece captured_piece
= final
.get(move
.to
)) {
685 captured
= m_cinterface
->setPiece(move
.to
, captured_piece
, false);
686 res
.addPreAnimation(Animate::appear(captured
));
690 piece
= m_cinterface
->createPiece(move
.to
, final
.get(move
.from
), false);
691 res
.addPreAnimation(Animate::appear(piece
));
694 m_cinterface
->setSprite(move
.from
, piece
);
696 if (final
.get(move
.from
) != m_cinterface
->position()->get(move
.to
)) {
697 Piece old_piece
= final
.get(move
.from
);
699 NamedSprite old
= m_cinterface
->createPiece(move
.to
, old_piece
, false);
700 res
.addPreAnimation(Animate::morph(piece
, old
));
702 // replace piece with pawn
703 m_cinterface
->setSprite(move
.from
, old
);
708 res
.addPreAnimation(Animate::move(piece
, move
.from
));
716 class MoveSerializer
<ShogiPosition
> {
717 const ShogiMove
& m_move
;
718 const ShogiPosition
& m_ref
;
719 bool isAmbiguous() const {
720 ShogiPiece p
= m_move
.drop() ? m_move
.drop() : m_ref
.m_board
[m_move
.from
];
721 bool ambiguous
= false;
723 for (Point i
= m_ref
.m_board
.first(); i
<= m_ref
.m_board
.last(); i
= m_ref
.m_board
.next(i
) ) {
724 if (i
==m_move
.from
|| m_ref
.m_board
[i
] != p
)
726 ShogiMove
mv(i
, m_move
.to
, false);
727 if (m_ref
.testMove(mv
)) {
735 MoveSerializer(const ShogiMove
& m
, const ShogiPosition
& r
)
736 : m_move(m
), m_ref(r
) { }
738 QString
SAN() const {
739 ShogiPiece p
= m_move
.drop() ? m_move
.drop() : m_ref
.m_board
[m_move
.from
];
740 bool ambiguous
= isAmbiguous();
744 retv
+= ShogiPiece::typeSymbol(p
.type());
746 retv
+= QString::number(m_ref
.m_board
.getSize().x
-m_move
.from
.x
);
747 retv
+= QString(m_move
.from
.y
+'a');
751 else if (m_ref
.m_board
[m_move
.to
])
755 retv
+= QString::number(m_ref
.m_board
.getSize().x
-m_move
.to
.x
);
756 retv
+= QString(m_move
.to
.y
+'a');
757 if (!p
.promoted() && !m_move
.drop() &&
758 ShogiPosition::promotionZone(m_ref
.turn(), m_move
.to
)) {
759 if (m_move
.m_promote
)
767 DecoratedMove
toDecoratedMove() const {
768 ShogiPiece p
= m_move
.drop() ? m_move
.drop() : m_ref
.m_board
[m_move
.from
];
769 bool ambiguous
= isAmbiguous();
771 if(p
.type() == ShogiPiece::KING
)
772 retv
.push_back(MovePart(p
.color() == ShogiPiece::BLACK
?"king1":"king2", MovePart::Figurine
));
774 retv
.push_back(MovePart((p
.promoted() ? "p_" : "") + ShogiPiece::typeName(p
.type()), MovePart::Figurine
));
776 retv
.push_back(MovePart(QString::number(m_ref
.m_board
.getSize().x
-m_move
.from
.x
)));
777 retv
.push_back(MovePart("num_"+QString::number(m_move
.from
.y
+1), MovePart::Figurine
));
782 else if (m_ref
.m_board
[m_move
.to
])
786 mmm
+= QString::number(m_ref
.m_board
.getSize().x
-m_move
.to
.x
);
788 retv
.push_back(MovePart("num_"+QString::number(m_move
.to
.y
+1), MovePart::Figurine
));
789 if (!p
.promoted() && !m_move
.drop() &&
790 ShogiPosition::promotionZone(m_ref
.turn(), m_move
.to
)) {
791 if (m_move
.m_promote
)
792 retv
.push_back(MovePart("+"));
794 retv
.push_back(MovePart("="));
802 struct MoveFactory
<ShogiVariantInfo
> {
803 static ShogiMove
createNormalMove(const NormalUserMove
& move
) {
804 return ShogiMove(move
.from
, move
.to
, move
.promotionType
>= 0);
806 static ShogiMove
createDropMove(const DropUserMove
& move
) {
807 return ShogiMove(move
.m_pool
, move
.m_piece_index
, move
.m_to
);
810 static NormalUserMove
toNormal(const ShogiMove
& move
) {
811 return NormalUserMove(move
.from
, move
.to
);