Jump to content

Advice on using numbers as variables...


Recommended Posts

I’m creating a front-end for the LC0 chess engine via the UCI protocol*.
To model the board I am using a simple 2-d 8x8 array.  But I am using Enums with number named identifiers, to make the array correspond with the standard algebraic notation used in chess.

tldr; 

Are there any reasons NOT to do the following;

Local Enum $a, $b, $c, $d, $e, $f, $g, $h
Local Enum $8, $7, $6, $5, $4, $3, $2, $1
Local $board[8][8]

$board[$a][$1]="rook"

*ICYWW, game creation, not game automation.

Code hard, but don’t hard code...

Link to comment
Share on other sites

You can test this for yourself by adding an _ArrayDisplay() debug statement. You will see that while it works, because the array is zero based your rook ends up at  7, 0 which may not be what you want.

#include <Array.au3>

Local Enum $a, $b, $c, $d, $e, $f, $g, $h
Local Enum $8, $7, $6, $5, $4, $3, $2, $1
Local $board[8][8]

$board[$a][$1]="rook"

_ArrayDisplay($board)

 

Phil Seakins

Link to comment
Share on other sites

4 minutes ago, pseakins said:

because the array is zero based your rook ends up at  7, 0 which may not be what you want.

Do you mean 0,7? It should be at 0,7.

0,7 in the array corresponds to chess notation a1 (when the player is playing the white pieces,)

 

 

Code hard, but don’t hard code...

Link to comment
Share on other sites

22 minutes ago, pseakins said:

Did you try running the code for yourself?

Yes, I am already using the array.  I know that it works as far as that is concerned.

What I am worried about is some unintended consequence using integers as identifiers for other integers.

I come from a C/Java background, and since there is no $ token to distinguish variables from literals, it’s not even an option there.

That said I haven’t come across anyone doing it in autoit yet.  Probably cuz there wasn’t a good enough reason.

Code hard, but don’t hard code...

Link to comment
Share on other sites

I don't think there is any issue doing that, but I would recommend making the variable name a little more meaningful.  

For your purposes, you know what they mean, so do as you wish; but if it were me, I might do something like this.

 

#include <Array.au3>

Local Enum $eColA, $eColB, $eColC, $eColD, $eColE, $eColF, $eColG, $eColH, $eColSize
Local Enum $eRow8, $eRow7, $eRow6, $eRow5, $eRow4, $eRow3, $eRow2, $eRow1, $eRowSize
Local $aBoard[$eColSize][$eRowSize]

$aBoard[$eRow1][$eColA]="rook"

_ArrayDisplay($aBoard)

 

You'll notice a few small changes; 

  1. Added a prefix to each variable (following best coding practices formats) to make the variable names more meaningful to coders.
  2. Added 9th variable at the end of the Enum statements to simplify the array defining.
  3. Changed Row and Col dimensions of the array, which is is what @pseakins was trying to illustrate (totally optional since array is a square as long as you are consistent with which dimension is which--but if you ever need or want to use _ArrayDisplay to view the contents, swapping them as I did makes ArrayDisplay represent the "real" board, better.

 

Link to comment
Share on other sites

2 hours ago, spudw2k said:

I don't think there is any issue doing that, but I would recommend making the variable name a little more meaningful. 

Thanks for your suggestions, they are very reasonable and understandable :)

However, I think perhaps I could have done better explaining what I was trying to achieve initially.

Right off, let me state that if I were a contract programmer working on this project for hire, and knew little about chess, there would be no need for any of this, a straight 0-7 2d array is totally clear.

The thing is that I am an experienced player as well.  Every square has a name, and I “know” where they all are without even looking at a board.  I know that a knight on b1 can get to the other side of the board via c3 d5 f6 and e8 as quickly as I could type it.

1F0E580F-E7E6-4C4A-89C3-90783EAF5261.gif.e9f5a0033be40e96c9fcbf02ffae0504.gif

So, in chess notation, the column (or file) comes first, followed by the row (or rank).

Therefore, it is the whole point of the exercise to end up where I can simply refer to a square as $board[$b][$6] and have it do the translation to 1,2.  
In other words, b6 has meaning to me, 1,2 not so much.  In fact it took me several seconds just to translate it and confirm it right now.

I was mostly worried about potential technical problems; the caveat about _ArrayDisplay is a good example of that.

Thanks!

 

 

Code hard, but don’t hard code...

Link to comment
Share on other sites

You could use Maps (latest Beta version of Autoit is needed) to do things like this:

Global $mBoard[]
$mBoard["b1"] = "King"
MsgBox(0, "", $mBoard.b1)

 

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

1 hour ago, JockoDundee said:

the whole point of the exercise to end up where I can simply refer to a square as $board[$b][$6]

There's nothing wrong with this notation (variable naming) if you are happy with it and it's clearer in your mind. As @spudw2k pointed out, the AutoIt  community has guidelines for variable and function naming but there is no need to adhere to them, particularly if it makes coding more difficult for you. Thanks for your clarification @spudw2k.

I don't know anything about the Maps feature that @water refers to but it looks like it may be very useful.

Phil Seakins

Link to comment
Share on other sites

My 2 Cents:
you could also create a small function to convert "chess notation" to "array coordinates" for the 8x8 array.
in this small example script I wrote:
the _ConvertCoords() function which accepts a chess notation and returns a 2-element array with the corresponding row and column coordinates for the 8x8 array
the _BoardSet() and _BoardGet() functions to show how you can use it.
The _Example() function uses the 3 functions above to initialize the 'chessboard' (the array) at the starting position. Just for fun I used Unicode symbols (for black chess) but of course you can insert whatever string is more appropriate into the array

#include <Array.au3> ; For _ArrayDisplay()
#include <StringConstants.au3>
Global $board[8][8]
Global Enum $iRow, $iCol ; 0, 1
Global Enum $iFile, $iRank
Global $WhiteChess = ObjCreate("Scripting.Dictionary")
$WhiteChess.add('King', ChrW(9812))
$WhiteChess.add('Queen', ChrW(9813))
$WhiteChess.add('Rook', ChrW(9814))
$WhiteChess.add('Bishop', ChrW(9815))
$WhiteChess.add('Knight', ChrW(9816))
$WhiteChess.add('Pawn', ChrW(9817))
Global $BlackChess = ObjCreate("Scripting.Dictionary")
$BlackChess.add('King', ChrW(9818))
$BlackChess.add('Queen', ChrW(9819))
$BlackChess.add('Rook', ChrW(9820))
$BlackChess.add('Bishop', ChrW(9821))
$BlackChess.add('Knight', ChrW(9822))
$BlackChess.add('Pawn', ChrW(9823))

_Example()

Func _Example()
    _BoardSet('a8', $BlackChess.item('Rook'))
    _BoardSet('b8', $BlackChess.item('Knight'))
    _BoardSet('c8', $BlackChess.item('Bishop'))
    _BoardSet('d8', $BlackChess.item('Queen'))
    _BoardSet('e8', $BlackChess.item('King'))
    _BoardSet('f8', $BlackChess.item('Bishop'))
    _BoardSet('g8', $BlackChess.item('Knight'))
    _BoardSet('h8', $BlackChess.item('Rook'))
    _BoardSet('a7', $BlackChess.item('Pawn'))
    _BoardSet('b7', $BlackChess.item('Pawn'))
    _BoardSet('c7', $BlackChess.item('Pawn'))
    _BoardSet('d7', $BlackChess.item('Pawn'))
    _BoardSet('e7', $BlackChess.item('Pawn'))
    _BoardSet('f7', $BlackChess.item('Pawn'))
    _BoardSet('g7', $BlackChess.item('Pawn'))
    _BoardSet('h7', $BlackChess.item('Pawn'))

    _BoardSet('a2', 'Pawn') ; $WhiteChess.item('Pawn'))
    _BoardSet('b2', 'Pawn') ; $WhiteChess.item('Pawn'))
    _BoardSet('c2', 'Pawn') ; $WhiteChess.item('Pawn'))
    _BoardSet('d2', 'Pawn') ; $WhiteChess.item('Pawn'))
    _BoardSet('e2', 'Pawn') ; $WhiteChess.item('Pawn'))
    _BoardSet('f2', 'Pawn') ; $WhiteChess.item('Pawn'))
    _BoardSet('g2', 'Pawn') ; $WhiteChess.item('Pawn'))
    _BoardSet('h2', 'Pawn') ; $WhiteChess.item('Pawn'))
    _BoardSet('a1', 'Rook') ;  $WhiteChess.item('Rook'))
    _BoardSet('b1', 'Knight') ; $WhiteChess.item('Knight'))
    _BoardSet('c1', 'Bishop') ; $WhiteChess.item('Bishop'))
    _BoardSet('d1', 'Queen') ;  $WhiteChess.item('Queen'))
    _BoardSet('e1', 'King') ;   $WhiteChess.item('King'))
    _BoardSet('f1', 'Bishop') ; $WhiteChess.item('Bishop'))
    _BoardSet('g1', 'Knight') ; $WhiteChess.item('Knight'))
    _BoardSet('h1', 'Rook') ;   $WhiteChess.item('Rook'))

    _ArrayDisplay($board)
    MsgBox(0, 'a1', "in a1 there is: " & _BoardGet('a1'))
EndFunc   ;==>_Example

; set a 'piece' on the board
; --------------------------
Func _BoardSet($sSquare, $vPiece)
    Local $xy = _ConvertCoords($sSquare)
    $board[$xy[$iRow]][$xy[$iCol]] = $vPiece
EndFunc   ;==>_BoardSet

; get the content of a square
; ---------------------------
Func _BoardGet($sSquare)
    Local $xy = _ConvertCoords($sSquare)
    Return $board[$xy[$iRow]][$xy[$iCol]]
EndFunc   ;==>_BoardGet

; convert chess notation to Array coordinates
; ===========================================
Func _ConvertCoords($sSquare)
    Local $aTemp = StringSplit($sSquare, "", $STR_NOCOUNT)
    Local $aRowCol[2]
    $aRowCol[$iCol] = StringInStr("abcdefgh", $aTemp[$iFile]) - 1
    $aRowCol[$iRow] = 8 - Number($aTemp[$iRank])
    Return $aRowCol
EndFunc   ;==>_ConvertCoords

 

Edited by Chimp

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

10 hours ago, Chimp said:

The _Example() function uses the 3 functions above to initialize the 'chessboard' (the array) at the starting position. Just for fun I used Unicode symbols (for black chess) but of course you can insert whatever string is more appropriate into the array

Nice.

Typically, when specifying chess positions, (as opposed to moves), the convention is to use majuscule letters for white and minuscule for black, code wise you can take a white Bishop and make it black by:

Chr(Asc(“B”)+32)

Similarly, for the file to column conversion I have done something like: (not tested)

$aRowCol[$iCol] = Int(Chr(Asc($aTemp[$iFile])-48))

But that’s nowhere near as clever as:

$aRowCol[$iCol] = StringInStr("abcdefgh", $aTemp[$iFile]) - 1

:)

Code hard, but don’t hard code...

Link to comment
Share on other sites

Fwiw, another example of unintended consequences of remapping Enums to Integer identifiers just came up...

so we had:

Local Enum $a, $b, $c, $d, $e, $f, $g, $h
Local Enum $8, $7, $6, $5, $4, $3, $2, $1
Local $board[8][8]

Now, when I try to use something normal like:

For $rank = $1 To $8

it doesn’t work because $1 > $8.

Of course there’s always:

Local Enum $One=-1
For $rank = $1 To $8 Step $One

but maybe things are getting out of hand here...

Code hard, but don’t hard code...

Link to comment
Share on other sites

8 hours ago, JockoDundee said:

maybe things are getting out of hand here...

I think so... maybe just use some comments?

This reminds of defining things in C to be other pre-defined things. We're going to need a script to translate your code into "real code" pretty soon :D

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

To each their own I suppose, but don't ask me to read your code! :o

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

<Snip>

Edited by seadoggie01
Slow internet? Double posted

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

1 hour ago, seadoggie01 said:

To each their own I suppose, but don't ask me to read your code! :o

If the programmer chooses descriptive function and variable names, and wraps magic numbers,  even uncommented code can be easily read by strangers  🤓

Func _Acro_DocDisplay($oPdDoc, $sTitle = Default, $iPage = Default)

    If IsKeyword($sTitle) Then $sTitle = ""

    If Not __Acro_ObjCheck($oPdDoc, "PDDoc") Then Return SetError(1, 0, False)
    Local $oAvDoc = $oPdDoc.OpenAVDoc($sTitle)
    If Not __Acro_ObjCheck($oAvDoc, "AVDoc") Then Return SetError(2, 0, False)
    If Not IsKeyword($iPage) Then
        Local $oPageView = $oAvDoc.GetAVPageView
        If Not __Acro_ObjCheck($oPageView, "AVPageView") Then Return SetError(3, 0, False)
        If Not ($oPageView.GoTo($iPage) = -1) Then Return SetError(4, 0, False)
    EndIf

    Return $oAvDoc

EndFunc   ;==>_Acro_DocDisplay

 

Code hard, but don’t hard code...

Link to comment
Share on other sites

Sure, it can be. But honestly, I wish I'd added more comments when writing that UDF as I seem to edit it every week.

You're asking for advice here, so this is mine: use comments instead of variables. I'd rather read an explanation of why a For loop is walking backwards instead of trying to figure out if $One equaling -1 is an error and why there are variables with numbers for names. I think that Chimp's code shows a great workaround for avoiding this entire issue and that would be my personal preference.

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

2 hours ago, seadoggie01 said:

You're asking for advice here, so this is mine: use comments instead of variables.

Fair enough.  

2 hours ago, seadoggie01 said:

I think that Chimp's code shows a great workaround for avoiding this entire issue and that would be my personal preference.

I think that Chimp’s code is good as well, as I have already indicated.

Originally, I considered using maps, but was concerned about the overhead involved.  
Not to add ex post facto requirements as a justification for my decision, but when you doing chess interfaces, a large portion of the code is looping up files and over ranks and doing compares etc. So performance has to be considered.

Basically, things like

For $row = 0 To 7
   For $col = 0 To 7
   
   If $board[$row][$col] = ...
  
  Next
Next

Chimp’s code requires multiple String library calls per usage.  So I was looking to maintain the performance of direct array access with more intuitive semantics.

I have amended my code thusly:

; These enums allow access to the zero-based board array thru the use of standard
; algebraic notation, such that $board[$h][$1] = $board[7][7]

Local Enum $a, $b, $c, $d, $e, $f, $g, $h
Local Enum $8, $7, $6, $5, $4, $3, $2, $1
Local $board[8][8]

 

2 hours ago, seadoggie01 said:

I wish I'd added more comments when writing that UDF as I seem to edit it every week.

Ok, granted.  But you don’t see any value in using descriptive constants for the return codes, for instance?

Return SetError(2, 0, False)

 

Code hard, but don’t hard code...

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...