General scripting language

General scripting language

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

el_muchacho
Posts: 201
Joined: 30 Apr 2005, 01:06

General scripting language

Post by el_muchacho »

As this is one of the developments proposed by Fnordia, I signal the existence of an excellent lightweight embedded language created by one of the authors of "Far Cry". It's derived from Lua, but adds classes and inheritance, higher order functions, delegation, coroutines, and exceptions. The GC can be turned off.
http://squirrel.sourceforge.net


Quoting the author (who is quite trustable) :

"-size wise, compared to python, squirrel gets much smaller, depending on the compiler (gcc produces 60%/70% bigger exes than VC).
Using VC 7.1 Release, multithread DLL and Maximize speed, squirrel + standard libraries 165k I guess will be smaller without execption handling.

-performance wise you should stay around twice as fast or more compared to python, and 30% slower than lua in most of the cases.
However you regain all the speed by not having a GC messing around.
On large datasets you should get equal-better performance than lua(I haven't made any precise test).

-Memory wise, squirrel is close to lua, however class instances are much smaller than cloning lua tables (32bytes + additional 8bytes per field, methods don't count because they are shared and not stored per instance). "
Last edited by el_muchacho on 02 May 2005, 14:25, edited 2 times in total.
el_muchacho
Posts: 201
Joined: 30 Apr 2005, 01:06

Re: General scripting language

Post by el_muchacho »

doublon
Dave
Posts: 56
Joined: 28 Apr 2005, 01:44

Post by Dave »

Personally, I'd be more for Lua. The features like object orientation can be added to Lua in pure Lua, without the need to alter the codebase. Also, coroutines are not an addition - Lua 5 have them, and have had them for at least a year. And I like the way that everything in Lua is there for a good reason, as part of a coherent whole, rather than just having piled some features together.

That said, if it allows writing lua-ish code whilst adding OO and doing it efficiently, it could be a good choice. It just won't be as fast as Lua (the GC argument is pretty much void, as Lua 5.1 has incremental GC which goes much easier on the program).
renrutal
Posts: 84
Joined: 28 Apr 2005, 16:45

Post by renrutal »

Another yay for Lua, whether pure or extended.

Pros and cons:
http://gothicshredder.cjb.net/scriptinglang.html
http://lua-users.org/wiki/LuaVersusPython (nice user opinion at the bottom)

But the real question is: "What do we want exactly want from a scripting language in Spring?"
User avatar
[K.B.] Napalm Cobra
Posts: 1222
Joined: 16 Aug 2004, 06:15

Post by [K.B.] Napalm Cobra »

Twas discussed before and for various reasons of which I don't recall was rejected.
el_muchacho
Posts: 201
Joined: 30 Apr 2005, 01:06

Post by el_muchacho »

renrutal wrote: But the real question is: "What do we exactly want from a scripting language in Spring?"
True :wink:
SJ
Posts: 618
Joined: 13 Aug 2004, 17:13

Post by SJ »

In the long run I think it would be good to have a unified scripting language that could be used in all different areas, unit scripting, different kind of ai, gameplay scripting.

The different areas would require somewhat different things. The unit scripting would have to be fast and low memory since it would be required to run at least one instance (thread sort of) for each unit while the ai and gameplay scripting would need to be more general and high level.

So is there any scripting language that can do these dual tasks or will we have to continue using a special scripting language for unit scripts ?
el_muchacho
Posts: 201
Joined: 30 Apr 2005, 01:06

Post by el_muchacho »

I guess there is no way to know except than testing. BTW squirrel was designed with videogames in mind, as the author uses it in a commercial MMORPG. Coroutines are supposed to be faster than threads for task switching, but I don't know if it can handle thousands of units at a time. I am not sure a general purpose scripting language is fit for this kind of task, I'd rather leave it for the other tasks you mentionned, but the author could probably easily answer that.
renrutal
Posts: 84
Joined: 28 Apr 2005, 16:45

Post by renrutal »

SJ wrote:So is there any scripting language that can do these dual tasks or will we have to continue using a special scripting language for unit scripts ?
Dunno SJ. I'll try to post some examples from Homeworld 2, it's the closest game related to Spring with one of those languages that I can think now.

Edit: Still trying to find info about the footprint and CPU time for all this, but while I'm at it I present you some uses of a scripting language within a RTS:

How to make a ship:

http://hw2.tproc.org/wiki/VariableShip

Code: Select all

NewShipType = StartShipConfig()
--==================================================  
--NAMING AND DESCRIPTION
--==================================================  
NewShipType.displayedName = "Carrack Cruiser"
NewShipType.sobDescription = "Fast Patrol Frigate"
NewShipType.SquadronSize = 1
--==================================================  
--COST
--==================================================  
NewShipType.buildCost = 3400
NewShipType.buildTime = 43
NewShipType.buildPriorityOrder = 5
--==================================================  
--HEALTH
--==================================================  
NewShipType.mass = 350
NewShipType.maxhealth = 65088
NewShipType.regentime = 451
NewShipType.minRegenTime = 225
NewShipType.sideArmourDamage = 1
NewShipType.rearArmourDamage = 1.5
NewShipType.dustCloudDamageTime = 280
NewShipType.nebulaDamageTime = 1200
addShield(NewShipType,"EMP",22532,20)
--==================================================  
--FORMATION
--==================================================  
NewShipType.paradeData = "hgn_carrier_parade"
NewShipType.passiveFormation = "Broad"
NewShipType.defensiveFormation = "Delta"
NewShipType.aggressiveFormation = "Claw"
NewShipType.formationSpacing=200
--==================================================  
--PROPULSION
--==================================================  
NewShipType.thrusterMaxSpeed = 175
NewShipType.mainEngineMaxSpeed = 350
NewShipType.rotationMaxSpeed = 21
NewShipType.thrusterAccelTime = 3
NewShipType.thrusterBrakeTime = 1
NewShipType.mainEngineAccelTime = 3
NewShipType.mainEngineBrakeTime = 1
NewShipType.rotationAccelTime = 1
NewShipType.rotationBrakeTime = 0.5
--==================================================  
--MOVEMENT
--==================================================  
NewShipType.controllerType = "Ship"
NewShipType.thrusterUsage = 1
NewShipType.accelerationAngle = 90
NewShipType.mirrorAngle = 0
NewShipType.secondaryTurnAngle = 0
NewShipType.maxBankingAmount = 40
NewShipType.descendPitch = 80
NewShipType.goalReachEpsilon = 50
NewShipType.slideMoveRange = 500
NewShipType.relativeMoveFactor = 1
NewShipType.collisionMultiplier = 1
--==================================================  
--CLASSIFICATION
--==================================================  
NewShipType.militaryUnit = 1
NewShipType.MinimalFamilyToFindPathAround = "Destroyer"
NewShipType.BuildFamily = "Frigate_Imp"
NewShipType.AttackFamily = "Frigate"
NewShipType.DockFamily = "Frigate"
NewShipType.AvoidanceFamily = "Destroyer"
NewShipType.DisplayFamily = "Frigate"
NewShipType.AutoFormationFamily = "Frigate"
NewShipType.CollisionFamily = "Big"
NewShipType.ArmourFamily = "Hull_Cap_5D"
NewShipType.UnitCapsFamily = "Frigate"
NewShipType.unitCapsNumber = 1
--==================================================  
--SENSORS
--==================================================  
NewShipType.visualRange = 15000
NewShipType.prmSensorRange = 15000
NewShipType.secSensorRange = 15000
NewShipType.detectionStrength = 1
--==================================================  
--COMBAT
--==================================================  
NewShipType.useEngagementRanges = 1
NewShipType.retaliationRange = 8000
NewShipType.retaliationDistanceFromGoal = 5000
addAbility(NewShipType,"CanAttack",1,1,0,1,0.35,1.2,"Capturer,Corvette,Heavy_Corvette,Fighter,Utility,S  ubSystem,Emplacement,SmallCapitalShip,Frigate,Heav  y_Frigate,Destroyer,BigCapitalShip,Cruiser,SuperCa  pital,MotherShip","FlyRound_Corvette_vs_Frigate",{
Fighter = "MoveToTargetAndShoot",
},{
Corvette = "MoveToTargetAndShoot",
},{
Heavy_Corvette = "flyround_corvette_vs_frigate",
},{
Frigate = "FlyRound_Corvette_vs_CapShip",
},{
Heavy_Frigate = "FlyRound_Corvette_vs_CapShip",
},{
Destroyer = "FlyRound_Corvette_vs_CapShip",
},{
Cruiser = "flyround_Corvette_vs_Mothership",
},{
SuperCapital = "flyround_Corvette_vs_Mothership",
},{
SubSystem = "MoveToTargetAndShoot",
},{
Capturer = "MoveToTargetAndShoot",
})
addAbility(NewShipType,"GuardCommand",1,8000,1000)
--==================================================  
--UI VISIBILITY
--==================================================  
NewShipType.TOIcon="Diamond"
NewShipType.TOScale=1
NewShipType.TODistanceFade0=9000
NewShipType.TODistanceDisappear0=7000
NewShipType.TODistanceFade1=4500
NewShipType.TODistanceDisappear1=3500
NewShipType.TODistanceFade2=12000
NewShipType.TODistanceDisappear2=50000
NewShipType.TOGroupScale=1
NewShipType.TOGroupMergeSize=0
NewShipType.mouseOverMinFadeSize=0.045
NewShipType.mouseOverMaxFadeSize=0.1
NewShipType.healthBarStyle=1
--==================================================  
--MESH VISIBILITY
--==================================================  
NewShipType.nlips = 0
NewShipType.nlipsRange = 75000
NewShipType.nlipsFar = 0
NewShipType.nlipsFarRange = 0
NewShipType.SMRepresentation="HardDot"
NewShipType.meshRenderLimit = 20000
NewShipType.dotRenderLimit = 10
NewShipType.visibleInSecondary = 1
NewShipType.goblinsStartFade = 1500
NewShipType.goblinsOff = 1500
NewShipType.minimumZoomFactor = 0.5
NewShipType.selectionLimit = 400000000000
NewShipType.preciseATILimit = 0
NewShipType.selectionPriority = 100
--==================================================  
--ABILITIES
--==================================================  
addAbility(NewShipType,"MoveCommand",1,0)
addAbility(NewShipType,"WaypointMove")
addAbility(NewShipType,"HyperSpaceCommand",1,1,25,25,1,2)
addAbility(NewShipType,"CanBeCaptured",260,0.5)
addAbility(NewShipType,"CanBeRepaired")
addAbility(NewShipType,"RetireAbility",1,1)
--==================================================  
--DOCKING
--==================================================  
addAbility(NewShipType,"CanDock",1,0)
NewShipType.dockTimeBetweenTwoFormations = 1
NewShipType.dockTimeBeforeStart = 2
NewShipType.dockNrOfShipsInDockFormation = 1
NewShipType.dockFormation = "delta"
NewShipType.queueFormation = "dockline"
NewShipType.dontDockWithOtherRaceShips = 1
NewShipType.ignoreRaceWhenDocking = 0
addAbility(NewShipType,"CanLaunch")
NewShipType.launchTimeBetweenTwoFormations = 1
NewShipType.launchTimeBeforeStart = 2
NewShipType.launchNrOfShipsInDockFormation = 1
NewShipType.launchFormation = "delta"
addAbility(NewShipType,"ParadeCommand",1)
--==================================================  
--CONSTRUCTION
--==================================================  
--==================================================  
--SUBSYSTEMS
--==================================================  
LoadModel(NewShipType,1)
--StartShipHardPointConfig(NewShipType,"Shield","Hardpoint_Shield","System","Innate","Damageable","Imp_Imperator_II_Shields","","","","","","","","")
--==================================================  
--WEAPONRY
--==================================================  
StartShipWeaponConfig(NewShipType,"TurboLaser_7D","Weapon_L0","Fire_Top");
StartShipWeaponConfig(NewShipType,"TurboLaser_7D","Weapon_L1","Fire_Top");
StartShipWeaponConfig(NewShipType,"TurboLaser_7D","Weapon_L2","Fire_Bottom");
StartShipWeaponConfig(NewShipType,"TurboLaser_7D","Weapon_L3","Fire_Bottom");
StartShipWeaponConfig(NewShipType,"TurboLaser_7D","Weapon_L4","Fire_Bottom");
StartShipWeaponConfig(NewShipType,"TurboLaser_7D","Weapon_R0","Fire_Bottom");
StartShipWeaponConfig(NewShipType,"TurboLaser_7D","Weapon_R1","Fire_Top");
StartShipWeaponConfig(NewShipType,"TurboLaser_7D","Weapon_R2","Fire_Top");
StartShipWeaponConfig(NewShipType,"TurboLaser_7D","Weapon_R3","Fire_Top");
StartShipWeaponConfig(NewShipType,"TurboLaser_7D","Weapon_R4","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_L0","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_L1","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_L2","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_L3","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_L4","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_L5","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_L6","Fire_Bottom");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_L7","Fire_Bottom");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_R0","Fire_Bottom");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_R1","Fire_Bottom");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_R2","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_R3","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_R4","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_R5","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_R6","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_R7","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_T0","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_T1","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_T2","Fire_Top");
StartShipWeaponConfig(NewShipType,"Laser_2D","Weapon_T3","Fire_Top");
--==================================================  
--DEATH
--==================================================  
NewShipType.battleScarMaxTriBase = 500
NewShipType.battleScarMaxTriInc = 1000
NewShipType.sobDieTime = 4
NewShipType.sobSpecialDieTime = 1
NewShipType.specialDeathSpeed = 40
NewShipType.chanceOfSpecialDeath = 0
NewShipType.deadSobFadeTime = 0
--==================================================  
--ENGINES AND SOUND
--==================================================  
setEngineBurn(NewShipType,9,0.2,0.5,300,1.02,0.1,0  .25,380)
setEngineGlow(NewShipType,1,1,1.02,20,450,150,1.5,  {
0.27,
0.47,
0.69,
0.25,
})
loadShipPatchList(NewShipType,"data:sound/sfx/ship/Hiigaran/Frigate/",0,"Engines/HFrigateEng","",1,"Ambience/HFrigateAmb","");
--==================================================  
--MISC movement
--==================================================  
NewShipType.isTransferable = 1
NewShipType.tumbleStaticX = 0
NewShipType.tumbleStaticY = 0
NewShipType.tumbleStaticZ = 0
NewShipType.tumbleDynamicX = 1
NewShipType.tumbleDynamicY = 2
NewShipType.tumbleDynamicZ = 1
NewShipType.tumbleSpecialDynamicX = 1
NewShipType.tumbleSpecialDynamicY = 2
NewShipType.tumbleSpecialDynamicZ = 1
NewShipType.swayUpdateTime = 10
NewShipType.swayOffsetRandomX = 10
NewShipType.swayOffsetRandomY = 10
NewShipType.swayOffsetRandomZ = 10
NewShipType.swayBobbingFactor = 0
NewShipType.swayRotateFactor = 0
NewShipType.useTargetRandom = 1
NewShipType.targetRandomPointXMin = -0.5
NewShipType.targetRandomPointXMax = 0.5
NewShipType.targetRandomPointYMin = -0.5
NewShipType.targetRandomPointYMax = 0.5
NewShipType.targetRandomPointZMin = -0.5
NewShipType.targetRandomPointZMax = 0.5
--==================================================  
--AI values
--==================================================  
NewShipType.fighterValue = 0
NewShipType.corvetteValue = 0
NewShipType.frigateValue = 160
NewShipType.neutralValue = 60
NewShipType.antiFighterValue = 0
NewShipType.antiCorvetteValue = 10
NewShipType.antiFrigateValue = 120
NewShipType.totalValue = 95
Where does it load the model?

