Finding Next Obstacle in List - python

I am trying to create a game that moves to the end of a square. Inside the game I created obstacles by making a list of true and false (false=obstacles). What I have (but did not post) is something that detects an obstacle ONLY IF the user lands on the obstacle. However, I want to find a way to detect an obstacle BEFORE the user makes its next move and make it stay in place if the next spot will be an obstacle. In other words I want to find the next index of list before proceeding. Here's some pseudo code for a better picture:
if next_left != [[False]]: # if there is no obstacle
officially_move_left
else: # if there is an obstacle
user_do_nothing
What I have (in pseudo):
def moving_pos(user):
copy_user.pos = user.pos
if copy_user.pos +1 == [True]
user.pos += 1
copy_user.pos += 1
else:
return user.pos

if (user_position == obstacle):
next_square_is_obstacle = true
user_move_backwards
ie, move the player, detect the object, move the player back again. It's very difficult to help without seeing the actual implementation
Edit: Okay, in your new edit I don't see any reason why the program should have such constraints. However, let me suggest something new-
obstacle_index = [obs1, obs2, obs3...]
if user_position+1 in obstacle_index:
do_nothing;
else
user_move_forward;
Can you post the actual minimal working code, or at least a more detailed pseudocode of the implementation?

Related

How to minimize recursion

I'm trying to make minesweeper with tkinter in a really simple way but on the first click that break a lot of cells with no mines around it is kinda confusing. I tried checking all the cells around it by calling a function over and over again, there aren't that many cells to check but I keep getting a recursion error. How do I fix this?
def break_logic(now):
global checked
if BTNvals.get(now)==0: #check if the button has 0 mines around it
checked.append(now)
CanGo = check(now)[1] #check surroundings
for _checked in CanGo:
if _checked in checked:
CanGo.remove(_checked)
elif BTNvals.get(_checked)!=0:
button_ids[_checked-1].destroy()
CanGo.remove(_checked)
for _cans in CanGo:
button_ids[_cans-1].destroy()
break_logic(_cans) #recursion
0 means no mines around it.
It breaks a bit but not all it's supposed to.

How do I get this input to work inside of an inherited class in Python?

So, to preface this I’m self learning python and I’m trying to build a Tic-Tac-Toe game using the command line as an interface. The issue that I have is that I can’t get the input inside one of the inherited class for the player to work (so the game itself doesn’t work aside from the 3x3 board showing up on the command line)
The section of code that I’m having issues with goes as such:
class HumanPlayer(Player):
def __init__(self, letter):
super().__init__(letter)
def get_move(self, game):
valid_square = False
val = None
while not valid_square:
square = input(self.letter + ' s turn. Input move (0-9):')
# we are going to check that this is a correct value by trying to cast
# it into an integer, and if it's not, then we will say its invalid
# if that spot is not available on the board, then we also say it's invalid
try:
val = int(square)
if val not in game.available_moves:
raise ValueError
valid_square = True # if these are successful, then oh yeah!
except ValueError:
print ('Invalid Square. Try Again. ')
return val
I’ve tried to make sure that my spacing is correct within this class, but now I’m not sure what else to do. Any help, suggestions, or the like would be appreciated since I’m learning to program in general
Thanks!
Although there is nothing wrong with an object-oriented approach, and it can be the (or at least a) right approach for many problems, it looks like your program has "classes because of classes". It's probably easier if you don't bother with the object-orientation too much at this stage and focus on the main gameplay loop.
Try to imagine how the game should progress: you start the game, you make a move, another player makes a move, this continues until the game decides either play has won and then perhaps you can start a new game. And the other player might be an "AI" (tic tac toe doesn't require much intelligence) or another live player.
Your code covers what needs to happen for a single player to enter a valid square and it appears you have another class somewhere that's a Game, an instance of which has an attribute available_moves that contains all the currently valid moves. Or perhaps that Game class is the next thing you plan to write.
The main game loop would be to ask players for a move in alternating fashion, update the game board, decide if someone has won yet, and keep doing that. And you'll need to get the whole thing started, some core routine that sets up the game and the players and gets the ball rolling.
If you have a more specific problem getting all that to work, you should post a question about that - but without a more specific problem, it's hard to provide a better answer.
Where is the code for th

Is there a way to get legal moves for the person whos turn its not? python-chess

I am interested in making a chess algorithm. For this, I will be using the python-chess library. However, to make a good algorithm I need to be able to return the opposing persons legal moves even if it isn't their turn.
So in the start of the game it would return
board.legal_moves() -> [A2A4, A2A1, B2B4, B2B1, ect...]
I was wondering if during the start of the game I could say something like
board.enemy_legal_moves() > [A7A5, A7A6, ect...]
or if there is any algorithmic way I could do it.
Thank you for your time!
A solution would be to keep track of the legal moves in a list from the beginning of the game:
legal_moves = []
current_legal_moves = board.legal_moves()
legal_moves.append(current_legal_moves)
Then you can simply get the list of your enemy's legal moves by:
enemy_legal_moves = legal_moves[-1]
This will obviously not work if you want to call this for the first move in the game. If you really need to do that, then you can either:
From the start position switch to black and run the board.legal_moves(). Then take this list and add as start value like this: legal_moves = [black_legal_moves_start_pos]
Write the list of blacks 20 first legal moves from the start position and add it to legal_moves as in option 1 above.

Python thread executing function twice

Atm I'm working on a game using tkinter. I'm working on algorithm that moves enemies through the game map.
I will post only relevant lines, since the code is quiet hard-to-read.
I'm using class Timer imported from threading.
2 relevant functions are:
def add_enemies(self):
enemy = self.enemies.pop(0)
if enemy in '.':
Timer(1, self.add_enemies).start()
else:
self.move_enemy(enemy,set())
if not self.game_ended and self.enemies:
Timer(1, self.add_enemies).start()
def move_enemy(self, enemy, visited):
if type(enemy) == str:
if enemy in 'm':
enemy = Mongol(self.canvas, *self.start)
visited.add((enemy.x,enemy.y))
for move in (-1,0),(0,1),(1,0),(0,-1):
pos = (enemy.x + move[0], enemy.y+move[1])
if pos in self.way and pos not in visited:
print(pos)
enemy.move(*move)
enemy.take_shot(6)
visited.add(pos)
Timer(0.5, lambda: self.move_enemy(enemy, visited)).start()
This function should move the enemy, wait 0.5 second, then create a thread in which it recursively calls itself and moves the enemy again.
It might not be the best solution the create another thread inside the thread, but all other solutions made my GUI to freeze while executing the function.
Problem is, that Timer executes function move_enemy twice. Nothing else in the code can cause this problem.
Simple print test of enemy position shows this:
It simply moves the enemy twice, and increases its position twice as shown on the picture.
This is a wild guess, but substituting the enemy object with a new enemy object with a modified location in
Timer(0.5, lambda: self.move_enemy(enemy, visited)).start() might get the inbetween coordinates ((3,1),(5,1) and others). (If you do the same thing twice with the same input, you get two identical values.)
From the output I deduce: visited.add(pos) doesn't add positions to visited hence the if pos in self.way and pos not in visited: clause doesn't filter out already tested values (hence the (2,1)(2,1) printout). Try, if .append() works better.
I tried my best :D gl hf
Judging from the output, it looks like what's actually happening is that you were expecting things to execute in this order
print
move
print
move
print
move
print
move
....
but you failed to include enough synchronization and they are instead happening in this order:
print
print
move
move
print
print
move
move
....
It's not doing anything extra: it's just doing things not in the order you were hoping for.
Problem was, that tkinter is not thread safe hence it doesn't act deterministic.
I solved the problem by using Queue. My main thread, in which tkinter runs, periodically checks wheter or not it has something to draw.

I'm Programming a Roguelike in Python and I need a Specific Monster Following Script

I'm using libtcod and python to make a roguelike; the tutorial I'm following the monsters only follow you if you're in their field of view. Obviously this is insufficient; as it means you can turn a corner and they don't follow you around the corner.
I tried something like this;
class BasicMonster:
def take_turn(self, seen):
self.seen = False
monster = self.owner
if lib.map_is_in_fov(fov_map, monster.x, monster.y):
self.seen == True
if self.seen == True:
self.move_towards(player.x, player.y)
To no avail. It raises
TypeError: take_turn() takes exactly 2 arguments (1 given)
Not sure how to implement this.
I'm calling I'm calling take_turn under
if game_state == 'playing' and player_action != 'didnt-take-turn':
for object in objects:
if object.ai:
object.ai.take_turn()
A simple solution is to keep track of the position of the player the last time the monster saw the player.
When the player moves out of view, simply move towards that last position.
class BasicMonster:
def __init__(self):
self.last_player_pos = None
def take_turn(self):
monster = self.owner
if libtcod.map_is_in_fov(fov_map, monster.x, monster.y):
# store position we last saw the player
self.last_player_pos = player.x, player.y
#move towards player if far away
# ... rest of code here ...
else:
if self.last_player_pos:
monster.move_towards(*self.last_player_pos)
This is of course very simple (and exploitable), but you'll get the idea. Further steps could be creating some sort of time-out and/or tracking the player by sound/scent or anything not related to FOV.
Scent-tracking is a very effective way to control monster movement; I've used a variation in my C++ roguelike project that sets a 'scent trail', which makes it possible to 'confuse' a monster by backtracking or walking over your own scent multiple times.
I only have experience with C++, but if you search for 'libtcod C++ tutorial', it should bring the page with the scent routine up in the first few results. It should be easy enough to get the general idea.
Good luck!

Categories

Resources