Thursday, March 29, 2012

On History, Assassins, and crappy rationales...

So, recently there was a press-release style thing from Ubisoft about why they’re not having a female protagonist in AC3. It basically boiled down to “No powerful females in that era!”

I, uh, have a small problem with that justification. It’s worth noting that I don’t really have an issue with their decision. It’s their game, they can have whatever gender/ethnicity/alien protagonist they like. (And, a Native American protagonist in good light, is, in itself, a rarity.).

However, their stated rationale makes no sense whatsoever. Perhaps I’m missing something, but I’m not entirely sure that Ezio ever directly impersonated a Templar to get close enough for the stabby-stabby.

Hell, in AC:Brotherhood, you can recruit female assassin novices, and send them on some pretty high-profile contracts. (Funnily enough, my best assassin in AC:B was a blonde female, first to Assassin rank, never failed a contract, and was hilariously lethal when called to aid Ezio.)

Essentially, the case is “Because institutional sexism”, it’s not believable if they challenge it. Er, huh? The entire concept of the games is frolicking about in the grey margins of history, writing whole subtexts and grand plots that aren’t there. A few Templars dying horribly because they made the mistake that “A woman can never be a threat” would play incredibly well into the game’s core themes. It neatly nails a subversion of expected history AND the powerless toppling the powerful.

If anything, it’d work better, since the protagonist could just pose as a maid and be effectively invisible. (And, last I checked, Ezio blended in with mostly female crowds just fine.).

All that said, I can think of a much better explanation for it. The whole Animus concept revolves around living in the body of your ancestor, and getting to the good bits requires a high-level of sync. (And side-effects of blurring your own memories with that of your ancestors...). It follows that Desmond, someone with a clearly male gender identity, would have a hell of a time syncing with a female ancestor, if he could at all.

Hell, you could address that in a couple of throwaway lines, or even a failed sync with a female ancestor that directly knows what you needed to know.

So, with a decent explanation at hand, why try to justify it with something that doesn’t make any sense at all in the context of the game universe?

Monday, August 15, 2011

Reworking Arcane Defiling

I'm currently running a Dark Sun game in 4e. One of the merry band of miscreants is a Defiling Wizard. Now, since they all went into it knowing that having a wizard in the party would cause some trouble. (And I'll be honest, the player of the wizard is playing a shade north of evil character to the hilt, and it's hilarious.), I want to make sure the wizard stays useful. The RAW arcane defiling power is.... underwhelming. "All allies within 20 squares take half-surge irresistible necrotic damage.", for a reroll of the attack or damage roll. Not exactly fear-inducing material. Here's what I reworked it to:

Arcane Defiling
Arcane Feature
You draw on the nearby life energy of comrades and enemies alike to fuel your spells.
Encounter * Arcane, Necrotic, Implement
Immediate Interrupt                 Close burst 5
Trigger: You use a power with the Arcane keyword.
Target: Each creature in burst
Attack: Intelligence vs. Fortitude
Hit: Intelligence modifier necrotic damage.
Effect: For each creature hit by the burst attack, you gain a +1 bonus to the hit and damage roll of the triggering power.
Special: You can use this power as a free action when you use a daily or encounter power with the Arcane keyword.

Now, it's far more powerful, and tactically not shooting the party in the foot. Well, not as much, at least. I'm sure it breaks the math for expected damage per turn or combat a bit, but considering I'm typically running encounters a bit overpowered, it all balances out.

Tuesday, August 2, 2011

It's all in the name.

With the recent spate of account bans for “fake names” on G+, for obvious reasons, I am a bit concerned. Not in the least because of my G+ name. I'm not in a hurry to change it, though. And I am just a little irked by that the majority opinion seems to be that this is an unqualified good thing.

Let me let you in on a secret. My “actual” name is Zachary Boody, I'm an unemployed 22 year old stuck in the rural area outside of Lincoln, NE. It's not a secret. Anyone who knows me, even online, knows most of that info. I'm not a secretive person. Here's the thing, though. With all of that information, good luck finding me. I'm not the only one. It's a peculiarly common name. I'm not even the only one in Lincoln. It caused no shortage of confusion at school ages ago. It's about as personally identifiable as me liking spicy food, or knowing how to drive.

And my supposedly personally identifiable name is likely to change far sooner than my handle is. When my mom got married, I went by her husband's name for a time. When I get married, I plan on taking my now-girlfriend's name. You know what hasn't changed in all that, and for around 15 years, my handle hasn't. I tripped over it as a typo during a sleep-deprived online gaming session when I was 7, and it stuck.

