shithub: city

Download patch

ref: 063901a12ba4031e700716f193818a88a25439b2
parent: 2d226f3ddc911ad4a47d7c986b359075d89f7eea
author: qwx <qwx@sciops.net>
date: Tue Feb 16 13:31:52 EST 2021

sim: basic production states logic

--- a/dat.h
+++ b/dat.h
@@ -58,11 +58,12 @@
 };
 struct Building{
 	char *name;
-	int time;
 	int buildtime;
-	int costs[Gtot];
+	int buildcost[Gtot];
+	int prodtime;
+	int product[Gtot];
+	int prodcost[Gtot];
 	int terrain;
-	int goods[Gtot];
 	int upkeep[Rtot];
 };
 extern Building buildings[Btot];
@@ -87,16 +88,25 @@
 
 enum{
 	Snull,
+	Svoid,
+	Swaitbuild,
 	Sbuild,
-	Swait,
+	Sstarved,
+	Swaitsupply,
 	Sproduce,
 };
 struct Tile{
 	Terrain *t;
-	Building *b;
+	int distance;
 	int stock;
+	Building *b;
 	int state;
-	int clock;
+	int gotsupply;
+	int prodstock[Gtot];
+	vlong clock;
+	vlong prodΔt;
+	vlong supplyΔt;
+	vlong pickupΔt;
 };
 extern Tile *map;
 extern int mapwidth, mapheight;
