diff --git a/src/doors/dgnlance/combat.c b/src/doors/dgnlance/combat.c new file mode 100644 index 0000000000000000000000000000000000000000..9de9979f695a4a655139b90afd1db9a11728885d --- /dev/null +++ b/src/doors/dgnlance/combat.c @@ -0,0 +1,465 @@ +#include <stdlib.h> +#include <string.h> + +#include "xpdev.h" +#include "dgnlnce.h" +#include "fileutils.h" +#include "userfile.h" +#include "utils.h" + +double +tohit(struct playertype * attacker, struct playertype * defender) +{ + return ((attacker->attack * attacker->strength * attacker->dexterity * (xp_random(5) + 1) * attacker->vary) / + (defender->armour * defender->dexterity * defender->luck * defender->vary)); +} + +double +damage(struct playertype * attacker, struct playertype * defender) +{ + return ((attacker->power * attacker->strength * (xp_random(5) + 1) * (xp_random(5) + 1) * attacker->vary) / + ((defender->armour) * defender->luck * defender->vary)); +} + +void +endofbattle(BOOL won) +{ + int bt; + int d; + FILE *outfile; + char lstr[5]; + char wstr[5]; + struct playertype *winner; + struct playertype *loser; + if (opp.status != MONSTER) + loaduser(opp.name, TRUE, &tmpuser); + if (won) { + winner = &user; + loser = &tmpuser; + SAFECOPY(lstr, sexstrings(loser, HIS, FALSE)); + SAFECOPY(wstr, "You"); + } else { + winner = &tmpuser; + loser = &user; + SAFECOPY(lstr, sexstrings(winner, HIS, FALSE)); + SAFECOPY(lstr, "your"); + opp.experience = user.experience / 10; + } + if (opp.status == MONSTER) + opp.gold = opp.gold * supplant(); + nl(); + if (won) + od_printf("You take %s %" QWORDFORMAT " Steel pieces.\r\n", sexstrings(&opp, HIS, FALSE), opp.gold); + else { + if (opp.status != MONSTER) + od_printf("%s takes your %" QWORDFORMAT " Steel pieces.\r\n", sexstrings(&opp, HE, TRUE), opp.gold); + } + winner->gold += opp.gold; + loser->gold = 0; + + if (opp.status != MONSTER) { + nl(); + od_set_color(D_GREEN, D_BLACK); + if (won) { + od_printf("The Last Words %s Utters Are...\r\n", sexstrings(&tmpuser, HE, FALSE)); + nl(); + od_printf("\"%s\"\r\n", tmpuser.gaspd); + nl(); + } else { + od_disp_str("The Last Words You Hear Are...\r\n"); + nl(); + od_printf("\"%s\"\r\n", tmpuser.winmsg); + nl(); + } + winner->wins++; + loser->loses++; + SAFECOPY(loser->killer, winner->pseudo); + loser->status = DEAD; + if (loser->weapon > winner->weapon) { + d = winner->weapon; + winner->weapon = loser->weapon; + loser->weapon = d; + bt = winner->plus; + winner->plus = loser->plus; + loser->plus = bt; + od_set_color(D_GREEN, D_BLACK); + od_printf("%s Hath Taken %s Weapon.\r\n", wstr, lstr); + } + if (tmpuser.armour > user.armour) { + d = winner->armour; + winner->armour = loser->armour; + loser->armour = d; + od_set_color(L_YELLOW, D_BLACK); + od_printf("%s Hath Taken %s Armour.\r\n", wstr, lstr); + } + user.attack = weapon[user.weapon].attack; + user.power = weapon[user.weapon].power; + tmpuser.attack = weapon[tmpuser.weapon].attack; + tmpuser.power = weapon[tmpuser.weapon].power; + outfile = fopen("data/record.lan", "ab"); + fprintf(outfile, "%s attacked %s and %s was victorious!\r\n", user.pseudo, tmpuser.pseudo, loser->pseudo); + fclose(outfile); + } + opp.experience *= supplant(); + winner->experience += opp.experience; + if (won || opp.status != MONSTER) + od_printf("%s obtain %" QWORDFORMAT " exp points.\r\n", wstr, opp.experience); + + if (opp.status != MONSTER) + saveuser(&tmpuser); +} + +void +findo(void) +{ + int okea; + nl(); + od_set_color(L_YELLOW, D_BLACK); + od_disp_str("The Vile Enemy Dropped Something!\r\n"); + od_disp_str("Do you want to get it? "); + if (od_get_answer("YN") == 'Y') { + od_disp_str("Yes\r\n"); + okea = xp_random(99) + 1; + if ((okea < 10) && (user.weapon <= 25)) { + user.weapon++; + od_printf("You have found a %s.\r\n", weapon[user.weapon].name); + } + if ((okea > 11) && (okea < 40)) { + user.gold = user.gold + 40; + od_disp_str("You have come across 40 Steel pieces\r\n"); + } else + od_disp_str("It's gone!!!!\r\n"); + } else { + od_disp_str("No\r\n"); + od_disp_str("I wonder what it was?!?\r\n"); + } +} + +void +amode(void) +{ + double roll; /* Used for To Hit and damage rolls */ + int okea; + int tint; + roll = tohit(&user, &opp); + if (roll < 1.5) { + tint = xp_random(3) + 1; + switch (tint) { + case 1: + od_disp_str("Swish you missed!\r\n"); + break; + case 2: + od_printf("HA HA! %s dodges your swing!\r\n", sexstrings(&opp, HE, FALSE)); + break; + case 3: + od_disp_str("CLANG, The attack is blocked!\r\n"); + break; + case 4: + od_disp_str("You Fight vigorously and miss!\r\n"); + break; + } + } else { + roll = damage(&user, &opp); + if (roll > 5 * user.power) + roll = 5 * user.power; + if (roll < 1) + roll = 1; + opp.damage += roll; + tint = xp_random(2) + 1; + switch (tint) { + case 1: + od_printf("You sliced %s for %1.0f.\r\n", sexstrings(&opp, HIM, FALSE), roll); + break; + case 2: + od_printf("You made contact to %s body for %1.0f.\r\n", sexstrings(&opp, HIS, FALSE), roll); + break; + case 3: + od_printf("You hacked %s for %1.0f.", sexstrings(&opp, HIM, FALSE), roll); + break; + } + if (opp.hps <= opp.damage) { + nl(); + tint = xp_random(3) + 1; + switch (tint) { + case 1: + od_disp_str("A Painless Death!\r\n"); + break; + case 2: + od_printf("%s Hath died!\r\n", sexstrings(&opp, HE, TRUE)); + break; + case 3: + od_disp_str("A Smooth killing!\r\n"); + break; + case 4: + od_printf("%s has gone to the Abyss!\r\n", sexstrings(&opp, HE, TRUE)); + break; + } + okea = xp_random(99) + 1; + if (okea < 30) + findo(); + endofbattle(TRUE); + } + } +} + +void +bmode(void) +{ + double roll; /* Used for To Hit and damage rolls */ + int tint; + if ((opp.hps > opp.damage) && user.damage < user.hps) { + roll = tohit(&opp, &user); + if (roll < 1.5) { + od_set_color(D_GREEN, D_BLACK); + od_printf("%s attack tears your armour.\r\n", sexstrings(&opp, HIS, TRUE)); + } else { + roll = tohit(&opp, &user); + if (roll > 5 * opp.power) + roll = 5 * opp.power; + if (roll < 1) + roll = 1; + tint = xp_random(2) + 1; + switch (tint) { + case 1: + od_printf("%s hammered you for %1.0f.\r\n", sexstrings(&opp, HE, TRUE), roll); + break; + case 2: + od_printf("%s swung and hit for %1.0f.\r\n", sexstrings(&opp, HE, TRUE), roll); + break; + case 3: + od_printf("You are surprised when %s hits you for %1.0f.\r\n", sexstrings(&opp, HE, FALSE), roll); + break; + } + user.damage += roll; + if (user.damage >= user.hps) { + nl(); + tint = xp_random(3) + 1; + switch (tint) { + case 1: + od_disp_str("Return This Knight To Huma's Breast....\r\n"); + break; + case 2: + od_disp_str("You Hath Been Slain!!\r\n"); + break; + case 3: + od_disp_str("Return Soon Brave Warrior!\r\n"); + break; + case 4: + od_disp_str("May Palidine Be With You!!\r\n"); + break; + } + endofbattle(FALSE); + } + } + } +} + +void +searcher(char *filename) +{ + FILE *infile; + int a; + int rd; + infile = fopen(filename, "rb"); + user.fights--; + rd = xp_random(readnumb(0, infile) - 1) + 1; + endofline(infile); + for (a = 1; a <= rd; a++) { + readline(opp.pseudo, sizeof(opp.pseudo), infile); + opp.hps = readnumb(10, infile); + opp.damage = 0; + opp.attack = readnumb(1, infile); + opp.power = readnumb(1, infile); + opp.armour = readnumb(1, infile); + opp.luck = readnumb(1, infile); + opp.strength = readnumb(6, infile); + opp.dexterity = readnumb(6, infile); + opp.gold = readnumb(0, infile); + opp.experience = readnumb(0, infile); + opp.status = MONSTER; + opp.sex = 'I'; + endofline(infile); + } + fclose(infile); + opp.attack *= supplant(); + if (opp.attack < 1) + opp.attack = 1; + opp.power *= supplant(); + if (opp.power < 1) + opp.power = 1; + opp.armour *= supplant(); + if (opp.armour < 1) + opp.armour = 1; + opp.luck *= supplant(); + if (opp.luck < 1) + opp.luck = 1; + opp.strength *= supplant(); + if (opp.strength < 1) + opp.strength = 1; + opp.dexterity *= supplant(); + if (opp.dexterity < 1) + opp.dexterity = 1; + opp.hps *= supplant(); + if (opp.hps < 1) + opp.hps = 1; + opp.vary = supplant(); +} + +void +attackmodes(void) +{ + if (opp.dexterity > user.dexterity) { + if (user.damage < user.hps && opp.damage < opp.hps) + bmode(); + if (user.damage < user.hps && opp.damage < opp.hps) + amode(); + } else if (opp.dexterity < user.dexterity) { + if (user.damage < user.hps && opp.damage < opp.hps) + amode(); + if (user.damage < user.hps && opp.damage < opp.hps) + bmode(); + } else { + if (user.damage < user.hps && opp.damage < opp.hps) + amode(); + if (user.damage < user.hps && opp.damage < opp.hps) + bmode(); + } +} + +void +battle(void) +{ + WORD playerrem; + char option; + nl(); + while (user.damage < user.hps && opp.damage < opp.hps) { + playerrem = user.hps - user.damage; + nl(); + od_set_color(L_YELLOW, D_BLACK); + od_printf("You are attacked by a %s.\r\n", opp.pseudo); + for (option = '?'; option == '?';) { + od_set_color(L_BLUE, D_BLACK); + od_printf("Combat (%u hps): (B,F,S): ", playerrem); + option = od_get_answer("BFS?"); + if (option == '?') { + od_disp_str("Help\r\n"); + nl(); + nl(); + od_disp_str("(B)attle your opponent.\r\n"); + od_disp_str("(F)lee from your opponent.\r\n"); + od_disp_str("(S)tatus check.\r\n"); + nl(); + } + } + switch (option) { + case 'B': + od_disp_str("Battle\r\n"); + attackmodes(); + break; + case 'S': + od_disp_str("Stats\r\n"); + statshow(); + break; + case 'F': + od_disp_str("Flee\r\n"); + if ((xp_random(4) + 1) + user.dexterity > opp.dexterity) { + nl(); + od_set_color(D_GREEN, D_BLACK); + od_disp_str("You Ride away on a Silver Dragon.\r\n"); + return; + } + break; + } + } +} + +void +fight(char *filename) +{ + searcher(filename); + battle(); +} + +void +afight(int lev) +{ + char fname[32]; + if (user.fights == 0) { + nl(); + od_set_color(D_MAGENTA, D_BLACK); + od_disp_str("It's Getting Dark Out!\r\n"); + od_disp_str("Return to the Nearest Inn!\r\n"); + } else { + od_clr_scr(); + sprintf(fname, "data/junkm%d.lan", lev); + fight(fname); + } +} + +void +doggie(void) +{ + char tmphh[3]; + int a, i; + DWORD enemy; + BOOL finder; + FILE *infile; + char temp[81]; + if (user.battles > 0) { + nl(); + infile = fopen("data/characte.lan", "rb"); + for (finder = FALSE; finder == FALSE;) { + od_clr_scr(); + od_set_color(L_YELLOW, D_BLACK); + od_disp_str("Battle Another Hero:\r\n"); + od_disp_str("********************\r\n"); + i = 3; + a = 1; + fseek(infile, 0, SEEK_SET); + fgets(temp, sizeof(temp), infile); + while (loadnextuser(&opp, infile)) { + if (opp.r > user.r - 4) { + nl(); + od_set_color(D_MAGENTA, D_BLACK); + od_printf("%2u. `bright cyan`%.30s%.*s`bright blue`Lev=%-2u W=%-2" QWORDFORMAT " L=%-2" QWORDFORMAT " S=%s `blinking red`%s" + ,a++, opp.pseudo, 30 - strlen(opp.pseudo), dots + ,opp.r, opp.wins, opp.loses + ,((opp.status & DEAD) ? "SLAIN" : "ALIVE"), ((opp.status & ONLINE) ? "ONLINE" : "")); + if (++i >= od_control.user_screen_length) + pausescr(); + a += 1; + } + } + nl(); + od_set_color(L_CYAN, D_BLACK); + od_disp_str("Enter the # of your opponent: "); + od_input_str(tmphh, 2, '0', '9'); + enemy = strtoul(tmphh, NULL, 10); + if (enemy < 1 || enemy >= a) + continue; + fseek(infile, 0, SEEK_SET); + fgets(temp, sizeof(temp), infile); + for (a = 1; a <= enemy;) { + if (!loadnextuser(&opp, infile)) + opp.status = DEAD; + else if (opp.r > user.r - 4) + a++; + } + if ((!stricmp(opp.pseudo, user.pseudo)) || (opp.status == DEAD)) { + fclose(infile); + return; + } + finder = TRUE; + } + fclose(infile); + opp.status = PLAYER; + user.battles--; + opp.experience /= 10; + nl(); + od_disp_str("Your opponent screams out:\r\n"); + od_printf("\"%s\" as battle is joined.\r\n", opp.bcry); + nl(); + finder = FALSE; + battle(); + } +} diff --git a/src/doors/dgnlance/combat.h b/src/doors/dgnlance/combat.h new file mode 100644 index 0000000000000000000000000000000000000000..ff37b18b950f6b87b27b0a1cbc6f7d640ba39deb --- /dev/null +++ b/src/doors/dgnlance/combat.h @@ -0,0 +1,9 @@ +#ifndef _COMBAT_H_ +#define _COMBAT_H_ + +#include "dgnlnce.h" + +void afight(int lev); +void doggie(void); + +#endif diff --git a/src/doors/dgnlance/dgnlnce.c b/src/doors/dgnlance/dgnlnce.c index aec02b041cc406384413838e6d7f22ada2974282..c34e77c335503c365bba86d9fa292e29a51ec57a 100644 --- a/src/doors/dgnlance/dgnlnce.c +++ b/src/doors/dgnlance/dgnlnce.c @@ -3,180 +3,25 @@ #include <stdlib.h> #include <string.h> #include <time.h> -#include "OpenDoor.h" - -#define FIGHTS_PER_DAY 10 -#define BATTLES_PER_DAY 3 -#define FLIGHTS_PER_DAY 3 - -#ifndef INT64 -#ifdef _MSC_VER -#define INT64 __int64 -#else -#define INT64 long long int -#endif -#endif - -#ifndef INT64FORMAT -#ifdef __BORLANDC__ -#define INT64FORMAT "Ld" -#else -#ifdef _MSC_VER -#define INT64FORMAT "I64d" -#else -#define INT64FORMAT "lld" -#endif -#endif -#endif - -#ifndef QWORD -#ifdef _MSC_VER -#define QWORD unsigned _int64 -#else -#define QWORD unsigned long long int -#endif -#endif - -#ifndef QWORDFORMAT -#ifdef __BORLANDC__ -#define QWORDFORMAT "Lu" -#else -#ifdef _MSC_VER -#define QWORDFORMAT "I64u" -#else -#define QWORDFORMAT "llu" -#endif -#endif -#endif - -#define DEAD 1<<0 -#define ONLINE 1<<1 -/* Status for opponent != a player */ - -enum { - MONSTER - ,PLAYER -}; - -enum { - HE - ,HIS - ,HIM -}; - -struct playertype { - char name[31]; /* Name from BBS drop file */ - char pseudo[31]; /* In-game pseudonym */ - char killer[31]; /* Person killed by (if status==DEAD) */ - char bcry[61]; /* Battle Cry */ - char winmsg[61]; /* What you say when you win a battle */ - char gaspd[61]; /* Dying curse */ - char laston[11]; /* Last date one */ - char sex; /* Characters sex */ - DWORD status; /* Status alive or dead for player - * records, PLAYER or MONSTER for - * opponent record (record 0) */ - /* ToDo make configurable */ - WORD flights; /* Weird thing... may be number of - * times game can be ran per day */ - WORD plus; /* Weapon Bonus - Not currently Used */ - WORD r; /* Level */ - WORD strength; /* Str */ - WORD intelligence; /* Int */ - WORD dexterity; /* Dex */ - WORD constitution; /* Con */ - WORD charisma; /* Cha */ - QWORD experience; /* Exp */ - WORD luck; /* Luk */ - WORD weapon; /* Weapon Number */ - WORD armour; /* Armour Number */ - WORD hps; /* Hit Points */ - WORD damage; /* Damage taken so far */ - QWORD gold; /* Gold on hand */ - QWORD bank; /* Gold in bank */ - WORD attack; /* Weapon Attack */ - WORD power; /* Weapon Power */ - QWORD wins; /* Wins so far */ - QWORD loses; /* Losses so far */ - WORD battles; /* Battles left today */ - WORD fights; /* Fights left today */ - /* Players variance... applied to various rolls, Generally, how good the - * player is feeling. Is set at start and not modified */ - double vary; -}; - -struct weapon { - char name[31]; - WORD attack; - WORD power; - DWORD cost; -}; - - -struct armour { - char name[31]; - DWORD cost; -}; +#include "OpenDoor.h" +#include "xp64.h" +#include "xpdev.h" +#include "dgnlnce.h" +#include "combat.h" +#include "fileutils.h" +#include "userfile.h" +#include "utils.h" struct playertype player[3]; -/* player[1] is the current user */ -#define user player[1] -/* player[0] is the current enemy/temp player */ -#define opp player[0] -/* player[2] is the temporary user */ -#define tmpuser player[2] - -const char dots[] = "..............................................."; /* In these arrays, 0 isn't actually used */ QWORD required[29]; /* Experience required for each level */ struct weapon weapon[26]; struct armour armour[26]; -char temp[81]; -FILE *infile; /* Current input file */ -/************************/ -/* Functions from xpdev */ -/************************/ -#define SAFECOPY(dst,src) sprintf(dst,"%.*s",(int)sizeof(dst)-1,src) -#if defined(__unix__) -#if !defined(stricmp) -#define stricmp(x,y) strcasecmp(x,y) -#define strnicmp(x,y,z) strncasecmp(x,y,z) -#endif -#endif - -/****************************************************************************/ -/* Truncates all white-space chars off end of 'str' (needed by STRERRROR) */ -/****************************************************************************/ -char * -truncsp(char *str) -{ - size_t i, len; - i = len = strlen(str); - - while (i && (str[i - 1] == ' ' || str[i - 1] == '\t' || str[i - 1] == '\r' || str[i - 1] == '\n')) - i--; - if (i != len) - str[i] = 0; /* truncate */ - return (str); -} -int -xp_random(int n) -{ - float f; - static BOOL initialized; - if (!initialized) { - srand(time(NULL)); /* seed random number generator */ - rand(); /* throw away first result */ - initialized = TRUE; - } - if (n < 2) - return (0); - f = (float)rand() / (float)RAND_MAX; - return ((int)(n * f)); -} +const char dots[] = "..............................................."; +char temp[81]; /*****************************/ /* Functions from common.pas */ /*****************************/ @@ -190,61 +35,10 @@ date(void) strftime(retdate, sizeof(retdate), "%m/%d/%y", localtime(&now)); return (retdate); } - -void -pausescr(void) -{ - od_set_color(L_CYAN, D_BLACK); - od_disp_str("[Pause]"); - od_set_color(D_GREY, D_BLACK); - od_get_key(TRUE); - od_disp_str("\010 \010\010 \010\010 \010\010 \010\010 \010\010 \010\010 \010"); -} -#define nl() od_disp_str("\r\n"); - /********************************/ /* Functions from original .pas */ /********************************/ -void quickexit(void); -BOOL loadnextuser(struct playertype * plr); -BOOL loaduser(char *name, BOOL bbsname, struct playertype * plr); -void writenextuser(struct playertype * plr, FILE * outfile); - -double -playerattack(void) -{ - return ((user.attack * user.strength * user.dexterity * (xp_random(5) + 1) * user.vary) / - (opp.armour * opp.dexterity * opp.luck * opp.vary)); -} - -double -playerattack2(void) -{ - return ((user.power * user.strength * (xp_random(5) + 1) * (xp_random(5) + 1) * user.vary) / - ((opp.armour) * opp.luck * opp.vary)); -} - -double -opponentattack(void) -{ - return ((opp.attack * opp.strength * opp.dexterity * (xp_random(5) + 1) * opp.vary) / - (user.armour * user.dexterity * user.luck * user.vary)); -} - -double -opponentattack2(void) -{ - return ((opp.power * opp.strength * (xp_random(5) + 1) * (xp_random(5) + 1) * opp.vary) / - ((user.armour) * user.luck * user.vary)); -} - -double -supplant(void) -{ - return ((double)(xp_random(40) + 80)) / 100; -} - void depobank(void) { @@ -269,14 +63,6 @@ withdrawbank(void) od_printf("You are now carrying %" QWORDFORMAT " Steel pieces.\r\n", user.gold); } -char * -readline(char *buf, size_t size) -{ - fgets(buf, size, infile); - truncsp(buf); - return (buf); -} - void checkday(void) { @@ -284,10 +70,11 @@ checkday(void) DWORD h, i, j; FILE *outfile; BOOL newday = FALSE; + FILE *infile; struct playertype **playerlist = NULL; struct playertype **ra; infile = fopen("data/date.lan", "r+b"); - readline(oldy, sizeof(oldy)); + readline(oldy, sizeof(oldy), infile); if (strcmp(oldy, date())) { fseek(infile, 0, SEEK_SET); @@ -304,14 +91,14 @@ checkday(void) if (feof(infile)) return; i = 0; - while (loadnextuser(&tmpuser)) { + while (loadnextuser(&tmpuser, infile)) { ra = (struct playertype **) realloc(playerlist, sizeof(struct playertype *) * (i + 1)); if (ra == NULL) - quickexit(); + exit(1); playerlist = ra; playerlist[i] = (struct playertype *) malloc(sizeof(struct playertype)); if (playerlist[i] == NULL) - quickexit(); + exit(1); *playerlist[i] = tmpuser; if (newday) { playerlist[i]->battles = BATTLES_PER_DAY; @@ -334,7 +121,7 @@ checkday(void) } } outfile = fopen("data/characte.lan", "wb"); - fprintf(outfile, "%u\n", i); + fprintf(outfile, "%lu\n", i); for (j = 0; j < i; j++) { writenextuser(playerlist[j], outfile); free(playerlist[j]); @@ -347,6 +134,7 @@ void playerlist(void) { int i, a; + FILE *infile; checkday(); od_clr_scr(); nl(); @@ -357,7 +145,7 @@ playerlist(void) fgets(temp, sizeof(temp), infile); i = 3; a = 1; - while (loadnextuser(&tmpuser)) { + while (loadnextuser(&tmpuser, infile)) { nl(); od_set_color(D_MAGENTA, D_BLACK); od_printf("%2u. `bright cyan`%.30s%.*s`green`Lev=%-2u W=%-6" QWORDFORMAT " L=%-6" QWORDFORMAT " S=%s `blinking red`%s" @@ -371,85 +159,6 @@ playerlist(void) fclose(infile); } -void -writenextuser(struct playertype * plr, FILE * outfile) -{ - fprintf(outfile, "%s\n", plr->name); - fprintf(outfile, "%s\n", plr->pseudo); - fprintf(outfile, "%c\n", plr->sex); - fprintf(outfile, "%s\n", plr->gaspd); - fprintf(outfile, "%s\n", plr->laston); - fprintf(outfile, "%u\n", plr->status); - if (plr->status == DEAD) - fprintf(outfile, "%s\n", plr->killer); - fprintf(outfile, "%u %u %u %u %u %u %" QWORDFORMAT " %u %u %u %u %" QWORDFORMAT " %u %" QWORDFORMAT " %" QWORDFORMAT " %" QWORDFORMAT " %u %u %u %1.4f\n", - plr->strength, plr->intelligence, - plr->luck, plr->dexterity, plr->constitution, - plr->charisma, plr->experience, - plr->r, plr->hps, plr->weapon, - plr->armour, plr->gold, - plr->flights, plr->bank, plr->wins, plr->loses, - plr->plus, plr->fights, plr->battles, plr->vary); -} - -void -saveuser(struct playertype * plr) -{ - DWORD h, i, j; - FILE *outfile; - struct playertype **playerlist = NULL; - struct playertype **ra; - BOOL saved = FALSE; - infile = fopen("data/characte.lan", "rb"); - fgets(temp, sizeof(temp), infile); - i = 0; - while (loadnextuser(&tmpuser)) { - ra = (struct playertype **) realloc(playerlist, sizeof(plr) * (i + 1)); - if (ra == NULL) - quickexit(); - playerlist = ra; - playerlist[i] = (struct playertype *) malloc(sizeof(struct playertype)); - if (playerlist[i] == NULL) - quickexit(); - if (!stricmp(tmpuser.name, plr->name)) { - *playerlist[i] = *plr; - saved = TRUE; - } else - *playerlist[i] = tmpuser; - i++; - } - fclose(infile); - - if (!saved) { - ra = (struct playertype **) realloc(playerlist, sizeof(plr) * (i + 1)); - if (ra == NULL) - quickexit(); - playerlist = ra; - playerlist[i] = (struct playertype *) malloc(sizeof(struct playertype)); - if (playerlist[i] == NULL) - quickexit(); - *playerlist[i] = *plr; - i++; - } - for (j = 0; j < (i - 1); j++) { - for (h = j + 1; h < i; h++) { - if (playerlist[h]->experience > playerlist[j]->experience) { - tmpuser = *playerlist[h]; - *playerlist[h] = *playerlist[j]; - *playerlist[j] = tmpuser; - } - } - } - outfile = fopen("data/characte.lan", "wb"); - fprintf(outfile, "%u\n", i); - for (j = 0; j < i; j++) { - writenextuser(playerlist[j], outfile); - free(playerlist[j]); - } - free(playerlist); - fclose(outfile); -} - void leave(void) { @@ -483,174 +192,6 @@ heal(void) od_printf("%u hit points healed.\r\n", opt); } -void -findo(void) -{ - int okea; - nl(); - od_set_color(L_YELLOW, D_BLACK); - od_disp_str("The Vile Enemy Dropped Something!\r\n"); - od_disp_str("Do you want to get it? "); - if (od_get_answer("YN") == 'Y') { - od_disp_str("Yes\r\n"); - okea = xp_random(99) + 1; - if ((okea < 10) && (user.weapon <= 25)) { - user.weapon++; - od_printf("You have found a %s.\r\n", weapon[user.weapon].name); - } - if ((okea > 11) && (okea < 40)) { - user.gold = user.gold + 40; - od_disp_str("You have come across 40 Steel pieces\r\n"); - } else - od_disp_str("It's gone!!!!\r\n"); - } else { - od_disp_str("No\r\n"); - od_disp_str("I wonder what it was?!?\r\n"); - } -} - -void battle(void); - -char * -sexstrings(struct playertype * plr, int type, BOOL cap) -{ - static char retbuf[16]; - char sex; - sex = plr->sex; - if (plr->charisma < 8) - sex = 'I'; - switch (sex) { - case 'M': - switch (type) { - case HIS: - SAFECOPY(retbuf, "his"); - break; - case HE: - SAFECOPY(retbuf, "he"); - break; - case HIM: - SAFECOPY(retbuf, "him"); - break; - } - case 'F': - switch (type) { - case HIS: - SAFECOPY(retbuf, "her"); - break; - case HE: - SAFECOPY(retbuf, "she"); - break; - case HIM: - SAFECOPY(retbuf, "her"); - break; - } - case 'I': - switch (type) { - case HIS: - SAFECOPY(retbuf, "its"); - break; - case HE: - SAFECOPY(retbuf, "it"); - break; - case HIM: - SAFECOPY(retbuf, "it"); - break; - } - } - if (cap) - retbuf[0] = toupper(retbuf[0]); - return (retbuf); -} - -void -endofbattle(BOOL won) -{ - int bt; - int d; - FILE *outfile; - char lstr[5]; - char wstr[5]; - struct playertype *winner; - struct playertype *loser; - if (opp.status != MONSTER) - loaduser(opp.name, TRUE, &tmpuser); - if (won) { - winner = &user; - loser = &tmpuser; - SAFECOPY(lstr, sexstrings(loser, HIS, FALSE)); - SAFECOPY(wstr, "You"); - } else { - winner = &tmpuser; - loser = &user; - SAFECOPY(lstr, sexstrings(winner, HIS, FALSE)); - SAFECOPY(lstr, "your"); - opp.experience = user.experience / 10; - } - - if (opp.status == MONSTER) - opp.gold = opp.gold * supplant(); - nl(); - if (won) - od_printf("You take %s %" QWORDFORMAT " Steel pieces.\r\n", sexstrings(&opp, HIS, FALSE), opp.gold); - else { - if (opp.status != MONSTER) - od_printf("%s takes your %" QWORDFORMAT " Steel pieces.\r\n", sexstrings(&opp, HE, TRUE), opp.gold); - } - winner->gold += opp.gold; - loser->gold = 0; - - if (opp.status != MONSTER) { - nl(); - od_set_color(D_GREEN, D_BLACK); - if (won) { - od_printf("The Last Words %s Utters Are...\r\n", sexstrings(&tmpuser, HE, FALSE)); - nl(); - od_printf("\"%s\"\r\n", tmpuser.gaspd); - nl(); - } else { - od_disp_str("The Last Words You Hear Are...\r\n"); - nl(); - od_printf("\"%s\"\r\n", tmpuser.winmsg); - nl(); - } - winner->wins++; - loser->loses++; - SAFECOPY(loser->killer, winner->pseudo); - loser->status = DEAD; - if (loser->weapon > winner->weapon) { - d = winner->weapon; - winner->weapon = loser->weapon; - loser->weapon = d; - bt = winner->plus; - winner->plus = loser->plus; - loser->plus = bt; - od_set_color(D_GREEN, D_BLACK); - od_printf("%s Hath Taken %s Weapon.\r\n", wstr, lstr); - } - if (tmpuser.armour > user.armour) { - d = winner->armour; - winner->armour = loser->armour; - loser->armour = d; - od_set_color(L_YELLOW, D_BLACK); - od_printf("%s Hath Taken %s Armour.\r\n", wstr, lstr); - } - user.attack = weapon[user.weapon].attack; - user.power = weapon[user.weapon].power; - tmpuser.attack = weapon[tmpuser.weapon].attack; - tmpuser.power = weapon[tmpuser.weapon].power; - outfile = fopen("data/record.lan", "ab"); - fprintf(outfile, "%s attacked %s and %s was victorious!\r\n", user.pseudo, tmpuser.pseudo, loser->pseudo); - fclose(outfile); - } - opp.experience *= supplant(); - winner->experience += opp.experience; - if (won || opp.status != MONSTER) - od_printf("%s obtain %" QWORDFORMAT " exp points.\r\n", wstr, opp.experience); - - if (opp.status != MONSTER) - saveuser(&tmpuser); -} - void levelupdate(void) { @@ -683,152 +224,6 @@ levelupdate(void) user.hps = user.hps + (xp_random(5) + 1) + (user.constitution / 4); } } - -void -quickexit(void) -{ - od_disp_str("The Gods of Krynn Disapprove of your actions!\r\n"); - exit(1); -} - -void -amode(void) -{ - double roll; /* Used for To Hit and damage rolls */ - int okea; - int tint; - roll = playerattack(); - if (roll < 1.5) { - tint = xp_random(3) + 1; - switch (tint) { - case 1: - od_disp_str("Swish you missed!\r\n"); - break; - case 2: - od_printf("HA HA! %s dodges your swing!\r\n", sexstrings(&opp, HE, FALSE)); - break; - case 3: - od_disp_str("CLANG, The attack is blocked!\r\n"); - break; - case 4: - od_disp_str("You Fight vigorously and miss!\r\n"); - break; - } - } else { - roll = playerattack2(); - if (roll > 5 * user.power) - roll = 5 * user.power; - if (roll < 1) - roll = 1; - opp.damage += roll; - tint = xp_random(2) + 1; - switch (tint) { - case 1: - od_printf("You sliced %s for %1.0f.\r\n", sexstrings(&opp, HIM, FALSE), roll); - break; - case 2: - od_printf("You made contact to %s body for %1.0f.\r\n", sexstrings(&opp, HIS, FALSE), roll); - break; - case 3: - od_printf("You hacked %s for %1.0f.", sexstrings(&opp, HIM, FALSE), roll); - break; - } - if (opp.hps <= opp.damage) { - nl(); - tint = xp_random(3) + 1; - switch (tint) { - case 1: - od_disp_str("A Painless Death!\r\n"); - break; - case 2: - od_printf("%s Hath died!\r\n", sexstrings(&opp, HE, TRUE)); - break; - case 3: - od_disp_str("A Smooth killing!\r\n"); - break; - case 4: - od_printf("%s has gone to the Abyss!\r\n", sexstrings(&opp, HE, TRUE)); - break; - } - okea = xp_random(99) + 1; - if (okea < 30) - findo(); - endofbattle(TRUE); - } - } -} - -void -bmode(void) -{ - double roll; /* Used for To Hit and damage rolls */ - int tint; - if ((opp.hps > opp.damage) && user.damage < user.hps) { - roll = opponentattack(); - if (roll < 1.5) { - od_set_color(D_GREEN, D_BLACK); - od_printf("%s attack tears your armour.\r\n", sexstrings(&opp, HIS, TRUE)); - } else { - roll = opponentattack2(); - if (roll > 5 * opp.power) - roll = 5 * opp.power; - if (roll < 1) - roll = 1; - tint = xp_random(2) + 1; - switch (tint) { - case 1: - od_printf("%s hammered you for %1.0f.\r\n", sexstrings(&opp, HE, TRUE), roll); - break; - case 2: - od_printf("%s swung and hit for %1.0f.\r\n", sexstrings(&opp, HE, TRUE), roll); - break; - case 3: - od_printf("You are surprised when %s hits you for %1.0f.\r\n", sexstrings(&opp, HE, FALSE), roll); - break; - } - user.damage += roll; - if (user.damage >= user.hps) { - nl(); - tint = xp_random(3) + 1; - switch (tint) { - case 1: - od_disp_str("Return This Knight To Huma's Breast....\r\n"); - break; - case 2: - od_disp_str("You Hath Been Slain!!\r\n"); - break; - case 3: - od_disp_str("Return Soon Brave Warrior!\r\n"); - break; - case 4: - od_disp_str("May Palidine Be With You!!\r\n"); - break; - } - endofbattle(FALSE); - } - } - } -} - -void -statshow(void) -{ - od_clr_scr(); - od_set_color(D_MAGENTA, D_BLACK); - od_printf("Name: %s Level: %d\r\n", user.pseudo, user.r); - od_set_color(L_CYAN, D_BLACK); - od_printf("W/L: %" QWORDFORMAT "/%" QWORDFORMAT " Exp: %" QWORDFORMAT "\r\n", user.wins, user.loses, user.experience); - nl(); - od_set_color(L_YELLOW, D_BLACK); - od_printf("Steel (in hand): %" QWORDFORMAT "\r\n", user.gold); - od_printf("Steel (in bank): %" QWORDFORMAT "\r\n", user.bank); - nl(); - od_set_color(L_BLUE, D_BLACK); - od_printf("Battles: %u Retreats: %u Fights: %u Hps: %u(%u)\r\n", user.battles, user.flights, user.fights, user.hps - user.damage, user.hps); - nl(); - od_set_color(L_CYAN, D_BLACK); - od_printf("Weapon: %s Armor: %s\r\n", weapon[user.weapon].name, armour[user.armour].name); -} BOOL incre(void) { @@ -986,266 +381,6 @@ chstats(void) } } -void -attackmodes(void) -{ - if (opp.dexterity > user.dexterity) { - if (user.damage < user.hps && opp.damage < opp.hps) - bmode(); - if (user.damage < user.hps && opp.damage < opp.hps) - amode(); - } else if (opp.dexterity < user.dexterity) { - if (user.damage < user.hps && opp.damage < opp.hps) - amode(); - if (user.damage < user.hps && opp.damage < opp.hps) - bmode(); - } else { - if (user.damage < user.hps && opp.damage < opp.hps) - amode(); - if (user.damage < user.hps && opp.damage < opp.hps) - bmode(); - } -} - -double -readfloat(float deflt) -{ - char buf[101]; - int pos = 0; - int rd; - double ret; - buf[0] = 0; - while ((rd = fgetc(infile)) != EOF) { - if (rd == '\r') - continue; - if (rd == '\n') { - ungetc('\n', infile); - break; - } - /* Skip leading spaces */ - if (!pos && isspace(rd)) - continue; - if (isspace(rd)) - break; - buf[pos++] = rd; - } - if (!pos) - return (deflt); - buf[pos++] = 0; - ret = strtod(buf, NULL); - return (ret); -} - -QWORD -readnumb(QWORD deflt) -{ - char buf[101]; - int pos = 0; - int rd; - QWORD ret; - buf[0] = 0; - - while ((rd = fgetc(infile)) != EOF) { - if (rd == '\r') - continue; - if (rd == '\n') { - ungetc('\n', infile); - break; - } - /* Skip leading spaces */ - if (!pos && isspace(rd)) - continue; - if (isspace(rd)) - break; - buf[pos++] = rd; - } - if (!pos) - return (deflt); - buf[pos++] = 0; - ret = strtoull(buf, NULL, 10); - return (ret); -} - -void -endofline(void) -{ - int rd; - while ((rd = fgetc(infile)) != EOF) { - if (rd == '\n'); - break; - } -} - -void -searcher(void) -{ - int a; - int rd; - user.fights--; - rd = xp_random(readnumb(0) - 1) + 1; - endofline(); - for (a = 1; a <= rd; a++) { - readline(opp.pseudo, sizeof(opp.pseudo)); - opp.hps = readnumb(10); - opp.damage = 0; - opp.attack = readnumb(1); - opp.power = readnumb(1); - opp.armour = readnumb(1); - opp.luck = readnumb(1); - opp.strength = readnumb(6); - opp.dexterity = readnumb(6); - opp.gold = readnumb(0); - opp.experience = readnumb(0); - opp.status = MONSTER; - opp.sex = 'I'; - endofline(); - } - fclose(infile); - opp.attack *= supplant(); - if (opp.attack < 1) - opp.attack = 1; - opp.power *= supplant(); - if (opp.power < 1) - opp.power = 1; - opp.armour *= supplant(); - if (opp.armour < 1) - opp.armour = 1; - opp.luck *= supplant(); - if (opp.luck < 1) - opp.luck = 1; - opp.strength *= supplant(); - if (opp.strength < 1) - opp.strength = 1; - opp.dexterity *= supplant(); - if (opp.dexterity < 1) - opp.dexterity = 1; - opp.hps *= supplant(); - if (opp.hps < 1) - opp.hps = 1; - opp.vary = supplant(); -} - -void -fight(char *filename) -{ - infile = fopen(filename, "rb"); - searcher(); - battle(); -} - -void -doggie(void) -{ - char tmphh[3]; - int a, i; - DWORD enemy; - BOOL finder; - if (user.battles > 0) { - nl(); - infile = fopen("data/characte.lan", "rb"); - for (finder = FALSE; finder == FALSE;) { - od_clr_scr(); - od_set_color(L_YELLOW, D_BLACK); - od_disp_str("Battle Another Hero:\r\n"); - od_disp_str("********************\r\n"); - i = 3; - a = 1; - fseek(infile, 0, SEEK_SET); - fgets(temp, sizeof(temp), infile); - while (loadnextuser(&opp)) { - if (opp.r > user.r - 4) { - nl(); - od_set_color(D_MAGENTA, D_BLACK); - od_printf("%2u. `bright cyan`%.30s%.*s`bright blue`Lev=%-2u W=%-2" QWORDFORMAT " L=%-2" QWORDFORMAT " S=%s `blinking red`%s" - ,a++, opp.pseudo, 30 - strlen(opp.pseudo), dots - ,opp.r, opp.wins, opp.loses - ,((opp.status & DEAD) ? "SLAIN" : "ALIVE"), ((opp.status & ONLINE) ? "ONLINE" : "")); - if (++i >= od_control.user_screen_length) - pausescr(); - a += 1; - } - } - nl(); - od_set_color(L_CYAN, D_BLACK); - od_disp_str("Enter the # of your opponent: "); - od_input_str(tmphh, 2, '0', '9'); - enemy = strtoul(tmphh, NULL, 10); - if (enemy < 1 || enemy >= a) - continue; - fseek(infile, 0, SEEK_SET); - fgets(temp, sizeof(temp), infile); - for (a = 1; a <= enemy;) { - if (!loadnextuser(&opp)) - opp.status = DEAD; - else if (opp.r > user.r - 4) - a++; - } - if ((!stricmp(opp.pseudo, user.pseudo)) || (opp.status == DEAD)) { - fclose(infile); - return; - } - finder = TRUE; - } - fclose(infile); - opp.status = PLAYER; - user.battles--; - opp.experience /= 10; - nl(); - od_disp_str("Your opponent screams out:\r\n"); - od_printf("\"%s\" as battle is joined.\r\n", opp.bcry); - nl(); - finder = FALSE; - battle(); - } -} - -void -battle(void) -{ - WORD playerrem; - char option; - nl(); - while (user.damage < user.hps && opp.damage < opp.hps) { - playerrem = user.hps - user.damage; - nl(); - od_set_color(L_YELLOW, D_BLACK); - od_printf("You are attacked by a %s.\r\n", opp.pseudo); - for (option = '?'; option == '?';) { - od_set_color(L_BLUE, D_BLACK); - od_printf("Combat (%u hps): (B,F,S): ", playerrem); - option = od_get_answer("BFS?"); - if (option == '?') { - od_disp_str("Help\r\n"); - nl(); - nl(); - od_disp_str("(B)attle your opponent.\r\n"); - od_disp_str("(F)lee from your opponent.\r\n"); - od_disp_str("(S)tatus check.\r\n"); - nl(); - } - } - switch (option) { - case 'B': - od_disp_str("Battle\r\n"); - attackmodes(); - break; - case 'S': - od_disp_str("Stats\r\n"); - statshow(); - break; - case 'F': - od_disp_str("Flee\r\n"); - if ((xp_random(4) + 1) + user.dexterity > opp.dexterity) { - nl(); - od_set_color(D_GREEN, D_BLACK); - od_disp_str("You Ride away on a Silver Dragon.\r\n"); - return; - } - break; - } - } -} - void credits(void) { @@ -1584,22 +719,6 @@ gamble(void) } } -void -afight(int lev) -{ - char fname[32]; - if (user.fights == 0) { - nl(); - od_set_color(D_MAGENTA, D_BLACK); - od_disp_str("It's Getting Dark Out!\r\n"); - od_disp_str("Return to the Nearest Inn!\r\n"); - } else { - od_clr_scr(); - sprintf(fname, "data/junkm%d.lan", lev); - fight(fname); - } -} - void bulletin(void) { @@ -1740,86 +859,13 @@ menuit(void) od_clr_scr(); od_send_file("text/menu"); } -BOOL -loadnextuser(struct playertype * plr) -{ - if (feof(infile)) - return (FALSE); - readline(plr->name, sizeof(plr->name)); - if (feof(infile)) - return (FALSE); - readline(plr->pseudo, sizeof(plr->pseudo)); - if (feof(infile)) - return (FALSE); - fread(&plr->sex, 1, 1, infile); - endofline(); - if (feof(infile)) - return (FALSE); - readline(plr->gaspd, sizeof(plr->gaspd)); - if (feof(infile)) - return (FALSE); - readline(plr->laston, sizeof(plr->laston)); - if (feof(infile)) - return (FALSE); - fgets(temp, sizeof(temp), infile); - plr->status = strtoul(temp, NULL, 10); - if (feof(infile)) - return (FALSE); - if (plr->status == DEAD) { - readline(plr->killer, sizeof(plr->killer)); - if (feof(infile)) - return (FALSE); - } - plr->strength = readnumb(6); - plr->intelligence = readnumb(6); - plr->luck = readnumb(6); - plr->dexterity = readnumb(6); - plr->constitution = readnumb(6); - plr->charisma = readnumb(6); - plr->experience = readnumb(0); - plr->r = readnumb(1); - plr->hps = readnumb(10); - plr->weapon = readnumb(1); - plr->armour = readnumb(1); - plr->gold = readnumb(0); - plr->flights = readnumb(3); - plr->bank = readnumb(0); - plr->wins = readnumb(0); - plr->loses = readnumb(0); - plr->plus = readnumb(0); - plr->fights = readnumb(FIGHTS_PER_DAY); - plr->battles = readnumb(BATTLES_PER_DAY); - plr->vary = readfloat(supplant()); - endofline(); - return (TRUE); -} -BOOL -loaduser(char *name, BOOL bbsname, struct playertype * plr) -{ - infile = fopen("data/characte.lan", "rb"); - fgets(temp, sizeof(temp), infile); - while (loadnextuser(plr)) { - if (bbsname) { - if (!stricmp(plr->name, name)) { - fclose(infile); - return (TRUE); - } - } else { - if (!stricmp(plr->pseudo, name)) { - fclose(infile); - return (TRUE); - } - } - } - fclose(infile); - return (FALSE); -} int main(int argc, char **argv) { DWORD i; BOOL found; + FILE *infile; od_init(); checkday(); atexit(leave); @@ -1867,30 +913,30 @@ main(int argc, char **argv) infile = fopen("data/weapons.lan", "rb"); od_set_color(L_BLUE, D_BLACK); for (i = 1; i <= 25; i++) { - readline(weapon[i].name, sizeof(weapon[i].name)); - weapon[i].attack = readnumb(1); - weapon[i].power = readnumb(1); - endofline(); + readline(weapon[i].name, sizeof(weapon[i].name), infile); + weapon[i].attack = readnumb(1, infile); + weapon[i].power = readnumb(1, infile); + endofline(infile); } fclose(infile); infile = fopen("data/armor.lan", "rb"); od_set_color(L_BLUE, D_BLACK); for (i = 1; i <= 25; i++) - readline(armour[i].name, sizeof(armour[i].name)); + readline(armour[i].name, sizeof(armour[i].name), infile); fclose(infile); infile = fopen("data/prices.lan", "rb"); for (i = 1; i <= 25; i++) { - weapon[i].cost = readnumb(100000000); + weapon[i].cost = readnumb(100000000, infile); armour[i].cost = weapon[i].cost; - endofline(); + endofline(infile); } fclose(infile); user.attack = weapon[user.weapon].attack; user.power = weapon[user.weapon].power; infile = fopen("data/experience.lan", "rb"); for (i = 1; i <= 28; i++) { - required[i] = readnumb(100000000); - endofline(); + required[i] = readnumb(100000000, infile); + endofline(infile); } fclose(infile); od_set_color(L_YELLOW, D_BLACK); diff --git a/src/doors/dgnlance/dgnlnce.h b/src/doors/dgnlance/dgnlnce.h new file mode 100644 index 0000000000000000000000000000000000000000..3a0ba6fec66e58295161c7ae940d1d7e8781ad76 --- /dev/null +++ b/src/doors/dgnlance/dgnlnce.h @@ -0,0 +1,101 @@ +#ifndef _DGNLNCE_H_ +#define _DGNLNCE_H_ + +#include <stdio.h> + +#include "xp64.h" +#include "OpenDoor.h" + +#define FIGHTS_PER_DAY 10 +#define BATTLES_PER_DAY 3 +#define FLIGHTS_PER_DAY 3 + +#define DEAD 1<<0 +#define ONLINE 1<<1 + +/* Status for opponent */ +enum { + MONSTER + ,PLAYER +}; + +/* Used for sextrings() */ +enum { + HE + ,HIS + ,HIM +}; + +struct playertype { + char name[31]; /* Name from BBS drop file */ + char pseudo[31]; /* In-game pseudonym */ + char killer[31]; /* Person killed by (if status==DEAD) */ + char bcry[61]; /* Battle Cry */ + char winmsg[61]; /* What you say when you win a battle */ + char gaspd[61]; /* Dying curse */ + char laston[11]; /* Last date one */ + char sex; /* Characters sex */ + DWORD status; /* Status alive or dead for player + * records, PLAYER or MONSTER for + * opponent record (record 0) */ + /* ToDo make configurable */ + WORD flights; /* Weird thing... may be number of + * times game can be ran per day */ + WORD plus; /* Weapon Bonus - Not currently Used */ + WORD r; /* Level */ + WORD strength; /* Str */ + WORD intelligence; /* Int */ + WORD dexterity; /* Dex */ + WORD constitution; /* Con */ + WORD charisma; /* Cha */ + QWORD experience; /* Exp */ + WORD luck; /* Luk */ + WORD weapon; /* Weapon Number */ + WORD armour; /* Armour Number */ + WORD hps; /* Hit Points */ + WORD damage; /* Damage taken so far */ + QWORD gold; /* Gold on hand */ + QWORD bank; /* Gold in bank */ + WORD attack; /* Weapon Attack */ + WORD power; /* Weapon Power */ + QWORD wins; /* Wins so far */ + QWORD loses; /* Losses so far */ + WORD battles; /* Battles left today */ + WORD fights; /* Fights left today */ + /* Players variance... applied to various rolls, Generally, how good the + * player is feeling. Is set at start and not modified */ + double vary; +}; + +struct weapon { + char name[31]; + WORD attack; + WORD power; + DWORD cost; +}; + +struct armour { + char name[31]; + DWORD cost; +}; + + +extern struct playertype player[3]; +/* player[1] is the current user */ +#define user player[1] +/* player[0] is the current enemy */ +#define opp player[0] +/* player[2] is the temporary user */ +#define tmpuser player[2] + +/* In these arrays, 0 isn't actually used */ +extern QWORD required[29]; /* Experience required for each level */ +extern struct weapon weapon[26]; +extern struct armour armour[26]; +extern const char dots[]; +FILE *infile; /* Current input file */ + +/* Utility macros */ +#define nl() od_disp_str("\r\n"); + +#endif diff --git a/src/doors/dgnlance/fileutils.c b/src/doors/dgnlance/fileutils.c new file mode 100644 index 0000000000000000000000000000000000000000..7adbb7a8fe51670eb6384355fe2be302457bba8c --- /dev/null +++ b/src/doors/dgnlance/fileutils.c @@ -0,0 +1,83 @@ +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> + +#include "xpdev.h" /* truncsp() */ +#include "fileutils.h" + +char * +readline(char *buf, size_t size, FILE * infile) +{ + fgets(buf, size, infile); + truncsp(buf); + return (buf); +} + +double +readfloat(float deflt, FILE * infile) +{ + char buf[101]; + int pos = 0; + int rd; + double ret; + buf[0] = 0; + while ((rd = fgetc(infile)) != EOF) { + if (rd == '\r') + continue; + if (rd == '\n') { + ungetc('\n', infile); + break; + } + /* Skip leading spaces */ + if (!pos && isspace(rd)) + continue; + if (isspace(rd)) + break; + buf[pos++] = rd; + } + if (!pos) + return (deflt); + buf[pos++] = 0; + ret = strtod(buf, NULL); + return (ret); +} + +QWORD +readnumb(QWORD deflt, FILE * infile) +{ + char buf[101]; + int pos = 0; + int rd; + QWORD ret; + buf[0] = 0; + + while ((rd = fgetc(infile)) != EOF) { + if (rd == '\r') + continue; + if (rd == '\n') { + ungetc('\n', infile); + break; + } + /* Skip leading spaces */ + if (!pos && isspace(rd)) + continue; + if (isspace(rd)) + break; + buf[pos++] = rd; + } + if (!pos) + return (deflt); + buf[pos++] = 0; + ret = strtoull(buf, NULL, 10); + return (ret); +} + +void +endofline(FILE * infile) +{ + int rd; + while ((rd = fgetc(infile)) != EOF) { + if (rd == '\n'); + break; + } +} diff --git a/src/doors/dgnlance/fileutils.h b/src/doors/dgnlance/fileutils.h new file mode 100644 index 0000000000000000000000000000000000000000..3c116de6b61cfce6e72c90a519b7ae652290f89b --- /dev/null +++ b/src/doors/dgnlance/fileutils.h @@ -0,0 +1,11 @@ +#ifndef _FILEUTILS_H_ +#define _FILEUTILS_H_ + +#include "xp64.h" + +char *readline(char *buf, size_t size, FILE *infile); +void endofline(FILE *infile); +QWORD readnumb(QWORD deflt, FILE *infile); +double readfloat(float deflt, FILE *infile); + +#endif \ No newline at end of file diff --git a/src/doors/dgnlance/objects.mk b/src/doors/dgnlance/objects.mk index ea8449242ba1dd793b4b1ebf143a8bcf86945ccd..40e4a48255fc35342b0eddba009d3043e2236125 100644 --- a/src/doors/dgnlance/objects.mk +++ b/src/doors/dgnlance/objects.mk @@ -1 +1,6 @@ -OBJS = $(OBJODIR)$(DIRSEP)dgnlnce$(OFILE) +OBJS = $(OBJODIR)$(DIRSEP)dgnlnce$(OFILE) \ + $(OBJODIR)$(DIRSEP)xpdev$(OFILE) \ + $(OBJODIR)$(DIRSEP)userfile$(OFILE) \ + $(OBJODIR)$(DIRSEP)fileutils$(OFILE) \ + $(OBJODIR)$(DIRSEP)utils$(OFILE) \ + $(OBJODIR)$(DIRSEP)combat$(OFILE) diff --git a/src/doors/dgnlance/userfile.c b/src/doors/dgnlance/userfile.c new file mode 100644 index 0000000000000000000000000000000000000000..04395b2b31e72609913a2d6519003704fb7cca04 --- /dev/null +++ b/src/doors/dgnlance/userfile.c @@ -0,0 +1,169 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> + +#include "fileutils.h" +#include "xpdev.h" +#include "dgnlnce.h" +#include "utils.h" + +BOOL +loadnextuser(struct playertype * plr, FILE * infile) +{ + char temp[81]; + if (feof(infile)) + return (FALSE); + readline(plr->name, sizeof(plr->name), infile); + if (feof(infile)) + return (FALSE); + readline(plr->pseudo, sizeof(plr->pseudo), infile); + if (feof(infile)) + return (FALSE); + fread(&plr->sex, 1, 1, infile); + endofline(infile); + if (feof(infile)) + return (FALSE); + readline(plr->gaspd, sizeof(plr->gaspd), infile); + if (feof(infile)) + return (FALSE); + readline(plr->laston, sizeof(plr->laston), infile); + if (feof(infile)) + return (FALSE); + fgets(temp, sizeof(temp), infile); + plr->status = strtoul(temp, NULL, 10); + if (feof(infile)) + return (FALSE); + if (plr->status == DEAD) { + readline(plr->killer, sizeof(plr->killer), infile); + if (feof(infile)) + return (FALSE); + } + plr->strength = readnumb(6, infile); + plr->intelligence = readnumb(6, infile); + plr->luck = readnumb(6, infile); + plr->dexterity = readnumb(6, infile); + plr->constitution = readnumb(6, infile); + plr->charisma = readnumb(6, infile); + plr->experience = readnumb(0, infile); + plr->r = readnumb(1, infile); + plr->hps = readnumb(10, infile); + plr->weapon = readnumb(1, infile); + plr->armour = readnumb(1, infile); + plr->gold = readnumb(0, infile); + plr->flights = readnumb(3, infile); + plr->bank = readnumb(0, infile); + plr->wins = readnumb(0, infile); + plr->loses = readnumb(0, infile); + plr->plus = readnumb(0, infile); + plr->fights = readnumb(FIGHTS_PER_DAY, infile); + plr->battles = readnumb(BATTLES_PER_DAY, infile); + plr->vary = readfloat(supplant(), infile); + endofline(infile); + return (TRUE); +} +BOOL +loaduser(char *name, BOOL bbsname, struct playertype * plr) +{ + char temp[81]; + FILE *infile; + infile = fopen("data/characte.lan", "rb"); + fgets(temp, sizeof(temp), infile); + while (loadnextuser(plr, infile)) { + if (bbsname) { + if (!stricmp(plr->name, name)) { + fclose(infile); + return (TRUE); + } + } else { + if (!stricmp(plr->pseudo, name)) { + fclose(infile); + return (TRUE); + } + } + } + fclose(infile); + return (FALSE); +} + +void +writenextuser(struct playertype * plr, FILE * outfile) +{ + fprintf(outfile, "%s\n", plr->name); + fprintf(outfile, "%s\n", plr->pseudo); + fprintf(outfile, "%c\n", plr->sex); + fprintf(outfile, "%s\n", plr->gaspd); + fprintf(outfile, "%s\n", plr->laston); + fprintf(outfile, "%lu\n", plr->status); + if (plr->status == DEAD) + fprintf(outfile, "%s\n", plr->killer); + fprintf(outfile, "%u %u %u %u %u %u %" QWORDFORMAT " %u %u %u %u %" QWORDFORMAT " %u %" QWORDFORMAT " %" QWORDFORMAT " %" QWORDFORMAT " %u %u %u %1.4f\n", + plr->strength, plr->intelligence, + plr->luck, plr->dexterity, plr->constitution, + plr->charisma, plr->experience, + plr->r, plr->hps, plr->weapon, + plr->armour, plr->gold, + plr->flights, plr->bank, plr->wins, plr->loses, + plr->plus, plr->fights, plr->battles, plr->vary); +} + +void +saveuser(struct playertype * plr) +{ + DWORD h, i, j; + FILE *outfile; + FILE *infile; + char temp[81]; + + struct playertype **playerlist = NULL; + struct playertype **ra; + BOOL saved = FALSE; + infile = fopen("data/characte.lan", "rb"); + fgets(temp, sizeof(temp), infile); + i = 0; + while (loadnextuser(&tmpuser, infile)) { + ra = (struct playertype **) realloc(playerlist, sizeof(plr) * (i + 1)); + if (ra == NULL) + exit(1);; + playerlist = ra; + playerlist[i] = (struct playertype *) malloc(sizeof(struct playertype)); + if (playerlist[i] == NULL) + exit(1);; + if (!stricmp(tmpuser.name, plr->name)) { + *playerlist[i] = *plr; + saved = TRUE; + } else + *playerlist[i] = tmpuser; + i++; + } + fclose(infile); + + if (!saved) { + ra = (struct playertype **) realloc(playerlist, sizeof(plr) * (i + 1)); + if (ra == NULL) + exit(1);; + playerlist = ra; + playerlist[i] = (struct playertype *) malloc(sizeof(struct playertype)); + if (playerlist[i] == NULL) + exit(1);; + *playerlist[i] = *plr; + i++; + } + for (j = 0; j < (i - 1); j++) { + for (h = j + 1; h < i; h++) { + if (playerlist[h]->experience > playerlist[j]->experience) { + tmpuser = *playerlist[h]; + *playerlist[h] = *playerlist[j]; + *playerlist[j] = tmpuser; + } + } + } + outfile = fopen("data/characte.lan", "wb"); + fprintf(outfile, "%lu\n", i); + for (j = 0; j < i; j++) { + writenextuser(playerlist[j], outfile); + free(playerlist[j]); + } + free(playerlist); + fclose(outfile); +} diff --git a/src/doors/dgnlance/userfile.h b/src/doors/dgnlance/userfile.h new file mode 100644 index 0000000000000000000000000000000000000000..f77672f678db2b1081ce6807fa0737dd98018207 --- /dev/null +++ b/src/doors/dgnlance/userfile.h @@ -0,0 +1,12 @@ +#ifndef _USERFILE_H_ +#define _USERFILE_H_ + +#include "OpenDoor.h" /* BOOL */ +#include "dgnlnce.h" /* struct playertype */ + +void writenextuser(struct playertype * plr, FILE * outfile); +void saveuser(struct playertype * plr); +BOOL loadnextuser(struct playertype * plr, FILE *infile); +BOOL loaduser(char *name, BOOL bbsname, struct playertype * plr); + +#endif diff --git a/src/doors/dgnlance/utils.c b/src/doors/dgnlance/utils.c new file mode 100644 index 0000000000000000000000000000000000000000..9ac6ba5db321f200519f03081baa362764da6af2 --- /dev/null +++ b/src/doors/dgnlance/utils.c @@ -0,0 +1,94 @@ +#include <ctype.h> + +#include "OpenDoor.h" + +#include "dgnlnce.h" +#include "xp64.h" +#include "xpdev.h" + +double +supplant(void) +{ + return ((double)(xp_random(40) + 80)) / 100; +} + +void +statshow(void) +{ + od_clr_scr(); + od_set_color(D_MAGENTA, D_BLACK); + od_printf("Name: %s Level: %d\r\n", user.pseudo, user.r); + od_set_color(L_CYAN, D_BLACK); + od_printf("W/L: %" QWORDFORMAT "/%" QWORDFORMAT " Exp: %" QWORDFORMAT "\r\n", user.wins, user.loses, user.experience); + nl(); + od_set_color(L_YELLOW, D_BLACK); + od_printf("Steel (in hand): %" QWORDFORMAT "\r\n", user.gold); + od_printf("Steel (in bank): %" QWORDFORMAT "\r\n", user.bank); + nl(); + od_set_color(L_BLUE, D_BLACK); + od_printf("Battles: %u Retreats: %u Fights: %u Hps: %u(%u)\r\n", user.battles, user.flights, user.fights, user.hps - user.damage, user.hps); + nl(); + od_set_color(L_CYAN, D_BLACK); + od_printf("Weapon: %s Armor: %s\r\n", weapon[user.weapon].name, armour[user.armour].name); +} + +void +pausescr(void) +{ + od_set_color(L_CYAN, D_BLACK); + od_disp_str("[Pause]"); + od_set_color(D_GREY, D_BLACK); + od_get_key(TRUE); + od_disp_str("\010 \010\010 \010\010 \010\010 \010\010 \010\010 \010\010 \010"); +} + +char * +sexstrings(struct playertype * plr, int type, BOOL cap) +{ + static char retbuf[16]; + char sex; + sex = plr->sex; + if (plr->charisma < 8) + sex = 'I'; + switch (sex) { + case 'M': + switch (type) { + case HIS: + SAFECOPY(retbuf, "his"); + break; + case HE: + SAFECOPY(retbuf, "he"); + break; + case HIM: + SAFECOPY(retbuf, "him"); + break; + } + case 'F': + switch (type) { + case HIS: + SAFECOPY(retbuf, "her"); + break; + case HE: + SAFECOPY(retbuf, "she"); + break; + case HIM: + SAFECOPY(retbuf, "her"); + break; + } + case 'I': + switch (type) { + case HIS: + SAFECOPY(retbuf, "its"); + break; + case HE: + SAFECOPY(retbuf, "it"); + break; + case HIM: + SAFECOPY(retbuf, "it"); + break; + } + } + if (cap) + retbuf[0] = toupper(retbuf[0]); + return (retbuf); +} diff --git a/src/doors/dgnlance/utils.h b/src/doors/dgnlance/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..4fda5adbe09c982c54220c40f72fa73eaf7e658d --- /dev/null +++ b/src/doors/dgnlance/utils.h @@ -0,0 +1,9 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +double supplant(void); +void statshow(void); +void pausescr(void); +char *sexstrings(struct playertype * plr, int type, BOOL cap); + +#endif \ No newline at end of file diff --git a/src/doors/dgnlance/xp64.h b/src/doors/dgnlance/xp64.h new file mode 100644 index 0000000000000000000000000000000000000000..af463129e7b2b90eff4002b48319862ed04810ae --- /dev/null +++ b/src/doors/dgnlance/xp64.h @@ -0,0 +1,39 @@ +#ifndef INT64 +#ifdef _MSC_VER +#define INT64 __int64 +#else +#define INT64 long long int +#endif +#endif + +#ifndef INT64FORMAT +#ifdef __BORLANDC__ +#define INT64FORMAT "Ld" +#else +#ifdef _MSC_VER +#define INT64FORMAT "I64d" +#else +#define INT64FORMAT "lld" +#endif +#endif +#endif + +#ifndef QWORD +#ifdef _MSC_VER +#define QWORD unsigned _int64 +#else +#define QWORD unsigned long long int +#endif +#endif + +#ifndef QWORDFORMAT +#ifdef __BORLANDC__ +#define QWORDFORMAT "Lu" +#else +#ifdef _MSC_VER +#define QWORDFORMAT "I64u" +#else +#define QWORDFORMAT "llu" +#endif +#endif +#endif diff --git a/src/doors/dgnlance/xpdev.c b/src/doors/dgnlance/xpdev.c new file mode 100644 index 0000000000000000000000000000000000000000..1ca02509d9e73518127d80e79a8970069e106212 --- /dev/null +++ b/src/doors/dgnlance/xpdev.c @@ -0,0 +1,39 @@ +#include <string.h> +#include <stdlib.h> /* RAND_MAX */ +#include <time.h> /* time() */ + +#include "OpenDoor.h" /* BOOL */ + +#include "xpdev.h" + +/****************************************************************************/ +/* Truncates all white-space chars off end of 'str' (needed by STRERRROR) */ +/****************************************************************************/ +char * +truncsp(char *str) +{ + size_t i, len; + i = len = strlen(str); + + while (i && (str[i - 1] == ' ' || str[i - 1] == '\t' || str[i - 1] == '\r' || str[i - 1] == '\n')) + i--; + if (i != len) + str[i] = 0; /* truncate */ + return (str); +} + +int +xp_random(int n) +{ + float f; + static BOOL initialized; + if (!initialized) { + srand(time(NULL)); /* seed random number generator */ + rand(); /* throw away first result */ + initialized = TRUE; + } + if (n < 2) + return (0); + f = (float)rand() / (float)RAND_MAX; + return ((int)(n * f)); +} diff --git a/src/doors/dgnlance/xpdev.h b/src/doors/dgnlance/xpdev.h new file mode 100644 index 0000000000000000000000000000000000000000..a42977e6368a409c1b8c7f918068f4141aa628de --- /dev/null +++ b/src/doors/dgnlance/xpdev.h @@ -0,0 +1,15 @@ +#ifndef _XPDEV_H_ +#define _XPDEV_H_ + +#define SAFECOPY(dst, src) sprintf(dst, "%.*s", (int)sizeof(dst) - 1, src) +#if defined(__unix__) +#if !defined(stricmp) +#define stricmp(x,y) strcasecmp(x,y) +#define strnicmp(x,y,z) strncasecmp(x,y,z) +#endif +#endif + +char *truncsp(char *str); +int xp_random(int n); + +#endif