int init_type_table() { node_t *p ; p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "integer" ) ; strcpy( p->mapsto, "INTEGER(IntKi)") ; add_node_to_end ( p , &Type ) ; p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "intki" ) ; strcpy( p->mapsto, "INTEGER(IntKi)") ; add_node_to_end ( p , &Type ) ; p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "b4ki" ) ; // this won't necesarially work as intended! strcpy( p->mapsto, "INTEGER(IntKi)") ; add_node_to_end ( p , &Type ) ; p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "real" ) ; p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "real" ) ; strcpy( p->mapsto, "REAL(ReKi)") ; add_node_to_end ( p , &Type ) ; p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "reki" ) ; strcpy( p->mapsto, "REAL(ReKi)") ; add_node_to_end ( p , &Type ) ; p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "siki" ) ; strcpy( p->mapsto, "REAL(SiKi)") ; add_node_to_end ( p , &Type ) ; p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "logical" ) ; strcpy( p->mapsto, "LOGICAL") ; add_node_to_end ( p , &Type ) ; #if 0 // bjj: would like to add this back to see if we can use this for pack/unpack // these have to be handled individually because people can and will put lengths after them // so can't make a generic type node here p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "character" ) ; strcpy( p->mapsto, "CHARACTER") /**/ ; add_node_to_end ( p , &Type ) ; #endif p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "doubleprecision" ) ; strcpy( p->mapsto, "REAL(DbKi)") ; add_node_to_end ( p , &Type ) ; p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "dbki" ) ; strcpy( p->mapsto, "REAL(DbKi)") ; add_node_to_end ( p , &Type ) ; p = new_node(TYPE) ; p->type_type = SIMPLE ; strcpy( p->name , "r8ki" ) ; strcpy( p->mapsto, "REAL(R8Ki)") ; add_node_to_end ( p , &Type ) ; p = new_node(TYPE) ; p->type_type = DERIVED ; strcpy( p->name , "meshtype" ) ; strcpy( p->mapsto, "MeshType") ; add_node_to_end ( p , &Type ) ; p = new_node(TYPE) ; p->type_type = DERIVED ; strcpy( p->name , "dll_type" ) ; strcpy( p->mapsto, "DLL_Type") ; add_node_to_end ( p , &Type ) ; return(0) ; }
/** * runs minmax algorithm, extends the tree at the same time. * decides what is the best move to perform according to the minmax algorithm (with alphabeta pruning) * * @param node - the current root of the minmax tree * @param alpha - the current maximum we got (for alphabeta pruning) * @param beta - the current minimum we got (for alphabeta pruning) * @param depth - the depth of the tree * @param max - do max or min? * @param board - the current board * @param best_move - pointer that will contain the best move to make, AFTER the function finishes. * @param is_valid_move - function that decides if a move is valid * @param make_move - function that makes the move on the board * @param get_score - the scoring function for the current game */ int minmax_with_extend(vertex *node, int depth, int alpha, int beta, int max, Board *board, Move *best_move, int (*is_valid_move)(Board *board, Move *move, int value), int (*make_move)(Board* board, Move* new_move, int value), int (*get_score)(Board* board)) { int i; int unimplemented_moves_length; int current_score; Move *next_best_move; Board *copied_board = new_board(board->n, board->m); if (copied_board == NULL) { printf("ERROR: can't initiazlie copied board.\n"); exit(1); } // we stop if we got to a winning move or if we reached the requested depth if ((depth == 0) || (node->score == EXTREME_VALUE) || (node->score == -EXTREME_VALUE)) { free_board(copied_board); return node->score; } // if we don't have a linked list, but the depth isn't 0, we'll create an empty linked list if (node->children == NULL) { if ((node->children = (linked_list*)malloc(sizeof(linked_list))) == NULL) { printf("ERROR: standard function malloc has failed\n"); exit(1); } node->children->head = NULL; node->children->tail = NULL; } if ((next_best_move = (Move*)malloc(sizeof(Move))) == NULL) { printf("ERROR: malloc has failed in minmaxtree\n"); exit(1); } element *iterator = node->children->head; Move *unimplemented_moves = get_unimplemented_moves(node->children, board, &unimplemented_moves_length, max, is_valid_move); // we'll initialize best_move to SOME move, just in case EVERY move is a losing move. if (iterator != NULL) { best_move->i = iterator->node->current_move->i; best_move->j = iterator->node->current_move->j; } else { if (unimplemented_moves_length > 0) { best_move->i = unimplemented_moves[0].i; best_move->j = unimplemented_moves[0].j; // NO MOVES AT ALL - we don't care about the best move, just return the current score. } else { free_board(copied_board); free(next_best_move); free(unimplemented_moves); return node->score; } } // runs max if (max) { while (iterator != NULL) { copy_board(board, copied_board); make_move(copied_board, iterator->node->current_move, max ? FIRST_PL_TURN:SECOND_PL_TURN); current_score = minmax_with_extend(iterator->node, depth-1, alpha, beta, !max, copied_board, next_best_move, is_valid_move, make_move, get_score); // get the maximum of alpha and current score if (current_score > alpha) { alpha = current_score; // update the best move accordingly best_move->i = iterator->node->current_move->i; best_move->j = iterator->node->current_move->j; // alpha-beta pruning if (beta <= alpha) { free_board(copied_board); free(next_best_move); free(unimplemented_moves); return alpha; } } iterator = iterator->next; } for (i=0; i<unimplemented_moves_length; i++) { copy_board(board, copied_board); add_node_to_end(node->children, unimplemented_moves[i], copied_board, max ? FIRST_PL_TURN:SECOND_PL_TURN); // still need to update the score of the node. so we'll make the move and then update the score. make_move(copied_board, node->children->tail->node->current_move, node->children->tail->node->value); node->children->tail->node->score = get_score(copied_board); // now for the minmax part current_score = minmax_with_extend(node->children->tail->node, depth-1, alpha, beta, !max, copied_board, next_best_move, is_valid_move, make_move, get_score); // get the maximum of alpha and current score if (current_score > alpha) { alpha = current_score; // update the best move accordingly best_move->i = node->children->tail->node->current_move->i; best_move->j = node->children->tail->node->current_move->j; // alpha-beta pruning if (beta <= alpha) { free_board(copied_board); free(next_best_move); free(unimplemented_moves); return alpha; } } } free_board(copied_board); free(next_best_move); free(unimplemented_moves); return alpha; // runs min } else { while (iterator != NULL) { copy_board(board, copied_board); make_move(copied_board, iterator->node->current_move, max ? FIRST_PL_TURN:SECOND_PL_TURN); current_score = minmax_with_extend(iterator->node, depth-1, alpha, beta, !max, copied_board, next_best_move, is_valid_move, make_move, get_score); // get the minimum of beta and current score if (current_score < beta) { beta = current_score; // update the best move accordingly best_move->i = iterator->node->current_move->i; best_move->j = iterator->node->current_move->j; // alpha-beta pruning if (beta <= alpha) { free_board(copied_board); free(next_best_move); free(unimplemented_moves); return beta; } } iterator = iterator->next; } for (i=0; i<unimplemented_moves_length; i++) { copy_board(board, copied_board); add_node_to_end(node->children, unimplemented_moves[i], copied_board, max ? FIRST_PL_TURN:SECOND_PL_TURN); // still need to update the score of the node. so we'll make the move and then update the score. make_move(copied_board, node->children->tail->node->current_move, node->children->tail->node->value); node->children->tail->node->score = get_score(copied_board); // now for the minmax part current_score = minmax_with_extend(node->children->tail->node, depth-1, alpha, beta, !max, copied_board, next_best_move, is_valid_move, make_move, get_score); // get the minimum of beta and current score if (current_score < beta) { beta = current_score; // update the best move accordingly best_move->i = node->children->tail->node->current_move->i; best_move->j = node->children->tail->node->current_move->j; // alpha-beta pruning if (beta <= alpha) { free_board(copied_board); free(next_best_move); free(unimplemented_moves); return beta; } } } free_board(copied_board); free(next_best_move); free(unimplemented_moves); return beta; } }