Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Enter chess moves with Visual Foxpro 4

Status
Not open for further replies.

german12

Programmer
Nov 12, 2001
563
DE
I have a lot of chess books because I've been playing for a long time.
For a special opening I am always looking for variants, but they are difficult to find in my literature.
Now - when I've found something - I want these moves
transferred to a separate Foxpro table.
This would also have the advantage that you can then use a program to remove duplicate variants, or to index or recognize transpositions of moves, etc.
It's faster than writing it down, and I programmed a keyboard to do this.
In the photo you can see this keyboard at the top left.

Schachvarianten_hac5cr.jpg



The program works fine up to this point.

Example 1:
The move with the rook on the e4 square is displayed after clicking R-e-4 in the text field (text1, yellow).

Now I want this content in the table below
in the field M1 (means: Move No.1).
Field-names are M1 to M20
Then I want to type the next move on the keyboard again
and that should then be saved in field M2.
This is how it should go on .... next move in M3 .... etc.

So it is a horizontal filling of the table.
Example 2:
The table should look like this:
Row 1: e4 c5 Nf3 Nb6 d4
Row2: d4 Nf6 Nc3 d5 Bg5 c6

That means the length of the variants can be different.
My table is sufficient for 20 moves (half moves).

Each time a new series of moves is entered, a
new data set is necessary.

Maybe someone can help what the code behind the button "Transfer to table" (red) could be like, or there is a better idea.

I would be very pleased.
Thank you.

Greetings Klaus

By the way:
If you wanted to record all possible moves within a game of chess in a database, then there would be
big problems: at some point I read that there were 10 to the power of 35 possibilities. (So ​​a 10 with 35 zeros).
[blush]

Peace worldwide - it starts here...
 
Koen: thanks for that info. But it does not help to find the necessary code.
Klaus

Peace worldwide - it starts here...
 
Klaus,

I won't try to answer your question. But I would like to take you up on your statement:

Klaus said:
If you wanted to record all possible moves within a game of chess in a database, then there would be
big problems: at some point I read that there were 10 to the power of 35 possibilities. (So ​​a 10 with 35 zeros).

10 to the power of 35 seems like it's much too low. If you are talking about the number of combinations of legal moves that can be played throughout the game from the start, I would guess that it is much more than 10^35. In fact, in can even be considered infinite. After all, at any one time within a game, there are probably several moves that are infinitely reversible. With than in mind, you should be talking about unique moves.

But is that what you really want to know? I think what you are really asking is: how many legal games are there - a game being defined as a series of legal moves that can be expected to reach a conclusion after a reasonable number of moves. On that basis, you should look at the Shannon number, which gives a conservative lower bound 10^120 for a game lasting 40 moves.

Next point: why would you want to store every possible move in a database? I can't think of any chess-playing strategy that would require that. I believe the latest chess-playing algorithms use a database of actual games played over a period of time between expert players. I would guess that such a database would be an order of magnitude smaller than one containing every possible game; it might be as small as a few million rows.

I'm sorry that this doesn't help answer your question, but I hope it might be of interest.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Klaus,

I think most championship games have been recorded somewhere. You could scan them from books, newspapers, etc. Convert the scans to text using one of the many tools available. Then create a program in VFP to enter the moves into a table. Lots of work...

Steve
 
Actually, it's easier than. No need to search books or newspapers. Databases of championship games already exist. A quick search finds sites with names like chess.com and chessgames.com. To illustrate, I just downloaded the first game in the Kasparov vs Topalov 2018 match form chess.com. The match is in a PGN file, which I gather is "portable game notation", which I have no way of opening. But at least the database does exist.

But I dona't think that helps with Klaus's original question.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike, you are right,
After just two moves, 72,084 different positions can arise. The number of possible game courses is once again many times greater: For the first 40 moves, the estimates amount to around 10 ^ 115 to 10 ^ 120 different game courses.
I read the number 10 ^ 35 somewhere over 40 years ago.
Your information relates to about 40 moves ("normal" length of a game) - and of course there are chess games that have over 100 moves - and other chess games that end after just a few moves. (eg German "Schäfermatt" = 1.e4 e5, 2.Bc4 Nc6, 3.Qh5 Nf6 ??? 4.Qxf7= mate in 4)
I expressed myself wrong.
Now I think it was the number of possible positions in an average long game of chess at the time.
In Wikipedia you can see the number 10 ^ 41 for this, which is of course considerably more than my number, but perhaps the mathematicians didn't know any better back then.
Anyway - thanks for your hint.

Mike said:
Next point: why would you want to store every possible move in a database? I can't think of any chess-playing strategy that would require that.
No, that's not my intention.
In my opinion, most games are decided if mistakes are made in the opening of a chess game. You don't need to have knowledge of the endgame if
the game is flawed for that reason alone.
In my experience, for an amateur, this is roughly the field of
first 10 moves.
I also don't intend to know a whole game of chess - that's why I wanted a brief overview of my favorite opening
memorize - working in the middlegame becomes easier if you don't have to struggle with your own mistakes in the opening.
That said, I don't want to make an encyclopedia of chess openings for myself, just a brief overview.
Anything else would be unnecessary and insane work - there are plenty of better sources in books, on the internet and elsewhere.

Mike said:
I'm sorry that this doesn't help answer your question, but I hope it might be of interest.

That's true.
My question isn't just about chess notation either.
I also wanted to know in general how to fill a table horizontally.(field by field - and then next line for a new sequence)
In my example, the fields M1 to M20 in the 1st data record have to be filled for a sequence.
With the 2nd chess variant, these would be the fields M1 to M20 for record no. 2 ... etc.

I can imagine that there are other areas where you would have to build a file like this.
It is not the usual way to fill a file.
But maybe someone has already used or programmed something similar ...

Steve said:
I think most championship games have been recorded somewhere. You could scan them from books, newspapers, etc. Convert the scans to text using one of the many tools available. Then create a program in VFP to enter the moves into a table. Lots of work...
Steve, thank you for this opportunity, but it involves a lot more work.

In principle I need e.g. only one line from chess books.
To scan (cut out) that e.g. from books - is much more work, than to click 3 or 4 times per move.
As mentioned above, I don't want to create an insanely large file.
I only want to focus on a single chess opening for white, which I enjoy playing.
(Later on perhaps a defense for Black). And that is all I want.

In order to scan individual lines from books that contain whole lots, you would have to buy a line scanner.
Then you would have a file as a text file, but not a database that can be recognized with many more options.
A VFP file has many more management options.
I just want to concentrate on one opening for White that is not very well known (Kurt RIchter played it:
The Richter – Veresov Attack (also known as The Veresov Opening) was also named after Kurt Richter and Gavriil Veresov. It most commonly occurs after 1.d4 d5 2.Nc3 Nf6 3.Bg5.

Kurt Paul Otto Joseph Richter (November 24, 1900 in Berlin - December 29, 1969 in Berlin) was a German chess International Master and chess writer. [1]
and that is the reason why many of my opponents always only play the openings that today's champions play - with the openings that are rarely played today that would be an advantage for me.(if I know the structure of that opening better)

Kurt Richter played it very sharply and therefore he was also called "Scharfrichter" engl."executioner" (in English this is a "sharp judge") because "Richter" is not only a German name but the name for a judge.

Koen, Steve and Mike:
My question has not yet been answered, but I am very grateful for all of your suggestions

Best regards
Klaus






S

Peace worldwide - it starts here...
 
Oh what I forgot to write:
When I have gathered a lot of information about my special opening, I can make the file available (of course for free) here for any chess freaks
Maybe an opponent in your chess club can be surprised with it ......

Klaus


Peace worldwide - it starts here...
 
Klaus, have you considered looking for a chess-related forum where you might be able to discuss these ideas? It's quite likely that others have tried to do what you are doing, and they might be happy to share their experiences. It wouldn't be Visual FoxPro of course, but the general techniques would be independent of any particular language.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Klaus,

Please have a look at the code sketch below. Maybe it helps.

Code:
PUBLIC go_Form

go_Form = CreateObject ("frmForm")
go_Form.Visible = .T.
go_Form.Show

READ Events

CLOSE ALL
CLEAR ALL

*****

DEFINE CLASS frmForm As Form
	Width = 600
	Height = 360
	MinWidth = This.Width
	MinHeight = This.Height
	AutoCenter = .T.
	
	Add Object grdGames as Grid with;
		Top = 66, ;
		Left = 18, ;
		Height = 360 - 120, ;
		Width = 600 - 36, ;
		RowHeight = 48, ;
		AllowRowSizing = .F., ;
		DeleteMark = .F., ;
		Anchor = 15, ;
		Visible = .T., ;
		ColumnCount = -1, ;
		RecordSource = "csrChessGames"
    	
		PROCEDURE grdGames.Init()
			WITH This 
				.Column1.Header1.Caption = "Date"
				.Column1.Width = 90

				.Column2.Header1.Caption = "City"
				.Column2.Width = 90

				.Column3.Header1.Caption = "Players"
				.Column3.Width = 150
			ENDWITH 

			With This.Column4
				.Width = This.Parent.Width - 372
				.Header1.Caption = "Moves"
				.NewObject("edtChessMoves","EditBox")
				.CurrentControl = "edtChessMoves"
				.edtChessMoves.Visible = .T.
				.Sparse = .F.
			ENDWITH    	
		ENDPROC 
    	
	ADD OBJECT lblSearch as LABEL WITH ;
		Top = 12, Left = 18, FontBold = .T., FontSize = 10, AutoSize = .T., ;
		Caption = "Search City, Players or Moves"
		
	ADD OBJECT txtSearch as Textbox WITH ;
		Top = 36, Left = 18, Width = 180, Format = "!"

	ADD OBJECT cmdSearch As CommandButton WITH;
		Width = 60, Height = 24, Left = 522, Top = 324, Anchor = 12, Caption = "Search"
		
		PROCEDURE cmdSearch.RightClick()
			ThisForm.txtSearch.Value = ""
			This.Click()
		ENDPROC 

		PROCEDURE cmdSearch.Click()
			IF !EMPTY(ALLTRIM(ThisForm.txtSearch.Value))
				SET Filter TO ;
					ATC(ALLTRIM(ThisForm.txtSearch.Value), cCity) !=  0 OR ;
					ATC(ALLTRIM(ThisForm.txtSearch.Value), cNames) != 0 OR ;
					ATC(ALLTRIM(ThisForm.txtSearch.Value), mMoves) !=  0
			ELSE
				SET Filter TO 
			ENDIF 

			LOCATE
			 
			ThisForm.Refresh()
		ENDPROC

	ADD OBJECT cmdCancel As CommandButton WITH;
		Width = 60, Height = 24, Left = 18, Top = 324, Anchor = 6, Caption = "Exit"

		PROCEDURE cmdCancel.Click()
			CLEAR Events
			ThisForm.Release
		ENDPROC

	PROCEDURE Resize()
		WITH ThisForm.grdGames
			.Column4.Width = .Width - 372
		ENDWITH 
	ENDPROC 

	PROCEDURE Destroy()
		CLEAR Events
		ThisForm.Release
	ENDPROC
    
	PROCEDURE Load()
		Create Cursor csrChessGames (dDate D, cCity C(20), cNames C(20), mMoves M)
		
		INSERT INTO csrChessGames VALUES ( {^2019/12/02}, "London", "Hosky/Schmidt", "e2e3:e7e6 - d2d3:d7d5 - f2f4:f7f5 - since this is a Memo-Field you may add almost as much text as you'd like - " + ;
			"Wenn der Assistent eine neue Firmware findet, zeigt er die Version der neuen Firmware an. Über den Link unter der Firmware-Version erhalten Sie Informationen über " + ;
			"Weiterentwicklungen und neue Funktionen, die das Firmware-Update enthält. Lesen Sie diese Informationen,bevor Sie das Firmware-Update starten.")
		INSERT INTO csrChessGames VALUES ( {^2019/11/03}, "Paris", "Bauer/Koenig", "e2e4:e7e5")
		INSERT INTO csrChessGames VALUES ( {^2018/09/03}, "Budapest", "Dame/Turm", "e2e4:e7e6")
		INSERT INTO csrChessGames VALUES ( {^2018/06/18}, "Budapest", "Laufer/Turm", "e2e4:e7e6 - d2d5:d7d6 ")
		
		LOCATE 
	ENDPROC

ENDDEFINE
*****

marK
 
Mark
Thank you for the program.
I think I can learn a lot from this, which helps me with my question.
Transferring captured data in memo fields like in your code could be a good solution.
I hadn't thought about that yet.
If I can do it with that, I'll publish it here too.
Thanks again.


Mike
I really like your reference to special forums for chess.
Thank you very much.
So far I have never known boredom - and now in the Corona crisis
it is not to be feared either, because there are so many interesting forums.
So far, T-T is the best I know.

Keep healthy both

Klaus




Peace worldwide - it starts here...
 
Could I be the first to actually answer your question?

You can locate or seek to the row you want to change and then just need a
Code:
REPLACE M1 with thisform.textbox1.value

And then M1 needs to change which you can do with macro substitution. Perhaps you alternate between row 1 and 2, I don't know how you'd decide which rows belong to a game. Your goal seems to spare as much space as you can by not normalizing the tables, but it makes it hard to actually find rows that match to the current opening. this would be much simpler in the case you store the whole game into one memo. You can't index a full memo, but LEFT(memo,128) and you can seek partial matches "beginning with" what you seek, ideal for finding openings.

You may also spare some bytes not writing down chess notation. Even though often pawn moves only need 2 bytes, your m1,m2,m3 solution needs to be able to store something like Nexf6++, too, so it needs c(7) fields. There is a very simple technical way to store chess moves as start field and end field in binary form you can use chr(0) to chr(63) for this, just 2 bytes per half move or in theory just 12 bits.

But to overcome the 2GB limit of DBFs you could use an SQL Server Express or LocalDB edition. They are royalty free even for commercial use.

Chriss
 
Hi Chris,
thanks for your hints.
To make it clear
For what I want, the capacity of a VFP table is more than enough.
I have 200,000 records with fields M1 through M20 each
filled with a chess-move (= Nexf6 ++) and the table got a size of 170 MB.
Of course you could compress it with CHR ... (thanks for the hint), but I only want to save a maximum of 10 half moves -
and for that it is enough to know your way around a chess opening if you are not a grandmaster.

Code:
CLOSE DATA
LOCAL nmoves AS NUMBER
LOCAL nfld AS INTEGER
LOCAL cfillstring AS STRING
CLEAR ALL
nmoves = 200,000
nfld = 20
cfillstring = "Nexf6 ++"

* CREATE A TABLE "TESTBOARD" WITH 20 CHARACTER-FIELDS (M1 TO M20)
* and fill it with the chess move "Nexf6 ++"
USE TESTBOARD

DELETE ALL
PACK


FOR i = 1 TO nmoves
APPEND BLANK
ENDFOR

FOR i = 1 TO nfld
FNAME = "M" + ALLTRIM (STR (I))
REPLACE ALL & FNAME WITH cfillstring
ENDFOR

BROWSE
* shows 200,000 records filled with fillstring = size about 170 MB

It is also not necessary to describe the move in such a way that you write down e.g. e2 (where the pawn comes from) and then e4 (where it is going) - so most chess books do not write e2-e4 but only e4 (see the following moves in the notation where he was last.)
That also saves a lot of space.


Chris said:
I don't know how you'd decide which rows belong to a game.
That is not needed

When I have gathered information about my own special chess opening,
then I will try to determine by program
that e.g.
record 1: e4 e5 Nf3 Nf6 Bc4 Bc5
record 2: e4 e5 Bc4 Nf6 Bc5 Nf3
is identical - this leads to the same situation on the chessboard.
But then I have to think about it.

Thank you for your help.

Klaus

Peace worldwide - it starts here...
 
Hello Klaus,

I recommend not to use M1-M20 but a memo field for moves

So I would do this like this :
lets think about a table "chess" like this : pk_chess I, year N(4,0), player1 c(50), player2 c(50), pname c(50), pmoves M
add a property odata to form.
Now make a form with text boxes for year, player1/2, pname and an editbox for moves, maybe with the help of add. buttons as shortcuts.
make controlsource of textboxes/editbox according to fields , for example textbox for year : Thisform.odata.year, editbox thisform.odata.pmoves

In load of form :
select chess
scatter memo blank name thisform.odata

in save button :
* get a new pk
select chess
if reccount() = 0
nnewpk = 1
else
select max(pk_chess) from chess into array andummy
nnewpk = nvl(andummy[1],0) + 1
endif
thisform.odata.pk_chess = nnewpk
insert into chess from name thisform.odata

you can also implement an edit function :
search record and then scatter memo name thisform.odata (no blank clause)
and you can have chess in a grid, index it,....
and make input easier : use a tool like autohotkey to define abbreviations for player names (fi blank may becomes Fischer)


hint
There are sites where you can download PGN files, to transfer them into a VFP table should not be not too difficult.
see here :
and tools to convert them to excel (which maybe easier to import)

Best regards
tom
 
Hi klaus,

thanks. I misunderstood what you said:
Klaus said:
My table is sufficient for 20 moves (half moves).
I thought you'd store 20 half moves for each player = 20 moves in total in two records. Also because in all your examples you were given two records. So in fact 1 record is about 1 opening up to move 10.

Code:
FOR i = 1 TO nfld
FNAME = "M" + ALLTRIM (STR (I))
REPLACE ALL & FNAME WITH cfillstring
ENDFOR

You'll not be happy with the result of REPLACE ALL. The ALL scope means you replace the same value into all records of the table. Simply as I said REPLACE or - if you absolutely want to use the scope option REPLACE NEXT 1, that will replace in the current row. Since you don't need to change the row while recording a game you only need to append blank once for the game and then replace the fields one by one. Since you enter one half move at a time you need 20 iterations, but this will not need a loop, these iterations are by the user interaction, you need to store the counter i in some property of the form you count up with each click and make just the replace in that click code, all preparations of appending the new record only need to be done once when the game starts.

So once you have a form counter your code could look like this:
Code:
FNAME = "M" + ALLTRIM (STR(Thisform.halfmovenumber))
REPLACE &FNAME WITH thisform.textbox1.value
Thisform.halfmovenumber = Thisform.halfmovenumber + 1
You'll need to initialize this counter to 1, of course, and need to check when you reach 21 to not accept further half moves. You could also display the half move number in another textbox, though it's obvious from the grid.

I'd only use this kind of interface to enter new openings you don't yet have stored. As you say you already have 200,000 records I wonder how you got there. It's fine but has it anything to do with the question of what code to put into the red "transfer to table" button? You only record one half-move at a time with this form, don't you? And that's a REPLACE of the current field of the same record throughout the same opening.

Mass import would work much simpler, if you already have a CSV file of the moves you could simply APPEND from that file. As others have recommended a memo per game is also what I see as a better fit for the data and then you could quite easily import the portions of PGN files that are the half move notations because it seems to be a standard and I don't know where you'd instead find a game as a comma-separated list of the moves to append to your table.

And the next topic, finding the same or similar records, also is much simpler when the whole opening is just one string instead of 20 strings. To see whether two openings are the same you'd need to compare m1+m2+...+m20 of one record with the same "Sum" of all the fields of another record. If you store an opening in a memo you just compare two memos. The topic of two different openings leading to the same constellation is another topic, that's hard in any case.

Chriss
 
Chris

Chris said:
So in fact 1 record is about 1 opening up to move 10.

That is correct.

Chris said:
You'll not be happy with the result of REPLACE ALL.

My code was only made to find out, what space would be used, when I fill a table with 200,000 records.
Of course, in such a file there would be very different moving strings in each data record.
I don't have such a file yet. It was just to see if the files were getting too big - nothing else.

Your reference to a counter is welcome.
This is how I imagined that the end of an entry could be checked via a counter.
That has to be the case because the sequences can be of different lengths.
In some cases maybe only 5 chess moves, and in others 9 etc.

Chris said:
Mass import would work much simpler, if you already have a CSV file of the moves you could simply APPEND from that file. As others have recommended a memo per game is also what I see as a better fit for the data and then you could quite easily import the portions of PGN files that are the half move notations because it seems to be a standard and I don't know where you'd instead find a game as a comma-separated list of the moves to append to your table.
I agree with you.
When I started my thread here, I initially only thought of entering my own data into the system to create an overview, and that would not have been a lot of data. That's why I only thought of a manual input that runs through the fields of a file, and where each new input should be a sequence of several moves
to an entry in the following data record.

That's why I limited the entries to the first 10 half moves.
This mainly applies to information from chess books or magazines that may are not present in digital sources.

Therefore, I also welcome the fact that the reference to a storage in memo fields would save me the mass work.
So the system could do both:
Pull existing sequences from other sources (e.g. PGN files that are integrated into the VFP file via memo fields - and import from existing digital resources as well.

Chris said:
And the next topic, finding the same or similar records, also is much simpler when the whole opening is just one string instead of 20 strings.
I agree with you on that.

Thank you for your patience.

Klaus




Peace worldwide - it starts here...
 
Tomk3:
In my answer to Chris (above) I stated that I am of course also very interested in the transfer of digital data from the Internet - and I thank you very much for the two links you mentioned.

I am also looking forward to your tips on how to build a form with appropriate memo files.

The link
is very interesting - and a lot of material I have to search in.
However at a first glance I did not find this opening I look for : d4 d5 Nc3 Nf6 Bg5...and more, may be it is hidden there in other variations.

The other link:
a got a warning by Windows 10 Microsoft Defender - I should not download that prog...
means: I hesitate to install that ...

Anyway I appreciate your comment.

Thanks
Klaus






Peace worldwide - it starts here...
 
Hello Klaus,

I added a project "chess".
Pls. take it as a sample for startup.

Doubleclick to edit an entry
Klick "Neu" to enter a new entry
Klick "Löschen" to delete

Its only a startup, so no checking for double entrys, no search (thats easy : drag a _locatebutton from baseclasses _table2 on form)

Because of your name I made form and fieldnames in german :)

Have fun and stay healthy.
Best regards
tom

 
 https://files.engineering.com/getfile.aspx?folder=4f6203de-3764-471d-952c-5ff42471ee53&file=Chess.zip
Hello Tom
Thank you for your help with a start-up program.
Very good job, I will certainly use it for my purpose.
I can also learn a lot of things from looking into the program.
As I wrote before, object-oriented programming is new to me.

It's especially friendly that you even used German terms in the code.[smile]
I guess you already had German at school, right?
I will now try to connect my screen keyboard to your program.
It is significantly faster if you write chess moves with mouse clicks.

See the screenshot at the beginning of this thread.
Thank you again - and if you want to know more about my home country - don't hesitate to ask me.

Thank you again - do you play chess too? It seems like that.
Greetings from Germany

Klaus

Peace worldwide - it starts here...
 
Hello Klaus,

you are welcome.

If you have questions, you can ask them in this thread, I am here in the forum 1-2 times a week.

Buttons
The click of the buttons could do something like that :
Thisform.odata.zuege = Thisform.odata.zuege + this.caption && assuming caption of button = text to insert

Modifications
It is possible to insert the text at cursorposition.
You may think of a button class containing the code above.
And this class can have an own property for the text to be inserted and caption can be different.

General improvements
Player names could come from another table to make sure they are always spelled the same
And some double checking

Best regards
Tom

Moin, moin
I am born and living in Hamburg (the real one in northern germany), so german usually is not a big problem for me :)
VFP and this forums are an international community.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top