All pastes #797089 Raw Edit

Someone

public text v1 · immutable
#797089 ·published 2007-11-25 19:16 UTC
rendered paste body
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; Chess game with picture windows by Cail at Quakenet -> #help.script
;
; The singleplayer mode is only for debugging and testing.
; Multiplayer was the main idea, you can use sockets or IRC to play (read help).
; The game will download the pieces automatically and put them into right place, 
; If you are experiencing problems with the game's download, get the image from: http://lost.kapsi.fi/cail/pieces.png 
; (images originally from mediawiki, by Wapcaplet) and put them into /mircdir/chess directory.
;
; Type /chess to start the game.
; Also support saving and loading the game state.
; Includes logging of moves, shows last move all the time, and last 40/24 moves in a sidepanel, which can be toggled on/off.
;
; Be sure to read the help for full description of all features.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

alias chess {
  if ($hget(chess.board))    { hfree chess.board } | hmake chess.board 100
  if ($hget(chess.info))     { hfree chess.info } | hmake chess.info 100
  if ($hget(chess.options))  { hfree chess.options } | hmake chess.options 100
  if ($exists(chess/options.hsh)) { hload chess.options chess/options.hsh }
  else {
    hadd chess.options size 100
    hadd chess.options log_format 1
    hadd chess.options send_method msg
    hadd chess.options frames 1
  }

  window -adfpw0C +nft @chess 0 0 $calc(($hget(chess.options,size) *8) +240) $calc(($hget(chess.options,size) *8) +50) 
  drawrect -rf @chess 3684408 0 0 0 $calc(($hget(chess.options,size) *8) +240) $calc(($hget(chess.options,size) *8) +50)

  log_show -200
  hadd chess.info log_lines 0

  drawrect -r @chess 65280 1 60 $iif($hget(chess.options,size) == 100,320,140) 300 50
  drawrect -r @chess 65280 1 60 $iif($hget(chess.options,size) == 100,380,200) 300 50
  drawrect -r @chess 65280 1 60 $iif($hget(chess.options,size) == 100,440,260) 300 50
  drawrect -r @chess 65280 1 60 $iif($hget(chess.options,size) == 100,500,320) 300 50

  drawtext -ro @chess 16749691 verdana 22 70 $iif($hget(chess.options,size) == 100,330,150) single player (debug)
  drawtext -ro @chess 16749691 verdana 22 70 $iif($hget(chess.options,size) == 100,390,210) connect to a server
  drawtext -ro @chess 16749691 verdana 22 70 $iif($hget(chess.options,size) == 100,450,270) start a server
  drawtext -ro @chess 16749691 verdana 22 70 $iif($hget(chess.options,size) == 100,510,330) help

  if (!$exists($qt($mircdirchess/pieces.png))) { .echo -qg $dialog(chess_getimg,chess_getimg) }
}

menu @chess {
  sclick: chess_sclick
  dclick: chess_dclick
  options:.echo -qg $dialog(chess_options,chess_options)
  help:url -n http://wiki.prco23.org/index.php/Chess_game#Help
  $iif($hget(chess.info,init),save):chess_save
  $iif($hget(chess.info,init),load):chess_load $$dialog(load_table,load_table)
  $iif($hget(chess.info,mode) == mp,send msg):.echo -qg $dialog(chess_send_pm,chess_send_pm)

  $iif($inrect($mouse.x,$mouse.y,$iif($hget(chess.options,size) == 100,840,520),20,200,$iif($hget(chess.options,size) == 100,840,520)),-)
  $iif($inrect($mouse.x,$mouse.y,$iif($hget(chess.options,size) == 100,840,520),20,200,$iif($hget(chess.options,size) == 100,840,520)),save log):log_save
}

