samples/games/chess: Fixed exit following game still running confirmation
[sdk] / samples / games / chess / src / chess.ec
1 /****************************************************************************
2    CHESS Game
3
4    Copyright (c) 2001 Jerome Jacovella-St-Louis
5    All Rights Reserved.
6
7    chess.ec - Chess Main Window
8 ****************************************************************************/
9 #ifdef ECERE_STATIC
10 import static "ecere"
11 #else
12 import "ecere"
13 #endif
14 import "chess2D.ec"
15 import "chess3D.ec"
16 import "promotion.ec"
17 import "connect.ec"
18 import "about.ec"
19 import "ai.ec"
20 import "chessutils.ec"
21
22 // --- Definitions ---
23 define APPNAME = "ECERE Chess v0.4";
24 define CHESS_PORT = 7778;
25 define SERVER_COLOR = Black;
26 define CLIENT_COLOR = White;
27
28 // Network Messages
29 enum ChessMessage : byte { NewGame = 1, Position = 2 };
30
31 struct ChessPacket
32 {
33    ChessMessage type;
34    Player player;
35    byte x1,y1,x2,y2;
36    PieceType promotion;
37 };
38
39 ChessApp app;
40
41 class ChessApp : GuiApplication
42 {
43    appName = APPNAME;
44 /*#if defined(__WIN32__)
45    driver = "Direct3D";
46 #else*/
47    driver = "OpenGL";
48 //#endif
49    Chess{};
50
51    void Main()
52    {
53       app = this;
54       GuiApplication::Main();
55    }
56 }
57
58 enum GameAction { newAIGame, newLocalGame, endGame, close, connect, host, stop };
59
60
61 #ifdef HIGH_DPI
62 define stateWidth = 300;
63 define turnWidth = 150;
64 #else
65 define stateWidth = 200;
66 define turnWidth = 100;
67 #endif
68
69 class Chess : Window
70 {
71    background = gray, hasMenuBar = true, hasStatusBar = true,
72    fullRender = true;
73    text = APPNAME,
74 #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
75    hasClose = true, hasMaximize = true, hasMinimize = true,
76    borderStyle = sizable,
77 #endif
78    anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
79
80    bool hosting, local, ai;
81 #ifndef CHESS_NONET
82    Socket sockets[Player];
83
84    ChessService service { port = CHESS_PORT, chess = this };
85 #endif
86
87    MenuItem * driverItems;
88
89    ChessState chessState;
90
91    StatusField stateField { statusBar, width = stateWidth};
92    StatusField turnField { statusBar, width = turnWidth };
93
94    property ChessState * chessState { get { return &chessState; } }
95
96    // AI Player Threading
97    AIThread aiThread { chess = this };
98
99    // Windows
100
101    ListBox moveList
102    {
103       parent = this,
104       isActiveClient = true,
105       text = "MoveList",
106       autoScroll = true,
107       hasMinimize = true,
108       borderStyle = sizable,
109       hasVertScroll = true,
110       hasHorzScroll = true,
111       position = Point { x = 445 },
112       size = Size { 200, 450 }
113    };
114
115    Chess2D chess2D
116    {
117       parent = this,
118       text = "2D Chess Board",
119       chessState = &chessState
120    };
121
122    Chess3D chess3D
123    {
124       parent = this,
125       text = "3D Chess Board",
126       anchor = Anchor { left = 0.5, top = 0.5, right = 0, bottom = 0 },
127       chessState = &chessState,
128       state = maximized
129    };
130
131    // Main Menu
132    menu = Menu {};
133
134    Menu gameMenu    { menu, "Game", g };
135    Menu networkMenu { menu, "Network", n };
136    Menu viewMenu    { menu, "View", v };
137    Menu windowMenu  { menu, "Window", w };
138    MenuDivider      { menu };
139    Menu helpMenu    { menu, "Help", h };
140
141    // Game Menu
142    MenuItem aiItem
143    {
144       gameMenu, "New AI Game\tCtrl+N", n, ctrlN;
145
146       bool NotifySelect(MenuItem selection, Modifiers mods)
147       {
148          if(EndGame(newAIGame))
149          {
150             ai = true;
151             chessState.gameRunning = true;
152
153             chessState.isLocalPlayer[White] = true;
154             chessState.isLocalPlayer[Black] = false;
155
156             EnableMenus();
157
158             RandomSeed((uint)(((uint64)(GetTime() * 1000)) & MAXDWORD));
159
160             NewGame();
161          }
162          return true;
163       }
164    };
165
166    MenuItem localItem
167    {
168       gameMenu, "New Local Game\tCtrl+L", l, ctrlL;
169       bool NotifySelect(MenuItem selection, Modifiers mods)
170       {
171          if(EndGame(newLocalGame))
172          {
173             local = true;
174             chessState.gameRunning = true;
175             chessState.isLocalPlayer[White] = true;
176             chessState.isLocalPlayer[Black] = true;
177             EnableMenus();
178             NewGame();
179          }
180          return true;
181       }
182    };
183
184    MenuItem endGameItem
185    {
186       gameMenu, "End Game", e;
187       bool NotifySelect(MenuItem selection, Modifiers mods)
188       {
189          EndGame(endGame);
190          return true;
191       }
192    };
193
194    MenuItem { gameMenu, "Exit\tAlt+F4", x, NotifySelect = MenuFileExit };
195
196 #ifndef CHESS_NONET
197    // Network Menu
198    MenuItem connectItem
199    {
200       networkMenu, "Connect...", c;
201       bool NotifySelect(MenuItem selection, Modifiers mods)
202       {
203          if(EndGame(connect))
204          {
205             hosting = false;
206             service.Stop();
207             ConnectDialog { master = this, isModal = true }.Create();
208          }
209          return true;
210       }
211    };
212
213    MenuItem disconnectItem
214    {
215       networkMenu, "Disconnect", d, NotifySelect = endGameItem.NotifySelect
216    };
217
218    MenuItem hostItem
219    {
220       networkMenu, "Host", h;
221       bool NotifySelect(MenuItem selection, Modifiers mods)
222       {
223          if(EndGame(host))
224          {
225             if(service.Start())
226             {
227                hosting = true;
228                EnableMenus();
229             }
230          }
231          return true;
232       }
233    };
234
235    MenuItem stopItem
236    {
237       networkMenu, "Stop Hosting", s;
238       bool NotifySelect(MenuItem selection, Modifiers mods)
239       {
240          if(EndGame(stop))
241          {
242             hosting = false;
243             service.Stop();
244             EnableMenus();
245          }
246          return true;
247       }
248    };
249 #endif
250
251    // View Menu
252    MenuItem fullScreenItem
253    {
254       //viewMenu, "Full Screen", f, checkable = true;
255       bool NotifySelect(MenuItem selection, Modifiers mods)
256       {
257          app.fullScreen ^= true;
258          SetDriver();
259          anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
260          return true;
261       }
262    };
263
264    bool SetDisplayDriver(MenuItem selection, Modifiers mods)
265    {
266       //app.driver = app.drivers[selection.id];
267       SetDriver();
268       return true;
269    }
270
271    // Window Menu
272    MenuItem { windowMenu, "Next\tF6", n, NotifySelect = MenuWindowNext };
273    MenuItem { windowMenu, "Previous\tShift-F6", p, NotifySelect = MenuWindowPrevious };
274    MenuDivider { windowMenu };
275    MenuItem { windowMenu, "Windows...", w, NotifySelect = MenuWindowWindows };
276
277    //  Help Menu
278    MenuItem aboutItem
279    {
280       helpMenu, "About...\tF1", a, f1;
281       bool NotifySelect(MenuItem selection, Modifiers mods)
282       {
283          AboutChess { master = this, isModal = true }.Create();
284          return true;
285       }
286    };
287
288    int cx1, cy1, cx2, cy2;
289
290    bool DoMove(int x1, int y1, int x2, int y2, PieceType promotion)
291    {
292       bool valid = false;
293       PieceType type = chessState.board[y1][x1].type;
294       Player player = chessState.board[y1][x1].player;
295
296       if(StateMakeMove(chessState, x1,y1,x2,y2, promotion, true, null))
297       {
298          valid = true;
299
300          if(chessState.isLocalPlayer[player] && !local && !ai)
301          {
302             ChessPacket packet
303             {
304                type = Position,
305                player = player,
306                x1 = (byte)x1,
307                y1 = (byte)y1,
308                x2 = (byte)x2,
309                y2 = (byte)y2,
310                promotion = promotion
311             };
312 #ifndef CHESS_NONET
313             sockets[player^(Player)1].Send((byte *)&packet, sizeof(ChessPacket));
314 #endif
315          }
316
317          if(player == Black)
318          {
319             moveList.AddStringf("               %c%c-%c%c",
320                x1+'a',y1+'1', x2+'a',y2+'1');
321          }
322          else
323          {
324             moveList.AddStringf("%3d. %c%c-%c%c",
325                chessState.numMoves/2+1, x1+'a',y1+'1', x2+'a',y2+'1');
326          }
327
328
329          // Update Status Bar
330          {
331             MoveStack stack { };
332             GenerateMoveList(chessState, stack);
333
334             delete stack.moves;
335
336             if(Check(chessState, chessState.turn, -1, -1))
337             {
338                if(stack.count)
339                {
340                   chessState.state = Check; // TODO: Fix this
341                   stateField.text = "Check!";
342                }
343                else
344                {
345                   chessState.state = CheckMate;
346                   if(chessState.turn == White)
347                      stateField.text = "White are Checkmate.";
348                   else
349                      stateField.text = "Black are Checkmate.";
350                }
351             }
352             else if(!stack.count)
353             {
354                chessState.state = StaleMate;
355                stateField.text = "Stalemate.";
356             }
357             else
358                stateField.text = "";
359
360             // TOFIX: Gets confused with function!
361             if((chessState.state == Check || chessState.state == Normal) &&
362                chessState.isLocalPlayer[chessState.turn] && !local)
363                turnField.text = "Your turn";
364             else
365                turnField.text = "";
366          }
367       }
368
369       chess2D.Update(null);
370       chess3D.Update(null);
371       return valid;
372    }
373
374    // --- Chess Utilities ---
375    bool MakeMove(int x1, int y1, int x2, int y2, PieceType promotion)
376    {
377       bool makeMove = true;
378
379       PieceType type = chessState.board[y1][x1].type;
380       Player player = chessState.board[y1][x1].player;
381
382       // Pawn Promotion
383       if(type == Pawn && y2 == ((player == White) ? 7 : 0))
384       {
385          if(chessState.isLocalPlayer[chessState.turn] &&
386             IsMoveValid(x1,y1,x2,y2, chessState, null, true))
387          {
388             makeMove = false;
389             cx1 = x1, cy1 = y1, cx2 = x2, cy2 = y2;
390             chess2D.Update(null);
391             chess3D.Update(null);
392             promotion = (PieceType)Promotion
393             {
394                master = this;
395                isModal = true;
396
397                void Chess::NotifyDestroyed(Window promotionDlg, DialogResult r)
398                {
399                   DoMove(cx1, cy1, cx2, cy2, (PieceType)r);
400                   if(ai)
401                      aiThread.Play();
402                }
403             }.Create();
404          }
405       }
406       return makeMove ? DoMove(x1, y1, x2, y2, promotion) : false;
407    }
408
409    void ProcessUserMove(int x1, int y1, int x2, int y2)
410    {
411       if(MakeMove(x1, y1, x2, y2, 0))
412       {
413          if(ai)
414             aiThread.Play();
415       }
416
417       chess2D.Update(null);
418
419       chess3D.Update(null);
420    }
421
422    // #define QUEENMATE
423
424    void NewGame()
425    {
426       int x,y;
427
428       moveList.Clear();
429
430       chessState.state = Normal;
431       chessState.numMoves = 0;
432
433       for(y = 0; y <8; y++)
434          for(x = 0; x<8; x++)
435             chessState.board[y][x] = Piece {};
436
437       // WHITE PIECES
438
439    #ifndef QUEENMATE
440       for(x = 0; x<8; x++)
441          chessState.board[1][x] = Piece { White, Pawn };
442       chessState.board[0][0] = chessState.board[0][7] = Piece { White, Rook };
443       chessState.board[0][1] = chessState.board[0][6] = Piece { White, Knight };
444       chessState.board[0][2] = chessState.board[0][5] = Piece { White, Bishop };
445       chessState.board[0][3] = Piece { White, Queen };
446    #endif
447       chessState.board[0][4] = Piece { White, King };
448
449       // BLACK PIECES
450    #ifndef QUEENMATE
451       for(x = 0; x<8; x++)
452          chessState.board[6][x] = Piece { Black, Pawn };
453       chessState.board[7][0] = chessState.board[7][7] = Piece { Black, Rook };
454       chessState.board[7][1] = chessState.board[7][6] = Piece { Black, Knight };
455       chessState.board[7][2] = chessState.board[7][5] = Piece { Black, Bishop };
456    #endif
457       chessState.board[7][3] = Piece { Black, Queen };
458       chessState.board[7][4] = Piece { Black, King };
459
460       // CASTLE STATUS
461    #ifndef QUEENMATE
462       chessState.kingMoved[Black] = chessState.kingMoved[White] = false;
463       chessState.kRookMoved[Black] = chessState.kRookMoved[White] = false;
464       chessState.qRookMoved[Black] = chessState.qRookMoved[White] = false;
465    #else
466       chessState.kRookMoved[Black] = chessState.kRookMoved[White] = true;
467       chessState.qRookMoved[Black] = chessState.qRookMoved[White] = true;
468    #endif
469
470       // KING POSITION
471       chessState.kings[Black].x = chessState.kings[White].x = 4;
472       chessState.kings[Black].y = 7;
473       chessState.kings[White].y = 0;
474
475    #if 0
476       chessState.kings[Black].x = 4;
477       chessState.kings[Black].y = 6;
478       chessState.kings[White].x = 4;
479       chessState.kings[White].y = 0;
480
481       chessState.kingMoved[0] = false;
482       chessState.kingMoved[1] = true;
483       chessState.kRookMoved[0] = false;
484       chessState.qRookMoved[0] = false;
485       chessState.kRookMoved[1] = true;
486       chessState.qRookMoved[1] = true;
487
488       chessState.board[0][0] = Piece { White, Rook };
489       chessState.board[0][4] = Piece { White, King };
490       chessState.board[0][7] = Piece { White, Rook };
491       chessState.board[1][0] = Piece { White, Pawn };
492       chessState.board[1][2] = Piece { White, Pawn };
493       chessState.board[1][5] = Piece { White, Pawn };
494       chessState.board[1][6] = Piece { White, Pawn };
495       chessState.board[1][7] = Piece { White, Pawn };
496       chessState.board[2][1] = Piece { White, Pawn };
497       chessState.board[2][2] = Piece { White, Knight };
498       chessState.board[4][3] = Piece { White, Pawn };
499       chessState.board[5][6] = Piece { White, Bishop };
500
501       chessState.board[5][0] = Piece { Black, Pawn };
502       chessState.board[5][1] = Piece { Black, Pawn };
503       chessState.board[5][3] = Piece { Black, Knight };
504       chessState.board[5][5] = Piece { Black, Pawn };
505       chessState.board[5][7] = Piece { Black, Bishop };
506       chessState.board[6][0] = Piece { White, Rook };
507       chessState.board[6][2] = Piece { Black, Pawn };
508       chessState.board[6][3] = Piece { Black, Pawn };
509       chessState.board[6][4] = Piece { Black, King };
510       chessState.board[7][1] = Piece { Black, Knight };
511       chessState.board[7][2] = Piece { Black, Bishop };
512    #endif
513       chessState.turn = White;
514
515       chessState.castled[White] =
516       chessState.castled[Black] = false;
517
518       // EN PASSANT STATUS
519       chessState.enPassant.x = -1;
520       chessState.enPassant.y = -1;
521
522       chessState.pieceCount[White][Pawn]   = chessState.pieceCount[Black][Pawn] = 8;
523       chessState.pieceCount[White][Knight] = chessState.pieceCount[Black][Knight] = 2;
524       chessState.pieceCount[White][Bishop] = chessState.pieceCount[Black][Bishop] = 2;
525       chessState.pieceCount[White][Rook]   = chessState.pieceCount[Black][Rook] = 2;
526       chessState.pieceCount[White][Queen]  = chessState.pieceCount[Black][Queen] = 1;
527       chessState.pieceCount[White][King]   = chessState.pieceCount[Black][King] = 1;
528
529       chessState.materialValue[White] =
530          chessState.pieceCount[White][Pawn]   * materialValues[Pawn] +
531          chessState.pieceCount[White][Knight] * materialValues[Knight] +
532          chessState.pieceCount[White][Bishop] * materialValues[Bishop] +
533          chessState.pieceCount[White][Rook]   * materialValues[Rook] +
534          chessState.pieceCount[White][Queen]  * materialValues[Queen];
535       chessState.materialValue[Black] =
536          chessState.pieceCount[Black][Pawn]   * materialValues[Pawn] +
537          chessState.pieceCount[Black][Knight] * materialValues[Knight] +
538          chessState.pieceCount[Black][Bishop] * materialValues[Bishop] +
539          chessState.pieceCount[Black][Rook]   * materialValues[Rook] +
540          chessState.pieceCount[Black][Queen]  * materialValues[Queen];
541
542       chess2D.Update(null);
543       chess3D.Update(null);
544
545       if(chessState.isLocalPlayer[chessState.turn] && !local)
546          turnField.text = "Your turn";
547       stateField.text = "";
548
549    /*
550       // 1
551       MakeMoveChar('e',2, 'e',4);
552       MakeMoveChar('a',7, 'a',6);
553       // 2
554       MakeMoveChar('d',2, 'd',4);
555       MakeMoveChar('f',7, 'f',5);
556       // 3
557       MakeMoveChar('e',4, 'f',5);
558       MakeMoveChar('b',8, 'c',6);
559       // 4
560       MakeMoveChar('d',4, 'd',5);
561       MakeMoveChar('c',6, 'e',5);
562       // 5
563       MakeMoveChar('f',2, 'f',4);
564       MakeMoveChar('e',5, 'f',7);
565       // 6
566       MakeMoveChar('g',1, 'f',3);
567       MakeMoveChar('c',7, 'c',5);
568       // 7
569       MakeMoveChar('c',2, 'c',4);
570       MakeMoveChar('g',7, 'g',6);
571       // 8
572       MakeMoveChar('f',5, 'g',6);
573       MakeMoveChar('f',7, 'd',6);
574       // 9
575       MakeMoveChar('g',6, 'h',7);
576       MakeMoveChar('g',8, 'h',6);
577       // 10
578       MakeMoveChar('f',1, 'd',3);
579       MakeMoveChar('d',6, 'f',7);
580       // 11
581       MakeMoveChar('c',1, 'd',2);
582       MakeMoveChar('d',8, 'b',6);
583       // 12
584       MakeMoveChar('d',2, 'c',3);
585       MakeMoveChar('b',6, 'd',6);
586       // 13
587       MakeMoveChar('c',3, 'h',8);
588       MakeMoveChar('f',7, 'h',8);
589       // 14
590       MakeMoveChar('d',1, 'd',2);
591       MakeMoveChar('e',7, 'e',6);
592    */
593    }
594
595    void MakeMoveChar(char x1, int y1, char x2, int y2)
596    {
597       MakeMove(x1 - 'a', y1 - 1, x2 - 'a', y2 - 1, Queen);
598    }
599
600    void EnableMenus()
601    {
602 #ifndef CHESS_NONET
603       stopItem.disabled = !hosting;
604       disconnectItem.disabled = !sockets[SERVER_COLOR] && !sockets[CLIENT_COLOR];
605       hostItem.disabled = hosting;
606 #endif
607       endGameItem.disabled = !chessState.gameRunning;
608    }
609
610    void SetDriver()
611    {
612       int c;
613       for(c = 0; c<app.numDrivers; c++)
614          if(!strcmp(app.drivers[c], app.driver))
615          {
616             driverItems[c].checked = true;
617             break;
618          }
619    }
620
621    // --- Chess Window Class ---
622    bool OnCreate()
623    {
624       int c;
625
626       driverItems = new MenuItem[app.numDrivers];
627       for(c = 0; c<app.numDrivers; c++)
628       {
629          driverItems[c] = MenuItem { viewMenu, app.drivers[c], NotifySelect = SetDisplayDriver };
630          driverItems[c].id = c;
631          driverItems[c].isRadio = true;
632       }
633       // this.SetPalette(palette, true);
634
635       SetDriver();
636       NewGame();
637       EnableMenus();
638
639       return true;
640    }
641
642    void DoEndGame(GameAction action)
643    {
644 #ifndef CHESS_NONET
645       if(sockets[SERVER_COLOR])
646          sockets[SERVER_COLOR].Disconnect(0);
647       else if(sockets[CLIENT_COLOR])
648          sockets[CLIENT_COLOR].Disconnect(0);
649       else
650 #endif
651       if(local || ai)
652       {
653          if(ai) aiThread.Abort();
654          local = ai = false;
655          chessState.gameRunning = false;
656       }
657       EnableMenus();
658
659       turnField.text = "";
660       stateField.text = "";
661
662       switch(action)
663       {
664          case newAIGame:    aiItem.NotifySelect(this, aiItem, 0); break;
665          case newLocalGame: localItem.NotifySelect(this, localItem, 0); break;
666          case close:        Destroy(0); break;
667       }
668    }
669
670    GameAction nextAction;
671
672    bool EndGame(GameAction action)
673    {
674       if(chessState.gameRunning &&
675          (chessState.state == Normal || chessState.state == Check))
676       {
677          nextAction = action;
678          MessageBox
679          {
680             type = okCancel, contents = "Quit current game?",
681             master = this, text = "ECERE Chess";
682             isModal = true;
683
684             void Chess::NotifyDestroyed(Window msgBox, DialogResult result)
685             {
686                if(result != cancel)
687                   DoEndGame(nextAction);
688             }
689          }.Create();
690          return false;
691       }
692       return true;
693    }
694
695    bool OnClose(bool parentClosing)
696    {
697       return EndGame(close);
698    }
699
700    void OnDestroy()
701    {
702 #ifndef CHESS_NONET
703       delete sockets[Black];
704       delete sockets[White];
705 #endif
706       delete driverItems;
707    }
708
709 #ifndef CHESS_NONET
710    void Connect(const char * address)
711    {
712       ChessSocket socket { chess = this };
713       if(socket.Connect(address, CHESS_PORT))
714       {
715          sockets[SERVER_COLOR] = socket;
716          EnableMenus();
717
718          chessState.isLocalPlayer[CLIENT_COLOR] = true;
719          chessState.isLocalPlayer[SERVER_COLOR] = false;
720       }
721    }
722 #endif
723 }
724
725 // --- Chess Communications ---
726 #ifndef CHESS_NONET
727 class ChessSocket : Socket
728 {
729    Chess chess;
730    property Chess chess { set { chess = value; } }
731
732    void OnDisconnect(int code)
733    {
734       if(this == chess.sockets[CLIENT_COLOR])
735       {
736          chess.sockets[CLIENT_COLOR] = null;
737          chess.chessState->gameRunning = false;
738          chess.turnField.text = "";
739          chess.stateField.text = "";
740       }
741       else if(this == chess.sockets[SERVER_COLOR])
742       {
743          chess.sockets[SERVER_COLOR] = null;
744          chess.chessState->gameRunning = false;
745          chess.turnField.text = "";
746          chess.stateField.text = "";
747       }
748
749       chess.EnableMenus();
750       chess.chess2D.Update(null);
751       chess.chess3D.Update(null);
752    }
753
754    uint OnReceive(const byte * buffer, uint count)
755    {
756       if(count >= sizeof(ChessPacket))
757       {
758          ChessPacket packet = *(ChessPacket *)buffer;
759          switch(packet.type)
760          {
761             case Position:
762                chess.MakeMove(packet.x1, packet.y1, packet.x2, packet.y2, packet.promotion);
763                chess.Activate();
764                break;
765             case NewGame:
766                chess.chessState->gameRunning = true;
767                chess.NewGame();
768                break;
769          }
770          return sizeof(ChessPacket);
771       }
772       return 0;
773    }
774
775    void OnConnect()
776    {
777       chess.sockets[SERVER_COLOR] = this;
778       chess.chessState->gameRunning = true;
779       chess.EnableMenus();
780       chess.NewGame();
781    }
782 }
783
784 class ChessService : Service
785 {
786    Chess chess;
787    property Chess chess { set { chess = value; } }
788
789    void OnAccept()
790    {
791       if(!chess.chessState->gameRunning)
792       {
793          ChessPacket packet { type = NewGame };
794
795          chess.sockets[CLIENT_COLOR] = ChessSocket { this, chess = chess };
796          chess.sockets[CLIENT_COLOR].Send((byte *)&packet, sizeof(ChessPacket));
797
798          chess.chessState->isLocalPlayer[SERVER_COLOR] = true;
799          chess.chessState->isLocalPlayer[CLIENT_COLOR] = false;
800
801          chess.NewGame();
802          chess.chessState->gameRunning = true;
803          chess.EnableMenus();
804          chess.chess2D.Update(null);
805          chess.chess3D.Update(null);
806       }
807    }
808 }
809 #endif