Subversion Repositories Games.Chess Giants

Rev

Rev 50 | Rev 75 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
// window_main.cpp
2
 
3
#include "../common.h"
4
 
5
 
21 pmbaty 6
// global variables used in this module only
7
static wchar_t folder_path[MAX_PATH];
8
 
9
 
1 pmbaty 10
// prototypes of local functions
11
static bool Button_IsHovered (guibutton_t *button, int gui_x, int gui_y);
12
static bool Button_UpdateHoverState (guibutton_t *button, int gui_x, int gui_y);
13
 
14
 
15
LRESULT CALLBACK WindowProc_Main (HWND hWnd, unsigned int message, WPARAM wParam, LPARAM lParam)
16
{
17
   // this is the main message handler for the program
18
 
19
   static wchar_t fen_string[128];
20
   static char selectable_parts[14] = "PRNBQK kqbnrp";
21
   static int prevgui_x = 0;
22
   static int prevgui_y = 0;
3 pmbaty 23
   static bool ctrl_pressed = false;
1 pmbaty 24
   static bool rbutton_pushed = false;
25
 
26
   unsigned short wParam_hiword;
27
   unsigned short wParam_loword;
28
   int prev_hovered_position[2];
29
   player_t *current_player;
30
   player_t *opposite_player;
31
   player_t *local_player;
32
   player_t *remote_player;
33
   ccreply_t *entered_ccreply;
34
   boardmove_t *current_move;
35
   float board_x;
36
   float board_y;
37
   int gui_x;
38
   int gui_y;
39
   int line;
40
   int column;
41
   int index_line;
42
   int index_column;
43
   int part_index;
44
   int part_color;
24 pmbaty 45
   int viewer_index;
1 pmbaty 46
 
47
   // filter out the commonly used message values
48
   wParam_hiword = HIWORD (wParam);
49
   wParam_loword = LOWORD (wParam);
50
 
51
   ////////////////////////////////////////////////////////////////////////////////////////////////
52
   // has the window just been fired up ?
53
   if (message == WM_CREATE)
54
   {
55
      the_scene.gui.is_entering_text = false; // we are NOT entering text yet
56
 
57
      // call the default window message processing function to keep things going
58
      return (DefWindowProc (hWnd, message, wParam, lParam));
59
   }
60
 
61
   ////////////////////////////////////////////////////////////////////////////////////////////////
62
   // else have we clicked on the close button ?
63
   else if (message == WM_CLOSE)
64
   {
65
      if (the_board.game_state == STATE_PLAYING)
66
         DialogBox_Quit (); // if a game has started, ask for confirmation
67
      else
68
         is_dialogbox_quit_validated = true; // if game hasn't started yet, quit without question
69
 
70
      return (0); // don't let Windows do the default processing on this message
71
   }
72
 
73
   ////////////////////////////////////////////////////////////////////////////////////////////////
74
   // else is the user closing its session OR the window is being destroyed ?
75
   else if ((message == WM_QUERYENDSESSION) || (message == WM_ENDSESSION) || (message == WM_DESTROY))
76
      terminate_everything = true; // suicide (for some reason, PostQuitMessage() is unreliable !?)
77
 
21 pmbaty 78
   /////////////////
79
   // MENU EVENTS //
80
   /////////////////
81
 
82
   ///////////////
83
   // menu command
1 pmbaty 84
   else if (message == WM_COMMAND)
85
   {
86
      // game menu, new game
87
      if (wParam_loword == MENUID_GAME_NEWGAME)
88
      {
89
         if ((the_board.game_state == STATE_PLAYING) && (the_board.move_count > 1))
90
            DialogBox_Resign (); // if a game is playing, ask to resign first
91
         else
92
            DialogBox_NewGame (); // game not started yet, show the new game dialog box
93
      }
94
 
95
      // game menu, setup start position
96
      else if (wParam_loword == MENUID_GAME_SETUPPOSITION)
97
      {
98
         if ((the_board.game_state == STATE_PLAYING) && (the_board.move_count > 1))
99
            DialogBox_Resign (); // if a game is playing, ask to resign first
100
         else
101
         {
102
            current_move = &the_board.moves[0]; // quick access to start move
103
            memset (&current_move->slots, 0, sizeof (current_move->slots)); // erase all slots
104
 
105
            the_board.game_state = STATE_SETUPPOSITION; // game not started yet, enter board setup mode
106
            the_board.reevaluate = true; // evaluate board again
107
 
108
            // display the "please choose start position" phrase in the middle of the screen
109
            Scene_SetText (&the_scene.gui.central_text, 50.0f, 50.0f, -1, ALIGN_CENTER, ALIGN_CENTER, ALIGN_CENTER, centermsg_fontindex, RGBA_TO_RGBACOLOR (255, 255, 255, 191),
110
                           999999.0f, true, LOCALIZE (L"SetupMode"));
111
            the_scene.gui.partspick_selectedpart = ' '; // no selected part yet
112
            the_scene.update = true; // and update the 3D scene
113
         }
114
      }
115
 
116
      // game menu, load game
117
      else if (wParam_loword == MENUID_GAME_LOAD)
118
         DialogBox_Load (); // fire up the load dialog box
119
 
120
      // game menu, save game
121
      else if (wParam_loword == MENUID_GAME_SAVE)
122
      {
123
         if (save_pathname[0] != 0)
124
            is_dialogbox_save_validated = true; // if the filename is known, save it directly
125
         else
126
            DialogBox_Save (); // else fire up the save dialog box
127
      }
128
 
129
      // game menu, save as
130
      else if (wParam_loword == MENUID_GAME_SAVEAS)
131
         DialogBox_Save (); // fire up the save dialog box
132
 
133
      // game menu, save position as
134
      else if (wParam_loword == MENUID_GAME_SAVEPOSITIONAS)
135
         DialogBox_SavePosition (); // fire up the save position dialog box
136
 
137
      // game menu, resign
138
      else if (wParam_loword == MENUID_GAME_RESIGN)
139
         DialogBox_Resign (); // if a game has started, ask for confirmation
140
 
141
      // game menu, statistics (stats are only available in online mode)
142
      else if (wParam_loword == MENUID_GAME_STATISTICS)
143
      {
144
         local_player = Player_FindByType (PLAYER_HUMAN);
145
         if (local_player != NULL)
146
            PlayerCard_FindOrCreate (local_player->name); // display player's own player card
147
      }
148
 
149
      // game menu, options
150
      else if (wParam_loword == MENUID_GAME_OPTIONS)
151
         DialogBox_Options (); // fire up the options dialog box
152
 
153
      // game menu, quit
154
      else if (wParam_loword == MENUID_GAME_QUIT)
155
      {
156
         if (the_board.game_state == STATE_PLAYING)
157
            DialogBox_Quit (); // if a game has started, ask for confirmation
158
         else
159
            is_dialogbox_quit_validated = true; // if game hasn't started yet, quit without question
160
      }
161
 
162
      // chessboard menu, suggest move
163
      else if (wParam_loword == MENUID_CHESSBOARD_SUGGESTMOVE)
164
         the_board.players[current_viewer].wants_hint = true; // remember this player wants a hint
165
 
166
      // chessboard menu, cancel last move
167
      else if (wParam_loword == MENUID_CHESSBOARD_CANCELLASTMOVE)
168
         the_board.players[current_viewer].wants_cancel = true; // remember this player wants to cancel his last move
169
 
170
      // chessboard menu, comment move
171
      else if (wParam_loword == MENUID_CHESSBOARD_COMMENTMOVE)
172
         DialogBox_Comment (); // fire up the comment dialog box
173
 
174
      // chessboard menu, go to move
175
      else if (wParam_loword == MENUID_CHESSBOARD_GOTOMOVE)
176
         DialogBox_GoToMove (); // fire up the go to move dialog box
177
 
178
      // chessboard menu, swap sides
179
      else if (wParam_loword == MENUID_CHESSBOARD_SWAPSIDES)
180
         the_board.want_playerswap = true; // remember board sides are to be swapped
181
 
182
      // chessboard menu, beginning of game
183
      else if (wParam_loword == MENUID_CHESSBOARD_BEGINNINGOFGAME)
184
      {
185
         the_board.viewed_move = 0; // enter view mode and go to the beginning of the game
186
         Audio_PlaySound (SOUNDTYPE_CLICK); // make a click sound
187
         the_board.reevaluate = true; // evaluate board again
188
      }
189
 
190
      // chessboard menu, previous move (only if arrow is enabled)
191
      else if ((wParam_loword == MENUID_CHESSBOARD_PREVIOUSMOVE) && (the_scene.gui.larrow.state != 0))
192
      {
193
         the_board.viewed_move--; // enter view mode and go back one move
194
         Audio_PlaySound (SOUNDTYPE_CLICK); // make a click sound
195
         the_board.reevaluate = true; // evaluate board again
196
      }
197
 
198
      // chessboard menu, next move (only if arrow is enabled)
199
      else if ((wParam_loword == MENUID_CHESSBOARD_NEXTMOVE) && (the_scene.gui.rarrow.state != 0))
200
      {
201
         the_board.viewed_move++; // enter view mode and go forward one move
202
         Audio_PlaySound (SOUNDTYPE_CLICK); // make a click sound
203
         the_board.reevaluate = true; // evaluate board again
204
      }
205
 
206
      // chessboard menu, current state of game
207
      else if (wParam_loword == MENUID_CHESSBOARD_CURRENTSTATEOFGAME)
208
      {
209
         the_board.viewed_move = the_board.move_count - 1; // enter view mode and go to the current state of the game
210
         Audio_PlaySound (SOUNDTYPE_CLICK); // make a click sound
211
         the_board.reevaluate = true; // evaluate board again
212
      }
213
 
214
      // chessboard menu, top view
215
      else if (wParam_loword == MENUID_CHESSBOARD_TOPVIEW)
216
      {
24 pmbaty 217
         // cycle through both players and change their view angles EXCEPT the opponent if he's human
218
         for (viewer_index = 0; viewer_index < 2; viewer_index++)
219
            if ((the_board.players[viewer_index].type == PLAYER_COMPUTER)
220
                || (the_board.players[viewer_index].type == PLAYER_INTERNET)
221
                || (viewer_index == current_viewer))
222
            {
25 pmbaty 223
               the_board.players[viewer_index].view_pitch = 89.99f;
24 pmbaty 224
               the_board.players[viewer_index].view_yaw = (current_viewer == COLOR_BLACK ? 90.0f : -90.0f);
225
               the_board.players[viewer_index].view_distance = 58.0f;
226
            }
1 pmbaty 227
      }
228
 
229
      // chessboard menu, default view
230
      else if (wParam_loword == MENUID_CHESSBOARD_DEFAULTVIEW)
231
      {
24 pmbaty 232
         // cycle through both players and change their view angles EXCEPT the opponent if he's human
233
         for (viewer_index = 0; viewer_index < 2; viewer_index++)
234
            if ((the_board.players[viewer_index].type == PLAYER_COMPUTER)
235
                || (the_board.players[viewer_index].type == PLAYER_INTERNET)
236
                || (viewer_index == current_viewer))
237
            {
238
               the_board.players[viewer_index].view_pitch = 55.0f;
239
               the_board.players[viewer_index].view_yaw = (current_viewer == COLOR_BLACK ? 90.0f : -90.0f);
240
               the_board.players[viewer_index].view_distance = 70.0f;
241
            }
1 pmbaty 242
      }
243
 
244
      // chessboard menu, reset view
245
      else if (wParam_loword == MENUID_CHESSBOARD_RESETVIEW)
246
      {
24 pmbaty 247
         // cycle through both players and change their view angles EXCEPT the opponent if he's human
248
         for (viewer_index = 0; viewer_index < 2; viewer_index++)
249
            if ((the_board.players[viewer_index].type == PLAYER_COMPUTER)
250
                || (the_board.players[viewer_index].type == PLAYER_INTERNET)
251
                || (viewer_index == current_viewer))
252
            {
253
               the_board.players[viewer_index].view_pitch = the_board.players[current_viewer].custom_pitch;
254
               the_board.players[viewer_index].view_yaw = the_board.players[current_viewer].custom_yaw;
255
               the_board.players[viewer_index].view_distance = the_board.players[current_viewer].custom_distance;
256
            }
1 pmbaty 257
      }
258
 
259
      // chessboard menu, zoom in
260
      else if (wParam_loword == MENUID_CHESSBOARD_ZOOMIN)
261
      {
262
         // scroll up & save this as the new custom distance
263
         the_board.players[current_viewer].view_distance = max (48.0f, the_board.players[current_viewer].view_distance - 2.0f);
264
         the_board.players[current_viewer].custom_distance = the_board.players[current_viewer].view_distance;
265
         the_scene.update = true; // update the 3D scene
266
      }
267
 
268
      // chessboard menu, zoom out
269
      else if (wParam_loword == MENUID_CHESSBOARD_ZOOMOUT)
270
      {
271
         // scroll down & save this as the new custom distance
272
         the_board.players[current_viewer].view_distance = min (100.0f, the_board.players[current_viewer].view_distance + 2.0f);
273
         the_board.players[current_viewer].custom_distance = the_board.players[current_viewer].view_distance;
274
         the_scene.update = true; // update the 3D scene
275
      }
276
 
277
      // chessboard menu, change appearance
278
      else if (wParam_loword == MENUID_CHESSBOARD_CHANGEAPPEARANCE)
279
         DialogBox_ChangeAppearance ();
280
 
281
      // chessboard menu, display windows desktop
282
      else if (wParam_loword == MENUID_CHESSBOARD_DISPLAYWINDOWSDESKTOP)
283
         ShowWindow (hWnd, SW_MINIMIZE);
284
 
285
      // internet menu, show online players
286
      else if (wParam_loword == MENUID_INTERNET_SHOWONLINEPLAYERS)
287
         Window_Opponents ();
288
 
289
      // internet menu, show sought games
290
      else if (wParam_loword == MENUID_INTERNET_SHOWSOUGHTGAMES)
291
         Window_Sought ();
292
 
293
      // internet menu, seek game
294
      else if (wParam_loword == MENUID_INTERNET_SEEKGAME)
295
         DialogBox_SendSeek ();
296
 
297
      // internet menu, chatter channels
298
      else if (wParam_loword == MENUID_INTERNET_CHATTERCHANNELS)
299
         Window_ChatterChannels ();
300
 
301
      // internet menu, enter chat text
302
      else if (wParam_loword == MENUID_INTERNET_ENTERCHATTEXT)
303
         PostMessage (hWnd, WM_CHAR, L' ', 0); // emulate a space bar hit
304
 
305
      // internet menu, display player card
306
      else if (wParam_loword == MENUID_INTERNET_DISPLAYPLAYERCARD)
307
         DialogBox_PlayerInfoName ();
308
 
309
      // internet menu, display your card
310
      else if (wParam_loword == MENUID_INTERNET_DISPLAYYOURCARD)
311
      {
312
         local_player = Player_FindByType (PLAYER_HUMAN);
313
         if (local_player != NULL)
314
            PlayerCard_FindOrCreate (local_player->name); // display player's own player card
315
      }
316
 
317
      // internet menu, MOTD
318
      else if (wParam_loword == MENUID_INTERNET_MOTD)
319
         Window_MOTD ();
320
 
321
      // help menu, help
322
      else if (wParam_loword == MENUID_HELP_HELP)
29 pmbaty 323
      {
59 pmbaty 324
         swprintf_s (folder_path, WCHAR_SIZEOF (folder_path), L"%s\\Chess Giants (%s).html", app_path, languages[language_id].name);
325
         if (_waccess (folder_path, 0) != 0)
326
            swprintf_s (folder_path, WCHAR_SIZEOF (folder_path), L"%s\\Chess Giants (English).html", app_path);
29 pmbaty 327
         ShellExecute (NULL, L"open", folder_path, NULL, NULL, SW_MAXIMIZE); // fire up the help file
328
      }
1 pmbaty 329
 
330
      // help menu, get chess games
331
      else if (wParam_loword == MENUID_HELP_GETCHESSGAMES)
332
         ShellExecute (NULL, L"open", L"http://www.chessgames.com", NULL, NULL, SW_MAXIMIZE); // fire up the browser
333
 
21 pmbaty 334
      // help menu, add/modify visual themes
335
      else if (wParam_loword == MENUID_HELP_ADDMODIFYVISUALTHEMES)
336
      {
337
         swprintf_s (folder_path, WCHAR_SIZEOF (folder_path), L"%s\\themes", app_path);
338
         ShellExecute (NULL, L"open", folder_path, NULL, NULL, SW_SHOWNORMAL); // fire up Windows Explorer
339
      }
340
 
50 pmbaty 341
      // help menu, add/modify engines
342
      else if (wParam_loword == MENUID_HELP_ADDMODIFYENGINES)
343
      {
344
         swprintf_s (folder_path, WCHAR_SIZEOF (folder_path), L"%s\\engines", app_path);
345
         ShellExecute (NULL, L"open", folder_path, NULL, NULL, SW_SHOWNORMAL); // fire up Windows Explorer
346
      }
347
 
21 pmbaty 348
      // help menu, add/modify translations
349
      else if (wParam_loword == MENUID_HELP_ADDMODIFYTRANSLATIONS)
350
      {
351
         swprintf_s (folder_path, WCHAR_SIZEOF (folder_path), L"%s\\data\\languages", app_path);
352
         ShellExecute (NULL, L"open", folder_path, NULL, NULL, SW_SHOWNORMAL); // fire up Windows Explorer
353
      }
354
 
1 pmbaty 355
      // help menu, about
356
      else if (wParam_loword == MENUID_HELP_ABOUT)
357
         DialogBox_About (); // show the About dialog box
358
 
359
      // call the default window message processing function to keep things going
360
      return (DefWindowProc (hWnd, message, wParam, lParam));
361
   }
362
 
3 pmbaty 363
   /////////////////////////////////////////////////////
364
   // ctrl key press or release (while not in animation)
365
   else if ((message == WM_KEYDOWN) && (wParam == VK_CONTROL) && (animation_endtime + 1.0f < current_time))
366
   {
367
      ctrl_pressed = true; // remember the ctrl key is pressed
368
 
369
      // call the default window message processing function to keep things going
370
      return (DefWindowProc (hWnd, message, wParam, lParam));
371
   }
372
   else if ((message == WM_KEYUP) && (wParam == VK_CONTROL) && (animation_endtime + 1.0f < current_time))
373
   {
374
      ctrl_pressed = false; // remember the ctrl key is released
375
      rbutton_pushed = false; // remember button is released
376
      the_scene.update = true; // update the 3D scene
377
 
378
      // call the default window message processing function to keep things going
379
      return (DefWindowProc (hWnd, message, wParam, lParam));
380
   }
381
 
21 pmbaty 382
   //////////////////
383
   // MOUSE EVENTS //
384
   //////////////////
385
 
1 pmbaty 386
   ////////////////////////////////////////////////////////////////////////////////////////////////
21 pmbaty 387
   // left mouse button push
388
   else if (message == WM_LBUTTONDOWN)
3 pmbaty 389
   {
21 pmbaty 390
      // are we in animation OR are mouse commands NOT allowed ?
391
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
392
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
393
 
3 pmbaty 394
      // is the ctrl key pressed (emulates a right click) ?
395
      if (ctrl_pressed)
396
      {
397
         prevgui_x = GET_X_LPARAM (lParam); // remember mouse coordinates
398
         prevgui_y = GET_Y_LPARAM (lParam);
399
 
400
         // if we click something, stop moving the table immediately
401
 
24 pmbaty 402
         // cycle through both players and change their view angles EXCEPT the opponent if he's human
403
         for (viewer_index = 0; viewer_index < 2; viewer_index++)
404
            if ((the_board.players[viewer_index].type == PLAYER_COMPUTER)
405
                || (the_board.players[viewer_index].type == PLAYER_INTERNET)
406
                || (viewer_index == current_viewer))
407
            {
408
               the_board.players[viewer_index].view_pitch = current_pitch;
409
               the_board.players[viewer_index].view_yaw = current_yaw;
410
            }
411
 
3 pmbaty 412
         rbutton_pushed = true; // remember button is clicked
413
      }
414
 
415
      // call the default window message processing function to keep things going
416
      return (DefWindowProc (hWnd, message, wParam, lParam));
417
   }
418
 
419
   ////////////////////////////////////////////////////////////////////////////////////////////////
21 pmbaty 420
   // left mouse button release
421
   else if (message == WM_LBUTTONUP)
1 pmbaty 422
   {
21 pmbaty 423
      // are we in animation OR are mouse commands NOT allowed ?
424
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
425
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
426
 
3 pmbaty 427
      // is the ctrl key pressed (emulates a right click) ?
428
      if (ctrl_pressed)
429
      {
430
         rbutton_pushed = false; // remember button is released
431
         the_scene.update = true; // update the 3D scene
432
 
433
         // call the default window message processing function to keep things going
434
         return (DefWindowProc (hWnd, message, wParam, lParam));
435
      }
436
 
1 pmbaty 437
      prevgui_x = GET_X_LPARAM (lParam); // remember mouse coordinates
438
      prevgui_y = GET_Y_LPARAM (lParam);
439
 
440
      // get mouse coordinates
441
      gui_x = GET_X_LPARAM (lParam);
442
      gui_y = GET_Y_LPARAM (lParam);
443
 
444
      // is the left arrow displayed AND is the mouse hovering it ?
445
      if ((the_scene.gui.larrow.state != 0) && Button_IsHovered (&the_scene.gui.larrow, gui_x, gui_y))
446
         SendMessage (hWnd, WM_COMMAND, MENUID_CHESSBOARD_PREVIOUSMOVE, NULL); // send a "previous move" event
447
 
448
      // is the right arrow displayed AND is the mouse hovering it ?
449
      if ((the_scene.gui.rarrow.state != 0) && Button_IsHovered (&the_scene.gui.rarrow, gui_x, gui_y))
450
         SendMessage (hWnd, WM_COMMAND, MENUID_CHESSBOARD_NEXTMOVE, NULL); // send a "next move" event
451
 
452
      // is the chat button displayed AND is the mouse hovering it ?
453
      if ((the_scene.gui.chatbutton.state != 0) && Button_IsHovered (&the_scene.gui.chatbutton, gui_x, gui_y))
454
      {
455
         opposite_player = Player_FindByType (PLAYER_INTERNET); // get a hand on the remote player
456
 
457
         // find or create the corresponding interlocutor structure and fire it up
458
         if (opposite_player != NULL)
459
            Interlocutor_FindOrCreate (opposite_player->name);
460
      }
461
 
462
      // is the games button displayed AND is the mouse hovering it ?
463
      if ((the_scene.gui.gamesbutton.state != 0) && Button_IsHovered (&the_scene.gui.gamesbutton, gui_x, gui_y))
464
         Window_Sought (); // if so, display the sought games window
465
 
466
      // is the people button displayed AND is the mouse hovering it ?
467
      if ((the_scene.gui.peoplebutton.state != 0) && Button_IsHovered (&the_scene.gui.peoplebutton, gui_x, gui_y))
468
         Window_Opponents (); // if so, display the opponents window
469
 
470
      // is the parts selection line displayed AND is the mouse anywhere near it ?
471
      if (the_scene.gui.is_partspick_displayed && Render_IsMouseInBox (gui_x, gui_y, 0.0f, 0.0f, 100.0f, 11.0f))
472
      {
473
         // for each selectable part, if the mouse is on it, mark it as selected
474
         for (part_index = 0; part_index < 13; part_index++)
475
            if (Render_IsMouseInBox (gui_x, gui_y, part_index * (100.0f / 13.0f), 0, 100.0f / 13.0f, 11.0f))
476
            {
477
               the_scene.gui.partspick_selectedpart = selectable_parts[part_index]; // mark it as selected
478
               Audio_PlaySound (SOUNDTYPE_CLICK); // make a click sound
479
               break; // no need to search further if one selection was found
480
            }
481
      }
482
 
483
      // get current player and see if we're online
484
      current_player = Player_GetCurrent ();
485
      remote_player = Player_FindByType (PLAYER_INTERNET);
486
 
487
      // if we are not allowed to select anything, don't even try
488
      if ((current_player->type != PLAYER_HUMAN) || (the_board.viewed_move != the_board.move_count - 1)
489
          || ((remote_player != NULL) && !remote_player->is_in_game))
490
      {
491
         the_scene.update = true; // update the 3D scene
492
 
493
         // call the default window message processing function to keep things going
494
         return (DefWindowProc (hWnd, message, wParam, lParam));
495
      }
496
 
497
      // it's a single click. The user clicked on a square.
498
 
499
      // figure out the coordinates on table
500
      Render_MouseToFloor (gui_x, gui_y, &board_x, &board_y);
501
 
502
      // translate them to board coordinates
503
      the_board.hovered_position[0] = (int) floor ((20.0f - board_y) / 5.0f);
504
      the_board.hovered_position[1] = 7 - (int) floor ((20.0f - board_x) / 5.0f);
505
      highlight_endtime = 0; // stop highlighting anything
506
 
507
      // if it's outside the table, end the job
508
      if (!IS_VALID_POSITION (the_board.hovered_position))
509
      {
510
         the_scene.update = true; // update the 3D scene
511
 
512
         // call the default window message processing function to keep things going
513
         return (DefWindowProc (hWnd, message, wParam, lParam));
514
      }
515
 
516
      // we clicked a valid slot on the table
517
 
518
      current_move = &the_board.moves[the_board.viewed_move]; // quick access to current move
519
 
520
      ///////////////////////////////////
521
      // are we in parts placement mode ?
522
      if (the_board.game_state == STATE_SETUPPOSITION)
523
      {
524
         // quick access to line and column
525
         line = the_board.hovered_position[0];
526
         column = the_board.hovered_position[1];
527
 
528
         // figure out the color of the part we are placing
529
         if (the_scene.gui.partspick_selectedpart == tolower (the_scene.gui.partspick_selectedpart))
530
            part_color = COLOR_BLACK; // black color
531
         else
532
            part_color = COLOR_WHITE; // white color
533
 
534
         // are we erasing a king ? if so, replace it at its default location
535
         if ((current_move->slots[line][column].part == PART_KING) && (current_move->slots[line][column].color == COLOR_BLACK)
536
             && (the_scene.gui.partspick_selectedpart != 'k'))
537
         {
538
            // is it ALREADY the king's default location ? if so, give up
539
            if ((line == 7) && (column == 4))
540
            {
541
               Audio_PlaySound (SOUNDTYPE_ILLEGALMOVE); // play the "illegal move" sound
542
               return (DefWindowProc (hWnd, message, wParam, lParam)); // call the default window message proc
543
            }
544
 
545
            Move_SetSlot (current_move, 7, 4, COLOR_BLACK, PART_KING); // replace black king
546
         }
547
         else if ((current_move->slots[line][column].part == PART_KING) && (current_move->slots[line][column].color == COLOR_WHITE)
548
                  && (the_scene.gui.partspick_selectedpart != 'K'))
549
         {
550
            // is it ALREADY the king's default location ? if so, give up
551
            if ((line == 0) && (column == 4))
552
            {
553
               Audio_PlaySound (SOUNDTYPE_ILLEGALMOVE); // play the "illegal move" sound
554
               return (DefWindowProc (hWnd, message, wParam, lParam)); // call the default window message proc
555
            }
556
 
557
            Move_SetSlot (current_move, 0, 4, COLOR_WHITE, PART_KING); // replace white king
558
         }
559
 
560
         // place the selected part on the board
561
         if (tolower (the_scene.gui.partspick_selectedpart) == 'p')
562
            Move_SetSlot (current_move, line, column, part_color, PART_PAWN); // pawn
563
         else if (tolower (the_scene.gui.partspick_selectedpart) == 'r')
564
            Move_SetSlot (current_move, line, column, part_color, PART_ROOK); // rook
565
         else if (tolower (the_scene.gui.partspick_selectedpart) == 'n')
566
            Move_SetSlot (current_move, line, column, part_color, PART_KNIGHT); // knight
567
         else if (tolower (the_scene.gui.partspick_selectedpart) == 'b')
568
            Move_SetSlot (current_move, line, column, part_color, PART_BISHOP); // bishop
569
         else if (tolower (the_scene.gui.partspick_selectedpart) == 'q')
570
            Move_SetSlot (current_move, line, column, part_color, PART_QUEEN); // queen
571
         else if (tolower (the_scene.gui.partspick_selectedpart) == 'k')
572
         {
573
            // parse the board for other kings of the same color and erase them
574
            for (index_line = 0; index_line < 8; index_line++)
575
               for (index_column = 0; index_column < 8; index_column++)
576
                  if ((current_move->slots[index_line][index_column].color == part_color)
577
                      && (current_move->slots[index_line][index_column].part == PART_KING))
578
                     memset (&current_move->slots[index_line][index_column], 0, sizeof (boardslot_t)); // erase this slot
579
 
580
            Move_SetSlot (current_move, line, column, part_color, PART_KING); // king
581
         }
582
         else
583
            Move_SetSlot (current_move, line, column, 0, PART_NONE); // no part
584
 
585
         // figure out which sound to play
586
         if (the_scene.gui.partspick_selectedpart != ' ')
587
            Audio_PlaySound (SOUNDTYPE_MOVE); // play a move sound when placing a part
588
 
589
         the_scene.update = true; // update the 3D scene
590
 
591
         // call the default window message processing function to keep things going
592
         return (DefWindowProc (hWnd, message, wParam, lParam));
593
      }
594
      // end of parts placement mode
595
      //////////////////////////////
596
 
597
      // does a selection NOT exist yet ?
598
      if (!IS_VALID_POSITION (the_board.selected_position))
599
      {
600
         // is there a selectable part at this location ?
601
         if ((current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].part != PART_NONE)
602
            && (current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].color == Board_ColorToMove (&the_board)))
603
         {
604
            // mark the selected position as selected (and remember it)
605
            the_board.selected_position[0] = the_board.hovered_position[0];
606
            the_board.selected_position[1] = the_board.hovered_position[1];
607
         }
608
 
609
         the_scene.update = true; // update the 3D scene
610
 
611
         // call the default window message processing function to keep things going
612
         return (DefWindowProc (hWnd, message, wParam, lParam));
613
      }
614
 
615
      // a selection exists already
616
 
617
      // is it the slot that was previously selected ? (i.e, user wants to "unselect" it)
618
      if ((the_board.hovered_position[0] == the_board.selected_position[0]) && (the_board.hovered_position[1] == the_board.selected_position[1]))
619
      {
620
         // forget the selected position
621
         the_board.selected_position[0] = -1;
622
         the_board.selected_position[1] = -1;
623
 
624
         the_scene.update = true; // update the 3D scene
625
 
626
         // call the default window message processing function to keep things going
627
         return (DefWindowProc (hWnd, message, wParam, lParam));
628
      }
629
 
630
      // else is it another part of the same color ? (i.e, user wants to change the part he selected)
631
      else if ((current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].part != PART_NONE)
632
               && (current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].color == Board_ColorToMove (&the_board)))
633
      {
634
         // mark the selected position as selected (and remember it)
635
         the_board.selected_position[0] = the_board.hovered_position[0];
636
         the_board.selected_position[1] = the_board.hovered_position[1];
637
 
638
         the_scene.update = true; // update the 3D scene
639
 
640
         // call the default window message processing function to keep things going
641
         return (DefWindowProc (hWnd, message, wParam, lParam));
642
      }
643
 
644
      // else is it a possible move ?
645
      else if ((current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].flags & FLAG_POSSIBLEMOVE)
646
               || (current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].flags & FLAG_TAKEABLE))
647
      {
648
         // are we in check after the move ? (FIXME: call EP version of this func for en passant moves)
649
         if (Move_IsColorInCheckAfterTestMove (current_move, the_board.selected_position[0], the_board.selected_position[1], the_board.hovered_position[0], the_board.hovered_position[1], Board_ColorToMove (&the_board)))
650
         {
651
            Audio_PlaySound (SOUNDTYPE_ILLEGALMOVE); // play the "illegal move" sound
652
 
653
            the_scene.update = true; // update the 3D scene
654
 
655
            // call the default window message processing function to keep things going
656
            return (DefWindowProc (hWnd, message, wParam, lParam));
657
         }
658
 
659
         ////////////////////
660
         // movement is valid
661
 
662
         // do it
663
         Board_AppendMove (&the_board, the_board.selected_position[0], the_board.selected_position[1], the_board.hovered_position[0], the_board.hovered_position[1], PART_NONE, NULL);
664
         current_move = &the_board.moves[the_board.move_count - 1]; // update current move pointer
665
 
666
         // are we in internet mode ?
667
         if (remote_player != NULL)
668
            the_board.reevaluate = false; // if so, don't reevaluate the board yet, let the server do it
669
 
670
         // was it a pawn being promoted ? if so, display the dialog box and wait for the reply
671
         if ((current_move->slots[the_board.hovered_position[0]][the_board.hovered_position[1]].part == PART_PAWN)
672
             && ((the_board.hovered_position[0] == 0) || (the_board.hovered_position[0] == 7)))
673
            DialogBox_PawnPromotion (); // display the pawn promotion dialog box
674
 
675
         // else it was a normal move
676
         else
677
         {
678
            Board_SetSelectedAndHovered (&the_board, -1, -1, -1, -1); // forget the hovered and selected positions
679
            the_board.has_playerchanged = true; // and switch players
680
         }
681
 
682
         the_scene.update = true; // update the 3D scene
683
         animation_endtime = current_time + ANIMATION_DURATION; // play animation now
684
         sound_playtime = current_time + ANIMATION_DURATION - 0.1f; // play sound near the end of animation
685
 
686
         // call the default window message processing function to keep things going
687
         return (DefWindowProc (hWnd, message, wParam, lParam));
688
      }
689
 
690
      // else it's another location
691
 
692
      Audio_PlaySound (SOUNDTYPE_ILLEGALMOVE); // play the "illegal move" sound
693
 
694
      the_scene.update = true; // update the 3D scene
695
 
696
      // call the default window message processing function to keep things going
697
      return (DefWindowProc (hWnd, message, wParam, lParam));
698
   }
699
 
700
   ////////////////////////////////////////////////////////////////////////////////////////////////
21 pmbaty 701
   // right mouse button push
702
   else if (message == WM_RBUTTONDOWN)
1 pmbaty 703
   {
21 pmbaty 704
      // are we in animation OR are mouse commands NOT allowed ?
705
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
706
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
707
 
1 pmbaty 708
      prevgui_x = GET_X_LPARAM (lParam); // remember mouse coordinates
709
      prevgui_y = GET_Y_LPARAM (lParam);
710
 
711
      // if we click something, stop moving the table immediately
712
 
24 pmbaty 713
      // cycle through both players and change their view angles EXCEPT the opponent if he's human
714
      for (viewer_index = 0; viewer_index < 2; viewer_index++)
715
         if ((the_board.players[viewer_index].type == PLAYER_COMPUTER)
716
               || (the_board.players[viewer_index].type == PLAYER_INTERNET)
717
               || (viewer_index == current_viewer))
718
         {
719
            the_board.players[viewer_index].view_pitch = current_pitch;
720
            the_board.players[viewer_index].view_yaw = current_yaw;
721
         }
722
 
1 pmbaty 723
      rbutton_pushed = true; // remember button is clicked
724
 
725
      // call the default window message processing function to keep things going
726
      return (DefWindowProc (hWnd, message, wParam, lParam));
727
   }
728
 
729
   ////////////////////////////////////////////////////////////////////////////////////////////////
21 pmbaty 730
   // right mouse button release
731
   else if (message == WM_RBUTTONUP)
1 pmbaty 732
   {
21 pmbaty 733
      // are we in animation OR are mouse commands NOT allowed ?
734
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
735
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
736
 
1 pmbaty 737
      rbutton_pushed = false; // remember button is released
738
      the_scene.update = true; // update the 3D scene
739
 
740
      // call the default window message processing function to keep things going
741
      return (DefWindowProc (hWnd, message, wParam, lParam));
742
   }
743
 
21 pmbaty 744
   ////////////////////////////////////////////////////////////////////////////////////////////////
1 pmbaty 745
   // left mouse button DOUBLE-click
21 pmbaty 746
   else if (message == WM_LBUTTONDBLCLK)
1 pmbaty 747
   {
21 pmbaty 748
      // are we in animation OR are mouse commands NOT allowed ?
749
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
750
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
751
 
1 pmbaty 752
      // get mouse coordinates
753
      gui_x = GET_X_LPARAM (lParam);
754
      gui_y = GET_Y_LPARAM (lParam);
755
 
756
      // are we in game and did we click the move comments area ?
757
      if ((the_board.game_state >= STATE_PLAYING) && (the_board.viewed_move > 0) && Render_IsMouseInBox (gui_x, gui_y, 10.0f, 0.0f, 80.0f, 10.0f))
758
      {
759
         DialogBox_Comment (); // fire up the comment dialog box
760
         return (DefWindowProc (hWnd, message, wParam, lParam)); // call the default window message processing function to keep things going
761
      }
21 pmbaty 762
 
763
      // call the default window message processing function to keep things going
764
      return (DefWindowProc (hWnd, message, wParam, lParam));
1 pmbaty 765
   }
766
 
767
   ////////////////////////////////////////////////////////////////////////////////////////////////
768
   // mouse move (while not in animation)
21 pmbaty 769
   else if (message == WM_MOUSEMOVE)
1 pmbaty 770
   {
21 pmbaty 771
      // are we in animation OR are mouse commands NOT allowed ?
772
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
773
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
774
 
1 pmbaty 775
      // get mouse coordinates
776
      gui_x = GET_X_LPARAM (lParam);
777
      gui_y = GET_Y_LPARAM (lParam);
778
 
779
      // handle button update status
780
      the_scene.update |= Button_UpdateHoverState (&the_scene.gui.larrow, gui_x, gui_y);
781
      the_scene.update |= Button_UpdateHoverState (&the_scene.gui.rarrow, gui_x, gui_y);
782
      the_scene.update |= Button_UpdateHoverState (&the_scene.gui.chatbutton, gui_x, gui_y);
783
      the_scene.update |= Button_UpdateHoverState (&the_scene.gui.gamesbutton, gui_x, gui_y);
784
      the_scene.update |= Button_UpdateHoverState (&the_scene.gui.peoplebutton, gui_x, gui_y);
785
 
786
      // see if we're online
787
      remote_player = Player_FindByType (PLAYER_INTERNET);
788
 
789
      // are we online AND do we NOT have the right to select anything ?
790
      if ((remote_player != NULL) && !remote_player->is_in_game)
791
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default window message processing function to keep things going
792
 
793
      // is the parts selection line displayed AND is the mouse anywhere in it ?
794
      if (the_scene.gui.is_partspick_displayed && Render_IsMouseInBox (gui_x, gui_y, 0.0f, 0.0f, 100.0f, 11.0f))
795
      {
796
         // for each selectable part...
797
         for (part_index = 0; part_index < 13; part_index++)
798
         {
799
            // is the mouse hovering it ?
800
            if (Render_IsMouseInBox (gui_x, gui_y, part_index * (100.0f / 13.0f), 0, 100.0f / 13.0f, 11.0f))
801
            {
802
               // was it NOT hovered before ?
803
               if (the_scene.gui.partspick_hoveredpart != selectable_parts[part_index])
804
               {
805
                  the_scene.gui.partspick_hoveredpart = selectable_parts[part_index]; // mark it as hovered
806
                  the_scene.update = true; // update the scene
807
               }
808
            }
809
 
810
            // else was it hovered before ?
811
            else if (the_scene.gui.partspick_hoveredpart == selectable_parts[part_index])
812
            {
813
               the_scene.gui.partspick_hoveredpart = 0; // clear the hovered part
814
               the_scene.update = true; // update the scene
815
            }
816
         }
817
      }
818
      else
819
         the_scene.gui.partspick_hoveredpart = 0; // clear the hovered part
820
 
821
      // get current and opposite players
822
      current_player = Player_GetCurrent ();
823
      opposite_player = Player_GetOpposite ();
824
 
825
      // if right button was clicked, compute new pitch and yaw
826
      if (rbutton_pushed)
827
      {
24 pmbaty 828
         // cycle through both players and change their view angles EXCEPT the opponent if he's human
829
         for (viewer_index = 0; viewer_index < 2; viewer_index++)
830
            if ((the_board.players[viewer_index].type == PLAYER_COMPUTER)
831
                || (the_board.players[viewer_index].type == PLAYER_INTERNET)
832
                || (viewer_index == current_viewer))
833
            {
834
               the_board.players[viewer_index].view_pitch += (gui_y - prevgui_y) * 0.3f;
835
               if (the_board.players[viewer_index].view_pitch < 10.0f)
836
                  the_board.players[viewer_index].view_pitch = 10.0f; // wrap angles around so that they
25 pmbaty 837
               if (the_board.players[viewer_index].view_pitch > 89.99f)
838
                  the_board.players[viewer_index].view_pitch = 89.99f; // stay in the [10, 89.99] bounds
1 pmbaty 839
 
24 pmbaty 840
               the_board.players[viewer_index].view_yaw += (gui_x - prevgui_x) * 0.3f;
841
               the_board.players[viewer_index].view_yaw = WrapAngle (the_board.players[viewer_index].view_yaw);
1 pmbaty 842
 
24 pmbaty 843
               // save these as the new custom angles
844
               the_board.players[viewer_index].custom_pitch = the_board.players[viewer_index].view_pitch;
845
               the_board.players[viewer_index].custom_yaw = the_board.players[viewer_index].view_yaw;
1 pmbaty 846
 
24 pmbaty 847
               // when moving the table around, jump to ideal angles immediately
848
               current_pitch = the_board.players[viewer_index].view_pitch;
849
               current_yaw = the_board.players[viewer_index].view_yaw;
850
            }
1 pmbaty 851
 
852
         the_scene.update = true; // button was clicked, update the 3D scene
853
      }
854
 
855
      // else it's just the mouse wandering around ; have we the right to select something ?
856
      else if ((the_board.viewed_move == the_board.move_count - 1) && (current_player->type == PLAYER_HUMAN) && (highlight_endtime < current_time))
857
      {
858
         // save the old positions
859
         prev_hovered_position[0] = the_board.hovered_position[0];
860
         prev_hovered_position[1] = the_board.hovered_position[1];
861
 
862
         // figure out the coordinates on table
863
         Render_MouseToFloor (gui_x, gui_y, &board_x, &board_y);
864
 
865
         // translate them to board coordinates
866
         the_board.hovered_position[0] = (int) floor ((20.0f - board_y) / 5.0f);
867
         the_board.hovered_position[1] = 7 - (int) floor ((20.0f - board_x) / 5.0f);
868
 
869
         // do they differ from last time ?
870
         if ((the_board.hovered_position[0] != prev_hovered_position[0]) || (the_board.hovered_position[1] != prev_hovered_position[1]))
871
            the_scene.update = true; // if so, update scene
872
      }
873
 
874
      // has the user the right to leave a command AND is there no comment yet ?
875
      if ((the_board.game_state >= STATE_PLAYING) && (the_board.viewed_move > 0)
876
          && ((the_board.moves[the_board.viewed_move].comment == NULL) || (the_board.moves[the_board.viewed_move].comment[0] == 0)))
877
      {
878
         // is the mouse above the comments zone ? if so, display a dimmed hint text
879
         if (Render_IsMouseInBox (gui_x, gui_y, 30.0f, 0.0f, 40.0f, 10.0f))
880
         {
881
            if (!the_scene.gui.comment_text.is_displayed)
882
            {
883
               Scene_SetText (&the_scene.gui.comment_text, 50.0f, 5.0f, 40.0f, ALIGN_CENTER, ALIGN_CENTER, ALIGN_LEFT, chat_fontindex, RGBA_TO_RGBACOLOR (255, 255, 255, 127), 999999.0f, false, LOCALIZE (L"DoubleClickToEnterComment"));
884
               the_scene.update = true; // and update the scene
885
            }
886
         }
887
         else
888
         {
889
            if (the_scene.gui.comment_text.is_displayed)
890
            {
891
               the_scene.gui.comment_text.is_displayed = false; // if not, erase the hint text
892
               the_scene.update = true; // and update the scene
893
            }
894
         }
895
      }
896
 
897
      // remember these coordinates for next time
898
      prevgui_x = gui_x;
899
      prevgui_y = gui_y;
900
 
901
      // call the default window message processing function to keep things going
902
      return (DefWindowProc (hWnd, message, wParam, lParam));
903
   }
