ecere: Initial Emscripten support
[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 valid = false;
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          valid = true;
386          if(chessState.isLocalPlayer[chessState.turn] &&
387             (valid = IsMoveValid(x1,y1,x2,y2, chessState, null, true)))
388          {
389             valid = false;
390             cx1 = x1, cy1 = y1, cx2 = x2, cy2 = y2;
391             chess2D.Update(null);
392             chess3D.Update(null);
393             promotion = (PieceType)Promotion
394             {
395                master = this;
396                isModal = true;
397
398                void Chess::NotifyDestroyed(Window promotionDlg, DialogResult r)
399                {
400                   DoMove(cx1, cy1, cx2, cy2, (PieceType)r);
401                   if(ai)
402                      aiThread.Play();
403                }
404             }.Create();
405          }
406       }
407       else
408          valid = DoMove(x1, y1, x2, y2, promotion);
409       return valid;
410    }
411
412    void ProcessUserMove(int x1, int y1, int x2, int y2)
413    {
414       if(MakeMove(x1, y1, x2, y2, 0))
415       {
416          if(ai)
417             aiThread.Play();
418       }
419
420       chess2D.Update(null);
421
422       chess3D.Update(null);
423    }
424
425    // #define QUEENMATE
426
427    void NewGame()
428    {
429       int x,y;
430
431       moveList.Clear();
432
433       chessState.state = Normal;
434       chessState.numMoves = 0;
435
436       for(y = 0; y <8; y++)
437          for(x = 0; x<8; x++)
438             chessState.board[y][x] = Piece {};
439
440       // WHITE PIECES
441
442    #ifndef QUEENMATE
443       for(x = 0; x<8; x++)
444          chessState.board[1][x] = Piece { White, Pawn };
445       chessState.board[0][0] = chessState.board[0][7] = Piece { White, Rook };
446       chessState.board[0][1] = chessState.board[0][6] = Piece { White, Knight };
447       chessState.board[0][2] = chessState.board[0][5] = Piece { White, Bishop };
448       chessState.board[0][3] = Piece { White, Queen };
449    #endif
450       chessState.board[0][4] = Piece { White, King };
451
452       // BLACK PIECES
453    #ifndef QUEENMATE
454       for(x = 0; x<8; x++)
455          chessState.board[6][x] = Piece { Black, Pawn };
456       chessState.board[7][0] = chessState.board[7][7] = Piece { Black, Rook };
457       chessState.board[7][1] = chessState.board[7][6] = Piece { Black, Knight };
458       chessState.board[7][2] = chessState.board[7][5] = Piece { Black, Bishop };
459    #endif
460       chessState.board[7][3] = Piece { Black, Queen };
461       chessState.board[7][4] = Piece { Black, King };
462
463       // CASTLE STATUS
464    #ifndef QUEENMATE
465       chessState.kingMoved[Black] = chessState.kingMoved[White] = false;
466       chessState.kRookMoved[Black] = chessState.kRookMoved[White] = false;
467       chessState.qRookMoved[Black] = chessState.qRookMoved[White] = false;
468    #else
469       chessState.kRookMoved[Black] = chessState.kRookMoved[White] = true;
470       chessState.qRookMoved[Black] = chessState.qRookMoved[White] = true;
471    #endif
472
473       // KING POSITION
474       chessState.kings[Black].x = chessState.kings[White].x = 4;
475       chessState.kings[Black].y = 7;
476       chessState.kings[White].y = 0;
477
478    #if 0
479       chessState.kings[Black].x = 4;
480       chessState.kings[Black].y = 6;
481       chessState.kings[White].x = 4;
482       chessState.kings[White].y = 0;
483
484       chessState.kingMoved[0] = false;
485       chessState.kingMoved[1] = true;
486       chessState.kRookMoved[0] = false;
487       chessState.qRookMoved[0] = false;
488       chessState.kRookMoved[1] = true;
489       chessState.qRookMoved[1] = true;
490
491       chessState.board[0][0] = Piece { White, Rook };
492       chessState.board[0][4] = Piece { White, King };
493       chessState.board[0][7] = Piece { White, Rook };
494       chessState.board[1][0] = Piece { White, Pawn };
495       chessState.board[1][2] = Piece { White, Pawn };
496       chessState.board[1][5] = Piece { White, Pawn };
497       chessState.board[1][6] = Piece { White, Pawn };
498       chessState.board[1][7] = Piece { White, Pawn };
499       chessState.board[2][1] = Piece { White, Pawn };
500       chessState.board[2][2] = Piece { White, Knight };
501       chessState.board[4][3] = Piece { White, Pawn };
502       chessState.board[5][6] = Piece { White, Bishop };
503
504       chessState.board[5][0] = Piece { Black, Pawn };
505       chessState.board[5][1] = Piece { Black, Pawn };
506       chessState.board[5][3] = Piece { Black, Knight };
507       chessState.board[5][5] = Piece { Black, Pawn };
508       chessState.board[5][7] = Piece { Black, Bishop };
509       chessState.board[6][0] = Piece { White, Rook };
510       chessState.board[6][2] = Piece { Black, Pawn };
511       chessState.board[6][3] = Piece { Black, Pawn };
512       chessState.board[6][4] = Piece { Black, King };
513       chessState.board[7][1] = Piece { Black, Knight };
514       chessState.board[7][2] = Piece { Black, Bishop };
515    #endif
516       chessState.turn = White;
517
518       chessState.castled[White] =
519       chessState.castled[Black] = false;
520
521       // EN PASSANT STATUS
522       chessState.enPassant.x = -1;
523       chessState.enPassant.y = -1;
524
525       chessState.pieceCount[White][Pawn]   = chessState.pieceCount[Black][Pawn] = 8;
526       chessState.pieceCount[White][Knight] = chessState.pieceCount[Black][Knight] = 2;
527       chessState.pieceCount[White][Bishop] = chessState.pieceCount[Black][Bishop] = 2;
528       chessState.pieceCount[White][Rook]   = chessState.pieceCount[Black][Rook] = 2;
529       chessState.pieceCount[White][Queen]  = chessState.pieceCount[Black][Queen] = 1;
530       chessState.pieceCount[White][King]   = chessState.pieceCount[Black][King] = 1;
531
532       chessState.materialValue[White] =
533          chessState.pieceCount[White][Pawn]   * materialValues[Pawn] +
534          chessState.pieceCount[White][Knight] * materialValues[Knight] +
535          chessState.pieceCount[White][Bishop] * materialValues[Bishop] +
536          chessState.pieceCount[White][Rook]   * materialValues[Rook] +
537          chessState.pieceCount[White][Queen]  * materialValues[Queen];
538       chessState.materialValue[Black] =
539          chessState.pieceCount[Black][Pawn]   * materialValues[Pawn] +
540          chessState.pieceCount[Black][Knight] * materialValues[Knight] +
541          chessState.pieceCount[Black][Bishop] * materialValues[Bishop] +
542          chessState.pieceCount[Black][Rook]   * materialValues[Rook] +
543          chessState.pieceCount[Black][Queen]  * materialValues[Queen];
544
545       chess2D.Update(null);
546       chess3D.Update(null);
547
548       if(chessState.isLocalPlayer[chessState.turn] && !local)
549          turnField.text = "Your turn";
550       stateField.text = "";
551
552    /*
553       // 1
554       MakeMoveChar('e',2, 'e',4);
555       MakeMoveChar('a',7, 'a',6);
556       // 2
557       MakeMoveChar('d',2, 'd',4);
558       MakeMoveChar('f',7, 'f',5);
559       // 3
560       MakeMoveChar('e',4, 'f',5);
561       MakeMoveChar('b',8, 'c',6);
562       // 4
563       MakeMoveChar('d',4, 'd',5);
564       MakeMoveChar('c',6, 'e',5);
565       // 5
566       MakeMoveChar('f',2, 'f',4);
567       MakeMoveChar('e',5, 'f',7);
568       // 6
569       MakeMoveChar('g',1, 'f',3);
570       MakeMoveChar('c',7, 'c',5);
571       // 7
572       MakeMoveChar('c',2, 'c',4);
573       MakeMoveChar('g',7, 'g',6);
574       // 8
575       MakeMoveChar('f',5, 'g',6);
576       MakeMoveChar('f',7, 'd',6);
577       // 9
578       MakeMoveChar('g',6, 'h',7);
579       MakeMoveChar('g',8, 'h',6);
580       // 10
581       MakeMoveChar('f',1, 'd',3);
582       MakeMoveChar('d',6, 'f',7);
583       // 11
584       MakeMoveChar('c',1, 'd',2);
585       MakeMoveChar('d',8, 'b',6);
586       // 12
587       MakeMoveChar('d',2, 'c',3);
588       MakeMoveChar('b',6, 'd',6);
589       // 13
590       MakeMoveChar('c',3, 'h',8);
591       MakeMoveChar('f',7, 'h',8);
592       // 14
593       MakeMoveChar('d',1, 'd',2);
594       MakeMoveChar('e',7, 'e',6);
595    */
596    }
597
598    void MakeMoveChar(char x1, int y1, char x2, int y2)
599    {
600       MakeMove(x1 - 'a', y1 - 1, x2 - 'a', y2 - 1, Queen);
601    }
602
603    void EnableMenus()
604    {
605 #ifndef CHESS_NONET
606       stopItem.disabled = !hosting;
607       disconnectItem.disabled = !sockets[SERVER_COLOR] && !sockets[CLIENT_COLOR];
608       hostItem.disabled = hosting;
609 #endif
610       endGameItem.disabled = !chessState.gameRunning;
611    }
612
613    void SetDriver()
614    {
615       int c;
616       for(c = 0; c<app.numDrivers; c++)
617          if(!strcmp(app.drivers[c], app.driver))
618          {
619             driverItems[c].checked = true;
620             break;
621          }
622    }
623
624    // --- Chess Window Class ---
625    bool OnCreate()
626    {
627       int c;
628
629       driverItems = new MenuItem[app.numDrivers];
630       for(c = 0; c<app.numDrivers; c++)
631       {
632          driverItems[c] = MenuItem { viewMenu, app.drivers[c], NotifySelect = SetDisplayDriver };
633          driverItems[c].id = c;
634          driverItems[c].isRadio = true;
635       }
636       // this.SetPalette(palette, true);
637
638       SetDriver();
639       NewGame();
640       EnableMenus();
641
642       return true;
643    }
644
645    void DoEndGame(GameAction action)
646    {
647 #ifndef CHESS_NONET
648       if(sockets[SERVER_COLOR])
649          sockets[SERVER_COLOR].Disconnect(0);
650       else if(sockets[CLIENT_COLOR])
651          sockets[CLIENT_COLOR].Disconnect(0);
652       else
653 #endif
654       if(local || ai)
655       {
656          if(ai) aiThread.Abort();
657          local = ai = false;
658          chessState.gameRunning = false;
659       }
660       EnableMenus();
661
662       turnField.text = "";
663       stateField.text = "";
664
665       switch(action)
666       {
667          case newAIGame:    aiItem.NotifySelect(this, aiItem, 0); break;
668          case newLocalGame: localItem.NotifySelect(this, localItem, 0); break;
669       }
670    }
671
672    GameAction nextAction;
673
674    bool EndGame(GameAction action)
675    {
676       if(chessState.gameRunning &&
677          (chessState.state == Normal || chessState.state == Check))
678       {
679          nextAction = action;
680          MessageBox
681          {
682             type = okCancel, contents = "Quit current game?",
683             master = this, text = "ECERE Chess";
684             isModal = true;
685
686             void Chess::NotifyDestroyed(Window msgBox, DialogResult result)
687             {
688                if(result != cancel)
689                   DoEndGame(nextAction);
690             }
691          }.Create();
692          return false;
693       }
694       return true;
695    }
696
697    bool OnClose(bool parentClosing)
698    {
699       return EndGame(close);
700    }
701
702    void OnDestroy()
703    {
704 #ifndef CHESS_NONET
705       delete sockets[Black];
706       delete sockets[White];
707 #endif
708       delete driverItems;
709    }
710
711 #ifndef CHESS_NONET
712    void Connect(const char * address)
713    {
714       ChessSocket socket { chess = this };
715       if(socket.Connect(address, CHESS_PORT))
716       {
717          sockets[SERVER_COLOR] = socket;
718          EnableMenus();
719
720          chessState.isLocalPlayer[CLIENT_COLOR] = true;
721          chessState.isLocalPlayer[SERVER_COLOR] = false;
722       }
723    }
724 #endif
725 }
726
727 // --- Chess Communications ---
728 #ifndef CHESS_NONET
729 class ChessSocket : Socket
730 {
731    Chess chess;
732    property Chess chess { set { chess = value; } }
733
734    void OnDisconnect(int code)
735    {
736       if(this == chess.sockets[CLIENT_COLOR])
737       {
738          chess.sockets[CLIENT_COLOR] = null;
739          chess.chessState->gameRunning = false;
740          chess.turnField.text = "";
741          chess.stateField.text = "";
742       }
743       else if(this == chess.sockets[SERVER_COLOR])
744       {
745          chess.sockets[SERVER_COLOR] = null;
746          chess.chessState->gameRunning = false;
747          chess.turnField.text = "";
748          chess.stateField.text = "";
749       }
750
751       chess.EnableMenus();
752       chess.chess2D.Update(null);
753       chess.chess3D.Update(null);
754    }
755
756    uint OnReceive(const byte * buffer, uint count)
757    {
758       if(count >= sizeof(ChessPacket))
759       {
760          ChessPacket packet = *(ChessPacket *)buffer;
761          switch(packet.type)
762          {
763             case Position:
764                chess.MakeMove(packet.x1, packet.y1, packet.x2, packet.y2, packet.promotion);
765                chess.Activate();
766                break;
767             case NewGame:
768                chess.chessState->gameRunning = true;
769                chess.NewGame();
770                break;
771          }
772          return sizeof(ChessPacket);
773       }
774       return 0;
775    }
776
777    void OnConnect()
778    {
779       chess.sockets[SERVER_COLOR] = this;
780       chess.chessState->gameRunning = true;
781       chess.EnableMenus();
782       chess.NewGame();
783    }
784 }
785
786 class ChessService : Service
787 {
788    Chess chess;
789    property Chess chess { set { chess = value; } }
790
791    void OnAccept()
792    {
793       if(!chess.chessState->gameRunning)
794       {
795          ChessPacket packet { type = NewGame };
796
797          chess.sockets[CLIENT_COLOR] = ChessSocket { this, chess = chess };
798          chess.sockets[CLIENT_COLOR].Send((byte *)&packet, sizeof(ChessPacket));
799
800          chess.chessState->isLocalPlayer[SERVER_COLOR] = true;
801          chess.chessState->isLocalPlayer[CLIENT_COLOR] = false;
802
803          chess.NewGame();
804          chess.chessState->gameRunning = true;
805          chess.EnableMenus();
806          chess.chess2D.Update(null);
807          chess.chess3D.Update(null);
808       }
809    }
810 }
811 #endif