简体   繁体   English

如何在Prolog的递归函数中使用动态列表

[英]How to use dynamic lists in a recursive function in Prolog

I have a dynamic list storing a field coordinate and owner of that field 我有一个动态列表,用于存储字段坐标和该字段的所有者

:-dynamic
    board/2.

One entry of this list looks like that: 该列表的一项如下所示:

board(e4,[w]).

There are 22 more board positions all looking similar. 还有22个董事会职位看起来都很相似。

I am trying to implement an AI for the game the board is for. 我正在尝试为董事会开发的游戏实现AI。 I am using the alpha beta algorithm and therefore have to create new 'boards' to evalate the situation. 我使用的是alpha beta算法,因此必须创建新的“木板”来规避这种情况。

I have a copy of the original board to work with but now have a function adjusting the board for the current move like this: 我有一个原始板的副本可以使用,但是现在有一个功能可以针对当前移动调整板,如下所示:

move(position,boardOld,boardNew)

This is called recursive therefore in second call boardOld equals boardNew and boardNew is the oldBoard with the next move in the analysis. 这称为递归,因此在第二次调用中,boardOld等于boardNew,而boardNew则是分析下一步的旧Board。

My idea was to copy the old Board in every iteration, but i have no idea how to do this as this 我的想法是在每次迭代中都复制旧的Board,但是我不知道该怎么做

copy_predicate_clauses(boardOld(A,B),boardNew(A,B)).

would add the old Board to the newBoard because the list already exists. 因为列表已经存在,所以会将旧的Board添加到newBoard中。

I am using the following algorithm (can't copy it, as it is an image): 我正在使用以下算法(无法复制它,因为它是图像):

http://www.cuceinetwork.net/archivos/prolog/The_Art_of_Prolog.pdf http://www.cuceinetwork.net/archivos/prolog/The_Art_of_Prolog.pdf

PDF page 445 (Book page 407). PDF第445页(本书第407页)。

The algorithm gets Position as 'Board' while initializing, i don't know how to do this with my list and furthermore the clause move(Move,Position,Position1) return the new Board with the current move. 该算法在初始化时将Position设为“ Board”,我不知道如何使用列表进行此操作,此外,子句move(Move,Position,Position1)会以当前移动返回新的Board。 This is called recursive and i have no idea how to create the board for position1 without overwriting the ones from before. 这称为递归,我不知道如何在不覆盖以前的位置的情况下为position1创建板。

Edit// 编辑//

ok, i get the problem. 好,我明白了。 But i already used this predicate a lot in my game and don't want to change it all. 但是我已经在游戏中使用了很多谓词,并且不想更改所有谓词。 I did this: 我这样做:

findall((X,Y),board(X,Y),CurrentBoard).

CurrentBoard gives me a list like this CurrentBoard给我这样的清单

[(e4,[w,w]),(g4,[s,w]),(b7,[r,w,s])]

Now i can't use my methods to determine the possible moves. 现在,我无法使用我的方法来确定可能的移动。

I have facts like 我有类似的事实

move(e4,d5).
move(d5,e6).

stating which move(from,to) is possible and now i tried this 指出可能的移动(从,到),现在我尝试了

findall((X,Y),listMoves(CurrentBoard,X,Y),possibleMoves).

with something like this. 像这样 I am struggeling at this point. 在这一点上,我正在努力。 How do i generate a list with possible moves. 我如何生成可能动作的列表。 I somehow have to get the X coordinate from currentBoard, check if the Head of the list from that coordinate (pawns on that coordinate) belongs to me and check if the Y coordinate (to) is free. 我必须以某种方式从currentBoard获取X坐标,检查该坐标列表中的Head(该坐标上的棋子)是否属于我,并检查Y坐标(至)是否空闲。

listMoves([Coordinate|[Head|Tail]], X, Y) :-
     move(X,Y),
     ownField(X,Coordinate,Head),

If you read from (printed) page 401, the authors outline the basic gameplay algorithm as: 如果您从(印刷的)第401页阅读,作者将基本的游戏算法概述为:

  play(Game) :- initialize(Game, Position, Player), display_game(Position, Player), play(Position, Player, Result). 

The rest of the section uses the term "position" in a way that makes me believe they are referring to the entire state of the game. 本节的其余部分使用术语“位置”,使我相信他们指的是游戏的整个状态。 For a game like chess, this would be the state of the board itself: what pieces are where. 对于象棋这样的游戏,这将是棋盘本身的状态:什么棋子在哪里。

From there, the authors go on to discuss move/2 and move/3 , which are defined thusly: 从那里开始,作者继续讨论move/2move/3 ,它们由此定义:

It is convenient to separate the choice of the move by choose_move/3 from its execution by move/3 是很方便的到移动的选择分离choose_move/3从它的执行由move/3

And then later on page 403, 然后在第403页,

The predicate move(Position, Move) is true if Move is a possible move from the current position. 如果Move是从当前位置开始的可能移动,则谓词move(Position, Move)为true。

Taken together, this all suggests to me that they expect a Position to be the complete chess board (I think you're playing chess, are you?) and Move to be a legitimate move, for the purposes of defining move/2 , and then move/3 is just move/2 , returning the resultant board. 综上所述,所有这些都向我表明,他们希望Position可以构成完整的棋盘(我认为您正在下棋,对吗?),而Move是合法的举动,以定义move/2 ,并且然后move/3只是move/2 ,返回结果板。 In other words, the initial chessboard might look something like this: 换句话说,最初的棋盘可能看起来像这样:

starting_board([[b-r, b-b, b-n, b-q, b-k, b-n, b-b, b-r],
                [b-p, b-p, b-p, b-p, b-p, b-p, b-p, b-p],
                [nil, nil, nil, nil, nil, nil, nil, nil],
                [nil, nil, nil, nil, nil, nil, nil, nil],
                [nil, nil, nil, nil, nil, nil, nil, nil],
                [nil, nil, nil, nil, nil, nil, nil, nil],
                [w-p, w-p, w-p, w-p, w-p, w-p, w-p, w-p],
                [w-r, w-b, w-n, w-q, w-k, w-n, w-b, w-r]]).    

This is how I might set it up; 这就是我可能要设置的方式; doubtless there are probably more efficient or wiser ways of doing it, but the point is, your Position values should always encompass the whole state of the board like this. 毫无疑问,可能有更有效或更明智的方法,但是重点是,您的“ Position值应始终包含这样的董事会整体状态。 In fact, it may need to include other information, like whose turn it is, or if you wanted to keep a log of each move, you could throw that in there as well. 实际上,它可能需要包括其他信息,例如轮到谁,或者如果您想保存每个动作的日志,也可以在其中添加这些信息。

From here, you're prepared to write move/2 and move/3 . 从这里开始,您准备编写move/2move/3 I would be inclined (for didactic purposes) to just write move/3 and use that to build move/2 but for efficiency you probably want to do them separately. 我倾向于(出于教学目的)只编写move/3并使用它来构建move/2但是为了提高效率,您可能想单独进行操作。 I'm bad enough at chess that I'm going to stop here (that and I am not convinced you're doing chess anyway). 我对国际象棋非常糟糕,因此我将在这里停下来(那也是我不相信您还是在做国际象棋)。 But basically, what you want is to see that move(StartPosition, Move, NewPosition) , given a start position, will unify Move with some sort of short description of the move and NewPosition with the whole board state after having made that move, so you get a before-and-after snapshot. 但是基本上,您想要看到的是给定了开始位置的move(StartPosition, Move, NewPosition)此移动NewPosition与移动的某种简短描述统一为Move ,并将NewPosition与整个板状态统一起来,因此您将获得前后快照。

Once you have these parts built I think you can mostly use the book code as-is. 构建完这些部分后,我想您基本上可以直接使用本书的代码。

I think you basically had a few misunderstandings: 我认为您基本上有一些误解:

  1. The board is not a predicate with multiple solutions. 董事会不是具有多种解决方案的谓词。 It's a data structure you create that represents the whole story of what's going on. 您创建的数据结构代表了所发生事情的全部故事。
  2. Dynamic predicates do not form a list. 动态谓词不构成列表。 It's true that you can have multiple solutions and that they have an order, it is not a convenient data structure for the kinds of manipulations you're going to need to do. 的确,您可以有多个解决方案,并且它们都有顺序,这对于您需要进行的各种操作来说不是一个方便的数据结构。
  3. I really don't think you want to mix those two ideas together and see what falls out. 我真的不认为您想将这两个想法混合在一起,看看会发生什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM