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(index+1); |
| 24 | strncpy(formatted.id, msg, index); |
| 25 | formatted.id[index] = '\0'; |
| 26 | } |
| 27 | |
| 28 | formatted.command = malloc(strlen(msg+index) + 1); |
| 29 | sscanf(msg+index, "%s", formatted.command); |
| 30 | |
| 31 | formatted.arguments = new_vector(); |
| 32 | |
| 33 | char* tmp_msg = malloc(strlen(msg+index)+1); |
| 34 | strcpy(tmp_msg, msg+index); |
| 35 | |
| 36 | |
| 37 | char* current = strtok(tmp_msg, " "); |
| 38 | char* tmp_arg; |
| 39 | |
| 40 | while(current) |
| 41 | { |
| 42 | tmp_arg = malloc(strlen(current)+1); |
| 43 | strcpy(tmp_arg, current); |
| 44 | vector_push(formatted.arguments, tmp_arg); |
| 45 | current = strtok(NULL, " "); |
| 46 | } |
| 47 | |
| 48 | if(formatted.arguments->length > 1) |
| 49 | vector_remove(formatted.arguments, 0, free); |
| 50 | |
| 51 | free(tmp_msg); |
| 52 | |
| 53 | return formatted; |
| 54 | } |
| 55 | |
| 56 | static char* sanitize(const char* msg) |
| 57 | { |
| 58 | char* ret = calloc(strlen(msg)+1, 1); |
| 59 | |
| 60 | for(size_t i = 0, reti = 0; i < strlen(msg); i++) |
| 61 | { |
| 62 | if(msg[i] == '\t') |
| 63 | { |
| 64 | ret[reti++] = ' '; |
| 65 | } else if(iscntrl(msg[i])){ |
| 66 | ++reti; |
| 67 | } else if(msg[i] == '#'){ |
| 68 | break; |
| 69 | } else { |
| 70 | ret[reti++] = msg[i]; |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | return ret; |
| 75 | } |
| 76 | |
| 77 | char* handle_gtp_cmd(const char* msg, game_state* game) |
| 78 | { |
| 79 | if(!msg || !strlen(msg)) |
| 80 | { |
| 81 | char* ret = calloc(1,1); |
| 82 | return ret; |
| 83 | } |
| 84 | char* msg_san = sanitize(msg); |
| 85 | |
| 86 | msg_formatted formatted = format_msg(msg_san); |
| 87 | char* command = formatted.command; |
| 88 | Vector* arguments = formatted.arguments; |
| 89 | char* id = formatted.id; |
| 90 | |
| 91 | char* ret; |
| 92 | char* (*func_ptr)(const Vector*, const char*, game_state*); |
| 93 | |
| 94 | if(strcmp(command, "protocol_version") == 0) |
| 95 | { |
| 96 | func_ptr = protocol_version_func; |
| 97 | } else if(strcmp(command, "name") == 0) { |
| 98 | func_ptr = name_func; |
| 99 | } else if(strcmp(command, "version") == 0) { |
| 100 | func_ptr = version_func; |
| 101 | } else if(strcmp(command, "known_command") == 0) { |
| 102 | func_ptr = known_command_func; |
| 103 | } else if(strcmp(command, "list_commands") == 0) { |
| 104 | func_ptr = list_commands_func; |
| 105 | } else if(strcmp(command, "boardsize") == 0) { |
| 106 | func_ptr = boardsize_func; |
| 107 | } else if(strcmp(command, "komi") == 0) { |
| 108 | func_ptr = komi_func; |
| 109 | } else if(strcmp(command, "clear_board") == 0) { |
| 110 | func_ptr = clear_board_func; |
| 111 | } else if(strcmp(command, "play") == 0) { |
| 112 | func_ptr = play_func; |
| 113 | } else if(strcmp(command, "genmove") == 0) { |
| 114 | func_ptr = genmove_func; |
| 115 | } else if(strcmp(command, "showboard") == 0) { |
| 116 | func_ptr = show_board_func; |
| 117 | } |
| 118 | |
| 119 | ret = func_ptr(arguments, id, game); |
| 120 | |
| 121 | free(command); |
| 122 | free(msg_san); |
| 123 | free(id); |
| 124 | delete_vector(arguments, free); |
| 125 | |
| 126 | return ret; |
| 127 | } |
| 128 |