From 2eef87c8970db643c4ef09e0fd9e8110c8193043 Mon Sep 17 00:00:00 2001 From: jacopo grandi Date: Sat, 20 Feb 2021 00:11:23 +0100 Subject: finish condition and bad cost function --- build/army/army.txt | Bin 0 -> 21528 bytes build/content/armor.txt | 66 +++++++++++++++---------------- build/content/autolevel.py | 20 +++++++--- build/test.exe | Bin 751762 -> 775710 bytes design/notes.txt | 95 +++++++++++++++++++++++++++++++++++++++------ gst/gst.c | 29 +++++++++++++- gst/gst.h | 3 ++ gst/info.c | 86 +++++++++++++++++++++++++++++++++++++++- gst/info.h | 1 + gst/units.c | 9 +++-- gst/units.h | 4 +- hud/hud.c | 29 +++++++++++--- hud/hud_views.c | 6 +++ 13 files changed, 282 insertions(+), 66 deletions(-) create mode 100644 build/army/army.txt diff --git a/build/army/army.txt b/build/army/army.txt new file mode 100644 index 0000000..033dd7c Binary files /dev/null and b/build/army/army.txt differ diff --git a/build/content/armor.txt b/build/content/armor.txt index 5182a0c..5ceaacc 100644 --- a/build/content/armor.txt +++ b/build/content/armor.txt @@ -2,9 +2,9 @@ { "name": "metal plating", "weight": [ - 50.0, - 50.0, - 50.0 + 10.0, + 10.0, + 10.0 ], "pierce": [ 5.0, @@ -20,9 +20,9 @@ { "name": "heavy metal plating", "weight": [ - 80.0, - 80.0, - 80.0 + 16.0, + 16.0, + 16.0 ], "pierce": [ 7.0, @@ -43,9 +43,9 @@ { "name": "reflective plating", "weight": [ - 40.0, - 40.0, - 40.0 + 8.0, + 8.0, + 8.0 ], "laser": [ 10.0, @@ -56,9 +56,9 @@ { "name": "heat resistent plating", "weight": [ - 50.0, - 50.0, - 50.0 + 10.0, + 10.0, + 10.0 ], "fusion": [ 8.0, @@ -69,9 +69,9 @@ { "name": "padding", "weight": [ - 20.0, - 20.0, - 20.0 + 4.0, + 4.0, + 4.0 ], "spread": [ 5.0, @@ -87,9 +87,9 @@ { "name": "reactive armor", "weight": [ - 75.0, - 75.0, - 75.0 + 15.0, + 15.0, + 15.0 ], "explosive": [ 12.0, @@ -100,9 +100,9 @@ { "name": "energy shields", "weight": [ - 25.0, - 25.0, - 25.0 + 5.0, + 5.0, + 5.0 ], "pierce": [ 3.0, @@ -133,9 +133,9 @@ { "name": "composite armor", "weight": [ - 30.0, - 30.0, - 30.0 + 6.0, + 6.0, + 6.0 ], "pierce": [ 6.0, @@ -156,9 +156,9 @@ { "name": "plastic armor", "weight": [ - 10.0, - 10.0, - 10.0 + 2.0, + 2.0, + 2.0 ], "pierce": [ 4.0, @@ -169,9 +169,9 @@ { "name": "sloped steel armor", "weight": [ - 45.0, - 45.0, - 45.0 + 9.0, + 9.0, + 9.0 ], "pierce": [ 10.0, @@ -187,9 +187,9 @@ { "name": "charged armor", "weight": [ - 100.0, - 100.0, - 100.0 + 20.0, + 20.0, + 20.0 ], "explosive": [ 25.0, diff --git a/build/content/autolevel.py b/build/content/autolevel.py index eac6e09..345bccf 100644 --- a/build/content/autolevel.py +++ b/build/content/autolevel.py @@ -1,6 +1,6 @@ import json -def vectorize (obj, forbidlist): +def vectorize (obj, forbidlist, _): for c in obj: for key in c: if not(key in forbidlist): @@ -10,13 +10,18 @@ def vectorize (obj, forbidlist): try: val = float(val); except: pass c[key] = [val for i in range(3)] - return obj + +def query (obj, allowlist, op): + for c in obj: + for key in c: + if key in allowlist: + c[key] = op(c[key]) -def comp(filename, forbidlist): +def comp(filename, l, fun, op=None): with open(filename+".txt", "r") as f: obj = json.loads(f.read()) - obj = vectorize(obj, forbidlist) - with open(filename+".txt", "w") as f: + fun(obj, l, op) + with open(filename+"-new"+".txt", "w") as f: f.write(json.dumps(obj, indent=4)) if __name__ == "__main__": @@ -25,4 +30,7 @@ if __name__ == "__main__": #comp("batteries", ["name"]) #comp("armor", ["name"]) #comp("chassis", ["name"]) - comp("brains", ["name"]) + #comp("brains", ["name"]) + #comp("brains", ["name"]) + + #comp("armor", ["weight"], query, lambda x: [x[i]/5 for i in range(3)]) diff --git a/build/test.exe b/build/test.exe index de1814f..a57fe22 100644 Binary files a/build/test.exe and b/build/test.exe differ diff --git a/design/notes.txt b/design/notes.txt index ef2bb25..c9903bb 100644 --- a/design/notes.txt +++ b/design/notes.txt @@ -1,22 +1,14 @@ tasks: (date) -[x] implement rm unit (issued on 18:02:21, done on 18:02:21) -[x] implement armor calculation (issued on 18:02:21, done on 18:02:21) -[x] implement augment calculations (issued on 18:02:21, done on 18:02:21) -[x] implement augment hud view (issued on 18:02:21, done on 18:02:21) -[ ] implement sound (issued on 18:02:21) -[ ] implement end of battle condition (issued on 19:02:21) +[ ] implement cost function (issued on 18:02:21) [ ] implement stats hud view (issued on 18:02:21) -[x] implement battery calculation (issued on 18:02:21, done on 19:02:21) -[ ] implement brain behaviour (issued on 18:02:21) -[ ] implement component levels (issued on 18:02:21) -[ ] implement persistent settings (issued on 18:02:21) [ ] implement net hud and minilobby (issued on 18:02:21) +[ ] implement brain behaviour (issued on 18:02:21) [ ] implement army hud view (issued on 18:02:21) -[ ] implement cost function (issued on 18:02:21) [ ] implement lobby cost constraints (issued on 18:02:21) [ ] implement edit unit directly (issued on 18:02:21) [ ] implement naming template and army (issued on 18:02:21) +[ ] implement persistent settings (issued on 18:02:21) [ ] implement move animation (issued on 18:02:21) [ ] implement fire animation (issued on 18:02:21) [ ] implement explosions (issued on 18:02:21) @@ -24,7 +16,15 @@ tasks: (date) [ ] design 3d map tiles (issued on 18:02:21) [ ] implement 3d units (issued on 18:02:21) [ ] design component sprites (issued on 18:02:21) +[ ] implement sound (issued on 18:02:21) +[x] implement end of battle condition (issued on 19:02:21, done on 19:02:21) +[x] implement battery calculation (issued on 18:02:21, done on 19:02:21) +[x] implement component levels (issued on 18:02:21, done on 19:02:21) +[x] implement rm unit (issued on 18:02:21, done on 18:02:21) +[x] implement armor calculation (issued on 18:02:21, done on 18:02:21) +[x] implement augment calculations (issued on 18:02:21, done on 18:02:21) +[x] implement augment hud view (issued on 18:02:21, done on 18:02:21) bugs: @@ -52,6 +52,77 @@ view from 18:02:21 to the end: details: +implement cost function: + oh boy + cost of a component = c_c + cost of a unit = c_u + cost of an army = c_a + c_a = sum {i=0..ar->uslen-1} c_u[i] + c_u = sum {comp j} c_c[j] -> maybe unfair, does not consider synergies + = sum of stats -> nerfs synergies, confusing and hard to calculate + c_c = sum of abs attributes -> ez but trash + = basis function of effectiveness of attribute -> cool + cost of unit is tricky + if i consider the simple sum of c_c, the augment bonuses are left out + gun cost 10, better ammo 10, total cost is 20. + otherwise every unit is calculated ad hoc. + gun cost 10, better ammo 10, dps is way better so total cost is 30 + -> i'm using the cost by unit final stats, it's better but harder + what is effectiveness, i have to find formulas + . effectiveness of a weapon + + total damage output + + range multiplies total damage + + aoe multiplies total damage + + knockback fixed cost + + stun fixed cost + - upkeep as a % of total cost + - charge per shot required + - weight as a % of total cost + . effectiveness of a chassis + + slots (different by slot type) + + speed + + hp + + weight_max + - upkeep + . effectiveness of a battery + + capacity + + recharge based on capacity + - weight as a % of total cost + . effectiveness of an armor component + + armor amount + - weight + - upkeep + . effectiveness of an augment + + all add effects, weighted accordingly + - weight as a % of total cost + . effectiveness of a controller + + base cost by complexity of strategy (so base cost is defined in data) + - upkeep + multiplicative constants (buy with weight): + . 1 total damage per turn = 2 weight + . 1 armor = 2 weight + . 10 hp = 1 weight + . 100 capacity = 1 weight + . 1 upkeep = 1 weight + (they differ in the implementation) + basis function: (to modulate the increase in cost, double effectiveness, maybe 4*cost, or 70*cost) + . linear y=x + . log y=log(x) + . exp y=exp(x) + . other maybe? + cost of a unit: (info_unit_get_cost) + . sum of cost of components but with the final modified values + i can also price components based on no bonuses to provide a price gauge -> meh + i think it's better to focus on the cost indipendently of weight for now + +implement end of battle condition: + i was thinking i can detect the end as no damage is being dealt in 10 turns + and no movement takes place + another condition is that the enemy has no units, but it's not necessary. + end <==> no movement or fire + have to do transition from battle to editor, done ez +-> done + implement components level: could do it globally, every level is +5%atk and +10% cost could set each weapon stat as a vector, v[level] is the stat @@ -67,6 +138,8 @@ implement components level: . design with a lot more variables in play before writing 10000 numbers i should design, or autogenerate them settled on 3 lvls, autogenerated with python + missing hud! +-> done, also some testing implement rm unit: -> done, paper note solution diff --git a/gst/gst.c b/gst/gst.c index 09f3c1c..a97b4f9 100644 --- a/gst/gst.c +++ b/gst/gst.c @@ -66,6 +66,24 @@ void gst_tobattle (gamestate *gst) { gst->starttime = FLT_MAX; gst->turn = 0; gst->coveredtime = 0; + gst->turn_until_finish = 5; + gst->over = 0; +} + +void gst_toeditor(gamestate *gst) { + gst->playernum = 1; +} + +int gst_check_victory (gamestate *gst) { + int counts[gst->playernum], max=-1, imax = -1; + for (int i=0; iar.uslen; i++) { + counts[gst->ar.us[i].owner] ++; + if (counts[gst->ar.us[i].owner] > max) { + imax = gst->ar.us[i].owner; + max = counts[gst->ar.us[i].owner]; + } + } + return imax; } void gst_process (gamestate *gst, infos *info, float t) { @@ -76,8 +94,15 @@ void gst_process (gamestate *gst, infos *info, float t) { gst->turn ++; map *m; army *ar; gst_get_maparmy(gst, &m, &ar); - army_move(info, ar, m); - army_fire(info, ar, m); + int move = army_move(info, ar, m); + int fire = army_fire(info, ar, m); army_upkeep(info, ar, m); + printf("%d, %d\n", move, fire); + if (move == 0 && fire == 0) { + gst->turn_until_finish--; + } else { gst->turn_until_finish = 5; } + if (gst->turn_until_finish <= 0) { + gst->over = 1; + } } } \ No newline at end of file diff --git a/gst/gst.h b/gst/gst.h index 8acb699..171e213 100644 --- a/gst/gst.h +++ b/gst/gst.h @@ -19,12 +19,15 @@ typedef struct { float coveredtime; int turn; float turnspeed; + int turn_until_finish; + int over; } gamestate; void gst_init (gamestate *gst); void gst_destroy (gamestate *gst); void gst_get_maparmy(gamestate *gst, map **m, army **ar); void gst_tobattle (gamestate *gst); +void gst_toeditor (gamestate *gst); void gst_process (gamestate *gst, infos *info, float t); #endif \ No newline at end of file diff --git a/gst/info.c b/gst/info.c index 985b7dd..15c7c0b 100644 --- a/gst/info.c +++ b/gst/info.c @@ -130,8 +130,10 @@ float info_unit_get_health(infos *info, info_unit *u) { sum += info->augs[u->augs[i]].add_hp[lvl]; } } - sum += info->chassis[u->chassis].hp[lc]; - return sum; + float mult = (1 + sum/100.0f); + if (mult < 0) mult = 0; + float ret = info->chassis[u->chassis].hp[lc] * mult; + return ret; } float info_unit_get_speed(infos *info, info_unit *u) { @@ -175,6 +177,39 @@ float info_unit_get_damage_target (infos *info, info_unit *u, int w, return damage * mult; } +float info_unit_get_aoe (infos *info, info_unit *u, int w) { + int lc = u->levels[LEVEL_CHASSIS]; + float sum = 0; + for(int i=0; i<16; i++) { + if (u->augs[i] != -1 && info->chassis[u->chassis].slot_aug[lc]) { + int lvl = u->levels[LEVEL_AUGS+i]; + //sum += info->augs[u->augs[i]].add_aoe[lvl]; + } + } + int lw = u->levels[LEVEL_WEAPONS+w]; + float dam = info->weapons[u->weapons[w]].aoe[lw] + sum; + return dam; +} + +float info_unit_get_knockback (infos *info, info_unit *u, int w) { + int lc = u->levels[LEVEL_CHASSIS]; + float sum = 0; + for(int i=0; i<16; i++) { + if (u->augs[i] != -1 && info->chassis[u->chassis].slot_aug[lc]) { + int lvl = u->levels[LEVEL_AUGS+i]; + //sum += info->augs[u->augs[i]].add_knockback[lvl]; + } + } + int lw = u->levels[LEVEL_WEAPONS+w]; + float dam = info->weapons[u->weapons[w]].knockback[lw] + sum; + return dam; +} + +float info_unit_get_stun (infos *info, info_unit *u, int w) { + // TODO + return 0; +} + float info_unit_get_cooldown(infos *info, info_unit *u, int w) { int lc = u->levels[LEVEL_CHASSIS]; float sum = 0; @@ -228,6 +263,53 @@ float info_unit_get_armor(infos *info, info_unit *u, int d) { return sum; } +float info_unit_get_cost (infos *info, info_unit *u) { + // see design/notes.txt:implement cost function + float sum = 0; + int lc = u->levels[LEVEL_CHASSIS]; + info_chassis *chassis = info->chassis+u->chassis; + float sumchassis = 0; + sumchassis += powf(2, chassis->slot_weapon[lc])*20; + sumchassis += powf(2, chassis->slot_armor[lc])*10; + sumchassis += powf(2, chassis->slot_aug[lc])*5; + sumchassis += chassis->weight_max[lc]/5; + sumchassis += chassis->hp[lc]/20; + sumchassis += chassis->speed[lc]*32; + sum += sumchassis; + if (u->battery != -1) { + int lb = u->levels[LEVEL_BATTERY]; + info_battery *battery = info->batteries+u->battery; + float sumbattery = 0; + sumbattery += battery->capacity[lb]; + sum += sumbattery; + } + for(int i=0; i<8; i++) { + int lw = u->levels[LEVEL_WEAPONS+i]; + int la = u->levels[LEVEL_ARMOR+i]; + if (u->weapons[i] != -1 && islot_weapon[lc]) { + info_weapon *weapon = info->weapons+u->weapons[i]; + float sumweap = 0; + float dam = info_unit_get_damage(info, u, i); + float cool = info_unit_get_cooldown(info, u, i); + float damtot = dam / cool; + float aoe = info_unit_get_aoe(info, u, i); + float knockback = info_unit_get_knockback(info, u, i); + float stun = info_unit_get_stun(info, u, i); + float mult = 1+aoe*5 + 10; + damtot = damtot*mult; + damtot += knockback * 20 + stun * 50; + sumweap = damtot; + sum += sumweap; + } + } + for(int t=0; t<7; t++) { + float armortot = info_unit_get_armor(info, u, t) * 3; + sum += armortot; + } + + return sum; +} + void weapon_init (info_weapon *w) { strcpy(w->name, "nameless"); diff --git a/gst/info.h b/gst/info.h index 8e7fdaf..9219f8b 100644 --- a/gst/info.h +++ b/gst/info.h @@ -116,6 +116,7 @@ float info_unit_get_damage_target(infos *info, info_unit *u, int w, float info_unit_get_cooldown(infos *info, info_unit *u, int w); float info_unit_get_range(infos *info, info_unit *u, int w); float info_unit_get_armor(infos *info, info_unit *u, int d); +float info_unit_get_cost(infos *info, info_unit *u); void info_load (infos *info); diff --git a/gst/units.c b/gst/units.c index dbf177b..b247e3c 100644 --- a/gst/units.c +++ b/gst/units.c @@ -168,18 +168,18 @@ int army_move_step (infos *info, army *ar, map *m) { else return 1; } -void army_move (infos *info, army *ar, map *m) { +int army_move (infos *info, army *ar, map *m) { for (int i=0; iuslen; i++) { ar->us[i].move_points += info_unit_get_speed(info, &ar->us[i].info); } - int iter = 0, finished = 0; + int iter = 0, finished = army_move_step(info, ar, m); for (; iter<5 && !finished; iter++) { finished = army_move_step(info, ar, m); } - //printf("stepped %d %d\n", iter, finished); + return iter; } -void army_fire (infos *info, army *ar, map *m) { +int army_fire (infos *info, army *ar, map *m) { for (int i=0; iuslen; i++) { unit *u = ar->us+i; int lw = u->info.levels[LEVEL_CHASSIS]; @@ -216,6 +216,7 @@ void army_fire (infos *info, army *ar, map *m) { unit_dead(ar, m, dmgs[i].u); } } + return dmgslen; } void army_upkeep (infos *info, army *ar, map *m) { diff --git a/gst/units.h b/gst/units.h index 615eaa7..8e78d8d 100644 --- a/gst/units.h +++ b/gst/units.h @@ -34,8 +34,8 @@ void army_grid_init(army *ar); void army_init (army *ar, map *m); void army_destory(army *ar); void army_spawn (army *ar, map *m, unit u); -void army_move (infos *info, army *ar, map *m); -void army_fire (infos *info, army *ar, map *m); +int army_move (infos *info, army *ar, map *m); +int army_fire (infos *info, army *ar, map *m); void army_upkeep (infos *info, army *ar, map *m); #endif \ No newline at end of file diff --git a/hud/hud.c b/hud/hud.c index 2c73288..7906c84 100644 --- a/hud/hud.c +++ b/hud/hud.c @@ -314,6 +314,19 @@ void hud_process_form_new_unit (graphic_settings *gs, hud *h, MKb *mkb, } } +void hud_process_overlay_battle (graphic_settings *gs, hud *h, MKb *mkb, + infos *info, army *ar, map *m, txtd *t, gamestate *gst, + Mix_Chunk *sounds[]) +{ + if (gst->over == 1) { + h->state = 0; + gst->state = 0; + gst->cam[0] = -gs->resx/2+gst->map_editor.sx*gst->map_editor.ts/2; + gst->cam[1] = -gs->resy/2+gst->map_editor.sy*gst->map_editor.ts/2; + gst_toeditor(gst); + } +} + void hud_process_overlay_game (graphic_settings *gs, hud *h, MKb *mkb, infos *info, army *ar, map *m, txtd *t, gamestate *gst, net_client *netc, net_server *nets, Mix_Chunk *sounds[]) @@ -339,7 +352,7 @@ void hud_process_overlay_game (graphic_settings *gs, hud *h, MKb *mkb, gst_tobattle(gst); gst->cam[0] = -gs->resx/2+gst->map_battle.sx*gst->map_battle.ts/2; gst->cam[1] = -gs->resy/2+gst->map_battle.sy*gst->map_battle.ts/2; - h->state = 4; + h->state = 3; } } } @@ -355,7 +368,7 @@ void hud_process_overlay_game (graphic_settings *gs, hud *h, MKb *mkb, gst_tobattle(gst); gst->cam[0] = -gs->resx/2+gst->map_battle.sx*gst->map_battle.ts/2; gst->cam[1] = -gs->resy/2+gst->map_battle.sy*gst->map_battle.ts/2; - h->state = 4; + h->state = 3; } } @@ -380,7 +393,7 @@ void hud_process_overlay_game (graphic_settings *gs, hud *h, MKb *mkb, gst->cam[0] = -gs->resx/2+gst->map_battle.sx*gst->map_battle.ts/2; gst->cam[1] = -gs->resy/2+gst->map_battle.sy*gst->map_battle.ts/2; h->og.battle_state = 3; - h->state = 4; + h->state = 3; Mix_PlayChannel( -1, sounds[SOUND_SUCCESS], 0 ); } @@ -522,9 +535,13 @@ void hud_process (graphic_settings *gs, hud *h, MKb *mkb, hud_process_overlay_game(gs, h, mkb, info, ar, m, t, gst, netc, nets, sounds); break; - case 1: hud_process_form_new_unit(gs, h, mkb, info, ar, m, t, - sounds); break; - case 2: hud_process_sel(gs, h, mkb, info, ar, m, t, sounds); break; + case 1: hud_process_form_new_unit(gs, h, mkb, info, ar, m, t, sounds); + break; + case 2: hud_process_sel(gs, h, mkb, info, ar, m, t, sounds); + break; + case 3: hud_process_overlay_battle(gs, h, mkb, info, ar, m, t, gst, + sounds); + break; } } diff --git a/hud/hud_views.c b/hud/hud_views.c index 4828275..046ba53 100644 --- a/hud/hud_views.c +++ b/hud/hud_views.c @@ -14,6 +14,12 @@ void render_view_stats (SDL_Renderer* rend, txtd *t, int px, int py, render_text_scaled(rend, sname, pname, t, 2); h += 35; + float cost = info_unit_get_cost(info, tm); + float pcost[2] = { px+10, py+h }; + char scost[64]; sprintf(scost, "COST: %.2f", cost); + render_text_scaled(rend, scost, pcost, t, 1); + h += 20; + float calcweight = info_unit_get_weight(info, tm); float maxweight = info->chassis[tm->chassis].weight_max[ tm->levels[LEVEL_CHASSIS]]; -- cgit v1.2.3-54-g00ecf