This is not a post-mortem in the strictest sense of the word, but I have had a few PM’s and emails asking ‘how did you do that?’ – in reference in particular to the fact the graphical elements are injected into the HTML framework from Inform, and the AI of the opponent.
GoW TOURNAMENT is just a card game I thought was fun, and I wanted people to play. It placed slightly higher in the comp than I thought it would – most reviews were entirely correct in their assessment of ‘this is quite fun, but I’m supposed to be judging IF here!’ and I expected and was entirely ok with that – I would have written the same thing.
The graphical elements use Furkle’s excellent little framework to inject elements from Inform into the framing Javascript. I’ve written a blog post about it:
http://www.interactivefables.com/blog/worldsmith-devblog-integrating-the-parser-and-the-web-page
It is not perfect, but it really is worth experimenting with if you get the chance. I don’t think I’ve even scratched the surface of potential here. In theory, you could use Inform as a meta-language to manage entirely the front-end – specifically as a kind of user-command led wrapper around a suite of Javascript functions.
Each card has a little meta-description in the code. For example:
Scion of Uther is a GameCard. The description of it is "Arcana: Mind[line break]Name : Scion of Uther[line break]Effect : Four turns[line break]Description: Halves progress of your opponent's Lifeform towards the next stage of Evolution.[paragraph break][italic type]He was the scion of an ancient noble family; she an orphan without money or friends_*|CFICODE: './interpreter/Assets/Scion_Uther.jpg', 'Scion of Uther'|*_.[roman type]". The target_type of it is opposition. The priority of Scion of Uther is 4. The printed name of Scion of Uther is "[set link 1302]Scion of Uther[end link]".
This has the effect of replacing the image and text in the sidebar every time the description of the card is printed out in the main parser screen.
It would be interesting to see some experimentation with this. Each output in Inform could theoretically, for example be redirected to a different part of the page. Hmmmm….
The other aspect of the game that was interesting to develop was the AI. It’s actually quite a complicated thing. It’s a four-pass AI:
[code]Each turn:
- Assign Strategy to myself from aggressive, passive, builder, defender from game’s current state and the cards in hand.
- Optimise Cards – A little non-linear optimization function that prioritises each card depending on the strategy and game’s current state
- Optimise Field – Assess impact of each card on field of play.
- ……rinse and repeat recursively until an optimal choice is reached according to a fairly arbitrary ceiling[/code]
With this, the opponent can quite easily play the absolute optimal card every time – that maximizes its winning chance based on the state of play. Interestingly, this made the game too hard. It wasn’t much fun. Even when the player fully understood every mechanic of the game, and played optimally, the average win-rate was 50%.
So I had to do a ‘de-optimize’ step 5. You’ll notice that the opponent quite often will play a foolish card. Basically, every now and again, the opponent will ignore its optimized card and choose a ‘non-optimal’ card from its hand. The frequency and chance of this decreases as you progress through the competition.
The rulebook is a Twine. It is called directly from the game into a modal window using the BROWSE action. If anyone is interested, here is the code:
[code]browsing is an action applying to one thing.
Understand “browse [something]” as browsing.
Does the player mean browsing the game of worlds rulebook: it is very likely.
Check browsing:
if the noun is not the Game of Worlds Rulebook:
say “That is not browsable.” instead.
Carry out browsing:
if the noun is the Game of Worlds Rulebook:
say “You _|INCOPEN: ‘./interpreter/Assets/Rulebook.html’|_open the rulebook.”;[/code]
And here is the little javascript function that sits inside Furkle’s framework:
[code]var ROUTINES = {
‘INCOPEN’: doIncModal,
};
// Get the modal
var incmodal = document.getElementById(‘myIncModal’);
//To launch the Rulebook modal window
function doIncModal(source) {
var txtmod = document.getElementById(‘books’);
txtmod.src = source;
var modal = document.getElementById(‘myIncModal’);
modal.style.display = “block”;
}
[/code]
Finally, as a note to self - I’m adding a commandment to the canon of ‘thou should not’ for authors:
I lost count of the number of people who overlooked the Rulebook. This was my fault entirely.
Great competition. Great entries. Thanks to all who participated.
Ade.