dslinux/user/bitchx/dll/acro Makefile.in README TODO acro.c acro.h acro.sh

stsp stsp at user.in-berlin.de
Sun Jul 2 15:18:32 CEST 2006


Update of /cvsroot/dslinux/dslinux/user/bitchx/dll/acro
In directory antilope:/tmp/cvs-serv9280/dll/acro

Added Files:
	Makefile.in README TODO acro.c acro.h acro.sh 
Log Message:
Adding pristine copy of BitchX so I can branch from it.


--- NEW FILE: acro.h ---
#include "struct.h"
#include "ircaux.h"
#include "server.h"
#include "output.h"
#include "module.h"
#include "parse.h"
#include "timer.h"
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>

#define INIT_MODULE
#include "modval.h"

/*
 * I put this here because pana said I should use it, but its commented out
 * in ircaux.h :)
 */
#ifndef new_realloc
#define new_realloc(x,y) n_realloc((x),(y),__FILE__,__LINE__)
#endif

#define MINPLAYERS 2            /* Minimum number of players per game */
#define MAXPLAYERS 10           /* Max number of players per game */
#define MINLENGTH 3             /* Minimum number of letters per acronym */
#define MAXLENGTH 5             /* Max number of letters per acronym */
#define ROUNDS 10               /* Number of rounds to play */
#define EXTENSIONS 3            /* Max number of 30 second extensions */
#define TOP 10                  /* Show the top XX names for the scores */
#define MAXLEN 15               /* Max number of characters per acro word */

/*
 * These must be "proper" paths -- ie the ENTIRE path must exist and there
 * are no expansion characters in there (IE ~ or $(HOME))
 */

#define SCOREFILE ".BitchX/acro.score"
#define WEBSCORE "acro.html"

/* prec -- a linked list containing all the player info */

typedef struct _prec {
	char *nick;
	char *host;
	char *acro;
	char *last;
	struct _prec *next;
} prec;

/* vrec -- linked list storing voters, and who they voted for */

typedef struct _vrec {
	char *nick;
	char *host;
	int vote;
	struct _vrec *next;
} vrec;

/* grec -- struct containing the info about the current game */

typedef struct {
	int progress;
	int round;
	int rounds;
	int players;
	int extended;
	int top;
	int maxlen;
	char *nym;
} grec; 

/* srec -- linked list of scores */

typedef struct _srec {
	char *nick;
	unsigned long score;
	struct _srec *next;
} srec;

struct settings {
	int minplayers;
	int maxplayers;
	int minlength;
	int maxlength;
	int rounds;
	int extensions;
	int top;
	int maxlen;
	char *scorefile;
	char *webscore;
};

static char letters[] = "ABCDEFGHIJKLMNOPRSTUVWY";

static int acro_main (char *, char *, char *, char **);
int Acro_Init(IrcCommandDll **, Function_ptr *);
BUILT_IN_DLL(put_scores);
grec *init_acro(grec *);
void make_acro(grec *);
int valid_acro(grec *, char *);
srec *read_scores(void);
int write_scores(srec *);
prec *take_acro(grec *, prec *, char *, char *, char *);
vrec *take_vote(grec *, vrec *, prec *, char *, char *, char *);
srec *end_vote(vrec *, prec *, srec *);
srec *sort_scores(srec *);
int comp_score(srec **one, srec **two);
void show_scores(grec *, srec *, srec *, char *);
void warn_acro(char *);
void start_vote(char *);
void warn_vote(char *);
void end_voting(char *);
void show_acros(prec *, char *);
void free_round(prec **, vrec **);
void free_score(srec **);
/* static void game_setup _(( IrcCommandDll *, char *, char *, char *)); */

--- NEW FILE: Makefile.in ---
SHELL = @SHELL@

srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
topdir = @topdir@
prefix = @prefix@
exec_prefix = @exec_prefix@

bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = @oldincludedir@

local_dir = $(HOME)

# Where the BitchX binary will be installed.
# "make install" will compile and install the program.
INSTALL_IRC = @INSTALL_IRC@

# Where the BitchX library will be. Generally this is the place that
# you put the scripts, help pages and translation tables. It is
# very important that you set this correctly.
IRCLIB = @IRCLIB@

CC = @CC@
DEFS = @INCLUDES@
LIBS = @LIBS@

# Tcl library.
TCL_LIBS = @TCL_LIBS@

