For this week’s assignment I wanted to make a dice-roller for monopoly – As in, an object that you shake as if you’re shaking dice and that triggers the dice roll in the monopoly I had previously made in processing. This proved to be challenging.
I wanted to make the roller as compact and sturdy as possible, since it will be subject to shaking and I didn’t want anything to come lose, so I started with this circuit:

I used an arduino maker1000 because of it’s small size. The shaking was detected using a tilt sensor. Everything is soldered on in one unit so it was easy to hold and shake and everything would still be stable. However, no matter how hard I tried, the maker1000 would not communicate with processing. So I switched to a redboard.

Here’s the video of how it works:
The code:
Arduino:
const int tiltPin = 6;
const int ledPin = 10;
int tiltState; // the current reading from the input pin
int lastTiltState = LOW; // the previous reading from the input pin
int counter = 0;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 20;
void setup() {
// put your setup code here, to run once:
pinMode(tiltPin, INPUT);
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
digitalWrite(ledPin, HIGH);
Serial.write(0);
}
void loop() {
if (Serial.available() > 0) {
int inByte = Serial.read();
if (counter <= 20) {
digitalWrite(ledPin, HIGH);
Serial.write(0);
} else {
counter = 0;
digitalWrite(ledPin, LOW);
Serial.write(1);
delay(2000);
}
int reading = digitalRead(tiltPin);
if (reading != lastTiltState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != tiltState) {
tiltState = reading;
counter++;
}
}
// Serial.print(reading);
// Serial.print(" || ");
// Serial.println(counter);
lastTiltState = reading;
}
// put your main code here, to run repeatedly:
}
Processing:
import processing.serial.*;
//0 name, 1 type, 2 owner, 3 cost, 4 rent, 5 xcoordinate, 6 ycoordinate
// types: 0 = income tax, 1 = normal, 2 = railroad, 3 = utilities, 4 = community chest and chance, 5 = jail and free parking, 6 = go,7 = supertax
String[][] places = {
{"Go", "6", "Bank", " ", "-200", "750", "750"}, // 0
{"Old kent road", "1", "Bank", "60", "6", "660", "750"}, // 1
{"Community chest", "4", "Bank", " ", "0", "595", "750"}, // 2
{"White chapel road", "1", "Bank", "60", "6", "530", "750"}, //3
{"Income tax", "0", "Bank", " ", "200", "465", "750"}, // 4
{"Kings cross station", "2", "Bank", "200", "25", "400", "750"}, // 5
{"The angel islington", "1", "Bank", "100", "10", "335", "750"}, // 6
{"Chance", "4", "Bank", " ", "0", "270", "750"}, // 7
{"Euston Road", "1", "Bank", "100", "10", "205", "750"}, // 8
{"Pentonville Road", "1", "Bank", "120", "12", "140", "750"}, // 9
{"Jail", "5", "Bank", " ", "0", "50", "750"}, // 10
{"Pall Mall", "1", "Bank", "140", "14", "50", "660"}, // 11
{"Electric Company", "3", "Bank", "150", "15", "50", "595"}, // 12
{"Whitehall", "1", "Bank", "140", "14", "50", "530"}, // 13
{"Northumberland Avenue", "1", "Bank", "160", "16", "50", "465"}, // 14
{"Marylebone station", "2", "Bank", "200", "25", "50", "400"}, // 15
{"Bow street", "1", "Bank", "180", "18", "50", "335"}, // 16
{"Community chest", "4", "Bank", " ", "0", "50", "270"}, // 17
{"Marlborough street", "1", "Bank", "180", "18", "50", "205"}, // 18
{"Vine street", "1", "Bank", "200", "20", "50", "130"}, // 19
{"Free Parking", "5", "Bank", " ", "0", "50", "50"}, // 20
{"Strand", "1", "Bank", "220", "22", "140", "50"}, // 21
{"chance", "4", "Bank", " ", "0", "205", "50"}, // 22
{"Fleet street", "1", "Bank", "220", "22", "270", "50"}, // 23
{"Trafalgar square", "1", "Bank", "240", "24", "335", "50"}, // 24
{"Fenchurch st station", "2", "Bank", "200", "25", "400", "50"}, // 25
{"Leicester square", "1", "Bank", "260", "26", "465", "50"}, // 26
{"Coventry street", "1", "Bank", "260", "26", "530", "50"}, // 27
{"Waterworks", "3", "Bank", "150", "15", "595", "50"}, // 28
{"Piccadilly", "1", "Bank", "280", "28", "660", "50"}, // 29
{"Jail", "5", "Bank", " ", "0", "750", "50"}, // 30
{"Regent street", "1", "Bank", "300", "30", "750", "130"}, // 31
{"Oxford street", "1", "Bank", "300", "30", "750", "205"}, // 32
{"Community chest", "4", "Bank", " ", "0", "750", "270"}, // 33
{"Bond street", "1", "Bank", "320", "32", "750", "335"}, // 32
{"Marylebone station", "2", "Bank", "200", "25", "750", "400"}, // 15
{"Chance", "4", "Bank", " ", "0", "750", "465"}, // 33
{"Park lane", "1", "Bank", "350", "32", "750", "530"}, // 32
{"Supertax", "7", "Bank", " ", "200", "750", "595"},
{"Mayfair", "1", "Bank", "400", "40", "750", "660"},
};
int toRoll;
int prevToRoll;
boolean allowRoll = true;
int circlesize = 10;
int turn = 0;
int diceroll;
PImage bg;
boolean first = true;
boolean proceed = false;
// colors: red or blue
Player p1 = new Player("red", int(places[0][5]), int(places[0][6]), 10);
Player p2 = new Player("blue", int(places[0][5]), int(places[0][6]), -10);
Serial myPort;
void setup() {
printArray(Serial.list());
String portname=Serial.list()[2];
println(portname);
myPort = new Serial(this, portname, 9600);
//myPort.clear();
//myPort.bufferUntil('\n');
first = false;
size(800, 800);
bg = loadImage("board.jpg");
background(0);
fill(255);
textSize(16);
text("Welcome to mehnopoly. It's almost monopoly, but seriously lower your expectations.", 20, 50);
text("The game is for two players. or You can play against yourself if you can't find friends. I dont judge.", 20, 100);
text("You win by making your opponent go bankrupt. Go nuts!", 20, 150);
text("Press S to start the game", 20, 200);
textSize(12);
text("Fun Fact: Monopoly was originally created as a statement against capitalism.", 20, 250);
}
void draw() {
if (proceed==true ){
refresh();
allowRoll = false;
diceroll = rollDice();
handleRoll();
proceed=false;
}
if (first) {
textSize(24);
fill(255, 127, 0);
text("Player 1 has "+p1.money+" left", 150, 200);
text("Player 2 has "+p2.money+" left", 150, 250);
text("Player 1's turn", 150, 300);
text("Press R to roll dice", 150, 350);
}
}
int keycounter = 0;
class Player {
int money, xpos, ypos, rails, utilities, offset, placecount, propertyamount;
int[] properties = new int[50];
String col;
Player (String n, int xp, int yp, int off) {
col = n;
placecount = 0;
money = 1500;
offset = off;
xpos = xp;
ypos = yp;
rails = 0;
utilities = 0;
propertyamount = 0;
}
void display() {
strokeWeight(2);
stroke(255, 255, 255);
if (col == "red")fill(255, 0, 0);
if (col == "blue")fill(0, 0, 255);
ellipse(xpos+offset, ypos, circlesize, circlesize);
}
void updatePos() {
xpos = int(places[placecount][5]);
ypos = int(places[placecount][6]);
}
}
int rollDice() {
return round(random(2, 12));
//return 7;
}
void checkLanded(Player x) {
textSize(24);
fill(255, 127, 0);
text("You rolled "+diceroll+" and landed on: "+places[x.placecount][0], 150, 200);
if (int(places[x.placecount][1]) == 5 || int(places[x.placecount][1]) == 6)text("Press E to end turn", 150, 250);
// if income tax
if (int(places[x.placecount][1]) == 0) {
fill(255, 127, 0);
text("You pay 200 for income tax", 150, 250);
x.money-=200;
text("You now have: "+str(x.money)+" left", 150, 300);
text("Press E to end turn", 150, 350);
// if purchasable
} else if (int(places[x.placecount][1]) == 1 || int(places[x.placecount][1]) == 2 || int(places[x.placecount][1]) == 3) {
// if owner is bank
if (places[x.placecount][2] == "Bank") {
fill(255, 127, 0);
text("Property isn't owned, what would you like to do?", 150, 250);
text("Press B to buy for "+places[x.placecount][3]+" or press E to end turn", 150, 300);
// if owner is not bank
} else {
// if it's a normal purchasable
if (int(places[x.placecount][1]) == 1) {
if (turn == 0 && places[x.placecount][2] == "Player2")handleRent(p1, p2, int(places[x.placecount][4]));
if (turn == 1 && places[x.placecount][2] == "Player1")handleRent(p2, p1, int(places[x.placecount][4]));
// if railroad
} else if (int(places[x.placecount][1]) == 2) {
int rent;
if (turn == 1 && places[x.placecount][2] == "Player1") {
rent = checkRailRent(p1);
handleRent(p2, p1, rent);
} else if (turn == 0 && places[x.placecount][2] == "Player2") {
rent = checkRailRent(p2);
handleRent(p1, p2, rent);
}
// if utilities
} else if (int(places[x.placecount][1]) == 3) {
int rent = 0;
if (turn == 0 && places[x.placecount][2] == "Player2") {
if (p2.utilities == 1)rent= 7*diceroll;
if (p2.utilities == 2)rent= 15*diceroll;
handleRent(p1, p2, rent);
} else if (turn == 1 && places[x.placecount][2] == "Player1") {
if (p1.utilities == 1)rent= 7*diceroll;
if (p1.utilities == 2)rent= 15*diceroll;
handleRent(p2, p1, rent);
}
}
}
// super tax
} else if (int(places[x.placecount][1]) == 7) {
fill(255, 127, 0);
text("You pay 100 for super tax", 150, 250);
x.money-=200;
text("You now have: "+str(x.money)+" left", 150, 300);
text("Press E to end turn", 150, 350);
//community chest and chance
} else if (int(places[x.placecount][1]) == 4) {
int r = round(random(1, 3));
if (!(r == 2)) {
text("Jeff Bezos felt generous today, he gave you 100!", 150, 250);
text("Assuming 1 = $100,000 , this amounts to", 150, 300);
text("a whooping 0.0001% of his net worth", 150, 350);
text("press E to end turn", 150, 400);
x.money += 100;
} else {
text("You did some contractual work on one of", 150, 250);
text("Trump's properties! He paid you a 1000!", 150, 300);
text("Just kidding, he didn't pay you at all.", 150, 350);
text("In fact you paid a 100 for materials.", 150, 400);
text("press E to end turn", 150, 450);
x.money -= 100;
}
}
checkWin();
}
void checkWin() {
if (p1.money < 0) {
refresh();
fill(255, 127, 0);
text("P2 has won", 150, 200);
noLoop();
}
if (p2.money < 0) {
refresh();
fill(255, 127, 0);
text("P1 has won", 150, 200);
noLoop();
}
}
void endTurn() {
refresh();
fill(255, 127, 0);
text("Player 1 has "+p1.money+" left", 150, 200);
text("Player 2 has "+p2.money+" left", 150, 250);
if (turn == 0) {
fill(255, 127, 0);
text("Player 1's turn has ended. Player 2's turn", 150, 300);
turn = 1;
} else {
fill(255, 127, 0);
text("Player 2's turn has ended. Player 1's turn", 150, 300);
turn = 0;
}
text("Press R to roll or I for a list of your properties,", 150, 350);
allowRoll = true;
checkWin();
}
void refresh() {
background(bg);
p1.display();
p2.display();
fill(0);
rect(100, 100, 600, 600);
}
void buy(Player x) {
fill(255, 127, 0);
if (places[x.placecount][2] == "Bank") {
x.money -= int(places[x.placecount][3]);
x.properties[p1.propertyamount] = x.placecount;
x.propertyamount++;
text(places[x.placecount][0]+" has been purchased", 150, 200);
if (turn == 0) places[x.placecount][2] = "Player1";
if (turn == 1) places[x.placecount][2] = "Player2";
if (int(places[x.placecount][1]) == 2) {
x.rails += 1;
text("You now have "+x.rails+" railroads", 150, 250);
text("Press E to end turn", 150, 300);
} else if (int(places[x.placecount][1]) == 3) {
x.utilities += 1;
text("You now have "+x.utilities+" utilities", 150, 250);
text("Press E to end turn", 150, 300);
} else {
text("Press E to end turn", 150, 250);
}
}
checkWin();
}
int checkRailRent(Player x) {
if (x.rails == 1) return x.rails*25;
if (x.rails == 2) return x.rails*25;
if (x.rails == 3) return 100;
if (x.rails == 4) return 200;
return 0;
}
void handleRent(Player renter, Player rentee, int rent) {
renter.money -= rent;
rentee.money += rent;
fill(255, 127, 0);
text("Property is owned, you have paid "+rent+" in rent", 150, 250);
text("You have "+renter.money+" left", 150, 300);
text("Press E to end turn", 150, 350);
checkWin();
}
void handleRoll() {
if (turn == 0) {
if (p1.placecount + diceroll >= 40) {
p1.placecount = p1.placecount+diceroll - 40;
p1.money += 200;
} else {
p1.placecount+= diceroll;
}
p1.updatePos();
refresh();
checkLanded(p1);
} else {
if (p2.placecount + diceroll >= 40) {
p2.placecount = p2.placecount+diceroll - 40;
p2.money += 200;
} else {
p2.placecount+= diceroll;
}
p2.updatePos();
refresh();
checkLanded(p2);
}
}
void serialEvent(Serial myPort) {
int x = myPort.read();
println(x);
if (x == 1 && allowRoll) {
proceed=true;
}
//toRoll = myPort.read();
//println(toRoll);
myPort.write(0);
}
void keyPressed() {
//keycounter++;
//if (keycounter == 1) first = true;
//if (keycounter == 2) first = false;
if (key =='s')refresh();
//refresh();
// Roll dice phase
if ((key == 'r' || key == 'R')&&allowRoll) {
allowRoll = false;
diceroll = rollDice();
handleRoll();
}
if ((key == 'b' || key =='B')&& !allowRoll) {
refresh();
if (turn == 0) {
buy(p1);
} else {
buy(p2);
}
}
if ((key == 'e' || key == 'E')&& !allowRoll) {
refresh();
endTurn();
}
if ((key == 'i' || key == 'I') && allowRoll) {
fill(255, 127, 0);
if (turn == 0) {
int ycounter = 200;
for (int i = 0; i<p1.propertyamount; i++, ycounter+=50) {
text(places[p1.properties[i]][0], 150, ycounter);
}
}
if (turn == 1) {
int ycounter = 200;
for (int i = 0; i<p2.propertyamount; i++, ycounter+=50) {
text(places[p2.properties[i]][0], 150, ycounter);
}
}
}
}