segunda-feira, dezembro 11, 2017

Such a Beautiful Hindquarter of Pork: "Emma" by Jane Austen



I wonder if a variation on the Unreliable Narrator is permissible here? Jane Austen's Emma, while narrated solely by the author herself, is told exclusively from the title character's point of view (chime in and correct me if there are scenes in which she doesn't take part, however minor) so that Austen becomes Emma's interpreter, and our interlocutor. It's a very deliberate choice, because Austen then goes on deftly but in plain sight to give you every reason to question Emma's headlong conclusions, while knowing full well that you'll simply go right along with Emma anyway. Surprisingly, none of this feels tricksy or opportunistic, though of course it might had Austen not had this particular objective unwaveringly in her sights: The Unreliable Reader. If we look at the story from within Emma's world, she's a classic unreliable narrator, primarily to poor Harriet Smith. Emma's wishful and willful narratives consistently mislead Harriet, who depends entirely on Emma's versions of things. To make matters more complex, Emma really should have known better, as she admits (to her credit) when her eyes are opened. Nor is Emma the only unreliable narrator. She is misled in her turn by Frank Churchill's camouflaging accounts of his relationship to Jane Fairfax. Again, the reliability angle is enriched when Frank thinks at one point that Emma does perceive his attachment to Jane.

In fact, there is one scene in which Emma doesn't appear, one that fits into my interpretation. It's the conversation between Mrs. Weston and Mr. Knightley about whether Emma's friendship with Harriet is desirable or not. Mrs. Weston sees the matter fondly through Emma's eyes, while Mr. Knightley's cooler assessment sees the situation accurately. Mr. Knightley and Mr. John Knightley could be called reliable narrators of the story. Again significantly for my thesis, each attempts to alert Emma to her mistaken narratives. Mr. Knightley tells her realistically about Harriet's prospects and Robert Martin's virtues, and shares his suspicions about an attachment between Frank and Jane. Mr. John Knightley gives her a hint about Mr. Elton's real intentions. Of course, they don't make a dent.

Now I've got myself really thinking, and I realise . . . I forgot Miss Bates, the most persistent narrator of them all! I'd call her a reliable narrator because her stream-of-consciousness approach ends up letting us know her entire (and exhaustive) fact-base. She also tells us her certainty values.

I've read Emma countless times, but I still laugh out loud at the pork-and-Mr.-Elton scene:

“Full of thanks, and full of news, Miss Bates knew not which to give quickest. Mr. Knightley soon saw that he had lost his moment, and that not another syllable of communication could rest with him.
‘Oh! my dear sir, how are you this morning? My dear Miss Woodhouse---I come quite overpowered. Such a beautiful hind-quarter of pork! You are too bountiful! Have you heard the news? Mr. Elton is going to be married.’"

This scene goes exactly to the narrator issue, when Miss Bates nearly backs herself into the corner of naming Highbury's corporate speculation that Mr. Elton would propose to Emma:

"A Miss Hawkins.---Well, I had always rather fancied it would be some young lady hereabouts; not that I ever-----Mrs. Cole once whispered to me---but I immediately said, 'No, Mr. Elton is a most worthy young man---but'-----In short, I do not think I am particularly quick at those sort of discoveries. I do not pretend to it. What is before me, I see. At the same time, nobody could wonder if Mr. Elton should have aspired-----Miss Woodhouse let me chatter on, so good-humouredly. She knows I would not offend for the world. How does Miss Smith do?"

How different from the Mr. Knightleys, and yet Miss Bates's native honesty and good will keep her on the straight and narrow. She knows (and as importantly, reports) when she's drawing a conclusion, when her memory might be at fault, etc.

What a masterly triumph for Jane Austen, to have Miss Bates, of all people, win the Reliable Narrator Sweepstakes! LOL, indeed!

The famous Irony that Austen deployed (and refined to its utmost in Emma) is, rather than being crudely and obviously signposted, actually embedded in the means of the narrative. We are constantly seduced into Emma's solipsism because it flatters our own - we even fail to pull up the drawbridge during that famous opening sentence because we so wish to believe that a pretty, rich, single, and indulged young woman could have 'anything to vex her'. Or us. The reason the Box Hill episode is so painful - to Miss Bates, as much as to the reader (and, eventually, Emma) - is that Miss Bates is wholly without guile. It's the book's first real gathering-of-clouds warning that we are not reading this story as it needs to be read: that we are in danger of wafting away on the brio of Emma's self-satisfaction, and using it to fluff the duvet of our own. After all, Emma is gravely wrong three times over (towards Harriet, Jane Fairfax, and Miss Bates), and because of her position of influence it's in her hands to materially affect their lives. Potentially, she can ruin Harriet's prospects, cast malicious shade on Jane's reputation, and fatally disturb Miss Bates's peace. She's lucky that the damage was limited in the first two cases and that Miss Bates was capable of recovering in the third.

I see Emma as a miracle novel---a perfect comedy of manners taking place in the perfect confessional world of Highbury, and yet as serious in its moral content as Mansfield Park. I think Emma becomes a sympathetic moral character when we allow her to be a mirror for ourselves.


The book is a brilliant and unique accomplishment in literature, and is the reason it's still one of my favourite novels, even though I'm more temperamentally drawn to some others.

domingo, dezembro 10, 2017

Frazzled Frenzy SF: "The Stand - The Complete & Uncut Edition" by Stephen King



One of my favourite SF books was Stephen King's 1979 "The Stand", which I read in the full unadulterated double-doorstop version released in 1990, which was considered far to voluminous to release in 1979. This is the second time I'm re-reading it. How did it fare?

This is the sort of SF that is all too plausible, an accidental spill from a biological weapons facility releasing a plague-like virus which sweeps the planet in a matter of weeks, leaving 99% of humanity dead. King introduces a scores of protagonists, split into two camps of good and evil, the good 'uns drawn to Boulder Colorado through a shared dream of a 108 year old black woman, and the baddies under the control of supernatural drifter Randal Flagg.

King said he had been wanting to create an American Lord of the Rings, saying he:

“...just couldn't figure out how to do it. Then . . . after my wife and kids and I moved to Boulder, Colorado, I saw a 60 Minutes segment on CBW (chemical-biological warfare). I never forgot the gruesome footage of the test mice shuddering, convulsing, and dying, all in twenty seconds or less. That got me remembering a chemical spill in Utah, that killed a bunch of sheep (these were canisters on their way to some burial ground; they fell off the truck and ruptured). I remembered a news reporter saying, 'If the winds had been blowing the other way, there was Salt Lake City.' Only instead of a hobbit, my hero was a Texan named Stu Redman, and instead of a Dark Lord, my villain was a ruthless drifter and supernatural madman named Randall Flagg. The land of Mordor ('where the shadows lie,' according to Tolkien) was played by Las Vegas”

I noticed on re-reading it that the first half of the book is dark and wickedly drawn, mining the full depths of human depravity. A gang of marauding baddies rounding up any men and women they come across and forcing them into herds of sex slaves, and as it is King writing, always managing to make the premise and dialogue believable; tugging at the reaches of the readers mind in slightly disturbing ways, causing intakes of breath at the audacity of his imagination; as the, by now unfazed members in the sex slave gang giving advice to the new, offering tips on how to keep the brutes from fully ravishing them, by making sure to give effective head, a particularly transgressive flight which spurs the pages to turn in anticipation of how much farther he is going to push the envelope. And then, in the second half, this muck and mire kind of vibe, dissipates as the goodies win out and the whole tenor and underlying tow of the book fundamentally shifts into a wholly different register, suffused with an evangelical tint. The ferocity of it, which at the time I noticed but did not think on, ebbing away into the denouement of all the baddies, who King opts to get rid of by having a pyromaniac protagonist, Trash Can Man, accidentally blow them all up after towing a nuclear bomb to the Las Vegas HQ, and all the good people living happily ever after. The creative nuts and bolts of the writer's personal psychology behind this book, were made known to me after I read King's prose how-to book: On Writing, which he wrote whilst recuperating from a serious accident after being put in a coma when a juggernaut knocked him down as he was on his daily afternoon walk; the driver of which he ominously revealed in passing, had died (I think) a violent death a few years after at the hands of an unknown killer.

He said that when he began to write “The Stand”, his daily and prodigious writing practice was centred around sitting at the word processor, with a 12 or 24 slab of beer, drinking, smoking and ingesting lots of drugs, which explained the outrageous feats of his imagination in the earlier part of the book. Mentally loosened up by a cocktail from across the full spectrum, his mind in a cloud all of its own making, revved along in that particular frazzled frenzy conclusive to massive paranoia which conjures up all sorts of diabolical scenarios - King had harnessed this power which in most people would see them on the streets whacked out their minds, and put it to profitable use. However, half way through the book, at the insistence of his family, he reached the end of the road with this lifestyle, and suddenly found himself in a new head-space after drying out, and minus the previous crutches and creative aids (and personal wrecking balls) of drink and drugs, so the totally different register and massively toned down transgressive scenes in the second half of the book is explained. He said that due to this sudden shift in his day to day habit, he ended up, even by his standards, with a sprawling mass of characters, of which there were just too many to tie up into a denouement of set coherent scenes, so came up with the brainwave of just blowing them all up, and at a stroke unburdened himself of a massive workload.

It is what it is.



SF = Speculative Fiction.

sábado, dezembro 09, 2017

Pax Americana: "Double Star" by Robert A. Heinlein



Implausible and impossible to put down- like all of Heinlein's books I've read its hero is a man of action and boundless self-confidence, a wisecracking all-American cowboy figure who brushes obstacles aside, a genial dictator figure who knows that as long as he's left in charge everything will be o.k. The voice is always the same - and I can see why the new wake of science fiction writers reacted against Heinlein: Aldiss, Moorcock, Ballard, Dick. Heinlein's Pax Americana and paternalism vision of the future certainly does have fascist overtones. But he's still a great storyteller, his books filled with mind-bending concepts presumably achieved without the help of the consciousness expanding substances that inspired some of his successors.

Yes, the Bonforte character was a very macho autocrat...Who cares? Nevertheless, “The Great Lorenzo” doesn't quite conform to the macho 'tit man' narrator as Heinlein... although the authorial voice does creep through in interesting ways in his stereotyped descriptions of Lorenzo's camp-actor personality and co...Heinlein enjoyed challenging established ways of thinking, and for most of his great period of writing liberal politics was on the rise, so he took great pleasure in poking holes in political sacred figures. The conservative viewpoint is already being expressed quite vocally in SF - take a look at Baen Books for a few examples. Some might argue its a viewpoint that doesn't merit expression, but I'm not sure what it says about contemporary literature if it can't manage a political dialogue.

My grumble with it is that I didn't really think it was proper SF - which may sound odd given the presence of Martians etc., but what I mean is that at its heart, the plot is about a man masquerading as someone else, and a pretty much identical story could be told in a real world setting. What I enjoy in SF is the way it changes the rules of the world and explores the consequences of these changes. I recently read Richard Morgan's brilliant “Altered Carbon”, which was superb in the way it used its central "rule change" (that people's personalities get stored in a chip implanted into the cortex, which can then be transferred into other bodies) to drive the plot and then use that plot to show the effects of this technology on people and society.


As I say, not that rewarding as SF, but fun and certainly intriguing.


SF = Speculative Fiction.

sexta-feira, dezembro 08, 2017

Crap on Repeat: "Two Kinds of Truth" by Michael Connelly


I used to feel that I shouldn't like reading Crime Fiction so much, but then sensibly decided that a well written Crime Fiction book has as much "value" as any other book, however much the literary snobs may turn their noses up. Good writing is good writing, whether it's a spy novel or a romance, a whodunit or a family saga. When I had finished all of the wonderful Wallander books, I started looking elsewhere for Nordic detection. Helene Tursten's Inspector Irene Huss (Swedish) is wonderful as is Ake Edwardson's young, hip Inspector Winter, while Liza Marklund's newspaper reporter, Annika Bengtzon gets herself into some rivetting, nail-biting situations. Karin Fossum's Inspector Sejer (Norwegian) is great, as is Arnaldur Indridason's Inspector Erlunder (Icelandic)! These are all excellent translations (unlike the earlier Swedish thrillers by Maj Sjöwall and Per Wahlöö, whose translations leave something to be desired). When I had got through all the Wallander books I was devastated, which is how I found these other wonderful Scandinavian mystery writers and a few others, namely their American counterparts. There is apparently something about the Nordic climate and temperament that makes for unbeatable crime stories! Unfortunately, it is looking like there won't be any more Wallanders since Mr. Mankell has gone to another plane of existence - though one can always hope.

As I said, when I ran out of Wallander books to read I found Michael Connelly and he made a huge impact upon the way I started reading Crime Fiction. At the time I had an antler table lamp by my couch...Marvellous Winters... Unfortunately this latest Bosch installment is crap. Only toward the end did Connelly's old style of action and suspense (e.g, the one we can still read in the early Harry Bosch novels) infuse the pages with something akin to the old Connelly. Solving each of the crimes is not a bad thing since you don't want to really leave any dangling threads, but having so many to close out detracts from the story. It was almost as if there was a feeling of needing to shove as much as possible into the story.

Sadly, there are so many badly written books in print. Far too many. But that is not down to the authors; that is down to agents and publishers. Even more sad is that fact that any author who wants to try something new is going to be against a business that simply wants you to repeat your last success by writing the same book again. In a market flooded with the cess of 'celebrity' titles, with vast (and stupid) advances that publishers work to recoup whilst mid list authors find themselves being dumped, there isn't much room for good, interesting, let alone innovative writing. At the end of the day readers - and publishers - should accept that the great authors are often those who don't like to remain pigeonholed, who strive to produce different styles and tones based on what each story merits. Because sometimes a bad novel isn't a sign of a miscalculated change of direction, it's a sign of disenchantment from an author stuck following the same direction.


Connelly seems to be going down the path of crappy Crime Fiction. 

quinta-feira, dezembro 07, 2017

Who am I? : "A Scanner Darkly" by Philip K. Dick


I'm a big Pynchon fan, too, so don't get me wrong here, but it seems to me like the main difference between Dick's writing style and Pynchon's--or at least, the difference that mostly accounts for Dick being treated as a "pulp" author with some interesting ideas whereas Pynchon is considered a major "literary" figure--is simply that Dick tends to write in crisp, straightforward sentences that just directly say what he means to say, whereas Pynchon's writing is (in)famously dense with allusion and rambling esoteric figurative expressions to the point where it can be an intellectual exercise in its own right just trying to figure out what the hell Pynchon is trying to say.

All of which makes major Dick novels like “Do Androids Dream of Electric Sheep?” or “Radio Free Albemuth” sort of resemble, IMHO, what “Gravity's Rainbow” might have looked like if Pynchon had been working with editors who expected him to actually keep tight deadlines.

I think Dick was really gifted as a wry satirist, too, and this is something I think he's often under-appreciated for. Probably my favourite single episode in all of Dick's stories I've ever read--and I was quite overjoyed to see this faithfully recreated in the film adaptation--is still the "suicide" sequence from “A Scanner Darkly”. In short, I don't think Dick was ever bad at writing--he just doesn't seem to have had any real interest in the kind of writing that people like James Joyce or William Burroughs (or Pynchon, for whom to my mind it seems that both Joyce and Burroughs were major stylistic influences) were famous for. I mean, in the 60's it was still nigh-impossible for anyone writing SF at all to be taken seriously by the "literary" world, which is important to remember as well--in the minds of smart, educated, respected literary critics, you simply didn't write about aliens or robots or time machines if you even wanted to be taken seriously as a "good writer", so I think it stands to reason that people like that were never an audience that Dick was even trying to impress or appeal to. He was writing for teenage boys and maladjusted stoners who didn't exactly run in sophisticated high-culture circles, so I imagine those audiences were really the people to whose tastes he tailored his style. I do think that with Dick, the whole is somehow greater than the sum of the parts. There are a few books that stand out as more perfect, or more complete, than the others, but in general I think it is the cumulative impact of the themes across the whole body of work that is his greatest achievement. Some of his books are quite flawed, or even weak - yet almost all feature at least one startlingly brilliant idea.

I read lots of Phil Dick as a teenager and it really put a perspective on the world that all the Asimov, Clarke and other SF authors really didn't... It's not that Phil Dick was more SF than the others; it's just the psychedelic perception manipulating stories seemed to be more vivid...One of the things that I enjoy about Phil’s books are that his lead characters lack "agency." When things go cross-eyed, they have a tendency to freeze up and simply endure whatever madness their damaged universe dishes out. It adds a certain plausibility to his stories -- we've all been, or we know, the guy who can't get it together, even when reality itself is up for grabs.

The thing to remember about Dick is he was inventive. The mechanical SF of today is pre-packaged, made to order product. Dick (who could have written about that) explored darkly funny worlds. When someone says he couldn't write, who are they comparing him to... today's writers with the publisher's crack team of craftsmen: Alpha & Beta readers, Restructuring, Copy-editing, Proofreaders? (Martin and Rothfuss come to mind) For that level of writing support, the books of today had better be good. And yet they don't have a tenth of Dick's creativity. Did Dick even have an agent? The Scott Meredith Agency - his last attempt to get a literary agent, returned his manuscripts, didn't it? Those who say he couldn't write are glossing over the reality of publishing. The question is: does the carefully crafted fiction of now bear comparison with him? I've studied Trad-Pub genre offerings for the last twenty years; I know what my answer would be.

Dick was not at all into dystopia or any kind of prospective/political SF. His main interest, in his life like in his art, was personal identity and all the doubts surrounding it. Who am I? Is the world around me true or an illusion? It was a philosophical and idiosyncratic SF that put him in another dimension than the rest of the genre. Emmanuel Carrère calls Dick the Dostoevsky of the 20th century, which is something I never agreed with. There is only one Dostoevsky, who was moments from being executed, reprieved and sent to a Siberian prison. Later released, became a gambling addict and after authoring some of the most distinctive, profound works of Literature became a national figure in Russia. Carriere is not correct with his comparison. Any more than Dostoevsky was a Russian Phillip K. Dick. "Who am I? What is my place in the world?" I can see why Carrère would appreciate Dick the same way Truffaut and French cultural commentators idolized David Goodis. He reads differently in their language and culture. Whereas in English, both of them come across as unable to escape from their pulp vision of the world. Orwell was always suspicious of novels that eschewed politics completely. Rightly so. I would think that Dick like Ayn Rand who asked the same questions, "who am I?, etc.) fantasize about an island or planet all their own in which they do not have to share anything with others. Dick inhabits a solipsistic universe and I like some of my fiction thus. Heinlein  is another case in point when it comes to solipsistic universes...I've written about it elsewhere.

“A Scanner Darkly” is a fine example of his literary world; he inhabits a solipsistic terrain which is the most extreme form of subjectivity. I get a measure of nihilism, and full-fledged meaning, reading him. I have to say, though, Kafka and Borges are two authors that I don't particularly enjoy reading. I know they are stalwarts of the modernist canon but I find them gimmicky, Borges with his inverted, convoluted, Kabbalistic fables and Kafka with his Central European father/Emperor psychological complexes. Banishing politics from literature has robbed it of much of its context. This is why Phil Dick is such a hero to me. Yes, he could set it aside but he addressed it, as well. I am almost sure Phil Dick and his descent into self-destruction via drugs was a response to the direction America went in from the 50's to the 80's. It's evident in many films and books during that period.


SF = Speculative Fiction.


segunda-feira, dezembro 04, 2017

On How to Spin a Top-Notch Yarn of Bullshit: "The Moon is a Harsh Mistress" by Robert A. Heinlein



The usual pretty crude pneumatic sex-fantasies cropped up... But women actually have a pretty dominant role in Heinlein's lunar society... It's a penal colony, and Heinlein reckons that means there are going to be far fewer women than men there - so he's come up with a system called 'line-marriage'... wherein a few women in a household share numerous husbands... And the head of the household is a woman... and women call the shots... Meanwhile, outside the home, women are treated with far more respect than they are on earth because they are so rare and precious... Obviously, he's not going to get any badges from feminists, but he does at least ask a few interesting questions about the way women were viewed in his own world...The characters explicitly reject using patriotism as a method to revolution.  

I think that Prof De La Paz's 'rational anarchism' is also expressed by Jubal Harshaw in 'Stranger', though not in as straightforward a manner. Both seem to say that it's not that hard to figure out what ideal behavior should be but expecting actual live humans to live up that is impossible. After accepting that point, they both want to move on. Yep, humans are hypocritical and sometimes hard to live with. What of it? The other big point of this is that only the direst situation (near term cannibalism here) justifies butting into other people's business. Sadly, this attitude is pretty rare today. The characters explicitly reject using patriotism as a method to revolution. The brain of the book (De La Paz) is an extreme libertarian who has a strong aversion to using the state to make people do anything. There is no attempt to export any kind of ideology to other countries, or even teach some kind of uniform value to its own citizens. How anyone could possibly describe it as 'neo-con' or 'fascist' is beyond me. What's the fascist charge based on? I read a ton of Heinlein in adolescence, and the politics varies a lot book to book. To be honest, extrapolating from the politics in a book to the author's politics is, well, not wholly reliable let's say.

For me, as great as the likes of Arthur C Clarke and Asimov were, they defined the golden age of SF - brilliant, groundbreaking science/concepts but wafer-thin characterisation. Heinlein for me stuck out not only because of his mind-bending concepts but mostly his unique protagonists who - so flawed, so outrageous and out-there (Maureen Johnson from the ‘Cat Who Walks Through Walls’, anyone?) who delivered witty, sarcastic dialogue. This didn't make him necessarily the best for me at the time, just the more humane of SF writers because his ideas seemed less firmly rooted in science than the above mentioned and more on the human condition and the limits of the imagination. I read a lot of his novels when I was a teenager and at the time, felt Heinlein wrote and delivered with a freewheeling sense of irony, certainly arrogance as if he was deliberately going against the grain of SF at the time, wearing his heart on his sleeve and not giving a damn.

And seeing as I’m throwing in my bit about his female characters, anyone remember ‘I Will Fear No Evil’? The dying genius Johann Sebastian Bach Smith who transplants his brain into the body of his secretary, learns how to live like a woman, keeps on having amorous congress left and right, falls in love, and, and, ...; the guys in ‘Starship Troopers’ really wouldn't have approved at all...Have to admit I loved it at the time because it was so different...but then I was only 14...

Heinlein's at his best does great adventure stories that are also full of ideas, and sometimes witty dialogue. When I was a kid, people used to actually say tanstaafl sometimes (geeks obviously, but geeks are people too). His later stuff though, his odd ideas about women get more prominent, his writing flabbier and more self-indulgent, generally he just loses it. But before then, well, he's got a bit dated but he wasn't bad at what he did.


NB: What I always admire about Heinlein is the way he manages to spin a yarn of bullshit so well: you know it's bullshit, he knows it's bullshit but you still swallow it all the same until you've finished the story and then you go "wait a minute..."

domingo, dezembro 03, 2017

Thinking in Code: "Antao's Tetris Ported from Python"


If you want to have a go at my version of the game, you can install it from here at the Google Play Store (Python version running on the Chrome Browser here).

The above app layout was modelled after my own gameboy:


Compare both pictures above. Was I successful? You tell me!

Any idiot can code, and many do. The skill is in understanding the maths and algorithms (speaking as an idiot who codes).

Lazy (or to be fair perhaps just poorly informed) people have taken to use the word "coding" as a synonym for software development. Actually, coding is tricky in and of itself (read the C++11 reference manual and tell me it ain't so) but it is still only the "bricklaying" part of construction, so to speak. Programming is creative and exploratory and stimulating to the imagination. It's a different way of thinking that serves people well in all sorts of life situations outside of software. So as a way to develop skills in logical thinking, problem solving and invention it's very useful. Not every child will go on to write software as an adult but having a basic understanding and insight into systems has to be a fundamental part of every child's education I say. If you don't understand the systems controlling your life how can you ever use them to your best advantage?

Actually the basics of code are not directly computer related at all. A simple binary device is an on-off light switch which says something like when I am 'on' my user is at home and when I am 'off' my user is away. A second light switch allows this develop into when both lights are on my user is awake and when only one light is on my user is asleep and so on. The code is what you make the light sequences mean. The same use is made of morse code, an abacus, flag signals , hand gestures, anything that can be logically explained to mean something for each different state. I think most children develop logic rather more quickly than we believe possible, and the only problem with computers is demystifying their apparent complexity when they are only ever very fast at very simple arithmetic and being given very precise instructions about what to do with all that speed adding numbers together.

I have to say that contemporary programming is much poorer than it was ten years ago, and I believe that is because we have provided far too many lazy ways to do complex things without making students graft hard at the basics and that is where I do believe improvements are to be found. However , ask a 20 something year old to sit there all day and write "select from where" ad infinitum and it doesn't take long to realise why younger people are not motivated by "heavy lifting" programming...

Programming is easy. Like any language, it is easy once you know how to talk, and think it. We have to stop thinking of programming as mathematics, science or engineering. It needs to be taught as a language skill. The moment we treat it as a language skill, the traditional barriers begin to fall. It becomes acceptable for parents of both sexes, at any age, and any religion. I don't think there are many people who would object to their kids having the opportunity to learn multiple languages, as early as possible, if they could. I don't think I have ever heard anyone object to a child being able to speak multiple languages. Once academics can get over their misconceptions on what they need programming to be, we could all move on, and start teaching our kids how to make them look stupid.

Once you can program in one language it is easy enough with the help of Google to pick up other languages. I've spent quite a lot of time programming in languages that I didn't know. In my experience what people find harder to pick up is the logic and the ability to break down the task required into the small logical steps required to make a computer perform the task. I started out very young; I learned to program because I wanted to play games and back then that meant typing in program listings from computer magazines. They never worked properly so I worked out how to fix them. Do a few of those, and you soon enough prick up how to program. After that new languages are easy. The only time I struggled a little bit was in making the leap from procedural coding to object-orientated as that's a bit of a paradigm shift.

I used to be a software developer, and have developed lots of software for the last 25 years. Believe me when I tell you that 99% of the job, has nothing to do with either mathematics, or science. The only reason you, and most other people, who probably don't program, think it does, is because everyone you ever see, working in this branch, drives that, image. Syntax is language, but expression is also language. Being able to understand, and then describe a process, is absolutely, a pure language skill. Most of the work ever done, is little more than connecting dots, and building logical expressions with existing tools and libraries. The language behind every programming language, is pretty much universal. once you have learned how to express yourself, and approach problems, you can easily skip to any language, and syntax, with a short learning curve. Ask a database developer, or a network developer how much math and science they need, to do their job. Not a lot, that is for sure. some do, but in general, very little real math is required, and it sure ain't rocket science these days. of course further skills are required in some areas, depending on what you want to do, but I would argue with anyone that this job is generally NOT science anymore. I would also argue that that math is absolutely NOT a prerequisite to be able to program today. If you are a good communicator, and you have normal math skills, you can be a great programmer. If IMO, we exclude the wrong people from programming. We need less geeks with personality disorders in this branch, and more talented communicators. To get that, we need to rethink who we think are going to be good at the job, and include a completely different skill set, as prerequisite to what makes a programmer today.

I still sometimes dream of creating some games and getting a bit of cash from it. I still tinker with Android (a few more examples of coding in Android here), and have a few half-finished games that I did in XNA for the Xbox Live Indie store. I think part of the problem for games now, or at least console games, is the publisher and retailer taking so much of the pie. Digital distribution is great in principle, but on console at least, unless you're using Xbox Live Gold or PSN+ or whatever there seems to be absolutely no discount - in fact a lot of games are more expensive than their retail counterpart (which is expensive and fickle enough). If a developer could get a lot more of the money without going through a publisher or retailer, I'd be all for it. At the moment, the vast, vast majority of games I buy are old ones (2 years old or more) that you just can't buy new, so it's all second hand. This extra money, if going to the developers themselves, would give them a lot more freedom and make conditions at them a lot more tolerable.

As for "thinking in code", I used to be the same. I could have code swimming around in my head for hours, and to an extent still do (only now, with me doing a lot of QLIK work too, a lot of mine is maps, statistics and graphs). The experience hasn't put me off playing games, but given me more respect for the people that make them - and then, sometimes, less respect when they get things wrong, especially design-wise (Dead Rising's save system, I'm looking at you).


NB: The core of the engine is the following class.

class TetrisGame implements PosPaintable {
    Grid playfield;
    TetrisPiece piece;
    int curScore;
    int px,py; 
    intNonZero testNonZero;
    intOr      putDown;

    public TetrisGame(int xs,int ys,boolean randomCrap)
{
playfield=new Grid(xs,ys,1);
clear();
piece = new TetrisPiece();
py=0;
px=(xs-piece.sizex())/2;
testNonZero = new intNonZero();
putDown = new intOr();
curScore=0;
}
    
    void clear()
{
playfield.fill(0,0,playfield.sizex(),playfield.sizey(),0);
}

    public void paint(Graphics g, int x,int y)
{
g.drawRect(x,y,2+playfield.sizex()*10,2+playfield.sizey()*10);
for(int j=0;j
    for(int i=0;i
if((playfield.grid[i][j]!=0) ||
   ((i>=px) && (i
    (j>=py) && (j
    (piece.grid[i-px][j-py]!=0)))
    g.fillRect(3+x+i*10,3+y+j*10,8,8);
        }


    public boolean step()
{
if(playfield.compare(piece,px,py+1,testNonZero))
    {
    // Put down the piece
    playfield.put_on(piece,px,py,putDown);
    // Clear out full lines
    for(int j=playfield.sizey()-1;j>=0;j--)
while(testFullLine(j)==true)
    {
    deleteLine(j);
    // Simple scoring function
    curScore+=10;
    }

            // Put on a new piece
    piece = new TetrisPiece();
    py=0;
    px=(playfield.sizex()-piece.sizex())/2;
    if(playfield.compare(piece,px,py,testNonZero))
return true;
            }
        py++;
return false;
        }

    private boolean testFullLine(int y)
{
for(int i=0;i
    if(playfield.grid[i][y]==0)
return false;
        return true;
}

    private void deleteLine(int y)
{
for(int j=y;j>0;j--)
            for(int i=0;i
playfield.grid[i][j]=playfield.grid[i][j-1];
        for(int i=0;i
    playfield.grid[i][0]=0;
        }

// Data-returning methods

    public int score()
{
return curScore;
}

// Game-play interface methods

    public void move_left(int i)
{
if(playfield.compare(piece,px-i,py,testNonZero))
    return; // Should we throw an exception here?
        px-=i;
}
    public void move_left()
{
        move_left(1);
}

    public void move_right(int i)
{
if(playfield.compare(piece,px+i,py,testNonZero))
    return; // Should we throw an exception here?
        px+=i;
}
    public void move_right()
{
        move_right(1);
}

    public void rotate_cw()
{
TetrisPiece test=new TetrisPiece(piece);
        test.rotate_cw();
if(!playfield.compare(test,px,py,testNonZero))
    piece=test;
        }

    public void rotate_ccw()
{
TetrisPiece test=new TetrisPiece(piece);
        test.rotate_ccw();
if(!playfield.compare(test,px,py,testNonZero))
    piece=test;
        }

    public void drop()
{
while(!playfield.compare(piece,px,py+1,testNonZero))
    py++;
        }







sábado, dezembro 02, 2017

The SF Lamp was Broken: "Six of Crows" by Leigh Bardugo



After having finished “Six of Crows”, I would encourage anyone to consider the potential for SF to help us all drop our lazy assumptions about Realism, mimesis, and how any writing made up of words upon a page ever really relates to or captures some discernible, locatable "real world." As someone who prefers poetry over novels (Yep. I know I'm built that way), I turn to SF (science-fiction, weird fiction, fantasy) for the same sort of liberation from the tyrannous fantasy of the Real. Forget the mirror; look to the Lamp. Every piece of fiction is just that, fiction, and for those who read attentively and with appreciation of the power of the imagination. Dickens's London in “Bleak House” and Eliot's “Middlemarch” are just as artificial and speculative and weird as Carroll's “Looking Glass” world or Stoker's “Transylvania” or Barrie's “Neverland” or Mirrlees “Lud-in-the-Mist” or Jack Vance's “Dying Earth” or Peake's “Gormenghast” or China Mieville's “New Crobuzon”. All of these fantastic places are projections of the imagination. All of them hold prime value in the way they transport us away from our easy assumptions about what is real and then return us, much changed.

In his Lectures on Literature, Nabokov is quite good at pointing out the need to redraw our maps and drop our assumptions. The gist of what he says is that every time we open a novel we are visiting a new potential world, very different from our own ideas about our own world, and we will be sorely misguided unless we redraw our maps and learn to see difference everywhere.

Finally, I must admit that I am drawn to SF for its decadent, art-for-art's sake aspects. Because I was taught Victorian poetry at the British Council, it reminds of me of Swinburne's urgent lesson. It matters not whether the art deals with Past or Present or Future or something apparently unknown. Instead, what matters is the excellence of the writing, the breadth of the imagination.

Love and the idea of love aren't so different. Like cheese on the farm and processed cheese, those who've experienced one and not the other have no way of knowing the difference. Yet the distance between the word and the thing is infinite. Either suffices because like everything else in this world, we have what we have and we only know what we lack (beyond flesh's necessities) because others tell us so. With proper programming, at least a spouse-bot won't remind us of what we lack. If I want to read "romancy SF", I’ll choose it myself. I don’t want to read a romance novel disguised as SF.

At the end of “Six of Crows”, I felt the Real was not kept at bay because the Lamp was broken.



SF = Speculative Fiction.

sexta-feira, dezembro 01, 2017

Beckettian SF: "The Man in the High Castle" by Philip K. Dick


“The Man in the High Castle” is my second favourite PKD novel, after “Do Androids Dream of Electric Sheep”. I read both novels in the same year, back in the day, along with “Ubik”, “VALIS” and “The Three Stigmata of Palmer Eldritch”, and most of PKD's short fiction. Without doubt the most mind-bending year of reading I've ever had, and the one that hooked me on SF more than any other. The thing I love about his stories more than anything else is their mastery of chaos and illogicality. Reality in a PKD story is held together by the desperate hopes of his characters, and it's always falling apart beneath their feet. Love it!

As for PKD's prose not keeping up with his ideas and co... I agree... and also agree it's often part of the fun. Although here, as noted, I found his writing mainly quite elegant.

I've been hunting around for speculation as to why PKD called Hawthorne Abendsen's book “The Grasshopper Lies Heavy”. Dick says in the book that the title is a quote from The Bible, but if so it is not in a common translation. You can find some speculation elsewhere; being speculative about a Dick novel means we'll be wandering into some fairly strange territory... I've also asked the question on my own blog, so there may be enlightening comments there.

I suppose I've never really considered him as SF and therefore haven't really considered him as SF. I realise this is rather weak and tautological but it’s the fact of the matter. I suppose probably because I have quite restricted notion of what SF actually is. Perhaps I should try more. I make the further claim because it often seems to me to be too far away from how we experience the world. I find it often too far removed from reality to effect the way I perceive it. I've always been away of a porous boundary between what we take as truth and fiction and the most effective novels seem to me to find a way to weave the two together questioning both. I'm never sure that SF takes enough of the former to do that.

It is part of what SF often does to propose realities different from our own. And often proposing that our own reality is not even really reality. Metaphysics, including religions of every ilk, has routinely done the same thing over long millennia, and convincingly enough for religions to have dominated much of human history and metaphysics to have dominated, in full or in part, the thinking of many of the best minds in human history. Science fiction has only been at it for decades, but PKD managed to bring it to a level still unsurpassed by any other SF writer, perhaps any other writer at all. Although, in one way or another, many philosophers have questioned the phenomenal world and our lives in it, Descartes brought to the table the "I", the individual identity, and that "I" has more than held its own for going on 500 years, as a, perhaps THE, preoccupation in Western thought and feeling, very much including Literature.

Beckett has put his "I" character into strange wavering limbos where it manages to unwaveringly 'go on'; PKD's 'I' exists in equally strange bizarre worlds (that often somehow make too much sense), but they waver and shift in a constant struggle to adapt to relentless rifts and shifts in the world around them, and in all that they know. Paul Williams in his 1974 Rolling Stone interview with PKD says: "Dick's characters are all ultimately small (that is ordinary, believable) people made big by their stamina in the face of an uncertain world." This would almost apply to Beckett's characters too, but where 'uncertain world' in Dick's case doesn't mean the vicissitudes of an individual's life at the ultimate bottom of the lowest of the barrels, but a world whose very reality is an uncertainty that is bottomless, and whose uncertainty is very much in the individual identity's (the "I"'s) life as a problem and condition of life. This "I" too "goes on".

I wouldn't take away Beckett's Nobel in Literature and give it to PKD, and I don't in the least believe Beckett will not stand the test of time, but I do believe that PKD's work will keep on being evaluated upwards as Literature as the years roll on. My PKD’s re-read project shows how very alive and well his body of work is, which means people still read it and feel it is a relevant artistic vision. For me, artistic vision is the most important thing a writer can have. Dick's was a strange and evolving visionary critter, but it was powerful and still is. Dick brings it to life in his reader's minds. He's a great writer thereby. Beckett may have the Nobel and the literary criticism reputation but it's PKD who continues to have the social influence thanks to his peerless imagination and paranoia (which grows increasingly justifiable as time goes by).


Since I think of PKD in terms of Literature I tend to think about him more in the context of Kafka, Beckett, and Burroughs. I rarely try to put him into a science fiction genre series of writers, although some may have written better SF (as genre) than him. What makes him transcend, if you will, the sci fi genre is that 'science fiction' is now, and increasingly, defining our daily 'mainstream' lives as technological innovation, but mainstream Literature has not caught up with what is happening, and veers away from it, looking for the meanings of human experience elsewhere. It's a weird kind of disconnect between contemporary literature and modern life. But PKD's writing was and is thoroughly aware of the entanglement of brave new science-fictional realities with our age old humanity. Even his metaphysics involve supercomputer gods, temporal interpret rations, and the like. He does it better than anyone and that's why I don't flinch to think about him being in exalted literary company. And it's why I think that sooner or later readers and lit critics and academics are going to reconnect mainstream literature with mainstream daily life. Dick's fiction will be right there in the forefront.


SF = Speculative Fiction.

quinta-feira, novembro 30, 2017

The Risks of Universal Enfranchisement: "Starship Troopers" by Robert A. Heinlein



Word of warning. I’m going to discourse both on the book and on the Verhoeven’s movie.

He didn't include them as "grunts" probably because the training was sufficiently hard that most wouldn't have made it. If you read the description of the training it wasn't just 12 weeks square-bashing, it reads far more like Special Forces.

It might also have been because he was paying lip service to a society kind of modelled on 50s America where the ladies were the home-makers and females in the frontline weren't even on the radar.

However, having said that, we have the fabulous line about females in high rank and esteem:

"If the Almighty ever needs a hand to run the universe: hot ship pilot Yvette Deladrier" after Starship commander Deladrier brakes her ship's orbit to recover a lander that has blasted off late and which otherwise would miss rendezvous and all on board would perish. I’ve heard from a lot of my friends saying the movie version is utter shit. I’m not so sure. The thing is, Verhoeven was a master of taking existing texts and subtly pushing them into satire by overdoing Hollywood/MTV filming tropes. The viewer was encouraged to look at the films as broad entertainment and then ask what the actions of the heroes had to do with American culture. He did the same with Joe Eszterhas's scripts for “Basic Instinct” and “Showgirls”. “Basic Instinct” is a detective story where the 'hero' is someone who's already gotten away with murder because of his badge, and who shoots another innocent victim before the film is out, while the 'villain' is never actually shown to kill anyone. She's chiefly a suspect because of her sexuality (which is why GLAAD picketed the film) and lack of shame about it. “Showgirls” meanwhile depicts a vision of Las Vegas as a patriarchal dystopia where every woman is judged on her body and literally every male character is a predator of some kind. The fact the film is framed as a “Star is Born” story is even better when you consider all the revelations going on in Hollywood right now. If anything, it's timelier than Starship Troopers.

The movie is the opposite of the book. The movie is not in earnest, the book is. It's probably a failure of Verhoeven's in that respect. “RoboCop” was seen as a satire from the get-go. I don't think there are enough sign-posts in “Starship Troopers” to stamp it as a satire outright, although it clearly is in hind-sight.

Verhoeven's early life was under the Nazis. When the movie came out Iwas on an internet forum and we were relentlessly trolled by a few young Americans who took it seriously as an action film, as some kind of heroism to emulate. It was actually a while before the film was released in the Portugal, so I didn't have much to say until I saw it. That's when the satire was obvious to me, but I also realised how teenagers would just go with the fascism (not even realising it was fascism) and feel it was a good thing. The problem was that, just as in “Robocop” (and “Showgirls”, to be honest), Verhoeven's satire comes within some superb plotting and film design that, if one is not careful, might actually seem sincere. Unbelievably, a lot of critics just didn't get it at the time, especially American film critics. I wonder if they didn't want to get it - far too close for comfort to an attitude among many in American society (and not just American society): a simplistic good versus evil narrative with the only solution being to crush the evil-doers with overwhelming force.

As to the accusation that Heinlein was a fascist, you need to remember that he wrote most of his works over fifty years ago, in a VERY different world from ours. I want to say, he was the first one to have a Japanese American Hero - Jeff Mitsui in "Sixth Column", the first to have a Hispanic hero - heck a bunch of them - in "Starship Troopers" - Juan and Simon Rico, Carmen Ibanez, David "Dizzy" Flores - all of them quite literally "white-washed" by that never-to-be-sufficiently-smartaleck Verhoeven in the movie. Col Dubois and "Ace" Smith were both black in the book, but "White-washed" in the movie. In "The Star Beast" - the true hero was the Assistant Secretary General of the United Nations, Samuel Kikui, a Masai tribesman from Kenya, with a Doctorate from Cambridge. In "Stranger in a Strange Land" - Judge Jubal Early spoke Arabic, "because he wanted to read the Quaran in the original Language of the Prophet." As I said, the book was written in the 1950's so must be read in the context of that time - not 'fiercely rightwing' at all. Robert Heinlein's attitudes changed as the times changed - communes and homosexual love featured in his books and not in a negative way. I feel the book and movie are far too divergent to reasonably discuss both as if they were the same. Each is its own standalone message and art. It's similar to the Japanese movie Kairo and its American remake “Pulse”. Even though both included a similar starting premise and “Pulse” even had some exact shot-for-shot scene recreations from the original, the stories diverge wildly and both show a very distinct difference between the cultures in how they tell stories and what they tell stories about. But "Heinlein is a conservative, white fascist" because that is a useful shibboleth for those who get their information from other people, who are too busy to actually read what they are condemning. Heinlein had a long fascination with the risks of universal enfranchisement. This is of a piece with American concerns about majoritarianism. In “Expanded Universe”, he goes through a few ways in which the right to vote might be restricted in aid of better governance and decision making. My favourite example is his suggestion that only women be allowed to vote, because men have made such a god awful mess of things for such a very long time. It's never clear how serious he's being, except insofar as he is concerned that democracies often make idiotic decisions (alluded to in “Stranger in a Strange Land”, also). And honestly, in this world of Trump and Brexit, he's got plenty of company, even if lots of us still hew to Churchill's dictum in the end. Because of a few "brain bugs" is considered a fascist? The mass insects were brainless ferocious foot-soldiers. Round these parts, of course they'd be considered misunderstood and victimised. The humans weren't great, but we can’t make the bugs to be the good guys, right? The future Earth depicted in “Starship Troopers” didn't have nationalities just a common Earth citizenship. Plus men and women of multiple races fighting and showering together. What could be more democratic? Epic comprehension malfunction on the part of some of the readers, so to speak.

Piece of advice. Don't watch the film - read the original book! It predates the film about 40 years and - shock, horror - in the book our hero Rico is of good, solid South-American stock (as is the school's math-wiz, Juanita, on which Rico has a mild crush). Worse, he doesn't get the girl. Nobody dares tell Donald, in case he would reach for his tweeter...

Heinlein speaking as Heinlein put his money where his mouth was - joining the navy and serving his country. As a volunteer; he memorably denounced conscription under any circumstances as slavery.

quarta-feira, novembro 29, 2017

Argghh, Just One More Go Mum: "Exploring Tetris On My Own"



"but...but...the Spectrum is for educational purposes Mum! Honest, look it comes with a game called Chess and Scrabble!"


Ping pong, Pacman, Defender, Elite, Sabre Wolf, Manic Miner, Jetset Willy, Tekken Sensible Soccer, Mario, Sonic, NHL, PES, Fifa, COD, Forza, Dirt, Bubble Burst, Candy Crush, Donald Trump, Mickey Mouse... Never affected me in anyway whatsoever, thinking back, I still haven't handed in my Technical Drawing homework due in 1985. "Argghh, just one more go mum."


I grew up with a commodore 64 and ZX Spectrum. I use to play games obsessively, especially Elite but it never impacted my social and family life. Apart from a bit of cop killing and drug, slave and alien artifact trading here and there I have grown up to be a well rounded member of society

I seem to be the only person in public spaces sitting staring into space, thinking without a device of some kind. Looking at other people using their phones, it seems that we're at the point where they're virtually programmed to reach for their phones as soon at every conceivable opportunity without even thinking about it. Often going through the same cycle, checking text, mail, news. Seems the whole concept of independent reflection has gone out the window.

In fairness sitting by yourself and staring into space in public was considered a bit odd even before computer games and smart phones. I feel the same way about people who can only run if they do so with headphones, that on some level they are saying 'Running is crap and I need this ear candy to make it bearable'.

It just depends if you have an addictive nature or not. Everyone's brains are wired differently. Our brains goe haywire with dopamine and serotonin whenever we receive a positive feedback. Doesn't matter if it's a blackjack, some under 20 team in Uzbekistan winning, landing a dragon punch in SFII, scoring a Tetris, looking at porn, reading or writing reviews... I'm just a born addict and will keep on doing that thing, usually addictive stuff.

Tetris. Ah. Those were the days...It's a beautiful game except when the pieces start falling faster. I always played with the sound off to reduce the stress but the pile-up . . . (deep breath) . . . .is always on the horizon . . . (deep breath) . . . .(deep breath) . . . .(deep breath) . . . .

What follows is something I concocted to while away the time when I was dealing with tossers I won't say where...

NB: Next step is porting the the following Tetris Engine to Android, which is already under way. The hard part is finished (e.g., collision detection, rotation matrices, and so forth).

Python Tetris Engine:


import simplegui
import random

BACKGROUND_COLOR = "White"
WIDTH = 700
HEIGHT = 600
BOARD_WIDTH = 10
BOARD_HEIGHT = 20
BOARD_UPPER_LEFT = (300, 75)
BLOCK_SIZE = 25
START_POSITION = (3, 0)
gameInPlay = False
score = 0
time = 0
vel_y = 0
next_piece = None
speed = 15

# global game objects
piece_O = None
piece_I = None
piece_T = None
piece_L = None
piece_J = None
piece_S = None
piece_Z = None
piece_B = None
board = None
pieces = None
pos = [10, 10]
current_piece = None

# test shape of one block
SHAPE_ONE_BLOCK = ["X"]
SHAPE_ONE_BLOCK.append("B")
SHAPE_ONE_BLOCK.append("Green")

SHAPE_O_0 = [["O", "X", "X", "O"],
             ["O", "X", "X", "O"],
             ["O", "O", "O", "O"],
             ["O", "O", "O", "O"]]
temp = []
temp.append(SHAPE_O_0)
temp.append(SHAPE_O_0)
temp.append(SHAPE_O_0)
temp.append(SHAPE_O_0)
SHAPE_O = []
SHAPE_O.append(temp)
SHAPE_O.append("O")
SHAPE_O.append("Yellow")

SHAPE_I_0 = [["O", "O", "O", "O"],
             ["X", "X", "X", "X"],
             ["O", "O", "O", "O"],
             ["O", "O", "O", "O"]]
SHAPE_I_1 = [["O", "X", "O", "O"],
             ["O", "X", "O", "O"],
             ["O", "X", "O", "O"],
             ["O", "X", "O", "O"]]
SHAPE_I_2 = [["O", "O", "O", "O"],
             ["O", "O", "O", "O"],
             ["X", "X", "X", "X"],
             ["O", "O", "O", "O"]]
SHAPE_I_3 = [["O", "O", "X", "O"],
             ["O", "O", "X", "O"],
             ["O", "O", "X", "O"],
             ["O", "O", "X", "O"]]
temp = []
temp.append(SHAPE_I_0)
temp.append(SHAPE_I_1)
temp.append(SHAPE_I_2)
temp.append(SHAPE_I_3)
SHAPE_I = []
SHAPE_I.append(temp)
SHAPE_I.append("I")
SHAPE_I.append("LightBlue") ##ADD8E6

SHAPE_T_0 = [["O", "X", "O"],
             ["X", "X", "X"],
             ["O", "O", "O"]]
SHAPE_T_90 = [["O", "X", "O"],
              ["X", "X", "O"],
              ["O", "X", "O"]]
SHAPE_T_180 = [["O", "O", "O"],
               ["X", "X", "X"],
               ["O", "X", "O"]]
SHAPE_T_270 = [["O", "X", "O"],
               ["O", "X", "X"],
               ["O", "X", "O"]]
temp = []
temp.append(SHAPE_T_0)
temp.append(SHAPE_T_90)
temp.append(SHAPE_T_180)
temp.append(SHAPE_T_270)
SHAPE_T = []
SHAPE_T.append(temp)
SHAPE_T.append("T")
SHAPE_T.append("Purple")

SHAPE_L_0 = [["O", "O", "X"],
             ["X", "X", "X"],
             ["O", "O", "O"]]
SHAPE_L_1 = [["X", "X", "O"],
             ["O", "X", "O"],
             ["O", "X", "O"]]
SHAPE_L_2 = [["O", "O", "O"],
             ["X", "X", "X"],
             ["X", "O", "O"]]
SHAPE_L_3 = [["O", "X", "O"],
             ["O", "X", "O"],
             ["O", "X", "X"]]
temp = []
temp.append(SHAPE_L_0)
temp.append(SHAPE_L_1)
temp.append(SHAPE_L_2)
temp.append(SHAPE_L_3)
SHAPE_L = []
SHAPE_L.append(temp)
SHAPE_L.append("L")
SHAPE_L.append("Orange")

SHAPE_J_0 = [["X", "O", "O"],
             ["X", "X", "X"],
             ["O", "O", "O"]]
SHAPE_J_1 = [["O", "X", "O"],
             ["O", "X", "O"],
             ["X", "X", "O"]]
SHAPE_J_2 = [["O", "O", "O"],
             ["X", "X", "X"],
             ["O", "O", "X"]]
SHAPE_J_3 = [["O", "X", "X"],
             ["O", "X", "O"],
             ["O", "X", "O"]]
temp = []
temp.append(SHAPE_J_0)
temp.append(SHAPE_J_1)
temp.append(SHAPE_J_2)
temp.append(SHAPE_J_3)
SHAPE_J = []
SHAPE_J.append(temp)
SHAPE_J.append("J")
SHAPE_J.append("DarkBlue") #00008B

SHAPE_S_0 = [["O", "X", "X"],
             ["X", "X", "O"],
             ["O", "O", "O"]]
SHAPE_S_1 = [["X", "O", "O"],
             ["X", "X", "O"],
             ["O", "X", "O"]]
SHAPE_S_2 = [["O", "O", "O"],
             ["O", "X", "X"],
             ["X", "X", "O"]]
SHAPE_S_3 = [["O", "X", "O"],
             ["O", "X", "X"],
             ["O", "O", "X"]]
temp = []
temp.append(SHAPE_S_0)
temp.append(SHAPE_S_1)
temp.append(SHAPE_S_2)
temp.append(SHAPE_S_3)
SHAPE_S = []
SHAPE_S.append(temp)
SHAPE_S.append("S")
SHAPE_S.append("Green")

SHAPE_Z_0 = [["X", "X", "O"],
             ["O", "X", "X"],
             ["O", "O", "O"]]
SHAPE_Z_1 = [["O", "X", "O"],
             ["X", "X", "O"],
             ["X", "O", "O"]]
SHAPE_Z_2 = [["O", "O", "O"],
             ["X", "X", "O"],
             ["O", "X", "X"]]
SHAPE_Z_3 = [["O", "O", "X"],
             ["O", "X", "X"],
             ["O", "X", "O"]]
temp = []
temp.append(SHAPE_Z_0)
temp.append(SHAPE_Z_1)
temp.append(SHAPE_Z_2)
temp.append(SHAPE_Z_3)
SHAPE_Z = []
SHAPE_Z.append(temp)
SHAPE_Z.append("Z")
SHAPE_Z.append("Red")

class Board():
 
    def __init__(self, upper_left_corner):
        self.upper_left = upper_left_corner
        self.upper_right = (upper_left_corner[0] + (BLOCK_SIZE * BOARD_WIDTH), self.upper_left[1])
        self.lower_right = (upper_left_corner[0] + (BLOCK_SIZE * BOARD_WIDTH), self.upper_left[1] + (BLOCK_SIZE * BOARD_HEIGHT))
        self.lower_left = (self.upper_left[0], self.upper_left[1] + (BLOCK_SIZE * BOARD_HEIGHT))

        # setup grid
        self.grid = []
        for i in range(BOARD_HEIGHT):
            row = [None] *  BOARD_WIDTH
            self.grid.append(row)
     
    def draw(self, canvas):
        for c in range(BOARD_WIDTH):
            for r in range(BOARD_HEIGHT):
                if self.grid[r][c] != None:
                    block = self.grid[r][c]
                    draw_block(canvas, (self.upper_left[0] + (BLOCK_SIZE * c), self.upper_left[1] + (BLOCK_SIZE * r)), 1, BACKGROUND_COLOR, block.get_color())
        canvas.draw_polygon((self.upper_left, self.upper_right, self.lower_right, self.lower_left), 1, "Black")

    def fill(self, pos, piece):
        self.grid[pos[0]][pos[1]] = piece
     
    def empty(self, pos):
        self.grid[pos[0]][pos[1]] = None
     
    def isEmpty(self, pos):
        return (self.grid[pos[0]][pos[1]] == None)
 
    def isRowFull(self, row):
        for col in range(BOARD_WIDTH):
            if self.grid[row][col] == None:
                return False
        return True
 
class Piece():
    def __init__(self, shape, pos = None):
        self.color = shape[2]
        self.type = shape[1]
        self.shapes = shape[0]
        self.shape_index = 0
        self.shape = self.shapes[0]
        self.width = len(self.shape[0])
        self.height = len(self.shape)
        if pos != None:
            self.x = pos[0]
            self.y = pos[1]
     
    def __str__(self):
        s = ""
        s += "Piece (shape = " + self.type + ", color = " + self.color + ")\n"
        s += " (width = " + str(self.width) + ", height = " + str(self.height) + ")\n"
        for row in self.shape:
            value = ""
            for col in row:
                value += col
            s += value + "\n"         
        return s
 
    def isValidRotation(self, direction):
        if direction == "CCW":
            if self.shape_index == len(self.shapes) - 1:
                idx = 0
            else:
                idx = self.shape_index + 1
        else:
            if self.shape_index == 0:
                idx = len(self.shapes) - 1
            else:
                idx = self.shape_index - 1
        temp_piece = Piece([[self.shapes[idx]], "temp", "Blue"], (self.x, self.y))

        canRotate = True
     
        #Check top side
        for row in range(len(temp_piece.shape)):
            for col in range(len(temp_piece.shape[row])):
                if temp_piece.shape[row][col] == "X":
                    if (temp_piece.y + row) < 0:
                        canRotate = False
                     
        #check down side
        for row in range(len(temp_piece.shape) - 1, -1, -1):
           for col in range(len(temp_piece.shape[row])):
                if temp_piece.shape[row][col] == "X":
                    if (temp_piece.y + row) >= BOARD_HEIGHT:
                        canRotate = False
                     
        #check right side
        for row in range(len(temp_piece.shape)):
            if "X" in temp_piece.shape[row]:
                reversed_row = list(temp_piece.shape[row])
                reversed_row.reverse()
                offset = reversed_row.index("X")
                if (temp_piece.x + temp_piece.width - offset) > BOARD_WIDTH:
                    canRotate = False
     
        #check left side
        for row in range(len(temp_piece.shape)):
            if "X" in temp_piece.shape[row]:
                offset = temp_piece.shape[row].index("X")
                if (temp_piece.x + offset) < 0:
                    canRotate = False
                 
        #check for overlaps
        for row in range(len(temp_piece.shape)):
            for col in range(len(temp_piece.shape[row])):
                if temp_piece.shape[row][col] == "X":
                    if temp_piece.x + col >= BOARD_WIDTH or temp_piece.y + row >= BOARD_HEIGHT:
                        canRotate = False
                    elif temp_piece.x + col < 0 or temp_piece.y + row < 0:
                        canRotate = False
                    elif not board.isEmpty((temp_piece.y + row, temp_piece.x + col)):
                        canRotate = False     
     
        return canRotate

    def rotate_ccw(self):
        if self.shape_index == len(self.shapes) - 1:
            self.shape_index = 0
        else:
            self.shape_index += 1
        self.shape = self.shapes[self.shape_index]
        self.width = len(self.shape[0])
        self.height = len(self.shape)
 
    def rotate_cw(self):
        if self.shape_index == 0:
            self.shape_index = len(self.shapes) - 1
        else:
            self.shape_index -= 1
        self.shape = self.shapes[self.shape_index]
        self.width = len(self.shape[0])
        self.height = len(self.shape)

    def get_color(self):
        return self.color
 
    def get_width(self):
        return self.width
 
    def get_height(self):
        return self.height
 
    def move_left(self):
        canMove = True
         
        for row in range(len(self.shape)):
            if "X" in self.shape[row]:
                offset = self.shape[row].index("X")
                if (self.x + offset) - 1 < 0:
                    canMove = False
                elif not board.isEmpty((self.y + row, self.x + offset - 1)):
                    canMove = False

        if canMove:
            self.x -= 1
         
    def move_right(self):
            canMove = True
         
            for row in range(len(self.shape)):
                if "X" in self.shape[row]:
                    reversed_row = list(self.shape[row])
                    reversed_row.reverse()
                    offset = reversed_row.index("X")
                    if (self.x + self.width - offset) + 1 > BOARD_WIDTH:
                        canMove = False
                    elif not board.isEmpty((self.y + row, self.x + self.width - offset)):
                        canMove = False

            if canMove:
                self.x += 1
     
    def move_up(self):
            canMove = True
         
            for row in range(len(self.shape)):
                for col in range(len(self.shape[row])):
                    if self.shape[row][col] == "X":
                        if (self.y + row - 1) < 0:
                            canMove = False
                        elif not board.isEmpty((self.y + row - 1, self.x + col)):
                            canMove = False

            if canMove:
                self.y -= 1       
 
    def move_down(self):
            canMove = True
         
            for row in range(len(self.shape) - 1, -1, -1):
                for col in range(len(self.shape[row])):
                    if self.shape[row][col] == "X":
                        if (self.y + row + 1) >= BOARD_HEIGHT:
                            canMove = False
                        elif not board.isEmpty((self.y + row + 1, self.x + col)):
                            canMove = False

            if canMove:
                self.y += 1
             
            return canMove
 
    def get_blocks(self):
        positions = []
        for row in range(len(self.shape)):
            for col in range(len(self.shape[row])):
                if self.shape[row][col] == "X":
                    positions.append((self.x + col, self.y + row))
        return positions
     
    def draw(self, canvas):
        for row in range(len(self.shape)):
            pos_y = BOARD_UPPER_LEFT[1] + (BLOCK_SIZE * self.y) + (BLOCK_SIZE * row)
            for col in range(len(self.shape[row])):
                pos_x = BOARD_UPPER_LEFT[0] + (BLOCK_SIZE * self.x) + (BLOCK_SIZE * col)
                if self.shape[row][col] == "X":
                    draw_block(canvas, (pos_x, pos_y), 1, BACKGROUND_COLOR, self.color)
                else:
                    draw_block(canvas, (pos_x, pos_y), 1, BACKGROUND_COLOR, BACKGROUND_COLOR)
 
    def get_position(self):
        return (self.x, self.y)
 
def draw_block(canvas, pos, line_width = 1, line_color = "Black", fill_color = None):
    block = [(pos[0], pos[1]), (pos[0] + BLOCK_SIZE, pos[1]), (pos[0] + BLOCK_SIZE, pos[1] + BLOCK_SIZE), (pos[0], pos[1] + BLOCK_SIZE)]
    canvas.draw_polygon(block, line_width, line_color, fill_color)

def draw(canvas):
    global time
    global gameInPlay
 
    time += 1
 
    if gameInPlay:
     
        if (time % speed == 0):
            piece_moved = current_piece.move_down()

            if current_piece.get_position() == START_POSITION:

                gameInPlay = False


            if (not piece_moved):
                lockdown_handler()
                create_new_piece_handler()

        for i in range(BOARD_HEIGHT):
            check_full_rows_handler()
         
        # draw next piece
        positions = next_piece.get_blocks()

        color = next_piece.get_color()
     
        pos[0] = BOARD_UPPER_LEFT[0] + (BOARD_WIDTH * BLOCK_SIZE)
        pos[1] = BOARD_UPPER_LEFT[1] + 60
     
        canvas.draw_text("Next Piece", [pos[0] + 20, pos[1] - 40], 20, "Black")

        for i in positions:
            draw_block(canvas, [pos[0] + (BLOCK_SIZE * i[0]) - 50, pos[1] + (BLOCK_SIZE * i[1])], 1, BACKGROUND_COLOR, color)
         
    current_piece.draw(canvas)
    board.draw(canvas)
 
    # Game Over Check
    if not gameInPlay:
        width = frame.get_canvas_textwidth("Game Over", 50)
        canvas.draw_text("Game Over", (BOARD_UPPER_LEFT[0] + (BOARD_WIDTH * 0.50 * BLOCK_SIZE) - (width * 0.50), BOARD_UPPER_LEFT[0] + (BOARD_HEIGHT * 0.5)), 50, "Black")
 
    # Instructions
    offset = 275
    text_score = "0000" + str(score)
    text_score = text_score[-4:]
    canvas.draw_text(text_score, (BOARD_UPPER_LEFT[0], BOARD_UPPER_LEFT[1] - 25), 50, "Blue")
    canvas.draw_text("left arrow = move piece left", (BOARD_UPPER_LEFT[0] - offset, BOARD_UPPER_LEFT[1] + 20), 15, "Black")
    canvas.draw_text("right arrow = move piece right", (BOARD_UPPER_LEFT[0] - offset, BOARD_UPPER_LEFT[1] + 40), 15, "Black")
    canvas.draw_text("down arrow = move piece down", (BOARD_UPPER_LEFT[0] - offset, BOARD_UPPER_LEFT[1] + 60), 15, "Black")
    canvas.draw_text("'z' = turn piece counter clockwise", (BOARD_UPPER_LEFT[0] - offset, BOARD_UPPER_LEFT[1] + 80), 15, "Black")
    canvas.draw_text("up arrow = turn piece counter clockwise", (BOARD_UPPER_LEFT[0] - offset, BOARD_UPPER_LEFT[1] + 100), 15, "Black")
    canvas.draw_text("'x' = turn piece clockwise", (BOARD_UPPER_LEFT[0] - offset, BOARD_UPPER_LEFT[1] + 120), 15, "Black")
    canvas.draw_text("'n' = new game", (BOARD_UPPER_LEFT[0] - offset, BOARD_UPPER_LEFT[1] + 140), 15, "Black")
    canvas.draw_text("'space' = drops the piece", (BOARD_UPPER_LEFT[0] - offset, BOARD_UPPER_LEFT[1] + 160), 15, "Black")

def init():
    global board
    board = Board(BOARD_UPPER_LEFT)
 
    global piece_O
    piece_O = Piece(SHAPE_O)
 
    global piece_I
    piece_I = Piece(SHAPE_I)
 
    global piece_T
    piece_T = Piece(SHAPE_T)
 
    global piece_L
    piece_L = Piece(SHAPE_L)
 
    global piece_J
    piece_J = Piece(SHAPE_J)
 
    global piece_S
    piece_S = Piece(SHAPE_S)
 
    global piece_Z
    piece_Z = Piece(SHAPE_Z)
 
    global piece_B
    piece_B = Piece(SHAPE_ONE_BLOCK)
 
 
    global current_piece
    global pieces
 
    pieces = [SHAPE_O, SHAPE_I, SHAPE_T, SHAPE_L, SHAPE_J, SHAPE_S, SHAPE_Z]
 
    current_piece = Piece(random.choice(pieces), START_POSITION)
    global next_piece
    next_piece = Piece(random.choice(pieces), START_POSITION)
 
    global gameInPlay
    gameInPlay = True
 
    global score
    score = 0
 
    global speed
    speed = 15

def move_left_handler():
    current_piece.move_left()

def move_right_handler():
    current_piece.move_right()

def move_up_handler():
    current_piece.move_up()

def move_down_handler():
    current_piece.move_down()

def rotate_ccw_handler():
    if current_piece.isValidRotation("CCW"):
        current_piece.rotate_ccw()
 
def rotate_cw_handler():
    if current_piece.isValidRotation("CW"):
        current_piece.rotate_cw()
 
def keydown_handler(key):
    if key == simplegui.KEY_MAP["left"]:
        current_piece.move_left()
    if key == simplegui.KEY_MAP["right"]:
        current_piece.move_right()
    if key == simplegui.KEY_MAP["down"]:
        current_piece.move_down()
    if key == simplegui.KEY_MAP["up"]:
        if current_piece.isValidRotation("CCW"):
            current_piece.rotate_ccw()
    if key == simplegui.KEY_MAP["z"]:
        if current_piece.isValidRotation("CCW"):
            current_piece.rotate_ccw()
    if key == simplegui.KEY_MAP["x"]:
        if current_piece.isValidRotation("CW"):
            current_piece.rotate_cw()
    if key == simplegui.KEY_MAP["space"]:
        drop_piece_handler()
    if key == simplegui.KEY_MAP["n"]:
        new_game_handler()

def check_full_rows_handler():
    row_to_pop = None
    for row in range(BOARD_HEIGHT):
        if board.isRowFull(row):
            row_to_pop = row
    if row_to_pop != None:
        board.grid.pop(row_to_pop)
        row = [None] *  BOARD_WIDTH
        board.grid.insert(0, row)
        global score
        score += 1
        global speed
        if (score % 5) == 0:
            speed -= 2
 
def lockdown_handler():
    positions = current_piece.get_blocks()
    color = current_piece.get_color()
    for i in positions:
        board.fill([i[1], i[0]], Piece(['X', 'B', color]))

def drop_piece_handler():
    while (current_piece.move_down()):
        pass
    lockdown_handler()
    create_new_piece_handler()
         
def new_game_handler():
    init()

def create_new_piece_handler():
    global current_piece
    global next_piece
 
    current_piece = next_piece

    next_piece = Piece(random.choice(pieces), START_POSITION)

def check_ccw_handler():
    print current_piece.isValidRotateCCW()
             
frame = simplegui.create_frame("Antao", WIDTH, HEIGHT)
frame.set_canvas_background(BACKGROUND_COLOR)

frame.set_keydown_handler(keydown_handler)

frame.set_draw_handler(draw)

frame.start()

init()