I'm learning python still so the rest of my code may be flawed but my main problem is I cant disable this button when the Wood and Stone variable are at 0. I've tried using a while statement that runs the button.config(state=DISABLED) command when stone > 0 and wood > 0 but that didn't seem to work.
from tkinter import *
from tkinter import tkk
class main:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.CraftPickaxe = Button(frame, text = 'Pickaxe', command = self.craftPick)
self.CraftPickaxe.pack()
###RESOURCES###
self.wood = 1
self.stone = 1
self.pickaxe = 0
def craftPick(self):
self.stone -= 1
self.wood -= 1
self.pickaxe += 1
print(self.stone)
print(self.wood)
print(self.pickaxe)
def loop(self):
while True:
if self.stone < 0 and self.wood < 0:
self.CraftPickaxe.config(state=DISABLED)
elif self.stone > 0 and self.wood > 0:
self.CraftPickaxe.config(state=NORMAL)
root = Tk()
b = main(root)
root.mainloop()
EDIT:
what I think is happening now is that its not constantly checking the variables to see if it goes below zero and therefore not disabling at all. What I'm thinking may need to happen is a check that runs in the craftPick function.
I think that your problem is that your variable is 0 and not a negative number.
So when you check if your variable is less than 0 it won't disable it because your variable is not smaller than 0, it is exactly 0.
Try with this better
while True:
if self.stone < 1 and self.wood < 1:
self.CraftPickaxe.config(state=DISABLED)
elif self.stone > 0 and self.wood > 0:
self.CraftPickaxe.config(state=NORMAL)
Also, you must avoid the loop.
def craftPick(self):
self.stone -= 1
self.wood -= 1
self.pickaxe += 1
if self.stone < 1 and self.wood < 1:
self.CraftPickaxe.config(state=DISABLED)
elif self.stone > 0 and self.wood > 0:
self.CraftPickaxe.config(state=NORMAL)
Related
from src.common import config, settings, utils
import time
import math
from src.routine.components import Command
from src.common.vkeys import press, key_down, key_up
class Adjust(Command):
"""Fine-tunes player position using small movements."""
def __init__(self, x, y, max_steps=5):
super().__init__(locals())
self.target = (float(x), float(y))
self.max_steps = settings.validate_nonnegative_int(max_steps)
def main(self):
counter = self.max_steps
toggle = True
error = utils.distance(config.player_pos, self.target)
while config.enabled and counter > 0 and error > settings.adjust_tolerance:
if toggle:
d_x = self.target[0] - config.player_pos[0]
threshold = settings.adjust_tolerance / math.sqrt(2)
if abs(d_x) > threshold:
walk_counter = 0
if d_x < 0:
key_down('left')
while config.enabled and d_x < -1 * threshold and walk_counter < 60:
time.sleep(0.05)
walk_counter += 1
d_x = self.target[0] - config.player_pos[0]
key_up('left')
else:
key_down('right')
while config.enabled and d_x > threshold and walk_counter < 60:
time.sleep(0.05)
walk_counter += 1
d_x = self.target[0] - config.player_pos[0]
key_up('right')
counter -= 1
else:
d_y = self.target[1] - config.player_pos[1]
if abs(d_y) > settings.adjust_tolerance / math.sqrt(2):
if d_y < 0:
time.sleep(0.25)
press(Key.ROPE, 1, up_time=0.1)
time.sleep(2)
# press(Key.JUMP, 1, up_time=0.1)
# time.sleep(0.175)
# UpJump('up').main()
else:
key_down('down')
time.sleep(0.05)
press(Key.JUMP, 3, down_time=0.1)
key_up('down')
time.sleep(0.5)
counter -= 1
error = utils.distance(config.player_pos, self.target)
toggle = not toggle
This section of code is from a bot i'm working on for a game, essentially. The bot checks my X and Y and will make my character move left or right to adjust for an X,Y I give it. The issue with this is if I over-jump the target, since my character walks through the correct (X,Y) while overshooting, it will consider itself as done.
I want it to sleep for a second or two after running once, then recheck my (X,Y) and rerun if needed to avoid overshooting.
I've been trying for a while, and want to avoid just running the same thing tons of times
I'm trying to figure out how I can solve this issue. I have a Raspberry Pi that is set up with a breadboard that consists of:
1 RGB light
2 buttons (left and right)
1 OLED screen
Each component works and I can run each one. What I'm trying to do is write a script that will allow me to select the "mode" with the left button (everything off vs lights vs screen on).
When a mode is selected, the right button then allows me to select between options within that mode. Below is the code as I have it:
def off():
lights = [red,green,blue]
for light in lights:
light.off()
def lightSelector():
off()
number = 0
while number < 5:
if rightButton.is_pressed:
if number == 0:
off()
red.on()
sleep(1)
number += 1
elif number == 1:
off()
green.on()
sleep(1)
number += 1
elif number == 2:
off()
blue.on()
sleep(1)
number += 1
elif number == 3:
off()
row()
sleep(1)
number+= 1
else:
number = 0
def picture():
image = Image.open('grant.jpeg')
image_r = image.resize((width,height), Image.BICUBIC)
image_bw = image_r.convert("1")
for x in range(width):
for y in range(height):
oled.pixel(x,y,bool(int(image_bw.getpixel((x,y)))))
oled.show()
def oledOff():
oled.fill(0)
oled.show()
def buttons():
x = 0
y = 0
while y is 0:
print('x = ' , x)
print('y = ' , y)
if leftButton.is_pressed:
if x == 0 :
oledOff()
off()
sleep(0.5)
x += 1
elif x == 1:
oledOff()
off()
lightSelector()
sleep(0.5)
x += 1
elif x == 2:
oledOff()
off()
picture()
sleep(0.5)
x += 1
else:
x = 0
oledOff()
off()
buttons()
The idea is that the buttons() function is the main overall function and will call the others as needed. My issue is that once I get to y == 1, or the lightSelector() function, it no longer registers that the leftButton is being pressed and won't switch to the next mode and I'm stuck in the lightSelector() function.
I know at baseline I can spell out lightSelector within the buttons function instead of calling another function but I'm trying to not be as verbose. I don't have any experience with threading or multprocessing and looked into it but couldn't see how that would help.
I've been working on a program for the Microbit inspired by some basic blocks script I saw a few years back. The functionality of the AI controlled pixel and the player controlled pixel work as intended--which one annoying, and game breaking bug--the player ship resets to its spawn position whenever the AI ship completes its function.
I suspect this is because I have an assigned position for the ship in the beginning of the code, where it is then modified in the function itself. Removing this results in an error where a variable is not referenced--however, I cannot leave the problem alone. I welcome any guidance. The code is below.
from microbit import *
import random
enemyXpos = 4
playerXpos = 2
while True:
display.set_pixel(enemyXpos,0,4)
display.set_pixel(playerXpos,4,6)
def laser(laserXpos, laserYpos):
laserXpos = playerXpos
laserYpos = 3
for i in range (4):
display.set_pixel(laserXpos,laserYpos,9)
if laserYpos > 0:
display.set_pixel(laserXpos,laserYpos,0)
laserYpos -= 1
display.set_pixel(laserXpos,laserYpos,9)
if laserYpos == 0 and laserXpos == enemyXpos:
display.show(all_booms, delay=200)
score = score + 1
continue
elif laserYpos == 0:
display.set_pixel(bombXpos,bombYpos,0)
laserYpos = newlaserYpos
sleep (200)
def enemy_left(enemyXpos, playerXpos):
enemyXpos = 4
for i in range (4):
display.clear()
enemyXpos -= 1
display.set_pixel(enemyXpos,0,4)
display.set_pixel(playerXpos,4,6)
if button_a.is_pressed() and button_b.is_pressed():
laser(laserXpos,laserYpos)
elif button_a.is_pressed() and playerXpos > 0:
playerXpos -= 1
elif button_b.is_pressed() and playerXpos < 4:
playerXpos += 1
sleep(200)
def enemy_right(enemyXpos, playerXpos):
enemyXpos = 0
for i in range (4):
display.clear()
enemyXpos += 1
display.set_pixel(enemyXpos,0,4)
display.set_pixel(playerXpos,4,6)
if button_a.is_pressed() and button_b.is_pressed():
laser(laserXpos,laserYpos)
elif button_a.is_pressed() and playerXpos > 0:
playerXpos -= 1
elif button_b.is_pressed() and playerXpos < 4:
playerXpos += 1
sleep(200)
enemy_left(enemyXpos, playerXpos)
enemy_right(enemyXpos, playerXpos)
At the moment, I managed to code, successfully, a simulation for a work that I need to do. However, I'm fairly new to python. And so, I'm now in the process of making the simulation more efficient.
For instance:
if random.random() < mm:
z = numpy.random.choice(pat)
if random.random() < 0.5:
if random.random() < mut:
if maleadult[z][0] == 0:
malejuv[y][x][0] = 1
elif maleadult[z][0] == 1:
malejuv[y][x][0] = 0
else:
malejuv[y][x][0] = maleadult[z][0]
else:
if random.random() < mut:
if femaleadult[z][0] == 0:
malejuv[y][x][0] = 1
elif femaleadult[z][0] == 1:
malejuv[y][x][0] = 0
else:
malejuv[y][x][0] = femaleadult[z][0]
if random.random() < 0.5:
if random.random() < mut:
if maleadult[z][1] == 0:
malejuv[y][x][1] = 1
elif maleadult[z][1] == 1:
malejuv[y][x][1] = 0
else:
malejuv[y][x][1] = maleadult[z][1]
else:
if random.random() < mut:
if femaleadult[z][1] == 0:
malejuv[y][x][1] = 1
elif femaleadult[z][1] == 1:
malejuv[y][x][1] = 0
else:
malejuv[y][x][1] = femaleadult[z][0]
where:
mm - male dispersal,
mf - female dispersal,
mut - mutations,
pat - patch,
maleadult - adult male,
femaleadult - adult female,
malejuv - juvenile male,
femalejuv - juvenile female.
As you can see, the code is big. And this is only for males and when they disperse. The rest of the code is very similar. These are standard genetic and demographic processes - but I feel like this can be improved. I feel like these processes are simple enough, so maybe code as big as this is not necessary.
Does anyone have any ideas to shorten this and, by consequence, making it more efficient?
Your example does not have any loops but it looks like it could be simplified by one:
if random.random() < mm:
z = numpy.random.choice(pat)
for i in range(2):
if random.random() < 0.5:
if random.random() < mut:
if maleadult[z][i] == 0:
malejuv[y][x][i] = 1
elif maleadult[z][i] == 1:
malejuv[y][x][i] = 0
else:
malejuv[y][x][i] = maleadult[z][i]
else:
if random.random() < mut:
if femaleadult[z][i] == 0:
malejuv[y][x][i] = 1
elif femaleadult[z][i] == 1:
malejuv[y][x][i] = 0
else:
malejuv[y][x][i] = femaleadult[z][i]
It is also possible to pass a mutable object as reference to a function which can modify it, which allows further reduction of almost redundant code. I've added some data to test it:
#!python3
#coding=utf-8
import random
maleadult = [[["male adult"], ["another male adult"], ]]
femaleadult = [[["female adult"], ["another female adult"], ]]
malejuv = [[[["male juv"],["another male juv"]]]]
mut = 0.5
mm = 1.0
x = 0
y = 0
z = 0
def some_logic(a, j):
""" does something """
if random.random() < mut:
if a[z][i] == 0:
j[y][x][i] = 1
elif a[z][i] == 1:
j[y][x][i] = 0
# added!
else:
j[y][x][i] = 0
else:
j[y][x][i] = a[z][i]
if random.random() < mm:
z = 0 #numpy.random.choice(pat)
for i in range(2):
print(i)
if random.random() < 0.5:
some_logic(maleadult, malejuv)
else:
some_logic(femaleadult, malejuv)
print(maleadult)
print(malejuv)
print(femaleadult)
I wrote this Python interpreter for a language called Self-modifying Brainf*** (SMBF). Today I discovered a bug where if the program dynamically creates code at the initial cell or after on the tape, it will not be executed. I wrote this interpreter to look as close as possible to the Ruby interpreter on the linked page. Note that this bug may exist in the original Ruby interpreter, too. I don't know, I haven't used it.
The way SMBF is different from normal BF is that the source code is placed on the tape to the left of the cell that the pointer starts at. So the program <. would print the last character of the source (a period). This works.
Note that I trimmed some code out so it's still runnable but takes less space in this post.
The interpreter:
from __future__ import print_function
import os, sys
class Tape(bytearray):
def __init__(self):
self.data = bytearray(b'\0' * 1000)
self.center = len(self.data) // 2
def __len__(self):
return len(self.data)
def __getitem__(self, index):
try:
return self.data[index + self.center]
except:
return 0
def __setitem__(self, index, val):
i = index + self.center
if i < 0 or i >= len(self.data):
# resize the data array to be large enough
new_size = len(self.data)
while True:
new_size *= 2
test_index = index + (new_size // 2)
if test_index >= 0 and test_index < new_size:
# array is big enough now
break
# generate the new array
new_data = bytearray(b'\0' * new_size)
new_center = new_size // 2
# copy old data into new array
for j in range(0, len(self.data)):
new_data[j - self.center + new_center] = self.data[j]
self.data = new_data
self.center = new_center
self.data[index + self.center] = val & 0xff
class Interpreter():
def __init__(self, data):
self.tape = Tape()
# copy the data into the tape
for i in range(0, len(data)):
self.tape[i - len(data)] = data[i]
# program start point
self.entrypoint = -len(data)
def call(self):
pc = self.entrypoint
ptr = 0
# same as -len(self.tape) // 2 <= pc + self.tape.center < len(self.tape) // 2
while -len(self.tape) <= pc < 0: # used to be "while pc < 0:"
c = chr(self.tape[pc])
if c == '>':
ptr += 1
elif c == '<':
ptr -= 1
elif c == '+':
self.tape[ptr] += 1
elif c == '-':
self.tape[ptr] -= 1
elif c == '.':
print(chr(self.tape[ptr]), end="")
elif c == ',':
sys.stdin.read(1)
elif c == '[':
if self.tape[ptr] == 0:
# advance to end of loop
loop_level = 1
while loop_level > 0:
pc += 1
if chr(self.tape[pc]) == '[': loop_level += 1
elif chr(self.tape[pc]) == ']': loop_level -= 1
elif c == ']':
# rewind to the start of the loop
loop_level = 1
while loop_level > 0:
pc -= 1
if chr(self.tape[pc]) == '[': loop_level -= 1
elif chr(self.tape[pc]) == ']': loop_level += 1
pc -= 1
pc += 1
# DEBUG
#print(pc, self.tape.data.find(b'.'))
def main():
# Working "Hello, World!" program.
#data = bytearray(b'<[.<]>>>>>>>>+\x00!dlroW ,olleH')
# Should print a period, but doesn't.
data = bytearray(b'>++++++++++++++++++++++++++++++++++++++++++++++')
intr = Interpreter(data)
intr.call()
#print(intr.tape.data.decode('ascii').strip('\0'))
if __name__ == "__main__":
main()
The problem:
This line is how I set the program (so I can run this on Ideone.com):
data = bytearray(b'++++++++++++++++++++++++++++++++++++++++++++++')
The program adds to the cell until it is 46, which is the decimal value for an ASCII ., which should print the current cell (a period). But for some reason, the program counter pc never gets to that cell. I want the program to run all code it finds until it hits the end of the tape, but I'm having a hard time getting the program counter to take into account the center of the tape, and ensure that it's still correct if the tape is resized in __setitem__.
The relevant line is (what I was trying out):
while -len(self.tape) <= pc < 0:
which was originally this:
while pc < 0:
So I think that the while line either needs to be adjusted, or I need to change it to while True: and just use a try/except while getting chr(self.tape[pc]) to determine if I've hit the end of the tape.
Does anyone see what is wrong or how to fix it?
Found a solution thanks to Sp3000.
self.end = 0 in Tape.__init__, self.end = max(self.end, index+1) in Tape.__setitem__ and replace the while in Interpreter.call with while pc < self.tape.end:.