src/chess/rules.c

changeset 99
231a79d93c0c
parent 98
9cb41383540f
child 100
685af47592b5
equal deleted inserted replaced
98:9cb41383540f 99:231a79d93c0c
156 struct timeval curtimestamp; 156 struct timeval curtimestamp;
157 gettimeofday(&curtimestamp, NULL); 157 gettimeofday(&curtimestamp, NULL);
158 move->timestamp.tv_sec = curtimestamp.tv_sec; 158 move->timestamp.tv_sec = curtimestamp.tv_sec;
159 move->timestamp.tv_usec = (int32_t) curtimestamp.tv_usec; 159 move->timestamp.tv_usec = (int32_t) curtimestamp.tv_usec;
160 160
161 if (gamestate->movecount > 0) { 161 if (gamestate->movecount > 1) {
162 struct movetimeval lasttstamp = last_move(gamestate).timestamp; 162 struct movetimeval lasttstamp = last_move(gamestate).timestamp;
163 uint64_t sec = curtimestamp.tv_sec - lasttstamp.tv_sec; 163 uint64_t sec = curtimestamp.tv_sec - lasttstamp.tv_sec;
164 suseconds_t micros; 164 suseconds_t micros;
165 if (curtimestamp.tv_usec < lasttstamp.tv_usec) { 165 if (curtimestamp.tv_usec < lasttstamp.tv_usec) {
166 micros = 1000000-(lasttstamp.tv_usec - curtimestamp.tv_usec); 166 micros = 1000000-(lasttstamp.tv_usec - curtimestamp.tv_usec);
170 } 170 }
171 171
172 move->movetime.tv_sec = sec; 172 move->movetime.tv_sec = sec;
173 move->movetime.tv_usec = (int32_t) micros; 173 move->movetime.tv_usec = (int32_t) micros;
174 } else { 174 } else {
175 /* no move time for the first move of both white and black */
175 move->movetime.tv_usec = 0; 176 move->movetime.tv_usec = 0;
176 move->movetime.tv_sec = 0; 177 move->movetime.tv_sec = 0;
177 } 178 }
178 gamestate->movecount++; 179 gamestate->movecount++;
179 } 180 }
767 } 768 }
768 } 769 }
769 770
770 uint16_t remaining_movetime(GameInfo *gameinfo, GameState *gamestate, 771 uint16_t remaining_movetime(GameInfo *gameinfo, GameState *gamestate,
771 uint8_t color) { 772 uint8_t color) {
773 unsigned move_number = gamestate->movecount;
774 if (color == BLACK) {
775 move_number |= 1;
776 } else {
777 move_number = (move_number + 1) & ~1;
778 }
779 return remaining_movetime2(gameinfo, gamestate, move_number);
780 }
781
782 uint16_t remaining_movetime2(GameInfo *gameinfo, GameState *gamestate,
783 unsigned move_number) {
772 if (!gameinfo->timecontrol) { 784 if (!gameinfo->timecontrol) {
773 return 0; 785 return 0;
774 } 786 }
775 787
776 if (gamestate->movecount > 0) { 788 unsigned total_time = gameinfo->time;
777 uint16_t time = gameinfo->time; 789 unsigned used_time = 0;
778 suseconds_t micros = 0; 790 suseconds_t micros = 0;
779 791
780 for (unsigned i = color == WHITE ? 0 : 1 792 /* go through all already played moves */
781 ; i < gamestate->movecount ; i += 2) { 793 unsigned first_move = move_number % 2;
782 time += gameinfo->addtime; 794 unsigned next_move = move_number;
783 795 if (next_move > gamestate->movecount) next_move = gamestate->movecount;
784 if (gamestate->moves[i].movetime.tv_sec >= time) { 796 for (unsigned i = first_move ; i < next_move ; i += 2) {
785 return 0; 797 used_time += gamestate->moves[i].movetime.tv_sec;
786 } 798 micros += gamestate->moves[i].movetime.tv_usec;
787 799 /* add increments starting with move 2 */
788 time -= gamestate->moves[i].movetime.tv_sec; 800 if (i > 1) total_time += gameinfo->addtime;
789 micros += gamestate->moves[i].movetime.tv_usec; 801 }
790 } 802
791 803 /* when the player is currently playing, count down the clock */
792 time_t sec; 804 if (is_game_running(gamestate) && move_number > 1 &&
793 Move *lastmove = &last_move(gamestate); 805 move_number == gamestate->movecount) {
794 if ((lastmove->piece & COLOR_MASK) != color) { 806 struct movetimeval lastmovetstamp =
795 struct movetimeval lastmovetstamp = lastmove->timestamp; 807 gamestate->moves[move_number - 1].timestamp;
796 struct timeval currenttstamp; 808 struct timeval currenttstamp;
797 gettimeofday(&currenttstamp, NULL); 809 gettimeofday(&currenttstamp, NULL);
798 micros += currenttstamp.tv_usec - lastmovetstamp.tv_usec; 810 used_time += currenttstamp.tv_sec - lastmovetstamp.tv_sec;
799 sec = currenttstamp.tv_sec - lastmovetstamp.tv_sec; 811 micros += currenttstamp.tv_usec - lastmovetstamp.tv_usec;
800 if (sec >= time) { 812 }
801 return 0; 813
802 } 814 /* apply the microseconds */
803 815 used_time += micros / 1000000;
804 time -= sec; 816
805 } 817 return used_time >= total_time ? 0 : total_time - used_time;
806 818 }
807 sec = micros / 1000000;
808
809 if (sec >= time) {
810 return 0;
811 }
812
813 time -= sec;
814
815 return time;
816 } else {
817 return gameinfo->time;
818 }
819 }

mercurial