|
||||
Title: Board Representation Post by doublep on Oct 16th, 2005, 4:09pm Discussion here seems to concentrate on important things, like search algorithms and evaluation. Why not talk about something more to the ground? I wonder which board representation is more popular among Arimaa bot authors. I'm aware of three standard schemes: a collection of bitmaps, a two-dimensional array or a single-dimension array (or there could be not one but a few arrays.) Which one do you use and why? Maybe you use something completely different? Do you prefer several arrays of primitive types or an array of objects? Aami-ra uses two single-dimension arrays. The main array stores actual board situation: each element (of type `char') contains a code for a piece, an empty square or an off-board code. Second array (also `char') contains auxiliary data that allows to quickly determine if a piece is frozen and how many neighbors of different kinds it has. We prefer single-dimension arrays since they are more efficient (you only pass one index around) and actually easier to work with, once you get used to. Arrays of objects are usually less efficient too, because CPU memory caching suffers. Anyway, in our case the object would have been just two `char's if we had used them. Both arrays are updated incrementally. Move/step undoing is performed using a change stack: whenever a value in either of the two arrays changes, Aami-ra stores the old value together with its address. Undoing then simply consists of copying the old values back. |
||||
Title: Re: Board Representation Post by nbarriga on Oct 16th, 2005, 4:44pm I never gave it too much thought. I just assumed everybody used 64-bit bitmaps. It's memory efficient and you just use fast bitwise operations. I thought using arrays would be much slower, but your solution of using a second array keeping auxiliar data seems like a clever solution. |
||||
Title: Re: Board Representation Post by jdb on Oct 16th, 2005, 6:14pm Clueless uses 64 bit bitmaps. The board is stored as an array of 12 bit maps plus an int for the number of steps used in the game so far. Last year's move representation was a 4 step move compressed into a 64 bit long. This year a move is stored in the same format as the board. The makemove routine xor's the current position with the move to get the new position. Nothing is done incrementally. |
||||
Title: Re: Board Representation Post by Fritzlein on Oct 16th, 2005, 9:42pm I suppose I should let Fotland speak for himself, but he seems not to be active at the moment. I seem to recall him telling me that Bomb uses bitmaps for speed. |
||||
Title: Re: Board Representation Post by 99of9 on Oct 17th, 2005, 12:22am Gnobby uses the bitmap representation used by Don in the sample bot (because I don't know enough to better it). |
||||
Title: Re: Board Representation Post by doublep on Oct 17th, 2005, 3:42pm We use arrays since they seem to easier to work with in tactical reading (we have unfinished 4 steps goal lookahead and directed search for trapping moves intended to improve move ordering.) Basically, each board square is described with just two values, which you don't even need to extract from a bitmask. This approach may be more efficient in some cases, for instance the check if a piece is frozen is a single comparison. Additionally, our GNU Go experience might have played its role :) |
||||
Title: Re: Board Representation Post by PMertens on Oct 17th, 2005, 4:33pm my first bot used VB (no comment, it was a first try ever) arrays, but after I read the sample bot I learned C and used bitmaps ... suddenly everything became faster (and move generation as well as evaluation much easier) |
||||
Title: Re: Board Representation Post by doublep on Oct 18th, 2005, 2:40pm on 10/17/05 at 16:33:20, PMertens wrote:
Well, in this case the speedup is of course because of changing the language. No matter how you do it in C, it will be faster than VB. Actually, C and C++ are you best languages if you want something to be _real_ fast. |
||||
Title: Re: Board Representation Post by ntroncos on Nov 13th, 2005, 2:16pm It seems that 64 bitmap is the common usage. By the way this is quite good and they will benifit from 64bit procesor. With 32bit Procesors we need 2 (normaly) instructions to handle the bitmap, with the new 64bit this is reduced to 1 (normaly), hence we see a speed enhancement. Normaly what you should try is to avoid is a representation where you store to much zeros, bitmap in this case. But the tradeof of this representation is that we have a vision of the board as a whole, be sides the space overhead for each zero is only 1bit. Never the less other other representation should be explored, maybe there is a whole new, more eficient representation waiting to be implemented ;). |
||||
Title: Re: Board Representation Post by Swynndla on May 17th, 2006, 6:59am Can someone help me understand bitboards? ... and how the Sample C bot implements it? |
||||
Title: Re: Board Representation Post by jdb on May 17th, 2006, 8:26am http://en.wikipedia.org/wiki/Bitboard is a decent description. The sample bot also defines some Arimaa specific bitboards, like trap squares and squares adjacent to trap squares etc. |
||||
Title: Re: Board Representation Post by unic on May 17th, 2006, 9:29am Fairy represents the board as an array[100]. I find it easier to understand and to write evaluation for than a bitboard - might be slower in execution, but quicker in development for me. |
||||
Title: Re: Board Representation Post by nbarriga on May 17th, 2006, 10:12pm on 05/17/06 at 09:29:42, unic wrote:
You should rethink that, i did some tests a while ago, and it really is a LOT slower. Maybe you should write a couple of functions to manipulate the bitboard, so you write the bitwise operations only once. |
||||
Title: Re: Board Representation Post by Swynndla on May 18th, 2006, 2:42am Is it clear cut? ... I didn't think it was when reading the wikipedia article and also this: http://www.cis.uab.edu/hyatt/boardrep.html It seemed to me that the two links are saying that bitboards may be better, but not by much (if both methods are done properly)? Although there may be a significant difference with a 64 bit processor? I know next to nothing about both methods, and so I don't know what I'm talking about ... I'm interested in you're opinions. From what I've read so far, bitboards seem more logical to me, but if I use them, it may slow my bot development down quite a bit while I get to grips with bitboards. At the moment, I'm just wondering if I spent that time on developing an effective pruning strategy instead, that I'd have a faster bot in the end. I'm wondering this as both articles warn that bitboards take a long time to get to grips with, and that any bitboard code must be well-commented in order to develop more code and to debug it too ... I'm not sure that the sample C bot is all that well-commented? |
||||
Title: Re: Board Representation Post by 99of9 on May 18th, 2006, 3:08am I learnt bitboards from the sample code. I don't think they're *that* hard to get to grips with. |
||||
Title: Re: Board Representation Post by BlackKnight on May 18th, 2006, 3:37am I think it also helps a lot to write down the following: // The squares on the board (looking from Gold's side) have the indices // (within the bitstring): // 0 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 44 45 46 47 // 48 49 50 51 52 53 54 55 // 56 57 58 59 60 61 62 63 // And the bitstring is numbered 63 62 61 ... 2 1 0. Then you can easily get the following constants: #define A_FILE 0x0101010101010101ULL #define B_FILE 0x0202020202020202ULL #define C_FILE 0x0404040404040404ULL #define D_FILE 0x0808080808080808ULL #define E_FILE 0x1010101010101010ULL #define F_FILE 0x2020202020202020ULL #define G_FILE 0x4040404040404040ULL #define H_FILE 0x8080808080808080ULL #define RANK_1 0xff00000000000000ULL #define RANK_2 0x00ff000000000000ULL #define RANK_3 0x0000ff0000000000ULL #define RANK_4 0x000000ff00000000ULL #define RANK_5 0x00000000ff000000ULL #define RANK_6 0x0000000000ff0000ULL #define RANK_7 0x000000000000ff00ULL #define RANK_8 0x00000000000000ffULL #define LEFT_SIDE 0x0f0f0f0f0f0f0f0fULL // a, b, c, d #define RIGHT_SIDE 0xf0f0f0f0f0f0f0f0ULL // e, f, g, h #define TRAPS 0x0000240000240000ULL #define TRAPGUARDS 0x00245a24245a2400ULL #define RING0 0x0000001818000000ULL // same as small center #define RING1 0x00003c24243c0000ULL #define RING2 0x007e424242427e00ULL #define RING3 0xff818181818181ffULL // edges |
||||
Title: Re: Board Representation Post by nbarriga on May 19th, 2006, 11:52pm on 05/18/06 at 02:42:31, Swynndla wrote:
Well, with ntroncos we may contribute a bit on that. We are giving his students an assignment, consisting on understanding the sample C bot, and commenting using doxygen style. I think in about a month we may publish here the best commented program of the class. |
||||
Title: Re: Board Representation Post by Swynndla on May 20th, 2006, 6:49am I'm getting a lot of help ... thanks to all your posts! on 05/19/06 at 23:52:43, nbarriga wrote:
Nice! ... I look forward to it :) What course are the students studying? BlackKnight, thanks for those lines ... why is the board numbered from a8 instead of a1? |
||||
Title: Re: Board Representation Post by nbarriga on May 20th, 2006, 11:26am on 05/20/06 at 06:49:21, Swynndla wrote:
It's a second year course called Programming Workshop, where they learn programming good practices, and some tools. first they are introduced to the all the dark corners of C :) , then some tools like gdb, autotools, doxygen. |
||||
Title: Re: Board Representation Post by nbarriga on May 25th, 2006, 9:06pm I just made a simple test to find out if 64 bit CPUs are worth it. I used bot_SampleC compiled using gcc 4.1.0 with -O4, searching 10 steps, on the following position: 5w +-----------------+ 8| r r r r r r r | 7| h d c m h | 6| X c d | 5| e E r | 4| | 3| X X | 2| H D C M R C D H | 1| R R R R R R R | +-----------------+ a b c d e f g h (sorry for the ugly board, i just copy and paste the matchMove file) One PC, an athlonXP 2600+ clocked at 1900Mhz with 512kb L2 cache, i compiled with -march=athlon-xp. The other, a Sempron64 2800+ clocked at 1600Mhz with 256kb L2 cache, compiled with -march=athlon64 Results from 3 consecutive runs: XP: real 0m13.628s user 0m13.461s sys 0m0.152s real 0m11.492s user 0m11.353s sys 0m0.116s real 0m11.222s user 0m11.025s sys 0m0.184s ------------------------------------ and Sempron64: real 0m7.916s user 0m7.792s sys 0m0.048s real 0m8.431s user 0m8.217s sys 0m0.052s real 0m9.581s user 0m9.425s sys 0m0.056s ------------------------------ If would be nice if someone not using bitboards could send me his bot compiled for the two different architectures to run the same test. |
||||
Title: Re: Board Representation Post by chessandgo on May 25th, 2006, 9:26pm Is there any translation from chinese to english of this post ? :) |
||||
Title: Re: Board Representation Post by jdb on May 25th, 2006, 9:32pm Checking through my notes, here are some results of a perft using clueless's makemove/undo. They are all pure bitboard methods. This is on an AMD64 2.2Ghz The java and c versions are as close to the same code as I could make them. java32 3719 Knps java64 13791 Knps gcc64 23065 Knps |
||||
Title: Re: Board Representation Post by unic on May 25th, 2006, 9:35pm I offered in the chat earlier today to upload a non-bitboard sample bot in C (i.e. a somewhat cleaned-up and simplified version of Fairy). I was hoping to get around to doing that during the weekend... I'll post once I have it done. |
||||
Title: Re: Board Representation Post by nbarriga on May 25th, 2006, 11:15pm on 05/25/06 at 21:26:16, chessandgo wrote:
Yes, the athlon XP averaged about 12 seconds, while the sempron 64 averaged about 8.5 seconds on analizing 10 steps from the move i gave them. |
||||
Title: Re: Board Representation Post by Swynndla on May 27th, 2006, 8:10pm nbarriga, I'm looking forward to your results of testing a version of Fairy on the 32 and 64 bit cpu's :) |
||||
Title: Re: Board Representation Post by nbarriga on May 28th, 2006, 1:05pm Ok, i run Fairy_light, with the same position as the earlier test: XP: real 0m44.878s user 0m43.911s sys 0m0.824s real 0m44.707s user 0m43.791s sys 0m0.748s real 0m45.078s user 0m43.819s sys 0m0.792s Sempron64: real 0m42.045s user 0m40.383s sys 0m0.420s real 0m43.482s user 0m41.447s sys 0m0.524s real 0m42.849s user 0m41.307s sys 0m0.476s |
||||
Title: Re: Board Representation Post by nbarriga on May 28th, 2006, 1:09pm If someone has a bot that uses many threads or processes, i can test it in an athlon 64 dual-core i have access to. |
||||
Title: Re: Board Representation Post by Swynndla on May 28th, 2006, 9:23pm So this is hard proof of the theory that 64 bit cpu's are free speed upgrades for bitboards, while not doing a lot for non-bitboards! ... http://www.cis.uab.edu/hyatt/bitmaps.html ... Quote:
and http://www.cis.uab.edu/hyatt/boardrep.html ... Quote:
|
||||
Title: Re: Board Representation Post by fotland on Aug 14th, 2006, 10:34pm bomb uses bitboads. bmap is a 64-bit bitmap class with many member functions for and, or, set-bit, find-first-bit, etc. Here is the code: // the basic core data of a board, must be copied to new board - change DATASIZE when add to this bmap p[NUMBITMAPS]; // locations of pieces, by PIECE NAMES bmap frozen; // bit set if that piece is frozen char pieces[64]; // piece on each point, 0 is upper left (black side of board ) char strongest[2][64]; // strongest piece next to each square, by color (or EMPTY) unsigned int hashindex, hashkey1; // transposition table values int material; // material balance, 1000 per pawn, positive for gold int bestmateval; // best pawn matestep value char bestmateloc; // best mate location char tm; // side to move (0-white, 1-black) char phase; // phase of the the move, 0-3 char wtotmat, btotmat; // white and black total material, 1, 2, 3, 5, 9, 11 unsigned char pullsquare, pullpiece; // last move's pulling square (empty square where piece was) // and piece doing the pulling - unless pullpiece is empty unsigned char pushsquare, pushpiece; // last move pushed square (empty point where piece was) // and enemy piece that was pushed - // unless pushpiece is empty - next step is forced unsigned char pawncount[2]; // how many pawns left by color |
||||
Title: Re: Board Representation Post by Fritzlein on Aug 15th, 2006, 2:08pm on 08/14/06 at 22:34:50, fotland wrote:
If you ever get motivated to work on Bomb some more, consider changing the material values to 1, 1.5, 2, 3, 5, 10. We've had a lot of experience with uneven trades since the old days, and it turns out camels and horses are not worth as many little pieces as we used to think. (Yes, I realize that many other parameters would have to change as well to correspond, but Bomb's overvaluation of camels and horses is actually an exploitable bug. Indeed, overvaluing the camel may have caused Bomb its one loss in the 2006 CC.) |
||||
Title: Re: Board Representation Post by clauchau on Feb 2nd, 2008, 9:58am I'm going to store and compare lossless representations of positions instead of colliding hash values, so that 1) checking for games lost by repetition is not done wrong, and 2) I'm sure that the simple bots I have playing over a million games don't ever overlook moves by wrongly believing they've already been evaluated. How few bits as possible would you need to code every possible Arimaa position (without needing too much time to code it)? I've a simple solution that goes down to using 153 bits (or 154 if I also need the active side). |
||||
Title: Re: Board Representation Post by Fritzlein on Feb 2nd, 2008, 6:31pm OK, you got me thinking about it for a few minutes, and I couldn't beat your answer. I did a Huffman Code on the pieces, listed in order of the squares. Bit one is empty/occupied. Bit two is Silver/Gold. Bit 3 is rabbit/piece. Bit 4 is minor/major piece. Etc. The full code is 0 empty 100 silver rabbit 10100 silver cat 10101 silver dog 10110 silver horse 101110 silver camel 101111 silver elephant 110 gold rabbit 11100 gold cat 11101 gold dog 11110 gold horse 111110 gold camel 111111 gold elephant My description length when all pieces are on the board is 32*1 + 16*3 + 12*5 + 4*6 = 164 bits, plus one for side to move. Of course it is shorter after captures, but it's eleven bits longer than yours worst case. >:( Now you explain your 153-bit solution. It had better be more complicated than mine! :P |
||||
Title: Re: Board Representation Post by jdb on Feb 2nd, 2008, 6:39pm on 02/02/08 at 09:58:22, clauchau wrote:
If 64 bit zobrist hashing is used, there is a better chance of being killed by a falling coconut while playing arimaa, than having an incorrect hash collision. |
||||
Title: Re: Board Representation Post by lightvector on Feb 3rd, 2008, 10:34am I don't know whether this is considered easy to code, but I have a practical way to achieve 146 bits (147 with side to move, 149 if you want to specify 1-4 steps as well). First, compute a unique index for each possible combination of squares occupied on the board. There are 64C32 + 64C31 + ... +64C0 possible combinations for occupancy (ignoring traps, etc). Adding all this up and taking the log base 2, we find we can store this index in 64 bits. To represent what pieces are on the board, we can write a string such as RcEreMrrRrHDrDRC, specifying sequentially the pieces that are in each subsequent occupied position. Each string will be exactly 32 characters long, and will contain exactly 8 r's, 8 R's, 2 c's, 2 C's, and so on. If there are fewer than 32 occupied positions on the board, then we simply fill in the rest of the string past that point however we wish (this is wasteful, so there is still room to shave off a few more bits without resorting to Arimaa-specific properties like traps or the fact that there can never be more than 4 rabbits that have reached the goal line). We then compute a unique index for each possible 32 character string. The total number of possibilities is 32!/8!/8!/2!/2!/2!/2!/2!/2!, and taking the log base 2, we find we can store this index in 82 bits. This gives a grand total of 146 bits. I hope I didn't get anything wrong above. I will post how to calculate the indices shortly. It's not actually that bad. |
||||
Title: Re: Board Representation Post by lightvector on Feb 3rd, 2008, 11:14am How do we compute the required indices? Here is one way (there may be better ways). This requires 64 bit unsigned integer math. To compute the index for occupied board positions, first count how many there are. We have a list matching number of positions to the desired combination. 32 Positions: 64C32 31 Positions: 64C31 30 Positions: 64C30 ... To get an index, we sum all the values of the previous, then add the specific index for the combination we want. For example there are 30 occupied positions, then we want the case 64C30. So our index is 64C32 + 64C31 + (the unique index for combinations of 30 elements from 64). -------- To find the index for combinations of C squares from N, we number the board squares 0-N. Then we consider the smallest square chosen, x. Removing that square, we recursively have a choice of C-1 squares out of the remaining N-x-1 subsequent squares. Again, to get an index in the case we want, we sum all the values of the previous, then recursively add the unique index for the combination we want. Say in our example x = 3, C=30, N = 64. Then, our list of the possible cases looks like: x = 0: 63C29 x = 1: 62C29 x = 2: 61C29 x = 3: 60C29 ... and our index is 63C29+62C29+61C29 +(the unique index for a choice 29 squares from 60). Recursively proceed until we have gone through each occupied square (recursively reaching a case of the form xC0). This gives us our final unique index. ------- If we want to go from the index back to the position, we simply following the same procedure, but make the choice at each step that would give us the index we want. For example, in the initial counting of board squares, if our index X is such that 64C32+64C31...+64C10 <= X < 64C32+64C31...+64C10+64C9, then we know that there are 9 squares occupied, and to find out which squares, we continue into the case 64C9. All of this can be made relatively fast by precomputing all the required values xCy up to 64C32 and storing them in an array. Calculating the index for the piece string can be done very similarly (but will require up to 82 bit math). Somewhat complicated, and probably a pain to code, but definitely feasible. Of course, the extra effort required to implement something like this is probably not worth the tiny reduction in size, but it is certainly fun to see how it can be done. My explanation is probably overly confusing, but I hope it is good enough. |
||||
Title: Re: Board Representation Post by Janzert on Feb 3rd, 2008, 11:50am Just a note since it was mentioned storing how many steps are left. If you have a mid-move position then you also need to know the type of the last piece to move and the square it moved from. Otherwise you can't correctly deal with pushes and pulls. Janzert |
||||
Title: Re: Board Representation Post by 99of9 on Feb 3rd, 2008, 5:51pm I can get 160 bits quite easily (for the board configuration, not the move status). Lightvector, you've given us a good bound to shoot for! Your first 64 bits are overly complex though... you can fully indicate occupancy by storing a 64 bit checkerboard with 1 for occupied and 0 for unoccupied, just as Fritz suggested for his first bit. No need to calculate anything. |
||||
Title: Re: Board Representation Post by 99of9 on Feb 3rd, 2008, 8:02pm Using a slightly complex, but human-decodeable scheme, I can get 156. I'll also be fascinated to see the 153! |
||||
Title: Re: Board Representation Post by lightvector on Feb 3rd, 2008, 11:33pm on 02/03/08 at 11:50:07, Janzert wrote:
It might depend on your search algorithm though. In my bot, I generate and search pushpulls first as 2-step moves, and never end in an intermediate position. But yes, if you have to store that info, it will increase the size. on 02/03/08 at 17:51:15, 99of9 wrote:
Haha! I suppose I should have check for easier ways first. =). |
||||
Title: Re: Board Representation Post by clauchau on Feb 4th, 2008, 6:19am Lightvector, I'm delighted to see your optimal solution for the piece string. Fascinating. Poor me, I miscalculated my solution (while trying to sleep and the next day making my groceries :-/ ). I need 155 bits indeed, not 153. Forgive me. Here is what I had in mind. The idea is to start with the 164-bits solution and simply drop 9 redundant bits! For each board square, one bit tells whether it is empty or occupied => 64 bits. For each occupied square except the possible 32nd one, one bit tells whether it is occupied by Gold or by Silver => 31 bits. If there are 32 occupied squares, it means 16 are by Gold and 16 are by Silver, so you always know the 32nd color is the one missing from the 31 first squares. For each square occupied by Gold except the possible 16th one, one bit tells whether it is by rabbit or not => 15 bits. If there are 16 squares occupied by Gold, it means 8 are by rabbits and 8 are by non-rabbits, so you always know about the 16th according to how many rabbits are already counted for in the 15 first squares occupied by Gold. For each square occupied by a non-rabbit Gold piece except the possible 8th, two bits tell whether it is 00 = by a cat, 01 = by a dog, 10 = by a horse, or 11 = by a camel or an elephant, not distinguishing camels from elephants => 14 bits. Same reasoning as above in case there are 8 non-rabbit Gold pieces - there should be two 00, two 01, two 10 and two 11, so the 8th one is the one missing. For the first square occupied by a Gold camel or elephant, one bit tells whether it is a camel or an elephant => 1 bit. If there are two such squares, the 2nd is always of the other species. Do the same for Silver, and you need 64+31+(15+14+1)x2 = 155 bits. 99of9, what's your own solution to get to 160? |
||||
Title: Re: Board Representation Post by 99of9 on Feb 4th, 2008, 6:41am Here is my 160 bit solution: 64 occupied/not 32 gold/not (as clauchau correctly notes, I should only use 31) For each colour, we now have up to 16 squares. A location amongst 16 squares can be denoted with 4 bits. So listing the locations for all of the 8 majour pieces takes 8*4 bits. Times 2 for the two colours = 64. The rest of the occupied squares (of known colour) must be rabbits. 64+32+64 = 160 (or 159 if you use clauchau's trick) |
||||
Title: Re: Board Representation Post by 99of9 on Feb 4th, 2008, 6:43am Using clauchau's trick, my complicated method comes down to 153! 64 occupied / not 31 gold / not From now on everything must be doubled for both colours: 15 rabbit / not Now we have 8 squares on which our majour pieces must be placed. An address amongst 8 requires 3 bits. Specify the addresses of the elephants and camels: 3 bits * 2 pieces = 6. Now we have 6 squares to place 2C 2D and 2H. Divide these 6 into two sets of 3. Are both cats in the same set of 3? 1 bit. Are both dogs in the same set of 3? 1 bit. a) If both answers were YES: Are cats both in first set? 1 bit. The answer to this question tells us whether we have {c,c,h}{d,d,h} or {d,d,h}{c,c,h}. Either way, we just need to find the horse in each set of 3. A location amongst 3 spots requires 2 bits. Do this for both sets of 3. 4 bits. (total required under option a is 5 bits) b) If both answers were NO: Now we know we have {c,d,h} in both sets, which we have to sort out. Do the following for each set: Specify the location of the cat. 2 bits. Now, out of the D/H, is the D first? 1 bit. (total required under option b is 6 bits) c) If one answer was YES, and the other NO (wlog cats were the YES): We have a similar situation to answer (a) except dogs have been switched for horses. We know we either have: {c,c,d}{h,h,d} or {h,h,d}{c,c,d} (figuring this out requires 5 bits, similar to answer (a)). So, at worst, we use: 64 + 31 + (15 + 6 + 2 + 6) * 2 = 153 |
||||
Title: Re: Board Representation Post by clauchau on Feb 4th, 2008, 7:13am Edit : Ouch, I used ruby to compute it, and forgot ^ is xor, not exponentiation, which is **. So what I describe below doesn't miraculously use only 122 bits but 149 :-X Ah yes, poor poor me, I had really managed 153 bits. Instead of 14 bits for distinguishing Gold cats from dogs from horses from camel-elephant, first use 7 to distinguish cats-dogs from horses-camel-elephant (the possible 8th is the missing one), then 3 to distinguish cats from dogs (the possible 4th is the missing one) and 3 to distinguish horses from camel-elephant. Combining lightvector arithmetics of combinations with this removal of 11 bits, and packing it all together we can get down to 149 bits : There are A = 64C32 + 64C31 + ... + 64C0 = 10139684107326071075 ways to choose 0 to 32 occupied squares among 64. There are B = 31C16 + 31C15 + ... + 31C0 = 1374282019 ways to choose 0 to 16 Gold pieces among 31. There are C = 15C8 + 15C7 + ... + 15C0 = 22816 ways to choose 0 to 8 rabbits among 15 Gold pieces. There are D = 7C4 + 7C3 + ... + 7C0 = 99 ways to choose 0 to 4 cats-dogs among 7 non-rabbit Gold pieces. There are E = 3C2 + 3C1 + 3C0 = 7 ways to choose 0 to 2 cats among 3 Gold cats or dogs and 0 to 2 horses among 3 Gold horses or elephant or camel. There are F = 2 ways to choose 0 to 1 camel among 1 Gold camel or elephant. So we only need G = A*B*(C*D*E*E*F)^2 = 682813102718264674657879442836350524710195200 ~ 2^148.94 ~ 10^44.83 The drawback is you need arithmetics on 149-bits integers though. |
||||
Title: Re: Board Representation Post by 99of9 on Feb 4th, 2008, 7:35am Nice! When computers go to 128 bits, someone might start trying this... |
||||
Title: Re: Board Representation Post by clauchau on Feb 4th, 2008, 8:26am Sorry 99of9, I was highly dreaming for a while there, it seems there really are more than 2^128 different positions ! |
||||
Title: Re: Board Representation Post by lightvector on Feb 4th, 2008, 8:47am I suspect that something in the above calculations is wrong. It should not be possible to get to 122 bits simply by piece combinations. Take the subcase where there are 32 pieces on the board. Then, the number of unique positions is given by: 64!/32!/8!/8!/2!/2!/2!/2!/2!/2! = 4.63 * 10^42 = 2^141.7 Any lossless encoding, regardless of how well it compresses, must distinguish each of these positions, and therefore must use at least 141.7 bits on average. And this doesn't even account for the cases where there are 31, 30, 29, etc. pieces. Taking into account things like traps, it could be possible to reduce it a bit, but the true optimal value should be close to 140 bits, if not slightly greater. Edit: This was addressed just prior to my post. |
||||
Title: Re: Board Representation Post by clauchau on Feb 4th, 2008, 10:36am Well spotted, lightvector. So I'll use 20 bytes = 160 bits to store each position that has already occured during the game. Now I realize I can use fewer bits when comparing a move with the other moves already generated for a given position, since most of the board is the same within the distance of a move (1 to 4 steps by the same player). Ideally I would like to compare the steps themselves modulo permutations and equivalent paths, but it seems a bit complicated to me for the moment. I have a simple solution with 58 bits, i.e. 58 bits are enough to code every unique positions 1 move away from a known given position, whatever that fixed position is. Any astute improvement? |
||||
Title: Re: Board Representation Post by leo on Feb 4th, 2008, 3:06pm on 02/04/08 at 10:36:52, clauchau wrote:
I probably miss your point, but moves can be stored in 36 bits: For each step: - 6 bits for the index of the origin square - 2 bits for the direction - 1 bit telling whether the nearest trap was activated (6+2+1)*4 = 9*4 = 36 But you are probably looking for a more convenient way to compute board state difference? Please tell us more! EDIT: One can even use piece index on 5 bits instead of square index, since we start from an already analysed position. Which reduces the data to 32 bits. But I keep feeling that this is not what you're after. Do you search a system that allows generating the resulting full state of the board by a simple operation out of the previous state and the difference? |
||||
Title: Re: Board Representation Post by clauchau on Feb 5th, 2008, 6:40am Leo, it's a good idea but I am not looking after a fast and compact way to code moves so that it's simple and fast to compose a board state with the code to get a new board state. For now listing steps is good enough for me for that purpose. I need a fast equivalence test for comparing the million moves I generate for the same position : If I show you two moves with different steps, can you tell me if they result in getting the same position? If they do, they are equivalent and I ignore one of them. So I would like a way to recode moves that would yield the same code if the moves are equivalent. Then I would only have to check equality of a few bytes. That's what hash/zobrist codes do on board states, except I also want to be sure the codes are different when the moves are not equivalent. Your code is a good start, but it doesn't say how to give the same code to equivalent moves with different steps. One solution is to compare the state boards. We could use the schemes we have designed here to deal with only 160 bits or so. With the help of lightvector's combinatorial wizardry and your reduction from 6 to 5 bits, I now claim there is a scheme that only need 31 bits. Something at the complication level of 99of9's and lightvector's ideas, but reasonable enough, especially because it's now only 31 bits. (By the way, the best solution would be to radically avoid any comparison by generating only one move for each set of equivalent moves. The move that represents his equivalence set could be minimal with respect to something. Every time I generate a move, I would only check whether it is minimal among all valid permutations of its steps and other null-effect changes on its paths. Anyway, it's a bit complicated to design right now.) |
||||
Title: Re: Board Representation Post by clauchau on Feb 5th, 2008, 7:52am on 02/02/08 at 18:39:45, jdb wrote:
I realize you are right. I calculated that during a million games between a random mover and a piece-count-optimizing mover (57 turns on average and 14600 unique best moves on average for each turn), there is a risk of 1 over 3000 to have a collision if 64 bits are used. I have been using 32 bit zobrist hashing, that's where I was wrong. Anyway, I think I'll now use an exact 31-bit coding scheme for the move generator. I'm crazy about being as tight and exact as possible. |
||||
Arimaa Forum » Powered by YaBB 1 Gold - SP 1.3.1! YaBB © 2000-2003. All Rights Reserved. |