Hacker News new | past | comments | ask | show | jobs | submit login
Julius: An open source re-implementation of Caesar III (github.com/bvschaik)
298 points by nix23 on Dec 3, 2022 | hide | past | favorite | 62 comments



In Caesar III, your "blocks" were organized by how far the laborers walked. For example, the houses a Bath Worker walked by determined which houses had access to a bath. If the worker took a left at a fork, all the houses to the left would have access to the bath, but none of the houses to the right would have a bath.

This led to the strategy of minimizing forks and maximizing the worker loops to create "blocks", where workers reliably provided needed services (marketplace for food/pottery, furniture. Bath houses. Doctors. Prefects/police+firefighter units, religious services, entertainment, etc. etc.0.

-------

Pharaoh / Cleopatra, the next game in this series, made this more explicit. With "roadblocks", any worker who "determines services" would make a U-turn upon touching a blocker. This allows you to explicitly make blocks (by preventing workers from taking the wrong fork in a road).

So I guess what I'm saying is... the "height" of the gameplay was found in Pharaoh / Cleopatra, rather than Caesar III. Impressions Games did a great job with Caesar III, but those last few additions in Pharaoh / Cleopatra really makes the designing of blocks / housing areas much easier and more consistent.

> While Julius does not implement any gameplay changes, a fork of Julius named Augustus is implementing many long-wanted gameplay changes, such as roadblocks.

Ah, that's somewhat exciting. At least another open source project is backporting the roadblock to Caesar III's engine. Which of course breaks compatibility... but it'd be a better game IMO.


In my recollection, roadblocks didn't really fix the walker issues.

I've had countless occasions where a walker would suddenly stop servicing a row of houses he or she could previously access just fine without any change to the layout of a "neighbourhood". This seemed to happen because the houses had gotten too big and a resource the walker was distributing to the houses did not last until the last few houses (walkers had limited stores of resources they carried, although this seemed to happen with religious walkers also who as far as I remember didn't have quantifiable stores; might be wrong). At that point the walker would have to go back to fetch more of the resource to service those last few houses. Meanwhile those houses would devolve because they didn't have any more of the resource they needed to keep their current level. Devolving houses would lose one or more levels and shed occupants. Once the walker reached them with the required resource, the houses would evolve again. Then when they ran out of the resource again they 'd also devolve again, in a vicious circle that could drive a player mad. Usually the only solution was to demolish some housing and build a service building in their place. Which messed up everything all over again.

To be fair, I observed this primarily in Emperor: Rise of the Middle Kingdom (which I played at least as much as Cesar III, but more recently since I found it on GOG a few years ago). I've only played a little bit of Pharaoh and Zeus, but if this kind of problem wasn't fixed in Emperor (which came after Pharaoh) then I'm guessing it affected Pharaoh too.

Interestingly, I observed exactly the same issue in Lethis: Path of Progress, a Cesar III clone I've played. Lethis also has roadblocks, but they don't really help, you gotta be prepared to pull some houses down and build new service buildings.


Well, the key to these games is to "not solve every problem" for the players, but only to "solve the tedious problems" for the players.

You could build very good blocks in Caesar III with consistent services. However, it meant that you couldn't have _ANY_ forks in the road at all, and that all of your blocks would be giant loops. By adding roadblocks (ie: Pharaoh), you can suddenly have as many forks in the road as you like. For different sized blocks. Expanding the kinds of "block designs" that are optimal for the game is probably a good thing. Base CaesarIII is too restrictive IMO.

--------

"Running out of resources" locally is solved through warehouse management. I'd argue that this is the "fun" part of the game. Each warehouse + marketplace only can serve as many homes / houses as they can reliably pull supplies. For something like pottery, that is:

1. Clay Pits

2. Pottery furnace

3. Warehouse

4. + Additional Warehouses throughout the city for a good distribution network. Possibly augmented with foreign trade / docks.

5. Marketplaces

6. The final delivery to the house.

