/*******************************************************************************
* FSCTOOL.C *
* - Declarations and functions for Free Space Colonization tools *
* *
* FREE SPACE COLONISATION *
* (c)2002 - 2017 Paul Mueller <muellerp61@bluewin.ch> *
* *
* 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 of the License, 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
*******************************************************************************/
/*******************************************************************************
* INCLUDES *
*******************************************************************************/
#include <stdlib.h> /* rand() */
#include <string.h> /* strchr() */
#include <time.h>
#include "fsctool.h" /* own header */
/*******************************************************************************
* CODE *
*******************************************************************************/
/* ========================================================================== */
/* ======================== PUBLIC FUNCTIONS ============================= */
/* ========================================================================== */
/*
* Name:
* fsctool_rand_set_seed
* Description:
* Sets the seed for the random generator. If 'seed' is 0, then the
* current system time is used as seed.
* Input:
* Upper bound
*/
void fsctool_rand_set_seed(int seed)
{
if(! seed)
{
seed = time(NULL);
}
srand(seed);
}
/*
* Name:
* fsctool_rand_no
* Description:
* Returns a random number between 1 and (num).
* Input:
* Upper bound
* Output:
* Generated random number (1 .. Upper Bound)
*/
int fsctool_rand_no(int num)
{
if(num < 2)
{
if(num < 0)
{
num = 0;
}
return num;
}
return ((rand() % num) + 1);
}
/*
* Name:
* fsctool_rand
* Description:
* Returns a random number between 1 and RAND_MAX.
* Input:
* None
* Output:
* Generated random number (1 .. RAND_MAX)
*/
int fsctool_rand(void)
{
return rand();
}
/*
* Name:
* fsctool_haschance_percent
* Description:
* Returns != 0 if given value is <= fsctool_rand_no(100)
* Input:
* chance: Chance in percent
* Output:
* Chance true / false
*/
int fsctool_haschance_percent(int chance)
{
if(chance >= 100)
{
return 1;
}
if(chance <= fsctool_rand_no(100))
{
return 1;
}
return 0;
}
/*
* Name:
* fsctool_roll_dice
* Description:
* Rolls a dice 'numthrow' times and adds the 'base' value.
* Input:
* dice[4]: [0] Base-Value to add to rolled dice
* [1] Number of sides the dice has
* [2] Number of times the dice is rolled
* Returns:
* Pointer on string with given number
*/
int fsctool_roll_dice(char dice[4])
{
int result;
result = 0;
do
{
/* At least one time... */
result += fsctool_rand_no(dice[1]);
/* Reduce the number of rolls */
dice[3]--;
}
while(dice[3] > 0);
return (result + dice[0]);
}
/*
* Name:
* fsctool_rand_range
* Description:
* Rolls a dice 'numthrow' times and adds the 'base' value.
* Input:
* range: Between this two numbers
* Returns:
* Pointer on string with given number
*/
char fsctool_rand_range(char range[2])
{
int result, diff;
result = 0;
diff = range[1] - range[0];
if(diff > 0)
{
result = fsctool_rand_no(diff + 1) - 1;
return (char)(result + range[0]);
}
return range[0];
}
/*
* Name:
* fsctool_mix_numbers
* Description:
* Mixes the given numbers in given list. List must have
* a size of 'num_element' + 1 to key_code end of list with a 0.
* Input:
* list *: List of numbers to mix (max = 128)
* num_element: Number of elements in list
*/
void fsctool_mix_numbers(char *list, int num_element)
{
char mixed_list[132];
int mix_count, index;
if(num_element < 2)
{
/* Nothing to mix */
return;
}
if(num_element > 128)
{
num_element = 128;
}
/* Sort the given numbers in random way */
mixed_list[0] = 0;
mix_count = 0;
while(num_element > 0)
{
index = fsctool_rand_no(num_element);
mixed_list[mix_count] = list[index];
num_element--;
mix_count++;
}
mixed_list[mix_count] = 0;
/* Now copy the moxes list back */
memcpy(list, mixed_list, (num_element + 1) * sizeof(char));
}
/* ===== Tools for list management ===== */
/*
* Name:
* fsctool_list_movecursor
* Description:
* Moves the cursor in given list in given direction. Does a wraparound,
* if needed. It's assumed that the list is a 0-terminated list of
* integer numbers.
* Input:
* plist *: Pointer on list with values
* pcursor *: Pointer on cursor to move
* pvalue *: Pointer on where to return the value at given cursor position
* dir: Direction of cursor movement
* Output:
* Cursor position has changed, new value
*/
int fsctool_list_movecursor(int *plist, int *pcursor, int *pvalue, int dir)
{
int newcursor;
int cur_moved;
newcursor = *pcursor;
cur_moved = 0;
if(plist[1] > 0)
{
/* If there is more then one element in this list... */
if(dir > 0)
{
newcursor++;
if (! plist[newcursor])
{
/* End of list reached -- Do wrap around to first element */
newcursor = 0; /* */
}
}
else if(dir < 0)
{
newcursor--;
if(newcursor < 0) {
/* Wrap around -- Get the last element in list */
/* */
newcursor = 0;
while(plist[newcursor + 1] > 0)
{
newcursor++;
}
}
}
if (*pcursor != newcursor)
{
/* Cursor has moved */
cur_moved = 1;
}
*pcursor = newcursor;
}
*pvalue = plist[newcursor];
return cur_moved;
}
/*
* Name:
* fsctool_list_find_element
* Description:
* Does a lookup in the list for element with given number.
* If the element is found, the output is the index of the element
* in given list.
* In all other cases it 's 0.
* Input:
* plist *: Pointer on list with values
* element_no: Number of element to look for
* Output:
* < 0: Element not found
*/
int fsctool_list_find_element(int *plist, int element_no)
{
int cursor;
cursor = 0;
while(plist[cursor] > 0)
{
if(plist[cursor] == element_no)
{
return cursor;
}
cursor++;
}
return -1;
}
/*
* Name:
* fsctool_list_remove_element
* Description:
* Does a lookup in the list for element with given number.
* If the element is found, the output is the index of the element
* in given list.
* In all other cases it 's 0.
* Input:
* plist *: Pointer on list with values
* element_no: Number of element to look for
* Output:
* Element removed, new cursor
*/
int fsctool_list_remove_element(int *plist, int element_no)
{
int found_pos;
found_pos = fsctool_list_find_element(plist, element_no);
/* Check it again */
if(found_pos >= 0)
{
/* Found this element, remove it */
while(plist[found_pos] > 0)
{
plist[found_pos] = plist[found_pos + 1];
found_pos++;
}
/* Element could be removed */
return 1;
}
/* Element not found */
return 0;
}
/* ========= Other tools ====== */
/*
* Name:
* fsctool_str_fromlist
* Description:
* Returns the string with the given number from the given list.
* Specification of list:
* - There has to be a 0 at the very first position of the liststring.
* - The end of the list string has to be signed by two zeros.
*
* If the given number is less 0 or bigger then the strings available
* in the given list, a pointer on the first string in list is returned.
* Input:
* str_list *: Pointer on string made from strings
* str_no: Number of string to return
* Returns:
* Pointer on string with given number
*/
char *fsctool_str_fromlist(char *str_list, int str_no)
{
char *pstr;
pstr = str_list;
while(str_no > 0)
{
pstr = strchr(pstr, 0);
str_no--;
pstr++; /* Skip leading break-char of string */
if (*pstr == 0)
{
return pstr;
}
}
return pstr;
}
/*
* Name:
* fsctool_expand_bits2numbers
* Description:
* Returns for every bit set in 'pbits' its position as number
* Input:
* pbits *: Pointer on a string with bits to expand
* pnumbers *: Where to return the numbers
* num_bits: Number of bits in 'pbits' ==> 'numbers'
*/
void fsctool_expand_bits2numbers(char *pbits, int *pnumbers, int num_bits)
{
int bit_bytes, i, bit_no, number_base;
char bit_mask;
bit_bytes = (num_bits / 8);
if((bit_bytes % 8) > 0)
{
bit_bytes++;
}
for(i = 0, number_base = 0; i < bit_bytes; i++, number_base += 8)
{
for(bit_no = 0, bit_mask = 0x01; bit_no < 8; bit_mask <<= 1)
{
if(pbits[i] & bit_mask)
{
*pnumbers = number_base + bit_no;
}
}
}
/* Sign end of list */
*pnumbers = 0;
}
/*
* Name:
* fsctool_shrink_numbers2bits
* Description:
* Returns for every bit set in 'pbits' its position as number
* Input:
* pbits *: Pointer on a string with bits to expand
* pnumbers *: Where to return the numbers
* num_bits: Number of bits in 'pbits' ==> 'numbers'
*/
void fsctool_shrink_numbers2bits(int *pnumbers, char *pbits, int num_bits)
{
int bit_bytes;
bit_bytes = (num_bits / 8);
if((bit_bytes % 8) > 0)
{
bit_bytes++;
}
/* Clear the target buffer */
memset(pbits, 0, (bit_bytes * sizeof(char)));
while(*pnumbers)
{
pbits[*pnumbers >> 3] |= ((unsigned char)(0x01 << (char)(*pnumbers & 0x07)));
pnumbers++;
}
}