expdef: name:Capture The Flag game info:~ A simple Capture The Flag game. Read more at http://www.framsticks.com/capture-the-flag ~ code:~ //Flag positions global flagsX; global flagsY; //global log; //Sum of team points and events global points; global scored; global taken; global retrieved; function onExpDefLoad() { GenePools.clear(); Populations.clear(); World.wrldsiz = 100; World.wrldtyp = 0; World.wrldbnd = 2; //Teleport ExpProperties.memberssno = 4; ExpProperties.teamsno = 2; ExpProperties.mindistance = 60; ExpProperties.pointsCapture = 10; ExpProperties.pointsRetrieve = 5; ExpProperties.pointsScoring = 50; //Styles of flags Shapes.set("1p_flag0","lllX(X, RRllX(, RRllX(, (X, lllX, X),), LLLLLLLX(,, llllX)), X)", 0xFF0000); Shapes.set("1p_flag1","lllX(X, RRllX(, RRllX(, (X, lllX, X),), LLLLLLLX(,, llllX)), X)", 0x0000FF); Shapes.set("1p_flag2","lllX(X, RRllX(, RRllX(, (X, lllX, X),), LLLLLLLX(,, llllX)), X)", 0x00FF00); Shapes.set("1p_flag3","lllX(X, RRllX(, RRllX(, (X, lllX, X),), LLLLLLLX(,, llllX)), X)", 0x00FFFF); Shapes.set("1p_flag4","lllX(X, RRllX(, RRllX(, (X, lllX, X),), LLLLLLLX(,, llllX)), X)", 0xFF00FF); // log = File.createDirect("statistics"+Math.time+".txt","CTF statistics"); // log.writeString("Step;Team1_Points;Team1_Scored;Team1_Captured;Team1_Retrieved;Team2_Points;Team2_Scored;Team2_Captured;Team2_Retrieved;\n"); } function onExpInit() { ExpProperties_create_call(); } function onBorn(cr) { cr.energ0 = 100; cr.energy = cr.energ0; } function onDied(cr) { } function onExpLoad() { } function onExpLoad_Unknown() { } function onExpSave() { } function createTeams(){ } function ExpProperties_create_call(){ //Create GenePool and Population for each team GenePools.clear(); var pool=GenePools[0]; pool.name = "Team1"; pool.fitness = "return 0;"; while (pool.size > 0) pool.delete(0); Populations.clear(); var pop=Populations[0]; pop.name = "Team1"; while (pop.size > 0) pop.delete(0); pop.selfmask = 0x50001; pop.othermask = 0x60001; var i = 2; for (i = 2; i <= ExpProperties.teamsno; i++){ pop=Populations.addGroup("Team"+i); pop.selfmask = 0x50001; pop.othermask = 0x60001; pool=GenePools.addGroup("Team"+i); pool.fitness = "return 0;"; } //Create GenePool for flags and fill it pool=GenePools.addGroup("Flags"); pool.add(Geno.newFrom("m:Vstyle=flag0\np:",48,"Flag","Single flag object")); pool.add(Geno.newFrom("m:Vstyle=flag1\np:",48,"Flag","Single flag object")); pool.add(Geno.newFrom("m:Vstyle=flag2\np:",48,"Flag","Single flag object")); pool.add(Geno.newFrom("m:Vstyle=flag3\np:",48,"Flag","Single flag object")); pool.add(Geno.newFrom("m:Vstyle=flag4\np:",48,"Flag","Single flag object")); } function ExpProperties_fill_call(){ var team = 0; var player = 0; //Reset all global points vectors flagsX = []; flagsY = []; points = []; scored = []; taken = []; retrieved = []; //Init global vectors var x, y, i; var ok = 0; for (i = 0; i < ExpProperties.teamsno; i++){ points.add(0); scored.add(0); taken.add(0); retrieved.add(0); } //Clear Populations for (team = 0; team < ExpProperties.teamsno; team++){ while (Populations[team].size > 0) Populations[team].delete(0); } //Draw flag positions according to minimal distance parameter var totalTries = 0, flagTries = 0, done = 0; while (totalTries < 1000 && done == 0){ flagsX = Vector.new(); flagsY = Vector.new(); ok = 1; while (flagsX.size < ExpProperties.teamsno && ok == 1){ ok = 0; flagTries = 0; while (ok == 0 && flagTries < 1000){ x = Math.random(80) + 10; y = Math.random(80) + 10; ok = 1; for (i = 0; i < flagsX.size; i++){ if (Math.sqrt(Math.pow(flagsX[i] - x, 2)+Math.pow(flagsY[i] - y,2)) < ExpProperties.mindistance){ ok = 0; break; } } if (ok == 1){ flagsX.add(x); flagsY.add(y); } else flagTries += 1; } } if (flagsX.size == ExpProperties.teamsno) done = 1; else totalTries += 1; } //Flags weren't placed successfully' if (done != 1){ Simulator.message("Flags could not be placed correctly. Consider lowering minimal distance between flags.", 2); Simulator.beep(); return; } //Fill each team's Population with players and a flag and place players close to their flag for (team = 0; team < ExpProperties.teamsno; team++){ while (Populations[team].size > 0) Populations[team].delete(0); var cr = Populations[team].add(GenePools[ExpProperties.teamsno][team]); placeFlag(cr); cr.signals.add("Flag"); cr.signals[0].flavor = team; cr.signals[0].power=1000; cr.data->taken = 0; cr.data->owner = 0; cr.data->cooldown = 0; var crX, crY; for (player = 0; player < ExpProperties.memberssno; player++){ var pool=GenePools[team]; cr = Populations[team].add(pool[player % pool.size]); crX = Math.random(30) - 15; if (crX >=0 && crX < 5) crX = 5; else if (crX > -5 && crX < 0) crX = -5; crY = Math.random(30) - 15; if (crY >=0 && crY < 5) crY = 5; else if (crY > -5 && crY < 0) crY = -5; cr.moveAbs(flagsX[team] + crX, flagsY[team] + crY, 0); cr.data->holding = 0; cr.data->flag = 0; cr.data->score = 0; } } } function ExpProperties_default_call(){ //Insert default player genotype in team's GenePools var team = 0; for (team = 0; team < ExpProperties.teamsno; team++){ while (GenePools[team].size > 0) GenePools[team].delete(0); if (team != 1) GenePools[team].add(Geno.newFrom("lllfffX[0:2.420, 2:-2, 1:-1][-1:1, 0:1, 0:-1][-1:1](RRlllfffMMMX[|-1:-10]lllFFFMMMX[|-2:-1], fffIXlllfffMMMsX[|6:10, 3:-10](RRlllfffMMMIX[|-4:-10]lllFFFMMMIX[|-5:-1][*], , RRlllfffMMMIX[|-7:10]lllFFFMMMIX[|-8:-1][*]), RRlllfffMMMX[|-10:10]lllFFFMMMX[|-11:-1.784])", 49, "Player", "Player")); else if (team == 1) GenePools[team].add(Geno.newFrom("lllfffX[0:2.420, 2:-2, 1:-1][-1:1, 0:1, 0:-1][-1:1](RRlllfffMMMX[|-1:-10]lllFFFMMMX[|-2:-1], fffIXlllfffMMMsX[|1:1][Thr2,lo:-0.75,hi:0.75,t:0.75,3:-10,6:10](RRlllfffMMMIX[|-4:-10]lllFFFMMMIX[|-5:-1][FlagDef,opp:0,my:1], , RRlllfffMMMIX[|-7:10]lllFFFMMMIX[|-8:-1][FlagDef,opp:0,my:1]), RRlllfffMMMX[|-10:10]lllFFFMMMX[|-11:-1.784])", 49, "Inteligent Player", "Inteligent Player")); } } function onStep(){ var team = 0; var player = 0; //Update flags position if taken and cooldown if recently retrieved for (team = 0; team < Populations.size; team++){ var pop=Populations[team]; if (pop[0].data->cooldown > 0) pop[0].data->cooldown -= 1; for (player = 1; player < pop.size; player++){ var cr=pop[player]; if (cr.data->holding == 1){ cr.data->flag.moveAbs(cr.pos_x, cr.pos_y, cr.size_z + 1); } } } // if (Simulator.time % 100 == 0){ // var i = 0; // var line = ""; // line=line+Simulator.time+";"; // // for (i = 0; i < ExpProperties.teamsno; i++){ // line=line+points[i]+";"+scored[i]+";"+taken[i]+";"+retrieved[i]+";"; // } // line=line+"\n"; // log.writeString(line); // // } } function placeFlag(flag){ flag.moveAbs(flagsX[flag.population.index], flagsY[flag.population.index], 0); } function takeFlag(flag, creature){ //If the cooldown is on - do nothing if (flag.data->cooldown > 0) return; //Take flag by changing its flavour and setting flag in player and player in flag fields flag.signals[0].flavor = flag.population.index + 100; flag.data->taken = 1; flag.data->owner = creature; creature.data->holding = 1; creature.data->flag = flag; //Score points for taking a flag creature.data->score += ExpProperties.pointsCapture; // Simulator.print("Flag "+(flag.group.index+1)+" taken by team "+(creature.group.index+1)); //Update team points and events points[creature.population.index] = points[creature.population.index] + ExpProperties.pointsCapture; taken[creature.population.index] = taken[creature.population.index] + 1; } function retrieveFlag(flag, creature){ //Retrieve flag by changing its flavour and deleting it from player and player from flag flag.signals[0].flavor = flag.population.index; flag.data->taken = 0; flag.data->owner.data->holding = 0; flag.data->owner.data->flag = 0; flag.data->owner = 0; //Set cooldown for taking a flag flag.data->cooldown = 1000; placeFlag(flag); //Score points for retrieving a flag creature.data->score += ExpProperties.pointsRetrieve; // Simulator.print("Flag "+ (flag.group.index+1) +" retrieved"); //Update team scores points[creature.population.index] = points[creature.population.index] + ExpProperties.pointsRetrieve; retrieved[creature.population.index] = retrieved[creature.population.index] + 1; } function scoreFlag(flag, creature){ //Put the flag back on its spot and delete references between player and flag creature.data->flag.signals[0].flavor = creature.data->flag.population.index; creature.data->flag.data->taken = 0; creature.data->flag.data->owner = 0; placeFlag(creature.data->flag); creature.data->holding = 0; creature.data->flag = 0; //Score points for scoring a flag creature.data->score += ExpProperties.pointsScoring; // Simulator.print("Team "+ (creature.group.index + 1) +" scored"); //Update team points points[creature.population.index] = points[creature.population.index] + ExpProperties.pointsScoring; scored[creature.population.index] = scored[creature.population.index] + 1; } function onTeam1CrCollision, onTeam2CrCollision, onTeam3CrCollision, onTeam4CrCollision, onTeam5CrCollision(){ var c1 = CrCollision.Creature1; var c2 = CrCollision.Creature2; //Flag vs. flag collision - do nothing if (c1.geno.name == "Flag" && c2.geno.name == "Flag"){ return; } var flag; var creature; var colFlag = 0; //Try to assign colliding creatures to flag and player if (c1.geno.name == "Flag"){ flag = c1; creature = c2; colFlag = 1; } else if (c2.geno.name == "Flag"){ flag = c2; creature = c1; colFlag = 1; } //Flag vs. player collision if (colFlag == 1){ //Collision with my flag which is taken if (flag.population.index == creature.population.index && flag.data->taken == 1){ retrieveFlag(flag, creature); } //Collision with my flag which is not taken while carrying another team's flag else if (flag.population.index == creature.population.index && flag.data->taken == 0 && creature.data->holding == 1 && flag.data->cooldown != 1){ scoreFlag(flag, creature); } //Collision with another team's flag which is not taken while not carrying any flag else if (flag.population.index != creature.population.index && flag.data->taken == 0 && creature.data->holding == 0 && flag.data->cooldown != 1){ takeFlag(flag, creature); } } //Player vs. player collision else { //Players of different teams if (c1.population.index != c2.population.index){ //If player 1 has a flag ... if (c1.data->holding == 1){ // ... and the flag is of my team ... if (c2.population.index == c1.data->flag.population.index){ //... retrieve it retrieveFlag(c1.data->flag, c2); } } //If player 2 has a flag ... if (c2.data->holding == 1){ // ... and the flag is of my team ... if (c1.population.index == c2.data->flag.population.index){ //... retrieve it retrieveFlag(c2.data->flag, c1); } } } } } ~ property: id:teamsno name:Number of teams type:d 2 5 property: id:memberssno name:Number of members in team type:d 1 8 property: id:mindistance name:Minimal distance between flags type:d 1 100 property: id:create name:Create teams type:p property: id:default name:Insert default player type:p property: id:fill name:Fill teams type:p property: id:pointsCapture name:Points for flag capture type:d 0 100 property: id:pointsRetrieve name:Points for flag retrieve type:d 0 100 property: id:pointsScoring name:Points for scoring a flag type:d 0 100