Morpion solitaire/Unicon

From Rosetta Code
Revision as of 14:41, 8 February 2012 by rosettacode>Dgamey (word smithing)

This example goes beyond the task goal of playing a random game of Morpion solitaire. The program was designed as a first cut/test bed more for understanding and explore the problem space rather than for high efficiency. The program is structured to allow its behaviour to be configured (see options and M_ vars). Some of the features and extensions include:

  • Playing a single games or running multigame simulations to find and capture the best games
  • Producing re-loadable game records and the ability to replay a saved game from a given position forward
  • The ability to reproduce purely random games from the random number seed
  • Limiting the initial random moves to 1 of 4 cases (inside corners, outside corners (2 types), outside valley) not 1 of 28
  • Plugable modules for functions including applying player strategy, position evaluation (fitness/heuristics)to facilitate quick experimentation

Using random play in many summary runs, the highest score achieved was 90. While it was fairly easy to push random games into the low 80's running simulations of as little as a few hundred games, going beyond the highest score without adding some smarts will require some very long runs and is unlikely to result in any significant progress. Observing multigame runs show that play advances fairly quickly before a progress grinds to a virtual halt. Many runs peak in the first few hundred or thousand games.

The ability to replay recorded games provides a way to study the behaviour of the problem. Selecting successful random games, truncating them and running multigame simulations using a successful base shows that the seeds of success are sown early. It was possible to better good random game scores (mid 80s) pushing the new scores up into the mid 90s. Unfortunately this technique when applied to Chris Rosin's 177 move record game did not produce any new records  :(. Surprisingly however, it was possible to produce games in the high 160's! using random play with a truncated (60%) version of this game.

The observation that a game becomes bad or good fairly early suggests that finding an intelligent forward looking position fitness evaluator is going to be a challenge to say the least.

It's also possible to capture bad games. This might provide some kind of comparison against good games when considering fitness evaluators. Or not.

Internally, the grid is automatically expanded as needed whenever a cell is played on an outer edge. When this happens only the affected side is expanded. As a side effect the grid numbering will seem unusual. The game log shows all row/col coordinates relative to the 1,1 origin located at the intersection of the lines containing top and left most edges of the cross. A fixed grid might be more efficient. With the ability to detect an off page condition and save and replay the game later this could be easier to deal with. The issue of grid origin comes up all the time when working with the code.

For an example of a loadable and re-playable game see Chris Rosin's 177 move 5T previous record holder.

For more see: Morpion -h|-help

Core Morpion Routines

<lang Unicon>link printf,strings,options

$define MORPVER "1.7b" # version

procedure main(A) # Morphion

  MorpionConf(A)
  if \M_ReplayFile then ReplayMorpion() 
  else if \M_Limit === 1 then PlayMorphion5T()
  else MultiSimMorphion(\M_Limit)
  printf("Finished.\n")

end

record morpioncell(symbol,direction,row,col) # a grid cell record morpionmove(direction,move,line,roff,coff) # move & line record morpiongame(grid, # the grid

                 log,history,            # move log and replayable history log
                 roff,coff,center,       # origin expansion offsets and center 
                 pool,                   # pool of avail moves
                 move,                   # selected move
                 count,                  # game number (multi-game)
                 rseed)                  # &random at start of random play  

global M_Strategy,M_Eval,M_Mvalid # Pluggable procedures global M_CommandLine,M_Config,M_PrintOpt,M_GameSave # Misc. global M_Limit,M_StatUpd,M_BestL,M_WorstL # Multi-game simulation options global M_SrchWid,M_SrchDep # For strategy modules global M_ReplayFile,M_ReplayAfter # For game replay

$define XEMPTY "." # symbols used in Grid $define XINIT "*" $define XUSED "+"

$define DHOR "-" # Directions for moves $define DVER "|" $define DRD "\\" $define DLD "/"

procedure PlayMorphion5T() #: Play a 5T game

  G := (MG := SetupM5Grid()).grid                 # start new game
  &random := MG.rseed := \M_Rseed                 # set &random
  if M_PrintOpt = 1 then PrintGrid(MG)
  pg := if M_PrintOpt == 2 then PrintGrid else 1 
  while MorphionMove(M_Strategy(pg(MG)))          # keep moving     
  if M_PrintOpt = 1 then PrintGrid(MG)  
  if M_PrintOpt > 0 then {
     PrintLog(MG)
     WriteMoveLog(MG)
     }
  return MG

end

procedure MorphionMove(MG) #: make a move

  (M := MG.move).roff := MG.roff      
  M.coff := MG.coff                
  put(MG.history,M)                
  log := FormatMoveLog(M)             
  log ||:= sprintf(" - of %i choices.",*MG.pool)  # append # choices  
  log ||:= sprintf(" Metric=%i",M_Eval(MG))       # append score (opt)
  put(MG.log,log)                                 # log the move
  every x := !M.line do {                         # draw the line 
     g := MG.grid[x[1],x[2]]
     g.direction ||:= M.direction       
     /g.symbol := XUSED                           # remove / for all XUSED
     }
  return

end

procedure ScanGrid(MG) #: Scan all grid lines

  G := ExpandGrid(MG).grid                        # expand the grid if needed
  MG.pool := []                                   # candidate moves   
  every c := 1 & r := 1 to *G do                  # horizontal
     ScanGridLine(G,r,c,0,+1,DHOR,MG.pool)
  every r := 1 & c := 1 to *G[1] do               # vertical
     ScanGridLine(G,r,c,+1,0,DVER,MG.pool)   
  every ( c := 1 & r := 1 to *G-4 ) |
        ( c := 2 to *G[r := 1] ) do               # down & right
     ScanGridLine(G,r,c,+1,+1,DRD,MG.pool)  
  every ( r := 2 to *G-4 & c := *G[r] ) |
        ( c := 5 to *G[r := 1] ) do               # down & left
  ScanGridLine(G,r,c,+1,-1,DLD,MG.pool)  
  if *MG.history = 0 & M_Strategy ~=== Replayer then {  # move 1 special case
     every put(pool1 := [], MG.pool[2|19|20|26])  # cor. o(2), i(1), val o(1) 
     MG.pool := pool1       
     }
  if *MG.pool > 0 then return MG                 

end

procedure ScanGridLine(G,r0,c0,ri,ci,dir,pool) #: scan 1 grid line (5T)

  local L5,M,r,c,x
  L5 := []                          
  r := r0 - ri & c := c0 -ci                      # one step back
  while put(L5,G[r +:= ri,c +:= ci]) do {          
     while *L5 > 5 do pop(L5)                     # too long ? 
     if *L5 < 5 then next                         # too short ?
     if M_Mvalid(L5,dir) then {                   # just right, but valid?
        put(pool,M := morpionmove(dir,,[]))       # add to pool of valid moves               
        every x := L5[i := 1 to *L5] do  {
           put(M.line,[x.row,x.col])
           if /x.symbol then M.move := i
           }
        }
     }
  return pool

end

procedure ValidMove5T(L,dir) #: Succeed if L has valid dir move

  local i,j
  if *L ~= 5 then fail                      # wrong count
  every (i := 0) +:= (/(!L).symbol,1)  
  if i ~= 1 then fail                       # more than 1 avail space
  every (j := 0) +:= ( find(dir,(!L).direction), 1) 
  if j > 1 then fail                        # no overlap, =1 implies at an end
  return                                    # that's it!

end

procedure SetupM5Grid() #: construct 5T/D grid & cross

  local G,r,c,s
  every !(G := list(10)) := list(10)                          # Grid
  every G[r := 1 to 10, c := 1 to 10] := morpioncell(,"",r,c) # Empties  
  every s := ![[1,4],[4,1],[4,7],[7,1],[7,7],[10,4]] do {     # Cross
     every r := s[1] & c := s[2] + (0 to 3) do
        G[r,c] := morpioncell(XINIT,"",r,c)    
     every r := s[2] + (0 to 3) & c := s[1] do         
        G[r,c] := morpioncell(XINIT,"",r,c)    
     }                                                     
  return morpiongame(G,[],[],0,0,1 + (*G-1)/2.,,,,&random)    # Create game 

end

procedure ExpandGrid(MG) #: expand any touching sides

  local r,c,rn,cn,C
  rn := *(G := MG.grid)                     # capture ...
  cn := *G[1]                               # ... entry dimensions
  
  if \(!G)[1].symbol then {                 # left edge  
     MG.coff +:= 1   
     every (cn | (!!G).col) +:= 1
     every push(G[r := 1 to rn],morpioncell(,"",r,1))  
     }   
  if \(!G)[cn].symbol then  {               # right edge
     cn +:= 1   
     every put(G[r := 1 to rn],morpioncell(,"",r,cn))  
     }
  if \(!G[1]).symbol then {                 # top edge
     MG.roff +:= 1
     every (rn | (!!G).row) +:= 1
     push(G,C := list(cn))
     every C[c := 1 to cn] := morpioncell(,"",1,c)     
     }   
  if \(!G[rn]).symbol then {                # bottom edge
     rn +:= 1
     put(G,C := list(cn)) 
     every C[c := 1 to cn] := morpioncell(,"",rn,c)  
     }
  return MG

end

procedure PrintGrid(MG) #: print the current Grid

  G := MG.grid
  write("\nMorphion Solitare Grid (move=",*(L := MG.log),"):\n")
  every (ruler := "   ") ||:= (1 to *G[1]) % 10                      
  write(ruler)                                                  
  every r :=  1 to *G do {
     writes(right(r%100,2)," ")                                  
     every c := 1 to *(G[r]) do 
        writes(\G[r,c].symbol | XEMPTY)    
     write()
     }   
  write(ruler,"\n")                                                
  return MG

end

procedure PrintLog(MG) #: print the log

  printf("Move Log\n")
  every printf("%i : %s\n",i := 1 to *MG.log,MG.log[i])

end

procedure FormatMoveLog(M,roff,coff) #: format a log entry

  /M.roff := \roff | 0  
  /M.coff := \coff | 0  
  log := sprintf("\"%s\" [%i,%i] : ",M.direction,
                 M.line[M.move,1]-M.roff,M.line[M.move,2]-M.coff)  
  every x := !M.line do                             
     log ||:= sprintf("[%i,%i] ",x[1]-M.roff,x[2]-M.coff)          
  return log

end

procedure RandomPlayer(MG) #: Simulate random player

  if MG.move := ?ScanGrid(MG).pool then return MG

end

procedure Scorefail(MG);end #: dummy always fails</lang>

Strategy Support

<lang Unicon># Not yet complete </lang>

Interface & Parameters

