<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40618 >

> [matthias.pfaffer...@mapfa.de - Sat Jan 03 12:50:40 2009]:
> 
> Am Saturday 03 January 2009 02:27:31 schrieb Madeline Book:
> > <URL: http://bugs.freeciv.org/Ticket/Display.html?id=40618 >
> >
> > > [matthias.pfaffer...@mapfa.de - Fri Jan 02 21:15:47 2009]:
> > >
> > > This patch adds the possibility to randomize the lists used by
> > > freeciv.
> >
> > I think array_shuffle() would be better placed in utility/
> > shared.[ch], since it is useful for more than just genlists,
> > and shared.h already has some array related stuff.
> 
> done
> 
> > Also, it should probably use myrand() from utility/rand.[ch]
> > instead of the system rand(). This will make it possible to
> > reproduce the same "random" behavior via seed parameters
> > (e.g. mapseed, gameseed), which helps in debugging.
> 
> done
> 
> > Lastly, the two "for" lines in genlist_shuffle() are missing
> > some spaces. ;)
> 
> done; I just copied the line from the function above ...
> 
> The patch is only compile tested.

Attached version 3 just makes some minor style fixes and
makes compilation work with --enable-debug.


-----------------------------------------------------------------------
おっと。切り直すね。
 server/plrhand.c   |   18 ++++++++++--------
 utility/genlist.c  |   34 ++++++++++++++++++++++++++++++++++
 utility/genlist.h  |    1 +
 utility/shared.c   |   18 ++++++++++++++++++
 utility/shared.h   |    3 +++
 utility/speclist.h |    6 ++++++
 6 files changed, 72 insertions(+), 8 deletions(-)

diff --git a/server/plrhand.c b/server/plrhand.c
index 507444a..2aa8f1f 100644
--- a/server/plrhand.c
+++ b/server/plrhand.c
@@ -1311,22 +1311,24 @@ void maybe_make_contact(struct tile *ptile, struct player *pplayer)
 **************************************************************************/
 void shuffle_players(void)
 {
-  int i, pos, tmp;
+  /* shuffled_order is defined global */
+  int n = player_slot_count();
+  int i;
 
   freelog(LOG_DEBUG, "shuffle_players: creating shuffled order");
 
-  for (i = 0; i < player_slot_count(); i++) {
+  for (i = 0; i < n; i++) {
     shuffled_order[i] = i;
   }
 
-  for (i = 0; i < player_slot_count() - 1; i++) {
-    /* for each run: shuffled[ <i ] is already shuffled [Kero+dwp] */
-    pos = i + myrand(player_slot_count() - i);
-    tmp = shuffled_order[i]; 
-    shuffled_order[i] = shuffled_order[pos];
-    shuffled_order[pos] = tmp;
+  /* randomize it */
+  array_shuffle(shuffled_order, n);
+
+#ifdef DEBUG
+  for (i = 0; i < n; i++) {
     freelog(LOG_DEBUG, "shuffled_order[%d] = %d", i, shuffled_order[i]);
   }
+#endif
 }
 
 /**************************************************************************
diff --git a/utility/genlist.c b/utility/genlist.c
index e827f47..c4567f5 100644
--- a/utility/genlist.c
+++ b/utility/genlist.c
@@ -20,6 +20,7 @@
 #include "mem.h"
 
 #include "genlist.h"
+#include "shared.h"  /* array_shuffle */
 
 static struct genlist_link *find_genlist_position(const struct genlist *pgenlist,
 						  int pos);
@@ -302,3 +303,36 @@ void genlist_sort(struct genlist *pgenlist,
     myiter->dataptr = sortbuf[i];
   }
 }
+
+/************************************************************************
+  Randomize the elements of a genlist using the Fisher-Yates shuffle.
+
+  see: genlist_sort() and shared.c:array_shuffle()
+************************************************************************/
+void genlist_shuffle(struct genlist *pgenlist)
+{
+  const int n = genlist_size(pgenlist);
+  void *sortbuf[n];
+  struct genlist_link *myiter;
+  int i, shuffle[n];
+
+  if (n <= 1) {
+    return;
+  }
+
+  myiter = find_genlist_position(pgenlist, 0);
+  for (i = 0; i < n; i++, ITERATOR_NEXT(myiter)) {
+    sortbuf[i] = ITERATOR_PTR(myiter);
+    /* also create the shuffle list */
+    shuffle[i] = i;
+  }
+
+  /* randomize it */
+  array_shuffle(shuffle, n);
+
+  /* create the shuffled list */
+  myiter = find_genlist_position(pgenlist, 0);
+  for (i = 0; i < n; i++, ITERATOR_NEXT(myiter)) {
+    myiter->dataptr = sortbuf[shuffle[i]];
+  }
+}
diff --git a/utility/genlist.h b/utility/genlist.h
index 7090b00..415c699 100644
--- a/utility/genlist.h
+++ b/utility/genlist.h
@@ -84,6 +84,7 @@ bool genlist_search(struct genlist *pgenlist, const void *data);
 
 void genlist_sort(struct genlist *pgenlist,
 		  int (*compar)(const void *, const void *));
+void genlist_shuffle(struct genlist *pgenlist);
 
 #define ITERATOR_PTR(iter) ((iter) ? ((iter)->dataptr) : NULL)
 #define ITERATOR_NEXT(iter) (iter = (iter)->next)
diff --git a/utility/shared.c b/utility/shared.c
index dc29a9e..9abccca 100644
--- a/utility/shared.c
+++ b/utility/shared.c
@@ -1797,3 +1797,21 @@ char scanin(char **buf, char *delimiters, char *dest, int size)
 
   return found;
 }
+
+/************************************************************************
+  Randomize the elements of an array using the Fisher-Yates shuffle.
+
+  see: http://benpfaff.org/writings/clc/shuffle.html
+************************************************************************/
+void array_shuffle(int *array, int n)
+{
+  if (n > 1 && array != NULL) {
+    int i, j, t;
+    for (i = 0; i < n - 1; i++) {
+      j = i + myrand(n - i);
+      t = array[j];
+      array[j] = array[i];
+      array[i] = t;
+    }
+  }
+}
diff --git a/utility/shared.h b/utility/shared.h
index df20992..eada885 100644
--- a/utility/shared.h
+++ b/utility/shared.h
@@ -244,4 +244,7 @@ bool make_dir(const char *pathname);
 bool path_is_absolute(const char *filename);
 
 char scanin(char **buf, char *delimiters, char *dest, int size);
+
+void array_shuffle(int *array, int n);
+
 #endif  /* FC__SHARED_H */
diff --git a/utility/speclist.h b/utility/speclist.h
index b1c1540..4894905 100644
--- a/utility/speclist.h
+++ b/utility/speclist.h
@@ -41,6 +41,7 @@
       bool foo_list_search(struct foo_list *this, foo_t *pfoo);
       void foo_list_sort(struct foo_list *This, 
          int (*compar)(const void *, const void *));
+      void foo_list_shuffle(struct foo_list *This);
 
    You should also define yourself:  (this file cannot do this for you)
    
@@ -148,6 +149,11 @@ static inline void SPECLIST_FOO(_list_sort) (SPECLIST_LIST * tthis, int (*compar
   genlist_sort(tthis->list, compar);
 }
 
+static inline void SPECLIST_FOO(_list_shuffle) (SPECLIST_LIST * tthis)
+{
+  genlist_shuffle(tthis->list);
+}
+
 #undef SPECLIST_TAG
 #undef SPECLIST_TYPE
 #undef SPECLIST_PASTE_
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to