mirror of
https://git.zap.org.au/git/trader.git
synced 2024-09-01 17:14:15 -04:00
308 lines
9.2 KiB
C
308 lines
9.2 KiB
C
/************************************************************************
|
|
* *
|
|
* Star Traders: A Game of Interstellar Trading *
|
|
* Copyright (C) 1990-2011, John Zaitseff *
|
|
* *
|
|
************************************************************************/
|
|
|
|
/*
|
|
Author: John Zaitseff <J.Zaitseff@zap.org.au>
|
|
$Id$
|
|
|
|
This file, utils.c, contains the implementation of various utility
|
|
function for Star Traders.
|
|
|
|
|
|
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 3 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
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see http://www.gnu.org/licenses/.
|
|
*/
|
|
|
|
|
|
#include "system.h"
|
|
#include "utils.h"
|
|
#include "intf.h"
|
|
|
|
|
|
/************************************************************************
|
|
* Module variables *
|
|
************************************************************************/
|
|
|
|
static char *program_name_str = NULL; // Canonical program name
|
|
static char *home_directory_str = NULL; // Full pathname to home
|
|
static char *data_directory_str = NULL; // Writable data dir pathname
|
|
|
|
|
|
/************************************************************************
|
|
* Utility function definitions *
|
|
************************************************************************/
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
Function: init_program_name - Make the program name "canonical"
|
|
Arguments: argv - Same as passed to main()
|
|
Returns: (nothing)
|
|
|
|
This function modifies the argv[0] pointer to eliminate the leading
|
|
path name from the program name. In other words, it strips any leading
|
|
directories and leaves just the base name of the program. It also
|
|
assigns the module variable "program_name_str".
|
|
*/
|
|
|
|
void init_program_name (char *argv[])
|
|
{
|
|
if ((argv == NULL) || (argv[0] == NULL) || (*(argv[0]) == '\0')) {
|
|
program_name_str = PACKAGE;
|
|
} else {
|
|
char *p = strrchr(argv[0], '/');
|
|
|
|
if ((p != NULL) && (*++p != '\0')) {
|
|
argv[0] = p;
|
|
}
|
|
|
|
program_name_str = argv[0];
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
Function: program_name - Return the canonical program name
|
|
Arguments: (none)
|
|
Returns: const char * - Pointer to program name
|
|
|
|
This function returns the canonical program name (the program name as
|
|
invoked on the command line, without any leading pathname). NULL
|
|
should never be returned.
|
|
*/
|
|
|
|
const char *program_name (void)
|
|
{
|
|
if (program_name_str == NULL) {
|
|
init_program_name(NULL);
|
|
}
|
|
|
|
return program_name_str;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
Function: home_directory - Return home directory pathname
|
|
Arguments: (none)
|
|
Returns: const char * - Pointer to home directory
|
|
|
|
This function returns the full pathname to the user's home directory,
|
|
using the HOME environment variable. Note that the existance or
|
|
writability of this pathname is NOT checked by this function. NULL is
|
|
returned if the home directory cannot be determined.
|
|
*/
|
|
|
|
const char *home_directory (void)
|
|
{
|
|
if (home_directory_str == NULL) {
|
|
// Use the HOME environment variable where possible
|
|
char *p = getenv("HOME");
|
|
if ((p != NULL) && (*p != '\0')) {
|
|
home_directory_str = strdup(p);
|
|
}
|
|
}
|
|
|
|
return home_directory_str;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
Function: data_directory - Return writable data directory pathname
|
|
Arguments: (none)
|
|
Returns: const char * - Pointer to data directory
|
|
|
|
This function returns the full pathname to a writable subdirectory
|
|
within the user's home directory. Essentially, home_directory() + "/."
|
|
+ program_name() is returned. Note that this path is NOT created by
|
|
this function, nor is the writability of this path checked. NULL is
|
|
returned if this path cannot be determined.
|
|
*/
|
|
|
|
const char *data_directory (void)
|
|
{
|
|
if (data_directory_str == NULL) {
|
|
const char *name = program_name();
|
|
const char *home = home_directory();
|
|
if ((name != NULL) && (home != NULL)) {
|
|
char *p = malloc(strlen(home) + strlen(name) + 3);
|
|
if (p != NULL) {
|
|
strcpy(p, home);
|
|
strcat(p, "/.");
|
|
strcat(p, name);
|
|
data_directory_str = p;
|
|
}
|
|
}
|
|
}
|
|
|
|
return data_directory_str;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
Function: game_filename - Convert an integer to a game filename
|
|
Arguments: game_num - Game number (1-9) as an integer
|
|
Returns: char * - Pointer to game filename string
|
|
|
|
This function returns the full game filename as a malloc()ed string.
|
|
If game_num is between 1 and 9 inclusive, the string returned is in the
|
|
form data_directory() + "/" + GAME_FILENAME(game_num). If game_num is
|
|
any other integer, NULL is returned.
|
|
*/
|
|
|
|
char *game_filename (const int game_num)
|
|
{
|
|
char buf[GAME_FILENAME_BUFSIZE]; // Buffer for part of filename
|
|
const char *dd; // Data directory
|
|
|
|
|
|
if ((game_num < 1) || (game_num > 9)) {
|
|
return NULL;
|
|
}
|
|
|
|
dd = data_directory();
|
|
snprintf(buf, GAME_FILENAME_BUFSIZE, GAME_FILENAME_PROTO, game_num);
|
|
|
|
if (dd == NULL) {
|
|
char *p = malloc(strlen(buf) + 1);
|
|
if (p != NULL) {
|
|
strcpy(p, buf);
|
|
}
|
|
return p;
|
|
} else {
|
|
char *p = malloc(strlen(dd) + strlen(buf) + 2);
|
|
if (p != NULL) {
|
|
strcpy(p, dd);
|
|
strcat(p, "/");
|
|
strcat(p, buf);
|
|
}
|
|
return p;
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
Function: err_exit - Print an error and exit
|
|
Arguments: format - printf()-like format of error message
|
|
... - printf()-like arguments
|
|
Returns: (does not return)
|
|
|
|
This function closes all curses windows, prints the name of the program
|
|
and the error message to stderr (using format and following arguments
|
|
as if passed to printf()) and exits with error code EXIT_FAILURE. The
|
|
format supplied does NOT need to supply the program name nor the
|
|
trailing end-line character. The format should not be NULL; user-
|
|
supplied strings should ALWAYS be printed using "%s" as the format (and
|
|
with the user string as a second argument), NOT passed in as the format
|
|
itself.
|
|
*/
|
|
|
|
void err_exit (const char *format, ...)
|
|
{
|
|
va_list args;
|
|
|
|
|
|
end_screen();
|
|
|
|
fprintf(stderr, "%s: ", program_name());
|
|
va_start(args, format);
|
|
vfprintf(stderr, format, args);
|
|
va_end(args);
|
|
fputs("\n", stderr);
|
|
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
Function: errno_exit - Print an error (using errno) and exit
|
|
Arguments: format - printf()-like format of error message
|
|
... - printf()-like arguments
|
|
Returns: (does not return)
|
|
|
|
This function closes all curses windows, prints the name of the
|
|
program, the error message (using format and following arguments as if
|
|
passed to printf()) and the string corresponding to errno to stderr,
|
|
then exits with error code EXIT_FAILURE. The format supplied does NOT
|
|
need to supply the program name, any colons nor the trailing end-line
|
|
character. The format may be NULL if no intermediate message is
|
|
needed.
|
|
*/
|
|
|
|
void errno_exit (const char *format, ...)
|
|
{
|
|
va_list args;
|
|
int saved_errno = errno;
|
|
|
|
|
|
end_screen();
|
|
|
|
fprintf(stderr, "%s: ", program_name());
|
|
if (format != NULL) {
|
|
va_start(args, format);
|
|
vfprintf(stderr, format, args);
|
|
va_end(args);
|
|
fputs(": ", stderr);
|
|
}
|
|
fprintf(stderr, "%s\n", strerror(saved_errno));
|
|
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
Function: init_rand - Initialise the random number generator
|
|
Arguments: (none)
|
|
Returns: (nothing)
|
|
|
|
This function initialises the pseudo-random number generator.
|
|
*/
|
|
|
|
void init_rand (void)
|
|
{
|
|
time_t curtime = time(NULL); // NB: time_t may be larger than long int
|
|
srand48((long int) curtime);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
Function: randf - Return a random number between 0.0 and 1.0
|
|
Arguments: (none)
|
|
Returns: double - The random number
|
|
|
|
This function returns a pseudo-random number between 0.0 (inclusive)
|
|
and 1.0 (not inclusive) as a floating-point number.
|
|
*/
|
|
|
|
extern double randf (void)
|
|
{
|
|
return drand48();
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
Function: randi - Return a random number between 0 and limit
|
|
Arguments: limit - Upper limit of random number
|
|
Returns: int - The random number
|
|
|
|
This function returns a pseudo-random number between 0 (inclusive) and
|
|
limit (not inclusive) as an integer.
|
|
*/
|
|
|
|
extern int randi (int limit)
|
|
{
|
|
return randf() * (double) limit;
|
|
}
|