# These are for Tcl support.
TCL_OBJS = @TCL_OBJS@
# You don't have the following, so you'll want to leave this blank.
TCL_SRCS = @TCL_SRCS@

# Set this to -g if you want to be able to debug the client, otherwise
# use -O to have the compiler do some optimization instead.
CFLAGS = @CFLAGS@

# Set this to -s if you want the binary to be stripped.
LDFLAGS = @LDFLAGS@

# These are for the cd device player.
CD_SRCS = @CD_SRCS@
CD_OBJS = @CD_OBJS@

# This is the executable suffix for the target operating system.
EXEEXT = @EXEEXT@

# Extra files.
DEFAULT_CTOOLZ_DIR = @DEFAULT_CTOOLZ_DIR@
DEFAULT_MSGLOGFILE = @DEFAULT_MSGLOGFILE@
DEFAULT_BITCHX_HELP_FILE = @DEFAULT_BITCHX_HELP_FILE@
DEFAULT_SCRIPT_HELP_FILE = @DEFAULT_SCRIPT_HELP_FILE@
DEFAULT_BITCHX_KICK_FILE = @DEFAULT_BITCHX_KICK_FILE@
DEFAULT_BITCHX_QUIT_FILE = @DEFAULT_BITCHX_QUIT_FILE@
DEFAULT_BITCHX_IRCNAME_FILE = @DEFAULT_BITCHX_IRCNAME_FILE@

# Full path of the directory for BitchX help files.
HELPDIR = @HELPDIR@

# Full path of the directory for the BitchX scripts.
INSTALL_SCRIPT = @INSTALL_SCRIPT@

# Default setting for IRCPATH where BitchX will look for
# its script files if the environment variable is undefined.
# Usually, this should contain the same path as used for INSTALL_SCRIPT in
# the Makefile, but it can contain multiple path elements
# separated by colons. The path MUST lead to an existing directory,
# because the 'global' script is expected to be found there.
IRCPATH = @IRCPATH@

# Path for TRANSLATION variable.
TRANSLATION_PATH = @TRANSLATION_PATH@

# This command will be used to install the BitchX help files. If you don't
# want to install them, replace with the following:
# INSTALL_HELP_CMD = @echo The help files have not been installed.
INSTALL_HELP_CMD = @INSTALL_HELP_CMD@

# This is where the optional plugins will be copied to.
PLUGINDIR = @PLUGINDIR@

# Plugin flags.
SHLIB_LD = @SHLIB_LD@
SHLIB_CFLAGS = @SHLIB_CFLAGS@
SHLIB_SUFFIX = @SHLIB_SUFFIX@

# This command will be used to install the BitchX files on Win32/OS2EMX
# systems.
WINNT_INSTALL = @WINNT_INSTALL@

# This program allows you to use screen/xterm's to put new BitchX windows
# on new screen/xterm windows.
INSTALL_WSERV = @INSTALL_WSERV@

# This program allows you to screen BitchX and reattach to it later.
INSTALL_SCRBX = @INSTALL_SCRBX@

# Set gzip and bzip2 options.
GZIP_ENV = @GZIP_ENV@
BZIP2 = @BZIP2@

# Standard programs.
RM = @RM@
LN = @LN_S@
CP = @CP@
MV = @MV@

INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@

VERSION = @VERSION@
_VERSION_ = @_VERSION_@

MAKE_BIN = @MAKE@
MAKE = $(MAKE_BIN) $(MFLAGS)
MFLAGS = \
	'local_dir=$(HOME)'			\
	'INSTALL_IRC=$(INSTALL_IRC)'		\
	'IRCLIB=$(IRCLIB)'			\
	'CC=$(CC)'				\
	'CFLAGS=$(CFLAGS)'			\
	'HELPDIR=$(HELPDIR)'			\
        'INSTALL_WSERV=$(INSTALL_WSERV)'	\
	'IRCPATH=$(IRCPATH)'			\
	'TRANSLATION_PATH=$(TRANSLATION_PATH)'	\
	'LDFLAGS=$(LDFLAGS)'			\
	'LIBS=$(LIBS)'				\
	'LN=$(LN)'				\
	'RM=$(RM)'				\
	'TCL_SRCS=$(TCL_SRCS)'			\
	'TCL_OBJS=$(TCL_OBJS)'			\
	'CD_PLAY=$(CD_PLAY)'			\
	'CD_SRCS=$(CD_SRCS)'			\
	'CD_OBJS=$(CD_OBJS)'			\
	'TCL_LIBS=$(TCL_LIBS)'			\
	'PLUGINDIR=$(PLUGINDIR)'		\
	'_VERSION_=$(_VERSION_)'		\
	'VERSION=$(VERSION)'			\
	'INSTALL_DATA=$(INSTALL_DATA)'		\
	'INSTALL_SCRIPT=$(INSTALL_SCRIPT)'	\
	'EXEEXT=$(EXEEXT)'			\
	'SHLIB_CFLAGS=$(SHLIB_CFLAGS)'		\
	'SHLIB_SUFFIX=$(SHLIB_SUFFIX)'

## Makefile starts here.

PLUGIN_NAME = acro

all: Makefile acro$(SHLIB_SUFFIX)

Makefile: Makefile.in
	cd $(topdir) \
	  && ./config.status

acro.o: $(srcdir)/acro.c
	$(CC) $(DEFS) $(CFLAGS) -c $(srcdir)/acro.c

acro$(SHLIB_SUFFIX): acro.o ../dllinit.o
	$(SHLIB_LD) acro.o ../dllinit.o $(SHLIB_CFLAGS) -o acro$(SHLIB_SUFFIX)

clean:
	$(RM) *~ *.o acro$(SHLIB_SUFFIX) *.a *.def .#*

distclean: clean
	$(RM) Makefile

install:
	$(INSTALL) $(PLUGIN_NAME)$(SHLIB_SUFFIX) $(PLUGINDIR)

--- NEW FILE: README ---
First public release of a dll-ized version of my TCL acromania script.
You need the BitchX include files for it to compile (duh).
Seems to work fine in testing, alert me of any problems.

                    ************ WARNING ************
DO NOT /UNLOADDLL WHILE A GAME IS IN PROGRESS, YOUR CLIENT WILL CORE!
If you MUST stop a game in progress, FIRST KILL THE TIMER(S) and unload it.
Maybe panasync will take these race conditions into account someday :)...
                    ************ WARNING ************


Greetz to (in NO particular order) dh, hammz, scoop, hammz, oweff, shewp
ice-man, sideshow, BlackJac, fudd, shade, psykotyk, MHacker, Sheik, easyme
macker, |Fingers|, mrr, Timer, and anyone else I'm forgetting (let me know)

Major super-kudo greets to panasync, without his help I never would have got
this working properly, and of course for making bX in the first place.. =)

--- NEW FILE: acro.c ---
#include "acro.h"

srec *scores = NULL, *gscores = NULL;
prec *player = NULL;
vrec *voter = NULL;
grec *game = NULL;

int Acro_Init(IrcCommandDll **intp, Function_ptr *global_table)
{
	initialize_module("Acromania");
	add_module_proc(RAW_PROC, "acro", "PRIVMSG", NULL, 0, 0, acro_main, NULL);
	add_module_proc(COMMAND_PROC, "scores", "scores", NULL, 0, 0, put_scores, NULL);

	gscores = read_scores();
	if (!game)
		game = init_acro(game);
	put_it("BitchX Acromania dll v0.9b by By-Tor loaded...");
	return 0;
}

static int acro_main (char *comm, char *from, char *userhost, char **args)
{
	if (*args[1] && !strncasecmp(args[1], "acro ", 5) && !strcasecmp(args[0], get_server_nickname(from_server)))
	{
		PasteArgs(args, 1);
		switch(game->progress) {
			case 0:
				send_to_server("notice %s :Sorry, no game in progress.", from);
				break;
			case 1:
				if (valid_acro(game, args[1]+5))
					player = take_acro(game, player, from, userhost, args[1]+5);
				else
					send_to_server("PRIVMSG %s :Invalid acronym", from);
				break;
			case 2:
				voter = take_vote(game, voter, player, from, userhost, args[1]+5);
				break;
		}
		return 1;
	}
	if (*args[0] == '#' && *args[1] && !my_stricmp(args[1], "start"))
	{
		if (game && game->progress)
		{
			send_to_server("PRIVMSG %s :Game already in progress, %s. Puzzle is: %s", from, from, game->nym);
			return 0;
		}
		make_acro(game);
		game->progress = 1;
		send_to_server("PRIVMSG %s :Round %d", args[0], game->round);
		send_to_server("PRIVMSG %s :The acronym for this round is %s. You have 60 seconds.", args[0], game->nym);
		send_to_server("PRIVMSG %s :/msg %s \"acro <your answer>\"", args[0], get_server_nickname(from_server));
		add_timer(0, "Acro", 60 * 1000, 1, (int(*)(void *))warn_acro, m_sprintf("%s", args[0]), NULL, NULL, "acro");
	}
	return 0;
}


BUILT_IN_DLL(put_scores)
{
	srec *stmp = NULL;
	if (scores) {
		put_it("Start Normal scores");
		for (stmp = scores; stmp; stmp = stmp->next)
			put_it("Nick: %s\tScore: %lu", stmp->nick, stmp->score);
		put_it("End scores");
	}
/*
	if (gscores) {
		put_it("GLOBAL SCORES START HERE!"); 
		for (stmp = gscores; stmp; stmp = stmp->next)
			put_it("Nick: %s\tScore %lu", stmp->nick, stmp->score);
		put_it("GLOBAL SCORES END HERE!"); 
	}
*/
}

void warn_acro(char *chan)
{
	send_to_server("PRIVMSG %s :30 seconds! Puzzle is: %s", chan, game->nym);
	add_timer(0, "Acro", 30 * 1000, 1, (int(*)(void *))start_vote, m_sprintf("%s", chan), NULL, NULL, "acro");
}

void start_vote(char *chan)
{
	if (game->players >= MINPLAYERS)
	{
		send_to_server("PRIVMSG %s :Time's up, lets vote!\r\nPRIVMSG %s :/msg %s \"acro #\" to vote", chan, chan, get_server_nickname(from_server));
		game->progress = 2;
		show_acros(player, chan);
		add_timer(0, "Acro", 30 * 1000, 1, (int(*)(void *))warn_vote, m_sprintf("%s", chan), NULL, NULL, "acro");
	}
	else if (game->extended < EXTENSIONS)
	{
		send_to_server("PRIVMSG %s :Aww, too few players! Puzzle is: %s", chan, game->nym);
		add_timer(0, "Acro", 30 * 1000, 1, (int(*)(void *))start_vote, m_sprintf("%s", chan), NULL, NULL, "acro");
		game->extended++;
	}
	else
	{
		send_to_server("PRIVMSG %s :Not enough players, ending game...", chan);
		free_round(&player, &voter);
		game->players = 0;
		game->progress = 0;
	}
}
 
void warn_vote(char *chan)
{
	send_to_server("PRIVMSG %s :30 seconds left to vote!", chan);
	add_timer(0, "Acro", 30 * 1000, 1, (int(*)(void *))end_voting, m_sprintf("%s", chan), NULL, NULL, "acro");
}

void end_voting(char *chan)
{
	put_it("END_VOTING");
	send_to_server("PRIVMSG %s :Voting complete, sorting scores...", chan);
	gscores = end_vote(voter, player, gscores);
	scores = end_vote(voter, player, scores);
	write_scores(gscores);
	show_scores(game, scores, gscores, chan);
	free_round(&player, &voter);
	if (player)
	{
		put_it("Player was non-null!!");
		player = NULL;
	}
	if (voter)
	{
		put_it("voter was non-null!!");
		voter = NULL;
	}
	if (game->round < game->rounds)
	{
		init_acro(game);
		send_to_server("PRIVMSG %s :Round %d", chan, game->round);
		send_to_server("PRIVMSG %s :The acronym for this round is %s. You have 60 seconds.", chan, game->nym);
		send_to_server("PRIVMSG %s :/msg %s \"acro <your answer>\"", chan, get_server_nickname(from_server));
		add_timer(0, "Acro", 60 * 1000, 1, (int(*)(void *))warn_acro, m_sprintf("%s", chan), NULL, NULL, "acro");
	}		
	else
	{
		game->round = 1;
		game->progress = 0;
		free_score(&scores);
		new_free(&game->nym);
		init_acro(game);
	}
}

grec *init_acro(grec *gtmp)
{
	if (!gtmp)
		gtmp = (grec *)new_malloc(sizeof(grec));
	if (gtmp->nym)
	{
		gtmp->progress = 1;
		gtmp->round++;
		gtmp->players = 0;
		gtmp->extended = 0;
		new_free(&gtmp->nym);
		make_acro(gtmp);
	}
	else
	{	
		gtmp->progress = 0;
		gtmp->round = 1;
		gtmp->rounds = ROUNDS;
		gtmp->players = 0;
		gtmp->extended = 0;
		gtmp->top = TOP;
		gtmp->maxlen = MAXLEN;
		gtmp->nym = NULL;
	}
	return gtmp;
}

void make_acro(grec *acro)
{
	int i, r;
	char *p;
	if (acro->nym)
		new_free(&acro->nym);
	r = MINLENGTH+(int)((float) (1+MAXLENGTH-MINLENGTH)*random()/(RAND_MAX+1.0));
	p = acro->nym = (char *)new_malloc(r+1);
	for (i = 0; i < r; i++)
		*p++ = letters[(int)((float)(strlen(letters))*random()/(RAND_MAX+1.0))];
	return;
}

int valid_acro(grec *acro, char *p)
{
	int spaces = 0, len = 0, gotsp = 1;
	if (!p)
		return 0;
	if (!acro)
		return 0;
	for (; *p; p++)
	{
		if (isalpha(*p))
		{
			len++;
			if (gotsp && (toupper(*p) != acro->nym[spaces]))
				return 0;
			gotsp = 0;
		}
		else if (*p == 32)
		{
			if (!gotsp)
			{
				spaces++;
				gotsp = 1;
			}
		}
		else return 0;
	}
	if ((len > strlen(acro->nym)) && (spaces+1 == strlen(acro->nym)))
		return 1;
	return 0;
}

prec *take_acro(grec *acro, prec *players, char *nick, char *host, char *stuff)
{
	prec *tmp, *last = NULL;
	if (!players)
	{
		players = (prec *)new_malloc(sizeof(prec));
		players->nick = (char *)new_malloc(strlen(nick)+1);
		players->host = (char *)new_malloc(strlen(host)+1);
		players->acro = (char *)new_malloc(strlen(stuff)+1);
		strcpy(players->nick, nick);
		strcpy(players->host, host);
		strcpy(players->acro, stuff);
		send_to_server("PRIVMSG %s :Answer set to \"%s\"\r\nPRIVMSG %s :You are player #%d", nick, stuff, nick, ++acro->players);
		return players;
	}
	for (tmp = players; tmp; tmp = tmp->next)
	{
		if (tmp->host && !strcasecmp(host, tmp->host))
		{
			if (tmp->acro && !strcasecmp(stuff, tmp->acro))
			{
				send_to_server("PRIVMSG %s :Your answer is alreay \"%s\"", nick, stuff);
				return players;
			}
			else if (tmp->last && !strcasecmp(stuff, tmp->last))
			{
				RESIZE(tmp->acro, char, strlen(stuff)+1);
				strcpy(tmp->acro, stuff);
				send_to_server("PRIVMSG %s :Answer changed to \"%s\"", nick, stuff);
				new_free(&tmp->last);
				return players;
			}
			else {
				tmp->last = (char *)new_malloc(strlen(stuff)+1);
				strcpy(tmp->last, stuff);
				send_to_server("PRIVMSG %s :You already submitted an answer, submit once more to change.", nick);
				return players;
			}
		}
		last = tmp;
	}
	if (acro->players < MAXPLAYERS && last)
	{
		tmp = last->next = (prec *)new_malloc(sizeof(prec));
		tmp->nick = (char *)new_malloc(strlen(nick)+1);
		tmp->host = (char *)new_malloc(strlen(host)+1);
		tmp->acro = (char *)new_malloc(strlen(stuff)+1);
		strcpy(tmp->nick, nick);
		strcpy(tmp->host, host);
		strcpy(tmp->acro, stuff);
		send_to_server("PRIVMSG %s :Answer set to \"%s\"\r\nPRIVMSG %s :You are player #%d", nick, stuff, nick, ++acro->players);
	}
	else
		send_to_server("PRIVMSG %s :Sorry, too many players.", nick);
	return players;
}

vrec *take_vote(grec *acro, vrec *voters, prec *players, char *nick, char *host, char *num)
{
	vrec *tmp = NULL, *last = voters;
	int i;
  if (atoi(num) > acro->players || atoi(num) < 1)
	{
		send_to_server("PRIVMSG %s :No such answer...", nick);
		return voters;
	}
	for (i = 1; i < atoi(num); i++)
		players = players->next;
	if (players->nick && nick && !strcasecmp(players->nick, nick))
	{
		send_to_server("PRIVMSG %s :You can't vote for yourself.", nick);
		return voters;
	}
	if (!voters)
	{
		voters = (vrec *)new_malloc(sizeof(vrec));
		voters->nick = (char *)new_malloc(strlen(nick)+1);
		voters->host = (char *)new_malloc(strlen(host)+1);
		voters->vote = atoi(num)-1;
		strcpy(voters->nick, nick);
		strcpy(voters->host, host);
		send_to_server("PRIVMSG %s :Vote recorded...", nick);
		return voters;
	}
	for (tmp = voters; tmp; tmp = tmp->next)
	{
		if ((tmp->nick && !strcasecmp(tmp->nick, nick)) || (tmp->host && !strcasecmp(tmp->host, host)))
		{
			send_to_server("PRIVMSG %s :You already voted.", nick);
			return voters;
		}
		last = tmp;
	}
	if (last && !last->next)
	{
		last = last->next = (vrec *)new_malloc(sizeof(vrec));
		last->nick = (char *)new_malloc(strlen(nick)+1+sizeof(char *));
		last->host = (char *)new_malloc(strlen(host)+1+sizeof(char *));
		last->vote = atoi(num)-1;
		strcpy(last->nick, nick);
		strcpy(last->host, host);
		send_to_server("PRIVMSG %s :Vote recorded...", nick);
	}
	return voters;
}

srec *read_scores()
{
	srec *tmp, *tmp2;
	char buff[100], *p;
	FILE *sf;
	tmp = tmp2 = (srec *)new_malloc(sizeof(srec));
	memset(buff, 0, sizeof(buff));
	sf = fopen(SCOREFILE, "r");
	if (!sf)
		return 0;
	while (!feof(sf))
	{
		if (fgets(buff, 51, sf))
		{
			if (tmp->nick)
				tmp = tmp->next = (srec *)new_malloc(sizeof(srec));
			if (buff[strlen(buff)-1] == '\n')
				buff[strlen(buff)-1] = 0;
			if (!*buff)
				break;
			if ((p = (char *)strchr(buff, ',')))
				*p++ = 0;
			else if (!p)
			{
				return tmp2;
				fclose(sf);
			}
			tmp->nick = (char *)new_malloc(strlen(buff+1));
			strcpy(tmp->nick, buff);
			if (p)
				tmp->score = strtoul(p, NULL, 10);
		}
		else
			break;
	}
	fclose(sf);
	return tmp2;
}

int write_scores(srec *tmp)
{
	FILE *sf;
	if (!tmp)
		return 0;
	tmp = sort_scores(tmp);
	sf = fopen(SCOREFILE, "w");
	if (!sf)
		return 0;
	for (; tmp; tmp = tmp->next)
		if (tmp->score > 0)
			fprintf(sf, "%s,%lu\n", tmp->nick, tmp->score);
	fclose(sf);
	return 1;
}

/*
 * Here we take the votes from the current round and translate them into
 * scores for the players. gscores is the score per game, while scores
 * is the overall score for all games... So we call it with a ptr to the
 * score record we want to update and it makes it more useful :)
 * The dual for () loop is probably inefficient, but its all I can think of
 * right now ;), besides we aren't talking about 10,000 members here

 * Eventually I'll convert this to support variable arg lengths and thus
 * update for multiple scores with one call...
 * This function is a mess right now, I'll clean it up later.
*/

srec *end_vote(vrec *voters, prec *players, srec *stmp)
{
	int i, gotscore;
	vrec *tmp = NULL;
	prec *tmp2 = NULL;
	srec *tmp3 = NULL, *last;
	if (!stmp && voters && players)
		stmp = (srec *)new_malloc(sizeof(srec));
	for (tmp = voters; tmp; tmp = tmp->next)
	{
		gotscore = 0;
		tmp2 = players;
		for (i = 0; i < tmp->vote; i++)
			tmp2 = tmp2->next;
		if (stmp && !stmp->nick)
		{
			stmp->nick = (char *)new_malloc(strlen(tmp2->nick)+1);
			strcpy(stmp->nick, tmp2->nick);
			stmp->score = 1;
			continue;
		}
		for (tmp3 = last = stmp; tmp3; tmp3 = tmp3->next)
		{
			if (tmp2->nick && tmp3->nick && !strcasecmp(tmp2->nick, tmp3->nick))
			{
				tmp3->score++;
				gotscore = 1;
				break;
			}
			last = tmp3;
		}
		if (!gotscore)
		{
			tmp3 = last->next = (srec *)new_malloc(sizeof(srec));
			tmp3->nick = (char *)new_malloc(strlen(tmp2->nick)+1);
			strcpy(tmp3->nick, tmp2->nick);
			tmp3->score = 1;
		}
	}
	return stmp;
}

srec *sort_scores(srec *stmp)
{
	int i = 0;
	srec *tmp;
	srec **sort, **ctmp;
	if (!stmp->next)
		return stmp;
	for (tmp = stmp; tmp; tmp = tmp->next)
		i++;
	ctmp = sort = (srec **)new_malloc(i*sizeof(srec *));
	put_it("START SORTING");
	put_scores(NULL, NULL, NULL, NULL, NULL);
	for (tmp = stmp; tmp; tmp = tmp->next)
		*ctmp++ = tmp;
        qsort((void *)sort, i+1, sizeof(srec *), (int (*)(const void *, const void *))comp_score);
	ctmp = sort;
	for (tmp = *ctmp++; *ctmp; ctmp++)
		tmp = tmp->next = *ctmp;
	tmp->next = NULL;
	tmp = *sort;
	new_free(&sort);
	put_scores(NULL, NULL, NULL, NULL, NULL);
	put_it("END SCORES");
 	return tmp;
}

/* 
 * Here we sort deeze babys ... The return values are "opposite" so we can
 * sort in descending order instead of ascending... Stupid declarations had 
 * me going for a while, no wonder it didnt sort right at first! :)
*/

int comp_score(srec **one, srec **two)
{
  if ((*one)->score > (*two)->score)
    return -1;
  if ((*one)->score < (*two)->score)
    return 1;
  else
    return strcasecmp((*one)->nick, (*two)->nick);
}

void show_acros(prec *players, char *chan)
{
	prec *tmp;
	int i = 1;
	char *line, buff[201];
	if (!players)
		return;
	line = (char *)new_malloc(513);
	memset(buff, 0, sizeof(buff));
	for (tmp = players; tmp; tmp = tmp->next)
	{
		snprintf(buff, 198, "PRIVMSG %s :%2d: %s", chan, i++, tmp->acro);
		strcat(buff, "\r\n");
		if (strlen(line)+strlen(buff) >= 512)
		{
			send_to_server("%s", line);
			memset(line, 0, 513);
		}
		strcat(line, buff);
		memset(buff, 0, sizeof(buff));
	}
	if (line)
		send_to_server("%s", line);
	new_free(&line);
} 

void show_scores(grec *acro, srec *score, srec *gscore, char *chan)
{
	char *line, buff[201];
	int i;
	line = (char *)new_malloc(513);
	memset(buff, 0, sizeof(buff));
	if (score)
		score = sort_scores(score);
	if (gscore && (acro->round >= acro->rounds))
		gscore = sort_scores(gscore);
	if (acro->round < acro->rounds)
		sprintf(line, "PRIVMSG %s :Scores for round %d\r\nPRIVMSG %s :Nick        Score\r\nPRIVMSG %s :-----------------\r\n", chan, acro->round, chan, chan);
	else
		sprintf(line, "PRIVMSG %s :Game over, tallying final scores...\r\nPRIVMSG %s :   Game Score          Overall Score\r\nPRIVMSG %s :Nick        Score    Nick        Score\r\nPRIVMSG %s :-----------------    -----------------\r\n", chan, chan, chan, chan);
	for (i = 0; i < acro->top && (score || gscore); i++)
	{
		if ((acro->round < acro->rounds) && score)
		{
			snprintf(buff, 198, "PRIVMSG %s :%-9s    %lu", chan, score->nick, score->score);
			strcat(buff, "\r\n");
			score = score->next;
		}
		else if (acro->round == acro->rounds && (score || gscore)) 
		{
			if (!score && gscore)
			{
				snprintf(buff, 198, "PRIVMSG %s :                     %-9s   %lu", chan, gscore->nick, gscore->score);
				strcat(buff, "\r\n");
				gscore = gscore->next;
			}
			else if (score && !gscore)
			{
				snprintf(buff, 198, "PRIVMSG %s :%-9s    %lu", chan, score->nick, score->score);
				strcat(buff, "\r\n");
				score = score->next;
			}
			else if (gscore && score)
			{
				snprintf(buff, 198, "PRIVMSG %s :%-9s    %-5lu   %-9s    %lu", chan, score->nick, score->score, gscore->nick, gscore->score);
				strcat(buff, "\r\n");
				gscore = gscore->next;
				score = score->next;
			}
		}
		if (strlen(line)+strlen(buff) >= 512)
		{
			send_to_server("%s", line);
			memset(line, 0, 513);
		}
		strcat(line, buff);
		memset(buff, 0, sizeof(buff));
	}
	if (line)
		send_to_server("%s", line);
	new_free(&line);
} 

void free_round(prec **players, vrec **voters)
{
	prec *ptmp, *ptmp2;
	vrec *vtmp, *vtmp2;
	if (players && *players) {
		for (ptmp = *players; ptmp;)
		{
			if (ptmp->nick)
				new_free(&ptmp->nick);
			if (ptmp->host)
  			new_free(&ptmp->host);
  		if (ptmp->acro)
  			new_free(&ptmp->acro);
  		if (ptmp->last)
  			new_free(&ptmp->last);
  		if (ptmp->next)
  			ptmp2 = ptmp->next;
  		else
  			ptmp2 = NULL;
  		new_free(&ptmp);
  		ptmp = ptmp2;
  	}
  	*players = NULL;
  }
  if (voters && *voters) {
  	for (vtmp = *voters; vtmp;)
  	{
  		if (vtmp->nick)
  			new_free(&vtmp->nick);
  		if (vtmp->host)
  			new_free(&vtmp->host);
  		if (vtmp->next)
  			vtmp2 = vtmp->next;
  		else
  			vtmp2 = NULL;
  		new_free(&vtmp);
  		vtmp = vtmp2;
  	}
  	*voters = NULL;
  }
}

void free_score(srec **score)
{
	srec *stmp, *stmp2;
	for (stmp = *score; stmp;)
	{
		if (stmp->nick)
			new_free(&stmp->nick);
		if (stmp->next)
			stmp2 = stmp->next;
		else
			stmp2 = NULL;
		new_free(&stmp);
		stmp = stmp2;
	}
	*score = NULL;
}

--- NEW FILE: acro.sh ---
#!/bin/sh
# Make .def file:
export LIBPATH=/usr/local/cygwin-new/i586-pc-cygwin/lib
export LD=/usr/local/cygwin-new/bin/i586-pc-cygwin-ld
export NM=/usr/local/cygwin-new/bin/i586-pc-cygwin-nm
export DLLTOOL=/usr/local/cygwin-new/bin/i586-pc-cygwin-dlltool
export AS=/usr/local/cygwin-new/bin/i586-pc-cygwin-as
export GCC=/usr/local/cygwin-new/bin/i586-pc-cygwin-gcc
RM=rm
CP=cp

$GCC -I../../include -c acro.c

echo EXPORTS > acro.def
$NM acro.o ../init.o ../fixup.o | grep '^........ [T] _' | sed 's/[^_]*_//' >> acro.def

# Link DLL.
$LD --base-file acro.base --dll -o acro.dll acro.o ../init.o ../fixup.o\
 $LIBPATH/libcygwin.a $LIBPATH/libkernel32.a -e _dll_entry at 12
$DLLTOOL --as=$AS --dllname acro.dll --def acro.def --base-file\
 acro.base --output-exp acro.exp
$LD --base-file acro.base acro.exp --dll -o acro.dll acro.o\
 ../init.o ../fixup.o $LIBPATH/libcygwin.a $LIBPATH/libkernel32.a -e _dll_entry at 12
$DLLTOOL --as=$AS --dllname acro.dll --def acro.def --base-file\
 acro.base --output-exp acro.exp
$LD acro.exp --dll -o acro.dll acro.o ../init.o ../fixup.o\
 $LIBPATH/libcygwin.a $LIBPATH/libkernel32.a -e _dll_entry at 12

# Build the acroB.a lib to link to:
$DLLTOOL --as=$AS --dllname acro.dll --def acro.def --output-lib acro.a
$RM *.base *.exp *.def
$CP *.dll ..

--- NEW FILE: TODO ---
Things to do...

Everyone seems to want point deductions for playing and not voting, maybe
I'll make that an option or something:)

Need to get rid of all the compile time defines and make them dynamic with a
command in bx.




More information about the dslinux-commit mailing list