[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  ROM
. -> [Folder]  Compiling the server
. . -> [Subject]  Character Creation help?

Character Creation help?

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Posted by Wandering_Ponderer   (27 posts)  [Biography] bio
Date Mon 21 Nov 2005 01:20 PM (UTC)

Amended on Tue 22 Nov 2005 12:20 AM (UTC) by Nick Gammon

Message
Ok, so one more question...I was able to add the stats perfectly, but am having a bit of trouble now writing something up for rolling stats during character creation. It's getting caught up in an infinite loop spamming the same stats... Also, any idea what the function is for getting a random number? I thought it was URANGE, but it looks like all that does is instead take the larger of the two given numbers.:



/* initialize stats */
write_to_buffer(d,"Now rolling for stats...\n",0);



for (i = 0; i < MAX_STATS; i++)
  {
  ch->perm_stat[i] = URANGE(pc_race_table[race].stats[i],ch->perm_stat[i],pc_race_table[race].max_stats[i]);
  }

sprintf(buf,"Str: %d Int: %d Wis: %d Dex: %d Con: %d Cha: %d Lck: %d Morale: %d\n",
        ch->perm_stat[0],ch->perm_stat[1],ch->perm_stat[2],ch->perm_stat[3],ch->perm_stat[4],
        ch->perm_stat[5],ch->perm_stat[6],ch->perm_stat[7]);
send_to_char(buf, ch);
write_to_buffer(d,"Accept these stats? (Y/N)\n",0);

int creationroll = 0;
while ((creationroll == 0))
  {
  switch ( argument[0] )
    case 'y': case 'Y':
      creationroll = 1;
    case 'n': case 'N':
      for (i = 0; i < MAX_STATS; i++)
        {
        ch->perm_stat[i] = URANGE(pc_race_table[race].stats[i],ch->perm_stat[i],pc_race_table[race].max_stats[i]);
        }
      sprintf(buf,"Str: %d Int: %d Wis: %d Dex: %d Con: %d Cha: %d Lck: %d Morale: %d",
        ch->perm_stat[0],ch->perm_stat[1],ch->perm_stat[2],ch->perm_stat[3],ch->perm_stat[4],
        ch->perm_stat[5],ch->perm_stat[6],ch->perm_stat[7]);
      send_to_char(buf, ch);
      write_to_buffer(d,"Accept these stats? (Y/N)\n",0);
      
  }

ch->affected_by = ch->affected_by|race_table[race].aff;
ch->imm_flags = ch->imm_flags|race_table[race].imm;
ch->res_flags = ch->res_flags|race_table[race].res;
ch->vuln_flags = ch->vuln_flags|race_table[race].vuln;
ch->form = race_table[race].form;
ch->parts = race_table[race].parts;
[Go to top] top

Posted by Zeno   USA  (2,871 posts)  [Biography] bio
Date Reply #1 on Mon 21 Nov 2005 01:44 PM (UTC)

Amended on Mon 21 Nov 2005 07:40 PM (UTC) by Nick Gammon

Message
You'll have to use gdb to see why it's stuck. I can't really tell from just the code. Seems like you missed something; something to do with the race table:

ch->perm_stat[i] = URANGE(pc_race_table[race].stats[i],ch->perm_stat[i],pc_race_table[race].max_stats[i]);

Seems like it's either the .stats or .max_stats part that would be causing it.

As for a random range, I'm not sure. Try looking over code that uses a random range, like maybe a skill.

Zeno McDohl,
Owner of Bleached InuYasha Galaxy
http://www.biyg.org
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #2 on Mon 21 Nov 2005 07:40 PM (UTC)
Message
rand is the random-number generator.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Wandering_Ponderer   (27 posts)  [Biography] bio
Date Reply #3 on Mon 21 Nov 2005 10:52 PM (UTC)

Amended on Mon 21 Nov 2005 11:49 PM (UTC) by Wandering_Ponderer

Message
How can I use the rand function to get random numbers in a selected range?
[Go to top] top

Posted by Wandering_Ponderer   (27 posts)  [Biography] bio
Date Reply #4 on Mon 21 Nov 2005 10:56 PM (UTC)

Amended on Mon 21 Nov 2005 10:58 PM (UTC) by Wandering_Ponderer

Message
Also, I just realized I did a very poor job of explaining the problem I was having. Anyone who wants to see it for themselves can try making a new test character on port 9000 of rom.servegame.org. Basically, The stats continue to spam themselves until the character is disconnected, and the mud itself reports the following until I force-quit it:


Write_to_descriptor: Bad file descriptor
Mon Nov 21 05:52:39 2005 :: Closing link to Test.
Mon Nov 21 05:52:39 2005 :: [*****] BUG: Close_socket: dclose not found.
Mon Nov 21 05:52:39 2005 :: [*****] BUG: Buffer overflow. Closing.

Write_to_descriptor: Bad file descriptor
Mon Nov 21 05:52:39 2005 :: Closing link to Test.
Mon Nov 21 05:52:39 2005 :: [*****] BUG: Close_socket: dclose not found.
Mon Nov 21 05:52:39 2005 :: [*****] BUG: Buffer overflow. Closing.

Write_to_descriptor: Bad file descriptor
Mon Nov 21 05:52:39 2005 :: Closing link to Test.
Mon Nov 21 05:52:39 2005 :: [*****] BUG: Close_socket: dclose not found.
Mon Nov 21 05:52:39 2005 :: [*****] BUG: Buffer overflow. Closing.
[Go to top] top

Posted by Wandering_Ponderer   (27 posts)  [Biography] bio
Date Reply #5 on Mon 21 Nov 2005 11:55 PM (UTC)
Message
I believe my main problem is that I'm not sure how to make character creation pause while waiting for input from a character without a descriptor...Any help?
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #6 on Tue 22 Nov 2005 12:22 AM (UTC)
Message
Quote:

How can I use the rand function to get random numbers in a selected range?


There was a post about this very thing on this page:

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=4649&page=2

Basically you want a function like this:


const int getrandom (const int x)
{
  if (x <= 0)
    return 0;
  return (double) rand () / ((double) (RAND_MAX) + 1.0) * (double) x;
}   // end of getrandom


This will return a number in the range 0 to, but excluding, x.

So, to generate a number in the range 1 to 10, you would do this:


num = getrandom (10) + 1;


This is because getrandom (10) returns a number in the range 0 to 9.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #7 on Tue 22 Nov 2005 12:34 AM (UTC)
Message
Quote:

I believe my main problem is that I'm not sure how to make character creation pause while waiting for input from a character without a descriptor...


Yes that is your problem alright. Imagine what you are doing here - you have rolled some stats and are waiting for the player to say Y or N. But what if s/he takes a minute to decide? Or goes and makes a cup of coffee and watches TV for an hour? You can't really have the entire server pause while this is happening, as all the other players would freeze up.

You need to look at how the nanny function works in general. What it does is maintain a "state" using the d->connected variable. The various states tell the server what the player is about to input next, such as:

CON_GET_NAME, CON_GET_OLD_PASSWORD, CON_CONFIRM_NEW_NAME, CON_GET_NEW_PASSWORD, CON_CONFIRM_NEW_PASSWORD, CON_GET_NEW_SEX, CON_GET_NEW_CLASS (and so on).

So you need to make a new state type (eg. CON_CONFIRM_STAT_ROLL) and add it to mud.h.

Then you need to create a new section in the big case statement in nanny, which handles their response.
It would look something like this:



case CON_CONFIRM_STAT_ROLL:

  switch ( argument[0] )
    {
    case 'y': case 'Y':
      write_to_buffer( d, "\n\rWould you like RIP, ANSI or no graphic/color support, (R/A/N)? ", 0 );
       d->connected = CON_GET_WANT_RIPANSI;
      break;

    case 'n': case 'N':
      for (i = 0; i < MAX_STATS; i++)
        {
        ch->perm_stat[i] = URANGE(pc_race_table[race].stats[i],ch->perm_stat[i],pc_race_table[race].max_stats[i]);
        }
      sprintf(buf,"Str: %d Int: %d Wis: %d Dex: %d Con: %d Cha: %d Lck: %d Morale: %d",
        ch->perm_stat[0],ch->perm_stat[1],ch->perm_stat[2],ch->perm_stat[3],ch->perm_stat[4],
        ch->perm_stat[5],ch->perm_stat[6],ch->perm_stat[7]);
      send_to_char(buf, ch);
      write_to_buffer(d,"Accept these stats? (Y/N)\n",0);
    break;

    default:  write_to_buffer(d,"Accept these stats? (Y/N)\n",0);
    break;
    }  /* end of switch */ 
      


I haven't tested it, but this shows the general approach. Basicall you are staying in the connection state CON_CONFIRM_STAT_ROLL until such time as they enter Y then you move onto the next state. In my example I made it CON_GET_WANT_RIPANSI but you would put it whereever in the sequence you wanted it.

Each state in the connection sequence ends with the question to be answered in the next state.

Of course, you need to fix up your URANGE problem too.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Wandering_Ponderer   (27 posts)  [Biography] bio
Date Reply #8 on Tue 22 Nov 2005 03:30 AM (UTC)

Amended on Tue 22 Nov 2005 04:03 AM (UTC) by Wandering_Ponderer

Message
Alright guys. I know I'm PAINFULLY close here, but I'm just missing something...Here's what I have right now. And for anyone who's been wondering, luck and morale are only showing up for now so I can see if it's working. Anyone's welcome to see the error for themselves. Port 9000 at rom.servegame.org.

in merc.h:

/*
* Connected state for a channel.
*/
#define CON_PLAYING 0
#define CON_GET_NAME 1
#define CON_GET_OLD_PASSWORD 2
#define CON_CONFIRM_NEW_NAME 3
#define CON_GET_NEW_PASSWORD 4
#define CON_CONFIRM_NEW_PASSWORD 5
#define CON_GET_NEW_RACE 6
#define CON_GET_NEW_SEX 7
#define CON_GET_NEW_CLASS 8
#define CON_GET_ALIGNMENT 9
#define CON_CHOOSE_TERM 11
#define CON_DEFAULT_CHOICE 12
#define CON_GEN_GROUPS 13
#define CON_PICK_WEAPON 14
#define CON_READ_IMOTD 15
#define CON_READ_MOTD 16
#define CON_BREAK_CONNECT 17
#define CON_COPYOVER_RECOVER 18
/*Dave Added for Char Generation*/
#define CON_ROLLING_STATS 19

in comm.c:

ch->pcdata->points = pc_race_table[race].points;
ch->size = pc_race_table[race].size;
write_to_buffer(d,"Now rolling for stats...\n\n",0);
d->connected = CON_ROLLING_STATS;
break;

case CON_ROLLING_STATS:

/* initialize stats */

for (i = 0; i < MAX_STATS; i++)
{

ch->perm_stat[i] = rollstats(pc_race_table[ch->race].stats[i],pc_race_table[ch->race].max_stats[i]);
}
sprintf(buf,"Str: %d Int: %d Wis: %d Dex: %d Con: %d Cha: %d Lck: %d Morale: %d",

ch->perm_stat[0],ch->perm_stat[1],ch->perm_stat[2],ch->perm_stat[3],ch->perm_stat[4],
ch->perm_stat[5],ch->perm_stat[6],ch->perm_stat[7]);
send_to_char(buf, ch);
write_to_buffer(d,"Accept these stats? (Y/N)\n",0);


switch ( argument[0] )
{
case 'y': case 'Y':
d->connected = CON_GET_NEW_SEX;
break;

case 'n': case 'N':

for (i = 0; i < MAX_STATS; i++)
{

ch->perm_stat[i] = rollstats(pc_race_table[ch->race].stats[i],pc_race_table[ch->race].max_stats[i]);
}
sprintf(buf,"Str: %d Int: %d Wis: %d Dex: %d Con: %d Cha: %d Lck: %d Morale: %d",

ch->perm_stat[0],ch->perm_stat[1],ch->perm_stat[2],ch->perm_stat[3],ch->perm_stat[4],
ch->perm_stat[5],ch->perm_stat[6],ch->perm_stat[7]);
send_to_char(buf, ch);
write_to_buffer(d,"Accept these stats? (Y/N)\n",0);
break;

default:
write_to_buffer(d,"Accept these stats? (Y/N)\n",0);
break;
}

case CON_GET_NEW_SEX:
write_to_buffer(d,"What is your sex (M/F)? ", 0 );
switch ( argument[0] )
{
case 'm': case 'M': ch->sex = SEX_MALE;
ch->pcdata->true_sex = SEX_MALE;
break;
case 'f': case 'F': ch->sex = SEX_FEMALE;
ch->pcdata->true_sex = SEX_FEMALE;
break;
default:
write_to_buffer( d, "That's not a sex.\n\rWhat IS your sex? ", 0 );
return;
}

strcpy( buf, "Select a class [" );
for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
{
if ( iClass > 0 )
strcat( buf, " " );
strcat( buf, class_table[iClass].name );
}
strcat( buf, "]: " );
write_to_buffer( d, buf, 0 );
d->connected = CON_GET_NEW_CLASS;
break;


and further down:

const int rollstats (const int min, const int max)
{
int num = (max - min);
num = (((double) rand () / ((double) (RAND_MAX) + 1.0) * (double) num) + min);
return num;
}

the prototype is simply:
const int rollstats (const int min, const int max);

So here's what's happening...

By what name do you wish to be known? test
Did I get that right, Test (Y/N)? y
New character.
Give me a password for Test:
Please retype password:
The following races are available:
human elf dwarf halfling
What is your race (help for more information)? elf
Now rolling for stats...


Accept these stats? (Y/N)
What is your sex (M/F)? That's not a sex.

it shows up blank, and if i hit enter it then says 'accept these stat's and goes on, instantly saying 'That's not a sex'. If I hit 'N' right after typing elf, it shows a unique (but correct) roll, then goes straight to this same point...not allowing me to reroll more than once. Any ideas what the heck is going on here?
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #9 on Tue 22 Nov 2005 04:10 AM (UTC)

Amended on Tue 22 Nov 2005 04:12 AM (UTC) by Nick Gammon

Message
You have to think about the order things are happening. Once you break out of nanny you are waiting on user input. You have not told them their stats, but are rerolling them *after* they have said Y or N, which means they would get different ones to what they agreed to. You need to resequence a bit:


in comm.c:

  ch->pcdata->points = pc_race_table[race].points;
  ch->size = pc_race_table[race].size;
  write_to_buffer(d,"Now rolling for stats...\n\n",0);
  
  /* initialize stats - roll first set*/
  
  for (i = 0; i < MAX_STATS; i++)
    {
    
    ch->perm_stat[i] = rollstats(pc_race_table[ch->race].stats[i],pc_race_table[ch->race].max_stats[i]);
    }
  
  sprintf(buf,"Str: %d Int: %d Wis: %d Dex: %d Con: %d Cha: %d Lck: %d Morale: %d",
    
    ch->perm_stat[0],ch->perm_stat[1],ch->perm_stat[2],ch->perm_stat[3],ch->perm_stat[4],
    ch->perm_stat[5],ch->perm_stat[6],ch->perm_stat[7]);
  send_to_char(buf, ch);
  write_to_buffer(d,"Accept these stats? (Y/N)\n",0);

  d->connected = CON_ROLLING_STATS;
  break;

case CON_ROLLING_STATS:
  
  
  
  switch ( argument[0] )
    {
    case 'y': case 'Y':
      d->connected = CON_GET_NEW_SEX;
      break;
      
    case 'n': case 'N':
      
      /* reroll stats */

      for (i = 0; i < MAX_STATS; i++)
        {
        
        ch->perm_stat[i] = rollstats(pc_race_table[ch->race].stats[i],pc_race_table[ch->race].max_stats[i]);
        }
      sprintf(buf,"Str: %d Int: %d Wis: %d Dex: %d Con: %d Cha: %d Lck: %d Morale: %d",
        
        ch->perm_stat[0],ch->perm_stat[1],ch->perm_stat[2],ch->perm_stat[3],ch->perm_stat[4],
        ch->perm_stat[5],ch->perm_stat[6],ch->perm_stat[7]);
      send_to_char(buf, ch);
      write_to_buffer(d,"Accept these stats? (Y/N)\n",0);
      break;
      
    default:
      write_to_buffer(d,"Accept these stats? (Y/N)\n",0);
      break;
    }

break;



You also need that final break, otherwise it drops down to the code for handling sex choices.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Wandering_Ponderer   (27 posts)  [Biography] bio
Date Reply #10 on Tue 22 Nov 2005 04:28 AM (UTC)
Message
Nick and Zeno, You guys are awesome!!! It works like a charm, and I have the two of you thank for it. Thank you so much ^_^
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


22,897 views.

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]