Maybe I'm biased. I am not exactly known for my stellar social life. It's not helped by the fact that I live in the middle of nowhere, but family aside, no one would really care too much if suddenly my real-life name was Bob Smith. A lot less confused than people would be if I changed my handle. Really, there's no one that would be able to find me on G+ using my “real” name that doesn't know my handle, and a lot of people that couldn't find me by my real name that know my handle. It seems a simple choice to me which one to use.

As an aside, perhaps I should clarify my (ab)use of quotes. It's probably pretty clear from the above, I consider Kannon a truer representation of who I am than my given name. I had some input on that, I'm looking to ditch my last name anyway. And, as I said, I've run into a lot more Zachs with the same last name than I ever have Kannons. (Using both last names, even!) I even met the love of my life (Who currently lives with me) online.

Combine that with living in a place where I have about as much in common with the average person as an electric car has with a combine harvester, and most people who truly know me, met me as Kannon. Claiming that it's not my actual identity because it's a psudonym misses the entire point. I could change my profile name to my actual name. But isn't the whole point to have a name that people identify you with?


Sunday, July 17, 2011

My Dream Edition of D&D 5e

Spurred on by this ENWorld thread, I got to thinking about what my dream 5e would look like. And since I can't stand to miss a chance to pontificate, and this is way too long to break the board's formatting with, why not  put it here. To start with, for those that don't know, I prefer 4th edition D&D, but I think all of the editions have done something right. And I frequently use inspiration, convert variant rules from older editions, or Pathfinder. With that in mind, let's take a look at what my dream edition of D&D would look like.

Saturday, July 16, 2011

CherryPy, Server Sent Events, and You.

There was a dearth of decent information on how to implement server side events for anything but PHP, so, being a mediocre python coder, I felt the need to correct this for my favorite web framework. A far better general (or client-side) writeup is at HTML5Rocks. The basic idea is pretty straightforward, subscribe to an event stream on the client, the server then sends a message when something happens, and there you go.

Because of the limits of HTTP, it's not quite "true" push. It's closer in implementation to typical Comet pattern, but an order of magnitude easier to actually use. This does have an effect on how you'd implement it in CherryPy, however.

First, our simple HTML file.

<html>
 <head>
  <title>Server Side Event Test</title>
  
 </head>
 <body>
  <script type="text/javascript">
   document.addEventListener('DOMContentLoaded', function () {
  
     var timeSrc  = new EventSource('sendTime');     
     timeSrc.addEventListener('time', function (event) {
     document.getElementById("Test").innerHTML += "\n " + event.data
     
     });
   
   
   }, false);
  </script>
  
  Test box! 
  <br/>
  <textarea id="Test"></textarea>

 </body>
</html>
Pretty straightforward. That sets up our event listener to listen for an event named 'time', from the 'sendTime' URL. (And appends it to a text box, to make it easier to see.).

import cherrypy
import os.path
import json
import time
from cherrypy.lib.static import serve_file

current_dir = os.path.dirname(os.path.abspath(__file__))


class Root():
    
    #Our toggle variable.
    timeFeedEnabled = False
    
    @cherrypy.expose
    def index(self):
        return serve_file(os.path.join(current_dir, 'index.html'), content_type='text/html')
        #serves our index client page.
    
    @cherrypy.expose
    def timeSwitch(self):
        #When this page gets requested, it'll toggle the time feed updating
        #and return an OK message.
        if self.timeFeedEnabled:    
            self.timeFeedEnabled = False
        else:
            self.timeFeedEnabled = True
        return "Feed Toggled"
    
    @cherrypy.expose
    def sendTime(self):
        #Set the expected headers...
        cherrypy.response.headers["Content-Type"] = "text/event-stream"
        if self.timeFeedEnabled:
            return "event: time\n" + "data: " + str(time.time()) + "\n\n";
        else:
            pass
        

if __name__ == '__main__':
    pageroot = Root()
    #And, standard cherrypy quickstart.
    cherrypy.quickstart(pageroot, config="test.conf")
No big shockers here. The main thing you might wonder about, is why our sendTime url is just a normal request handler. That's the underlying comet pattern helping us out a little. What'll happen, is the browser will ping the server, and if the feed is toggled on, it'll send the info. Which means, if you only want the feed to update when you have something worth updating, you'll need something similar to the timeFeedEnabled variable I have set up. If you don't, it'll just pass out, and it'll keep working.

If you want the feed to stop completely and not come back until a page refresh or other events (say, on log out or something), you can call  .close() on the javascript side, or change the headers to something other than 'text/event-stream', which will also make the web browser disconnect without retrying.

This is a quick and dirty example without any error checking, security, or any real robustness. For example, you'd want authentication and session stuff for anything major, obviously, as well as making sure the event-stream came from your domain. But it does show how to do it, without getting overly complicated.