penguins  1.0.0
arguments.c
Go to the documentation of this file.
1 #include "arguments.h"
2 #include "bot.h"
3 #include "utils.h"
4 #include <stdbool.h>
5 #include <stdio.h>
6 #include <string.h>
7 
8 void init_arguments(Arguments* self) {
9  self->action = ACTION_ARG_INTERACTIVE;
10  self->penguins = 0;
11  self->input_board_file = NULL;
12  self->output_board_file = NULL;
13  self->set_name = NULL;
14  self->board_gen_width = 0;
15  self->board_gen_height = 0;
16  self->board_gen_type = GENERATE_ARG_NONE;
17  init_bot_parameters(&self->bot);
18 }
19 
20 void print_usage(const char* prog_name) {
21  fprintf(stderr, "Usage:\n");
22  fprintf(stderr, "%s help\n", prog_name);
23  fprintf(stderr, "%s version\n", prog_name);
24 #ifdef AUTONOMOUS_MODE
25  fprintf(stderr, "%s phase=placement penguins=N inputboard.txt outpuboard.txt\n", prog_name);
26  fprintf(stderr, "%s phase=movement board.txt board.txt\n", prog_name);
27  fprintf(stderr, "%s generate <island|random> <WIDTH> <HEIGHT> board.txt\n", prog_name);
28  fprintf(stderr, "%s view board.txt\n", prog_name);
29  fprintf(stderr, "%s name\n", prog_name);
30 #endif
31 #ifdef INTERACTIVE_MODE
32  fprintf(stderr, "%s interactive\n", prog_name);
33 #endif
34 }
35 
36 bool parse_arguments(Arguments* result, int argc, char* argv[]) {
37  init_arguments(result);
38 
39  bool ok = true;
40  int file_arg = 0;
41  for (int i = 1; i < argc; i++) {
42  const char* arg = argv[i];
43  const char* arg_value = arg;
44  bool is_placement_or_movement =
45  result->action == ACTION_ARG_PLACEMENT || result->action == ACTION_ARG_MOVEMENT;
46  bool is_board_gen = result->action == ACTION_ARG_GENERATE;
47  long num = 0;
48  if ((arg_value = strip_prefix(arg, "phase="))) {
49  if (strcmp(arg_value, "placement") == 0) {
50  result->action = ACTION_ARG_PLACEMENT;
51  } else if (strcmp(arg_value, "movement") == 0) {
52  result->action = ACTION_ARG_MOVEMENT;
53  } else {
54  fprintf(stderr, "Invalid value for the 'phase' option: '%s'\n", arg_value);
55  ok = false;
56  }
57  } else if ((arg_value = strip_prefix(arg, "penguins="))) {
58  if (parse_number(arg_value, &num) && num > 0) {
59  result->penguins = (int)num;
60  } else {
61  fprintf(stderr, "Invalid value for the 'penguins' option: '%s'\n", arg_value);
62  ok = false;
63  }
64  } else if (strcmp(arg, "version") == 0) {
66  } else if (strcmp(arg, "help") == 0) {
67  result->action = ACTION_ARG_PRINT_HELP;
68  } else if (strcmp(arg, "name") == 0) {
69  result->action = ACTION_ARG_PRINT_NAME;
70  } else if (strcmp(arg, "interactive") == 0) {
72  } else if (strcmp(arg, "generate") == 0) {
73  result->action = ACTION_ARG_GENERATE;
74  } else if (strcmp(arg, "view") == 0) {
75  result->action = ACTION_ARG_VIEW;
76  } else if ((arg_value = strip_prefix(arg, "name="))) {
77  if (*arg_value != '\0') {
78  result->set_name = arg_value;
79  } else {
80  ok = false;
81  fprintf(stderr, "Invalid value for the 'name' option: '%s'\n", arg_value);
82  }
83  } else if ((arg_value = strip_prefix(arg, "bot-placement="))) {
84  if (strcmp(arg_value, "smart") == 0) {
86  } else if (strcmp(arg_value, "random") == 0) {
88  } else if (strcmp(arg_value, "first") == 0) {
90  } else if (strcmp(arg_value, "fish") == 0) {
92  } else {
93  ok = false;
94  fprintf(stderr, "Invalid value for the 'bot-placement' option: '%s'\n", arg_value);
95  }
96  } else if ((arg_value = strip_prefix(arg, "bot-placement-scan-area="))) {
97  if (parse_number(arg_value, &num) && num >= 0) {
98  result->bot.placement_scan_area = (int)num;
99  } else {
100  fprintf(
101  stderr, "Invalid value for the 'bot-placement-scan-area' option: '%s'\n", arg_value
102  );
103  ok = false;
104  }
105  } else if ((arg_value = strip_prefix(arg, "bot-movement="))) {
106  if (strcmp(arg_value, "smart") == 0) {
108  } else if (strcmp(arg_value, "random") == 0) {
110  } else if (strcmp(arg_value, "first") == 0) {
112  } else {
113  ok = false;
114  fprintf(stderr, "Invalid value for the 'bot-movement' option: '%s'\n", arg_value);
115  }
116  } else if ((arg_value = strip_prefix(arg, "bot-max-move-steps="))) {
117  if (parse_number(arg_value, &num) && num >= 0) {
118  result->bot.max_move_length = (int)num;
119  } else {
120  fprintf(stderr, "Invalid value for the 'bot-max-move-steps' option: '%s'\n", arg_value);
121  ok = false;
122  }
123  } else if ((arg_value = strip_prefix(arg, "bot-recursion="))) {
124  if (parse_number(arg_value, &num) && num >= 0) {
125  result->bot.recursion_limit = (int)num;
126  } else {
127  fprintf(stderr, "Invalid value for the 'bot-recursion' option: '%s'\n", arg_value);
128  ok = false;
129  }
130  } else if ((arg_value = strip_prefix(arg, "bot-junction-check-recursion="))) {
131  if (parse_number(arg_value, &num) && num >= -1) {
132  result->bot.junction_check_recursion_limit = (int)num;
133  } else {
134  fprintf(
135  stderr, "Invalid value for the 'bot-junction-check-recursion' option: '%s'\n", arg_value
136  );
137  ok = false;
138  }
139  } else if (is_board_gen && file_arg == 0) {
140  if (strcmp(arg, "island") == 0) {
142  } else if (strcmp(arg, "random") == 0) {
144  } else {
145  fprintf(stderr, "Invalid value for the 'board_gen_type' option: '%s'\n", arg);
146  ok = false;
147  }
148  file_arg++;
149  } else if (is_board_gen && file_arg == 1) {
150  if (parse_number(arg, &num) && num >= 1) {
151  result->board_gen_width = (int)num;
152  } else {
153  fprintf(stderr, "Invalid value for the 'WIDTH' option: '%s'\n", arg);
154  ok = false;
155  }
156  file_arg++;
157  } else if (is_board_gen && file_arg == 2) {
158  if (parse_number(arg, &num) && num >= 1) {
159  result->board_gen_height = (int)num;
160  } else {
161  fprintf(stderr, "Invalid value for the 'HEIGHT' option: '%s'\n", arg);
162  ok = false;
163  }
164  file_arg++;
165  } else if (is_board_gen && file_arg == 3) {
166  result->output_board_file = arg;
167  file_arg++;
168  } else if (result->action == ACTION_ARG_VIEW && file_arg == 0) {
169  result->input_board_file = arg;
170  file_arg++;
171  } else if (is_placement_or_movement && file_arg == 0) {
172  result->input_board_file = arg;
173  file_arg++;
174  } else if (is_placement_or_movement && file_arg == 1) {
175  result->output_board_file = arg;
176  file_arg++;
177  } else {
178  fprintf(stderr, "Unexpected argument: '%s'\n", arg);
179  ok = false;
180  }
181  }
182 
183  if (result->action == ACTION_ARG_PLACEMENT || result->action == ACTION_ARG_MOVEMENT) {
184  if (result->input_board_file == NULL) {
185  fprintf(stderr, "Expected a value for the required argument 'input_board_file'\n");
186  ok = false;
187  }
188  if (result->output_board_file == NULL) {
189  fprintf(stderr, "Expected a value for the required argument 'output_board_file'\n");
190  ok = false;
191  }
192  }
193 
194  if (result->action == ACTION_ARG_PLACEMENT) {
195  if (result->penguins <= 0) {
196  fprintf(stderr, "Expected a value for the 'penguins' option\n");
197  ok = false;
198  }
199  }
200 
201  if (result->action == ACTION_ARG_GENERATE) {
202  if (result->board_gen_type == GENERATE_ARG_NONE) {
203  fprintf(stderr, "Expected a value for the required argument 'board_gen_type'\n");
204  ok = false;
205  }
206  if (result->board_gen_width <= 0) {
207  fprintf(stderr, "Expected a value for the required argument 'WIDTH'\n");
208  ok = false;
209  }
210  if (result->board_gen_height <= 0) {
211  fprintf(stderr, "Expected a value for the required argument 'HEIGHT'\n");
212  ok = false;
213  }
214  if (result->output_board_file == NULL) {
215  fprintf(stderr, "Expected a value for the required argument 'output_board_file'\n");
216  ok = false;
217  }
218  }
219 
220  if (result->action == ACTION_ARG_VIEW) {
221  if (result->input_board_file == NULL) {
222  fprintf(stderr, "Expected a value for the required argument 'input_board_file'\n");
223  ok = false;
224  }
225  }
226 
227  return ok;
228 }
bool parse_arguments(Arguments *result, int argc, char *argv[])
Definition: arguments.c:36
void print_usage(const char *prog_name)
Definition: arguments.c:20
void init_arguments(Arguments *self)
Definition: arguments.c:8
The command-line argument parser.
@ ACTION_ARG_PRINT_NAME
Definition: arguments.h:17
@ ACTION_ARG_GENERATE
Definition: arguments.h:20
@ ACTION_ARG_PRINT_VERSION
Definition: arguments.h:15
@ ACTION_ARG_MOVEMENT
Definition: arguments.h:19
@ ACTION_ARG_PLACEMENT
Definition: arguments.h:18
@ ACTION_ARG_VIEW
Definition: arguments.h:21
@ ACTION_ARG_PRINT_HELP
Definition: arguments.h:14
@ ACTION_ARG_INTERACTIVE
Definition: arguments.h:16
@ GENERATE_ARG_ISLAND
Definition: arguments.h:26
@ GENERATE_ARG_NONE
Definition: arguments.h:25
@ GENERATE_ARG_RANDOM
Definition: arguments.h:27
The bot algorithm.
@ BOT_PLACEMENT_MOST_FISH
Pick the tiles with the most fish in the vicinity.
Definition: bot.h:27
@ BOT_PLACEMENT_SMART
The standard "smart" algorithm, see bot_compute_placement for its description.
Definition: bot.h:21
@ BOT_PLACEMENT_RANDOM
Pick a random tile for placement.
Definition: bot.h:23
@ BOT_PLACEMENT_FIRST_POSSIBLE
Pick the first possible tile (first tile in the first row).
Definition: bot.h:25
@ BOT_MOVEMENT_SMART
The standard "smart" algorithm, see bot_compute_move for its description.
Definition: bot.h:34
@ BOT_MOVEMENT_RANDOM
Pick a random move.
Definition: bot.h:36
@ BOT_MOVEMENT_FIRST_POSSIBLE
Pick the first possible move (also known as the "dumb" algorithm).
Definition: bot.h:38
const char * set_name
Definition: arguments.h:35
ActionArg action
Definition: arguments.h:31
int board_gen_height
Definition: arguments.h:38
const char * input_board_file
Definition: arguments.h:33
const char * output_board_file
Definition: arguments.h:34
GenerateArg board_gen_type
Definition: arguments.h:39
BotParameters bot
Definition: arguments.h:36
int penguins
Definition: arguments.h:32
int board_gen_width
Definition: arguments.h:37
BotPlacementStrategy placement_strategy
BOT_PLACEMENT_SMART by default.
Definition: bot.h:46
int max_move_length
The maximum number of tiles allowed for bot's moves, must be positive.
Definition: bot.h:52
int recursion_limit
The maximum recursion depth, must be positive. Zero means no recursion.
Definition: bot.h:54
void init_bot_parameters(BotParameters *self)
Initializes all fields of the given BotParameters to default values.
Definition: bot.c:31
BotMovementStrategy movement_strategy
BOT_MOVEMENT_SMART by default.
Definition: bot.h:50
int junction_check_recursion_limit
The maximum recursion depth at which junction checks are performed.
Definition: bot.h:56
int placement_scan_area
An area surrounding the placement tile which bot_rate_placement considers.
Definition: bot.h:48
bool parse_number(const char *str, long *result)
Converts a string into a number, returns false if the string was invalid.
Definition: utils.c:64
const char * strip_prefix(const char *str, const char *prefix)
Returns a substring with the prefix removed if the given string starts with the prefix,...
Definition: utils.c:46