駒はsignedがいいのかunsignedがいいのか

Bonanzaでは駒を表現する型はs8(singed char)になっています。

さて、問題です。私のように設計した場合、 -(int)UToCap(move) に相当する部分はどう書けるでしょうか?なるべく速いコードを求みます!

http://d.hatena.ne.jp/LS3600/20111001

私が書いたコードは、次のコードでした。

( ( Cap(move) + (piece_enemy - 1) ) & piece_enemy) | Cap(move)

Cap(move) > 0のときに(piece_enemy - 1)を足せば、piece_enemyのbitが1になるので、Cap(move) > 0のときだけpiece_enemyのbitをもらってこれるなぁというコードです。

これが最速かどうかはよくわかりませんが、そこそこ優秀なコードではないでしょうか。


駒をu8(unsigned char)で持つほうがいいのかs8で持つほうがいいのかは難しいところで、s8で持っていると、駒種を得るときにabsで絶対値を求める必要があったりして、どちらが良いとは一概には言えません。私はBonanzaのソースの全体を通して、トータルではu8のほうがわずかに得かと思ってu8にして設計しています。

u8にする上で問題だったのが上の部分のコードでして、ここが上記のようなコードを書くことで解決できたので、それほど悪くないとは思います。

u8で設計したときに必要になるその他のテクニックをいくつか書いておきます。
u8とs8との比較のため、両者のコードを掲載します。

[先手の駒を後手の駒に]
u8) piece |= piece_enemy;
s8) piece = -piece;


[後手の駒を先手の駒に]
u8) piece ~= piece_enemy;
s8) piece = -piece;


[先手・後手の駒の駒種を求める]
u8) piece ~= piece_enemy;
s8) piece = abs(piece)


[駒種から、手番を考慮した駒に変換したいとき]
// turnは先手なら0,後手なら-1になっている。
u8) piece |= turn & piece_enemy;
s8) piece = turn==black ? piece : -piece;


[先手の駒なら後手の駒、後手の駒なら先手の駒にしたいとき]
u8) piece ^= piece_enemy;
s8) piece = -piece;


[先手・後手の駒を強制的に先手の駒にしたいとき]
u8) piece &= ~piece_enemy;
s8) piece = abs(piece);


[先手・後手の駒を強制的に後手の駒にしたいとき]
u8) piece |= piece_enemy;
s8) piece = - abs(piece);


[0なら0、先手の駒なら後手の駒にしたいとき] ←今回の問題
u8) piece |= (piece + (piece_enemy - 1)) & piece_enemy;
s8) piece = -piece;


[0なら0、先手の駒なら後手の駒、後手の駒なら先手の駒にしたいとき] ← 今回の問題の応用。先後のコードを場合分けして書いていれば、これが必要になることはないのだが…。
u8) piece ^= (piece + (piece_enemy - 1)) & piece_enemy); ← 右辺は、piece > 0のときだけpiece_enemyが得られ、piece > 0のときだけpiece ^= piece_enemyされる。
s8) piece = - piece;


先後のコードを場合分けして書くのであれば、一番最後のは使いませんし、s8のほうはabsが結構出てくるのでちょっと不利かなぁというのが私の判断でした。みなさんはどう思われますでしょうか。