Tower Takeover Scoring Recommendation Code

Hello everybody!

It’s been a while (so long I forgot my old password for the forums). Anyway, I competed in VEX for 6 years from 2008-2014, and I’ve kept up with the new games a bit since I stopped competing (went to college, got a degree in MECH-E). I was looking at Tower Takeover, and I thought to myself there must be a quick easy way to figure out what the optimal score move is (what color to place in the towers, etc.). I threw together a quick Matlab script (it’s my daily driver language these days) that intakes the amount of cubes in various places on the field and spits the color you should prioritize in the tower for the largest point swing in your favor. Nobody but me likes Matlab though, so I ported it to C++. I created a new account for this, so unfortunately I can’t attach the code as a document. Feel free to alter and use (it won’t quite easily implement onboard a VEX robot yet), but please credit this post when you do. If it does something dumb like not compiling, feel free to tinker or respond to this post, and I’ll try to troubleshoot on my end.

//This code recommends a scoring choice based on the current scores
//Keep in mind I learned C++ in like, 2 days before I wrote this
//So stuff that I do, you might have a better way of doing.

//standard stuff, whatnot
#include
using namespace std;

//make variables for colors
//This way, we can use the color names instead of 0,1,2 as indexes for arrays
enum colors {
Purple = 0,
Green = 1,
Orange = 2
};

//Make variables for the players
//Again, we can use the names later instead of numbers to index stuff
enum players {
Us = 0,
Them = 1
};

//Same thing here, we can use these names instead of numbers
enum actions {
DoNothing = 0,
AddPurple = 1,
AddGreen = 2,
AddOrange = 3,
SubPurple = 4,
SubGreen = 5,
SubOrange = 6
};

//Now we create arrays and variables for the scores for out opponent and us, contributed by each color
//These are all 3x2, because each column will correspond to each team, and each row corresponds to a color.
//With the enumerated variables from before, we can say Score[Purple][Them] , instead of Score[0][1] , just to keep things straight
int Score[3][2] = {
{0,0},
{0,0},
{0,0}
};
int Ground[3][2] = {
{0,0},
{0,0},
{0,0}
};
int Controlled_Towers[3][2] = {
{0,0},
{0,0},
{0,0}
};
int Neutral_Towers[3] = {0,0,0};

//this array has seven rows, because there are 7 possible actions. We will store all of the scores given different actions in this array
int Totals[7][2] = { 0,0 };

//This function takes a given action as an argument and then changes the values of Totals given that action
//Score is updated in different entries for colors and team, and then Totals is summed from those
int update_score(int action) {
Score[Purple][Them] = Ground[Purple][Them] + Ground[Purple][Them] * (Controlled_Towers[Purple][Them] + Neutral_Towers[Purple]);
Score[Green][Them] = Ground[Green][Them] + Ground[Green][Them] * (Controlled_Towers[Green][Them] + Neutral_Towers[Green]);
Score[Orange][Them] = Ground[Orange][Them] + Ground[Orange][Them] * (Controlled_Towers[Orange][Them] + Neutral_Towers[Orange]);
Score[Purple][Us] = Ground[Purple][Us] + Ground[Purple][Us] * (Controlled_Towers[Purple][Us] + Neutral_Towers[Purple]);
Score[Green][Us] = Ground[Green][Us] + Ground[Green][Us] * (Controlled_Towers[Green][Us] + Neutral_Towers[Green]);
Score[Orange][Us] = Ground[Orange][Us] + Ground[Orange][Us] * (Controlled_Towers[Orange][Us] + Neutral_Towers[Orange]);
Totals[action][Us] = Score[Purple][Us] + Score[Green][Us] + Score[Orange][Us];
Totals[action][Them] = Score[Purple][Them] + Score[Green][Them] + Score[Orange][Them];
return 0;
}
//This is the main, looping function
int main() {

//This is where you would put the code that updates the scored cubes given button presses 
//You can do this however you want, I have some pseudocote below

//if certain button gets pressed, add 1 cube to certain area
/*
if (buttonpress == 1) {
	Ground[Purple][Them]++;
}
*/

//Now, we will populate the Totals array with results from the update_score function we wrote above
	//First, we do nothing, to get a baseline
	update_score(DoNothing);

	//Then, we add a purple to the towers
	Neutral_Towers[Purple]++; // add one "hypothetical point" to the score
	update_score(AddPurple);
	Neutral_Towers[Purple]--; // subtract that "hypothetical point"

	//Then, we add a green to the towers
	Neutral_Towers[Green]++;
	update_score(AddGreen);
	Neutral_Towers[Green]--;

	//Then, we add an orange to the towers
	Neutral_Towers[Orange]++;
	update_score(AddOrange);
	Neutral_Towers[Orange]--;

	//Then, we subtract a purple from the towers
	Neutral_Towers[Purple]--;
	update_score(SubPurple);
	Neutral_Towers[Purple]++;

	//Then, we subtract a green from the towers
	Neutral_Towers[Green]--;
	update_score(SubGreen);
	Neutral_Towers[Green]++;

	//Then, we subtract an orange from the towers
	Neutral_Towers[Orange]--;
	update_score(SubOrange);
	Neutral_Towers[Orange]++;

	//Now, we're going to calculate the difference between our score and theirs for each possible action
	int difference[7];
	difference[DoNothing] = Totals[DoNothing][Us] - Totals[DoNothing][Them];
	difference[AddPurple] = Totals[AddPurple][Us] - Totals[AddPurple][Them];
	difference[AddGreen] = Totals[AddGreen][Us] - Totals[AddGreen][Them];
	difference[AddOrange] = Totals[AddOrange][Us] - Totals[AddOrange][Them];
	difference[SubPurple] = Totals[SubPurple][Us] - Totals[SubPurple][Them];
	difference[SubGreen] = Totals[SubGreen][Us] - Totals[SubGreen][Them];
	difference[SubOrange] = Totals[SubOrange][Us] - Totals[SubOrange][Them];

	//which possible action gives us the highest difference (the biggest advantage over the other team)
	//We're also going to get the index of that entry
	int max = difference[0];
	int maxindex = actions(0);
	//add recommendation array
	int add_rec[4] = { 1,0,0,0 };
	//this loop handles the finding of the index and value, for the "do nothing" and "add" options
	//we're splitting this up because we want to recommend an "add this color" and "subtract this color" if possible
	for (int i = 1; i < 4; i++) {
		//loop through the difference array
		if (difference[i] > max) {
			max = difference[i];
			maxindex = actions(i);
			//in the loop, if the current entry is bigger than the maximum known one, make the new maximum into this entry, and make the maxIndex this action
			//we will control the values in the add_rec array and use them later
			//basically, if we find an action that works, better than previously tested actions, we will make the entire array zero, and then make the ith entry in the array non-zero
			//this means, later, we will only have to search for that non-zero value in the add_rec array to find the recommended action
			for (int n = 0; n < 3; n++) {
				add_rec[n] = 0;
			}
			add_rec[i] = maxindex;
		}
		else if (difference[i] == max) {
			add_rec[i] = maxindex;
		}
	}

	//this loop handles the finding of the index and value, for the "subtract" options
	max = difference[0];
	maxindex = actions(0);
	int sub_rec[4] = { 1,0,0,0 };
	for (int i = 4; i < 7; i++) {
		if (difference[i] > max) {
			max = difference[i];
			maxindex = actions(i);
			//in the loop, if the current entry is bigger than the maximum known one, make the new maximum into this entry, and make the maxIndex this action
			//we will control the values in the sub_rec array and use them later
			//basically, if we find an action that works, better than previously tested actions, we will make the entire array zero, and then make the ith entry in the array non-zero
			//this means, later, we will only have to search for that non-zero value in the add_rec array to find the recommended action
			for (int n = 0; n < 3; n++) {
				sub_rec[n] = 0;
			}
			sub_rec[(i - 3)] = maxindex;
		}
		else if (difference[i] == max) {
			sub_rec[(i - 3)] = maxindex;
		}
	}

	//loop through the add_rec arrays
	for (int a = 0; a < sizeof(add_rec) / sizeof(add_rec[0]); a++) {
		//if we find that an add_rec value is non-zero (which the logic above means that it's recommended), print a statement that recommends it
		//the second logic statement here is used because we're going to loop through the add_rec array 4 times, and we don't want the statement to print every time, just once
		//instead of using cout, you could use an LED of a certain color, or whatever you want
		if ((add_rec[a] != 0) && (a == 0)) {
			cout << "Score more in the floor goals" << endl;
		}
		if ((add_rec[a] != 0) && (a == 1)) {
			cout << "Add a Purple Cube to the Towers" << endl;
		}
		if ((add_rec[a] != 0) && (a == 2)) {
			cout << "Add a Green Cube to the Towers" << endl;
		}
		if ((add_rec[a] != 0) && (a == 3)) {
			cout << "Add an Orange Cube to the Towers" << endl;
		}
	}
	
	//and then we do the same thing with subtraction recommendations. This way, we print both recommendations.
	for (int s = 0; s < sizeof(add_rec) / sizeof(add_rec[0]); s++) {
		if ((sub_rec[s] != 0) && (s == 0)) {
			cout << "Score more in the floor goals" << endl;
		}
		if ((sub_rec[s] != 0) && (s == 1)) {
			cout << "Descore a Purple Cube from the Towers" << endl;
		}
		if ((sub_rec[s] != 0) && (s == 2)) {
			cout << "Descore a Green Cube from the Towers" << endl;
		}
		if ((sub_rec[s] != 0) && (s == 3)) {
			cout << "Descore an Orange Cube from the Towers" << endl;
		}
	}
return 0;

}

3 posts were merged into an existing topic: Tower Takeover Recommendation Code