c++ how to have the cpu keep choosing a play from a menu

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
theprodigy
Posts: 5
Joined: December 9th, 2018, 9:51 pm

c++ how to have the cpu keep choosing a play from a menu

Post by theprodigy » December 14th, 2018, 11:46 pm

I am trying to write a function for the CPU to keep calling a play in a do while loop (which I am assuming is correct) with a pause in between and for the menu to be brought up to the user after each selection from the playbook function that contains the playbook menu. I am not an expert with the cin operator, but my playbook function works perfectly when the user is entering the plays but the cursor hangs when it is calling the function_cpu for the cpu to make the selection. I am sure I am missing something in the code here. I put some notes in the code below.


Code: Select all

int function_CPU(int &choice , int &cpu_random_play, int &result,int &down, int &yards_gained, int &yards_to_go) {
	// want this function to keep to looping and the cpu keep calling plays until downs > 4 -- with a pause in between
	// so the end user can see what the cpu is calling

	do {
			
		//have CPU call a random play from the list -- not dependent on down and distance or offense/defense attribution
		srand((unsigned)time(NULL));

		//generate random 1 or 2 -- either qb sneak or off guard run
		cpu_random_play = rand() % 2 + 1; 

		//calls this function which has a menu to a choose but then stops at the cin prompt
		//from within that function

		//for the player 1 function works perfectly but when the cpu is trying to access cin, prompt is
		//waiting for user input and doesnt get the cpu input

		playbook(playbook_choice);

		//??? How to make the CPU automatically select a play!!!!!!!!
		if (cpu_random_play == 1) {		
			//chooses the play 1 from the playbook menu
			playbook_choice = 1;		
			playbook_qb_sneak(result, down, yards_gained, yards_to_go);	
		}

		if (cpu_random_play == 2) {
			//chooses the play 2 from the playbook menu
			playbook_choice = 2;
			off_guard_run(result, down, yards_gained, yards_to_go);
		}
		
	}while (player_control = 2 && down <= 4);

	return choice, cpu_random_play, result,down, yards_gained,yards_to_go;









albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: c++ how to have the cpu keep choosing a play from a menu

Post by albinopapa » December 15th, 2018, 9:13 am

Not sure about your issue, but there are some errors in your code.

Code: Select all

 }while (player_control = 2 && down <= 4);
This assigns 2 to player_control, and performs a logical and with !0 and down <= 4. So it's true and down <= 4.

The other is you are returning return choice, cpu_random_play, result,down, yards_gained,yards_to_go;

which means the only thing actually returned is yards to go, because that is the last thing after all the commas.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: c++ how to have the cpu keep choosing a play from a menu

Post by albinopapa » December 15th, 2018, 9:29 am

The while thing should probably be: while( player_control == 2 && down <= 4 ).

The return is another story. It depends on what you are wanting to return. If you are wanting all that info, then you should encapsulate that data in a struct and return the struct.

Since you aren't needing the parameters to the function, just create a struct and have the function fill in the struct object and return it.

As far as the CPU choosing a play and having it shown to the user, I'd say use std::cout to display the play, and use std::chrono::high_resolution_clock or std::chrono::standard_clock to keep track of time, and do a busy loop or something. You'll have to #include <chrono> to use the clocks.

Code: Select all

