You are here

Informatiker-Zeitvertreib

Am 1.1. wollte Bettina unbedingt "Mensch ärgere dich nicht" spielen. Ich war nicht so begeistert, weil ich das Spiel für ziemlich langweilig halte. Zunächst diskutierten wir also meinen Standpunkt ("Da würfelt man doch nur abwechselnd") und den von Bettina ("Gar nicht, das hat voll viel mit Taktik zu tun"). Schlussendlich haben wir dann drei Runden gespielt. Später hatten wir Hunger und da nichts zu Essen im Haus war, haben wir uns Happy Meals bei McDonald's geholt. Als Spielzeug gab es "Monopoly Junior", also wurde auch das gespielt. Im Vergleich zum normalen Monopoly geht es deutlich vereinfacht zu - wenn man auf einer Straße ohne Besitzer landet kauft man und markiert sie mit einem Haus - zusätzliche Häuser kann man nicht erwerben.

Monopoly Junior

Das Spiel war ganz lustig und ich hatte zunächst das Gefühl, sehr viel mehr Kontrolle über mein Schicksal als bei "Mensch ärgere dich nicht" zu haben. Schließlich hatte man Geldscheine in der Hand, konnte Straßen kaufen und musste Miete bezahlen. Aber nach einer Weile dämmerte mir, dass durch die vereinfachten Regeln das Ganze mehr einer griechischen Tragödie ähnelt: das Schicksal ist vorherbestimmt. Schließlich muss man kaufen, wenn man auf einer Straße ohne Besitzer landet und gezieltes Investieren ist durch die Nur-ein-Haus-Regel auch nicht möglich. Also schlimmer als "Mensch ärgere dich nicht", bei dem man immerhin noch überlegen kann, wo man seine erwürfelten Punkte am besten investiert; nämlich dort, wo die Chance am geringsten ist, sie wieder zu verlieren. Außerdem fiel uns auf, dass bei uns immer der Spieler die Partie gewann, der als erster gezogen hatte. Ist es wirklich so ein Vorteil, die erste Runde vor dem anderen herzulaufen oder war das Zufall? Da inzwischen klar war, dass es - anders als bei "Mensch ärgere dich nicht" - wirklich nur um abwechselndes Würfeln geht und man absolut keinen Einfluss auf den Spielverlauf hat (verbotenes Glücksspiel!), war die nächste Neujahrsbeschäftigung schnell gefunden: Wir haben eine Monopoly-Junior-Simulation geschrieben um herauszufinden, wie deutlich sich der Startvorteil auswirkt (wenn es ihn denn gibt). Nach zwei Stunden programmieren und 1.000.000 simulierten Spielen hatten wir das Ergebnis:

Gewinnchancen bei Monopoly Junior:

Bei zwei Spielern: Spieler 1: 57.24% Spieler 2: 41.50% Unentschieden: 1.26%

Bei drei Spielern: Spieler 1: 42.62% Spieler 2: 30.96% Spieler 3: 23.80% Unentschieden: 2.62%

Bei vier Spielern: Spieler 1: 34.35% Spieler 2: 25.20% Spieler 3: 19.13% Spieler 4: 14.96% Unentschieden: 6.36%

Also: Immer bei Monopoly Junior als erster ziehen und mit möglichst vielen Leuten spielen (die man am besten abwechselnd auf unterschiedlichen Positionen starten lässt). Das ist kein Schummeln - nur ein schlechtes Spieldesign.

Und für alle, die diese bahnbrechenden Ergebnisse überprüfen wollen, hier noch der Quellcode:

package mcmonopolyjunior;

import java.util.Random;

/**
 * Simuliert das Spiel Monopoly Junior (aus dem McDonald's Happy Meal)
 * um herauszufinden, wie sehr die Gewinnchancen von der Startposition
 * des Spielers abhängen. Da man bei diesem Spiel keinen taktischen
 * Entscheidungsspielraum hat, lässt es sich vollständig simulieren.
 *
 * Wie sich bei den Simulationen gezeigt hat, kann das Spiel ins Leere
 * laufen: Es kann so lange keinen Gewinner geben, dass die Bank kein Geld
 * mehr hat. Setzt für die Bank Liquidität voraus (unendlich viel Geld
 * im Spiel), so kann es passieren, dass die Spieler so viel Geld
 * ansammeln, dass die Partie in eine Endlosschleife gerät. Deshalb wird
 * ein unentschieden angenommen, wenn ein Spieler mehr Geld hat, als die
 * Bank im realen Spiel (100$).
 * Wenn zwei Spieler gleich viel Geld haben, wenn die Partie endet, wird
 * ebenfalls ein Unentschieden gezählt.
 *
 * @author Bettina Selig und Tilman Walther
 */

public class McMonopolyJunior {
       
        int[] money;
        int[] position;
       
        int[] rent = { 1, 2, 2, 3, 3, 4, 4, 5 };
        int[][] streets = new int[8][2];
        int jackpot;
       
