Це гра захоплення прапора, сильно натхненна та заснована на Red vs. Blue - Pixel Team Battlebots . Це було дивовижне питання (дуже дякую Calvin'sHobbies; я сподіваюся, ви не заперечуєте, що я безсоромно вкрав у вас багато коду) - ось ще одна команда, заснована королем гірки. Сподіваємось, захоплення прапора вимагатиме більше співпраці в команді, а також більше стратегії.
Щоб змішати це, ви вважаєтесь командою червоного кольору, якщо остання цифра вашого ідентифікатора знаходиться між 0
і 4
включно. Це повинно запобігти повторному битві абсолютно тих самих команд, якщо ті ж люди вирішать відповісти. Дошка - 350px
повз 350px
. Синя команда починається з верхньої половини дошки, а червона команда - з нижньої.
Спосіб грати захоплення прапора полягає в наступному: мета гри - взяти прапор команди суперника і повернути його на свій бік. Якщо ви на їх боці, вас можуть помітити та відправити до в'язниці. Якщо ви в тюрмі, ви не можете рухатися. Якщо ви на вашій стороні, ваше завдання - позначати протилежних членів команди, щоб відправити їх до в'язниці. Єдиний спосіб вийти з в'язниці - це той, хто у вашій команді може вільно позначити усіх у в'язниці. (Зверніть увагу, що в'язниця знаходиться на стороні команди суперника).
Конкретно:
- Постійна -
FIELD_PADDING
- встановлена на 20. Це поле для поля. Якби він дорівнював нулю, значить, прапори та в’язниці були б саме на кутах полотна. Так як це не так, прапор та в'язниця за 20 куточків від кутів. - Синій прапор (пам’ятайте: синя команда знаходиться у верхній половині) розташований у
(WIDTH - FIELD_PADDING, FIELD_PADDING) = (330, 20)
верхньому правому куті. - Червоний прапор знаходиться на
(FIELD_PADDING, HEIGHT - FIELD_PADDING) = (20, 330)
- Блакитна в'язниця (де тримаються червоні члени) знаходиться біля
(20, 20)
блакитної сторони, вгорі зліва. - Червона в'язниця, де утримуються сині члени, знаходиться в
(330, 330)
Кожен член команди починає випадковим чином в положенні 45 < x < 305
і 45 < y < 175
для синього і 175 < y < 305
для червоного. Жоден член команди не може переходити в DEFENSE_RADIUS = 25
пікселі власного прапора або власної в'язниці (якщо, звичайно, ваш власний прапор не взяв протистоящий бот; в цьому випадку вам потрібно позначити цього бота). Це запобігає охороні цуценя, як боти. Якщо ви переходите в цей діапазон, вас "відштовхують" назад. Так само жоден член команди не може вийти за межі (менше нуля або більше 350) - якщо це зробити, вас відсунуть до найближчого юридичного місця, де ви можете бути.
Кожен раз, коли ви рухаєтесь, ви використовуєте strength
. Ваш strength
старт починається 20
і поповнюється 2
щоразу. Кількість сили, яку ви використовуєте, дорівнює відстані, яку ви проїхали. Якщо ваша сила стане негативною, перемістившись у певне місце, вам не вдасться зробити цей крок. Напевно, це гарна ідея просто їхати зі швидкістю 2
для звичайного погоні. Більш високі швидкості слід використовувати лише у тому випадку, якщо ви близькі до виграшу та потребуєте додаткової швидкості (на мою думку).
Специфікація :
Специфікація досить схожа на питання Pixel Team Battlebots. Вам слід написати блок коду (пам’ятайте, відсутні глобальні змінні) у javascript. Він повинен повернути об’єкт зі x
значеннями -значення та y
-значення, що представляють вашу зміну x та зміну значень y. Наступна відповідь:
return {
x: 0,
y: -2
};
завжди рухається вгору, поки не вдариться про стіну. Ви не можете редагувати через 8 годин після публікації (за винятком LegionMammal98, який вважав, що контролер не завантажує свій код і не перевіряє) . У вас є доступ до таких змінних у вашому коді:
this
- себе, як гравця (див. нижче, що таке гравці)move
- кругле число, починаючи з 0tJailed
- масив усіх гравців вашої команди, які потрапили до в'язниціeJailed
- масив усіх гравців протилежної команди, які потрапляють до в'язниціteam
- масив усіх гравців вашої команди, а не лише тих, хто поручenemies
- масив усіх гравців іншої команди, а не лише тих, хто поручtFlag
- ваш прапор (ви намагаєтесь захистити його)eFlag
- інший прапор (ви намагаєтесь його вкрасти)messages
- пояснено нижче- Список констант:
WIDTH = 350
,HEIGHT = 350
,FIELD_PADDING = 20
,DEFENSE_RADIUS = 25
.
Кожен "гравець" - це об'єкт із такими властивостями:
x
іy
strength
id
isJailed
- вірно, якщо гравець у в'язниці
Кожен прапор має такі властивості:
x
іy
pickedUpBy
- гравець, у якого зараз є прапор, або нульовий, якщо у гравця немає прапора.
Тепер messages
це об’єкт, яким поділяються серед ваших товаришів по команді. Мені все одно, що ти з цим робиш. Цей самий об’єкт ділиться і передається кожному з членів вашої команди. Це єдиний спосіб спілкування. Ви можете приєднувати до нього властивості, ділитися об'єктами тощо. Він може бути настільки великим, наскільки ви хочете - без обмеження розміру.
Кожного кроку відбувається таке:
- Список гравців (червоний та синій) випадковим чином переміщується для порядку черги.
- Кожен гравець робить хід.
- Якщо будь-який член червоної команди торкається (у межах 10 пікселів) будь-якого синього колективу на стороні червоного, відправте синіх членів команди у в'язницю та навпаки. Ув'язнений гравець скидає свій прапор і сили падають до нуля. Зауважте, що покрокова функція (код, який ви надаєте) все ще називається - тож ви можете отримувати / встановлювати повідомлення, але не можете рухатися, перебуваючи у в'язниці.
- Якщо будь-який гравець торкається (у межах 10 пікселів) іншого прапора, то інший прапор позначається як "підхоплений" цим гравцем. Коли гравець рухається, прапор рухається - доки гравця не позначено тегом і не потрапить до в'язниці, тобто.
- Якщо будь-який гравець торкається тюрми іншої сторони, звільніть усіх у цій тюрмі. Коли гравець звільняється з в'язниці, його передають у випадкове місце з його боку.
Підказки:
- Принаймні, при регулярному захопленні прапора, атаки працюють набагато краще, коли багато гравців йдуть одразу, оскільки це, як правило, бентежить захисників щодо того, за яким гравцем вони будуть переслідувати.
- Так само захисники можуть захотіти узгодити того, кого вони переслідують, щоб атаки не проходили
Фрагмент стека:
window.onload=function(){(function(){function p(a,b,c,e){return Math.sqrt((a-c)*(a-c)+(b-e)*(b-e))}function l(a,b){this.x=this.y=0;this.id=a.id;this.title=a.title+" ["+this.id+"]";this.link=a.link||"javascript:;";this.team=b;this.isJailed=!1;this.flag=null;this.moveFn=new Function("move","tJailed","eJailed","team","enemies","tFlag","eFlag","messages","WIDTH","HEIGHT","FIELD_PADDING","DEFENSE_RADIUS",a.code);this.init()}function x(a,b){return Math.floor(Math.random()*(b-a))+a}function q(a,b){this.startX=this.x=a;this.startY=
this.y=b;this.following=null}function t(a,b){return a===e&&b||a===h&&!b?{x:20,y:20}:{x:g.width-20,y:g.height-20}}function y(){var a,b=$("#redTeam"),c=$("#blueTeam");for(a=0;a<e.length;++a)e[a].addToDiv(b);for(a=0;a<h.length;++a)h[a].addToDiv(c)}function z(){d.clearRect(0,0,g.width,g.height);d.beginPath();d.moveTo(0,g.height/2);d.lineTo(g.width,g.height/2);d.stroke();var a=e.concat(h),b,c;for(b=a.length-1;0<b;b--){c=Math.floor(Math.random()*(b+1));var f=a[b];a[b]=a[c];a[c]=f}for(b=0;b<a.length;++b)a[b].step(u);
for(b=0;b<e.length;++b)for(c=0;c<h.length;++c)10>p(e[b].x,e[b].y,h[c].x,h[c].y)&&(e[b].y<g.height/2&&e[b].goToJail(),h[c].y>g.height/2&&h[c].goToJail());for(b=0;b<a.length;++b)c=a[b].team===e!==!0?m:n,!c.following&&10>p(a[b].x,a[b].y,c.x,c.y)&&(c.following=a[b]);for(b=0;b<a.length;++b)if(c=t(a[b].team,!0),!a[b].isJailed&&10>p(a[b].x,a[b].y,c.x,c.y))for(c=a[b].team,f=0;f<c.length;++f)c[f].isJailed&&(c[f].isJailed=!1,c[f].init());m.follow();n.follow();b=m.y<g.height/2;c=n.y>g.height/2;b&&c&&alert("EXACT TIE!!!! This is very unlikely to happen.");
b&&!c&&(alert("Blue wins!"),$("#playpause").click().hide());c&&!b&&(alert("Red wins!"),$("#playpause").click().hide());for(b=0;b<a.length;++b)a[b].draw(d);m.draw("red");n.draw("blue");u++}$.ajaxSetup({cache:!1});var e=[],h=[],g=$("canvas")[0],d=g.getContext("2d"),v,u=0,m={},n={},r=!0,A={},B={},w;l.prototype.init=function(){this.x=x(45,g.width-45);this.y=x(45,g.height/2);this.team===e&&(this.y+=g.height/2);this.strength=20};l.prototype.makeShallowCopy=function(){return{x:this.x,y:this.y,strength:this.strength,
id:this.id,isJailed:this.isJailed}};l.prototype.goToJail=function(){this.isJailed=!0;var a=this.team===e!==!0?m:n;(this.team===e!==!0?m:n).following===this&&(a.following=null);a=t(this.team,!0);this.x=a.x;this.y=a.y;this.strength=0};l.prototype.step=function(a){function b(a,b,c){var e,d,f;for(e=0;e<a.length;++e)d=a[e],d!==C&&(f=d.makeShallowCopy(),d.isJailed?b.push(f):c.push(f))}var c=[],f=[],d=[],k=[],l=this.team===e?h:e,C=this,q=this.team===e?m:n,r=this.team===e?n:m;b(this.team,c,d);b(l,f,k);f=
this.moveFn.call(this.makeShallowCopy(),a,c,f,d,k,q.copy(),r.copy(),this.team===e?A:B,g.width,g.height,20,25);"object"===typeof f&&"number"===typeof f.x&&"number"===typeof f.y&&(d=p(0,0,f.x,f.y),a=t(this.team,!1),c=this.team===e!==!1?m:n,d<=this.strength&&(this.strength-=d,this.x+=f.x,this.y+=f.y,0>this.x&&(this.x=0),0>this.y&&(this.y=0),this.x>g.width&&(this.x=g.width),this.y>g.height&&(this.y=g.height),f=p(this.x,this.y,c.x,c.y),d=p(this.x,this.y,a.x,a.y),25>f&&null===c.following&&(this.x=25*(this.x-
c.x)/f*1.3+c.x,this.y=25*(this.y-c.y)/f*1.3+c.y),25>d&&(this.x=25*(this.x-a.x)/d*1.3+a.x,this.y=25*(this.y-a.y)/d*1.3+a.y)),this.isJailed||(this.strength+=2),20<this.strength&&(this.strength=20))};l.prototype.addToDiv=function(a){var b=$("<option>").text(this.title).val(this.id);a.find(".playersContainer").append(b)};l.prototype.draw=function(a){a.fillStyle=this.team===e?"red":"blue";a.beginPath();a.arc(this.x,this.y,5,0,2*Math.PI,!0);a.fill();!this.isJailed&&$("#labels").is(":checked")&&a.fillText(this.title,
this.x+5,this.y+10)};q.prototype.draw=function(a){d.strokeStyle=a;d.beginPath();d.arc(this.x,this.y,5,0,2*Math.PI,!0);d.stroke();d.fillStyle=a;d.strokeRect(this.x-2,this.y-2,4,2);d.beginPath();d.moveTo(this.x-2,this.y);d.lineTo(this.x-2,this.y+3);d.stroke()};q.prototype.copy=function(){return{x:this.x,y:this.y,pickedUpBy:this.following&&this.following.makeShallowCopy()}};q.prototype.follow=function(){null!==this.following&&(this.x=this.following.x,this.y=this.following.y)};$("#newgame").click(function(){function a(a,
b){w?b(w):$.get("https://api.stackexchange.com/2.2/questions/"+(49028).toString()+"/answers",{page:a.toString(),pagesize:100,order:"asc",sort:"creation",site:"codegolf",filter:"!JDuPcYJfXobC6I9Y-*EgYWAe3jP_HxmEee"},b,"json")}function b(g){w=g;g.items.forEach(function(a){function b(a){return $("<textarea>").html(a).text()}var d=4>=a.owner.user_id%10?e:h;a.owner.display_name=b(a.owner.display_name);if(!(a.hasOwnProperty("last_edit_date")&&28800<a.last_edit_date-a.creation_date&&33208!==a.owner.user_id||
-1<p.indexOf(a.owner.user_id))){p.push(a.owner.user_id);var g=c.exec(a.body);if(!(null===g||1>=g.length)){var f={};f.id=a.owner.user_id;f.title=a.owner.display_name;f.code=b(g[1]);f.link=a.link;d.push(new l(f,d))}}});g.has_more?a(++d,b):(console.log("Red team",e),console.log("Blue team",h),y(),clearInterval(v),r=!0,$("#playpause").show().click())}var c=/<pre><code>((?:\n|.)*?)\n<\/code><\/pre>/,d=1,p=[];e=[];h=[];u=0;m=new q(20,g.height-20);n=new q(g.width-20,20);$(".teamColumn select").empty();var k=
$("#testbotCode").val();0<k.length&&(console.log("Using test entry"),k={title:"TEST ENTRY",link:"javascript:;",code:k},$("#testbotIsRed").is(":checked")&&(k.id=-1,e.push(new l(k,e)),k.id=-3,e.push(new l(k,e))),$("#testbotIsBlue").is(":checked")&&(k.id=-2,h.push(new l(k,h)),k.id=-4,h.push(new l(k,h))));a(1,b)});$("#playpause").hide().click(function(){r?(v=setInterval(z,25),$(this).text("Pause")):(clearInterval(v),$(this).text("Play"));r=!r})})();}
#main{padding:10px;text-align:center}#testbot{padding:10px;clear:both}.teamColumn{width:25%;padding:0 10px;border:3px solid;border-color:#000;text-align:center;height:500px;overflow:scroll;white-space:nowrap}.playersContainer p{padding:0;margin:0}#redTeam{float:left;border-color:red;color:red;background-color:#fee}#blueTeam{float:right;border-color:#00f;color:#00f;background-color:#fee}#arena{display:inline-block;width:40%;text-align:center}canvas{border:1px solid #000}select{width:100%}
<script src=https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js></script><div id=main><div class=teamColumn id=redTeam><h1>Red Team</h1><select size=20 class=playersContainer></select></div><div id=arena><h1>Battlefield</h1><canvas width=350 height=350></canvas></div><div class=teamColumn id=blueTeam><h1>Blue Team</h1><select size=20 class=playersContainer></select></div><div id=loadingInfo><button id=newgame>New Game</button> <button id=playpause>Play</button><br><input type=checkbox id="labels"> Show labels</div></div><div id=testbot><textarea id=testbotCode placeholder="testbot code"></textarea><br><input type=checkbox id="testbotIsRed">Red Team<br><input type=checkbox id="testbotIsBlue">Blue Team<br></div>
Контролер: http://jsfiddle.net/prankol57/4L7fdmkk/
Повноекранний контролер: http://jsfiddle.net/prankol57/4L7fdmkk/embedded/result/
Повідомте мене, чи є помилки в контролері.
Примітка. Якщо ви переходите до контролера і думаєте, що він нічого не завантажує, натисніть "Нова гра". Він завантажує все лише після натискання кнопки "Нова гра", щоб він міг завантажувати всі боти та можливі тестові боти одночасно.
Удачі.
Якщо хтось хоче побачити приклад гри, я зробив приклад-бот, який ви можете скопіювати та вставити в textarea "testbot" (тестова робота створює два дублікати для кожної команди; перевіряйте як червону команду, так і синю команду):
var r2 = Math.sqrt(2);
if (this.id === -1) {
// red team 1
// go after flag regardless of what is going on
if (eFlag.pickedUpBy !== null && eFlag.pickedUpBy.id === this.id) {
return {
x: 0,
y: 2
};
}
return {
x: this.x < eFlag.x ? r2 : -r2,
y: this.y < eFlag.y ? r2 : -r2
};
}
if (this.id === -2) {
// blue team 1
// a) go after opposing team members on your side b) get the other flag if no enemies on your side
var closestEnemy = null;
for (var i = 0; i < enemies.length; ++i) {
if (enemies[i].y < HEIGHT/2 && (closestEnemy === null || enemies[i].y < closestEnemy.y)) {
closestEnemy = enemies[i];
}
}
if (closestEnemy !== null) {
return {
x: this.x < closestEnemy.x ? r2 : -r2,
y: this.y < closestEnemy.y ? r2 : -r2
};
}
if (eFlag.pickedUpBy !== null && eFlag.pickedUpBy.id === this.id) {
return {
x: 0,
y: -2
};
}
return {
x: this.x < eFlag.x ? r2 : -r2,
y: this.y < eFlag.y ? r2 : -r2
};
}
if (this.id === -3) {
// red team 2
// a) defend the flag b) if at least half of enemies in jail and no enemies on this side, free jailed reds and quickly return
var closestEnemy = null;
for (var i = 0; i < enemies.length; ++i) {
if (enemies[i].y > HEIGHT/2 && (closestEnemy === null || enemies[i].y > closestEnemy.y)) {
closestEnemy = enemies[i];
}
}
if (closestEnemy !== null) {
return {
x: this.x < closestEnemy.x ? r2 : -r2,
y: this.y < closestEnemy.y ? r2 : -r2
};
}
if (enemies.length / eJailed.length <= 1 && tJailed.length > 0) {
return {
x: this.x < FIELD_PADDING ? r2 : -r2,
y: this.y < FIELD_PADDING ? r2 : -r2
};
}
if (this.y < 350/2) return {x: 0, y: 2};
return {
x: this.x < tFlag.x ? r2 : -r2,
y: this.y < tFlag.y ? r2 : -r2
};
}
if (this.id === -4) {
// blue team 2
// a) try freeing jail if there are jailed team members b) capture the flag
if (tJailed.length > 0) {
return {
x: this.x < WIDTH - FIELD_PADDING ? r2 : -r2,
y: this.y < HEIGHT - FIELD_PADDING ? r2 : -r2
};
}
if (eFlag.pickedUpBy !== null && eFlag.pickedUpBy.id === this.id) {
return {
x: 0,
y: -2
};
}
return {
x: this.x < eFlag.x ? r2 : -r2,
y: this.y < eFlag.y ? r2 : -r2
};
}