src/chess/rules.c

changeset 130
3fc6b1d6cbe9
parent 129
189c7c77aaab
equal deleted inserted replaced
129:189c7c77aaab 130:3fc6b1d6cbe9
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(&currenttstamp, NULL); 896 gettimeofday(&currenttstamp, 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) {

mercurial