        private Random rnd = new Random();
        boolean gameOver;
       
        public int simulate(int numPlayers) {
               
                if ((numPlayers < 2) || (numPlayers > 4)) {
                        System.err.println("Diese Spielerzahl ist nicht möglich.");
                        System.exit(1);
                }
               
                gameOver = false;
                money = new int[numPlayers];
                position = new int[numPlayers];
               
                int budget;
               
                if (numPlayers == 2)
                        budget = 25;
                else if (numPlayers == 3)
                        budget = 20;
                else
                        budget = 15;
               
                for (int i = 0; i < numPlayers; i++) {
                        money[i] = budget;
                }
               
                for (int i = 0; i < streets.length; i++) {
                        streets[i][0] = -1;
                        streets[i][1] = -1;
                }
               
                // Spielen!
                while (!gameOver) {
                        for (int i = 0; (i < numPlayers) && (!gameOver); i++) {
                                move(i);
                        }
                }
               
                // Abbruchbedingung: Wenn ein Spieler mehr Dollar hat, als die Bank ursprünglich besitzt,
                // wird das Spiel nicht gewertet
                for (int i = 0; i < numPlayers; i++) {
                        if (money[i] > 100)
                                return -1;
                }
               
                int winner = 0;
                for (int i = 1; i < numPlayers; i++) {
                        if (money[i] > money[winner]) {
                                winner = i;
                        }
                        else if (money[i] == money[winner]) {
                                // bei einem Unentschieden wird das Spiel nicht gewertet
                                return -1;
                        }
                }
               
                return winner;
        }
       
        private void move(int player) {
                position[player] = position[player] + rnd.nextInt(6) + 1;
               
                // Ziehen über Start
                if (position[player] > 27) {
                        money[player] += 2;
                        position[player] = position[player] % 28;
                }
               
                // nochmals ziehen
                if ((position[player] == 3) || (position[player] == 11) || (position[player] == 17) || (position[player] == 25)) {
                        move(player);
                }
                // 2$ bekommen
                else if ((position[player] == 4) || (position[player] == 18)) {
                        money[player] += 2;
                }
                // 2$ bezahlen
                else if ((position[player] == 7) || (position[player] == 21)) {
                        money[player] -= 2;
                }
                // Jackpot einziehen
                else if (position[player] == 14) {
                        money[player] += jackpot;
                        jackpot = 0;
                }
                // McDonald's-Gefängnis
                else if (position[player] == 2) {
                        money[player] -= 3;
                        jackpot += 3;
                        position[player] = 8;
                }
                // Straße kaufen / Miete zahlen
                else {
                        int street;
                        int house;
                       
                        if ((position[player] == 1) || (position[player] == 5) || (position[player] == 9) ||
                                        (position[player] == 12) ||(position[player] == 15) || (position[player] == 19) ||
                                        (position[player] == 23) || (position[player] == 26))
                                house = 0;
                        else
                                house = 1;
                       
                        if (position[player] < 3)
                                street = 0;
                        else if (position[player] < 7)
                                street = 1;
                        else if (position[player] < 11)
                                street = 2;
                        else if (position[player] < 14)
                                street = 3;
                        else if (position[player] < 17)
                                street = 4;
                        else if (position[player] < 21)
                                street = 5;
                        else if (position[player] < 25)
                                street = 6;
                        else
                                street = 7;
                       
                        if (streets[street][house] < 0) {
                                money[player] -= rent[street];
                                streets[street][house] = player;
                        }
                        else if (streets[street][house] != player) {
                                if (streets[street][0] != streets[street][1]) {
                                        money[player] -= rent[street];
                                        money[streets[street][house]] += rent[street];
                                }
                                else {
                                        money[player] -= 2*rent[street];
                                        money[streets[street][house]] += 2*rent[street];
                                }
                        }
                }
               
                if (money[player] < 0)
                        gameOver = true;
               
                if (money[player] > 100)
                        gameOver = true;
        }
       
        public static void main(String[] args) {
               
                int numPlayers = 4;  // Anzahl der Spieler (1 bis 4)
                int numRuns = 1000000;  // Anzahl der simulierten Spiele
               
                McMonopolyJunior monopoly = new McMonopolyJunior();
                int[] wins = new int[numPlayers];
                int draws = 0;
               
                for (int i = 0; i < numRuns; i++) {
                        int winner = monopoly.simulate(numPlayers);
                        if (winner >= 0)
                                wins[winner]++;
                        else
                                draws++;                       
                }
               
                System.out.println("Chancenverteilung:");
                for (int i = 0; i < numPlayers; i++) {
                        System.out.println(" Spieler "+(i+1)+": "+(wins[i] * 100.0 / numRuns)+"%");
                }
                System.out.println(" Unentschieden: "+(draws * 100.0 / numRuns)+"%");
        }

}
AttachmentSize
Image icon monopoly_junior.jpg60.17 KB