- // scene.cpp 
-   
- #include "common.h" 
-   
-   
- // prototypes of local functions 
- static void Scene_AddPart (scene_t *scene, int part_type, int part_color, float pos_x, float pos_y, float pos_z, float turn_yaw, float pitch); 
- static void Scene_AddTile (scene_t *scene, int tile_type, float scale, float pos_x, float pos_y, float pos_z, float turn_yaw); 
-   
-   
- // global variables used in this module only 
- static wchar_t connected_comment[4096]; 
- static wchar_t filename[MAX_PATH]; 
- static float simpleshadow_sizes[] = 
- { 
-    0, // #define PART_NONE 0 
-    2.5f, // #define PART_KING 1 
-    2.45f, // #define PART_QUEEN 2 
-    2.35f, // #define PART_BISHOP 3 
-    2.25f, // #define PART_KNIGHT 4 
-    2.15f, // #define PART_ROOK 5 
-    2.0f, // #define PART_PAWN 6 
- }; 
-   
-   
- void Scene_Init (scene_t *scene, board_t *board) 
- { 
-    // this function initializes the scene objects array and inserts the chess table in it 
-   
-    wchar_t format_string[4096]; 
-   
-    // allocate array for the board (3 objects) and zero it out 
-    scene->objects = (sceneobject_t *) SAFE_malloc (3, sizeof (sceneobject_t), true); 
-   
-    // insert the table edges, the table and the board 
-    scene->objects[0].mesh_index = theme->trim_meshindex; 
-    scene->objects[0].texture_index = theme->trim_texture; 
-    scene->objects[0].scale = 1.0f; 
-    scene->objects[1].mesh_index = theme->table_meshindex; 
-    scene->objects[1].texture_index = theme->table_texture; 
-    scene->objects[1].scale = 1.0f; 
-    scene->objects[2].mesh_index = theme->board_meshindex; 
-    scene->objects[2].texture_index = theme->board_texture; 
-    scene->objects[2].scale = 1.0f; 
-    scene->object_count = 3; 
-   
-    // reset the camera position for a cool slide-in effect, but only if autorotate is enabled 
-    if (options.want_autorotateon1vs1) 
-    { 
-       current_pitch = 6.0f; // autorotate is enabled, prepare for slide-in effect 
-       current_yaw = (Board_ColorToMove (board) == COLOR_WHITE ? 90.0f : -90.0f); 
-       current_distance = 40.0f; 
-    } 
-    else 
-    { 
-       current_pitch = 55.0f; // no autorotate, reset to standard view position directly 
-       current_yaw = (Board_ColorToMove (board) == COLOR_BLACK ? 90.0f : -90.0f); 
-       current_distance = 70.0f; 
-    } 
-   
-    // HACK to prevent the player to click and block the view angles while the slide-in is not finished 
-    command_ignoretime = current_time + 2.0f; // allow 2 seconds 
-   
-    // build the connected comment string (we use it as a global variable) 
-    wcscpy_s (format_string, WCHAR_SIZEOF (format_string), LOCALIZE (L"YouAreConnectedToX")); 
-    wcscat_s (format_string, WCHAR_SIZEOF (format_string), L"\n"); 
-    wcscat_s (format_string, WCHAR_SIZEOF (format_string), LOCALIZE (L"YouMayEitherDisplayThePlayersListOrTheSoughtGamesList")); 
-    wcscat_s (format_string, WCHAR_SIZEOF (format_string), L"\n"); 
-    wcscat_s (format_string, WCHAR_SIZEOF (format_string), LOCALIZE (L"PleaseReferToTheInternetMenu")); 
-    swprintf_s (connected_comment, WCHAR_SIZEOF (connected_comment), format_string, options.network.server_address); 
-   
-    // completely reset the whole GUI structure so as to NULL out all pointers 
-    memset (&scene->gui, 0, sizeof (scene->gui)); 
-   
-    // set the buttons locations 
-    Scene_SetButton (&scene->gui.larrow, 0.3f, 0.5f, 3.0f, 4.0f, larrow_spriteindex); 
-    Scene_SetButton (&scene->gui.rarrow, 3.3f, 0.5f, 3.0f, 4.0f, rarrow_spriteindex); 
-    Scene_SetButton (&scene->gui.chatbutton, 1.0f, 10.0f, 10.0f, 13.0f, chatbutton_spriteindex); 
-    Scene_SetButton (&scene->gui.gamesbutton, 1.0f, 35.0f, 10.0f, 13.0f, gamesbutton_spriteindex); 
-    Scene_SetButton (&scene->gui.peoplebutton, 1.0f, 60.0f, 10.0f, 13.0f, peoplebutton_spriteindex); 
-   
-    // remember to update the scene 
-    scene->update = true; 
-   
-    return; // finished 
- } 
-   
-   
- void Scene_Shutdown (scene_t *scene) 
- { 
-    // this function frees the memory space allocated for the 3D scene and clears its pointers 
-   
-    int cchistory_index; 
-   
-    // free GUI mallocated buffers 
-    SAFE_free ((void **) &scene->gui.arrow_text.buffer); 
-    scene->gui.arrow_text.is_displayed = false; 
-    SAFE_free ((void **) &scene->gui.comment_text.buffer); 
-    scene->gui.comment_text.is_displayed = false; 
-    SAFE_free ((void **) &scene->gui.history_text.buffer); 
-    scene->gui.history_text.is_displayed = false; 
-    SAFE_free ((void **) &scene->gui.clock_text.buffer); 
-    scene->gui.clock_text.is_displayed = false; 
-    SAFE_free ((void **) &scene->gui.turn_text.buffer); 
-    scene->gui.turn_text.is_displayed = false; 
-    SAFE_free ((void **) &scene->gui.central_text.buffer); 
-    scene->gui.central_text.is_displayed = false; 
-   
-    // for each entry in the CC history... 
-    for (cchistory_index = 0; cchistory_index < scene->gui.cchistory_count; cchistory_index++) 
-       SAFE_free ((void **) &scene->gui.cchistory[cchistory_index].text); // free its text buffer 
-    SAFE_free ((void **) &scene->gui.cchistory); // free the GUI's CC history 
-    scene->gui.cchistory_count = 0; 
-   
-    SAFE_free ((void **) &scene->objects); // free the scene objects array 
-    scene->object_count = 0; 
-   
-    return; // finished 
- } 
-   
-   
- void Scene_Update (scene_t *scene, board_t *board) 
- { 
-    // this function updates the scene objects to display with what's currently on the board 
-   
-    static bool rooksound_played = false; // hack to have two sounds when a king castles 
-   
-    boardslot_t *boardslot; 
-    boardmove_t *currentmove; 
-    player_t *local_player; 
-    player_t *network_player; 
-    player_t *current_player; 
-    player_t *opposite_player; 
-    wchar_t *history_text; // mallocated 
-    int historytext_size; 
-    unsigned char takenpart_type; 
-    int movement_direction; 
-    int line; 
-    int column; 
-    int pos_index; 
-    int part_index; 
-    int move_index; 
-    int start_index; 
-    int length; 
-    int threat_line; 
-    int threat_column; 
-    int minutes; 
-    int seconds; 
-    float flaticons_yaw; 
-    float source_x; 
-    float source_y; 
-    float target_x; 
-    float target_y; 
-    float current_x; 
-    float current_y; 
-    float current_z; 
-    int movement_diffco; 
-    int movement_diffli; 
-    float movement_maxheight; 
-    float movement_ratio; 
-   
-    // get the current player (we'll need it), its opponent and see if we're online 
-    current_player = Player_GetCurrent (); 
-    opposite_player = Player_GetOpposite (); 
-    network_player = Player_FindByType (PLAYER_INTERNET); 
-   
-    // determine display yaw (for flat icons) according to camera angle 
-    if ((current_yaw > 45.0f) && (current_yaw <= 135.0f)) 
-       flaticons_yaw = 180.0f; 
-    else if ((current_yaw > -45.0f) && (current_yaw <= 45.0f)) 
-       flaticons_yaw = 90.0f; 
-    else if ((current_yaw > -135.0f) && (current_yaw <= -45.0f)) 
-       flaticons_yaw = 0.0f; 
-    else 
-       flaticons_yaw = -90.0f; 
-   
-    // get the current move 
-    currentmove = &board->moves[board->viewed_move]; // quick access to current move 
-   
-    // fetch the background sprite from the theme 
-    if (want_custombackground) 
-       scene->background_spriteindex = custombg.sprite_index; // use the custom background if specified 
-    else 
-       scene->background_spriteindex = theme->bg.sprite_index; // else use the theme's supplied background 
-   
-    // shrink the scene objects array to leave just the board (3 objects) 
-    scene->objects = (sceneobject_t *) SAFE_realloc (scene->objects, scene->object_count, 3, sizeof (sceneobject_t), false); 
-    scene->object_count = 3; 
-   
-    // update the board theme 
-    scene->objects[0].mesh_index = theme->trim_meshindex; 
-    scene->objects[0].texture_index = theme->trim_texture; 
-    scene->objects[0].material_index = theme->trim_material; 
-    scene->objects[0].scale = 1.0f; 
-    scene->objects[1].mesh_index = theme->table_meshindex; 
-    scene->objects[1].texture_index = theme->table_texture; 
-    scene->objects[1].material_index = theme->table_material; 
-    scene->objects[1].scale = 1.0f; 
-    scene->objects[2].mesh_index = theme->board_meshindex; 
-    scene->objects[2].texture_index = theme->board_texture; 
-    scene->objects[2].material_index = theme->board_material; 
-    scene->objects[2].scale = 1.0f; 
-   
-    // draw the grid numbers if we want them 
-    if (want_grid) 
-       Scene_AddTile (scene, theme->grid_texture, 30.0f, 0.0f, 0.0f, 0.01f, 0.0f); 
-   
-    //////////////////////////////////////////////////////////////////////////////////////////////// 
-    // recompute the slot textures (only in play mode when we render the real board) 
-   
-    // erase all the slot flags 
-    for (line = 0; line < 8; line++) 
-       for (column = 0; column < 8; column++) 
-          currentmove->slots[line][column].flags = FLAG_NONE; // because we will recompute them 
-   
-    // cycle through all the grid again and see if either king is in check 
-    for (line = 0; line < 8; line++) 
-       for (column = 0; column < 8; column++) 
-       { 
-          boardslot = ¤tmove->slots[line][column]; // quick access to grid slot 
-   
-          if (boardslot->part != PART_KING) 
-             continue; // if this slot is not a king, skip it 
-   
-          // is this king currently threatened ? 
-          if (Move_IsKingThreatenedAtLocation (currentmove, boardslot->color, line, column, &threat_line, &threat_column)) 
-          { 
-             currentmove->slots[line][column].flags |= FLAG_CHECK; // mark it as threatened 
-             currentmove->slots[threat_line][threat_column].flags |= FLAG_THREAT; // and who threatens it 
-          } 
-       } 
-   
-    // are we in play mode ? i.e, are we rendering the last move ? 
-    if (board->viewed_move == board->move_count - 1) 
-    { 
-       // mark the selected position as selected 
-       if (IS_VALID_POSITION (board->selected_position)) 
-          currentmove->slots[board->selected_position[0]][board->selected_position[1]].flags |= FLAG_SELECTED; 
-   
-       // now cycle through all the grid again and see if some slots need to be coloured 
-       for (line = 0; line < 8; line++) 
-          for (column = 0; column < 8; column++) 
-          { 
-             boardslot = ¤tmove->slots[line][column]; // quick access to grid slot 
-   
-             if (!(boardslot->flags & FLAG_SELECTED)) 
-                continue; // if this slot is not selected, skip it 
-   
-             ////////////////////////////////////////////////////////////////////////////////////////// 
-             ////////////////////////////////////////// PAWN ////////////////////////////////////////// 
-             ////////////////////////////////////////////////////////////////////////////////////////// 
-             // is it a pawn ? 
-             if (boardslot->part == PART_PAWN) 
-             { 
-                // figure out movement direction 
-                if (boardslot->color == COLOR_WHITE) 
-                   movement_direction = 1; 
-                else 
-                   movement_direction = -1; 
-   
-                // if pawn has still room to move forward, it can 
-                if ((((line < 7) && (movement_direction == 1)) || ((line > 0) && (movement_direction == -1))) 
-                    && (currentmove->slots[line + movement_direction][column].part == PART_NONE)) 
-                { 
-                   currentmove->slots[line + movement_direction][column].flags |= FLAG_POSSIBLEMOVE; 
-   
-                   // if pawn is still in its initial slot, it can move twice forward 
-                   if ((((line == 1) && (movement_direction == 1)) || ((line == 6) && (movement_direction == -1))) 
-                       && (currentmove->slots[line + movement_direction * 2][column].part == PART_NONE)) 
-                      currentmove->slots[line + movement_direction * 2][column].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see if pawn can take a piece on its left 
-                if ((column > 0) && (currentmove->slots[line + movement_direction][column - 1].part != PART_NONE) 
-                    && (currentmove->slots[line + movement_direction][column - 1].color != currentmove->slots[line][column].color)) 
-                   currentmove->slots[line + movement_direction][column - 1].flags |= FLAG_TAKEABLE; 
-   
-                // see if pawn can take a piece on its right 
-                if ((column < 7) && (currentmove->slots[line + movement_direction][column + 1].part != PART_NONE) 
-                    && (currentmove->slots[line + movement_direction][column + 1].color != currentmove->slots[line][column].color)) 
-                   currentmove->slots[line + movement_direction][column + 1].flags |= FLAG_TAKEABLE; 
-   
-                // if previous move was a pawn rush, see if pawn can take "en passant" 
-                if ((currentmove->part == PART_PAWN) 
-                      && (currentmove->target[1] == currentmove->source[1]) // pawn moved in column 
-                      && (abs (currentmove->target[0] - currentmove->source[0]) == 2) // pawn rushed 
-                      && (currentmove->target[0] == line) // pawn is in line with us 
-                      && (abs (currentmove->target[1] - column) == 1)) // pawn is next to us 
-                   currentmove->slots[line + movement_direction][currentmove->target[1]].flags |= FLAG_TAKEABLE; 
-             } 
-   
-             ////////////////////////////////////////////////////////////////////////////////////////// 
-             ////////////////////////////////////////// ROOK ////////////////////////////////////////// 
-             ////////////////////////////////////////////////////////////////////////////////////////// 
-             // else is it a rook ? 
-             else if (boardslot->part == PART_ROOK) 
-             { 
-                // see how far rook can move upwards 
-                for (pos_index = line + 1; pos_index < 8; pos_index++) 
-                { 
-                   if (currentmove->slots[pos_index][column].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[pos_index][column].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[pos_index][column].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[pos_index][column].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far rook can move downwards 
-                for (pos_index = line - 1; pos_index >= 0; pos_index--) 
-                { 
-                   if (currentmove->slots[pos_index][column].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[pos_index][column].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[pos_index][column].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[pos_index][column].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far rook can move left 
-                for (pos_index = column - 1; pos_index >= 0; pos_index--) 
-                { 
-                   if (currentmove->slots[line][pos_index].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[line][pos_index].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[line][pos_index].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[line][pos_index].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far rook can move right 
-                for (pos_index = column + 1; pos_index < 8; pos_index++) 
-                { 
-                   if (currentmove->slots[line][pos_index].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[line][pos_index].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[line][pos_index].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[line][pos_index].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-             } 
-   
-             ////////////////////////////////////////////////////////////////////////////////////////// 
-             ///////////////////////////////////////// KNIGHT ///////////////////////////////////////// 
-             ////////////////////////////////////////////////////////////////////////////////////////// 
-             // else is it a knight ? 
-             else if (boardslot->part == PART_KNIGHT) 
-             { 
-                // peek knight's NNW move 
-                if ((column > 0) && (line < 6)) 
-                   if (currentmove->slots[line + 2][column - 1].part == PART_NONE) 
-                      currentmove->slots[line + 2][column - 1].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line + 2][column - 1].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line + 2][column - 1].flags |= FLAG_TAKEABLE; 
-   
-                // peek knight's NNE move 
-                if ((column < 7) && (line < 6)) 
-                   if (currentmove->slots[line + 2][column + 1].part == PART_NONE) 
-                      currentmove->slots[line + 2][column + 1].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line + 2][column + 1].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line + 2][column + 1].flags |= FLAG_TAKEABLE; 
-   
-                // peek knight's ENE move 
-                if ((column < 6) && (line < 7)) 
-                   if (currentmove->slots[line + 1][column + 2].part == PART_NONE) 
-                      currentmove->slots[line + 1][column + 2].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line + 1][column + 2].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line + 1][column + 2].flags |= FLAG_TAKEABLE; 
-   
-                // peek knight's ESE move 
-                if ((column < 6) && (line > 0)) 
-                   if (currentmove->slots[line - 1][column + 2].part == PART_NONE) 
-                      currentmove->slots[line - 1][column + 2].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line - 1][column + 2].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line - 1][column + 2].flags |= FLAG_TAKEABLE; 
-   
-                // peek knight's SSW move 
-                if ((column > 0) && (line > 1)) 
-                   if (currentmove->slots[line - 2][column - 1].part == PART_NONE) 
-                      currentmove->slots[line - 2][column - 1].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line - 2][column - 1].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line - 2][column - 1].flags |= FLAG_TAKEABLE; 
-   
-                // peek knight's SSE move 
-                if ((column < 7) && (line > 1)) 
-                   if (currentmove->slots[line - 2][column + 1].part == PART_NONE) 
-                      currentmove->slots[line - 2][column + 1].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line - 2][column + 1].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line - 2][column + 1].flags |= FLAG_TAKEABLE; 
-   
-                // peek knight's WNW move 
-                if ((column > 1) && (line < 7)) 
-                   if (currentmove->slots[line + 1][column - 2].part == PART_NONE) 
-                      currentmove->slots[line + 1][column - 2].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line + 1][column - 2].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line + 1][column - 2].flags |= FLAG_TAKEABLE; 
-   
-                // peek knight's WSW move 
-                if ((column > 1) && (line > 0)) 
-                   if (currentmove->slots[line - 1][column - 2].part == PART_NONE) 
-                      currentmove->slots[line - 1][column - 2].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line - 1][column - 2].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line - 1][column - 2].flags |= FLAG_TAKEABLE; 
-             } 
-   
-             ////////////////////////////////////////////////////////////////////////////////////////// 
-             ///////////////////////////////////////// BISHOP ///////////////////////////////////////// 
-             ////////////////////////////////////////////////////////////////////////////////////////// 
-             // else is it a bishop ? 
-             else if (boardslot->part == PART_BISHOP) 
-             { 
-                // see how far bishop can move NE 
-                for (pos_index = 1; pos_index < 8; pos_index++) 
-                { 
-                   if ((line + pos_index > 7) || (column + pos_index > 7)) 
-                      break; 
-                   if (currentmove->slots[line + pos_index][column + pos_index].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[line + pos_index][column + pos_index].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[line + pos_index][column + pos_index].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[line + pos_index][column + pos_index].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far bishop can move SE 
-                for (pos_index = 1; pos_index < 8; pos_index++) 
-                { 
-                   if ((line - pos_index < 0) || (column + pos_index > 7)) 
-                      break; 
-                   if (currentmove->slots[line - pos_index][column + pos_index].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[line - pos_index][column + pos_index].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[line - pos_index][column + pos_index].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[line - pos_index][column + pos_index].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far bishop can move NW 
-                for (pos_index = 1; pos_index < 8; pos_index++) 
-                { 
-                   if ((line + pos_index > 7) || (column - pos_index < 0)) 
-                      break; 
-                   if (currentmove->slots[line + pos_index][column - pos_index].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[line + pos_index][column - pos_index].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[line + pos_index][column - pos_index].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[line + pos_index][column - pos_index].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far bishop can move SW 
-                for (pos_index = 1; pos_index < 8; pos_index++) 
-                { 
-                   if ((line - pos_index < 0) || (column - pos_index < 0)) 
-                      break; 
-                   if (currentmove->slots[line - pos_index][column - pos_index].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[line - pos_index][column - pos_index].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[line - pos_index][column - pos_index].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[line - pos_index][column - pos_index].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-             } 
-   
-             ////////////////////////////////////////////////////////////////////////////////////////// 
-             ///////////////////////////////////////// QUEEN ////////////////////////////////////////// 
-             ////////////////////////////////////////////////////////////////////////////////////////// 
-             // else is it a queen ? 
-             else if (boardslot->part == PART_QUEEN) 
-             { 
-                // see how far queen can move NE 
-                for (pos_index = 1; pos_index < 8; pos_index++) 
-                { 
-                   if ((line + pos_index > 7) || (column + pos_index > 7)) 
-                      break; 
-                   if (currentmove->slots[line + pos_index][column + pos_index].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[line + pos_index][column + pos_index].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[line + pos_index][column + pos_index].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[line + pos_index][column + pos_index].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far queen can move SE 
-                for (pos_index = 1; pos_index < 8; pos_index++) 
-                { 
-                   if ((line - pos_index < 0) || (column + pos_index > 7)) 
-                      break; 
-                   if (currentmove->slots[line - pos_index][column + pos_index].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[line - pos_index][column + pos_index].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[line - pos_index][column + pos_index].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[line - pos_index][column + pos_index].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far queen can move NW 
-                for (pos_index = 1; pos_index < 8; pos_index++) 
-                { 
-                   if ((line + pos_index > 7) || (column - pos_index < 0)) 
-                      break; 
-                   if (currentmove->slots[line + pos_index][column - pos_index].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[line + pos_index][column - pos_index].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[line + pos_index][column - pos_index].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[line + pos_index][column - pos_index].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far queen can move SW 
-                for (pos_index = 1; pos_index < 8; pos_index++) 
-                { 
-                   if ((line - pos_index < 0) || (column - pos_index < 0)) 
-                      break; 
-                   if (currentmove->slots[line - pos_index][column - pos_index].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[line - pos_index][column - pos_index].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[line - pos_index][column - pos_index].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[line - pos_index][column - pos_index].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far queen can move upwards 
-                for (pos_index = line + 1; pos_index < 8; pos_index++) 
-                { 
-                   if (currentmove->slots[pos_index][column].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[pos_index][column].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[pos_index][column].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[pos_index][column].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far queen can move downwards 
-                for (pos_index = line - 1; pos_index >= 0; pos_index--) 
-                { 
-                   if (currentmove->slots[pos_index][column].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[pos_index][column].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[pos_index][column].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[pos_index][column].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far queen can move left 
-                for (pos_index = column - 1; pos_index >= 0; pos_index--) 
-                { 
-                   if (currentmove->slots[line][pos_index].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[line][pos_index].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[line][pos_index].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[line][pos_index].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-   
-                // see how far queen can move right 
-                for (pos_index = column + 1; pos_index < 8; pos_index++) 
-                { 
-                   if (currentmove->slots[line][pos_index].part != PART_NONE) 
-                   { 
-                      if (currentmove->slots[line][pos_index].color != currentmove->slots[line][column].color) 
-                         currentmove->slots[line][pos_index].flags |= FLAG_TAKEABLE; 
-                      break; 
-                   } 
-                   currentmove->slots[line][pos_index].flags |= FLAG_POSSIBLEMOVE; 
-                } 
-             } 
-   
-             ////////////////////////////////////////////////////////////////////////////////////////// 
-             ////////////////////////////////////////// KING ////////////////////////////////////////// 
-             ////////////////////////////////////////////////////////////////////////////////////////// 
-             // else is it a king ? 
-             else if (boardslot->part == PART_KING) 
-             { 
-                // see if king can move NE 
-                if ((line < 7) && (column < 7)) 
-                { 
-                   if (currentmove->slots[line + 1][column + 1].part == PART_NONE) 
-                      currentmove->slots[line + 1][column + 1].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line + 1][column + 1].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line + 1][column + 1].flags |= FLAG_TAKEABLE; 
-                } 
-   
-                // see if king can move SE 
-                if ((line > 0) && (column < 7)) 
-                { 
-                   if (currentmove->slots[line - 1][column + 1].part == PART_NONE) 
-                      currentmove->slots[line - 1][column + 1].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line - 1][column + 1].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line - 1][column + 1].flags |= FLAG_TAKEABLE; 
-                } 
-   
-                // see if king can move NW 
-                if ((line < 7) && (column > 0)) 
-                { 
-                   if (currentmove->slots[line + 1][column - 1].part == PART_NONE) 
-                      currentmove->slots[line + 1][column - 1].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line + 1][column - 1].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line + 1][column - 1].flags |= FLAG_TAKEABLE; 
-                } 
-   
-                // see if king can move SW 
-                if ((line > 0) && (column > 0)) 
-                { 
-                   if (currentmove->slots[line - 1][column - 1].part == PART_NONE) 
-                      currentmove->slots[line - 1][column - 1].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line - 1][column - 1].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line - 1][column - 1].flags |= FLAG_TAKEABLE; 
-                } 
-   
-                // see if king can move upwards 
-                if (line < 7) 
-                { 
-                   if (currentmove->slots[line + 1][column].part == PART_NONE) 
-                      currentmove->slots[line + 1][column].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line + 1][column].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line + 1][column].flags |= FLAG_TAKEABLE; 
-                } 
-   
-                // see if king can move downwards 
-                if (line > 0) 
-                { 
-                   if (currentmove->slots[line - 1][column].part == PART_NONE) 
-                      currentmove->slots[line - 1][column].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line - 1][column].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line - 1][column].flags |= FLAG_TAKEABLE; 
-                } 
-   
-                // see if king can move right 
-                if (column < 7) 
-                { 
-                   if (currentmove->slots[line][column + 1].part == PART_NONE) 
-                      currentmove->slots[line][column + 1].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line][column + 1].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line][column + 1].flags |= FLAG_TAKEABLE; 
-                } 
-   
-                // see if king can move left 
-                if (column > 0) 
-                { 
-                   if (currentmove->slots[line][column - 1].part == PART_NONE) 
-                      currentmove->slots[line][column - 1].flags |= FLAG_POSSIBLEMOVE; 
-                   else if (currentmove->slots[line][column - 1].color != currentmove->slots[line][column].color) 
-                      currentmove->slots[line][column - 1].flags |= FLAG_TAKEABLE; 
-                } 
-   
-                // can king castle bishopside ? 
-                if (currentmove->sides[boardslot->color].shortcastle_allowed // no parts have moved yet 
-                    && (currentmove->slots[line][5].part == PART_NONE) // no other part... 
-                    && (currentmove->slots[line][6].part == PART_NONE) // ...in the way 
-                    && !Move_IsCheck (currentmove, boardslot->color) // king not currently in check 
-                    && !Move_IsKingThreatenedAtLocation (currentmove, boardslot->color, line, 5, &threat_line, &threat_column)) // king's way safe 
-                   currentmove->slots[line][column + 2].flags |= FLAG_POSSIBLEMOVE; // allow castling bishopside 
-   
-                // can king castle queenside ? 
-                if (currentmove->sides[boardslot->color].longcastle_allowed // no parts have moved yet 
-                    && (currentmove->slots[line][3].part == PART_NONE) // no other part... 
-                    && (currentmove->slots[line][2].part == PART_NONE) // ...is... 
-                    && (currentmove->slots[line][1].part == PART_NONE) // ...in the way 
-                    && !Move_IsCheck (currentmove, boardslot->color) // king not currently in check 
-                    && !Move_IsKingThreatenedAtLocation (currentmove, boardslot->color, line, 3, &threat_line, &threat_column)) // king's way safe 
-                   currentmove->slots[line][column - 2].flags |= FLAG_POSSIBLEMOVE; // allow castling queenside 
-             } 
-          } 
-    } // end if (play mode) 
-   
-    //////////////////////////////////////////////////////////////////////////////////////////////// 
-    // now place the parts that are off-board (taken parts) 
-   
-    // but only if we want them displayed 
-    if (options.want_takenparts) 
-    { 
-       // draw the white player's taken parts, place the part off the board (watch out for the hack...) 
-       for (part_index = 0; part_index < currentmove->sides[COLOR_WHITE].takenpart_count; part_index++) 
-       { 
-          takenpart_type = currentmove->sides[COLOR_WHITE].takenparts[part_index]; 
-   
-          // do we want the 3D models or the flat icons ? 
-          // we do when EITHER we don't want flat icons OR the current player is looking downstraight 
-          if (!want_flaticons || (current_pitch < MAX_PITCH_FOR_FLAT_ICONS)) 
-             Scene_AddPart (scene, takenpart_type, COLOR_BLACK, (part_index < MAX_STACKABLE_PARTS ? 23.2f : 26.8f), 
-                            (part_index % MAX_STACKABLE_PARTS == 0 ? 23.2f : scene->objects[scene->object_count - 1].y - (scene->objects[scene->object_count - 1].simpleshadow_size + simpleshadow_sizes[takenpart_type]) * 0.75f), 
-                            0.04f, (takenpart_type == PART_PAWN ? -90.0f : 100.0f), 0.0f); // rotate pawns 90° 
-          else 
-             Scene_AddTile (scene, theme->flattextures[COLOR_BLACK][takenpart_type], 1.25f, (part_index < MAX_STACKABLE_PARTS ? 23.2f : 26.8f), 
-                            20.0f - (part_index < MAX_STACKABLE_PARTS ? part_index : (part_index - MAX_STACKABLE_PARTS)) * 2.5f, 0.07f, flaticons_yaw); 
-       } 
-   
-       // now draw the black player's taken parts, place the part off the board (watch out for the hack...) 
-       for (part_index = 0; part_index < currentmove->sides[COLOR_BLACK].takenpart_count; part_index++) 
-       { 
-          takenpart_type = currentmove->sides[COLOR_BLACK].takenparts[part_index]; 
-   
-          // do we want the 3D models or the flat icons ? 
-          // we do when EITHER we don't want flat icons OR the current player is looking downstraight 
-          if (!want_flaticons || (current_pitch < MAX_PITCH_FOR_FLAT_ICONS)) 
-             Scene_AddPart (scene, takenpart_type, COLOR_WHITE, (part_index < MAX_STACKABLE_PARTS ? -23.2f : -26.8f), 
-                            (part_index % MAX_STACKABLE_PARTS == 0 ? -23.2f : scene->objects[scene->object_count - 1].y + (scene->objects[scene->object_count - 1].simpleshadow_size + simpleshadow_sizes[takenpart_type]) * 0.75f), 
-                            0.04f, (takenpart_type == PART_PAWN ? -90.0f : 100.0f), 0.0f); // rotate pawns 90° 
-          else 
-             Scene_AddTile (scene, theme->flattextures[COLOR_WHITE][takenpart_type], 1.25f, (part_index < MAX_STACKABLE_PARTS ? -23.2f : -26.8f), 
-                            -20.0f + (part_index < MAX_STACKABLE_PARTS ? part_index : (part_index - MAX_STACKABLE_PARTS)) * 2.5f, 0.07f, flaticons_yaw); 
-       } 
-    } 
-   
-    //////////////////////////////////////////////////////////////////////////////////////////////// 
-    // now draw the textured slots 
-   
-    // cycle through all the board slots... 
-    for (line = 0; line < 8; line++) 
-       for (column = 0; column < 8; column++) 
-       { 
-          if (currentmove->slots[line][column].flags == FLAG_NONE) 
-             continue; // skip everything that doesn't need to be drawn 
-   
-          // draw the texture we want. Only one texture is allowed, so PRIORITY MATTERS. 
-          if (currentmove->slots[line][column].flags & FLAG_SELECTED) 
-             Scene_AddTile (scene, theme->selected_textureindex, 2.5f, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.02f, 0.0f); 
-          else if (options.want_threats && currentmove->slots[line][column].flags & FLAG_CHECK) 
-             Scene_AddTile (scene, theme->check_textureindex, 2.5f, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.02f, 0.0f); 
-          else if (options.want_possiblemoves && currentmove->slots[line][column].flags & FLAG_POSSIBLEMOVE) 
-             Scene_AddTile (scene, theme->possiblemove_textureindex, 2.5f, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.02f, 0.0f); 
-          else if (options.want_possiblemoves && currentmove->slots[line][column].flags & FLAG_TAKEABLE) 
-             Scene_AddTile (scene, theme->takeable_textureindex, 2.5f, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.02f, 0.0f); 
-          else if (options.want_threats && currentmove->slots[line][column].flags & FLAG_THREAT) 
-             Scene_AddTile (scene, theme->threat_textureindex, 2.5f, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.02f, 0.0f); 
-       } 
-   
-    // is it time to draw the hovered slot and last move textures on the board slots ? 
-    if (animation_endtime < current_time) 
-    { 
-       // add the hovered slot tile (only when it should not be hidden because of highlighting) 
-       if (!is_paused && IS_VALID_POSITION (board->hovered_position) 
-           && ((highlight_endtime < current_time) || ((int) ((highlight_endtime - current_time) * 20.0f) % 2 == 1))) 
-          Scene_AddTile (scene, theme->hovered_textureindex, 3.1f, 
-                         17.5f - (7 - board->hovered_position[1]) * 5.0f, 
-                         17.5f - board->hovered_position[0] * 5.0f, 
-                         0.03f, 0.0f); // hovered tile 
-   
-       // and the previous move source and target 
-       if (options.want_lastmove && (board->move_count > 1) && (board->viewed_move > 0) 
-           && IS_VALID_POSITION (board->moves[board->viewed_move].source) 
-           && IS_VALID_POSITION (board->moves[board->viewed_move].target)) 
-       { 
-          Scene_AddTile (scene, theme->lastmovesource_textureindex, 2.5f, 
-                         17.5f - (7 - board->moves[board->viewed_move].source[1]) * 5.0f, 
-                         17.5f - board->moves[board->viewed_move].source[0] * 5.0f, 
-                         0.04f, 0.0f); // previous move source 
-          Scene_AddTile (scene, theme->lastmovetarget_textureindex, 2.5f, 
-                         17.5f - (7 - board->moves[board->viewed_move].target[1]) * 5.0f, 
-                         17.5f - board->moves[board->viewed_move].target[0] * 5.0f, 
-                         0.04f, 0.0f); // previous move target 
-       } 
-    } 
-   
-    //////////////////////////////////////////////////////////////////////////////////////////////// 
-    // now draw the 3D parts that are still in play 
-   
-    // cycle through all the grid and place all static parts 
-    for (line = 0; line < 8; line++) 
-    { 
-       for (column = 0; column < 8; column++) 
-       { 
-          boardslot = ¤tmove->slots[line][column]; // quick access to grid slot 
-   
-          // is there nothing on this grid slot ? 
-          if (boardslot->part == PART_NONE) 
-             continue; // then don't draw anything on it 
-   
-          // is this part not animated ? i.e.: 
-          // has no movement happened yet 
-          // OR does the movement NOT land on this slot 
-          //    AND is it NOT the tower concerned by a castle ? 
-          if ((board->viewed_move == 0) 
-              || (((line != currentmove->target[0]) || (column != currentmove->target[1])) 
-                  && ((towupper (currentmove->pgntext[0]) != L'O') 
-                      || (line != (currentmove->color == COLOR_WHITE ? 0 : 7)) || (column != (currentmove->target[1] == 2 ? 3 : 5))))) 
-          { 
-             // do we want the 3D models or the flat icons ? 
-             // we do when EITHER we don't want flat icons OR the player playing the current move is looking downstraight 
-             if (!want_flaticons || (current_pitch < MAX_PITCH_FOR_FLAT_ICONS)) 
-                Scene_AddPart (scene, boardslot->part, boardslot->color, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.04f, 0.0f, 0.0f); 
-             else 
-                Scene_AddTile (scene, theme->flattextures[boardslot->color][boardslot->part], 2.5f, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.05f, flaticons_yaw); 
-          } 
-       } // end for (column = 0; column < 8; column++) 
-    } // end for (line = 0; line < 8; line++) 
-   
-    // now do another pass and draw the part(s) that are currently moving 
-    for (line = 0; line < 8; line++) 
-    { 
-       for (column = 0; column < 8; column++) 
-       { 
-          boardslot = ¤tmove->slots[line][column]; // quick access to grid slot 
-   
-          // is there nothing on this grid slot ? 
-          if (boardslot->part == PART_NONE) 
-             continue; // then don't draw anything on it 
-   
-          // has a movement happened yet AND does it land on this slot ? 
-          if ((board->viewed_move > 0) 
-              && (line == currentmove->target[0]) && (column == currentmove->target[1])) 
-          { 
-             // do we want animations AND is it still time to play the animation ? 
-             if (options.want_animations && (animation_endtime > current_time)) 
-             { 
-                // get the source and target X and Y positions 
-                source_x = 17.5f - (7 - currentmove->source[1]) * 5.0f; 
-                source_y = 17.5f - currentmove->source[0] * 5.0f; 
-                target_x = 17.5f - (7 - currentmove->target[1]) * 5.0f; 
-                target_y = 17.5f - currentmove->target[0] * 5.0f; 
-   
-                // compute the movement completion ratio between 0 and 1 
-                movement_ratio = 1.0f - (animation_endtime - current_time) / ANIMATION_DURATION; 
-   
-                // compute the current X an Y based on movement timing 
-                current_x = source_x + (target_x - source_x) * movement_ratio; 
-                current_y = source_y + (target_y - source_y) * movement_ratio; 
-   
-                // do we want the 3D models or the flat icons ? 
-                // we do when EITHER we don't want flat icons OR the player playing the current move is looking downstraight 
-                if (!want_flaticons || (current_pitch < MAX_PITCH_FOR_FLAT_ICONS)) 
-                { 
-                   // height is a sine positive, max height is proportional to travelled distance 
-                   movement_diffco = abs (currentmove->target[1] - currentmove->source[1]); 
-                   movement_diffli = abs (currentmove->target[0] - currentmove->source[0]); 
-                   movement_maxheight = 0.5f + (float) movement_diffco + (float) movement_diffli; 
-                   if (currentmove->part == PART_KNIGHT) 
-                      movement_maxheight *= 2.0f; // knights jump high 
-                   else if ((currentmove->part == PART_KING) && (movement_diffco == 2)) 
-                      movement_maxheight *= 5.0f; // kings jump VERY high when castling too 
-                   else if (movement_maxheight > 5.0f) 
-                      movement_maxheight = 5.0f; // all other parts just hover above the ground 
-                   current_z = 0.04f + (float) sin (MATH_PI * movement_ratio) * movement_maxheight; 
-   
-                   // make this part move realistically 
-                   Scene_AddPart (scene, boardslot->part, boardslot->color, current_x, current_y, current_z, 0.0f, (boardslot->color == COLOR_BLACK ? -1 : 1) * min (current_z * 3.0f, 10.0f)); 
-                } 
-                else 
-                   Scene_AddTile (scene, theme->flattextures[boardslot->color][boardslot->part], 2.5f, current_x, current_y, 0.07f, flaticons_yaw); 
-             } 
-             else 
-             { 
-                // do we want the 3D models or the flat icons ? 
-                // we do when EITHER we don't want flat icons OR the current player is looking downstraight 
-                if (!want_flaticons || (current_pitch < MAX_PITCH_FOR_FLAT_ICONS)) 
-                   Scene_AddPart (scene, boardslot->part, boardslot->color, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.04f, 0.0f, 0.0f); 
-                else 
-                   Scene_AddTile (scene, theme->flattextures[boardslot->color][boardslot->part], 2.5f, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.05f, flaticons_yaw); 
-             } 
-   
-             // is it time to play a move sound ? 
-             if ((sound_playtime != 0) && (sound_playtime < current_time)) 
-             { 
-                // is the current player in checkmate, in check, in stalemate or is it a capture ? (to play the right sound) 
-                // read as: was the last move an opponent's move AND did it put us to check ? 
-                if (currentmove->is_check) 
-                { 
-                   Audio_PlaySound (SOUNDTYPE_MOVE, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.04f); // play the normal move sound 
-   
-                   // is it a checkmate or a normal check ? (checkmate == check + stalemate) 
-                   if (currentmove->is_stalemate) 
-                      Audio_PlaySound (board->players[currentmove->color].type == PLAYER_HUMAN ? SOUNDTYPE_VICTORY : SOUNDTYPE_DEFEAT, 0.0f, 0.0f, 0.04f); // if so, play endgame sound at the center of the board 
-                   else 
-                      Audio_PlaySound (SOUNDTYPE_CHECK, 0.0f, 0.0f, 0.04f); // else play the check sound at the center of the board 
-                } 
-                else if (currentmove->is_stalemate) 
-                { 
-                   Audio_PlaySound (SOUNDTYPE_MOVE, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.04f); // play the normal move sound 
-                   Audio_PlaySound (SOUNDTYPE_DEFEAT, 0.0f, 0.0f, 0.04f); // on stalemate, play defeat sound at the center of the board 
-                } 
-                else if (currentmove->has_captured) 
-                   Audio_PlaySound (SOUNDTYPE_PIECETAKEN, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.04f); // on capture, play the capture sound 
-                else 
-                   Audio_PlaySound (SOUNDTYPE_MOVE, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.04f); // play the normal move sound 
-   
-                sound_playtime = 0; // mark this animation as completed and sound played 
-             } 
-          } 
-   
-          // else has a movement happened yet AND is this movement a castle AND is this the concerned tower ? 
-          else if ((board->viewed_move > 0) 
-                   && (towupper (currentmove->pgntext[0]) == L'O') // either O-O-O or O-O 
-                   && (line == (currentmove->color == COLOR_WHITE ? 0 : 7)) && (column == (currentmove->target[1] == 2 ? 3 : 5))) 
-          { 
-             // do we want animations AND is it still time to play the animation ? (castling rooks move faster) 
-             if (options.want_animations && (animation_endtime - (0.5f * ANIMATION_DURATION) > current_time)) 
-             { 
-                // get the source and target X and Y positions 
-                source_x = 17.5f - (7 - (currentmove->target[1] == 2 ? 0 : 7)) * 5.0f; // if king moves left, then rook starts on column a, else it starts on column h 
-                source_y = 17.5f - line * 5.0f; 
-                target_x = 17.5f - (7 - column) * 5.0f; 
-                target_y = 17.5f - line * 5.0f; 
-   
-                // compute the movement completion ratio between 0 and 1 (castling rooks move faster) 
-                movement_ratio = min (1.0f, 1.0f - (animation_endtime - (0.5f * ANIMATION_DURATION) - current_time) / (0.5f * ANIMATION_DURATION)); 
-   
-                // compute the current X an Y based on movement timing 
-                current_x = source_x + (target_x - source_x) * movement_ratio; 
-                current_y = source_y + (target_y - source_y) * movement_ratio; 
-   
-                // height is a sine positive, max height is proportional to travelled distance 
-                movement_maxheight = 1.0f; // castling rook will barely hover above the ground 
-                current_z = 0.04f + (float) sin (MATH_PI * movement_ratio) * movement_maxheight; 
-   
-                // make this part move realistically - do we want the 3D models or the flat icons ? 
-                // we do when EITHER we don't want flat icons OR the player playing the current move is looking downstraight 
-                if (!want_flaticons || (current_pitch < MAX_PITCH_FOR_FLAT_ICONS)) 
-                   Scene_AddPart (scene, boardslot->part, boardslot->color, current_x, current_y, current_z, 0.0f, (boardslot->color == COLOR_BLACK ? -1 : 1) * min (current_z * 3.0f, 10.0f)); 
-                else 
-                   Scene_AddTile (scene, theme->flattextures[boardslot->color][boardslot->part], 2.5f, current_x, current_y, 0.09f, flaticons_yaw); 
-   
-                if (movement_ratio < 0.9f) 
-                   rooksound_played = false; // if the rook is still moving, reset the "sound played" flag 
-                else if (!rooksound_played) 
-                { 
-                   Audio_PlaySound (SOUNDTYPE_MOVE, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.04f); // when the rook has landed, play a move sound 
-                   rooksound_played = true; // remember this is no longer to be done 
-                } 
-             } 
-             else 
-             { 
-                // do we want the 3D models or the flat icons ? 
-                // we do when EITHER we don't want flat icons OR the current player is looking downstraight 
-                if (!want_flaticons || (current_pitch < MAX_PITCH_FOR_FLAT_ICONS)) 
-                   Scene_AddPart (scene, boardslot->part, boardslot->color, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.04f, 0.0f, 0.0f); 
-                else 
-                   Scene_AddTile (scene, theme->flattextures[boardslot->color][boardslot->part], 2.5f, 17.5f - (7 - column) * 5.0f, 17.5f - line * 5.0f, 0.05f, flaticons_yaw); 
-             } 
-          } 
-       } // end for (column = 0; column < 8; column++) 
-    } // end for (line = 0; line < 8; line++) 
-   
-    //////////////////////////////////////////////////////////////////////////////////// 
-    // now draw the sepia overlay if we're in history view mode or if the game is paused 
-   
-    if (options.want_sepiafilter && (is_paused || ((board->move_count > 1) && (board->viewed_move != board->move_count - 1)))) 
-       scene->overlay_spriteindex = sepia_spriteindex; // use the sepia filter 
-    else 
-       scene->overlay_spriteindex = -1; // else use natural colors 
-   
-    //////////////////////////////////////////////////////////////////////////////////////////////// 
-    // now draw the move comment text 
-   
-    // does the move we are viewing have a comment ? if so, copy it, else leave it clear. Also if we're online, display a help text 
-    if ((currentmove->comment != NULL) && (currentmove->comment[0] != 0)) 
-       Scene_SetText (&scene->gui.comment_text, 53.3f, 0.5f, 93.0f, ALIGN_CENTER, ALIGN_TOP, ALIGN_LEFT, chat_fontindex, RGBA_TO_RGBACOLOR (255, 255, 255, 191), 999999.0f, false, currentmove->comment); 
-    else if ((network_player != NULL) && network_player->is_logged_in && !network_player->is_in_game) 
-       Scene_SetText (&scene->gui.comment_text, 53.3f, 0.5f, 93.0f, ALIGN_CENTER, ALIGN_TOP, ALIGN_LEFT, chat_fontindex, RGBA_TO_RGBACOLOR (255, 255, 255, 191), 999999.0f, false, connected_comment); 
-    else if (RGBACOLOR_ALPHA (scene->gui.comment_text.color) >= 128) // HACK: don't clear if a dimmed hint text is already here 
-       scene->gui.comment_text.is_displayed = false; // else clear comment text 
-   
-    //////////////////////////////////////////////////////////////////////////////////////////////// 
-    // now draw the game clock 
-   
-    // do we want to print the game clock ? 
-    if (options.want_clock && (board->move_count > 1) && (board->game_state == STATE_PLAYING)) 
-    { 
-       network_player = Player_FindByType (PLAYER_INTERNET); // quick access to network player 
-   
-       // are we in Internet play ? if so, count time down, else count it up 
-       if ((network_player != NULL) && network_player->is_in_game) 
-          seconds = Player_GetCurrent ()->remaining_seconds - (int) (current_time - board->lastmove_time); // total seconds first 
-       else 
-          seconds = (int) (current_time - stoppage_time - board->lastmove_time); // total seconds first, take pauses in account 
-   
-       minutes = seconds / 60; // minutes 
-       seconds -= 60 * minutes; // remaining seconds 
-   
-       Scene_SetText (&the_scene.gui.clock_text, 99.0f, 66.6f, -1, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_RIGHT, players_fontindex, RGBACOLOR_SETALPHA (options.clock_color, 0x7f), 999999.0f, false, L"%02d:%02d  ", minutes, seconds); // note: last space is alt+255 
-    } 
-    else 
-       scene->gui.clock_text.is_displayed = false; 
-   
-    //////////////////////////////////////////////////////////////////////////////////////////////// 
-    // now draw the turn text 
-   
-    // do we want to print the player's turn AND has the game not ended yet ? if so, copy it, else leave it clear 
-    if (options.want_turn && (board->game_state == STATE_PLAYING)) 
-    { 
-       if (Board_ColorToMove (board) == COLOR_BLACK) 
-       { 
-          if (the_scene.gui.turn_text.color != 0x000000C0) 
-             Scene_SetText (&the_scene.gui.turn_text, 99.0f, 100.0f, -1, ALIGN_RIGHT, ALIGN_BOTTOM, ALIGN_RIGHT, players_fontindex, 0x000000C0, 999999.0f, true, LOCALIZE (L"BlackMoves")); 
-       } 
-       else 
-       { 
-          if (the_scene.gui.turn_text.color != 0xFFFFFF80) 
-             Scene_SetText (&the_scene.gui.turn_text, 99.0f, 100.0f, -1, ALIGN_RIGHT, ALIGN_BOTTOM, ALIGN_RIGHT, players_fontindex, 0xFFFFFF80, 999999.0f, true, LOCALIZE (L"WhiteMoves")); 
-       } 
-    } 
-    else 
-       scene->gui.turn_text.is_displayed = false; 
-   
-    //////////////////////////////////////////////////////////////////////////////////////////////// 
-    // now draw the game history text 
-   
-    // do we want to display the game history ? if so, display the game history text in PGN 
-    if (options.want_history && (board->move_count > 1)) 
-    { 
-       // first off, see where we start (for long games, we don't want to display EVERYTHING... 
-       if (board->viewed_move > 30) 
-          start_index = board->viewed_move - 30; // display 30 moves maximum 
-       else 
-          start_index = 1; 
-   
-       // allocate an arbitrary length history text string buffer (assume each move can't be longer than 15 characters) 
-       historytext_size = 15 * (1 + (board->viewed_move + 1) - start_index); 
-       history_text = (wchar_t *) SAFE_malloc (historytext_size, sizeof (wchar_t), false); 
-       history_text[0] = 0; // and reset it 
-   
-       // now for each move we want to display... 
-       for (move_index = start_index; move_index <= board->viewed_move; move_index++) 
-       { 
-          length = wcslen (history_text); // get current text length 
-   
-          // every move pair, append move pair number 
-          if (move_index % 2 == 1) 
-             swprintf_s (&history_text[length], historytext_size - length, L"%d.   ", 1 + move_index / 2); 
-   
-          // append move text 
-          wcscat_s (history_text, historytext_size, board->moves[move_index].pgntext); 
-          wcscat_s (history_text, historytext_size, L"   "); 
-   
-          // every odd move, drop a newline 
-          if (move_index % 2 == 0) 
-             wcscat_s (history_text, historytext_size, L"\n"); 
-       } 
-   
-       // add 50% alpha to game history color and transmit it to 3D engine 
-       Scene_SetText (&the_scene.gui.history_text, 100.0f, 50.0f, -1, ALIGN_RIGHT, ALIGN_BOTTOM, ALIGN_LEFT, chat_fontindex, RGBACOLOR_SETALPHA (options.history_color, 0x7f), 999999.0f, false, history_text); 
-       SAFE_free ((void **) &history_text); 
-    } 
-    else 
-       scene->gui.history_text.is_displayed = false; // if we don't need to display the game history, free the buffer 
-   
-    //////////////////////////////////////////////////////////////////////////////////////////////// 
-    // now draw the chat area 
-   
-    // is a valid chatter channel selected ? 
-    if ((selected_chatterchannel != NULL) && (chatterchannel_count > 0) && ((local_player = Player_FindByType (PLAYER_HUMAN)) != NULL)) 
-    { 
-       // set the chatter's name 
-       wcscpy_s (scene->gui.entered_ccreply.nickname, WCHAR_SIZEOF (scene->gui.entered_ccreply.nickname), local_player->name); 
-   
-       // correct or update the channel name and color 
-       if (selected_chatterchannel->theme[0] != 0) 
-          wcscpy_s (scene->gui.entered_ccreply.channelname, WCHAR_SIZEOF (scene->gui.entered_ccreply.channelname), selected_chatterchannel->theme); 
-       else 
-          swprintf_s (scene->gui.entered_ccreply.channelname, WCHAR_SIZEOF (scene->gui.entered_ccreply.channelname), L"%s %d", LOCALIZE (L"ChatterChannels_ColumnChannelNumber"), selected_chatterchannel->id); 
-       scene->gui.entered_ccreply.color = RGBACOLOR_FULLALPHA (selected_chatterchannel->color); // full bright for entering text 
-    } 
-   
-    // display parts pick line in position setup mode only 
-    scene->gui.is_partspick_displayed = (board->game_state == STATE_SETUPPOSITION ? true : false); 
-   
-    ////////////////////////// 
-    // error and notifications 
-   
-    // is the current player a computer AND are we playing a game right now 
-    // AND has the computer been thinking for more than 5 seconds AND is there no "thinking" text yet ? 
-    if ((board->players[Board_ColorToMove (board)].type == PLAYER_COMPUTER) && (board->game_state == STATE_PLAYING) 
-        && (board->lastmove_time + 5.0f < current_time) && !scene->gui.central_text.is_displayed) 
-    { 
-       Scene_SetText (&the_scene.gui.central_text, 50.0f, 40.0f, -1, ALIGN_CENTER, ALIGN_CENTER, ALIGN_CENTER, centermsg_fontindex, RGBA_TO_RGBACOLOR (255, 255, 255, 191), 
-                      999999.0f, true, LOCALIZE (L"Thinking")); // if so, display the "thinking" phrase in the middle of the screen 
-       the_scene.gui.want_spinwheel = true; // start spinning wheel 
-    } 
-   
-    // is there a network player AND is our socket gone AWOL ? 
-    else if ((network_player != NULL) && (network_player->our_socket == INVALID_SOCKET)) 
-    { 
-       // is there nothing in the center of the screen yet ? 
-       if (!the_scene.gui.central_text.is_displayed) 
-          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), 
-                         999999.0f, true, LOCALIZE (L"Error_ConnectionToChessServerLost")); // display "error" in the middle of the screen 
-       the_scene.overlay_spriteindex = sepia_spriteindex; // display sepia filter if no connection 
-    } 
-   
-    // is the game paused ? 
-    if (is_paused) 
-       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, 255), 
-                      1.0f, false, LOCALIZE (L"Paused")); // if so, display the "paused" phrase in the middle of the screen 
-   
-    return; // finished, scene is updated 
- } 
-   
-   
- void Scene_AddCCReply (scene_t *scene, wchar_t *nickname, wchar_t *channelname, unsigned long color_rgbx, wchar_t *fmt, ...) 
- { 
-    // helper function to add a CC reply on display 
-   
-    static wchar_t message[4096]; 
-    ccreply_t re; 
-    va_list argptr; 
-   
-    // concatenate all the arguments in one string 
-    va_start (argptr, fmt); 
-    _vsnwprintf_s (message, WCHAR_SIZEOF (message), _TRUNCATE, fmt, argptr); 
-    va_end (argptr); 
-   
-    // now put the text in place 
-    memset (&re, 0, sizeof (re)); // reset the structure we're about to fill 
-   
-    wcscpy_s (re.nickname, WCHAR_SIZEOF (re.nickname), nickname); // copy nickname 
-    wcscpy_s (re.channelname, WCHAR_SIZEOF (re.channelname), channelname); // copy channel name 
-   
-    re.text_length = wcslen (message); // get text length 
-    re.text = (wchar_t *) SAFE_malloc (re.text_length + 1, sizeof (wchar_t), false); // allocate text space (include null terminator) 
-    wcscpy_s (re.text, re.text_length + 1, message); // get the text 
-   
-    re.color = RGBACOLOR_SETALPHA (color_rgbx, 0xC0); // copy reply color and force a slightly transparent alpha 
-    re.arrival_time = current_time; // save CC reply arrival time 
-   
-    // reallocate CC history array to hold now one reply more 
-    the_scene.gui.cchistory = (ccreply_t *) SAFE_realloc (the_scene.gui.cchistory, the_scene.gui.cchistory_count, the_scene.gui.cchistory_count + 1, sizeof (ccreply_t), false); 
-    memcpy (&the_scene.gui.cchistory[the_scene.gui.cchistory_count], &re, sizeof (ccreply_t)); 
-    the_scene.gui.cchistory_count++; // CC history holds now one reply more 
-   
-    return; // finished, announcement text is set 
- } 
-   
-   
- void Scene_AddAnnouncement (scene_t *scene, wchar_t *fmt, ...) 
- { 
-    // helper function to set the announcement (red) text on display 
-   
-    static wchar_t message[4096]; 
-    ccreply_t re; 
-    va_list argptr; 
-   
-    // concatenate all the arguments in one string 
-    va_start (argptr, fmt); 
-    _vsnwprintf_s (message, WCHAR_SIZEOF (message), _TRUNCATE, fmt, argptr); 
-    va_end (argptr); 
-   
-    // now put the text in place 
-    memset (&re, 0, sizeof (re)); // reset the structure we're about to fill 
-   
-    re.text_length = wcslen (message); // get text length 
-    re.text = (wchar_t *) SAFE_malloc (re.text_length + 1, sizeof (wchar_t), false); // allocate text space (include null terminator) 
-    wcscpy_s (re.text, re.text_length + 1, message); // get the text 
-   
-    wcscpy_s (re.channelname, WCHAR_SIZEOF (re.channelname), LOCALIZE (L"ImportantMessage")); 
-    re.color = RGBA_TO_RGBACOLOR (192, 0, 0, 0xE0); // fair red, a bit more opaque than normal messages 
-    re.arrival_time = current_time; // save announcement arrival time 
-   
-    // reallocate CC history array to hold now one reply more 
-    the_scene.gui.cchistory = (ccreply_t *) SAFE_realloc (the_scene.gui.cchistory, the_scene.gui.cchistory_count, the_scene.gui.cchistory_count + 1, sizeof (ccreply_t), false); 
-    memcpy (&the_scene.gui.cchistory[the_scene.gui.cchistory_count], &re, sizeof (ccreply_t)); 
-    the_scene.gui.cchistory_count++; // CC history holds now one reply more 
-   
-    return; // finished, announcement text is set 
- } 
-   
-   
- void Scene_SetButton (guibutton_t *button, float left, float top, float width, float height, int sprite_index) 
- { 
-    // helper function to set up a GUI button 
-   
-    button->left = left; 
-    button->top = top; 
-    button->width = width; 
-    button->height = height; 
-    button->sprite_index = sprite_index; 
-   
-    return; // finished, button is set 
- } 
-   
-   
- void Scene_SetText (guitext_t *text, float xpos_percent, float ypos_percent, float maxwidth_percent, int horizontal_align, int vertical_align, int text_align, int font_index, unsigned long color_rgba, float duration, bool want_fade, wchar_t *fmt, ...) 
- { 
-    // helper function to set some text on display 
-   
-    static wchar_t message[4096]; 
-    va_list argptr; 
-    int length; 
-   
-    // concatenate all the arguments in one string 
-    va_start (argptr, fmt); 
-    _vsnwprintf_s (message, WCHAR_SIZEOF (message), _TRUNCATE, fmt, argptr); 
-    va_end (argptr); 
-   
-    text->xpos_percent = xpos_percent; // save text's X position, in percents from left to right 
-    text->ypos_percent = ypos_percent; // save text's Y position, in percents from top to bottom 
-    text->maxwidth_percent = maxwidth_percent; // save text's max width before word wrapping 
-    text->horizontal_align = horizontal_align; // save text's horizontal alignment regarding the X position 
-    text->vertical_align = vertical_align; // save text's vertical alignment regarding the Y position 
-    text->text_align = text_align; // save text's horizontal alignment inside the bounding rectangle 
-    text->font_index = font_index; // save the index of the font with which to display this text 
-    text->color = color_rgba; // text's color, in RGBA 
-   
-    // now put the text in place 
-    length = wcslen (message) + 1; // include null terminator 
-    text->buffer = (wchar_t *) SAFE_realloc (text->buffer, text->buffer_size, length, sizeof (wchar_t), false); 
-    wcscpy_s (text->buffer, length, message); // copy message text 
-    text->buffer_size = length; // and save buffer length 
-   
-    text->appear_time = current_time; // save text arrival time 
-    text->disappear_time = current_time + duration; // make it last duration seconds 
-    text->want_fade = want_fade; // remember if text needs to be faded in and out 
-   
-    // mark this text for display 
-    text->is_displayed = true; 
-   
-    return; // finished, text is set 
- } 
-   
-   
- static void Scene_AddPart (scene_t *scene, int part_type, int part_color, float pos_x, float pos_y, float pos_z, float turn_yaw, float pitch) 
- { 
-    // helper function to add a specified part of the specified color to the rendered scene 
-   
-    sceneobject_t *object; 
-    partcolor_t *partcolor; 
-   
-    // reallocate space to hold one object more and blank it out 
-    scene->objects = (sceneobject_t *) SAFE_realloc (scene->objects, scene->object_count, scene->object_count + 1, sizeof (sceneobject_t), true); 
-   
-    object = &scene->objects[scene->object_count]; // quick access to object 
-   
-    object->mesh_index = theme->part_meshes[part_type]; // retrieve object mesh 
-    object->simpleshadow_size = simpleshadow_sizes[part_type]; // retrieve simple shadow size according to part type 
-    object->scale = 1.0f; // scale at 1 so far 
-   
-    // set object texture and material 
-    partcolor = &theme->part_colors[part_color]; // quick access to part color struct 
-    object->texture_index = partcolor->texture; 
-    object->material_index = partcolor->material; 
-   
-    // figure out object position on board 
-    object->x = pos_x; 
-    object->y = pos_y; 
-    object->z = pos_z; 
-   
-    // turn a color's all parts' yaw 180 degrees so as both sides face each other 
-    if (part_color == COLOR_WHITE) 
-       object->yaw = 180.0f; 
-    else 
-       object->yaw = 0.0f; 
-   
-    // and add the final turn pitch and yaw 
-    object->pitch = pitch; 
-    object->yaw = WrapAngle (object->yaw + turn_yaw); 
-   
-    scene->object_count++; // array holds now one object more 
-    return; // finished 
- } 
-   
-   
- static void Scene_AddTile (scene_t *scene, int texture_index, float scale, float pos_x, float pos_y, float pos_z, float turn_yaw) 
- { 
-    // helper function to add a specified part of the specified color to the rendered scene 
-   
-    sceneobject_t *object; 
-   
-    // reallocate space to hold one object more and blank it out 
-    scene->objects = (sceneobject_t *) SAFE_realloc (scene->objects, scene->object_count, scene->object_count + 1, sizeof (sceneobject_t), true); 
-   
-    object = &scene->objects[scene->object_count]; // quick access to object 
-   
-    // save object data 
-    object->mesh_index = -1; // objects that have -1 as mesh index are tiles 
-    object->texture_index = texture_index; 
-    object->material_index = -1; // objects will use the default material 
-   
-    // figure out object position on board 
-    object->x = pos_x; 
-    object->y = pos_y; 
-    object->z = pos_z; 
-    object->scale = scale; 
-   
-    // turn tile as requested 
-    object->yaw = turn_yaw; 
-   
-    scene->object_count++; // array holds now one object more 
-   
-    return; // finished 
- } 
-