0,]']±>Sï}WÿÍu§ðp8·d%qy)6o;]ÉA¦ösï÷ôôôH]i, x then input_mngr:move_right() elseif self.target_cell.y < y then input_mngr:move_up() elseif self.target_cell.y > y then input_mngr:move_down() else input_mngr:press_select() self.target_cell = nil end end end, } function get_prior_score(field_size, my_marks, enemy_marks) local score = 0 if my_marks == field_size-1 then score = score + 1000 end if enemy_marks == field_size-1 then score = score + 500 end if my_marks >= 1 and my_marks < field_size-1 and enemy_marks == 0 then score = score + 50 end if enemy_marks >= 1 and enemy_marks < field_size-1 and my_marks == 0 then score = score + 5 end if my_marks == 0 and enemy_marks == 0 then score = score + 1 end return score end function ai:analys(field) local prior_map = {h = {}, v = {}, d1 = {}, d2 = {}} for i = 1, field:get_size() do prior_map.h[i] = {} prior_map.v[i] = {} prior_map.h[i][self.value] = 0 prior_map.v[i][self.value] = 0 prior_map.h[i][self.enemy_value] = 0 prior_map.v[i][self.enemy_value] = 0 end prior_map.d1[self.value] = 0 prior_map.d2[self.value] = 0 prior_map.d1[self.enemy_value] = 0 prior_map.d2[self.enemy_value] = 0 for i = 1, field:get_size() do for j = 1, field:get_size() do local cell = field:get_cell(j, i) if cell ~= 0 then prior_map.h[i][cell] = prior_map.h[i][cell] + 1 prior_map.v[j][cell] = prior_map.v[j][cell] + 1 if i == j then prior_map.d1[cell] = prior_map.d1[cell] + 1 end if i == field:get_size()+1-j then prior_map.d2[cell] = prior_map.d2[cell] + 1 end end end end best_cell = {score = -1, x = 0, y = 0} for i = 1, field:get_size() do for j = 1, field:get_size() do local cur_score = -1 if field:get_cell(j, i) == 0 then cur_score = get_prior_score(field:get_size(), prior_map.h[i][self.value], prior_map.h[i][self.enemy_value]) + get_prior_score(field:get_size(), prior_map.v[j][self.value], prior_map.v[j][self.enemy_value]) if i == j then cur_score = cur_score + get_prior_score(field:get_size(), prior_map.d1[self.value], prior_map.d1[self.enemy_value]) end if i == field:get_size()+1-j then cur_score = cur_score + get_prior_score(field:get_size(), prior_map.d2[self.value], prior_map.d2[self.enemy_value]) end end if cur_score > best_cell.score then best_cell.score = cur_score best_cell.x = j best_cell.y = i end end end return best_cell end function gen_input_map_field() local m = {} for i = 1, field:get_size() do m[i] = {} for j = 1, field:get_size() do local x, y = field:get_draw_cell_values(j, i) m[i][j] = {x, y} end end return m end screen_menu = { create = function(self, size) draw_mngr:clear() math.randomseed(tstamp()) self.win_moves = {} self.sprs_marks = sprs_b[math.random(1, #sprs_b)] field:set_size(size) draw_mngr:set_map(field:get_draw_map_values()) input_mngr:set(296, 1, { {{143, 63}, {191, 63}}, {{143, 70}, {191, 70}}, {{143, 77}, {191, 77}}, {{165, 94}, {165, 94}}, }) draw_mngr:add_spr("cursor", input_mngr:get_draw_cursor_values()) draw_mngr:add_text("title1", "TIC", 144, 8, 12, 2) draw_mngr:add_text("title2", "TAC", 171, 20, 12, 2) draw_mngr:add_text("title3", "TOE", 199, 32, 12, 2) draw_mngr:add_text("settings_title11", "FIELD", 152, 50) draw_mngr:add_text("settings_title12", "SIZE", 152, 56) draw_mngr:add_text("settings_title21", "GAME", 200, 50) draw_mngr:add_text("settings_title22", "MODE", 200, 56) self.field_mode = 3 draw_mngr:add_text("field_mode1", "3x3", 152, 65) draw_mngr:add_text("field_mode2", "4x4", 152, 72) draw_mngr:add_text("field_mode3", "5x5", 152, 79, 3) self.game_mode = 1 draw_mngr:add_text("game_mode1", "1p", 200, 65, 3) draw_mngr:add_text("game_mode2", "2p", 200, 72) draw_mngr:add_text("game_mode3", "demo", 200, 79) draw_mngr:add_text("start_button", "START", 174, 96) draw_mngr:add_spr("btnA", 314, 186, 113, 1) draw_mngr:add_text("btnA", "select", 197, 114) draw_mngr:add_spr("btnB", 315, 186, 122, 1) draw_mngr:add_text("btnB", "exit", 197, 123) end, dispose = function(self) screen = screen_game screen:create(self.field_mode, self.game_mode) end, update = function(self) input_mngr:btn_input() local input_code = input_mngr:get_input_code() if input_code == 1 then sfx(2) draw_mngr:set_spr("cursor", input_mngr:get_draw_cursor_values()) elseif input_code == 2 then local cur_x, cur_y = input_mngr:get_cursor_pos() if cur_y == 4 then sfx(1) return false else sfx(0) if cur_x == 1 then draw_mngr:set_text("field_mode"..self.field_mode, nil, nil, nil, 12) draw_mngr:set_text("field_mode"..cur_y, nil, nil, nil, 3) self.field_mode = cur_y else draw_mngr:set_text("game_mode"..self.game_mode, nil, nil, nil, 12) draw_mngr:set_text("game_mode"..cur_y, nil, nil, nil, 3) self.game_mode = cur_y end end end if btnp(5) then exit() end if t % 15 == 0 then for k, v in pairs(self.win_moves) do if v.id == -1 then local x = v.cells[v.index][1] local y = v.cells[v.index][2] draw_mngr:remove_spr("chk"..x..y) field:set_cell(x, y, 0) self.win_moves[k].index = v.index - 1 if self.win_moves[k].index == 0 then for k, v in pairs(v.cells) do draw_mngr:remove_spr("ovr"..v[1]..v[2]) end self.win_moves[k] = nil end elseif not fget(draw_mngr:get_spr_id(v.id), 0) then self.win_moves[k].id = -1 for k, v in pairs(v.cells) do draw_mngr:add_spr("ovr"..v[1]..v[2], 344, field:get_draw_cell_values(v[1], v[2])) end end end local x = math.random(1, field:get_size()) local y = math.random(1, field:get_size()) local id = "chk"..x..y if not fget(draw_mngr:get_spr_id(id), 0) and draw_mngr:get_spr_id("ovr"..x..y) == -1 then if field:get_cell(x, y) == 0 then local fill = math.random(1, #self.sprs_marks) draw_mngr:add_spr(id, self.sprs_marks[fill], field:get_draw_cell_values(x, y)) field:set_cell(x, y, fill) local val, cells = field:winning_move(x, y) if cells then self.win_moves[#self.win_moves + 1] = {cells = cells, index = field:get_size(), id = id} end else draw_mngr:remove_spr(id) field:set_cell(x, y, 0) end end end return true end, } screen_game = { create = function(self, field_mode, game_mode) draw_mngr:clear() self.field_mode = field_mode self.game_mode = game_mode self.game_over = false self.win_cells = nil field:set_size(field_mode+2) draw_mngr:set_map(field:get_draw_map_values()) input_mngr:set(312, 2, gen_input_map_field()) self.players = {} if game_mode == 1 then self.players = {player, ai} elseif game_mode == 2 then self.players = {player, copy_table(player)} else self.players = {ai, copy_table(ai)} end self.sprs_marks = sprs_b[3] for i, v in ipairs(self.players) do local rand = math.random(1, #self.sprs_marks) if i == 2 and self.sprs_marks[rand] == self.players[i-1]:get_spr_turn() then rand = another_player(rand, #self.sprs_marks) end v:create(self.sprs_marks[rand], game_mode ~= 1 and i or nil, i, another_player(i, #self.players)) draw_mngr:add_spr(v:get_name().."_icon", v:get_emoji_spr_id(), 144+((i-1)*50), 40) draw_mngr:add_spr(v:get_name().."_mark", v:get_spr_turn(), 162+((i-1)*50), 40) draw_mngr:add_text(v:get_name().."_score", "0", 152+((i-1)*50), 64, 12, 3) end draw_mngr:add_text(":", ":", 177, 64, 12, 3) self.cur_turn = math.random(1, #self.players) draw_mngr:add_text("text1", "", 144, 8, 12, 2) draw_mngr:add_text("text2", "", 144, 20) self.anim_id = self.players[self.cur_turn]:get_name().."_mark" draw_mngr:add_spr("btnA", 0, 172, 113, 1) draw_mngr:add_text("btnA", "", 183, 114) draw_mngr:add_spr("btnB", 315, 172, 122, 1) draw_mngr:add_text("btnB", "main menu", 183, 123) end, dispose = function(self) screen = screen_menu screen:create(field:get_size()) end, update = function(self) if btnp(5) then sfx(1) return false end if not fget(draw_mngr:get_spr_id(self.anim_id), 0) then self.anim_id = nil if self.game_over then local restart = false if self.game_mode == 3 then restart = (t - self.t) > 60 else input_mngr:btn_input() restart = input_mngr:get_input_code() == 2 end if restart then sfx(0) if self.win_cells then for i, v in ipairs(self.win_cells) do draw_mngr:remove_spr("ovr"..i) end end field:set_size(self.field_mode+2) self.cur_turn = math.random(1, #self.players) for i, v in ipairs(self.players) do draw_mngr:set_spr(v:get_name().."_icon", v:get_emoji_spr_id()) end self.win_cells = nil for i = 1, field:get_size() do for j = 1, field:get_size() do draw_mngr:remove_spr("chk"..i..j) end end self.game_over = false end elseif self.win_cells or field:get_remaining() == 0 then sfx(3) if self.win_cells then draw_mngr:set_text("text1", nil, nil, nil, 3) draw_mngr:set_text("text2", "win", nil, nil, 3) for i, v in ipairs(self.win_cells) do draw_mngr:add_spr("ovr"..i, 344, field:get_draw_cell_values(v[1], v[2])) end local player = {self.players[self.cur_turn], self.players[another_player(self.cur_turn, #self.players)]} player[1]:score_inc() draw_mngr:set_text(player[1]:get_name().."_score", player[1]:get_score()) local score_diff = player[1]:get_score() - player[2]:get_score() if score_diff >= 3 then draw_mngr:set_spr(player[1]:get_name().."_icon", player[1]:get_emoji_spr_id("happy")) draw_mngr:set_spr(player[2]:get_name().."_icon", player[2]:get_emoji_spr_id("angry")) else draw_mngr:set_spr(player[1]:get_name().."_icon", player[1]:get_emoji_spr_id("win")) if score_diff <= -3 then draw_mngr:set_spr(player[2]:get_name().."_icon", player[2]:get_emoji_spr_id("happy")) else draw_mngr:set_spr(player[2]:get_name().."_icon", player[2]:get_emoji_spr_id("lose")) end end else draw_mngr:set_text("text1", "Draw") draw_mngr:set_text("text2", "") end if self.game_mode ~= 3 then draw_mngr:set_spr("btnA", 314) draw_mngr:set_text("btnA", "restart") end self.t = t self.game_over = true else draw_mngr:add_spr("cursor", input_mngr:get_draw_cursor_values()) draw_mngr:set_text("text1", self.players[self.cur_turn]:get_name(), nil, nil, 12) draw_mngr:set_text("text2", "turn", nil, nil, 12) if self.game_mode ~= 3 then draw_mngr:set_spr("btnA", 314) draw_mngr:set_text("btnA", "turn") end self.players[self.cur_turn]:act(10) input_code = input_mngr:get_input_code() if input_code == 1 then sfx(2) elseif input_code == 2 then local x, y = input_mngr:get_cursor_pos() if field:get_cell(x, y) == 0 then sfx(0) self.anim_id = "chk"..x..y draw_mngr:add_spr(self.anim_id, self.players[self.cur_turn]:get_spr_turn(), field:get_draw_cell_values(x, y)) field:set_cell(x, y, self.players[self.cur_turn]:get_value()) local v v, self.win_cells = field:winning_move(x, y) if not self.win_cells then self.cur_turn = another_player(self.cur_turn, #self.players) end else sfx(4) end end end else draw_mngr:remove_spr("cursor") if self.game_mode ~= 3 then draw_mngr:set_spr("btnA", 0) draw_mngr:set_text("btnA", "") end end return true end, } function BOOT() screen = screen_menu screen:create(5) end function TIC() if not screen:update() then screen:dispose() end draw_mngr:draw() draw_mngr:update(15) t=t+1 end