# source:experiments/frams/deathmatch/data/scripts/deathmatch.expdef@231

Last change on this file since 231 was 231, checked in by sz, 10 years ago

Deathmatch experiment - http://www.framsticks.com/deathmatch

File size: 23.9 KB
Line
1expdef:
2name:Deathmatch
3info:~
4This experiment simulates a team deathmatch. It means that framstick creatures are grouped in teams and the basic rule is: "My team vs WORLD!".
5
6The basic battle rules and collectibles are implemented. Statistics for the battle are saved to text files in CSV format: creatures.txt, teams.txt.
7
9~
10code:~
11
12//Author: Mateusz Cicheñski @ Poznan University of Technology, 2012
13
14@include "deathmatch-utils.inc"
15@include "deathmatch-levels.inc"
16
17global idleSimulationSteps;
18global battleNumber;
19global teams;
20
22{
23  idleSimulationSteps = 0;
24  battleNumber = 0;
25  initLevels();
26  initPopulations();
27
28  Shapes.set("1p_weaponbox","//0\n"+
29  "p:-0.5, -0.5, -0.5\n"+
30  "p: 0.5, -0.5, -0.5\n"+
31  "p: 0.5, 0.5, -0.5\n"+
32  "p: -0.5, 0.5, -0.5\n"+
33  "p:-0.5, -0.5, 0.5\n"+
34  "p:0.5, -0.5, 0.5\n"+
35  "p:0.5, 0.5, 0.5\n"+
36  "p:-0.5, 0.5, 0.5\n"+
37  "j: 0,1\n"+
38  "j: 1,2\n"+
39  "j: 2,3\n"+
40  "j: 3,0\n"+
41  "j: 4,5\n"+
42  "j: 5,6\n"+
43  "j: 6,7\n"+
44  "j: 7,4\n"+
45  "j: 0,4\n"+
46  "j: 1,5\n"+
47  "j: 2,6\n"+
48  "j: 3,7", 0x0FAA0F);
49
50  Shapes.set("1p_hpbox","//0\n"+
51  "p:-0.5, -0.5, -0.5\n"+
52  "p: 0.5, -0.5, -0.5\n"+
53  "p: 0.5, 0.5, -0.5\n"+
54  "p: -0.5, 0.5, -0.5\n"+
55  "p:-0.5, -0.5, 0.5\n"+
56  "p:0.5, -0.5, 0.5\n"+
57  "p:0.5, 0.5, 0.5\n"+
58  "p:-0.5, 0.5, 0.5\n"+
59  "j: 0,1\n"+
60  "j: 1,2\n"+
61  "j: 2,3\n"+
62  "j: 3,0\n"+
63  "j: 4,5\n"+
64  "j: 5,6\n"+
65  "j: 6,7\n"+
66  "j: 7,4\n"+
67  "j: 0,4\n"+
68  "j: 1,5\n"+
69  "j: 2,6\n"+
70  "j: 3,7", 0xAA0F0F);
71}
72
73function initPopulations()
74{
75  //clear anything in populations
76  Populations.clear();
77
78  //add Food population (group 0)
79  Population.name = "Food";
80  Population.nnsim = 0;
81  Population.enableperf = 0;
82  Population.death = 1;
83  Population.energy = 1;
86
89  Population.nnsim = 0;
90  Population.enableperf = 0;
91  Population.death = 1;
92  Population.energy = 1;
95
96  //add Teams populations (group above 2)
97  var i = 0;
98  teams = ExpParams.teamCount;
99  if (teams == 1) {
100        GenePools.group = 0;
101        teams = GenePool.size;
102  }
103  for (i = 0; i < teams; i++)
104  {
106    Population.nnsim = 1;
107    Population.enableperf = 1;
108    Population.death = 0;
109    Population.energy = 1;
112  }
113
114  //Collisions on 32 bit mask:
115  // standard - rebound creatures => if lower bits 0xFFFF
116  // custom - custom function handler => if higher bits 0xFFFF0000
117  //Collisions map:
118  // Food vs Food = 0x20002 & 0x10002 = 2 - standard
119  // Upgrades vs Upgrades = 0x20002 & 0x10002 = 2 - standard
120  // Team X vs Team X = 0x50001 & 0x60001 = 0x40001 - standard + custom
121  // Team X vs Team Y = 0x50001 & 0x60001 = 0x40001 - standard + custom
122  // Food vs Upgrades = 0x20002 & 0x10002 = 2 - standard
123  // Food vs Team X = 0x20002 & 0x60001 = 0x20000 || 0x50001 & 0x10002 = 0x10000 - custom
124  // Upgrades vs Team X = 0x20002 & 0x60001 = 0x20000 || 0x50001 & 0x10002 = 0x10000 - custom
125}
126
127function initCreatures()
128{
129  var i = 0;
130  var j = 0;
131  GenePools.group = 0;
132  for (i = 0; i < Populations.size - 2; i++)
133  {
134    Populations.group = i + 2;
135        for (j = 0; j < ExpParams.teamSize; j++)
136        {
137          if (ExpParams.teamCount != 1)
138                GenePools.genotype = Math.random(GenePool.size);
139          else
140            GenePools.genotype = i;
141          Population.createFromGenotype();
142          Creature.name = "Member " + j;
143        }
144  }
145}
146
147function onExpInit()
148{
149  battleNumber = 0;
150  initAll();
151}
152
153function initAll()
154{
155  idleSimulationSteps = 0;
156  battleNumber += 1;
157  initLevel();
158  initPopulations();
159  initCreatures();
160  initFiles();
161  writeTeamStatistics();
162}
163
164function initFiles()
165{
166  var f=File.createDirect("creatures"+battleNumber+".txt","Creature statistics");
167  f.writeString("#Creature name; Team; Kills; Assists; Total damage dealt; Total damage received; HP boxes collected; Upgrade boxes collected; Lifespan\n");
168  f.close();
169
170  var s = "#Time interval; ";
171  var i = 0;
172  for (i = 0; i < Populations.size - 2; i++)
173  {
174    s += "Team " + i + "; ";
175        s += "Team members; ";
176  }
177  s += "Total energy\n";
178
179  var f=File.createDirect("teams"+battleNumber+".txt","Teams statistics");
180  f.writeString(s);
181  f.close();
182}
183
184function initLevel()
185{
186  var levelNumber;
187  if (ExpParams.level == -1)
188    levelNumber = Math.random(levels.size);
189  else
190    levelNumber = ExpParams.level;
191
192  var level = levels.get(levelNumber);
193  Simulator.print("Level #" + (levelNumber + 1) + ": " + level[0]);
194
195  World.wrldbnd = level[2];
196  World.wrldsiz = level[1];
197  World.wrldwat = -1;
198  World.wrldtyp = level[3];
199  World.wrldmap = level[4];
200
201  World.wrldchg();
202}
203
204function tryCreateHPBox()
205{
206  Populations.group = 0;
207
208  if (Population.size >= ExpParams.hpBoxTotalCount) return;
209
210  if (Math.rnd01 > ExpParams.hpBoxProbability) return;
211
212  var food = Populations.createFromString("//0\nm:Vstyle=hpbox\np:");
213  food.name = "HP Box";
214  food.idleen = ExpParams.hpBoxIdleEnergy;
215  food.energ0 = ExpParams.hpBoxStartingEnergy;
216  food.energy = food.energ0;
217  food.nnenabled = 0;
218}
219
221{
222  Populations.group = 1;
223
224  if (Population.size >= ExpParams.upgradeBoxTotalCount) return;
225
226  if (Math.rnd01 > ExpParams.upgradeBoxProbability) return;
227
228  var weapon = Populations.createFromString("//0\nm:Vstyle=weaponbox\np:");
229  weapon.name = "Weapon Box";
232  weapon.energy = weapon.energ0;
233  weapon.nnenabled = 0;
234}
235
236//handle creature placement in the world
237function onBorn()
238{
239  // place newly born creature
240  var retry = 20; //try 20 times
241  var placed_ok = 0;
242  while (retry-- && !placed_ok)
243  {
244    switch (Populations.group)
245    {
246    case 0: //food placement
248      break;
251      break;
252    default:
253          Creature.user1 = Vector.new();
256          Creature.user2 = Vector.new();
259          Creature.user2.add(0); //total damage dealt (2)
261          Creature.user2.add(0); //HP boxes collected (4)
263          Creature.user3 = Vector.new(); //who dealt damage to this creature
264          Creature.energ0 = ExpParams.creatureStartingEnergy;
265          Creature.energy = Creature.energ0;
266      place_inTeamSpot();
267      break;
268    }
269
270    if (!Populations.creatBBCollisions(0))
271      placed_ok = 1;
272  }
273  if (!placed_ok)
274    print("onBorn() could not avoid collisions.");
275}
276
277//place creature in random spot and make it head center of the map
279{
280  var x, y, z;
281  x = (World.wrldsiz - Creature.size_x) * Math.rnd01 - Creature.size_x / 2;
282  y = (World.wrldsiz - Creature.size_y) * Math.rnd01 - Creature.size_y / 2;
283  z = WorldMap.getHeight(x, y);
284
285  var hx = 0.0 + (World.wrldsiz / 2) - x;
286  var hy = 0.0 + (World.wrldsiz / 2) - y;
287  var alpha_rad = vectorsAngle([1.0, 0.0], [hx, hy]);
288
290  Creature.moveAbs(x, y, z - 0.999);
291
292  print("Creature placed in [" + x +" " + y + " " + z);
293
294  return ;
295}
296
297//Place creature in correct team spot (valid for Team creatures only)
298//Creatures are placed in circle with random rotation (commented out: heading center of the map) in their respective team groups
299function place_inTeamSpot()
300{
301  var radius = 360.00 * (Populations.group - 1) / teams;
302
303  var x, y, z;
304  x = (ExpParams.teamSpawningAreaSize) * Math.rnd01 - Creature.size_x / 2 - ExpParams.teamSpawningAreaSize/2;
305  y = (ExpParams.teamSpawningAreaSize) * Math.rnd01 - Creature.size_y / 2 - ExpParams.teamSpawningAreaSize/2;
306
307  //vector of length half the world size minus spawning area size
308  var vect = [0.0 + World.wrldsiz/2 - ExpParams.teamSpawningAreaSize/2 - 1.0, 0.0];
310
311  //translate creature by given vector
312  //then translate by halfworld (as it is the center of the world
313  //and the positions were calculated for point [0,0]
314  x = x + vect[0] + World.wrldsiz/2;
315  y = y + vect[1] + World.wrldsiz/2;
316
317  z = WorldMap.getHeight(x, y);
318
319  var alpha_rad = 360.0 * Math.rnd01; //random rotation
320
321  //this would rotate creatures so that they would face the world center:
322  //var hx = 0.0 + (World.wrldsiz / 2) - x;
323  //var hy = 0.0 + (World.wrldsiz / 2) - y;
324  //var alpha_rad = vectorsAngle([1.0, 0.0], [hx, hy]);
325
327  //place it mid-air
328  Creature.moveAbs(x, y, z);
329
330  return ;
331}
332
333// ////////////////////////////////
334// Simulation steps
335
336function onStep()
337
338  idleSimulationSteps += 1;
339  tryCreateHPBox();
341
342  lowerCooldownCounters();
343  applySuddenDeathModifier();
344
346  checkGameState();
347}
348
349function writeTeamStatistics()
350{
351  var s = "" + Simulator.time + "; ";
352  var i = 0;
353  var j = 0;
354  var total = 0.0;
355  for (i = 0; i < Populations.size - 2; i++)
356  {
357    Populations.group = i + 2;
358        var sum = 0.0;
359        for (j = 0; j < Population.size; j++)
360        {
361          Populations.creature = j;
362          sum += Creature.energy;
363        }
364    s += "" + sum + "; ";
365        s += "" + Population.size + "; ";
366        total += sum;
367  }
368  if (total < 0) total == 0;
369  s += "" + total + "\n";
370
371  var f=File.appendDirect("teams"+battleNumber+".txt","Teams statistics");
372  f.writeString(s);
373  f.close();
374}
375
377{
378  var i = 0;
379  var j = 0;
380  for (i = 0; i < Populations.size - 2; i++)
381  {
382    Populations.group = i + 2;
383        for (j = 0; j < Population.size; j++)
384        {
385      Populations.creature = j;
386      if (Creature.energy <= 0) Populations.killSelected();
387        }
388  }
389}
390
391function applySuddenDeathModifier()
392{
393  if (idleSimulationSteps < ExpParams.stagnationInterval) return;
394
395  var i = 0;
396  var j = 0;
397  for (i = 0; i < Populations.size - 2; i++)
398  {
399    Populations.group = i + 2;
400        for (j = 0; j < Population.size; j++)
401        {
402          Populations.creature = j;
403          Creature.energy -= ExpParams.stagnationHealthReduce;
404        }
405  }
406}
407function lowerCooldownCounters()
408{
409  var i = 0;
410  var j = 0;
411  for (i = 0; i < Populations.size - 2; i++)
412  {
413    Populations.group = i + 2;
414        for (j = 0; j < Population.size; j++)
415        {
416          Populations.creature = j;
417          if (Creature.user1 != null)
418          {
419            if (Creature.user1.get(0) > 0) Creature.user1.set(0, Creature.user1.get(0) - 1);
420            if (Creature.user1.get(0) < 0) Creature.user1.set(0,0.0);
421            if (Creature.user1.get(1) > 0) Creature.user1.set(1, Creature.user1.get(1) - ExpParams.upgradeBoxDecay);
422            if (Creature.user1.get(1) < 0) Creature.user1.set(1,0.0);
423          }
424        }
425  }
426}
427
428function checkGameState()
429{
430  var i = 0;
431  var alivePop = 0;
432  for (i = 0; i < Populations.size - 2; i++)
433  {
434    Populations.group = i + 2;
435        if (Population.size > 0) alivePop += 1;
436  }
437
438  if (alivePop == 0 && Simulator.time <= 1)
439  {
440    onExpInit(); //do initialization for user, because he forgot to do so
441        return;
442  }
443
444  if (alivePop <= 1)
445  {
446    for (i = 0; i < Populations.size - 2; i++)
447    {
448      Populations.group = i + 2;
449          if (Population.size > 0)
450          {
451            Simulator.print("Battle is OVER! The winner is: " + Population.name);
452
453                //write stats of last living creatures
454                var f=File.appendDirect("creatures"+battleNumber+".txt","Creature statistics");
455                var j = 0;
456                for (j = 0; j < Population.size; j++)
457                {
458                  Populations.creature = j;
459                  //f.writeString("Creature name; Team; Kills; Assists; Total damage dealt; Total damage received; HP boxes collected; Upgrade boxes collected; Lifespan");
460                  if (Creature.user2 != null)
461                    f.writeString(Creature.name + "; " + Population.name + "; " + Creature.user2.get(0) + "; " + Creature.user2.get(1) + "; " + Creature.user2.get(2) + "; " + Creature.user2.get(3) + "; " + Creature.user2.get(4) + "; " + Creature.user2.get(5) + "; " + Creature.lifespan + "\n");
462                }
463
464                f.close();
465          }
466    }
467        if (alivePop == 0) Simulator.print("Battle is OVER! Total annihilation!");
468
469        Simulator.stop();
470  }
471}
472
473function print(msg)
474{
475  if (ExpParams.debug)
476    Simulator.print(msg);
477}
478
479function stop(msg)
480{
481  Simulator.print(msg);
482  Simulator.stop();
483}
484
485// ////////////////////////////
486// Collisions
487
488//function executed on any Creature collission
489function onTeam0CrCollision, onTeam1CrCollision, onTeam2CrCollision, onTeam3CrCollision, onTeam4CrCollision, onTeam5CrCollision, onTeam6CrCollision, onTeam7CrCollision, onTeam8CrCollision, onTeam9CrCollision()
490{
491  var c1 = CrCollision.Creature1;
492  var c2 = CrCollision.Creature2;
493
494  if (c1 == null) stop("2");
495  if (c2 == null) stop("2");
496
497  if (c1.energy <= 0 || c2.energy <= 0)
498  {
499    //collision with already killed creature (chain resolution)
500        print("onCrCollision called with less than 2 Creatures");
501        return ;
502  }
503
504  if (c1.group == null || c2.group == null)
505  {
506    //collision of creature without a group
507        print("onCrCollision called for creature without group, ignoring");
508        return ;
509  }
510
511  //first condition should never occur, but who knows?
512  if (c1.group.index < 2 || c2.group.index < 2)
513  {
514    //collision with HP Box and Upgrades are handled separately
515        print("onCrCollision called for population 0 or 1, ignoring");
516        return ;
517  }
518
519  idleSimulationSteps = 0;
520
521  var kill_c1 = 0;
522  var kill_c2 = 0;
523  var dice1 = 0;
524  var dice2 = 0;
525  var changed = 0;
526  var i = 0;
527  for (i = 0; i < ExpParams.diceCount; i++)
528  {
529    dice1 = dice1 + Math.random(ExpParams.diceSides) + 1;
530        dice2 = dice2 + Math.random(ExpParams.diceSides) + 1;
531  }
532  var energy1 = 0.0 + ExpParams.creatureDamage * dice1;
533  var energy2 = 0.0 + ExpParams.creatureDamage * dice2;
534  energy1 += ExpParams.upgradeMultiplier * c1.user1.get(1);
535  energy2 += ExpParams.upgradeMultiplier * c2.user1.get(1);
536  if (c1.group == c2.group)
537  {
538    energy1 = ExpParams.friendlyFireDamageMultiplier * energy1;
539        energy2 = ExpParams.friendlyFireDamageMultiplier * energy2;
540  }
541
542  if (c1.user1 == null) stop("3");
543  if (c1.user2 == null) stop("3");
544  if (c1.user3 == null) stop("3");
545  if (c2.user1 == null) stop("3");
546  if (c2.user2 == null) stop("3");
547  if (c2.user2 == null) stop("3");
548
549  if (c2.user1.get(0) <= 0 && energy2 > 0)
550  {
551    changed = 1;
552
553    c1.energy = c1.energy - energy2;
554        if (c1.energy < 0) c1.energy = 0;
555    print(c2.name + " [" + c2.group.name + "] rolled " + dice2 + " and dealt " + energy2 + " [+" + (ExpParams.upgradeMultiplier * c2.user1.get(1)) +" bonus] damage to " + c1.name + " [" + c1.group.name + "]");
556        c2.user1.set(0, ExpParams.attackCooldown);
557        c2.user2.set(2, c2.user2.get(2) + energy1);
558        c1.user2.set(3, c1.user2.get(3) + energy1);
559        var vect = Vector.new();
562        var arrindex = arrayContains(c1.user3, 0, c2.uid);
563        if (arrindex != -1)
564        {
566          c1.user3.set(arrindex, vect);
567        }
568        else
569        {
571          if (c1.user3 == null) c1.user3 = Vector.new();
573          if (c1.energy > 0)
574          {
575        c2.user2.set(1, c2.user2.get(1) + 1); //increase assists statistic
576          }
577        }
578        if (c1.energy <= 0)
579        {
580          c2.user2.set(0, c2.user2.get(0) + 1); //increase kills statistic
581          kill_c1 = 1;
582        }
583  }
584
585  if (c1.user1.get(0) <= 0 && energy1 > 0)
586  {
587    changed = 1;
588
589    c2.energy = c2.energy - energy1;
590        if (c2.energy < 0) c2.energy = 0;
591    print(c1.name + " [" + c1.group.name + "] rolled " + dice1 + " and dealt " + energy1 + " [+" + (ExpParams.upgradeMultiplier * c1.user1.get(1)) +" bonus] damage to " + c2.name + " [" + c2.group.name + "]");
592    c1.user1.set(0, ExpParams.attackCooldown);
593        c1.user2.set(2, c1.user2.get(2) + energy1);
594        c2.user2.set(3, c2.user2.get(3) + energy1);
595        var vect = Vector.new();
598        var arrindex = arrayContains(c2.user3, 0, c1.uid);
599        if (arrindex != -1)
600        {
602          c2.user3.set(arrindex, vect);
603        }
604        else
605        {
607          if (c2.user3 == null) c2.user3 = Vector.new();
609          if (c2.energy > 0)
610          {
611        c1.user2.set(1, c1.user2.get(1) + 1); //increase assists statistic
612          }
613        }
614        if (c2.energy <= 0)
615        {
616          c1.user2.set(0, c1.user2.get(0) + 1); //increase kills statistic
617          kill_c2 = 1;
618        }
619  }
620
621  if (changed == 1)
622  {
623    writeTeamStatistics();
624  }
625
626  //resolve kills
627  if (kill_c1 == 1)
628  {
629    Populations.group = c1.group.index;
630    Populations.creature = c1.group.findUID(c1.uid);
631        if (Populations.creature == -1) stop("4");
632    Populations.killSelected();
633  }
634  if (kill_c2 == 1)
635  {
636    Populations.group = c2.group.index;
637    Populations.creature = c2.group.findUID(c2.uid);
638        if (Populations.creature == -1) stop("4");
639    Populations.killSelected();
640  }
641}
642
643//function executed on collision with Food population group
644function onFoodCollision()
645{
646  if (ExpParams.pickupNotStagnation == 1) idleSimulationSteps = 0;
647
648  //collect HP Box (by eating it :D)
649  print(Collision.Creature2.name + " [" + Collision.Creature2.group.name + "] picked a HP box");
650  Collision.Creature2.user2.set(4, Collision.Creature2.user2.get(4) + 1);
651  Collision.Creature1.energy_m = Collision.Creature1.energy_m + Collision.Creature1.energy;
652  Collision.Creature2.energy_p = Collision.Creature2.energy_p + Collision.Creature1.energy;
653
654  //kill HP Box
655  Populations.group = Collision.Creature1.group.index;
656  Populations.creature = Collision.Creature1.group.findUID(Collision.Creature1.uid);
657  Populations.killSelected();
658
659  writeTeamStatistics();
660}
661
662//function executed on collision with Upgrade population group
664{
665  if (ExpParams.pickupNotStagnation == 1) idleSimulationSteps = 0;
666
667  //collect Upgrade Box (by eating it :D)
668  print(Collision.Creature2.name + " [" + Collision.Creature2.group.name + "] picked an upgrade box");
669  Collision.Creature2.user2.set(5, Collision.Creature2.user2.get(5) + 1);
670  Collision.Creature1.energy_m = Collision.Creature1.energy_m + Collision.Creature1.energy;
671  Collision.Creature2.user1.set(1, Collision.Creature2.user1.get(1) + Collision.Creature1.energy);
672
674  Populations.group = Collision.Creature1.group.index;
675  Populations.creature = Collision.Creature1.group.findUID(Collision.Creature1.uid);
676  Populations.killSelected();
677
678  writeTeamStatistics();
679}
680
681//function executed on Creature death
682//TODO: implement some statistics for dieing creature
683function onDied()
684{
685  //ignore death of hp boxes and upgrades
686  if (Populations.group < 2)
687   return ;
688
689  print(Creature.name + " was killed");
690  var i = 0;
691  for (i = 0; i < Creature.user3.size; i++)
692  {
693    print(Creature.user3.get(i).get(1) + " dealt " + Creature.user3.get(i).get(2) + " damage");
694  }
695
696  var f=File.appendDirect("creatures"+battleNumber+".txt","Creature statistics");
697  //f.writeString("Creature name; Team; Kills; Assists; Total damage dealt; Total damage received; HP boxes collected; Upgrade boxes collected; Lifespan");
698  f.writeString(Creature.name + "; " + Population.name + "; " + Creature.user2.get(0) + "; " + Creature.user2.get(1) + "; " + Creature.user2.get(2) + "; " + Creature.user2.get(3) + "; " + Creature.user2.get(4) + "; " + Creature.user2.get(5) + "; " + Creature.lifespan + "\n");
699  f.close();
700
701  writeTeamStatistics();
702}
703
704// ////////////////////////////
705// ExpParams setters
706
707//reinit populations on change
708function ExpParams_teamCount_set()
709{
710  initPopulations();
711}
712
713function ExpParams_level_set()
714{
715  initLevel();
716}
717~
718
719# ################################
720# Team
721
722prop:
723id:teamCount
724name:Number of teams in Deathmatch
725type:d 1 10 1
726group:Team
727help:If set to 1, the number of teams will be equal to the number of genotypes in gene pool.
728
729prop:
730id:teamSize
731name:Number of creatures per team
732type:d 1 10 5
733group:Team
734
735prop:
736id:teamSpawningAreaSize
737name:Spawning area size for team
738type:f 10 30 20
739group:Team
740
741prop:
742id:creatureStartingEnergy
743name:Starting energy of creature
744type:f 0 1000 300
745group:Team
746help:Base starting energy level for each creature in teams
747
748# ################################
749# Attack parameters
750
751prop:
752id:diceSides
753name:Number of sides of dices
754type:f 1 10 1
755group:Attack rules
756
757prop:
758id:diceCount
759name:Number of dices to roll per attack
760type:f 0 10 5
761group:Attack rules
762
763prop:
764id:creatureDamage
765name:Basic damage multiplied by result of dice roll
766type:f 0 100 10
767group:Attack rules
768
769prop:
770id:friendlyFireDamageMultiplier
771name:Multiplier of energy taken when Creatures of the same team collide
772type:f 0 1 0.0
773group:Attack rules
774help:Set to 0 for no friendly fire, set to 1 if full damage should be dealt when interacting with team member
775
776prop:
777id:attackCooldown
778name:Number of simulation steps between two consecutive attacks of a creature
779type:f 100 10000 1000
780group:Attack rules
781help:Set this to 100 to nearly instantly resolve battles
782
783# ################################
784# Collectibles - HP Boxes & Upgrades
785
786prop:
787id:pickupNotStagnation
788name:Collectible pick-up resets stagnation counter?
789type:d 0 1 1
790help:If set to true picking up an item will restart counting towards stagnation, effects in longer battles.
791
792prop:
793id:hpBoxStartingEnergy
794name:Starting energy of HP Box
795type:f 0 1000 100
796group:Collectibles
797help:Base starting energy level for HP Box
798
799prop:
800id:hpBoxIdleEnergy
801name:Amount of energy lost by HP Box
802type:f 0 10 0.00
803group:Collectibles
804help:How much energy HP Box looses each step (0 - it will not disappear)
805
806prop:
807id:hpBoxProbability
808name:Probablity that new HP Box will spawn
809type:f 0 1 0.0005
810group:Collectibles
811help:Probability of HP Box appearing each step of simulation
812
813prop:
814id:hpBoxTotalCount
815name:Maximum number of HP Boxes on the field
816type:d 0 20 10
817group:Collectibles
818help:The total number of HP Boxes on the field will never exceed this number
819
820prop:
823type:f 0 1000 500
824group:Collectibles
825help:Base starting energy level for Upgrade Box
826
827prop:
829name:Amount of energy lost by Upgrade Box
830type:f 0 10 0.00
831group:Collectibles
832help:How much energy Upgrade Box looses each step (0 - it will not disappear)
833
834prop:
836name:Probablity that new Upgrade Box will spawn
837type:f 0 1 0.0005
838group:Collectibles
839help:Probability of Upgrade Box appearing each step of simulation
840
841prop:
843name:Maximum number of Upgrade Boxes on the field
844type:d 0 20 10
845group:Collectibles
846help:The total number of Upgrade Boxes on the field will never exceed this number
847
848prop:
851type:f 0 10 0.1
852group:Collectibles
853help:Each step creature damage bonus will be decreased by given amount until it reaches 0
854
855prop:
857name:Multiplier of bonus damage
858type:f 0 1 0.1
859group:Collectibles
860help:Value of collected bonus multiplied by this variable is taken as bonus damage
861
862# ################################
863# Other
864
865prop:
866id:level
867name:Level
868type:d -1 2 0
869help:Number of a level to battle (-1 is random)
870
871prop:
872id:stagnationInterval
873name:Number of idle simulation steps before Sudden Death
874type:d 0 10000 5000
875help:If no combat occurs during given number of steps, the Sudden Death mode is turned on (0 = Sudden Death all the time)
876
877prop:
878id:stagnationHealthReduce
879name:Sudden Death health reduce
880type:f 0 100 0.1
881help:If Suddent Death is turned on, creatures will lose given amount of HP each simulation step
882
883prop:
884id:debug