This file provides guidance to coding agents when working with code in this repository.
SimpliCity — a fork of MicropolisJ (Will Wright's SimCity / Micropolis port to Java/Swing) by Jason Long, originally licensed GPLv3 with the EA "no SimCity trademark" addendum (see README and COPYING). The codebase was recently retargeted: build moved from Ant to Maven (597b08e), Java source/target raised to 25 (843bea3), and game defaults were tweaked (autoBudget on, disasters off — 721c6ab). The legacy INSTALL / HACKING files still describe the old Ant/Java-7 workflow and are out of date — trust pom.xml.
Maven project (pom.xml), packaging jar, main class micropolisj.Main.
mvn package # produces target/SimpliCity-<version>.jar
java -jar target/SimpliCity-*.jar # run the game
mvn exec:java -Dexec.mainClass=micropolisj.Main # run without packaging (if exec plugin present locally)JUnit 5 tests live under src/test/java; run mvn test (or mvn package) for code changes. GUI behavior also needs a manual check when a display and audio output are available.
JDK 25 is required. The simplicity.iml file is an IntelliJ module descriptor; the project also opens cleanly as a Maven project in IntelliJ/JetBrains IDEs.
These are utility main() classes invoked via java -cp against the built jar (or target/classes):
micropolisj.util.TranslationTool— Swing tool for editingsrc/main/resources/i18n/*.propertieslocale bundles. SeeHACKINGfor the localization workflow (still accurate apart from the jar name).micropolisj.build_tool.MakeTiles— regenerates the composite tile sheet from individual tile PNGs andgraphics/tiles.rc. Honors-Dtile_size=,-Dskip_tiles=,-Dtile_count=system properties. Resolves per-size source art (name_NxN.png/name.svg) before falling back to scaling the 16pxname.png.micropolisj.build_tool.UpscaleArt— Scale2x/EPX pixel-art upscaler (factor 2 or 4).micropolisj.build_tool.HalveArt— box-filter downscale by 2 (derives 8px sheets from cleaned 16px art).micropolisj.build_tool.DeDither— blends the dense 80s two-color dithering on the building/zone sheets into smooth shades (sparse detail like window grids stays crisp).micropolisj.build_tool.GenerateTerrainArt— draws the modern full-color terrain/forest/park/rubble/flood/radiation/fire art procedurally (seedocs/graphics-roadmap.adoc).micropolisj.build_tool.GenerateOverlayArt— draws the modern road/rail/wire/bridge/traffic art procedurally.micropolisj.build_tool.GenerateSpriteArt— draws the mobile sprites (obj*_{32x32,64x64}.png: train, helicopter, airplane, ship, monster, tornado, explosion, bus) as real hi-res art. The classic skin keeps pixel-art upscales of the originals underresources/classic/(preferred byTileImages); the 16px baseobj*.pngstays the original art everywhere.micropolisj.build_tool.GenerateDeluxeArt— produces the deluxe skin's building sheets (graphics/deluxe/gen/). Every building sheet is drawn from scratch at 64px/tile:DeluxeResArt(residential),DeluxeComArt(commercial),DeluxeIndArt(industrial zones plus piston/smoke frames),DeluxeCivicArt(fire/police stations plus their beacon-light animation frames — new always-on animations wired viagraphics/tiles.rctiles 763/771 and the*_light*_animation.anifiles; their 16px base sheets are generated intographics/so classic/modern compose them too),DeluxeStadiumArt(stadium, full stadium, football-game frames),DeluxePowerArt(coal plant + smoke frames, nuclear plant + reactor swirl),DeluxePortArt(seaport, airport, radar frames). Onlymisc_animationstill goes through the legacy upscaler (checker pre-blend + edge-aware mean-shift 4x + saturation/grain), as the baseDeluxeMiscArtpatches its redrawn tiles into (power-out indicator, drawbridges, destruction explosion, radar, swirl).micropolisj.build_tool.GenerateToolIcons— draws the toolbar tool icons (ic*.png/ic*hi.png) as stylized glyphs for the modern and deluxe skins, at the exact per-tool pixel sizes the classic icons use. Outputsresources/tools/(modern) andresources/deluxe/tools/(deluxe); the classic skin keeps the original rootic*.png. The GUI (MainWindow.toolIconResource) resolves icons per skin andrefreshToolIcons()reloads them when the graphics theme changes.micropolisj.build_tool.GenerateMinimapArt— derives the modern/deluxe 3px minimap source sheets (gen-minimap/name_3x3.png, gitignored) by alpha-weighted box-filter from the modern 16px art, so the modernsmsheet follows the modern palette. The classic skin instead keeps its original committed hand-made_3x3.pngart (classic/smis composed straight from it), so the minimap is skin-aware like the rest of the graphics.micropolisj.build_tool.GenerateLegendArt— redraws the modern/deluxe minimap overlay legend strips (rootlegendmm.png,legendpm.png) as gradient bars keyed toOverlayMapView.VAL_*; the classic skin keeps the original strips underclassic/.micropolisj.build_tool.RearrangeTiles— companion tool for tile reorganization.
Don't run these by hand for routine regeneration — graphics/build-tiles.sh orchestrates the whole sheet pipeline (all tile sizes, sprites, tiles.rc sync).
Running any of these (or any Swing/AWT code) headlessly: they touch java.awt/BufferedImage, so on a box with no display they die with java.awt.AWTError: Can't connect to X11 window server. Always pass -Djava.awt.headless=true, e.g. java -Djava.awt.headless=true -cp target/classes micropolisj.build_tool.GenerateTerrainArt graphics. This applies to the build tools, the TranslationTool, and any throwaway harness that renders a Swing component to an image. (build-tiles.sh is normally run on a desktop with a display, so it doesn't set the flag; add it if you invoke the script or its tools over SSH/CI.)
Three layers, kept strictly separated; the engine has no Swing dependency.
Micropolis is the simulation god-object: it owns the tile map (char[][] map), per-quadrant overlays at half/quarter resolution (pollutionMem, crimeMem, popDensity, trfDensity, terrainMem, landValueMem), the budget (CityBudget), evaluation state (CityEval), and active sprites. The front-end drives time by calling animate() periodically.
Key concepts:
- Tiles are 16-bit
charvalues. Static metadata for each tile id lives inTileSpec(loaded fromsrc/main/resources/tiles.rcat startup) — burnability, conductivity, zone status, animation chain, power/shutdown variants.TileConstantsexposes the integer IDs and helper predicates. - Sprites (
Spriteand subclasses:AirplaneSprite,HelicopterSprite,ShipSprite,TrainSprite,MonsterSprite,TornadoSprite,ExplosionSprite) are mobile entities overlaid on the tile grid. - Tools (
MicropolisTool,ToolStroke,BuildingTool,RoadLikeTool,Bulldozer) encapsulate user build actions; they produceToolResult/ToolEffectso previews and actual mutations share logic. - Listeners (
Micropolis.Listener,MapListener,EarthquakeListener) are how the GUI subscribes to engine events — never the other way around. - Save format is custom binary (see
FILE_FORMAT.txt); XML import/export goes throughXML_Helper. InfluenceModeselects Gaussian (default) or Classic pollution and police/fire coverage.MainWindowstores the choice as a global preference, independent of city save files; switching recomputes the overlays immediately. Gaussian service coverage is evaluated per tile, while the legacy mode preserves its coarse map.
MainWindow extends JFrame implements Micropolis.Listener, EarthquakeListener is the application shell. MicropolisDrawingArea renders the tile map; OverlayMapView is the minimap with data overlays; BudgetDialog, EvaluationPane, GraphsPane, MessagesPane, NotificationPane, DemandIndicator, NewCityDialog are the dialog/panel components. TileImages loads the rendered tile sheet produced by MakeTiles. The history graph window (GraphsPane, incl. its GraphGlyphIcon series buttons) and the RCI demand panel (DemandIndicator) are skin-aware: classic keeps the original raster art, while modern/deluxe paint crisp vector graphics live, refreshed by MainWindow.onGraphicsSkinClicked on theme change (see docs/graphics-roadmap.adoc → "Report graphs and demand indicator").
Sound effects run on worker threads. On Linux, MainWindow tries paplay with the system's default PulseAudio/PipeWire sink, then falls back to Java Sound; Java Sound clips are closed after playback.
graphics holds TileImage and Animation rendering primitives shared by the GUI and the build-tool. util contains the translation tool. build_tool contains the offline tile-sheet generators.
src/main/resources/i18n/— five.propertiesbundles per locale:CityMessages,CityStrings,GuiStrings,StatusMessages, plusMapGeneratoretc. Locales currently shipped: default (en),de,fr,it,sv. Italian was added inae11534.src/main/resources/tiles.rc— declarative tile definitions consumed byTileSpecat runtime; kept in sync with theMakeTilesrecipegraphics/tiles.rcbygraphics/build-tiles.sh.src/main/resources/{8x8,16x16,32x32,64x64}/— pre-rendered tile sheets at four zoom levels (zoom range 8–64;MicropolisDrawingAreais HiDPI-aware and picks the sheet coveringzoom × device scale).sm/holds the modern 3px minimap tiles andclassic/sm/the original ones (OverlayMapViewis skin-aware: classic loadsclassic/sm, modern/deluxe sharesm).classic/{N}x{N}/holds the original 80s-style art anddeluxe/{N}x{N}/the redrawn deluxe skin (falls back to modern art for sheets not yet redrawn ingraphics/deluxe/), both selectable live via Options → Graphics (TileSkinpreference). The minimap overlay legend strips are likewise per-skin: originalclassic/legend*.png, modern at the resource root.src/main/resources/obj*_{32x32,64x64}.png— derived sprite size variants (regenerated by the script; don't edit by hand).src/main/resources/sounds/— game audio.graphics/(repo root, outsidesrc/) — source artwork and thebuild-tiles.shregeneration script. Derivedgraphics/*_NxN.pngupscales are gitignored; committed_NxNfiles are hand-made art the script won't overwrite. Seedocs/graphics-roadmap.adocfor the full pipeline and the art-modernization TODO list.
- Existing files that already have the original GPLv3 / EA copyright header — keep it when editing them. Do not add copyright headers to new files.
- The simulation runs on the Swing EDT (
Main.mainschedules everything viaSwingUtilities.invokeLater); engine mutations from background threads are not safe. - Half-resolution and quarter-resolution overlay arrays in
Micropolisare indexed[y/2][x/2]and[y/4][x/4]respectively — read the field-level Javadoc inMicropolis.javabefore touching them.