Monday, 14 January 2019

It's always your political opponents engaging in a culture war

The art of modern political discourse is to treat whatever you issue you care about as either the status quo, or what would be considered the status quo if everyone thought about the issue for more than two seconds. Then any and all criticism can be framed as the opponents of the idea as "playing politics". This is true no matter if your ideas are on the left or right, authoritarian or libertarian, populist or contrarian, etc.

In reality, a culture war always has 2 (or more) sides, and each person engaging in it is playing politics. We have a "my side" bias that makes our own proposition seem inherently reasonable and thus beyond reproach. Those who oppose it are then unreasonable by definition, so they are the ones playing politics to us.

This issue came up in Australian politics with our current Prime Minister Scott Morrison using Twitter to announce that those moving citizenship ceremonies away from Australia Day are playing politics, so the Federal government is mandating that they must be held on Australia Day.

How he could think that he's not playing politics is beyond me, except in the context of the rhetorical device used above. It's playing politics in exactly the same way as those councils that moved the date - it's just that he's on the opposite side of the issue.

There are ways to depoliticise the issue. The most obvious would be to stay out of it and leave it as a matter for local politics. They are elected officials, after all, and the ballot box is as an effective tool on the local level as it is on the federal. So if the voters are genuinely concerned about a change in date, they can do something about it.

Another strategy would be to pick an arbitrary date that takes the issue away from its context. This move is more political than staying out of it, but it takes it away from the cultural narratives that the issue is being fought over and this avoids taking a stand on the issue.

But I'd wager Morrison doesn't want to avoid taking a stand. He knows full well what's at stake, and thus is taking a side that will serve him politically. And that should be expected of any politician savvy enough to be elected as leader of his party.

Sunday, 6 January 2019

The hills to die on

Thanks to social media, we now know everyone's opinion about virtually everything. And because of social media, the ease at which the right of reply can be exercised means we can nonchalantly stand a stand when needed. Or even just take a stand on whatever issue we feel like.

Politics, in this sense, means we're always on. There's nothing left on earth these days that can't be made political. Even when there's not an explicit link, omission or the identity of the user can turn something political.

The obvious problem with this is that we're often stretched in terms of our knowledge and abilities to make meaningful contributions to the dialogue. So we tend to be dismissive of ideas entirely, either relying on moral judgements, or going after some hidden political allegiance instead. Bad ideas don't get destroyed, but the people espousing bad ideas get shouted down - just like what happens to people espousing good ideas, or seemingly uncontroversial ideas too.

The more I think about it, what stands out for me is just how willing people are to take each of these topics, which they scarcely know anything about, as being worth standing up for. Part of this is the moral content, where it's good to stand up for moral ideals. But I'm sceptical of how far one can stretch their moral beliefs to be able to give resolute defences. I think the way social media plays out is evidence that it can't. We're far too sure of our positions given how little we can explore them in any detail.

To an extent, we all need to choose our battles. Morality makes for the illusion of expertise, which leaves us ill-equipped when encountering rival beliefs. To be able to defend a position adequately requires a deep knowledge of a topic, and we as individuals can only dedicate ourselves to learning a few things in our lifetimes - and even then most of us only will have enough knowledge to speak basically.

Take a non-controversial moral case: racism. Racism is bad, and ought to be opposed - a sentiment all but racists will get behind. Sometimes people accidentally say racist things without realising, and sometimes racist tropes get perpetuated. And many acts of racism are invisible to us, so it makes the problem of eliminating racism all the more difficult.

What most of us are able to do is call out explicit racism, which is fairly easily recognised. But most of us would be at a total loss on how to deal with issues like immigration, where racism may play a role in some people's opinions, but isn't really solved simply by shouting down an opinion as "racist". Indeed, this can backfire as can be seen around the world with populist anti-immigration politicians who are gaining sizeable voting numbers by capitalising on the gap between the anti-immigration sentiment and a coherent debate on the various issues.

(Of course some people are anti-immigration for racist reasons. And some people have implicit racial biases in theirs, even if they aren't explicit. The point isn't to deny that there's a link between racism and anti-immigration sentiment, but that the immigration debate isn't well served by simply pointing at race.)

Most of us aren't immigration experts, nor really know how to manage all the aspects of a society that immigration touches. We aren't experts on running an economy, planning a city, managing resources, etc. We resort to vapid slogans and moral condemnations of our ideological opposition because that's all we know how to do. To dismiss the whole debate as racist (or to see the debate in terms of race) means that the debate is largely irrelevant to the political reality.

Similarly for other issues that race touches on. How many of us could talk efficacy of workplace laws, or of the legality of hate speech, or of methods to deal with differing incarceration rates, de facto segregation in housing and schools, education gaps, inequality of opportunity, healthcare outcomes, etc.? Even if we know the extent of the problems, few of us can say anything meaningful in schools.

If a racist started attacking affirmative action, for example, how many of proponents of affirmative action could defend it in anything other than talking points? Not many, I'm betting, but I've seen the very idea of saying there's that affirmative action may be up for debate dismissed as proving racism on the part of the questioner.

Perhaps part of it is the rise of punditry in the 24 hour news cycle, where expertise has been replaced with opinion, and feeling strongly on a topic counts more than a deep expertise on the topic. When there are so many things in society worth feeling strongly about, how do we adequately defend all of them? The reality is that we can't. What we can do, however:

  1. We need to pick our battles. We can't defend everything, so we shouldn't try. More often than not, we look the fools and we don't serve the issues well.
  2. We need to give the benefit of the doubt. Not everything is an instance of the thing we care about, and certainly not worth defending to the death.
  3. We need to live life beyond politics. Most of what we do with most we do it with most of the time is not political. Making battles worth sacrificing friendships or relationships seems self-destructive to no clear degree. No-one thinks wholly like we do, so conflict is inevitable the more issues we take stands over.
  4. We need to learn more. We should know a topic in depth, which should be done in a rigorous nonpartisan way. Learn the science, where the science exists, and read diverging opinions in the field.
  5. We need to listen to our opponents. We should be able to state an opponent's case better than they can, including what positives their view has, and be open to their views changing our minds. Only that way can we begin to have a dialogue.

Tuesday, 25 December 2018

"Culture wars" are lazy politics

As far as the moral norms of both major parties in Australian politics goes, they're both middle of the road. Sure, there's the occasional far right winger in the Liberal Party that rallies against the prevailing norm, but politicians tend to know which way the moral winds are blowing and pander to it. Labor isn't a very progressive party in that respect, much to the chagrin of progressive voters, as they need to keep a broad appeal.

So when our Prime Minister says a vote for Labor is a vote for "extreme gender policies", he's lying. And such a comment works for the very reason you won't see Labor supporting anything resembling an "extreme gender policy" - because Labor needs to keep a broad appeal. It's the same reason why Labor opposed gay marriage when there wasn't much public support, then advocated for it when there was.

Which brings me to my point: this sort of rhetoric really brings down democratic discourse. That instead of debating the issues that tend to divide the left and right, we're instead fixating on a virtually non-existent issue that has little relevance to the direction of the country for the next 3 years.

It's lazy politics because of how easy it is up get people riled up over it despite how little relevance it has. The 8 people who take any mention of gender to mean it's denying their right to exist (it doesn't - no party has an "execution of intersex and transgender people" platform), and the True Believers who think that gender was defined the moment God fashioned a penis from dirt and a vagina from a rib, are going to make noise that exacerbates a non-issue into the public consciousness.

There's plenty of issues separating the major parties; issues that are relevant to the functioning of government and ought to decide the election. There are meaningful differences in funding public education and healthcare, differences in workplace laws and taxation, differences in environmental policy, etc. And even in issues where the major parties don't differ much (immigration, national security, food security, trade, indigenous issues, etc.) there's plenty of issues that ought to be debated publicly. But "culture wars" issues are playing into conspiracy theories on the fringes of politics and pretending they are relevant or a defining point of difference. It's cheap point scoring over nothing.

Saturday, 17 November 2018

We are all partisan hacks now

When I was younger, I thought the internet would improve political discourse, as it would take away the stranglehold of the mainstream media. Information wouldn't be filtered through a few agenda-laden voices, but there would be more of a focus on facts.

It's fair to say that I was extremely naive, and spectacularly wrong. Instead, as we all have come to learn, the internet has exacerbated the polemic nature in us and pushed us into even more tribal positions to the point we don't even feel the need to engage in substantive rhetoric.

But the problem is worse than that. We can now see others as mere mouthpieces of certain political rhetoric. In other words, they are biased, and all we need to do is point out how they are biased in order to dismiss them.

I've seen right wingers use the accusation of being left wing against fellow right wingers, and left wingers do the same against left wingers. The accusation is often confusing because those criticisms are often valid, but their use is disappointing because it shows how lazy we've become in our political rhetoric. We don't feel the need to address the substance, but immediately and indiscriminately try to cast the criticisms as extensions of a political identity we don't share.

It doesn't matter why we hold the positions we do. It doesn't matter about the underlying substance. It doesn't even matter where we actually sit on the political spectrum. When we are online, we are avatars of whatever politician / pundit / celebrity and need to be attacked as such.

Let's face it, we don't know nor need to know anything anymore. We don't need to have informed opinions, or be able to think through an issue. What matters is which side of politics closest resembles the view being put forward, and we need to remind ourselves that we are mere puppets of those views with no values or beliefs of our own.

Friday, 2 November 2018

Try putting politics you disagree with in terms of positive values

If you can't articulate a positive account of a given political belief in terms of positive values, you haven't understood that belief.

With the erosion of political discourse online, it's often hard to get away from the partisan rhetoric and inevitable strawmanning. We have our own political narratives for our own beliefs, bolstered by a community of like-minded individuals, yet we are isolating ourselves from other groups who respond to different values and narratives.

The more I saw this rhetoric online, the less I could figure out who it's for. It seems more about fostering in-group solidarity than an attempt to win in a democracy. And in a democracy, persuasion is the path to adoption.

Gross caricatures are not at all persuasive to those who are caricatured, and may only be effective on the neutral if it can capture an actionable value. More specifically, if you don't capture the correct values that are in play, you are showing yourself as an unreliable critic. You are a partisan hack repeating your tribe's talking points instead of offering a penetrating criticism.

Beliefs are rooted in values, and one reason why anyone claiming to be the moral majority or the 99% is greatly overestimating how widespread their particular values are. Yet both the moral majority movement and the Occupy Wall Street movement had values they believed in and believed were worth fighting for. To address either is to address those underlying values, however divergent they are from your own.

If you cannot see the focus on family, on love, on valuing social order, on the important of doing right morally, then the moral majority seems like a bible-thumping persecution-happy hate group. Similarly, if you can't see the commitment to justice, to rooting out corruption and greed, to caring for the basic welfare of people, then OWS seems like a bunch of self-righteous anti-capitalists who know nothing of how the world works demanding a socialist revolution.

People tend to centre their politics around beliefs that matter to them, so trying to demand a political discourse that ignores that is a disaster in a democracy. It's hard to break out of our own narratives and tribal allegiances, but doing so is how political discourse can (at least partly) transcend partisan talking points because it gets to the heart of what matters to a voter. Talking about their moral failings that you perceive in their beliefs is going to be ineffective at best, and often even counterproductive.

Thursday, 1 November 2018

Welfare as a stick for conservatives

Money is a necessity in society. It's our agreed upon standard for facilitating most transactions. This fact alone justifies the need for welfare, because without it people cannot function in our society.

Its necessity doesn't mean it's well catered for, however, with crackdowns frequent and even modest increases being politically untenable on either side of politics. I used to think that it was because they're an easy target - a group that can be demonised who have little recourse to fight back - but I think that explanation excludes the basic moral impulses in play. Rather the unfairness of getting something for nothing makes them an easy target.

In short, there is a tension between the necessity of welfare and the perceived unfairness of a welfare state.

People can, if they choose to, live their whole life without needing to work, which requires that others in the society do the so-called heavy lifting. The welfare rhetoric often focuses on abuse of the system for this reason, even if those abuses are rare and end up affecting those who aren't abusing the system.

This is why programs to restrict welfare to the deserving are part of populist politics, irrespective of whether it provides good societal outcomes. Drug testing welfare recipients is one policy that's expensive, counter-productive, yet gets popular support. After all, drugs are illegal, and welfare is meant to look after individuals. Cards that restrict purchases or even food stamps are another. They are the tacit recognition that welfare is necessary but that out shouldn't go beyond that.

The current contention over welfare in Australia currently is that the rate is so low that it's not even performing its necessary function. Again, for conservatives, this is a good thing because it means welfare shouldn't be relied upon, so it should only be used as a last resort. Combine this with the complaint that welfare recipients find ways to get on higher payments (such as disability pensions, which again get repeated crackdowns) or that they are supplementing their income without declaring (see: robodebt) and we've got a punitive system that makes it harder for those on welfare to survive.

Yet all these measures don't address some of the problems associated with unemployment. People in vulnerable jobs can be exploited. Long-term unemployed have weakened job prospects. There can never be full employment, and many who work now are underemployed. No amount of sticks within the welfare system are going to change that.

Instead, what is needed are practical steps to overcoming barriers for entry. There needs to be better support to get people into work, from better training, to employer incentives. These should be driven by practical results.

At the same time, we really need to change how we view welfare from a handout to the ability to participate in society. This would be more in line with the role welfare plays in a society, allowing for economic activity. Money given to welfare tends to go back into the economy, so the money isn't being lost, but encouraging economic engagement.

So when the the rate jobseekers get remains stagnant while the cost of living goes up, the outcome will be pushing more people into deeper poverty. The stick methods may be a deterrent effect for people in crappy jobs not to quit and live off welfare, but it's not going to get many people off welfare without other changes that make it easier to work. The necessary function of welfare needs to be depoliticised because of how easy it is to perceive it as a straightforward unfairness problem.

Thursday, 11 October 2018

Morality is sanctioned discrimination

With the question of religious freedom once again popping up, we get reminded that what people most want is the ability to discriminate against others.
In this case, religious schools want to be be exempt from anti-discrimination legislation in order to keep the school's environment within their set moral boundaries.
Similarly sitting the "I can't believe it's not a plebiscite" postal survey on gay marriage, a woman was fired for her "immoral" posting on Facebook against the proposition.
Or take the case of Louis C.K. His career definitely took a hit from the emergence of his masturbatory habits, but him performing again at all has some #MeToo advocates outraged. His punishment is deemed insufficient in that he's gone forever.
And even safe zones around abortion clinics draw this same ire as it prevents the moral crusaders from directly confronting the sinners using the service.
I could go all day with examples, and those examples would be from all across the political spectrum. But the point with the examples is to illustrate how morality is targeted at individuals and groups seen to break it.

Tolerance under "normal" conditions

A pluralistic society survives by allowing a personal moral compass - at least to the extent that is allowable by law. Our society can accommodate both those who choose to hunt animals and those who think it's immoral to do so. Each may teeth to convince the other of its validity, but there's no need to solve the problem via societal enforcement.
That's not to say there's no tension or coercion. Moral issues ignite our passions, after all, and invoke strong outrage. Impassioned pleas and organised protests are a healthy part of democracy.
Arguments are made in the public sphere in a variety of ways, and over time values can and do change. A majority of people in Australia choose to vote for gay marriage despite a majority seeing homosexuality as immoral less than a generation ago.
The key factor to my mind is tolerance - that we have learnt that our personal convictions most of the time are not necessarily what others hold it even ought to hold. This is not the same as relativism, though may be described as a pragmatic relativism. Christians and Muslims have truth as they see it, and they are allowed to practice those truths, insofar as they don't affect our ability to do the same. Likewise for vegans and hunters, capitalists and communists, etc.
We can argue passionately for our against these positions without the need to dictate how anyone lives within these bounds. This holds even when we vehemently disagree.

Localised sanctioned discrimination

The pluralism generally succeeds when the moral impulses are confined to limited areas where they are sanctioned. A church is a straight-forward example of this, as is a group of vegans. The organising principles of the group allow the group to police the behaviours of their own members irrespective of what those in the wider society believe.
When these sanctions aren't reflected in the wider society, there is a tension whenever these individuals deal with outsiders. The boundary of where discrimination is sanctioned can see seen where public services are provided, such as in businesses, or in schools.
When local groups create a bubble of like-minded individuals, the wider community can be seen as downright immoral for failing to grasp those moral truths. This raises the legitimate concern that outsiders are dehumanised, and that there is the threat of exertion of power. One strategy is playing the political game (and why abortion is a perennial issue), but others include shaming, ostracism, and even taking the law into their own hands.
The ideological bindings of the group shape the individual. There are few true lone wolves, but those who attack abortion clinic doctors, homosexuals, GM crops, politicians, civilian populations, etc. all share a common morality with a local group that holds them as moral and the outside society as dangerously immoral in need of rectification.

The rule of law as a proxy to justice

Law is the ultimate standard in any given society. While psychologically we may feel morality transcends law (we are all familiar with the notion of an unjust law), we know that the law is the arbiter of disputes.
Movements like #MeToo exist because of the failure of law to sufficiently address systemic problems. Conversely laws like anti-discrimination legislation exist because of a need to address systemic injustice in a society.
The law needs to be seen by enough of the population as being fair. Not perfect - no set of rules can be perfect, let alone satisfy the myriad of different moral beliefs - but good enough that major problems will be addressed so that we don't need to settle them ourselves. If enough see the law as insufficient or capricious, we get mob justice. And while mob justice might be satisfying when it comes to your beliefs (e.g. taking down serial sex offenders), it can be an outrage when it goes the other way (e.g. gay bashing).
The reason we have due process, innocent until proven guilty, tolerance, etc. is that the other way has been tried and it leads to more barbaric societies. It's not always satisfying to think that some can get away with immoral behaviour, but the alternative is far worse.

Monday, 1 October 2018

Happy Labour Day!

It's always good to have a day off work, and public holidays are a great way to enshrine the balance between life and work into law. Labour Day is unique along public holidays in that it celebrates this victory for the rights of workers.

Yet it's another day off.

We don't really celebrate labour day here, not in the sense that we celebrate Anzac Day or Christmas. There's no reminder of what importance the day has, nor what it was like before for workers.

Yet it's another day off.

What was fought for and won by the labour movement is more important than ever at a time when wages are stagnant and working conditions are gradually being eroded in the name of efficiency (i.e. shareholder profits). We have a proven way to give better working conditions and help share the success of the economy among the people.

Unions should be using this as an opportunity to show their relevance, especially at a time when they are only ever in the media when there's corruption or strikes. Without collective bargaining, the forces of supply and demand fix wages. Unskilled or low-skilled work is vulnerable to tougher conditions, lower pay, and exploitation.

Yet it's another day off.

We need more attention given to why it is we have this day off because without that attention there's too much power for those who can gradually erode the gains made by the labour movement. We are seeing the effects of that already, and as technology and globalisation continue to push forward, we will see greater effects.

It's no wonder MAGA was a thing, or Brexit was a thing, or that far-right national parties around the world are taking more and more of the protest vote of vulnerable workers feeling betrayed and marginalised by a political system that seems to serve the wealthy. It's no wonder many young people see communism as a solution despite every implementation of communism being a dismal failure that made workers worse off than a market-driven economy.

Yet it's another day off.

Every company wants to maximise its profits, and that means trying to get the most out of the workers for the least amount of money. The human capital - our wellbeing and our lives above and beyond work - doesn't factor into it. That's our responsibility, and we can only get that as a greater society reflecting on itself.

Labour Day is important because it's a reminder of how everyone can be made better off by collective action, and that we as a society ought to be having the conversation of how we want to live. It's a reminder that conditions can improve and that we aren't fully beholden to the relentless pursuit of profit.

It's another day off, and that's worth celebrating.

Tuesday, 22 March 2016

Terrorism As A Theological Statement

What's important to remember about any religiously-motivated act of terrorism is that the act itself is a theological statement. Any such act must be countered swiftly and vehemently with the denial of the truth of their interpretation of the doctrine, such that the argument is put in its place once and for all. And the fact that it hasn't seemed to get through is all the more reason to repeat it loudly and often - such is the role of the layman in theological disputes.

And if that fails, there's always politics to fall back on, as true theology is never political in nature...

Sunday, 6 March 2016

The Parable of the Atom Seeker

A young student grows up in a society that holds the belief where she, like everything else, is made up of tiny unseen particles called atoms. So after learning something about the methodologies of science, she decides to understand what the science is behind the atom.

What strikes her at first is how the explanations for the atom didn't fit at all into the scientific method, but relied heavily on everyday experience. Furthermore, no modern physicists have witnessed such experiences, but rely solely on the accounts of early physicists. Some physicists claimed to have experiences that tangentially supported the experiences of the original physicists, but none of them could produce any evidence remotely like that which holds for other theories.

Upon further investigation, she realises that physicists disagree among themselves as to which experiences count as evidence of the atom. Some physicists argue that the experiences are interpreted too literally, while others hold to as literal a reading as possible. Some argue that the experiences can only be understood in light of arcane mystic writings and ancient mythic tales, and there is disagreement among those physicists as to the process this takes.

The quality of evidence is further called into question when other physical theories adequately account for the evidence for atoms without needing to posit atomic theory. She finds physicists will admit this in parts, but again there is disagreement between physicists over which scientific phenomena explain away the need for atoms in any given case. Some physicists spoke of the atom in metaphor, some shrouded knowledge of atoms in mystery, and some asserted that certain experiences of atoms were brute facts.

But not all physicists even agreed that evidence was important. Some physicists argued from first principles alone, invoking philosophical arguments that spoke of the atom's necessity in some respect. There were multiple of these arguments, though physicists disagreed among themselves as to the validity and significance of various arguments. Entire classes of arguments were championed by some physicists, while others favoured a different kind of arguments. She found the arguments for the most part lacking in any detail, and where there was detail it contradicted other established science. There was just no way to reconcile the arguments with the claims made about atoms.

She found some physicists who disagreed with both the arguments and the evidential approach. Some argued for the beauty of the idea as proof of the reality of atoms. Other physicists argued that atoms fit with our emotional needs. Some argued that the atoms were needed to keep social order. Some argued that their emotional response to the theory is its proof. Finally, some physicists admitted that a belief in atoms is a matter of faith, which a few embracing the idea of atoms precisely because they are an absurd concept.

The only constant she found in the exercise was the belief itself. Physicists couldn't decide among themselves what the implications were, let alone any detail that could be subject to the same scrutiny that other physical theories have. What follows is that the consensus among physicists is an artificial one, with no two physicist sharing quite the same view of what an atom is or how we know about it. And, finally, the reasons and evidence given in favour of atomic theory were unlike the various successful epistemologies that she had learnt about. At that point, there was nothing to do for the idea of atoms than to just walk away until such time the concept became more scientific... though she doubts that would ever be the case.


The question "does God exist?" has been the focus of more than enough academic inquiry that the inquiry itself deserves to be taken seriously. In any given field, outsiders looking in are looking at the promise of a discipline to be able to provide satisfactory answers on the questions it purports to cover. This isn't always easy, as academic discourse tends to become self-sustaining making it harder for outsiders to be able to make sense of it. So some latitude must be given for outsiders simply not to "get it" when it comes to the validity of the questions and the approach to answers the discipline offers.

Two things to recognise are that a) no human endeavour is truly in isolation, and b) there are a lot of ways to spend a lot of time asking wrong questions. Astrology and alchemy good examples of both. The methods of astrologers and alchemists throughout the ages have overlap with the methods used in science and philosophy. And both astrology and alchemy are nonsense notions that had a lot of ink spilled over a long time by some very smart and learned people. Very few of us are astrologers today, and none are alchemists, yet as outsiders we feel sufficiently qualified to write off both intellectual disciplines as failed truth-telling endeavours about the universe. It could have turned out both were true. It turned out neither were.

What I tried to do in the parable above was highlight my own experiences trying to understand the question of God as believers see it, including what philosophers and theologians have said about the question. I grant the possibility that there could be a theologian out there who has a legitimate case for God's existence, but I don't see the worth of exploring the subject in any great detail. Despite the towering intellects and sheer amount of manpower thrown at the problem, there doesn't seem to be the same conversation among learned believers about what God is and does - let alone a case made with the successful epistemologies we have developed. This stands out in contrast to the actual atomic theory - or any other scientific theory - where the scientists have general agreement as to what theories are and the state of the evidence, even if they sometimes disagree on detail.

Wednesday, 15 April 2015

The Cult of Health

A few days ago, someone in my Facebook feed shared an article about how psychiatrists want to classify an obsession with health as a mental illness. The impropriety! How could it possibly be that wanting to be healthy be a disorder?!

I don't know if the article was correct, and I certainly don't know the details of psychiatric diagnoses, or what should be a disorder or not. I'm not a psychiatrist. But the article did get me thinking about a more general concern I have - that the fixation on health isn't so much about actually being healthy.

Before I go into this, I need to take a few steps back.

A number of years back, I was browsing the health section in a book store. There were plenty of books to choose from, but almost all of them were complete crap. I left the the book store with two thoughts: people want to be healthy, and there's plenty of misinformation out there for anyone wanting to make that choice. For a society that demonises being fat, glorifies being fit and thin, what we've got is an industry dedicated to making money from it.

Fast forward a little. A couple of years ago, I joined a gym in a somewhat futile effort to get in shape. One day, as I was trying to work my triceps, I looked up at the TV. There was an ad for some equipment that promised all the results without any of the effort. Here I am in agony making barely any inroads, yet there was a machine promising me everything I wanted without needing to engage in this masochistic endeavour. Naturally I'm dubious, so I kept my gym membership and did not get suckered in by the infomercial, but again there was that parasitism on the desire for being fit. (Ignoring, for a moment, the false promise that is a gym membership.)

About 18 months into the gym membership, and it was going reasonably well. I was losing weight, though not as much as I liked, and I was getting fitter. Then two things happened: I injured myself, meaning I had to cut back, and I took on some extra responsibility at work, which meant I was working longer hours and eating a lot of pizza (provided by the company). In a month, I had regained over half of the 11kg I had lost over the previous 18 months. There had to be a better way.

First, I read The Healthy Programmer - a book I had bought during a sale, but it sat on my virtual shelf for months. I read it in 4 days, and was eager to take my new-found knowledge and put it into action. Second, my mother told me about a website called MyFitnessPal, which I could use for tracking my food and exercise - something I took to quite obsessively. And between the diet and exercise, I've had really good results. I'm now normal weight for the first time in my adult life, and I recently beat the 10km mark in a run.

So hopefully I've established that I do have an interest in health, in being healthy, and in leading a healthy lifestyle. I'm not at all opposed to the idea of people wanting to be healthy, and I don't care in the slightest if that interest in health for others is something related to wanting to look sexually desirable or simply wanting to avoid the prejudices our society has against the overweight. People spend far too much effort impugning and maligning the motives of others. (Again, the impropriety!)
  1. Health foods - There's an aisle in my local supermarket dedicated to what it calls "health" foods. It's good that there's an aisle for foods that don't contain foods with allergens, it's hard to grasp how the foods in that section are any healthier than the equivalents in different aisles. Are the organic almonds really better for me nutritionally than the regular almonds sitting with the other nuts? Are bars made of sesame seeds, condensed milk and honey? They taste good, don't get me wrong, but it's hard to know where the "health" comes into it. And of course, the "health" food is opposite the wall of vitamin pills and meal replacement powders. So we have an entire section of the supermarket dedicated to foods pretending to be better for us next to pills and powder that try to mimic food. Whatever happened to a balanced diet?
  2. Health food claims - Two aisles over from the wall of pills is the wall of sugar, which incidentally is my favourite wall because it has dark chocolate. But it's also the aisle that shows how health claims permeate all our subconscious desires. Because labels like "all natural" and "99% fat free" sit proudly on packets harbouring highly process sugar melded into fun shapes. No marketer is really trying to convince us that Starburst is actually healthy, but highlights the absurdity of the practice taken to an extreme. It's comical on that packet of Starburst, but pernicious on TV dinners with the brand "Healthy Choice".
  3. Superfoods - There's no such thing. There are basic micro and macronutrients we need to survive, and the best way to do that seems to be to eat a balanced diet. But beyond that, the idea that there are particular foods that are nutritionally-overcharged and really ought to be on our plates is nothing more than marketing hype. Our species survived and thrived long before the vitamin pill aisle, and we similarly did without kale salad dusted with quinoa and chia seeds and a side of acai berries.
  4. Calories - On the flip-side to superfoods is the dreaded notion of energy. So while most of us need ~2000 of these a day to survive, foods that are high calories are demonised despite having a good nutritional profile. One article talking about the nutritional content of almonds, for example, talked about all the nutrients it had in it, then warned people off them because they are very high in calories. Again, it seems to be the superfood thinking - that there's this one magic ingredient that we should consume copious quantities of, and it would be almonds if not for its caloric content.
  5. Ethical eaters - I can appreciate vegans being so for ethical reasons, or people not wanting to eat certain foods because of industrial practices. But it amazes me how these ethical considerations just happen to line up with what they think is healthy. Just a vegan's luck that not only is eating animals cruel to the animal, it's unhealthy for us. Just as organic has extra nutritional benefits, genetically modified food is a health crisis in waiting, and those "unnatural" artificial sweeteners are already a health crisis. It's great that there's a direct correlation between ethical eating and healthy eating...
  6. Diets - Inevitably I'm asked what kind of diet I'm on. I answer "none". After being looked at sceptically, I elaborate "I'm on the not overeating diet". After growing up in a world where fat was the enemy, now it's carbohydrates that are the enemy. We now should quit sugar, live like our paleo ancestors (with our modern foods), take two days a week for radical reduction in calories, or even kick-start our metabolism with coffee filled with butter and coconut oil! And when those techniques don't do anything to help with the obesity crisis, you can be sure there's going to be some new techniques complete with success testimonials just around the corner. Again, whatever happened to a balanced diet?
  7. Willpower and choice - Everywhere in the West seems to be in an obesity crisis right now. So while more adults all around the world are becoming overweight, the issue keeps coming down to choice. That is, if you are fat, then you chose to be fat. If you try to lose weight and fail, it's because you didn't have the willpower for it. In other words, you are the disgusting blob you are because you make bad choices and don't apply willpower properly. It strikes me as a post hoc justification for victim-blaming, and that's highlighted by how much this argument is used by junk food companies to oppose regulation, but it's prevalent nonetheless.
  8. Motivation-in-a-box - The internalisation of the willpower argument is the idea that a particular product is going to be the thing that finally motivates you into becoming healthy. Right now, it's activity trackers. A few years ago, it was Wii Fit and Dance Dance Revolution. For as long as I can remember, there's always been some product that plays to our recognition of our inactivity. Even at the gym, I see infomercials on the TV for products that will tone our body without the slightest strain.
  9. The shortcut - Since the dawn of our species, we've taken the effort to make us look better than we actually are. We want to give the impression of health, youth, and vitality. The beauty industry is the logical, albeit absurd, consequence of this fundamental drive. And, thankfully, for those who recognise that there's no such thing as a product that will get them the look they desire, there's a product that will give the illusion. Body-shaping clothes sitting atop of skin full of fake tan and anti-wrinkle cream, you can appear healthy to the ouside world.
  10. Purity - Perhaps the worst aspect of health as a commodity is the expectation that health should be the aspect of our being our actions revolve around. Why should it be that drinking a glass of red wine for its supposed health benefits is acceptable, while drinking a glass of red wine for the sheer pleasure not? This idea that we have to be obsessed with our health (and by extension, everyone else's) is something that's just assumed by the "my body is my temple" crowd. The flip-side of this language is the impurity of failing to live up to the same aspirations, thereby condemning the failure as having morally failed.
What's questionable to me is whether any of this is doing us any good. Do any of the products in the store that have health claims make for part of being healthy? Does the consumption of superfoods and avoidance of calories? Do any diets, ethical or otherwise, work? Does making it a matter of willpower? Or is the focus on the appearance of health creating the market for products that mimic the look? And are we just becoming self-righteous in the condemnation of others for the crime of not living to our ideals?

We can frame obesity in economic terms, as everything is these days, and deduce that it's a moral imperative from the sheer weight exerted on our medical systems - similar to how we've deduced the moral imperative to rid tobacco from the world. But while smoking has declined, decades of focus on the "obesity epidemic" has seen obesity soar, as if somehow obese people haven't gotten the message that it's really really really really bad to be obese.

It seems to me that the focus on health as this sole marker of societal (and therefore, human) worth needs to be vastly toned down, or at the very least addressed in the way other health crises have been addressed - by trying to root out the underlying factors. Because what we have right now is a self-aware society getting more obese doomed to failure by the memetic equivalent of snake oil. The focus on health, at least in the current environment should be considered a complete failure, because it has not led to healthy outcomes. It hasn't even led to a blueprint for health that people can at least try to follow, beyond eat less skittles and exercise more - with the purchasing of skittles thereby being a moral failing. Clearly something has gone horribly wrong!

Saturday, 28 March 2015

Game Review: Frozen Cortex

The rogue-like FTL: Faster Than Light was an uncompromisingly difficult game, where playing up to two hours at a time could be undone by one moment of chaos. So many times I ploughed through that game only to declare the universe as being intrinsically unfair as a simple mistake cost me a good hour of careful planning, only to have to start over again. The illusion is that next time I'd get it right. I'd shield the doors earlier, or make sure to stock up on extra missiles, or avoid saving the crew of a ship on fire.

The futility of the game combined with the (somewhat illusory) sense that I was in control kept me coming back. It was only when I could get through to the end of the game regularly that I finally lost interest.

Which brings me to Frozen Cortex.

Frozen Cortex is what you get when you cross American Football with Frozen Synapse - which is in turn what you get when you cross chess with guns. I really enjoyed the idea of Frozen Synapse, but I never could fully immerse myself in it (Hell is Internet multiplayer...) I haven't had that trouble with Frozen Cortex, already rocking up close to 30 hours of game time.

The funny thing is that there's really not a lot to Frozen Cortex. The entire game consists of short matches, with each player controlling 5 robots on rectangular arenas populated with various obstacles. It's simple enough to grasp, simple enough to control, and a tiny mistake can undo hours of meticulous planning. Any given match can be thrown away from incorrectly guessing what an opponent would do, and that makes knock-out mode all the more difficult.

Because the games are so short, minor mistakes have those major consequences. Screw up on your own offense, and it's virtually guaranteed to be game over. Misread your opponents and it can be similarly difficult to come back during your own. The game's annoying habit to "pause" the turn halfway through a touchdown pass can often be just rubbing it in that you didn't realise the opponent had that option open, and there's nothing to do but slam the PRIME button and hope there's still enough time to recover.

And there are many ways it can cost you. A slightly mistimed run means a key player is knocked out. Throwing to a player too close to an opponent gives them no time to act before they are tackled. Passes that get intercepted. Having your player slightly mistime an interception. Moving to the wrong side of an obstacle. And of course, all these are compounded with scoring pads littered throughout the arena. They are only worth 2 points (compared to a 7 point "touchdown"), but a good run can cross several pads at a time. One particularly bad example was a robot that could just sneak around an obstacle for an unguarded heavily-padded run to the end-zone.

It's that futility that like in FTL: Faster Than Light keeps me coming back. I didn't see that play. I'll be mindful of that next time. It's with that attitude I've been able to beat the game on season mode (and opened up interesting variations), but haven't quite gotten through a knockout comp yet. The game is cruel, uncompromising, punishing, and that's what makes it such a rewarding experience.

Monday, 15 December 2014

Slipping Back into Old Habits

I have a lot more time to think about coding issues than I have time to code. In some ways, this is quite handy as it allows me to plan through certain problems and foresee potential pitfalls of a particular solution. I think there are two key problems with this, however. First, even if I come up with a solution it's still only half the job done. Second, it gets be bogged down in coding problems that often are beyond my coding abilities. This all became apparent in the last month when I became bogged down in a particular design problem. A month later, I'm still no closer to a solution, and worse still I'm not making any progress in any other area. And instead of just coding a workaround for the time being, I became fixated on solving the problem.

(I needed compile-time polymorphism where I previously had run-time polymorphism. I read through books and websites on templating, tried rudimentary attempts at adjusting my code, but always I was trying to code up a perfect solution in my head, weighing up potential considerations and pitfalls. And at the end of it, all I have is the lament I just didn't code around it.)

What I find so disappointing is I know all this. There's nothing particularly revelatory in that I dwell on problems instead of working around them, but it is disappointing that I still haven't moved on from the problems I had when I was at university learning to code. I get too hung up on solutions that I haven't learnt how to code around it.

This game coding happens in the limited spare time I have. It's a hobby, and comes after other aspects of work and life. So maintaining motivation is always a struggle, especially in the face of seeming blockers. And from what I've come to know about the role pressure plays in inhibiting the creative process, the limited time often translates into fixating on particular solutions instead of just getting on with something else.

Given that I'm still adjusting back into C++, it's easy for me to think of failures as a lack of knowledge of the language itself. Sometimes that's apparent, and I know as I'm reading through various C++ material that I'm skimming for a particular solution context rather than internalising the language feature as a potential design tool in the future. But I think it would be a cop-out to blame my current understanding of C++ when the language is so flexible in the kinds of solutions that are permitted.

It's always, I think, going to be a question of motivation. That is, am I able to code something that's good enough for the task at hand? One thing that's problematic is that my initial scope is far too ambitious – that is, I'm trying to create a framework that could be used to make any number of 2D games. So in that respect I'm stuck trying to figure out generic solutions.

And therein lies the problem. How do I know I'm going to get to use any of the design work I've put in so far? For example, all the time I spent writing wrapper objects for SDL code, as far as I can tell, has had very little benefit so far. Indeed, the main reason I did that was to have a sort of platform agnosticism – the theory was that I could refactor out the core features of the engine to a different library without having to permeate those decisions down through game code. Yet if I'm never going to do that, then as happy as I am with some of the wrapper code I wrote, then a lot of that effort was wasted.

(Funnily enough, as I was trying to learn SDL, one thing I got frustrated with was that the tutorials were so direct in their use of the libraries. I took it as an act of clarity on account of the tutorial writers that they didn't try to muddle things up by enclosing their code in some simple patterns. But as I was coding up my input system, I wondered just what benefit I was getting out of mapping SDL structures with my own.)

This too, I think, highlights the perils of solo development. As I'm working on this project, I'm accountable to one person: myself. What I design, what I build, what my desired end-product is – all that is my decision. And since I'm starting from scratch and working completely unguided, it’s inevitable that I'm going to not only make bad decisions, but those bad decisions will lead t o a lot of wasted time. You live, you (hopefully) learn.

What I think I've learnt is something about the limitations of myself. If I have a certain disposition to coding a certain way, then it would be madness to think I can just overcome it by saying "don't". What I hoped with prototype-driven design was that I could better focus on what needs to be done, rather than what I would think might need to be done. That, now, seems like only addressing half of the equation, and what's missing are techniques for build-and-refactor so I don’t get bogged down where an elegant solution is not immediately apparent.

I know at times I need to get out of my head – I have notebooks that are filling up with ideas faster than I'm adding lines of code to the codebase. What will remain to be seen is if I can work with my own personal practices and habits. Like losing weight, if you try to do it on willpower, then you’re going to fail miserably.

Sunday, 23 November 2014

The How of A*

(For the Why of A*, go here)

Here is a basic implementation of A*. Note that this isn’t necessarily an optimal solution, but it is a working one.

For my solution, I have two classes: Node and PathfindingAStar. The two classes are tightly coupled, with Pathfinding depending on Node to have certain properties in order to work. Node itself is the bridge between the pathfinding subsystem and the wider system.

Here is Node.h:

typedef struct
{
 unsigned int x;
 unsigned int y;
}NodePos;

class Node
{
public:
 Node(unsigned int p_x, unsigned int p_y);
 ~Node();
 NodePos getPosition();
 bool isSameNode(Node* p_node);
 void setNeighbourAt(Direction p_dir, Node* p_neighbour, double p_cost = 1.0);
 Node* getNeighbourAt(Direction p_dir);
 unsigned int getMovementCost(Direction p_dir);
 std::vector getAllAvailableDirections();
 bool isOccupied();
 void setOccupied(bool p_occupied);
 void setParent(Node* p_parent);
 Node* getParent();
 double getG();
 void setG(double p_distanceTravelled);
 double getH();
 void setH(double p_heuristic);
 double getF();
 unsigned int getX();
 unsigned int getY();
private:
 std::map m_movementCost;
 NodePos m_pos;
 std::map m_neighbours;
 Node *m_parent;
 bool m_occupied;
 double m_h;
 double m_g;
};
The Node caters for two purposes. Firstly, it holds information about the world itself that are vital for Pathfinding to operate. The position of the world, the neighbours of the node, the costs, and whether the node is occupied are all created and maintained by the game code. Neighbours cannot be populated upon creation because neighbours won’t have necessarily have been created themselves. Whether the node is currently occupied will be need to be maintained by the game code.

Secondly, the node holds information relevant to the cycle of the path. m_g and m_h are used by Pathfinding for the node’s distance from the start node and to the goal node. Similarly, m_parent is used to keep track of where the navigation came from.

As far as methods in Node.cpp go, there are two methods that are worth exploring, both to do with the available directions.

void Node::setNeighbourAt(Direction p_dir, Node* p_neighbour, double p_cost)
{
 m_neighbours[p_dir] = p_neighbour;
 m_movementCost[p_dir] = p_cost;
}
std::vector Node::getAllAvailableDirections()
{
 std::vector directions;
 directions.clear();
 std::map::iterator itr;
 std::pair pair;
 for(itr = m_movementCost.begin(); itr != m_movementCost.end(); itr++)
 {
  pair = *itr;
  directions.push_back(pair.first);
 }
 return directions;
}
The Pathfinding algorithm will need to know what directions are available to move in, and how much it will “cost” to move in that direction. An alternative would be to simply have a cost associated with a node, but this way gives more flexibility to the game code. So there are two lists, one for the cost of moving in a direction, and one for the neighbour Node in that direction.

Since directions are set when neighbours are set, there’s never any need to worry about the two maps going out of sync. So either map could have been iterated over to build a list for Pathfinding to use. This returned list could just as easily have been a private member of Node, generated as part of the setting of neighbours, and perhaps could be a point of efficiency to do so in the future.
Here is the source code for PathfindingAStar.h:

#include "Node.h"

class PathfindingAStar
{
public:
    static PathfindingAStar* getInstance();
    ~PathfindingAStar();
 std::list findPath(Node* p_startNode, Node* p_goalNode);
private:
 std::list finalisePath(Node* p_currentNode); 
 PathfindingAStar();
 static PathfindingAStar *singleton;
};
Pathfinding has one public method – to find the path. The rest is just for housekeeping. There only ever needs to be one instance of the class, so the Singleton pattern is implemented. There’s nothing particularly special about the class from an OO point of view, as all of the work is done in the single method search.

std::list PathfindingAStar::findPath(Node* p_startNode, Node* p_goalNode) 
{
 std::vector m_openList; //Nodes that are active
 std::vector m_closedList; //Nodes that have been used
 //Clear the list
 m_openList.clear();
 m_closedList.clear();
 //Reset the node to parent for the current cycle
 p_startNode->setParent(0);
 //and reset all values of f, g & h
 p_startNode->setG(0.0);
 double h = (double) abs(p_goalNode->getX() - p_startNode->getX());
 h += (double) abs(p_goalNode->getY() - p_startNode->getY());
 p_startNode->setH(h);
 m_openList.push_back(p_startNode);

 while (!m_openList.empty()) //If there are still nodes to explore
 {
  //Get the node with the smallest f value
  Node* currentNode = m_openList.front();
  //Remove node from the open list
  std::vector::iterator itr = m_openList.begin();
  m_openList.erase(itr);


  if (currentNode->isSameNode(p_goalNode)) 
  {
   std::list goalList = finalisePath(currentNode);
   //return out of the program
   return goalList;
  }

  std::vector neighbours = currentNode->getAllAvailableDirections();

  bool isFound;

  for (unsigned int i = 0; i < neighbours.size(); i++) {
   isFound = false;
   Node *n = currentNode->getNeighbourAt(neighbours[i]);
   if (n->isOccupied()) {
    continue;
   }
   //Make sure node isn't in open list
   for (unsigned int j = 0; j < m_openList.size(); j++) {
    Node *n2 = m_openList.at(j);
    if (n2 == n) 
    {
     double g = currentNode->getG() + currentNode->getMovementCost(neighbours[i]);
     if (g < n2->getG()) 
     {
      std::vector::iterator itr2 = m_openList.begin();
      m_openList.erase(itr2 + j);
      for (; itr2 != m_openList.end(); itr2++) 
      {
       Node* n2 = *itr2;
       if (n->getF() <= n2->getF()) 
       {
        break;
       }
      }
      m_openList.insert(itr2, n);

      n2->setG(g);
      n2->setParent(currentNode);
     }
     isFound = true;
     break;
    }
   }
   if (isFound)
    continue;
   for (unsigned int j = 0; j < m_closedList.size(); j++) 
   {
    Node *n2 = m_closedList.at(j);
    if (n2 == n) 
    {
     isFound = true;
     break;
    }
   }
   if (isFound)
    continue;

   n->setParent(currentNode);
   //work out g
   n->setG(currentNode->getG() + currentNode->getMovementCost(neighbours[i]));
   //work out h
   h = (double) abs(p_goalNode->getX() - n->getX());
   h += (double) abs(p_goalNode->getY() - n->getY());
   n->setH(h);

   //add to open list in order
   std::vector::iterator itr2 = m_openList.begin();
   for (; itr2 != m_openList.end(); itr2++) 
   {
    Node* n2 = *itr2;
    if (n->getF() <= n2->getF()) 
    {
     break;
    }
   }
   m_openList.insert(itr2, n);
  }

  m_closedList.push_back(currentNode);
 }
 std::list dummylist;
 return dummylist;
}
The first few lines of code are setting up the world. Since the start node has no parent, it’s set as 0. The start node is then pushed onto the frontier list. The reason there are two lists is so that once a node is fully explored, it never needs to be explored again. It subsequently shifts from the frontier list to the closed list.

The main algorithm is a while loop, which will run until either the goal Node is found, or the frontier list is exhausted. The Node at the front of the frontier list (sorted by f) is checked for whether it is in-fact the goal Node, in which case the algorithm constructs the list of Nodes and returns it. Otherwise, the Node goes through each available direction on the current Node, removes it from the frontier list, and adds it to the closed list.

For each neighbour Node, it needs to be checked whether it’s already a) on the frontier, or b) on the closed list. In either of these cases, the Node needs no further exploration except in one special case of a Node on the frontier. If the distance travelled to the Node in this iteration is less than the distance travelled to the Node, then the Node and frontier list need to be updated. i.e. we have found a shorter path to the same position. If the neighbour Node is not yet explored, its g and h are calculated (in this case, h is calculated using the Manhattan heuristic), its parent is set as the current Node, then it is put onto the frontier list sorted by f. Finally, if the frontier list is exhausted, this means there was no path from the start Node to the goal Node, so an empty list is created and returned. Thus the empty() function on list acts as the indicator of whether there was path successfully generated.

The code for building the path list is as follows:

std::list PathfindingAStar::finalisePath(Node* p_currentNode) 
{
 std::list goalList;
 while (p_currentNode != NULL) 
 {
  goalList.push_front(p_currentNode);
  p_currentNode = p_currentNode->getParent();
 }
 //don't need the first node
 goalList.pop_front();
 return goalList;
}
The code is fairly straight forward. Since each Node knows its parent, it’s simply a matter of traversing back to the first Node where the parent was set as NULL.
And there it is – a basic implementation of the A* algorithm. It’s by no means the most efficient possible version of the algorithm, nor does it do any of the C++ things one really ought to do when using the language. The important thing is that it works, and it’s reasonably clear how.

Saturday, 22 November 2014

The Why of A*

For pathfinding, breadth-first search (BFS) is almost always preferable to depth-first search (DFS). The general problem of a breadth-first search is that it is resource-intensive. Depth-first follows a single path that grows as the path is explored. Breadth-first explores multiple paths at once, with the amount of paths growing exponentially.

Both DFS and BFS are brute force attempts at finding a path, but they express themselves in different ways. A depth-first will in all likelihood find a path that won’t directly go from A to B, but follow the rules which govern how to choose the next position to explore. A breadth-first search might find a more direct path from A to B, but the result will take much more time to compute – something that’s unforgivable in a game which requires immediate feedback.

There are ways of directing a BFS so that it doesn’t take as much computational power. A* is the best of these, but it’s worth at least glancing over why this is the case. A* works on the following equation:
f = g + h
Where g is the total distance travelled, h is the estimated distance left to travel, and the smallest f is chosen next. An undirected BFS would be the equivalent of ignoring h altogether, so it’s worth exploring the role of h.

One strategy with a BFS is to just take into account the shortest distance to the goal. So whatever node is “closest” (and there are various strategies for working this out) should be the next node to search. This strategy works well if there are no obstacles directly between the start node and the goal node, as the closest node will always bring the path closer to the goal. The strategy fails, however, if there are obstacles, because the path will inevitably explore those dead ends like a DFS would.

A* gets around this problem by also taking into account just how far the path has travelled. In other words, what makes a path the most fruitful to explore is the estimated total of the journey. A path that goes down a dead end will have an overall larger journey than a path that took a deviation before the dead end path.

With the A* algorithm, the final output would be a path that always has the least number of moves between A and B calculated with exploring as little of the search tree as necessary. The algorithm, like with any algorithm, has its limitations, but ought to be used where the start and end goals are known and need to be computed.

Monday, 3 November 2014

Phase 3b: Flip Squares

With Snake, I could contain the notion of a Level within the screen itself, starting at (0,0) for both the top left coordinate and the offset for rendering the game objects. Going forward, this was not sustainable. Furthermore, I had no way of capturing or processing mouse input on the screen – limiting the engine in effect to whatever could be done solely with keyboard. Finally, there was no way of putting text onto the screen.

Since Snake wasn't really suited to these tasks, I decided to make a new prototype. I remembered an old puzzle from Black & White whereby you had to make a set of randomised trees all the same type. The rule was fairly simple – you had a 3x3 set of trees. If you pulled on a tree, it changed the tree and changed every neighbour of the tree. So there were patterns of 3, 4, or 5 changing depending on the location. Simple enough to code such that the game code itself wouldn't take up much of the development, yet would be useful to get all three aspects missing from the system coded up.

The Camera was a crucial class to get right, and if I was being honest, working out the logic for it has been something that I've been trying to get right in my head for months. Indeed, it was the bane of phase 1 and phase 2. With Level finally sorted out, it was more a matter of getting Camera right. The Level introduced the idea of WorldCoordinate – a simple structure that holds two doubles. So Camera could have a position relative to the Level by holding a world coordinate and the tile dimensions.

Camera needed to do a number of other things. For one, Camera had to be accessible by every AnimationObject so that the destination rect could be relative to the Camera rather than the level. This way textures could be updated out of sight of the game code. The other major thing was to keep track of the mouse, to keep track of where it is on screen and to be able to translate back into a WorldCoordinate for use in-game.

When designing my Input class in the abstract, I thought all I would need to do was keep track of the relative movement of the mouse. This proved to have a limited utility when running in Windowed mode – with the absolute position of the cursor sometimes moving out of the window altogether while not being able to reach certain objects in game. It’s this kind of phenomenon that has helped me understand how important prototypes are to getting the engine running right.

In order to get the prototype up and running, I avoided working out how to display a cursor, and instead used an overlay object for the squares themselves. It worked well enough, and well enough to force me to revisit the equations in the Camera class for getting the translation of WorldCoordinate right. By this stage, I had a working prototype, as seen here.

The last thing I wanted to do was to get text rendering on the screen. For the prototype, I wanted to display something simple – the number of moves in trying to solve the puzzle. With TextureObject (my wrapper of SDL_Texture), the textures were meant to live for the lifetime of the application, so it could be managed by TextureManager. With text, its creation and destruction needed to be with regards to its use. Obviously I don’t want this to be manual, so when I created TextObject (the text equivalent of AnimationObject) I handled the deletion of text objects in code.

It turned out getting text on screen was mostly straightforward. The only problem was the difference between relative and absolute positioning of text. Obviously I would want the option of having both, but I haven’t come up with a good solution yet. For now I’ve created two objects: TextObject and TextGameObject with game objects being camera-relative while TextObject has an absolute position. When I get to working on the HUD, I might encounter this problem with AnimationObject, so there’s a refactor issue.

In the absence of another prototype idea, I refactored the game itself with an algorithm to brute-force a solution. Taking a purely random approach to the game meant that occasionally really easy puzzles would be thrown up (I coded to stop 0-step puzzles). So I wrote an algorithm that would brute-force a solution - to work out just what are the moves needed to solve the puzzle from any given position. This didn't advance the engine in any way, but was a good coding exercise nonetheless.

Saturday, 1 November 2014

Internet Debating: The Complete Idiot Hypothesis

If you argue a point and someone doesn't get it, then it must be asserted that the reason they didn't get it is they are a complete idiot.

Friday, 31 October 2014

Phase 3a: Snake Enhanced

The last couple of weeks has seen a continuation of the approach I took developing Snake. Since there is still more to be done getting the Engine to a functional state, enhancing the existing game seemed like the quickest way of those enhancements in.

The two major enhancements I had for the system were to get animation working, and to get level as its own concept. For the first cut of snake, these were two areas where there was a lot of manual code.

The need for an AnimationObject arose out of the unsuitability of RenderObject and TextureObject to be complete for use as the game object. Each game object was loading its correct texture, then using that to populate the RenderObject associated with rendering. That was fine except for the snake itself, which changed whether the body part was a head, body part, or tail. So the snake had to keep track of both the texture and the render object so it could manually shift the frame corresponding to the right body part.

AnimationObject was my solution. By taking the texture, there was no need for the game object to have continual reference to the texture object (or even retrieve it) in order to change frames. Any animation in the original version was simply the illusion of movement. With AnimationObject, I’d have actual animation at the speed I desired simply by creating the object. It also meant that if the object moved, I could update the game coordinates without having to write the code to manually update the destination rect on the RenderObject.

Instead of trying to put absolutely every scenario into the single AnimationObject, I instead made use of inheritance and polymorphism to get specific functions. I made a RunOnceAnimationObject and a LoopAnimationObject – both of which override the render() method to allow for timer-based animation. The base AnimationObject would be for pointing to a single frame of a texture, while RunOnce would go from start to finish and hold on the final frame, and Loop would loop indefinitely.

The satisfying thing about the AnimationObject classes was that it took no more than an evening to write the code and refactor the game code. The whole process was seamless, and worked with very little effort. Building the level code was more effort, and one of those points where I had to remind myself to design for the game rather than design for some abstract ideal of what I wanted to achieve. The problem is this: Level ideally loads from an XML file (in my case, I wanted those XML files generated by Tiled!), and what is in the XML file on any given tile conforms to a game object.

To solve this problem, I implemented the abstract factory pattern. Level takes a TileFactory (an abstract type) that has a generateTile(int id) method which returns a Tile pointer (also an abstract). Level populates a Vector, where tiles can be retrieved with an x and y coordinate. So what kinds of tiles are produced depends on the concrete TileFactory, and all the SnakeGameObjects that could be Tile had to do was inherit from Tile. This approach does have a limitation, using Level like this means accessing any Tile will only have the methods that exist on the Tile contract. For now, I put the method bool isCollision() onto Tile to allow for collision detection within the game object. In the future, enhancing Tile to cater for all iterations of what Level could do might prove to be unwieldy. For now, the class does enough to work.

Here’s the enhanced game.

It might not look like much, but there are those enhancements that went on in the backing code – animation was handled automatically, and the world itself was controlled by an XML generated by the Tiled! application. In the spirit of prototype-driven design, I feel I was able to accomplish a number of vital tasks in a short period of time. Of course, there is still more to go, but that requires a different kind of prototype.

Saturday, 25 October 2014

Jonathan Blow on Programming Practices

Since the game programming is a hobby of mine – something I do in my spare time – I tend to have a lot more time to think about what I do than to actually do it. I have filled many pages of notebooks and have made many documents with notes ranging from design material, to specific solutions, and everything in between.

So it’s with that in mind that the following video from the Braid developer Jonathan Blow intrigued me, for it advocates effectively the opposite approach to what I've been taking.



One immediate thing that occurs to me is that I’m no Jonathan Blow. Just being able to sit down and write without inhibitions, I'm fairly certain, would get me a mess that doesn't really do much of anything.

The second thing that occurs to me is that it's taken me a year to get half an engine. So the approach I'm taking now is realistically-speaking unsustainable – at least for the goal I'm trying to work towards.

My hope by this stage of my career is that I've absorbed enough of the good design patterns such that the hard work is done for me. What I seemed to have absorbed, however, is knowledge of the existence of patterns minus the knowledge of their application on low-level functions. Since I've had no professional game development experience, this should come as no surprise – why would I have needed to understand patterns outside of their application in Java EE?

Same goes for my stagnated C++ skills, whereby I'm digging through Scott Meyer’s Effective C++ in the hope I can mitigate a lot of the 'gotchas' on areas where Java manages it for you (such as dealing with pointers). My intuitive grasp of class design and function design is rooted in a Java mindset, and C++ is just far enough away from it that my coding style has to be more deliberate. The lack of private functions, especially, is testing my coding sensibilities.

Blow's list of do’s and don'ts seems on the face of it a good one, and especially pertinent if I replace his use of optimisation with "open design" to reflect the kind of design considerations I'm currently working with. I've spent so much time trying to get things just right – of trying to come up with a perfect class order that will enable extensible code. It’s great when it works, but the cost in time and effort has been considerable for that. As Blow pointed out, this kind of approach won’t pay off in the long term.

The other stand-out idea in his talk was the idea of writing specific code over general code. I know I'm especially guilty of doing this. Some of the time there is good reason to write general code, and to my mind it’s especially important to get it right in the core. But it’s something to reflect on that there is good that is fit for purposes without being so flexible it fits every purpose I desire. My Input class comes to mind, and part of that was I think a rationalisation of adding an abstraction atop of SDL's abstraction of the interface. I got what I wanted, but it’s easy to forget the cost of that.

One final lesson that was worth highlighting was the idea of writing code in a single block. This goes dead against the coding principles outline in Robert C. Martin’s Clean Code. In one sense, I can understand this in C++ because of how annoying it is to write function headers for private functions. But Blow’s suggestion about encapsulation is a point well made.

Friday, 24 October 2014

Prototype-Driven Design

This is designed to be a normative approach based off the three [1, 2, 3] development approaches I wrote about earlier. Namely, how to take the use cases of a simple game to develop and refactor an extensible and versatile underlying code. This is a note to myself for next time.

Bootstrapping the framework
A game is a loop, and the loop has an exit condition. Hitting the exit condition exits the game. To be interesting, while the game is looping, the game has to do stuff. All that should be met with “duh”. What this means is that we have to organise an order of things to do in the loop. You need to create a window, load images, display, capture input, change game code, etc. Organising this basic pattern needs to come first..

The first thing is to get the libraries loading successfully. This may take more time than the task sounds like it would, and doing something slightly unusual (for example, choosing to develop on Windows using MinGW) might not have a single point of clear instructions. Don’t fret if this takes longer, it’s important to get this right.

There are a number of discrete systems that in concert make up a game. Many of these are “core”, and will be used every time in very nearly the same way. As such, each of these systems can be given a basic function (such as render updating the screen each frame), and each function placed as part of a list of functions that are always called. In mine, I called this the Engine façade, where the update() loop took care of everything the engine needed to do with a single call from the game loop.

At this stage, it’s okay to use scenario-based development. “A screen should appear on start-up”, “a button press should quit the game”, etc. Indeed, there’s little more one can do at this stage. The important point is not to overdo this, however, because you a) cannot account for every scenario, and b) what you think will be right scenarios may not be the case. Overdo it at this stage, and prepare to refactor.

