Search the Community
Showing results for tags 'utopia'.
Found 4 results
Hello everyone, just a quick heads up about an interesting article published in the latest issue of Retro Gamer. It is an article about the making of Utopia. There is a candid interview with Don Laglow and some useful playing tips (see pics). Best wishes and enjoy!
Introduction Ok, so I spent a couple days reverse engineering Utopia. I now know pretty much how it all works, and now you can find out too. Here's some highlights, in case you don't want to wade through the code: Forts: Do protect a 1 unit radius against rebels Will protect parked ships that have the same owner as the fort. Radius of 1 card. Will protect both players ships when they're under active control. Radius of 1 card. Do not otherwise contribute to your score Bugs: Scoring will overflow, if you have more than 65 crops + fishing boats combined. It will also overflow if you earn more than 255 gold bars in a single turn. (Is that possible?) The "float off bottom of screen" bug is likely due to island/status collision detection interacting poorly with EXEC's boundary detection. The game can "nudge" a boat across the boundary the EXEC checks for. There is a check for this, but it only has been applied properly to the left/right edges. Delay loop in scoring display appear to want to update random number generator, but they don't actually. Code quality:Let's just say it's likely the priority was to have a compelling game, and have it out quickly, as opposed to writing the tightest, cleanest possible code. Miscellaneous: Pirates will never sail toward a parked PT boat on purpose. The "nudge" code, though, can nudge them through a tangle of PT boats. Hurricanes are 5 times more destructive than tropical storms. All three forms of weather water crops at the same rate, though. There's two copies of the "sinking fishing boat" animation in the ROM, due to how the EXEC distinguishes between background cards and MOB animations Each island has precisely 29 squares. When weather takes out something on your island, it will incur 0 to 101 casualties. If you want more details, you'll have to dig through the code unless it's covered in the slightly more detailed review below. :-) Code attached. Code Structure The bulk of the main game code can be put into one of three categories -- The Timer Tick Task, Dispatches, Scoring Logic. The rest of the code is either initialization code, or support code for those three categories. Timer Tick Task The bulk of the game logic hangs off the the Timer Tick Task. This task runs 20 times a second, and it handles everything from spawning weather to collision detection to animating certain sinking ships. It's quite a lot of code and is fairly linear. The rough order of execution: Update the weather, possibly creating new weather Update the fish, possibly creating new schools of fish Update the pirates, possibly spawning new pirates Island vs. boat collision detection Update the game clock If not end of round / end of game: Update the status line at bottom of screen Update parked sinking ships At end-of-round, fire off the scoring code and then show the scores At end-of-game, show final score and halt Dispatches The next big set of code is the set of Dispatches. The EXEC mostly works by calling various functions in response to various events. Dispatches fall into a few categories: Controller input dispatches. The action-button and disc handlers are pretty simple. The keypad dispatch is amazingly convoluted, but that makes sense when you consider everything that it has to account for. Object vs. object dispatches. These handle pirates vs. PT boats and similar such things. Object vs. land dispatches. This is what handles rain on crops, pirates sinking parked ships, or parked ships going fishing. Scoring Logic The final big piece of code is the scoring logic. Scoring happens in four phases: Income Computation, Population Update, Round Score Calculation, Rebellion. Income Computation During the round, every gold bar you earn (say due to fishing, rain on crops, etc.) gets tallied in this round's Gross Domestic Product (Round GDP), separate from your actual gold bar balance. That is, spending does not subtract from Round GDP even though it lowers your treasury balance. At the end of the round, you get awarded additional gold as follows. Each of these contributes to the Round GDP except for the "baseline 10 bars." 4 gold bars per factory 1 gold bar per fishing boat Productivity bonus: ((Schools + Hospitals) * Factories) + Hospitals, clamped to a maximum of 30 gold bars. 10 gold bars of baseline income (does not contribute to the Round GDP). Population computation -- expressed as a growth rate, resulting in exponential growth. Fertility computation Start with a baseline fertility rate of 5.0% Increase fertility by 0.3% for every crop Increase fertility by 0.3% for every hospital Increase fertility by 0.1% for every house Decrease fertility by 0.3% for every school Clamp fertility to a minimum of 4.0%. You can't have fertility below 4% even if you filled the island with schools. Mortality computation Start with a baseline mortality rate of 1.1% Decrease mortality by 0.3% for every hospital, but not below 0.2%. (This limit is applied before the next step.) Increase mortality by 0.1% for every factory. If you fill the island with factories, your mortality rate will be 4.0%, matching the minimum allowed fertility. New population: Population + Population * Fertility - Population * Mortality. Maximum allowed population is limited to 9999. Round Score Calculation -- roughly, "approval rating", 0-100% First compute the following four subscores: Housing score: ((Houses * 500) / (Population / 100)) / 3. If larger than 30, clamp it to 30. Per-capita GDP score: ((Round GDP * 100) / (Population / 100)) / 12. If larger than 30, clamp it at 30. Food supply score: (((Fishing boats + Crops) * 500) / (Population / 100)) / 3. If this value is larger than 30, clamp it to 30.Note: 65 * 500 = 32500. So, if you have more than 65 fishing boats + crops, this score can go negative. This is fixable by changing the BLE at $5B1E to a BNC, I think, so it treats the overflow case as a case that needs to clamp to 30. General welfare score: 1 point for every school or hospital Add up the four subscores, limiting the total to 100 or less. That's the per-round score. Rebellion Compare this round's score to the previous round, and consider it in absolute terms as well If it dropped by more than 10 points or is below 30 points, add a rebel If it increased by more than 10 points or is above 70 points, remove a rebel If you want to see the exact details of how these pieces work, look at the code. For example, in the scoring section, some divides are rounding divides, and some are truncating divides. The population computation is actually carried out with scaled arithmetic (ie. fertility/mortality rates are multiplied by 10, and population divided by 10 when computing numbers of births and deaths.) For anything else... see the code! ____ [Edited to fix some formatting issues in the nested bulleted lists.] utopia.asm
This reproduction of the overlay for the Intellivision game Utopia is quite faithful to the original except for the typeface used in the text (the numerals, on the other hand, seem to be very close). I think the original overlay design uses Helvetica, while the closest clone I have is Swiss 721. I'll update this file with a more faithful version when it becomes available.
© Illustration by The Eyeball Mural, no rights reserved. Intellivision intellectual properties belong to Intellivision Productions.
I wrote up a quick and dirty C program to simulate many millions of tics of weather movement across the Utopia map, to see if there are any biases inherent in the weather algorithm. It turns out there are. The weather turns out to be very sensitive to its initial velocity, in fact. The weather movement algorithm is pretty simple. Weather always originates from [27, 0], with a velocity of [+5/8, +4/8]. (+5/8 means it takes 8 tics to move 5 pixels.) On any given tic, there's a 1-in-10 chance of modifying the weather's velocity. If the algorithm decides to adjust the weather velocity, it picks a direction (N/S/E/W) and increments the velocity by 1/8 in that direction. If the weather moves off screen, it gets deactivated. It turns out that the fixed starting location/velocity and the deactivate-on-exit behavior lead to a pretty stable distribution of "likely weather" areas. Furthermore, the right island seems to get more weather than the left island, on average, if my simulation is accurate. Below is my "heat map". Every four bands in the color spectrum represent a factor of 10 difference in likelihood that pixel seeing weather. Two adjacent bands in the color map are approx a factor of 1.78 apart. As you can see, the right island gets more rain on average than the left, with the buld of the benefit concentrated in the northwest corner of the island. The entire west coast of the right-hand island gets a pretty good bit of rain. The left island has a more concentrated set of raininess along its east coast. Overall, it's dryer. I suspect this ends up making the right hand island easier to get started with, while both islands are agrarian and just getting established. In the long run, though, since all weather follows these trajectories (rain, tropical storms and hurricanes), the right island will also see more damaging weather events. Now, I did experiment with the parameters a little bit, to see how sensitive the model is to that initial velocity. It turns out it's quite sensitive. Here's what it looks like with [+5/8, +5/8] as the initial velocity: And here's what it looks like with [+4/8, +5/8]: As you can see, slight changes in that initial velocity really shift the distribution around, even though most of the motion is a random walk. You have an extreme sensitivity to initial conditions, and I think it's reinforced by the fact weather deactivates when it reaches a screen boundary, so you can't average behavior over an unbounded amount of time. I suspect this bit of code was intended to reduce the bias a little by shifting the weather entry point occasionally: MVII #$0003, R0 ; 51EB \_ Random 0..2 JSR R5, X_RAND2 ; 51ED / TSTR R0 ; 51F0 \_ If non-zero, done spawning BNEQ L_51F8 ; 51F1 / weather INCR R2 ; 51F3 \ MVII #$001B, R1 ; 51F4 |_ Set X coord to 27. SWAP R1, 1 ; 51F6 | (But, it should already be 27!) [email protected] R1, R2 ; 51F7 / But, as my disassembly comments indicate, this picks between a starting X coordinate of 27, or with 1-in-3 chance, selecting 27 instead. That is, no matter what, you're starting at [27, 0]. You can see my quick and dirty code here: http://spatula-city.org/~im14u2c/intv/dl/weather-track.c Enjoy!