Hi Pedro,
welcome!
You seem to be on the right track. One thing is not clear to me: do you need to keep the whole tree in memory? If so, you could do something like the following, where computeMoves generates the tree and evaluatePosition evaluates it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
type Piece = | BLACK | WHITE | EMPTY type Position = Map<int*int, Piece> type TreeNode = Leaf of Position | Branch of Position * TreeNode list let minimax = [| min; max |] let initBoard () = (* unit -> Position *) ... let isWin (position : Position) = (* Position -> bool *) ... let isLoss (position : Position) = (* Position -> bool *) ... let isDraw (position : Position) = (* Position -> bool *) ... let rec computeMoves (position : Position) = (* Position -> TreeNode *) if isWin position || isLoss position || isDraw position then Leaf(position) else do_Some_Magic_and_Call_Recursively let evaluateLeaf (position : Position) = (* Position -> int *) if isWin positions then 1 elif isLoss positions then -1 else 0 let evaluatePosition (startPosition : Position) (player : int) (* 0, 1 *) = let root = computeMoves startPosition let rec loop minORmax node = match node with | Leaf(position) -> evaluateLeaf position | Branch(position, children) -> children |> List.map (loop (1 - minORmax)) |> List.reduce (minimax.[minORmax]) loop root player
Note that:
1) I used map instead of dictionary for the board representation (that's an immutable implementation of dictionary).
2) The evaluation is NOT tail recursive (BAD).
3) I use a 0,1 index to pick the function to be used to reduce the list of children of the current node and then i switch it passing (1-currentIndex) to the next level.
4) You could have an implementation where you generate nodes as you evaluate them and keep memory requirements low.
Also, since it's you first post, you might want to check this out.
Good luck!
Thanks for the answers mau! They helped a lot.
I putted all my "stable code" until now here: [link:www.inf.ufrgs.br] I dont know which is better, post it here or leave it there...you tell me!
As you can see, I did it a little different from what you told me. I made a computeMoves function to generate the Position lists and then use it inside a computeTree (good tree data structure ;) function. I liked the result.
I'm trying to do it the most modularized as I can, so after I got a Tree of Position, I'm thinking about passing this tree to a "evaluateTree" function, that will work together some other "prune x" function. Just when I get to the leafs I must use the evaluateLeaf function. This way, I hope, I can change the static evaluation function easily.
I'm posting again to ask you (or somebody else...) to explain your evaluatePosition function and how does minimax work with it.
What a immutable implementation does mean? It’s something like define all my keys when I'm constructing the object? I must have a mutable data structure because I need to move and “eat" the pieces all the time...
Thanks again,
Pedro Dusso
I'm posting again to ask you (or somebody else...) to explain your evaluatePosition function and how does minimax work with it.
My evaluatePosition (which actually evaluates the tree) is a simple recursion that,
- when a leaf is found, evaluates the position as a win or loss
- for intermediate nodes, calls (maps) itself on all the children (
1
children |> List.map (loop (1 - minORmax))
) and then applies min or max on the resulting list of scores, depending on depth in the tree (
1
|> List.reduce (minimax.[minORmax])
).
Minimax is the array of (min, max) functions and minORmax is the index that is switched between 0 and 1 between recursive calls.
What a immutable implementation does mean? It’s something like define all my keys when I'm constructing the object? I must have a mutable data structure because I need to move and “eat" the pieces all the time...
Thanks again,
Pedro Dusso
An immutable data structure like map does not indeed let you change the contents. However, it defines add/remove/etc operations that return a new object with the new contents. In the case of map, add and remove operations create a new map thta shares most of the nodes with the old one, thus not duplicating memory requirements every time a new object is created.
Hello again!
I think I’m having a good progress, but I still having some difficulties =/.
I project my minimax working something like this:
1 2
let nextPosition = evaluateTree computeTree startPosition
I imagine this working something like computeTree creating a tree of TreeOfPosition (the one you defined ), using the computeMove for that. The tree generated is like this:
val a : TreeNode =
Branch
(dict [(1, EMPTY)],
[Branch
(dict [(2, BLACK)],
[Branch (dict [(4, BLACK)],[]); Branch (dict [(5, WHITE)],[])]);
Branch (dict [(3, WHITE)],[])])
Then, the evaluateTree takes this tree and navigate through it evaluating the Leaf nodes and sending the better ones up.
For this, based in your (very good) tips I built this functions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// Func: computeTree : Position -> TreeOfPosition // Desc: Takes a game-position as its argument and returns a tree of all positions that can be reached from it in one move. // Args: (position : Position) a position (board configuration) to generate the next moves from. let rec computeTree (position : Position) = if isWin position || isLoss position then LeafP(position) else let nextMoves = computeMoves position BranchP(position, List.map computeTree nextMoves)
And
1 2 3 4 5 6 7 8 9 10 11 12
let evaluateTree ( tree : TreeOfPosition) (player : int) = let rec loop minOrmax node = match node with | LeafP(position) -> evaluateLeaf position | BranchP(position, children) -> children |> List.map (loop (1 - minOrmax)) |> List.reduce (minimax.[minOrmax]) loop player tree
In the List.reduce I’m getting this error:
Minimax.fs(147,106): error FS0001: This expression was expected to have type
int -> int -> int
but here has type
int
I don’t know this is the right way…
Thanks very much
Pedro Dusso
I don't know if that's the problem, but you might need to add a type annotation on the minimax definition, like so:
1
let minimax = [| (min : int->int->int); max |]
Yes, it "compiled"!
I'm trying to understand you function (because I'm still having troubles with the pipe operator...)
The match is works like a powerful C# switch right? It will marry my current node with Leaf or Branch.
If it is Leaf, I will evaluate its position (which returna a integer).
If it is a Branch, it will come back the recursion selecting the min or the max (depending the node high right?) of two nodes and I dont understang anymore :P
Could you right in the "normal" way like f(g(x))...
PS.: i tihnk I'm gonna use
1
let minimax = [| List.min; List.max |]
because I must get the min or the max value of a list of node's children...
PD
The match is works like a powerful C# switch right? It will marry my current node with Leaf or Branch. If it is Leaf, I will evaluate its position (which returna a integer). If it is a Branch, it will come back the recursion selecting the min or the max (depending the node high right?)
Correct.
Could you right in the "normal" way like f(g(x))...
Translation:
1 2 3 4 5 6 7
children |> List.map (loop (1 - minOrmax)) |> List.reduce (minimax.[minOrmax]) = List.reduce (minimax.[minOrmax]) (List.map (loop (1 - minOrmax)) children)
PS.: i tihnk I'm gonna use [| List.min; List.max |] because I must get the min or the max value of a list of node's children... PD
Well, if your list is made of numeric values, that will work. So in the last step you could do:
1 2 3 4 5 6 7 8 9 10
let minimax = [| List.min; List.max |] children |> List.map (loop (1 - minOrmax)) |> minimax.[minOrmax] = minimax.[minOrmax] (List.map (loop (1 - minOrmax)) children)
Thanks very much! Its clearly now to me... and worked.
1 2 3 4 5 6 7 8 9 10 11 12
let evaluateTree ( tree : TreeOfPosition, player : int) = let rec loop minOrmax node = match node with | LeafP(position) -> evaluateLeaf position | BranchP(position, children) -> List.reduce (minimax.[minOrmax]) (List.map (loop (1 - minOrmax)) children) loop player tree
For example, when I build a tree like:
BranchP
(dict [(1, BLACK); (8, WHITE)],
[BranchP
(dict [(2, BLACK)],[LeafP dict [(4, BLACK)]; LeafP dict [(5, WHITE)]]);
LeafP dict [(3, WHITE)]])
which looks like this (with the (virtual) static evaluation in the parantheses)
p1
...a
.......c(-10)/d(0) //takes the min here
...b(0)
p1
...a(0) // takes the max here (i believe i will choose the left branch if they are equal, no bigger reasons)
...b(0)
Them the evaluateTree function returns (int) 0. Wonderful!
However, I need the Position of the value, which in my data struct I think I'm nothing handling.
1 2
type TreeOfPosition = LeafP of Position | BranchP of Position * TreeOfPosition list
As you sad, if mylist is made of numeric values, that will work - but its not... I'm thinking something like this:
1 2
type TreeOfPosition = LeafP of Position * int | BranchP of Position * TreeOfPosition list
Adding a int value to the Leaf tuple I believe I can sort it by this int, which will be the result of the static evaluation.
I look after the List.sort and it requieres a Operators.compare (for non default comparison I believe). So I tested:
1 2 3 4 5 6
let l1 = LeafP(p,2) let l2 = LeafP(p,3) Operators.compare l1 l2
And, as I expected, get a error.
"The type 'TreeOfPosition' does not support the 'comparison' constraint because it is a record, union or struct with one or more structural element types which do not support the 'comparison' constraint. Either avoid the use of comparison with this type, or add the 'StructuralComparison' attribute to the type to determine which field type does not support comparison".
And now I'm looking for a way to get this done. I believe this way I can built a let minimax = [| MyOwnMin; MyOwnMax |] which will select the min or the max of the TreeOfPosition list. I believe this is something like implementing a IComparable compareTO in C#?
Thanks one more time,
Pedro
PS.: I dont know why im losing identation....
I working in something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
[<CustomEquality;CustomComparison>] type TreeOfPosition = { LeafP : Position * staticValue; BranchP : Position * TreeOfPosition list} override x.Equals(yobj) = match yobj with | :? TreeOfPosition as y -> (snd x.LeafP = snd y.LeafP) | _ -> false override x.GetHashCode() = hash (snd x.LeafP) interface System.IComparable with member x.CompareTo yobj = match yobj with | :? TreeOfPosition as y -> compare (snd x.LeafP) (snd y.LeafP) | _ -> invalidArg "yobj" "cannot compare value of different types"
Hopefully this will work...
I manage the TreeOfPosition to work with List.min and List.max.
More than override the x.Equals and x.GetHashCode, I needed a particularly mycompare function to work in the tuple, because of its singularly structure.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
[< CustomEquality ; CustomComparison >] type TreeOfPosition = | LeafP of Position * int | BranchP of Position * TreeOfPosition list static member mycompare (x, y) = match x, y with // Compare values stored as part of your type | LeafP(_, n1), LeafP(_, n2) -> compare n1 n2 | _ -> 0 // or 1 depending on which is list... override x.Equals(yobj) = match yobj with | :? TreeOfPosition as y -> (x = y) | _ -> false override x.GetHashCode() = hash (x) interface System.IComparable with member x.CompareTo yobj = match yobj with | :? TreeOfPosition as y -> TreeOfPosition.mycompare(x, y) | _ -> invalidArg "yobj" "cannot compare value of different types"
Lets "Keep walking" ;)
Pedro Dusso
Hello again...
No that my List.min is working, the evaluateTree starts to work too. However it is returning a wrong answer. But dont get me wrong! The corret one is there, I just cant get it...
1 2 3 4 5 6 7 8 9 10 11 12
let evaluateTree ( tree : TreeOfPosition, player : int) = let rec loop minOrmax node = match node with | LeafP(position, 0) -> LeafP(position, evaluateLeaf(position)) | BranchP(position, children) -> minimax.[minOrmax](List.map (loop (1 - minOrmax)) children) loop player tree
This version in returning the TreeOfPosition node with the best (min or max) value of all tree. I mean, it navegates until the leafs, then evaluate all of then, gets the min (or max) and como back sending up that node.
This is wrong beacuse what I want is not a deep good node but the best in the first level (immediately below the start position) node.
So I change my function to
1 2 3 4 5 6 7 8 9 10 11 12
let evaluateTree ( tree : TreeOfPosition, player : int) = let rec loop minOrmax node = match node with | LeafP(position, 0) -> LeafP(position, evaluateLeaf(position)) | BranchP(position, children) -> LeafP(position, getStaticEvalFromNode(minimax.[minOrmax](List.map (loop (1 - minOrmax)) children))) loop player tree
Which sends up just the static value of the leaf nodes. However, when it finds the best node in the first level, it sends its value to the father node... and return this one :(
Any tips in how to solve this?
Thanks in advance, sorry bothering you so much folks... but I'm learning a lot
Pedro Dusso
Hello guys,
I’m here to say thank you to all of you, especially mau! All the help you gave me made possible to complete this F# Minimax project.
You can access all the .fs files and project in this link ([link:www.inf.ufrgs.br] in English. Remembering, you can see the full project (C# + F#) at CodePlex in [link:eukreukla.codeplex.com.]
Thanks one more time,
Best Regards,
Pedro Dusso
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
My name is Pedro Dusso and I’m from Porto Alegre, south Brasil. This is my first topic here, since I recently bought the Programming F#, from Chris Smith. I wish to learn F# first for have some fundamentation in the Functional world and second because I must chose a functional language to develop a class work.
I should implement a full Minimax algorithm (for the Alquerque board game). I already did it in C# last semester so I’m quite understand Minimax and its evaluation functions, move generators, etc (you can find it in [link:eukreukla.codeplex.com] .) I found something in ML, which looks like easy to “translate”, but much more than the syntax I want to learn the semantics of F#.
I started with a position type, to hold my board. I think a
type Piece = | BLACK | WHITE | EMPTY (this is for save space)
type position = Dictionary<int,Piece>
because I represent my board with a 25 vector in which index can be a black or white piece or could be empty. Then I defined a moves function which is moves: position -> position list. From a board configuration it results a list of possible boards configuration.
Then I arrive at my problem. I must define some kind of game tree. The nodes of this game tree are labeled by positions, such that the children of a node are labeled with the position that can be reached in one move from that node.
The game tree must be built by repeated applications of moves. Starting from the root position, moves is used to generate the labels for the sub-trees of the root. Move is then used again to generate the sub-trees of the sub-trees and so on. This pattern of recursion can be expressed as a higher-order function (reptree f a = node a (map (reptree f) (f a)) (1).
So, I don’t know what to do. I thought in some steps to do this:
1) Receive a N node
2) N.possibleMoves = moves ( N)
3) If N.possibleMoves.IsEmpty == true, end
4) Else List.map moves n.possibleMoves…
All code I could write (wrong) is here:
type treeNode = position * position list
let rec reptree (f, p : treeNode ) =
if ((snd (p)).IsEmpty) then (reptree(f (f p)))
else List.map (moves (snd (p)))
In the end, I just wanna a list of treeNodes (I think) to keep calculation the static value of each position and other Minimax stuff (yes, this is the beggning… I will bother you a lot)
Thanks in advance,
Pedro Dusso