Up to Main Index Up to Journal for March, 2015 JOURNAL FOR MONDAY 16TH MARCH, 2015 ______________________________________________________________________________ SUBJECT: That's the way to go - with a bit of fun DATE: Mon 16 Mar 22:34:47 GMT 2015 After much procrastinating and even more umming and erring I have decided to export some types so that I can provide better documentation[1]. After refactoring the code I'm back to documenting again. For some reason people actually *LIKE* reading my comments and documentation, quite often finding it amusing... Only a few people have seen the code for WolfMUD-mini so far but one method seems to confound them - I like leaving little 'gems' for people who actually read the code to find :) In the exits code I have defined constants for directions: const ( North byte = iota Northeast East Southeast South Southwest West Northwest Up Down ) No surprises there. Later on there is a method that calculates the opposite of a given direction. Here it is complete with comments: // Return calculates the opposite/return direction for the direction given. // This is handy for calculating things like normal exits where if you go // north you return by going back south for example. func Return(direction byte) byte { if direction < Up { return direction ^ 1<<2 } else { return direction ^ 1 } } This does a little bit of bit twiddling[2]. Sadly a lot of programmers don't do bit twiddling any more, most of the programmers I know wouldn't even know what the << and ^ operators do! So for completeness I will start off with an explanation of those operators - feel free to skim the explanations if you are already an accomplished bit twiddler :) Left shift operator '<<' The left shit operator takes the binary representation of a number and shifts the bits to the left, the left most bit drops off and zeros are added to the right. The number to be shifted is on the left and the number of bits to shift by is on the right. For example: 148 decimal = 10010100 binary 148 << 2 = 10010100 << 2 = 10010100 00101000 (shifted left once) 01010000 (shifted left twice) = 80 decimal In the code above we have: 1 decimal = 00000001 binary 1 << 2 = 00000001 << 2 = 00000001 00000010 (shifted left once) 00000100 (shifted left twice) = 4 decimal So in the above code we could have written '4' instead of '1<<2' however when bit twiddling it is usually easier to write numbers using shifts instead of decimal, hex or octal. Bitwise exclusive OR '^' The bitwsie exclusive OR (XOR )operator compares two numbers. Where the bits are the same a 0 is returned in the result. If they are different a 1 is returned. For example: 148 decimal = 10010100 binary 28 decimal = 00011100 binary 148 ^ 28 = 10010100 00011100 -------- 10001000 = 136 decimal One interesting property of XOR is that the number to the right can be used as a mask to toggle bits on and off in the number to the left. In the number to the right - the mask - zeros keep their original values while ones indicate bits to be toggled. Reusing our example from before we can toggle the bits back again by repeating the operation with the same mask - of 28 decimal or 00011100 binary - on the previous result we got: 136 ^ 28 = 10001000 00011100 -------- 10010100 = 148 decimal In our example go code 'direction ^ 1<<2', simplified as 'direction ^ 4' is simply taking the value of direction and toggling the 3rd bit - because 4 decimal is 00000100 binary. But how does this explain how the code calculates the opposite direction!? Lets create a table representing the decimal and binary values of the constants: Constant Decimal Binary North 0 00000000 Northeast 1 00000001 East 2 00000010 Southeast 3 00000011 South 4 00000100 Southwest 5 00000101 West 6 00000110 Northwest 7 00000111 Up 8 00001000 Down 9 00001001 If you look closely at the table the first four directions (North, Northeast, East, Southeast) map to the next four directions (South, Southwest, West, Northwest). If you look at the binary representation the only difference in the two groups is the 3rd bit - 0 in the first group and 1 in the second. So if we take any of the first 8 directions we can flip the 3rd bit to get it's opposite direction! Lets take Southwest as an example: Southwest ^ 4 = 5 ^ 4 = 00000101 00000100 -------- 00000001 = 1 = Northeast This only works for the first 8 directions - those before Up. This is why we need the if statement in our original code 'if direction < Up'. If we look at out table we see that the only difference between Up and Down is the right most bit. So we can simple flip that bit to toggle between Up and Down. This is what 'direction ^ 1' does for us. And there you have it - a 7 line function explained in only 160 odd lines ;) -- Diddymus [1] 3.html [2] Proper programmers twiddle their own bits. Up to Main Index Up to Journal for March, 2015