on *:close:@chess:{
  hfree chess.board
  hfree chess.info
  hfree chess.options

  if ($exists(chess/temp.log)) { .remove chess/temp.log }
  if ($sock(chess_connect)) { sockclose chess_connect }
  if ($sock(chess)) { sockclose chess }

  if ($hget(chess.info,con_type) == irc) { chess_send disconnect | .disable #chess.n }
}

on *:active:@chess:{ titlebar @chess }

dialog load_table {
  title "Chess"
  size -1 -1 422 220
  option pixels

  text "Select a saved game.", 1, 7 5 417 20,result
  list 2, 5 25 410 200, sort
  button "", 3, -20 -20 1 1, ok
}

on 1:dialog:load_table:init:*:{
  .echo -qg $findfile(chess,*board*.save,0,parse_save $1-)
}

alias -l parse_save {
  .echo -qg $regex($1-,/\\([^\\]+)_board_(.+)\.save/g) 
  var %s = $gettok($regml(1),-1,45)
  did -a $dname 2 $gettok($regml(1),-4--2,45) $+($mid(%s,1,2),:,$mid(%s,3,2),:,$mid(%s,5,2)) - $regml(2)
}

on 1:dialog:load_table:dclick:2:{
  did -ra $dname 1 $did($dname,2).seltext 
  dialog -k $dname
}

alias chess_restart {
  hadd chess.info restart 1
  window -c @chess
  window -adfpw0C +nft @chess 0 0 $calc(($hget(chess.options,size) *8) +240) $calc(($hget(chess.options,size) *8) +60) 
  drawrect -rf @chess 3684408 0 0 0 $calc(($hget(chess.options,size) *8) +240) $calc(($hget(chess.options,size) *8) +60)
  drawrect -r @chess 22456 3 17 17 $iif($hget(chess.options,size) == 100,806,486) $iif($hget(chess.options,size) == 100,806,486)

  hadd chess.info log_lines 0
  if ($exists(chess/temp.log)) { filter -fk chess/temp.log filter_log * }
  hdel chess.info log_shown
  hdel chess.info log_show
  log_show -200

  chess_load
  hdel chess.info restart
}

alias -l chess_load {
  if (!$hget(chess.info,restart)) {
    hdel -w chess.board *
    hdel -w chess.info *
    hload chess.board $+(chess\,$+($1,-,$remove($2,:)),_board_,$4,.save)
    hload chess.info $+(chess\,$+($1,-,$remove($2,:)),_info_,$4,.save)
  }
  var %y = 1
  while (%y <= 8) {
    var %x = 1
    while (%x <= 8) {
      var %dx = $get_square(%x)
      var %dy = $get_square(%y)
      drawrect -rf @chess $get_color(%x,%y) 0 %dx %dy $hget(chess.options,size) $hget(chess.options,size)
      if ($hget(chess.board,$+(%y,%x))) { draw_piece %dx %dy $v1 $get_color(%x,%y) }

      var %alph = $gettok(A B C D E F G H I J K L M,$iif($hget(chess.info,clr_own) == w,%x,$calc(9 - %x)),32)
      var %xz = $calc((($hget(chess.options,size) * %x) + ($hget(chess.options,size)/2+15)) - $hget(chess.options,size))
      drawtext -ro @chess 16749691 verdana 16 %xz 0 %alph

      inc %x
    }  

    var %yz = $calc((($hget(chess.options,size) * %y) + ($hget(chess.options,size)/2+10)) - $hget(chess.options,size))
    drawtext -ro @chess 16749691 verdana 16 5 %yz $iif($hget(chess.info,clr_own) == w,$calc(9 - %y),%y)

    inc %y
  }

  if ($hget(chess.info,mode) == mp) && (!$hget(chess.info,restart)) {
    chess_send load $1 $3
    if ($hget(chess.info,own_turn)) { print_info light_blue Game loaded succesfully, your turn. }
    else { print_info light_blue Game loaded succesfully, $hget(chess.info,opponent) $+ 's turn. }
  }
}

alias -l chess_save {
  hsave chess.board $+(chess/,$asctime(yyyy-mm-dd-hhnnss),_board_,$iif($hget(chess.info,mode) == sp,singleplayer,$hget(chess.info,opponent)),.save)
  hsave chess.info $+(chess/,$asctime(yyyy-mm-dd-hhnnss),_info_,$iif($hget(chess.info,mode) == sp,singleplayer,$hget(chess.info,opponent)),.save)
}

alias -l chess_initiate {
  drawrect -r @chess 22456 3 17 17 $iif($hget(chess.options,size) == 100,806,486) $iif($hget(chess.options,size) == 100,806,486)
  hadd chess.info clr_select blue

  var %y = 1
  while (%y <= 8) {
    var %x = 1
    while (%x <= 8) {
      var %dx = $get_square(%x)
      var %dy = $get_square(%y)
      drawrect -rf @chess $get_color(%x,%y) 0 %dx %dy $hget(chess.options,size) $hget(chess.options,size)
      if ($get_piece(%y,%x)) { hadd chess.board $+(%y,%x) $v1 | draw_piece %dx %dy $v1 $get_color(%x,%y) }

      var %alph = $gettok(A B C D E F G H I J K L M,$iif($hget(chess.info,clr_own) == w,%x,$calc(9 - %x)),32)
      var %xz = $calc((($hget(chess.options,size) * %x) + ($hget(chess.options,size)/2+15)) - $hget(chess.options,size))
      drawtext -ro @chess 16749691 verdana 16 %xz 0 %alph

      inc %x
    }  

    var %yz = $calc((($hget(chess.options,size) * %y) + ($hget(chess.options,size)/2+10)) - $hget(chess.options,size))
    drawtext -ro @chess 16749691 verdana 16 5 %yz $iif($hget(chess.info,clr_own) == w,$calc(9 - %y),%y)

    inc %y  
  }
}

alias -l chess_dclick {
  if (!$inrect($mouse.x,$mouse.y,$iif($hget(chess.options,size) == 100,840,520),20,200,$iif($hget(chess.options,size) == 100,840,520))) { return }
  var %n = $calc($hget(chess.info,log_lines) - $iif($hget(chess.options,size) == 100,40,24))
  var %n = $calc($abs(%n) %n)

  var %log_line = $read(chess/temp.log,$calc($left($calc(($mouse.y *100) /20),-2) + %n))
  var %clr = $iif($gettok(%log_line,1,32) == white,w,b)

  if ($gettok(%log_line,2,32) == 0-0) {
    var %f.y = $iif($gettok(%log_line,1,32) == light_blue,8,1)

    if ($hget(chess.info,clr_own) == w) {
      var %f.y = $calc(9 - %f.y)
    }

    var %x1 = $iif($hget(chess.info,clr_own) == w,5,1)
    var %x2 = $iif($hget(chess.info,clr_own) == w,8,4)
    var %x3 = $iif($hget(chess.info,clr_own) == w,6,2)
    var %x4 = $iif($hget(chess.info,clr_own) == w,7,3)

    draw_selection %x1 %f.y light_blue
    draw_selection %x2 %f.y light_blue
    draw_selection %x3 %f.y yellow
    draw_selection %x4 %f.y yellow
    hadd chess.info log_select $+(%f.y,%x1) $+(%f.y,%x2) $+(%f.y,%x3) $+(%f.y,%x4)
  }
  elseif ($gettok(%log_line,2,32) == 0-0-0) {
    var %f.y = $iif($gettok(%log_line,1,32) == light_blue,8,1)

    if ($hget(chess.info,clr_own) == w) {
      var %f.y = $calc(9 - %f.y)
    }

    var %x1 = $iif($hget(chess.info,clr_own) == w,5,4)
    var %x2 = $iif($hget(chess.info,clr_own) == w,1,8)
    var %x3 = $iif($hget(chess.info,clr_own) == w,3,5)
    var %x4 = $iif($hget(chess.info,clr_own) == w,4,6)

    draw_selection %x1 %f.y light_blue
    draw_selection %x2 %f.y light_blue
    draw_selection %x3 %f.y yellow
    draw_selection %x4 %f.y yellow
    hadd chess.info log_select $+(%f.y,%x1) $+(%f.y,%x2) $+(%f.y,%x3) $+(%f.y,%x4)
  }
  else {
    if ($hget(chess.options,log_format) == 1) {
      var %move = $gettok(%log_line,2,32)
      var %from = $replace($mid(%move,2,2),a,1,b,2,c,3,d,4,e,5,f,6,g,7,h,8)
      var %to = $replace($mid(%move,5,2),a,1,b,2,c,3,d,4,e,5,f,6,g,7,h,8)
    }
    else {
      var %move = $gettok(%log_line,3,32)
      var %from = $replace($mid(%move,1,2),a,1,b,2,c,3,d,4,e,5,f,6,g,7,h,8)
      var %to = $replace($mid(%move,5,2),a,1,b,2,c,3,d,4,e,5,f,6,g,7,h,8)
    }
    var %from.x = $mid(%from,1,1)
    var %from.y = $mid(%from,2,1)
    var %to.x = $mid(%to,1,1)
    var %to.y = $mid(%to,2,1)

    if ($hget(chess.info,clr_own) == w) {
      var %from.y = $calc(9 - %from.y)
      var %to.y = $calc(9 - %to.y)
    }
    else {
      var %from.x = $calc(9 - %from.x)
      var %to.x = $calc(9 - %to.x)
    }

    draw_selection %from.x %from.y light_blue
    draw_selection %to.x %to.y yellow
    hadd chess.info log_select $+(%from.y,%from.x) $+(%to.y,%to.x)  
  }
}

alias -l chess_sclick {
  if ($hget(chess.info,log_select)) { clear_selections $v1 | hdel chess.info log_select }

  if (!$hget(chess.info,init)) { 

    ; SELECT: single player
    if ($inrect($mouse.x,$mouse.y,60,$iif($hget(chess.options,size) == 100,320,140),300,50)) { 
      hadd chess.info init 1 | hadd chess.info clr_own w | hadd chess.info mode sp 
      chess_initiate 
    }   
    ; SELECT: connect to a server
    elseif ($inrect($mouse.x,$mouse.y,60,$iif($hget(chess.options,size) == 100,380,200),300,50)) { 
      connect_dialog
    }
    ; SELECT: start a server
    elseif ($inrect($mouse.x,$mouse.y,60,$iif($hget(chess.options,size) == 100,440,260),300,50)) { 
      server_dialog
    } 
    ; SELECT: help
    elseif ($inrect($mouse.x,$mouse.y,60,$iif($hget(chess.options,size) == 100,500,310),300,50)) { 
      url -n http://wiki.prco23.org/index.php/Chess_game#Help
    } 
    return 
  }
  ; OPEN: log-window
  elseif ($inrect($mouse.x,$mouse.y,$iif($hget(chess.options,size) == 100,700,380),$iif($hget(chess.options,size) == 100,820,510),125,40)) {
    if ($hget(chess.info,log_show)) { hdel chess.info log_show | log_show $iif(($hget(chess.options,log_format) == 1),-120,-220) }
    else { hadd chess.info log_show 1 | log_show $iif(($hget(chess.options,log_format) == 1),+120,+220) }

    if (!$hget(chess.info,log_shown)) { 
      hadd chess.info log_shown 1
      if ($exists(chess/temp.log)) { filter -fk chess/temp.log filter_log * }
    }
  }

  if ($hget(chess.info,mode) == mp) && (!$hget(chess.info,own_turn)) { return }
  if ($hget(chess.info,mode) == sp) { var %clr_own = $iif($hget(chess.info,last_moved) == w,b,w) | hadd chess.info clr_own %clr_own }
  else { var %clr_own = $hget(chess.info,clr_own) }

  var %x = $iif($hget(chess.options,size) == 100,$left($calc($mouse.x -20+100),1),$left($calc(((($mouse.x -20) /60) * 100) +100),1))
  var %y = $iif($hget(chess.options,size) == 100,$left($calc($mouse.y -20+100),1),$left($calc(((($mouse.y -20) /60) * 100) +100),1))

  var %xy = $+(%y,%x)
  var %clr_selected = $left($hget(chess.board,%xy),1)
  var %clr_moved = $hget(chess.info,clr_moved)

  var %last.x = $hget(chess.info,last.x)
  var %last.y = $hget(chess.info,last.y)
  var %last.xy = $+(%last.y,%last.x)
  var %y-1 = $iif($hget(chess.info,clr_own) == w,$fw(%y,1,%clr_moved),$bw(%y,1,%clr_moved))
  var %xy-1 = $+(%y-1,%x)

  var %y2 = $calc(9 - %y)
  var %x2 = $calc(9 - %x)
  var %xy2 = $+(%y2,%x2)
  var %last.x2 = $calc(9 - $hget(chess.info,last.x))
  var %last.y2 = $calc(9 - $hget(chess.info,last.y))
  var %last.xy2 = $+(%last.y2,%last.x2)

  var %is_last = $iif((%x == %last.x) && (%y == %last.y),$true,$false)
  var %current_selections = $hget(chess.info,current_selections)
  var %selected = $hget(chess.info,selected)


  if (!%selected) && (%clr_selected != %clr_own) && ($hget(chess.board,%xy)) { return }
  elseif (%selected) && (%clr_selected == %clr_own) {
    clear_selections %last.xy %current_selections | hdel chess.info selected | hdel chess.info current_selections
    if (%is_last) { hdel chess.info castling | return } 
    if ($hget(chess.info,castling)) { chess_castling %last.xy %xy $hget(chess.info,clr_own) | return }
    hdel chess.info castling
  }
  elseif (!$hget(chess.board,%xy) && !$hget(chess.info,selected)) { return }
  elseif (!$istok(%current_selections,%xy,32)) && (%current_selections) { return }

  ; a piece is selected, and moveable
  if ($hget(chess.info,selected)) {
    hadd chess.info last_moved %clr_own

    if ($hget(chess.info,en_passant) == %xy-1) && ($left($hget(chess.board,%xy-1),1) != %clr_own) { 
      hadd chess.info log_ep 1
      hdel chess.board %xy-1 
      drawrect -rf @chess $get_color(%x,%y-1) 0 $get_square(%x) $get_square(%y-1) $hget(chess.options,size) $hget(chess.options,size)
    }
    hdel chess.info en_passant
    hdel chess.info check

    drawrect -rf @chess $get_color(%last.x,%last.y) 0 $get_square(%last.x) $get_square(%last.y) $hget(chess.options,size) $hget(chess.options,size)
    if ($hget(chess.board,%last.xy)) { draw_piece $get_square(%x) $get_square(%y) $v1 $get_color(%x,%y) }
    if ($hget(chess.board,%xy)) { hadd chess.info take $v1 }
    .echo -qg $chess_move(%last.xy,->,%xy)
    clear_selections %current_selections %last.xy
    hdel chess.info selected
    hdel chess.info current_selections

    if ($hget(chess.info,mode) == mp) && (!$hget(chess.info,king_in_danger)) {
      if (!$hget(chess.info,just_switched)) { chess_send move %last.xy2 %xy2 }
      print_info light_blue $hget(chess.info,opponent) $+ 's turn
      hdel chess.info own_turn
    }
    hdel chess.info just_switched  
    hdel chess.info king_in_danger
  }

  ; nothing selected, so we're selecting a piece
  else {
    var %piece = $hget(chess.board,%xy)
    draw_selection %x %y green
    hadd chess.info selected 1
    chess_piece_options %piece %x %y
  }

  hadd chess.info clr_moved %clr_selected
  hadd chess.info last.x %x
  hadd chess.info last.y %y
}

alias -l draw_piece {
  var %y = $calc((($replace($left($3,1),w,1,b,3) + $iif($4 == 10407679,0,1)) *100) -100) 
  var %x = $calc($replace($right($3,-2),pawn,0,rook,1,knight,2,bishop,3,queen,4,king,5) *100)
  drawpic -cms @chess $1 $2 $hget(chess.options,size) $hget(chess.options,size) %x %y 100 100 $qt($mircdirchess/pieces.png)
}

alias -l draw_selection {
  if ($3 == red) && (!$hget(chess.options,frames)) { return }
  drawrect -r @chess $clr_replace($3) 3 $calc($get_square($1) +1) $calc($get_square($2) +1) $calc($hget(chess.options,size) -2) $calc($hget(chess.options,size) -2)
}

alias -l chess_move {
  var %piece = $hget(chess.board,$1)
  var %move_len = $abs($calc($left($3,1) - $left($1,1)))

  if ($right(%piece,-2) == pawn) {
    var %l.x = $mid($3,2,1)
    var %l.y = $mid($3,1,1)
    var %l.y-1 = $calc(%l.y -1)
    var %l.xy-1 = $+(%l.y-1,%l.x)

    if ($istok(1 8,$left($3,1),32)) { 
      var %l.x2 = $calc(9 - $mid($1,2,1))
      var %l.y2 = $calc(9 - $mid($1,1,1))
      var %l.xy2 = $+(%l.y2,%l.x2)

      var %n.x2 = $calc(9 - $mid($3,2,1))
      var %n.y2 = $calc(9 - $mid($3,1,1))
      var %n.xy2 = $+(%n.y2,%n.x2)

      .echo -qg $dialog(choose_piece,choose_piece) 
      if ($hget(chess.info,mode) == mp) { chess_send switch %newpiece %n.xy2 %l.xy2 }
      switch_piece %newpiece $3 $1  
      hadd chess.info just_switched 1

      return 
    }
    elseif (%move_len == 2) { hadd chess.info en_passant $3 }

    if ($hget(chess.info,opponent_move)) && ($hget(chess.info,en_passant) == %l.xy-1) {
      hadd chess.info log_ep 1
      hdel chess.board %l.xy-1 
      drawrect -rf @chess $get_color(%l.x,%l.y-1) 0 $get_square(%l.x) $get_square(%l.y-1) $hget(chess.options,size) $hget(chess.options,size) 
    }

  }
  elseif (%piece == $+($hget(chess.info,clr_own),_king)) {
    hadd chess.info $+($1,_king_moved) 1
  }
  elseif (%piece == $+($hget(chess.info,clr_own),rook)) && ($1 == 81) {
    hadd chess.info left_rook_moved 1
  }
  elseif (%piece == $+($hget(chess.info,clr_own),rook)) && ($1 == 88) {
    hadd chess.info right_rook_moved 1
  }
  hadd chess.board $3 %piece
  hdel chess.board $1

  hadd chess.info king_check 1
  hadd chess.info king_check2 1
  chess_piece_options %piece $mid($3,2,1) $mid($3,1,1)

  if ($hget(chess.info,opponent_move)) {
    if ($istok($hget(chess.info,threat_zone),$hfind(chess.board,$+($hget(chess.info,clr_own),_king),1).data,32)) { 
      print_info red Check
      hadd chess.info check 1
      chess_log $replacex($hget(chess.info,clr_own),b,w,w,b) $1 $3 $right(%piece,-2) $+(+,$iif($hget(chess.info,take),x))
    }
    else { chess_log $replacex($hget(chess.info,clr_own),b,w,w,b) $1 $3 $right(%piece,-2) $iif($hget(chess.info,take),x) }
  }
  elseif (!$hget(chess.info,opponent_move)) {
    if ($istok($hget(chess.info,threat_zone),$hfind(chess.board,$+($iif($hget(chess.info,clr_own) == w,b,w),_king),1).data,32)) { 
      var %checked 1      
      chess_log $hget(chess.info,clr_own) $1 $3 $right(%piece,-2) $+(+,$iif($hget(chess.info,take),x))
    }

    hdel chess.info threat_zone
    var %n = 1
    hadd chess.info king_check 1
    while ($hfind(chess.board,$+($iif($hget(chess.info,clr_own) == w,b,w),_,*),%n,w).data) {
      var %s = $v1
      if ($right($hget(chess.board,%s),-2) != king) { chess_piece_options_rec $hget(chess.board,%s) $mid(%s,2,1) $mid(%s,1,1) }
      inc %n
    }

    if ($istok($hget(chess.info,threat_zone),$hfind(chess.board,$+($hget(chess.info,clr_own),_king),1).data,32)) { 
      hadd chess.info king_in_danger 1
    }
    elseif (!$hget(chess.info,just_switched)) && (!%checked) { chess_log $hget(chess.info,clr_own) $1 $3 $right(%piece,-2) $iif($hget(chess.info,take),x) }

  }

  if ($hget(chess.info,king_in_danger)) {
    print_info red Illegal move! king would be threated.
    hadd chess.board $1 %piece
    if ($hget(chess.info,take)) { hadd chess.board $3 $v1 }
    else { hdel chess.board $3 }
  }
  else {
    hdel chess.info just_switched
    hdel chess.info take
    hdel chess.info log_ep
    hdel chess.info opponent_move
  }
  hdel chess.info threat_zone
  hdel chess.info king_check
  hdel chess.info king_check2

  return
}

alias -l switch_piece {
  var %x = $mid($2,1,1)
  var %y = $mid($2,2,1)
  var %dx = $get_square(%x)
  var %dy = $get_square(%y)
  var %piece = $hget(chess.board,$3)

  var %new_piece = $1
  hadd chess.board $2 %new_piece
  hdel chess.board $3

  draw_piece %dy %dx %new_piece $get_color(%x,%y)

  hadd chess.info king_check 1
  hadd chess.info king_check2 1
  chess_piece_options %new_piece %y %x

  if ($hget(chess.info,opponent_move)) {
    if ($istok($hget(chess.info,threat_zone),$hfind(chess.board,$+($hget(chess.info,clr_own),_king),1).data,32)) { 
      print_info red Check
      chess_log $replacex($hget(chess.info,clr_own),b,w,w,b) $3 $2 $right(%piece,-2) $+(s,+,$replace($hget(chess.info,take),1,x)) $right(%new_piece,-2)
    }
    else { chess_log $replacex($hget(chess.info,clr_own),b,w,w,b) $3 $2 $right(%piece,-2) $+(s,$replace($hget(chess.info,take),1,x)) $right(%new_piece,-2) }
  }
  elseif ($istok($hget(chess.info,threat_zone),$hfind(chess.board,$+($iif($hget(chess.info,clr_own) == w,b,w),_king),1).data,32)) {  
    chess_log $hget(chess.info,clr_own) $1 $3 $right(%piece,-2) $+(s,+,$replace($hget(chess.info,take),1,x)) $right(%new_piece,-2)
  }
  else { chess_log $hget(chess.info,clr_own) $3 $2 $right(%piece,-2) $+(s,$replace($hget(chess.info,take),1,x)) $right(%new_piece,-2) }

  unset %newpiece

  hdel chess.info just_switched
  hdel chess.info take
  hdel chess.info log_ep
  hdel chess.info opponent_move
  hdel chess.info threat_zone
  hdel chess.info king_check
  hdel chess.info king_check2
}

alias -l chess_castling {
  var %x.king = $mid($1,2,1)
  var %y.king = $mid($1,1,1)
  var %x.rook = $mid($2,2,1)
  var %y.rook = $mid($2,1,1)

  var %xy.king = $+(%y.king,%x.king)
  var %xy.rook = $+(%y.rook,%x.rook)
  var %king = $+($3,_king)
  var %rook = $+($3,_rook)


  var %l.x2 = $calc(9 - $mid($1,2,1))
  var %l.y2 = $calc(9 - $mid($1,1,1))
  var %l.xy2 = $+(%l.y2,%l.x2)

  var %n.x2 = $calc(9 - $mid($2,2,1))
  var %n.y2 = $calc(9 - $mid($2,1,1))
  var %n.xy2 = $+(%n.y2,%n.x2)

  if ($3 == $hget(chess.info,clr_own)) {
    hadd chess.info king_moved 1
    hadd chess.info $+($iif(%x.rook == 8,right,left),_rook_moved) 1
  }

  if (%x.rook == 8) {
    var %x+1.king = $calc(%x.king +2)
    var %xy+1.king = $+(%y.king,%x+1.king)
    var %x-1.king = $calc(%x.king +1)
    var %xy-1.king = $+(%y.king,%x-1.king)
    var %castling = $iif($hget(chess.info,clr_own) == w,0-0,0-0-0)
  }
  else {
    var %x+1.king = $calc(%x.king -2)
    var %xy+1.king = $+(%y.king,%x+1.king)
    var %x-1.king = $calc(%x.king -1)
    var %xy-1.king = $+(%y.king,%x-1.king)
    var %castling = $iif($hget(chess.info,clr_own) == w,0-0-0,0-0)
  }

  if ($hget(chess.info,clr_own) == w) {
    ;draw_piece $get_square(%x+1.king) $get_square(%y.king) %king $get_color(%x+1.king,%y.king)
    ;draw_piece $get_square(%x-1.king) $get_square(%y.king) %rook $get_color(%x-1.king,%y.king)
  }

  draw_piece $get_square(%x+1.king) $get_square(%y.king) %king $get_color(%x+1.king,%y.king)
  draw_piece $get_square(%x-1.king) $get_square(%y.king) %rook $get_color(%x-1.king,%y.king)

  drawrect -rf @chess $get_color(%x.rook,%y.rook) 0 $get_square(%x.rook) $get_square(%y.rook) $hget(chess.options,size) $hget(chess.options,size)
  drawrect -rf @chess $get_color(%x.king,%y.king) 0 $get_square(%x.king) $get_square(%y.king) $hget(chess.options,size) $hget(chess.options,size)

  hadd chess.board %xy+1.king %king
  hadd chess.board %xy-1.king %rook
  hdel chess.board %xy.rook
  hdel chess.board %xy.king

  if ($hget(chess.info,mode) == mp) && (!$4) { 
    chess_send castling %l.xy2 %n.xy2 $3
    print_info light_blue $hget(chess.info,opponent) $+ 's turn
  }

  hadd chess.info king_check 1
  hadd chess.info king_check2 1

  var %piece = %rook
  chess_piece_options %piece %x-1.king %y.king

  if ($hget(chess.info,opponent_move)) {
    if ($istok($hget(chess.info,threat_zone),$hfind(chess.board,$+($hget(chess.info,clr_own),_king),1).data,32)) { 
      print_info red Check | chess_log $replacex($hget(chess.info,clr_own),b,w,w,b) %castling +
    }
    else { chess_log $replacex($hget(chess.info,clr_own),b,w,w,b) %castling }
  }
  elseif ($istok($hget(chess.info,threat_zone),$hfind(chess.board,$+($iif($hget(chess.info,clr_own) == w,b,w),_king),1).data,32)) {  
    chess_log $hget(chess.info,clr_own) %castling +
  }
  else { chess_log $hget(chess.info,clr_own) %castling }

  hdel chess.info just_switched
  hdel chess.info take
  hdel chess.info log_ep
  hdel chess.info opponent_move
  hdel chess.info threat_zone
  hdel chess.info king_check
  hdel chess.info king_check2
  hdel chess.info own_turn
  hdel chess.info castling
}

alias -l clr_replace {
  return $replacex($1,red,255,green,65280,blue,16732457,yellow,2751743,light_blue,16749691,white,16777215)
}

alias -l get_color {
  ;return $iif($calc(($1 -($2 % 2)) % 2),0,16777215)
  return $iif($calc(($1 -($2 % 2)) % 2),4688849,10407679)
  ; 10407679
}

alias get_piece {
  if ($istok(1 2 7 8,$1,32)) { 
    var %c = $hget(chess.info,clr_own)
    if ($1 == 2) { return $+($iif(%c == w,b,w),_pawn) }
    elseif ($1 == 7) { return $+(%c,_pawn) }
    elseif ($1 == 8) { return $+(%c,$gettok(_rook _knight _bishop $iif(%c == w,_queen _king,_king _queen) _bishop _knight _rook,$2,32)) }
    else { return $+($iif(%c == w,b,w),$gettok(_rook _knight _bishop $iif(%c == w,_queen _king,_king _queen) _bishop _knight _rook,$2,32)) }
  }
}

alias -l get_square {
  return $calc((($1 -1) * $hget(chess.options,size)) +20)
}

alias -l clear_selections {
  var %z = 1 
  while ($gettok($1-,%z,32)) {
    var %x = $mid($v1,2,1)
    var %y = $mid($v1,1,1)
    var %ispiece = $hget(chess.board,$v1)
    if ($v1 != 99) { 
      drawrect -rf @chess $get_color(%x,%y) 0 $get_square(%x) $get_square(%y) $hget(chess.options,size) $hget(chess.options,size)
      if (%ispiece) { draw_piece $get_square(%x) $get_square(%y) $v1 $get_color(%x,%y) }
    }
    inc %z
  }
}

alias -l print_info {
  drawrect -rf @chess 3684408 0 20 $iif($hget(chess.options,size) == 100,825,505) $iif($hget(chess.options,size) == 100,570,420) 20 | drawtext -cro @chess $clr_replace($1) "courier new" $iif($hget(chess.options,size) == 100,16,12) 20 $iif($hget(chess.options,size) == 100,825,505) $iif($hget(chess.options,size) == 100,570,420) 20 $2-
}

alias -l check_square {
  var %hg = $hget(chess.board,$+($2,$1))
  var %c = $iif($hget(chess.info,clr_own) == w,b,w)
  if ($hget(chess.info,king_check)) { var %c = $iif(%c == w,b,w) }
  if ($3) { var %c = $3 }
  if (!%hg) || ($left(%hg,1) == %c) { 
    return $true 
  }
}

alias -l in_board {
  if ($1 isnum 1-8) && ($2 isnum 1-8) { return $true }
}

alias -l draw+select {
  if (!$hget(chess.info,king_check)) { draw_selection $1 $2 $hget(chess.info,clr_select) }
  return $+($2,$1)
}

alias -l chess_piece_options_rec {
  chess_piece_options $1-
}

alias -l fw { return $calc($1 $iif($3 == w,+,-) $2) }
alias -l bw { return $calc($1 $iif($3 == w,-,+) $2) }

alias -l chess_piece_options {
  var %king_check = $hget(chess.info,king_check)
  var %king_check2 = $hget(chess.info,king_check2)

  var %piece = $right($1,-2)
  var %clr_own = $left($1,1)

  if (!%king_check) {
    var %clr_own = $iif(%clr_own == w,w,b)
    var %clr_opponent = $iif(%clr_own == w,b,w)
  }

  var %clr_opponent = $iif(%clr_own == w,b,w) 

  var %x = $2
  var %y = $3

  ; PAWN
  if (%piece == pawn) { 

    var %y+1 = $iif(%clr_own == w,$bw(%y,1,%clr_own),$fw(%y,1,%clr_own))
    var %y-1 = $iif(%clr_own == w,$fw(%y,1,%clr_own),$bw(%y,1,%clr_own))
    var %y+2 = $iif(%clr_own == w,$bw(%y,2,%clr_own),$fw(%y,2,%clr_own))
    var %x+1 = $calc(%x +1)
    var %x-1 = $calc(%x -1)

    var %take_left = $+(%y+1,%x+1)
    var %take_right = $+(%y+1,%x-1)

    if (($left($hget(chess.board,%take_left),1) == %clr_opponent) || (($hget(chess.info,en_passant) == $+(%y,%x+1)) && ($left($hget(chess.board,$+(%y,%x+1)),1) == %clr_opponent))) {    
      if (!%king_check) { var %select = %select $draw+select(%x+1,%y+1,%x) }
    }
    if (%king_check) { var %select = %select $draw+select(%x+1,%y-1) }

    if (($left($hget(chess.board,%take_right),1) == %clr_opponent) || (($hget(chess.info,en_passant) == $+(%y,%x-1)) && ($left($hget(chess.board,$+(%y,%x-1)),1) == %clr_opponent))) { 
      if (!%king_check) { var %select = %select $draw+select(%x-1,%y+1) }
    }
    if (%king_check) { var %select = %select $draw+select(%x-1,%y-1) }

    if (!$hget(chess.board,$+(%y+1,%x))) && (%y+1 <= 8) && (%y+1 >= 1) && (!%king_check) {
      var %select = %select $draw+select(%x,%y+1)

      ; 2 steps for first move
      if ($istok(2 7,%y,32)) && (!$hget(chess.board,$+(%y+2,%x))) && (%y+2 <= 8) && (%y+2 > 1) { var %select = %select $draw+select(%x,%y+2) }
    }
    if (!%king_check) { hadd chess.info current_selections $iif(%select,$v1,99) }
    else { hadd chess.info threat_zone $hget(chess.info,threat_zone) %select }
    return
  }

  ; ROOK
  elseif (%piece == rook) {

    ; :: RIGHT
    var %z = $iif(%x == 8,9,$calc(%x +1))
    while (%z <= 8) { if ($kc(%y,%z)) { break } | var %select = %select $draw+select(%z,%y) | inc %z }
    if ($left($hget(chess.board,$+(%y,%z)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%z,%y) }

    ; :: LEFT
    var %z = $iif(%x == 1,0,$calc(%x -1))
    while (%z >= 1) { if ($kc(%y,%z)) { break } | var %select = %select $draw+select(%z,%y) | dec %z } 
    if ($left($hget(chess.board,$+(%y,%z)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%z,%y) }

    ; :: UP
    var %z = $iif(%y == 1,0,$calc(%y -1))
    while (%z >= 1) { if ($kc(%z,%x)) { break } | var %select = %select $draw+select(%x,%z) | dec %z }
    if ($left($hget(chess.board,$+(%z,%x)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%x,%z) }

    ; :: DOWN
    var %z = $iif(%y == 8,9,$calc(%y +1))
    while (%z <= 8) { if ($kc(%z,%x)) { break } | var %select = %select $draw+select(%x,%z) | inc %z }
    if ($left($hget(chess.board,$+(%z,%x)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%x,%z) }

    if (!%king_check) { hadd chess.info current_selections $iif(%select,$v1,99) }
    else { hadd chess.info threat_zone $hget(chess.info,threat_zone) %select }
    return
  }

  ; BISHOP
  elseif (%piece == bishop) {

    ; :: LEFT-UP
    var %sx = $iif(%x == 1,0,$calc(%x -1))
    var %sy = $iif(%y == 1,0,$calc(%y -1))
    while (%sx >= 1) && (%sy >= 1) { if ($kc(%sy,%sx)) { break } | var %select = %select $draw+select(%sx,%sy) | dec %sx | dec %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%sx,%sy) }

    ; :: LEFT-DOWN
    var %sx = $iif(%x == 1,0,$calc(%x -1))
    var %sy = $iif(%y == 8,9,$calc(%y +1))
    while (%sx >= 1) && (%sy <= 8) { if ($kc(%sy,%sx)) { break } | var %select = %select $draw+select(%sx,%sy) | dec %sx | inc %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%sx,%sy) }

    ; :: RIGHT-UP
    var %sx = $iif(%x == 8,9,$calc(%x +1))
    var %sy = $iif(%y == 1,0,$calc(%y -1))
    while (%sx <= 8) && (%sy >= 1) { if ($kc(%sy,%sx)) { break } | var %select = %select $draw+select(%sx,%sy) | inc %sx | dec %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%sx,%sy) }

    ; :: RIGHT-DOWN
    var %sx = $iif(%x == 8,9,$calc(%x +1))
    var %sy = $iif(%y == 8,9,$calc(%y +1))
    while (%sx <= 8) && (%sy <= 8) { if ($kc(%sy,%sx)) { break } | var %select = %select $draw+select(%sx,%sy) | inc %sx | inc %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%sx,%sy) }

    if (!%king_check) { hadd chess.info current_selections $iif(%select,$v1,99) }
    else { hadd chess.info threat_zone $hget(chess.info,threat_zone) %select }
    return
  }

  ; QUEEN
  elseif (%piece == queen) {

    ; :: RIGHT
    var %z = $iif(%x == 8,9,$calc(%x +1))
    while (%z <= 8) { if ($kc(%y,%z)) { break } | var %select = %select $draw+select(%z,%y) | inc %z }   
    if ($left($hget(chess.board,$+(%y,%z)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%z,%y) }

    ; :: LEFT
    var %z = $iif(%x == 1,0,$calc(%x -1))
    while (%z >= 1) { if ($kc(%y,%z)) { break } | var %select = %select $draw+select(%z,%y) | dec %z }    
    if ($left($hget(chess.board,$+(%y,%z)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%z,%y) }

    ; :: UP
    var %z = $iif(%y == 1,0,$calc(%y -1))
    while (%z >= 1) { if ($kc(%z,%x)) { break } | var %select = %select $draw+select(%x,%z) | dec %z }   
    if ($left($hget(chess.board,$+(%z,%x)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%x,%z) }

    ; :: DOWN
    var %z = $iif(%y == 8,9,$calc(%y +1))
    while (%z <= 8) { if ($kc(%z,%x)) { break } | var %select = %select $draw+select(%x,%z) | inc %z }
    if ($left($hget(chess.board,$+(%z,%x)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%x,%z) }

    ; :: LEFT-UP
    var %sx = $iif(%x == 1,0,$calc(%x -1))
    var %sy = $iif(%y == 1,0,$calc(%y -1))
    while (%sx >= 1) && (%sy >= 1) { if ($kc(%sy,%sx)) { break } | var %select = %select $draw+select(%sx,%sy) | dec %sx | dec %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%sx,%sy) }

    ; :: LEFT-DOWN
    var %sx = $iif(%x == 1,0,$calc(%x -1))
    var %sy = $iif(%y == 8,9,$calc(%y +1))
    while (%sx >= 1) && (%sy <= 8) { if ($kc(%sy,%sx)) { break } | var %select = %select $draw+select(%sx,%sy) | dec %sx | inc %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%sx,%sy) }

    ; :: RIGHT-UP
    var %sx = $iif(%x == 8,9,$calc(%x +1))
    var %sy = $iif(%y == 1,0,$calc(%y -1))
    while (%sx <= 8) && (%sy >= 1) { if ($kc(%sy,%sx)) { break } | var %select = %select $draw+select(%sx,%sy) | inc %sx | dec %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%sx,%sy) }

    ; :: RIGHT-DOWN
    var %sx = $iif(%x == 8,9,$calc(%x +1))
    var %sy = $iif(%y == 8,9,$calc(%y +1))
    while (%sx <= 8) && (%sy <= 8) { if ($kc(%sy,%sx)) { break } | var %select = %select $draw+select(%sx,%sy) | inc %sx | inc %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) || (%king_check) { var %select = %select $draw+select(%sx,%sy) }

    if (!%king_check) { hadd chess.info current_selections $iif(%select,$v1,99) }
    else { hadd chess.info threat_zone $hget(chess.info,threat_zone) %select }
    return
  }

  ; KNIGHT
  elseif (%piece = knight) {

    var %x+1 = $iif(%x == 8,9,$calc(%x +1))
    var %x-1 = $iif(%x == 1,0,$calc(%x -1))
    var %x+2 = $iif(%x == 8,9,$calc(%x +2))
    var %x-2 = $iif(%x == 1,0,$calc(%x -2))
    var %y+1 = $iif(%y == 8,9,$calc(%y +1))
    var %y-1 = $iif(%y == 1,0,$calc(%y -1))
    var %y+2 = $iif(%y == 8,9,$calc(%y +2))
    var %y-2 = $iif(%y == 1,0,$calc(%y -2))

    ; :: DOWN-2 RIGHT-1
    if (($check_square(%x+1,%y+2,%clr_opponent)) && ($in_board(%x+1,%y+2))) || (%king_check) { var %select = %select $draw+select(%x+1,%y+2) }

    ; :: DOWN-2 LEFT-1
    if (($check_square(%x-1,%y+2,%clr_opponent)) && ($in_board(%x-1,%y+2))) || (%king_check) { var %select = %select $draw+select(%x-1,%y+2) }

    ; :: DOWN-1 RIGHT-2
    if (($check_square(%x+2,%y+1,%clr_opponent)) && ($in_board(%x+2,%y+1))) || (%king_check) { var %select = %select $draw+select(%x+2,%y+1) }

    ; :: DOWN-1 LEFT-2
    if (($check_square(%x-2,%y+1,%clr_opponent)) && ($in_board(%x-2,%y+1))) || (%king_check) { var %select = %select $draw+select(%x-2,%y+1) }

    ; :: UP-2 RIGHT-1
    if (($check_square(%x+1,%y-2,%clr_opponent)) && ($in_board(%x+1,%y-2))) || (%king_check) { var %select = %select $draw+select(%x+1,%y-2) }

    ; :: UP-2 LEFT-1
    if (($check_square(%x-1,%y-2,%clr_opponent)) && ($in_board(%x-1,%y-2))) || (%king_check) { var %select = %select $draw+select(%x-1,%y-2) }

    ; :: UP-1 RIGHT-2
    if (($check_square(%x+2,%y-1,%clr_opponent)) && ($in_board(%x+2,%y-1))) || (%king_check) { var %select = %select $draw+select(%x+2,%y-1) }

    ; :: UP-1 LEFT-2
    if (($check_square(%x-2,%y-1,%clr_opponent)) && ($in_board(%x-2,%y-1))) || (%king_check) { var %select = %select $draw+select(%x-2,%y-1) }

    if (!%king_check) { hadd chess.info current_selections $iif(%select,$v1,99) }
    else { hadd chess.info threat_zone $hget(chess.info,threat_zone) %select }
    return
  }

  ; KING
  elseif (%piece == king) {

    var %x-1 = $iif(%x == 1,0,$calc(%x -1))
    var %y-1 = $iif(%y == 1,0,$calc(%y -1))
    var %x+1 = $iif(%x == 8,9,$calc(%x +1))
    var %y+1 = $iif(%y == 8,9,$calc(%y +1))
    var %xy = $+(%y,%x)

    if  (!%king_check) {
      var %n = 1

      hadd chess.info king_check 1
      while ($hfind(chess.board,$+(%clr_opponent,_,*),%n,w).data) {
        var %s = $v1
        if ($right($hget(chess.board,%s),-2) != king) { chess_piece_options_rec $hget(chess.board,%s) $mid(%s,2,1) $mid(%s,1,1) }
        inc %n
      }
      hdel chess.info king_check
    }

    ; :: RIGHT
    if ($check_square(%x+1,%y)) && ($in_board(%x+1,%y)) && (!$istok($hget(chess.info,threat_zone),$+(%y,%x+1),32)) { 
      var %select = %select $draw+select(%x+1,%y) 
    }

    ; :: LEFT
    if ($check_square(%x-1,%y)) && ($in_board(%x-1,%y)) && (!$istok($hget(chess.info,threat_zone),$+(%y,%x-1),32)) { var %select = %select $draw+select(%x-1,%y) }

    ; :: UP
    if ($check_square(%x,%y-1)) && ($in_board(%x,%y-1)) && (!$istok($hget(chess.info,threat_zone),$+(%y-1,%x),32)) { var %select = %select $draw+select(%x,%y-1) }

    ; :: DOWN
    if ($check_square(%x,%y+1)) && ($in_board(%x,%y+1)) && (!$istok($hget(chess.info,threat_zone),$+(%y+1,%x),32)) { var %select = %select $draw+select(%x,%y+1) }

    ; :: LEFT-UP
    if ($check_square(%x-1,%y-1)) && ($in_board(%x-1,%y-1)) && (!$istok($hget(chess.info,threat_zone),$+(%y-1,%x-1),32)) { var %select = %select $draw+select(%x-1,%y-1) }

    ; :: LEFT-DOWN
    if ($check_square(%x-1,%y+1)) && ($in_board(%x-1,%y+1)) && (!$istok($hget(chess.info,threat_zone),$+(%y+1,%x-1),32)) { var %select = %select $draw+select(%x-1,%y+1) }

    ; :: RIGHT-UP
    if ($check_square(%x+1,%y-1)) && ($in_board(%x+1,%y-1)) && (!$istok($hget(chess.info,threat_zone),$+(%y-1,%x+1),32)) { var %select = %select $draw+select(%x+1,%y-1) }

    ; :: RIGHT-DOWN
    if ($check_square(%x+1,%y+1)) && ($in_board(%x+1,%y+1)) && (!$istok($hget(chess.info,threat_zone),$+(%y+1,%x+1),32)) { var %select = %select $draw+select(%x+1,%y+1) }

    ; :: Castling
    if (!$hget(chess.info,king_moved)) {
      var %iy = 8
      var %lxy = $+(%iy,1)
      var %rxy = $+(%iy,8)

      if ($castling_left(%lxy,%iy,%clr_own)) { 
        var %select = %select $draw+select(1,%iy) 
        hadd chess.info castling 1
      }
      if ($castling_right(%rxy,%iy,%clr_own)) {
        var %select = %select $draw+select(8,%iy) 
        hadd chess.info castling 1
      }      
    }

    hdel chess.info threat_zone

    if (!%king_check) { hadd chess.info current_selections $iif(%select,$v1,99) }
    else { hadd chess.info threat_zone $hget(chess.info,threat_zone) %select }

    return
  }

}

alias -l kc {
  if ($hget(chess.info,king_check)) {
    if ($right($hget(chess.board,$+($1,$2)),-2) != king) && ($hget(chess.board,$+($1,$2))) { return $true }
  } 
  elseif ($hget(chess.board,$+($1,$2))) {
    return $true
  }
}

alias castling_left {
  if ($hget(chess.info,clr_own) == w) {
    if (!$hget(chess.info,left_rook_moved)) && ($left($hget(chess.board,$1),1) == $3) && (!$hget(chess.board,$+($2,2))) && (!$hget(chess.board,$+($2,3))) && (!$hget(chess.board,$+($2,4))) && (!$istok($hget(chess.info,threat_zone),$+($2,2),32)) && (!$istok($hget(chess.info,threat_zone),$+($2,3),32)) && (!$istok($hget(chess.info,threat_zone),$+($2,4),32)) && (!$hget(chess.info,check)) {
      return $true
    }
  }
  else {
    if (!$hget(chess.info,left_rook_moved)) && ($left($hget(chess.board,$1),1) == $3) && (!$hget(chess.board,$+($2,2))) && (!$hget(chess.board,$+($2,3))) && (!$istok($hget(chess.info,threat_zone),$+($2,2),32)) && (!$istok($hget(chess.info,threat_zone),$+($2,3),32)) && (!$hget(chess.info,check)) {
      return $true
    }
  }
}

alias castling_right {
  if ($hget(chess.info,clr_own) == w) {
    if (!$hget(chess.info,right_rook_moved)) && ($left($hget(chess.board,$1),1) == $3) && (!$hget(chess.board,$+($2,6))) && (!$hget(chess.board,$+($2,7))) && (!$istok($hget(chess.info,threat_zone),$+($2,6),32)) && (!$istok($hget(chess.info,threat_zone),$+($2,7),32)) && (!$hget(chess.info,check)) {
      return $true
    }
  }
  else {
    if (!$hget(chess.info,right_rook_moved)) && ($left($hget(chess.board,$1),1) == $3) && (!$hget(chess.board,$+($2,6))) && (!$hget(chess.board,$+($2,7))) && (!$istok($hget(chess.info,threat_zone),$+($2,5),32)) && (!$istok($hget(chess.info,threat_zone),$+($2,6),32)) && (!$istok($hget(chess.info,threat_zone),$+($2,7),32)) && (!$hget(chess.info,check)) {
      return $true
    }
  }
}

;; SOCKETS, msg, notice

#chess.n off
on ^*:notice:chess_game *:?:{
  if ($nick == $hget(chess.info,opponent)) { parse_incoming $2- | haltdef }
}
on ^*:text:chess_game *:?:{
  if ($nick == $hget(chess.info,opponent)) { parse_incoming $2- | haltdef }
}
#chess.n end

alias start_server {
  if ($hget(chess.info,con_type) != irc) {
    sockclose chess_connect
    socklisten chess_connect 6666
    hadd chess.info init 1
  }
  hadd chess.info clr_own w 
  hadd chess.info mode mp 
  hadd chess.info own_turn 1
  drawtext -ro @chess 16749691 verdana 22 60 $iif($hget(chess.options,size) == 100,560,380) waiting for other player...
}

alias -l connect_to_server {
  sockopen chess %chess.ip %chess.port
}

alias -l chess_send { 
  if ($hget(chess.info,con_type) == irc) { 
    var %m = $iif($hget(chess.options,send_method),$v1,msg)
    %m $hget(chess.info,opponent) chess_game $1- 
  }
  else { sockwrite -n chess $1- }
}

on *:socklisten:chess_connect:{
  chess_initiate
  print_info light_blue You start.
  sockaccept chess
  chess_send init $me
}

on *:sockopen:chess:{ 
  chess_initiate 
  chess_send init $me 
}

on *:sockread:chess:{ 
  var %t
  sockread %t 
  parse_incoming %t
}

on *:sockclose:chess:{
  print_info red $hget(chess.info,opponent) disconnected.
}

alias -l parse_incoming {
  if ($active != chess) && ($1 != cmsg) { flash @chess | titlebar @chess your turn! }
  tokenize 32 $1-

  if ($1 == init) { 
    hadd chess.info opponent $2
    if (!$hget(chess.info,own_turn)) { print_info light_blue $2 starts. }
    if ($hget(chess.info,con_type) == irc) && (!$hget(chess.info,init)) {
      hadd chess.info init 1      
      chess_initiate
      print_info light_blue You start.
      chess_send init $me
    }
  }
  elseif ($1 == move) { 
    hadd chess.info own_turn 1 
    hadd chess.info opponent_move 1

    var %last.xy = $2
    var %last.x = $mid(%last.xy,2,1)
    var %last.y = $mid(%last.xy,1,1)

    var %xy = $3
    var %x = $mid(%xy,2,1)
    var %y = $mid(%xy,1,1)

    drawrect -rf @chess $get_color(%last.x,%last.y) 0 $get_square(%last.x) $get_square(%last.y) $hget(chess.options,size) $hget(chess.options,size)
    if ($hget(chess.board,%last.xy)) { draw_piece $get_square(%x) $get_square(%y) $v1 $get_color(%x,%y) }
    print_info light_blue Your turn.
    if ($hget(chess.board,%xy)) { hadd chess.info take 1 }
    .echo -gq $chess_move(%last.xy,->,%xy)
    draw_selection %last.x %last.y light_blue
    draw_selection %x %y yellow
    .timerclrlast $+ %xy 1 5 clear_selections %last.xy %xy
  } 
  elseif ($1 == load) {
    print_info light_blue $hget(chess.info,opponent) loaded a game: $2 with $3
  }
  elseif ($1 == cmsg) {
    print_info yellow msg: $2-
  }
  elseif ($1 == disconnect) {
    print_info red $hget(chess.info,opponent) disconnected.
  }
  elseif ($1 == switch) {
    hadd chess.info opponent_move 1 
    print_info light_blue Your turn.
    if ($hget(chess.board,$4)) { hadd chess.info take 1 }
    switch_piece $2-4
    clear_selections $4
    hadd chess.info own_turn 1
  }
  elseif ($1 == castling) { 
    print_info light_blue Your turn.
    hadd chess.info opponent_move 1
    chess_castling $2-4 1
    hadd chess.info own_turn 1
  }
}

; LOGGING


alias -l log_show {
  window -C @chess $window(@chess).x $window(@chess).y $calc($window(@chess).w $1) $window(@chess).h
}

alias -l chess_log {
  if ($2 != 0-0) && ($2 != 0-0-0) {
    var %x.from = $mid($2,2,1)
    var %x.to = $mid($3,2,1)
    var %y.from = $mid($2,1,1)
    var %y.to = $mid($3,1,1)

    if ($hget(chess.info,clr_own) == w) { 
      var %y.from = $calc(9 - %y.from)
      var %y.to = $calc(9 - %y.to)
    }
    else { 
      var %x.from = $calc(9 - %x.from)
      var %x.to = $calc(9 - %x.to)
    }

    var %x.from = $gettok(a b c d e f g h,%x.from,32)
    var %x.to = $gettok(a b c d e f g h,%x.to,32)

    var %from = $+(%x.from,%y.from)
    var %to = $+(%x.to,%y.to)
    var %p = $replace($4,pawn,P,king,K,queen,Q,knight,N,bishop,B,rook,R)
    if ($hget(chess.options,log_format) == 1) { var %l = $+(%p,%from,$iif((x isin $5) || ($hget(chess.info,log_ep)),x,-),%to,$iif(s isin $5,$replace($6,pawn,P,king,K,queen,Q,knight,N,bishop,B,rook,R))) $+ $remove($5,x,s) $iif($hget(chess.info,log_ep),e.p.) }
    else { var %l = %p $upper(%from) $+ -> $+ $upper(%to) $iif(s isin $5,$replace($6,pawn,P,king,K,queen,Q,knight,N,bishop,B,rook,R))) $iif((x isin $5) || ($hget(chess.info,log_ep)),take) $replace($remove($5,x,s),+,check) $iif($hget(chess.info,log_ep),e.p.)  }  
  }

  else { var %l = $2 $+ $3 }
  print_last_move light_blue %l
  print_log $iif($1 == w,white,light_blue) %l
}

alias -l print_last_move {
  var %z = $width($2-,courier new,16)
  var %y = $calc($iif($hget(chess.options,size) == 100,820,500) - %z)
  drawrect -rf @chess 3684408 0 $iif($hget(chess.options,size) == 100,600,280) $iif($hget(chess.options,size) == 100,825,505) 225 20 | drawtext -ro @chess $clr_replace($1) "Courier New" 16 %y $iif($hget(chess.options,size) == 100,825,505) $2-
}

alias -l print_log {
  write chess\temp.log $1-
  if (!$hget(chess.info,log_shown)) { return }
  hinc chess.info log_lines
  var %l = $hget(chess.info,log_lines)
  if (%l > $iif($hget(chess.options,size) == 100,40,24)) { drawscroll @chess 0 -20 $iif($hget(chess.options,size) == 100,840,520) 20 200 $iif($hget(chess.options,size) == 100,840,520) }

  drawtext -ro @chess $clr_replace($1) "Courier New" 16 $iif($hget(chess.options,size) == 100,840,520) $calc(0+(20 * $iif(%l <= $iif($hget(chess.options,size) == 100,40,24),%l,$v2) )) $2-
}

alias -l filter_log {
  tokenize 32 $1
  hinc chess.info log_lines
  var %l = $hget(chess.info,log_lines)

  if (%l > $iif($hget(chess.options,size) == 100,40,24)) { drawscroll @chess 0 -20 $iif($hget(chess.options,size) == 100,840,520) 20 200 $iif($hget(chess.options,size) == 100,840,520) }

  drawtext -ro @chess $clr_replace($1) "Courier New" 16 $iif($hget(chess.options,size) == 100,840,520) $calc(0+(20 * $iif(%l <= $iif($hget(chess.options,size) == 100,40,24),%l,$v2) )) $2-
}

alias -l log_save {
  var %f = $+(chess/,$asctime(yyyy-mm-dd-hhnnss),-,$iif($hget(chess.info,mode) == sp,singleplayer,$hget(chess.info,opponent)),.log)
  filter -ff chess\temp.log %f
}

; DIALOGS


alias -l connect_dialog { .echo -gq $$dialog(chess_connect,chess_connect) }

dialog -l chess_connect {
  title "Create chess connection"
  size -1 -1 275 70
  option pixels

  tab "Sockets",  11, -1 -1 277 202
  tab "IRC", 12, -1 -1 277 202

  text "IP", 1, 7 25 100 20, tab11
  text "PORT", 2, 111 25 100 20, tab11
  edit "", 3, 5 42 100 20, tab11
  edit "", 4, 108 42 100 20, tab11
  button "connect", 5, 211 41 60 22,default


  text "IRC-nick to connect to", 8, 7 25 150 20, tab12
  edit "", 9, 5 42 100 20 , tab12
}

on 1:dialog:chess_connect:init:*:{
  did -a $dname 3 %chess.ip
  did -a $dname 4 $iif(%chess.port,$v1,6666)
}

on 1:dialog:chess_connect:sclick:5:{
  if ($dialog($dname).tab == 11) {
    set %chess.ip $did($dname,3)
    set %chess.port $did($dname,4)
    hadd chess.info init 1 | hadd chess.info clr_own b | hadd chess.info mode mp | hadd chess.info last_moved b
    dialog -x chess_connect
    connect_to_server
  }
  else {
    hadd chess.info init 1 | hadd chess.info clr_own b | hadd chess.info mode mp | hadd chess.info last_moved b | hadd chess.info opponent $did($dname,9)
    dialog -x chess_connect
    hadd chess.info con_type irc
    chess_send init $me
    chess_initiate
    .enable #chess.n
  }
}

dialog -l chess_send_pm {
  title "Send a message"
  size -1 -1 275 50
  option pixels

  text "", 1, 7 5 250 20,
  edit "", 2, 5 25 200 20,
  button "send" 3, 211 25 60 22,default
}

on 1:dialog:chess_send_pm:init:*:{
  did -a $dname 1 Send a message to $hget(chess.info,opponent)
}

on 1:dialog:chess_send_pm:sclick:3:{
  dialog -x chess_send_pm
  chess_send cmsg $did($dname,2)
}

dialog -l chess_getimg {
  title "Missing files"
  size -1 -1 275 70
  option pixels

  text "The file pieces.png doesn't seem to exist in your chess-directory, download it?", 1, 7 5 270 30,
  text "", 2, 7 50 250 20
  button "download" 3, 211 45 60 22,default
}

on 1:dialog:chess_getimg:sclick:3:{
  if (!$hget(chess.info,retry)) { getimg | did -ra $dname 2 downloading... }
  elseif ($hget(chess.info,retry) < 5) { getimg }
  else { dialog -x $dname }
}

alias -l server_dialog { .echo -gq $$dialog(chess_server,chess_server) }

dialog -l chess_server {
  title "Start a chess server"
  size -1 -1 275 70
  option pixels

  tab "Sockets",  11, -1 -1 277 202
  tab "IRC", 12, -1 -1 277 202

  text "Start a socket connection", 1, 7 25 200 20, tab11
  button "start", 2, 5 41 60 22,default tab11

  text "Wait for a connection from nick...", 3, 7 25 200 20, tab12
  edit "", 4, 5 42 100 20 , tab12
  button "start", 5, 108 41 60 22,default tab12
}

on 1:dialog:chess_server:init:*:{
  did -a $dname 4 $iif(%chess.nick,$v1)
}

on 1:dialog:chess_server:sclick:2:{
  start_server
  dialog -x $dname
}

on 1:dialog:chess_server:sclick:5:{
  hadd chess.info con_type irc
  hadd chess.info opponent $did($dname,4)
  .enable #chess.n
  start_server 
  set %chess.nick $did($dname,4)
  dialog -x $dname
}

dialog choose_piece {
  title "Chess - choose new piece"
  size -1 -1 422 130
  option pixels

  text "Select a new piece.",5, 7 5 417 20
  button "Queen" 1, 5 25 100 100
  button "Rook" 2, 108 25 100 100
  button "Bishop" 3, 211 25 100 100
  button "Knight" 4, 314 25 100 100
}

on 1:dialog:choose_piece:sclick:1,2,3,4:{
  set %newpiece $+($hget(chess.info,clr_own),_,$gettok(queen rook bishop knight,$did,32))
  dialog -x choose_piece
}

dialog -l chess_options {
  title "Chess options"
  size -1 -1 400 400
  option pixels

  text "Logging format", 1, 7 8 100 20
  combo 2, 110 5 200 20,drop

  text "Square size (pixels)", 3, 7 30 100 20
  combo 4, 110 27 200 20,drop

  text "IRC send method", 5, 7 52 100 20
  combo 6, 110 49 200 20,drop

  text "Selection frames", 7, 7 74 100 20
  check "" 8, 110 71 20 20,

  button "save", 10, 330 370 60 22,ok
}

on 1:dialog:chess_options:init:*:{
  did -a $dname 2 International (Pe2xf1Q+)
  did -a $dname 2 New (P E2->F1 Q take+check)
  did -c $dname 2 $iif($hget(chess.options,log_format),$v1,1)

  did -a $dname 4 100
  did -a $dname 4 60
  did -c $dname 4 $iif($hget(chess.options,size) == 100,1,2)

  did -a $dname 6 msg
  did -a $dname 6 notice
  did -c $dname 6 $iif($hget(chess.options,send_method) == msg,1,2)

  if ($hget(chess.options,frames)) { did -c $dname 8 }
}

on 1:dialog:chess_options:sclick:10:{
  hadd chess.options log_format $did($dname,2).sel
  if ($did($dname,4).seltext != $hget(chess.options,size)) { hadd chess.options size $did($dname,4).seltext | .timerrestart 1 0 chess_restart }
  if ($did($dname,8).state == 1) { hadd chess.options frames 1 }
  else { hdel chess.options frames }
  hadd chess.options send_method $did($dname,6)

  hsave chess.options chess/options.hsh
}

; FETCH IMAGE
alias getimg { 
  if (!$exists(chess)) { mkdir chess }
  .remove $qt($mircdirchess/pieces.png) 
  sockclose getimg 
  sockopen getimg lost.kapsi.fi 80 
}
on *:sockopen:getimg:{ 
  sockwrite -nt getimg GET /cail/pieces.png HTTP/1.1 
  sockwrite -nt getimg Host: lost.kapsi.fi
  sockwrite -nt getimg Connection: close
  sockwrite -nt getimg $crlf 
}
on *:sockread:getimg:{ 
  if (!$sock(getimg).mark) { 
    var %t
    sockread %t
    if ($gettok(%t,1,32) == Content-Length:) { var %content_len = $gettok(%t,2,32) }
  }
  if (!%t) { sockmark getimg $iif(%content_len,$v1,1) }
  if ($sock(getimg).mark) {
    sockread -f &img
    bwrite $qt($mircdirchess/pieces.png) -1 &img
  }
}
on *:sockclose:getimg:{ 
  if ($file($qt($mircdirchess/pieces.png)) == $sock(getimg).mark) || ($sock(getimg).mark == 1) { dialog -x chess_getimg }
  elseif ($hget(chess.info,retry) <= 5) { hinc chess.info retry | did chess_getimg 2 Error, trying again... ( $+ $hget(chess.info,retry) $+ ) | .remove $qt($mircdirchess/pieces.png) | getimg }
  else { did chess_getimg 2 5 retries gone, try again later }
  unset %content_len
}