Evennia - a Python-Based Mu* Server
-
@Roz said:
From the perspective of someone who places ads on places like Tumblr in hopes of hooking in the younger generation that doesn't realize there's a way easier way to do this RP thing, promise, clients are a barrier to entry.
Hell, I spent two years RPing on raw telnet just because I didn't want to download a client. You could be that stubborn/young and dumb back in the day and still get involved, albeit in a way I didn't realize was horrible and broken. You can't anymore, unfortunately, though I think web clients you can log into directly off a game's web page are a promising way to confront this.
-
@Three-Eyed-Crow said:
@Roz said:
From the perspective of someone who places ads on places like Tumblr in hopes of hooking in the younger generation that doesn't realize there's a way easier way to do this RP thing, promise, clients are a barrier to entry.
Hell, I spent two years RPing on raw telnet just because I didn't want to download a client.
Well that's just stupid. Which I say lovingly because I'm your friend but WHY.
@Three-Eyed-Crow said:
You can't anymore, unfortunately, though I think web clients you can log into directly off a game's web page are a promising way to confront this.
Yeah, web clients are becoming really important, because they provide a way for people to just check out the game and poke around without committing to downloading a new program, setting it up, etc.
-
@Roz said:
@Three-Eyed-Crow said:
@Roz said:
From the perspective of someone who places ads on places like Tumblr in hopes of hooking in the younger generation that doesn't realize there's a way easier way to do this RP thing, promise, clients are a barrier to entry.
Hell, I spent two years RPing on raw telnet just because I didn't want to download a client.
Well that's just stupid. Which I say lovingly because I'm your friend but WHY.
Bwahaha. Pure dumb obstinance, which is the beginning and end of the reasoning behind many things I did in college.
From a user standpoint, I'm excited about things like Evennia, and what I've seen of AresMUSH, just because I want to see where they go and what they look like when people start playing with them. Even if the future is imperfect, I like the idea that people are still interested in working on it.
-
@faraday said:
But when you think about the user experience, IMHO it becomes a little murkier. Right now I can have multiple character windows open across multiple games, yet still have a central client to flip between them and a central notification system. The games all have a different syntax, but fundamentally they all work the same way and I interact with them in the same way. I can save logs to my desktop easily. Replicating those core experiences in a web client is going to be a challenge.
Oh, it is a challenge. It's a crapload of work - no arguments there. Doom 2 had to go through that crapload when they went up from Doom 1, right? But all I'm thinking of here is the user experience, so to use your paradigm:
-
A web browser can have as many tabs open as your machine can handle. Isn't that central enough? Notifications can be easily implemented.
-
Since we're talking about web development at this point there are a zillion libraries and methods already available you can use to do this without having to rewrite your own from scratch. Compare that to the meager resources a handful of our community's enthusiasts have been kind enough to share with us so far.
-
Logging can be done much more efficient on a web browser! You could implement an interface so you can mark part of your backscroll and send it straight to a wiki log for instance, ready to be used - or you can keep your existent method (is it harder to copy/paste from a web client's tab into your editor of choice than from SimpleMU?).
-
You can do context-sensitive stuff. Like... right click on a person's name and you can PM, view their wiki entry, add them to a group conversation - how annoying is it to update pages to multiple people? - or whatever else. Or... you're looking at a help file, and just click the hyperlinks to read the next entry.
There really is no comparison, folks. The feature sets are a world apart. Hell, you could conceivably implement a web interface that's identical in every way to SimpleMU without a single thing missing - but why would you?
All that's missing is hands on deck to implement what we already have - and if people like those who're offering Evennia are doing part of the grunt work then the only correct response is gratitude. Even if I never touch their code or play a game they made, it's silly to berate them because what they're doing isn't providing us with all the bells and whistles - the result of so many years of development - yet.
-
-
@Arkandel I wouldn't want to have multiple tabs open for my games, and web page notifications are kind of flakey in my experience. The Slack chat client has a web app - but I far prefer the desktop client. That may just be a matter of personal taste.
I also have to disagree about logging. Existing MUSH clients log without needing to copy/paste anything, and I don't really want my logs auto-posted to a wiki; I want them saved to my hard drive. Not saying you can't do it, but live-update logging to a file on your desktop is not really what web pages are geared toward.
You're quite right that there are a zillion libraries and methods for web development. It's a lot easier than it used to be, but it's still hard IMHO. And I say this as someone who writes web apps for a living
Anyway, as you say - Evennia offers web functionality for those who need it, so props to them. Time will tell if that proves to be the wave of the future.
-
@WTFE
I agree with you 100% where I agree with you.Why would %[...] be insane? I mean, I prefer typing %(...), but for me, visually, the hard edges of the [ are easier to see over the { and ( characters. I don't think %[ is used that often in the English language. By 'not often' I will guess 'not at all'.
I'll also agree with @faraday that some shortcut for ease of typing in situations where little things are little are perfectly fine. %
may not be the world's bestis not even remotely a sensible token, but having a shortcut character makes life easier on the author. And I'll admit, `|r<text>` is a hell of a lot easier to type than `$[ansi( r, <text> )]`. I'll live with escaping the occasional character for the usefulness of those shortcuts.Maybe I can live with $(<ansi code>), but I'd also want shortcuts for carriage returns/line feeds/whatever, dbref of self, subjective form of the enactor's gender, and so forth. As I'll get into later, a lot of what I think Evennia is missing in the inline-code aspect is for the builders, not the coders.
Also, I see what you mean about `. I still don't think escaping is horrible, in small doses. Or bigger ones when it's SQL and I can't exactly complain to the ANSI committee.
@Griatch said:
I think @thenomain should probably have referenced this feature request which actually provides the context for the discussion.
I purposefully didn't. For me, the context was my bringing it up without realizing there was a feature request in. Then to throw that concept out into the mixed pool of Professionals and Amateurs, stir, and see what would happen. Which is why ...
We didn't have a compelling enough use-case to implement it since we don't explicitly support softcode and no user had so far felt that nesting was a must-have. With enough good arguments brought forward we might well expand the design to support it.
This is why I'm muddling up the discussion a bit by bringing it here. I was less interested in "would you solve problem x this way?" and more interested in seeing how Mushlike people would respond to "problem x".
I am overjoyed that people jumped on this with input from their own experience. <3s all around.
@faraday said:
@Griatch I think the biggest issue is that "builders" kind of straddle the fence between "players" and "developers" in terms of their use of inline functions.
Emphasis mine. I would make this 72 pt text and blinking bright red if I could. (note: I realize now that I can do some of this, but I'll be nice. you're welcome.)
While in #evennia chat yesterday, another user (acharles) was surprised that allowing players to use color codes was on by default. As a Mud developer, his viewpoint was valid and interesting and entirely backwards from mine. I was surprised that Evennia had inline functions turned off by default.
A good Mush builder is constantly asking me for code to allow for creativity, clarity, and organization. I would say that almost all of my non-RPG-system code is for builders. Yes, I will be doing a lot of that server-side with Evennia, but for example I can easily let a builder change small parts of the description of a room based upon the time of day. I don't have to do anything but expose a function I call `ictime()` and the rest is them.
@desc here=This is Thenomain's happy place, with one window looking out across the landscape. It is [get( me/desc-[ictime( time-of-day )])]. &desc-dawn here=dim and hopeful &desc-day here=bright and cheerful &desc-dusk here=maudlin but relaxing (you get the idea)
I know Evennia is not geared toward coding inside the game, but the shortcuts available mean that the builders are enabled and the main coder is less depended upon. To me, this is a win-win.
Of course, this is only important to the games who give this level of control to the builders. I won't pretend that the Mush niche is more important than the Mud niche. I wanted to expand on Faraday's example with a 'oh god dear god yes a thousand times yes'.
-
@Thenomain @Griatch FWIW in terms of builders being mini-coders, the common examples I've come up with where builders might need functions are things like spacing/formatting, weather and time of day. My plan for AresMUSH is to make these things into format codes. I confess I stuck with the existing paradigm of % codes for formatting. Ares is geared towards backwards compatibility more than extensibility.
So in addition to the old standbys like %r for a linebreak, you can have things like %l1 and %l2 for those nifty border lines that turn up all over creation, and %timeofday for the time of day, and %weather for the weather, and stuff like that. (Admittedly the latter two are in the TODO column still, but that's the idea).
Edit to add: Oh, and I stole the %x and %c codes from MUX(?) for ansi control. So %xb toggles on blue.
-
@faraday said:
FWIW in terms of builders being mini-coders, the common examples I've come up with where builders might need functions are things like spacing/formatting, weather and time of day
Sometimes it gets even more complex though. Sometimes, you need commands that only work inside of specific rooms, for which you code in $-commands. You sometimes need rooms that can respond to certain stimuli within them, and so listen patterns become important. Etc.
Essentially, there could be a reason for a builder to need nearly every function available to the MUSH (because most commands have functional equivalents, and the ones that don't are probably things you wouldn't much use on a room anyway). Not every room has a strict IC purpose, because they aren't all IC rooms. Some of them serve specific OOC purposes (your build nexus, for example). The IC side of things is all well and good, but time/date/weather/formatting is just a small fraction of what builders will end up doing.
-
@Thenomain said:
Why would %[...] be insane?
It wouldn't be. Plain […] was an insane choice. %[…] is sufficiently distinct that it's perfectly fine.
-
Fair nuff.
-
@WTFE said:
You can't get away from null ... and yet entire language environments exist in which there's not a nil/null/whatever check in sight.
None that I use regularly... except for assembly code. ColdC doesn't need to. It does have a nil object (#-1), but I've never actually used the syntax. You do have to do valid() checks on objects considering they can be user entered. But then that goes to the issue of interactive user programming being quite similar to hotloading code.
For example in Ruby I might have a Character that initially has two stats:
$ irb irb(main):001:0> load "./character.rb" => true irb(main):002:0> bubba = Character.new "Bubba", 3, 5 => #<Character:0x00000600359390 @name="Bubba", @str=3, @cha=5> irb(main):003:0> bubba.score Name: Bubba Strength: 3 Charisma: 5 => nil
I decide to rewrite it to add a third stat:
irb(main):004:0> load "./character2.rb" => true irb(main):005:0> boffo = Character.new "Boffo", 2, 4, 3 => #<Character:0x0000060038aff8 @name="Boffo", @str=2, @cha=4, @dex=3> irb(main):006:0> boffo.score Name: Boffo Strength: 2 Charisma: 4 Dexterity: 3 => nil irb(main):007:0> bubba.score Name: Bubba Strength: 3 Charisma: 5 Dexterity: => nil
The issue is that @dex doesn't exist on Bubba in memory (or for that matter in any data store).
So the field has no value or nil.
So you have to fix that issue with a handler that does it automatically.
For example, to fix all Characters in memory by setting a default:irb(main):008:0> ObjectSpace.each_object(Character) {|x| irb(main):009:1* if !x.instance_variable_get(:@dex) irb(main):010:2> x.instance_variable_set(:@dex,3) irb(main):011:2> end irb(main):012:1> } => 2
And of course you'd have to update whatever data storage schema you're using.
In an interactive programming environment like ColdC the above is like:
@add-variable $character, dex = 3
It shouldn't be much of a leap to apply the same automation to hotloading code.
The above is just a simple example though. There are othe issues to handle like
deleting and renaming variables, deleting methods, etc.
You also need to correctly update the code itself.
Using Ruby meta-programming to write your own attribute accessors and consistently use
them in "plugins" helps a lot.I don't know Erlang but quoting from the Wikipedia entry:
"Successful hot code loading is a tricky subject; Code needs to be written to make use of Erlang's facilities."
Same is true for Ruby and Python. It's a tricky subject.@WTFE said:
If you can have a value that is "nothing" that needs to be tested for before you do things, you have a null check. It may not be a physical null pointer (although I'd bet large amounts of money that most ARE such behind the scenes), but it's effectively the same thing: a bottom test. An unnecessary complication that boils down to "get X, test if X is actually there, use X". Such a manual cycle is incredibly error-prone (and is, indeed, at the core of a lot of security breaches and other related bugs).
Languages which don't have this basically do proper abstraction behind the scenes. Prolog, for example, has no "nil" value (unless you deliberately put one in for the rare use cases in which it is necessary). Any language with proper higher-order functions (or equivalent) can also dodge the bullet in most cases. The same applies to languages like Erlang or the ML family (although sadly in the libraries people will define an equivalent instead of thinking out their abstraction; imperative thinking still infects even declarative languages a lot of the time when people get started).
As an example of how Erlang (the language, not necessarily the library) avoids the need for nil checks, the core of a proper Erlang program is a process. A process has a mailbox. A typical process waits for a message and reacts according to it. If there is no message it waits until there is one. There's no cycle of "get message; check if message exists; do something with that message" -- unless you explicitly TELL it to work that way (with timeouts, etc.). By default there's no need for nil checks.
Similarly pattern matching in the MLs, combined with the nice array of higher-order functions, eliminates the need for nil checks in the overwhelming majority of cases you'd find them in imperative code (to the point that I don't actually recall when I last did an explicit nil check in SML). Sure, under the covers, there's presence checks galore, but the end-user is shielded from them in 99.44% of the cases unless they're doing some very specific things.
As for Prolog, the most common use case for nil checks in imperative languages coincides with backtracking situations in Prolog. The runtime finds the "nil" (no solution) case for you and just goes back and tries again if there's another path.
Of course I went searching for muds that use Erlang, ML, or Prolog.
I did a search on my own project
Searching for 'nil'
Found 212 occurrence(s) in 60 file(s)I found PrologMud which is more MOOish and has some very interesting features.
Searching for 'nil'
Found 622 occurrence(s) in 81 file(s)Turns out my top use of 'nil' is in generated parser tables (Racc - Ruby Yacc). Not disimilar to Prolog's use of them in rules to indicate no solution.
The next biggest use was in test code assertions.
And then in parameters passed to functions. PrologMud appears to also do that also quite a bit.But then I looked for explicit checks in my code.
Searching for 'nil?' or '== nil'
Found 30 occurrence(s) in 26 file(s)
That doesn't find them all because I also use other forms.x ||= 56 * y x && (x = y + z * 42)
I'm not very likely to switch my style of programming in C, C++, Perl or Ruby.
If anything it's a motivation to add more checks on nil or null.
Nor am I likely to eschew a language or environment that uses them heavily or learn one
because it doesn't. Prolog looks interesting just for its possibilities for natural language
parsing and AI which PrologMud seems to make use of. -
@Thenomain said:
For people reading this thread who are more softcoders, a situation that came up in the Evennia IRC channel:
In order to embed functions, you currently need to type
{function( args )
. Since my text editor wants to close all brackets, braces, parens, and so forth I suggested another character. They were already thinking about|function( args )
, which while I think is better I don't think is very legible. For example:This is a test|testfunc( me )...
I suggested fully enclosing for functions. The above might be:
This is a test|testfunc( me )|...
Someone mentioned brackets [], and as a Mush coder, this hit a happy spot. The above would end up:
This is test[testfunc( me )]...
However!
Evennia's lead designer wants a single token to mean all inline substitutions, both ANSI and functions. ANSI color codes would use the same inline token. For example:
{r
for red,{B
for blue background, and so forth.Why is this a problem? Because ANSI color codes would become harder to type if brackets [] were used. I mean, imagine typing this:
[r][h][B]This is really ugly text.[n]
Eugh, no. This would be a lot easier for everyone:
|r|h|BThis is really ugly text.|n
If it's really a framework, it won't be just one way. There ought to be formatters/translators and generators or some such abstract arrangement. Your formatter will take in html, bbcode, mushlike format, diku/merc format, cml, or whatever and store it in some intermediate format.
When it comes time to process and send it to the VT100 terminal or WebClient it will generate VT100, html, MXP or whatever the client wants. When it comes to editing or setting it, it ought to show in the format the user wants to use.
@set my formatter=mush
or
@set my formatter=html
or
@set my formatter=bbcode
followed by
@edit my descriptionJust a thought.
-
@Tyche said:
If it's really a framework, it won't be just one way. There ought to be formatters/translators and generators or some such abstract arrangement. Your formatter will take in html, bbcode, mushlike format, diku/merc format, cml, or whatever and store it in some intermediate format.
When it comes time to process and send it to the VT100 terminal or WebClient it will generate VT100, html, MXP or whatever the client wants. When it comes to editing or setting it, it ought to show in the format the user wants to use.
@set my formatter=mush
or
@set my formatter=html
or
@set my formatter=bbcode
followed by
@edit my descriptionThat is a neat concept. We don't have formatter changes on the command line out of the box but you can plop in your own Python parser in the message parsing chain if you wanted to (just overload the
msg()
method on your custom objects, through this goes all outgoing text). If you wanted multiple styles as you suggest you could make a command to do so (just have it set some flag and have your addition tomsg()
check the flag to decide which parsing to go for).
The Evennia markup syntax is converted to client-specific code at the protocol-level (so a "red" marker (currently{r
) will be translated to the red ANSI sequence if you are sending over telnet to an ANSI-capable client or to a HTML span if sending to the webclient etc).
.
Griatch -
-
XKCD is as always spot on. There is a lot of useful resources in Python's standard library, sometimes it does feel quite empowering to just do
import X
and instantly have the tools needed to solve whatever it was one was working on.
.
Griatch (flying to a new location for better reception) -
I am reminded of another situation where nested functions would come in handy for builders: width( [<target>] ), the current reported width of the enactor's (or optionally target's) client.
-
@Thenomain Huh, I never even knew width() existed. How does the client communicate the width to the game?
-
@faraday said:
@Thenomain Huh, I never even knew width() existed. How does the client communicate the width to the game?
Through the telnet NAWS option.
Edit to add useful link:
Comparison of MUD Clients -
What @Tyche said. I've been using it a lot because someone on RenoMux told me it was stupid and that nobody would ever use it.
Only Potato on Windows seems to pass that information along, or TinyFugue if that's the way you roll. Atlantis (OS X) also sends it, so at the very least I can get the benefit of it.
I use my own width() function, too, so that can test how other clients see my code without having to physically re-size the screen. Just set your '&width' attribute to a new number, and viola. I hoped that people using the other Windows Mu* Clients would use it too, but it's very hard to break people out of 80 columns.
-
Belatedly - Evennia does check and store NAWS info during telnet negotiation. In practice we have not been making much use of that value in our default command set though - before we supported NAWS or a centralized width, a width of 80 (or even 78) was used and that is still in the code for the most part, just haven't gotten around to generalizing it in many places.
.
Griatch