modernc.org/ccgo/v3@v3.16.14/lib/testdata/CompCert-3.6/test/c/chomp.c (about) 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define NDATA (int *)malloc(ncol * sizeof(int)) 5 #define NLIST (struct _list *)malloc(sizeof(struct _list)) 6 #define NPLAY (struct _play *)malloc(sizeof(struct _play)) 7 8 struct _list 9 { 10 int *data; 11 struct _list *next; 12 } *wanted; 13 14 struct _play 15 { 16 int value; 17 int *state; 18 struct _list *first; 19 struct _play *next; 20 } *game_tree; 21 22 int nrow,ncol; /* global so as to avoid passing them all over the place */ 23 24 int *copy_data(int* data) /* creates a duplicate of a given -data list */ 25 { 26 int *new = NDATA; 27 int counter = ncol; 28 while (counter --) 29 new[counter] = data[counter]; 30 return new; 31 } 32 33 int next_data(int *data) /* gives the next logical setup to the one passed */ 34 /* new setup replaces the old. Returns 0 if no valid */ 35 { /* setup exists after the one passed */ 36 int counter = 0; 37 int valid = 0; /* default to none */ 38 while ((counter != ncol) && (! valid)) /* until its done */ 39 { 40 if (data[counter] == nrow) /* if we hit a border */ 41 { 42 data[counter] = 0; /* reset it to zero */ 43 counter ++; /* and take next column */ 44 } 45 else 46 { 47 data[counter] ++; /* otherwise, just increment row number */ 48 valid = 1; /* and set valid to true. */ 49 } 50 } 51 return valid; /* return whether or not */ 52 } /* a next could be found */ 53 54 void melt_data(int *data1,int *data2) /* melts 2 _data's into the first one. */ 55 { 56 int counter = ncol; 57 while (counter --) /* do every column */ 58 { 59 if (data1[counter] > data2[counter]) /* take the lowest one */ 60 data1[counter] = data2[counter]; /* and put in first _data */ 61 } 62 } 63 64 int equal_data(int *data1,int *data2) /* check if both _data's are equal */ 65 { 66 int counter = ncol; 67 while ((counter --) && (data1[counter] == data2[counter])); 68 return (counter < 0); 69 } 70 71 int valid_data(int *data) /* checks if the play could ever be achieved. */ 72 { 73 int low; /* var to hold the current height */ 74 int counter = 0; 75 low = nrow; /* default to top of board */ 76 while (counter != ncol) /* for every column */ 77 { 78 if (data[counter] > low) break; /* if you get something higher */ 79 low = data[counter]; /* set this as current height */ 80 counter ++; 81 } 82 return (counter == ncol); 83 } 84 85 void dump_list(struct _list *list) /* same for a _list structure */ 86 { 87 if (list != NULL) 88 { 89 dump_list(list -> next); /* dump the rest of it */ 90 free(list -> data); /* and its _data structure */ 91 free(list); 92 } 93 } 94 95 void dump_play(struct _play *play) /* and for the entire game tree */ 96 { 97 if (play != NULL) 98 { 99 dump_play(play -> next); /* dump the rest of the _play */ 100 dump_list(play -> first); /* its _list */ 101 free(play -> state); /* and its _data */ 102 free(play); 103 } 104 } 105 106 int get_value(int *data) /* get the value (0 or 1) for a specific _data */ 107 { 108 struct _play *search; 109 search = game_tree; /* start at the beginning */ 110 while (! equal_data(search -> state,data)) /* until you find a match */ 111 search = search -> next; /* take next element */ 112 return search -> value; /* return its value */ 113 } 114 115 void show_data(int *data) /* little display routine to give off results */ 116 { 117 int counter = 0; 118 while (counter != ncol) 119 { 120 printf("%d",data[counter ++]); 121 if (counter != ncol) putchar(','); 122 } 123 } 124 125 void show_move(int *data) /* puts in the "(" and ")" for show_data() */ 126 { 127 putchar('('); 128 show_data(data); 129 printf(")\n"); 130 } 131 132 void show_list(struct _list *list) /* show the entire list of moves */ 133 { 134 while (list != NULL) 135 { 136 show_move(list -> data); 137 list = list -> next; 138 } 139 } 140 141 void show_play(struct _play *play) /* to display the whole tree */ 142 { 143 while (play != NULL) 144 { 145 printf("For state :\n"); 146 show_data(play -> state); 147 printf(" value = %d\n",play -> value); 148 printf("We get, in order :\n"); 149 show_list(play -> first); 150 play = play -> next; 151 } 152 } 153 154 int in_wanted(int *data) /* checks if the current _data is in the wanted list */ 155 { 156 struct _list *current; 157 current = wanted; /* start at the beginning */ 158 while (current != NULL) /* unitl the last one */ 159 { 160 if (equal_data(current -> data,data)) break; /* break if found */ 161 current = current -> next; /* take next element */ 162 } 163 if (current == NULL) return 0; /* if at the end, not found */ 164 return 1; 165 } 166 167 int *make_data(int row,int col) /* creates a new _data with the correct */ 168 /* contents for the specified row & col */ 169 { 170 int count; 171 int *new = NDATA; 172 for (count = 0;count != col;count ++) /* creates col-1 cells with nrow */ 173 new[count] = nrow; 174 for (;count != ncol;count ++) /* and the rest with row as value */ 175 new[count] = row; 176 return new; /* and return pointer to first element */ 177 } 178 179 struct _list *make_list(int *data,int *value,int *all) /* create the whole _list of moves */ 180 /* for the _data structure data */ 181 { 182 int row,col; 183 int *temp; 184 struct _list *head,*current; 185 *value = 1; /* set to not good to give */ 186 head = NLIST; /* create dummy header */ 187 head -> next = NULL; /* set NULL as next element */ 188 current = head; /* start from here */ 189 for (row = 0;row != nrow;row ++) /* for every row */ 190 { 191 for (col = 0;col != ncol;col ++) /* for every column */ 192 { 193 temp = make_data(row,col); /* create _data for this play */ 194 melt_data(temp,data); /* melt it with the current one */ 195 if (! equal_data(temp,data)) /* if they are different, it good */ 196 { 197 current -> next = NLIST; /* create new element in list */ 198 current -> next -> data = copy_data(temp); /* copy data, and place in list */ 199 current -> next -> next = NULL; /* NULL the next element */ 200 current = current -> next; /* advance pointer */ 201 if (*value == 1) /* if still not found a good one */ 202 *value = get_value(temp); /* look at this value */ 203 if ((! *all) && (*value == 0)) 204 { /* if we found it, and all is not set */ 205 col = ncol - 1; /* do what it take sto break out now */ 206 row = nrow - 1; 207 if (in_wanted(temp)) /* if in the wanted list */ 208 *all = 2; /* flag it */ 209 } 210 } 211 else /* if its not a valid move */ 212 { 213 if (col == 0) row = nrow - 1; /* break out if at first column */ 214 col = ncol - 1; /* but make sure you break out */ 215 } /* of the col for-loop anyway */ 216 free(temp); /* dump this unneeded space */ 217 } 218 } 219 current = head -> next; /* skip first element */ 220 free(head); /* dump it */ 221 if (current != NULL) *value = 1 - *value; /* invert value if its */ 222 return current; /* not the empty board */ 223 } 224 225 struct _play *make_play(int all) /* make up the entire tree-like stuff */ 226 { 227 int val; 228 int *temp; 229 struct _play *head,*current; 230 head = NPLAY; /* dummy header again */ 231 current = head; /* start here */ 232 game_tree = NULL; /* no elements yet */ 233 temp = make_data(0,0); /* new data, for empty board */ 234 temp[0] --; /* set it up at (-1,xx) so that next_data() returns (0,xx) */ 235 while (next_data(temp)) /* take next one, and break if none */ 236 { 237 if (valid_data(temp)) /* if board position is possible */ 238 { 239 current -> next = NPLAY; /* create a new _play cell */ 240 if (game_tree == NULL) game_tree = current -> next; 241 /* set up game_tree if it was previously NULL */ 242 current -> next -> state = copy_data(temp); /* make a copy of temp */ 243 current -> next -> first = make_list(temp,&val,&all); 244 /* make up its whole list of possible moves */ 245 current -> next -> value = val; /* place its value */ 246 current -> next -> next = NULL; /* no next element */ 247 current = current -> next; /* advance pointer */ 248 if (all == 2) /* if found flag is on */ 249 { 250 free(temp); /* dump current temp */ 251 temp = make_data(nrow,ncol); /* and create one that will break */ 252 } 253 } 254 } 255 current = head -> next; /* skip first element */ 256 free(head); /* dump it */ 257 return current; /* and return pointer to start of list */ 258 } 259 260 void make_wanted(int *data) /* makes up the list of positions from the full board */ 261 { 262 /* everything here is almost like in the previous function. */ 263 /* The reason its here, is that it does not do as much as */ 264 /* the one before, and thus goes faster. Also, it saves the */ 265 /* results directly in wanted, which is a global variable. */ 266 267 int row,col; 268 int *temp; 269 struct _list *head,*current; 270 head = NLIST; 271 head -> next = NULL; 272 current = head; 273 for (row = 0;row != nrow;row ++) 274 { 275 for (col = 0;col != ncol;col ++) 276 { 277 temp = make_data(row,col); 278 melt_data(temp,data); 279 if (! equal_data(temp,data)) 280 { 281 current -> next = NLIST; 282 current -> next -> data = copy_data(temp); 283 current -> next -> next = NULL; 284 current = current -> next; 285 } 286 else 287 { 288 if (col == 0) row = nrow - 1; 289 col = ncol - 1; 290 } 291 free(temp); 292 } 293 } 294 current = head -> next; 295 free(head); 296 wanted = current; 297 } 298 299 int *get_good_move(struct _list *list) /* gets the first good move from a _list */ 300 { 301 if (list == NULL) return NULL; /* if list is NULL, say so */ 302 /* until end-of-list or a good one is found */ 303 /* a good move is one that gives off a zero value */ 304 while ((list -> next != NULL) && (get_value(list -> data))) 305 list = list -> next; 306 return copy_data(list -> data); /* return the value */ 307 } 308 309 int *get_winning_move(struct _play *play) /* just scans for the first good move */ 310 /* in the last _list of a _play. This */ 311 { /* is the full board */ 312 int *temp; 313 while (play -> next != NULL) play = play -> next; /* go to end of _play */ 314 temp = get_good_move(play -> first); /* get good move */ 315 return temp; /* return it */ 316 } 317 318 struct _list *where(int *data,struct _play *play) 319 { 320 while (! equal_data(play -> state,data)) /* search for given _data */ 321 play = play -> next; 322 return play -> first; /* return the pointer */ 323 } 324 325 void get_real_move(int *data1,int *data2,int *row,int *col) /* returns row & col of the move */ 326 /* which created data1 from data2 */ 327 { 328 *col = 0; 329 while (data1[*col] == data2[*col]) /* until there is a change */ 330 (*col) ++; /* and increment col number */ 331 *row = data1[*col]; /* row is given by the content of the structure */ 332 } 333 334 int main(void) 335 { 336 int row,col,player; 337 int *current,*temp; 338 struct _play *tree; 339 340 341 ncol = 7; 342 nrow = 7; 343 tree = make_play(1); /* create entire tree structure, not just the */ 344 player = 0; /* needed part for first move */ 345 current = make_data(nrow,ncol); /* start play at full board */ 346 while (current != NULL) 347 { 348 temp = get_good_move(where(current,tree)); /* get best move */ 349 if (temp != NULL) /* temp = NULL when the poison pill is taken */ 350 { 351 get_real_move(temp,current,&row,&col); /* calculate coordinates */ 352 /* print it out nicely */ 353 printf("player %d plays at (%d,%d)\n",player,row,col); 354 player = 1 - player; /* next player to do the same */ 355 free(current); /* dump for memory management */ 356 } 357 current = temp; /* update board */ 358 } 359 dump_play(tree); /* dump unneeded tree */ 360 printf("player %d loses\n",1 - player); /* display winning player */ 361 return 0; 362 } 363 364 /*****************************************************************************/