Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <map>
- #include <cmath>
- #include <cstdio>
- #include <cstdlib>
- #include <fstream>
- #include <iostream>
- #include <sys/wait.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <signal.h>
- using namespace std;
- ofstream log_file("log.txt", ios::app);
- //#define log_file cout
- enum ValType
- {
- vt_01, vt_log
- };
- struct Param
- {
- double init_val;
- ValType type;
- };
- const Param param[] =
- {
- {0.4, vt_01}, {0.3, vt_01}, {0.1, vt_01},
- {2.5, vt_log}, {0.4, vt_log}, {0.2, vt_log},
- {30, vt_log}, {50, vt_log}, {10, vt_log},
- {600, vt_log}, {0.1, vt_log}, {0.07, vt_log}, {0.8, vt_log},
- {3, vt_log}, {2, vt_log}, {0.5, vt_01},
- {1.2, vt_log}, {30000, vt_log},
- {0.08, vt_log}, {250, vt_log},
- {6, vt_log}, {100, vt_log},
- {0.5, vt_log}, {4000, vt_log}
- };
- const int param_count = sizeof(param) / sizeof(Param);
- double mirror(double val)
- {
- if(val < 0)return -val; if(val > 1)return 2 - val; return val;
- }
- double rand_move()
- {
- double res = random() / (0.5 * RAND_MAX) - 1;
- return res * res * res * abs(res);
- }
- struct State
- {
- static int next_id;
- int id, score;
- double val[param_count];
- void init()
- {
- id = 0;
- for(int i = 0; i < param_count; i++)val[i] = param[i].init_val;
- }
- void mutate(const State &parent)
- {
- id = next_id++;
- for(int i = 0; i < param_count; i++)
- if(param[i].type == vt_01)val[i] = mirror(parent.val[i] + rand_move());
- else val[i] = parent.val[i] * exp(rand_move());
- }
- void print(const char *title = "New ")
- {
- log_file << title << id << ':';
- for(int i = 0; i < param_count; i++)log_file << ' ' << val[i];
- log_file << endl;
- }
- bool load(istream &file)
- {
- unsigned long long num;
- file.read(reinterpret_cast<char *>(&num), sizeof(num)); id = num;
- file.read(reinterpret_cast<char *>(val), sizeof(val)); return file;
- }
- bool save(ostream &file) const
- {
- unsigned long long num = id;
- file.write(reinterpret_cast<char *>(&num), sizeof(num));
- file.write(reinterpret_cast<const char *>(val), sizeof(val)); return file;
- }
- };
- int State::next_id = 1;
- pid_t start_strategy(const State &state, int port)
- {
- int pfd[2];
- if(pipe(pfd))
- {
- cout << "Cannot create pipe!" << endl; return -1;
- }
- pid_t pid = fork();
- if(!pid)
- {
- close(STDIN_FILENO);
- if(dup2(pfd[0], STDIN_FILENO) != STDIN_FILENO)exit(-1);
- close(pfd[0]); close(pfd[1]);
- char buf[8]; sprintf(buf, "%d", port);
- execl("MyStrategy", "MyStrategy", "localhost", buf, "0000000000000000", static_cast<char *>(0));
- printf("Cannot start strategy!\n"); exit(-1);
- }
- if(pid == -1)
- {
- close(pfd[0]); close(pfd[1]);
- cout << "Cannot create process!" << endl; return -1;
- }
- static const unsigned long long flag = 0x0123456789ABCDEF;
- close(pfd[0]);
- if(write(pfd[1], &flag, sizeof(flag)) != sizeof(flag) ||
- write(pfd[1], state.val, sizeof(state.val)) != sizeof(state.val) ||
- write(pfd[1], &flag, sizeof(flag)) != sizeof(flag))
- {
- kill(pid, SIGKILL); close(pfd[1]);
- cout << "Cannot send parameters!" << endl; return -1;
- }
- close(pfd[1]); return pid;
- }
- struct Game
- {
- static const int player_count = 2;
- static int next_id;
- int id;
- State *state[player_count];
- Game()
- {
- }
- Game(State &state1, State &state2) : id(next_id++)
- {
- state[0] = &state1; state[1] = &state2;
- }
- bool process_result()
- {
- static const int place_score[] = {1, 0};
- char buf[256]; sprintf(buf, "games/%06d.txt", id);
- ifstream res_file(buf); string text; res_file >> text;
- if(text != "OK")
- {
- cout << "Game " << id << " failed!" << endl; return false;
- }
- int top[player_count];
- for(int i = 0; i < player_count; i++)top[i] = -1;
- for(int i = 0; i < player_count; i++)
- {
- int place, score;
- res_file >> place >> score >> text;
- for(place--;; place++)
- {
- if(place < 0 || place >= player_count)
- {
- cout << "Game " << id << ": invalid result!" << endl; return false;
- }
- if(top[place] < 0)break;
- }
- top[place] = i; state[i]->score += place_score[place];
- }
- log_file << "Game " << id << ':';
- for(int i = 0; i < player_count; i++)log_file << ' ' << state[top[i]]->id;
- log_file << endl; return true;
- }
- };
- int Game::next_id = 0;
- pid_t start_game(const Game &game, int base_port)
- {
- pid_t pid = fork();
- if(!pid)
- {
- char buf1[256], buf2[256];
- sprintf(buf1, "-base-adapter-port=%d", base_port);
- sprintf(buf2, "-results-file=games/%06d.txt", game.id);
- execl("/usr/bin/java", "java", "-cp", ".:local-runner.jar", "Run", "-render-to-screen=false",
- //"-render-to-screen=true", "-render-to-screen-scale=0.75", "-render-to-screen-sync=true",
- "-debug=true", buf1, "-p1-name=P1", "-p1-team-size=3", "-p2-name=P2", "-p2-team-size=3",
- buf2, "#LocalTestPlayer", "#LocalTestPlayer", static_cast<char *>(0));
- printf("Cannot start game!\n"); exit(-1);
- }
- if(pid == -1)
- {
- cout << "Cannot create process!" << endl; return -1;
- }
- usleep(1000000);
- for(int i = 0; i < Game::player_count; i++)
- {
- usleep(200000);
- start_strategy(*game.state[i], base_port + i);
- }
- return pid;
- }
- const int state_count = 8;
- const unsigned long long header = 0x0123456789ABCDEF ^ (state_count << 16 | param_count);
- bool load(State state[state_count])
- {
- ifstream file("restart.dat"); unsigned long long num = 0;
- file.read(reinterpret_cast<char *>(&num), sizeof(num));
- if(num != header)return false;
- file.read(reinterpret_cast<char *>(&num), sizeof(num));
- State::next_id = num >> 32; Game::next_id = num & 0xFFFFFFFF;
- for(int i = 0; i < state_count; i++)if(!state[i].load(file))return false;
- return true;
- }
- bool save(State state[state_count])
- {
- ofstream file("restart.dat", ios::trunc);
- file.write(reinterpret_cast<const char *>(&header), sizeof(header));
- unsigned long long num = (unsigned long long)State::next_id << 32 | Game::next_id;
- file.write(reinterpret_cast<char *>(&num), sizeof(num));
- for(int i = 0; i < state_count; i++)if(!state[i].save(file))return false;
- return true;
- }
- bool round(State state[state_count])
- {
- static const int game_count = 6;
- for(int i = 0; i < state_count; i++)state[i].score = 0;
- map<pid_t, Game> games;
- int ip1 = 0, ip2 = 1, port = 31000;
- while(ip2 < state_count || games.size())
- {
- while(ip2 < state_count && games.size() < game_count)
- {
- Game game(state[ip1], state[ip2]);
- pid_t pid = start_game(game, port);
- if(pid < 0)return false;
- games[pid] = game; port += Game::player_count;
- if(++ip2 >= state_count)
- {
- ip2 = ++ip1 + 1;
- if(ip2 >= state_count)break;
- }
- }
- pid_t pid = waitpid(0, 0, 0);
- map<pid_t, Game>::iterator ptr = games.find(pid);
- if(ptr != games.end())
- {
- if(!ptr->second.process_result())return false; games.erase(ptr);
- }
- }
- int best = 0, worst = 0;
- for(int i = 1; i < state_count; i++)
- {
- if(state[i].score > state[best].score)best = i;
- if(state[i].score < state[worst].score)worst = i;
- }
- log_file << "End round, worst " << state[worst].id << " removed" << endl;
- state[best].print("Best "); state[worst].mutate(state[best]);
- state[worst].print(); log_file << endl; save(state); return true;
- }
- int main()
- {
- State state[state_count];
- if(load(state))log_file << "Loaded restart file:" << endl;
- else
- {
- log_file << "Cannot find restart file, generating:" << endl;
- state[0].init();
- for(int i = 1; i < state_count; i++)state[i].mutate(state[0]);
- save(state);
- }
- for(int i = 0; i < state_count; i++)state[i].print(); log_file << endl;
- while(round(state));
- }
Advertisement
Add Comment
Please, Sign In to add comment