904
 
905
   ////////////////////////////////////////////////////////////////////////////////////////////////
21 pmbaty 906
   // mouse scroll
907
   else if (message == WM_MOUSEWHEEL)
1 pmbaty 908
   {
21 pmbaty 909
      // are we in animation OR are mouse commands NOT allowed ?
910
      if ((animation_endtime + 1.0f >= current_time) || (command_ignoretime >= current_time))
911
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default message proc to keep things going
912
 
1 pmbaty 913
      // see if we're online
914
      remote_player = Player_FindByType (PLAYER_INTERNET);
915
 
916
      // are we online AND do we NOT have the right to select anything ?
917
      if ((remote_player != NULL) && !remote_player->is_in_game)
918
         return (DefWindowProc (hWnd, message, wParam, lParam)); // if so, call the default window message processing function to keep things going
919
 
920
      // scroll up / scroll down ?
921
      if (GET_WHEEL_DELTA_WPARAM (wParam) > 0)
922
         the_board.players[current_viewer].view_distance = max (48.0f, the_board.players[current_viewer].view_distance - 2.0f);
923
      else if (GET_WHEEL_DELTA_WPARAM (wParam) < 0)
924
         the_board.players[current_viewer].view_distance = min (100.0f, the_board.players[current_viewer].view_distance + 2.0f);
925
 
926
      // save this as the new custom distance
927
      the_board.players[current_viewer].custom_distance = the_board.players[current_viewer].view_distance;
928
 
929
      // when moving the table around, jump to ideal angles immediately
930
      current_distance = the_board.players[current_viewer].view_distance;
931
 
932
      the_scene.update = true; // update the 3D scene
933
 
934
      // call the default window message processing function to keep things going
935
      return (DefWindowProc (hWnd, message, wParam, lParam));
936
   }
937
 
938
   ////////////////////////////////////////////////////////////////////////////////////////////////
939
   // keyboard release
940
   else if (message == WM_CHAR)
941
   {
942
      // are we in position setup mode ?
943
      if (the_board.game_state == STATE_SETUPPOSITION)
944
      {
945
         // is it the enter key ? if so, exit setup mode and start playing
946
         if (wParam == L'\r')
947
         {
948
            current_move = &the_board.moves[the_board.viewed_move]; // quick access to current move
949
 
950
            // (in)validate the castling positions
951
            if ((current_move->slots[0][0].color == COLOR_WHITE) && (current_move->slots[0][0].part == PART_ROOK)
952
                && (current_move->slots[0][4].color == COLOR_WHITE) && (current_move->slots[0][4].part == PART_KING))
953
               current_move->sides[COLOR_WHITE].longcastle_allowed = true; // white castling queenside allowed
954
            else
955
               current_move->sides[COLOR_WHITE].longcastle_allowed = false; // white castling queenside no longer possible
956
            if ((current_move->slots[0][7].color == COLOR_WHITE) && (current_move->slots[0][7].part == PART_ROOK)
957
                && (current_move->slots[0][4].color == COLOR_WHITE) && (current_move->slots[0][4].part == PART_KING))
958
               current_move->sides[COLOR_WHITE].shortcastle_allowed = true; // white castling kingside allowed
959
            else
960
               current_move->sides[COLOR_WHITE].shortcastle_allowed = false; // white castling kingside no longer possible
961
            if ((current_move->slots[7][0].color == COLOR_BLACK) && (current_move->slots[7][0].part == PART_ROOK)
962
                && (current_move->slots[7][4].color == COLOR_BLACK) && (current_move->slots[7][4].part == PART_KING))
963
               current_move->sides[COLOR_BLACK].longcastle_allowed = true; // white castling queenside allowed
964
            else
965
               current_move->sides[COLOR_BLACK].longcastle_allowed = false; // white castling queenside no longer possible
966
            if ((current_move->slots[7][7].color == COLOR_BLACK) && (current_move->slots[7][7].part == PART_ROOK)
967
                && (current_move->slots[7][4].color == COLOR_BLACK) && (current_move->slots[7][4].part == PART_KING))
968
               current_move->sides[COLOR_BLACK].shortcastle_allowed = true; // white castling kingside allowed
969
            else
970
               current_move->sides[COLOR_BLACK].shortcastle_allowed = false; // white castling kingside no longer possible
971
 
972
            current_move->color = COLOR_BLACK; // so that game starts with white
973
 
974
            // validate this board in Forsyth-Edwards Notation and reset it
975
            Move_DescribeInFEN (current_move);
976
            wcscpy_s (fen_string, WCHAR_SIZEOF (fen_string), current_move->fen_string); // have a copy of fen string
977
            Board_Reset (&the_board, fen_string);
978
 
979
            the_board.game_state = STATE_PLAYING; // start the game now
980
            the_board.reevaluate = true; // evaluate board again
981
 
982
            the_scene.gui.central_text.disappear_time = current_time + 1.0f; // fade out help text now (FIXME: ugly)
983
            the_scene.update = true; // update the 3D scene
984
 
985
            // call the default window message processing function to keep things going
986
            return (DefWindowProc (hWnd, message, wParam, lParam));
987
         }
988
      }
989
 
990
      // else are we in internet mode ?
991
      else if (Player_FindByType (PLAYER_INTERNET) != NULL)
992
      {
993
         entered_ccreply = &the_scene.gui.entered_ccreply; // quick access to entered ccreply
994
         local_player = Player_FindByType (PLAYER_HUMAN); // quick access to local player
995
         if (local_player == NULL)
996
            return (DefWindowProc (hWnd, message, wParam, lParam)); // theoretically impossible condition, but better be sure
997
         if (selected_chatterchannel == NULL)
998
            return (DefWindowProc (hWnd, message, wParam, lParam)); // theoretically impossible condition, but better be sure
999
 
1000
         // are we NOT entering text yet ?
1001
         if (!the_scene.gui.is_entering_text)
1002
         {
1003
            // is it the space bar ?
1004
            if (wParam == L' ')
1005
            {
1006
               the_scene.gui.is_entering_text = true; // remember we are entering text
1007
 
1008
               // reset the entered text buffer
1009
               entered_ccreply->text = (wchar_t *) SAFE_malloc (1, sizeof (wchar_t), false);
1010
               entered_ccreply->text[0] = 0; // only the null terminator will fit
1011
               entered_ccreply->text_length = 0; // and set its length to zero
1012
            }
1013
         }
1014
 
1015
         // else we are currently in text entering mode
1016
         else
1017
         {
1018
            // is the typed character a printable character ?
1019
            if (iswprint (wParam))
1020
            {
1021
               // if so, reallocate space in the typed buffer (include null terminator)
1022
               entered_ccreply->text = (wchar_t *) SAFE_realloc (entered_ccreply->text, entered_ccreply->text_length + 1, entered_ccreply->text_length + 1 + 1, sizeof (wchar_t), false);
1023
               swprintf_s (&entered_ccreply->text[entered_ccreply->text_length], 1 + 1, L"%c", wParam); // append character
1024
               entered_ccreply->text_length++; // buffer holds now one character more
1025
            }
1026
 
1027
            // else is the typed character a backspace AND is there text to erase ?
1028
            else if ((wParam == 0x08) && (entered_ccreply->text_length > 0))
1029
            {
1030
               // if so, reallocate space in the typed buffer (include null terminator)
1031
               entered_ccreply->text = (wchar_t *) SAFE_realloc (entered_ccreply->text, entered_ccreply->text_length + 1, entered_ccreply->text_length + 1 - 1, sizeof (wchar_t), false);
1032
               entered_ccreply->text[entered_ccreply->text_length - 1] = 0; // backspace, delete one character
1033
               entered_ccreply->text_length--; // buffer holds now one character less
1034
            }
1035
 
1036
            // else is the typed character the escape key ?
1037
            else if (wParam == 0x1b)
1038
            {
1039
               SAFE_free ((void **) &entered_ccreply->text); // reset the entered text buffer
1040
               entered_ccreply->text_length = 0; // and set its length to zero
1041
               the_scene.gui.is_entering_text = false; // and exit from the text entering mode
1042
            }
1043
 
1044
            // else is the typed character the enter key ?
1045
            else if (wParam == 0x0d)
1046
               the_scene.gui.is_entering_text = false; // enter, exit from the text entering mode (this will validate our reply)
1047
 
1048
            // else it's an illegal character
1049
            else
1050
               Audio_PlaySound (SOUNDTYPE_ILLEGALMOVE); // illegal character, beep the illegal move sound
1051
         }
1052
 
1053
         the_scene.update = true; // update the 3D scene
1054
 
1055
         // call the default window message processing function to keep things going
1056
         return (DefWindowProc (hWnd, message, wParam, lParam));
1057
      }
1058
   }
1059
 
1060
   ////////////////////////////////////////////////////////////////////////////////////////////////
1061
   // mouse move outside the window
1062
   else if (message == WM_NCMOUSEMOVE)
1063
   {
1064
      rbutton_pushed = false; // remember right button is released
1065
 
1066
      // call the default window message processing function to keep things going
1067
      return (DefWindowProc (hWnd, message, wParam, lParam));
1068
   }
1069
 
1070
   ////////////////////////////////////////////////////////////////////////////////////////////////
1071
   // window repaint
1072
   else if (message == WM_PAINT)
1073
   {
1074
      the_scene.update = true; // update the 3D scene
1075
 
1076
      // call the default window message processing function to keep things going
1077
      return (DefWindowProc (hWnd, message, wParam, lParam));
1078
   }
1079
 
1080
   // call the default window message processing function to keep things going
1081
   return (DefWindowProc (hWnd, message, wParam, lParam));
1082
}
1083
 
1084
 
1085
static bool Button_IsHovered (guibutton_t *button, int gui_x, int gui_y)
1086
{
1087
   // handy wrapper that returns whether a particular GUI button is hovered when the mouse is at the given coordinates
1088
 
1089
   return (Render_IsMouseInBox (gui_x, gui_y, button->left, button->top, button->width, button->height));
1090
}
1091
 
1092
 
1093
static bool Button_UpdateHoverState (guibutton_t *button, int gui_x, int gui_y)
1094
{
1095
   // this function updates the hover state of a GUI button, and returns TRUE if the
1096
   // scene needs to be updated, FALSE otherwise.
1097
 
1098
   // is the button displayed ?
1099
   if (button->state != 0)
1100
   {
1101
      // is the mouse hovering it ?
1102
      if (Render_IsMouseInBox (gui_x, gui_y, button->left, button->top, button->width, button->height))
1103
      {
1104
         // was it NOT hovered before ?
1105
         if (button->state != 2)
1106
         {
1107
            button->state = 2; // mark it as hovered
1108
            return (true); // return TRUE so as to update the scene
1109
         }
1110
      }
1111
 
1112
      // else was it hovered before ?
1113
      else if (button->state == 2)
1114
      {
1115
         button->state = 1; // else mark it as not hovered
1116
         return (true); // return TRUE so as to update the scene
1117
      }
1118
   }
1119
 
1120
   return (false); // no need to update the scene
1121
}