ref: 24e3f38bb4e102aebca99a107ccbe99dbf4a107f
author: qwx <[email protected]>
date: Sun Feb 14 17:41:03 EST 2021
skeleton
--- /dev/null
+++ b/city.c
@@ -1,0 +1,50 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+int tdiv;
+vlong clock;
+
+void *
+emalloc(ulong n)
+{
+ void *p;
+
+ if((p = mallocz(n, 1)) == nil)
+ sysfatal("emalloc: %r");
+ setmalloctag(p, getcallerpc(&n));
+ return p;
+}
+
+void
+input(void)
+{
+
+}
+
+void
+main(int argc, char **argv)
+{
+ vlong t, t0, dt, Δtc;
+
+ ARGBEGIN{
+ }ARGEND
+ srand(time(nil));
+ init();
+ tdiv = Te9 / THz;
+ t0 = nsec();
+ for(;;){
+ input();
+ step();
+ clock++;
+ t = nsec();
+ Δtc = (t - t0) / tdiv;
+ if(Δtc <= 0)
+ Δtc = 1;
+ t0 += Δtc * tdiv;
+ dt = (t0 - t) / Te6;
+ if(dt > 0)
+ sleep(dt);
+ }
+}
--- /dev/null
+++ b/dat.h
@@ -1,0 +1,110 @@
+typedef struct Resource Resource;
+typedef struct Good Good;
+typedef struct Building Building;
+typedef struct Terrain Terrain;
+typedef struct Tile Tile;
+
+enum{
+ Gfish,
+ Gcattle,
+ Gwheat,
+ Gwood,
+ Glumber,
+ Gstone,
+ Giron,
+ Gtools,
+ Ggold,
+ Gjewelry,
+ Gtot,
+};
+struct Good{
+ char *name;
+ int terrain;
+ int resource;
+};
+extern Good goods[Gtot];
+extern int initialstock[Gtot];
+
+enum{
+ Rfood,
+ Rwood,
+ Rlumber,
+ Rstone,
+ Riron,
+ Rtools,
+ Rgold,
+ Rjewelry,
+ Rtot,
+};
+struct Resource{
+ char *name;
+ int goods[Gtot];
+};
+
+enum{
+ Btownhall,
+ Bmarket,
+ Bfishyard,
+ Bcarpentry,
+ Bsawmill,
+ Bmill,
+ Bfarm,
+ Bquarry,
+ Bsmeltery,
+ Bforge,
+ Blapidary,
+ Btot,
+};
+struct Building{
+ char *name;
+ int time;
+ int buildtime;
+ int costs[Gtot];
+ int terrain;
+ int goods[Gtot];
+ int upkeep[Rtot];
+};
+extern Building buildings[Btot];
+
+enum{
+ Tplain,
+ Twoods,
+ Tpond,
+ Tcrop,
+ Tmountain,
+ Tironvein,
+ Tgoldvein,
+ Ttot,
+};
+struct Terrain{
+ char *name;
+ int good;
+ int initialstock;
+ double yield;
+};
+extern Terrain terrains[Ttot];
+
+enum{
+ Snull,
+ Swait,
+ Sbuild,
+ Sproduce,
+};
+struct Tile{
+ Terrain *t;
+ Building *b;
+ int stock;
+ int state;
+ int clock;
+};
+extern Tile *map;
+extern int mapwidth, mapheight;
+
+enum{
+ Te9 = 1000000000,
+ Te6 = 1000000,
+ THz = 5,
+ Travelticks = 10,
+};
+extern int tdiv;
+extern vlong clock;
--- /dev/null
+++ b/defs.c
@@ -1,0 +1,308 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+
+Good goods[] = {
+ [Gfish]{
+ .name "fish",
+ .terrain Tpond,
+ .resource Rfood,
+ },[Gcattle]{
+ .name "cattle",
+ .terrain -1,
+ .resource Rfood,
+ },[Gwheat]{
+ .name "wheat",
+ .terrain -1,
+ .resource Rfood,
+ },[Gwood]{
+ .name "wood",
+ .terrain Twoods,
+ .resource Rwood,
+ },[Glumber]{
+ .name "lumber",
+ .terrain -1,
+ .resource Rlumber,
+ },[Gstone]{
+ .name "stone",
+ .terrain Tmountain,
+ .resource Rstone,
+ },[Giron]{
+ .name "iron",
+ .terrain -1,
+ .resource Riron,
+ },[Gtools]{
+ .name "tools",
+ .terrain -1,
+ .resource Rtools,
+ },[Ggold]{
+ .name "gold",
+ .terrain Tgoldvein,
+ .resource Rgold,
+ },[Gjewelry]{
+ .name "jewelry",
+ .terrain -1,
+ .resource Rjewelry,
+ }
+};
+int initialstock[Gtot] = {
+ [Gwood] 10,
+ [Gwheat] 5,
+ [Gfish] 5,
+ [Gcattle] 5,
+ [Ggold] 100,
+};
+Resource resources[] = {
+ [Rfood]{
+ .name "food",
+ .goods {
+ [Gfish] 1,
+ [Gcattle] 1,
+ [Gwheat] 1,
+ },
+ },[Rwood]{
+ .name "wood",
+ .goods {
+ [Gwood] 1,
+ },
+ },[Rlumber]{
+ .name "lumber",
+ .goods {
+ [Glumber] 1,
+ },
+ },[Rstone]{
+ .name "stone",
+ .goods {
+ [Gstone] 1,
+ },
+ },[Riron]{
+ .name "iron",
+ .goods {
+ [Giron] 1,
+ },
+ },[Rtools]{
+ .name "tools",
+ .goods {
+ [Gtools] 1,
+ },
+ },[Rgold]{
+ .name "gold",
+ .goods {
+ [Ggold] 1,
+ },
+ },[Rjewelry]{
+ .name "jewelry",
+ .goods {
+ [Gjewelry] 1,
+ },
+ }
+};
+Building buildings[] = {
+ [Btownhall]{
+ .name "townhall",
+ .time 0,
+ .buildtime 1000,
+ .costs {0},
+ .terrain Tplain,
+ .goods {0},
+ .upkeep {
+ [Rfood] 1,
+ },
+ },[Bcarpentry]{
+ .name "carpentry",
+ .time 25,
+ .buildtime 50,
+ .costs {
+ [Ggold] 3,
+ [Gwood] 3,
+ },
+ .terrain Tplain,
+ .goods {
+ [Gwood] 1,
+ },
+ .upkeep {
+ [Rfood] 1,
+ },
+ },[Bsawmill]{
+ .name "sawmill",
+ .time 25,
+ .buildtime 50,
+ .costs {
+ [Ggold] 10,
+ [Gwood] 10,
+ },
+ .terrain Tplain,
+ .goods {
+ [Glumber] 1,
+ },
+ .upkeep {
+ [Rfood] 2,
+ },
+ },[Bfishyard]{
+ .name "fishyard",
+ .time 25,
+ .buildtime 50,
+ .costs {
+ [Ggold] 5,
+ [Gwood] 5,
+ },
+ .terrain Tpond,
+ .goods {
+ [Gfish] 1,
+ },
+ .upkeep {
+ [Rfood] 1,
+ },
+ },[Bmill]{
+ .name "mill",
+ .time 25,
+ .buildtime 50,
+ .costs {
+ [Ggold] 8,
+ [Glumber] 8,
+ },
+ .terrain Tplain,
+ .goods {
+ [Gwheat] 2,
+ },
+ .upkeep {
+ [Rfood] 1,
+ },
+ },[Bfarm]{
+ .name "farm",
+ .time 25,
+ .buildtime 50,
+ .costs {
+ [Ggold] 8,
+ [Glumber] 4,
+ [Gwheat] 4,
+ },
+ .terrain Tplain,
+ .goods {
+ [Gcattle] 2,
+ },
+ .upkeep {
+ [Rfood] 1,
+ [Rlumber] 1,
+ },
+ },[Bquarry]{
+ .name "quarry",
+ .time 25,
+ .buildtime 50,
+ .costs {
+ [Ggold] 5,
+ [Glumber] 2,
+ [Gwheat] 3,
+ },
+ .terrain Tplain,
+ .goods {
+ [Gstone] 1,
+ },
+ .upkeep {
+ [Rfood] 1,
+ },
+ },[Bsmeltery]{
+ .name "smeltery",
+ .time 25,
+ .buildtime 50,
+ .costs {
+ [Ggold] 12,
+ [Glumber] 6,
+ [Gstone] 4,
+ [Gwood] 2,
+ },
+ .terrain Tplain,
+ .goods {
+ [Giron] 1,
+ },
+ .upkeep {
+ [Rfood] 2,
+ },
+ },[Bforge]{
+ .name "forge",
+ .time 25,
+ .buildtime 50,
+ .costs {
+ [Ggold] 10,
+ [Glumber] 4,
+ [Gstone] 4,
+ [Giron] 2,
+ },
+ .terrain Tplain,
+ .goods {
+ [Gtools] 1,
+ },
+ .upkeep {
+ [Rfood] 2,
+ },
+ },[Blapidary]{
+ .name "lapidary",
+ .time 25,
+ .buildtime 50,
+ .costs {
+ [Ggold] 26,
+ [Gstone] 16,
+ [Giron] 14,
+ [Gtools] 14,
+ },
+ .terrain Tplain,
+ .goods {
+ [Gjewelry] 1,
+ },
+ .upkeep {
+ [Rfood] 2,
+ },
+ },[Bmarket]{
+ .name "market",
+ .time 25,
+ .buildtime 50,
+ .costs {
+ [Ggold] 10,
+ [Glumber] 10,
+ },
+ .terrain Tplain,
+ .goods {0},
+ .upkeep {
+ [Rgold] 1,
+ [Rfood] 5,
+ },
+ }
+};
+Terrain terrains[] = {
+ [Tplain]{
+ .name "plain",
+ .good -1,
+ .initialstock 0,
+ .yield 0,
+ },[Twoods]{
+ .name "woods",
+ .good Gwood,
+ .initialstock 9001,
+ .yield 1,
+ },[Tpond]{
+ .name "pond",
+ .good Gfish,
+ .initialstock 9001,
+ .yield 1,
+ },[Tcrop]{
+ .name "crop",
+ .good Gwheat,
+ .initialstock 800,
+ .yield 0.8,
+ },[Tmountain]{
+ .name "mountain",
+ .good Gstone,
+ .initialstock 9001,
+ .yield 0.8,
+ },[Tironvein]{
+ .name "ironvein",
+ .good Giron,
+ .initialstock 9001,
+ .yield 0.5,
+ },[Tgoldvein]{
+ .name "goldvein",
+ .good Ggold,
+ .initialstock 9001,
+ .yield 0.3,
+ },
+};
--- /dev/null
+++ b/drw.c
@@ -1,0 +1,4 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
--- /dev/null
+++ b/fns.h
@@ -1,0 +1,5 @@
+void* emalloc(ulong);
+void init(void);
+void initmap(void);
+void step(void);
+void input(void);
--- /dev/null
+++ b/map.c
@@ -1,0 +1,30 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+int mapwidth, mapheight;
+Tile *map;
+
+void
+loadmap(void)
+{
+ Tile *m;
+ Terrain *t;
+
+ for(m=map; m<map+mapwidth*mapheight; m++){
+ t = terrains + nrand(Ttot);
+ m->t = t;
+ m->state = Snull;
+ m->stock = t->initialstock;
+ }
+}
+
+void
+initmap(void)
+{
+ mapwidth = 16;
+ mapheight = 16;
+ map = emalloc(mapwidth * mapheight * sizeof *map);
+ loadmap();
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,11 @@
+</$objtype/mkfile
+BIN=$home/bin/$objtype
+TARG=city
+OFILES=\
+ city.$O\
+ defs.$O\
+ map.$O\
+ sim.$O\
+
+HFILES=dat.h fns.h
+</sys/src/cmd/mkone
--- /dev/null
+++ b/sim.c
@@ -1,0 +1,100 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+static Tile **objs, **objhead;
+static int maxobj;
+
+enum{
+ UpkeepΔt = 150,
+};
+static int stock[Gtot], rstock[Rtot];
+
+static void
+spawn(Tile *m, int n)
+{
+ Tile **o;
+
+ if(objhead - objs >= maxobj)
+ sysfatal("spawn: out of bounds");
+ m->t = terrains + Tplain;
+ m->b = buildings + n;
+ for(o=objhead-1; o>=objs; o--)
+ if((*o)->b - buildings <= n)
+ break;
+ /* push in front of lower priority object */
+ if(++o < objhead)
+ memmove(o+1, o, (objhead - o) * sizeof *o);
+ *o = m;
+ objhead++;
+}
+
+static void
+upkeep(void)
+{
+ Tile **o;
+
+ if(clock % UpkeepΔt != 0 || clock == 0)
+ return;
+ for(o=objhead-1; o>=objs; o--){
+ /* if upkeep can't be kept, stop production immediately
+ * else decrease stock
+ */
+ }
+}
+
+static void
+updateobj(void)
+{
+/*
+ iterate through obj stack
+
+ build
+ call for supplies, start travel towards building site
+ done?
+ start production
+ upgrade
+ finished?
+ start production
+ destroy
+ finished?
+ despawn
+ produce
+ call for supplies
+ enough supplies? else wait until next tick (loop)
+ decrement stocks, start traveling from townhall
+ reached building?
+ increment supplies
+ begin production
+ while producing, if we can call for supplies earlier to restart immediately, do it
+ finished producing?
+ start travel towards building
+ reached building?
+ call for pickup
+ loop
+*/
+}
+
+void
+step(void)
+{
+ upkeep();
+ updateobj();
+}
+
+void
+init(void)
+{
+ int i;
+
+ initmap();
+ maxobj = mapwidth * mapheight;
+ objs = emalloc(maxobj * sizeof *objs);
+ objhead = objs;
+ spawn(map + nrand(maxobj), Btownhall);
+ for(i=0; i<nelem(initialstock); i++){
+ stock[i] = initialstock[i];
+ rstock[goods[i].resource] += stock[i];
+ }
+}