#include #include #include "config.h" const ConfigItem DEFAULT_CONFIG[] = { {"player_count", "1"}, // プレイヤー数 {"bot_count", "3"}, // ボットの数 {"init_chips", "10000"}, // 初期チップ数 {"min_bets", "100"}, // 最小ベット額 {"max_bets", "10000"}, // 最大ベット額 {"bj_rate", "1.5"}, // ブラックジャック時の配当倍率 {"bot_double_down_min", "9"}, // ボットがダブルダウンする最小値 {"bot_double_down_max", "11"}, // ボットがダブルダウンする最大値 {"bot_double_down_rate", "75"}, // ボットがダブルダウンを選択する確率 {"bot_hit_soft_rate", "80"}, // ボットが12以下でヒットする確率 {"bot_hit_middle_rate", "40"}, // ボットが13-16でヒットする確率 {"bot_hit_hard_rate", "10"}, // ボットが17-18でヒットする確率 }; const int DEFAULT_CONFIG_COUNT = 12; int _createConfig(const char *filename) { FILE *file = fopen(filename, "w"); if (!file) { return 0; } for (int i = 0; i < DEFAULT_CONFIG_COUNT; i++) { fprintf(file, "%s=%s\n", DEFAULT_CONFIG[i].key, DEFAULT_CONFIG[i].value); } fclose(file); return 1; } char *_trimLine(char *line) { char *end; // 行頭の空白文字をスキップ while (*line == ' ' || *line == '\t' || *line == '\n' || *line == '\r') { line++; } if (*line == '\0') { return line; } // 行末の空白文字を削除 end = line + strlen(line) - 1; while (end > line && (*end == ' ' || *end == '\t' || *end == '\n' || *end == '\r')) { *end = '\0'; end--; } return line; } Config *loadConfig(const char *filename) { FILE *file = fopen(filename, "r"); if (!file) { // ファイルが存在しない場合、デフォルト設定で作成 if (!_createConfig(filename)) { fprintf(stderr, "Error: Failed to create config file '%s'\n", filename); return NULL; } file = fopen(filename, "r"); if (!file) { fprintf(stderr, "Error: Failed to load config file '%s'\n", filename); return NULL; } } Config *config = (Config *)malloc(sizeof(Config)); if (!config) { fprintf(stderr, "Error: Failed to allocate memory for config\n"); return NULL; } config->items = NULL; config->count = 0; // 設定ファイルを1行ずつ読み込み char line[CONFIG_MAX_KEY_LENGTH + CONFIG_MAX_VALUE_LENGTH + 2]; while (fgets(line, sizeof(line), file)) { char *trimmedLine = _trimLine(line); if (*trimmedLine == '\0') { continue; } // key=value形式をパース char *equalsSign = strchr(trimmedLine, '='); if (!equalsSign) { continue; } *equalsSign = '\0'; char *key = _trimLine(trimmedLine); char *value = _trimLine(equalsSign + 1); // 設定項目を追加 ConfigItem *newItems = (ConfigItem *)realloc(config->items, (config->count + 1) * sizeof(ConfigItem)); if (!newItems) { fprintf(stderr, "Error: Failed to allocate memory for config items\n"); free(config->items); free(config); return NULL; } config->items = newItems; strncpy(config->items[config->count].key, key, CONFIG_MAX_KEY_LENGTH); strncpy(config->items[config->count].value, value, CONFIG_MAX_VALUE_LENGTH); config->count++; } fclose(file); // 必要な設定項目が全て存在するか確認 int missingKey = 0; for (int i = 0; i < DEFAULT_CONFIG_COUNT; i++) { if (getConfigValue(config, DEFAULT_CONFIG[i].key) == NULL) { missingKey = 1; break; } } // 不足している項目がある場合は設定ファイルを作り直し if (missingKey) { fprintf(stderr, "Error: Missing required keys in config file '%s'\n", filename); free(config->items); free(config); if (!_createConfig(filename)) { fprintf(stderr, "Error: Failed to create config file '%s'\n", filename); return NULL; } return loadConfig(filename); } return config; } const char *getConfigValue(const Config *config, const char *key) { for (int i = 0; i < config->count; i++) { if (strcmp(config->items[i].key, key) == 0) { return config->items[i].value; } } return NULL; } int getConfigValueInt(const Config *config, const char *key, int *target) { char *e; const char *value = getConfigValue(config, key); if (value == NULL) return 1; const long t = strtol(value, &e, 10); if (*e != '\0') return 1; // intの範囲外の値はエラー if (t > INT_MAX || t < INT_MIN) return 1; *target = (int)t; return 0; } int getConfigValueLong(const Config *config, const char *key, long *target) { char *e; const char *value = getConfigValue(config, key); if (value == NULL) return 1; const long t = strtol(value, &e, 10); if (*e != '\0') return 1; *target = t; return 0; } int getConfigValueDouble(const Config *config, const char *key, double *target) { char *e; const char *value = getConfigValue(config, key); if (value == NULL) return 1; const double t = strtod(value, &e); if (*e != '\0') return 1; *target = t; return 0; }