Ceasar's Mind

Follow me: @Ceasar_Bautista

Author Archive

How to use default arguments with namedtuple

with one comment

I was running into some trouble earlier today trying to figure out how to use default argument with namedtuple.

According to the docs:

Default values can be implemented by using _replace() to customize a prototype instance:

>>> Account = namedtuple('Account', 'owner balance transaction_count')
>>> default_account = Account('<owner name>', 0.0, 0)
>>> johns_account = default_account._replace(owner='John')

This is of course not really what I was looking for.

Searching around some more led to the Python mailing list where a software engineer by the name of Issac Morland suggests exactly what I was looking for.

2. It would be nice to be able to have default values for named tuple fields.
Using Signature it’s easy to do this – I just specify a dictionary of defaults
at named tuple class creation time.

To which Raymond Hettinger (the creator of collections) responds:

This came-up before, but I’ll take another look at it this weekend. If it
significantly complicates the API or impacts performance, then it is a
non-starter; otherwise, I’ll put together an implementation and float it on
ASPN for comments.

And the trail ends. Not sure what the full story is.

In any case, the solution is fairly simple. Just subclass the result of namedtuple and override __new__ as follows:

from collections import namedtuple
class Move(namedtuple('Move', 'piece start to captured promotion')):
    def __new__(cls, piece, start, to, captured=None, promotion=None):
        # add default values
        return super(Move, cls).__new__(cls, piece, start, to, captured, promotion)

As you’ll notice, super is being used a little weird here, with cls being passed to both super and __new__. I’m not quite sure why that’s neccessary, but I can say I’ve tested it and it does work.

EDIT: It appears this question on SO explains the weirdness with using super together with __new__. tldr; __new__ is a static method, not a class method, so it requires an explicit passing of cls.

Written by Ceasar Bautista

2012/03/19 at 15:30

Posted in Uncategorized

Tagged with

Recursive Python Considered Harmful

with 6 comments

It somewhat recently occurred to me that recursion, despite it cleanliness, improves readability at a significant cost in memory. By piling on the stack trace, at best we get a function that uses O(n) memory, and quite possibly even one that is even worse. Given that any recursive function can be written using a while loop with O(1) memory bounds, recursion seems quite a poor choice for all practical purposes.

I brought this up at work and Alexey explained that while this is true, many (particularly, functional) compilers are intelligent enough to optimize the code for you if you use tail-recursion. Being unaware of the concept, I looked up how to convert a regular recursive function into a tail-recursive function and discovered I was wasting my time since Guido has decided not to implement tail-recursion in Python.

This begs the question then, is recursion ever useful in Python or should we go back to our code and start writing those while loops?

As I see it, there is only one reason to use recursion in Python and that is when you plan to memoize your function (which makes the function take up O(n) memory anyway). (Additionally, it may be helpful to write functions out as recursive functions in order to assist in proving things, but I think, again, the function would almost certainly need to be memoized or transformed.)

In all other cases, I believe while loops are the way to go. Besides the obvious problems with memory, there are a few other points worth mentioning.

For one, Python caps the stack height at 1000. While for some functions this may be okay, if you have any interest in scaling, this limit is way too small.

Additionally, function call overhead is Python is extremely slow. (Source: the official Python wiki.)

Anyway, that’s my two cents.

Written by Ceasar Bautista

2011/10/23 at 00:51

Posted in Uncategorized

Tagged with ,

Understanding Flow

with one comment

Have you ever lost yourself in an activity and found yourself performing beyond expectation?If so, then you know exactly what I’m about to describe, and it’s a topic collectively referred to as “flow.” Flow is a concept in the field of positive psychology that was first proposed by (and extensively studied by) Mihaly Csikzentmihalyi, a Hungarian psychology professor, back in the 1960s, although only becoming popular fairly recently, particularly among the game development industry.

What exactly is flow?

So I kind of skimped on the definition. “Flow is the mental state of operation in which a person in an activity is fully immersed in a feeling of energized focus, full involvement, and success in the process of the activity.” It’s typically hard to trigger in our day to day life, although I’ve triggered it before while playing soccer (“the zone”), programming (“wired in”), and notably, a variety of high intensity video games, ranging from Halo, Call of Duty, and even Wii Tennis (seriously, I used to sweat while playing games a kid, and sharing controllers because impossible). It’s the state when you get so immersed in something that you kind of lose track of yourself, lose consciousness, and just let your body take over to do the impossible. That is to say, if you’ve ever done something and then stopped and realized you just did the impossible, then you’ve felt it. (Mihaly often refers to flow as “the optimal experience.”)

Why is flow important?

You may have heard that more money does not make us happy. Lottery winners enjoy their winnings ecstatically for a while, but then get used to their new riches. Likewise, you may have heard (or may personally know) of people who have lost things that are irreplaceable to them, their legs or arms, or loved ones, yet after some time eventually cheer up and become perfectly happy people. The answer to why flow is important is the same answer to why people who gain or lose massively can be happy.

The answer is that extrinsic rewards- sugar, alcohol, drugs, sex, money -are fleeting. The human psyche has an in-built system familiarly known as “the hedonistic treadmill” that ensures we are never content with what we have. All gains are relative, so to get our fix with any of these things, we are compelled always to acquire more.

Intrinsic rewards however, do not suffer this problem. Something that is intrinsically rewarding can be done repeatedly and never lose its appeal.

Flow is intrinsically rewarding.

Triggering flow

So that’s all well and good. But how do we trigger flow? In short, to trigger flow the difficulty of a challenge must exactly meet our skills in such a way to demand maximum concentration.

A graph of the various states of emotion produced by combining different levels of skill and challenge.

A graph of the various states of emotion produced by combining different levels of skill and challenge.

We do things optimally when the experience has been tailored to match our skill level. This is why games with adaptive difficulties, Tetris or Wii Tennis immediately come to mind, invariably trigger flow. In fact, if you look carefully, you’ll quickly understand why Mario Kart is so incredibly addictive- since the better you’re doing, the worse your items and better your opponents items, you are always playing at your peak, and when you screw up, the items prop you immediately back into it. (This adaptive difficulty in so important in some competitive games that game designers have a name for it– aptly, the rubber-band effect.)

This is, in real-life, typically pretty hard to achieve. When only a few friends are available to play soccer or ultimate, you either find yourself playing with newbies or experts, and in either case, the game isn’t challenging enough to be fun. Likewise, while studying for a test, most times the text-book is too dense (or very rarely, too shallow) such that learning becomes very difficult. It is no wonder people get addicted to games, or at the least, would often rather spend an hour in a virtual world than the real one.

Addendum: I thought it was interesting to read that many game designers these days stop playing games once they’ve mastered them. At that point, the learning stops, and the game becomes tedious rather than interesting- put another way, imagine playing Tetris except remade such that it never got harder. Not fun.

More interestingly, this suggests that learning can only happen in a state of flow, if only for brief moments. Content that we already know and poorly presented content that we don’t know both bore us because we aren’t in flow, or equivalently, not learning.

How to put a stopper on flow

Flow is inherently tied to performance. Thus, the surest way to put a stopper on flow is to make us think- the essence of bad design. Notice how puzzles could never direct a person into a state of flow, nor a poorly written text-book. (Well, most puzzles. If they are designed correctly, one should never get stuck, but most seem geared to stop us. Portal is an astounding example of good puzzle design. This is all not to say conventional puzzles are bad, just that they focus on producing eureka and that eureka is incompatible with flow.)

It is so obvious to game designers that thinking is bad that anything not a puzzle game always makes it extremely obvious how to complete the objective. Just to drive the point home, let’s dissect a typical quest in World of WarCraft:

Quest: A Distracting Scent
Predators will smell these dead naga from nearly a mile away. Soon we’ll find ourselves fighting just to get in and out of the cave. Care to help me clean up?
Just over the ridge to the south is Glimmerdeep Gorge. If you drag the corpses over there and cut them loose, the wildlife will pick them clean before they hit the sea floor. Just steer clear of the sharks as much as you can.

Notice there is no thought involved here. There is just a set of instructions here. While of course this doesn’t guarantee that players will find the task difficult enough to be interesting, the fact that the players could not possibly misunderstand what they are expect to do ensures that the player could never be unexpectedly un-immersed from he game.

But if flow requires that we don’t think…

Doesn’t that mean it’s more or less just work? Quite simply, yes! Putting this all together, this means that sustainable happiness is possible only through sustainable interesting work and perhaps more interestingly that games are a form of work! Quite an interesting take on things.

Written by Ceasar Bautista

2011/09/02 at 12:00

Games as Economies

leave a comment »

In a previous post, I wrote about how it’s impossible to price an object in a game according to a systematic formula, barring games of limited complexity, and objects that cover the same span (that is, there are just different multiples of the same vector). Instead I claimed at the time it was just arbitrary- that designers could set the prices to whatever they liked and that the game would always be fair so long as each player had equal opportunity. Thus, the designer’s job is really just to play with the prices until it produces the interplay he is looking for.

In another post, I wrote about how research in RTS games, and why spending resources in order to have the option to train new units can payoff. While upgrades obviously boost the strength of an army, research unlocks news units for a price, and that price is only worth paying if one can expect to use the unlocked units in such a way, that the utility of their use exceeds the initial cost of research. Thus, the price of research is also arbitrary.

Having since studied microeconomics, I’d like to revisit these topics.

An indifference curve is a line that shows combinations of goods among which a consumer is indifferent.

Economists call the phenomenon I just described the marginal rate of substitution or MRS for short. Formally, the MRS is defined as “the rate at which a person will give up good y for good x while remaining indifferent”. In other words, it’s the price at which you are willing to buy something using something else (ie, how much you are willing to shell out for a can of soda). What’s interesting about the MRS is that it changes- the more a person has of good x, the more one is willing to trade of good x for good y. Said another way, because billionaires have so much money, they don’t mind paying $5.00 for a hot dog.

