wow-03.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <assert.h>
  5. const char *wnames[3] = { "sword", "bomb", "arrow" };
  6. struct warrior;
  7. struct headquarter;
  8. typedef struct
  9. {
  10. const char *tname;
  11. int tid;
  12. int initlife;
  13. int attack;
  14. void (*init)(struct headquarter *hq, struct warrior *me);
  15. void (*init_print)(struct warrior *me);
  16. } warrior_type;
  17. struct warrior
  18. {
  19. const warrior_type *wtype;
  20. int number;
  21. int life;
  22. int attack;
  23. int no_weapons[3]; /* number of sword, bomb, arrow */
  24. int used_arrow;
  25. double morale;
  26. int loyalty;
  27. };
  28. struct headquarter
  29. {
  30. const char *name;
  31. int life;
  32. int nsoldiers;
  33. int seqnum; /* the next worrier to made */
  34. int counts[5];
  35. int stopped;
  36. };
  37. #define DEFW(_id, name) \
  38. void init_##name(struct headquarter *, struct warrior *); \
  39. void init_print_##name(struct warrior *); \
  40. warrior_type name = { \
  41. .tname = #name, \
  42. .tid = _id, \
  43. .init = init_##name, \
  44. .init_print = init_print_##name \
  45. }
  46. #define DRAGON 0
  47. #define NINJA 1
  48. #define ICEMAN 2
  49. #define LION 3
  50. #define WOLF 4
  51. DEFW(DRAGON,dragon);
  52. DEFW(NINJA,ninja);
  53. DEFW(ICEMAN,iceman);
  54. DEFW(LION,lion);
  55. DEFW(WOLF,wolf);
  56. warrior_type *all_wtypes[5] = {
  57. &dragon, &ninja, &iceman, &lion, &wolf
  58. };
  59. /* new_warrior: build a warrior of type idx */
  60. static struct warrior *new_warrior(struct headquarter *hq, int idx)
  61. {
  62. struct warrior *me = (struct warrior*)malloc(sizeof(struct warrior));
  63. memset(me->no_weapons, 0, sizeof(me->no_weapons));
  64. me->used_arrow = 0;
  65. me->wtype = all_wtypes[idx];
  66. me->number = hq->nsoldiers;
  67. me->life = me->wtype->initlife;
  68. me->attack = me->wtype->attack;
  69. me->wtype->init(hq, me);
  70. return me;
  71. }
  72. void init_dragon(struct headquarter *hq, struct warrior *me)
  73. {
  74. me->no_weapons[me->number % 3] ++;
  75. me->morale = (double)(hq->life) / dragon.initlife;
  76. }
  77. void init_ninja(struct headquarter *hq, struct warrior *me)
  78. {
  79. me->no_weapons[me->number % 3] ++;
  80. me->no_weapons[(me->number + 1) % 3] ++;
  81. }
  82. void init_iceman(struct headquarter *hq, struct warrior *me)
  83. {
  84. me->no_weapons[me->number % 3] ++;
  85. }
  86. void init_lion(struct headquarter *hq, struct warrior *me)
  87. {
  88. me->no_weapons[me->number % 3] ++;
  89. me->loyalty = hq->life;
  90. }
  91. void init_wolf(struct headquarter *hq, struct warrior *me)
  92. {
  93. }
  94. void init_print_dragon(struct warrior *me)
  95. {
  96. }
  97. void init_print_ninja(struct warrior *me)
  98. {
  99. }
  100. void init_print_iceman(struct warrior *me)
  101. {
  102. }
  103. void init_print_lion(struct warrior *me)
  104. {
  105. printf("It's loyalty is %d\n", me->loyalty);
  106. }
  107. void init_print_wolf(struct warrior *me) {}
  108. /* headquarter */
  109. struct headquarter hq[2];
  110. /* the creation sequence of dragon, ninja, iceman, lion, wolf */
  111. int seqs[2][5] = {
  112. { 2, 3, 4, 1, 0 },
  113. { 3, 0, 1, 2, 4 }
  114. };
  115. const char *colors[2] = { "red", "blue" };
  116. static void hq_init()
  117. {
  118. memset(hq, 0, sizeof(hq));
  119. hq[0].name = colors[0];
  120. hq[1].name = colors[1];
  121. }
  122. /* hq_make_warrior: try to make a warrior for headquarter n
  123. * if success, return the created warrior
  124. * otherwise return NULL */
  125. struct warrior * hq_make_warrior(int n)
  126. {
  127. assert(n<2);
  128. int idx = hq[n].seqnum;
  129. int sol = seqs[n][idx];
  130. hq[n].seqnum = (idx + 1) % 5;
  131. if (hq[n].life >= all_wtypes[sol]->initlife) {
  132. hq[n].life -= all_wtypes[sol]->initlife;
  133. hq[n].nsoldiers ++;
  134. hq[n].counts[sol] ++;
  135. return new_warrior(&hq[n], sol);
  136. }
  137. return NULL;
  138. }
  139. struct City
  140. {
  141. // int number;
  142. struct warrior *red_warrior;
  143. struct warrior *blue_warrior;
  144. };
  145. int hour;
  146. int total_time;
  147. int war_stopped;
  148. int ncities;
  149. int loy_dec; /* for lions */
  150. struct City *cities;
  151. void war_init(int n)
  152. {
  153. hour = 0;
  154. war_stopped = 0;
  155. ncities = n + 2;
  156. cities = (struct City*)malloc(sizeof(struct City)*ncities);
  157. for (int i=0; i<ncities; i++)
  158. cities[i].red_warrior = cities[i].blue_warrior = NULL;
  159. }
  160. void war_cleanup()
  161. {
  162. for (int i=0; i<ncities; i++) {
  163. if (cities[i].red_warrior)
  164. free(cities[i].red_warrior);
  165. if (cities[i].blue_warrior)
  166. free(cities[i].blue_warrior);
  167. }
  168. free(cities);
  169. }
  170. /* simulate events */
  171. static void _00_warrior_born()
  172. {
  173. for (int j = 0; j < 2; j++) {
  174. if (!hq[j].stopped) {
  175. struct warrior * made_warrior = hq_make_warrior(j);
  176. if (made_warrior != NULL) {
  177. printf("%03d:00 %s %s %d born\n",
  178. hour, colors[j], made_warrior->wtype->tname,
  179. hq[j].nsoldiers);
  180. made_warrior->wtype->init_print(made_warrior);
  181. if (j==0)
  182. cities[0].red_warrior = made_warrior;
  183. else
  184. cities[ncities-1].blue_warrior = made_warrior;
  185. } else {
  186. hq[j].stopped = 1;
  187. }
  188. }
  189. }
  190. }
  191. static void _05_lion_runs()
  192. {
  193. const char *s = "%03d:05 %s lion %d ran away\n";
  194. for (int i = 0; i < ncities; i++) {
  195. struct warrior *redw = cities[i].red_warrior;
  196. struct warrior *bluew = cities[i].blue_warrior;
  197. if (redw != NULL && redw->wtype->tid == LION && i != ncities - 1
  198. && redw->loyalty <= 0) {
  199. printf(s, hour, "red", redw->number);
  200. free(redw);
  201. cities[i].red_warrior = NULL;
  202. }
  203. if (bluew != NULL && bluew->wtype->tid == LION && i != 0
  204. && bluew->loyalty <= 0) {
  205. printf(s, hour, "blue", bluew->number);
  206. free(bluew);
  207. cities[i].blue_warrior = NULL;
  208. }
  209. }
  210. }
  211. static void _10_warrior_walks()
  212. {
  213. const char *s1 = "%03d:10 %s %s %d reached %s headquarter with %d elements and force %d\n";
  214. const char *s2 = "%03d:10 %s headquarter was taken\n";
  215. const char *walk = "%03d:10 %s %s %d marched to city %d with %d elements and force %d\n";
  216. for (int i = ncities-1; i > 0; i--) {
  217. cities[i].red_warrior = cities[i-1].red_warrior;
  218. if (cities[i].red_warrior != NULL) {
  219. if (cities[i].red_warrior->wtype->tid == LION)
  220. cities[i].red_warrior->loyalty -= loy_dec;
  221. if (cities[i].red_warrior->wtype->tid == ICEMAN)
  222. cities[i].red_warrior->life -= cities[i].red_warrior->life / 10;
  223. }
  224. }
  225. cities[0].red_warrior = NULL;
  226. for (int i = 0; i < ncities-1; i++) {
  227. cities[i].blue_warrior = cities[i+1].blue_warrior;
  228. if (cities[i].blue_warrior != NULL) {
  229. if (cities[i].blue_warrior->wtype->tid == LION)
  230. cities[i].blue_warrior->loyalty -= loy_dec;
  231. if (cities[i].blue_warrior->wtype->tid == ICEMAN)
  232. cities[i].blue_warrior->life -= cities[i].blue_warrior->life / 10;
  233. }
  234. }
  235. cities[ncities-1].blue_warrior = NULL;
  236. for (int i = 1; i < ncities - 1; i++) {
  237. struct warrior *redw = cities[i].red_warrior;
  238. struct warrior *bluew = cities[i].blue_warrior;
  239. if (redw)
  240. printf(walk, hour, "red", redw->wtype->tname, redw->number, i,
  241. redw->life, redw->attack);
  242. if (bluew)
  243. printf(walk, hour, "blue", bluew->wtype->tname, bluew->number, i,
  244. bluew->life, bluew->attack);
  245. }
  246. struct warrior *bluew = cities[0].blue_warrior;
  247. struct warrior *redw = cities[ncities-1].red_warrior;
  248. if (bluew != NULL) {
  249. printf(s1, hour, "blue", bluew->wtype->tname, bluew->number, "red",
  250. bluew->life, bluew->attack);
  251. printf(s2, hour, "red");
  252. war_stopped = 1;
  253. }
  254. if (redw != NULL) {
  255. printf(s1, hour, "red", redw->wtype->tname, redw->number, "blue",
  256. redw->life, redw->attack);
  257. printf(s2, hour, "blue");
  258. war_stopped = 1;
  259. }
  260. }
  261. static unsigned char rob_weapons(struct warrior *me, struct warrior *you, int roball)
  262. {
  263. int no_my_weapons = me->no_weapons[0] + me->no_weapons[1] + me->no_weapons[2];
  264. for (int i=0; i<3 && no_my_weapons < 10; i++) {
  265. if (you->no_weapons[i]==0)
  266. continue;
  267. int no_rob;
  268. if (10 - no_my_weapons >= you->no_weapons[i])
  269. no_rob = you->no_weapons[i];
  270. else
  271. no_rob = 10 - no_my_weapons;
  272. no_my_weapons += no_rob;
  273. me->no_weapons[i] += no_rob;
  274. if (i == 2) {
  275. /* unused arrows first */
  276. int unused = you->no_weapons[2] - you->used_arrow;
  277. if (unused < no_rob) {
  278. int rob_used = no_rob - unused;
  279. me->used_arrow += rob_used;
  280. you->used_arrow -= rob_used;
  281. } /* else nothing changed */
  282. }
  283. you->no_weapons[i] -= no_rob;
  284. if (!roball)
  285. return (no_rob << 4) | i;
  286. }
  287. return 0;
  288. }
  289. static void _35_wolf_rob_weapons()
  290. {
  291. const char *s = "%03d:35 %s wolf %d took %d %s from %s %s %d in city %d\n";
  292. unsigned char res;
  293. for (int i = 1; i < ncities-1; i++) {
  294. struct warrior *redw = cities[i].red_warrior;
  295. struct warrior *bluew = cities[i].blue_warrior;
  296. if (redw == NULL || bluew == NULL)
  297. continue;
  298. if (redw->wtype->tid == WOLF && bluew->wtype->tid != WOLF) {
  299. res = rob_weapons(redw, bluew, 0);
  300. if (res) {
  301. printf(s, hour, "red", redw->number, res>>4, wnames[res&0xf], "blue",
  302. bluew->wtype->tname, bluew->number, i);
  303. }
  304. } else if (redw->wtype->tid != WOLF && bluew->wtype->tid == WOLF) {
  305. res = rob_weapons(bluew, redw, 0);
  306. if (res) {
  307. printf(s, hour, "blue", bluew->number, res>>4, wnames[res&0xf], "red",
  308. redw->wtype->tname, redw->number, i);
  309. }
  310. }
  311. }
  312. }
  313. /* do_attack: attack the opponent with weapon index stored in w
  314. , return 1 if state changes */
  315. static int do_attack(struct warrior *me, struct warrior *you, int *w)
  316. {
  317. int idx = *w;
  318. int total = me->no_weapons[0]+me->no_weapons[1]+me->no_weapons[2];
  319. int attack;
  320. if (total == 0)
  321. return 0;
  322. if (idx < me->no_weapons[0]) {
  323. /* use a sword */
  324. attack = me->attack * 2 / 10;
  325. you->life -= attack;
  326. idx++;
  327. if (idx < total)
  328. *w = idx;
  329. else
  330. *w = 0;
  331. if (attack > 0)
  332. return 1;
  333. else
  334. return 0;
  335. } else if (idx < me->no_weapons[0]+me->no_weapons[1]) {
  336. /* use a bomb */
  337. attack = me->attack * 2 / 5;
  338. you->life -= attack;
  339. if (me->wtype->tid != NINJA)
  340. me->life -= attack/2;
  341. me->no_weapons[1]--;
  342. total--;
  343. if (idx == total)
  344. *w = 0;
  345. return 1;
  346. } else {
  347. /* use an arrow */
  348. attack = me->attack * 3 / 10;
  349. you->life -= attack;
  350. if (me->used_arrow > 0) {
  351. me->used_arrow--;
  352. me->no_weapons[2]--;
  353. total--;
  354. } else {
  355. me->used_arrow++;
  356. idx++;
  357. }
  358. if (idx == total)
  359. *w = 0;
  360. return 1;
  361. }
  362. }
  363. static void
  364. printwin(int win, int city, struct warrior *me, struct warrior *you)
  365. {
  366. const char *wins = "%03d:40 %s %s %d killed %s %s %d in city %d remaining %d elements\n";
  367. const char *yell = "%03d:40 %s dragon %d yelled in city %d\n";
  368. printf(wins, hour, colors[win], me->wtype->tname, me->number, colors[1-win],
  369. you->wtype->tname, you->number, city, me->life);
  370. if (me->wtype->tid == DRAGON)
  371. printf(yell, hour, colors[win], me->number, city);
  372. }
  373. static void sim_battle(int city)
  374. {
  375. const char *both = "%03d:40 both %s %s %d and %s %s %d %s in city %d\n";
  376. struct warrior *redw = cities[city].red_warrior;
  377. struct warrior *bluew = cities[city].blue_warrior;
  378. char reds_turn = city&1;
  379. int next_weapon[2] = {0, 0};
  380. int changed;
  381. do {
  382. changed = 0;
  383. if (reds_turn && redw->life>0 && bluew->life>0)
  384. changed = do_attack(redw, bluew, &next_weapon[0]);
  385. if (redw->life>0 && bluew->life>0)
  386. changed |= do_attack(bluew, redw, &next_weapon[1]);
  387. reds_turn = 1;
  388. } while (changed);
  389. if (redw->life>0 && bluew->life<=0) {
  390. printwin(0, city, redw, bluew);
  391. rob_weapons(redw, bluew, 1);
  392. } else if (redw->life<=0 && bluew->life>0) {
  393. printwin(1, city, bluew, redw);
  394. rob_weapons(bluew, redw, 1);
  395. } else if (redw->life<=0 && bluew->life<=0) {
  396. printf(both, hour, "red", redw->wtype->tname, redw->number,
  397. "blue", bluew->wtype->tname, bluew->number, "died", city);
  398. } else {
  399. printf(both, hour, "red", redw->wtype->tname, redw->number,
  400. "blue", bluew->wtype->tname, bluew->number, "were alive", city);
  401. }
  402. if (redw->life<=0) {
  403. cities[city].red_warrior = NULL;
  404. free(redw);
  405. }
  406. if (bluew->life<=0) {
  407. cities[city].blue_warrior = NULL;
  408. free(bluew);
  409. }
  410. }
  411. static void _40_battle()
  412. {
  413. for (int i=1; i<ncities-1; i++)
  414. if (cities[i].red_warrior && cities[i].blue_warrior)
  415. sim_battle(i);
  416. }
  417. static void _50_report_elements()
  418. {
  419. const char *s = "%03d:50 %d elements in %s headquarter\n";
  420. printf(s, hour, hq[0].life, "red");
  421. printf(s, hour, hq[1].life, "blue");
  422. }
  423. static void _55_report_weapons()
  424. {
  425. const char *s = "%03d:55 %s %s %d has %d sword %d bomb %d arrow and %d elements\n";
  426. for (int i = 0; i < ncities; i++) {
  427. struct warrior *redw = cities[i].red_warrior;
  428. struct warrior *bluew = cities[i].blue_warrior;
  429. if (redw)
  430. printf(s, hour, "red", redw->wtype->tname, redw->number, redw->no_weapons[0],
  431. redw->no_weapons[1], redw->no_weapons[2], redw->life);
  432. if (bluew)
  433. printf(s, hour, "blue", bluew->wtype->tname, bluew->number, bluew->no_weapons[0],
  434. bluew->no_weapons[1], bluew->no_weapons[2], bluew->life);
  435. }
  436. }
  437. void simulate_an_hour()
  438. {
  439. if (total_time >= 0)
  440. _00_warrior_born();
  441. total_time -= 5;
  442. if (total_time >= 0)
  443. _05_lion_runs();
  444. total_time -= 5;
  445. if (total_time >= 0)
  446. _10_warrior_walks();
  447. if (!war_stopped) {
  448. total_time -= 25;
  449. if (total_time >= 0)
  450. _35_wolf_rob_weapons();
  451. total_time -= 5;
  452. if (total_time >= 0)
  453. _40_battle();
  454. total_time -= 10;
  455. if (total_time >= 0)
  456. _50_report_elements();
  457. total_time -= 5;
  458. if (total_time >= 0)
  459. _55_report_weapons();
  460. total_time -= 5;
  461. hour++;
  462. }
  463. }
  464. /* end of simulate events */
  465. int main(void)
  466. {
  467. int ncases;
  468. scanf("%d", &ncases);
  469. for (int i=1; i<=ncases; i++) {
  470. hq_init();
  471. printf("Case:%d\n", i);
  472. int M, N, K, T;
  473. scanf("%d%d%d%d", &M, &N, &K, &T);
  474. hq[0].life = hq[1].life = M;
  475. war_init(N);
  476. loy_dec = K;
  477. total_time = T;
  478. for (int j=0; j<5; j++)
  479. scanf("%d", &all_wtypes[j]->initlife);
  480. for (int j=0; j<5; j++)
  481. scanf("%d", &all_wtypes[j]->attack);
  482. while (total_time >= 0 && !war_stopped)
  483. simulate_an_hour();
  484. }
  485. }