$ filename "nQueens.exe"
'uses rtl32
'uses rtl64

'about 2.5 times faster than nQueens.o2bas
uses console

! GetTickCount lib "kernel32.dll"

int doprint
int solution
int size_of_board
double t1, t2
string ans
int *index

sub printBoard(int col_in_row[], size_of_board, solution)
=========================================================
  int x, row, col

  printl "Solution: " + solution
'/*
  int m,k
  string pr
  pr = space( (size_of_board+1) * (size_of_board*2+3+2) +2 )
  byte *b 
  @b = strptr(pr)+3
  k = 97
  for x = 1 to size_of_board
    b=k : k+=1 : @b+=2 'a b c d e etc  ...  
  next
  for row = 1 to size_of_board
    b=13 : @b++ 'cr
    b=10 : @b++ 'lf
    m=32
    if row < 10
      b=row+48  : @b+=3 'units digit
    else
      m=row\10
      k=row-(m*10)
      b=m+48 : @b++  'tens digit
      b=k+48 : @b+=2 'units digit
    endif
    for col = 1 to size_of_board
      if col_in_row[col] = row
        b=0x51 'Q
      else
        b=45 '-
      endif
      @b += 2
    next col
  next row
  b=13 : @b++
  b=10 : @b++
  print pr
  printl
'*/
/*
  print "   "
  for x = 1 to size_of_board
    print chr(x+96) + " "
  next x
  for row = 1 to size_of_board
    if row < 10
      printl row + "  "
    else
      printl row + " "
    endif
    for col = 1 to size_of_board
      if col_in_row[col] = row
        print "Q "
      else
        print "- "
      endif
    next col
  next row
  printl
*/
end sub


' place queen in current row
sub try(int col_in_row[], current_row)
======================================
  int test_row
  if current_row > size_of_board
    solution += 1
    if doprint = 0
      copy &index, &col_in_row[], size_of_board*sizeof(int)
    endif
    if solution = 1
      printBoard(col_in_row[], size_of_board, solution)
    endif
    if solution > 1 and doprint
      printBoard(col_in_row[], size_of_board, solution)
    endif   
  else
    for test_row = 1 to size_of_board
      '
      'is_free
      'int i,k
      'for i = 1 to current_row-1
        'k=col_in_row[i]
        'if k = test_row
        '  jmp fwd nxt_test_row  'beat queen in the vertical
        'endif
        'if abs(k-test_row) = abs(i-current_row)
        '  jmp fwd nxt_test_row  'beat queen in the diagonal
        'endif
      'next i
      int i
      mov ecx,current_row
      addr rdi,col_in_row
      mov dword i,1
      (
        dec ecx
        jle fwd exit
        mov eax,[rdi] 'k col_in_row
        cmp eax,test_row
        jz fwd nxt_test_row
        sub eax,test_row
        (
         jge exit
         neg eax
        )
        mov edx,i
        sub edx,current_row
        (
         jge exit
         neg edx
        )
        cmp eax,edx
        jz fwd nxt_test_row
        add rdi,4
        inc dword i
        repeat
      )
      '
      col_in_row[current_row] = test_row
      try(col_in_row[], current_row+1)
      '
      nxt_test_row:      
      '
    next test_row
  endif
end sub


sub main()
==========
  '
  loop1:
  '
  'redim int col_in_row(0)
  'redim int indexes(0)
  dim int col_in_row(20)
  dim int indexes(20)
  solution = 0
  '
  cls
  print "Size of Board (1-16)? " : size_of_board = val(input())
  '
  if size_of_board < 1
    size_of_board = 1
  endif
  if size_of_board > 16
    size_of_board = 16
  endif
  '
  printl  "Your input = " size_of_board
  print   "Show all solutions - default is first and last? (Y/N): " : ans=ltrim rtrim(input)
  printl
  '
  if lcase(ans) = "y"
    doprint = 1
  else
    doprint = 0
  endif
  'redim int col_in_row(size_of_board)  'column of queen in row
  'redim int indexes(size_of_board)
  @index = @indexes
  '
  t1=GetTickCount
  try(col_in_row[], 1)
  t2=GetTickCount
  '
  if doprint = 0
    printBoard(indexes[], size_of_board, solution)
  endif
  printl : printl "Found " + solution + " Solutions, " + "used time: " + (t2-t1)/1000 + " seconds"
  '
  print "Another Try? (Y/N) "
  ans = ltrim rtrim(input())
  if lcase(ans) = "y"
    goto loop1
  endif
end sub

main()