Yes, the Marketplaces, and even warehouses, have limited "throughput" and can only serve a finite number of houses. After that, you must expand by building "parallel marketplaces". Eventually, you build too many marketplaces and the Warehouse cart-pusher is overloaded with work, so you need additional warehouses to expand that bottleneck. Etc. etc.

IE: This problem is "reserved for the player to solve". The game shouldn't solve it for you, otherwise it wouldn't be a game anymore. Deciding "which bits" of the game to solve vs leave to the player to solve is the fundamental question of game design: what is fun anyway?


You're saying it's part of the challenge to build an efficient neihgbourhood, and I agree but it detracts from the charm of the game to see a neighbourhood oscillating wildly between house levels. At that point, for me anyway, the game's behaviour goes beyond "a challenge" to "an annoyance".

Now that I remember it, my solution was rather to keep some neighbourhoods deliberately low-level so that my city had enough working hands, even if some of them weren't living in luxury. It meant I could keep their houses provisioned much more easily to stay at a middle level, even if I had to build more of them. So I created an underclass, in short. In Emperor, the distinction between citizen class was part of the rules of the game.

Another solution is to do more or less what you and ufo below say: break up the city in small enough blocks with enough close-by service buildings that they won't run out. But that takes up a lot of space and the need for warehouses in close proximity tends to depress the land value of plots, which again hampers development. But that's OK, I agree that overcoming that sort of challenge is part of the fun of the game. Although I mainly played those games because I loved seeing a pretty ancient city filled with simulated people going about their life run on my machine :)

If you like that sort of challenge in a game (where to place distinct production units in a predetermined space with limited options) then you might enjoy the game Slipways:

https://store.steampowered.com/app/1264280/Slipways/

Nothing to do with ancient cities, or city building, but for me at least it scratches the same itch of micromanaging as playing Cesar III sometimes did.


In my experience, the biggest source of "random" glitches were the entertainment walkers. Because of a bug, sometimes the dancers would teleport and wonder off outside of the block. Lack of bazaar goods can also be a problem, specially if you have 1x1 houses because those run out of supplies faster than 2x2 houses. For 2x2 houses they need a bazaar visit twice a year, which matches the period in the random walker algorithm. However, for 1x1 houses that might not be enough; I suggest building an extra bazaar to be safe. Religion & water walkers don't spend resources. Education walkers consume papyrus every time they leave their building. If they're out of papyrus they don't go to work.


Right, I thought I might be misremembering the need for resources of religious workers, thanks.

The markets always tend to be a little unwieldy. It's easy to run out of space to place a maker far enough from housing to not depress its value, on smaller maps or ragged terrain with lots of rivers etc. So you gotta manage carefully.


One funny thing about bazaars is that they decrease desirability for adjacent houses but increase desirability for houses that are 3-6 tiles away. A good strategy is to build them close to the houses, but surrounded by other service buildings.


And with lots of plazas in between.


Yeah, I really wish those games allowed me to simplify "draw" the trajectory of the workers. You'd still be limited by the length they can walk from their origin building but would not get frustrated by worker suddenly choosing another route, breaking all the nice areas you took hours to build.

But they were really great games anyway. Caesar III in particular is the first game I spent many hours on, and hold a special place in my heart.


Augustus has been playable for a long time now. I was playing it months ago when I went back to revisit CIII.

The walker mechanic struck me as a clever solution that really feels like something from a more resource-constrained era of games. With one feature, they managed to solve two problems: “is this service building close enough to this other building when following the road graph” and “guys walking around whom you can click on”.


I remember spending class time diagraming possible “block layouts” on graph paper, trying to optimize and perfect this.


A catalog of more than one thousand open source game re-implementations: https://osgameclones.com/


This would be a bit more usable if it were in a sortable table and/or had more filters. The badges look is cute, but less useful for quickly skimming. As a casual "hey I want to play an opensource game" reader, I think it would be beneficial if the landing page focused only on those that were Playable. A long list of Unplayable games with Halted development degrades the quality of the resource.


