diff -urw freeciv-1.14.0/common/game.c freeciv/common/game.c --- freeciv-1.14.0/common/game.c 2002-10-11 19:35:13.000000000 -0400 +++ freeciv/common/game.c 2003-04-02 18:22:40.000000000 -0500 @@ -714,6 +714,11 @@ game.watchtower_extra_vision=GAME_DEFAULT_WATCHTOWER_EXTRA_VISION, game.allowed_city_names = GAME_DEFAULT_ALLOWED_CITY_NAMES; + game.slowai_tech = GAME_DEFAULT_SLOWAI_TECH; + game.slowai_grow = GAME_DEFAULT_SLOWAI_GROW; + game.check_isles = GAME_DEFAULT_CHECK_ISLES; + game.best_isles = GAME_DEFAULT_BEST_ISLES; + sz_strlcpy(game.rulesetdir, GAME_DEFAULT_RULESETDIR); game.firepower_factor = 1; diff -urw freeciv-1.14.0/common/game.h freeciv/common/game.h --- freeciv-1.14.0/common/game.h 2002-10-11 19:35:13.000000000 -0400 +++ freeciv/common/game.h 2003-04-02 18:25:13.000000000 -0500 @@ -217,6 +217,11 @@ bool load_private_map; /* Only makes sense if the players are loaded. */ bool load_settings; } load_options; + + int slowai_tech; /* AI gains tech slower then normal. */ + int slowai_grow; /* AI grows slower then normal. */ + int check_isles; /* Make sure there each player gets their own island. */ + bool best_isles; /* Make sure players get best islands. */ }; /* Unused? */ @@ -455,4 +460,15 @@ #define GAME_START_YEAR -4000 +#define GAME_DEFAULT_SLOWAI_TECH 1 +#define GAME_MIN_SLOWAI_TECH 1 +#define GAME_MAX_SLOWAI_TECH 4 +#define GAME_DEFAULT_SLOWAI_GROW 100 +#define GAME_MIN_SLOWAI_GROW 25 +#define GAME_MAX_SLOWAI_GROW 100 +#define GAME_DEFAULT_CHECK_ISLES 0 +#define GAME_MIN_CHECK_ISLES 0 +#define GAME_MAX_CHECK_ISLES 30 /* Max # of players. */ +#define GAME_DEFAULT_BEST_ISLES FALSE + #endif /* FC__GAME_H */ diff -urw freeciv-1.14.0/common/map.h freeciv/common/map.h --- freeciv-1.14.0/common/map.h 2002-10-11 19:35:13.000000000 -0400 +++ freeciv/common/map.h 2003-04-02 18:25:45.000000000 -0500 @@ -619,7 +619,7 @@ #define MAP_DEFAULT_GENERATOR 1 #define MAP_MIN_GENERATOR 1 -#define MAP_MAX_GENERATOR 5 +#define MAP_MAX_GENERATOR 8 #define MAP_DEFAULT_TINYISLES FALSE #define MAP_MIN_TINYISLES FALSE diff -urw freeciv-1.14.0/common/rand.c freeciv/common/rand.c --- freeciv-1.14.0/common/rand.c 2002-03-13 05:40:00.000000000 -0500 +++ freeciv/common/rand.c 2003-04-02 19:05:20.000000000 -0500 @@ -1,148 +1,127 @@ -/********************************************************************** - Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -***********************************************************************/ - -/************************************************************************* - The following random number generator can be found in _The Art of - Computer Programming Vol 2._ (2nd ed) by Donald E. Knuth. (C) 1998. - The algorithm is described in section 3.2.2 as Mitchell and Moore's - variant of a standard additive number generator. Note that the - the constants 55 and 24 are not random. Please become familiar with - this algorithm before you mess with it. - - Since the additive number generator requires a table of numbers from - which to generate its random sequences, we must invent a way to - populate that table from a single seed value. I have chosen to do - this with a different PRNG, known as the "linear congruential method" - (also found in Knuth, Vol2). I must admit that my choices of constants - (3, 257, and MAX_UINT32) are probably not optimal, but they seem to - work well enough for our purposes. - - Original author for this code: Cedric Tefft - Modified to use rand_state struct by David Pfitzner -*************************************************************************/ - #include - -#include "log.h" -#include "shared.h" /* TRUE, FALSE */ +#include +#include #include "rand.h" +#include "log.h" +#include "shared.h" +BYTE r_inBlock[17],r_binKey[17]; +BYTE r_keyMaterial[320]; /* We may not eventually need this */ +keyInstance r_keyInst; +cipherInstance r_cipherInst; -/* A global random state: - * Initialized by mysrand(), updated by myrand(), - * Can be duplicated/saved/restored via get_myrand_state() - * and set_myrand_state(). - */ static RANDOM_STATE rand_state; -/************************************************************************* - Returns a new random value from the sequence, in the interval 0 to - (size-1) inclusive, and updates global state for next call. - size==0 means result will be within 0 to MAX_UINT32 inclusive. - - Once we calculate new_rand below uniform (we hope) between 0 and - MAX_UINT32 inclusive, need to reduce to required range. Using - modulus is bad because generators like this are generally less - random for their low-significance bits, so this can give poor - results when 'size' is small. Instead want to divide the range - 0..MAX_UINT32 into (size) blocks, each with (divisor) values, and - for any remainder, repeat the calculation of new_rand. - Then: - return_val = new_rand / divisor; - Will repeat for new_rand > max, where: - max = size * divisor - 1 - Then max <= MAX_UINT32 implies - size * divisor <= (MAX_UINT32+1) - thus divisor <= (MAX_UINT32+1)/size - - Need to calculate this divisor. Want divisor as large as possible - given above contraint, but it doesn't hurt us too much if it is a - bit smaller (just have to repeat more often). Calculation exactly - as above is complicated by fact that (MAX_UINT32+1) may not be - directly representable in type RANDOM_TYPE, so we do instead: - divisor = MAX_UINT32/size -*************************************************************************/ -RANDOM_TYPE myrand(RANDOM_TYPE size) -{ - RANDOM_TYPE new_rand, divisor=1, max=MAX_UINT32; - int bailout = 0; - - assert(rand_state.is_init); - - if (size>1) { - divisor = MAX_UINT32/size; - max = size * divisor - 1; - } - - do { - new_rand = (rand_state.v[rand_state.j] - + rand_state.v[rand_state.k]) & MAX_UINT32; - - rand_state.x = (rand_state.x +1) % 56; - rand_state.j = (rand_state.j +1) % 56; - rand_state.k = (rand_state.k +1) % 56; - rand_state.v[rand_state.x] = new_rand; - - if (++bailout > 10000) { - freelog(LOG_ERROR, "Bailout in myrand(%u)", size); - new_rand = 0; - break; - } - - } while (new_rand > max && size > 1); - - if (size > 1) { - new_rand /= divisor; - } else if (size == 1) { - new_rand = 0; - } - /* else leave it "raw" */ - - /* freelog(LOG_DEBUG, "rand(%u) = %u", size, new_rand); */ - return new_rand; +/* A cryptgraphically secure random number with a value between + 0 and 2^31 + Input: None + Output: A number between 0 and 2^32 - 1 +*/ +u_int32_t rng_raw() { + u_int32_t nummake; + int rp; + + /* If needed, rerun the encryption to create 128 more random bits */ + if(rand_state.r_place > 12) { + rp = 15; + nummake = ++rand_state.dice_counter; + /* Make sure the dice counter can not step on the seed */ + nummake %= 10000000; + while(rp > 0 && nummake > 0) { + r_inBlock[rp] = '0' + nummake % 10; + nummake /= 10; + rp--; + } +#ifdef DEBUG + printf("\nNEW BLOCK "); + for(rp = 0; rp < 16; rp++) { + printf("%c",r_inBlock[rp]); + } + printf("\n"); +#endif /* DEBUG */ + blockEncrypt(&r_cipherInst,&r_keyInst,r_inBlock,128,rand_state.v); +#ifdef DEBUG + for(rp = 0; rp < 16; rp++) { + printf("%2x ",rand_state.v[r_place]); + } + printf("END NEW BLOCK\n"); +#endif /* DEBUG */ + rand_state.r_place = 0; + } + nummake = (rand_state.v[rand_state.r_place] & 0xff); + rand_state.r_place++; + nummake <<= 8; + nummake |= (rand_state.v[rand_state.r_place] & 0xff); + rand_state.r_place++; + nummake <<= 8; + nummake |= (rand_state.v[rand_state.r_place] & 0xff); + rand_state.r_place++; + nummake <<= 8; + nummake |= (rand_state.v[rand_state.r_place] & 0xff); + rand_state.r_place++; + nummake <<= 8; + nummake |= (rand_state.v[rand_state.r_place] & 0xff); + return nummake; + } + +/* Return a number from 1 to n; we make sure this is good */ +RANDOM_TYPE myrand(RANDOM_TYPE n) { + u_int32_t r; + if(n <= 0 || n > 2000000000) { + return rng_raw(); + } + r = rng_raw(); + while(r > 4294967296 - n) { + r = rng_raw(); + } + return r % n; + } + +/* Initialize the cryptographically secure psudo-random-number generator */ +/* Input: pointer to string that has binary crypto key */ + +int init_rng_g(char *key) { + unsigned char crypto_key[34]; + /* Initialize the keys, including the "binKey" (is this used?) */ + memset(r_binKey,'0',16); + memset(crypto_key,'0',33); + strncpy(crypto_key,key,32); + + if(makeKey(&r_keyInst, DIR_ENCRYPT, 128, crypto_key) != 1) + return -1; + if(cipherInit(&r_cipherInst, MODE_ECB, NULL) != 1) + return -1; + if(blockEncrypt(&r_cipherInst,&r_keyInst,r_inBlock,128,rand_state.v)!=128) + return -1; + + return 1; + } + +void mysrand(RANDOM_TYPE seed) { + + int counter; + + /* Set the plaintext block to '0000000000000000' */ + memset(r_inBlock,'0',16); + + /* Make sure the seed can not step on the dice rolls */ + /* seed %= 1000000000; */ + + /* Put the seed in the block which we encrypt in counter mode (A seed of + 1 makes the plaintext clock look like '1000000000000000', a seed of 256 + makes the plaintext look like '6520000000000000', and so on */ + counter = 0; + while(seed > 0 && counter < 16) { + r_inBlock[counter] = '0' + seed % 10; + seed /= 10; + counter++; } -/************************************************************************* - Initialize the generator; see comment at top of file. -*************************************************************************/ -void mysrand(RANDOM_TYPE seed) -{ - int i; - - rand_state.v[0]=(seed & MAX_UINT32); + /* Initialize the crypto with a fixed key and the above seed */ + init_rng_g("1970012508675309"); - for(i=1; i<56; i++) { - rand_state.v[i] = (3 * rand_state.v[i-1] + 257) & MAX_UINT32; - } - - rand_state.j = (55-55); - rand_state.k = (55-24); - rand_state.x = (55-0); - - rand_state.is_init = TRUE; - - /* Heat it up a bit: - * Using modulus in myrand() this was important to pass - * test_random1(). Now using divisor in myrand() that particular - * test no longer indicates problems, but this seems a good idea - * anyway -- eg, other tests could well reveal other initial - * problems even using divisor. - */ - for (i=0; i<10000; i++) { - (void) myrand(0); - } } /************************************************************************* @@ -208,3 +187,430 @@ /* restore state: */ set_myrand_state(saved_state); } + +/* Now the nuts and bolts; here be dragons */ + +/* Copyright (c) 2002,2003 Sam Trenholme + * + * TERMS + * + * 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. + * + * This software is provided 'as is' with no guarantees of correctness or + * fitness for purpose. + * + * Note that this copyrighted code is based on public domain code + */ + + +/** + * rng-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Note: This is a Rijndael variant. + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * The original code was hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + */ +#include +#include + +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) + +#ifdef _MSC_VER +#define GETU32(p) SWAP(*((u32 *)(p))) +#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } +#else +#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } +#endif + +/** + * Expand the cipher key into the encryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +int rngKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { + int i = 0; + u32 temp; + + rk[0] = GETU32(cipherKey ); + rk[1] = GETU32(cipherKey + 4); + rk[2] = GETU32(cipherKey + 8); + rk[3] = GETU32(cipherKey + 12); + if (keyBits == 128) { + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 10; + } + rk += 4; + } + } + exit(1); +} + +void rngEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(pt ) ^ rk[0]; + s1 = GETU32(pt + 4) ^ rk[1]; + s2 = GETU32(pt + 8) ^ rk[2]; + s3 = GETU32(pt + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4[(t0 >> 24) ] & 0xff000000) ^ + (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(ct , s0); + s1 = + (Te4[(t1 >> 24) ] & 0xff000000) ^ + (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(ct + 4, s1); + s2 = + (Te4[(t2 >> 24) ] & 0xff000000) ^ + (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(ct + 8, s2); + s3 = + (Te4[(t3 >> 24) ] & 0xff000000) ^ + (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(ct + 12, s3); +} + +/* Copyright (c) 2002,2003 Sam Trenholme + * + * TERMS + * + * 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. + * + * This software is provided 'as is' with no guarantees of correctness or + * fitness for purpose. + * + * Note that this copyrighted code is based on public domain code + */ + +/** + * rng-api-fst.c + * + * @version 2.9 (December 2000) + * (Modified by Sam for MaraDNS use) + * + * Note: This is a Rijndael variant. + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * @author Sam Trenholme + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + * + * Acknowledgements: + * + * We are deeply indebted to the following people for their bug reports, + * fixes, and improvement suggestions to this implementation. Though we + * tried to list all contributions, we apologise in advance for any + * missing reference. + * + * Andrew Bales + * Markus Friedl + * John Skodon + */ + +#include +#include +#include + +int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) { + int i; + char *keyMat; + u8 cipherKey[MAXKB]; + + if (key == NULL) { + return BAD_KEY_INSTANCE; + } + + if (direction == DIR_ENCRYPT) { + key->direction = direction; + } else { + return BAD_KEY_DIR; + } + + if (keyLen == 128) { + key->keyLen = keyLen; + } else { + return BAD_KEY_MAT; + } + +#ifdef ASCII_KEY + strncpy(key->keyMaterial, keyMaterial, keyLen/4); +#else + memcpy(key->keyMaterial, keyMaterial, keyLen/8); +#endif + + /* initialize key schedule: */ + keyMat = key->keyMaterial; + for (i = 0; i < key->keyLen/8; i++) { + int v; +#ifdef ASCII_KEY + int t; + t = *keyMat++; + if ((t >= '0') && (t <= '9')) v = (t - '0') << 4; + else if ((t >= 'a') && (t <= 'f')) v = (t - 'a' + 10) << 4; + else if ((t >= 'A') && (t <= 'F')) v = (t - 'A' + 10) << 4; + else return BAD_KEY_MAT; + + t = *keyMat++; + if ((t >= '0') && (t <= '9')) v ^= (t - '0'); + else if ((t >= 'a') && (t <= 'f')) v ^= (t - 'a' + 10); + else if ((t >= 'A') && (t <= 'F')) v ^= (t - 'A' + 10); + else return BAD_KEY_MAT; +#else + v = *keyMat; + keyMat++; +#endif /* ASCII_KEY */ + cipherKey[i] = (u8)v; + } + if (direction == DIR_ENCRYPT) { + key->Nr = rngKeySetupEnc(key->rk, cipherKey, keyLen); + } else { + return -1; + } + rngKeySetupEnc(key->ek, cipherKey, keyLen); + return TRUE; +} + +int cipherInit(cipherInstance *cipher, BYTE mode, char *IV) { + if (mode == MODE_ECB) { + cipher->mode = mode; + } else { + return BAD_CIPHER_MODE; + } + if (IV != NULL) { + return BAD_CIPHER_MODE; + } else { + memset(cipher->IV, 0, MAX_IV_SIZE); + } + return TRUE; +} + +int blockEncrypt(cipherInstance *cipher, keyInstance *key, + BYTE *input, int inputLen, BYTE *outBuffer) { + int i, numBlocks; + + if (cipher == NULL || + key == NULL || + key->direction == DIR_DECRYPT) { + return BAD_CIPHER_STATE; + } + if (input == NULL || inputLen <= 0) { + return 0; /* nothing to do */ + } + + numBlocks = inputLen/128; + + switch (cipher->mode) { + case MODE_ECB: + for (i = numBlocks; i > 0; i--) { + rngEncrypt(key->rk, key->Nr, input, outBuffer); + input += 16; + outBuffer += 16; + } + break; + + default: + return BAD_CIPHER_STATE; + } + + return 128*numBlocks; +} + diff -urw freeciv-1.14.0/common/rand.h freeciv/common/rand.h --- freeciv-1.14.0/common/rand.h 2002-04-12 09:50:56.000000000 -0400 +++ freeciv/common/rand.h 2003-04-02 19:17:08.000000000 -0500 @@ -18,11 +18,13 @@ /* This is duplicated in shared.h to avoid extra includes: */ #define MAX_UINT32 0xFFFFFFFF -typedef unsigned int RANDOM_TYPE; +typedef u_int32_t RANDOM_TYPE; +typedef unsigned char BYTE; typedef struct { - RANDOM_TYPE v[56]; - int j, k, x; + BYTE v[16]; + int dice_counter; + int r_place; bool is_init; /* initially 0 for static storage */ } RANDOM_STATE; @@ -35,4 +37,531 @@ void test_random1(int n); +/* All of the RNG-specific stuff */ + +/* Copyright (c) 2002,2003 Sam Trenholme + * + * TERMS + * + * 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. + * + * This software is provided 'as is' with no guarantees of correctness or + * fitness for purpose. + * + * Note that this code is based on public domain code + */ + +/** + * rng-alg-fst.h + * + * @version 3.0 (December 2000) + * + * Note: This is a Rijndael variant. + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + */ +#ifndef __RNG_ALG_FST_H +#define __RNG_ALG_FST_H + +#define MAXKC (256/32) +#define MAXKB (256/8) +#define MAXNR 14 + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +int rngKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits); +void rngEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]); + +#endif /* __RNG_ALG_FST_H */ + +/* Copyright (c) 2002,2003 Sam Trenholme + * + * TERMS + * + * 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. + * + * This software is provided 'as is' with no guarantees of correctness or + * fitness for purpose. + * + * Note that this copyrighted code is based on public domain code + */ + +/** + * rng-api-fst.h + * + * @version 2.9 (December 2000) + * + * Note: This is a Rijndael variant. + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + * + * Acknowledgements: + * + * We are deeply indebted to the following people for their bug reports, + * fixes, and improvement suggestions to this implementation. Though we + * tried to list all contributions, we apologise in advance for any + * missing reference. + * + * Andrew Bales + * Markus Friedl + * John Skodon + */ + +#ifndef __RIJNDAEL_API_FST_H +#define __RIJNDAEL_API_FST_H + +#include + +/* Generic Defines */ +#define DIR_ENCRYPT 0 /* Are we encrpyting? */ +#define DIR_DECRYPT 1 /* Are we decrpyting? */ +#define MODE_ECB 1 /* Are we ciphering in ECB mode? */ +#define MODE_CBC 2 /* Are we ciphering in CBC mode? */ +#define MODE_CFB1 3 /* Are we ciphering in 1-bit CFB mode? */ +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif +#define BITSPERBLOCK 128 /* Default number of bits in a cipher block */ + +/* Error Codes */ +#define BAD_KEY_DIR -1 /* Key direction is invalid, e.g., unknown value */ +#define BAD_KEY_MAT -2 /* Key material not of correct length */ +#define BAD_KEY_INSTANCE -3 /* Key passed is not valid */ +#define BAD_CIPHER_MODE -4 /* Params struct passed to cipherInit invalid */ +#define BAD_CIPHER_STATE -5 /* Cipher in wrong state (e.g., not initialized) */ +#define BAD_BLOCK_LENGTH -6 +#define BAD_CIPHER_INSTANCE -7 +#define BAD_DATA -8 /* Data contents are invalid, e.g., invalid padding */ +#define BAD_OTHER -9 /* Unknown error */ + +/* Algorithm-specific Defines */ +#define MAX_KEY_SIZE 64 /* # of ASCII char's needed to represent a key */ +#define MAX_IV_SIZE 16 /* # bytes needed to represent an IV */ + +/* Typedefs */ + +/* The structure for key information */ +typedef struct { + BYTE direction; /* Key used for encrypting or decrypting? */ + int keyLen; /* Length of the key */ + char keyMaterial[MAX_KEY_SIZE+1]; /* Raw key data in ASCII, e.g., user input or KAT values */ + int Nr; /* key-length-dependent number of rounds */ + u32 rk[4*(MAXNR + 1)]; /* key schedule */ + u32 ek[4*(MAXNR + 1)]; /* CFB1 key schedule (encryption only) */ +} keyInstance; + +/* The structure for cipher information */ +typedef struct { /* changed order of the components */ + BYTE mode; /* MODE_ECB, MODE_CBC, or MODE_CFB1 */ + BYTE IV[MAX_IV_SIZE]; /* A possible Initialization Vector for ciphering */ +} cipherInstance; + +/* Function prototypes */ + +int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial); + +int cipherInit(cipherInstance *cipher, BYTE mode, char *IV); + +int blockEncrypt(cipherInstance *cipher, keyInstance *key, + BYTE *input, int inputLen, BYTE *outBuffer); + +int padEncrypt(cipherInstance *cipher, keyInstance *key, + BYTE *input, int inputOctets, BYTE *outBuffer); + +int blockDecrypt(cipherInstance *cipher, keyInstance *key, + BYTE *input, int inputLen, BYTE *outBuffer); + +int padDecrypt(cipherInstance *cipher, keyInstance *key, + BYTE *input, int inputOctets, BYTE *outBuffer); + +#ifdef INTERMEDIATE_VALUE_KAT +int cipherUpdateRounds(cipherInstance *cipher, keyInstance *key, + BYTE *input, int inputLen, BYTE *outBuffer, int Rounds); +#endif /* INTERMEDIATE_VALUE_KAT */ + +#endif /* __RIJNDAEL_API_FST_H */ + +/* The tables for the RNG core */ +static const u32 Te0[256] = { +0xb3e2509bU, 0x63b4ca06U, 0x85e4a2d4U, 0x216c4602U, +0x3a6f3fa8U, 0xa616bd75U, 0x134d0610U, 0x4d60b99cU, +0x176ab44dU, 0x7f41f98eU, 0xe277da8fU, 0xcdec08c9U, +0x5a0a0dd1U, 0x1b0379aaU, 0x7b664bd3U, 0xa1e0f757U, +0xfaa55b5aU, 0xea39a535U, 0xc5a27773U, 0xb17c0938U, +0x2023e7deU, 0xd47128c0U, 0x7c9001f1U, 0x22bdbe7dU, +0xec804ecbU, 0xb9327682U, 0xbd15c4dfU, 0xc9cbba94U, +0xa488e4d6U, 0x014fa1dcU, 0x60653279U, 0xfe82e907U, +0x74de7e4bU, 0xa8e12931U, 0x0427b25dU, 0xe65068d2U, +0x898d6f33U, 0x928e1699U, 0x1202a7ccU, 0x7a29ea0fU, +0x1f24cbf7U, 0x64428024U, 0xdd70f6a6U, 0xbec43ca0U, +0x2d058be5U, 0x15f4edeeU, 0x572c61eaU, 0x1cf53388U, +0xf974a325U, 0x4046d5a7U, 0x2bbc601bU, 0xdea10ed9U, +0x42d88c04U, 0x8f3484cdU, 0x5f621e50U, 0x835d492aU, +0xf51d6ec2U, 0x2f9bd246U, 0xbf8b9d7cU, 0xee1e1768U, +0x6c0cff9eU, 0x16251591U, 0x37495393U, 0x5cb3e62fU, +0x3f072c29U, 0x4bd95262U, 0x05681381U, 0x90104f3aU, +0x03d1f87fU, 0x5244726bU, 0xd53e891cU, 0x9ac06923U, +0x51958a14U, 0x915feee6U, 0xdfeeaf05U, 0x79f81270U, +0xd2c8c33eU, 0x39bec7d7U, 0x764027e8U, 0x4808aa1dU, +0xcf72516aU, 0x269a0c20U, 0xab30d14eU, 0xc2543d51U, +0x770f8634U, 0xa0af568bU, 0x27d5adfcU, 0x4ffee03fU, +0xb4141ab9U, 0x8ce57cb2U, 0x2af3c1c7U, 0xdbc91d58U, +0xd6ef7163U, 0x3cd6d456U, 0x5b45ac0dU, 0x3e488df5U, +0x32214012U, 0xe1a622f0U, 0x9b8fc8ffU, 0x43972dd8U, +0xcca3a915U, 0x286d9864U, 0x31f0b86dU, 0x3498abecU, +0x73283469U, 0x6fdd07e1U, 0x682b4dc3U, 0x66dcd987U, +0x5663c036U, 0x62fb6bdaU, 0x95785cbbU, 0xe71fc90eU, +0x726795b5U, 0xcb55e337U, 0x5dfc47f3U, 0x70f9cc16U, +0xb68a431aU, 0x81c31089U, 0xe4ce3171U, 0x0d266c3bU, +0xacc69b6cU, 0x985e3080U, 0xda86bc84U, 0x6d435e42U, +0x6964ec1fU, 0x06b9ebfeU, 0x84ab0308U, 0xbae38efdU, +0x11d35fb3U, 0x00000000U, 0x0ef79444U, 0xfbeafa86U, +0xbbac2f21U, 0x650d21f8U, 0xae58c2cfU, 0x86355aabU, +0x612a93a5U, 0xf452cf1eU, 0x446167faU, 0x877afb77U, +0xf3a4853cU, 0xa7591ca9U, 0x7ddfa02dU, 0x58945472U, +0x9c7982ddU, 0xd818e527U, 0x336ee1ceU, 0x07f64a22U, +0xa5c7450aU, 0x808cb155U, 0xb7c5e2c6U, 0xef51b6b4U, +0x3606f24fU, 0xffcd48dbU, 0x55b23849U, 0x6bfab5bcU, +0x4eb141e3U, 0x8e7b2511U, 0x6ab51460U, 0xfd531178U, +0x18d281d5U, 0xd38762e2U, 0xf2eb24e0U, 0xca1a42ebU, +0xdc3f577aU, 0x88c2ceefU, 0x8daadd6eU, 0x029e59a3U, +0x199d2009U, 0xb033a8e4U, 0x0901de66U, 0x0c69cde7U, +0x0fb83598U, 0xf7833761U, 0xf6cc96bdU, 0x78b7b3acU, +0x7591df97U, 0x49470bc1U, 0xe58190adU, 0x97e60518U, +0xd7a0d0bfU, 0x4a96f3beU, 0x9fa87aa2U, 0xe9e85d4aU, +0x0b9f87c5U, 0x452ec626U, 0xbc5a6503U, 0xd95744fbU, +0x9911915cU, 0x96a9a4c4U, 0x46ff3e59U, 0x4c2f1840U, +0x9437fd67U, 0xe3387b53U, 0x3d99758aU, 0xc73c2ed0U, +0x2c4a2a39U, 0x254bf45fU, 0x23f21fa1U, 0x1a4cd876U, +0xd0569a9dU, 0xb87dd75eU, 0x1dba9254U, 0x38f1660bU, +0xa2310f28U, 0x5e2dbf8cU, 0x47b09f85U, 0x14bb4c32U, +0xa9ae88edU, 0x50da2bc8U, 0x24045583U, 0xeb7604e9U, +0xb55bbb65U, 0x1e6b6a2bU, 0x8212e8f6U, 0xf13adc9fU, +0xc0ca64f2U, 0x084e7fbaU, 0xa37eaef4U, 0x35d70a30U, +0xedcfef17U, 0xe0e9832cU, 0x30bf19b1U, 0x9ee7db7eU, +0xe8a7fc96U, 0x93c1b745U, 0xfc1cb0a4U, 0xb2adf147U, +0x109cfe6fU, 0xad893ab0U, 0xaf176313U, 0x2ed4739aU, +0x6e92a63dU, 0x9d362301U, 0xf83b02f9U, 0xc6738f0cU, +0xc185c52eU, 0xc8841b48U, 0x6793785bU, 0xaa7f7092U, +0x4109747bU, 0xc31b9c8dU, 0x71b66dcaU, 0x8b133690U, +0xd1193b41U, 0x54fd9995U, 0xc4edd6afU, 0x7e0e5852U, +0x3b209e74U, 0x8a5c974cU, 0xf0757d43U, 0x59dbf5aeU, +0xce3df0b6U, 0x530bd3b7U, 0x0ad02619U, 0x292239b8U, +}; +static const u32 Te1[256] = { +0x9bb3e250U, 0x0663b4caU, 0xd485e4a2U, 0x02216c46U, +0xa83a6f3fU, 0x75a616bdU, 0x10134d06U, 0x9c4d60b9U, +0x4d176ab4U, 0x8e7f41f9U, 0x8fe277daU, 0xc9cdec08U, +0xd15a0a0dU, 0xaa1b0379U, 0xd37b664bU, 0x57a1e0f7U, +0x5afaa55bU, 0x35ea39a5U, 0x73c5a277U, 0x38b17c09U, +0xde2023e7U, 0xc0d47128U, 0xf17c9001U, 0x7d22bdbeU, +0xcbec804eU, 0x82b93276U, 0xdfbd15c4U, 0x94c9cbbaU, +0xd6a488e4U, 0xdc014fa1U, 0x79606532U, 0x07fe82e9U, +0x4b74de7eU, 0x31a8e129U, 0x5d0427b2U, 0xd2e65068U, +0x33898d6fU, 0x99928e16U, 0xcc1202a7U, 0x0f7a29eaU, +0xf71f24cbU, 0x24644280U, 0xa6dd70f6U, 0xa0bec43cU, +0xe52d058bU, 0xee15f4edU, 0xea572c61U, 0x881cf533U, +0x25f974a3U, 0xa74046d5U, 0x1b2bbc60U, 0xd9dea10eU, +0x0442d88cU, 0xcd8f3484U, 0x505f621eU, 0x2a835d49U, +0xc2f51d6eU, 0x462f9bd2U, 0x7cbf8b9dU, 0x68ee1e17U, +0x9e6c0cffU, 0x91162515U, 0x93374953U, 0x2f5cb3e6U, +0x293f072cU, 0x624bd952U, 0x81056813U, 0x3a90104fU, +0x7f03d1f8U, 0x6b524472U, 0x1cd53e89U, 0x239ac069U, +0x1451958aU, 0xe6915feeU, 0x05dfeeafU, 0x7079f812U, +0x3ed2c8c3U, 0xd739bec7U, 0xe8764027U, 0x1d4808aaU, +0x6acf7251U, 0x20269a0cU, 0x4eab30d1U, 0x51c2543dU, +0x34770f86U, 0x8ba0af56U, 0xfc27d5adU, 0x3f4ffee0U, +0xb9b4141aU, 0xb28ce57cU, 0xc72af3c1U, 0x58dbc91dU, +0x63d6ef71U, 0x563cd6d4U, 0x0d5b45acU, 0xf53e488dU, +0x12322140U, 0xf0e1a622U, 0xff9b8fc8U, 0xd843972dU, +0x15cca3a9U, 0x64286d98U, 0x6d31f0b8U, 0xec3498abU, +0x69732834U, 0xe16fdd07U, 0xc3682b4dU, 0x8766dcd9U, +0x365663c0U, 0xda62fb6bU, 0xbb95785cU, 0x0ee71fc9U, +0xb5726795U, 0x37cb55e3U, 0xf35dfc47U, 0x1670f9ccU, +0x1ab68a43U, 0x8981c310U, 0x71e4ce31U, 0x3b0d266cU, +0x6cacc69bU, 0x80985e30U, 0x84da86bcU, 0x426d435eU, +0x1f6964ecU, 0xfe06b9ebU, 0x0884ab03U, 0xfdbae38eU, +0xb311d35fU, 0x00000000U, 0x440ef794U, 0x86fbeafaU, +0x21bbac2fU, 0xf8650d21U, 0xcfae58c2U, 0xab86355aU, +0xa5612a93U, 0x1ef452cfU, 0xfa446167U, 0x77877afbU, +0x3cf3a485U, 0xa9a7591cU, 0x2d7ddfa0U, 0x72589454U, +0xdd9c7982U, 0x27d818e5U, 0xce336ee1U, 0x2207f64aU, +0x0aa5c745U, 0x55808cb1U, 0xc6b7c5e2U, 0xb4ef51b6U, +0x4f3606f2U, 0xdbffcd48U, 0x4955b238U, 0xbc6bfab5U, +0xe34eb141U, 0x118e7b25U, 0x606ab514U, 0x78fd5311U, +0xd518d281U, 0xe2d38762U, 0xe0f2eb24U, 0xebca1a42U, +0x7adc3f57U, 0xef88c2ceU, 0x6e8daaddU, 0xa3029e59U, +0x09199d20U, 0xe4b033a8U, 0x660901deU, 0xe70c69cdU, +0x980fb835U, 0x61f78337U, 0xbdf6cc96U, 0xac78b7b3U, +0x977591dfU, 0xc149470bU, 0xade58190U, 0x1897e605U, +0xbfd7a0d0U, 0xbe4a96f3U, 0xa29fa87aU, 0x4ae9e85dU, +0xc50b9f87U, 0x26452ec6U, 0x03bc5a65U, 0xfbd95744U, +0x5c991191U, 0xc496a9a4U, 0x5946ff3eU, 0x404c2f18U, +0x679437fdU, 0x53e3387bU, 0x8a3d9975U, 0xd0c73c2eU, +0x392c4a2aU, 0x5f254bf4U, 0xa123f21fU, 0x761a4cd8U, +0x9dd0569aU, 0x5eb87dd7U, 0x541dba92U, 0x0b38f166U, +0x28a2310fU, 0x8c5e2dbfU, 0x8547b09fU, 0x3214bb4cU, +0xeda9ae88U, 0xc850da2bU, 0x83240455U, 0xe9eb7604U, +0x65b55bbbU, 0x2b1e6b6aU, 0xf68212e8U, 0x9ff13adcU, +0xf2c0ca64U, 0xba084e7fU, 0xf4a37eaeU, 0x3035d70aU, +0x17edcfefU, 0x2ce0e983U, 0xb130bf19U, 0x7e9ee7dbU, +0x96e8a7fcU, 0x4593c1b7U, 0xa4fc1cb0U, 0x47b2adf1U, +0x6f109cfeU, 0xb0ad893aU, 0x13af1763U, 0x9a2ed473U, +0x3d6e92a6U, 0x019d3623U, 0xf9f83b02U, 0x0cc6738fU, +0x2ec185c5U, 0x48c8841bU, 0x5b679378U, 0x92aa7f70U, +0x7b410974U, 0x8dc31b9cU, 0xca71b66dU, 0x908b1336U, +0x41d1193bU, 0x9554fd99U, 0xafc4edd6U, 0x527e0e58U, +0x743b209eU, 0x4c8a5c97U, 0x43f0757dU, 0xae59dbf5U, +0xb6ce3df0U, 0xb7530bd3U, 0x190ad026U, 0xb8292239U, +}; +static const u32 Te2[256] = { +0x509bb3e2U, 0xca0663b4U, 0xa2d485e4U, 0x4602216cU, +0x3fa83a6fU, 0xbd75a616U, 0x0610134dU, 0xb99c4d60U, +0xb44d176aU, 0xf98e7f41U, 0xda8fe277U, 0x08c9cdecU, +0x0dd15a0aU, 0x79aa1b03U, 0x4bd37b66U, 0xf757a1e0U, +0x5b5afaa5U, 0xa535ea39U, 0x7773c5a2U, 0x0938b17cU, +0xe7de2023U, 0x28c0d471U, 0x01f17c90U, 0xbe7d22bdU, +0x4ecbec80U, 0x7682b932U, 0xc4dfbd15U, 0xba94c9cbU, +0xe4d6a488U, 0xa1dc014fU, 0x32796065U, 0xe907fe82U, +0x7e4b74deU, 0x2931a8e1U, 0xb25d0427U, 0x68d2e650U, +0x6f33898dU, 0x1699928eU, 0xa7cc1202U, 0xea0f7a29U, +0xcbf71f24U, 0x80246442U, 0xf6a6dd70U, 0x3ca0bec4U, +0x8be52d05U, 0xedee15f4U, 0x61ea572cU, 0x33881cf5U, +0xa325f974U, 0xd5a74046U, 0x601b2bbcU, 0x0ed9dea1U, +0x8c0442d8U, 0x84cd8f34U, 0x1e505f62U, 0x492a835dU, +0x6ec2f51dU, 0xd2462f9bU, 0x9d7cbf8bU, 0x1768ee1eU, +0xff9e6c0cU, 0x15911625U, 0x53933749U, 0xe62f5cb3U, +0x2c293f07U, 0x52624bd9U, 0x13810568U, 0x4f3a9010U, +0xf87f03d1U, 0x726b5244U, 0x891cd53eU, 0x69239ac0U, +0x8a145195U, 0xeee6915fU, 0xaf05dfeeU, 0x127079f8U, +0xc33ed2c8U, 0xc7d739beU, 0x27e87640U, 0xaa1d4808U, +0x516acf72U, 0x0c20269aU, 0xd14eab30U, 0x3d51c254U, +0x8634770fU, 0x568ba0afU, 0xadfc27d5U, 0xe03f4ffeU, +0x1ab9b414U, 0x7cb28ce5U, 0xc1c72af3U, 0x1d58dbc9U, +0x7163d6efU, 0xd4563cd6U, 0xac0d5b45U, 0x8df53e48U, +0x40123221U, 0x22f0e1a6U, 0xc8ff9b8fU, 0x2dd84397U, +0xa915cca3U, 0x9864286dU, 0xb86d31f0U, 0xabec3498U, +0x34697328U, 0x07e16fddU, 0x4dc3682bU, 0xd98766dcU, +0xc0365663U, 0x6bda62fbU, 0x5cbb9578U, 0xc90ee71fU, +0x95b57267U, 0xe337cb55U, 0x47f35dfcU, 0xcc1670f9U, +0x431ab68aU, 0x108981c3U, 0x3171e4ceU, 0x6c3b0d26U, +0x9b6cacc6U, 0x3080985eU, 0xbc84da86U, 0x5e426d43U, +0xec1f6964U, 0xebfe06b9U, 0x030884abU, 0x8efdbae3U, +0x5fb311d3U, 0x00000000U, 0x94440ef7U, 0xfa86fbeaU, +0x2f21bbacU, 0x21f8650dU, 0xc2cfae58U, 0x5aab8635U, +0x93a5612aU, 0xcf1ef452U, 0x67fa4461U, 0xfb77877aU, +0x853cf3a4U, 0x1ca9a759U, 0xa02d7ddfU, 0x54725894U, +0x82dd9c79U, 0xe527d818U, 0xe1ce336eU, 0x4a2207f6U, +0x450aa5c7U, 0xb155808cU, 0xe2c6b7c5U, 0xb6b4ef51U, +0xf24f3606U, 0x48dbffcdU, 0x384955b2U, 0xb5bc6bfaU, +0x41e34eb1U, 0x25118e7bU, 0x14606ab5U, 0x1178fd53U, +0x81d518d2U, 0x62e2d387U, 0x24e0f2ebU, 0x42ebca1aU, +0x577adc3fU, 0xceef88c2U, 0xdd6e8daaU, 0x59a3029eU, +0x2009199dU, 0xa8e4b033U, 0xde660901U, 0xcde70c69U, +0x35980fb8U, 0x3761f783U, 0x96bdf6ccU, 0xb3ac78b7U, +0xdf977591U, 0x0bc14947U, 0x90ade581U, 0x051897e6U, +0xd0bfd7a0U, 0xf3be4a96U, 0x7aa29fa8U, 0x5d4ae9e8U, +0x87c50b9fU, 0xc626452eU, 0x6503bc5aU, 0x44fbd957U, +0x915c9911U, 0xa4c496a9U, 0x3e5946ffU, 0x18404c2fU, +0xfd679437U, 0x7b53e338U, 0x758a3d99U, 0x2ed0c73cU, +0x2a392c4aU, 0xf45f254bU, 0x1fa123f2U, 0xd8761a4cU, +0x9a9dd056U, 0xd75eb87dU, 0x92541dbaU, 0x660b38f1U, +0x0f28a231U, 0xbf8c5e2dU, 0x9f8547b0U, 0x4c3214bbU, +0x88eda9aeU, 0x2bc850daU, 0x55832404U, 0x04e9eb76U, +0xbb65b55bU, 0x6a2b1e6bU, 0xe8f68212U, 0xdc9ff13aU, +0x64f2c0caU, 0x7fba084eU, 0xaef4a37eU, 0x0a3035d7U, +0xef17edcfU, 0x832ce0e9U, 0x19b130bfU, 0xdb7e9ee7U, +0xfc96e8a7U, 0xb74593c1U, 0xb0a4fc1cU, 0xf147b2adU, +0xfe6f109cU, 0x3ab0ad89U, 0x6313af17U, 0x739a2ed4U, +0xa63d6e92U, 0x23019d36U, 0x02f9f83bU, 0x8f0cc673U, +0xc52ec185U, 0x1b48c884U, 0x785b6793U, 0x7092aa7fU, +0x747b4109U, 0x9c8dc31bU, 0x6dca71b6U, 0x36908b13U, +0x3b41d119U, 0x999554fdU, 0xd6afc4edU, 0x58527e0eU, +0x9e743b20U, 0x974c8a5cU, 0x7d43f075U, 0xf5ae59dbU, +0xf0b6ce3dU, 0xd3b7530bU, 0x26190ad0U, 0x39b82922U, +}; +static const u32 Te3[256] = { +0xe2509bb3U, 0xb4ca0663U, 0xe4a2d485U, 0x6c460221U, +0x6f3fa83aU, 0x16bd75a6U, 0x4d061013U, 0x60b99c4dU, +0x6ab44d17U, 0x41f98e7fU, 0x77da8fe2U, 0xec08c9cdU, +0x0a0dd15aU, 0x0379aa1bU, 0x664bd37bU, 0xe0f757a1U, +0xa55b5afaU, 0x39a535eaU, 0xa27773c5U, 0x7c0938b1U, +0x23e7de20U, 0x7128c0d4U, 0x9001f17cU, 0xbdbe7d22U, +0x804ecbecU, 0x327682b9U, 0x15c4dfbdU, 0xcbba94c9U, +0x88e4d6a4U, 0x4fa1dc01U, 0x65327960U, 0x82e907feU, +0xde7e4b74U, 0xe12931a8U, 0x27b25d04U, 0x5068d2e6U, +0x8d6f3389U, 0x8e169992U, 0x02a7cc12U, 0x29ea0f7aU, +0x24cbf71fU, 0x42802464U, 0x70f6a6ddU, 0xc43ca0beU, +0x058be52dU, 0xf4edee15U, 0x2c61ea57U, 0xf533881cU, +0x74a325f9U, 0x46d5a740U, 0xbc601b2bU, 0xa10ed9deU, +0xd88c0442U, 0x3484cd8fU, 0x621e505fU, 0x5d492a83U, +0x1d6ec2f5U, 0x9bd2462fU, 0x8b9d7cbfU, 0x1e1768eeU, +0x0cff9e6cU, 0x25159116U, 0x49539337U, 0xb3e62f5cU, +0x072c293fU, 0xd952624bU, 0x68138105U, 0x104f3a90U, +0xd1f87f03U, 0x44726b52U, 0x3e891cd5U, 0xc069239aU, +0x958a1451U, 0x5feee691U, 0xeeaf05dfU, 0xf8127079U, +0xc8c33ed2U, 0xbec7d739U, 0x4027e876U, 0x08aa1d48U, +0x72516acfU, 0x9a0c2026U, 0x30d14eabU, 0x543d51c2U, +0x0f863477U, 0xaf568ba0U, 0xd5adfc27U, 0xfee03f4fU, +0x141ab9b4U, 0xe57cb28cU, 0xf3c1c72aU, 0xc91d58dbU, +0xef7163d6U, 0xd6d4563cU, 0x45ac0d5bU, 0x488df53eU, +0x21401232U, 0xa622f0e1U, 0x8fc8ff9bU, 0x972dd843U, +0xa3a915ccU, 0x6d986428U, 0xf0b86d31U, 0x98abec34U, +0x28346973U, 0xdd07e16fU, 0x2b4dc368U, 0xdcd98766U, +0x63c03656U, 0xfb6bda62U, 0x785cbb95U, 0x1fc90ee7U, +0x6795b572U, 0x55e337cbU, 0xfc47f35dU, 0xf9cc1670U, +0x8a431ab6U, 0xc3108981U, 0xce3171e4U, 0x266c3b0dU, +0xc69b6cacU, 0x5e308098U, 0x86bc84daU, 0x435e426dU, +0x64ec1f69U, 0xb9ebfe06U, 0xab030884U, 0xe38efdbaU, +0xd35fb311U, 0x00000000U, 0xf794440eU, 0xeafa86fbU, +0xac2f21bbU, 0x0d21f865U, 0x58c2cfaeU, 0x355aab86U, +0x2a93a561U, 0x52cf1ef4U, 0x6167fa44U, 0x7afb7787U, +0xa4853cf3U, 0x591ca9a7U, 0xdfa02d7dU, 0x94547258U, +0x7982dd9cU, 0x18e527d8U, 0x6ee1ce33U, 0xf64a2207U, +0xc7450aa5U, 0x8cb15580U, 0xc5e2c6b7U, 0x51b6b4efU, +0x06f24f36U, 0xcd48dbffU, 0xb2384955U, 0xfab5bc6bU, +0xb141e34eU, 0x7b25118eU, 0xb514606aU, 0x531178fdU, +0xd281d518U, 0x8762e2d3U, 0xeb24e0f2U, 0x1a42ebcaU, +0x3f577adcU, 0xc2ceef88U, 0xaadd6e8dU, 0x9e59a302U, +0x9d200919U, 0x33a8e4b0U, 0x01de6609U, 0x69cde70cU, +0xb835980fU, 0x833761f7U, 0xcc96bdf6U, 0xb7b3ac78U, +0x91df9775U, 0x470bc149U, 0x8190ade5U, 0xe6051897U, +0xa0d0bfd7U, 0x96f3be4aU, 0xa87aa29fU, 0xe85d4ae9U, +0x9f87c50bU, 0x2ec62645U, 0x5a6503bcU, 0x5744fbd9U, +0x11915c99U, 0xa9a4c496U, 0xff3e5946U, 0x2f18404cU, +0x37fd6794U, 0x387b53e3U, 0x99758a3dU, 0x3c2ed0c7U, +0x4a2a392cU, 0x4bf45f25U, 0xf21fa123U, 0x4cd8761aU, +0x569a9dd0U, 0x7dd75eb8U, 0xba92541dU, 0xf1660b38U, +0x310f28a2U, 0x2dbf8c5eU, 0xb09f8547U, 0xbb4c3214U, +0xae88eda9U, 0xda2bc850U, 0x04558324U, 0x7604e9ebU, +0x5bbb65b5U, 0x6b6a2b1eU, 0x12e8f682U, 0x3adc9ff1U, +0xca64f2c0U, 0x4e7fba08U, 0x7eaef4a3U, 0xd70a3035U, +0xcfef17edU, 0xe9832ce0U, 0xbf19b130U, 0xe7db7e9eU, +0xa7fc96e8U, 0xc1b74593U, 0x1cb0a4fcU, 0xadf147b2U, +0x9cfe6f10U, 0x893ab0adU, 0x176313afU, 0xd4739a2eU, +0x92a63d6eU, 0x3623019dU, 0x3b02f9f8U, 0x738f0cc6U, +0x85c52ec1U, 0x841b48c8U, 0x93785b67U, 0x7f7092aaU, +0x09747b41U, 0x1b9c8dc3U, 0xb66dca71U, 0x1336908bU, +0x193b41d1U, 0xfd999554U, 0xedd6afc4U, 0x0e58527eU, +0x209e743bU, 0x5c974c8aU, 0x757d43f0U, 0xdbf5ae59U, +0x3df0b6ceU, 0x0bd3b753U, 0xd026190aU, 0x2239b829U, +}; +static const u32 Te4[256] = { +0x18181818U, 0x23232323U, 0xc6c6c6c6U, 0xe8e8e8e8U, +0x87878787U, 0xb8b8b8b8U, 0x01010101U, 0x4f4f4f4fU, +0x36363636U, 0xa6a6a6a6U, 0xd2d2d2d2U, 0xf5f5f5f5U, +0x79797979U, 0x6f6f6f6fU, 0x91919191U, 0x52525252U, +0x60606060U, 0xbcbcbcbcU, 0x9b9b9b9bU, 0x8e8e8e8eU, +0xa3a3a3a3U, 0x0c0c0c0cU, 0x7b7b7b7bU, 0x35353535U, +0x1d1d1d1dU, 0xe0e0e0e0U, 0xd7d7d7d7U, 0xc2c2c2c2U, +0x2e2e2e2eU, 0x4b4b4b4bU, 0xfefefefeU, 0x57575757U, +0x15151515U, 0x77777777U, 0x37373737U, 0xe5e5e5e5U, +0x9f9f9f9fU, 0xf0f0f0f0U, 0x4a4a4a4aU, 0xdadadadaU, +0x58585858U, 0xc9c9c9c9U, 0x29292929U, 0x0a0a0a0aU, +0xb1b1b1b1U, 0xa0a0a0a0U, 0x6b6b6b6bU, 0x85858585U, +0xbdbdbdbdU, 0x5d5d5d5dU, 0x10101010U, 0xf4f4f4f4U, +0xcbcbcbcbU, 0x3e3e3e3eU, 0x05050505U, 0x67676767U, +0xe4e4e4e4U, 0x27272727U, 0x41414141U, 0x8b8b8b8bU, +0xa7a7a7a7U, 0x7d7d7d7dU, 0x95959595U, 0xd8d8d8d8U, +0xfbfbfbfbU, 0xeeeeeeeeU, 0x7c7c7c7cU, 0x66666666U, +0xddddddddU, 0x17171717U, 0x47474747U, 0x9e9e9e9eU, +0xcacacacaU, 0x2d2d2d2dU, 0xbfbfbfbfU, 0x07070707U, +0xadadadadU, 0x5a5a5a5aU, 0x83838383U, 0x33333333U, +0x63636363U, 0x02020202U, 0xaaaaaaaaU, 0x71717171U, +0xc8c8c8c8U, 0x19191919U, 0x49494949U, 0xd9d9d9d9U, +0xf2f2f2f2U, 0xe3e3e3e3U, 0x5b5b5b5bU, 0x88888888U, +0x9a9a9a9aU, 0x26262626U, 0x32323232U, 0xb0b0b0b0U, +0xe9e9e9e9U, 0x0f0f0f0fU, 0xd5d5d5d5U, 0x80808080U, +0xbebebebeU, 0xcdcdcdcdU, 0x34343434U, 0x48484848U, +0xffffffffU, 0x7a7a7a7aU, 0x90909090U, 0x5f5f5f5fU, +0x20202020U, 0x68686868U, 0x1a1a1a1aU, 0xaeaeaeaeU, +0xb4b4b4b4U, 0x54545454U, 0x93939393U, 0x22222222U, +0x64646464U, 0xf1f1f1f1U, 0x73737373U, 0x12121212U, +0x40404040U, 0x08080808U, 0xc3c3c3c3U, 0xececececU, +0xdbdbdbdbU, 0xa1a1a1a1U, 0x8d8d8d8dU, 0x3d3d3d3dU, +0x97979797U, 0x00000000U, 0xcfcfcfcfU, 0x2b2b2b2bU, +0x76767676U, 0x82828282U, 0xd6d6d6d6U, 0x1b1b1b1bU, +0xb5b5b5b5U, 0xafafafafU, 0x6a6a6a6aU, 0x50505050U, +0x45454545U, 0xf3f3f3f3U, 0x30303030U, 0xefefefefU, +0x3f3f3f3fU, 0x55555555U, 0xa2a2a2a2U, 0xeaeaeaeaU, +0x65656565U, 0xbabababaU, 0x2f2f2f2fU, 0xc0c0c0c0U, +0xdedededeU, 0x1c1c1c1cU, 0xfdfdfdfdU, 0x4d4d4d4dU, +0x92929292U, 0x75757575U, 0x06060606U, 0x8a8a8a8aU, +0xb2b2b2b2U, 0xe6e6e6e6U, 0x0e0e0e0eU, 0x1f1f1f1fU, +0x62626262U, 0xd4d4d4d4U, 0xa8a8a8a8U, 0x96969696U, +0xf9f9f9f9U, 0xc5c5c5c5U, 0x25252525U, 0x59595959U, +0x84848484U, 0x72727272U, 0x39393939U, 0x4c4c4c4cU, +0x5e5e5e5eU, 0x78787878U, 0x38383838U, 0x8c8c8c8cU, +0xd1d1d1d1U, 0xa5a5a5a5U, 0xe2e2e2e2U, 0x61616161U, +0xb3b3b3b3U, 0x21212121U, 0x9c9c9c9cU, 0x1e1e1e1eU, +0x43434343U, 0xc7c7c7c7U, 0xfcfcfcfcU, 0x04040404U, +0x51515151U, 0x99999999U, 0x6d6d6d6dU, 0x0d0d0d0dU, +0xfafafafaU, 0xdfdfdfdfU, 0x7e7e7e7eU, 0x24242424U, +0x3b3b3b3bU, 0xababababU, 0xcecececeU, 0x11111111U, +0x8f8f8f8fU, 0x4e4e4e4eU, 0xb7b7b7b7U, 0xebebebebU, +0x3c3c3c3cU, 0x81818181U, 0x94949494U, 0xf7f7f7f7U, +0xb9b9b9b9U, 0x13131313U, 0x2c2c2c2cU, 0xd3d3d3d3U, +0xe7e7e7e7U, 0x6e6e6e6eU, 0xc4c4c4c4U, 0x03030303U, +0x56565656U, 0x44444444U, 0x7f7f7f7fU, 0xa9a9a9a9U, +0x2a2a2a2aU, 0xbbbbbbbbU, 0xc1c1c1c1U, 0x53535353U, +0xdcdcdcdcU, 0x0b0b0b0bU, 0x9d9d9d9dU, 0x6c6c6c6cU, +0x31313131U, 0x74747474U, 0xf6f6f6f6U, 0x46464646U, +0xacacacacU, 0x89898989U, 0x14141414U, 0xe1e1e1e1U, +0x16161616U, 0x3a3a3a3aU, 0x69696969U, 0x09090909U, +0x70707070U, 0xb6b6b6b6U, 0xd0d0d0d0U, 0xededededU, +0xccccccccU, 0x42424242U, 0x98989898U, 0xa4a4a4a4U, +0x28282828U, 0x5c5c5c5cU, 0xf8f8f8f8U, 0x86868686U, +}; + #endif /* FC__RAND_H */ diff -urw freeciv-1.14.0/common/tech.c freeciv/common/tech.c --- freeciv-1.14.0/common/tech.c 2002-10-11 19:35:13.000000000 -0400 +++ freeciv/common/tech.c 2003-04-02 18:27:05.000000000 -0500 @@ -462,6 +462,12 @@ cost = 1; } + /* For casual players, the AI gets tech far too fast. This + slows down how fast the AI gets tech by 4x at the easy level */ + if (!game.is_new_game && pplayer->ai.control) { + cost *= game.slowai_tech; + } + return cost; } Only in freeciv/server: DIFF diff -urw freeciv-1.14.0/server/gamehand.c freeciv/server/gamehand.c --- freeciv-1.14.0/server/gamehand.c 2002-10-11 19:35:50.000000000 -0400 +++ freeciv/server/gamehand.c 2003-04-02 18:31:15.000000000 -0500 @@ -42,9 +42,77 @@ int start_pos[MAX_NUM_PLAYERS]; /* indices into map.start_positions[] */ if (!map.fixed_start_positions) { - /* except in a scenario which provides them, - shuffle the start positions around... */ assert(game.nplayers==map.num_start_positions); + + /* We move all of the ai players after all of the humans. This is done + in conjunciton with code in mapgen.c which makes sure all of the + starting points on good islands come before (in the + map.start_positions array) all of the starting positions on bad + islands. + + The code assumes that each player gets their own island. + If not, then what this code will do is cause all of the humans + to share the best islands and all of the AIs to share the not-so-good + islands. + + Note that this is an inefficient O(N^2) algorithm; with the current + max of 30 players, there should not be a problem */ + + if (game.best_isles) { + int last_human_player = game.nplayers + 1; + int first_ai_player; + + for(j=game.nplayers - 1; j >=0; j--) { + if(!game.players[j].ai.control) { + last_human_player = j; + break; + } + } + if(last_human_player + 1< game.nplayers) { + for(i=0; i=0 ; j--) { + if(!game.players[j].ai.control) { + last_human_player = j; + break; + } + } + } + } + } + + /* except in a scenario which provides them, + shuffle the human's start positions around... */ + for (i=0; i<= last_human_player;i++) { /* no advantage to the romans!! */ + j=myrand(last_human_player + 1); + x=map.start_positions[j].x; + y=map.start_positions[j].y; + map.start_positions[j].x=map.start_positions[i].x; + map.start_positions[j].y=map.start_positions[i].y; + map.start_positions[i].x=x; + map.start_positions[i].y=y; + } + + /* Also shuffle all of the ai's start positions */ + first_ai_player = last_human_player + 1; + for(i = first_ai_player;i < game.nplayers; i++) { + j = myrand(game.nplayers - first_ai_player); + j += first_ai_player; + x=map.start_positions[j].x; + y=map.start_positions[j].y; + map.start_positions[j].x=map.start_positions[i].x; + map.start_positions[j].y=map.start_positions[i].y; + map.start_positions[i].x=x; + map.start_positions[i].y=y; + } + } else /* ! game.best_isles */ { for (i=0; i #include #include +#include /* For the plate tectonic simulator */ #include "fcintl.h" #include "game.h" @@ -41,6 +42,8 @@ static void mapgenerator3(void); static void mapgenerator4(void); static void mapgenerator5(void); +static void mapgenerator6(void); +static void mapgenerator_tectonic(void); static void smooth_map(void); static void adjust_map(int minval); @@ -258,13 +261,23 @@ while (i > 0 && j < 500) { j++; + if(map.ysize >= 18) { y=myrand(map.ysize*10/180)+map.ysize*110/180; + } + else { + y = map.ysize*110/180; + } x=myrand(map.xsize); if (map_get_terrain(x, y)==T_GRASSLAND) { make_desert(x,y, hmap(x, y), 50); i--; } + if(map.ysize >= 18) { y=myrand(map.ysize*10/180)+map.ysize*60/180; + } + else { + y = map.ysize*60/180; + } x=myrand(map.xsize); if (map_get_terrain(x, y)==T_GRASSLAND) { make_desert(x,y, hmap(x, y), 50); @@ -823,7 +836,7 @@ 1) with map.landpercent it generates a ocean/grassland map 2) it then calls the above functions to generate the different terrains **************************************************************************/ -static void make_land(void) +static void make_land(int window_size) { int tres=(maxval*map.landpercent)/100; int count=0; @@ -846,7 +859,7 @@ else tres*=9; tres/=10; - } while (abs(total-count)> maxval/40); + } while (abs(total-count)> window_size/40); if (map.separatepoles) { make_passable(); } @@ -941,8 +954,9 @@ Allocate islands array and fill in values. Note this is only use for map.generator<=1, since others setups islands and starters explicitly. + Output: The number of good islands that this map has **************************************************************************/ -static void setup_isledata(void) +int setup_isledata(void) { int x; int good, mingood, maxgood; @@ -1102,8 +1116,31 @@ _("Map generator: not enough start positions, fixing.")); } } - freelog(LOG_DEBUG, "The map has %i starting positions on %i isles.", + freelog(LOG_VERBOSE, "The map has %i starting positions on %i isles.", starters, goodisles); + return goodisles; +} + +/************************************************************************** + Comparison function that compares the goodness of two start points (how + good the island the two start points are on + *************************************************************************/ + +static int +compar_isle_goodness(const void *a,const void *b) +{ + int ia, ib; + int x,y; + struct map_position *t; + t = (struct map_position *)a; + x=t->x; + y=t->y; + ia = islands[(int)map_get_continent(x, y)].goodies; + t = (struct map_position *)b; + x=t->x; + y=t->y; + ib = islands[(int)map_get_continent(x, y)].goodies; + return ib - ia; } /************************************************************************** @@ -1113,23 +1150,106 @@ FIXME: MAXTRIES used to be 1.000.000, but has been raised to 10.000.000 because a set of values hit the limit. At some point we want to make a better solution. + Output: Whether this is a good map; 1 if yes, 0 if no **************************************************************************/ #define MAXTRIES 10000000 -void create_start_positions(void) +int Tec_Cleanup(void); + +int +create_start_positions(void) { int nr=0; int dist=40; - int x, y, j=0, k, sum; + int x, y, i, j=0, k, sum; int counter = 0; + int isles = 0; + int xz, yz, pxz; + if (!islands) /* already setup for generators 2,3, and 4 */ - setup_isledata(); + isles = setup_isledata(); + else + isles = 10000; /* Big number so this passes the "own island" test */ + + yz = map.ysize - 2; + xz = pxz = map.xsize; + + for(x=0;x 6) { + Tec_Cleanup(); + } +// map.seed++; + map.seed = myrand(MAX_UINT32); + free(islands); + free(height_map); + free(river_map); + islands = NULL; + height_map = NULL; + river_map = NULL; + maxval = 0; + forests = 0; + free(map.tiles); + map.tiles = NULL; + map.num_continents = 0; + map.num_start_positions = 0; + map.have_specials = FALSE; + map.have_huts = FALSE; + /* Initializing the next two may not be necessary */ + map.fixed_start_positions = FALSE; + map.have_rivers_overlay = FALSE; + return 0; + } + + printf("Using seed %d\n",map.seed); if(dist>= map.xsize/2) dist= map.xsize/2; if(dist>= map.ysize/2) dist= map.ysize/2; + /* If we make distance really big here (and do the check to make sure each + player gets their own island), we can 100% ensure that each player + gets their own island; dist is the minimum distance that two players + can be from one another on the same island */ + sum=0; for (k=0; k<=map.num_continents; k++) { sum += islands[k].starters; @@ -1167,8 +1287,21 @@ } map.num_start_positions = game.nplayers; + /* Sort the array so that the lowered numbered starting positions are + always on the best isles; this is used in conjunction with code in + gamehand.c to make sure that the humans get the best islands; the + code works best when each player gets their own island (otherwise + all of the humans will share the best islands and all of the AIs will + share the worse islands) */ + + if (game.best_isles) { + qsort(map.start_positions,map.num_start_positions, + sizeof(struct map_position),compar_isle_goodness); + } + free(islands); islands = NULL; + return 1; /* Good map */ } /************************************************************************** @@ -1196,6 +1329,10 @@ map_allocate(); /* if one mapgenerator fails, it will choose another mapgenerator */ /* with a lower number to try again */ + if (map.generator == 6 ) + mapgenerator6(); + if (map.generator == 7 || map.generator == 8) + mapgenerator_tectonic(); if (map.generator == 5 ) mapgenerator5(); if (map.generator == 4 ) @@ -1245,7 +1382,7 @@ /*!PS: I don't have the time to have several test runs */ /* to find a mapping from percents to generator 1 settings. */ - if(map.generator==1){ + if(map.generator==1 || map.generator > 6){ /*map.riverlength*= 10; */ /*I leave this out, people will get too upset if they have to change all their scripts */ @@ -1289,7 +1426,7 @@ /************************************************************************** since the generated map will always have a positive number as minimum height - i reduce the height so the lowest height is zero, this makes calculations + reduce the height so the lowest height is zero, this makes calculations easier **************************************************************************/ static void adjust_map(int minval) @@ -1338,7 +1475,866 @@ maxval-=minval; adjust_map(minval); - make_land(); + make_land(maxval); + free(height_map); + height_map = NULL; +} + +/************************************************************************** + The following code was written by Mark Isaak in 1988 and converted in to + a freeciv-compatible form 2003 by Sam Trenholme + *************************************************************************/ + +/* + * A program to simulate tectonics. + * + * Copyright 1988 by Mark Isaak. + * Copyright 2003 Sam Trenholme; with Mark Isaak's permission, I have + * relicensed this under the GPL. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * Wish list (from 1988): + * Do it on a sphere, not a square torus (not wanted for FreeCiv) + * Give plates angular momentum + * Make some constants variable + * Horsts and grabens + * Let 2 plates fuse together and/or 1 plate split apart sometimes + * Astroblemes + * Take density of rock into account + */ + +/* + * ---------- Structures ----------------------------------------------------- + */ + +/* + * ---------- Defined parameters --------------------------------------------- + * + * Some notes on Earth for comparison: + * Mean elevation of land = 840 m. + * Kilamanjaro = 5895 m. + * Everest = 8848 m. + * Dead Sea = -400 m. + * Gread Rift Valley = -150 m. + * Andes = 6950 m. + * Marianas Trench = -11000 m. + * Mean depth of sea = -3810 m. + */ + +struct tectonic_data { + + int xsize; /* Size of map along x axis */ + int ysize; /* Size of map along y axis */ + int nplates; /* # of plates in world at genesis */ + int maxplates; /* maximum # of plates we can have */ + int ncontinents; /* # of plates which are continental */ + int nhotspots; /* # of hot spots */ + + int landelev; /* starting elevation of land */ + int oceanelev; /* starting elevation of oceans */ + + int epochmove; /* max movement during one epoch */ + + float foldfactor; /* how much to increase ht. of folds */ + int riftelev; /* elevation for rifts */ + int subsumeheight; /* elevation change for coastal ranges */ + int trenchheight; /* elev. change for trench by coastal range */ + int hotspotheight; /* average ht. growth of hot spots */ + + int riftminerals; /* minerals in rifts */ + int subsumeminerals; /* minerals in costal ranges */ + int archipminerals; /* minerals in archipelagos */ + int hotspotminerals; /* minerals in underwater hot spots */ + + float erodefactor; /* how much of a height to erode */ + float submergefactor; /* how being underwater slows erosion */ + int skyelev; /* no erosion above this */ + int waveaction; /* erosion due entirely to waves */ + int subsidefactor; /* how fast ocean floor sinks */ + int basinelev; /* how far ocean floor can sink */ + +}; + +static struct tectonic_data tectonic; + +void init_tec_data() { + tectonic.xsize = map.xsize; /* Width of map */ + tectonic.ysize = map.ysize; /* Height of map */ + + tectonic.nplates = 20; /* # of plates in world at genesis */ + tectonic.maxplates = 27; /* maximum # of plates we can have */ + if (game.nplayers > 5) /* # of plates which are continental */ + tectonic.ncontinents = game.nplayers; + else + tectonic.ncontinents = 5; + tectonic.nhotspots = 10; /* # of hot spots */ + + tectonic.landelev = 800; /* starting elevation of land */ + tectonic.oceanelev = -1000; /* starting elevation of oceans */ + + tectonic.epochmove = 5; /* max movement during one epoch */ + + tectonic.foldfactor = 1.2; /* how much to increase ht. of folds */ + tectonic.riftelev = -400; /* elevation for rifts */ + tectonic.subsumeheight = 1200; /* elevation change for coastal ranges */ + tectonic.trenchheight = -500; /* elev. change for trench by coastal range */ + tectonic.hotspotheight = 600; /* average ht. growth of hot spots */ + + tectonic.riftminerals = 7; /* minerals in rifts */ + tectonic.subsumeminerals = 3; /* minerals in costal ranges */ + tectonic.archipminerals = 5; /* minerals in archipelagos */ + tectonic.hotspotminerals = 2; /* minerals in underwater hot spots */ + + tectonic.erodefactor = 0.023; /* how much of a height to erode */ + tectonic.submergefactor = 0.2; /* how being underwater slows erosion */ + tectonic.skyelev = 10000; /* no erosion above this */ + tectonic.waveaction = 400; /* erosion due entirely to waves */ + tectonic.subsidefactor = 0.05; /* how fast ocean floor sinks */ + tectonic.basinelev = -9000; /* how far ocean floor can sink */ + } + +/* + * Tectonic plate + */ +typedef struct { + float xvec, yvec; /* direction of plate movement */ + short dx, dy; /* how far do move plate per age */ + bool continent; /* whether initially continent or ocean */ +} Plate_t; + +/* + * Hot spot + */ +typedef struct { + short x, y; /* location of hot spot */ + short howhot; /* how much it spews forth */ +} Hotspot_t; + +/* + * A piece of land which moves around + */ +typedef struct rock_s { + short elev; /* elevation */ + short elevchange; /* change in elevation due to erosion */ + Plate_t *plate; /* which plate it belongs to */ + bool moved; /* whether we've moved this iteration */ + long minerals; /* how many minerals */ + struct rock_s *next; /* next in linked list */ +} Rock_t; + +/* + * ---------- Global variables ----------------------------------------------- + */ +Rock_t *surface[1024][1024]; /* surface of planet */ +Plate_t plates[1024]; /* descriptions of plates */ +Hotspot_t hotspots[1024]; /* descriptions of hot spots */ + +int nplates; /* # of tectonic plates */ +Rock_t *freeRockList; /* ptr to list of unused rocks */ + +/* + * ---------- Declarations ------------------------------------------------------ + */ +int Wrap_x(register int val); +int Wrap_y(register int val); +Rock_t * AllocRock(Plate_t *pl); +int SeedPlates(void); +int InitSurface(void); +int SeedHotSpots(void); +int Epoch(void); +int AssignDirections(void); +int SetMovementVectors(int iter); +int MovePlates(void); +int MountainBuild(void); +int Rift(int x, int y); +int Fold(int x, int y); +int ElevNearby(int x, int y, Rock_t *rp, short height); +int Subsume(int x, int y); +int EruptHotSpots(void); +int Erode(void); + +/* + * ---------- Utilities ------------------------------------------------------ + */ +/* + * Wraparound from one side of the world to the other. + */ +int Wrap_x(register int val) +{ + if (val < 0) + val += tectonic.xsize; + else if (val >= tectonic.xsize) + val -= tectonic.xsize; + return (val); +} + +int Wrap_y(register int val) +{ + if (val < 0) + val += tectonic.ysize; + else if (val >= tectonic.ysize) + val -= tectonic.ysize; + return (val); +} + +/* + * Allocate a rock. + */ +Rock_t * AllocRock(Plate_t *pl) +{ + Rock_t *rp; /* ptr to rock */ + + if (freeRockList) { + rp = freeRockList; + freeRockList = rp->next; + } else + rp = (Rock_t *)malloc(sizeof(Rock_t)); + rp->plate = pl; + rp->elev = (pl->continent ? tectonic.landelev : tectonic.oceanelev); + rp->elevchange = 0; + rp->moved = FALSE; + rp->minerals = 0; + rp->next = NULL; + return (rp); +} + +/* + * ---------- Initialization ------------------------------------------------- + */ + +/* + * Put plates at random spots on the planet. + * Make tectonic.ncontinents of them land, the rest ocean. + */ +int SeedPlates(void) +{ + register int i; + register Plate_t *pl; /* ptr to plates */ + + pl = &plates[0]; + for (i = 0; i < tectonic.nplates; ++i, ++pl) { + pl->dx = myrand(tectonic.xsize); + pl->dy = myrand(tectonic.ysize); + /* + * Check if this spot is already taken. + */ + if (surface[pl->dx][pl->dy]) { + --pl; + --i; + continue; /* try again */ + } + surface[pl->dx][pl->dy] = (Rock_t *)pl; + pl->xvec = 0.0; + pl->yvec = 0.0; + pl->continent = (i < tectonic.ncontinents); + } + return 0; +} + +/* + * Initialize the surface. Allocate a rock for each spot on the surface + * and assign it to the nearest plate. + */ +int InitSurface(void) +{ + register short dx, dy; /* x, y distance */ + register long dist; /* distance */ + register short x, y; /* location on surface */ + register Plate_t *pl; /* plate pointer */ + register Plate_t *bestpl; /* closest plate */ + register long bestdist; /* distance of closest plate */ + register int i; /* plate counter */ + + bestpl = NULL; + + for (x = 0; x < tectonic.xsize; ++x) { + for (y = 0; y < tectonic.ysize; ++y) { + bestdist = 2 * tectonic.xsize * tectonic.ysize; + for (pl = &plates[0], i = 0; i < tectonic.nplates; ++i, ++pl) { + dx = pl->dx - x; + if (dx < 0) + dx = -dx; + if (dx > tectonic.xsize/2) + dx = tectonic.xsize - dx; + dy = pl->dy - y; + if (dy < 0) + dy = -dy; + if (dy > tectonic.ysize/2) + dy = tectonic.ysize - dy; + dist = dx * dx + dy * dy; + if (dist < bestdist) { + bestdist = dist; + bestpl = pl; + } + } + surface[x][y] = AllocRock(bestpl); + } + } + return 0; +} + +/* + * Place some hot spots randomly. + */ +int SeedHotSpots(void) +{ + register int i; /* hot spot counter */ + register Hotspot_t *hsp; /* hot spot pointer */ + + for (hsp = &hotspots[0], i = 0; i < tectonic.nhotspots; ++i, ++hsp) { + hsp->x = myrand(tectonic.xsize); + hsp->y = myrand(tectonic.ysize); + hsp->howhot = (myrand(tectonic.hotspotheight) + myrand(tectonic.hotspotheight) + + myrand(tectonic.hotspotheight) + myrand(tectonic.hotspotheight) + 2) >> 1; + } + return 0; +} + +/* + * All initialization. + */ +int Tec_Init(void) +{ + nplates = tectonic.nplates; + SeedPlates(); + InitSurface(); + SeedHotSpots(); + return 0; +} + +/* + * Cleanup of memory allocated by tectonic code + */ +int Tec_Cleanup(void) +{ + int x,y; + Rock_t *tofree,*tmp; + + /* Start up with the freeRockList */ + tofree = freeRockList; + while(tofree != NULL) { + tmp = tofree->next; + free(tofree); + tofree = tmp; + } + freeRockList = NULL; + for (x = 0; x < tectonic.xsize; ++x) { + for (y = 0; y < tectonic.ysize; ++y) { + tofree = surface[x][y]; + while(tofree != NULL) { + tmp = tofree->next; + free(tofree); + tofree = tmp; + } + surface[x][y] = NULL; + } + } + return 0; +} + +/* + * ---------- Land movement -------------------------------------------------- + */ +/* + * Assign each of the plates a direction and distance (velocity) to move. + * Velocity is added to previous value, but isn't allowed to exceed + * tectonic.epochmove in any direction. + */ +int AssignDirections(void) +{ + register int i; /* plate counter */ + register Plate_t *pl; /* ptr to plates */ + float dist; /* magnitude of vector */ + register int dir; /* direction of vector */ +#define DEGtoRAD (3.1415926 / 180.0) + + for (pl = &plates[0], i = 0; i < nplates; ++i, ++pl) { + dir = myrand(360); + dist = (float)(myrand(101) + myrand(101) + myrand(101) - 150) * + (float)tectonic.epochmove/150.0; + pl->xvec += dist * cos(dir * DEGtoRAD); + pl->yvec += dist * sin(dir * DEGtoRAD); + if ((dist = hypot(pl->xvec, pl->yvec)) > (float)tectonic.epochmove) { + dist = (float)tectonic.epochmove / dist; + pl->xvec *= dist; + pl->yvec *= dist; + } + } + return 0; +} + +/* + * Set plates' dx,dy to the vector given by (i+1)*v/tectonic.epochmove - i*v/tectonic.epochmove, + * where v = plate's (xvec,yvec) vector. This arrangement makes the sum of + * (dx,dy) over an epoch equal to (xvec,yvec). + */ +int SetMovementVectors(int iter) +{ + register int i; /* plate counter */ + register Plate_t *pl; /* ptr to plates */ + + for (pl = &plates[0], i = 0; i < nplates; ++i, ++pl) { + pl->dx = (short)((iter + 1) * pl->xvec / tectonic.epochmove) - + (short)(iter * pl->xvec / tectonic.epochmove); + pl->dy = (short)((iter + 1) * pl->yvec / tectonic.epochmove) - + (short)(iter * pl->yvec / tectonic.epochmove); + } + return 0; +} + +/* + * Move each rock according to its plate's movement vector. + * Use the rock's 'next' field to keep track of rocks that pile up. + */ +int MovePlates(void) +{ + register int x, y; /* where in the world */ + register int newx, newy; /* rock's new home */ + register Rock_t *rp; /* rock pointer */ + register Rock_t *prevrp; /* rock before rp */ + register Rock_t *nextrp; /* rock after rp */ + + for (x = 0; x < tectonic.xsize; ++x) { + for (y = 0; y < tectonic.ysize; ++y) { + prevrp = NULL; + for (rp = surface[x][y]; rp; prevrp = rp, rp = nextrp) { + nextrp = rp->next; + if (rp->moved) + continue; + /* + * Figure out where to move rock. + */ + rp->moved = TRUE; + if ((rp->plate->dx == 0) && (rp->plate->dy == 0)) + continue; + newx = Wrap_x(x + rp->plate->dx); + newy = Wrap_y(y + rp->plate->dy); + /* + * Move rock. + */ + if (prevrp == NULL) + surface[x][y] = rp->next; + else + prevrp->next = rp->next; + rp->next = surface[newx][newy]; + surface[newx][newy] = rp; + } + } + } + return 0; +} + +/* + * ---------- Mountain building and the like --------------------------------- + */ + +/* + * Create land where plates have spread apart. + */ +int Rift(int x, int y) +{ + register Plate_t *pl; /* which plate new land goes with */ + register int px, py; /* offset at which to look for plate */ + register long tries; /* # of failures to find plate */ + register Rock_t *rp; /* new rock */ + Rock_t *tofree, *tmp; /* For freeing memory */ + + pl = NULL; + + /* + * Find a plate to go with. + */ + for (tries = 0; tries < 30; ++tries) { + px = Wrap_x(x + myrand(3) - 1); + py = Wrap_y(y + myrand(3) - 1); + if ((rp = surface[px][py]) != NULL) { + pl = rp->plate; + break; + } + } + /* + * Can't find a plate; start a new one. + */ + if (pl == NULL) { + if (nplates < tectonic.maxplates) + ++nplates; + pl = &plates[nplates - 1]; + pl->xvec = pl->yvec = 0.0; + pl->dx = pl->dy = 0; + pl->continent = FALSE; + } + /* + * Make rock. + */ + rp = AllocRock(pl); + rp->elev = tectonic.riftelev; + rp->minerals = tectonic.riftminerals; /* should distinguish between ocean and continental rifts!!! */ + tofree = surface[x][y]; + while(tofree != NULL) { + tmp = tofree->next; + free(tofree); + tofree = tmp; + } + surface[x][y] = rp; + return 0; +} + +/* + * Raise (or lower) land near x,y by height. + * Determine direction from x,y by rp's plate's vector. + */ +int ElevNearby(int x, int y, Rock_t *rp, short height) +{ + float h; /* hypotenuse of rp->plate->vec */ + int x2, y2; /* rock to raise */ + + h = hypot(rp->plate->xvec, rp->plate->yvec); + if (h < 0.01) { + x2 = x; + y2 = y; + } else { + x2 = Wrap_x(x + (int)(rp->plate->xvec / h + 1.5) - 1); + y2 = Wrap_y(y + (int)(rp->plate->yvec / h + 1.5) - 1); + } + if (surface[x2][y2]) + surface[x2][y2]->elev += height; + return 0; +} + +/* + * Continent hits continent; mountains are pushed up. + * New height = taller + 0.5 * shorter. The leftover height is + * distributed to other rocks in the area. + */ +int Fold(int x, int y) +{ + register Rock_t *rp0; /* first rock on list */ + register Rock_t *rp1; /* short rock */ + register Rock_t *rp2; /* tall rock */ + register short halfshort; /* half the short elevation */ + + rp0 = surface[x][y]; + if (rp0->next->elev > rp0->elev) { + rp1 = rp0; + rp2 = rp1->next; + } else { + rp2 = rp0; + rp1 = rp2->next; + } + halfshort = (rp1->elev >> 1) * tectonic.foldfactor; + ElevNearby(x, y, rp1, (halfshort + 1) >> 1); + ElevNearby(x, y, rp2, halfshort >> 1); + /* + * Combine rocks and free a rock structure. + */ + rp0->elev = rp2->elev + halfshort; + rp0->minerals = (rp1->minerals + rp2->minerals + 1) >> 1; + rp0->plate = myrand(2) ? rp1->plate : rp2->plate; + + rp1 = rp0->next; + rp0->next = rp1->next; + rp1->next = freeRockList; + freeRockList = rp1; + return 0; +} + +/* + * Create a costal range where oceanic plate is subsumed by continental + * plate. Simply add a constant height and minerals to the continent. + */ +int Subsume(int x, int y) +{ + register Rock_t *rp0; /* first rock on list */ + register Rock_t *rp1; /* underwater rock */ + register Rock_t *rp2; /* higher rock */ + + rp0 = surface[x][y]; + if (rp0->next->elev > rp0->elev) { + rp1 = rp0; + rp2 = rp1->next; + } else { + rp2 = rp0; + rp1 = rp2->next; + } + ElevNearby(x, y, rp2, tectonic.trenchheight); + if (rp2->elev < 0) + rp0->minerals = rp2->minerals + tectonic.archipminerals; + else + rp0->minerals = rp2->minerals + tectonic.subsumeminerals; + rp0->elev = rp2->elev + tectonic.subsumeheight; + rp0->plate = rp2->plate; + + rp1 = rp0->next; + rp0->next = rp1->next; + rp1->next = freeRockList; + freeRockList = rp1; + return 0; +} + +/* + * For each spot on the surface, combine rocks which were piled on top of + * each other in MovePlates() into mountains, + * and create rifts where plates have spread apart leaving nothing. + */ +int MountainBuild(void) +{ + register int x, y; /* where in the world */ + register Rock_t *rp; /* rock pointer */ + register Rock_t *rp2; /* another rock pointer */ + + for (x = 0; x < tectonic.xsize; ++x) { + for (y = 0; y < tectonic.ysize; ++y) { + rp = surface[x][y]; + if (rp == NULL) + Rift(x, y); + else while ((rp2 = rp->next) != NULL) { + if ((rp->elev > 0) && (rp2->elev > 0)) + Fold(x, y); /* land + land */ + else + Subsume(x, y); /* land or ocean + ocean */ + } + } + } + return 0; +} + +/* + * Increase elevation of hot spots. If underwater, increase minerals. + */ +int EruptHotSpots(void) +{ + register int i; /* hot spot counter */ + register Hotspot_t *hsp; /* hot spot pointer */ + register Rock_t *rp; /* rock pointer */ + + for (hsp = &hotspots[0], i = 0; i < tectonic.nhotspots; ++i, ++hsp) { + rp = surface[hsp->x][hsp->y]; + if (rp->elev <= 0) + rp->minerals += tectonic.hotspotminerals; + rp->elev += hsp->howhot; + } + return 0; +} + +/* + * Wear down mountains. Amount of wear is proportional to the average + * difference in height between a rock and the surrounding rocks, + * except very tall mountains don't erode much (no weather), + * there's more erosion around seashores (waves), and underwater + * mountains don't erode much. + * Also lower sea floors. + * Mark everything unmoved. + */ +int Erode(void) +{ + register int x, y; /* where in the world */ + register Rock_t *rp0; /* rock pointer */ + register Rock_t *rp1; /* pointer to nearby rock */ + register short elev0, elev1; /* elevation of rp0, rp1 */ + register int i, j; /* indices to nearby rocks */ + register short diff; /* difference in height, roughly */ + register long depth; /* average height of area */ + int diffplates; /* nearby rocks belonging to other plates */ + int deepplates; /* # of nearby rocks under water */ + + rp1 = NULL; + + for (x = 0; x < tectonic.xsize; ++x) { + for (y = 0; y < tectonic.ysize; ++y) { + rp0 = surface[x][y]; + elev0 = rp0->elev; + depth = elev0; + if (elev0 < 0) + elev0 = elev0 * tectonic.submergefactor; + else if (elev0 > tectonic.skyelev) + elev0 = tectonic.skyelev; + diffplates = 0; + deepplates = 0; + for (i = -1; i <= 1; ++i) { + for (j = -1; j <= 1; ++j) { /* for each surrounding rock */ + if ((i == 0) && (j == 0)) + continue; + rp1 = surface[Wrap_x(x + i)][Wrap_y(y + j)]; + elev1 = rp1->elev; + if (rp1->plate != rp0->plate) + ++diffplates; + depth += elev1; + if (elev1 < 0) { + ++deepplates; + elev1 = elev1 * tectonic.submergefactor; + } else if (elev1 > tectonic.skyelev) + elev1 = tectonic.skyelev; + /* + * Erode according to diff between elev0, elev1. + */ + diff = elev0 - elev1; + if ((elev0 <= 0 && elev1 >= 0) || + (elev0 >= 0 && elev1 <= 0)) { + diff += tectonic.waveaction; + } + diff = tectonic.erodefactor * diff + 0.5; + rp0->elevchange -= diff; + rp1->elevchange += diff; + } + } + /* + * If 7/8 of the rocks surrounding us belong to different + * plates, join the crowd. + */ + if (diffplates >= 7) { + do { + i = myrand(3) - 2; + j = myrand(3) - 2; + if (i == 0 && j == 0) + continue; + rp1 = surface[Wrap_x(x + i)][Wrap_y(y + j)]; + } while (rp1->plate == rp0->plate); + rp0->plate = rp1->plate; + } + /* + * Compute subsidence of ocean basins. + */ + if (deepplates >= (rp0->elev >= 0 ? 8 : 6)) { + rp0->elevchange -= tectonic.subsidefactor * (depth/9 - tectonic.basinelev); + } + } + } + /* + * Incorporate elevchange; mark things moved. + */ + for (x = 0; x < tectonic.xsize; ++x) { + for (y = 0; y < tectonic.ysize; ++y) { + rp0 = surface[x][y]; + rp0->moved = FALSE; + rp0->elev += rp0->elevchange; + rp0->elevchange = 0; + } + } + return 0; +} + +/* + * Give all the plates directions, move them, and see what happens. + * They may move a maximum of tectonic.epochmove cells per epoch. + */ +int Epoch(void) +{ + register int i; + + AssignDirections(); + for (i = 0; i < tectonic.epochmove; ++i) { + SetMovementVectors(i); + MovePlates(); + MountainBuild(); + EruptHotSpots(); + Erode(); + } + return 0; +} + +/************************************************************************* + This ends Mark's plate tectonic code + *************************************************************************/ + +/************************************************************************** + mapgenerator_tectonic: Use Mark Isaak's plate tectonic simulation code + to generate a realistic world. +**************************************************************************/ +static void mapgenerator_tectonic(void) +{ + register int i; + int minval=5000000; + height_map=fc_malloc (sizeof(int)*map.xsize*map.ysize); + + adjust_terrain_param(); + + /* Now, call Mark's teconic simulator to create a height map */ + + init_tec_data(); + Tec_Init(); + for(i=0;i<45;i++) + Epoch(); + + /* Convert the tectonically-synthsized map in to a freeciv height field */ + + whole_map_iterate(x, y) { + hmap(x, y) = surface[x][y]->elev; + } whole_map_iterate_end; + + /* Mark's code generates negative values; adjust + To do: Add code which uses Mark's idea of what should be land + and water to determine where the oceans go; modify Mark's + code to use map.landpercent */ + minval = 600000; + + whole_map_iterate(x, y) { + + /* Hackish code to discard some more extreme values */ + if (hmap(x, y) < -400) { + hmap(x, y) = -400; + } + if (hmap(x, y) > 10000) { + hmap(x, y) = 10000; + } + + if (hmap(x, y) < minval) { + minval = hmap(x, y); + } + } whole_map_iterate_end; + + if(minval < 0) { + whole_map_iterate(x, y) { + hmap(x, y) -= minval; + } whole_map_iterate_end; + } + + /* If we are using map generator eight, make the pure plate tectonic + land more lumpy. We do this because the plate tectonic code simulates + the Earth's processes too well to make a traditional FreeCiv game: It + makes large stretches of land and water instead of the FreeCiv + model of having many islands. + + The alleviates this by adding some lumpyness to the generated land; + this makes the continents smaller and the islands more numerous */ + + if(map.generator == 8) { + for (i=0;i<(map.xsize*map.ysize)/2;i++) { + int x,y; + rand_map_pos(&x, &y); + hmap(x, y) += myrand(4000) + myrand(2000); + } + + /* Smooth things out just a tad */ + smooth_map(); + smooth_map(); + } + + /* Find the minval and maxval now that we have made a plate tectonic + simulated map */ + + whole_map_iterate(x, y) { + if (hmap(x, y) > maxval) + maxval = hmap(x, y); + if (hmap(x, y) < minval) + minval = hmap(x, y); + } whole_map_iterate_end; + + maxval-=minval; + adjust_map(minval); + + /* based on map.landpercent, separate land from water */ + make_land(maxval / 5); + free(height_map); height_map = NULL; } @@ -1394,7 +2390,7 @@ rand_map_pos(&x, &y); l=myrand(6); if (map_get_terrain(x, y)!=T_OCEAN && - ( map_get_terrain(x, y)!=T_ARCTIC || l<3 ) + ( map_get_terrain(x, y)!=T_ARCTIC ) ) { if (!is_hut_close(x,y)) { number--; @@ -2208,7 +3204,271 @@ maxval -= minval; adjust_map(minval); - make_land(); + make_land(maxval); free(height_map); height_map = NULL; } + +static int is_ocean(int l) +{ + return (l == T_OCEAN); +} + +static int land_terrain(int x, int y) +{ + return !is_ocean(map_get_terrain(x,y)); +} + +static int border_score(int x, int y) +{ + int adj_score = 2; + int diag_score = 1; + int score = 0; + score += land_terrain(x-1,y) ? adj_score : 0; + score += land_terrain(x+1,y) ? adj_score : 0; + score += land_terrain(x,y-1) ? adj_score : 0; + score += land_terrain(x,y+1) ? adj_score : 0; + score += land_terrain(x-1,y-1) ? diag_score : 0; + score += land_terrain(x+1,y-1) ? diag_score : 0; + score += land_terrain(x-1,y+1) ? diag_score : 0; + score += land_terrain(x+1,y+1) ? diag_score : 0; + return score; +} + +static int random_new_land(int x, int y) +{ + int score; + int random; + if(land_terrain(x, y)) { + return T_PLAINS; + } + score = border_score(x, y); + random = myrand(4*2+4*1); + return random + 1 > score ? T_OCEAN : T_GRASSLAND; + +} + +/* Creates a peninsula and put the player's starting position + on it; this is used by map generator 6 */ +static void create_peninsula(int x, int y,int player_number, + int width, int height,int direction, + int remaining_count) +{ + int cx, cy; + + cx = x+width/2; + for(cy = y; cy != y + (height + 1)*direction; + cy += direction) { + map_set_terrain(cx, cy, T_GRASSLAND); + map_set_continent(cx, cy, 1); + } + remaining_count -= height; /* account for the already added strip */ + cy = y; + for(cx = x + width/2 - 2; cx <= x + width/2 + 2; cx ++) { + map_set_terrain(cx, cy, T_GRASSLAND); + map_set_continent(cx, cy, 1); + } + remaining_count -= 4; /* account for extra 4 (not 5 because that would + double count the one already done by height strip.*/ + + while (remaining_count > 0) { + for(cx = x; cx < x+width; cx++) { + for(cy = y; cy != y + (height + 1)*direction; cy += direction) { + int new_terrain = random_new_land(cx, cy); + if(new_terrain == T_GRASSLAND){ + remaining_count--; + map_set_terrain(cx, cy, T_GRASSLAND); + map_set_continent(cx, cy, 1); + hmap(cx, cy) = 20 * (cx - x) * (width - (cx - x)) + myrand(80) - 40; + } + if(remaining_count <= 0) { + goto done_with_peninsula; + } + } + } + } + + done_with_peninsula: + + map.start_positions[player_number].x = x+width/2; + map.start_positions[player_number].y = y; +} + +/* This generator creates a map with one penisula for each + player and an isthmus between. It creates a central + ocean and puts the peninsulas around the edges. It is + intented for quicker games. Should look something like this: + ***************************** + ** ***** ***** ***** ** + * *** *** *** * + * * + * * + * *** *** * + ** ***** ***** ** + ***************************** + */ +static void mapgenerator6(void) +{ + int peninsulas = game.nplayers; + int peninsulas_on_one_side = (peninsulas + 1)/2; + int isthmus_width = 10; + int peninsula_separation = 5; + int peninsula_width = + (map.xsize - isthmus_width - peninsula_separation) + /(peninsulas_on_one_side) - peninsula_separation; + /* if landpercent <= 50, then make shorter peninsulas */ + int peninsula_height = (map.landpercent <= 50) + ? map.ysize/3 + : (map.ysize*2)/5; + int continent_percent = (map.landpercent <= 50) + ? (map.landpercent * 3)/2 + : (map.landpercent * 5)/4; + int i, x, y; + int polar_height = 3; + int remaining_count = + MIN(isthmus_width * (map.ysize - polar_height*2), + ((isthmus_width+peninsula_separation) * (map.ysize - polar_height*2) + * continent_percent)/100); + + height_map = fc_malloc(sizeof(int) * map.xsize * map.ysize); + + /* initialize everything to ocean */ + for (y = 0 ; y < map.ysize ; y++) + for (x = 0 ; x < map.xsize ; x++) { + map_set_terrain(x, y, T_OCEAN); + map_set_continent(x, y, 0); + hmap(x, y) = 0; + } + + /* create polar regions */ + for (x = 0 ; x < map.xsize; x++) { + for (y = 0; y < polar_height; y++) { + int rand_num = myrand(9); + map_set_terrain(x, y, rand_num > 7 ? T_ARCTIC : + (rand_num < 2 ? T_MOUNTAINS : T_TUNDRA)); + map_set_continent(x, y, 1); + rand_num = myrand(9); + map_set_terrain(x, map.ysize-1-y, rand_num > 7 ? T_ARCTIC : + (rand_num < 2 ? T_MOUNTAINS : T_TUNDRA)); + map_set_continent(x, map.ysize-1-y, 1); + } + } + + /* build polar regions road */ + for (x = 0 ; x < map.xsize; x++) { + y = polar_height-1; + if(map_build_road_time(x,y-1) < map_build_road_time(x,y)) + { + map_set_special(x,y-1,S_ROAD); + } else { + map_set_special(x,y,S_ROAD); + } + y = map.ysize-polar_height; + if(map_build_road_time(x,y+1) < map_build_road_time(x,y)) + { + map_set_special(x,y+1,S_ROAD); + } else { + map_set_special(x,y,S_ROAD); + } + } + + map.num_continents = 1; + + /* create isthmus centeral strip */ + x = isthmus_width/2; + for (y = polar_height; y < map.ysize - polar_height; y++) { + map_set_terrain(x, y, T_GRASSLAND); + map_set_continent(x, y, 1); + hmap(x, y) = 100 * x * (isthmus_width - x) + (myrand(400) - 200); + } + + remaining_count -= (map.ysize - 2*polar_height) * 1; + + /* add additional isthmus area randomly */ + while(remaining_count > 0) { + for (y = polar_height; y < map.ysize/2; y++) { + for (x = 0; x < isthmus_width; x++) { + int new_terrain = random_new_land(x, y); + if(new_terrain == T_GRASSLAND){ + remaining_count--; + map_set_terrain(x, y, T_GRASSLAND); + map_set_continent(x, y, 1); + hmap(x, y) = 100 * x * (isthmus_width - x) + (myrand(400) - 200); + } + if(remaining_count <= 0) { + goto done_with_isthmus; + } + } + } + + for (y = map.ysize - polar_height - 1; y >= map.ysize/2; y--) { + for (x = 0; x < isthmus_width; x++) { + int new_terrain = random_new_land(x, y); + if(new_terrain == T_GRASSLAND){ + remaining_count--; + map_set_terrain(x, y, T_GRASSLAND); + map_set_continent(x, y, 1); + hmap(x, y) = 100 * x * (isthmus_width - x) + (myrand(400) - 200); + } + if(remaining_count <= 0) { + goto done_with_isthmus; + } + } + } + } + done_with_isthmus: + + /* setup peninsulas */ + for(i = 0; i < game.nplayers; i++) { + /* direction is the direction to increment from the x and y location */ + int direction = (i < peninsulas_on_one_side) ? -1 : 1; + int index = (direction == -1) ? i : i - peninsulas_on_one_side; + int width = (continent_percent < 95) + ? peninsula_width + : peninsula_width + peninsula_separation - 1;/*Give more room */ + int height = peninsula_height-polar_height; + int peninsula_remaining_count = + MIN(width*height, + ((width+peninsula_separation)*height*continent_percent)/100); + x = index * (peninsula_width + peninsula_separation) + + isthmus_width + peninsula_separation; + y = (direction == -1) + ? peninsula_height + : map.ysize - 1 - peninsula_height; + create_peninsula(x,y,i,width,height,direction,peninsula_remaining_count); + } + + map.num_start_positions = game.nplayers; + + /* setup terrain */ + make_mountains(1600); + make_swamps(); + make_forests(); + make_deserts(); + make_plains(); + make_fair(); + make_rivers(); + + /* create isthmus road */ + { + int last_x, middle_x = isthmus_width/2; + last_x = middle_x; + for (y = polar_height - 1; y < map.ysize - polar_height + 1; y++) { + int best_x = middle_x; + int min_build = 100; + for(x = MAX(last_x - 1, middle_x - 1); + x != MIN(last_x + 1,middle_x + 1) + 1; x++) { + if(land_terrain(x,y) && map_build_road_time(x,y) < min_build) { + best_x = x; + min_build = map_build_road_time(x,y); + } + } + map_set_special(best_x,y,S_ROAD); + last_x = best_x; + } + } + + + free(height_map); + +} diff -urw freeciv-1.14.0/server/mapgen.h freeciv/server/mapgen.h --- freeciv-1.14.0/server/mapgen.h 2002-02-05 14:05:51.000000000 -0500 +++ freeciv/server/mapgen.h 2003-03-28 12:19:44.000000000 -0500 @@ -15,7 +15,7 @@ void assign_continent_numbers(void); void map_fractal_generate(void); -void create_start_positions(void); +int create_start_positions(void); void adjust_terrain_param(void); #endif /* FC__MAPGEN_H */ diff -urw freeciv-1.14.0/server/savegame.c freeciv/server/savegame.c --- freeciv-1.14.0/server/savegame.c 2002-12-08 18:32:30.000000000 -0500 +++ freeciv/server/savegame.c 2003-04-02 18:45:39.000000000 -0500 @@ -1862,6 +1862,15 @@ secfile_lookup_int_default(file, game.allowed_city_names, "game.allowed_city_names"); + game.slowai_tech = secfile_lookup_int_default(file, + GAME_DEFAULT_SLOWAI_TECH, "game.slowai_tech"); + game.slowai_grow = secfile_lookup_int_default(file, + GAME_DEFAULT_SLOWAI_GROW, "game.slowai_grow"); + game.check_isles = secfile_lookup_int_default(file, + GAME_DEFAULT_CHECK_ISLES, "game.check_isles"); + game.best_isles = secfile_lookup_bool_default(file, + GAME_DEFAULT_BEST_ISLES, "game.best_isles"); + if(game.civstyle == 1) { string = "civ1"; } else { @@ -1989,17 +1998,15 @@ && secfile_lookup_bool_default(file, TRUE, "game.save_random") && game.load_options.load_random) { RANDOM_STATE rstate; - rstate.j = secfile_lookup_int(file,"random.index_J"); - rstate.k = secfile_lookup_int(file,"random.index_K"); - rstate.x = secfile_lookup_int(file,"random.index_X"); - for(i=0;i<8;i++) { - char name[20]; - my_snprintf(name, sizeof(name), "random.table%d",i); - string=secfile_lookup_str(file,name); - sscanf(string,"%8x %8x %8x %8x %8x %8x %8x", &rstate.v[7*i], - &rstate.v[7*i+1], &rstate.v[7*i+2], &rstate.v[7*i+3], - &rstate.v[7*i+4], &rstate.v[7*i+5], &rstate.v[7*i+6]); - } + rstate.dice_counter = secfile_lookup_int(file,"random.index_dice_counter"); + rstate.r_place = secfile_lookup_int(file,"random.r_place"); + string=secfile_lookup_str(file,"random.table"); + sscanf(string, + "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + &rstate.v[0], &rstate.v[1], &rstate.v[2], &rstate.v[3], + &rstate.v[4], &rstate.v[5], &rstate.v[6], &rstate.v[7], + &rstate.v[8], &rstate.v[9], &rstate.v[10], &rstate.v[11], + &rstate.v[12], &rstate.v[13], &rstate.v[14], &rstate.v[15]); rstate.is_init = TRUE; set_myrand_state(rstate); } else { @@ -2185,6 +2192,11 @@ secfile_insert_int(file, game.watchtower_extra_vision, "game.watchtower_extra_vision"); secfile_insert_int(file, game.allowed_city_names, "game.allowed_city_names"); + secfile_insert_int(file, game.slowai_tech, "game.slowai_tech"); + secfile_insert_int(file, game.slowai_grow, "game.slowai_grow"); + secfile_insert_int(file, game.check_isles, "game.check_isles"); + secfile_insert_bool(file, game.best_isles, "game.best_isles"); + if (TRUE) { /* Now always save these, so the server options reflect the * actual values used at the start of the game. @@ -2212,23 +2224,19 @@ secfile_insert_int(file, game.randseed, "game.randseed"); if (myrand_is_init() && game.save_options.save_random) { + char vec[33]; RANDOM_STATE rstate = get_myrand_state(); secfile_insert_int(file, 1, "game.save_random"); assert(rstate.is_init); - secfile_insert_int(file, rstate.j, "random.index_J"); - secfile_insert_int(file, rstate.k, "random.index_K"); - secfile_insert_int(file, rstate.x, "random.index_X"); - - for(i=0;i<8;i++) { - char name[20], vec[100]; - my_snprintf(name, sizeof(name), "random.table%d", i); - my_snprintf(vec, sizeof(vec), - "%8x %8x %8x %8x %8x %8x %8x", rstate.v[7*i], - rstate.v[7*i+1], rstate.v[7*i+2], rstate.v[7*i+3], - rstate.v[7*i+4], rstate.v[7*i+5], rstate.v[7*i+6]); - secfile_insert_str(file, vec, name); + secfile_insert_int(file, rstate.dice_counter, "random.index_dice_counter"); + secfile_insert_int(file, rstate.r_place, "random.r_place"); + + vec[0]='\0'; + for(i=0;i<16;i++) { + my_snprintf(vec, sizeof(vec),"%s%02x",vec,rstate.v[i]); } + secfile_insert_str(file, vec, "random.table"); } else { secfile_insert_int(file, 0, "game.save_random"); } diff -urw freeciv-1.14.0/server/settlers.c freeciv/server/settlers.c --- freeciv-1.14.0/server/settlers.c 2002-11-15 22:14:22.000000000 -0500 +++ freeciv/server/settlers.c 2003-04-02 18:46:46.000000000 -0500 @@ -34,6 +34,7 @@ #include "aiunit.h" #include "aidata.h" +#include "rand.h" #include "settlers.h" /* negative: in_city_radius, 0: unassigned, positive: city_des */ @@ -1262,8 +1263,8 @@ /* Decide whether to build a new city: * if so, modify: gx, gy, best_newv, best_act */ - if (unit_flag(punit, F_CITIES) && - pplayer->ai.control) { + if (unit_flag(punit, F_CITIES) && pplayer->ai.control && + (myrand(101) <= game.slowai_grow)) { int nx, ny; int want = evaluate_city_building(punit, &nx, &ny, &ferryboat); diff -urw freeciv-1.14.0/server/srv_main.c freeciv/server/srv_main.c --- freeciv-1.14.0/server/srv_main.c 2002-10-11 19:35:50.000000000 -0400 +++ freeciv/server/srv_main.c 2003-04-02 18:50:50.000000000 -0500 @@ -1798,6 +1798,7 @@ void srv_main(void) { int i; + int is_good_map = 1; /* make sure it's initialized */ if (!has_been_srv_init) { @@ -1944,6 +1945,13 @@ if(game.is_new_game) generate_ai_players(); + if (game.check_isles == 1) + game.check_isles = game.nplayers; + + /* This is a loop which will recreate the map in case the map + generator decides the generated map is not good enough */ + do { + /* if we have a tile map, and map.generator==0, call map_fractal_generate anyway, to make the specials and huts */ if(map_is_empty() || (map.generator == 0 && game.is_new_game)) @@ -1975,10 +1983,23 @@ /* we don't want random start positions in a scenario which already provides them. -- Gudy */ if(map.num_start_positions==0) { - create_start_positions(); + is_good_map = create_start_positions(); } } + /* we aren't verifying, ensure a positive return. */ + if (!game.check_isles) + is_good_map = 1; + + /* Save the whales, free the mallocs */ + if(is_good_map == 0) { + players_iterate(pplayer) { + free(pplayer->private_map); + } players_iterate_end; + } + + } while(is_good_map == 0); + initialize_move_costs(); /* this may be the wrong place to do this */ generate_minimap(); /* for city_desire; saves a lot of calculations */ diff -urw freeciv-1.14.0/server/stdinhand.c freeciv/server/stdinhand.c --- freeciv-1.14.0/server/stdinhand.c 2002-11-15 22:14:22.000000000 -0500 +++ freeciv/server/stdinhand.c 2003-04-02 18:54:43.000000000 -0500 @@ -239,7 +239,13 @@ "additional\n" " smaller islands.\n" "5 = one or more large earthlike continents with some scatter.\n" - "Note: values 2,3 and 4 generate \"fairer\" (but more boring) " + "6 = equally sized peninsulas with one player each surrounding\n" + " an inland sea.\n" + "7 = generates maps based on simulated tectonic plates algorithims\n" + " which produces more realistic looking maps.\n" + "8 = same as 7, but breaks the islands apart better to work with\n" + " the seperate islands setting.\n" + "Note: values 2,3,4 and 6 generate \"fairer\" (but more boring) " "maps.\n" "(Zero indicates a scenario map.)"), NULL, MAP_MIN_GENERATOR, MAP_MAX_GENERATOR, MAP_DEFAULT_GENERATOR) @@ -820,6 +826,37 @@ "40=debuging logging."), NULL, 0, 40, 20) + GEN_INT("slowaitech", game.slowai_tech, SSET_RULES_FLEXIBLE, SSET_SERVER_ONLY, + N_("Adjust AI tech advancement"), + N_("This value determines how much slower the AI will learn" + "new technologies compared to human players. Setting a value " + "greater then 1 will slow their advancement that many times."), NULL, + GAME_MIN_SLOWAI_TECH, GAME_MAX_SLOWAI_TECH, GAME_DEFAULT_SLOWAI_TECH) + + GEN_INT("slowaigrowth", game.slowai_grow, SSET_RULES_FLEXIBLE, SSET_SERVER_ONLY, + N_("Adjust city growth by %"), + N_("This value determines how much slower the AI will expand in" + "relation to human players. Setting a percent value under " + "100 will cause them to expand at about the specified rate " + "as compared to normal AI expansion."), NULL, + GAME_MIN_SLOWAI_GROW, GAME_MAX_SLOWAI_GROW, GAME_DEFAULT_SLOWAI_GROW) + + GEN_INT("checkisles", game.check_isles, SSET_MAP_GEN, SSET_SERVER_ONLY, + N_("Try to create a number of islands to start."), + N_("Setting this causes the map generator to discard maps that " + "create less than this number of valid islands. A value of 1 " + "means that all players get their own island."), NULL, + GAME_MIN_CHECK_ISLES, GAME_MAX_CHECK_ISLES, GAME_DEFAULT_CHECK_ISLES) + + GEN_BOOL("bestisles", game.best_isles, SSET_MAP_GEN, SSET_SERVER_ONLY, + N_("Players get best islands"), + N_("This enables algorithims that shuffle the starting positions " + "such that human players will get the best islands and AI the " + "worse ones. This is mostly useful when used with the " + "\"checkisles\" option, otherwise humans will be lumped " + "together on the better isles and AI grouped on the worse " + "ones."), NULL, GAME_DEFAULT_CHECK_ISLES) + GEN_END };