<lang Unicon>procedure Usage()

  fprintf(&errout,"_
     Morphion [options]  Plays the 5T variant of Morphion Solitaire\n_ 
     Arguments : ")
  every fprintf(&errout," %s",!M_CommandLine)
  fprintf(&errout,"_                                                         
     Morphion [options]  Plays the 5T variant of Morphion Solitaire\n_ 
     Where options are:\n_
     \t-P|-print\tcontrols how much is printed \n_                              
     \t\t\tn=2\tshows all boards and a log of all moves (every game)\n_
     \t\t\tn=1\tshows a log of the moves and final board (default single game)\n_
     \t\t\tn=0\tproduces no per game output (default for multigames)\n_
     \t-A\tchoose player strategy approach (default=random, future)\n_
     \t-E\tSpecifiy an position fitness evaluation function (default none, future)\n_       
     \t-SW\tSearch width (strategy dependent, future)\n_
     \t-SD\tSearch depth (strategy dependent, future)\n_      
     \t-R|-replay\treplay\n_
     \t-RF\tfile containing game record to be replayed\n_
     \t-RN\tnumber of moves to replay (0=all)\n_
     \t-seed\tstart the seed of the random number at this value\n_  
     \t-L|-limit\tgames to play (if 0 or less then play until any of 'XxQq' is pressed\n_
     \t\tnote for larger n this benefits from larger BLKSIZE, STRSIZE environment variables\n_   
     \t-UN\tGive status update notifications every n simulations\n_  
     \t-B\tKeep best n games of unique length (default 5)\n_        
     \t-W\tKeep worst n games of unique length (default 3)\n_       
     \t-?|-h|-help\tthis help text")
  stop()

end

procedure MorpionConf(A) # Configure the Solver

  M_CommandLine := copy(A)                        # preserve
  os := "-Q! -L+ -limit+ -P+ -print+ -R! -replay! -RF: -RN+ -seed+ -save! " 
  os ||:= "-UN+ -SW+ -SD+ -A: -E+ -B+ -W+"
  opt := options(A,os,Usage)                      # -<anything else> gets help
  M_Limit     := ( 0 <= integer(\opt["limit"|"L"])) | 1   
  M_GameSave  := opt["save"]   
  M_PrintOpt  := (0|1|2) = \opt["P"|"print"]   
  /M_PrintOpt := \M_Limit === 1 | 0  
  if \opt["R"|"replay"] then {
     M_ReplayFile   := \opt["RF"]       | "Games/177-5T-rosin.txt"
     M_ReplayAfter  := (0 < \opt["RN"]) | &null
     }
  else M_ReplayFile   := &null 
  M_Rseed := \opt["seed"]  
  M_Strategy := case opt["A"] of {                    
     "A1"     :  (def_un := 50,  PlayerA1) 
     default  :  (def_un := 500, RandomPlayer)
     }       
  M_StatUpd      := (0 < \opt["UN"]) | def_un   
  M_BestL        := (0 < \opt["B"])  | 5  
  M_WorstL       := (0 < \opt["W"])  | 0    

  M_SrchWid      := (0 < \opt["SW"]) | 5   
  M_SrchDep      := (0 < \opt["SD"]) | 5         
  M_Eval := case opt["E"] of { 
     "1"      :  Score1         #  test
     default  :  &null          # also "0"      
     }   
  c := sprintf("# --- Morpion Solitaire 5 (v%s) ---\n#\n",MORPVER)  
  c ||:= "# Command line options :"
  every c ||:= " " || !A
  c ||:=         "\n# Summary of Morpion Configuration:\n"  
  c ||:= sprintf("#   Variant (5T/5D) move validation     = %i\n",M_Mvalid := ValidMove5T)    
  c ||:= sprintf("#   Games to play                       = %s\n",(0 < M_Limit) | "* unlimited *")
  c ||:= sprintf("#   Print (0=none,1=minimal,2=all)      = %i\n",M_PrintOpt)   
  c ||:= sprintf("#   Games will be saved                 = %s\n",\M_SaveGame)
  c ||:=         "#   Multi-game options:\n"
  c ||:= sprintf("#   - Status Updates                    = %i\n",M_StatUpd) 
  c ||:= sprintf("#   - Keep best                         = %i\n",M_BestL)   
  c ||:= sprintf("#   - Keep worst                        = %i\n",M_WorstL)  
  c ||:=         "#   Replaying\n"
  c ||:= sprintf("#   - Load recorded game file           = %i\n",\M_ReplayFile | "* None *")   
  c ||:= sprintf("#   - Moves to replay                   = %i\n",0 ~= \M_ReplayAfter)    
  c ||:= sprintf("#   Player Strategy                     = %i\n",M_Strategy)  
  c ||:= sprintf("#   - Position Fitness Evaluator        = %i\n",\M_Eval | "* None *")         
  c ||:= sprintf("#   - Search Width (strategy dependant) = %i\n",M_SrchWid)   
  c ||:= sprintf("#   - Search Depth (strategy dependant) = %i\n",M_SrchDep)     
  c ||:=         "#\n# Running:\n"
  M_Config := c
  if \opt["Q"] then stop(M_Config,"-Q Stops run after processing options")
  else write(M_Config)
  /M_Eval := Scorefail    

end</lang>

Multigame Simulation and Monitoring Support

<lang Unicon>procedure MultiSimMorphion(N) #: Simulate N games

     etime := -&time 
     scores := table(n := 0) 
     every bestL|worstL  := []     
     if N <= 0 then N := "unlimited"         
     repeat {
        if n >= numeric(N) then break else n +:= 1     
        scores[*(mg := PlayMorphion5T()).log] +:= 1 
        mg.count := n                          # game number
        if short := ( /short | *(\short).log >= *mg.log, mg) then {   
           push(worstL,short)                  # keep worst 
           if *worstL > M_WorstL then pull(worstL)
           }
        if long := ( /long | *(\long).log <= *mg.log, mg) then {     
           put(bestL,long)                     # keep best
           if *bestL > M_BestL then get(bestL)
           printf("Longest game %i after %i simulations.\n",*long.log,n)
           fprintf(&errout,"\r%i of %s simulations, long=%i (%s)",
                           n,N,*long.log,&dateline)
           }            
        if (n % M_StatUpd) = 0 then    # show we're alive and working
           fprintf(&errout,"\r%i of %s simulations, long=%i (%s)",
                           n,N,*long.log,&dateline)
        if kbhit() & getch() == !"QqXx" then   # exit if any q/x
           break fprintf(&errout,"\nExiting after %i simulations.\n",n)  
        }
     etime +:= &time   
     avg := 0.0
     short := key(scores) \ 1                  # 1 key only
     every i := key(scores) do {               # summarize stats
        short >:= i
        avg +:= i * scores[i]
        }       
     printf("\nResults from Sample of %i games of Morpion 5T:\n",n)
     printf("Shortest game was %i moves.\n",short)
     printf("Average game was %i moves.\n",avg /:= n)
     printf("Longest game was %i moves.\n",*long.log)
     printf("Average time/game is %i ms.\n",etime/real(n))
     GraphScores(scores)              # graph results
     printf("\nLongest (%i) Game(s):\n",M_BestL)
     every x := !reverse(bestL) do {  # show longest game(s) and log
        PrintGrid(x) 
        WriteMoveLog(x)         
        PrintLog(x)
        }
     printf("\nShortest (%i) Game(s):\n",M_WorstL) 
     every x := !worstL do {          # show longest game(s) and log
        PrintGrid(x)                  
        PrintLog(x)
        WriteMoveLog(x)
        }      
     MemUsage()                       # diagnostic        

end

$define CHARTW 80 # chart width $define CHARTG 20 # size of chart buckets

procedure GraphScores(S) #: graph results

  chart := []
  every s := key(S) do {              # by score 
     n := s/CHARTG+1                  # chunks of ...
     until chart[n] do put(chart,0)   # grow chart to need
     chart[n] +:= S[s]
     }
  s := (1 < max!chart/CHARTW | 1)     # scale 
  printf("\nSummary of Results every '*' = %d games\n",s)
  every n := 1 to *chart do 
     printf("%3d | (%6d) %s\n",(n-1)*CHARTG,chart[n],repl("*",chart[n]/s))

end

procedure MemUsage() #: monitor usage

     printf("\nTotal run time = %i ms\n",&time)
     printf("&allocated   (Total,static,string,block) : ")
     every printf(" %i",&allocated) ;  printf("\n")      
     printf("&collections (Total,static,string,block) : ")
     every printf(" %i",&collections) ;  printf("\n")
     printf("&regions     ( -   , -    ,string,block) : ")
     every printf(" %s","-"|&regions) ;  printf("\n")          
     printf("&storage     ( -   , -    ,string,block) : ")
     every printf(" %s","-"|&storage) ;  printf("\n\n")         

end</lang>

Game Reloader/Replayer

<lang Unicon>procedure ReplayMorpion() #: Handle recorded games

  Replayer(M := ReadMoveLog(M_ReplayFile))  # read game and save data 
  if /M_ReplayAfter | (M_ReplayAfter > *M) then {
     printf("Single game replay\n")
     M_Strategy := Replayer  
     PlayMorphion5T()
     }
  else {                                    # truncation replay  
     G := (MG := SetupM5Grid()).grid        # start new grid
     while MorphionMove(Replayer(MG)) do 
        if *MG.history = M_ReplayAfter then # play until move
           break        
     (SetupM5Grid := ReSetupM5Grid)(MG)     # replace procedure and set grid
     &random := MG.rseed := \M_Rseed        # set &random per M_Seed
     if M_Limit === 1 then 
        PlayMorphion5T()                    # single game
     else
        MultiSimMorphion(M_Limit)           # simulate many games from here
     }
  return

end

procedure ReSetupM5Grid(MG) #: Used to override initial setup

  static MGB 
  if MGB := \MG then return              # 'set' partial game if arg
  else return deepcopy(MGB)              # otherwise return a new copy

end

procedure Replayer(MG) #: feed replayed moves static ML,radj,cadj

  if type(MG[1]) == "MorpionGameRecord" then return ML := MG
  if not ScanGrid(MG) then fail
  x := get(ML) | fail
  if x.ref = 0 then x := get(ML) | fail
  xr := x.row + MG.roff                  # adjust for expansion
  xc := x.col + MG.coff      
  pool := []
  every m := !MG.pool do {
     mr := m.line[m.move,1]  
     mc := m.line[m.move,2]
     if xr=mr & xc=mc then 
        put(pool,m)
     }      
  if MG.move := pool[*pool = 1] then     # is move unique ?
     return MG   
  else                                   # no - need to disambiguate 
     if /(x.darow|x.dacol) then {
        printf("Ambiguous position at move #%i with %i choices\n_
                Need unique disambiguation, syntax: n:r,c^r,c\n",*MG.log+1,*pool)
        every m := !pool do 
           printf("   %s\n",FormatMoveLog(m,MG.roff,MG.coff))                 
        }
     else { 
        dr := x.darow + MG.roff          # adjust for expansion
        dc := x.dacol + MG.coff       
        every p := ((m := !pool).line)[1|5] do
           if p[1] = dr & p[2] = dc then {
              MG.move := m
              return MG
              }
        printf("No Match found to disambiguate move #%i\n",*MG.log+1)
        every m := !pool do 
           printf("   %s\n",FormatMoveLog(m,MG.roff,MG.coff))  
        }
  PrintGrid(MG)
  PrintLog(MG) 
  WriteMoveLog(MG)
  stop()   

end

record MorpionGameRecord(ref,row,col,darow,dacol)

procedure ReadMoveLog(fn) #: Read a move log

  printf("Reading recorded game from: %s\n",fn)
  f := open(fn,"r") | stop("Unable to open file ",fn," for read.")
  M := []
  while b := trim(read(f)) do {               
     if b ? ="$end" then break           # allow pre-mature end of file
     b := deletec(b,' \t')
     b ?:= tab(find("#")|0)    
     until *b = 0 do {     
        x := MorpionGameRecord()
        b ?:= ( x.ref := integer(tab(many(&digits))),=":",            # base
                x.row := integer(=!["-","+",""]||tab(many(&digits))),=",",
                x.col := integer(=!["-","+",""]||tab(many(&digits))), 
                tab(0)) |
           stop(&output,"Syntax error in line above.")
        if b ?:= ( ="^", tab(0)) then {                               # disamb
           b ?:= ( x.darow := integer(=!["-","+",""]||tab(many(&digits))),=",",
                   x.dacol := integer(=!["-","+",""]||tab(many(&digits))), 
                   tab(0)) |
              stop(&output,"Syntax error in line above (disamiguation).")
           }
        b ?:=  ( =(";"|""), tab(0) )                                    
        put(M,x)
        }
     }
  return sortf(M,1)

end

procedure WriteMoveLog(MG) #: write out a re-readable move log

  savegame := sprintf("Games/%i-L%i",*MG.history,M_Limit)
  if M_Limit ~= 1 then 
     savegame ||:= sprintf("(%i)",MG.count)
  if \M_ReplayFile then {
     M_ReplayFile ? (="Games/", savegame ||:= "-RF" || tab(find(".txt")))
     savegame ||:= "-RN" || (0 < \M_ReplayAfter) 
     }
  savegame ||:= sprintf("_%s-%s.txt",deletec(&date,'/'),deletec(&clock,':'))
  c := sprintf( "#\n# Game Record for Morphion 5T game of %i moves\n_
                 # Reference: %s\n_
                 # &random: %i\n_
                 # Syntax for recorded games:\n_
                 #   1.  whitespace and comments (everything past #) are ignored\n_
                 #   2.  moves may be ; or newline separated\n_
                 #   3.  moves are formatted (using BNF style variables like <x>):\n_
                 #           <movenumber>:<row>,<col>[^<drow>,<dcol>]\n_
                 #       The optional drow/dcol values provide an additional point\n_ 
                 #       used to disambiguate moves.  The point drow/dcol must be\n_
                 #       chosen at one end of the line.\n_    
                 #       Moves are applied in sorted order.\n_
                 #   4.  all row/col coordinates are relative to the 1,1 origin\n_ 
                 #       located at the intersection of the lines containing the\n_
                 #       top and left most edges of the cross.\n#\n",
                 *MG.history,savegame,MG.rseed)           
  every m := MG.history[i := 1 to *MG.history] do {
     e := m.move ~= (1|5)
     /l := ""
     l ||:= sprintf("%i:%i,%i^%i,%i;",
                    i,m.line[m.move,1]-m.roff,m.line[m.move,2]-m.coff,  
                    m.line[e,1]-m.roff,m.line[e,2]-m.coff)              
     if *l > 70 then {
        c ||:= l || "\n"
        l := &null
        }
     }
     c ||:= \l || "\n"
     write(c)
     
  if \M_GameSave then {
     f := open(savegame,"w") | stop("Unable to open ",savegame," for writing")
     write(f,M_Config,c)
     close(f)
     }      

end</lang>

printf.icn provides formatting strings.icn provides deletec options.icn provides options processing

Other RosettaCode pages used Deepcopy

SampleOutput

Help

Morphion [options]  Plays the 5T variant of Morphion Solitaire
Arguments :  -hMorphion [options]  Plays the 5T variant of Morphion Solitaire
Where options are:
	-P|-print	controls how much is printed 
			n=2	shows all boards and a log of all moves (every game)
			n=1	shows a log of the moves and final board (default single game)
			n=0	produces no per game output (default for multigames)
	-A	choose player strategy approach (default=random, future)
	-E	Specifiy an position fitness evaluation function (default none, future)
	-SW	Search width (strategy dependent, future)
	-SD	Search depth (strategy dependent, future)
	-R|-replay	replay
	-RF	file containing game record to be replayed
	-RN	number of moves to replay (0=all)
	-seed	start the seed of the random number at this value
	-L|-limit	games to play (if 0 or less then play until any of 'XxQq' is pressed
		note for larger n this benefits from larger BLKSIZE, STRSIZE environment variables
	-UN	Give status update notifications every n simulations
	-B	Keep best n games of unique length (default 5)
	-W	Keep worst n games of unique length (default 3)
	-?|-h|-help	this help text

Multigame

# --- Morpion Solitaire 5 (v1.7b) ---
#
# Command line options :
# Summary of Morpion Configuration:
#   Variant (5T/5D) move validation     = procedure ValidMove5T
#   Games to play                       = * unlimited *
#   Print (0=none,1=minimal,2=all)      = 0
#   Multi-game options:
#   - Status Updates                    = 500
#   - Keep best                         = 5
#   - Keep worst                        = 0
#   Replaying
#   - Load recorded game file           = "* None *"
#   Player Strategy                     = procedure RandomPlayer
#   - Position Fitness Evaluator        = "* None *"
#   - Search Width (strategy dependant) = 5
#   - Search Depth (strategy dependant) = 5
#
# Running:

Longest game 66 after 1 simulations.
Longest game 69 after 3 simulations.
Longest game 69 after 9 simulations.
Longest game 70 after 23 simulations.
Longest game 70 after 42 simulations.
Longest game 74 after 110 simulations.
Longest game 77 after 167 simulations.
Longest game 78 after 223 simulations.
Longest game 79 after 357 simulations.
Longest game 81 after 555 simulations.
Longest game 82 after 887 simulations.
Longest game 82 after 2119 simulations.
Longest game 86 after 3092 simulations.

Results from Sample of 31434 games of Morpion 5T:
Shortest game was 20 moves.
Average game was 53.63997582235795 moves.
Longest game was 86 moves.
Average time/game is 205.6081313227715 ms.

Summary of Results every '*' = 246 games
  0 | (     0) 
 20 | (  7970) ********************************
 40 | (  3681) **************
 60 | ( 19737) ********************************************************************************
 80 | (    46) 

Longest (5) Game(s):

Morphion Solitare Grid (move=86):

   1234567890123456
 1 ................
 2 .....+....+.....
 3 .....++++++.....
 4 .....+****+.....
 5 ..++++*++*++....
 6 .+++++*++*++++..
 7 ..+****++****+..
 8 ...*++++++++*+..
 9 ...*++++++++*+..
10 ..+****++****+..
11 ..+..+*++*++++..
12 ....++*++*++++..
13 ......****+++++.
14 .....+...++++++.
15 .........++.....
16 .........+......
17 ................
   1234567890123456

#
# Game Record for Morphion 5T game of 86 moves
# Reference: Games/86-L0(3092)_20120208-090217.txt
# &random: 913514172
# Syntax for recorded games:
#   1.  whitespace and comments (everything past #) are ignored
#   2.  moves may be ; or newline separated
#   3.  moves are formatted (using BNF style variables like <x>):
#           <movenumber>:<row>,<col>[^<drow>,<dcol>]
#       The optional drow/dcol values provide an additional point
#       used to disambiguate moves.  The point drow/dcol must be
#       chosen at one end of the line.
#       Moves are applied in sorted order.
#   4.  all row/col coordinates are relative to the 1,1 origin
#       located at the intersection of the lines containing the
#       top and left most edges of the cross.
#
1:5,7^1,7;2:10,8^10,4;3:3,1^7,1;4:3,3^1,5;5:3,8^1,6;6:4,6^4,10;7:4,5^4,2;
8:5,4^1,4;9:7,0^7,4;10:6,4^5,4;11:3,10^7,10;12:7,11^7,7;13:6,7^5,7;14:5,2^3,4;
15:8,8^6,10;16:5,6^3,4;17:5,5^3,7;18:1,3^1,7;19:3,5^1,3;20:2,5^1,5;21:5,9^3,7;
22:5,3^5,1;23:5,8^5,5;24:7,6^3,10;25:3,6^3,3;26:1,8^5,4;27:2,0^6,4;28:2,3^1,3;
29:6,6^3,3;30:7,5^4,8;31:6,8^3,8;32:8,3^6,1;33:2,6^1,6;34:2,8^2,4;35:0,8^4,4;
36:0,3^4,7;37:8,6^6,4;38:3,11^7,7;39:9,6^5,6;40:6,5^3,8;41:3,2^7,6;42:8,5^8,3;
43:6,2^3,2;44:9,5^6,5;45:8,0^4,4;46:11,7^7,3;47:-1,8^3,8;48:6,3^6,2;49:9,3^5,3;
50:9,2^9,6;51:6,9^10,5;52:8,11^4,7;53:3,9^3,7;54:6,11^6,7;55:0,5^4,1;56:0,6^4,10;
57:0,7^-1,8;58:2,9^6,9;59:0,4^0,3;60:4,11^0,7;61:5,11^3,11;62:-1,3^3,7;
63:11,3^7,7;64:3,0^7,4;65:3,-1^3,3;66:4,0^3,-1;67:11,8^7,4;68:2,2^0,4;69:9,8^7,8;
70:2,1^2,0;71:8,9^6,11;72:8,10^8,7;73:9,9^7,11;74:9,11^5,7;75:10,9^6,9;
76:11,10^7,6;77:9,10^9,7;78:12,7^8,11;79:10,10^7,10;80:13,7^9,7;81:11,11^7,7;
82:11,9^11,7;83:12,8^9,11;84:10,11^7,11;85:10,12^10,8;86:11,12^7,8;

Move Log
1 : "|" [5,7] : [1,7] [2,7] [3,7] [4,7] [5,7]  - of 4 choices.
2 : "-" [10,8] : [10,4] [10,5] [10,6] [10,7] [10,8]  - of 27 choices.
3 : "|" [3,1] : [3,1] [4,1] [5,1] [6,1] [7,1]  - of 25 choices.
4 : "/" [3,3] : [1,5] [2,4] [3,3] [4,2] [5,1]  - of 23 choices.
5 : "\" [3,8] : [1,6] [2,7] [3,8] [4,9] [5,10]  - of 22 choices.
6 : "-" [4,6] : [4,6] [4,7] [4,8] [4,9] [4,10]  - of 21 choices.
7 : "-" [4,5] : [4,2] [4,3] [4,4] [4,5] [4,6]  - of 20 choices.
8 : "|" [5,4] : [1,4] [2,4] [3,4] [4,4] [5,4]  - of 17 choices.
9 : "-" [7,0] : [7,0] [7,1] [7,2] [7,3] [7,4]  - of 16 choices.
10 : "|" [6,4] : [5,4] [6,4] [7,4] [8,4] [9,4]  - of 15 choices.
11 : "|" [3,10] : [3,10] [4,10] [5,10] [6,10] [7,10]  - of 13 choices.
12 : "-" [7,11] : [7,7] [7,8] [7,9] [7,10] [7,11]  - of 11 choices.
13 : "|" [6,7] : [5,7] [6,7] [7,7] [8,7] [9,7]  - of 10 choices.
14 : "/" [5,2] : [3,4] [4,3] [5,2] [6,1] [7,0]  - of 8 choices.
15 : "/" [8,8] : [6,10] [7,9] [8,8] [9,7] [10,6]  - of 7 choices.
16 : "\" [5,6] : [3,4] [4,5] [5,6] [6,7] [7,8]  - of 6 choices.
17 : "/" [5,5] : [3,7] [4,6] [5,5] [6,4] [7,3]  - of 6 choices.
18 : "-" [1,3] : [1,3] [1,4] [1,5] [1,6] [1,7]  - of 11 choices.
19 : "\" [3,5] : [1,3] [2,4] [3,5] [4,6] [5,7]  - of 10 choices.
20 : "|" [2,5] : [1,5] [2,5] [3,5] [4,5] [5,5]  - of 13 choices.
21 : "\" [5,9] : [3,7] [4,8] [5,9] [6,10] [7,11]  - of 12 choices.
22 : "-" [5,3] : [5,1] [5,2] [5,3] [5,4] [5,5]  - of 13 choices.
23 : "-" [5,8] : [5,5] [5,6] [5,7] [5,8] [5,9]  - of 15 choices.
24 : "/" [7,6] : [3,10] [4,9] [5,8] [6,7] [7,6]  - of 18 choices.
25 : "-" [3,6] : [3,3] [3,4] [3,5] [3,6] [3,7]  - of 17 choices.
26 : "/" [1,8] : [1,8] [2,7] [3,6] [4,5] [5,4]  - of 21 choices.
27 : "\" [2,0] : [2,0] [3,1] [4,2] [5,3] [6,4]  - of 19 choices.
28 : "|" [2,3] : [1,3] [2,3] [3,3] [4,3] [5,3]  - of 17 choices.
29 : "\" [6,6] : [3,3] [4,4] [5,5] [6,6] [7,7]  - of 16 choices.
30 : "/" [7,5] : [4,8] [5,7] [6,6] [7,5] [8,4]  - of 16 choices.
31 : "|" [6,8] : [3,8] [4,8] [5,8] [6,8] [7,8]  - of 16 choices.
32 : "\" [8,3] : [6,1] [7,2] [8,3] [9,4] [10,5]  - of 17 choices.
33 : "|" [2,6] : [1,6] [2,6] [3,6] [4,6] [5,6]  - of 17 choices.
34 : "-" [2,8] : [2,4] [2,5] [2,6] [2,7] [2,8]  - of 16 choices.
35 : "/" [0,8] : [0,8] [1,7] [2,6] [3,5] [4,4]  - of 14 choices.
36 : "\" [0,3] : [0,3] [1,4] [2,5] [3,6] [4,7]  - of 12 choices.
37 : "\" [8,6] : [6,4] [7,5] [8,6] [9,7] [10,8]  - of 9 choices.
38 : "/" [3,11] : [3,11] [4,10] [5,9] [6,8] [7,7]  - of 13 choices.
39 : "|" [9,6] : [5,6] [6,6] [7,6] [8,6] [9,6]  - of 11 choices.
40 : "/" [6,5] : [3,8] [4,7] [5,6] [6,5] [7,4]  - of 12 choices.
41 : "\" [3,2] : [3,2] [4,3] [5,4] [6,5] [7,6]  - of 12 choices.
42 : "-" [8,5] : [8,3] [8,4] [8,5] [8,6] [8,7]  - of 13 choices.
43 : "|" [6,2] : [3,2] [4,2] [5,2] [6,2] [7,2]  - of 17 choices.
44 : "|" [9,5] : [6,5] [7,5] [8,5] [9,5] [10,5]  - of 22 choices.
45 : "/" [8,0] : [4,4] [5,3] [6,2] [7,1] [8,0]  - of 22 choices.
46 : "\" [11,7] : [7,3] [8,4] [9,5] [10,6] [11,7]  - of 21 choices.
47 : "|" [-1,8] : [-1,8] [0,8] [1,8] [2,8] [3,8]  - of 19 choices.
48 : "-" [6,3] : [6,2] [6,3] [6,4] [6,5] [6,6]  - of 19 choices.
49 : "|" [9,3] : [5,3] [6,3] [7,3] [8,3] [9,3]  - of 14 choices.
50 : "-" [9,2] : [9,2] [9,3] [9,4] [9,5] [9,6]  - of 13 choices.
51 : "/" [6,9] : [6,9] [7,8] [8,7] [9,6] [10,5]  - of 11 choices.
52 : "\" [8,11] : [4,7] [5,8] [6,9] [7,10] [8,11]  - of 11 choices.
53 : "-" [3,9] : [3,7] [3,8] [3,9] [3,10] [3,11]  - of 10 choices.
54 : "-" [6,11] : [6,7] [6,8] [6,9] [6,10] [6,11]  - of 11 choices.
55 : "/" [0,5] : [0,5] [1,4] [2,3] [3,2] [4,1]  - of 10 choices.
56 : "\" [0,6] : [0,6] [1,7] [2,8] [3,9] [4,10]  - of 8 choices.
57 : "/" [0,7] : [-1,8] [0,7] [1,6] [2,5] [3,4]  - of 6 choices.
58 : "|" [2,9] : [2,9] [3,9] [4,9] [5,9] [6,9]  - of 8 choices.
59 : "-" [0,4] : [0,3] [0,4] [0,5] [0,6] [0,7]  - of 8 choices.
60 : "\" [4,11] : [0,7] [1,8] [2,9] [3,10] [4,11]  - of 6 choices.
61 : "|" [5,11] : [3,11] [4,11] [5,11] [6,11] [7,11]  - of 6 choices.
62 : "\" [-1,3] : [-1,3] [0,4] [1,5] [2,6] [3,7]  - of 4 choices.
63 : "/" [11,3] : [7,7] [8,6] [9,5] [10,4] [11,3]  - of 3 choices.
64 : "\" [3,0] : [3,0] [4,1] [5,2] [6,3] [7,4]  - of 2 choices.
65 : "-" [3,-1] : [3,-1] [3,0] [3,1] [3,2] [3,3]  - of 2 choices.
66 : "\" [4,0] : [3,-1] [4,0] [5,1] [6,2] [7,3]  - of 2 choices.
67 : "\" [11,8] : [7,4] [8,5] [9,6] [10,7] [11,8]  - of 2 choices.
68 : "/" [2,2] : [0,4] [1,3] [2,2] [3,1] [4,0]  - of 2 choices.
69 : "|" [9,8] : [7,8] [8,8] [9,8] [10,8] [11,8]  - of 2 choices.
70 : "-" [2,1] : [2,0] [2,1] [2,2] [2,3] [2,4]  - of 2 choices.
71 : "/" [8,9] : [6,11] [7,10] [8,9] [9,8] [10,7]  - of 1 choices.
72 : "-" [8,10] : [8,7] [8,8] [8,9] [8,10] [8,11]  - of 1 choices.
73 : "/" [9,9] : [7,11] [8,10] [9,9] [10,8] [11,7]  - of 2 choices.
74 : "\" [9,11] : [5,7] [6,8] [7,9] [8,10] [9,11]  - of 3 choices.
75 : "|" [10,9] : [6,9] [7,9] [8,9] [9,9] [10,9]  - of 3 choices.
76 : "\" [11,10] : [7,6] [8,7] [9,8] [10,9] [11,10]  - of 3 choices.
77 : "-" [9,10] : [9,7] [9,8] [9,9] [9,10] [9,11]  - of 2 choices.
78 : "/" [12,7] : [8,11] [9,10] [10,9] [11,8] [12,7]  - of 3 choices.
79 : "|" [10,10] : [7,10] [8,10] [9,10] [10,10] [11,10]  - of 2 choices.
80 : "|" [13,7] : [9,7] [10,7] [11,7] [12,7] [13,7]  - of 2 choices.
81 : "\" [11,11] : [7,7] [8,8] [9,9] [10,10] [11,11]  - of 1 choices.
82 : "-" [11,9] : [11,7] [11,8] [11,9] [11,10] [11,11]  - of 2 choices.
83 : "/" [12,8] : [9,11] [10,10] [11,9] [12,8] [13,7]  - of 2 choices.
84 : "|" [10,11] : [7,11] [8,11] [9,11] [10,11] [11,11]  - of 1 choices.
85 : "-" [10,12] : [10,8] [10,9] [10,10] [10,11] [10,12]  - of 2 choices.
86 : "\" [11,12] : [7,8] [8,9] [9,10] [10,11] [11,12]  - of 1 choices.

Morphion Solitare Grid (move=82):

   12345678901234567
 1 .................
 2 ....+.+..........
 3 ....++++++++.....
 4 ..+++++****......
 5 ..+++++*++*......
 6 ..+++++*++*+.....
 7 ..++****++****...
 8 .+++*++++++++*...
 9 ....*++++++++*...
10 ...+****++****+..
11 ..+++++*++*++++..
12 ......+*++*++..+.
13 .......****+.....
14 .......++++++....
15 .........+.......
16 .................
   12345678901234567

#
# Game Record for Morphion 5T game of 82 moves
# Reference: Games/82-L0(2119)_20120208-090217.txt
# &random: 2066669156
# Syntax for recorded games:
#   1.  whitespace and comments (everything past #) are ignored
#   2.  moves may be ; or newline separated
#   3.  moves are formatted (using BNF style variables like <x>):
#           <movenumber>:<row>,<col>[^<drow>,<dcol>]
#       The optional drow/dcol values provide an additional point
#       used to disambiguate moves.  The point drow/dcol must be
#       chosen at one end of the line.
#       Moves are applied in sorted order.
#   4.  all row/col coordinates are relative to the 1,1 origin
#       located at the intersection of the lines containing the
#       top and left most edges of the cross.
#
1:0,7^4,7;2:3,8^1,6;3:8,1^4,1;4:11,7^7,7;5:9,5^7,3;6:8,8^6,10;7:7,11^7,7;
8:8,3^6,1;9:4,0^4,4;10:7,5^7,1;11:5,9^3,7;12:3,3^1,5;13:8,10^4,10;14:2,5^0,7;
15:11,4^7,4;16:10,8^10,4;17:1,3^1,7;18:9,9^7,11;19:4,6^4,10;20:9,6^7,8;
21:9,8^9,5;22:11,8^7,8;23:8,5^7,4;24:8,6^8,3;25:11,9^7,5;26:6,8^5,9;27:0,4^4,4;
28:5,8^3,8;29:3,6^1,4;30:5,7^4,6;31:5,6^5,10;32:11,5^7,5;33:2,6^1,6;34:3,5^3,4;
35:-1,3^3,7;36:2,3^2,7;37:6,5^4,7;38:11,6^11,5;39:12,6^8,6;40:0,8^4,4;41:0,3^4,3;
42:8,9^7,10;43:0,2^4,6;44:6,9^4,9;45:8,11^8,7;46:6,6^4,8;47:5,5^9,9;48:6,7^6,6;
49:6,4^3,7;50:4,5^8,9;51:0,5^4,5;52:7,6^5,8;53:5,4^9,8;54:6,3^3,6;55:9,12^5,8;
56:0,6^0,2;57:3,2^0,5;58:5,3^4,3;59:3,1^7,5;60:6,2^6,6;61:3,-1^7,3;62:3,0^3,-1;
63:5,2^5,6;64:2,2^0,4;65:1,1^5,5;66:2,-1^6,3;67:2,0^-1,3;68:1,2^0,2;69:8,2^4,2;
70:9,3^8,2;71:8,0^4,4;72:2,1^2,-1;73:0,1^4,5;74:4,-1^0,3;75:1,0^5,4;76:5,0^1,0;
77:1,-1^1,3;78:8,-1^8,3;79:5,-1^1,-1;80:-1,1^3,1;81:7,0^4,3;82:5,-2^5,2;

Move Log
1 : "|" [0,7] : [0,7] [1,7] [2,7] [3,7] [4,7]  - of 4 choices.
2 : "\" [3,8] : [1,6] [2,7] [3,8] [4,9] [5,10]  - of 27 choices.
3 : "|" [8,1] : [4,1] [5,1] [6,1] [7,1] [8,1]  - of 26 choices.
4 : "|" [11,7] : [7,7] [8,7] [9,7] [10,7] [11,7]  - of 24 choices.
5 : "\" [9,5] : [7,3] [8,4] [9,5] [10,6] [11,7]  - of 23 choices.
6 : "/" [8,8] : [6,10] [7,9] [8,8] [9,7] [10,6]  - of 22 choices.
7 : "-" [7,11] : [7,7] [7,8] [7,9] [7,10] [7,11]  - of 21 choices.
8 : "\" [8,3] : [6,1] [7,2] [8,3] [9,4] [10,5]  - of 20 choices.
9 : "-" [4,0] : [4,0] [4,1] [4,2] [4,3] [4,4]  - of 19 choices.
10 : "-" [7,5] : [7,1] [7,2] [7,3] [7,4] [7,5]  - of 17 choices.
11 : "\" [5,9] : [3,7] [4,8] [5,9] [6,10] [7,11]  - of 15 choices.
12 : "/" [3,3] : [1,5] [2,4] [3,3] [4,2] [5,1]  - of 14 choices.
13 : "|" [8,10] : [4,10] [5,10] [6,10] [7,10] [8,10]  - of 13 choices.
14 : "/" [2,5] : [0,7] [1,6] [2,5] [3,4] [4,3]  - of 11 choices.
15 : "|" [11,4] : [7,4] [8,4] [9,4] [10,4] [11,4]  - of 10 choices.
16 : "-" [10,8] : [10,4] [10,5] [10,6] [10,7] [10,8]  - of 9 choices.
17 : "-" [1,3] : [1,3] [1,4] [1,5] [1,6] [1,7]  - of 8 choices.
18 : "/" [9,9] : [7,11] [8,10] [9,9] [10,8] [11,7]  - of 6 choices.
19 : "-" [4,6] : [4,6] [4,7] [4,8] [4,9] [4,10]  - of 5 choices.
20 : "/" [9,6] : [7,8] [8,7] [9,6] [10,5] [11,4]  - of 3 choices.
21 : "-" [9,8] : [9,5] [9,6] [9,7] [9,8] [9,9]  - of 5 choices.
22 : "|" [11,8] : [7,8] [8,8] [9,8] [10,8] [11,8]  - of 4 choices.
23 : "\" [8,5] : [7,4] [8,5] [9,6] [10,7] [11,8]  - of 3 choices.
24 : "-" [8,6] : [8,3] [8,4] [8,5] [8,6] [8,7]  - of 7 choices.
25 : "\" [11,9] : [7,5] [8,6] [9,7] [10,8] [11,9]  - of 10 choices.
26 : "/" [6,8] : [5,9] [6,8] [7,7] [8,6] [9,5]  - of 8 choices.
27 : "|" [0,4] : [0,4] [1,4] [2,4] [3,4] [4,4]  - of 6 choices.
28 : "|" [5,8] : [3,8] [4,8] [5,8] [6,8] [7,8]  - of 4 choices.
29 : "\" [3,6] : [1,4] [2,5] [3,6] [4,7] [5,8]  - of 4 choices.
30 : "\" [5,7] : [4,6] [5,7] [6,8] [7,9] [8,10]  - of 5 choices.
31 : "-" [5,6] : [5,6] [5,7] [5,8] [5,9] [5,10]  - of 7 choices.
32 : "|" [11,5] : [7,5] [8,5] [9,5] [10,5] [11,5]  - of 8 choices.
33 : "|" [2,6] : [1,6] [2,6] [3,6] [4,6] [5,6]  - of 8 choices.
34 : "-" [3,5] : [3,4] [3,5] [3,6] [3,7] [3,8]  - of 10 choices.
35 : "\" [-1,3] : [-1,3] [0,4] [1,5] [2,6] [3,7]  - of 11 choices.
36 : "-" [2,3] : [2,3] [2,4] [2,5] [2,6] [2,7]  - of 10 choices.
37 : "/" [6,5] : [4,7] [5,6] [6,5] [7,4] [8,3]  - of 11 choices.
38 : "-" [11,6] : [11,5] [11,6] [11,7] [11,8] [11,9]  - of 9 choices.
39 : "|" [12,6] : [8,6] [9,6] [10,6] [11,6] [12,6]  - of 10 choices.
40 : "/" [0,8] : [0,8] [1,7] [2,6] [3,5] [4,4]  - of 8 choices.
41 : "|" [0,3] : [0,3] [1,3] [2,3] [3,3] [4,3]  - of 6 choices.
42 : "/" [8,9] : [7,10] [8,9] [9,8] [10,7] [11,6]  - of 3 choices.
43 : "\" [0,2] : [0,2] [1,3] [2,4] [3,5] [4,6]  - of 6 choices.
44 : "|" [6,9] : [4,9] [5,9] [6,9] [7,9] [8,9]  - of 5 choices.
45 : "-" [8,11] : [8,7] [8,8] [8,9] [8,10] [8,11]  - of 2 choices.
46 : "/" [6,6] : [4,8] [5,7] [6,6] [7,5] [8,4]  - of 2 choices.
47 : "\" [5,5] : [5,5] [6,6] [7,7] [8,8] [9,9]  - of 7 choices.
48 : "-" [6,7] : [6,6] [6,7] [6,8] [6,9] [6,10]  - of 7 choices.
49 : "/" [6,4] : [3,7] [4,6] [5,5] [6,4] [7,3]  - of 11 choices.
50 : "\" [4,5] : [4,5] [5,6] [6,7] [7,8] [8,9]  - of 10 choices.
51 : "|" [0,5] : [0,5] [1,5] [2,5] [3,5] [4,5]  - of 4 choices.
52 : "/" [7,6] : [5,8] [6,7] [7,6] [8,5] [9,4]  - of 8 choices.
53 : "\" [5,4] : [5,4] [6,5] [7,6] [8,7] [9,8]  - of 9 choices.
54 : "/" [6,3] : [3,6] [4,5] [5,4] [6,3] [7,2]  - of 10 choices.
55 : "\" [9,12] : [5,8] [6,9] [7,10] [8,11] [9,12]  - of 9 choices.
56 : "-" [0,6] : [0,2] [0,3] [0,4] [0,5] [0,6]  - of 8 choices.
57 : "/" [3,2] : [0,5] [1,4] [2,3] [3,2] [4,1]  - of 4 choices.
58 : "|" [5,3] : [4,3] [5,3] [6,3] [7,3] [8,3]  - of 3 choices.
59 : "\" [3,1] : [3,1] [4,2] [5,3] [6,4] [7,5]  - of 5 choices.
60 : "-" [6,2] : [6,2] [6,3] [6,4] [6,5] [6,6]  - of 6 choices.
61 : "\" [3,-1] : [3,-1] [4,0] [5,1] [6,2] [7,3]  - of 7 choices.
62 : "-" [3,0] : [3,-1] [3,0] [3,1] [3,2] [3,3]  - of 7 choices.
63 : "-" [5,2] : [5,2] [5,3] [5,4] [5,5] [5,6]  - of 6 choices.
64 : "/" [2,2] : [0,4] [1,3] [2,2] [3,1] [4,0]  - of 5 choices.
65 : "\" [1,1] : [1,1] [2,2] [3,3] [4,4] [5,5]  - of 6 choices.
66 : "\" [2,-1] : [2,-1] [3,0] [4,1] [5,2] [6,3]  - of 6 choices.
67 : "/" [2,0] : [-1,3] [0,2] [1,1] [2,0] [3,-1]  - of 5 choices.
68 : "|" [1,2] : [0,2] [1,2] [2,2] [3,2] [4,2]  - of 5 choices.
69 : "|" [8,2] : [4,2] [5,2] [6,2] [7,2] [8,2]  - of 4 choices.
70 : "\" [9,3] : [8,2] [9,3] [10,4] [11,5] [12,6]  - of 5 choices.
71 : "/" [8,0] : [4,4] [5,3] [6,2] [7,1] [8,0]  - of 3 choices.
72 : "-" [2,1] : [2,-1] [2,0] [2,1] [2,2] [2,3]  - of 3 choices.
73 : "\" [0,1] : [0,1] [1,2] [2,3] [3,4] [4,5]  - of 6 choices.
74 : "/" [4,-1] : [0,3] [1,2] [2,1] [3,0] [4,-1]  - of 5 choices.
75 : "\" [1,0] : [1,0] [2,1] [3,2] [4,3] [5,4]  - of 3 choices.
76 : "|" [5,0] : [1,0] [2,0] [3,0] [4,0] [5,0]  - of 5 choices.
77 : "-" [1,-1] : [1,-1] [1,0] [1,1] [1,2] [1,3]  - of 3 choices.
78 : "-" [8,-1] : [8,-1] [8,0] [8,1] [8,2] [8,3]  - of 4 choices.
79 : "|" [5,-1] : [1,-1] [2,-1] [3,-1] [4,-1] [5,-1]  - of 4 choices.
80 : "|" [-1,1] : [-1,1] [0,1] [1,1] [2,1] [3,1]  - of 3 choices.
81 : "/" [7,0] : [4,3] [5,2] [6,1] [7,0] [8,-1]  - of 2 choices.
82 : "-" [5,-2] : [5,-2] [5,-1] [5,0] [5,1] [5,2]  - of 1 choices.

Morphion Solitare Grid (move=82):

   1234567890123456789
 1 ...................
 2 .........+.++......
 3 ........****++.....
 4 ........*++*+++....
 5 .......+*++*++++...
 6 .....****++****+++.
 7 ....+*++++++++*+++.
 8 ...++*++++++++*+...
 9 ..+.+****++****+...
10 .+++++++*++*++++...
11 ....++++*++*++..+..
12 ....++++****+......
13 ......++...+.......
14 ......+.+..........
15 ...................
   1234567890123456789

#
# Game Record for Morphion 5T game of 82 moves
# Reference: Games/82-L0(887)_20120208-090217.txt
# &random: 1478604792
# Syntax for recorded games:
#   1.  whitespace and comments (everything past #) are ignored
#   2.  moves may be ; or newline separated
#   3.  moves are formatted (using BNF style variables like <x>):
#           <movenumber>:<row>,<col>[^<drow>,<dcol>]
#       The optional drow/dcol values provide an additional point
#       used to disambiguate moves.  The point drow/dcol must be
#       chosen at one end of the line.
#       Moves are applied in sorted order.
#   4.  all row/col coordinates are relative to the 1,1 origin
#       located at the intersection of the lines containing the
#       top and left most edges of the cross.
#
1:0,7^4,7;2:2,5^0,7;3:4,5^4,1;4:10,8^10,4;5:4,6^4,5;6:11,7^7,7;7:3,8^1,6;
8:8,8^6,10;9:7,11^7,7;10:1,8^1,4;11:3,3^1,5;12:6,4^10,4;13:5,9^3,7;14:8,10^4,10;
15:7,0^7,4;16:5,4^2,4;17:3,6^1,8;18:5,8^1,4;19:2,8^1,8;20:8,1^4,1;21:5,5^2,8;
22:6,6^3,3;23:3,5^3,3;24:0,5^4,5;25:9,9^7,11;26:9,5^7,3;27:2,6^2,4;28:0,8^4,4;
29:5,6^1,6;30:6,7^3,4;31:8,3^6,1;32:6,5^4,7;33:5,7^5,4;34:6,3^6,7;35:5,3^3,3;
36:9,0^5,4;37:6,8^4,6;38:9,8^5,8;39:9,6^9,4;40:3,11^7,7;41:7,6^4,3;42:6,9^5,10;
43:8,6^5,6;44:3,10^7,6;45:8,9^5,9;46:7,5^5,3;47:8,5^4,5;48:8,11^8,7;49:6,11^6,7;
50:8,2^8,6;51:11,3^7,7;52:3,9^3,7;53:5,11^1,7;54:4,11^8,11;55:5,12^5,8;
56:4,13^8,9;57:5,2^4,1;58:2,9^0,7;59:2,10^6,6;60:9,12^5,8;61:4,12^4,9;62:5,0^5,4;
63:1,9^5,9;64:6,2^4,2;65:5,13^1,9;66:8,-1^4,3;67:8,0^4,4;68:6,0^5,0;69:8,-2^8,2;
70:9,3^6,0;71:10,2^6,6;72:10,3^7,3;73:6,-1^6,3;74:9,2^6,-1;75:11,2^7,6;
76:9,1^9,0;77:10,0^6,4;78:12,2^8,2;79:10,1^10,0;80:12,4^8,0;81:7,-2^11,2;
82:8,-3^4,1;

Move Log
1 : "|" [0,7] : [0,7] [1,7] [2,7] [3,7] [4,7]  - of 4 choices.
2 : "/" [2,5] : [0,7] [1,6] [2,5] [3,4] [4,3]  - of 27 choices.
3 : "-" [4,5] : [4,1] [4,2] [4,3] [4,4] [4,5]  - of 26 choices.
4 : "-" [10,8] : [10,4] [10,5] [10,6] [10,7] [10,8]  - of 25 choices.
5 : "-" [4,6] : [4,5] [4,6] [4,7] [4,8] [4,9]  - of 23 choices.
6 : "|" [11,7] : [7,7] [8,7] [9,7] [10,7] [11,7]  - of 20 choices.
7 : "\" [3,8] : [1,6] [2,7] [3,8] [4,9] [5,10]  - of 19 choices.
8 : "/" [8,8] : [6,10] [7,9] [8,8] [9,7] [10,6]  - of 18 choices.
9 : "-" [7,11] : [7,7] [7,8] [7,9] [7,10] [7,11]  - of 17 choices.
10 : "-" [1,8] : [1,4] [1,5] [1,6] [1,7] [1,8]  - of 16 choices.
11 : "/" [3,3] : [1,5] [2,4] [3,3] [4,2] [5,1]  - of 14 choices.
12 : "|" [6,4] : [6,4] [7,4] [8,4] [9,4] [10,4]  - of 13 choices.
13 : "\" [5,9] : [3,7] [4,8] [5,9] [6,10] [7,11]  - of 13 choices.
14 : "|" [8,10] : [4,10] [5,10] [6,10] [7,10] [8,10]  - of 12 choices.
15 : "-" [7,0] : [7,0] [7,1] [7,2] [7,3] [7,4]  - of 11 choices.
16 : "|" [5,4] : [2,4] [3,4] [4,4] [5,4] [6,4]  - of 9 choices.
17 : "/" [3,6] : [1,8] [2,7] [3,6] [4,5] [5,4]  - of 7 choices.
18 : "\" [5,8] : [1,4] [2,5] [3,6] [4,7] [5,8]  - of 10 choices.
19 : "|" [2,8] : [1,8] [2,8] [3,8] [4,8] [5,8]  - of 11 choices.
20 : "|" [8,1] : [4,1] [5,1] [6,1] [7,1] [8,1]  - of 10 choices.
21 : "/" [5,5] : [2,8] [3,7] [4,6] [5,5] [6,4]  - of 8 choices.
22 : "\" [6,6] : [3,3] [4,4] [5,5] [6,6] [7,7]  - of 9 choices.
23 : "-" [3,5] : [3,3] [3,4] [3,5] [3,6] [3,7]  - of 7 choices.
24 : "|" [0,5] : [0,5] [1,5] [2,5] [3,5] [4,5]  - of 6 choices.
25 : "/" [9,9] : [7,11] [8,10] [9,9] [10,8] [11,7]  - of 4 choices.
26 : "\" [9,5] : [7,3] [8,4] [9,5] [10,6] [11,7]  - of 3 choices.
27 : "-" [2,6] : [2,4] [2,5] [2,6] [2,7] [2,8]  - of 2 choices.
28 : "/" [0,8] : [0,8] [1,7] [2,6] [3,5] [4,4]  - of 6 choices.
29 : "|" [5,6] : [1,6] [2,6] [3,6] [4,6] [5,6]  - of 4 choices.
30 : "\" [6,7] : [3,4] [4,5] [5,6] [6,7] [7,8]  - of 6 choices.
31 : "\" [8,3] : [6,1] [7,2] [8,3] [9,4] [10,5]  - of 5 choices.
32 : "/" [6,5] : [4,7] [5,6] [6,5] [7,4] [8,3]  - of 5 choices.
33 : "-" [5,7] : [5,4] [5,5] [5,6] [5,7] [5,8]  - of 6 choices.
34 : "-" [6,3] : [6,3] [6,4] [6,5] [6,6] [6,7]  - of 8 choices.
35 : "|" [5,3] : [3,3] [4,3] [5,3] [6,3] [7,3]  - of 9 choices.
36 : "/" [9,0] : [5,4] [6,3] [7,2] [8,1] [9,0]  - of 7 choices.
37 : "\" [6,8] : [4,6] [5,7] [6,8] [7,9] [8,10]  - of 6 choices.
38 : "|" [9,8] : [5,8] [6,8] [7,8] [8,8] [9,8]  - of 8 choices.
39 : "-" [9,6] : [9,4] [9,5] [9,6] [9,7] [9,8]  - of 9 choices.
40 : "/" [3,11] : [3,11] [4,10] [5,9] [6,8] [7,7]  - of 11 choices.
41 : "\" [7,6] : [4,3] [5,4] [6,5] [7,6] [8,7]  - of 7 choices.
42 : "/" [6,9] : [5,10] [6,9] [7,8] [8,7] [9,6]  - of 10 choices.
43 : "|" [8,6] : [5,6] [6,6] [7,6] [8,6] [9,6]  - of 11 choices.
44 : "/" [3,10] : [3,10] [4,9] [5,8] [6,7] [7,6]  - of 16 choices.
45 : "|" [8,9] : [5,9] [6,9] [7,9] [8,9] [9,9]  - of 14 choices.
46 : "\" [7,5] : [5,3] [6,4] [7,5] [8,6] [9,7]  - of 14 choices.
47 : "|" [8,5] : [4,5] [5,5] [6,5] [7,5] [8,5]  - of 15 choices.
48 : "-" [8,11] : [8,7] [8,8] [8,9] [8,10] [8,11]  - of 13 choices.
49 : "-" [6,11] : [6,7] [6,8] [6,9] [6,10] [6,11]  - of 13 choices.
50 : "-" [8,2] : [8,2] [8,3] [8,4] [8,5] [8,6]  - of 12 choices.
51 : "/" [11,3] : [7,7] [8,6] [9,5] [10,4] [11,3]  - of 10 choices.
52 : "-" [3,9] : [3,7] [3,8] [3,9] [3,10] [3,11]  - of 9 choices.
53 : "\" [5,11] : [1,7] [2,8] [3,9] [4,10] [5,11]  - of 10 choices.
54 : "|" [4,11] : [4,11] [5,11] [6,11] [7,11] [8,11]  - of 12 choices.
55 : "-" [5,12] : [5,8] [5,9] [5,10] [5,11] [5,12]  - of 10 choices.
56 : "/" [4,13] : [4,13] [5,12] [6,11] [7,10] [8,9]  - of 10 choices.
57 : "\" [5,2] : [4,1] [5,2] [6,3] [7,4] [8,5]  - of 9 choices.
58 : "\" [2,9] : [0,7] [1,8] [2,9] [3,10] [4,11]  - of 9 choices.
59 : "/" [2,10] : [2,10] [3,9] [4,8] [5,7] [6,6]  - of 8 choices.
60 : "\" [9,12] : [5,8] [6,9] [7,10] [8,11] [9,12]  - of 6 choices.
61 : "-" [4,12] : [4,9] [4,10] [4,11] [4,12] [4,13]  - of 5 choices.
62 : "-" [5,0] : [5,0] [5,1] [5,2] [5,3] [5,4]  - of 5 choices.
63 : "|" [1,9] : [1,9] [2,9] [3,9] [4,9] [5,9]  - of 4 choices.
64 : "|" [6,2] : [4,2] [5,2] [6,2] [7,2] [8,2]  - of 4 choices.
65 : "\" [5,13] : [1,9] [2,10] [3,11] [4,12] [5,13]  - of 4 choices.
66 : "/" [8,-1] : [4,3] [5,2] [6,1] [7,0] [8,-1]  - of 2 choices.
67 : "/" [8,0] : [4,4] [5,3] [6,2] [7,1] [8,0]  - of 1 choices.
68 : "|" [6,0] : [5,0] [6,0] [7,0] [8,0] [9,0]  - of 2 choices.
69 : "-" [8,-2] : [8,-2] [8,-1] [8,0] [8,1] [8,2]  - of 3 choices.
70 : "\" [9,3] : [6,0] [7,1] [8,2] [9,3] [10,4]  - of 2 choices.
71 : "/" [10,2] : [6,6] [7,5] [8,4] [9,3] [10,2]  - of 3 choices.
72 : "|" [10,3] : [7,3] [8,3] [9,3] [10,3] [11,3]  - of 2 choices.
73 : "-" [6,-1] : [6,-1] [6,0] [6,1] [6,2] [6,3]  - of 2 choices.
74 : "\" [9,2] : [6,-1] [7,0] [8,1] [9,2] [10,3]  - of 2 choices.
75 : "/" [11,2] : [7,6] [8,5] [9,4] [10,3] [11,2]  - of 2 choices.
76 : "-" [9,1] : [9,0] [9,1] [9,2] [9,3] [9,4]  - of 2 choices.
77 : "/" [10,0] : [6,4] [7,3] [8,2] [9,1] [10,0]  - of 4 choices.
78 : "|" [12,2] : [8,2] [9,2] [10,2] [11,2] [12,2]  - of 4 choices.
79 : "-" [10,1] : [10,0] [10,1] [10,2] [10,3] [10,4]  - of 3 choices.
80 : "\" [12,4] : [8,0] [9,1] [10,2] [11,3] [12,4]  - of 4 choices.
81 : "\" [7,-2] : [7,-2] [8,-1] [9,0] [10,1] [11,2]  - of 2 choices.
82 : "/" [8,-3] : [4,1] [5,0] [6,-1] [7,-2] [8,-3]  - of 2 choices.

Morphion Solitare Grid (move=81):

   12345678901234567
 1 .................
 2 ...........+.....
 3 ..........+......
 4 .........+++++...
 5 .....+..++++++...
 6 .....+****++++...
 7 .....+*++*+++++..
 8 .....+*++*+++++..
 9 ...****++****+.+.
10 ...*++++++++*+...
11 ...*++++++++*....
12 ..+****++****....
13 .+.+++*++*++.+...
14 ....++*++*+......
15 ...+.+****+......
16 .....+++++.......
17 .................
   12345678901234567

#
# Game Record for Morphion 5T game of 81 moves
# Reference: Games/81-L0(555)_20120208-090217.txt
# &random: 1350476946
# Syntax for recorded games:
#   1.  whitespace and comments (everything past #) are ignored
#   2.  moves may be ; or newline separated
#   3.  moves are formatted (using BNF style variables like <x>):
#           <movenumber>:<row>,<col>[^<drow>,<dcol>]
#       The optional drow/dcol values provide an additional point
#       used to disambiguate moves.  The point drow/dcol must be
#       chosen at one end of the line.
#       Moves are applied in sorted order.
#   4.  all row/col coordinates are relative to the 1,1 origin
#       located at the intersection of the lines containing the
#       top and left most edges of the cross.
#
1:5,7^1,7;2:10,3^10,7;3:8,3^6,1;4:1,3^1,7;5:4,5^4,1;6:5,4^1,4;7:7,6^7,10;
8:8,1^4,1;9:11,7^7,7;10:11,4^7,4;11:6,3^4,5;12:7,5^7,2;13:6,5^4,3;14:3,10^7,10;
15:9,3^6,3;16:9,6^7,8;17:4,11^4,7;18:9,5^7,3;19:9,2^9,6;20:8,5^6,5;21:8,8^6,10;
22:7,0^11,4;23:5,2^9,6;24:8,2^8,1;25:6,7^10,3;26:8,-1^4,3;27:10,1^6,5;28:3,3^1,5;
29:11,5^7,1;30:6,6^5,7;31:5,5^4,4;32:5,3^5,1;33:6,2^4,2;34:3,5^7,1;35:8,6^6,6;
36:6,4^6,2;37:5,6^3,4;38:11,3^7,7;39:3,6^3,3;40:2,3^6,3;41:4,6^8,2;42:6,8^3,5;
43:2,5^6,5;44:0,7^4,3;45:6,9^6,6;46:2,6^1,6;47:10,8^6,4;48:3,8^1,6;49:5,9^2,6;
50:3,9^7,9;51:2,8^2,4;52:5,8^4,8;53:8,9^8,5;54:0,6^4,10;55:2,9^6,5;56:0,3^4,7;
57:11,6^11,3;58:9,8^7,10;59:3,11^3,7;60:8,11^4,7;61:2,12^6,8;62:2,11^6,7;
63:2,10^2,8;64:5,11^5,7;65:1,11^5,7;66:1,8^0,7;67:0,9^4,5;68:3,12^7,8;69:0,11^4,11;
70:0,8^4,8;71:-1,9^3,5;72:1,9^-1,9;73:0,10^0,6;74:-1,11^3,7;75:-1,7^3,11;
76:-2,8^2,12;77:1,10^1,7;78:4,13^0,9;79:-3,9^1,5;80:-1,10^3,10;81:-1,8^-1,7;

Move Log
1 : "|" [5,7] : [1,7] [2,7] [3,7] [4,7] [5,7]  - of 4 choices.
2 : "-" [10,3] : [10,3] [10,4] [10,5] [10,6] [10,7]  - of 27 choices.
3 : "\" [8,3] : [6,1] [7,2] [8,3] [9,4] [10,5]  - of 25 choices.
4 : "-" [1,3] : [1,3] [1,4] [1,5] [1,6] [1,7]  - of 24 choices.
5 : "-" [4,5] : [4,1] [4,2] [4,3] [4,4] [4,5]  - of 22 choices.
6 : "|" [5,4] : [1,4] [2,4] [3,4] [4,4] [5,4]  - of 21 choices.
7 : "-" [7,6] : [7,6] [7,7] [7,8] [7,9] [7,10]  - of 20 choices.
8 : "|" [8,1] : [4,1] [5,1] [6,1] [7,1] [8,1]  - of 20 choices.
9 : "|" [11,7] : [7,7] [8,7] [9,7] [10,7] [11,7]  - of 19 choices.
10 : "|" [11,4] : [7,4] [8,4] [9,4] [10,4] [11,4]  - of 17 choices.
11 : "/" [6,3] : [4,5] [5,4] [6,3] [7,2] [8,1]  - of 15 choices.
12 : "-" [7,5] : [7,2] [7,3] [7,4] [7,5] [7,6]  - of 16 choices.
13 : "\" [6,5] : [4,3] [5,4] [6,5] [7,6] [8,7]  - of 14 choices.
14 : "|" [3,10] : [3,10] [4,10] [5,10] [6,10] [7,10]  - of 14 choices.
15 : "|" [9,3] : [6,3] [7,3] [8,3] [9,3] [10,3]  - of 12 choices.
16 : "/" [9,6] : [7,8] [8,7] [9,6] [10,5] [11,4]  - of 11 choices.
17 : "-" [4,11] : [4,7] [4,8] [4,9] [4,10] [4,11]  - of 12 choices.
18 : "\" [9,5] : [7,3] [8,4] [9,5] [10,6] [11,7]  - of 9 choices.
19 : "-" [9,2] : [9,2] [9,3] [9,4] [9,5] [9,6]  - of 10 choices.
20 : "|" [8,5] : [6,5] [7,5] [8,5] [9,5] [10,5]  - of 12 choices.
21 : "/" [8,8] : [6,10] [7,9] [8,8] [9,7] [10,6]  - of 17 choices.
22 : "\" [7,0] : [7,0] [8,1] [9,2] [10,3] [11,4]  - of 17 choices.
23 : "\" [5,2] : [5,2] [6,3] [7,4] [8,5] [9,6]  - of 16 choices.
24 : "-" [8,2] : [8,1] [8,2] [8,3] [8,4] [8,5]  - of 15 choices.
25 : "/" [6,7] : [6,7] [7,6] [8,5] [9,4] [10,3]  - of 16 choices.
26 : "/" [8,-1] : [4,3] [5,2] [6,1] [7,0] [8,-1]  - of 15 choices.
27 : "/" [10,1] : [6,5] [7,4] [8,3] [9,2] [10,1]  - of 12 choices.
28 : "/" [3,3] : [1,5] [2,4] [3,3] [4,2] [5,1]  - of 9 choices.
29 : "\" [11,5] : [7,1] [8,2] [9,3] [10,4] [11,5]  - of 8 choices.
30 : "/" [6,6] : [5,7] [6,6] [7,5] [8,4] [9,3]  - of 6 choices.
31 : "\" [5,5] : [4,4] [5,5] [6,6] [7,7] [8,8]  - of 8 choices.
32 : "-" [5,3] : [5,1] [5,2] [5,3] [5,4] [5,5]  - of 7 choices.
33 : "|" [6,2] : [4,2] [5,2] [6,2] [7,2] [8,2]  - of 8 choices.
34 : "/" [3,5] : [3,5] [4,4] [5,3] [6,2] [7,1]  - of 10 choices.
35 : "|" [8,6] : [6,6] [7,6] [8,6] [9,6] [10,6]  - of 12 choices.
36 : "-" [6,4] : [6,2] [6,3] [6,4] [6,5] [6,6]  - of 16 choices.
37 : "\" [5,6] : [3,4] [4,5] [5,6] [6,7] [7,8]  - of 16 choices.
38 : "/" [11,3] : [7,7] [8,6] [9,5] [10,4] [11,3]  - of 15 choices.
39 : "-" [3,6] : [3,3] [3,4] [3,5] [3,6] [3,7]  - of 14 choices.
40 : "|" [2,3] : [2,3] [3,3] [4,3] [5,3] [6,3]  - of 13 choices.
41 : "/" [4,6] : [4,6] [5,5] [6,4] [7,3] [8,2]  - of 11 choices.
42 : "\" [6,8] : [3,5] [4,6] [5,7] [6,8] [7,9]  - of 12 choices.
43 : "|" [2,5] : [2,5] [3,5] [4,5] [5,5] [6,5]  - of 11 choices.
44 : "/" [0,7] : [0,7] [1,6] [2,5] [3,4] [4,3]  - of 13 choices.
45 : "-" [6,9] : [6,6] [6,7] [6,8] [6,9] [6,10]  - of 12 choices.
46 : "|" [2,6] : [1,6] [2,6] [3,6] [4,6] [5,6]  - of 14 choices.
47 : "\" [10,8] : [6,4] [7,5] [8,6] [9,7] [10,8]  - of 16 choices.
48 : "\" [3,8] : [1,6] [2,7] [3,8] [4,9] [5,10]  - of 15 choices.
49 : "\" [5,9] : [2,6] [3,7] [4,8] [5,9] [6,10]  - of 16 choices.
50 : "|" [3,9] : [3,9] [4,9] [5,9] [6,9] [7,9]  - of 18 choices.
51 : "-" [2,8] : [2,4] [2,5] [2,6] [2,7] [2,8]  - of 17 choices.
52 : "|" [5,8] : [4,8] [5,8] [6,8] [7,8] [8,8]  - of 18 choices.
53 : "-" [8,9] : [8,5] [8,6] [8,7] [8,8] [8,9]  - of 12 choices.
54 : "\" [0,6] : [0,6] [1,7] [2,8] [3,9] [4,10]  - of 11 choices.
55 : "/" [2,9] : [2,9] [3,8] [4,7] [5,6] [6,5]  - of 9 choices.
56 : "\" [0,3] : [0,3] [1,4] [2,5] [3,6] [4,7]  - of 9 choices.
57 : "-" [11,6] : [11,3] [11,4] [11,5] [11,6] [11,7]  - of 8 choices.
58 : "/" [9,8] : [7,10] [8,9] [9,8] [10,7] [11,6]  - of 8 choices.
59 : "-" [3,11] : [3,7] [3,8] [3,9] [3,10] [3,11]  - of 7 choices.
60 : "\" [8,11] : [4,7] [5,8] [6,9] [7,10] [8,11]  - of 6 choices.
61 : "/" [2,12] : [2,12] [3,11] [4,10] [5,9] [6,8]  - of 5 choices.
62 : "/" [2,11] : [2,11] [3,10] [4,9] [5,8] [6,7]  - of 4 choices.
63 : "-" [2,10] : [2,8] [2,9] [2,10] [2,11] [2,12]  - of 4 choices.
64 : "-" [5,11] : [5,7] [5,8] [5,9] [5,10] [5,11]  - of 4 choices.
65 : "/" [1,11] : [1,11] [2,10] [3,9] [4,8] [5,7]  - of 5 choices.
66 : "\" [1,8] : [0,7] [1,8] [2,9] [3,10] [4,11]  - of 4 choices.
67 : "/" [0,9] : [0,9] [1,8] [2,7] [3,6] [4,5]  - of 5 choices.
68 : "/" [3,12] : [3,12] [4,11] [5,10] [6,9] [7,8]  - of 4 choices.
69 : "|" [0,11] : [0,11] [1,11] [2,11] [3,11] [4,11]  - of 3 choices.
70 : "|" [0,8] : [0,8] [1,8] [2,8] [3,8] [4,8]  - of 1 choices.
71 : "/" [-1,9] : [-1,9] [0,8] [1,7] [2,6] [3,5]  - of 4 choices.
72 : "|" [1,9] : [-1,9] [0,9] [1,9] [2,9] [3,9]  - of 4 choices.
73 : "-" [0,10] : [0,6] [0,7] [0,8] [0,9] [0,10]  - of 7 choices.
74 : "/" [-1,11] : [-1,11] [0,10] [1,9] [2,8] [3,7]  - of 6 choices.
75 : "\" [-1,7] : [-1,7] [0,8] [1,9] [2,10] [3,11]  - of 5 choices.
76 : "\" [-2,8] : [-2,8] [-1,9] [0,10] [1,11] [2,12]  - of 3 choices.
77 : "-" [1,10] : [1,7] [1,8] [1,9] [1,10] [1,11]  - of 2 choices.
78 : "\" [4,13] : [0,9] [1,10] [2,11] [3,12] [4,13]  - of 4 choices.
79 : "/" [-3,9] : [-3,9] [-2,8] [-1,7] [0,6] [1,5]  - of 2 choices.
80 : "|" [-1,10] : [-1,10] [0,10] [1,10] [2,10] [3,10]  - of 1 choices.
81 : "-" [-1,8] : [-1,7] [-1,8] [-1,9] [-1,10] [-1,11]  - of 1 choices.

Morphion Solitare Grid (move=79):

   1234567890123456
 1 ................
 2 .....+..........
 3 .....++.........
 4 .....+****......
 5 .+++++*++*+.....
 6 ..++++*++*+++++.
 7 ..+****++****+..
 8 .++*++++++++*+..
 9 ..+*++++++++*++.
10 ...****++****+..
11 ....++*++*++++..
12 ....++*++*++++..
13 ....++****+.....
14 ....++++++.+....
15 ..........+.....
16 ................
   1234567890123456

#
# Game Record for Morphion 5T game of 79 moves
# Reference: Games/79-L0(357)_20120208-090217.txt
# &random: 417754092
# Syntax for recorded games:
#   1.  whitespace and comments (everything past #) are ignored
#   2.  moves may be ; or newline separated
#   3.  moves are formatted (using BNF style variables like <x>):
#           <movenumber>:<row>,<col>[^<drow>,<dcol>]
#       The optional drow/dcol values provide an additional point
#       used to disambiguate moves.  The point drow/dcol must be
#       chosen at one end of the line.
#       Moves are applied in sorted order.
#   4.  all row/col coordinates are relative to the 1,1 origin
#       located at the intersection of the lines containing the
#       top and left most edges of the cross.
#
1:5,7^1,7;2:7,11^7,7;3:10,8^10,4;4:7,5^7,1;5:3,3^1,5;6:3,8^1,6;7:8,8^6,10;
8:11,4^7,4;9:1,3^1,7;10:5,9^3,7;11:4,6^4,10;12:4,0^4,4;13:6,2^4,0;14:3,1^7,1;
15:3,5^1,3;16:5,4^1,4;17:9,6^7,8;18:11,7^7,7;19:8,3^6,1;20:3,10^7,10;21:3,6^3,4;
22:5,3^3,5;23:6,6^4,8;24:6,3^3,3;25:4,5^2,7;26:6,4^3,1;27:6,0^6,4;28:5,5^4,4;
29:8,2^4,6;30:9,3^6,0;31:8,5^6,3;32:9,5^9,3;33:12,8^8,4;34:8,6^8,3;35:6,5^5,5;
36:2,5^1,5;37:0,3^4,7;38:5,6^5,3;39:2,6^1,6;40:11,9^7,5;41:5,2^2,5;42:9,2^5,6;
43:3,2^7,2;44:6,7^3,4;45:6,8^6,4;46:7,6^3,2;47:11,3^7,7;48:9,8^6,8;49:3,0^3,4;
50:5,8^3,10;51:10,3^7,3;52:11,6^7,6;53:3,11^7,7;54:2,8^6,8;55:2,3^2,7;56:8,9^7,10;
57:6,9^4,9;58:11,2^7,6;59:5,0^1,4;60:11,5^11,3;61:-1,3^3,3;62:5,11^5,7;
63:2,0^6,0;64:3,9^1,7;65:3,12^3,8;66:4,11^3,12;67:8,11^4,7;68:5,-1^5,3;
69:8,10^8,7;70:2,-1^6,3;71:10,2^7,2;72:9,9^7,11;73:2,2^1,3;74:2,1^2,-1;
75:9,11^5,7;76:6,11^5,11;77:9,10^9,7;78:0,4^-1,3;79:6,12^6,8;

Move Log
1 : "|" [5,7] : [1,7] [2,7] [3,7] [4,7] [5,7]  - of 4 choices.
2 : "-" [7,11] : [7,7] [7,8] [7,9] [7,10] [7,11]  - of 27 choices.
3 : "-" [10,8] : [10,4] [10,5] [10,6] [10,7] [10,8]  - of 26 choices.
4 : "-" [7,5] : [7,1] [7,2] [7,3] [7,4] [7,5]  - of 24 choices.
5 : "/" [3,3] : [1,5] [2,4] [3,3] [4,2] [5,1]  - of 23 choices.
6 : "\" [3,8] : [1,6] [2,7] [3,8] [4,9] [5,10]  - of 22 choices.
7 : "/" [8,8] : [6,10] [7,9] [8,8] [9,7] [10,6]  - of 21 choices.
8 : "|" [11,4] : [7,4] [8,4] [9,4] [10,4] [11,4]  - of 20 choices.
9 : "-" [1,3] : [1,3] [1,4] [1,5] [1,6] [1,7]  - of 19 choices.
10 : "\" [5,9] : [3,7] [4,8] [5,9] [6,10] [7,11]  - of 17 choices.
11 : "-" [4,6] : [4,6] [4,7] [4,8] [4,9] [4,10]  - of 16 choices.
12 : "-" [4,0] : [4,0] [4,1] [4,2] [4,3] [4,4]  - of 16 choices.
13 : "\" [6,2] : [4,0] [5,1] [6,2] [7,3] [8,4]  - of 14 choices.
14 : "|" [3,1] : [3,1] [4,1] [5,1] [6,1] [7,1]  - of 13 choices.
15 : "\" [3,5] : [1,3] [2,4] [3,5] [4,6] [5,7]  - of 11 choices.
16 : "|" [5,4] : [1,4] [2,4] [3,4] [4,4] [5,4]  - of 14 choices.
17 : "/" [9,6] : [7,8] [8,7] [9,6] [10,5] [11,4]  - of 12 choices.
18 : "|" [11,7] : [7,7] [8,7] [9,7] [10,7] [11,7]  - of 11 choices.
19 : "\" [8,3] : [6,1] [7,2] [8,3] [9,4] [10,5]  - of 8 choices.
20 : "|" [3,10] : [3,10] [4,10] [5,10] [6,10] [7,10]  - of 7 choices.
21 : "-" [3,6] : [3,4] [3,5] [3,6] [3,7] [3,8]  - of 5 choices.
22 : "/" [5,3] : [3,5] [4,4] [5,3] [6,2] [7,1]  - of 2 choices.
23 : "/" [6,6] : [4,8] [5,7] [6,6] [7,5] [8,4]  - of 5 choices.
24 : "|" [6,3] : [3,3] [4,3] [5,3] [6,3] [7,3]  - of 6 choices.
25 : "/" [4,5] : [2,7] [3,6] [4,5] [5,4] [6,3]  - of 6 choices.
26 : "\" [6,4] : [3,1] [4,2] [5,3] [6,4] [7,5]  - of 4 choices.
27 : "-" [6,0] : [6,0] [6,1] [6,2] [6,3] [6,4]  - of 7 choices.
28 : "\" [5,5] : [4,4] [5,5] [6,6] [7,7] [8,8]  - of 4 choices.
29 : "/" [8,2] : [4,6] [5,5] [6,4] [7,3] [8,2]  - of 7 choices.
30 : "\" [9,3] : [6,0] [7,1] [8,2] [9,3] [10,4]  - of 7 choices.
31 : "\" [8,5] : [6,3] [7,4] [8,5] [9,6] [10,7]  - of 7 choices.
32 : "-" [9,5] : [9,3] [9,4] [9,5] [9,6] [9,7]  - of 11 choices.
33 : "\" [12,8] : [8,4] [9,5] [10,6] [11,7] [12,8]  - of 14 choices.
34 : "-" [8,6] : [8,3] [8,4] [8,5] [8,6] [8,7]  - of 13 choices.
35 : "|" [6,5] : [5,5] [6,5] [7,5] [8,5] [9,5]  - of 15 choices.
36 : "|" [2,5] : [1,5] [2,5] [3,5] [4,5] [5,5]  - of 13 choices.
37 : "\" [0,3] : [0,3] [1,4] [2,5] [3,6] [4,7]  - of 17 choices.
38 : "-" [5,6] : [5,3] [5,4] [5,5] [5,6] [5,7]  - of 15 choices.
39 : "|" [2,6] : [1,6] [2,6] [3,6] [4,6] [5,6]  - of 19 choices.
40 : "\" [11,9] : [7,5] [8,6] [9,7] [10,8] [11,9]  - of 17 choices.
41 : "/" [5,2] : [2,5] [3,4] [4,3] [5,2] [6,1]  - of 16 choices.
42 : "/" [9,2] : [5,6] [6,5] [7,4] [8,3] [9,2]  - of 14 choices.
43 : "|" [3,2] : [3,2] [4,2] [5,2] [6,2] [7,2]  - of 12 choices.
44 : "\" [6,7] : [3,4] [4,5] [5,6] [6,7] [7,8]  - of 13 choices.
45 : "-" [6,8] : [6,4] [6,5] [6,6] [6,7] [6,8]  - of 13 choices.
46 : "\" [7,6] : [3,2] [4,3] [5,4] [6,5] [7,6]  - of 13 choices.
47 : "/" [11,3] : [7,7] [8,6] [9,5] [10,4] [11,3]  - of 13 choices.
48 : "|" [9,8] : [6,8] [7,8] [8,8] [9,8] [10,8]  - of 13 choices.
49 : "-" [3,0] : [3,0] [3,1] [3,2] [3,3] [3,4]  - of 10 choices.
50 : "/" [5,8] : [3,10] [4,9] [5,8] [6,7] [7,6]  - of 10 choices.
51 : "|" [10,3] : [7,3] [8,3] [9,3] [10,3] [11,3]  - of 8 choices.
52 : "|" [11,6] : [7,6] [8,6] [9,6] [10,6] [11,6]  - of 8 choices.
53 : "/" [3,11] : [3,11] [4,10] [5,9] [6,8] [7,7]  - of 9 choices.
54 : "|" [2,8] : [2,8] [3,8] [4,8] [5,8] [6,8]  - of 8 choices.
55 : "-" [2,3] : [2,3] [2,4] [2,5] [2,6] [2,7]  - of 7 choices.
56 : "/" [8,9] : [7,10] [8,9] [9,8] [10,7] [11,6]  - of 8 choices.
57 : "|" [6,9] : [4,9] [5,9] [6,9] [7,9] [8,9]  - of 8 choices.
58 : "/" [11,2] : [7,6] [8,5] [9,4] [10,3] [11,2]  - of 8 choices.
59 : "/" [5,0] : [1,4] [2,3] [3,2] [4,1] [5,0]  - of 9 choices.
60 : "-" [11,5] : [11,3] [11,4] [11,5] [11,6] [11,7]  - of 10 choices.
61 : "|" [-1,3] : [-1,3] [0,3] [1,3] [2,3] [3,3]  - of 8 choices.
62 : "-" [5,11] : [5,7] [5,8] [5,9] [5,10] [5,11]  - of 8 choices.
63 : "|" [2,0] : [2,0] [3,0] [4,0] [5,0] [6,0]  - of 8 choices.
64 : "\" [3,9] : [1,7] [2,8] [3,9] [4,10] [5,11]  - of 6 choices.
65 : "-" [3,12] : [3,8] [3,9] [3,10] [3,11] [3,12]  - of 6 choices.
66 : "/" [4,11] : [3,12] [4,11] [5,10] [6,9] [7,8]  - of 6 choices.
67 : "\" [8,11] : [4,7] [5,8] [6,9] [7,10] [8,11]  - of 6 choices.
68 : "-" [5,-1] : [5,-1] [5,0] [5,1] [5,2] [5,3]  - of 7 choices.
69 : "-" [8,10] : [8,7] [8,8] [8,9] [8,10] [8,11]  - of 7 choices.
70 : "\" [2,-1] : [2,-1] [3,0] [4,1] [5,2] [6,3]  - of 8 choices.
71 : "|" [10,2] : [7,2] [8,2] [9,2] [10,2] [11,2]  - of 7 choices.
72 : "/" [9,9] : [7,11] [8,10] [9,9] [10,8] [11,7]  - of 6 choices.
73 : "/" [2,2] : [1,3] [2,2] [3,1] [4,0] [5,-1]  - of 5 choices.
74 : "-" [2,1] : [2,-1] [2,0] [2,1] [2,2] [2,3]  - of 5 choices.
75 : "\" [9,11] : [5,7] [6,8] [7,9] [8,10] [9,11]  - of 4 choices.
76 : "|" [6,11] : [5,11] [6,11] [7,11] [8,11] [9,11]  - of 5 choices.
77 : "-" [9,10] : [9,7] [9,8] [9,9] [9,10] [9,11]  - of 3 choices.
78 : "\" [0,4] : [-1,3] [0,4] [1,5] [2,6] [3,7]  - of 2 choices.
79 : "-" [6,12] : [6,8] [6,9] [6,10] [6,11] [6,12]  - of 1 choices.

Shortest (0) Game(s):

Total run time = 6463131 ms
&allocated   (Total,static,string,block) :  -232605485 0 119365103 -351970588
&collections (Total,static,string,block) :  618 0 0 618
&regions     ( -   , -    ,string,block) :  - 0 41859440 41859440
&storage     ( -   , -    ,string,block) :  - 0 275127 21216628

Finished.