Files
secondo/Algebras/Chess/chess.cpp

2352 lines
58 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
----
This file is part of SECONDO.
Copyright (C) 2004, University in Hagen, Department of Computer Science,
Database Systems for New Applications.
SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
//characters [1] verbatim: [\verb@] [@]
//paragraph [1] title: [{\Large \bf ] [}]
[1] chess Algebra
20070104 A. Behrendt Operator movingpoints
20070121 (stream(tuple (Piece: string IsWhite: bool Route:mpoint))) wird erzeugt.
Rochade funktioniert, Bauernwandlung noch nicht eingebaut.
Testspiel chess1 getestet, korrekt bis auf Bauernwandlung im letzten Zug.
1 Defines and includes
*/
#include "Algebra.h"
#include "NestedList.h"
#include "QueryProcessor.h"
#include "StandardTypes.h"
#include <iostream>
#include <string>
#include <sstream>
#include "chessTypes.h"
#include "pgnparser.h"
#include "TypeMapUtils.h"
#include "Symbols.h"
#include "Algebras/Temporal/TemporalAlgebra.h"
//using namespace symbols;
using namespace mappings;
using namespace temporalalgebra;
using namespace std;
const std::string MATERIAL="material";
const std::string STRING="string";
const std::string POSITION="position";
const std::string INT = "int";
const std::string BOOL = "bool";
extern NestedList* nl;
extern QueryProcessor *qp;
namespace ChessAlgebra
{
#define readIntValue(var, list)\
if ( nl->IsAtom( list ) && nl->AtomType( list ) == IntType )\
var = nl->IntValue( list );\
else\
{\
string liststr;\
nl->WriteToString(liststr, list );\
ErrorReporter::ReportError( "Error: Expected an "\
"integer value at " + liststr + "." );\
correct = false;\
return SetWord( Address( 0 ) );\
}
#define readStringValue(var, list)\
if ( nl->IsAtom( list ) && nl->AtomType( list ) == StringType )\
var = nl->StringValue( list );\
else\
{\
string liststr;\
nl->WriteToString(liststr, list );\
ErrorReporter::ReportError( "Error: Expected a"\
" string value at " + liststr + "." );\
correct = false;\
return SetWord( Address( 0 ) );\
}
#define readBoolValue(var, list)\
if ( nl->IsAtom( list ) && nl->AtomType( list ) == BoolType )\
var = nl->BoolValue( list );\
else\
{\
string liststr;\
nl->WriteToString(liststr, list );\
ErrorReporter::ReportError( "Error: Expected a"\
" bool value at " + liststr + "." );\
correct = false;\
return SetWord( Address( 0 ) );\
}
#define returnError(errstr)\
ErrorReporter::ReportError( errstr );\
correct = false;\
return SetWord( Address( 0 ) )
/*
2 Type Constructors
*/
/*
2.1 Type Constructor material
*/
ListExpr
MaterialProp()
{
return (
nl->TwoElemList(
nl->FiveElemList(
nl->StringAtom( "Signature" ),
nl->StringAtom( "Example Type List" ),
nl->StringAtom( "List Rep" ),
nl->StringAtom( "Example List" ),
nl->StringAtom( "Remarks" ) ),
nl->FiveElemList(
nl->StringAtom( "-> DATA" ),
nl->StringAtom( "material" ),
nl->StringAtom( "(int int ... int) (12 int values)" ),
nl->StringAtom( "(8 2 2 2 1 1 8 2 2 2 1 1)" ),
nl->StringAtom( "..." )
)
)
);
}
ListExpr
OutMaterial( ListExpr typeInfo, Word value )
{
Material * mat = ( Material* ) ( value.addr );
ListExpr outlist;
if ( mat->IsDefined() )
{
outlist = nl->Cons(
nl->TwoElemList(
nl->StringAtom( DecodeAgent( BLACK_KING ) ),
nl->IntAtom( mat->Count( DecodeAgent( BLACK_KING ) ) )
),
nl->TheEmptyList()
);
for ( int i = BLACK_QUEEN; i >= WHITE_PAWN; i-- )
{
outlist = nl->Cons(
nl->TwoElemList(
nl->StringAtom( DecodeAgent( i ) ),
nl->IntAtom( mat->Count( DecodeAgent( i ) ) )
),
outlist );
}
}
else
return nl->SymbolAtom( "undef" );
return ( outlist );
}
Word
InMaterial(
const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr & errorInfo, bool & correct )
{
if ( nl->ListLength( instance ) == 12 )
{
char agents[ 12 ];
ListExpr current = nl->First( instance );
ListExpr rest = nl->Rest( instance );
if ( nl->IsAtom( current ) && nl->AtomType( current ) == IntType )
agents[ 0 ] = nl->IntValue( current );
else if ( ( nl->ListLength( current ) == 2 )
&& ( nl->IsAtom( nl->Second( current ) ) )
&& ( nl->AtomType( nl->Second( current ) ) ) == IntType )
agents[ 0 ] = nl->IntValue( nl->Second( current ) );
else
{
returnError(
"Error: Wrong list format. Expected list of type\n"
"(int ... int) or ((string int) ... (string int))." );
}
for ( int i = 1; i < 12; i++ )
{
current = nl->First( rest );
rest = nl->Rest( rest );
if ( nl->IsAtom( current ) && nl->AtomType( current ) == IntType )
agents[ i ] = nl->IntValue( current );
else if ( ( nl->ListLength( current ) == 2 )
&& ( nl->IsAtom( nl->Second( current ) ) )
&& ( nl->AtomType( nl->Second( current ) ) ) == IntType )
agents[ i ] = nl->IntValue( nl->Second( current ) );
else
{
returnError(
"Error: Wrong list format. Expected list of type\n"
"(int ... int) or ((string int) ... (string int)).\n"
"(string value will be ignored)" );
}
}
cout << "OK" << endl;
correct = true;
Material * newmat = new Material ( agents );
return SetWord( newmat );
}
else
{
returnError(
"Error: Wrong list format. Expect list with 12 elements of type\n"
"int or (string int)." );
}
}
void *
CastMaterial( void * addr )
{
return ( new ( addr ) Material );
}
Word
CreateMaterial( const ListExpr typeInfo )
{
return ( SetWord( new Material( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) ) );
}
void
DeleteMaterial( const ListExpr typeInfo, Word & w )
{
( ( Material * ) w.addr ) ->DeleteIfAllowed();
w.addr = 0;
}
void
CloseMaterial( const ListExpr typeInfo, Word & w )
{
( ( Material * ) w.addr ) ->DeleteIfAllowed();
w.addr = 0;
}
Word
CloneMaterial( const ListExpr typeInfo, const Word & w )
{
return SetWord( ( ( Material * ) w.addr ) ->Clone() );
}
int
SizeOfMaterial()
{
return sizeof( Material );
}
bool
MaterialType( ListExpr type, ListExpr & errorInfo )
{
return ( nl->IsEqual( type, "material" ) );
}
/*
2.2 Type Constructor move
*/
ListExpr
MoveProp()
{
return (
nl->TwoElemList(
nl->FiveElemList(
nl->StringAtom( "Signature" ),
nl->StringAtom( "Example Type List" ),
nl->StringAtom( "List Rep" ),
nl->StringAtom( "Example List" ),
nl->StringAtom( "Remarks" ) ),
nl->FiveElemList(
nl->StringAtom( "-> DATA" ),
nl->StringAtom( "(move)" ),
nl->StringAtom( "(int string string string"
" int string int bool)" ),
nl->StringAtom( "(3 \"Pawn\" \"none\" \"b\" 2 \"b\" 4 FALSE)" ),
nl->StringAtom( "move, agent, capt. startpos, endpos, check" )
)
)
);
}
ListExpr
OutMove( ListExpr typeInfo, Word value )
{
Move * move = ( Move* ) ( value.addr );
ListExpr outlist;
if ( move->IsDefined() )
{
outlist = nl->Cons( nl->BoolAtom( move->IsCheck() ), nl->TheEmptyList() );
outlist = nl->Cons( nl->IntAtom( move->GetEndRow() ), outlist );
outlist = nl->Cons( nl->StringAtom( move->GetEndFile() ), outlist );
outlist = nl->Cons( nl->IntAtom( move->GetStartRow() ), outlist );
outlist = nl->Cons( nl->StringAtom( move->GetStartFile() ), outlist );
outlist = nl->Cons( nl->StringAtom( move->GetCaptured() ), outlist );
outlist = nl->Cons( nl->StringAtom( move->GetAgent() ), outlist );
outlist = nl->Cons( nl->IntAtom( move->GetMoveNumber() ), outlist );
}
else
return nl->SymbolAtom( "undef" );
return ( outlist );
}
Word
InMove(
const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr & errorInfo, bool & correct )
{
cout << "InMove..." << endl;
if ( nl->ListLength( instance ) == 8 )
{
int moveNumber, startRow, endRow;
string agent, captured, startFile, endFile;
bool check;
ListExpr current = nl->First( instance );
ListExpr rest = nl->Rest( instance );
readIntValue( moveNumber, current )
current = nl->First( rest );
rest = nl->Rest( rest );
readStringValue( agent, current )
current = nl->First( rest );
rest = nl->Rest( rest );
readStringValue( captured, current )
current = nl->First( rest );
rest = nl->Rest( rest );
readStringValue( startFile, current )
current = nl->First( rest );
rest = nl->Rest( rest );
readIntValue( startRow, current )
current = nl->First( rest );
rest = nl->Rest( rest );
readStringValue( endFile, current )
current = nl->First( rest );
rest = nl->Rest( rest );
readIntValue( endRow, current )
current = nl->First( rest );
rest = nl->Rest( rest );
readBoolValue( check, current )
correct = true;
Move * newmove = new Move ( moveNumber, agent, captured,
startFile, startRow, endFile, endRow,
check );
return SetWord( newmove );
}
else
{
returnError(
"Error: Wrong list format. Expected list of type\n"
"(int string string string int string int bool)." );
}
}
void *
CastMove( void * addr )
{
return ( new ( addr ) Move );
}
Word
CreateMove( const ListExpr typeInfo )
{
return ( SetWord( new Move( 0, "none", "none", "a", 1, "a", 1, false ) ) );
}
void
DeleteMove( const ListExpr typeInfo, Word & w )
{
( ( Move * ) w.addr ) ->DeleteIfAllowed();
w.addr = 0;
}
void
CloseMove( const ListExpr typeInfo, Word & w )
{
( ( Move * ) w.addr ) ->DeleteIfAllowed();
w.addr = 0;
}
Word
CloneMove( const ListExpr typeInfo, const Word & w )
{
return SetWord( ( ( Move * ) w.addr ) ->Clone() );
}
int
SizeOfMove()
{
return sizeof( Move );
}
bool
MoveType( ListExpr type, ListExpr & errorInfo )
{
return ( nl->IsEqual( type, "chessmove" ) );
}
/*
2.3 Type Constructor position
*/
ListExpr
PositionProp()
{
return (
nl->TwoElemList(
nl->FiveElemList(
nl->StringAtom( "Signature" ),
nl->StringAtom( "Example Type List" ),
nl->StringAtom( "List Rep" ),
nl->StringAtom( "Example List" ),
nl->StringAtom( "Remarks" ) ),
nl->FiveElemList(
nl->StringAtom( "-> DATA" ),
nl->StringAtom( "position" ),
nl->StringAtom( "(int ((string string int)...))" ),
nl->StringAtom( "(43 ((\"King\" \"b\" 5)(\"king\" \"h\" 7)))" ),
nl->StringAtom( "..." )
)
)
);
}
ListExpr
OutPosition( ListExpr typeInfo, Word value )
{
Position * pos = ( Position* ) ( value.addr );
ListExpr outlist;
if ( pos->IsDefined() )
{
int moveNumber = pos->GetMoveNumber();
ListExpr agentList, agentRow;
bool firstRow = true;
agentList = nl->TheEmptyList();
for ( int row = 1; row <= 8; row++ )
{
bool firstAgent = true;
agentRow = nl->TheEmptyList();
for ( char file = 'h'; file >= 'a'; file-- )
{
if ( firstAgent )
{
agentRow = nl->Cons(
nl->StringAtom( pos->GetAgentShort( file, row ) ) ,
nl->TheEmptyList() );
firstAgent = false;
}
else
{
agentRow = nl->Cons(
nl->StringAtom( pos->GetAgentShort( file, row ) ) ,
agentRow );
}
}
if ( firstRow )
{
agentList = nl->Cons( agentRow , nl->TheEmptyList() );
firstRow = false;
}
else
{
agentList = nl->Cons( agentRow , agentList );
}
}
outlist = nl->TwoElemList( nl->IntAtom( moveNumber ), agentList );
}
else
return nl->SymbolAtom( "undef" );
return ( outlist );
}
Word
InPosition(
const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr & errorInfo, bool & correct )
{
if ( nl->ListLength( instance ) == 2 )
{
ListExpr first, second, current;
string agent;
int moveNumber, row;
first = nl->First( instance );
second = nl->Second( instance );
readIntValue( moveNumber, first )
Position * newpos = new Position ( moveNumber );
ListExpr rowList;
if ( nl->ListLength( second ) == 8 )
{
int row = 8;
while ( !nl->IsEmpty( second ) )
{
char file = 'a';
rowList = nl->First( second );
second = nl->Rest( second );
if ( nl->ListLength( rowList ) == 8 )
{
while ( !nl->IsEmpty( rowList ) )
{
current = nl->First( rowList );
rowList = nl->Rest( rowList );
readStringValue( agent, current )
int err = 0;
if ( agent != DecodeAgentShort( NONE ) )
err = newpos->AddAgent( agent, file, row );
if ( err == -2 )
{
ostringstream errmsg;
errmsg << "Error: Agent type '" << agent << "' not found.";
returnError( errmsg.str() );
}
file++;
}
row--;
}
else
{
returnError(
"Error: Wrong list format. Expected list of type\n"
"(int ((string ... string)...(string ... string))),\n"
"which defines the agents on all 64 squares." );
}
}
}
else
{
string file;
while ( !nl->IsEmpty( second ) )
{
current = nl->First( second );
second = nl->Rest( second );
if ( nl->ListLength( current ) == 3 )
{
readStringValue( agent, nl->First( current ) )
readStringValue( file, nl->Second( current ) )
readIntValue( row, nl->Third( current ) )
int err = newpos->AddAgent( agent, file[ 0 ], row );
if ( err )
{
ostringstream errmsg;
if ( err == -1 )
{
errmsg << "Error: Can't store agent '"
<< agent
<< "' at square " << file << row
<< ", square already contains an agent of type '"
<< newpos->GetAgent( file[ 0 ], row )
<< "'.";
}
else if ( err == -2 )
{
errmsg << "Error: Agent type '" << agent << "' not found.";
}
returnError( errmsg.str() );
}
}
else
{
returnError(
"Error: Wrong list format. Expected list of type\n"
"(int ((string string int)...(string string int)))." );
}
}
}
correct = true;
return SetWord( newpos );
}
else
{
returnError(
"Error: Wrong list format. Expected list of type\n"
"(int ((string string int)...(string string int))) or\n"
"(int ((string ... string)...(string ... string)))." );
}
}
void *
CastPosition( void * addr )
{
return ( new ( addr ) Position );
}
Word
CreatePosition( const ListExpr typeInfo )
{
return ( SetWord( new Position( 0 ) ) );
}
void
DeletePosition( const ListExpr typeInfo, Word & w )
{
( ( Position * ) w.addr ) ->DeleteIfAllowed();
w.addr = 0;
}
void
ClosePosition( const ListExpr typeInfo, Word & w )
{
( ( Position * ) w.addr ) ->DeleteIfAllowed();
w.addr = 0;
}
Word
ClonePosition( const ListExpr typeInfo, const Word & w )
{
return SetWord( ( ( Position * ) w.addr ) ->Clone() );
}
int
SizeOfPosition()
{
return sizeof( Position );
}
bool
PositionType( ListExpr type, ListExpr & errorInfo )
{
return ( nl->IsEqual( type, "position" ) );
}
/*
2.4 Type Constructor Chessgame
*/
ListExpr
ChessgameProp()
{
return (
nl->TwoElemList(
nl->FiveElemList(
nl->StringAtom( "Signature" ),
nl->StringAtom( "Example Type List" ),
nl->StringAtom( "List Rep" ),
nl->StringAtom( "Example List" ),
nl->StringAtom( "Remarks" ) ),
nl->FiveElemList(
nl->StringAtom( "-> DATA" ),
nl->StringAtom( "( chessgame ) " ),
nl->StringAtom( "() " ),
nl->StringAtom( "() " ),
nl->StringAtom( "" )
)
)
);
}
ListExpr
OutChessgame( ListExpr typeInfo, Word value )
{
Chessgame * game = ( Chessgame* ) ( value.addr );
ListExpr outlist;
if ( game->IsDefined() )
{
ListExpr metainfoList, movesList;
// build metainfoList;
if ( !game->GetMetainfoCount() )
metainfoList = nl->TheEmptyList();
else
{
bool firstListEntry = true;
for ( int i = ( ( game->GetMetainfoCount() ) - 1 ); i >= 0; i-- )
{
MetainfoEntry metainfo = game->GetMetainfoEntry( i );
/* do not print EventDate and ECO if respective values are empty. Date,
Event, White, Black, Site, Round and Result (STR-Tags) will always be
printed, even if they are originaly not contained in the pgn-file.
All other tags will only be printed, if they are contained in the
respective pgn file
*/
string key ( metainfo.key );
if ( ( metainfo.value[ 0 ] != '\0' ) ||
( ( key != "EventDate" ) &&
( key != "ECO" ) )
)
{
if ( firstListEntry )
{
metainfoList = nl->Cons( nl->TwoElemList(
nl->StringAtom( metainfo.key ),
nl->StringAtom( metainfo.value )
), nl->TheEmptyList() );
firstListEntry = false;
}
else
{
metainfoList = nl->Cons( nl->TwoElemList(
nl->StringAtom( metainfo.key ),
nl->StringAtom( metainfo.value )
), metainfoList );
}
}
}
}
// build movesList;
if ( game->GetMovesCount() == 0 )
movesList = nl->TheEmptyList();
else
{
bool firstListEntry = true;
for ( int i = ( game->GetMovesCount() ); i > 0; i-- )
{
ListExpr movelist;
Move move;
game->GetMove( move, i );
// build movelist
movelist = nl->Cons( nl->StringAtom( game->GetPGN( i ) ),
nl->TheEmptyList() );
movelist = nl->Cons( nl->BoolAtom( move.IsCheck() ), movelist );
movelist = nl->Cons( nl->IntAtom( move.GetEndRow() ), movelist );
movelist = nl->Cons( nl->StringAtom( move.GetEndFile() ), movelist );
movelist = nl->Cons( nl->IntAtom( move.GetStartRow() ), movelist );
movelist = nl->Cons( nl->StringAtom( move.GetStartFile() ), movelist);
movelist = nl->Cons( nl->StringAtom( move.GetCaptured() ), movelist );
movelist = nl->Cons( nl->StringAtom( move.GetAgent() ), movelist );
if ( firstListEntry )
{
movesList = nl->Cons( movelist, nl->TheEmptyList() );
firstListEntry = false;
}
else
{
movesList = nl->Cons( movelist, movesList );
}
}
}
outlist = nl->TwoElemList( metainfoList, movesList );
}
else
return nl->SymbolAtom( "undef" );
return ( outlist );
}
Word
InChessgame(
const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr & errorInfo, bool & correct )
{
Chessgame * game = new Chessgame( 0, 0 );
if ( nl->ListLength( instance ) == 2 )
{
ListExpr current, rest;
// read metainfos
rest = nl->First( instance );
while ( !nl->IsEmpty( rest ) )
{
current = nl->First( rest );
rest = nl->Rest( rest );
if ( nl->ListLength( current ) == 2 )
{
string key, value;
readStringValue( key, nl->First( current ) )
readStringValue( value, nl->Second( current ) )
// add metainfo entry
game->AddMetainfoEntry( key, value );
}
else
{
returnError(
"Error: Wrong list format. Expected list of type\n"
"((string string)...(string string))." );
}
}
// read moves
rest = nl->Second( instance );
while ( !nl->IsEmpty( rest ) )
{
current = nl->First( rest );
rest = nl->Rest( rest );
if ( nl->ListLength( current ) == 8 )
{
string startFile, endFile, pgn;
int startRow, endRow;
// first value is ignored
ListExpr current2 = nl->First( current );
ListExpr rest2 = nl->Rest( current );
// second value is ignored
current2 = nl->First( rest2 );
rest2 = nl->Rest( rest2 );
// read startfile
current2 = nl->First( rest2 );
rest2 = nl->Rest( rest2 );
readStringValue( startFile, current2 )
// read startrow
current2 = nl->First( rest2 );
rest2 = nl->Rest( rest2 );
readIntValue( startRow, current2 )
// read endfile
current2 = nl->First( rest2 );
rest2 = nl->Rest( rest2 );
readStringValue( endFile, current2 )
// read endrow
current2 = nl->First( rest2 );
rest2 = nl->Rest( rest2 );
readIntValue( endRow, current2 )
// check state value is ignored
current2 = nl->First( rest2 );
rest2 = nl->Rest( rest2 );
// read pgn-notation
current2 = nl->First( rest2 );
rest2 = nl->Rest( rest2 );
readStringValue( pgn, current2 )
// add move
game->AddMove( startFile[ 0 ], startRow, endFile[ 0 ], endRow, pgn );
}
else
{
returnError(
"Error: Wrong list format. Expected list of type\n"
"((string string string int string "
"int bool string string)...(...))." );
}
}
game->SortMetainfos();
correct = true;
return SetWord( game );
}
else if ( ( nl->ListLength( instance ) == 1 )
&& ( nl->IsAtom( nl->First( instance ) )
&& nl->AtomType( nl->First( instance ) ) == TextType ) )
{
string filename;
nl->Text2String( nl->First( instance ), filename );
ifstream * file = new ifstream( filename.c_str() );
if ( file )
{
game = ParseFile( file );
if ( game )
{
correct = true;
return SetWord( game );
}
else
{
returnError( "Error while parsing file " + filename + "." );
}
}
else
{
returnError( "Error: File " + filename + " not found." );
}
}
else
{
returnError(
"Error: Wrong list format. Expected list of type\n"
"(metainfo_list move_list)." );
}
}
void *
CastChessgame( void * addr )
{
return ( new ( addr ) Chessgame );
}
Word
CreateChessgame( const ListExpr typeInfo )
{
return ( SetWord( new Chessgame( 0, 0 ) ) );
}
void
DeleteChessgame( const ListExpr typeInfo, Word & w )
{
( ( Chessgame * ) w.addr ) ->DeleteIfAllowed();
w.addr = 0;
}
void
CloseChessgame( const ListExpr typeInfo, Word & w )
{
( ( Chessgame * ) w.addr ) ->DeleteIfAllowed();
w.addr = 0;
}
Word
CloneChessgame( const ListExpr typeInfo, const Word & w )
{
return SetWord( ( ( Chessgame * ) w.addr ) ->Clone() );
}
int
SizeOfChessgame()
{
return sizeof( Chessgame );
}
bool
ChessgameType( ListExpr type, ListExpr & errorInfo )
{
return ( nl->IsEqual( type, "chessgame" ) );
}
bool
OpenChessgame(
SmiRecord & valueRecord, size_t & offset,
const ListExpr typeInfo, Word & value )
{
Chessgame * game;
game = ( Chessgame* ) Attribute::Open( valueRecord, offset, typeInfo );
value = SetWord( game );
return true;
}
bool
SaveChessgame(
SmiRecord & valueRecord, size_t & offset,
const ListExpr typeInfo, Word & value )
{
Chessgame * p = ( Chessgame * ) value.addr;
Attribute::Save( valueRecord, offset, typeInfo, p );
return true;
}
/*
3 Operators
*/
/*
3.1 Operator readpgn
reads a pgn file and returns a realtion of tuples, each containing only one
attribute of type games
*/
const string readpgnSpec =
"( " "( " "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>text -> stream (game)</text--->"
"<text>readpgn( _ )</text--->"
"<text>Reads a file and returns a stream of games</text--->"
"<text>query readpgn(\"ICCF2006.pgn\")</text--->"
")" ")";
int readpgnValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
ifstream * file;
const char* filename;
FText* fn;
Chessgame* game;
switch ( message )
{
case OPEN:
fn = ( ( FText * ) args[ 0 ].addr );
filename = fn->Get();
file = new ifstream( filename );
local.addr = file;
cout << "Parsing file '" << filename << "' - please wait..." << endl;
return 0;
case REQUEST:
file = ( ifstream* ) local.addr;
if(!(*file)){
return CANCEL;
}
if ( file->is_open() )
{
if ( !file->eof() )
game = ParseFile( file );
else
return CANCEL;
}
else
ErrorReporter::ReportError( "File not open." );
if ( game != NULL )
{
cout << ".";
result.addr = game;
return YIELD;
}
else
{
cout << endl << "Finished parsing file.";
return CANCEL;
}
case CLOSE:
file = ( ifstream* ) local.addr;
file->close();
cout << endl;
return 0;
}
return -1;
}
ListExpr readpgnTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg = nl->First( args );
if ( nl->IsAtom( arg ) && nl->IsEqual( arg, "text" ) )
{
return nl->TwoElemList(
nl->SymbolAtom( "stream" ),
nl->SymbolAtom( "chessgame" ) );
}
}
return nl->SymbolAtom( "typeerror" );
}
/*
3.2 Operators on move type constructor
*/
const string agentSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>move -> string</text--->"
"<text>_ move</text--->"
"<text>Returns agent figure of a move.</text--->"
"<text>query move1 agent</text--->"
")" ")";
const string capturedSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>move -> string</text--->"
"<text>_ move</text--->"
"<text>Returns captured figure of a move.</text--->"
"<text>query move1 captured</text--->"
")" ")";
const string startrowSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>move -> int</text--->"
"<text>_ move</text--->"
"<text>Returns start row of a move.</text--->"
"<text>query move1 startrow</text--->"
")" ")";
const string endrowSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>move -> int</text--->"
"<text>_ move</text--->"
"<text>Returns end row of a move.</text--->"
"<text>query move1 endrow</text--->"
")" ")";
const string startfileSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>move -> string</text--->"
"<text>_ move</text--->"
"<text>Returns start file of a move.</text--->"
"<text>query move1 startfile</text--->"
")" ")";
const string endfileSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>move -> string</text--->"
"<text>_ move</text--->"
"<text>Returns end file of a move.</text--->"
"<text>query move1 endfile</text--->"
")" ")";
const string checkSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>move -> bool</text--->"
"<text>_ move</text--->"
"<text>Returns true, if check was offered.</text--->"
"<text>query move1 check</text--->"
")" ")";
const string capturesSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>move -> bool</text--->"
"<text>_ move</text--->"
"<text>Returns true, if some figure was captured.</text--->"
"<text>query move1 captured</text--->"
")" ")";
int agentValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Move * move = ( ( Move* ) args[ 0 ].addr );
result = qp->ResultStorage( s );
STRING_T resultString;
int len = ( move->GetAgent() ).string::copy( resultString, 48, 0 );
resultString[ len ] = '\0';
( ( CcString* ) result.addr ) ->Set( true, &resultString );
return 0;
}
int capturedValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Move * move = ( ( Move* ) args[ 0 ].addr );
result = qp->ResultStorage( s );
STRING_T resultString;
int len = ( move->GetCaptured() ).string::copy( resultString, 48, 0 );
resultString[ len ] = '\0';
( ( CcString* ) result.addr ) ->Set( true, &resultString );
return 0;
}
int startrowValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Move * move = ( ( Move* ) args[ 0 ].addr );
result = qp->ResultStorage( s );
( ( CcInt* ) result.addr ) ->Set( true, move->GetStartRow() );
return 0;
}
int endrowValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Move * move = ( ( Move* ) args[ 0 ].addr );
result = qp->ResultStorage( s );
( ( CcInt* ) result.addr ) ->Set( true, move->GetEndRow() );
return 0;
}
int startfileValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Move * move = ( ( Move* ) args[ 0 ].addr );
result = qp->ResultStorage( s );
STRING_T resultString;
int len = ( move->GetStartFile() ).string::copy( resultString, 48, 0 );
resultString[ len ] = '\0';
( ( CcString* ) result.addr ) ->Set( true, &resultString );
return 0;
}
int endfileValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Move * move = ( ( Move* ) args[ 0 ].addr );
result = qp->ResultStorage( s );
STRING_T resultString;
int len = ( move->GetEndFile() ).string::copy( resultString, 48, 0 );
resultString[ len ] = '\0';
( ( CcString* ) result.addr ) ->Set( true, &resultString );
return 0;
}
int checkValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Move * move = ( ( Move* ) args[ 0 ].addr );
result = qp->ResultStorage( s );
( ( CcBool* ) result.addr ) ->Set( true, move->IsCheck() );
return 0;
}
int capturesValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Move * move = ( ( Move* ) args[ 0 ].addr );
result = qp->ResultStorage( s );
( ( CcBool* ) result.addr ) ->Set( true, move->GetCaptures() );
return 0;
}
ListExpr moveStrTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg = nl->First( args );
if ( nl->IsEqual( arg, "chessmove" ) )
{
return nl->SymbolAtom( "string" );
}
}
return nl->SymbolAtom( "typeerror" );
}
ListExpr moveIntTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg = nl->First( args );
if ( nl->IsEqual( arg, "chessmove" ) )
{
return nl->SymbolAtom( "int" );
}
}
return nl->SymbolAtom( "typeerror" );
}
ListExpr moveBoolTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg = nl->First( args );
if ( nl->IsEqual( arg, "chessmove" ) )
{
return nl->SymbolAtom( "bool" );
}
}
return nl->SymbolAtom( "typeerror" );
}
/*
3.3 Operator piececount
*/
struct piececountInfo : OperatorInfo {
piececountInfo() : OperatorInfo()
{
name = "piececount";
signature = "material x string -> int, position x string -> int";
syntax = "_ piececount[_]";
meaning = "Returns number of respective figures for the given "
"material or position. The regerded figures can be specified "
"by names or by a sequence of their first letter, or the "
"special set constants \"all\", \"white\" and \"black\"";
}
};
const string maps_pc[2][3] = { {MATERIAL, STRING, INT},
{POSITION, STRING, INT} };
static ListExpr
piececount_tm(ListExpr args)
{
return SimpleMaps<2,3>(maps_pc, args);
}
int
piececount_sf( ListExpr args )
{
return SimpleSelect<2,3>(maps_pc, args);
}
int piececount_vm( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Material* material = static_cast<Material*>( args[ 0 ].addr );
CcString* value = static_cast<CcString*>( args[ 1 ].addr );
result = qp->ResultStorage( s );
static_cast<CcInt*>( result.addr )->Set( true,
material->Count( *value->GetStringval() ) );
return 0;
}
int piececount_vm2( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Position* pos = static_cast<Position*>( args[ 0 ].addr );
CcString* value = static_cast<CcString*>( args[ 1 ].addr );
result = qp->ResultStorage( s );
Material mat;
pos->GetMaterial(&mat);
static_cast<CcInt*>( result.addr )->Set( true,
mat.Count( *value->GetStringval() ) );
return 0;
}
/*
3.3 Operators exact equal "(=)"[1] and piecevalue equal "(tilde)" and piecvalue less "(<)"
*/
struct equalInfo : OperatorInfo {
equalInfo() : OperatorInfo()
{
name = "=";
signature = "material x material -> bool, position x string -> bool";
syntax = "_ = _";
meaning = "Returns true if both values are exactly equal. In the case "
"of positions the move must not be equal";
}
};
struct approxequalInfo : OperatorInfo {
approxequalInfo() : OperatorInfo()
{
name = "~";
signature = "material x material -> bool, position x string -> bool";
syntax = "_ ~ _";
meaning = "Returns true if both weighted sums of material are equal. "
"In the case of positions the material of the whole board "
"is used.";
}
};
struct lessInfo : OperatorInfo {
lessInfo() : OperatorInfo()
{
name = "<";
signature = "material x material -> bool, position x string -> bool";
syntax = "_ < _";
meaning = "Returns true if the weighted sum of the material, or"
"the material given by the position is less than the other";
}
};
/*
3.4 Type Mappings
*/
const string maps_equal[2][3] = { {MATERIAL, MATERIAL, BOOL},
{POSITION, POSITION, BOOL} };
static ListExpr
equal_tm(ListExpr args)
{
return SimpleMaps<2,3>(maps_equal, args);
}
int
equal_sf( ListExpr args )
{
return SimpleSelect<2,3>(maps_equal, args);
}
template<class T>
int equal_vm( Word * args, Word & result,
int message, Word & local, Supplier s )
{
T* arg1 = static_cast<T*>( args[0].addr );
T* arg2 = static_cast<T*>( args[1].addr );
result = qp->ResultStorage( s );
static_cast<CcBool*>( result.addr )->Set( true, arg1->Compare( arg2 ) == 0 );
return 0;
}
template<class T>
int approxequal_vm( Word * args, Word & result,
int message, Word & local, Supplier s )
{
T* arg1 = static_cast<T*>( args[0].addr );
T* arg2 = static_cast<T*>( args[1].addr );
result = qp->ResultStorage( s );
static_cast<CcBool*>( result.addr )->Set( true,
arg1->ComparePieceValues( arg2 ) == 0 );
return 0;
}
template<class T>
int less_vm( Word * args, Word & result,
int message, Word & local, Supplier s )
{
T* arg1 = static_cast<T*>( args[ 0 ].addr );
T* arg2 = static_cast<T*>( args[ 1 ].addr );
result = qp->ResultStorage( s );
static_cast<CcBool*>( result.addr )->Set( true,
( arg1->ComparePieceValues( arg2 ) < 0 ) );
return 0;
}
ListExpr MatMatBoolTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args );
ListExpr arg2 = nl->Second( args );
if ( nl->IsEqual( arg1, "material" ) && nl->IsEqual( arg2, "material" ) )
return nl->SymbolAtom( "bool" );
}
return nl->SymbolAtom( "typeerror" );
}
/*
3.4 Operator pieces
*/
const string piecesSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>material string -> bool</text--->"
"<text>_ pieces</text--->"
"<text>Returns respective material object.</text--->"
"<text>query pos1 pieces</text--->"
")" ")";
int piecesValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Position * position = ( ( Position* ) args[ 0 ].addr );
result = qp->ResultStorage( s );
if ( position->IsDefined() )
position->GetMaterial( ( ( Material* ) result.addr ) );
else
( ( Material* ) result.addr ) ->SetDefined( false );
return 0;
}
ListExpr piecesTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg = nl->First( args );
if ( nl->IsEqual( arg, "position" ) )
return nl->SymbolAtom( "material" );
}
return nl->SymbolAtom( "typeerror" );
}
/*
3.5 Operator moveNo
*/
const string moveNoSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>move -> int, position -> int</text--->"
"<text>_ moveNo</text--->"
"<text>Returns move number of move or position object.</text--->"
"<text>query move1 moveNo</text--->"
")" ")";
int moveNoValueMapM( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Move * move = ( ( Move* ) args[ 0 ].addr );
result = qp->ResultStorage( s );
if ( move->IsDefined() )
( ( CcInt* ) result.addr ) ->Set( true, move->GetMoveNumber() );
else
( ( CcInt* ) result.addr ) ->SetDefined( false );
return 0;
}
int moveNoValueMapP( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Position * position = ( ( Position* ) args[ 0 ].addr );
result = qp->ResultStorage( s );
if ( position->IsDefined() )
( ( CcInt* ) result.addr ) ->Set( true, position->GetMoveNumber() );
else
( ( CcInt* ) result.addr ) ->SetDefined( false );
return 0;
}
ListExpr moveNoTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
ListExpr arg = nl->First( args );
if ( ( nl->IsEqual( arg, "chessmove" ) ) ||
( nl->IsEqual( arg, "position" ) ) )
return nl->SymbolAtom( "int" );
}
return nl->SymbolAtom( "typeerror" );
}
ValueMapping moveNoMap[] = { moveNoValueMapM, moveNoValueMapP };
int moveNoSelect( ListExpr args )
{
ListExpr arg = nl->First( args );
if ( nl->IsEqual( arg, "chessmove" ) )
return ( 0 );
if ( nl->IsEqual( arg, "position" ) )
return ( 1 );
return ( -1 ); // This point should never be reached
}
/*
3.6 Operator range
*/
const string rangeSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>string int string int-> position</text--->"
"<text>_ range[_,_,_,_]</text--->"
"<text>Returns a partial position object.</text--->"
"<text>query pos1 range[\"b\",2,\"g\",7]</text--->"
")" ")";
int rangeValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Position * position = ( ( Position* ) args[ 0 ].addr );
CcString * startFile = ( ( CcString* ) args[ 1 ].addr );
CcInt * startRow = ( ( CcInt* ) args[ 2 ].addr );
CcString * endFile = ( ( CcString* ) args[ 3 ].addr );
CcInt * endRow = ( ( CcInt* ) args[ 4 ].addr );
result = qp->ResultStorage( s );
position->Range( ( ( Position* ) result.addr ),
startFile->GetValue() [ 0 ], startRow->GetValue(),
endFile->GetValue() [ 0 ], endRow->GetValue() );
return 0;
}
ListExpr rangeTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 5 )
{
ListExpr arg1 = nl->First( args );
ListExpr arg2 = nl->Second( args );
ListExpr arg3 = nl->Third( args );
ListExpr arg4 = nl->Fourth( args );
ListExpr arg5 = nl->Fifth( args );
if ( ( nl->IsEqual( arg1, "position" ) )
&& nl->IsAtom( arg2 ) && nl->IsEqual( arg2, "string" )
&& nl->IsAtom( arg3 ) && nl->IsEqual( arg3, "int" )
&& nl->IsAtom( arg4 ) && nl->IsEqual( arg4, "string" )
&& nl->IsAtom( arg5 ) && nl->IsEqual( arg5, "int" ) )
return nl->SymbolAtom( "position" );
}
return nl->SymbolAtom( "typeerror" );
}
/*
3.7 Operator includes
*/
const string includesSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>position position -> bool</text--->"
"<text>_ includes [ _ ]</text--->"
"<text>Returns true, if pos2 is included in pos2</text--->"
"<text>query pos1 includes [pos2]</text--->"
")" ")";
int includesValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Position * pos1 = ( ( Position* ) args[ 0 ].addr );
Position * pos2 = ( ( Position* ) args[ 1 ].addr );
result = qp->ResultStorage( s );
( ( CcBool* ) result.addr ) ->Set( true, pos2->IsIncluded( pos1 ) );
return 0;
}
ListExpr includesTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args );
ListExpr arg2 = nl->Second( args );
if ( ( nl->IsEqual( arg1, "position" ) )
&& ( nl->IsEqual( arg2, "position" ) ) )
return nl->SymbolAtom( "bool" );
}
return nl->SymbolAtom( "typeerror" );
}
/*
3.8 Operator getposition
*/
const string getpositionSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>game int -> position</text--->"
"<text>_ getposition [_]</text--->"
"<text>Returns position of a game after the specificated move</text--->"
"<text>query game getposition [4]</text--->"
")" ")";
int getpositionValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Chessgame * game = ( ( Chessgame* ) args[ 0 ].addr );
CcInt * moveNumber = ( ( CcInt* ) args[ 1 ].addr );
result = qp->ResultStorage( s );
if ( ( moveNumber->GetValue() < 0 )
|| ( moveNumber->GetValue() > game->GetMovesCount() ) )
( ( Position* ) result.addr ) ->SetDefined( false );
else
game->GetPosition( ( Position* ) result.addr, moveNumber->GetValue() );
return 0;
}
ListExpr getpositionTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args );
ListExpr arg2 = nl->Second( args );
if ( ( nl->IsEqual( arg1, "chessgame" ) )
&& ( nl->IsAtom( arg2 ) && nl->IsEqual( arg2, "int" ) ) )
return nl->SymbolAtom( "position" );
}
return nl->SymbolAtom( "typeerror" );
}
/*
3.8 Operator getmove
*/
const string getmoveSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>game int -> move</text--->"
"<text>_ getmove [_]</text--->"
"<text>Returns specified move of a game</text--->"
"<text>query game getmove [4]</text--->"
")" ")";
int getmoveValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Chessgame * game = ( ( Chessgame* ) args[ 0 ].addr );
CcInt * moveNumber = ( ( CcInt* ) args[ 1 ].addr );
result = qp->ResultStorage( s );
if ( ( moveNumber->GetValue() < 1 )
|| ( moveNumber->GetValue() > game->GetMovesCount() ) )
( ( Move* ) result.addr ) ->SetDefined( false );
else
game->GetMove( (* ( Move* ) result.addr), moveNumber->GetValue() );
return 0;
}
ListExpr getmoveTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args );
ListExpr arg2 = nl->Second( args );
if ( ( nl->IsEqual( arg1, "chessgame" ) )
&& ( nl->IsAtom( arg2 ) && nl->IsEqual( arg2, "int" ) ) )
return nl->SymbolAtom( "chessmove" );
}
return nl->SymbolAtom( "typeerror" );
}
/*
3.9 Operator getkey
*/
const string getkeySpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>game string -> string</text--->"
"<text>_ getkey [_]</text--->"
"<text>Returns specified data of a game</text--->"
"<text>query game getkey [\"name_w\"]</text--->"
")" ")";
int getkeyValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Chessgame * game = ( ( Chessgame* ) args[ 0 ].addr );
CcString * key = ( ( CcString* ) args[ 1 ].addr );
result = qp->ResultStorage( s );
STRING_T resultStr;
game->GetMetainfoValue( key->GetValue(), &resultStr );
( ( CcString* ) result.addr ) ->Set( true, &resultStr ) ;
return 0;
}
ListExpr getkeyTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 2 )
{
ListExpr arg1 = nl->First( args );
ListExpr arg2 = nl->Second( args );
if ( ( nl->IsEqual( arg1, "chessgame" ) )
&& ( nl->IsAtom( arg2 ) && nl->IsEqual( arg2, "string" ) ) )
return nl->SymbolAtom( "string" );
}
return nl->SymbolAtom( "typeerror" );
}
struct Localinfo
{
Chessgame * game;
int cntr;
};
/*
3.10 Operator moves
*/
const string movesSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>game -> moves</text--->"
"<text>_ moves</text--->"
"<text>Returns a stream of all moves of a game</text--->"
"<text>query game moves</text--->"
")" ")";
int movesValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Localinfo * localinfo = new Localinfo;
switch ( message )
{
case OPEN:
localinfo->game = ( Chessgame* ) args[ 0 ].addr;
localinfo->cntr = 1;
local.addr = localinfo;
return 0;
case REQUEST:
localinfo = ( Localinfo* ) local.addr;
if ( localinfo->cntr <= ( localinfo->game->GetMovesCount() ) )
{
Move m = localinfo->game->GetMove( localinfo->cntr++ );
Move* res = new Move(m);
result.addr = res;
return YIELD;
}
else
return CANCEL;
case CLOSE:
localinfo = ( Localinfo* ) local.addr;
delete localinfo;
return 0;
}
return -1;
}
ListExpr movesTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
if ( nl->IsEqual( nl->First( args ), "chessgame" ) )
return nl->TwoElemList( nl->SymbolAtom( "stream" ),
nl->SymbolAtom( "chessmove" ) );
}
return nl->SymbolAtom( "typeerror" );
}
/*
3.10 Operator positions
*/
const string positionsSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>game -> positions</text--->"
"<text>_ moves</text--->"
"<text>Returns a stream of all moves of a game</text--->"
"<text>query game positions</text--->"
")" ")";
int positionsValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
Localinfo * localinfo = new Localinfo();
switch ( message )
{
case OPEN:
localinfo->game = ( Chessgame* ) args[ 0 ].addr;
localinfo->cntr = 0;
local.addr = localinfo;
return 0;
case REQUEST:
localinfo = ( Localinfo* ) local.addr;
if ( localinfo->cntr <= ( localinfo->game->GetMovesCount() ) )
{
result.addr = ( localinfo->game->GetPosition( localinfo->cntr++ ) );
return YIELD;
}
else
return CANCEL;
case CLOSE:
return 0;
}
return -1;
}
ListExpr positionsTypeMap( ListExpr args )
{
if ( nl->ListLength( args ) == 1 )
{
if ( nl->IsEqual( nl->First( args ), "chessgame" ) )
return nl->TwoElemList( nl->SymbolAtom( "stream" ),
nl->SymbolAtom( "position" ) );
}
return nl->SymbolAtom( "typeerror" );
}
/*
3.11 Operator movingpoints
Dieser Fehler ist in der movingpoints-Implementierung enthalten:
Wenn eine Figur geschlagen wird, wandert sie auf die Koordinaten (x,
y+-2), wenn seine Anfangskoordinaten (x,y) waren; dabei gilt "+" f<EFBFBD>r
schwarze und "-" f<EFBFBD>r wei<EFBFBD>e Figuren. Z.B. wandert die wei<EFBFBD>e Dame auf die
Koordinaten (4.0, -1.0).
Handelt es ich bei der geschlagenen Figur um einen Offizier, der aus
einer Bauernumwandlung hervorging, so zeigen seine Anfangskoordinaten
auf die gegnerische Grundlinie. Er zieht also auf die Linie 6, wenn er
wei<EFBFBD> ist, auf die Linie 3, wenn er schwarz ist - und da geh<EFBFBD>rt er nun
wirklich nicht hin.
M<EFBFBD>gliche L<EFBFBD>sungsvarianten w<EFBFBD>ren:
- <EFBFBD>nderung des Figurtyps beim umgewandelten Bauern statt Erzeugung einer
neuen Figur (das hat Vor- und Nachteile f<EFBFBD>r manche analytischen Abfragen)
- Setzen eines Flags "isPromotedPawn" oder so, das bei der Berechnung
des Abstellplatzes ausgewertet wird
- Festlegen des Abstellplatzes bei der Initialisierung, statt sie erst
im Moment des Schlagens zu berechnen
Bei der 2. und 3. L<EFBFBD>sung m<EFBFBD><EFBFBD>te man noch <EFBFBD>berlegen, was ein geeigneter
Abstellplatz ist und wie man zuverl<EFBFBD>ssig vermeidet, da<EFBFBD> dort mehrere
Figuren abgestellt werden.
*/
const string movingpointsSpec =
"(" "(" "\"Signature\"" "\"Syntax\"" "\"Meaning\"" "\"Example\"" ")" "("
"<text>chessgame -> stream(tup(Piece White Route)</text--->"
"<text>with Piece: string, White: bool, Route: mpoint</text--->"
"<text>Returns a stream with all pieces' movements</text--->"
"<text>query game movingpoints consume</text--->"
")" ")";
int movingpointsValueMap( Word * args, Word & result,
int message, Word & local, Supplier s )
{
MovingChessPieces * mcps = 0;
MovingChessPiece* mcp = 0;
Chessgame* game = 0;
Move mv;
string startfile, endfile, argstr;
CcString* ki = 0;
STRING_T hilfstr;
CcBool* iw = 0;
MPoint* mp = 0;
int i = 0;
ListExpr resultType;
TupleType* resultTupleType = 0;
Tuple* tup = 0;
switch ( message )
{
case OPEN:
game = ( Chessgame* ) args[ 0 ].addr;
resultType = GetTupleResultType( s );
resultTupleType = new TupleType( nl->Second( resultType ) );
/*
The result is a stream of tuples with an attribute of type mpoint,
these mpoints must be completely created from the chessgame before
the first tuple can be written. Therefore, this work is done when the
stream is opened.
1st step: create the movingpoints for the start position of the game
*/
mcps = new MovingChessPieces();
local.addr = mcps;
mcps->setTupleTypeRemember( resultTupleType );
/*
2nd step: read all moves of the game and realize it in the mcps structure
*/
for ( i = 1;i <= game->GetMovesCount();i++ )
{
Move m1;
game->GetMove(m1,i);
MoveData m2 = game->GetMoveData(i-1);
mcps->realizeMove( &m1, &m2 );
}
mcps->closeMPoints();
return 0;
case REQUEST:
mcps = ( MovingChessPieces* ) local.addr;
// reestablish access to moving points array
i = mcps->getMPointWriteNextCount();
// look how many tuples have been written
if ( i < 48 )
{
while ( i < 48 )
{
if ( mcps->isValid( i ) ) break;
// only write mpoints representing chesspieces used
i++;
mcps->incMPointWriteNextCount();
}
if ( i >= 48 ) return CANCEL;
// if i !< 48: no valid mpoints any more to write
mcps->incMPointWriteNextCount();
mcp = mcps->getMovingChessPiece( i );
resultTupleType = mcps->getTupleTypeRemember();
tup = new Tuple( resultTupleType );
strcpy( hilfstr, ( char* ) ( mcp->getKind() ->c_str() ) );
ki = new CcString( true, &hilfstr );
tup->PutAttribute( 0, ( Attribute* ) ki );
iw = new CcBool( true, *( mcp->trueIsWhite() ) );
tup->PutAttribute( 1, ( Attribute* ) iw );
mp = mcp->getMPoint();
tup->PutAttribute( 2, ( ( Attribute* ) mp ) ->Clone() );
result = SetWord( tup );
return YIELD;
}
else
return CANCEL;
case CLOSE:
//cout << "movingpointsValueMap entered for CLOSE" << endl;
mcps = ( MovingChessPieces* ) local.addr;
// reestablish access to moving points array
mcps->getTupleTypeRemember() ->DeleteIfAllowed();
delete mcps;
return 0;
}
return -1;
}
ListExpr movingpointsTypeMap( ListExpr args )
{
ListExpr streamList, tupleList;
string argstr;
nl->WriteToString( argstr, args );
if ( nl->ListLength( args ) == 1 )
{
tupleList = nl->ThreeElemList(
nl->TwoElemList(
nl->SymbolAtom( "Piece" ), nl->SymbolAtom( "string" ) ),
nl->TwoElemList(
nl->SymbolAtom( "White" ), nl->SymbolAtom( "bool" ) ) ,
nl->TwoElemList(
nl->SymbolAtom( "Route" ), nl->SymbolAtom( "mpoint" ) )
);
streamList = nl->TwoElemList( nl->SymbolAtom( "stream" ),
nl->TwoElemList( nl->SymbolAtom( "tuple" ),
tupleList ) );
if ( nl->IsEqual( nl->First( args ), "chessgame" ) )
{
nl->WriteToString( argstr, streamList );
return streamList;
}
}
return nl->SymbolAtom( "typeerror" );
}
/*
4 Build Type Constructors
*/
TypeConstructor materialTC(
"material",
MaterialProp,
OutMaterial, InMaterial,
0, 0,
CreateMaterial, DeleteMaterial,
0, 0,
CloseMaterial, CloneMaterial,
CastMaterial,
SizeOfMaterial,
MaterialType
);
TypeConstructor moveTC(
"chessmove",
MoveProp,
OutMove, InMove,
0, 0,
CreateMove, DeleteMove,
0, 0,
CloseMove, CloneMove,
CastMove,
SizeOfMove,
MoveType
);
TypeConstructor positionTC(
"position",
PositionProp,
OutPosition, InPosition,
0, 0,
CreatePosition, DeletePosition,
0, 0,
ClosePosition, ClonePosition,
CastPosition,
SizeOfPosition,
PositionType
);
#ifdef RELALG_PERSISTENT
TypeConstructor gameTC(
"chessgame",
ChessgameProp,
OutChessgame, InChessgame,
0, 0,
CreateChessgame, DeleteChessgame,
OpenChessgame, SaveChessgame,
CloseChessgame, CloneChessgame,
CastChessgame,
SizeOfChessgame,
ChessgameType
);
#else
TypeConstructor gameTC(
"chessgame",
ChessgameProp,
OutChessgame, InChessgame,
0, 0,
CreateChessgame, DeleteChessgame,
0, 0,
CloseChessgame, CloneChessgame,
CastChessgame,
SizeOfChessgame,
ChessgameType
);
#endif // RELALG_PERSISTENT
/*
5 Build Operators
*/
Operator readpgnOp (
"readpgn",
readpgnSpec,
readpgnValueMap,
Operator::SimpleSelect,
readpgnTypeMap
);
Operator agentOp (
"agent",
agentSpec,
agentValueMap,
Operator::SimpleSelect,
moveStrTypeMap
);
Operator capturedOp (
"captured",
capturedSpec,
capturedValueMap,
Operator::SimpleSelect,
moveStrTypeMap
);
Operator startrowOp (
"startrow",
startrowSpec,
startrowValueMap,
Operator::SimpleSelect,
moveIntTypeMap
);
Operator endrowOp (
"endrow",
endrowSpec,
endrowValueMap,
Operator::SimpleSelect,
moveIntTypeMap
);
Operator startfileOp (
"startfile",
startfileSpec,
startfileValueMap,
Operator::SimpleSelect,
moveStrTypeMap
);
Operator endfileOp (
"endfile",
endfileSpec,
endfileValueMap,
Operator::SimpleSelect,
moveStrTypeMap
);
Operator checkOp (
"check",
checkSpec,
checkValueMap,
Operator::SimpleSelect,
moveBoolTypeMap
);
Operator capturesOp (
"captures",
capturesSpec,
capturesValueMap,
Operator::SimpleSelect,
moveBoolTypeMap
);
ValueMapping piececount_vms[] =
{
piececount_vm,
piececount_vm2
};
ValueMapping equal_vms[] =
{
equal_vm<Material>,
equal_vm<Position>
};
ValueMapping approxequal_vms[] =
{
approxequal_vm<Material>,
approxequal_vm<Position>
};
ValueMapping less_vms[] =
{
less_vm<Material>,
less_vm<Position>
};
Operator piecesOp (
"pieces",
piecesSpec,
piecesValueMap,
Operator::SimpleSelect,
piecesTypeMap
);
Operator moveNoOp (
"moveNo",
moveNoSpec,
2, moveNoMap,
moveNoSelect,
moveNoTypeMap
);
Operator rangeOp (
"posrange",
rangeSpec,
rangeValueMap,
Operator::SimpleSelect,
rangeTypeMap
);
Operator includesOp (
"includes",
includesSpec,
includesValueMap,
Operator::SimpleSelect,
includesTypeMap
);
Operator getpositionOp (
"getposition",
getpositionSpec,
getpositionValueMap,
Operator::SimpleSelect,
getpositionTypeMap
);
Operator getmoveOp (
"getmove",
getmoveSpec,
getmoveValueMap,
Operator::SimpleSelect,
getmoveTypeMap
);
Operator getkeyOp (
"getkey",
getkeySpec,
getkeyValueMap,
Operator::SimpleSelect,
getkeyTypeMap
);
Operator movesOp (
"moves",
movesSpec,
movesValueMap,
Operator::SimpleSelect,
movesTypeMap
);
Operator positionsOp (
"positions",
positionsSpec,
positionsValueMap,
Operator::SimpleSelect,
positionsTypeMap
);
Operator movingpointsOp (
"movingpoints",
movingpointsSpec,
movingpointsValueMap,
Operator::SimpleSelect,
movingpointsTypeMap
);
/*
6 Build Algebra
*/
class ChessAlgebra : public Algebra
{
public:
ChessAlgebra() : Algebra()
{
AddTypeConstructor( &materialTC );
AddTypeConstructor( &moveTC );
AddTypeConstructor( &positionTC );
AddTypeConstructor( &gameTC );
materialTC.AssociateKind( "DATA" );
moveTC.AssociateKind( "DATA" );
positionTC.AssociateKind( "DATA" );
gameTC.AssociateKind( "DATA" );
materialTC.AssociateKind( "INDEXABLE" );
moveTC.AssociateKind( "INDEXABLE" );
positionTC.AssociateKind( "INDEXABLE" );
gameTC.AssociateKind( "INDEXABLE" );
AddOperator( &readpgnOp );
AddOperator( &agentOp );
AddOperator( &capturedOp );
AddOperator( &startrowOp );
AddOperator( &endrowOp );
AddOperator( &startfileOp );
AddOperator( &endfileOp );
AddOperator( &checkOp );
AddOperator( &capturesOp );
AddOperator( piececountInfo(), piececount_vms,
piececount_sf, piececount_tm );
AddOperator( equalInfo(), equal_vms, equal_sf, equal_tm );
AddOperator( approxequalInfo(), approxequal_vms, equal_sf, equal_tm );
AddOperator( lessInfo(), less_vms, equal_sf, equal_tm );
AddOperator( &piecesOp );
AddOperator( &moveNoOp );
AddOperator( &rangeOp );
AddOperator( &includesOp );
AddOperator( &getpositionOp );
AddOperator( &getmoveOp );
AddOperator( &getkeyOp );
AddOperator( &movesOp );
AddOperator( &positionsOp );
AddOperator( &movingpointsOp );
}
~ChessAlgebra() {}
;
};
extern "C"
Algebra*
InitializeChessAlgebra( NestedList * nlRef, QueryProcessor * qpRef )
{
nl = nlRef;
qp = qpRef;
return ( new ChessAlgebra() );
}
} // Namespace chessAlgebra