A few days ago, I came up with a fun card game to play with my friends. We were having fun playing it, when I thought, "Why not make this a KoTH?" So, here it is!
Overview
In this game, the objective is to get the most points. Your bot starts with 0 points and 20 energy. Every turn (500 in a game), both bots play one card. Some earn you points, some take the opponent's points.
Cards
A=Add 5 points to your score [Costs 0.1 energy]
R=Remove 5 points from opponent [Costs 0.1 energy]
H=Half your next score [Costs 1 energy]
Y=Half opponent's next score [Costs 1 energy]
D=Double your next score [Costs 2 energy]
T=Double opponent's next score [Costs 2 energy]
N=Negate your next score [Costs 3 energy]
O=Negate opponent's next score [Costs 3 energy]
S=Shield for 5 turns [Costs 15 energy]
X=Take five energy from opponent [Gives opponent 10 points]
E=Refill five energy [Costs 10 points]
How it works
First how would halving your next score or doubling your opponent's next score come in handy? Well, imagine you get 5 points taken away on your next turn. Instead, 2.5 points get taken away. Cool, right? Or, negating your next score would give you 5. If you think your opponent will give themself points, negate their next move!
The order of operations for modifying point values is:
Add all positive or negative point changes
Half if necessary
Double if necessary
Negate if necessary
If shielding and result is negative, change to 0
Attempting to lower the opponent's energy past 0 does not work. There is no upper limit to energy, or lower limit to points. Energy reducing cards are played before other cards, so if Bot A with 17 energy runs shield and Bot B runs take 5 energy, Bot A cannot shield.
Creating a bot
In Javascript, create a new function with whatever name you wish. This function should take 3 parameters:
Array of Numbers (Your coins, Opponent's coins)
Array of Numbers (Your energy, Opponent's energy)
Object (Use for storage between rounds)
Note that there is no way of knowing what cards have been played. You must teach the bot to figure it out by itself!
The way you select a card is by return
ing a string, containing the letter of the card in uppercase or lowercase. Note that Standard Loopholes (obviously) aren't allowed. If any other value is returned, your bot just does nothing.
Scoring
Every bot will be run against each other bot once. The loser will get 0 points, anbd the winner will get the difference in points added to its total score (Between all rounds). The top 8 will compete in a tournament. In other words, they will each fight one other bot, the four winners will fight another bot, and the two remaining bots will fight for first.
Controller
var botDataList = [
{
name: "",
desc: "",
run: function(){
}
}, {
name: "",
desc: "",
run: function(){
}
}
];
function playGame() {
botSetup();
for (var i = 0; i < 500; i++) {
runBots();
}
var botA = botDataList[0];
var botB = botDataList[1];
console.log("Bot " + botA.name + ": " + botA.points);
console.log("Bot " + botB.name + ": " + botB.points);
}
function botSetup() {
for (var b, i = 0; i < 2; i++) {
b = botDataList[i];
b.points = 0;
b.energy = 20;
b.storage = {};
b.affectAdd = [];
b.affectAct = [];
b.shield = 0;
}
}
function runBots() {
var botA = botDataList[0];
var botB = botDataList[1];
var resA = botA.run([botDataList[0].points, botDataList[1].points], [botDataList[0].energy, botDataList[1].energy], botDataList[0].storage).toLowerCase();
var resB = botB.run([botDataList[1].points, botDataList[0].points], [botDataList[1].energy, botDataList[0].energy], botDataList[1].storage).toLowerCase();
var modA = 0;
var modB = 0;
if (resA == 'a' && botA.energy >= 0.1) {
botA.energy -= 0.1;
modA += 5;
} else if (resA == 'r' && botA.energy >= 0.1) {
botA.energy -= 0.1;
modB -= 5;
} else if (resA == 'h' && botA.energy >= 1) {
botA.energy -= 1;
botA.affectAdd.push('h');
} else if (resA == 'y' && botA.energy >= 1) {
botA.energy -= 1;
botB.affectAdd.push('h');
} else if (resA == 'd' && botA.energy >= 2) {
botA.energy -= 2;
botA.affectAdd.push('d');
} else if (resA == 't' && botA.energy >= 2) {
botA.energy -= 2;
botB.affectAdd.push('d');
} else if (resA == 'n' && botA.energy >= 3) {
botA.energy -= 3;
botA.affectAdd.push('n');
} else if (resA == 'o' && botA.energy >= 3) {
botA.energy -= 3;
botB.affectAdd.push('n');
} else if (resA == 's' && botA.energy >= 15) {
botA.energy -= 15;
botA.shield += 5;
} else if (resA == 'x') {
modB += 10;
botB.energy = (botB.energy >= 5) ? botB.energy - 5 : 0;
} else if (resA == 'e' && botA.points >= 10) {
modA -= 10;
botA.energy += 5;
}
if (resB == 'a' && botB.energy >= 0.1) {
botB.energy -= 0.1;
modB += 5;
} else if (resB == 'r' && botB.energy >= 0.1) {
botB.energy -= 0.1;
modA -= 5;
} else if (resB == 'h' && botB.energy >= 1) {
botB.energy -= 1;
botB.affectAdd.push('h');
} else if (resB == 'y' && botB.energy >= 1) {
botB.energy -= 1;
botA.affectAdd.push('h');
} else if (resB == 'd' && botB.energy >= 2) {
botB.energy -= 2;
botB.affectAdd.push('d');
} else if (resB == 't' && botB.energy >= 2) {
botB.energy -= 2;
botA.affectAdd.push('d');
} else if (resB == 'n' && botB.energy >= 3) {
botB.energy -= 3;
botB.affectAdd.push('n');
} else if (resB == 'o' && botB.energy >= 3) {
botB.energy -= 3;
botA.affectAdd.push('n');
} else if (resB == 's' && botB.energy >= 15) {
botB.energy -= 15;
botB.shield += 5;
} else if (resB == 'x') {
modA += 10;
botA.energy = (botA.energy >= 5) ? botA.energy - 5 : 0;
} else if (resB == 'e' && botB.points >= 10) {
modB -= 10;
botB.energy += 5;
}
if (botA.affectAct.includes('h')) {
modA *= 0.5;
}
if (botA.affectAct.includes('d')) {
modA *= 2;
}
if (botA.affectAct.includes('n')) {
modA *= -1;
}
if (botA.shield > 0) {
modA = (modA < 0) ? 0 : modA;
botA.shield--;
}
botA.points += modA;
botA.affectAct = botA.affectAdd;
botA.affectAdd = [];
if (botB.affectAct.includes('h')) {
modB *= 0.5;
}
if (botB.affectAct.includes('d')) {
modB *= 2;
}
if (botB.affectAct.includes('n')) {
modB *= -1;
}
if (botB.shield > 0) {
modB = (modB < 0) ? 0 : modB;
botB.shield--;
}
botB.points += modB;
botB.affectAct = botB.affectAdd;
botB.affectAdd = [];
}
/* A=Add 5 points to your score [Costs 0.1 energy]
R=Remove 5 points from opponent [Costs 0.1 energy]
H=Half your next score [Costs 1 energy]
Y=Half opponent's next score [Costs 1 energy]
D=Double your next score [Costs 2 energy]
T=Double opponent's next score [Costs 2 energy]
N=Negate your next score [Costs 3 energy]
O=Negate opponent's next score [Costs 3 energy]
S=Shield for 5 turns [Costs 15 energy]
X=Take five energy from opponent [Gives opponent 10 points]
E=Refill five energy [Takes 10 points] */
X
is an energy reducing card? IMO this question still needs a few days in the sandbox. \$\endgroup\$