From b7552f0d06ef5e9cdf9a754f8d0e062eb855b322 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno@eressea.de>
Date: Sun, 19 Feb 2006 22:43:56 +0000
Subject: [PATCH] - New random number generator - Faster get_pooled/use_pooled
 - faster peasants() - faster plagues() - faster horses()

---
 src/Jamrules                         |  33 +-
 src/common/attributes/key.c          |   1 +
 src/common/attributes/orcification.c |   1 +
 src/common/gamecode/creport.c        | 428 ++++++++--------
 src/common/gamecode/economy.c        | 728 ++++++++++++++-------------
 src/common/gamecode/laws.c           | 128 +++--
 src/common/gamecode/luck.c           |  22 +-
 src/common/gamecode/monster.c        |  68 +--
 src/common/gamecode/randenc.c        |  87 ++--
 src/common/gamecode/report.c         | 213 ++++----
 src/common/gamecode/spy.c            |   5 +-
 src/common/gamecode/study.c          |   7 +-
 src/common/items/phoenixcompass.c    |   4 +-
 src/common/items/weapons.c           |  11 +-
 src/common/kernel/battle.c           |  34 +-
 src/common/kernel/border.c           |   5 +-
 src/common/kernel/build.c            |  33 +-
 src/common/kernel/curse.c            |   4 +-
 src/common/kernel/equipment.c        |   5 +-
 src/common/kernel/eressea.c          |  76 ++-
 src/common/kernel/eressea.h          |  19 +-
 src/common/kernel/faction.c          |  11 +-
 src/common/kernel/faction.h          |   3 +-
 src/common/kernel/give.c             |   2 +-
 src/common/kernel/item.c             | 124 ++---
 src/common/kernel/item.h             |  38 +-
 src/common/kernel/karma.c            |   7 +-
 src/common/kernel/magic.c            |  83 ++-
 src/common/kernel/movement.c         |  18 +-
 src/common/kernel/names.c            |  47 +-
 src/common/kernel/player.c           |   6 +-
 src/common/kernel/pool.c             |   8 +-
 src/common/kernel/pool.h             |   2 +-
 src/common/kernel/race.c             |   9 +-
 src/common/kernel/region.c           |  40 +-
 src/common/kernel/reports.c          | 122 +++--
 src/common/kernel/reports.h          |  24 +-
 src/common/kernel/resources.c        |   7 +-
 src/common/kernel/save.c             |  17 +-
 src/common/kernel/skill.c            |   3 +-
 src/common/kernel/teleport.c         |  10 +-
 src/common/kernel/unit.c             |   6 +-
 src/common/kernel/unit.h             |   2 +-
 src/common/modules/arena.c           |  69 +--
 src/common/modules/autoseed.c        |  24 +-
 src/common/modules/dungeon.c         |   8 +-
 src/common/modules/gmcmd.c           |  21 +-
 src/common/modules/weather.c         |   8 +-
 src/common/modules/wormhole.c        |   3 +-
 src/common/races/dragons.c           |   8 +-
 src/common/races/zombies.c           |  25 +-
 src/common/spells/combatspells.c     |  16 +-
 src/common/spells/spells.c           |  70 +--
 src/common/util/Jamfile              |   2 +
 src/common/util/cvector.c            |   9 +-
 src/common/util/dice.c               |   7 +-
 src/common/util/mt19937ar.c          | 172 +++++++
 src/common/util/rand.c               |  11 +-
 src/common/util/rng.h                |  45 ++
 src/eressea/lua/eressea.cpp          |   5 +-
 src/eressea/main.c                   |  22 +-
 src/eressea/server.cpp               |   6 +-
 src/mapper/map_modify.c              |  36 +-
 src/mapper/mapper.c                  |  14 +-
 src/tools/namegen.c                  |   2 +-
 65 files changed, 1698 insertions(+), 1386 deletions(-)
 create mode 100644 src/common/util/mt19937ar.c
 create mode 100644 src/common/util/rng.h

diff --git a/src/Jamrules b/src/Jamrules
index df9c50026..83e7ad7b8 100644
--- a/src/Jamrules
+++ b/src/Jamrules
@@ -18,6 +18,10 @@ if ! $(HAVE_LUA) {
   HAVE_LUA = 1 ;
 }
 
+if ! $(CPU) {
+  CPU = pentium2 ;
+}
+
 if $(DISTCC_HOSTS) {
   DISTCC = 1 ;
 }
@@ -42,6 +46,13 @@ if $(DMALLOC) {
   LINKFLAGS += -ldmalloc ;
 }
 
+if $(COVERAGE) = 1 {
+  Echo Compiling with gcov info ;
+  CCFLAGS += -fprofile-arcs -ftest-coverage ;
+  C++FLAGS += -fprofile-arcs -ftest-coverage ;
+  LINKFLAGS += -fprofile-arcs -ftest-coverage ;
+}
+
 if $(PROFILE) = 1 {
   Echo Compiling with profiler ;
   CCFLAGS += -pg -ggdb ;
@@ -125,8 +136,8 @@ rule TargetDirectory
             SubDirC++Flags -ggdb -O0 ;
         }
         else {
-            SubDirCcFlags -DNDEBUG -O2 ;
-            SubDirC++Flags -DNDEBUG -O2 ;
+            SubDirCcFlags -DNDEBUG -O3 -mtune=$(CPU) ;
+            SubDirC++Flags -DNDEBUG -O3 -mtune=$(CPU) ;
         }
 }
 
@@ -136,19 +147,21 @@ if ! $(DEBUG) {
 }
 
 if $(WITHOUT_LUA) {
-	 ECHO Compiling without LUA ;
+   ECHO Compiling without LUA ;
 }
 
+if $(DEBUG) = 0 {
+  TARGET_PREFIX = Release ;
+}
+else {
+  TARGET_PREFIX = Debug ;
+}
 if $(PROFILE) = 1 {
    TARGET_PREFIX = Profile ;
 }
-else {
-  if $(DEBUG) = 0 {
-    TARGET_PREFIX = Release ;
-  }
-  else {
-    TARGET_PREFIX = Debug ;
-  }
+if $(COVERAGE) = 1 {
+   TARGET_PREFIX = Coverage ;
 }
 
 
+
diff --git a/src/common/attributes/key.c b/src/common/attributes/key.c
index 2f8c12871..27f6b0013 100644
--- a/src/common/attributes/key.c
+++ b/src/common/attributes/key.c
@@ -13,6 +13,7 @@
  */
 
 #include <config.h>
+#include <eressea.h>
 #include "key.h"
 
 #include <kernel/save.h>
diff --git a/src/common/attributes/orcification.c b/src/common/attributes/orcification.c
index f6bc70d44..c2719c717 100644
--- a/src/common/attributes/orcification.c
+++ b/src/common/attributes/orcification.c
@@ -13,6 +13,7 @@
  */
 
 #include <config.h>
+#include <eressea.h>
 #include "orcification.h"
 
 #include <kernel/save.h>
diff --git a/src/common/gamecode/creport.c b/src/common/gamecode/creport.c
index f0636ce57..42f369870 100644
--- a/src/common/gamecode/creport.c
+++ b/src/common/gamecode/creport.c
@@ -1089,6 +1089,7 @@ report_computer(const char * filename, report_context * ctx)
   unit *u;
   const char * mailto = locale_string(f->locale, "mailto");
   const attrib * a;
+  seen_region * sr = NULL;
 #ifdef SCORE_MODULE
   int score = 0, avgscore = 0;
 #endif
@@ -1224,7 +1225,7 @@ report_computer(const char * filename, report_context * ctx)
       description = LOC(f->locale, potiontext);
     }
     
-    fprintf(F, "\"%s\";Beschr\n", description);
+          fprintf(F, "\"%s\";Beschr\n", description);
 		fprintf(F, "ZUTATEN\n");
 
 		while (m->number) {
@@ -1235,237 +1236,238 @@ report_computer(const char * filename, report_context * ctx)
 	}
 
   /* traverse all regions */
-  for (r=ctx->first;r!=ctx->last;r=r->next) {
+  for (r=ctx->first;sr==NULL && r!=ctx->last;r=r->next) {
+    sr = find_seen(ctx->seen, r);
+  }
+  for (;sr!=NULL;sr=sr->next) {
+    region * r = sr->r;
     int modifier = 0;
     const char * tname;
-    const seen_region * sd = find_seen(ctx->seen, r);
-    
-    if (sd==NULL) continue;
 		
-		if (!rplane(r)) {
-			if (opt_cr_absolute_coords) {
-				fprintf(F, "REGION %d %d\n", r->x, r->x);
-			} else {
-				fprintf(F, "REGION %d %d\n", region_x(r, f), region_y(r, f));
-			}
-		} else {
+    if (!rplane(r)) {
+      if (opt_cr_absolute_coords) {
+        fprintf(F, "REGION %d %d\n", r->x, r->x);
+      } else {
+        fprintf(F, "REGION %d %d\n", region_x(r, f), region_y(r, f));
+      }
+    } else {
 #if ENCODE_SPECIAL
-			if (rplane(r)->flags & PFL_NOCOORDS) fprintf(F, "SPEZIALREGION %d %d\n", encode_region(f, r), rplane(r)->id);
+      if (rplane(r)->flags & PFL_NOCOORDS) fprintf(F, "SPEZIALREGION %d %d\n", encode_region(f, r), rplane(r)->id);
 #else
-			if (rplane(r)->flags & PFL_NOCOORDS) continue;
+      if (rplane(r)->flags & PFL_NOCOORDS) continue;
 #endif
-			else fprintf(F, "REGION %d %d %d\n", region_x(r, f), region_y(r, f), rplane(r)->id);
-		}
-		if (r->land && strlen(rname(r, f->locale))) fprintf(F, "\"%s\";Name\n", rname(r, f->locale));
-		if (is_cursed(r->attribs,C_MAELSTROM, 0))
-			tname = "maelstrom";
-		else {
-			tname = terrain_name(r);
-		}
-
-		fprintf(F, "\"%s\";Terrain\n", add_translation(tname, locale_string(f->locale, tname)));
-    if (sd->mode!=see_unit) fprintf(F, "\"%s\";visibility\n", visibility[sd->mode]);
-
+      else fprintf(F, "REGION %d %d %d\n", region_x(r, f), region_y(r, f), rplane(r)->id);
+    }
+    if (r->land && strlen(rname(r, f->locale))) fprintf(F, "\"%s\";Name\n", rname(r, f->locale));
+    if (is_cursed(r->attribs,C_MAELSTROM, 0))
+        tname = "maelstrom";
+    else {
+      tname = terrain_name(r);
+    }
+    
+    fprintf(F, "\"%s\";Terrain\n", add_translation(tname, locale_string(f->locale, tname)));
+    if (sr->mode!=see_unit) fprintf(F, "\"%s\";visibility\n", visibility[sr->mode]);
+    
     {
       faction * owner = region_owner(r);
       if (owner) {
         fprintf(F, "%d;owner\n", owner->no);
       }
     }
-		if (sd->mode == see_neighbour) {
-			cr_borders(ctx->seen, r, f, sd->mode, F);
-		} else {
+    if (sr->mode == see_neighbour) {
+      cr_borders(ctx->seen, r, f, sr->mode, F);
+    } else {
 #define RESOURCECOMPAT
-			char cbuf[8192], *pos = cbuf;
+      char cbuf[8192], *pos = cbuf;
 #ifdef RESOURCECOMPAT
-			if (r->display && strlen(r->display))
-				fprintf(F, "\"%s\";Beschr\n", r->display);
+      if (r->display && strlen(r->display))
+          fprintf(F, "\"%s\";Beschr\n", r->display);
 #endif
-			if (fval(r->terrain, LAND_REGION)) {
-				int trees = rtrees(r, 2);
-				int saplings = rtrees(r, 1);
-# ifdef RESOURCECOMPAT
-				if (trees > 0) fprintf(F, "%d;Baeume\n", trees);
-				if (saplings > 0) fprintf(F, "%d;Schoesslinge\n", saplings);
-				if (fval(r, RF_MALLORN) && (trees > 0 || saplings > 0))
-					fprintf(F, "1;Mallorn\n");
-# endif
-				if (!fval(r, RF_MALLORN)) {
-					if (saplings) pos = report_resource(pos, "rm_sapling", f->locale, saplings, -1);
-					if (trees) pos = report_resource(pos, "rm_trees", f->locale, trees, -1);
-				} else {
-					if (saplings) pos = report_resource(pos, "rm_mallornsapling", f->locale, saplings, -1);
-					if (trees) pos = report_resource(pos, "rm_mallorn", f->locale, trees, -1);
-				}
-				fprintf(F, "%d;Bauern\n", rpeasants(r));
-				if(fval(r, RF_ORCIFIED)) {
-					fprintf(F, "1;Verorkt\n");
-				}
-				fprintf(F, "%d;Pferde\n", rhorses(r));
-
-				if (sd->mode>=see_unit) {
-					struct demand * dmd = r->land->demands;
-					struct rawmaterial * res = r->resources;
-					fprintf(F, "%d;Silber\n", rmoney(r));
-					fprintf(F, "%d;Unterh\n", entertainmoney(r));
-
-					if (is_cursed(r->attribs, C_RIOT, 0)){
-						fprintf(F, "0;Rekruten\n");
-					} else {
-						fprintf(F, "%d;Rekruten\n", rpeasants(r) / RECRUITFRACTION);
-					}
-					if (production(r)) {
-						fprintf(F, "%d;Lohn\n", wage(r, f, f->race));
-					}
-
-					while (res) {
-						int maxskill = 0;
-						int level = -1;
-						int visible = -1;
-						const item_type * itype = resource2item(res->type->rtype);
-						if (res->type->visible==NULL) {
-							visible = res->amount;
-							level = res->level + itype->construction->minskill - 1;
-						} else {
-							const unit * u;
-							for (u=r->units; visible!=res->amount && u!=NULL; u=u->next) {
-								if (u->faction == f) {
-									int s = eff_skill(u, itype->construction->skill, r);
-									if (s>maxskill) {
-										if (s>=itype->construction->minskill) {
-											assert(itype->construction->minskill>0);
-											level = res->level + itype->construction->minskill - 1;
-										}
-										maxskill = s;
-										visible = res->type->visible(res, maxskill);
-									}
-								}
-							}
-						}
-						if (level>=0 && visible >=0) {
-							pos = report_resource(pos, res->type->name, f->locale, visible, level);
-# ifdef RESOURCECOMPAT
-							if (visible>=0) fprintf(F, "%d;%s\n", visible, crtag(res->type->name));
+      if (fval(r->terrain, LAND_REGION)) {
+        int trees = rtrees(r, 2);
+        int saplings = rtrees(r, 1);
+#ifdef RESOURCECOMPAT
+        if (trees > 0) fprintf(F, "%d;Baeume\n", trees);
+        if (saplings > 0) fprintf(F, "%d;Schoesslinge\n", saplings);
+        if (fval(r, RF_MALLORN) && (trees > 0 || saplings > 0))
+            fprintf(F, "1;Mallorn\n");
 #endif
-						}
-						res = res->next;
-					}
-					/* trade */
-					if (!TradeDisabled() && rpeasants(r)/TRADE_FRACTION > 0) {
-						fputs("PREISE\n", F);
-						while (dmd) {
-							const char * ch = resourcename(dmd->type->itype->rtype, 0);
-							fprintf(F, "%d;%s\n", (dmd->value
-									  ? dmd->value*dmd->type->price
-									  : -dmd->type->price),
-									  add_translation(ch, locale_string(f->locale, ch)));
-							dmd=dmd->next;
-						}
-					}
-				}
-				if (pos!=cbuf) fputs(cbuf, F);
-			}
+        if (!fval(r, RF_MALLORN)) {
+          if (saplings) pos = report_resource(pos, "rm_sapling", f->locale, saplings, -1);
+          if (trees) pos = report_resource(pos, "rm_trees", f->locale, trees, -1);
+        } else {
+          if (saplings) pos = report_resource(pos, "rm_mallornsapling", f->locale, saplings, -1);
+          if (trees) pos = report_resource(pos, "rm_mallorn", f->locale, trees, -1);
+        }
+        fprintf(F, "%d;Bauern\n", rpeasants(r));
+        if(fval(r, RF_ORCIFIED)) {
+          fprintf(F, "1;Verorkt\n");
+        }
+        fprintf(F, "%d;Pferde\n", rhorses(r));
+        
+        if (sr->mode>=see_unit) {
+          struct demand * dmd = r->land->demands;
+          struct rawmaterial * res = r->resources;
+          fprintf(F, "%d;Silber\n", rmoney(r));
+          fprintf(F, "%d;Unterh\n", entertainmoney(r));
+          
+          if (is_cursed(r->attribs, C_RIOT, 0)){
+            fprintf(F, "0;Rekruten\n");
+          } else {
+            fprintf(F, "%d;Rekruten\n", rpeasants(r) / RECRUITFRACTION);
+          }
+          if (production(r)) {
+            fprintf(F, "%d;Lohn\n", wage(r, f, f->race));
+          }
+          
+          while (res) {
+            int maxskill = 0;
+            int level = -1;
+            int visible = -1;
+            const item_type * itype = resource2item(res->type->rtype);
+            if (res->type->visible==NULL) {
+              visible = res->amount;
+              level = res->level + itype->construction->minskill - 1;
+            } else {
+              const unit * u;
+              for (u=r->units; visible!=res->amount && u!=NULL; u=u->next) {
+                if (u->faction == f) {
+                  int s = eff_skill(u, itype->construction->skill, r);
+                  if (s>maxskill) {
+                    if (s>=itype->construction->minskill) {
+                      assert(itype->construction->minskill>0);
+                      level = res->level + itype->construction->minskill - 1;
+                    }
+                    maxskill = s;
+                    visible = res->type->visible(res, maxskill);
+                  }
+                }
+              }
+            }
+            if (level>=0 && visible >=0) {
+              pos = report_resource(pos, res->type->name, f->locale, visible, level);
+#ifdef RESOURCECOMPAT
+              if (visible>=0) fprintf(F, "%d;%s\n", visible, crtag(res->type->name));
+#endif
+            }
+            res = res->next;
+          }
+          /* trade */
+          if (!TradeDisabled() && rpeasants(r)/TRADE_FRACTION > 0) {
+            fputs("PREISE\n", F);
+            while (dmd) {
+              const char * ch = resourcename(dmd->type->itype->rtype, 0);
+              fprintf(F, "%d;%s\n", (dmd->value
+                                     ? dmd->value*dmd->type->price
+                                     : -dmd->type->price),
+                      add_translation(ch, locale_string(f->locale, ch)));
+              dmd=dmd->next;
+            }
+          }
+        }
+        if (pos!=cbuf) fputs(cbuf, F);
+      }
       if (r->land) {
         print_items(F, r->land->items, f->locale);
       }
-			print_curses(F, f, r, TYP_REGION);
-			cr_borders(ctx->seen, r, f, sd->mode, F);
-			if (sd->mode==see_unit && rplane(r)==get_astralplane() && !is_cursed(r->attribs, C_ASTRALBLOCK, 0))
-			{
-				/* Sonderbehandlung Teleport-Ebene */
-				region_list *rl = astralregions(r, inhabitable);
-
-				if (rl) {
-					region_list *rl2 = rl;
-					while(rl2) {
-						region * r = rl2->data;
-						fprintf(F, "SCHEMEN %d %d\n", region_x(r, f), region_y(r, f));
-						fprintf(F, "\"%s\";Name\n", rname(r, f->locale));
-						rl2 = rl2->next;
-						if(rl2) scat(", ");
-					}
-					free_regionlist(rl);
-				}
-			}
-
-			/* describe both passed and inhabited regions */
-			show_active_spells(r);
-			if (fval(r, RF_TRAVELUNIT)) {
-				boolean seeunits = false, seeships = false;
-				const attrib * ru;
-				/* show units pulled through region */
-				for (ru = a_find(r->attribs, &at_travelunit); ru; ru = ru->nexttype) {
-					unit * u = (unit*)ru->data.v;
-					if (cansee_durchgezogen(f, r, u, 0) && r!=u->region) {
-						if (!u->ship || !fval(u, UFL_OWNER)) continue;
-						if (!seeships) fprintf(F, "DURCHSCHIFFUNG\n");
-						seeships = true;
-						fprintf(F, "\"%s\"\n", shipname(u->ship));
-					}
-				}
-				for (ru = a_find(r->attribs, &at_travelunit); ru; ru = ru->nexttype) {
-					unit * u = (unit*)ru->data.v;
-					if (cansee_durchgezogen(f, r, u, 0) && r!=u->region) {
-						if (u->ship) continue;
-						if (!seeunits) fprintf(F, "DURCHREISE\n");
-						seeunits = true;
-						fprintf(F, "\"%s\"\n", unitname(u));
-					}
-				}
-			}
-			cr_output_messages(F, r->msgs, f);
-			{
-				message_list * mlist = r_getmessages(r, f);
-				if (mlist) cr_output_messages(F, mlist, f);
-			}
-			/* buildings */
-			for (b = rbuildings(r); b; b = b->next) {
-				int fno = -1;
-				u = buildingowner(r, b);
-				if (u && !fval(u, UFL_PARTEITARNUNG)) {
-					const faction * sf = visible_faction(f,u);
-					fno = sf->no;
-				}
-				cr_output_buildings(F, b, u, fno, f);
-			}
-
-			/* ships */
-			for (sh = r->ships; sh; sh = sh->next) {
-				int fno = -1;
-				u = shipowner(sh);
-				if (u && !fval(u, UFL_PARTEITARNUNG)) {
-					const faction * sf = visible_faction(f,u);
-					fno = sf->no;
-				}
-
-				cr_output_ship(F, sh, u, fno, f, r);
-			}
-
-			/* visible units */
-			for (u = r->units; u; u = u->next) {
-				boolean visible = true;
-				switch (sd->mode) {
-				case see_unit:
-					modifier=0;
-					break;
-				case see_far:
-				case see_lighthouse:
-					modifier = -2;
-					break;
-				case see_travel:
-					modifier = -1;
-					break;
-				default:
-					visible=false;
-				}
-				if (u->building || u->ship || (visible && cansee(f, r, u, modifier)))
-					cr_output_unit(F, r, f, u, sd->mode);
-			}
-		}			/* region traversal */
-	}
-	report_crtypes(F, f->locale);
-	write_translations(F);
-	reset_translations();
+      print_curses(F, f, r, TYP_REGION);
+      cr_borders(ctx->seen, r, f, sr->mode, F);
+      if (sr->mode==see_unit && rplane(r)==get_astralplane() && !is_cursed(r->attribs, C_ASTRALBLOCK, 0))
+      {
+        /* Sonderbehandlung Teleport-Ebene */
+        region_list *rl = astralregions(r, inhabitable);
+        
+        if (rl) {
+          region_list *rl2 = rl;
+          while(rl2) {
+            region * r = rl2->data;
+            fprintf(F, "SCHEMEN %d %d\n", region_x(r, f), region_y(r, f));
+            fprintf(F, "\"%s\";Name\n", rname(r, f->locale));
+            rl2 = rl2->next;
+            if(rl2) scat(", ");
+          }
+          free_regionlist(rl);
+        }
+      }
+      
+      /* describe both passed and inhabited regions */
+      show_active_spells(r);
+      if (fval(r, RF_TRAVELUNIT)) {
+        boolean seeunits = false, seeships = false;
+        const attrib * ru;
+        /* show units pulled through region */
+        for (ru = a_find(r->attribs, &at_travelunit); ru; ru = ru->nexttype) {
+          unit * u = (unit*)ru->data.v;
+          if (cansee_durchgezogen(f, r, u, 0) && r!=u->region) {
+            if (!u->ship || !fval(u, UFL_OWNER)) continue;
+            if (!seeships) fprintf(F, "DURCHSCHIFFUNG\n");
+            seeships = true;
+            fprintf(F, "\"%s\"\n", shipname(u->ship));
+          }
+        }
+        for (ru = a_find(r->attribs, &at_travelunit); ru; ru = ru->nexttype) {
+          unit * u = (unit*)ru->data.v;
+          if (cansee_durchgezogen(f, r, u, 0) && r!=u->region) {
+            if (u->ship) continue;
+            if (!seeunits) fprintf(F, "DURCHREISE\n");
+            seeunits = true;
+            fprintf(F, "\"%s\"\n", unitname(u));
+          }
+        }
+      }
+      cr_output_messages(F, r->msgs, f);
+      {
+        message_list * mlist = r_getmessages(r, f);
+        if (mlist) cr_output_messages(F, mlist, f);
+      }
+      /* buildings */
+      for (b = rbuildings(r); b; b = b->next) {
+        int fno = -1;
+        u = buildingowner(r, b);
+        if (u && !fval(u, UFL_PARTEITARNUNG)) {
+          const faction * sf = visible_faction(f,u);
+          fno = sf->no;
+        }
+        cr_output_buildings(F, b, u, fno, f);
+      }
+      
+      /* ships */
+      for (sh = r->ships; sh; sh = sh->next) {
+        int fno = -1;
+        u = shipowner(sh);
+        if (u && !fval(u, UFL_PARTEITARNUNG)) {
+          const faction * sf = visible_faction(f,u);
+          fno = sf->no;
+        }
+        
+        cr_output_ship(F, sh, u, fno, f, r);
+      }
+      
+      /* visible units */
+      for (u = r->units; u; u = u->next) {
+        boolean visible = true;
+        switch (sr->mode) {
+        case see_unit:
+          modifier=0;
+          break;
+        case see_far:
+        case see_lighthouse:
+          modifier = -2;
+          break;
+        case see_travel:
+          modifier = -1;
+          break;
+        default:
+          visible=false;
+        }
+        if (u->building || u->ship || (visible && cansee(f, r, u, modifier)))
+            cr_output_unit(F, r, f, u, sr->mode);
+      }
+    } /* region traversal */
+  }
+  report_crtypes(F, f->locale);
+  write_translations(F);
+  reset_translations();
   if (errno) {
     log_error(("%s\n", strerror(errno)));
     errno = 0;
diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c
index 48c694176..6e0d25267 100644
--- a/src/common/gamecode/economy.c
+++ b/src/common/gamecode/economy.c
@@ -58,11 +58,11 @@
 #include <util/event.h>
 #include <util/goodies.h>
 #include <util/message.h>
+#include <util/rng.h>
 
 /* libs includes */
 #include <math.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include <limits.h>
@@ -116,7 +116,7 @@ scramble(void *data, int n, size_t width)
   char temp[64];
   assert(width<=sizeof(temp));
   for (j=0;j!=n;++j) {
-    int k = rand() % n;
+    int k = rng_int() % n;
 	if (k==j) continue;
     memcpy(temp, (char*)data+j*width, width);
     memcpy((char*)data+j*width, (char*)data+k*width, width);
@@ -325,7 +325,7 @@ do_recruiting(recruitment * recruits, int available)
 
       if (want>0) {
         int get = mintotal;
-        if (want>mintotal && rest<n && (rand() % n) < rest) {
+        if (want>mintotal && rest<n && (rng_int() % n) < rest) {
           --rest;
           ++get;
         }
@@ -349,7 +349,7 @@ do_recruiting(recruitment * recruits, int available)
 
       number = min(req->qty, get / multi);
       if (rc->recruitcost) {
-        int afford = get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT) / rc->recruitcost;
+        int afford = get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT, number*rc->recruitcost) / rc->recruitcost;
         number = min(number, afford);
         use_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT, rc->recruitcost*number);
       }
@@ -494,60 +494,63 @@ recruit(unit * u, struct order * ord, request ** recruitorders)
       return;
     }
   }
-
-	recruitcost = rc->recruitcost;
-	if (recruitcost) {
-		pl = getplane(r);
-		if (pl && fval(pl, PFL_NORECRUITS)) {
-			ADDMSG(&u->faction->msgs,
-				msg_feedback(u, ord, "error_pflnorecruit", ""));
-			return;
-		}
-
-		if (get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT) < recruitcost) {
+  
+  recruitcost = rc->recruitcost;
+  if (recruitcost) {
+    pl = getplane(r);
+    if (pl && fval(pl, PFL_NORECRUITS)) {
+      ADDMSG(&u->faction->msgs,
+             msg_feedback(u, ord, "error_pflnorecruit", ""));
+      return;
+    }
+    
+    if (get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT, recruitcost) < recruitcost) {
       cmistake(u, ord, 142, MSG_EVENT);
-			return;
-		}
-	}
-	if (!playerrace(u->race) || idle(u->faction)) {
-		cmistake(u, ord, 139, MSG_EVENT);
-		return;
-	}
-	/* snotlinge sollten hiermit bereits abgefangen werden, die
-	* parteirasse ist uruk oder ork*/
-	if (u->race != rc) {
-		if (u->number != 0) {
-			cmistake(u, ord, 139, MSG_EVENT);
-			return;
-		}
-		else u->race = rc;
-	}
-
-	if (has_skill(u, SK_MAGIC)) {
-		/* error158;de;{unit} in {region}: '{command}' - Magier arbeiten
-		* grunds�tzlich nur alleine! */
-		cmistake(u, ord, 158, MSG_EVENT);
-		return;
-	}
-	if (has_skill(u, SK_ALCHEMY)
-		&& count_skill(u->faction, SK_ALCHEMY) + n >
-		max_skill(u->faction, SK_ALCHEMY))
-	{
-		cmistake(u, ord, 156, MSG_EVENT);
-		return;
-	}
-	if (recruitcost) n = min(n, get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT) / recruitcost);
-
-	u->wants = n;
-
-	if (!n) {
-		cmistake(u, ord, 142, MSG_EVENT);
-		return;
-	}
-	o = (request *) calloc(1, sizeof(request));
-	o->qty = n;
-	o->unit = u;
-	addlist(recruitorders, o);
+      return;
+    }
+  }
+  if (!playerrace(u->race) || idle(u->faction)) {
+    cmistake(u, ord, 139, MSG_EVENT);
+    return;
+  }
+  /* snotlinge sollten hiermit bereits abgefangen werden, die
+   * parteirasse ist uruk oder ork*/
+  if (u->race != rc) {
+    if (u->number != 0) {
+      cmistake(u, ord, 139, MSG_EVENT);
+      return;
+    }
+    else u->race = rc;
+  }
+  
+  if (has_skill(u, SK_MAGIC)) {
+    /* error158;de;{unit} in {region}: '{command}' - Magier arbeiten
+     * grunds�tzlich nur alleine! */
+    cmistake(u, ord, 158, MSG_EVENT);
+    return;
+  }
+  if (has_skill(u, SK_ALCHEMY)
+      && count_skill(u->faction, SK_ALCHEMY) + n >
+      max_skill(u->faction, SK_ALCHEMY))
+  {
+    cmistake(u, ord, 156, MSG_EVENT);
+    return;
+  }
+  if (recruitcost>0) {
+    int pooled = get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT, recruitcost * n);
+    n = min(n, pooled / recruitcost);
+  }
+  
+  u->wants = n;
+  
+  if (!n) {
+    cmistake(u, ord, 142, MSG_EVENT);
+    return;
+  }
+  o = (request *) calloc(1, sizeof(request));
+  o->qty = n;
+  o->unit = u;
+  addlist(recruitorders, o);
 }
 /* ------------------------------------------------------------- */
 
@@ -871,43 +874,43 @@ maintain(building * b, boolean first)
 		fset(b, BLD_WORKING);
 		return true;
 	}
-	u = buildingowner(r, b);
-	if (u==NULL) return false;
-	for (c=0;b->type->maintenance[c].number;++c) {
-		const maintenance * m = b->type->maintenance+c;
-		int need = m->number;
-
-		if (fval(m, MTF_VARIABLE)) need = need * b->size;
-		if (u) {
-			/* first ist im ersten versuch true, im zweiten aber false! Das
-			* bedeutet, das in der Runde in die Region geschafften Resourcen
-			* nicht genutzt werden k�nnen, weil die reserviert sind! */
-			if (!first) need -= get_pooled(u, m->rtype, GET_ALL);
-			else need -= get_pooled(u, m->rtype, GET_DEFAULT);
-			if (!first && need > 0) {
-				unit * ua;
-				for (ua=r->units;ua;ua=ua->next) freset(ua->faction, FL_DH);
-				fset(u->faction, FL_DH); /* hat schon */
-				for (ua=r->units;ua;ua=ua->next) {
-					if (!fval(ua->faction, FL_DH) && (ua->faction == u->faction || alliedunit(ua, u->faction, HELP_MONEY))) {
-						need -= get_pooled(ua, m->rtype, GET_ALL);
-						fset(ua->faction, FL_DH);
-						if (need<=0) break;
-					}
-				}
-			}
-			if (need > 0) {
-				if (!fval(m, MTF_VITAL)) work = false;
-				else {
-					paid = false;
-					break;
-				}
-			}
-		}
-	}
-	if (paid && c>0) {
-		/* TODO: wieviel von was wurde bezahlt */
-		if (first) {
+  u = buildingowner(r, b);
+  if (u==NULL) return false;
+  for (c=0;b->type->maintenance[c].number;++c) {
+    const maintenance * m = b->type->maintenance+c;
+    int need = m->number;
+    
+    if (fval(m, MTF_VARIABLE)) need = need * b->size;
+    if (u) {
+      /* first ist im ersten versuch true, im zweiten aber false! Das
+       * bedeutet, das in der Runde in die Region geschafften Resourcen
+       * nicht genutzt werden k�nnen, weil die reserviert sind! */
+      if (!first) need -= get_pooled(u, m->rtype, GET_ALL, need);
+      else need -= get_pooled(u, m->rtype, GET_DEFAULT, need);
+      if (!first && need > 0) {
+        unit * ua;
+        for (ua=r->units;ua;ua=ua->next) freset(ua->faction, FL_DH);
+        fset(u->faction, FL_DH); /* hat schon */
+        for (ua=r->units;ua;ua=ua->next) {
+          if (!fval(ua->faction, FL_DH) && (ua->faction == u->faction || alliedunit(ua, u->faction, HELP_MONEY))) {
+            need -= get_pooled(ua, m->rtype, GET_ALL, need);
+            fset(ua->faction, FL_DH);
+            if (need<=0) break;
+          }
+        }
+      }
+      if (need > 0) {
+        if (!fval(m, MTF_VITAL)) work = false;
+        else {
+          paid = false;
+          break;
+        }
+      }
+    }
+  }
+  if (paid && c>0) {
+    /* TODO: wieviel von was wurde bezahlt */
+    if (first) {
 			ADDMSG(&u->faction->msgs, msg_message("maintenance", "unit building", u, b));
 		} else {
 			ADDMSG(&u->faction->msgs, msg_message("maintenance_late", "building", b));
@@ -968,7 +971,7 @@ gebaeude_stuerzt_ein(region * r, building * b)
 			leave(r,u);
 			n = u->number;
 			for (i = 0; i < n; i++) {
-				if (rand() % 100 >= EINSTURZUEBERLEBEN) {
+				if (rng_int() % 100 >= EINSTURZUEBERLEBEN) {
 					++loss;
 				}
 			}
@@ -1002,7 +1005,7 @@ maintain_buildings(boolean crash)
 
       /* the second time, send a message */
       if (crash) {
-        if (!maintained && (rand() % 100 < EINSTURZCHANCE)) {
+        if (!maintained && (rng_int() % 100 < EINSTURZCHANCE)) {
   				gebaeude_stuerzt_ein(r, b);
 	  			continue;
         } else if (!fval(b, BLD_WORKING)) {
@@ -1409,7 +1412,7 @@ leveled_allocation(const resource_type * rtype, region * r, allocation * alist)
             int want = required(al->want-al->get, al->save);
             int x = avail*want/norders;
             /* Wenn Rest, dann w�rfeln, ob ich was bekomme: */
-            if (rand() % norders < (avail*want) % norders)
+            if (rng_int() % norders < (avail*want) % norders)
               ++x;
             avail -= x;
             use += x;
@@ -1453,7 +1456,7 @@ attrib_allocation(const resource_type * rtype, region * r, allocation * alist)
       int want = required(al->want, al->save);
       int x = avail*want/norders;
       /* Wenn Rest, dann w�rfeln, ob ich was bekomme: */
-      if (rand() % norders < (avail*want) % norders)
+      if (rng_int() % norders < (avail*want) % norders)
         ++x;
       avail -= x;
       norders -= want;
@@ -1757,32 +1760,32 @@ expandbuying(region * r, request * buyorders)
 
 	max_products = rpeasants(r) / TRADE_FRACTION;
 
-	/* Kauf - auch so programmiert, da� er leicht erweiterbar auf mehrere
-	* G�ter pro Monat ist. j sind die Befehle, i der Index des
-	* gehandelten Produktes. */
+  /* Kauf - auch so programmiert, da� er leicht erweiterbar auf mehrere
+   * G�ter pro Monat ist. j sind die Befehle, i der Index des
+   * gehandelten Produktes. */
   if (max_products>0) {
-	expandorders(r, buyorders);
-	if (!norders) return;
-
-	for (j = 0; j != norders; j++) {
-		int price, multi;
-		ltype = oa[j].type.ltype;
-		trade = trades;
-		while (trade->type!=ltype) ++trade;
-		multi = trade->multi;
-		if (trade->number + 1 > max_products) ++multi;
-		price = ltype->price * multi;
-
-		if (get_pooled(oa[j].unit, oldresourcetype[R_SILVER], GET_DEFAULT) >= price) {
-			unit * u = oa[j].unit;
-
-			/* litems z�hlt die G�ter, die verkauft wurden, u->n das Geld, das
-			* verdient wurde. Dies mu� gemacht werden, weil der Preis st�ndig sinkt,
-			* man sich also das verdiente Geld und die verkauften Produkte separat
-			* merken mu�. */
-			attrib * a = a_find(u->attribs, &at_luxuries);
-			if (a==NULL) a = a_add(&u->attribs, a_new(&at_luxuries));
-			i_change((item**)&a->data.v, ltype->itype, 1);
+    expandorders(r, buyorders);
+    if (!norders) return;
+    
+    for (j = 0; j != norders; j++) {
+      int price, multi;
+      ltype = oa[j].type.ltype;
+      trade = trades;
+      while (trade->type!=ltype) ++trade;
+      multi = trade->multi;
+      if (trade->number + 1 > max_products) ++multi;
+      price = ltype->price * multi;
+      
+      if (get_pooled(oa[j].unit, oldresourcetype[R_SILVER], GET_DEFAULT, price) >= price) {
+        unit * u = oa[j].unit;
+        
+        /* litems z�hlt die G�ter, die verkauft wurden, u->n das Geld, das
+         * verdient wurde. Dies mu� gemacht werden, weil der Preis st�ndig sinkt,
+         * man sich also das verdiente Geld und die verkauften Produkte separat
+         * merken mu�. */
+        attrib * a = a_find(u->attribs, &at_luxuries);
+        if (a==NULL) a = a_add(&u->attribs, a_new(&at_luxuries));
+        i_change((item**)&a->data.v, ltype->itype, 1);
 			i_change(&oa[j].unit->items, ltype->itype, 1);
 			use_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT, price);
 			if (u->n < 0)
@@ -2113,13 +2116,13 @@ static boolean
 sell(unit * u, request ** sellorders, struct order * ord)
 {
   boolean unlimited = true;
-	const item_type * itype;
-	const luxury_type * ltype=NULL;
-	int n;
+  const item_type * itype;
+  const luxury_type * ltype=NULL;
+  int n;
   region * r = u->region;
-	const char *s;
-
-	if (u->ship && is_guarded(r, u, GUARD_CREWS)) {
+  const char *s;
+  
+  if (u->ship && is_guarded(r, u, GUARD_CREWS)) {
 		cmistake(u, ord, 69, MSG_INCOME);
 		return false;
 	}
@@ -2165,13 +2168,13 @@ sell(unit * u, request ** sellorders, struct order * ord)
     building * b;
     static const struct building_type * bt_castle;
     if (!bt_castle) bt_castle = bt_find("castle");
-    for (b=r->buildings;b;b=b->next) {
-      if (b->type==bt_castle && b->size>=2) break;
+          for (b=r->buildings;b;b=b->next) {
+            if (b->type==bt_castle && b->size>=2) break;
     }
-		if (b==NULL) {
-			cmistake(u, ord, 119, MSG_COMMERCE);
-			return false;
-		}
+          if (b==NULL) {
+            cmistake(u, ord, 119, MSG_COMMERCE);
+            return false;
+          }
 	}
 
 	/* Ein H�ndler kann nur 10 G�ter pro Talentpunkt verkaufen. */
@@ -2189,27 +2192,27 @@ sell(unit * u, request ** sellorders, struct order * ord)
 		cmistake(u, ord, 126, MSG_COMMERCE);
 		return false;
 	}
-	else {
-		attrib * a;
+  else {
+    attrib * a;
     request *o;
-		int k, available;
+    int k, available;
+    
+    if (!r_demand(r, ltype)) {
+      cmistake(u, ord, 263, MSG_COMMERCE);
+      return false;
+    }
+    available = get_pooled(u, itype->rtype, GET_DEFAULT, INT_MAX);
 
-		if (!r_demand(r, ltype)) {
-			cmistake(u, ord, 263, MSG_COMMERCE);
-			return false;
-		}
-		available = get_pooled(u, itype->rtype, GET_DEFAULT);
-
-		/* Wenn andere Einheiten das selbe verkaufen, mu� ihr Zeug abgezogen
-		* werden damit es nicht zweimal verkauft wird: */
-		for (o=*sellorders;o;o=o->next) {
-			if (o->type.ltype==ltype && o->unit->faction == u->faction) {
-				int fpool = o->qty - get_pooled(o->unit, itype->rtype, GET_RESERVE);
-				available -= max(0, fpool);
-			}
-		}
-
-		n = min(n, available);
+    /* Wenn andere Einheiten das selbe verkaufen, mu� ihr Zeug abgezogen
+     * werden damit es nicht zweimal verkauft wird: */
+    for (o=*sellorders;o;o=o->next) {
+      if (o->type.ltype==ltype && o->unit->faction == u->faction) {
+        int fpool = o->qty - get_pooled(o->unit, itype->rtype, GET_RESERVE, INT_MAX);
+        available -= max(0, fpool);
+      }
+    }
+    
+    n = min(n, available);
 
 		if (n <= 0) {
 			cmistake(u, ord, 264, MSG_COMMERCE);
@@ -2262,212 +2265,212 @@ expandstealing(region * r, request * stealorders)
 	* u ist die beklaute unit. oa.unit ist die klauende unit.
 	*/
 
-	for (i = 0; i != norders && oa[i].unit->n <= oa[i].unit->wants; i++) {
-		unit *u = findunitg(oa[i].no, r);
-		int n = 0;
-		if (u && u->region==r) n = get_pooled(u, r_silver, GET_ALL);
+  for (i = 0; i != norders && oa[i].unit->n <= oa[i].unit->wants; i++) {
+    unit *u = findunitg(oa[i].no, r);
+    int n = 0;
+    if (u && u->region==r) {
+      n = get_pooled(u, r_silver, GET_ALL, INT_MAX);
+    }
 #ifndef GOBLINKILL
-		if (oa[i].type.goblin) { /* Goblin-Spezialklau */
-			int uct = 0;
-			unit *u2;
-			assert(effskill(oa[i].unit, SK_STEALTH)>=4 || !"this goblin\'s talent is too low");
+    if (oa[i].type.goblin) { /* Goblin-Spezialklau */
+      int uct = 0;
+      unit *u2;
+      assert(effskill(oa[i].unit, SK_STEALTH)>=4 || !"this goblin\'s talent is too low");
       for (u2 = r->units; u2; u2 = u2->next) {
         if (u2->faction == u->faction) {
           uct += maintenance_cost(u2);
         }
       }
-			n -= uct * 2;
-		}
+      n -= uct * 2;
+    }
 #endif
-		if (n>10 && rplane(r) && (rplane(r)->flags & PFL_NOALLIANCES)) {
-			/* In Questen nur reduziertes Klauen */
-			n = 10;
-		}
-		if (n > 0) {
-			n = min(n, oa[i].unit->wants);
-			use_pooled(u, r_silver, GET_ALL, n);
-			oa[i].unit->n = n;
-			change_money(oa[i].unit, n);
-			ADDMSG(&u->faction->msgs, msg_message("stealeffect", "unit region amount", u, u->region, n));
-		}
-		add_income(oa[i].unit, IC_STEAL, oa[i].unit->wants, oa[i].unit->n);
+    if (n>10 && rplane(r) && (rplane(r)->flags & PFL_NOALLIANCES)) {
+      /* In Questen nur reduziertes Klauen */
+      n = 10;
+    }
+    if (n > 0) {
+      n = min(n, oa[i].unit->wants);
+      use_pooled(u, r_silver, GET_ALL, n);
+      oa[i].unit->n = n;
+      change_money(oa[i].unit, n);
+      ADDMSG(&u->faction->msgs, msg_message("stealeffect", "unit region amount", u, u->region, n));
+    }
+    add_income(oa[i].unit, IC_STEAL, oa[i].unit->wants, oa[i].unit->n);
     fset(oa[i].unit, UFL_LONGACTION);
-	}
-	free(oa);
+  }
+  free(oa);
 }
 
 /* ------------------------------------------------------------- */
 static void
 plant(region *r, unit *u, int raw)
 {
-	int n, i, skill, planted = 0;
+  int n, i, skill, planted = 0;
   const item_type * itype;
   static const resource_type * rt_water = NULL;
   if (rt_water==NULL) rt_water = rt_find("p2");
-
+  
   assert(rt_water!=NULL);
-	if (!fval(r->terrain, LAND_REGION)) {
-		return;
-	}
-	if (rherbtype(r) == NULL) {
-		cmistake(u, u->thisorder, 108, MSG_PRODUCE);
-		return;
-	}
-
-	/* Skill pr�fen */
-	skill = eff_skill(u, SK_HERBALISM, r);
-	itype = rherbtype(r);
-	if (skill < 6) {
-		ADDMSG(&u->faction->msgs,
-			msg_feedback(u, u->thisorder, "plant_skills",
+  if (!fval(r->terrain, LAND_REGION)) {
+    return;
+  }
+  if (rherbtype(r) == NULL) {
+    cmistake(u, u->thisorder, 108, MSG_PRODUCE);
+    return;
+  }
+  
+  /* Skill pr�fen */
+  skill = eff_skill(u, SK_HERBALISM, r);
+  itype = rherbtype(r);
+  if (skill < 6) {
+    ADDMSG(&u->faction->msgs,
+           msg_feedback(u, u->thisorder, "plant_skills",
 			"skill minskill product", SK_HERBALISM, 6, itype->rtype, 1));
-		return;
-	}
-	/* Wasser des Lebens pr�fen */
-	if (get_pooled(u, rt_water, GET_DEFAULT) == 0) {
-		ADDMSG(&u->faction->msgs,
-			msg_feedback(u, u->thisorder, "resource_missing", "missing", rt_water));
-		return;
-	}
-	n = get_pooled(u, itype->rtype, GET_DEFAULT);
-	/* Kr�uter pr�fen */
-	if (n==0) {
-		ADDMSG(&u->faction->msgs,
-			msg_feedback(u, u->thisorder, "resource_missing", "missing",
+    return;
+  }
+  /* Wasser des Lebens pr�fen */
+  if (get_pooled(u, rt_water, GET_DEFAULT, 1) == 0) {
+    ADDMSG(&u->faction->msgs,
+           msg_feedback(u, u->thisorder, "resource_missing", "missing", rt_water));
+    return;
+  }
+  n = get_pooled(u, itype->rtype, GET_DEFAULT, skill*u->number);
+  /* Kr�uter pr�fen */
+  if (n==0) {
+    ADDMSG(&u->faction->msgs,
+           msg_feedback(u, u->thisorder, "resource_missing", "missing",
 			itype->rtype));
-		return;
-	}
+    return;
+  }
 
-	n = min(skill*u->number, n);
-	n = min(raw, n);
-	/* F�r jedes Kraut Talent*10% Erfolgschance. */
-	for(i = n; i>0; i--) {
-		if (rand()%10 < skill) planted++;
-	}
-	produceexp(u, SK_HERBALISM, u->number);
-
-	/* Alles ok. Abziehen. */
-	use_pooled(u, rt_water, GET_DEFAULT, 1);
-	use_pooled(u, itype->rtype, GET_DEFAULT, n);
-	rsetherbs(r, rherbs(r)+planted);
-	ADDMSG(&u->faction->msgs, msg_message("plant", "unit region amount herb", 
-    u, r, planted, itype->rtype));
+  n = min(skill*u->number, n);
+  n = min(raw, n);
+  /* F�r jedes Kraut Talent*10% Erfolgschance. */
+  for(i = n; i>0; i--) {
+    if (rng_int()%10 < skill) planted++;
+  }
+  produceexp(u, SK_HERBALISM, u->number);
+  
+  /* Alles ok. Abziehen. */
+  use_pooled(u, rt_water, GET_DEFAULT, 1);
+  use_pooled(u, itype->rtype, GET_DEFAULT, n);
+  rsetherbs(r, rherbs(r)+planted);
+  ADDMSG(&u->faction->msgs, msg_message("plant", "unit region amount herb", 
+                                        u, r, planted, itype->rtype));
 }
 
 static void
 planttrees(region *r, unit *u, int raw)
 {
-	int n, i, skill, planted = 0;
-	const resource_type * rtype;
-
-	if (!fval(r->terrain, LAND_REGION)) {
-		return;
-	}
-
-	/* Mallornb�ume kann man nur in Mallornregionen z�chten */
-	if (fval(r, RF_MALLORN)) {
-		rtype = rt_mallornseed;
-	} else {
-		rtype = rt_seed;
-	}
-
-	/* Skill pr�fen */
-	skill = eff_skill(u, SK_HERBALISM, r);
-	if (skill < 6) {
-		ADDMSG(&u->faction->msgs,
-			msg_feedback(u, u->thisorder, "plant_skills",
+  int n, i, skill, planted = 0;
+  const resource_type * rtype;
+  
+  if (!fval(r->terrain, LAND_REGION)) {
+    return;
+  }
+  
+  /* Mallornb�ume kann man nur in Mallornregionen z�chten */
+  if (fval(r, RF_MALLORN)) {
+    rtype = rt_mallornseed;
+  } else {
+    rtype = rt_seed;
+  }
+  
+  /* Skill pr�fen */
+  skill = eff_skill(u, SK_HERBALISM, r);
+  if (skill < 6) {
+    ADDMSG(&u->faction->msgs,
+           msg_feedback(u, u->thisorder, "plant_skills",
 			"skill minskill product", SK_HERBALISM, 6, rtype, 1));
-		return;
-	}
-	if (fval(r, RF_MALLORN) && skill < 7 ) {
-		ADDMSG(&u->faction->msgs,
-			msg_feedback(u, u->thisorder, "plant_skills",
+    return;
+  }
+  if (fval(r, RF_MALLORN) && skill < 7 ) {
+    ADDMSG(&u->faction->msgs,
+           msg_feedback(u, u->thisorder, "plant_skills",
 			"skill minskill product", SK_HERBALISM, 7, rtype, 1));
-		return;
-	}
-
-	n = get_pooled(u, rtype, GET_DEFAULT);
-	/* Samen pr�fen */
-	if (n==0) {
-		ADDMSG(&u->faction->msgs,
-			msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype));
-		return;
-	}
-
-	/* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */
-	n = min(raw, n);
-	n = min(skill*u->number, n);
-
-	/* F�r jeden Samen Talent*10% Erfolgschance. */
-	for(i = n; i>0; i--) {
-		if (rand()%10 < skill) planted++;
-	}
-	rsettrees(r, 0, rtrees(r, 0)+planted);
-
-	/* Alles ok. Abziehen. */
-	produceexp(u, SK_HERBALISM, u->number);
-	use_pooled(u, rtype, GET_DEFAULT, n);
-
-	ADDMSG(&u->faction->msgs, msg_message("plant",
-		"unit region amount herb", u, r, planted, rtype));
+    return;
+  }
+  
+  /* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */
+  raw = min(raw, skill*u->number);
+  n = get_pooled(u, rtype, GET_DEFAULT, raw);
+  if (n==0) {
+    ADDMSG(&u->faction->msgs,
+           msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype));
+    return;
+  }
+  n = min(raw, n);
+  
+  /* F�r jeden Samen Talent*10% Erfolgschance. */
+  for(i = n; i>0; i--) {
+    if (rng_int()%10 < skill) planted++;
+  }
+  rsettrees(r, 0, rtrees(r, 0)+planted);
+  
+  /* Alles ok. Abziehen. */
+  produceexp(u, SK_HERBALISM, u->number);
+  use_pooled(u, rtype, GET_DEFAULT, n);
+  
+  ADDMSG(&u->faction->msgs, msg_message("plant",
+                                        "unit region amount herb", u, r, planted, rtype));
 }
 
 /* z�chte b�ume */
 static void
 breedtrees(region *r, unit *u, int raw)
 {
-	int n, i, skill, planted = 0;
-	const resource_type * rtype;
-	static int current_season = -1;
+  int n, i, skill, planted = 0;
+  const resource_type * rtype;
+  static int current_season = -1;
   
   if (current_season<0) current_season = get_gamedate(turn, NULL)->season;
-
-	/* B�ume z�chten geht nur im Fr�hling */
-	if (current_season != SEASON_SPRING){
-		planttrees(r, u, raw);
-		return;
-	}
-
-	if (!fval(r->terrain, LAND_REGION)) {
-		return;
-	}
-
-	/* Mallornb�ume kann man nur in Mallornregionen z�chten */
-	if (fval(r, RF_MALLORN)) {
-		rtype = rt_mallornseed;
-	} else {
-		rtype = rt_seed;
-	}
-
-	/* Skill pr�fen */
-	skill = eff_skill(u, SK_HERBALISM, r);
-	if (skill < 12) {
-		planttrees(r, u, raw);
-		return;
-	}
-	n = get_pooled(u, rtype, GET_DEFAULT);
-	/* Samen pr�fen */
-	if (n==0) {
-		ADDMSG(&u->faction->msgs,
-			msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype));
-		return;
-	}
-
-	/* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */
-	n = min(raw, n);
-	n = min(skill*u->number, n);
-
-	/* F�r jeden Samen Talent*5% Erfolgschance. */
-	for(i = n; i>0; i--) {
-		if (rand()%100 < skill*5) planted++;
-	}
-	rsettrees(r, 1, rtrees(r, 1)+planted);
-
-	/* Alles ok. Abziehen. */
-	produceexp(u, SK_HERBALISM, u->number);
-	use_pooled(u, rtype, GET_DEFAULT, n);
-
-  ADDMSG(&u->faction->msgs, msg_message("plant", 
+  
+  /* B�ume z�chten geht nur im Fr�hling */
+  if (current_season != SEASON_SPRING){
+    planttrees(r, u, raw);
+    return;
+  }
+  
+  if (!fval(r->terrain, LAND_REGION)) {
+    return;
+  }
+  
+  /* Mallornb�ume kann man nur in Mallornregionen z�chten */
+  if (fval(r, RF_MALLORN)) {
+    rtype = rt_mallornseed;
+  } else {
+    rtype = rt_seed;
+  }
+  
+  /* Skill pr�fen */
+  skill = eff_skill(u, SK_HERBALISM, r);
+  if (skill < 12) {
+    planttrees(r, u, raw);
+    return;
+  }
+  
+  /* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */
+  raw = min(skill*u->number, raw);
+  n = get_pooled(u, rtype, GET_DEFAULT, raw);
+  /* Samen pr�fen */
+  if (n==0) {
+    ADDMSG(&u->faction->msgs,
+           msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype));
+    return;
+  }
+  n = min(raw, n);
+  
+  /* F�r jeden Samen Talent*5% Erfolgschance. */
+  for(i = n; i>0; i--) {
+    if (rng_int()%100 < skill*5) planted++;
+  }
+  rsettrees(r, 1, rtrees(r, 1)+planted);
+  
+  /* Alles ok. Abziehen. */
+  produceexp(u, SK_HERBALISM, u->number);
+  use_pooled(u, rtype, GET_DEFAULT, n);
+  
+  ADDMSG(&u->faction->msgs, msg_message("plant",
     "unit region amount herb", u, r, planted, rtype));
 }
 
@@ -2475,11 +2478,11 @@ static void
 plant_cmd(unit *u, struct order * ord)
 {
   region * r = u->region;
-	int m;
-	const char *s;
-	param_t p;
-	const resource_type * rtype = NULL;
-
+  int m;
+  const char *s;
+  param_t p;
+  const resource_type * rtype = NULL;
+  
   if (r->land==NULL) {
     /* TODO: error message here */
     return;
@@ -2488,40 +2491,39 @@ plant_cmd(unit *u, struct order * ord)
   /* pflanze [<anzahl>] <parameter> */
   init_tokens(ord);
   skip_token();
-	s = getstrtoken();
-	m = atoi(s);
-	sprintf(buf, "%d", m);
-	if (!strcmp(buf, s)) {
-		/* first came a want-paramter */
-		s = getstrtoken();
-	} else {
-		m = INT_MAX;
-	}
-
-	if (!s[0]) {
-		p = P_ANY;
-	} else {
-		p = findparam(s, u->faction->locale);
-		rtype = findresourcetype(s, u->faction->locale);
-	}
-
-	if (p==P_HERBS){
-		plant(r, u, m);
-		return;
-	}
-	else if (p==P_TREES){
-		breedtrees(r, u, m);
-		return;
-	}
-	else if (rtype!=NULL){
-		if (rtype==rt_mallornseed || rtype==rt_seed) {
-			breedtrees(r, u, m);
-			return;
-		}
-	}
+  s = getstrtoken();
+  m = atoi(s);
+  sprintf(buf, "%d", m);
+  if (!strcmp(buf, s)) {
+    /* first came a want-paramter */
+    s = getstrtoken();
+  } else {
+    m = INT_MAX;
+  }
+  
+  if (!s[0]) {
+    p = P_ANY;
+  } else {
+    p = findparam(s, u->faction->locale);
+    rtype = findresourcetype(s, u->faction->locale);
+  }
+  
+  if (p==P_HERBS){
+    plant(r, u, m);
+    return;
+  }
+  else if (p==P_TREES){
+    breedtrees(r, u, m);
+    return;
+  }
+  else if (rtype!=NULL){
+    if (rtype==rt_mallornseed || rtype==rt_seed) {
+      breedtrees(r, u, m);
+      return;
+    }
+  }
 }
 
-
 /* z�chte pferde */
 static void
 breedhorses(region *r, unit *u)
@@ -2542,7 +2544,7 @@ breedhorses(region *r, unit *u)
 	n = min(u->number * eff_skill(u, SK_HORSE_TRAINING, r), get_item(u, I_HORSE));
 
 	for (c = 0; c < n; c++) {
-		if (rand() % 100 < eff_skill(u, SK_HORSE_TRAINING, r)) {
+		if (rng_int() % 100 < eff_skill(u, SK_HORSE_TRAINING, r)) {
 			i_change(&u->items, olditemtype[I_HORSE], 1);
 			gezuechtet++;
 		}
@@ -2882,7 +2884,7 @@ expandwork(region * r)
 		if (m>=working) workers = u->number;
 		else {
 			workers = u->number * m / working;
-			if (rand() % working < (u->number * m) % working) workers++;
+			if (rng_int() % working < (u->number * m) % working) workers++;
 		}
 
 		assert(workers>=0);
diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c
index 78ebed40c..b244ac2d6 100644
--- a/src/common/gamecode/laws.c
+++ b/src/common/gamecode/laws.c
@@ -77,8 +77,10 @@
 #include <util/goodies.h>
 #include <util/log.h>
 #include <util/rand.h>
+#include <util/rng.h>
 #include <util/sql.h>
 #include <util/message.h>
+#include <util/rng.h>
 
 #include <modules/xecmd.h>
 
@@ -91,7 +93,6 @@
 #include <stdio.h>
 #include <math.h>
 #include <time.h>
-#include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include <ctype.h>
@@ -99,6 +100,21 @@
 
 #include <attributes/otherfaction.h>
 
+/* chance that a peasant dies of starvation: */
+#define PEASANT_STARVATION_CHANCE 0.9F
+/* Pferdevermehrung */
+#define HORSEGROWTH 4
+/* Wanderungschance pro Pferd */
+#define HORSEMOVE   3
+/* Vermehrungschance pro Baum */
+#define FORESTGROWTH 10000 /* In Millionstel */
+
+/** Ausbreitung und Vermehrung */
+#define MAXDEMAND      25
+#define DMRISE         0.1F /* weekly chance that demand goes up */
+#define DMRISEHAFEN    0.2F /* weekly chance that demand goes up with harbor */
+
+
 /* - external symbols ------------------------------------------ */
 extern int dropouts[2];
 extern int * age;
@@ -526,38 +542,43 @@ calculate_emigration(region *r)
 static void
 peasants(region * r)
 {
-  int glueck = 0;
   int peasants = rpeasants(r);
   int money = rmoney(r);
   int maxp = production(r) * MAXPEASANTS_PER_AREA;
   int n, satiated;
   int dead = 0;
-  attrib * a = a_find(r->attribs, &at_peasantluck);
 
   /* Bis zu 1000 Bauern k�nnen Zwillinge bekommen oder 1000 Bauern
    * wollen nicht! */
 
-  if (a!=NULL) {
-    glueck = a->data.i * 1000;
-  }
+  if (peasants>0) {
+    int glueck = 0;
+    int births = (int)(0.5F + peasants * 0.0001F * PEASANTGROWTH);
+    attrib * a = a_find(r->attribs, &at_peasantluck);
 
-  for (n = peasants; n; n--) {
-    int chances = 1;
-
-    if (glueck>0) {
-      --glueck;
-      chances += PEASANTLUCK;
+    if (a!=NULL) {
+      glueck = a->data.i * 1000;
     }
 
-    while (chances--) {
-      if (rand() % 10000 < PEASANTGROWTH) {
-        /* First chance always goes through. Next ones only with 75% chance if
-         * peasants have reached 90% of maxpopulation */
-        if (chances==0 || peasants/(float)maxp < 0.9 || chance(PEASANTFORCE)) {
-          ++peasants;
+    for (n = peasants; n; --n) {
+      int chances = 0;
+
+      if (glueck>0) {
+        --glueck;
+        chances += PEASANTLUCK;
+      }
+
+      while (chances--) {
+        if (rng_int() % 10000 < PEASANTGROWTH) {
+          /* Only raise with 75% chance if peasants have
+           * reached 90% of maxpopulation */
+          if (peasants/(float)maxp < 0.9 || chance(PEASANTFORCE)) {
+            ++births;
+          }
         }
       }
     }
+    peasants += births;
   }
 
   /* Alle werden satt, oder halt soviele f�r die es auch Geld gibt */
@@ -571,9 +592,8 @@ peasants(region * r)
 
   /* Es verhungert maximal die unterern�hrten Bev�lkerung. */
 
-  for (n = min((peasants - satiated), rpeasants(r)); n; n--) {
-    if (rand() % 100 > STARVATION_SURVIVAL) ++dead;
-  }
+  n = min(peasants - satiated, rpeasants(r));
+    dead += (int)(n * PEASANT_STARVATION_CHANCE);
 
   if (dead > 0) {
     message * msg = add_message(&r->msgs, msg_message("phunger", "dead", dead));
@@ -656,19 +676,21 @@ horses(region * r)
   maxhorses = maxworkingpeasants(r)/10;
   maxhorses = max(0, maxhorses);
   horses = rhorses(r);
-  if(is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) {
-    rsethorses(r, (int)(horses*0.9));
-  } else if (maxhorses > 0) {
-    int i;
-    int growth = (int)((RESOURCE_QUANTITY * HORSEGROWTH * 200 * (maxhorses-horses))/maxhorses);
+  if (horses > 0) {
+    if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) {
+      rsethorses(r, (int)(horses*0.9F));
+    } else if (maxhorses) {
+      int i;
+      double growth = (RESOURCE_QUANTITY * HORSEGROWTH * 200 * (maxhorses-horses))/maxhorses;
 
-    if(a_find(r->attribs, &at_horseluck)) growth *= 2;
-    /* printf("Horses: <%d> %d -> ", growth, horses); */
-    for(i = 0; i < horses; i++) {
-      if(rand()%10000 < growth) horses++;
+      if (growth>0) {
+        if (a_find(r->attribs, &at_horseluck)) growth *= 2;
+        /* printf("Horses: <%d> %d -> ", growth, horses); */
+        i = (int)(0.5F + (horses * 0.0001F) * growth);
+        /* printf("%d\n", horses); */
+        rsethorses(r, horses + i);
+      }
     }
-    /* printf("%d\n", horses); */
-    rsethorses(r, horses);
   }
 
   /* Pferde wandern in Nachbarregionen.
@@ -743,7 +765,7 @@ trees(region * r, const int current_season, const int last_weeks_season)
       return;
     }
 
-    if(production(r) <= 0) return;
+    if (production(r) <= 0) return;
 
     /* Grundchance 1.0% */
     seedchance = (int)(FORESTGROWTH * RESOURCE_QUANTITY);
@@ -752,8 +774,8 @@ trees(region * r, const int current_season, const int last_weeks_season)
     grownup_trees = rtrees(r, 2);
     seeds = 0;
 
-    for(i=0;i<grownup_trees;i++) {
-      if(rand()%1000000 < seedchance) seeds++;
+    if (grownup_trees>0) {
+      seeds += (int)(seedchance*0.000001F*grownup_trees);
     }
     rsettrees(r, 0, rtrees(r, 0) + seeds);
 
@@ -773,7 +795,7 @@ trees(region * r, const int current_season, const int last_weeks_season)
         sprout = 0;
         seedchance = (1000 * maxworkingpeasants(r2)) / r2->terrain->size;
         for(i=0; i<seeds/MAXDIRECTIONS; i++) {
-          if(rand()%10000 < seedchance) sprout++;
+          if(rng_int()%10000 < seedchance) sprout++;
         }
         rsettrees(r2, 0, rtrees(r2, 0) + sprout);
       }
@@ -804,7 +826,7 @@ trees(region * r, const int current_season, const int last_weeks_season)
     sprout = 0;
 
     for(i=0;i<seeds;i++) {
-      if(rand()%10000 < growth) sprout++;
+      if(rng_int()%10000 < growth) sprout++;
     }
     /* aus dem Samenpool dieses Jahres abziehen */
     a->data.sa[0] = (short)(seeds - sprout);
@@ -823,7 +845,7 @@ trees(region * r, const int current_season, const int last_weeks_season)
     grownup_trees = 0;
 
     for(i=0;i<sprout;i++) {
-      if(rand()%10000 < growth) grownup_trees++;
+      if(rng_int()%10000 < growth) grownup_trees++;
     }
     /* aus dem Spr��lingepool dieses Jahres abziehen */
     a->data.sa[1] = (short)(sprout - grownup_trees);
@@ -841,7 +863,7 @@ trees(region * r, const int current_season, const int last_weeks_season)
       || current_season == SEASON_AUTUMN)
   {
     for(i = rherbs(r); i > 0; i--) {
-      if (rand()%100 < (100-rherbs(r))) rsetherbs(r, (short)(rherbs(r)+1));
+      if (rng_int()%100 < (100-rherbs(r))) rsetherbs(r, (short)(rherbs(r)+1));
     }
   }
 }
@@ -868,9 +890,9 @@ demographics(void)
       struct demand * dmd;
       if (r->land) for (dmd=r->land->demands;dmd;dmd=dmd->next) {
         if (dmd->value>0 && dmd->value < MAXDEMAND) {
-          int rise = DMRISE;
+          float rise = DMRISE;
           if (buildingtype_exists(r, bt_find("harbour"))) rise = DMRISEHAFEN;
-          if (rand() % 100 < rise) dmd->value++;
+          if (rng_double()<rise) ++dmd->value;
         }
       }
       /* Seuchen erst nachdem die Bauern sich vermehrt haben
@@ -921,7 +943,7 @@ modify(int i)
   c = i * 2 / 3;
 
   if (c >= 1) {
-    return (c + rand() % c);
+    return (c + rng_int() % c);
   } else {
     return (i);
   }
@@ -1118,7 +1140,7 @@ parse_restart(void)
     }
     if (fval(f, FFL_OVERRIDE)) {
       free(f->override);
-      f->override = strdup(itoa36(rand()));
+      f->override = strdup(itoa36(rng_int()));
       freset(f, FFL_OVERRIDE);
     }
     if (turn!=f->lastorders) {
@@ -2075,7 +2097,7 @@ password_cmd(unit * u, struct order * ord)
   s = getstrtoken();
 
   if (!s || !*s) {
-    for(i=0; i<6; i++) pbuf[i] = (char)(97 + rand() % 26);
+    for(i=0; i<6; i++) pbuf[i] = (char)(97 + rng_int() % 26);
     pbuf[6] = 0;
   } else {
     boolean pwok = true;
@@ -2090,7 +2112,7 @@ password_cmd(unit * u, struct order * ord)
     }
     if (pwok == false) {
       cmistake(u, ord, 283, MSG_EVENT);
-      for(i=0; i<6; i++) pbuf[i] = (char)(97 + rand() % 26);
+      for(i=0; i<6; i++) pbuf[i] = (char)(97 + rng_int() % 26);
       pbuf[6] = 0;
     }
   }
@@ -2485,8 +2507,8 @@ promotion_cmd(unit * u, struct order * ord)
       u->race));
     return 0;
   }
-  money = get_pooled(u, i_silver->rtype, GET_ALL);
   people = count_all(u->faction) * u->number;
+  money = get_pooled(u, i_silver->rtype, GET_ALL, people);
 
   if (people>money) {
     ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "heroes_cost", "cost have",
@@ -3589,7 +3611,7 @@ use_item(unit * u, const item_type * itype, int amount, struct order * ord)
   int i;
   int target = read_unitid(u->faction, u->region);
 
-  i = get_pooled(u, itype->rtype, GET_DEFAULT);
+  i = get_pooled(u, itype->rtype, GET_DEFAULT, amount);
 
   if (amount>i) {
     amount = i;
@@ -3921,8 +3943,8 @@ processorders (void)
 
   puts(" - Attackieren");
   if (nobattle == false) do_battle();
-  if (turn == 0) srand((int)time(0));
-  else srand(turn);
+  if (turn == 0) rng_init((int)time(0));
+  else rng_init(turn);
 
   puts(" - Belagern");
   do_siege();
@@ -3936,8 +3958,8 @@ processorders (void)
   puts(" - Folge auf Einheiten ersetzen");
   follow_unit();
 
-  if (turn == 0) srand((int)time(0));
-  else srand(turn);
+  if (turn == 0) rng_init((int)time(0));
+  else rng_init(turn);
 
   puts(" - Zerst�ren, Geben, Rekrutieren, Vergessen");
   economics();
@@ -3980,8 +4002,8 @@ processorders (void)
   puts(" - Zufallsbegegnungen");
   encounters();
 
-  if (turn == 0) srand((int)time(0));
-  else srand(turn);
+  if (turn == 0) rng_init((int)time(0));
+  else rng_init(turn);
 
   puts(" - Monster fressen und vertreiben Bauern");
   monsters_kill_peasants();
diff --git a/src/common/gamecode/luck.c b/src/common/gamecode/luck.c
index fb15fbf78..53a0cfb4f 100644
--- a/src/common/gamecode/luck.c
+++ b/src/common/gamecode/luck.c
@@ -43,7 +43,8 @@
 #include <karma.h>
 
 /* util includes */
-#include <rand.h>
+#include <util/rand.h>
+#include <util/rng.h>
 #include <util/message.h>
 
 /* libc includes */
@@ -51,7 +52,6 @@
 #include <string.h>
 #include <assert.h>
 #include <math.h>
-#include <stdlib.h>
 
 #ifdef KARMA_MODULE
 
@@ -64,7 +64,7 @@ lucky_silver(const unit *u)
 	int luck = fspecial(u->faction, FS_LUCKY);
 
 	do {
-		r = 1 + rand()%(10000*(luck+STANDARD_LUCK));
+		r = 1 + rng_int()%(10000*(luck+STANDARD_LUCK));
 		if(r > max) max = r;
 		i++;
 	} while(i <= luck);
@@ -101,10 +101,10 @@ lucky_item(const unit *u)
 		}
 	}
 	/* weight is unused */
-	r = rand()%nitems;
+	r = rng_int()%nitems;
 
 	do {
-		r = rand()%nitems;
+		r = rng_int()%nitems;
 		if(r > max) max = r;
 		i++;
 	} while(i <= luck);
@@ -112,9 +112,9 @@ lucky_item(const unit *u)
 	itype = it_find(it_list[r].name);
 
 	if(luck)
-		amount = 10 + rand()%(luck*40) + rand()%(luck*40);
+		amount = 10 + rng_int()%(luck*40) + rng_int()%(luck*40);
 	else 
-		amount = 5 + rand()%10 +rand()%10;
+		amount = 5 + rng_int()%10 +rng_int()%10;
 
 	i_change(&((unit *)u)->items, itype, amount);
   ADDMSG(&u->faction->msgs, msg_message("lucky_item", 
@@ -144,8 +144,8 @@ lucky_magic_item(const unit *u)
 		olditemtype[I_SACK_OF_CONSERVATION],
 	};
 
-	itype = it_list[rand()%n_items];
-	amount = 1 + rand()%luck;
+	itype = it_list[rng_int()%n_items];
+	amount = 1 + rng_int()%luck;
 
 	i_change(&((unit *)u)->items, itype, amount);
 	ADDMSG(&u->faction->msgs, msg_message("lucky_item", 
@@ -161,7 +161,7 @@ lucky_event(const faction *f)
 
 	if(!u) return;
 
-	switch(rand()%3) {
+	switch(rng_int()%3) {
 	case 0:
 		lucky_silver(u);
 		break;
@@ -180,7 +180,7 @@ check_luck(void)
 	faction *f;
 
   for(f=factions; f; f=f->next) {
-    if(rand()%100 < STANDARD_LUCK+fspecial(f, FS_LUCKY)*8)
+    if(rng_int()%100 < STANDARD_LUCK+fspecial(f, FS_LUCKY)*8)
 			lucky_event(f);
 	}
 }
diff --git a/src/common/gamecode/monster.c b/src/common/gamecode/monster.c
index bf06d75a2..eb1866e82 100644
--- a/src/common/gamecode/monster.c
+++ b/src/common/gamecode/monster.c
@@ -57,14 +57,14 @@
 #include <kernel/unit.h>
 
 /* util includes */
-#include <attrib.h>
-#include <base36.h>
-#include <event.h>
-#include <rand.h>
+#include <util/attrib.h>
+#include <util/base36.h>
+#include <util/event.h>
+#include <util/rand.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 
@@ -283,7 +283,7 @@ random_neighbour(region * r, unit *u)
 
 	/* Zuf�llig eine ausw�hlen */
 
-	rr = rand() % c;
+	rr = rng_int() % c;
 
 	/* Durchz�hlen */
 
@@ -327,7 +327,7 @@ treeman_neighbour(region * r)
 	}
 	/* Zuf�llig eine ausw�hlen */
 
-	rr = rand() % c;
+	rr = rng_int() % c;
 
 	/* Durchz�hlen */
 
@@ -382,7 +382,7 @@ monster_move(region * r, unit * u)
 
 /* Wir machen das mal autoconf-style: */
 #ifndef HAVE_DRAND48
-#define drand48() (((double)rand()) / RAND_MAX)
+#define drand48() (((double)rng_int()) / RAND_MAX)
 #endif
 
 static int
@@ -552,7 +552,7 @@ random_unit(const region * r)
 	if (c == 0) {
 		return NULL;
 	}
-	n = rand() % c;
+	n = rng_int() % c;
 	c = 0;
 	u = r->units;
 
@@ -588,19 +588,19 @@ eaten_by_monster(unit * u)
 
 	switch (old_race(u->race)) {
 	case RC_FIREDRAGON:
-		n = rand()%80 * u->number;
+		n = rng_int()%80 * u->number;
 		horse = get_item(u, I_HORSE);
 		break;
 	case RC_DRAGON:
-		n = rand()%200 * u->number;
+		n = rng_int()%200 * u->number;
 		horse = get_item(u, I_HORSE);
 		break;
 	case RC_WYRM:
-		n = rand()%500 * u->number;
+		n = rng_int()%500 * u->number;
 		horse = get_item(u, I_HORSE);
 		break;
 	default:
-		n = rand()%(u->number/20+1);
+		n = rng_int()%(u->number/20+1);
 	}
 
 	if (n > 0) {
@@ -626,7 +626,7 @@ absorbed_by_monster(unit * u)
 
 	switch (old_race(u->race)) {
 	default:
-		n = rand()%(u->number/20+1);
+		n = rng_int()%(u->number/20+1);
 	}
 
 	if(n > 0) {
@@ -660,7 +660,7 @@ scareaway(region * r, int anzahl)
 	p = rpeasants(r);
 	assert(p >= 0 && anzahl >= 0);
 	for (n = min(p, anzahl); n; n--) {
-		direction_t dir = (direction_t)(rand() % MAXDIRECTIONS);
+		direction_t dir = (direction_t)(rng_int() % MAXDIRECTIONS);
 		region * rc = rconnect(r, dir);
 
 		if (rc && fval(rc->terrain, LAND_REGION)) {
@@ -681,16 +681,16 @@ scared_by_monster(unit * u)
 
 	switch (old_race(u->race)) {
 	case RC_FIREDRAGON:
-		n = rand()%160 * u->number;
+		n = rng_int()%160 * u->number;
 		break;
 	case RC_DRAGON:
-		n = rand()%400 * u->number;
+		n = rng_int()%400 * u->number;
 		break;
 	case RC_WYRM:
-		n = rand()%1000 * u->number;
+		n = rng_int()%1000 * u->number;
 		break;
 	default:
-		n = rand()%(u->number/4+1);
+		n = rng_int()%(u->number/4+1);
 	}
 
 	if(n > 0) {
@@ -709,7 +709,7 @@ scared_by_monster(unit * u)
 static const char *
 random_growl(void)
 {
-	switch(rand()%5) {
+	switch(rng_int()%5) {
 	case 0:
 		return "Groammm";
 	case 1:
@@ -743,7 +743,7 @@ monster_learn(unit *u)
   
   if(c == 0) return NULL;
   
-  n = rand()%c + 1;
+  n = rng_int()%c + 1;
   c = 0;
   
   for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
@@ -884,7 +884,7 @@ plan_dragon(unit * u)
       long_order = make_movement_order(u, tr, 1, allowed_dragon);
       break;
     }
-    if (rand()%100 < 15) {
+    if (rng_int()%100 < 15) {
       /* do a growl */
       if (rname(tr, u->faction->locale)) {
         sprintf(buf,
@@ -904,8 +904,8 @@ plan_dragon(unit * u)
     else if (u->race != new_race[RC_FIREDRAGON]) {
       /* neue dracoiden! */
       if (r->land && !fval(r->terrain, FORBIDDEN_REGION)) {
-        int ra = 20 + rand() % 100;
-        if (get_money(u) > ra * 50 + 100 && rand() % 100 < 50) {
+        int ra = 20 + rng_int() % 100;
+        if (get_money(u) > ra * 50 + 100 && rng_int() % 100 < 50) {
           recruit_dracoids(u, ra);
         }
       }
@@ -985,7 +985,7 @@ plan_monsters(void)
             a_remove(&u->attribs, ta);
           }
         } else if (u->race->flags & RCF_MOVERANDOM) {
-          if (rand()%100<MOVECHANCE || check_overpopulated(u)) {
+          if (rng_int()%100<MOVECHANCE || check_overpopulated(u)) {
             long_order = monster_move(r, u);
           }
         }
@@ -1053,7 +1053,7 @@ nrand(int start, int sub)
   int res = 0;
 
   do {
-    if (rand() % 100 < start)
+    if (rng_int() % 100 < start)
       res++;
     start -= sub;
   } while (start > 0);
@@ -1071,7 +1071,7 @@ spawn_dragons(void)
     unit * u;
     message * msg;
 
-    if (fval(r->terrain, SEA_REGION) && rand()%10000 < 1) {
+    if (fval(r->terrain, SEA_REGION) && rng_int()%10000 < 1) {
       u = createunit(r, findfaction(MONSTER_FACTION), 1, new_race[RC_SEASERPENT]);
       fset(u, UFL_ISNEW|UFL_MOVED);
       set_level(u, SK_MAGIC, 4);
@@ -1081,7 +1081,7 @@ spawn_dragons(void)
       set_string(&u->name, "Seeschlange");
     }
 
-    if ((rterrain(r) == T_GLACIER || r->terrain == newterrain(T_SWAMP) || rterrain(r) == T_DESERT) && rand() % 10000 < (5 + 100 * chaosfactor(r))) 
+    if ((rterrain(r) == T_GLACIER || r->terrain == newterrain(T_SWAMP) || rterrain(r) == T_DESERT) && rng_int() % 10000 < (5 + 100 * chaosfactor(r))) 
     {
       if (chance(0.80)) {
         u = createunit(r, findfaction(MONSTER_FACTION), nrand(60, 20) + 1, new_race[RC_FIREDRAGON]);
@@ -1090,9 +1090,9 @@ spawn_dragons(void)
       }
       fset(u, UFL_ISNEW|UFL_MOVED);
 
-      set_money(u, u->number * (rand() % 500 + 100));
+      set_money(u, u->number * (rng_int() % 500 + 100));
       set_level(u, SK_MAGIC, 4);
-      set_level(u, SK_OBSERVATION, 1+rand()%3);
+      set_level(u, SK_OBSERVATION, 1+rng_int()%3);
       set_level(u, SK_STEALTH, 1);
       set_level(u, SK_AUSDAUER, 1);
       log_printf("%d %s in %s.\n", u->number,
@@ -1132,19 +1132,19 @@ spawn_undead(void)
     if(is_cursed(r->attribs, C_HOLYGROUND, 0)) continue;
 
     /* Chance 0.1% * chaosfactor */
-    if (r->land && unburied > r->land->peasants / 20 && rand() % 10000 < (100 + 100 * chaosfactor(r))) {
+    if (r->land && unburied > r->land->peasants / 20 && rng_int() % 10000 < (100 + 100 * chaosfactor(r))) {
       unit * u;
       /* es ist sinnfrei, wenn irgendwo im Wald 3er-Einheiten Untote entstehen.
       * Lieber sammeln lassen, bis sie mindestens 5% der Bev�lkerung sind, und
       * dann erst auferstehen. */
-      int undead = unburied / (rand() % 2 + 1);
+      int undead = unburied / (rng_int() % 2 + 1);
       const race * rc = NULL;
       int i;
       if (r->age<100) undead = undead * r->age / 100; /* newbie-regionen kriegen weniger ab */
 
       if (!undead || r->age < 20) continue;
 
-      switch(rand()%3) {
+      switch(rng_int()%3) {
       case 0:
         rc = new_race[RC_SKELETON]; break;
       case 1:
@@ -1155,7 +1155,7 @@ spawn_undead(void)
 
       u = createunit(r, findfaction(MONSTER_FACTION), undead, rc);
       fset(u, UFL_ISNEW|UFL_MOVED);
-      if ((rc == new_race[RC_SKELETON] || rc == new_race[RC_ZOMBIE]) && rand()%10 < 4) {
+      if ((rc == new_race[RC_SKELETON] || rc == new_race[RC_ZOMBIE]) && rng_int()%10 < 4) {
         equip_unit(u, get_equipment("rising_undead"));
       }
 
diff --git a/src/common/gamecode/randenc.c b/src/common/gamecode/randenc.c
index 10a757881..670838713 100644
--- a/src/common/gamecode/randenc.c
+++ b/src/common/gamecode/randenc.c
@@ -55,8 +55,9 @@
 #include <attributes/racename.h>
 
 /* util includes */
-#include <rand.h>
+#include <util/rand.h>
 #include <util/message.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <stdio.h>
@@ -93,7 +94,7 @@ dissolve_units(void)
 				} else {
 					n = 0;
 					for (i=0;i<u->number;i++) {
-						if (rand()%100 < a->data.ca[1]) n++;
+						if (rng_int()%100 < a->data.ca[1]) n++;
 					}
 				}
 
@@ -180,7 +181,7 @@ find_manual(region * r, unit * u)
   sprintf(buf, "%s stolper%c bei der Erforschung der Region �ber ",
           unitname(u), "nt"[u->number == 1]);
   
-  switch (rand() % 4) {
+  switch (rng_int() % 4) {
   case 0:
     scat("die Ruine eines alten Tempels");
     break;
@@ -203,7 +204,7 @@ find_manual(region * r, unit * u)
   }
   scat(" sie auf das zerfledderte Exemplar eines alten Buches, betitelt ");
   
-  switch (rand() % 36) {
+  switch (rng_int() % 36) {
   case 0:
     scat("\'Magie der Elemente\'");
     skill = SK_MAGIC;
@@ -295,7 +296,7 @@ get_unit(region * r, unit * u)
 
 	addmessage(r, u->faction, buf, MSG_EVENT, ML_IMPORTANT);
 
-	newunit = createunit(r, u->faction, rand() % 20 + 3, u->faction->race);
+	newunit = createunit(r, u->faction, rng_int() % 20 + 3, u->faction->race);
   fset(newunit, UFL_ISNEW|UFL_MOVED);
 	set_string(&newunit->name, "Dorfbewohner");
   if (fval(u, UFL_PARTEITARNUNG)) {
@@ -313,9 +314,9 @@ get_allies(region * r, unit * u)
 
 	case T_PLAIN:
 		if (!r_isforest(r)) {
-			if (get_money(u) / u->number < 100 + rand() % 200)
+			if (get_money(u) / u->number < 100 + rng_int() % 200)
 				return;
-			newunit = createunit(r, u->faction, rand() % 8 + 2, u->faction->race);
+			newunit = createunit(r, u->faction, rng_int() % 8 + 2, u->faction->race);
 			set_string(&newunit->name, "S�ldner");
       equip_unit(newunit, get_equipment("random_plain"));
 			break;
@@ -325,7 +326,7 @@ get_allies(region * r, unit * u)
 				&& eff_skill(u, SK_MAGIC, r) < 2) {
 				return;
 			}
-			newunit = createunit(r, u->faction, rand() % 6 + 2, u->faction->race);
+			newunit = createunit(r, u->faction, rng_int() % 6 + 2, u->faction->race);
 			set_string(&newunit->name, "Waldbewohner");
       equip_unit(newunit, get_equipment("random_forest"));
 		}
@@ -335,7 +336,7 @@ get_allies(region * r, unit * u)
 		if (eff_skill(u, SK_OBSERVATION, r) <= 3) {
 			return;
 		}
-		newunit = createunit(r, u->faction, rand() % 6 + 2, u->faction->race);
+		newunit = createunit(r, u->faction, rng_int() % 6 + 2, u->faction->race);
 		set_string(&newunit->name, "Sumpfbewohner");
     equip_unit(newunit, get_equipment("random_swamp"));
 		break;
@@ -344,7 +345,7 @@ get_allies(region * r, unit * u)
 		if (eff_skill(u, SK_RIDING, r) <= 2) {
 			return;
 		}
-		newunit = createunit(r, u->faction, rand() % 12 + 2, u->faction->race);
+		newunit = createunit(r, u->faction, rng_int() % 12 + 2, u->faction->race);
 		set_string(&newunit->name, "Berber");
     equip_unit(newunit, get_equipment("random_desert"));
 		break;
@@ -353,7 +354,7 @@ get_allies(region * r, unit * u)
 		if (eff_skill(u, SK_MELEE, r) <= 1) {
 			return;
 		}
-		newunit = createunit(r, u->faction, rand() % 8 + 2, u->faction->race);
+		newunit = createunit(r, u->faction, rng_int() % 8 + 2, u->faction->race);
 		set_string(&newunit->name, "Hochlandbarbaren");
     equip_unit(newunit, get_equipment("random_highland"));
 		break;
@@ -363,7 +364,7 @@ get_allies(region * r, unit * u)
 			|| eff_skill(u, SK_TRADE, r) <= 2) {
 			return;
 		}
-		newunit = createunit(r, u->faction, rand() % 6 + 2, u->faction->race);
+		newunit = createunit(r, u->faction, rng_int() % 6 + 2, u->faction->race);
 		set_string(&newunit->name, "Bergbewohner");
     equip_unit(newunit, get_equipment("random_mountain"));
 
@@ -374,7 +375,7 @@ get_allies(region * r, unit * u)
 			|| eff_skill(u, SK_TRADE, r) <= 1) {
 			return;
 		}
-		newunit = createunit(r, u->faction, rand() % 4 + 2, u->faction->race);
+		newunit = createunit(r, u->faction, rng_int() % 4 + 2, u->faction->race);
 		set_string(&newunit->name, "Eisleute");
     equip_unit(newunit, get_equipment("random_glacier"));
 
@@ -403,8 +404,8 @@ encounter(region * r, unit * u)
 {
 	if (!fval(r, RF_ENCOUNTER)) return;
 	freset(r, RF_ENCOUNTER);
-	if (rand() % 100>=ENCCHANCE) return;
-	switch (rand() % 3) {
+	if (rng_int() % 100>=ENCCHANCE) return;
+	switch (rng_int() % 3) {
 	case 0:
 		find_manual(r, u);
 		break;
@@ -434,7 +435,7 @@ encounters(void)
 			}
 
 			if (c > 0) {
-				n = rand() % c;
+				n = rng_int() % c;
 				u = r->units;
 
 				for (i = u->number; i < n; i += u->number) {
@@ -468,7 +469,7 @@ chaosterrain(void)
       }
     }
   }
-  return types[rand() % numtypes];
+  return types[rng_int() % numtypes];
 }
 
 void
@@ -477,8 +478,8 @@ chaos(region * r)
 	unit *u = NULL, *u2;
 	building *b, *b2;
 
-	if (rand() % 100 < 8) {
-		switch (rand() % 3) {
+	if (rng_int() % 100 < 8) {
+		switch (rng_int() % 3) {
 		case 0:				/* Untote */
 			if (!fval(r->terrain, SEA_REGION)) {
 				u = random_unit(r);
@@ -494,10 +495,10 @@ chaos(region * r)
 		case 1:				/* Drachen */
 			if (random_unit(r)) {
 				int mfac = 0;
-				switch (rand() % 3) {
+				switch (rng_int() % 3) {
 				case 0:
 					mfac = 100;
-					u = createunit(r, findfaction(MONSTER_FACTION), rand() % 8 + 1, new_race[RC_FIREDRAGON]);
+					u = createunit(r, findfaction(MONSTER_FACTION), rng_int() % 8 + 1, new_race[RC_FIREDRAGON]);
 					if (u->number == 1) {
 						set_string(&u->name, "Feuerdrache");
 					} else {
@@ -506,7 +507,7 @@ chaos(region * r)
 					break;
 				case 1:
 					mfac = 500;
-					u = createunit(r, findfaction(MONSTER_FACTION), rand() % 4 + 1, new_race[RC_DRAGON]);
+					u = createunit(r, findfaction(MONSTER_FACTION), rng_int() % 4 + 1, new_race[RC_DRAGON]);
 					if (u->number == 1) {
 						set_string(&u->name, "Drache");
 					} else {
@@ -515,7 +516,7 @@ chaos(region * r)
 					break;
 				case 2:
 					mfac = 1000;
-					u = createunit(r, findfaction(MONSTER_FACTION), rand() % 2 + 1, new_race[RC_WYRM]);
+					u = createunit(r, findfaction(MONSTER_FACTION), rng_int() % 2 + 1, new_race[RC_WYRM]);
 					if (u->number == 1) {
 						set_string(&u->name, "Wyrm");
 					} else {
@@ -523,7 +524,7 @@ chaos(region * r)
 					}
 					break;
 				}
-				if (mfac) set_money(u, u->number * (rand() % mfac));
+				if (mfac) set_money(u, u->number * (rng_int() % mfac));
         fset(u, UFL_ISNEW|UFL_MOVED);
 			}
 		case 2:	/* Terrainver�nderung */
@@ -719,7 +720,7 @@ rrandneighbour(region *r)
 	}
 	/* Zuf�llig eine ausw�hlen */
 
-	rr = rand() % c;
+	rr = rng_int() % c;
 
 	/* Durchz�hlen */
 
@@ -759,7 +760,7 @@ volcano_outbreak(region *r)
 	/* Produktion vierteln ... */
 	a->data.sa[0] = 25;
 	/* F�r 6-17 Runden */
-	a->data.sa[1] = (short)(a->data.sa[1] + 6 + rand()%12);
+	a->data.sa[1] = (short)(a->data.sa[1] + 6 + rng_int()%12);
 
 	/* Personen bekommen 4W10 Punkte Schaden. */
 
@@ -799,7 +800,7 @@ volcano_outbreak(region *r)
 		/* Produktion vierteln ... */
 		a->data.sa[0] = 25;
 		/* F�r 6-17 Runden */
-		a->data.sa[1] = (short)(a->data.sa[1] + 6 + rand()%12);
+		a->data.sa[1] = (short)(a->data.sa[1] + 6 + rng_int()%12);
 
 		/* Personen bekommen 3W10 Punkte Schaden. */
 		for (up=&rn->units; *up;) {
@@ -860,11 +861,11 @@ move_iceberg(region *r)
 
 	a = a_find(r->attribs, &at_iceberg);
 	if (!a) {
-		dir = (direction_t)(rand()%MAXDIRECTIONS);
+		dir = (direction_t)(rng_int()%MAXDIRECTIONS);
 		a = a_add(&r->attribs, make_iceberg(dir));
 	} else {
-		if (rand()%100 < 20) {
-			dir = (direction_t)(rand()%MAXDIRECTIONS);
+		if (rng_int()%100 < 20) {
+			dir = (direction_t)(rng_int()%MAXDIRECTIONS);
 			a->data.i = dir;
 		} else {
 			dir = (direction_t)a->data.i;
@@ -949,7 +950,7 @@ move_iceberg(region *r)
 				sh = shn;
 			}
 
-		} else if (rand()%100 < 20) {	/* Eisberg bleibt als Gletscher liegen */
+		} else if (rng_int()%100 < 20) {	/* Eisberg bleibt als Gletscher liegen */
 			unit *u;
 
 			rsetterrain(r, T_GLACIER);
@@ -971,7 +972,7 @@ move_icebergs(void)
 
   for (r=regions; r; r=r->next) {
     if (rterrain(r) == T_ICEBERG && !fval(r, RF_DH)) {
-      int select = rand() % 10;
+      int select = rng_int() % 10;
       if (select < 4) {
         /* 4% chance */
   			fset(r, RF_DH);
@@ -1036,7 +1037,7 @@ godcurse(void)
       for(u=r->units; u; u=u->next) {
         skill * sv = u->skills;
         while (sv!=u->skills+u->skill_size) {
-          int weeks = 1+rand()%3;
+          int weeks = 1+rng_int()%3;
           reduce_skill(u, sv, weeks);
           ++sv;
         }
@@ -1117,7 +1118,7 @@ orc_growth(void)
         int prob = curse_geteffect(c);
 
         for (n = (num - get_item(u, I_CHASTITY_BELT)); n > 0; n--) {
-          if (rand() % 100 < prob) {
+          if (rng_int() % 100 < prob) {
             ++increase;
           }
         }
@@ -1146,9 +1147,9 @@ demon_skillchanges(void)
       if (u->race == new_race[RC_DAEMON]) {
         skill * sv = u->skills;
         while (sv!=u->skills+u->skill_size) {
-          if (sv->level>0 && rand() % 100 < 25) {
-            int weeks = 1+rand()%3;
-            if (rand() % 100 < 40) {
+          if (sv->level>0 && rng_int() % 100 < 25) {
+            int weeks = 1+rng_int()%3;
+            if (rng_int() % 100 < 40) {
               reduce_skill(u, sv, weeks);
             } else {
               while (weeks--) learn_skill(u, sv->id, 1.0);
@@ -1234,16 +1235,16 @@ randomevents(void)
       rsetterrain(r, T_VOLCANO);
     } else switch(rterrain(r)) {
     case T_VOLCANO:
-      if (rand()%100 < 4) {
+      if (rng_int()%100 < 4) {
         ADDMSG(&r->msgs, msg_message("volcanostartsmoke", "region", r));
         rsetterrain(r, T_VOLCANO_SMOKING);
       }
       break;
     case T_VOLCANO_SMOKING:
-      if (rand()%100 < 12) {
+      if (rng_int()%100 < 12) {
         ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r));
         rsetterrain(r, T_VOLCANO);
-      } else if (rand()%100 < 8) {
+      } else if (rng_int()%100 < 8) {
         volcano_outbreak(r);
       }
       break;
@@ -1270,7 +1271,7 @@ randomevents(void)
       if (u->faction->no != MONSTER_FACTION
         && (u->race->flags & RCF_DESERT)) {
           if (fval(u, UFL_ISNEW)) continue;
-          if (rand()%100 < 5) {
+          if (rng_int()%100 < 5) {
             ADDMSG(&u->faction->msgs, msg_message("desertion",
               "unit region", u, r));
             u_setfaction(u, findfaction(MONSTER_FACTION));
@@ -1285,7 +1286,7 @@ randomevents(void)
     int level = fspecial(f, FS_LYCANTROPE);
     if (level > 0) {
       for(u = f->units; u; u=u->nextF) {
-        if(rand()%100 < 2*level) {
+        if(rng_int()%100 < 2*level) {
           ADDMSG(&u->faction->msgs, msg_message("becomewere",
             "unit region", u, u->region));
           fset(u, UFL_WERE);
@@ -1303,7 +1304,7 @@ randomevents(void)
 		}
 		i = chaoscount(r);
 		if (!i) continue;
-		chaoscounts(r, -(int) (i * ((double) (rand() % 10)) / 100.0));
+		chaoscounts(r, -(int) (i * ((double) (rng_int() % 10)) / 100.0));
 	}
 
 #ifdef HERBS_ROT
diff --git a/src/common/gamecode/report.c b/src/common/gamecode/report.c
index aa8ee9b3a..bdc30a32b 100644
--- a/src/common/gamecode/report.c
+++ b/src/common/gamecode/report.c
@@ -68,12 +68,13 @@
 
 /* util includes */
 #include <util/bsdstring.h>
-#include <goodies.h>
-#include <base36.h>
-#include <nrmessage.h>
-#include <translation.h>
+#include <util/goodies.h>
+#include <util/base36.h>
+#include <util/nrmessage.h>
+#include <util/translation.h>
 #include <util/message.h>
-#include <log.h>
+#include <util/rng.h>
+#include <util/log.h>
 
 /* libc includes */
 #include <assert.h>
@@ -1234,8 +1235,9 @@ report_template(const char * filename, report_context * ctx)
   faction * f = ctx->f;
   region *r;
   plane *pl;
-  region *last = lastregion(f);
   FILE * F = fopen(filename, "wt");
+  seen_region * sr = NULL;
+
   if (F==NULL) {
     perror(filename);
     return -1;
@@ -1260,11 +1262,18 @@ report_template(const char * filename, report_context * ctx)
   rps_nowrap(F, buf);
   rnl(F);
 
-  for (r = firstregion(f); r != last; r = r->next) {
+  for (r=ctx->first; sr==NULL && r!=ctx->last; r=r->next) {
+    sr = find_seen(ctx->seen, r);
+  }
+  
+  for (;sr!=NULL;sr=sr->next) {
+    region * r = sr->r;
     unit *u;
-
     int dh = 0;
-    for (u = r->units; u; u = u->next)
+    
+    if (sr->mode<see_unit) continue;
+
+    for (u = r->units; u; u = u->next) {
       if (u->faction == f && u->race != new_race[RC_SPELL]) {
         order * ord;
         if (!dh) {
@@ -1349,6 +1358,7 @@ report_template(const char * filename, report_context * ctx)
         }
 #endif
       }
+    }
   }
   rps_nowrap(F, "");
   rnl(F);
@@ -1721,22 +1731,24 @@ report_building(FILE *F, const region * r, const building * b, const faction * f
 int
 report_plaintext(const char * filename, report_context * ctx)
 {
-	int flag = 0;
-	char ch;
-	int dh;
-	int anyunits;
-	const struct region *r;
+  int flag = 0;
+  char ch;
+  int dh;
+  int anyunits;
+  const struct region *r;
   faction * f = ctx->f;
-	building *b;
-	ship *sh;
-	unit *u;
+  building *b;
+  ship *sh;
+  unit *u;
   char pzTime[64];
-	attrib *a;
-	message * m;
-	unsigned char op;
+  attrib *a;
+  message * m;
+  unsigned char op;
   int ix = Pow(O_STATISTICS);
-	int wants_stats = (f->options & ix);
+  int wants_stats = (f->options & ix);
   FILE * F = fopen(filename, "wt");
+  seen_region * sr = NULL;
+
   if (F==NULL) {
     perror(filename);
     return -1;
@@ -1952,30 +1964,32 @@ report_plaintext(const char * filename, report_context * ctx)
         const char * potiontext = mkname("potion", pname);
         description = LOC(f->locale, potiontext);
       }
-		  centre(F, description, true);
+      centre(F, description, true);
     }
 	}
-	rnl(F);
-	centre(F, LOC(f->locale, "nr_alliances"), false);
-	rnl(F);
-
+  rnl(F);
+  centre(F, LOC(f->locale, "nr_alliances"), false);
+  rnl(F);
+  
 #ifdef ENEMIES
   enemies(F, f);
 #endif
-	allies(F, f);
+  allies(F, f);
+  
+  rpline(F);
+  
+  anyunits = 0;
 
-	rpline(F);
-
-	anyunits = 0;
-
-  for (r=ctx->first;r!=ctx->last;r=r->next) {
+  for (r=ctx->first;sr==NULL && r!=ctx->last;r=r->next) {
+    sr = find_seen(ctx->seen, r);
+  }
+  for (;sr!=NULL;sr=sr->next) {
+    region * r = sr->r;
     boolean unit_in_region = false;
     boolean durchgezogen_in_region = false;
     int turm_sieht_region = false;
-    seen_region * sd = find_seen(ctx->seen, r);
-    if (sd==NULL) continue;
     
-    switch (sd->mode) {
+    switch (sr->mode) {
     case see_lighthouse:
       turm_sieht_region = true;
       break;
@@ -1991,7 +2005,6 @@ report_plaintext(const char * filename, report_context * ctx)
     default:
       continue;
     }
-    r = sd->r;
     /* Beschreibung */
     
     if (unit_in_region) {
@@ -2004,68 +2017,68 @@ report_plaintext(const char * filename, report_context * ctx)
       durchreisende(F, r, f);
     }
     else {
-      if (sd->mode==see_far) {
-			  describe(F, r, 3, f);
-			  guards(F, r, f);
-			  durchreisende(F, r, f);
-		  }
-		  else if (turm_sieht_region) {
-			  describe(F, r, 2, f);
-			  durchreisende(F, r, f);
-		  } else {
-			  describe(F, r, 1, f);
-			  durchreisende(F, r, f);
-		  }
+      if (sr->mode==see_far) {
+        describe(F, r, 3, f);
+        guards(F, r, f);
+        durchreisende(F, r, f);
+      }
+      else if (turm_sieht_region) {
+        describe(F, r, 2, f);
+        durchreisende(F, r, f);
+      } else {
+        describe(F, r, 1, f);
+        durchreisende(F, r, f);
+      }
     }
-		/* Statistik */
-
-		if (wants_stats && unit_in_region == 1)
-			statistics(F, r, f);
-
-		/* Nachrichten an REGION in der Region */
-
-		if (unit_in_region || durchgezogen_in_region) {
-			message_list * mlist = r_getmessages(r, f);
-			rp_messages(F, r->msgs, f, 0, true);
-			if (mlist) rp_messages(F, mlist, f, 0, true);
-		}
-		/* Burgen und ihre Einheiten */
-
-		for (b = rbuildings(r); b; b = b->next) {
-			rnl(F);
-			report_building(F, r, b, f, sd->mode);
-		}
-
-		/* Restliche Einheiten */
-
-		if (sd->mode>=see_lighthouse) {
-			for (u = r->units; u; u = u->next) {
-				if (!u->building && !u->ship) {
-					if ((u->faction == f) ||
-					    (unit_in_region && cansee(f, r, u, 0)) ||
-					    (durchgezogen_in_region && cansee(f, r, u, -1)) ||
-					    (sd->mode==see_far && cansee(f, r, u, -2)) ||
-					    (turm_sieht_region && cansee(f, r, u, -2)))
-					{
-						if (dh == 0 && !(rbuildings(r) || r->ships)) {
-							dh = 1;
-							/* rnl(F); */
-						}
-						rpunit(F, f, u, 4, sd->mode);
-					}
-				}
-			}
-		}
-
-		/* Schiffe und ihre Einheiten */
-
-		for (sh = r->ships; sh; sh = sh->next) {
-			faction *of = NULL;
-
-			rnl(F);
-
-			/* Gewicht feststellen */
+    /* Statistik */
+    
+    if (wants_stats && unit_in_region == 1)
+        statistics(F, r, f);
+    
+    /* Nachrichten an REGION in der Region */
+    
+    if (unit_in_region || durchgezogen_in_region) {
+      message_list * mlist = r_getmessages(r, f);
+      rp_messages(F, r->msgs, f, 0, true);
+      if (mlist) rp_messages(F, mlist, f, 0, true);
+    }
+    /* Burgen und ihre Einheiten */
+    
+    for (b = rbuildings(r); b; b = b->next) {
+      rnl(F);
+      report_building(F, r, b, f, sr->mode);
+    }
+    
+    /* Restliche Einheiten */
+    
+    if (sr->mode>=see_lighthouse) {
+      for (u = r->units; u; u = u->next) {
+        if (!u->building && !u->ship) {
+          if ((u->faction == f) ||
+              (unit_in_region && cansee(f, r, u, 0)) ||
+              (durchgezogen_in_region && cansee(f, r, u, -1)) ||
+              (sr->mode==see_far && cansee(f, r, u, -2)) ||
+              (turm_sieht_region && cansee(f, r, u, -2)))
+          {
+            if (dh == 0 && !(rbuildings(r) || r->ships)) {
+              dh = 1;
+              /* rnl(F); */
+            }
+            rpunit(F, f, u, 4, sr->mode);
+          }
+        }
+      }
+    }
+    
+    /* Schiffe und ihre Einheiten */
 
+    for (sh = r->ships; sh; sh = sh->next) {
+      faction *of = NULL;
+      
+      rnl(F);
+      
+      /* Gewicht feststellen */
+      
       for (u = r->units; u; u = u->next) {
         if (u->ship == sh && fval(u, UFL_OWNER)) {
           of = u->faction;
@@ -2076,7 +2089,7 @@ report_plaintext(const char * filename, report_context * ctx)
         int n = 0, p = 0;
         getshipweight(sh, &n, &p);
         n = (n+99) / 100; /* 1 Silber = 1 GE */
-
+        
         sprintf(buf, "%s, %s, (%d/%d)", shipname(sh), 
           LOC(f->locale, sh->type->name[0]), n, shipcapacity(sh) / 100);
       } else {
@@ -2116,13 +2129,13 @@ report_plaintext(const char * filename, report_context * ctx)
 
       for (u = r->units; u; u = u->next) {
         if (u->ship == sh && fval(u, UFL_OWNER)) {
-          rpunit(F, f, u, 6, sd->mode);
+          rpunit(F, f, u, 6, sr->mode);
           break;
         }
       }
       for (u = r->units; u; u = u->next) {
         if (u->ship == sh && !fval(u, UFL_OWNER)) {
-          rpunit(F, f, u, 6, sd->mode);
+          rpunit(F, f, u, 6, sr->mode);
         }
       }
     }
@@ -2490,7 +2503,7 @@ writemonument(void)
 	fprintf(F, "\n--- newcomer ---\n\n");
 
 	if(count > 7) {
-		ra = rand()%(count-7);
+		ra = rng_int()%(count-7);
 		j = 0;
 		for (r = regions; r; r = r->next) {
 			for (b = r->buildings; b; b = b->next) {
diff --git a/src/common/gamecode/spy.c b/src/common/gamecode/spy.c
index ef65b99c2..125fb1058 100644
--- a/src/common/gamecode/spy.c
+++ b/src/common/gamecode/spy.c
@@ -47,6 +47,7 @@
 /* util includes */
 #include <util/vset.h>
 #include <util/rand.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <assert.h>
@@ -134,7 +135,7 @@ setwere_cmd(unit *u, struct order * ord)
   if (s == NULL || *s == '\0') {
     if(fval(u, UFL_WERE)) {
       cmistake(u, ord, 309, MSG_EVENT);
-    } else if(rand()%100 < 35+(level-1)*20) { /* 35, 55, 75, 95% */
+    } else if(rng_int()%100 < 35+(level-1)*20) { /* 35, 55, 75, 95% */
       fset(u, UFL_WERE);
     } else {
       cmistake(u, ord, 311, MSG_EVENT);
@@ -142,7 +143,7 @@ setwere_cmd(unit *u, struct order * ord)
   } else if (findparam(s, u->faction->locale) == P_NOT) {
     if(fval(u, UFL_WERE)) {
       cmistake(u, ord, 310, MSG_EVENT);
-    } else if(rand()%100 < 90-level*20) {	/* 70, 50, 30, 10% */
+    } else if(rng_int()%100 < 90-level*20) {	/* 70, 50, 30, 10% */
       freset(u, UFL_WERE);
     } else {
       cmistake(u, ord, 311, MSG_EVENT);
diff --git a/src/common/gamecode/study.c b/src/common/gamecode/study.c
index 1b2bbde98..58d352a0d 100644
--- a/src/common/gamecode/study.c
+++ b/src/common/gamecode/study.c
@@ -194,7 +194,7 @@ teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk,
       int j = study_cost(student, sk);
       j = max(50, j * 2);
       /* kann Einheit das zahlen? */
-      if (get_pooled(student, oldresourcetype[R_SILVER], GET_DEFAULT) >= j) {
+      if (get_pooled(student, oldresourcetype[R_SILVER], GET_DEFAULT, j) >= j) {
         /* Jeder Sch�ler zus�tzlich +10 Tage wenn in Uni. */
         teach->value += (n / 30) * 10; /* learning erh�hen */
         /* Lehrer zus�tzlich +1 Tag pro Sch�ler. */
@@ -605,8 +605,9 @@ learn(void)
             }
         }
         if (studycost) {
-          money = get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT);
-          money = min(money, studycost * u->number);
+          int cost = studycost * u->number;
+          money = get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT, cost);
+          money = min(money, cost);
         }
         if (money < studycost * u->number) {
           studycost = p;	/* Ohne Univertreurung */
diff --git a/src/common/items/phoenixcompass.c b/src/common/items/phoenixcompass.c
index 37d896a37..600cc5044 100644
--- a/src/common/items/phoenixcompass.c
+++ b/src/common/items/phoenixcompass.c
@@ -26,11 +26,11 @@
 /* util includes */
 #include <util/functions.h>
 #include <util/rand.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <assert.h>
 #include <string.h>
-#include <stdlib.h>
 #include <limits.h>
 
 static int
@@ -98,7 +98,7 @@ use_phoenixcompass(struct unit * u, const struct item_type * itype,
       if(dist < closest_neighbour_distance) {
         closest_neighbour_direction = direction;
         closest_neighbour_distance = dist;
-      } else if(dist == closest_neighbour_distance && rand()%100 < 50) {
+      } else if(dist == closest_neighbour_distance && rng_int()%100 < 50) {
         /* there can never be more than two neighbours with the same
          * distance (except when you are standing in the same region
          * as the phoenix, but that case has already been handled).
diff --git a/src/common/items/weapons.c b/src/common/items/weapons.c
index f5c857c7c..94d18982a 100644
--- a/src/common/items/weapons.c
+++ b/src/common/items/weapons.c
@@ -24,7 +24,8 @@
 #include <pool.h>
 
 /* util includes */
-#include <functions.h>
+#include <util/functions.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <assert.h>
@@ -82,7 +83,7 @@ attack_firesword(const troop * at, const struct weapon_type * wtype, int *casual
 	int enemies = 0;
 	int killed = 0;
 	const char *damage = "2d8";
-	int force  = 1+rand()%10;
+	int force  = 1+rng_int()%10;
 
 	if (row==FIGHT_ROW) {
 		enemies = count_enemies(fi->side->battle, fi->side, minrow, maxrow, true);
@@ -140,7 +141,7 @@ attack_catapult(const troop * at, const struct weapon_type * wtype, int * casual
 	assert(af->person[at->index].reload==0);
 
   if (it_catapultammo!=NULL) {
-    if (get_pooled(au, it_catapultammo->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK) <= 0) {
+    if (get_pooled(au, it_catapultammo->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, 1) <= 0) {
       /* No ammo. Use other weapon if available. */
       return true;
     }
@@ -174,9 +175,9 @@ attack_catapult(const troop * at, const struct weapon_type * wtype, int * casual
 		if (hits(*at, dt, wp)) {
 			d += terminate(dt, *at, AT_STANDARD, wp->type->damage[0], true);
 #ifdef CATAPULT_STRUCTURAL_DAMAGE
-			if (dt.fighter->unit->building && rand()%100 < 5) {
+			if (dt.fighter->unit->building && rng_int()%100 < 5) {
 				damage_building(b, dt.fighter->unit->building, 1);
-			} else if (dt.fighter->unit->ship && rand()%100 < 5) {
+			} else if (dt.fighter->unit->ship && rng_int()%100 < 5) {
 				dt.fighter->unit->ship->damage+=DAMAGE_SCALE;
 			}
 #endif
diff --git a/src/common/kernel/battle.c b/src/common/kernel/battle.c
index 0db147d1a..3ea8c4fc2 100644
--- a/src/common/kernel/battle.c
+++ b/src/common/kernel/battle.c
@@ -56,6 +56,7 @@
 #include <util/bsdstring.h>
 #include <util/cvector.h>
 #include <util/rand.h>
+#include <util/rng.h>
 #include <util/log.h>
 
 /* libc includes */
@@ -63,7 +64,6 @@
 #include <ctype.h>
 #include <limits.h>
 #include <math.h>
-#include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
 
@@ -73,7 +73,7 @@ static FILE *bdebug;
 #undef DELAYED_OFFENSE /* non-guarding factions cannot attack after moving */
 
 #define TACTICS_RANDOM 5 /* define this as 1 to deactivate */
-#define CATAPULT_INITIAL_RELOAD 4 /* erster schuss in runde 1 + rand() % INITIAL */
+#define CATAPULT_INITIAL_RELOAD 4 /* erster schuss in runde 1 + rng_int() % INITIAL */
 #define CATAPULT_STRUCTURAL_DAMAGE
 
 #define BASE_CHANCE    70 /* 70% Basis-�berlebenschance */
@@ -143,7 +143,7 @@ fleeregion(const unit * u)
 
 	if (!c)
 		return NULL;
-	return neighbours[rand() % c];
+	return neighbours[rng_int() % c];
 }
 
 static char *
@@ -331,7 +331,7 @@ select_corpse(battle * b, fighter * af)
 	}
 	cv_next(side);
 
-	di = rand() % maxcasualties;
+	di = rng_int() % maxcasualties;
 	cv_foreach(df, b->fighters) {
 		/* Geflohene haben auch 0 hp, d�rfen hier aber nicht ausgew�hlt
 		 * werden! */
@@ -522,7 +522,7 @@ contest(int skilldiff, const armor_type * ar, const armor_type * sh)
 	vw = (int)(100 - ((100 - vw) * mod));
 
 	do {
-		p = rand() % 100;
+		p = rng_int() % 100;
 		vw -= p;
 	}
 	while (vw >= 0 && p >= 90);
@@ -849,7 +849,7 @@ remove_troop(troop dt)
 void
 drain_exp(struct unit *u, int n)
 {
-	skill_t sk = (skill_t)(rand() % MAXSKILLS);
+	skill_t sk = (skill_t)(rng_int() % MAXSKILLS);
 	skill_t ssk;
 
 	ssk = sk;
@@ -870,7 +870,7 @@ drain_exp(struct unit *u, int n)
 				reduce_skill(u, sv, 1);
 				n-=30;
 			} else {
-				if (rand()%(30*u->number)<n) reduce_skill(u, sv, 1);
+				if (rng_int()%(30*u->number)<n) reduce_skill(u, sv, 1);
 				n = 0;
 			}
 		}
@@ -1192,7 +1192,7 @@ terminate(troop dt, troop at, int type, const char *damage, boolean missile)
     const item_type * itype = (*pitm)->type;
     if (!itype->flags & ITF_CURSED && dt.index < (*pitm)->number) {
       /* 25% Grundchance, das ein Item kaputtgeht. */
-      if (rand() % 4 < 1) i_change(pitm, itype, -1);
+      if (rng_int() % 4 < 1) i_change(pitm, itype, -1);
     }
   }
   remove_troop(dt);
@@ -1269,7 +1269,7 @@ select_enemy(battle * b, fighter * af, int minrow, int maxrow, boolean advance)
   /* Niemand ist in der angegebenen Entfernung? */
   if (enemies<=0) return no_troop;
 
-  enemies = rand() % enemies;
+  enemies = rng_int() % enemies;
   for (si=0;as->enemies[si];++si) {
     side *ds = as->enemies[si];
     void ** fi;
@@ -1556,7 +1556,7 @@ do_combatspell(troop at, int row)
   }
 
   /* Antimagie die Fehlschlag erh�ht */
-  if (rand()%100 < fumblechance) {
+  if (rng_int()%100 < fumblechance) {
     report_failed_spell(b, mage, sp);
     pay_spell(mage, sp, level, 1);
     free_order(ord);
@@ -1735,7 +1735,7 @@ attack_message(const troop at, const troop dt, const weapon * wp, int dist)
 
 	if (wp == NULL) {
 		sprintf(smallbuf, "%s %s %s",
-			a_unit, noweap_string[rand()%4], d_unit);
+			a_unit, noweap_string[rng_int()%4], d_unit);
 		return smallbuf;
 	}
 
@@ -1779,12 +1779,12 @@ hits(troop at, troop dt, weapon * awp)
 			af->person[at.index].flags &= ~FL_STUNNED;
 		return 0;
 	}
-	if ((af->person[at.index].flags & FL_TIRED && rand()%100 < 50)
+	if ((af->person[at.index].flags & FL_TIRED && rng_int()%100 < 50)
 			|| (af->person[at.index].flags & FL_SLEEPING))
 		return 0;
 	if (awp && fval(awp->type, WTF_MISSILE)
 			&& af->side->battle->reelarrow == true
-			&& rand()%100 < 50)
+			&& rng_int()%100 < 50)
 	{
 		return 0;
 	}
@@ -2053,7 +2053,7 @@ attack(battle *b, troop ta, const att *a, int numattack)
 		if (hits(ta, td, NULL)) {
 			int c = dice_rand(a->data.dice);
 			while(c > 0) {
-				if (rand()%2) {
+				if (rng_int()%2) {
 					td.fighter->person[td.index].attack -= 1;
 				} else {
 					td.fighter->person[td.index].defence -= 1;
@@ -2263,7 +2263,7 @@ loot_items(fighter * corpse)
           if (itm->type->flags & (ITF_CURSED|ITF_NOTLOST)) maxrow = LAST_ROW;
           itm->number -= loot;
 
-          if (maxrow == LAST_ROW || rand() % 100 < lootchance) {
+          if (maxrow == LAST_ROW || rng_int() % 100 < lootchance) {
             fighter *fig = select_enemy(b, corpse, FIGHT_ROW, maxrow, false).fighter;
             if (fig) {
               item * l = fig->loot;
@@ -2382,7 +2382,7 @@ aftermath(battle * b)
     /* Regeneration durch PR_MERCY */
     if (dead>0 && pr_mercy) {
       for (i = 0; i != dead; ++i) {
-        if (rand()%100 < pr_mercy) {
+        if (rng_int()%100 < pr_mercy) {
           ++df->alive;
           ++df->side->alive;
           ++df->side->battle->alive;
@@ -3089,7 +3089,7 @@ make_fighter(battle * b, unit * u, side * s1, boolean attack)
 			int rnd;
 
 			do {
-				rnd = rand()%100;
+				rnd = rng_int()%100;
 				if (rnd >= 40 && rnd <= 69)
 					p_bonus += 1;
 				else if (rnd <= 89)
diff --git a/src/common/kernel/border.c b/src/common/kernel/border.c
index c8b6a040c..0c220b12f 100644
--- a/src/common/kernel/border.c
+++ b/src/common/kernel/border.c
@@ -21,10 +21,11 @@
 #include "terrain.h"
 #include "unit.h"
 
+#include <util/rng.h>
+
 /* libc includes */
 #include <assert.h>
 #include <limits.h>
-#include <stdlib.h>
 #include <string.h>
 
 extern boolean incomplete_data;
@@ -549,7 +550,7 @@ read_borders(FILE * f)
     }
 
     if (to==from) {
-      direction_t dir = (direction_t) (rand() % MAXDIRECTIONS);
+      direction_t dir = (direction_t) (rng_int() % MAXDIRECTIONS);
       region * r = rconnect(from, dir);
       log_error(("[read_borders] invalid %s in %s\n", type->__name, 
 				 regionname(from, NULL)));
diff --git a/src/common/kernel/build.c b/src/common/kernel/build.c
index 774f66857..bc2f13a66 100644
--- a/src/common/kernel/build.c
+++ b/src/common/kernel/build.c
@@ -192,7 +192,7 @@ siege_cmd(unit * u, order * ord)
   region * r = u->region;
   unit *u2;
   building *b;
-  int d;
+  int d, pooled;
   int bewaffnete, katapultiere = 0;
   static boolean init = false;
   static const curse_type * magicwalls_ct;
@@ -222,8 +222,10 @@ siege_cmd(unit * u, order * ord)
   }
   /* schaden durch katapulte */
 
-  d = min(u->number, i_get(u->items, it_catapult));
-  d = min(get_pooled(u, it_catapultammo->rtype, GET_DEFAULT), d);
+  d = i_get(u->items, it_catapult);
+  d = min(u->number, d);
+  pooled = get_pooled(u, it_catapultammo->rtype, GET_DEFAULT, d);
+  d = min(pooled, d);
   if (eff_skill(u, SK_CATAPULT, r) >= 1) {
     katapultiere = d;
     d *= eff_skill(u, SK_CATAPULT, r);
@@ -501,13 +503,10 @@ build_road(region * r, unit * u, int size, direction_t d)
       return;
     }
   }
-  if (!get_pooled(u, oldresourcetype[R_STONE], GET_DEFAULT) && u->race != new_race[RC_STONEGOLEM]) {
-    cmistake(u, u->thisorder, 151, MSG_PRODUCE);
-    return;
-  }
-
+  
   /* left kann man noch bauen */
   left = r->terrain->max_road - rroad(r, d);
+
   /* hoffentlich ist r->road <= r->terrain->max_road, n also >= 0 */
   if (left <= 0) {
     sprintf(buf, "In %s gibt es keine Br�cken und Stra�en "
@@ -516,14 +515,18 @@ build_road(region * r, unit * u, int size, direction_t d)
     return;
   }
 
+  if (size>0) left = min(size, left);
   /* baumaximum anhand der rohstoffe */
   if (u->race == new_race[RC_STONEGOLEM]){
     n = u->number * GOLEM_STONE;
   } else {
-    n = get_pooled(u, oldresourcetype[R_STONE], GET_DEFAULT);
+    n = get_pooled(u, oldresourcetype[R_STONE], GET_DEFAULT, left);
+    if (n==0) {
+      cmistake(u, u->thisorder, 151, MSG_PRODUCE);
+      return;
+    }
   }
   left = min(n, left);
-  if (size>0) left = min(size, left);
 
   /* n = maximum by skill. try to maximize it */
   n = u->number * eff_skill(u, SK_ROAD_BUILDING, r);
@@ -710,13 +713,13 @@ build(unit * u, const construction * ctype, int completed, int want)
 
     if (type->materials) for (c=0;n>0 && type->materials[c].number;c++) {
       const struct resource_type * rtype = type->materials[c].rtype;
-      int need;
-      int have = get_pooled(u, rtype, GET_DEFAULT);
-      int prebuilt;
-      int canuse = have;
+      int need, prebuilt;
+      int canuse = get_pooled(u, rtype, GET_DEFAULT, INT_MAX);
+
       if (inside_building(u)) {
         canuse = matmod(u->building->type->attribs, u, rtype, canuse);
       }
+
       if (canuse<0) return canuse; /* pass errors to caller */
       canuse = matmod(type->attribs, u, rtype, canuse);
       if (type->reqsize>1) {
@@ -771,7 +774,7 @@ maxbuild(const unit * u, const construction * cons)
   int maximum = INT_MAX;
   for (c=0;cons->materials[c].number;c++) {
     const resource_type * rtype = cons->materials[c].rtype;
-    int have = get_pooled(u, rtype, GET_DEFAULT);
+    int have = get_pooled(u, rtype, GET_DEFAULT, INT_MAX);
     int need = required(1, cons->reqsize, cons->materials[c].number);
     if (have<need) {
       cmistake(u, u->thisorder, 88, MSG_PRODUCE);
diff --git a/src/common/kernel/curse.c b/src/common/kernel/curse.c
index 7efcd8a5f..5cf6d85b5 100644
--- a/src/common/kernel/curse.c
+++ b/src/common/kernel/curse.c
@@ -38,13 +38,13 @@
 #include <util/resolve.h>
 #include <util/base36.h>
 #include <util/rand.h>
+#include <util/rng.h>
 #include <util/goodies.h>
 #include <util/variant.h>
 
 /* libc includes */
 #include <stdio.h>
 #include <string.h>
-#include <stdlib.h>
 #include <limits.h>
 #include <assert.h>
 #include <math.h>
@@ -584,7 +584,7 @@ do_transfer_curse(curse *c, unit * u, unit * u2, int n)
 			int i;
 			int u_number = u->number;
 			for (i=0;i<n+1 && u_number>0;i++){
-				if (rand()%u_number < cursedmen){
+				if (rng_int()%u_number < cursedmen){
 					++men;
 					--cursedmen;
 					dogive = true;
diff --git a/src/common/kernel/equipment.c b/src/common/kernel/equipment.c
index ba057b5d0..afa07fa51 100644
--- a/src/common/kernel/equipment.c
+++ b/src/common/kernel/equipment.c
@@ -28,6 +28,7 @@
 
 /* util includes */
 #include <util/rand.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <string.h>
@@ -141,7 +142,7 @@ equip_unit(struct unit * u, const struct equipment * eq)
       int i;
       for (i=0;eq->subsets[i].sets;++i) {
         if (chance(eq->subsets[i].chance)) {
-          float rnd = (1+rand() % 1000) / 1000.0f;
+          float rnd = (1+rng_int() % 1000) / 1000.0f;
           int k;
           for (k=0;eq->subsets[i].sets[k].set;++k) {
             if (rnd<=eq->subsets[i].sets[k].chance) {
@@ -172,7 +173,7 @@ equip_items(struct item ** items, const struct equipment * eq)
       int i;
       for (i=0;eq->subsets[i].sets;++i) {
         if (chance(eq->subsets[i].chance)) {
-          float rnd = (1+rand() % 1000) / 1000.0f;
+          float rnd = (1+rng_int() % 1000) / 1000.0f;
           int k;
           for (k=0;eq->subsets[i].sets[k].set;++k) {
             if (rnd<=eq->subsets[i].sets[k].chance) {
diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c
index b5d6d84e4..a36b15bab 100644
--- a/src/common/kernel/eressea.c
+++ b/src/common/kernel/eressea.c
@@ -64,6 +64,7 @@
 #include <util/event.h>
 #include <util/functions.h>
 #include <util/log.h>
+#include <util/rng.h>
 #include <util/sql.h>
 #include <util/translation.h>
 #include <util/umlaut.h>
@@ -75,7 +76,6 @@
 
 /* libc includes */
 #include <stdio.h>
-#include <stdlib.h>
 #include <message.h>
 #include <string.h>
 #include <ctype.h>
@@ -766,7 +766,7 @@ distribute(int old, int new_value, int n)
 
 	t = (n / old) * new_value;
 	for (i = (n % old); i; i--)
-		if (rand() % old < new_value)
+		if (rng_int() % old < new_value)
 			t++;
 
 	return t;
@@ -881,7 +881,7 @@ scale_number (unit * u, int n)
     full = u->hp/u->number; /* wieviel kriegt jede person mindestens */
     u->hp = full * n + (u->hp-full*u->number) * n / u->number;
     assert(u->hp>=0);
-    if ((rand() % u->number) < remain)
+    if ((rng_int() % u->number) < remain)
       ++u->hp;	/* Nachkommastellen */
   } else {
     remain = 0;
@@ -894,7 +894,7 @@ scale_number (unit * u, int n)
       remain = data->value - snew / n * u->number;
       snew += remain * n / u->number;
       remain = (remain * n) % u->number;
-      if ((rand() % u->number) < remain)
+      if ((rng_int() % u->number) < remain)
         ++snew;	/* Nachkommastellen */
     }
     data->value = snew;
@@ -1850,7 +1850,7 @@ newunitid(void)
 {
 	int random_unit_no;
 	int start_random_no;
-	random_unit_no = 1 + (rand() % MAX_UNIT_NR);
+	random_unit_no = 1 + (rng_int() % MAX_UNIT_NR);
 	start_random_no = random_unit_no;
 
 	while (ufindhash(random_unit_no) || dfindhash(random_unit_no)
@@ -1874,7 +1874,7 @@ newcontainerid(void)
 	int random_no;
 	int start_random_no;
 
-	random_no = 1 + (rand() % MAX_CONTAINER_NR);
+	random_no = 1 + (rng_int() % MAX_CONTAINER_NR);
 	start_random_no = random_no;
 
 	while (findship(random_no) || findbuilding(random_no)) {
@@ -2678,7 +2678,7 @@ hunger(int number, unit * u)
 	int hp = u->hp / u->number;
 
 	while (number--) {
-		int dam = u->race==new_race[RC_HALFLING]?15+rand()%14:(13+rand()%12);
+		int dam = u->race==new_race[RC_HALFLING]?15+rng_int()%14:(13+rng_int()%12);
 		if (dam >= hp) {
 			++dead;
 		} else {
@@ -2711,40 +2711,36 @@ hunger(int number, unit * u)
 void
 plagues(region * r, boolean ismagic)
 {
-	double prob;
-	int peasants;
-	int i;
-	int gestorben;
-	/* Vermeidung von DivByZero */
-	double mwp = max(maxworkingpeasants(r), 1);
+  int peasants;
+  int i;
+  int dead = 0;
 
-	/* Seuchenwahrscheinlichkeit in % */
+  /* Seuchenwahrscheinlichkeit in % */
 
-	prob = pow((double) rpeasants(r) /
-	  (mwp * (((double)wage(r, NULL, NULL)) / 10.0) * 1.3), 4.0)
-		* (double) SEUCHE;
+  if (!ismagic) {
+    double mwp = max(maxworkingpeasants(r), 1);
+    double prob = pow(rpeasants(r) / (mwp * wage(r, NULL, NULL) * 0.13), 4.0)
+        * SEUCHE;
+    
+    if (rng_double() >= prob) return;
+  }
 
-	if (rand() % 100 >= (int)prob && !ismagic) return;
+  peasants = rpeasants(r);
+  dead = (int)(0.5F + SEUCHENOPFER * peasants);
+  for (i = dead; i != 0; i--) {
+    if (rng_int() % 100 < HEILCHANCE && rmoney(r) >= HEILKOSTEN) {
+      rsetmoney(r, rmoney(r) - HEILKOSTEN);
+    } else {
+      --dead;
+    }
+  }
 
-	peasants = rpeasants(r);
-	for (i = peasants; i != 0; i--) {
-		if (rand() % 100 < SEUCHENOPFER) {
-			if (rand() % 100 < HEILCHANCE && rmoney(r) >= HEILKOSTEN) {
-				rsetmoney(r, rmoney(r) - HEILKOSTEN);
-			} else {
-				peasants--;
-			}
-		}
-	}
-
-	gestorben = rpeasants(r) - peasants;
-
-	if (gestorben > 0) {
-		message * msg = add_message(&r->msgs, msg_message("pest", "dead", gestorben));
-		msg_release(msg);
-		deathcounts(r, gestorben);
-	}
-	rsetpeasants(r, peasants);
+  if (dead > 0) {
+    message * msg = add_message(&r->msgs, msg_message("pest", "dead", dead));
+    msg_release(msg);
+    deathcounts(r, dead);
+    rsetpeasants(r, peasants - dead);
+  }
 }
 
 /* Lohn bei den einzelnen Burgstufen f�r Normale Typen, Orks, Bauern,
@@ -3053,7 +3049,7 @@ lovar(double xpct_x2)
 {
   int n = (int)(xpct_x2 * 500)+1;
   if (n==0) return 0;
-	return (rand() % n + rand() % n)/1000;
+	return (rng_int() % n + rng_int() % n)/1000;
 }
 
 boolean
@@ -3139,9 +3135,9 @@ kernel_init(void)
 
 	if (!turn) turn = lastturn();
 	if (turn == 0)
-		srand((int)time(0));
+		rng_init((int)time(0));
 	else
-		srand(turn);
+		rng_init(turn);
 	if (sqlpatch) {
 		sprintf(zBuffer, "%s/patch-%d.sql", datapath(), turn);
 		sql_init(zBuffer);
diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h
index 1fd57cee8..419c2af89 100644
--- a/src/common/kernel/eressea.h
+++ b/src/common/kernel/eressea.h
@@ -223,27 +223,12 @@ extern void read_laen(struct region * r, int laen);
 
 #define DISALLOW_ATTACK_AND_WORK
 
-/** Ausbreitung und Vermehrung */
-
-#define MAXDEMAND      25
-#define DMRISE         10
-#define DMRISEHAFEN    20
-
 /* Vermehrung trotz 90% Auslastung */
 #define PEASANTFORCE   0.75
 
 #define PEASANTSWANDER_WEIGHT 5
 #define PEASANTSGREED_WEIGHT  5
 
-#define STARVATION_SURVIVAL  10
-
-/* Pferdevermehrung */
-#define HORSEGROWTH 4
-/* Wanderungschance pro Pferd */
-#define HORSEMOVE   3
-
-/* Vermehrungschance pro Baum */
-#define FORESTGROWTH 10000					/* In Millionstel */
 #define TREESIZE     (MAXPEASANTS_PER_AREA-2)
 
 /* Eisen in Bergregionen bei Erschaffung */
@@ -273,9 +258,9 @@ extern void read_laen(struct region * r, int laen);
 
 /** Plagues **/
 /* Seuchenwahrscheinlichkeit (siehe plagues()) */
-#define SEUCHE         10
+#define SEUCHE         0.1F
 /* % Betroffene */
-#define SEUCHENOPFER   20
+#define SEUCHENOPFER   0.2F
 extern void plagues(struct region * r, boolean ismagic);
 
 /** Healing **/
diff --git a/src/common/kernel/faction.c b/src/common/kernel/faction.c
index a1260e6f4..e3fdbaf01 100644
--- a/src/common/kernel/faction.c
+++ b/src/common/kernel/faction.c
@@ -31,6 +31,7 @@
 #include <util/event.h>
 #include <util/goodies.h>
 #include <util/resolve.h>
+#include <util/rng.h>
 #include <util/variant.h>
 
 #include <attributes/otherfaction.h>
@@ -48,7 +49,7 @@ random_unit_in_faction(const faction *f)
 
   for(u = f->units; u; u=u->next) c++;
 
-  u_nr = rand()%c;
+  u_nr = rng_int()%c;
   c = 0;
 
   for(u = f->units; u; u=u->next)
@@ -85,7 +86,7 @@ resolve_faction(variant id) {
 static int
 unused_faction_id(void)
 {
-  int id = rand()%MAX_FACTION_ID;
+  int id = rng_int()%MAX_FACTION_ID;
 
   while (!faction_id_is_unused(id)) {
     id++; if(id == MAX_FACTION_ID) id = 0;
@@ -111,10 +112,10 @@ addfaction(const char *email, const char * password,
   if (password) {
     set_string(&f->passw, password);
   } else {
-    for (i = 0; i < 6; i++) buf[i] = (char) (97 + rand() % 26); buf[i] = 0;
+    for (i = 0; i < 6; i++) buf[i] = (char) (97 + rng_int() % 26); buf[i] = 0;
     set_string(&f->passw, buf);
   }
-  for (i = 0; i < 6; i++) buf[i] = (char) (97 + rand() % 26); buf[i] = 0;
+  for (i = 0; i < 6; i++) buf[i] = (char) (97 + rng_int() % 26); buf[i] = 0;
   set_string(&f->override, buf);
 
   f->lastorders = turn;
@@ -152,7 +153,7 @@ addplayer(region *r, faction * f)
   if (f->race == new_race[RC_DAEMON]) {
     race_t urc;
     do {
-      urc = (race_t)(rand() % MAXRACES);
+      urc = (race_t)(rng_int() % MAXRACES);
     } while (new_race[urc]==NULL || urc == RC_DAEMON || !playerrace(new_race[urc]));
     u->irace = new_race[urc];
   }
diff --git a/src/common/kernel/faction.h b/src/common/kernel/faction.h
index db761a8e8..56d4476ec 100644
--- a/src/common/kernel/faction.h
+++ b/src/common/kernel/faction.h
@@ -18,7 +18,8 @@ extern "C" {
 
 struct player;
 struct alliance;
-
+struct item;
+  
 /* SMART_INTERVALS: define to speed up finding the interval of regions that a 
    faction is in. defining this speeds up the turn by 30-40% */
 #define SMART_INTERVALS
diff --git a/src/common/kernel/give.c b/src/common/kernel/give.c
index e43f86766..26541349c 100644
--- a/src/common/kernel/give.c
+++ b/src/common/kernel/give.c
@@ -96,7 +96,7 @@ give_item(int want, const item_type * itype, unit * src, unit * dest, struct ord
   int n;
 
   assert(itype!=NULL);
-  n = get_pooled(src, item2resource(itype), GET_DEFAULT);
+  n = get_pooled(src, item2resource(itype), GET_DEFAULT, want);
   n = min(want, n);
   if (dest && src->faction != dest->faction && src->faction->age < GiveRestriction()) {
 		if (ord!=NULL) {
diff --git a/src/common/kernel/item.c b/src/common/kernel/item.c
index 4832fe0bd..c0014ebc6 100644
--- a/src/common/kernel/item.c
+++ b/src/common/kernel/item.c
@@ -40,6 +40,7 @@
 #include <util/goodies.h>
 #include <util/message.h>
 #include <util/umlaut.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <assert.h>
@@ -315,20 +316,21 @@ new_potiontype(item_type * itype,
 void
 rt_register(resource_type * rtype)
 {
-	resource_type ** prtype = &resourcetypes;
-
-	if (!rtype->hashkey)
-		rtype->hashkey = hashstring(rtype->_name[0]);
-	while (*prtype && *prtype!=rtype) prtype=&(*prtype)->next;
-	if (*prtype == NULL) {
-		*prtype = rtype;
-	}
+  resource_type ** prtype = &resourcetypes;
+  
+  if (!rtype->hashkey) {
+    rtype->hashkey = hashstring(rtype->_name[0]);
+  }
+  while (*prtype && *prtype!=rtype) prtype=&(*prtype)->next;
+  if (*prtype == NULL) {
+    *prtype = rtype;
+  }
 }
 
 const resource_type *
 item2resource(const item_type * itype)
 {
-	return itype->rtype;
+  return itype->rtype;
 }
 
 const item_type *
@@ -339,18 +341,18 @@ resource2item(const resource_type * rtype)
 
 const weapon_type *
 resource2weapon(const resource_type * rtype) {
-	return rtype->wtype;
+  return rtype->wtype;
 }
 
 const luxury_type *
 resource2luxury(const resource_type * rtype)
 {
 #ifdef AT_LTYPE
-	attrib * a = a_find(rtype->attribs, &at_ltype);
-	if (a) return (const luxury_type *)a->data.v;
-	return NULL;
+  attrib * a = a_find(rtype->attribs, &at_ltype);
+  if (a) return (const luxury_type *)a->data.v;
+  return NULL;
 #else
-	return rtype->ltype;
+  return rtype->ltype;
 #endif
 }
 
@@ -358,25 +360,25 @@ const potion_type *
 resource2potion(const resource_type * rtype)
 {
 #ifdef AT_PTYPE
-	attrib * a = a_find(rtype->attribs, &at_ptype);
-	if (a) return (const potion_type *)a->data.v;
-	return NULL;
+  attrib * a = a_find(rtype->attribs, &at_ptype);
+  if (a) return (const potion_type *)a->data.v;
+  return NULL;
 #else
-	return rtype->ptype;
+  return rtype->ptype;
 #endif
 }
 
 resource_type *
 rt_find(const char * name)
 {
-	unsigned int hash = hashstring(name);
-	resource_type * rtype;
+  unsigned int hash = hashstring(name);
+  resource_type * rtype;
 
   for (rtype=resourcetypes; rtype; rtype=rtype->next) {
     if (rtype->hashkey==hash && !strcmp(rtype->_name[0], name)) break;
   }
 
-	return rtype;
+  return rtype;
 }
 
 static const char * it_aliases[][2] = { 
@@ -401,57 +403,57 @@ it_alias(const char * zname)
 item_type *
 it_find(const char * zname)
 {
-	const char * name = it_alias(zname);
-	unsigned int hash = hashstring(name);
-	item_type * itype;
+  const char * name = it_alias(zname);
+  unsigned int hash = hashstring(name);
+  item_type * itype;
   unsigned int key = hash % IMAXHASH;
-
+  
   for (itype=itemtypes[key]; itype; itype=itype->next) {
     if (itype->rtype->hashkey==hash && strcmp(itype->rtype->_name[0], name) == 0) {
       break;
     }
-	}
+  }
   if (itype==NULL) {
     for (itype=itemtypes[key]; itype; itype=itype->next) {
       if (strcmp(itype->rtype->_name[1], name) == 0) break;
     }
   }
-	return itype;
+  return itype;
 }
 
 item **
 i_find(item ** i, const item_type * it)
 {
-	while (*i && (*i)->type!=it) i = &(*i)->next;
-	return i;
+  while (*i && (*i)->type!=it) i = &(*i)->next;
+  return i;
 }
 
 
 int
 i_get(const item * i, const item_type * it)
 {
-	i = *i_find((item**)&i, it);
-	if (i) return i->number;
-	return 0;
+  i = *i_find((item**)&i, it);
+  if (i) return i->number;
+  return 0;
 }
 
 item *
 i_add(item ** pi, item * i)
 {
-	assert(i && i->type && !i->next);
-	while (*pi) {
-		int d = strcmp((*pi)->type->rtype->_name[0], i->type->rtype->_name[0]);
-		if (d>=0) break;
-		pi = &(*pi)->next;
-	}
-	if (*pi && (*pi)->type==i->type) {
-		(*pi)->number += i->number;
-		i_free(i);
-	} else {
-		i->next = *pi;
-		*pi = i;
-	}
-	return *pi;
+  assert(i && i->type && !i->next);
+  while (*pi) {
+    int d = strcmp((*pi)->type->rtype->_name[0], i->type->rtype->_name[0]);
+    if (d>=0) break;
+    pi = &(*pi)->next;
+  }
+  if (*pi && (*pi)->type==i->type) {
+    (*pi)->number += i->number;
+    i_free(i);
+  } else {
+    i->next = *pi;
+    *pi = i;
+  }
+  return *pi;
 }
 
 void
@@ -629,7 +631,7 @@ use_tacticcrystal(region * r, unit * u, int amount, struct order * ord)
 		curse * c;
     variant effect;
 
-    effect.i = rand()%6 - 1;
+    effect.i = rng_int()%6 - 1;
     c = create_curse(u, &u->attribs, ct_find("skillmod"), power,
 			duration, effect, u->number);
 		c->data.i = SK_TACTICS;
@@ -1125,7 +1127,7 @@ use_bloodpotion(struct unit *u, const struct item_type *itype, int amount, struc
     change_effect(u, itype->rtype->ptype, 100*amount);
 	} else {
     trigger * trestore = trigger_changerace(u, u->race, u->irace);
-    int duration = 2 + rand() % 8;
+    int duration = 2 + rng_int() % 8;
 
     add_trigger(&u->attribs, "timer", trigger_timeout(duration, trestore));
     u->irace = u->race = new_race[RC_TOAD];
@@ -1142,25 +1144,25 @@ use_bloodpotion(struct unit *u, const struct item_type *itype, int amount, struc
 static int
 use_mistletoe(struct unit * user, const struct item_type * itype, int amount, struct order * ord)
 {
-	int mtoes = get_pooled(user, itype->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK);
+  int mtoes = get_pooled(user, itype->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, user->number);
 
-	if (user->number>mtoes) {
-		ADDMSG(&user->faction->msgs, msg_message("use_singleperson",
-			"unit item region command", user, itype->rtype, user->region, ord));
-		return -1;
-	}
-	use_pooled(user, itype->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, user->number);
-	a_add(&user->attribs, make_fleechance((float)1.0));
-		ADDMSG(&user->faction->msgs, msg_message("use_item",
-			"unit item", user, itype->rtype));
-	
-	return 0;
+  if (user->number>mtoes) {
+    ADDMSG(&user->faction->msgs, msg_message("use_singleperson",
+                                             "unit item region command", user, itype->rtype, user->region, ord));
+    return -1;
+  }
+  use_pooled(user, itype->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, user->number);
+  a_add(&user->attribs, make_fleechance((float)1.0));
+  ADDMSG(&user->faction->msgs, 
+         msg_message("use_item", "unit item", user, itype->rtype));
+  
+  return 0;
 }
 
 static int
 use_magicboost(struct unit * user, const struct item_type * itype, int amount, struct order * ord)
 {
-  int mtoes = get_pooled(user, itype->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK);
+  int mtoes = get_pooled(user, itype->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, user->number);
   faction * f = user->faction;
   if (user->number>mtoes) {
     ADDMSG(&user->faction->msgs, msg_message("use_singleperson",
diff --git a/src/common/kernel/item.h b/src/common/kernel/item.h
index b67b792b5..82caba55f 100644
--- a/src/common/kernel/item.h
+++ b/src/common/kernel/item.h
@@ -53,22 +53,22 @@ typedef int (*rtype_uchange)(struct unit * user, const struct resource_type * rt
 typedef int (*rtype_uget)(const struct unit * user, const struct resource_type * rtype);
 typedef char * (*rtype_name)(const struct resource_type * rtype, int flags);
 typedef struct resource_type {
-	/* --- constants --- */
-	char * _name[2]; /* wie es hei�t */
-	char * _appearance[2]; /* wie es f�r andere aussieht */
-	unsigned int flags;
-	/* --- functions --- */
-	rtype_uchange uchange;
-	rtype_uget uget;
-	rtype_name name;
-	/* --- pointers --- */
-	struct attrib * attribs;
-	struct resource_type * next;
-	unsigned int hashkey;
-	struct item_type * itype;
-	struct potion_type * ptype;
-	struct luxury_type * ltype;
-	struct weapon_type * wtype;
+  /* --- constants --- */
+  char * _name[2]; /* wie es hei�t */
+  char * _appearance[2]; /* wie es f�r andere aussieht */
+  unsigned int flags;
+  /* --- functions --- */
+  rtype_uchange uchange;
+  rtype_uget uget;
+  rtype_name name;
+  /* --- pointers --- */
+  struct attrib * attribs;
+  struct resource_type * next;
+  unsigned int hashkey;
+  struct item_type * itype;
+  struct potion_type * ptype;
+  struct luxury_type * ltype;
+  struct weapon_type * wtype;
   struct armor_type * atype;
 } resource_type;
 extern resource_type * resourcetypes;
@@ -90,10 +90,10 @@ extern struct attrib_type at_resourcelimit;
 typedef int (*rlimit_limit)(const struct region * r, const struct resource_type * rtype);
 typedef void (*rlimit_produce)(struct region * r, const struct resource_type * rtype, int n);
 typedef struct resource_limit {
-	rlimit_limit limit;
-	rlimit_produce produce;
+  rlimit_limit limit;
+  rlimit_produce produce;
   unsigned int guard; /* how to guard against theft */
-	int value;
+  int value;
   resource_mod * modifiers;
 } resource_limit;
 
diff --git a/src/common/kernel/karma.c b/src/common/kernel/karma.c
index 23a8142f6..adaf50d6c 100644
--- a/src/common/kernel/karma.c
+++ b/src/common/kernel/karma.c
@@ -32,8 +32,9 @@
 #include "message.h"
 
 /* util includes */
-#include <attrib.h>
-#include <base36.h>
+#include <util/attrib.h>
+#include <util/base36.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <math.h>
@@ -561,7 +562,7 @@ jihad_attacks(void)
 
 	for(f=factions; f; f=f->next) if(fspecial(f, FS_JIHAD)) {
     region * last = lastregion(f);
-		for (r=firstregion(f); r != last; r = r->next) if (rand()%1000 <= 1) {
+		for (r=firstregion(f); r != last; r = r->next) if (rng_int()%1000 <= 1) {
 			boolean doit = false;
 
 			for(u=r->units; u; u=u->next) if(jihad(f, u->race)) {
diff --git a/src/common/kernel/magic.c b/src/common/kernel/magic.c
index 2c6f7ce33..7fd579887 100644
--- a/src/common/kernel/magic.c
+++ b/src/common/kernel/magic.c
@@ -54,6 +54,7 @@
 #include <util/attrib.h>
 #include <util/resolve.h>
 #include <util/rand.h>
+#include <util/rng.h>
 #include <util/base36.h>
 #include <util/event.h>
 
@@ -803,42 +804,40 @@ spl_costtyp(const spell * sp)
 int
 eff_spelllevel(unit *u, const spell * sp, int cast_level, int range)
 {
-	int k;
-	int maxlevel;
-	int needplevel;
-	int costtyp = SPC_FIX;
-
-	for (k = 0; sp->components[k].type; k++) {
-		if (cast_level == 0)
-			return 0;
-
-		if (sp->components[k].amount > 0) {
-			/* Die Kosten f�r Aura sind auch von der Zahl der bereits
-			 * gezauberten Spr�che abh�ngig */
-			if (sp->components[k].type == r_aura) {
-				needplevel = spellcost(u, sp) * range;
-			} else {
-				needplevel = sp->components[k].amount * range;
-			}
-			maxlevel = get_pooled(u, sp->components[k].type, GET_DEFAULT)/needplevel;
-
-			/* sind die Kosten fix, so muss die Komponente nur einmal vorhanden
-			 * sein und der cast_level �ndert sich nicht */
-			if (sp->components[k].cost == SPC_FIX) {
-				if (maxlevel < 1) cast_level = 0;
-			/* ansonsten wird das Minimum aus maximal m�glicher Stufe und der
-			 * gew�nschten gebildet */
-			} else if (sp->components[k].cost == SPC_LEVEL) {
-				costtyp = SPC_LEVEL;
-				cast_level = min(cast_level, maxlevel);
-			/* bei Typ Linear m�ssen die Kosten in H�he der Stufe vorhanden
-			 * sein, ansonsten schl�gt der Spruch fehl */
-			} else if (sp->components[k].cost == SPC_LINEAR) {
-				costtyp = SPC_LINEAR;
-				if (maxlevel < cast_level) cast_level = 0;
-			}
-		}
-	}
+  int k, maxlevel, needplevel;
+  int costtyp = SPC_FIX;
+  
+  for (k = 0; sp->components[k].type; k++) {
+    if (cast_level == 0)
+        return 0;
+    
+    if (sp->components[k].amount > 0) {
+      /* Die Kosten f�r Aura sind auch von der Zahl der bereits
+       * gezauberten Spr�che abh�ngig */
+      if (sp->components[k].type == r_aura) {
+        needplevel = spellcost(u, sp) * range;
+      } else {
+        needplevel = sp->components[k].amount * range;
+      }
+      maxlevel = get_pooled(u, sp->components[k].type, GET_DEFAULT, needplevel*cast_level)/needplevel;
+      
+      /* sind die Kosten fix, so muss die Komponente nur einmal vorhanden
+       * sein und der cast_level �ndert sich nicht */
+      if (sp->components[k].cost == SPC_FIX) {
+        if (maxlevel < 1) cast_level = 0;
+        /* ansonsten wird das Minimum aus maximal m�glicher Stufe und der
+         * gew�nschten gebildet */
+      } else if (sp->components[k].cost == SPC_LEVEL) {
+        costtyp = SPC_LEVEL;
+        cast_level = min(cast_level, maxlevel);
+        /* bei Typ Linear m�ssen die Kosten in H�he der Stufe vorhanden
+         * sein, ansonsten schl�gt der Spruch fehl */
+      } else if (sp->components[k].cost == SPC_LINEAR) {
+        costtyp = SPC_LINEAR;
+        if (maxlevel < cast_level) cast_level = 0;
+      }
+    }
+  }
 	/* Ein Spruch mit Fixkosten wird immer mit der Stufe des Spruchs und
 	 * nicht auf der Stufe des Magiers gezaubert */
 	if (costtyp == SPC_FIX) {
@@ -965,7 +964,7 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
         break;
       }
       
-      if (get_pooled(u, rtype, GET_DEFAULT) < itemanz) {
+      if (get_pooled(u, rtype, GET_DEFAULT, itemanz) < itemanz) {
         resource * res = malloc(sizeof(resource));
         res->number = itemanz;
         res->type = rtype;
@@ -1263,7 +1262,7 @@ fumble(region * r, unit * u, const spell * sp, int cast_grade)
 #endif
 		return false;
 	}
-	rnd = rand()%100;
+	rnd = rng_int()%100;
 
 #ifdef PATZERDEBUG
 	printf("%s: Zauber Stufe %d, Talent %d, Patzerchance %d, rand: %d\n",
@@ -1306,7 +1305,7 @@ do_fumble(castorder *co)
 
   ADDMSG(&u->faction->msgs, msg_message("patzer", "unit region spell",
     u, r, sp));
-  switch (rand() % 10) {
+  switch (rng_int() % 10) {
   case 0:
     /* wenn vorhanden spezieller Patzer, ansonsten nix */
     if (sp->patzer) sp->patzer(co);
@@ -1315,7 +1314,7 @@ do_fumble(castorder *co)
 
   case 1:
     /* Kr�te */
-    duration = rand()%level/2;
+    duration = rng_int()%level/2;
     if (duration<2) duration = 2;
     {
       /* one or two things will happen: the toad changes her race back,
@@ -1340,7 +1339,7 @@ do_fumble(castorder *co)
 
   case 2:
     /* tempor�rer Stufenverlust */
-    duration = max(rand()%level/2, 2);
+    duration = max(rng_int()%level/2, 2);
     effect.i = -(level/2);
     c = create_curse(u, &u->attribs, ct_find("skil"), level, duration,
       effect, 1);
@@ -1413,7 +1412,7 @@ regeneration(unit * u)
 	/* TODO (noch gibs keine)*/
 
 	/* W�rfeln */
-	aura = (rand() % d + rand() % d)/2 + 1;
+	aura = (rng_int() % d + rng_int() % d)/2 + 1;
 
 	aura = (int)(aura * MagicRegeneration());
 
diff --git a/src/common/kernel/movement.c b/src/common/kernel/movement.c
index 6570892d4..8ed53c550 100644
--- a/src/common/kernel/movement.c
+++ b/src/common/kernel/movement.c
@@ -51,12 +51,12 @@
 #include <util/goodies.h>
 #include <util/language.h>
 #include <util/rand.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <assert.h>
 #include <math.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 
 /* attributes includes */
@@ -479,7 +479,7 @@ do_maelstrom(region *r, unit *u)
 {
   int damage;
 
-  damage = rand()%150 - eff_skill(u, SK_SAILING, r)*5;
+  damage = rng_int()%150 - eff_skill(u, SK_SAILING, r)*5;
 
   if(damage <= 0) {
     ADDMSG(&u->faction->msgs, msg_message("entermaelstrom", 
@@ -721,7 +721,7 @@ drifting_ships(region * r)
 
       /* Auswahl einer Richtung: Zuerst auf Land, dann
       * zuf�llig. Falls unm�gliches Resultat: vergi� es. */
-      d_offset = rand() % MAXDIRECTIONS;
+      d_offset = rng_int() % MAXDIRECTIONS;
       for (d = 0; d != MAXDIRECTIONS; ++d) {
         region * rn = rconnect(r, (direction_t)((d + d_offset) % MAXDIRECTIONS));
         if (rn!=NULL && fval(rn->terrain, SAIL_INTO) && ship_allowed(sh, rn)) {
@@ -1107,7 +1107,7 @@ regain_orientation(region * r)
     cap = shipowner(sh);
     if (cap==NULL) continue;
 
-    if (!fval(r->terrain, SEA_REGION) || rand() % 10 >= storms[thismonth]) {
+    if (!fval(r->terrain, SEA_REGION) || rng_int() % 10 >= storms[thismonth]) {
       remove_curse(&sh->attribs, c);
       ADDMSG(&cap->faction->msgs, msg_message("shipnoconf", "ship", sh));
       continue;
@@ -1132,7 +1132,7 @@ next_region(unit * u, region * current, region * next)
   if (is_disoriented(u)) {
     direction_t d = reldirection(current, next);
     if (d<MAXDIRECTIONS) {
-      d = (direction_t)(((d+MAXDIRECTIONS-1)+rand()%3)%MAXDIRECTIONS);
+      d = (direction_t)(((d+MAXDIRECTIONS-1)+rng_int()%3)%MAXDIRECTIONS);
       next = rconnect(current, d);
     }
   }
@@ -1634,11 +1634,11 @@ sail(unit * u, order * ord, boolean move_on_land, region_list **routep)
       stormchance = stormyness / shipspeed(sh, u);
       if (check_leuchtturm(next_point, NULL)) stormchance /= 3;
 
-      if (rand()%10000 < stormchance && fval(current_point->terrain, SEA_REGION)) {
+      if (rng_int()%10000 < stormchance && fval(current_point->terrain, SEA_REGION)) {
         if (!is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) {
           region * rnext = NULL;
           boolean storm = true;
-          int d_offset = rand() % MAXDIRECTIONS;
+          int d_offset = rng_int() % MAXDIRECTIONS;
           direction_t d;
           /* Sturm nur, wenn n�chste Region Hochsee ist. */
           for (d=0;d!=MAXDIRECTIONS;++d) {
@@ -2144,7 +2144,7 @@ piracy_cmd(unit *u, struct order * ord)
             if (alliedunit(u, f, HELP_FIGHT)) continue;
             if (il == 0 || intlist_find(il, cap->faction->no)) {
               ++aff[dir].value;
-              if (rand() % aff[dir].value == 0) {
+              if (rng_int() % aff[dir].value == 0) {
                 aff[dir].target = f;
               }
             }
@@ -2157,7 +2157,7 @@ piracy_cmd(unit *u, struct order * ord)
 		}
 
 		if (saff != 0) {
-			saff = rand() % saff;
+			saff = rng_int() % saff;
 			for (dir=0; dir!=MAXDIRECTIONS; ++dir) {
 				if (saff!=aff[dir].value) break;
 				saff -= aff[dir].value;
diff --git a/src/common/kernel/names.c b/src/common/kernel/names.c
index 829fd803a..c0983c665 100644
--- a/src/common/kernel/names.c
+++ b/src/common/kernel/names.c
@@ -40,6 +40,7 @@
 /* util includes */
 #include <util/base36.h>
 #include <util/bsdstring.h>
+#include <util/rng.h>
 
 /* Untote */
 
@@ -119,10 +120,10 @@ untoten_name(const unit * u)
 
 	/* nur 50% aller Namen haben "Vor-Teil" */
 	u=u;
-	uv = rand() % (UNTOT_VOR * 2);
+	uv = rng_int() % (UNTOT_VOR * 2);
 
-	uu = rand() % UNTOT;
-	un = rand() % (UNTOT_NACH * (uv >= UNTOT_VOR ? 1 : 2));
+	uu = rng_int() % UNTOT;
+	un = rng_int() % (UNTOT_NACH * (uv >= UNTOT_VOR ? 1 : 2));
 	/* nur 50% aller Namen haben "Nach-Teil", wenn kein Vor-Teil */
 
 	if (uv < UNTOT_VOR) {
@@ -206,9 +207,9 @@ skeleton_name(const unit * u)
 	u=u;
 
 	/* nur 20% aller Namen haben "Vor-Teil" */
-	uv = rand() % (SKEL_VOR * 5);
-	uu = rand() % SKEL;
-	un = rand() % (SKEL_NACH * (uv >= SKEL_VOR ? 1 : 2));
+	uv = rng_int() % (SKEL_VOR * 5);
+	uu = rng_int() % SKEL;
+	un = rng_int() % (SKEL_NACH * (uv >= SKEL_VOR ? 1 : 2));
 
 	/* nur 50% aller Namen haben "Nach-Teil", wenn kein Vor-Teil */
 
@@ -289,9 +290,9 @@ zombie_name(const unit * u)
 	u=u;
 
 	/* nur 20% aller Namen haben "Vor-Teil" */
-	uv = rand() % (ZOM_VOR * 5);
-	uu = rand() % ZOM;
-	un = rand() % (ZOM_NACH * (uv >= ZOM_VOR ? 1 : 2));
+	uv = rng_int() % (ZOM_VOR * 5);
+	uu = rng_int() % ZOM;
+	un = rng_int() % (ZOM_NACH * (uv >= ZOM_VOR ? 1 : 2));
 
 	/* nur 50% aller Namen haben "Nach-Teil", wenn kein Vor-Teil */
 
@@ -374,9 +375,9 @@ ghoul_name(const unit * u)
 	u=u;
 
 	/* nur 20% aller Namen haben "Vor-Teil" */
-	uv = rand() % (GHOUL_VOR * 5);
-	uu = rand() % GHOUL;
-	un = rand() % (GHOUL_NACH * (uv >= GHOUL_VOR ? 1 : 4));
+	uv = rng_int() % (GHOUL_VOR * 5);
+	uu = rng_int() % GHOUL;
+	un = rng_int() % (GHOUL_NACH * (uv >= GHOUL_VOR ? 1 : 4));
 
 	/* nur 25% aller Namen haben "Nach-Teil", wenn kein Vor-Teil */
 
@@ -521,7 +522,7 @@ const char *
 drachen_name(const unit *u)
 {
 	static char name[NAMESIZE + 1];
-	int rnd = rand() % DTITEL;
+	int rnd = rng_int() % DTITEL;
 	const char *t = dtitel[0][rnd];
 	int anzahl = 1;
 
@@ -552,10 +553,10 @@ drachen_name(const unit *u)
 	} else {
 		char n[32];
 
-		strcpy(n, silbe1[rand() % SIL1]);
-		strcat(n, silbe2[rand() % SIL2]);
-		strcat(n, silbe3[rand() % SIL3]);
-		if (rand() % 5 > 2) {
+		strcpy(n, silbe1[rng_int() % SIL1]);
+		strcat(n, silbe2[rng_int() % SIL2]);
+		strcat(n, silbe3[rng_int() % SIL3]);
+		if (rng_int() % 5 > 2) {
 			sprintf(name, "%s, %s", n, t);	/* "Name, der Titel" */
 		} else {
 			strcpy(name, t);	/* "Der Titel Name" */
@@ -563,7 +564,7 @@ drachen_name(const unit *u)
 			strcat(name, " ");
 			strcat(name, n);
 		}
-		if (u && (rand() % 3 == 0)) {
+		if (u && (rng_int() % 3 == 0)) {
 			strcat(name, " von ");
 			strcat(name, rname(u->region, NULL));
 		}
@@ -630,15 +631,15 @@ dracoid_name(const unit *u)
 	u=u;
 	/* Wieviele Mittelteile? */
 
-	mid_syllabels = rand()%4;
+	mid_syllabels = rng_int()%4;
 
-	strcpy(name, drac_pre[rand()%DRAC_PRE]);
+	strcpy(name, drac_pre[rng_int()%DRAC_PRE]);
 	while(mid_syllabels > 0) {
 		mid_syllabels--;
-		if(rand()%10 < 4) strcat(name,"'");
-		strcat(name, drac_mid[rand()%DRAC_MID]);
+		if(rng_int()%10 < 4) strcat(name,"'");
+		strcat(name, drac_mid[rng_int()%DRAC_MID]);
 	}
-	strcat(name, drac_suf[rand()%DRAC_SUF]);
+	strcat(name, drac_suf[rng_int()%DRAC_SUF]);
 	return name;
 }
 
diff --git a/src/common/kernel/player.c b/src/common/kernel/player.c
index 5103031de..bce2704a3 100644
--- a/src/common/kernel/player.c
+++ b/src/common/kernel/player.c
@@ -13,10 +13,10 @@
 #include <config.h>
 #include "player.h"
 
-#include <goodies.h>
+#include <util/goodies.h>
+#include <util/rng.h>
 
 #include <string.h>
-#include <stdlib.h>
 #include <limits.h>
 
 #define PMAXHASH 1021
@@ -33,7 +33,7 @@ make_player(const struct faction * f)
 	player * p = calloc(sizeof(player), 1);
 	unsigned int hash;
 	
-	for (p->id = rand();;p->id++) {
+	for (p->id = rng_int();;p->id++) {
 		/* if there is a hashing conflict, resolve it */
 		player * pi = get_player(p->id);
 		if (pi) p->id++;
diff --git a/src/common/kernel/pool.c b/src/common/kernel/pool.c
index 5d84b2920..69210b311 100644
--- a/src/common/kernel/pool.c
+++ b/src/common/kernel/pool.c
@@ -166,7 +166,7 @@ new_set_resvalue(unit * u, const resource_type * rtype, int value)
 }
 
 int
-get_pooled(const unit * u, const resource_type * rtype, unsigned int mode)
+get_pooled(const unit * u, const resource_type * rtype, unsigned int mode, int count)
 {
   const faction * f = u->faction;
   unit *v;
@@ -186,7 +186,7 @@ get_pooled(const unit * u, const resource_type * rtype, unsigned int mode)
     else if (mode & GET_SLACK) use = slack;
   }
   if (rtype->flags & RTF_POOLED && mode & ~(GET_SLACK|GET_RESERVE)) {
-    for (v = r->units; v; v = v->next) if (u!=v) {
+    for (v = r->units; v && use<count; v = v->next) if (u!=v) {
       int mask;
 
       if (u==v) continue;
@@ -202,7 +202,7 @@ get_pooled(const unit * u, const resource_type * rtype, unsigned int mode)
       }
       else if (alliedunit(v, f, HELP_MONEY)) mask = (mode >> 6) & (GET_SLACK|GET_RESERVE);
       else continue;
-      use += get_pooled(v, rtype, mask);
+      use += get_pooled(v, rtype, mask, count-use);
     }
   }
   return use;
@@ -241,7 +241,7 @@ use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count)
   }
 
   if (rtype->flags & RTF_POOLED && mode & ~(GET_SLACK|GET_RESERVE)) {
-    for (v = r->units; v; v = v->next) if (u!=v) {
+    for (v = r->units; use>0 && v!=NULL; v = v->next) if (u!=v) {
       int mask;
       if (urace(v)->ec_flags & NOGIVE) continue;
       if (v->faction == f) {
diff --git a/src/common/kernel/pool.h b/src/common/kernel/pool.h
index 74ae04ca1..b9bbac38f 100644
--- a/src/common/kernel/pool.h
+++ b/src/common/kernel/pool.h
@@ -32,7 +32,7 @@ extern "C" {
 #define GET_DEFAULT (GET_RESERVE|GET_SLACK|GET_POOLED_SLACK)
 #define GET_ALL (GET_SLACK|GET_RESERVE|GET_POOLED_SLACK|GET_POOLED_RESERVE|GET_POOLED_FORCE)
 
-int get_pooled(const struct unit * u, const struct resource_type * res, unsigned int mode);
+int get_pooled(const struct unit * u, const struct resource_type * res, unsigned int mode, int count);
 int use_pooled(struct unit * u, const struct resource_type * res, unsigned int mode, int count);
 	/** use_pooled
 	 * verbraucht 'count' Objekte der resource 'itm'
diff --git a/src/common/kernel/race.c b/src/common/kernel/race.c
index 1ac7a7607..75f73b87c 100644
--- a/src/common/kernel/race.c
+++ b/src/common/kernel/race.c
@@ -43,8 +43,9 @@
 #include "unit.h"
 
 /* util includes */
-#include <attrib.h>
-#include <functions.h>
+#include <util/attrib.h>
+#include <util/functions.h>
+#include <util/rng.h>
 
 /* attrib includes */
 #include <attributes/raceprefix.h>
@@ -260,7 +261,7 @@ give_starting_equipment(struct unit *u)
     }
     break;
   case RC_CENTAUR:
-    rsethorses(r, 250+rand()%51+rand()%51);
+    rsethorses(r, 250+rng_int()%51+rng_int()%51);
     break;
   }
   u->hp = unit_max_hp(u);
@@ -331,7 +332,7 @@ default_spoil(const struct race * rc, int size)
 {
   item * itm = NULL;
 
-  if (rand()%100 < RACESPOILCHANCE) {
+  if (rng_int()%100 < RACESPOILCHANCE) {
     char spoilname[32];
     const item_type * itype;
 
diff --git a/src/common/kernel/region.c b/src/common/kernel/region.c
index 2f548a137..3de2be0ca 100644
--- a/src/common/kernel/region.c
+++ b/src/common/kernel/region.c
@@ -40,7 +40,8 @@
 #include "unit.h"
 
 /* util includes */
-#include <resolve.h>
+#include <util/resolve.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <assert.h>
@@ -48,7 +49,6 @@
 #include <limits.h>
 #include <rand.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 
 extern int dice_rand(const char *s);
@@ -777,21 +777,21 @@ makename(void)
 	nv = strlen(vokal);
 	ns = strlen(start);
 
-	for (s = rand() % 3 + 2; s > 0; s--) {
+	for (s = rng_int() % 3 + 2; s > 0; s--) {
 		if (x > 0) {
-			k = rand() % (int)nk;
+			k = rng_int() % (int)nk;
 			name[p] = kons[k];
 			p++;
 		} else {
-			k = rand() % (int)ns;
+			k = rng_int() % (int)ns;
 			name[p] = start[k];
 			p++;
 		}
-		v = rand() % (int)nv;
+		v = rng_int() % (int)nv;
 		name[p] = vokal[v];
 		p++;
-		if (rand() % 3 == 2 || s == 1) {
-			e = rand() % (int)ne;
+		if (rng_int() % 3 == 2 || s == 1) {
+			e = rng_int() % (int)ne;
 			name[p] = end[e];
 			p++;
 			x = 1;
@@ -815,7 +815,7 @@ setluxuries(region * r, const luxury_type * sale)
 	for (ltype=luxurytypes; ltype; ltype=ltype->next) {
 		struct demand * dmd = calloc(sizeof(struct demand), 1);
 		dmd->type = ltype;
-		if (ltype!=sale) dmd->value = 1 + rand() % 5;
+		if (ltype!=sale) dmd->value = 1 + rng_int() % 5;
 		dmd->next = r->land->demands;
 		r->land->demands = dmd;
 	}
@@ -917,12 +917,12 @@ terraform_region(region * r, const terrain_type * terrain)
 		if (!nb) {
 			int i = get_maxluxuries();
       if (i>0) {
-        i = rand() % i;
+        i = rng_int() % i;
         ltype = luxurytypes;
         while (i--) ltype=ltype->next; 
       }
 		} else {
-			int i = rand() % mnr;
+			int i = rng_int() % mnr;
 			struct surround * srd = nb;
 			while (i>srd->value) {
 				i-=srd->value;
@@ -947,19 +947,19 @@ terraform_region(region * r, const terrain_type * terrain)
     if (r->terrain->herbs) {
 			int len=0;
 			while (r->terrain->herbs[len]) ++len;
-			if (len) itype = r->terrain->herbs[rand()%len];
+			if (len) itype = r->terrain->herbs[rng_int()%len];
 		}
 		if (itype!=NULL) {
 			rsetherbtype(r, itype);
-			rsetherbs(r, (short)(50+rand()%31));
+			rsetherbs(r, (short)(50+rng_int()%31));
 		}
 		else {
 			rsetherbtype(r, NULL);
 		}
     if (oldterrain==NULL || !fval(oldterrain, LAND_REGION)) {
-      if (rand() % 100 < 3) fset(r, RF_MALLORN);
+      if (rng_int() % 100 < 3) fset(r, RF_MALLORN);
       else freset(r, RF_MALLORN);
-      if (rand() % 100 < ENCCHANCE) {
+      if (rng_int() % 100 < ENCCHANCE) {
         fset(r, RF_ENCOUNTER);
       }
     }
@@ -967,14 +967,14 @@ terraform_region(region * r, const terrain_type * terrain)
 
   if (oldterrain==NULL || terrain->size!=oldterrain->size) {
     if (terrain==newterrain(T_PLAIN)) {
-      rsethorses(r, rand() % (terrain->size / 50));
-      if(rand()%100 < 40) {
-        rsettrees(r, 2, terrain->size * (30+rand()%40)/1000);
+      rsethorses(r, rng_int() % (terrain->size / 50));
+      if(rng_int()%100 < 40) {
+        rsettrees(r, 2, terrain->size * (30+rng_int()%40)/1000);
         rsettrees(r, 1, rtrees(r, 2)/4);
         rsettrees(r, 0, rtrees(r, 2)/2);
       }
     } else if (chance(0.2)) {
-      rsettrees(r, 2, terrain->size * (30 + rand() % 40) / 1000);
+      rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000);
       rsettrees(r, 1, rtrees(r, 2)/4);
       rsettrees(r, 0, rtrees(r, 2)/2);
     }
@@ -983,7 +983,7 @@ terraform_region(region * r, const terrain_type * terrain)
 		  int peasants;
 		  peasants = (maxworkingpeasants(r) * (20+dice_rand("6d10")))/100;
 		  rsetpeasants(r, max(100, peasants));
-		  rsetmoney(r, rpeasants(r) * ((wage(r, NULL, NULL)+1) + rand() % 5));
+		  rsetmoney(r, rpeasants(r) * ((wage(r, NULL, NULL)+1) + rng_int() % 5));
     }
 	}
 }
diff --git a/src/common/kernel/reports.c b/src/common/kernel/reports.c
index 3742b9544..9e56c7889 100644
--- a/src/common/kernel/reports.c
+++ b/src/common/kernel/reports.c
@@ -913,62 +913,67 @@ spy_message(int spy, unit *u, unit *target)
 const struct unit *
 ucansee(const struct faction *f, const struct unit *u, const struct unit *x)
 {
-	if (cansee(f, u->region, u, 0)) return u;
-	return x;
+  if (cansee(f, u->region, u, 0)) return u;
+  return x;
 }
 
 static void
 get_addresses(report_context * ctx)
 {
 /* "TODO: travelthru" */
+  seen_region * sr = NULL;
   region *r;
   const faction * lastf = NULL;
   faction_list * flist = calloc(1, sizeof(faction_list));
+  
   flist->data = ctx->f;
 
-  for (r=ctx->first;r!=ctx->last;r=r->next) {
+  for (r=ctx->first;sr==NULL && r!=ctx->last;r=r->next) {
+    sr = find_seen(ctx->seen, r);
+  }
+  
+  for (;sr!=NULL;sr=sr->next) {
+    const region * r = sr->r;
     const unit * u = r->units;
-    const seen_region * sr = find_seen(ctx->seen, r);
-
-    if (sr==NULL) continue;
+    
     while (u!=NULL) {
-			faction * sf = visible_faction(ctx->f, u);
-			boolean ballied = sf && sf!=ctx->f && sf!=lastf
-				&& !fval(u, UFL_PARTEITARNUNG) && cansee(ctx->f, r, u, 0);
-			if (ballied || ALLIED(ctx->f, sf)) {
-				faction_list ** fnew = &flist;
-				while (*fnew && (*fnew)->data->no < sf->no) {
-					fnew =&(*fnew)->next;
-				}
-				if ((*fnew==NULL) || (*fnew)->data!=sf) {
-					faction_list * finsert = malloc(sizeof(faction_list));
-					finsert->next = *fnew;
-					*fnew = finsert;
-					finsert->data = sf;
-				}
-				lastf = sf;
-			}
-			u = u->next;
-		}
-	}
-
+      faction * sf = visible_faction(ctx->f, u);
+      boolean ballied = sf && sf!=ctx->f && sf!=lastf
+          && !fval(u, UFL_PARTEITARNUNG) && cansee(ctx->f, r, u, 0);
+      if (ballied || ALLIED(ctx->f, sf)) {
+        faction_list ** fnew = &flist;
+        while (*fnew && (*fnew)->data->no < sf->no) {
+          fnew =&(*fnew)->next;
+        }
+        if ((*fnew==NULL) || (*fnew)->data!=sf) {
+          faction_list * finsert = malloc(sizeof(faction_list));
+          finsert->next = *fnew;
+          *fnew = finsert;
+          finsert->data = sf;
+        }
+        lastf = sf;
+      }
+      u = u->next;
+    }
+  }
+  
   if (ctx->f->alliance != NULL) {
-		faction *f2;
-		for(f2 = factions; f2; f2 = f2->next) {
-			if(f2->alliance != NULL && f2->alliance == ctx->f->alliance) {
-				faction_list ** fnew = &flist;
-				while (*fnew && (*fnew)->data->no < f2->no) {
-					fnew =&(*fnew)->next;
-				}
-				if ((*fnew==NULL) || (*fnew)->data!=f2) {
-					faction_list * finsert = malloc(sizeof(faction_list));
-					finsert->next = *fnew;
-					*fnew = finsert;
-					finsert->data = f2;
-				}
-			}
-		}
-	}
+    faction *f2;
+    for(f2 = factions; f2; f2 = f2->next) {
+      if(f2->alliance != NULL && f2->alliance == ctx->f->alliance) {
+        faction_list ** fnew = &flist;
+        while (*fnew && (*fnew)->data->no < f2->no) {
+          fnew =&(*fnew)->next;
+        }
+        if ((*fnew==NULL) || (*fnew)->data!=f2) {
+          faction_list * finsert = malloc(sizeof(faction_list));
+          finsert->next = *fnew;
+          *fnew = finsert;
+          finsert->data = f2;
+        }
+      }
+    }
+  }
   ctx->addresses = flist;
 }
 
@@ -1006,6 +1011,30 @@ free_seen(void)
   }
 }
 
+void
+link_seen(seen_region * seehash[], const region * first, const region * last)
+{
+  const region * r = first;
+  seen_region * sr = NULL;
+
+  if (first==last) return;
+
+  do {
+    sr = find_seen(seehash, r);
+    r = r->next;
+  } while (sr==NULL && r!=last);
+
+  while (r!=last) {
+    seen_region * sn = find_seen(seehash, r);
+    if (sn!=NULL) {
+      sr->next = sn;
+      sr = sn;
+    }
+    r = r->next;
+  }
+  sr->next = 0;
+}
+
 seen_region *
 find_seen(struct seen_region * seehash[], const region * r)
 {
@@ -1036,6 +1065,7 @@ get_seen_interval(report_context * ctx)
       sr = sr->nextHash;
     }
   }
+  link_seen(ctx->seen, ctx->first, ctx->last);
 }
 
 boolean
@@ -1059,10 +1089,10 @@ add_seen(struct seen_region * seehash[], struct region * r, unsigned char mode,
 }
 
 typedef struct report_type {
-	struct report_type * next;
-	report_fun write;
-	const char * extension;
-	int flag;
+  struct report_type * next;
+  report_fun write;
+  const char * extension;
+  int flag;
 } report_type;
 
 static report_type * report_types;
diff --git a/src/common/kernel/reports.h b/src/common/kernel/reports.h
index a36df2c87..63caade55 100644
--- a/src/common/kernel/reports.h
+++ b/src/common/kernel/reports.h
@@ -59,17 +59,18 @@ int hat_in_region(item_t itm, struct region * r, struct faction * f);
 /* f�r fast_region und neuen CR: */
 
 enum {
-	see_none,
-	see_neighbour,
-	see_lighthouse,
-	see_travel,
-	see_far,
-	see_unit,
-	see_battle
+  see_none,
+  see_neighbour,
+  see_lighthouse,
+  see_travel,
+  see_far,
+  see_unit,
+  see_battle
 };
 
 typedef struct seen_region {
   struct seen_region * nextHash;
+  struct seen_region * next;
   struct region *r;
   unsigned char mode;
   boolean disbelieves;
@@ -80,14 +81,15 @@ extern boolean add_seen(struct seen_region * seehash[], struct region * r, unsig
 extern struct seen_region ** seen_init(void);
 extern void seen_done(struct seen_region * seehash[]);
 extern void free_seen(void);
+extern void link_seen(seen_region * seehash[], const struct region * first, const struct region * last);
 extern const char * visibility[];
 
 typedef struct report_context {
-	struct faction * f;
-	struct faction_list * addresses;
-	struct seen_region ** seen;
+  struct faction * f;
+  struct faction_list * addresses;
+  struct seen_region ** seen;
   struct region * first, * last;
-	void * userdata;
+  void * userdata;
   time_t report_time;
 } report_context;
 
diff --git a/src/common/kernel/resources.c b/src/common/kernel/resources.c
index 2dca79513..b06a91d97 100644
--- a/src/common/kernel/resources.c
+++ b/src/common/kernel/resources.c
@@ -21,6 +21,7 @@
 #include "terrain.h"
 
 #include <util/rand.h>
+#include <util/rng.h>
 
 #include <stdlib.h>
 #include <assert.h>
@@ -97,7 +98,7 @@ static void
 terraform_default(struct rawmaterial * res, const region * r)
 {
 #define SHIFT 70
-	double modifier = 1.0 + ((rand() % (SHIFT*2+1)) - SHIFT) * ((rand() % (SHIFT*2+1)) - SHIFT) / 10000.0;
+	double modifier = 1.0 + ((rng_int() % (SHIFT*2+1)) - SHIFT) * ((rng_int() % (SHIFT*2+1)) - SHIFT) / 10000.0;
 	res->amount = (int)(res->amount*modifier); /* random adjustment, +/- 91% */
 	if (res->amount<1) res->amount=1;
 	unused(r);
@@ -108,7 +109,7 @@ static void
 resource_random_change(int *pvalue, boolean used)
 {
 	int split = 5;
-	int rnd = rand()%100;
+	int rnd = rng_int()%100;
 
 	if (pvalue==0 || rnd %10 >= 10) return;
 	if (used) split = 4;
@@ -147,7 +148,7 @@ use_default(rawmaterial *res, const region * r, int amount)
   assert(res->amount>0 && amount>=0 && amount <= res->amount);
   res->amount-=amount;
   while (res->amount==0) {
-    double modifier = 1.0 + ((rand() % (SHIFT*2+1)) - SHIFT) * ((rand() % (SHIFT*2+1)) - SHIFT) / 10000.0;
+    double modifier = 1.0 + ((rng_int() % (SHIFT*2+1)) - SHIFT) * ((rng_int() % (SHIFT*2+1)) - SHIFT) / 10000.0;
     int i;
 
     for (i=0;r->terrain->production[i].type;++i) {
diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c
index 9b781fb05..3c9555ef4 100644
--- a/src/common/kernel/save.c
+++ b/src/common/kernel/save.c
@@ -52,14 +52,15 @@
 #include <attributes/key.h>
 
 /* util includes */
-#include <attrib.h>
-#include <base36.h>
-#include <event.h>
+#include <util/attrib.h>
+#include <util/base36.h>
+#include <util/event.h>
 #include <util/goodies.h>
-#include <resolve.h>
-#include <sql.h>
-#include <rand.h>
-#include <umlaut.h>
+#include <util/resolve.h>
+#include <util/sql.h>
+#include <util/rand.h>
+#include <util/rng.h>
+#include <util/umlaut.h>
 
 /* libc includes */
 #include <string.h>
@@ -1505,7 +1506,7 @@ readfaction(FILE * F)
   if (global.data_version >= OVERRIDE_VERSION) {
     rds(F, &f->override);
   } else {
-    f->override = strdup(itoa36(rand()));
+    f->override = strdup(itoa36(rng_int()));
   }
 
   if (global.data_version < LOCALE_VERSION) {
diff --git a/src/common/kernel/skill.c b/src/common/kernel/skill.c
index c0346aad1..e70f5129c 100644
--- a/src/common/kernel/skill.c
+++ b/src/common/kernel/skill.c
@@ -35,6 +35,7 @@
 
 #include <util/attrib.h>
 #include <util/goodies.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <assert.h>
@@ -302,7 +303,7 @@ skill_weeks(int level)
 	int coins = 2*level;
 	int heads = 1;
 	while (coins--) {
-		heads += rand() % 2;
+		heads += rng_int() % 2;
 	}
 	return heads;
 }
diff --git a/src/common/kernel/teleport.c b/src/common/kernel/teleport.c
index e1f7f482a..f1dccdd2d 100644
--- a/src/common/kernel/teleport.c
+++ b/src/common/kernel/teleport.c
@@ -33,11 +33,11 @@
 #include "plane.h"
 
 /* util includes */
-#include <log.h>
+#include <util/log.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <assert.h>
-#include <stdlib.h>
 
 #define TE_CENTER_X 1000
 #define TE_CENTER_Y 1000
@@ -142,7 +142,7 @@ spawn_braineaters(float chance)
 {
   region *r;
   faction *f0 = findfaction(MONSTER_FACTION);
-  int next = rand() % (int)(chance*100);
+  int next = rng_int() % (int)(chance*100);
   
   if (f0==NULL) return;
 
@@ -151,13 +151,13 @@ spawn_braineaters(float chance)
 
     /* Neues Monster ? */
     if (next-- == 0) {
-      unit *u = createunit(r, f0, 1+rand()%10+rand()%10, new_race[RC_HIRNTOETER]);
+      unit *u = createunit(r, f0, 1+rng_int()%10+rng_int()%10, new_race[RC_HIRNTOETER]);
 
       set_string(&u->name, "Hirnt�ter");
       set_string(&u->display, "Wabernde gr�ne Schwaden treiben durch den Nebel und verdichten sich zu einer unheimlichen Kreatur, die nur aus einem langen Ruderschwanz und einem riesigen runden Maul zu bestehen scheint.");
       set_level(u, SK_STEALTH, 1);
       set_level(u, SK_OBSERVATION, 1);
-      next = rand() % (int)(chance*100);
+      next = rng_int() % (int)(chance*100);
     }
   }
 }
diff --git a/src/common/kernel/unit.c b/src/common/kernel/unit.c
index 539e93c94..8a826f51e 100644
--- a/src/common/kernel/unit.c
+++ b/src/common/kernel/unit.c
@@ -46,12 +46,12 @@
 #include <util/event.h>
 #include <util/goodies.h>
 #include <util/resolve.h>
+#include <util/rng.h>
 #include <util/variant.h>
 
 /* libc includes */
 #include <assert.h>
 #include <limits.h>
-#include <stdlib.h>
 #include <string.h>
 #include <math.h>
 
@@ -227,7 +227,7 @@ destroy_unit(unit * u)
 	 * Items haben, sonst Memory-Leak. */
 	
 	clone = has_clone(u);
-	if (clone && rand()%100 < 90) {
+	if (clone && rng_int()%100 < 90) {
 		attrib *a;
 		int i;
 
@@ -955,7 +955,7 @@ boolean
 learn_skill(unit * u, skill_t sk, double chance)
 {
 	skill * sv = u->skills;
-	if (chance < 1.0 && rand()%10000>=chance*10000) return false;
+	if (chance < 1.0 && rng_int()%10000>=chance*10000) return false;
 	while (sv != u->skills + u->skill_size) {
 		assert (sv->weeks>0);
 		if (sv->id == sk) {
diff --git a/src/common/kernel/unit.h b/src/common/kernel/unit.h
index fb1bfc215..879f3cf47 100644
--- a/src/common/kernel/unit.h
+++ b/src/common/kernel/unit.h
@@ -29,7 +29,7 @@ extern "C" {
 #endif
 
 struct skill;
-
+struct item;
 #define UFL_DEBUG         (1<<0)
 #define UFL_ISNEW         (1<<1)	/* 2 */
 #define UFL_LONGACTION    (1<<2)	/* 4 */
diff --git a/src/common/modules/arena.c b/src/common/modules/arena.c
index eca6abc6b..898bb75d4 100644
--- a/src/common/modules/arena.c
+++ b/src/common/modules/arena.c
@@ -46,11 +46,12 @@
 #include <kernel/unit.h>
 
 /* util include */
-#include <base36.h>
-#include <resolve.h>
-#include <functions.h>
-#include <event.h>
-#include <goodies.h>
+#include <util/base36.h>
+#include <util/event.h>
+#include <util/functions.h>
+#include <util/goodies.h>
+#include <util/resolve.h>
+#include <util/rng.h>
 
 /* libc include */
 #include <assert.h>
@@ -110,22 +111,22 @@ enter_fail(unit * u) {
 static int
 enter_arena(unit * u, const item_type * itype, int amount, order * ord)
 {
-	skill_t sk;
-	region * r = u->region;
-	unit * u2;
-	int fee = u->faction->score / 5;
-	unused(ord);
-	unused(amount);
-	unused(itype);
-	if (fee>2000) fee = 2000;
-	if (getplane(r)==arena) return -1;
-	if (u->number!=1 && enter_fail(u)) return -1;
-	if (get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT) < fee && enter_fail(u)) return -1;
-	for (sk=0;sk!=MAXSKILLS;++sk) {
-		if (get_level(u, sk)>1 && enter_fail(u)) return -1;
-	}
-	for (u2=r->units;u2;u2=u2->next) if (u2->faction==u->faction) break;
-
+  skill_t sk;
+  region * r = u->region;
+  unit * u2;
+  int fee = u->faction->score / 5;
+  unused(ord);
+  unused(amount);
+  unused(itype);
+  if (fee>2000) fee = 2000;
+  if (getplane(r)==arena) return -1;
+  if (u->number!=1 && enter_fail(u)) return -1;
+  if (get_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT, fee) < fee && enter_fail(u)) return -1;
+  for (sk=0;sk!=MAXSKILLS;++sk) {
+    if (get_level(u, sk)>1 && enter_fail(u)) return -1;
+  }
+  for (u2=r->units;u2;u2=u2->next) if (u2->faction==u->faction) break;
+  
   assert(!"not implemented");
 /*
 	for (res=0;res!=MAXRESOURCES;++res) if (res!=R_SILVER && res!=R_ARENA_GATE && (is_item(res) || is_herb(res) || is_potion(res))) {
@@ -139,18 +140,18 @@ enter_arena(unit * u, const item_type * itype, int amount, order * ord)
 		}
 	}
 */
-	if (get_money(u) > fee) {
-		if (u2) change_money(u2, get_money(u) - fee);
-		else if (enter_fail(u)) return -1;
-	}
-	sprintf(buf, "In %s �ffnet sich ein Portal. Eine Stimme ert�nt, und spricht: 'Willkommen in der Ebene der Herausforderung'. %s durchschreitet das Tor zu einer anderen Welt.", regionname(u->region, u->faction), unitname(u));
-	addmessage(NULL, u->faction, buf, MSG_MESSAGE, ML_IMPORTANT);
-	use_pooled(u, itype->rtype, GET_SLACK|GET_RESERVE, 1);
+  if (get_money(u) > fee) {
+    if (u2) change_money(u2, get_money(u) - fee);
+    else if (enter_fail(u)) return -1;
+  }
+  sprintf(buf, "In %s �ffnet sich ein Portal. Eine Stimme ert�nt, und spricht: 'Willkommen in der Ebene der Herausforderung'. %s durchschreitet das Tor zu einer anderen Welt.", regionname(u->region, u->faction), unitname(u));
+  addmessage(NULL, u->faction, buf, MSG_MESSAGE, ML_IMPORTANT);
+  use_pooled(u, itype->rtype, GET_SLACK|GET_RESERVE, 1);
   use_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT, fee);
   set_money(u, 109);
-	fset(u, UFL_PARTEITARNUNG);
-	move_unit(u, start_region[rand() % 6], NULL);
-	return 0;
+  fset(u, UFL_PARTEITARNUNG);
+  move_unit(u, start_region[rng_int() % 6], NULL);
+  return 0;
 }
 
 /***
@@ -169,7 +170,7 @@ use_wand_of_tears(unit * user, const struct item_type * itype, int amount, order
 				int i;
 
 				for (i=0;i!=u->skill_size;++i) {
-					if (rand()%3) reduce_skill(u, u->skills+i, 1);
+					if (rng_int()%3) reduce_skill(u, u->skills+i, 1);
 				}
 				ADDMSG(&u->faction->msgs, msg_message("wand_of_tears_effect",
 					"unit", u));
@@ -301,8 +302,8 @@ guardian_faction(plane * pl, int id)
 	if (!f) {
 		f = calloc(1, sizeof(faction));
 		f->banner = strdup("Sie dienen dem gro�en Wyrm");
-		f->passw = strdup(itoa36(rand()));
-		f->override = strdup(itoa36(rand()));
+		f->passw = strdup(itoa36(rng_int()));
+		f->override = strdup(itoa36(rng_int()));
     set_email(&f->email, "igjarjuk@eressea.de");
 		f->name = strdup("Igjarjuks Kundschafter");
 		f->race = new_race[RC_ILLUSION];
diff --git a/src/common/modules/autoseed.c b/src/common/modules/autoseed.c
index 47d2a32cd..8bf848883 100644
--- a/src/common/modules/autoseed.c
+++ b/src/common/modules/autoseed.c
@@ -27,8 +27,8 @@
 
 /* util includes */
 #include <util/base36.h>
-#include <util/sql.h>
 #include <util/goodies.h>
+#include <util/rng.h>
 #include <util/sql.h>
 
 /* libc includes */
@@ -51,7 +51,7 @@ random_terrain(boolean distribution)
     }
   }
 
-  n = rand() % (distribution?ndistribution:nterrains);
+  n = rng_int() % (distribution?ndistribution:nterrains);
   for (terrain=terrains();terrain;terrain=terrain->next) {
     n -= distribution?terrain->distribution:1;
     if (n<0) break;
@@ -152,7 +152,7 @@ fix_demand(region *r)
     for (i=maxlux;i!=2;++i) {
       int j;
       do {
-        int k = rand() % maxluxuries;
+        int k = rng_int() % maxluxuries;
         mlux[i] = ltypes[k];
         for (j=0;j!=i;++j) {
           if (mlux[j]==mlux[i]) break;
@@ -166,7 +166,7 @@ fix_demand(region *r)
     if (!fval(r, RF_CHAOTIC)) {
       log_warning(("fixing demand in %s\n", regionname(r, NULL)));
     }
-    sale = mlux[rand() % maxlux];
+    sale = mlux[rng_int() % maxlux];
     if (sale) setluxuries(r, sale);
   }
   while (rlist) {
@@ -200,8 +200,8 @@ read_newfactions(const char * filename)
     sscanf(buf, "%s %s %s %d %d %s %d", email, race, lang, &bonus, &subscription, password, &alliance);
     if (email[0]=='\0') break;
     if (password[0]=='\0') {
-      strcpy(password, itoa36(rand()));
-      strcat(password, itoa36(rand()));
+      strcpy(password, itoa36(rng_int()));
+      strcat(password, itoa36(rng_int()));
     }
     for (f=factions;f;f=f->next) {
       if (strcmp(f->email, email)==0 && f->subscription && f->age<MINAGE_MULTI) break;
@@ -578,7 +578,7 @@ autoseed(newfaction ** players, int nsize, boolean new_island)
   }
 
   while (rsize && (nsize || isize>=REGIONS_PER_FACTION)) {
-    int i = rand() % rsize;
+    int i = rng_int() % rsize;
     region_list ** rnext = &rlist;
     region_list * rfind;
     direction_t d;
@@ -602,9 +602,9 @@ autoseed(newfaction ** players, int nsize, boolean new_island)
         ++rsize;
       }
     }
-    if (volcano_terrain!=NULL && (rand() % VOLCANO_CHANCE == 0)) {
+    if (volcano_terrain!=NULL && (rng_int() % VOLCANO_CHANCE == 0)) {
       terraform_region(r, volcano_terrain);
-    } else if (nsize && (rand() % isize == 0 || rsize==0)) {
+    } else if (nsize && (rng_int() % isize == 0 || rsize==0)) {
       newfaction ** nfp, * nextf = *players;
       faction * f;
       unit * u;
@@ -692,7 +692,7 @@ autoseed(newfaction ** players, int nsize, boolean new_island)
           if (rn==NULL) {
             const struct terrain_type * terrain = newterrain(T_OCEAN);
             rn = new_region(r->x + delta_x[d], r->y + delta_y[d]);
-            if (rand() % SPECIALCHANCE < special) {
+            if (rng_int() % SPECIALCHANCE < special) {
               terrain = random_terrain(true);
               special = SPECIALCHANCE / 3; /* 33% chance auf noch eines */
             } else {
@@ -700,9 +700,9 @@ autoseed(newfaction ** players, int nsize, boolean new_island)
             }
 						terraform_region(rn, terrain);
             /* the new region has an extra 15% chance to have laen */
-            if (rand() % 100 < 15) rsetlaen(r, 5 + rand() % 5);
+            if (rng_int() % 100 < 15) rsetlaen(r, 5 + rng_int() % 5);
             /* the new region has an extra 20% chance to have mallorn */
-            if (rand() % 100 < 20) fset(r, RF_MALLORN);
+            if (rng_int() % 100 < 20) fset(r, RF_MALLORN);
             add_regionlist(rend, rn);
           }
         }
diff --git a/src/common/modules/dungeon.c b/src/common/modules/dungeon.c
index d53901b15..9039ee6ac 100644
--- a/src/common/modules/dungeon.c
+++ b/src/common/modules/dungeon.c
@@ -106,7 +106,7 @@ make_dungeon(const dungeon * data)
 	add_regionlist(&rlist, center);
 	rnext = r = center;
 	while (size>0 && iterations--) {
-		int d, o = rand() % 3;
+		int d, o = rng_int() % 3;
 		for (d=0;d!=3;++d) {
 			int index = (d+o) % 3;
 			region * rn = findregion(r->x+nb[n][index][0], r->y+nb[n][index][1]);
@@ -115,7 +115,7 @@ make_dungeon(const dungeon * data)
 				if (rn->terrain==terrain_hell) {
           rnext = rn;
         } else if (fval(rn->terrain, SEA_REGION)) {
-					if (rand() % 100 < data->connect*100) {
+					if (rng_int() % 100 < data->connect*100) {
 						terraform_region(rn, terrain_hell);
 						--size;
 						rnext = rn;
@@ -143,11 +143,11 @@ make_dungeon(const dungeon * data)
 		monster * m = data->monsters;
 		region * r = iregion->data;
 		while (m) {
-			if ((rand() % 100) < (m->chance * 100)) {
+			if ((rng_int() % 100) < (m->chance * 100)) {
 				/* TODO: check maxunits. */
 				treasure * loot = m->treasures;
 				struct itemtype_list * weapon = m->weapons;
-				int size = 1 + (rand() % m->avgsize) + (rand() % m->avgsize);
+				int size = 1 + (rng_int() % m->avgsize) + (rng_int() % m->avgsize);
 				unit * u = createunit(r, fmonsters, size, m->race);
 				while (weapon) {
 					i_change(&u->items, weapon->type, size);
diff --git a/src/common/modules/gmcmd.c b/src/common/modules/gmcmd.c
index 41d0759df..11b544561 100644
--- a/src/common/modules/gmcmd.c
+++ b/src/common/modules/gmcmd.c
@@ -40,6 +40,7 @@
 #include <util/event.h>
 #include <util/goodies.h>
 #include <util/umlaut.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <stdlib.h>
@@ -628,9 +629,9 @@ gm_addquest(const char * email, const char * name, short radius, unsigned int fl
 	/* GM faction */
 	a_add(&f->attribs, make_key(atoi36("quest")));
 	f->banner = strdup("Questenpartei");
-	f->passw = strdup(itoa36(rand()));
-	f->override = strdup(itoa36(rand()));
-	f->override = strdup(itoa36(rand()));
+	f->passw = strdup(itoa36(rng_int()));
+	f->override = strdup(itoa36(rng_int()));
+	f->override = strdup(itoa36(rng_int()));
   if (set_email(&f->email, email)!=0) {
     log_error(("Invalid email address for faction %s: %s\n", itoa36(f->no), email));
   }
@@ -655,8 +656,8 @@ gm_addquest(const char * email, const char * name, short radius, unsigned int fl
 
 	/* GM playfield */
 	do {
-		minx = (short)((rand() % (2*EXTENSION)) - EXTENSION);
-		miny = (short)((rand() % (2*EXTENSION)) - EXTENSION);
+		minx = (short)((rng_int() % (2*EXTENSION)) - EXTENSION);
+		miny = (short)((rng_int() % (2*EXTENSION)) - EXTENSION);
 		for (x=0;!invalid && x<=radius*2;++x) {
       short y;
 			for (y=0;!invalid && y<=radius*2;++y) {
@@ -667,7 +668,7 @@ gm_addquest(const char * email, const char * name, short radius, unsigned int fl
 	} while (invalid);
 	maxx = minx+2*radius; cx = minx+radius;
 	maxy = miny+2*radius; cy = miny+radius;
-	p = create_new_plane(rand(), name, minx, maxx, miny, maxy, flags);
+	p = create_new_plane(rng_int(), name, minx, maxx, miny, maxy, flags);
 	center = new_region(cx, cy);
 	for (x=0;x<=2*radius;++x) {
 		short y;
@@ -735,7 +736,7 @@ gm_addfaction(const char * email, plane * p, region * r)
 	/* GM faction */
 	add_key(&f->attribs, atoi36("quest"));
 	f->banner = strdup("Questenpartei");
-	f->passw = strdup(itoa36(rand()));
+	f->passw = strdup(itoa36(rng_int()));
   if (set_email(&f->email, email)!=0) {
     log_error(("Invalid email address for faction %s: %s\n", itoa36(f->no), email));
   }
@@ -798,8 +799,8 @@ gm_addplane(short radius, unsigned int flags, const char * name)
 
 	/* GM playfield */
 	do {
-		minx = (short)(rand() % (2*EXTENSION)) - EXTENSION;
-		miny = (short)(rand() % (2*EXTENSION)) - EXTENSION;
+		minx = (short)(rng_int() % (2*EXTENSION)) - EXTENSION;
+		miny = (short)(rng_int() % (2*EXTENSION)) - EXTENSION;
 		for (x=0;!invalid && x<=radius*2;++x) {
       short y;
 			for (y=0;!invalid && y<=radius*2;++y) {
@@ -810,7 +811,7 @@ gm_addplane(short radius, unsigned int flags, const char * name)
 	} while (invalid);
 	maxx = minx+2*radius; cx = minx+radius;
 	maxy = miny+2*radius; cy = miny+radius;
-	p = create_new_plane(rand(), name, minx, maxx, miny, maxy, flags);
+	p = create_new_plane(rng_int(), name, minx, maxx, miny, maxy, flags);
 	center = new_region(cx, cy);
 	for (x=0;x<=2*radius;++x) {
 		short y;
diff --git a/src/common/modules/weather.c b/src/common/modules/weather.c
index 902f45de1..426354138 100644
--- a/src/common/modules/weather.c
+++ b/src/common/modules/weather.c
@@ -42,12 +42,12 @@ create_weather(region *r, weather_t type)
 	w->center[0] = r->x;
 	w->center[1] = r->y;
 	w->type      = type;
-	w->move[0]   = (rand()%3) - 1;
-	w->move[1]   = (rand()%3) - 1;
+	w->move[0]   = (rng_int()%3) - 1;
+	w->move[1]   = (rng_int()%3) - 1;
 
 	switch(type) {
 	case WEATHER_STORM:
-		w->radius = rand()%2+1;
+		w->radius = rng_int()%2+1;
 		break;
 	case WEATHER_HURRICANE:
 		w->radius = 1;
@@ -128,7 +128,7 @@ move_weather(void)
 		w->center[0] = w->center[0] + w->move[0];
 		w->center[1] = w->center[1] + w->move[1];
 		r = findregion(w->center[0], w->center[1]);
-		if(!r || rand()%100 < 5) {
+		if(!r || rng_int()%100 < 5) {
 			removelist(&weathers, w);
 		}
 		w = wnext;
diff --git a/src/common/modules/wormhole.c b/src/common/modules/wormhole.c
index 16cb37448..b272e1790 100644
--- a/src/common/modules/wormhole.c
+++ b/src/common/modules/wormhole.c
@@ -26,6 +26,7 @@
 
 /* util includes */
 #include <util/attrib.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <assert.h>
@@ -159,7 +160,7 @@ create_wormholes(void)
    * select a list of regions. we'll sort them by age later.
    */
   while (r!=NULL) {
-    int next = rand() % (2*WORMHOLE_CHANCE);
+    int next = rng_int() % (2*WORMHOLE_CHANCE);
     while (r!=NULL && (next!=0 || !good_region(r))) {
       if (good_region(r)) {
         --next;
diff --git a/src/common/races/dragons.c b/src/common/races/dragons.c
index a27692c56..ad3a9a39d 100644
--- a/src/common/races/dragons.c
+++ b/src/common/races/dragons.c
@@ -20,8 +20,8 @@
 #include <region.h>
 #include <unit.h>
 
-/* libc includes */
-#include <stdlib.h>
+/* util includes */
+#include <util/rng.h>
 
 #define age_chance(a,b,p) (max(0,a-b)*p)
 
@@ -31,7 +31,7 @@
 void
 age_firedragon(unit *u)
 {
-	if (rand()%100 < age_chance(u->age, DRAGONAGE, 1)) {
+	if (rng_int()%100 < age_chance(u->age, DRAGONAGE, 1)) {
 		double q = (double) u->hp / (double) (unit_max_hp(u) * u->number);
 		u->race = new_race[RC_DRAGON];
 		u->irace = new_race[RC_DRAGON];
@@ -43,7 +43,7 @@ age_firedragon(unit *u)
 void
 age_dragon(unit *u)
 {
-	if (rand()%100 < age_chance(u->age, WYRMAGE, 1)) {
+	if (rng_int()%100 < age_chance(u->age, WYRMAGE, 1)) {
 		double q = (double) u->hp / (double) (unit_max_hp(u) * u->number);
 		u->race = new_race[RC_WYRM];
 		u->irace = new_race[RC_WYRM];
diff --git a/src/common/races/zombies.c b/src/common/races/zombies.c
index 956554650..c14f02837 100644
--- a/src/common/races/zombies.c
+++ b/src/common/races/zombies.c
@@ -17,16 +17,19 @@
 #include "zombies.h"
 
 /* kernel includes */
-#include <unit.h>
-#include <faction.h>
-#include <region.h>
+#include <kernel/unit.h>
+#include <kernel/faction.h>
+#include <kernel/region.h>
+
+/* util iclude */
+#include <util/rng.h>
 
 /* libc includes */
 #include <stdlib.h>
 
 #define UNDEAD_MIN                  90	/* mind. zahl vor weg gehen */
 #define UNDEAD_BREAKUP              25	/* chance dafuer */
-#define UNDEAD_BREAKUP_FRACTION     (25+rand()%70)	/* anteil der weg geht */
+#define UNDEAD_BREAKUP_FRACTION     (25+rng_int()%70)	/* anteil der weg geht */
 
 #define age_chance(a,b,p) (max(0,a-b)*p)
 
@@ -45,14 +48,14 @@ age_undead(unit *u)
 			for (m=0;m!=100;++m) {
 				int d = k/(100-m);
 				k-=d;
-				if (rand() % 100 < UNDEAD_REPRODUCTION)
+				if (rng_int() % 100 < UNDEAD_REPRODUCTION)
 					n+=d;
 			}
 			assert(k==0);
 		} else
 #endif
 		for (m = u->number; m; m--)
-			if (rand() % 100 < UNDEAD_REPRODUCTION)
+			if (rng_int() % 100 < UNDEAD_REPRODUCTION)
 				n++;
 		set_number(u, u->number + n);
 		u->hp += n * unit_max_hp(u);
@@ -65,13 +68,13 @@ age_undead(unit *u)
 	 * absplitten, anstatt sich zu vermehren. monster
 	 * untote vermehren sich nur noch */
 
-	if (u->number > UNDEAD_MIN && u->faction->no != MONSTER_FACTION && rand() % 100 < UNDEAD_BREAKUP) {
+	if (u->number > UNDEAD_MIN && u->faction->no != MONSTER_FACTION && rng_int() % 100 < UNDEAD_BREAKUP) {
 		int m;
 		unit *u2;
 
 		n = 0;
 		for (m = u->number; m; m--)
-			if (rand() % 100 < UNDEAD_BREAKUP_FRACTION)
+			if (rng_int() % 100 < UNDEAD_BREAKUP_FRACTION)
 				n++;
 		u2 = create_unit(r, findfaction(MONSTER_FACTION), 0, new_race[RC_UNDEAD], 0, NULL, u);
     make_undead_unit(u2);
@@ -82,7 +85,7 @@ age_undead(unit *u)
 void
 age_skeleton(unit *u)
 {
-	if (u->faction->no == 0 && rand()%100 < age_chance(u->age, 27, 1)) {
+	if (u->faction->no == 0 && rng_int()%100 < age_chance(u->age, 27, 1)) {
 		int n = max(1,u->number/2);
 		double q = (double) u->hp / (double) (unit_max_hp(u) * u->number);
 		u->race = new_race[RC_SKELETON_LORD];
@@ -95,7 +98,7 @@ age_skeleton(unit *u)
 void
 age_zombie(unit *u)
 {
-	if (u->faction->no == 0 && rand()%100 < age_chance(u->age, 27, 1)) {
+	if (u->faction->no == 0 && rng_int()%100 < age_chance(u->age, 27, 1)) {
 		int n = max(1,u->number/2);
 		double q = (double) u->hp / (double) (unit_max_hp(u) * u->number);
 		u->race = new_race[RC_ZOMBIE_LORD];
@@ -108,7 +111,7 @@ age_zombie(unit *u)
 void
 age_ghoul(unit *u)
 {
-	if (u->faction->no == 0 && rand()%100 < age_chance(u->age, 27, 1)) {
+	if (u->faction->no == 0 && rng_int()%100 < age_chance(u->age, 27, 1)) {
 		int n = max(1,u->number/2);
 		double q = (double) u->hp / (double) (unit_max_hp(u) * u->number);
 		u->race = new_race[RC_GHOUL_LORD];
diff --git a/src/common/spells/combatspells.c b/src/common/spells/combatspells.c
index 4c5dcbde6..c8655b2a1 100644
--- a/src/common/spells/combatspells.c
+++ b/src/common/spells/combatspells.c
@@ -31,12 +31,12 @@
 #include <kernel/skill.h>
 
 /* util includes */
-#include <rand.h>
-#include <base36.h>
+#include <util/base36.h>
+#include <util/rand.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <assert.h>
-#include <stdlib.h>
 
 #define EFFECT_HEALING_SPELL     5
 
@@ -426,7 +426,7 @@ select_ally_in_row(fighter * af, int minrow, int maxrow)
 
 	if (!allies)
 		return dt;
-	allies = rand() % allies;
+	allies = rng_int() % allies;
 
 	cv_foreach(df, b->fighters) {
 		side *ds = df->side;
@@ -501,7 +501,7 @@ random_skill(unit *u)
 	if(n == 0)
 		return NOSKILL;
 
-	n = rand()%n;
+	n = rng_int()%n;
 
   for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
 		if (sv->level>0) {
@@ -548,7 +548,7 @@ sp_mindblast(fighter * fi, int level, double power, spell * sp)
       sk = random_skill(du);
       if (sk != NOSKILL) {
         skill * sv = get_skill(du, sk);
-        int n = 1 + rand() % 3;
+        int n = 1 + rng_int() % 3;
         /* Skill abziehen */
         reduce_skill(du, sv, n);
       } else {
@@ -755,7 +755,7 @@ sp_shadowcall(fighter * fi, int level, double power, spell * sp)
 	int force = (int)(get_force(power, 3)/2);
 	unit *u;
   const char * races[3] = { "shadowbat", "nightmare", "vampunicorn" };
-  const race *rc = rc_find(races[rand()%3]);
+  const race *rc = rc_find(races[rng_int()%3]);
 
 	unused(sp);
 
@@ -928,7 +928,7 @@ sp_chaosrow(fighter * fi, int level, double power, spell * sp)
       if (df->unit->race->battle_flags & BF_NOBLOCK) {
         df->side->nonblockers[row] -= df->alive;
       }
-      row = FIRST_ROW + (rand()%(LAST_ROW-FIRST_ROW));
+      row = FIRST_ROW + (rng_int()%(LAST_ROW-FIRST_ROW));
       switch (row) {
         case FIGHT_ROW:
           df->status = ST_FIGHT;
diff --git a/src/common/spells/spells.c b/src/common/spells/spells.c
index 177c17775..37560096b 100644
--- a/src/common/spells/spells.c
+++ b/src/common/spells/spells.c
@@ -65,13 +65,13 @@ extern void ct_register(const struct curse_type * ct);
 #include <util/variant.h>
 #include <util/goodies.h>
 #include <util/resolve.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <assert.h>
 #include <ctype.h>
 #include <math.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #include <limits.h>
 
@@ -134,7 +134,7 @@ magicanalyse_region(region *r, unit *mage, double force)
     /* ist der curse schw�cher als der Analysezauber, so ergibt sich
      * mehr als 100% probability und damit immer ein Erfolg. */
     probability = curse_chance(c, force);
-    mon = c->duration + (rand()%10) - 5;
+    mon = c->duration + (rng_int()%10) - 5;
     mon = max(1, mon);
     found = true;
 
@@ -176,7 +176,7 @@ magicanalyse_unit(unit *u, unit *mage, double force)
     /* ist der curse schw�cher als der Analysezauber, so ergibt sich
      * mehr als 100% probability und damit immer ein Erfolg. */
     probability = curse_chance(c, force);
-    mon = c->duration + (rand()%10) - 5;
+    mon = c->duration + (rng_int()%10) - 5;
     mon = max(1,mon);
 
     if (chance(probability)) { /* Analyse gegl�ckt */
@@ -218,7 +218,7 @@ magicanalyse_building(building *b, unit *mage, double force)
     /* ist der curse schw�cher als der Analysezauber, so ergibt sich
      * mehr als 100% probability und damit immer ein Erfolg. */
     probability = curse_chance(c, force);
-    mon = c->duration + (rand()%10) - 5;
+    mon = c->duration + (rng_int()%10) - 5;
     mon = max(1,mon);
 
     if (chance(probability)) { /* Analyse gegl�ckt */
@@ -260,7 +260,7 @@ magicanalyse_ship(ship *sh, unit *mage, double force)
     /* ist der curse schw�cher als der Analysezauber, so ergibt sich
      * mehr als 100% probability und damit immer ein Erfolg. */
     probability = curse_chance(c, force);
-    mon = c->duration + (rand()%10) - 5;
+    mon = c->duration + (rng_int()%10) - 5;
     mon = max(1,mon);
 
     if (chance(probability)) { /* Analyse gegl�ckt */
@@ -478,7 +478,7 @@ static const race *
 select_familiar(const race * magerace, magic_t magiegebiet)
 {
   const race * retval = NULL;
-  int rnd = rand()%100;
+  int rnd = rng_int()%100;
 
   assert(magerace->familiars[0]);
   if (rnd < 3) {
@@ -486,7 +486,7 @@ select_familiar(const race * magerace, magic_t magiegebiet)
     unsigned int maxlen = listlen(familiarraces);
     if (maxlen>0) {
       race_list * rclist = familiarraces;
-      int index = rand()%maxlen;
+      int index = rng_int()%maxlen;
       while (index-->0) {
         rclist = rclist->next;
       }
@@ -562,7 +562,7 @@ sp_summon_familiar(castorder *co)
     }
 
     /* In welcher benachbarten Ozeanregion soll der Familiar erscheinen? */
-    coasts = rand()%coasts;
+    coasts = rng_int()%coasts;
     dh = -1;
     for(d=0; d<MAXDIRECTIONS; d++) {
       region * rn = rconnect(r,d);
@@ -1294,7 +1294,7 @@ sp_rosthauch(castorder *co)
 #endif
   }
 
-  force = rand()%((int)(force * 10)) + force;
+  force = rng_int()%((int)(force * 10)) + force;
 
   /* fuer jede Einheit */
   for (n = 0; n < pa->length; n++) {
@@ -1448,7 +1448,7 @@ sp_sparkle(castorder *co)
   if(pa->param[0]->flag == TARGET_RESISTS) return cast_level;
 
   u = pa->param[0]->data.u;
-  effect.i = rand();
+  effect.i = rng_int();
   create_curse(mage, &u->attribs, ct_find("sparkle"), cast_level,
       duration, effect, u->number);
 
@@ -1645,7 +1645,7 @@ sp_great_drought(castorder *co)
   create_curse(mage, &r->attribs, ct_find("drought"), force, duration, effect, 0);
 
   /* terraforming */
-  if (rand() % 100 < 25){
+  if (rng_int() % 100 < 25){
     terraform = true;
 
     switch(rterrain(r)) {
@@ -1665,7 +1665,7 @@ sp_great_drought(castorder *co)
         break;
 */
       case T_GLACIER:
-        if (rand() % 100 < 50){
+        if (rng_int() % 100 < 50){
           rsetterrain(r, T_SWAMP);
           destroy_all_roads(r);
         } else {   /* Ozean */
@@ -2414,7 +2414,7 @@ patzer_peasantmob(castorder *co)
     faction * f = findfaction(MONSTER_FACTION);
     const struct locale * lang = f->locale;
 
-    anteil += rand() % 4;
+    anteil += rng_int() % 4;
     n = rpeasants(r) * anteil / 10;
     rsetpeasants(r, rpeasants(r) - n);
     assert(rpeasants(r) >= 0);
@@ -2474,7 +2474,7 @@ sp_forest_fire(castorder *co)
   unit *mage = co->magician.u;
   int cast_level = co->level;
   double probability;
-  double percentage = (rand() % 8 + 1) * 0.1;  /* 10 - 80% */
+  double percentage = (rng_int() % 8 + 1) * 0.1;  /* 10 - 80% */
 
   int vernichtet_schoesslinge = (int)(rtrees(r, 1) * percentage);
   int destroyed = (int)(rtrees(r, 2) * percentage);
@@ -2578,7 +2578,7 @@ sp_fumblecurse(castorder *co)
 
   target = pa->param[0]->data.u;
 
-  rx = rand()%3;
+  rx = rng_int()%3;
   sx = cast_level - effskill(target, SK_MAGIC);
   duration = max(sx, rx) + 1;
 
@@ -2660,8 +2660,8 @@ sp_summondragon(castorder *co)
   }
 
   for(time = 1; time < 7; time++){
-    if (rand()%100 < 25){
-      switch(rand()%3){
+    if (rng_int()%100 < 25){
+      switch(rng_int()%3){
       case 0:
         race = new_race[RC_WYRM];
         number = 1;
@@ -3007,7 +3007,7 @@ wisps_move(const border * b, struct unit * u, struct region * from, struct regio
     /* pick left and right region: */
     region * rl = rconnect(from, (direction_t)((reldir+MAXDIRECTIONS-1)%MAXDIRECTIONS));
     region * rr = rconnect(from, (direction_t)((reldir+1)%MAXDIRECTIONS));
-    int j = rand() % 3;
+    int j = rng_int() % 3;
     if (j==1 && rl && fval(rl->terrain, LAND_REGION)==fval(next, LAND_REGION)) return rl;
     if (j==2 && rr && fval(rr->terrain, LAND_REGION)==fval(next, LAND_REGION)) return rr;
   }
@@ -3318,7 +3318,7 @@ patzer_deathcloud(castorder *co)
   unit *mage = co->magician.u;
   int hp = (mage->hp - 2);
 
-  change_hitpoints(mage, -rand()%hp);
+  change_hitpoints(mage, -rng_int()%hp);
 
   ADDMSG(&mage->faction->msgs, msg_message(
     "magic_fumble", "unit region command",
@@ -3953,7 +3953,7 @@ sp_charmingsong(castorder *co)
     return 0;
   }
 
-  duration = 3 + rand()%(int)force;
+  duration = 3 + rng_int()%(int)force;
   {
     trigger * trestore = trigger_changefaction(target, target->faction);
     /* l�uft die Dauer ab, setze Partei zur�ck */
@@ -4137,7 +4137,7 @@ sp_raisepeasantmob(castorder *co)
   double force = co->force;
   int duration = (int)force+1;
 
-  anteil.i = 6 + (rand()%4);
+  anteil.i = 6 + (rng_int()%4);
 
   n = rpeasants(r) * anteil.i / 10;
   n = max(0, n);
@@ -4609,7 +4609,7 @@ sp_seduce(castorder *co)
     item * itm = *itmp;
     loot = itm->number/2;
     if (itm->number % 2) {
-      loot += rand() % 2;
+      loot += rng_int() % 2;
     }
     if (loot > 0) {
       loot = (int)min(loot, force * 5);
@@ -4730,7 +4730,7 @@ sp_headache(castorder *co)
   }
   if (smax!=NULL) {
     /* wirkt auf maximal 10 Personen */
-    int change = min(10, target->number) * (rand()%2+1) / target->number;
+    int change = min(10, target->number) * (rng_int()%2+1) / target->number;
     reduce_skill(target, smax, change);
   }
   set_order(&target->thisorder, NULL);
@@ -4991,9 +4991,9 @@ sp_icastle(castorder *co)
 
   /* Gr��e festlegen. */
   if (type == bt_find("illusion")) {
-    b->size = (rand()%(int)((power*power)+1)*10);
+    b->size = (rng_int()%(int)((power*power)+1)*10);
   } else if (type->maxsize == -1) {
-    b->size = ((rand()%(int)(power))+1)*5;
+    b->size = ((rng_int()%(int)(power))+1)*5;
   } else {
     b->size = type->maxsize;
   }
@@ -5005,7 +5005,7 @@ sp_icastle(castorder *co)
   data = (icastle_data*)a->data.v;
   data->type = type;
   data->building = b;
-  data->time = 2+(rand()%(int)(power)+1)*(rand()%(int)(power)+1);
+  data->time = 2+(rng_int()%(int)(power)+1)*(rng_int()%(int)(power)+1);
 
   if(mage->region == r) {
     leave(r, mage);
@@ -5211,7 +5211,7 @@ sp_baddreams(castorder *co)
   /* wirkt erst in der Folgerunde, soll mindestens eine Runde wirken,
    * also duration+2 */
   duration = (int)max(1, power/2); /* Stufe 1 macht sonst mist */
-  duration = 2 + rand()%duration;
+  duration = 2 + rng_int()%duration;
 
   /* Nichts machen als ein entsprechendes Attribut in die Region legen. */
   effect.i = -1;
@@ -5252,7 +5252,7 @@ sp_gooddreams(castorder *co)
   /* wirkt erst in der Folgerunde, soll mindestens eine Runde wirken,
    * also duration+2 */
   duration = (int)max(1, power/2); /* Stufe 1 macht sonst mist */
-  duration = 2 + rand()%duration;
+  duration = 2 + rng_int()%duration;
   effect.i = 1;
   c = create_curse(mage, &r->attribs, ct_find("gbdream"), power, duration, effect, 0);
   curse_setflag(c, CURSE_ISNEW);
@@ -6304,7 +6304,7 @@ sp_disruptastral(castorder *co)
         if (u->race != new_race[RC_SPELL]) {
           region_list *trl2 = trl;
           region *tr;
-          int c = rand() % inhab_regions;
+          int c = rng_int() % inhab_regions;
 
           /* Zuf�llige Zielregion suchen */
           while (c--!=0) trl2 = trl2->next;
@@ -6507,7 +6507,7 @@ sp_movecastle(castorder *co)
   bunhash(b);
   translist(&r->buildings, &target_region->buildings, b);
   b->region = target_region;
-  b->size -= b->size/(10-rand()%6);
+  b->size -= b->size/(10-rng_int()%6);
   bhash(b);
 
   for(u=r->units;u;) {
@@ -6642,7 +6642,7 @@ sp_stealaura(castorder *co)
     return 0;
   }
 
-  taura = (get_mage(u)->spellpoints*(rand()%(int)(3*power)+1))/100;
+  taura = (get_mage(u)->spellpoints*(rng_int()%(int)(3*power)+1))/100;
 
   if(taura > 0) {
     get_mage(u)->spellpoints -= taura;
@@ -6725,7 +6725,7 @@ sp_antimagiczone(castorder *co)
  *
  * Wirkung:
  *   Gibt Geb�uden einen Bonus auf Magieresistenz von +20%. Der Zauber
- *   dauert 3+rand()%Level Wochen an, also im Extremfall bis zu 2 Jahre
+ *   dauert 3+rng_int()%Level Wochen an, also im Extremfall bis zu 2 Jahre
  *   bei Stufe 20
  *
  *   Es k�nnen mehrere Zauber �bereinander gelegt werden, der Effekt
@@ -6734,7 +6734,7 @@ sp_antimagiczone(castorder *co)
  * oder:
  *
  *   Gibt Schiffen einen Bonus auf Magieresistenz von +20%. Der Zauber
- *   dauert 3+rand()%Level Wochen an, also im Extremfall bis zu 2 Jahre
+ *   dauert 3+rng_int()%Level Wochen an, also im Extremfall bis zu 2 Jahre
  *   bei Stufe 20
  *
  *   Es k�nnen mehrere Zauber �bereinander gelegt werden, der Effekt
@@ -6759,7 +6759,7 @@ sp_magicrunes(castorder *co)
   spellparameter *pa = co->par;
   variant effect;
 
-  duration = 3 + rand()%cast_level;
+  duration = 3 + rng_int()%cast_level;
   effect.i = 20;
 
   switch(pa->param[0]->typ){
@@ -7116,7 +7116,7 @@ sp_wdwpyramid(castorder *co)
 
     assert(mindist >= 1);
 
-    minshowdist = mindist - rand()%5;
+    minshowdist = mindist - rng_int()%5;
     maxshowdist = minshowdist + 4;
 
     ADDMSG(&mage->faction->msgs, msg_message("wdw_pyramidspell_notfound",
diff --git a/src/common/util/Jamfile b/src/common/util/Jamfile
index 6d30d656f..26cc6f234 100644
--- a/src/common/util/Jamfile
+++ b/src/common/util/Jamfile
@@ -37,6 +37,8 @@ SOURCES =
  xml.c
  ;
 
+SOURCES += mt19937ar.c  ;
+
 if $(MSPACES) {
  SOURCES += <dl>malloc.c ;
 }
diff --git a/src/common/util/cvector.c b/src/common/util/cvector.c
index 500f8d0de..bbf037883 100644
--- a/src/common/util/cvector.c
+++ b/src/common/util/cvector.c
@@ -19,12 +19,13 @@
  * permission from the authors.
  */
 
+#include <config.h>
+#include "cvector.h"
+#include "rng.h"
+
 #include <stdlib.h>
 #include <assert.h>
 #include <limits.h>
-#include <config.h>
-#include "cvector.h"
-#include "memory.h"
 
 void
 cv_init(cvector * cv)
@@ -114,7 +115,7 @@ __cv_scramble(void *v1, size_t n, size_t width)
 		v = (void *) realloc(v, s);
 	}
 	for (i = 0; i != n; i++) {
-		*(long *) addptr(v, i * (width + 4)) = rand();
+		*(long *) addptr(v, i * (width + 4)) = rng_int();
 		memcpy(addptr(v, i * (width + 4) + 4), addptr(v1, i * width), width);
 	}
 
diff --git a/src/common/util/dice.c b/src/common/util/dice.c
index b1d82396c..4050f3aba 100644
--- a/src/common/util/dice.c
+++ b/src/common/util/dice.c
@@ -18,6 +18,7 @@
  */
 
 #include <config.h>
+#include "rng.h"
 
 #include <assert.h>
 #include <stdlib.h>
@@ -33,10 +34,10 @@ dice(int count, int value)
   if (value<=0) return 0; /* (enno) %0 geht nicht. echt wahr. */
   if (count >= 0)
     for (c = count; c > 0; c--)
-      d += rand() % value + 1;
+      d += rng_int() % value + 1;
   else
     for (c = count; c < 0; c++)
-      d -= rand() % value + 1;
+      d -= rng_int() % value + 1;
 
   return d;
 }
@@ -58,7 +59,7 @@ term_eval(const char **sptr)
       else if (state==2) { /* dDk */
         int i;
         if (k == 0) k = 6; /* 3d == 3d6 */
-        for (i=0;i!=d;++i) m += (1 + rand() % k)*multi;
+        for (i=0;i!=d;++i) m += (1 + rng_int() % k)*multi;
       }
       else assert(!"dice_rand: illegal token");
       if (*c=='*') {
diff --git a/src/common/util/mt19937ar.c b/src/common/util/mt19937ar.c
new file mode 100644
index 000000000..4fbd3f70d
--- /dev/null
+++ b/src/common/util/mt19937ar.c
@@ -0,0 +1,172 @@
+/* 
+   A C-program for MT19937, with initialization improved 2002/1/26.
+   Coded by Takuji Nishimura and Makoto Matsumoto.
+
+   Before using, initialize the state by using init_genrand(seed)  
+   or init_by_array(init_key, key_length).
+
+   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+   All rights reserved.                          
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+     1. Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+
+     2. Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+     3. The names of its contributors may not be used to endorse or promote 
+        products derived from this software without specific prior written 
+        permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+   Any feedback is very welcome.
+   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
+*/
+
+#include <stdio.h>
+
+/* Period parameters */  
+#define N 624
+#define M 397
+#define MATRIX_A 0x9908b0dfUL   /* constant vector a */
+#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
+#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
+
+static unsigned long mt[N]; /* the array for the state vector  */
+static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
+
+/* initializes mt[N] with a seed */
+void init_genrand(unsigned long s)
+{
+    mt[0]= s & 0xffffffffUL;
+    for (mti=1; mti<N; mti++) {
+        mt[mti] = 
+	    (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); 
+        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
+        /* In the previous versions, MSBs of the seed affect   */
+        /* only MSBs of the array mt[].                        */
+        /* 2002/01/09 modified by Makoto Matsumoto             */
+        mt[mti] &= 0xffffffffUL;
+        /* for >32 bit machines */
+    }
+}
+
+/* initialize by an array with array-length */
+/* init_key is the array for initializing keys */
+/* key_length is its length */
+/* slight change for C++, 2004/2/26 */
+void init_by_array(unsigned long init_key[], int key_length)
+{
+    int i, j, k;
+    init_genrand(19650218UL);
+    i=1; j=0;
+    k = (N>key_length ? N : key_length);
+    for (; k; k--) {
+        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+          + init_key[j] + j; /* non linear */
+        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+        i++; j++;
+        if (i>=N) { mt[0] = mt[N-1]; i=1; }
+        if (j>=key_length) j=0;
+    }
+    for (k=N-1; k; k--) {
+        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
+          - i; /* non linear */
+        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+        i++;
+        if (i>=N) { mt[0] = mt[N-1]; i=1; }
+    }
+
+    mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 
+}
+
+/* generates a random number on [0,0xffffffff]-interval */
+unsigned long genrand_int32(void)
+{
+    unsigned long y;
+    static unsigned long mag01[2]={0x0UL, MATRIX_A};
+    /* mag01[x] = x * MATRIX_A  for x=0,1 */
+
+    if (mti >= N) { /* generate N words at one time */
+        int kk;
+
+        if (mti == N+1)   /* if init_genrand() has not been called, */
+            init_genrand(5489UL); /* a default initial seed is used */
+
+        for (kk=0;kk<N-M;kk++) {
+            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+            mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
+        }
+        for (;kk<N-1;kk++) {
+            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+            mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
+        }
+        y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
+        mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
+
+        mti = 0;
+    }
+  
+    y = mt[mti++];
+
+    /* Tempering */
+    y ^= (y >> 11);
+    y ^= (y << 7) & 0x9d2c5680UL;
+    y ^= (y << 15) & 0xefc60000UL;
+    y ^= (y >> 18);
+
+    return y;
+}
+
+/* generates a random number on [0,0x7fffffff]-interval */
+long genrand_int31(void)
+{
+    return (long)(genrand_int32()>>1);
+}
+
+/* generates a random number on [0,1]-real-interval */
+double genrand_real1(void)
+{
+    return genrand_int32()*(1.0/4294967295.0); 
+    /* divided by 2^32-1 */ 
+}
+
+/* generates a random number on [0,1)-real-interval */
+double genrand_real2(void)
+{
+    return genrand_int32()*(1.0/4294967296.0); 
+    /* divided by 2^32 */
+}
+
+/* generates a random number on (0,1)-real-interval */
+double genrand_real3(void)
+{
+    return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); 
+    /* divided by 2^32 */
+}
+
+/* generates a random number on [0,1) with 53-bit resolution*/
+double genrand_res53(void) 
+{ 
+    unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; 
+    return(a*67108864.0+b)*(1.0/9007199254740992.0); 
+} 
+/* These real versions are due to Isaku Wada, 2002/01/09 added */
diff --git a/src/common/util/rand.c b/src/common/util/rand.c
index eec3b3372..4ef75e534 100644
--- a/src/common/util/rand.c
+++ b/src/common/util/rand.c
@@ -21,15 +21,14 @@
 
 #include <config.h>
 #include "rand.h"
+#include "rng.h"
 
-#include <stdlib.h>
 #include <assert.h>
 #include <string.h>
 #include <math.h>
 #include <float.h>
 #include <ctype.h>
 
-#define drand() ((rand()%RAND_MAX)/(double)RAND_MAX)
 #define M_PIl   3.1415926535897932384626433832795029L  /* pi */
 
 /* NormalRand aus python, random.py geklaut, dort ist Referenz auf
@@ -40,8 +39,8 @@ normalvariate(double mu, double sigma)
   static double NV_MAGICCONST = 1.7155277699214135;
   double z;
   for (;;) {
-    double u1 = drand();
-    double u2 = 1.0 - drand();
+    double u1 = rng_double();
+    double u2 = 1.0 - rng_double();
     z = NV_MAGICCONST*(u1-0.5)/u2;
     if (z*z/4.0 <= -log(u2)) {
       break;
@@ -57,7 +56,7 @@ ntimespprob(int n, double p, double mod)
   int i;
 
   for(i=0; i<n && p>0; i++) {
-    if(drand() < p) {
+    if(rng_double() < p) {
       count++;
       p += mod;
     }
@@ -69,6 +68,6 @@ boolean
 chance(double x)
 {
   if (x>=1.0) return true;
-  return (boolean) (rand() % RAND_MAX < RAND_MAX * x);
+  return rng_double() < x;
 }
 
diff --git a/src/common/util/rng.h b/src/common/util/rng.h
new file mode 100644
index 000000000..7dbc81039
--- /dev/null
+++ b/src/common/util/rng.h
@@ -0,0 +1,45 @@
+/* vi: set ts=2:
+ * +-------------------+  Christian Schlittchen <corwin@amber.kn-bremen.de>
+ * |                   |  Enno Rehling <enno@eressea.de>
+ * | Eressea PBEM host |  Katja Zedel <katze@felidae.kn-bremen.de>
+ * | (c) 1998 - 2005   |  
+ * |                   |  This program may not be used, modified or distributed
+ * +-------------------+  without prior permission by the authors of Eressea.
+ *  
+ */
+#ifndef UTIL_RNG_H
+#define UTIL_RNG_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RNG_MT
+
+#ifdef RNG_MT  
+  /* initializes mt[N] with a seed */
+  extern void init_genrand(unsigned long s);
+
+  /* generates a random number on [0,0xffffffff]-interval */
+  extern unsigned long genrand_int32(void);
+  
+  /* generates a random number on [0,1]-real-interval */
+  extern double genrand_real1(void);
+
+  /* generates a random number on [0,0x7fffffff]-interval */
+  long genrand_int31(void);
+
+# define rng_init(seed) init_genrand(seed)
+# define rng_int() genrand_int31()
+# define rng_double() genrand_real1() 
+# define RNG_RAND_MAX 0x7fffffff
+#else
+# include <stdlib.h>
+# define rng_init(seed) srand(seed)
+# define rng_int() rand()
+# define rng_double() ((rand()%RAND_MAX)/(double)RAND_MAX)
+# define RNG_RAND_MAX RAND_MAX
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/eressea/lua/eressea.cpp b/src/eressea/lua/eressea.cpp
index 37b9695a4..e21cf5c22 100644
--- a/src/eressea/lua/eressea.cpp
+++ b/src/eressea/lua/eressea.cpp
@@ -35,6 +35,7 @@
 #include <util/language.h>
 #include <util/base36.h>
 #include <util/rand.h>
+#include <util/rng.h>
 
 #include <cstring>
 #include <ctime>
@@ -154,8 +155,8 @@ lua_planmonsters(void)
   faction * f = findfaction(MONSTER_FACTION);
 
   if (f==NULL) return;
-  if (turn == 0) srand((int)time(0));
-  else srand(turn);
+  if (turn == 0) rng_init((int)time(0));
+  else rng_init(turn);
   plan_monsters();
   for (u=f->units;u;u=u->nextF) {
     call_script(u);
diff --git a/src/eressea/main.c b/src/eressea/main.c
index ed38261f9..67c2192fd 100644
--- a/src/eressea/main.c
+++ b/src/eressea/main.c
@@ -83,16 +83,16 @@
 #include <kernel/item.h>
 
 /* util includes */
-#include <rand.h>
+#include <util/rand.h>
+#include <util/rng.h>
 #include <util/xml.h>
 #include <util/goodies.h>
-#include <log.h>
-#include <sql.h>
-#include <base36.h>
+#include <util/log.h>
+#include <util/sql.h>
+#include <util/base36.h>
 
 /* libc includes */
 #include <stdio.h>
-#include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
 #include <time.h>
@@ -244,8 +244,8 @@ processturn(char *filename)
   newfaction * players;
 	int i;
 
-  if (turn == 0) srand((int)time(0));
-  else srand(turn);
+  if (turn == 0) rng_init((int)time(0));
+  else rng_init(turn);
 
 #ifdef SHORTPWDS
   readshortpwds("passwords");
@@ -254,8 +254,8 @@ processturn(char *filename)
 	turn++;
 	if ((i=readorders(filename))!=0) return i;
   if (!nomonsters) {
-    if (turn == 0) srand((int)time(0));
-    else srand(turn);
+    if (turn == 0) rng_init((int)time(0));
+    else rng_init(turn);
     puts(" - Monster KI...");
     plan_monsters();
   }
@@ -604,8 +604,8 @@ main(int argc, char *argv[])
 		return crwritemap("world.cr"); 
 	}
 
-  if (turn == 0) srand((int)time(0));
-  else srand(turn);
+  if (turn == 0) rng_init((int)time(0));
+  else rng_init(turn);
 
 
 	if ((i = processturn(orders))!=0) {
diff --git a/src/eressea/server.cpp b/src/eressea/server.cpp
index cdb11ed9d..e3810c628 100644
--- a/src/eressea/server.cpp
+++ b/src/eressea/server.cpp
@@ -87,6 +87,7 @@
 #include <util/goodies.h>
 #include <util/log.h>
 #include <util/rand.h>
+#include <util/rng.h>
 #include <util/sql.h>
 #ifdef MSPACES
 # include <util/dl/malloc.h>
@@ -106,7 +107,6 @@
 
 /* libc includes */
 #include <cstdio>
-#include <cstdlib>
 #include <cctype>
 #include <cstring>
 #include <ctime>
@@ -332,8 +332,8 @@ lua_done(lua_State * luaState)
 int
 process_orders()
 {
-  if (turn == 0) srand((int)time(0));
-  else srand(turn);
+  if (turn == 0) rng_init((int)time(0));
+  else rng_init(turn);
 
 #ifdef SHORTPWDS
   readshortpwds("passwords");
diff --git a/src/mapper/map_modify.c b/src/mapper/map_modify.c
index 150913a4a..e2143fded 100644
--- a/src/mapper/map_modify.c
+++ b/src/mapper/map_modify.c
@@ -33,10 +33,10 @@
 #include <resources.h>
 
 /* util includes */
-#include <base36.h>
+#include <util/base36.h>
+#include <util/rng.h>
 
 /* libc includes */
-#include <stdlib.h>
 #include <string.h>
 
 typedef struct menulist {
@@ -77,7 +77,7 @@ static char maxseeds[MAXCLIMATES][8] =
 static terrain_t
 terrain_create(int climate)
 {
-	int i = rand() % MAXSEEDSIZE;
+	int i = rng_int() % MAXSEEDSIZE;
 	terrain_t terrain = T_OCEAN;
 
 	while (i > maxseeds[climate][terrain])
@@ -151,7 +151,7 @@ block_create(short x1, short y1, int size, char chaotisch, int special, const te
 		}
 	}
 	for (k = 0; k != size; ++k) {
-		int c = (int) fringe.data[rand() % fringe.size];
+		int c = (int) fringe.data[rng_int() % fringe.size];
 		direction_t d;
 
 		x = (short)(c >> 16);
@@ -176,9 +176,9 @@ block_create(short x1, short y1, int size, char chaotisch, int special, const te
 		const luxury_type *ltype, *p1 = NULL, *p2=NULL;
     int maxlux = get_maxluxuries();
     if (maxlux>0) {
-      i1 = (item_t)(rand() % maxlux);
+      i1 = (item_t)(rng_int() % maxlux);
       do {
-        i2 = (item_t)(rand() % maxlux);
+        i2 = (item_t)(rng_int() % maxlux);
       }
       while (i2 == i1);
     }
@@ -190,7 +190,7 @@ block_create(short x1, short y1, int size, char chaotisch, int special, const te
 		}
 		for (x = 0; x != BLOCKSIZE; x++) {
 			for (y = 0; y != BLOCKSIZE; y++) {
-				const luxury_type * sale = (rand()%2)?p1:p2;
+				const luxury_type * sale = (rng_int()%2)?p1:p2;
 				r = findregion(x1 + x - BLOCKSIZE/2, y1 + y - BLOCKSIZE/2);
 				if (r && !fval(r->terrain, SEA_REGION)) continue;
 				if (r==NULL) r = new_region(x1 + x - BLOCKSIZE/2, y1 + y - BLOCKSIZE/2);
@@ -1026,15 +1026,15 @@ static terrain_t
 choose_terrain(terrain_t t) {
 	int q;
 
-	if (rand()%100 < 50) return t;
-	if (rand()%100 < 10) return T_OCEAN;
+	if (rng_int()%100 < 50) return t;
+	if (rng_int()%100 < 10) return T_OCEAN;
 
-	q = rand()%100;
+	q = rng_int()%100;
 
 	switch (t) {
 		case T_OCEAN:
-			if(rand()%100 < 60) return T_OCEAN;
-			switch(rand()%6) {
+			if(rng_int()%100 < 60) return T_OCEAN;
+			switch(rng_int()%6) {
 			case 0:
 				return T_SWAMP;
 			case 1:
@@ -1142,7 +1142,7 @@ shift(void)
 
 	if(t_queue_len == 0) return NULL;
 
-	p = rand()%t_queue_len;
+	p = rng_int()%t_queue_len;
 	r = t_queue[p];
 
 	memmove(&t_queue[p], &t_queue[p+1], (10000-p)*sizeof(region *));
@@ -1160,11 +1160,11 @@ settg(region *r)
 	if (tradegood==NULL) tradegood = luxurytypes;
 
 	for (ltype=luxurytypes; ltype; ltype=ltype->next) {
-		if (ltype!=tradegood) r_setdemand(r, ltype, 1 + rand() % 5);
+		if (ltype!=tradegood) r_setdemand(r, ltype, 1 + rng_int() % 5);
 	}
 	r_setdemand(r, tradegood, 0);
-	if (g>0 && (rand()%10)<2) {
-		int t = rand() % g;
+	if (g>0 && (rng_int()%10)<2) {
+		int t = rng_int() % g;
 
 		for (tradegood = luxurytypes;t;--t) {
 			tradegood = tradegood->next;
@@ -1178,7 +1178,7 @@ Create_Island(region *r, int * n, const terrain_type * terrain, int x, int y) {
 	if (!r) return false;
 	if (*n == 0) return true;
 
-	if((t == T_MOUNTAIN || t == T_GLACIER) && rand()%100 < 5) {
+	if((t == T_MOUNTAIN || t == T_GLACIER) && rng_int()%100 < 5) {
 		terraform(r,T_VOLCANO);
 	} else {
 		terraform_region(r, terrain);
@@ -1203,7 +1203,7 @@ create_island(region *r, int n, const struct terrain_type * terrain)
 	tradegood = NULL;
 	terraform_region(r, terrain);
 	if(r->land) settg(r);
-	r->msgs = (void *)(rand()%6);
+	r->msgs = (void *)(rng_int()%6);
 
 	push(r);
 	for(d=0; d<MAXDIRECTIONS; d++) {
diff --git a/src/mapper/mapper.c b/src/mapper/mapper.c
index 6b472c2f9..9aa9537d6 100644
--- a/src/mapper/mapper.c
+++ b/src/mapper/mapper.c
@@ -60,13 +60,13 @@
 /* util includes */
 #include <util/base36.h>
 #include <util/goodies.h>
+#include <util/rng.h>
 
 /* libc includes */
 #include <ctype.h>
 #include <limits.h>
 #include <locale.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #include <time.h>
 
@@ -693,14 +693,14 @@ modify_block(void)
 					rsetname(r, name);
 					break;
 				case 'p':
-					rsetpeasants(r, (production(r)*3+rand()%(production(r)*3))/div);
-					rsetmoney(r, (production(r)*10+rand()%(production(r)*10))/div);
+					rsetpeasants(r, (production(r)*3+rng_int()%(production(r)*3))/div);
+					rsetmoney(r, (production(r)*10+rng_int()%(production(r)*10))/div);
 					break;
 				case 'h':
-					rsethorses(r, rand()%(production(r) / 10));
+					rsethorses(r, rng_int()%(production(r) / 10));
 					break;
 				case 's':
-					rsetmoney(r, production(r)*10+rand()%(production(r)*10));
+					rsetmoney(r, production(r)*10+rng_int()%(production(r)*10));
 					break;
 				case 'r':
 					for (res=r->resources;res;res=res->next) {
@@ -1528,7 +1528,7 @@ makemonsters(void)
 	f->subscription = 0;
 	f->name=strdup("Monster");
 	f->passw=strdup("abc123");
-	f->override = strdup(itoa36(rand()));
+	f->override = strdup(itoa36(rng_int()));
 	return f;
 }
 
@@ -1701,7 +1701,7 @@ main(int argc, char *argv[])
 	make_xref();
 #endif
 	setminmax();
-	srand(time((time_t *) NULL));
+	rng_init(time((time_t *) NULL));
 
 	if (autoseeding) {
 		runautoseed();
diff --git a/src/tools/namegen.c b/src/tools/namegen.c
index ef4366dff..564d73743 100644
--- a/src/tools/namegen.c
+++ b/src/tools/namegen.c
@@ -143,7 +143,7 @@ create_random_name(race_t race)
 	switch (race)
 	{
 	case RC_DWARF:
-		strcpy(name, dwarf_syllable1[rand()%(sizeof(dwarf_syllable1) / sizeof(char*))]);
+		strcpy(name, dwarf_syllable1[rng_int()%(sizeof(dwarf_syllable1) / sizeof(char*))]);
 		strcat(name, dwarf_syllable2[rand()%(sizeof(dwarf_syllable2) / sizeof(char*))]);
 		strcat(name, dwarf_syllable3[rand()%(sizeof(dwarf_syllable3) / sizeof(char*))]);
 		break;