/* 对当前时间增加 1 厘秒, 并判断当前时间是否到了需要重新安排触发列表的时候执行相应的安排. * 具体说就是到达 0x100 的整数倍时对第一级触发列表集中的触发列表进行重新安排, * 0x4000 的整数倍则是第二级触发列表集中的触发列表, 0x100000 的整数倍是第三级, 0x4000000 的整数倍是第四级. * 具体是该集中哪个列表取决于所在区间的值, 这个值将作为索引. 重新安排的算法参考 add_node 函数. * * 需要注意的是层级列表集的首节点是不会使用的, 除了当时间距离回绕时, 回绕的定时器会从第四级列表集的第一个节点开始放置, * 因而, 如果当前时间回绕时需要在那里重新安排触发列表. 此函数不是线程安全的. */ static void timer_shift(struct timer *T) { int mask = TIME_NEAR; uint32_t ct = ++T->time; if (ct == 0) { /* 如果当前时间产生回绕, 需要重新安排第四级列表集的第一个节点处的列表集 */ move_list(T, 3, 0); } else { /* 检查当前时间是哪个级别时间范围的整数倍, 并以上一级区间的值为索引进行重新安排. * 如果不是任何级别时间范围的整数倍, 将不做任何重新安排. */ uint32_t time = ct >> TIME_NEAR_SHIFT; int i=0; while ((ct & (mask-1))==0) { int idx=time & TIME_LEVEL_MASK; /* idx!=0 正表明层级列表集的首节点不会使用 */ if (idx!=0) { move_list(T, i, idx); break; } mask <<= TIME_LEVEL_SHIFT; time >>= TIME_LEVEL_SHIFT; ++i; } } }
static void timer_shift(struct timer *T) { int mask = TIME_NEAR; uint32_t ct = ++T->time; if (ct == 0) { move_list(T, 3, 0); } else { uint32_t time = ct >> TIME_NEAR_SHIFT; int i=0; while ((ct & (mask-1))==0) { int idx=time & TIME_LEVEL_MASK; if (idx!=0) { move_list(T, i, idx); break; } mask <<= TIME_LEVEL_SHIFT; time >>= TIME_LEVEL_SHIFT; ++i; } } }
static void timer_shift(struct timer *T) { int mask = TIME_NEAR; uint32_t ct = ++T->time; if (ct == 0) { move_list(T, 3, 0); } else { uint32_t time = ct >> TIME_NEAR_SHIFT; // 当前刻的分钟+小时+天+月 int i=0; while ((ct & (mask-1))==0) { // 当前时刻的秒回绕,找高一层挂接的定时器,如果高一层也回绕,就找更高一层的(分钟/小时/天/月) int idx=time & TIME_LEVEL_MASK; if (idx!=0) { move_list(T, i, idx); break; } mask <<= TIME_LEVEL_SHIFT; time >>= TIME_LEVEL_SHIFT; ++i; } } }
int hci_send_req(struct hci_request *r, BOOL async) { uint8_t *ptr; uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf)); hci_event_pckt *event_pckt; hci_uart_pckt *hci_hdr; int to = DEFAULT_TIMEOUT; struct timer t; tHciDataPacket * hciReadPacket = NULL; tListNode hciTempQueue; list_init_head(&hciTempQueue); hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam); if(async){ goto done; } /* Minimum timeout is 1. */ if(to == 0) to = 1; Timer_Set(&t, to); while(1) { evt_cmd_complete *cc; evt_cmd_status *cs; evt_le_meta_event *me; int len; #if ENABLE_MICRO_SLEEP while(1){ ATOMIC_SECTION_BEGIN(); if(Timer_Expired(&t)){ ATOMIC_SECTION_END(); goto failed; } if(!HCI_Queue_Empty()){ ATOMIC_SECTION_END(); break; } Enter_Sleep_Mode(); ATOMIC_SECTION_END(); } #else while(1){ if(Timer_Expired(&t)){ goto failed; } if(!HCI_Queue_Empty()){ break; } } #endif /* Extract packet from HCI event queue. */ Disable_SPI_IRQ(); list_remove_head(&hciReadPktRxQueue, (tListNode **)&hciReadPacket); hci_hdr = (void *)hciReadPacket->dataBuff; if(hci_hdr->type != HCI_EVENT_PKT){ list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket); // See comment below Enable_SPI_IRQ(); continue; } event_pckt = (void *) (hci_hdr->data); ptr = hciReadPacket->dataBuff + (1 + HCI_EVENT_HDR_SIZE); len = hciReadPacket->data_len - (1 + HCI_EVENT_HDR_SIZE); switch (event_pckt->evt) { case EVT_CMD_STATUS: cs = (void *) ptr; if (cs->opcode != opcode) goto failed; if (r->event != EVT_CMD_STATUS) { if (cs->status) { goto failed; } break; } r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, ptr, r->rlen); goto done; case EVT_CMD_COMPLETE: cc = (void *) ptr; if (cc->opcode != opcode) goto failed; ptr += EVT_CMD_COMPLETE_SIZE; len -= EVT_CMD_COMPLETE_SIZE; r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, ptr, r->rlen); goto done; case EVT_LE_META_EVENT: me = (void *) ptr; if (me->subevent != r->event) break; len -= 1; r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, me->data, r->rlen); goto done; case EVT_HARDWARE_ERROR: goto failed; default: break; } /* In the meantime there could be other events from the controller. In this case, insert the packet in a different queue. These packets will be inserted back in the main queue just before exiting from send_req(). */ list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket); /* Be sure there is at list one packet in the pool to process the expected event. */ if(list_is_empty(&hciReadPktPool)){ pListNode tmp_node; list_remove_head(&hciReadPktRxQueue, &tmp_node); list_insert_tail(&hciReadPktPool, tmp_node); } Enable_SPI_IRQ(); } failed: move_list(&hciReadPktRxQueue, &hciTempQueue); Enable_SPI_IRQ(); return -1; done: // Insert the packet back into the pool. list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket); move_list(&hciReadPktRxQueue, &hciTempQueue); Enable_SPI_IRQ(); return 0; }
double Alan_Turing_AI::position_play_value(const Board& board, Color perspective) const { double total_score = 0.0; for(char file = 'a'; file <= 'h'; ++file) { for(int rank = 1; rank <= 8; ++rank) { auto piece = board.piece_on_square(file, rank); if( ! piece) { continue; } if(piece->color() == perspective) { if(piece->type() == QUEEN || piece->type() == ROOK || piece->type() == BISHOP || piece->type() == KNIGHT) { // Number of moves score double move_score = 0.0; for(auto move : board.legal_moves()) { if(move->start_file() == file && move->start_rank() == rank) { move_score += 1.0; if(board.move_captures(*move)) { move_score += 1.0; } } } total_score += std::sqrt(move_score); // Non-queen pieces defended if(piece->type() != QUEEN) { auto defender_count = board.moves_attacking_square(file, rank, perspective).count(); if(defender_count > 0) { total_score += 1.0 + 0.5*(defender_count - 1); } } } else if(piece->type() == KING) { // King move scores double move_score = 0.0; double castling_moves = 0.0; for(auto move : board.legal_moves()) { if(move->start_file() != file || move->start_rank() != rank) { continue; } if(move->is_castling()) { castling_moves += 1.0; } else { move_score += 1.0; } } total_score += std::sqrt(move_score) + castling_moves; // King vulnerability (count number of queen moves from king square and subtract) double king_squares = 0.0; for(int file_step = -1; file_step <= 1; ++file_step) { for(int rank_step = -1; rank_step <= 1; ++rank_step) { if(file_step == 0 && rank_step == 0) { continue; } for(int steps = 1; steps <= 7; ++steps) { char attack_file = file + steps*file_step; int attack_rank = rank + steps*rank_step; if(!board.inside_board(attack_file, attack_rank)) { break; } auto other_piece = board.piece_on_square(attack_file, attack_rank); if( ! other_piece) { king_squares += 1.0; } else { if(other_piece->color() != perspective) { king_squares += 1.0; } break; } } } } total_score -= std::sqrt(king_squares); // Castling score if(!board.piece_has_moved(file, rank)) { // Queenside castling if( ! board.piece_has_moved('a', rank)) { total_score += 1.0; // Can castle on next move if(board.all_empty_between('a', rank, file, rank)) { total_score += 1.0; } } // Kingside castling if(!board.piece_has_moved('h', rank)) { total_score += 1.0; // Can castle on next move if(board.all_empty_between('h', rank, file, rank)) { total_score += 1.0; } } } // Last move was castling if(board.castling_move_index(perspective) < board.game_record().size()) { total_score += 1.0; } } else if(piece->type() == PAWN) { // Pawn advancement auto base_rank = (perspective == WHITE ? 2 : 7); total_score += 0.2*std::abs(base_rank - rank); // Pawn defended auto pawn_defended = false; for(auto piece_type :{QUEEN, ROOK, BISHOP, KNIGHT, KING}) { if(pawn_defended) { break; } auto defending_piece = board.piece_instance(piece_type, perspective); for(auto move : defending_piece->move_list(file, rank)) { if(defending_piece == board.piece_on_square(move->end_file(), move->end_rank())) { if(piece_type == KNIGHT || board.all_empty_between(file, rank, move->end_file(), move->end_rank())) { pawn_defended = true; break; } } } } if(pawn_defended) { total_score += 0.3; } } } else // piece->color() == opposite(perspective) { if(piece->type() == KING) { auto temp_board = board; temp_board.set_turn(opposite(perspective)); if(temp_board.king_is_in_check()) { total_score += 0.5; } else { temp_board.set_turn(perspective); for(auto move : temp_board.legal_moves()) { auto temp_temp_board = temp_board; if(temp_temp_board.submit_move(*move).winner() != NONE) { total_score += 1.0; } } } } } } } return total_score; }
int hci_send_req(struct hci_request *r, BOOL async) { uint8_t *ptr; uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf)); hci_event_pckt *event_pckt; hci_uart_pckt *hci_hdr; int to = /*1;*/ DEFAULT_TIMEOUT; struct timer t; tHciDataPacket * hciReadPacket = NULL; tListNode hciTempQueue; list_init_head((tListNode*)&hciTempQueue); // cannot be processed, due to reentrancy if (hciAwaitReply) { return -1; } hciAwaitReply = TRUE; hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam); if(async){ goto done; } /* Minimum timeout is 1. */ if(to == 0) to = 1; Timer_Set(&t, to); while(1) { evt_cmd_complete *cc; evt_cmd_status *cs; evt_le_meta_event *me; int len; // we're done with the sending, wait for a reply from the bluenrg io_seproxyhal_general_status(); // perform io_event based loop to wait for BLUENRG_RECV_EVENT for (;;) { io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); // check if event is a ticker event unsigned int ticker_event = G_io_seproxyhal_spi_buffer[0] == SEPROXYHAL_TAG_TICKER_EVENT; // process IOs, and BLE fetch, ble queue is updated through common code io_seproxyhal_handle_event(); // don't ack the BLUENRG_RECV_EVENT as we would require to reply another command to it. if(!list_is_empty((tListNode*)&hciReadPktRxQueue)){ /* Extract packet from HCI event queue. */ //Disable_SPI_IRQ(); list_remove_head((tListNode*)&hciReadPktRxQueue, (tListNode **)&hciReadPacket); list_insert_tail((tListNode*)&hciTempQueue, (tListNode *)hciReadPacket); hci_hdr = (void *)hciReadPacket->dataBuff; if(hci_hdr->type != HCI_EVENT_PKT){ move_list((tListNode*)&hciReadPktPool, (tListNode*)&hciTempQueue); //list_insert_tail((tListNode*)&hciTempQueue, (tListNode *)hciReadPacket); // See comment below //Enable_SPI_IRQ(); goto case_USER_PROCESS; } event_pckt = (void *) (hci_hdr->data); ptr = hciReadPacket->dataBuff + (1 + HCI_EVENT_HDR_SIZE); len = hciReadPacket->data_len - (1 + HCI_EVENT_HDR_SIZE); /* In the meantime there could be other events from the controller. In this case, insert the packet in a different queue. These packets will be inserted back in the main queue just before exiting from send_req(). */ event_pckt = (void *) (hci_hdr->data); switch (event_pckt->evt) { case EVT_CMD_STATUS: cs = (void *) ptr; if (cs->opcode != opcode) { goto case_USER_PROCESS; } if (r->event != EVT_CMD_STATUS) { goto case_USER_PROCESS; } r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, ptr, r->rlen); goto done; case EVT_CMD_COMPLETE: cc = (void *) ptr; if (cc->opcode != opcode) { goto case_USER_PROCESS; } ptr += EVT_CMD_COMPLETE_SIZE; len -= EVT_CMD_COMPLETE_SIZE; r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, ptr, r->rlen); goto done; case EVT_LE_META_EVENT: me = (void *) ptr; if (me->subevent != r->event) { goto case_USER_PROCESS; } len -= 1; r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, me->data, r->rlen); goto done; case EVT_HARDWARE_ERROR: return -1; default: case_USER_PROCESS: HCI_Event_CB(hciReadPacket->dataBuff); break; } } // timeout if (ticker_event) { if (to) { to--; } // don't signal timeout if the event has been closed by handle event to avoid sending commands after a status has been issued else if (!io_seproxyhal_spi_is_status_sent()) { return -1; } } // ack the received event we have processed io_seproxyhal_general_status(); } //Enable_SPI_IRQ(); } failed: move_list((tListNode*)&hciReadPktPool, (tListNode*)&hciTempQueue); hciAwaitReply = FALSE; //Enable_SPI_IRQ(); return -1; done: // Insert the packet back into the pool. /* if (hciReadPacket) { list_insert_head((tListNode*)&hciReadPktPool, (tListNode *)hciReadPacket); } */ move_list((tListNode*)&hciReadPktPool, (tListNode*)&hciTempQueue); hciAwaitReply = FALSE; //Enable_SPI_IRQ(); return 0; }