Posts filled under: bot

WordSquared bot

Looks like i wrote a good enough bot for http://wordsquared.com/

Version 0.1b at youtube: http://www.youtube.com/watch?v=NilCjtRIvng
It was more laggy, than current :)

As below log shows, its completing words with 2-4w per 1s, but this affected only by my current internet connection.
Later i’ll move it to dedicated server in hetzner.de to test European’s speed.

P.S. from 3k point to 10k in 10 mins :) P.S.S. Still using http://wordsolver.net/ word’s database -.-

Logged as Bubonic Pestilence
Loading game .. OK
@ws.tiles: 1.678851842880249 parse: 0.00460505485534668
9958 6998 A DIRECTION: bottom SIZE: 11 WORD: ALB
9918 6997 H DIRECTION: left SIZE: 11 WORD: LECH
9958 6997 L DIRECTION: left SIZE: 11 WORD: EXCEL
9958 6996 B DIRECTION: right SIZE: 11 WORD: BECK
9959 6996 E DIRECTION: bottom SIZE: 11 WORD: EMEU
9961 6996 K DIRECTION: bottom SIZE: 11 WORD: KAYO
9921 6995 O DIRECTION: bottom SIZE: 11 WORD: OAT
9923 6995 E DIRECTION: top SIZE: 3 WORD: DYE
9961 6995 A DIRECTION: right SIZE: 11 WORD: AFT
9963 6995 T DIRECTION: bottom SIZE: 11 WORD: TAXI
9921 6994 A DIRECTION: left SIZE: 11 WORD: RAJA
9950 6994 J DIRECTION: right SIZE: 8 WORD: JAWS
9951 6994 A DIRECTION: top SIZE: 9 WORD: HANSA
9952 6994 W DIRECTION: top SIZE: 8 WORD: SHAW
9953 6994 S DIRECTION: bottom SIZE: 5 WORD: SAINS
9959 6994 E DIRECTION: left SIZE: 5 WORD: HAME
9963 6994 A DIRECTION: right SIZE: 11 WORD: AHI
9921 6993 T DIRECTION: right SIZE: 2 WORD: TI
9922 6993 I DIRECTION: bottom SIZE: 3 WORD: IRE
9945 6993 R DIRECTION: left SIZE: 3 WORD: PUR
9950 6993 A DIRECTION: left SIZE: 3 WORD: BA
9953 6993 A DIRECTION: right SIZE: 3 WORD: AVE
9955 6993 E DIRECTION: bottom SIZE: 6 WORD: EDS
9953 6992 I DIRECTION: left SIZE: 2 WORD: TI
9963 6992 I DIRECTION: right SIZE: 11 WORD: IN
9922 6991 E DIRECTION: left SIZE: 11 WORD: RE
9925 6990 E DIRECTION: bottom SIZE: 11 WORD: EF
9926 6990 A DIRECTION: bottom SIZE: 11 WORD: ADZ
9951 6985 E DIRECTION: bottom SIZE: 11 WORD: EF
9957 7029 I DIRECTION: left SIZE: 11 WORD: QI
9959 7029 I DIRECTION: right SIZE: 11 WORD: IF
9891 7028 R DIRECTION: right SIZE: 2 WORD: RE
9897 7028 B DIRECTION: bottom SIZE: 2 WORD: BE
9940 7028 E DIRECTION: right SIZE: 4 WORD: ED
9897 7027 E DIRECTION: left SIZE: 5 WORD: DICE
9897 7025 E DIRECTION: left SIZE: 11 WORD: WE
9942 7025 O DIRECTION: bottom SIZE: 3 WORD: OS
9961 7025 D DIRECTION: right SIZE: 11 WORD: DIG
9962 7025 I DIRECTION: top SIZE: 11 WORD: QI
9963 7025 G DIRECTION: bottom SIZE: 11 WORD: GINKS
9954 7024 Y DIRECTION: top SIZE: 11 WORD: BY

Oh shit! I did it! It so perfectly FARM NOW xDDD

First thanks

I really wish to say thanks to Panagiotis Peikidis for providing me advices, links to algorithms, and patience :) Without you, i couldn’t do anything, Thank you very much.

MovementRequestMessage -> AutoBan for 2 hours

Generally, if you want move using packets, u will notice, that without MovementCompleteMessage, after re-login, you’ll be teleported back to start position.

And 2nd “thing”, after MovementRequestMessage, without sending MovementCompleteMessage, you can’t move anymore xD

Fix… send MovementCompleteMessage… but if u send it too fast, after 20-30 steps u will be kicked and banned for two hours. Why?! Because it will look like you’re using SpeedHack.

That’s why you should use 250ms+ delay for EACH CELL YOU MOVE.

Dofus first AI… Roaming between wheet :) That later it will farm…

Oh yeah!

Now it can login, move, and say through console :)

Dofus bot can speak

[ INFO] [D2I] Parsing i18n_en.d2i
[ INFO] [D2O] Parsing InfoMessages.d2o
[ INFO] [D2O] Parsing Servers.d2o
[ INFO] [D2O] Parsing ChatChannels.d2o
[ INFO] Connected
[   OK] Authentification successful
[ INFO] Connected
[   OK] Ticket accepted
[ INFO] Position in character selection queue: 1 / 1
[ INFO] Position in character selection queue: 0 / 0
[ INFO] Position in character selection queue: 0 / 0
[ INFO] Character weight: 14 / 1000
[   OK] Welcome to DOFUS, and welcome to the World of Twelve! Remember that it is <b>strictly forbidden</b> to disclose your account name or password.
[   OK] This account was last accessed on 13/07/2011 at 05:02.
[CHAT] [GENERAL]               : oops
[CHAT] [GENERAL]               : like i didn't did it wrong?!
[CHAT] [GENERAL]               : heh
[CHAT] [PRIVATE]               : asd
[CHAT] [PRIVATE]               : wanna join me ? )
say hellow world )
[CHAT] [GENERAL]          : hellow world )
say bla bla bla
[CHAT] [GENERAL]          : bla bla bla

Dofus «login -> game» sequence

Just got it…

def check_connection
  recv # receive packets

  case @state
  when STATE_NOT_CONNECTED
    reconnect
  when STATE_CONNECTED_TO_LOGIN
    @packets.pop do |packet|
      case packet
      when Com::AnkamaGames::Dofus::Network::Messages::Handshake::ProtocolRequired
        if packet.requiredVersion > $config.protocol_build
          log("Current protocol build: #{$config.protocol_build}, required build: #{packet.requiredVersion}", Logger::FATAL)
        end

        if packet.currentVersion < $config.protocol_required_build
          log("Current protocol build: #{$config.protocol_required_build}, is too new for the server version: #{packet.currentVersion}", Logger::FATAL)
        end
      when HelloConnectMessage
        $config.session_key = packet.sessionKey

        im = IdentificationMessage.new
        bytes = im.build!({
          username: $config.username,
          password: $config.password,
          version: $config.version,
          session_key: $config.session_key
        })

        send_data bytes
      when Com::AnkamaGames::Dofus::Network::Messages::Queues::LoginQueueStatusMessage
        l("Position in login queue: #{packet.position} / #{packet.total}")
      when IdentificationSuccessMessage
        l('Authentification successful', Logger::OK)
        @state = STATE_SERVERS_LIST
      else
        l("Incorrect packet at $net.STATE_CONNECTED_TO_LOGIN: #{packet.class}", Logger::FATAL)
      end
    end
  when STATE_SERVERS_LIST
    @packets.pop do |packet|
      case packet
      when ServersListMessage
        if !$config.server_id
          "Select server:".to_block(10) {
            packet.servers.select { |s| s.status == s.class::STATUS_ONLINE }.each do |s|
              printf("%5d %s %d %s\n", s.id, "-", s.charactersCount, s.status_t)
            end
          }

          while line = gets do
            line.strip!
            next if line.empty?

            exit if line.to_i == 0

            server = packet.servers.find { |s| s.id == line.to_i }
            next unless server

            $config.server_id = server.id
            break
          end
        end

        ssm = ServerSelectionMessage.new.build!($config.server_id)
        send_data ssm
      when SelectedServerDataMessage
        @ip = packet.address
        @port = packet.port
        $config.ticket = packet.ticket

        reconnect

        @state = STATE_CONNECTED_TO_GAME
      else
        l("Incorrect packet at $net.STATE_SERVERS_LIST: #{packet.class}", Logger::FATAL)
      end
    end
  when STATE_CONNECTED_TO_GAME
    @packets.pop do |packet|
      case packet
      when Com::AnkamaGames::Dofus::Network::Messages::Handshake::ProtocolRequired
        if packet.requiredVersion > $config.protocol_build
          log("Current protocol build: #{$config.protocol_build}, required build: #{packet.requiredVersion}", Logger::FATAL)
        end

        if packet.currentVersion < $config.protocol_required_build
          log("Current protocol build: #{$config.protocol_required_build}, is too new for the server version: #{packet.currentVersion}", Logger::FATAL)
        end
      when HelloGameMessage
        atm = AuthenticationTicketMessage.new.build!('en', $config.ticket)
        send_data atm
      when AuthenticationTicketAcceptedMessage
        l("Ticket accepted", Logger::OK)
      when Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::BasicTimeMessage
        # nothing to do, just ignore
      when Com::AnkamaGames::Dofus::Network::Messages::Game::Approach::AccountCapabilitiesMessage
        $config.account_id = packet.account_id

        clrm = Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharactersListRequestMessage.new.build!
        send_data clrm

        @state = STATE_CHARACTER_SELECTION
      else
        l("Incorrect packet at $net.STATE_CONNECTED_TO_GAME: #{packet.class}", Logger::FATAL)
      end
    end
  when STATE_CHARACTER_SELECTION
    @packets.pop do |packet|
      case packet
      when Com::AnkamaGames::Dofus::Network::Messages::Queues::QueueStatusMessage
        l("Position in character selection queue: #{packet.position} / #{packet.total}")
      when Com::AnkamaGames::Dofus::Network::Messages::Secure::TrustStatusMessage,
           Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::BasicNoOperationMessage
        # nothing to do, ignore
      when Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharactersListMessage
        characters = packet.characters

        if !$config.character_id && characters.size > 0
          puts "Choose your character:"

          fields = sprintf("%20s | %5s | %5s | %6s", 'Name', 'Level', 'Class', 'Sex')
          puts fields, '-' * fields.size

          characters.each do |c|
            puts sprintf("%20s | %5d | %5d | %6s", c.name, c.level, c.breed, c.sex ? 'Male' : 'Female')
          end

          while line = gets do
            line.strip!
            break if line.empty?

            character = characters.find { |c| c.name.downcase == line.downcase }
            next unless character

            $config.character_id = character.id
            break
          end

          csm = Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharacterSelectionMessage.new.build!($config.character_id)
          send_data csm

          @state = STATE_IN_GAME
        elsif characters.size == 0
          l("No character created", Logger::FATAL)
          exit
        end
      else
        l("Incorrect packet at $net.STATE_CHARACTER_SELECTION: #{packet.class}", Logger::FATAL)
      end
    end
  when STATE_IN_GAME
  else
    l("Unknown state #{state} for $net", Logger::FATAL);
    exit
  end
end

Output

[user host-122 ~/Documents/Projects/dofus] ./run.rb
[ INFO] [D2O] Parsing Servers.d2o
[ INFO] Connected
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Handshake::ProtocolRequired
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Connection::HelloConnectMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Connection::IdentificationMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Connection::IdentificationSuccessMessage
[   OK] Authentification successful
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Connection::ServersListMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Connection::ServerSelectionMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Connection::SelectedServerDataMessage
[ INFO] Connected
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Handshake::ProtocolRequired
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Approach::HelloGameMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Approach::AuthenticationTicketMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Approach::AuthenticationTicketAcceptedMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::BasicTimeMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Approach::AccountCapabilitiesMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Secure::TrustStatusMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::BasicNoOperationMessage
[   OK] Ticket accepted
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharactersListRequestMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Queues::QueueStatusMessage
[ INFO] Position in character selection queue: 1 / 1
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Queues::QueueStatusMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::BasicNoOperationMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Queues::QueueStatusMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharactersListMessage
[ INFO] Position in character selection queue: 0 / 0
[ INFO] Position in character selection queue: 0 / 0
Choose your character:
                Name | Level | Class |    Sex
---------------------------------------------
               Char1 |     2 |     5 |   Male
               Char2 |     4 |     3 | Female
               Char3 |    19 |     9 | Female
Char1
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharacterSelectionMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::BasicNoOperationMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Context::Notification::NotificationListMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharacterSelectedSuccessMessage
[ INFO] Selected character: [------] Char1 (2)
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Inventory::Items::InventoryContentMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Inventory::Items::SetUpdateMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Shortcut::ShortcutBarContentMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Shortcut::ShortcutBarContentMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Context::Roleplay::Emote::EmoteListMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Pvp::AlignmentRankUpdateMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Pvp::AlignmentSubAreasListMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Chat::Channel::EnabledChannelsMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Inventory::Spells::SpellListMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Shortcut::ShortcutBarContentMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Initialization::SetCharacterRestrictionsMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Inventory::Items::InventoryWeightMessage
[ INFO] Character weight: 14 / 1000
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Friend::FriendWarnOnConnectionStateMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Friend::GuildMemberWarnOnConnectionStateMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Friend::FriendWarnOnLevelGainStateMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::TextInformationMessage
[ WARN] Check Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::TextInformationMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::TextInformationMessage
[ WARN] Check Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::TextInformationMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Initialization::ServerExperienceModificatorMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Friend::SpouseStatusMessage