The prototype approach
Take a simple game like Snake. It’s a fairly simple game so it won’t take much to work out how to translate what happens on screen into code. It’s also a fairly-well defined game, so there’s not a lot of effort in setting the win / loss conditions and how that translates to a loop. It also tests out what you need in a game – to capture input, to update the game world accordingly, to trigger off sounds, play music, and to update the screen.

The general approach goes like this.
  1. Try to build the game artefact to do what you want it to do.
  2. If the engine can’t support the functionality, add the functionality.
  3. If the engine only partially supports the functionality, enhance what’s there.
  4. If the engine encourages a lot of writing the same code multiple times, refactor.

Such a system will also feed back into itself, where later development will override earlier development. The important point is not to get hung up on a decision made earlier if a better decision comes along, after a short while you should have a working game and hence a platform to immediately test out how well the system works.

Like the bootstrap framework, this might take some time to set up. There’s a lot to do going from nothing at all to even a simple working game (without taking every possible shortcut). But what it allows for is very quick refactoring and enhancement. Once you have a fully functioning product, it should be a matter of hours or even minutes to enhance it for the better.

The development phase is similar to Test-Driven Design, though in this case a piece of game functionality is the unit test. You write game code to do something, but it won’t work until you then write the engine enhancement that will make it work.

The allure of design
The prototype approach requires a continual awareness of the allure of design. When making a component, it’s easy to come up with potential uses for that component – all of which takes time to design, develop, and debug. Furthermore, enhancing the system in such a way doesn't mean the work will actually achieve anything. The prototype-driven design in this sense is a way of keeping the developer honest and focused, and not wasting time on the mere potentiality of a function.

This is not a call, however, for the abandonment of design. It’s a call to prevent overdesign, to limit areas where splurges in design can lose sight of the bigger picture. The idea of a chaotic mess of code is what you end up with even with the best of intentions, so there’s no need to add to it if it can be avoided. What I am talking about here is a different kind of chaotic mess – a bloat of code of which only some applies to the end result.

The allure of design is part of the creativity that enables development in the first place, and to some extent it’s necessary for consideration for any potential solution. Otherwise we hit the other extreme – a constant rewriting of the same basic code whenever a new requirement exists. It’s a balancing act, yes, and how the prototype-driven design approach works should be to limit the potential for overdesign.

I suppose the difference I'm trying to articulate is the difference between extensible and bulletproof.

Scope-creep is a good indication that you are moving away from the PD-D and being drawn back into the allure of design. If a problem is getting unwieldy, it’s worth reminding yourself of what the component was meant to achieve in the first place. If it wasn't something with a game-related end product, then that should be a strong indication of overdesign and grounds to stop.

A guideline
The approach sketch above isn't much of a methodology, but a guideline to stay focused. It’s a way to catch that intuitive aesthetic about how code ought to be done and give it a focal point. Furthermore, it’s a guideline that as far as I can tell applies to one person: me. Or to put it another way, this is a sketch of an approach that keeps my distracted-self focused on why I'm doing this in the first place. The desire to “get it right” is coming at the expense of “getting it done”, and this approach seems promising as a way of somewhat alleviating that.