/*  playergen.c: (c) 2002 sibn

    This file is part of GWiz.

    GWiz 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.

    GWiz 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 GWiz; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "gwiz.h"
#include "uiloop.h"
#include "prefsdat.h"
#include "text.h"
#include "maploader.h"
#include "menus.h"
#include "playerpawn.h"
#include "castle.h"
#include "keynames.h"
#include "playergen.h"
#include "items.h"
#include "joystick.h"

extern GwizApp gwiz;
extern SDL_Color fg, bg;

void GeneratePlayer (void)
{
    SDL_Surface *tmp;
    GwizBonusRect gwbr;
    int emptypawn = -1;
    char *confcreate[] = {
	"Create this Character",
	"Cancel Character Creation",
	NULL
    };
    char *confrace[] = {
	"Human",
	"Elf",
	"Dwarf",
	"Gnome",
	"Hobbit",
	NULL
    };
    char *confsex[] = {
	"Male",
	"Female",
	NULL
    };
    char *confali[] = {
	"Good",
	"Neutral",
	"Evil",
	NULL
    };
    char *confkeep[] = {
	"Keep this Character",
	"Discard this Character",
	NULL
    };
    PlayerPawn *pawn = &gwbr.pawn;
    
    InitNewPlayer (pawn);
    CompactPartyFile(); /* squeeze everybody to the front of the line */
    emptypawn = FirstAvailablePawn();
    if (emptypawn < 0)
	{
	    MsgBox ("No space for new characters");
	    return;
	}
    
    gwbr.pawn.version = 0;
    gwbr.pawn.level = 1;
    
    tmp = SDL_DisplayFormat (gwiz.canvas);
    NewTextEntry ("Enter a Name:", gwbr.pawn.name, 16);
    
    if (NewGwizMenu(gwiz.canvas, confcreate, -1, -1, 0) != 0)
	{
	    SDL_BlitSurface(tmp, NULL, gwiz.canvas, NULL);
	    SDL_FreeSurface (tmp);
	    return;
	}
    
    switch (NewGwizMenu (gwiz.canvas, confrace, -1, -1, 0))
	{
	case -1:
	case 0:
	    pawn->race = HUMAN;
	    break;
	case 1:
	    pawn->race = ELF;
	    break;
	case 2:
	    pawn->race = DWARF;
	    break;
	case 3:
	    pawn->race = GNOME;
	    break;
	case 4:
	    pawn->race = HOBBIT;
	    break;
	}
    
    SDL_BlitSurface (tmp, NULL, gwiz.canvas, NULL);
    SDL_Flip (gwiz.canvas);
    
    switch (pawn->race)
	{
	case HUMAN:
	    pawn->attr.str = 8;
	    gwbr.min[0] = 8;
	    gwbr.max[0] = 18;
	    pawn->attr.iq = 8;
	    gwbr.min[1] = 8;
	    gwbr.max[1] = 18;
	    pawn->attr.dev = 5;
	    gwbr.min[2] = 5;
	    gwbr.max[2] = 15;
	    pawn->attr.vit = 8;
	    gwbr.min[3] = 8;
	    gwbr.max[3] = 18;
	    pawn->attr.agi = 8;
	    gwbr.min[4] = 8;
	    gwbr.max[4] = 18;
	    pawn->attr.luck = 9;
	    gwbr.min[5] = 9;
	    gwbr.max[5] = 19;
	    break;
	case ELF:
	    pawn->attr.str = 7;
	    gwbr.min[0] = 7;
	    gwbr.max[0] = 17;
	    pawn->attr.iq = 10;
	    gwbr.min[1] = 10;
	    gwbr.max[1] = 20;
	    pawn->attr.dev = 10;
	    gwbr.min[2] = 10;
	    gwbr.max[2] = 20;
	    pawn->attr.vit = 6;
	    gwbr.min[3] = 6;
	    gwbr.max[3] = 16;
	    pawn->attr.agi = 9;
	    gwbr.min[4] = 9;
	    gwbr.max[4] = 19;
	    pawn->attr.luck = 6;
	    gwbr.min[5] = 6;
	    gwbr.max[5] = 16;
	    break;
	case DWARF:
	    pawn->attr.str = 10;
	    gwbr.min[0] = 10;
	    gwbr.max[0] = 20;
	    pawn->attr.iq = 7;
	    gwbr.min[1] = 7;
	    gwbr.max[1] = 17;
	    pawn->attr.dev = 10;
	    gwbr.min[2] = 10;
	    gwbr.max[2] = 20;
	    pawn->attr.vit = 10;
	    gwbr.min[3] = 10;
	    gwbr.max[3] = 20;
	    pawn->attr.agi = 5;
	    gwbr.min[4] = 5;
	    gwbr.max[4] = 15;
	    pawn->attr.luck = 6;
	    gwbr.min[5] = 6;
	    gwbr.max[5] = 16;
	    break;
	case GNOME:
	    pawn->attr.str = 7;
	    gwbr.min[0] = 7;
	    gwbr.max[0] = 17;
	    pawn->attr.iq = 7;
	    gwbr.min[1] = 7;
	    gwbr.max[1] = 17;
	    pawn->attr.dev = 10;
	    gwbr.min[2] = 10;
	    gwbr.max[2] = 20;
	    pawn->attr.vit = 8;
	    gwbr.min[3] = 8;
	    gwbr.max[3] = 18;
	    pawn->attr.agi = 10;
	    gwbr.min[4] = 10;
	    gwbr.max[4] = 10;
	    pawn->attr.luck = 7;
	    gwbr.min[5] = 7;
	    gwbr.max[5] = 17;
	    break;
	case HOBBIT:
	    pawn->attr.str = 5;
	    gwbr.min[0] = 5;
	    gwbr.max[0] = 15;
	    pawn->attr.iq = 7;
	    gwbr.min[1] = 7;
	    gwbr.max[1] = 17;
	    pawn->attr.dev = 7;
	    gwbr.min[2] = 7;
	    gwbr.max[2] = 17;
	    pawn->attr.vit = 6;
	    gwbr.min[3] = 6;
	    gwbr.max[3] = 16;
	    pawn->attr.agi = 12;
	    gwbr.min[4] = 12;
	    gwbr.max[4] = 22;
	    pawn->attr.luck = 15;
	    gwbr.min[5] = 15;
	    gwbr.max[5] = 25;
	}

    switch (NewGwizMenu (gwiz.canvas, confsex, -1, -1, 0))
	{
	case -1:
	case 0:
	    pawn->sex = MALE;
	    break;
	case 1:
	    pawn->sex = FEMALE;
	    break;
	}
    
    SDL_BlitSurface (tmp, NULL, gwiz.canvas, NULL);
    SDL_Flip (gwiz.canvas);
    
    switch (NewGwizMenu (gwiz.canvas, confali, -1, -1, 0))
	{
	case -1:
	case 0:
	    pawn->ali = GOOD;
	    break;
	case 1:
	    pawn->ali = NEUTRAL;
	    break;
	case 2:
	    pawn->ali = EVIL;
	    break;
	}
    
    SDL_BlitSurface (tmp, NULL, gwiz.canvas, NULL);
    SDL_Flip (gwiz.canvas);
    
    NewBonusDistributor(&gwbr);
    
    switch (NewGwizMenu (gwiz.canvas, confkeep, -1, -1, 0))
	{
	case -1:
	case 0:
	    /* "keeping" means not returning here.  :) */
	    break;
	case 1:
	    SDL_BlitSurface (tmp, NULL, gwiz.canvas, NULL);
	    SDL_FreeSurface (tmp);
	    return;
	}
    
    GivePawnInitialEquipment(pawn);
    GivePawnInitialSpells(pawn);
    pawn->counter.age = gwbr.bonusmax;
    
    SDL_BlitSurface (tmp, NULL, gwiz.canvas, NULL);
    SDL_Flip (gwiz.canvas);

    if (strcmp (gwbr.pawn.name, "Bubba") == 0) /* Cheat mode */
	EnableCheatModeForPawn (&gwbr.pawn);

    SavePawn (gwbr.pawn, emptypawn);
    
    SDL_FreeSurface (tmp);
}

int GenBonusPoints (void)
{
    int luck = 0;
    int bonus = 0;
    
    luck = rand() % (100 - 1) + 1;
    
    if (luck > 99)
	bonus = rand() % (22 - 17) + 17;
    else if (luck > 96)
	bonus = rand() % (19 - 15) + 15;
    else if (luck > 90)
	bonus = rand() % (16 - 10) + 10;
    else if (luck > 75)
	bonus = rand() % (14 - 10) + 10;
    else if (luck > 50)
	bonus = rand() % (13 - 9) + 9;
    else if (luck > 25)
	bonus = rand() % (12 - 8) + 8;
    else if (luck > 5)
	bonus = rand() % (10 - 8) + 8;
    else
	bonus = 8;
    return (bonus);
}

void NewBonusDistributor (GwizBonusRect *gwbr)
{
    int b;
    gwbr->cursormode = 0;
    gwbr->position = 0;
    gwbr->maxposition = 5;
    gwbr->bonusmax = GenBonusPoints();
    if (strcmp (gwbr->pawn.name, "Bubba") == 0)
	gwbr->bonusmax = 10;
    gwbr->bonus = gwbr->bonusmax;
    b = gwbr->bonus + 6;
    gwbr->pawn.counter.hp_max = rand() % (b - 8) + 8;
    gwbr->pawn.counter.hp = gwbr->pawn.counter.hp_max;
    gwbr->pawn.counter.gp = rand() % (255 - 1) + 1;
    gwbr->availclasses = 0;
    
    BonusGraphicsPreload (gwbr);
    BonusLoop(gwbr); /* make the magick work */
    
    /* Reached end of function.  cleanup now. */
    SDL_BlitSurface (gwbr->screen, NULL, gwiz.canvas, NULL);
    SDL_FreeSurface (gwbr->screen);
    SDL_FreeSurface (gwbr->area);
    SDL_FreeSurface (gwbr->instructions);
    SDL_Flip (gwiz.canvas);
}

void BonusGraphicsPreload (GwizBonusRect *gwbr)
{
    SDL_Surface *tmp;
    SDL_Surface *bonus;
    SDL_Surface *class;
    SDL_Surface *instructions;
    SDL_Surface *bonusstring;
    SDL_Surface *attrstrs[6];
    SDL_Surface *instrstrs[4];
    SDL_Rect dest;
    char *attrs[] = {
	"Strength",
	"I.Q.    ",
	"Devotion",
	"Vitality",
	"Agility ",
	"Luck    " /* Equal length, to make stuff a little easier */ 
    };
    char *instrs[] = {
	"Up/Down: Change selection",
	"Left/Right: Increment/Decrement Attribute",
	KeyToChar (gwiz.key.act),
	": Finished"
    };
    int i;
    
    for (i = 0; i < 6; i++)
	attrstrs[i] = GwizRenderText(attrs[i]);
    
    for (i = 0; i < 4; i++)
	instrstrs[i] = GwizRenderText(instrs[i]);
    
    bonusstring = GwizRenderText("Bonus   ");
    
    bonus = NewTextBox((attrstrs[0]->w + gwiz.number[20]->w + 10),
		       (gwiz.font.height * 8));
    
    /* FIXME: +2 is a fugly hack. */ 
    class = NewTextBox((gwiz.classpix[0]->w + gwiz.cursor->w + 2),
		       (gwiz.font.height*8));
    
    dest.x = 8;
    dest.y = 8;
    dest.h = attrstrs[0]->h;
    dest.w = attrstrs[0]->w;
    for (i = 0; i < 6; i++)
	{
	    SDL_BlitSurface (attrstrs[i], NULL, bonus, &dest);
	    dest.y += gwiz.font.height;
	}
    
    dest.y += gwiz.font.height;
    SDL_BlitSurface (bonusstring, NULL, bonus, &dest);
    
    tmp = NewGwizSurface (bonus->w+class->w, bonus->h);
    
    dest.x = 0;
    dest.y = 0;
    dest.h = bonus->h;
    dest.w = bonus->w;
    SDL_BlitSurface (bonus, NULL, tmp, &dest);
    dest.x = bonus->w;
    dest.w = class->w;
    SDL_BlitSurface (class, NULL, tmp, &dest);
    
    instructions = NewTextBox(instrstrs[1]->w, gwiz.font.height*3);
    
    dest.x = 8;
    dest.y = 8;
    dest.h = instructions->h;
    dest.w = instructions->w;
    SDL_BlitSurface (instrstrs[0], NULL, instructions, &dest);
    dest.y += gwiz.font.height;
    SDL_BlitSurface (instrstrs[1], NULL, instructions, &dest);
    dest.y += gwiz.font.height;
    SDL_BlitSurface (instrstrs[2], NULL, instructions, &dest);
    dest.x += instrstrs[2]->w;
    dest.w = instrstrs[3]->w;
    SDL_BlitSurface (instrstrs[3], NULL, instructions, &dest);
    
    gwbr->area = SDL_DisplayFormat (tmp);
    gwbr->instructions = SDL_DisplayFormat (instructions);
    dest.x = gwiz.canvas->w/2 - gwbr->area->w/2;
    dest.y = gwiz.canvas->h/2 - gwbr->area->h/2;
    dest.h = gwbr->area->h;
    dest.w = gwbr->area->w;
    gwbr->screen = SDL_DisplayFormat (gwiz.canvas);
    SDL_BlitSurface (gwbr->area, NULL, gwiz.canvas, &dest);
    
    /* init the rects too, because they get used a lot. */
    gwbr->bonuscursordest.x = gwiz.canvas->w/2 - gwbr->area->w/2 +
	bonus->w - gwiz.tbord[0]->w - gwiz.number[0]->w - 
	gwiz.cursor->w; 
    gwbr->bonuscursordest.y = gwiz.canvas->h/2 - gwbr->area->h/2 +
	gwiz.tbord[0]->h + 1 - gwiz.cursor->h/2 + gwiz.font.height/2;
    gwbr->bonuscursordest.h = gwiz.cursor->h;
    gwbr->bonuscursordest.w = gwiz.cursor->w;
    
    gwbr->classcursordest.x = gwbr->bonuscursordest.x + gwiz.number[20]->w
	+ (gwiz.tbord[0]->w*2) + gwiz.cursor->w + 2; /* 2=border pad */
    gwbr->classcursordest.y = gwbr->bonuscursordest.y;
    gwbr->classcursordest.w = gwbr->bonuscursordest.w;
    gwbr->classcursordest.h = gwbr->bonuscursordest.h;
    
    gwbr->bonuscursordestinit.x = gwbr->bonuscursordest.x;
    gwbr->bonuscursordestinit.y = gwbr->bonuscursordest.y;
    gwbr->bonuscursordestinit.h = gwiz.cursor->h;
    gwbr->bonuscursordestinit.w = gwiz.cursor->w;
    
    gwbr->classcursordestinit.x = gwbr->classcursordest.x;;
    gwbr->classcursordestinit.y = gwbr->bonuscursordest.y;
    gwbr->classcursordestinit.w = gwbr->bonuscursordest.w;
    gwbr->classcursordestinit.h = gwbr->bonuscursordest.h;
    /* end rects init */
    
    SDL_FreeSurface (bonus);
    SDL_FreeSurface (class);
    SDL_FreeSurface (instructions);
    SDL_FreeSurface (bonusstring);
    for (i = 0; i < 5; i++)
	SDL_FreeSurface (attrstrs[i]);
    for (i = 0; i < 3; i++)
	SDL_FreeSurface (instrstrs[i]);
    SDL_FreeSurface (tmp);
}

void BonusLoop (GwizBonusRect *gwbr)
{
    SDL_Event event;
    SDL_Rect dest;
    SDL_Rect irect;
    
    irect.x = gwiz.canvas->w/2 - gwbr->instructions->w/2;
    irect.y = gwiz.canvas->h - gwbr->instructions->h;
    irect.h = gwbr->instructions->h;
    irect.w = gwbr->instructions->w;
    dest.x = 0;
    dest.y = 0;
    dest.h = gwiz.canvas->h;
    dest.w = gwiz.canvas->w;
    
    SDL_BlitSurface (gwiz.cursor, NULL, gwiz.canvas,
		     &gwbr->bonuscursordestinit);
    ChangeBonusPoints (gwbr, 0); /* -1, 0, and 1 sub., noop, or add */
    
    while (SDL_WaitEvent (&event) != 0)  /* enter new permanent loop */
	{
	    SDL_Event *e = &event;
	    if (EventIsUp (e))
		MoveBonusCursor (gwbr, NORTH); /* "up" */
	    if (EventIsDown (e))
		MoveBonusCursor (gwbr, SOUTH); /* "down" */
	    if (EventIsLeft (e))
		ChangeBonusPoints (gwbr, -1);
	    if (EventIsRight (e))
		ChangeBonusPoints (gwbr, 1);
	    if (EventIsOk (e) && (gwbr->cursormode == 1))
		{
		    gwbr->pawn.class = gwbr->whichclasses[gwbr->position];
		    return;
		}
	    if (EventIsOk (e) && (gwbr->cursormode == 0) && (gwbr->bonus == 0))
		MoveBonusCursor (gwbr, EAST);
	    if (EventIsCancel (e) && (gwbr->cursormode == 1))
		MoveBonusCursor (gwbr, WEST);

	    SDL_BlitSurface(gwbr->instructions, NULL, gwiz.canvas, &irect);
	    SDL_Flip (gwiz.canvas);
	}
}

void MoveBonusCursor (GwizBonusRect *gwbr, int dir)
{
    if (gwbr->cursormode == 0)
	switch (dir)
	    {
	    case NORTH:
		if (gwbr->position == 0)
		    break; /* no wrapping here */
		gwbr->position--;
		SDL_FillRect (gwiz.canvas, &gwbr->bonuscursordest, 0);
		gwbr->bonuscursordest.y -= gwiz.font.height;
		SDL_BlitSurface (gwiz.cursor, NULL, gwiz.canvas,
				 &gwbr->bonuscursordest);
		break;
	    case SOUTH:
		if (gwbr->position == 5)
		    break; /* no wrapping down, either */
		gwbr->position++;
		SDL_FillRect (gwiz.canvas, &gwbr->bonuscursordest, 0);
		gwbr->bonuscursordest.y += gwiz.font.height;
		SDL_BlitSurface (gwiz.cursor, NULL, gwiz.canvas,
				 &gwbr->bonuscursordest);
		break;
	    case EAST:
		gwbr->position = 0;
		SDL_FillRect (gwiz.canvas, &gwbr->bonuscursordest, 0);
		SDL_BlitSurface (gwiz.cursor, NULL, gwiz.canvas,
				 &gwbr->classcursordestinit);
		gwbr->classcursordest.x = gwbr->classcursordestinit.x;
		gwbr->classcursordest.y = gwbr->classcursordestinit.y;
		gwbr->cursormode = 1;
		break;
	    case WEST:
		break;
	    }
    else
	switch (dir)
	    {
	    case NORTH:
		if (gwbr->position == 0)
		    break;
		gwbr->position--;
		SDL_FillRect (gwiz.canvas, &gwbr->classcursordest, 0);
		gwbr->classcursordest.y -= gwiz.font.height;
		SDL_BlitSurface (gwiz.cursor, NULL, gwiz.canvas,
				 &gwbr->classcursordest);
		break;
	    case SOUTH:
		if (gwbr->availclasses-1 == gwbr->position)
		    break;
		gwbr->position++;
		SDL_FillRect (gwiz.canvas, &gwbr->classcursordest, 0);
		gwbr->classcursordest.y += gwiz.font.height;
		SDL_BlitSurface (gwiz.cursor, NULL, gwiz.canvas,
				 &gwbr->classcursordest);
	    case EAST:
		break;
	    case WEST:
		gwbr->position = 0;
		SDL_FillRect (gwiz.canvas, &gwbr->classcursordest, 0);
		SDL_BlitSurface (gwiz.cursor, NULL, gwiz.canvas,
				 &gwbr->bonuscursordestinit);
		gwbr->bonuscursordest.x = gwbr->bonuscursordestinit.x;
		gwbr->bonuscursordest.y = gwbr->bonuscursordestinit.y;
		gwbr->cursormode = 0;
		gwbr->maxposition = 5;
		break;
	    }
}

void ChangeBonusPoints (GwizBonusRect *gwbr, int dir)
{
    SDL_Surface *list;
    SDL_Rect dest;
    SDL_Rect nd;
    
    /* leetly quit if you can't adjust a given variable :) */
    switch (dir)
	{
	case -1:
	    if (gwbr->bonusmax > gwbr->bonus)
	        {
		    switch (gwbr->position)
			{
			case 0:
			    if (gwbr->pawn.attr.str > gwbr->min[0])
				{
				    gwbr->pawn.attr.str--;
				    gwbr->bonus++;
				}
			    break;
			case 1:
			    if (gwbr->pawn.attr.iq > gwbr->min[1])
				{
				    gwbr->pawn.attr.iq--;
				    gwbr->bonus++;
				}
			    break;
			case 2:
			    if (gwbr->pawn.attr.dev > gwbr->min[2])
				{
				    gwbr->pawn.attr.dev--;
				    gwbr->bonus++;
				}
			    break;
			case 3:
			    if (gwbr->pawn.attr.vit > gwbr->min[3])
				{
				    gwbr->pawn.attr.vit--;
				    gwbr->bonus++;
				}
			    break;
			case 4:
			    if (gwbr->pawn.attr.agi > gwbr->min[4])
				{
				    gwbr->pawn.attr.agi--;
				    gwbr->bonus++;
				}
			    break;
			case 5:
			    if (gwbr->pawn.attr.luck > gwbr->min[5])
				{
				    gwbr->pawn.attr.luck--;
				    gwbr->bonus++;
				}
			    break;
			}
		}
	    break;
	case 0:
	    break; /* "Continue with no change */
	case 1:
	    if (gwbr->bonus > 0)
		{
		    switch (gwbr->position)
		        {
			case 0:
			    if (gwbr->pawn.attr.str < gwbr->max[0])
				{
				    gwbr->pawn.attr.str++;
				    gwbr->bonus--;
				}
			    break;
			case 1:
			    if (gwbr->pawn.attr.iq < gwbr->max[1])
				{
				    gwbr->pawn.attr.iq++;
				    gwbr->bonus--;
				}
			    break;
			case 2:
			    if (gwbr->pawn.attr.dev < gwbr->max[2])
				{
				    gwbr->pawn.attr.dev++;
				    gwbr->bonus--;
				}
			    break;
			case 3:
			    if (gwbr->pawn.attr.vit < gwbr->max[3])
				{
				    gwbr->pawn.attr.vit++;
				    gwbr->bonus--;
				}
			    break;
			case 4:
			    if (gwbr->pawn.attr.agi < gwbr->max[4])
				{
				    gwbr->pawn.attr.agi++;
				    gwbr->bonus--;
				}
			    break;
			case 5:
			    if (gwbr->pawn.attr.luck < gwbr->max[5])
				{
				    gwbr->pawn.attr.luck++;
				    gwbr->bonus--;
				}
			    break;
			}
		}
	default:
	    break;
	}
    
    dest.x = gwbr->bonuscursordestinit.x + gwiz.cursor->w;
    dest.y = gwbr->bonuscursordestinit.y - gwiz.font.height/2 +
	gwiz.cursor->h/2;
    list = NewGwizSurface (gwiz.number[20]->w, gwiz.font.height*8);
    
    dest.h = list->h;
    dest.w = list->w;

    nd.x = 0;
    nd.y = 0;
    nd.w = list->w;
    nd.h = gwiz.font.height;
    
    SDL_BlitSurface (gwiz.number[gwbr->pawn.attr.str], NULL, list, NULL);
    nd.y += gwiz.font.height;
    SDL_BlitSurface (gwiz.number[gwbr->pawn.attr.iq], NULL, list, &nd);
    nd.y += gwiz.font.height;
    SDL_BlitSurface (gwiz.number[gwbr->pawn.attr.dev], NULL, list, &nd);
    nd.y += gwiz.font.height;
    SDL_BlitSurface (gwiz.number[gwbr->pawn.attr.vit], NULL, list, &nd);
    nd.y += gwiz.font.height;
    SDL_BlitSurface (gwiz.number[gwbr->pawn.attr.agi], NULL, list, &nd);
    nd.y += gwiz.font.height; 
    SDL_BlitSurface (gwiz.number[gwbr->pawn.attr.luck], NULL, list, &nd);
    nd.y = list->h - gwiz.font.height;
    if (gwbr->bonus < 26)
	SDL_BlitSurface (gwiz.number[gwbr->bonus], NULL, list, &nd);
    else
	{
	    char *num = ItoA (gwbr->bonus, 3);
	    SDL_Surface *amount = GwizRenderText (num);
	    SDL_BlitSurface (amount, NULL, list, &nd);
	    Sfree (num);
	    SDL_FreeSurface (amount);
	}
    
    SDL_BlitSurface (list, NULL, gwiz.canvas, &dest);
    PopulateAvailableClasses(gwbr);
}

int PopulateAvailableClasses (GwizBonusRect *gwbr)
{
    SDL_Surface *classlist;
    SDL_Rect dest;
    SDL_Rect crect;
    int i = 0;
    
    /* over number, 2 borders, 2 pads, and the cursor width */
    dest.x = gwiz.canvas->w/2 + gwbr->area->w/2 - 1 - gwiz.tbord[0]->w -
	gwiz.classpix[0]->w;
    dest.y = gwiz.canvas->h/2 - gwbr->area->h/2 + gwiz.tbord[0]->w + 1;
    dest.h = gwiz.font.height;
    dest.w = gwiz.classpix[0]->w;
    crect.x = dest.x;
    crect.y = dest.y;
    crect.h = dest.h*6;
    crect.w = dest.w;
    
    classlist = NewGwizSurface (gwiz.classpix[0]->w, gwiz.font.height*6);
    
    SDL_BlitSurface (classlist, NULL, gwiz.canvas, &crect);
    gwbr->availclasses = 0;
	
    /* Long and ugly.  does exactly what I want, though.  :) */
    
    /* Fighter */
    if ((gwbr->pawn.attr.str > 10))
	{
	    SDL_BlitSurface (gwiz.classpix[0], NULL, gwiz.canvas, &dest);
	    dest.y += gwiz.font.height;
	    gwbr->availclasses++;
	    gwbr->whichclasses[i] = FIGHTER;
	    i++;
	}
    
    /* Mage */
    if ((gwbr->pawn.attr.iq > 10))
	{
	    SDL_BlitSurface (gwiz.classpix[1], NULL, gwiz.canvas, &dest);
	    dest.y += gwiz.font.height;
	    gwbr->availclasses++;
	    gwbr->whichclasses[i] = MAGE;
	    i++;
	}
    
    /* Cleric */
    if ((gwbr->pawn.attr.dev > 10) &&
	(gwbr->pawn.ali != NEUTRAL))
	{
	    SDL_BlitSurface (gwiz.classpix[2], NULL, gwiz.canvas, &dest);
	    dest.y += gwiz.font.height;
	    gwbr->availclasses++;
	    gwbr->whichclasses[i] = CLERIC;
	    i++;
	}
    
    /* Thief */
    if ((gwbr->pawn.attr.agi > 10) &&
	(gwbr->pawn.ali != GOOD))
	{
	    SDL_BlitSurface (gwiz.classpix[3], NULL, gwiz.canvas, &dest);
	    dest.y += gwiz.font.height;
	    gwbr->availclasses++;
	    gwbr->whichclasses[i] = THIEF;
	    i++;
	}
    
    /* Wizard */
    if ((gwbr->pawn.attr.dev > 11) &&
	(gwbr->pawn.attr.iq > 11) &&
	(gwbr->pawn.ali != NEUTRAL))
	{
	    SDL_BlitSurface (gwiz.classpix[4], NULL, gwiz.canvas, &dest);
	    dest.y += gwiz.font.height;
	    gwbr->availclasses++;
	    gwbr->whichclasses[i] = WIZARD;
	    i++;
	}
    
    /* Samurai */
    if ((gwbr->pawn.attr.str > 14) &&
	(gwbr->pawn.attr.iq > 10) &&
	(gwbr->pawn.attr.dev > 9) &&
	(gwbr->pawn.attr.vit > 13) &&
	(gwbr->pawn.attr.agi > 9) &&
	(gwbr->pawn.ali != EVIL))
	{
	    SDL_BlitSurface (gwiz.classpix[5], NULL, gwiz.canvas, &dest);
	    dest.y += gwiz.font.height;
	    gwbr->availclasses++;
	    gwbr->whichclasses[i] = SAMURAI;
	    i++;
	}
    
    /* Lord */
    if ((gwbr->pawn.attr.str > 14) &&
	(gwbr->pawn.attr.iq > 11) &&
	(gwbr->pawn.attr.dev > 11) &&
	(gwbr->pawn.attr.vit > 15) &&
	(gwbr->pawn.attr.agi > 13) &&
	(gwbr->pawn.attr.luck > 14) &&
	(gwbr->pawn.ali == GOOD))
	{
	    SDL_BlitSurface (gwiz.classpix[6], NULL, gwiz.canvas, &dest);
	    dest.y += gwiz.font.height;
	    gwbr->availclasses++;
	    gwbr->whichclasses[i] = LORD;
	    i++;
	}
    
    /* Ninja */
    if ((gwbr->pawn.attr.str > 14) &&
	(gwbr->pawn.attr.iq > 16) &&
	(gwbr->pawn.attr.dev > 14) &&
	(gwbr->pawn.attr.vit > 15) &&
	(gwbr->pawn.attr.agi > 14) &&
	(gwbr->pawn.attr.luck > 15) &&
	(gwbr->pawn.ali == EVIL))
	{
	    SDL_BlitSurface (gwiz.classpix[7], NULL, gwiz.canvas, &dest);
	    gwbr->availclasses++;
	    gwbr->whichclasses[i] = NINJA;
	    i++;
	}
    return gwbr->availclasses;
}

void GivePawnInitialEquipment (PlayerPawn *pawn)
{
    switch (pawn->class)
	{
	case FIGHTER:
	    LoadItem (&pawn->item[0], 4);
	    LoadItem (&pawn->item[1], 2);
	    break;
	case MAGE:
	    LoadItem (&pawn->item[0], 3);
	    LoadItem (&pawn->item[1], 6);
	    break;
	case CLERIC:
	    LoadItem (&pawn->item[0], 5);
	    LoadItem (&pawn->item[1], 6);
	    break;
	case WIZARD:
	    LoadItem (&pawn->item[0], 3);
	    LoadItem (&pawn->item[1], 6);
	    break;
	case THIEF:
	    LoadItem (&pawn->item[0], 2);
	    break;
	case SAMURAI:
	    LoadItem (&pawn->item[0], 4);
	    LoadItem (&pawn->item[1], 2);
	    break;
	case LORD:
	    LoadItem (&pawn->item[0], 1);
	    LoadItem (&pawn->item[1], 2);
	    break;
	case NINJA:
	    /* Ninjas don't get any equipment because it generally lowers their
	       performance. */
	    break;
	}
    /* Equipment should be equipped by default, right? */
    if (pawn->item[0].usage & USAGE_EQUIPPABLE)
	pawn->item[0].usage = (pawn->item[0].usage|USAGE_EQUIPPED);
    if (pawn->item[1].usage & USAGE_EQUIPPABLE)
	pawn->item[1].usage = (pawn->item[1].usage|USAGE_EQUIPPED);
}

void GivePawnInitialSpells (PlayerPawn *pawn)
{
    switch (pawn->class)
	{
	case MAGE:
	case SAMURAI:
	    pawn->spellsknown[IGNIS] = TRUE;
	    pawn->spellsknown[CLARITAS] = TRUE;
	    pawn->mm.spellpoints[0] = 2;
	    pawn->mm.maxpoints[0] = 2;
	    break;
	case CLERIC:
	case LORD:
	    pawn->spellsknown[MEDERI] = TRUE;
	    pawn->spellsknown[LUMEN] = TRUE;
	    pawn->cm.spellpoints[0] = 2;
	    pawn->cm.maxpoints[0] = 2;
	    break;
	case WIZARD:
	    pawn->spellsknown[IGNIS] = TRUE;
	    pawn->spellsknown[MEDERI] = TRUE;
	    pawn->mm.spellpoints[0] = 2;
	    pawn->cm.spellpoints[0] = 2;
	    pawn->mm.maxpoints[0] = 2;
	    pawn->cm.maxpoints[0] = 2;
	    break;
	}
}

void EnableCheatModeForPawn (PlayerPawn *pawn)
{
    pawn->counter.gp = 0x77000077; /* should be good for either endianness */
    /* other stuff (like magic, when I get that sorted out) goes here */
    pawn->counter.age = 15;
    pawn->counter.ep = 0x88000088;
}