P.S. Please don’t blame my ugly code :)

Unpacking Dofus’ d2p files… the source of PakProtocol2

Generally, d2p files looks like splitted archives and each one have some pack of maps in it.

.d2p or PakProtocol2 files

module Com::AnkamaGames::Jerakine::Resources::Protocols::Impl
  class PakProtocol2
    include Singleton

    attr_accessor :indexes, :properties

    def self.method_missing meth, *args
      instance.send(meth, *args)
    end

    def initialize
      @indexes = {}
      @properties = {}

      @adapter = MapsAdapter.new
    end

    def [](key)
      index, subpath = key.to_s.split("/", 2)

      read(index, subpath)
    end

    def read(index, subpath)
      i = 0

      item = @indexes[index][subpath]
      file_stream = item[:stream]

      file_stream.pos = item[:offset]
      data = file_stream.read(item[:length])

      # @adapther is instance of MapsAdapter (see below)
      map = @adapter.getResource(data)
    end

    def parse filepath
      raise "[D2P] File doesn't exists #{filepath}" unless File.exists?(filepath)

      @stream_name = File.dirname(filepath).gsub("#{RES_ROOT}/", "")

      file_stream = nil
      unless @indexes[@stream_name]
        file_stream = init_stream(filepath)

        raise "[D2P] Error while looking for file_stream: #{@stream_name}" unless file_stream
      end
    end

    def init_stream filepath
      @indexes[@stream_name] = {}
      @properties[@stream_name] = {}

      indexes = @indexes[@stream_name]
      properties = @properties[@stream_name]

      base_pos = 0
      base_size = 0
      indexes_pos = 0
      indexes_size = 0
      properties_pos = 0
      properties_size = 0

      link_filepath = filepath

      while File.exists?(link_filepath)
        fp = File.open(link_filepath)

        raise "[D2P] Incorrect file?!" if fp.read(2) != "\x02\x01"

        fp.pos = fp.size - 24

        base_pos = fp.readUInt
        base_size = fp.readUInt
        indexes_pos = fp.readUInt
        indexes_size = fp.readUInt
        properties_pos = fp.readUInt
        properties_size = fp.readUInt

        fp.pos = properties_pos
        link_filepath = ""

        properties_size.times do
          prop_type = fp.readUTFString
          prop_value = fp.readUTFString

          properties[prop_type] = prop_value

          if prop_type == "link"
            link_filepath = File.join(@stream_name, prop_value)
          end
        end

        fp.pos = indexes_pos
        indexes_size.times do
          name = fp.readUTFString
          offset = fp.readInt
          length = fp.readInt

          indexes[name] = {
            offset: base_pos + offset,
            length: length,
            stream: fp
          }
        end
      end

      return fp
    end
  end

  PakProtocol2.parse "#{RES_ROOT}/maps/maps0.d2p"
end

chunks of .d2p is .dlm:

As first, they’re packed in GZip, with metadata, and simple inflate isn’t working for it. For more descriptive information visit: ActionScript 3 ByteArray and look at compress method.

Generally, we just need to skip till we get 0x77 byte )

module Com::AnkamaGames::Atouin::Resources::Adapters
  class MapsAdapter
    def getResource orig_data
      data = StringIO.new(orig_data)
      header = data.readByte

      if header != 77
        data.pos = 0
        data = StringIO.new(Zlib::Inflate.inflate(data.read))

        header = data.readByte
        raise "Incorrect header file" if header != 77
      end

      data.pos = 0

      # Map class below :)
      map = Map.new
      map.parse data

      map
    end
  end
end

Starting reading dlm structure… Map class!

module Com::AnkamaGames::Atouin::Data::Map
  class Map
    include Enumerable

    attr_accessor :header, :background, :zoomScale, :zoomOffsetX, :zoomOffsetY, :useLowPassFilter, :useReverb, :presetId, :backgroundsCount, :backgroundFixtures, :foregroundsCount, :foregroundFixtures, :cellsCount, :groundCRC, :layersCount, :layers, :cells

    def parse data
      raise "Incorrect header file" unless data.readByte == 77

      @header = {
        mapVersion: data.readByte,
        id: data.readUInt,
        relativeId: data.readUInt,
        mapType: data.readByte,
        subareaId: data.readInt,
        topNeighbourId: data.readInt,
        bottomNeighbourId: data.readInt,
        leftNeighbourId: data.readInt,
        rightNeighbourId: data.readInt,
        shadowBonusOnEntities: data.readInt
      }

      if @header[:mapVersion] >= 3
        @background = {
          red: data.readByte,
          green: data.readByte,
          blue: data.readByte
        }

        @background[:color] = (@background[:red] & 255) << 16 | (@background[:green] & 255) << 8 | @background[:blue] & 255
      end

      if @header[:mapVersion] >= 4
        @zoomScale = data.readUShort / 100
        @zoomOffsetX = data.readShort
        @zoomOffsetY = data.readShort
      end

      @useLowPassFilter = data.readByte == 1

      @useReverb = data.readByte == 1
      @presetId = -1
      @presetId = data.readInt if @useReverb

      @backgroundsCount = data.readByte
      @backgroundFixtures = []
      @backgroundsCount.times {
        bg = Fixture.new
        bg.parse data

        @backgroundFixtures << bg
      }

      @foregroundsCount = data.readByte
      @foregroundFixtures = []
      @foregroundsCount.times {
        fg = Fixture.new
        fg.parse data

        @foregroundFixtures << fg
      }

      @cellsCount = 560
      data.readInt
      @groundCRC = data.readInt
      @layersCount = data.readByte
      @layers = []
      @layersCount.times {
        la = Layer.new
        la.parse data

        @layers << la
      }

      @cells = []
      @cellsCount.times {
        cd = CellData.new
        cd.parse data

        @cells << cd
      }
    end
  end
end

Generally, i don’t care about colors & other info… i just need to get @cells information :)

Fixture, Layer classes

module Com::AnkamaGames::Atouin::Data::Map
  class Fixture
    def parse data
      @fixtureId = data.readInt

      @offset = OpenStruct.new
      @offset.x = data.readShort
      @offset.y = data.readShort

      @rotation = data.readShort

      @xScale = data.readShort
      @yScale = data.readShort

      @redMultiplier = data.readByte
      @greenMultiplier = data.readByte
      @blueMultiplier = data.readByte
      @hue = @redMultiplier | @greenMultiplier | @blueMultiplier

      @alpha = data.readUnsignedByte
    end
  end
end

module Com::AnkamaGames::Atouin::Data::Map
  class Layer
    def parse data
      @layerId = data.readInt
      @cellsCount = data.readShort
      @cells = []

      @cellsCount.times {
        c = Cell.new
        c.parse data

        @cells << c
      }
    end
  end
end

And at last… CellData class!

module Com::AnkamaGames::Atouin::Data::Map
  class CellData
    attr_accessor :floor, :losmov, :speed, :mapChangeData 

    def parse data
      @floor = data.readByte * 10;
      @losmov = data.readUnsignedByte
      @speed = data.readByte
      @mapChangeData = data.readUnsignedByte
    end

    def nonWalkableDuringRP
      (@losmov & 128) >> 7 == 1
    end

    def nonWalkableDuringFight
      (@losmov & 4) >> 2 == 1
    end

    def visible
      (@losmov & 64) >> 6 == 1
    end

    def farmCell
      (@losmov & 32) >> 5 == 1
    end

    def blue
      (@losmov & 16) >> 4 == 1
    end

    def red
      (@losmov & 8) >> 3 == 1
    end

    def los
      (@losmov & 2) >> 1 == 1
    end

    def mov
      (@losmov & 1) == 1
    end
  end
end

You can detect “move-ability” of cell using methods: mov, nonWalkableDuringRP and nonWalkableDuringFight.

Usage

map_id = 21760516
map_path = "maps/#{map_id % 10}/#{map_id}.dlm"
map = PakProtocol2[map_path]

puts map.cells[0].mov # true or false, means movable?
puts map.cells.select { |c| c.mov } # select all movable cells

Output

true

[
  #<Com::AnkamaGames::Atouin::Data::Map::CellData:0x0001 ...>,
  #<Com::AnkamaGames::Atouin::Data::Map::CellData:0x0002 ...>,
  #<Com::AnkamaGames::Atouin::Data::Map::CellData:0x0003 ...>,
  #<Com::AnkamaGames::Atouin::Data::Map::CellData:0x0004 ...>,
  #<Com::AnkamaGames::Atouin::Data::Map::CellData:0x0005 ...>,
  #<Com::AnkamaGames::Atouin::Data::Map::CellData:0x0006 ...>
]

Packet-based Dofus Bot Presentation #2
Added some AI, Map parsing, Pathfinding…

Posted on May 23, 2011

Notes: 1 note

Comments: View comments

Tags: dofus,bot,

Native (packet-based) bot for Dofus

P.S. Currently in proxy-stage :)

Posted on May 1, 2011

Notes: 2 notes

Comments: View comments

Tags: dofus,bot,

MLGame bot-loop... do i suck?!

Top of Page