Computer decision mechanism - python

I have 5 players where they throw dice. We cannot use any external input such as onclick action or something.
How do I make the computer decide whether it is good to stop throwing? The stopping criteria is either you didn't throw 1,5 or straight or triples or higher. Everything counts as a point and if you hit something, lets say triple sixes you now can decide whether you throw again, but without these three dice. But if you fail to hit anything on the next throw, you lose every point you've got in the section. Or keep the sixes, which gives you 600 points.
def game(length, output = True):
round_no = 0
avg_pts = 0
player_points[0,0,0,0,0]
while output:
round_no += 1
for i in range 5:
lock = true
while lock:
dice_throw(number_of_throws)
def dice_throw(number_of_throws):
throw_values = []
for i in range(number_of_throws):
throw_values.append(randint(1,6))
throw_values.sort()
for i in range(throw_values)
How can I make a mechanism that decides if its good to continue throwing or not?

Related

How to change value to zero but not in the first iteration of a loop

I am trying to implement turning of front wheels in PyBox2D, for now, I was able to make it turn left/right but I am not able to stop it when the angle reaches zero (to make the car to go straight)
My goal is to stop turning when the angle of a wheel reaches zero or value similar to zero, but not on the beginning (sometimes when the angles are zero they do not move at all, and if possible I would like to make it independent from pressing key on a keyboard (moving those two nested if statements out of the if keyboard_is_pressed(hotkey) part did not help
I hope I made myself clear and thank you very much for any help
EDIT I tried to implement solution given in the answer, it kind of worked but I tried to improve it and now I am stuck again, the wheels turn, but when they return to their initial position they stop moving. One of problems can be that when I press "a" or "d" key my variable self.ticking changes by more than just one, because I am not able to press the key for such a short period of time.
variable self.on_the_beginning is equivalent to on_starting_race from the answer below:
def control(self): # This makes control independent from visualisation
#Front left suspension: index 2
#Front right suspension: index 3
print(self.ticking)
if keyboard.is_pressed("a"):
self.suspensions[2].motorSpeed = -5
self.suspensions[3].motorSpeed = -5
self.ticking -= 1
if keyboard.is_pressed("d"):
self.suspensions[2].motorSpeed = 5
self.suspensions[3].motorSpeed = 5
self.ticking += 1
if self.ticking <= -3:
self.ticking = -3
self.on_the_beginning = True
elif self.ticking >= 3:
self.ticking = 3
self.on_the_beginning = True
if np.radians(-5) <= self.tires[2].wheel.angle <= np.radians(5) and self.on_the_beginning == True and self.ticking !=0:
self.suspensions[2].motorSpeed = 0
self.suspensions[3].motorSpeed = 0
self.tires[2].SetAngularVelocity = 0
self.tires[3].SetAngularVelocity = 0
self.ticking = 0
on_the_beginning = False
If i understand correctly, you can have a variable, say on_starting_race, set to false, then check whenever it is above a set number (say, when it's above 10 you know for a fact that the race has already started and the car moved at least for a few seconds), then change that value to True, now add an if statement to determine whether the value is close to 0 (say val<5) AND on_starting_race is True.
There might be a more elegant way, but this is pretty straight forward(assuming you check the state of the car every frame or a set period of time).
Sorry, because I am not 100% sure of your problem without the whole code.
I think the solution could be using an input parameter in you function, let's say first_run, that you can control from inside and outside the function.
def control(self, first_run=True):
This way, you may start the race (from your main program) setting first_run to True, so you don't care about the angle. And use this same function setting first_run to False the rest of the times.
You can also use a self.first_run variable that you may set to True in the init, then setting self.first_run to False if it is True (which is really the first time you use your control() function).

Creating Decision Tree for Simple Game

I am currently a new student learning python. This is my first real experience doing much computer coding. For my project I must create a fill in the blank quiz with three different levels of difficulty. Once the user chooses a difficulty the game should print a different paragraph based on the difficulty. Each section of the game works fine but I am having trouble creating the "difficulty chooser." No matter the difficulty I choose, the game rolls through the easy, medium, and the hard level in order and then crashes.
Below I have included the introductory text and the difficulty chooser. I would love some help. I am sure there are really obvious things I don't see. Thank you!
def introduction():
print '''Welcome to Kevin's European Geography Quizzes.
Test your knowledge of European geography. \n'''
difficulty = raw_input('''Do you want to play an easy, medium, or hard game?
Please type the number 1 for easy, 2 for medium, or 3 for hard.\n''' )
game_chooser(difficulty)
def game_chooser(difficulty):
cursor = 0
difficulty_choice = [easy_game(), medium_game(), hard_game()]
#each element of the above list links to a procedure and starts one of the
#mini-games.
while cursor < len(difficulty_choice):
if difficulty != cursor:
cursor += 1
else:
difficulty_choice[cursor]
break
You can do with if else if you only want to print something but if you have separate code block for each level then define a function for each level and use this pattern :
You can define the function blocks and call them basis on user input something like:
# define the function blocks
def hard():
print ("Hard mode code goes here.\n")
def medium():
print ("medium mode code goes here\n")
def easy():
print ("easy mode code goes here\n")
def lazy():
print ("i don't want to play\n")
# Now map the function to user input
difficulty_choice = {0 : hard,
1 : medium,
4 : lazy,
9 : easy,
}
user_input=int(input("which mode do you want to choose : \n press 0 for hard \n press 1 for medium \n press 4 for lazy \n press 9 for easy "))
difficulty_choice[user_input]()
Then invocation of function block will be:
difficulty_choice[num]()
Add a conditional for the input.
if difficulty == 'easy':
print("here is an easy game")
elif difficulty == 'medium':
print('here is a medium game')
elif difficulty == 'hard':
print('here is hard')
else:
print('Please enter valid input (easy, medium, hard)')
Under each if statement put your game code.
The reason your code goes through all the difficulties is because of this line:
difficulty_choice = [easy_game(), medium_game(), hard_game()]
When Python sees something like easy_game(), it calls the easy_game function and replaces it with the result. You don't want to call the function yet though, so you can take off the parenthesis to store just the function instead:
difficulty_choice = [easy_game, medium_game, hard_game]
This will mean you have to call the function after you take it out of the array.
As for the crash, when you use raw_input() you get a string back. That means when you type in the 1 to decide for an easy game, you get the character 1, which is represented by the number 49. That's why your code goes through everything and crashes: Your 1 is really a 49. In fact, if you type 1 < '1' into the interpreter, you'll get True back.
To fix that, you can pass the result of raw_input() to the int() function, which will parse it and give you the proper integer (or throw an exception if it can't be parsed). The last line of introduction would then look like game_chooser(int(difficulty)).
You could also skip most of the code of game_chooser by just indexing into the array (that's what they're for, after all):
def game_chooser(difficulty):
# the lack of parens here means you get the function itself, not what it returns
difficulty_choice = [easy_game, medium_game, hard_game]
#each element of the above list links to a procedure and starts one of the
#mini-games.
# note the parens to actually call the retrieved function now
difficulty_choice[difficulty]()

What is the best way to exit out of an unbounded loop after n failures in Python?

I am newbie in Python. And I am wondering how to exit out of an unbounded loop after n failures. Using counter seems for me unpythonic.
This is my code:
while(True):
#get trigger state
trigState = scope.ask("TRIG:STATE?")
#check if Acq complete
if( trigState.endswith('SAVE') ):
print 'Acquisition complete. Writing into file ...\n'
#save screen
#rewrite in file
#check if trigger is still waiting
elif( trigState.endswith('READY') ):
print 'Please wait ...\n'
#if trigger neither in SAVE nor in READY mode
else:
#THIS IS FAILURE!!!
print 'Failure: k tries remaining'
#wait for several seconds before next iteration
time.sleep(2)
Note that loop must be unbounded - it may iterate arbitrarily many times until number of tries exceeded.
Is there an elegant (or at least pythonic) method to meet the requirements?
To be "pythonic" you'll want to write code that conforms to the Zen of Python and a relevant rules here are:
Explicit is better than implicit.
Readability counts.
You should be explicit about the number of failures you allow, or the number of failures remaining. In the former case:
for number_of_failures in range(MAX_FAILURE):
...
expresses that intent, but is clunky because each time through the loop you are not necessarily failing, so you'd have to be be contorted in counting successes, which would impact readability. You can go with:
number_of_failures = 0
while number_of_failures < MAX_FAILURES:
...
if this_is_a_failure_case:
number_of_failures += 1
...
This is perfectly fine, as it says "if I haven't failed the maximum number of times, keep going. This is a little better than:
number_of_failures = 0
while True:
...
if this_is_a_failure_case:
number_of_failures += 1
...
if number_of_failures == MAX_FAILURES: #you could use >= but this isn't necessary
break
which hides the exit case. There are times when it is perfectly fine to exit the loop in the middle, but in your case, aborting after N failures is so crucial to what you want to do, that the condition should be in the while-loop condition.
You can also rephrase in terms of number of failures remaining:
failures_remaining = MAX_FAILURES
while failures_remaining > 0:
...
if this_is_a_failure_case:
failures_remaining -= 1
...
If you like functional programming, you can get rid of the loop and use tail recursion:
def do_the_thing():
def try_it(failures_remaining = MAX_FAILURES):
...
failed = ....
...
try_it(failures_remaining-1 if failed else failures_remaining)
try_it()
but IMHO that isn't really an improvement. In Python, we like to be direct and meaningful. Counters may sound clunky, but if you phrase things well (after all you are counting failures, right?) you are safely in the realm of Pythonic code.
Using an if statement to number your attempts seems simple enough for your purposes. It's simple, and (to my eyes anyway) easily readable, which suits your Pythonic criterion.
Within your while loop you you can do:
failure_no = 0
max_fails = n #you can substitute an integer for this variable
while:
#...other code
else:
failure_no += 1
if failure_no == max_fails:
break
print 'Failure: '+str(max_fails - failure_no)+' tries remaining'
This will only iterate the number of attempts if a else/failure condition is met, if you wanted to count the total number of run throughs, not just failures, you could put the failure_no +=1 right after your while rather than within the else block.
NB You could easily put a notification inside your escape:
eg
if failure_no == max_fails:
print 'Maximum number of failures reached'
break
E.g. you can use an if statement and raise an error after n tries.
You only need a limit and a counter.
while(True):
#get trigger state
limit = 5
counter = 0
trigState = scope.ask("TRIG:STATE?")
#check if Acq complete
if( trigState.endswith('SAVE') ):
print 'Acquisition complete. Writing into file ...\n'
#save screen
#rewrite in file
#check if trigger is still waiting
elif( trigState.endswith('READY') ):
print 'Please wait ...\n'
#if trigger neither in SAVE nor in READY mode
else:
#THIS IS FAILURE!!!
counter +=1
print 'Failure: ', limit - counter ,' tries remaining'
if k => limit: raise RuntimeError('too many attempts')
#wait for several seconds before next iteration
time.sleep(2)
...

Why does this code make my Python interpreter hang?

I had an identical problem with my other laptop, which led me to get this new one (new in the NBC after Friends sense) -- the interpreter would hang on some kind of nested iteration, and even freeze up and/or go berserk if left to its own devices. In this case, I CTRL+C'd after about five seconds. The interpreter said it stopped at some line in the while loop, different each time, indicating that it was working but at a slooooooooooow pace. Some test print statements seemed to show some problem with the iteration controls (the counter and such).
Is it a CPU problem, or what?
from __future__ import print_function
import sys
# script is a useless dummy variable, setting captures the setting (enc or dec), steps captures the number of lines.
script, setting, steps = sys.argv
# Input handling bloc.
if setting not in ('enc', 'dec'):
sys.exit("First command line thing must either be 'enc' or 'dec'.")
try:
steps = int(steps)
except:
sys.exit("Second command line thing must be convertable to an integer.")
# Input string here.
string_to_convert = raw_input().replace(' ', '').upper()
if setting == 'enc':
conversion_string = ''
counter = 0
while len(conversion_string) < len(string_to_convert):
for char in string_to_convert:
if counter == steps:
conversion_string += char
counter = 0
counter += 1
steps -= 1
print(conversion_string)
Depending on the starting value of steps its possible for counter and steps to never be equal, which means conversion_string is never altered, so it is always shorter than string_to_convert and the loop never ends.
A naive example is, let steps=-1, since counter starts at 0 and increments, and steps always decrements, they will never be equal.
Actually, on further inspection, if steps is less than len(string_to_convert) this will always end in an infinite loop.
Consider:
steps=2
string_to_convert="Python"
The first iteration of the for loop will iterate counter to 2 and fetch the "t"; now steps = 1, conversion_string="t"
Next for loop will iterate counter to 1, fetch the "y"; now steps = 0, conversion_string="ty"
for loop iterates counter to 0, fetch the "P"; now steps = -1, conversion_string="tyP"
Now, steps = -1, counter can never equal it, for loop ends without changing conversion_string.
Step 4 repeats while decreasing steps without any ability to quit the while loop.
Thus, why it sometimes works and sometimes doesn't.

Implementing an Anti Spamming thing?

I have an IRC bot that I made for automating stuff.
Here's a snippet of it:
def analyseIRCText(connection, event):
global adminList, userList, commandPat, flood
userName = extractUserName(event.source())
userCommand = event.arguments()[0]
escapedChannel = cleanUserCommand(config.channel).replace('\\.', '\\\\.')
escapedUserCommand = cleanUserCommand(event.arguments()[0])
#print userName, userCommand, escapedChannel, escapedUserCommand
if flood.has_key(userName):
flood[userName] += 1
else:
flood[userName] = 1
... (if flood[userName] > certain number do...)
So the idea is that flood thing is a dictionary where a list of users who have entered in a command to the bot in the recent... some time is kept, and how many times they've said so and so within that time period.
Here's where I run into trouble. There has to be SOMETHING that resets this dictionary so that the users can say stuff every once in awhile, no? I think that a little thing like this would do the trick.
def floodClear():
global flood
while 1:
flood = {} # Clear the list
time.sleep(4)
But what would be the best way to do this?
At the end of the program, I have a little line called:
thread.start_new_thread(floodClear,())
so that this thing doesn't get called at gets stuck in an infinite loop that halts everything else. Would this be a good solution or is there something better that I could do?
Your logic should be enough. If you have say:
if flood.has_key(userName):
flood[userName] += 1
else:
flood[userName] = 1
if flood[userName] > say 8:
return 0
That should make your bot ignore the user if he has spammed too many times within your given time period. What you have there should also work to clear up your flood dictionary.

Categories