// File: /workspace/github_cpp_makefile_star2_O2/legendddhgf[P]Text2RPG/GameEngine.cpp
// Function: GameEngine::GameEngine(_IO_FILE*)
GameEngine::GameEngine (FILE *fp) {
  map_room_descriptions.clear(); // are these done automatically?
  map_room_contents.clear();
  map_room_opts.clear();
  map_room_tags.clear();

  int parseMode = PARSEMODENONE;
  string lastKey = string(""); // the key for the current parseMode
  // (IE: the current room if PARSEMODEROOM)
  char *buf = (char *) calloc(1024, sizeof(char)); // this is simply a
  // temporary string which
  // gets trimmed to modstr
  char *modstr = (char *) calloc(1024, sizeof(char)); // THIS IS THE STRING
  // WE ARE USING!!!
  int linecount = 0; // helps the user debug their text file
  while (fgets(buf, 1023, fp)) {
    linecount++;
    if (strlen(modstr) >= 1000) {
      fprintf(stderr, "line %d: Too long\n", linecount);
      exit(1);
    }
    stringTrim(buf, "\n\r ", modstr); // trim newline, carriage return,
    // and space from front and back
    if (strlen(modstr) == 0) { // skip empty lines
      continue;
    }
    if (strlen(modstr) == 1) {
      fprintf(stderr, "line %d: No parameters specified\n", linecount);
      exit(1);
    }
    char tag = modstr[0]; // in this case, by tag we mean the character of
    // the line (IE: 'r', 'd', 'g', etc.)
    strncpy(buf, modstr, strlen(modstr) + 1); // this line and the
    // following one trim
    // everything from
    stringTrim(buf + 1, "\n\r ", modstr);     // the tag to the beginning
    // of the parameter
    vector<string> params = {};
    stringToParams(modstr, &params, " ");
    // (room for 'r', description for 'd', etc)
    switch (tag) { // REMEMBER: at this point modstr only contains the
      // parameter, tag contains the current tag
      case 'r': // room
        {
          if (params.size() != 1) {
            fprintf(stderr, "line %d: 'r' takes one parameter\n", linecount);
            exit(1);
          }
          // TODO: create a function that checks if it is ok to
          // continue parsing, in other words, checks that the
          // previous thing being modified is ok up to this point
          parseMode = PARSEMODEROOM;

          /* VERY BAD BECAUSE WE DON'T KNOW IF LASTKEY IS A ROOM!,
           * just make a complete checking function already
           if (map_room_descriptions.size() > 0 &&
          // if desc is blank, none specified
          map_room_descriptions.at(lastKey).compare(string("")) == 0) {
          fprintf(stderr, "%s: Room has no description\n",
          list_rooms.back().c_str());
          exit(1);
          }
          */

          if (map_room_opts.size() != map_room_tags.size()) {
            fprintf(stderr, "line %d: There must be one tag for every option\n",
                linecount);
            exit(1);
          }
          lastKey = params.at(0); // key is now the current room
          if (map_room_descriptions.find(lastKey) !=
              map_room_descriptions.end()) {
            fprintf(stderr, "line %d: Can't have duplicate room names\n",
                linecount);
            exit(1);
          }
          if (map_room_descriptions.size() == 0) { // don't check tags if there
            // are no rooms yet
            map_room_descriptions.insert(pair<string, // new entry
                string>(lastKey, string("")));
            break;
          }
          auto opts_iter = map_room_opts.find(lastKey); // the next ~10 lines
          // are for checking
          // opts : tags
          auto tags_iter = map_room_tags.find(lastKey);
          if (opts_iter == map_room_opts.end() &&
              tags_iter == map_room_tags.end()) { // no tags or opts, thus equal
            map_room_descriptions.insert(pair<string,
                string>(lastKey, string(""))); // if unchanged, if
            // statement above is trigerred
            break;
          }
          if (opts_iter == map_room_opts.end() || // only opts has nothing
              tags_iter == map_room_tags.end() || // or only tags has nothing
              opts_iter->second.size() !=
              tags_iter->second.size()) { // or for key: numopts != numtags
            fprintf(stderr, "line %d: There must be one tag for every option\n",
                linecount);
            exit(1);
          }
          map_room_descriptions.insert(pair<string,
              string>(lastKey, string("")));
          break;
        }
      case 'd': // description
        // NOTE: that there is only ever one description per room. The
        // functionality of having multiple descriptions is implemented
        // by appending to the previous description string for a given
        // room if it already exists
        if (parseMode == PARSEMODEROOM) {
          // in all cases, append: we know the entry must exist at
          // this point
          // Note: in this case we take the entire group of parameters excluding
          // the newline and space after the tag as the description
          map_room_descriptions.at(lastKey).append(string("\t")
              + string(modstr) + string("\n"));
        } else if (parseMode == PARSEMODEITEM) {
          // in all cases, append: we know the entry must exist at
          // this point
          // Note: in this case we take the entire group of parameters excluding
          // the newline and space after the tag as the description
          map_item_descriptions.at(lastKey).append(string("\t")
              + string(modstr) + string("\n"));
        } else {
          fprintf(stderr, "line %d: Invalid parsemode for 'd'\n", linecount);
          exit(1);
        }
        break;
      case 'o':
        {
          if (parseMode == PARSEMODEROOM) {
            if (map_room_opts.find(lastKey) != map_room_opts.end() &&
                map_room_tags.find(lastKey) != map_room_tags.end() &&
                map_room_opts.find(lastKey)->second.size() !=
                map_room_tags.find(lastKey)->second.size()) { // numopts should
              // equal numtags
              // at this point
              fprintf(stderr, "line %d: Expected another tag first\n",
                  linecount);
              exit(1);
            }
            // if there are no transitions from the current room, insert
            // a blank one
            if (map_room_opts.find(lastKey) == map_room_opts.end()) {
              map_room_opts.insert(pair<string, vector<string>>(lastKey, {}));
            }
            // finally, append to the appropriate vector
            map_room_opts.find(lastKey)->second.push_back(params.at(0));
          } else if (parseMode == PARSEMODEITEM) {
            // TODO: dat functionality
          } else {
            fprintf(stderr, "line %d: Invalid parsemode for 'o'\n", linecount);
            exit(1);
          }
          break;
        }
      case 't':
        {
          if (parseMode == PARSEMODEROOM) {
            // can't have tags before opts
            if (map_room_opts.find(lastKey) == map_room_opts.end() ||
                (map_room_opts.find(lastKey) != map_room_opts.end() &&
                 map_room_tags.find(lastKey) != map_room_tags.end() &&
                 map_room_opts.find(lastKey)->second.size() ==
                 map_room_tags.find(lastKey)->second.size())) {
              // numopts should equal numtags - 1 at this point
              fprintf(stderr, "line %d: Expected another option first\n",
                  linecount);
              exit(1);
            }
            // if there are no transitions from the current room, insert
            // a blank one
            if (map_room_tags.find(lastKey) == map_room_tags.end())
              map_room_tags.insert(pair<string, vector<string>>(lastKey, {}));
            // finally, append to the appropriate vector
            map_room_tags.find(lastKey)->second.push_back(params.at(0));
          } else if (parseMode == PARSEMODEITEM) {
            // TODO: dat functionality
          } else {
            fprintf(stderr, "line %d: Invalid parsemode for 't'\n", linecount);
            exit(1);
          }
          break;
        }
      case 'm':
        if (parseMode == PARSEMODEROOM) {
          if (params.size() > 2) {
            fprintf(stderr, "line %d: in room parsing, 'm' %s",
                linecount, "takes one or two parameters\n");
            exit(1);
          }
          // Cannot have a room be a member of itself
          if (params.at(0).compare(lastKey) == 0) {
            fprintf(stderr, "line %d: %s cannot be a member of itself\n",
                linecount, modstr);
            exit(1);
          }
          if (map_room_contents.find(lastKey) == map_room_contents.end()) {
            // sometimes life isn't simple but it could be
            map_room_contents.insert(pair<string,
                vector<tuple<string, string>>>(lastKey, {}));
          }
          if (params.size() == 1) {
            map_room_contents.find(lastKey)->second.emplace_back(
                params.at(0), to_string(PRIORITYDEFAULT));
          } else {
            if (params.at(1).find_first_not_of("1234567890") != string::npos) {
              fprintf(stderr, "line %d: Priority must be an integer\n",
                  linecount);
              exit(1);
            }
            map_room_contents.find(lastKey)->second.emplace_back(
                params.at(0), params.at(1));
          }
        } else {
          fprintf(stderr, "line %d: Invalid parsemode for 'm'\n", linecount);
          exit(1);
        }
        break;
      case 'e':
        // TODO
        break;
      case 'a':
        // TODO
        break;
      case 'i':
        {
          // TODO: create a function that checks if it is ok to
          // continue parsing, in other words, checks that the
          // previous thing being modified is ok up to this point
          parseMode = PARSEMODEITEM;
          if (params.size() != 1) {
            fprintf(stderr, "line %d: 'i' takes one parameter\n", linecount);
            exit(1);
          }
          lastKey = params.at(0); // key is now the current item
          if (map_item_descriptions.find(lastKey) !=
              map_item_descriptions.end()) {
            fprintf(stderr, "line %d: Can't have duplicate item names\n",
                linecount);
            exit(1);
          }
          map_item_descriptions.insert(pair<string, // new entry
              string>(lastKey, string("")));
          break;
        }
      case 'q':
        {
          if (parseMode == PARSEMODEITEM) {
            // TODO
          } else {
            fprintf(stderr, "line %d: Invalid parsemode for 'q'\n", linecount);
            exit(1);
          }
          break;
        }
      case '#': // support those comments
        // Yes, this works.
        break;
      default:
        fprintf(stderr, "%c: No Corresponding field\n", tag);
        exit(1);
        break;
    }
  }
  /* General checking function needed
     if (list_rooms.size() != list_room_descriptions.size()) {
// one description per room required
fprintf(stderr, "%s: Room has no description\n",
list_rooms.back().c_str());
exit(1); }
*/
  // TODO resolve regex
  // TODO:
  // check that for all keys num opts = num tags and all opts are valid rooms
  // (will have to add checking for non-visitable rooms later)

  // print all info
  auto iter_room = map_room_descriptions.begin();
  int count_rooms = 1;
  fprintf(stdout, "ROOMS:\n=====\n");
  while (iter_room != map_room_descriptions.end()) {
    string room = iter_room->first;
    string description = iter_room->second;
    iter_room++;
    fprintf(stdout, "%d: %s\n", count_rooms++, room.c_str());
    // assumes description was modified in a certain way first
    fprintf(stdout, "%s", description.c_str());
    if (map_room_contents.find(room) != map_room_contents.end()) {
      fprintf(stdout, "\tHas Members:\n");
      auto list_contents = map_room_contents.find(room)->second;
      for (size_t k = 0; k < list_contents.size(); k++) {
        fprintf(stdout, "\t\t%s: Priority=%s\n",
            get<0>(list_contents.at(k)).c_str(),
            get<1>(list_contents.at(k)).c_str());
      }
    }
    // if no opts/tags
    if (map_room_opts.find(room) == map_room_opts.end()) continue;
    fprintf(stdout, "\tHas Options and Tags:\n");
    auto list_opts = map_room_opts.at(room);
    auto list_tags = map_room_tags.at(room);
    for (size_t k = 0; k < list_opts.size(); k++) { // since numopts = numtags
      fprintf(stdout, "\t\tOption: %s\n", list_opts.at(k).c_str());
      fprintf(stdout, "\t\t\tTag: %s\n", list_tags.at(k).c_str());
    }
  }
  fprintf(stdout, "=====\nITEMS:\n=====\n");
  auto iter_items = map_item_descriptions.begin();
  int count_items = 1;
  // print item info
  while(iter_items != map_item_descriptions.end()) {
    string item = iter_items->first;
    string description = iter_items->second;
    iter_items++;
    fprintf(stdout, "%d: %s\n", count_items++, item.c_str());
    // assumes description was modified in a certain way first
    fprintf(stdout, "%s", description.c_str());
  }
  fprintf(stdout, "=====\n");
  free(buf);
  free(modstr);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x168, %rsp            # imm = 0x168
movq %rsi, -0xb0(%rbp)
movq %rdi, %r15
leaq 0x30(%rdi), %rax
movq %rax, (%rdi)
pushq $0x1
popq %rax
movq %rax, 0x8(%rdi)
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rdi)
movl $0x3f800000, %ecx       # imm = 0x3F800000
movl %ecx, 0x20(%rdi)
movups %xmm0, 0x28(%rdi)
leaq 0x38(%rdi), %rbx
leaq 0x68(%rdi), %rdx
movq %rdx, 0x38(%rdi)
movq %rax, 0x40(%rdi)
movups %xmm0, 0x48(%rdi)
movl %ecx, 0x58(%rdi)
movups %xmm0, 0x60(%rdi)
leaq 0x70(%rdi), %r12
leaq 0xa0(%rdi), %rdx
movq %rdx, 0x70(%rdi)
movq %rax, 0x78(%rdi)
movups %xmm0, 0x80(%rdi)
movl %ecx, 0x90(%rdi)
movups %xmm0, 0x98(%rdi)
leaq 0xa8(%rdi), %r13
leaq 0xd8(%rdi), %rdx
movq %rdx, 0xa8(%rdi)
movq %rax, 0xb0(%rdi)
movups %xmm0, 0xb8(%rdi)
movl %ecx, 0xc8(%rdi)
movups %xmm0, 0xd0(%rdi)
leaq 0xe0(%rdi), %rdx
movq %rdx, -0xa8(%rbp)
leaq 0x110(%rdi), %rdx
movq %rdx, 0xe0(%rdi)
movq %rax, 0xe8(%rdi)
movups %xmm0, 0xf0(%rdi)
movl %ecx, 0x100(%rdi)
movups %xmm0, 0x108(%rdi)
leaq 0x148(%rdi), %rdx
movq %rdx, 0x118(%rdi)
movq %rax, 0x120(%rdi)
movups %xmm0, 0x128(%rdi)
movl %ecx, 0x138(%rdi)
movups %xmm0, 0x140(%rdi)
callq 0x2e36
movq %rbx, -0x70(%rbp)
movq %rbx, %rdi
callq 0x52e0
movq %r12, -0x40(%rbp)
movq %r12, %rdi
callq 0x51fc
movq %r13, -0x68(%rbp)
movq %r13, %rdi
callq 0x51fc
leaq 0x3522(%rip), %rsi      # 0x7217
leaq -0x188(%rbp), %rdi
leaq -0x120(%rbp), %rdx
callq 0x2090
leaq 0x10(%r15), %rax
movq %rax, -0xe0(%rbp)
movq %r15, -0x30(%rbp)
leaq 0xf0(%r15), %rax
movq %rax, -0x148(%rbp)
pushq $0x1
popq %rbx
movl $0x400, %edi            # imm = 0x400
movq %rbx, %rsi
callq 0x2130
movq %rax, %r13
movl $0x400, %edi            # imm = 0x400
movq %rbx, %rsi
callq 0x2130
movq %rax, -0x98(%rbp)
movq %r13, %rax
incq %rax
movq %rax, -0xd8(%rbp)
xorl %ebx, %ebx
leaq -0x188(%rbp), %r15
xorl %r12d, %r12d
movq %r13, %rdi
movl $0x3ff, %esi            # imm = 0x3FF
movq -0xb0(%rbp), %rdx
callq 0x2270
testq %rax, %rax
je 0x45d4
movq %r15, %r14
incl %ebx
movq -0x98(%rbp), %r15
movq %r15, %rdi
callq 0x20b0
cmpq $0x3e8, %rax            # imm = 0x3E8
jae 0x490d
movq %r13, %rdi
leaq 0x33c7(%rip), %rsi      # 0x7173
movq %r15, %rdx
callq 0x23cc
movq %r15, %rdi
callq 0x20b0
testq %rax, %rax
movq %r14, %r15
je 0x3d65
movl %r12d, -0xa0(%rbp)
cmpq $0x1, %rax
je 0x4920
movq %r13, %r12
movq -0x98(%rbp), %r13
movsbl (%r13), %r15d
incq %rax
movq %r12, %rdi
movq %r13, %rsi
movq %rax, %rdx
callq 0x20e0
movq -0xd8(%rbp), %rdi
leaq 0x3370(%rip), %rsi      # 0x7173
movq %r13, %rdx
callq 0x23cc
xorps %xmm0, %xmm0
movaps %xmm0, -0x90(%rbp)
andq $0x0, -0x80(%rbp)
movq %r13, %rdi
leaq -0x90(%rbp), %rsi
leaq 0x334a(%rip), %rdx      # 0x7175
callq 0x246c
movq %r12, %r13
movzbl %r15b, %eax
leal -0x61(%rax), %ecx
cmpl $0x13, %ecx
movl -0xa0(%rbp), %r12d
ja 0x3f39
leaq 0x32bf(%rip), %rsi      # 0x7110
movslq (%rsi,%rcx,4), %rax
addq %rsi, %rax
jmpq *%rax
cmpl $0x3, %r12d
je 0x43e3
cmpl $0x1, %r12d
jne 0x4a80
movq %r14, %rsi
movq -0x30(%rbp), %rdi
callq 0x3b92
movq %rax, -0xa0(%rbp)
leaq -0xd0(%rbp), %rdi
leaq 0x3387(%rip), %rsi      # 0x7216
leaq -0x33(%rbp), %rdx
callq 0x2090
leaq -0x140(%rbp), %r12
movq %r12, %rdi
movq -0x98(%rbp), %rsi
leaq -0x32(%rbp), %rdx
callq 0x2090
leaq -0x60(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
movq %r12, %rdx
callq 0x4d15
leaq -0x168(%rbp), %r12
movq %r12, %rdi
leaq 0x3364(%rip), %rsi      # 0x723a
leaq -0x31(%rbp), %rdx
callq 0x2090
leaq -0x120(%rbp), %r15
movq %r15, %rdi
leaq -0x60(%rbp), %rsi
movq %r12, %rdx
callq 0x4d15
movq -0xa0(%rbp), %rdi
movq %r15, %rsi
callq 0x22c0
movq %r15, %rdi
callq 0x20d0
leaq -0x168(%rbp), %rdi
callq 0x20d0
leaq -0x60(%rbp), %rdi
callq 0x20d0
leaq -0x140(%rbp), %rdi
callq 0x20d0
leaq -0xd0(%rbp), %rdi
jmp 0x45b7
cmpl $0x23, %eax
je 0x45c0
jmp 0x4955
cmpl $0x3, %r12d
pushq $0x3
popq %r12
je 0x45c0
jmp 0x4991
movq -0x88(%rbp), %rax
subq -0x90(%rbp), %rax
cmpq $0x20, %rax
jne 0x496b
movq -0x30(%rbp), %rcx
movq 0x88(%rcx), %rax
cmpq 0xc0(%rcx), %rax
jne 0x4942
leaq -0x90(%rbp), %rdi
xorl %esi, %esi
callq 0x4cce
movq %r14, %rdi
movq %rax, %rsi
callq 0x2100
movq -0x30(%rbp), %r12
movq %r12, %rdi
movq %r14, %r15
movq %r14, %rsi
callq 0x3b64
testq %rax, %rax
jne 0x497e
cmpq $0x0, 0x18(%r12)
je 0x452c
movq -0x40(%rbp), %rdi
movq %r15, %rsi
callq 0x53c2
movq %r15, %rsi
movq %rax, %r15
movq -0x68(%rbp), %rdi
callq 0x53c2
testq %r15, %r15
je 0x456a
testq %rax, %rax
je 0x4942
movq 0x30(%r15), %rcx
subq 0x28(%r15), %rcx
movq 0x30(%rax), %rdx
subq 0x28(%rax), %rdx
cmpq %rdx, %rcx
jne 0x4942
leaq -0x60(%rbp), %rdi
leaq 0x31fc(%rip), %rsi      # 0x7217
leaq -0xd0(%rbp), %rdx
callq 0x2090
leaq -0x120(%rbp), %r15
movq %r15, %rdi
movq %r14, %rsi
leaq -0x60(%rbp), %rdx
callq 0x4cf0
movq %r12, %rdi
movq %r15, %rsi
callq 0x3a5e
jmp 0x45ab
cmpl $0x3, %r12d
je 0x45c0
cmpl $0x1, %r12d
jne 0x4a3e
movq -0x40(%rbp), %rdi
movq %r14, %r15
movq %r14, %rsi
callq 0x53c2
testq %rax, %rax
je 0x4a28
movq -0x40(%rbp), %rdi
movq %r15, %rsi
callq 0x53c2
testq %rax, %rax
je 0x40d2
movq -0x68(%rbp), %rdi
movq %r15, %rsi
callq 0x53c2
testq %rax, %rax
je 0x40d2
movq -0x40(%rbp), %rdi
movq %r15, %rsi
callq 0x53c2
movq %r15, %rsi
movq 0x28(%rax), %r12
movq 0x30(%rax), %r15
movq -0x68(%rbp), %rdi
callq 0x53c2
subq %r12, %r15
movq 0x30(%rax), %rcx
subq 0x28(%rax), %rcx
cmpq %rcx, %r15
movq %r14, %r15
je 0x4a28
movq -0x68(%rbp), %rdi
movq %r15, %rsi
callq 0x53c2
testq %rax, %rax
jne 0x4122
xorps %xmm0, %xmm0
movaps %xmm0, -0x60(%rbp)
andq $0x0, -0x50(%rbp)
leaq -0x120(%rbp), %r12
movq %r12, %rdi
movq %r15, %rsi
leaq -0x60(%rbp), %rdx
callq 0x4d86
movq -0x68(%rbp), %rdi
movq %r12, %rsi
callq 0x5538
movq %r12, %rdi
callq 0x4dbc
leaq -0x60(%rbp), %rdi
callq 0x2d80
movq -0x68(%rbp), %rdi
movq %r15, %rsi
callq 0x53c2
movq %rax, %r15
leaq -0x90(%rbp), %rdi
xorl %esi, %esi
callq 0x4cce
addq $0x28, %r15
movq %r15, %rdi
movq %rax, %rsi
callq 0x2556
pushq $0x1
popq %r12
jmp 0x45c0
movq -0x88(%rbp), %rax
subq -0x90(%rbp), %rax
cmpq $0x20, %rax
jne 0x49ba
leaq -0x90(%rbp), %rdi
xorl %esi, %esi
callq 0x4cce
movq %r14, %rdi
movq %rax, %rsi
callq 0x2100
movq -0xa8(%rbp), %rdi
movq %r14, %r15
movq %r14, %rsi
callq 0x3b64
testq %rax, %rax
jne 0x4a12
leaq -0x60(%rbp), %rdi
leaq 0x3069(%rip), %rsi      # 0x7217
leaq -0xd0(%rbp), %rdx
callq 0x2090
leaq -0x120(%rbp), %r12
movq %r12, %rdi
movq %r15, %rsi
leaq -0x60(%rbp), %rdx
callq 0x4cf0
movq -0xa8(%rbp), %rdi
movq %r12, %rsi
callq 0x3a5e
movq %r12, %rdi
callq 0x2de2
leaq -0x60(%rbp), %rdi
jmp 0x44ac
cmpl $0x3, %r12d
je 0x45c0
cmpl $0x1, %r12d
jne 0x4a54
movq -0x40(%rbp), %rdi
movq %r14, %r15
movq %r14, %rsi
callq 0x53c2
testq %rax, %rax
je 0x4260
movq -0x68(%rbp), %rdi
movq %r15, %rsi
callq 0x53c2
testq %rax, %rax
je 0x4260
movq -0x40(%rbp), %rdi
movq %r15, %rsi
callq 0x53c2
movq %r15, %rsi
movq 0x28(%rax), %r12
movq 0x30(%rax), %r15
movq -0x68(%rbp), %rdi
callq 0x53c2
subq %r12, %r15
movq 0x30(%rax), %rcx
subq 0x28(%rax), %rcx
cmpq %rcx, %r15
movq %r14, %r15
jne 0x4a96
movq -0x40(%rbp), %rdi
movq %r15, %rsi
callq 0x53c2
testq %rax, %rax
jne 0x42b0
xorps %xmm0, %xmm0
movaps %xmm0, -0x60(%rbp)
andq $0x0, -0x50(%rbp)
leaq -0x120(%rbp), %r12
movq %r12, %rdi
movq %r15, %rsi
leaq -0x60(%rbp), %rdx
callq 0x4d86
movq -0x40(%rbp), %rdi
movq %r12, %rsi
callq 0x5538
movq %r12, %rdi
callq 0x4dbc
leaq -0x60(%rbp), %rdi
callq 0x2d80
movq -0x40(%rbp), %rdi
movq %r15, %rsi
callq 0x53c2
movq %rax, %r15
leaq -0x90(%rbp), %rdi
xorl %esi, %esi
callq 0x4cce
addq $0x28, %r15
movq %r15, %rdi
movq %rax, %rsi
callq 0x2556
pushq $0x1
popq %r12
jmp 0x45c0
cmpl $0x1, %r12d
jne 0x49a4
movq -0x88(%rbp), %rax
subq -0x90(%rbp), %rax
cmpq $0x41, %rax
jae 0x49d0
leaq -0x90(%rbp), %rdi
xorl %esi, %esi
callq 0x4cce
movq %rax, %rdi
movq %r14, %r15
movq %r14, %rsi
callq 0x2030
testl %eax, %eax
je 0x49ec
movq -0x70(%rbp), %rdi
movq %r15, %rsi
callq 0x58a8
testq %rax, %rax
jne 0x437b
xorps %xmm0, %xmm0
movaps %xmm0, -0x60(%rbp)
andq $0x0, -0x50(%rbp)
leaq -0x120(%rbp), %r12
movq %r12, %rdi
movq %r15, %rsi
leaq -0x60(%rbp), %rdx
callq 0x4ddc
movq -0x70(%rbp), %rdi
movq %r12, %rsi
callq 0x5afc
movq %r12, %rdi
callq 0x4e12
leaq -0x60(%rbp), %rdi
callq 0x4e32
movq -0x88(%rbp), %rax
subq -0x90(%rbp), %rax
cmpq $0x20, %rax
jne 0x44b8
movq -0x70(%rbp), %rdi
movq %r15, %rsi
callq 0x58a8
movq %rax, %r15
leaq -0x90(%rbp), %rdi
xorl %esi, %esi
callq 0x4cce
movq %rax, %r12
leaq -0x120(%rbp), %rdi
pushq $0x64
popq %rsi
callq 0x4e9f
addq $0x28, %r15
movq %r15, %rdi
movq %r12, %rsi
leaq -0x120(%rbp), %r15
movq %r15, %rdx
callq 0x4e5e
movq %r15, %rdi
jmp 0x45b7
movq -0xa8(%rbp), %rdi
movq %r14, %rsi
callq 0x3b92
movq %rax, -0xa0(%rbp)
leaq -0xd0(%rbp), %rdi
leaq 0x2e0f(%rip), %rsi      # 0x7216
leaq -0x33(%rbp), %rdx
callq 0x2090
leaq -0x140(%rbp), %r12
movq %r12, %rdi
movq -0x98(%rbp), %rsi
leaq -0x32(%rbp), %rdx
callq 0x2090
leaq -0x60(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
movq %r12, %rdx
callq 0x4d15
leaq -0x168(%rbp), %r12
movq %r12, %rdi
leaq 0x2dec(%rip), %rsi      # 0x723a
leaq -0x31(%rbp), %rdx
callq 0x2090
leaq -0x120(%rbp), %r15
movq %r15, %rdi
leaq -0x60(%rbp), %rsi
movq %r12, %rdx
callq 0x4d15
movq -0xa0(%rbp), %rdi
movq %r15, %rsi
callq 0x22c0
movq %r15, %rdi
callq 0x20d0
leaq -0x168(%rbp), %rdi
callq 0x20d0
leaq -0x60(%rbp), %rdi
callq 0x20d0
leaq -0x140(%rbp), %rdi
callq 0x20d0
leaq -0xd0(%rbp), %rdi
callq 0x20d0
pushq $0x3
jmp 0x45be
leaq -0x90(%rbp), %rdi
pushq $0x1
popq %rsi
callq 0x4cce
movq %rax, %rdi
leaq 0x2e68(%rip), %rsi      # 0x7339
xorl %edx, %edx
callq 0x2120
cmpq $-0x1, %rax
jne 0x4a6a
movq -0x70(%rbp), %rdi
movq %r14, %rsi
callq 0x58a8
movq %rax, %r15
leaq -0x90(%rbp), %rdi
xorl %esi, %esi
callq 0x4cce
movq %rax, %r12
leaq -0x90(%rbp), %rdi
pushq $0x1
popq %rsi
callq 0x4cce
addq $0x28, %r15
movq %r15, %rdi
movq %r12, %rsi
movq %rax, %rdx
callq 0x4f00
pushq $0x1
popq %r12
jmp 0x45c0
leaq -0x60(%rbp), %rdi
leaq 0x2ce0(%rip), %rsi      # 0x7217
leaq -0xd0(%rbp), %rdx
callq 0x2090
leaq -0x120(%rbp), %rdi
movq %r15, %rsi
leaq -0x60(%rbp), %rdx
callq 0x4cf0
movq %r12, %rdi
leaq -0x120(%rbp), %r15
movq %r15, %rsi
callq 0x3a5e
jmp 0x45ab
testq %rax, %rax
jne 0x4942
leaq -0x60(%rbp), %rdi
leaq 0x2c99(%rip), %rsi      # 0x7217
leaq -0xd0(%rbp), %rdx
callq 0x2090
leaq -0x120(%rbp), %r15
movq %r15, %rdi
movq %r14, %rsi
leaq -0x60(%rbp), %rdx
callq 0x4cf0
movq %r12, %rdi
movq %r15, %rsi
callq 0x3a5e
movq %r15, %rdi
callq 0x2de2
leaq -0x60(%rbp), %rdi
callq 0x20d0
pushq $0x1
popq %r12
leaq -0x90(%rbp), %rdi
callq 0x2d80
movq %r14, %r15
jmp 0x3d65
movq %r13, -0xd8(%rbp)
movq -0xe0(%rbp), %rax
movq (%rax), %r14
movq 0x69dc(%rip), %r13      # 0xafc8
movq (%r13), %rcx
leaq 0x2e23(%rip), %rdi      # 0x741a
pushq $0xd
popq %rsi
pushq $0x1
popq %rdx
callq 0x22b0
pushq $0x1
popq %r15
leaq -0x120(%rbp), %r12
leaq -0xd0(%rbp), %rbx
testq %r14, %r14
je 0x482e
leaq 0x8(%r14), %rsi
movq %r12, %rdi
callq 0x2220
leaq 0x28(%r14), %rsi
leaq -0x60(%rbp), %rdi
callq 0x2220
movq (%r14), %r14
movq (%r13), %rdi
movq -0x120(%rbp), %rcx
leaq 0x2ddd(%rip), %rsi      # 0x7428
movl %r15d, %edx
xorl %eax, %eax
callq 0x2230
movq (%r13), %rsi
movq -0x60(%rbp), %rdi
callq 0x21a0
movq -0x70(%rbp), %rdi
movq %r12, %rsi
callq 0x58a8
testq %rax, %rax
movl %r15d, -0xb0(%rbp)
je 0x4727
movq %r14, -0xe0(%rbp)
movq (%r13), %rcx
leaq 0x2da0(%rip), %rdi      # 0x7430
pushq $0xe
popq %rsi
pushq $0x1
popq %rdx
callq 0x22b0
movq -0x70(%rbp), %rdi
movq %r12, %rsi
callq 0x58a8
addq $0x28, %rax
movq %rbx, %rdi
movq %rax, %rsi
callq 0x4f42
xorl %r12d, %r12d
movq -0xc8(%rbp), %rax
subq -0xd0(%rbp), %rax
sarq $0x6, %rax
cmpq %rax, %r12
jae 0x470a
movq (%r13), %r15
movq %rbx, %rdi
movq %r12, %rsi
callq 0x4f96
movq 0x20(%rax), %r14
movq %rbx, %rdi
movq %r12, %rsi
callq 0x4f96
movq (%rax), %rcx
movq %r15, %rdi
leaq 0x2d44(%rip), %rsi      # 0x743f
movq %r14, %rdx
xorl %eax, %eax
callq 0x2230
incq %r12
jmp 0x46b9
movq %rbx, %rdi
callq 0x4e32
movq -0xe0(%rbp), %r14
movl -0xb0(%rbp), %r15d
leaq -0x120(%rbp), %r12
movq -0x40(%rbp), %rdi
movq %r12, %rsi
callq 0x53c2
testq %rax, %rax
je 0x4815
movq (%r13), %rcx
leaq 0x2d0b(%rip), %rdi      # 0x7452
pushq $0x17
popq %rsi
pushq $0x1
popq %rdx
callq 0x22b0
movq -0x40(%rbp), %rdi
movq %r12, %rsi
callq 0x61d8
movq %rbx, %rdi
movq %rax, %rsi
callq 0x4fb8
movq %r14, %r15
movq -0x68(%rbp), %rdi
movq %r12, %rsi
callq 0x61d8
leaq -0x140(%rbp), %rdi
movq %rax, %rsi
callq 0x4fb8
xorl %r12d, %r12d
movq -0xc8(%rbp), %rax
subq -0xd0(%rbp), %rax
sarq $0x5, %rax
cmpq %rax, %r12
jae 0x47f0
movq (%r13), %r14
movq %rbx, %rdi
movq %r12, %rsi
callq 0x4cce
movq (%rax), %rdx
movq %r14, %rdi
leaq 0x2cad(%rip), %rsi      # 0x746a
xorl %eax, %eax
callq 0x2230
movq (%r13), %r14
leaq -0x140(%rbp), %rdi
movq %r12, %rsi
callq 0x4cce
movq (%rax), %rdx
movq %r14, %rdi
leaq 0x2c94(%rip), %rsi      # 0x7478
xorl %eax, %eax
callq 0x2230
incq %r12
jmp 0x478a
leaq -0x140(%rbp), %rdi
callq 0x2d80
movq %rbx, %rdi
callq 0x2d80
movq %r15, %r14
movl -0xb0(%rbp), %r15d
leaq -0x120(%rbp), %r12
incl %r15d
leaq -0x60(%rbp), %rdi
callq 0x20d0
movq %r12, %rdi
callq 0x20d0
jmp 0x4614
movq (%r13), %rcx
leaq 0x2c4b(%rip), %rdi      # 0x7484
pushq $0x13
popq %rsi
pushq $0x1
popq %rdx
callq 0x22b0
movq -0x148(%rbp), %rax
movq (%rax), %r15
pushq $0x1
popq %r12
leaq -0x60(%rbp), %r14
testq %r15, %r15
je 0x48c1
leaq 0x8(%r15), %rsi
leaq -0x120(%rbp), %rdi
callq 0x2220
leaq 0x28(%r15), %rsi
movq %r14, %rdi
callq 0x2220
movq (%r15), %r15
movq (%r13), %rdi
leal 0x1(%r12), %ebx
movq -0x120(%rbp), %rcx
leaq 0x2b97(%rip), %rsi      # 0x7428
movl %r12d, %edx
xorl %eax, %eax
callq 0x2230
movq (%r13), %rsi
movq -0x60(%rbp), %rdi
callq 0x21a0
movq %r14, %rdi
callq 0x20d0
leaq -0x120(%rbp), %rdi
callq 0x20d0
movl %ebx, %r12d
jmp 0x4856
movq (%r13), %rcx
leaq 0x2bc5(%rip), %rdi      # 0x7491
pushq $0x6
popq %rsi
pushq $0x1
popq %rdx
callq 0x22b0
movq -0xd8(%rbp), %rdi
callq 0x21d0
movq -0x98(%rbp), %rdi
callq 0x21d0
leaq -0x188(%rbp), %rdi
callq 0x20d0
addq $0x168, %rsp            # imm = 0x168
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x66cc(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x2842(%rip), %rsi      # 0x7160
jmp 0x4931
movq 0x66b9(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x2846(%rip), %rsi      # 0x7177
movl %ebx, %edx
xorl %eax, %eax
callq 0x2230
pushq $0x1
popq %rdi
callq 0x21e0
movq 0x6697(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x2868(%rip), %rsi      # 0x71bb
jmp 0x4931
movq 0x6684(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x2a98(%rip), %rsi      # 0x73fe
movl %r15d, %edx
jmp 0x4933
movq 0x666e(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x281d(%rip), %rsi      # 0x7199
jmp 0x4931
movq 0x665b(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x285d(%rip), %rsi      # 0x71ec
jmp 0x4931
movq 0x6648(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x2a38(%rip), %rsi      # 0x73da
jmp 0x4931
movq 0x6635(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x29b5(%rip), %rsi      # 0x736a
jmp 0x4931
movq 0x661f(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x29c3(%rip), %rsi      # 0x738e
jmp 0x4931
movq 0x6609(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x28f0(%rip), %rsi      # 0x72d1
leaq 0x290a(%rip), %rcx      # 0x72f2
movl %ebx, %edx
jmp 0x4a06
movq 0x65ed(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x2912(%rip), %rsi      # 0x730f
movl %ebx, %edx
movq -0x98(%rbp), %rcx
xorl %eax, %eax
callq 0x2230
jmp 0x493a
movq 0x65c7(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x298d(%rip), %rsi      # 0x73b0
jmp 0x4931
movq 0x65b1(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x284c(%rip), %rsi      # 0x7285
jmp 0x4931
movq 0x659b(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x285e(%rip), %rsi      # 0x72ad
jmp 0x4931
movq 0x6585(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x27fc(%rip), %rsi      # 0x7261
jmp 0x4931
movq 0x656f(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x28c9(%rip), %rsi      # 0x7344
jmp 0x4931
movq 0x6559(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x2787(%rip), %rsi      # 0x7218
jmp 0x4931
movq 0x6543(%rip), %rax      # 0xafe0
movq (%rax), %rdi
leaq 0x2795(%rip), %rsi      # 0x723c
jmp 0x4931
jmp 0x4aba
jmp 0x4acb
jmp 0x4bf2
jmp 0x4bf2
movq %rax, %rbx
leaq -0x120(%rbp), %rdi
callq 0x4dbc
jmp 0x4ace
movq %rax, %rbx
leaq -0x60(%rbp), %rdi
callq 0x2d80
jmp 0x4bf5
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bb9
jmp 0x4bca
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bb9
jmp 0x4bca
jmp 0x4bf2
movq %rax, %rbx
leaq -0x120(%rbp), %rdi
callq 0x4e12
jmp 0x4b22
movq %rax, %rbx
leaq -0x60(%rbp), %rdi
callq 0x4e32
jmp 0x4bf5
jmp 0x4bb9
jmp 0x4bca
jmp 0x4bf2
jmp 0x4b4e
jmp 0x4b5f
jmp 0x4b70
jmp 0x4b7e
jmp 0x4b96
jmp 0x4bf2
movq %rax, %rbx
leaq -0x120(%rbp), %rdi
callq 0x20d0
jmp 0x4b62
movq %rax, %rbx
leaq -0x168(%rbp), %rdi
callq 0x20d0
jmp 0x4b73
movq %rax, %rbx
leaq -0x60(%rbp), %rdi
callq 0x20d0
jmp 0x4b81
movq %rax, %rbx
leaq -0x140(%rbp), %rdi
callq 0x20d0
leaq -0xd0(%rbp), %rdi
jmp 0x4bd1
movq %rax, %rbx
jmp 0x4b8d
jmp 0x4bf2
movq %rax, %rbx
leaq -0x120(%rbp), %rdi
jmp 0x4bd1
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
movq %rax, %rbx
leaq -0x120(%rbp), %rdi
callq 0x2de2
jmp 0x4bcd
movq %rax, %rbx
leaq -0x60(%rbp), %rdi
callq 0x20d0
jmp 0x4bf5
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4bf2
jmp 0x4c25
movq %rax, %rbx
jmp 0x4c8b
movq %rax, %rbx
leaq -0x90(%rbp), %rdi
callq 0x2d80
jmp 0x4c28
jmp 0x4c25
movq %rax, %rbx
leaq -0x120(%rbp), %rdi
callq 0x20d0
jmp 0x4c28
jmp 0x4c35
jmp 0x4c25
movq %rax, %rbx
movq -0x30(%rbp), %r15
jmp 0x4c73
jmp 0x4c35
movq %rax, %rbx
movq -0x30(%rbp), %r15
jmp 0x4c7f
jmp 0x4c35
movq %rax, %rbx
jmp 0x4c49
movq %rax, %rbx
jmp 0x4c66
movq %rax, %rbx
leaq -0x140(%rbp), %rdi
callq 0x2d80
leaq -0xd0(%rbp), %rdi
callq 0x2d80
jmp 0x4c66
movq %rax, %rbx
leaq -0xd0(%rbp), %rdi
callq 0x4e32
movq -0x30(%rbp), %r15
leaq -0x60(%rbp), %rdi
callq 0x20d0
leaq -0x120(%rbp), %rdi
callq 0x20d0
leaq -0x188(%rbp), %rdi
callq 0x20d0
leaq 0x118(%r15), %rdi
callq 0x50b2
movq -0xa8(%rbp), %rdi
callq 0x2e10
movq -0x68(%rbp), %rdi
callq 0x51d6
movq -0x40(%rbp), %rdi
callq 0x51d6
movq -0x70(%rbp), %rdi
callq 0x52ba
movq %r15, %rdi
callq 0x2e10
movq %rbx, %rdi
callq 0x22a0