src/chess/rules.c

changeset 98
9cb41383540f
parent 87
d4d67105d4e1
equal deleted inserted replaced
97:f87cad9445b4 98:9cb41383540f
39 #include <stdlib.h> 39 #include <stdlib.h>
40 #include <sys/time.h> 40 #include <sys/time.h>
41 41
42 static GameState gamestate_copy_sim(GameState *gamestate) { 42 static GameState gamestate_copy_sim(GameState *gamestate) {
43 GameState simulation = *gamestate; 43 GameState simulation = *gamestate;
44 simulation.movecount = 0; /* simulations do not count moves */ 44
45 if (simulation.lastmove) { 45 // create a new move list for the simulation
46 MoveList *lastmovecopy = malloc(sizeof(MoveList)); 46 simulation.movecapacity = 4;
47 *lastmovecopy = *(simulation.lastmove); 47 simulation.movecount = 0;
48 simulation.movelist = simulation.lastmove = lastmovecopy; 48 simulation.moves = malloc(4 * sizeof(Move));
49
50 // copy the most recent move if a move was played
51 if (gamestate->movecount > 0) {
52 simulation.moves[0] = last_move(gamestate);
53 simulation.movecount++;
49 } 54 }
50 55
51 return simulation; 56 return simulation;
52 } 57 }
53 58
136 if (move->check) { 141 if (move->check) {
137 string[idx++] = gamestate->checkmate?'#':'+'; 142 string[idx++] = gamestate->checkmate?'#':'+';
138 } 143 }
139 } 144 }
140 145
141 static void addmove(GameState* gamestate, Move *move) { 146 static void addmove(GameState* gamestate, Move *data) {
142 MoveList *elem = malloc(sizeof(MoveList)); 147 if (gamestate->movecount == gamestate->movecapacity) {
143 elem->next = NULL; 148 gamestate->movecapacity += 64; /* 32 more full moves */
144 elem->move = *move; 149 gamestate->moves = realloc(gamestate->moves,
145 150 gamestate->movecapacity * sizeof(Move));
151 }
152
153 Move *move = &gamestate->moves[gamestate->movecount];
154 *move = *data;
155
146 struct timeval curtimestamp; 156 struct timeval curtimestamp;
147 gettimeofday(&curtimestamp, NULL); 157 gettimeofday(&curtimestamp, NULL);
148 elem->move.timestamp.tv_sec = curtimestamp.tv_sec; 158 move->timestamp.tv_sec = curtimestamp.tv_sec;
149 elem->move.timestamp.tv_usec = curtimestamp.tv_usec; 159 move->timestamp.tv_usec = (int32_t) curtimestamp.tv_usec;
150 160
151 if (gamestate->lastmove) { 161 if (gamestate->movecount > 0) {
152 struct movetimeval *lasttstamp = &(gamestate->lastmove->move.timestamp); 162 struct movetimeval lasttstamp = last_move(gamestate).timestamp;
153 uint64_t sec = curtimestamp.tv_sec - lasttstamp->tv_sec; 163 uint64_t sec = curtimestamp.tv_sec - lasttstamp.tv_sec;
154 suseconds_t micros; 164 suseconds_t micros;
155 if (curtimestamp.tv_usec < lasttstamp->tv_usec) { 165 if (curtimestamp.tv_usec < lasttstamp.tv_usec) {
156 micros = 1e6L-(lasttstamp->tv_usec - curtimestamp.tv_usec); 166 micros = 1000000-(lasttstamp.tv_usec - curtimestamp.tv_usec);
157 sec--; 167 sec--;
158 } else { 168 } else {
159 micros = curtimestamp.tv_usec - lasttstamp->tv_usec; 169 micros = curtimestamp.tv_usec - lasttstamp.tv_usec;
160 } 170 }
161 171
162 elem->move.movetime.tv_sec = sec; 172 move->movetime.tv_sec = sec;
163 elem->move.movetime.tv_usec = micros; 173 move->movetime.tv_usec = (int32_t) micros;
164
165 gamestate->lastmove->next = elem;
166 gamestate->lastmove = elem;
167 gamestate->movecount++;
168 } else { 174 } else {
169 elem->move.movetime.tv_usec = 0; 175 move->movetime.tv_usec = 0;
170 elem->move.movetime.tv_sec = 0; 176 move->movetime.tv_sec = 0;
171 gamestate->movelist = gamestate->lastmove = elem; 177 }
172 gamestate->movecount = 1; 178 gamestate->movecount++;
173 }
174 } 179 }
175 180
176 char getpiecechr(uint8_t piece) { 181 char getpiecechr(uint8_t piece) {
177 switch (piece & PIECE_MASK) { 182 switch (piece & PIECE_MASK) {
178 case ROOK: return 'R'; 183 case ROOK: return 'R';
365 gamestate_cleanup(&simulation); 370 gamestate_cleanup(&simulation);
366 if ((move->piece & PIECE_MASK) == KING) { 371 if ((move->piece & PIECE_MASK) == KING) {
367 return KING_MOVES_INTO_CHECK; 372 return KING_MOVES_INTO_CHECK;
368 } else { 373 } else {
369 /* last move is always not null in this case */ 374 /* last move is always not null in this case */
370 return gamestate->lastmove->move.check ? 375 return last_move(gamestate).check ?
371 KING_IN_CHECK : PIECE_PINNED; 376 KING_IN_CHECK : PIECE_PINNED;
372 } 377 }
373 } 378 }
374 379
375 /* correct check and checkmate flags (move is still valid) */ 380 /* correct check and checkmate flags (move is still valid) */
567 572
568 static int getlocation(GameState *gamestate, Move *move) { 573 static int getlocation(GameState *gamestate, Move *move) {
569 574
570 uint8_t color = move->piece & COLOR_MASK; 575 uint8_t color = move->piece & COLOR_MASK;
571 uint8_t piece = move->piece & PIECE_MASK; 576 uint8_t piece = move->piece & PIECE_MASK;
572 bool incheck = gamestate->lastmove?gamestate->lastmove->move.check:false; 577 bool incheck = gamestate->movecount > 0 ? last_move(gamestate).check:false;
573 578
574 Move threats[16], *threat = NULL; 579 Move threats[16], *threat = NULL;
575 uint8_t threatcount; 580 uint8_t threatcount;
576 581
577 if (get_threats(gamestate, move->torow, move->tofile, color, 582 if (get_threats(gamestate, move->torow, move->tofile, color,
766 uint8_t color) { 771 uint8_t color) {
767 if (!gameinfo->timecontrol) { 772 if (!gameinfo->timecontrol) {
768 return 0; 773 return 0;
769 } 774 }
770 775
771 if (gamestate->movelist) { 776 if (gamestate->movecount > 0) {
772 uint16_t time = gameinfo->time; 777 uint16_t time = gameinfo->time;
773 suseconds_t micros = 0; 778 suseconds_t micros = 0;
774 779
775 MoveList *movelist = color == WHITE ? 780 for (unsigned i = color == WHITE ? 0 : 1
776 gamestate->movelist : gamestate->movelist->next; 781 ; i < gamestate->movecount ; i += 2) {
777
778 while (movelist) {
779 time += gameinfo->addtime; 782 time += gameinfo->addtime;
780 783
781 struct movetimeval *movetime = &(movelist->move.movetime); 784 if (gamestate->moves[i].movetime.tv_sec >= time) {
782 if (movetime->tv_sec >= time) {
783 return 0; 785 return 0;
784 } 786 }
785 787
786 time -= movetime->tv_sec; 788 time -= gamestate->moves[i].movetime.tv_sec;
787 micros += movetime->tv_usec; 789 micros += gamestate->moves[i].movetime.tv_usec;
788
789 movelist = movelist->next ? movelist->next->next : NULL;
790 } 790 }
791 791
792 time_t sec; 792 time_t sec;
793 movelist = gamestate->lastmove; 793 Move *lastmove = &last_move(gamestate);
794 if ((movelist->move.piece & COLOR_MASK) != color) { 794 if ((lastmove->piece & COLOR_MASK) != color) {
795 struct movetimeval *lastmovetstamp = &(movelist->move.timestamp); 795 struct movetimeval lastmovetstamp = lastmove->timestamp;
796 struct timeval currenttstamp; 796 struct timeval currenttstamp;
797 gettimeofday(&currenttstamp, NULL); 797 gettimeofday(&currenttstamp, NULL);
798 micros += currenttstamp.tv_usec - lastmovetstamp->tv_usec; 798 micros += currenttstamp.tv_usec - lastmovetstamp.tv_usec;
799 sec = currenttstamp.tv_sec - lastmovetstamp->tv_sec; 799 sec = currenttstamp.tv_sec - lastmovetstamp.tv_sec;
800 if (sec >= time) { 800 if (sec >= time) {
801 return 0; 801 return 0;
802 } 802 }
803 803
804 time -= sec; 804 time -= sec;
805 } 805 }
806 806
807 sec = micros / 1e6L; 807 sec = micros / 1000000;
808 808
809 if (sec >= time) { 809 if (sec >= time) {
810 return 0; 810 return 0;
811 } 811 }
812 812

mercurial