simple-gtp.c
| 1 | #include <simple-go/simple-gtp.h> |
| 2 | #include <simple-go/simple-gtp-func.h> |
| 3 | |
| 4 | typedef struct msg_formatted |
| 5 | { |
| 6 | char* command; |
| 7 | Vector arguments; |
| 8 | char* id; |
| 9 | } msg_formatted; |
| 10 | |
| 11 | |
| 12 | static msg_formatted format_msg(const char* msg) |
| 13 | { |
| 14 | msg_formatted formatted = {0}; |
| 15 | |
| 16 | size_t index = 0; |
| 17 | |
| 18 | while(isdigit(msg[index]) || msg[index] == '-') |
| 19 | index++; |
| 20 | |
| 21 | if(index) |
| 22 | { |
| 23 | formatted.id = malloc_die(index+1); |
| 24 | strncpy(formatted.id, msg, index); |
| 25 | formatted.id[index] = '\0'; |
| 26 | } |
| 27 | |
| 28 | formatted.command = malloc_die(strlen(msg+index) + 1); |
| 29 | sscanf(msg+index, "%s", formatted.command); |
| 30 | |
| 31 | if(!new_vector_adv(&formatted.arguments, VECTOR_DEFAULT_SIZE, free)) |
| 32 | { |
| 33 | perror("malloc"); |
| 34 | exit(EXIT_FAILURE); |
| 35 | } |
| 36 | |
| 37 | char* tmp_msg = malloc_die(strlen(msg+index)+1); |
| 38 | strcpy(tmp_msg, msg+index); |
| 39 | |
| 40 | |
| 41 | char* current = strtok(tmp_msg, " "); |
| 42 | char* tmp_arg; |
| 43 | |
| 44 | while(current) |
| 45 | { |
| 46 | tmp_arg = malloc_die(strlen(current)+1); |
| 47 | strcpy(tmp_arg, current); |
| 48 | vector_push(&formatted.arguments, tmp_arg); |
| 49 | current = strtok(NULL, " "); |
| 50 | } |
| 51 | |
| 52 | if(formatted.arguments.length > 1) |
| 53 | vector_remove(&formatted.arguments, 0); |
| 54 | |
| 55 | free(tmp_msg); |
| 56 | |
| 57 | return formatted; |
| 58 | } |
| 59 | |
| 60 | static char* sanitize(const char* msg) |
| 61 | { |
| 62 | char* ret = calloc(strlen(msg)+1, 1); |
| 63 | |
| 64 | for(size_t i = 0, reti = 0; i < strlen(msg); i++) |
| 65 | { |
| 66 | if(msg[i] == '\t') |
| 67 | { |
| 68 | ret[reti++] = ' '; |
| 69 | } else if(iscntrl(msg[i])){ |
| 70 | ++reti; |
| 71 | } else if(msg[i] == '#'){ |
| 72 | break; |
| 73 | } else { |
| 74 | ret[reti++] = msg[i]; |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | return ret; |
| 79 | } |
| 80 | |
| 81 | char* handle_gtp_cmd(const char* msg, game_state* game) |
| 82 | { |
| 83 | if(!msg || !strlen(msg)) |
| 84 | { |
| 85 | char* ret = calloc(1,1); |
| 86 | return ret; |
| 87 | } |
| 88 | char* msg_san = sanitize(msg); |
| 89 | |
| 90 | msg_formatted formatted = format_msg(msg_san); |
| 91 | char* command = formatted.command; |
| 92 | Vector arguments = formatted.arguments; |
| 93 | char* id = formatted.id; |
| 94 | |
| 95 | char* ret; |
| 96 | char* (*func_ptr)(const Vector*, const char*, game_state*) = unkown_command_func; |
| 97 | |
| 98 | if(strcmp(command, "protocol_version") == 0) |
| 99 | { |
| 100 | func_ptr = protocol_version_func; |
| 101 | } else if(strcmp(command, "name") == 0) { |
| 102 | func_ptr = name_func; |
| 103 | } else if(strcmp(command, "version") == 0) { |
| 104 | func_ptr = version_func; |
| 105 | } else if(strcmp(command, "known_command") == 0) { |
| 106 | func_ptr = known_command_func; |
| 107 | } else if(strcmp(command, "list_commands") == 0) { |
| 108 | func_ptr = list_commands_func; |
| 109 | } else if(strcmp(command, "boardsize") == 0) { |
| 110 | func_ptr = boardsize_func; |
| 111 | } else if(strcmp(command, "komi") == 0) { |
| 112 | func_ptr = komi_func; |
| 113 | } else if(strcmp(command, "clear_board") == 0) { |
| 114 | func_ptr = clear_board_func; |
| 115 | } else if(strcmp(command, "play") == 0) { |
| 116 | func_ptr = play_func; |
| 117 | } else if(strcmp(command, "genmove") == 0) { |
| 118 | func_ptr = genmove_func; |
| 119 | } else if(strcmp(command, "showboard") == 0) { |
| 120 | func_ptr = show_board_func; |
| 121 | } else if(strcmp(command, "final_score") == 0) { |
| 122 | func_ptr = final_score_func; |
| 123 | } |
| 124 | |
| 125 | ret = func_ptr(&arguments, id, game); |
| 126 | |
| 127 | free(command); |
| 128 | free(msg_san); |
| 129 | free(id); |
| 130 | delete_vector(&arguments); |
| 131 | |
| 132 | return ret; |
| 133 | } |
| 134 |