Click to return Home

  Newsreel
  Products & Services
  Web Watch
  Software Update
  Events Diary
  Articles
  The Magazine
  Subscribe
  Contact Us

  Advertisers


Writing your own strategies

It's easy to add your own strategy functions to DNJ Dilemma. A strategy function is a standard script function, written in JScript or VBScript. Its main task is to decide whether to play cooperate or defect in the current round of the game. To help it decide, it can examine its own and its opponent's plays in previous rounds of the game, and look at the round-by-round history of games in the current statistics session. However it can't examine its opponent's play in the current round, or find out how many rounds the current game will contain - that would be cheating!

Introduction
Rules
Parameters
Properties
Sample code
Installing
Offline pack

Writing strategy functions.
A strategy function must take two parameters (see below) and return a string value. The meaning of the return value depends on the call mode (see callMode parameter, below). The most important call mode is 'play', in which case the function must return a value of 'c' or 'd' (case-sensitive), indicating cooperate or defect.

A strategy function must be 'player neutral', i.e. able to operate on behalf of the left or right-hand DNJ Dilemma player. It must also be fully re-entrant, so able to play against itself in both sides of a game. These characteristics are automatic in functions which follow the guidelines set out below, and unless it particularly wants to, a function need never know which side it's playing on. 

Strategy functions must also work in both the Standard and Tournament editions of DNJ Dilemma (which is the case by default). However they can examine the game.tournament property (see below) and behave differently in the two versions.

 

The rules!

Data access. A strategy function is restricted to accessing two 'legal' data objects, plus its own local variables. The legal data objects are:

  • Player object - representing the left or right-hand player, and passed to the function via the .playerObj  parameter.
  • Game object - containing non player-specific data items (such as the .roundnum property, indicating the current round number within the game), and accessible as .game.

Functions can use local variables, and for persistent storage (within a game) can add custom properties to .playerObj. The values of custom .playerObj properties are guaranteed to persist throughout a game, but not between games. Custom properties should always be initialised at the start of each game (see 'init' mode below), as the same property names may have been used by other strategies in other games.

Functions must not:

  • Update any properties of .game, or any of the standard properties (see below) of .playerObj.
  • Access any other objects or variables in the DNJ Dilemma system. 
  • Call any functions in the DNJ Dilemma system except for genRandNum() (see below). A strategy function may, however, come with its own secondary functions (for examples, see below and the built-in Adaptive Defects function). 

 

Strategy function parameters.
Strategy functions are called with these two parameters:

Name Type Details
playerObj  Object reference Points to the data object for either the left or right-hand side player (the strategy doesn't need to know which side it is, but can examine its .me property to find out). 

The function can access properties of this object, e.g. playerObj .opponent. See below for full details of the properties of the playerObj and game objects.

callMode  String Call mode, set to one of the following (case-sensitive) values:
  • "init" - initialise mode, called at the start of each game to allow the function to initialise custom properties, choose a 'tendency to defect' percentage, etc.
  • "info" - information mode. The function should return its name (for display on-screen). Name lengths should be no more than 16 characters.
  • "play" - play mode, the function should return 'c' or 'd' (cooperate or defect - case-sensitive).

The function should return null if it receives an unrecognised callMode value.

 

Standard properties of .playerObj. 

Name Type Values
.me String  "l" or "r" indicating which player (left or right) this object refers to. 
.opponent  String "r" or "l", indicating the opposite player. 
.otherplayerobj  Object 
ref
Pointer to the opposing player object. It's legitimate to read any of the properties of this object (see .plays[] below). 
.plays[] String Array The plays (c or d) which this player has made in this game up to and including the previous round. Rounds start from 1 (.plays[0] has an indeterminate value), and the highest element with a value relevant to the current game is  playerObj.plays[game.roundnum - 1].

NOTE - by accessing playerObj.otherplayerobj.plays[], you can analyse your opponent's previous plays in this game. This is perfectly legal. Trying to access your opponent's play in the current round is highly illegal, and no use anyway, as it isn't loaded into .plays until the end of the round!

.score Int  This player's score in this game so far. Possible per-round points awards are:
Plays
Left
Scores
Right
Scores
cc 250  250
dd 50  50
cd 0 400
dc 400  0
.average Int  This player's per-round average score in this game so far.

 

Properties of .game:

Name Type Values
.roundnum Int  Current round number within the game. Round numbers start from 1. The number of rounds for each game is chosen at random, and is between 6 and 16 inclusive. Strategies can't tell how many rounds the current game will have. 
.history String  Game plays history up to the previous round. Always starts with 'xx', followed by two-character (left-right) play codes, e.g. 'xxcddccd' for three rounds. This is the same data as held in the two player objects' .plays[] arrays.
.overallscore Int  The two players' combined scores in this game so far. 
.overallaverage Int  Combined average score in this game so far. Maximum value is 800.
.selfplay Bool  true when both players are computer strategies, false when the left-hand player is the browser user (if playerObj.me == 'l' & game.selfplay == false, then something's seriously wrong!!!)
.tournament Bool true if this is DNJ Dilemma Tournament Edition, false if not.

The game object also has a set of properties which contain game-by-game results data for the current session up to the previous game. You can read these properties in order to analyse previous game patterns.

A session is an arbitrary number of games. In DNJ Dilemma Standard Edition, (game.tournament == false), the left and right hand players can change between games in a session, and the left-hand player can be a mixture of human and computer strategies. In the Tournament Edition (game.tournament == true), the left-hand player is always a computer strategy, and the same for all games in a session. 

.sgamenum Int  The game number within the current session. This is zero for the first game of the session, so game.sgamenum's value indicates the number of games completed so far. You should only access elements of the results arrays lower than [game.sgamenum] - don't bother accessing the current-game [game.sgamenum] elements, as they aren't loaded with current round data until the end of the game.
.slplayer[] String array left-side (human) player or (computer) strategy name in each game.
.srplayer[] String array right-side strategy name in each game.
.sltot[] Int array left-player total score in each game
.srtot[] Int array right-player total score in each game
.srounds[] Int array  number of rounds played in each game
.shists[] String array game history string for each game. NOTE - unlike game.history, this doesn't start with 'xx', so an example value would be 'cddddccdcdcc'.

ANY ATTEMPT TO UPDATE STANDARD OBJECT PROPERTIES, OR TO ACCESS ANY OTHER PROPERTIES OR VARIABLES IN THE MAIN GAME, IS CHEATING, AND WILL BE DEALT WITH RUTHLESSLY BY THE DNJ DILEMMA SCRUTINEERS!

 

Calling secondary functions.
Your strategy function can be accompanied by its own secondary functions. e.g.

function mystrategy (playerObj, callMode) {
......
localvar = mystrategyhelper(playerObj, callMode)
........
}

function mystrategyhelper (playerObj, callMode) {
.....
}

remember to pass playerObj and callMode to your secondary functions, if you want them to be able to access these items.

 

Calling genRandNum().
DNJ Dilemma
provides a standard function 
genRandNum(minvalue, maxvalue)
, which generates a pseudo-random integer within a specified range. For example, this statement:

var x = genRandNum(1, 20)

would load the local variable x with a random value in the range 1 to 20 inclusive. 

 

Example function code.
Here's the JScript code for DNJ Dilemma's built in Tit-for-Tat strategy function:

function tit4tat (playerObj, callMode) {

if (callMode == "init") {
  // No special initialisation process in this strategy
  return ""
}

if (callMode == "info") {
    // Return name string for screen displays
    return "Tit for Tat"
}

if (callMode == "play") {
/* 
The tit for tat strategy is simple - play "cooperate" unless your opponent has defected in the previous round
*/
if (game.roundnum == 1 ) { 
  // always cooperate on the first round
  return "c"
} else { 
  // play whatever your opponent played last time
  return playerObj.otherplayerobj.plays[game.roundnum - 1] 


} // end of play mode code

return null // default return in case of an unrecognised callMode value

} // END OF TIT-FOR-TAT STRATEGY FUNCTION

Adding a strategy function to DNJ Dilemma 

1. Developing strategies locally
You can test your strategy functions by downloading the DNJ Dilemma Offline Pack (see below) and adding it to your local copy of the system. When it's ready, you can mail it to DNJ Online, and if it's suitable, we'll add it to the online version of DNJ Dilemma.

2. Where to put your strategy code - Strategy/frameset documents.
DNJ Dilemma Strategy functions are held in an unusual place - a frameset definition document that opens the main game page in a full-width frame. The strategy functions (plus some system code) are held in a <script> in the <head> section of the document. There's no <body>, just another script that generates a frameset which loads either the Standard or Tournament edition game page into a frame occupying 100% of the browser width.

To tell the strategy/frameset document which edition of the game to load, you supply it with a parameter. This is built into the hyperlink that loads it from the menu page. Here are examples:

<a href="dnjdmstrats.htm?dnjdmstd.htm">DNJ Dilemma Standard Edition</a>

<a href="dnjdmstrats.htm?dnjdmtourn.htm">DNJ Dilemma Tournament Edition</a>

In both cases "dnjdmstrats.htm" is the name of the strategy/frameset document; "dnjdmstd.htm" is the Standard edition game page, while "dnjdmtourn.htm" is the Tournament edition. 

This system makes it easy to test alternative strategy files - just set up a test menu page with links such as:

<a href="teststrats.htm?dnjdmstd.htm">DNJ Dilemma Standard Edition with test strategy file</a>

Adding your strategy functions to a strategy/frameset document.
To test your strategies using your local copy of the DNJ Dilemma system (see below), first make a copy of the default strategy/frameset document "dnjdmstrats.htm", and add a hyperlink to it to the menu page "dnjdilemma.htm" (see above for the format of the link).

Now you can add your strategy function(s) to the strategy/frameset document.

Here's an overview of the strategy/frameset document structure:

<HTML>
<HEAD>
<script>
// system functions - do not edit! -------
etc...
// end of system code block

// strategy pointer array builder - add your new strategy function 
// to this list
stratfunctionpointers = new Array(tit4tat, randomDefects,... 

// strategy functions
// Standard strategy functions
function tit4tat () { etc....

// ADD YOUR STRATEGY FUNCTION CODE HERE

// end of strategy functions

</script>
</HEAD>
<script>
// frameset generating code - do not edit!
document.write("<frameset etc...
</script>
</HTML>

As long as you only make changes in the green areas, you won't go too far wrong!

Adding a JScript strategy function to a  strategy document is simple:

  1. Paste the function(s) into the document's <script><script> block (see above), or add a separate script block of your own to the <HEAD> section, AFTER the main script block.
  2. Find the statement which begins:

    stratfunctionpointers = new Array(tit4tat, randomDefects, ... etc

  3. Add the name of your function to the list, like this:

    stratfunctionpointers = new Array(tit4tat, mystratfunction, random... etc

Note that you don't put the function name in "" marks, and don't include () brackets.

Adding a VBScript function to the library is simple too, but does require an additional step.

Internet Explorer won't let you point a JScript variable or array element (such as stratfunctionpointers[]) directly at a VBScript function, so you have to use a JScript function as an intermediary. For example, if your VBScript function was called alwaysDefect, then you'd do this:

<SCRIPT LANGUAGE="JAVASCRIPT">
etc...
stratfunctionpointers = new Array(tit4tat, JSalwaysDefect, random... etc
etc...
function JSalwaysDefect (playerObj, callMode) {
  return alwaysDefect(playerObj, callMode)
}
</SCRIPT>

<SCRIPT LANGUAGE="VBScript">
function alwaysDefect(playerObj, callMode) 
etc...
End Function
</SCRIPT>

The JScript function JSalwaysDefect() is registered in stratfunctionpointers[] as the strategy function, but simply returns whatever is returned by its call to the VB function alwaysDefect(). Note that the JScript and VBScript functions should have different names.

 

Downloading the DNJ Dilemma Offline Pack.
To enable you to develop strategy functions locally, we've put copies of the entire DNJ Dilemma system (including these Help pages) into downloadable archive files.

Once you've downloaded the archive, just unzip it into a folder on your local disk, then open index.htm to run DNJ Dilemma. The system only works in Microsoft Internet Explorer 4.0 or later.

Click here to download dnjdmoffline.zip (ZIP archive, requires PKUNZIP or equivalent.

Click here to download dnjdmoffline.exe (self-extracting ZIP archive, requires Windows 95/98/NT/2000).

Top of page
   Exit help

 

Copyright © 2001 Matt Publishing Limited. All rights reserved. No part of this site may be reproduced without the prior consent of the copyright holder.











Introduction

Rules of the game

Starting the game

Playing the game

Game statistics

Your objectives

Strategies Primer

Writing strategies

Exit