Menu
News
All News
Dungeons & Dragons
Level Up: Advanced 5th Edition
Pathfinder
Starfinder
Warhammer
2d20 System
Year Zero Engine
Industry News
Reviews
Dragon Reflections
White Dwarf Reflections
Columns
Weekly Digests
Weekly News Digest
Freebies, Sales & Bundles
RPG Print News
RPG Crowdfunding News
Game Content
ENterplanetary DimENsions
Mythological Figures
Opinion
Worlds of Design
Peregrine's Nest
RPG Evolution
Other Columns
From the Freelancing Frontline
Monster ENcyclopedia
WotC/TSR Alumni Look Back
4 Hours w/RSD (Ryan Dancey)
The Road to 3E (Jonathan Tweet)
Greenwood's Realms (Ed Greenwood)
Drawmij's TSR (Jim Ward)
Community
Forums & Topics
Forum List
Latest Posts
Forum list
*Dungeons & Dragons
Level Up: Advanced 5th Edition
D&D Older Editions
*TTRPGs General
*Pathfinder & Starfinder
EN Publishing
*Geek Talk & Media
Search forums
Chat/Discord
Resources
Wiki
Pages
Latest activity
Media
New media
New comments
Search media
Downloads
Latest reviews
Search resources
EN Publishing
Store
EN5ider
Adventures in ZEITGEIST
Awfully Cheerful Engine
What's OLD is NEW
Judge Dredd & The Worlds Of 2000AD
War of the Burning Sky
Level Up: Advanced 5E
Events & Releases
Upcoming Events
Private Events
Featured Events
Socials!
EN Publishing
Twitter
BlueSky
Facebook
Instagram
EN World
BlueSky
YouTube
Facebook
Twitter
Twitch
Podcast
Features
Top 5 RPGs Compiled Charts 2004-Present
Adventure Game Industry Market Research Summary (RPGs) V1.0
Ryan Dancey: Acquiring TSR
Q&A With Gary Gygax
D&D Rules FAQs
TSR, WotC, & Paizo: A Comparative History
D&D Pronunciation Guide
Million Dollar TTRPG Kickstarters
Tabletop RPG Podcast Hall of Fame
Eric Noah's Unofficial D&D 3rd Edition News
D&D in the Mainstream
D&D & RPG History
About Morrus
Log in
Register
What's new
Search
Search
Search titles only
By:
Forums & Topics
Forum List
Latest Posts
Forum list
*Dungeons & Dragons
Level Up: Advanced 5th Edition
D&D Older Editions
*TTRPGs General
*Pathfinder & Starfinder
EN Publishing
*Geek Talk & Media
Search forums
Chat/Discord
Menu
Log in
Register
Install the app
Install
Community
General Tabletop Discussion
*Geek Talk & Media
d20 die roll string parser and roller in C#
JavaScript is disabled. For a better experience, please enable JavaScript in your browser before proceeding.
You are using an out of date browser. It may not display this or other websites correctly.
You should upgrade or use an
alternative browser
.
Reply to thread
Message
<blockquote data-quote="azhrei_fje" data-source="post: 4105261" data-attributes="member: 12966"><p>Yeah, perhaps I came across that way too. My apologies. <img src="https://cdn.jsdelivr.net/joypixels/assets/8.0/png/unicode/64/1f641.png" class="smilie smilie--emoji" loading="lazy" width="64" height="64" alt=":(" title="Frown :(" data-smilie="3"data-shortname=":(" /></p><p></p><p>I used to write code. Lots of it. (But you know the saying, "Those who can't do, teach." <img src="https://cdn.jsdelivr.net/joypixels/assets/8.0/png/unicode/64/1f642.png" class="smilie smilie--emoji" loading="lazy" width="64" height="64" alt=":)" title="Smile :)" data-smilie="1"data-shortname=":)" />)</p><p></p><p>Anyway, my experience over the last 30 years (ouch! THAT LONG?!) has been that if I don't write something generic in the beginning, I end up redesigning/reimplementing it again later. Usually this happens when I'm writing code for myself, because I think, "Well, I'm only ever going to use this code in this application. Why bother to do a grand design when the code won't be reused anywhere else?" And of course, you know what usually happens... <img src="https://cdn.jsdelivr.net/joypixels/assets/8.0/png/unicode/64/1f609.png" class="smilie smilie--emoji" loading="lazy" width="64" height="64" alt=";)" title="Wink ;)" data-smilie="2"data-shortname=";)" /></p><p></p><p>In any case, the Observer pattern is supposed to separate an object that generates events from the object that interprets those events. This is going to get long-winded, but I'll try to get through it all anyway... <img src="https://cdn.jsdelivr.net/joypixels/assets/8.0/png/unicode/64/1f642.png" class="smilie smilie--emoji" loading="lazy" width="64" height="64" alt=":)" title="Smile :)" data-smilie="1"data-shortname=":)" /></p><p></p><p>Imagine a hierarchy of classes such as DieRoller that takes a dice string to parse and generates a list of random numbers. How should those numbers be displayed? They could be displayed on a terminal, drawn on the screen as graphics elements, flashed on LEDs hooked up to the parallel port, spoken aloud, and so on. Because the data might be used in many different ways, the specific implementation should not be in the DieRoller class.</p><p></p><p>Instead, a new class called DieObserver is created. (This would actually be an interface, but I'm simplifying.) The DieObserver would implement a callback, such as <strong>dieRollUpdated(DieRoller dr)</strong>. When the DieRoller class is told to roll its dice, each random number generated causes DieRoller to invoke the <strong>dieRollUpdated()</strong> method of a DieObserver that was passed in at the time the DieRoller was created. The DieObserver object can now query back to the original DieRoller using the passed in parameter and ask it what the latest roll was. (The query back to DieRoller is done to avoid hard-coding a data type into the parameter list of the <strong>dieRollUpdated</strong> method, and hence, makes the DieObserver more generic and reusable. And, it many cases allows a single DieObserver to be used by multiple DieRollers; not in this example, though.)</p><p></p><p>This allows me to use DieObserver as the top class in a hierarchy of classes: GraphicsDieObserver, LEDDieObserver, TerminalDieObserver, and so on. The main application passes the dice string to be parsed to the DieRoller, and as it generates random numbers it passes them to a particular DieObserver and the DieObserver is responsible for building the result. In your code example, that would be StringDieObserver -- it would simply concatenate all of the values together into a string.</p><p></p><p>Because the DieObserver was passed to the DieRoller at instantiation time, the main application can have a reference to the DieObserver cached and </p><p>later call a method of the DieObserver to retrieve the string.</p><p></p><p>Empirical data suggests that object-oriented code has roughly 15%-20% more lines of code than a procedural program (Martin Fowler, <em>UML Distilled, 2nd Edition</em>). This means that it takes longer to get from the starting point to the end result. But if analysis patterns and design patterns are applied at each step along the way, the resulting code is highly modular and quite easy to reuse in other applications later. This means that the next version of the code can be released sooner, that the readability of the code is improved, and that maintenance is easier.</p><p></p><p><rant></p><p>I read somewhere that, "[...] software doesn't need maintenance. It doesn't require periodic oil changes and its tires don't wear out. Instead, the functionality required of the software changes. Software doesn't need maintenance -- it needs redesign and reimplementation." I like that quote because it pinpoints one of the major problems with software production today: the feeling that the code is such a mess that it needs to be redone from the ground up. Why would that happen? It happens because the A&D steps were skipped or severely limited so that the program did not include the proper design elements. Since the design was not robust enough in the beginning, the patches made later to add functionality instead just obscure the existing functionality! Instead of patching a single class to add functionality, that subsystem of the application should be sent back to the A&D folks so that they can evaluate what the proper design should be to accommodate the change in functionality that is desired and then the code reimplemented.</p><p></rant></p><p></p><p>Concerning the link to the Microsoft web site, I understand the goal behind the question, but I'm not sure I understand whether the question is asking for a design that will accomplish what the OP is asking about or if the OP wants an implementation. The answer provided by the next post mentions the Provider pattern and this seems like a good way to go. If the question was concerning the C# implementation, ie. "How do I implement this in C#?", then I can't help. <img src="https://cdn.jsdelivr.net/joypixels/assets/8.0/png/unicode/64/1f641.png" class="smilie smilie--emoji" loading="lazy" width="64" height="64" alt=":(" title="Frown :(" data-smilie="3"data-shortname=":(" /></p><p></p><p>Again, I apologize again for the long-winded reply. And yes, this probably seems like a lot of work to go through to get from point A to point B. I have found that if I write all of my code as though it were going into a library/framework instead of into a specific application, I end up with generic, reusable classes more often. It is hard to discipline myself, however, when I think that I just want something quick and dirty that works. <img src="https://cdn.jsdelivr.net/joypixels/assets/8.0/png/unicode/64/1f642.png" class="smilie smilie--emoji" loading="lazy" width="64" height="64" alt=":)" title="Smile :)" data-smilie="1"data-shortname=":)" /></p></blockquote><p></p>
[QUOTE="azhrei_fje, post: 4105261, member: 12966"] Yeah, perhaps I came across that way too. My apologies. :( I used to write code. Lots of it. (But you know the saying, "Those who can't do, teach." :)) Anyway, my experience over the last 30 years (ouch! THAT LONG?!) has been that if I don't write something generic in the beginning, I end up redesigning/reimplementing it again later. Usually this happens when I'm writing code for myself, because I think, "Well, I'm only ever going to use this code in this application. Why bother to do a grand design when the code won't be reused anywhere else?" And of course, you know what usually happens... ;) In any case, the Observer pattern is supposed to separate an object that generates events from the object that interprets those events. This is going to get long-winded, but I'll try to get through it all anyway... :) Imagine a hierarchy of classes such as DieRoller that takes a dice string to parse and generates a list of random numbers. How should those numbers be displayed? They could be displayed on a terminal, drawn on the screen as graphics elements, flashed on LEDs hooked up to the parallel port, spoken aloud, and so on. Because the data might be used in many different ways, the specific implementation should not be in the DieRoller class. Instead, a new class called DieObserver is created. (This would actually be an interface, but I'm simplifying.) The DieObserver would implement a callback, such as [b]dieRollUpdated(DieRoller dr)[/b]. When the DieRoller class is told to roll its dice, each random number generated causes DieRoller to invoke the [b]dieRollUpdated()[/b] method of a DieObserver that was passed in at the time the DieRoller was created. The DieObserver object can now query back to the original DieRoller using the passed in parameter and ask it what the latest roll was. (The query back to DieRoller is done to avoid hard-coding a data type into the parameter list of the [b]dieRollUpdated[/b] method, and hence, makes the DieObserver more generic and reusable. And, it many cases allows a single DieObserver to be used by multiple DieRollers; not in this example, though.) This allows me to use DieObserver as the top class in a hierarchy of classes: GraphicsDieObserver, LEDDieObserver, TerminalDieObserver, and so on. The main application passes the dice string to be parsed to the DieRoller, and as it generates random numbers it passes them to a particular DieObserver and the DieObserver is responsible for building the result. In your code example, that would be StringDieObserver -- it would simply concatenate all of the values together into a string. Because the DieObserver was passed to the DieRoller at instantiation time, the main application can have a reference to the DieObserver cached and later call a method of the DieObserver to retrieve the string. Empirical data suggests that object-oriented code has roughly 15%-20% more lines of code than a procedural program (Martin Fowler, [i]UML Distilled, 2nd Edition[/i]). This means that it takes longer to get from the starting point to the end result. But if analysis patterns and design patterns are applied at each step along the way, the resulting code is highly modular and quite easy to reuse in other applications later. This means that the next version of the code can be released sooner, that the readability of the code is improved, and that maintenance is easier. <rant> I read somewhere that, "[...] software doesn't need maintenance. It doesn't require periodic oil changes and its tires don't wear out. Instead, the functionality required of the software changes. Software doesn't need maintenance -- it needs redesign and reimplementation." I like that quote because it pinpoints one of the major problems with software production today: the feeling that the code is such a mess that it needs to be redone from the ground up. Why would that happen? It happens because the A&D steps were skipped or severely limited so that the program did not include the proper design elements. Since the design was not robust enough in the beginning, the patches made later to add functionality instead just obscure the existing functionality! Instead of patching a single class to add functionality, that subsystem of the application should be sent back to the A&D folks so that they can evaluate what the proper design should be to accommodate the change in functionality that is desired and then the code reimplemented. </rant> Concerning the link to the Microsoft web site, I understand the goal behind the question, but I'm not sure I understand whether the question is asking for a design that will accomplish what the OP is asking about or if the OP wants an implementation. The answer provided by the next post mentions the Provider pattern and this seems like a good way to go. If the question was concerning the C# implementation, ie. "How do I implement this in C#?", then I can't help. :( Again, I apologize again for the long-winded reply. And yes, this probably seems like a lot of work to go through to get from point A to point B. I have found that if I write all of my code as though it were going into a library/framework instead of into a specific application, I end up with generic, reusable classes more often. It is hard to discipline myself, however, when I think that I just want something quick and dirty that works. :) [/QUOTE]
Insert quotes…
Verification
Post reply
Community
General Tabletop Discussion
*Geek Talk & Media
d20 die roll string parser and roller in C#
Top