Complete.Org: Mailing Lists: Archives: freeciv-dev: August 1999:
Re: [Freeciv-Dev] Adding scripting language
Home

Re: [Freeciv-Dev] Adding scripting language

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: Artur Biesiadowski <abies@xxxxxxxxx>
Cc: Freeciv Dev <freeciv-dev@xxxxxxxxxxxx>
Subject: Re: [Freeciv-Dev] Adding scripting language
From: Jules Bean <jmlb2@xxxxxxxxxxxxxxxx>
Date: Tue, 31 Aug 1999 23:14:35 +0100

Artur Biesiadowski wrote:
> 
> Let's talk a bit about it.
> 

Absolutely.  To quote from the perl book, 'Theres More Than One Way To
Do It'.

> As it is note on web site guile seems to be best choice. I personally
> would prefer java, but it's footprint is way too large for just
> scripting language (and it needs compiling - more mess than with fully
> interpreted language).

IMO, this is not in itself a good enough reason to disqualify java.  I
don't think a compiling step is a problem.  More worrying about java,
IMO, is the fairly 'hefty' virtual machine needed - but perhaps a
cut-down build of kaffe could be used.

> 
> Adding guile to C programs seems straigforward. Hooks into C data can be
> added incrementally - when somebody will need somthing he will just add
> needed accessor/side effect function.

True.  I think slang is supposed to be very simple to integrate with C.

Of course, just adding needed functions when somebody needs them isn't
the best way to produce an elegant or consistent design ;)


> 
> Some points where scripts can be added are obvious - for example
> can_build predicate for building with (player,city) arguments. For
> default rule (just prerequisite tech) no script will be given so normal
> code will be executed. If script is given, it will be run instead of C
> code (possibly repeating some steps from C - but sometimes it might be
> necessary to override them - for example if given building is enabled
> earlier by wonder).
> 
> Real question is how to arrange it all so guile code will execute only
> on server (as it is better to keep client simple and additionally client
> sometime will have not enough data to correctly evaluate script). For
> script with attack routine it is easy - just run on server and send
> results about units. But what with can_build predicate ?

Hmm.  Yes, this question (and similar questions, can_build is just one
example) is a very good one.  I think we will need the client to, each
time it brings up the city dialog, ask the server what can be built. 
More bandwidth, unfortunately, but I see no way around it.

> 
> My proposition is to add can_build array to city and send it with city
> data - filling on server with results of all can_build routines. It
> shouldn't be problem for network traffic (bitfield will maybe 20-30
> bytes and city packet is few times larger), but I'm not sure how it will
> affect cpu usage - after all a lot of scripts will have to be run every
> turn for every thing that changes state.

True.  It is for this reason that I favour a 'partially compiled'
language - like perl or java - since they tend to run faster.

> 
> Second big question is how to implement wonders etc - things with global
> affects. Wonder which establishes embassies with all civs is easy - just
> run script and forget. But wonder which cuts down shield cost of air
> units in half is more complicated. You can add build_cost script to air
> units and add same check for given wonder in each of them, but it's a
> bit overkill. I do not see easy way to solve this. Maybe some kind of
> event registry, so for example each time some kind of script is called
> first global overrules are checked. But with 5 global event listeners
> for build_cost, every change in city would require evaluation not of 100
> build_cost scripts, but 600 of them. Any ideas ?

(Note of English: affects is the verb.  Effects is the noun :-)

Personally (as Artur knows, and others may have gathered) I'm interested
in using FreeCiv as a test case for a simple object VM I'm working on. 
My approach would be the following:

Create an object model of the freeciv world, and carefully define
'hooks' where the C code will call methods from the object world.  For
example, we could model each unit in freeciv also with an object.  Then,
every time an object is to attack, the C code would call the method
'getAttackStrength()'.  We would need to define the parameters for the
method - certainly, the object would want to know its opponent, so that
might be a parameter.  It would also maybe want to know the terrain.

This approach - where the C code is the 'active' party, and the object
code is the 'passive' party, makes it simpler to design a clean
interface, and doesn't involve exposing the C code internals to the
object world.

On the other hand, it is inclined to be less flexible.

I then intend to layer on top of this a compiler which makes complex
idioms simple to write.  To continue the above example, some simple
units might implement getDefenceStrength() as follows: (pseudo-code,
resembling java, but my virtual machine is a bit like that inside)

# This one's for phalanx
getDefenceStrength(Opponent o) {
    return 2;
}

# This one's for Pikemen
getDefenceStrength(Opponent o) {
    return 2;
}

# This one's for Musketeers
getDefenceStrength(Opponent o) {
    return 3;
}

Now, this doesn't take into account terrain modifications.  So, we could
extend the interface to take 'Terrain' as another parameter:

# Phalanx again
getDefenceStrength(Opponent o,Terrain t) {
    if (t == mountains) {
        return 6;
    }
    if (t == forest) {
        return 4;
    }
    return 2;
}

But then we have horrible code duplication between units, which makes
the ruleset file hard to work with.  Which is where the compiler comes
in.  I envisage the compiler meaning that rules files look more like:

global terrain defence adjustments {
  mountains=3;
  forest=2;
  grassland=1;
}

mountaineer terrain defence adjustments {
  mountains=6;
}

unit phalanx { defence=2 }
unit pikemen { defence=2 }
unit musketeer { defence=3 }
unit strange_type { defence=10 adjustments=none }
unit mountain_ranger { defence=1 adjustments=mountaineer }

So that the compiler generates the code which applies the standard
adjustments to all types,  except that strange_type doesn't get any
adjustments, and mountain_ranger falls into a special class
'mountaineer' which gets different adjustments.

I am interested in any and all comments on these ideas!

Jules


-- 
/----------------+-------------------------------+---------------------\
|  Jelibean aka  | jules@xxxxxxxxxxxxxxx         |  6 Evelyn Rd        |
|  Jules aka     |                               |  Richmond, Surrey   |
|  Julian Bean   | jmlb2@xxxxxxxxxxxxxxxx        |  TW9 2TF *UK*       |
+----------------+-------------------------------+---------------------+
|  War doesn't demonstrate who's right... just who's left.             |
|  When privacy is outlawed... only the outlaws have privacy.          |
\----------------------------------------------------------------------/

[Prev in Thread] Current Thread [Next in Thread]