// Pause for 1 second
void Pause( int milliseconds = 1000 )
{
      const auto start = std::chrono::standard_clock::now();
      while( std::chrono::duration( std::chrono::standard::clock::now() - start )::count() < milliseconds );
}
This should ( though haven't tested ) cause a loop that keeps going for the number of milliseconds specified in the function parameter. Though, I might have it wrong and the default will be nanoseconds, so a value of 1000 will only be a 1 millisecond delay. Just adjust accordingly I suppose.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

theprodigy
Posts: 5
Joined: December 9th, 2018, 9:51 pm

Re: c++ how to have the cpu keep choosing a play from a menu

Post by theprodigy » December 15th, 2018, 4:27 pm

Basically, I just want to the computer (player_control == 2) to keep choosing a play while on offense (also of course when down is less than or equal to 4). I want the playbook to appear, the number that the comp chooses to appear via the prompt and for the loop to cycle through slowly, so that the end user can actually read and see what play that the computer chooses. I will include more of the code below.

The chrono....pause code was throwing me compiler errors, but there very well could be errors in my code, since I am a beginner.

Code: Select all

//Playbook function

int playbook(int &playbook_choice) {

	cout << "Please choose a play from the options below : " << endl;
	cout << "================================================" << endl;
	cout << "1." << plays[0] << endl;
	cout << "2." << plays[1] << endl;
	cout << "3." << plays[2] << endl;
	cout << "4." << plays[3] << endl;
	cout << "5." << plays[4] << endl;
	cout << "6." << plays[5] << endl;
	cout << "7." << plays[6] << endl;
	cout << "8." << plays[7] << endl;
	cout << "9." << plays[8] << endl;
	cout << "10." << plays[9] << endl;
	cout << "11." << plays[10] << endl;
	cout << "12." << plays[11] << endl;
	cout << "13." << plays[12] << endl;
	cout << "14." << plays[13] << endl;
	cout << "15." << plays[14] << endl;
	cout << "16." << plays[15] << endl;
	cout << "17." << plays[16] << endl;
	cout << "18." << plays[17] << endl;
	cout << "19." << plays[18] << endl;


	cin >> playbook_choice;

	do {

		switch (playbook_choice) {

		case 1:
			cout << "You selected the" << " " << plays[0] << " " << "play" << endl;
			break;
		case 2:
			cout << "You selected the" << " " << plays[1] << " " << "play" << endl;
			break;
		case 3:
			cout << "You selected the" << " " << plays[2] << " " << "play" << endl;
			break;
		case 4:
			cout << "You selected the" << " " << plays[3] << " " << "play" << endl;
			break;
		case 5:
			cout << "You selected the" << " " << plays[4] << " " << "play" << endl;
			break;
		case 6:
			cout << "You selected the" << " " << plays[5] << " " << "play" << endl;
			break;
		case 7:
			cout << "You selected the" << " " << plays[6] << " " << "play" << endl;
			break;
		case 8:
			cout << "You selected the" << " " << plays[7] << " " << "play" << endl;
			break;
		case 9:
			cout << "You selected the" << " " << plays[8] << " " << "play" << endl;
			break;
		case 10:
			cout << "You selected the" << " " << plays[9] << " " << "play" << endl;
			break;
		case 11:
			cout << "You selected the" << " " << plays[10] << " " << "play" << endl;
			break;
		case 12:
			cout << "You selected the" << " " << plays[11] << " " << "play" << endl;
			break;
		case 13:
			cout << "You selected the" << " " << plays[12] << " " << "play" << endl;
			break;
		case 14:
			cout << "You selected the" << " " << plays[13] << " " << "play" << endl;
			break;
		case 15:
			cout << "You selected the" << " " << plays[14] << " " << "play" << endl;
			break;
		case 16:
			cout << "You selected the" << " " << plays[15] << " " << "play" << endl;
			break;
		case 17:
			cout << "You selected the" << " " << plays[16] << " " << "play" << endl;
			break;
		case 18:
			cout << "You selected the" << " " << plays[17] << " " << "play" << endl;
			break;
		case 19:
			cout << "You selected the" << " " << plays[18] << " " << "play" << endl;
			break;
		case 0:
			std::exit(0);
			break;
		default:
			cout << "Invalid selection!!! , Please enter a number from 1-7 to choose a play!" << endl;
			break;
		}

	} while (playbook_choice > 19 || playbook_choice < 1);


	return playbook_choice;
}

//Function Comp

int function_CPU(int &cpu_random_play) {
	// want this function to keep to looping and the cpu keep calling plays until downs > 4 -- with a pause in between
	// so the end user can see what the cpu is calling

	do {
			
		//have CPU call a random play from the list -- not dependent on down and distance or offense/defense attribution
		srand((unsigned)time(NULL));

		//generate random 1 or 2 -- either qb sneak or off guard run
		cpu_random_play = rand() % 2 + 1; 

		//calls this function which has a menu to a choose but then stops at the cin prompt
		//from within that function

		//for the player 1 function works perfectly but when the cpu is trying to access cin, prompt is
		//waiting for user input and doesnt get the cpu input

		playbook(playbook_choice);

		//??? How to make the CPU automatically select a play!!!!!!!!
		if (cpu_random_play == 1) {		
			//chooses the play 1 from the playbook menu
			playbook_choice = 1;		
			playbook_qb_sneak(result, down, yards_to_go);	
		}

		if (cpu_random_play == 2) {
			//chooses the play 2 from the playbook menu
			playbook_choice = 2;
			off_guard_run(result, down, yards_to_go);
		}
		
		
	}while (player_control == 2 && down <= 4);

	return cpu_random_play;

}







The code below was giving me a few errors that the compiler did not like.

Code: Select all


// Pause for 1 second
void Pause( int milliseconds = 1000 )
{
      const auto start = std::chrono::standard_clock::now();
      while( std::chrono::duration( std::chrono::standard::clock::now() - start )::count() < milliseconds );
}



cameron
Posts: 794
Joined: June 26th, 2012, 5:38 pm
Location: USA

Re: c++ how to have the cpu keep choosing a play from a menu

Post by cameron » December 15th, 2018, 8:08 pm

I'm not sure I entirely understand what you mean by "keep choosing a play while on offense." In most programs, they run on a single thread. Meaning only 1 task happens at a time. In a multithreaded situation, multiple things can be done at once. However, in this instance single threaded is surely what you want. And so the code should be structured so that the AI reacts to whatever the user does and the user reacts to what the ai does. If you're trying to simulate a play, its probably going to need to be done in one function after you parse user input.

To do something over again your choices are loops and recursion. Loops are best for simplicity.
As for outputting what the AI does just use std::cout

This is probably what papa meant(no idea what chrono::standard is):

Code: Select all

using clock = std::chrono::high_resolution_clock;
	const auto start = clock::now();
	while (std::chrono::duration_cast<std::chrono::milliseconds>(clock::now() - start) < milliseconds);
However, you don't want to use a busy loop and waste cpu cycles. Use std::this_thread::sleep_for or std::getline() to wait for user to press enter or soemthing of the likes.
Computer too slow? Consider running a VM on your toaster.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: c++ how to have the cpu keep choosing a play from a menu

Post by albinopapa » December 15th, 2018, 10:04 pm

Ok, let me bring up a topic that won't be covered by chili in the current series that I remember, but he did cover it in his original series. It's called a finite state machine.

The simplest way to implement such a thing would be to use some enumerations, like:

Code: Select all

enum class PlayState
{
   PickPlay, RunPlay, PassPlay
};
enum class GameState
{
   ShowPlayerPlaybook, ShowCPUPlaybook, ShowCPUPlayChoice, ExecuteDown
};
Then, give each player their own class ( CPU, Human ) and store a PlayState in each.
Same for the main game logic, create a class called Game and give it a GameState enum.

What this does is allows you to handle specific states separately and helps clarify what state the AI is in. Once it is the AI's turn, you enter a GameState::ShowCPUPlaybook state for game and a PlayState::PickPlay state for the CPU. Once the CPU picks it's play, the CPU could enter a PlayState::WaitingForWhistle state. The Game object then goes to a GameState::ShowCPUPlayChoice state and wait for a specified amount of time or user input. Once the time has elapsed or user presses a key, then the game state would need to change to GameState::ExecuteDown.

Hopefully you see where this is going. You just create enums for each state of the game and for each state of the CPU's decisions. After each action taken, you need to determine what state to put each object in.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: c++ how to have the cpu keep choosing a play from a menu

Post by albinopapa » December 15th, 2018, 10:07 pm

Well, it was suppose to be std::chrono::steady_clock
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply