0707070000020074741006440001500000000000010534260372074576400000500000000003Size80 0707070000020074451006440001500000000000010436100372074576400000500000000036NameOthello - v1.0 - Rick Sladkey 0707070000020073771007550001500000000000010534310372074576500001000000001345Install# Install - installation program for othello - rick sladkey cat </dev/rfp021 cpio: all cpio -oBcv OTHELLO+IN .c: cc -c $(CFLAGS) $< ld $(LDFLAGS) $(SHLIB) $(<:.c=.o) -o $* rm $(<:.c=.o) 0707070000020074221006440001500000000000010534410372221646700001200000044712othello.c/* othello.c - the game of othello on the unix pc - rick sladkey */ #include #include #include #include #include #include #include #ifndef VERSION #define VERSION "Othello v1.0" #endif #define AUTHOR "Rick Sladkey" #define ADDRESS "ihnp4!mvgpa!mvjrs" #define TITLE "Othello" /* label for all windows */ #define DEFSDEPTH 2 /* search two levels past current */ #define EMPTY 0 /* nothing in square */ #define WHITE 1 /* white piece in square */ #define BLACK (-1) /* black piece in square */ #define IDIOTIC 0 #define EASY 1 #define MEDIUM 2 #define HARD 3 #define GREEDY 4 #define PNAME(p) ((p) == WHITE ? "White" : "Black") #define OTHER(pc) (-(pc)) #define INRANGE(z) (((unsigned) (z)) < 8) /* fast */ /* #define INRANGE(z) ((z) >= 0 && (z) < 8) /* slow */ #define ASPECT 8 / 5 /* aspect ratio to make squares */ #define BOXH 20 /* box height */ #define BOXW (BOXH * ASPECT) /* box width */ #define WINH (BOXH * 8 / 12 + 3) #define WINW (BOXW * 8 / 9 + 5) #define CX 20 /* x offset in window */ #define CY 15 /* y offset in window */ /* mouse button bits */ #define LEFTB 4 #define MIDDLEB 2 #define RIGHTB 1 struct state { /* state of the game at any point */ int player; /* whose turn is it */ int x; /* move for that player */ int y; char cell[8][8]; /* board configuration */ }; /* relative strategic value of have a piece on a given square */ #define CORNER 100 /* love those corners */ #define ADJC -25 /* edge adjacent to corner */ #define FEDGE 5 /* edge two from corner */ #define EDGE 3 /* normal edge */ #define NORMAL 1 /* all other squares */ int relval[8][8] = { CORNER, ADJC, FEDGE, EDGE, EDGE, FEDGE, ADJC, CORNER, ADJC, ADJC, NORMAL, NORMAL, NORMAL, NORMAL, ADJC, ADJC, FEDGE, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, FEDGE, EDGE, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, EDGE, EDGE, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, EDGE, FEDGE, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, FEDGE, ADJC, ADJC, NORMAL, NORMAL, NORMAL, NORMAL, ADJC, ADJC, CORNER, ADJC, FEDGE, EDGE, EDGE, FEDGE, ADJC, CORNER, }; unsigned short whiterast[] = { /* raster pattern for white piece */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe000, 0x001f, 0xfc00, 0x00ff, 0xfe00, 0x01ff, 0xff00, 0x03ff, 0xff00, 0x03ff, 0xff00, 0x03ff, 0xff00, 0x03ff, 0xff00, 0x03ff, 0xfe00, 0x01ff, 0xfc00, 0x00ff, 0xe000, 0x001f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, }; unsigned short blackrast[] = { /* raster pattern for black piece */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf000, 0x003f, 0x1c00, 0x00e0, 0x0600, 0x0180, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0300, 0x0600, 0x0180, 0x1c00, 0x00e0, 0xf000, 0x003f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, }; #define PCWID 4 /* raster widths in bytes */ /* icon structures for mouse pointer when making moves */ struct icon whiteicon[1] = { 0, { BOXW - 1, BOXH - 1, -(BOXW / 2), -(BOXH / 2), 0, 0, 0 }, 0 /* raster gets copied here */ }; struct icon blackicon[1] = { 0, { BOXW - 1, BOXH - 1, -(BOXW / 2), -(BOXH / 2), 0, 0, 0 }, 0 /* raster gets copied here */ }; /* global variables */ int level; /* easy, medium or hard */ int players; /* zero, one or two */ int computer; /* white or black */ char *progname; /* argv[0] for errors */ int w; /* the board window number */ struct state prevstate[1]; /* previous state in games */ int won; /* games won by computer */ int lost; /* games lost by computer */ int played; /* total games played */ int score; /* computer running difference */ char *logname; /* who am i playing */ char *home; /* and their home directory */ char logfile[256]; /* "$HOME/.othello.log" */ char author[] = AUTHOR; char address[] = ADDRESS; main(argc, argv) int argc; char **argv; { progname = argv[0]; if (argc > 1) testing(argc, argv); else { srand(time(NULL)); setup(); getstats(); options(); putstats(); } exit(0); } testing(argc, argv) int argc; char **argv; { int ngames = 20; int lev1 = 1; int lev2 = 0; int seed = -1; int errflag = 0; int c; struct state board[1]; int game; int p1; int sum1, sum2; extern int optind; extern char *optarg; while ((c = getopt(argc, argv, "s:n:a:b:")) != EOF) { switch (c) { case 's' : seed = atoi(optarg); break; case 'n' : ngames = atoi(optarg); break; case 'a' : lev1 = atoi(optarg); break; case 'b' : lev2 = atoi(optarg); break; case '?' : errflag++; break; } } argc -= optind; argv += optind; if (argc != 0) errflag++; if (errflag) { fprintf(stderr, "usage: %s [ -s seed -n ngames -a lev1 -b lev2 ]\n", progname); exit(1); } setbuf(stdout, NULL); srand(seed < 0 ? time(NULL) : seed); for (game = 0; game < ngames; game++) { newboard(board); p1 = rand() % 2 == 0 ? WHITE : BLACK; for (;;) { level = board->player == p1 ? lev1 : lev2; if (!hasmove(board)) { swap(board); if (!hasmove(board)) break; } else { selectmove(board); makemove(board); swap(board); } } sum1 = pcsum(board, p1); sum2 = pcsum(board, OTHER(p1)); printf("%8d %-8.8s %-8.8s %8d %8d %8d\n", game + 1, PNAME(p1), PNAME(OTHER(p1)), sum1, sum2, sum1 - sum2); } } options() { struct wstat ws[1]; struct umdata md[1]; int key; int x, y, b, r; for (;;) { clear(); mvaddstr(2, (WINW - strlen(VERSION)) / 2, VERSION); wprompt(w, "Select an option from the Function Keys"); slkon(w, " EASY", " GAME", " MEDIUM", " GAME", " HARD", " GAME", " TWO", "PLAYERS", " AUTO", " PLAY", " SHOW", " STATS", " HELP", "", " QUIT", "" ); wgetstat(w, ws); md->um_flags = MSDOWN; md->um_x = 0; md->um_y = 0; md->um_w = ws->width; md->um_h = ws->height; md->um_icon = NULL; wsetmouse(w, md); for (;;) { switch (key = wgetc(w)) { case Mouse: wreadmouse(w, &x, &y, &b, &r); case Enter: case Return: key = F3; break; case Help: key = F7; break; case F1: case F2: case F3: case F4: case F5: case F6: case F7: break; case F8: case Cancl: case s_Cancl: case Exit: case s_Exit: return; default: continue; } break; } slkoff(w); wprompt(w, ""); md->um_flags = 0; md->um_icon = NULL; wsetmouse(w, md); switch (key) { case F1: level = EASY; players = 1; play(); break; case F2: level = MEDIUM; players = 1; play(); break; case F3: level = HARD; players = 1; play(); break; case F4: players = 2; play(); break; case F5: level = HARD; players = 0; play(); break; case F6: stats(); break; case F7: help(); break; default: break; } } } stats() { clear(); mvaddstr(2, 6, "Statistics\n\n"); wprintf(w, " Total Games: %6d\n", played); wprintf(w, " Won by Computer: %6d\n", won); wprintf(w, " Won by You: %6d\n", lost); wprintf(w, " Running Score: %6d\n", -score); getenter(w); } help() { clear(); mvaddstr(2, 0, "\ Flip over your opponents\n\ pieces by outflanking them on\n\ both sides in any direction\n\ \n\ Mouse Buttons\n\ \n\ Left selects move\n\ Middle shows legal moves\n\ Right shows previous board\n\ " ); getenter(w); } play() { char prompt[80]; struct state board[1]; int x, y; if (players == 1) { computer = rand() % 2 == 0 ? WHITE : BLACK; message(MT_INFO, NULL, NULL, "%s\n%s %s\n", TITLE, "The computer will play", PNAME(computer)); } newboard(board); drawboard(); for (;;) { showboard(board); if (!hasmove(board)) { swap(board); if (!hasmove(board)) { endgame(board); break; } swap(board); message(MT_INFO, NULL, NULL, "%s\n%s %s\n", TITLE, PNAME(board->player), "has no legal move"); } else { if (players == 0) if (getenter(w) < 0) break; sprintf(prompt, "%s's Move", PNAME(board->player)); wprompt(w, prompt); if (players == 0) selectmove(board); else if (players == 1 && board->player == computer) selectmove(board); else if (getmove(prompt, board) < 0) break; *prevstate = *board; makemove(board); wprompt(w, ""); } swap(board); } } selectmove(s) struct state *s; { int i, j; /* vary over possible moves */ int val; /* relative value of a given move */ int best; /* best value so far */ int numbest; /* number found with that value */ int bestx[64], besty[64]; /* pairs of x and y for best values */ int choice; /* random selection from best */ numbest = 0; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) { s->x = i; s->y = j; val = value(s); if (val > 0 && (numbest == 0 || val >= best)) { if (numbest > 0 && val > best) numbest = 0; bestx[numbest] = i; besty[numbest] = j; numbest++; best = val; } } if (numbest > 0) { choice = rand() % numbest; s->x = bestx[choice]; s->y = besty[choice]; } } int value(s) struct state *s; { struct state sc[1]; int val; int pcs; if (!islegal(s)) return (0); *sc = *s; makemove(sc); swap(sc); pcs = numpieces(sc); switch (level) { case EASY: if (pcs > 48) val = lookahead(sc, s->player, 2); else val = lookahead(sc, s->player, 0); break; case MEDIUM: if (pcs > 48) val = lookahead(sc, s->player, 3); else val = lookahead(sc, s->player, 1); break; case HARD: if (pcs > 58) val = lookahead(sc, s->player, 6); else if (pcs > 52) val = lookahead(sc, s->player, 4); else val = lookahead(sc, s->player, 2); break; case GREEDY: val = pcsum(s->player) - pcsum(OTHER(s->player)); break; case IDIOTIC: default: val = 0; break; } return (val + 100000); } int lookahead(s, p, depth) register struct state *s; int p; int depth; { register short i, j; register int val; int c; int smart; struct state sc[1]; int nummoves; int min, max; if (depth == 0) { val = 0; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) { c = s->cell[i][j]; if (c == p) val += relval[i][j]; else if (c) val -= relval[i][j]; } return (val); } nummoves = 0; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) { s->x = i; s->y = j; if (islegal(s)) { *sc = *s; makemove(sc); swap(sc); val = lookahead(sc, p, depth - 1); if (nummoves == 0) max = min = val; else if (val < min) min = val; else if (val > max) max = val; nummoves++; } } if (nummoves == 0) { *sc = *s; swap(sc); if (!hasmove(sc)) return ((pcsum(sc, p) - pcsum(sc, OTHER(p))) * 1000); else return (lookahead(sc, p, depth - 1)); } if (p == s->player) return (max); else return (min); } endgame(s) struct state *s; { char *msg; int wsum, bsum; int diff; wsum = pcsum(s, WHITE); bsum = pcsum(s, BLACK); diff = wsum - bsum; if (players == 1) { if (computer != WHITE) diff = -diff; played++; score += diff; if (diff > 0) { msg = "The Computer Wins"; won++; } else if (diff == 0) msg = "A Tie"; else { msg = "You Win"; lost++; } } else { if (diff > 0) msg = "White Wins"; else if (diff == 0) msg = "A Tie"; else msg = "Black Wins"; } message(MT_INFO, NULL, NULL, "%s\n%s\n\nWhite: %2d, Black: %2d\n%s\n", TITLE, "Game Over", wsum, bsum, msg); } swap(s) struct state *s; { s->player = OTHER(s->player); } /* get a move from the keyboard and store it in the x and y of the state */ int getmove(prompt, s) char *prompt; struct state *s; { struct umdata md[1]; int c; int x, y, b, r; int val; int verbose = 0; /* enable mouse reports over boxes with piece shaped icon */ md->um_flags = MSDOWN; md->um_x = CX; md->um_y = CY; md->um_w = 8 * BOXW + 1; md->um_h = 8 * BOXH + 1; md->um_icon = s->player == WHITE ? whiteicon : blackicon; /* get a legal move or an exit request */ for (;;) { wsetmouse(w, md); wprompt(w, prompt); switch (c = wgetc(w)) { case Mouse: wreadmouse(w, &x, &y, &b, &r); if (!(b & LEFTB)) { if (b & MIDDLEB) { if (verbose) showboard(s); else showlegal(s); verbose = 1 - verbose; } else if (b & RIGHTB) { showprev(s); verbose = 0; } continue; } if (x < CX || y < CY) continue; s->x = (x - CX) / BOXW; s->y = (y - CY) / BOXH; if (!INRANGE(s->x) || !INRANGE(s->y)) continue; if (!islegal(s)) { beep(); continue; } val = 0; break; case Help: help(); drawboard(); showboard(s); verbose = 0; continue; case Exit: case s_Exit: case Cancl: case s_Cancl: val = -1; break; default: continue; } break; } md->um_flags = 0; md->um_icon = NULL; wsetmouse(w, md); return (val); } /* makemove() - effect a presumably legal move */ makemove(s) register struct state *s; { register short i, j; s->cell[s->x][s->y] = s->player; for (i = -1; i <= 1; i++) for (j = -1; j <= 1; j++) { if ((i || j) && flips(s, i, j)) flip(s, i, j); } } int islegal(s) register struct state *s; { register short i, j; if (s->cell[s->x][s->y] != EMPTY) return (0); for (i = -1; i <= 1; i++) for (j = -1; j <= 1; j++) { if ((i || j) && flips(s, i, j)) return (1); } return (0); } int pcsum(s, p) struct state *s; int p; { register short i, j; register short sum = 0; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) sum += s->cell[i][j] == p; return (sum); } int numpieces(s) struct state *s; { register short i, j; register short sum = 0; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) sum += s->cell[i][j] != EMPTY; return (sum); } int hasmove(s) register struct state *s; { register short i, j; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) { s->x = i; s->y = j; if (islegal(s)) return (1); } return (0); } int flips(s, i, j) register struct state *s; register short i, j; { register short x = s->x + i; register short y = s->y + j; int c; if (INRANGE(x) && INRANGE(y) && s->cell[x][y] == OTHER(s->player)) { x += i; y += j; while (INRANGE(x) && INRANGE(y)) { c = s->cell[x][y]; if (c == s->player) return (1); if (c == EMPTY) break; x += i; y += j; } } return (0); } flip(s, i, j) register struct state *s; register short i, j; { register short x = s->x + i; register short y = s->y + j; while (INRANGE(x) && INRANGE(y) && s->cell[x][y] == OTHER(s->player)) { s->cell[x][y] = s->player; x += i; y += j; } } /* newboard() - set up board for a new game */ newboard(s) struct state *s; { int i, j; s->player = BLACK; /* black always goes first */ s->x = s->y = -1; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) s->cell[i][j] = EMPTY; s->cell[3][3] = WHITE; s->cell[4][4] = WHITE; s->cell[3][4] = BLACK; s->cell[4][3] = BLACK; } /* showprev() - show previous board for examination */ showprev(s) struct state *s; { showboard(prevstate); getenter(w); showboard(s); } showboard(s) struct state *s; { int i, j; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) putpiece(s->cell[i][j], i, j); } putpiece(pc, i, j) int pc; int i, j; { extern unsigned short patblack[]; wrastop(0, pc == WHITE ? whiterast : blackrast, PCWID, 0, 0, 0, 0, CX + i * BOXW + 1, CY + j * BOXH + 1, BOXW - 1, BOXH - 1, pc == EMPTY ? SRCPAT : SRCSRC, DSTSRC, patblack); } showlegal(s) struct state *s; { int i, j; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) { s->x = i; s->y = j; if (islegal(s)) putlegal(i, j); } } putlegal(i, j) int i, j; { int ox = CX + i * BOXW; int oy = CY + j * BOXH; rectangle(ox + BOXW / 4, oy + BOXH / 2, BOXW / 2 + 1, 1); rectangle(ox + BOXW / 2, oy + BOXH / 4, 1, BOXH / 2 + 1); } setup() { struct uwdata wd; FILE *fp; int i; if (ioctl(0, WIOCGETD, &wd) < 0) { fprintf(stderr, "%s: must run on bitmap", progname); exit(1); } close(0); close(1); close(2); fp = fopen("/dev/window", "r+"); dup(0); dup(0); winit(); w = wind(W_POPUP, WINH, WINW, BORDCANCEL | BORDHELP, 0); clear(); wlabel(w, TITLE); wuser(w, TITLE); wputs(w, "\033[=1C"); keypad(0, 1); windtrap(SIGWIND); for (i = 0; i < sizeof (whiterast) / sizeof (short); i++) whiteicon->ic_raster[i] = whiterast[i]; for (i = 0; i < sizeof (blackrast) / sizeof (short); i++) blackicon->ic_raster[i] = blackrast[i]; } getstats() { char *getenv(); FILE *ifp; logname = getenv("LOGNAME"); home = getenv("HOME"); sprintf(logfile, "%s/%s", home, ".othello.log"); if ((ifp = fopen(logfile, "r")) == NULL) { played = won = lost = score = 0; return; } fscanf(ifp, "%d%d%d%d", &played, &won, &lost, &score); fclose(ifp); } putstats() { FILE *ofp; if ((ofp = fopen(logfile, "w")) == NULL) return; fprintf(ofp, "%d %d %d %d\n", played, won, lost, score); fclose(ofp); } /* windtrap - catch window signal and update width and height appropriately */ windtrap(sig) int sig; { signal(sig, windtrap); } drawboard() { int i; clear(); rectangle(CX - 3, CY - 2, 1, 8 * BOXH + 5); rectangle(CX - 3, CY - 2, 8 * BOXW + 7, 1); rectangle(CX + 8 * BOXW + 3, CY - 2, 1, 8 * BOXH + 5); rectangle(CX - 3, CY + 8 * BOXH + 2, 8 * BOXW + 7, 1); for (i = 0; i <= 8; i++) rectangle(CX + i * BOXW, CY, 1, 8 * BOXH + 1); for (i = 0; i <= 8; i++) rectangle(CX, CY + i * BOXH, 8 * BOXW + 1, 1); } rectangle(x, y, w, h) int x, y, w, h; { extern unsigned short patwhite[]; wrastop(0, 0, 0, 0, 0, 0, 0, x, y, w, h, SRCPAT, DSTSRC, patwhite); } slkon(wn, f1t, f1b, f2t, f2b, f3t, f3b, f4t, f4b, f5t, f5b, f6t, f6b, f7t, f7b, f8t, f8b) int wn; char *f1t, *f1b, *f2t, *f2b, *f3t, *f3b, *f4t, *f4b; char *f5t, *f5b, *f6t, *f6b, *f7t, *f7b, *f8t, *f8b; { char slkt[128]; char slkb[128]; sprintf(slkt, " %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s ", f1t, f2t, f3t, f4t, f5t, f6t, f7t, f8t); sprintf(slkb, " %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s ", f1b, f2b, f3b, f4b, f5b, f6b, f7b, f8b); wslk(wn, 0, slkt, slkb, NULL); } slkoff(wn) int wn; { wslk(wn, 0, NULL, NULL, NULL); } int getenter(wn) { struct wstat ws[1]; struct umdata md[1]; int c; int x, y, b, r; int val; wgetstat(wn, ws); md->um_flags = MSDOWN; md->um_x = 0; md->um_y = 0; md->um_w = ws->width; md->um_h = ws->height; md->um_icon = NULL; wsetmouse(wn, md); wprompt(wn, "Press Enter to continue"); for (;;) { switch (c = wgetc(wn)) { case Mouse: wreadmouse(w, &x, &y, &b, &r); case Enter: case Return: val = 0; break; case Exit: case s_Exit: case Cancl: case s_Cancl: val = -1; break; default: continue; } break; } wprompt(wn, ""); md->um_flags = 0; md->um_icon = NULL; wsetmouse(wn, md); return (val); } 0707070000020074751007550001500000000000010534370372221666100001000000023464othelloRI H4x .textH .data 4 @.bss 4 4x.lib  /< N1X OQ./HJf/H#0N`NVp-@p-@Bp-@B`z ?gl ag> bgH ng sg`L.0&N1V-@`:.0&N1V-@`(.0&N1V-@`.0&N1V-@`R. /. /.N1P-@rfh 90"Ѯ JgRJg$. @/< /<0N1Pp.N1xp./<0N1XJl p.N1` ..N1pB`&HnN*XN1jJj DD`fp`p-@ .f .` .# 4HnNpXJfhHnN XHnNVXJf.HnNX-@ .D.HnNX-@ .././. .Drf* | >`(HnN4XHnN \XHnN 8X`P | D/ f | 2` | 8/ .R//< N1R .mN^NuNV` fHnHnHnHn/9 DN1T-|`6p# 4`p`p# 4p`p# 8`p# 4B 8Nd`6N:`0N`* b@0; NJ. J090 H/N1X. ON1 r!JjDD`.p/090 H/N1HP. \090 H/N1X. i/9 DN1rX. /< /< /< /< /< /< /< /< /< /< /< /< /< /< /< /9 DN @Hn/9 DN1P|BnBn=n=nBHn/9 DN1ZP. DN1-@ gB g8 gb gZ g^ gV gN gF g> g6 g. g g g fN^Nu-|. DN. /9 DN1rXB.BHn/9 DN1ZP .`NV. 090 H/N1Xp.p/090 H/N1HP. 090 H/N1X. /<  /9 DN1P. /< !/9 DN1P. /< 9/9 DN1P 9 D./< Q/9 DN1P. DNN^NuNV. i090 H/N1Xp.p/090 H/N1HP. n090 H/N1X. DN~N^NuNVX  8flN1jJj DD`fp`p# < f | X` | ^./< A/< 9/< /p//p/N14HndN XNHndN NXHndN XJfxHndN^XHndN XJfHndNHXN^NuHndN8X.  df | v` | |//< n/< dp//p/N14`J 8f. DNNJm df | ` | ./< HnN1PHn/9 DN1rPJ 8g  8f .d Jo .oB .C# .C#R-nR mR mjJoP-@`& n D.N$ n.N-@`B .`NVH$nJfx$`pv``0HC A00HH-@మ f0H*0H"| ر` Jg0H,0H"| ƘRC CmRB Bm LN^NuBt`v`0H%@0H%@.NJghAp Q HHnN XHnNX .S./. HnNP(Jf-D`l-D` o-DRRC CmvRB BmfJfvAp Q HnNvXHnNXJf4 . D.HnNXX.. HnNHX.N1` .S./. HnNFP` . f .` .`NVp./.NX-@p./.NX-@ .-@  8f  /< 2N1RX @-Hp.N1Np.N1NN1$p.p0/p!/p/p/N1# D. A090 H/N1X. F/9 DN1X. N/9 DN1X. V/9 DN1Xp.p/N1 Xp.NB`( .Ѐ"| =q .Ѐ"| 3R (eB`( .Ѐ"| P=q .Ѐ"| 43R (eN^NuNV. \N1 @# . dN1 @# . o//< i/< N1 . |/< N1RX @-Hfp# # # # N^Nu. /< /< /< /< ~/.N1.N1F`NV. /< N1RX @-Hg8. /9 /9 /9 /< /.N1.N1FN^NuNV.(/.N1nXN^NuNV. 090 H/N1X.p/p /p/N p./<p /p/N .p/p //<N p./</<p/N B`*.p/p/ ./NZ R oB`0p./< ."Ё/p/N R oN^NuNV.04p/p//././. /.p//p//p//p/N14N^NuNV.D/.