| 168 static void calc_movetime(GameState *gamestate, Move *move) { |
168 static void calc_movetime(GameState *gamestate, Move *move) { |
| 169 struct timeval curtimestamp; |
169 struct timeval curtimestamp; |
| 170 gettimeofday(&curtimestamp, NULL); |
170 gettimeofday(&curtimestamp, NULL); |
| 171 move->timestamp.tv_sec = curtimestamp.tv_sec; |
171 move->timestamp.tv_sec = curtimestamp.tv_sec; |
| 172 move->timestamp.tv_usec = (int32_t) curtimestamp.tv_usec; |
172 move->timestamp.tv_usec = (int32_t) curtimestamp.tv_usec; |
| 173 |
173 move->movetime.tv_usec = 0; |
| |
174 move->movetime.tv_sec = 0; |
| 174 if (gamestate->movecount > 1) { |
175 if (gamestate->movecount > 1) { |
| 175 struct movetimeval lasttstamp = last_move(gamestate).timestamp; |
176 struct movetimeval lasttstamp = last_move(gamestate).timestamp; |
| 176 uint64_t sec = curtimestamp.tv_sec - lasttstamp.tv_sec; |
177 uint64_t sec = curtimestamp.tv_sec - lasttstamp.tv_sec; |
| 177 suseconds_t micros; |
178 suseconds_t micros; |
| 178 if (curtimestamp.tv_usec < lasttstamp.tv_usec) { |
179 if (curtimestamp.tv_usec < lasttstamp.tv_usec) { |
| 179 micros = 1000000-(lasttstamp.tv_usec - curtimestamp.tv_usec); |
180 micros = 1000000-(lasttstamp.tv_usec - curtimestamp.tv_usec); |
| 180 sec--; |
181 sec--; |
| 181 } else { |
182 } else { |
| 182 micros = curtimestamp.tv_usec - lasttstamp.tv_usec; |
183 micros = curtimestamp.tv_usec - lasttstamp.tv_usec; |
| 183 } |
184 } |
| 184 |
185 |
| 185 move->movetime.tv_sec = sec; |
186 while (micros >= 1000000) { |
| 186 move->movetime.tv_usec = (int32_t) micros; |
187 micros -= 1000000; |
| 187 } else { |
188 sec++; |
| 188 /* no move time for the first move of both white and black */ |
189 } |
| 189 move->movetime.tv_usec = 0; |
190 |
| 190 move->movetime.tv_sec = 0; |
191 if (sec >= gamestate->info.delay) { |
| |
192 move->movetime.tv_sec = sec; |
| |
193 move->movetime.tv_usec = (int32_t) micros; |
| |
194 } |
| 191 } |
195 } |
| 192 } |
196 } |
| 193 |
197 |
| 194 static void addmove(GameState* gamestate, Move *data) { |
198 static void addmove(GameState* gamestate, Move *data) { |
| 195 if (gamestate->movecount == gamestate->movecapacity) { |
199 if (gamestate->movecount == gamestate->movecapacity) { |
| 314 } |
318 } |
| 315 |
319 |
| 316 void gamestate_at_move(GameState *gamestate, |
320 void gamestate_at_move(GameState *gamestate, |
| 317 unsigned move_number, GameState *replay) { |
321 unsigned move_number, GameState *replay) { |
| 318 gamestate_init(replay); |
322 gamestate_init(replay); |
| |
323 memcpy(&replay->info, &gamestate->info, sizeof(GameInfo)); |
| 319 replay->review = true; |
324 replay->review = true; |
| 320 if (move_number > gamestate->movecount) { |
325 if (move_number > gamestate->movecount) { |
| 321 move_number = gamestate->movecount; |
326 move_number = gamestate->movecount; |
| 322 } |
327 } |
| 323 for (unsigned i = 0 ; i < move_number ; i++) { |
328 for (unsigned i = 0 ; i < move_number ; i++) { |
| 839 } else { |
844 } else { |
| 840 return false; |
845 return false; |
| 841 } |
846 } |
| 842 } |
847 } |
| 843 |
848 |
| 844 uint16_t remaining_movetime(GameInfo *gameinfo, GameState *gamestate, |
849 uint16_t remaining_movetime(GameState *gamestate, uint8_t color) { |
| 845 uint8_t color) { |
|
| 846 unsigned move_number = gamestate->movecount; |
850 unsigned move_number = gamestate->movecount; |
| 847 if (color == BLACK) { |
851 if (color == BLACK) { |
| 848 move_number |= 1; |
852 move_number |= 1; |
| 849 } else { |
853 } else { |
| 850 move_number = (move_number + 1) & ~1; |
854 move_number = (move_number + 1) & ~1; |
| 851 } |
855 } |
| 852 return remaining_movetime2(gameinfo, gamestate, move_number); |
856 return remaining_movetime2(gamestate, move_number); |
| 853 } |
857 } |
| 854 |
858 |
| 855 uint16_t remaining_movetime2(GameInfo *gameinfo, GameState *gamestate, |
859 uint16_t remaining_movetime2(GameState *gamestate, unsigned move_number) { |
| 856 unsigned move_number) { |
860 if (!gamestate->info.timecontrol) { |
| 857 if (!gameinfo->timecontrol) { |
|
| 858 return 0; |
861 return 0; |
| 859 } |
862 } |
| 860 |
863 |
| 861 unsigned total_time = gameinfo->time; |
864 unsigned total_time = gamestate->info.time; |
| 862 unsigned used_time = 0; |
865 unsigned used_time = 0; |
| 863 suseconds_t micros = 0; |
866 suseconds_t micros = 0; |
| 864 |
867 |
| 865 /* when this is a 0+X game, the clock starts with the increment */ |
868 /* when this is a 0+X game, the clock starts with the increment */ |
| 866 if (gameinfo->time == 0) { |
869 if (gamestate->info.time == 0) { |
| 867 total_time += gameinfo->addtime; |
870 total_time += gamestate->info.addtime; |
| 868 } |
871 } |
| 869 |
872 |
| 870 /* go through all already played moves */ |
873 /* go through all already played moves */ |
| 871 unsigned first_move = move_number % 2; |
874 unsigned first_move = move_number % 2; |
| 872 unsigned next_move = move_number; |
875 unsigned next_move = move_number; |
| 873 if (next_move > gamestate->movecount) next_move = gamestate->movecount; |
876 if (next_move > gamestate->movecount) next_move = gamestate->movecount; |
| 874 for (unsigned i = first_move ; i < next_move ; i += 2) { |
877 for (unsigned i = first_move ; i < next_move ; i += 2) { |
| 875 used_time += gamestate->moves[i].movetime.tv_sec; |
878 used_time += gamestate->moves[i].movetime.tv_sec; |
| 876 micros += gamestate->moves[i].movetime.tv_usec; |
879 micros += gamestate->moves[i].movetime.tv_usec; |
| 877 /* add increments starting with move 2 */ |
880 /* add increments starting with move 2 */ |
| 878 if (i > 1) total_time += gameinfo->addtime; |
881 if (i > 1) total_time += gamestate->info.addtime; |
| |
882 } |
| |
883 |
| |
884 /* apply microseconds */ |
| |
885 while (micros >= 1000000) { |
| |
886 micros -= 1000000; |
| |
887 used_time++; |
| 879 } |
888 } |
| 880 |
889 |
| 881 /* when the player is currently playing, count down the clock */ |
890 /* when the player is currently playing, count down the clock */ |
| 882 if (is_game_running(gamestate) && move_number > 1 && |
891 if (is_game_running(gamestate) && move_number > 1 && |
| 883 move_number == gamestate->movecount) { |
892 move_number == gamestate->movecount) { |
| 884 struct movetimeval lastmovetstamp = |
893 struct movetimeval lastmovetstamp = |
| 885 gamestate->moves[move_number - 1].timestamp; |
894 gamestate->moves[move_number - 1].timestamp; |
| 886 struct timeval currenttstamp; |
895 struct timeval currenttstamp; |
| 887 gettimeofday(¤ttstamp, NULL); |
896 gettimeofday(¤ttstamp, NULL); |
| 888 used_time += currenttstamp.tv_sec - lastmovetstamp.tv_sec; |
897 |
| 889 micros += currenttstamp.tv_usec - lastmovetstamp.tv_usec; |
898 /* calculate current move time */ |
| 890 } |
899 unsigned cmsec = currenttstamp.tv_sec - lastmovetstamp.tv_sec; |
| 891 |
900 suseconds_t cmusec = currenttstamp.tv_usec - lastmovetstamp.tv_usec; |
| 892 /* apply the microseconds */ |
901 |
| 893 used_time += micros / 1000000; |
902 /* add microseconds carried over from last move and apply both */ |
| |
903 cmusec += micros; |
| |
904 cmsec += cmusec / 1000000; |
| |
905 |
| |
906 /* add the time and respect a possible dealy */ |
| |
907 if (cmsec >= gamestate->info.delay) { |
| |
908 used_time += cmsec - gamestate->info.delay; |
| |
909 } |
| |
910 } |
| 894 |
911 |
| 895 return used_time >= total_time ? 0 : total_time - used_time; |
912 return used_time >= total_time ? 0 : total_time - used_time; |
| 896 } |
913 } |
| 897 |
914 |
| 898 int print_clk(uint16_t time, char *str, bool always_hours) { |
915 int print_clk(uint16_t time, char *str, bool always_hours) { |