~~~~More to come.
SJ
Posts: 618
Joined: 13 Aug 2004, 17:13

Post by SJ »

renrutal: What you are talking about seems more like a replacement for the tdf files rather than the bos/cob that we are talking about.
Archangel of Death
Posts: 854
Joined: 28 Jan 2005, 18:15

Post by Archangel of Death »

Renrutal: LoadModel(NewShipType,1) loads a model of the same name in the same folder. I also notice your using the Warlords mod, good choice :wink:

A more accurate look at the lua code in Homeworld 2 would be mission gamerule, and AI scripting, thats all I can think of right now. The other stuff may have been compiled like the code, but its not actually lua. I don't think it handles the ships with lua because what it will read is hardcoded.

Also, having thousands of units in tends to slow things down, though perhaps that has to do with all the guns things tend to have. The stock game has ships with up to about a dozen guns. The Warlords mod has many ships with hundreds of guns, a few nearing 1000, but they are often grouped into single turrets.
el_muchacho
Posts: 201
Joined: 30 Apr 2005, 01:06

Post by el_muchacho »

Far Cry also uses a modified version of lua. Alberto De Michelis, the author of squirrel, is behind it. He modified lua because the garbage collector was too often in the way, sometimes slowing down the game. He wrote squirrel out of his experience with lua.

Now as for the use of a scripting language, I'd say it could be useful for IA and testing purposes (scripts that move units), as well as some elements of the user interface that don't belong to the game (online help, or options windows for example).
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Post by AF »

I wonder, is fnorida and Jouninkomiko going to allow entire skirmish AI's to be implemented in springs scripting engine
Xon
Posts: 33
Joined: 07 May 2005, 17:07

Post by Xon »

SJ wrote:So is there any scripting language that can do these dual tasks or will we have to continue using a special scripting language for unit scripts ?
Embedded Mono would work wonders for this.

With tht you can then run Java or any other .NET language under it, including Lua! :-)
el_muchacho
Posts: 201
Joined: 30 Apr 2005, 01:06

Post by el_muchacho »

From de Icaza's description, It seems that embedded Mono uses a Boehm GC, which I fear is unsuitable for realtime apps like Spring, as it will fire at any time and take unpredictable amounts of time.
Xon
Posts: 33
Joined: 07 May 2005, 17:07

Post by Xon »

el_muchacho wrote:From de Icaza's description, It seems that embedded Mono uses a Boehm GC, which I fear is unsuitable for realtime apps like Spring, as it will fire at any time and take unpredictable amounts of time.
Under Mono the only time the GC can get fired is when you allocate something. And you shouldnt be allocation happy anyway for any realtime app. Any GCed enviroment has to deal with a non-deterministic collection & time taken (which is normally proportially to how many objects it needs to handle)

With something like Lua or Python you take a significant preformace hit compared to managed or native code. Ultimately, the GC is the least of your problems.
jouninkomiko
Posts: 436
Joined: 26 Aug 2004, 08:11

Post by jouninkomiko »

imo lua or something of the sort cant be used in its current state. a scripting language needs to be more lightweight in order to avoid killing the CPU while running spring
Xon
Posts: 33
Joined: 07 May 2005, 17:07

Post by Xon »

jouninkomiko wrote:imo lua or something of the sort cant be used in its current state. a scripting language needs to be more lightweight in order to avoid killing the CPU while running spring
That would basicly mean you would need something with near-native preformance. So either using native compiled DLLs or some type of JITed managed enviroment. Ironically, you can probably make a compiled DLL which loads a bunch of managed code too.

Once I get some free time(sometime towards the end of may), I'll DL the latest spring code base and try integrating Mono into it and then exposing the various internals of Spring to the managed code. I would like to add some console code too.

Or someone else might beat me to it in testing how Spring works with using managed code.

One posible use of managed code is to JIT the COB/animation code into a managed GC codepath. This would then result in the COB/Animation interpreted code being JITed into native code :D

:edit: I've tried poking around with Mono, and it looks like it might be easy to embed under linux, but under windows I have had exactly zero luck getting it to work. I cant find any samples or even adequate instructions on how the **** I compile an application against Mono so I can start using it's embeded API.

If some of the people handling the linux port could see how hard it is todo on their side, this entier idea might need dropping :(

I know embedding any given version of the .NET framework is trivial, but that will make some work for the people trying for a linux port
Dave
Posts: 56
Joined: 28 Apr 2005, 01:44

Post by Dave »

Don't know if anyone mentionned this before, but Lua 5.1 is about to be released, with a big new feature: incremental garbage collection. This essentially eliminates the big lags you would usually experience in lua 5.0 when the GC runs through a big collection run.

Also, benchmarks conducted by various people show Lua code to be on average 10 times slower than the corresponding C code. This may seem bad, but keep in mind that anything really slow can be rewritten in C with near to no change to the Lua code, and that, well... Ten times slower than "f*cking fast" is still pretty damn good :)

Also note that most of World of Warcraft is scripted in Lua... Does TA Spring really have needs that are meaningless to WoW ?
Xon
Posts: 33
Joined: 07 May 2005, 17:07

Post by Xon »

Dave wrote:Also, benchmarks conducted by various people show Lua code to be on average 10 times slower than the corresponding C code. This may seem bad, but keep in mind that anything really slow can be rewritten in C with near to no change to the Lua code, and that, well... Ten times slower than "f*cking fast" is still pretty damn good :)
.NET/Mono code runs at almost ~95% in the general case compared to native code. Probably the biggest weakness is heavy lifting floatpoint maths in MS .NET due to them not having any floatpoint optimizations in the JITer in v1.x, this gets better in v2.0.
Also note that most of World of Warcraft is scripted in Lua... Does TA Spring really have needs that are meaningless to WoW ?
Vastly more units running around at any give time in the one area.
Post Reply

Return to “Engine”