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  /*****************************************************************************/