--- a/defs.c
+++ b/defs.c
@@ -100,87 +100,97 @@
 Building buildings[] = {
 	[Btownhall]{
 		.name "townhall",
-		.time 0,
 		.buildtime 1000,
-		.costs {0},
+		.buildcost {0},
 		.terrain Tplain,
-		.goods {0},
+		.prodtime 0,
+		.product {0},
+		.prodcost {0},
 		.upkeep {
 			[Rfood] 1,
 		},
+	},[Bfishyard]{
+		.name "fishyard",
+		.buildtime 50,
+		.buildcost {
+			[Ggold] 5,
+			[Gwood] 5,
+		},
+		.terrain Tpond,
+		.prodtime 25,
+		.product {
+			[Gfish] 1,
+		},
+		.prodcost {0},
+		.upkeep {
+			[Rfood] 1,
+		},
 	},[Bcarpentry]{
 		.name "carpentry",
-		.time 25,
 		.buildtime 50,
-		.costs {
+		.buildcost {
 			[Ggold] 3,
 			[Gwood] 3,
 		},
 		.terrain Tplain,
-		.goods {
+		.prodtime 25,
+		.product {
 			[Gwood] 1,
 		},
+		.prodcost {0},
 		.upkeep {
 			[Rfood] 1,
 		},
 	},[Bsawmill]{
 		.name "sawmill",
-		.time 25,
 		.buildtime 50,
-		.costs {
+		.buildcost {
 			[Ggold] 10,
 			[Gwood] 10,
 		},
 		.terrain Tplain,
-		.goods {
+		.prodtime 50,
+		.product {
 			[Glumber] 1,
 		},
+		.prodcost {
+			[Gwood] 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 {
+		.buildcost {
 			[Ggold] 8,
 			[Glumber] 8,
 		},
 		.terrain Tplain,
-		.goods {
+		.prodtime 25,
+		.product {
 			[Gwheat] 2,
 		},
+		.prodcost {0},
 		.upkeep {
 			[Rfood] 1,
 		},
 	},[Bfarm]{
 		.name "farm",
-		.time 25,
 		.buildtime 50,
-		.costs {
+		.buildcost {
 			[Ggold] 8,
 			[Glumber] 4,
 			[Gwheat] 4,
 		},
 		.terrain Tplain,
-		.goods {
+		.prodtime 25,
+		.product {
 			[Gcattle] 2,
 		},
+		.prodcost {
+			[Gwheat] 1,
+		},
 		.upkeep {
 			[Rfood] 1,
 			[Rlumber] 1,
@@ -187,25 +197,25 @@
 		},
 	},[Bquarry]{
 		.name "quarry",
-		.time 25,
 		.buildtime 50,
-		.costs {
+		.buildcost {
 			[Ggold] 5,
 			[Glumber] 2,
 			[Gwheat] 3,
 		},
 		.terrain Tplain,
-		.goods {
+		.prodtime 25,
+		.product {
 			[Gstone] 1,
 		},
+		.prodcost {0},
 		.upkeep {
 			[Rfood] 1,
 		},
 	},[Bsmeltery]{
 		.name "smeltery",
-		.time 25,
 		.buildtime 50,
-		.costs {
+		.buildcost {
 			[Ggold] 12,
 			[Glumber] 6,
 			[Gstone] 4,
@@ -212,17 +222,20 @@
 			[Gwood] 2,
 		},
 		.terrain Tplain,
-		.goods {
+		.prodtime 50,
+		.product {
 			[Giron] 1,
 		},
+		.prodcost {
+			[Gwood] 2,
+		},
 		.upkeep {
 			[Rfood] 2,
 		},
 	},[Bforge]{
 		.name "forge",
-		.time 25,
 		.buildtime 50,
-		.costs {
+		.buildcost {
 			[Ggold] 10,
 			[Glumber] 4,
 			[Gstone] 4,
@@ -229,17 +242,21 @@
 			[Giron] 2,
 		},
 		.terrain Tplain,
-		.goods {
+		.prodtime 25,
+		.product {
 			[Gtools] 1,
 		},
+		.prodcost {
+			[Gwood] 1,
+			[Giron] 1,
+		},
 		.upkeep {
 			[Rfood] 2,
 		},
 	},[Blapidary]{
 		.name "lapidary",
-		.time 25,
 		.buildtime 50,
-		.costs {
+		.buildcost {
 			[Ggold] 26,
 			[Gstone] 16,
 			[Giron] 14,
@@ -246,22 +263,29 @@
 			[Gtools] 14,
 		},
 		.terrain Tplain,
-		.goods {
+		.prodtime 100,
+		.product {
 			[Gjewelry] 1,
 		},
+		.prodcost {
+			[Gwood] 2,
+			[Giron] 2,
+			[Gtools] 2,
+		},
 		.upkeep {
 			[Rfood] 2,
 		},
 	},[Bmarket]{
 		.name "market",
-		.time 25,
 		.buildtime 50,
-		.costs {
+		.buildcost {
 			[Ggold] 10,
 			[Glumber] 10,
 		},
 		.terrain Tplain,
-		.goods {0},
+		.prodtime 0,
+		.product {0},
+		.prodcost {0},
 		.upkeep {
 			[Rgold] 1,
 			[Rfood] 5,
--- a/fns.h
+++ b/fns.h
@@ -3,3 +3,4 @@
 void	initmap(void);
 void	step(void);
 void	input(void);
+int	mhdist(int, int, int, int);
--- a/map.c
+++ b/map.c
@@ -6,6 +6,12 @@
 int mapwidth, mapheight;
 Tile *map;
 
+int
+mhdist(int x, int y, int x´, int y´)
+{
+	return abs(x - x´) + abs(y - y´);
+}
+
 void
 loadmap(void)
 {
--- a/sim.c
+++ b/sim.c
@@ -45,7 +45,7 @@
 static void
 starve(Tile *o)
 {
-	o->state = Swait;
+	o->state = Svoid;
 }
 
 static void
@@ -58,7 +58,7 @@
 		return;
 	for(ol=objhead-1; ol>=objs; ol--){
 		o = *ol;
-		if(o->state <= Swait)
+		if(o->state <= Svoid)
 			continue;
 		if(o->b == nil)
 			sysfatal("empty active tile");
@@ -84,35 +84,96 @@
 	}
 }
 
+static int
+trypickup(Tile *o)
+{
+	int g;
+
+	if(o->pickupΔt == 0 || o->clock < o->pickupΔt)
+		return 0;
+	for(g=0; g<nelem(goods); g++)
+		stock[g] += o->prodstock[g];
+	o->pickupΔt = 0;
+	return 1;
+}
+
+static int
+trysupply(Tile *o)
+{
+	int g;
+	for(g=0; g<nelem(goods); g++)
+		if(o->b->prodcost[g] > stock[g])
+			return 0;
+	for(g=0; g<nelem(goods); g++)
+		if(o->b->prodcost[g] > 0)
+			stock[g] -= o->b->prodcost[g];
+	o->supplyΔt = o->clock + o->distance;
+	return 1;
+}
+
 static void
 updateobj(void)
 {
+	int g;
 	Tile *o, **ol;
 
 	for(ol=objhead-1; ol>=objs; ol--){
 		o = *ol;
+		o->clock++;
 		switch(o->state){
+		case Swaitbuild:
+			if(o->clock >= o->distance){
+				o->clock = 0;
+				o->state = Sbuild;
+			}
+			break;
 		case Sbuild:
-			/* 
-			call for supplies, start travel towards building site
-			done?
-			start production
-			*/
+			if(o->clock >= o->b->buildtime){
+				o->clock = 0;
+				o->state = o->b->prodtime > 0 ? Sstarved : Svoid;
+			}
+			break;
+		case Sstarved:
+			trypickup(o);
+			if(trysupply(o))
+				o->state = Swaitsupply;
+			break;
+		case Swaitsupply:
+			trypickup(o);
+			if(o->clock >= o->supplyΔt){
+				o->gotsupply = 0;
+				o->supplyΔt = 0;
+				o->prodΔt = o->clock + o->b->prodtime;
+				o->state = Sproduce;
+			}
+			break;
 		case Sproduce:
-			/*
-			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
-			*/
+			if(!o->gotsupply){
+				if(o->supplyΔt == 0){
+					if(!trysupply(o))
+						return;
+					for(g=0; g<nelem(goods); g++)
+						if(o->b->prodcost[g] > stock[g])
+							break;
+				}else if(o->clock >= o->supplyΔt){
+					o->gotsupply = 1;
+					o->supplyΔt = 0;
+				}
+			}
+			trypickup(o);
+			if(o->clock >= o->prodΔt){
+				o->pickupΔt = o->clock + o->distance * 2;
+				if(!o->gotsupply){
+					if(o->supplyΔt == 0)
+						o->state = Sstarved;
+					else
+						o->state = Swaitsupply;
+				}else{
+					o->prodΔt += o->b->prodtime;
+					o->gotsupply = 0;
+				}
+			}
+			break;
 		default: break;
 		}
 	}
@@ -125,16 +186,35 @@
 	updateobj();
 }
 
+static void
+calcdists(int n)
+{
+	int x, y, x´, y´;
+	Tile *o;
+
+	x = n % mapwidth;
+	y = n / mapheight;
+	for(o=map, x´=0, y´=0; o<map+mapwidth*mapheight; o++, x´++){
+		o->distance = mhdist(x, y, x´, y´);
+		if(x´ == mapwidth){
+			x´ = 0;
+			y´++;
+		}
+	}
+}
+
 void
 init(void)
 {
-	int i;
+	int i, n;
 
 	initmap();
 	maxobj = mapwidth * mapheight;
 	objs = emalloc(maxobj * sizeof *objs);
 	objhead = objs;
-	spawn(map + nrand(maxobj), Btownhall);
+	n = nrand(maxobj);
+	spawn(map + n, Btownhall);
+	calcdists(n);
 	for(i=0; i<nelem(initialstock); i++){
 		stock[i] = initialstock[i];
 		rstock[goods[i].resource] += stock[i];