123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <assert.h>
- const char *wnames[3] = { "sword", "bomb", "arrow" };
- struct warrior;
- struct headquarter;
- typedef struct
- {
- const char *tname;
- int tid;
- int initlife;
- int attack;
- void (*init)(struct headquarter *hq, struct warrior *me);
- void (*init_print)(struct warrior *me);
- } warrior_type;
- struct warrior
- {
- const warrior_type *wtype;
- int number;
- int life;
- int attack;
- int no_weapons[3]; /* number of sword, bomb, arrow */
- int used_arrow;
- double morale;
- int loyalty;
- };
- struct headquarter
- {
- const char *name;
- int life;
- int nsoldiers;
- int seqnum; /* the next worrier to made */
- int counts[5];
- int stopped;
- };
- #define DEFW(_id, name) \
- void init_##name(struct headquarter *, struct warrior *); \
- void init_print_##name(struct warrior *); \
- warrior_type name = { \
- .tname = #name, \
- .tid = _id, \
- .init = init_##name, \
- .init_print = init_print_##name \
- }
- #define DRAGON 0
- #define NINJA 1
- #define ICEMAN 2
- #define LION 3
- #define WOLF 4
- DEFW(DRAGON,dragon);
- DEFW(NINJA,ninja);
- DEFW(ICEMAN,iceman);
- DEFW(LION,lion);
- DEFW(WOLF,wolf);
- warrior_type *all_wtypes[5] = {
- &dragon, &ninja, &iceman, &lion, &wolf
- };
- /* new_warrior: build a warrior of type idx */
- static struct warrior *new_warrior(struct headquarter *hq, int idx)
- {
- struct warrior *me = (struct warrior*)malloc(sizeof(struct warrior));
- memset(me->no_weapons, 0, sizeof(me->no_weapons));
- me->used_arrow = 0;
- me->wtype = all_wtypes[idx];
- me->number = hq->nsoldiers;
- me->life = me->wtype->initlife;
- me->attack = me->wtype->attack;
- me->wtype->init(hq, me);
- return me;
- }
- void init_dragon(struct headquarter *hq, struct warrior *me)
- {
- me->no_weapons[me->number % 3] ++;
- me->morale = (double)(hq->life) / dragon.initlife;
- }
- void init_ninja(struct headquarter *hq, struct warrior *me)
- {
- me->no_weapons[me->number % 3] ++;
- me->no_weapons[(me->number + 1) % 3] ++;
- }
- void init_iceman(struct headquarter *hq, struct warrior *me)
- {
- me->no_weapons[me->number % 3] ++;
- }
- void init_lion(struct headquarter *hq, struct warrior *me)
- {
- me->no_weapons[me->number % 3] ++;
- me->loyalty = hq->life;
- }
- void init_wolf(struct headquarter *hq, struct warrior *me)
- {
- }
- void init_print_dragon(struct warrior *me)
- {
- }
- void init_print_ninja(struct warrior *me)
- {
- }
- void init_print_iceman(struct warrior *me)
- {
- }
- void init_print_lion(struct warrior *me)
- {
- printf("It's loyalty is %d\n", me->loyalty);
- }
- void init_print_wolf(struct warrior *me) {}
- /* headquarter */
- struct headquarter hq[2];
- /* the creation sequence of dragon, ninja, iceman, lion, wolf */
- int seqs[2][5] = {
- { 2, 3, 4, 1, 0 },
- { 3, 0, 1, 2, 4 }
- };
- const char *colors[2] = { "red", "blue" };
- static void hq_init()
- {
- memset(hq, 0, sizeof(hq));
- hq[0].name = colors[0];
- hq[1].name = colors[1];
- }
- /* hq_make_warrior: try to make a warrior for headquarter n
- * if success, return the created warrior
- * otherwise return NULL */
- struct warrior * hq_make_warrior(int n)
- {
- assert(n<2);
- int idx = hq[n].seqnum;
- int sol = seqs[n][idx];
- hq[n].seqnum = (idx + 1) % 5;
- if (hq[n].life >= all_wtypes[sol]->initlife) {
- hq[n].life -= all_wtypes[sol]->initlife;
- hq[n].nsoldiers ++;
- hq[n].counts[sol] ++;
- return new_warrior(&hq[n], sol);
- }
- return NULL;
- }
- struct City
- {
- // int number;
- struct warrior *red_warrior;
- struct warrior *blue_warrior;
- };
- int hour;
- int total_time;
- int war_stopped;
- int ncities;
- int loy_dec; /* for lions */
- struct City *cities;
- void war_init(int n)
- {
- hour = 0;
- war_stopped = 0;
- ncities = n + 2;
- cities = (struct City*)malloc(sizeof(struct City)*ncities);
- for (int i=0; i<ncities; i++)
- cities[i].red_warrior = cities[i].blue_warrior = NULL;
- }
- void war_cleanup()
- {
- for (int i=0; i<ncities; i++) {
- if (cities[i].red_warrior)
- free(cities[i].red_warrior);
- if (cities[i].blue_warrior)
- free(cities[i].blue_warrior);
- }
- free(cities);
- }
- /* simulate events */
- static void _00_warrior_born()
- {
- for (int j = 0; j < 2; j++) {
- if (!hq[j].stopped) {
- struct warrior * made_warrior = hq_make_warrior(j);
- if (made_warrior != NULL) {
- printf("%03d:00 %s %s %d born\n",
- hour, colors[j], made_warrior->wtype->tname,
- hq[j].nsoldiers);
- made_warrior->wtype->init_print(made_warrior);
- if (j==0)
- cities[0].red_warrior = made_warrior;
- else
- cities[ncities-1].blue_warrior = made_warrior;
- } else {
- hq[j].stopped = 1;
- }
- }
- }
- }
- static void _05_lion_runs()
- {
- const char *s = "%03d:05 %s lion %d ran away\n";
- for (int i = 0; i < ncities; i++) {
- struct warrior *redw = cities[i].red_warrior;
- struct warrior *bluew = cities[i].blue_warrior;
- if (redw != NULL && redw->wtype->tid == LION && i != ncities - 1
- && redw->loyalty <= 0) {
- printf(s, hour, "red", redw->number);
- free(redw);
- cities[i].red_warrior = NULL;
- }
- if (bluew != NULL && bluew->wtype->tid == LION && i != 0
- && bluew->loyalty <= 0) {
- printf(s, hour, "blue", bluew->number);
- free(bluew);
- cities[i].blue_warrior = NULL;
- }
- }
- }
- static void _10_warrior_walks()
- {
- const char *s1 = "%03d:10 %s %s %d reached %s headquarter with %d elements and force %d\n";
- const char *s2 = "%03d:10 %s headquarter was taken\n";
- const char *walk = "%03d:10 %s %s %d marched to city %d with %d elements and force %d\n";
- for (int i = ncities-1; i > 0; i--) {
- cities[i].red_warrior = cities[i-1].red_warrior;
- if (cities[i].red_warrior != NULL) {
- if (cities[i].red_warrior->wtype->tid == LION)
- cities[i].red_warrior->loyalty -= loy_dec;
- if (cities[i].red_warrior->wtype->tid == ICEMAN)
- cities[i].red_warrior->life -= cities[i].red_warrior->life / 10;
- }
- }
- cities[0].red_warrior = NULL;
- for (int i = 0; i < ncities-1; i++) {
- cities[i].blue_warrior = cities[i+1].blue_warrior;
- if (cities[i].blue_warrior != NULL) {
- if (cities[i].blue_warrior->wtype->tid == LION)
- cities[i].blue_warrior->loyalty -= loy_dec;
- if (cities[i].blue_warrior->wtype->tid == ICEMAN)
- cities[i].blue_warrior->life -= cities[i].blue_warrior->life / 10;
- }
- }
- cities[ncities-1].blue_warrior = NULL;
- for (int i = 1; i < ncities - 1; i++) {
- struct warrior *redw = cities[i].red_warrior;
- struct warrior *bluew = cities[i].blue_warrior;
- if (redw)
- printf(walk, hour, "red", redw->wtype->tname, redw->number, i,
- redw->life, redw->attack);
- if (bluew)
- printf(walk, hour, "blue", bluew->wtype->tname, bluew->number, i,
- bluew->life, bluew->attack);
- }
- struct warrior *bluew = cities[0].blue_warrior;
- struct warrior *redw = cities[ncities-1].red_warrior;
- if (bluew != NULL) {
- printf(s1, hour, "blue", bluew->wtype->tname, bluew->number, "red",
- bluew->life, bluew->attack);
- printf(s2, hour, "red");
- war_stopped = 1;
- }
- if (redw != NULL) {
- printf(s1, hour, "red", redw->wtype->tname, redw->number, "blue",
- redw->life, redw->attack);
- printf(s2, hour, "blue");
- war_stopped = 1;
- }
- }
- static unsigned char rob_weapons(struct warrior *me, struct warrior *you, int roball)
- {
- int no_my_weapons = me->no_weapons[0] + me->no_weapons[1] + me->no_weapons[2];
- for (int i=0; i<3 && no_my_weapons < 10; i++) {
- if (you->no_weapons[i]==0)
- continue;
- int no_rob;
- if (10 - no_my_weapons >= you->no_weapons[i])
- no_rob = you->no_weapons[i];
- else
- no_rob = 10 - no_my_weapons;
- no_my_weapons += no_rob;
- me->no_weapons[i] += no_rob;
- if (i == 2) {
- /* unused arrows first */
- int unused = you->no_weapons[2] - you->used_arrow;
- if (unused < no_rob) {
- int rob_used = no_rob - unused;
- me->used_arrow += rob_used;
- you->used_arrow -= rob_used;
- } /* else nothing changed */
- }
- you->no_weapons[i] -= no_rob;
- if (!roball)
- return (no_rob << 4) | i;
- }
- return 0;
- }
- static void _35_wolf_rob_weapons()
- {
- const char *s = "%03d:35 %s wolf %d took %d %s from %s %s %d in city %d\n";
- unsigned char res;
- for (int i = 1; i < ncities-1; i++) {
- struct warrior *redw = cities[i].red_warrior;
- struct warrior *bluew = cities[i].blue_warrior;
- if (redw == NULL || bluew == NULL)
- continue;
- if (redw->wtype->tid == WOLF && bluew->wtype->tid != WOLF) {
- res = rob_weapons(redw, bluew, 0);
- if (res) {
- printf(s, hour, "red", redw->number, res>>4, wnames[res&0xf], "blue",
- bluew->wtype->tname, bluew->number, i);
- }
- } else if (redw->wtype->tid != WOLF && bluew->wtype->tid == WOLF) {
- res = rob_weapons(bluew, redw, 0);
- if (res) {
- printf(s, hour, "blue", bluew->number, res>>4, wnames[res&0xf], "red",
- redw->wtype->tname, redw->number, i);
- }
- }
- }
- }
- /* do_attack: attack the opponent with weapon index stored in w
- , return 1 if state changes */
- static int do_attack(struct warrior *me, struct warrior *you, int *w)
- {
- int idx = *w;
- int total = me->no_weapons[0]+me->no_weapons[1]+me->no_weapons[2];
- int attack;
- if (total == 0)
- return 0;
- if (idx < me->no_weapons[0]) {
- /* use a sword */
- attack = me->attack * 2 / 10;
- you->life -= attack;
- idx++;
- if (idx < total)
- *w = idx;
- else
- *w = 0;
- if (attack > 0)
- return 1;
- else
- return 0;
- } else if (idx < me->no_weapons[0]+me->no_weapons[1]) {
- /* use a bomb */
- attack = me->attack * 2 / 5;
- you->life -= attack;
- if (me->wtype->tid != NINJA)
- me->life -= attack/2;
- me->no_weapons[1]--;
- total--;
- if (idx == total)
- *w = 0;
- return 1;
- } else {
- /* use an arrow */
- attack = me->attack * 3 / 10;
- you->life -= attack;
- if (me->used_arrow > 0) {
- me->used_arrow--;
- me->no_weapons[2]--;
- total--;
- } else {
- me->used_arrow++;
- idx++;
- }
- if (idx == total)
- *w = 0;
- return 1;
- }
- }
- static void
- printwin(int win, int city, struct warrior *me, struct warrior *you)
- {
- const char *wins = "%03d:40 %s %s %d killed %s %s %d in city %d remaining %d elements\n";
- const char *yell = "%03d:40 %s dragon %d yelled in city %d\n";
- printf(wins, hour, colors[win], me->wtype->tname, me->number, colors[1-win],
- you->wtype->tname, you->number, city, me->life);
- if (me->wtype->tid == DRAGON)
- printf(yell, hour, colors[win], me->number, city);
- }
- static void sim_battle(int city)
- {
- const char *both = "%03d:40 both %s %s %d and %s %s %d %s in city %d\n";
- struct warrior *redw = cities[city].red_warrior;
- struct warrior *bluew = cities[city].blue_warrior;
- char reds_turn = city&1;
- int next_weapon[2] = {0, 0};
- int changed;
- do {
- changed = 0;
- if (reds_turn && redw->life>0 && bluew->life>0)
- changed = do_attack(redw, bluew, &next_weapon[0]);
- if (redw->life>0 && bluew->life>0)
- changed |= do_attack(bluew, redw, &next_weapon[1]);
- reds_turn = 1;
- } while (changed);
- if (redw->life>0 && bluew->life<=0) {
- printwin(0, city, redw, bluew);
- rob_weapons(redw, bluew, 1);
- } else if (redw->life<=0 && bluew->life>0) {
- printwin(1, city, bluew, redw);
- rob_weapons(bluew, redw, 1);
- } else if (redw->life<=0 && bluew->life<=0) {
- printf(both, hour, "red", redw->wtype->tname, redw->number,
- "blue", bluew->wtype->tname, bluew->number, "died", city);
- } else {
- printf(both, hour, "red", redw->wtype->tname, redw->number,
- "blue", bluew->wtype->tname, bluew->number, "were alive", city);
- }
- if (redw->life<=0) {
- cities[city].red_warrior = NULL;
- free(redw);
- }
- if (bluew->life<=0) {
- cities[city].blue_warrior = NULL;
- free(bluew);
- }
- }
- static void _40_battle()
- {
- for (int i=1; i<ncities-1; i++)
- if (cities[i].red_warrior && cities[i].blue_warrior)
- sim_battle(i);
- }
- static void _50_report_elements()
- {
- const char *s = "%03d:50 %d elements in %s headquarter\n";
- printf(s, hour, hq[0].life, "red");
- printf(s, hour, hq[1].life, "blue");
- }
- static void _55_report_weapons()
- {
- const char *s = "%03d:55 %s %s %d has %d sword %d bomb %d arrow and %d elements\n";
- for (int i = 0; i < ncities; i++) {
- struct warrior *redw = cities[i].red_warrior;
- struct warrior *bluew = cities[i].blue_warrior;
- if (redw)
- printf(s, hour, "red", redw->wtype->tname, redw->number, redw->no_weapons[0],
- redw->no_weapons[1], redw->no_weapons[2], redw->life);
- if (bluew)
- printf(s, hour, "blue", bluew->wtype->tname, bluew->number, bluew->no_weapons[0],
- bluew->no_weapons[1], bluew->no_weapons[2], bluew->life);
- }
- }
- void simulate_an_hour()
- {
- if (total_time >= 0)
- _00_warrior_born();
- total_time -= 5;
- if (total_time >= 0)
- _05_lion_runs();
- total_time -= 5;
- if (total_time >= 0)
- _10_warrior_walks();
- if (!war_stopped) {
- total_time -= 25;
- if (total_time >= 0)
- _35_wolf_rob_weapons();
- total_time -= 5;
- if (total_time >= 0)
- _40_battle();
- total_time -= 10;
- if (total_time >= 0)
- _50_report_elements();
- total_time -= 5;
- if (total_time >= 0)
- _55_report_weapons();
- total_time -= 5;
- hour++;
- }
- }
- /* end of simulate events */
- int main(void)
- {
- int ncases;
- scanf("%d", &ncases);
- for (int i=1; i<=ncases; i++) {
- hq_init();
- printf("Case:%d\n", i);
- int M, N, K, T;
- scanf("%d%d%d%d", &M, &N, &K, &T);
- hq[0].life = hq[1].life = M;
- war_init(N);
- loy_dec = K;
- total_time = T;
- for (int j=0; j<5; j++)
- scanf("%d", &all_wtypes[j]->initlife);
- for (int j=0; j<5; j++)
- scanf("%d", &all_wtypes[j]->attack);
- while (total_time >= 0 && !war_stopped)
- simulate_an_hour();
- }
- }
|