#include "graph.h"
#include "node.h"


void OldBooster::print_state(){
  /*
  for(auto cen: big_vertices){
    cout<<"B:"<<cen->cooperator<<" ("<<cen->compute_payoff(1.0)<<") ";
  }
  cout<<endl;
  for(auto cen: small_vertices){
    cout<<"S:"<<cen->cooperator<<" ("<<cen->compute_payoff(1.0)<<") ";
  }
  cout<<endl;
  cout<<"---------\n";
  */
  int sum = 0;
  for(auto n: nodes){
    if(n->cooperator) sum++;
  }
  cout<<sum<<endl;
}

void OldBooster::run(){
  while(!finished_half()){
    for(int a = 0; a < 10*(int)nodes.size(); a++){
      make_step();
      if(rand() % 100000 == 0 && setting.get_s() >= 5 && setting.random_one)
        make_faster();
    }
    //print_state();
  }
}


void OldBooster::make_faster(){
  int b_act = 2;//(int)(setting.get_b()+1);
  highest_degree = (setting.bigger_support)*b_act*b_act;
  support_small = b_act;
  
  int neighborhood = highest_degree + 1 + 2*support_small;

  int sum = 0;
  for(auto n: nodes){
    if(n->cooperator) sum++;
  }
  if(sum >= neighborhood){
    for(auto n: nodes){
      n->change(true);
    }
  }
}

void OldBooster::create_edges(){
  int b_act = 2;//(int)(setting.get_b()+1);
  highest_degree = (setting.bigger_support)*b_act*b_act;
  int support_big = highest_degree - 2*b_act;
  support_small = b_act;
  bridge_vertices = b_act - 1;

  vector<Node*> pr_bri;
  Node* pr_sm  = NULL;
  int n = setting.n;
  while(n > 0){
    n--;
    Node* cr_bi = nodes[n];
    big_vertices.push_back(cr_bi);
    for(auto prb: pr_bri){
      make_edge(cr_bi, prb);
    }
    if(pr_sm != NULL) make_edge(cr_bi,pr_sm);

    int ss = min(support_big, n);
    for(int a = 1; a <= ss; a++) make_edge(cr_bi,nodes[n-a]);
    n-= ss;

    if(n == 0) break;
    n--;
    pr_sm = nodes[n];
    make_edge(cr_bi,pr_sm);
    small_vertices.push_back(pr_sm);


    int fb = min(bridge_vertices, n);
    for(int a = 1; a <= fb; a++) {
      make_edge(cr_bi,nodes[n-a]);
      make_edge(pr_sm,nodes[n-a]);
    }
    n-= fb;

    int supp_small = min(support_small,n);
    for(int a = 1; a <= supp_small; a++) {
      make_edge(pr_sm,nodes[n-a]);
    }
    n-= supp_small;

    pr_bri.clear();
    int sb = min(bridge_vertices, n);
    for(int a = 1; a <= sb; a++) {
      pr_bri.push_back(nodes[n-a]);
      make_edge(pr_sm,nodes[n-a]);
    }
    n-= sb;
  }
}

/*
bool OldBooster::contains_invincible(){
  for(auto bb: big_vertices){
    if(!bb->cooperator) continue;
    if(bb->compute_payoff(0.0) > (setting.get_b())*(support_small + 2*bridge_vertices + 1)) return true;
  }
  return false;
}

void OldBooster::run_invincible(){
  while(!finished()){
    for(int a = 0; a < (int)nodes.size(); a++){
      make_step();
    }
    if(contains_invincible()){
      for(auto nn: nodes) nn->change(true);
    }
  }
}
*/

OldBooster::OldBooster(Setting st):Graph(st){
  create_vertices();
  create_edges();
}


