U0 InitDefines() { I64 w = GR_WIDTH, h = GR_HEIGHT - FONT_HEIGHT, cols, rows, size = PopUpRangeI64(1,9,, "Size\n"), rad = 16 - size; if (size < 0) throw; DefinePrint("UNITS_NUM", "%d", 4096 / SqrI64(rad) & ~1); DefinePrint("CIRCLE_RAD", "%d", rad); DefinePrint("MOVE_CIRCLES", "%d", 65 / rad); cols = (w - 8 - rad) / (2 * rad) & ~1 - 1; DefinePrint("BORDER_X", "%d", (w + rad - cols * 2 * rad) / 2); rows = (h - 8) / (2 * rad) & ~1; DefinePrint("BORDER_Y","%d", (h - rows * 2 * rad) / 2); } InitDefines; class Unit { I64 num, x, y, player, link, color; Bool alive, king; } u[UNITS_NUM]; CDC *map_dc; I64 cur_player, num_alive[2], start_x, start_y, end_x, end_y; Bool show_start; U0 S2Circle(I64 *_x, I64 *_y) { I64 i, j; j = (*_y - BORDER_Y) / (CIRCLE_RAD * 2); if (j & 1) i = (*_x - CIRCLE_RAD - BORDER_X) / (CIRCLE_RAD * 2); else i = (*_x - BORDER_X) / (CIRCLE_RAD * 2); *_y = j; *_x = i; } U0 Circle2S(I64 *_x, I64 *_y) { I64 j = *_y, i = *_x; *_y = j * CIRCLE_RAD * 2 + CIRCLE_RAD + BORDER_Y; *_x = i * CIRCLE_RAD * 2 + CIRCLE_RAD + BORDER_X; if (j & 1) *_x += CIRCLE_RAD; } U0 S2W(I64 *_x, I64 *_y) { S2Circle(_x, _y); Circle2S(_x, _y); } U0 DrawIt(CTask *task, CDC *dc) { I64 i; map_dc->flags |= DCF_NO_TRANSPARENTS; GrBlot(dc, 0, 0, map_dc); if (cur_player == 0) { dc->color = LTCYAN; GrFloodFill(dc, 0, 0); dc->color = CYAN; } else { dc->color = LTPURPLE; GrFloodFill(dc, 0, 0); dc->color = PURPLE; } GrPrint(dc, 2, 2, "Player %d", cur_player + 1); for (i = 0; i < UNITS_NUM; i++) if (u[i].alive) { dc->color = u[i].color; GrFloodFill(dc, u[i].x, u[i].y); } for (i = 0; i < UNITS_NUM; i++) if (u[i].alive && !u[i].king) { dc->color = BLACK; GrLine(dc, u[i].x, u[i].y, u[u[i].link].x, u[u[i].link].y); if (Blink) { dc->color = BLUE; dc->thick = 6; GrPlot3(dc, (u[i].x + u[u[i].link].x) >> 1, (u[i].y + u[u[i].link].y) >> 1, 0); } } if (show_start) { dc->color = LTRED; GrLine(dc, start_x - 4, start_y - 4, start_x + 4, start_y + 4); GrLine(dc, start_x - 4, start_y + 4, start_x + 4, start_y - 4); GrLine(dc, start_x, start_y, end_x, end_y); } if ((num_alive[0] == 1 || num_alive[1] == 1) && Blink(4)) { dc->color = BLACK; GrPrint(dc, (task->pix_width - FONT_WIDTH * 9) >> 1, (task->pix_height - FONT_HEIGHT) >> 1, "Game Over"); } } Unit *UnitFind(I64 x, I64 y, I64 player) { I64 i, dd, best_dd = I64_MAX; Unit *res = NULL; for (i = 0; i < UNITS_NUM; i++) { if (u[i].player == player && u[i].alive) { dd = SqrI64(u[i].x - x) + SqrI64(u[i].y - y); if (dd < best_dd) { best_dd = dd; res = &u[i]; } } } return res; } U0 KillsCheck(I64 x1, I64 y1, I64 player) { I64 i, j, x2, y2, dd; Bool found; for (i = 0; i < UNITS_NUM; i++) { if (u[i].player != player && u[i].alive && !u[i].king) { x2 = (u[i].x + u[u[i].link].x) >> 1; y2 = (u[i].y + u[u[i].link].y) >> 1; dd = SqrI64(x2 - x1) + SqrI64(y2 - y1); if (dd <= (CIRCLE_RAD + 2) * (CIRCLE_RAD + 2)) { u[i].alive = FALSE; Sound(62); Sleep(100); Sound; Sleep(25); num_alive[u[i].player]--; do { found = FALSE; for (j = 0; j < UNITS_NUM; j++) if (u[j].alive && u[j].player != player && !u[j].king && !u[u[j].link].alive) { found = TRUE; u[j].alive = FALSE; Sound(62); Sleep(100); Sound; Sleep(25); num_alive[u[j].player]--; } } while (found); } } } } Bool UnitMove(Unit *tmpu, I64 x2, I64 y2) { I64 i, r, c, r2, c2, x = start_x, y = start_y; S2W(&x2, &y2); c2 = x2; r2 = y2; S2Circle(&c2, &r2); for (i = 0; i < MOVE_CIRCLES + 1; i++) { c = x; r = y; S2Circle(&c, &r); if (c == c2 && r == r2) { end_x = tmpu->x = x2; end_y = tmpu->y = y2; return TRUE; } if (r2 != r) { if (r&1) { if (c < c2) c++; } else { if (c > c2) c--; } } if (r2 > r) { x = c; y = ++r; Circle2S(&x, &y); } else if (r2 < r) { x = c; y = --r; Circle2S(&x, &y); } else if (c2 > c) { x = ++c; y = r; Circle2S(&x, &y); } else if (c2 < c) { x = --c; y = r; Circle2S(&x, &y); } } return FALSE; } CDC *DrawHexMap(I64 *_w, I64 *_h) { CDC *dc = DCNew(*_w, *_h); I64 i, j, x, y; *_w = (dc->width - BORDER_X * 2 - CIRCLE_RAD) / (CIRCLE_RAD * 2); *_h = (dc->height - BORDER_Y * 2) / (CIRCLE_RAD * 2); DCFill(dc, WHITE); dc->color =LTGRAY; for (j = 0; j < *_h; j++) { for (i = 0; i < *_w; i++) { x = i * CIRCLE_RAD * 2 + BORDER_X + CIRCLE_RAD; y = j * CIRCLE_RAD * 2 + BORDER_Y + CIRCLE_RAD; if (j & 1) x += CIRCLE_RAD; S2W(&x, &y); GrCircle(dc, x, y, CIRCLE_RAD); } } *_w *= CIRCLE_RAD * 2; *_h *= CIRCLE_RAD * 2; return dc; } U0 Init() { I64 i, j, j1, j2, dd, best_dd, best, w = Fs->pix_width, h = Fs->pix_height; map_dc = DrawHexMap(&w, &h); cur_player = 0; for (i = 0; i < UNITS_NUM / 2; i++) { u[i].num = i; u[i + UNITS_NUM / 2].num = i + UNITS_NUM / 2; ti_restart: u[i].y = FloorI64(RandU32 % h, CIRCLE_RAD * 2) + CIRCLE_RAD; u[i + UNITS_NUM / 2].y = h - 1 - u[i].y; j1 = u[i].y / (CIRCLE_RAD * 2); j2 = u[i + UNITS_NUM / 2].y / (CIRCLE_RAD * 2); u[i].y += BORDER_Y; u[i + UNITS_NUM / 2].y += BORDER_Y; if (!i) { u[i].x = CIRCLE_RAD; if (j1 & 1) goto ti_restart; } else u[i].x = FloorI64(RandU32 % ((w - CIRCLE_RAD * 2 * 2) / 2), CIRCLE_RAD * 2) + CIRCLE_RAD; u[i + UNITS_NUM / 2].x = w - 1 - u[i].x; if (j1 & 1) u[i].x += CIRCLE_RAD; if (j2 & 1) u[i + UNITS_NUM / 2].x += CIRCLE_RAD; u[i].x += BORDER_X; u[i + UNITS_NUM / 2].x += BORDER_X; S2W(&u[i].x, &u[i].y); S2W(&u[i + UNITS_NUM / 2].x, &u[i + UNITS_NUM / 2].y); u[i].player = 0; u[i + UNITS_NUM / 2].player = 1; u[i].alive = TRUE; u[i + UNITS_NUM / 2].alive = TRUE; if (!i) { u[i].color = LTCYAN; u[i + UNITS_NUM / 2].color = LTPURPLE; u[i].king = TRUE; u[i + UNITS_NUM / 2].king = TRUE; } else { u[i].color = CYAN; u[i + UNITS_NUM / 2].color = PURPLE; u[i].king = FALSE; u[i + UNITS_NUM / 2].king = FALSE; } } for (i = 0; i < UNITS_NUM / 2; i++) { if (!u[i].king) { best_dd = I64_MAX; for (j = 0; j < UNITS_NUM / 2; j++) { if (i != j) { dd = SqrI64(u[i].x - u[j].x) + SqrI64(u[i].y - u[j].y); if ((u[j].x < u[i].x || u[j].king) && dd < best_dd ) { best_dd = dd; best = j; } } } u[i].link = best; u[i + UNITS_NUM / 2].link = best + UNITS_NUM / 2; } } num_alive[0] = UNITS_NUM / 2; num_alive[1] = UNITS_NUM / 2; } U0 CleanUp() { DCDel(map_dc); } U0 TreeCheckers() { I64 message_code, arg1, arg2, ch, sc; Unit *tmpu; SettingsPush; //See SettingsPush MenuPush( "File {" " Abort(,CH_SHIFT_ESC);" " Exit(,CH_ESC);" "}" "Play {" " Restart(,'\n');" "}" ); AutoComplete; WinBorder; WinMax; DocCursor; DocClear; PopUpOk("Step on the link mid points.\n"); Fs->win_inhibit = WIG_TASK_DEFAULT - WIF_SELF_FOCUS - WIF_SELF_BORDER - WIF_FOCUS_TASK_MENU; try { cn_start: Init; tmpu = NULL; show_start = FALSE; Fs->draw_it = &DrawIt; while (TRUE) { message_code = MessageGet(&arg1, &arg2, 1 << MESSAGE_KEY_DOWN + 1 << MESSAGE_MS_L_DOWN + 1 << MESSAGE_MS_L_UP + 1 << MESSAGE_MS_MOVE); switch (message_code) { case MESSAGE_KEY_DOWN: switch (arg1) { case '\n': CleanUp; goto cn_start; case CH_ESC: case CH_SHIFT_ESC: goto cn_done; } break; case MESSAGE_MS_L_DOWN: if (num_alive[0] > 1 && num_alive[1] > 1) { tmpu = UnitFind(arg1, arg2, cur_player); end_x = start_x = tmpu->x; end_y = start_y = tmpu->y; show_start = TRUE; } break; case MESSAGE_MS_MOVE: if (tmpu) UnitMove(tmpu, arg1, arg2); break; case MESSAGE_MS_L_UP: UnitMove(tmpu, arg1, arg2); KillsCheck(tmpu->x, tmpu->y, cur_player); show_start = FALSE; tmpu = NULL; cur_player = 1 - cur_player; break; } } cn_done: MessageGet(,, 1 << MESSAGE_KEY_UP); } catch PutExcept; SettingsPop; CleanUp; MenuPop; } TreeCheckers;