terrain gen python constraints - python

in my free time I'm making a text-based/ascii(for now) rogue-like game as a study(relevant because context for question)
At the moment, I'm trying to generate the terrain/the rooms that will be used in the world.
The world should be 'endless'.
Generating random terrain isn't the big issue.
I'm struggling with finding a way to maintainably add constraints like:
'plains can not be next to mountain'
I could build a big decisiontree, however, this would mean an if currentTile == plain: if not next to mountain and an if currentTile == mountain: if not text to plains.
this not maintainable, since every rule has to be implemented on 2 places.
I'm wondering what standard solutions for this type of issues exist?
Greetings

I'm not entirely sure I follow your example excerpt but you could have a list of 2 element sets, each containing disallowed combinations. Then you could look up
disallowed = [set(plain, mountains)]
if set(currentTile, newTile) not in disallowed:
#rest of code

Related

Python ete3 - Is there a way to stretch branches of phylogenetic trees?

I am trying to read a phylogenetic tree and stretch its branches to be bigger or smaller than the original, but I didn't find how.
The stretch needs to be on the tree itself - not on its visualization.
For example, the following code reads a tree and presents it:
from ete3 import Tree
t = Tree("(2azaa:0.1871453443,1dz0a:0.1944528747, (((1joi:0.1917345578,1nwpa:0.206793251):0.2050584423,"
"(1jzga:0.3027313573,1rkra:0.2710518895):0.08148637118):0.06756061176,(1cuoa:0.2959705289,"
"((1qhqa:0.585997308,1gy1a:2.509606787):0.1590837051,(1kdj:0.9427371887,"
"((1iuz:0.1918780006,7pcy:0.2035503755):0.1750205426,((2plt:0.2727097306,(2b3ia:0.6259053315,"
"(((1bawa:0.3036227494,1nin:0.5134587308):0.1375675558,((2raca:0.4617882857,1id2a:0.3274320042):0.7764884063,"
"(1pmy:0.7017063073,(1bqk:0.2214168026,(1adwa:0.4171298259,1paz:0.4214910379):0.08599165577):0.2074622534):0.9354371144):0.4486761297)"
":0.1105387947,(1m9wa:0.4551681561,1bxva:0.3931722476):0.06879588421):0.1131812572):0.4242876607):0.1447393581,"
"(1plb:0.2176281022,(1byoa:0.2314554253,(9pcy:0.2456728049,(1ag6:0.1776514893,1plc:0.318467746):0.02728470893)"
":0.07383541027):0.1260361833):0.2659408726):0.05013755844):0.2637791318):1.001560925):1.018869112):0.4609302267):0.1807238866);")
t.show()
The following link discusses how to use the library, but I didn't find what I was looking for:
http://etetoolkit.org/docs/latest/tutorial/tutorial_trees.html
Can anyone help?
Edit: If there are other Python libraries that can do that, I would love to hear which and how it's done.
Edit2: I know that in R there is a library named "ape" then can do it very simply... maybe someone who works with it knows the parallel operation in some python library?
After a long time I found a solution:
As far as I know there are no built in functions to stretch trees in phylogentic python libraries. This is very strange and I hope I am wrong.
However once you understand their data-structures there is in easy way to do it: all you need to do is just to run over all the edges in the trees and multiply them by the desired factor. This is done differently, depending on which library you use.
Here are two examples how to stretch the trees twice their size using dendropy and ete3:
from ete3 import Tree
import dendropy as dp
original_tree = "(2azaa:0.1871453443,1dz0a:0.1944528747,(((1joi:0.1917345578,1nwpa:0.206793251):0.2050584423,"\
"(1jzga:0.3027313573,1rkra:0.2710518895):0.08148637118):0.06756061176,(1cuoa:0.2959705289,"\
"((1qhqa:0.585997308,1gy1a:2.509606787):0.1590837051,(1kdj:0.9427371887,"\
"((1iuz:0.1918780006,7pcy:0.2035503755):0.1750205426,((2plt:0.2727097306,(2b3ia:0.6259053315,"\
"(((1bawa:0.3036227494,1nin:0.5134587308):0.1375675558,((2raca:0.4617882857,1id2a:0.3274320042):0.7764884063,"\
"(1pmy:0.7017063073,(1bqk:0.2214168026,(1adwa:0.4171298259,1paz:0.4214910379):0.08599165577):0.2074622534):0.9354371144):0.4486761297)"\
":0.1105387947,(1m9wa:0.4551681561,1bxva:0.3931722476):0.06879588421):0.1131812572):0.4242876607):0.1447393581,"\
"(1plb:0.2176281022,(1byoa:0.2314554253,(9pcy:0.2456728049,(1ag6:0.1776514893,1plc:0.318467746):0.02728470893)"\
":0.07383541027):0.1260361833):0.2659408726):0.05013755844):0.2637791318):1.001560925):1.018869112):0.4609302267):0.1807238866);"
#dendropy test
print("These are the dendropy results:")
t1 = dp.Tree.get_from_string(original_tree,"newick")
t2 = dp.Tree.get_from_string(original_tree,"newick")
for edge in t2.levelorder_edge_iter():
if(edge.length == None):
continue
edge.length *=2
print(t1)
print(t2)
#ete3 test
print("These are the ete3 results:")
t3 = Tree(original_tree)
t4 = Tree(original_tree)
for node in t4.iter_descendants():
node.dist*=2
print(t3.write())
print(t4.write())
Another lesson we can learn from this case - always do your homework on the data-structure you work with before you search for a built in function...
So far i didn't found a way to do this stretch...
I made a simple code that runs over the string that represents the tree, finds the numbers (which are the brunches lengths) and multiply then by 2.
This is a patch and not a real solution... still hoping someone will have an idea.
for c in original_tree:
if is_number(c) or c=='.':
number+=c
else:
if len(number)<5:
stretched_tree+=number
number=""
elif number!="":
stretched_tree+=str(float(number)*2)
number = ""
stretched_tree+=c

grounding predicates with python scripts in asp/clingo

I am using clingo version 4 and wish to be able to ground relations via python script (please don't ask why, it's not a crime, since you can at least ground 1-ary relations). I am hoping this is possible, and need some help.
#script (python)
import gringo;
def main(prg):
prg.ground([('base', [])]);
# ... compute somethings ...
prg.ground([('myrel', [[10,20],[30,40],[70,40]])]);
prg.solve();
#end.
#program myrel(x,y).
r(x,y).
#show r/2.
this doesn't work. Does anyone know how to do this? I tried [(10,20),(30,40),(70,40)] instead, but that also did not work.
It is possible, but one has to input each entry one by one (which for my application is actually good). Instead of
prg.ground([('myrel', [[10,20],[30,40],[70,40]])]);
one has to write
prg.ground([('myrel', [10,20])]);
prg.ground([('myrel', [30,40])]);
prg.ground([('myrel', [70,40])]);
and then it is accepted and yields the right output.

Goto\Jump in Python

I'm coding a text game in python 3.4 and when I though about making a save game came the question:
How can I jump to the place that the player stopped?
I'm making a simple game, me and my friends, so I just wanna jump to a certain part of the code, and I can't do that without having to make around 15 copies of the code, so can I jump to a line?
You can do that using something like python-goto but this is a very bad idea.
In python, you don't have really any reason to do a goto.
A way better way would be to save the structure containing your data with something like pickle and loading it back when the user want to restart the game.
For instance:
import pickle
game_data = {'something': [1, 2, 3 ]}
pickle.dump(game_data, open('file.bin', 'wb')
Then, you can load the data back:
import pickle
game_data = pickle.load(open('file.bin', 'rb'))
There is no goto built into Python. There are ways to effectively 'halt' in a method by using yield and creating a generator, which is effectively how Python coroutines work (see the asyncio module) however this isn't really appropriate for your needs.
For saving game state, saving and serialising the state you need to resume the gameplay in a more general way is a much better idea. You could use pickle For this serialisation.
You need to consider the game-state as something that you can assign a value (or values) to. If this is a very simple text game, then the player will have a location, and that location will presumably be something you can "jump" to via use of a reference.
Let's say your code follows this pseudo-code pattern:
start
player_location = 0
print_start_game_text()
begin loop:
display_text_for_location[player_location]
display_options_for_location[player_location]
player_location = parse_player_response(response_options_for_location[player_location])
if isGameEndCondition(player_location):
break;
print_end_game_text()
end
This pattern would reference some data files that, for each location provided some collection such as 1, "you are in a room, doors are [E]ast and [W]est. You can [S]ave your game, or [L]oad a previously saved one", { "E" : 3, "W" : 2, "S" : "savegame", "L" : "loadgame" }
Then using a function to display some options, collecting the users response and parsing that data, returning a single value; the next location. You then have a new key to reference the next element in the data-file.
IF your game is as simple as this, then your save file need only contain a single reference, the player's location! Simple.
If you have objects that the player can manipulate, then you'll need to figure out a way to keep track of those, their locations, or state-values - it all depends on what your game does, and how it's played.
You should be thinking along these program vs data lines though, as it will make the game much easier to design, and later, extend, since all you'd have to do to create a new adventure, or level, is provide a new datafile.

Lattice paths algorithm does not finish running for 20 X 20 grid

I wrote the following code in python to solve
problem 15 from Project Euler:
grid_size = 2
def get_paths(node):
global paths
if node[0] >= grid_size and node[1] >= grid_size:
paths += 1
return
else:
if node[0]<grid_size+1 and node[1] < grid_size+1:
get_paths((node[0]+1,node[1]))
get_paths((node[0],node[1]+1))
return paths
def euler():
print get_paths((0,0))
paths = 0
if __name__ == '__main__':
euler()
Although it runs quite well for a 2 X 2 grid, it's been running for hours for a 20 X 20 grid. How can I optimise the code so that it can run on larger grids?
Is it a kind of breadth first search problem? (It seems so to me.)
How can I measure the complexity of my solution in its current form?
You might want to look into the maths behind this problem. It's not necessary to actually iterate through all routes. (In fact, you'll never make the 1 minute mark like that).
I can post a hint but won't do so unless you ask for it, since I wouldn't want to spoil it for you.
Edit:
Yes, the algorithm you're using will never really be optimal since there's no way to reduce the search space of your problem. This means that (as pg1989 stated) you'll have to look into alternative means of solving this problem.
As sverre said looking over here might give a nudge in the right direction:
http://en.wikipedia.org/wiki/Binomial_coefficient
A direct solution may be found here (warning, big spoiler):
http://www.joaoff.com/2008/01/20/a-square-grid-path-problem/
Your algorithm is exponential, but only because you are re-evaluating get_paths with the same input many times. Adding Memoization to it will make it run in time. Also, you'll need to get rid of the global variable, and use return values instead. See also Dynamic Programming for a similar idea.
When solving problems on Project Euler, think about the math behind the problem for a long time before starting to code. This problem can be solved without any code whatsoever.
We're trying to count the number of ways through a grid. If you observe that the number of moves down and right do not change regardless of the path, then you only need to worry about the order in which you move down and right. So in the 2x2 case, the following combinations work:
DDRR
DRDR
RDRD
RRDD
RDDR
DRRD
Notice that if we pick where we put the R moves, the placement of the D moves is determined. So really we only have to choose, from the 4 movement slots available, which get the R moves. Can you think of a mathematical operation that does this?
Probably not the way the project Euler guys wanted this problem to be solved but the answer is just the central binomial coefficient of a 20x20 grid.
Using the formula provided at the wiki article you get:
from math import factorial, pow
grid = 20
print int(factorial(2 * grid) / pow(factorial(grid), 2))
The key is not to make your algorithm run faster, as it will (potentially) run in exponential time, no matter how fast each step is.
It is probably better to find another way of computing the answer. Using your (expensive, but correct) solution as a comparison for small values is probably a sanity-preserver during the algorithm optimization effort.
This question provides some good insight into optimization. The code is in c# but the algorithms are applicable. Watch out for spoilers, though.
Project Euler #15
It can be solved by simple observation of the pattern for small grids, and determining a straightforward formula for larger grids. There are over 100 billion paths for a 20x20 grid and any iterative solution will take too long to compute.
Here's my solution:
memo = {(0, 1) : 1, (1, 0) : 1}
def get_pathways(x, y):
if (x, y) in memo : return memo[(x, y)]
pathways = 0
if 0 in (x, y):
pathways = 1
else:
pathways = get_pathways(x-1, y) + get_pathways(x, y-1)
memo[(x, y)] = pathways
return pathways
enjoy :)

python: Chess moves validation

Does anybody know if there is a free python chess moves validation function available somewhere?
What I need. I have a diagram stored as a string, and move candidate. What I need is to see if move candidate is valid for the diagram.
Would be really interested to see examples, if possible.
The string looks this way:
ememememememememememememememememememembbememwpemememememememwpemembkememememememememememememememememwbembrememememwkemememememem
I understand it may seem stupid, but I find it the easiest to encode position this way. Move candidate for me is just another such position (which happened after next move, can change this behavior I think)
You are missing information e.g. whose turn to move, whether each king has ever moved (means castling is not allowed), the "en passant" status of each pawn. That aside, it would be a very instructive exercise for you to write your own, using a not-very-complicated board representation like the 10x12-element array described here (except that you'd linearise it to a 120-element array).
I know this is a rather old question, but my brother and me were looking for the same thing and we came across this awesome little python module called Chessnut.
Here is an example of its use:
#!/usr/bin/python
from Chessnut import Game
chessgame = Game(fen="rnbq1rk1/ppppp1bp/5np1/5p2/2PP4/2NBPN2/PP3PPP/R1BQK2R b KQ - 4 6")
print chessgame
print chessgame.get_moves()
# apply a move
chessgame.apply_move(chessgame.get_moves()[1])
print chessgame
and here the generated output:
rnbq1rk1/ppppp1bp/5np1/5p2/2PP4/2NBPN2/PP3PPP/R1BQK2R b KQ - 4 6
['b8a6', 'b8c6', 'd8e8', 'f8e8', 'f8f7', 'g8h8', 'g8f7', 'a7a6', 'a7a5', 'b7b6', 'b7b5', 'c7c6', 'c7c5', 'd7d6', 'd7d5', 'e7e6', 'e7e5', 'g7h8', 'g7h6', 'h7h6', 'h7h5', 'f6e8', 'f6d5', 'f6e4', 'f6g4', 'f6h5', 'g6g5', 'f5f4']
r1bq1rk1/ppppp1bp/2n2np1/5p2/2PP4/2NBPN2/PP3PPP/R1BQK2R w KQ - 5 7
Awesome! :)
Thanks cgearhart!
Just use the source of one of the Python Chess programs like PyChess or Python Chess
Specifically, the valid moves for pychess: https://code.google.com/p/pychess/source/browse/lib/pychess/Utils/lutils/validator.py
Wouldn't hurt to look at some of the related answers on the side: Chess move validation library and https://stackoverflow.com/questions/1239913/smallest-chess-playing-program stand out to me.
Though personally I'm in favor of building your own.
Check out ChessBoard.
Unfortunately it has some drawbacks:
it seems to be abandoned, because the bugs reported more than one year ago in the comments don't seem to be fixed
the code is not really PEP-8 compliant
some methods are very ugly and big, not all methods have docstrings
there are no unit tests, so digging into that code might be a challenge (I've already tried it at least twice and failed)
The good thing is that the code is GPL so you can play with it as long as you stick to that license.
I've made a simple chess implementation with move validation here: https://github.com/akulakov/pychess
Validation logic is in each piece's "moves()" method, and you can validate your own move by generating full list of moves and checking if your move is there.

Categories

Resources