Variable question

#1
Hello,
For a long term project, I want to be able to make a robot that would play mancala. To see how mancala is played, see https://www.thesprucecrafts.com/how-to-play-mancala-409424

For the first part of the program, I need it to sense if one cup was emptied and if so, to change it's variable (the one that counts how many pieces the cup has in it) to zero, and then add 1 to all the variables that come after for as many pieces there were in the first cup. This sounded like I needed a loop to go from 1 to how many was in the cup, and add one to the variables that would be affected. But I can't figure out how to increment the variable each time to add 1 to it.

I am using a picaxe 20x2 for this project.

If anyone has any ideas, I would welcome them.
RNovember
 
#3
Sorry, I should have been more clear. In my code, each cup has two variable. One of them is used to remember how many pieces are in the cup. After I empty one cup, I need to add one to the next cups. If I took the pieces out of cup 1, I need to add 1 to b2, add 1 to b3, and so on for as many pieces were in the first cup. This is what I can't figure out how to do.
 

hippy

Technical Support
Staff member
#4
Giving yourself a crash course in 'bptr' and '@bptr' use is probably going to pay dividends.

I'm not sure if I have got the game right so let's assume something where it's take whatever is in a cup and then spread them one at a time to following cups just by way of an example.

Let's assume 12 cups and 'b0' to 'b11' represents the cups and hold how many stones in each. And let's assume 'b0' contains some stones.
Code:
.-----.-----.-----.-----.-----.-----.
| b11 | b10 | b9  | b8  | b7  | b6  |   Play goes   <--.
}-----+-----+-----+-----+-----+-----{     anti         |
| b0  | b1  | b2  | b3  | b4  | b5  |   clockwise   `--'
`-----^-----^-----^-----^-----^-----'
So, if we are pointing at 'b0' ...

bPtr = 0

We can take how many there are ,,,

stones = @bPtr

And that cup (b0) is now empty, bPtr still points to 'b0' ...

@bPtr = 0

Then we step through the following cups dropping one stone in each while we have any stones ...
Code:
Do While stones > 0
  bPtr = bPtr + 1 // 12
  @bPtr = @bPtr + 1
  stones = stones - 1
Loop
I don't know if it helps but the equivalent in something like C using an array of 'b' for the cups is ...
Code:
bPtr = 0;
stones = b[bPtr];
b[bPtr] = 0;
while stones > 0 do
{
  bPtr = ( bPtr + 1 ) % 12;
  b[bPtr] = b[bPtr] + 1;
  stones = stones - 1;
};
 
Last edited:

Buzby

Senior Member
#5
This looks a great game to play by Picaxe !.

hippy just posted the core idea of how to do it, but I think there are 13 holes from the player's point of view, not 12.

When you say robot, do you mean a physical machine, or just software ?

A slow project I'm working on is a game engine to play Othello, but it would be fun to try it on Mancala.

Keep us informed of progress.

Cheers,

Buzby
 

hippy

Technical Support
Staff member
#6
hippy just posted the core idea of how to do it, but I think there are 13 holes from the player's point of view, not 12.
Reading the link I think you're right -

Code:
                       Their side
.-----.  .-----.-----.-----.-----.-----.-----.   Our
| b13 |  | b12 | b11 | b10 | b9  | b8  | b7  |  store   Play goes   <--.
`-----'  }-----+-----+-----+-----+-----+-----{  .----.    anti         |
 Their   | b0  | b1  | b2  | b3  | b4  | b5  |  | b6 |  clockwise   `--'
 store   `-----^-----^-----^-----^-----^-----'  `----'
                        Our side
It looks like an interesting game. Guess I'm going to have to read up on the rules.
 

Buzby

Senior Member
#7
From the link posted above :
Planning ahead is essential to victory in board games like Mancala. Try to plan two or three moves into the future.
This is the bit I'm struggling to implement in the restricted environment of a Picaxe. Looking at it again, mandala with 13 positions will be easier to implement than boards like Othello or chess with 64 positions. It also only has a maximum of 6 possible move choices at each turn, not the over 20 for Othello, which again reduces memory requirements. Even so, I think you might struggle on a 20X2.

I think I might change my engine to play mancala !
 

hippy

Technical Support
Staff member
#8
I think I might change my engine to play mancala !
It's a very interesting game, deceptively simple mechanics, albeit with numerous different versions and rules, but the strategy is quite complicated, or so it seems if one has never played before. It's a mix of winning while not handing your opponent an advantage

I now have a PICAXE Simulation version which handles the board and shows what's going on, allows both players to have their own strategy via #INCLUDE files ( including player controlled play against computer strategy ), so it basically asks a player "what hole do you want to play?", plays that, then hands back another go, passes play to the other, or declares a winner.

That means one can play against a simple computer strategy, against one's own designed computer strategy, or automatically play two people's strategies off against each other.

I was mostly interested in the engine part rather than the strategy or decision making so I'm not planning to win on that front. I can post the engine code but don't want to spoil any fun anyone else was looking to have. So I think posting that rests on RNovember saying "please do" or anyone asking "please don't".
 
#9
Hello,
Buzby said:
When you say robot, do you mean a physical machine, or just software ?
I haven't decided if I want it to be an actual robot that picks up washers with a magnet and moves them, or if I want the chip to just control LEDs that represent how many should be in a cup, or just have the robot tell you where to move its pieces (which lends itself to all kinds of fun!).

I actually started my variables at b1 because that is the way it seems to make sense to me for some reason.
Code:
Their side
.-----.    .-----.-----.------.-------.-----.------.     Our
| b14 |  | b13|b12| b11 | b10 | b9  | b8  |     store
`-----'   }-----+-----+-----+-----+-----+-----{     .----.
Their   | b1  | b2  | b3  | b4  | b5  | b6  |      | b7 |
store   `-----^-----^-----^-----^-----^-----'      `----'
                        Our side
(The formatting for the above board keeps getting jacked up)
For now I am just trying to get the software to be able to sense when a cup is emptied, and then advance the other variables that will be affected 1 number.

hippy said:
So I think posting that rests on RNovember saying "please do" or anyone asking "please don't".
Please do!

By the way, is there a way that you can write a computer program to get info from serout of the picaxe, process it, and send information back to the chip while the chip is running a program. If there is, then I could write a computer program to control the strategy, and use the picaxe for the rest. That would make it easier.
 
Last edited:

Buzby

Senior Member
#10
Hi hippy,

I think I bit off a bit more than I can chew with Othello. However, Mancala looks easier to code for the infrastructure stuff, lots less board to display, and lots less memory needed for each depth of the 'look ahead'.

The bit I can't gauge very well though is the 'board evaluation' routine, but I think I understand enough to code some strategies that will perform reasonably well.

My next challenge in the Othello is to code the 'look ahead', but this might be a bit easier with Mancala, because of the reduced moves possibilities.

Once the 'look ahead' logic is working it should be reasonably easy to apply it to other games, you just need to change the 'possible move', 'board evaluation' and 'depth+1' routines.

So if you don't think it will give me too much of a head start, I'd like to see your code.
( I did post my Othello in snippets, but it's not moved on much since then. )

Cheers,

Buzby
 

Buzby

Senior Member
#11
By the way, is there a way that you can write a computer program to get info from serout of the picaxe, process it, and send information back to the chip while the chip is running a program.
Yes, no problem at all.

You just need a PC with some kind of serial interface, and code written in a language you can speak. Visual Basic, C, Java, Excel VBA, BASIC, NODE-RED, or whatever the latest faddy language is.

Cheers,

Buzby
 

hippy

Technical Support
Staff member
#12
My version of an engine is attached. Just unzip the whole collection to a directory, then run PE6 and open the Mancala-003.bas file. Start the simulation and it should run through playing a game and showing that on the Terminal.

Right at the bottom you can tweak the algorithm to use.

Do ask if there's any questions.
 

Attachments

#13
hippy said:
Do ask if there's any questions.
OK, I have a question. Did you write all that code? And if so, how long did it take you.

I haven't had time to test the code yet.
Buzby said:
You just need a PC with some kind of serial interface, and code written in a language you can speak. Visual Basic, C, Java, Excel VBA, BASIC, NODE-RED, or whatever the latest faddy language is.
Buzby, I am using a homemade programing cable made from an old seria cable. See https://picaxeforum.co.uk/threads/hardware-not-found.31200/
Can I use that cable for it?
 
Last edited:

hippy

Technical Support
Staff member
#14
I actually started my variables at b1 because that is the way it seems to make sense to me for some reason.
I guess the only reason not to do that is it somewhat simplifies the maths when starting with b0 and bPtr being zero to point at that.

To cycle through 0 to 13 and then back to 0 one can simply do -

bPtr = bPtr + 1 // 14

To cycle through 1 to 14 and then back to 1 isn't really much more complicated -

bPtr = bPtr + 1 // 15 Min 1

If also means having to check a value is between 1 and 6 to be one's own hole/cup rather than simply < 6 which covers b0-b5.

As long as everything is consistent it should all be fine whichever is used. It probably just comes down to what one's most used to, the first being the 0 element or the first being 1. Going for the latter certainly isn't wrong.

When counting off holes/cup to play that it can be a pain if one forgets to start with 0 for the first so perhaps 1 for first is actually better. I guess I am inclined to agree. It also frees up b0 and 8 bit variables for general purpose use.

I also guess it's a classic case of why one shouldn't use 'magic number' constants in code; makes it a lot to change.
 

hippy

Technical Support
Staff member
#15
OK, I have a question. Did you right all that code? And if so, how long did it take you.
Yes all my own work. Probably spent about an hour or two last night being inspired ( more interesting than whatever was on TV ), and the same this morning. Basically the code in Post #4 was the guts of it; all else is just tweaking.
 
#16
OK, I didn't understand the advantages of starting with b0 instead of b1. I think I'll change my existing code.

Does a Picaxe 28x2 hold more memory than a 20x2?
 
Last edited:

hippy

Technical Support
Staff member
#17
OK, I didn't understand the advantages of starting with b0 instead of b1. I think I'll change my existing code.
If I were you I wouldn't. As I noted I think you have justified starting at 1 rather than 0 and am inclined to change my own scheme to reflect that.

I would probably have chosen to start with 1 if I hadn't just rushed in there to create a proof of concept.

Does a Picaxe 28x2 hold more memory than a 20x2?
It has more Scratchpad, 1024 bytes versus 128, which could be useful in determining strategy and what to play next, and it also has four internal program slots rather than just the one.

At this stage I wouldn't worry about moving to the 28X2 but would stick with the 20X2.

There are three parts; the game, playing strategy, plus the robot interface. All three can be developed pretty much independently of the other.

On strategy; it's fun to design strategies which will win a game, great to be able to succeed, but it's not so much fun to play against them. So that's one thing to keep in mind.

I was reflecting on how one could build a robot to play Mancala. I suspect the best way would be to play with a variant of the board. Perhaps make them squares on a flat surface and use chess pawns as stones. That way a traditional robot arm or some three-axis contraption can pick them up individually, take them off the board and drop them on it one at a time. That might require some pretty big squares.

Magnets sounded like they could be an idea, but I'm not sure how you would achieve picking up or dropping just one piece at a time if placed in cups.
 
#18
My idea for the design of the board was to take a flat piece of wood and where there would be the 12 holes in the two rows, I would glue two strips of tinfoil, not touching each other, and use metal washers as my pieces. Each spot would have one piece of tinfoil connected to ground, and the other one would be connected to the 20x2. That way, the robot can tell what cup was just moved by just testing all its pins to see if any are low (if there is a washer in that cup, it will bridge power to that pin (you might have seen the picaxe robot that could play tic tac toe. This is where I got the idea for the whole thing)). Then I would glue a board with holes on top of the other board, so that the washers stay on the tinfoil.

In my second post in this thread, I said that each hole had two variables. The second one is set to 1 when the cup is first emptied, and set back to 0 when it is filled again. This is so that if one cup is emptied on one round and nothing gets put in it the second round, the robot doesn't think that the cup was emptied again, and add more to the other cups that shouldn't be there.

My design for the arm might be overly complicated. I thought that I would have one arm with and electromagnet to pick up the washers, and then drop them in a cup in another arm (I thought maybe I could combine both arms, and just have the electromagnet be a little side thing that comes off). The cup would have a little slit in the bottom just wide enough to fit one washer through at a time. Then, as the arm went around counter clockwise, there would be a little rod in the back that would push one washer out into a hole on the board.

That might be overly complicated, so I might simplify it.
 
Last edited:
#19
Okay, I have started to test some code, and it doesn't seem to work.
here's my code.
Code:
b1 = 4
b2 = 4
b3 = 4
b4 = 4
b5 = 4
b6 = 4
b7 = 0
b8 = 4
b9 = 4
b10 = 4
b11 = 4
b12 = 4
b13 = 4
b14 = 0
symbol stones = @bPtr

do
    if pinC.0 = 1 then
        bPtr = 1
        @bPtr = 1
        stones = @bPtr
        Do While stones > 0
            bPtr = bPtr + 1 // 15 Min 1
            @bPtr = @bPtr + 1
            stones = stones - 1
        loop
    endif
loop
When I simulate it (I haven't downloaded it to a chip yet) and watch the "b" values that I am using, they increment one, like they are supposed to, and then they jump back. I can't figure out why. Does anyone know?
 
#21
Okay, I tried changing stones to b15, and now it only increments b2 every time it goes through the loop.
Code:
b1 = 4
b2 = 4
b3 = 4
b4 = 4
b5 = 4
b6 = 4
b7 = 0
b8 = 4
b9 = 4
b10 = 4
b11 = 4
b12 = 4
b13 = 4
b14 = 0
symbol stones = b30

do
    if pinC.0 = 1 then
        bPtr = 1
        @bPtr = 1
        stones = @bPtr
        Do While stones > 0
            bPtr = bPtr + 1 // 15 Min 1
            @bPtr = @bPtr + 1
            stones = stones - 1
        loop
    endif
loop
I still don't know what is going on with the bptr and @bptr.
 
#22
bPtr = 1
bPtr is a pointer into RAM. Addresses 0 to 20 or more (depending on your chip) are b0 to b20. @bptr is the contents of the RAM addressed by bPtr. So, as you have set bPtr = 1, bPtr is addressing b1. So the next line
@bPtr = 1
is the same as b1 = 1

stones = @bPtr
is equivalent to b30 = b1, so stones = 1

Do While stones > 0
well, at the moment, stones = 1 so we do start ...

bPtr = bPtr + 1 // 15 Min 1
bPtr now becomes 2

@bPtr = @bPtr + 1
bPtr is 2, so @bptr is b2, so b2 = b2 + 1 (i.e. 5)

stones = stones - 1
stones is now zero, so the loop will terminate.
loop
 
#23
Thanks for the information. Now I understand what is going on.

Code:
b1 = 4
b2 = 4
b3 = 4
b4 = 4
b5 = 4
b6 = 4
b7 = 0
b8 = 4
b9 = 4
b10 = 4
b11 = 4
b12 = 4
b13 = 4
b14 = 0
symbol stones1 = b1
symbol stones2 = b2
symbol stones3 = b3
symbol stones4 = b4
symbol stones5 = b5
symbol stones6 = b6
symbol stones7 = b7
symbol stones8 = b8
symbol stones9 = b9
symbol stones10 = b10
symbol stones11 = b11
symbol stones12 = b12
symbol stones13 = b13
symbol stones14 = b14

do
        if pinC.0 = 1 then
            bPtr = 8
            Do While stones8 > 0
                bPtr = bPtr + 1 // 15 Min 1
                @bPtr = @bPtr + 1
                stones8 = stones8 - 1
            loop
    endif

    if pinC.1 = 1 then
            bPtr = 9
            Do While stones9 > 0
                bPtr = bPtr + 1 // 15 Min 1
                @bPtr = @bPtr + 1
                stones9 = stones9 - 1
            loop
        endif

    if pinC.2 = 1 then
            bPtr = 10
            Do While stones10 > 0
                bPtr = bPtr + 1 // 15 Min 1
                @bPtr = @bPtr + 1
                stones10 = stones10 - 3
            loop
        endif

    if pinC.3 = 1 then
            bPtr = 11
            Do While stones11 > 0
                bPtr = bPtr + 1 // 15 Min 1
                @bPtr = @bPtr + 1
                stones11 = stones11 - 1
            loop
        endif

    if pinC.4 = 1 then
            bPtr = 12
            Do While stones12 > 0
                bPtr = bPtr + 1 // 15 Min 1
                @bPtr = @bPtr + 1
                stones12 = stones12 - 1
            loop
        endif

    if pinC.5 = 1 then
            bPtr = 13
            Do While stones13 > 0
                bPtr = bPtr + 1 // 15 Min 1
                @bPtr = @bPtr + 1
                stones13 = stones13 - 1
            loop
        endif


loop
There still seem to be some problems, but I'm working on it.
 
Last edited:
#24
You would do well to learn to use the simulator for this problem. You can single-step through the code and see exactly what is happening and what the variable values are.
 
#25
This is my schematic.
Code:
.-----.
|   c.1|----------------------------------.
|   c.2|-----------------------------.     |
|   c.3|------------------------.     |    |
|   c.4|------------------.      |    |    |
|   c.5| ------------.     |     |    |    |
|   c.6| ------.     |     |     |    |    |
------      .-----.-----.------.-----.----.----.                                                                  
.-----.     | b13 | b12 | b11  | b10 | b9 | b8 |       .-----.
| b14  |    }-----:-----:------:-----:----:----{       | b7  |
            | b1  | b2  | b3   |  b4 | b5 | b6 |
            `-----^-----^------^-----^----^----^
Each cup has a switch that conects to ground when there are stones in it.
 

hippy

Technical Support
Staff member
#26
Subroutines will solve a lot of problems, #MACRO perhaps even more so, but we will leave those for later ...
Rich (BB code):
Do
  If pinC.0 = 1 then
    bPtr = 8 : Gosub MoveStones 
  End If
  If pinC.1 = 1 then
    bPtr = 9 : Gosub MoveStones
  End If
  etc
Loop

MoveStones:
  stones = @bPtr
  Do While stones > 0
    bPtr = bPtr + 1 // 15 Min 1
    @bPtr = @bPtr + 1
    stones = stones - 1
  Loop
  Return
 
Last edited:
#27
Not quite ...
The "stones8" in the MoveStones subroutine should be "stones".

I would also be inclined to use
Code:
@bPtr = @bPtr // 14 + 1
which I think is a bit more elegant (and uses less code). It also makes it a bit more obvious that you have a set of 14 items rather than 15.
 
#29
Okay, I think that I am just going to have the picaxe keep track of variables for now, and have the raspberry pi control the strategy. The only thing is that I need to be able to use I2C. Which pins are those on a 20x2, and how do I use them.

The raspberry pi has 40 gpio (General Purpose Input Output) pins, 4 of which are I2C, so I thought that this would be a good way to do it. Also, there is a python library for dealing with gpio pins, so it would be easy to get it to talk to a python file (which is the only other high level language that I know).
 

hippy

Technical Support
Staff member
#31
Okay, I think that I am just going to have the picaxe keep track of variables for now, and have the raspberry pi control the strategy.
It would probably be better to have the PICAXE control the hardware, read the sensors, move the arm, inform the Pi which cup has been triggered, have the Pi tell the PICAXE which cup to trigger.

That will be far easier done using UART serial or, even better and simpler, with an AXE027 plugged into a Pi's USB port, rather than I2C.
 

hippy

Technical Support
Staff member
#33
A UART is simply a serial sending and receiving chip, exactly what's behind your PC case which sends downloads to the PICAXE if using a 9-way serial port rather than an AXE027.

TX is the signal which comes out of a UART, RX is the signal which goes into it. These can attach to a PICAXE but be careful with a Pi because voltages must never exceed 3V3 and the UART polarity is inverted compared to what the normal download protocol is.

You will have to jump through some hoops to enable the Pi's UART to be used for data transfer, but you would still have those hoops to jump through to use I2C.

It would probably be best to embark on a separate sub-project to the Mancala project to get to grips with linking a PICAXE to a Pi and transferring data.
 
Top