Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: Limbo: Infernal Chess

jalski [27.03.2011 18:44:58]

#

Infernal Chess on kahden pelattava verkkopelitoteutus shakista Infernolle Limbo-ohjelmointikielellä.

Infernal Chess "äksönissä"

Lataa koodipaketti grafiikkatiedostoineen täältä

Lisään tarvittaessa kommentteja, jos löytyy aiheesta kiinnostuneita.

#
# Infernal Chess v. 0.1
#
# Just another shitty game by jalski
#
# Send comments and insults to: jali.heinonen@gmail.com
#
# Written in a hurry, so it may not be that great yet...
#    But it's free...
#      So, stop whining about it...
#
implement Chess;

include "sys.m";
   sys: Sys;
   Dir: import sys;
   Connection : import Sys;
include "draw.m";
   draw: Draw;
   Screen, Display, Image, Context, Point, Rect: import draw;

include "tk.m";
   tk: Tk;
   Toplevel: import tk;

include "tkclient.m";
   tkclient: Tkclient;
   Hide: import tkclient;

include "dialog.m";
   dialog : Dialog;


Chess : module
{
   init: fn(ctxt: ref Draw->Context, argv: list of string);
};

PORT : con "2000";
WINBUT : con Hide;
BSZ : con 8;
BSZI : con BSZ + 2;

TILEX : con 45;
TILEY : con 45;

EMPTY2, PLAYER1, PLAYER2 : con iota;

WHITE : con 1;
BLACK : con -1;

EMPTY, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING, BORDER : con iota;

# board[row][column]
chessboard := array  [BSZI] of
      {
         array [BSZI] of { BORDER, BORDER, BORDER,  BORDER , BORDER, BORDER, BORDER , BORDER , BORDER, BORDER },
         array [BSZI] of { BORDER, ROOK  , KNIGHT,  BISHOP , KING ,  QUEEN , BISHOP , KNIGHT , ROOK  , BORDER },
         array [BSZI] of { BORDER, PAWN  , PAWN   , PAWN   , PAWN  , PAWN  , PAWN   , PAWN   , PAWN  , BORDER },
         array [BSZI] of { BORDER, EMPTY , EMPTY  , EMPTY  , EMPTY , EMPTY , EMPTY  , EMPTY  , EMPTY , BORDER },
         array [BSZI] of { BORDER, EMPTY , EMPTY  , EMPTY  , EMPTY , EMPTY , EMPTY  , EMPTY  , EMPTY , BORDER },
         array [BSZI] of { BORDER, EMPTY , EMPTY  , EMPTY  , EMPTY , EMPTY , EMPTY  , EMPTY  , EMPTY , BORDER },
         array [BSZI] of { BORDER, EMPTY , EMPTY  , EMPTY  , EMPTY , EMPTY , EMPTY  , EMPTY  , EMPTY , BORDER },
         array [BSZI] of { BORDER, -PAWN , -PAWN  , -PAWN  , -PAWN , -PAWN , -PAWN  , -PAWN  , -PAWN , BORDER },
         array [BSZI] of { BORDER, -ROOK , -KNIGHT, -BISHOP, -KING , -QUEEN, -BISHOP, -KNIGHT, -ROOK , BORDER },
         array [BSZI] of { BORDER, BORDER, BORDER,  BORDER , BORDER, BORDER, BORDER , BORDER , BORDER, BORDER }
      };


ctxt: ref Draw->Context;
mainwin : ref Tk->Toplevel;

display : ref Display;
buffer : ref Image;
board_img : ref Image;
colour := array [10] of ref Image;

mark1, mark1m : ref Image;
mark2, mark2m : ref Image;

wpawn, wpawnm : ref Image;
wknight, wknightm : ref Image;
wking, wkingm : ref Image;
wqueen, wqueenm : ref Image;
wrook, wrookm : ref Image;
wbishop, wbishopm : ref Image;
bking, bkingm : ref Image;
bqueen, bqueenm : ref Image;
bbishop, bbishopm : ref Image;
brook, brookm : ref Image;
bpawn, bpawnm : ref Image;
bknight, bknightm : ref Image;

workerpid : int;

cmdch : chan of string;
gamecmdch : chan of string;
localcmdch : chan of string;
remotecmdch : chan of string;

lambda := 1;


init(xctxt: ref Draw->Context, argv: list of string)
{
   sys  = load Sys Sys->PATH;

   if(len argv != 2) {
      sys->fprint(sys->fildes(2), "usage: %s nickname\n", hd argv);
       raise "fail:bad usage";
   }

   if (len hd tl argv > 12) {
      sys->fprint(sys->fildes(2), "error: nickname: %s too long, must be 12 characters max.\n", hd tl argv);
       raise "fail:nickname too long";
   }

   if (xctxt == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: no window context\n");
      raise "fail:bad context";
   }

   ctxt = xctxt;
   display = ctxt.display;

   draw = load Draw Draw->PATH;
   tk   = load Tk   Tk->PATH;
   tkclient = load Tkclient Tkclient->PATH;
   dialog = load Dialog Dialog->PATH;

   sys->pctl(Sys->NEWPGRP, nil);

   board := array[BSZI] of { * => array[BSZI] of {* => EMPTY} };
   init_board(board);

   tkclient->init();
   dialog->init();

   wmctl : chan of string;
   (mainwin, wmctl) = tkclient->toplevel(ctxt, nil, "Infernal Chess v. 0.1", WINBUT);
   if(mainwin == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: creation of toplevel window failed\n");
      raise "fail:creation of toplevel window failed";
   }

   gamecmdch = chan of string;

   cmdch = chan of string;
   tk->namechan(mainwin, cmdch, "cmd");

   localcmdch = chan of string;
   tk->namechan(mainwin, localcmdch, "pcmd");

   remotecmdch = chan of string;

   center(mainwin);
   tkclient->onscreen(mainwin, "exact");
   tkclient->startinput(mainwin, "kbd"::"ptr"::nil);

   load_images();
   display_board();

   for(;;)
      alt {
      s := <- mainwin.ctxt.kbd =>
         tk->keyboard(mainwin, s);

      s := <- mainwin.ctxt.ptr =>
         tk->pointer(mainwin, *s);

      s := <- mainwin.ctxt.ctl or
      s = <- mainwin.wreq or
      s = <- wmctl =>
         case s {
            "exit" =>
               fd := sys->open("#p/" + string workerpid +"/ctl", sys->OWRITE);
               if(fd != nil)
                  sys->fprint(fd, "kill");

               tkclient->wmctl(mainwin, "exit");

            * =>
               tkclient->wmctl(mainwin, s);
         }

      menucmd := <- cmdch =>
         case menucmd {
            "host" =>
               (n, conn) := sys->announce("tcp!*!" + PORT);
               if (n < 0) {
                  cmd(mainwin,".ft.ls configure -text {Hosting of a game failed}");
                  cmd(mainwin, "update");
               }
               else {
                  spawn listenthread(conn, board, hd tl argv);

                  cmd(mainwin,".f.menu.gm entryconfigure 0 -state disabled");
                  cmd(mainwin,".f.menu.gm entryconfigure 1 -state disabled");
                  cmd(mainwin, ".p1name configure -text " + hd tl argv);
                  buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                  draw_pieces(board, WHITE);
                  cmd(mainwin,".ft.ls configure -text {Waiting for black player}");
                  cmd(mainwin, ".p dirty;update");
               }

            "join" =>
               address := "tcp!" + dialog->getstring(ctxt,mainwin.image, "Enter host's address") + "!" + PORT;
               (ok, conn) := sys->dial(address, "");
               if (ok < 0) {
                  cmd(mainwin,".ft.ls configure -text {Connection failed}");
                  cmd(mainwin, "update");
               }
               else {
                  cmd(mainwin,".f.menu.gm entryconfigure 0 -state disabled");
                  cmd(mainwin,".f.menu.gm entryconfigure 1 -state disabled");
                  cmd(mainwin, ".p2name configure -text " + hd tl argv);
                  buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                  draw_pieces(board, BLACK);
                  cmd(mainwin,".ft.ls configure -text {White player's turn. (OPPONENT)}");
                  cmd(mainwin, ".p dirty; update");

                  spawn workerthread(conn, BLACK);
                  spawn runclient(conn, board);
                  message := sys->sprint("NICK %s\r\n", hd tl argv);
                  sys->write(conn.dfd, array of byte message, len array of byte message);

               }

         }

   }

}



runserver(conn : Connection, board : array of array of int)
{
   dummych := chan of string;
   absorb(localcmdch);
   localch := localcmdch;

   a, b, c, d : Point;

   moves : list of Point;
   piece1 := EMPTY;
   piece2 := EMPTY;
   selected := 0;

   wklcf := 0;
   wkscf := 0;

   for(;;)
      alt {
         game := <- gamecmdch =>
            case game {
               "close" =>
                  init_board(board);
                  buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                  draw_pieces(board, WHITE);
                  cmd(mainwin,".ft.ls configure -text {Black player closed the connection}");
                  cmd(mainwin,".f.menu.gm entryconfigure 0 -state normal");
                  cmd(mainwin,".f.menu.gm entryconfigure 1 -state normal");
                  cmd(mainwin, ".p dirty;update");
                  lambda = 1;
                  exit;
            }

         local := <- localch =>
            localch = dummych;

            (nil, tokens) := sys->tokenize(local, " ");
            case hd tokens {
               "M" =>
                  if (selected == 0) {
                     bx := int hd tl tokens / TILEX;
                     by := int hd tl tl tokens / TILEY;

                     p := Point(8 - bx, 8 - by);
                     pt := Point(9, 9);

                     if (lambda * board [p.y][p.x] > 0) {
                        selected = 1;
                        a = p;
                        piece1 = board[a.y][a.x];
                        buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                        draw_mark(pt.sub(p), mark2, mark2m);

                        m1 := movelist(p, board);

                        # en passant
                        if (piece1 == PAWN && a.y == 5) {
                           if (c.y == 7 && d.y == 5 && d.x == a.x - 1 && board[a.y + 1][a.x - 1] == EMPTY && board [d.y][d.x] == -PAWN)
                              m1 = Point(a.x - 1, a.y + 1) :: m1;

                           else if (c.y == 7 && d.y == 5 && d.x == a.x + 1 && board[a.y + 1][a.x + 1] == EMPTY && board [d.y][d.x] == -PAWN)
                              m1 = Point(a.x + 1, a.y + 1) :: m1;
                        }


                        else if (piece1 == KING && (wklcf == 0 || wkscf == 0) && in_check(board) == 0) {
                           if (wklcf == 0)
                              if (board [1][7] == EMPTY && board [1][6] == EMPTY && board [1][5] == EMPTY && board [1][8] == ROOK) {
                                 board [1][4] = EMPTY;
                                 board [1][6] = KING;

                                 if (in_check(board) == 0)
                                    m1 = a.add(Point(2, 0)) :: m1;

                                 board [1][6] = EMPTY;
                                 board [1][4] = KING;
                              }

                           if (wkscf == 0)
                              if (board [1][2] == EMPTY && board [1][3] == EMPTY && board [1][1] == ROOK) {
                                 board [1][4] = EMPTY;
                                 board [1][2] = KING;

                                 if (in_check(board) == 0)
                                    m1 = a.sub(Point(2, 0)) :: m1;

                                 board [1][2] = EMPTY;
                                 board [1][4] = KING;
                              }

                        }

                        m2 : list of Point;

                        while (m1 != nil) {
                           piece2 = board[(hd m1).y][(hd m1).x];
                           (board [a.y][a.x], board[(hd m1).y][(hd m1).x])  = (EMPTY, piece1);

                           if (in_check(board) == 0)
                              m2 = hd m1 :: m2;

                           (board [a.y][a.x], board[(hd m1).y][(hd m1).x])  = (piece1, piece2);

                           m1 = tl m1;

                        }

                        moves = m2;

                        while (m2 != nil) {
                           draw_mark(pt.sub(hd m2), mark1, mark1m);
                           m2 = tl m2;
                        }

                        draw_pieces(board, WHITE);

                        cmd(mainwin, ".p dirty; update");
                        localch = localcmdch;

                     }
                     else
                        localch = localcmdch;

                  }
                  else if (selected == 1) {
                     bx := int hd tl tokens / TILEX;
                     by := int hd tl tl tokens / TILEY;

                     p := Point(8 - bx, 8 - by);
                     pt := Point(9, 9);

                     if ( p.x == a.x && p.y == a.y) {
                        selected = 0;
                        buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                        draw_pieces(board, WHITE);
                        cmd(mainwin, ".p dirty; update");
                        localch = localcmdch;
                        break;
                     }

                     movelist := moves;

                     while (moves != nil) {
                        if ((hd moves).x == p.x && (hd moves).y == p.y) {
                           # en passant and promotion
                           if (piece1 == PAWN) {
                              if (p.x == a.x - 1 || p.x == a.x + 1 && board [p.y][p.x] == EMPTY)
                                 board [d.y][d.x] = EMPTY;

                              else if (p.y == 8)
                                 piece1 = QUEEN;

                           }

                           else if (piece1 == KING) {
                              if (p.x == a.x - 2) {
                                 board [1][1] = EMPTY;
                                 board [1][3] = ROOK;
                              }
                              else if (p.x == a.x + 2) {
                                 board [1][8] = EMPTY;
                                 board [1][5] = ROOK;
                              }
                                 wklcf = 1;
                                 wkscf = 1;
                           }

                           else if (piece1 == ROOK) {
                              if (a.x == 1 && a.y == 1 && wklcf == 0)
                                 wklcf = 1;

                              else if (a.x == 1 && a.y == 8 && wkscf == 0)
                                 wkscf = 1;
                           }

                           b = p;
                           board[b.y][b.x] = piece1;
                           board[a.y][a.x] = EMPTY;

                           message := sys->sprint("M %d %d %d %d\r\n", a.x, a.y, b.x, b.y);
                           wdfd := sys->open(conn.dir + "/data", Sys->OWRITE);
                           sys->write(wdfd, array of byte message, len array of byte message);

                           buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                           draw_pieces(board, WHITE);
                           draw_arrow(pt.sub(a), pt.sub(b));
                           cmd(mainwin, ".p dirty; update");
                           buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                           draw_pieces(board, WHITE);
                           sys->sleep(1000);
                           cmd(mainwin, ".ft.ls configure -text {Black player's turn. (OPPONENT)}");
                           cmd(mainwin, ".p dirty; update");
                           selected = 0;
                           (c, d) = (a, b);
                           lambda = -lambda;

                           if (in_check(board)) {
                              cmd(mainwin, ".ft.ls configure -text {Check!}");

                              if (is_mate(board)) {
                                 cmd(mainwin, ".ft.ls configure -text {Check mate! White player won!}");

                                 fd := sys->open("#p/" + string workerpid +"/ctl", sys->OWRITE);
                                 if(fd != nil)
                                    sys->fprint(fd, "kill");

                                 cmd(mainwin, "update");
                                 exit;
                              }

                              cmd(mainwin, "update");
                           }

                           break;
                        }

                        moves = tl moves;
                     }

                     if (moves == nil) {
                        moves = movelist;
                        localch = localcmdch;
                     }
                     else
                        localch = dummych;


                  }

               * =>
                 localch = dummych;


            }

         remote := <-remotecmdch =>
            (n, tokens) := sys->tokenize(remote, " ");
            if(n >= 5)
               case hd tokens {
                  "M" =>
                     a.x = int hd tl tokens;
                     a.y = int hd tl tl tokens;
                     b.x = int hd tl tl tl tokens;
                     b.y = int hd tl tl tl tl tokens;

                     pt := Point(9, 9);

                     piece1 = board[a.y][a.x];
                     if (piece1 == -PAWN && b.y == 1)
                        piece1 = -QUEEN;

                     # en passant
                     else if (piece1 == -PAWN && a.y == 4) {
                        if (c.y == 2 && d.y == 4 && d.x == a.x - 1 && board [d.y][d.x] == PAWN)
                           board[d.y][d.x] = EMPTY;

                        else if (c.y == 2 && d.y == 4 && d.x == a.x + 1 && board [d.y][d.x] == PAWN)
                              board[d.y][d.x] = EMPTY;;
                     }


                     else if (piece1 == -KING && a.x == 4 && b.x == 2)
                              (board[8][1], board[8][3]) = (EMPTY, -ROOK);

                     else if (piece1 == -KING && a.x == 4 && b.x == 6)
                              (board[8][8], board[8][5]) = (EMPTY, -ROOK);


                     (board[a.y][a.x], board[b.y][b.x]) = (EMPTY, piece1);


                     buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                     draw_pieces(board, WHITE);
                     draw_arrow(pt.sub(a), pt.sub(b));
                     cmd(mainwin, ".p dirty; update");
                     buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                     draw_pieces(board, WHITE);
                     sys->sleep(1000);

                     cmd(mainwin,".ft.ls configure -text {White player's turn. (YOU)}");
                     cmd(mainwin, ".p dirty; update");

                     (c, d) = (a, b);

                     lambda = -lambda;

                     if (in_check(board)) {
                        cmd(mainwin, ".ft.ls configure -text {Check!}");

                        if (is_mate(board)) {
                           cmd(mainwin, ".ft.ls configure -text {Check mate! Black player won!}");

                           fd := sys->open("#p/" + string workerpid +"/ctl", sys->OWRITE);
                           if(fd != nil)
                           sys->fprint(fd, "kill");

                           cmd(mainwin, "update");
                           exit;
                        }

                        cmd(mainwin, "update");

                     }

                     absorb(localcmdch);
                     localch = localcmdch;

               }

      }

}



runclient(conn : Connection, board : array of array of int)
{
   dummych := chan of string;
   localch := dummych;

   a, b, c, d : Point;

   moves : list of Point;
   piece1 := EMPTY;
   piece2 := EMPTY;
   selected := 0;

   bklcf := 0;
   bkscf := 0;

   for(;;)
      alt {
         game := <- gamecmdch =>
            case game {
               "close" =>
                  init_board(board);
                  buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                  draw_pieces(board, BLACK);
                  cmd(mainwin,".ft.ls configure -text {White player closed the connection}");
                  cmd(mainwin,".f.menu.gm entryconfigure 0 -state normal");
                  cmd(mainwin,".f.menu.gm entryconfigure 1 -state normal");
                  cmd(mainwin, ".p dirty;update");
                  lambda = 1;
                  exit;
            }

         local := <- localch =>
            localch = dummych;

            (nil, tokens) := sys->tokenize(local, " ");
            case hd tokens {
               "M" =>
                  if (selected == 0) {
                     bx := int hd tl tokens / TILEX + 1;
                     by := int hd tl tl tokens / TILEY + 1;

                     p := Point(bx, by);

                     if (lambda * board [p.y][p.x] > 0) {
                        selected = 1;
                        a = p;
                        piece1 = board[p.y][p.x];
                        buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                        draw_mark(p, mark2, mark2m);

                        m1 := movelist(p, board);

                        # en passant
                        if (piece1 == -PAWN && a.y == 4) {
                           if (c.y == 2 && d.y == 4 && d.x == a.x - 1 && board[a.y - 1][a.x - 1] == EMPTY && board [d.y][d.x] == PAWN)
                              m1 = Point(a.x - 1, a.y - 1) :: m1;

                           else if (c.y == 2 && d.y == 4 && d.x == a.x + 1 && board[a.y - 1][a.x + 1] == EMPTY && board [d.y][d.x] == PAWN)
                              m1 = Point(a.x + 1, a.y - 1) :: m1;
                        }

                        else if (piece1 == -KING && (bklcf == 0 || bkscf == 0) && in_check(board) == 0) {
                           if (bklcf == 0)
                              if (board [8][7] == EMPTY && board [8][6] == EMPTY && board [8][5] == EMPTY && board [8][8] == -ROOK) {
                                 board [8][4] = EMPTY;
                                 board [8][6] = -KING;

                                 if (in_check(board) == 0)
                                    m1 = a.add(Point(2, 0)) :: m1;

                                 board [8][6] = EMPTY;
                                 board [8][4] = -KING;
                              }

                           if (bkscf == 0)
                              if (board [8][2] == EMPTY && board [8][3] == EMPTY && board [8][1] == -ROOK) {
                                 board [8][4] = EMPTY;
                                 board [8][2] = -KING;

                                 if (in_check(board) == 0)
                                    m1 = a.sub(Point(2, 0)) :: m1;

                                 board [8][2] = EMPTY;
                                 board [8][4] = -KING;
                              }
                        }

                        m2 : list of Point;

                        while (m1 != nil) {
                           piece2 = board[(hd m1).y][(hd m1).x];
                           (board [p.y][p.x], board[(hd m1).y][(hd m1).x])  = (EMPTY, piece1);

                           if (in_check(board) == 0)
                              m2 = hd m1 :: m2;

                           (board [p.y][p.x], board[(hd m1).y][(hd m1).x])  = (piece1, piece2);

                           m1 = tl m1;

                        }

                        moves = m2;

                        while (m2 != nil) {
                           draw_mark(hd m2, mark1, mark1m);
                           m2 = tl m2;
                        }

                        draw_pieces(board, BLACK);

                        cmd(mainwin, ".p dirty; update");
                        localch = localcmdch;

                     }
                     else
                        localch = localcmdch;

                  }
                  else if (selected == 1) {
                     bx := int hd tl tokens / TILEX + 1;
                     by := int hd tl tl tokens / TILEY + 1;

                     p := Point(bx, by);
                     if ( p.x == a.x && p.y == a.y) {
                        selected = 0;
                        buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                        draw_pieces(board, BLACK);
                        cmd(mainwin, ".p dirty; update");
                        localch = localcmdch;
                        break;
                     }

                     movelist := moves;

                     while (moves != nil) {
                        if ((hd moves).x == p.x && (hd moves).y == p.y) {
                           # en passant and promotion
                           if (piece1 == -PAWN) {
                              if (p.x == a.x - 1 || p.x == a.x + 1 && board [p.y][p.x] == EMPTY)
                                 board [d.y][d.x] = EMPTY;

                              else if (p.y == 1)
                                 piece1 = -QUEEN;
                           }

                           else if (piece1 == -KING) {
                              if (p.x == a.x - 2) {
                                 board [8][1] = EMPTY;
                                 board [8][3] = -ROOK;
                              }
                              else if (p.x == a.x + 2) {
                                 board [8][8] = EMPTY;
                                 board [8][5] = -ROOK;
                              }
                                 bklcf = 1;
                                 bkscf = 1;
                           }

                           else if (piece1 == -ROOK) {
                              if (a.x == 1 && a.y == 8 && bklcf == 0)
                                 bklcf = 1;

                              if (a.x == 8 && a.y == 8 && bkscf == 0)
                                 bkscf = 1;
                           }

                           b = p;
                           board[b.y][b.x] = piece1;
                           board[a.y][a.x] = EMPTY;

                           message := sys->sprint("M %d %d %d %d\r\n", a.x, a.y, b.x, b.y);
                           sys->write(conn.dfd, array of byte message, len array of byte message);

                           buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                           draw_pieces(board, BLACK);
                           draw_arrow(a, b);
                           cmd(mainwin, ".p dirty; update");
                           buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                           draw_pieces(board, BLACK);
                           sys->sleep(1000);
                           cmd(mainwin, ".ft.ls configure -text {White player's turn. (OPPONENT)}");
                           cmd(mainwin, ".p dirty; update");
                           selected = 0;
                           (c, d) = (a, b);
                           lambda = -lambda;

                           if (in_check(board)) {
                              cmd(mainwin, ".ft.ls configure -text {Check!}");

                              if (is_mate(board)) {
                                 cmd(mainwin, ".ft.ls configure -text {Check mate! Black player won!}");

                                 fd := sys->open("#p/" + string workerpid +"/ctl", sys->OWRITE);
                                 if(fd != nil)
                                    sys->fprint(fd, "kill");

                                 cmd(mainwin, "update");
                                 exit;
                              }

                              cmd(mainwin, "update");

                           }

                           break;
                        }

                        moves = tl moves;
                     }

                     if (moves == nil) {
                        localch = localcmdch;
                        moves = movelist;
                     }
                     else
                        localch = dummych;

                  }

               * =>
                 localch = dummych;

            }

         remote := <-remotecmdch =>
            (n, tokens) := sys->tokenize(remote, " ");
            if(n >= 5)
               case hd tokens {
                  "M" =>
                     a.x = int hd tl tokens;
                     a.y = int hd tl tl tokens;
                     b.x = int hd tl tl tl tokens;
                     b.y = int hd tl tl tl tl tokens;

                     piece1 = board[a.y][a.x];
                     if (piece1 == PAWN && b.y == 8)
                        piece1 = QUEEN;

                     # en passant
                     else if (piece1 == PAWN && a.y == 5) {
                        if (c.y == 7 && d.y == 5 && d.x == a.x - 1 && board[d.y][d.x] == -PAWN)
                           board[d.y][d.x] = EMPTY;

                        else if (c.y == 7 && d.y == 5 && d.x == a.x + 1 && board[d.y][d.x] == -PAWN)
                              board[d.y][d.x] = EMPTY;
                     }

                     else if (piece1 == KING && a.x == 4 && b.x == 2)
                              (board[1][1], board[1][3]) = (EMPTY, ROOK);

                     else if (piece1 == KING && a.x == 4 && b.x == 6)
                              (board[1][8], board[1][5]) = (EMPTY, ROOK);


                     (board[a.y][a.x], board[b.y][b.x]) = (EMPTY, piece1);

                     buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                     draw_pieces(board, BLACK);
                     draw_arrow(a, b);
                     cmd(mainwin, ".p dirty; update");
                     buffer.draw(board_img.r, board_img, nil, Point(0, 0));
                     draw_pieces(board, BLACK);
                     sys->sleep(1000);

                     cmd(mainwin, ".ft.ls configure -text {Black player's turn. (YOU)}");
                     cmd(mainwin, ".p dirty; update");

                     (c, d) = (a, b);

                     lambda = -lambda;

                     if (in_check(board))
                     {
                        cmd(mainwin, ".ft.ls configure -text {Check!}");

                        if (is_mate(board))
                        {
                           cmd(mainwin, ".ft.ls configure -text {Check mate! White player won!}");

                           fd := sys->open("#p/" + string workerpid +"/ctl", sys->OWRITE);
                           if(fd != nil)
                              sys->fprint(fd, "kill");

                           cmd(mainwin, "update");
                           exit;
                        }

                        cmd(mainwin, "update");

                     }

                     absorb(localcmdch);
                     localch = localcmdch;

               }

      }

}



center(t: ref Tk->Toplevel)
{
   org: Point;
   ir := tk->rect(t, ".", Tk->Border|Tk->Required);
   org.x = t.screenr.dx() / 2 - BSZ * TILEX / 2;
   org.y = (t.screenr.dy() / 2) - (ir.dy() + (BSZ * TILEY) / 2);

   if (org.y < 0)
      org.y = 0;

   tk->cmd(t, ". configure -x " + string org.x + " -y " + string org.y);
}



draw_mark(p : Point, img : ref Image, mask : ref Image)
{

   p.x = (p.x - 1) * TILEX;
   p.y = (p.y - 1) * TILEY;

   buffer.draw(img.r.addpt(p), img, mask, Point(0, 0));

}



draw_arrow(p1, p2 : Point)
{
   p1.x = p1.x * TILEX - TILEX / 2;
   p1.y = p1.y * TILEY - TILEY / 2;

   p2.x = p2.x * TILEX - TILEX / 2;
   p2.y = p2.y * TILEY - TILEY / 2;

   buffer.line(p1, p2, Draw->Endsquare, Draw->Endarrow, 3, colour[2], Point(0,0));
}



draw_pieces(board : array of array of int, player : int)
{
   p := Point(0, 0);


   if (player == WHITE) {
         for (j := 8; j >= 1; j --) {
            for (i := 8; i >= 1; i --) {
               case board [j][i] {
                  PAWN =>
                     buffer.draw(wpawn.r.addpt(p), wpawn, wpawnm, Point(0, 0));

                  KNIGHT =>
                     buffer.draw(wknight.r.addpt(p), wknight, wknightm, Point(0, 0));

                  KING =>
                     buffer.draw(wking.r.addpt(p), wking, wkingm, Point(0, 0));

                  QUEEN =>
                     buffer.draw(wqueen.r.addpt(p), wqueen, wqueenm, Point(0, 0));

                  ROOK =>
                     buffer.draw(wrook.r.addpt(p), wrook, wrookm, Point(0, 0));

                  BISHOP =>
                     buffer.draw(wbishop.r.addpt(p), wbishop, wbishopm, Point(0, 0));

                  -KING =>
                     buffer.draw(bking.r.addpt(p), bking, bkingm, Point(0, 0));

                  -QUEEN =>
                     buffer.draw(bqueen.r.addpt(p), bqueen, bqueenm, Point(0, 0));

                  -ROOK =>
                     buffer.draw(brook.r.addpt(p), brook, brookm, Point(0, 0));

                  -KNIGHT =>
                     buffer.draw(bknight.r.addpt(p), bknight, bknightm, Point(0, 0));

                  -BISHOP =>
                     buffer.draw(bbishop.r.addpt(p), bbishop, bbishopm, Point(0, 0));

                  -PAWN =>
                     buffer.draw(bpawn.r.addpt(p), bpawn, bpawnm, Point(0, 0));

               }

               p.x += TILEX;

            }

            p.x = 0;
            p.y += TILEY;

         }
   }
   else {
         for (j := 1; j <= BSZ; j ++) {
            for (i := 1; i <= BSZ; i ++) {
               case board [j][i] {
                  PAWN =>
                     buffer.draw(wpawn.r.addpt(p), wpawn, wpawnm, Point(0, 0));

                  KNIGHT =>
                     buffer.draw(wknight.r.addpt(p), wknight, wknightm, Point(0, 0));

                  KING =>
                     buffer.draw(wking.r.addpt(p), wking, wkingm, Point(0, 0));

                  QUEEN =>
                     buffer.draw(wqueen.r.addpt(p), wqueen, wqueenm, Point(0, 0));

                  ROOK =>
                     buffer.draw(wrook.r.addpt(p), wrook, wrookm, Point(0, 0));

                  BISHOP =>
                     buffer.draw(wbishop.r.addpt(p), wbishop, wbishopm, Point(0, 0));

                  -KING =>
                     buffer.draw(bking.r.addpt(p), bking, bkingm, Point(0, 0));

                  -QUEEN =>
                     buffer.draw(bqueen.r.addpt(p), bqueen, bqueenm, Point(0, 0));

                  -ROOK =>
                     buffer.draw(brook.r.addpt(p), brook, brookm, Point(0, 0));

                  -KNIGHT =>
                     buffer.draw(bknight.r.addpt(p), bknight, bknightm, Point(0, 0));

                  -BISHOP =>
                     buffer.draw(bbishop.r.addpt(p), bbishop, bbishopm, Point(0, 0));

                  -PAWN =>
                     buffer.draw(bpawn.r.addpt(p), bpawn, bpawnm, Point(0, 0));

               }

               p.x += TILEX;

            }

            p.x = 0;
            p.y += TILEY;

         }
   }

}



display_board()
{

   cmd(mainwin, "frame .f -bd 1 -relief raised");
   cmd(mainwin, "menubutton .f.menu -text Game -menu .f.menu.gm");
   cmd(mainwin, "menu .f.menu.gm");
   cmd(mainwin, ".f.menu.gm add command -label {host game (White)} -command {send cmd host}");
   cmd(mainwin, ".f.menu.gm add command -label {join game (Black)} -command {send cmd join}");
   cmd(mainwin, "pack .f.menu -side left");
   cmd(mainwin, "pack .f -fill x");

   cmd(mainwin, "frame .fpinfo -bd 1 -relief flat");
   cmd(mainwin, "label .p1 -background white -text ' ");
   cmd(mainwin, "label .p1name -foreground black");
   cmd(mainwin, "label .p2 -background black -text ' ");
   cmd(mainwin, "label .p2name -foreground black");
   cmd(mainwin, "pack .p1 .p1name -in .fpinfo -side left");
   cmd(mainwin, "pack .p2 .p2name -in .fpinfo -side right");
   cmd(mainwin, "pack .fpinfo -fill x");

   cmd(mainwin, "panel .p -bd 3 -relief flat");
   cmd(mainwin, "pack  .p -fill both -expand 1");

   buffer.draw(board_img.r, board_img, nil, Point(0, 0));

   cmd(mainwin, "frame .ft");
   cmd(mainwin, "label .ft.li -text {Status: }");
   cmd(mainwin, "label .ft.ls -text {Not connected}");
   cmd(mainwin, "pack .ft.li .ft.ls -side left -fill x");
   cmd(mainwin, "pack .ft -side bottom -fill x");
   cmd(mainwin, "bind .p  <ButtonRelease> {send pcmd M %x %y}");

   tk->putimage(mainwin, ".p", buffer, nil);
   cmd(mainwin, ".p dirty; update");

}



is_mate(board : array of array of int) : int
{
   piece1 := EMPTY;
   piece2 := EMPTY;

   for (j := 1 ; j <= BSZ; j ++)
      for (i := 1; i <= BSZ; i ++)
         if (lambda * board [j][i] > 0) {
            moves := movelist(Point(i, j), board);

            while (moves != nil) {
               piece1 = board [j][i];
               piece2 = board[(hd moves).y][(hd moves).x];
               (board [j][i], board[(hd moves).y][(hd moves).x])  = (EMPTY, piece1);

               if (in_check(board) == 0) {
                  (board [j][i], board[(hd moves).y][(hd moves).x])  = (piece1, piece2);
                  return 0;
               }

               (board [j][i], board[(hd moves).y][(hd moves).x])  = (piece1, piece2);

               moves = tl moves;
            }

         }

   return 1;
}



in_check(board : array of array of int) : int
{
   moves : list of Point;
   for (j := 1 ; j <= BSZ; j ++)
      for (i := 1; i <= BSZ; i ++) {
         if (lambda * board [j][i] < 0) {
            lambda = -lambda;
            moves = movelist(Point(i, j), board);
            lambda = -lambda;

            while (moves != nil) {
               if (lambda * board [(hd moves).y][(hd moves).x] == KING)
                  return 1;

               moves = tl moves;
            }

         }

      }

   return 0;
}



movelist(p : Point, board : array of array of int) : list of Point
{

   piece := lambda * board[p.y][p.x];

   case piece {
      PAWN =>
         return pawn(p, board);

      ROOK =>
         return rook(p, board);

      BISHOP =>
         return bishop(p, board);

      KNIGHT =>
         return knight(p, board);

      QUEEN =>
         return queen(p, board);

      KING =>
         return king(p, board);

      * =>
         return nil;
   }


}



king(p : Point, board : array of array of int) : list of Point
{
   up := Point(0, -1);
   down := Point(0, 1);
   left := Point(-1, 0);
   right := Point(1, 0);
   upleft := Point(-1, -1);
   upright := Point(1, -1);
   downleft := Point(-1, 1);
   downright := Point(1, 1);

   m : list of Point;

   pos :=  p.add(up);

   if (lambda * board[pos.y][pos.x] <= EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;

   pos =  p.add(down);

   if (lambda * board[pos.y][pos.x] <= EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;

   pos =  p.add(left);

   if (lambda * board[pos.y][pos.x] <= EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;

   pos =  p.add(right);

   if (lambda * board[pos.y][pos.x] <= EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;

   pos =  p.add(upleft);

   if (lambda * board[pos.y][pos.x] <= EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;

   pos =  p.add(upright);

   if (lambda * board[pos.y][pos.x] <= EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;

   pos =  p.add(downleft);

   if (lambda * board[pos.y][pos.x] <= EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;

   pos =  p.add(downright);

   if (lambda * board[pos.y][pos.x] <= EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;

   return m;

}



rook(p : Point, board : array of array of int) : list of Point
{
   up := Point(0, -1);
   down := Point(0, 1);
   left := Point(-1, 0);
   right := Point(1, 0);

   m : list of Point;

   pos := p.add(down);

   while (board[pos.y][pos.x] == EMPTY) {
      m = pos :: m;
      pos = pos.add(down);
   }

   if (lambda * board[pos.y][pos.x] < EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;

   pos = p.add(up);

   while (board[pos.y][pos.x] == EMPTY) {
      m = pos :: m;
      pos = pos.add(up);
   }

   if (lambda * board[pos.y][pos.x] < EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;

   pos = p.add(right);

   while (board[pos.y][pos.x] == EMPTY) {
      m = pos :: m;
      pos = pos.add(right);
   }

   if (lambda * board[pos.y][pos.x] < EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;

   pos = p.add(left);

   while (board[pos.y][pos.x] == EMPTY) {
      m = pos :: m;
      pos = pos.add(left);
   }

   if (lambda * board[pos.y][pos.x] < EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;


   return m;

}




bishop(p : Point, board : array of array of int) : list of Point
{
   upleft := Point(-1, -1);
   upright := Point(1, -1);
   downleft := Point(-1, 1);
   downright := Point(1, 1);

   m : list of Point;

   pos := p.add(downright);

   while (board[pos.y][pos.x] == EMPTY) {
      m = pos :: m;
      pos = pos.add(downright);
   }

   if (lambda * board[pos.y][pos.x] < EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;


   pos = p.add(upleft);

   while (board[pos.y][pos.x] == EMPTY) {
      m = pos :: m;
      pos = pos.add(upleft);
   }

   if (lambda * board[pos.y][pos.x] < EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;


   pos = p.add(upright);

   while (board[pos.y][pos.x] == EMPTY) {
      m = pos :: m;
      pos = pos.add(upright);
   }

   if (lambda * board[pos.y][pos.x] < EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;


   pos = p.add(downleft);

   while (board[pos.y][pos.x] == EMPTY) {
      m = pos :: m;
      pos = pos.add(downleft);
   }

   if (lambda * board[pos.y][pos.x] < EMPTY && board[pos.y][pos.x] != BORDER)
      m = pos :: m;


   return m;

}



queen(p : Point, board : array of array of int) : list of Point
{
   m1 := bishop(p, board);
   m2 := rook(p, board);

   while(m2 != nil) {
      m1 = hd m2 :: m1;
      m2 = tl m2;
   }

   return m1;
}



knight(p : Point, board : array of array of int) : list of Point
{
   twouponeleft := Point(-1, -2);
   twouponeright := Point(1, -2);
   twodownoneleft := Point(-1, 2);
   twodownoneright := Point(1, 2);
   twoleftonedown := Point(-2, 1);
   twoleftoneup := Point(-2, -1);
   tworightonedown := Point(2, 1);
   tworightoneup := Point(2, -1);

   m : list of Point;
   pos : Point;

   if (p.y >= 3) {
      pos = p.add(twouponeleft);

      if (lambda * board[pos.y][pos.x] <= EMPTY)
               m = pos :: m;

      pos = p.add(twouponeright);

      if (lambda * board[pos.y][pos.x] <= EMPTY)
               m = pos :: m;

   }

   if (p.y <= 6) {
      pos = p.add(twodownoneleft);

      if (lambda * board[pos.y][pos.x] <= EMPTY)
               m = pos :: m;

      pos = p.add(twodownoneright);

      if (lambda * board[pos.y][pos.x] <= EMPTY)
               m = pos :: m;

   }

   if (p.x >= 3) {
      pos = p.add(twoleftoneup);

      if (lambda * board[pos.y][pos.x] <= EMPTY)
               m = pos :: m;

      pos = p.add(twoleftonedown);

      if (lambda * board[pos.y][pos.x] <= EMPTY)
               m = pos :: m;

   }

   if (p.x <= 6) {
      pos = p.add(tworightoneup);

      if (lambda * board[pos.y][pos.x] <= EMPTY)
               m = pos :: m;

      pos = p.add(tworightonedown);

      if (lambda * board[pos.y][pos.x] <= EMPTY)
               m = pos :: m;

   }

   return m;
}



pawn(p : Point, board : array of array of int) : list of Point
{
   twoup := Point(0, -2);
   twodown := Point(0, 2);
   up := Point(0, -1);
   down := Point(0, 1);
   upright := Point(1, -1);
   upleft := Point(-1, -1);
   downright := Point(1, 1);
   downleft := Point(-1, 1);

   m : list of Point;
   pos : Point;

   case lambda {
      WHITE =>
         pos = p.add(down);

         if (lambda * board[pos.y][pos.x] == EMPTY) {
            m = pos :: m;

            if (p.y == 2) {
               pos = p.add(twodown);

               if (lambda * board[pos.y][pos.x] == EMPTY)
                  m = pos :: m;

            }

         }


         pos = p.add(downright);

         if (lambda * board[pos.y][pos.x] < EMPTY && board[pos.y][pos.x] != BORDER)
            m = pos :: m;

         pos = p.add(downleft);

         if (lambda * board[pos.y][pos.x] < EMPTY && board[pos.y][pos.x] != BORDER)
            m = pos :: m;

      BLACK =>
         pos = p.add(up);

         if (lambda * board[pos.y][pos.x] == EMPTY) {
            m = pos :: m;

            if (p.y == 7) {
               pos = p.add(twoup);

               if (lambda * board[pos.y][pos.x] == EMPTY)
                  m = pos :: m;

            }

         }

         pos = p.add(upright);

         if (lambda * board[pos.y][pos.x] < EMPTY && board[pos.y][pos.x] != BORDER)
            m = pos :: m;

         pos = p.add(upleft);

         if (lambda * board[pos.y][pos.x] < EMPTY && board[pos.y][pos.x] != BORDER)
            m = pos :: m;

   }

   return m;
}



load_images()
{
   r := Rect((0, 0), (BSZ * TILEX, BSZ * TILEY));
   buffer = display.newimage(r, mainwin.image.chans, 0, Draw->Black);
   if (buffer == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   #colour [0] = display.white;
   #colour [1] = display.black;
   colour [0] = display.color(Draw->Greygreen);
   colour [1] = display.color(Draw->Palegreygreen);
   colour [2] = display.color(Draw->Red);
   colour [3] = display.color(Draw->Magenta);
   colour [4] = display.color(Draw->Paleyellow);
   colour [5] = display.color(Draw->Yellowgreen);
   colour [6] = display.color(Draw->Paleyellow);
   colour [7] = display.color(Draw->Grey);
   colour [8] = display.color(Draw->Greyblue);
   colour [9] = display.color(Draw->Palegreyblue);

   board_img = display.newimage(r, mainwin.image.chans, 0, Draw->Black);
   if (board_img == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   tiler := Rect((0,0), (TILEX, TILEY));


   yscol := 0;
   col := 0;
   p := Point(0, 0);

   for (j := 1; j <= BSZ; j ++) {
      yscol ^= 1;
      col = yscol;
      for (i := 1; i <= BSZ; i ++) {
         board_img.draw(tiler.addpt(p), colour[col], nil, Point(0, 0));

         p.x += TILEX;

         col ^= 1;
      }

      p.x = 0;
      p.y += TILEY;

   }


   mark1 = display.open("./data/mark1.bit");
   if (mark1 == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   mark1m = display.open("./data/mark1m.bit");
   if (mark1m == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   mark2 = display.open("./data/mark2.bit");
   if (mark2 == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   mark2m = display.open("./data/mark2m.bit");
   if (mark2m == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }


   wpawn = display.open("./data/wpawn.bit");
   if (wpawn == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   wpawnm = display.open("./data/wpawnm.bit");
   if (wpawnm == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   wknight = display.open("./data/wknight.bit");
   if (wknight == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   wknightm = display.open("./data/wknightm.bit");
   if (wknightm == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   wking = display.open("./data/wking.bit");
   if (wking == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   wkingm = display.open("./data/wkingm.bit");
   if (wkingm == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   wqueen = display.open("./data/wqueen.bit");
   if (wqueen == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   wqueenm = display.open("./data/wqueenm.bit");
   if (wqueenm == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   wrook = display.open("./data/wrook.bit");
   if (wrook == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   wrookm = display.open("./data/wrookm.bit");
   if (wrookm == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   wbishop = display.open("./data/wbishop.bit");
   if (wbishop == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   wbishopm = display.open("./data/wbishopm.bit");
   if (wbishopm == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   bking = display.open("./data/bking.bit");
   if (bking == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   bkingm = display.open("./data/bkingm.bit");
   if (bkingm == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   bqueen = display.open("./data/bqueen.bit");
   if (bking == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   bqueenm = display.open("./data/bqueenm.bit");
   if (bqueenm == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   brook = display.open("./data/brook.bit");
   if (brook == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   brookm = display.open("./data/brookm.bit");
   if (brookm == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   bknight = display.open("./data/bknight.bit");
   if (bknight == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   bknightm = display.open("./data/bknightm.bit");
   if (bknightm == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   bbishop = display.open("./data/bbishop.bit");
   if (bbishop == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   bbishopm = display.open("./data/bbishopm.bit");
   if (bbishopm == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   bpawn = display.open("./data/bpawn.bit");
   if (bpawn == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

   bpawnm = display.open("./data/bpawnm.bit");
   if (bpawnm == nil) {
      sys->fprint(sys->fildes(2), "Infernal Chess: failed to allocate image\n");
      exit;
   }

}



listenthread(conn : Connection, board : array of array of int, nick : string)
{

   (ok, c) := sys->listen(conn);
   if (ok < 0) {
      sys->fprint(sys->fildes(2), "Server: listen failed\n");
      raise "fail:listen failed";
   }

   spawn workerthread(c, WHITE);
   spawn runserver(c, board);

   wdfd := sys->open(c.dir + "/data", Sys->OWRITE);
   message := sys->sprint("NICK %s\r\n", nick);
   sys->write(wdfd, array of byte message, len array of byte message);

   cmd(mainwin,".ft.ls configure -text {White player's turn. (YOU)}");
   cmd(mainwin, "update");

}



workerthread(conn : Connection, player : int)
{
   workerpid = sys->pctl(0, nil);

   buf := array [1] of byte;
   rdfd := sys->open(conn.dir + "/data", Sys->OREAD);
   output := "";

   while( (n := sys->read(rdfd, buf, len buf ) ) > 0 ) {
      output[len output] = int buf[0];

      if(len output >= 2) {
         if(output[len output - 2:] == "\r\n") {
            if(len output > 7 && output[:5] == "NICK ") {
               (count, nil) := sys->tokenize(output[5:], " ");
               if(count == 1 && len output[5:len output - 2] < 10) {
                  if (player == WHITE)
                     cmd(mainwin, ".p2name configure -text " + output[5:len output - 2]);
                  else
                     cmd(mainwin, ".p1name configure -text " + output[5:len output - 2]);
                  cmd(mainwin, "update");
                  output = "";
               }
            }
            else {
               remotecmdch <- = output[:len output - 2];
               output = "";
            }

         }
      }
      if (len output >= 1024) # line getting a little too long?
         output = "";

   }

   gamecmdch <- = "close";


}



absorb(ch : chan of string)
{
   for(;;) {
      alt {
         <- ch =>
            ;
         * =>
            return;
      }
   }
}



init_board(board : array of array of int)
{
   for (i := 0; i < BSZI; i++)
      for (j := 0; j < BSZI; j++)
         board[i][j] = chessboard[i][j];
}



cmd(win: ref Tk->Toplevel, s: string): string
{
   r := tk->cmd(win, s);
   if (len r > 0 && r[0] == '!') {
      sys->print("error executing '%s': %s\n", s, r[1:]);
   }
   return r;
}

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta