Difference between revisions of "Chess game"

From Scriptwiki
Jump to: navigation, search
m (added saving + loading + a bunch of fixes)
m (a little fix :))
Line 22: Line 22:
 
   if ($hget(chess.board)) { hfree chess.board } | hmake chess.board 64
 
   if ($hget(chess.board)) { hfree chess.board } | hmake chess.board 64
 
   if ($hget(chess.info))  { hfree chess.info } | hmake chess.info 64
 
   if ($hget(chess.info))  { hfree chess.info } | hmake chess.info 64
  ;if ($hget(chess.taken))  { hfree chess.taken } | hmake chess.taken 64
 
 
   
 
   
 
   window -dfpw0C +nft @chess 0 0 840 860  
 
   window -dfpw0C +nft @chess 0 0 840 860  

Revision as of 11:35, 21 March 2007

Screenshot of the gameplay

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
; 
; Chess game with picture windows by Cail at Quakenet -> #help.script
;
; Includes singleplayer and multiplayer.
; In singleplayer mode you move black's and white's in turns.
; Multiplayer was the main idea, and the game uses sockets to start a server and to connect to a server
; Get the pieces at: http://lost.kapsi.fi/cail/chess.zip (images originally from mediawiki, by Wapcaplet)
; After you've put the images of pieces into /mircdir/chess directory, start the game by typing /chess and choose your mode 
; Also support saving and loading the game state, for singleplayer and multiplayer.
;
; TODO:
;  - function to check if a square is attacked
;  - castling-move for king and rook
;  - comments for the code
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

alias chess {
  if ($hget(chess.board)) { hfree chess.board } | hmake chess.board 64
  if ($hget(chess.info))  { hfree chess.info } | hmake chess.info 64

  window -dfpw0C +nft @chess 0 0 840 860 
  drawrect -rf @chess 3684408 0 0 0 840 860

  drawrect -r @chess 65280 1 60 350 300 50
  drawrect -r @chess 65280 1 60 410 300 50
  drawrect -r @chess 65280 1 60 470 300 50

  drawtext -ro @chess 16749691 verdana 22 70 360 single player
  drawtext -ro @chess 16749691 verdana 22 70 420 connect to a server
  drawtext -ro @chess 16749691 verdana 22 70 480 start a server
}

menu @chess {
  sclick: chess_click
  save:chess_save
  $iif($hget(chess.info,init),load):chess_load $dialog(load_table,load_table)
}


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:*:{
  noop $findfile(chess,*board*.save,0,parse_save $1-)
}

alias -l parse_save {
  noop $regex($1-,/\\([^\\]+)_board_(.+)\.save/g) 
  did -a $dname 2 $regml(1) - $regml(2)
}

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

alias -l chess_load {
  hdel -w chess.board *
  hdel -w chess.info *
  hload chess.board $+(chess\,$1,_board_,$3,.save)
  hload chess.info $+(chess\,$1,_info_,$3,.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 100 100
      if ($hget(chess.board,$+(%y,%x))) { draw_piece %dx %dy $v1 $get_color(%x,%y) }
      inc %x
    }  
    inc %y
  }

  if ($hget(chess.info,mode) == mp) {
    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),_board_,$iif($hget(chess.info,mode) == sp,sp,$hget(chess.info,opponent)),.save)
  hsave chess.info $+(chess/,$asctime(yyyy-mm-dd),_info_,$iif($hget(chess.info,mode) == sp,sp,$hget(chess.info,opponent)),.save)
}

alias -l chess_initiate {
  hadd chess.info clr_select red

  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 100 100
      if ($get_piece(%y,%x)) { hadd chess.board $+(%y,%x) $v1 | draw_piece %dx %dy $v1 $get_color(%x,%y) }
      inc %x
    }  
    inc %y
  }
}

alias -l chess_click {
  if (!$inrect($mouse.x,$mouse.y,20,20,800,800)) { return }
  elseif (!$hget(chess.info,init)) { 

    ; SELECT: single player
    if ($inrect($mouse.x,$mouse.y,60,350,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,410,300,50)) { 
      hadd chess.info init 1 | hadd chess.info clr_own b | hadd chess.info mode mp | hadd chess.info last_moved b
      connect_dialog
    }
    ; SELECT: start a server
    elseif ($inrect($mouse.x,$mouse.y,60,470,300,50)) { 
      hadd chess.info init 1 | hadd chess.info clr_own w | hadd chess.info mode mp | hadd chess.info own_turn 1
      start_server | drawtext -ro @chess 16749691 verdana 22 370 480 waiting for other player...
    } 
    return 
  }

  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 = $left($calc($mouse.x -20+100),1) 
  var %y = $left($calc($mouse.y -20+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 = $bw(%y,1,%clr_moved)
  var %xy-1 = $+(%y-1,%x)

  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) { return }   
  }
  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.board,%xy)) { hadd chess.taken $v1 }
    if ($hget(chess.info,en_passant) == %xy-1) && ($left($hget(chess.board,%xy-1),1) != %clr_own) { 
      ;hadd chess.taken $+($hget(chess.board,%xy-1),%xy-1) 1 
      hdel chess.board %xy-1 
      drawrect -rf @chess $get_color(%x,%y-1) 0 $get_square(%x) $get_square(%y-1) 100 100
    }
    hdel chess.info en_passant

    drawrect -rf @chess $get_color(%last.x,%last.y) 0 $get_square(%last.x) $get_square(%last.y) 100 100
    if ($hget(chess.board,%last.xy)) { draw_piece $get_square(%x) $get_square(%y) $v1 $get_color(%x,%y) }
    noop $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) {
      if (!$hget(chess.info,just_switched)) { chess_send move %last.xy %xy }
      print_info light_blue $hget(chess.info,opponent) $+ 's turn
      hdel chess.info own_turn 
    }
    hdel chess.info just_switched  
  }

  ; nothing selected, so we're selecting a piece
  else {
    var %piece = $hget(chess.board,%xy)
    draw_selection %x %y green
    ;draw_piece $get_square(%x) $get_square(%y) %piece $get_color(%x,%y)
    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 {
  drawpic -c @chess $1 $2 0 0 100 100 $+(chess/,$3,_,$iif($4,w,b),.png)
}

alias -l draw_selection {
  drawrect -r @chess $clr_replace($3) 3 $calc($get_square($1) +1) $calc($get_square($2) +1) 98 98
}

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) {
    if ($istok(1 8,$left($3,1),32)) { 
      noop $dialog(choose_piece,choose_piece) 
      switch_piece %newpiece $3 $1 
      if ($hget(chess.info,mode) == mp) { chess_send switch %newpiece $3 $1 } 
      hadd chess.info just_switched 1
      unset %newpiece
      return 
    }
    elseif (%move_len == 2) { hadd chess.info en_passant $3 }
  }
  hadd chess.board $3 %piece
  hdel chess.board $1
  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 %new_piece = $1
  hadd chess.board $2 %new_piece
  hdel chess.board $3

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

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

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

alias -l get_piece {
  if ($istok(1 2 7 8,$1,32)) { 
    if ($1 == 2) { return w_pawn }
    elseif ($1 == 7) { return b_pawn }
    elseif ($1 == 8) { return $gettok(b_rook b_knight b_bishop b_queen b_king b_bishop b_knight b_rook,$2,32) }
    else { return $gettok(w_rook w_knight w_bishop w_queen w_king w_bishop w_knight w_rook,$2,32) }
  }
}

alias -l get_square {
  return $calc((($1 -1) *100) +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) 100 100
      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 830 840 20 | drawtext -ro @chess $clr_replace($1) verdana 16 20 830 $2-
}

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

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

