#include #include #include struct { char *komento, nimi[16]; } hippa = {0}, pakenija = {0}; char valenimi[16] = {0}; int leveys, korkeus, pelaajia, kierroksia; int pakopisteet, pakopisteet_d0, pakopisteet_d1, pakopisteet_sama_d; FILE *hippa_tmp = 0; long tmp_viimeiset_paikat; int ei_eri_nayttoa = 0, ei_mitaan_nayttoa = 0; #define poista_tyhjat(f) (fscanf(f, " ")) #define etsi_rivin_loppu(f) (fscanf(f, "%*[^\n]")) struct pelaaja { char t; int x, y; int nx, ny; }; struct pelaaja *_pelaajat, *pelaajat; char *pyyda_komento(const char *msg) { char buf[100]; char *ret = calloc(1, 1); int len = 0, tmp; printf("%s", msg); poista_tyhjat(stdin); do { fgets(buf, sizeof(buf), stdin); tmp = strlen(buf); if (buf[tmp - 1] == '\n') { buf[--tmp] = 0; } len += tmp; ret = realloc(ret, len + 1); strcat(ret, buf); } while (tmp == sizeof(buf) - 1); if (strcmp(ret, "-") == 0) { free(ret); return 0; } return ret; } int pyyda_kylla_ei_tyhja(const char *msg) { char buf[2] = {0}, ret[2] = {0}; while (ret[0] == 0) { printf("%s", msg); fgets(buf, 2, stdin); sscanf(buf, "%1[kKyYeEnN\n]", ret); if (ret[0] != '\n') { etsi_rivin_loppu(stdin); fgets(buf, 2, stdin); } } return + (strstr("kKyY", ret) ? 1 : 0) - (strstr("eEnN", ret) ? 1 : 0); } int cat(FILE *in, FILE *out) { char buf[256]; int i; while ((i = fread(buf, 1, sizeof(buf), in))) { if (fwrite(buf, 1, i, out) != i) { return 1; } } return 0; } void oma_exit(int ret) { if (ret != 0) printf("%s\n%s\n%s\n%s", "LUE OHJEET, jos jokin askarruttaa:\n" , "Ohjelma kysyy aluksi komennot, joilla hippa ja pakenija ajetaan.\n" "Komento - tarkoittaa ihmispelaajaa, jolloin ohjauskomennot kirjoitetaan\n" "suoraan testiohjelmaan. Sitten se kopioi tiedoston hippa.in tiedostoon\n" "hippa.txt ja jatkaa ottelua. Joka kierroksella ohjelma ajaa hipan ja\n" "pakenijan ja generoi molemmille oman mini.txt-tiedoston.\n" , "Testiohjelma itse ei mittaa aikaa!\n" , "Jossakin vaiheessa on nyt tapahtunut virhe, joten tarkista kaikki\n" "mainitut tiedostot ja antamasi ajokomennot.\n" ); #ifdef SCANF_AT_EXIT printf("\nKirjoita jotain ja paina enter, niin ohjelma sulkeutuu.\n"); scanf(" %*s"); #endif exit(ret); } void nayta_tilanne() { int i, j, p; char P = 1, H = 2; char *buf; buf = calloc(korkeus, leveys); for (p = 1; p <= pelaajia; ++p) { j = pelaajat[p].y - 1; i = pelaajat[p].x - 1; buf[j*leveys+i] |= (pelaajat[p].t == 'P' ? P : H); } printf("%3s ", "*"); for (i = 0; i < leveys; ++i) { putchar('0' + (i+1) % 10); } putchar('\n'); for (j = korkeus; j-- > 0;) { printf("%3d ", j + 1); for (i = 0; i < leveys; ++i) { if (buf[j*leveys+i] & H) putchar('H'); else if (buf[j*leveys+i] & P) putchar('P'); else putchar('.'); } putchar('\n'); } printf("%3s ", "*"); for (i = 0; i < leveys; ++i) { putchar('0' + (i+1) % 10); } putchar('\n'); fflush(stdout); free(buf); } void pyyda_liike(char t) { FILE *fp; char str[8]; printf("Ihmisen vuoro.\n"); printf("mini.txt:\n"); if ((fp = fopen("mini.txt", "r"))) { cat(fp, stdout); fclose(fp); } nayta_tilanne(); if (!(fp = fopen("liike.txt", "w"))) { printf("\nVirhe tiedoston liike.txt kirjoittamisessa!\n"); oma_exit(4); } printf("Anna omat ohjauskomennot (oma liike.txt). Tyhja rivi lopettaa.\n"); do { str[0] = 0; scanf("%7[^\n]", str); fprintf(fp, "%s\n", str); etsi_rivin_loppu(stdin); fgets(str+1, 2, stdin); } while (str[0]); fclose(fp); } void lue_liike(const char t) { int i, nx, ny; char dir[3]; struct pelaaja *pel; FILE *fp = fopen("liike.txt", "r"); if (!fp) return; while (fscanf(fp, "%d %2s", &i, dir) == 2) { pel = pelaajat + i; if (i <= 0 || pelaajia < i || pel->t != t) { continue; } if (dir[0] == '0' && dir[1] == 0) { nx = pel->x; ny = pel->y; } else if (dir[0] == '+') { if (dir[1] == 'x') { nx = pel->x + 1; ny = pel->y; } else if (dir[1] == 'y') { nx = pel->x; ny = pel->y + 1; } else { continue; } } else if (dir[0] == '-') { if (dir[1] == 'x') { nx = pel->x - 1; ny = pel->y; } else if (dir[1] == 'y') { nx = pel->x; ny = pel->y - 1; } else { continue; } } else { continue; } if (nx <= 0) nx = 1; if (ny <= 0) ny = 1; if (nx > leveys) nx = leveys; if (ny > korkeus) ny = korkeus; pel->nx = nx; pel->ny = ny; } fclose(fp); } void tee_valenimi(char vuorossa) { FILE *fp = fopen("hippa.txt", "r+"); if (!fp) { printf("\nhippa.txt ei aukea, tarkista kirjoitusoikeudet.\n"); oma_exit(3); } fprintf(fp, "%s\n", vuorossa == 'H' ? hippa.nimi : valenimi); fprintf(fp, "%s\n", vuorossa == 'P' ? pakenija.nimi : valenimi); fclose(fp); } void tee_hippa_txt(void) { FILE *fp = fopen("hippa.txt", "w"); if (!fp) { printf("\nhippa.txt ei aukea, tarkista kirjoitusoikeudet.\n"); oma_exit(3); } fprintf(fp, "%s\n", hippa.nimi); fprintf(fp, "%s\n", pakenija.nimi); fprintf(fp, "%d %d %d %d\n", leveys, korkeus, pelaajia, kierroksia); rewind(hippa_tmp); cat(hippa_tmp, fp); fclose(fp); if (!ei_eri_nayttoa) { nayta_tilanne(); } } void tee_mini_txt(char t) { FILE *fp = fopen("mini.txt", "w"); if (!fp) { printf("\nmini.txt ei aukea, tarkista kirjoitusoikeudet.\n"); oma_exit(3); } fprintf(fp, "%c %d %d %d %d\n", t, leveys, korkeus, pelaajia, kierroksia); fseek(hippa_tmp, tmp_viimeiset_paikat, SEEK_SET); cat(hippa_tmp, fp); fclose(fp); } int laske(const char t) { int i, c = 0; for (i = 1; i <= pelaajia; ++i) { if (pelaajat[i].t == t) { ++c; } } return c; } void liikuta(void) { int i, j; for (i = 1; i <= pelaajia; ++i) { pelaajat[i].x = pelaajat[i].nx; pelaajat[i].y = pelaajat[i].ny; } for (i = 1; i <= pelaajia; ++i) { if (pelaajat[i].t != 'P') { continue; } for (j = 1; j <= pelaajia; ++j) { if (pelaajat[j].t != 'H') { continue; } if (pelaajat[i].x == pelaajat[j].x && pelaajat[i].y == pelaajat[j].y) { pelaajat[i].t = 'H'; } } } ++kierroksia; fprintf(hippa_tmp, "%d\n", kierroksia); tmp_viimeiset_paikat = ftell(hippa_tmp); for (i = 1; i <= pelaajia; ++i) { fprintf(hippa_tmp, "%c %d %d\n", pelaajat[i].t, pelaajat[i].x, pelaajat[i].y); } } void aja_aly(const char t, const char *cmd) { FILE *fp; char buf[16]; if (valenimi[0]) { tee_valenimi(t); } tee_mini_txt(t); if (!(fp = fopen("liike.txt", "w"))) { printf("\nliike.txt ei aukea, tarkista kirjoitusoikeudet.\n"); oma_exit(3); } fclose(fp); if (cmd) { sprintf(buf, "muisti%c.dat", t); rename(buf, "muisti.dat"); system(cmd); rename("muisti.dat", buf); } else { pyyda_liike(t); } lue_liike(t); } void aja_peli(void) { tee_hippa_txt(); if (ei_mitaan_nayttoa) { printf("kierrokset, pakopisteet, vapaat pakenijat, saamattomia kierroksia\n"); } pakopisteet_d0 = laske('P'); while (pakopisteet_d0 > 0 && pakopisteet_sama_d < 10 * (leveys+korkeus)) { if (!ei_mitaan_nayttoa) { printf("kierrokset, pakopisteet, vapaat pakenijat, saamattomia kierroksia\n"); printf("%10d, %11d, %16d, %22d\n", kierroksia, pakopisteet, pakopisteet_d1, pakopisteet_sama_d); } else { printf("%10d, %11d, %16d, %22d\r", kierroksia, pakopisteet, pakopisteet_d1, pakopisteet_sama_d); fflush(stdout); } pakopisteet += pakopisteet_d1; aja_aly('H', hippa.komento); aja_aly('P', pakenija.komento); liikuta(); tee_hippa_txt(); pakopisteet_d1 = laske('P'); if (pakopisteet_d0 == pakopisteet_d1) { ++pakopisteet_sama_d; } else { pakopisteet_sama_d = 0; pakopisteet_d0 = pakopisteet_d1; } } if (!ei_mitaan_nayttoa) { printf("kierrokset, pakopisteet, vapaat pakenijat, saamattomia kierroksia\n"); } printf("%10d, %11d, %16d, %22d\n", kierroksia, pakopisteet, pakopisteet_d1, pakopisteet_sama_d); if (pakopisteet_d0) { printf("10L + 10K kierrosta ilman kiinniottoja, peli loppuu kesken.\n"); } else { printf("Kaikki pakenijat on saatu kiinni.\n"); } } void lataa(FILE *fp) { int _i, i, j; pakopisteet = 0; pakopisteet_sama_d = 0; pakopisteet_d0 = -1; pakopisteet_d1 = 0; for (_i = 0; _i <= kierroksia; ++_i) { if (fscanf(fp, "%d ", &i) != 1 || i != _i) { printf("\nhippa.in on viallinen, tarkista kierros %d!\n", _i); oma_exit(2); } fprintf(hippa_tmp, "%d\n", i); tmp_viimeiset_paikat = ftell(hippa_tmp); pakopisteet += pakopisteet_d1; pakopisteet_d1 = 0; for (j = 1; j <= pelaajia; ++j) { if (fscanf(fp, "%c %d %d ", &pelaajat[j].t, &pelaajat[j].x, &pelaajat[j].y) != 3 || (pelaajat[j].t != 'H' && pelaajat[j].t != 'P') || pelaajat[j].x <= 0 || leveys < pelaajat[j].x || pelaajat[j].y <= 0 || korkeus < pelaajat[j].y) { printf("\nhippa.in on viallinen, tarkista tilanne %d!\n", i); oma_exit(2); } fprintf(hippa_tmp, "%c %d %d\n", pelaajat[j].t, pelaajat[j].x, pelaajat[j].y); if (pelaajat[j].t == 'P') { ++pakopisteet_d1; } } if (pakopisteet_d0 == pakopisteet_d1) { ++pakopisteet_sama_d; } else { pakopisteet_sama_d = 0; pakopisteet_d0 = pakopisteet_d1; } } } int main(int argc, char **argv) { int i; FILE *fp; hippa.komento = pyyda_komento("Anna komento hipan ajamiseen (esim. hipake.exe):\n> "); pakenija.komento = pyyda_komento("Anna komento pakenijan ajamiseen (esim. pinko.exe):\n> "); if (pyyda_kylla_ei_tyhja("Poistetaanko vanhat muisti.dat-tiedostot? [K/e] ") > -1) { remove("muistiH.dat"); remove("muistiP.dat"); } for (i = 1; i < argc; ++i) { if (strcmp(argv[i], "-q") == 0) { ei_eri_nayttoa = 1; } } /* Tilanne saattaa tulla joka tapauksessa komentojen kanssa. */ ei_mitaan_nayttoa = (ei_eri_nayttoa && pakenija.komento && hippa.komento); ei_eri_nayttoa = (ei_eri_nayttoa || !pakenija.komento || !hippa.komento); fp = fopen("hippa.in", "r"); if (!fp) { printf("\nhippa.in ei auennut.\n"); oma_exit(1); } hippa_tmp = tmpfile(); if (!hippa_tmp) { printf("\nTarvittavaa aputiedostoa ei voitu luoda.\n"); oma_exit(1); } if (fscanf(fp, "%15s", hippa.nimi) != 1 || fscanf(fp, "%15s", pakenija.nimi) != 1 || fscanf(fp, "%d %d %d %d", &leveys, &korkeus, &pelaajia, &kierroksia) != 4) { printf("hippa.in on viallinen, tarkista tiedoston alku!\n"); } if (strcmp(hippa.nimi, pakenija.nimi) == 0) { strcpy(valenimi, hippa.nimi); valenimi[0] = (valenimi[0] == 'V' ? 'v' : 'V'); } _pelaajat = calloc(pelaajia, sizeof(*pelaajat)); if (!_pelaajat) { printf("\nMuistivirhe.\n"); oma_exit(1); } pelaajat = _pelaajat - 1; lataa(fp); fclose(fp); for (i = 1; i <= pelaajia; ++i) { pelaajat[i].nx = pelaajat[i].x; pelaajat[i].ny = pelaajat[i].y; } aja_peli(); fclose(hippa_tmp); if (_pelaajat) free(_pelaajat); if (hippa.komento) free(hippa.komento); if (pakenija.komento) free(pakenija.komento); oma_exit(0); return 0; }