This is a far more intuitive way of looking at things than trying to predict prices from the attributes of the game objects. In short, all one needs to understand now is that players will buy an object when the utility of a object exceeds its cost.

While the main point I wanted to convey has been made, I want to just put down some related ideas that don’t exactly deserve a post of their own but that I think are worth sharing.

-If you are familiar with Dominion, you may know MRS as “the Silver test”. (If you are not familiar with Dominion, all you need to know is that players regularly face the choice of buying cards with special effects or treasures, such as a Silver, which increase income.) That is, when making a non-trivial purchasing decision, one always has to consider if the object at hand is in fact better than a Silver. What I find most interesting about the Silver test is how many players completely fail to pick up this rule, instead being regularly mislead by the incorrect assumption that “things that cost more must be better”. Certainly changed a few paradigms of mine after noticing what was going on.

-Knowing when to buy what is the backbone of many games. In Dominion, playing cards is fairly trivial- but the decisions of which cards to buy each turn is often rather complex, and in the majority of cases, determines who wins. Likewise, in StarCraft, micro-ing units is fairly simple- but, again, the decisions of which units to buy and which tech to research is far more complex, and is far more important than any tactical feat. In short, your economics textbook may be more valuable than The Art of War.

Written by Ceasar Bautista

2011/08/27 at 19:39

Strategy: A Definition

leave a comment »

If you’ve never seriously studied the concept, strategy is really rather hard to define. At first glance, strategy seems synonymous with the word plan, but that’s not really true, since plans aren’t really adaptive- that is, plans assume everything go as forecasted. (Hence the phrase “everything is going as planned”.)

Even as a strategy gamer, it doesn’t become much easier. Amateur gamers throw the words “tactics”, “strategy”, and “plan” around as if they were interchangeable; maybe embracing some small nuances that are hard to define. (Typically, as I understand how it’s popularly perceived, “strategy” refers to long term goals and “tactics” to short terms goals. These definitions are problematic though because like any other meta definition, take the concept of a pile for example, they are impossible to explicitly define.)

Fortunately for us though, game theory offers a pretty satisfying definition that is so useful that I think it’s worth sharing. According to game theory, a strategy is an algorithm that takes a game state and produces a decision. Rephrased, for all possible states in the game space, reachable via rational play or not, a strategy defines a decision.

If it seems silly for me to explain this, it kind of is, except that I plan to use the definition defined here in the future. Stay tuned.

Written by Ceasar Bautista

2011/08/21 at 00:34

Posted in Uncategorized

Tagged with ,

Python Tips

leave a comment »

The “with” statement

This is just incredibly beautiful code.

Check out the source for more details on Python’s “with” statement if you’re interested.

Get current directory

Too useful not to know.  Source is here.

max and min accept a sorting function

Instead of writing out this:

def best(candidates, scoref):
    '''Use scoref to find the candidate with the highest score.'''
    highest_score = float('-inf')
    best = None
    for candidate in candidates:
	candidate_score = scoref(candidate)
        if candidate_score &gt; highest_score:
            highest_score = candidate_score
            best = candidate
    return best

You can just write:

max(iterable, key=scoref)

Don’t forget the “key” keyword, or Python will think you are comparing the list against the function. This is pretty cool because it makes things like getting the max value in a dictionary trivial.

>>> a = {'a': 1, 'b':2, 'c':3}
>>> a
{'a': 1, 'c': 3, 'b': 2}
>>> max(a, key=lambda x: a[x])
'c'

Written by Ceasar Bautista

2011/08/02 at 22:26

Posted in Uncategorized

Tagged with ,

Complex vs. Complicated

leave a comment »

My younger self very much liked arguing with people. Not to piss people off, but to fire up their passions, and delve quickly into the core of an issue.

One such issue that is particularly vivid, is the difference between the words complex and complicated.

There is a common idiom among game designers that complexity is good, while complication is bad, although a bit of complication is needed to produce complexity. This was for the longest time extremely confusing to me, and I finally came to understand the difference today. Here are two pictures to explain.

Complexity refers to systems. A Rubik's Cube, for example is extremely complex, due to the number of moves at each step. Chess likewise, Advance Wars, likewise-- most games and pretty much anything that is not fully understood is complex.

Complication, on the other hand, refers to content. For example, most law is complicated. Understandable, but just draining to read. Chemistry is also pretty complicated. My perception anyhow says chemistry is hard because there are rules, exception to rules, and exceptions to exceptions, all of which must be memorized. That of course puts Pokemon's type match-up matrix hell up there as well.

Written by Ceasar Bautista

2011/07/28 at 23:36

Posted in Uncategorized

Tagged with ,

Follow

Get every new post delivered to your Inbox.

Join 69 other followers