You can click on the playable tag to filter all the ones that are playable.


For a more modern take on the genre check out Nebuchadnezzar: https://store.steampowered.com/app/1157220/Nebuchadnezzar/

It's got some great new features, like having some control and visibility over where and how far the workers go.


Make sure to try out the Augustus fork if you want extra niceties from "future" Impressions games like roadblocks and a global labor pool.


The old 'Plebs are needed' from Caesar II still burnt into my brain.

The amount of detail and information thrown into the game and the manual.


I am haunted by the of things that caught fire and as a 8-9 year old I didn’t understand why. I don’t think I generally made it far enough that the plebs were in need because the whole city had burned.


Yeah 10 yr old me burnt a dozen or so cities before deciding the point of the game is humiliating me by burning my granaries/gymnasiums etc and moved on to Czar and ultimately Age of Empires 2.


Oh yes the dreaded “(There is) Fire in the city!”

I really liked Caesar III but I never seemed to be able to get service reach a reasonable amount of real-estate, presumably due to the left turn mentioned in another branch. So I ended up plopping way more temples and engineers/prefects than strictly required.


> The old 'Plebs are needed' from Caesar II still burnt into my brain.

That would drive me nuts. Plebs is not a plural noun.


Came here to say “need more plebs” lol!


I have seen a few of these full source re-implementations. There's also one for Roller Coaster Tycoon 1 & 2 which is awesome.

I would love love love to see a source code remake of Heroes of Might and Magic 3.


Here you go: https://vcmi.eu/


Holy mackerel.

VCMI looks like it's at parity with the original game https://www.youtube.com/watch?v=S4WWRrh-KIc


Amazing memories of growing up on this game. I remember playing others in the series, but somehow this is what stuck in my mind.

Spiritual successor is probably Anno 1800, for anyone who wants to try a modern take on this.


Aw heck yeah, this is ported to OpenBSD and is up to date! Great surprise since I wasn't expecting it to be available haha :)


I have spent countless hours on this on my unlocked PS Vita... it runs very smoothly, and the controls are great. Really scratches an itch that few games do. Man does it get difficult at the later stages though...


Well that was misleading if you need an original copy of the game


I remember playing this game as a kid, and it was basically “build however you can until an army comes and destroys everything”.

I don’t think I ever managed to understand how to properly fight with the legions you build. Then again, I was like 10 years old at the time…


I can't remember if all stages have the option, but most stages in the game give you two cities to choose from, one peaceful and one with combat.


The problem was, even in peaceful cities, if you failed in economy and borrowed money from Caesar and not pay back for a long time or failed to send him his “gifts” he would send an army to destroy you.

In peaceful cities that was game over. In combat cities you could potentially defeat his army once or twice and buy yourself some time to pay up his debt.


Most of the economic/"peaceful" cities also have invasions that you need to deal with, though they're smaller than if you had chosen the military city.


Save game compatibilty is impressive and maybe an "unnecessary" feature. Any reason that this was possible, was the save game format documented or just reverse engineered?


This appears to be a huge effort. The "Augustus" engine, which shares a lot of code with "Julius", has all of the incompatible updates (roadblocks, zoom, changes to worker behavior, etc. etc.).

The compatible updates (compatibility with modern Windows, MP3 based sound support, etc. etc.) are all together in Julius... I guess for all the people who have 20+ year old save files they want to come back to.


Creator of Julius here.

The save format was reverse engineered. Quite a bit was already known from my previous tool to create a .png image out of a saved game file, and from someone who created a Mac <--> Windows converter for saved games: the Mac version of the game used a different file format. Julius also contains tests to make sure it stays compatible.


Save game compatibility would be very useful for testing if a bug was reproducible in the original game.


Indeed, what blows my mind is not just an excellent open-source re-implementation, it also is (or aims to be?) bug-for-bug accurate [1,2].

