General scripting language
Moderator: Moderators
-
- Posts: 201
- Joined: 30 Apr 2005, 01:06
General scripting language
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). "
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.
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).
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).
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?"
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?"
- [K.B.] Napalm Cobra
- Posts: 1222
- Joined: 16 Aug 2004, 06:15
-
- Posts: 201
- Joined: 30 Apr 2005, 01:06
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 ?
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 ?
-
- Posts: 201
- Joined: 30 Apr 2005, 01:06
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.
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.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 ?
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
~~~~More to come.
-
- Posts: 854
- Joined: 28 Jan 2005, 18:15
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
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.

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.
-
- Posts: 201
- Joined: 30 Apr 2005, 01:06
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).
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).
Embedded Mono would work wonders for this.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 ?
With tht you can then run Java or any other .NET language under it, including Lua!

-
- Posts: 201
- Joined: 30 Apr 2005, 01:06
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)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.
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.
-
- Posts: 436
- Joined: 26 Aug 2004, 08:11
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.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
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
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 ?
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 ?
.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.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 :)
Vastly more units running around at any give time in the one area.Also note that most of World of Warcraft is scripted in Lua... Does TA Spring really have needs that are meaningless to WoW ?