alias -l draw+select {
  draw_selection $1 $2 $hget(chess.info,clr_select) | return $+($2,$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 %piece = $right($1,-2)
  var %clr_own = $left($1,1)
  var %clr_opponent = $iif(%clr_own == w,b,w)
  var %x = $2
  var %y = $3

  ; PAWN
  if (%piece == pawn) { 

    var %y+1 = $fw(%y,1,%clr_own)
    var %y+2 = $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))) {
      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))) { 
      var %select = %select $draw+select(%x-1,%y+1) 
    }
    if (!$hget(chess.board,$+(%y+1,%x))) && (%y+1 <= 8) && (%y+1 > 1) {
      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) }
    }
    hadd chess.info current_selections $iif(%select,$v1,99)
    return
  }

  ; ROOK
  elseif (%piece == rook) {

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

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

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

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

    hadd chess.info current_selections $iif(%select,$v1,99)
    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 ($hget(chess.board,$+(%sy,%sx))) { break } | var %select = %select $draw+select(%sx,%sy) | dec %sx | dec %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) { 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 ($hget(chess.board,$+(%sy,%sx))) { break } | var %select = %select $draw+select(%sx,%sy) | dec %sx | inc %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) { 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 ($hget(chess.board,$+(%sy,%sx))) { break } | var %select = %select $draw+select(%sx,%sy) | inc %sx | dec %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) { 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 ($hget(chess.board,$+(%sy,%sx))) { break } | var %select = %select $draw+select(%sx,%sy) | inc %sx | inc %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) { var %select = %select $draw+select(%sx,%sy) }

    hadd chess.info current_selections $iif(%select,$v1,99)
    return
  }

  ; QUEEN
  elseif (%piece == queen) {

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

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

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

    ; :: DOWN
    var %z = $iif(%y == 8,9,$calc(%y +1))
    while (%z <= 8) { if ($hget(chess.board,$+(%z,%x))) { break } | var %select = %select $draw+select(%x,%z) | inc %z }
    if ($left($hget(chess.board,$+(%z,%x)),1) == %clr_opponent) { 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 ($hget(chess.board,$+(%sy,%sx))) { break } | var %select = %select $draw+select(%sx,%sy) | dec %sx | dec %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) { 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 ($hget(chess.board,$+(%sy,%sx))) { break } | var %select = %select $draw+select(%sx,%sy) | dec %sx | inc %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) { 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 ($hget(chess.board,$+(%sy,%sx))) { break } | var %select = %select $draw+select(%sx,%sy) | inc %sx | dec %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) { 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 ($hget(chess.board,$+(%sy,%sx))) { break } | var %select = %select $draw+select(%sx,%sy) | inc %sx | inc %sy }
    if ($left($hget(chess.board,$+(%sy,%sx)),1) == %clr_opponent) { var %select = %select $draw+select(%sx,%sy) }

    hadd chess.info current_selections $iif(%select,$v1,99)
    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))

    ; :: RIGHT
    if ($check_square(%x+1,%y)) && ($in_board(%x+1,%y)) { var %select = %select $draw+select(%x+1,%y) }

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

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

    ; :: DOWN
    if ($check_square(%x,%y+1)) && ($in_board(%x,%y+1)) { var %select = %select $draw+select(%x,%y+1) }

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

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

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

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

    hadd chess.info current_selections $iif(%select,$v1,99)
    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)) && ($in_board(%x+1,%y+2)) { var %select = %select $draw+select(%x+1,%y+2) }

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

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

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

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

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

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

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

    hadd chess.info current_selections $iif(%select,$v1,99)
    return
  }

}

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

  text "Select a new piece.",5, 7 5 417 20
  icon 1, 5 25 100 100
  icon 2, 108 25 100 100
  icon 3, 211 25 100 100
  icon 4, 314 25 100 100
}

on 1:dialog:choose_piece:init:*:{
  did -g $dname 1 $+(chess/,$hget(chess.info,clr_own),_queen_w.png)
  did -g $dname 2 $+(chess/,$hget(chess.info,clr_own),_rook_w.png)
  did -g $dname 3 $+(chess/,$hget(chess.info,clr_own),_bishop_w.png)
  did -g $dname 4 $+(chess/,$hget(chess.info,clr_own),_knight_w.png)
}


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
}

on *:close:@chess:{
  hfree chess.board
  hfree chess.info
  ;hfree chess.taken

  if ($sock(chess_connect)) { sockclose chess_connect }
  if ($sock(chess)) { sockclose chess }
}

;; socket part

alias -l connect_dialog { noop $dialog(chess_connect,chess_connect) }

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

  text "IP", 1, 7 5 100 20
  text "PORT", 2, 111 5 100 20
  edit "", 3, 5 22 100 20
  edit "", 4, 108 22 100 20
  button "connect", 5, 211 21 60 22,default
}

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:{
  set %chess.ip $did($dname,3)
  set %chess.port $did($dname,4)
  dialog -x chess_connect
  connect_to_server
}

alias start_server {
  sockclose chess_connect
  socklisten chess_connect 6666
}

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

alias -l chess_send { 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 

  if ($gettok(%t,1,32) == init) { 
    hadd chess.info opponent $gettok(%t,2,32)
    if (!$hget(chess.info,own_turn)) { print_info light_blue $gettok(%t,2,32) starts. }
  }
  elseif ($gettok(%t,1,32) == move) { 
    hadd chess.info own_turn 1 
    var %last.xy = $gettok(%t,2,32)
    var %last.x = $mid(%last.xy,2,1)
    var %last.y = $mid(%last.xy,1,1)

    var %xy = $gettok(%t,3,32)
    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) 100 100
    if ($hget(chess.board,%last.xy)) { draw_piece $get_square(%x) $get_square(%y) $v1 $get_color(%x,%y) }
    noop $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
    print_info light_blue Your turn.
  } 
  elseif ($gettok(%t,1,32) == load) {
    print_info light_blue $hget(chess.info,opponent) loaded a game: $gettok(%t,2,32) with $gettok(%t,3,32)
  }
  elseif ($gettok(%t,1,32) == switch) { 
    switch_piece $gettok(%t,2,32) $gettok(%t,3,32) $gettok(%t,4,32)
    clear_selections $gettok(%t,4,32)
    hadd chess.info own_turn 1
    print_info light_blue Your turn.
  }
}

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