Dice-roller for Monopoly

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);
      }
    }
  }
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *