Lua script for splitting Cutechess log files

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
Roland Chastain
Posts: 745
Joined: Sat Jun 08, 2013 10:07 am
Location: France
Full name: Roland Chastain

Lua script for splitting Cutechess log files

Post by Roland Chastain »

I needed a tool to split Cutechess log files, so I made this Lua script. Maybe someone will find it useful.

What I call Cutechess log file is what I get when I run this kind of command:

Code: Select all

$HOME/Documents/echecs/sources/cutechess/1_5_1/build/cutechess-cli \
-rounds 2 \
-tournament gauntlet \
-engine conf="Fimbulwinter 260913" \
-engine conf="Zoe 0.4" \
-engine conf="miniMardi 1.3" \
-engine conf="OliveChess 0.3.3" \
-engine name="Alouette 0.1.9" cmd="./alouette" dir="/home/roland/Documents/pascal/echecs/alouette/git" proto="uci" \
-each tc=40/30 option.Threads=1 \
-openings file=$BOOK plies=4 order=random \
-debug all \
-pgnout tournoi.pgn \
-wait 500 2>> tournoi.err | tee tournoi.log
The script is a bit slow and can look a bit complicated because it deals with the case of lines arriving late, like this:

Code: Select all

Finished game 2 (Fimbulwinter 260913 vs miniMardi 1.3): 1/2-1/2 {Draw by fifty moves rule}
265554 >Fimbulwinter 260913(4): xboard
265554 >Fimbulwinter 260913(4): protover 2
265554 >OliveChess 0.3.3(5): uci
265554 >miniMardi 1.3(3): quit <-- This line belongs to the previous game
It creates a file for each game. For now the files are named game1.log, game2.log...

Usage: lua split-cutechess-log.lua LOGFILE_NAME

Code: Select all

--[[
  split-cutechess-log.lua
  Usage: lua split-cutechess-log.lua LOGFILE_NAME
  Creates game1.log, game2.log...
--]]

local newfile = nil
local oldfile = nil
local fcp_num

for line in io.lines((#arg > 0) and arg[1] or 'tournoi.log') do
  
  -- 27 >Fimbulwinter 5.05(0): xboard
  -- 28 >Zoe 0.4(1): xboard
  -- 28807 >Fimbulwinter 5.05(2): xboard
  local cp_num = string.match(line, '%d+ >.-%((%d+)%): ([xu][bc][oi]a?r?d?)$')
  
  if cp_num then -- protocol line
    if tonumber(cp_num) % 2 == 0 then -- protocol line for first engine => beginning of a game
      fcp_num = tonumber(cp_num)
      
      if newfile ~= nil then
        newfile:close()
      end
      newfile = io.open(string.format('game%d.log', fcp_num / 2 + 1), 'w')
      
      if fcp_num >= 2 then
        if oldfile ~= nil then
          oldfile:close()
        end
        oldfile = io.open(string.format('game%d.log', fcp_num / 2), 'a')
        -- open the previous file in append mode, in case a line belonging
        -- to the previous game arrives late
      end
    end
  end
  
  if newfile == nil then
    print('[IGNORED]' .. line)
  else
    cp_num = string.match(line, '%d+ [><].-%((%d+)%): ')
    if cp_num and tonumber(cp_num) < fcp_num then
      oldfile:write(line .. '\n')
    else
      newfile:write(line .. '\n')
    end
  end
end

newfile:close()
oldfile:close()
Qui trop embrasse mal étreint.

Author of Eschecs, a simple UCI chess GUI written in Pascal.