Permalink
Browse files

Improved the record definition, enhanced it with type definition and …

…refreshed the documentation
  • Loading branch information...
1 parent 3d67bdb commit 64cea53a6f47acf3f352d3be729c2f015d2095e1 @fcardinaux committed Jun 26, 2011
Showing with 102 additions and 90 deletions.
  1. +1 −1 BUILDING.txt
  2. +1 −1 Makefile
  3. +4 −3 README.txt
  4. +6 −0 beams/Makefile
  5. BIN beams/chessfold.beam
  6. BIN beams/chessfold_test.beam
  7. +30 −57 erl/chessfold.erl
  8. +53 −16 erl/chessfold.hrl
  9. +6 −0 test/Makefile
  10. +1 −12 test/chessfold_test.erl
View
@@ -101,4 +101,4 @@ How to set up the test environment (Ubuntu 11.04)
* R14B03 only: MyValue#my_type.my_property#my_subtype.my_subproperty
* Both versions: (MyValue#my_type.my_property)#my_subtype.my_subproperty
- 3. TODO INSTALL AND TEST THE CHESS MOVE GENERATOR
+
View
@@ -1,4 +1,4 @@
-# Make file for Erlang code
+# Make file for the Erlang Chess Move Generator
# Author: Francois Cardinaux
# Date: 2011.06.24
#
View
@@ -8,10 +8,11 @@ Overview of the current folder:
* It contains all files that are necessary to this project
* There is no symlink of any sort to external resources
-The subfolders (updated on 2011.06.23):
- * _work: any kind of unversionned work file
+The subfolders (updated on 2011.06.26):
+ * beams: the beam files
* doc: documentation
- * erl: Erlang part of the project, versionned
+ * erl: Erlang part of the project
+ * test: Erlang unit tests
* test_data: any kind of test data
Conventions
View
@@ -1,3 +1,9 @@
+# Make file for the Erlang Chess Move Generator
+# Author: Francois Cardinaux
+# Date: 2011.06.24
+#
+# Use the Makefile in the parent directory instead.
+
# leave these lines alone
.SUFFIXES: .erl .beam .yrl
View
Binary file not shown.
View
Binary file not shown.
View
@@ -8,7 +8,6 @@
-module(chessfold).
-% API
-export([
player_color/1,
opponent_color/1,
@@ -44,40 +43,9 @@
-define(WIN_THRESHOLD, 10).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% MACROS AND CONSTANTS
+% CONSTANTS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Source: Programming Erlang, p 424
--define(NYI(X), (begin
- io:format("*** NYI ~p ~p ~p~n", [?MODULE, ?LINE, X])
- end)).
-
-% Noticeable values in 0x88 representation:
--define(ROW_SPAN, 16).
--define(MOVE_UP, 16).
--define(MOVE_UP_LEFT, 15).
--define(MOVE_UP_RIGHT, 17).
--define(MOVE_UP_2, 32).
--define(MOVE_DOWN, -16).
--define(MOVE_DOWN_LEFT, -17).
--define(MOVE_DOWN_RIGHT, -15).
--define(MOVE_DOWN_2, -32).
--define(BOTTOM_LEFT_CORNER, 0).
--define(BOTTOM_RIGHT_CORNER, 7).
--define(TOP_LEFT_CORNER, 112).
--define(TOP_RIGHT_CORNER, 119).
-
--define(CASTLING_ALL, 15).
--define(CASTLING_WHITE_KING, 8).
--define(CASTLING_WHITE_QUEEN, 4).
--define(CASTLING_BLACK_KING, 2).
--define(CASTLING_BLACK_QUEEN, 1).
-
-% Positions of the elements inside the ntc_chess_piece record
--define(PIECE_RECORD_COLOR, 2).
--define(PIECE_RECORD_TYPE, 3).
--define(PIECE_RECORD_SQUARE, 4).
-
% Attack- and delta-array and constants (source: Jonatan Pettersson (mediocrechess@gmail.com))
-define(ATTACK_NONE, 0). % Deltas that no piece can move
-define(ATTACK_KQR, 1). % One square up down left and right
@@ -122,17 +90,17 @@
16, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% API functions
+%% Public functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% -----------------------------------------------------------------------------
-%% @doc Get the identifier of the current player, i.e. the player that will play
+%% @doc Get the color of the current player, i.e. the player that will play
%% the move FROM the current position
-%% @spec player_color(tuple()) -> atom()
+%% @spec player_color(tuple()) -> chess_piece_color()
player_color(#ntc_chess_position{turn = Turn}) ->
Turn;
-%% @spec player_color(list()) -> atom()
+%% @spec player_color(string()) -> chess_piece_color()
player_color(PositionString) ->
Position = string_to_position(PositionString),
player_color(Position).
@@ -142,7 +110,7 @@ player_color(PositionString) ->
%% In case there are more two colors in the game, the returned color must be the one
%% against which the current player can win. In other words, it is the previous player's
%% color, except that a color must be returned at initial position as well.
-%% @spec opponent_color(term()) -> atom()
+%% @spec opponent_color(term()) -> chess_piece_color()
opponent_color(PositionTupleOrString) ->
case player_color(PositionTupleOrString) of
white -> black;
@@ -151,29 +119,31 @@ opponent_color(PositionTupleOrString) ->
%% -----------------------------------------------------------------------------
%% @doc Get the list of pieces of the position
-%% @spec pieces(term()) -> atom()
+%% @spec pieces(#ntc_chess_position{}) -> list(#ntc_chess_piece{})
pieces(#ntc_chess_position{pieces = Pieces}) ->
Pieces;
+
+%% @spec pieces(string()) -> list(#ntc_chess_piece{})
pieces(PositionString) ->
pieces(string_to_position(PositionString)).
%% -----------------------------------------------------------------------------
%% @doc Is the king attacked in the position
-%% @spec is_king_attacked(term()) -> atom()
+%% @spec is_king_attacked(#ntc_chess_position{}) -> boolean()
is_king_attacked(#ntc_chess_position{pieces = Pieces, turn = PlayerColor} = Position) ->
is_square_in_attack(
Pieces,
opponent_color(Position),
king_square(Pieces, PlayerColor));
+%% @spec is_king_attacked(string()) -> boolean()
is_king_attacked(PositionString) ->
Position = string_to_position(PositionString),
is_king_attacked(Position).
-
%% -----------------------------------------------------------------------------
%% @doc Transform a string into a position Tuple
-%% @spec string_to_position(string()) -> ntc_chess_position()
+%% @spec string_to_position(string()) -> #ntc_chess_position{}
string_to_position(String) ->
try
@@ -298,7 +268,7 @@ string_to_position(String) ->
%% -----------------------------------------------------------------------------
%% @doc Transform a position Tuple into string.
%% Returns the Forsyth-Edwards representation of the position.
-%% @spec position_to_string(ntc_chess_position()) -> string()
+%% @spec position_to_string(#ntc_chess_position{}) -> string()
position_to_string(#ntc_chess_position{
halfMoveClock = HalfMoveClock,
moveNumber = MoveNumber} = Position) ->
@@ -308,7 +278,7 @@ position_to_string(#ntc_chess_position{
%% -----------------------------------------------------------------------------
%% @doc Transform a position Tuple into string.
%% The returned string doesn't have any counter information (move count and half-move clock).
-%% @spec position_to_string_without_counters(ntc_chess_position()) -> string()
+%% @spec position_to_string_without_counters(#ntc_chess_position{}) -> string()
position_to_string_without_counters(
#ntc_chess_position{
pieces = Pieces,
@@ -391,10 +361,12 @@ position_to_string_without_counters(
%% -----------------------------------------------------------------------------
%% @doc Get all possible moves from a specific position
-%% @spec all_possible_moves(tuple()) -> list()
+%% @spec all_possible_moves(#ntc_chess_position{}) -> list(#ntc_chess_move{})
all_possible_moves(Position) when is_record(Position, ntc_chess_position) ->
PseudoLegalMoves = all_pseudo_legal_moves(Position),
eliminate_illegal_moves(PseudoLegalMoves);
+
+%% @spec all_possible_moves(string()) -> list(#ntc_chess_move{})
all_possible_moves(PositionString) ->
all_possible_moves(string_to_position(PositionString)).
@@ -409,10 +381,12 @@ all_possible_moves(PositionString) ->
%% -----------------------------------------------------------------------------
%% @doc Get all possible moves from a specific position and a specific start square
-%% @spec all_possible_moves(tuple()) -> list()
+%% @spec all_possible_moves_from(#ntc_chess_position{}, #ntc_chess_piece{}) -> list(#ntc_chess_move{})
all_possible_moves_from(Position, StartPiece) when is_record(StartPiece, ntc_chess_piece) ->
PseudoLegalMoves = accumulate_pseudo_legal_moves_of_piece(Position, StartPiece, []),
eliminate_illegal_moves(PseudoLegalMoves);
+
+%% @spec all_possible_moves_from(#ntc_chess_position{}, integer()) -> list(#ntc_chess_move{})
all_possible_moves_from(Position, StartSquare) ->
StartPiece = get_piece_on_square(Position#ntc_chess_position.pieces, StartSquare),
all_possible_moves_from(Position, StartPiece).
@@ -460,42 +434,42 @@ all_possible_moves_from(Position, StartSquare) ->
%% -----------------------------------------------------------------------------
%% @doc Get the position after a move
-%% @spec position_after_move(tuple()) -> list()
+%% @spec position_after_move(#ntc_chess_move{}) -> #ntc_chess_position{}
position_after_move(#ntc_chess_move{newPosition = NewPosition}) ->
NewPosition.
%% -----------------------------------------------------------------------------
%% @doc Get the position after a move
-%% @spec move_origin(tuple()) -> list()
+%% @spec move_origin(#ntc_chess_move{}) -> #ntc_chess_piece{}
move_origin(#ntc_chess_move{from = Origin}) ->
Origin.
%% -----------------------------------------------------------------------------
%% @doc Get the position after a move
-%% @spec move_target(tuple()) -> list()
+%% @spec move_target(#ntc_chess_move{}) -> #ntc_chess_piece{}
move_target(#ntc_chess_move{to = Target}) ->
Target.
%% -----------------------------------------------------------------------------
%% @doc Get the color of the piece
-%% @spec piece_color(tuple()) -> atom()
+%% @spec piece_color(#ntc_chess_piece{}) -> chess_piece_color()
piece_color(#ntc_chess_piece{color = Color}) ->
Color.
%% -----------------------------------------------------------------------------
%% @doc Get the type of the piece
-%% @spec piece_type(tuple()) -> atom()
+%% @spec piece_type(#ntc_chess_piece{}) -> chess_piece_type()
piece_type(#ntc_chess_piece{type = Type}) ->
Type.
%% -----------------------------------------------------------------------------
%% @doc Get the square of the piece
-%% @spec piece_square(tuple()) -> atom()
+%% @spec piece_square(#ntc_chess_piece{}) -> chess_piece_square()
piece_square(#ntc_chess_piece{square = Square}) ->
Square.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Functions that are public in test mode and private in normal mode
+%% Functions that are public in test mode but private in normal mode
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% -----------------------------------------------------------------------------
@@ -524,7 +498,7 @@ allowed_castling_value_to_string(AllowedCastling) ->
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Private functions related to squares
+%% Private functions that are related to squares
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% -----------------------------------------------------------------------------
@@ -629,8 +603,7 @@ king_square(Pieces, KingColor) ->
case lists:filter(IsPlayerKing, Pieces) of
[PlayerKing] -> PlayerKing#ntc_chess_piece.square;
- _ -> ?NYI(Pieces),
- false
+ _ -> false
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -917,7 +890,7 @@ insert_pseudo_legal_move(Position, From, To, Taken, Castling, NewEnPassant, fals
%% -----------------------------------------------------------------------------
%% @doc Execute the specified move and return the new ntc_chess_position tuple
-%% @spec get_new_position(tuple(), tuple(), tuple(), tuple() or false, atom() or boolean()) -> tuple()
+%% @spec get_new_position(#ntc_chess_position{}, #ntc_chess_piece{}, #ntc_chess_piece{}, false | #ntc_chess_piece{}, castling(), 'false' | chess_piece_square()) -> #ntc_chess_position{}
get_new_position( #ntc_chess_position{
pieces = Pieces,
turn = Turn,
View
@@ -4,23 +4,60 @@
%% Author François Cardinaux, CH 1207 Genève
%% Copyright 2011 François Cardinaux
--record(ntc_chess_position, {
- pieces, % a list of ntc_chess_piece records
- turn,
- allowedCastling = 0,
- enPassantSquare = false,
- halfMoveClock = 0,
- moveNumber = 0}).
-
+% Noticeable values in 0x88 representation:
+-define(ROW_SPAN, 16).
+-define(MOVE_UP, 16).
+-define(MOVE_UP_LEFT, 15).
+-define(MOVE_UP_RIGHT, 17).
+-define(MOVE_UP_2, 32).
+-define(MOVE_DOWN, -16).
+-define(MOVE_DOWN_LEFT, -17).
+-define(MOVE_DOWN_RIGHT, -15).
+-define(MOVE_DOWN_2, -32).
+-define(BOTTOM_LEFT_CORNER, 0).
+-define(BOTTOM_RIGHT_CORNER, 7).
+-define(TOP_LEFT_CORNER, 112).
+-define(TOP_RIGHT_CORNER, 119).
+
+-define(CASTLING_ALL, 15).
+-define(CASTLING_WHITE_KING, 8).
+-define(CASTLING_WHITE_QUEEN, 4).
+-define(CASTLING_BLACK_KING, 2).
+-define(CASTLING_BLACK_QUEEN, 1).
+
+% Positions of the elements inside the ntc_chess_piece record
+-define(PIECE_RECORD_COLOR, 2).
+-define(PIECE_RECORD_TYPE, 3).
+-define(PIECE_RECORD_SQUARE, 4).
+
+-type chess_piece_color() :: 'black' | 'white'.
+-type chess_piece_type() :: 'pawn' | 'knight' | 'bishop' | 'rook' | 'queen' | 'king'.
+-type chess_piece_square() :: ?BOTTOM_LEFT_CORNER..?TOP_RIGHT_CORNER. % In 0x88 representation
+-type castling() :: 'false' | 'queen' | 'king'.
+
-record(ntc_chess_piece, {
- color,
- type,
- square = false}).
+ color :: chess_piece_color(),
+ type :: chess_piece_type(),
+ square = false :: 'false' | chess_piece_square()}).
+
+-record(ntc_chess_position, {
+ pieces :: [#ntc_chess_piece{}],
+ turn :: 'false' | chess_piece_color(),
+ allowedCastling = 0 :: 0..?CASTLING_ALL,
+ enPassantSquare = false :: 'false' | chess_piece_square(),
+ halfMoveClock = 0 :: integer(),
+ moveNumber = 0 :: integer()}).
-record(ntc_chess_move, {
- from, % ntc_chess_piece (i.e. with square)
- to, % ntc_chess_piece (i.e. with square)
- newPosition, % ntc_chess_position
- castling = false, % false, king or queen
- taken = false}). % ntc_chess_piece (i.e. with square of taken piece, which may be different from 'to')
+ from :: #ntc_chess_piece{},
+ to :: #ntc_chess_piece{}, % May be a different piece, in case of promotion
+ newPosition :: #ntc_chess_position{},
+ castling = false :: castling(),
+ taken = false :: 'false' | #ntc_chess_piece{}}). % Not necessarily the same square as 'to' (en passant)
+
+% Source: Programming Erlang, p 424
+-define(NYI(X), (begin
+ io:format("*** NYI ~p ~p ~p~n", [?MODULE, ?LINE, X])
+ end)).
+
View
@@ -1,3 +1,9 @@
+# Make file for the Erlang Chess Move Generator
+# Author: Francois Cardinaux
+# Date: 2011.06.24
+#
+# Use the Makefile in the parent directory instead.
+
# leave these lines alone
.SUFFIXES: .erl .beam .yrl
View
@@ -1,11 +1,6 @@
%% @doc Tests of the Chess Move Generator
%% @end
%%
-%% To compile:
-%% erlc -DTEST chessfold_test.erl
-%% To test:
-%% erl -run chessfold_test test -run init stop -noshell
-%%
%% @author François Cardinaux, CH 1207 Genève
%% @copyright 2011 François Cardinaux
@@ -23,12 +18,7 @@
-include_lib("eunit/include/eunit.hrl").
-% Source: Programming Erlang, p 424
--define(NYI(X), (begin
- io:format("*** NYI ~p ~p ~p~n", [?MODULE, ?LINE, X])
- end)).
-
--define(PERFT_DEPTH, 4). % Depth 4 OK
+-define(PERFT_DEPTH, 2). % Depth 4 OK
-define(PERFT_SUITE, "../test_data/perftsuite.txt").
-define(DO_NON_EVOLUTIVE_TESTS, false).
-define(DO_ISOLATION_TESTS, false).
@@ -258,7 +248,6 @@ string_to_position_test_acc([]) -> true;
string_to_position_test_acc(Positions) ->
[Test | Remaining] = Positions,
Position = string_to_position(Test),
- ?NYI(position_to_string(Position)),
?assert(position_to_string(Position) =:= Test),
string_to_position_test_acc(Remaining).

0 comments on commit 64cea53

Please sign in to comment.