You need an active account with a confirmed e-mail address to use the chat board.
| Page 1 of 4 |
|---|
|
Dima Suraev (dvsur) # ========================================== # Function to send F12 and Enter to all windows # ========================================== function Send-TournamentKeys { Write-Host "Sending commands to windows (bottom to top, left to right: F12 -> Enter)..." -ForegroundColor Green $total = $global:processes.Count # Calculate number of rows $rows = [math]::Ceiling($total / $GridColumns) # Iterate from the last row (bottom) to the first (top) for ($r = $rows - 1; $r -ge 0; $r--) { # Inside the row, iterate left to right for ($c = 0; $c -lt $GridColumns; $c++) { # Calculate window index in the array $i = ($r * $GridColumns) + $c # If index exists if ($i -lt $total) { $p = $global:processes[$i] $p.Refresh() if (-not $p.HasExited -and $p.MainWindowHandle -ne [IntPtr]::Zero) { [WinApi]::ShowWindow($p.MainWindowHandle, 9) | Out-Null [WinApi]::SetForegroundWindow($p.MainWindowHandle) | Out-Null Start-Sleep -Milliseconds 300 [System.Windows.Forms.SendKeys]::SendWait("{F12}") Start-Sleep -Milliseconds 500 [System.Windows.Forms.SendKeys]::SendWait("{ENTER}") } } } } } # ========================================== # 3. First launch: Start, Arrange, and Tournaments # ========================================== Start-PiskvorkInstances Arrange-Windows Send-TournamentKeys Restore-ConsoleFocus # Bring console to front and place it in its spot # ========================================== # 4. User input loop # ========================================== while ($true) { Write-Host "" Write-Host "Available commands:" -ForegroundColor Cyan Write-Host " C - CLOSE tournaments (keep script running)" Write-Host " Q - CLOSE tournaments and QUIT" Write-Host " R - RESTART tournaments" Write-Host " N - RESTART tournaments AND delete statistics files" Write-Host " S - SHOW win statistics" $userInput = Read-Host "Enter command" switch ($userInput.ToUpper()) { 'C' { Stop-PiskvorkInstances Write-Host "Tournaments closed." -ForegroundColor Green Restore-ConsoleFocus } 'Q' { Stop-PiskvorkInstances Write-Host "Programs closed. Exiting." -ForegroundColor Green Start-Sleep -Seconds 2 exit } 'R' { Stop-PiskvorkInstances # Close everything before launching Start-PiskvorkInstances Arrange-Windows Send-TournamentKeys Restore-ConsoleFocus } 'N' { Stop-PiskvorkInstances # Close everything before deleting and launching if (Test-Path $StatsFile1) { Remove-Item $StatsFile1 -Force; Write-Host "Deleted: $StatsFile1" -ForegroundColor Yellow } if (Test-Path $StatsFile2) { Remove-Item $StatsFile2 -Force; Write-Host "Deleted: $StatsFile2" -ForegroundColor Yellow } Start-PiskvorkInstances Arrange-Windows Send-TournamentKeys Restore-ConsoleFocus } 'S' { $lines1 = 0 $lines2 = 0 if (Test-Path $StatsFile1) { $lines1 = @(Get-Content $StatsFile1).Count } if (Test-Path $StatsFile2) { $lines2 = @(Get-Content $StatsFile2).Count } $diff = [math]::Abs($lines1 - $lines2) $totalGames = $lines1 + $lines2 $pct1 = 0 $pct2 = 0 $confidence = 0 # Calculate percentages and confidence if ($totalGames -gt 0) { $pct1 = [math]::Round(($lines1 / $totalGames) * 100, 2) $pct2 = [math]::Round(($lines2 / $totalGames) * 100, 2) # Mathematical calculation of confidence $zSquared = ($diff * $diff) / $totalGames $exponent = - (2 / [math]::Pi) * $zSquared $cVal = [math]::Sqrt(1 - [math]::Exp($exponent)) $confidence = [math]::Round($cVal * 100, 2) } Write-Host "" # Row 1: Headers $headerStr = "{0,-7} | {1,-7} | {2,-8}" -f "OLE1", "OLE2", "Diff" Write-Host $headerStr -ForegroundColor White # Row 2: Win count $scoreStr = "{0,-7} | {1,-7} | {2,-8}" -f $lines1, $lines2, $diff Write-Host $scoreStr -ForegroundColor White # Row 3: Win percentages and confidence in 3rd column $pctStr = "{0,-7} | {1,-7} | {2,-8}" -f "$pct1%", "$pct2%", "$confidence%" Write-Host $pctStr -ForegroundColor Cyan Write-Host "" # Result evaluation based on confidence if ($totalGames -eq 0) { Write-Host "No data to analyze." -ForegroundColor DarkGray } elseif ($lines1 -gt $lines2) { if ($confidence -ge 95) { Write-Host "OLE1 IS SIGNIFICANTLY STRONGER (Confidence >95%)" -ForegroundColor Green } else { Write-Host "OLE1 is leading (Low confidence: possible margin of error)" -ForegroundColor Yellow } } elseif ($lines2 -gt $lines1) { if ($confidence -ge 95) { Write-Host "OLE2 IS SIGNIFICANTLY STRONGER (Confidence >95%)" -ForegroundColor Green } else { Write-Host "OLE2 is leading (Low confidence: possible margin of error)" -ForegroundColor Yellow } } else { Write-Host "Draw (Absolute tie)" -ForegroundColor DarkGray } Write-Host "" } Default { Write-Host "Invalid input. Please enter one of the suggested letters." -ForegroundColor Red } } } |
|
Dima Suraev (dvsur) [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 <# ========================================================================================= CONFIGURATION GUIDE ========================================================================================= 1. CPU THREADS & INSTANCES ($TotalInstances) - How to set: This number should be based on your CPU's logical cores (threads). - Recommendation: It is best to leave 1 or 2 threads free for the Operating System and PowerShell script to run smoothly without system freezes. - Example: If you have an 8-core / 16-thread CPU, set $TotalInstances to 14 or 15. - Example: If you have a 6-core / 12-thread CPU, set $TotalInstances to 10 or 11. 2. SCREEN RESOLUTION & GRID LAYOUT ($GridColumns, $StepX, $StepY) - The script arranges windows in a grid. - Total Width used = $GridColumns * $StepX - Total Height used = (Total Rows) * $StepY - How to set for 1920x1080 (FullHD): If window width ($StepX) is ~370px, max columns = 1920 / 370 = 5. If you set $GridColumns to 5, and $TotalInstances to 15, it will make 3 rows. Max height is 1080. 3 rows * 395px = 1185px (Slightly larger than FullHD height, windows will overlap the taskbar or go slightly off-screen unless you adjust $StepY). - How to set for 2560x1440 (2K): $GridColumns = 6 is perfectly fine (6 * 370 = 2220px width). 3 rows * 395px = 1185px height (Fits comfortably inside 1440px). 3. CONSOLE POSITIONING ($ConsoleGridCol, $ConsoleGridRow) - This determines where the PowerShell terminal window will be placed over the grid. - It is calculated using the same grid cells. - Note: Columns and Rows are 0-indexed (0 is the first column/row). - For example: Col 3, Row 2 means it will be placed in the 4th column of the 3rd row. ========================================================================================= #> # ========================================== # CONFIGURATION # ========================================== # --- Process / CPU Settings --- # Total number of Piskvork tournament instances to run. $TotalInstances = 15 # --- Window Grid Settings --- # Number of windows per horizontal row. $GridColumns = 6 # Starting coordinates for the very first window (Top-Left corner). $StartX = 0 $StartY = -50 # The width ($StepX) and height ($StepY) of each Piskvork window. # Change these if you resize the Piskvork windows or use a different resolution. $StepX = 370 $StepY = 395 # --- Console (Terminal) Window Settings --- # Dimensions of the PowerShell Terminal window. $ConsoleWidth = 1347 $ConsoleHeight = 403 # Which cell in the grid the Console should snap to (0-indexed). $ConsoleGridCol = 3 $ConsoleGridRow = 2 # Fine-tuning pixel offsets to perfectly align the Console window. $ConsoleOffsetX = -4 $ConsoleOffsetY = 70 # --- File Paths --- # Use {0} as a placeholder for the instance number (1, 2, 3...) $PiskvorkBasePath = "C:\Project\gomocup.org\gomocup{0}.org\piskvork.exe" $StatsFile1 = "C:\Project\Phaser\5_in_row\5inRow\cocos-project2\cpp\1\_Win_pbrain-ole1.txt" $StatsFile2 = "C:\Project\Phaser\5_in_row\5inRow\cocos-project2\cpp\1\_Win_pbrain-ole2.txt" # ========================================== # END OF CONFIGURATION # ========================================== # Import WinAPI with advanced window search Add-Type @" using System; using System.Runtime.InteropServices; using System.Text; public class WinApi { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll", SetLastError = true)] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); [DllImport("user32.dll", SetLastError = true)] public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); // Functions to enumerate all windows and search by partial title public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); [DllImport("user32.dll")] public static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount); [DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd); public static IntPtr FindConsoleWindowByTitle(string substring) { IntPtr found = IntPtr.Zero; EnumWindows((hWnd, lParam) => { if (IsWindowVisible(hWnd)) { StringBuilder sb = new StringBuilder(256); GetWindowText(hWnd, sb, 256); if (sb.ToString().Contains(substring)) { found = hWnd; return false; // Stop searching, window found } } return true; }, IntPtr.Zero); return found; } } "@ # Import class for sending keystrokes [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null # ========================================== # 1. Delete old logs/statistics on startup # ========================================== if (Test-Path $StatsFile1) { Remove-Item $StatsFile1 -Force; Write-Host "Deleted: $StatsFile1" -ForegroundColor Yellow } if (Test-Path $StatsFile2) { Remove-Item $StatsFile2 -Force; Write-Host "Deleted: $StatsFile2" -ForegroundColor Yellow } # Global array to store processes $global:processes = @() # ========================================== # 2. Process management functions # ========================================== function Stop-PiskvorkInstances { if ($global:processes.Count -gt 0) { Write-Host "Closing existing Piskvork processes..." -ForegroundColor Yellow foreach ($p in $global:processes) { if ($null -ne $p -and -not $p.HasExited) { $p.Kill() } } Start-Sleep -Seconds 1 # Short pause to allow OS to release files/resources $global:processes = @() # Clear the array } } function Start-PiskvorkInstances { $alive = $false if ($global:processes) { foreach ($p in $global:processes) { if (-not $p.HasExited) { $alive = $true; break } } } # Start only if there are no alive processes if (-not $alive) { Write-Host "Launching $($TotalInstances) instances of Piskvork..." -ForegroundColor Cyan $global:processes = @() for ($i = 1; $i -le $TotalInstances; $i++) { $path = $PiskvorkBasePath -f $i if (Test-Path $path) { $proc = Start-Process -FilePath $path -PassThru $global:processes += $proc } else { Write-Host "File not found: $path" -ForegroundColor Red } } Write-Host "Waiting for windows to load..." -ForegroundColor Cyan Start-Sleep -Seconds 3 } } # ========================================== # Function to return focus to the script and resize (Win11 Terminal FIX) # ========================================== function Restore-ConsoleFocus { # 1. Remember current title and set a unique ID $originalTitle = [Console]::Title $uniqueGuid = [guid]::NewGuid().ToString() [Console]::Title = $uniqueGuid # Give Windows Terminal time to update the title (important for Win11) Start-Sleep -Milliseconds 400 # 2. Search window by partial title (bypasses the "Windows PowerShell" suffix) $hwnd = [WinApi]::FindConsoleWindowByTitle($uniqueGuid) # 3. Restore original title [Console]::Title = $originalTitle if ($hwnd -ne [IntPtr]::Zero) { # Calculate position based on constants $posX = $StartX + ($ConsoleGridCol * $StepX) + $ConsoleOffsetX $posY = $StartY + ($ConsoleGridRow * $StepY) + $ConsoleOffsetY # Restore window [WinApi]::ShowWindow($hwnd, 9) | Out-Null # Hard-set window position and size [WinApi]::MoveWindow($hwnd, $posX, $posY, $ConsoleWidth, $ConsoleHeight, $true) | Out-Null # Make window always on top [WinApi]::SetWindowPos($hwnd, [IntPtr](-1), 0, 0, 0, 0, 3) | Out-Null [WinApi]::SetWindowPos($hwnd, [IntPtr](-2), 0, 0, 0, 0, 3) | Out-Null # Focus [WinApi]::SetForegroundWindow($hwnd) | Out-Null } else { Write-Host "Failed to capture the console (Terminal) window!" -ForegroundColor Red } } # ========================================== # Function to arrange windows in a grid # ========================================== function Arrange-Windows { Write-Host "Arranging windows..." -ForegroundColor Cyan $uFlags = 0x0001 -bor 0x0004 for ($i = 0; $i -lt $global:processes.Count; $i++) { $p = $global:processes[$i] $p.Refresh() if (-not $p.HasExited -and $p.MainWindowHandle -ne [IntPtr]::Zero) { $col = $i % $GridColumns $row = [math]::Floor($i / $GridColumns) $posX = $StartX + ($col * $StepX) $posY = $StartY + ($row * $StepY) [WinApi]::SetWindowPos($p.MainWindowHandle, [IntPtr]::Zero, $posX, $posY, 0, 0, $uFlags) | Out-Null } } Start-Sleep -Milliseconds 500 } # ========================================== # Function to send F12 and Enter to all windows # ========================================== function Send-TournamentKeys { Write-Host "Sending commands to windows (bottom to top, left to right: F12 -> Enter)..." -ForegroundColor Green $total = $global:processes.Count # Calculate number of rows $rows = [math]::Ceiling($total / $GridColumns) # Iterate from the last row (bottom) to the first (top) for ($r = $rows - 1; |
|
Dima Suraev (dvsur) Here is a brief summary of the dependencies and prerequisites in English. **No external libraries (like NuGet, npm, or pip) are required.** The script uses built-in Windows APIs and .NET features. However, you need to ensure the following system and environment setups: * **OS Environment:** Windows 10 or 11 (the script relies on the Windows-specific `user32.dll` and built-in .NET Framework). * **Execution Policy:** Windows blocks local scripts by default. You must open PowerShell as Administrator and run: `Set-ExecutionPolicy RemoteSigned` * **Folder Structure:** The directories for your Piskvork instances (`$PiskvorkBasePath`) and the log/stats folders must actually exist on your hard drive. The script does not create folders, it only reads/deletes files inside them. * **Pre-configured Piskvork:** You must manually open each Piskvork instance once, set up the tournament (choose bots, board size, time limits), and close it to save the settings. The script only sends `F12` and `Enter` to start the tournament; it cannot configure the UI. * **Admin Privileges (Recommended):** Run the script in a PowerShell terminal opened as **Administrator**. Otherwise, Windows might block the simulated keystrokes (`SendKeys`) sent to the Piskvork windows. |
|
Dima Suraev (dvsur) I learned about this competition only a month before it started, even though it has existed for several years — that was a big miss on my part. Previously, I participated in the Russian AI Cup and reached the final games among thousands of participants. Competitions like this are a real outlet for me from all the harsh things happening in the world. In one month, I managed to write a bot that ended up exactly at the ranking position I had predicted. However, I made mistakes both in implementing my ideas and in meeting the contest requirements regarding program dependencies on installed DLLs. The organizers fixed my DLL-dependency issues so that I could participate in this wonderful competition, and I’m very grateful to them. Now I want to give something back to this contest community. This is a script that launches multiple instances of Piskvork and collects statistics that engines write into special files when they win (your engines will need a small modification to support this). In the next post, I will describe the script’s requirements. |
|
Dima Suraev (dvsur) Hey there! First off — please don't disqualify yourself just yet! Yes, the deadline confusion is frustrating (UTC vs. local time gets the best of us), but your passion and effort still count for a lot. I actually only found out about this competition a few weeks before submissions closed, and I went all out in that final stretch — late nights, lots of caffeine, and pushing through to get something I was proud of submitted. I even downloaded other participants' engines and ran local tournaments on my own machine to test and prepare, which was honestly half the fun! If the official deadline has technically passed, I'd still encourage you to reach out to the organizers — explain the timezone mix-up. These communities are often more understanding than you'd expect, especially when they see genuine effort and enthusiasm. And even if the official window has closed, the local tournament scene is alive and well — you've already got the setup to keep competing, learning, and iterating. The fact that you built something, tested it against other engines, and submitted it shows real dedication. That effort doesn't disappear because of a four-hour technicality. Hold your head up — you're already part of the community just by showing up and shipping something. |
|
Konstantin Gredeskoul (kig) Hey. This is my first time participating and I don't notice the UTC on the deadline and submitted it at 8pm San Francisco time, which is 4 hrs after May 29 in UTC. Does that mean I am automatically disqualified? |
|
shunyi sui (suishunyi) If there is any problem with my pbrain that prevents you from participating in the competition, please contact me immediately by phone: +86 13601946763 |
|
shunyi sui (suishunyi) Hi everyone, it had been a long long time since my last time attending the Gomocup competition. the last time was DDQK-Conquer 1.0 when i was in junor school(7grade) that during the pedemic era i coded the AI and submit. Now i have already been a high school students so i want to have an improve. I hope that my AI preform well in the competition I will play fastgame and standard. see you guys in the court |
|
Tianyi Hao (wind23) Thank you, Petr! |
|
Petr Laštovička (pela) Piskvork 9.0 has been released. It supports freestyle Caro (INFO rule 8) and standard Caro (INFO rule 9). You can run a tournament on your own computer to test your AI. You can download it from https://sourceforge.net/projects/piskvork/ or get the C++ source code from https://github.com/plastovicka/Piskvork |
|
shunyi sui (suishunyi) Hello everyone It is my first time to attent this competition Also, because i am not a English speaker. Please be torrent for my gramma error and phraseology. |
|
Thang Nguyen Van (iwannabetheguy) Hi everyone ! I've started a project for a gomoku AI and I have some problem about my evaluation function. I have a question that how can I implementation a simplest a evaluation function. Thank you so much ! |
|
Maciej Kozarzewski (maciek) I've recently started working on something similar, but just forked GomocupJudge and created a version that can run 1vs1 engine tournaments locally - https://github.com/MaciejKozarzewski/GomocupJudgeLocal/tree/master/local_launcher |
|
Haobin Duan (riki) Hi all engine developers! I would like to introduce a great CLI tool for running large-scale engine tournaments: c-gomoku-cli (https://github.com/nkg114mc/c-gomoku-cli) authored by Chao Ma and me. This project was originally inspired by c-chess-cli. It has a lot of useful features such as gauntlet tournament, concurrency games, game sampling and more. All three rules(freestyle, standard, renju) are supported. Since this is still a relatively new project, we would like to hear any useful feedback from you, and PR is welcomed as well. |
|
Olga Gromova (shaurma) I HAVE SOLVED THE PROBLEM - I ASK FOR FORGIVENESS TO THE TOURNAMENT ORGANIZERS AND ENGINE DEVELOPERS. "Barbican" and "AlfaGomoku" did not start for me because the path to the file (engine) contained Cyrillic (it was in Russian). I'm from Russia :) The engines started working as soon as I changed the folder names to English |
|
Olga Gromova (shaurma) AlphaGomoku 21 also (not only BARBAKAN) does not start, it gives an error. But AG 20 (last year) is working. Maybe they put something wrong for the download ... Why does AG 21 give an error at startup? |
|
Olga Gromova (shaurma) What's the difference between "pbrain-barbakan" and "pbrain-barbakan_avx2" in archive follder? what should i use - "pbrain-barbakan" or "pbrain-barbakan_avx2"? |
|
Paul Dwyer (paulfdwyer) I think the submission form needs some work. Word of warning to people using it: if you have a couple of errors in your entry (version has a some char that it doesn't like etc) then it will only tell you about the first error it hits and then if you click "back" you text data is all gone. Write long text fields into notepad first and copy paste them to the form so you don't have to type them again and again when you tread on each error. Then you are all good! :) |
|
Yuliang Sun (pentazen) https://github.com/sun-yuliang/PentaZen/releases/tag/v0.4.18. Send the link here for ensurance... |
|
Yuliang Sun (pentazen) The one hour submission limitation was not expected.. |