Moderator: Andres Valverde
H.G.Muller wrote:You paint a much too gloomy picture, Reinhard. It is true some people are only interested in playing engines like Rybka against Fruit. But enough people reamain that have interest in other engines as well.
That those people don't use your creations is more a consequence of that you seem to make it almost impossible for them to do so. I would be very interested to play automated engine-engine games of 10x8 variants with SMIRF, but I could not find any description of how to inteface SMIRF to other engines, and a clear definition of the protocol to use...
Reinhard Scharnagl wrote:Before I wrote SMIRF, I dedicatedly tried to avoid any one-man modification of a protocol (I would have thought on UCI-2). Thus I have invented and published the TMCI (Third Millennium Chess Interface), which still is used for the communication between SMIRF and its GUI.
//================================================
// PROJECT: SmirfEngine.dll (C) R. Scharnagl
//================================================
#ifndef SmirfEngineH
#define SmirfEngineH
// --- to be defined when included in its *.cpp ---
#ifdef SmirfDLL
#define IMP_EXP dllexport
#else
#define IMP_EXP dllimport
#endif
#include "../Schach/Mov.h"
#include "../Schach/Hsh.h"
#ifdef __BCPLUSPLUS__
#define ENGINE_NAME "Smirf"
#else
#define ENGINE_NAME "SMIRF"
#endif
// the TMCI engine interface function: DoCmd()
extern "C" __declspec(IMP_EXP) const char * __cdecl DoCmd(
char MainCmd, char SubCmd, int nrIn = 0, const char *pIn = 0L);
/*
TMCI protocol (Third Millennium Chess Interface) [ incomplete draft ]
The protocol is intended to keep the GUI realy silly. The GUI
gets all its knowlegde on chess moves from the engines. This
makes those GUIs much easier to be extended to new variants,
and also allows an easier writing of such GUIs.
COMMANDS (please discuss planned extensions with R. Scharnagl)
How to perform any command:
(DoCmd args) (DoCmd answer)
'*' '*' ** ** => char string "<answer>" rsp. "ok" at success
(and stop any engine run task, if necessary)
=> otherwise 0L, if impossible or after errors
(query last error reason by: DoCmd('I','R'))
(ALREADY DONE)
Query:
'?' '*' -- -- => list of all sub commands to any main command '*'
'?' '?' -- -- => list of all main commands
Info:
'I' 'A' -- -- => name of the author
'I' 'E' -- -- => name of the engine
'I' 'V' -- -- => version of the engine
'I' 'R' -- -- => reason (of the last error situation)
FEN-Position:
'F' 'S' -- -- => produce the FEN char string matching the
current situation
'F' '4' nr -- => produce the FEN char string to a numbered
Chess480 starting position (<nr> 1...960)
(or else 0L, when not FRC 8x8 aware)
'F' '8' nr -- => produce the FEN char string to a numbered
chess960 8x8 starting position (<nr> 1...960)
(or else 0L, when not FRC 8x8 aware)
0 -- => produce the FEN char string to
the classical 8x8 chess starting array
(or else 0L, when not standard 8x8 aware)
'F' 'C' nr vv => produce the FEN char string to a numbered (not
selected) CRC 10x8 starting position (<nr> 1...48000)
(or else 0L, when not CRC 10x8 aware if vv != 0L)
0 -- => produce the FEN char string to
the Capablanca 10x8 chess starting array
(or else 0L, when not Capablanca 10x8 aware)
-1 -- => produce the FEN char string to
the MBC Chess 10x8 chess starting array
(or else 0L, when not MBC Chess 10x8 aware)
-2 -- => produce the FEN char string to
the Janus Chess 10x8 chess starting array
(or else 0L, when not Janus Chess 10x8 aware)
-3 -- => produce the FEN char string to
the Bird 10x8 chess starting array
(or else 0L, when not Bird 10x8 aware)
-4 -- => produce the FEN char string (Pos. 25495) to
the Carrera 10x8 chess starting array
(or else 0L, when not Carrera 10x8 aware)
-5 -- => produce the FEN char string (Pos. 25933) to
the GothicChess 10x8 chess starting array
(or else 0L, when not GothicChess 10x8 aware)
-6 -- => produce the FEN char string (Pos. 27016) to
the Optimized Chess 10x8 chess starting array
(or else 0L, when not Optimized Chess 10x8 aware)
Move:
'M' 'A' nr -- => show the currently prepared move <nr> in
algebraic form (letter, digit, letter, digit, extra),
source before target, where extra is the lower promotion
piece code (English) or zero. When a King's castling
move does less than two elementary steps, the involved
Rook's coordinate will be used as target coordinate.
(or else 0L, if move <nr> does not exist)
This codes are sent back to the engine in case that
a move would be selected.
'M' 'T' nr -- => show the currently prepared move <nr> as long text
(e.g. "e4xf5+", "O-O-O" or "Bc1-f4" using English)
(or else 0L, when move <nr> does not exist)
'M' 'S' nr -- => show the currently prepared move <nr> as short text
(e.g. "ef5+", "O-O-O" or "Bf4" using English)
(or else 0L, when move <nr> does not exist)
'M' 'V' nr -- => show the evaluation to currently prepared move <nr>
(or else 0L, when move <nr> does not exist)
'M' 'L' nr -- => show the search level of currently prepared move <nr>
(or else 0L, when move <nr> does not exist)
Enter:
'E' 'F' -- fs => enter a FEN char string <fs> as position
(and prepare a list of actual moves)
'E' 'M' -- mv => enter a move <mv>
(as been encoded before by DoCmd('M', 'A', nr))
(and prepare FEN and a list of actual moves)
'E' '-' -- -- => take back last move
(and prepare FEN and a list of actual moves)
Licensing: (to be set (once) before calculating or pondering)
'L' 'N' -- nm => input the user name <nm>
(will answer a string truncated to < 255 chars)
'L' 'K' -- ky => input the engine-key <ky>
(will answer "ok" when key matches or engine is not
protected at all, or 0L if necessary key was wrong)
(the procedure should not work after some bad trials)
Timing: (to be set befor pondering or computing)
'T' 'W' tm -- => Time Left White, in MSec, totale Restzeit
'T' 'B' tm -- => Time Left Black, in MSec, totale Restzeit
'T' '#' =1 -- => Time is for one move (=1) only or all (=0) moves
Computing:
'C' 'P' -- -- => let the engine start its Ponder-thinking
'C' '+' -- -- => let the engine start its thinking
'C' '-' -- -- => let the engine terminate its thinking
'C' 'B' -- -- => busy? answer with "ok" or 0L
'C' 'I' 00 -- => Info: answer with (last) actual move
'C' 'I' 01 -- => Info: answer with (last) actual value
'C' 'I' 02 -- => Info: answer with (last) actual PV
'C' 'A' -- -- => request answer-move in algebraic notation
'C' 'H' -1 -- => query hash size as a char string
'C' 'H' mb -- => set new hash size in MB and query result
(TODO)
'T' 'F' tm -- => Fischerzeit pro Zug (falls geändert)
Computing:
*/
//-------------------------------------------------------
// A simple program that uses LoadLibrary and
// GetProcAddress to access myPuts from Myputs.dll.
#include <windows.h>
#include <stdio.h>
typedef const char * (__cdecl *MYPROC)(char, char, int, LPWSTR);
int main(VOID)
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
char buf[80]; const char *p;
// Get a handle to the DLL module.
hinstLib = LoadLibrary(TEXT("SmirfEngine.dll"));
if(hinstLib == NULL) { printf("Smirf DLL not found\n"); exit(0); }
// If the handle is valid, try to get the function address.
if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, TEXT("DoCmd"));
// If the function address is valid, call the function.
if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
p = (ProcAdd) ('L', 'N', 0, L"H.G.Muller");
printf("Smirf returned '%s'\n", p);
(ProcAdd) ('L', 'K', 0, L"342f6f5e 026b3179");
printf("Smirf returned '%s'\n", p);
} else { printf("Bad entry point %d\n", GetLastError()); exit(0); }
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
// If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
printf("Message printed from executable\n");
}
//---------------------------------------------------------------------------
// --- System-Includes ---
#include <windows.h>
#include <iostream>
#pragma hdrstop
//---------------------------------------------------------------------------
// own datatype
typedef const char * __cdecl FEngine(
char MainCmd, char SubCmd, int nrIn = 0, const char *pIn = 0L);
// the engine link
HMODULE HdEngine;
FEngine *Engine;
using namespace std;
#pragma argsused
int main(int argc, char* argv[])
{
// load engine
bool loadOk = false;
if ((HdEngine = LoadLibrary("SmirfEngine.dll")) != 0) {
// load engine flexibly on compiled version
// using two different entry name patterns
char *name[] = {
"_DoCmd", "DoCmd"
};
int i;
for (i = sizeof(name)/sizeof(*name); --i >= 0; ) {
if ( ((FARPROC)Engine
= GetProcAddress(HdEngine, name[i])) != 0
) {
loadOk = true;
break;
}
}
}
if (!loadOk) {
// SmirfEngine.dll not in local folder
cout << "DLL does not match" << endl;
} else {
// get name of engine example
cout << (*Engine)('I', 'E') << endl;
// get name of author example
cout << (*Engine)('I', 'A') << endl;
}
system("pause");
return 0;
}
//---------------------------------------------------------------------------
// A simple program that uses LoadLibrary and
// GetProcAddress to access myPuts from Myputs.dll.
#include <windows.h>
#include <stdio.h>
typedef const char * (__cdecl *MYPROC)(char, char, int, char *);
int main(VOID)
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
char buf[80]; const char *p;
// Get a handle to the DLL module.
hinstLib = LoadLibrary(TEXT("SmirfEngine.dll"));
if(hinstLib == NULL) { printf("Smirf DLL not found\n"); exit(0); }
// If the handle is valid, try to get the function address.
if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, TEXT("_DoCmd"));
// If the function address is valid, call the function.
if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
p = (ProcAdd) ('L', 'N', 0, "H.G.Muller");
printf("Send name: Smirf returned '%s'\n", p);
p = (ProcAdd) ('L', 'K', 0, "342f6f5e 026b3179");
printf("Send key: Smirf returned '%s'\n", p);
p = (ProcAdd) ('F', 'S', 0, NULL);
printf("Print board: Smirf returned '%s'\n", p);
p = (ProcAdd) ('F', 'C', -5, NULL);
printf("Ask FEN: Smirf returned '%s'\n", p);
p = (ProcAdd) ('E', 'F', 0, "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
printf("Enter FEN: Smirf returned '%s'\n", p);
p = (ProcAdd) ('F', 'S', 0, NULL);
printf("Print board: Smirf returned '%s'\n", p);
p = (ProcAdd) ('E', 'M', 0, "e2e4");
printf("Enter move: Smirf returned '%s'\n", p);
p = (ProcAdd) ('F', 'S', 0, NULL);
printf("Print board: Smirf returned '%s'\n", p);
p = (ProcAdd) ('T', 'W', 300000, NULL);
printf("Enter wTime: Smirf returned '%s'\n", p);
p = (ProcAdd) ('T', 'B', 300000, NULL);
printf("Enter bTime: Smirf returned '%s'\n", p);
p = (ProcAdd) ('T', '#', 40, NULL);
printf("Enter nrMov: Smirf returned '%s'\n", p);
p = (ProcAdd) ('C', '+', 0, NULL);
printf("Search: Smirf returned '%s'\n", p);
p = (ProcAdd) ('C', 'A', 0, NULL);
printf("Get move: Smirf returned '%s'\n", p);
} else { printf("Bad entry point %d\n", GetLastError()); exit(0); }
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
// If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
printf("Message printed from executable\n");
}
Send name: Smirf returned 'H.G.Muller'
Send key: Smirf returned '(null)'
Print board: Smirf returned ''
Ask FEN: Smirf returned 'rnbqckabnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNBQCKABNR w KQkq - 0 1'
Enter FEN: Smirf returned 'ok'
Print board: Smirf returned 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
Enter move: Smirf returned 'ok'
Print board: Smirf returned 'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1'
Enter wTime: Smirf returned 'ok'
Enter bTime: Smirf returned 'ok'
Enter nrMov: Smirf returned 'ok'
Search: Smirf returned 'ok'
Get move: Smirf returned '#0#0'
p = (ProcAdd) ('L', 'N', 0, "H.G.Muller");
printf("Send name: Smirf returned '%s'\n", p);
p = (ProcAdd) ('L', 'K', 0, "");
printf("Send key: Smirf returned '%s'\n", p);
p = (ProcAdd) ('F', 'S', 0, NULL);
printf("Print board: Smirf returned '%s'\n", p);
p = (ProcAdd) ('F', 'C', -5, NULL);
printf("Ask FEN: Smirf returned '%s'\n", p);
p = (ProcAdd) ('E', 'F', 0,
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
printf("Enter FEN: Smirf returned '%s'\n", p);
p = (ProcAdd) ('F', 'S', 0, NULL);
printf("Print board: Smirf returned '%s'\n", p);
p = (ProcAdd) ('E', 'M', 0, "e2e4");
printf("Enter move: Smirf returned '%s'\n", p);
p = (ProcAdd) ('F', 'S', 0, NULL);
printf("Print board: Smirf returned '%s'\n", p);
p = (ProcAdd) ('T', 'W', 300000, NULL);
printf("Enter wTime: Smirf returned '%s'\n", p);
p = (ProcAdd) ('T', 'B', 300000, NULL);
printf("Enter bTime: Smirf returned '%s'\n", p);
p = (ProcAdd) ('T', '#', 40, NULL);
printf("Enter nrMov: Smirf returned '%s'\n", p);
p = (ProcAdd) ('C', '+', 0, NULL);
printf("Search: Smirf returned '%s'\n", p);
do {
p = (ProcAdd) ('C', 'B', 0, NULL);
cnt++;
} while(p != NULL);
printf("%4d polls: Smirf returned '%s'\n", cnt, p);
p = (ProcAdd) ('C', 'I', 2, NULL);
printf("Get PV: Smirf returned '%s'\n", p);
p = (ProcAdd) ('C', 'I', 1, NULL);
printf("Get score: Smirf returned '%s'\n", p);
p = (ProcAdd) ('C', 'A', 0, NULL);
printf("Get move: Smirf returned '%s'\n", p);
Send name: Smirf returned 'H.G.Muller'
Send key: Smirf returned '(null)'
Print board: Smirf returned ''
Ask FEN: Smirf returned 'rnbqckabnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNBQCKABNR w KQkq - 0 1'
Enter FEN: Smirf returned 'ok'
Print board: Smirf returned 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
Enter move: Smirf returned 'ok'
Print board: Smirf returned 'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1'
Enter wTime: Smirf returned 'ok'
Enter bTime: Smirf returned 'ok'
Enter nrMov: Smirf returned 'ok'
Search: Smirf returned 'ok'
29926817 polls: Smirf returned '(null)'
Get PV: Smirf returned '00:00.6 End of thinking (time eco lo)'
Get score: Smirf returned '(07.02=) -0.141'
Get move: Smirf returned 'b8c6'
Return to Programming and Technical Discussions
Users browsing this forum: No registered users and 15 guests