[1]: https://github.com/bvschaik/julius/wiki/Caesar-3-bugs

[2]: https://github.com/bvschaik/julius/issues?q=label%3A%22origi...


My guess is that save game compatibility is a great way to get people to try the new engine, and it was probably relatively easy to reverse engineer.


If only 27-year-old me had realized that 50-year-old me would have need of save files from a game I no longer wanted to play.


The regret and heartache of not saving every floppy, and not imaging them sooner.


Is it necessary to build a game like this in C? Could one build a game with comparable computational and graphical requirements in Python or something?


One could.

However, many people in game programming care about their craft and having as much control as possible and also being efficient with their resources. In this project specifically, there might be also some kind of nostalgia thing going on.

By the way, even though I use Python daily for ML and some web stuff, I find Python very lacking for serious, complex projects because of the dynamic type system, bad performance, and the infamous GIL. I find the idea that programming something in a system-level language is some kind of lost, arcane craft that shouldn't even be attempted quite perplexing.


> By the way, even though I use Python daily for ML and some web stuff, I find Python very lacking for serious, complex projects because of the dynamic type system, bad performance, and the infamous GIL.

I don't disagree re: the downsides of Python specifically, just threw it out as an example.

> I find the idea that programming something in a system-level language is some kind of lost, arcane craft that shouldn't even be attempted quite perplexing.

Well, some of us are self-taught developers and so system-level languages are very unapproachable.

Ultimately though, seems like a simply unnecessary headache even if one would be competent in using those languages. Friends of mine with CS degrees still don't opt to do side and hobbyist projects in those languages, for example.


C has an extremely sloppy type system as well, where basically pointers to objects of differing types are arbitrarily interchangeable.


Rather than calling it sloppy, I would instead say types barely exist at all in C. A type in C is really just a transient label reminding you and the compiler how to interepret some block of 1's and 0's, which is the only true type.

The Python type system really has quite a lot of overhead compared to this :P


And as disgusted as you might be that is also part of it's strengths - allowing various optimizations and not having to focus too much on typing.


Creator of Julius here.

Not specifically C, but you do want to have a language that's as close to the hardware as possible. Since Julius supports way higher resolutions than the original, the time required to draw the screen also increases: full-HD resolution requires 6.75 times more pixels to be drawn than 640x480. I've had to make optimizations to the drawing code to get a decent framerate on higher resolutions.


This (original) game came out in 1998.

You could write an emulator for x86 in Python that'd be fast enough to run the original operating system and game on modern equipment.

Whether that would be the best choice for implementing a game like this today - probably not.


Seems unlikely. The performance ratio of native code vs. Python is hundreds of times. The original game targeted roughly 100 MHz CPUs. Computers have gotten faster since 1998, but not that much faster in terms of single-threaded performance, the relevant metric here. I'd guess a python x86 emulator would run at 1/5 to 1/10 the required speed.


Unfortunately, that's just not true. At least not in pure Python without using Cython, C-extensions, graphical libraries implemented in C, or the like. In pure Python, you can't even write an NES emulator that operates at full-speed. Look it up. Every NES emulator ever written in Python uses C libraries or some kind of C extension like construct to achieve 60 FPS.


I prefer Augustus (a fork) over Julius.


For a second I though this was CAESAR II, the piping analysis program, and got excited.


Thank you for doing this <3


Half of me agrees with this, the other half doesn't... I liked too much that game.


I recently downloaded this and got it to work. I loved it. So much nostalgia.


Why is C code so beautiful?


No objects, no bullshit (for the most part), just write what you want the code to do.


As someone who used to feel that the most beautiful and elegant code was written in C, I feel the same way about (base) Rust. Assuming you 1) avoid async and 2) avoid excessive use of traits and generics, it has a real, pure C feel to it.

There's something fundamental about C though - and in some ways it feels as pure and fundamental as LISP.


Mm, I'll wait for Brutus' release.


Have my upvote, you made my day!


Hmmm




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: