09 Jan, 2009, kaervos wrote in the 41st comment:
Votes: 0
Hey everyone. I've been somewhat ignoring recent suggestions, just so I can get done what I was working on. It may not be perfectly ideal, but it is definitely a few steps in the right direction.

I implemented the two layer word and letter based language translation system. This allows you to have a dictionary of elven words for example that will replace specific words, while also having a letter based translation system that is used on the word when no match in the language dictionary is found. The results are quite nice, perhaps even a bit excessive. Much work was put into making the words have appropriate capitalization, so speakers can YELL PARTICULAR WORDS in a sentence, even in foreign languages. I also implemented drunken speech, on top of the language translation. This means that drunken elves sound like drunken elves and drunken dwarves sound like drunken dwarves.

All channels in act_comm.c (even tell and reply) have been pushed through a common function channel_speech(…), where the content can easily be filtered.

Currently there is no way to specify the language a character is speaking aside from using the wiz command set:

Quote
set mob kaervos speaking 1


Makes the character kaervos speak elven. The languages defined are common (0), elven (1) and dwarven (2). There are no language comprehension skills implemented, so hearing elven or dwarven always produces a fully foreign translation. Here is what it looks like:

From the speaker:

Quote
<29hp 110m 160mv> set mob kaervos speaking 0
LOG_AUTH> Caught Kaervos doing set mob kaervos speaking 0

<47hp 130m 280mv> say Ok, this is me speaking common. Everyone can understand this.
You say 'Ok, this is me speaking common. Everyone can understand this.'

<47hp 130m 280mv> set mob kaervos speaking 1
LOG_AUTH> Caught Kaervos doing set mob kaervos speaking 1

<47hp 130m 280mv> say Alright, now I'm speaking in Elven. Words like Midgaard, mithril and Mota still sound familliar.
You say 'Alright, now I'm speaking in Elven. Words like Midgaard, mithril and
Mota still sound familliar.'

<56hp 140m 340mv> say I can also YELL SOME WORDS TO EMPHASIZE!
You say 'I can also YELL SOME WORDS TO EMPHASIZE!'

<65hp 150m 400mv> set mob kaervos speaking 2
LOG_AUTH> Caught Kaervos doing set mob kaervos speaking 2

<65hp 150m 400mv> say Indeed. Now I am speaking in dwarven. Again familliar words may appear.
You say 'Indeed. Now I am speaking in dwarven. Again familliar words may
appear.'

<74hp 160m 454mv> burp
You burp loudly.

<74hp 160m 454mv> mull
You mull over the idea at hand, asking for patience.

<74hp 160m 454mv> drink fire
You can't find it.

<74hp 160m 454mv> load obj 3003
LOG_AUTH> Caught Kaervos doing load obj 3003
Ok.

<74hp 160m 454mv> drink fire
You drink firebreather from a bottle of firebreather.
You are full.
Your thirst is quenched.

<74hp 160m 454mv> drink fire
You drink firebreather from a bottle of firebreather.
You are full.
Your thirst is quenched.

<74hp 160m 454mv> set mob kaervos drunk 10
LOG_AUTH> Caught Kaervos doing set mob kaervos drunk 10

<74hp 160m 454mv> say Indeed. Now I am speaking in dwarven. Again familliar words may appear.
You say 'innDeed. nooow ii am ssPehAhkiinNng Iiin Dwaorvehnnn. ahhhhgaiinNn
faommIiilLiaor WordzzZzssZ mAhY aapPear.'

<74hp 160m 454mv> say YOUR MOTHER HAS NO BEARD!
You say 'yOoouhr mmmmmooothher Has nno bEoard!'

<83hp 170m 454mv> set mob kaervos speaking 1
LOG_AUTH> Caught Kaervos doing set mob kaervos speaking 1

<83hp 170m 454mv> gos You are no match for my DRUNKEN ELF STYLE!
You gossip 'yoUhuhhuh Ahreh nNnooOo MmMawtch ffoooR MmMy DRunNnkENn ehLf
zzZzssZTYLE!'

<92hp 180m 454mv> set mob kaervos drunk 0
LOG_AUTH> Caught Kaervos doing set mob kaervos drunk 0

<92hp 180m 454mv> gos You are no match for my DRUNKEN ELF STYLE!
You gossip 'You are no match for my DRUNKEN ELF STYLE!'

<92hp 180m 454mv>


From the listener:
Quote
<20hp 100m 100mv>
Kaervos coughs loudly.

<20hp 100m 100mv>
Kaervos says 'Ok, this is me speaking common. Everyone can understand this.'

<20hp 100m 100mv>
Kaervos says 'Ilcmeviran, leam E's latyailnelv aul Acelal. Amemwla cena
Midgaard, mithril ent Mota laanecc laeylw oilsecceilm.'

<20hp 100m 100mv>
Kaervos says 'E nyill ilclae AACC LAESA AMEMWLA NAE ASTYIRILLAEJA!'

<20hp 100m 100mv>
Kaervos says 'Artaat. Rurzh A azl thrhaazgark kurs tzhazhgar. Azkazar
waazlannaazh zhurhtth lazo azrhrhaazh.'

<20hp 100m 100mv>
Kaervos burps loudly.

<20hp 100m 100mv>
Kaervos mulls over the idea at hand. Please be patient.

<20hp 100m 100mv>
Kaervos has created a bottle of firebreather!

<20hp 100m 100mv>
Kaervos drinks firebreather from a bottle of firebreather.

<20hp 100m 100mv>
Kaervos drinks firebreather from a bottle of firebreather.

<20hp 100m 100mv>
Kaervos says 'artaaot. RuhURsZZzh A AhZsszzszl tHhHrhhhAhAzGoaRk KuhUrss
TzhhhahhhhZsszzszhgawR. aZzzZzkaaszzahhhhR waoaozlannnnnoaoazZh Zsszzszhhuhhurhh
hTtHhh LAzZOoo aoZzzZzRHrhhhAahzZHhH.'

<20hp 100m 100mv>
Kaervos says 'ooouhR'h Luhhurk'ah 'AhzZTh maOoosSzzsss grIiM!' <— drunken Dwarven

<20hp 100m 100mv>
Kaervos gossips 'NeHhHehl Iilmmaa nehh ZSssSilanNnnyiiR NesSssh ssA wMmMyLnaoL
KesSzzsssIr laoahNnacoa!' <— drunken Elven

<20hp 100m 100mv>
Kaervos gossips 'Nehel ilma neh silannyir nesh sa WMYLNAL KESIR LAANACA!' <— sober Elven

<20hp 100m 100mv>



Results are nice, I think. Obviously there is more to be done before a proper implementation of languages is complete. The race table needs to have languages in it, language skills need to be added and checked against to provide a % of words in the speech (based on skill) left in common tongue. I suspect one's language skill should be checked against improving everytime the language in question is heard spoken. Obviously a command for users to change currently spoken language is needed as well.

I uploaded a patch to the RaM file area. This patch was made against the most recent SVN version (~5pm EST 01/09/2009), and has been verified as functional.

Definitely let me know your thoughs.
09 Jan, 2009, Tyche wrote in the 42nd comment:
Votes: 0
quixadhal said:
Seems reasonable. Oh, I do have to ask this though…. std::endl. I know what it's supposed to do, but is that really the right thing to use for TELNET? IE: On my OS (linux), std::endl should resolve to "\n". On MS-DOGGIE, it should become "\r\n", which also happens to be the correct ending for TELNET.

I know it's the right choice for console I/O, and for file I/O (presumably it auto-converts on input streams?), but I'm not sure it's correct for TELNET.


No it's not equivalent. The STL has no clue the stream is intended for telnet. You'd need to define your own end of line sequence, perhaps something like telnet_endl, so you'll get CRLF on both Lamex and Windows.

Actually the following might be better as long as your namespace is clean:
talkchannelstream out;
out << who(ch) << yellow << "You're a noob!" << telnet_eol;

But remember there's nothing at all special about operator<<. The above is equivalent to:
talkchannelstream out;
operator<<(out,who(ch)).operator<<(yellow).operator<<("You're a noob!").operator<<(telnet_eol);

And you need not even have to use a stream or subclass from a stream, you can certainly define operator<< on your Descriptor class without it being a subclass of a stream. You do lose the already defined formatting capabilities and have to implement your own.
10 Jan, 2009, kaervos wrote in the 43rd comment:
Votes: 0
Tyche, did you just use the term "Lamex" when referring to the best operating system ever?

As soon as I think of some zingers to lambaste your Windows using arse with, I'll get back to you. ;)

I like the stream ideas though. I've always overloaded the << operator for objects I create, and definite a function that prints all sorts of good info on the object so I can just toss them to stdout for debugging or whatnot.

I wanted to give some more info on the patch I just submitted to the file area. If you check it out, you'll notice I removed this from act_printf(…)

-        if ( !IS_AWAKE( to ) )
- continue;


It doesn't seem to make sense there, because min_pos is already an argument to act_printf(…) (used to be act_new(…)), so the caller can specify if the victim can be sleeping and still receive the act message. In fact, a number of the channels by default in ROM seem to want to allow this to happen. CHAN_AUCTION and CHAN_GROUP are a couple that are supposed to be received even while sleeping. If anyone sees any ramifications of this change that I overlooked, speak up.

Also, I need to credit the source of the Dwarven and Elven word dictionaries. They came from two articles in Dragon Magazine written by Sean K. Reynolds:

Dragon Magazine #278 "A Dwarven Lexicon" by Sean K. Reynolds
Dragon Magazine #279 "An Elven Lexicon" by Sean K. Reynolds

I suppose the lengthy word dictionaries really aren't that important, and the implementation will work fine just using the letter-based language tables. They definitely add to it though, and we should credit Mr. Reynolds for that.
10 Jan, 2009, quixadhal wrote in the 44th comment:
Votes: 0
kaervos said:
I wanted to give some more info on the patch I just submitted to the file area. If you check it out, you'll notice I removed this from act_printf(…)
-        if ( !IS_AWAKE( to ) )
- continue;


Probably fine, although you'll want to verify that the macros to emulate act_new() and act() set min_pos to resting or higher. I know the default is for people to be awake to hear most things.
12 Jan, 2009, kaervos wrote in the 45th comment:
Votes: 0
Finished the basics of a language implementation. pc_race_table has been
modified to contain a language type for each race. New players are given a
100% skill in common comprehension and their race's native language
comprehension if they are not human raced. Players can now 'speak' in a
language as defined in language_table. The language currently being spoken is
displayed in 'score' and can be set with 'set'. Language speaking proficiencies
are defined as skills. They are practiced like normal skills, and
the new channel_speech(…) gives the skill a chance at improving when the
player hears a language spoken (when calling language_convert(…)). Since the
language implementation operates on a word level, based on the listener's
proficiency in the spoken language, a certain percentage of the spoken words
will be left in common language (as originally input). Success or failure of
word translation is then used when checking skill improvement.

I uploaded a new patch against the latest SVN to the RaM file area.

At first I liked the skill names like "elven comprehension" and "dwarven
comprehension", but they are so long they mess up some of the formatting of
skill tables (like when customizing a player). Changing the names to
"comprehend elven" and "comprehend dwarven" saves three letters, which is
enough to save the formatting of the customization skill table… anyway…
please comment on the overall implementation. It seems pretty solid from my
point of view.

I gave a little thought to furthering the channel implementation beyond just
communication channels. channel_speech(…) was named in that it deals only in
words spoken by players. As such the channel_table contains the outgoing and
incoming verbs as heard by players speaking and hearing the channel
respectively. This doesn't fit in the scheme of having channels for all the
different game outputs. I can't think of how they would be used for other
output channels at all. Removing them from the table would require a switch
statement in channel_speech(…) that would assign the appropriate verbs based
on the channel type. They won't cause any harm in the table for now.

The overall implementation scheme to categorize all mud outputs into various
types would be to either tag all strings sent to any ch_printf(…) call with a
token, or extend the current channel_table, and pass the appropriate channel
definition (pehaps as an optional parameter that defaults to CHAN_UNKNOWN). I'm
leaning to the latter idea in preference.
12 Jan, 2009, David Haley wrote in the 46th comment:
Votes: 0
target->tell(ch) could be a method that returns a special stream that sends its data to the tell stream for target with ch as the sender. Or you could do what Tyche suggested and use a modifier like who(ch).

And no, you probably don't want to use std::endl if you really want \r\n to be sent out.
12 Jan, 2009, quixadhal wrote in the 47th comment:
Votes: 0
kaervos said:
At first I liked the skill names like "elven comprehension" and "dwarven
comprehension", but they are so long they mess up some of the formatting of
skill tables (like when customizing a player). Changing the names to
"comprehend elven" and "comprehend dwarven" saves three letters, which is
enough to save the formatting of the customization skill table… anyway…
please comment on the overall implementation. It seems pretty solid from my
point of view.


I wouldn't worry overmuch about the table, as it will go away eventually. I really do want everything that CAN be loaded at boot time from files to be done that way, as the ability to add new races and/or languages shouldn't require one to recompile.

I'm not sure I really like having languages lumped into the main skill table… hmmmm… I suppose it's ok since the skill table isn't categorized anyways. Heh, I suppose it also means you can have a scroll of "comprehend dwarven"… of course, if it's written in dwarven it might be rather useless. *grin*

kaervos said:
I gave a little thought to furthering the channel implementation beyond just
communication channels. channel_speech(…) was named in that it deals only in
words spoken by players. As such the channel_table contains the outgoing and
incoming verbs as heard by players speaking and hearing the channel
respectively. This doesn't fit in the scheme of having channels for all the
different game outputs. I can't think of how they would be used for other
output channels at all. Removing them from the table would require a switch
statement in channel_speech(…) that would assign the appropriate verbs based
on the channel type. They won't cause any harm in the table for now.

The overall implementation scheme to categorize all mud outputs into various
types would be to either tag all strings sent to any ch_printf(…) call with a
token, or extend the current channel_table, and pass the appropriate channel
definition (pehaps as an optional parameter that defaults to CHAN_UNKNOWN). I'm
leaning to the latter idea in preference.


A channel parameter would be best for now. I don't want to add some crackpot inline token scheme that will make parsing the text even harder! My eventual design concept is to end up moving away from raw text at the bottom level, and having structures that contain the text plus data about how it should be displayed. Thus, at the bottom level, it can have whatever tagging is appropriate added before it goes out the socket.

My reasoning there is that if you're using MXP, you want a "tell" to get wrapped by whatever MXP uses to denote tells. If your target is a web browser, you'd want the right HTML/CSS stuff, and if you're a telnet socket with ANSI enabled, you probably want your chosen text color codes. At the code level, you just want to say "send this tell message to the user" and let that bottom layer handle HOW.

Color codes are a special case, because you want them mixed into normal text (at least in room descriptions and such), but the text block is still of type "room description". So, if the ANSI user wants room descriptions to be purple, you STILL parse the color codes at the bottom so the default color can become purple.

The only case I can think of where you'd want that kind of functionality for languages is a cross-language puzzle, and that's pushing it. So, I'd kindof expect an eventual structure that has the text (with color embedded), the purpose (room desc, editor, tell, damage, etc), and the language. There might be other properties to consider too, but that's for a bit down the road I think.
40.0/47