This time maybe a bit longer thread, and I'd like to thank anyone in advance who takes time to read and spent some time for typing a reply.
For a long time I always wanted to implement the well known cardboard game of Monopoly in Java, based on an original one I have laying around here (oh boy, this really helps, as you can find almost any information - except the chance and community cards - seems like there nowhere listed anywhere on teh internetz - same for "official" rules). I've tried to start some times in the past - but never got more than a few lines down.
As for the new year - I now want to finaly get it done.
So, I looked up Monopoly at Wikipedia - wich referenced to the page about cardboard games - and starting here there's a really neat bit I really like and wich I'd like to base my game on:
A board game is a tabletop game that involves counters or pieces moved or placed on a pre-marked surface or "board", according to a set of rules.
As I'm really into this whole object orientend thing and like abstraction - I want to start as follows:
I know the "game" I like to implement is a board game - based on a cicrcle wich is played by 2+ players on a round-by-round style with possible interactions - according to some specific rules. So I start with the basis - the board. Looking at the board we can note down some important specs:
- the board is a square with overall 40 fields - layed out as 4 corner tiles - one in each corner - and placed 9 tiles in between on each side
- there some different types of fields: buyable properties (wich divide into properties with houses and those without (the two supply facilities and the 4 railroad stations)) and special actions (community chest, chance, taxes, corners (go, jail, free parking, go-to-jail))
- it is played with 2 - 8 players (each player has a unique toke)
- for the buyable properties with spaces for buildings apply some rules for those buildings (how, when, how many)
- the overall ruleset about the game itself
So to get started, I came up with this abstract description of the board wich now needs to be implemented in a Java class. As said - I really like abstraction - so in the board-class I would ignore the facts about different types of fields - the board just have fields. Also, for the board-class it doesn't matter in wich order the fields are or that they form a circle - that's up for the graphical classes and the logic-class responseable for player movement. This leads me to the question: as there is no logical relationship between the board and the fields in terms of Java-classes wich has to know each other - is it useful at all to implement a relationship here?
Maybe I can find an awnser when I try to think about: What kind of information the fields hold and do I access them? The fields themselves only have to know its type, and, if there buyable, if they're bought by a player, also, if they have room for houses, how many are on them.
On the other hand - does a field have to know if it's owned by a player - or is it better if players know what properties they own? I would try to awnser it this way: Each round a player has to roll the dice - wich let them land on a field. To decide what happens when a player lands on a field it needs to know its state and all what's needed for it.
So let me start on another side: I will have a "session"-class - the main object wich represents the overall gaming session itself - just like if you get together with some friends to play round of Monopoly. So this class knows the overall state of the game and of all pieces it is made of, i.e. wich player is currently the active one, in wich state a player is (so it can be checked what actions a player can do at any time) and wich actions a player can do on a field he stands on. So, one could think about: First step a player has to do is to roll the dice. This is only true with the exception of one field: the jail. Wich leads to this flow-chart:
1) check on wich field the player is currently on
- 1a) if the player is currently not on the field "jail" skip the following and proceed at step 1b
-- 1aa) the player is just on the "just visit" part of the "jail"-field - skip the following and proceed at step 1b
-- 1ab) check if the player has at least one of the two available "get out of jail"-cards
--- 1aba) the player doesn't have any card - skip the following and proceed at step 1ac
--- 1abba) the player have at least one of the cards and decide to use one - so he will get out for free - proceed at step 1b
--- 1abbb) the player have at least one of the cards, but decide to don't use one - player have to pay
-- 1ac) player has to roll the dice
--- 1aca) if the player rolls doublets (both dice show same number) the player gets out of jail for free and moves the amount of fields the player rolled > step 2
--- 1acb) the player doesn't hit a doublets
---- 1acba) if it's the first or second try nothing else happens - the player can still decide to trade - otherwise turn ends and next player get to move
---- 1acbb) if it's the thrid try, the player didn't used a card and didn't hit a doublets - the player gets out of jail buy paying a fee and moves the amount of fields > step 2
- 1b) if the player is on any other field than "jail" - according to rules the first thing a player has to do is roll the dice and advance the amount of fields
2) check type of field
- 2a) its a corner field
-- 2aa) go - if custom rule is enabeld - player gets double of round fee - otherwise just normal amount > turn ends
-- 2ab) jail - just visit - nothing happens - turn ends
-- 2ac) free parking - action depends on active rule - nothing, fixed amount, taxes, custom rule
-- 2ad) go to jail - player is move back to jail, flag "player in jail" is triggered and turn ends without able to trade
- 2b) taxes - player has to pay taxes - depend on rule if payed to bank or to free parking
- 2c) chance / community chest - action noted on card
- 2d) buyable property
-- 2da) owned by player - player can decide to manage buildings
-- 2db) owned by another player - player has to pay
--- 2dba) special case: if a player doesn't have enough net-worth money (including selling houses and taking mortgages) he may is allowed to trade or ask bank for money - but this is uncommon - usually a player is out and declared bankrouptcy
-- 2dc) not owned at all
--- 2dca) player can decide to buy - if he has enough money to do so
--- 2dcb) player decide to not to buy - or doesn't have money to do so - property is sold by auction (as of official rules: a not owned property has to be sold by auction - although player can agree upon to simple "nothing happens -> next player" - wich, according to google, seems common)
3) after above steps done the active player can decide to start a trade with another player (except for "go to fail" - then turn ends directly) - it's common that a player can manage buildings - although official rules say a player may only manage buildings if it stays on a field of the color group
4) all actions a player is allowed to do - and anything that has to be done mandatory is done - the current turn ends and the next player gets the dice
Looks kind of confusing - and it may contain errors - but this is simply how monopoly round plays. Based on these actions wich has to an can happen at each turn - the session object needs to now the players - and somehow has to connect on wich field the player is on - to decide what to do and to wich field a player moves next after rolling the dice. As on the gui-classes the tokens has to somehow get rendered - there needs to be a connection to tell wich player is on it. Drawing require information about status - so it needs to be kept in sync with the session. I'm not yet sure about how I will implement it.
Also - as I want to implement this project as MVP - it will be based on events. So may following flow helps to awnser last question: A player is selected as active - starts by rolling the dice - wich in its turn triggers the next events (checking field, moving, actions) and finally updates the new game status. So this would be:
- Session.checkField() -> jail-logic
- Session.fieldAction() -> cards, buy, buildings
- Session.update() -> sends out current new status to all player and instances to sync all objects
I would think its maybe a good idea to implement to field-updates - first in the movePlayer() - and second at last call on session-update. So the fields know wich players are on them - the players also know on wich fields they are - wich needs to be kept in sync - and thier internal status (owned, if so by wich player, buildings). I'm still a bit worried about the facilities as the logic has to check when a player lands on one of them if the other is owned at all and if so if its the same or an other player.
So, as I now already needed over 1 hour to right this post - I will think about some sample implementations and how to link the different pieces.
So long ...
sounds like a very interesting project, although a far from easy one. Couple of years ago I too made a start with it, it was about Project Euler exercise 84, and though I solved that question, I did not go any further with the game. Way too much work.
Enjoy, and keep us informed!
First I looked about what the session needs to know during the game, how it interacts with other objects, and how to create one.
To get a possible constructor I thought about: What does a Session-object need to know to? So we have the players, a ruleset, the fields/gameboard (I'm still not sure about that) and the internal current status. As the last two gets reset and newly created for each new session a constructor needs a PlayerList and a RuleSet. So we get this:
As for the PlayerList I've decided to write some own code based on an internal java.util.Deque. Some now may ask: Why? Well, a Deque provides an easy FIFO-Buffer while maintaining the initial order. So, even there will be a possible shuffle by rules to determine wich player's first and what's the order - if it's initialy set can easy to some like this:
Why to add some custom code? Well, I plan to add optional rules to set the order and wich player starts. This may will be:
- lobby leader goes always first - this means, it doesn't matter in wich order the list is set, the leader of the lobby (the player wich set it up) will always go first
- random - explains it self - list gets shuffled at on player is chosen as random
- as joined - some more code needed in the lobby code, means the players will go in the order the initialy joined the lobby
- by dice - each player rolls the dice - order is set by highest or lowest - if two player roll the same the will have to roll again aganst eachother
- set - the lobby-leader sets an order before session starts
As far as it makes sense / is possible I want to make each rule combineable with each other - for example a leader could set random order but a set player as the first one - or a fixed order like "as joined" or "set by leader" and players still roll the dice just to select the first player. Sure - this sounds error prone in the first place - but I think: Monopoly is mostly played with custom rules - why not offer this freedom for the player-list also? Bugs get thrown out later.
So I will need a data structure wich provides a simple FIFO-buffer, but is also flexiable enough for mixing up random stuff. The docs says that a Deque doesn't provide a way to access by index - but I think that all those fancy streams-api added with v9 somehow provide an easy way to implement these different options. If not I can still go the old way > Iterator > Array > some shuffeling > and with a for-loop back into a new Deque. I think as heavy array-copying may be expensive - I may will go with LinkedList - may someone can help here.
So, even if it's called a "loop" - the game-loop still needs an entry-point wich can somehow set to the applied ruleset. As I can go with the above code to step through the Deque to set the starting player (if needed), I may alter may mentioned loop from last post to move the "nextPlayer" call to the end. This will simplyfy the start of the loop as I can just run through the list - and when the desired player is found - just stop right there - instead of add fancy magic to "step back once" (wich sure is easy possible by getting last element and re-adding it in the first place, but this step can be saved).
This may lead to the following:
So, you may start to see - this is all heavy pseudo-code - there's no real lines yet.
Why this "waitForTrade"? Well, as mentioned in the last post, each player still has the ability to initiate a trade (in real world may at any time - as the computer one have to follow some rules - we set it as "at the end of turn"). So, after any mandatory action is done, the player will get sent an event like "hey, you, you may trade now within the next 30sec" and simply will call a .wait() on the thread. To escape this there 3 actions: a player does not trade calls "end turn" -> notify(), a player will start a trade -> notify(), the timeout is triggered -> interrupt(). This is just because this is planed to run over network connections.
Sure, this is still in the planing phase - and many implementation details may depent on some tests I will have to run, like how to sync the timeout (what happens when a player hits the trade button the split-second between the "it's over"-timeout is triggered on server side but the event to inform the client is still on its way?), what order of actions fits best the real game, how to set-up the playerlist and ruleset in the firstplace (or: how to design the "lobby"). As some of you mentioned: this will be a big, not so easy project for something simple as a boardgame (ok, Monopoly itself isn't an easy boardgame - but it's still "just" a boardgame - only with some complex rules).
I'll keep you up through the week as I get some steps along.
So long ... Matt out.
Some of the points to think. I ignore implementation details what you started exposing, but rather thinking more about the design.
1. First, I wouldn't call the very first class you showed us a Session. That may mislead and make think about the HTTP sessions. Think maybe there is some better name which can reveal its intention. Maybe GameSession? GameRound? Game?
2. Session class. It has constructor PlayerList and RuleSet. First thought which came to my mind was, does the RuleSet changes per each session or just players (more likely)? Not saying it is incorrect, but that was my first thought.
3. You have Board and Field class as separate entities coupled with Session class. Does that mean that Board is a general board on which you could possibly also play chess, meaning you'd just set different fields? Maybe field better would be as constructor injection to board class, and game session would have only the board? Does session class really need to know about the fields individually? Maybe better to construct board fully (with fields) and then give it to game session?
These are just for you to think, might some ideas will help improve some areas. I'll step in later on more. Interesting project though.
thank you for your reply - it really made me thinking about some decisions. May let me awnser your points in order:
to your 1)
First of: I agree with you, "Session" doesn't really fit - GameRound seems to fit better.
I have to explain my already made up plan a bit more: When a user (a "Player") starts my code (I refer to as "Game") after connection one gets shown available games to join or spectate - this overview I call "main hub" - and the games listet are joinable "Lobbies" (or "Lobby" for one). A Lobby is kind of a "preparation room" players join together, agree upon rules and when all ready to play the game starts - that's how I come up with Session.
As it made me rethink about these names - not only I changed it to GameRound, but also PlayerList to just Players and Rule(s)Set to just Rules - just fits it better.
to your 2)
Refering to the Lobbies in 1, well, yea, each GameRound is supposed to have its own Rules. These rules are the "house rules" - that small differences each game is unlike others, like the amount of cash at start, if you get double money when you hit GO spot on, if you always pay taxes in fixed amount or always 10%, if there is a limit on houses, what happens at Free Parking - and so on. Sure, one can decide to stick to official rules - but may choose to change some. So your thought was correct.
to your 3)
I'm still unsure about the relationship between players, fields, the board itself, the session and how they all play together. I've just put it in as a placeholder. Do I need it? Not sure yet. The most think I'm still unsure about is the relation between the Player class and the Field class - wich one does need to know wich? Do they need to know each other at all? Can this relation been build externaly like in an external Board class? There're many placeholders and questions still flowin around in my head.
I wanted to get some line down and start with the rules - as they only consists of ints, booleans and maybe one or two enums - so the Rules itself doesn't depend on others. But your post somewhat throw me around the rethink about some thinks. So maybe let me just list the rules I already came up with - maybe some can changed, maybe split into others or taken togheter, may some more can be added - we'll see.
- amount of cash at start - int
- collect double on hit go - boolean
- how to pay taxes - enum [player choose, always fixed amount, always percentage]
- fixed amount of taxes - int
- percentage of taxes - int
- free parking action - enum [none, fixed amount, taxes, bank (this means also what's noted on cards like "doctors fee" or the famous "repair your properties" card), maybe some other rule ...]
- double amount of community chest or chance cards (payments players have to make to bank or to other players as well as payments a player receive from bank and others) - boolean
- house limit - int (-1 means no limit)
- hotel limit - int (-1 means no limit)
- buy on first round allowed - boolean
- enforce rolling dice as first action - boolean (except jail - wich player can decide to use card instant without rolling first)
- enforce auctioning - boolean
- on bankruptcy: go properties back to bank or player to wich is lost - enum [bank, player]
- how is decided wich player goes first - enum [set value, random, rolling dice]
- when above is set to specific value: reference to player wich goes first - object(Player)
- is a player allowed to trady when in jail
- additional fee/taxes when re-buy mortgaged properties in percentage of base value - int (0 means no additional fee/taxes)
So you see there's a huge list how a round can differ from others, and these only the "common ones" wich are also noted as "subject to agreed upon by players" in the official rules.
I think the easiest way to implement these rules is just following bean-convention: private fields with public getters/setters and constructor init fields to some "default" values.
As an example wich I will also add is a very neat additional rule added by a friend of mine: You just can't "manage" your properties as you like, even official rules only allow it 1) when its your turn 2) only for the property you're currently on (wich means when you're in jail you're not allowed to), but also you're also allowed only a limited amount of actions you can do. So it goes like this: each round you cross GO you earn an additional "action point" (on wich also can be a max set to) wich limits your actions. Each time you upgrade from houses to hotel or downgrade, even when just add or remove a house, or mortgage or re-buy a mortgaged property - you always have to spent such an action point. This means: When you're screwed at need to seel houses or mortgage properties to get enough money to pay a rent - you can only do so if you have enought points. If you don't have enough such points you can't scrap together enough money - and you're out. It spices thinks way up. One round I earned around 15 such points, but couldn't use them cause I kept down below 1k by other players (finaly I got sniped) - but they on the other hand kept landing on "go to jail" or drawing the jail cards - so they didn't completed as many rounds as I did so the didn't got much points - so they luckly couldn't upgrade for a long time (altough they stacked up to 100k+ (yea, german original edition is played each number added an additional 0 - so 100k in german edition is equivalent to 10k in us/uk version)).
Long post - again - apologies to anyone and thanks for reading. Next reply maybe on weekend - at least if I get time to.
Matt Wong wrote:I'm still unsure about the relationship between players, fields, the board itself, the session and how they all play together.
I'll be quick for now.
Some saying that designing close to a real life isn't the right thing to do. That's probably right, but, no one is saying that it does instant harm if you try to think it through. I'm about the Board and the Fields you have in GameRound (ex Session class).
Single Responsibility Principle - I think that's not the bad place to start thinking from when dealing with dillema about the responsibilities. This principle says, that class supposed to have one and only one reason to change.
What that means? Well, exactly what it says, somewhat stupid, isn't. Let's assume board's fields changing from red to blue, and from green to yellow. Does that supposed to affect GameRound class somehow directly? GameRound class's responsibility may remain to define and inform player that it his turn now to move (presumably onto the next field), but what these fields are, not too much to bother GameRound. I think much better would be to construct the fully operating Board with the Fields and pass it onto the GameRound. Similarly as when you order double glazed windows, so they bring stuff ready to put into the place. You don't get glass, then frame, handle, screws for handle, in fact, you don't need to know much what screws are used, you just expecting that they do their job what is needed to do to secure handle. Handle needs to know what screws are used, and if something changes in screws, only the handle needs to worry about that.
So I'd imagine to have something similar to:
So the GameRound class is dependent and interested only about the Board (in this example) as this is where the game takes place on. And leaves the fields stuff to worry for the Board class. And how that relates to SRP (single responsibility principle), well, whenever fields change, they don't affect at all how GameRound class is constructed, you don't need to recompile GameRound class as GameRound takes only the Board. Maybe Board itself tomorrow will have 2 layers of Fields (silly example, but good for emphasizing), which in turn would require to pass to Board(List<Layer1> fields, List<Layer2> fields) (meaning you'd modify Board class, recompile). Now imagine you'd remain with current scenario, you'd still need modify Board class + GameRound class in order to accept Layer1 and Layer2 stuff as all these would be injected through the constructor of GameRound class and then to Board class.
You aren't beginner, so apologies if I expand too much into details. But we have lots of readers here, so the more users (i.e. students) could possibly be on the same page, the better
Liutauras Vilda wrote:You aren't beginner, so apologies if I expand too much into details. But we have lots of readers here, so the more users (i.e. students) could possibly be on the same page, the better
Nah, don't worry - that's a really good post and really helps to think about this project in some new ways I hadn't yet thought of, for instance to look at it from a developers point of view instead of trying to adapt the real life scenario and glue into code. I was aware of SRP before - and what it mean in general - but didn't knew how helpful it can be to get a different look on specific problems to solve.
So far we can extend the example - if the GameRound is responsible to link the Players to the GameBoard, how could a player interact with a field? As noted above - when a new turn starts for a player there some actions happen (check jail, roll dice, advance, perform actions, trade). The check for jail sounds easy (as the status if a player is in jail, and if so, for how many rounds and if a player owns a "get out of jail"-card should all be properties of the Player class), but after a player rolled the dice (wich of course to prevent "getting out of sync" (in lack of a better term to say "prevent cheating") is done on server side) this somehow needs to "get done on the board". So I would consider something like this:
If we go with that - the gameboard has to manage:
1) update the field the player is on (so this may be a property of the Player class) - according to check for passing GO (not sure yet how to implement this one)
2) send out this update to connected game clients (wich infact gets managed by other classes wich just get called by the gameboard class)
3) check what action has to happen after movement
But then we're out of this SRP again as the gameboard suddenly again takes care of more than one action.
If we add another line - say
then the field class gets out of SRP as it has to check if the field is already owned by another player and what's is current status (in terms of buldings), somehow has to get back to the gameround object to access the rules object (example to check for the rule for taxes field) wich would lead to some ugly line like this:
wich then may could offer the player to choose from two options, then, depending on this decision, it could go furhter on like
wich then finaly further may lead to calculation of networth - and then - depending on the "free parking"-rule - decide where this money is payed to.
So, you see, I really have trouble to stick to this whole SRP thing and may need help to clean this up.
Unfortunately, I'm now up for a whole long 10-day shift, around 10h a day, so it may take some time until my next response if I don't find a spare minute in between.
So long for now - Matt out.
Matt Wong wrote:The check for jail sounds easy (as the status if a player is in jail, and if so, for how many rounds and if a player owns a "get out of jail"-card should all be properties of the Player class)
Not necessarily. Let’s think about other possibilities what can go wrong. So new fields tomorrow appeared, in fact, jail is no longer there. So we end up with low cohesion Player class, as class gets stuffed with methods which are no longer needed, or needed only for an unknown period of time. But that probably isn't the worry in your case, the worry I'd say is, that Player class would need to have properties for each card, if not for each, then at least for some, then question would be why not for each and just for some, that way Player class could get confusing, player.isInJail(); player.isInHotel(); player.isAbleToMove(); more and more and more... What we might want to achieve, that player would be independent from fields and their underlying logic changes.
What if there were some mechanism to check that independently from player class.
I am nearly sleeping, but wanted to drop this thought for you to think for some time. There are various ways, which might worth to consider or at least to discover.
The Not-so-Good: You're starting out in the bushes. Too many details. You will soon get lost in them and quickly find yourself bogged down by complexity. STOP. Take that literally and as an acronym for what you should do when you get lost in the woods:
S - Stay calm. Relax, breath.
T - Think. When you start out, resist the urge to jump right into the nitty-gritty details that you've already waded yourself into. Think high-level first.
O - Observe. Play the game with a friend or two. Carefully observe what happens as you play the game. How would each action be represented in the computer game? What interactions with the software would a user have that would closely replicate the experience they have when playing the game in real life?
P - Plan. Plan out your moves before diving in. Visualize the end result instead of trying to think of every single little implementation detail. When you take care of the big thing, the little things usually fall in line nicely with them. When you start with the little things, they quickly pile up and leave very little room to fit the big things in later. Again, start with the big things.
I suggest you start by thinking about how the user(s) interact with the computer to play the game. Think about things like this first:
How does this game get played on the computer? Is it one person against the computer? Do multiple people take turns at the input device? What is the input device, a mouse? A keyboard? An XBox Kinect?
How are you going to move pieces around the board? Will the player press a key to throw some virtual dice? How are you going to track where each player is on the board? How will you track whose turn it is to move?
How are you going to keep track of who owns what? How do you get the computer to know when the game has been won?
Again, when you think about these things, resist the urge to think about classes, methods, fields, etc. Don't go into implementation before you have a good sense of the general direction you want to go. That is, don't start hacking away at the underbrush without even getting your bearings and setting your sights in the general direction of where you want to go.
Programming is largely a heuristic process. That is, you do a lot of experimentation, a lot of trial and error. Tests are your way of trying things out. They state your hypotheses of how your software is expected to work. They will fail first, of course, because you haven't written any software that works. But with a failing test, you now have a goal to work towards. That failing test focuses your efforts into getting this one aspect of the software you want to produce to work correctly. From one small thing that works, you add on another small thing that works. Again, starting with a test that fails to set your sights on the new bit of behavior you want to add.
This process is called Test-Driven Development. I have found it to be a very effective way to work. I recommend you try it.
Of course, I wouldn't write these all at once. I'd write them one at a time, implementing some piece of functionality and only as much of the design as is needed to support that piece of functionality. I'd keep implementing little by little, always running my tests so I know if something is broken, in which case I should go and fix it first, or if I can go ahead and add another little bit of functionality, starting with another small test.
1. define a "board space" class with fields for all pieces of information that exist on each space on the game board.
2. define a "board" class as an array or list of "board space" elements. I'd assign each board space a numeric index
3. define a "player" class with fields for all required data ( such as cash available, properties owned, current board position index)
4. the main function would call the board class constructer which would create the array and call the space class to initiate all the spaces on the standard board
5. the main function would then get input from the user and call the player constructor.
6. play would initiate and rotate with each player called to "roll" the dice and have a graphic presented illustrating their new board position, and a list of options that they can choose to perform.
What I'm not presently sure of is whether I would choose to show an actual game board or a small graphic of each space with houses/hotels as they are populated. It's a user feedback choice.
Also not sure how I would implement the function where a player whon forgets to demand rent as a player lands on their property. My understanding is if someone lands on my property and I don't say "rent" before the next player picks up the dice, I loose that rent payment. We'v enever played that way, but I believe that's how the rules read.
Sadly I don't have time to awnser as my other posts - as I simple didn't had enough time to think about your posts - so I'll try to make it short:
Once again, I'd like to thank anyone who took the time to read, also the ones who took even more time to reply - and to make me look at this project not just from one other side - but a few - to discover lot of new possibilities.
I already made some changes to once pretty stiff but now really loose basic consept in my mind. I've already tried to re-arange things - threw it away and came up with also another solutions - while still tryin to think about and figure more ... one word: amazing.
To tighten this up a bit: Lot of posts made me think of a, for me really strange but productive, way to not really start all other again, but to let other points of view lighten me up.
Just for a quick example: somewhere I've wrote: "first: check if player is in jail", uhm - yea, about that - I re-thought about this whole "jail-magic"-thingy and came up with: "Wait a second - I always have to keep track of the dice if the current player rolled a double, and if so, how many times in a row?". So, from my original "nah, just take the sum of both dice into what ever type might fit" I already move to "there's a lot more just about the dice than I thought of until now". There many of such cases where I know think: "Just wait a second - this crap of b-sh*t just doesn't make sense at all! - I have to aproach it from a different way ...".
Just a quick side-note on test-driven dev: I support that, as in the past I've seen so much goin wrong with "modders" of minecraft - wich fail to just follow Java Conventions (ok, don't blame them - this fault comes back to 1) Notch who screwed up the original 2) the "forge"-team wich screwed it up even more and worse) - and just by starting up the logger throws so many RuntimeException - hiding away checked Exception - one who can read and understand the logs and StackTrace just can think: "Ok little chumps - you got this all wrong pretty hard.".
But: I'm just not used to this kind of development. To admit: I'm the one kind of "hobby dev" wich just uses an editor and the terminal to write his codes (at least after many years I've moved from just notepad to notepad2 (I like it more than notepad++) wich at least adds syntax-highlightning - and yes: I'm using vim on teh unix). I'm not afraid of learning how to use IDEs, version control repos and all that stuff - I'm just not used to it - and starting to learn this now maybe a good idea - but would throw me back half a year on this project - wich I don't want like to waste. - Hey, I can still refactor it later on, can't I?
Also I've wrapped my head around this "board and fields"-thing and - although I really like abstraction (in the past I've over-complicated some easy examples with a full over blown interface-abstract-impl-factory thing) - I, at least until now, still can't make it up so that the board itself could be a "regular" interface without any specifics like jail and free parking, but I also aware that such funcationality can be made up through "external consturcts" cleverly hidden through interfaces
[spoiler] - is thier some code to "hide" some lines? know [spoiler]-tag from BB ...
don't ask me or nail me down on it, but on some of my not-so-well-known german small-community boards I've read some clever "hidden through abstraction"-code by one of our trolls - wich, to be honest to him (I really don't know if "it" is a he or she) sometimes has his really bright moments to shine, wrote some beautiful abstract code wich opened up to one of our "abstract-interface-magicians" the possibility to write some few lines wich, if you know java8 and its tweaks, allows you to write some 3-liners wich just fit in basicly everywhere[/spoiler]
and thier factory-style implementations.
Don't get me wrong - this project will only subject specific on the game of Monopoly and its own unique styles of gameplay - I don't want to make up a "general card-board game -engine-", so at least some spaghetti code would/could/should be allowed to get this runnig without over-complicating stuff unnecessarily.
I know one who have years of experience to build such things may can get away way more cleaner - but as I'm already into Java from about the age of 12 (I'm almost 27 now) and the only one project I finally got done was a very simple and ugly prototype-like implementation of battle ships - this is "the one project" I really like finally to get into the world of "productive developing" some code - no matter what it is, whats the plan/idea behind it is and how it will come out in the end.
If this long "I've already got this done 5 years ago"-"project" finally gets to a stage where it is at least "useable", let alone the term "playable". this would be the biggest achievement in my personal dev-carrer until now - no matter how bad the code will be nor how many bugs it will have - I really want to get this done - not only for myself but also as for a service I can offer to anyone in the world wide net: "You want to play a round of Monopoly?", as, to be honest, to find free online games or cheap buyable ones is still pretty hard. And pay 15 bucks on steam for table-top-sim to play Monopoly? There just has to be another way ...
As for all other replies I didnt awnsered - be sure I've read them - and sill will - but I'm out for about a week now only get some minutes to check for replies - await my next reply around next weekend.
Additional for any mods: If the way I'm taking this thread doesn't fit the forum rules - or if something else is not the way this "board" should be used - please inform me/us - and we will alter the way this "project" will go.
I've just started here as this seems to be an international place to finally get my first real project finally to be done (wich, no offense to my german board, couldn't happen at a smaller community). May there's a special "blog like" are where this may fit better than in the regular forums - any advice is highly appreciated as I want to comply with the overall rules as much as possible.
Thank you all again, in retrospect and in advance, to get this project done.
For those who want to think a dozen steps ahead: This project is subject to also imply some sort of "AI" - so, what I'm currently refering to as "the player" (or better: the Player class) will be an interface in the end wich either is set to an implementation of a real player (wich means any action is send over network and is displayed and controlled to and by a game client controlled by a real person) or just a "bot" (an AI if you will wich makes decisions based upon maths over some dozen rules) run on the server side. Therefore I want to already encourage any game-AI-dev to prepare up for an implementation - those wich will get into the "final" realease of course will get credited (either by pseudo nick or real full name - as you wish).
There're just a few, really "open", possibilities for this game, to play it online - that's the real reason I want to get it done: not just to play it with my friends on a real board but also in the cyberspace. If you think the same way - please join up this crew and be part of it on its journey to its endeavour to achieve its goal.
So long, until next weekend (don't expect any reply from me as I'm away for the next few days), Matt out.
I re-thought about the Jail logic. Why not decouple it into its own class?
So when a player is advanced to jail (third double in a row, go to jail field, go to jail card), the board will call an incacerate method on the jail field - wich then delegates the incarceration to the jail-logic class wich keeps track of players incarcerated and for how many rounds. So it should be easier to check when a new turn starts for a player. Something like jailInstance.isIncacerated(currentPlayer) and if so maybe some like jailInstance.rounds(currentPlayer) to check for how many rounds. This way the actions can be split of into another flow handling the jail mechanics.
Some in this way also for the dice: To keep track how many doubles rolled in a row and re-setting it if the dice show different numbers. Otherwise, if it hits the limit, trigger the into-jail event.
Sure, maybe it's possible to design interfaces to abstract the board, the fields, the dice - link some overall relationship in - and specialize depended on the type of board played (like a board w/o jail, a game with 3 dice, maybe some "extended" or "multi-layer" types). It's hard to think abstract high-level enough when talking about implementing a game with a set of rules - but yet different types (can't remember about this two-layer style to find it quick on the net - but the extended version is called "mega monopoly", and the small one is the junior one - wich, iirc, doesn't have a jail - not sure tho). I also think it should be my goal to implement the standard version first - then, after upping my skills, maybe refactor to add such additions.
I also thought about the GUI and wich way to go. As I'm pretty good in swing I think this will be my first choice. Sure, when keeping it strictly split apart and develope a good interface - it should be easy to replace it with javafx (although this would require some re-code cause javafx applications are different from swing ones).
So long, if I'm up to some other major news I'll post again.
Yeah, a jail class would probably be an excellent exercise in good practices. At a minimum, it could be a Container (for the "convict") and an Observer (for the jailing events, including watching the dice and cards).
I'm not clear on whether you expect to have the software merely referee the game or to act as a player. Monopoly is probably harder to play-by-computer than chess, since there's both chance and a certain amount of bluff, aided and abetted by calculation of odds and payoffs for the different properties. You have to make decisions to buy and sell properties, and, if memory serves, even auction them.
A good preliminary to Monopoly would probably be to model pachesi. It, too is a board-circling game with chance and decision making. And as a bonus, not commercially owned, should you decide to make it public. I think there are actually some computer versions of it around, although I'm pretty sure none in Java.
On SEP 7 2017 Ubisoft released Monopoly Plus on steam - and I have to admit: yea, even someone already created it in "table top simulator" - it's kinda neat and also supports online multiplayer (from what I've seen you YT).
I'm aware about possible legal issues when opening this to the public - so my guess is - unless I advertise it (wich I'm clearly not allowed to due to missing marketing rights wich is still hold by Hasbro) it wont get a big audience, let alone the chance to even have it as a public download - wich I also could get sued for. But that's stuff for another topic for another time. The goal is very simple: a monopoly game wich I can play over the net with my friends written by myself in Java. I doesn't even have to have an AI - although would be nice to - sometimes back in the days I already dreamed about a "get your AI in"-challenge ...
anyway - back to topic
As I still have not that much time, and currently working on some other real-life stuff, my next goal is to get up a simple "tech demo" - just consisting of a board with fields and only the logic to advance the players around it in order. If I managed to get it to this stage - evolving it to the full game shouldn't be that hard as it's just extending something already running. Maybe I can get some time at sunday to get some lines down.
About pachesi - after I searched what this means and is (sorry, I'm german native) - yea, sure I know it. The main difference: you would only follow a more ore less straight line from a fix start to a fix finish - you don't go around the same board more than once (it's not even a complete circle as you never get on any field again). Just as an exercise? Well, maybe worth it, just to get into the whole "multiple players" thing - I'll see how it could help here ...
Funny, pachesi originated closer to where you are than to where I am. But I re-read the rules a year or so ago and they seemed a lot more complex than what I remembered.
Pachesi, like chess, is an ancient game and was popular at caravanserais. I've seen boards that were simply cross-shaped bits of cloth that folded up neatly for travel. Instead of dice, it was common to toss cowrie shells.
But I'm pretty sure that actually you had to go around and around the board until you landed on the place that led into your home stretch.